{"id":4614,"date":"2025-01-01T16:30:33","date_gmt":"2025-01-01T11:00:33","guid":{"rendered":"https:\/\/rajmedical.co.in\/?p=4614"},"modified":"2026-06-22T16:30:36","modified_gmt":"2026-06-22T11:00:36","slug":"pdf-editor","status":"publish","type":"post","link":"https:\/\/rajmedical.co.in\/hi\/pdf-editor\/","title":{"rendered":"PDF Editor"},"content":{"rendered":"<!doctype html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"utf-8\" \/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" \/>\r\n<title>Folio \u2014 PDF editor<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Big+Shoulders+Display:wght@600;700;800&family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:wght@400;500;600&display=swap\" rel=\"stylesheet\">\r\n<style>\r\n  :root{\r\n    --bg: #1c1b19;\r\n    --panel: #242220;\r\n    --panel-2: #2b2925;\r\n    --border: #3a3733;\r\n    --paper: #f2ede4;\r\n    --paper-dim: #c9c2b4;\r\n    --steel: #8fa3a8;\r\n    --steel-dim: #6c7a7e;\r\n    --safelight: #ff6a2b;\r\n    --safelight-dim: #c9531f;\r\n    --good: #6fcf7a;\r\n    --warn: #ffb84d;\r\n    --radius: 4px;\r\n  }\r\n  *{ box-sizing: border-box; }\r\n  html,body{ margin:0; padding:0; }\r\n  .wrap{\r\n    background: var(--bg);\r\n    color: var(--paper);\r\n    font-family: 'IBM Plex Sans', sans-serif;\r\n    -webkit-font-smoothing: antialiased;\r\n    min-height: 100vh;\r\n  }\r\n  .mono{ font-family: 'IBM Plex Mono', monospace; }\r\n  a{ color: inherit; }\r\n  button{ font-family: inherit; }\r\n  ::selection{ background: var(--safelight); color: #1c1b19; }\r\n\r\n  :focus-visible{ outline: 2px solid var(--safelight); outline-offset: 2px; }\r\n\r\n  .wrap{\r\n    max-width: 980px;\r\n    margin: 0 auto;\r\n    padding: 56px 24px 80px;\r\n  }\r\n\r\n  \/* ---------- Header ---------- *\/\r\n  header{ margin-bottom: 40px; }\r\n  .eyebrow{\r\n    font-size: 11px;\r\n    letter-spacing: 0.16em;\r\n    text-transform: uppercase;\r\n    color: var(--steel);\r\n    margin: 0 0 10px;\r\n  }\r\n  .eyebrow .dot{ color: var(--safelight); }\r\n  h1.wordmark{\r\n    font-family: 'Big Shoulders Display', sans-serif;\r\n    font-weight: 800;\r\n    font-size: clamp(56px, 11vw, 96px);\r\n    line-height: 0.86;\r\n    letter-spacing: -0.01em;\r\n    margin: 0 0 16px;\r\n    color: var(--paper);\r\n    opacity: 0;\r\n    transform: translateY(10px);\r\n    animation: rise 0.6s ease forwards;\r\n  }\r\n  h1.wordmark span{ color: var(--safelight); }\r\n  @keyframes rise{ to{ opacity:1; transform: translateY(0); } }\r\n  .tagline{\r\n    font-size: 16px;\r\n    line-height: 1.55;\r\n    color: var(--paper-dim);\r\n    max-width: 52ch;\r\n    margin: 0;\r\n  }\r\n\r\n  \/* ---------- Dropzone ---------- *\/\r\n  .dropzone{\r\n    position: relative;\r\n    border: 2px dashed var(--border);\r\n    border-radius: var(--radius);\r\n    padding: 64px 24px;\r\n    text-align: center;\r\n    cursor: pointer;\r\n    transition: border-color 0.15s ease, background-color 0.15s ease;\r\n    margin-bottom: 28px;\r\n  }\r\n  .dropzone:hover{ border-color: #545049; }\r\n  .dropzone.active{\r\n    border-color: var(--safelight);\r\n    background: rgba(255,106,43,0.06);\r\n  }\r\n  .dropzone .corner{\r\n    position: absolute;\r\n    width: 18px; height: 18px;\r\n    border: 0 solid var(--safelight);\r\n    opacity: 0.85;\r\n  }\r\n  .dropzone .corner.tl{ top:10px; left:10px; border-top-width:2px; border-left-width:2px; }\r\n  .dropzone .corner.tr{ top:10px; right:10px; border-top-width:2px; border-right-width:2px; }\r\n  .dropzone .corner.bl{ bottom:10px; left:10px; border-bottom-width:2px; border-left-width:2px; }\r\n  .dropzone .corner.br{ bottom:10px; right:10px; border-bottom-width:2px; border-right-width:2px; }\r\n  .dropzone svg{ color: var(--steel); margin-bottom: 14px; }\r\n  .dropzone .dz-title{ font-size: 19px; font-weight: 500; margin: 0 0 8px; color: var(--paper); }\r\n  .dropzone .dz-sub{ font-size: 12px; color: var(--steel); letter-spacing: 0.02em; }\r\n  .dropzone input[type=file]{ display:none; }\r\n\r\n  \/* ---------- Global stats \/ controls bar ---------- *\/\r\n  .statsbar{\r\n    display:none;\r\n    background: var(--panel);\r\n    border: 1px solid var(--border);\r\n    border-radius: var(--radius);\r\n    padding: 14px 18px;\r\n    margin-bottom: 20px;\r\n    align-items: center;\r\n    justify-content: space-between;\r\n    gap: 16px;\r\n    flex-wrap: wrap;\r\n  }\r\n  .statsbar.show{ display:flex; }\r\n  .statsbar .totals{ font-size: 13px; color: var(--paper-dim); }\r\n  .statsbar .totals b{ color: var(--paper); font-weight: 600; }\r\n  .statsbar .totals .pct{ color: var(--good); font-weight: 600; }\r\n  .statsbar .actions{ display:flex; gap:8px; flex-wrap: wrap; align-items:center; }\r\n\r\n  select.mini, .num-input{\r\n    background: var(--panel-2);\r\n    border: 1px solid var(--border);\r\n    color: var(--paper);\r\n    font-family: 'IBM Plex Mono', monospace;\r\n    font-size: 12px;\r\n    padding: 6px 8px;\r\n    border-radius: var(--radius);\r\n  }\r\n\r\n  .btn{\r\n    font-family: 'IBM Plex Mono', monospace;\r\n    font-size: 11px;\r\n    letter-spacing: 0.06em;\r\n    text-transform: uppercase;\r\n    padding: 8px 14px;\r\n    border-radius: var(--radius);\r\n    border: 1px solid var(--border);\r\n    background: transparent;\r\n    color: var(--paper-dim);\r\n    cursor: pointer;\r\n    transition: all 0.12s ease;\r\n  }\r\n  .btn:hover{ border-color: var(--steel); color: var(--paper); }\r\n  .btn.primary{\r\n    background: var(--safelight);\r\n    border-color: var(--safelight);\r\n    color: #1c1503;\r\n    font-weight: 600;\r\n  }\r\n  .btn.primary:hover{ background: #ff7d45; }\r\n  .btn:disabled{ opacity:0.35; cursor: not-allowed; }\r\n\r\n  \/* ---------- Cards ---------- *\/\r\n  .cards{ display:flex; flex-direction: column; gap: 16px; }\r\n  .card{\r\n    background: var(--panel);\r\n    border: 1px solid var(--border);\r\n    border-radius: var(--radius);\r\n    padding: 18px;\r\n    position: relative;\r\n    opacity: 0;\r\n    transform: translateY(6px);\r\n    animation: cardin 0.25s ease forwards;\r\n  }\r\n  @keyframes cardin{ to{ opacity:1; transform: translateY(0); } }\r\n  .card.skeleton .card-grid{ opacity: 0.4; }\r\n  .card.error{ border-color: var(--safelight-dim); }\r\n  .card .remove{\r\n    position:absolute; top:12px; right:12px;\r\n    background:none; border:none; color: var(--steel-dim);\r\n    font-size: 18px; line-height:1; cursor:pointer; padding: 4px;\r\n  }\r\n  .card .remove:hover{ color: var(--safelight); }\r\n\r\n  .card-grid{\r\n    display:grid;\r\n    grid-template-columns: 150px 1fr;\r\n    gap: 20px;\r\n  }\r\n  @media (max-width: 640px){\r\n    .card-grid{ grid-template-columns: 1fr; }\r\n  }\r\n\r\n  .thumb-wrap{\r\n    width:100%;\r\n    aspect-ratio: 1\/1;\r\n    border-radius: 2px;\r\n    border: 1px solid var(--border);\r\n    overflow:hidden;\r\n    background-image:\r\n      linear-gradient(45deg, #2b2925 25%, transparent 25%),\r\n      linear-gradient(-45deg, #2b2925 25%, transparent 25%),\r\n      linear-gradient(45deg, transparent 75%, #2b2925 75%),\r\n      linear-gradient(-45deg, transparent 75%, #2b2925 75%);\r\n    background-size: 16px 16px;\r\n    background-position: 0 0, 0 8px, 8px -8px, -8px 0px;\r\n    background-color: #1f1e1b;\r\n  }\r\n  .thumb-wrap img{ width:100%; height:100%; object-fit: contain; display:block; }\r\n\r\n  .card-head{ display:flex; align-items:flex-start; justify-content:space-between; gap: 10px; margin-bottom: 14px; padding-right: 20px; }\r\n  .card-name{ font-size: 13px; color: var(--paper); word-break: break-all; margin: 0 0 6px; }\r\n  .pill-row{ display:flex; gap:8px; flex-wrap: wrap; align-items:center; }\r\n  .pill{\r\n    font-size: 10px;\r\n    letter-spacing: 0.05em;\r\n    text-transform: uppercase;\r\n    border: 1px solid var(--steel-dim);\r\n    color: var(--steel);\r\n    padding: 2px 6px;\r\n    border-radius: 2px;\r\n  }\r\n  .meta-text{ font-size: 11px; color: var(--steel); }\r\n\r\n  \/* Quality control *\/\r\n  .ctrl-block{ margin-bottom: 16px; }\r\n  .ctrl-label{\r\n    font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase;\r\n    color: var(--steel); display:flex; justify-content: space-between; margin-bottom: 8px;\r\n  }\r\n  .ctrl-label .val{ color: var(--paper); }\r\n  input[type=range]{\r\n    -webkit-appearance: none;\r\n    width: 100%;\r\n    height: 4px;\r\n    background: var(--border);\r\n    border-radius: 2px;\r\n    margin: 0;\r\n  }\r\n  input[type=range]::-webkit-slider-thumb{\r\n    -webkit-appearance: none;\r\n    width: 15px; height: 15px;\r\n    border-radius: 50%;\r\n    background: var(--safelight);\r\n    cursor: pointer;\r\n    border: 2px solid #1c1b19;\r\n    box-shadow: 0 0 0 1px var(--safelight);\r\n  }\r\n  input[type=range]::-moz-range-thumb{\r\n    width: 15px; height: 15px;\r\n    border-radius: 50%;\r\n    background: var(--safelight);\r\n    cursor: pointer;\r\n    border: 2px solid #1c1b19;\r\n  }\r\n  .stops-row{\r\n    display:flex; justify-content: space-between;\r\n    margin-top: 6px;\r\n    font-size: 10px;\r\n    color: var(--steel-dim);\r\n    font-family: 'IBM Plex Mono', monospace;\r\n  }\r\n  .stops-row span{ flex: 1; text-align:center; }\r\n  .stops-row span:first-child{ text-align:left; }\r\n  .stops-row span:last-child{ text-align:right; }\r\n  .stops-row span.active{ color: var(--safelight); font-weight: 600; }\r\n\r\n  \/* Format chips *\/\r\n  .chip-row{ display:flex; gap:8px; flex-wrap: wrap; }\r\n  .chip{\r\n    flex: 1 1 90px;\r\n    position: relative;\r\n    border: 1px solid var(--border);\r\n    background: var(--panel-2);\r\n    border-radius: var(--radius);\r\n    padding: 8px 10px;\r\n    text-align:left;\r\n    cursor: pointer;\r\n    transition: border-color 0.12s ease, background-color 0.12s ease;\r\n  }\r\n  .chip:hover:not(:disabled){ border-color: var(--steel); }\r\n  .chip.active{ border-color: var(--safelight); background: rgba(255,106,43,0.08); }\r\n  .chip:disabled{ opacity: 0.32; cursor: not-allowed; }\r\n  .chip .fmt{ display:block; font-family:'IBM Plex Mono', monospace; font-size: 11px; font-weight:600; letter-spacing:0.04em; color: var(--paper); text-transform: uppercase; }\r\n  .chip .sz{ display:block; font-family:'IBM Plex Mono', monospace; font-size: 11px; color: var(--steel); margin-top:3px; }\r\n  .chip.active .fmt{ color: var(--safelight); }\r\n  .chip .badge{\r\n    position:absolute; top:-7px; right:6px;\r\n    font-size: 8px; letter-spacing: 0.05em; text-transform: uppercase;\r\n    background: var(--good); color: #0e1f10; padding: 1px 4px; border-radius: 2px; font-weight:700;\r\n  }\r\n\r\n  \/* Resize row *\/\r\n  .resize-row{ display:flex; align-items:center; gap:10px; margin-top: 14px; font-size: 12px; color: var(--paper-dim); flex-wrap: wrap; }\r\n  .resize-row label.cb{ display:flex; align-items:center; gap:7px; cursor:pointer; }\r\n  input[type=checkbox]{\r\n    appearance: none; width:15px; height:15px; border:1px solid var(--steel-dim); border-radius:2px;\r\n    background: var(--panel-2); cursor:pointer; position: relative; flex-shrink:0;\r\n  }\r\n  input[type=checkbox]:checked{ background: var(--safelight); border-color: var(--safelight); }\r\n  input[type=checkbox]:checked::after{\r\n    content:''; position:absolute; left:4px; top:1px; width:4px; height:8px;\r\n    border: solid #1c1b19; border-width: 0 2px 2px 0; transform: rotate(45deg);\r\n  }\r\n  .resize-row .num-input{ width: 80px; }\r\n  .resize-fields{ display:flex; align-items:center; gap:8px; }\r\n  .resize-fields[hidden]{ display:none; }\r\n\r\n  \/* Result row *\/\r\n  .result-row{\r\n    margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--border);\r\n    display:flex; align-items:center; justify-content: space-between; gap: 14px; flex-wrap: wrap;\r\n  }\r\n  .result-figures{ display:flex; align-items:baseline; gap: 12px; flex-wrap: wrap; }\r\n  .fig{ }\r\n  .fig .flabel{ font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--steel); display:block; margin-bottom: 3px; }\r\n  .fig .fval{ font-family: 'IBM Plex Mono', monospace; font-size: 14px; color: var(--steel); }\r\n  .fig.out .fval{ font-family: 'Big Shoulders Display', sans-serif; font-size: 26px; font-weight: 700; color: var(--paper); }\r\n  .arrow{ color: var(--steel-dim); font-size: 16px; }\r\n  .pct-badge{\r\n    font-family: 'IBM Plex Mono', monospace; font-size: 12px; font-weight: 600;\r\n    padding: 3px 8px; border-radius: 3px;\r\n  }\r\n  .pct-badge.down{ color: var(--good); background: rgba(111,207,122,0.12); }\r\n  .pct-badge.up{ color: var(--warn); background: rgba(255,184,77,0.12); }\r\n\r\n  .err-msg{ font-size: 13px; color: var(--warn); margin: 4px 0 0; }\r\n\r\n  \/* ---------- Footer ---------- *\/\r\n  footer{ margin-top: 56px; text-align:center; }\r\n  footer p{ font-size: 11px; color: var(--steel-dim); letter-spacing: 0.02em; line-height:1.6; }\r\n\r\n  @media (prefers-reduced-motion: reduce){\r\n    *{ animation: none !important; transition: none !important; }\r\n  }\r\n\r\n  \/* Tabs *\/\r\n  .tabs{display:flex;gap:0;margin-bottom:28px;border-bottom:1px solid var(--border);}\r\n  .tab{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:0.06em;text-transform:uppercase;background:none;border:none;color:var(--steel);padding:12px 6px 14px;margin-right:24px;cursor:pointer;border-bottom:2px solid transparent;transform:translateY(1px);}\r\n  .tab .n{color:var(--steel-dim);margin-right:6px;}\r\n  .tab:hover{color:var(--paper-dim);}\r\n  .tab.active{color:var(--paper);border-bottom-color:var(--safelight);}\r\n  .tab.active .n{color:var(--safelight);}\r\n  .mode-panel{display:none;}.mode-panel.active{display:block;}\r\n  \/* Helpers *\/\r\n  .section-label{font-size:10px;letter-spacing:0.12em;text-transform:uppercase;color:var(--steel);margin:0 0 10px;}\r\n  .action-bar{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:14px 18px;display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-top:20px;}\r\n  .action-bar .status{font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--steel);}\r\n  .action-bar .status b{color:var(--paper);}\r\n  \/* Page grid *\/\r\n  .page-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:12px;margin-bottom:20px;}\r\n  .page-tile{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;position:relative;user-select:none;opacity:0;transform:translateY(6px);animation:cardin 0.25s ease forwards;}\r\n  .page-tile.selected{border-color:var(--safelight);box-shadow:0 0 0 1px var(--safelight);}\r\n  .page-tile.drag-over{border-color:var(--good);box-shadow:0 0 0 1px var(--good);}\r\n  .page-thumb{aspect-ratio:3\/4;background:#1f1e1b;overflow:hidden;cursor:pointer;background-image:linear-gradient(45deg,#2b2925 25%,transparent 25%),linear-gradient(-45deg,#2b2925 25%,transparent 25%),linear-gradient(45deg,transparent 75%,#2b2925 75%),linear-gradient(-45deg,transparent 75%,#2b2925 75%);background-size:14px 14px;background-position:0 0,0 7px,7px -7px,-7px 0;}\r\n  .page-thumb canvas{width:100%;height:100%;object-fit:contain;display:block;}\r\n  .page-thumb .loading{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:10px;color:var(--steel-dim);font-family:'IBM Plex Mono',monospace;}\r\n  .page-badge{position:absolute;top:6px;left:6px;font-family:'IBM Plex Mono',monospace;font-size:10px;font-weight:700;background:var(--safelight);color:#1c1503;padding:1px 5px;border-radius:2px;}\r\n  .page-badge.green{background:var(--good);color:#0e1f10;}\r\n  .page-info{padding:6px 8px;font-size:10px;font-family:'IBM Plex Mono',monospace;color:var(--steel);line-height:1.5;}\r\n  .page-acts{display:flex;border-top:1px solid var(--border);}\r\n  .page-acts button{flex:1;background:none;border:none;border-right:1px solid var(--border);color:var(--steel);padding:6px 0;font-size:13px;cursor:pointer;line-height:1;}\r\n  .page-acts button:last-child{border-right:none;}\r\n  .page-acts button:hover:not(:disabled){color:var(--safelight);background:var(--panel-2);}\r\n  .page-acts button:disabled{opacity:0.25;cursor:default;}\r\n  \/* PDF source card (merge) *\/\r\n  .pdf-source-card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:12px 16px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;opacity:0;transform:translateY(6px);animation:cardin 0.25s ease forwards;margin-bottom:10px;}\r\n  .pdf-source-card .meta{flex:1;min-width:0;}\r\n  .pdf-source-card .fname{font-size:13px;color:var(--paper);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0 0 3px;}\r\n  .pdf-source-card .fmeta{font-size:11px;font-family:'IBM Plex Mono',monospace;color:var(--steel);}\r\n  .pdf-source-card .order-btns{display:flex;gap:4px;}\r\n  \/* Settings row *\/\r\n  .settings-row{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:14px 18px;margin-bottom:20px;display:flex;align-items:flex-end;gap:20px;flex-wrap:wrap;}\r\n  .sfield label{display:block;font-size:10px;letter-spacing:0.08em;text-transform:uppercase;color:var(--steel);margin-bottom:7px;}\r\n  .sfield select,.sfield input[type=text]{background:var(--panel-2);border:1px solid var(--border);color:var(--paper);font-family:'IBM Plex Mono',monospace;font-size:12px;padding:7px 9px;border-radius:var(--radius);}\r\n  .sfield input[type=text]{width:200px;}\r\n  \/* Edit toolbar *\/\r\n  .edit-toolbar{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:12px 16px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:16px;}\r\n  .tool-btn{font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:0.06em;text-transform:uppercase;padding:7px 12px;border-radius:var(--radius);border:1px solid var(--border);background:transparent;color:var(--paper-dim);cursor:pointer;transition:all 0.12s ease;}\r\n  .tool-btn:hover{border-color:var(--steel);color:var(--paper);}\r\n  .tool-btn.active{background:var(--safelight);border-color:var(--safelight);color:#1c1503;font-weight:600;}\r\n  .tool-sep{width:1px;height:22px;background:var(--border);flex-shrink:0;}\r\n  .swatch-row{display:flex;gap:5px;align-items:center;}\r\n  .swatch{width:18px;height:18px;border-radius:50%;border:2px solid transparent;cursor:pointer;flex-shrink:0;}\r\n  .swatch.active{border-color:var(--paper);}\r\n  \/* Edit layout *\/\r\n  .edit-layout{display:grid;grid-template-columns:1fr 200px;gap:20px;align-items:start;}\r\n  @media(max-width:700px){.edit-layout{grid-template-columns:1fr;}}\r\n  .edit-main{}\r\n  .edit-page-nav{display:flex;align-items:center;gap:12px;margin-bottom:12px;}\r\n  .edit-area{position:relative;display:block;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:#1f1e1b;}\r\n  #renderCanvas{display:block;width:100%;height:auto;}\r\n  #overlayCanvas{position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair;}\r\n  .text-input-float{position:absolute;background:var(--panel);border:1px solid var(--safelight);border-radius:var(--radius);padding:0;display:none;z-index:20;}\r\n  .text-input-float textarea{background:transparent;border:none;outline:none;resize:none;color:var(--paper);font-family:'IBM Plex Sans',sans-serif;font-size:14px;padding:8px 10px;min-width:180px;min-height:48px;}\r\n  .text-input-float .commit{display:block;width:100%;text-align:right;background:none;border:none;border-top:1px solid var(--border);color:var(--safelight);font-size:11px;padding:5px 10px;cursor:pointer;font-family:'IBM Plex Mono',monospace;}\r\n  \/* Edit sidebar thumbnail grid *\/\r\n  .edit-sidebar .page-grid{grid-template-columns:repeat(auto-fill,minmax(80px,1fr));}\r\n  \/* Thumb selected in edit mode *\/\r\n  .edit-sidebar .page-tile.current-page{border-color:var(--safelight);box-shadow:0 0 0 1px var(--safelight);}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<div class=\"wrap\">\r\n  <header>\r\n    <p class=\"eyebrow\"><span class=\"dot\">\u25cf<\/span> client-side photo lab<\/p>\r\n    <h1 class=\"wordmark\">FOL<span>IO<\/span><\/h1>\r\n    <p class=\"tagline\">Split a PDF into parts, stitch multiple PDFs into one, or annotate and rearrange pages \u2014 all in this tab, nothing saved in our server.<\/p>\r\n  <\/header>\r\n\r\n  <nav class=\"tabs\" role=\"tablist\">\r\n    <button class=\"tab active\" id=\"tabSplit\" role=\"tab\"><span class=\"n\">01<\/span>Split<\/button>\r\n    <button class=\"tab\" id=\"tabMerge\" role=\"tab\"><span class=\"n\">02<\/span>Merge<\/button>\r\n    <button class=\"tab\" id=\"tabEdit\" role=\"tab\"><span class=\"n\">03<\/span>Edit<\/button>\r\n  <\/nav>\r\n\r\n  <!-- SPLIT -->\r\n  <section class=\"mode-panel active\" id=\"panelSplit\">\r\n    <section class=\"dropzone\" id=\"dzSplit\" tabindex=\"0\" role=\"button\" aria-label=\"Upload PDF to split\">\r\n      <span class=\"corner tl\"><\/span><span class=\"corner tr\"><\/span><span class=\"corner bl\"><\/span><span class=\"corner br\"><\/span>\r\n      <svg width=\"34\" height=\"34\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\"\/><path d=\"M14 2v6h6\"\/><line x1=\"9\" y1=\"12\" x2=\"15\" y2=\"12\"\/><\/svg>\r\n      <p class=\"dz-title\">Drop a PDF to split, or click to browse<\/p>\r\n      <p class=\"dz-sub mono\">Extract every page, a custom range, or fixed-size chunks<\/p>\r\n      <input type=\"file\" id=\"splitInput\" accept=\"application\/pdf\" \/>\r\n    <\/section>\r\n    <div id=\"splitBody\" style=\"display:none;\">\r\n      <div class=\"settings-row\">\r\n        <div class=\"sfield\">\r\n          <label>Split mode<\/label>\r\n          <select id=\"splitMode\">\r\n            <option value=\"all\">Every page (individual files)<\/option>\r\n            <option value=\"range\">Custom page ranges<\/option>\r\n            <option value=\"chunk\">Fixed chunks<\/option>\r\n          <\/select>\r\n        <\/div>\r\n        <div class=\"sfield\" id=\"splitRangeField\" style=\"display:none;\">\r\n          <label>Ranges (comma-separated)<\/label>\r\n          <input type=\"text\" id=\"splitRangeInput\" placeholder=\"1-3, 4-6, 7\" \/>\r\n        <\/div>\r\n        <div class=\"sfield\" id=\"splitChunkField\" style=\"display:none;\">\r\n          <label>Pages per chunk<\/label>\r\n          <select id=\"splitChunkSize\">\r\n            <option value=\"1\">1 page<\/option><option value=\"2\">2 pages<\/option>\r\n            <option value=\"3\">3 pages<\/option><option value=\"5\" selected>5 pages<\/option>\r\n            <option value=\"10\">10 pages<\/option>\r\n          <\/select>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"page-grid\" id=\"splitPageGrid\"><\/div>\r\n      <div class=\"action-bar\">\r\n        <span class=\"status mono\" id=\"splitStatus\">Ready<\/span>\r\n        <div class=\"btns\">\r\n          <button class=\"btn primary\" id=\"splitBtn\" disabled>Split &amp; Download .zip<\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- MERGE -->\r\n  <section class=\"mode-panel\" id=\"panelMerge\">\r\n    <section class=\"dropzone\" id=\"dzMerge\" tabindex=\"0\" role=\"button\" aria-label=\"Upload PDFs to merge\">\r\n      <span class=\"corner tl\"><\/span><span class=\"corner tr\"><\/span><span class=\"corner bl\"><\/span><span class=\"corner br\"><\/span>\r\n      <svg width=\"34\" height=\"34\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z\"\/><path d=\"M14 2v6h6\"\/><line x1=\"9\" y1=\"12\" x2=\"15\" y2=\"12\"\/><line x1=\"12\" y1=\"9\" x2=\"12\" y2=\"15\"\/><\/svg>\r\n      <p class=\"dz-title\">Drop PDFs to merge \u2014 add as many as you need<\/p>\r\n      <p class=\"dz-sub mono\">Files are stitched together in the order shown<\/p>\r\n      <input type=\"file\" id=\"mergeInput\" accept=\"application\/pdf\" multiple \/>\r\n    <\/section>\r\n    <div id=\"mergeBody\" style=\"display:none;\">\r\n      <p class=\"section-label\">Source files<\/p>\r\n      <div id=\"mergeFileList\"><\/div>\r\n      <p class=\"section-label\" style=\"margin-top:20px;\">Page previews<\/p>\r\n      <div class=\"page-grid\" id=\"mergePageGrid\"><\/div>\r\n      <div class=\"action-bar\">\r\n        <span class=\"status mono\" id=\"mergeStatus\">Ready<\/span>\r\n        <div class=\"btns\">\r\n          <button class=\"btn\" id=\"mergeClearBtn\">Clear all<\/button>\r\n          <button class=\"btn primary\" id=\"mergeBtn\" disabled>Merge &amp; Download<\/button>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- EDIT -->\r\n  <section class=\"mode-panel\" id=\"panelEdit\">\r\n    <section class=\"dropzone\" id=\"dzEdit\" tabindex=\"0\" role=\"button\" aria-label=\"Upload PDF to edit\">\r\n      <span class=\"corner tl\"><\/span><span class=\"corner tr\"><\/span><span class=\"corner bl\"><\/span><span class=\"corner br\"><\/span>\r\n      <svg width=\"34\" height=\"34\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.4\"><path d=\"M12 20h9\"\/><path d=\"M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z\"\/><\/svg>\r\n      <p class=\"dz-title\">Drop a PDF to edit, or click to browse<\/p>\r\n      <p class=\"dz-sub mono\">Annotate \u00b7 Draw \u00b7 Add text \u00b7 Highlight \u00b7 Rotate \u00b7 Reorder \u00b7 Delete pages<\/p>\r\n      <input type=\"file\" id=\"editInput\" accept=\"application\/pdf\" \/>\r\n    <\/section>\r\n    <div id=\"editBody\" style=\"display:none;\">\r\n      <div class=\"edit-toolbar\">\r\n        <button class=\"tool-btn active\" id=\"toolSelect\">\u2b1a Select<\/button>\r\n        <button class=\"tool-btn\" id=\"toolText\">T Text<\/button>\r\n        <button class=\"tool-btn\" id=\"toolDraw\">\u270f Draw<\/button>\r\n        <button class=\"tool-btn\" id=\"toolHighlight\">\u25ac Highlight<\/button>\r\n        <div class=\"tool-sep\"><\/div>\r\n        <div class=\"swatch-row\" id=\"swatchRow\"><\/div>\r\n        <div class=\"tool-sep\"><\/div>\r\n        <div class=\"sfield\">\r\n          <select id=\"toolFontSize\" style=\"background:var(--panel-2);border:1px solid var(--border);color:var(--paper);font-family:'IBM Plex Mono',monospace;font-size:11px;padding:6px 8px;border-radius:var(--radius);\">\r\n            <option value=\"10\">10px<\/option><option value=\"12\">12px<\/option>\r\n            <option value=\"14\" selected>14px<\/option><option value=\"18\">18px<\/option>\r\n            <option value=\"24\">24px<\/option><option value=\"32\">32px<\/option>\r\n          <\/select>\r\n        <\/div>\r\n        <div class=\"tool-sep\"><\/div>\r\n        <button class=\"tool-btn\" id=\"toolUndo\">\u21a9 Undo<\/button>\r\n      <\/div>\r\n\r\n      <div class=\"edit-layout\">\r\n        <div class=\"edit-main\">\r\n          <div class=\"edit-page-nav\">\r\n            <button class=\"btn\" id=\"editPrevPage\">\u2039<\/button>\r\n            <span class=\"mono\" id=\"editPageLabel\" style=\"font-size:12px;color:var(--steel);\">Page 1<\/span>\r\n            <button class=\"btn\" id=\"editNextPage\">\u203a<\/button>\r\n          <\/div>\r\n          <div class=\"edit-area\" id=\"editArea\">\r\n            <canvas id=\"renderCanvas\"><\/canvas>\r\n            <canvas id=\"overlayCanvas\"><\/canvas>\r\n            <div class=\"text-input-float\" id=\"textFloat\">\r\n              <textarea id=\"textInput\" placeholder=\"Type here\u2026\" rows=\"2\"><\/textarea>\r\n              <button class=\"commit\" id=\"textCommit\">Place \u21b5<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"edit-sidebar\">\r\n          <p class=\"section-label\">All pages<\/p>\r\n          <div class=\"page-grid\" id=\"editThumbGrid\" style=\"grid-template-columns:repeat(auto-fill,minmax(80px,1fr));\"><\/div>\r\n          <div class=\"action-bar\" style=\"margin-top:16px;\">\r\n            <span class=\"status mono\" id=\"editStatus\">Ready<\/span>\r\n            <div class=\"btns\">\r\n              <button class=\"btn primary\" id=\"editSaveBtn\" disabled>Save PDF<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <footer>\r\n    <p> <!-- PDF manipulation runs on-device using pdf-lib and pdf.js.<br>  --> No file ever saves in our server.<\/p>\r\n  <\/footer>\r\n<\/div>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jszip\/3.10.1\/jszip.min.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/pdf-lib\/1.17.1\/pdf-lib.min.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/pdf.js\/2.16.105\/pdf.min.js\"><\/script>\r\n<script>\r\n(function(){\r\n\"use strict\";\r\n\r\n\/\/ \u2500\u2500\u2500 Shared utils \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction formatBytes(b){if(!b)return'\u2014';if(b<1024)return b+' B';var u=['KB','MB','GB'],v=b,i=-1;do{v\/=1024;i++;}while(v>=1024&&i<u.length-1);return v.toFixed(v<10?2:1)+' '+u[i];}\r\nfunction uid(){return 'f'+Math.random().toString(36).slice(2,9)+Date.now().toString(36);}\r\nfunction baseName(n){var i=n.lastIndexOf('.');return i>0?n.slice(0,i):n;}\r\nfunction pad(n,d){return String(n).padStart(d,'0');}\r\nfunction esc(s){var d=document.createElement('div');d.textContent=s;return d.innerHTML;}\r\nfunction dl(url,name){var a=document.createElement('a');a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();}\r\nfunction parseRange(text,max){\r\n  text=(text||'').trim();\r\n  if(!text){var r=[];for(var i=1;i<=max;i++)r.push(i);return r;}\r\n  var set={};\r\n  text.split(',').forEach(function(t){\r\n    t=t.trim();if(!t)return;\r\n    if(t.indexOf('-')>-1){var p=t.split('-'),a=parseInt(p[0]),b=parseInt(p[1]);if(isNaN(a)||isNaN(b))return;if(a>b){var x=a;a=b;b=x;}for(var n=Math.max(1,a);n<=Math.min(max,b);n++)set[n]=true;}\r\n    else{var v=parseInt(t,10);if(!isNaN(v)&&v>=1&&v<=max)set[v]=true;}\r\n  });\r\n  return Object.keys(set).map(Number).sort(function(a,b){return a-b;});\r\n}\r\nfunction wireDropzone(dzId,inputId,cb){\r\n  var dz=document.getElementById(dzId),inp=document.getElementById(inputId);\r\n  dz.addEventListener('click',function(){inp.click();});\r\n  dz.addEventListener('keydown',function(e){if(e.key==='Enter'||e.key===' '){e.preventDefault();inp.click();}});\r\n  inp.addEventListener('change',function(){if(inp.files.length)cb(inp.files);inp.value='';});\r\n  ['dragenter','dragover'].forEach(function(ev){dz.addEventListener(ev,function(e){e.preventDefault();dz.classList.add('active');});});\r\n  ['dragleave','drop'].forEach(function(ev){dz.addEventListener(ev,function(e){e.preventDefault();dz.classList.remove('active');});});\r\n  dz.addEventListener('drop',function(e){if(e.dataTransfer&&e.dataTransfer.files.length)cb(e.dataTransfer.files);});\r\n}\r\n\r\n\/\/ \u2500\u2500\u2500 pdf.js thumbnail helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction renderThumb(pdfDoc,pageNum,container,scale){\r\n  scale=scale||0.35;\r\n  container.innerHTML='<div class=\"loading\">\u2026<\/div>';\r\n  pdfDoc.getPage(pageNum).then(function(page){\r\n    var vp=page.getViewport({scale:scale});\r\n    var canvas=document.createElement('canvas');\r\n    canvas.width=Math.ceil(vp.width);canvas.height=Math.ceil(vp.height);\r\n    var ctx=canvas.getContext('2d');\r\n    ctx.fillStyle='#ffffff';ctx.fillRect(0,0,canvas.width,canvas.height);\r\n    page.render({canvasContext:ctx,viewport:vp}).promise.then(function(){\r\n      container.innerHTML='';container.appendChild(canvas);\r\n    });\r\n  });\r\n}\r\n\r\n\/\/ \u2500\u2500\u2500 TABS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction wireTabs(){\r\n  var tabs=[\r\n    {btn:'tabSplit',panel:'panelSplit'},\r\n    {btn:'tabMerge',panel:'panelMerge'},\r\n    {btn:'tabEdit',panel:'panelEdit'}\r\n  ];\r\n  tabs.forEach(function(t){\r\n    document.getElementById(t.btn).addEventListener('click',function(){\r\n      tabs.forEach(function(x){\r\n        document.getElementById(x.btn).classList.toggle('active',x.btn===t.btn);\r\n        document.getElementById(x.panel).classList.toggle('active',x.panel===t.panel);\r\n      });\r\n    });\r\n  });\r\n}\r\n\r\n\/\/ ===================================================================\r\n\/\/ SPLIT\r\n\/\/ ===================================================================\r\nvar splitState={pdfBytes:null,pdfDoc:null,pjsDoc:null,name:'',numPages:0};\r\n\r\nfunction initSplit(){\r\n  wireDropzone('dzSplit','splitInput',function(files){\r\n    var f=Array.from(files).find(function(x){return x.type==='application\/pdf'||\/\\.pdf$\/i.test(x.name);});\r\n    if(f)loadSplitFile(f);\r\n  });\r\n  document.getElementById('splitMode').addEventListener('change',onSplitModeChange);\r\n  document.getElementById('splitBtn').addEventListener('click',doSplit);\r\n}\r\n\r\nfunction onSplitModeChange(){\r\n  var m=document.getElementById('splitMode').value;\r\n  document.getElementById('splitRangeField').style.display=m==='range'?'':'none';\r\n  document.getElementById('splitChunkField').style.display=m==='chunk'?'':'none';\r\n}\r\n\r\nfunction loadSplitFile(file){\r\n  splitState.name=baseName(file.name);\r\n  document.getElementById('splitStatus').textContent='Loading\u2026';\r\n  file.arrayBuffer().then(function(buf){\r\n    splitState.pdfBytes=new Uint8Array(buf);\r\n    return Promise.all([\r\n      PDFLib.PDFDocument.load(splitState.pdfBytes),\r\n      pdfjsLib.getDocument({data:buf.slice()}).promise\r\n    ]);\r\n  }).then(function(results){\r\n    splitState.pdfDoc=results[0];\r\n    splitState.pjsDoc=results[1];\r\n    splitState.numPages=splitState.pdfDoc.getPageCount();\r\n    document.getElementById('splitBody').style.display='';\r\n    document.getElementById('splitBtn').disabled=false;\r\n    renderSplitGrid();\r\n    document.getElementById('splitStatus').textContent=splitState.numPages+' pages \u00b7 '+formatBytes(splitState.pdfBytes.length);\r\n  }).catch(function(e){\r\n    document.getElementById('splitStatus').textContent='Error: '+e.message;\r\n  });\r\n}\r\n\r\nfunction renderSplitGrid(){\r\n  var grid=document.getElementById('splitPageGrid');\r\n  grid.innerHTML='';\r\n  var n=splitState.numPages;\r\n  for(var i=1;i<=n;i++){\r\n    (function(pageNum){\r\n      var tile=document.createElement('div');\r\n      tile.className='page-tile';\r\n      tile.innerHTML='<div class=\"page-thumb\"><\/div><div class=\"page-info\">Page '+pageNum+'<\/div>';\r\n      var badge=document.createElement('span');badge.className='page-badge';badge.textContent=pad(pageNum,2);\r\n      tile.querySelector('.page-thumb').appendChild(badge);\r\n      renderThumb(splitState.pjsDoc,pageNum,tile.querySelector('.page-thumb'));\r\n      grid.appendChild(tile);\r\n    })(i);\r\n  }\r\n}\r\n\r\nasync function doSplit(){\r\n  if(!splitState.pdfDoc)return;\r\n  var btn=document.getElementById('splitBtn');\r\n  var statusEl=document.getElementById('splitStatus');\r\n  btn.disabled=true;statusEl.textContent='Splitting\u2026';\r\n\r\n  var mode=document.getElementById('splitMode').value;\r\n  var ranges=[];\r\n  var n=splitState.numPages;\r\n\r\n  if(mode==='all'){\r\n    for(var i=1;i<=n;i++)ranges.push([i]);\r\n  }else if(mode==='range'){\r\n    var text=document.getElementById('splitRangeInput').value;\r\n    var pages=parseRange(text,n);\r\n    \/\/ Each comma token becomes a part \u2014 re-parse properly\r\n    var rawTokens=(document.getElementById('splitRangeInput').value||'').split(',');\r\n    rawTokens.forEach(function(tok){\r\n      var pg=parseRange(tok,n);\r\n      if(pg.length)ranges.push(pg);\r\n    });\r\n    if(!ranges.length){statusEl.textContent='No valid ranges entered.';btn.disabled=false;return;}\r\n  }else{\r\n    var chunk=parseInt(document.getElementById('splitChunkSize').value,10);\r\n    for(var j=1;j<=n;j+=chunk){\r\n      var part=[];\r\n      for(var k=j;k<=Math.min(j+chunk-1,n);k++)part.push(k);\r\n      ranges.push(part);\r\n    }\r\n  }\r\n\r\n  var zip=new JSZip();\r\n  var digits=String(ranges.length).length;\r\n  for(var r=0;r<ranges.length;r++){\r\n    statusEl.textContent='Building part '+(r+1)+' of '+ranges.length+'\u2026';\r\n    var subDoc=await PDFLib.PDFDocument.create();\r\n    var pageIndices=ranges[r].map(function(p){return p-1;});\r\n    var copied=await subDoc.copyPages(splitState.pdfDoc,pageIndices);\r\n    copied.forEach(function(p){subDoc.addPage(p);});\r\n    var bytes=await subDoc.save();\r\n    var partName=splitState.name+'-part'+pad(r+1,digits)+'.pdf';\r\n    zip.file(partName,bytes);\r\n  }\r\n\r\n  statusEl.textContent='Zipping '+ranges.length+' files\u2026';\r\n  var content=await zip.generateAsync({type:'blob'});\r\n  var url=URL.createObjectURL(content);\r\n  dl(url,splitState.name+'-split.zip');\r\n  setTimeout(function(){URL.revokeObjectURL(url);},5000);\r\n  statusEl.textContent='Done \u2014 '+ranges.length+' parts downloaded.';\r\n  btn.disabled=false;\r\n}\r\n\r\n\/\/ ===================================================================\r\n\/\/ MERGE\r\n\/\/ ===================================================================\r\nvar mergeFiles=[];\r\n\r\nfunction initMerge(){\r\n  wireDropzone('dzMerge','mergeInput',function(files){\r\n    Array.from(files).filter(function(f){return f.type==='application\/pdf'||\/\\.pdf$\/i.test(f.name);}).forEach(addMergeFile);\r\n  });\r\n  document.getElementById('mergeClearBtn').addEventListener('click',clearMerge);\r\n  document.getElementById('mergeBtn').addEventListener('click',doMerge);\r\n}\r\n\r\nfunction addMergeFile(file){\r\n  var id=uid();\r\n  var entry={id:id,file:file,name:file.name,base:baseName(file.name),size:file.size,numPages:0,pdfBytes:null,pdfDoc:null,pjsDoc:null};\r\n  mergeFiles.push(entry);\r\n  document.getElementById('mergeBody').style.display='';\r\n  renderMergeFileList();\r\n  file.arrayBuffer().then(function(buf){\r\n    entry.pdfBytes=new Uint8Array(buf);\r\n    return Promise.all([PDFLib.PDFDocument.load(entry.pdfBytes),pdfjsLib.getDocument({data:buf.slice()}).promise]);\r\n  }).then(function(r){\r\n    entry.pdfDoc=r[0];entry.pjsDoc=r[1];entry.numPages=r[0].getPageCount();\r\n    renderMergeFileList();\r\n    renderMergeGrid();\r\n    updateMergeStatus();\r\n  });\r\n}\r\n\r\nfunction renderMergeFileList(){\r\n  var list=document.getElementById('mergeFileList');\r\n  list.innerHTML='';\r\n  mergeFiles.forEach(function(e,idx){\r\n    var card=document.createElement('div');\r\n    card.className='pdf-source-card';\r\n    card.innerHTML=\r\n      '<span style=\"font-size:22px;flex-shrink:0;\">\ud83d\udcc4<\/span>'+\r\n      '<div class=\"meta\"><div class=\"fname\">'+esc(e.name)+'<\/div>'+\r\n      '<div class=\"fmeta\">'+(e.numPages||'\u2026')+' pages \u00b7 '+formatBytes(e.size)+'<\/div><\/div>'+\r\n      '<div class=\"order-btns\">'+\r\n        '<button class=\"btn\" data-act=\"up\" '+(idx===0?'disabled':'')+'>\u2039<\/button>'+\r\n        '<button class=\"btn\" data-act=\"dn\" '+(idx===mergeFiles.length-1?'disabled':'')+'>\u203a<\/button>'+\r\n        '<button class=\"btn\" data-act=\"rm\">\u00d7<\/button>'+\r\n      '<\/div>';\r\n    card.querySelectorAll('button[data-act]').forEach(function(btn){\r\n      btn.addEventListener('click',function(){\r\n        var act=btn.dataset.act,i=mergeFiles.findIndex(function(x){return x.id===e.id;});\r\n        if(act==='up'&&i>0){var t=mergeFiles[i];mergeFiles[i]=mergeFiles[i-1];mergeFiles[i-1]=t;}\r\n        else if(act==='dn'&&i<mergeFiles.length-1){var t2=mergeFiles[i];mergeFiles[i]=mergeFiles[i+1];mergeFiles[i+1]=t2;}\r\n        else if(act==='rm'){mergeFiles.splice(i,1);}\r\n        renderMergeFileList();renderMergeGrid();updateMergeStatus();\r\n        if(mergeFiles.length===0)document.getElementById('mergeBody').style.display='none';\r\n      });\r\n    });\r\n    list.appendChild(card);\r\n  });\r\n}\r\n\r\nfunction renderMergeGrid(){\r\n  var grid=document.getElementById('mergePageGrid');\r\n  grid.innerHTML='';\r\n  var globalPage=0;\r\n  mergeFiles.forEach(function(entry,fi){\r\n    for(var p=1;p<=entry.numPages;p++){\r\n      globalPage++;\r\n      (function(gp,ep,ent){\r\n        var tile=document.createElement('div');\r\n        tile.className='page-tile';\r\n        tile.innerHTML='<div class=\"page-thumb\"><\/div><div class=\"page-info\">File '+(fi+1)+' \u00b7 p.'+ep+'<\/div>';\r\n        var badge=document.createElement('span');badge.className='page-badge';badge.textContent=pad(gp,2);\r\n        tile.querySelector('.page-thumb').appendChild(badge);\r\n        if(ent.pjsDoc)renderThumb(ent.pjsDoc,ep,tile.querySelector('.page-thumb'));\r\n        else tile.querySelector('.page-thumb').innerHTML='<div class=\"loading\">\u2026<\/div>';\r\n        grid.appendChild(tile);\r\n      })(globalPage,p,entry);\r\n    }\r\n  });\r\n}\r\n\r\nfunction updateMergeStatus(){\r\n  var totalPages=mergeFiles.reduce(function(s,e){return s+e.numPages;},0);\r\n  document.getElementById('mergeStatus').textContent=mergeFiles.length+' files \u00b7 '+totalPages+' pages total';\r\n  document.getElementById('mergeBtn').disabled=mergeFiles.length<2||mergeFiles.some(function(e){return!e.pdfDoc;});\r\n}\r\n\r\nfunction clearMerge(){\r\n  mergeFiles=[];\r\n  document.getElementById('mergeBody').style.display='none';\r\n  document.getElementById('mergePageGrid').innerHTML='';\r\n  document.getElementById('mergeFileList').innerHTML='';\r\n}\r\n\r\nasync function doMerge(){\r\n  var btn=document.getElementById('mergeBtn');\r\n  var statusEl=document.getElementById('mergeStatus');\r\n  btn.disabled=true;statusEl.textContent='Merging\u2026';\r\n  try{\r\n    var merged=await PDFLib.PDFDocument.create();\r\n    for(var i=0;i<mergeFiles.length;i++){\r\n      statusEl.textContent='Copying file '+(i+1)+' of '+mergeFiles.length+'\u2026';\r\n      var src=mergeFiles[i].pdfDoc;\r\n      var indices=src.getPageIndices();\r\n      var pages=await merged.copyPages(src,indices);\r\n      pages.forEach(function(p){merged.addPage(p);});\r\n    }\r\n    statusEl.textContent='Saving\u2026';\r\n    var bytes=await merged.save();\r\n    var blob=new Blob([bytes],{type:'application\/pdf'});\r\n    var url=URL.createObjectURL(blob);\r\n    dl(url,'merged.pdf');\r\n    setTimeout(function(){URL.revokeObjectURL(url);},5000);\r\n    statusEl.textContent='Done \u2014 '+merged.getPageCount()+' pages merged.';\r\n    btn.disabled=false;\r\n  }catch(e){\r\n    statusEl.textContent='Error: '+e.message;btn.disabled=false;\r\n  }\r\n}\r\n\r\n\/\/ ===================================================================\r\n\/\/ EDIT\r\n\/\/ ===================================================================\r\nvar editState={\r\n  pdfBytes:null,pdfLib:null,pjsDoc:null,name:'',\r\n  numPages:0,currentPage:1,\r\n  pageScale:1.5,\r\n  annotations:{}, \/\/ pageNum -> [{type,x,y,text,color,fontSize,strokes}]\r\n  activeTool:'select',\r\n  activeColor:'#ff6a2b',\r\n  activeFontSize:14,\r\n  drawActive:false,currentStroke:null,\r\n  undoStack:[] \/\/ {page, annotations snapshot}\r\n};\r\n\r\nvar SWATCHES=['#ff6a2b','#ffffff','#000000','#ffb84d','#6fcf7a','#5bc0eb','#e85d75'];\r\n\r\nfunction initEdit(){\r\n  wireDropzone('dzEdit','editInput',function(files){\r\n    var f=Array.from(files).find(function(x){return x.type==='application\/pdf'||\/\\.pdf$\/i.test(x.name);});\r\n    if(f)loadEditFile(f);\r\n  });\r\n\r\n  \/\/ Swatches\r\n  var swRow=document.getElementById('swatchRow');\r\n  SWATCHES.forEach(function(col){\r\n    var sw=document.createElement('div');\r\n    sw.className='swatch'+(col===editState.activeColor?' active':'');\r\n    sw.style.background=col;\r\n    sw.title=col;\r\n    sw.addEventListener('click',function(){\r\n      editState.activeColor=col;\r\n      document.querySelectorAll('.swatch').forEach(function(s){s.classList.toggle('active',s.style.background===col||s.title===col);});\r\n    });\r\n    swRow.appendChild(sw);\r\n  });\r\n\r\n  \/\/ Tools\r\n  ['toolSelect','toolText','toolDraw','toolHighlight'].forEach(function(id){\r\n    document.getElementById(id).addEventListener('click',function(){\r\n      editState.activeTool=id.replace('tool','').toLowerCase();\r\n      ['toolSelect','toolText','toolDraw','toolHighlight'].forEach(function(x){\r\n        document.getElementById(x).classList.toggle('active',x===id);\r\n      });\r\n      updateOverlayCursor();\r\n    });\r\n  });\r\n  document.getElementById('toolUndo').addEventListener('click',doUndo);\r\n  document.getElementById('toolFontSize').addEventListener('change',function(e){editState.activeFontSize=parseInt(e.target.value,10);});\r\n\r\n  \/\/ Page nav\r\n  document.getElementById('editPrevPage').addEventListener('click',function(){if(editState.currentPage>1){editState.currentPage--;renderEditPage();}});\r\n  document.getElementById('editNextPage').addEventListener('click',function(){if(editState.currentPage<editState.numPages){editState.currentPage++;renderEditPage();}});\r\n\r\n  \/\/ Overlay canvas events\r\n  var oc=document.getElementById('overlayCanvas');\r\n  oc.addEventListener('mousedown',onOverlayDown);\r\n  oc.addEventListener('mousemove',onOverlayMove);\r\n  oc.addEventListener('mouseup',onOverlayUp);\r\n  oc.addEventListener('click',onOverlayClick);\r\n  \/\/ Touch\r\n  oc.addEventListener('touchstart',function(e){e.preventDefault();var t=e.touches[0];onOverlayDown(toFakeMouseEvent(t,oc));},{passive:false});\r\n  oc.addEventListener('touchmove',function(e){e.preventDefault();var t=e.touches[0];onOverlayMove(toFakeMouseEvent(t,oc));},{passive:false});\r\n  oc.addEventListener('touchend',function(e){e.preventDefault();onOverlayUp({});});\r\n\r\n  \/\/ Text commit\r\n  document.getElementById('textCommit').addEventListener('click',commitText);\r\n  document.getElementById('editSaveBtn').addEventListener('click',saveEditPdf);\r\n}\r\n\r\nfunction toFakeMouseEvent(touch,canvas){\r\n  var r=canvas.getBoundingClientRect();\r\n  return{clientX:touch.clientX,clientY:touch.clientY,target:canvas};\r\n}\r\n\r\nfunction loadEditFile(file){\r\n  editState.name=baseName(file.name);\r\n  document.getElementById('editStatus').textContent='Loading\u2026';\r\n  file.arrayBuffer().then(function(buf){\r\n    editState.pdfBytes=new Uint8Array(buf);\r\n    return Promise.all([PDFLib.PDFDocument.load(editState.pdfBytes),pdfjsLib.getDocument({data:buf.slice()}).promise]);\r\n  }).then(function(r){\r\n    editState.pdfLib=r[0];editState.pjsDoc=r[1];\r\n    editState.numPages=editState.pdfLib.getPageCount();\r\n    editState.currentPage=1;editState.annotations={};editState.undoStack=[];\r\n    document.getElementById('editBody').style.display='';\r\n    document.getElementById('editSaveBtn').disabled=false;\r\n    renderEditThumbGrid();\r\n    renderEditPage();\r\n    document.getElementById('editStatus').textContent=editState.numPages+' pages';\r\n  }).catch(function(e){document.getElementById('editStatus').textContent='Error: '+e.message;});\r\n}\r\n\r\nfunction renderEditThumbGrid(){\r\n  var grid=document.getElementById('editThumbGrid');\r\n  grid.innerHTML='';\r\n  for(var i=1;i<=editState.numPages;i++){\r\n    (function(pageNum){\r\n      var tile=document.createElement('div');\r\n      tile.className='page-tile'+(pageNum===editState.currentPage?' current-page':'');\r\n      tile.dataset.page=pageNum;\r\n      tile.innerHTML='<div class=\"page-thumb\"><\/div><div class=\"page-info\">p.'+pageNum+'<\/div>';\r\n      var badge=document.createElement('span');badge.className='page-badge';badge.textContent=pad(pageNum,2);\r\n      tile.querySelector('.page-thumb').appendChild(badge);\r\n      renderThumb(editState.pjsDoc,pageNum,tile.querySelector('.page-thumb'),0.25);\r\n      tile.querySelector('.page-thumb').addEventListener('click',function(){\r\n        editState.currentPage=pageNum;\r\n        document.querySelectorAll('#editThumbGrid .page-tile').forEach(function(t){\r\n          t.classList.toggle('current-page',parseInt(t.dataset.page,10)===pageNum);\r\n        });\r\n        renderEditPage();\r\n      });\r\n      \/\/ Page actions: rotate CW, rotate CCW, delete\r\n      var acts=document.createElement('div');acts.className='page-acts';\r\n      acts.innerHTML='<button data-act=\"rcw\" title=\"Rotate CW\">\u21bb<\/button><button data-act=\"rccw\" title=\"Rotate CCW\">\u21ba<\/button><button data-act=\"del\" title=\"Delete page\">\u00d7<\/button>';\r\n      acts.querySelectorAll('button').forEach(function(btn){\r\n        btn.addEventListener('click',function(e){\r\n          e.stopPropagation();\r\n          var act=btn.dataset.act;\r\n          if(act==='rcw')rotatePage(pageNum,90);\r\n          else if(act==='rccw')rotatePage(pageNum,-90);\r\n          else if(act==='del')deletePage(pageNum);\r\n        });\r\n      });\r\n      tile.appendChild(acts);\r\n      grid.appendChild(tile);\r\n    })(i);\r\n  }\r\n}\r\n\r\n\/\/ Re-export the live pdf-lib doc to bytes, reload pdf.js from those bytes,\r\n\/\/ then re-render thumbnails and the current page. This is required after any\r\n\/\/ structural change (rotate, delete) because renderEditThumbGrid\/renderEditPage\r\n\/\/ both read from editState.pjsDoc which starts from the original upload bytes.\r\nasync function resyncPjsDoc(statusMsg){\r\n  var statusEl=document.getElementById('editStatus');\r\n  if(statusMsg)statusEl.textContent=statusMsg;\r\n  var bytes=await editState.pdfLib.save();\r\n  \/\/ CRITICAL: reload pdfLib from the saved bytes after every save().\r\n  \/\/ pdf-lib's save() modifies the document's internal object references\r\n  \/\/ and page tree, so subsequent getPage()\/setRotation() calls on the\r\n  \/\/ same instance break silently for pages beyond the first few.\r\n  \/\/ Reloading gives a clean, consistent document ready for the next edit.\r\n  editState.pdfLib=await PDFLib.PDFDocument.load(bytes);\r\n  var newPjs=await pdfjsLib.getDocument({data:bytes}).promise;\r\n  editState.pjsDoc=newPjs;\r\n  renderEditThumbGrid();\r\n  renderEditPage();\r\n  statusEl.textContent=editState.numPages+' pages';\r\n}\r\n\r\nfunction rotatePage(pageNum,degrees){\r\n  var page=editState.pdfLib.getPage(pageNum-1);\r\n  page.setRotation(PDFLib.degrees((page.getRotation().angle+degrees+360)%360));\r\n  resyncPjsDoc('Rotating\u2026');\r\n}\r\n\r\nfunction deletePage(pageNum){\r\n  if(editState.numPages<=1){alert('Cannot delete the only page.');return;}\r\n  editState.pdfLib.removePage(pageNum-1);\r\n  editState.numPages--;\r\n  if(editState.currentPage>editState.numPages)editState.currentPage=editState.numPages;\r\n  \/\/ Renumber annotations: drop deleted page, shift pages above it down by 1\r\n  var newAnn={};\r\n  Object.keys(editState.annotations).forEach(function(k){\r\n    var n=parseInt(k,10);\r\n    if(n===pageNum)return;          \/\/ discard annotations on deleted page\r\n    newAnn[n<pageNum?n:n-1]=editState.annotations[k];\r\n  });\r\n  editState.annotations=newAnn;\r\n  resyncPjsDoc('Deleting page '+pageNum+'\u2026');\r\n}\r\n\r\nvar renderCanvasRef=document.getElementById?document.getElementById('renderCanvas'):null;\r\n\r\nfunction renderEditPage(){\r\n  var rc=document.getElementById('renderCanvas');\r\n  var oc=document.getElementById('overlayCanvas');\r\n  var labelEl=document.getElementById('editPageLabel');\r\n  if(labelEl)labelEl.textContent='Page '+editState.currentPage+' of '+editState.numPages;\r\n  document.getElementById('editPrevPage').disabled=editState.currentPage<=1;\r\n  document.getElementById('editNextPage').disabled=editState.currentPage>=editState.numPages;\r\n\r\n  editState.pjsDoc.getPage(editState.currentPage).then(function(page){\r\n    var vp=page.getViewport({scale:editState.pageScale});\r\n    rc.width=Math.ceil(vp.width);rc.height=Math.ceil(vp.height);\r\n    oc.width=rc.width;oc.height=rc.height;\r\n    var ctx=rc.getContext('2d');\r\n    ctx.fillStyle='#ffffff';ctx.fillRect(0,0,rc.width,rc.height);\r\n    page.render({canvasContext:ctx,viewport:vp}).promise.then(function(){\r\n      redrawOverlay();\r\n    });\r\n  });\r\n  \/\/ sync sidebar\r\n  document.querySelectorAll('#editThumbGrid .page-tile').forEach(function(t){\r\n    t.classList.toggle('current-page',parseInt(t.dataset.page,10)===editState.currentPage);\r\n  });\r\n}\r\n\r\nfunction redrawOverlay(){\r\n  var oc=document.getElementById('overlayCanvas');\r\n  var ctx=oc.getContext('2d');\r\n  ctx.clearRect(0,0,oc.width,oc.height);\r\n  var anns=editState.annotations[editState.currentPage]||[];\r\n  anns.forEach(function(ann){\r\n    if(ann.type==='text'){\r\n      ctx.font=ann.fontSize+'px IBM Plex Sans, sans-serif';\r\n      ctx.fillStyle=ann.color;\r\n      ctx.fillText(ann.text,ann.x,ann.y);\r\n    }else if(ann.type==='draw'){\r\n      if(!ann.strokes||!ann.strokes.length)return;\r\n      ctx.beginPath();ctx.strokeStyle=ann.color;ctx.lineWidth=2;ctx.lineCap='round';ctx.lineJoin='round';\r\n      ann.strokes.forEach(function(s){ctx.moveTo(s[0].x,s[0].y);s.forEach(function(pt){ctx.lineTo(pt.x,pt.y);});});\r\n      ctx.stroke();\r\n    }else if(ann.type==='highlight'){\r\n      ctx.fillStyle=hexToRgba(ann.color,0.35);\r\n      ctx.fillRect(ann.x,ann.y,ann.w,ann.h);\r\n    }\r\n  });\r\n}\r\n\r\nfunction hexToRgba(hex,alpha){\r\n  var r=parseInt(hex.slice(1,3),16),g=parseInt(hex.slice(3,5),16),b=parseInt(hex.slice(5,7),16);\r\n  return 'rgba('+r+','+g+','+b+','+alpha+')';\r\n}\r\n\r\nfunction getCanvasPoint(e,canvas){\r\n  var r=canvas.getBoundingClientRect();\r\n  var scaleX=canvas.width\/r.width,scaleY=canvas.height\/r.height;\r\n  return{x:(e.clientX-r.left)*scaleX,y:(e.clientY-r.top)*scaleY};\r\n}\r\n\r\nfunction updateOverlayCursor(){\r\n  var oc=document.getElementById('overlayCanvas');\r\n  var cursors={select:'default',text:'text',draw:'crosshair',highlight:'crosshair'};\r\n  oc.style.cursor=cursors[editState.activeTool]||'default';\r\n}\r\n\r\n\/\/ Highlight drag state\r\nvar hlDrag={active:false,startX:0,startY:0};\r\n\r\nfunction onOverlayDown(e){\r\n  var oc=document.getElementById('overlayCanvas');\r\n  if(editState.activeTool==='draw'){\r\n    editState.drawActive=true;\r\n    editState.currentStroke=[];\r\n    var pt=getCanvasPoint(e,oc);\r\n    editState.currentStroke.push(pt);\r\n  }else if(editState.activeTool==='highlight'){\r\n    var pt=getCanvasPoint(e,oc);\r\n    hlDrag.active=true;hlDrag.startX=pt.x;hlDrag.startY=pt.y;\r\n  }\r\n}\r\nfunction onOverlayMove(e){\r\n  var oc=document.getElementById('overlayCanvas');\r\n  if(editState.activeTool==='draw'&&editState.drawActive){\r\n    var pt=getCanvasPoint(e,oc);\r\n    editState.currentStroke.push(pt);\r\n    \/\/ live draw\r\n    var ctx=oc.getContext('2d');\r\n    redrawOverlay();\r\n    ctx.beginPath();ctx.strokeStyle=editState.activeColor;ctx.lineWidth=2;ctx.lineCap='round';ctx.lineJoin='round';\r\n    var s=editState.currentStroke;\r\n    ctx.moveTo(s[0].x,s[0].y);s.forEach(function(p){ctx.lineTo(p.x,p.y);});ctx.stroke();\r\n  }else if(editState.activeTool==='highlight'&&hlDrag.active){\r\n    var pt=getCanvasPoint(e,oc);\r\n    redrawOverlay();\r\n    var ctx=oc.getContext('2d');\r\n    ctx.fillStyle=hexToRgba(editState.activeColor,0.35);\r\n    ctx.fillRect(hlDrag.startX,hlDrag.startY,pt.x-hlDrag.startX,pt.y-hlDrag.startY);\r\n  }\r\n}\r\nfunction onOverlayUp(e){\r\n  var oc=document.getElementById('overlayCanvas');\r\n  if(editState.activeTool==='draw'&&editState.drawActive){\r\n    editState.drawActive=false;\r\n    if(editState.currentStroke&&editState.currentStroke.length>1){\r\n      pushUndo();\r\n      var anns=editState.annotations[editState.currentPage]||(editState.annotations[editState.currentPage]=[]);\r\n      anns.push({type:'draw',strokes:[editState.currentStroke],color:editState.activeColor});\r\n      editState.currentStroke=null;\r\n      redrawOverlay();\r\n    }\r\n  }else if(editState.activeTool==='highlight'&&hlDrag.active){\r\n    var pt=getCanvasPoint(e,oc);\r\n    hlDrag.active=false;\r\n    var w=pt.x-hlDrag.startX,h=pt.y-hlDrag.startY;\r\n    if(Math.abs(w)>5&&Math.abs(h)>5){\r\n      pushUndo();\r\n      var anns=editState.annotations[editState.currentPage]||(editState.annotations[editState.currentPage]=[]);\r\n      anns.push({type:'highlight',x:hlDrag.startX,y:hlDrag.startY,w:w,h:h,color:editState.activeColor});\r\n      redrawOverlay();\r\n    }\r\n  }\r\n}\r\nfunction onOverlayClick(e){\r\n  if(editState.activeTool==='text'){\r\n    var oc=document.getElementById('overlayCanvas');\r\n    var pt=getCanvasPoint(e,oc);\r\n    var float=document.getElementById('textFloat');\r\n    \/\/ position relative to edit-area\r\n    var area=document.getElementById('editArea');\r\n    var ar=area.getBoundingClientRect();\r\n    float.style.display='block';\r\n    float.style.left=Math.min(e.clientX-ar.left,ar.width-200)+'px';\r\n    float.style.top=(e.clientY-ar.top)+'px';\r\n    float._px=pt.x;float._py=pt.y;\r\n    document.getElementById('textInput').value='';\r\n    document.getElementById('textInput').focus();\r\n  }\r\n}\r\nfunction commitText(){\r\n  var float=document.getElementById('textFloat');\r\n  var text=document.getElementById('textInput').value.trim();\r\n  if(text){\r\n    pushUndo();\r\n    var anns=editState.annotations[editState.currentPage]||(editState.annotations[editState.currentPage]=[]);\r\n    anns.push({type:'text',x:float._px,y:float._py,text:text,color:editState.activeColor,fontSize:editState.activeFontSize});\r\n    redrawOverlay();\r\n  }\r\n  float.style.display='none';\r\n}\r\n\r\nfunction pushUndo(){\r\n  var snap=JSON.parse(JSON.stringify(editState.annotations[editState.currentPage]||[]));\r\n  editState.undoStack.push({page:editState.currentPage,snap:snap});\r\n  if(editState.undoStack.length>50)editState.undoStack.shift();\r\n}\r\nfunction doUndo(){\r\n  if(!editState.undoStack.length)return;\r\n  var last=editState.undoStack.pop();\r\n  editState.annotations[last.page]=last.snap;\r\n  if(last.page===editState.currentPage)redrawOverlay();\r\n}\r\n\r\nasync function saveEditPdf(){\r\n  var btn=document.getElementById('editSaveBtn');\r\n  var statusEl=document.getElementById('editStatus');\r\n  btn.disabled=true;statusEl.textContent='Saving\u2026';\r\n  try{\r\n    \/\/ Start from the live edited doc (has rotations + deletions applied),\r\n    \/\/ serialise it to bytes, then reload a fresh copy to bake annotations onto.\r\n    \/\/ Loading a new copy avoids mutating editState.pdfLib so the user can save again.\r\n    var liveBytes=await editState.pdfLib.save();\r\n    var doc=await PDFLib.PDFDocument.load(liveBytes);\r\n    \/\/ Embed a standard font\r\n    var font=await doc.embedFont(PDFLib.StandardFonts.Helvetica);\r\n\r\n    var allPages=doc.getPages();\r\n    var pageKeys=Object.keys(editState.annotations);\r\n    for(var ki=0;ki<pageKeys.length;ki++){\r\n      var pageNum=parseInt(pageKeys[ki],10);\r\n      var anns=editState.annotations[pageNum];\r\n      if(!anns||!anns.length)continue;\r\n      var page=allPages[pageNum-1];\r\n      if(!page)continue;\r\n      var ph=page.getHeight();\r\n      var w=page.getWidth();\r\n      \/\/ pdfLib uses PDF coordinate system (y from bottom)\r\n      \/\/ canvas Y is from top; renderCanvas has size proportional to viewport\r\n      var rc=document.getElementById('renderCanvas');\r\n      var scaleX=w\/(rc.width||1),scaleY=ph\/(rc.height||1);\r\n\r\n      for(var ai=0;ai<anns.length;ai++){\r\n        var ann=anns[ai];\r\n        if(ann.type==='text'){\r\n          var pdfY=ph - ann.y*scaleY;\r\n          var hexCol=ann.color||'#000000';\r\n          var rgb={r:parseInt(hexCol.slice(1,3),16)\/255,g:parseInt(hexCol.slice(3,5),16)\/255,b:parseInt(hexCol.slice(5,7),16)\/255};\r\n          page.drawText(ann.text,{x:ann.x*scaleX,y:pdfY-ann.fontSize*scaleY,font:font,size:(ann.fontSize||14)*Math.min(scaleX,scaleY),color:PDFLib.rgb(rgb.r,rgb.g,rgb.b)});\r\n        }else if(ann.type==='highlight'){\r\n          var x=ann.x*scaleX,y=ph-(ann.y+ann.h)*scaleY;\r\n          var hw=ann.w*scaleX,hh=Math.abs(ann.h*scaleY);\r\n          var hc=ann.color||'#ffb84d';\r\n          var hrgb={r:parseInt(hc.slice(1,3),16)\/255,g:parseInt(hc.slice(3,5),16)\/255,b:parseInt(hc.slice(5,7),16)\/255};\r\n          page.drawRectangle({x:x,y:y,width:hw,height:hh,color:PDFLib.rgb(hrgb.r,hrgb.g,hrgb.b),opacity:0.35});\r\n        }else if(ann.type==='draw'&&ann.strokes){\r\n          var dc=ann.color||'#ff6a2b';\r\n          var drgb={r:parseInt(dc.slice(1,3),16)\/255,g:parseInt(dc.slice(3,5),16)\/255,b:parseInt(dc.slice(5,7),16)\/255};\r\n          ann.strokes.forEach(function(stroke){\r\n            if(stroke.length<2)return;\r\n            for(var si=0;si<stroke.length-1;si++){\r\n              var x1=stroke[si].x*scaleX,y1=ph-stroke[si].y*scaleY;\r\n              var x2=stroke[si+1].x*scaleX,y2=ph-stroke[si+1].y*scaleY;\r\n              page.drawLine({start:{x:x1,y:y1},end:{x:x2,y:y2},thickness:2,color:PDFLib.rgb(drgb.r,drgb.g,drgb.b)});\r\n            }\r\n          });\r\n        }\r\n      }\r\n    }\r\n    var bytes=await doc.save();\r\n    var blob=new Blob([bytes],{type:'application\/pdf'});\r\n    var url=URL.createObjectURL(blob);\r\n    dl(url,editState.name+'-edited.pdf');\r\n    setTimeout(function(){URL.revokeObjectURL(url);},5000);\r\n    statusEl.textContent='Saved \u2014 '+formatBytes(bytes.length);\r\n  }catch(e){\r\n    statusEl.textContent='Error: '+e.message;console.error(e);\r\n  }\r\n  btn.disabled=false;\r\n}\r\n\r\n\/\/ ===================================================================\r\n\/\/ Init\r\n\/\/ ===================================================================\r\nfunction init(){\r\n  if(typeof pdfjsLib!=='undefined')pdfjsLib.GlobalWorkerOptions.workerSrc='https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/pdf.js\/2.16.105\/pdf.worker.min.js';\r\n  wireTabs();\r\n  initSplit();\r\n  initMerge();\r\n  initEdit();\r\n}\r\ndocument.addEventListener('DOMContentLoaded',init);\r\n})();\r\n\r\n<\/script>\r\n<\/body>\r\n<\/html>\r\n\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_eb_attr":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[76],"tags":[],"class_list":["post-4614","post","type-post","status-publish","format-standard","hentry","category-tools"],"_links":{"self":[{"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/posts\/4614","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/comments?post=4614"}],"version-history":[{"count":11,"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/posts\/4614\/revisions"}],"predecessor-version":[{"id":4616,"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/posts\/4614\/revisions\/4616"}],"wp:attachment":[{"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/media?parent=4614"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/categories?post=4614"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rajmedical.co.in\/hi\/wp-json\/wp\/v2\/tags?post=4614"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}