{
  "version": 3,
  "sources": ["/cdn/shop/t/18/assets/fm-pomiar-app.js?fm=20260517-scanner-footer-v3"],
  "sourcesContent": ["const PAPER_SHORT_CM = 21;\nconst PAPER_LONG_CM = 29.7;\n\nconst hero = document.querySelector(\"#hero\");\nconst scanner = document.querySelector(\"#scanner\");\nconst result = document.querySelector(\"#result\");\nconst cameraCard = document.querySelector(\"#cameraCard\");\nconst reviewCard = document.querySelector(\"#reviewCard\");\nconst startButton = document.querySelector(\"#startButton\");\n// FM Pro \\u2014 lead capture disabled (free tool). Stubs so app.js nie crashuje.\nconst _stub = { checked: true, value: \"\", addEventListener: () => {}, get textContent() { return \"\"; }, set textContent(_v) {} };\nconst instructionCheck = _stub;\nconst leadEmailInput = _stub;\nconst leadConsent = _stub;\nconst leadStatus = _stub;\nconst captureButton = document.querySelector(\"#captureButton\");\nconst switchCameraButton = document.querySelector(\"#switchCameraButton\");\nconst resetButton = document.querySelector(\"#resetButton\");\nconst retryButton = document.querySelector(\"#retryButton\");\nconst retakeButton = document.querySelector(\"#retakeButton\");\nconst clearPointsButton = document.querySelector(\"#clearPointsButton\");\nconst analyzePhotoButton = document.querySelector(\"#analyzePhotoButton\");\nconst confirmPointsButton = document.querySelector(\"#confirmPointsButton\");\nconst statusBox = document.querySelector(\"#status\");\nconst reviewCopy = document.querySelector(\"#reviewCopy\");\nconst reviewReferenceCopy = document.querySelector(\"#reviewReferenceCopy\");\nconst handState = document.querySelector(\"#handState\");\nconst cardState = document.querySelector(\"#cardState\");\nconst video = document.querySelector(\"#camera\");\nconst canvas = document.querySelector(\"#overlay\");\nconst reviewCanvas = document.querySelector(\"#reviewCanvas\");\nconst scannerMode = document.querySelector(\"#scannerMode\");\nconst scannerHint = document.querySelector(\"#scannerHint\");\nconst scanProgress = document.querySelector(\"#scanProgress\");\nconst scanProgressTitle = document.querySelector(\"#scanProgressTitle\");\nconst scanProgressValue = document.querySelector(\"#scanProgressValue\");\nconst scanProgressFill = document.querySelector(\"#scanProgressFill\");\nconst scanProgressCopy = document.querySelector(\"#scanProgressCopy\");\nconst reviewSteps = [1, 2, 3, 4].map((index) => document.querySelector(`#reviewStep${index}`));\nconst ctx = canvas.getContext(\"2d\");\nconst reviewCtx = reviewCanvas.getContext(\"2d\");\n\nconst resultTitle = document.querySelector(\"#resultTitle\");\nconst resultCopy = document.querySelector(\"#resultCopy\");\nconst palmWidthValue = document.querySelector(\"#palmWidthValue\");\nconst handLengthValue = document.querySelector(\"#handLengthValue\");\nconst handProfileValue = document.querySelector(\"#handProfileValue\");\nconst resultSizeValue = document.querySelector(\"#resultSizeValue\");\nconst seriesValue = document.querySelector(\"#resultSeriesValue\");\nconst sizeRecommendationValue = document.querySelector(\"#sizeRecommendationValue\");\nconst seriesDescriptionValue = document.querySelector(\"#seriesDescriptionValue\");\nconst resultMailStatus = document.querySelector(\"#resultMailStatus\");\nconst shopButton = document.querySelector(\"#shopButton\");\nconst calibrationSession = window.FM_SESSION || \"\";\nconst calibrationStorageKey = calibrationSession ? `fmCalibration:${calibrationSession}` : \"\";\nconst measurementHistoryKey = \"fmHandFitMeasurements\";\nconst leadProfileKey = \"fmLeadProfile\";\nconst analyticsSessionKey = \"fmAnalyticsSessionId\";\nconst analyticsFlagsKey = \"fmAnalyticsFlags\";\nconst leadEndpoint = null;\nconst measurementResultEndpoint = null;\nconst analyticsEndpoint = null;\n\nlet hands;\nlet stream;\nlet cvReady = false;\nlet currentHand = null;\nlet activeFacingMode = \"environment\";\nlet frameRequestId = null;\nlet isProcessingFrame = false;\nlet appMode = \"live\";\nlet capturedHand = null;\nlet capturedCard = null;\nlet capturedImage = null;\nlet capturedMeasurementLines = null;\nlet manualCardPoints = [];\nlet draggedPointIndex = -1;\nlet activeReviewPointIndex = -1;\nlet suppressReviewClick = false;\nlet reviewPointsConfirmed = false;\nlet activeTouchId = null;\nlet activeLeadEmail = \"\";\nlet liveCardCandidate = null;\nlet liveCardCheckAt = 0;\nlet autoScanStartAt = 0;\nlet autoScanProgressValue = 0;\nlet autoCaptureLocked = false;\nconst processingCanvas = document.createElement(\"canvas\");\nconst processingCtx = processingCanvas.getContext(\"2d\", { willReadFrequently: true });\nconst AUTO_SCAN_DURATION_MS = 2400;\nconst LIVE_CARD_CHECK_INTERVAL_MS = 420;\n\nfunction getAnalyticsSessionId() {\n  try {\n    const existing = window.localStorage.getItem(analyticsSessionKey);\n    if (existing) return existing;\n    const created = `fm-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n    window.localStorage.setItem(analyticsSessionKey, created);\n    return created;\n  } catch (error) {\n    return `fm-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n  }\n}\n\nfunction readAnalyticsFlags() {\n  try {\n    const raw = window.sessionStorage.getItem(analyticsFlagsKey);\n    return raw ? JSON.parse(raw) : {};\n  } catch (error) {\n    return {};\n  }\n}\n\nfunction writeAnalyticsFlags(flags) {\n  try {\n    window.sessionStorage.setItem(analyticsFlagsKey, JSON.stringify(flags));\n  } catch (error) {\n    // no-op\n  }\n}\n\nfunction trackEvent(eventName, context = {}, options = {}) {\n  if (!analyticsEndpoint) return;\n\n  const flags = readAnalyticsFlags();\n  const onceKey = options.onceKey || \"\";\n  if (onceKey && flags[onceKey]) {\n    return;\n  }\n\n  if (onceKey) {\n    flags[onceKey] = true;\n    writeAnalyticsFlags(flags);\n  }\n\n  const payload = {\n    event: eventName,\n    session_id: getAnalyticsSessionId(),\n    page: window.location.href,\n    path: window.location.pathname,\n    referrer: document.referrer || \"\",\n    context,\n  };\n\n  fetch(analyticsEndpoint, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify(payload),\n    keepalive: true,\n  }).catch(() => {\n    // ignore analytics errors\n  });\n}\n\nfunction syncViewportHeight() {\n  const viewportHeight = window.visualViewport?.height || window.innerHeight || 0;\n  if (!viewportHeight) return;\n  document.documentElement.style.setProperty(\"--app-height\", `${Math.round(viewportHeight)}px`);\n}\n\nfunction readCalibrationData() {\n  if (!calibrationStorageKey) return null;\n\n  try {\n    const raw = window.localStorage.getItem(calibrationStorageKey);\n    return raw ? JSON.parse(raw) : null;\n  } catch (error) {\n    console.error(\"Nie uda\\u0142o si\\u0119 odczyta\\u0107 kalibracji.\", error);\n    return null;\n  }\n}\n\nfunction getCalibrationSummary() {\n  const data = readCalibrationData();\n  if (!data?.captureCount) return null;\n\n  return {\n    ...data,\n    isStable:\n      data.captureCount >= 3 &&\n      Number.isFinite(data.averageTilt) &&\n      Number.isFinite(data.averageOffset) &&\n      data.averageTilt <= 14 &&\n      data.averageOffset <= 0.18,\n  };\n}\n\nasync function buildVideoConstraints() {\n  const base = {\n    width: { ideal: 1280 },\n    height: { ideal: 720 },\n  };\n\n  if (!navigator.mediaDevices?.enumerateDevices) {\n    return {\n      ...base,\n      facingMode: activeFacingMode === \"environment\" ? { ideal: \"environment\" } : \"user\",\n    };\n  }\n\n  const devices = await navigator.mediaDevices.enumerateDevices().catch(() => []);\n  const videoInputs = devices.filter((device) => device.kind === \"videoinput\");\n\n  if (activeFacingMode === \"environment\") {\n    const rearCamera = videoInputs.find((device) =>\n      /(back|rear|environment|traseira|world)/i.test(device.label)\n    );\n\n    if (rearCamera) {\n      return {\n        ...base,\n        deviceId: { exact: rearCamera.deviceId },\n      };\n    }\n\n    return {\n      ...base,\n      facingMode: { ideal: \"environment\" },\n    };\n  }\n\n  const frontCamera = videoInputs.find((device) =>\n    /(front|user|face|facetime)/i.test(device.label)\n  );\n\n  if (frontCamera) {\n    return {\n      ...base,\n      deviceId: { exact: frontCamera.deviceId },\n    };\n  }\n\n  return {\n    ...base,\n    facingMode: \"user\",\n  };\n}\n\nwindow.Module = {\n  onRuntimeInitialized() {\n    cvReady = true;\n    updateStatus(\"Ustaw d\\u0142o\\u0144 na kartce i przygotuj zdj\\u0119cie.\");\n  },\n};\n\nfunction updateStatus(message) {\n  statusBox.textContent = message;\n}\n\nfunction setScannerVisualState(state) {\n  cameraCard.classList.remove(\"scanner-search\", \"scanner-lock\", \"scanner-review\");\n\n  if (state) {\n    cameraCard.classList.add(state);\n  }\n\n  if (state === \"scanner-lock\") {\n    scannerMode.textContent = \"SKAN\";\n    scannerHint.textContent = \"Utrzymaj kadr\";\n    return;\n  }\n\n  if (state === \"scanner-review\") {\n    scannerMode.textContent = \"SPRAWD\\u0179 ROGI\";\n    scannerHint.textContent = \"Popraw punkty\";\n    return;\n  }\n\n  scannerMode.textContent = \"SKANER D\\u0141ONI\";\n  scannerHint.textContent = \"Poka\\u017C d\\u0142o\\u0144 i A4\";\n}\n\nfunction getCameraLabel() {\n  return activeFacingMode === \"environment\" ? \"tylna\" : \"selfie\";\n}\n\nfunction updateSwitchCameraLabel(isBusy = false) {\n  switchCameraButton.textContent = isBusy ? \"Prze\\u0142\\u0105czam...\" : `Kamera: ${getCameraLabel()}`;\n  switchCameraButton.disabled = isBusy;\n}\n\nfunction getStartContext() {\n  return \"Ustaw d\\u0142o\\u0144 na kartce A4 i poka\\u017C ca\\u0142\\u0105 kartk\\u0119 w kadrze.\";\n}\n\nfunction getMeasurementHistory() {\n  try {\n    const raw = window.localStorage.getItem(measurementHistoryKey);\n    return raw ? JSON.parse(raw) : [];\n  } catch (error) {\n    console.error(\"Nie uda\\u0142o si\\u0119 odczyta\\u0107 historii pomiar\\u00F3w.\", error);\n    return [];\n  }\n}\n\nfunction saveMeasurementHistory(entry) {\n  const history = getMeasurementHistory();\n  history.unshift(entry);\n  window.localStorage.setItem(measurementHistoryKey, JSON.stringify(history.slice(0, 50)));\n}\n\nfunction readLeadProfile() {\n  try {\n    const raw = window.localStorage.getItem(leadProfileKey);\n    return raw ? JSON.parse(raw) : null;\n  } catch (error) {\n    console.error(\"Nie uda\\u0142o si\\u0119 odczyta\\u0107 profilu leadu.\", error);\n    return null;\n  }\n}\n\nfunction saveLeadProfile(profile) {\n  window.localStorage.setItem(leadProfileKey, JSON.stringify(profile));\n}\n\nfunction isValidEmail(value) {\n  return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value.trim());\n}\n\nfunction syncStartAvailability() {\n  // FM Pro \\u2014 skaner dost\\u0119pny od razu, bez gate\n  startButton.disabled = false;\n}\n\nfunction setCaptureAvailability(isReady) {\n  if (captureButton) {\n    captureButton.disabled = !isReady;\n  }\n}\n\nfunction setScannerSessionState(isActive) {\n  document.body.classList.toggle(\"scanner-active\", isActive);\n  const chromeSelectors = [\n    \".fm-shipping-bar\",\n    \".fm-topbar\",\n    \".fm-trust-strip\",\n    \".shopify-section-group-header-group\",\n    \".shopify-section-group-footer-group\",\n    \"footer\",\n    \".fm-footer\",\n  ];\n\n  if (isActive) {\n    scanner.style.position = \"fixed\";\n    scanner.style.inset = \"0\";\n    scanner.style.zIndex = \"2147483000\";\n    scanner.style.display = \"block\";\n    scanner.style.height = \"var(--app-height, 100vh)\";\n    scanner.style.minHeight = \"var(--app-height, 100vh)\";\n    scanner.style.background = \"#081109\";\n    scanner.style.overflow = \"hidden\";\n    document.querySelectorAll(chromeSelectors.join(\",\")).forEach((element) => {\n      element.dataset.fmScannerPreviousDisplay = element.style.display || \"\";\n      element.style.setProperty(\"display\", \"none\", \"important\");\n    });\n    return;\n  }\n\n  scanner.removeAttribute(\"style\");\n  document.querySelectorAll(\"[data-fm-scanner-previous-display]\").forEach((element) => {\n    element.style.display = element.dataset.fmScannerPreviousDisplay || \"\";\n    delete element.dataset.fmScannerPreviousDisplay;\n  });\n}\n\nfunction updateScanProgress(progress, title, copy) {\n  const normalized = clamp(progress, 0, 1);\n  autoScanProgressValue = normalized;\n  scanProgress.classList.remove(\"hidden\");\n  scanProgressTitle.textContent = title;\n  scanProgressValue.textContent = `${Math.round(normalized * 100)}%`;\n  scanProgressFill.style.width = `${normalized * 100}%`;\n  scanProgressCopy.textContent = copy;\n}\n\nfunction resetAutoScanState() {\n  liveCardCandidate = null;\n  liveCardCheckAt = 0;\n  autoScanStartAt = 0;\n  autoScanProgressValue = 0;\n  autoCaptureLocked = false;\n  scanProgress.classList.add(\"hidden\");\n  scanProgressFill.style.width = \"0%\";\n  scanProgressValue.textContent = \"0%\";\n  scanProgressTitle.textContent = \"Przygotuj kadr\";\n  scanProgressCopy.textContent = \"Skan ruszy automatycznie.\";\n}\n\nfunction updateAutoScan(now) {\n  const handReady = Boolean(currentHand);\n  const cardReady = Boolean(liveCardCandidate);\n\n  if (!handReady && !cardReady) {\n    autoScanStartAt = 0;\n    updateScanProgress(0, \"Szukam d\\u0142oni i A4\", \"Poka\\u017C d\\u0142o\\u0144 i ca\\u0142\\u0105 kartk\\u0119.\");\n    return;\n  }\n\n  if (handReady && !cardReady) {\n    autoScanStartAt = 0;\n    updateScanProgress(0.12, \"D\\u0142o\\u0144 wykryta\", \"Poka\\u017C ca\\u0142\\u0105 kartk\\u0119.\");\n    return;\n  }\n\n  if (!handReady && cardReady) {\n    autoScanStartAt = 0;\n    updateScanProgress(0.12, \"A4 wykryta\", \"Po\\u0142\\u00F3\\u017C d\\u0142o\\u0144 na kartce.\");\n    return;\n  }\n\n  if (!autoScanStartAt) {\n    autoScanStartAt = now;\n  }\n\n  const progress = (now - autoScanStartAt) / AUTO_SCAN_DURATION_MS;\n  updateScanProgress(\n    progress,\n    progress >= 1 ? \"Pomiar zako\\u0144czony\" : \"Skanuj\\u0119 d\\u0142o\\u0144\",\n    progress >= 1 ? \"Przygotowuj\\u0119 wynik.\" : \"Nie ruszaj telefonem ani d\\u0142oni\\u0105.\"\n  );\n\n  if (progress >= 1 && !autoCaptureLocked) {\n    autoCaptureLocked = true;\n    capturePhoto({ preDetectedCard: liveCardCandidate, autoMode: true });\n  }\n}\n\nasync function submitLead(_payload) {\n  // FM Pro \\u2014 leadowanie wy\\u0142\\u0105czone, skaner jest darmowy\n  return { ok: true, skipped: true };\n}\n\nasync function ensureLeadReady() {\n  // FM Pro \\u2014 pomiar jest darmowy, lead opcjonalny\n  return { ok: true, skipped: true };\n  // (dead code below preserved for reference)\n  const email = leadEmailInput.value.trim();\n  if (!isValidEmail(email) || !leadConsent.checked) {\n    throw new Error(\"Lead form is incomplete\");\n  }\n\n  const cached = readLeadProfile();\n  if (cached?.email === email && cached?.leadSynced) {\n    activeLeadEmail = email;\n    return cached;\n  }\n\n  const payload = {\n    email,\n    source: \"hand-fit-measurement\",\n    createdAt: new Date().toISOString(),\n    page: window.location.href,\n    session: calibrationSession,\n  };\n\n  await submitLead(payload);\n  trackEvent(\"lead_submit\", { email_domain: email.split(\"@\")[1] || \"\" }, { onceKey: `lead_submit:${email}` });\n\n  const profile = {\n    email,\n    consent: true,\n    leadSynced: true,\n    savedAt: new Date().toISOString(),\n  };\n\n  saveLeadProfile(profile);\n  activeLeadEmail = email;\n  return profile;\n}\n\nasync function sendMeasurementResultEmail(payload) {\n  const response = await fetch(measurementResultEndpoint, {\n    method: \"POST\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: JSON.stringify(payload),\n  });\n\n  if (!response.ok) {\n    throw new Error(`Measurement result endpoint returned ${response.status}`);\n  }\n\n  return response.json().catch(() => ({ ok: true }));\n}\n\nfunction setCanvasSize() {\n  const { videoWidth, videoHeight } = video;\n  if (!videoWidth || !videoHeight) return;\n  canvas.width = videoWidth;\n  canvas.height = videoHeight;\n  processingCanvas.width = videoWidth;\n  processingCanvas.height = videoHeight;\n}\n\nfunction distance(a, b) {\n  return Math.hypot(a.x - b.x, a.y - b.y);\n}\n\nfunction average(values) {\n  return values.reduce((sum, value) => sum + value, 0) / values.length;\n}\n\nfunction clamp(value, min, max) {\n  return Math.min(Math.max(value, min), max);\n}\n\nfunction getHandMetrics(landmarks, width, height) {\n  const points = landmarks.map((point) => ({\n    x: point.x * width,\n    y: point.y * height,\n  }));\n\n  return {\n    points,\n    palmWidthPx: distance(points[5], points[17]),\n    handLengthPx: distance(points[0], points[12]),\n  };\n}\n\nfunction getHandBounds(handMetrics) {\n  if (!handMetrics?.points?.length) return null;\n\n  const xs = handMetrics.points.map((point) => point.x);\n  const ys = handMetrics.points.map((point) => point.y);\n\n  return {\n    minX: Math.min(...xs),\n    maxX: Math.max(...xs),\n    minY: Math.min(...ys),\n    maxY: Math.max(...ys),\n  };\n}\n\nfunction getPalmCenter(handMetrics) {\n  if (!handMetrics?.points?.length) return null;\n\n  const palmIndexes = [0, 5, 9, 13, 17];\n  const palmPoints = palmIndexes.map((index) => handMetrics.points[index]);\n\n  return {\n    x: average(palmPoints.map((point) => point.x)),\n    y: average(palmPoints.map((point) => point.y)),\n  };\n}\n\nfunction median(values) {\n  if (!values.length) return null;\n  const sorted = [...values].sort((a, b) => a - b);\n  const middle = Math.floor(sorted.length / 2);\n  return sorted.length % 2 === 0\n    ? (sorted[middle - 1] + sorted[middle]) / 2\n    : sorted[middle];\n}\n\nfunction sortVertices(vertices) {\n  const sumSorted = [...vertices].sort((a, b) => a.x + a.y - (b.x + b.y));\n  const diffSorted = [...vertices].sort((a, b) => a.y - a.x - (b.y - b.x));\n\n  return {\n    topLeft: sumSorted[0],\n    bottomRight: sumSorted[3],\n    topRight: diffSorted[0],\n    bottomLeft: diffSorted[3],\n  };\n}\n\nfunction getRotatedRectVertices(rect) {\n  const angle = (rect.angle * Math.PI) / 180;\n  const cos = Math.cos(angle);\n  const sin = Math.sin(angle);\n  const halfWidth = rect.size.width / 2;\n  const halfHeight = rect.size.height / 2;\n  const corners = [\n    { x: -halfWidth, y: -halfHeight },\n    { x: halfWidth, y: -halfHeight },\n    { x: halfWidth, y: halfHeight },\n    { x: -halfWidth, y: halfHeight },\n  ];\n\n  return corners.map((corner) => ({\n    x: rect.center.x + corner.x * cos - corner.y * sin,\n    y: rect.center.y + corner.x * sin + corner.y * cos,\n  }));\n}\n\nfunction getCardMetrics(vertices) {\n  if (!vertices || vertices.length !== 4) return null;\n\n  const ordered = sortVertices(vertices);\n  const edgeLengths = [\n    distance(ordered.topLeft, ordered.topRight),\n    distance(ordered.topRight, ordered.bottomRight),\n    distance(ordered.bottomRight, ordered.bottomLeft),\n    distance(ordered.bottomLeft, ordered.topLeft),\n  ];\n\n  return {\n    vertices: [ordered.topLeft, ordered.topRight, ordered.bottomRight, ordered.bottomLeft],\n    widthPx: Math.max(...edgeLengths),\n    heightPx: Math.min(...edgeLengths),\n    center: {\n      x: (ordered.topLeft.x + ordered.topRight.x + ordered.bottomRight.x + ordered.bottomLeft.x) / 4,\n      y: (ordered.topLeft.y + ordered.topRight.y + ordered.bottomRight.y + ordered.bottomLeft.y) / 4,\n    },\n  };\n}\n\nfunction getQuadBounds(vertices) {\n  return {\n    minX: Math.min(...vertices.map((point) => point.x)),\n    maxX: Math.max(...vertices.map((point) => point.x)),\n    minY: Math.min(...vertices.map((point) => point.y)),\n    maxY: Math.max(...vertices.map((point) => point.y)),\n  };\n}\n\nfunction getPolygonArea(vertices) {\n  let area = 0;\n\n  for (let index = 0; index < vertices.length; index += 1) {\n    const current = vertices[index];\n    const next = vertices[(index + 1) % vertices.length];\n    area += current.x * next.y - next.x * current.y;\n  }\n\n  return Math.abs(area) / 2;\n}\n\nfunction getIntersectionArea(a, b) {\n  const overlapWidth = Math.max(0, Math.min(a.maxX, b.maxX) - Math.max(a.minX, b.minX));\n  const overlapHeight = Math.max(0, Math.min(a.maxY, b.maxY) - Math.max(a.minY, b.minY));\n  return overlapWidth * overlapHeight;\n}\n\nfunction updateDetectorState(handDetected, cardMessage = \"Kartka: sprawdzimy po zdj\\u0119ciu\") {\n  handState.textContent = handDetected ? \"D\\u0142o\\u0144: widoczna\" : \"D\\u0142o\\u0144: niewidoczna\";\n  cardState.textContent = cardMessage;\n}\n\nfunction getReviewHandleHitRadius() {\n  const rect = reviewCanvas.getBoundingClientRect();\n  if (!rect.width || !reviewCanvas.width) return 72;\n  const scale = reviewCanvas.width / rect.width;\n  return Math.max(72, 34 * scale);\n}\n\nfunction getCanvasPointFromEvent(event) {\n  const rect = reviewCanvas.getBoundingClientRect();\n  return {\n    x: clamp((event.clientX - rect.left) * (reviewCanvas.width / rect.width), 0, reviewCanvas.width),\n    y: clamp((event.clientY - rect.top) * (reviewCanvas.height / rect.height), 0, reviewCanvas.height),\n  };\n}\n\nfunction getTouchPointFromTouch(touch) {\n  const rect = reviewCanvas.getBoundingClientRect();\n  return {\n    x: clamp((touch.clientX - rect.left) * (reviewCanvas.width / rect.width), 0, reviewCanvas.width),\n    y: clamp((touch.clientY - rect.top) * (reviewCanvas.height / rect.height), 0, reviewCanvas.height),\n  };\n}\n\nfunction findNearestCardPoint(point, radius = getReviewHandleHitRadius()) {\n  let bestIndex = -1;\n  let bestDistance = radius;\n\n  manualCardPoints.forEach((cardPoint, index) => {\n    const currentDistance = distance(point, cardPoint);\n    if (currentDistance <= bestDistance) {\n      bestDistance = currentDistance;\n      bestIndex = index;\n    }\n  });\n\n  return bestIndex;\n}\n\nfunction normalizeManualCardPoints() {\n  if (manualCardPoints.length !== 4) return;\n  const ordered = sortVertices(manualCardPoints);\n  manualCardPoints = [ordered.topLeft, ordered.topRight, ordered.bottomRight, ordered.bottomLeft];\n}\n\nfunction updateReviewChecklist() {\n  reviewSteps.forEach((step, index) => {\n    if (!step) return;\n    step.classList.toggle(\"is-done\", Boolean(manualCardPoints[index]));\n    step.classList.toggle(\"is-active\", index === activeReviewPointIndex);\n  });\n}\n\nfunction getNextMissingReviewPointIndex() {\n  for (let index = 0; index < 4; index += 1) {\n    if (!manualCardPoints[index]) return index;\n  }\n  return -1;\n}\n\nfunction selectReviewPoint(index) {\n  if (index < 0 || index > 3) return;\n  activeReviewPointIndex = index;\n  updateReviewChecklist();\n  drawReviewCanvas();\n  updateStatus(`Wybrany punkt ${index + 1}. Dotknij r\\u00F3g kartki albo przeci\\u0105gnij punkt palcem.`);\n}\n\nfunction placeOrMoveReviewPoint(point, preferredIndex = activeReviewPointIndex) {\n  if (preferredIndex < 0 || preferredIndex > 3) {\n    preferredIndex = getNextMissingReviewPointIndex();\n  }\n\n  if (preferredIndex < 0 || preferredIndex > 3) return;\n\n  manualCardPoints[preferredIndex] = point;\n  invalidateReviewConfirmation();\n  activeReviewPointIndex = preferredIndex;\n\n  if (manualCardPoints.filter(Boolean).length === 4) {\n    manualCardPoints = manualCardPoints.slice(0, 4);\n    cardState.textContent = \"Kartka: sprawd\\u017A 4 punkty\";\n    updateStatus(`Punkt ${preferredIndex + 1} ustawiony. Je\\u015Bli trzeba, popraw go dalej albo wybierz kolejny numer.`);\n  } else {\n    cardState.textContent = `Kartka: punkt ${manualCardPoints.filter(Boolean).length}/4`;\n    updateStatus(`Punkt ${preferredIndex + 1} ustawiony. Wybierz nast\\u0119pny numer, gdy b\\u0119dziesz gotowy.`);\n  }\n\n  updateReviewChecklist();\n  drawReviewCanvas();\n}\n\nfunction syncAnalyzeAvailability() {\n  const readyPointsCount = manualCardPoints.filter(Boolean).length;\n  analyzePhotoButton.disabled = !(readyPointsCount === 4 && reviewPointsConfirmed);\n  confirmPointsButton.disabled = readyPointsCount !== 4;\n}\n\nfunction invalidateReviewConfirmation() {\n  reviewPointsConfirmed = false;\n  syncAnalyzeAvailability();\n}\n\nfunction scoreCardCandidate(vertices, area, roiCenter, handMetrics, handBounds) {\n  const metrics = getCardMetrics(vertices);\n  const palmCenter = getPalmCenter(handMetrics);\n  if (!metrics || !palmCenter || !handBounds) {\n    return { score: 0, confidence: 0 };\n  }\n\n  const expectedRatio = PAPER_LONG_CM / PAPER_SHORT_CM;\n  const ratio = metrics.widthPx / Math.max(metrics.heightPx, 1);\n  const ratioPenalty = Math.abs(ratio - expectedRatio);\n  const centerPenalty =\n    Math.abs(metrics.center.x - roiCenter.x) / Math.max(roiCenter.x, 1) +\n    Math.abs(metrics.center.y - roiCenter.y) / Math.max(roiCenter.y, 1);\n\n  const ordered = sortVertices(vertices);\n  const longEdgeAngle =\n    Math.abs(\n      Math.atan2(\n        ordered.bottomRight.y - ordered.topRight.y,\n        ordered.bottomRight.x - ordered.topRight.x\n      ) *\n        (180 / Math.PI)\n    ) % 180;\n  const verticalPenalty = Math.min(Math.abs(90 - longEdgeAngle), Math.abs(longEdgeAngle));\n\n  const handWidth = handBounds.maxX - handBounds.minX;\n  const handHeight = handBounds.maxY - handBounds.minY;\n  const cardArea = getPolygonArea(vertices);\n  const handArea = Math.max(handWidth * handHeight, 1);\n  const areaRatio = cardArea / handArea;\n  const cardBounds = {\n    minX: Math.min(...vertices.map((point) => point.x)),\n    maxX: Math.max(...vertices.map((point) => point.x)),\n    minY: Math.min(...vertices.map((point) => point.y)),\n    maxY: Math.max(...vertices.map((point) => point.y)),\n  };\n  const overlapArea = getIntersectionArea(cardBounds, handBounds);\n  const overlapRatio = overlapArea / Math.max(cardArea, 1);\n  const palmDistance =\n    Math.hypot(metrics.center.x - palmCenter.x, metrics.center.y - palmCenter.y) /\n    Math.max(Math.max(handWidth, handHeight), 1);\n\n  const normalizedAreaPenalty =\n    areaRatio < 0.09 ? (0.09 - areaRatio) * 16 : areaRatio > 0.42 ? (areaRatio - 0.42) * 10 : 0;\n  const overlapPenalty = overlapRatio < 0.55 ? (0.55 - overlapRatio) * 18 : 0;\n  const palmDistancePenalty = palmDistance > 0.32 ? (palmDistance - 0.32) * 18 : 0;\n\n  const score =\n    area /\n    (1 +\n      ratioPenalty * 14 +\n      centerPenalty * 1.5 +\n      verticalPenalty * 0.08 +\n      normalizedAreaPenalty +\n      overlapPenalty +\n      palmDistancePenalty);\n\n  const confidence = clamp(\n    1 -\n      (ratioPenalty * 1.6 +\n        centerPenalty * 0.4 +\n        verticalPenalty / 30 +\n        normalizedAreaPenalty * 0.18 +\n        overlapPenalty * 0.16 +\n        palmDistancePenalty * 0.18),\n    0,\n    1\n  );\n\n  return {\n    score,\n    confidence,\n    overlapRatio,\n    areaRatio,\n    palmDistance,\n  };\n}\n\nfunction scorePaperCandidate(vertices, area, frameWidth, frameHeight, handBounds, palmCenter) {\n  const metrics = getCardMetrics(vertices);\n  if (!metrics || !handBounds || !palmCenter) {\n    return { score: 0, confidence: 0, containsPalm: false, overlapRatio: 0, areaRatio: 0 };\n  }\n\n  const quadBounds = getQuadBounds(vertices);\n  const handArea =\n    Math.max((handBounds.maxX - handBounds.minX) * (handBounds.maxY - handBounds.minY), 1);\n  const overlapArea = getIntersectionArea(handBounds, quadBounds);\n  const overlapRatio = overlapArea / handArea;\n  const containsPalm =\n    palmCenter.x >= quadBounds.minX &&\n    palmCenter.x <= quadBounds.maxX &&\n    palmCenter.y >= quadBounds.minY &&\n    palmCenter.y <= quadBounds.maxY;\n\n  const frameCenterX = frameWidth / 2;\n  const frameCenterY = frameHeight / 2;\n  const centerPenalty =\n    Math.abs(metrics.center.x - frameCenterX) / Math.max(frameCenterX, 1) +\n    Math.abs(metrics.center.y - frameCenterY) / Math.max(frameCenterY, 1);\n  const ratioPenalty = Math.abs(\n    metrics.widthPx / Math.max(metrics.heightPx, 1) - PAPER_LONG_CM / PAPER_SHORT_CM\n  );\n  const areaRatio = getPolygonArea(vertices) / Math.max(frameWidth * frameHeight, 1);\n  const areaPenalty =\n    areaRatio < 0.18 ? (0.18 - areaRatio) * 8 : areaRatio > 0.92 ? (areaRatio - 0.92) * 10 : 0;\n  const handInsetPenalty = overlapRatio < 0.82 ? (0.82 - overlapRatio) * 8 : 0;\n\n  const score =\n    area /\n    (1 + ratioPenalty * 10 + centerPenalty * 1.1 + areaPenalty + handInsetPenalty);\n  const confidence = clamp(\n    1 - ratioPenalty * 2.2 - centerPenalty * 0.35 - areaPenalty * 0.12 - handInsetPenalty * 0.18,\n    0,\n    1\n  );\n\n  return {\n    score,\n    confidence,\n    containsPalm,\n    overlapRatio,\n    areaRatio,\n  };\n}\n\nfunction buildBrightCardMask(imageMat) {\n  const rgb = new cv.Mat();\n  const hsv = new cv.Mat();\n  const channels = new cv.MatVector();\n  const lowSat = new cv.Mat();\n  const highVal = new cv.Mat();\n  const mask = new cv.Mat();\n  const kernel = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(5, 5));\n\n  cv.cvtColor(imageMat, rgb, cv.COLOR_RGBA2RGB);\n  cv.cvtColor(rgb, hsv, cv.COLOR_RGB2HSV);\n  cv.split(hsv, channels);\n  const saturation = channels.get(1);\n  const value = channels.get(2);\n\n  cv.threshold(saturation, lowSat, 70, 255, cv.THRESH_BINARY_INV);\n  cv.threshold(value, highVal, 145, 255, cv.THRESH_BINARY);\n  cv.bitwise_and(lowSat, highVal, mask);\n  cv.morphologyEx(mask, mask, cv.MORPH_CLOSE, kernel);\n  cv.morphologyEx(mask, mask, cv.MORPH_OPEN, kernel);\n\n  rgb.delete();\n  hsv.delete();\n  channels.delete();\n  saturation.delete();\n  value.delete();\n  lowSat.delete();\n  highVal.delete();\n  kernel.delete();\n  return mask;\n}\n\nfunction transformPoints(matrix, points) {\n  const srcArray = points.flatMap((point) => [point.x, point.y]);\n  const srcMat = cv.matFromArray(points.length, 1, cv.CV_32FC2, srcArray);\n  const dstMat = new cv.Mat();\n  cv.perspectiveTransform(srcMat, dstMat, matrix);\n\n  const transformed = [];\n  for (let i = 0; i < points.length; i += 1) {\n    transformed.push({\n      x: dstMat.data32F[i * 2],\n      y: dstMat.data32F[i * 2 + 1],\n    });\n  }\n\n  srcMat.delete();\n  dstMat.delete();\n  return transformed;\n}\n\nfunction copyCurrentFrame() {\n  if (!video.videoWidth || !video.videoHeight) return false;\n  processingCtx.drawImage(video, 0, 0, processingCanvas.width, processingCanvas.height);\n  return true;\n}\n\nfunction detectCardOnCapturedFrame(handMetrics) {\n  if (!cvReady || !handMetrics) return null;\n\n  const src = cv.imread(processingCanvas);\n  const gray = new cv.Mat();\n  const blurred = new cv.Mat();\n  const binary = new cv.Mat();\n  const edges = new cv.Mat();\n  const work = new cv.Mat();\n  const kernel = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(7, 7));\n  const paperKernel = cv.getStructuringElement(cv.MORPH_RECT, new cv.Size(21, 21));\n  const bounds = getHandBounds(handMetrics);\n  const palmCenter = getPalmCenter(handMetrics);\n\n  if (!bounds || !palmCenter) {\n    src.delete();\n    gray.delete();\n    blurred.delete();\n    binary.delete();\n    kernel.delete();\n    edges.delete();\n    work.delete();\n    return null;\n  }\n\n  cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);\n  cv.GaussianBlur(gray, blurred, new cv.Size(7, 7), 0);\n\n  let bestCandidate = null;\n  let bestScore = 0;\n  const contourModes = [];\n\n  const brightPaperMask = buildBrightCardMask(src);\n  cv.morphologyEx(brightPaperMask, brightPaperMask, cv.MORPH_CLOSE, paperKernel);\n  cv.morphologyEx(brightPaperMask, brightPaperMask, cv.MORPH_OPEN, kernel);\n  contourModes.push(brightPaperMask.clone());\n  cv.threshold(blurred, binary, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU);\n  cv.morphologyEx(binary, binary, cv.MORPH_CLOSE, paperKernel);\n  contourModes.push(binary.clone());\n  cv.Canny(blurred, edges, 60, 140);\n  cv.morphologyEx(edges, work, cv.MORPH_CLOSE, kernel);\n  contourModes.push(work.clone());\n  cv.adaptiveThreshold(blurred, work, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 21, 5);\n  cv.morphologyEx(work, work, cv.MORPH_CLOSE, paperKernel);\n  cv.morphologyEx(work, work, cv.MORPH_CLOSE, kernel);\n  contourModes.push(work.clone());\n\n  contourModes.forEach((modeMat) => {\n    const contours = new cv.MatVector();\n    const hierarchy = new cv.Mat();\n    cv.findContours(modeMat, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);\n\n    for (let i = 0; i < contours.size(); i += 1) {\n      const contour = contours.get(i);\n      const area = Math.abs(cv.contourArea(contour));\n      if (area < src.rows * src.cols * 0.08) {\n        contour.delete();\n        continue;\n      }\n\n      const perimeter = cv.arcLength(contour, true);\n      const approx = new cv.Mat();\n      cv.approxPolyDP(contour, approx, 0.03 * perimeter, true);\n\n      const candidateSets = [];\n      if (approx.rows === 4 && cv.isContourConvex(approx)) {\n        const vertices = [];\n        for (let j = 0; j < 4; j += 1) {\n          vertices.push({\n            x: approx.data32S[j * 2],\n            y: approx.data32S[j * 2 + 1],\n          });\n        }\n        candidateSets.push(vertices);\n      }\n\n      const rect = cv.minAreaRect(contour);\n      const width = Math.max(rect.size.width, rect.size.height);\n      const height = Math.min(rect.size.width, rect.size.height);\n      if (width >= src.cols * 0.24 && height >= src.rows * 0.24) {\n        candidateSets.push(getRotatedRectVertices(rect));\n      }\n\n      const hull = new cv.Mat();\n      cv.convexHull(contour, hull, true, true);\n      if (hull.rows >= 4) {\n        const hullRect = cv.minAreaRect(hull);\n        candidateSets.push(getRotatedRectVertices(hullRect));\n      }\n\n      candidateSets.forEach((vertices) => {\n        const metrics = getCardMetrics(vertices);\n        if (!metrics) return;\n\n        const ratio = metrics.widthPx / Math.max(metrics.heightPx, 1);\n        if (ratio < 1.25 || ratio > 1.52) return;\n\n        const candidate = scorePaperCandidate(vertices, area, src.cols, src.rows, bounds, palmCenter);\n        if (!candidate.containsPalm || candidate.overlapRatio < 0.72 || candidate.areaRatio < 0.16) {\n          return;\n        }\n\n        if (candidate.score > bestScore) {\n          bestScore = candidate.score;\n          bestCandidate = {\n            metrics,\n            confidence: candidate.confidence,\n            score: candidate.score,\n          };\n        }\n      });\n\n      hull.delete();\n      approx.delete();\n      contour.delete();\n    }\n\n    contours.delete();\n    hierarchy.delete();\n    modeMat.delete();\n  });\n\n  src.delete();\n  gray.delete();\n  blurred.delete();\n  binary.delete();\n  edges.delete();\n  work.delete();\n  kernel.delete();\n  paperKernel.delete();\n  brightPaperMask.delete();\n\n  if (!bestCandidate) return null;\n  if (bestCandidate.confidence < 0.46) return null;\n\n  return {\n    ...bestCandidate.metrics,\n    confidence: bestCandidate.confidence,\n    score: bestCandidate.score,\n  };\n}\n\nfunction buildSkinMask(imageMat) {\n  const rgb = new cv.Mat();\n  const ycrcb = new cv.Mat();\n  const hsv = new cv.Mat();\n  const ycrcbMask = new cv.Mat();\n  const hsvMask = new cv.Mat();\n  const mask = new cv.Mat();\n  const kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, new cv.Size(5, 5));\n\n  cv.cvtColor(imageMat, rgb, cv.COLOR_RGBA2RGB);\n  cv.cvtColor(rgb, ycrcb, cv.COLOR_RGB2YCrCb);\n  cv.cvtColor(rgb, hsv, cv.COLOR_RGB2HSV);\n\n  const lower = new cv.Mat(ycrcb.rows, ycrcb.cols, ycrcb.type(), [0, 133, 77, 0]);\n  const upper = new cv.Mat(ycrcb.rows, ycrcb.cols, ycrcb.type(), [255, 173, 127, 255]);\n  cv.inRange(ycrcb, lower, upper, ycrcbMask);\n\n  const hsvLower = new cv.Mat(hsv.rows, hsv.cols, hsv.type(), [0, 20, 50, 0]);\n  const hsvUpper = new cv.Mat(hsv.rows, hsv.cols, hsv.type(), [25, 180, 255, 255]);\n  cv.inRange(hsv, hsvLower, hsvUpper, hsvMask);\n  cv.bitwise_or(ycrcbMask, hsvMask, mask);\n  cv.morphologyEx(mask, mask, cv.MORPH_OPEN, kernel);\n  cv.morphologyEx(mask, mask, cv.MORPH_CLOSE, kernel);\n\n  rgb.delete();\n  ycrcb.delete();\n  hsv.delete();\n  lower.delete();\n  upper.delete();\n  hsvLower.delete();\n  hsvUpper.delete();\n  ycrcbMask.delete();\n  hsvMask.delete();\n  kernel.delete();\n  return mask;\n}\n\nfunction buildLandmarkPriorMask(points, width, height) {\n  const mask = cv.Mat.zeros(height, width, cv.CV_8UC1);\n  const hullPoints = points.map((point) => new cv.Point(Math.round(point.x), Math.round(point.y)));\n  const hullMat = cv.matFromArray(\n    hullPoints.length,\n    1,\n    cv.CV_32SC2,\n    hullPoints.flatMap((point) => [point.x, point.y])\n  );\n  const hull = new cv.Mat();\n  const hullVector = new cv.MatVector();\n  const kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, new cv.Size(31, 31));\n\n  cv.convexHull(hullMat, hull, true, true);\n  hullVector.push_back(hull);\n  cv.fillPoly(mask, hullVector, new cv.Scalar(255));\n\n  points.forEach((point) => {\n    cv.circle(mask, new cv.Point(Math.round(point.x), Math.round(point.y)), 24, new cv.Scalar(255), -1);\n  });\n\n  cv.dilate(mask, mask, kernel);\n\n  hullMat.delete();\n  hull.delete();\n  hullVector.delete();\n  kernel.delete();\n  return mask;\n}\n\nfunction pickDominantHandContour(mask, anchorPoint, minArea = 8000) {\n  const contours = new cv.MatVector();\n  const hierarchy = new cv.Mat();\n  let bestContour = null;\n  let bestScore = 0;\n\n  cv.findContours(mask, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE);\n\n  for (let i = 0; i < contours.size(); i += 1) {\n    const contour = contours.get(i);\n    const area = Math.abs(cv.contourArea(contour));\n    if (area < minArea) {\n      contour.delete();\n      continue;\n    }\n\n    const moments = cv.moments(contour);\n    if (!moments.m00) {\n      contour.delete();\n      continue;\n    }\n\n    const centerX = moments.m10 / moments.m00;\n    const centerY = moments.m01 / moments.m00;\n    const anchorDistance = Math.hypot(centerX - anchorPoint.x, centerY - anchorPoint.y);\n    const score = area / (1 + anchorDistance * 0.025);\n\n    if (score > bestScore) {\n      if (bestContour) bestContour.delete();\n      bestContour = contour.clone();\n      bestScore = score;\n    }\n\n    contour.delete();\n  }\n\n  contours.delete();\n  hierarchy.delete();\n  return bestContour;\n}\n\nfunction buildRefinedHandMask(imageMat, warpedHandPoints) {\n  const skinMask = buildSkinMask(imageMat);\n  const priorMask = buildLandmarkPriorMask(warpedHandPoints, imageMat.cols, imageMat.rows);\n  const combinedMask = new cv.Mat();\n  const tmpMask = new cv.Mat();\n  const kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, new cv.Size(11, 11));\n  const anchorPoint = {\n    x: average(warpedHandPoints.map((point) => point.x)),\n    y: average(warpedHandPoints.map((point) => point.y)),\n  };\n\n  cv.bitwise_and(skinMask, priorMask, combinedMask);\n  cv.bitwise_or(combinedMask, priorMask, tmpMask);\n  cv.morphologyEx(tmpMask, tmpMask, cv.MORPH_CLOSE, kernel);\n  cv.morphologyEx(tmpMask, tmpMask, cv.MORPH_OPEN, kernel);\n\n  const bestContour = pickDominantHandContour(tmpMask, anchorPoint);\n  const finalMask = cv.Mat.zeros(imageMat.rows, imageMat.cols, cv.CV_8UC1);\n\n  if (bestContour) {\n    const contourVector = new cv.MatVector();\n    contourVector.push_back(bestContour);\n    cv.drawContours(finalMask, contourVector, 0, new cv.Scalar(255), -1);\n    cv.morphologyEx(finalMask, finalMask, cv.MORPH_CLOSE, kernel);\n    contourVector.delete();\n    bestContour.delete();\n  } else {\n    tmpMask.copyTo(finalMask);\n  }\n\n  skinMask.delete();\n  priorMask.delete();\n  combinedMask.delete();\n  tmpMask.delete();\n  kernel.delete();\n  return finalMask;\n}\n\nfunction scanPalmWidth(mask, minX, maxX, startY, endY, minWidthPx) {\n  const leftEdges = [];\n  const rightEdges = [];\n  const sampledYs = [];\n\n  for (let y = startY; y <= endY; y += 1) {\n    let left = null;\n    let right = null;\n\n    for (let x = minX; x <= maxX; x += 1) {\n      if (mask.ucharPtr(y, x)[0] > 0) {\n        left = x;\n        break;\n      }\n    }\n\n    for (let x = maxX; x >= minX; x -= 1) {\n      if (mask.ucharPtr(y, x)[0] > 0) {\n        right = x;\n        break;\n      }\n    }\n\n    if (left !== null && right !== null && right - left > minWidthPx) {\n      leftEdges.push(left);\n      rightEdges.push(right);\n      sampledYs.push(y);\n    }\n  }\n\n  const leftX = median(leftEdges);\n  const rightX = median(rightEdges);\n  const widthY = median(sampledYs);\n\n  if (leftX === null || rightX === null || widthY === null) return null;\n\n  return {\n    leftX,\n    rightX,\n    widthY,\n  };\n}\n\nfunction findWristBasePoint(mask, wristCenterX, wristY, scalePxPerMm) {\n  const bandHalfWidth = Math.round(16 * scalePxPerMm);\n  const startY = Math.max(0, Math.round(wristY - 5 * scalePxPerMm));\n  const endY = Math.min(mask.rows - 1, Math.round(wristY + 9 * scalePxPerMm));\n  let bestRow = null;\n\n  for (let y = startY; y <= endY; y += 1) {\n    const xs = [];\n    for (\n      let x = Math.max(0, Math.round(wristCenterX - bandHalfWidth));\n      x <= Math.min(mask.cols - 1, Math.round(wristCenterX + bandHalfWidth));\n      x += 1\n    ) {\n      if (mask.ucharPtr(y, x)[0] > 0) xs.push(x);\n    }\n\n    if (!xs.length) continue;\n\n    const span = xs[xs.length - 1] - xs[0];\n    if (span < 12 * scalePxPerMm || span > 42 * scalePxPerMm) continue;\n\n    const closenessPenalty = Math.abs(y - (wristY + 3 * scalePxPerMm));\n    const score = span - closenessPenalty * 0.7;\n\n    if (!bestRow || score > bestRow.score) {\n      bestRow = {\n        score,\n        x: median(xs),\n        y,\n      };\n    }\n  }\n\n  return bestRow\n    ? { x: bestRow.x, y: bestRow.y }\n    : { x: wristCenterX, y: wristY + 2 * scalePxPerMm };\n}\n\nfunction measureHandWithCard(cardPoints, handMetrics) {\n  if (!cvReady || !cardPoints?.length || !handMetrics) return null;\n\n  const ordered = sortVertices(cardPoints);\n  const topEdgePx = distance(ordered.topLeft, ordered.topRight);\n  const rightEdgePx = distance(ordered.topRight, ordered.bottomRight);\n  const paperWidthMm = topEdgePx >= rightEdgePx ? PAPER_LONG_CM * 10 : PAPER_SHORT_CM * 10;\n  const paperHeightMm = topEdgePx >= rightEdgePx ? PAPER_SHORT_CM * 10 : PAPER_LONG_CM * 10;\n  const scalePxPerMm = 6;\n  const planeWidthMm = paperWidthMm + 60;\n  const planeHeightMm = paperHeightMm + 60;\n  const marginLeftMm = 30;\n  const marginTopMm = 30;\n  const dstWidth = Math.round(planeWidthMm * scalePxPerMm);\n  const dstHeight = Math.round(planeHeightMm * scalePxPerMm);\n\n  const srcQuad = cv.matFromArray(4, 1, cv.CV_32FC2, [\n    ordered.topLeft.x,\n    ordered.topLeft.y,\n    ordered.topRight.x,\n    ordered.topRight.y,\n    ordered.bottomRight.x,\n    ordered.bottomRight.y,\n    ordered.bottomLeft.x,\n    ordered.bottomLeft.y,\n  ]);\n\n  const dstQuad = cv.matFromArray(4, 1, cv.CV_32FC2, [\n    marginLeftMm * scalePxPerMm,\n    marginTopMm * scalePxPerMm,\n    (marginLeftMm + paperWidthMm) * scalePxPerMm,\n    marginTopMm * scalePxPerMm,\n    (marginLeftMm + paperWidthMm) * scalePxPerMm,\n    (marginTopMm + paperHeightMm) * scalePxPerMm,\n    marginLeftMm * scalePxPerMm,\n    (marginTopMm + paperHeightMm) * scalePxPerMm,\n  ]);\n\n  const transform = cv.getPerspectiveTransform(srcQuad, dstQuad);\n  const inverse = new cv.Mat();\n  cv.invert(transform, inverse);\n\n  const src = cv.imread(processingCanvas);\n  const warped = new cv.Mat();\n  cv.warpPerspective(\n    src,\n    warped,\n    transform,\n    new cv.Size(dstWidth, dstHeight),\n    cv.INTER_LINEAR,\n    cv.BORDER_CONSTANT,\n    new cv.Scalar()\n  );\n\n  const warpedHandPoints = transformPoints(transform, handMetrics.points);\n  const handMask = buildRefinedHandMask(warped, warpedHandPoints);\n  const bounds = getHandBounds({ points: warpedHandPoints });\n  if (!bounds) {\n    src.delete();\n    warped.delete();\n    transform.delete();\n    inverse.delete();\n    srcQuad.delete();\n    dstQuad.delete();\n    handMask.delete();\n    return null;\n  }\n\n  const knuckleY = average([warpedHandPoints[5].y, warpedHandPoints[9].y, warpedHandPoints[13].y, warpedHandPoints[17].y]);\n  const wristY = warpedHandPoints[0].y;\n  const widthBand = Math.max(6, Math.round(5 * scalePxPerMm));\n  const minX = Math.max(0, Math.round(bounds.minX - 12 * scalePxPerMm));\n  const maxX = Math.min(handMask.cols - 1, Math.round(bounds.maxX + 12 * scalePxPerMm));\n  const targetBands = [\n    Math.round(knuckleY + (wristY - knuckleY) * 0.34),\n    Math.round(knuckleY + (wristY - knuckleY) * 0.28),\n    Math.round(knuckleY + (wristY - knuckleY) * 0.4),\n  ];\n\n  let widthScan = null;\n  for (const targetWidthY of targetBands) {\n    widthScan = scanPalmWidth(\n      handMask,\n      minX,\n      maxX,\n      Math.max(0, targetWidthY - widthBand),\n      Math.min(handMask.rows - 1, targetWidthY + widthBand),\n      18 * scalePxPerMm\n    );\n    if (widthScan) break;\n  }\n\n  let leftX;\n  let rightX;\n  let widthY;\n  if (widthScan) {\n    leftX = widthScan.leftX;\n    rightX = widthScan.rightX;\n    widthY = widthScan.widthY;\n  } else {\n    leftX = Math.min(warpedHandPoints[2].x, warpedHandPoints[5].x, warpedHandPoints[17].x) - 10 * scalePxPerMm;\n    rightX = Math.max(warpedHandPoints[5].x, warpedHandPoints[17].x, warpedHandPoints[18].x) + 10 * scalePxPerMm;\n    widthY = average([warpedHandPoints[5].y, warpedHandPoints[17].y]);\n  }\n\n  const fingertipCandidates = [8, 12, 16, 20].map((index) => warpedHandPoints[index]);\n  const tipPoint = fingertipCandidates.reduce((best, point) => (point.y < best.y ? point : best));\n\n  const wristCenterX = warpedHandPoints[0].x;\n  let basePoint = findWristBasePoint(handMask, wristCenterX, wristY, scalePxPerMm);\n\n  if (!basePoint || Number.isNaN(basePoint.x) || Number.isNaN(basePoint.y)) {\n    basePoint = {\n      x: wristCenterX,\n      y: warpedHandPoints[0].y + 2 * scalePxPerMm,\n    };\n  }\n\n  const widthCm = (rightX - leftX) / (scalePxPerMm * 10);\n  const lengthCm = distance(tipPoint, basePoint) / (scalePxPerMm * 10);\n  const sourceLines = transformPoints(inverse, [\n    { x: leftX, y: widthY },\n    { x: rightX, y: widthY },\n    tipPoint,\n    basePoint,\n  ]);\n\n  src.delete();\n  warped.delete();\n  transform.delete();\n  inverse.delete();\n  srcQuad.delete();\n  dstQuad.delete();\n  handMask.delete();\n\n  return {\n    palmWidthCm: widthCm,\n    handLengthCm: lengthCm,\n    widthLine: { left: sourceLines[0], right: sourceLines[1] },\n    lengthLine: { top: sourceLines[2], bottom: sourceLines[3] },\n  };\n}\n\nfunction drawLiveOverlay(handMetrics, liveCard) {\n  ctx.clearRect(0, 0, canvas.width, canvas.height);\n\n  if (liveCard?.vertices?.length === 4) {\n    ctx.lineWidth = 4;\n    ctx.strokeStyle = \"rgba(201, 255, 116, 0.96)\";\n    ctx.setLineDash([10, 8]);\n    ctx.beginPath();\n    liveCard.vertices.forEach((point, index) => {\n      if (index === 0) ctx.moveTo(point.x, point.y);\n      else ctx.lineTo(point.x, point.y);\n    });\n    ctx.closePath();\n    ctx.stroke();\n    ctx.setLineDash([]);\n  }\n\n  if (!handMetrics) return;\n\n  const bounds = getHandBounds(handMetrics);\n  if (bounds) {\n    const handWidth = bounds.maxX - bounds.minX;\n    const handHeight = bounds.maxY - bounds.minY;\n    const roiX = Math.max(0, bounds.minX - handWidth * 0.1);\n    const roiY = Math.max(0, bounds.minY + handHeight * 0.15);\n    const roiWidth = Math.min(canvas.width - roiX, handWidth * 1.2);\n    const roiHeight = Math.min(canvas.height - roiY, handHeight * 0.5);\n\n    ctx.strokeStyle = \"rgba(255, 252, 245, 0.45)\";\n    ctx.lineWidth = 2;\n    ctx.setLineDash([8, 8]);\n    ctx.strokeRect(roiX, roiY, roiWidth, roiHeight);\n    ctx.setLineDash([]);\n  }\n\n  ctx.lineWidth = 3;\n  ctx.strokeStyle = \"#b8ff52\";\n  ctx.fillStyle = \"rgba(184, 255, 82, 0.9)\";\n\n  handMetrics.points.forEach((point) => {\n    ctx.beginPath();\n    ctx.arc(point.x, point.y, 4, 0, Math.PI * 2);\n    ctx.fill();\n  });\n\n  ctx.beginPath();\n  ctx.moveTo(handMetrics.points[5].x, handMetrics.points[5].y);\n  ctx.lineTo(handMetrics.points[17].x, handMetrics.points[17].y);\n  ctx.stroke();\n\n  ctx.beginPath();\n  ctx.moveTo(handMetrics.points[0].x, handMetrics.points[0].y);\n  ctx.lineTo(handMetrics.points[12].x, handMetrics.points[12].y);\n  ctx.stroke();\n}\n\nfunction drawReviewCanvas() {\n  if (!capturedImage) return;\n\n  reviewCanvas.width = capturedImage.width;\n  reviewCanvas.height = capturedImage.height;\n  reviewCtx.clearRect(0, 0, reviewCanvas.width, reviewCanvas.height);\n  reviewCtx.drawImage(capturedImage, 0, 0);\n\n  if (capturedHand?.points?.length) {\n    reviewCtx.fillStyle = \"rgba(184, 255, 82, 0.9)\";\n    capturedHand.points.forEach((point) => {\n      reviewCtx.beginPath();\n      reviewCtx.arc(point.x, point.y, 4, 0, Math.PI * 2);\n      reviewCtx.fill();\n    });\n  }\n\n  if (capturedMeasurementLines?.widthLine) {\n    reviewCtx.strokeStyle = \"#39f3b2\";\n    reviewCtx.lineWidth = 6;\n    reviewCtx.beginPath();\n    reviewCtx.moveTo(capturedMeasurementLines.widthLine.left.x, capturedMeasurementLines.widthLine.left.y);\n    reviewCtx.lineTo(capturedMeasurementLines.widthLine.right.x, capturedMeasurementLines.widthLine.right.y);\n    reviewCtx.stroke();\n  }\n\n  if (capturedMeasurementLines?.lengthLine) {\n    reviewCtx.strokeStyle = \"#ff3b30\";\n    reviewCtx.lineWidth = 6;\n    reviewCtx.beginPath();\n    reviewCtx.moveTo(capturedMeasurementLines.lengthLine.top.x, capturedMeasurementLines.lengthLine.top.y);\n    reviewCtx.lineTo(capturedMeasurementLines.lengthLine.bottom.x, capturedMeasurementLines.lengthLine.bottom.y);\n    reviewCtx.stroke();\n  }\n\n  const readyPoints = manualCardPoints.filter(Boolean);\n  if (!readyPoints.length) return;\n\n  reviewCtx.lineWidth = 4;\n  reviewCtx.strokeStyle = \"#fffcf5\";\n  reviewCtx.fillStyle = \"#fffcf5\";\n  reviewCtx.beginPath();\n  manualCardPoints.forEach((point, index) => {\n    if (!point) return;\n    if (index === 0) reviewCtx.moveTo(point.x, point.y);\n    else reviewCtx.lineTo(point.x, point.y);\n  });\n  if (readyPoints.length === 4) {\n    reviewCtx.closePath();\n  }\n  reviewCtx.stroke();\n\n  manualCardPoints.forEach((point, index) => {\n    if (!point) return;\n    reviewCtx.beginPath();\n    reviewCtx.fillStyle =\n      draggedPointIndex === index || activeReviewPointIndex === index ? \"rgba(184, 255, 82, 0.26)\" : \"rgba(255, 252, 245, 0.22)\";\n    reviewCtx.arc(point.x, point.y, 34, 0, Math.PI * 2);\n    reviewCtx.fill();\n    reviewCtx.beginPath();\n    reviewCtx.fillStyle = draggedPointIndex === index || activeReviewPointIndex === index ? \"#b8ff52\" : \"#fffcf5\";\n    reviewCtx.arc(point.x, point.y, 22, 0, Math.PI * 2);\n    reviewCtx.fill();\n    reviewCtx.lineWidth = 3;\n    reviewCtx.strokeStyle = \"rgba(16, 21, 15, 0.28)\";\n    reviewCtx.stroke();\n    reviewCtx.fillStyle = \"#10150f\";\n    reviewCtx.font = \"700 22px sans-serif\";\n    reviewCtx.textAlign = \"center\";\n    reviewCtx.textBaseline = \"middle\";\n    reviewCtx.fillText(String(index + 1), point.x, point.y + 1);\n  });\n}\n\nfunction classifyProfile(palmWidthCm) {\n  if (palmWidthCm < 9.6) return \"Smuk\\u0142a\";\n  if (palmWidthCm < 10.4) return \"Standard\";\n  return \"Szeroka\";\n}\n\nfunction describeSeries(profile, fitStyle) {\n  if (profile === \"Smuk\\u0142a\" || fitStyle.includes(\"ciasna\")) {\n    return {\n      series: \"Varis X PRO\",\n      description:\n        \"Varis X PRO to najbardziej dopasowany feeling. Celuj w t\\u0119 seri\\u0119, je\\u015Bli lubisz ciasne czucie d\\u0142oni i bardziej precyzyjny kontakt z pi\\u0142k\\u0105.\",\n    };\n  }\n\n  if (fitStyle.includes(\"lu\\u017Ana\")) {\n    return {\n      series: \"Invictus X\",\n      description:\n        \"Invictus X daje bardziej swobodny fit. To dobry kierunek, je\\u015Bli wolisz troch\\u0119 wi\\u0119cej luzu i \\u0142atwiejsze wej\\u015Bcie d\\u0142oni w r\\u0119kawic\\u0119.\",\n    };\n  }\n\n  return {\n    series: \"Invictus X PRO\",\n    description:\n      \"Invictus X PRO to \\u015Brodek premium: bardziej pe\\u0142na, pewna r\\u0119kawica bez przesadnego luzu. Celuj w ni\\u0105, je\\u015Bli chcesz stabilny meczowy fit.\",\n  };\n}\n\nfunction getSizeRecommendation(handLengthCm, palmWidthCm) {\n  const profile = classifyProfile(palmWidthCm);\n  // Tabela pomiar\\u00F3w FM (2026-04-20):\n  //   13 cm \\u2192 3 | 14 cm \\u2192 4 | 15 cm \\u2192 5 | 16 cm \\u2192 6 | 17 cm \\u2192 7\n  //   18 cm \\u2192 8 | 19 cm \\u2192 9 | 20 cm \\u2192 10 | 21 cm \\u2192 11\n  // Logika: size = Math.round(handLengthCm - 10). Zaokr\\u0105glenie half-up:\n  //   18.49 \\u2192 round(8.49) = 8\n  //   18.50 \\u2192 round(8.50) = 9 (JS half-away-from-zero dla dodatnich)\n  //   18.60 \\u2192 round(8.60) = 9\n  //   19.00 \\u2192 round(9.00) = 9 \\u2713 (user test case)\n  const clamp = (n) => Math.max(3, Math.min(11, n));\n  const raw = handLengthCm - 10;\n  const primary = clamp(Math.round(raw));\n  const fraction = raw - Math.floor(raw);  // 0.0-0.99\n\n  // ZAWSZE dwie alternatywy: ciasne (primary-1) i lu\\u017Ane (primary+1)\n  // Wyj\\u0105tki: primary=3 \\u2192 tylko lu\\u017Ane 4; primary=11 \\u2192 tylko ciasne 10\n  const tighter = primary > 3 ? primary - 1 : null;\n  const looser = primary < 11 ? primary + 1 : null;\n\n  const size = String(primary);\n  const tighterStr = tighter !== null ? String(tighter) : null;\n  const looserStr = looser !== null ? String(looser) : null;\n\n  // Okre\\u015Bl kt\\u00F3ry alt jest bardziej blisko (dla subtelnego podkre\\u015Blenia)\n  // Je\\u015Bli fraction < 0.5 \\u2192 jeste\\u015B bli\\u017Cej tighter, wi\\u0119c to bardziej realna alternatywa\n  // Je\\u015Bli fraction \\u2265 0.5 \\u2192 jeste\\u015B bli\\u017Cej looser (primary), wi\\u0119c alternatywa to naprawd\\u0119 ciasne\n  const closerAlt = fraction >= 0.5 ? \"tighter\" : \"looser\";\n\n  // Fit style \\u2014 zawsze pokazujemy primary jako \"dopasowany\"\n  const sizeNum = primary;\n  const fitStyle = sizeNum <= 5 ? `dopasowany ${size}` : (sizeNum <= 8 ? `dopasowany ${size}` : `dopasowany ${size}`);\n\n  // Recommendation z konkretn\\u0105 tabel\\u0105\n  let recommendation = `Twoja d\\u0142ugo\\u015B\\u0107 d\\u0142oni ${handLengthCm.toFixed(2)} cm \\u2192 **rozmiar ${size}** to dopasowany fit. `;\n  if (tighterStr && looserStr) {\n    recommendation += `Alternatywy: **${tighterStr}** \\u2014 cia\\u015Bniejszy, lepsze czucie pi\\u0142ki, mniej luzu. **${looserStr}** \\u2014 lu\\u017Aniejszy, wygodniejszy na d\\u0142u\\u017Cszym treningu, wi\\u0119cej miejsca dla palc\\u00F3w.`;\n  } else if (looserStr) {\n    recommendation += `Alternatywa: **${looserStr}** \\u2014 lu\\u017Aniejszy fit.`;\n  } else if (tighterStr) {\n    recommendation += `Alternatywa: **${tighterStr}** \\u2014 cia\\u015Bniejszy fit.`;\n  }\n\n  const seriesData = describeSeries(profile, fitStyle);\n\n  return {\n    size,\n    altSize: closerAlt === \"tighter\" ? tighterStr : looserStr,  // legacy field\n    tighter: tighterStr,\n    looser: looserStr,\n    dualZone: true,  // zawsze pokazujemy obie opcje w UI\n    fitStyle,\n    profile,\n    recommendation,\n    series: seriesData.series,\n    seriesDescription: seriesData.description,\n  };\n}\n\nfunction showResult(data) {\n  const verdict = getSizeRecommendation(data.handLengthCm, data.palmWidthCm);\n  const precisionCopy =\n    data.quality === \"high\"\n      ? \"FM Lab policzy\\u0142 wynik na podstawie dobrze ustawionej kartki.\"\n      : \"FM Lab policzy\\u0142 wynik, ale przy nietypowym odczycie warto powt\\u00F3rzy\\u0107 skan z dok\\u0142adniej ustawion\\u0105 kartk\\u0105.\";\n\n  resultTitle.textContent = `Rozmiar d\\u0142oni: ${verdict.size}`;\n  resultCopy.textContent = `${precisionCopy} Masz ju\\u017C sw\\u00F3j punkt wyj\\u015Bcia do wyboru r\\u0119kawic Football Masters.`;\n  palmWidthValue.textContent = `${data.palmWidthCm.toFixed(2)} cm`;\n  handLengthValue.textContent = `${data.handLengthCm.toFixed(2)} cm`;\n  handProfileValue.textContent = verdict.fitStyle;\n  resultSizeValue.textContent = verdict.size;\n  seriesValue.textContent = verdict.series;\n  sizeRecommendationValue.textContent = verdict.recommendation;\n  seriesDescriptionValue.textContent = verdict.seriesDescription;\n\n  // BIOMETRIC \\u2192 CART BRIDGE (unique moat \\u2014 nikt w EU nie \\u0142\\u0105czy pomiaru \\u2192 koszyk)\n  // Deep link do sklepu z preselected size + series\n  try {\n    if (shopButton) {\n      const params = new URLSearchParams();\n      params.set(\"size\", String(verdict.size));\n      if (verdict.series) params.set(\"series\", String(verdict.series).toLowerCase().replace(/\\s+/g, \"-\"));\n      if (verdict.fitStyle) params.set(\"fit\", String(verdict.fitStyle).toLowerCase());\n      params.set(\"from\", \"pomiar\");\n      const shopUrl = \"/collections/all?\" + params.toString();\n      shopButton.href = shopUrl;\n      if (verdict.dualZone) {\n        shopButton.textContent = `Zobacz rozmiar ${verdict.size} (polecany) \\u2192`;\n      } else {\n        shopButton.textContent = `Zobacz r\\u0119kawice \\u00B7 rozmiar ${verdict.size} \\u00B7 ${verdict.series || \"FM\"} \\u2192`;\n      }\n      shopButton.setAttribute(\"aria-label\", `Przejd\\u017A do sklepu z dopasowanymi r\\u0119kawicami rozmiar ${verdict.size}`);\n    }\n    // Dual zone \\u2192 2 extra buttons (cia\\u015Bniejsze + lu\\u017Aniejsze)\n    const container = shopButton ? shopButton.parentElement : null;\n    if (verdict.dualZone && container) {\n      // Usu\\u0144 poprzednie (je\\u015Bli user reruns)\n      container.querySelectorAll(\".shop-btn-alt\").forEach(b => b.remove());\n      const mkBtn = (sz, label, tone) => {\n        const a = document.createElement(\"a\");\n        a.className = \"shop-btn-alt\";\n        const p = new URLSearchParams();\n        p.set(\"size\", String(sz));\n        p.set(\"from\", \"pomiar\");\n        p.set(\"fit_pref\", tone);\n        a.href = \"/collections/all?\" + p.toString();\n        a.textContent = label;\n        a.setAttribute(\"aria-label\", `Zobacz r\\u0119kawice w rozmiarze ${sz}`);\n        a.style.cssText = \"display:inline-flex;margin:6px 8px 0 0;padding:10px 18px;background:transparent;color:#fff;border:1px solid rgba(255,255,255,0.25);border-radius:999px;font:700 12px/1 'Space Grotesk',sans-serif;letter-spacing:0.04em;text-transform:uppercase;text-decoration:none;transition:border-color 0.15s\";\n        a.addEventListener(\"mouseenter\", () => a.style.borderColor = \"#d8ff62\");\n        a.addEventListener(\"mouseleave\", () => a.style.borderColor = \"rgba(255,255,255,0.25)\");\n        return a;\n      };\n      container.appendChild(mkBtn(verdict.tighter, `Wol\\u0119 cia\\u015Bniejsze \\u2192 rozmiar ${verdict.tighter}`, \"tight\"));\n      container.appendChild(mkBtn(verdict.looser, `Wol\\u0119 lu\\u017Aniejsze \\u2192 rozmiar ${verdict.looser}`, \"loose\"));\n    }\n  } catch (e) {}\n\n  saveMeasurementHistory({\n    createdAt: new Date().toISOString(),\n    palmWidthCm: Number(data.palmWidthCm.toFixed(2)),\n    handLengthCm: Number(data.handLengthCm.toFixed(2)),\n    size: verdict.size,\n    fitStyle: verdict.fitStyle,\n    series: verdict.series,\n    quality: data.quality,\n  });\n\n  trackEvent(\"scan_result\", {\n    size: verdict.size,\n    fit_style: verdict.fitStyle,\n    series: verdict.series,\n    hand_length_cm: Number(data.handLengthCm.toFixed(2)),\n    palm_width_cm: Number(data.palmWidthCm.toFixed(2)),\n    quality: data.quality,\n  });\n\n  if (activeLeadEmail) {\n    resultMailStatus.textContent = `Wysy\\u0142amy wynik FM Lab na ${activeLeadEmail}...`;\n    sendMeasurementResultEmail({\n      email: activeLeadEmail,\n      session: calibrationSession,\n      measuredAt: new Date().toISOString(),\n      result: {\n        size: verdict.size,\n        fitStyle: verdict.fitStyle,\n        profile: verdict.profile,\n        recommendation: verdict.recommendation,\n        series: verdict.series,\n        seriesDescription: verdict.seriesDescription,\n        palmWidthCm: Number(data.palmWidthCm.toFixed(2)),\n        handLengthCm: Number(data.handLengthCm.toFixed(2)),\n        quality: data.quality,\n      },\n    })\n      .then(() => {\n        resultMailStatus.textContent = `Wynik FM Lab zosta\\u0142 wys\\u0142any na ${activeLeadEmail}.`;\n        trackEvent(\"result_email_sent\", { email_domain: activeLeadEmail.split(\"@\")[1] || \"\" });\n      })\n      .catch((error) => {\n        console.error(error);\n        resultMailStatus.textContent = \"Nie uda\\u0142o si\\u0119 wys\\u0142a\\u0107 wiadomo\\u015Bci. Spr\\u00F3buj ponownie za chwil\\u0119.\";\n        trackEvent(\"result_email_failed\", { email_domain: activeLeadEmail.split(\"@\")[1] || \"\" });\n      });\n  } else {\n    resultMailStatus.textContent = \"Dodaj adres e-mail przed pomiarem, aby otrzyma\\u0107 wynik tak\\u017Ce w wiadomo\\u015Bci.\";\n  }\n\n  scanner.classList.add(\"hidden\");\n  setScannerSessionState(false);\n  result.classList.remove(\"hidden\");\n}\n\nfunction analyzeCapturedMeasurement() {\n  const card = getCardMetrics(manualCardPoints);\n  if (!capturedHand || !card) {\n    updateStatus(\"Ustaw cztery rogi kartki, aby obliczy\\u0107 wynik.\");\n    return;\n  }\n\n  const measurement = measureHandWithCard(manualCardPoints, capturedHand);\n  if (!measurement || Number.isNaN(measurement.palmWidthCm) || Number.isNaN(measurement.handLengthCm)) {\n    updateStatus(\"Nie uda\\u0142o si\\u0119 policzy\\u0107 wyniku. Popraw rogi kartki albo zr\\u00F3b nowe zdj\\u0119cie.\");\n    return;\n  }\n  capturedMeasurementLines = {\n    widthLine: measurement.widthLine,\n    lengthLine: measurement.lengthLine,\n  };\n  drawReviewCanvas();\n  showResult({\n    palmWidthCm: measurement.palmWidthCm,\n    handLengthCm: measurement.handLengthCm,\n    quality: manualCardPoints.length === 4 ? \"high\" : \"medium\",\n  });\n}\n\nasync function handleFrame() {\n  if (!hands || !video.videoWidth || isProcessingFrame || appMode !== \"live\") return;\n  isProcessingFrame = true;\n\n  try {\n    await hands.send({ image: video });\n\n    const now = performance.now();\n    if (currentHand && cvReady && now - liveCardCheckAt >= LIVE_CARD_CHECK_INTERVAL_MS && copyCurrentFrame()) {\n      liveCardCheckAt = now;\n      liveCardCandidate = detectCardOnCapturedFrame(currentHand);\n    } else if (!currentHand) {\n      liveCardCandidate = null;\n    }\n\n    updateAutoScan(now);\n  } finally {\n    isProcessingFrame = false;\n  }\n}\n\nfunction scheduleFrameLoop() {\n  if (frameRequestId) {\n    cancelAnimationFrame(frameRequestId);\n  }\n\n  const tick = async () => {\n    if (stream && !video.paused && !video.ended && appMode === \"live\") {\n      await handleFrame();\n    }\n    frameRequestId = requestAnimationFrame(tick);\n  };\n\n  frameRequestId = requestAnimationFrame(tick);\n}\n\nfunction pauseFrameLoop() {\n  if (frameRequestId) {\n    cancelAnimationFrame(frameRequestId);\n    frameRequestId = null;\n  }\n}\n\nasync function stopCamera() {\n  pauseFrameLoop();\n\n  if (stream) {\n    stream.getTracks().forEach((track) => track.stop());\n    stream = null;\n  }\n\n  video.srcObject = null;\n}\n\nfunction isPublicQaCameraRequest() {\n  const params = new URLSearchParams(window.location.search);\n  return params.has(\"cachecheck\") || params.has(\"parity\") || params.get(\"fm_result_fixture\") === \"1\";\n}\n\nfunction createSyntheticCameraStream() {\n  if (!canvas.captureStream) return null;\n  const width = 640;\n  const height = 480;\n  canvas.width = width;\n  canvas.height = height;\n  ctx.fillStyle = \"#102018\";\n  ctx.fillRect(0, 0, width, height);\n  ctx.fillStyle = \"#f5f0e8\";\n  ctx.fillRect(210, 70, 220, 330);\n  ctx.fillStyle = \"#d7b98e\";\n  ctx.beginPath();\n  ctx.ellipse(320, 250, 70, 120, 0, 0, Math.PI * 2);\n  ctx.fill();\n  ctx.fillStyle = \"#ffffff\";\n  ctx.font = \"24px sans-serif\";\n  ctx.fillText(\"FM Pro camera QA\", 205, 430);\n  return canvas.captureStream(15);\n}\n\nfunction getUserMediaWithTimeout(constraints, timeoutMs = 4500) {\n  return new Promise((resolve, reject) => {\n    let settled = false;\n    const timer = window.setTimeout(() => {\n      if (settled) return;\n      settled = true;\n      reject(new Error(\"Camera start timeout.\"));\n    }, timeoutMs);\n\n    navigator.mediaDevices.getUserMedia(constraints)\n      .then((mediaStream) => {\n        if (settled) {\n          mediaStream.getTracks().forEach((track) => track.stop());\n          return;\n        }\n        settled = true;\n        window.clearTimeout(timer);\n        resolve(mediaStream);\n      })\n      .catch((error) => {\n        if (settled) return;\n        settled = true;\n        window.clearTimeout(timer);\n        reject(error);\n      });\n  });\n}\n\nasync function startCamera() {\n  await stopCamera();\n\n  if (!navigator.mediaDevices?.getUserMedia) {\n    throw new Error(\"Ta przegl\u0105darka nie udost\u0119pnia aparatu dla tej strony.\");\n  }\n\n  const preferredConstraints = await buildVideoConstraints();\n  const fallbackConstraints = [\n    preferredConstraints,\n    {\n      width: { ideal: 1280 },\n      height: { ideal: 720 },\n      facingMode: activeFacingMode,\n    },\n    {\n      width: { ideal: 1280 },\n      height: { ideal: 720 },\n    },\n    true,\n  ];\n\n  let lastCameraError = null;\n  for (const constraints of fallbackConstraints) {\n    try {\n      stream = await getUserMediaWithTimeout({\n        video: constraints,\n        audio: false,\n      });\n      break;\n    } catch (error) {\n      lastCameraError = error;\n      console.warn(\"Nie uda\\u0142o si\\u0119 uruchomi\\u0107 kamery dla constraints, pr\\u00F3buj\\u0119 fallback.\", error);\n    }\n  }\n\n  if (!stream && isPublicQaCameraRequest()) {\n    stream = createSyntheticCameraStream();\n  }\n\n  if (!stream) {\n    throw lastCameraError || new Error(\"Brak dost\\u0119pnej kamery.\");\n  }\n\n  video.srcObject = stream;\n  video.setAttribute(\"playsinline\", \"\");\n  video.muted = true;\n  await video.play().catch(async (error) => {\n    await new Promise((resolve) => window.setTimeout(resolve, 200));\n    return video.play().catch(() => {\n      throw error;\n    });\n  });\n  setCanvasSize();\n  scheduleFrameLoop();\n  updateSwitchCameraLabel(false);\n}\n\nfunction resetReviewState() {\n  capturedHand = null;\n  capturedCard = null;\n  capturedImage = null;\n  capturedMeasurementLines = null;\n  manualCardPoints = [];\n  draggedPointIndex = -1;\n  activeReviewPointIndex = -1;\n  suppressReviewClick = false;\n  reviewPointsConfirmed = false;\n  syncAnalyzeAvailability();\n  updateReviewChecklist();\n  reviewCard.classList.add(\"hidden\");\n  cameraCard.classList.remove(\"hidden\");\n  resetAutoScanState();\n  setScannerVisualState(\"scanner-search\");\n  cardState.textContent = \"Kartka: sprawdzimy po zdj\\u0119ciu\";\n  reviewCopy.textContent =\n    \"Sprawd\\u017A rogi kartki. W razie potrzeby zresetuj je, ustaw cztery rogi i doprecyzuj przeci\\u0105ganiem.\";\n  reviewReferenceCopy.textContent = \"Zweryfikuj zdj\\u0119cie: punkty 1-4 powinny le\\u017Ce\\u0107 dok\\u0142adnie w rogach kartki.\";\n}\n\nfunction resetExperience() {\n  appMode = \"live\";\n  currentHand = null;\n  liveCardCandidate = null;\n  ctx.clearRect(0, 0, canvas.width, canvas.height);\n  setCaptureAvailability(false);\n  result.classList.add(\"hidden\");\n  scanner.classList.remove(\"hidden\");\n  setScannerSessionState(true);\n  resetReviewState();\n  updateDetectorState(false);\n  setScannerVisualState(\"scanner-search\");\n  resultTitle.textContent = \"Rozmiar d\\u0142oni: --\";\n  resultCopy.textContent = \"Za chwil\\u0119 poka\\u017Cemy Tw\\u00F3j wynik.\";\n  palmWidthValue.textContent = \"-- cm\";\n  handLengthValue.textContent = \"-- cm\";\n  handProfileValue.textContent = \"--\";\n  seriesValue.textContent = \"--\";\n  sizeRecommendationValue.textContent = \"Tutaj pojawi si\\u0119 rekomendacja rozmiaru.\";\n  seriesDescriptionValue.textContent = \"Tutaj pojawi si\\u0119 rekomendowana seria r\\u0119kawic.\";\n  resultMailStatus.textContent = \"Wy\\u015Blemy te\\u017C ten wynik na podany adres e-mail.\";\n  resultSizeValue.textContent = \"--\";\n  updateStatus(`${getStartContext()} Aktywna kamera: ${getCameraLabel()}.`);\n  if (stream) {\n    scheduleFrameLoop();\n  }\n}\n\nasync function switchCamera() {\n  activeFacingMode = activeFacingMode === \"environment\" ? \"user\" : \"environment\";\n  appMode = \"live\";\n  liveCardCandidate = null;\n  resetReviewState();\n  setCaptureAvailability(false);\n  updateSwitchCameraLabel(true);\n  updateStatus(`Prze\\u0142\\u0105czam na kamer\\u0119 ${getCameraLabel()}...`);\n\n  try {\n    await startCamera();\n    updateStatus(`Kamera ${getCameraLabel()} aktywna. ${getStartContext()}`);\n  } catch (error) {\n    setCaptureAvailability(false);\n    updateSwitchCameraLabel(false);\n    updateStatus(\"Nie uda\\u0142o si\\u0119 prze\\u0142\\u0105czy\\u0107 kamery. Sprawd\\u017A uprawnienia aparatu.\");\n    console.error(error);\n  }\n}\n\nasync function capturePhoto(options = {}) {\n  if (!currentHand || !copyCurrentFrame()) {\n    updateStatus(\"Poka\\u017C d\\u0142o\\u0144 stabilnie na kartce, a rozpoczniemy pomiar.\");\n    autoCaptureLocked = false;\n    return;\n  }\n\n  appMode = \"review\";\n  pauseFrameLoop();\n  capturedHand = currentHand;\n  const image = new Image();\n  image.src = processingCanvas.toDataURL(\"image/jpeg\", 0.95);\n  await image.decode();\n  capturedImage = image;\n\n  capturedCard = options.preDetectedCard || detectCardOnCapturedFrame(capturedHand);\n  manualCardPoints = capturedCard ? [...capturedCard.vertices] : [];\n  activeReviewPointIndex = 0;\n  reviewPointsConfirmed = false;\n  syncAnalyzeAvailability();\n  updateReviewChecklist();\n\n  cameraCard.classList.add(\"hidden\");\n  reviewCard.classList.remove(\"hidden\");\n  setScannerVisualState(\"scanner-review\");\n  drawReviewCanvas();\n\n  if (capturedCard) {\n    cardState.textContent = \"Kartka: gotowa\";\n    reviewCopy.textContent =\n      \"Kartka zosta\\u0142a wykryta. Dotknij numeru przy rogu i przeci\\u0105gnij go palcem, je\\u015Bli kt\\u00F3ry\\u015B punkt nie siedzi idealnie.\";\n    reviewReferenceCopy.textContent =\n      \"Zweryfikuj sw\\u00F3j pomiar. Je\\u015Bli kt\\u00F3ry\\u015B punkt nie le\\u017Cy idealnie w rogu kartki, popraw go przed potwierdzeniem.\";\n    updateStatus(\n      options.autoMode\n        ? \"Pomiar gotowy. Sprawd\\u017A rogi kartki i oblicz wynik.\"\n        : \"Zdj\\u0119cie gotowe. Sprawd\\u017A rogi kartki i oblicz wynik.\"\n    );\n  } else {\n    cardState.textContent = \"Kartka: ustaw 4 rogi\";\n    reviewCopy.textContent =\n      \"Kartka nie zosta\\u0142a wykryta wystarczaj\\u0105co dok\\u0142adnie. Ustaw cztery rogi kolejno i doprecyzuj je palcem.\";\n    reviewReferenceCopy.textContent =\n      \"Zaznacz punkt 1, 2, 3 i 4 dok\\u0142adnie w rogach kartki. Dopiero potem potwierd\\u017A uk\\u0142ad.\";\n    updateStatus(\"Zdj\\u0119cie gotowe. Ustaw cztery rogi kartki, aby przej\\u015B\\u0107 dalej.\");\n  }\n}\n\nfunction setupHands() {\n  if (hands) return;\n\n  hands = new Hands({\n    locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`,\n  });\n\n  hands.setOptions({\n    maxNumHands: 1,\n    modelComplexity: 0,\n    minDetectionConfidence: 0.45,\n    minTrackingConfidence: 0.45,\n  });\n\n  hands.onResults((results) => {\n    setCanvasSize();\n    if (!canvas.width || !canvas.height || appMode !== \"live\") return;\n\n    currentHand = results.multiHandLandmarks?.[0]\n      ? getHandMetrics(results.multiHandLandmarks[0], canvas.width, canvas.height)\n      : null;\n\n    drawLiveOverlay(currentHand, liveCardCandidate);\n\n    if (currentHand) {\n      updateDetectorState(true, liveCardCandidate ? \"Kartka: gotowa do skanu\" : \"Kartka: szukam\");\n      setScannerVisualState(\"scanner-lock\");\n      setCaptureAvailability(true);\n      updateStatus(\n        liveCardCandidate\n          ? \"D\\u0142o\\u0144 i kartka s\\u0105 widoczne. Nie ruszaj telefonu ani d\\u0142oni.\"\n          : \"D\\u0142o\\u0144 jest widoczna. Poka\\u017C teraz ca\\u0142\\u0105 kartk\\u0119 A4 w pionie.\"\n      );\n    } else {\n      updateDetectorState(false);\n      setScannerVisualState(\"scanner-search\");\n      setCaptureAvailability(false);\n      updateStatus(\"Ustaw d\\u0142o\\u0144 na \\u015Brodku kartki i poka\\u017C j\\u0105 w ca\\u0142o\\u015Bci.\");\n    }\n  });\n}\n\nfunction handleReviewClick(event) {\n  if (suppressReviewClick) {\n    suppressReviewClick = false;\n    return;\n  }\n\n  if (appMode !== \"review\" || !capturedImage) return;\n\n  const point = getCanvasPointFromEvent(event);\n\n  if (manualCardPoints.filter(Boolean).length === 4) {\n    const nearestIndex = findNearestCardPoint(point);\n    if (nearestIndex !== -1) {\n      selectReviewPoint(nearestIndex);\n      return;\n    }\n  }\n\n  placeOrMoveReviewPoint(point);\n}\n\nfunction handleReviewPointerDown(event) {\n  if (appMode !== \"review\" || !manualCardPoints.length) return;\n\n  const point = getCanvasPointFromEvent(event);\n  const nearestIndex = findNearestCardPoint(point);\n  if (nearestIndex === -1) return;\n\n  draggedPointIndex = nearestIndex;\n  activeReviewPointIndex = nearestIndex;\n  suppressReviewClick = false;\n  reviewCanvas.setPointerCapture(event.pointerId);\n  selectReviewPoint(nearestIndex);\n}\n\nfunction handleReviewPointerMove(event) {\n  if (draggedPointIndex === -1 || appMode !== \"review\") return;\n\n  manualCardPoints[draggedPointIndex] = getCanvasPointFromEvent(event);\n  activeReviewPointIndex = draggedPointIndex;\n  cardState.textContent =\n    manualCardPoints.filter(Boolean).length === 4 ? \"Kartka: poprawiasz r\\u0119cznie\" : cardState.textContent;\n  invalidateReviewConfirmation();\n  suppressReviewClick = true;\n  updateReviewChecklist();\n  drawReviewCanvas();\n}\n\nfunction handleReviewPointerUp(event) {\n  if (draggedPointIndex === -1) return;\n\n  manualCardPoints[draggedPointIndex] = getCanvasPointFromEvent(event);\n  activeReviewPointIndex = draggedPointIndex;\n  draggedPointIndex = -1;\n  if (reviewCanvas.hasPointerCapture(event.pointerId)) {\n    reviewCanvas.releasePointerCapture(event.pointerId);\n  }\n  if (manualCardPoints.filter(Boolean).length === 4) {\n    cardState.textContent = \"Kartka: sprawd\\u017A 4 punkty\";\n    invalidateReviewConfirmation();\n    updateStatus(\"Rogi poprawione. Sprawd\\u017A jeszcze raz wszystkie 4 punkty i potwierd\\u017A uk\\u0142ad.\");\n  }\n  updateReviewChecklist();\n  drawReviewCanvas();\n}\n\nfunction clearManualPoints() {\n  manualCardPoints = new Array(4);\n  activeReviewPointIndex = -1;\n  reviewPointsConfirmed = false;\n  syncAnalyzeAvailability();\n  cardState.textContent = \"Kartka: ustaw 4 rogi\";\n  updateReviewChecklist();\n  reviewReferenceCopy.textContent =\n    \"Zaznacz punkt 1, 2, 3 i 4 dok\\u0142adnie w rogach kartki. Dopiero potem potwierd\\u017A uk\\u0142ad.\";\n  updateStatus(\"Ustaw cztery rogi kartki od nowa.\");\n  drawReviewCanvas();\n}\n\nfunction confirmReviewPoints() {\n  if (manualCardPoints.filter(Boolean).length !== 4) {\n    updateStatus(\"Najpierw ustaw wszystkie 4 rogi kartki.\");\n    return;\n  }\n\n  reviewPointsConfirmed = true;\n  activeReviewPointIndex = -1;\n  cardState.textContent = \"Kartka: potwierdzona\";\n  reviewReferenceCopy.textContent =\n    \"Uk\\u0142ad punkt\\u00F3w zosta\\u0142 potwierdzony. Je\\u015Bli co\\u015B jeszcze poprawisz, potwierdzenie zniknie i trzeba b\\u0119dzie je zrobi\\u0107 ponownie.\";\n  syncAnalyzeAvailability();\n  updateReviewChecklist();\n  drawReviewCanvas();\n  updateStatus(\"Punkty s\\u0105 potwierdzone. Mo\\u017Cesz policzy\\u0107 wynik.\");\n}\n\nfunction handleReviewTouchStart(event) {\n  if (appMode !== \"review\" || !event.changedTouches.length) return;\n\n  const touch = event.changedTouches[0];\n  const point = getTouchPointFromTouch(touch);\n  const nearestIndex = findNearestCardPoint(point);\n\n  if (nearestIndex !== -1) {\n    activeTouchId = touch.identifier;\n    draggedPointIndex = nearestIndex;\n    activeReviewPointIndex = nearestIndex;\n    invalidateReviewConfirmation();\n    updateReviewChecklist();\n    drawReviewCanvas();\n    event.preventDefault();\n    return;\n  }\n\n  if (activeReviewPointIndex !== -1 || getNextMissingReviewPointIndex() !== -1) {\n    placeOrMoveReviewPoint(point);\n    event.preventDefault();\n  }\n}\n\nfunction handleReviewTouchMove(event) {\n  if (appMode !== \"review\" || draggedPointIndex === -1) return;\n\n  const touch = Array.from(event.changedTouches).find((item) => item.identifier === activeTouchId);\n  if (!touch) return;\n\n  manualCardPoints[draggedPointIndex] = getTouchPointFromTouch(touch);\n  activeReviewPointIndex = draggedPointIndex;\n  cardState.textContent = \"Kartka: poprawiasz r\\u0119cznie\";\n  invalidateReviewConfirmation();\n  updateReviewChecklist();\n  drawReviewCanvas();\n  event.preventDefault();\n}\n\nfunction handleReviewTouchEnd(event) {\n  if (draggedPointIndex === -1) return;\n\n  const touch = Array.from(event.changedTouches).find((item) => item.identifier === activeTouchId);\n  if (touch) {\n    manualCardPoints[draggedPointIndex] = getTouchPointFromTouch(touch);\n  }\n\n  activeTouchId = null;\n  activeReviewPointIndex = draggedPointIndex;\n  draggedPointIndex = -1;\n  cardState.textContent = \"Kartka: sprawd\\u017A 4 punkty\";\n  invalidateReviewConfirmation();\n  updateReviewChecklist();\n  drawReviewCanvas();\n  updateStatus(\"R\\u00F3g poprawiony. Sprawd\\u017A pozosta\\u0142e punkty i potwierd\\u017A uk\\u0142ad.\");\n  event.preventDefault();\n}\n\nfunction retakePhoto() {\n  appMode = \"live\";\n  liveCardCandidate = null;\n  resetReviewState();\n  updateDetectorState(Boolean(currentHand));\n  updateStatus(\"Wr\\u00F3cili\\u015Bmy do aparatu. Ustaw d\\u0142o\\u0144 na kartce i poka\\u017C ca\\u0142\\u0105 kartk\\u0119 w kadrze.\");\n  scheduleFrameLoop();\n}\n\nstartButton.addEventListener(\"click\", async () => {\n  leadStatus.textContent = \"Zapisujemy adres i uruchamiamy aparat...\";\n  startButton.disabled = true;\n\n  try {\n    await ensureLeadReady();\n    leadStatus.textContent = `Adres ${activeLeadEmail} zapisany. Otwieramy aparat.`;\n    trackEvent(\"scan_start\", {}, { onceKey: \"scan_start\" });\n  } catch (error) {\n    console.error(error);\n    leadStatus.textContent = \"Nie uda\\u0142o si\\u0119 zapisa\\u0107 adresu. Sprawd\\u017A go i spr\\u00F3buj ponownie.\";\n    syncStartAvailability();\n    return;\n  }\n\n  hero.classList.add(\"hidden\");\n  scanner.classList.remove(\"hidden\");\n  setScannerSessionState(true);\n  window.scrollTo({ top: 0, left: 0, behavior: \"instant\" });\n  updateStatus(\"Uruchamiam kamer\\u0119...\");\n  updateSwitchCameraLabel(true);\n  setupHands();\n  const cameraStartupTimer = window.setTimeout(() => {\n    const ready = Boolean(video?.srcObject && video.readyState >= 1);\n    if (!ready) {\n      updateStatus(\"Czekamy na zgod\\u0119 aparatu. Je\\u015Bli telefon pyta o kamer\\u0119, wybierz Zezw\\u00F3l. Gdy komunikat nie znika, od\\u015Bwie\\u017C stron\\u0119 albo otw\\u00F3rz j\\u0105 w Safari lub Chrome.\");\n    }\n  }, 7000);\n\n  try {\n    await startCamera();\n    window.clearTimeout(cameraStartupTimer);\n    updateStatus(`Kamera ${getCameraLabel()} aktywna. ${getStartContext()}`);\n  } catch (error) {\n    window.clearTimeout(cameraStartupTimer);\n    scanner.classList.remove(\"hidden\");\n    hero.classList.add(\"hidden\");\n    setScannerSessionState(true);\n    syncStartAvailability();\n    updateSwitchCameraLabel(false);\n    updateStatus(\"Nie uda\\u0142o si\\u0119 uruchomi\\u0107 kamery. Sprawd\\u017A zgod\\u0119 na aparat i otw\\u00F3rz stron\\u0119 w Safari albo Chrome. Mo\\u017Cesz te\\u017C prze\\u0142\\u0105czy\\u0107 kamer\\u0119.\");\n    setScannerVisualState(\"scanner-search\");\n    console.error(error);\n  }\n});\n\nif (captureButton) {\n  captureButton.addEventListener(\"click\", capturePhoto);\n}\nanalyzePhotoButton.addEventListener(\"click\", analyzeCapturedMeasurement);\nclearPointsButton.addEventListener(\"click\", clearManualPoints);\nconfirmPointsButton.addEventListener(\"click\", confirmReviewPoints);\nretakeButton.addEventListener(\"click\", retakePhoto);\nreviewCanvas.addEventListener(\"click\", handleReviewClick);\nreviewCanvas.addEventListener(\"pointerdown\", handleReviewPointerDown);\nreviewCanvas.addEventListener(\"pointermove\", handleReviewPointerMove);\nreviewCanvas.addEventListener(\"pointerup\", handleReviewPointerUp);\nreviewCanvas.addEventListener(\"pointercancel\", handleReviewPointerUp);\nreviewCanvas.addEventListener(\"touchstart\", handleReviewTouchStart, { passive: false });\nreviewCanvas.addEventListener(\"touchmove\", handleReviewTouchMove, { passive: false });\nreviewCanvas.addEventListener(\"touchend\", handleReviewTouchEnd, { passive: false });\nreviewCanvas.addEventListener(\"touchcancel\", handleReviewTouchEnd, { passive: false });\nreviewSteps.forEach((step, index) => {\n  if (!step) return;\n  step.addEventListener(\"click\", () => selectReviewPoint(index));\n});\nswitchCameraButton.addEventListener(\"click\", switchCamera);\nresetButton.addEventListener(\"click\", resetExperience);\nretryButton.addEventListener(\"click\", resetExperience);\nif (shopButton) {\n  shopButton.addEventListener(\"click\", () => {\n    trackEvent(\"shop_click\");\n  });\n}\n\nif (new URLSearchParams(window.location.search).get(\"fm_result_fixture\") === \"1\") {\n  hero.classList.add(\"hidden\");\n  scanner.classList.add(\"hidden\");\n  result.classList.remove(\"hidden\");\n  showResult({\n    quality: \"high\",\n    handLengthCm: 19,\n    palmWidthCm: 9,\n  });\n}\nsetScannerVisualState(\"scanner-search\");\ninstructionCheck.addEventListener(\"change\", syncStartAvailability);\nleadConsent.addEventListener(\"change\", syncStartAvailability);\nleadEmailInput.addEventListener(\"input\", syncStartAvailability);\nsetCaptureAvailability(false);\nresetAutoScanState();\nsyncViewportHeight();\ntrackEvent(\"page_view\", {}, { onceKey: \"page_view\" });\n\nwindow.addEventListener(\"resize\", syncViewportHeight);\nwindow.addEventListener(\"orientationchange\", () => {\n  window.setTimeout(syncViewportHeight, 160);\n});\n\nif (window.visualViewport) {\n  window.visualViewport.addEventListener(\"resize\", syncViewportHeight);\n}\n\nconst savedLeadProfile = readLeadProfile();\nif (savedLeadProfile?.email) {\n  leadEmailInput.value = savedLeadProfile.email;\n  leadConsent.checked = Boolean(savedLeadProfile.consent);\n  activeLeadEmail = savedLeadProfile.email;\n  leadStatus.textContent = `U\\u017Cyjemy zapisanego adresu ${savedLeadProfile.email}, aby wys\\u0142a\\u0107 wynik.`;\n}\n\nsyncStartAvailability();\n\nif (calibrationSession) {\n  hero.classList.add(\"hidden\");\n  scanner.classList.remove(\"hidden\");\n  setScannerSessionState(true);\n  updateStatus(\"Uruchamiamy aparat do pomiaru...\");\n  updateSwitchCameraLabel(true);\n  setupHands();\n  startCamera()\n    .then(() => {\n      updateStatus(`Kamera ${getCameraLabel()} aktywna. ${getStartContext()}`);\n    })\n    .catch((error) => {\n      updateSwitchCameraLabel(false);\n      updateStatus(\"Nie uda\\u0142o si\\u0119 uruchomi\\u0107 kamery po kalibracji.\");\n      console.error(error);\n    });\n}\n\nif (window.cv && typeof window.cv.imread === \"function\") {\n  window.Module.onRuntimeInitialized();\n}\n"],
  "mappings": "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",
  "names": ["clamp"]
}
