<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Darmowy konwerter PDF na JPG, PNG, Word i Excel</title>
<meta name="description" content="Zamień PDF na JPG, PNG, Word, Excel lub PowerPoint online za darmo. Bez rejestracji i znaku wodnego - wynik w kilka sekund.">
<link rel="canonical" href="https://pdfconverter.pl/">
<meta name="robots" content="index, follow">
<meta name="theme-color" content="#E31C23">
<meta property="og:type" content="website">
<meta property="og:locale" content="pl_PL">
<meta property="og:site_name" content="pdfconverter.pl">
<meta property="og:title" content="Darmowy konwerter PDF na JPG, PNG, Word i Excel">
<meta property="og:description" content="Zamień PDF na JPG, PNG, Word, Excel lub PowerPoint online za darmo. Bez rejestracji i znaku wodnego - wynik w kilka sekund.">
<meta property="og:url" content="https://pdfconverter.pl/">
<meta property="og:image" content="https://pdfconverter.pl/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Darmowy konwerter PDF na JPG, PNG, Word i Excel">
<meta name="twitter:description" content="Zamień PDF na JPG, PNG, Word, Excel lub PowerPoint online za darmo. Bez rejestracji i znaku wodnego - wynik w kilka sekund.">
<meta name="twitter:image" content="https://pdfconverter.pl/og-image.png">
<meta name="keywords" content="konwerter pdf, pdf na jpg, pdf na word, pdf na excel, pdf na powerpoint, darmowy konwerter pdf online, konwertuj pdf">
<meta name="author" content="pdfconverter.pl">

<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='22' fill='%23E31C23'/><text x='50' y='68' font-size='48' text-anchor='middle' fill='white' font-family='system-ui,sans-serif' font-weight='700'>P</text></svg>">

<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap" rel="stylesheet"></noscript>

<style>
:root {
 --blue-900: #9f1239;
 --blue-700: #be123c;
 --blue-600: #E31C23;
 --blue-500: #f43f5e;
 --blue-200: #fecdd3;
 --blue-100: #fecaca;
 --blue-050: #fef2f2;
 --blue-025: #fff5f5;
 --cyan: #f87171;
 --navy: #0b2545;
 --muted: #3d4f66;
 --muted-2: #3d4f66;
 --white: #ffffff;
 --green: #0e6b3c;
 --green-bg: #e7f8ee;
 --blue: #E31C23;
 --error: #c62828;
 --error-bg: #fdecec;
 --blue-bg: #fdecec;
 --amber: #8a5a00;
 --amber-bg: #fff6e0;
 --radius: 16px;
 --radius-lg: 24px;
 --shadow-sm: 0 2px 10px rgba(11,37,69,.05);
 --shadow: 0 10px 34px rgba(11,37,69,.08);
 --shadow-lg: 0 24px 60px rgba(159,18,57,.14);
 --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
 margin: 0;
 font-family: var(--font);
 font-size: 17px;
 line-height: 1.65;
 color: var(--navy);
 background: var(--white);
 -webkit-font-smoothing: antialiased;
}
img, svg { max-width: 100%; }
a { color: var(--blue-600); text-decoration: none; }
a:hover { text-decoration: underline; } a.brand:hover,a.brand:focus,.brand span,.wordmark span{text-decoration:none!important}
.wrap { width: 100%; max-width: 1080px; margin: 0 auto; padding: 0 20px; }
.narrow { max-width: 800px; margin-left: auto; margin-right: auto; }

/* Header */
.site-header {
 position: sticky;
 top: 0;
 z-index: 50;
 background: var(--white);
 border-bottom: 1px solid var(--blue-100);
}
.site-header .wrap {
 display: flex;
 align-items: center;
 justify-content: space-between;
 height: 68px;
 gap: 16px;
}
.brand {
 display: flex;
 align-items: center;
 gap: 10px;
 text-decoration: none;
}
.brand:hover, .brand:focus, .brand:active { text-decoration: none !important; }
.brand span, .wordmark, .wordmark span { text-decoration: none !important; }
.footer-logo:hover, .footer-logo:focus { text-decoration: none !important; }
.footer-logo span { text-decoration: none !important; }
.brand-icon {
 width: 36px;
 height: 36px;
 border-radius: 10px;
 background: #E31C23;
 display: grid;
 place-items: center;
 color: white;
 font-weight: 800;
 font-size: 18px;
}
.wordmark {
 font-size: 22px;
 font-weight: 800;
 letter-spacing: -0.6px;
 color: var(--navy);
}
.wordmark span { color: #E31C23; }
.nav { display: flex; align-items: center; gap: 26px; }
.nav a {
 color: var(--muted);
 font-size: 15px;
 font-weight: 600;
 text-decoration: none;
}
.nav a:hover { color: var(--blue-600); text-decoration: none; }

.nav-toggle {
 display: none;
 width: 44px;
 height: 44px;
 border: none;
 background: transparent;
 border-radius: 10px;
 cursor: pointer;
 padding: 10px;
 flex-direction: column;
 justify-content: center;
 gap: 5px;
 -webkit-tap-highlight-color: transparent;
}
.nav-toggle span {
 display: block;
 height: 2px;
 background: var(--navy);
 border-radius: 2px;
 transition: transform .2s, opacity .2s;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 720px) {
.nav-toggle { display: flex; }
.nav {
 display: none;
 position: absolute;
 top: 64px;
 left: 0;
 right: 0;
 flex-direction: column;
 align-items: stretch;
 gap: 0;
 background: #fff;
 border-bottom: 1px solid var(--blue-100);
 box-shadow: 0 12px 28px rgba(11,37,69,.1);
 padding: 8px 0 12px;
 z-index: 60;
 }
.nav.open { display: flex; }
.nav a {
 padding: 14px 20px;
 font-size: 16px;
 border-bottom: 1px solid #f0f4fa;
 }
.nav a:last-child { border-bottom: none; }
.site-header .wrap { position: relative; }
}

/* Hero */
.hero {
 position: relative;
 padding: 56px 0 48px;
 background: radial-gradient(1100px 460px at 50% -140px, #fecaca 0%, rgba(255,228,230,0) 70%),
 linear-gradient(180deg, var(--blue-050) 0%, var(--white) 100%);
 overflow: hidden;
}
.hero::before {
 content: '';
 position: absolute;
 inset: 0;
 background-image: radial-gradient(var(--blue-200) 1px, transparent 1px);
 background-size: 26px 26px;
 opacity: 0.32;
 mask-image: linear-gradient(180deg, rgba(0,0,0,.7), transparent 62%);
 pointer-events: none;
}
.hero .wrap { position: relative; }
.hero h1 {
 margin: 0 auto 14px;
 max-width: 860px;
 text-align: center;
 font-size: clamp(28px, 5vw, 46px);
 line-height: 1.15;
 font-weight: 800;
 letter-spacing: -1.1px;
}
.hero h1 em {
 font-style: normal;
 color: var(--blue-600);
}
.hero-lead {
 text-align: center;
 max-width: 640px;
 margin: 0 auto 36px;
 color: var(--muted);
 font-size: 18px;
 line-height: 1.55;
}

/* Converter */
.converter {
 max-width: 680px;
 margin: 0 auto;
 background: var(--white);
 border-radius: var(--radius-lg);
 box-shadow: var(--shadow-lg);
 border: 1px solid var(--blue-100);
 overflow: hidden;
}
.dropzone {
 padding: 48px 28px 40px;
 text-align: center;
 cursor: pointer;
 transition: background 0.2s;
 border: 2px dashed var(--blue-200);
 border-radius: var(--radius-lg);
 margin: 12px;
 background: var(--blue-025);
}
.dropzone:hover, .dropzone.dragover {
 background: var(--blue-050);
 border-color: var(--blue-500);
}
.dropzone-icon {
 width: 64px;
 height: 64px;
 margin: 0 auto 18px;
 border-radius: 18px;
 background: linear-gradient(135deg, var(--blue-600), var(--blue-500));
 display: grid;
 place-items: center;
 color: white;
}
.dropzone h2 {
 margin: 0 0 8px;
 font-size: 20px;
 font-weight: 700;
}
.dropzone p {
 margin: 0 0 20px;
 color: var(--muted);
 font-size: 15px;
}
.btn {
 display: inline-flex;
 align-items: center;
 justify-content: center;
 gap: 8px;
 font-family: inherit;
 font-weight: 700;
 font-size: 16px;
 border: none;
 border-radius: 12px;
 cursor: pointer;
 transition: transform 0.15s, box-shadow 0.15s, background 0.15s;
}
.btn:active { transform: scale(0.98); }
.btn-primary {
 background: var(--blue-600);
 color: white;
 padding: 14px 28px;
 box-shadow: 0 4px 14px rgba(227,28,35,0.35);
}
.btn-primary:hover {
 background: var(--blue-700);
 box-shadow: 0 6px 20px rgba(227,28,35,0.4);
}
.btn-secondary {
 background: var(--blue-050);
 color: var(--blue-700);
 padding: 12px 20px;
 border: 1px solid var(--blue-100);
}
.btn-secondary:hover { background: var(--blue-100); }
.btn-lg { padding: 16px 32px; font-size: 17px; }
.btn:disabled {
 opacity: 0.55;
 cursor: not-allowed;
 transform: none;
}

/* After upload */
.file-panel {
 display: none;
 padding: 20px 22px 24px;
}
.file-panel.visible { display: block; }
.file-row {
 display: flex;
 align-items: center;
 gap: 14px;
 padding: 14px 16px;
 background: var(--blue-025);
 border-radius: 14px;
 border: 1px solid var(--blue-100);
 margin-bottom: 20px;
}
.file-icon {
 width: 48px;
 height: 48px;
 border-radius: 12px;
 background: #e74c3c;
 color: white;
 display: grid;
 place-items: center;
 font-weight: 800;
 font-size: 13px;
 flex-shrink: 0;
}
.file-info { flex: 1; min-width: 0; }
.file-name {
 font-weight: 700;
 font-size: 15px;
 white-space: nowrap;
 overflow: hidden;
 text-overflow: ellipsis;
}
.file-meta { font-size: 13px; color: var(--muted); margin-top: 2px; }
.btn-x {
 width: 36px;
 height: 36px;
 border-radius: 10px;
 border: none;
 background: transparent;
 color: var(--muted);
 cursor: pointer;
 font-size: 20px;
 line-height: 1;
}
.btn-x:hover { background: var(--blue-050); color: var(--navy); }

.format-label {
 font-size: 14px;
 font-weight: 700;
 color: var(--muted-2);
 margin-bottom: 10px;
 text-transform: uppercase;
 letter-spacing: 0.4px;
}
.format-grid {
 display: grid;
 grid-template-columns: repeat(5, 1fr);
 gap: 10px;
 margin-bottom: 22px;
}
@media (max-width: 560px) {
.format-grid { grid-template-columns: repeat(3, 1fr); }
}
.format-btn {
 display: flex;
 flex-direction: column;
 align-items: center;
 gap: 6px;
 padding: 14px 8px;
 border-radius: 12px;
 border: 2px solid var(--blue-100);
 background: var(--white);
 cursor: pointer;
 font-family: inherit;
 font-weight: 700;
 font-size: 13px;
 color: var(--navy);
 transition: border-color 0.15s, background 0.15s, transform 0.15s;
}
.format-btn:hover {
 border-color: var(--blue-300);
 background: var(--blue-025);
}
.format-btn.active {
 border-color: var(--blue-600);
 background: var(--blue-050);
 color: var(--blue-700);
 box-shadow: 0 0 0 1px var(--blue-600);
}
.format-btn span.ext {
 font-size: 11px;
 font-weight: 600;
 color: var(--muted);
 text-transform: uppercase;
}
.format-btn.active span.ext { color: var(--blue-600); }

.progress-wrap {
 display: none;
 margin: 16px 0;
}
.progress-wrap.visible { display: block; }
.progress-bar {
 height: 8px;
 background: var(--blue-100);
 border-radius: 99px;
 overflow: hidden;
}
.progress-fill {
 height: 100%;
 width: 0%;
 background: linear-gradient(90deg, var(--blue-600), #f87171);
 border-radius: 99px;
 transition: width 0.3s ease;
}
.progress-text {
 font-size: 13.5px;
 color: var(--muted);
 margin-top: 8px;
 text-align: center;
}

.done-bar {
 display: none;
 flex-wrap: wrap;
 align-items: center;
 justify-content: space-between;
 gap: 14px;
 margin-top: 8px;
 padding: 18px 20px;
 border-radius: 16px;
 background: linear-gradient(135deg, #fef2f2, #fecaca);
 border: 1px solid #fecdd3;
}
.done-bar.visible { display: flex; }
.done-bar p { margin: 0; font-weight: 700; font-size: 15.5px; }
.done-bar small {
 display: block;
 font-weight: 600;
 color: var(--muted);
 font-size: 13.5px;
 margin-top: 2px;
}
.done-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.notice {
 margin: 12px 0 0;
 padding: 12px 16px;
 border-radius: 12px;
 font-size: 14px;
 background: var(--amber-bg);
 color: var(--amber);
 border-left: 4px solid #e0a800;
}
.notice.info {
 background: var(--blue-050);
 color: var(--blue-700);
 border-left-color: var(--blue-600);
}
.notice.error {
 background: var(--error-bg, #fdecec);
 color: var(--error, #c62828);
 border-left-color: var(--error, #c62828);
}

/* Sections */
.section { padding: 72px 0; background: var(--white); }
.section.alt {
 background: var(--white);
}
.section h2 {
 font-size: clamp(25px, 3.6vw, 34px);
 line-height: 1.2;
 letter-spacing: -0.7px;
 font-weight: 800;
 margin: 0 0 12px;
}
.section h3 {
 font-size: 20px;
 font-weight: 700;
 margin: 28px 0 10px;
}
.section p { margin: 0 0 16px; color: var(--navy); }
.section .lead {
 font-size: 18px;
 color: var(--muted);
 margin-bottom: 28px;
 max-width: 640px;
}

.steps {
 display: grid;
 grid-template-columns: repeat(3, 1fr);
 gap: 20px;
 margin-top: 32px;
}
@media (max-width: 700px) {
.steps { grid-template-columns: 1fr; }
}
.step {
 background: var(--white);
 border: 1px solid var(--blue-100);
 border-radius: var(--radius);
 padding: 24px 22px;
 box-shadow: var(--shadow-sm);
}
.step-num {
 width: 36px;
 height: 36px;
 border-radius: 10px;
 background: var(--blue-600);
 color: white;
 font-weight: 800;
 display: grid;
 place-items: center;
 margin-bottom: 14px;
 font-size: 16px;
}
.step h3 { margin: 0 0 8px; font-size: 17px; }
.step p { margin: 0; font-size: 15px; color: var(--muted); }

.feature {
 transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.feature:hover {
 transform: translateY(-4px);
 box-shadow: 0 14px 32px rgba(227,28,35,.12);
 border-color: #fecdd3;
}
.features {
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 gap: 16px;
 margin-top: 28px;
}
@media (max-width: 600px) {
.features { grid-template-columns: 1fr; }
}
.feature {
 display: flex;
 gap: 14px;
 padding: 18px;
 background: var(--white);
 border-radius: 14px;
 border: 1px solid var(--blue-100);
 transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.feature:hover {
 transform: translateY(-4px);
 box-shadow: 0 14px 32px rgba(227,28,35,.12);
 border-color: #fecaca;
}
.feature-icon {
 width: 40px;
 height: 40px;
 border-radius: 10px;
 background: var(--blue-050);
 color: var(--blue-600);
 display: grid;
 place-items: center;
 flex-shrink: 0;
}
.feature h3 { margin: 0 0 4px; font-size: 16px; font-weight: 700; }
.feature p { margin: 0; font-size: 14.5px; color: var(--muted); }

.table-wrap {
 max-width: 100%;
 overflow-x: auto;
 overflow-x: auto;
 margin: 24px 0;
 border-radius: 14px;
 border: 1px solid var(--blue-100);
}
table {
 width: 100%;
 border-collapse: collapse;
 font-size: 15px;
}
th, td {
 padding: 12px 16px;
 text-align: left;
 border-bottom: 1px solid var(--blue-100);
}
th {
 background: var(--blue-050);
 font-weight: 700;
 color: var(--navy);
}
tr:last-child td { border-bottom: none; }
td { color: var(--muted-2); }
td:first-child { color: var(--navy); font-weight: 600; }

.faq-item {
 border-bottom: 1px solid var(--blue-100);
 padding: 18px 0;
}
.faq-item:last-child { border-bottom: none; }
.faq-q {
 font-weight: 700;
 font-size: 16.5px;
 margin: 0 0 8px;
 cursor: pointer;
 display: flex;
 justify-content: space-between;
 align-items: center;
 gap: 12px;
}
.faq-q::after {
 content: '+';
 font-size: 22px;
 color: var(--blue-600);
 font-weight: 400;
 transition: transform 0.2s;
}
.faq-item.open .faq-q::after { content: '−'; }
.faq-a {
 display: none;
 color: var(--muted);
 font-size: 15.5px;
 line-height: 1.6;
 padding-bottom: 4px;
}
.faq-item.open .faq-a { display: block; }

.cta-final {
 padding: 48px 20px 72px;
 background: var(--white);
}
.cta-card {
 max-width: 640px;
 margin: 0 auto;
 text-align: center;
 padding: 48px 36px 44px;
 border-radius: 28px;
 background: linear-gradient(160deg, #E31C23 0%, #be123c 55%, #9f1239 100%);
 color: white;
 box-shadow: 0 24px 60px rgba(159,18,57,.28), 0 8px 24px rgba(227,28,35,.2);
}
.cta-card h2 {
 margin: 0 0 12px;
 font-size: clamp(26px, 4vw, 34px);
 font-weight: 800;
 letter-spacing: -0.6px;
 color: white;
}
.cta-card p {
 margin: 0 0 28px;
 font-size: 17px;
 line-height: 1.5;
 opacity: 0.92;
 color: white;
}
.cta-card .btn {
 background: white;
 color: var(--blue-700);
 padding: 15px 32px;
 font-size: 16.5px;
 border-radius: 999px;
 box-shadow: 0 4px 16px rgba(0,0,0,.12);
}
.cta-card {
 transition: transform .35s ease, box-shadow .35s ease;
}
.cta-card:hover {
 transform: translateY(-6px);
 box-shadow: 0 28px 64px rgba(227,28,35,.32), 0 12px 28px rgba(159,18,57,.2);
}
.cta-card .btn {
 transition: transform .2s ease, box-shadow .2s ease;
}
.cta-card:hover .btn {
 transform: scale(1.04);
}
.cta-card .btn:hover {
 background: #fef2f2;
 color: var(--blue-900);
}

/* Footer */
.site-footer {
 background: #0b2545;
 color: #c5d4e8;
 padding: 0;
 font-size: 14.5px;
}
.footer-main {
 padding: 48px 0 36px;
}
.footer-grid {
 display: grid;
 grid-template-columns: 1.5fr 1fr 1fr 1.2fr;
 gap: 32px;
}
@media (max-width: 900px) {
.footer-grid {
 grid-template-columns: 1fr 1fr;
 gap: 28px;
 }
}
@media (max-width: 560px) {
.footer-grid {
 grid-template-columns: 1fr;
 gap: 28px;
 }
}
.footer-brand {
 display: flex;
 flex-direction: column;
 gap: 14px;
}
.footer-logo {
 display: flex;
 align-items: center;
 gap: 10px;
 text-decoration: none;
 color: white;
}
.footer-logo:hover { text-decoration: none; }
.footer-logo-icon {
 width: 36px;
 height: 36px;
 border-radius: 10px;
 background: #E31C23;
 display: grid;
 place-items: center;
 color: white;
 font-weight: 800;
 font-size: 16px;
 flex-shrink: 0;
}
.footer-logo-text {
 font-size: 20px;
 font-weight: 800;
 letter-spacing: -0.5px;
 color: white;
}
.footer-logo-text span { color: #E31C23; }
.footer-desc {
 margin: 0;
 line-height: 1.55;
 max-width: 280px;
 color: #b6c7dc;
 font-size: 14px;
}
.footer-col h4, .footer-col-title {
 margin: 0 0 16px;
 font-size: 12px;
 font-weight: 700;
 letter-spacing: 0.8px;
 text-transform: uppercase;
 color: #f87171;
}
.footer-col ul {
 list-style: none;
 margin: 0;
 padding: 0;
}
.footer-col li { margin-bottom: 10px; }
.footer-col a {
 color: #c5d4e8;
 text-decoration: none;
 font-size: 14.5px;
 font-weight: 600;
 transition: color 0.15s;
}
.footer-col a:hover {
 color: white;
 text-decoration: none;
}
.footer-bottom {
 border-top: 1px solid rgba(255,255,255,0.08);
 padding: 18px 0;
 display: flex;
 flex-wrap: wrap;
 justify-content: space-between;
 gap: 10px;
 font-size: 13px;
 color: #b6c7dc;
}
.footer-bottom a {
 color: #9eb0c7;
 text-decoration: none;
}
.footer-bottom a:hover { color: #c5d4e8; }


/* ========== Mobile / tablet ========== */
html { -webkit-text-size-adjust: 100%; }
body { overflow-x: hidden; }
img, svg, video, canvas { max-width: 100%; height: auto; }
button, a, .format-btn, .btn { -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
input, select, textarea { font-size: 16px; } /* prevent iOS zoom on focus */


@media (max-width: 900px) {
.footer-grid { grid-template-columns: 1fr 1fr; gap: 28px; }
.feature {
 transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.feature:hover {
 transform: translateY(-4px);
 box-shadow: 0 14px 32px rgba(227,28,35,.12);
 border-color: #fecdd3;
}
.features { grid-template-columns: 1fr 1fr !important; }
.steps { grid-template-columns: 1fr !important; }
}
@media (max-width: 720px) {
.wrap { padding: 0 16px; }
.wordmark { font-size: 18px; }
.brand-icon { width: 32px; height: 32px; font-size: 15px; border-radius: 9px; }
.hero { padding: 36px 0 28px; }
.hero h1 { font-size: clamp(24px, 7vw, 34px); letter-spacing: -0.6px; }
.hero-lead { font-size: 16px; margin-bottom: 28px; }
.dropzone { padding: 36px 18px 32px; }
.dropzone h2 { font-size: 18px; }
.dropzone p { font-size: 14px; }
.btn-lg { width: 100%; padding: 15px 20px; font-size: 16px; }
.file-panel { padding: 16px 14px 20px; }
.file-row { padding: 12px; gap: 10px; }
.file-icon { width: 42px; height: 42px; font-size: 12px; }
.format-grid { grid-template-columns: repeat(3, 1fr); gap: 8px; }
.format-btn { padding: 12px 6px; font-size: 12px; min-height: 64px; }
.done-bar { flex-direction: column; align-items: stretch; text-align: center; }
.done-actions { justify-content: center; width: 100%; }
.done-actions .btn { flex: 1; min-width: 0; justify-content: center; }
.section { padding: 48px 0; }
.section h2 { font-size: 1.45rem; }
.cta-card { padding: 28px 18px; }
.cta-card h2 { font-size: 1.35rem; }
.footer-main { padding: 40px 0 28px; }
.footer-bottom .wrap { flex-direction: column; text-align: center; gap: 6px; }
.faq-item { padding: 14px 0; }
 table { font-size: 13px; }
 th, td { padding: 10px 12px; }
}
@media (max-width: 480px) {
.format-grid { grid-template-columns: repeat(2, 1fr); }
.feature {
 transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}
.feature:hover {
 transform: translateY(-4px);
 box-shadow: 0 14px 32px rgba(227,28,35,.12);
 border-color: #fecdd3;
}
.features { grid-template-columns: 1fr !important; }
.footer-grid { grid-template-columns: 1fr; gap: 24px; }
.hero h1 br { display: none; }
.btn, .btn-lg { min-height: 48px; }
.format-btn { min-height: 72px; }
}

/* Safe area for notched phones */
@supports (padding: max(0px)) {
.site-header .wrap,
.wrap {
 padding-left: max(16px, env(safe-area-inset-left));
 padding-right: max(16px, env(safe-area-inset-right));
 }
.site-footer { padding-bottom: max(28px, env(safe-area-inset-bottom)); }
}


.stat-grid {
 display: grid;
 grid-template-columns: repeat(3, 1fr);
 gap: 14px;
 margin: 28px 0 8px;
}
@media (max-width: 600px) {
.stat-grid { grid-template-columns: 1fr; }
}
.stat-card {
 text-align: center;
 padding: 22px 16px;
 border-radius: 16px;
 background: linear-gradient(160deg, #fef2f2, #fff);
 border: 1px solid #fecdd3;
 transition: transform .25s ease, box-shadow .25s ease;
}
.stat-card:hover {
 transform: translateY(-3px);
 box-shadow: 0 10px 24px rgba(227,28,35,.12);
}
.stat-card .num {
 font-size: 1.85rem;
 font-weight: 800;
 color: #E31C23;
 letter-spacing: -1px;
 line-height: 1.1;
}
.stat-card .lbl {
 font-size: 13.5px;
 color: var(--muted);
 margin-top: 6px;
 font-weight: 600;
}
.hidden { display: none !important; }
</style>
<script src="https://analytics.ahrefs.com/analytics.js" data-key="eW/OZjKg9pXCRq1k4/aZ2g" async></script>
</head>
<body>

<header class="site-header">
 <div class="wrap">
 <a href="/" class="brand">
 <div class="brand-icon">P</div>
 <div class="wordmark">pdf<span>converter</span>.pl</div>
 </a>
 <button type="button" class="nav-toggle" id="nav-toggle" aria-label="Menu" aria-expanded="false" aria-controls="main-nav">
 <span></span><span></span><span></span>
 </button>
 <nav class="nav" id="main-nav">
 <a href="/">Konwerter PDF</a>
 <a href="/blog/">Blog</a>
 </nav>
 </div>
</header>

<main>
 <section class="hero">
 <div class="wrap">
 <h1>Darmowy konwerter <em>PDF na JPG</em>, PNG, Word, Excel i PowerPoint</h1>
 <p class="hero-lead">Wrzuć plik PDF, wybierz format docelowy i pobierz wynik w kilka sekund. Bez rejestracji, bez znaku wodnego. Szybko i za darmo.</p>

 <div class="converter" id="converter">
 <div class="dropzone" id="dropzone">
 <div class="dropzone-icon">
 <svg width="28" height="28" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24"><path d="M12 16V4m0 0l-4 4m4-4l4 4"/><path d="M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2"/></svg>
 </div>
 <h2>Przeciągnij plik PDF tutaj</h2>
 <p>lub kliknij, aby wybrać plik z dysku<br><small>Maksymalnie 25 MB · tylko PDF</small></p>
 <button type="button" class="btn btn-primary btn-lg" id="btn-choose">Wybierz plik PDF</button>
 <input type="file" id="file-input" accept=".pdf,application/pdf" class="hidden">
 </div>

 <div class="file-panel" id="file-panel">
 <div class="file-row">
 <div class="file-icon">PDF</div>
 <div class="file-info">
 <div class="file-name" id="file-name">dokument.pdf</div>
 <div class="file-meta" id="file-meta">0 KB</div>
 </div>
 <button type="button" class="btn-x" id="btn-remove" title="Usuń plik">×</button>
 </div>

 <div class="format-label">Wybierz format docelowy</div>
 <div class="format-grid" id="format-grid">
 <button type="button" class="format-btn active" data-format="jpg"><strong>JPG</strong><span class="ext">obraz</span></button>
 <button type="button" class="format-btn" data-format="png"><strong>PNG</strong><span class="ext">obraz</span></button>
 <button type="button" class="format-btn" data-format="docx"><strong>Word</strong><span class="ext">docx</span></button>
 <button type="button" class="format-btn" data-format="xlsx"><strong>Excel</strong><span class="ext">xlsx</span></button>
 <button type="button" class="format-btn" data-format="pptx"><strong>PowerPoint</strong><span class="ext">pptx</span></button>
 </div>

 <button type="button" class="btn btn-primary btn-lg" id="btn-convert" style="width:100%">Konwertuj teraz</button>

 <div class="progress-wrap" id="progress-wrap">
 <div class="progress-bar"><div class="progress-fill" id="progress-fill"></div></div>
 <div class="progress-text" id="progress-text">Przygotowuję konwersję…</div>
 </div>

 <div class="done-bar" id="done-bar">
 <div>
 <p>Gotowe!</p>
 <small id="done-info">Twój plik jest gotowy do pobrania</small>
 </div>
 <div class="done-actions">
 <button type="button" class="btn btn-primary" id="btn-download">Pobierz plik</button>
 <button type="button" class="btn btn-secondary" id="btn-again">Konwertuj kolejny</button>
 </div>
 </div>

 <div class="notice info" id="format-notice" style="display:none"></div>
 </div>
 </div>
 </div>
 </section>

 <!-- Jak to działa -->
 <section class="section" id="jak-to-dziala">
 <div class="wrap">
 <h2>Jak przekonwertować PDF - trzy proste kroki</h2>
 <p class="lead">Konwersja PDF online jeszcze nigdy nie była tak prosta. Nie instalujesz żadnego programu i nie zakładasz konta.</p>
 <div class="steps">
 <div class="step">
 <div class="step-num">1</div>
 <h3>Wrzuć plik PDF</h3>
 <p>Przeciągnij dokument na strefę lub kliknij „Wybierz plik PDF”. Obsługujemy pliki do 25 MB.</p>
 </div>
 <div class="step">
 <div class="step-num">2</div>
 <h3>Wybierz format</h3>
 <p>Wskaż, na co chcesz zamienić PDF: JPG, PNG, Word (DOCX), Excel (XLSX) lub PowerPoint (PPTX).</p>
 </div>
 <div class="step">
 <div class="step-num">3</div>
 <h3>Pobierz wynik</h3>
 <p>Kliknij „Konwertuj teraz”. Po kilku sekundach pobierzesz gotowy plik na swój komputer.</p>
 </div>
 </div>
 </div>
 </section>

 <!-- Dlaczego my -->
 <section class="section alt" id="dlaczego">
 <div class="wrap">
 <h2>Dlaczego warto korzystać z pdfconverter.pl</h2>
 <p class="lead">Jeden cel: szybka, bezpieczna i darmowa konwersja PDF na najpopularniejsze formaty. Bez zbędnych rozpraszaczy.</p>
 <div class="stat-grid">
 <div class="stat-card"><div class="num">5</div><div class="lbl">formatów z jednego PDF<br>JPG · PNG · Word · Excel · PPT</div></div>
 <div class="stat-card"><div class="num">25 MB</div><div class="lbl">maksymalny rozmiar<br>jednego pliku PDF</div></div>
 <div class="stat-card"><div class="num">0 zł</div><div class="lbl">bez konta, bez limitu<br>i bez znaku wodnego</div></div>
 </div>

 <div class="features">
 <div class="feature">
 <div class="feature-icon">
 <svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
 </div>
 <div>
 <h3>Bezpieczne przetwarzanie</h3>
 <p>Dokumenty trafiają pod losowy, nieodgadywalny adres. Nie oglądamy ich, nie udostępniamy dalej i nie używamy do trenowania AI.</p>
 </div>
 </div>
 <div class="feature">
 <div class="feature-icon">
 <svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
 </div>
 <div>
 <h3>Szybko i bez limitów dziennych</h3>
 <p>Brak sztucznych limitów liczby konwersji. Przetwarzasz tyle plików, ile potrzebujesz.</p>
 </div>
 </div>
 <div class="feature">
 <div class="feature-icon">
 <svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M20 6L9 17l-5-5"/></svg>
 </div>
 <div>
 <h3>Bez rejestracji i znaków wodnych</h3>
 <p>Nie musisz zakładać konta. Wynikowy plik nie zawiera żadnych znaków wodnych ani reklam.</p>
 </div>
 </div>
 <div class="feature">
 <div class="feature-icon">
 <svg width="20" height="20" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18M9 21V9"/></svg>
 </div>
 <div>
 <h3>Wszystkie popularne formaty</h3>
 <p>PDF na JPG, PNG, Word, Excel i PowerPoint - w jednym miejscu, bez skakania między narzędziami.</p>
 </div>
 </div>
 </div>
 </div>
 </section>

 <!-- Co to PDF -->
 <section class="section">
 <div class="wrap narrow">
 <h2>Czym jest format PDF i dlaczego go konwertujemy?</h2>
 <p>PDF (Portable Document Format) to uniwersalny format dokumentów stworzony przez Adobe. Zachowuje wygląd strony niezależnie od urządzenia i systemu operacyjnego. Dlatego PDF idealnie nadaje się do umów, faktur, raportów i materiałów do druku.</p>
 <p>Problem pojawia się, gdy chcesz <strong>edytować treść</strong>, wyciągnąć tabele do arkusza kalkulacyjnego albo użyć stron jako obrazów. Wtedy potrzebujesz konwersji PDF na inny format:</p>
 <ul>
 <li><strong>PDF na Word (DOCX)</strong> - gdy chcesz poprawić tekst, zmienić akapity lub dodać komentarze.</li>
 <li><strong>PDF na Excel (XLSX)</strong> - gdy w dokumencie są tabele, które chcesz sortować, filtrować lub liczyć.</li>
 <li><strong>PDF na PowerPoint (PPTX)</strong> - gdy strony PDF mają stać się slajdami prezentacji.</li>
 <li><strong>PDF na JPG / PNG</strong> - gdy potrzebujesz obrazów stron do wstawienia na stronę WWW, do mediów społecznościowych lub do wydruku zdjęć.</li>
 </ul>
 <p>Nasz darmowy konwerter PDF online rozwiązuje te potrzeby w kilka kliknięć - bez instalowania programów typu Adobe Acrobat czy Microsoft Office.</p>
 </div>
 </section>

 <!-- PDF na JPG/PNG -->
 <section class="section alt">
 <div class="wrap narrow">
 <h2>PDF na JPG i PDF na PNG - kiedy wybrać który format?</h2>
 <p>Oba formaty obrazów są popularne, ale służą do trochę innych celów.</p>
 <h3>PDF na JPG</h3>
 <p>JPG (JPEG) to format stratny, który świetnie kompresuje zdjęcia i strony z dużą ilością kolorów. Pliki JPG są zwykle mniejsze, dlatego chętnie używa się ich na stronach internetowych i w mailach. Konwersja <strong>PDF na JPG</strong> jest idealna, gdy chcesz szybko dostać podgląd stron lub wstawić je jako grafiki.</p>
 <h3>PDF na PNG</h3>
 <p>PNG to format bezstratny. Zachowuje ostre krawędzie tekstu, logo i przezroczystość. Wybierz <strong>PDF na PNG</strong>, gdy zależy Ci na maksymalnej jakości i czytelności tekstu (np. skany dokumentów, wykresy, zrzuty ekranu).</p>
 <p>W naszym konwerterze możesz wybrać zarówno JPG, jak i PNG. Strony PDF renderowane są w wysokiej rozdzielczości, dzięki czemu wynikowy obraz zachowuje czytelność nawet przy powiększeniu.</p>
 </div>
 </section>

 <!-- PDF na Word -->
 <section class="section">
 <div class="wrap narrow">
 <h2>PDF na Word - edytuj dokumenty bez ograniczeń</h2>
 <p>Jedno z najczęstszych zapytań w wyszukiwarce to „pdf na word” lub „jak zamienić pdf na worda”. Ludzie potrzebują edytowalnej wersji umowy, CV, oferty czy raportu.</p>
 <p>Konwersja <strong>PDF na Word (DOCX)</strong> pozwala otworzyć dokument w Microsoft Word, Google Docs lub LibreOffice i swobodnie zmieniać treść, formatowanie oraz układ. Nasz konwerter wyodrębnia tekst ze stron PDF i przygotowuje plik DOCX gotowy do dalszej edycji.</p>
 <p>Warto pamiętać, że skomplikowane układy (wielokolumnowe, z tabelami i grafikami) mogą wymagać drobnych poprawek po konwersji - to normalne przy każdym narzędziu online. Dla prostych i średnio złożonych dokumentów wynik jest bardzo dobry.</p>
 </div>
 </section>

 <!-- PDF na Excel -->
 <section class="section alt">
 <div class="wrap narrow">
 <h2>PDF na Excel - wyciągnij tabele do arkusza</h2>
 <p>Gdy w PDF-ie znajdują się tabele (faktury, cenniki, raporty sprzedażowe), najlepszym celem jest format Excel. Konwersja <strong>PDF na Excel (XLSX)</strong> pozwala pracować na danych: sortować, filtrować, tworzyć wykresy i formuły.</p>
 <p>Narzędzie stara się rozpoznać strukturę tabel i przenieść je do arkusza. Im bardziej regularna tabela w oryginalnym PDF, tym lepszy efekt końcowy. Dla skanów i skomplikowanych układów zalecamy sprawdzenie wyniku i ewentualne poprawki.</p>
 </div>
 </section>

 <!-- PDF na PowerPoint -->
 <section class="section">
 <div class="wrap narrow">
 <h2>PDF na PowerPoint - zamień strony na slajdy</h2>
 <p>Czasem masz gotowy dokument PDF (np. raport, ofertę, materiały szkoleniowe) i chcesz go pokazać jako prezentację. Wtedy przydaje się konwersja <strong>PDF na PowerPoint (PPTX)</strong>.</p>
 <p>Każda strona PDF staje się osobnym slajdem. Możesz potem dodać animacje, notatki prelegenta lub zmienić kolejność. To wygodniejsze niż pokazywanie PDF-a na pełnym ekranie.</p>
 </div>
 </section>

 <!-- Porównanie -->
 <section class="section alt">
 <div class="wrap narrow">
 <h2>Szybkie porównanie formatów docelowych</h2>
 <p class="lead">Wybierz format w zależności od tego, co chcesz zrobić z dokumentem po konwersji. Poniżej krótkie porównanie - bez marketingowego bełkotu.</p>
 <p>JPG i PNG to obrazy stron (idealne do podglądu, maila, social mediów). Word i Excel służą do dalszej edycji treści i danych. PowerPoint zamienia strony na slajdy prezentacji. Żaden konwerter nie gwarantuje idealnego układu 1:1 przy bardzo skomplikowanych PDF-ach - przy prostych dokumentach wynik jest zwykle gotowy do użycia od razu.</p>
 <div class="table-wrap">
 <table>
 <thead>
 <tr>
 <th>Format</th>
 <th>Najlepszy do</th>
 <th>Edytowalność</th>
 <th>Rozmiar pliku</th>
 </tr>
 </thead>
 <tbody>
 <tr>
 <td>JPG</td>
 <td>Zdjęcia, podglądy stron, web</td>
 <td>Brak (obraz)</td>
 <td>Mały / średni</td>
 </tr>
 <tr>
 <td>PNG</td>
 <td>Tekst, wykresy, ostre krawędzie</td>
 <td>Brak (obraz)</td>
 <td>Średni / duży</td>
 </tr>
 <tr>
 <td>Word (DOCX)</td>
 <td>Edycja tekstu, poprawki, komentarze</td>
 <td>Pełna</td>
 <td>Mały</td>
 </tr>
 <tr>
 <td>Excel (XLSX)</td>
 <td>Tabele, dane, obliczenia</td>
 <td>Pełna (arkusz)</td>
 <td>Mały</td>
 </tr>
 <tr>
 <td>PowerPoint (PPTX)</td>
 <td>Prezentacje, slajdy</td>
 <td>Pełna (slajdy)</td>
 <td>Średni</td>
 </tr>
 </tbody>
 </table>
 </div>
 </div>
 </section>

 <!-- Bezpieczeństwo -->
 <section class="section">
 <div class="wrap narrow">
 <h2>Co dzieje się z Twoimi plikami?</h2>
 <p>Bezpieczeństwo i prywatność są dla nas priorytetem. Przesłany PDF trafia na serwer, zostaje przekonwertowany i zapisany pod <strong>losowym, trudnym do odgadnięcia adresem</strong> - jak w prywatnym sejfie, do którego klucz masz tylko Ty (link z wyniku).</p>
 <div class="stat-grid">
 <div class="stat-card"><div class="num">0</div><div class="lbl">podglądu przez nas<br>i zero sprzedaży danych</div></div>
 <div class="stat-card"><div class="num">🔒</div><div class="lbl">dane techniczne<br>w formie zaszyfrowanej</div></div>
 <div class="stat-card"><div class="num">🔒</div><div class="lbl">losowy adres<br>bez listowania katalogu</div></div>
 </div>
 <ul>
 <li>Nikt nie przegląda przesłanych dokumentów. Nie ma panelu podglądu ani moderacji treści.</li>
 <li>Nie udostępniamy plików osobom trzecim i nie używamy ich do trenowania modeli AI.</li>
 <li>Nie wymagamy rejestracji ani podania e-maila - nie budujemy bazy kont.</li>
 <li>Twojego adresu w internecie nie trzymamy w zwykłej, czytelnej formie - tylko w postaci zaszyfrowanej, na wypadek nadużyć.</li>
 <li>Pliki nie trafiają do wyników wyszukiwania Google - nikt obcy nie znajdzie ich wpisując adres w przeglądarce.</li>
 </ul>
 <p>Szczegóły znajdziesz w <a href="/polityka-prywatnosci/">polityce prywatności</a> i <a href="/regulamin/">regulaminie</a>.</p>
 </div>
 </section>

 <!-- FAQ -->
 <section class="section alt" id="faq">
 <div class="wrap narrow">
 <h2>Najczęściej zadawane pytania</h2>

 <div class="faq-item">
 <div class="faq-q">Czy konwersja PDF jest całkowicie darmowa?</div>
 <div class="faq-a">Tak. pdfconverter.pl jest darmowy. Nie ma ukrytych opłat, limitów dziennych ani wymogu założenia konta. Możesz konwertować tyle plików, ile potrzebujesz.</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Czy pliki są bezpieczne?</div>
 <div class="faq-a">Tak. Po wrzuceniu PDF trafia na serwer pod <strong>losowym, nieodgadywalnym adresem</strong>. Nikt go nie przegląda i nie udostępniamy go dalej. Nie wymagamy konta ani e-maila. Szczegóły: <a href="/polityka-prywatnosci/">polityka prywatności</a> i <a href="/regulamin/">regulamin</a>.</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Jakie formaty mogę uzyskać z PDF?</div>
 <div class="faq-a">Obecnie obsługujemy konwersję PDF na: JPG, PNG, Word (DOCX), Excel (XLSX) oraz PowerPoint (PPTX). To najpopularniejsze formaty, których szukają użytkownicy w Polsce.</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Czy konwersja PDF na Word zachowuje układ strony?</div>
 <div class="faq-a">Dla prostych dokumentów tekstowych układ jest zachowany bardzo dobrze. Przy skomplikowanych layoutach (wiele kolumn, tabele, grafiki) mogą pojawić się drobne różnice - to normalne przy każdej konwersji PDF → DOCX.</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Czy mogę konwertować skany PDF (obrazy)?</div>
 <div class="faq-a">Tak, w przypadku JPG i PNG - strony skanów zostaną wiernie oddane jako obrazy. Przy konwersji na Word/Excel/PowerPoint tekst ze skanów nie jest rozpoznawany przez OCR (obecnie konwerter działa na warstwie tekstowej PDF).</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Jaki jest limit wielkości pliku?</div>
 <div class="faq-a">Maksymalny rozmiar to 25 MB. Dla większości dokumentów biurowych i skanów to w zupełności wystarcza.</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Czy działa na telefonie i tablecie?</div>
 <div class="faq-a">Tak. Strona jest w pełni responsywna. Możesz wrzucić PDF z galerii lub menedżera plików na Androidzie i iOS.</div>
 </div>
 <div class="faq-item">
 <div class="faq-q">Czym różni się pdfconverter.pl od iLovePDF i FreePDFConvert?</div>
 <div class="faq-a">Skupiamy się wyłącznie na konwersji PDF → inne formaty, interfejs jest prostszy i szybszy. Nie musisz zakładać konta ani oglądać agresywnych reklam premium.</div>
 </div>
 </div>
 </section>

 <!-- Final CTA -->
 <section class="cta-final">
 <div class="wrap">
 <div class="cta-card">
 <h2>Gotowy? To zajmie chwilę</h2>
 <p>Wrzuć plik PDF, wybierz format i pobierz wynik.<br>Bez konta, bez opłat, bez znaku wodnego.</p>
 <a href="#converter" class="btn">Konwertuj PDF teraz</a>
 </div>
 </div>
 </section>
</main>

<footer class="site-footer">
 <div class="footer-main">
 <div class="wrap">
 <div class="footer-grid">
 <div class="footer-brand">
 <a href="/" class="footer-logo">
 <div class="footer-logo-icon">P</div>
 <div class="footer-logo-text">pdf<span>converter</span>.pl</div>
 </a>
 <p class="footer-desc">Darmowy konwerter PDF online. Zamień PDF na JPG, PNG, Word, Excel lub PowerPoint. Jedno narzędzie, zero zbędnych kroków.</p>
 </div>
 <div class="footer-col">
 <div class="footer-col-title">Na stronie</div>
 <ul>
 <li><a href="#jak-to-dziala">Jak to działa</a></li>
 <li><a href="#dlaczego">Dlaczego my</a></li>
 <li><a href="/blog/">Blog</a></li>
 <li><a href="#faq">FAQ</a></li>
 <li><a href="#converter">Konwerter PDF</a></li>
 </ul>
 </div>
 <div class="footer-col">
 <div class="footer-col-title">Serwis</div>
 <ul>
 <li><a href="/o-nas/">O nas</a></li>
 <li><a href="/regulamin/">Regulamin</a></li>
 <li><a href="/polityka-prywatnosci/">Polityka prywatności</a></li>
 <li><a href="/polityka-cookies/">Polityka cookies</a></li>
 <li><a href="mailto:kontakt@pdfconverter.pl">Kontakt</a></li>
 </ul>
 </div>
 <div class="footer-col">
 <div class="footer-col-title">Przydatne narzędzia</div>
 <ul>
 <li><a href="https://heicnajpg.pl/" target="_blank" rel="noopener">HEICnaJPG.pl - zamiana HEIC na JPG online</a></li>
 <li><a href="https://usuwanietla.pl/" target="_blank" rel="noopener">UsuwanieTla.pl - usuń tło ze swojego zdjęcia</a></li>
 </ul>
 </div>
 </div>
 </div>
 </div>
 <div class="footer-bottom">
 <div class="wrap" style="display:flex;flex-wrap:wrap;justify-content:space-between;gap:10px;width:100%;">
 <span>© 2026 pdfconverter.pl. Wszystkie prawa zastrzeżone.</span>
 <span>Pliki usuwamy automatycznie po 30 dniach.</span>
 </div>
 </div>
</footer>

<script>

(function () {

 // Lazy-load heavy libs only when user picks a PDF (nie blokują pierwszego renderu)
 let libsPromise = null;
 function loadConverterLibs() {
 if (libsPromise) return libsPromise;
 libsPromise = new Promise(function (resolve, reject) {
 function loadScript(src) {
 return new Promise(function (res, rej) {
 var s = document.createElement('script');
 s.src = src;
 s.async = true;
 s.onload = res;
 s.onerror = function () { rej(new Error('Nie udało się załadować: ' + src)); };
 document.head.appendChild(s);
 });
 }
 loadScript('https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js')
 .then(function () {
 return loadScript('https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js');
 })
 .then(function () {
 if (window.pdfjsLib) {
 pdfjsLib.GlobalWorkerOptions.workerSrc =
 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
 }
 resolve();
 })
 .catch(reject);
 });
 return libsPromise;
 }

 const dropzone = document.getElementById('dropzone');
 const fileInput = document.getElementById('file-input');
 const btnChoose = document.getElementById('btn-choose');
 const filePanel = document.getElementById('file-panel');
 const fileNameEl = document.getElementById('file-name');
 const fileMetaEl = document.getElementById('file-meta');
 const btnRemove = document.getElementById('btn-remove');
 const formatGrid = document.getElementById('format-grid');
 const btnConvert = document.getElementById('btn-convert');
 const progressWrap = document.getElementById('progress-wrap');
 const progressFill = document.getElementById('progress-fill');
 const progressText = document.getElementById('progress-text');
 const doneBar = document.getElementById('done-bar');
 const doneInfo = document.getElementById('done-info');
 const btnDownload = document.getElementById('btn-download');
 const btnAgain = document.getElementById('btn-again');
 const formatNotice = document.getElementById('format-notice');

 let currentFile = null;
 let serverToken = null;
 let selectedFormat = 'jpg';
 let downloadBlob = null;
 let downloadName = '';

 // Format buttons
 formatGrid.querySelectorAll('.format-btn').forEach(btn => {
 btn.addEventListener('click', () => {
 formatGrid.querySelectorAll('.format-btn').forEach(b => b.classList.remove('active'));
 btn.classList.add('active');
 selectedFormat = btn.dataset.format;
 formatNotice.style.display = 'none';
 doneBar.classList.remove('visible');
 progressWrap.classList.remove('visible');
 });
 });

 // File selection
 btnChoose.addEventListener('click', (e) => {
 e.stopPropagation();
 fileInput.click();
 });
 dropzone.addEventListener('click', () => fileInput.click());

 dropzone.addEventListener('dragover', (e) => {
 e.preventDefault();
 dropzone.classList.add('dragover');
 });
 dropzone.addEventListener('dragleave', () => dropzone.classList.remove('dragover'));
 dropzone.addEventListener('drop', (e) => {
 e.preventDefault();
 dropzone.classList.remove('dragover');
 const files = e.dataTransfer.files;
 if (files.length) handleFile(files[0]);
 });

 fileInput.addEventListener('change', () => {
 if (fileInput.files.length) handleFile(fileInput.files[0]);
 });

 function handleFile(file) {
 if (file.type !== 'application/pdf' && !file.name.toLowerCase().endsWith('.pdf')) {
 alert('Proszę wybrać plik PDF.');
 return;
 }
 if (file.size > 25 * 1024 * 1024) {
 alert('Plik jest za duży. Maksymalny rozmiar to 25 MB.');
 return;
 }
 // Start loading pdf.js + JSZip in background as soon as file is chosen
 loadConverterLibs().catch(function (e) { console.warn(e); });
 currentFile = file;
 serverToken = null;
 fileNameEl.textContent = file.name;
 fileMetaEl.textContent = formatSize(file.size) + ' · zapisuję na serwerze…';
 dropzone.style.display = 'none';
 filePanel.classList.add('visible');
 doneBar.classList.remove('visible');
 progressWrap.classList.remove('visible');
 formatNotice.style.display = 'none';
 downloadBlob = null;

 // Zaraz po wrzuceniu PDF trafia do folderu files/ (przed konwersją)
 uploadOriginal(file).then(function (data) {
 if (data && data.token) {
 serverToken = data.token;
 fileMetaEl.textContent = formatSize(file.size) + ' · zapisano';
 } else {
 fileMetaEl.textContent = formatSize(file.size);
 }
 }).catch(function (e) {
 console.warn('Upload PDF:', e);
 fileMetaEl.textContent = formatSize(file.size) + ' · zapis lokalny (serwer niedostępny)';
 });
 }

 btnRemove.addEventListener('click', reset);

 function reset() {
 currentFile = null;
 serverToken = null;
 fileInput.value = '';
 dropzone.style.display = '';
 filePanel.classList.remove('visible');
 doneBar.classList.remove('visible');
 progressWrap.classList.remove('visible');
 formatNotice.style.display = 'none';
 downloadBlob = null;
 }

 btnAgain.addEventListener('click', reset);

 function formatSize(bytes) {
 if (bytes < 1024) return bytes + ' B';
 if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
 return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
 }

 async function uploadOriginal(file) {
 const fd = new FormData();
 fd.append('original', file, file.name);
 const res = await fetch('/api/save.php', { method: 'POST', body: fd });
 if (!res.ok) throw new Error('HTTP ' + res.status);
 const data = await res.json();
 if (!data.ok) throw new Error(data.error || 'upload failed');
 console.log('PDF zapisany w files/', data.token);
 return data;
 }

 async function saveResult(blob, filename) {
 const fd = new FormData();
 fd.append('result', blob, filename);
 if (serverToken) {
 fd.append('token', serverToken);
 } else if (currentFile) {
 fd.append('original', currentFile, currentFile.name);
 }
 const res = await fetch('/api/save.php', { method: 'POST', body: fd });
 if (!res.ok) throw new Error('HTTP ' + res.status);
 const data = await res.json();
 if (!data.ok) throw new Error(data.error || 'save failed');
 if (data.token) serverToken = data.token;
 console.log('Wynik zapisany w files/', data.token, data.download_url);
 return data;
 }



 function setProgress(pct, text) {
 progressFill.style.width = pct + '%';
 progressText.textContent = text || '';
 }

 btnConvert.addEventListener('click', async () => {
 if (!currentFile) return;
 btnConvert.disabled = true;
 progressWrap.classList.add('visible');
 doneBar.classList.remove('visible');
 formatNotice.style.display = 'none';
 setProgress(3, 'Ładuję silnik konwersji…');

 try {
 await loadConverterLibs();
 setProgress(8, 'Wczytuję dokument PDF…');
 const arrayBuffer = await currentFile.arrayBuffer();
 const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
 const numPages = pdf.numPages;
 setProgress(15, `Dokument ma ${numPages} stron. Konwertuję…`);

 if (selectedFormat === 'jpg' || selectedFormat === 'png') {
 await convertToImages(pdf, numPages, selectedFormat);
 } else if (selectedFormat === 'docx') {
 await convertToDocx(pdf, numPages);
 } else if (selectedFormat === 'xlsx') {
 await convertToXlsx(pdf, numPages);
 } else if (selectedFormat === 'pptx') {
 await convertToPptx(pdf, numPages);
 }

 progressWrap.classList.remove('visible');
 doneBar.classList.add('visible');
 doneInfo.textContent = downloadName + ' · ' + formatSize(downloadBlob.size);

 // Zapis na serwerze (folder files/)
 saveResult(downloadBlob, downloadName).catch(function (e) {
 console.warn('Zapis wyniku nieudany:', e);
 });
 } catch (err) {
 console.error(err);
 progressWrap.classList.remove('visible');
 formatNotice.className = 'notice error';
 formatNotice.style.display = 'block';
 formatNotice.textContent = 'Wystąpił błąd podczas konwersji: ' + (err.message || 'nieznany błąd');
 } finally {
 btnConvert.disabled = false;
 }
 });

 async function convertToImages(pdf, numPages, format) {
 const mime = format === 'jpg' ? 'image/jpeg' : 'image/png';
 const quality = format === 'jpg' ? 0.92 : undefined;
 const scale = 2;
 const blobs = [];

 for (let i = 1; i <= numPages; i++) {
 setProgress(15 + Math.round((i / numPages) * 75), `Renderuję stronę ${i} z ${numPages}…`);
 const page = await pdf.getPage(i);
 const viewport = page.getViewport({ scale });
 const canvas = document.createElement('canvas');
 canvas.width = viewport.width;
 canvas.height = viewport.height;
 const ctx = canvas.getContext('2d');
 await page.render({ canvasContext: ctx, viewport }).promise;
 const blob = await new Promise(resolve => canvas.toBlob(resolve, mime, quality));
 blobs.push(blob);
 }

 const baseName = currentFile.name.replace(/\.pdf$/i, '');
 if (blobs.length === 1) {
 downloadBlob = blobs[0];
 downloadName = baseName + '.' + format;
 } else {
 setProgress(92, 'Pakuję strony do ZIP…');
 const zip = new JSZip();
 blobs.forEach((b, idx) => {
 zip.file(baseName + '_strona_' + (idx + 1) + '.' + format, b);
 });
 downloadBlob = await zip.generateAsync({ type: 'blob' });
 downloadName = baseName + '_strony.zip';
 }
 setProgress(100, 'Gotowe!');
 }

 async function extractText(pdf, numPages) {
 let fullText = '';
 for (let i = 1; i <= numPages; i++) {
 setProgress(20 + Math.round((i / numPages) * 50), `Odczytuję tekst ze strony ${i}…`);
 const page = await pdf.getPage(i);
 const content = await page.getTextContent();
 const strings = content.items.map(item => item.str);
 fullText += strings.join(' ') + '\n\n';
 }
 return fullText.trim() || '(Brak warstwy tekstowej w tym PDF - dokument może być skanem.)';
 }

 async function convertToDocx(pdf, numPages) {
 const text = await extractText(pdf, numPages);
 setProgress(80, 'Tworzę plik Word…');
 // Minimal valid DOCX (ZIP with required XML parts)
 const zip = new JSZip();
 zip.file('[Content_Types].xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
 <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
 <Default Extension="xml" ContentType="application/xml"/>
 <Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/>
</Types>`);
 zip.folder('_rels').file('.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
 <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
</Relationships>`);
 const paragraphs = text.split(/\n+/).map(line =>
 `<w:p><w:r><w:t xml:space="preserve">${escapeXml(line)}</w:t></w:r></w:p>`
 ).join('');
 zip.folder('word').file('document.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
 <w:body>
 ${paragraphs}
 <w:sectPr><w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"/></w:sectPr>
 </w:body>
</w:document>`);
 downloadBlob = await zip.generateAsync({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
 downloadName = currentFile.name.replace(/\.pdf$/i, '') + '.docx';
 setProgress(100, 'Gotowe!');
 }

 async function convertToXlsx(pdf, numPages) {
 const text = await extractText(pdf, numPages);
 setProgress(80, 'Tworzę plik Excel…');
 // Simple CSV-based approach packaged as minimal XLSX is complex; we create a valid simple spreadsheet XML
 // For reliability we generate a CSV and name it .xlsx with note, but better: real minimal XLSX
 const lines = text.split(/\n+/).filter(Boolean);
 const rows = lines.map(line => {
 // try split by multiple spaces or tabs as crude table
 const cells = line.split(/\s{2,}|\t/).map(c => c.trim()).filter(Boolean);
 return cells.length ? cells : [line];
 });

 const zip = new JSZip();
 zip.file('[Content_Types].xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
 <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
 <Default Extension="xml" ContentType="application/xml"/>
 <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
 <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
</Types>`);
 zip.folder('_rels').file('.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
 <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/>
</Relationships>`);
 zip.folder('xl').folder('_rels').file('workbook.xml.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
 <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/>
</Relationships>`);
 zip.folder('xl').file('workbook.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
 <sheets><sheet name="Arkusz1" sheetId="1" r:id="rId1"/></sheets>
</workbook>`);
 let sheetData = '';
 rows.forEach((row, rIdx) => {
 sheetData += `<row r="${rIdx + 1}">`;
 row.forEach((cell, cIdx) => {
 const col = String.fromCharCode(65 + (cIdx % 26));
 sheetData += `<c r="${col}${rIdx + 1}" t="inlineStr"><is><t>${escapeXml(cell)}</t></is></c>`;
 });
 sheetData += `</row>`;
 });
 zip.folder('xl').folder('worksheets').file('sheet1.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
 <sheetData>${sheetData}</sheetData>
</worksheet>`);
 downloadBlob = await zip.generateAsync({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
 downloadName = currentFile.name.replace(/\.pdf$/i, '') + '.xlsx';
 setProgress(100, 'Gotowe!');
 }

 async function convertToPptx(pdf, numPages) {
 // For PPTX we create one slide per page with the extracted text
 const texts = [];
 for (let i = 1; i <= numPages; i++) {
 setProgress(15 + Math.round((i / numPages) * 55), `Odczytuję stronę ${i}…`);
 const page = await pdf.getPage(i);
 const content = await page.getTextContent();
 const pageText = content.items.map(item => item.str).join(' ').trim() || `(Strona ${i})`;
 texts.push(pageText);
 }
 setProgress(75, 'Tworzę prezentację PowerPoint…');

 // Minimal PPTX structure is quite heavy; we generate a simple one with text boxes
 const zip = new JSZip();
 zip.file('[Content_Types].xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
 <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
 <Default Extension="xml" ContentType="application/xml"/>
 <Override PartName="/ppt/presentation.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml"/>
 ${texts.map((_, i) => `<Override PartName="/ppt/slides/slide${i + 1}.xml" ContentType="application/vnd.openxmlformats-officedocument.presentationml.slide+xml"/>`).join('')}
</Types>`);
 zip.folder('_rels').file('.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
 <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="ppt/presentation.xml"/>
</Relationships>`);
 const slideRels = texts.map((_, i) =>
 `<Relationship Id="rId${i + 1}" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="slides/slide${i + 1}.xml"/>`
 ).join('');
 zip.folder('ppt').folder('_rels').file('presentation.xml.rels', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">${slideRels}</Relationships>`);
 zip.folder('ppt').file('presentation.xml', `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:presentation xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
 <p:sldIdLst>
 ${texts.map((_, i) => `<p:sldId id="${256 + i}" r:id="rId${i + 1}"/>`).join('')}
 </p:sldIdLst>
 <p:sldSz cx="9144000" cy="6858000"/>
</p:presentation>`);

 texts.forEach((txt, i) => {
 const safe = escapeXml(txt.substring(0, 2000));
 zip.folder('ppt').folder('slides').file(`slide${i + 1}.xml`, `<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<p:sld xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
 <p:cSld>
 <p:spTree>
 <p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr>
 <p:grpSpPr/>
 <p:sp>
 <p:nvSpPr><p:cNvPr id="2" name="Title"/><p:cNvSpPr/><p:nvPr/></p:nvSpPr>
 <p:spPr>
 <a:xfrm><a:off x="457200" y="457200"/><a:ext cx="8229600" cy="5943600"/></a:xfrm>
 </p:spPr>
 <p:txBody>
 <a:bodyPr wrap="square"/>
 <a:lstStyle/>
 <a:p><a:r><a:rPr lang="pl-PL" sz="1800"/><a:t>${safe}</a:t></a:r></a:p>
 </p:txBody>
 </p:sp>
 </p:spTree>
 </p:cSld>
 <p:clrMapOvr><a:masterClrMapping/></p:clrMapOvr>
</p:sld>`);
 });

 downloadBlob = await zip.generateAsync({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' });
 downloadName = currentFile.name.replace(/\.pdf$/i, '') + '.pptx';
 setProgress(100, 'Gotowe!');
 }

 function escapeXml(str) {
 return String(str)
 .replace(/&/g, '&amp;')
 .replace(/</g, '&lt;')
 .replace(/>/g, '&gt;')
 .replace(/"/g, '&quot;')
 .replace(/'/g, '&apos;');
 }

 btnDownload.addEventListener('click', () => {
 if (!downloadBlob) return;
 const url = URL.createObjectURL(downloadBlob);
 const a = document.createElement('a');
 a.href = url;
 a.download = downloadName;
 document.body.appendChild(a);
 a.click();
 setTimeout(() => {
 URL.revokeObjectURL(url);
 a.remove();
 }, 1000);
 });

 // FAQ accordion
 document.querySelectorAll('.faq-q').forEach(q => {
 q.addEventListener('click', () => {
 const item = q.parentElement;
 const wasOpen = item.classList.contains('open');
 document.querySelectorAll('.faq-item').forEach(i => i.classList.remove('open'));
 if (!wasOpen) item.classList.add('open');
 });
 });
})();
</script>
<script>
(function () {
 var toggle = document.getElementById('nav-toggle');
 var nav = document.getElementById('main-nav');
 if (!toggle || !nav) return;
 toggle.addEventListener('click', function () {
 var open = nav.classList.toggle('open');
 toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
 });
 nav.querySelectorAll('a').forEach(function (a) {
 a.addEventListener('click', function () {
 nav.classList.remove('open');
 toggle.setAttribute('aria-expanded', 'false');
 });
 });
 window.addEventListener('resize', function () {
 if (window.innerWidth > 720) {
 nav.classList.remove('open');
 toggle.setAttribute('aria-expanded', 'false');
 }
 });
})();
</script>
</body>
</html>
