{"id":301,"date":"2025-09-20T20:07:23","date_gmt":"2025-09-20T20:07:23","guid":{"rendered":"https:\/\/cirkulaerthaandvaerk.dk\/?page_id=301"},"modified":"2025-09-30T10:45:59","modified_gmt":"2025-09-30T10:45:59","slug":"book-en-opgave","status":"publish","type":"page","link":"https:\/\/staging1.eudportal.dk\/index.php\/book-en-opgave\/","title":{"rendered":"Book en opgave"},"content":{"rendered":"<div class=\"chrf-wrap\" style=\"max-width:980px;margin:24px auto;\">\n    \n  \n  <form id=\"chrf-form\" action=\"https:\/\/staging1.eudportal.dk\/wp-admin\/admin-post.php\" method=\"post\" enctype=\"multipart\/form-data\" class=\"chrf-form\" style=\"display:grid;grid-template-columns:1fr 1fr;gap:16px;background:#fff;border-radius:12px;padding:24px;box-shadow:0 1px 12px rgba(0,0,0,.06);\">\n    <input type=\"hidden\" name=\"action\" value=\"ch_request_submit\" \/><input type=\"hidden\" id=\"chrf_nonce\" name=\"chrf_nonce\" value=\"642d82198f\" \/><input type=\"hidden\" name=\"_wp_http_referer\" value=\"\/index.php\/wp-json\/wp\/v2\/pages\/301\" \/>\n    <div class=\"full\" style=\"grid-column:1\/-1;\"><h2>Kontaktoplysninger<\/h2><\/div>\n    <div class=\"full\" style=\"grid-column:1\/-1;\"><label>Projektoverskrift *<\/label><input type=\"text\" name=\"project_title\" required placeholder=\"F.eks. Nyt k\u00f8kken i Valby\" \/><\/div>\n    <div><label>Navn *<\/label><input type=\"text\" name=\"name\" required \/><\/div>\n    <div><label>E\u2011mail *<\/label><input type=\"email\" name=\"email\" required \/><\/div>\n    <div><label>Telefon *<\/label><input type=\"tel\" name=\"phone\" required \/><\/div>\n    <div><label>Adresse *<\/label><input type=\"text\" name=\"address\" required \/><\/div>\n\n    <div class=\"full\" style=\"grid-column:1\/-1;\"><h2>Bookingperiode<\/h2><\/div>\n\n        <div class=\"calendar-cell\" style=\"grid-column:1 \/ span 1;\">\n      <div class=\"chfc-wrap\" style=\"max-width:980px;margin:12px auto;\">\n  <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;\">\n    <a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?year=2026&month=7\">\u00ab Forrige<\/a>\n    <strong>August 2026<\/strong>\n    <a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?year=2026&month=9\">N\u00e6ste \u00bb<\/a>\n  <\/div>\n\n  \n  <table class=\"widefat fixed striped\" style=\"width:100%;\">\n    <thead><tr><th>Man<\/th><th>Tir<\/th><th>Ons<\/th><th>Tor<\/th><th>Fre<\/th><th>L\u00f8r<\/th><th>S\u00f8n<\/th><\/tr><\/thead>\n    <tbody>\n      <tr><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>1<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>2<\/strong><\/div><\/div><\/td><\/tr><tr><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>3<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>4<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>5<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>6<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>7<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>8<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>9<\/strong><\/div><\/div><\/td><\/tr><tr><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>10<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>11<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>12<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>13<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>14<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>15<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>16<\/strong><\/div><\/div><\/td><\/tr><tr><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>17<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>18<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>19<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>20<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>21<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>22<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>23<\/strong><\/div><\/div><\/td><\/tr><tr><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>24<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>25<\/strong><\/div><\/div><\/td><td><div style=\"background:#f3f4f6;border-radius:8px;padding:6px 8px;cursor:not-allowed;\"><div style=\"display:flex;justify-content:space-between;align-items:center;opacity:.55;\"><strong>26<\/strong><\/div><\/div><\/td><td><a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?start_date=2026-08-27\" style=\"display:block;text-decoration:none;color:inherit;\"><div style=\"display:flex;justify-content:space-between;align-items:center;\"><strong>27<\/strong><span class=\"badge\" style=\"background:#2271b1;color:#fff;border-radius:999px;padding:2px 8px;font-size:11px;\">Ledig<\/span><\/div><\/a><\/td><td><a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?start_date=2026-08-28\" style=\"display:block;text-decoration:none;color:inherit;\"><div style=\"display:flex;justify-content:space-between;align-items:center;\"><strong>28<\/strong><span class=\"badge\" style=\"background:#2271b1;color:#fff;border-radius:999px;padding:2px 8px;font-size:11px;\">Ledig<\/span><\/div><\/a><\/td><td><a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?start_date=2026-08-29\" style=\"display:block;text-decoration:none;color:inherit;\"><div style=\"display:flex;justify-content:space-between;align-items:center;\"><strong>29<\/strong><span class=\"badge\" style=\"background:#2271b1;color:#fff;border-radius:999px;padding:2px 8px;font-size:11px;\">Ledig<\/span><\/div><\/a><\/td><td><a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?start_date=2026-08-30\" style=\"display:block;text-decoration:none;color:inherit;\"><div style=\"display:flex;justify-content:space-between;align-items:center;\"><strong>30<\/strong><span class=\"badge\" style=\"background:#2271b1;color:#fff;border-radius:999px;padding:2px 8px;font-size:11px;\">Ledig<\/span><\/div><\/a><\/td><\/tr><tr><td><a href=\"\/index.php\/wp-json\/wp\/v2\/pages\/301?start_date=2026-08-31\" style=\"display:block;text-decoration:none;color:inherit;\"><div style=\"display:flex;justify-content:space-between;align-items:center;\"><strong>31<\/strong><span class=\"badge\" style=\"background:#2271b1;color:#fff;border-radius:999px;padding:2px 8px;font-size:11px;\">Ledig<\/span><\/div><\/a><\/td><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><td>\u00a0<\/td><\/tr>    <\/tbody>\n  <\/table>\n  <p style=\"margin-top:6px;\"><strong>Legend:<\/strong> <span style=\"background:#2271b1;color:#fff;border-radius:6px;padding:2px 6px;\">Ledig<\/span> <span style=\"background:#a00;color:#fff;border-radius:6px;padding:2px 6px;\">Optaget<\/span> \u00b7 <em>Gr\u00e5 = Ikke bookbar<\/em><\/p>\n<\/div>\n    <\/div>\n    \n    <div class=\"date-fields\" style=\"grid-column:2 \/ span 1; display:flex; flex-direction:column; gap:12px;\">\n      <div><label>Startdato *<\/label><input type=\"date\" name=\"start_date\" required min=\"2026-08-27\" value=\"\" \/><\/div>\n      <div><label>Slutdato *<\/label><input type=\"date\" name=\"end_date\" required min=\"2026-08-27\" value=\"\" \/><\/div>\n      <div id=\"chrf-date-msg\" style=\"font-size:13px;\"><\/div>\n    <\/div>\n\n    <div class=\"full\" style=\"grid-column:1\/-1;\"><h2>Opgaveoplysninger<\/h2><\/div>\n    <div class=\"full\" style=\"grid-column:1\/-1;\"><label>Beskrivelse af opgaven *<\/label><textarea name=\"description\" required style=\"min-height:140px;width:100%\"><\/textarea><\/div>\n\n    <div><label>Omfang *<\/label><select name=\"scope\" required><option value=\"hele-projektet\">Hele projektet<\/option><option value=\"del-af-projektet\">Del af projektet<\/option><\/select><\/div>\n\n    <div><label><input type=\"checkbox\" name=\"has_materials\" \/> Jeg har selv materialer<\/label><\/div>\n    <div><label>Materialer (tilf\u00f8j hvis du ikke har)<\/label><input type=\"text\" name=\"materials_list\" \/><\/div>\n\n    <div class=\"full\" style=\"grid-column:1\/-1;\">\n      <label>Billeder (op til 3, valgfri)<\/label>\n      <div id=\"chrf-drop\" style=\"border:2px dashed #cbd5e1;border-radius:12px;padding:16px;text-align:center;cursor:pointer;\">\n        Tr\u00e6k og slip billeder her eller klik for at v\u00e6lge\n        <input id=\"chrf-files\" type=\"file\" name=\"photos[]\" accept=\"image\/jpeg,image\/png,image\/webp\" multiple style=\"display:none;\" \/>\n      <\/div>\n      <div id=\"chrf-previews\" style=\"display:flex;gap:10px;margin-top:10px;flex-wrap:wrap;\"><\/div>\n<div id=\"chrf-editor\" style=\"display:none;position:fixed;inset:0;background:#000000a0;align-items:center;justify-content:center;z-index:9999;\">\n  <div style=\"background:#fff;border-radius:12px;padding:16px;width:min(92vw,900px);max-height:92vh;display:flex;flex-direction:column;gap:10px;\">\n    <div style=\"display:flex;justify-content:space-between;align-items:center;\"><strong>Redig\u00e9r billede<\/strong><button type=\"button\" id=\"chrf-ed-close\" style=\"border:0;background:#eee;border-radius:8px;padding:6px 10px;cursor:pointer;\">Luk<\/button><\/div>\n    <div style=\"display:flex;gap:12px;align-items:flex-start;\">\n      <div style=\"flex:1;position:relative;border:1px solid #e5e7eb;border-radius:8px;overflow:auto;background:#000;\">\n        <img decoding=\"async\" id=\"chrf-ed-img\" src=\"\" style=\"max-width:none;transform-origin:center center;display:block;user-select:none;\" \/>\n        <div id=\"chrf-ed-crop\" style=\"position:absolute;border:2px solid #39f;box-shadow:0 0 0 9999px #00000066;cursor:move;\"><\/div>\n      <\/div>\n      <div style=\"width:200px;display:flex;flex-direction:column;gap:8px;\">\n        <label>Zoom <input id=\"chrf-ed-zoom\" type=\"range\" min=\"10\" max=\"300\" value=\"100\" \/><\/label>\n        <div style=\"display:flex;gap:6px;flex-wrap:wrap;\">\n          <button type=\"button\" id=\"chrf-ed-rot-left\" style=\"padding:6px 8px;\">\u27f2 Roter venstre<\/button>\n          <button type=\"button\" id=\"chrf-ed-rot-right\" style=\"padding:6px 8px;\">\u27f3 Roter h\u00f8jre<\/button>\n        <\/div>\n        <small>Maks. billedst\u00f8rrelse ved upload: 2000 px (automatisk nedskalering).<\/small>\n        <button type=\"button\" id=\"chrf-ed-apply\" style=\"margin-top:auto;background:#0d5;color:#053;border:0;border-radius:8px;padding:8px 10px;cursor:pointer;\">Gem \u00e6ndringer<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n      <div style=\"font-size:12px;color:#666;margin-top:6px;\">JPG\/PNG\/WEBP, max 10 MB pr. fil \u2013 h\u00f8jst 3 billeder.<\/div>\n    <\/div>\n\n    <div class=\"full\" style=\"grid-column:1\/-1;display:flex;gap:12px;margin-top:8px;\">\n      <button id=\"chrf-submit\" type=\"submit\" style=\"appearance:none;border:0;border-radius:999px;padding:12px 20px;font-weight:700;background:#0d5;color:#053;cursor:pointer;\">Send foresp\u00f8rgsel<\/button>\n      <button type=\"reset\" style=\"appearance:none;border:0;border-radius:999px;padding:12px 20px;font-weight:700;background:#eef1f5;cursor:pointer;\">Nulstil<\/button>\n    <\/div>\n  <\/form>\n<\/div>\n\n<script>\n(function(){\n  const form = document.getElementById('chrf-form');\n  if (!form) return;\n  const s = form.querySelector('input[name=\"start_date\"]');\n  const e = form.querySelector('input[name=\"end_date\"]');\n  const msg = document.getElementById('chrf-date-msg');\n  const submitBtn = document.getElementById('chrf-submit');\n\n  function showOk(){\n    if (!msg) return;\n    msg.style.color = '#065f46'; msg.style.background = '#e8fff3'; msg.style.padding='8px 10px'; msg.style.borderRadius='8px';\n    msg.textContent = 'Datoerne er ledige.';\n    if (submitBtn) submitBtn.disabled = false;\n  }\n  function showBusy(list){\n    if (!msg) return;\n    msg.style.color = '#b00020'; msg.style.background = '#ffe9e9'; msg.style.padding='8px 10px'; msg.style.borderRadius='8px';\n    msg.textContent = 'Ikke bookbar\/optaget: ' + list.join(', ') + '. V\u00e6lg venligst andre datoer.';\n    if (submitBtn) submitBtn.disabled = true;\n  }\n  function clearMsg(){\n    if (!msg) return;\n    msg.textContent = ''; msg.style.background='transparent'; msg.style.padding='0';\n    if (submitBtn) submitBtn.disabled = false;\n  }\n\n  async function check(){\n    const sv = s && s.value ? s.value : '';\n    const ev = e && e.value ? e.value : sv;\n    if (!sv || !ev){ clearMsg(); return; }\n    try{\n      const data = new FormData();\n      data.append('action','ch_check_range');\n      data.append('start', sv);\n      data.append('end', ev);\n      const res = await fetch('https:\/\/staging1.eudportal.dk\/wp-admin\/admin-ajax.php', { method:'POST', credentials:'same-origin', body:data });\n      const json = await res.json();\n      if (json && json.ok){ showOk(); } else if (json && json.busy) { showBusy(json.busy); } else { clearMsg(); }\n    } catch(err){ clearMsg(); }\n  }\n\n  if (s) s.addEventListener('change', check);\n  if (e) e.addEventListener('change', check);\n  document.addEventListener('DOMContentLoaded', check);\n\n  \/\/ Drag & drop multi-upload with previews (max 3)\n  const drop = document.getElementById('chrf-drop');\n  const fileInput = document.getElementById('chrf-files');\n  const previews = document.getElementById('chrf-previews');\n  const MAX_FILES = 3;\n  const ALLOWED = ['image\/jpeg','image\/png','image\/webp'];\n  const MAX_SIZE = 10 * 1024 * 1024;\n\n  function renderPreview(file){\n    file.__rotation = file.__rotation || 0;\n    file.__crop = file.__crop || null;\n    const url = URL.createObjectURL(file);\n    const wrap = document.createElement('div');\n    wrap.style.width='110px'; wrap.style.height='110px'; wrap.style.border='1px solid #e5e7eb'; wrap.style.borderRadius='8px'; wrap.style.overflow='hidden'; wrap.style.position='relative';\n    const img = document.createElement('img'); img.src = url; img.style.width='100%'; img.style.height='100%'; img.style.objectFit='cover';\n    const x = document.createElement('button'); x.type='button'; x.textContent='\u00d7'; x.style.position='absolute'; x.style.top='4px'; x.style.right='6px'; x.style.background='#00000088'; x.style.color='#fff'; x.style.border='0'; x.style.borderRadius='999px'; x.style.width='22px'; x.style.height='22px'; x.style.cursor='pointer';\n    x.addEventListener('click', ()=>{\n      \/\/ remove from DataTransfer\n      const dt = new DataTransfer();\n      Array.from(fileInput.files).forEach(f=>{ if(f!==file) dt.items.add(f); });\n      fileInput.files = dt.files;\n      wrap.remove();\n    });\n    const edit = document.createElement('button'); edit.type='button'; edit.textContent='Redig\u00e9r'; edit.style.position='absolute'; edit.style.left='6px'; edit.style.bottom='6px'; edit.style.background='#ffffffdd'; edit.style.border='0'; edit.style.borderRadius='6px'; edit.style.padding='4px 6px'; edit.style.cursor='pointer';\nedit.addEventListener('click', ()=> openEditor(file, wrap));\nwrap.appendChild(img); wrap.appendChild(x); wrap.appendChild(edit); previews.appendChild(wrap);\n  }\n\n  function validateAndSet(files){\n    const existing = fileInput.files ? Array.from(fileInput.files) : [];\n    const incoming = Array.from(files);\n    \/\/ merge but limit to MAX_FILES\n    const merged = existing.concat(incoming).slice(0, MAX_FILES);\n    \/\/ type\/size filter\n    for (const f of merged){\n      if (!ALLOWED.includes(f.type)){ alert('Kun JPG, PNG eller WEBP er tilladt.'); return; }\n      if (f.size > MAX_SIZE){ alert('Hver fil m\u00e5 h\u00f8jst v\u00e6re 10 MB.'); return; }\n    }\n    const dt = new DataTransfer();\n    merged.forEach(f => dt.items.add(f));\n    fileInput.files = dt.files;\n    \/\/ refresh previews\n    previews.innerHTML='';\n    merged.forEach(renderPreview);\n  }\n\n  if (drop && fileInput){\n    drop.addEventListener('click', ()=> fileInput.click());\n    drop.addEventListener('dragover', (e)=>{ e.preventDefault(); drop.style.background='#f8fafc'; });\n    drop.addEventListener('dragleave', ()=>{ drop.style.background='transparent'; });\n    drop.addEventListener('drop', (e)=>{\n      e.preventDefault(); drop.style.background='transparent';\n      validateAndSet(e.dataTransfer.files);\n    });\n    fileInput.addEventListener('change', (e)=> validateAndSet(e.target.files));\n  }\n\n  \/\/ === Image editor state ===\n  const editor = document.getElementById('chrf-editor');\n  const edImg = document.getElementById('chrf-ed-img');\n  const edCrop = document.getElementById('chrf-ed-crop');\n  const edClose = document.getElementById('chrf-ed-close');\n  const edZoom = document.getElementById('chrf-ed-zoom');\n  const edRotL = document.getElementById('chrf-ed-rot-left');\n  const edRotR = document.getElementById('chrf-ed-rot-right');\n  const edApply = document.getElementById('chrf-ed-apply');\n  let currentFile = null;\n  let imgNatural = {w:0,h:0};\n  let view = {scale:1, rot:0, offsetX:0, offsetY:0};\n  let crop = {x:50,y:50,w:300,h:300};\n  function openEditor(file, previewWrap){\n    currentFile = file;\n    view = {scale:1, rot:file.__rotation||0, offsetX:0, offsetY:0};\n    crop = file.__crop || {x:50,y:50,w:300,h:300};\n    edZoom.value = 100;\n    const url = URL.createObjectURL(file);\n    edImg.onload = ()=>{\n      imgNatural = {w: edImg.naturalWidth, h: edImg.naturalHeight};\n      \/\/ fit img to container width\n      edImg.style.width = imgNatural.w + 'px';\n      edImg.style.height = 'auto';\n      edImg.style.transform = `translate(${view.offsetX}px, ${view.offsetY}px) rotate(${view.rot}deg) scale(${view.scale})`;\n      \/\/ Position crop box\n      edCrop.style.left = crop.x + 'px'; edCrop.style.top = crop.y + 'px'; edCrop.style.width = crop.w + 'px'; edCrop.style.height = crop.h + 'px';\n    };\n    edImg.src = url;\n    editor.style.display = 'flex';\n\n    \/\/ Drag crop\n    let dragging = false, start = {x:0,y:0}, orig = {x:0,y:0};\n    edCrop.onmousedown = (e)=>{ dragging=true; start={x:e.clientX,y:e.clientY}; orig={x:crop.x,y:crop.y}; };\n    window.onmousemove = (e)=>{ if(!dragging) return; const dx=e.clientX-start.x, dy=e.clientY-start.y; crop.x = Math.max(0, orig.x+dx); crop.y = Math.max(0, orig.y+dy); edCrop.style.left=crop.x+'px'; edCrop.style.top=crop.y+'px'; };\n    window.onmouseup = ()=> dragging=false;\n\n    \/\/ Resize via Shift+Wheel (quick)\n    edCrop.onwheel = (e)=>{ e.preventDefault(); const dw = e.deltaY>0 ? -20 : 20; crop.w = Math.max(50, crop.w + dw); crop.h = Math.max(50, crop.h + dw); edCrop.style.width=crop.w+'px'; edCrop.style.height=crop.h+'px'; };\n\n    \/\/ Zoom\n    edZoom.oninput = ()=>{ view.scale = parseInt(edZoom.value,10)\/100; edImg.style.transform = `translate(${view.offsetX}px, ${view.offsetY}px) rotate(${view.rot}deg) scale(${view.scale})`; };\n\n    \/\/ Rotate\n    edRotL.onclick = ()=>{ view.rot = (view.rot - 90) % 360; edImg.style.transform = `translate(${view.offsetX}px, ${view.offsetY}px) rotate(${view.rot}deg) scale(${view.scale})`; };\n    edRotR.onclick = ()=>{ view.rot = (view.rot + 90) % 360; edImg.style.transform = `translate(${view.offsetX}px, ${view.offsetY}px) rotate(${view.rot}deg) scale(${view.scale})`; };\n\n    \/\/ Apply\n    edApply.onclick = async ()=>{\n      \/\/ Draw onto canvas with rotation and crop, downscale to max 2000px later\n      const canvas = document.createElement('canvas');\n      \/\/ We'll first render full image with rotation then crop selection area mapped to image coords.\n      \/\/ For a simple approach, assume crop is in image pixel coordinates (1:1 preview). If zoomed, we ignore for now to keep UX simple.\n      const angle = (view.rot % 360 + 360) % 360;\n      const rad = angle * Math.PI\/180;\n      const iw = imgNatural.w, ih = imgNatural.h;\n      \/\/ Compute rotated bounding box size\n      const sin = Math.abs(Math.sin(rad)), cos = Math.abs(Math.cos(rad));\n      const rw = Math.round(iw * cos + ih * sin);\n      const rh = Math.round(ih * cos + iw * sin);\n      canvas.width = rw; canvas.height = rh;\n      const ctx = canvas.getContext('2d');\n      ctx.save();\n      ctx.translate(rw\/2, rh\/2);\n      ctx.rotate(rad);\n      ctx.drawImage(edImg, -iw\/2, -ih\/2);\n      ctx.restore();\n\n      \/\/ Crop area: clamp to canvas bounds\n      const cx = Math.max(0, Math.min(rw-1, crop.x));\n      const cy = Math.max(0, Math.min(rh-1, crop.y));\n      const cw = Math.max(1, Math.min(crop.w, rw - cx));\n      const ch = Math.max(1, Math.min(crop.h, rh - cy));\n\n      \/\/ Extract cropped image to another canvas\n      const c2 = document.createElement('canvas');\n      c2.width = cw; c2.height = ch;\n      const c2x = c2.getContext('2d');\n      c2x.drawImage(canvas, cx, cy, cw, ch, 0, 0, cw, ch);\n\n      \/\/ Downscale to max 2000\n      const MAX = 2000;\n      let outW = cw, outH = ch;\n      if (Math.max(cw, ch) > MAX){\n        if (cw >= ch){ outW = MAX; outH = Math.round(ch * (MAX \/ cw)); }\n        else { outH = MAX; outW = Math.round(cw * (MAX \/ ch)); }\n      }\n      const c3 = document.createElement('canvas');\n      c3.width = outW; c3.height = outH;\n      const c3x = c3.getContext('2d');\n      c3x.imageSmoothingQuality = 'high';\n      c3x.drawImage(c2, 0, 0, outW, outH);\n\n      const blob = await new Promise(res=> c3.toBlob(res, 'image\/jpeg', 0.92));\n      if (blob){\n        const newFile = new File([blob], file.name.replace(\/\\.(png|webp)$\/i,'.jpg').replace(\/\\.(jpeg|jpg)$\/i,'.jpg'), {type:'image\/jpeg'});\n        newFile.__rotation = view.rot;\n        newFile.__crop = {...crop};\n        \/\/ Replace this file in input\n        const dt = new DataTransfer();\n        Array.from(fileInput.files).forEach(f=>{ dt.items.add(f===file? newFile : f); });\n        fileInput.files = dt.files;\n        \/\/ refresh previews\n        validateAndSet([]);\n      }\n      editor.style.display='none';\n    };\n\n    edClose.onclick = ()=>{ editor.style.display='none'; };\n  }\n\n  \/\/ Before submit: ensure downscale even if user didn't edit\n  form.addEventListener('submit', async (e)=>{\n    if (!fileInput.files || !fileInput.files.length) return;\n    e.preventDefault();\n    const MAX = 2000;\n    const files = Array.from(fileInput.files);\n    const processed = [];\n    for (const file of files){\n      if (!['image\/jpeg','image\/png','image\/webp'].includes(file.type)){ processed.push(file); continue; }\n      \/\/ If already edited (jpeg), likely fine, but still enforce max size\n      const img = await new Promise(res=>{ const im=new Image(); im.onload=()=>res(im); im.src=URL.createObjectURL(file); });\n      let w = img.naturalWidth, h = img.naturalHeight;\n      let needScale = Math.max(w,h) > MAX;\n      if (!needScale){ processed.push(file); continue; }\n      \/\/ Scale down\n      if (w >= h){ h = Math.round(h * (MAX \/ w)); w = MAX; } else { w = Math.round(w * (MAX \/ h)); h = MAX; }\n      const c = document.createElement('canvas'); c.width = w; c.height = h;\n      const cx = c.getContext('2d'); cx.imageSmoothingQuality='high'; cx.drawImage(img, 0, 0, w, h);\n      const blob = await new Promise(res=> c.toBlob(res, 'image\/jpeg', 0.92));\n      if (blob){ processed.push(new File([blob], file.name.replace(\/\\.(png|webp)$\/i,'.jpg').replace(\/\\.(jpeg|jpg)$\/i,'.jpg'), {type:'image\/jpeg'})); }\n      else { processed.push(file); }\n    }\n    const dt = new DataTransfer();\n    processed.forEach(f=> dt.items.add(f));\n    fileInput.files = dt.files;\n    form.submit();\n  });\n\n})();\n<\/script>\n\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":{"footnotes":""},"class_list":["post-301","page","type-page","status-publish","hentry"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/pages\/301","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/comments?post=301"}],"version-history":[{"count":6,"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/pages\/301\/revisions"}],"predecessor-version":[{"id":498,"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/pages\/301\/revisions\/498"}],"wp:attachment":[{"href":"https:\/\/staging1.eudportal.dk\/index.php\/wp-json\/wp\/v2\/media?parent=301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}