{"id":48,"date":"2026-09-13T16:24:58","date_gmt":"2026-09-13T16:24:58","guid":{"rendered":"https:\/\/iuravent.es\/?page_id=48"},"modified":"2026-09-13T19:57:58","modified_gmt":"2026-09-13T19:57:58","slug":"protector-documental","status":"publish","type":"page","link":"https:\/\/iuravent.es\/index.php\/protector-documental\/","title":{"rendered":"Protector documental"},"content":{"rendered":"\n<style>body:has(#iuravent-protector){padding:0}body:has(#iuravent-protector) .wp-site-blocks{padding:0}body:has(#iuravent-protector) .wp-site-blocks>header,body:has(#iuravent-protector) .wp-site-blocks>footer,body:has(#iuravent-protector) .wp-block-post-title{display:none}body:has(#iuravent-protector) main,body:has(#iuravent-protector) .entry-content{max-width:none!important;width:100%!important;margin:0!important;padding:0!important}#iuravent-protector{display:block;width:100%;max-width:none;border:0;min-height:1200px;margin:0}<\/style>\n<iframe id=\"iuravent-protector\" title=\"IURAVENT \u00b7 Protector documental\" sandbox=\"allow-scripts allow-downloads allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox\" referrerpolicy=\"no-referrer\" srcdoc=\"&lt;!doctype html&gt;&lt;html lang=&quot;es&quot;&gt;&lt;head&gt;&lt;meta charset=&quot;utf-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width,initial-scale=1&quot;&gt;&lt;meta name=&quot;referrer&quot; content=&quot;no-referrer&quot;&gt;&lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;default-src &#x27;none&#x27;; script-src &#x27;unsafe-inline&#x27; https:\/\/cdn.jsdelivr.net; worker-src blob:; connect-src https:\/\/cdn.jsdelivr.net; img-src blob: data: https:\/\/iuravent.es; font-src blob: data:; style-src &#x27;unsafe-inline&#x27;; base-uri &#x27;none&#x27;; form-action &#x27;none&#x27;; object-src &#x27;none&#x27;&quot;&gt;&lt;title&gt;IURAVENT \u00b7 Protector documental&lt;\/title&gt;\n&lt;style&gt;\n:root{--navy:#0b1723;--gold:#b6a071;--paper:#f5f2eb;--ink:#25313a;--muted:#58636b;--line:#d6d0c3}*{box-sizing:border-box}body{margin:0;background:var(--paper);color:var(--ink);font:16px\/1.65 Arial,sans-serif}h1,h2,h3,p{margin:0}h1,h2,h3{font-family:Georgia,serif;font-weight:400;color:var(--navy)}h1{font-size:clamp(34px,5vw,52px);line-height:1.15}h2{font-size:27px;line-height:1.25;margin-bottom:18px}h3{font-size:20px;line-height:1.35;margin-bottom:12px}a{color:inherit}button,input,select{font:inherit}button,.button{min-height:44px;padding:10px 16px;border:1px solid #a69a84;border-radius:2px;background:white;color:var(--navy);cursor:pointer;text-decoration:none;display:inline-flex;align-items:center;justify-content:center;text-align:center;gap:8px;line-height:1.35}button:hover,.button:hover{background:#eee8dc}button:disabled{opacity:.42;cursor:not-allowed}.primary{background:var(--navy);color:white;border-color:var(--navy)}.primary:hover{background:#233646}.quiet{font-size:14px}.selected,button[aria-pressed=true]{background:var(--navy);color:white;border-color:var(--navy)}:focus-visible{outline:3px solid #967b45;outline-offset:3px}input:not([type=checkbox]),select{padding:10px 12px;min-height:44px;border:1px solid #b7bdc0;border-radius:2px;background:white;color:var(--ink);width:100%;min-width:0}input[type=checkbox]{width:20px;height:20px;accent-color:var(--navy);vertical-align:middle;margin:0 8px 0 0}label{font-size:14px;display:block}label input,label select{margin-top:5px}.check{display:flex;align-items:flex-start;gap:4px}.check input{flex:none;margin-top:3px}.wrap{width:min(1180px,90%);margin:auto}header{background:var(--navy);color:var(--paper);border-bottom:1px solid #b6a07155}header .wrap{display:flex;align-items:center;justify-content:space-between;padding:18px 0;gap:20px}.brand{font:24px Georgia,serif;letter-spacing:4px;text-decoration:none;color:#d2bf96}.brand img{width:38px;height:38px;object-fit:cover;vertical-align:middle;margin-right:10px}.back{font-size:13px;text-decoration:none}.intro{padding:50px 0 30px}.eyebrow{font-size:11px;letter-spacing:2.5px;color:#8a7142;text-transform:uppercase;margin-bottom:14px}.subtitle{font:23px\/1.4 Georgia,serif;margin:17px 0}.lead{max-width:790px;color:var(--muted)}.notice{border-left:2px solid var(--gold);padding:14px 20px;margin:22px 0;background:#eeeae2;font-size:14px}.notice strong{display:block;color:var(--navy);margin-bottom:4px}.privacy{background:var(--navy);color:#d8dce0;padding:17px 22px;font-size:14px;margin:24px 0}.privacy strong{color:#d2bf96;display:block;margin-bottom:3px}.panel{background:#fffdf9;border:1px solid var(--line);padding:26px;margin-bottom:22px}.types{display:grid;grid-template-columns:repeat(5,1fr);gap:10px;margin:16px 0 28px}.types button{font-size:14px;min-height:68px}.drop{padding:28px;border:1px dashed #a99876;text-align:center;background:#f7f5ef}.drop.drag{outline:3px solid var(--gold)}.drop input{max-width:410px;margin:12px auto;display:block}.help{font-size:13px;color:var(--muted);margin-top:10px}.status{padding:12px 0;min-height:45px;font-size:14px;overflow-wrap:anywhere}.status.error{color:#883b30}.toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px}.toolbar select{width:auto}.toolbar label{display:flex;align-items:center;gap:8px}.toolbar button{font-size:13px}.workspace{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:24px}.workspace:has(.side[hidden]){grid-template-columns:1fr}.viewer{height:600px;max-height:75vh;min-height:300px;overflow:auto;background:#e4e3df;border:1px solid #c5c9cb;overscroll-behavior:contain;position:relative;padding:16px}.stage{position:relative;line-height:0;touch-action:none;margin:0 auto;box-shadow:0 3px 14px #0002;max-width:none}canvas{display:block;width:100%;height:100%}.overlay{position:absolute;inset:0;touch-action:none}.mark{position:absolute;border:2px solid #a0854a;background:transparent;cursor:move;touch-action:none}.mark.selected{border-color:#f0c367;outline:1px solid #0b1723}.mark.pending{background:#b6a07155;border:2px dashed #725824}.handle{width:17px;height:17px;background:#f4d08a;border:1px solid #182838;position:absolute;right:-9px;bottom:-9px;cursor:nwse-resize}.mark.watermark{border-style:dashed;background:#b6a07122}.side .panel{padding:18px;margin-bottom:16px}.side .toolbar{margin:12px 0 0}.side .toolbar button{flex:1}.coordinates{display:grid;grid-template-columns:1fr 1fr;gap:9px;margin-top:12px}.marks{display:grid;gap:6px;max-height:170px;overflow:auto}.marks button{justify-content:flex-start;font-size:13px;min-height:40px}.field-help{font-size:13px;line-height:1.7;margin:12px 0;color:var(--muted)}details{border-bottom:1px solid var(--line);padding:12px 0}summary{cursor:pointer;font-size:14px;color:var(--navy)}.water-fields{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:14px}.water-fields .wide{grid-column:1\/-1}.water-section{margin-top:24px;border-top:1px solid var(--line);padding-top:24px}.review-note{background:#eee9dd;padding:14px 18px;margin-bottom:14px;font-size:14px}.bottom-actions{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:22px}.progress{font-size:13px;color:var(--muted)}footer{padding:35px 0 50px;border-top:1px solid var(--line);margin-top:36px}footer p{font-size:13px;color:var(--muted);max-width:950px;margin-bottom:10px}[hidden]{display:none!important}.orientation{font-size:12px;color:var(--muted)}#result{border-top:3px solid var(--gold)}#result h2{margin-bottom:12px}dialog{max-width:440px;width:90%;border:1px solid var(--gold);padding:26px;background:var(--paper);color:var(--ink)}dialog::backdrop{background:#07142199}.redaction-count{font-size:13px}.field-picker{margin:10px 0}.water-reminder{font-size:13px;color:#62605b;margin:14px 0}.page-review{margin-left:auto;font-size:13px}noscript{display:block;padding:30px;color:#8d3328}\n@media(max-width:900px){.workspace{grid-template-columns:1fr}.side{display:grid;grid-template-columns:1fr 1fr;gap:16px}.types{grid-template-columns:repeat(3,1fr)}.viewer{height:500px}}\n@media(max-width:600px){.wrap{width:92%}.intro{padding-top:30px}.panel{padding:17px}.types{grid-template-columns:1fr 1fr;gap:8px}.types button:last-child{grid-column:1\/-1;min-height:44px}.side{grid-template-columns:1fr}.water-fields{grid-template-columns:1fr}.water-fields .wide{grid-column:auto}.viewer{padding:8px;height:420px}.toolbar{gap:6px}.toolbar button{padding:9px 11px}.bottom-actions&gt;*{width:100%}.subtitle{font-size:21px}.brand{font-size:21px}.brand img{width:30px;height:30px}.back{font-size:12px}.privacy{padding:16px}.page-review{margin:0;width:100%}}\n&lt;\/style&gt;&lt;\/head&gt;&lt;body&gt;\n&lt;header&gt;&lt;div class=&quot;wrap&quot;&gt;&lt;a class=&quot;brand&quot; href=&quot;https:\/\/iuravent.es\/&quot; target=&quot;_top&quot;&gt;&lt;img src=&quot;https:\/\/iuravent.es\/wp-content\/uploads\/2026\/09\/Logo-IURAVENT.png&quot; alt=&quot;&quot;&gt;IURAVENT&lt;\/a&gt;&lt;a class=&quot;back&quot; href=&quot;https:\/\/iuravent.es\/&quot; target=&quot;_top&quot;&gt;\u2190 Volver a la web&lt;\/a&gt;&lt;\/div&gt;&lt;\/header&gt;\n&lt;main class=&quot;wrap&quot;&gt;&lt;section class=&quot;intro&quot;&gt;&lt;p class=&quot;eyebrow&quot;&gt;Herramientas \u00b7 IURAVENT&lt;\/p&gt;&lt;h1&gt;Protector documental&lt;\/h1&gt;&lt;p class=&quot;subtitle&quot;&gt;Proteja la informaci\u00f3n que no necesita compartir.&lt;\/p&gt;&lt;p class=&quot;lead&quot;&gt;Genere una copia protegida de sus documentos antes de facilitarlos a terceros. Seleccione qu\u00e9 informaci\u00f3n desea ocultar, a\u00f1ada una finalidad de uso y descargue una nueva copia protegida.&lt;\/p&gt;&lt;div class=&quot;notice&quot;&gt;&lt;strong&gt;Antes de compartir un documento&lt;\/strong&gt;Compruebe qu\u00e9 informaci\u00f3n necesita realmente el destinatario. En muchas situaciones puede no ser necesario facilitar todos los datos contenidos en un documento.&lt;\/div&gt;&lt;div class=&quot;privacy&quot;&gt;&lt;strong&gt;Privacidad por dise\u00f1o&lt;\/strong&gt;El documento se procesa localmente en su dispositivo. IURAVENT no recibe ni almacena el archivo.&lt;\/div&gt;&lt;\/section&gt;\n&lt;noscript&gt;Active JavaScript para utilizar esta herramienta. No seleccione documentos si la herramienta no se ha iniciado.&lt;\/noscript&gt;\n&lt;div id=&quot;status&quot; role=&quot;status&quot; aria-live=&quot;polite&quot; class=&quot;status&quot;&gt;Preparando la herramienta\u2026&lt;\/div&gt;\n&lt;section class=&quot;panel&quot; id=&quot;start&quot;&gt;&lt;h2&gt;1. Seleccione su documento&lt;\/h2&gt;&lt;p class=&quot;help&quot; style=&quot;margin-bottom:18px&quot;&gt;Marque manualmente las zonas que desea ocultar en cada p\u00e1gina y descargue una copia protegida. La herramienta no detecta ni oculta datos autom\u00e1ticamente.&lt;\/p&gt;&lt;div class=&quot;drop&quot; id=&quot;drop&quot;&gt;&lt;p&gt;Arrastre su documento aqu\u00ed o seleccione un archivo&lt;\/p&gt;&lt;label for=&quot;file&quot;&gt;Seleccionar documento&lt;\/label&gt;&lt;input id=&quot;file&quot; type=&quot;file&quot; accept=&quot;.jpg,.jpeg,.png,.pdf,image\/jpeg,image\/png,application\/pdf&quot; disabled&gt;&lt;p class=&quot;help&quot;&gt;El archivo permanece en su dispositivo.&lt;\/p&gt;&lt;p class=&quot;help&quot;&gt;JPG, JPEG, PNG o PDF \u00b7 M\u00e1ximo 15 MB y 50 p\u00e1ginas. Im\u00e1genes de hasta 25 megap\u00edxeles. PDF sin contrase\u00f1a.&lt;\/p&gt;&lt;p class=&quot;help&quot;&gt;Para documentos extensos, recomendamos ordenador. Las p\u00e1ginas se cargan al abrirlas y la copia final se genera de forma secuencial.&lt;\/p&gt;&lt;\/div&gt;&lt;p class=&quot;help&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;demo&quot; class=&quot;quiet&quot;&gt;Probar con un documento ficticio&lt;\/button&gt;&lt;\/p&gt;&lt;p class=&quot;help&quot;&gt;La copia se genera como imagen plana. No conserva firmas digitales, texto seleccionable ni elementos interactivos del original. Revise siempre su legibilidad.&lt;\/p&gt;&lt;\/section&gt;\n&lt;section id=&quot;editor&quot; hidden&gt;&lt;h2 id=&quot;mode-title&quot;&gt;2. Seleccione las zonas que desea proteger&lt;\/h2&gt;&lt;div id=&quot;review-note&quot; class=&quot;review-note&quot; hidden&gt;Est\u00e1 en vista previa. Para ocultar m\u00e1s datos, pulse \u00abEditar esta p\u00e1gina\u00bb, tambi\u00e9n en la segunda p\u00e1gina y siguientes. Solo se ocultar\u00e1n las zonas marcadas; los dem\u00e1s datos seguir\u00e1n visibles. La marca de agua indica una finalidad, pero no impide por s\u00ed sola otros usos de la copia.&lt;\/div&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;page-prev&quot;&gt;\u2190 P\u00e1gina anterior&lt;\/button&gt;&lt;label&gt;P\u00e1gina &lt;select id=&quot;page&quot; aria-label=&quot;P\u00e1gina del documento&quot;&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;button type=&quot;button&quot; id=&quot;page-next&quot;&gt;P\u00e1gina siguiente \u2192&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;edit-current&quot; class=&quot;primary&quot; hidden&gt;Editar esta p\u00e1gina&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;zoom-out&quot; aria-label=&quot;Reducir documento&quot;&gt;\u2212&lt;\/button&gt;&lt;span id=&quot;zoom-label&quot; class=&quot;quiet&quot;&gt;100 %&lt;\/span&gt;&lt;button type=&quot;button&quot; id=&quot;zoom-in&quot; aria-label=&quot;Ampliar documento&quot;&gt;+&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;fit&quot;&gt;Ajustar&lt;\/button&gt;&lt;span id=&quot;orientation&quot; class=&quot;orientation&quot;&gt;&lt;\/span&gt;&lt;span id=&quot;page-review&quot; class=&quot;page-review&quot;&gt;&lt;\/span&gt;&lt;\/div&gt;\n&lt;p id=&quot;page-help&quot; class=&quot;help&quot; style=&quot;margin:0 0 16px&quot;&gt;&lt;\/p&gt;&lt;div class=&quot;workspace&quot;&gt;&lt;div&gt;&lt;div class=&quot;toolbar&quot; id=&quot;edit-tools&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;draw&quot; aria-pressed=&quot;true&quot;&gt;Seleccionar zona&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;pan&quot; aria-pressed=&quot;false&quot;&gt;Mover documento&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;hide-zone&quot; disabled&gt;Ocultar selecci\u00f3n&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;undo&quot; disabled&gt;Deshacer&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;redo&quot; disabled&gt;Rehacer&lt;\/button&gt;&lt;\/div&gt;&lt;div class=&quot;viewer&quot; id=&quot;viewer&quot;&gt;&lt;div class=&quot;stage&quot; id=&quot;stage&quot;&gt;&lt;canvas id=&quot;canvas&quot; aria-label=&quot;Vista previa de la p\u00e1gina&quot;&gt;&lt;\/canvas&gt;&lt;div class=&quot;overlay&quot; id=&quot;overlay&quot; role=&quot;group&quot; aria-label=&quot;Zonas del documento&quot;&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;p id=&quot;instructions&quot; class=&quot;help&quot;&gt;Arrastre sobre el documento para dibujar una zona y pulse \u00abOcultar selecci\u00f3n\u00bb. Toque una zona para moverla; use su esquina inferior derecha para cambiar el tama\u00f1o. Tambi\u00e9n puede ajustar sus medidas en el panel.&lt;\/p&gt;&lt;div class=&quot;bottom-actions&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;review&quot; class=&quot;primary&quot;&gt;Revisar copia protegida&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;back-edit&quot; hidden&gt;Volver a editar&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;reset&quot;&gt;Restablecer documento&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;clear&quot;&gt;Cerrar documento&lt;\/button&gt;&lt;\/div&gt;&lt;\/div&gt;\n&lt;aside class=&quot;side&quot; id=&quot;side&quot;&gt;&lt;section class=&quot;panel&quot;&gt;&lt;h3&gt;Zonas de esta p\u00e1gina&lt;\/h3&gt;&lt;label for=&quot;zone-style&quot;&gt;Aspecto de la zona&lt;select id=&quot;zone-style&quot; aria-describedby=&quot;style-help&quot;&gt;&lt;option value=&quot;black&quot;&gt;Negro&lt;\/option&gt;&lt;option value=&quot;white&quot;&gt;Blanco&lt;\/option&gt;&lt;option value=&quot;blur&quot;&gt;Borroso&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;p id=&quot;style-help&quot; class=&quot;help&quot;&gt;Se aplica a la zona seleccionada o a la siguiente que marque.&lt;\/p&gt;&lt;p id=&quot;blur-warning&quot; class=&quot;notice&quot; role=&quot;status&quot; hidden&gt;El desenfoque no garantiza que los datos sean ilegibles. Para informaci\u00f3n sensible, utilice negro o blanco.&lt;\/p&gt;&lt;p id=&quot;count&quot; class=&quot;redaction-count&quot;&gt;Sin zonas ocultas.&lt;\/p&gt;&lt;div id=&quot;marks&quot; class=&quot;marks&quot;&gt;&lt;\/div&gt;&lt;button type=&quot;button&quot; id=&quot;add-center&quot; class=&quot;quiet&quot;&gt;A\u00f1adir zona con controles&lt;\/button&gt;&lt;div id=&quot;coords&quot; hidden&gt;&lt;div class=&quot;coordinates&quot;&gt;&lt;label&gt;Posici\u00f3n X (%)&lt;input id=&quot;rx&quot; type=&quot;number&quot; min=&quot;0&quot; max=&quot;99&quot; step=&quot;0.1&quot;&gt;&lt;\/label&gt;&lt;label&gt;Posici\u00f3n Y (%)&lt;input id=&quot;ry&quot; type=&quot;number&quot; min=&quot;0&quot; max=&quot;99&quot; step=&quot;0.1&quot;&gt;&lt;\/label&gt;&lt;label&gt;Ancho (%)&lt;input id=&quot;rw&quot; type=&quot;number&quot; min=&quot;0.2&quot; max=&quot;100&quot; step=&quot;0.1&quot;&gt;&lt;\/label&gt;&lt;label&gt;Alto (%)&lt;input id=&quot;rh&quot; type=&quot;number&quot; min=&quot;0.2&quot; max=&quot;100&quot; step=&quot;0.1&quot;&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;apply-coords&quot;&gt;Aplicar medidas&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;delete&quot;&gt;Eliminar zona&lt;\/button&gt;&lt;\/div&gt;&lt;\/div&gt;&lt;\/section&gt;&lt;\/aside&gt;&lt;\/div&gt;\n&lt;section id=&quot;water-section&quot; class=&quot;panel water-section&quot;&gt;&lt;h2&gt;3. Limitar el uso de la copia&lt;\/h2&gt;&lt;label class=&quot;check&quot;&gt;&lt;input type=&quot;checkbox&quot; id=&quot;water-on&quot;&gt;A\u00f1adir marca de agua&lt;\/label&gt;&lt;div class=&quot;water-fields&quot;&gt;&lt;label class=&quot;wide&quot;&gt;Finalidad de la copia&lt;input id=&quot;purpose&quot; maxlength=&quot;110&quot; placeholder=&quot;Documentaci\u00f3n aportada exclusivamente para expediente 2026\/XXX&quot; autocomplete=&quot;off&quot;&gt;&lt;\/label&gt;&lt;label&gt;Destinatario (opcional)&lt;input id=&quot;recipient&quot; maxlength=&quot;70&quot; autocomplete=&quot;off&quot;&gt;&lt;\/label&gt;&lt;label&gt;Referencia (opcional)&lt;input id=&quot;reference&quot; maxlength=&quot;60&quot; autocomplete=&quot;off&quot;&gt;&lt;\/label&gt;&lt;label&gt;Fecha (opcional)&lt;input id=&quot;water-date&quot; type=&quot;date&quot; autocomplete=&quot;off&quot;&gt;&lt;\/label&gt;&lt;label&gt;Colocaci\u00f3n&lt;select id=&quot;water-position&quot;&gt;&lt;option value=&quot;diagonal&quot;&gt;Diagonal&lt;\/option&gt;&lt;option value=&quot;horizontal&quot;&gt;Horizontal&lt;\/option&gt;&lt;option value=&quot;custom&quot;&gt;En una zona seleccionada&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;\/div&gt;&lt;div class=&quot;toolbar&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;today&quot;&gt;Usar fecha actual&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;place-water&quot; disabled&gt;Seleccionar zona de la marca&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;remove-water-zone&quot; disabled&gt;Quitar zona de la marca&lt;\/button&gt;&lt;\/div&gt;&lt;p class=&quot;water-reminder&quot;&gt;La marca se aplica a todas las p\u00e1ginas. En modo \u00abzona seleccionada\u00bb, marque su posici\u00f3n en cada p\u00e1gina; si no la marca, aparecer\u00e1 centrada. Una marca de agua no garantiza que se respete la finalidad indicada.&lt;\/p&gt;&lt;\/section&gt;\n&lt;section id=&quot;export-panel&quot; class=&quot;panel&quot; hidden&gt;&lt;h2&gt;4. Generar copia protegida&lt;\/h2&gt;&lt;p id=&quot;review-summary&quot; class=&quot;help&quot;&gt;&lt;\/p&gt;&lt;p id=&quot;review-blur-warning&quot; class=&quot;notice&quot; hidden&gt;Esta copia contiene zonas borrosas. El desenfoque no garantiza que los datos sean ilegibles. Para informaci\u00f3n sensible, vuelva a editar y utilice negro o blanco.&lt;\/p&gt;&lt;p id=&quot;export-help&quot; role=&quot;status&quot; aria-live=&quot;polite&quot; class=&quot;notice&quot;&gt;&lt;\/p&gt;&lt;button type=&quot;button&quot; id=&quot;review-next&quot;&gt;Revisar siguiente p\u00e1gina pendiente \u2192&lt;\/button&gt;&lt;label class=&quot;check&quot; style=&quot;margin:18px 0&quot;&gt;&lt;input type=&quot;checkbox&quot; id=&quot;reviewed&quot;&gt;He revisado todas las p\u00e1ginas y los datos que siguen visibles.&lt;\/label&gt;&lt;label&gt;Formato de descarga&lt;select id=&quot;format&quot;&gt;&lt;option value=&quot;pdf&quot;&gt;PDF \u00b7 todas las p\u00e1ginas&lt;\/option&gt;&lt;option value=&quot;png&quot;&gt;PNG \u00b7 p\u00e1gina actual&lt;\/option&gt;&lt;\/select&gt;&lt;\/label&gt;&lt;div id=&quot;export-progress&quot; hidden style=&quot;margin-top:18px&quot;&gt;&lt;label for=&quot;export-meter&quot;&gt;Generando copia en su dispositivo&lt;\/label&gt;&lt;progress id=&quot;export-meter&quot; value=&quot;0&quot; max=&quot;1&quot; style=&quot;width:100%;accent-color:#0b1723&quot;&gt;&lt;\/progress&gt;&lt;p id=&quot;export-status&quot; role=&quot;status&quot; aria-live=&quot;polite&quot; class=&quot;help&quot;&gt;&lt;\/p&gt;&lt;button type=&quot;button&quot; id=&quot;cancel-export&quot;&gt;Cancelar generaci\u00f3n&lt;\/button&gt;&lt;\/div&gt;&lt;div class=&quot;bottom-actions&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;generate&quot; class=&quot;primary&quot; disabled&gt;Generar copia protegida&lt;\/button&gt;&lt;\/div&gt;&lt;\/section&gt;&lt;\/section&gt;\n&lt;section id=&quot;result&quot; class=&quot;panel&quot; hidden&gt;&lt;h2&gt;Su copia protegida est\u00e1 preparada&lt;\/h2&gt;&lt;p id=&quot;result-info&quot;&gt;&lt;\/p&gt;&lt;div class=&quot;bottom-actions&quot;&gt;&lt;a id=&quot;download&quot; class=&quot;button primary&quot;&gt;Descargar copia protegida&lt;\/a&gt;&lt;button type=&quot;button&quot; id=&quot;new-copy&quot;&gt;Crear otra copia&lt;\/button&gt;&lt;\/div&gt;&lt;p class=&quot;help&quot;&gt;El original y los datos de edici\u00f3n se han liberado de la aplicaci\u00f3n. La copia preparada se mantiene solo durante esta sesi\u00f3n; desc\u00e1rguela antes de cerrar o recargar.&lt;\/p&gt;&lt;\/section&gt;\n&lt;footer&gt;&lt;h3&gt;Privacidad y minimizaci\u00f3n de datos&lt;\/h3&gt;&lt;p&gt;IURAVENT Protector documental es una herramienta t\u00e9cnica destinada a facilitar la generaci\u00f3n de copias protegidas de documentos. El usuario decide qu\u00e9 informaci\u00f3n mantiene visible y qu\u00e9 informaci\u00f3n oculta.&lt;\/p&gt;&lt;p&gt;La herramienta no determina qu\u00e9 datos deben facilitarse en cada procedimiento. La informaci\u00f3n necesaria depender\u00e1 de la finalidad, del destinatario y de las obligaciones legales aplicables.&lt;\/p&gt;&lt;p&gt;Antes de proporcionar documentaci\u00f3n personal, compruebe qu\u00e9 informaci\u00f3n es realmente necesaria.&lt;\/p&gt;&lt;p&gt;Una herramienta gratuita de IURAVENT. &lt;a href=&quot;https:\/\/iuravent.es\/?page_id=22&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Pol\u00edtica de Privacidad&lt;\/a&gt;&lt;\/p&gt;&lt;details&gt;&lt;summary&gt;Funcionamiento y l\u00edmites&lt;\/summary&gt;&lt;p style=&quot;margin-top:12px&quot;&gt;Selecci\u00f3n manual, sin OCR autom\u00e1tico. Los archivos se leen en memoria y no se env\u00edan a IURAVENT ni a servicios de tratamiento documental. Para leer PDF se descarga c\u00f3digo de PDF.js desde jsDelivr; el proveedor sirve la biblioteca, no recibe el documento. Esta herramienta no utiliza anal\u00edtica ni guarda archivos en el navegador. En PDF se conserva temporalmente el original en memoria para abrir cada p\u00e1gina bajo demanda; no se guardan im\u00e1genes de todas las p\u00e1ginas a la vez. La copia final puede ocupar hasta 80 MB. La exportaci\u00f3n vuelve a dibujar todas las p\u00e1ginas y descarta el contenido original, sus metadatos, adjuntos y capas. Los datos que no marque permanecer\u00e1n visibles. La copia no equivale al documento original ni conserva su firma digital.&lt;\/p&gt;&lt;\/details&gt;&lt;\/footer&gt;&lt;\/main&gt;\n&lt;dialog id=&quot;confirm-dialog&quot;&gt;&lt;h3 id=&quot;confirm-title&quot;&gt;Confirmar&lt;\/h3&gt;&lt;p id=&quot;confirm-text&quot;&gt;&lt;\/p&gt;&lt;div class=&quot;bottom-actions&quot;&gt;&lt;button type=&quot;button&quot; id=&quot;confirm-cancel&quot;&gt;Cancelar&lt;\/button&gt;&lt;button type=&quot;button&quot; id=&quot;confirm-ok&quot; class=&quot;primary&quot;&gt;Continuar&lt;\/button&gt;&lt;\/div&gt;&lt;\/dialog&gt;\n&lt;script&gt;\n(()=&gt;{&#x27;use strict&#x27;;\nconst $=id=&gt;document.getElementById(id),MAX_BYTES=15*1024*1024,MAX_PAGES=50,MAX_PIXELS=25000000;\nlet defaultStyle=&#x27;black&#x27;,pages=[],idx=0,bitmap=null,selected=null,pending=null,mode=&#x27;draw&#x27;,zoom=1,fitScale=1,reviewing=false,busy=false,outputURL=null,pdfjs=null,loadSerial=0,drag=null,confirmResolve=null,pdfTask=null,pdfDocument=null,cancelExport=false;\nconst ctx=$(&#x27;canvas&#x27;).getContext(&#x27;2d&#x27;,{alpha:false});\nconst watermark=()=&gt;({on:$(&#x27;water-on&#x27;).checked,purpose:$(&#x27;purpose&#x27;).value.trim(),recipient:$(&#x27;recipient&#x27;).value.trim(),reference:$(&#x27;reference&#x27;).value.trim(),date:$(&#x27;water-date&#x27;).value,position:$(&#x27;water-position&#x27;).value});\nfunction status(message,error=false){$(&#x27;status&#x27;).textContent=message;$(&#x27;status&#x27;).classList.toggle(&#x27;error&#x27;,error);}\nfunction make(tag,text){const e=document.createElement(tag);if(text!==undefined)e.textContent=text;return e;}\nfunction dateName(){const d=new Date();return d.getFullYear()+&#x27;-&#x27;+String(d.getMonth()+1).padStart(2,&#x27;0&#x27;)+&#x27;-&#x27;+String(d.getDate()).padStart(2,&#x27;0&#x27;)}\nfunction canvas(w,h){const c=document.createElement(&#x27;canvas&#x27;);c.width=w;c.height=h;return c}\nfunction toBlob(c,type=&#x27;image\/png&#x27;,quality){return new Promise((resolve,reject)=&gt;c.toBlob(b=&gt;b?resolve(b):reject(new Error(&#x27;No se ha podido generar la imagen.&#x27;)),type,quality))}\nconst tick=()=&gt;new Promise(r=&gt;setTimeout(r,0));\nfunction snapshot(){const p=pages[idx];return {rects:p.rects.map(r=&gt;({...r})),water:p.water?{...p.water}:null}}\nfunction remember(){const p=pages[idx];p.undo.push(snapshot());if(p.undo.length&gt;60)p.undo.shift();p.redo=[];invalidate(false)}\nfunction invalidate(all=true){if(all)pages.forEach(p=&gt;p.reviewed=false);else if(pages[idx])pages[idx].reviewed=false;$(&#x27;reviewed&#x27;).checked=false;$(&#x27;generate&#x27;).disabled=true;}\nfunction setBusy(on){busy=on;$(&#x27;demo&#x27;).disabled=on;$(&#x27;file&#x27;).disabled=on;document.querySelectorAll(&#x27;#editor button,#editor select,#editor input&#x27;).forEach(e=&gt;e.disabled=on);if(!on&amp;&amp;pages.length)controls()}\nfunction clearOutput(){if(outputURL){URL.revokeObjectURL(outputURL);outputURL=null}$(&#x27;download&#x27;).removeAttribute(&#x27;href&#x27;);$(&#x27;result&#x27;).hidden=true}\nfunction freeSource(){defaultStyle=&#x27;black&#x27;;$(&#x27;zone-style&#x27;).value=&#x27;black&#x27;;loadSerial++;$(&#x27;export-progress&#x27;).hidden=true;cancelExport=false;const oldTask=pdfTask;pdfTask=null;pdfDocument=null;if(oldTask)oldTask.destroy().catch(()=&gt;{});if(bitmap){bitmap.close();bitmap=null}pages.forEach(p=&gt;{p.blob=null;p.rects=[];p.undo=[];p.redo=[]});pages=[];pending=null;selected=null;drag=null;ctx.clearRect(0,0,$(&#x27;canvas&#x27;).width,$(&#x27;canvas&#x27;).height);$(&#x27;canvas&#x27;).width=1;$(&#x27;canvas&#x27;).height=1;$(&#x27;overlay&#x27;).replaceChildren();$(&#x27;marks&#x27;).replaceChildren();$(&#x27;page&#x27;).replaceChildren();$(&#x27;file&#x27;).value=&#x27;&#x27;;[&#x27;purpose&#x27;,&#x27;recipient&#x27;,&#x27;reference&#x27;,&#x27;water-date&#x27;].forEach(id=&gt;$(id).value=&#x27;&#x27;);$(&#x27;water-on&#x27;).checked=false;$(&#x27;reviewed&#x27;).checked=false;reviewing=false;}\nfunction startOver(){freeSource();clearOutput();$(&#x27;editor&#x27;).hidden=true;$(&#x27;start&#x27;).hidden=false;$(&#x27;file&#x27;).disabled=false;status(&#x27;Seleccione un archivo para empezar.&#x27;);$(&#x27;start&#x27;).scrollIntoView({block:&#x27;start&#x27;});}\nfunction ask(message){$(&#x27;confirm-text&#x27;).textContent=message;$(&#x27;confirm-dialog&#x27;).showModal();return new Promise(r=&gt;confirmResolve=r)}\n$(&#x27;confirm-cancel&#x27;).onclick=()=&gt;{$(&#x27;confirm-dialog&#x27;).close();if(confirmResolve)confirmResolve(false);confirmResolve=null};$(&#x27;confirm-ok&#x27;).onclick=()=&gt;{$(&#x27;confirm-dialog&#x27;).close();if(confirmResolve)confirmResolve(true);confirmResolve=null};$(&#x27;confirm-dialog&#x27;).addEventListener(&#x27;cancel&#x27;,()=&gt;{if(confirmResolve)confirmResolve(false);confirmResolve=null});\nfunction dimensions(bytes,type){const v=new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength);if(type===&#x27;png&#x27;)return [v.getUint32(16),v.getUint32(20)];let i=2;while(i+8&lt;bytes.length){if(bytes[i++]!==255)continue;let marker=bytes[i++];if(marker===216||marker===217)continue;const len=(bytes[i]&lt;&lt;8)+bytes[i+1];if(len&lt;2)break;if([192,193,194,195,197,198,199,201,202,203,205,206,207].includes(marker))return [(bytes[i+5]&lt;&lt;8)+bytes[i+6],(bytes[i+3]&lt;&lt;8)+bytes[i+4]];i+=len}throw Error(&#x27;No se reconocen las dimensiones de la imagen.&#x27;);}\nasync function library(){if(pdfjs)return pdfjs;const base=&#x27;https:\/\/cdn.jsdelivr.net\/npm\/pdfjs-dist@6.3.289\/&#x27;;const lib=await import(base+&#x27;build\/pdf.mjs&#x27;);lib.GlobalWorkerOptions.workerSrc=base+&#x27;build\/pdf.worker.mjs&#x27;;pdfjs=lib;return lib}\nasync function loadFile(file){if(busy||!file)return;clearOutput();setBusy(true);status(&#x27;Comprobando el archivo en su dispositivo\u2026&#x27;);let task=null,source=null,passwordRequired=false;const prepared=[];try{if(file.size&gt;MAX_BYTES||file.size&lt;8)throw Error(&#x27;El archivo debe ocupar entre 8 bytes y 15 MB.&#x27;);let bytes=new Uint8Array(await file.arrayBuffer());const ext=(file.name.split(&#x27;.&#x27;).pop()||&#x27;&#x27;).toLowerCase();let type=bytes[0]===137&amp;&amp;bytes[1]===80&amp;&amp;bytes[2]===78&amp;&amp;bytes[3]===71&amp;&amp;bytes[4]===13&amp;&amp;bytes[5]===10&amp;&amp;bytes[6]===26&amp;&amp;bytes[7]===10?&#x27;png&#x27;:bytes[0]===255&amp;&amp;bytes[1]===216&amp;&amp;bytes[2]===255?&#x27;jpeg&#x27;:new TextDecoder(&#x27;ascii&#x27;).decode(bytes.slice(0,5))===&#x27;%PDF-&#x27;?&#x27;pdf&#x27;:null;if(!type||!(type===&#x27;jpeg&#x27;?[&#x27;jpg&#x27;,&#x27;jpeg&#x27;]: [type]).includes(ext))throw Error(&#x27;El contenido no coincide con un JPG, PNG o PDF v\u00e1lido.&#x27;);if(file.type&amp;&amp;!(type===&#x27;pdf&#x27;?[&#x27;application\/pdf&#x27;]:type===&#x27;png&#x27;?[&#x27;image\/png&#x27;]:[&#x27;image\/jpeg&#x27;]).includes(file.type))throw Error(&#x27;El tipo declarado no coincide con el contenido del archivo.&#x27;);\nif(type===&#x27;pdf&#x27;){status(&#x27;Preparando el lector PDF local\u2026&#x27;);const lib=await library(),base=&#x27;https:\/\/cdn.jsdelivr.net\/npm\/pdfjs-dist@6.3.289\/&#x27;;task=lib.getDocument({data:bytes,isEvalSupported:false,enableXfa:false,stopAtErrors:true,disableAutoFetch:true,disableStream:true,maxImageSize:MAX_PIXELS,canvasMaxAreaInBytes:16000000,verbosity:0,cMapUrl:base+&#x27;cmaps\/&#x27;,standardFontDataUrl:base+&#x27;standard_fonts\/&#x27;,wasmUrl:base+&#x27;wasm\/&#x27;});task.onPassword=()=&gt;{passwordRequired=true;task.destroy();};source=await task.promise;bytes=null;if(source.numPages&gt;MAX_PAGES)throw Error(&#x27;Este PDF supera el l\u00edmite de 50 p\u00e1ginas.&#x27;);if(source.isPureXfa)throw Error(&#x27;Los formularios XFA no se admiten en esta versi\u00f3n.&#x27;);for(let i=0;i&lt;source.numPages;i++)prepared.push({blob:null,w:0,h:0,pw:0,ph:0,rects:[],undo:[],redo:[],water:null,reviewed:false});\n\n}else{const [w,h]=dimensions(bytes,type);if(!w||!h||w*h&gt;MAX_PIXELS||Math.max(w,h)&gt;16000)throw Error(&#x27;La imagen supera 25 megap\u00edxeles o 16.000 p\u00edxeles por lado.&#x27;);const b=await createImageBitmap(new Blob([bytes],{type:type===&#x27;png&#x27;?&#x27;image\/png&#x27;:&#x27;image\/jpeg&#x27;}),{imageOrientation:&#x27;from-image&#x27;});bytes=null;const scale=Math.min(1,2200\/Math.max(b.width,b.height)),c=canvas(Math.round(b.width*scale),Math.round(b.height*scale));const cc=c.getContext(&#x27;2d&#x27;,{alpha:false});cc.fillStyle=&#x27;white&#x27;;cc.fillRect(0,0,c.width,c.height);cc.drawImage(b,0,0,c.width,c.height);b.close();prepared.push({blob:await toBlob(c),w:c.width,h:c.height,pw:c.width*.5,ph:c.height*.5,rects:[],undo:[],redo:[],water:null,reviewed:false});c.width=c.height=1;}\nfreeSource();pages=prepared;pdfTask=task;pdfDocument=source;task=null;source=null;idx=0;$(&#x27;page&#x27;).replaceChildren(...pages.map((p,i)=&gt;{const o=make(&#x27;option&#x27;,&#x27;&#x27;+(i+1)+&#x27; \/ &#x27;+pages.length);o.value=i;return o}));$(&#x27;start&#x27;).hidden=true;$(&#x27;editor&#x27;).hidden=false;reviewing=false;setReview(false);await showPage(0);status(&#x27;Documento preparado localmente. Marque los datos que desea ocultar.&#x27;);$(&#x27;editor&#x27;).scrollIntoView({block:&#x27;start&#x27;});\n}catch(e){if(pages===prepared){freeSource();$(&#x27;editor&#x27;).hidden=true;$(&#x27;start&#x27;).hidden=false;}prepared.forEach(p=&gt;p.blob=null);if(task)await task.destroy().catch(()=&gt;{});status(passwordRequired||(e&amp;&amp;e.name===&#x27;PasswordException&#x27;)?&#x27;Este PDF est\u00e1 protegido con contrase\u00f1a. Utilice una copia sin contrase\u00f1a.&#x27;:e.message||&#x27;No se ha podido abrir el archivo. Utilice un JPG, PNG o PDF est\u00e1ndar sin contrase\u00f1a.&#x27;,true)}finally{$(&#x27;file&#x27;).value=&#x27;&#x27;;setBusy(false)}}\n\/\/ PDF input stays only in its worker; only the displayed\/exported page is rasterized.\nasync function rasterPage(n){const p=pages[n];if(p.blob)return createImageBitmap(p.blob);if(!pdfDocument)throw Error(&#x27;El documento ya est\u00e1 cerrado.&#x27;);const doc=pdfDocument;let pg=null,c=null;try{pg=await doc.getPage(n+1);const v=pg.getViewport({scale:1});if(!Number.isFinite(v.width*v.height)||v.width&lt;=0||v.height&lt;=0)throw Error(&#x27;Una p\u00e1gina tiene dimensiones no v\u00e1lidas.&#x27;);const scale=Math.min(2,2200\/Math.max(v.width,v.height)),view=pg.getViewport({scale});p.w=Math.ceil(view.width);p.h=Math.ceil(view.height);p.pw=v.width;p.ph=v.height;c=canvas(p.w,p.h);await pg.render({canvasContext:c.getContext(&#x27;2d&#x27;,{alpha:false}),viewport:view,annotationMode:pdfjs.AnnotationMode.ENABLE,background:&#x27;rgb(255,255,255)&#x27;,intent:&#x27;display&#x27;}).promise;return await createImageBitmap(c)}finally{if(c)c.width=c.height=1;if(pg)pg.cleanup();if(pdfDocument===doc)await doc.cleanup();}}\nasync function showPage(n){if(!pages[n])return;const serial=++loadSerial;pending=null;selected=null;if(bitmap){bitmap.close();bitmap=null}ctx.clearRect(0,0,$(&#x27;canvas&#x27;).width,$(&#x27;canvas&#x27;).height);$(&#x27;overlay&#x27;).replaceChildren();status(&#x27;Abriendo p\u00e1gina &#x27;+(n+1)+&#x27; de &#x27;+pages.length+&#x27; en su dispositivo\u2026&#x27;);const next=await rasterPage(n);if(serial!==loadSerial){next.close();return}idx=n;bitmap=next;$(&#x27;canvas&#x27;).width=pages[n].w;$(&#x27;canvas&#x27;).height=pages[n].h;zoom=1;if(!reviewing)mode=&#x27;draw&#x27;;fit();if(reviewing)pages[n].reviewed=true;controls();draw();}\n\nfunction fit(){if(!pages.length)return;fitScale=Math.min(1,Math.max(100,$(&#x27;viewer&#x27;).clientWidth-34)\/pages[idx].w,Math.max(100,$(&#x27;viewer&#x27;).clientHeight-34)\/pages[idx].h);size()}\nfunction size(){if(!pages.length)return;const p=pages[idx];$(&#x27;stage&#x27;).style.width=Math.round(p.w*fitScale*zoom)+&#x27;px&#x27;;$(&#x27;stage&#x27;).style.height=Math.round(p.h*fitScale*zoom)+&#x27;px&#x27;;$(&#x27;zoom-label&#x27;).textContent=Math.round(zoom*100)+&#x27; %&#x27;;}\nfunction paintWater(cc,p){const w=watermark();if(!w.on)return;let lines=[];lines.push(w.purpose||&#x27;COPIA PARA USO EXCLUSIVO&#x27;);if(w.recipient)lines.push(&#x27;Destinatario: &#x27;+w.recipient);if(w.reference)lines.push(&#x27;Referencia: &#x27;+w.reference);if(w.date)lines.push(w.date.split(&#x27;-&#x27;).reverse().join(&#x27;\/&#x27;));const box=w.position===&#x27;custom&#x27;&amp;&amp;p.water?p.water:{x:.06,y:.30,w:.88,h:.40};let maxw=box.w*p.w,maxh=box.h*p.h;cc.save();cc.translate((box.x+box.w\/2)*p.w,(box.y+box.h\/2)*p.h);if(w.position===&#x27;diagonal&#x27;){cc.rotate(-Math.PI\/7);maxw=Math.min(p.w*.86,Math.hypot(p.w,p.h)*.72);maxh=p.h*.34;}cc.textAlign=&#x27;center&#x27;;cc.textBaseline=&#x27;middle&#x27;;let font=Math.max(10,Math.min(p.w*.034,maxh\/(lines.length*1.7)));cc.font=&#x27;600 &#x27;+font+&#x27;px Arial&#x27;;const longest=Math.max(...lines.map(t=&gt;cc.measureText(t).width));if(longest&gt;maxw)font*=maxw\/longest;cc.font=&#x27;600 &#x27;+font+&#x27;px Arial&#x27;;cc.fillStyle=&#x27;rgba(35,48,62,0.30)&#x27;;cc.strokeStyle=&#x27;rgba(255,255,255,0.40)&#x27;;cc.lineWidth=Math.max(.5,font*.03);lines.forEach((t,i)=&gt;{const y=(i-(lines.length-1)\/2)*font*1.55;cc.strokeText(t,0,y);cc.fillText(t,0,y)});cc.restore()}\nfunction zoneBounds(r,p){const x=Math.max(0,Math.floor(r.x*p.w)-1),y=Math.max(0,Math.floor(r.y*p.h)-1);return {x,y,w:Math.min(p.w,Math.ceil((r.x+r.w)*p.w)+1)-x,h:Math.min(p.h,Math.ceil((r.y+r.h)*p.h)+1)-y}}\nfunction paintBlur(cc,b,q){if(q.w&lt;=0||q.h&lt;=0)return;const scale=Math.min(1,300\/Math.max(q.w,q.h)),w=Math.max(1,Math.ceil(q.w*scale)),h=Math.max(1,Math.ceil(q.h*scale)),c=canvas(w,h),cx=c.getContext(&#x27;2d&#x27;,{willReadFrequently:true});try{cx.drawImage(b,q.x,q.y,q.w,q.h,0,0,w,h);const im=cx.getImageData(0,0,w,h),a=im.data,tmp=new Uint8ClampedArray(a.length),radius=Math.max(4,Math.min(16,Math.round(Math.max(w,h)*.06))),size=radius*2+1;for(let pass=0;pass&lt;3;pass++){for(let y=0;y&lt;h;y++)for(let k=0;k&lt;3;k++){let sum=0;for(let d=-radius;d&lt;=radius;d++)sum+=a[(y*w+Math.max(0,Math.min(w-1,d)))*4+k];for(let x=0;x&lt;w;x++){tmp[(y*w+x)*4+k]=sum\/size;sum+=a[(y*w+Math.min(w-1,x+radius+1))*4+k]-a[(y*w+Math.max(0,x-radius))*4+k]}}for(let x=0;x&lt;w;x++)for(let k=0;k&lt;3;k++){let sum=0;for(let d=-radius;d&lt;=radius;d++)sum+=tmp[(Math.max(0,Math.min(h-1,d))*w+x)*4+k];for(let y=0;y&lt;h;y++){a[(y*w+x)*4+k]=sum\/size;sum+=tmp[(Math.min(h-1,y+radius+1)*w+x)*4+k]-tmp[(Math.max(0,y-radius)*w+x)*4+k]}}}for(let i=3;i&lt;a.length;i+=4)a[i]=255;cx.putImageData(im,0,0);cc.save();cc.imageSmoothingEnabled=true;cc.drawImage(c,q.x,q.y,q.w,q.h);cc.restore()}finally{c.width=c.height=1}}\nfunction paint(cc,b,p){cc.save();cc.setTransform(1,0,0,1,0,0);cc.globalAlpha=1;cc.globalCompositeOperation=&#x27;source-over&#x27;;cc.fillStyle=&#x27;#fff&#x27;;cc.fillRect(0,0,p.w,p.h);cc.drawImage(b,0,0,p.w,p.h);p.rects.filter(r=&gt;r.style===&#x27;blur&#x27;).forEach(r=&gt;paintBlur(cc,b,zoneBounds(r,p)));paintWater(cc,p);p.rects.filter(r=&gt;r.style!==&#x27;blur&#x27;).forEach(r=&gt;{const q=zoneBounds(r,p);cc.fillStyle=r.style===&#x27;white&#x27;?&#x27;#fff&#x27;:&#x27;#0b1723&#x27;;cc.fillRect(q.x,q.y,q.w,q.h)});cc.restore()}\n\nfunction draw(){if(!bitmap||!pages.length)return;paint(ctx,bitmap,pages[idx]);overlay();}\nfunction overlay(){const root=$(&#x27;overlay&#x27;);root.replaceChildren();if(reviewing)return;const p=pages[idx];p.rects.forEach((r,i)=&gt;addOverlay(r,i,false));if(pending)addOverlay(pending,-1,true);if(watermark().on&amp;&amp;watermark().position===&#x27;custom&#x27;&amp;&amp;p.water)addOverlay(p.water,&#x27;water&#x27;,false)}\nfunction addOverlay(r,key,isPending){const e=make(&#x27;div&#x27;);e.className=&#x27;mark&#x27;+(selected===key?&#x27; selected&#x27;:&#x27;&#x27;)+(isPending?&#x27; pending&#x27;:&#x27;&#x27;)+(key===&#x27;water&#x27;?&#x27; watermark&#x27;:&#x27;&#x27;);e.style.cssText=&#x27;left:&#x27;+r.x*100+&#x27;%;top:&#x27;+r.y*100+&#x27;%;width:&#x27;+r.w*100+&#x27;%;height:&#x27;+r.h*100+&#x27;%;&#x27;;e.dataset.key=key;e.setAttribute(&#x27;aria-label&#x27;,key===&#x27;water&#x27;?&#x27;Zona de la marca de agua&#x27;:isPending?&#x27;Selecci\u00f3n pendiente&#x27;:&#x27;Zona oculta &#x27;+(key+1));if(!isPending){const h=make(&#x27;span&#x27;);h.className=&#x27;handle&#x27;;h.dataset.resize=&#x27;1&#x27;;e.append(h)}$(&#x27;overlay&#x27;).append(e)}\nfunction pageRanges(ns){const out=[];for(let i=0;i&lt;ns.length;i++){const a=ns[i];let b=a;while(i+1&lt;ns.length&amp;&amp;ns[i+1]===b+1)b=ns[++i];out.push(a===b?String(a):a+&#x27;\u2013&#x27;+b)}return out.join(&#x27;, &#x27;)}\nfunction controls(){if(!pages.length)return;if(!busy)$(&#x27;cancel-export&#x27;).disabled=true;const p=pages[idx];$(&#x27;page-prev&#x27;).disabled=busy||idx===0;$(&#x27;page-next&#x27;).disabled=busy||idx===pages.length-1;$(&#x27;page-help&#x27;).textContent=(reviewing?&#x27;VISTA PREVIA \u00b7 Para ocultar datos pulse \u00abEditar esta p\u00e1gina\u00bb. &#x27;:&#x27;EDICI\u00d3N \u00b7 Puede ocultar datos en todas las p\u00e1ginas. &#x27;)+&#x27;P\u00e1gina &#x27;+(idx+1)+&#x27; de &#x27;+pages.length+&#x27;. &#x27;+(pages.length&gt;1?&#x27;Use los botones \u00abP\u00e1gina anterior\u00bb y \u00abP\u00e1gina siguiente\u00bb para recorrer el PDF.&#x27;:&#x27;El archivo contiene una sola p\u00e1gina. Si incluye ambas caras, \u00abAjustar\u00bb permite verla completa; ampl\u00ede para marcar los detalles.&#x27;);const missing=pages.map((p,i)=&gt;p.reviewed?null:i+1).filter(n=&gt;n!==null);$(&#x27;review-next&#x27;).hidden=!missing.length;$(&#x27;review-next&#x27;).disabled=busy;$(&#x27;export-help&#x27;).textContent=missing.length?&#x27;Falta revisar &#x27;+(missing.length===1?&#x27;la p\u00e1gina &#x27;:&#x27;las p\u00e1ginas &#x27;)+pageRanges(missing)+&#x27;. Pulse \u00abRevisar siguiente p\u00e1gina pendiente\u00bb.&#x27;:!$(&#x27;reviewed&#x27;).checked?&#x27;Ha visitado todas las p\u00e1ginas. Marque la casilla de confirmaci\u00f3n que aparece debajo para activar la descarga.&#x27;:&#x27;Todo preparado. Pulse \u00abGenerar copia protegida\u00bb.&#x27;;$(&#x27;undo&#x27;).disabled=busy||!p.undo.length;$(&#x27;redo&#x27;).disabled=busy||!p.redo.length;$(&#x27;hide-zone&#x27;).disabled=busy||!pending||mode===&#x27;water&#x27;;$(&#x27;count&#x27;).textContent=p.rects.length?p.rects.length+&#x27; zona(s) marcada(s).&#x27;:&#x27;Sin zonas marcadas.&#x27;;$(&#x27;orientation&#x27;).textContent=p.w&gt;p.h?&#x27;Horizontal&#x27;:&#x27;Vertical&#x27;;$(&#x27;page-review&#x27;).textContent=reviewing?pages.filter(p=&gt;p.reviewed).length+&#x27; de &#x27;+pages.length+&#x27; p\u00e1ginas revisadas&#x27;:&#x27;&#x27;;$(&#x27;page&#x27;).value=idx;$(&#x27;marks&#x27;).replaceChildren(...p.rects.map((r,i)=&gt;{const b=make(&#x27;button&#x27;,(i+1)+&#x27;. &#x27;+r.label+&#x27; \u00b7 &#x27;+({black:&#x27;Negro&#x27;,white:&#x27;Blanco&#x27;,blur:&#x27;Borroso&#x27;}[r.style||&#x27;black&#x27;]));b.type=&#x27;button&#x27;;b.setAttribute(&#x27;aria-pressed&#x27;,selected===i);b.onclick=()=&gt;{selected=i;pending=null;mode=&#x27;draw&#x27;;controls();draw()};return b}));$(&#x27;coords&#x27;).hidden=selected===null;const r=selected===&#x27;water&#x27;?p.water:p.rects[selected];$(&#x27;zone-style&#x27;).disabled=busy||selected===&#x27;water&#x27;;$(&#x27;zone-style&#x27;).value=selected!==null&amp;&amp;selected!==&#x27;water&#x27;?(r.style||&#x27;black&#x27;):defaultStyle;$(&#x27;blur-warning&#x27;).hidden=$(&#x27;zone-style&#x27;).value!==&#x27;blur&#x27;;$(&#x27;review-blur-warning&#x27;).hidden=!pages.some(pg=&gt;pg.rects.some(z=&gt;z.style===&#x27;blur&#x27;));if(r){[&#x27;x&#x27;,&#x27;y&#x27;,&#x27;w&#x27;,&#x27;h&#x27;].forEach(k=&gt;$(&#x27;r&#x27;+k).value=(r[k]*100).toFixed(1))}$(&#x27;draw&#x27;).setAttribute(&#x27;aria-pressed&#x27;,mode===&#x27;draw&#x27;);$(&#x27;pan&#x27;).setAttribute(&#x27;aria-pressed&#x27;,mode===&#x27;pan&#x27;);$(&#x27;place-water&#x27;).disabled=!$(&#x27;water-on&#x27;).checked||$(&#x27;water-position&#x27;).value!==&#x27;custom&#x27;;$(&#x27;remove-water-zone&#x27;).disabled=!p.water;$(&#x27;generate&#x27;).disabled=!$(&#x27;reviewed&#x27;).checked||!pages.every(p=&gt;p.reviewed)||!bitmap||busy;}\nfunction point(e){const b=$(&#x27;stage&#x27;).getBoundingClientRect();return{x:Math.max(0,Math.min(1,(e.clientX-b.left)\/b.width)),y:Math.max(0,Math.min(1,(e.clientY-b.top)\/b.height))}}\nconst rectBetween=(a,b)=&gt;({x:Math.min(a.x,b.x),y:Math.min(a.y,b.y),w:Math.abs(a.x-b.x),h:Math.abs(a.y-b.y)});\n$(&#x27;overlay&#x27;).addEventListener(&#x27;pointerdown&#x27;,e=&gt;{if(reviewing||busy||!pages.length||e.button&gt;0)return;e.preventDefault();$(&#x27;overlay&#x27;).setPointerCapture(e.pointerId);const at=point(e),el=e.target.closest(&#x27;.mark&#x27;),p=pages[idx];if(mode===&#x27;pan&#x27;){drag={type:&#x27;pan&#x27;,x:e.clientX,y:e.clientY,sx:$(&#x27;viewer&#x27;).scrollLeft,sy:$(&#x27;viewer&#x27;).scrollTop};return}if(el&amp;&amp;!el.classList.contains(&#x27;pending&#x27;)&amp;&amp;mode!==&#x27;water&#x27;){const key=el.dataset.key===&#x27;water&#x27;?&#x27;water&#x27;:Number(el.dataset.key),r=key===&#x27;water&#x27;?p.water:p.rects[key];selected=key;pending=null;remember();drag={type:e.target.dataset.resize?&#x27;resize&#x27;:&#x27;move&#x27;,at,original:{...r},key};}else{selected=null;pending={x:at.x,y:at.y,w:0,h:0};drag={type:mode===&#x27;water&#x27;?&#x27;water&#x27;:&#x27;new&#x27;,at};}controls();overlay()});\n$(&#x27;overlay&#x27;).addEventListener(&#x27;pointermove&#x27;,e=&gt;{if(!drag)return;const at=point(e);if(drag.type===&#x27;pan&#x27;){$(&#x27;viewer&#x27;).scrollLeft=drag.sx-(e.clientX-drag.x);$(&#x27;viewer&#x27;).scrollTop=drag.sy-(e.clientY-drag.y);return}if(drag.type===&#x27;new&#x27;||drag.type===&#x27;water&#x27;){pending=rectBetween(drag.at,at);overlay();return}const p=pages[idx],r=drag.key===&#x27;water&#x27;?p.water:p.rects[drag.key],o=drag.original;if(drag.type===&#x27;move&#x27;){r.x=Math.max(0,Math.min(1-o.w,o.x+at.x-drag.at.x));r.y=Math.max(0,Math.min(1-o.h,o.y+at.y-drag.at.y));}else{r.w=Math.max(.002,Math.min(1-o.x,o.w+at.x-drag.at.x));r.h=Math.max(.002,Math.min(1-o.y,o.h+at.y-drag.at.y));}draw()});\nfunction endDrag(){if(!drag)return;const type=drag.type;drag=null;if(pending&amp;&amp;(pending.w&lt;.002||pending.h&lt;.002))pending=null;if(type===&#x27;water&#x27;&amp;&amp;pending){remember();pages[idx].water={...pending};pending=null;selected=&#x27;water&#x27;;mode=&#x27;draw&#x27;;}controls();draw()}\n$(&#x27;overlay&#x27;).addEventListener(&#x27;pointerup&#x27;,endDrag);$(&#x27;overlay&#x27;).addEventListener(&#x27;pointercancel&#x27;,endDrag);\n$(&#x27;hide-zone&#x27;).onclick=()=&gt;{if(!pending)return;remember();pages[idx].rects.push({...pending,label:&#x27;Zona manual&#x27;,style:defaultStyle});selected=pages[idx].rects.length-1;pending=null;controls();draw()};\n$(&#x27;draw&#x27;).onclick=()=&gt;{mode=&#x27;draw&#x27;;controls()};$(&#x27;pan&#x27;).onclick=()=&gt;{mode=&#x27;pan&#x27;;pending=null;controls();draw()};\n$(&#x27;zone-style&#x27;).onchange=()=&gt;{const value=$(&#x27;zone-style&#x27;).value;if(![&#x27;black&#x27;,&#x27;white&#x27;,&#x27;blur&#x27;].includes(value))return;defaultStyle=value;if(selected!==null&amp;&amp;selected!==&#x27;water&#x27;){remember();pages[idx].rects[selected].style=value;}controls();draw()};\n$(&#x27;add-center&#x27;).onclick=()=&gt;{remember();pages[idx].rects.push({x:.3,y:.3,w:.3,h:.1,label:&#x27;Zona manual&#x27;,style:defaultStyle});selected=pages[idx].rects.length-1;pending=null;controls();draw()};\n$(&#x27;delete&#x27;).onclick=()=&gt;{if(selected===null)return;remember();if(selected===&#x27;water&#x27;)pages[idx].water=null;else pages[idx].rects.splice(selected,1);selected=null;controls();draw()};\n$(&#x27;apply-coords&#x27;).onclick=()=&gt;{if(selected===null)return;const values={};for(const k of [&#x27;x&#x27;,&#x27;y&#x27;,&#x27;w&#x27;,&#x27;h&#x27;]){values[k]=Number($(&#x27;r&#x27;+k).value)\/100;if(!Number.isFinite(values[k]))return}values.x=Math.max(0,Math.min(.998,values.x));values.y=Math.max(0,Math.min(.998,values.y));values.w=Math.max(.002,Math.min(1-values.x,values.w));values.h=Math.max(.002,Math.min(1-values.y,values.h));remember();Object.assign(selected===&#x27;water&#x27;?pages[idx].water:pages[idx].rects[selected],values);controls();draw()};\nfor(const [id,from,to] of [[&#x27;undo&#x27;,&#x27;undo&#x27;,&#x27;redo&#x27;],[&#x27;redo&#x27;,&#x27;redo&#x27;,&#x27;undo&#x27;]])$(id).onclick=()=&gt;{const p=pages[idx];if(!p[from].length)return;p[to].push(snapshot());const s=p[from].pop();p.rects=s.rects;p.water=s.water;selected=null;pending=null;invalidate(false);controls();draw()};\n$(&#x27;zoom-in&#x27;).onclick=()=&gt;{zoom=Math.min(4,zoom*1.25);size()};$(&#x27;zoom-out&#x27;).onclick=()=&gt;{zoom=Math.max(.5,zoom\/1.25);size()};$(&#x27;fit&#x27;).onclick=()=&gt;{zoom=1;fit()};async function goPage(n){if(busy||!Number.isInteger(n)||n&lt;0||n&gt;=pages.length)return;if(pending){$(&#x27;page&#x27;).value=idx;status(&#x27;Pulse \u00abOcultar selecci\u00f3n\u00bb antes de cambiar de p\u00e1gina, o \u00abMover documento\u00bb para descartar la selecci\u00f3n pendiente.&#x27;,true);$(&#x27;status&#x27;).scrollIntoView({block:&#x27;center&#x27;});return}setBusy(true);try{await showPage(n);$(&#x27;viewer&#x27;).scrollTop=0;$(&#x27;viewer&#x27;).scrollLeft=0;status(&#x27;P\u00e1gina &#x27;+(n+1)+&#x27; de &#x27;+pages.length+&#x27;. &#x27;+(reviewing?&#x27;Compruebe los datos visibles y las zonas ocultas.&#x27;:&#x27;Marque los datos que desea ocultar.&#x27;));$(&#x27;mode-title&#x27;).scrollIntoView({block:&#x27;start&#x27;});}catch(e){pages[n].reviewed=false;$(&#x27;page&#x27;).value=idx;status(&#x27;No se ha podido mostrar esta p\u00e1gina. Cierre el documento e int\u00e9ntelo de nuevo.&#x27;,true)}finally{setBusy(false)}}$(&#x27;page&#x27;).onchange=()=&gt;goPage(Number($(&#x27;page&#x27;).value));$(&#x27;page-prev&#x27;).onclick=()=&gt;goPage(idx-1);$(&#x27;page-next&#x27;).onclick=()=&gt;goPage(idx+1);$(&#x27;review-next&#x27;).onclick=()=&gt;goPage(pages.findIndex(p=&gt;!p.reviewed));\nfunction setReview(on){reviewing=on;if(!on)mode=&#x27;draw&#x27;;$(&#x27;edit-current&#x27;).hidden=!on;pending=null;selected=null;$(&#x27;review-note&#x27;).hidden=!on;$(&#x27;edit-tools&#x27;).hidden=on;$(&#x27;side&#x27;).hidden=on;$(&#x27;water-section&#x27;).hidden=on;$(&#x27;export-panel&#x27;).hidden=!on;$(&#x27;review&#x27;).hidden=on;$(&#x27;back-edit&#x27;).hidden=!on;$(&#x27;reset&#x27;).hidden=on;$(&#x27;mode-title&#x27;).textContent=on?&#x27;Vista previa&#x27;:&#x27;2. Seleccione las zonas que desea proteger&#x27;;$(&#x27;instructions&#x27;).hidden=on;$(&#x27;reviewed&#x27;).checked=false;$(&#x27;generate&#x27;).disabled=true;if(pages.length){if(on&amp;&amp;bitmap)pages[idx].reviewed=true;$(&#x27;review-summary&#x27;).textContent=&#x27;Se generar\u00e1 una copia nueva de &#x27;+pages.length+&#x27; p\u00e1gina(s), con &#x27;+pages.reduce((n,p)=&gt;n+p.rects.length,0)+&#x27; zona(s) tratada(s). Revise tambi\u00e9n los c\u00f3digos QR, c\u00f3digos de barras y zonas MRZ.&#x27;;zoom=1;fit();$(&#x27;viewer&#x27;).scrollTop=0;$(&#x27;viewer&#x27;).scrollLeft=0;controls();draw();$(&#x27;mode-title&#x27;).scrollIntoView({block:&#x27;start&#x27;});}}\n$(&#x27;review&#x27;).onclick=()=&gt;{if(pending){status(&#x27;Hay una selecci\u00f3n pendiente. Pulse \u00abOcultar selecci\u00f3n\u00bb o cambie al modo \u00abMover documento\u00bb para descartarla.&#x27;,true);return}status(&#x27;Revise todas las p\u00e1ginas antes de generar la copia.&#x27;);setReview(true)};function editCurrent(){setReview(false);status(&#x27;Edici\u00f3n de la p\u00e1gina &#x27;+(idx+1)+&#x27; de &#x27;+pages.length+&#x27;. Dibuje una zona y pulse \u00abOcultar selecci\u00f3n\u00bb.&#x27;);} $(&#x27;back-edit&#x27;).onclick=editCurrent;$(&#x27;edit-current&#x27;).onclick=editCurrent;$(&#x27;reviewed&#x27;).onchange=controls;\n$(&#x27;reset&#x27;).onclick=async()=&gt;{if(await ask(&#x27;Se quitar\u00e1n todas las zonas ocultas y la marca de agua de este documento. \u00bfDesea restablecerlo?&#x27;)){pages.forEach(p=&gt;{p.rects=[];p.water=null;p.undo=[];p.redo=[];p.reviewed=false});$(&#x27;water-on&#x27;).checked=false;[&#x27;purpose&#x27;,&#x27;recipient&#x27;,&#x27;reference&#x27;,&#x27;water-date&#x27;].forEach(id=&gt;$(id).value=&#x27;&#x27;);pending=null;selected=null;controls();draw()}};\n$(&#x27;clear&#x27;).onclick=async()=&gt;{if(await ask(&#x27;Se cerrar\u00e1 el documento y se descartar\u00e1n los cambios que no haya descargado.&#x27;))startOver()};$(&#x27;new-copy&#x27;).onclick=startOver;\nfor(const id of [&#x27;water-on&#x27;,&#x27;purpose&#x27;,&#x27;recipient&#x27;,&#x27;reference&#x27;,&#x27;water-date&#x27;,&#x27;water-position&#x27;])$(id).addEventListener(&#x27;input&#x27;,()=&gt;{invalidate();controls();draw()});$(&#x27;today&#x27;).onclick=()=&gt;{$(&#x27;water-date&#x27;).value=dateName();invalidate();draw()};$(&#x27;place-water&#x27;).onclick=()=&gt;{mode=&#x27;water&#x27;;selected=null;pending=null;status(&#x27;Dibuje el espacio para la marca de agua en esta p\u00e1gina.&#x27;);controls();draw()};$(&#x27;remove-water-zone&#x27;).onclick=()=&gt;{remember();pages[idx].water=null;selected=null;controls();draw()};\n\/\/ A new, image-only PDF. No bytes, objects, metadata or text from the input PDF are reused.\nfunction pdfWriter(count){const enc=new TextEncoder(),parts=[],offsets=[0];let length=0,added=0;const put=x=&gt;{const b=typeof x===&#x27;string&#x27;?enc.encode(x):x;parts.push(b);length+=b.length};const obj=(id,body,stream)=&gt;{offsets[id]=length;put(id+&#x27; 0 obj\\n&#x27;+body);if(stream){put(&#x27;\\nstream\\n&#x27;);put(stream);put(&#x27;\\nendstream&#x27;)}put(&#x27;\\nendobj\\n&#x27;)};put(&#x27;%PDF-1.4\\n&#x27;);obj(1,&#x27;&lt;&lt; \/Type \/Catalog \/Pages 2 0 R &gt;&gt;&#x27;);obj(2,&#x27;&lt;&lt; \/Type \/Pages \/Count &#x27;+count+&#x27; \/Kids [&#x27;+Array.from({length:count},(_,i)=&gt;(3+i*3)+&#x27; 0 R&#x27;).join(&#x27; &#x27;)+&#x27;] &gt;&gt;&#x27;);return{add(im){if(length+im.bytes.length&gt;80*1024*1024)throw Error(&#x27;La copia supera 80 MB. Divida el documento en archivos m\u00e1s peque\u00f1os.&#x27;);const id=3+added++*3,w=Number(im.pw.toFixed(3)),h=Number(im.ph.toFixed(3)),content=enc.encode(&#x27;q\\n&#x27;+w+&#x27; 0 0 &#x27;+h+&#x27; 0 0 cm\\n\/Im0 Do\\nQ\\n&#x27;);obj(id,&#x27;&lt;&lt; \/Type \/Page \/Parent 2 0 R \/MediaBox [0 0 &#x27;+w+&#x27; &#x27;+h+&#x27;] \/Resources &lt;&lt; \/XObject &lt;&lt; \/Im0 &#x27;+(id+1)+&#x27; 0 R &gt;&gt; &gt;&gt; \/Contents &#x27;+(id+2)+&#x27; 0 R &gt;&gt;&#x27;);obj(id+1,&#x27;&lt;&lt; \/Type \/XObject \/Subtype \/Image \/Width &#x27;+im.w+&#x27; \/Height &#x27;+im.h+&#x27; \/ColorSpace \/DeviceRGB \/BitsPerComponent 8 \/Filter \/DCTDecode \/Length &#x27;+im.bytes.length+&#x27; &gt;&gt;&#x27;,im.bytes);obj(id+2,&#x27;&lt;&lt; \/Length &#x27;+content.length+&#x27; &gt;&gt;&#x27;,content)},finish(){if(added!==count)throw Error(&#x27;No se han procesado todas las p\u00e1ginas.&#x27;);const xref=length;put(&#x27;xref\\n0 &#x27;+offsets.length+&#x27;\\n0000000000 65535 f \\n&#x27;);for(let i=1;i&lt;offsets.length;i++)put(String(offsets[i]).padStart(10,&#x27;0&#x27;)+&#x27; 00000 n \\n&#x27;);put(&#x27;trailer\\n&lt;&lt; \/Size &#x27;+offsets.length+&#x27; \/Root 1 0 R &gt;&gt;\\nstartxref\\n&#x27;+xref+&#x27;\\n%%EOF\\n&#x27;);const result=new Blob(parts,{type:&#x27;application\/pdf&#x27;});parts.length=0;return result},discard(){parts.length=0}}}\n$(&#x27;cancel-export&#x27;).onclick=()=&gt;{cancelExport=true;$(&#x27;cancel-export&#x27;).disabled=true;$(&#x27;export-status&#x27;).textContent=&#x27;Cancelando al terminar la p\u00e1gina actual\u2026&#x27;;};\n$(&#x27;generate&#x27;).onclick=async()=&gt;{if(busy||!bitmap||!$(&#x27;reviewed&#x27;).checked||!pages.every(p=&gt;p.reviewed))return;setBusy(true);cancelExport=false;const format=$(&#x27;format&#x27;).value,chosen=format===&#x27;png&#x27;?[idx]:pages.map((_,i)=&gt;i),writer=format===&#x27;pdf&#x27;?pdfWriter(chosen.length):null;let output;const cancelled=()=&gt;{if(cancelExport)throw Error(&#x27;CANCELLED&#x27;)};$(&#x27;export-progress&#x27;).hidden=false;$(&#x27;export-meter&#x27;).max=chosen.length;$(&#x27;export-meter&#x27;).value=0;$(&#x27;cancel-export&#x27;).disabled=false;$(&#x27;export-status&#x27;).textContent=&#x27;Preparando la copia\u2026&#x27;;$(&#x27;export-progress&#x27;).scrollIntoView({block:&#x27;center&#x27;});try{for(let i=0;i&lt;chosen.length;i++){cancelled();const message=&#x27;Generando p\u00e1gina &#x27;+(i+1)+&#x27; de &#x27;+chosen.length+&#x27;\u2026&#x27;;status(message);$(&#x27;export-status&#x27;).textContent=message;const p=pages[chosen[i]],b=await rasterPage(chosen[i]),c=canvas(p.w,p.h);try{cancelled();paint(c.getContext(&#x27;2d&#x27;,{alpha:false}),b,p);if(format===&#x27;png&#x27;)output=await toBlob(c);else writer.add({bytes:new Uint8Array(await (await toBlob(c,&#x27;image\/jpeg&#x27;,.96)).arrayBuffer()),w:p.w,h:p.h,pw:p.pw,ph:p.ph});}finally{b.close();c.width=c.height=1}$(&#x27;export-meter&#x27;).value=i+1;await tick()}cancelled();if(writer)output=writer.finish();clearOutput();outputURL=URL.createObjectURL(output);$(&#x27;download&#x27;).href=outputURL;$(&#x27;download&#x27;).download=&#x27;documento_protegido_&#x27;+dateName()+&#x27;.&#x27;+format;$(&#x27;result-info&#x27;).textContent=format===&#x27;pdf&#x27;?&#x27;PDF nuevo con &#x27;+chosen.length+&#x27; p\u00e1gina(s) rasterizada(s).&#x27;:&#x27;Imagen PNG de la p\u00e1gina seleccionada.&#x27;;freeSource();$(&#x27;editor&#x27;).hidden=true;$(&#x27;start&#x27;).hidden=true;$(&#x27;result&#x27;).hidden=false;status(&#x27;Copia generada. Desc\u00e1rguela y compruebe el resultado antes de compartirlo.&#x27;);$(&#x27;result&#x27;).scrollIntoView({behavior:&#x27;smooth&#x27;,block:&#x27;start&#x27;});}catch(e){if(writer)writer.discard();const message=e.message===&#x27;CANCELLED&#x27;?&#x27;Generaci\u00f3n cancelada. Sus marcas se conservan; puede volver a generar la copia.&#x27;:e.message===&#x27;La copia supera 80 MB. Divida el documento en archivos m\u00e1s peque\u00f1os.&#x27;?e.message:&#x27;No se ha podido generar la copia completa. No se ha descargado ning\u00fan original ni un PDF parcial. Pruebe con un documento m\u00e1s peque\u00f1o.&#x27;;status(message,e.message!==&#x27;CANCELLED&#x27;);$(&#x27;export-status&#x27;).textContent=message;}finally{$(&#x27;cancel-export&#x27;).disabled=true;setBusy(false);$(&#x27;cancel-export&#x27;).disabled=true;}};\n\n\/\/ Non-personal demonstration PDF, generated in memory; never fetched or uploaded.\n$(&#x27;demo&#x27;).onclick=()=&gt;{const parts=[&#x27;%PDF-1.4\\n&#x27;],offsets=[0];let len=parts[0].length;const add=(n,t)=&gt;{offsets[n]=len;const x=n+&#x27; 0 obj\\n&#x27;+t+&#x27;\\nendobj\\n&#x27;;parts.push(x);len+=x.length};add(1,&#x27;&lt;&lt; \/Type \/Catalog \/Pages 2 0 R &gt;&gt;&#x27;);add(2,&#x27;&lt;&lt; \/Type \/Pages \/Count 2 \/Kids [3 0 R 5 0 R] &gt;&gt;&#x27;);for(let i=0;i&lt;2;i++){const n=3+i*2,t=&#x27;BT \/F1 20 Tf 35 735 Td (IURAVENT - EJEMPLO FICTICIO &#x27;+(i+1)+&#x27;) Tj 145 -215 Td (DATO-PRIVADO-&#x27;+(i+1)+&#x27;-84729) Tj -145 -445 Td (DATO VISIBLE - conservar) Tj ET&#x27;;add(n,&#x27;&lt;&lt; \/Type \/Page \/Parent 2 0 R \/MediaBox [0 0 600 800] \/Resources &lt;&lt; \/Font &lt;&lt; \/F1 7 0 R &gt;&gt; &gt;&gt; \/Contents &#x27;+(n+1)+&#x27; 0 R &gt;&gt;&#x27;);add(n+1,&#x27;&lt;&lt; \/Length &#x27;+t.length+&#x27; &gt;&gt;\\nstream\\n&#x27;+t+&#x27;\\nendstream&#x27;)}add(7,&#x27;&lt;&lt; \/Type \/Font \/Subtype \/Type1 \/BaseFont \/Helvetica &gt;&gt;&#x27;);const xref=len;parts.push(&#x27;xref\\n0 8\\n0000000000 65535 f \\n&#x27;+offsets.slice(1).map(n=&gt;String(n).padStart(10,&#x27;0&#x27;)+&#x27; 00000 n \\n&#x27;).join(&#x27;&#x27;)+&#x27;trailer\\n&lt;&lt; \/Size 8 \/Root 1 0 R &gt;&gt;\\nstartxref\\n&#x27;+xref+&#x27;\\n%%EOF\\n&#x27;);loadFile(new File(parts,&#x27;ejemplo-ficticio.pdf&#x27;,{type:&#x27;application\/pdf&#x27;}))};\n$(&#x27;file&#x27;).addEventListener(&#x27;change&#x27;,e=&gt;loadFile(e.target.files[0]));[&#x27;dragenter&#x27;,&#x27;dragover&#x27;].forEach(t=&gt;$(&#x27;drop&#x27;).addEventListener(t,e=&gt;{e.preventDefault();$(&#x27;drop&#x27;).classList.add(&#x27;drag&#x27;)}));[&#x27;dragleave&#x27;,&#x27;drop&#x27;].forEach(t=&gt;$(&#x27;drop&#x27;).addEventListener(t,e=&gt;{e.preventDefault();$(&#x27;drop&#x27;).classList.remove(&#x27;drag&#x27;)}));$(&#x27;drop&#x27;).addEventListener(&#x27;drop&#x27;,e=&gt;{if(e.dataTransfer.files.length!==1){status(&#x27;Seleccione un \u00fanico documento cada vez.&#x27;,true);return}loadFile(e.dataTransfer.files[0])});\nwindow.addEventListener(&#x27;resize&#x27;,fit);window.addEventListener(&#x27;pagehide&#x27;,()=&gt;{freeSource();clearOutput()});window.addEventListener(&#x27;pageshow&#x27;,e=&gt;{if(e.persisted)startOver()});if(window.parent!==window){let lastHeight=0;new ResizeObserver(()=&gt;{const h=Math.ceil(document.documentElement.getBoundingClientRect().height);if(h!==lastHeight){lastHeight=h;window.parent.postMessage({type:&#x27;iuravent-protector-height&#x27;,height:h},&#x27;*&#x27;)}}).observe(document.body)}$(&#x27;file&#x27;).disabled=false;status(&#x27;Seleccione un archivo para empezar.&#x27;);\n})();\n&lt;\/script&gt;&lt;\/body&gt;&lt;\/html&gt;\n\"><\/iframe>\n<script>(()=>{const frame=document.getElementById('iuravent-protector');window.addEventListener('message',e=>{if(e.source!==frame.contentWindow||!e.data||e.data.type!=='iuravent-protector-height')return;const h=Number(e.data.height);if(Number.isFinite(h)&&h>0&&h<30000)frame.style.height=Math.ceil(h)+'px'});})();<\/script>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"slim_seo":{"title":"Protector documental - IURAVENT","description":""},"footnotes":""},"class_list":["post-48","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/pages\/48","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/comments?post=48"}],"version-history":[{"count":11,"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/pages\/48\/revisions"}],"predecessor-version":[{"id":66,"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/pages\/48\/revisions\/66"}],"wp:attachment":[{"href":"https:\/\/iuravent.es\/index.php\/wp-json\/wp\/v2\/media?parent=48"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}