1"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6152],{12940:(e,t,a)=>{a.d(t,{p:()=>n});let r="ea-admin-screenshot-hide",s="ea-admin-screenshot-style";async function o(e,t,a){let r=new Image;r.crossOrigin="anonymous",await new Promise((t,a)=>{r.onload=()=>t(),r.onerror=()=>a(Error("Screenshot image failed to load")),r.src=e});let s=Math.min(1,t/r.naturalWidth),o=Math.max(1,Math.round(r.naturalWidth*s)),n=Math.max(1,Math.round(r.naturalHeight*s)),i=document.createElement("canvas");i.width=o,i.height=n;let l=i.getContext("2d");if(!l)throw Error("Canvas 2D context unavailable");l.drawImage(r,0,0,o,n);let d=await new Promise(e=>i.toBlob(e,"image/webp",a));if(!d)throw Error("canvas.toBlob returned null");return d}async function n(){var e,t;let n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if("undefined"==typeof document)throw Error("captureViewportWebp must run in the browser");let i=null!=(e=n.maxWidth)?e:1200,l=null!=(t=n.quality)?t:.85;!function(){if("undefined"==typeof document||document.getElementById(s))return;let e=document.createElement("style");e.id=s,e.textContent=".".concat(r,"{visibility:hidden !important;}"),document.head.appendChild(e)}();let d=Array.from(document.querySelectorAll("[data-admin-modal]"));d.forEach(e=>e.classList.add(r));try{await new Promise(e=>requestAnimationFrame(()=>e(null)));let{domToDataUrl:e}=await a.e(4495).then(a.bind(a,94495)),t=await e(document.documentElement,{width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,backgroundColor:"#272936"});return await o(t,i,l)}finally{d.forEach(e=>e.classList.remove(r))}}},16152:(e,t,a)=>{a.r(t),a.d(t,{default:()=>h});var r=a(95155),s=a(12115),o=a(12940);let n={"image/webp":"webp","image/png":"png","image/jpeg":"jpg","video/mp4":"mp4","video/webm":"webm"},i={webp:"image/webp",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",mp4:"video/mp4",webm:"video/webm"},l=Object.keys(n).join(","),d=["typo","replace text","replace background","swap tile","swap poster","replace video"],c=new Set(["replace background","swap tile","swap poster","replace video"]);function p(){return{id:crypto.randomUUID(),page:"",where:"",change:"typo",assetText:"",assetBefore:"",assetAfter:"",assetFromUrl:"",assetUploading:!1,assetError:"",notes:""}}function h(e){let{onClose:t}
1=e,[a,h]=(0,s.useState)(()=>[p()]),[u,m]=(0,s.useState)(!0),[x,g]=(0,s.useState)(""),[w,b]=(0,s.useState)({kind:"idle"});function f(e,t){h(a=>a.map(a=>a.id===e?{...a,...t}:a))}async function y(e,t){let a=t.type&&t.type in n?t.type:i[t.name.toLowerCase().split(".").pop()||""]||null;if(!a)return void f(e,{assetError:"Unsupported file (".concat(t.type||t.name.split(".").pop()||"unknown","). Allowed: PNG, JPEG, WebP, MP4, WebM.")});if(t.size>0x3c00000){let a=Math.round(t.size/1048576);f(e,{assetError:"File too large (".concat(a," MB) â max 60 MB. Compress before upload.")});return}f(e,{assetUploading:!0,assetError:"",assetFromUrl:""});try{let r=n[a],s=await fetch("/api/admin/upload-url",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({contentType:a,extension:r})});if(!s.ok){let e=await s.text().catch(()=>"");throw Error("upload-url ".concat(s.status).concat(e?": ".concat(e.slice(0,120)):""))}let o=await s.json(),i=await fetch(o.url,{method:"PUT",headers:{"Content-Type":a},body:t});if(!i.ok){let e=await i.text().catch(()=>"");throw Error("R2 PUT ".concat(i.status).concat(e?": ".concat(e.slice(0,120)):""))}f(e,{assetFromUrl:o.publicUrl,assetUploading:!1})}catch(t){f(e,{assetUploading:!1,assetError:t instanceof Error?t.message:"asset_upload_failed"})}}async function v(e){if(e.preventDefault(),"submitting"===w.kind)return;let t=function(){if(0===a.length)return"Add at least one row.";if(a.length>25)return"Max 25 rows per batch.";for(let e=0;e<a.length;e++){let t=a[e];if(!t.page.trim())return"Row ".concat(e+1,": Page is required.");if(!t.where.trim())return"Row ".concat(e+1,": Where is required.");if("typo"===t.change){let a=t.assetBefore.trim(),r=t.assetAfter.trim();if(!a||!r)return"Row ".concat(e+1,": Typo needs both Before and After.");if(a===r)return"Row ".concat(e+1,": Typo Before and After must differ.")}if("replace text"===t.change&&!t.assetText.trim())return"Row ".concat(e+1,": Replacement text is required.");if(c.has(t.change)&&!t.assetFromUrl)return"Row ".concat(e+1,": Upload a media asset.");if(a[e].assetUploading)return"Row ".concat(e+1,": Asset still uploading.")}return null}();if(t)return void b({kind:"error",message:t});try{let e;if(u){b({kind:"submitting",step:"Capturing screenshotâ¦"});let t=await (0,o.p)(),a=await fetch("/api/admin/upload-url",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({contentType:"image/webp"})});if(!a.ok)throw Error("upload-url ".concat(a.status));let r=await a.json(),s=await fetch(r.url,{method:"PUT",headers:{"Content-Type":"image/webp"},body:t});if(!s.ok)throw Error("r2 PUT ".concat(s.status));e=r.publicUrl}b({kind:"submitting",step:"Dispatching workflowâ¦"});let t=a.map(e=>{let t={page:e.page.trim(),where:e.where.trim(),change:e.change,notes:e.notes.trim()||void 0};return"typo"===e.change?{...t,assetText:"".concat(e.assetBefore.trim()," â ").concat(e.assetAfter.trim())}:"replace text"===e.change?{...t,assetText:e.assetText.trim()}:{...t,assetFrom:e.assetFromUrl}}),r=await fetch("/api/admin/content-dispatch",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({rows:t,screenshotUrl:e,pageUrl:window.location.href,note:x.trim()||void 0})});if(!r.ok){let e=await r.json().catch(()=>({error:"unknown"}));throw Error(e.message||e.error||"HTTP ".concat(r.status))}b({kind:"success",rowCount:a.length})}catch(e){b({kind:"error",message:e instanceof Error?e.message:"dispatch_failed"})}}(0,s.useEffect)(()=>{let e=e=>{"Escape"===e.key&&"submitting"!==w.kind&&t()};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[t,w.kind]);let j="submitting"===w.kind;return(0,r.jsx)("div",{"data-admin-modal":!0,className:"fixed inset-0 z-[9999] flex items-center justify-center p-4 bg-black/70",role:"dialog","aria-modal":"true","aria-label":"Update content",onClick:e=>{e.target!==e.currentTarget||j||t()},children:(0,r.jsxs)("div",{className:"w-full max-w-3xl max-h-[90vh] rounded-xl bg-[var(--color-bg)] border border-white/15 shadow-2xl flex flex-col overflow-hidden",children:[(0,r.jsxs)("div",{className:"px-4 py-3 border-b border-white/10 flex items-center justify-between",children:[(0,r.jsxs)("h2",{className:"text-sm font-semibold text-[var(--color-heading)]",children:["Update content (",a.length,"/25 rows)"]}),(0,r.jsx)("button",{type:"button",onClick:t,disabled:j,className:"text-slate-300 hover:text-white disabled:opacity-40 cursor-pointer","aria-label":"Close",children:"â"})]}),"success"===w.kind?(0,r.jsxs)("div",{className:"p-4 space-y-3 text-sm text-slate-200",children:[(0,r.jsxs)("p",{children:["â
Dispatched ",w.rowCount," row",1===w.rowCount?"":"s",". The GitHub Action will run Claude Code headlessly; you'll get an ntfy push on"," ",(0,r.jsx)("code",{className:"text-[var(--color-primary)]",children:"ethospower-ai"})," ","when it finishes."]}),(0,r.jsx)("div",{className:"flex justify-end",children:(0,r.jsx)("button",{type:"button",onClick:t,className:"px-3 py-1.5 text-xs rounded-md bg-white/10 hover:bg-white/20 text-white cursor-pointer",children:"Close"})})]}):(0,r.jsxs)("form",{onSubmit:v,className:"flex-1 flex flex-col overflow-hidden",children:[(0,r.jsxs)("div",{className:"flex-1 overflow-y-auto p-4 space-y-3",children:[a.map((e,t)=>(0,r.jsxs)("div",{className:"rounded-md bg-white/5 border border-white/10 p-3 space-y-2",children:[(0,r.jsxs)("div",{className:"flex items-center justify-between",children:[(0,r.jsxs)("span",{className:"text-xs text-slate-400",children:["Row ",t+1]}),a.length>1&&(0,r.jsx)("button",{type:"button",onClick:()=>{var t;return t=e.id,void h(e=>e.length<=1?e:e.filter(e=>e.id!==t))},disabled:j,className:"text-xs text-red-300 hover:text-red-200 disabled:opacity-40 cursor-pointer",children:"Remove"})]}),(0,r.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-2",children:[(0,r.jsx)("input",{type:"text",value:e.page,onChange:t=>f(e.id,{page:t.target.value}),placeholder:"Page (e.g. /about, nav)",maxLength:500,disabled:j,className:"px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"}),(0,r.jsx)("input",{type:"text",value:e.where,onChange:t=>f(e.id,{where:t.target.value}),placeholder:"Where (e.g. Hero, Footer)",maxLength:500,disabled:j,className:"px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"}),(0,r.jsx)("select",{value:e.change,onChange:t=>f(e.id,{change:t.target.value,assetText:"",assetBefore:"",assetAfter:"",assetFromUrl:"",assetError:""}),disabled:j,className:"px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white focus:outline-none focus:border-[var(--color-primary)]",children:d.map(e=>(0,r.jsx)("option",{value:e,className:"bg-[var(--color-bg)]",children:e},e))})]}),"typo"===e.change&&(0,r.jsxs)("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:[(0,r.jsx)("input",{type:"text",value:e.assetBefore,onChange:t=>f(e.id,{assetBefore:t.target.value}),placeholder:"Before (e.g. enginer)",maxLength:2e3,disabled:j,className:"px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"}),(0,r.jsx)("input",{type:"text",value:e.assetAfter,onChange:t=>f(e.id,{assetAfter:t.target.value}),placeholder:"After (e.g. engineer)",maxLength:2e3,disabled:j,className:"px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"})]}),"replace text"===e.change&&(0,r.jsx)("input",{type:"text",value:e.assetText,onChange:t=>f(e.id,{assetText:t.target.value}),placeholder:"New text exactly as it should appear",maxLength:2e3,disabled:j,className:"w-full px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"}),c.has(e.change)&&(0,r.jsxs)("div",{className:"space-y-1",children:[(0,r.jsx)("input",{type:"file",accept:l,disabled:j||e.assetUploading,onChange:t=>{var a;let r=null==(a=t.target.files)?void 0:a[0];r&&y(e.id,r)},className:"w-full text-xs text-slate-200 file:mr-2 file:px-2 file:py-1 file:rounded-md file:border-0 file:bg-white/10 file:text-white file:cursor-pointer"}),e.assetUploading&&(0,r.jsx)("p",{className:"text-xs text-slate-400",children:"Uploadingâ¦"}),e.assetFromUrl&&!e.assetUploading&&(0,r.jsxs)("p",{className:"text-xs text-emerald-300 truncate",children:["Uploaded: ",e.assetFromUrl.split("/").pop()]}
1),e.assetError&&!e.assetUploading&&(0,r.jsxs)("p",{className:"text-xs text-red-300",children:["â ",e.assetError]})]}),(0,r.jsx)("input",{type:"text",value:e.notes,onChange:t=>f(e.id,{notes:t.target.value}),placeholder:"Notes (optional, e.g. 'crop centre')",maxLength:1e3,disabled:j,className:"w-full px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"})]},e.id)),(0,r.jsx)("button",{type:"button",onClick:()=>h(e=>e.length>=25?e:[...e,p()]),disabled:j||a.length>=25,className:"w-full px-3 py-1.5 text-xs rounded-md border border-dashed border-white/20 text-slate-300 hover:bg-white/5 disabled:opacity-40 cursor-pointer",children:"+ Add row"}),(0,r.jsxs)("div",{className:"pt-2 space-y-2",children:[(0,r.jsx)("textarea",{value:x,onChange:e=>g(e.target.value),placeholder:"Batch note (optional context for the builder)",maxLength:2e3,rows:2,disabled:j,className:"w-full px-2 py-1.5 rounded-md bg-white/5 border border-white/15 text-xs text-white placeholder:text-slate-400 focus:outline-none focus:border-[var(--color-primary)]"}),(0,r.jsxs)("label",{className:"flex items-center gap-2 text-xs text-slate-300 cursor-pointer",children:[(0,r.jsx)("input",{type:"checkbox",checked:u,onChange:e=>m(e.target.checked),disabled:j}),"Attach viewport screenshot"]})]})]}),(0,r.jsxs)("div",{className:"border-t border-white/10 px-4 py-3 flex items-center justify-between",children:[(0,r.jsx)("span",{className:"text-xs text-slate-400 truncate pr-2",children:j?w.step:"error"===w.kind?"â ".concat(w.message):" "}),(0,r.jsxs)("div",{className:"flex gap-2 shrink-0",children:[(0,r.jsx)("button",{type:"button",onClick:t,disabled:j,className:"px-3 py-1.5 text-xs rounded-md bg-white/5 hover:bg-white/10 text-slate-200 disabled:opacity-40 cursor-pointer",children:"Cancel"}),(0,r.jsx)("button",{type:"submit",disabled:j,className:"px-3 py-1.5 text-xs rounded-md bg-[var(--color-primary)] hover:bg-[var(--color-primary)]/90 text-white disabled:opacity-40 cursor-pointer",children:j?"Dispatchingâ¦":"Dispatch batch"})]})]})]})]})})}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.