Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Image to PDF Converter</title> | |
| <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}"> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
| <script src="{{ url_for('static', filename='script.js') }}"></script> | |
| <!-- Three.js for the 3D rotating PDF icon in the header --> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> | |
| </head> | |
| <body> | |
| <!-- ββ 3D Canvas header ββββββββββββββββββββββββββββββββββββ --> | |
| <div id="three-header" style="width:120px;height:120px;margin:0 auto 1rem;"></div> | |
| <header> | |
| <h1>Image to PDF</h1> | |
| <p>Upload images, arrange them, and download a ready PDF β free up to 15 images.</p> | |
| </header> | |
| <main> | |
| <div class="card"> | |
| <!-- Drop zone --> | |
| <div id="drop-zone"> | |
| <input type="file" id="file-input" multiple accept="image/png,image/jpeg,image/webp,image/gif,image/bmp" /> | |
| <div class="drop-icon"> | |
| <!-- upload icon --> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="#5048c8" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"> | |
| <polyline points="16 16 12 12 8 16"></polyline> | |
| <line x1="12" y1="12" x2="12" y2="21"></line> | |
| <path d="M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3"></path> | |
| </svg> | |
| </div> | |
| <h2>Drop images here or click to browse</h2> | |
| <p>PNG, JPG, WEBP, GIF, BMP Β· Free tier: up to 15 images</p> | |
| <div class="limit-badge"> | |
| <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> | |
| <circle cx="12" cy="12" r="10"></circle> | |
| <line x1="12" y1="8" x2="12" y2="12"></line> | |
| <line x1="12" y1="16" x2="12.01" y2="16"></line> | |
| </svg> | |
| Free plan: 15 images max | |
| </div> | |
| </div> | |
| <!-- Counter bar --> | |
| <div id="counter-bar"> | |
| <span> | |
| <span class="count-dot" id="count-dot"></span> | |
| <span class="count-num" id="count-num">0</span> image(s) selected | |
| </span> | |
| <span id="count-limit-text" style="font-size:12px;color:var(--text-muted);">0 / 15 free slots used</span> | |
| </div> | |
| <!-- Preview grid --> | |
| <div id="preview-grid"></div> | |
| <!-- Actions --> | |
| <div class="actions"> | |
| <button class="btn-ghost" id="clear-btn" onclick="clearAll()" style="display:none;">Clear all</button> | |
| <button class="btn-primary" id="convert-btn" disabled onclick="convertToPDF()"> | |
| <svg width="16" height="16" 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> | |
| <span id="btn-label">Convert to PDF</span> | |
| <div id="loading-bar"><div id="loading-bar-fill"></div></div> | |
| </button> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- ββ Toast βββββββββββββββββββββββββββββββββββββββββββββββ --> | |
| <div id="toast"></div> | |
| <!-- ββ Premium dialog overlay ββββββββββββββββββββββββββββββ --> | |
| <div id="overlay" onclick="closeDialog(event)"> | |
| <div id="premium-dialog"> | |
| <div class="dialog-icon"> | |
| <!-- crown / star icon --> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="#ba7517" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"> | |
| <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon> | |
| </svg> | |
| </div> | |
| <h2>Upgrade to Premium</h2> | |
| <p>You've reached the <strong>15-image limit</strong> for the free plan. Unlock unlimited conversions and more with Premium.</p> | |
| <ul class="perks"> | |
| <li> | |
| <span class="perk-check"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> | |
| </span> | |
| Unlimited images per PDF | |
| </li> | |
| <li> | |
| <span class="perk-check"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> | |
| </span> | |
| Custom page sizes & orientation | |
| </li> | |
| <li> | |
| <span class="perk-check"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> | |
| </span> | |
| Password-protected PDFs | |
| </li> | |
| <li> | |
| <span class="perk-check"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg> | |
| </span> | |
| Priority conversion speed | |
| </li> | |
| </ul> | |
| <div class="dialog-actions"> | |
| <button class="btn-upgrade" onclick="showToast('Redirecting to checkoutβ¦')">Upgrade Now β $4.99 / mo</button> | |
| <button class="btn-close-dialog" onclick="closeDialog()">Maybe later</button> | |
| </div> | |
| </div> | |
| </div> | |
| </body> | |
| </html> | |