{"id":24670,"date":"2026-01-16T11:08:37","date_gmt":"2026-01-16T10:08:37","guid":{"rendered":"https:\/\/telemedi.com\/?page_id=24670"},"modified":"2026-03-11T13:17:22","modified_gmt":"2026-03-11T12:17:22","slug":"sprawdz-status-sprawy","status":"publish","type":"page","link":"https:\/\/telemedi.com\/pl\/sprawdz-status-sprawy\/","title":{"rendered":"Sprawd\u017a status sprawy"},"content":{"rendered":"\n<noscript>\n\t<div class=\"bg-red-600 text-white p-4 text-center font-bold mb-4\">\n\t\tUwaga! Ta strona wymaga w\u0142\u0105czonego JavaScript, aby dzia\u0142a\u0107 poprawnie. W\u0142\u0105cz obs\u0142ug\u0119 JavaScript w przegl\u0105darce i\n\t\tod\u015bwie\u017c stron\u0119.\n\t<\/div>\n<\/noscript>\n\n<div class=\"min-h-screen flex items-center justify-center p-4\">\n\t<!-- View 1: Verification -->\n\t<div id=\"verificationView\" class=\"view active w-full max-w-2xl\">\n\t\t<div class=\"card p-8\">\n\t\t\t<div class=\"flex justify-center mb-8 logo-container\">\n\t\t\t\t<img decoding=\"async\" src=\"https:\/\/telemedi.com\/wp-content\/themes\/telemedico-home-page\/src\/icons\/telemedi.svg\"\n\t\t\t\t\talt=\"Telemedi Logo\" class=\"h-12\">\n\t\t\t<\/div>\n\n\t\t\t<div id=\"loadingWorkflow\" class=\"hidden\">\n\t\t\t\t<div class=\"text-center py-8\">\n\t\t\t\t\t<div class=\"inline-block rounded-full h-12 w-12 border-b-2 border-gray-900 mb-4\"><\/div>\n\t\t\t\t\t<p class=\"text-gray-600\">\u0141adowanie&#8230;<\/p>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\n\t\t\t<div id=\"verificationContent\" class=\"hidden\">\n\t\t\t\t<h1 class=\"text-3xl font-bold text-gray-800 mb-4 text-center\">\n\t\t\t\t\tStatus Twojej Sprawy\n\t\t\t\t<\/h1>\n\n\t\t\t\t<p class=\"text-gray-600 mb-8 text-center leading-relaxed\" id=\"verificationDescription\">\n\t\t\t\t<\/p>\n\n\t\t\t\t<div id=\"verificationError\" class=\"mb-6 p-4 rounded-lg border-2 border-red-200 bg-red-50 hidden\">\n\t\t\t\t\t<div class=\"flex items-start\">\n\t\t\t\t\t\t<div class=\"flex-shrink-0\">\n\t\t\t\t\t\t\t<svg class=\"h-6 w-6 text-red-600\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n\t\t\t\t\t\t\t\t<path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"><\/path>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<div class=\"ml-3 flex-1\">\n\t\t\t\t\t\t\t<h3 class=\"text-sm font-semibold text-red-800 mb-2\">Nie uda\u0142o si\u0119 uzyska\u0107 dost\u0119pu do sprawy<\/h3>\n\t\t\t\t\t\t\t<div class=\"text-sm text-red-700\" id=\"verificationErrorMessage\">\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\n\t\t\t\t<form id=\"verificationForm\" class=\"space-y-6\">\n\t\t\t\t<div>\n\t\t\t\t\t<label for=\"secret\" class=\"block text-gray-700 font-medium mb-2\" id=\"secretLabel\">\n\t\t\t\t\t<\/label>\n\t\t\t\t\t<input type=\"text\" id=\"secret\" name=\"secret\"\n\t\t\t\t\t\tclass=\"input-field w-full px-4 py-3 rounded-lg text-gray-800\" required>\n\t\t\t\t\t<p id=\"secretError\" class=\"error-message\">\n\t\t\t\t\t<\/p>\n\t\t\t\t\t<p class=\"text-sm text-gray-500 mt-2\" id=\"secretHelpText\">\n\t\t\t\t\t<\/p>\n\t\t\t\t<\/div>\n\n\t\t\t\t\t<button type=\"submit\" class=\"btn-primary w-full py-3 px-6 rounded-lg text-white font-semibold text-lg\">\n\t\t\t\t\t\tSprawd\u017a Status\n\t\t\t\t\t<\/button>\n\t\t\t\t<\/form>\n\n\t\t\t\t<div class=\"mt-8 pt-6 border-t border-gray-200\">\n\t\t\t\t\t<p class=\"text-sm text-gray-500 text-center leading-relaxed\">\n\t\t\t\t\t\tZajmujemy si\u0119 Twoj\u0105 spraw\u0105. Skontaktujemy si\u0119 z Tob\u0105, je\u015bli b\u0119dziemy potrzebowa\u0107 dodatkowych\n\t\t\t\t\t\tinformacji.\n\t\t\t\t\t<\/p>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\n\t\t\t<div id=\"errorWorkflow\" class=\"hidden\">\n\t\t\t\t<div class=\"mb-6 p-4 rounded-lg border-2 border-red-200 bg-red-50\">\n\t\t\t\t\t<div class=\"flex items-start\">\n\t\t\t\t\t\t<div class=\"flex-shrink-0\">\n\t\t\t\t\t\t\t<svg class=\"h-6 w-6 text-red-600\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n\t\t\t\t\t\t\t\t<path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"><\/path>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<div class=\"ml-3 flex-1\">\n\t\t\t\t\t\t\t<h3 class=\"text-sm font-semibold text-red-800 mb-2\">Nie mo\u017cna za\u0142adowa\u0107 sprawy<\/h3>\n\t\t\t\t\t\t\t<div class=\"text-sm text-red-700\">\n\t\t\t\t\t\t\t\t<p class=\"mb-2\">Nie uda\u0142o si\u0119 uzyska\u0107 dost\u0119pu do sprawy. Mo\u017cliwe przyczyny:<\/p>\n\t\t\t\t\t\t\t\t<ul class=\"list-disc list-inside space-y-1\">\n\t\t\t\t\t\t\t\t\t<li>Link jest nieprawid\u0142owy lub wygas\u0142<\/li>\n\t\t\t\t\t\t\t\t\t<li>Problem z po\u0142\u0105czeniem internetowym<\/li>\n\t\t\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t\t\t<p class=\"mt-3\">Sprawd\u017a poprawno\u015b\u0107 linku, kt\u00f3ry otrzyma\u0142e\u015b.<\/p>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\t<\/div>\n\n\t<!-- View 2: Loading -->\n\t<div id=\"loadingView\" class=\"view w-full max-w-2xl\">\n\t\t<div class=\"card p-8\">\n\t\t\t<div class=\"flex justify-center mb-8 logo-container\">\n\t\t\t\t<img decoding=\"async\" src=\"https:\/\/telemedi.com\/wp-content\/themes\/telemedico-home-page\/src\/icons\/telemedi.svg\"\n\t\t\t\t\talt=\"Telemedi Logo\" class=\"h-12\">\n\t\t\t<\/div>\n\n\t\t\t<div class=\"text-center py-8\">\n\t\t\t\t<div class=\"inline-block rounded-full h-16 w-16 border-b-2 border-gray-900 mb-4\"><\/div>\n\t\t\t\t<h2 class=\"text-2xl font-bold text-gray-800 mb-2\">Sprawdzanie statusu&#8230;<\/h2>\n\t\t\t\t<p class=\"text-gray-600\">Prosimy o chwil\u0119 cierpliwo\u015bci<\/p>\n\t\t\t<\/div>\n\t\t<\/div>\n\t<\/div>\n\n\t<!-- View 3: Issue Status -->\n\t<div id=\"statusView\" class=\"view w-full max-w-2xl\">\n\t\t<div class=\"card p-8\">\n\t\t\t<div class=\"flex justify-center mb-8 logo-container\">\n\t\t\t\t<img decoding=\"async\" src=\"https:\/\/telemedi.com\/wp-content\/themes\/telemedico-home-page\/src\/icons\/telemedi.svg\"\n\t\t\t\t\talt=\"Telemedi Logo\" class=\"h-12\">\n\t\t\t<\/div>\n\n\t\t\t<h1 class=\"text-3xl font-bold text-gray-800 mb-4 text-center\">\n\t\t\t\tStatus Twojej Sprawy\n\t\t\t<\/h1>\n\n\t\t\t<p class=\"text-gray-600 mb-8 text-center leading-relaxed\">\n\t\t\t\tPoni\u017cej znajdziesz aktualne informacje dotycz\u0105ce Twojej sprawy.\n\t\t\t<\/p>\n\n\t\t\t<div id=\"timeLimitBox\" class=\"info-box fade-in fade-in-delayed hidden\">\n\t\t\t\t<div class=\"info-box-content\">\n\t\t\t\t\t<div class=\"info-box-header\">\n\t\t\t\t\t\t<div class=\"info-box-icon\">\n\t\t\t\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\"><\/circle>\n\t\t\t\t\t\t\t\t<polyline points=\"12 6 12 12 16 14\"><\/polyline>\n\t\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<h3 id=\"timeLimitText\">&#8211;<\/h3>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\n\t\t\t<div class=\"space-y-4\">\n\t\t\t\t<div class=\"grid grid-cols-1 md:grid-cols-2 gap-4 slide-in slide-in-delayed\">\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<h3 class=\"font-semibold text-gray-700 mb-2\">Numer Sprawy<\/h3>\n\t\t\t\t\t\t<p class=\"text-lg text-gray-800 break-words\" id=\"issueNumber\">&#8211;<\/p>\n\t\t\t\t\t<\/div>\n\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<h3 class=\"font-semibold text-gray-700 mb-2\">Data Utworzenia<\/h3>\n\t\t\t\t\t\t<p class=\"text-lg text-gray-800\" id=\"creationDate\">&#8211;<\/p>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\n\t\t\t\t<div class=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<h3 class=\"font-semibold text-gray-700 mb-3\">Aktualny Etap<\/h3>\n\t\t\t\t\t\t<span class=\"status-badge-large block text-center\" id=\"currentStatus\">&#8211;<\/span>\n\t\t\t\t\t<\/div>\n\n\t\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t\t<h3 class=\"font-semibold text-gray-700 mb-2\">Ostatnia Aktualizacja<\/h3>\n\t\t\t\t\t\t<p class=\"text-lg text-gray-800\" id=\"lastUpdate\">&#8211;<\/p>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\n\t\t\t\t<div class=\"info-item\">\n\t\t\t\t\t<h3 class=\"font-semibold text-gray-700 mb-2\">Dane Klienta<\/h3>\n\t\t\t\t\t<div class=\"mb-2\">\n\t\t\t\t\t\t<span class=\"text-sm text-gray-600 font-medium\">Imi\u0119 i Nazwisko: <\/span>\n\t\t\t\t\t\t<span class=\"text-lg text-gray-800 break-words\" id=\"clientName\">&#8211;<\/span>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<div>\n\t\t\t\t\t\t<span class=\"text-sm text-gray-600 font-medium\">Telefon: <\/span>\n\t\t\t\t\t\t<span class=\"text-lg text-gray-800 break-words\" id=\"clientPhone\">&#8211;<\/span>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\n\t\t<div id=\"caseClosedNotice\" class=\"case-closed-banner hidden\">\n\t\t\t<div class=\"case-closed-inner\">\n\t\t\t\t<div class=\"case-closed-icon\">\n\t\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t\t<path d=\"M20 6L9 17l-5-5\"\/>\n\t\t\t\t\t<\/svg>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"case-closed-text\">\n\t\t\t\t\t<div class=\"case-closed-title\">Sprawa zosta\u0142a zako\u0144czona<\/div>\n\t\t\t\t\t<div class=\"case-closed-subtitle\">Ta sprawa zosta\u0142a zamkni\u0119ta i nie wymaga dalszych dzia\u0142a\u0144.<\/div>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n\t\t<div id=\"stagesTimeline\" class=\"mt-8 hidden\">\n\t\t\t<h2 class=\"text-xl font-bold text-gray-800 mb-4\">Historia Etap\u00f3w<\/h2>\n\t\t\t<div class=\"timeline-container\">\n\t\t\t\t<div class=\"timeline-line\" id=\"timelineLine\"><\/div>\n\t\t\t\t<div id=\"timelineItems\"><\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\n\t\t<div id=\"visitInfoBox\" class=\"visit-info-box hidden\">\n\t\t\t<div id=\"visitInfoText\" class=\"visit-info-text\"><\/div>\n\t\t\t<div class=\"visit-info-buttons\">\n\t\t\t\t<button onclick=\"downloadVisitICS()\" class=\"btn-calendar btn-calendar-primary\">\n\t\t\t\t\t<svg role=\"img\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"currentColor\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701\"\/><\/svg>\n\t\t\t\t\tDodaj do kalendarza (Apple \/ Outlook)\n\t\t\t\t<\/button>\n\t\t\t\t<button onclick=\"openGoogleCalendar()\" class=\"btn-calendar btn-calendar-secondary\">\n\t\t\t\t\t<svg role=\"img\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M18.316 5.684H24v12.632h-5.684V5.684zM5.684 24h12.632v-5.684H5.684V24zM18.316 5.684V0H1.895A1.894 1.894 0 0 0 0 1.895v16.421h5.684V5.684h12.632zm-7.207 6.25v-.065c.272-.144.5-.349.687-.617s.279-.595.279-.982c0-.379-.099-.72-.3-1.025a2.05 2.05 0 0 0-.832-.714 2.703 2.703 0 0 0-1.197-.257c-.6 0-1.094.156-1.481.467-.386.311-.65.671-.793 1.078l1.085.452c.086-.249.224-.461.413-.633.189-.172.445-.257.767-.257.33 0 .602.088.816.264a.86.86 0 0 1 .322.703c0 .33-.12.589-.36.778-.24.19-.535.284-.886.284h-.567v1.085h.633c.407 0 .748.109 1.02.327.272.218.407.499.407.843 0 .336-.129.614-.387.832s-.565.327-.924.327c-.351 0-.651-.103-.897-.311-.248-.208-.422-.502-.521-.881l-1.096.452c.178.616.505 1.082.977 1.401.472.319.984.478 1.538.477a2.84 2.84 0 0 0 1.293-.291c.382-.193.684-.458.902-.794.218-.336.327-.72.327-1.149 0-.429-.115-.797-.344-1.105a2.067 2.067 0 0 0-.881-.689zm2.093-1.931l.602.913L15 10.045v5.744h1.187V8.446h-.827l-2.158 1.557zM22.105 0h-3.289v5.184H24V1.895A1.894 1.894 0 0 0 22.105 0zm-3.289 23.5l4.684-4.684h-4.684V23.5zM0 22.105C0 23.152.848 24 1.895 24h3.289v-5.184H0v3.289z\" fill=\"#4285F4\"\/><\/svg>\n\t\t\t\t\tDodaj do Kalendarza Google\n\t\t\t\t<\/button>\n\t\t\t<\/div>\n\t\t<\/div>\n\n\t\t<div id=\"patientDecisionBox\" class=\"patient-decision-box hidden\">\n\t\t\t<div id=\"patientDecisionText\" class=\"patient-decision-text\"><\/div>\n\t\t\t<div id=\"patientDecisionActions\" class=\"patient-decision-actions\">\n\t\t\t\t<button id=\"btnScheduleNoPreferences\" onclick=\"handlePatientDecision('book_without_preferences')\" class=\"btn-decision btn-decision-schedule\">\n\t\t\t\t\tUm\u00f3w wizyt\u0119 w pierwszym dost\u0119pnym terminie, bez preferencji plac\u00f3wki, daty oraz godziny.\n\t\t\t\t<\/button>\n\t\t\t\t<button id=\"btnCancelByPatient\" onclick=\"handlePatientDecision(PATIENT_ACTION.CANCEL_BY_PATIENT_REQUEST)\" class=\"btn-decision btn-decision-cancel\">\n\t\t\t\t\tAnuluj zg\u0142oszenie\n\t\t\t\t<\/button>\n\t\t\t<\/div>\n\t\t\t<div id=\"patientDecisionConfirmation\" class=\"patient-decision-confirmation hidden\">\n\t\t\t\t<div class=\"patient-decision-confirmation-inner\">\n\t\t\t\t\t<svg width=\"18\" height=\"18\" viewBox=\"0 0 20 20\" fill=\"#20a869\" class=\"patient-decision-confirmation-icon\"><path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"\/><\/svg>\n\t\t\t\t\t<span class=\"patient-decision-confirmation-text\">Twoja decyzja zosta\u0142a zapisana. Dzi\u0119kujemy.<\/span>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t<div id=\"patientDecisionError\" class=\"patient-decision-error hidden\"><\/div>\n\t\t<\/div>\n\n\t\t<div id=\"fileUploadBox\" class=\"file-upload-box hidden\">\n\t\t\t<div class=\"file-upload-box-title\">Dodaj dokumenty do sprawy<\/div>\n\t\t\t<div id=\"fileUploadDeadlineWarning\" class=\"file-upload-deadline-warning hidden\">\n\t\t\t\t<div class=\"file-upload-deadline-warning-icon\">\n\t\t\t\t\t<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t\t<circle cx=\"12\" cy=\"12\" r=\"10\"><\/circle>\n\t\t\t\t\t\t<polyline points=\"12 6 12 12 16 14\"><\/polyline>\n\t\t\t\t\t<\/svg>\n\t\t\t\t<\/div>\n\t\t\t\t<span class=\"file-upload-deadline-warning-text\">Masz 5 dni na przes\u0142anie wymaganej dokumentacji. Po tym czasie sprawa zostanie anulowana.<\/span>\n\t\t\t<\/div>\n\t\t\t<div id=\"fileUploadDescription\" class=\"file-upload-description hidden\"><\/div>\n\t\t\t<div id=\"fileUploadContent\">\n\t\t\t\t<div id=\"fileUploadDropzone\" class=\"file-upload-dropzone\" tabindex=\"0\" role=\"button\" aria-label=\"Wybierz pliki do przes\u0142ania\">\n\t\t\t\t\t<div class=\"file-upload-dropzone-icon\">\n\t\t\t\t\t\t<svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t\t\t<path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"><\/path>\n\t\t\t\t\t\t\t<polyline points=\"17 8 12 3 7 8\"><\/polyline>\n\t\t\t\t\t\t\t<line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"><\/line>\n\t\t\t\t\t\t<\/svg>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t<p class=\"file-upload-dropzone-label\">Kliknij aby wybra\u0107 pliki<\/p>\n\t\t\t\t\t<p class=\"file-upload-dropzone-sublabel\">lub przeci\u0105gnij i upu\u015b\u0107<\/p>\n\t\t\t\t\t<input id=\"fileUploadInput\" type=\"file\" class=\"hidden\" multiple accept=\".pdf,.jpg,.jpeg,.png,application\/pdf,image\/jpeg,image\/png\">\n\t\t\t\t<\/div>\n\t\t\t\t<p id=\"fileUploadFormats\" class=\"file-upload-formats\"><\/p>\n\t\t\t\t<div id=\"fileUploadList\" class=\"file-upload-list hidden\"><\/div>\n\t\t\t\t<button id=\"btnFileUpload\" type=\"button\" class=\"btn-file-upload hidden\" onclick=\"handleFileUpload()\">\n\t\t\t\t\t<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n\t\t\t\t\t\t<path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"><\/path>\n\t\t\t\t\t\t<polyline points=\"17 8 12 3 7 8\"><\/polyline>\n\t\t\t\t\t\t<line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"><\/line>\n\t\t\t\t\t<\/svg>\n\t\t\t\t\tWy\u015blij pliki\n\t\t\t\t<\/button>\n\t\t\t<\/div>\n\t\t\t<div id=\"fileUploadConfirmation\" class=\"file-upload-confirmation hidden\">\n\t\t\t\t<div class=\"file-upload-confirmation-inner\">\n\t\t\t\t\t<svg width=\"18\" height=\"18\" viewBox=\"0 0 20 20\" fill=\"#20a869\" class=\"file-upload-confirmation-icon\">\n\t\t\t\t\t\t<path fill-rule=\"evenodd\" d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"\/>\n\t\t\t\t\t<\/svg>\n\t\t\t\t\t<span class=\"file-upload-confirmation-text\">Pliki zosta\u0142y przes\u0142ane. Dzi\u0119kujemy.<\/span>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t\t<div id=\"fileUploadError\" class=\"file-upload-error hidden\"><\/div>\n\t\t<\/div>\n\n\t\t\t<div class=\"mt-8 pt-6 border-t border-gray-200\">\n\t\t\t\t<p class=\"text-sm text-gray-500 text-center leading-relaxed\">\n\t\t\t\t\tZajmujemy si\u0119 Twoj\u0105 spraw\u0105 i aktualizujemy etapy na bie\u017c\u0105co. Skontaktujemy si\u0119 z Tob\u0105, je\u015bli\n\t\t\t\t\tb\u0119dziemy potrzebowa\u0107 dodatkowych informacji lub gdy nast\u0105pi\u0105 istotne zmiany w etapach.\n\t\t\t\t<\/p>\n\t\t\t<\/div>\n\n\t\t\t<div id=\"faqSection\" class=\"mt-8 pt-6 border-t border-gray-200 hidden\">\n\t\t\t\t<h2 class=\"text-xl font-bold text-gray-800 mb-4\">Najcz\u0119\u015bciej zadawane pytania<\/h2>\n\t\t\t\t<div id=\"faqList\" class=\"space-y-2\">\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n<!-- Confirmation modal for patient decision -->\n<div id=\"confirmationModal\" class=\"confirmation-modal hidden\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"confirmationMessage\">\n\t<div id=\"confirmationBackdrop\" class=\"confirmation-backdrop\" onclick=\"closeConfirmationModal()\"><\/div>\n\t<div id=\"confirmationPanel\" class=\"confirmation-panel\">\n\t\t<p id=\"confirmationMessage\" class=\"confirmation-message\"><\/p>\n\t\t<div class=\"confirmation-buttons\">\n\t\t\t<button id=\"confirmationCancelBtn\" class=\"btn-confirmation-cancel\" onclick=\"closeConfirmationModal()\">\n\t\t\t\tWr\u00f3\u0107\n\t\t\t<\/button>\n\t\t\t<button id=\"confirmationConfirmBtn\" class=\"btn-confirmation-confirm\"><\/button>\n\t\t<\/div>\n\t<\/div>\n<\/div>\n\n\n\n<script>\n\twindow.TELEMEDI_API_BASE_URL = 'https:\/\/ims-backend.tmdi00.com';\n<\/script>\n\n\n\n<script>\n\t\/\/ Workflow name constants\n\tconst WORKFLOW = {\n\t\tMOTO_ASSISTANCE: 'moto_assistance',\n\t\tREFUND_ISSUE: 'refund_issue',\n\t\tNON_INTEGRATED_VISIT_STANDARD: 'non_integrated_visit_standard',\n\t};\n\n\t\/\/ Patient action code constants\n\tconst PATIENT_ACTION = {\n\t\tBOOK_WITHOUT_PREFERENCES: 'book_without_preferences',\n\t\tCANCEL_BY_PATIENT_REQUEST: 'cancel_by_patient_request',\n\t\tUPLOAD_DOCUMENTS: 'patient_upload_documents',\n\t};\n\n\t\/\/ Sanitization helper to prevent XSS\n\tfunction sanitizeHTML(str) {\n\t\tconst temp = document.createElement('div');\n\t\ttemp.textContent = str;\n\t\treturn temp.innerHTML;\n\t}\n\n\t\/\/ Safely retrieve a patient action from workflowData\n\tfunction getPatientAction(workflowData, actionName) {\n\t\treturn workflowData && workflowData.patientActionInfo\n\t\t\t&& workflowData.patientActionInfo[actionName] || null;\n\t}\n\n\t\/\/ Check if the patient decision (cancel or book-without-preferences) is pending\n\tfunction isPatientDecisionPending(workflowData) {\n\t\treturn !!(getPatientAction(workflowData, 'cancelByPatientRequest')\n\t\t\t|| getPatientAction(workflowData, 'bookWithoutPreferences'));\n\t}\n\n\t\/\/ Verification configuration per workflow\n\tconst verificationConfig = {\n\t\tdefault: {\n\t\t\tlabel: 'Numer PESEL',\n\t\t\tplaceholder: 'Wprowad\u017a numer PESEL',\n\t\t\tdescription: 'Aby sprawdzi\u0107 status Twojej sprawy, prosimy o podanie numeru PESEL w celu weryfikacji. Twoje dane s\u0105 bezpieczne i chronione.',\n\t\t\thelpText: 'Numer PESEL s\u0142u\u017cy wy\u0142\u0105cznie do weryfikacji Twojej to\u017csamo\u015bci.',\n\t\t\terrorMessage: 'Numer PESEL musi sk\u0142ada\u0107 si\u0119 z dok\u0142adnie 11 cyfr.',\n\t\t\tvalidation: {\n\t\t\t\tmaxLength: 11,\n\t\t\t\tpattern: '[0-9]{11}',\n\t\t\t\tvalidateLength: 11\n\t\t\t}\n\t\t},\n\t\tworkflows: {\n\t\t\t[WORKFLOW.MOTO_ASSISTANCE]: {\n\t\t\t\tlabel: 'Numer Rejestracyjny Pojazdu',\n\t\t\t\tplaceholder: 'Wprowad\u017a numer rejestracyjny pojazdu',\n\t\t\t\tdescription: 'Aby sprawdzi\u0107 status Twojej sprawy, prosimy o podanie numeru rejestracyjnego pojazdu w celu weryfikacji. Twoje dane s\u0105 bezpieczne i chronione.',\n\t\t\t\thelpText: 'Numer rejestracyjny pojazdu s\u0142u\u017cy wy\u0142\u0105cznie do weryfikacji.',\n\t\t\t\terrorMessage: 'Numer rejestracyjny pojazdu jest wymagany.',\n\t\t\t\tvalidation: {\n\t\t\t\t\tmaxLength: 20,\n\t\t\t\t\tpattern: null,\n\t\t\t\t\tvalidateLength: null\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\n\t\/\/ Time limit configuration per workflow (days and text generator function)\n\tconst timeLimitConfig = {\n\t\t[WORKFLOW.REFUND_ISSUE]: {\n\t\t\tdays: 30,\n\t\t\tgetText: (days) => `Termin rozpatrzenia wniosku refundacyjnego wynosi do ${days} dni`\n\t\t}\n\t};\n\n\n\t\/\/ Common fetch function with timeout handling\n\tasync function fetchWithTimeout(url) {\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(() => controller.abort(), 10000);\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: controller.signal });\n\t\t\tclearTimeout(timeoutId);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = new Error('HTTP error');\n\t\t\t\terror.status = response.status;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn await response.json();\n\t\t} catch (error) {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tif (error.name === 'AbortError') {\n\t\t\t\tconst timeoutError = new Error('Request timeout');\n\t\t\t\ttimeoutError.type = 'timeout';\n\t\t\t\tthrow timeoutError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t\/\/ API call to fetch workflow code\n\tasync function fetchWorkflowCode(issueId, hash) {\n\t\tconst url = getWorkflowURL(issueId, hash);\n\t\treturn await fetchWithTimeout(url);\n\t}\n\n\t\/\/ API call to fetch issue data\n\tasync function fetchIssueData(issueId, hash, secret) {\n\t\tconst url = getIssueDataUrl(issueId, hash, secret);\n\t\treturn await fetchWithTimeout(url);\n\t}\n\n\t\/\/ FAQ configuration\n\tconst faqConfig = {\n\t\t\"default\": [],\n\t\t\"workflows\": {\n\t\t[WORKFLOW.REFUND_ISSUE]: [\n\t\t\t{\n\t\t\t\t\"question\": \"Czy mog\u0119 uzyska\u0107 wi\u0119cej informacji na temat statusu swojego wniosku refundacyjnego?\",\n\t\t\t\t\"answer\": \"Wszystkie informacje na tocz\u0105cego si\u0119 procesu refundacyjnego podane s\u0105 powy\u017cej. Nasza infolinia nie jest w stanie udzieli\u0107 dodatkowych informacji na ten temat.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Jak d\u0142ugo trwa realizacja wniosku refundacyjnego?\",\n\t\t\t\t\"answer\": \"Czas realizacji wniosku refundacyjnego wynosi do 30 dni kalendarzowych. Status wniosku jest aktualizowany na bie\u017c\u0105co. Skontaktujemy si\u0119 z Tob\u0105, gdy b\u0119dziemy potrzebowali uzupe\u0142nienia dokumentacji b\u0105d\u017a innych informacji.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Jak d\u0142ugo trwa zwrot \u015brodk\u00f3w?\",\n\t\t\t\t\"answer\": \"Przelew jest realizowany w ci\u0105gu kilku dni roboczych po wydaniu pozytywnej decyzji w sprawie. Samo z\u0142o\u017cenie wniosku refundacyjnego nie jest gwarantem uzyskania zwrotu \u015brodk\u00f3w. Jedynie pozytywna decyzja w sprawie refundacyjnej powoduje zwrot \u015brodk\u00f3w.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Na jakie konto zostanie wykonany zwrot \u015brodk\u00f3w?\",\n\t\t\t\t\"answer\": \"Zwrot \u015brodk\u00f3w przekazywany jest na numer konta bankowego wpisany we wniosku refundacyjnym.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Czy potrzebuj\u0119 dostarczy\u0107 dodatkowe dokumenty?\",\n\t\t\t\t\"answer\": \"W sytuacji kiedy b\u0119dziemy potrzebowali od Ciebie dodatkowej dokumentacji medycznej lub innych wyja\u015bnie\u0144, b\u0119dziemy kontaktowa\u0107 si\u0119 z Tob\u0105 mailowo.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Jakie dokumenty musz\u0119 do\u0142\u0105czy\u0107 do wniosku, aby otrzyma\u0107 refundacj\u0119 koszt\u00f3w?\",\n\t\t\t\t\"answer\": \"Kluczowe dokumenty to:\\n- faktura imienna za us\u0142ug\u0119 medyczn\u0105, kt\u00f3ra ma zosta\u0107 zrefundowana (w przypadku faktury za rehabilitacj\u0119 musi ona zawiera\u0107 rozbicie na poszczeg\u00f3lne zabiegi i ich krotno\u015b\u0107),\\n- dokumentacja medyczna potwierdzaj\u0105ca wyst\u0105pienie zdarzenia ubezpieczeniowego (musi zawiera\u0107 dat\u0119 konsultacji, rozpoznanie medyczne, ewentualne zalecenia),\\n- dokumentacja medyczna z konsultacji lekarskiej, o kt\u00f3r\u0105 wnioskujesz, je\u015bli jest inna ni\u017c dokumentacja ze zdarzenia ubezpieczeniowego (przyk\u0142ad: zdarzenie uraz stawu kolanowego 05.2025, wizyta ortopedyczna 07.2025),\\n- w przypadku op\u0142acenia faktury przelewem: potwierdzenie przelewu,\\n- dla sprz\u0119tu rehabilitacyjnego: zalecenie lekarskie dotycz\u0105ce u\u017cywania danego sprz\u0119tu,\\n- dla transportu medycznego: zalecenie lekarskie na transport z okre\u015bleniem pozycji w transporcie.\\n\\nPowy\u017csza lista zawiera najcz\u0119\u015bciej wymagane dokumenty, natomiast nie jest kompletna. Wymagana dokumentacja medyczna zale\u017cy od charakteru zdarzenia medycznego i podj\u0119tego leczenia.\\n\\nSamo z\u0142o\u017cenie wniosku refundacyjnego z za\u0142\u0105czon\u0105 dokumentacj\u0105 medyczn\u0105 nie jest gwarantem uzyskania zwrotu \u015brodk\u00f3w. Jedynie pozytywna decyzja w sprawie refundacyjnej powoduje zwrot \u015brodk\u00f3w.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Czy musz\u0119 do\u0142\u0105czy\u0107 do wniosku od razu wszystkie faktury, czy mog\u0119 zg\u0142asza\u0107 koszty pojedynczo?\",\n\t\t\t\t\"answer\": \"Do wniosku refundacyjnego mo\u017cesz za\u0142\u0105czy\u0107 jedn\u0105 lub wi\u0119cej faktur. Pami\u0119taj aby we wniosku opisa\u0107 ka\u017cd\u0105 faktur\u0119, to przyspieszy procesowanie wniosku.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Czy je\u015bli mam ju\u017c z\u0142o\u017cony wniosek, kt\u00f3ry jest zamkni\u0119ty i koszty medyczne zosta\u0142y zrefundowane, mog\u0119 dos\u0142a\u0107 kolejn\u0105 faktur\u0119 mailem?\",\n\t\t\t\t\"answer\": \"Nie, ka\u017cda nowa faktura musi zosta\u0107 przekazywana do procesowania poprzez wniosek refundacyjny. Zatem je\u015bli z\u0142o\u017cony zosta\u0142 ju\u017c wniosek, kt\u00f3ry jest ju\u017c zamkni\u0119ty, konieczne jest z\u0142o\u017cenie nowego wniosku.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Je\u015bli mam dwie polisy to czy mog\u0119 podw\u00f3jnie uzyska\u0107 zwrot koszt\u00f3w?\",\n\t\t\t\t\"answer\": \"Nie. Refundacja mo\u017ce by\u0107 dokonana tylko raz. Wielokrotne wnioskowanie o wyp\u0142at\u0119 poniesionych koszt\u00f3w jest z\u0142amaniem Og\u00f3lnych Warunk\u00f3w Ubezpieczenia i mo\u017ce prowadzi\u0107 do konsekwencji prawnych dla ubezpieczonego.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"U kogo mog\u0119 podj\u0105\u0107 leczenie\/rehabilitacj\u0119 w przypadku diagnozy b\u0105d\u017a otrzymania skierowania?\",\n\t\t\t\t\"answer\": \"Refundacji podlegaj\u0105 wy\u0142\u0105cznie \u015bwiadczenia medyczne wykonane przez podmioty zarejestrowane w Rejestrze Podmiot\u00f3w Wykonuj\u0105cych Dzia\u0142alno\u015b\u0107 Lecznicz\u0105 (RPWDL). Oznacza to, \u017ce realizatorem \u015bwiadczenia medycznego (wystawc\u0105 faktury) musi by\u0107 podmiot medyczny posiadaj\u0105cy uprawnienia do wykonywania \u015bwiadcze\u0144 medycznych. Uprawnienia te mo\u017cna zweryfikowa\u0107 w ramach publicznego Rejestru Podmiot\u00f3w Wykonuj\u0105cych Dzia\u0142alno\u015b\u0107 Lecznicz\u0105 (RPWDL), pod adresem: rpwdl2.ezdrowie.gov.pl\\n\\nSamo z\u0142o\u017cenie wniosku refundacyjnego z za\u0142\u0105czon\u0105 dokumentacj\u0105 medyczn\u0105 nie jest gwarantem uzyskania zwrotu \u015brodk\u00f3w. Jedynie pozytywna decyzja w sprawie refundacyjnej powoduje zwrot \u015brodk\u00f3w.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Czy je\u015bli podczas wizyty lekarskiej zosta\u0142y wykonane dodatkowe badania (np. badanie RTG, testy alergiczne, cytologia \u2026), to czy one r\u00f3wnie\u017c podlegaj\u0105 refundacji?\",\n\t\t\t\t\"answer\": \"Nie. Refundacji podlegaj\u0105 \u015bci\u015ble okre\u015blone us\u0142ugi medycznej wymienione w tabeli \u015bwiadcze\u0144 zawartej w Og\u00f3lnych Warunkach Ubezpieczenia.\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"question\": \"Jaki pozosta\u0142 mi limit do wykorzystania na leczenie?\",\n\t\t\t\t\"answer\": \"Limity kwotowe oraz ilo\u015bciowe zosta\u0142y okre\u015blone w Og\u00f3lnych Warunkach Ubezpieczenia. W zale\u017cno\u015bci jaki masz limit oraz z ilu \u015bwiadcze\u0144 ju\u017c skorzysta\u0142e\u015b mo\u017cesz obliczy\u0107 jaka kwota pozosta\u0142a do wykorzystania. Pami\u0119taj, \u017ce limit dotyczy zdarzenia ubezpieczeniowego i wliczane s\u0105 do niego wszystkie us\u0142ugi (konsultacje, telekonsultacje, rehabilitacja, sprz\u0119t rehabilitacyjny, transport medyczny i inne).\"\n\t\t\t}\n\t\t]\n\t\t}\n\t};\n\n\t\/\/ Get FAQs based on workflow code\n\tfunction getFAQsForWorkflow(workflowCode) {\n\t\tif (!faqConfig) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (workflowCode && faqConfig.workflows && faqConfig.workflows[workflowCode]) {\n\t\t\treturn faqConfig.workflows[workflowCode];\n\t\t}\n\n\t\treturn faqConfig.default || [];\n\t}\n\n\t\/\/ Render FAQ section\n\tfunction renderFAQ(workflowCode) {\n\t\tconst faqSection = document.getElementById('faqSection');\n\t\tconst faqList = document.getElementById('faqList');\n\t\tconst faqs = getFAQsForWorkflow(workflowCode);\n\n\t\tif (faqs.length === 0) {\n\t\t\tfaqSection.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\tfaqSection.classList.remove('hidden');\n\t\tfaqList.innerHTML = '';\n\n\t\tfaqs.forEach((faq, index) => {\n\t\t\tconst faqItem = document.createElement('div');\n\t\t\tfaqItem.className = 'faq-item';\n\t\t\tfaqItem.innerHTML = `\n\t\t\t\t<div class=\"faq-question\" onclick=\"toggleFAQ(this)\">\n\t\t\t\t\t<span>${sanitizeHTML(faq.question)}<\/span>\n\t\t\t\t\t<span class=\"faq-icon\">+<\/span>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"faq-answer\">\n\t\t\t\t\t${sanitizeHTML(faq.answer)}\n\t\t\t\t<\/div>\n\t\t\t`;\n\t\t\tfaqList.appendChild(faqItem);\n\t\t});\n\t}\n\n\t\/\/ Toggle FAQ item\n\twindow.toggleFAQ = function (element) {\n\t\tconst faqItem = element.parentElement;\n\t\tconst isActive = faqItem.classList.contains('active');\n\n\t\tdocument.querySelectorAll('.faq-item').forEach(item => {\n\t\t\titem.classList.remove('active');\n\t\t});\n\n\t\tif (!isActive) {\n\t\t\tfaqItem.classList.add('active');\n\t\t}\n\t};\n\n\t\/\/ Format date helper - converts \"2025-06-24 11:45:20\" to \"24 czerwca 2025, 11:45\"\n\tfunction formatDate(dateString) {\n\t\tconst months = ['stycznia', 'lutego', 'marca', 'kwietnia', 'maja', 'czerwca',\n\t\t\t'lipca', 'sierpnia', 'wrze\u015bnia', 'pa\u017adziernika', 'listopada', 'grudnia'];\n\n\t\t\/\/ Parse the date string (format: \"YYYY-MM-DD HH:MM:SS\")\n\t\tconst [datePart, timePart] = dateString.split(' ');\n\t\tconst [year, month, day] = datePart.split('-');\n\t\tconst [hours, minutes] = timePart.split(':');\n\n\t\tconst monthName = months[parseInt(month) - 1];\n\n\t\treturn `${parseInt(day)} ${monthName} ${year}, ${hours}:${minutes}`;\n\t}\n\n\t\/\/ Get URL parameters\n\tfunction getURLParams() {\n\t\tconst params = new URLSearchParams(window.location.search);\n\t\treturn {\n\t\t\tissueId: params.get('issueId') || null,\n\t\t\thash: params.get('hash') || null\n\t\t};\n\t}\n\n\t\/\/ API Configuration\n\tconst API_CONFIG = {\n\t\tBASE_URL: window.TELEMEDI_API_BASE_URL\n\t};\n\n\t\/\/ Construct full API URLs\n\tconst getWorkflowURL = (issueId, hash) => {\n\t\tconst baseUrl = `${API_CONFIG.BASE_URL}\/api\/issue-status-check\/workflow`;\n\t\treturn `${baseUrl}?issueId=${encodeURIComponent(issueId)}&hash=${encodeURIComponent(hash)}`;\n\t};\n\tconst getIssueDataUrl = (issueId, hash, secret) => {\n\t\tconst baseUrl = `${API_CONFIG.BASE_URL}\/api\/issue-status-check`;\n\t\treturn `${baseUrl}?issueId=${encodeURIComponent(issueId)}&hash=${encodeURIComponent(hash)}&secret=${encodeURIComponent(secret)}`;\n\t};\n\n\t\/\/ Get verification config for workflow code\n\tfunction getVerificationConfig(workflowCode) {\n\t\tif (workflowCode && verificationConfig.workflows && verificationConfig.workflows[workflowCode]) {\n\t\t\treturn verificationConfig.workflows[workflowCode];\n\t\t}\n\t\treturn verificationConfig.default;\n\t}\n\n\t\/\/ Apply verification config to the form\n\tfunction applyVerificationConfig(config) {\n\t\tconst labelElement = document.getElementById('secretLabel');\n\t\tconst inputElement = document.getElementById('secret');\n\t\tconst errorElement = document.getElementById('secretError');\n\t\tconst helpTextElement = document.getElementById('secretHelpText');\n\t\tconst descriptionElement = document.getElementById('verificationDescription');\n\n\t\tif (labelElement) {\n\t\t\tlabelElement.textContent = config.label + ' *';\n\t\t}\n\n\t\tif (inputElement) {\n\t\t\tinputElement.placeholder = config.placeholder;\n\t\t\tinputElement.maxLength = config.validation.maxLength;\n\t\t\t\n\t\t\tif (config.validation.pattern) {\n\t\t\t\tinputElement.setAttribute('pattern', config.validation.pattern);\n\t\t\t} else {\n\t\t\t\tinputElement.removeAttribute('pattern');\n\t\t\t}\n\t\t}\n\n\t\tif (errorElement) {\n\t\t\terrorElement.textContent = config.errorMessage;\n\t\t}\n\n\t\tif (helpTextElement) {\n\t\t\thelpTextElement.textContent = config.helpText;\n\t\t}\n\n\t\tif (descriptionElement) {\n\t\t\tdescriptionElement.textContent = config.description;\n\t\t}\n\t}\n\n\t\/\/ Switch views\n\tfunction showView(viewId) {\n\t\tdocument.querySelectorAll('.view').forEach(view => {\n\t\t\tview.classList.remove('active');\n\t\t});\n\t\tdocument.getElementById(viewId).classList.add('active');\n\t}\n\n\t\/\/ Show verification error message\n\tfunction showVerificationError(reasons) {\n\t\tconst errorContainer = document.getElementById('verificationError');\n\t\tconst errorMessage = document.getElementById('verificationErrorMessage');\n\t\t\n\t\tlet html = '<p class=\"mb-2\">Mo\u017cliwe przyczyny:<\/p><ul class=\"list-disc list-inside space-y-1\">';\n\t\treasons.forEach(reason => {\n\t\t\thtml += `<li>${sanitizeHTML(reason)}<\/li>`;\n\t\t});\n\t\thtml += '<\/ul>';\n\t\t\n\t\terrorMessage.innerHTML = html;\n\t\terrorContainer.classList.remove('hidden');\n\n\t\t\/\/ Scroll to error message\n\t\terrorContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });\n\t}\n\n\t\/\/ Hide verification error message\n\tfunction hideVerificationError() {\n\t\tconst errorContainer = document.getElementById('verificationError');\n\t\terrorContainer.classList.add('hidden');\n\t}\n\n\n\t\/\/ Render stages timeline\n\tfunction renderStagesTimeline(stagesHistory, workflowCode, workflowData) {\n\t\tconst timelineSection = document.getElementById('stagesTimeline');\n\t\tconst timelineItems = document.getElementById('timelineItems');\n\t\tconst caseClosedNotice = document.getElementById('caseClosedNotice');\n\n\t\tif (!stagesHistory || stagesHistory.length === 0) {\n\t\t\ttimelineSection.classList.add('hidden');\n\t\t\tcaseClosedNotice.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\ttimelineSection.classList.remove('hidden');\n\t\ttimelineItems.innerHTML = '';\n\n\t\t\/\/ Check if the last stage is final\n\t\tconst lastStage = stagesHistory[stagesHistory.length - 1];\n\t\tconst isCaseClosed = lastStage && lastStage.isFinalStage === true;\n\n\t\t\/\/ Show\/hide closed case notice\n\t\tcaseClosedNotice.classList.toggle('hidden', !isCaseClosed);\n\n\t\t\/\/ Render past stages\n\t\tstagesHistory.forEach((stageItem, index) => {\n\t\t\tconst timelineItem = document.createElement('div');\n\t\t\ttimelineItem.className = 'timeline-item';\n\t\t\tconst isCurrent = index === stagesHistory.length - 1;\n\t\t\tconst dotClass = isCurrent ? 'timeline-dot current' : 'timeline-dot';\n\t\t\ttimelineItem.innerHTML = `\n\t\t\t\t<div class=\"${dotClass}\"><\/div>\n\t\t\t\t<div class=\"timeline-content\">\n\t\t\t\t\t<div class=\"timeline-stage-name\">${sanitizeHTML(stageItem.stage)}<\/div>\n\t\t\t\t\t<div class=\"timeline-stage-date\">${formatDate(stageItem.timestamp)}<\/div>\n\t\t\t\t<\/div>\n\t\t\t`;\n\t\t\ttimelineItems.appendChild(timelineItem);\n\t\t});\n\n\t\tconst hasScheduledVisit = workflowData && workflowData.visitInfo;\n\t\tconst isWaitingForDecision = isPatientDecisionPending(workflowData);\n\n\t\t\/\/ Add placeholder for future stages only if case is not closed, no visit is scheduled, and not waiting for patient decision\n\t\tif (!isCaseClosed && !hasScheduledVisit && !isWaitingForDecision) {\n\t\t\tconst placeholderItem = document.createElement('div');\n\t\t\tplaceholderItem.className = 'timeline-item timeline-placeholder';\n\t\t\tplaceholderItem.innerHTML = `\n\t\t\t\t<div class=\"timeline-dot\"><\/div>\n\t\t\t\t<div class=\"timeline-content\">\n\t\t\t\t\t<div class=\"timeline-stage-name\">Oczekuj na aktualizacj\u0119 dalszych status\u00f3w<\/div>\n\t\t\t\t\t<div class=\"timeline-stage-date\">...<\/div>\n\t\t\t\t<\/div>\n\t\t\t`;\n\t\t\ttimelineItems.appendChild(placeholderItem);\n\t\t}\n\n\t\t\/\/ Set timeline to green for completed stages only\n\t\tdocument.getElementById('timelineLine').classList.add('timeline-line-complete');\n\t}\n\n\t\/\/ Get time limit for workflow\n\tfunction getTimeLimitForWorkflow(workflowCode) {\n\t\tif (workflowCode && timeLimitConfig && timeLimitConfig[workflowCode]) {\n\t\t\treturn timeLimitConfig[workflowCode];\n\t\t}\n\t\treturn null;\n\t}\n\n\t\/\/ Render time limit box\n\tfunction renderTimeLimit(workflowCode) {\n\t\tconst timeLimitBox = document.getElementById('timeLimitBox');\n\t\tconst timeLimitText = document.getElementById('timeLimitText');\n\t\tconst timeLimitInfo = getTimeLimitForWorkflow(workflowCode);\n\n\t\tif (!timeLimitInfo) {\n\t\t\ttimeLimitBox.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\ttimeLimitBox.classList.remove('hidden');\n\t\ttimeLimitText.textContent = timeLimitInfo.getText(timeLimitInfo.days);\n\t}\n\n\t\/\/ Render visit info for non_integrated_visit_standard workflow\n\tfunction renderNonIntegratedVisitInfo(workflowData) {\n\t\tconst visitInfoBox = document.getElementById('visitInfoBox');\n\t\tconst visitInfoText = document.getElementById('visitInfoText');\n\n\t\tif (!workflowData || !workflowData.visitInfo) {\n\t\t\tvisitInfoBox.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\tconst visit = workflowData.visitInfo;\n\t\tconst parts = ['Us\u0142uga um\u00f3wiona'];\n\n\t\tif (visit.facilityName) {\n\t\t\tparts.push(visit.facilityName);\n\t\t}\n\t\tif (visit.facilityAddress) {\n\t\t\tparts.push(visit.facilityAddress);\n\t\t}\n\t\tif (visit.visitDate && visit.visitTime) {\n\t\t\tparts.push(`${visit.visitDate} godz ${visit.visitTime}`);\n\t\t} else if (visit.visitDate) {\n\t\t\tparts.push(visit.visitDate);\n\t\t}\n\n\t\tvisitInfoText.textContent = parts.join(' - ');\n\t\tvisitInfoBox.classList.remove('hidden');\n\n\t\t\/\/ Store visit data for ICS generation\n\t\tcurrentVisitInfo = visit;\n\t}\n\n\t\/\/ Current visit info for ICS download (set by renderNonIntegratedVisitInfo)\n\tlet currentVisitInfo = null;\n\n\t\/\/ Render patient decision box when cancel or book-without-preferences actions are available\n\tfunction renderPatientDecisionBox(workflowData) {\n\t\tconst decisionBox = document.getElementById('patientDecisionBox');\n\t\tconst visitInfoBox = document.getElementById('visitInfoBox');\n\t\tconst cancelAction = getPatientAction(workflowData, 'cancelByPatientRequest');\n\t\tconst bookAction = getPatientAction(workflowData, 'bookWithoutPreferences');\n\n\t\tif (!cancelAction && !bookAction) {\n\t\t\tdecisionBox.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\t\/\/ Hide visit info when decision is pending (mutually exclusive)\n\t\tvisitInfoBox.classList.add('hidden');\n\n\t\tdocument.getElementById('patientDecisionText').textContent =\n\t\t\t'Nie mo\u017cemy um\u00f3wi\u0107 us\u0142ugi zgodnie z Twoimi preferencjami \\u2014 zadecyduj o dalszych krokach sprawy. Brak decyzji w ci\u0105gu dw\u00f3ch dni skutkowa\u0107 b\u0119dzie anulacj\u0105.';\n\n\t\t\/\/ Show\/hide individual action buttons based on availability\n\t\tdocument.getElementById('btnScheduleNoPreferences').classList.toggle('hidden', !bookAction);\n\t\tdocument.getElementById('btnCancelByPatient').classList.toggle('hidden', !cancelAction);\n\n\t\tdecisionBox.classList.remove('hidden');\n\n\t\t\/\/ Reset state in case of re-render\n\t\tdocument.getElementById('patientDecisionActions').classList.remove('hidden');\n\t\tdocument.getElementById('patientDecisionConfirmation').classList.add('hidden');\n\t\tdocument.getElementById('patientDecisionError').classList.add('hidden');\n\t}\n\n\t\/\/ Submit a workflow action to the public API\n\tasync function submitWorkflowAction(actionCode) {\n\t\tconst url = `${API_CONFIG.BASE_URL}\/api\/public\/workflow\/action`;\n\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(() => controller.abort(), 10000);\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders: { 'Content-Type': 'application\/json' },\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tissueId: currentIssueId,\n\t\t\t\t\tactionCode: actionCode,\n\t\t\t\t\thash: currentHash,\n\t\t\t\t\tsecret: currentSecret,\n\t\t\t\t\tdata: []\n\t\t\t\t})\n\t\t\t});\n\t\t\tclearTimeout(timeoutId);\n\n\t\t\tconst data = await response.json().catch(() => null);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = new Error('HTTP error');\n\t\t\t\terror.status = response.status;\n\t\t\t\terror.responseData = data;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (data && !data.successful) {\n\t\t\t\tconst error = new Error('Action failed');\n\t\t\t\terror.status = 400;\n\t\t\t\terror.responseData = data;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn data;\n\t\t} catch (error) {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tif (error.name === 'AbortError') {\n\t\t\t\tconst timeoutError = new Error('Request timeout');\n\t\t\t\ttimeoutError.type = 'timeout';\n\t\t\t\tthrow timeoutError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t\/\/ Confirmation modal helpers\n\tconst confirmationMessages = {\n\t\t[PATIENT_ACTION.BOOK_WITHOUT_PREFERENCES]: {\n\t\t\tmessage: 'Czy napewno chcesz um\u00f3wi\u0107 wizyt\u0119 w pierwszym dost\u0119pnym terminie, bez preferencji plac\u00f3wki, daty oraz godziny?',\n\t\t\tconfirmLabel: 'Tak, um\u00f3w',\n\t\t\tconfirmClass: 'btn-confirmation-confirm-green',\n\t\t},\n\t\t[PATIENT_ACTION.CANCEL_BY_PATIENT_REQUEST]: {\n\t\t\tmessage: 'Czy na pewno chcesz anulowa\u0107 zg\u0142oszenie? Tej operacji nie mo\u017cna cofn\u0105\u0107.',\n\t\t\tconfirmLabel: 'Tak, anuluj',\n\t\t\tconfirmClass: 'btn-confirmation-confirm-red',\n\t\t},\n\t};\n\n\twindow.closeConfirmationModal = function () {\n\t\tconst modal = document.getElementById('confirmationModal');\n\t\tconst backdrop = document.getElementById('confirmationBackdrop');\n\t\tconst panel = document.getElementById('confirmationPanel');\n\t\tbackdrop.classList.remove('active');\n\t\tpanel.classList.remove('active');\n\t\tdocument.removeEventListener('keydown', handleModalEscape);\n\t\tsetTimeout(function () {\n\t\t\tmodal.classList.remove('active');\n\t\t\tmodal.classList.add('hidden');\n\t\t}, 300);\n\t};\n\n\tfunction handleModalEscape(e) {\n\t\tif (e.key === 'Escape') {\n\t\t\tcloseConfirmationModal();\n\t\t}\n\t}\n\n\t\/\/ Show confirmation modal before executing the action\n\twindow.handlePatientDecision = function (actionCode) {\n\t\tconst config = confirmationMessages[actionCode];\n\t\tif (!config) return;\n\n\t\tconst modal = document.getElementById('confirmationModal');\n\t\tconst backdrop = document.getElementById('confirmationBackdrop');\n\t\tconst panel = document.getElementById('confirmationPanel');\n\t\tdocument.getElementById('confirmationMessage').textContent = config.message;\n\n\t\tconst confirmBtn = document.getElementById('confirmationConfirmBtn');\n\t\tconfirmBtn.textContent = config.confirmLabel;\n\t\tconfirmBtn.className = 'btn-confirmation-confirm ' + config.confirmClass;\n\t\tconfirmBtn.onclick = function () { executePatientDecision(actionCode); };\n\n\t\t\/\/ Show modal and animate in\n\t\tmodal.classList.remove('hidden');\n\t\tmodal.classList.add('active');\n\t\tdocument.addEventListener('keydown', handleModalEscape);\n\t\trequestAnimationFrame(function () {\n\t\t\trequestAnimationFrame(function () {\n\t\t\t\tbackdrop.classList.add('active');\n\t\t\t\tpanel.classList.add('active');\n\t\t\t\tdocument.getElementById('confirmationCancelBtn').focus();\n\t\t\t});\n\t\t});\n\t};\n\n\t\/\/ Execute the confirmed patient decision\n\tasync function executePatientDecision(actionCode) {\n\t\tcloseConfirmationModal();\n\n\t\tconst btnSchedule = document.getElementById('btnScheduleNoPreferences');\n\t\tconst btnCancel = document.getElementById('btnCancelByPatient');\n\t\tconst errorBox = document.getElementById('patientDecisionError');\n\n\t\t\/\/ Disable buttons and show loading state\n\t\tbtnSchedule.disabled = true;\n\t\tbtnCancel.disabled = true;\n\t\tbtnSchedule.classList.add('disabled');\n\t\tbtnCancel.classList.add('disabled');\n\t\terrorBox.classList.add('hidden');\n\n\t\ttry {\n\t\t\tawait submitWorkflowAction(actionCode);\n\n\t\t\t\/\/ Success: hide buttons, show confirmation\n\t\t\tdocument.getElementById('patientDecisionActions').classList.add('hidden');\n\t\t\tdocument.getElementById('patientDecisionConfirmation').classList.remove('hidden');\n\t\t} catch (error) {\n\t\t\t\/\/ Re-enable buttons\n\t\t\tbtnSchedule.disabled = false;\n\t\t\tbtnCancel.disabled = false;\n\t\t\tbtnSchedule.classList.remove('disabled');\n\t\t\tbtnCancel.classList.remove('disabled');\n\n\t\t\t\/\/ Show error message based on failure type\n\t\t\tif (error.type === 'timeout') {\n\t\t\t\terrorBox.textContent = 'Przekroczono limit czasu odpowiedzi. Spr\u00f3buj ponownie.';\n\t\t\t} else if (error.status === 400) {\n\t\t\t\terrorBox.textContent = 'Nie uda\u0142o si\u0119 wykona\u0107 tej operacji. Skontaktuj si\u0119 z nami w celu uzyskania pomocy.';\n\t\t\t} else if (error.status === 403) {\n\t\t\t\terrorBox.textContent = 'Wyst\u0105pi\u0142 b\u0142\u0105d. Spr\u00f3buj ponownie p\u00f3\u017aniej.';\n\t\t\t} else {\n\t\t\t\terrorBox.textContent = 'Wyst\u0105pi\u0142 b\u0142\u0105d. Spr\u00f3buj ponownie p\u00f3\u017aniej.';\n\t\t\t}\n\t\t\terrorBox.classList.remove('hidden');\n\t\t}\n\t}\n\n\t\/\/ Shared calendar helpers\n\n\t\/\/ Parse visit date\/time strings into a Date; returns null if data is missing or malformed\n\t\/\/ Supports both DD.MM.YYYY and YYYY-MM-DD date formats\n\tfunction parseVisitDate(visit) {\n\t\tif (!visit.visitDate || !visit.visitTime) return null;\n\t\tconst timeParts = visit.visitTime.split(':');\n\t\tif (timeParts.length < 2) return null;\n\n\t\tlet day, month, year;\n\t\tif (visit.visitDate.includes('-')) {\n\t\t\tconst dateParts = visit.visitDate.split('-');\n\t\t\tif (dateParts.length !== 3) return null;\n\t\t\t[year, month, day] = dateParts;\n\t\t} else {\n\t\t\tconst dateParts = visit.visitDate.split('.');\n\t\t\tif (dateParts.length !== 3) return null;\n\t\t\t[day, month, year] = dateParts;\n\t\t}\n\n\t\tconst [hours, minutes] = timeParts;\n\t\tconst d = new Date(Number(year), Number(month) - 1, Number(day), Number(hours), Number(minutes));\n\t\treturn isNaN(d.getTime()) ? null : d;\n\t}\n\n\t\/\/ Escape special characters in ICS text values per RFC 5545\n\tfunction escapeICSText(value) {\n\t\treturn String(value ?? '')\n\t\t\t.replace(\/\\r\\n\/g, '\\n').replace(\/\\r\/g, '\\n')\n\t\t\t.replace(\/\\\\\/g, '\\\\\\\\')\n\t\t\t.replace(\/\\n\/g, '\\\\n')\n\t\t\t.replace(\/,\/g, '\\\\,')\n\t\t\t.replace(\/;\/g, '\\\\;');\n\t}\n\n\t\/\/ Fold ICS lines to max 75 octets per RFC 5545\n\tfunction foldICSLine(line) {\n\t\tif (line.length <= 75) return line;\n\t\tconst parts = [line.slice(0, 75)];\n\t\tlet i = 75;\n\t\twhile (i < line.length) {\n\t\t\tparts.push(' ' + line.slice(i, i + 74));\n\t\t\ti += 74;\n\t\t}\n\t\treturn parts.join('\\r\\n');\n\t}\n\n\t\/\/ Format local Date as ICS date-time (no timezone = floating local time)\n\tfunction toICSDate(d) {\n\t\tconst pad = n => String(n).padStart(2, '0');\n\t\treturn `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}T${pad(d.getHours())}${pad(d.getMinutes())}00`;\n\t}\n\n\t\/\/ Format UTC Date for DTSTAMP\n\tfunction toICSDateUTC(d) {\n\t\tconst pad = n => String(n).padStart(2, '0');\n\t\treturn `${d.getUTCFullYear()}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}T${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}${pad(d.getUTCSeconds())}Z`;\n\t}\n\n\t\/\/ Generate and download an ICS calendar file for the scheduled visit\n\twindow.downloadVisitICS = function () {\n\t\tif (!currentVisitInfo) return;\n\n\t\tconst visit = currentVisitInfo;\n\t\tconst start = parseVisitDate(visit);\n\t\tif (!start) return;\n\n\t\tconst end      = new Date(start.getTime() + 60 * 60 * 1000);\n\t\tconst location = [visit.facilityName, visit.facilityAddress].filter(Boolean).join(', ');\n\t\tconst summary  = visit.facilityName ? `Wizyta \u2013 ${visit.facilityName}` : 'Wizyta medyczna';\n\t\tconst uid      = `telemedi-${start.getTime()}-${Math.random().toString(36).slice(2)}@telemedi`;\n\n\t\tconst ics = [\n\t\t\t'BEGIN:VCALENDAR',\n\t\t\t'VERSION:2.0',\n\t\t\t'PRODID:-\/\/Telemedi\/\/Issue Status\/\/PL',\n\t\t\t'CALSCALE:GREGORIAN',\n\t\t\t'METHOD:PUBLISH',\n\t\t\t'BEGIN:VEVENT',\n\t\t\t`UID:${uid}`,\n\t\t\t`DTSTAMP:${toICSDateUTC(new Date())}`,\n\t\t\t`DTSTART:${toICSDate(start)}`,\n\t\t\t`DTEND:${toICSDate(end)}`,\n\t\t\t`SUMMARY:${escapeICSText(summary)}`,\n\t\t\tlocation ? `LOCATION:${escapeICSText(location)}` : '',\n\t\t\t`DESCRIPTION:${escapeICSText('Wizyta um\u00f3wiona przez Telemedi')}`,\n\t\t\t'STATUS:CONFIRMED',\n\t\t\t'TRANSP:OPAQUE',\n\t\t\t'END:VEVENT',\n\t\t\t'END:VCALENDAR',\n\t\t].filter(Boolean).map(foldICSLine).join('\\r\\n');\n\n\t\tconst blob = new Blob([ics], { type: 'text\/calendar;charset=utf-8' });\n\t\tconst url  = URL.createObjectURL(blob);\n\t\tconst a    = document.createElement('a');\n\t\ta.href     = url;\n\t\ta.download = 'wizyta.ics';\n\t\tdocument.body.appendChild(a);\n\t\ta.click();\n\t\tdocument.body.removeChild(a);\n\t\tURL.revokeObjectURL(url);\n\t};\n\n\t\/\/ Open Google Calendar \"add event\" URL (works on Android and desktop, opens calendar app directly)\n\twindow.openGoogleCalendar = function () {\n\t\tif (!currentVisitInfo) return;\n\n\t\tconst visit = currentVisitInfo;\n\t\tconst start = parseVisitDate(visit);\n\t\tif (!start) return;\n\n\t\tconst end      = new Date(start.getTime() + 60 * 60 * 1000);\n\t\tconst summary  = visit.facilityName ? `Wizyta \u2013 ${visit.facilityName}` : 'Wizyta medyczna';\n\t\tconst location = [visit.facilityName, visit.facilityAddress].filter(Boolean).join(', ');\n\n\t\t\/\/ Google Calendar expects local time without timezone suffix\n\t\tfunction toGCalDate(d) {\n\t\t\tconst pad = n => String(n).padStart(2, '0');\n\t\t\treturn `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}T${pad(d.getHours())}${pad(d.getMinutes())}00`;\n\t\t}\n\n\t\tconst params = new URLSearchParams({\n\t\t\taction: 'TEMPLATE',\n\t\t\ttext: summary,\n\t\t\tdates: `${toGCalDate(start)}\/${toGCalDate(end)}`,\n\t\t\tdetails: 'Wizyta um\u00f3wiona przez Telemedi',\n\t\t\tlocation: location,\n\t\t});\n\n\t\t\/\/ noopener prevents reverse-tabnabbing\n\t\twindow.open(`https:\/\/calendar.google.com\/calendar\/render?${params}`, '_blank', 'noopener,noreferrer');\n\t};\n\n\t\/\/ --- File Upload Functions ---\n\n\t\/\/ Format file size for display\n\tfunction formatFileSize(bytes) {\n\t\tif (bytes === 0) return '0 B';\n\t\tconst k = 1024;\n\t\tconst sizes = ['B', 'KB', 'MB', 'GB'];\n\t\tconst i = Math.floor(Math.log(bytes) \/ Math.log(k));\n\t\treturn parseFloat((bytes \/ Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\n\t}\n\n\t\/\/ Upload limits (must match backend: services.yaml)\n\tconst UPLOAD_LIMITS = {\n\t\tmaxFileSize: 10 * 1024 * 1024,   \/\/ 10 MB per file\n\t\tmaxTotalSize: 50 * 1024 * 1024,  \/\/ 50 MB total\n\t\tmaxFiles: 20,\n\t\tallowedTypes: ['application\/pdf', 'image\/jpeg', 'image\/png'],\n\t};\n\n\t\/\/ Check if adding a batch of files would exceed the max file count limit\n\tfunction wouldExceedMaxFiles(incomingCount) {\n\t\tif (selectedUploadFiles.length + incomingCount > UPLOAD_LIMITS.maxFiles) {\n\t\t\tshowFileUploadError('Wybrano zbyt wiele plik\u00f3w. Mo\u017cna przes\u0142a\u0107 maksymalnie ' + UPLOAD_LIMITS.maxFiles + ' plik\u00f3w.');\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t\/\/ Add a file to the upload list\n\tfunction addUploadFile(file) {\n\t\tif (!UPLOAD_LIMITS.allowedTypes.includes(file.type)) {\n\t\t\tshowFileUploadError('Nieprawid\u0142owy typ pliku. Obs\u0142ugiwane formaty: PDF, JPEG, PNG.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (file.size > UPLOAD_LIMITS.maxFileSize) {\n\t\t\tshowFileUploadError('Plik jest za du\u017cy. Maksymalny rozmiar pliku to 10 MB.');\n\t\t\treturn;\n\t\t}\n\n\t\tif (selectedUploadFiles.length >= UPLOAD_LIMITS.maxFiles) {\n\t\t\tshowFileUploadError('Mo\u017cna przes\u0142a\u0107 maksymalnie ' + UPLOAD_LIMITS.maxFiles + ' plik\u00f3w.');\n\t\t\treturn;\n\t\t}\n\n\t\tvar totalSize = selectedUploadFiles.reduce(function (sum, f) { return sum + f.size; }, 0) + file.size;\n\t\tif (totalSize > UPLOAD_LIMITS.maxTotalSize) {\n\t\t\tshowFileUploadError('\u0141\u0105czny rozmiar plik\u00f3w nie mo\u017ce przekracza\u0107 50 MB.');\n\t\t\treturn;\n\t\t}\n\n\t\t\/\/ Check for duplicates\n\t\tif (selectedUploadFiles.some(f => f.name === file.name && f.size === file.size)) {\n\t\t\treturn;\n\t\t}\n\n\t\tselectedUploadFiles.push(file);\n\t\trenderUploadFileList();\n\t\thideFileUploadError();\n\t}\n\n\t\/\/ Remove a file from the upload list\n\twindow.removeUploadFile = function (index) {\n\t\tselectedUploadFiles.splice(index, 1);\n\t\trenderUploadFileList();\n\t};\n\n\t\/\/ Render the list of selected files\n\tfunction renderUploadFileList() {\n\t\tconst listContainer = document.getElementById('fileUploadList');\n\t\tconst uploadBtn = document.getElementById('btnFileUpload');\n\n\t\tif (selectedUploadFiles.length === 0) {\n\t\t\tlistContainer.classList.add('hidden');\n\t\t\tuploadBtn.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\tlistContainer.innerHTML = '';\n\n\t\tselectedUploadFiles.forEach(function (file, index) {\n\t\t\tconst item = document.createElement('div');\n\t\t\titem.className = 'file-upload-item';\n\t\t\titem.innerHTML =\n\t\t\t\t'<div class=\"file-upload-item-info\">' +\n\t\t\t\t\t'<svg class=\"file-upload-item-icon\" width=\"16\" height=\"16\" viewBox=\"0 0 20 20\" fill=\"#9ca3af\"><path fill-rule=\"evenodd\" d=\"M4 4a2 2 0 012-2h4.586A2 2 0 0112 2.586L15.414 6A2 2 0 0116 7.414V16a2 2 0 01-2 2H6a2 2 0 01-2-2V4zm2 6a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7z\" clip-rule=\"evenodd\"><\/path><\/svg>' +\n\t\t\t\t\t'<span class=\"file-upload-item-name\">' + sanitizeHTML(file.name) + '<\/span>' +\n\t\t\t\t\t'<span class=\"file-upload-item-size\">(' + formatFileSize(file.size) + ')<\/span>' +\n\t\t\t\t'<\/div>' +\n\t\t\t\t'<button type=\"button\" onclick=\"removeUploadFile(' + index + ')\" class=\"file-upload-item-remove\" aria-label=\"Usu\u0144 plik\">' +\n\t\t\t\t\t'<svg width=\"16\" height=\"16\" viewBox=\"0 0 20 20\" fill=\"currentColor\"><path fill-rule=\"evenodd\" d=\"M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z\" clip-rule=\"evenodd\"><\/path><\/svg>' +\n\t\t\t\t'<\/button>';\n\t\t\tlistContainer.appendChild(item);\n\t\t});\n\n\t\tlistContainer.classList.remove('hidden');\n\t\tuploadBtn.classList.remove('hidden');\n\t}\n\n\t\/\/ Show file upload error message\n\tfunction showFileUploadError(message) {\n\t\tconst errorBox = document.getElementById('fileUploadError');\n\t\terrorBox.textContent = message;\n\t\terrorBox.classList.remove('hidden');\n\t}\n\n\t\/\/ Hide file upload error message\n\tfunction hideFileUploadError() {\n\t\tdocument.getElementById('fileUploadError').classList.add('hidden');\n\t}\n\n\t\/\/ Submit files via FormData to the workflow action API\n\tasync function submitWorkflowActionWithFiles(actionCode, files) {\n\t\tconst url = API_CONFIG.BASE_URL + '\/api\/public\/workflow\/action';\n\n\t\tconst controller = new AbortController();\n\t\tconst timeoutId = setTimeout(function () { controller.abort(); }, 30000); \/\/ 30s for file uploads\n\n\t\ttry {\n\t\t\tconst formData = new FormData();\n\t\t\tformData.append('payload', JSON.stringify({\n\t\t\t\tissueId: currentIssueId,\n\t\t\t\tactionCode: actionCode,\n\t\t\t\thash: currentHash,\n\t\t\t\tsecret: currentSecret,\n\t\t\t\tdata: {}\n\t\t\t}));\n\n\t\t\tfiles.forEach(function (file) {\n\t\t\t\tformData.append('documents[]', file);\n\t\t\t});\n\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\tsignal: controller.signal,\n\t\t\t\tbody: formData\n\t\t\t});\n\t\t\tclearTimeout(timeoutId);\n\n\t\t\tconst data = await response.json().catch(function () { return null; });\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst error = new Error('HTTP error');\n\t\t\t\terror.status = response.status;\n\t\t\t\terror.responseData = data;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (data && !data.successful) {\n\t\t\t\tconst error = new Error('Action failed');\n\t\t\t\terror.status = 400;\n\t\t\t\terror.responseData = data;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn data;\n\t\t} catch (error) {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tif (error.name === 'AbortError') {\n\t\t\t\tconst timeoutError = new Error('Request timeout');\n\t\t\t\ttimeoutError.type = 'timeout';\n\t\t\t\tthrow timeoutError;\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\t\/\/ Handle the file upload button click\n\twindow.handleFileUpload = async function () {\n\t\tif (selectedUploadFiles.length === 0) {\n\t\t\tshowFileUploadError('Wybierz co najmniej jeden plik.');\n\t\t\treturn;\n\t\t}\n\n\t\tconst uploadBtn = document.getElementById('btnFileUpload');\n\t\tconst originalText = uploadBtn.innerHTML;\n\t\thideFileUploadError();\n\n\t\t\/\/ Show loading state\n\t\tuploadBtn.disabled = true;\n\t\tuploadBtn.innerHTML =\n\t\t\t'<svg class=\"file-upload-spinner\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"10\" stroke-dasharray=\"31.4 31.4\" stroke-dashoffset=\"0\"><\/circle><\/svg>' +\n\t\t\t'Wysy\u0142anie...';\n\n\t\ttry {\n\t\t\tawait submitWorkflowActionWithFiles(PATIENT_ACTION.UPLOAD_DOCUMENTS, selectedUploadFiles);\n\n\t\t\t\/\/ Success: hide upload content, show confirmation\n\t\t\tdocument.getElementById('fileUploadContent').classList.add('hidden');\n\t\t\tdocument.getElementById('fileUploadConfirmation').classList.remove('hidden');\n\t\t\tselectedUploadFiles = [];\n\t\t} catch (error) {\n\t\t\t\/\/ Re-enable button\n\t\t\tuploadBtn.disabled = false;\n\t\t\tuploadBtn.innerHTML = originalText;\n\n\t\t\t\/\/ Show error based on type\n\t\t\tif (error.type === 'timeout') {\n\t\t\t\tshowFileUploadError('Przekroczono limit czasu przesy\u0142ania. Spr\u00f3buj ponownie.');\n\t\t\t} else if (error.status === 413) {\n\t\t\t\tshowFileUploadError('Pliki s\u0105 za du\u017ce. Zmniejsz rozmiar plik\u00f3w i spr\u00f3buj ponownie.');\n\t\t\t} else if (error.status === 400) {\n\t\t\t\tshowFileUploadError('Nie uda\u0142o si\u0119 przes\u0142a\u0107 plik\u00f3w. Sprawd\u017a format plik\u00f3w i spr\u00f3buj ponownie.');\n\t\t\t} else {\n\t\t\t\tshowFileUploadError('Wyst\u0105pi\u0142 b\u0142\u0105d podczas przesy\u0142ania plik\u00f3w. Spr\u00f3buj ponownie p\u00f3\u017aniej.');\n\t\t\t}\n\t\t}\n\t};\n\n\t\/\/ Render the file upload box based on workflowData\n\tfunction renderFileUploadBox(workflowData, workflowCode) {\n\t\tconst uploadBox = document.getElementById('fileUploadBox');\n\t\tconst descriptionEl = document.getElementById('fileUploadDescription');\n\t\tconst deadlineWarning = document.getElementById('fileUploadDeadlineWarning');\n\t\tconst uploadDocuments = getPatientAction(workflowData, 'uploadDocuments');\n\n\t\tif (!uploadDocuments) {\n\t\t\tuploadBox.classList.add('hidden');\n\t\t\treturn;\n\t\t}\n\n\t\tuploadBox.classList.remove('hidden');\n\n\t\t\/\/ Populate upload limits text from constants\n\t\tdocument.getElementById('fileUploadFormats').textContent =\n\t\t\t'PDF, JPEG, PNG - maks. ' + (UPLOAD_LIMITS.maxFileSize \/ (1024 * 1024)) + ' MB na plik, ' +\n\t\t\t(UPLOAD_LIMITS.maxTotalSize \/ (1024 * 1024)) + ' MB \u0142\u0105cznie, do ' + UPLOAD_LIMITS.maxFiles + ' plik\u00f3w';\n\n\t\t\/\/ Show deadline warning only for non-integrated visit workflow\n\t\tdeadlineWarning.classList.toggle('hidden', workflowCode !== WORKFLOW.NON_INTEGRATED_VISIT_STANDARD);\n\n\t\t\/\/ Render required documents description if present\n\t\tif (uploadDocuments.requiredDocumentsDescription) {\n\t\t\tdescriptionEl.innerHTML = '';\n\t\t\tvar label = document.createElement('div');\n\t\t\tlabel.className = 'file-upload-description-label';\n\t\t\tlabel.textContent = 'Wymagane dokumenty:';\n\t\t\tdescriptionEl.appendChild(label);\n\n\t\t\tvar itemsContainer = document.createElement('div');\n\t\t\titemsContainer.className = 'file-upload-description-items';\n\t\t\tuploadDocuments.requiredDocumentsDescription\n\t\t\t\t.split('\\n')\n\t\t\t\t.map(function (line) { return line.replace(\/^-\\s*\/, '').trim(); })\n\t\t\t\t.filter(function (line) { return line.length > 0; })\n\t\t\t\t.forEach(function (item) {\n\t\t\t\t\tvar card = document.createElement('div');\n\t\t\t\t\tcard.className = 'file-upload-doc-card';\n\n\t\t\t\t\tvar icon = document.createElement('div');\n\t\t\t\t\ticon.className = 'file-upload-doc-icon';\n\t\t\t\t\ticon.innerHTML = '<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"><\/path><polyline points=\"14 2 14 8 20 8\"><\/polyline><\/svg>';\n\t\t\t\t\tcard.appendChild(icon);\n\n\t\t\t\t\tvar name = document.createElement('span');\n\t\t\t\t\tname.className = 'file-upload-doc-name';\n\t\t\t\t\tname.textContent = item;\n\t\t\t\t\tcard.appendChild(name);\n\n\t\t\t\t\titemsContainer.appendChild(card);\n\t\t\t\t});\n\t\t\tdescriptionEl.appendChild(itemsContainer);\n\t\t\tdescriptionEl.classList.remove('hidden');\n\t\t} else {\n\t\t\tdescriptionEl.innerHTML = '';\n\t\t\tdescriptionEl.classList.add('hidden');\n\t\t}\n\n\t\t\/\/ Reset state in case of re-render\n\t\tselectedUploadFiles = [];\n\t\tdocument.getElementById('fileUploadContent').classList.remove('hidden');\n\t\tdocument.getElementById('fileUploadConfirmation').classList.add('hidden');\n\t\thideFileUploadError();\n\t\tdocument.getElementById('fileUploadList').classList.add('hidden');\n\t\tdocument.getElementById('btnFileUpload').classList.add('hidden');\n\n\t\t\/\/ Set up drag-and-drop and click handlers\n\t\tconst uploadArea = document.getElementById('fileUploadDropzone');\n\t\tconst fileInput = document.getElementById('fileUploadInput');\n\n\t\t\/\/ Clone to remove old listeners and avoid duplicates on re-render\n\t\tconst newUploadArea = uploadArea.cloneNode(true);\n\t\tuploadArea.parentNode.replaceChild(newUploadArea, uploadArea);\n\n\t\tconst newFileInput = newUploadArea.querySelector('#fileUploadInput');\n\n\t\tnewUploadArea.addEventListener('click', function () {\n\t\t\tnewFileInput.click();\n\t\t});\n\n\t\tnewUploadArea.addEventListener('keydown', function (e) {\n\t\t\tif (e.key === 'Enter' || e.key === ' ') {\n\t\t\t\te.preventDefault();\n\t\t\t\tnewFileInput.click();\n\t\t\t}\n\t\t});\n\n\t\tnewFileInput.addEventListener('click', function (e) {\n\t\t\te.stopPropagation();\n\t\t});\n\n\t\tnewFileInput.addEventListener('change', function (e) {\n\t\t\tvar newFiles = Array.from(e.target.files);\n\t\t\tif (wouldExceedMaxFiles(newFiles.length)) {\n\t\t\t\te.target.value = '';\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnewFiles.forEach(function (file) {\n\t\t\t\taddUploadFile(file);\n\t\t\t});\n\t\t\te.target.value = '';\n\t\t});\n\n\t\tnewUploadArea.addEventListener('dragover', function (e) {\n\t\t\te.preventDefault();\n\t\t\tnewUploadArea.classList.add('dragover');\n\t\t});\n\n\t\tnewUploadArea.addEventListener('dragleave', function (e) {\n\t\t\te.preventDefault();\n\t\t\tvar related = e.relatedTarget;\n\t\t\tif (related && newUploadArea.contains(related)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnewUploadArea.classList.remove('dragover');\n\t\t});\n\n\t\tnewUploadArea.addEventListener('drop', function (e) {\n\t\t\te.preventDefault();\n\t\t\tnewUploadArea.classList.remove('dragover');\n\t\t\tvar newFiles = Array.from(e.dataTransfer.files);\n\t\t\tif (wouldExceedMaxFiles(newFiles.length)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tnewFiles.forEach(function (file) {\n\t\t\t\taddUploadFile(file);\n\t\t\t});\n\t\t});\n\t}\n\n\t\/\/ Update status view with data\n\tfunction updateStatusView(data, workflowCode) {\n\t\tdocument.getElementById('issueNumber').textContent = data.issueNumber || '-';\n\t\tdocument.getElementById('creationDate').textContent = formatDate(data.creationDate);\n\t\tdocument.getElementById('lastUpdate').textContent = formatDate(data.lastUpdate);\n\t\tdocument.getElementById('clientName').textContent = data.clientName || '-';\n\t\tdocument.getElementById('clientPhone').textContent = data.phone || '-';\n\n\t\t\/\/ Get current status from the last stage in history\n\t\tconst currentStatus = data.stagesHistory && data.stagesHistory.length > 0\n\t\t\t? data.stagesHistory[data.stagesHistory.length - 1].stage\n\t\t\t: 'W trakcie realizacji';\n\t\tdocument.getElementById('currentStatus').textContent = currentStatus;\n\n\t\trenderTimeLimit(workflowCode);\n\t\trenderFAQ(workflowCode);\n\t\trenderStagesTimeline(data.stagesHistory, workflowCode, data.workflowData);\n\n\t\t\/\/ Patient decision box \u2014 driven by patientActionInfo\n\t\trenderPatientDecisionBox(data.workflowData);\n\n\t\t\/\/ Visit info \u2014 show only when present and no patient decision is pending\n\t\tif (!isPatientDecisionPending(data.workflowData)) {\n\t\t\trenderNonIntegratedVisitInfo(data.workflowData);\n\t\t} else {\n\t\t\tdocument.getElementById('visitInfoBox').classList.add('hidden');\n\t\t}\n\n\t\t\/\/ File upload box \u2014 driven by patientActionInfo\n\t\trenderFileUploadBox(data.workflowData, workflowCode);\n\t}\n\n\t\/\/ Global state\n\tlet currentValidationConfig = null;\n\tlet currentWorkflowCode = null;\n\tlet currentSecret = null;\n\tlet currentIssueId = null;\n\tlet currentHash = null;\n\tlet selectedUploadFiles = [];\n\n\t\/\/ Handle form submission\n\tdocument.getElementById('verificationForm').addEventListener('submit', async function (e) {\n\t\te.preventDefault();\n\n\t\tconst secretInput = document.getElementById('secret');\n\t\tconst secretError = document.getElementById('secretError');\n\t\tconst secret = secretInput.value.trim();\n\t\tconst urlParams = getURLParams();\n\n\t\t\/\/ Hide any previous verification errors\n\t\thideVerificationError();\n\n\t\t\/\/ Validate based on current config\n\t\tif (currentValidationConfig && currentValidationConfig.validateLength) {\n\t\t\tif (secret.length !== currentValidationConfig.validateLength) {\n\t\t\t\tsecretInput.classList.add('error');\n\t\t\t\tsecretError.classList.add('show');\n\t\t\t\treturn;\n\t\t\t}\n\t\t} else {\n\t\t\t\/\/ For workflows without specific length validation, just check if not empty\n\t\t\tif (secret.length === 0) {\n\t\t\t\tsecretInput.classList.add('error');\n\t\t\t\tsecretError.classList.add('show');\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tsecretInput.classList.remove('error');\n\t\tsecretError.classList.remove('show');\n\n\t\tconst issueId = urlParams.issueId;\n\t\tconst hash = urlParams.hash;\n\n\t\t\/\/ Show loading view\n\t\tshowView('loadingView');\n\n\t\ttry {\n\t\t\t\/\/ Fetch issue data from API\n\t\t\tconst response = await fetchIssueData(issueId, hash, secret);\n\n\t\t\tif (response.successful && response.data) {\n\t\t\t\t\/\/ Store credentials for later API calls (e.g., workflow actions)\n\t\t\t\tcurrentSecret = secret;\n\t\t\t\tcurrentIssueId = issueId;\n\t\t\t\tcurrentHash = hash;\n\n\t\t\t\tupdateStatusView(response.data, currentWorkflowCode);\n\t\t\t\tshowView('statusView');\n\t\t\t} else {\n\t\t\t\t\/\/ Handle API error - generic error for security reasons\n\t\t\t\tshowView('verificationView');\n\t\t\t\tshowVerificationError([\n\t\t\t\t\t'Wprowadzono nieprawid\u0142owe dane weryfikacyjne',\n\t\t\t\t\t'Sprawa nie jest ju\u017c dost\u0119pna do podgl\u0105du'\n\t\t\t\t]);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tshowView('verificationView');\n\t\t\t\n\t\t\t\/\/ Handle specific error types\n\t\t\tif (error.status === 403) {\n\t\t\t\t\/\/ Access denied from API\n\t\t\t\tshowVerificationError([\n\t\t\t\t\t'Wprowadzono nieprawid\u0142owe dane weryfikacyjne',\n\t\t\t\t\t'Sprawa nie jest ju\u017c dost\u0119pna do podgl\u0105du'\n\t\t\t\t]);\n\t\t\t} else if (error.type === 'timeout') {\n\t\t\t\t\/\/ Request timeout\n\t\t\t\tshowVerificationError([\n\t\t\t\t\t'Przekroczono limit czasu odpowiedzi',\n\t\t\t\t\t'Sprawd\u017a po\u0142\u0105czenie internetowe i spr\u00f3buj ponownie'\n\t\t\t\t]);\n\t\t\t} else if (error instanceof TypeError) {\n\t\t\t\t\/\/ Network error (no internet, CORS, DNS failure, etc.)\n\t\t\t\tshowVerificationError([\n\t\t\t\t\t'Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z serwerem',\n\t\t\t\t\t'Sprawd\u017a po\u0142\u0105czenie internetowe'\n\t\t\t\t]);\n\t\t\t} else {\n\t\t\t\t\/\/ Generic error for any other unexpected issue\n\t\t\t\tshowVerificationError([\n\t\t\t\t\t'Wyst\u0105pi\u0142 nieoczekiwany b\u0142\u0105d',\n\t\t\t\t\t'Spr\u00f3buj ponownie p\u00f3\u017aniej'\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t});\n\n\t\/\/ Format secret input and validate (set up during initialization)\n\tconst secretInput = document.getElementById('secret');\n\tconst secretError = document.getElementById('secretError');\n\n\tfunction setupInputFormatting(config) {\n\t\tsecretInput.removeEventListener('input', secretInput._inputHandler);\n\t\t\n\t\tsecretInput._inputHandler = function (e) {\n\t\t\t\/\/ Hide verification error when user starts typing\n\t\t\thideVerificationError();\n\t\t\t\n\t\t\t\/\/ Only allow numbers for PESEL-like fields\n\t\t\tif (config.validation.pattern && config.validation.pattern.includes('[0-9]')) {\n\t\t\t\tthis.value = this.value.replace(\/[^0-9]\/g, '');\n\t\t\t}\n\t\t\t\n\t\t\t\/\/ Clear error if valid length is reached (when applicable)\n\t\t\tif (config.validation.validateLength && this.value.length === config.validation.validateLength) {\n\t\t\t\tthis.classList.remove('error');\n\t\t\t\tsecretError.classList.remove('show');\n\t\t\t} else if (!config.validation.validateLength && this.value.length > 0) {\n\t\t\t\tthis.classList.remove('error');\n\t\t\t\tsecretError.classList.remove('show');\n\t\t\t}\n\t\t};\n\t\t\n\t\tsecretInput.addEventListener('input', secretInput._inputHandler);\n\t}\n\n\t\/\/ Initialize - fetch workflow code and set up verification view\n\twindow.addEventListener('DOMContentLoaded', async function () {\n\t\tconst urlParams = getURLParams();\n\t\tconst issueId = urlParams.issueId;\n\t\tconst hash = urlParams.hash;\n\n\t\t\/\/ Show loading state\n\t\tdocument.getElementById('loadingWorkflow').classList.remove('hidden');\n\n\t\ttry {\n\t\t\t\/\/ Validate required parameters\n\t\t\tif (!issueId || !hash) {\n\t\t\t\tdocument.getElementById('loadingWorkflow').classList.add('hidden');\n\t\t\t\tdocument.getElementById('errorWorkflow').classList.remove('hidden');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t\/\/ Fetch workflow code from API\n\t\t\tconst response = await fetchWorkflowCode(issueId, hash);\n\n\t\t\tif (response.successful && response.data && response.data.workflowCode) {\n\t\t\t\tconst workflowCode = response.data.workflowCode;\n\t\t\t\tcurrentWorkflowCode = workflowCode;\n\n\t\t\t\t\/\/ Get configuration for this workflow\n\t\t\t\tconst config = getVerificationConfig(workflowCode);\n\n\t\t\t\t\/\/ Store validation config globally\n\t\t\t\tcurrentValidationConfig = config.validation;\n\n\t\t\t\t\/\/ Apply all configuration in one place\n\t\t\t\tapplyVerificationConfig(config);\n\t\t\t\tsetupInputFormatting(config);\n\n\t\t\t\t\/\/ Show verification form\n\t\t\t\tdocument.getElementById('loadingWorkflow').classList.add('hidden');\n\t\t\t\tdocument.getElementById('verificationContent').classList.remove('hidden');\n\t\t\t} else {\n\t\t\t\t\/\/ Show error state - API returned unsuccessful response\n\t\t\t\tdocument.getElementById('loadingWorkflow').classList.add('hidden');\n\t\t\t\tdocument.getElementById('errorWorkflow').classList.remove('hidden');\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t\/\/ Show error state - all errors show the same generic message for security\n\t\t\tdocument.getElementById('loadingWorkflow').classList.add('hidden');\n\t\t\tdocument.getElementById('errorWorkflow').classList.remove('hidden');\n\t\t}\n\t});\n<\/script>\n\n\n\n<style>\nheader.header {\n  display: none;\n}\n<\/style>\n","protected":false},"excerpt":{"rendered":"<p>Uwaga! Ta strona wymaga w\u0142\u0105czonego JavaScript, aby dzia\u0142a\u0107 poprawnie. W\u0142\u0105cz obs\u0142ug\u0119 JavaScript w przegl\u0105darce i od\u015bwie\u017c stron\u0119. \u0141adowanie&#8230; Status Twojej Sprawy Nie uda\u0142o si\u0119 uzyska\u0107 dost\u0119pu do sprawy Sprawd\u017a Status Zajmujemy si\u0119 Twoj\u0105 spraw\u0105. Skontaktujemy si\u0119 z Tob\u0105, je\u015bli b\u0119dziemy potrzebowa\u0107 dodatkowych informacji. Nie mo\u017cna za\u0142adowa\u0107 sprawy Nie uda\u0142o si\u0119 uzyska\u0107 dost\u0119pu do sprawy. Mo\u017cliwe [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_acf_changed":false,"content-type":"","footnotes":""},"class_list":["post-24670","page","type-page","status-publish","hentry"],"acf":[],"lang":"pl","translations":{"pl":24670},"_links":{"self":[{"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/pages\/24670","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/comments?post=24670"}],"version-history":[{"count":4,"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/pages\/24670\/revisions"}],"predecessor-version":[{"id":25015,"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/pages\/24670\/revisions\/25015"}],"wp:attachment":[{"href":"https:\/\/telemedi.com\/tm-api\/wp\/v2\/media?parent=24670"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}