)}
@@ -1304,7 +1306,7 @@ export function StoriesPage({ token, authFetch }: StoriesPageProps) {
doesn't disappear on a timer. */}
{publishError && (
diff --git a/app/web/dist/assets/export-cut-BqZI0-Rv.js b/app/web/dist/assets/export-cut-CDJl8Zjg.js
similarity index 98%
rename from app/web/dist/assets/export-cut-BqZI0-Rv.js
rename to app/web/dist/assets/export-cut-CDJl8Zjg.js
index 0062c83..e2b0206 100644
--- a/app/web/dist/assets/export-cut-BqZI0-Rv.js
+++ b/app/web/dist/assets/export-cut-CDJl8Zjg.js
@@ -1 +1 @@
-import{M as w,v as O,t as A,c as M,b as R,s as H,l as I,a as B,d as F}from"./index-C43toXVm.js";const z=w;async function G(e){if(typeof document>"u"||!document.fonts||typeof document.fonts.load!="function")return{ready:!0,missing:[]};const n=[];for(const s of e)try{const t=await document.fonts.load(`16px "${s}"`);!t||t.length===0?n.push(s):document.fonts.check(`16px "${s}"`)||n.push(s)}catch{n.push(s)}return{ready:n.length===0,missing:n}}function C(e){return new Promise((n,s)=>{const t=new Image;t.crossOrigin="anonymous",t.onload=()=>n(t),t.onerror=()=>s(new Error("Failed to load image")),t.src=e})}const W="rgba(255, 255, 255, 0.95)",_="#1a1a1a",L="rgba(244, 239, 230, 0.94)",N="rgba(26, 26, 26, 0.55)";function Y(e){return Math.max(2,e*.004)}function K(e,n,s,t,c,d,f){e.beginPath();for(const o of F(n,s,t,c,d,f))o.k==="M"?e.moveTo(o.x,o.y):o.k==="L"?e.lineTo(o.x,o.y):e.arcTo(o.cornerX,o.cornerY,o.x,o.y,o.r);e.closePath()}function P(e,n,s,t,c,d){var f;for(const o of n){const l=o.x*s,i=o.y*t,r=o.width*s,a=o.height*t,y=Y(t);if(o.type==="speech"){const u=R(o,r,a),k=o.tailAnchor?H(l,i,r,a,o.tailAnchor,u):null;K(e,l,i,r,a,k,u),e.fillStyle=W,e.fill(),e.strokeStyle=_,e.lineWidth=y,e.lineJoin="round",e.stroke()}else if(o.type==="narration"){const u=Math.min(r,a)*.12;e.beginPath(),e.roundRect(l,i,r,a,u),e.fillStyle=L,e.fill(),e.strokeStyle=N,e.lineWidth=Math.max(1.5,y*.75),e.lineJoin="round",e.stroke()}const g=o.type==="sfx"?d:c,T=o.type!=="sfx"&&!!o.speaker,h=I((u,k,E=400)=>(e.font=`${E} ${k}px ${g}`,e.measureText(u).width),o.text,r,a,B(o,t,r,a));e.textAlign="center",e.textBaseline="middle";const p=l+r/2,S=T?h.speakerFontSize*1.2:0;T&&(e.fillStyle="#3a3a3a",e.font=`700 ${h.speakerFontSize}px ${g}`,e.fillText(o.speaker,p,i+S/2+a*.04,r-6));const v=i+S,b=a-S,$=h.lines.length*h.lineHeight;let m=v+b/2-$/2+h.lineHeight/2;e.font=`${((f=o.textStyle)==null?void 0:f.fontWeight)??400} ${h.fontSize}px ${g}`;for(const u of h.lines)o.type==="sfx"?(e.fillStyle="#000",e.strokeStyle="#fff",e.lineWidth=3,e.strokeText(u,p,m),e.fillText(u,p,m)):(e.fillStyle="#1a1a1a",e.fillText(u,p,m)),m+=h.lineHeight}}function X(e,n,s,t,c){const d=Math.max(14,Math.min(t*.05,28));e.font=`${d}px ${c}`,e.fillStyle="#1a1a1a",e.textAlign="center",e.textBaseline="middle";const f=[];if(n.dialogue)for(const i of n.dialogue)f.push(`${i.speaker}: ${i.text}`);n.narration&&f.push(n.narration);const o=d*1.6,l=t/2-(f.length-1)*o/2;for(let i=0;i
z?{valid:!1,error:`Image is ${(e.size/1024).toFixed(0)}KB, exceeds 1MB limit`}:{valid:!0}}export{z as MAX_SIZE,G as ensureFontsReady,Z as exportCut,P as renderOverlays,A as textPanelDimensions,j as validateExportSize};
+import{M as w,v as O,t as A,c as M,b as R,s as H,l as I,a as B,d as F}from"./index-CP7cx6Zm.js";const z=w;async function G(e){if(typeof document>"u"||!document.fonts||typeof document.fonts.load!="function")return{ready:!0,missing:[]};const n=[];for(const s of e)try{const t=await document.fonts.load(`16px "${s}"`);!t||t.length===0?n.push(s):document.fonts.check(`16px "${s}"`)||n.push(s)}catch{n.push(s)}return{ready:n.length===0,missing:n}}function C(e){return new Promise((n,s)=>{const t=new Image;t.crossOrigin="anonymous",t.onload=()=>n(t),t.onerror=()=>s(new Error("Failed to load image")),t.src=e})}const W="rgba(255, 255, 255, 0.95)",_="#1a1a1a",L="rgba(244, 239, 230, 0.94)",N="rgba(26, 26, 26, 0.55)";function Y(e){return Math.max(2,e*.004)}function K(e,n,s,t,c,d,f){e.beginPath();for(const o of F(n,s,t,c,d,f))o.k==="M"?e.moveTo(o.x,o.y):o.k==="L"?e.lineTo(o.x,o.y):e.arcTo(o.cornerX,o.cornerY,o.x,o.y,o.r);e.closePath()}function P(e,n,s,t,c,d){var f;for(const o of n){const l=o.x*s,i=o.y*t,r=o.width*s,a=o.height*t,y=Y(t);if(o.type==="speech"){const u=R(o,r,a),k=o.tailAnchor?H(l,i,r,a,o.tailAnchor,u):null;K(e,l,i,r,a,k,u),e.fillStyle=W,e.fill(),e.strokeStyle=_,e.lineWidth=y,e.lineJoin="round",e.stroke()}else if(o.type==="narration"){const u=Math.min(r,a)*.12;e.beginPath(),e.roundRect(l,i,r,a,u),e.fillStyle=L,e.fill(),e.strokeStyle=N,e.lineWidth=Math.max(1.5,y*.75),e.lineJoin="round",e.stroke()}const g=o.type==="sfx"?d:c,T=o.type!=="sfx"&&!!o.speaker,h=I((u,k,E=400)=>(e.font=`${E} ${k}px ${g}`,e.measureText(u).width),o.text,r,a,B(o,t,r,a));e.textAlign="center",e.textBaseline="middle";const p=l+r/2,S=T?h.speakerFontSize*1.2:0;T&&(e.fillStyle="#3a3a3a",e.font=`700 ${h.speakerFontSize}px ${g}`,e.fillText(o.speaker,p,i+S/2+a*.04,r-6));const v=i+S,b=a-S,$=h.lines.length*h.lineHeight;let m=v+b/2-$/2+h.lineHeight/2;e.font=`${((f=o.textStyle)==null?void 0:f.fontWeight)??400} ${h.fontSize}px ${g}`;for(const u of h.lines)o.type==="sfx"?(e.fillStyle="#000",e.strokeStyle="#fff",e.lineWidth=3,e.strokeText(u,p,m),e.fillText(u,p,m)):(e.fillStyle="#1a1a1a",e.fillText(u,p,m)),m+=h.lineHeight}}function X(e,n,s,t,c){const d=Math.max(14,Math.min(t*.05,28));e.font=`${d}px ${c}`,e.fillStyle="#1a1a1a",e.textAlign="center",e.textBaseline="middle";const f=[];if(n.dialogue)for(const i of n.dialogue)f.push(`${i.speaker}: ${i.text}`);n.narration&&f.push(n.narration);const o=d*1.6,l=t/2-(f.length-1)*o/2;for(let i=0;iz?{valid:!1,error:`Image is ${(e.size/1024).toFixed(0)}KB, exceeds 1MB limit`}:{valid:!0}}export{z as MAX_SIZE,G as ensureFontsReady,Z as exportCut,P as renderOverlays,A as textPanelDimensions,j as validateExportSize};
diff --git a/app/web/dist/assets/index-C43toXVm.js b/app/web/dist/assets/index-CP7cx6Zm.js
similarity index 97%
rename from app/web/dist/assets/index-C43toXVm.js
rename to app/web/dist/assets/index-CP7cx6Zm.js
index 3859e56..f165fdd 100644
--- a/app/web/dist/assets/index-C43toXVm.js
+++ b/app/web/dist/assets/index-CP7cx6Zm.js
@@ -127,9 +127,9 @@ WARNING: This link could potentially be dangerous`)){let i=window.open();if(i){t
`,...o.current()});return/^[\t ]/.test(f)&&(f=Oo(f.charCodeAt(0))+f.slice(1)),f=f?c+" "+f:c,i.options.closeAtx&&(f+=" "+c),p(),h(),f}dS.peek=cR;function dS(e){return e.value||""}function cR(){return"<"}fS.peek=uR;function fS(e,t,i,s){const a=pm(i),o=a==='"'?"Quote":"Apostrophe",c=i.enter("image");let h=i.enter("label");const p=i.createTracker(s);let f=p.move("![");return f+=p.move(i.safe(e.alt,{before:f,after:"]",...p.current()})),f+=p.move("]("),h(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(h=i.enter("destinationLiteral"),f+=p.move("<"),f+=p.move(i.safe(e.url,{before:f,after:">",...p.current()})),f+=p.move(">")):(h=i.enter("destinationRaw"),f+=p.move(i.safe(e.url,{before:f,after:e.title?" ":")",...p.current()}))),h(),e.title&&(h=i.enter(`title${o}`),f+=p.move(" "+a),f+=p.move(i.safe(e.title,{before:f,after:a,...p.current()})),f+=p.move(a),h()),f+=p.move(")"),c(),f}function uR(){return"!"}pS.peek=hR;function pS(e,t,i,s){const a=e.referenceType,o=i.enter("imageReference");let c=i.enter("label");const h=i.createTracker(s);let p=h.move("![");const f=i.safe(e.alt,{before:p,after:"]",...h.current()});p+=h.move(f+"]["),c();const _=i.stack;i.stack=[],c=i.enter("reference");const x=i.safe(i.associationId(e),{before:p,after:"]",...h.current()});return c(),i.stack=_,o(),a==="full"||!f||f!==x?p+=h.move(x+"]"):a==="shortcut"?p=p.slice(0,-1):p+=h.move("]"),p}function hR(){return"!"}mS.peek=dR;function mS(e,t,i){let s=e.value||"",a="`",o=-1;for(;new RegExp("(^|[^`])"+a+"([^`]|$)").test(s);)a+="`";for(/[^ \r\n]/.test(s)&&(/^[ \r\n]/.test(s)&&/[ \r\n]$/.test(s)||/^`|`$/.test(s))&&(s=" "+s+" ");++o\u007F]/.test(e.url))}xS.peek=fR;function xS(e,t,i,s){const a=pm(i),o=a==='"'?"Quote":"Apostrophe",c=i.createTracker(s);let h,p;if(gS(e,i)){const _=i.stack;i.stack=[],h=i.enter("autolink");let x=c.move("<");return x+=c.move(i.containerPhrasing(e,{before:x,after:">",...c.current()})),x+=c.move(">"),h(),i.stack=_,x}h=i.enter("link"),p=i.enter("label");let f=c.move("[");return f+=c.move(i.containerPhrasing(e,{before:f,after:"](",...c.current()})),f+=c.move("]("),p(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(p=i.enter("destinationLiteral"),f+=c.move("<"),f+=c.move(i.safe(e.url,{before:f,after:">",...c.current()})),f+=c.move(">")):(p=i.enter("destinationRaw"),f+=c.move(i.safe(e.url,{before:f,after:e.title?" ":")",...c.current()}))),p(),e.title&&(p=i.enter(`title${o}`),f+=c.move(" "+a),f+=c.move(i.safe(e.title,{before:f,after:a,...c.current()})),f+=c.move(a),p()),f+=c.move(")"),h(),f}function fR(e,t,i){return gS(e,i)?"<":"["}_S.peek=pR;function _S(e,t,i,s){const a=e.referenceType,o=i.enter("linkReference");let c=i.enter("label");const h=i.createTracker(s);let p=h.move("[");const f=i.containerPhrasing(e,{before:p,after:"]",...h.current()});p+=h.move(f+"]["),c();const _=i.stack;i.stack=[],c=i.enter("reference");const x=i.safe(i.associationId(e),{before:p,after:"]",...h.current()});return c(),i.stack=_,o(),a==="full"||!f||f!==x?p+=h.move(x+"]"):a==="shortcut"?p=p.slice(0,-1):p+=h.move("]"),p}function pR(){return"["}function mm(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function mR(e){const t=mm(e),i=e.options.bulletOther;if(!i)return t==="*"?"-":"*";if(i!=="*"&&i!=="+"&&i!=="-")throw new Error("Cannot serialize items with `"+i+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(i===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+i+"`) to be different");return i}function gR(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function bS(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function xR(e,t,i,s){const a=i.enter("list"),o=i.bulletCurrent;let c=e.ordered?gR(i):mm(i);const h=e.ordered?c==="."?")":".":mR(i);let p=t&&i.bulletLastUsed?c===i.bulletLastUsed:!1;if(!e.ordered){const _=e.children?e.children[0]:void 0;if((c==="*"||c==="-")&&_&&(!_.children||!_.children[0])&&i.stack[i.stack.length-1]==="list"&&i.stack[i.stack.length-2]==="listItem"&&i.stack[i.stack.length-3]==="list"&&i.stack[i.stack.length-4]==="listItem"&&i.indexStack[i.indexStack.length-1]===0&&i.indexStack[i.indexStack.length-2]===0&&i.indexStack[i.indexStack.length-3]===0&&(p=!0),bS(i)===c&&_){let x=-1;for(;++x-1?t.start:1)+(i.options.incrementListMarker===!1?0:t.children.indexOf(e))+o);let c=o.length+1;(a==="tab"||a==="mixed"&&(t&&t.type==="list"&&t.spread||e.spread))&&(c=Math.ceil(c/4)*4);const h=i.createTracker(s);h.move(o+" ".repeat(c-o.length)),h.shift(c);const p=i.enter("listItem"),f=i.indentLines(i.containerFlow(e,h.current()),_);return p(),f;function _(x,b,v){return b?(v?"":" ".repeat(c))+x:(v?o:o+" ".repeat(c-o.length))+x}}function vR(e,t,i,s){const a=i.enter("paragraph"),o=i.enter("phrasing"),c=i.containerPhrasing(e,s);return o(),a(),c}const yR=Wu(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function SR(e,t,i,s){return(e.children.some(function(c){return yR(c)})?i.containerPhrasing:i.containerFlow).call(i,e,s)}function wR(e){const t=e.options.strong||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize strong with `"+t+"` for `options.strong`, expected `*`, or `_`");return t}vS.peek=CR;function vS(e,t,i,s){const a=wR(i),o=i.enter("strong"),c=i.createTracker(s),h=c.move(a+a);let p=c.move(i.containerPhrasing(e,{after:a,before:h,...c.current()}));const f=p.charCodeAt(0),_=Lu(s.before.charCodeAt(s.before.length-1),f,a);_.inside&&(p=Oo(f)+p.slice(1));const x=p.charCodeAt(p.length-1),b=Lu(s.after.charCodeAt(0),x,a);b.inside&&(p=p.slice(0,-1)+Oo(x));const v=c.move(a+a);return o(),i.attentionEncodeSurroundingInfo={after:b.outside,before:_.outside},h+p+v}function CR(e,t,i){return i.options.strong||"*"}function kR(e,t,i,s){return i.safe(e.value,s)}function ER(e){const t=e.options.ruleRepetition||3;if(t<3)throw new Error("Cannot serialize rules with repetition `"+t+"` for `options.ruleRepetition`, expected `3` or more");return t}function NR(e,t,i){const s=(bS(i)+(i.options.ruleSpaces?" ":"")).repeat(ER(i));return i.options.ruleSpaces?s.slice(0,-1):s}const yS={blockquote:XA,break:Gv,code:iR,definition:rR,emphasis:hS,hardBreak:Gv,heading:oR,html:dS,image:fS,imageReference:pS,inlineCode:mS,link:xS,linkReference:_S,list:xR,listItem:bR,paragraph:vR,root:SR,strong:vS,text:kR,thematicBreak:NR};function jR(){return{enter:{table:TR,tableData:Yv,tableHeader:Yv,tableRow:RR},exit:{codeText:DR,table:AR,tableData:Rf,tableHeader:Rf,tableRow:Rf}}}function TR(e){const t=e._align;this.enter({type:"table",align:t.map(function(i){return i==="none"?null:i}),children:[]},e),this.data.inTable=!0}function AR(e){this.exit(e),this.data.inTable=void 0}function RR(e){this.enter({type:"tableRow",children:[]},e)}function Rf(e){this.exit(e)}function Yv(e){this.enter({type:"tableCell",children:[]},e)}function DR(e){let t=this.resume();this.data.inTable&&(t=t.replace(/\\([\\|])/g,MR));const i=this.stack[this.stack.length-1];i.type,i.value=t,this.exit(e)}function MR(e,t){return t==="|"?t:e}function BR(e){const t=e||{},i=t.tableCellPadding,s=t.tablePipeAlign,a=t.stringLength,o=i?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:`
`,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:b,table:c,tableCell:p,tableRow:h}};function c(v,S,j,R){return f(_(v,j,R),v.align)}function h(v,S,j,R){const E=x(v,j,R),N=f([E]);return N.slice(0,N.indexOf(`
`))}function p(v,S,j,R){const E=j.enter("tableCell"),N=j.enter("phrasing"),I=j.containerPhrasing(v,{...R,before:o,after:o});return N(),E(),I}function f(v,S){return KA(v,{align:S,alignDelimiters:s,padding:i,stringLength:a})}function _(v,S,j){const R=v.children;let E=-1;const N=[],I=S.enter("table");for(;++E0&&!i&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),i}const QR={tokenize:a3,partial:!0};function JR(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:n3,continuation:{tokenize:r3},exit:s3}},text:{91:{name:"gfmFootnoteCall",tokenize:i3},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:e3,resolveTo:t3}}}}function e3(e,t,i){const s=this;let a=s.events.length;const o=s.parser.gfmFootnotes||(s.parser.gfmFootnotes=[]);let c;for(;a--;){const p=s.events[a][1];if(p.type==="labelImage"){c=p;break}if(p.type==="gfmFootnoteCall"||p.type==="labelLink"||p.type==="label"||p.type==="image"||p.type==="link")break}return h;function h(p){if(!c||!c._balanced)return i(p);const f=fr(s.sliceSerialize({start:c.end,end:s.now()}));return f.codePointAt(0)!==94||!o.includes(f.slice(1))?i(p):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(p),e.exit("gfmFootnoteCallLabelMarker"),t(p))}}function t3(e,t){let i=e.length;for(;i--;)if(e[i][1].type==="labelImage"&&e[i][0]==="enter"){e[i][1];break}e[i+1][1].type="data",e[i+3][1].type="gfmFootnoteCallLabelMarker";const s={type:"gfmFootnoteCall",start:Object.assign({},e[i+3][1].start),end:Object.assign({},e[e.length-1][1].end)},a={type:"gfmFootnoteCallMarker",start:Object.assign({},e[i+3][1].end),end:Object.assign({},e[i+3][1].end)};a.end.column++,a.end.offset++,a.end._bufferIndex++;const o={type:"gfmFootnoteCallString",start:Object.assign({},a.end),end:Object.assign({},e[e.length-1][1].start)},c={type:"chunkString",contentType:"string",start:Object.assign({},o.start),end:Object.assign({},o.end)},h=[e[i+1],e[i+2],["enter",s,t],e[i+3],e[i+4],["enter",a,t],["exit",a,t],["enter",o,t],["enter",c,t],["exit",c,t],["exit",o,t],e[e.length-2],e[e.length-1],["exit",s,t]];return e.splice(i,e.length-i+1,...h),e}function i3(e,t,i){const s=this,a=s.parser.gfmFootnotes||(s.parser.gfmFootnotes=[]);let o=0,c;return h;function h(x){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(x),e.exit("gfmFootnoteCallLabelMarker"),p}function p(x){return x!==94?i(x):(e.enter("gfmFootnoteCallMarker"),e.consume(x),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",f)}function f(x){if(o>999||x===93&&!c||x===null||x===91||qt(x))return i(x);if(x===93){e.exit("chunkString");const b=e.exit("gfmFootnoteCallString");return a.includes(fr(s.sliceSerialize(b)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(x),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),t):i(x)}return qt(x)||(c=!0),o++,e.consume(x),x===92?_:f}function _(x){return x===91||x===92||x===93?(e.consume(x),o++,f):f(x)}}function n3(e,t,i){const s=this,a=s.parser.gfmFootnotes||(s.parser.gfmFootnotes=[]);let o,c=0,h;return p;function p(S){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(S),e.exit("gfmFootnoteDefinitionLabelMarker"),f}function f(S){return S===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(S),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",_):i(S)}function _(S){if(c>999||S===93&&!h||S===null||S===91||qt(S))return i(S);if(S===93){e.exit("chunkString");const j=e.exit("gfmFootnoteDefinitionLabelString");return o=fr(s.sliceSerialize(j)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(S),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),b}return qt(S)||(h=!0),c++,e.consume(S),S===92?x:_}function x(S){return S===91||S===92||S===93?(e.consume(S),c++,_):_(S)}function b(S){return S===58?(e.enter("definitionMarker"),e.consume(S),e.exit("definitionMarker"),a.includes(o)||a.push(o),kt(e,v,"gfmFootnoteDefinitionWhitespace")):i(S)}function v(S){return t(S)}}function r3(e,t,i){return e.check(Fo,t,e.attempt(QR,t,i))}function s3(e){e.exit("gfmFootnoteDefinition")}function a3(e,t,i){const s=this;return kt(e,a,"gfmFootnoteDefinitionIndent",5);function a(o){const c=s.events[s.events.length-1];return c&&c[1].type==="gfmFootnoteDefinitionIndent"&&c[2].sliceSerialize(c[1],!0).length===4?t(o):i(o)}}function l3(e){let i=(e||{}).singleTilde;const s={name:"strikethrough",tokenize:o,resolveAll:a};return i==null&&(i=!0),{text:{126:s},insideSpan:{null:[s]},attentionMarkers:{null:[126]}};function a(c,h){let p=-1;for(;++p1?p(S):(c.consume(S),x++,v);if(x<2&&!i)return p(S);const R=c.exit("strikethroughSequenceTemporary"),E=ml(S);return R._open=!E||E===2&&!!j,R._close=!j||j===2&&!!E,h(S)}}}class o3{constructor(){this.map=[]}add(t,i,s){c3(this,t,i,s)}consume(t){if(this.map.sort(function(o,c){return o[0]-c[0]}),this.map.length===0)return;let i=this.map.length;const s=[];for(;i>0;)i-=1,s.push(t.slice(this.map[i][0]+this.map[i][1]),this.map[i][2]),t.length=this.map[i][0];s.push(t.slice()),t.length=0;let a=s.pop();for(;a;){for(const o of a)t.push(o);a=s.pop()}this.map.length=0}}function c3(e,t,i,s){let a=0;if(!(i===0&&s.length===0)){for(;a-1;){const X=s.events[ce][1].type;if(X==="lineEnding"||X==="linePrefix")ce--;else break}const W=ce>-1?s.events[ce][1].type:null,K=W==="tableHead"||W==="tableRow"?D:p;return K===D&&s.parser.lazy[s.now().line]?i(H):K(H)}function p(H){return e.enter("tableHead"),e.enter("tableRow"),f(H)}function f(H){return H===124||(c=!0,o+=1),_(H)}function _(H){return H===null?i(H):Ye(H)?o>1?(o=0,s.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(H),e.exit("lineEnding"),v):i(H):gt(H)?kt(e,_,"whitespace")(H):(o+=1,c&&(c=!1,a+=1),H===124?(e.enter("tableCellDivider"),e.consume(H),e.exit("tableCellDivider"),c=!0,_):(e.enter("data"),x(H)))}function x(H){return H===null||H===124||qt(H)?(e.exit("data"),_(H)):(e.consume(H),H===92?b:x)}function b(H){return H===92||H===124?(e.consume(H),x):x(H)}function v(H){return s.interrupt=!1,s.parser.lazy[s.now().line]?i(H):(e.enter("tableDelimiterRow"),c=!1,gt(H)?kt(e,S,"linePrefix",s.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(H):S(H))}function S(H){return H===45||H===58?R(H):H===124?(c=!0,e.enter("tableCellDivider"),e.consume(H),e.exit("tableCellDivider"),j):F(H)}function j(H){return gt(H)?kt(e,R,"whitespace")(H):R(H)}function R(H){return H===58?(o+=1,c=!0,e.enter("tableDelimiterMarker"),e.consume(H),e.exit("tableDelimiterMarker"),E):H===45?(o+=1,E(H)):H===null||Ye(H)?te(H):F(H)}function E(H){return H===45?(e.enter("tableDelimiterFiller"),N(H)):F(H)}function N(H){return H===45?(e.consume(H),N):H===58?(c=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(H),e.exit("tableDelimiterMarker"),I):(e.exit("tableDelimiterFiller"),I(H))}function I(H){return gt(H)?kt(e,te,"whitespace")(H):te(H)}function te(H){return H===124?S(H):H===null||Ye(H)?!c||a!==o?F(H):(e.exit("tableDelimiterRow"),e.exit("tableHead"),t(H)):F(H)}function F(H){return i(H)}function D(H){return e.enter("tableRow"),ie(H)}function ie(H){return H===124?(e.enter("tableCellDivider"),e.consume(H),e.exit("tableCellDivider"),ie):H===null||Ye(H)?(e.exit("tableRow"),t(H)):gt(H)?kt(e,ie,"whitespace")(H):(e.enter("data"),fe(H))}function fe(H){return H===null||H===124||qt(H)?(e.exit("data"),ie(H)):(e.consume(H),H===92?Se:fe)}function Se(H){return H===92||H===124?(e.consume(H),fe):fe(H)}}function f3(e,t){let i=-1,s=!0,a=0,o=[0,0,0,0],c=[0,0,0,0],h=!1,p=0,f,_,x;const b=new o3;for(;++ii[2]+1){const S=i[2]+1,j=i[3]-i[2]-1;e.add(S,j,[])}}e.add(i[3]+1,0,[["exit",x,t]])}return a!==void 0&&(o.end=Object.assign({},ol(t.events,a)),e.add(a,0,[["exit",o,t]]),o=void 0),o}function Vv(e,t,i,s,a){const o=[],c=ol(t.events,i);a&&(a.end=Object.assign({},c),o.push(["exit",a,t])),s.end=Object.assign({},c),o.push(["exit",s,t]),e.add(i+1,0,o)}function ol(e,t){const i=e[t],s=i[0]==="enter"?"start":"end";return i[1][s]}const p3={name:"tasklistCheck",tokenize:g3};function m3(){return{text:{91:p3}}}function g3(e,t,i){const s=this;return a;function a(p){return s.previous!==null||!s._gfmTasklistFirstContentOfListItem?i(p):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(p),e.exit("taskListCheckMarker"),o)}function o(p){return qt(p)?(e.enter("taskListCheckValueUnchecked"),e.consume(p),e.exit("taskListCheckValueUnchecked"),c):p===88||p===120?(e.enter("taskListCheckValueChecked"),e.consume(p),e.exit("taskListCheckValueChecked"),c):i(p)}function c(p){return p===93?(e.enter("taskListCheckMarker"),e.consume(p),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),h):i(p)}function h(p){return Ye(p)?t(p):gt(p)?e.check({tokenize:x3},t,i)(p):i(p)}}function x3(e,t,i){return kt(e,s,"whitespace");function s(a){return a===null?i(a):t(a)}}function _3(e){return z0([FR(),JR(),l3(e),h3(),m3()])}const b3={};function AS(e){const t=this,i=e||b3,s=t.data(),a=s.micromarkExtensions||(s.micromarkExtensions=[]),o=s.fromMarkdownExtensions||(s.fromMarkdownExtensions=[]),c=s.toMarkdownExtensions||(s.toMarkdownExtensions=[]);a.push(_3(i)),o.push(IR()),c.push(HR(i))}const ha=["ariaDescribedBy","ariaLabel","ariaLabelledBy"],gl={ancestors:{tbody:["table"],td:["table"],th:["table"],thead:["table"],tfoot:["table"],tr:["table"]},attributes:{a:[...ha,"dataFootnoteBackref","dataFootnoteRef",["className","data-footnote-backref"],"href"],blockquote:["cite"],code:[["className",/^language-./]],del:["cite"],div:["itemScope","itemType"],dl:[...ha],h2:[["className","sr-only"]],img:[...ha,"longDesc","src"],input:[["disabled",!0],["type","checkbox"]],ins:["cite"],li:[["className","task-list-item"]],ol:[...ha,["className","contains-task-list"]],q:["cite"],section:["dataFootnotes",["className","footnotes"]],source:["srcSet"],summary:[...ha],table:[...ha],ul:[...ha,["className","contains-task-list"]],"*":["abbr","accept","acceptCharset","accessKey","action","align","alt","axis","border","cellPadding","cellSpacing","char","charOff","charSet","checked","clear","colSpan","color","cols","compact","coords","dateTime","dir","encType","frame","hSpace","headers","height","hrefLang","htmlFor","id","isMap","itemProp","label","lang","maxLength","media","method","multiple","name","noHref","noShade","noWrap","open","prompt","readOnly","rev","rowSpan","rows","rules","scope","selected","shape","size","span","start","summary","tabIndex","title","useMap","vAlign","value","width"]},clobber:["ariaDescribedBy","ariaLabelledBy","id","name"],clobberPrefix:"user-content-",protocols:{cite:["http","https"],href:["http","https","irc","ircs","mailto","xmpp"],longDesc:["http","https"],src:["http","https"]},required:{input:{disabled:!0,type:"checkbox"}},strip:["script"],tagNames:["a","b","blockquote","br","code","dd","del","details","div","dl","dt","em","h1","h2","h3","h4","h5","h6","hr","i","img","input","ins","kbd","li","ol","p","picture","pre","q","rp","rt","ruby","s","samp","section","source","span","strike","strong","sub","summary","sup","table","tbody","td","tfoot","th","thead","tr","tt","ul","var"]},Ps={}.hasOwnProperty;function v3(e,t){let i={type:"root",children:[]};const s={schema:t?{...gl,...t}:gl,stack:[]},a=RS(s,e);return a&&(Array.isArray(a)?a.length===1?i=a[0]:i.children=a:i=a),i}function RS(e,t){if(t&&typeof t=="object"){const i=t;switch(typeof i.type=="string"?i.type:""){case"comment":return y3(e,i);case"doctype":return S3(e,i);case"element":return w3(e,i);case"root":return C3(e,i);case"text":return k3(e,i)}}}function y3(e,t){if(e.schema.allowComments){const i=typeof t.value=="string"?t.value:"",s=i.indexOf("-->"),o={type:"comment",value:s<0?i:i.slice(0,s)};return Wo(o,t),o}}function S3(e,t){if(e.schema.allowDoctypes){const i={type:"doctype"};return Wo(i,t),i}}function w3(e,t){const i=typeof t.tagName=="string"?t.tagName:"";e.stack.push(i);const s=DS(e,t.children),a=E3(e,t.properties);e.stack.pop();let o=!1;if(i&&i!=="*"&&(!e.schema.tagNames||e.schema.tagNames.includes(i))&&(o=!0,e.schema.ancestors&&Ps.call(e.schema.ancestors,i))){const h=e.schema.ancestors[i];let p=-1;for(o=!1;++p1){let a=!1,o=0;for(;++o-1&&o>p||c>-1&&o>c||h>-1&&o>h)return!0;let f=-1;for(;++f4&&t.slice(0,4).toLowerCase()==="data")return i}function BS(e){return function(t){return v3(t,e)}}const dl=["Romance","Fantasy","Science Fiction","Mystery","Thriller","Horror","Adventure","Historical Fiction","Contemporary Lit","Humor","Poetry","Non-Fiction","Fanfiction","Short Story","Paranormal","Werewolf","LGBTQ+","New Adult","Teen Fiction","Diverse Lit","Others"],ts=["English","Chinese","Korean","Japanese","Spanish","French","Hindi","Arabic","Portuguese","Russian","Others"];function LS(e){return e.toLowerCase().replace(/[^a-z0-9+]/g,"")}const T3=Object.fromEntries(dl.map(e=>[LS(e),e])),A3={scifi:"Science Fiction",sf:"Science Fiction",comedy:"Humor",humour:"Humor",ya:"Teen Fiction",youngadult:"Teen Fiction",lgbt:"LGBTQ+",lgbtq:"LGBTQ+","lgbtqia+":"LGBTQ+",historical:"Historical Fiction",scary:"Horror"};function Cu(e){if(!e)return null;const t=LS(e.trim());return t?T3[t]??A3[t]??null:null}function OS(e,t){const i=t.startsWith("assets/")?t.slice(7):t;return`/api/stories/${e}/asset/${i}`}function zS(e,t,i){const[s,a]=w.useState({url:null,loading:!!t,error:!1});return w.useEffect(()=>{if(!t){a({url:null,loading:!1,error:!1});return}let o=null,c=!1;return a({url:null,loading:!0,error:!1}),(async()=>{try{const h=await i(OS(e,t));if(!h.ok)throw new Error(`asset request failed (${h.status})`);const p=await h.blob();if(c)return;o=URL.createObjectURL(p),a({url:o,loading:!1,error:!1})}catch{c||a({url:null,loading:!1,error:!0})}})(),()=>{c=!0,o&&URL.revokeObjectURL(o)}},[e,t,i]),s}function Bp({storyName:e,assetPath:t,authFetch:i,alt:s,className:a}){const{url:o,loading:c,error:h}=zS(e,t,i);return h||!c&&!o?d.jsx("div",{className:"w-full aspect-video bg-surface border border-border rounded flex items-center justify-center",children:d.jsx("span",{className:"text-xs text-muted",children:"Image not available"})}):o?d.jsx("img",{src:o,alt:s,className:a??"w-full rounded border border-border"}):d.jsx("div",{className:"w-full aspect-video bg-surface border border-border rounded flex items-center justify-center","data-testid":"asset-loading",children:d.jsx("span",{className:"text-xs text-muted",children:"Loading image…"})})}function Qv(e,t,i,s){const a=t.split(/\s+/).filter(Boolean);if(a.length===0)return[""];const o=[];let c="";for(const h of a){const p=c?`${c} ${h}`:h;!c||e(p,s)<=i?c=p:(o.push(c),c=h)}return c&&o.push(c),o}function uu(e,t,i,s,a){const o=a.lineHeightFactor??1.2,c=a.speakerScale??.8,h=a.paddingX??Math.max(2,i*.06),p=a.paddingY??Math.max(2,s*.08),f=Math.max(1,i-2*h),_=Math.max(1,s-2*p),x=Math.max(a.minFontSize,a.maxFontSize),b=Math.max(1,Math.min(a.minFontSize,x)),v=j=>{const R=a.hasSpeaker?j*c:0,E=a.hasSpeaker?R*o:0,N=Math.max(1,_-E),I=a.fontWeight??400,te=Qv((ie,fe)=>e(ie,fe,I),t,f,j),F=te.length*j*o,D=te.every(ie=>e(ie,j,I)<=f+.5);return{lines:te,ok:F<=N&&D}};if(typeof a.fontSize=="number"&&Number.isFinite(a.fontSize)&&a.fontSize>0){const j=Math.max(1,a.fontSize),{lines:R,ok:E}=v(j);return{lines:R,fontSize:j,lineHeight:j*o,speakerFontSize:a.hasSpeaker?j*c:0,overflow:!E}}for(let j=x;j>=b;j-=.5){const{lines:R,ok:E}=v(j);if(E)return{lines:R,fontSize:j,lineHeight:j*o,speakerFontSize:a.hasSpeaker?j*c:0,overflow:!1}}return{lines:Qv(e,t,f,b),fontSize:b,lineHeight:b*o,speakerFontSize:a.hasSpeaker?b*c:0,overflow:!0}}function R3(e){return{minFontSize:Math.max(1,e*.022),maxFontSize:Math.max(1,e*.05)}}const PS=["speech","narration","sfx"],D3=2;function Ar(e,t,i){return Math.min(i,Math.max(t,e))}function fl(e,t,i){return typeof e=="number"&&Number.isFinite(e)?Ar(e,t,i):void 0}function xm(e){if(!e||typeof e!="object")return;const t=e,i=t.mode==="manual"?"manual":t.mode==="auto"?"auto":void 0,s=fl(t.fontScale,.015,.12),a=t.fontWeight===700?700:t.fontWeight===400?400:void 0,o=fl(t.lineHeightFactor,.9,2),c=fl(t.speakerScale,.5,1.5);if(!(!i&&s===void 0&&a===void 0&&o===void 0&&c===void 0))return{...i?{mode:i}:{},...s!==void 0?{fontScale:s}:{},...a!==void 0?{fontWeight:a}:{},...o!==void 0?{lineHeightFactor:o}:{},...c!==void 0?{speakerScale:c}:{}}}function Yu(e){if(!e||typeof e!="object")return;const t=e,i=fl(t.paddingX,0,.25),s=fl(t.paddingY,0,.25),a=fl(t.cornerRadius,0,.49);if(!(i===void 0&&s===void 0&&a===void 0))return{...i!==void 0?{paddingX:i}:{},...s!==void 0?{paddingY:s}:{},...a!==void 0?{cornerRadius:a}:{}}}function hu(e,t,i,s){const{minFontSize:a,maxFontSize:o}=R3(t),c=xm(e.textStyle),h=Yu(e.bubbleStyle);return{minFontSize:a,maxFontSize:o,hasSpeaker:e.type!=="sfx"&&!!e.speaker,...(c==null?void 0:c.lineHeightFactor)!==void 0?{lineHeightFactor:c.lineHeightFactor}:{},...(c==null?void 0:c.speakerScale)!==void 0?{speakerScale:c.speakerScale}:{},...(c==null?void 0:c.fontWeight)!==void 0?{fontWeight:c.fontWeight}:{},...(c==null?void 0:c.mode)==="manual"&&c.fontScale!==void 0?{fontSize:Math.max(1,t*c.fontScale)}:{},...(h==null?void 0:h.paddingX)!==void 0?{paddingX:i*h.paddingX}:{},...(h==null?void 0:h.paddingY)!==void 0?{paddingY:s*h.paddingY}:{}}}function M3(e,t,i){const s=Yu(e.bubbleStyle);return(s==null?void 0:s.cornerRadius)!==void 0?Math.min(t,i)*s.cornerRadius:void 0}function IS(e,t){const i=Math.min(e,t);return Math.max(0,Math.min(i*.4,i/2))}function Jv(e,t,i,s,a){const o=Math.max(0,i-2*s),c=Math.max(1,Math.min(a,o)/2),h=t+s+c,p=t+i-s-c;return{center:p>=h?Ar(e,h,p):t+i/2,half:c}}function HS(e,t,i,s,a,o){const c=e+i/2,h=t+s/2,p=e+a.x*i,f=t+a.y*s;if(p>=e&&p<=e+i&&f>=t&&f<=t+s)return null;const _=p-c,x=f-h,b=Math.max(6,Math.min(i,s)*.3),v=o??IS(i,s);if(Math.abs(x)>=Math.abs(_)){const E=x>=0?t+s:t,{center:N,half:I}=Jv(p,e,i,v,b);return{tip:{x:p,y:f},base1:{x:N-I,y:E},base2:{x:N+I,y:E}}}const S=_>=0?e+i:e,{center:j,half:R}=Jv(f,t,s,v,b);return{tip:{x:p,y:f},base1:{x:S,y:j-R},base2:{x:S,y:j+R}}}function B3(e){return e.type!=="speech"||!e.tailAnchor?!1:HS(0,0,1,1,e.tailAnchor)!==null}function L3(e,t,i,s,a,o){const c=o??IS(i,s),h=e+i,p=t+s,f=!!a&&a.base1.y===t&&a.base2.y===t,_=!!a&&a.base1.x===h&&a.base2.x===h,x=!!a&&a.base1.y===p&&a.base2.y===p,b=!!a&&a.base1.x===e&&a.base2.x===e,v=[{k:"M",x:e+c,y:t}];return f&&a&&v.push({k:"L",x:a.base1.x,y:t},{k:"L",x:a.tip.x,y:a.tip.y},{k:"L",x:a.base2.x,y:t}),v.push({k:"L",x:h-c,y:t},{k:"A",cornerX:h,cornerY:t,x:h,y:t+c,r:c}),_&&a&&v.push({k:"L",x:h,y:a.base1.y},{k:"L",x:a.tip.x,y:a.tip.y},{k:"L",x:h,y:a.base2.y}),v.push({k:"L",x:h,y:p-c},{k:"A",cornerX:h,cornerY:p,x:h-c,y:p,r:c}),x&&a&&v.push({k:"L",x:a.base2.x,y:p},{k:"L",x:a.tip.x,y:a.tip.y},{k:"L",x:a.base1.x,y:p}),v.push({k:"L",x:e+c,y:p},{k:"A",cornerX:e,cornerY:p,x:e,y:p-c,r:c}),b&&a&&v.push({k:"L",x:e,y:a.base2.y},{k:"L",x:a.tip.x,y:a.tip.y},{k:"L",x:e,y:a.base1.y}),v.push({k:"L",x:e,y:t+c},{k:"A",cornerX:e,cornerY:t,x:e+c,y:t,r:c}),v}function O3(e,t,i,s,a,o){const c=L3(e,t,i,s,a,o).map(h=>h.k==="A"?`A ${h.r} ${h.r} 0 0 1 ${h.x} ${h.y}`:`${h.k} ${h.x} ${h.y}`);return c.push("Z"),c.join(" ")}function z3(e){return e.x<-1e-6||e.y<-1e-6||e.x+e.width>1+1e-6||e.y+e.height>1+1e-6}let ey=0;function Lp(e,t=.1,i=.1){return ey++,{id:`overlay-${Date.now()}-${ey}`,type:e,x:t,y:i,width:e==="sfx"?.15:.25,height:e==="sfx"?.08:.12,text:"",...e==="speech"?{speaker:"",tailAnchor:{x:.5,y:1.2}}:{}}}function US(e,t,i){return{width:Math.min(e==="sfx"?.3:.5,Math.max(.15,1-t)),height:Math.min(e==="sfx"?.1:.2,Math.max(.06,1-i))}}const du=.05;function Ui(e){return typeof e=="number"&&Number.isFinite(e)}function P3(e,t,i){const s=e.toLowerCase(),a=/\bleft\b/.test(s),o=/\bright\b/.test(s),c=/\b(?:top|upper)\b/.test(s),h=/\b(?:bottom|lower)\b/.test(s),p=/\b(?:center|centre|middle)\b/.test(s);if(!a&&!o&&!c&&!h&&!p)return null;const f=a?du:Ar(o?1-t-du:(1-t)/2,0,1),_=c?du:Ar(h?1-i-du:(1-i)/2,0,1);return{x:f,y:_}}let I3=0;function H3(e){if(!e||typeof e!="object")return null;const t=e,i=PS.includes(t.type)?t.type:"speech",s=typeof t.text=="string"?t.text:"";let a=Ui(t.width)&&t.width>0?t.width:i==="sfx"?.15:.4,o=Ui(t.height)&&t.height>0?t.height:i==="sfx"?.08:.16,c,h;if(Ui(t.x)&&Ui(t.y))c=t.x,h=t.y;else{const b=typeof t.position=="string"?P3(t.position,a,o):null;if(!b)return null;c=b.x,h=b.y}c=Ar(c,0,1),h=Ar(h,0,1),a=Ar(a,.02,1),o=Ar(o,.02,1);const f={id:typeof t.id=="string"&&t.id?t.id:`overlay-norm-${++I3}`,type:i,x:c,y:h,width:a,height:o,text:s};if(i==="speech"){f.speaker=typeof t.speaker=="string"?t.speaker:"";const b=t.tailAnchor;f.tailAnchor=b&&Ui(b.x)&&Ui(b.y)?{x:b.x,y:b.y}:{x:.5,y:1.2}}else typeof t.speaker=="string"&&t.speaker&&(f.speaker=t.speaker);const _=xm(t.textStyle),x=Yu(t.bubbleStyle);return _&&(f.textStyle=_),x&&(f.bubbleStyle=x),f}function U3(e){if(!e||typeof e!="object")return!1;const t=e;return typeof t.id=="string"&&!!t.id&&PS.includes(t.type)&&Ui(t.x)&&Ui(t.y)&&Ui(t.width)&&Ui(t.height)&&typeof t.text=="string"}function $3(e){const t=Array.isArray(e)?e:[],i=[],s=[];let a=!Array.isArray(e);return t.forEach((o,c)=>{const h=H3(o);if(!h){s.push({index:c,reason:"overlay has no numeric x/y/width/height and no recognizable position"}),a=!0;return}i.push(h),U3(o)||(a=!0)}),{overlays:i,changed:a,invalid:s}}function e4(e){for(let t=0;t0&&i.height>0))return{valid:!1,error:`Overlay ${t+1}${i!=null&&i.type?` (${i.type})`:""} has invalid geometry — repair or re-place it in the lettering editor before export`};const a=xm(i==null?void 0:i.textStyle);if(i!=null&&i.textStyle&&!a)return{valid:!1,error:`Overlay ${t+1}${i!=null&&i.type?` (${i.type})`:""} has invalid typography controls — reset them in the lettering editor before export`};const o=Yu(i==null?void 0:i.bubbleStyle);if(i!=null&&i.bubbleStyle&&!o)return{valid:!1,error:`Overlay ${t+1}${i!=null&&i.type?` (${i.type})`:""} has invalid bubble controls — reset them in the lettering editor before export`}}return{valid:!0}}const ty=new Set(["speech","narration"]),F3=.12;function iy(e){return Ui(e==null?void 0:e.x)&&Ui(e==null?void 0:e.y)&&Ui(e==null?void 0:e.width)&&Ui(e==null?void 0:e.height)&&e.width>0&&e.height>0}function q3(e,t=F3){const i=[];for(let s=0;s0?f/_:0;x>=t&&i.push({indexA:s,indexB:o,idA:a.id,idB:c.id,ratio:x})}}return i}function In(e){return e.kind==="text"}function W3(e){return!!e.finalImagePath||!!e.exportedAt?{key:"review",label:"Review final panel",opensEditor:!0}:e.cleanImagePath||In(e)?{key:"letter",label:"Letter this cut",opensEditor:!0}:{key:"add-art",label:"Add clean art for this cut",opensEditor:!1}}function $S(e,t=D3){return!e.finalImagePath||!(e.overlays??[]).some(B3)?!1:(e.finalRendererVersion??0)0)||!(s>0)?null:{width:ny,height:Math.round(ny*s/i)}}function fu({cut:e}){return e.dialogue.length>0||e.narration||e.sfx?d.jsxs("div",{className:"space-y-1.5","data-testid":`cut-${e.id}-overlay`,children:[e.dialogue.map((i,s)=>d.jsxs("div",{className:"flex gap-2 text-xs",children:[d.jsxs("span",{className:"font-medium text-foreground flex-shrink-0",children:[i.speaker,":"]}),d.jsx("span",{className:"text-foreground",children:i.text})]},s)),e.narration&&d.jsx("div",{className:"border-l-2 border-border pl-3",children:d.jsx("p",{className:"text-xs text-muted italic",children:e.narration})}),e.sfx&&d.jsxs("p",{className:"text-xs font-mono text-muted",children:["SFX: ",e.sfx]})]}):null}function Y3({cut:e,storyName:t,authFetch:i,onEditCut:s}){const a=!!e.finalImagePath,o=!!e.cleanImagePath,c=a||o,h=e.dialogue.length>0||!!e.narration||!!e.sfx,p=e.kind==="text";return d.jsxs("div",{className:"space-y-2",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsxs("span",{className:"text-[10px] font-mono text-muted bg-surface border border-border rounded px-1.5 py-0.5",children:["#",e.id]}),d.jsx("span",{className:"text-[10px] font-mono text-muted",children:e.shotType}),e.characters.length>0&&d.jsx("span",{className:"text-[10px] text-muted truncate",children:e.characters.join(", ")})]}),a&&d.jsx(Bp,{storyName:t,assetPath:e.finalImagePath,authFetch:i,alt:e.description||`Cut ${e.id}`}),!a&&o&&d.jsxs("div",{className:"border border-border rounded overflow-hidden",children:[d.jsx(Bp,{storyName:t,assetPath:e.cleanImagePath,authFetch:i,alt:e.description||`Cut ${e.id}`}),d.jsx("div",{className:"px-3 py-2 bg-surface/80 border-t border-border",children:d.jsx(fu,{cut:e})})]}),!c&&p&&d.jsxs("div",{className:"w-full border border-border rounded p-4 space-y-2",style:{background:e.background||void 0},"data-testid":`cut-${e.id}-textpanel`,children:[d.jsx("span",{className:"text-[10px] font-mono text-muted",children:"Text panel"}),h?d.jsx(fu,{cut:e}):d.jsx("p",{className:"text-xs text-muted italic",children:"Empty text panel — open the editor to add text."})]}),!c&&!p&&d.jsxs("div",{className:"w-full bg-surface border border-dashed border-border rounded p-4 space-y-2","data-testid":`cut-${e.id}-pending`,children:[d.jsxs("div",{className:"aspect-video flex flex-col items-center justify-center gap-1 text-center",children:[d.jsx("span",{className:"text-xs text-muted font-medium",children:"Image pending"}),d.jsx("span",{className:"text-[10px] text-muted",children:"Planned image cut — generate & upload the art"})]}),h&&d.jsxs("div",{className:"border-t border-dashed border-border pt-2 space-y-1",children:[d.jsx("span",{className:"text-[10px] font-mono text-muted",children:"Planned text (will be lettered onto the image)"}),d.jsx(fu,{cut:e})]})]}),e.description&&d.jsx("p",{className:"text-xs text-muted italic",children:e.description}),a&&d.jsx(fu,{cut:e}),s&&(()=>{const f=W3(e);return d.jsx("button",{type:"button","data-testid":`cut-${e.id}-cta`,"data-cut-action":f.key,onClick:()=>s(e.id,f.opensEditor),className:"w-full px-3 py-1.5 text-xs font-medium rounded bg-accent text-white hover:bg-accent-dim",children:f.label})})()]})}function K3({storyName:e,fileName:t,authFetch:i,onEditCut:s}){const[a,o]=w.useState(null),[c,h]=w.useState(!0),[p,f]=w.useState(null),_=t.replace(/\.md$/,""),x=w.useCallback(async()=>{h(!0),f(null);try{const b=await i(`/api/stories/${e}/cuts/${_}`);if(b.status===404){o(null),h(!1);return}if(!b.ok){const S=await b.json();f(S.error||"Failed to load cuts"),h(!1);return}const v=await b.json();o(v)}catch{f("Failed to load cuts")}finally{h(!1)}},[i,e,_]);return w.useEffect(()=>{x();const b=setInterval(x,5e3);return()=>clearInterval(b)},[x]),c&&!a?d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm",children:"Loading cuts..."}):p?d.jsxs("div",{className:"h-full flex flex-col items-center justify-center gap-2 px-4 text-center","data-testid":"cuts-error",children:[d.jsx("p",{className:"text-sm text-error font-medium",children:"Invalid cuts file"}),d.jsx("p",{className:"text-xs text-error",children:p}),d.jsxs("p",{className:"text-xs text-muted max-w-sm",children:[_,".cuts.json must follow the OWS v1 schema. Ask Claude to regenerate it using the v1 cuts schema shown in the cartoon writing instructions."]}),d.jsx("button",{onClick:x,className:"text-xs text-accent hover:text-accent-dim",children:"Retry"})]}):!a||a.cuts.length===0?d.jsxs("div",{className:"h-full flex flex-col items-center justify-center gap-2 px-4 text-center",children:[d.jsx("p",{className:"text-sm text-muted",children:"No cuts yet"}),d.jsx("p",{className:"text-xs text-muted",children:"Ask Claude to create a cut plan for this episode."})]}):d.jsx("div",{className:"h-full overflow-y-auto",children:d.jsx("div",{className:"max-w-lg mx-auto px-4 py-6 space-y-6",children:a.cuts.map(b=>d.jsx(Y3,{cut:b,storyName:e,authFetch:i,onEditCut:s},b.id))})})}const ry=/!\[[^\]]*\]\([^)]*\)/g,V3=//g,FS=200;function X3(e){const t=(e.match(ry)||[]).length,i=e.length,s=e.replace(V3," ").replace(ry," ").replace(/\s+/g," ").trim();return{imageCount:t,charCount:i,nonImageProse:s,nonImageProsePreview:s.slice(0,FS)}}function Z3(e){return`${e}: re-export required before publish — this final image uses an older speech-bubble tail style that can show a visible seam`}const Q3=[/placeholder only/i,/\bOWS (?:should )?generates? the publish markdown/i,/generate(?:s|d)? the publish markdown from/i,/after clean images are approved/i,/lettered final images are created/i,/do not hand-?write/i,/\b(?:TODO|FIXME)\b/];function J3(e){for(const t of Q3){const i=e.match(t);if(i)return i[0]}return null}function _m(e,t){const i=``,s=``,a=e.indexOf(i),o=e.indexOf(s);return a===-1||o===-1||ob[1].trim());x.length===0?i.push(`${p}: block has no image reference`):x.length>1?i.push(`${p}: block must contain exactly one image reference`):h.uploadedUrl&&x[0]!==h.uploadedUrl&&i.push(`${p}: image URL does not match the recorded uploaded URL`)}/awaiting upload|image pending|final image pending|pending upload/i.test(e)&&i.push("Markdown contains awaiting-upload placeholders");const s=J3(e);s&&i.push(`This episode still has placeholder/instructional text ("${s.slice(0,60)}") — remove it or re-run “Prepare episode for publish” so the published episode is images only`);const a=new Set(t.map(c=>c.uploadedUrl).filter(c=>!!c&&/^https?:\/\//i.test(c))),o=[...e.matchAll(/!\[[^\]]*\]\(([^)]*)\)/g)];for(const c of o){const h=c[1].trim();/^https?:\/\//i.test(h)?a.has(h)||i.push(`Image reference is not a recorded uploaded cut URL: ${h.slice(0,60)}`):i.push(`Invalid image reference (not an http(s) URL): ${h.slice(0,60)}`)}return e.length>1e4&&i.push(`Markdown is ${e.length} chars (limit 10,000)`),{ready:i.length===0,issues:i}}function WS(e,t){const i=t.length;if(i===0)return{stage:"not-started",issues:[],awaitingCount:0,totalCuts:0};if(eD(e,t))return{stage:"planning",issues:[],awaitingCount:0,totalCuts:i};const{ready:s,issues:a}=qS(e,t);if(s)return{stage:"ready",issues:[],awaitingCount:0,totalCuts:i};const o=new Set;for(let p=0;p!c.has(p));return h.length>0?{stage:"error",issues:h,awaitingCount:o.size,totalCuts:i}:{stage:"awaiting-upload",issues:[],awaitingCount:o.size,totalCuts:i}}const Df=[{key:"assemble",title:"Prepare the episode for publish",test:/markdown block|missing or incomplete/i},{key:"export",title:"Export final images",test:/re-export|older speech-bubble|visible seam/i},{key:"upload",title:"Upload final images",test:/not uploaded|no recorded uploaded url/i},{key:"images",title:"Fix image references",test:/image reference|not an http|does not match|exactly one image/i},{key:"cleanup",title:"Remove leftover text",test:/placeholder|instructional|awaiting-upload|awaiting upload/i},{key:"size",title:"Shorten the episode",test:/\blimit\b|\bchars\b/i}];function tD(e){const t=new Map,i=[],s=[];for(const o of e){const c=o.match(/^Cut (\d+): (.+)$/);if(c){const h=c[2];t.has(h)||(t.set(h,[]),i.push(h)),t.get(h).push(Number(c[1]))}else s.push(o)}return[...i.map(o=>{const c=t.get(o).slice().sort((p,f)=>p-f);return`${c.length===1?`Cut ${c[0]}`:`Cuts ${c.join(", ")}`}: ${o}`}),...s]}function GS(e){const t=c=>{var h;return((h=Df.find(p=>p.test.test(c)))==null?void 0:h.key)??"other"},i=new Map;for(const c of e){const h=t(c);i.has(h)||i.set(h,[]),i.get(h).push(c)}const s=[...Df.map(c=>c.key),"other"],a=c=>{var h;return((h=Df.find(p=>p.key===c))==null?void 0:h.title)??"Other issues"},o=[];for(const c of s){const h=i.get(c);!h||h.length===0||o.push({key:c,title:a(c),lines:tD(h)})}return o}const iD=220,Mf=/^(genre|logline|synopsis|premise|setting|tone|theme|themes|summary|hook|characters?|cast|arc|status|word\s*count|length|title)\b\s*[:\-–]/i;function bm(e){const t=[],i=[],s=e??"",a=s.match(/^#[ \t]+(.+)$/m),o=!!(a&&a[1].trim());o||t.push("Add a “# Title” heading — the Story opening needs a real title readers see first.");const c=s.replace(/^#\s+.+$/m,"").trim();if(c.lengthx.trim()).filter(Boolean),p=h.filter(x=>/^([-*+]|\d+[.)])\s/.test(x)||Mf.test(x)).length,f=c.split(/\n\s*\n/).map(x=>x.trim()).filter(Boolean),_=f.some(x=>x.length>=120&&!/^([-*+]|\d+[.)])\s/.test(x)&&!Mf.test(x));h.length>0&&p/h.length>=.5||!_?t.push("This reads like a synopsis or outline. Write the Genesis as a reader-facing opening scene that sets up the first beat and stakes, then bridges into Episode 01 — not a logline, genre pitch, or character list."):f.filter(b=>b.length>=40&&!/^([-*+]|\d+[.)])\s/.test(b)&&!Mf.test(b)).length<2&&t.push("Give the opening room to build: open across a few short paragraphs — the premise, what the lead wants, and the hook — that lead into Episode 01, instead of a single dense block that drops readers into a cold scene.")}return{hasTitle:o,blockers:t,warnings:i}}function nD(e){return/\.(webp|jpe?g)$/i.test(e)}function Op(e){var c,h;let t=0,i=0,s=0,a=0,o=0;for(const p of e)In(p)?(((h=p.overlays)==null?void 0:h.length)??0)>0&&s++:(t++,p.cleanImagePath&&nD(p.cleanImagePath)&&(i++,(((c=p.overlays)==null?void 0:c.length)??0)>0&&s++)),p.finalImagePath&&p.exportedAt&&a++,p.uploadedUrl&&o++;return{total:e.length,needClean:t,withClean:i,withText:s,exported:a,uploaded:o}}const rD={plan:"Plan cuts",clean:"Create clean images",letter:"Add speech bubbles & captions",export:"Export final images",upload:"Upload final images",publish:"Publish to PlotLink"};function vo(e,t){return`${e} / ${t} cut${t===1?"":"s"}`}function sD(e){const{cuts:t,published:i=!1}=e,s=Op(t);if(s.total===0)return{steps:[],nextStep:null};const a=s.total>0,o=a&&s.withClean===s.needClean,c=o&&s.withText===s.total,h=c&&s.exported===s.total,p=h&&s.uploaded===s.total,_={plan:a,clean:o,letter:c,export:h,upload:p,publish:p&&i},x=["plan","clean","letter","export","upload","publish"],b=x.findIndex(N=>!_[N]),v=N=>s.needClean>0?vo(N,s.needClean):"no image cuts",S={plan:vo(s.total,s.total),clean:v(s.withClean),letter:vo(s.withText,s.total),export:vo(s.exported,s.total),upload:vo(s.uploaded,s.total),publish:null},j=x.map((N,I)=>({key:N,label:rD[N],status:b===-1||IFS,a=oD({stage:t,imageCount:i.imageCount,hasNonImageProse:i.nonImageProse.length>0});return d.jsxs("div",{className:"h-full overflow-y-auto","data-testid":"cartoon-publish-preview",children:[d.jsxs("div",{className:"px-4 py-2 border-b border-border text-[10px] text-muted flex flex-wrap items-center gap-x-3 gap-y-1","data-testid":"cartoon-publish-summary",children:[d.jsxs("span",{children:[i.imageCount," image",i.imageCount===1?"":"s"]}),d.jsxs("span",{children:[i.charCount.toLocaleString()," / 10,000 chars"]}),d.jsx("span",{className:`rounded-full px-2 py-0.5 font-medium ${a.possible?"bg-green-100 text-green-800":"bg-background text-muted"}`,"data-testid":"publish-possible",children:a.possible?"Publish possible":"Publish not possible yet"}),d.jsx("span",{className:`rounded-full px-2 py-0.5 font-medium ${a.recommended?"bg-green-100 text-green-800":a.tone==="warning"?"bg-amber-100 text-amber-800":"bg-background text-muted"}`,"data-testid":"publish-recommended",children:a.recommended?"Recommended":"Not recommended yet"})]}),d.jsxs("div",{className:`px-4 py-2 border-b text-[11px] ${uD[a.tone]}`,"data-testid":"cartoon-publish-verdict",children:[d.jsx("p",{className:"font-medium",children:a.headline}),a.detail&&d.jsx("p",{className:"mt-0.5 opacity-90",children:a.detail}),a.action&&d.jsxs("p",{className:"mt-0.5 opacity-90",children:["→ ",a.action]})]}),i.nonImageProse&&d.jsxs("div",{className:"px-4 py-2 border-b border-amber-300 bg-amber-50 text-[11px] text-amber-800","data-testid":"cartoon-nonimage-prose",children:[d.jsx("p",{className:"font-medium",children:"⚠ Non-image text in the published markdown:"}),d.jsxs("p",{className:"font-mono mt-1 whitespace-pre-wrap break-words",children:[i.nonImageProsePreview,s?"…":""]}),d.jsx("p",{className:"mt-1",children:"This text publishes verbatim around the comic images. Remove it (or re-run “Prepare episode for publish”) if it is planning or placeholder prose."})]}),d.jsx("div",{className:"max-w-lg mx-auto px-4 py-6",children:e.trim()?d.jsx("div",{className:"prose max-w-none",children:d.jsx(rS,{remarkPlugins:[aS,AS],rehypePlugins:[[BS,cD]],children:e})}):d.jsx("p",{className:"text-muted italic text-sm","data-testid":"cartoon-publish-empty",children:"No publish markdown yet — build it from the cut plan (Edit → Upload & Prepare for Publish)."})})]})}const dD="modulepreload",fD=function(e){return"/"+e},sy={},ay=function(t,i,s){let a=Promise.resolve();if(i&&i.length>0){let c=function(f){return Promise.all(f.map(_=>Promise.resolve(_).then(x=>({status:"fulfilled",value:x}),x=>({status:"rejected",reason:x}))))};document.getElementsByTagName("link");const h=document.querySelector("meta[property=csp-nonce]"),p=(h==null?void 0:h.nonce)||(h==null?void 0:h.getAttribute("nonce"));a=c(i.map(f=>{if(f=fD(f),f in sy)return;sy[f]=!0;const _=f.endsWith(".css"),x=_?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${f}"]${x}`))return;const b=document.createElement("link");if(b.rel=_?"stylesheet":dD,_||(b.as="script"),b.crossOrigin="",b.href=f,p&&b.setAttribute("nonce",p),document.head.appendChild(b),_)return new Promise((v,S)=>{b.addEventListener("load",v),b.addEventListener("error",()=>S(new Error(`Unable to preload CSS for ${f}`)))})}))}function o(c){const h=new Event("vite:preloadError",{cancelable:!0});if(h.payload=c,window.dispatchEvent(h),!h.defaultPrevented)throw c}return a.then(c=>{for(const h of c||[])h.status==="rejected"&&o(h.reason);return t().catch(o)})},vm=[{family:"Noto Sans",googleFontsId:"Noto+Sans",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans/about",category:"body",weights:[400,500,700],languages:["English","Spanish","French","Portuguese","Russian","Others"]},{family:"Noto Sans KR",googleFontsId:"Noto+Sans+KR",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+KR/about",category:"body",weights:[400,500,700],languages:["Korean"]},{family:"Noto Sans JP",googleFontsId:"Noto+Sans+JP",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+JP/about",category:"body",weights:[400,500,700],languages:["Japanese"]},{family:"Noto Sans SC",googleFontsId:"Noto+Sans+SC",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+SC/about",category:"body",weights:[400,500,700],languages:["Chinese"]},{family:"Noto Sans Devanagari",googleFontsId:"Noto+Sans+Devanagari",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+Devanagari/about",category:"body",weights:[400,500,700],languages:["Hindi"]},{family:"Noto Naskh Arabic",googleFontsId:"Noto+Naskh+Arabic",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Naskh+Arabic/about",category:"body",weights:[400,500,700],languages:["Arabic"]},{family:"Bangers",googleFontsId:"Bangers",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/specimen/Bangers/about",category:"display",weights:[400],languages:[]}],pD="system-ui, sans-serif",mD=vm.find(e=>e.family==="Noto Sans"),gD=vm.find(e=>e.category==="display");function xD(e){return vm.find(i=>i.category==="body"&&i.languages.includes(e))||mD}function _D(){return gD}function bD(e){const t=e.weights.join(";");return`https://fonts.googleapis.com/css2?family=${e.googleFontsId}:wght@${t}&display=swap`}function ly(e){return`"${e.family}", ${pD}`}function vD(e,t={}){var a,o,c,h;const i=!t.staleExport&&(!!e.finalImagePath||!!e.exportedAt),s=!t.staleExport&&(!!e.uploadedUrl||!!e.uploadedCid);return{hasCleanImage:!!e.cleanImagePath,hasScriptText:(((a=e.dialogue)==null?void 0:a.length)??0)>0||!!((o=e.narration)!=null&&o.trim())||!!((c=e.sfx)!=null&&c.trim()),bubblesPlaced:((h=e.overlays)==null?void 0:h.length)??0,exported:i,uploaded:s}}function ul(e){return JSON.stringify((e??[]).map(t=>[t.type,t.x,t.y,t.width,t.height,t.text,t.speaker??"",t.tailAnchor??null,t.textStyle??null,t.bubbleStyle??null]))}function yD(e){return!e.exported&&!e.uploaded?!1:e.baselineSig!==ul(e.current)}function ym(e){var i,s;const t=[];return(e.dialogue??[]).forEach((a,o)=>{var c;(c=a==null?void 0:a.text)!=null&&c.trim()&&t.push({type:"speech",speaker:a.speaker,text:a.text.trim(),key:`speech-${o}`})}),(i=e.narration)!=null&&i.trim()&&t.push({type:"narration",text:e.narration.trim(),key:"narration"}),(s=e.sfx)!=null&&s.trim()&&t.push({type:"sfx",text:e.sfx.trim(),key:"sfx"}),t}function SD(e,t,i){if(e==="narration")return{x:.08,y:.05+Math.min(t,2)*.18};if(e==="sfx"){const c=t%2,h=Math.floor(t/2);return{x:c===0?.1:.62,y:.68+h*.12}}const s=Math.floor(t/2),a=t%2===0,o=.08+s*Math.max(.15,Math.min(.22,i>4?.16:.2));return{x:a?.05:.45,y:o}}function oy(e){const t=ym(e);return t.map((i,s)=>{const{x:a,y:o}=SD(i.type,s,t.length),c=Lp(i.type,a,o),h=US(i.type,a,o);return{...c,...h,text:i.text,...i.type==="speech"?{speaker:i.speaker??""}:{}}})}function wn(e,t){return e*t}function cy(e,t){return t===0?0:e/t}function uy(e){const t=`gfont-${e.googleFontsId}`;if(document.getElementById(t))return;const i=document.createElement("link");i.id=t,i.rel="stylesheet",i.href=bD(e),document.head.appendChild(i)}const ku={speech:"Speech",narration:"Narration",sfx:"SFX"},wD={speech:"border-foreground/40",narration:"border-muted/40",sfx:"border-accent/40"};function Bf(e){const t=(e.speaker||e.text||"").trim().replace(/\s+/g," ");return t?`“${t.length>18?`${t.slice(0,18)}…`:t}”`:ku[e.type]}const hy=.05,CD=[{key:"down",label:"Down",anchor:{x:.5,y:1.2}},{key:"up",label:"Up",anchor:{x:.5,y:-.2}},{key:"left",label:"Left",anchor:{x:-.2,y:.5}},{key:"right",label:"Right",anchor:{x:1.2,y:.5}}];function pu(e,t,i){return Math.min(i,Math.max(t,e))}function kD({storyName:e,cut:t,plotFile:i,onSave:s,onClose:a,onExported:o,language:c="English",authFetch:h,targetLabel:p,returnOnSave:f=!1,workspaceVisible:_=!1,onToggleWorkspaceVisible:x}){var Wt,ui,Bt,vt,At,Ze,hi;const b=xD(c),v=_D(),S=ly(b),j=ly(v);w.useEffect(()=>{uy(b),uy(v)},[b,v]),w.useEffect(()=>{let P=!1;return K(!1),(async()=>{try{const{ensureFontsReady:we}=await ay(async()=>{const{ensureFontsReady:ze}=await import("./export-cut-BqZI0-Rv.js");return{ensureFontsReady:ze}},[]);await we([b.family,v.family])}catch{}P||K(!0)})(),()=>{P=!0}},[b.family,v.family]);const R=zS(e,t.cleanImagePath,h),E=w.useMemo(()=>$3(t.overlays),[t.overlays]),N=E.invalid.length,[I,te]=w.useState(!1),F=N===0&&E.changed&&E.overlays.length>0,[D,ie]=w.useState(()=>E.overlays),[fe,Se]=w.useState(()=>ul(E.overlays)),H=w.useRef(null),ce=w.useCallback(P=>(we,ze,Re=400)=>{var $e;!H.current&&typeof document<"u"&&(H.current=document.createElement("canvas"));const Ge=($e=H.current)==null?void 0:$e.getContext("2d");return Ge?(Ge.font=`${Re} ${ze}px ${P}`,Ge.measureText(we).width):we.length*ze*.5},[]),[W,K]=w.useState(!1),[X,U]=w.useState(null),[A,O]=w.useState(!1),[$,xe]=w.useState(!1),[T,M]=w.useState(null),[G,C]=w.useState(null),[V,ne]=w.useState({x:0,y:0,width:0,height:0}),ae=w.useRef(null),Y=w.useRef(null),he=w.useRef(null),_e=w.useCallback(()=>{const P=ae.current;if(!P)return;const we=P.clientWidth,ze=P.clientHeight;let Re,Ge;if(t.kind==="text"){const lt=G3(t.aspectRatio)??{width:800,height:600};Re=lt.width,Ge=lt.height}else{const lt=Y.current;if(!lt||!lt.naturalWidth)return;Re=lt.naturalWidth,Ge=lt.naturalHeight}if(!we||!ze)return;const $e=Math.min(we/Re,ze/Ge),ht=Re*$e,dt=Ge*$e;ne({x:(we-ht)/2,y:(ze-dt)/2,width:ht,height:dt})},[t.kind,t.aspectRatio]);w.useEffect(()=>{const P=ae.current;if(!P)return;const we=new ResizeObserver(()=>_e());return we.observe(P),()=>we.disconnect()},[_e]);const Be=w.useCallback(P=>{const we=US(P.type,P.x,P.y),ze=we.width,Re=Math.max(.08,1-P.y);if(!P.text||!W||V.width<=0)return we;const Ge=P.type==="sfx"?j:S,$e=wn(ze,V.width);let ht=P.type==="sfx"?.08:.12;for(let dt=0;dt<24;dt++){const lt=Math.min(ht,Re),Vt=wn(lt,V.height);if(!uu(ce(Ge),P.text,$e,Vt,hu({...P},V.height||300,$e,Vt)).overflow||lt>=Re)return{width:ze,height:lt};ht+=.03}return{width:ze,height:Math.min(ht,Re)}},[W,V,ce,S,j]),Le=w.useCallback(P=>{const we=Lp(P,.1+Math.random()*.3,.1+Math.random()*.3),ze={...we,...Be(we)};ie(Re=>[...Re,ze]),U(ze.id)},[Be]),je=w.useCallback(P=>{const ze={...Lp(P.type,.1+Math.random()*.3,.1+Math.random()*.3),text:P.text,...P.type==="speech"&&P.speaker?{speaker:P.speaker}:{}},Re={...ze,...Be(ze)};ie(Ge=>[...Ge,Re]),U(Re.id)},[Be]),be=w.useCallback((P,we)=>{ie(ze=>ze.map(Re=>Re.id===P?{...Re,...we}:Re))},[]),tt=w.useCallback(P=>{var ht;const we=V.height||300,ze=V.width>0?wn(P.width,V.width):200,Re=V.height>0?wn(P.height,V.height):100,Ge=P.type==="sfx"?j:S,$e=uu(ce(Ge),P.text,ze,Re,hu({...P,textStyle:void 0},we,ze,Re));be(P.id,{textStyle:{mode:"manual",fontScale:$e.fontSize/Math.max(1,we),fontWeight:((ht=P.textStyle)==null?void 0:ht.fontWeight)??400,lineHeightFactor:$e.fontSize>0?$e.lineHeight/$e.fontSize:1.2,speakerScale:$e.fontSize>0&&$e.speakerFontSize>0?$e.speakerFontSize/$e.fontSize:.8}})},[V,j,S,ce,be]),St=w.useCallback(P=>{ie(we=>we.filter(ze=>ze.id!==P)),U(null),O(!1)},[]),ot=w.useCallback(()=>{U(null),O(!1)},[]),We=w.useCallback((P,we)=>{P.stopPropagation(),U(we),O(!1)},[]),Mt=w.useCallback((P,we,ze)=>{P.stopPropagation(),P.preventDefault();const Re=D.find(Ge=>Ge.id===we);Re&&(U(we),he.current={id:we,mode:ze,startX:P.clientX,startY:P.clientY,origX:Re.x,origY:Re.y,origW:Re.width,origH:Re.height})},[D]);w.useEffect(()=>{const P=ze=>{const Re=he.current;if(!Re||V.width===0)return;const Ge=cy(ze.clientX-Re.startX,V.width),$e=cy(ze.clientY-Re.startY,V.height);if(Re.mode==="move"){const ht=pu(Re.origX+Ge,0,1-Re.origW),dt=pu(Re.origY+$e,0,1-Re.origH);be(Re.id,{x:ht,y:dt})}else{const ht=pu(Re.origW+Ge,hy,1-Re.origX),dt=pu(Re.origH+$e,hy,1-Re.origY);be(Re.id,{width:ht,height:dt})}},we=()=>{he.current=null};return window.addEventListener("mousemove",P),window.addEventListener("mouseup",we),()=>{window.removeEventListener("mousemove",P),window.removeEventListener("mouseup",we)}},[V,be]);const He=w.useCallback(async()=>{var P;C(null);try{const we=ul(D),ze=((P=t.aiDraft)==null?void 0:P.status)==="generated"&&we!==(t.aiDraft.baseSig??"")?{...t.aiDraft,status:"edited",updatedAt:new Date().toISOString()}:t.aiDraft??void 0;await s(D,ze??null),f&&a()}catch(we){C(we instanceof Error?we.message:"Failed to save overlays")}},[D,s,a,f,t.aiDraft]),xt=w.useCallback(async()=>{if(N>0&&!I){const P=N;M(`${P} overlay${P===1?"":"s"} from the cut plan ${P===1?"has":"have"} no usable position and cannot be exported — re-place ${P===1?"it":"them"} or discard ${P===1?"it":"them"} first.`);return}xe(!0),M(null);try{await s(D);const{exportCut:P,ensureFontsReady:we}=await ay(async()=>{const{exportCut:ft,ensureFontsReady:Fi}=await import("./export-cut-BqZI0-Rv.js");return{exportCut:ft,ensureFontsReady:Fi}},[]),ze=D.some(ft=>ft.type==="sfx"),Re=[b.family,...ze?[v.family]:[]],{ready:Ge,missing:$e}=await we(Re);if(!Ge){M(`Fonts not loaded: ${$e.join(", ")}. Check your connection and retry.`),xe(!1);return}if(t.cleanImagePath&&!R.url){M(R.error?"Clean image failed to load — cannot export. Retry once it renders.":"Clean image still loading — wait for it to render, then export."),xe(!1);return}const ht=R.url,dt=await P(ht,D,S,j,{narration:t.narration,dialogue:t.dialogue},t.kind==="text"?{background:t.background,aspectRatio:t.aspectRatio}:void 0),lt=new FormData,Vt=dt.type==="image/webp"?"webp":"jpg";lt.append("file",dt,`cut-${t.id}.${Vt}`);const Ci=await h(`/api/stories/${e}/cuts/${i}/export-final/${t.id}`,{method:"POST",body:lt});if(Ci.ok)Se(ul(D)),o==null||o();else{const ft=await Ci.json();M(ft.error||"Export failed")}}catch(P){M(P instanceof Error?P.message:"Export failed")}finally{xe(!1)}},[t,R,D,e,i,b,v,S,j,h,s,o,N,I]),Ae=D.find(P=>P.id===X),Kt=w.useMemo(()=>q3(D),[D]),mi=w.useRef(t.id);w.useEffect(()=>{mi.current!==t.id&&(mi.current=t.id,Se(ul(E.overlays)))},[t.id,E.overlays]);const wt=yD({exported:!!t.finalImagePath||!!t.exportedAt,uploaded:!!t.uploadedUrl||!!t.uploadedCid,baselineSig:fe,current:D}),Qe=w.useMemo(()=>vD({...t,overlays:D},{staleExport:wt}),[t,D,wt]),Q=w.useMemo(()=>ym(t),[t]),ge=w.useMemo(()=>{const P={};for(const we of D){const ze=z3(we);let Re=!1;if(W&&V.width>0&&we.text){const Ge=we.type==="sfx"?j:S,$e=wn(we.width,V.width),ht=wn(we.height,V.height);Re=uu(ce(Ge),we.text,$e,ht,hu(we,V.height||300,$e,ht)).overflow}(ze||Re)&&(P[we.id]={outOfBounds:ze,overflow:Re})}return P},[D,W,V,ce,S,j]),Te=Object.keys(ge).length,Ue=t.kind==="text",it=!t.cleanImagePath;return!Ue&&it&&D.length===0&&!t.narration&&!((Wt=t.dialogue)!=null&&Wt.length)?d.jsx("div",{className:"h-full flex items-center justify-center text-sm text-muted",children:"No clean image — upload one first, or add overlays for a narration cut."}):d.jsxs("div",{className:"h-full flex flex-col","data-testid":"focused-lettering-editor",children:[d.jsxs("div",{className:"px-4 py-3 border-b border-border bg-surface/40 flex items-center justify-between gap-3",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("span",{className:"text-[10px] font-bold uppercase tracking-[0.16em] text-accent",children:"Focused lettering editor"}),d.jsx("span",{className:"text-xs font-mono text-muted",children:p??`Cut #${t.id}`})]}),d.jsx("p",{className:"mt-0.5 text-[11px] text-muted",children:"Place bubbles, captions, SFX, or between-scene card text, then save back to the full cut review."}),d.jsxs("span",{className:"text-[10px] text-muted","data-testid":"overlay-count",children:[D.length," overlays"]})]}),d.jsxs("div",{className:"flex items-center gap-2 flex-wrap justify-end",children:[d.jsx("button",{onClick:a,className:"px-3 py-1 text-xs border border-border rounded text-muted hover:text-foreground","data-testid":"return-to-cut-review-btn",children:"Back to cut review"}),x&&d.jsx("button",{onClick:x,className:"px-3 py-1 text-xs border border-border rounded text-muted hover:border-accent hover:text-accent","data-testid":"toggle-work-area-btn",children:_?"Hide work area":"Show work area"}),d.jsxs("div",{className:"flex items-center gap-1 ml-2",children:[d.jsx("button",{onClick:()=>Le("speech"),className:"px-2 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"add-speech",children:"Speech"}),d.jsx("button",{onClick:()=>Le("narration"),className:"px-2 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"add-narration",children:"Narration"}),d.jsx("button",{onClick:()=>Le("sfx"),className:"px-2 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"add-sfx",children:"SFX"})]}),T&&d.jsx("span",{className:"text-[10px] text-error",children:T}),G&&d.jsx("span",{className:"text-[10px] text-error",children:G}),d.jsx("button",{onClick:xt,disabled:$,className:"px-3 py-1 text-xs border border-accent text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"export-btn",children:$?"Exporting...":"Export"}),d.jsx("button",{onClick:()=>{He()},className:"px-3 py-1 text-xs bg-accent text-white rounded hover:bg-accent-dim","data-testid":"save-lettering-btn",children:"Save"}),d.jsx("button",{onClick:a,className:"px-3 py-1 text-xs text-muted hover:text-foreground border border-border rounded","data-testid":"cancel-lettering-btn",children:"Cancel"})]})]}),N>0&&!I?d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-error/10 text-[10px] text-error flex items-center gap-2 flex-wrap","data-testid":"overlay-repair-note",children:[d.jsxs("span",{children:[N," overlay",N===1?"":"s"," ","from the cut plan ",N===1?"has":"have"," no usable position and cannot be exported. Re-place"," ",N===1?"it":"them",", or"]}),d.jsxs("button",{onClick:()=>te(!0),"data-testid":"discard-invalid-overlays",className:"px-1.5 py-0.5 border border-error/40 rounded hover:bg-error/10",children:["discard ",N," unplaceable overlay",N===1?"":"s"]})]}):N>0?d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"overlay-repair-note",children:["Discarded ",N," unplaceable overlay",N===1?"":"s"," — the export will not include"," ",N===1?"it":"them","."]}):F?d.jsx("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"overlay-repair-note",children:"Auto-placed overlays from the cut plan — review their positions before exporting."}):null,Kt.length>0&&d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"overlay-overlap-warning",children:["Cut #",t.id,": ",Kt.length," bubble"," ",Kt.length===1?"pair overlaps":"pairs overlap"," and may be hard to read —"," ",Kt.map(P=>`#${P.indexA+1} ${Bf(D[P.indexA])} ↔ #${P.indexB+1} ${Bf(D[P.indexB])}`).join("; "),". Move them apart, or export as-is if the overlap is intended."]}),d.jsx("div",{className:"px-3 py-1 border-b border-border flex items-center gap-3 flex-wrap text-[10px] text-muted","data-testid":"lettering-checklist",children:[["clean-image","Clean image",Qe.hasCleanImage],["script-text","Script text",Qe.hasScriptText],["bubbles",`Bubbles placed${Qe.bubblesPlaced?` (${Qe.bubblesPlaced})`:""}`,Qe.bubblesPlaced>0],["exported","Final exported",Qe.exported],["uploaded","Uploaded",Qe.uploaded]].map(([P,we,ze])=>d.jsxs("span",{"data-testid":`lettering-check-${P}`,"data-done":ze?"true":"false",className:`flex items-center gap-1 ${ze?"text-green-700":"text-muted/70"}`,children:[d.jsx("span",{"aria-hidden":!0,children:ze?"✓":"○"}),we]},P))}),wt&&d.jsx("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"lettering-stale-export-warning",children:"Bubbles changed since the last export — re-export this cut and upload the new final image before publishing."}),Te>0&&d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"lettering-export-warning",children:[Te," bubble",Te===1?"":"s"," may not export cleanly:"," ",Object.entries(ge).map(([P,we])=>{const ze=D.findIndex(Ge=>Ge.id===P),Re=[we.outOfBounds?"outside image":null,we.overflow?"text overflow":null].filter(Boolean).join(", ");return`#${ze+1} ${Bf(D[ze])} (${Re})`}).join("; "),". Resize or reposition before exporting."]}),d.jsxs("div",{className:"flex-1 min-h-0 flex",children:[d.jsxs("div",{ref:ae,className:"flex-1 min-w-0 relative overflow-hidden bg-[#f8f5ef]",onClick:ot,"data-testid":"editor-surface",children:[t.cleanImagePath&&R.error?d.jsx("div",{className:"w-full h-full flex items-center justify-center text-muted text-xs","data-testid":"clean-image-error",children:"Clean image not available"}):t.cleanImagePath&&!R.url?d.jsx("div",{className:"w-full h-full flex items-center justify-center text-muted text-xs","data-testid":"clean-image-loading",children:"Loading clean image…"}):t.cleanImagePath?d.jsx("img",{ref:Y,src:R.url,alt:`Cut ${t.id} clean`,className:"w-full h-full object-contain",draggable:!1,onLoad:_e}):Ue?V.width>0&&d.jsx("div",{className:"absolute flex items-center justify-center text-muted text-xs",style:{left:V.x,top:V.y,width:V.width,height:V.height,background:t.background||"#ffffff"},"data-testid":"text-panel-canvas",children:"Text panel"}):d.jsx("div",{className:"w-full h-full bg-white flex items-center justify-center text-muted text-xs",ref:P=>{if(P&&V.width===0){const we=P.getBoundingClientRect();we.width>0&&ne({x:0,y:0,width:we.width,height:we.height})}},children:"Narration cut"}),V.width>0&&d.jsx("svg",{className:"absolute inset-0 w-full h-full pointer-events-none","data-testid":"balloon-layer",children:D.map(P=>{if(P.type!=="speech")return null;const we=V.x+wn(P.x,V.width),ze=V.y+wn(P.y,V.height),Re=wn(P.width,V.width),Ge=wn(P.height,V.height),$e=M3(P,Re,Ge),ht=P.tailAnchor?HS(we,ze,Re,Ge,P.tailAnchor,$e):null,dt=Math.max(1.5,V.height*.004),lt=P.id===X;return d.jsx("path",{"data-testid":`balloon-${P.id}`,d:O3(we,ze,Re,Ge,ht,$e),className:`fill-white/95 ${lt?"stroke-accent":"stroke-[#1a1a1a]"}`,strokeWidth:lt?dt+.5:dt,strokeLinejoin:"round"},P.id)})}),V.width>0&&D.map(P=>{const we=V.x+wn(P.x,V.width),ze=V.y+wn(P.y,V.height),Re=wn(P.width,V.width),Ge=wn(P.height,V.height),$e=P.id===X,ht=P.type==="speech",dt=P.type==="narration",lt=!!ge[P.id];return d.jsxs("div",{"data-testid":`overlay-${P.id}`,"data-warning":lt?"true":"false",onClick:Vt=>We(Vt,P.id),onMouseDown:Vt=>Mt(Vt,P.id,"move"),className:`absolute rounded cursor-move select-none ${ht?"":`border-2 ${wD[P.type]}`} ${dt?"bg-[#f4efe6]/85 rounded-md":""} ${$e&&!ht?"ring-2 ring-accent":""} ${lt?"ring-2 ring-amber-500":""}`,style:{left:we,top:ze,width:Re,height:Ge},children:[(()=>{var Fi,En;const Vt=P.type==="sfx"?j:S;if(!P.text)return d.jsx("span",{className:"text-[9px] px-1 text-muted truncate block pointer-events-none",style:{fontFamily:Vt},children:ku[P.type]});const Ci=P.type!=="sfx"&&!!P.speaker;if(!W)return d.jsx("div",{className:"absolute inset-0 flex items-center justify-center px-1 overflow-hidden pointer-events-none text-center break-words",style:{fontFamily:Vt,fontSize:Math.max(9,Math.min(Ge*.05,16)),fontWeight:((Fi=P.textStyle)==null?void 0:Fi.fontWeight)??400},"data-testid":`overlay-text-${P.id}`,"data-fonts-ready":"false",children:Ci?`${P.speaker}: ${P.text}`:P.text});const ft=uu(ce(Vt),P.text,Re,Ge,hu(P,V.height,Re,Ge));return d.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center px-1 overflow-hidden pointer-events-none text-center",style:{fontFamily:Vt},"data-testid":`overlay-text-${P.id}`,"data-fonts-ready":"true",children:[Ci&&d.jsx("span",{className:"font-bold text-[#3a3a3a] block",style:{fontSize:ft.speakerFontSize,lineHeight:1.2},children:P.speaker}),d.jsx("span",{className:"text-[#1a1a1a]",style:{fontSize:ft.fontSize,lineHeight:`${ft.lineHeight}px`,fontWeight:((En=P.textStyle)==null?void 0:En.fontWeight)??400},children:ft.lines.map((ln,Un)=>d.jsx("span",{className:"block",children:ln},Un))})]})})(),$e&&d.jsx("div",{onMouseDown:Vt=>{Vt.stopPropagation(),Mt(Vt,P.id,"resize")},className:"absolute bottom-0 right-0 w-2 h-2 bg-accent cursor-se-resize","data-testid":`resize-${P.id}`})]},P.id)})]}),d.jsxs("div",{className:"w-64 border-l border-border p-3 overflow-y-auto flex-shrink-0",children:[((ui=t.aiDraft)==null?void 0:ui.status)==="generated"&&d.jsxs("div",{className:"mb-3 rounded border border-accent/30 bg-accent/5 p-2 space-y-1","data-testid":"ai-draft-current-target",children:[d.jsx("p",{className:"text-[10px] font-bold uppercase tracking-[0.14em] text-accent",children:"AI draft ready"}),d.jsx("p",{className:"text-[11px] text-muted",children:"These first-pass overlays came from the cut script. Review and tune them here before exporting the final panel."})]}),Q.length>0&&d.jsxs("div",{className:"mb-3 space-y-1.5","data-testid":"script-insert-panel",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"From script"}),d.jsx("div",{className:"flex flex-col gap-1",children:Q.map(P=>d.jsxs("button",{onClick:()=>je(P),"data-testid":`script-insert-${P.key}`,title:`Add ${P.type} overlay with this text`,className:"text-left px-2 py-1 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5",children:[d.jsxs("span",{className:"font-medium text-accent",children:["+ ",ku[P.type]]})," ",d.jsxs("span",{className:"text-muted",children:[P.speaker?`${P.speaker}: `:"",P.text.length>32?`${P.text.slice(0,32)}…`:P.text]})]},P.key))})]}),Ae?d.jsxs("div",{className:"space-y-3",children:[d.jsx("p",{className:"text-xs font-medium text-foreground",children:ku[Ae.type]}),Ae.speaker!==void 0&&d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Speaker"}),d.jsx("input",{value:Ae.speaker||"",onChange:P=>be(Ae.id,{speaker:P.target.value}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",placeholder:"Character name","data-testid":"inspector-speaker"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Text"}),d.jsx("textarea",{value:Ae.text,onChange:P=>be(Ae.id,{text:P.target.value}),rows:3,className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent resize-none focus:border-accent focus:outline-none",placeholder:"Overlay text","data-testid":"inspector-text"})]}),d.jsx("button",{onClick:()=>be(Ae.id,Be(Ae)),"data-testid":"inspector-fit-text",className:"w-full px-2 py-1 text-[11px] border border-border rounded hover:border-accent hover:text-accent",title:"Resize this overlay so its text fits without overflowing",children:"Fit box to text"}),d.jsxs("div",{className:"space-y-1.5 rounded border border-border/70 p-2","data-testid":"inspector-typography",children:[d.jsxs("div",{className:"flex items-center justify-between gap-2",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Typography"}),((Bt=Ae.textStyle)==null?void 0:Bt.mode)==="manual"?d.jsx("button",{type:"button",onClick:()=>be(Ae.id,{textStyle:void 0}),className:"px-1.5 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"inspector-text-auto",children:"Auto-fit"}):d.jsx("button",{type:"button",onClick:()=>tt(Ae),className:"px-1.5 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"inspector-text-manual",children:"Manual"})]}),((vt=Ae.textStyle)==null?void 0:vt.mode)==="manual"?d.jsxs("div",{className:"space-y-1.5",children:[d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Font size (% panel height)"}),d.jsx("input",{type:"number",step:"0.1",min:"1.5",max:"12",value:((Ae.textStyle.fontScale??.032)*100).toFixed(1),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",fontScale:Math.max(.015,Math.min(.12,(parseFloat(P.target.value)||3.2)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-font-scale"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Weight"}),d.jsxs("select",{value:String(Ae.textStyle.fontWeight??400),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",fontWeight:P.target.value==="700"?700:400}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-font-weight",children:[d.jsx("option",{value:"400",children:"Regular"}),d.jsx("option",{value:"700",children:"Bold"})]})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Line height"}),d.jsx("input",{type:"number",step:"0.05",min:"0.9",max:"2",value:(Ae.textStyle.lineHeightFactor??1.2).toFixed(2),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",lineHeightFactor:Math.max(.9,Math.min(2,parseFloat(P.target.value)||1.2))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-line-height"})]}),Ae.type!=="sfx"&&d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Speaker scale"}),d.jsx("input",{type:"number",step:"0.05",min:"0.5",max:"1.5",value:(Ae.textStyle.speakerScale??.8).toFixed(2),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",speakerScale:Math.max(.5,Math.min(1.5,parseFloat(P.target.value)||.8))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-speaker-scale"})]})]}):d.jsx("p",{className:"text-[10px] text-muted",children:"Auto-fit stays on by default and resizes text to the box."})]}),Ae.type==="speech"&&(()=>{const P=Ae.tailAnchor||{x:.5,y:1.2};return d.jsxs("div",{className:"space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Tail anchor"}),d.jsx("div",{className:"flex flex-wrap gap-1","data-testid":"inspector-tail-presets",children:CD.map(we=>d.jsx("button",{type:"button",onClick:()=>be(Ae.id,{tailAnchor:we.anchor}),className:"px-1.5 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":`inspector-tail-${we.key}`,children:we.label},we.key))}),d.jsxs("div",{className:"flex gap-2",children:[d.jsxs("label",{className:"flex items-center gap-1 text-[10px] font-mono text-muted",children:["x",d.jsx("input",{type:"number",step:"0.1",value:P.x,onChange:we=>be(Ae.id,{tailAnchor:{...P,x:parseFloat(we.target.value)||0}}),className:"w-14 px-1 py-0.5 text-[10px] border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-tail-x"})]}),d.jsxs("label",{className:"flex items-center gap-1 text-[10px] font-mono text-muted",children:["y",d.jsx("input",{type:"number",step:"0.1",value:P.y,onChange:we=>be(Ae.id,{tailAnchor:{...P,y:parseFloat(we.target.value)||0}}),className:"w-14 px-1 py-0.5 text-[10px] border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-tail-y"})]})]})]})})(),Ae.type!=="sfx"&&d.jsxs("div",{className:"space-y-1.5 rounded border border-border/70 p-2","data-testid":"inspector-bubble-style",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Bubble controls"}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Padding X (% width)"}),d.jsx("input",{type:"number",step:"1",min:"0",max:"25",value:((((At=Ae.bubbleStyle)==null?void 0:At.paddingX)??.06)*100).toFixed(0),onChange:P=>be(Ae.id,{bubbleStyle:{...Ae.bubbleStyle,paddingX:Math.max(0,Math.min(.25,(parseFloat(P.target.value)||6)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-padding-x"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Padding Y (% height)"}),d.jsx("input",{type:"number",step:"1",min:"0",max:"25",value:((((Ze=Ae.bubbleStyle)==null?void 0:Ze.paddingY)??.08)*100).toFixed(0),onChange:P=>be(Ae.id,{bubbleStyle:{...Ae.bubbleStyle,paddingY:Math.max(0,Math.min(.25,(parseFloat(P.target.value)||8)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-padding-y"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Corner roundness (% short side)"}),d.jsx("input",{type:"number",step:"1",min:"0",max:"49",value:((((hi=Ae.bubbleStyle)==null?void 0:hi.cornerRadius)??.4)*100).toFixed(0),onChange:P=>be(Ae.id,{bubbleStyle:{...Ae.bubbleStyle,cornerRadius:Math.max(0,Math.min(.49,(parseFloat(P.target.value)||40)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-corner-radius"})]})]}),d.jsxs("div",{className:"text-[10px] text-muted","data-testid":"inspector-font",children:["Font:"," ",Ae.type==="sfx"?v.family:b.family]}),d.jsxs("div",{className:"text-[10px] font-mono text-muted space-y-0.5",children:[d.jsxs("p",{children:["x: ",Ae.x.toFixed(3),", y:"," ",Ae.y.toFixed(3)]}),d.jsxs("p",{children:["w: ",Ae.width.toFixed(3),", h:"," ",Ae.height.toFixed(3)]})]}),d.jsx("button",{onClick:()=>{A?St(Ae.id):O(!0)},className:"w-full px-2 py-1 text-xs text-error border border-error/30 rounded hover:bg-error/5","data-testid":"delete-overlay",children:A?"Click again to delete":"Delete"})]}):d.jsx("p",{className:"text-xs text-muted","data-testid":"inspector-empty",children:"Select an overlay to inspect."})]})]})]})}const ED={wide:"Wide",medium:"Medium","close-up":"Close-up","extreme-close-up":"Extreme close-up"},ND="No speech bubbles, captions, sound effects, narration, or any text or lettering in the image.",jD="Style lock — illustrated comic/webtoon panel art: clean black contour/ink lines, flat or cel shading, simplified but realistic (semi-realistic) anatomy and faces, backgrounds drawn as illustrated comic panels. Hold this same style on every cut for character and panel consistency. Hard negatives — NOT photorealistic, NOT a photograph, NOT a glossy or painterly digital painting, NOT concept art, NOT a 3D/CGI render, NOT airbrushed, no photoreal textures.";function TD(e){var a;const t=ED[e.shotType]??e.shotType,i=((a=e.description)==null?void 0:a.trim())||`Cut ${e.id}`,s=[`${t} shot. ${i}`];return e.characters.length>0&&s.push(`Characters: ${e.characters.join(", ")}.`),s.push(jD),s.push(ND),s.join(`
+`).map(x=>x.trim()).filter(Boolean),p=h.filter(x=>/^([-*+]|\d+[.)])\s/.test(x)||Mf.test(x)).length,f=c.split(/\n\s*\n/).map(x=>x.trim()).filter(Boolean),_=f.some(x=>x.length>=120&&!/^([-*+]|\d+[.)])\s/.test(x)&&!Mf.test(x));h.length>0&&p/h.length>=.5||!_?t.push("This reads like a synopsis or outline. Write the Genesis as a reader-facing opening scene that sets up the first beat and stakes, then bridges into Episode 01 — not a logline, genre pitch, or character list."):f.filter(b=>b.length>=40&&!/^([-*+]|\d+[.)])\s/.test(b)&&!Mf.test(b)).length<2&&t.push("Give the opening room to build: open across a few short paragraphs — the premise, what the lead wants, and the hook — that lead into Episode 01, instead of a single dense block that drops readers into a cold scene.")}return{hasTitle:o,blockers:t,warnings:i}}function nD(e){return/\.(webp|jpe?g)$/i.test(e)}function Op(e){var c,h;let t=0,i=0,s=0,a=0,o=0;for(const p of e)In(p)?(((h=p.overlays)==null?void 0:h.length)??0)>0&&s++:(t++,p.cleanImagePath&&nD(p.cleanImagePath)&&(i++,(((c=p.overlays)==null?void 0:c.length)??0)>0&&s++)),p.finalImagePath&&p.exportedAt&&a++,p.uploadedUrl&&o++;return{total:e.length,needClean:t,withClean:i,withText:s,exported:a,uploaded:o}}const rD={plan:"Plan cuts",clean:"Create clean images",letter:"Add speech bubbles & captions",export:"Export final images",upload:"Upload final images",publish:"Publish to PlotLink"};function vo(e,t){return`${e} / ${t} cut${t===1?"":"s"}`}function sD(e){const{cuts:t,published:i=!1}=e,s=Op(t);if(s.total===0)return{steps:[],nextStep:null};const a=s.total>0,o=a&&s.withClean===s.needClean,c=o&&s.withText===s.total,h=c&&s.exported===s.total,p=h&&s.uploaded===s.total,_={plan:a,clean:o,letter:c,export:h,upload:p,publish:p&&i},x=["plan","clean","letter","export","upload","publish"],b=x.findIndex(N=>!_[N]),v=N=>s.needClean>0?vo(N,s.needClean):"no image cuts",S={plan:vo(s.total,s.total),clean:v(s.withClean),letter:vo(s.withText,s.total),export:vo(s.exported,s.total),upload:vo(s.uploaded,s.total),publish:null},j=x.map((N,I)=>({key:N,label:rD[N],status:b===-1||IFS,a=oD({stage:t,imageCount:i.imageCount,hasNonImageProse:i.nonImageProse.length>0});return d.jsxs("div",{className:"h-full overflow-y-auto","data-testid":"cartoon-publish-preview",children:[d.jsxs("div",{className:"px-4 py-2 border-b border-border text-[10px] text-muted flex flex-wrap items-center gap-x-3 gap-y-1","data-testid":"cartoon-publish-summary",children:[d.jsxs("span",{children:[i.imageCount," image",i.imageCount===1?"":"s"]}),d.jsxs("span",{children:[i.charCount.toLocaleString()," / 10,000 chars"]}),d.jsx("span",{className:`rounded-full px-2 py-0.5 font-medium ${a.possible?"bg-green-100 text-green-800":"bg-background text-muted"}`,"data-testid":"publish-possible",children:a.possible?"Publish possible":"Publish not possible yet"}),d.jsx("span",{className:`rounded-full px-2 py-0.5 font-medium ${a.recommended?"bg-green-100 text-green-800":a.tone==="warning"?"bg-amber-100 text-amber-800":"bg-background text-muted"}`,"data-testid":"publish-recommended",children:a.recommended?"Recommended":"Not recommended yet"})]}),d.jsxs("div",{className:`px-4 py-2 border-b text-[11px] ${uD[a.tone]}`,"data-testid":"cartoon-publish-verdict",children:[d.jsx("p",{className:"font-medium",children:a.headline}),a.detail&&d.jsx("p",{className:"mt-0.5 opacity-90",children:a.detail}),a.action&&d.jsxs("p",{className:"mt-0.5 opacity-90",children:["→ ",a.action]})]}),i.nonImageProse&&d.jsxs("div",{className:"px-4 py-2 border-b border-amber-300 bg-amber-50 text-[11px] text-amber-800","data-testid":"cartoon-nonimage-prose",children:[d.jsx("p",{className:"font-medium",children:"⚠ Non-image text in the published markdown:"}),d.jsxs("p",{className:"font-mono mt-1 whitespace-pre-wrap break-words",children:[i.nonImageProsePreview,s?"…":""]}),d.jsx("p",{className:"mt-1",children:"This text publishes verbatim around the comic images. Remove it (or re-run “Prepare episode for publish”) if it is planning or placeholder prose."})]}),d.jsx("div",{className:"max-w-lg mx-auto px-4 py-6",children:e.trim()?d.jsx("div",{className:"prose max-w-none",children:d.jsx(rS,{remarkPlugins:[aS,AS],rehypePlugins:[[BS,cD]],children:e})}):d.jsx("p",{className:"text-muted italic text-sm","data-testid":"cartoon-publish-empty",children:"No publish markdown yet — build it from the cut plan (Edit → Upload & Prepare for Publish)."})})]})}const dD="modulepreload",fD=function(e){return"/"+e},sy={},ay=function(t,i,s){let a=Promise.resolve();if(i&&i.length>0){let c=function(f){return Promise.all(f.map(_=>Promise.resolve(_).then(x=>({status:"fulfilled",value:x}),x=>({status:"rejected",reason:x}))))};document.getElementsByTagName("link");const h=document.querySelector("meta[property=csp-nonce]"),p=(h==null?void 0:h.nonce)||(h==null?void 0:h.getAttribute("nonce"));a=c(i.map(f=>{if(f=fD(f),f in sy)return;sy[f]=!0;const _=f.endsWith(".css"),x=_?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${f}"]${x}`))return;const b=document.createElement("link");if(b.rel=_?"stylesheet":dD,_||(b.as="script"),b.crossOrigin="",b.href=f,p&&b.setAttribute("nonce",p),document.head.appendChild(b),_)return new Promise((v,S)=>{b.addEventListener("load",v),b.addEventListener("error",()=>S(new Error(`Unable to preload CSS for ${f}`)))})}))}function o(c){const h=new Event("vite:preloadError",{cancelable:!0});if(h.payload=c,window.dispatchEvent(h),!h.defaultPrevented)throw c}return a.then(c=>{for(const h of c||[])h.status==="rejected"&&o(h.reason);return t().catch(o)})},vm=[{family:"Noto Sans",googleFontsId:"Noto+Sans",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans/about",category:"body",weights:[400,500,700],languages:["English","Spanish","French","Portuguese","Russian","Others"]},{family:"Noto Sans KR",googleFontsId:"Noto+Sans+KR",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+KR/about",category:"body",weights:[400,500,700],languages:["Korean"]},{family:"Noto Sans JP",googleFontsId:"Noto+Sans+JP",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+JP/about",category:"body",weights:[400,500,700],languages:["Japanese"]},{family:"Noto Sans SC",googleFontsId:"Noto+Sans+SC",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+SC/about",category:"body",weights:[400,500,700],languages:["Chinese"]},{family:"Noto Sans Devanagari",googleFontsId:"Noto+Sans+Devanagari",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Sans+Devanagari/about",category:"body",weights:[400,500,700],languages:["Hindi"]},{family:"Noto Naskh Arabic",googleFontsId:"Noto+Naskh+Arabic",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/noto/specimen/Noto+Naskh+Arabic/about",category:"body",weights:[400,500,700],languages:["Arabic"]},{family:"Bangers",googleFontsId:"Bangers",license:"OFL-1.1",licenseUrl:"https://fonts.google.com/specimen/Bangers/about",category:"display",weights:[400],languages:[]}],pD="system-ui, sans-serif",mD=vm.find(e=>e.family==="Noto Sans"),gD=vm.find(e=>e.category==="display");function xD(e){return vm.find(i=>i.category==="body"&&i.languages.includes(e))||mD}function _D(){return gD}function bD(e){const t=e.weights.join(";");return`https://fonts.googleapis.com/css2?family=${e.googleFontsId}:wght@${t}&display=swap`}function ly(e){return`"${e.family}", ${pD}`}function vD(e,t={}){var a,o,c,h;const i=!t.staleExport&&(!!e.finalImagePath||!!e.exportedAt),s=!t.staleExport&&(!!e.uploadedUrl||!!e.uploadedCid);return{hasCleanImage:!!e.cleanImagePath,hasScriptText:(((a=e.dialogue)==null?void 0:a.length)??0)>0||!!((o=e.narration)!=null&&o.trim())||!!((c=e.sfx)!=null&&c.trim()),bubblesPlaced:((h=e.overlays)==null?void 0:h.length)??0,exported:i,uploaded:s}}function ul(e){return JSON.stringify((e??[]).map(t=>[t.type,t.x,t.y,t.width,t.height,t.text,t.speaker??"",t.tailAnchor??null,t.textStyle??null,t.bubbleStyle??null]))}function yD(e){return!e.exported&&!e.uploaded?!1:e.baselineSig!==ul(e.current)}function ym(e){var i,s;const t=[];return(e.dialogue??[]).forEach((a,o)=>{var c;(c=a==null?void 0:a.text)!=null&&c.trim()&&t.push({type:"speech",speaker:a.speaker,text:a.text.trim(),key:`speech-${o}`})}),(i=e.narration)!=null&&i.trim()&&t.push({type:"narration",text:e.narration.trim(),key:"narration"}),(s=e.sfx)!=null&&s.trim()&&t.push({type:"sfx",text:e.sfx.trim(),key:"sfx"}),t}function SD(e,t,i){if(e==="narration")return{x:.08,y:.05+Math.min(t,2)*.18};if(e==="sfx"){const c=t%2,h=Math.floor(t/2);return{x:c===0?.1:.62,y:.68+h*.12}}const s=Math.floor(t/2),a=t%2===0,o=.08+s*Math.max(.15,Math.min(.22,i>4?.16:.2));return{x:a?.05:.45,y:o}}function oy(e){const t=ym(e);return t.map((i,s)=>{const{x:a,y:o}=SD(i.type,s,t.length),c=Lp(i.type,a,o),h=US(i.type,a,o);return{...c,...h,text:i.text,...i.type==="speech"?{speaker:i.speaker??""}:{}}})}function wn(e,t){return e*t}function cy(e,t){return t===0?0:e/t}function uy(e){const t=`gfont-${e.googleFontsId}`;if(document.getElementById(t))return;const i=document.createElement("link");i.id=t,i.rel="stylesheet",i.href=bD(e),document.head.appendChild(i)}const ku={speech:"Speech",narration:"Narration",sfx:"SFX"},wD={speech:"border-foreground/40",narration:"border-muted/40",sfx:"border-accent/40"};function Bf(e){const t=(e.speaker||e.text||"").trim().replace(/\s+/g," ");return t?`“${t.length>18?`${t.slice(0,18)}…`:t}”`:ku[e.type]}const hy=.05,CD=[{key:"down",label:"Down",anchor:{x:.5,y:1.2}},{key:"up",label:"Up",anchor:{x:.5,y:-.2}},{key:"left",label:"Left",anchor:{x:-.2,y:.5}},{key:"right",label:"Right",anchor:{x:1.2,y:.5}}];function pu(e,t,i){return Math.min(i,Math.max(t,e))}function kD({storyName:e,cut:t,plotFile:i,onSave:s,onClose:a,onExported:o,language:c="English",authFetch:h,targetLabel:p,returnOnSave:f=!1,workspaceVisible:_=!1,onToggleWorkspaceVisible:x}){var Wt,ui,Bt,vt,At,Ze,hi;const b=xD(c),v=_D(),S=ly(b),j=ly(v);w.useEffect(()=>{uy(b),uy(v)},[b,v]),w.useEffect(()=>{let P=!1;return K(!1),(async()=>{try{const{ensureFontsReady:we}=await ay(async()=>{const{ensureFontsReady:ze}=await import("./export-cut-CDJl8Zjg.js");return{ensureFontsReady:ze}},[]);await we([b.family,v.family])}catch{}P||K(!0)})(),()=>{P=!0}},[b.family,v.family]);const R=zS(e,t.cleanImagePath,h),E=w.useMemo(()=>$3(t.overlays),[t.overlays]),N=E.invalid.length,[I,te]=w.useState(!1),F=N===0&&E.changed&&E.overlays.length>0,[D,ie]=w.useState(()=>E.overlays),[fe,Se]=w.useState(()=>ul(E.overlays)),H=w.useRef(null),ce=w.useCallback(P=>(we,ze,Re=400)=>{var $e;!H.current&&typeof document<"u"&&(H.current=document.createElement("canvas"));const Ge=($e=H.current)==null?void 0:$e.getContext("2d");return Ge?(Ge.font=`${Re} ${ze}px ${P}`,Ge.measureText(we).width):we.length*ze*.5},[]),[W,K]=w.useState(!1),[X,U]=w.useState(null),[A,O]=w.useState(!1),[$,xe]=w.useState(!1),[T,M]=w.useState(null),[G,C]=w.useState(null),[V,ne]=w.useState({x:0,y:0,width:0,height:0}),ae=w.useRef(null),Y=w.useRef(null),he=w.useRef(null),_e=w.useCallback(()=>{const P=ae.current;if(!P)return;const we=P.clientWidth,ze=P.clientHeight;let Re,Ge;if(t.kind==="text"){const lt=G3(t.aspectRatio)??{width:800,height:600};Re=lt.width,Ge=lt.height}else{const lt=Y.current;if(!lt||!lt.naturalWidth)return;Re=lt.naturalWidth,Ge=lt.naturalHeight}if(!we||!ze)return;const $e=Math.min(we/Re,ze/Ge),ht=Re*$e,dt=Ge*$e;ne({x:(we-ht)/2,y:(ze-dt)/2,width:ht,height:dt})},[t.kind,t.aspectRatio]);w.useEffect(()=>{const P=ae.current;if(!P)return;const we=new ResizeObserver(()=>_e());return we.observe(P),()=>we.disconnect()},[_e]);const Be=w.useCallback(P=>{const we=US(P.type,P.x,P.y),ze=we.width,Re=Math.max(.08,1-P.y);if(!P.text||!W||V.width<=0)return we;const Ge=P.type==="sfx"?j:S,$e=wn(ze,V.width);let ht=P.type==="sfx"?.08:.12;for(let dt=0;dt<24;dt++){const lt=Math.min(ht,Re),Vt=wn(lt,V.height);if(!uu(ce(Ge),P.text,$e,Vt,hu({...P},V.height||300,$e,Vt)).overflow||lt>=Re)return{width:ze,height:lt};ht+=.03}return{width:ze,height:Math.min(ht,Re)}},[W,V,ce,S,j]),Le=w.useCallback(P=>{const we=Lp(P,.1+Math.random()*.3,.1+Math.random()*.3),ze={...we,...Be(we)};ie(Re=>[...Re,ze]),U(ze.id)},[Be]),je=w.useCallback(P=>{const ze={...Lp(P.type,.1+Math.random()*.3,.1+Math.random()*.3),text:P.text,...P.type==="speech"&&P.speaker?{speaker:P.speaker}:{}},Re={...ze,...Be(ze)};ie(Ge=>[...Ge,Re]),U(Re.id)},[Be]),be=w.useCallback((P,we)=>{ie(ze=>ze.map(Re=>Re.id===P?{...Re,...we}:Re))},[]),tt=w.useCallback(P=>{var ht;const we=V.height||300,ze=V.width>0?wn(P.width,V.width):200,Re=V.height>0?wn(P.height,V.height):100,Ge=P.type==="sfx"?j:S,$e=uu(ce(Ge),P.text,ze,Re,hu({...P,textStyle:void 0},we,ze,Re));be(P.id,{textStyle:{mode:"manual",fontScale:$e.fontSize/Math.max(1,we),fontWeight:((ht=P.textStyle)==null?void 0:ht.fontWeight)??400,lineHeightFactor:$e.fontSize>0?$e.lineHeight/$e.fontSize:1.2,speakerScale:$e.fontSize>0&&$e.speakerFontSize>0?$e.speakerFontSize/$e.fontSize:.8}})},[V,j,S,ce,be]),St=w.useCallback(P=>{ie(we=>we.filter(ze=>ze.id!==P)),U(null),O(!1)},[]),ot=w.useCallback(()=>{U(null),O(!1)},[]),We=w.useCallback((P,we)=>{P.stopPropagation(),U(we),O(!1)},[]),Mt=w.useCallback((P,we,ze)=>{P.stopPropagation(),P.preventDefault();const Re=D.find(Ge=>Ge.id===we);Re&&(U(we),he.current={id:we,mode:ze,startX:P.clientX,startY:P.clientY,origX:Re.x,origY:Re.y,origW:Re.width,origH:Re.height})},[D]);w.useEffect(()=>{const P=ze=>{const Re=he.current;if(!Re||V.width===0)return;const Ge=cy(ze.clientX-Re.startX,V.width),$e=cy(ze.clientY-Re.startY,V.height);if(Re.mode==="move"){const ht=pu(Re.origX+Ge,0,1-Re.origW),dt=pu(Re.origY+$e,0,1-Re.origH);be(Re.id,{x:ht,y:dt})}else{const ht=pu(Re.origW+Ge,hy,1-Re.origX),dt=pu(Re.origH+$e,hy,1-Re.origY);be(Re.id,{width:ht,height:dt})}},we=()=>{he.current=null};return window.addEventListener("mousemove",P),window.addEventListener("mouseup",we),()=>{window.removeEventListener("mousemove",P),window.removeEventListener("mouseup",we)}},[V,be]);const He=w.useCallback(async()=>{var P;C(null);try{const we=ul(D),ze=((P=t.aiDraft)==null?void 0:P.status)==="generated"&&we!==(t.aiDraft.baseSig??"")?{...t.aiDraft,status:"edited",updatedAt:new Date().toISOString()}:t.aiDraft??void 0;await s(D,ze??null),f&&a()}catch(we){C(we instanceof Error?we.message:"Failed to save overlays")}},[D,s,a,f,t.aiDraft]),xt=w.useCallback(async()=>{if(N>0&&!I){const P=N;M(`${P} overlay${P===1?"":"s"} from the cut plan ${P===1?"has":"have"} no usable position and cannot be exported — re-place ${P===1?"it":"them"} or discard ${P===1?"it":"them"} first.`);return}xe(!0),M(null);try{await s(D);const{exportCut:P,ensureFontsReady:we}=await ay(async()=>{const{exportCut:ft,ensureFontsReady:Fi}=await import("./export-cut-CDJl8Zjg.js");return{exportCut:ft,ensureFontsReady:Fi}},[]),ze=D.some(ft=>ft.type==="sfx"),Re=[b.family,...ze?[v.family]:[]],{ready:Ge,missing:$e}=await we(Re);if(!Ge){M(`Fonts not loaded: ${$e.join(", ")}. Check your connection and retry.`),xe(!1);return}if(t.cleanImagePath&&!R.url){M(R.error?"Clean image failed to load — cannot export. Retry once it renders.":"Clean image still loading — wait for it to render, then export."),xe(!1);return}const ht=R.url,dt=await P(ht,D,S,j,{narration:t.narration,dialogue:t.dialogue},t.kind==="text"?{background:t.background,aspectRatio:t.aspectRatio}:void 0),lt=new FormData,Vt=dt.type==="image/webp"?"webp":"jpg";lt.append("file",dt,`cut-${t.id}.${Vt}`);const Ci=await h(`/api/stories/${e}/cuts/${i}/export-final/${t.id}`,{method:"POST",body:lt});if(Ci.ok)Se(ul(D)),o==null||o();else{const ft=await Ci.json();M(ft.error||"Export failed")}}catch(P){M(P instanceof Error?P.message:"Export failed")}finally{xe(!1)}},[t,R,D,e,i,b,v,S,j,h,s,o,N,I]),Ae=D.find(P=>P.id===X),Kt=w.useMemo(()=>q3(D),[D]),mi=w.useRef(t.id);w.useEffect(()=>{mi.current!==t.id&&(mi.current=t.id,Se(ul(E.overlays)))},[t.id,E.overlays]);const wt=yD({exported:!!t.finalImagePath||!!t.exportedAt,uploaded:!!t.uploadedUrl||!!t.uploadedCid,baselineSig:fe,current:D}),Qe=w.useMemo(()=>vD({...t,overlays:D},{staleExport:wt}),[t,D,wt]),Q=w.useMemo(()=>ym(t),[t]),ge=w.useMemo(()=>{const P={};for(const we of D){const ze=z3(we);let Re=!1;if(W&&V.width>0&&we.text){const Ge=we.type==="sfx"?j:S,$e=wn(we.width,V.width),ht=wn(we.height,V.height);Re=uu(ce(Ge),we.text,$e,ht,hu(we,V.height||300,$e,ht)).overflow}(ze||Re)&&(P[we.id]={outOfBounds:ze,overflow:Re})}return P},[D,W,V,ce,S,j]),Te=Object.keys(ge).length,Ue=t.kind==="text",it=!t.cleanImagePath;return!Ue&&it&&D.length===0&&!t.narration&&!((Wt=t.dialogue)!=null&&Wt.length)?d.jsx("div",{className:"h-full flex items-center justify-center text-sm text-muted",children:"No clean image — upload one first, or add overlays for a narration cut."}):d.jsxs("div",{className:"h-full flex flex-col","data-testid":"focused-lettering-editor",children:[d.jsxs("div",{className:"px-4 py-3 border-b border-border bg-surface/40 flex items-center justify-between gap-3",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("span",{className:"text-[10px] font-bold uppercase tracking-[0.16em] text-accent",children:"Focused lettering editor"}),d.jsx("span",{className:"text-xs font-mono text-muted",children:p??`Cut #${t.id}`})]}),d.jsx("p",{className:"mt-0.5 text-[11px] text-muted",children:"Place bubbles, captions, SFX, or between-scene card text, then save back to the full cut review."}),d.jsxs("span",{className:"text-[10px] text-muted","data-testid":"overlay-count",children:[D.length," overlays"]})]}),d.jsxs("div",{className:"flex items-center gap-2 flex-wrap justify-end",children:[d.jsx("button",{onClick:a,className:"px-3 py-1 text-xs border border-border rounded text-muted hover:text-foreground","data-testid":"return-to-cut-review-btn",children:"Back to cut review"}),x&&d.jsx("button",{onClick:x,className:"px-3 py-1 text-xs border border-border rounded text-muted hover:border-accent hover:text-accent","data-testid":"toggle-work-area-btn",children:_?"Hide work area":"Show work area"}),d.jsxs("div",{className:"flex items-center gap-1 ml-2",children:[d.jsx("button",{onClick:()=>Le("speech"),className:"px-2 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"add-speech",children:"Speech"}),d.jsx("button",{onClick:()=>Le("narration"),className:"px-2 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"add-narration",children:"Narration"}),d.jsx("button",{onClick:()=>Le("sfx"),className:"px-2 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"add-sfx",children:"SFX"})]}),T&&d.jsx("span",{className:"text-[10px] text-error",children:T}),G&&d.jsx("span",{className:"text-[10px] text-error",children:G}),d.jsx("button",{onClick:xt,disabled:$,className:"px-3 py-1 text-xs border border-accent text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"export-btn",children:$?"Exporting...":"Export"}),d.jsx("button",{onClick:()=>{He()},className:"px-3 py-1 text-xs bg-accent text-white rounded hover:bg-accent-dim","data-testid":"save-lettering-btn",children:"Save"}),d.jsx("button",{onClick:a,className:"px-3 py-1 text-xs text-muted hover:text-foreground border border-border rounded","data-testid":"cancel-lettering-btn",children:"Cancel"})]})]}),N>0&&!I?d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-error/10 text-[10px] text-error flex items-center gap-2 flex-wrap","data-testid":"overlay-repair-note",children:[d.jsxs("span",{children:[N," overlay",N===1?"":"s"," ","from the cut plan ",N===1?"has":"have"," no usable position and cannot be exported. Re-place"," ",N===1?"it":"them",", or"]}),d.jsxs("button",{onClick:()=>te(!0),"data-testid":"discard-invalid-overlays",className:"px-1.5 py-0.5 border border-error/40 rounded hover:bg-error/10",children:["discard ",N," unplaceable overlay",N===1?"":"s"]})]}):N>0?d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"overlay-repair-note",children:["Discarded ",N," unplaceable overlay",N===1?"":"s"," — the export will not include"," ",N===1?"it":"them","."]}):F?d.jsx("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"overlay-repair-note",children:"Auto-placed overlays from the cut plan — review their positions before exporting."}):null,Kt.length>0&&d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"overlay-overlap-warning",children:["Cut #",t.id,": ",Kt.length," bubble"," ",Kt.length===1?"pair overlaps":"pairs overlap"," and may be hard to read —"," ",Kt.map(P=>`#${P.indexA+1} ${Bf(D[P.indexA])} ↔ #${P.indexB+1} ${Bf(D[P.indexB])}`).join("; "),". Move them apart, or export as-is if the overlap is intended."]}),d.jsx("div",{className:"px-3 py-1 border-b border-border flex items-center gap-3 flex-wrap text-[10px] text-muted","data-testid":"lettering-checklist",children:[["clean-image","Clean image",Qe.hasCleanImage],["script-text","Script text",Qe.hasScriptText],["bubbles",`Bubbles placed${Qe.bubblesPlaced?` (${Qe.bubblesPlaced})`:""}`,Qe.bubblesPlaced>0],["exported","Final exported",Qe.exported],["uploaded","Uploaded",Qe.uploaded]].map(([P,we,ze])=>d.jsxs("span",{"data-testid":`lettering-check-${P}`,"data-done":ze?"true":"false",className:`flex items-center gap-1 ${ze?"text-green-700":"text-muted/70"}`,children:[d.jsx("span",{"aria-hidden":!0,children:ze?"✓":"○"}),we]},P))}),wt&&d.jsx("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"lettering-stale-export-warning",children:"Bubbles changed since the last export — re-export this cut and upload the new final image before publishing."}),Te>0&&d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-amber-500/10 text-[10px] text-amber-700","data-testid":"lettering-export-warning",children:[Te," bubble",Te===1?"":"s"," may not export cleanly:"," ",Object.entries(ge).map(([P,we])=>{const ze=D.findIndex(Ge=>Ge.id===P),Re=[we.outOfBounds?"outside image":null,we.overflow?"text overflow":null].filter(Boolean).join(", ");return`#${ze+1} ${Bf(D[ze])} (${Re})`}).join("; "),". Resize or reposition before exporting."]}),d.jsxs("div",{className:"flex-1 min-h-0 flex",children:[d.jsxs("div",{ref:ae,className:"flex-1 min-w-0 relative overflow-hidden bg-[#f8f5ef]",onClick:ot,"data-testid":"editor-surface",children:[t.cleanImagePath&&R.error?d.jsx("div",{className:"w-full h-full flex items-center justify-center text-muted text-xs","data-testid":"clean-image-error",children:"Clean image not available"}):t.cleanImagePath&&!R.url?d.jsx("div",{className:"w-full h-full flex items-center justify-center text-muted text-xs","data-testid":"clean-image-loading",children:"Loading clean image…"}):t.cleanImagePath?d.jsx("img",{ref:Y,src:R.url,alt:`Cut ${t.id} clean`,className:"w-full h-full object-contain",draggable:!1,onLoad:_e}):Ue?V.width>0&&d.jsx("div",{className:"absolute flex items-center justify-center text-muted text-xs",style:{left:V.x,top:V.y,width:V.width,height:V.height,background:t.background||"#ffffff"},"data-testid":"text-panel-canvas",children:"Text panel"}):d.jsx("div",{className:"w-full h-full bg-white flex items-center justify-center text-muted text-xs",ref:P=>{if(P&&V.width===0){const we=P.getBoundingClientRect();we.width>0&&ne({x:0,y:0,width:we.width,height:we.height})}},children:"Narration cut"}),V.width>0&&d.jsx("svg",{className:"absolute inset-0 w-full h-full pointer-events-none","data-testid":"balloon-layer",children:D.map(P=>{if(P.type!=="speech")return null;const we=V.x+wn(P.x,V.width),ze=V.y+wn(P.y,V.height),Re=wn(P.width,V.width),Ge=wn(P.height,V.height),$e=M3(P,Re,Ge),ht=P.tailAnchor?HS(we,ze,Re,Ge,P.tailAnchor,$e):null,dt=Math.max(1.5,V.height*.004),lt=P.id===X;return d.jsx("path",{"data-testid":`balloon-${P.id}`,d:O3(we,ze,Re,Ge,ht,$e),className:`fill-white/95 ${lt?"stroke-accent":"stroke-[#1a1a1a]"}`,strokeWidth:lt?dt+.5:dt,strokeLinejoin:"round"},P.id)})}),V.width>0&&D.map(P=>{const we=V.x+wn(P.x,V.width),ze=V.y+wn(P.y,V.height),Re=wn(P.width,V.width),Ge=wn(P.height,V.height),$e=P.id===X,ht=P.type==="speech",dt=P.type==="narration",lt=!!ge[P.id];return d.jsxs("div",{"data-testid":`overlay-${P.id}`,"data-warning":lt?"true":"false",onClick:Vt=>We(Vt,P.id),onMouseDown:Vt=>Mt(Vt,P.id,"move"),className:`absolute rounded cursor-move select-none ${ht?"":`border-2 ${wD[P.type]}`} ${dt?"bg-[#f4efe6]/85 rounded-md":""} ${$e&&!ht?"ring-2 ring-accent":""} ${lt?"ring-2 ring-amber-500":""}`,style:{left:we,top:ze,width:Re,height:Ge},children:[(()=>{var Fi,En;const Vt=P.type==="sfx"?j:S;if(!P.text)return d.jsx("span",{className:"text-[9px] px-1 text-muted truncate block pointer-events-none",style:{fontFamily:Vt},children:ku[P.type]});const Ci=P.type!=="sfx"&&!!P.speaker;if(!W)return d.jsx("div",{className:"absolute inset-0 flex items-center justify-center px-1 overflow-hidden pointer-events-none text-center break-words",style:{fontFamily:Vt,fontSize:Math.max(9,Math.min(Ge*.05,16)),fontWeight:((Fi=P.textStyle)==null?void 0:Fi.fontWeight)??400},"data-testid":`overlay-text-${P.id}`,"data-fonts-ready":"false",children:Ci?`${P.speaker}: ${P.text}`:P.text});const ft=uu(ce(Vt),P.text,Re,Ge,hu(P,V.height,Re,Ge));return d.jsxs("div",{className:"absolute inset-0 flex flex-col items-center justify-center px-1 overflow-hidden pointer-events-none text-center",style:{fontFamily:Vt},"data-testid":`overlay-text-${P.id}`,"data-fonts-ready":"true",children:[Ci&&d.jsx("span",{className:"font-bold text-[#3a3a3a] block",style:{fontSize:ft.speakerFontSize,lineHeight:1.2},children:P.speaker}),d.jsx("span",{className:"text-[#1a1a1a]",style:{fontSize:ft.fontSize,lineHeight:`${ft.lineHeight}px`,fontWeight:((En=P.textStyle)==null?void 0:En.fontWeight)??400},children:ft.lines.map((ln,Un)=>d.jsx("span",{className:"block",children:ln},Un))})]})})(),$e&&d.jsx("div",{onMouseDown:Vt=>{Vt.stopPropagation(),Mt(Vt,P.id,"resize")},className:"absolute bottom-0 right-0 w-2 h-2 bg-accent cursor-se-resize","data-testid":`resize-${P.id}`})]},P.id)})]}),d.jsxs("div",{className:"w-64 border-l border-border p-3 overflow-y-auto flex-shrink-0",children:[((ui=t.aiDraft)==null?void 0:ui.status)==="generated"&&d.jsxs("div",{className:"mb-3 rounded border border-accent/30 bg-accent/5 p-2 space-y-1","data-testid":"ai-draft-current-target",children:[d.jsx("p",{className:"text-[10px] font-bold uppercase tracking-[0.14em] text-accent",children:"AI draft ready"}),d.jsx("p",{className:"text-[11px] text-muted",children:"These first-pass overlays came from the cut script. Review and tune them here before exporting the final panel."})]}),Q.length>0&&d.jsxs("div",{className:"mb-3 space-y-1.5","data-testid":"script-insert-panel",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"From script"}),d.jsx("div",{className:"flex flex-col gap-1",children:Q.map(P=>d.jsxs("button",{onClick:()=>je(P),"data-testid":`script-insert-${P.key}`,title:`Add ${P.type} overlay with this text`,className:"text-left px-2 py-1 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5",children:[d.jsxs("span",{className:"font-medium text-accent",children:["+ ",ku[P.type]]})," ",d.jsxs("span",{className:"text-muted",children:[P.speaker?`${P.speaker}: `:"",P.text.length>32?`${P.text.slice(0,32)}…`:P.text]})]},P.key))})]}),Ae?d.jsxs("div",{className:"space-y-3",children:[d.jsx("p",{className:"text-xs font-medium text-foreground",children:ku[Ae.type]}),Ae.speaker!==void 0&&d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Speaker"}),d.jsx("input",{value:Ae.speaker||"",onChange:P=>be(Ae.id,{speaker:P.target.value}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",placeholder:"Character name","data-testid":"inspector-speaker"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Text"}),d.jsx("textarea",{value:Ae.text,onChange:P=>be(Ae.id,{text:P.target.value}),rows:3,className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent resize-none focus:border-accent focus:outline-none",placeholder:"Overlay text","data-testid":"inspector-text"})]}),d.jsx("button",{onClick:()=>be(Ae.id,Be(Ae)),"data-testid":"inspector-fit-text",className:"w-full px-2 py-1 text-[11px] border border-border rounded hover:border-accent hover:text-accent",title:"Resize this overlay so its text fits without overflowing",children:"Fit box to text"}),d.jsxs("div",{className:"space-y-1.5 rounded border border-border/70 p-2","data-testid":"inspector-typography",children:[d.jsxs("div",{className:"flex items-center justify-between gap-2",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Typography"}),((Bt=Ae.textStyle)==null?void 0:Bt.mode)==="manual"?d.jsx("button",{type:"button",onClick:()=>be(Ae.id,{textStyle:void 0}),className:"px-1.5 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"inspector-text-auto",children:"Auto-fit"}):d.jsx("button",{type:"button",onClick:()=>tt(Ae),className:"px-1.5 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":"inspector-text-manual",children:"Manual"})]}),((vt=Ae.textStyle)==null?void 0:vt.mode)==="manual"?d.jsxs("div",{className:"space-y-1.5",children:[d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Font size (% panel height)"}),d.jsx("input",{type:"number",step:"0.1",min:"1.5",max:"12",value:((Ae.textStyle.fontScale??.032)*100).toFixed(1),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",fontScale:Math.max(.015,Math.min(.12,(parseFloat(P.target.value)||3.2)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-font-scale"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Weight"}),d.jsxs("select",{value:String(Ae.textStyle.fontWeight??400),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",fontWeight:P.target.value==="700"?700:400}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-font-weight",children:[d.jsx("option",{value:"400",children:"Regular"}),d.jsx("option",{value:"700",children:"Bold"})]})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Line height"}),d.jsx("input",{type:"number",step:"0.05",min:"0.9",max:"2",value:(Ae.textStyle.lineHeightFactor??1.2).toFixed(2),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",lineHeightFactor:Math.max(.9,Math.min(2,parseFloat(P.target.value)||1.2))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-line-height"})]}),Ae.type!=="sfx"&&d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Speaker scale"}),d.jsx("input",{type:"number",step:"0.05",min:"0.5",max:"1.5",value:(Ae.textStyle.speakerScale??.8).toFixed(2),onChange:P=>be(Ae.id,{textStyle:{...Ae.textStyle,mode:"manual",speakerScale:Math.max(.5,Math.min(1.5,parseFloat(P.target.value)||.8))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-speaker-scale"})]})]}):d.jsx("p",{className:"text-[10px] text-muted",children:"Auto-fit stays on by default and resizes text to the box."})]}),Ae.type==="speech"&&(()=>{const P=Ae.tailAnchor||{x:.5,y:1.2};return d.jsxs("div",{className:"space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Tail anchor"}),d.jsx("div",{className:"flex flex-wrap gap-1","data-testid":"inspector-tail-presets",children:CD.map(we=>d.jsx("button",{type:"button",onClick:()=>be(Ae.id,{tailAnchor:we.anchor}),className:"px-1.5 py-0.5 text-[10px] border border-border rounded hover:border-accent hover:bg-accent/5","data-testid":`inspector-tail-${we.key}`,children:we.label},we.key))}),d.jsxs("div",{className:"flex gap-2",children:[d.jsxs("label",{className:"flex items-center gap-1 text-[10px] font-mono text-muted",children:["x",d.jsx("input",{type:"number",step:"0.1",value:P.x,onChange:we=>be(Ae.id,{tailAnchor:{...P,x:parseFloat(we.target.value)||0}}),className:"w-14 px-1 py-0.5 text-[10px] border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-tail-x"})]}),d.jsxs("label",{className:"flex items-center gap-1 text-[10px] font-mono text-muted",children:["y",d.jsx("input",{type:"number",step:"0.1",value:P.y,onChange:we=>be(Ae.id,{tailAnchor:{...P,y:parseFloat(we.target.value)||0}}),className:"w-14 px-1 py-0.5 text-[10px] border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-tail-y"})]})]})]})})(),Ae.type!=="sfx"&&d.jsxs("div",{className:"space-y-1.5 rounded border border-border/70 p-2","data-testid":"inspector-bubble-style",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Bubble controls"}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Padding X (% width)"}),d.jsx("input",{type:"number",step:"1",min:"0",max:"25",value:((((At=Ae.bubbleStyle)==null?void 0:At.paddingX)??.06)*100).toFixed(0),onChange:P=>be(Ae.id,{bubbleStyle:{...Ae.bubbleStyle,paddingX:Math.max(0,Math.min(.25,(parseFloat(P.target.value)||6)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-padding-x"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Padding Y (% height)"}),d.jsx("input",{type:"number",step:"1",min:"0",max:"25",value:((((Ze=Ae.bubbleStyle)==null?void 0:Ze.paddingY)??.08)*100).toFixed(0),onChange:P=>be(Ae.id,{bubbleStyle:{...Ae.bubbleStyle,paddingY:Math.max(0,Math.min(.25,(parseFloat(P.target.value)||8)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-padding-y"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] text-muted",children:"Corner roundness (% short side)"}),d.jsx("input",{type:"number",step:"1",min:"0",max:"49",value:((((hi=Ae.bubbleStyle)==null?void 0:hi.cornerRadius)??.4)*100).toFixed(0),onChange:P=>be(Ae.id,{bubbleStyle:{...Ae.bubbleStyle,cornerRadius:Math.max(0,Math.min(.49,(parseFloat(P.target.value)||40)/100))}}),className:"w-full px-2 py-1 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"inspector-corner-radius"})]})]}),d.jsxs("div",{className:"text-[10px] text-muted","data-testid":"inspector-font",children:["Font:"," ",Ae.type==="sfx"?v.family:b.family]}),d.jsxs("div",{className:"text-[10px] font-mono text-muted space-y-0.5",children:[d.jsxs("p",{children:["x: ",Ae.x.toFixed(3),", y:"," ",Ae.y.toFixed(3)]}),d.jsxs("p",{children:["w: ",Ae.width.toFixed(3),", h:"," ",Ae.height.toFixed(3)]})]}),d.jsx("button",{onClick:()=>{A?St(Ae.id):O(!0)},className:"w-full px-2 py-1 text-xs text-error border border-error/30 rounded hover:bg-error/5","data-testid":"delete-overlay",children:A?"Click again to delete":"Delete"})]}):d.jsx("p",{className:"text-xs text-muted","data-testid":"inspector-empty",children:"Select an overlay to inspect."})]})]})]})}const ED={wide:"Wide",medium:"Medium","close-up":"Close-up","extreme-close-up":"Extreme close-up"},ND="No speech bubbles, captions, sound effects, narration, or any text or lettering in the image.",jD="Style lock — illustrated comic/webtoon panel art: clean black contour/ink lines, flat or cel shading, simplified but realistic (semi-realistic) anatomy and faces, backgrounds drawn as illustrated comic panels. Hold this same style on every cut for character and panel consistency. Hard negatives — NOT photorealistic, NOT a photograph, NOT a glossy or painterly digital painting, NOT concept art, NOT a 3D/CGI render, NOT airbrushed, no photoreal textures.";function TD(e){var a;const t=ED[e.shotType]??e.shotType,i=((a=e.description)==null?void 0:a.trim())||`Cut ${e.id}`,s=[`${t} shot. ${i}`];return e.characters.length>0&&s.push(`Characters: ${e.characters.join(", ")}.`),s.push(jD),s.push(ND),s.join(`
`).trim()}function AD(e,t){return`assets/${e}/cut-${String(t).padStart(2,"0")}-clean.webp`}function dy(e,t){const i=AD(t,e.id);return[`Generate the clean image for cut ${e.id}.`,"","Image description:",TD(e),"","How to hand it off:","- Produce the actual image — do not just describe it or return a prompt.",`- If your image tool can write a WebP or JPEG under 1MB, save it at ${i} and run "Sync clean images".`,'- If it only produces a PNG (e.g. built-in image generation saves to ~/.codex/generated_images), that is fine — do NOT convert or rename it yourself. Leave it there and import it into this cut with the OWS "Import from Codex" button, which converts the PNG automatically.',"- Clean image only: no text, speech bubbles, captions, sound effects, signage, watermark, or signature.","- Hold the style lock above — an illustrated comic/webtoon panel, NOT a photoreal photo, painterly concept art, or 3D render. If a result reads photorealistic, regenerate it as illustrated panel art.","- Do not letter or upload anything — final lettering and upload happen later in OWS."].join(`
-`)}const YS=12e3,RD=5,DD=6e4,MD=6e4,BD=5;function LD(e,t){return e===429?!0:!!t&&/rate[\s-]?limit/i.test(t)}function OD(e,t=YS){return Math.min(t*2**e,DD)}const KS=e=>new Promise(t=>setTimeout(t,e));async function zD(e,t={}){var c;const i=t.sleep??KS,s=t.maxRetries??RD,a=t.baseDelayMs??YS;let o=0;for(;;){const h=await e();if(h.ok||!LD(h.status,h.errorMessage)||o>=s)return h;const p=OD(o,a);o+=1,(c=t.onWaiting)==null||c.call(t,{attempt:o,maxRetries:s,waitMs:p}),await i(p)}}function PD(e={}){const t=e.limit??BD,i=e.windowMs??MD,s=e.sleep??KS,a=e.now??(()=>Date.now()),o=[],c=()=>{const h=a()-i;for(;o.length&&o[0]<=h;)o.shift()};return async function(){var p;if(c(),o.length>=t){const f=o[0]+i-a();f>0&&((p=e.onWaiting)==null||p.call(e,{waitMs:f}),await s(f)),c()}o.push(a())}}const zp=1024*1024;function fy(e,t,i){return new Promise((s,a)=>{e.toBlob(o=>o?s(o):a(new Error(`Failed to export as ${t}`)),t,i)})}async function ID(e){const t=[.9,.8,.7,.6];for(const s of t)try{const a=await fy(e,"image/webp",s);if(a.type!=="image/webp")break;if(a.size<=zp)return a}catch{break}const i=[.85,.7,.5];for(const s of i){const a=await fy(e,"image/jpeg",s);if(a.size<=zp)return a}throw new Error("Cannot compress image under 1MB — reduce overlay count or image size")}const HD=["image/webp","image/jpeg"];function VS(e){return HD.includes(e.type)&&e.size<=zp}async function UD(e){var i;if(typeof createImageBitmap!="function")throw new Error("This browser cannot decode the image for import");let t;try{t=await createImageBitmap(e)}catch{throw new Error("Could not read the selected image — pick a PNG, WebP, or JPEG file")}try{const s=document.createElement("canvas");s.width=t.width,s.height=t.height;const a=s.getContext("2d");if(!a)throw new Error("Could not process the image for import");return a.drawImage(t,0,0),s}finally{(i=t.close)==null||i.call(t)}}async function Ku(e){if(VS(e))return e;const t=await UD(e);return ID(t)}function $D(e){if(!e||typeof e!="object")return!1;const t=e;return typeof t.token=="string"&&t.token.length>0&&typeof t.name=="string"&&typeof t.size=="number"&&typeof t.mtimeMs=="number"}async function FD(e){let t;try{t=await e("/api/codex/images")}catch{return[]}if(!t.ok)return[];let i;try{i=await t.json()}catch{return[]}const s=i==null?void 0:i.images;return Array.isArray(s)?s.filter($D):[]}async function qD(e,t){let i;try{i=await e(`/api/codex/images/${encodeURIComponent(t.token)}`)}catch{throw new Error("Could not read the generated image from the Codex cache")}if(!i.ok)throw new Error("Could not read the generated image from the Codex cache");const s=await i.blob(),a=s.type||i.headers.get("Content-Type")||"image/png";return new File([s],t.name||"codex-image.png",{type:a})}function WD(e,t){const[i,s]=w.useState(null);return w.useEffect(()=>{let a=null,o=!1;return(async()=>{try{const c=await t(e);if(!c.ok)return;const h=await c.blob();if(o)return;a=URL.createObjectURL(h),s(a)}catch{}})(),()=>{o=!0,a&&URL.revokeObjectURL(a)}},[e,t]),i}function GD(e){return e>=1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:e>=1024?`${Math.round(e/1024)} KB`:`${e} B`}function YD(e,t){const i=t-e;if(!Number.isFinite(i)||i<45e3)return"just now";const s=Math.round(i/6e4);if(s<60)return`${s}m ago`;const a=Math.round(i/36e5);if(a<24)return`${a}h ago`;const o=Math.round(i/864e5);return o<7?`${o}d ago`:`${Math.round(i/(7*864e5))}w ago`}function KD({image:e,authFetch:t}){const i=WD(`/api/codex/images/${encodeURIComponent(e.token)}`,t);return i?d.jsx("img",{src:i,alt:e.name,className:"w-16 h-16 flex-shrink-0 rounded border border-border object-cover bg-white"}):d.jsx("div",{className:"w-16 h-16 flex-shrink-0 rounded border border-border bg-surface"})}function VD({authFetch:e,cutId:t,onImport:i,onClose:s}){const[a,o]=w.useState(null),[c,h]=w.useState(null),[p,f]=w.useState(null),[_,x]=w.useState("");w.useEffect(()=>{let E=!1;return(async()=>{const N=await FD(e);E||o(N)})(),()=>{E=!0}},[e]);const b=_.trim().toLowerCase(),v=w.useMemo(()=>a?b?a.filter(E=>E.name.toLowerCase().includes(b)):a:[],[a,b]),S=Date.now(),j=async E=>{h(null),f(E.token);try{const N=await qD(e,E);await i(N)}catch(N){h(N instanceof Error?N.message:"Could not import the generated image")}finally{f(null)}},R=a!==null&&a.length>0;return d.jsxs("div",{className:"rounded border border-border bg-surface/60 p-2 space-y-2","data-testid":`codex-picker-${t}`,children:[d.jsxs("div",{className:"flex items-center justify-between",children:[d.jsx("p",{className:"text-[11px] font-medium text-foreground",children:"Import a Codex-generated image"}),d.jsx("button",{onClick:s,"data-testid":`codex-picker-close-${t}`,className:"text-[11px] text-muted hover:text-foreground",children:"Close"})]}),R&&d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("input",{type:"search",value:_,onChange:E=>x(E.target.value),placeholder:"Filter by file name…","data-testid":`codex-picker-search-${t}`,className:"min-w-0 flex-1 px-2 py-1 text-[11px] border border-border rounded bg-transparent focus:border-accent focus:outline-none"}),d.jsx("span",{className:"text-[10px] text-muted whitespace-nowrap","data-testid":`codex-picker-count-${t}`,children:b?`${v.length} of ${a.length}`:`${a.length} image${a.length===1?"":"s"}`})]}),a===null&&d.jsx("p",{className:"text-[11px] text-muted","data-testid":`codex-picker-loading-${t}`,children:"Looking for generated images…"}),a!==null&&a.length===0&&d.jsx("p",{className:"text-[11px] text-muted","data-testid":`codex-picker-empty-${t}`,children:"No generated images found in the Codex cache yet. Generate art in Codex, then reopen this list — or use “Upload clean image” to pick a file."}),R&&v.length===0&&d.jsxs("p",{className:"text-[11px] text-muted","data-testid":`codex-picker-no-match-${t}`,children:["No generated images match “",_.trim(),"”."]}),R&&v.length>0&&d.jsx("ul",{className:"space-y-1 max-h-72 overflow-y-auto",children:v.map(E=>d.jsxs("li",{"data-testid":`codex-image-${E.token}`,className:"flex items-center gap-2 rounded border border-border bg-background/40 p-1.5",children:[d.jsx(KD,{image:E,authFetch:e}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsxs("p",{className:"text-[11px] text-foreground",children:[YD(E.mtimeMs,S)," · ",GD(E.size)]}),d.jsx("p",{className:"truncate text-[10px] font-mono text-muted",title:E.name,children:E.name})]}),d.jsx("button",{onClick:()=>j(E),disabled:p!==null,"data-testid":`codex-import-${E.token}`,className:"px-2 py-1 text-[11px] border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50",children:p===E.token?"Importing…":"Import to this cut"})]},E.token))}),c&&d.jsx("p",{className:"text-[11px] text-error",children:c})]})}const XD={done:"✓",current:"▸",todo:"○"};function ZD({checklist:e,issues:t,onFinish:i,finishing:s,progressText:a,canFinish:o,markdownReady:c=!1,published:h=!1}){var E;if(!e||e.steps.length===0)return null;const p=GS(t),f=((E=e.steps.find(N=>N.key==="upload"))==null?void 0:E.status)==="done",_=f&&c&&!h,x=h||c?"done":f?"current":"todo",b=h?"done":_?"current":"todo",v=[...e.steps.filter(N=>N.key!=="publish"),{key:"assemble",label:"Episode sequence prepared",status:x,detail:null},{key:"ready",label:h?"Published to PlotLink":"Ready to publish",status:b,detail:null}],S=s?a||"Finishing…":h?"Published ✓":_?"Episode ready to publish":"Finish episode",j=v.filter(N=>N.status!=="done").length,R=p.reduce((N,I)=>N+I.lines.length,0);return d.jsxs("div",{className:"px-3 py-1.5 border-b border-border bg-surface/50 flex-shrink-0","data-testid":"finish-episode-panel",children:[d.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[d.jsx("span",{className:"text-[11px] font-medium text-foreground",children:"Finish episode"}),e.nextStep&&d.jsxs("span",{className:"min-w-0 flex-1 text-[10px] text-muted truncate","data-testid":"finish-next-step",children:["Next: ",e.nextStep]}),d.jsx("button",{onClick:i,disabled:s||!o,"data-testid":"finish-episode-btn",title:"Upload the exported final panels, then prepare the episode for publishing — picks up where it left off",className:"px-2.5 py-0.5 text-[11px] border border-accent/40 text-accent rounded hover:bg-accent/5 disabled:opacity-50",children:S})]}),d.jsxs("details",{className:"mt-1","data-testid":"finish-episode-details",children:[d.jsxs("summary",{className:"cursor-pointer select-none text-[10px] text-muted hover:text-foreground",children:[j===0?"Progress details":`${j} step${j===1?"":"s"} left`,R>0?` · ${R} blocker${R===1?"":"s"}`:""]}),d.jsxs("div",{className:"mt-1.5 space-y-1.5",children:[d.jsx("ol",{className:"flex flex-wrap gap-1.5",children:v.map(N=>d.jsxs("li",{"data-testid":`finish-step-${N.key}`,"data-status":N.status,className:`flex items-center gap-1 rounded border px-1.5 py-0.5 text-[10px] ${N.status==="current"?"border-accent/40 bg-accent/10 text-accent":N.status==="done"?"border-border bg-background/70 text-foreground":"border-border/70 bg-background/40 text-muted"}`,children:[d.jsx("span",{"aria-hidden":!0,children:XD[N.status]}),d.jsx("span",{children:N.label}),N.detail&&d.jsxs("span",{className:"text-muted",children:["· ",N.detail]})]},N.key))}),p.length>0&&d.jsx("div",{className:"space-y-1.5","data-testid":"finish-issues",children:p.map(N=>d.jsxs("div",{"data-testid":`finish-issue-group-${N.key}`,className:"text-[10px]",children:[d.jsx("p",{className:"font-medium text-amber-700",children:N.title}),d.jsx("ul",{className:"ml-3 list-disc text-muted",children:N.lines.map((I,te)=>d.jsx("li",{children:I},te))})]},N.key))})]})]})]})}function QD(e){return{planned:e.filter(t=>t.state==="planned").length,needsConversion:e.filter(t=>t.state==="needs-conversion").length,missing:e.filter(t=>t.state==="missing").length,cleanReady:e.filter(t=>t.state==="clean-ready").length,finalReady:e.filter(t=>t.state==="final-ready").length,uploaded:e.filter(t=>t.state==="uploaded").length}}function Ao(e){return(!!e.cleanImagePath||In(e))&&ym(e).length>0}function py(e){const t=new Date().toISOString();return{status:"generated",baseSig:ul(e),generatedAt:t,updatedAt:t}}function XS(e){return e.uploadedCid?"uploaded":e.finalImagePath||e.exportedAt?"lettered":e.cleanImagePath?"clean":In(e)?"text":"missing"}const my={muted:"text-muted",amber:"text-amber-700",green:"text-green-700",accent:"text-accent"},JD={muted:"bg-muted/40",amber:"bg-amber-500",green:"bg-green-600",accent:"bg-accent"};function eM(e,t,i){var s;return e.uploadedCid||e.uploadedUrl?{key:"uploaded",label:"Uploaded",tone:"green"}:t?{key:"convert",label:"Needs conversion",tone:"amber"}:i?e.finalImagePath?{key:"review",label:"Needs review",tone:"amber"}:{key:"needs-image",label:"Needs image",tone:"muted"}:e.finalImagePath?{key:"exported",label:"Exported",tone:"green"}:In(e)?{key:"text",label:"Ready for captions",tone:"accent"}:e.cleanImagePath?(((s=e.overlays)==null?void 0:s.length)??0)>0?{key:"review",label:"Needs review",tone:"amber"}:{key:"letter",label:"Ready for lettering",tone:"green"}:{key:"needs-image",label:"Needs image",tone:"muted"}}function tM(e){var t,i;return e.uploadedCid||e.uploadedUrl?{label:"Complete",detail:"Final image uploaded",tone:"green"}:e.finalImagePath||e.exportedAt?{label:"Exported",detail:"Ready to upload",tone:"green"}:(((t=e.overlays)==null?void 0:t.length)??0)>0?((i=e.aiDraft)==null?void 0:i.status)==="generated"?{label:"Draft ready",detail:`${e.overlays.length} AI-drafted overlay${e.overlays.length===1?"":"s"} ready to review`,tone:"amber"}:{label:"User-edited",detail:`${e.overlays.length} overlay${e.overlays.length===1?"":"s"} adjusted and ready to review`,tone:"amber"}:Ao(e)?{label:"No draft",detail:"Draft with AI or place bubbles manually",tone:"muted"}:In(e)?{label:"Between-scene card",detail:"Open to add narration or title text",tone:"accent"}:e.cleanImagePath?{label:"Unlettered",detail:"Clean art ready for bubble placement",tone:"muted"}:{label:"Needs artwork",detail:"Add or sync clean art first",tone:"muted"}}function iM({cut:e,storyName:t,plotFile:i,expanded:s,onToggle:a,authFetch:o,onUpdated:c,onOpenEditor:h,detectedLocalClean:p,onSyncClean:f,syncing:_,onAiDraft:x,aiDrafting:b,staleMessages:v,onRepairStale:S,repairing:j,conversionPng:R,onConvert:E,converting:N,rowRef:I}){var Be,Le;const te=w.useRef(null),[F,D]=w.useState(!1),[ie,fe]=w.useState(null),[Se,H]=w.useState(!1),[ce,W]=w.useState(!1),[K,X]=w.useState(!1),[U,A]=w.useState(!1),O=XS(e),$=v.length>0,xe=!!R,T=w.useCallback(async()=>{R&&(A(!0),await E(e.id,R),A(!1),c())},[R,E,e.id,c]),M=w.useCallback(async je=>{D(!0),fe(null);try{let be=je;if(!VS(je))try{be=await Ku(je)}catch(We){return fe(We instanceof Error?We.message:"Could not import image"),!1}const tt=be.type==="image/jpeg"?"jpg":"webp",St=new FormData;St.append("file",new File([be],`clean.${tt}`,{type:be.type}));const ot=await o(`/api/stories/${t}/cuts/${i}/upload-clean/${e.id}`,{method:"POST",body:St});if(!ot.ok){const We=await ot.json();return fe(We.error||"Upload failed"),!1}return c(),!0}catch{return fe("Upload failed"),!1}finally{D(!1)}},[o,t,i,e.id,c]),G=eM(e,xe,$),C=e.cleanImagePath??R??null,V=((Be=e.overlays)==null?void 0:Be.length)??0,ne=!In(e)&&!!e.cleanImagePath&&!e.finalImagePath&&!e.uploadedCid&&!e.uploadedUrl&&!$&&!xe,ae=!$&&!xe&&!e.finalImagePath&&!e.uploadedCid&&!e.uploadedUrl&&Ao(e),Y=(((Le=e.overlays)==null?void 0:Le.length)??0)>0?"Re-draft with AI":"AI draft lettering",he=G.key==="convert"?{label:U?"Converting…":"Convert image",onClick:T,testid:`card-convert-${e.id}`}:G.key==="review"?{label:"Review cut",onClick:h,testid:`card-review-${e.id}`}:G.key==="text"?{label:"Add captions",onClick:h,testid:`card-letter-${e.id}`}:G.key==="needs-image"?{label:"Add artwork",onClick:a,testid:`card-addart-${e.id}`}:null,_e=tM(e);return d.jsxs("div",{ref:I,"data-cut-row":e.id,className:`border rounded ${s?"border-accent/30":"border-border"}`,children:[d.jsxs("div",{className:"px-3 py-2 space-y-2","data-testid":`cut-card-${e.id}`,children:[d.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[d.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${JD[G.tone]}`}),d.jsxs("span",{className:"font-medium text-xs text-foreground",children:["Cut ",String(e.id).padStart(2,"0")]}),d.jsxs("span",{className:"font-mono text-[10px] text-muted",children:["· ",e.shotType]}),d.jsx("span",{className:`ml-auto text-[10px] font-medium flex-shrink-0 ${my[G.tone]}`,"data-testid":`cut-card-status-${e.id}`,children:G.label})]}),C?d.jsx(Bp,{storyName:t,assetPath:C,authFetch:o,alt:`Cut ${e.id} artwork`,className:"w-full max-h-[32rem] object-contain rounded border border-border bg-white"}):d.jsx("div",{className:"w-full min-h-28 rounded border border-dashed border-border bg-surface/40 flex items-center justify-center text-[10px] text-muted","data-testid":`cut-card-noart-${e.id}`,children:In(e)?"Text panel — no artwork needed":"No artwork yet"}),d.jsxs("div",{className:`rounded border border-border/70 bg-surface/50 px-2 py-1.5 text-[11px] ${my[_e.tone]}`,"data-testid":`lettering-review-state-${e.id}`,children:[d.jsx("span",{className:"font-semibold",children:_e.label}),d.jsxs("span",{className:"text-muted",children:[" · ",_e.detail]})]}),d.jsx("button",{onClick:a,"data-testid":`cut-desc-${e.id}`,className:"block w-full text-left text-[11px] text-muted hover:text-foreground",children:e.description||"No description"}),d.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[ne?d.jsxs(d.Fragment,{children:[d.jsx("button",{onClick:h,"data-testid":`add-bubbles-${e.id}`,className:"px-2.5 py-1 text-[11px] font-medium rounded bg-accent text-white hover:bg-accent-dim",children:V>0?"Review lettering":"Open focused editor"}),ae&&d.jsx("button",{onClick:x,disabled:b,"data-testid":`ai-draft-${e.id}`,className:"px-2.5 py-1 text-[11px] rounded border border-accent/40 text-accent hover:bg-accent/5 disabled:opacity-50",children:b?"Drafting…":Y})]}):he?d.jsx("button",{onClick:he.onClick,disabled:G.key==="convert"&&(U||N),"data-testid":he.testid,className:"px-2.5 py-1 text-[11px] font-medium rounded bg-accent text-white hover:bg-accent-dim disabled:opacity-50",children:he.label}):null,!ne&&!he&&ae&&d.jsx("button",{onClick:x,disabled:b,"data-testid":`ai-draft-${e.id}`,className:"px-2.5 py-1 text-[11px] rounded border border-accent/40 text-accent hover:bg-accent/5 disabled:opacity-50",children:b?"Drafting…":Y}),d.jsx("button",{onClick:a,"data-testid":`cut-details-${e.id}`,className:"px-2.5 py-1 text-[11px] rounded border border-border text-muted hover:border-accent hover:text-accent",children:s?"Hide details":"Open details"})]})]}),s&&d.jsxs("div",{className:"px-3 pb-3 space-y-3 border-t border-border",children:[xe&&d.jsxs("div",{className:"mt-2 rounded border border-amber-500/40 bg-amber-500/10 p-2 space-y-1","data-testid":`needs-conversion-${e.id}`,children:[d.jsx("p",{className:"text-[11px] text-amber-800",children:"This cut’s artwork is a PNG. Convert it to WebP so it can be lettered and published."}),d.jsx("button",{onClick:T,disabled:U||N,"data-testid":`convert-cut-${e.id}`,className:"px-2 py-1 text-[11px] border border-amber-500/50 text-amber-800 rounded hover:bg-amber-500/20 disabled:opacity-50",children:U?"Converting…":"Convert image"})]}),$&&!xe&&d.jsxs("div",{className:"mt-2 rounded border border-error/40 bg-error/5 p-2 space-y-1","data-testid":`stale-asset-${e.id}`,children:[v.map((je,be)=>d.jsx("p",{className:"text-[11px] text-error",children:je},be)),d.jsx("button",{onClick:S,disabled:j,"data-testid":`repair-stale-${e.id}`,className:"px-2 py-1 text-[11px] border border-error/40 text-error rounded hover:bg-error/10 disabled:opacity-50",children:j?"Repairing…":"Clear stale path"})]}),!In(e)&&d.jsxs("div",{className:"mt-2 space-y-2",children:[d.jsx("button",{onClick:()=>{navigator.clipboard.writeText(dy(e,i)),H(!0),setTimeout(()=>H(!1),2e3)},"data-testid":`copy-prompt-${e.id}`,className:"px-3 py-1.5 text-xs border border-border rounded hover:border-accent hover:bg-accent/5",children:Se?"Copied!":"Copy Codex task"}),d.jsx("input",{ref:te,type:"file",accept:"image/webp,image/jpeg,image/png",className:"hidden",onChange:je=>{var tt;const be=(tt=je.target.files)==null?void 0:tt[0];be&&M(be),je.target.value=""}}),d.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[d.jsx("button",{onClick:()=>{var je;return(je=te.current)==null?void 0:je.click()},disabled:F,className:"px-3 py-1.5 text-xs border border-border rounded hover:border-accent hover:bg-accent/5 disabled:opacity-50",children:F?"Uploading...":e.cleanImagePath?"Replace clean image":"Upload clean image"}),d.jsx("button",{onClick:()=>X(je=>!je),disabled:F,"data-testid":`import-codex-${e.id}`,className:"px-3 py-1.5 text-xs border border-border rounded hover:border-accent hover:bg-accent/5 disabled:opacity-50",children:K?"Hide Codex images":"Import from Codex"})]}),K&&d.jsx(VD,{authFetch:o,cutId:e.id,onImport:async je=>{await M(je)&&X(!1)},onClose:()=>X(!1)}),!e.cleanImagePath&&d.jsx("p",{className:"text-xs text-muted","data-testid":`clean-image-handoff-${e.id}`,children:"Generate this cut in Codex, then import the cached PNG with “Import from Codex” — or upload an image manually. Letter it next."}),O==="missing"&&d.jsxs("div",{className:"rounded border border-border bg-surface/60 p-2 space-y-1","data-testid":`ask-codex-${e.id}`,children:[d.jsx("p",{className:"text-[11px] font-medium text-foreground",children:"Generate this cut in Codex"}),d.jsxs("p",{className:"text-[10px] text-muted",children:["Copy the task below and paste it into Codex. Codex usually saves a PNG to its image cache — bring it into this cut with “Import from Codex” above (the PNG becomes a WebP automatically). If Codex instead writes a WebP/JPEG at"," ",d.jsxs("span",{className:"font-mono",children:["assets/",i,"/cut-",String(e.id).padStart(2,"0"),"-clean.webp"]}),", it’s picked up by “Sync clean images”."]}),d.jsx("button",{onClick:()=>{navigator.clipboard.writeText(dy(e,i)),W(!0),setTimeout(()=>W(!1),2e3)},"data-testid":`ask-codex-copy-${e.id}`,className:"px-2 py-1 text-[11px] border border-border rounded hover:border-accent hover:bg-accent/5",children:ce?"Copied!":"Copy Codex task"})]}),O==="missing"&&p&&d.jsx("button",{onClick:f,disabled:_,"data-testid":`found-local-clean-${e.id}`,className:"px-3 py-1.5 text-xs border border-green-700/40 text-green-700 rounded hover:bg-green-700/5 disabled:opacity-50",children:_?"Syncing...":"Found local clean image — sync to cut plan"}),ie&&d.jsx("p",{className:"text-xs text-error mt-1",children:ie})]}),(e.cleanImagePath||e.narration||e.dialogue.length>0||In(e))&&d.jsx("button",{onClick:h,"data-testid":`open-editor-${e.id}`,className:"px-3 py-1.5 text-xs border border-accent/30 text-accent rounded hover:bg-accent/5",children:"Open editor"}),e.characters.length>0&&d.jsxs("p",{className:"text-xs text-muted",children:["Characters: ",e.characters.join(", ")]}),e.dialogue.length>0&&d.jsx("div",{className:"text-xs text-muted",children:e.dialogue.map((je,be)=>d.jsxs("p",{children:[d.jsxs("span",{className:"font-medium",children:[je.speaker,":"]})," ",je.text]},be))}),e.narration&&d.jsx("p",{className:"text-xs text-muted italic",children:e.narration})]})]})}function gy({storyName:e,fileName:t,authFetch:i,language:s,uploadRetry:a,onCutsChanged:o,focusRequest:c,onFocusHandled:h,onFocusedLetteringModeChange:p,workspaceVisible:f=!1,onWorkspaceVisibleChange:_}){var pr,Lt,le;const[x,b]=w.useState(null),v=w.useRef(o);v.current=o;const S=w.useRef(h);S.current=h;const[j,R]=w.useState(!0),[E,N]=w.useState(null),[I,te]=w.useState(null),[F,D]=w.useState(null),[ie,fe]=w.useState(!1),[Se,H]=w.useState([]),[ce,W]=w.useState(!1),[K,X]=w.useState(""),[U,A]=w.useState({markdownReady:!1,published:!1}),[O,$]=w.useState(!1),[xe,T]=w.useState(!1),[M,G]=w.useState(!1),[C,V]=w.useState(null),[ne,ae]=w.useState(null),[Y,he]=w.useState(null),[_e,Be]=w.useState(!1),[Le,je]=w.useState(new Set),[be,tt]=w.useState(new Map),[St,ot]=w.useState(!1),[We,Mt]=w.useState(null),[He,xt]=w.useState(!1),[Ae,Kt]=w.useState(null),mi=w.useRef(new Map),wt=w.useRef(null),Qe=t.replace(/\.md$/,"");w.useEffect(()=>{var L;c&&wt.current!==c.seq&&(wt.current=c.seq,c.openEditor?D(c.cutId):(te(c.cutId),Kt(c.cutId)),(L=S.current)==null||L.call(S))},[c]),w.useEffect(()=>(p==null||p(F!==null),()=>p==null?void 0:p(!1)),[F,p]),w.useEffect(()=>{var oe;if(Ae==null)return;const L=mi.current.get(Ae);L&&((oe=L.scrollIntoView)==null||oe.call(L,{behavior:"smooth",block:"center"}),Kt(null))},[Ae,x]);const Q=w.useCallback(async()=>{var L;try{const oe=await i(`/api/stories/${e}/cuts/${Qe}`);if(oe.status===404){b(null);return}if(!oe.ok){const Me=await oe.json();N(Me.error||"Failed to load cuts");return}const Ee=await oe.json();b(Ee),N(null);try{const Me=await i(`/api/stories/${e}/${t}`);if(Me.ok){const Ne=await Me.json(),Pe=typeof(Ne==null?void 0:Ne.content)=="string"?Ne.content:"",qe=Array.isArray(Ee==null?void 0:Ee.cuts)?Ee.cuts:[],nt=Pe.length>0&&qS(Pe,qe).ready,Ve=(Ne==null?void 0:Ne.status)==="published"||(Ne==null?void 0:Ne.status)==="published-not-indexed";A({markdownReady:nt,published:Ve})}else A({markdownReady:!1,published:!1})}catch{A({markdownReady:!1,published:!1})}(L=v.current)==null||L.call(v)}catch{N("Failed to load cuts")}finally{R(!1)}},[i,e,Qe,t]),ge=w.useCallback(async L=>!!(await i(`/api/stories/${e}/cuts/${Qe}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(L)})).ok,[i,e,Qe]),Te=w.useCallback(async()=>{ot(!1);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/detect-clean-images`);if(!L.ok)return;const oe=await L.json();je(new Set(Array.isArray(oe.detected)?oe.detected:[]));const Ee=new Map,Me=oe.stale;if(Array.isArray(Me))for(const Ne of Me){if(typeof(Ne==null?void 0:Ne.cutId)!="number"||typeof(Ne==null?void 0:Ne.message)!="string")continue;const Pe=Ee.get(Ne.cutId)??[];Pe.push(Ne.message),Ee.set(Ne.cutId,Pe)}tt(Ee),ot(!0)}catch{}},[i,e,Qe]),Ue=w.useCallback(async()=>{Mt(null);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/asset-diagnostics`);if(!L.ok)return;const oe=await L.json();Mt(Array.isArray(oe.diagnostics)?oe.diagnostics:null)}catch{}},[i,e,Qe]),it=w.useCallback(async()=>{xt(!0);try{await Promise.all([Q(),Te(),Ue()])}finally{xt(!1)}},[Q,Te,Ue]),Wt=w.useCallback(async(L,oe={})=>{var Ne;if(!x)return!1;const Ee=x.cuts.find(Pe=>Pe.id===L);if(!Ee||!Ao(Ee)||(((Ne=Ee.overlays)==null?void 0:Ne.length)??0)>0&&!window.confirm("This cut already has overlays. Re-drafting with AI will replace the current draft overlays for this cut. Continue?"))return!1;const Me=oy(Ee);if(Me.length===0)return ae(`Cut ${Ee.id}: no script lines available to draft.`),!1;he(L),ae(null);try{const Pe={...x,cuts:x.cuts.map(nt=>nt.id===L?{...nt,overlays:Me,aiDraft:py(Me)}:nt)};return await ge(Pe)?(ae(`Cut ${Ee.id}: AI draft ready`),await Q(),oe.openEditor&&D(L),!0):(ae(`Cut ${Ee.id}: AI draft failed`),!1)}finally{he(null)}},[x,ge,Q]),ui=w.useCallback(async()=>{if(!x)return;const L=x.cuts.filter(oe=>{var Ee;return Ao(oe)&&(((Ee=oe.overlays)==null?void 0:Ee.length)??0)===0&&!oe.finalImagePath&&!oe.uploadedCid&&!oe.uploadedUrl});if(L.length===0){ae("No unlettered cuts need an AI draft");return}Be(!0),ae(null);try{const oe={...x,cuts:x.cuts.map(Me=>{if(!L.some(Pe=>Pe.id===Me.id))return Me;const Ne=oy(Me);return Ne.length>0?{...Me,overlays:Ne,aiDraft:py(Ne)}:Me})};if(!await ge(oe)){ae("AI draft failed");return}ae(`AI draft ready for ${L.length} cut${L.length===1?"":"s"}`),await Q()}finally{Be(!1)}},[x,ge,Q]),Bt=w.useCallback(async()=>{$(!0),ae(null),H([]);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/sync-clean-images`,{method:"POST"}),oe=await L.json().catch(()=>({}));if(!L.ok)ae(oe.error||"Sync failed");else{const Ee=Array.isArray(oe.synced)?oe.synced.length:0,Me=Array.isArray(oe.cleared)?oe.cleared.length:0,Ne=Array.isArray(oe.rejected)?oe.rejected:[];Ne.length>0&&H(Ne.map(qe=>`Cut ${qe.cutId}: ${qe.reason}`));const Pe=[];Ee>0&&Pe.push(`Synced ${Ee}`),Me>0&&Pe.push(`Cleared ${Me} stale path${Me===1?"":"s"}`),ae(Pe.length>0?Pe.join(", "):"No new clean images"),await Q(),await Te(),await Ue()}}catch{ae("Sync failed")}$(!1)},[i,e,Qe,Q,Te,Ue]),vt=w.useCallback(async(L,oe)=>{try{const Ee=await i(OS(e,oe));if(!Ee.ok)return!1;const Me=await Ee.blob(),Ne=await Ku(new File([Me],"clean.png",{type:Me.type||"image/png"})),Pe=Ne.type==="image/jpeg"?"jpg":"webp",qe=new FormData;return qe.append("file",new File([Ne],`clean.${Pe}`,{type:Ne.type})),(await i(`/api/stories/${e}/cuts/${Qe}/upload-clean/${L}`,{method:"POST",body:qe})).ok}catch{return!1}},[i,e,Qe]),At=w.useCallback(async L=>{G(!0),V(null);let oe=0;const Ee=[];for(const Me of L)await vt(Me.cutId,Me.pngPath)?oe++:Ee.push(Me.cutId);await it(),G(!1),V(Ee.length===0?`Converted ${oe} image${oe===1?"":"s"} to WebP`:`Converted ${oe}; ${Ee.length} failed (Cut ${Ee.join(", ")}) — try Convert image on each`)},[vt,it]),Ze=w.useCallback(async()=>{var Ne;if(!x)return;W(!0),X(""),H([]);const L=x.cuts.filter(Pe=>Pe.finalImagePath&&!Pe.uploadedCid),oe=[],Ee=PD({sleep:a==null?void 0:a.sleep,onWaiting:({waitMs:Pe})=>X(`Upload limit reached — waiting ${Math.round(Pe/1e3)}s before continuing…`)});for(let Pe=0;Pe{const Jt=await i("/api/publish/upload-plot-image",{method:"POST",body:Nt});if(Jt.ok){const{cid:$n,url:gr}=await Jt.json();return{ok:!0,status:Jt.status,cid:$n,url:gr}}const qi=await Jt.json().catch(()=>({}));return{ok:!1,status:Jt.status,errorMessage:qi.error}},{...a,onWaiting:({attempt:Jt,maxRetries:qi,waitMs:$n})=>X(`Cut ${qe.id} rate-limited — waiting ${Math.round($n/1e3)}s before retry ${Jt}/${qi}...`)});if(!Gt.ok){oe.push(`Cut ${qe.id}: upload failed — ${Gt.errorMessage||"unknown"}`);continue}const{cid:Rt,url:ki}=Gt;(await i(`/api/stories/${e}/cuts/${Qe}/set-uploaded/${qe.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cid:Rt,url:ki})})).ok||oe.push(`Cut ${qe.id}: failed to record upload`)}catch(nt){oe.push(`Cut ${qe.id}: ${nt instanceof Error?nt.message:"failed"}`)}}if(oe.length>0){H(oe),W(!1),X(""),Q();return}X("Preparing episode for publishing…");const Me=await i(`/api/stories/${e}/cuts/${Qe}/generate-markdown`,{method:"POST"});if(Me.ok){const Pe=await Me.json();((Ne=Pe.warnings)==null?void 0:Ne.length)>0&&H(Pe.warnings)}W(!1),X(""),Q()},[x,i,e,Qe,a,Q]),hi=w.useCallback(async()=>{T(!0),ae(null);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/repair-asset-paths`,{method:"POST"}),oe=await L.json().catch(()=>({}));if(!L.ok)ae(oe.error||"Repair failed");else{const Ee=Array.isArray(oe.cleared)?oe.cleared.length:0;ae(Ee>0?`Cleared ${Ee} stale path${Ee===1?"":"s"}`:"No stale paths to clear"),await Q(),await Te()}}catch{ae("Repair failed")}T(!1)},[i,e,Qe,Q,Te]),[P,we]=w.useState(!1),ze=w.useCallback(async(L,oe=!0)=>{if(x){we(!0);try{const Ee=x.cuts.reduce((nt,Ve)=>Math.max(nt,Ve.id),0)+1,Me={id:Ee,shotType:"wide",description:"Text panel",characters:[],dialogue:[],narration:"",sfx:"",cleanImagePath:null,finalImagePath:null,exportedAt:null,uploadedCid:null,uploadedUrl:null,overlays:[],kind:"text",background:"#101820",aspectRatio:"4:5"},Ne=[...x.cuts];Ne.splice(Math.max(0,Math.min(L,Ne.length)),0,Me);const Pe={...x,cuts:Ne},qe=await i(`/api/stories/${e}/cuts/${Qe}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(Pe)});if(qe.ok)oe?D(Ee):te(Ee),await Q();else{const nt=await qe.json().catch(()=>({}));ae(nt.error||"Could not add text panel")}}catch{ae("Could not add text panel")}we(!1)}},[x,i,e,Qe,Q]),Re=w.useCallback(()=>ze((x==null?void 0:x.cuts.length)??0,!0),[ze,x]);if(w.useEffect(()=>{Q(),Te(),Ue()},[Q,Te,Ue]),j)return d.jsx("div",{className:"p-4 text-sm text-muted",children:"Loading cuts..."});if(E)return d.jsxs("div",{className:"p-4 space-y-2","data-testid":"cuts-error",children:[d.jsx("p",{className:"text-sm text-error font-medium",children:"Invalid cuts file"}),d.jsx("p",{className:"text-xs text-error",children:E}),d.jsxs("p",{className:"text-xs text-muted",children:[Qe,".cuts.json must follow the OWS v1 schema. Ask Claude to regenerate it using the v1 cuts schema from the cartoon writing instructions."]}),d.jsx("button",{onClick:Q,className:"text-xs text-accent hover:text-accent-dim",children:"Retry"})]});if(!x||x.cuts.length===0)return d.jsxs("div",{className:"p-4 text-center space-y-1",children:[d.jsx("p",{className:"text-sm text-muted",children:"No cuts yet"}),d.jsx("p",{className:"text-xs text-muted",children:"Ask Claude to create a cut plan for this episode."})]});const Ge=F!==null?x.cuts.find(L=>L.id===F):null;if(Ge)return d.jsx(kD,{storyName:e,cut:Ge,plotFile:Qe,language:s,authFetch:i,targetLabel:In(Ge)?`Between-scene card ${Ge.id}`:`Cut ${String(Ge.id).padStart(2,"0")}`,returnOnSave:!0,workspaceVisible:f,onToggleWorkspaceVisible:_?()=>_(!f):void 0,onSave:async(L,oe)=>{const Ee={...x,cuts:x.cuts.map(Ne=>Ne.id===F?{...Ne,overlays:L,aiDraft:oe??Ne.aiDraft??null}:Ne)};if(!await ge(Ee))throw new Error("Failed to save overlays")},onExported:()=>Q(),onClose:()=>{D(null),Q()}});const $e=x.cuts.reduce((L,oe)=>{const Ee=XS(oe);return L[Ee]++,L},{missing:0,clean:0,lettered:0,uploaded:0,text:0}),ht=x.cuts.filter(L=>!In(L)).length,dt=x.cuts.filter(L=>$S(L)).map(L=>L.id),lt=sD({cuts:x.cuts,published:U.published}),Vt=((pr=lt.steps.find(L=>L.key==="upload"))==null?void 0:pr.status)==="done",Ci=x.cuts.some(L=>L.finalImagePath&&!L.uploadedCid)||Vt&&!U.markdownReady,ft=(We??[]).filter(L=>L.state==="needs-conversion"&&L.convertiblePng).map(L=>({cutId:L.cutId,pngPath:L.convertiblePng})),Fi=new Map(ft.map(L=>[L.cutId,L.pngPath])),En=(We??[]).filter(L=>L.state==="needs-conversion"&&L.issue).map(L=>L.issue),ln=t==="genesis.md"?"Genesis / Episode 1":`Episode ${parseInt(((Lt=Qe.match(/\d+/))==null?void 0:Lt[0])??"0",10)+1}`,Un=typeof x.title=="string"?x.title:null,on=x.cuts.filter(L=>!In(L)),gn={cuts:x.cuts.length,artwork:on.filter(L=>L.cleanImagePath||Fi.has(L.id)).length,converted:on.filter(L=>L.cleanImagePath&&/\.(webp|jpe?g)$/i.test(L.cleanImagePath)).length,lettered:x.cuts.filter(L=>{var oe;return(((oe=L.overlays)==null?void 0:oe.length)??0)>0||!!L.finalImagePath}).length,uploaded:x.cuts.filter(L=>L.uploadedCid||L.uploadedUrl).length},cn=x.cuts.filter(L=>{var oe;return Ao(L)&&(((oe=L.overlays)==null?void 0:oe.length)??0)===0&&!L.finalImagePath&&!L.uploadedCid&&!L.uploadedUrl}).length;return d.jsxs("div",{className:"h-full min-h-[22rem] flex flex-col overflow-hidden","data-testid":"cut-list-panel",children:[d.jsx("div",{className:"px-3 py-2 border-b border-border flex-shrink-0","data-testid":"cut-board-header",children:d.jsxs("div",{className:"flex items-start gap-3 justify-between",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[d.jsx("span",{className:"font-serif text-foreground truncate",children:ln}),Un&&d.jsxs("span",{className:"text-muted truncate",children:["· ",Un]})]}),d.jsxs("div",{className:"mt-0.5 text-[10px] text-muted","data-testid":"cut-board-summary",children:[gn.cuts," cuts · ",gn.artwork," artwork found ·"," ",gn.converted," converted · ",gn.lettered," ","lettered · ",gn.uploaded," uploaded"]})]}),cn>0&&d.jsx("button",{onClick:ui,disabled:_e,"data-testid":"ai-draft-all-btn",className:"px-2.5 py-1 text-[11px] rounded border border-accent/40 text-accent hover:bg-accent/5 disabled:opacity-50",children:_e?"Drafting…":`AI draft all unlettered (${cn})`})]})}),d.jsxs("details",{className:"border-b border-border flex-shrink-0","data-testid":"cut-advanced",children:[d.jsx("summary",{className:"px-3 py-1.5 text-[10px] text-muted cursor-pointer hover:text-foreground",children:"Technical details"}),d.jsxs("div",{className:"px-3 py-2 flex flex-wrap items-center gap-2 text-[10px]",children:[d.jsxs("span",{className:"font-mono text-muted",children:[x.cuts.length," cuts"]}),$e.missing>0&&d.jsxs("span",{className:"text-muted",children:[$e.missing," missing"]}),$e.clean>0&&d.jsxs("span",{className:"text-green-700",children:[$e.clean," clean"]}),$e.lettered>0&&d.jsxs("span",{className:"text-amber-700",children:[$e.lettered," lettered"]}),$e.uploaded>0&&d.jsxs("span",{className:"text-green-700",children:[$e.uploaded," uploaded"]}),$e.text>0&&d.jsxs("span",{className:"text-accent",children:[$e.text," text ",$e.text===1?"panel":"panels"]}),d.jsx("button",{onClick:async()=>{fe(!0),H([]);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/generate-markdown`,{method:"POST"});if(L.ok){const oe=await L.json();H(oe.warnings||[])}}catch{}fe(!1)},disabled:ie,className:"ml-auto px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"generate-markdown-btn",title:"Build the publish-ready episode from the uploaded cut images",children:ie?"Preparing…":"Prepare episode for publish"}),d.jsx("button",{onClick:Re,disabled:P,className:"px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"add-text-panel-btn",title:"Insert a narration/title card between art panels — a solid card exported as a final image panel, no drawing needed",children:P?"Adding…":"Add narration/text panel"}),d.jsx("button",{onClick:it,disabled:He,className:"px-2 py-0.5 border border-border text-muted rounded hover:border-accent hover:text-accent disabled:opacity-50","data-testid":"refresh-assets-btn",title:"Re-check the story folder for agent-generated images and report each cut's asset state — read only, nothing is uploaded or published",children:He?"Checking…":"Refresh assets"}),d.jsx("button",{onClick:Bt,disabled:O,className:"px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"sync-clean-btn",children:O?"Syncing...":"Sync clean images"}),d.jsx("button",{onClick:Ze,disabled:ce||!(x!=null&&x.cuts.some(L=>L.finalImagePath&&!L.uploadedCid)),className:"px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"upload-generate-btn",title:"Upload each cut's final lettered image, then prepare the episode for publishing",children:K||"Upload & Prepare for Publish"})]})]}),d.jsxs("details",{className:"px-3 py-1.5 border-b border-border bg-surface/40 flex-shrink-0","data-testid":"cartoon-workflow-help",children:[d.jsx("summary",{className:"cursor-pointer select-none text-[10px] text-muted hover:text-foreground",children:"Cut workflow help"}),d.jsxs("div",{className:"mt-1.5",children:[d.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 text-[10px] text-muted",children:[d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"1. Letter"}),d.jsx("span",{"aria-hidden":!0,children:"→"}),d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"2. Export"}),d.jsx("span",{"aria-hidden":!0,children:"→"}),d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"3. Upload"}),d.jsx("span",{"aria-hidden":!0,children:"→"}),d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"4. Prepare episode for publish"})]}),d.jsxs("div",{className:"mt-1 text-[10px] text-muted",children:["Use ",d.jsx("span",{className:"text-accent",children:"Add narration/text panel"})," ","for a narration or title card. It becomes a solid card exported as a final image."]})]})]}),dt.length>0&&d.jsxs("div",{className:"px-3 py-1.5 border-b border-amber-500/40 bg-amber-500/10 text-[10px] text-amber-700 flex-shrink-0","data-testid":"stale-bubble-export-warning",children:[dt.length===1?"Cut":"Cuts"," ",dt.join(", ")," ",dt.length===1?"was":"were"," lettered with an older speech-bubble style whose tail can show a visible seam. Re-export"," ",dt.length===1?"it":"them"," (open lettering → Export) and re-upload before publishing so the bubble tails are seamless."]}),St&&ht>0&&$e.missing===0&&be.size===0&&d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-green-600/10 text-[10px] text-green-700 flex items-center gap-1 flex-shrink-0","data-testid":"clean-assets-ready",children:[d.jsx("span",{"aria-hidden":!0,children:"✓"}),d.jsxs("span",{children:["All ",ht," clean image",ht===1?"":"s"," ","present — clean-asset generation is complete. Ready for lettering in OWS."]})]}),ne&&d.jsx("div",{className:"px-3 py-1 border-b border-border text-[10px] text-muted flex-shrink-0","data-testid":"sync-result",children:ne}),ft.length>0&&d.jsxs("div",{className:"px-3 py-2 border-b border-amber-500/40 bg-amber-500/10 text-[11px] flex-shrink-0","data-testid":"convert-artwork",children:[d.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[d.jsxs("span",{className:"font-medium text-amber-700","data-testid":"convert-artwork-count",children:[ft.length," PNG image",ft.length===1?"":"s"," found"]}),d.jsx("button",{onClick:()=>At(ft),disabled:M,"data-testid":"convert-all-btn",className:"ml-auto px-2 py-0.5 border border-amber-500/50 text-amber-800 rounded hover:bg-amber-500/20 disabled:opacity-50",children:M?"Converting…":"Convert all to WebP"})]}),d.jsx("p",{className:"mt-1 text-[10px] text-muted",children:"PNG artwork is fine while drafting. Convert it before lettering/export so PlotLink can publish it safely."}),C&&d.jsx("p",{className:"mt-1 text-[10px] text-muted","data-testid":"convert-result",children:C}),En.length>0&&d.jsxs("details",{className:"mt-1","data-testid":"convert-technical-details",children:[d.jsx("summary",{className:"text-[10px] text-muted cursor-pointer",children:"Technical details"}),d.jsx("ul",{className:"mt-1 ml-3 list-disc text-[10px] text-muted",children:En.map((L,oe)=>d.jsx("li",{children:L},oe))})]})]}),We&&We.length>0&&(()=>{const L=QD(We),oe=We.filter(Ee=>Ee.state==="missing");return d.jsxs("div",{className:"px-3 py-1.5 border-b border-border bg-surface/40 text-[10px] flex-shrink-0","data-testid":"asset-diagnostics",children:[d.jsxs("span",{className:"text-muted","data-testid":"asset-diag-summary",children:["Assets: ",L.uploaded," uploaded · ",L.finalReady," final ·"," ",L.cleanReady," clean · ",L.planned," planned",L.needsConversion>0?` · ${L.needsConversion} needs conversion`:"",L.missing>0?` · ${L.missing} missing`:""]}),oe.length>0&&d.jsx("ul",{className:"mt-1 ml-3 list-disc text-error","data-testid":"asset-diag-issues",children:oe.map(Ee=>d.jsx("li",{children:Ee.issue},Ee.cutId))})]})})(),d.jsx(ZD,{checklist:lt,issues:Se,onFinish:Ze,finishing:ce,progressText:K,canFinish:Ci,markdownReady:U.markdownReady,published:U.published}),d.jsxs("div",{className:"flex-1 min-h-56 overflow-y-auto p-3 space-y-3","data-testid":"lettering-review-board",children:[x.cuts.map((L,oe)=>{var Ee;return d.jsxs(w.Fragment,{children:[d.jsx(xy,{index:oe,beforeLabel:oe===0?"Episode opening":`After cut ${(Ee=x.cuts[oe-1])==null?void 0:Ee.id}`,afterLabel:`Before cut ${L.id}`,disabled:P,onAdd:()=>ze(oe)}),d.jsx(iM,{cut:L,storyName:e,plotFile:Qe,expanded:I===L.id,onToggle:()=>te(I===L.id?null:L.id),authFetch:i,onUpdated:()=>{Q(),Te(),Ue()},onOpenEditor:()=>D(L.id),detectedLocalClean:Le.has(L.id),onSyncClean:Bt,syncing:O,onAiDraft:()=>{Wt(L.id,{openEditor:!0})},aiDrafting:Y===L.id,staleMessages:be.get(L.id)??[],onRepairStale:hi,repairing:xe,conversionPng:Fi.get(L.id)??null,onConvert:vt,converting:M,rowRef:Me=>{Me?mi.current.set(L.id,Me):mi.current.delete(L.id)}})]},L.id)}),d.jsx(xy,{index:x.cuts.length,beforeLabel:`After cut ${(le=x.cuts[x.cuts.length-1])==null?void 0:le.id}`,afterLabel:"Episode ending",disabled:P,onAdd:()=>ze(x.cuts.length)})]})]})}function xy({index:e,beforeLabel:t,afterLabel:i,disabled:s,onAdd:a}){return d.jsxs("div",{className:"rounded border border-dashed border-border bg-surface/35 px-3 py-2 text-[11px] text-muted flex items-center gap-3","data-testid":`between-scene-slot-${e}`,children:[d.jsxs("span",{className:"min-w-0 flex-1",children:[d.jsx("span",{className:"font-medium text-foreground",children:"Between-scene lettering"}),d.jsxs("span",{className:"block truncate",children:[t," · ",i]})]}),d.jsx("button",{type:"button",onClick:a,disabled:s,className:"flex-shrink-0 rounded border border-accent/40 px-2.5 py-1 text-[11px] font-medium text-accent hover:bg-accent/5 disabled:opacity-50","data-testid":`add-between-scene-${e}`,children:"Add card"})]})}function Sm({coach:e,onAction:t,className:i="",showEmptyState:s=!1}){const[a,o]=w.useState(null),c=a!==null&&a===(e==null?void 0:e.prompt);return e===void 0?null:e?d.jsx("div",{className:`m-3 rounded-lg border border-accent/40 bg-accent/10 px-4 py-3 shadow-sm ${i}`,"data-testid":"workflow-coach","data-stage":e.stageLabel,"data-action-kind":e.actionKind,"data-ui-action":e.uiAction??"",children:d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("span",{className:"inline-flex rounded-full bg-background px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.14em] text-accent","data-testid":"workflow-coach-stage",children:e.stageLabel}),d.jsxs("p",{className:"mt-1 text-sm text-foreground","data-testid":"workflow-coach-action",children:[d.jsx("span",{className:"font-semibold",children:"Next: "}),d.jsx("span",{children:e.action})]}),c&&d.jsx("p",{className:"mt-1 text-[11px] font-medium text-accent",children:"Prompt copied."})]}),e.actionKind==="agent"&&e.prompt?d.jsx("button",{onClick:()=>{var p;if(!e.prompt)return;const h=e.prompt;(p=navigator.clipboard)==null||p.writeText(h).then(()=>o(h)).catch(()=>{})},"data-testid":"workflow-coach-copy",className:"flex-shrink-0 rounded bg-accent px-4 py-2.5 text-sm font-bold text-white shadow-sm transition-colors hover:bg-accent-dim",children:"Next Action"}):e.actionKind==="ui"&&e.uiAction?d.jsx("button",{onClick:()=>t(e.uiAction,e.episodeFile),"data-testid":"workflow-coach-do",className:"flex-shrink-0 rounded bg-accent px-4 py-2.5 text-sm font-bold text-white shadow-sm transition-colors hover:bg-accent-dim",children:"Next Action"}):null]})}):s?d.jsx("div",{className:`m-3 rounded-lg border border-green-700/25 bg-green-950/5 px-4 py-3 ${i}`,"data-testid":"workflow-coach","data-state":"complete",children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx("span",{className:"rounded-full bg-green-700/10 px-2 py-1 text-[10px] font-bold uppercase tracking-[0.16em] text-green-700",children:"Complete"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-sm font-semibold text-foreground",children:"No next action available"}),d.jsx("p",{className:"mt-0.5 text-xs text-muted",children:"This workflow has no queued next step right now."})]})]})}):null}function nM({storyName:e,fileName:t,authFetch:i,refreshKey:s=0,onAction:a,showEmptyState:o=!1}){const[c,h]=w.useState(void 0),p=JSON.stringify([e,t??"",s]),[f,_]=w.useState(null);return f!==p&&(h(void 0),_(p)),w.useEffect(()=>{let x=!1;const b=t?`?focus=${encodeURIComponent(t)}`:"";return i(`/api/stories/${e}/progress${b}`).then(v=>v.ok?v.json():null).then(v=>{x||h((v==null?void 0:v.coach)??null)}).catch(()=>{}),()=>{x=!0}},[e,t,i,s]),d.jsx(Sm,{coach:c,onAction:a,showEmptyState:o})}const rM=1024*1024,sM=["image/webp","image/jpeg"],aM="Cover: WebP or JPEG, max 1MB, 600×900 portrait recommended. Use clean cover art — avoid unreadable AI text or broken lettering.";function lM(e){return e.attached?{state:"attached",label:"Cover attached to your story.",tone:"success"}:e.invalid?{state:"invalid",label:"Cover file can't be used — must be WebP or JPEG, max 1MB.",tone:"error"}:e.hasSelectedCover?{state:"selected",label:"Cover selected — it will be uploaded when you publish.",tone:"accent"}:{state:"none",label:"No cover yet — add one before publishing (recommended).",tone:"muted"}}function _y(e){return e.size>rM?"Image exceeds 1MB limit":sM.includes(e.type)?null:"Only WebP and JPEG images are accepted"}async function oM(e,t,i){const s=new FormData;s.append("file",i);const a=await e("/api/publish/upload-cover",{method:"POST",body:s});if(!a.ok)return null;const{cid:o}=await a.json();return!o||!(await e("/api/publish/update-storyline",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storylineId:t,coverCid:o})})).ok?null:o}function Pp(e){const t=e.match(/^#\s+(.+)$/m),i=t?t[1].trim():"";return i||null}function cM(e){return e.replace(/[-_]+/g," ").replace(/\s+/g," ").trim().split(" ").map(t=>t&&t[0].toUpperCase()+t.slice(1)).join(" ")}function zo(e,t){const i=(e??"").trim().toLowerCase();if(!i)return!0;if(t==="genesis.md")return i==="genesis";const s=t.match(/^(plot-\d+)\.md$/);return s?i===s[1].toLowerCase()||/^plot-\d+$/.test(i):!1}function uM(e){const t=e.match(/^plot-(\d+)\.md$/);if(!t)return null;const i=t[1];return`Episode ${i.length<2?i.padStart(2,"0"):i}`}function Ip(e){const t=(e??"").trim();return!!(!t||/^(?:episode|ep|chapter|ch|part|pt|plot)\.?\s*[-–—:#]?\s*\d+$/i.test(t)||/^\d+$/.test(t)||/^plot[-_\s]?\d+$/i.test(t))}function wm(e){var s;const t=Pp(e.fileContent);if(t)return!Ip(t);const i=((s=e.episodeTitle)==null?void 0:s.trim())||null;return!!i&&!Ip(i)}function Cm(e){const{fileName:t,fileContent:i,storySlug:s,structureContent:a,contentType:o,episodeTitle:c}=e,h=Pp(i);if(t==="genesis.md"){const p=a?Pp(a):null;return(h??p??cM(s)).slice(0,60)}if(h)return h.slice(0,60);if(o==="cartoon"){const p=c==null?void 0:c.trim(),f=uM(t);return((p||f)??t.replace(/\.md$/,"")).slice(0,60)}return t.replace(/\.md$/,"").slice(0,60)}function hM(e){return!!(e!=null&&e.txHash)&&(e==null?void 0:e.plotIndex)!=null&&e.plotIndex>0}function dM(e){return hM(e)&&(e==null?void 0:e.status)!=="published-not-indexed"}function by(e,t,i){if(e[t]==="cartoon"&&!i)return"cartoon"}function fM(e,t,i){return!(e!=="cartoon"||t||!i||i.startsWith("_new_"))}function Lf(e,t,i){if(e)return t[e]||i.get(e)||"fiction"}function Of(e){if(!e)return null;const t=Number(e);return Number.isFinite(t)?(t/1e18).toFixed(6):null}function pM(e){return!!e&&e.ready===!1}function mM(e){const t=Of(e.requiredBalance)??Of(e.creationFee),i=Of(e.ethBalance);return e.hasEnoughEth===!1&&t&&i?`Insufficient ETH: need at least ${t} ETH to publish; current balance is ${i} ETH.`+(e.address?` Top up the OWS wallet (${e.address}) and try again.`:" Top up the OWS wallet and try again."):e.error||"Publish preflight failed — the OWS wallet isn't ready to publish."}const gM={...gl,attributes:{...gl.attributes,img:["src","alt","title"]}},xM="https://ipfs.filebase.io/ipfs/";function _M(e){const t=[],i=/!\[([^\]]*)\]\(([^)]+)\)/g;let s;for(;(s=i.exec(e))!==null;)t.push({full:s[0],alt:s[1],url:s[2]});return t}function bM(e){const t=_M(e),i=[];for(const a of t)a.url.startsWith(xM)||i.push(`Non-IPFS image URL: ${a.url.length>60?a.url.slice(0,60)+"...":a.url}`);return e.match(/!\[[^\]]*\]\([^)]*$|!\[[^\]]*$(?!\])/gm)&&i.push("Malformed image markdown detected — check brackets and parentheses"),{count:t.length,warnings:i}}function vM({storyName:e,fileName:t,authFetch:i,onPublish:s,publishingFile:a,walletAddress:o,contentType:c="fiction",language:h,genre:p,isNsfw:f,hasGenesis:_=!1,onViewProgress:x,onOpenFile:b,onViewPublish:v,focusedLetteringMode:S=!1,focusedLetteringWorkspaceVisible:j=!1,onFocusedLetteringModeChange:R,onFocusedLetteringWorkspaceVisibleChange:E}){const[N,I]=w.useState(null),[te,F]=w.useState(!1),[D,ie]=w.useState("preview"),[fe,Se]=w.useState("publish"),[H,ce]=w.useState("text"),[W,K]=w.useState(null),X=w.useCallback((re,ye)=>{ie("edit"),K(ke=>({cutId:re,openEditor:ye,seq:((ke==null?void 0:ke.seq)??0)+1}))},[]),[U,A]=w.useState(""),[O,$]=w.useState(!1),[xe,T]=w.useState(!1),[M,G]=w.useState(!1),[C,V]=w.useState(null),[ne,ae]=w.useState(""),[Y,he]=w.useState(""),[_e,Be]=w.useState(!1),[Le,je]=w.useState(null),[be,tt]=w.useState(0),[St,ot]=w.useState(0),[We,Mt]=w.useState(null),[He,xt]=w.useState(null),[Ae,Kt]=w.useState(null),[mi,wt]=w.useState(0),Qe=w.useRef(null),Q=w.useRef(!1),[ge,Te]=w.useState(!1),[Ue,it]=w.useState(dl[0]),[Wt,ui]=w.useState(ts[0]),[Bt,vt]=w.useState(!1),[At,Ze]=w.useState(null),[hi,P]=w.useState(null),[we,ze]=w.useState(!1),[Re,Ge]=w.useState(!1),[$e,ht]=w.useState(!1),[dt,lt]=w.useState(null),[Vt,Ci]=w.useState(!1),ft=w.useRef(null),Fi=w.useRef(null),[En,ln]=w.useState(!1),[Un,on]=w.useState(null),[gn,cn]=w.useState(null),[pr,Lt]=w.useState("unknown"),le=w.useRef(!1),[L,oe]=w.useState(!1),[Ee,Me]=w.useState(!1),[Ne,Pe]=w.useState(null),[qe,nt]=w.useState([]),[Ve,Et]=w.useState(null),Nt=w.useRef(null),Gt=w.useRef(null),Rt=w.useCallback(async()=>{if(!e||!t){I(null);return}const re=`${e}/${t}`,ye=Gt.current!==re;ye&&(Gt.current=re);try{const ke=await i(`/api/stories/${e}/${t}`);if(ke.ok){const Je=await ke.json();I(Je),(ye||!Q.current)&&(A(Je.content??""),ye&&(T(!1),Q.current=!1))}}catch{}},[e,t,i]);w.useEffect(()=>{F(!0),Rt().finally(()=>F(!1))},[Rt]),w.useEffect(()=>{if(!e||!t||D==="edit"&&xe)return;const re=setInterval(Rt,3e3);return()=>clearInterval(re)},[e,t,Rt,D,xe]);const[ki,mr]=w.useState(null),Jt=c==="cartoon"&&t==="genesis.md";w.useEffect(()=>{if(!Jt||!e){mr(null);return}let re=!1;return i(`/api/stories/${e}/cuts/genesis`).then(ye=>ye.ok?ye.json():null).then(ye=>{re||mr(ye?Op(ye.cuts||[]):null)}).catch(()=>{re||mr(null)}),()=>{re=!0}},[Jt,e,i]);const qi=c==="cartoon"&&!!t&&/^plot-\d+\.md$/.test(t);w.useEffect(()=>{if(!qi||!e||!t){je(null),tt(0),ot(0),Mt(null);return}let re=!1;const ye=t.replace(/\.md$/,"");return Mt(null),(async()=>{try{const[ke,Je]=await Promise.all([i(`/api/stories/${e}/${t}`),i(`/api/stories/${e}/cuts/${ye}`)]);if(re)return;if(!Je.ok){je("error"),tt(0),ot(0),Mt(null);return}const Pt=await Je.json(),Ni=Pt.cuts||[],Gn=ke.ok?(await ke.json()).content??"":"",or=WS(Gn,Ni);re||(je(or.stage),tt(or.awaitingCount),ot(or.totalCuts),Mt(Op(Ni)),Kt(typeof Pt.title=="string"?Pt.title:null))}catch{re||(je("error"),tt(0),ot(0),Mt(null))}})(),()=>{re=!0}},[qi,e,t,i,N==null?void 0:N.content,N==null?void 0:N.status,mi]),w.useEffect(()=>{if(!e){xt(null);return}let re=!1;return i(`/api/stories/${e}/structure.md`).then(ye=>ye.ok?ye.json():null).then(ye=>{re||xt((ye==null?void 0:ye.content)??null)}).catch(()=>{}),()=>{re=!0}},[e,i]),w.useEffect(()=>{if(!e)return;const re=Cu(p);let ye=re??"";if(!re&&He){const Je=He.match(/\*{0,2}genre\*{0,2}[:\s]+(.+)/i);Je&&(ye=Cu(Je[1].replace(/\*+/g,"").trim())??"")}ae(ye);let ke=h&&ts.find(Je=>Je.toLowerCase()===h.toLowerCase())||"";if(!ke&&He){const Je=He.match(/\*{0,2}language\*{0,2}[:\s]+(.+)/i);Je&&(ke=ts.find(Pt=>Pt.toLowerCase()===Je[1].replace(/\*+/g,"").trim().toLowerCase())||"")}he(ke),Be(f??!1)},[e,p,h,f,He]);const $n=w.useCallback(re=>{e&&i(`/api/stories/${e}/publish-metadata`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(re)}).catch(()=>{})},[e,i]),gr=w.useCallback(async()=>{if(!(!e||!t)){$(!0);try{(await i(`/api/stories/${e}/${t}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:U})})).ok&&(T(!1),Q.current=!1,I(ye=>ye&&{...ye,content:U}))}catch{}$(!1)}},[e,t,i,U]),ei=w.useCallback(async()=>{if(!e||!t)return;const re=t.replace(/\.md$/,"");try{(await i(`/api/stories/${e}/cuts/${re}/generate-markdown`,{method:"POST"})).ok&&(await Rt(),wt(ke=>ke+1))}catch{}},[e,t,i,Rt]),Br=w.useCallback((re,ye)=>{if(re==="view-progress"){x==null||x();return}if(ye&&ye!==t){b==null||b(ye);return}switch(re){case"open-cuts":case"open-lettering":case"upload":case"refresh-assets":ie("edit"),ce("cuts");break;case"generate-markdown":ei();break;case"publish":ie("preview");break}},[t,x,b,ei]),Fn=w.useCallback(re=>{var Je;const ye=(Je=re.target.files)==null?void 0:Je[0];if(!ye)return;le.current=!0,on(null),cn(null);const ke=_y(ye);if(ke){Ze(null),P(Pt=>(Pt&&URL.revokeObjectURL(Pt),null)),ft.current&&(ft.current.value=""),lt(ke),Lt("invalid");return}Ze(ye),P(Pt=>(Pt&&URL.revokeObjectURL(Pt),URL.createObjectURL(ye))),lt(null),Lt("selected")},[]),ar=w.useCallback(async re=>{var ke;const ye=(ke=re.target.files)==null?void 0:ke[0];if(Fi.current&&(Fi.current.value=""),!(!ye||!e)){le.current=!0,on(null),ln(!0),lt(null);try{let Je;try{Je=await Ku(ye)}catch(vr){Ze(null),P(Yi=>(Yi&&URL.revokeObjectURL(Yi),null)),lt(vr instanceof Error?vr.message:"Could not import image");return}const Pt=Je.type==="image/jpeg"?"jpg":"webp",Ni=new File([Je],`cover.${Pt}`,{type:Je.type}),Gn=new FormData;Gn.append("file",Ni);const or=await i(`/api/stories/${e}/import-cover`,{method:"POST",body:Gn});if(!or.ok){const vr=await or.json().catch(()=>({}));lt(vr.error||"Cover import failed");return}Ze(Ni),P(vr=>(vr&&URL.revokeObjectURL(vr),URL.createObjectURL(Ni))),cn(null),Lt("selected"),lt(null)}catch{lt("Cover import failed")}finally{ln(!1)}}},[e,i]),Wi=w.useCallback(async re=>{if(re.size>1024*1024){Pe("Image exceeds 1MB limit");return}if(!["image/webp","image/jpeg"].includes(re.type)){Pe("Only WebP and JPEG images are accepted");return}Me(!0),Pe(null);try{const ke=new FormData;ke.append("file",re);const Je=await i("/api/publish/upload-plot-image",{method:"POST",body:ke});if(!Je.ok){const Ni=await Je.json();throw new Error(Ni.error||"Upload failed")}const Pt=await Je.json();nt(Ni=>[...Ni,{cid:Pt.cid,url:Pt.url}])}catch(ke){Pe(ke instanceof Error?ke.message:"Upload failed")}finally{Me(!1),Nt.current&&(Nt.current.value="")}},[i]),Ct=w.useCallback(re=>{var ke;const ye=(ke=re.target.files)==null?void 0:ke[0];ye&&Wi(ye)},[Wi]),qn=w.useCallback(async()=>{if(N!=null&&N.storylineId){ze(!0),lt(null),Ci(!1);try{let re;if(At){const ke=new FormData;ke.append("file",At);const Je=await i("/api/publish/upload-cover",{method:"POST",body:ke});if(!Je.ok){const Ni=await Je.json();throw new Error(Ni.error||"Cover upload failed")}re=(await Je.json()).cid}const ye=await i("/api/publish/update-storyline",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storylineId:N.storylineId,...re!==void 0&&{coverCid:re},genre:Ue,language:Wt,isNsfw:Bt})});if(!ye.ok){const ke=await ye.json();throw new Error(ke.error||"Update failed")}Ci(!0),Ze(null),re!==void 0&&(ht(!0),P(ke=>(ke&&URL.revokeObjectURL(ke),null)),Lt("unknown"),ft.current&&(ft.current.value="")),setTimeout(()=>Ci(!1),3e3)}catch(re){lt(re instanceof Error?re.message:"Update failed")}finally{ze(!1)}}},[N==null?void 0:N.storylineId,At,Ue,Wt,Bt,i]);w.useEffect(()=>{Te(!1),Ze(null),P(null),lt(null),Ci(!1),Ge(!1),oe(!1),nt([]),Pe(null),on(null),cn(null),Lt("unknown"),le.current=!1,ce("text")},[e,t]),w.useEffect(()=>{if(t!=="genesis.md"||!e||!N||N.storylineId||N.status==="published"||N.status==="published-not-indexed"||le.current)return;let re=!1;return(async()=>{try{const ye=await i(`/api/stories/${e}/cover-asset`);if(re||!ye.ok)return;const ke=await ye.json();if(re)return;if(!(ke!=null&&ke.found)){Lt("none");return}if(!ke.valid){cn(ke.error||"Detected cover asset is invalid and was not used"),Lt("invalid");return}const Je=await i(`/api/stories/${e}/asset/${ke.path.replace(/^assets\//,"")}`);if(re||!Je.ok)return;const Pt=await Je.blob(),Ni=new File([Pt],ke.path.split("/").pop()||"cover.webp",{type:ke.type});if(_y(Ni)||re||le.current)return;Ze(Ni),P(Gn=>(Gn&&URL.revokeObjectURL(Gn),URL.createObjectURL(Ni))),on(ke.path),Lt("detected")}catch{}})(),()=>{re=!0}},[e,t,N,N==null?void 0:N.status,N==null?void 0:N.storylineId,i]),w.useEffect(()=>{if(!ge||!(N!=null&&N.storylineId))return;Ge(!1);const re="https://plotlink.xyz";let ye=!1;return fetch(`${re}/api/storyline/${N.storylineId}`).then(ke=>ke.ok?ke.json():null).then(ke=>{if(!ye){if(!ke){lt("Could not load current story metadata");return}if(ke.genre){const Je=Cu(ke.genre);Je&&it(Je)}if(ke.language){const Je=ts.find(Pt=>Pt.toLowerCase()===ke.language.toLowerCase());Je&&ui(Je)}ke.isNsfw!==void 0&&vt(!!ke.isNsfw),ht(!!(ke.coverCid||ke.coverUrl||ke.cover)),Ge(!0)}}).catch(()=>{ye||lt("Could not load current story metadata")}),()=>{ye=!0}},[ge,N==null?void 0:N.storylineId]),w.useEffect(()=>{if(D!=="edit")return;const re=ye=>{(ye.metaKey||ye.ctrlKey)&&ye.key==="s"&&(ye.preventDefault(),gr())};return window.addEventListener("keydown",re),()=>window.removeEventListener("keydown",re)},[D,gr]),w.useEffect(()=>{if((N==null?void 0:N.status)!=="published-not-indexed"||!N.publishedAt)return;const re=new Date(N.publishedAt).getTime(),ye=300*1e3,ke=()=>{const Pt=Math.max(0,ye-(Date.now()-re));V(Pt)};ke();const Je=setInterval(ke,1e3);return()=>clearInterval(Je)},[N==null?void 0:N.status,N==null?void 0:N.publishedAt]);const ya=C!==null&&C<=0,Lr=C!==null&&C>0?`${Math.floor(C/6e4)}:${String(Math.floor(C%6e4/1e3)).padStart(2,"0")}`:null;if(!e||!t)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted",children:d.jsxs("div",{className:"text-center",children:[d.jsx("p",{className:"text-lg font-serif",children:"Select a file to preview"}),d.jsx("p",{className:"text-sm mt-1",children:"Click a story file in the sidebar"})]})});if(te&&!N)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted",children:"Loading..."});const xr=(D==="edit"?U:(N==null?void 0:N.content)??"").length,Ei=t==="genesis.md",gi=t?/^plot-\d+\.md$/.test(t):!1,Gi=c==="cartoon"&&gi,Nn=c==="cartoon"&&Ei,Or=Nn||Gi,jn=(N==null?void 0:N.status)==="published"||(N==null?void 0:N.status)==="published-not-indexed",Sa=S&&Or,yl=Nn?ki?ki.total:null:Gi?Le===null?null:St:null,_r=lD({fileName:t??"",contentType:c,hasGenesis:_,isPublished:jn,cutCount:yl,cutProgress:Nn?ki:null}),Go=(Nn||Gi)&&!jn,as=Go?Cm({fileName:t,fileContent:(N==null?void 0:N.content)??"",storySlug:e??"",structureContent:He,contentType:"cartoon",episodeTitle:Ae}):null,wa=!!as&&zo(as,t),Ca=Gi&&!jn&&!wm({fileContent:(N==null?void 0:N.content)??"",episodeTitle:Ae}),qs=Nn&&!jn?bm((N==null?void 0:N.content)??""):null,Yo=!!qs&&qs.blockers.length>0,ka="w-full max-w-[32rem] rounded-xl border px-3 py-3",lr={muted:"text-muted",accent:"text-accent",error:"text-error",success:"text-green-700"},Ea=re=>{if(!Nn)return null;const ye=lM({hasSelectedCover:!!At,invalid:pr==="invalid",attached:re});return d.jsxs("div",{className:"flex flex-col gap-0.5","data-testid":"cartoon-cover-status","data-state":ye.state,children:[d.jsx("span",{className:`text-[11px] font-medium ${lr[ye.tone]}`,children:ye.label}),d.jsxs("details",{className:"text-[10px] text-muted","data-testid":"cover-details",children:[d.jsx("summary",{className:"cursor-pointer select-none",children:"Cover tips"}),d.jsx("span",{className:"block mt-0.5","data-testid":"cartoon-cover-guidance",children:aM})]})]})},Ws=wa||Ca,ls=()=>{if(!Go||!as)return null;const re=Ei?"Story title":"Episode title";return d.jsxs("div",{className:"flex flex-col gap-0.5","data-testid":"publish-title-preview","data-raw":wa?"true":"false","data-blocked":Ws?"true":"false",children:[d.jsxs("span",{className:"text-[11px] text-foreground",children:[d.jsxs("span",{className:"font-medium",children:[re,":"]})," ",d.jsx("span",{className:Ws?"text-error font-medium":"text-foreground",children:as})]}),wa?d.jsxs("span",{className:"text-[10px] text-error","data-testid":"publish-title-raw-error",children:["This would publish as a raw filename."," ",Ei?"Add a real “# Title” heading to genesis.md":"Set a title in the cut plan (or add a “# Title” to the episode)"," ","before publishing."]}):Ca?d.jsxs("span",{className:"text-[10px] text-error","data-testid":"publish-title-episode-required",children:["“",as,"” is a generic placeholder, not a reader-facing title, so it can’t be published. Set a real episode title in the cut plan (or add a “# Title” to the episode) — e.g. “Episode 01 — The Couple Coupon” — before publishing."]}):null]})},os=()=>qs?d.jsxs("div",{className:"flex flex-col gap-1 rounded border border-border bg-surface/50 p-2","data-testid":"cartoon-genesis-readiness","data-blocked":Yo?"true":"false",children:[d.jsx("span",{className:"text-[11px] font-medium text-foreground",children:"Story opening (Prologue)"}),d.jsx("span",{className:"text-[10px] text-muted","data-testid":"genesis-readiness-hint",children:"Genesis is the first thing readers see. Write it as the story opening/prologue, not a synopsis — set up the premise and stakes, then bridge into Episode 01."}),qs.blockers.map((re,ye)=>d.jsx("span",{className:"text-[10px] text-error","data-testid":"genesis-readiness-blocker",children:re},`b-${ye}`)),qs.warnings.map((re,ye)=>d.jsx("span",{className:"text-[10px] text-amber-600","data-testid":"genesis-readiness-warning",children:re},`w-${ye}`))]}):null,cs=Ei||gi?1e4:null,us=!jn&&cs!==null&&xr>cs,Ko=(N==null?void 0:N.content)??"",br=jn?{count:0,warnings:[]}:bM(Ko),Wn=d.jsxs("div",{className:"flex-1 min-h-0 flex flex-col",style:{background:"var(--paper-bg)"},children:[d.jsx("textarea",{ref:Qe,value:U,onChange:re=>{A(re.target.value),T(!0),Q.current=!0},className:"flex-1 min-h-0 w-full resize-none px-4 py-3 text-sm leading-relaxed focus:outline-none",style:{fontFamily:'"Geist Mono", ui-monospace, monospace',background:"var(--paper-bg)",color:"var(--text)"},spellCheck:!1}),d.jsxs("div",{className:"px-3 py-1.5 border-t border-border flex items-center justify-between",children:[d.jsx("span",{className:"text-xs text-muted",children:xe?"Unsaved changes":"No changes"}),d.jsx("button",{onClick:gr,disabled:!xe||O,className:"px-3 py-1 bg-accent text-white text-xs rounded hover:bg-accent-dim disabled:opacity-50 disabled:cursor-not-allowed",children:O?"Saving...":"Save"})]})]});return d.jsxs("div",{className:"h-full flex flex-col",children:[!Sa&&d.jsxs("div",{className:"border-b border-border",children:[d.jsxs("div",{className:"px-3 py-1.5 flex items-center justify-between",children:[d.jsxs("div",{className:"flex items-center gap-2 text-xs font-mono text-muted",children:[x&&d.jsx("button",{onClick:x,"data-testid":"view-progress-btn",className:"text-accent hover:underline font-sans",title:"Story progress overview",children:"← Progress"}),d.jsxs("span",{children:[e,"/",t]}),(N==null?void 0:N.status)==="published"&&d.jsx("span",{className:"text-green-700 font-medium",children:"Published"}),(N==null?void 0:N.status)==="published-not-indexed"&&d.jsx("span",{className:"text-amber-700 font-medium",title:N.indexError,children:"Published (not indexed)"}),(N==null?void 0:N.status)==="pending"&&d.jsx("span",{className:"text-amber-700 font-medium",children:"Pending"})]}),d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsxs("span",{className:`text-xs font-mono ${us?"text-error font-medium":"text-muted"}`,children:[xr.toLocaleString(),cs!==null?`/${cs.toLocaleString()}`:" chars"]}),us&&d.jsxs("span",{className:"text-error text-xs font-medium",children:[(xr-cs).toLocaleString()," over limit"]})]})]}),d.jsxs("div",{className:"flex px-3 gap-1",children:[d.jsx("button",{onClick:()=>ie("preview"),className:`px-3 py-1 text-xs font-medium border-b-2 transition-colors ${D==="preview"?"border-accent text-accent":"border-transparent text-muted hover:text-foreground"}`,children:"Preview"}),d.jsxs("button",{onClick:()=>ie("edit"),className:`px-3 py-1 text-xs font-medium border-b-2 transition-colors ${D==="edit"?"border-accent text-accent":"border-transparent text-muted hover:text-foreground"}`,children:["Edit",xe&&d.jsx("span",{className:"ml-1 text-amber-600",children:"*"})]})]})]}),!Sa&&c==="cartoon"&&e&&t&&d.jsx(nM,{storyName:e,fileName:t,authFetch:i,refreshKey:mi,onAction:Br,showEmptyState:!0}),D==="preview"?Gi?d.jsxs("div",{className:"flex-1 min-h-0 flex flex-col",style:{background:"var(--paper-bg)"},children:[d.jsxs("div",{className:"flex gap-1 px-3 py-1 border-b border-border",children:[d.jsx("button",{"data-testid":"cartoon-mode-publish",onClick:()=>Se("publish"),className:`px-2 py-0.5 text-[11px] rounded ${fe==="publish"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Publish Preview"}),d.jsx("button",{"data-testid":"cartoon-mode-inspect",onClick:()=>Se("inspect"),className:`px-2 py-0.5 text-[11px] rounded ${fe==="inspect"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Cut Inspector"})]}),d.jsx("div",{className:"flex-1 min-h-0",children:fe==="publish"?d.jsx(hD,{content:(N==null?void 0:N.content)??"",stage:Le}):d.jsx(K3,{storyName:e,fileName:t,authFetch:i,onEditCut:X})})]}):d.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto px-6 py-4",style:{background:"var(--paper-bg)"},children:N!=null&&N.content?d.jsx("div",{className:"prose max-w-none",children:d.jsx(rS,{remarkPlugins:[aS,AS],rehypePlugins:[[BS,gM]],children:N.content})}):d.jsx("p",{className:"text-muted italic",children:"No content"})}):Gi?d.jsx("div",{className:"flex-1 min-h-[22rem] overflow-hidden",style:{background:"var(--paper-bg)"},children:d.jsx(gy,{storyName:e,fileName:t,authFetch:i,language:h,onCutsChanged:()=>wt(re=>re+1),focusRequest:W,onFocusHandled:()=>K(null),onFocusedLetteringModeChange:R,workspaceVisible:j,onWorkspaceVisibleChange:E})}):Nn?d.jsxs("div",{className:"flex-1 min-h-0 flex flex-col",style:{background:"var(--paper-bg)"},children:[d.jsxs("div",{className:"flex gap-1 px-3 py-1 border-b border-border",children:[d.jsx("button",{"data-testid":"genesis-edit-mode-text",onClick:()=>ce("text"),className:`px-2 py-0.5 text-[11px] rounded ${H==="text"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Opening text"}),d.jsx("button",{"data-testid":"genesis-edit-mode-cuts",onClick:()=>ce("cuts"),className:`px-2 py-0.5 text-[11px] rounded ${H==="cuts"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Cuts"})]}),d.jsx("div",{className:"flex-1 min-h-0",children:H==="cuts"?d.jsx(gy,{storyName:e,fileName:t,authFetch:i,language:h,onCutsChanged:()=>wt(re=>re+1),focusRequest:W,onFocusHandled:()=>K(null),onFocusedLetteringModeChange:R,workspaceVisible:j,onWorkspaceVisibleChange:E}):Wn})]}):Wn,!Sa&&d.jsx("div",{className:"px-3 py-2 border-t border-border flex items-center justify-between",children:t==="structure.md"?d.jsx("p",{className:"text-muted text-xs italic","data-testid":"footer-guidance",children:_r}):(N==null?void 0:N.status)==="published-not-indexed"?d.jsxs("div",{className:"flex flex-col gap-1",children:[d.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[d.jsx("span",{className:"text-amber-700",children:"Published on-chain but not indexed on PlotLink"}),!ya&&d.jsx("button",{onClick:async()=>{if(!(!e||!t||!N.txHash)){G(!0);try{(await(await i("/api/publish/retry-index",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storyName:e,fileName:t,txHash:N.txHash,content:N.content,storylineId:N.storylineId})})).json()).ok&&(await i(`/api/stories/${e}/${t}/publish-status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({txHash:N.txHash,storylineId:N.storylineId,contentCid:"",gasCost:""})}),Rt())}catch{}G(!1)}},disabled:M,className:"px-3 py-1 bg-accent text-white text-xs rounded hover:bg-accent-dim disabled:opacity-50",children:M?"Retrying...":`Retry Index${Lr?` (${Lr})`:""}`}),gi&&d.jsx("button",{onClick:()=>{!e||!t||!window.confirm(`This episode is already on-chain — try “Retry Index” first.
+`)}const YS=12e3,RD=5,DD=6e4,MD=6e4,BD=5;function LD(e,t){return e===429?!0:!!t&&/rate[\s-]?limit/i.test(t)}function OD(e,t=YS){return Math.min(t*2**e,DD)}const KS=e=>new Promise(t=>setTimeout(t,e));async function zD(e,t={}){var c;const i=t.sleep??KS,s=t.maxRetries??RD,a=t.baseDelayMs??YS;let o=0;for(;;){const h=await e();if(h.ok||!LD(h.status,h.errorMessage)||o>=s)return h;const p=OD(o,a);o+=1,(c=t.onWaiting)==null||c.call(t,{attempt:o,maxRetries:s,waitMs:p}),await i(p)}}function PD(e={}){const t=e.limit??BD,i=e.windowMs??MD,s=e.sleep??KS,a=e.now??(()=>Date.now()),o=[],c=()=>{const h=a()-i;for(;o.length&&o[0]<=h;)o.shift()};return async function(){var p;if(c(),o.length>=t){const f=o[0]+i-a();f>0&&((p=e.onWaiting)==null||p.call(e,{waitMs:f}),await s(f)),c()}o.push(a())}}const zp=1024*1024;function fy(e,t,i){return new Promise((s,a)=>{e.toBlob(o=>o?s(o):a(new Error(`Failed to export as ${t}`)),t,i)})}async function ID(e){const t=[.9,.8,.7,.6];for(const s of t)try{const a=await fy(e,"image/webp",s);if(a.type!=="image/webp")break;if(a.size<=zp)return a}catch{break}const i=[.85,.7,.5];for(const s of i){const a=await fy(e,"image/jpeg",s);if(a.size<=zp)return a}throw new Error("Cannot compress image under 1MB — reduce overlay count or image size")}const HD=["image/webp","image/jpeg"];function VS(e){return HD.includes(e.type)&&e.size<=zp}async function UD(e){var i;if(typeof createImageBitmap!="function")throw new Error("This browser cannot decode the image for import");let t;try{t=await createImageBitmap(e)}catch{throw new Error("Could not read the selected image — pick a PNG, WebP, or JPEG file")}try{const s=document.createElement("canvas");s.width=t.width,s.height=t.height;const a=s.getContext("2d");if(!a)throw new Error("Could not process the image for import");return a.drawImage(t,0,0),s}finally{(i=t.close)==null||i.call(t)}}async function Ku(e){if(VS(e))return e;const t=await UD(e);return ID(t)}function $D(e){if(!e||typeof e!="object")return!1;const t=e;return typeof t.token=="string"&&t.token.length>0&&typeof t.name=="string"&&typeof t.size=="number"&&typeof t.mtimeMs=="number"}async function FD(e){let t;try{t=await e("/api/codex/images")}catch{return[]}if(!t.ok)return[];let i;try{i=await t.json()}catch{return[]}const s=i==null?void 0:i.images;return Array.isArray(s)?s.filter($D):[]}async function qD(e,t){let i;try{i=await e(`/api/codex/images/${encodeURIComponent(t.token)}`)}catch{throw new Error("Could not read the generated image from the Codex cache")}if(!i.ok)throw new Error("Could not read the generated image from the Codex cache");const s=await i.blob(),a=s.type||i.headers.get("Content-Type")||"image/png";return new File([s],t.name||"codex-image.png",{type:a})}function WD(e,t){const[i,s]=w.useState(null);return w.useEffect(()=>{let a=null,o=!1;return(async()=>{try{const c=await t(e);if(!c.ok)return;const h=await c.blob();if(o)return;a=URL.createObjectURL(h),s(a)}catch{}})(),()=>{o=!0,a&&URL.revokeObjectURL(a)}},[e,t]),i}function GD(e){return e>=1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:e>=1024?`${Math.round(e/1024)} KB`:`${e} B`}function YD(e,t){const i=t-e;if(!Number.isFinite(i)||i<45e3)return"just now";const s=Math.round(i/6e4);if(s<60)return`${s}m ago`;const a=Math.round(i/36e5);if(a<24)return`${a}h ago`;const o=Math.round(i/864e5);return o<7?`${o}d ago`:`${Math.round(i/(7*864e5))}w ago`}function KD({image:e,authFetch:t}){const i=WD(`/api/codex/images/${encodeURIComponent(e.token)}`,t);return i?d.jsx("img",{src:i,alt:e.name,className:"w-16 h-16 flex-shrink-0 rounded border border-border object-cover bg-white"}):d.jsx("div",{className:"w-16 h-16 flex-shrink-0 rounded border border-border bg-surface"})}function VD({authFetch:e,cutId:t,onImport:i,onClose:s}){const[a,o]=w.useState(null),[c,h]=w.useState(null),[p,f]=w.useState(null),[_,x]=w.useState("");w.useEffect(()=>{let E=!1;return(async()=>{const N=await FD(e);E||o(N)})(),()=>{E=!0}},[e]);const b=_.trim().toLowerCase(),v=w.useMemo(()=>a?b?a.filter(E=>E.name.toLowerCase().includes(b)):a:[],[a,b]),S=Date.now(),j=async E=>{h(null),f(E.token);try{const N=await qD(e,E);await i(N)}catch(N){h(N instanceof Error?N.message:"Could not import the generated image")}finally{f(null)}},R=a!==null&&a.length>0;return d.jsxs("div",{className:"rounded border border-border bg-surface/60 p-2 space-y-2","data-testid":`codex-picker-${t}`,children:[d.jsxs("div",{className:"flex items-center justify-between",children:[d.jsx("p",{className:"text-[11px] font-medium text-foreground",children:"Import a Codex-generated image"}),d.jsx("button",{onClick:s,"data-testid":`codex-picker-close-${t}`,className:"text-[11px] text-muted hover:text-foreground",children:"Close"})]}),R&&d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("input",{type:"search",value:_,onChange:E=>x(E.target.value),placeholder:"Filter by file name…","data-testid":`codex-picker-search-${t}`,className:"min-w-0 flex-1 px-2 py-1 text-[11px] border border-border rounded bg-transparent focus:border-accent focus:outline-none"}),d.jsx("span",{className:"text-[10px] text-muted whitespace-nowrap","data-testid":`codex-picker-count-${t}`,children:b?`${v.length} of ${a.length}`:`${a.length} image${a.length===1?"":"s"}`})]}),a===null&&d.jsx("p",{className:"text-[11px] text-muted","data-testid":`codex-picker-loading-${t}`,children:"Looking for generated images…"}),a!==null&&a.length===0&&d.jsx("p",{className:"text-[11px] text-muted","data-testid":`codex-picker-empty-${t}`,children:"No generated images found in the Codex cache yet. Generate art in Codex, then reopen this list — or use “Upload clean image” to pick a file."}),R&&v.length===0&&d.jsxs("p",{className:"text-[11px] text-muted","data-testid":`codex-picker-no-match-${t}`,children:["No generated images match “",_.trim(),"”."]}),R&&v.length>0&&d.jsx("ul",{className:"space-y-1 max-h-72 overflow-y-auto",children:v.map(E=>d.jsxs("li",{"data-testid":`codex-image-${E.token}`,className:"flex items-center gap-2 rounded border border-border bg-background/40 p-1.5",children:[d.jsx(KD,{image:E,authFetch:e}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsxs("p",{className:"text-[11px] text-foreground",children:[YD(E.mtimeMs,S)," · ",GD(E.size)]}),d.jsx("p",{className:"truncate text-[10px] font-mono text-muted",title:E.name,children:E.name})]}),d.jsx("button",{onClick:()=>j(E),disabled:p!==null,"data-testid":`codex-import-${E.token}`,className:"px-2 py-1 text-[11px] border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50",children:p===E.token?"Importing…":"Import to this cut"})]},E.token))}),c&&d.jsx("p",{className:"text-[11px] text-error",children:c})]})}const XD={done:"✓",current:"▸",todo:"○"};function ZD({checklist:e,issues:t,onFinish:i,finishing:s,progressText:a,canFinish:o,markdownReady:c=!1,published:h=!1}){var E;if(!e||e.steps.length===0)return null;const p=GS(t),f=((E=e.steps.find(N=>N.key==="upload"))==null?void 0:E.status)==="done",_=f&&c&&!h,x=h||c?"done":f?"current":"todo",b=h?"done":_?"current":"todo",v=[...e.steps.filter(N=>N.key!=="publish"),{key:"assemble",label:"Episode sequence prepared",status:x,detail:null},{key:"ready",label:h?"Published to PlotLink":"Ready to publish",status:b,detail:null}],S=s?a||"Finishing…":h?"Published ✓":_?"Episode ready to publish":"Finish episode",j=v.filter(N=>N.status!=="done").length,R=p.reduce((N,I)=>N+I.lines.length,0);return d.jsxs("div",{className:"px-3 py-1.5 border-b border-border bg-surface/50 flex-shrink-0","data-testid":"finish-episode-panel",children:[d.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[d.jsx("span",{className:"text-[11px] font-medium text-foreground",children:"Finish episode"}),e.nextStep&&d.jsxs("span",{className:"min-w-0 flex-1 text-[10px] text-muted truncate","data-testid":"finish-next-step",children:["Next: ",e.nextStep]}),d.jsx("button",{onClick:i,disabled:s||!o,"data-testid":"finish-episode-btn",title:"Upload the exported final panels, then prepare the episode for publishing — picks up where it left off",className:"px-2.5 py-0.5 text-[11px] border border-accent/40 text-accent rounded hover:bg-accent/5 disabled:opacity-50",children:S})]}),d.jsxs("details",{className:"mt-1","data-testid":"finish-episode-details",children:[d.jsxs("summary",{className:"cursor-pointer select-none text-[10px] text-muted hover:text-foreground",children:[j===0?"Progress details":`${j} step${j===1?"":"s"} left`,R>0?` · ${R} blocker${R===1?"":"s"}`:""]}),d.jsxs("div",{className:"mt-1.5 space-y-1.5",children:[d.jsx("ol",{className:"flex flex-wrap gap-1.5",children:v.map(N=>d.jsxs("li",{"data-testid":`finish-step-${N.key}`,"data-status":N.status,className:`flex items-center gap-1 rounded border px-1.5 py-0.5 text-[10px] ${N.status==="current"?"border-accent/40 bg-accent/10 text-accent":N.status==="done"?"border-border bg-background/70 text-foreground":"border-border/70 bg-background/40 text-muted"}`,children:[d.jsx("span",{"aria-hidden":!0,children:XD[N.status]}),d.jsx("span",{children:N.label}),N.detail&&d.jsxs("span",{className:"text-muted",children:["· ",N.detail]})]},N.key))}),p.length>0&&d.jsx("div",{className:"space-y-1.5","data-testid":"finish-issues",children:p.map(N=>d.jsxs("div",{"data-testid":`finish-issue-group-${N.key}`,className:"text-[10px]",children:[d.jsx("p",{className:"font-medium text-amber-700",children:N.title}),d.jsx("ul",{className:"ml-3 list-disc text-muted",children:N.lines.map((I,te)=>d.jsx("li",{children:I},te))})]},N.key))})]})]})]})}function QD(e){return{planned:e.filter(t=>t.state==="planned").length,needsConversion:e.filter(t=>t.state==="needs-conversion").length,missing:e.filter(t=>t.state==="missing").length,cleanReady:e.filter(t=>t.state==="clean-ready").length,finalReady:e.filter(t=>t.state==="final-ready").length,uploaded:e.filter(t=>t.state==="uploaded").length}}function Ao(e){return(!!e.cleanImagePath||In(e))&&ym(e).length>0}function py(e){const t=new Date().toISOString();return{status:"generated",baseSig:ul(e),generatedAt:t,updatedAt:t}}function XS(e){return e.uploadedCid?"uploaded":e.finalImagePath||e.exportedAt?"lettered":e.cleanImagePath?"clean":In(e)?"text":"missing"}const my={muted:"text-muted",amber:"text-amber-700",green:"text-green-700",accent:"text-accent"},JD={muted:"bg-muted/40",amber:"bg-amber-500",green:"bg-green-600",accent:"bg-accent"};function eM(e,t,i){var s;return e.uploadedCid||e.uploadedUrl?{key:"uploaded",label:"Uploaded",tone:"green"}:t?{key:"convert",label:"Needs conversion",tone:"amber"}:i?e.finalImagePath?{key:"review",label:"Needs review",tone:"amber"}:{key:"needs-image",label:"Needs image",tone:"muted"}:e.finalImagePath?{key:"exported",label:"Exported",tone:"green"}:In(e)?{key:"text",label:"Ready for captions",tone:"accent"}:e.cleanImagePath?(((s=e.overlays)==null?void 0:s.length)??0)>0?{key:"review",label:"Needs review",tone:"amber"}:{key:"letter",label:"Ready for lettering",tone:"green"}:{key:"needs-image",label:"Needs image",tone:"muted"}}function tM(e){var t,i;return e.uploadedCid||e.uploadedUrl?{label:"Complete",detail:"Final image uploaded",tone:"green"}:e.finalImagePath||e.exportedAt?{label:"Exported",detail:"Ready to upload",tone:"green"}:(((t=e.overlays)==null?void 0:t.length)??0)>0?((i=e.aiDraft)==null?void 0:i.status)==="generated"?{label:"Draft ready",detail:`${e.overlays.length} AI-drafted overlay${e.overlays.length===1?"":"s"} ready to review`,tone:"amber"}:{label:"User-edited",detail:`${e.overlays.length} overlay${e.overlays.length===1?"":"s"} adjusted and ready to review`,tone:"amber"}:Ao(e)?{label:"No draft",detail:"Draft with AI or place bubbles manually",tone:"muted"}:In(e)?{label:"Between-scene card",detail:"Open to add narration or title text",tone:"accent"}:e.cleanImagePath?{label:"Unlettered",detail:"Clean art ready for bubble placement",tone:"muted"}:{label:"Needs artwork",detail:"Add or sync clean art first",tone:"muted"}}function iM({cut:e,storyName:t,plotFile:i,expanded:s,onToggle:a,authFetch:o,onUpdated:c,onOpenEditor:h,detectedLocalClean:p,onSyncClean:f,syncing:_,onAiDraft:x,aiDrafting:b,staleMessages:v,onRepairStale:S,repairing:j,conversionPng:R,onConvert:E,converting:N,rowRef:I}){var Be,Le;const te=w.useRef(null),[F,D]=w.useState(!1),[ie,fe]=w.useState(null),[Se,H]=w.useState(!1),[ce,W]=w.useState(!1),[K,X]=w.useState(!1),[U,A]=w.useState(!1),O=XS(e),$=v.length>0,xe=!!R,T=w.useCallback(async()=>{R&&(A(!0),await E(e.id,R),A(!1),c())},[R,E,e.id,c]),M=w.useCallback(async je=>{D(!0),fe(null);try{let be=je;if(!VS(je))try{be=await Ku(je)}catch(We){return fe(We instanceof Error?We.message:"Could not import image"),!1}const tt=be.type==="image/jpeg"?"jpg":"webp",St=new FormData;St.append("file",new File([be],`clean.${tt}`,{type:be.type}));const ot=await o(`/api/stories/${t}/cuts/${i}/upload-clean/${e.id}`,{method:"POST",body:St});if(!ot.ok){const We=await ot.json();return fe(We.error||"Upload failed"),!1}return c(),!0}catch{return fe("Upload failed"),!1}finally{D(!1)}},[o,t,i,e.id,c]),G=eM(e,xe,$),C=e.cleanImagePath??R??null,V=((Be=e.overlays)==null?void 0:Be.length)??0,ne=!In(e)&&!!e.cleanImagePath&&!e.finalImagePath&&!e.uploadedCid&&!e.uploadedUrl&&!$&&!xe,ae=!$&&!xe&&!e.finalImagePath&&!e.uploadedCid&&!e.uploadedUrl&&Ao(e),Y=(((Le=e.overlays)==null?void 0:Le.length)??0)>0?"Re-draft with AI":"AI draft lettering",he=G.key==="convert"?{label:U?"Converting…":"Convert image",onClick:T,testid:`card-convert-${e.id}`}:G.key==="review"?{label:"Review cut",onClick:h,testid:`card-review-${e.id}`}:G.key==="text"?{label:"Add captions",onClick:h,testid:`card-letter-${e.id}`}:G.key==="needs-image"?{label:"Add artwork",onClick:a,testid:`card-addart-${e.id}`}:null,_e=tM(e);return d.jsxs("div",{ref:I,"data-cut-row":e.id,className:`border rounded ${s?"border-accent/30":"border-border"}`,children:[d.jsxs("div",{className:"px-3 py-2 space-y-2","data-testid":`cut-card-${e.id}`,children:[d.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[d.jsx("span",{className:`w-2 h-2 rounded-full flex-shrink-0 ${JD[G.tone]}`}),d.jsxs("span",{className:"font-medium text-xs text-foreground",children:["Cut ",String(e.id).padStart(2,"0")]}),d.jsxs("span",{className:"font-mono text-[10px] text-muted",children:["· ",e.shotType]}),d.jsx("span",{className:`ml-auto text-[10px] font-medium flex-shrink-0 ${my[G.tone]}`,"data-testid":`cut-card-status-${e.id}`,children:G.label})]}),C?d.jsx(Bp,{storyName:t,assetPath:C,authFetch:o,alt:`Cut ${e.id} artwork`,className:"w-full max-h-[32rem] object-contain rounded border border-border bg-white"}):d.jsx("div",{className:"w-full min-h-28 rounded border border-dashed border-border bg-surface/40 flex items-center justify-center text-[10px] text-muted","data-testid":`cut-card-noart-${e.id}`,children:In(e)?"Text panel — no artwork needed":"No artwork yet"}),d.jsxs("div",{className:`rounded border border-border/70 bg-surface/50 px-2 py-1.5 text-[11px] ${my[_e.tone]}`,"data-testid":`lettering-review-state-${e.id}`,children:[d.jsx("span",{className:"font-semibold",children:_e.label}),d.jsxs("span",{className:"text-muted",children:[" · ",_e.detail]})]}),d.jsx("button",{onClick:a,"data-testid":`cut-desc-${e.id}`,className:"block w-full text-left text-[11px] text-muted hover:text-foreground",children:e.description||"No description"}),d.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[ne?d.jsxs(d.Fragment,{children:[d.jsx("button",{onClick:h,"data-testid":`add-bubbles-${e.id}`,className:"px-2.5 py-1 text-[11px] font-medium rounded bg-accent text-white hover:bg-accent-dim",children:V>0?"Review lettering":"Open focused editor"}),ae&&d.jsx("button",{onClick:x,disabled:b,"data-testid":`ai-draft-${e.id}`,className:"px-2.5 py-1 text-[11px] rounded border border-accent/40 text-accent hover:bg-accent/5 disabled:opacity-50",children:b?"Drafting…":Y})]}):he?d.jsx("button",{onClick:he.onClick,disabled:G.key==="convert"&&(U||N),"data-testid":he.testid,className:"px-2.5 py-1 text-[11px] font-medium rounded bg-accent text-white hover:bg-accent-dim disabled:opacity-50",children:he.label}):null,!ne&&!he&&ae&&d.jsx("button",{onClick:x,disabled:b,"data-testid":`ai-draft-${e.id}`,className:"px-2.5 py-1 text-[11px] rounded border border-accent/40 text-accent hover:bg-accent/5 disabled:opacity-50",children:b?"Drafting…":Y}),d.jsx("button",{onClick:a,"data-testid":`cut-details-${e.id}`,className:"px-2.5 py-1 text-[11px] rounded border border-border text-muted hover:border-accent hover:text-accent",children:s?"Hide details":"Open details"})]})]}),s&&d.jsxs("div",{className:"px-3 pb-3 space-y-3 border-t border-border",children:[xe&&d.jsxs("div",{className:"mt-2 rounded border border-amber-500/40 bg-amber-500/10 p-2 space-y-1","data-testid":`needs-conversion-${e.id}`,children:[d.jsx("p",{className:"text-[11px] text-amber-800",children:"This cut’s artwork is a PNG. Convert it to WebP so it can be lettered and published."}),d.jsx("button",{onClick:T,disabled:U||N,"data-testid":`convert-cut-${e.id}`,className:"px-2 py-1 text-[11px] border border-amber-500/50 text-amber-800 rounded hover:bg-amber-500/20 disabled:opacity-50",children:U?"Converting…":"Convert image"})]}),$&&!xe&&d.jsxs("div",{className:"mt-2 rounded border border-error/40 bg-error/5 p-2 space-y-1","data-testid":`stale-asset-${e.id}`,children:[v.map((je,be)=>d.jsx("p",{className:"text-[11px] text-error",children:je},be)),d.jsx("button",{onClick:S,disabled:j,"data-testid":`repair-stale-${e.id}`,className:"px-2 py-1 text-[11px] border border-error/40 text-error rounded hover:bg-error/10 disabled:opacity-50",children:j?"Repairing…":"Clear stale path"})]}),!In(e)&&d.jsxs("div",{className:"mt-2 space-y-2",children:[d.jsx("button",{onClick:()=>{navigator.clipboard.writeText(dy(e,i)),H(!0),setTimeout(()=>H(!1),2e3)},"data-testid":`copy-prompt-${e.id}`,className:"px-3 py-1.5 text-xs border border-border rounded hover:border-accent hover:bg-accent/5",children:Se?"Copied!":"Copy Codex task"}),d.jsx("input",{ref:te,type:"file",accept:"image/webp,image/jpeg,image/png",className:"hidden",onChange:je=>{var tt;const be=(tt=je.target.files)==null?void 0:tt[0];be&&M(be),je.target.value=""}}),d.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[d.jsx("button",{onClick:()=>{var je;return(je=te.current)==null?void 0:je.click()},disabled:F,className:"px-3 py-1.5 text-xs border border-border rounded hover:border-accent hover:bg-accent/5 disabled:opacity-50",children:F?"Uploading...":e.cleanImagePath?"Replace clean image":"Upload clean image"}),d.jsx("button",{onClick:()=>X(je=>!je),disabled:F,"data-testid":`import-codex-${e.id}`,className:"px-3 py-1.5 text-xs border border-border rounded hover:border-accent hover:bg-accent/5 disabled:opacity-50",children:K?"Hide Codex images":"Import from Codex"})]}),K&&d.jsx(VD,{authFetch:o,cutId:e.id,onImport:async je=>{await M(je)&&X(!1)},onClose:()=>X(!1)}),!e.cleanImagePath&&d.jsx("p",{className:"text-xs text-muted","data-testid":`clean-image-handoff-${e.id}`,children:"Generate this cut in Codex, then import the cached PNG with “Import from Codex” — or upload an image manually. Letter it next."}),O==="missing"&&d.jsxs("div",{className:"rounded border border-border bg-surface/60 p-2 space-y-1","data-testid":`ask-codex-${e.id}`,children:[d.jsx("p",{className:"text-[11px] font-medium text-foreground",children:"Generate this cut in Codex"}),d.jsxs("p",{className:"text-[10px] text-muted",children:["Copy the task below and paste it into Codex. Codex usually saves a PNG to its image cache — bring it into this cut with “Import from Codex” above (the PNG becomes a WebP automatically). If Codex instead writes a WebP/JPEG at"," ",d.jsxs("span",{className:"font-mono",children:["assets/",i,"/cut-",String(e.id).padStart(2,"0"),"-clean.webp"]}),", it’s picked up by “Sync clean images”."]}),d.jsx("button",{onClick:()=>{navigator.clipboard.writeText(dy(e,i)),W(!0),setTimeout(()=>W(!1),2e3)},"data-testid":`ask-codex-copy-${e.id}`,className:"px-2 py-1 text-[11px] border border-border rounded hover:border-accent hover:bg-accent/5",children:ce?"Copied!":"Copy Codex task"})]}),O==="missing"&&p&&d.jsx("button",{onClick:f,disabled:_,"data-testid":`found-local-clean-${e.id}`,className:"px-3 py-1.5 text-xs border border-green-700/40 text-green-700 rounded hover:bg-green-700/5 disabled:opacity-50",children:_?"Syncing...":"Found local clean image — sync to cut plan"}),ie&&d.jsx("p",{className:"text-xs text-error mt-1",children:ie})]}),(e.cleanImagePath||e.narration||e.dialogue.length>0||In(e))&&d.jsx("button",{onClick:h,"data-testid":`open-editor-${e.id}`,className:"px-3 py-1.5 text-xs border border-accent/30 text-accent rounded hover:bg-accent/5",children:"Open editor"}),e.characters.length>0&&d.jsxs("p",{className:"text-xs text-muted",children:["Characters: ",e.characters.join(", ")]}),e.dialogue.length>0&&d.jsx("div",{className:"text-xs text-muted",children:e.dialogue.map((je,be)=>d.jsxs("p",{children:[d.jsxs("span",{className:"font-medium",children:[je.speaker,":"]})," ",je.text]},be))}),e.narration&&d.jsx("p",{className:"text-xs text-muted italic",children:e.narration})]})]})}function gy({storyName:e,fileName:t,authFetch:i,language:s,uploadRetry:a,onCutsChanged:o,focusRequest:c,onFocusHandled:h,onFocusedLetteringModeChange:p,workspaceVisible:f=!1,onWorkspaceVisibleChange:_}){var pr,Lt,le;const[x,b]=w.useState(null),v=w.useRef(o);v.current=o;const S=w.useRef(h);S.current=h;const[j,R]=w.useState(!0),[E,N]=w.useState(null),[I,te]=w.useState(null),[F,D]=w.useState(null),[ie,fe]=w.useState(!1),[Se,H]=w.useState([]),[ce,W]=w.useState(!1),[K,X]=w.useState(""),[U,A]=w.useState({markdownReady:!1,published:!1}),[O,$]=w.useState(!1),[xe,T]=w.useState(!1),[M,G]=w.useState(!1),[C,V]=w.useState(null),[ne,ae]=w.useState(null),[Y,he]=w.useState(null),[_e,Be]=w.useState(!1),[Le,je]=w.useState(new Set),[be,tt]=w.useState(new Map),[St,ot]=w.useState(!1),[We,Mt]=w.useState(null),[He,xt]=w.useState(!1),[Ae,Kt]=w.useState(null),mi=w.useRef(new Map),wt=w.useRef(null),Qe=t.replace(/\.md$/,"");w.useEffect(()=>{var L;c&&wt.current!==c.seq&&(wt.current=c.seq,c.openEditor?D(c.cutId):(te(c.cutId),Kt(c.cutId)),(L=S.current)==null||L.call(S))},[c]),w.useEffect(()=>(p==null||p(F!==null),()=>p==null?void 0:p(!1)),[F,p]),w.useEffect(()=>{var oe;if(Ae==null)return;const L=mi.current.get(Ae);L&&((oe=L.scrollIntoView)==null||oe.call(L,{behavior:"smooth",block:"center"}),Kt(null))},[Ae,x]);const Q=w.useCallback(async()=>{var L;try{const oe=await i(`/api/stories/${e}/cuts/${Qe}`);if(oe.status===404){b(null);return}if(!oe.ok){const Me=await oe.json();N(Me.error||"Failed to load cuts");return}const Ee=await oe.json();b(Ee),N(null);try{const Me=await i(`/api/stories/${e}/${t}`);if(Me.ok){const Ne=await Me.json(),Pe=typeof(Ne==null?void 0:Ne.content)=="string"?Ne.content:"",qe=Array.isArray(Ee==null?void 0:Ee.cuts)?Ee.cuts:[],nt=Pe.length>0&&qS(Pe,qe).ready,Ve=(Ne==null?void 0:Ne.status)==="published"||(Ne==null?void 0:Ne.status)==="published-not-indexed";A({markdownReady:nt,published:Ve})}else A({markdownReady:!1,published:!1})}catch{A({markdownReady:!1,published:!1})}(L=v.current)==null||L.call(v)}catch{N("Failed to load cuts")}finally{R(!1)}},[i,e,Qe,t]),ge=w.useCallback(async L=>!!(await i(`/api/stories/${e}/cuts/${Qe}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(L)})).ok,[i,e,Qe]),Te=w.useCallback(async()=>{ot(!1);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/detect-clean-images`);if(!L.ok)return;const oe=await L.json();je(new Set(Array.isArray(oe.detected)?oe.detected:[]));const Ee=new Map,Me=oe.stale;if(Array.isArray(Me))for(const Ne of Me){if(typeof(Ne==null?void 0:Ne.cutId)!="number"||typeof(Ne==null?void 0:Ne.message)!="string")continue;const Pe=Ee.get(Ne.cutId)??[];Pe.push(Ne.message),Ee.set(Ne.cutId,Pe)}tt(Ee),ot(!0)}catch{}},[i,e,Qe]),Ue=w.useCallback(async()=>{Mt(null);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/asset-diagnostics`);if(!L.ok)return;const oe=await L.json();Mt(Array.isArray(oe.diagnostics)?oe.diagnostics:null)}catch{}},[i,e,Qe]),it=w.useCallback(async()=>{xt(!0);try{await Promise.all([Q(),Te(),Ue()])}finally{xt(!1)}},[Q,Te,Ue]),Wt=w.useCallback(async(L,oe={})=>{var Ne;if(!x)return!1;const Ee=x.cuts.find(Pe=>Pe.id===L);if(!Ee||!Ao(Ee)||(((Ne=Ee.overlays)==null?void 0:Ne.length)??0)>0&&!window.confirm("This cut already has overlays. Re-drafting with AI will replace the current draft overlays for this cut. Continue?"))return!1;const Me=oy(Ee);if(Me.length===0)return ae(`Cut ${Ee.id}: no script lines available to draft.`),!1;he(L),ae(null);try{const Pe={...x,cuts:x.cuts.map(nt=>nt.id===L?{...nt,overlays:Me,aiDraft:py(Me)}:nt)};return await ge(Pe)?(ae(`Cut ${Ee.id}: AI draft ready`),await Q(),oe.openEditor&&D(L),!0):(ae(`Cut ${Ee.id}: AI draft failed`),!1)}finally{he(null)}},[x,ge,Q]),ui=w.useCallback(async()=>{if(!x)return;const L=x.cuts.filter(oe=>{var Ee;return Ao(oe)&&(((Ee=oe.overlays)==null?void 0:Ee.length)??0)===0&&!oe.finalImagePath&&!oe.uploadedCid&&!oe.uploadedUrl});if(L.length===0){ae("No unlettered cuts need an AI draft");return}Be(!0),ae(null);try{const oe={...x,cuts:x.cuts.map(Me=>{if(!L.some(Pe=>Pe.id===Me.id))return Me;const Ne=oy(Me);return Ne.length>0?{...Me,overlays:Ne,aiDraft:py(Ne)}:Me})};if(!await ge(oe)){ae("AI draft failed");return}ae(`AI draft ready for ${L.length} cut${L.length===1?"":"s"}`),await Q()}finally{Be(!1)}},[x,ge,Q]),Bt=w.useCallback(async()=>{$(!0),ae(null),H([]);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/sync-clean-images`,{method:"POST"}),oe=await L.json().catch(()=>({}));if(!L.ok)ae(oe.error||"Sync failed");else{const Ee=Array.isArray(oe.synced)?oe.synced.length:0,Me=Array.isArray(oe.cleared)?oe.cleared.length:0,Ne=Array.isArray(oe.rejected)?oe.rejected:[];Ne.length>0&&H(Ne.map(qe=>`Cut ${qe.cutId}: ${qe.reason}`));const Pe=[];Ee>0&&Pe.push(`Synced ${Ee}`),Me>0&&Pe.push(`Cleared ${Me} stale path${Me===1?"":"s"}`),ae(Pe.length>0?Pe.join(", "):"No new clean images"),await Q(),await Te(),await Ue()}}catch{ae("Sync failed")}$(!1)},[i,e,Qe,Q,Te,Ue]),vt=w.useCallback(async(L,oe)=>{try{const Ee=await i(OS(e,oe));if(!Ee.ok)return!1;const Me=await Ee.blob(),Ne=await Ku(new File([Me],"clean.png",{type:Me.type||"image/png"})),Pe=Ne.type==="image/jpeg"?"jpg":"webp",qe=new FormData;return qe.append("file",new File([Ne],`clean.${Pe}`,{type:Ne.type})),(await i(`/api/stories/${e}/cuts/${Qe}/upload-clean/${L}`,{method:"POST",body:qe})).ok}catch{return!1}},[i,e,Qe]),At=w.useCallback(async L=>{G(!0),V(null);let oe=0;const Ee=[];for(const Me of L)await vt(Me.cutId,Me.pngPath)?oe++:Ee.push(Me.cutId);await it(),G(!1),V(Ee.length===0?`Converted ${oe} image${oe===1?"":"s"} to WebP`:`Converted ${oe}; ${Ee.length} failed (Cut ${Ee.join(", ")}) — try Convert image on each`)},[vt,it]),Ze=w.useCallback(async()=>{var Ne;if(!x)return;W(!0),X(""),H([]);const L=x.cuts.filter(Pe=>Pe.finalImagePath&&!Pe.uploadedCid),oe=[],Ee=PD({sleep:a==null?void 0:a.sleep,onWaiting:({waitMs:Pe})=>X(`Upload limit reached — waiting ${Math.round(Pe/1e3)}s before continuing…`)});for(let Pe=0;Pe{const Jt=await i("/api/publish/upload-plot-image",{method:"POST",body:Nt});if(Jt.ok){const{cid:$n,url:gr}=await Jt.json();return{ok:!0,status:Jt.status,cid:$n,url:gr}}const qi=await Jt.json().catch(()=>({}));return{ok:!1,status:Jt.status,errorMessage:qi.error}},{...a,onWaiting:({attempt:Jt,maxRetries:qi,waitMs:$n})=>X(`Cut ${qe.id} rate-limited — waiting ${Math.round($n/1e3)}s before retry ${Jt}/${qi}...`)});if(!Gt.ok){oe.push(`Cut ${qe.id}: upload failed — ${Gt.errorMessage||"unknown"}`);continue}const{cid:Rt,url:ki}=Gt;(await i(`/api/stories/${e}/cuts/${Qe}/set-uploaded/${qe.id}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({cid:Rt,url:ki})})).ok||oe.push(`Cut ${qe.id}: failed to record upload`)}catch(nt){oe.push(`Cut ${qe.id}: ${nt instanceof Error?nt.message:"failed"}`)}}if(oe.length>0){H(oe),W(!1),X(""),Q();return}X("Preparing episode for publishing…");const Me=await i(`/api/stories/${e}/cuts/${Qe}/generate-markdown`,{method:"POST"});if(Me.ok){const Pe=await Me.json();((Ne=Pe.warnings)==null?void 0:Ne.length)>0&&H(Pe.warnings)}W(!1),X(""),Q()},[x,i,e,Qe,a,Q]),hi=w.useCallback(async()=>{T(!0),ae(null);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/repair-asset-paths`,{method:"POST"}),oe=await L.json().catch(()=>({}));if(!L.ok)ae(oe.error||"Repair failed");else{const Ee=Array.isArray(oe.cleared)?oe.cleared.length:0;ae(Ee>0?`Cleared ${Ee} stale path${Ee===1?"":"s"}`:"No stale paths to clear"),await Q(),await Te()}}catch{ae("Repair failed")}T(!1)},[i,e,Qe,Q,Te]),[P,we]=w.useState(!1),ze=w.useCallback(async(L,oe=!0)=>{if(x){we(!0);try{const Ee=x.cuts.reduce((nt,Ve)=>Math.max(nt,Ve.id),0)+1,Me={id:Ee,shotType:"wide",description:"Text panel",characters:[],dialogue:[],narration:"",sfx:"",cleanImagePath:null,finalImagePath:null,exportedAt:null,uploadedCid:null,uploadedUrl:null,overlays:[],kind:"text",background:"#101820",aspectRatio:"4:5"},Ne=[...x.cuts];Ne.splice(Math.max(0,Math.min(L,Ne.length)),0,Me);const Pe={...x,cuts:Ne},qe=await i(`/api/stories/${e}/cuts/${Qe}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(Pe)});if(qe.ok)oe?D(Ee):te(Ee),await Q();else{const nt=await qe.json().catch(()=>({}));ae(nt.error||"Could not add text panel")}}catch{ae("Could not add text panel")}we(!1)}},[x,i,e,Qe,Q]),Re=w.useCallback(()=>ze((x==null?void 0:x.cuts.length)??0,!0),[ze,x]);if(w.useEffect(()=>{Q(),Te(),Ue()},[Q,Te,Ue]),j)return d.jsx("div",{className:"p-4 text-sm text-muted",children:"Loading cuts..."});if(E)return d.jsxs("div",{className:"p-4 space-y-2","data-testid":"cuts-error",children:[d.jsx("p",{className:"text-sm text-error font-medium",children:"Invalid cuts file"}),d.jsx("p",{className:"text-xs text-error",children:E}),d.jsxs("p",{className:"text-xs text-muted",children:[Qe,".cuts.json must follow the OWS v1 schema. Ask Claude to regenerate it using the v1 cuts schema from the cartoon writing instructions."]}),d.jsx("button",{onClick:Q,className:"text-xs text-accent hover:text-accent-dim",children:"Retry"})]});if(!x||x.cuts.length===0)return d.jsxs("div",{className:"p-4 text-center space-y-1",children:[d.jsx("p",{className:"text-sm text-muted",children:"No cuts yet"}),d.jsx("p",{className:"text-xs text-muted",children:"Ask Claude to create a cut plan for this episode."})]});const Ge=F!==null?x.cuts.find(L=>L.id===F):null;if(Ge)return d.jsx(kD,{storyName:e,cut:Ge,plotFile:Qe,language:s,authFetch:i,targetLabel:In(Ge)?`Between-scene card ${Ge.id}`:`Cut ${String(Ge.id).padStart(2,"0")}`,returnOnSave:!0,workspaceVisible:f,onToggleWorkspaceVisible:_?()=>_(!f):void 0,onSave:async(L,oe)=>{const Ee={...x,cuts:x.cuts.map(Ne=>Ne.id===F?{...Ne,overlays:L,aiDraft:oe??Ne.aiDraft??null}:Ne)};if(!await ge(Ee))throw new Error("Failed to save overlays")},onExported:()=>Q(),onClose:()=>{D(null),Q()}});const $e=x.cuts.reduce((L,oe)=>{const Ee=XS(oe);return L[Ee]++,L},{missing:0,clean:0,lettered:0,uploaded:0,text:0}),ht=x.cuts.filter(L=>!In(L)).length,dt=x.cuts.filter(L=>$S(L)).map(L=>L.id),lt=sD({cuts:x.cuts,published:U.published}),Vt=((pr=lt.steps.find(L=>L.key==="upload"))==null?void 0:pr.status)==="done",Ci=x.cuts.some(L=>L.finalImagePath&&!L.uploadedCid)||Vt&&!U.markdownReady,ft=(We??[]).filter(L=>L.state==="needs-conversion"&&L.convertiblePng).map(L=>({cutId:L.cutId,pngPath:L.convertiblePng})),Fi=new Map(ft.map(L=>[L.cutId,L.pngPath])),En=(We??[]).filter(L=>L.state==="needs-conversion"&&L.issue).map(L=>L.issue),ln=t==="genesis.md"?"Genesis / Episode 1":`Episode ${parseInt(((Lt=Qe.match(/\d+/))==null?void 0:Lt[0])??"0",10)+1}`,Un=typeof x.title=="string"?x.title:null,on=x.cuts.filter(L=>!In(L)),gn={cuts:x.cuts.length,artwork:on.filter(L=>L.cleanImagePath||Fi.has(L.id)).length,converted:on.filter(L=>L.cleanImagePath&&/\.(webp|jpe?g)$/i.test(L.cleanImagePath)).length,lettered:x.cuts.filter(L=>{var oe;return(((oe=L.overlays)==null?void 0:oe.length)??0)>0||!!L.finalImagePath}).length,uploaded:x.cuts.filter(L=>L.uploadedCid||L.uploadedUrl).length},cn=x.cuts.filter(L=>{var oe;return Ao(L)&&(((oe=L.overlays)==null?void 0:oe.length)??0)===0&&!L.finalImagePath&&!L.uploadedCid&&!L.uploadedUrl}).length;return d.jsxs("div",{className:"h-full min-h-[22rem] flex flex-col overflow-hidden","data-testid":"cut-list-panel",children:[d.jsx("div",{className:"px-3 py-2 border-b border-border flex-shrink-0","data-testid":"cut-board-header",children:d.jsxs("div",{className:"flex items-start gap-3 justify-between",children:[d.jsxs("div",{className:"min-w-0",children:[d.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[d.jsx("span",{className:"font-serif text-foreground truncate",children:ln}),Un&&d.jsxs("span",{className:"text-muted truncate",children:["· ",Un]})]}),d.jsxs("div",{className:"mt-0.5 text-[10px] text-muted","data-testid":"cut-board-summary",children:[gn.cuts," cuts · ",gn.artwork," artwork found ·"," ",gn.converted," converted · ",gn.lettered," ","lettered · ",gn.uploaded," uploaded"]})]}),cn>0&&d.jsx("button",{onClick:ui,disabled:_e,"data-testid":"ai-draft-all-btn",className:"px-2.5 py-1 text-[11px] rounded border border-accent/40 text-accent hover:bg-accent/5 disabled:opacity-50",children:_e?"Drafting…":`AI draft all unlettered (${cn})`})]})}),d.jsxs("details",{className:"border-b border-border flex-shrink-0","data-testid":"cut-advanced",children:[d.jsx("summary",{className:"px-3 py-1.5 text-[10px] text-muted cursor-pointer hover:text-foreground",children:"Technical details"}),d.jsxs("div",{className:"px-3 py-2 flex flex-wrap items-center gap-2 text-[10px]",children:[d.jsxs("span",{className:"font-mono text-muted",children:[x.cuts.length," cuts"]}),$e.missing>0&&d.jsxs("span",{className:"text-muted",children:[$e.missing," missing"]}),$e.clean>0&&d.jsxs("span",{className:"text-green-700",children:[$e.clean," clean"]}),$e.lettered>0&&d.jsxs("span",{className:"text-amber-700",children:[$e.lettered," lettered"]}),$e.uploaded>0&&d.jsxs("span",{className:"text-green-700",children:[$e.uploaded," uploaded"]}),$e.text>0&&d.jsxs("span",{className:"text-accent",children:[$e.text," text ",$e.text===1?"panel":"panels"]}),d.jsx("button",{onClick:async()=>{fe(!0),H([]);try{const L=await i(`/api/stories/${e}/cuts/${Qe}/generate-markdown`,{method:"POST"});if(L.ok){const oe=await L.json();H(oe.warnings||[])}}catch{}fe(!1)},disabled:ie,className:"ml-auto px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"generate-markdown-btn",title:"Build the publish-ready episode from the uploaded cut images",children:ie?"Preparing…":"Prepare episode for publish"}),d.jsx("button",{onClick:Re,disabled:P,className:"px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"add-text-panel-btn",title:"Insert a narration/title card between art panels — a solid card exported as a final image panel, no drawing needed",children:P?"Adding…":"Add narration/text panel"}),d.jsx("button",{onClick:it,disabled:He,className:"px-2 py-0.5 border border-border text-muted rounded hover:border-accent hover:text-accent disabled:opacity-50","data-testid":"refresh-assets-btn",title:"Re-check the story folder for agent-generated images and report each cut's asset state — read only, nothing is uploaded or published",children:He?"Checking…":"Refresh assets"}),d.jsx("button",{onClick:Bt,disabled:O,className:"px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"sync-clean-btn",children:O?"Syncing...":"Sync clean images"}),d.jsx("button",{onClick:Ze,disabled:ce||!(x!=null&&x.cuts.some(L=>L.finalImagePath&&!L.uploadedCid)),className:"px-2 py-0.5 border border-accent/30 text-accent rounded hover:bg-accent/5 disabled:opacity-50","data-testid":"upload-generate-btn",title:"Upload each cut's final lettered image, then prepare the episode for publishing",children:K||"Upload & Prepare for Publish"})]})]}),d.jsxs("details",{className:"px-3 py-1.5 border-b border-border bg-surface/40 flex-shrink-0","data-testid":"cartoon-workflow-help",children:[d.jsx("summary",{className:"cursor-pointer select-none text-[10px] text-muted hover:text-foreground",children:"Cut workflow help"}),d.jsxs("div",{className:"mt-1.5",children:[d.jsxs("div",{className:"flex flex-wrap items-center gap-1.5 text-[10px] text-muted",children:[d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"1. Letter"}),d.jsx("span",{"aria-hidden":!0,children:"→"}),d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"2. Export"}),d.jsx("span",{"aria-hidden":!0,children:"→"}),d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"3. Upload"}),d.jsx("span",{"aria-hidden":!0,children:"→"}),d.jsx("span",{className:"rounded-full border border-border bg-background px-2 py-0.5 text-foreground",children:"4. Prepare episode for publish"})]}),d.jsxs("div",{className:"mt-1 text-[10px] text-muted",children:["Use ",d.jsx("span",{className:"text-accent",children:"Add narration/text panel"})," ","for a narration or title card. It becomes a solid card exported as a final image."]})]})]}),dt.length>0&&d.jsxs("div",{className:"px-3 py-1.5 border-b border-amber-500/40 bg-amber-500/10 text-[10px] text-amber-700 flex-shrink-0","data-testid":"stale-bubble-export-warning",children:[dt.length===1?"Cut":"Cuts"," ",dt.join(", ")," ",dt.length===1?"was":"were"," lettered with an older speech-bubble style whose tail can show a visible seam. Re-export"," ",dt.length===1?"it":"them"," (open lettering → Export) and re-upload before publishing so the bubble tails are seamless."]}),St&&ht>0&&$e.missing===0&&be.size===0&&d.jsxs("div",{className:"px-3 py-1 border-b border-border bg-green-600/10 text-[10px] text-green-700 flex items-center gap-1 flex-shrink-0","data-testid":"clean-assets-ready",children:[d.jsx("span",{"aria-hidden":!0,children:"✓"}),d.jsxs("span",{children:["All ",ht," clean image",ht===1?"":"s"," ","present — clean-asset generation is complete. Ready for lettering in OWS."]})]}),ne&&d.jsx("div",{className:"px-3 py-1 border-b border-border text-[10px] text-muted flex-shrink-0","data-testid":"sync-result",children:ne}),ft.length>0&&d.jsxs("div",{className:"px-3 py-2 border-b border-amber-500/40 bg-amber-500/10 text-[11px] flex-shrink-0","data-testid":"convert-artwork",children:[d.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[d.jsxs("span",{className:"font-medium text-amber-700","data-testid":"convert-artwork-count",children:[ft.length," PNG image",ft.length===1?"":"s"," found"]}),d.jsx("button",{onClick:()=>At(ft),disabled:M,"data-testid":"convert-all-btn",className:"ml-auto px-2 py-0.5 border border-amber-500/50 text-amber-800 rounded hover:bg-amber-500/20 disabled:opacity-50",children:M?"Converting…":"Convert all to WebP"})]}),d.jsx("p",{className:"mt-1 text-[10px] text-muted",children:"PNG artwork is fine while drafting. Convert it before lettering/export so PlotLink can publish it safely."}),C&&d.jsx("p",{className:"mt-1 text-[10px] text-muted","data-testid":"convert-result",children:C}),En.length>0&&d.jsxs("details",{className:"mt-1","data-testid":"convert-technical-details",children:[d.jsx("summary",{className:"text-[10px] text-muted cursor-pointer",children:"Technical details"}),d.jsx("ul",{className:"mt-1 ml-3 list-disc text-[10px] text-muted",children:En.map((L,oe)=>d.jsx("li",{children:L},oe))})]})]}),We&&We.length>0&&(()=>{const L=QD(We),oe=We.filter(Ee=>Ee.state==="missing");return d.jsxs("div",{className:"px-3 py-1.5 border-b border-border bg-surface/40 text-[10px] flex-shrink-0","data-testid":"asset-diagnostics",children:[d.jsxs("span",{className:"text-muted","data-testid":"asset-diag-summary",children:["Assets: ",L.uploaded," uploaded · ",L.finalReady," final ·"," ",L.cleanReady," clean · ",L.planned," planned",L.needsConversion>0?` · ${L.needsConversion} needs conversion`:"",L.missing>0?` · ${L.missing} missing`:""]}),oe.length>0&&d.jsx("ul",{className:"mt-1 ml-3 list-disc text-error","data-testid":"asset-diag-issues",children:oe.map(Ee=>d.jsx("li",{children:Ee.issue},Ee.cutId))})]})})(),d.jsx(ZD,{checklist:lt,issues:Se,onFinish:Ze,finishing:ce,progressText:K,canFinish:Ci,markdownReady:U.markdownReady,published:U.published}),d.jsxs("div",{className:"flex-1 min-h-56 overflow-y-auto p-3 space-y-3","data-testid":"lettering-review-board",children:[x.cuts.map((L,oe)=>{var Ee;return d.jsxs(w.Fragment,{children:[d.jsx(xy,{index:oe,beforeLabel:oe===0?"Episode opening":`After cut ${(Ee=x.cuts[oe-1])==null?void 0:Ee.id}`,afterLabel:`Before cut ${L.id}`,disabled:P,onAdd:()=>ze(oe)}),d.jsx(iM,{cut:L,storyName:e,plotFile:Qe,expanded:I===L.id,onToggle:()=>te(I===L.id?null:L.id),authFetch:i,onUpdated:()=>{Q(),Te(),Ue()},onOpenEditor:()=>D(L.id),detectedLocalClean:Le.has(L.id),onSyncClean:Bt,syncing:O,onAiDraft:()=>{Wt(L.id,{openEditor:!0})},aiDrafting:Y===L.id,staleMessages:be.get(L.id)??[],onRepairStale:hi,repairing:xe,conversionPng:Fi.get(L.id)??null,onConvert:vt,converting:M,rowRef:Me=>{Me?mi.current.set(L.id,Me):mi.current.delete(L.id)}})]},L.id)}),d.jsx(xy,{index:x.cuts.length,beforeLabel:`After cut ${(le=x.cuts[x.cuts.length-1])==null?void 0:le.id}`,afterLabel:"Episode ending",disabled:P,onAdd:()=>ze(x.cuts.length)})]})]})}function xy({index:e,beforeLabel:t,afterLabel:i,disabled:s,onAdd:a}){return d.jsxs("div",{className:"rounded border border-dashed border-border bg-surface/35 px-3 py-2 text-[11px] text-muted flex items-center gap-3","data-testid":`between-scene-slot-${e}`,children:[d.jsxs("span",{className:"min-w-0 flex-1",children:[d.jsx("span",{className:"font-medium text-foreground",children:"Between-scene lettering"}),d.jsxs("span",{className:"block truncate",children:[t," · ",i]})]}),d.jsx("button",{type:"button",onClick:a,disabled:s,className:"flex-shrink-0 rounded border border-accent/40 px-2.5 py-1 text-[11px] font-medium text-accent hover:bg-accent/5 disabled:opacity-50","data-testid":`add-between-scene-${e}`,children:"Add card"})]})}function Sm({coach:e,onAction:t,className:i="",showEmptyState:s=!1}){const[a,o]=w.useState(null),c=a!==null&&a===(e==null?void 0:e.prompt);return e===void 0?null:e?d.jsx("div",{className:`m-3 rounded-lg border border-accent/40 bg-accent/10 px-4 py-3 shadow-sm ${i}`,"data-testid":"workflow-coach","data-stage":e.stageLabel,"data-action-kind":e.actionKind,"data-ui-action":e.uiAction??"",children:d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("span",{className:"inline-flex rounded-full bg-background px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.14em] text-accent","data-testid":"workflow-coach-stage",children:e.stageLabel}),d.jsxs("p",{className:"mt-1 text-sm text-foreground","data-testid":"workflow-coach-action",children:[d.jsx("span",{className:"font-semibold",children:"Next: "}),d.jsx("span",{children:e.action})]}),c&&d.jsx("p",{className:"mt-1 text-[11px] font-medium text-accent",children:"Prompt copied."})]}),e.actionKind==="agent"&&e.prompt?d.jsx("button",{onClick:()=>{var p;if(!e.prompt)return;const h=e.prompt;(p=navigator.clipboard)==null||p.writeText(h).then(()=>o(h)).catch(()=>{})},"data-testid":"workflow-coach-copy",className:"flex-shrink-0 rounded bg-accent px-4 py-2.5 text-sm font-bold text-white shadow-sm transition-colors hover:bg-accent-dim",children:"Next Action"}):e.actionKind==="ui"&&e.uiAction?d.jsx("button",{onClick:()=>t(e.uiAction,e.episodeFile),"data-testid":"workflow-coach-do",className:"flex-shrink-0 rounded bg-accent px-4 py-2.5 text-sm font-bold text-white shadow-sm transition-colors hover:bg-accent-dim",children:"Next Action"}):null]})}):s?d.jsx("div",{className:`m-3 rounded-lg border border-green-700/25 bg-green-950/5 px-4 py-3 ${i}`,"data-testid":"workflow-coach","data-state":"complete",children:d.jsxs("div",{className:"flex items-start gap-3",children:[d.jsx("span",{className:"rounded-full bg-green-700/10 px-2 py-1 text-[10px] font-bold uppercase tracking-[0.16em] text-green-700",children:"Complete"}),d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("p",{className:"text-sm font-semibold text-foreground",children:"No next action available"}),d.jsx("p",{className:"mt-0.5 text-xs text-muted",children:"This workflow has no queued next step right now."})]})]})}):null}function nM({storyName:e,fileName:t,authFetch:i,refreshKey:s=0,onAction:a,showEmptyState:o=!1}){const[c,h]=w.useState(void 0),p=JSON.stringify([e,t??"",s]),[f,_]=w.useState(null);return f!==p&&(h(void 0),_(p)),w.useEffect(()=>{let x=!1;const b=t?`?focus=${encodeURIComponent(t)}`:"";return i(`/api/stories/${e}/progress${b}`).then(v=>v.ok?v.json():null).then(v=>{x||h((v==null?void 0:v.coach)??null)}).catch(()=>{}),()=>{x=!0}},[e,t,i,s]),d.jsx(Sm,{coach:c,onAction:a,showEmptyState:o})}const rM=1024*1024,sM=["image/webp","image/jpeg"],aM="Cover: WebP or JPEG, max 1MB, 600×900 portrait recommended. Use clean cover art — avoid unreadable AI text or broken lettering.";function lM(e){return e.attached?{state:"attached",label:"Cover attached to your story.",tone:"success"}:e.invalid?{state:"invalid",label:"Cover file can't be used — must be WebP or JPEG, max 1MB.",tone:"error"}:e.hasSelectedCover?{state:"selected",label:"Cover selected — it will be uploaded when you publish.",tone:"accent"}:{state:"none",label:"No cover yet — add one before publishing (recommended).",tone:"muted"}}function _y(e){return e.size>rM?"Image exceeds 1MB limit":sM.includes(e.type)?null:"Only WebP and JPEG images are accepted"}async function oM(e,t,i){const s=new FormData;s.append("file",i);const a=await e("/api/publish/upload-cover",{method:"POST",body:s});if(!a.ok)return null;const{cid:o}=await a.json();return!o||!(await e("/api/publish/update-storyline",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storylineId:t,coverCid:o})})).ok?null:o}function Pp(e){const t=e.match(/^#\s+(.+)$/m),i=t?t[1].trim():"";return i||null}function cM(e){return e.replace(/[-_]+/g," ").replace(/\s+/g," ").trim().split(" ").map(t=>t&&t[0].toUpperCase()+t.slice(1)).join(" ")}function zo(e,t){const i=(e??"").trim().toLowerCase();if(!i)return!0;if(t==="genesis.md")return i==="genesis";const s=t.match(/^(plot-\d+)\.md$/);return s?i===s[1].toLowerCase()||/^plot-\d+$/.test(i):!1}function uM(e){const t=e.match(/^plot-(\d+)\.md$/);if(!t)return null;const i=t[1];return`Episode ${i.length<2?i.padStart(2,"0"):i}`}function Ip(e){const t=(e??"").trim();return!!(!t||/^(?:episode|ep|chapter|ch|part|pt|plot)\.?\s*[-–—:#]?\s*\d+$/i.test(t)||/^\d+$/.test(t)||/^plot[-_\s]?\d+$/i.test(t))}function wm(e){var s;const t=Pp(e.fileContent);if(t)return!Ip(t);const i=((s=e.episodeTitle)==null?void 0:s.trim())||null;return!!i&&!Ip(i)}function Cm(e){const{fileName:t,fileContent:i,storySlug:s,structureContent:a,contentType:o,episodeTitle:c}=e,h=Pp(i);if(t==="genesis.md"){const p=a?Pp(a):null;return(h??p??cM(s)).slice(0,60)}if(h)return h.slice(0,60);if(o==="cartoon"){const p=c==null?void 0:c.trim(),f=uM(t);return((p||f)??t.replace(/\.md$/,"")).slice(0,60)}return t.replace(/\.md$/,"").slice(0,60)}function hM(e){return!!(e!=null&&e.txHash)&&(e==null?void 0:e.plotIndex)!=null&&e.plotIndex>0}function dM(e){return hM(e)&&(e==null?void 0:e.status)!=="published-not-indexed"}function by(e,t,i){if(e[t]==="cartoon"&&!i)return"cartoon"}function fM(e,t,i){return!(e!=="cartoon"||t||!i||i.startsWith("_new_"))}function Lf(e,t,i){if(e)return t[e]||i.get(e)||"fiction"}function Of(e){if(!e)return null;const t=Number(e);return Number.isFinite(t)?(t/1e18).toFixed(6):null}function pM(e){return!!e&&e.ready===!1}function mM(e){const t=Of(e.requiredBalance)??Of(e.creationFee),i=Of(e.ethBalance);return e.hasEnoughEth===!1&&t&&i?`Insufficient ETH: need at least ${t} ETH to publish; current balance is ${i} ETH.`+(e.address?` Top up the OWS wallet (${e.address}) and try again.`:" Top up the OWS wallet and try again."):e.error||"Publish preflight failed — the OWS wallet isn't ready to publish."}const gM={...gl,attributes:{...gl.attributes,img:["src","alt","title"]}},xM="https://ipfs.filebase.io/ipfs/";function _M(e){const t=[],i=/!\[([^\]]*)\]\(([^)]+)\)/g;let s;for(;(s=i.exec(e))!==null;)t.push({full:s[0],alt:s[1],url:s[2]});return t}function bM(e){const t=_M(e),i=[];for(const a of t)a.url.startsWith(xM)||i.push(`Non-IPFS image URL: ${a.url.length>60?a.url.slice(0,60)+"...":a.url}`);return e.match(/!\[[^\]]*\]\([^)]*$|!\[[^\]]*$(?!\])/gm)&&i.push("Malformed image markdown detected — check brackets and parentheses"),{count:t.length,warnings:i}}function vM({storyName:e,fileName:t,authFetch:i,onPublish:s,publishingFile:a,walletAddress:o,contentType:c="fiction",language:h,genre:p,isNsfw:f,hasGenesis:_=!1,onViewProgress:x,onOpenFile:b,onViewPublish:v,focusedLetteringMode:S=!1,focusedLetteringWorkspaceVisible:j=!1,onFocusedLetteringModeChange:R,onFocusedLetteringWorkspaceVisibleChange:E}){const[N,I]=w.useState(null),[te,F]=w.useState(!1),[D,ie]=w.useState("preview"),[fe,Se]=w.useState("publish"),[H,ce]=w.useState("text"),[W,K]=w.useState(null),X=w.useCallback((re,ye)=>{ie("edit"),K(ke=>({cutId:re,openEditor:ye,seq:((ke==null?void 0:ke.seq)??0)+1}))},[]),[U,A]=w.useState(""),[O,$]=w.useState(!1),[xe,T]=w.useState(!1),[M,G]=w.useState(!1),[C,V]=w.useState(null),[ne,ae]=w.useState(""),[Y,he]=w.useState(""),[_e,Be]=w.useState(!1),[Le,je]=w.useState(null),[be,tt]=w.useState(0),[St,ot]=w.useState(0),[We,Mt]=w.useState(null),[He,xt]=w.useState(null),[Ae,Kt]=w.useState(null),[mi,wt]=w.useState(0),Qe=w.useRef(null),Q=w.useRef(!1),[ge,Te]=w.useState(!1),[Ue,it]=w.useState(dl[0]),[Wt,ui]=w.useState(ts[0]),[Bt,vt]=w.useState(!1),[At,Ze]=w.useState(null),[hi,P]=w.useState(null),[we,ze]=w.useState(!1),[Re,Ge]=w.useState(!1),[$e,ht]=w.useState(!1),[dt,lt]=w.useState(null),[Vt,Ci]=w.useState(!1),ft=w.useRef(null),Fi=w.useRef(null),[En,ln]=w.useState(!1),[Un,on]=w.useState(null),[gn,cn]=w.useState(null),[pr,Lt]=w.useState("unknown"),le=w.useRef(!1),[L,oe]=w.useState(!1),[Ee,Me]=w.useState(!1),[Ne,Pe]=w.useState(null),[qe,nt]=w.useState([]),[Ve,Et]=w.useState(null),Nt=w.useRef(null),Gt=w.useRef(null),Rt=w.useCallback(async()=>{if(!e||!t){I(null);return}const re=`${e}/${t}`,ye=Gt.current!==re;ye&&(Gt.current=re);try{const ke=await i(`/api/stories/${e}/${t}`);if(ke.ok){const Je=await ke.json();I(Je),(ye||!Q.current)&&(A(Je.content??""),ye&&(T(!1),Q.current=!1))}}catch{}},[e,t,i]);w.useEffect(()=>{F(!0),Rt().finally(()=>F(!1))},[Rt]),w.useEffect(()=>{if(!e||!t||D==="edit"&&xe)return;const re=setInterval(Rt,3e3);return()=>clearInterval(re)},[e,t,Rt,D,xe]);const[ki,mr]=w.useState(null),Jt=c==="cartoon"&&t==="genesis.md";w.useEffect(()=>{if(!Jt||!e){mr(null);return}let re=!1;return i(`/api/stories/${e}/cuts/genesis`).then(ye=>ye.ok?ye.json():null).then(ye=>{re||mr(ye?Op(ye.cuts||[]):null)}).catch(()=>{re||mr(null)}),()=>{re=!0}},[Jt,e,i]);const qi=c==="cartoon"&&!!t&&/^plot-\d+\.md$/.test(t);w.useEffect(()=>{if(!qi||!e||!t){je(null),tt(0),ot(0),Mt(null);return}let re=!1;const ye=t.replace(/\.md$/,"");return Mt(null),(async()=>{try{const[ke,Je]=await Promise.all([i(`/api/stories/${e}/${t}`),i(`/api/stories/${e}/cuts/${ye}`)]);if(re)return;if(!Je.ok){je("error"),tt(0),ot(0),Mt(null);return}const Pt=await Je.json(),Ni=Pt.cuts||[],Gn=ke.ok?(await ke.json()).content??"":"",or=WS(Gn,Ni);re||(je(or.stage),tt(or.awaitingCount),ot(or.totalCuts),Mt(Op(Ni)),Kt(typeof Pt.title=="string"?Pt.title:null))}catch{re||(je("error"),tt(0),ot(0),Mt(null))}})(),()=>{re=!0}},[qi,e,t,i,N==null?void 0:N.content,N==null?void 0:N.status,mi]),w.useEffect(()=>{if(!e){xt(null);return}let re=!1;return i(`/api/stories/${e}/structure.md`).then(ye=>ye.ok?ye.json():null).then(ye=>{re||xt((ye==null?void 0:ye.content)??null)}).catch(()=>{}),()=>{re=!0}},[e,i]),w.useEffect(()=>{if(!e)return;const re=Cu(p);let ye=re??"";if(!re&&He){const Je=He.match(/\*{0,2}genre\*{0,2}[:\s]+(.+)/i);Je&&(ye=Cu(Je[1].replace(/\*+/g,"").trim())??"")}ae(ye);let ke=h&&ts.find(Je=>Je.toLowerCase()===h.toLowerCase())||"";if(!ke&&He){const Je=He.match(/\*{0,2}language\*{0,2}[:\s]+(.+)/i);Je&&(ke=ts.find(Pt=>Pt.toLowerCase()===Je[1].replace(/\*+/g,"").trim().toLowerCase())||"")}he(ke),Be(f??!1)},[e,p,h,f,He]);const $n=w.useCallback(re=>{e&&i(`/api/stories/${e}/publish-metadata`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(re)}).catch(()=>{})},[e,i]),gr=w.useCallback(async()=>{if(!(!e||!t)){$(!0);try{(await i(`/api/stories/${e}/${t}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:U})})).ok&&(T(!1),Q.current=!1,I(ye=>ye&&{...ye,content:U}))}catch{}$(!1)}},[e,t,i,U]),ei=w.useCallback(async()=>{if(!e||!t)return;const re=t.replace(/\.md$/,"");try{(await i(`/api/stories/${e}/cuts/${re}/generate-markdown`,{method:"POST"})).ok&&(await Rt(),wt(ke=>ke+1))}catch{}},[e,t,i,Rt]),Br=w.useCallback((re,ye)=>{if(re==="view-progress"){x==null||x();return}if(ye&&ye!==t){b==null||b(ye);return}switch(re){case"open-cuts":case"open-lettering":case"upload":case"refresh-assets":ie("edit"),ce("cuts");break;case"generate-markdown":ei();break;case"publish":ie("preview");break}},[t,x,b,ei]),Fn=w.useCallback(re=>{var Je;const ye=(Je=re.target.files)==null?void 0:Je[0];if(!ye)return;le.current=!0,on(null),cn(null);const ke=_y(ye);if(ke){Ze(null),P(Pt=>(Pt&&URL.revokeObjectURL(Pt),null)),ft.current&&(ft.current.value=""),lt(ke),Lt("invalid");return}Ze(ye),P(Pt=>(Pt&&URL.revokeObjectURL(Pt),URL.createObjectURL(ye))),lt(null),Lt("selected")},[]),ar=w.useCallback(async re=>{var ke;const ye=(ke=re.target.files)==null?void 0:ke[0];if(Fi.current&&(Fi.current.value=""),!(!ye||!e)){le.current=!0,on(null),ln(!0),lt(null);try{let Je;try{Je=await Ku(ye)}catch(vr){Ze(null),P(Yi=>(Yi&&URL.revokeObjectURL(Yi),null)),lt(vr instanceof Error?vr.message:"Could not import image");return}const Pt=Je.type==="image/jpeg"?"jpg":"webp",Ni=new File([Je],`cover.${Pt}`,{type:Je.type}),Gn=new FormData;Gn.append("file",Ni);const or=await i(`/api/stories/${e}/import-cover`,{method:"POST",body:Gn});if(!or.ok){const vr=await or.json().catch(()=>({}));lt(vr.error||"Cover import failed");return}Ze(Ni),P(vr=>(vr&&URL.revokeObjectURL(vr),URL.createObjectURL(Ni))),cn(null),Lt("selected"),lt(null)}catch{lt("Cover import failed")}finally{ln(!1)}}},[e,i]),Wi=w.useCallback(async re=>{if(re.size>1024*1024){Pe("Image exceeds 1MB limit");return}if(!["image/webp","image/jpeg"].includes(re.type)){Pe("Only WebP and JPEG images are accepted");return}Me(!0),Pe(null);try{const ke=new FormData;ke.append("file",re);const Je=await i("/api/publish/upload-plot-image",{method:"POST",body:ke});if(!Je.ok){const Ni=await Je.json();throw new Error(Ni.error||"Upload failed")}const Pt=await Je.json();nt(Ni=>[...Ni,{cid:Pt.cid,url:Pt.url}])}catch(ke){Pe(ke instanceof Error?ke.message:"Upload failed")}finally{Me(!1),Nt.current&&(Nt.current.value="")}},[i]),Ct=w.useCallback(re=>{var ke;const ye=(ke=re.target.files)==null?void 0:ke[0];ye&&Wi(ye)},[Wi]),qn=w.useCallback(async()=>{if(N!=null&&N.storylineId){ze(!0),lt(null),Ci(!1);try{let re;if(At){const ke=new FormData;ke.append("file",At);const Je=await i("/api/publish/upload-cover",{method:"POST",body:ke});if(!Je.ok){const Ni=await Je.json();throw new Error(Ni.error||"Cover upload failed")}re=(await Je.json()).cid}const ye=await i("/api/publish/update-storyline",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storylineId:N.storylineId,...re!==void 0&&{coverCid:re},genre:Ue,language:Wt,isNsfw:Bt})});if(!ye.ok){const ke=await ye.json();throw new Error(ke.error||"Update failed")}Ci(!0),Ze(null),re!==void 0&&(ht(!0),P(ke=>(ke&&URL.revokeObjectURL(ke),null)),Lt("unknown"),ft.current&&(ft.current.value="")),setTimeout(()=>Ci(!1),3e3)}catch(re){lt(re instanceof Error?re.message:"Update failed")}finally{ze(!1)}}},[N==null?void 0:N.storylineId,At,Ue,Wt,Bt,i]);w.useEffect(()=>{Te(!1),Ze(null),P(null),lt(null),Ci(!1),Ge(!1),oe(!1),nt([]),Pe(null),on(null),cn(null),Lt("unknown"),le.current=!1,ce("text")},[e,t]),w.useEffect(()=>{if(t!=="genesis.md"||!e||!N||N.storylineId||N.status==="published"||N.status==="published-not-indexed"||le.current)return;let re=!1;return(async()=>{try{const ye=await i(`/api/stories/${e}/cover-asset`);if(re||!ye.ok)return;const ke=await ye.json();if(re)return;if(!(ke!=null&&ke.found)){Lt("none");return}if(!ke.valid){cn(ke.error||"Detected cover asset is invalid and was not used"),Lt("invalid");return}const Je=await i(`/api/stories/${e}/asset/${ke.path.replace(/^assets\//,"")}`);if(re||!Je.ok)return;const Pt=await Je.blob(),Ni=new File([Pt],ke.path.split("/").pop()||"cover.webp",{type:ke.type});if(_y(Ni)||re||le.current)return;Ze(Ni),P(Gn=>(Gn&&URL.revokeObjectURL(Gn),URL.createObjectURL(Ni))),on(ke.path),Lt("detected")}catch{}})(),()=>{re=!0}},[e,t,N,N==null?void 0:N.status,N==null?void 0:N.storylineId,i]),w.useEffect(()=>{if(!ge||!(N!=null&&N.storylineId))return;Ge(!1);const re="https://plotlink.xyz";let ye=!1;return fetch(`${re}/api/storyline/${N.storylineId}`).then(ke=>ke.ok?ke.json():null).then(ke=>{if(!ye){if(!ke){lt("Could not load current story metadata");return}if(ke.genre){const Je=Cu(ke.genre);Je&&it(Je)}if(ke.language){const Je=ts.find(Pt=>Pt.toLowerCase()===ke.language.toLowerCase());Je&&ui(Je)}ke.isNsfw!==void 0&&vt(!!ke.isNsfw),ht(!!(ke.coverCid||ke.coverUrl||ke.cover)),Ge(!0)}}).catch(()=>{ye||lt("Could not load current story metadata")}),()=>{ye=!0}},[ge,N==null?void 0:N.storylineId]),w.useEffect(()=>{if(D!=="edit")return;const re=ye=>{(ye.metaKey||ye.ctrlKey)&&ye.key==="s"&&(ye.preventDefault(),gr())};return window.addEventListener("keydown",re),()=>window.removeEventListener("keydown",re)},[D,gr]),w.useEffect(()=>{if((N==null?void 0:N.status)!=="published-not-indexed"||!N.publishedAt)return;const re=new Date(N.publishedAt).getTime(),ye=300*1e3,ke=()=>{const Pt=Math.max(0,ye-(Date.now()-re));V(Pt)};ke();const Je=setInterval(ke,1e3);return()=>clearInterval(Je)},[N==null?void 0:N.status,N==null?void 0:N.publishedAt]);const ya=C!==null&&C<=0,Lr=C!==null&&C>0?`${Math.floor(C/6e4)}:${String(Math.floor(C%6e4/1e3)).padStart(2,"0")}`:null;if(!e||!t)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted",children:d.jsxs("div",{className:"text-center",children:[d.jsx("p",{className:"text-lg font-serif",children:"Select a file to preview"}),d.jsx("p",{className:"text-sm mt-1",children:"Click a story file in the sidebar"})]})});if(te&&!N)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted",children:"Loading..."});const xr=(D==="edit"?U:(N==null?void 0:N.content)??"").length,Ei=t==="genesis.md",gi=t?/^plot-\d+\.md$/.test(t):!1,Gi=c==="cartoon"&&gi,Nn=c==="cartoon"&&Ei,Or=Nn||Gi,jn=(N==null?void 0:N.status)==="published"||(N==null?void 0:N.status)==="published-not-indexed",Sa=S&&Or,yl=Nn?ki?ki.total:null:Gi?Le===null?null:St:null,_r=lD({fileName:t??"",contentType:c,hasGenesis:_,isPublished:jn,cutCount:yl,cutProgress:Nn?ki:null}),Go=(Nn||Gi)&&!jn,as=Go?Cm({fileName:t,fileContent:(N==null?void 0:N.content)??"",storySlug:e??"",structureContent:He,contentType:"cartoon",episodeTitle:Ae}):null,wa=!!as&&zo(as,t),Ca=Gi&&!jn&&!wm({fileContent:(N==null?void 0:N.content)??"",episodeTitle:Ae}),qs=Nn&&!jn?bm((N==null?void 0:N.content)??""):null,Yo=!!qs&&qs.blockers.length>0,ka="w-full max-w-[32rem] rounded-xl border px-3 py-3",lr={muted:"text-muted",accent:"text-accent",error:"text-error",success:"text-green-700"},Ea=re=>{if(!Nn)return null;const ye=lM({hasSelectedCover:!!At,invalid:pr==="invalid",attached:re});return d.jsxs("div",{className:"flex flex-col gap-0.5","data-testid":"cartoon-cover-status","data-state":ye.state,children:[d.jsx("span",{className:`text-[11px] font-medium ${lr[ye.tone]}`,children:ye.label}),d.jsxs("details",{className:"text-[10px] text-muted","data-testid":"cover-details",children:[d.jsx("summary",{className:"cursor-pointer select-none",children:"Cover tips"}),d.jsx("span",{className:"block mt-0.5","data-testid":"cartoon-cover-guidance",children:aM})]})]})},Ws=wa||Ca,ls=()=>{if(!Go||!as)return null;const re=Ei?"Story title":"Episode title";return d.jsxs("div",{className:"flex flex-col gap-0.5","data-testid":"publish-title-preview","data-raw":wa?"true":"false","data-blocked":Ws?"true":"false",children:[d.jsxs("span",{className:"text-[11px] text-foreground",children:[d.jsxs("span",{className:"font-medium",children:[re,":"]})," ",d.jsx("span",{className:Ws?"text-error font-medium":"text-foreground",children:as})]}),wa?d.jsxs("span",{className:"text-[10px] text-error","data-testid":"publish-title-raw-error",children:["This would publish as a raw filename."," ",Ei?"Add a real “# Title” heading to genesis.md":"Set a title in the cut plan (or add a “# Title” to the episode)"," ","before publishing."]}):Ca?d.jsxs("span",{className:"text-[10px] text-error","data-testid":"publish-title-episode-required",children:["“",as,"” is a generic placeholder, not a reader-facing title, so it can’t be published. Set a real episode title in the cut plan (or add a “# Title” to the episode) — e.g. “Episode 01 — The Couple Coupon” — before publishing."]}):null]})},os=()=>qs?d.jsxs("div",{className:"flex flex-col gap-1 rounded border border-border bg-surface/50 p-2","data-testid":"cartoon-genesis-readiness","data-blocked":Yo?"true":"false",children:[d.jsx("span",{className:"text-[11px] font-medium text-foreground",children:"Story opening (Prologue)"}),d.jsx("span",{className:"text-[10px] text-muted","data-testid":"genesis-readiness-hint",children:"Genesis is the first thing readers see. Write it as the story opening/prologue, not a synopsis — set up the premise and stakes, then bridge into Episode 01."}),qs.blockers.map((re,ye)=>d.jsx("span",{className:"text-[10px] text-error","data-testid":"genesis-readiness-blocker",children:re},`b-${ye}`)),qs.warnings.map((re,ye)=>d.jsx("span",{className:"text-[10px] text-amber-600","data-testid":"genesis-readiness-warning",children:re},`w-${ye}`))]}):null,cs=Ei||gi?1e4:null,us=!jn&&cs!==null&&xr>cs,Ko=(N==null?void 0:N.content)??"",br=jn?{count:0,warnings:[]}:bM(Ko),Wn=d.jsxs("div",{className:"flex-1 min-h-0 flex flex-col overflow-hidden","data-testid":"prose-editor-shell",style:{background:"var(--paper-bg)"},children:[d.jsx("textarea",{ref:Qe,value:U,onChange:re=>{A(re.target.value),T(!0),Q.current=!0},className:"flex-1 min-h-0 w-full resize-none px-4 py-3 text-sm leading-relaxed focus:outline-none",style:{fontFamily:'"Geist Mono", ui-monospace, monospace',background:"var(--paper-bg)",color:"var(--text)"},spellCheck:!1,"data-testid":"prose-editor-textarea"}),d.jsxs("div",{className:"shrink-0 px-3 py-1.5 border-t border-border flex items-center justify-between bg-surface/95","data-testid":"prose-editor-savebar",children:[d.jsx("span",{className:"text-xs text-muted",children:xe?"Unsaved changes":"No changes"}),d.jsx("button",{onClick:gr,disabled:!xe||O,className:"px-3 py-1 bg-accent text-white text-xs rounded hover:bg-accent-dim disabled:opacity-50 disabled:cursor-not-allowed",children:O?"Saving...":"Save"})]})]});return d.jsxs("div",{className:"h-full min-h-0 flex flex-col",children:[!Sa&&d.jsxs("div",{className:"border-b border-border",children:[d.jsxs("div",{className:"px-3 py-1.5 flex items-center justify-between",children:[d.jsxs("div",{className:"flex items-center gap-2 text-xs font-mono text-muted",children:[x&&d.jsx("button",{onClick:x,"data-testid":"view-progress-btn",className:"text-accent hover:underline font-sans",title:"Story progress overview",children:"← Progress"}),d.jsxs("span",{children:[e,"/",t]}),(N==null?void 0:N.status)==="published"&&d.jsx("span",{className:"text-green-700 font-medium",children:"Published"}),(N==null?void 0:N.status)==="published-not-indexed"&&d.jsx("span",{className:"text-amber-700 font-medium",title:N.indexError,children:"Published (not indexed)"}),(N==null?void 0:N.status)==="pending"&&d.jsx("span",{className:"text-amber-700 font-medium",children:"Pending"})]}),d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsxs("span",{className:`text-xs font-mono ${us?"text-error font-medium":"text-muted"}`,children:[xr.toLocaleString(),cs!==null?`/${cs.toLocaleString()}`:" chars"]}),us&&d.jsxs("span",{className:"text-error text-xs font-medium",children:[(xr-cs).toLocaleString()," over limit"]})]})]}),d.jsxs("div",{className:"flex px-3 gap-1",children:[d.jsx("button",{onClick:()=>ie("preview"),className:`px-3 py-1 text-xs font-medium border-b-2 transition-colors ${D==="preview"?"border-accent text-accent":"border-transparent text-muted hover:text-foreground"}`,children:"Preview"}),d.jsxs("button",{onClick:()=>ie("edit"),className:`px-3 py-1 text-xs font-medium border-b-2 transition-colors ${D==="edit"?"border-accent text-accent":"border-transparent text-muted hover:text-foreground"}`,children:["Edit",xe&&d.jsx("span",{className:"ml-1 text-amber-600",children:"*"})]})]})]}),!Sa&&c==="cartoon"&&e&&t&&d.jsx(nM,{storyName:e,fileName:t,authFetch:i,refreshKey:mi,onAction:Br,showEmptyState:!0}),D==="preview"?Gi?d.jsxs("div",{className:"flex-1 min-h-0 flex flex-col",style:{background:"var(--paper-bg)"},children:[d.jsxs("div",{className:"flex gap-1 px-3 py-1 border-b border-border",children:[d.jsx("button",{"data-testid":"cartoon-mode-publish",onClick:()=>Se("publish"),className:`px-2 py-0.5 text-[11px] rounded ${fe==="publish"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Publish Preview"}),d.jsx("button",{"data-testid":"cartoon-mode-inspect",onClick:()=>Se("inspect"),className:`px-2 py-0.5 text-[11px] rounded ${fe==="inspect"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Cut Inspector"})]}),d.jsx("div",{className:"flex-1 min-h-0",children:fe==="publish"?d.jsx(hD,{content:(N==null?void 0:N.content)??"",stage:Le}):d.jsx(K3,{storyName:e,fileName:t,authFetch:i,onEditCut:X})})]}):d.jsx("div",{className:"flex-1 min-h-0 overflow-y-auto px-6 py-4",style:{background:"var(--paper-bg)"},children:N!=null&&N.content?d.jsx("div",{className:"prose max-w-none",children:d.jsx(rS,{remarkPlugins:[aS,AS],rehypePlugins:[[BS,gM]],children:N.content})}):d.jsx("p",{className:"text-muted italic",children:"No content"})}):Gi?d.jsx("div",{className:"flex-1 min-h-[22rem] overflow-hidden",style:{background:"var(--paper-bg)"},children:d.jsx(gy,{storyName:e,fileName:t,authFetch:i,language:h,onCutsChanged:()=>wt(re=>re+1),focusRequest:W,onFocusHandled:()=>K(null),onFocusedLetteringModeChange:R,workspaceVisible:j,onWorkspaceVisibleChange:E})}):Nn?d.jsxs("div",{className:"flex-1 min-h-0 flex flex-col",style:{background:"var(--paper-bg)"},children:[d.jsxs("div",{className:"flex gap-1 px-3 py-1 border-b border-border",children:[d.jsx("button",{"data-testid":"genesis-edit-mode-text",onClick:()=>ce("text"),className:`px-2 py-0.5 text-[11px] rounded ${H==="text"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Opening text"}),d.jsx("button",{"data-testid":"genesis-edit-mode-cuts",onClick:()=>ce("cuts"),className:`px-2 py-0.5 text-[11px] rounded ${H==="cuts"?"bg-accent text-white":"text-muted hover:text-foreground"}`,children:"Cuts"})]}),d.jsx("div",{className:"flex-1 min-h-0",children:H==="cuts"?d.jsx(gy,{storyName:e,fileName:t,authFetch:i,language:h,onCutsChanged:()=>wt(re=>re+1),focusRequest:W,onFocusHandled:()=>K(null),onFocusedLetteringModeChange:R,workspaceVisible:j,onWorkspaceVisibleChange:E}):Wn})]}):Wn,!Sa&&d.jsx("div",{className:"shrink-0 px-3 py-2 border-t border-border flex items-center justify-between bg-surface/95","data-testid":"preview-panel-footer",children:t==="structure.md"?d.jsx("p",{className:"text-muted text-xs italic","data-testid":"footer-guidance",children:_r}):(N==null?void 0:N.status)==="published-not-indexed"?d.jsxs("div",{className:"flex flex-col gap-1",children:[d.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[d.jsx("span",{className:"text-amber-700",children:"Published on-chain but not indexed on PlotLink"}),!ya&&d.jsx("button",{onClick:async()=>{if(!(!e||!t||!N.txHash)){G(!0);try{(await(await i("/api/publish/retry-index",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storyName:e,fileName:t,txHash:N.txHash,content:N.content,storylineId:N.storylineId})})).json()).ok&&(await i(`/api/stories/${e}/${t}/publish-status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({txHash:N.txHash,storylineId:N.storylineId,contentCid:"",gasCost:""})}),Rt())}catch{}G(!1)}},disabled:M,className:"px-3 py-1 bg-accent text-white text-xs rounded hover:bg-accent-dim disabled:opacity-50",children:M?"Retrying...":`Retry Index${Lr?` (${Lr})`:""}`}),gi&&d.jsx("button",{onClick:()=>{!e||!t||!window.confirm(`This episode is already on-chain — try “Retry Index” first.
Retry Publish creates a NEW on-chain transaction and a SECOND, permanent chapter on PlotLink (PlotLink content is immutable). Only do this if the chapter never appeared after indexing.
@@ -138,4 +138,4 @@ Create a new on-chain chapter anyway?`)||s==null||s(e,t,ne,Y,_e)},disabled:!!a,"
Please verify illustrations appear correctly in Preview before continuing.
Publish now?`;if(!window.confirm(ye))return}const re=Ei?At:null;re?await(s==null?void 0:s(e,t,ne,Y,_e,re))&&(le.current=!0,on(null),cn(null),Lt("unknown"),Ze(null),P(ke=>(ke&&URL.revokeObjectURL(ke),null)),ft.current&&(ft.current.value="")):s==null||s(e,t,ne,Y,_e)},disabled:!!a||us||Ws||Yo||Ei&&(!ne||!Y)||Gi&&Le!=="ready",className:"px-4 py-1.5 bg-accent text-white text-sm rounded hover:bg-accent-dim disabled:opacity-50 disabled:cursor-not-allowed",children:a===t?"Publishing...":"Publish to PlotLink"}),Ei&&c==="cartoon"&&(!ne||!Y)&&d.jsx("span",{className:"text-amber-600 text-xs","data-testid":"cartoon-metadata-needs-story-info",children:"Set the genre and language in Story Info before publishing"}),Ei&&c!=="cartoon"&&!ne&&d.jsx("span",{className:"text-amber-600 text-xs","data-testid":"genre-needs-metadata",children:"Needs metadata — choose a genre before publishing"}),Ei&&c!=="cartoon"&&ne&&!Y&&d.jsx("span",{className:"text-amber-600 text-xs","data-testid":"language-needs-metadata",children:"Needs metadata — choose a language before publishing"}),us&&d.jsx("span",{className:"text-error text-xs",children:"Reduce content to publish"}),Gi&&Le==="error"&&d.jsx("span",{className:"text-error text-xs","data-testid":"publish-disabled-reason",children:"Fix the issues below before publishing"}),Gi&&Le==="planning"&&d.jsx("span",{className:"text-muted text-xs","data-testid":"publish-disabled-reason",children:"Prepare the episode for publish to continue"}),Gi&&Le==="awaiting-upload"&&d.jsxs("span",{className:"text-muted text-xs","data-testid":"publish-disabled-reason",children:["Upload all final images, then “Prepare episode for publish” — ",be," of ",St," ","still need an uploaded image"]})]}),Or&&d.jsx("button",{onClick:()=>v==null?void 0:v(),"data-testid":"cartoon-review-publish",className:"self-start rounded border border-accent/40 px-3 py-1 text-xs text-accent hover:bg-accent/5 transition-colors",children:"Review publish checklist →"}),br.warnings.length>0&&d.jsx("div",{className:"flex flex-col gap-0.5",children:br.warnings.map((re,ye)=>d.jsx("span",{className:"text-amber-600 text-xs",children:re},ye))}),Ei&&c!=="cartoon"&&d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsxs("label",{className:"flex items-center gap-1.5 text-xs text-muted cursor-pointer",children:[d.jsx("input",{type:"checkbox",checked:_e,onChange:re=>{Be(re.target.checked),$n({isNsfw:re.target.checked})},className:"rounded border-border"}),"This story contains adult content (18+)"]}),_e&&d.jsx("span",{className:"text-xs text-amber-600",children:"Adult content will be hidden from the default browse view."})]})]})})]})}function yM(e){if(e.cover!=="present")return e.cover==="invalid"?"Replace the cover image - it must be a valid WebP or JPEG.":"Add a cover image before publishing.";const t=[];return e.metadata.language||t.push("language"),e.metadata.genre||t.push("genre"),e.metadata.title||t.push("title"),`Add the story ${t.join(" and ")||"details"} before publishing.`}function ZS(e){const t=e.coach??null,i=e.metadata,s=e.setup.hasStructure,a=e.setup.hasGenesis,o=e.cover==="present",c=!i.title||!i.language||!i.genre,h=e.episodes.find(f=>!f.published)??null,p=!!h&&h.state!=="ready";return s?a?c?"story-info":p&&(t!=null&&t.episodeFile)?t.episodeFile:o?(t==null?void 0:t.episodeFile)??null:"story-info":"genesis.md":"whitepaper"}function SM({progress:e,onOpenStoryInfo:t}){return d.jsx("div",{className:"m-3 rounded-lg border border-accent/40 bg-accent/10 px-4 py-3 shadow-sm","data-testid":"story-info-cta",children:d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsxs("div",{className:"min-w-0 flex-1",children:[d.jsx("span",{className:"inline-flex rounded-full bg-background px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.14em] text-accent",children:"Story info"}),d.jsxs("p",{className:"mt-1 text-sm text-foreground","data-testid":"story-info-next-action",children:[d.jsx("span",{className:"font-semibold",children:"Next: "}),d.jsx("span",{children:yM(e)})]})]}),d.jsx("button",{type:"button",onClick:t,disabled:!t,className:"flex-shrink-0 rounded bg-accent px-4 py-2.5 text-sm font-bold text-white shadow-sm transition-colors hover:bg-accent-dim disabled:cursor-not-allowed disabled:opacity-50","data-testid":"story-info-next-action-btn",children:"Next Action"})]})})}function QS({progress:e,onCoachAction:t,onOpenStoryInfo:i}){return ZS(e)==="story-info"?d.jsx(SM,{progress:e,onOpenStoryInfo:i}):d.jsx(Sm,{coach:e.coach??null,showEmptyState:!0,onAction:t})}function wM({storyName:e,authFetch:t,refreshKey:i=0,onCoachAction:s,onOpenStoryInfo:a}){const[o,c]=w.useState(void 0),h=JSON.stringify([e,i]),[p,f]=w.useState(null);return p!==h&&(c(void 0),f(h)),w.useEffect(()=>{let _=!1;return t(`/api/stories/${e}/progress`).then(x=>x.ok?x.json():null).then(x=>{_||c(CM(x)?x:null)}).catch(()=>{_||c(null)}),()=>{_=!0}},[e,t,i]),o===void 0?null:o?d.jsx(QS,{progress:o,onCoachAction:s,onOpenStoryInfo:a}):d.jsx(Sm,{coach:null,showEmptyState:!0,onAction:s})}function CM(e){return!!e&&!!e.metadata&&!!e.setup&&Array.isArray(e.episodes)}function kM({storyName:e,authFetch:t,onOpenFile:i,onOpenStoryInfo:s,refreshKey:a=0}){const[o,c]=w.useState(null),[h,p]=w.useState(!0);return w.useEffect(()=>{let f=!1;return(async()=>{p(!0);try{const x=await t(`/api/stories/${e}/progress`),b=x.ok?await x.json():null;f||(c(b),p(!1))}catch{f||(c(null),p(!1))}})(),()=>{f=!0}},[e,t,a]),h?d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm","data-testid":"progress-loading",children:"Loading progress…"}):!o||!o.metadata||!Array.isArray(o.episodes)?d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm",children:"Could not load story progress."}):o.contentType==="cartoon"?d.jsx(DM,{progress:o,storyName:e,onOpenFile:i,onOpenStoryInfo:s}):d.jsx(LM,{progress:o,storyName:e,onOpenFile:i})}function mu({label:e,value:t,tone:i="muted"}){const s=i==="ok"?"text-green-700":i==="warn"?"text-amber-700":"text-muted";return d.jsxs("span",{className:"text-[11px]",children:[d.jsxs("span",{className:"text-muted",children:[e,": "]}),d.jsx("span",{className:`font-medium ${s}`,children:t})]})}function JS({progress:e}){const t=e.contentType==="cartoon",i=e.cover==="present"?"ok":e.cover==="invalid"?"warn":"muted";return d.jsxs("div",{className:"px-4 py-3 border-b border-border",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("h2",{className:"text-base font-serif text-foreground truncate",children:e.metadata.title||e.name}),d.jsx("span",{className:`rounded px-1.5 py-0.5 text-[10px] font-medium ${t?"bg-accent/10 text-accent":"bg-surface text-muted"}`,children:t?"Cartoon":"Fiction"})]}),d.jsxs("div",{className:"mt-1.5 flex flex-wrap gap-x-3 gap-y-1",children:[d.jsx(mu,{label:"Language",value:e.metadata.language||"Needs metadata",tone:e.metadata.language?"muted":"warn"}),d.jsx(mu,{label:"Genre",value:e.metadata.genre||"Needs metadata",tone:e.metadata.genre?"muted":"warn"}),e.metadata.isNsfw!=null&&d.jsx(mu,{label:"Adult",value:e.metadata.isNsfw?"Yes (18+)":"No"}),t&&d.jsx(mu,{label:"Cover",value:e.cover==="present"?"Ready":e.cover==="invalid"?"Invalid":"Missing",tone:i})]})]})}const e1={published:"✓",done:"●",current:"◉","needs-action":"●","not-started":"○"},Ou={published:"text-green-700",done:"text-green-700",current:"text-accent","needs-action":"text-amber-700","not-started":"text-muted"},t1={published:"Published",done:"Complete",current:"Current","needs-action":"Needs action","not-started":"Not started"},EM={done:"✓",current:"◓",todo:"○"},NM={done:"text-green-700",current:"text-accent",todo:"text-muted"};function i1({item:e}){return d.jsxs("div",{className:"flex items-baseline gap-2 text-[11px]","data-testid":"checklist-item","data-status":e.status,children:[d.jsx("span",{className:`${NM[e.status]} flex-shrink-0`,"aria-hidden":!0,children:EM[e.status]}),d.jsx("span",{className:e.status==="todo"?"text-muted":"text-foreground",children:e.label}),e.detail&&d.jsxs("span",{className:"text-muted",children:["· ",e.detail]})]})}function vy({index:e,title:t,status:i,items:s,fileName:a,openFile:o}){const c=d.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[d.jsx("span",{className:`flex-shrink-0 ${Ou[i]}`,"aria-hidden":!0,children:e1[i]}),d.jsxs("span",{className:"text-xs font-medium text-foreground truncate",children:[e,". ",t]}),a&&d.jsx("span",{className:"text-[10px] text-muted truncate",children:a}),d.jsx("span",{className:`ml-auto text-[10px] font-medium ${Ou[i]} flex-shrink-0`,children:t1[i]})]});return d.jsxs("div",{className:"px-4 py-2.5 border-b border-border","data-testid":`workflow-section-${e}`,"data-status":i,children:[o?d.jsx("button",{onClick:o,className:"w-full text-left rounded hover:bg-surface -mx-1 px-1 py-0.5","data-testid":`section-open-${e}`,children:c}):c,d.jsx("div",{className:"mt-1.5 ml-1 flex flex-col gap-1 border-l border-border pl-3",children:s.map((h,p)=>d.jsx(i1,{item:h},p))})]})}function jM(e,t){return e.published?"published":t?"current":e.state==="placeholder"?"not-started":(e.state==="blocked","needs-action")}function TM(e,t=!0){const i=e.checklist??[],s=[];if(e.kind==="genesis"&&s.push({label:"Opening text",status:t?"done":"todo"}),i.length===0)return s.push({label:"Cut plan",status:"todo"}),s.push({label:"Clean artwork",status:"todo"}),s;for(const a of i)s.push(AM(a));return s}function AM(e){return{label:e.label,status:e.status,detail:e.detail}}const RM={file:"genesis.md",label:"Episode 1 / Genesis",kind:"genesis",title:null,state:"placeholder",summary:"",published:!1,checklist:[],cuts:null};function DM({progress:e,storyName:t,onOpenFile:i,onOpenStoryInfo:s}){const a=e.metadata,o=e.setup.hasStructure,c=e.cover==="present",p=!a.title||!a.language||!a.genre||!c,f=ZS(e),_=d.jsx(QS,{progress:e,onOpenStoryInfo:s,onCoachAction:(E,N)=>{E!=="view-progress"&&N&&i(t,N)}}),x=[{label:"Public title",status:a.title?"done":"todo",detail:a.title??null},{label:"Language",status:a.language?"done":"todo",detail:a.language??null},{label:"Genre",status:a.genre?"done":"todo",detail:a.genre??null},{label:"Cover image",status:c?"done":"todo",detail:e.cover==="invalid"?"Invalid — re-import":c?null:"Missing"}],b=f==="story-info"?"current":p?"needs-action":"done",v=o?"done":f==="whitepaper"?"current":"not-started",S=e.episodes.find(E=>E.kind==="genesis")??null,j=e.episodes.filter(E=>E.kind==="plot");let R=0;return d.jsxs("div",{className:"h-full overflow-y-auto","data-testid":"story-progress-panel",children:[d.jsx(JS,{progress:e}),d.jsx("div",{className:"border-b border-border","data-testid":"persistent-next-action",children:_}),d.jsx("p",{className:"px-4 pt-3 pb-1 text-[11px] font-medium text-muted uppercase tracking-wider",children:"Production Progress"}),d.jsx(vy,{index:++R,title:"Define Story Info",status:b,items:x}),d.jsx(vy,{index:++R,title:"Story Whitepaper",status:v,fileName:"structure.md",openFile:o?()=>i(t,"structure.md"):void 0,items:[{label:"Planning document",status:o?"done":"todo",detail:o?null:"Not written yet"}]}),S?d.jsx(zf,{index:++R,ep:S,isActive:f===S.file,storyName:t,onOpenFile:i}):d.jsx(zf,{index:++R,ep:RM,isActive:f==="genesis.md",openingDone:!1,canOpen:!1,storyName:t,onOpenFile:i}),j.map(E=>d.jsx(zf,{index:++R,ep:E,isActive:f===E.file,storyName:t,onOpenFile:i},E.file)),d.jsxs("div",{className:"px-4 py-2 text-[11px] text-muted flex flex-wrap gap-x-3","data-testid":"progress-summary",children:[d.jsxs("span",{children:[e.summary.published," published"]}),d.jsxs("span",{children:[e.summary.readyToPublish," ready"]}),e.summary.placeholders>0&&d.jsxs("span",{children:[e.summary.placeholders," not started"]}),e.summary.blocked>0&&d.jsxs("span",{className:"text-error",children:[e.summary.blocked," need fixes"]})]})]})}function zf({index:e,ep:t,isActive:i,storyName:s,onOpenFile:a,openingDone:o=!0,canOpen:c=!0}){const h=jM(t,i),p=TM(t,o),f=t.title?`${t.label} · ${t.title}`:t.label,_=d.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[d.jsx("span",{className:`flex-shrink-0 ${Ou[h]}`,"aria-hidden":!0,children:e1[h]}),d.jsxs("span",{className:"text-xs font-medium text-foreground truncate",children:[e,". ",f]}),d.jsx("span",{className:"text-[10px] text-muted truncate",children:t.file}),d.jsx("span",{className:`ml-auto text-[10px] font-medium ${Ou[h]} flex-shrink-0`,children:t1[h]})]});return d.jsxs("div",{className:"px-4 py-2.5 border-b border-border","data-testid":`workflow-section-${e}`,"data-status":h,children:[c?d.jsx("button",{onClick:()=>a(s,t.file),"data-testid":`progress-episode-${t.file}`,"data-state":t.state,className:"w-full text-left rounded hover:bg-surface -mx-1 px-1 py-0.5",children:_}):d.jsx("div",{"data-state":t.state,children:_}),d.jsx("div",{className:"mt-1.5 ml-1 flex flex-col gap-1 border-l border-border pl-3",children:p.map((x,b)=>d.jsx(i1,{item:x},b))})]})}const MM={published:"✓",ready:"●","in-progress":"◐",planning:"○",placeholder:"○",blocked:"✕",draft:"○"},yy={published:"text-green-700",ready:"text-green-700","in-progress":"text-accent",planning:"text-accent",placeholder:"text-muted",blocked:"text-error",draft:"text-muted"},BM={published:"Published",ready:"Ready","in-progress":"In progress",planning:"Planning",placeholder:"Not started",blocked:"Needs fixes",draft:"Draft"};function LM({progress:e,storyName:t,onOpenFile:i}){const[s,a]=w.useState(!1);return d.jsxs("div",{className:"h-full overflow-y-auto","data-testid":"story-progress-panel",children:[d.jsx(JS,{progress:e}),e.nextAction&&d.jsxs("div",{className:"px-4 py-2 border-b border-accent/30 bg-accent/5 text-xs space-y-1.5","data-testid":"progress-next-action",children:[d.jsxs("div",{children:[d.jsx("span",{className:"font-medium text-foreground",children:"Next: "}),d.jsx("span",{className:"text-muted",children:e.nextAction})]}),e.nextPrompt&&d.jsxs("div",{className:"flex items-start gap-1.5","data-testid":"progress-next-prompt",children:[d.jsx("code",{className:"flex-1 rounded border border-border bg-surface px-1.5 py-1 text-[10px] text-foreground break-words",children:e.nextPrompt}),d.jsx("button",{onClick:()=>{var o;e.nextPrompt&&((o=navigator.clipboard)==null||o.writeText(e.nextPrompt).then(()=>{a(!0)}).catch(()=>{}))},"data-testid":"copy-next-prompt",className:"rounded border border-border px-2 py-1 text-[10px] text-muted hover:border-accent hover:text-accent transition-colors flex-shrink-0",children:s?"Copied!":"Copy"})]})]}),d.jsxs("div",{className:"px-4 py-2 border-b border-border flex flex-col gap-1",children:[d.jsx(Sy,{done:e.setup.hasStructure,label:"Story bible (structure.md)",onClick:e.setup.hasStructure?()=>i(t,"structure.md"):void 0}),d.jsx(Sy,{done:e.setup.hasGenesis,label:"Genesis written",onClick:e.setup.hasGenesis?()=>i(t,"genesis.md"):void 0})]}),d.jsxs("div",{className:"px-4 py-2",children:[d.jsx("p",{className:"text-[11px] font-medium text-muted uppercase tracking-wider mb-1.5",children:"Chapters"}),e.episodes.length===0?d.jsx("p",{className:"text-xs text-muted italic","data-testid":"progress-no-episodes",children:"No chapters yet — write the Genesis to start."}):d.jsx("ol",{className:"flex flex-col gap-1",children:e.episodes.map(o=>d.jsx("li",{children:d.jsxs("button",{onClick:()=>i(t,o.file),"data-testid":`progress-episode-${o.file}`,"data-state":o.state,className:"w-full text-left flex items-start gap-2 rounded px-2 py-1.5 hover:bg-surface",children:[d.jsx("span",{className:`mt-0.5 ${yy[o.state]}`,"aria-hidden":!0,children:MM[o.state]}),d.jsxs("span",{className:"min-w-0 flex-1",children:[d.jsxs("span",{className:"flex items-center gap-1.5",children:[d.jsx("span",{className:"text-xs font-medium text-foreground",children:o.label}),o.title&&d.jsxs("span",{className:"text-[11px] text-muted truncate",children:["· ",o.title]}),d.jsx("span",{className:`ml-auto text-[10px] font-medium ${yy[o.state]}`,children:BM[o.state]})]}),d.jsx("span",{className:"block text-[11px] text-muted",children:o.summary})]})]})},o.file))})]}),d.jsxs("div",{className:"px-4 py-2 border-t border-border text-[11px] text-muted flex flex-wrap gap-x-3","data-testid":"progress-summary",children:[d.jsxs("span",{children:[e.summary.published," published"]}),e.summary.blocked>0&&d.jsxs("span",{className:"text-error",children:[e.summary.blocked," need fixes"]})]})]})}function Sy({done:e,label:t,onClick:i}){const s=d.jsxs("span",{className:"flex items-center gap-2 text-xs",children:[d.jsx("span",{className:e?"text-green-700":"text-muted","aria-hidden":!0,children:e?"✓":"○"}),d.jsx("span",{className:e?"text-foreground":"text-muted",children:t})]});return i?d.jsx("button",{onClick:i,className:"text-left hover:underline",children:s}):d.jsx("div",{children:s})}const OM=[{key:"progress",label:"Progress"},{key:"story-info",label:"Story Info"},{key:"whitepaper",label:"Whitepaper"},{key:"genesis",label:"Genesis / Ep 1"},{key:"episodes",label:"Episodes"},{key:"publish",label:"Publish"}];function zM({storyTitle:e,active:t,onSelect:i}){return d.jsxs("div",{className:"flex-shrink-0 border-b border-border bg-surface/40","data-testid":"cartoon-workflow-nav",children:[d.jsxs("div",{className:"flex items-center gap-2 px-3 pt-2",children:[d.jsx("span",{className:"text-[10px] font-medium uppercase tracking-[0.14em] text-accent",children:"Cartoon"}),d.jsx("span",{className:"text-xs font-serif text-foreground truncate",children:e})]}),d.jsx("div",{className:"flex items-center gap-1 px-2 py-1.5 overflow-x-auto",role:"tablist",children:OM.map(s=>{const a=s.key===t;return d.jsx("button",{role:"tab","aria-selected":a,"data-testid":`nav-tab-${s.key}`,"data-active":a,onClick:()=>i(s.key),className:`flex-shrink-0 rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors ${a?"bg-accent text-white":"text-muted hover:text-foreground hover:bg-surface"}`,children:s.label},s.key)})})]})}function PM({storyName:e,authFetch:t,onSaved:i}){const[s,a]=w.useState(!0),[o,c]=w.useState(!1),[h,p]=w.useState(""),[f,_]=w.useState(""),[x,b]=w.useState(""),[v,S]=w.useState(""),[j,R]=w.useState(!1),[E,N]=w.useState("cartoon"),[I,te]=w.useState("unknown"),[F,D]=w.useState(!1),[ie,fe]=w.useState(!1),[Se,H]=w.useState(null),[ce,W]=w.useState(!1),[K,X]=w.useState(null),[U,A]=w.useState(!1),O=w.useRef(null);w.useEffect(()=>{let C=!1;return a(!0),c(!1),fe(!1),H(null),(async()=>{try{const[V,ne]=await Promise.all([t(`/api/stories/${e}`),t(`/api/stories/${e}/progress`)]);if(!V.ok){C||(c(!0),a(!1));return}const ae=await V.json(),Y=ne.ok?await ne.json().catch(()=>null):null;if(C)return;p(ae.title??""),_(ae.description??""),b(Cu(ae.genre)??""),S(ae.language&&ts.find(he=>he.toLowerCase()===ae.language.toLowerCase())||""),R(!!ae.isNsfw),N(ae.contentType==="fiction"?"fiction":"cartoon"),te((Y==null?void 0:Y.cover)??"unknown"),a(!1)}catch{C||(c(!0),a(!1))}})(),()=>{C=!0}},[e,t]);const $=w.useCallback(async()=>{D(!0),fe(!1),H(null);const C={title:h.trim(),description:f.trim(),genre:x,language:v,isNsfw:j};try{const V=await t(`/api/stories/${e}/publish-metadata`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(C)});if(V.ok)fe(!0),i==null||i({genre:x,language:v,isNsfw:j});else{const ne=await V.json().catch(()=>({}));H(ne.error||"Could not save story info.")}}catch{H("Could not save story info.")}D(!1)},[e,t,h,f,x,v,j,i]),xe=w.useCallback(async C=>{var ne;const V=(ne=C.target.files)==null?void 0:ne[0];if(O.current&&(O.current.value=""),!!V){W(!0),H(null);try{let ae;try{ae=await Ku(V)}catch(Le){H(Le instanceof Error?Le.message:"Could not import image");return}const Y=ae.type==="image/jpeg"?"jpg":"webp",he=new File([ae],`cover.${Y}`,{type:ae.type}),_e=new FormData;_e.append("file",he);const Be=await t(`/api/stories/${e}/import-cover`,{method:"POST",body:_e});if(!Be.ok){const Le=await Be.json().catch(()=>({}));H(Le.error||"Cover import failed.");return}te("present"),X(Le=>(Le&&URL.revokeObjectURL(Le),URL.createObjectURL(he)))}catch{H("Cover import failed.")}finally{W(!1)}}},[e,t]),T=w.useCallback(()=>{var V;const C=`Generate a cover image for this story (${h||e}) and save it as assets/cover.webp — portrait 600x900, WebP, under 1MB. Don't publish.`;(V=navigator.clipboard)==null||V.writeText(C).then(()=>{A(!0)}).catch(()=>{})},[h,e]);if(s)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm","data-testid":"story-info-loading",children:"Loading story info…"});if(o)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm",children:"Could not load story info."});const M=I==="present"?"Cover set":I==="invalid"?"Invalid cover — re-import a WebP/JPEG under 1MB":"Missing cover",G=I==="present"?"text-green-700":I==="invalid"?"text-amber-700":"text-muted";return d.jsxs("div",{className:"h-full overflow-y-auto px-4 py-4","data-testid":"story-info-page",children:[d.jsx("h2",{className:"text-base font-serif text-foreground",children:"Story Info"}),d.jsx("p",{className:"mt-0.5 text-[11px] text-muted",children:"These details appear on PlotLink when the story is published."}),d.jsxs("div",{className:"mt-4 flex flex-col gap-4 max-w-xl",children:[d.jsxs("label",{className:"flex flex-col gap-1",children:[d.jsx("span",{className:"text-[11px] font-medium text-muted",children:"Public title"}),d.jsx("input",{type:"text",value:h,onChange:C=>{p(C.target.value),fe(!1)},"data-testid":"story-info-title",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none"})]}),d.jsxs("label",{className:"flex flex-col gap-1",children:[d.jsx("span",{className:"text-[11px] font-medium text-muted",children:"Short description"}),d.jsx("textarea",{value:f,onChange:C=>{_(C.target.value),fe(!1)},rows:3,"data-testid":"story-info-description",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none resize-y"})]}),d.jsxs("div",{className:"flex flex-wrap gap-4",children:[d.jsxs("label",{className:"flex flex-col gap-1 min-w-[140px] flex-1",children:[d.jsx("span",{className:"text-[11px] font-medium text-muted",children:"Genre"}),d.jsxs("select",{value:x,onChange:C=>{b(C.target.value),fe(!1)},"data-testid":"story-info-genre",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",children:[d.jsx("option",{value:"",children:"Needs metadata"}),dl.map(C=>d.jsx("option",{value:C,children:C},C))]})]}),d.jsxs("label",{className:"flex flex-col gap-1 min-w-[140px] flex-1",children:[d.jsx("span",{className:"text-[11px] font-medium text-muted",children:"Language"}),d.jsxs("select",{value:v,onChange:C=>{S(C.target.value),fe(!1)},"data-testid":"story-info-language",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",children:[d.jsx("option",{value:"",children:"Needs metadata"}),ts.map(C=>d.jsx("option",{value:C,children:C},C))]})]}),d.jsxs("label",{className:"flex flex-col gap-1 min-w-[140px] flex-1",children:[d.jsx("span",{className:"text-[11px] font-medium text-muted",children:"Content type"}),d.jsx("span",{className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-surface text-muted","data-testid":"story-info-content-type",title:"Content type is locked after creation.",children:E==="cartoon"?"Cartoon · locked":"Fiction · locked"})]})]}),d.jsxs("div",{className:"flex flex-col gap-1.5",children:[d.jsx("span",{className:"text-[11px] font-medium text-muted",children:"Cover image"}),d.jsxs("div",{className:"flex items-start gap-3",children:[K&&d.jsx("img",{src:K,alt:"Cover preview",className:"w-16 h-24 object-cover rounded border border-border"}),d.jsxs("div",{className:"flex flex-col gap-1.5",children:[d.jsx("span",{className:`text-[11px] font-medium ${G}`,"data-testid":"story-info-cover-status",children:M}),d.jsx("span",{className:"text-[10px] text-muted",children:"WebP or JPEG, max 1MB, 600×900 recommended."}),d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("button",{type:"button",onClick:()=>{var C;return(C=O.current)==null?void 0:C.click()},disabled:ce,"data-testid":"story-info-import-cover",className:"rounded border border-border px-2.5 py-1 text-[11px] text-foreground hover:border-accent hover:text-accent transition-colors disabled:opacity-50",children:ce?"Importing…":"Import cover"}),d.jsx("button",{type:"button",onClick:T,"data-testid":"story-info-cover-prompt",className:"rounded border border-border px-2.5 py-1 text-[11px] text-muted hover:border-accent hover:text-accent transition-colors",children:U?"Copied!":"Ask agent for cover prompt"})]}),d.jsx("input",{ref:O,type:"file",accept:"image/*",onChange:xe,className:"hidden"})]})]})]}),d.jsxs("label",{className:"flex items-center gap-2",children:[d.jsx("input",{type:"checkbox",checked:j,onChange:C=>{R(C.target.checked),fe(!1)},"data-testid":"story-info-nsfw"}),d.jsx("span",{className:"text-xs text-foreground",children:"This story contains adult content (18+)"})]}),d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsx("button",{type:"button",onClick:$,disabled:F,"data-testid":"story-info-save",className:"rounded bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent-dim transition-colors disabled:opacity-50",children:F?"Saving…":"Save Story Info"}),ie&&d.jsx("span",{className:"text-[11px] text-green-700","data-testid":"story-info-saved",children:"Saved"}),Se&&d.jsx("span",{className:"text-[11px] text-error","data-testid":"story-info-error",children:Se})]})]})]})}function IM({storyName:e,authFetch:t,onOpenFile:i}){const[s,a]=w.useState(null),[o,c]=w.useState(!0);return w.useEffect(()=>{let h=!1;return(async()=>{c(!0);try{const f=await t(`/api/stories/${e}/progress`),_=f.ok?await f.json():null;h||(a(Array.isArray(_==null?void 0:_.episodes)?_.episodes:null),c(!1))}catch{h||(a(null),c(!1))}})(),()=>{h=!0}},[e,t]),o?d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm","data-testid":"episodes-loading",children:"Loading episodes…"}):s?d.jsxs("div",{className:"h-full overflow-y-auto px-4 py-4","data-testid":"episodes-page",children:[d.jsx("h2",{className:"text-base font-serif text-foreground",children:"Episodes"}),d.jsx("p",{className:"mt-0.5 text-[11px] text-muted",children:"Genesis is Episode 1; each plot file is the next episode."}),s.length===0?d.jsx("p",{className:"mt-4 text-xs text-muted italic","data-testid":"episodes-empty",children:"No episodes yet — write the Genesis to start Episode 1."}):d.jsx("ol",{className:"mt-3 flex flex-col gap-1",children:s.map(h=>d.jsx("li",{children:d.jsx("button",{onClick:()=>i(e,h.file),"data-testid":`episodes-row-${h.file}`,"data-state":h.state,className:"w-full text-left flex items-start gap-2 rounded px-2 py-1.5 hover:bg-surface",children:d.jsxs("span",{className:"min-w-0 flex-1",children:[d.jsxs("span",{className:"flex items-center gap-1.5",children:[d.jsx("span",{className:"text-xs font-medium text-foreground",children:h.label}),h.title&&d.jsxs("span",{className:"text-[11px] text-muted truncate",children:["· ",h.title]}),d.jsx("span",{className:"ml-auto text-[10px] text-muted",children:h.file})]}),d.jsx("span",{className:"block text-[11px] text-muted",children:h.summary})]})})},h.file))})]}):d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm",children:"Could not load episodes."})}function HM({storyName:e,authFetch:t,onOpenFile:i,onOpenStoryInfo:s,onPublish:a,publishingFile:o,genre:c,language:h,isNsfw:p,refreshKey:f=0}){var We,Mt;const[_,x]=w.useState(null),[b,v]=w.useState(!0),[S,j]=w.useState(!1),[R,E]=w.useState(null),[N,I]=w.useState(null),[te,F]=w.useState(null),[D,ie]=w.useState(null),[fe,Se]=w.useState(null),H=async()=>{try{const He=await t(`/api/stories/${e}/cover-asset`),xt=He.ok?await He.json():null;if(!(xt!=null&&xt.found)||!xt.valid||!xt.path)return null;const Ae=await t(`/api/stories/${e}/asset/${String(xt.path).replace(/^assets\//,"")}`);if(!Ae.ok)return null;const Kt=await Ae.blob();return new File([Kt],String(xt.path).split("/").pop()||"cover.webp",{type:xt.type||Kt.type})}catch{return null}};w.useEffect(()=>{let He=!1;return(async()=>{v(!0),j(!1);try{const Ae=await t(`/api/stories/${e}/progress`),Kt=Ae.ok?await Ae.json():null;if(He)return;!Kt||!Array.isArray(Kt.episodes)?(j(!0),x(null)):x(Kt),v(!1)}catch{He||(j(!0),x(null),v(!1))}})(),()=>{He=!0}},[e,t,f]);const ce=((Mt=(We=_==null?void 0:_.episodes)==null?void 0:We.find(He=>!He.published))==null?void 0:Mt.file)??null,W=ce==="genesis.md",K=JSON.stringify([ce??"",f]),[X,U]=w.useState(null);if(X!==K&&(U(K),I(null),F(null),ie(null),Se(null)),w.useEffect(()=>{if(!ce)return;let He=!1;const xt=ce.replace(/\.md$/,"");return(async()=>{var Ae;try{const Kt=[t(`/api/stories/${e}/${ce}`),t(`/api/stories/${e}/cuts/${xt}`)];W&&Kt.push(t(`/api/stories/${e}/structure.md`));const[mi,wt,Qe]=await Promise.all(Kt);if(He)return;if(I(mi.ok?(await mi.json()).content??"":""),wt.ok){const Q=await wt.json();if(He)return;F(Array.isArray(Q.cuts)?Q.cuts:[]),ie(typeof Q.title=="string"?Q.title:null)}else F(null),ie(null);Se(W&&Qe&&Qe.ok?((Ae=await Qe.json())==null?void 0:Ae.content)??null:null)}catch{He||(I(""),F(null),ie(null),Se(null))}})(),()=>{He=!0}},[ce,W,e,t,f]),b)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm","data-testid":"publish-page-loading",children:"Loading publish readiness…"});if(S||!_)return d.jsx("div",{className:"h-full flex items-center justify-center text-muted text-sm",children:"Could not load publish readiness."});const A=_.episodes.find(He=>!He.published);if(!A)return d.jsxs("div",{className:"h-full overflow-y-auto px-4 py-4","data-testid":"cartoon-publish-page",children:[d.jsx("h2",{className:"text-base font-serif text-foreground",children:"Publish"}),d.jsx("p",{className:"mt-2 text-xs text-green-700","data-testid":"publish-all-done",children:_.episodes.length>0?"All episodes are published to PlotLink. Plan the next episode to continue.":"No episodes yet — write the Genesis (Episode 1) to begin."})]});const O=A.cuts,$=_.cover==="present",xe=[{label:"Opening text ready",status:"done"},{label:"Cut plan",status:O&&O.total>0?"done":"todo",detail:O?`${O.total} cut${O.total===1?"":"s"} planned`:"not started"},{label:"Clean images converted",status:O&&O.needClean>0&&O.withClean===O.needClean?"done":"todo",detail:O?`${O.withClean} / ${O.needClean}`:null},{label:"Cuts lettered",status:O&&O.total>0&&O.withText===O.total?"done":"todo",detail:O?`${O.withText} / ${O.total}`:null},{label:"Final images exported",status:O&&O.total>0&&O.exported===O.total?"done":"todo",detail:O?`${O.exported} / ${O.total}`:null},{label:"Final images uploaded",status:O&&O.total>0&&O.uploaded===O.total?"done":"todo",detail:O?`${O.uploaded} / ${O.total}`:null},{label:"Cover image",status:$?"done":"todo",detail:$?null:"recommended before publishing"},{label:"Publish to PlotLink",status:A.published?"done":"todo"}],T=A.state==="ready",M=A.state==="blocked",G=A.file==="genesis.md",C=!G||!!c&&!!h,V=!!o&&o===A.file,ne=N!==null,ae=ne?Cm({fileName:A.file,fileContent:N??"",storySlug:e,structureContent:fe,contentType:"cartoon",episodeTitle:D}):null,Y=!!ae&&zo(ae,A.file),he=!G&&ne&&!wm({fileContent:N??"",episodeTitle:D}),_e=Y||he,Be=G&&ne?bm(N??""):null,Le=!!Be&&Be.blockers.length>0,je=!G&&ne&&te!==null?WS(N??"",te):null,be=je&&je.stage==="error"?je.issues:[],St=T&&C&&(ne&&(G||te!==null))&&!_e&&!Le&&!V&&!!a,ot=async()=>{if(!(!St||!a)){E(null);try{const He=G?await H():null;await a(e,A.file,c??"",h??"",!!p,He)}catch{E("Publish could not be started. Please try again.")}}};return d.jsxs("div",{className:"h-full overflow-y-auto px-4 py-4","data-testid":"cartoon-publish-page",children:[d.jsxs("h2",{className:"text-base font-serif text-foreground",children:["Publish ",A.label]}),d.jsx("p",{className:"mt-0.5 text-[11px] text-muted",children:"Finalize this episode: convert, letter, export, upload, then publish to PlotLink."}),d.jsx("ul",{className:"mt-3 flex flex-col gap-1.5 max-w-xl","data-testid":"publish-checklist",children:xe.map((He,xt)=>d.jsxs("li",{className:"flex items-baseline gap-2 text-xs","data-testid":"publish-check","data-status":He.status,children:[d.jsx("span",{className:`flex-shrink-0 ${He.status==="done"?"text-green-700":"text-muted"}`,"aria-hidden":!0,children:He.status==="done"?"✓":"○"}),d.jsx("span",{className:He.status==="done"?"text-foreground":"text-muted",children:He.label}),He.detail&&d.jsxs("span",{className:"text-muted",children:["· ",He.detail]})]},xt))}),ae&&d.jsxs("div",{className:"mt-4 flex flex-col gap-0.5 max-w-xl","data-testid":"publish-title-preview","data-raw":Y?"true":"false","data-blocked":_e?"true":"false",children:[d.jsxs("span",{className:"text-[11px] text-foreground",children:[d.jsxs("span",{className:"font-medium",children:[G?"Story title":"Episode title",":"]})," ",d.jsx("span",{className:_e?"text-error font-medium":"text-foreground",children:ae})]}),Y?d.jsxs("span",{className:"text-[10px] text-error","data-testid":"publish-title-raw-error",children:["This would publish as a raw filename. ",G?"Add a real “# Title” heading to genesis.md":"Set a title in the cut plan (or add a “# Title” to the episode)"," before publishing."]}):he?d.jsxs("span",{className:"text-[10px] text-error","data-testid":"publish-title-episode-required",children:["“",ae,"” is a generic placeholder, not a reader-facing title, so it can’t be published. Set a real episode title in the cut plan (or add a “# Title” to the episode) — e.g. “Episode 01 — The Couple Coupon” — before publishing."]}):null]}),Be&&d.jsxs("div",{className:"mt-4 flex flex-col gap-1 rounded border border-border bg-surface/50 p-2 max-w-xl","data-testid":"cartoon-genesis-readiness","data-blocked":Le?"true":"false",children:[d.jsx("span",{className:"text-[11px] font-medium text-foreground",children:"Story opening (Prologue)"}),d.jsx("span",{className:"text-[10px] text-muted","data-testid":"genesis-readiness-hint",children:"Genesis is the first thing readers see. Write it as the story opening/prologue, not a synopsis — set up the premise and stakes, then bridge into Episode 01."}),Be.blockers.map((He,xt)=>d.jsx("span",{className:"text-[10px] text-error","data-testid":"genesis-readiness-blocker",children:He},`b-${xt}`)),Be.warnings.map((He,xt)=>d.jsx("span",{className:"text-[10px] text-amber-600","data-testid":"genesis-readiness-warning",children:He},`w-${xt}`))]}),be.length>0&&d.jsxs("div",{className:"mt-4 flex flex-col gap-2 rounded-xl border border-error/30 bg-error/5 px-3 py-3 max-w-xl","data-testid":"cartoon-publish-issues",children:[d.jsxs("div",{className:"flex items-center gap-2",children:[d.jsx("span",{className:"rounded-full bg-error px-2 py-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-white",children:"Before publish"}),d.jsx("span",{className:"text-xs font-medium text-foreground",children:"Finish these workflow steps"})]}),GS(be).map(He=>d.jsx("div",{className:"rounded-lg border border-error/15 bg-background/70 px-2.5 py-2","data-testid":`cartoon-issue-group-${He.key}`,children:d.jsx("span",{className:"text-[11px] font-medium text-foreground",children:He.title})},He.key)),d.jsxs("details",{className:"text-[10px] text-muted","data-testid":"cartoon-technical-details",children:[d.jsx("summary",{className:"cursor-pointer select-none",children:"Technical details"}),d.jsx("ul",{className:"mt-1 ml-3 list-disc",children:be.map((He,xt)=>d.jsx("li",{className:"font-mono break-words",children:He},xt))})]})]}),d.jsxs("div",{className:"mt-4 flex flex-col gap-2 max-w-xl",children:[!$&&d.jsx("button",{onClick:s,"data-testid":"publish-add-cover",className:"self-start rounded border border-border px-3 py-1.5 text-xs text-foreground hover:border-accent hover:text-accent transition-colors",children:"Add a cover image (Story Info)"}),G&&!C&&d.jsx("button",{onClick:s,"data-testid":"publish-set-metadata",className:"self-start rounded border border-border px-3 py-1.5 text-xs text-foreground hover:border-accent hover:text-accent transition-colors",children:"Set genre & language (Story Info)"}),!T&&d.jsxs("button",{onClick:()=>i(e,A.file),"data-testid":"publish-open-episode",className:"self-start rounded border border-accent/40 px-3 py-1.5 text-xs text-accent hover:bg-accent/5 transition-colors",children:["Open ",A.label," to finish ",M?"and fix issues":"(letter / export / upload)"]}),d.jsx("button",{onClick:ot,disabled:!St,"data-testid":"publish-cta",className:"self-start rounded bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent-dim disabled:opacity-50 transition-colors",title:St?void 0:"Finish the remaining steps above first",children:V?"Publishing…":`Publish ${A.label} to PlotLink`}),T?C?_e||Le?d.jsx("p",{className:"text-[11px] text-error","data-testid":"publish-title-blocked-reason",children:Le?"Fix the Story opening issues above before publishing.":"Set a real reader-facing title above before publishing."}):null:d.jsx("p",{className:"text-[11px] text-amber-700","data-testid":"publish-needs-metadata",children:"Set the genre and language in Story Info before publishing."}):d.jsx("p",{className:"text-[11px] text-muted","data-testid":"publish-blocked-reason",children:M?`Not publishable yet — ${A.summary.toLowerCase()}. Open the episode to fix the flagged cuts.`:`Not ready yet — ${A.summary.toLowerCase()}.`}),R&&d.jsx("p",{className:"text-[11px] text-error","data-testid":"publish-error",children:R})]}),d.jsxs("details",{className:"mt-4 max-w-xl","data-testid":"publish-technical-details",children:[d.jsx("summary",{className:"text-[11px] text-muted cursor-pointer hover:text-foreground",children:"Technical validation details"}),d.jsxs("div",{className:"mt-1 text-[10px] text-muted space-y-0.5",children:[d.jsxs("p",{children:["Episode file: ",d.jsx("span",{className:"font-mono",children:A.file})]}),d.jsxs("p",{children:["State: ",A.state," — ",A.summary]}),d.jsx("p",{children:"Per-cut production (cut plan, clean images, lettering, export, upload) happens in the episode’s cut workspace; open it above to finish any remaining step."})]})]})]})}function UM(e,t){var s;const i=[e.plots,e.chapters].filter(Boolean);for(const a of i){let c=t!=null?a.find(p=>p.plotIndex===t||p.index===t):void 0;if(!c&&a.length===1){const p=a[0];(!(p.plotIndex!=null||p.index!=null)||t==null)&&(c=p)}const h=(s=(c==null?void 0:c.title)??(c==null?void 0:c.name))==null?void 0:s.trim();if(h)return h}}function $M(e){var o;const{fileName:t,detail:i,plotIndex:s}=e;if(!i)return{ok:!0,checked:!1};if(t==="genesis.md"){const c=(o=i.title??i.name)==null?void 0:o.trim();return c?zo(c,"genesis.md")?{ok:!1,checked:!0,publicTitle:c,reason:`PlotLink indexed the storyline title as “${c}”, a raw filename rather than the reader-facing title.`}:{ok:!0,checked:!0,publicTitle:c}:{ok:!0,checked:!1}}const a=UM(i,s);return a?zo(a,t)||Ip(a)?{ok:!1,checked:!0,publicTitle:a,reason:`PlotLink indexed the episode title as “${a}”, a generic placeholder rather than a reader-facing episode title.`}:{ok:!0,checked:!0,publicTitle:a}:{ok:!0,checked:!1}}function FM(e){return`${e.reason??"PlotLink indexed a raw/generic public title for this publish."} Published metadata is immutable on-chain and cannot be edited — the next publish must use corrected, reader-facing metadata. (The webtoon pilot stays blocked until a publish indexes a real public title.)`}const n1="plotlink-panel-ratio",qM=.6,wy=300,Pf=224,If=6;function WM(){try{const e=localStorage.getItem(n1);if(e){const t=parseFloat(e);if(t>0&&t<1)return t}}catch{}return qM}function Cy(e,t){if(t<=0)return e;const i=wy/t,s=1-wy/t;return i>=s?.5:Math.min(s,Math.max(i,e))}function GM({token:e,authFetch:t}){const[i,s]=w.useState(null),[a,o]=w.useState(null),[c,h]=w.useState(null),[p,f]=w.useState(null),[_,x]=w.useState(0),[b,v]=w.useState(""),[S,j]=w.useState(null),[R,E]=w.useState(null),[N,I]=w.useState(WM),[te,F]=w.useState([]),[D,ie]=w.useState(!1),[fe,Se]=w.useState(""),[H,ce]=w.useState(""),[W,K]=w.useState(""),[X,U]=w.useState("English"),[A,O]=w.useState("normal"),[$,xe]=w.useState("claude"),[T,M]=w.useState(null),[G,C]=w.useState(!1),[V,ne]=w.useState({}),[ae,Y]=w.useState({}),[he,_e]=w.useState(new Set),[Be,Le]=w.useState(new Set),[je,be]=w.useState({}),[tt,St]=w.useState({}),[ot,We]=w.useState({}),[Mt,He]=w.useState({}),[xt,Ae]=w.useState({}),[Kt,mi]=w.useState({}),[wt,Qe]=w.useState(!1),[Q,ge]=w.useState(!0),Te=w.useRef(new Map),Ue=w.useRef(new Map),it=w.useRef(new Map),Wt=w.useRef(new Map),ui=w.useRef(new Set),Bt=w.useRef(null),vt=w.useRef(null),At=w.useRef(!1);w.useEffect(()=>{t("/api/wallet").then(le=>le.ok?le.json():null).then(le=>{le!=null&&le.address&&E(le.address)}).catch(()=>{})},[t]),w.useEffect(()=>{t("/api/agent/readiness").then(le=>le.ok?le.json():null).then(le=>{le&&M(le)}).catch(()=>{})},[t]),w.useEffect(()=>{try{localStorage.setItem(n1,String(N))}catch{}},[N]),w.useEffect(()=>{const le=()=>{if(!vt.current)return;const L=vt.current.getBoundingClientRect().width-Pf-If;I(oe=>Cy(oe,L))};return window.addEventListener("resize",le),le(),()=>window.removeEventListener("resize",le)},[]);const Ze=w.useCallback(()=>{Se(""),ce(""),K(""),O("normal"),xe("claude"),ie(!0)},[]),hi=w.useCallback(async(le,L,oe,Ee)=>{const Me=fe.trim();if(!Me)return;const Ne=le==="cartoon"?"codex":Ee;try{const Pe=await t("/api/stories/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:Me,description:H.trim()||void 0,language:L,genre:W||void 0,contentType:le,agentMode:oe,agentProvider:Ne})});if(!Pe.ok)return;const qe=await Pe.json();ie(!1),be(nt=>({...nt,[qe.name]:le})),St(nt=>({...nt,[qe.name]:L})),W&&We(nt=>({...nt,[qe.name]:W})),Y(nt=>({...nt,[qe.name]:Ne})),oe==="bypass"&&ne(nt=>({...nt,[qe.name]:!0})),s(qe.name),o(null)}catch{}},[t,fe,H,W]);w.useEffect(()=>{if(te.length===0)return;const le=setInterval(async()=>{try{const L=await t("/api/stories");if(!L.ok)return;const oe=await L.json(),Ee=new Set(oe.stories.filter(Me=>Me.name!=="_example").map(Me=>Me.name));for(const Me of Ee)if(!ui.current.has(Me)&&te.length>0){const Ne=te[0],Pe=Te.current.get(Ne)||"fiction",qe=Ue.current.get(Ne)||"English",nt=it.current.get(Ne)||"normal",Ve=Wt.current.get(Ne)||"claude";let Et=!1;Bt.current&&(Et=await Bt.current(Ne,Me,{contentType:Pe,language:qe,agentMode:nt,agentProvider:Ve}).catch(()=>!1)),Et&&(F(Nt=>Nt.slice(1)),Te.current.delete(Ne),Ue.current.delete(Ne),it.current.delete(Ne),Wt.current.delete(Ne),nt==="bypass"&&ne(Nt=>{const Gt={...Nt,[Me]:!0};return delete Gt[Ne],Gt}),Y(Nt=>{const Gt={...Nt,[Me]:Ve};return delete Gt[Ne],Gt}),t(`/api/stories/${Me}/metadata`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({contentType:Pe,language:qe,agentMode:nt,agentProvider:Ve})}).catch(()=>{})),s(Me),o(null)}ui.current=Ee}catch{}},3e3);return()=>clearInterval(le)},[t,te]),w.useEffect(()=>{t("/api/stories").then(le=>{if(le.ok)return le.json()}).then(le=>{le!=null&&le.stories&&(ui.current=new Set(le.stories.filter(L=>L.name!=="_example").map(L=>L.name)))}).catch(()=>{})},[t]);const P=w.useCallback((le,L)=>{s(le),o(L),h(null)},[]),we=w.useRef(null),ze=w.useCallback(async le=>{var L,oe,Ee,Me;we.current=le,s(le),o(null),h(null);try{const Ne=await t(`/api/stories/${le}`);if(Ne.ok&&we.current===le){const Pe=await Ne.json();if(Pe.contentType==="cartoon")return;const qe=Pe.files||[],Ve=((L=qe.map(Et=>{var Nt;return{file:Et.file,num:(Nt=Et.file.match(/^plot-(\d+)\.md$/))==null?void 0:Nt[1]}}).filter(Et=>Et.num!=null).sort((Et,Nt)=>parseInt(Nt.num)-parseInt(Et.num))[0])==null?void 0:L.file)??((oe=qe.find(Et=>Et.file==="genesis.md"))==null?void 0:oe.file)??((Ee=qe.find(Et=>Et.file==="structure.md"))==null?void 0:Ee.file)??((Me=qe[0])==null?void 0:Me.file);Ve&&we.current===le&&o(Ve)}}catch{}},[t]),Re=w.useCallback(le=>{le.preventDefault(),At.current=!0,document.body.style.cursor="col-resize",document.body.style.userSelect="none";const L=Ee=>{if(!At.current||!vt.current)return;const Me=vt.current.getBoundingClientRect(),Ne=Me.width-Pf-If,Pe=Ee.clientX-Me.left-Pf;I(Cy(Pe/Ne,Ne))},oe=()=>{At.current=!1,document.body.style.cursor="",document.body.style.userSelect="",window.removeEventListener("mousemove",L),window.removeEventListener("mouseup",oe)};window.addEventListener("mousemove",L),window.addEventListener("mouseup",oe)},[]),Ge=w.useCallback(async(le,L,oe,Ee,Me,Ne)=>{var Ve;f(L),v("Reading file..."),j(null);let Pe=!1,qe=null,nt=!1;try{const Et=await t(`/api/stories/${le}/${L}`);if(!Et.ok)throw new Error("Failed to read file");const Nt=await Et.json(),Gt=je[le];let Rt=null,ki=null;if(L==="genesis.md")try{const ei=await t(`/api/stories/${le}/structure.md`);ei.ok&&(Rt=(await ei.json()).content??null)}catch{}else if(Gt==="cartoon"&&L.match(/^plot-\d+\.md$/))try{const ei=await t(`/api/stories/${le}/cuts/${L.replace(/\.md$/,"")}`);ei.ok&&(ki=(await ei.json()).title??null)}catch{}const mr=Cm({fileName:L,fileContent:Nt.content,storySlug:le,structureContent:Rt,contentType:Gt,episodeTitle:ki});if(Gt==="cartoon"&&zo(mr,L))return v(L==="genesis.md"?"Add a real “# Title” heading to genesis.md before publishing — it would otherwise publish as a raw filename.":"Set an episode title in the cut plan before publishing — it would otherwise publish as a raw filename."),setTimeout(()=>{f(null),v("")},6e3),!1;if(Gt==="cartoon"&&L.match(/^plot-\d+\.md$/)&&!wm({fileContent:Nt.content,episodeTitle:ki}))return v("Set a real episode title in the cut plan (or add a “# Title” to the episode) before publishing — a generic “Episode NN” placeholder can’t be published."),setTimeout(()=>{f(null),v("")},6e3),!1;if(Gt==="cartoon"&&L==="genesis.md"){const ei=bm(Nt.content).blockers;if(ei.length>0)return v(`Genesis is the reader-facing Story opening — fix it before publishing: ${ei[0]}`),setTimeout(()=>{f(null),v("")},6e3),!1}let Jt;if(L.match(/^plot-\d+\.md$/)){if(dM(Nt)){v("Already published on PlotLink — republishing would create a duplicate chapter. Open it on PlotLink instead (or use Retry Index if it isn't showing yet)."),setTimeout(()=>{f(null),v("")},6e3);return}try{const ei=await t(`/api/stories/${le}`);if(ei.ok){const Fn=(await ei.json()).files.find(ar=>ar.file==="genesis.md"&&ar.storylineId);Jt=Fn==null?void 0:Fn.storylineId}}catch{}if(!Jt)return v("Error: Publish genesis first to create the storyline"),setTimeout(()=>{f(null),v("")},3e3),!1}v("Checking wallet balance...");try{const ei=await t("/api/publish/preflight");if(ei.ok){const Br=await ei.json();if(pM(Br))return j(mM(Br)),f(null),v(""),!1}}catch{}v("Publishing...");const qi=await t("/api/publish/file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({storyName:le,fileName:L,title:mr,content:Nt.content,genre:oe,language:Ee,isNsfw:Me,storylineId:Jt,...by(je,le,Jt)?{contentType:by(je,le,Jt)}:{}})});if(!qi.ok){const ei=await qi.json();throw new Error(ei.error||"Publish failed")}const $n=(Ve=qi.body)==null?void 0:Ve.getReader(),gr=new TextDecoder;if($n)for(;;){const{done:ei,value:Br}=await $n.read();if(ei)break;const ar=gr.decode(Br).split(`
-`).filter(Wi=>Wi.startsWith("data: "));for(const Wi of ar)try{const Ct=JSON.parse(Wi.slice(6));if(Ct.step&&v(Ct.message||Ct.step),Ct.step==="done"&&Ct.txHash){if(nt=!0,await t(`/api/stories/${le}/${L}/publish-status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({txHash:Ct.txHash,storylineId:Ct.storylineId,plotIndex:Ct.plotIndex,contentCid:Ct.contentCid,gasCost:Ct.gasCost,indexError:Ct.indexError,authorAddress:R})}),x(qn=>qn+1),Ne&&L==="genesis.md"&&Ct.storylineId){v("Uploading cover...");let qn=null;try{qn=await oM(t,Ct.storylineId,Ne)}catch{}qn||(Pe=!0)}if(Gt==="cartoon"&&Ct.storylineId)try{const qn=L!=="genesis.md",ya=`storylineId=${Ct.storylineId}`+(qn&&Ct.plotIndex!=null?`&plotIndex=${Ct.plotIndex}`:""),Lr=await t(`/api/publish/public-title?${ya}`);if(Lr.ok){const Fs=await Lr.json(),xr=qn?{plots:Fs.plotTitle!=null?[{plotIndex:Ct.plotIndex,title:Fs.plotTitle}]:[]}:{title:Fs.storylineTitle},Ei=$M({fileName:L,detail:xr,plotIndex:Ct.plotIndex});Ei.ok||(qe=FM(Ei))}}catch{}}}catch{}}qe&&j(qe),v(Pe?"Published, but cover upload failed — set it later from Edit Story.":"Published!")}catch(Et){const Nt=Et instanceof Error?Et.message:"Publish failed";v(`Error: ${Nt}`)}finally{setTimeout(()=>{f(null),v("")},3e3)}return nt&&!Pe},[t,je,R]),$e=w.useCallback(le=>{le.startsWith("_new_")&&(F(L=>L.filter(oe=>oe!==le)),Te.current.delete(le),Ue.current.delete(le),it.current.delete(le),Wt.current.delete(le),ne(L=>{if(!(le in L))return L;const oe={...L};return delete oe[le],oe}),Y(L=>{if(!(le in L))return L;const oe={...L};return delete oe[le],oe}))},[]);w.useEffect(()=>{const le=oe=>{_e(new Set(oe.filter(Ve=>Ve.hasStructure).map(Ve=>Ve.name))),Le(new Set(oe.filter(Ve=>Ve.hasGenesis).map(Ve=>Ve.name)));const Ee={},Me={},Ne={},Pe={},qe={},nt={};for(const Ve of oe)Ee[Ve.name]=Ve.contentType||"fiction",Me[Ve.name]=Ve.language,Ne[Ve.name]=Ve.genre,Pe[Ve.name]=Ve.isNsfw,qe[Ve.name]=Ve.agentProvider,Ve.title&&(nt[Ve.name]=Ve.title);be(Ee),St(Me),We(Ne),He(Pe),mi(qe),Ae(nt)};t("/api/stories").then(oe=>oe.ok?oe.json():null).then(oe=>{oe!=null&&oe.stories&&le(oe.stories)}).catch(()=>{});const L=setInterval(async()=>{try{const oe=await t("/api/stories");if(oe.ok){const Ee=await oe.json();le(Ee.stories)}}catch{}},5e3);return()=>clearInterval(L)},[t]);const ht=!!T&&T.codex.installed&&T.codex.imageGeneration==="enabled",dt=!!T&&!ht,lt=w.useCallback(async()=>{try{await navigator.clipboard.writeText("codex features enable image_generation"),C(!0),setTimeout(()=>C(!1),2e3)}catch{}},[]),Vt=w.useCallback(async()=>{if(!i||i.startsWith("_new_"))return;const le=i;if((await t(`/api/stories/${le}/metadata`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({contentType:"cartoon",agentProvider:"codex"})})).ok){mi(oe=>({...oe,[le]:"codex"})),Y(oe=>({...oe,[le]:"codex"}));try{const oe=await t("/api/stories");if(oe.ok){const Ee=await oe.json();if(Ee!=null&&Ee.stories){const Me={};for(const Ne of Ee.stories)Me[Ne.name]=Ne.agentProvider;mi(Me)}}}catch{}}},[t,i]),Ci=w.useCallback(le=>{i===le&&(s(null),o(null))},[i]),ft=i?ae[i]??Kt[i]:void 0,Fi=Lf(i,je,Te.current),En=fM(Fi,ft,i),ln=!!i&&Fi==="cartoon",Un=c==="story-info"?"story-info":c==="episodes"?"episodes":c==="publish"?"publish":a==="structure.md"?"whitepaper":a==="genesis.md"?"genesis":a&&/^plot-\d+\.md$/.test(a)?"episodes":"progress",on=w.useCallback(le=>{const L=i;if(L)switch(le){case"progress":h(null),o(null);break;case"story-info":h("story-info");break;case"episodes":h("episodes");break;case"whitepaper":P(L,"structure.md");break;case"genesis":P(L,"genesis.md");break;case"publish":h("publish");break}},[i,P]),gn=w.useCallback((le,L)=>{const oe=i;if(oe)switch(le){case"view-progress":h(null),o(null);break;case"publish":h("publish");break;case"open-cuts":case"open-lettering":case"upload":case"refresh-assets":case"generate-markdown":L&&P(oe,L);break}},[i,P]),cn=w.useCallback(le=>{i&&(le.genre!==void 0&&We(L=>({...L,[i]:le.genre||void 0})),le.language!==void 0&&St(L=>({...L,[i]:le.language||void 0})),le.isNsfw!==void 0&&He(L=>({...L,[i]:le.isNsfw})))},[i]),pr=w.useCallback(le=>{Qe(le),ge(!le)},[]),Lt=wt&&!Q;return d.jsxs("div",{ref:vt,className:"h-[calc(100vh-3.5rem)] flex","data-testid":Lt?"stories-focused-lettering-mode":"stories-default-layout",children:[!Lt&&d.jsx("div",{className:"w-56 border-r border-border flex-shrink-0",children:d.jsx(kC,{authFetch:t,selectedStory:i,selectedFile:a,onSelectFile:P,onNewStory:Ze,untitledSessions:te})}),!Lt&&d.jsx("div",{className:"min-w-0 border-r border-border",style:{flex:`${N} 0 0`},children:d.jsx(ZE,{token:e,storyName:i,authFetch:t,onSelectStory:ze,onDestroySession:$e,onArchiveStory:Ci,confirmedStories:he,renameRef:Bt,bypassStories:V,agentProviders:ae,readiness:T,contentType:Lf(i,je,Te.current),needsProviderRepair:En,onRepairProvider:Vt})}),!Lt&&d.jsx("div",{onMouseDown:Re,className:"flex-shrink-0 flex items-center justify-center hover:bg-border/50 transition-colors",style:{width:If,cursor:"col-resize",background:"var(--border)"},children:d.jsxs("div",{className:"flex flex-col gap-1",children:[d.jsx("div",{className:"w-0.5 h-0.5 rounded-full",style:{background:"var(--text-muted)"}}),d.jsx("div",{className:"w-0.5 h-0.5 rounded-full",style:{background:"var(--text-muted)"}}),d.jsx("div",{className:"w-0.5 h-0.5 rounded-full",style:{background:"var(--text-muted)"}})]})}),d.jsxs("div",{className:"min-w-0 flex flex-col",style:Lt?{flex:"1 0 0"}:{flex:`${1-N} 0 0`},children:[!wt&&ln&&i&&d.jsx(zM,{storyTitle:xt[i]||i,active:Un,onSelect:on}),!wt&&ln&&i&&c!==null&&d.jsx("div",{className:"flex-shrink-0 border-b border-border","data-testid":"workflow-context-next-action",children:d.jsx(wM,{storyName:i,authFetch:t,refreshKey:_,onCoachAction:gn,onOpenStoryInfo:()=>h("story-info")})}),ln&&c==="story-info"&&i?d.jsx(PM,{storyName:i,authFetch:t,onSaved:cn}):ln&&c==="episodes"&&i?d.jsx(IM,{storyName:i,authFetch:t,onOpenFile:P}):ln&&c==="publish"&&i?d.jsx(HM,{storyName:i,authFetch:t,onOpenFile:P,onOpenStoryInfo:()=>h("story-info"),onPublish:Ge,publishingFile:p,genre:ot[i],language:tt[i],isNsfw:Mt[i],refreshKey:_}):i&&!a?d.jsx(kM,{storyName:i,authFetch:t,onOpenFile:P,onOpenStoryInfo:()=>h("story-info")}):d.jsx(vM,{storyName:i,fileName:a,authFetch:t,onPublish:Ge,publishingFile:p,walletAddress:R,contentType:Lf(i,je,Te.current)||"fiction",language:i?tt[i]:void 0,genre:i?ot[i]:void 0,isNsfw:i?Mt[i]:void 0,hasGenesis:i?Be.has(i):!1,onViewProgress:()=>o(null),onOpenFile:le=>i&&P(i,le),onViewPublish:()=>h("publish"),focusedLetteringMode:wt,focusedLetteringWorkspaceVisible:Q,onFocusedLetteringModeChange:pr,onFocusedLetteringWorkspaceVisibleChange:ge}),b&&d.jsx("div",{className:"px-3 py-1.5 bg-surface border-t border-border text-xs text-muted",children:b}),S&&d.jsxs("div",{className:"px-3 py-2 bg-error/10 border-t border-error/40 text-xs text-error flex items-start justify-between gap-3","data-testid":"publish-block-error",role:"alert",children:[d.jsx("span",{children:S}),d.jsx("button",{type:"button",onClick:()=>j(null),className:"shrink-0 text-error/70 hover:text-error underline","data-testid":"publish-block-error-dismiss",children:"Dismiss"})]})]}),D&&d.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center",style:{background:"rgba(240, 235, 225, 0.9)"},children:d.jsxs("div",{className:"bg-surface border border-border rounded-lg shadow-lg p-6 max-w-sm w-full space-y-4",children:[d.jsx("h3",{className:"text-sm font-serif font-medium text-foreground text-center",children:"New Story"}),d.jsxs("label",{className:"block space-y-1",children:[d.jsxs("span",{className:"text-[10px] font-medium text-muted",children:["Title ",d.jsx("span",{className:"text-accent",children:"*"})]}),d.jsx("input",{type:"text",value:fe,onChange:le=>Se(le.target.value),placeholder:"e.g. 신의 세포","data-testid":"new-story-title",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Short description (optional)"}),d.jsx("input",{type:"text",value:H,onChange:le=>ce(le.target.value),placeholder:"One line about the story","data-testid":"new-story-description",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Genre (optional)"}),d.jsxs("select",{value:W,onChange:le=>K(le.target.value),"data-testid":"new-story-genre",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",children:[d.jsx("option",{value:"",children:"— Select later —"}),dl.map(le=>d.jsx("option",{value:le,children:le},le))]})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Language"}),d.jsx("select",{value:X,onChange:le=>U(le.target.value),className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",children:ts.map(le=>d.jsx("option",{value:le,children:le},le))})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Agent mode"}),d.jsxs("select",{value:A,onChange:le=>O(le.target.value),className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"agent-mode-select",children:[d.jsx("option",{value:"normal",children:"Normal (approve each action)"}),d.jsx("option",{value:"bypass",children:"Permissions Bypass (advanced)"})]}),A==="bypass"&&d.jsx("p",{className:"text-[10px] text-amber-700","data-testid":"agent-mode-warning",children:"Less safe: Claude can run actions without per-command approval."})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Provider"}),d.jsxs("select",{value:$,onChange:le=>xe(le.target.value),className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"agent-provider-select",children:[d.jsx("option",{value:"claude",children:"🤖 Claude (default)"}),d.jsx("option",{value:"codex",children:"🎨 Codex"})]}),d.jsx("p",{className:"text-[10px] text-muted","data-testid":"agent-provider-helper",children:$==="codex"?"Codex can generate clean cartoon images directly in the terminal.":"Claude prepares image prompts; you generate and upload clean images externally."})]}),d.jsx("p",{className:"text-xs text-muted text-center",children:"Choose a content type to create"}),!fe.trim()&&d.jsx("p",{className:"text-[10px] text-amber-700 text-center","data-testid":"new-story-title-required",children:"Enter a title to create your story."}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("button",{onClick:()=>hi("fiction",X,A,$),disabled:!fe.trim(),"data-testid":"create-fiction",className:"border border-border rounded-lg p-4 hover:border-accent hover:bg-accent/5 transition-colors text-center space-y-1 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:border-border disabled:hover:bg-transparent",children:[d.jsx("p",{className:"text-sm font-serif font-medium text-foreground",children:"Fiction"}),d.jsx("p",{className:"text-[11px] text-muted",children:"Novels, short stories, poetry"})]}),d.jsxs("div",{className:"space-y-1",children:[d.jsxs("button",{onClick:()=>hi("cartoon",X,A,"codex"),disabled:dt||!fe.trim(),"data-testid":"create-cartoon",className:"w-full border border-border rounded-lg p-4 hover:border-accent hover:bg-accent/5 transition-colors text-center space-y-1 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:border-border disabled:hover:bg-transparent",children:[d.jsx("p",{className:"text-sm font-serif font-medium text-foreground",children:"Cartoon"}),d.jsx("p",{className:"text-[11px] text-muted",children:"Comics, manga, webtoons"}),d.jsx("p",{className:"text-[11px] text-muted","data-testid":"cartoon-codex-note",children:"Cartoon mode requires Codex because the clean-image step needs image generation support."})]}),T&&!T.codex.installed&&d.jsxs("p",{className:"text-[11px] text-amber-700 text-left","data-testid":"cartoon-codex-warning",children:["Codex was not detected. Install the Codex CLI and sign in (e.g."," ",d.jsx("span",{className:"font-mono",children:"npm i -g @openai/codex"})," ","then ",d.jsx("span",{className:"font-mono",children:"codex login"}),") to create cartoons."]}),Eu(T)&&d.jsx("p",{className:"text-[11px] text-amber-700 text-left","data-testid":"cartoon-codex-auth-unknown",children:Up}),T&&T.codex.installed&&!Eu(T)&&T.codex.imageGeneration!=="enabled"&&d.jsxs("div",{"data-testid":"cartoon-codex-warning",children:[d.jsx("p",{className:"text-[11px] text-amber-700 text-left",children:"Codex is installed but image generation isn't enabled. Enable it, then reopen this dialog:"}),d.jsxs("div",{className:"mt-1 flex items-center gap-1",children:[d.jsx("code",{className:"flex-1 truncate rounded border border-border bg-surface px-1.5 py-1 text-left text-[10px] font-mono text-foreground",children:"codex features enable image_generation"}),d.jsx("button",{type:"button","data-testid":"copy-codex-enable",onClick:lt,className:"rounded border border-border px-2 py-1 text-[10px] text-muted hover:border-accent hover:text-accent transition-colors",children:G?"Copied!":"Copy"})]})]})]})]}),d.jsx("button",{onClick:()=>ie(!1),className:"w-full px-3 py-1.5 text-xs text-muted hover:text-foreground hover:bg-surface rounded text-center",children:"Cancel"})]})})]})}function YM({token:e,onComplete:t}){const[i,s]=w.useState(!1),[a,o]=w.useState(null),[c,h]=w.useState(!1),p=async()=>{s(!0),o(null);try{const f=await fetch("/api/wallet/create",{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}}),_=await f.json();if(!f.ok)throw new Error(_.error||"Wallet creation failed");h(!0)}catch(f){o(f instanceof Error?f.message:"Wallet creation failed")}s(!1)};return w.useEffect(()=>{p()},[]),d.jsxs("div",{className:"mx-auto max-w-sm p-6 text-center",children:[d.jsx("h2",{className:"text-accent mb-1 text-lg font-bold",children:"Wallet Setup"}),d.jsx("p",{className:"text-muted mb-6 text-xs",children:"creating your OWS wallet for on-chain publishing"}),i&&d.jsx("p",{className:"text-accent text-sm",children:"creating wallet..."}),a&&d.jsxs("div",{className:"space-y-4",children:[d.jsx("div",{className:"rounded border border-red-700/30 p-3 text-xs text-red-700",children:a}),d.jsx("button",{onClick:p,className:"border-accent text-accent hover:bg-accent/10 w-full rounded border px-4 py-2 text-sm font-medium transition-colors",children:"retry"})]}),c&&d.jsxs("div",{className:"space-y-4",children:[d.jsx("div",{className:"text-accent text-2xl",children:"✓"}),d.jsx("p",{className:"text-foreground text-sm font-medium",children:"wallet created"}),d.jsx("button",{onClick:t,className:"border-accent text-accent hover:bg-accent/10 w-full rounded border px-4 py-2 text-sm font-medium transition-colors",children:"continue"})]})]})}function KM({token:e,onLogout:t}){const[i,s]=w.useState("home"),[a,o]=w.useState(0),[c,h]=w.useState(null),p=w.useCallback(async(f,_)=>fetch(f,{..._,headers:{...(_==null?void 0:_.headers)||{},Authorization:`Bearer ${e}`}}),[e]);return w.useEffect(()=>{fetch("/api/health").then(f=>f.json()).then(f=>{f.version&&h(f.version)}).catch(()=>{})},[]),w.useEffect(()=>{async function f(){try{if(!(await(await p("/api/wallet")).json()).exists){s("wallet-setup");return}const b=await p("/api/stories");if(b.ok){const v=await b.json();o(v.stories.filter(S=>S.name!=="_example").length)}}catch{}}f()},[e]),d.jsxs("div",{className:"flex h-screen flex-col",children:[d.jsxs("header",{className:"border-border flex h-14 items-center justify-between border-b px-4 flex-shrink-0",children:[d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsx("button",{onClick:()=>{i!=="wallet-setup"&&s("home")},className:"flex items-center gap-2 hover:opacity-80",children:d.jsx("span",{className:"text-accent text-sm font-bold tracking-tight",children:"PlotLink OWS"})}),d.jsxs("span",{className:"text-muted text-[10px] uppercase tracking-wider",children:["writer",c?` v${c}`:""]})]}),i!=="wallet-setup"&&d.jsxs("nav",{className:"flex items-center gap-4",children:[d.jsx("button",{onClick:()=>s("stories"),className:`text-xs transition-colors ${i==="stories"?"text-accent":"text-muted hover:text-foreground"}`,children:"stories"}),d.jsx("button",{onClick:()=>s("dashboard"),className:`text-xs transition-colors ${i==="dashboard"?"text-accent":"text-muted hover:text-foreground"}`,children:"dashboard"}),d.jsx("button",{onClick:()=>s("settings"),className:`text-xs transition-colors ${i==="settings"?"text-accent":"text-muted hover:text-foreground"}`,children:"settings"}),d.jsx("button",{onClick:t,className:"text-muted hover:text-foreground text-xs transition-colors",children:"logout"})]})]}),d.jsxs("main",{className:"flex-1 min-h-0",children:[i==="home"&&d.jsxs("div",{className:"mx-auto max-w-lg space-y-6 p-8",children:[d.jsxs("div",{className:"text-center space-y-2",children:[d.jsx("h1",{className:"text-2xl font-serif text-foreground",children:"Write. Publish. Earn."}),d.jsx("p",{className:"text-muted text-sm",children:"Claude or Codex helps create your story. You publish it on-chain."})]}),d.jsxs("div",{className:"text-center space-y-3",children:[d.jsx("button",{onClick:()=>s("stories"),className:"bg-accent text-white hover:bg-accent-dim px-6 py-2.5 rounded text-sm font-medium transition-colors",children:"Start Writing"}),a>0&&d.jsxs("p",{className:"text-muted text-xs",children:[a," ",a===1?"story":"stories"," in progress"]})]}),d.jsxs("div",{className:"rounded border border-border p-4 space-y-2 text-xs text-muted",children:[d.jsx("p",{className:"font-medium text-foreground text-sm",children:"How it works"}),d.jsxs("ol",{className:"space-y-1.5 list-decimal list-inside",children:[d.jsxs("li",{children:["Open the ",d.jsx("strong",{children:"Stories"})," tab — your writing agent launches in the terminal"]}),d.jsx("li",{children:"Tell the agent your story idea — it brainstorms, outlines, and writes"}),d.jsx("li",{children:"Review the live preview as the agent creates files"}),d.jsxs("li",{children:["Click ",d.jsx("strong",{children:"Publish"})," to put your story on-chain"]}),d.jsxs("li",{children:["Earn 5% royalties on every trade at ",d.jsx("a",{href:"https://plotlink.xyz",target:"_blank",rel:"noopener noreferrer",className:"text-accent underline",children:"plotlink.xyz"})]})]}),d.jsx("p",{className:"text-[11px] text-muted",children:"Fiction defaults to Claude; cartoon mode uses Codex for clean-image generation."})]}),d.jsx("div",{className:"text-center",children:d.jsx("a",{href:"https://github.com/realproject7/plotlink-ows#-wallet-setup",target:"_blank",rel:"noopener noreferrer",className:"text-xs text-muted hover:text-accent underline transition-colors",children:"Wallet Setup Guide"})}),d.jsx(jy,{token:e})]}),i==="stories"&&d.jsx(GM,{token:e,authFetch:p}),i==="dashboard"&&d.jsx(SC,{token:e}),i==="wallet-setup"&&d.jsx(YM,{token:e,onComplete:()=>s("home")}),i==="settings"&&d.jsx(vC,{token:e,onLogout:t})]})]})}function VM(){const[e,t]=w.useState(()=>localStorage.getItem("ows-token")),[i,s]=w.useState(null),[a,o]=w.useState(!0);w.useEffect(()=>{fetch("/api/auth/status").then(f=>f.json()).then(f=>s(f.configured)).catch(()=>s(null))},[]),w.useEffect(()=>{if(!e){o(!1);return}fetch("/api/auth/verify",{headers:{Authorization:`Bearer ${e}`}}).then(f=>{f.ok||(localStorage.removeItem("ows-token"),t(null))}).catch(()=>{localStorage.removeItem("ows-token"),t(null)}).finally(()=>o(!1))},[e]);const c=async f=>{try{const _=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({passphrase:f})}),x=await _.json();return _.ok?(localStorage.setItem("ows-token",x.token),t(x.token),null):x.error||"Login failed"}catch{return"Cannot connect to server"}},h=async f=>{try{const _=await fetch("/api/auth/setup",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({passphrase:f})}),x=await _.json();return _.ok?(localStorage.setItem("ows-token",x.token),t(x.token),s(!0),null):x.error||"Setup failed"}catch{return"Cannot connect to server"}},p=()=>{localStorage.removeItem("ows-token"),t(null)};return a||i===null?d.jsx("div",{className:"flex h-screen items-center justify-center",children:d.jsx("span",{className:"text-muted text-sm",children:"connecting..."})}):i?e?d.jsx(KM,{token:e,onLogout:p}):d.jsx(_C,{onLogin:c}):d.jsx(bC,{onSetup:h})}xC.createRoot(document.getElementById("root")).render(d.jsx(cC.StrictMode,{children:d.jsx(VM,{})}));export{zp as M,hu as a,M3 as b,ID as c,L3 as d,uu as l,HS as s,G3 as t,e4 as v};
+`).filter(Wi=>Wi.startsWith("data: "));for(const Wi of ar)try{const Ct=JSON.parse(Wi.slice(6));if(Ct.step&&v(Ct.message||Ct.step),Ct.step==="done"&&Ct.txHash){if(nt=!0,await t(`/api/stories/${le}/${L}/publish-status`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({txHash:Ct.txHash,storylineId:Ct.storylineId,plotIndex:Ct.plotIndex,contentCid:Ct.contentCid,gasCost:Ct.gasCost,indexError:Ct.indexError,authorAddress:R})}),x(qn=>qn+1),Ne&&L==="genesis.md"&&Ct.storylineId){v("Uploading cover...");let qn=null;try{qn=await oM(t,Ct.storylineId,Ne)}catch{}qn||(Pe=!0)}if(Gt==="cartoon"&&Ct.storylineId)try{const qn=L!=="genesis.md",ya=`storylineId=${Ct.storylineId}`+(qn&&Ct.plotIndex!=null?`&plotIndex=${Ct.plotIndex}`:""),Lr=await t(`/api/publish/public-title?${ya}`);if(Lr.ok){const Fs=await Lr.json(),xr=qn?{plots:Fs.plotTitle!=null?[{plotIndex:Ct.plotIndex,title:Fs.plotTitle}]:[]}:{title:Fs.storylineTitle},Ei=$M({fileName:L,detail:xr,plotIndex:Ct.plotIndex});Ei.ok||(qe=FM(Ei))}}catch{}}}catch{}}qe&&j(qe),v(Pe?"Published, but cover upload failed — set it later from Edit Story.":"Published!")}catch(Et){const Nt=Et instanceof Error?Et.message:"Publish failed";v(`Error: ${Nt}`)}finally{setTimeout(()=>{f(null),v("")},3e3)}return nt&&!Pe},[t,je,R]),$e=w.useCallback(le=>{le.startsWith("_new_")&&(F(L=>L.filter(oe=>oe!==le)),Te.current.delete(le),Ue.current.delete(le),it.current.delete(le),Wt.current.delete(le),ne(L=>{if(!(le in L))return L;const oe={...L};return delete oe[le],oe}),Y(L=>{if(!(le in L))return L;const oe={...L};return delete oe[le],oe}))},[]);w.useEffect(()=>{const le=oe=>{_e(new Set(oe.filter(Ve=>Ve.hasStructure).map(Ve=>Ve.name))),Le(new Set(oe.filter(Ve=>Ve.hasGenesis).map(Ve=>Ve.name)));const Ee={},Me={},Ne={},Pe={},qe={},nt={};for(const Ve of oe)Ee[Ve.name]=Ve.contentType||"fiction",Me[Ve.name]=Ve.language,Ne[Ve.name]=Ve.genre,Pe[Ve.name]=Ve.isNsfw,qe[Ve.name]=Ve.agentProvider,Ve.title&&(nt[Ve.name]=Ve.title);be(Ee),St(Me),We(Ne),He(Pe),mi(qe),Ae(nt)};t("/api/stories").then(oe=>oe.ok?oe.json():null).then(oe=>{oe!=null&&oe.stories&&le(oe.stories)}).catch(()=>{});const L=setInterval(async()=>{try{const oe=await t("/api/stories");if(oe.ok){const Ee=await oe.json();le(Ee.stories)}}catch{}},5e3);return()=>clearInterval(L)},[t]);const ht=!!T&&T.codex.installed&&T.codex.imageGeneration==="enabled",dt=!!T&&!ht,lt=w.useCallback(async()=>{try{await navigator.clipboard.writeText("codex features enable image_generation"),C(!0),setTimeout(()=>C(!1),2e3)}catch{}},[]),Vt=w.useCallback(async()=>{if(!i||i.startsWith("_new_"))return;const le=i;if((await t(`/api/stories/${le}/metadata`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({contentType:"cartoon",agentProvider:"codex"})})).ok){mi(oe=>({...oe,[le]:"codex"})),Y(oe=>({...oe,[le]:"codex"}));try{const oe=await t("/api/stories");if(oe.ok){const Ee=await oe.json();if(Ee!=null&&Ee.stories){const Me={};for(const Ne of Ee.stories)Me[Ne.name]=Ne.agentProvider;mi(Me)}}}catch{}}},[t,i]),Ci=w.useCallback(le=>{i===le&&(s(null),o(null))},[i]),ft=i?ae[i]??Kt[i]:void 0,Fi=Lf(i,je,Te.current),En=fM(Fi,ft,i),ln=!!i&&Fi==="cartoon",Un=c==="story-info"?"story-info":c==="episodes"?"episodes":c==="publish"?"publish":a==="structure.md"?"whitepaper":a==="genesis.md"?"genesis":a&&/^plot-\d+\.md$/.test(a)?"episodes":"progress",on=w.useCallback(le=>{const L=i;if(L)switch(le){case"progress":h(null),o(null);break;case"story-info":h("story-info");break;case"episodes":h("episodes");break;case"whitepaper":P(L,"structure.md");break;case"genesis":P(L,"genesis.md");break;case"publish":h("publish");break}},[i,P]),gn=w.useCallback((le,L)=>{const oe=i;if(oe)switch(le){case"view-progress":h(null),o(null);break;case"publish":h("publish");break;case"open-cuts":case"open-lettering":case"upload":case"refresh-assets":case"generate-markdown":L&&P(oe,L);break}},[i,P]),cn=w.useCallback(le=>{i&&(le.genre!==void 0&&We(L=>({...L,[i]:le.genre||void 0})),le.language!==void 0&&St(L=>({...L,[i]:le.language||void 0})),le.isNsfw!==void 0&&He(L=>({...L,[i]:le.isNsfw})))},[i]),pr=w.useCallback(le=>{Qe(le),ge(!le)},[]),Lt=wt&&!Q;return d.jsxs("div",{ref:vt,className:"h-[calc(100vh-3.5rem)] flex","data-testid":Lt?"stories-focused-lettering-mode":"stories-default-layout",children:[!Lt&&d.jsx("div",{className:"w-56 border-r border-border flex-shrink-0",children:d.jsx(kC,{authFetch:t,selectedStory:i,selectedFile:a,onSelectFile:P,onNewStory:Ze,untitledSessions:te})}),!Lt&&d.jsx("div",{className:"min-w-0 border-r border-border",style:{flex:`${N} 0 0`},children:d.jsx(ZE,{token:e,storyName:i,authFetch:t,onSelectStory:ze,onDestroySession:$e,onArchiveStory:Ci,confirmedStories:he,renameRef:Bt,bypassStories:V,agentProviders:ae,readiness:T,contentType:Lf(i,je,Te.current),needsProviderRepair:En,onRepairProvider:Vt})}),!Lt&&d.jsx("div",{onMouseDown:Re,className:"flex-shrink-0 flex items-center justify-center hover:bg-border/50 transition-colors",style:{width:If,cursor:"col-resize",background:"var(--border)"},children:d.jsxs("div",{className:"flex flex-col gap-1",children:[d.jsx("div",{className:"w-0.5 h-0.5 rounded-full",style:{background:"var(--text-muted)"}}),d.jsx("div",{className:"w-0.5 h-0.5 rounded-full",style:{background:"var(--text-muted)"}}),d.jsx("div",{className:"w-0.5 h-0.5 rounded-full",style:{background:"var(--text-muted)"}})]})}),d.jsxs("div",{className:"min-w-0 min-h-0 flex flex-col",style:Lt?{flex:"1 0 0"}:{flex:`${1-N} 0 0`},children:[!wt&&ln&&i&&d.jsx(zM,{storyTitle:xt[i]||i,active:Un,onSelect:on}),!wt&&ln&&i&&c!==null&&d.jsx("div",{className:"flex-shrink-0 border-b border-border","data-testid":"workflow-context-next-action",children:d.jsx(wM,{storyName:i,authFetch:t,refreshKey:_,onCoachAction:gn,onOpenStoryInfo:()=>h("story-info")})}),d.jsx("div",{className:"flex-1 min-h-0 flex flex-col",children:ln&&c==="story-info"&&i?d.jsx(PM,{storyName:i,authFetch:t,onSaved:cn}):ln&&c==="episodes"&&i?d.jsx(IM,{storyName:i,authFetch:t,onOpenFile:P}):ln&&c==="publish"&&i?d.jsx(HM,{storyName:i,authFetch:t,onOpenFile:P,onOpenStoryInfo:()=>h("story-info"),onPublish:Ge,publishingFile:p,genre:ot[i],language:tt[i],isNsfw:Mt[i],refreshKey:_}):i&&!a?d.jsx(kM,{storyName:i,authFetch:t,onOpenFile:P,onOpenStoryInfo:()=>h("story-info")}):d.jsx(vM,{storyName:i,fileName:a,authFetch:t,onPublish:Ge,publishingFile:p,walletAddress:R,contentType:Lf(i,je,Te.current)||"fiction",language:i?tt[i]:void 0,genre:i?ot[i]:void 0,isNsfw:i?Mt[i]:void 0,hasGenesis:i?Be.has(i):!1,onViewProgress:()=>o(null),onOpenFile:le=>i&&P(i,le),onViewPublish:()=>h("publish"),focusedLetteringMode:wt,focusedLetteringWorkspaceVisible:Q,onFocusedLetteringModeChange:pr,onFocusedLetteringWorkspaceVisibleChange:ge})}),b&&d.jsx("div",{className:"shrink-0 px-3 py-1.5 bg-surface border-t border-border text-xs text-muted",children:b}),S&&d.jsxs("div",{className:"shrink-0 px-3 py-2 bg-error/10 border-t border-error/40 text-xs text-error flex items-start justify-between gap-3","data-testid":"publish-block-error",role:"alert",children:[d.jsx("span",{children:S}),d.jsx("button",{type:"button",onClick:()=>j(null),className:"shrink-0 text-error/70 hover:text-error underline","data-testid":"publish-block-error-dismiss",children:"Dismiss"})]})]}),D&&d.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center",style:{background:"rgba(240, 235, 225, 0.9)"},children:d.jsxs("div",{className:"bg-surface border border-border rounded-lg shadow-lg p-6 max-w-sm w-full space-y-4",children:[d.jsx("h3",{className:"text-sm font-serif font-medium text-foreground text-center",children:"New Story"}),d.jsxs("label",{className:"block space-y-1",children:[d.jsxs("span",{className:"text-[10px] font-medium text-muted",children:["Title ",d.jsx("span",{className:"text-accent",children:"*"})]}),d.jsx("input",{type:"text",value:fe,onChange:le=>Se(le.target.value),placeholder:"e.g. 신의 세포","data-testid":"new-story-title",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Short description (optional)"}),d.jsx("input",{type:"text",value:H,onChange:le=>ce(le.target.value),placeholder:"One line about the story","data-testid":"new-story-description",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none"})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Genre (optional)"}),d.jsxs("select",{value:W,onChange:le=>K(le.target.value),"data-testid":"new-story-genre",className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",children:[d.jsx("option",{value:"",children:"— Select later —"}),dl.map(le=>d.jsx("option",{value:le,children:le},le))]})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Language"}),d.jsx("select",{value:X,onChange:le=>U(le.target.value),className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none",children:ts.map(le=>d.jsx("option",{value:le,children:le},le))})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Agent mode"}),d.jsxs("select",{value:A,onChange:le=>O(le.target.value),className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"agent-mode-select",children:[d.jsx("option",{value:"normal",children:"Normal (approve each action)"}),d.jsx("option",{value:"bypass",children:"Permissions Bypass (advanced)"})]}),A==="bypass"&&d.jsx("p",{className:"text-[10px] text-amber-700","data-testid":"agent-mode-warning",children:"Less safe: Claude can run actions without per-command approval."})]}),d.jsxs("label",{className:"block space-y-1",children:[d.jsx("span",{className:"text-[10px] font-medium text-muted",children:"Provider"}),d.jsxs("select",{value:$,onChange:le=>xe(le.target.value),className:"w-full px-2 py-1.5 text-xs border border-border rounded bg-transparent focus:border-accent focus:outline-none","data-testid":"agent-provider-select",children:[d.jsx("option",{value:"claude",children:"🤖 Claude (default)"}),d.jsx("option",{value:"codex",children:"🎨 Codex"})]}),d.jsx("p",{className:"text-[10px] text-muted","data-testid":"agent-provider-helper",children:$==="codex"?"Codex can generate clean cartoon images directly in the terminal.":"Claude prepares image prompts; you generate and upload clean images externally."})]}),d.jsx("p",{className:"text-xs text-muted text-center",children:"Choose a content type to create"}),!fe.trim()&&d.jsx("p",{className:"text-[10px] text-amber-700 text-center","data-testid":"new-story-title-required",children:"Enter a title to create your story."}),d.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[d.jsxs("button",{onClick:()=>hi("fiction",X,A,$),disabled:!fe.trim(),"data-testid":"create-fiction",className:"border border-border rounded-lg p-4 hover:border-accent hover:bg-accent/5 transition-colors text-center space-y-1 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:border-border disabled:hover:bg-transparent",children:[d.jsx("p",{className:"text-sm font-serif font-medium text-foreground",children:"Fiction"}),d.jsx("p",{className:"text-[11px] text-muted",children:"Novels, short stories, poetry"})]}),d.jsxs("div",{className:"space-y-1",children:[d.jsxs("button",{onClick:()=>hi("cartoon",X,A,"codex"),disabled:dt||!fe.trim(),"data-testid":"create-cartoon",className:"w-full border border-border rounded-lg p-4 hover:border-accent hover:bg-accent/5 transition-colors text-center space-y-1 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:border-border disabled:hover:bg-transparent",children:[d.jsx("p",{className:"text-sm font-serif font-medium text-foreground",children:"Cartoon"}),d.jsx("p",{className:"text-[11px] text-muted",children:"Comics, manga, webtoons"}),d.jsx("p",{className:"text-[11px] text-muted","data-testid":"cartoon-codex-note",children:"Cartoon mode requires Codex because the clean-image step needs image generation support."})]}),T&&!T.codex.installed&&d.jsxs("p",{className:"text-[11px] text-amber-700 text-left","data-testid":"cartoon-codex-warning",children:["Codex was not detected. Install the Codex CLI and sign in (e.g."," ",d.jsx("span",{className:"font-mono",children:"npm i -g @openai/codex"})," ","then ",d.jsx("span",{className:"font-mono",children:"codex login"}),") to create cartoons."]}),Eu(T)&&d.jsx("p",{className:"text-[11px] text-amber-700 text-left","data-testid":"cartoon-codex-auth-unknown",children:Up}),T&&T.codex.installed&&!Eu(T)&&T.codex.imageGeneration!=="enabled"&&d.jsxs("div",{"data-testid":"cartoon-codex-warning",children:[d.jsx("p",{className:"text-[11px] text-amber-700 text-left",children:"Codex is installed but image generation isn't enabled. Enable it, then reopen this dialog:"}),d.jsxs("div",{className:"mt-1 flex items-center gap-1",children:[d.jsx("code",{className:"flex-1 truncate rounded border border-border bg-surface px-1.5 py-1 text-left text-[10px] font-mono text-foreground",children:"codex features enable image_generation"}),d.jsx("button",{type:"button","data-testid":"copy-codex-enable",onClick:lt,className:"rounded border border-border px-2 py-1 text-[10px] text-muted hover:border-accent hover:text-accent transition-colors",children:G?"Copied!":"Copy"})]})]})]})]}),d.jsx("button",{onClick:()=>ie(!1),className:"w-full px-3 py-1.5 text-xs text-muted hover:text-foreground hover:bg-surface rounded text-center",children:"Cancel"})]})})]})}function YM({token:e,onComplete:t}){const[i,s]=w.useState(!1),[a,o]=w.useState(null),[c,h]=w.useState(!1),p=async()=>{s(!0),o(null);try{const f=await fetch("/api/wallet/create",{method:"POST",headers:{Authorization:`Bearer ${e}`,"Content-Type":"application/json"}}),_=await f.json();if(!f.ok)throw new Error(_.error||"Wallet creation failed");h(!0)}catch(f){o(f instanceof Error?f.message:"Wallet creation failed")}s(!1)};return w.useEffect(()=>{p()},[]),d.jsxs("div",{className:"mx-auto max-w-sm p-6 text-center",children:[d.jsx("h2",{className:"text-accent mb-1 text-lg font-bold",children:"Wallet Setup"}),d.jsx("p",{className:"text-muted mb-6 text-xs",children:"creating your OWS wallet for on-chain publishing"}),i&&d.jsx("p",{className:"text-accent text-sm",children:"creating wallet..."}),a&&d.jsxs("div",{className:"space-y-4",children:[d.jsx("div",{className:"rounded border border-red-700/30 p-3 text-xs text-red-700",children:a}),d.jsx("button",{onClick:p,className:"border-accent text-accent hover:bg-accent/10 w-full rounded border px-4 py-2 text-sm font-medium transition-colors",children:"retry"})]}),c&&d.jsxs("div",{className:"space-y-4",children:[d.jsx("div",{className:"text-accent text-2xl",children:"✓"}),d.jsx("p",{className:"text-foreground text-sm font-medium",children:"wallet created"}),d.jsx("button",{onClick:t,className:"border-accent text-accent hover:bg-accent/10 w-full rounded border px-4 py-2 text-sm font-medium transition-colors",children:"continue"})]})]})}function KM({token:e,onLogout:t}){const[i,s]=w.useState("home"),[a,o]=w.useState(0),[c,h]=w.useState(null),p=w.useCallback(async(f,_)=>fetch(f,{..._,headers:{...(_==null?void 0:_.headers)||{},Authorization:`Bearer ${e}`}}),[e]);return w.useEffect(()=>{fetch("/api/health").then(f=>f.json()).then(f=>{f.version&&h(f.version)}).catch(()=>{})},[]),w.useEffect(()=>{async function f(){try{if(!(await(await p("/api/wallet")).json()).exists){s("wallet-setup");return}const b=await p("/api/stories");if(b.ok){const v=await b.json();o(v.stories.filter(S=>S.name!=="_example").length)}}catch{}}f()},[e]),d.jsxs("div",{className:"flex h-screen flex-col",children:[d.jsxs("header",{className:"border-border flex h-14 items-center justify-between border-b px-4 flex-shrink-0",children:[d.jsxs("div",{className:"flex items-center gap-3",children:[d.jsx("button",{onClick:()=>{i!=="wallet-setup"&&s("home")},className:"flex items-center gap-2 hover:opacity-80",children:d.jsx("span",{className:"text-accent text-sm font-bold tracking-tight",children:"PlotLink OWS"})}),d.jsxs("span",{className:"text-muted text-[10px] uppercase tracking-wider",children:["writer",c?` v${c}`:""]})]}),i!=="wallet-setup"&&d.jsxs("nav",{className:"flex items-center gap-4",children:[d.jsx("button",{onClick:()=>s("stories"),className:`text-xs transition-colors ${i==="stories"?"text-accent":"text-muted hover:text-foreground"}`,children:"stories"}),d.jsx("button",{onClick:()=>s("dashboard"),className:`text-xs transition-colors ${i==="dashboard"?"text-accent":"text-muted hover:text-foreground"}`,children:"dashboard"}),d.jsx("button",{onClick:()=>s("settings"),className:`text-xs transition-colors ${i==="settings"?"text-accent":"text-muted hover:text-foreground"}`,children:"settings"}),d.jsx("button",{onClick:t,className:"text-muted hover:text-foreground text-xs transition-colors",children:"logout"})]})]}),d.jsxs("main",{className:"flex-1 min-h-0",children:[i==="home"&&d.jsxs("div",{className:"mx-auto max-w-lg space-y-6 p-8",children:[d.jsxs("div",{className:"text-center space-y-2",children:[d.jsx("h1",{className:"text-2xl font-serif text-foreground",children:"Write. Publish. Earn."}),d.jsx("p",{className:"text-muted text-sm",children:"Claude or Codex helps create your story. You publish it on-chain."})]}),d.jsxs("div",{className:"text-center space-y-3",children:[d.jsx("button",{onClick:()=>s("stories"),className:"bg-accent text-white hover:bg-accent-dim px-6 py-2.5 rounded text-sm font-medium transition-colors",children:"Start Writing"}),a>0&&d.jsxs("p",{className:"text-muted text-xs",children:[a," ",a===1?"story":"stories"," in progress"]})]}),d.jsxs("div",{className:"rounded border border-border p-4 space-y-2 text-xs text-muted",children:[d.jsx("p",{className:"font-medium text-foreground text-sm",children:"How it works"}),d.jsxs("ol",{className:"space-y-1.5 list-decimal list-inside",children:[d.jsxs("li",{children:["Open the ",d.jsx("strong",{children:"Stories"})," tab — your writing agent launches in the terminal"]}),d.jsx("li",{children:"Tell the agent your story idea — it brainstorms, outlines, and writes"}),d.jsx("li",{children:"Review the live preview as the agent creates files"}),d.jsxs("li",{children:["Click ",d.jsx("strong",{children:"Publish"})," to put your story on-chain"]}),d.jsxs("li",{children:["Earn 5% royalties on every trade at ",d.jsx("a",{href:"https://plotlink.xyz",target:"_blank",rel:"noopener noreferrer",className:"text-accent underline",children:"plotlink.xyz"})]})]}),d.jsx("p",{className:"text-[11px] text-muted",children:"Fiction defaults to Claude; cartoon mode uses Codex for clean-image generation."})]}),d.jsx("div",{className:"text-center",children:d.jsx("a",{href:"https://github.com/realproject7/plotlink-ows#-wallet-setup",target:"_blank",rel:"noopener noreferrer",className:"text-xs text-muted hover:text-accent underline transition-colors",children:"Wallet Setup Guide"})}),d.jsx(jy,{token:e})]}),i==="stories"&&d.jsx(GM,{token:e,authFetch:p}),i==="dashboard"&&d.jsx(SC,{token:e}),i==="wallet-setup"&&d.jsx(YM,{token:e,onComplete:()=>s("home")}),i==="settings"&&d.jsx(vC,{token:e,onLogout:t})]})]})}function VM(){const[e,t]=w.useState(()=>localStorage.getItem("ows-token")),[i,s]=w.useState(null),[a,o]=w.useState(!0);w.useEffect(()=>{fetch("/api/auth/status").then(f=>f.json()).then(f=>s(f.configured)).catch(()=>s(null))},[]),w.useEffect(()=>{if(!e){o(!1);return}fetch("/api/auth/verify",{headers:{Authorization:`Bearer ${e}`}}).then(f=>{f.ok||(localStorage.removeItem("ows-token"),t(null))}).catch(()=>{localStorage.removeItem("ows-token"),t(null)}).finally(()=>o(!1))},[e]);const c=async f=>{try{const _=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({passphrase:f})}),x=await _.json();return _.ok?(localStorage.setItem("ows-token",x.token),t(x.token),null):x.error||"Login failed"}catch{return"Cannot connect to server"}},h=async f=>{try{const _=await fetch("/api/auth/setup",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({passphrase:f})}),x=await _.json();return _.ok?(localStorage.setItem("ows-token",x.token),t(x.token),s(!0),null):x.error||"Setup failed"}catch{return"Cannot connect to server"}},p=()=>{localStorage.removeItem("ows-token"),t(null)};return a||i===null?d.jsx("div",{className:"flex h-screen items-center justify-center",children:d.jsx("span",{className:"text-muted text-sm",children:"connecting..."})}):i?e?d.jsx(KM,{token:e,onLogout:p}):d.jsx(_C,{onLogin:c}):d.jsx(bC,{onSetup:h})}xC.createRoot(document.getElementById("root")).render(d.jsx(cC.StrictMode,{children:d.jsx(VM,{})}));export{zp as M,hu as a,M3 as b,ID as c,L3 as d,uu as l,HS as s,G3 as t,e4 as v};
diff --git a/app/web/dist/assets/index-CcfChGEK.css b/app/web/dist/assets/index-MOqpTOzP.css
similarity index 74%
rename from app/web/dist/assets/index-CcfChGEK.css
rename to app/web/dist/assets/index-MOqpTOzP.css
index 680cde2..b389744 100644
--- a/app/web/dist/assets/index-CcfChGEK.css
+++ b/app/web/dist/assets/index-MOqpTOzP.css
@@ -29,4 +29,4 @@
* The original design remains. The terminal itself
* has been extended to include xterm CSI codes, among
* other features.
- */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-950:oklch(27.9% .077 45.635);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-300:oklch(87.1% .15 154.449);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-950:oklch(26.6% .065 152.934);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--aspect-video:16 / 9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent;font-family:Inter,system-ui,-apple-system,sans-serif;line-height:1.5}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.start\!{inset-inline-start:var(--spacing)!important}.end{inset-inline-end:var(--spacing)}.-top-1\.5{top:calc(var(--spacing) * -1.5)}.top-1{top:calc(var(--spacing) * 1)}.-right-1\.5{right:calc(var(--spacing) * -1.5)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.bottom-0{bottom:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-3{margin:calc(var(--spacing) * 3)}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-auto{margin-inline:auto}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows),0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-video{aspect-ratio:var(--aspect-video)}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-\[calc\(100vh-3\.5rem\)\]{height:calc(100vh - 3.5rem)}.h-full{height:100%}.h-screen{height:100vh}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-\[32rem\]{max-height:32rem}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-28{min-height:calc(var(--spacing) * 28)}.min-h-56{min-height:calc(var(--spacing) * 56)}.min-h-\[22rem\]{min-height:22rem}.w-0\.5{width:calc(var(--spacing) * .5)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-56{width:calc(var(--spacing) * 56)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-\[32rem\]{max-width:32rem}.max-w-\[120px\]{max-width:120px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[140px\]{min-width:140px}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-move{cursor:move}.cursor-pointer{cursor:pointer}.cursor-se-resize{cursor:se-resize}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent{border-color:#8b4513}.border-accent-dim\/30{border-color:#6b34104d}.border-accent\/30{border-color:#8b45134d}.border-accent\/40{border-color:#8b451366}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-500{border-color:var(--color-amber-500)}.border-amber-500\/40{border-color:#f99c0066}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/40{border-color:color-mix(in oklab,var(--color-amber-500) 40%,transparent)}}.border-amber-500\/50{border-color:#f99c0080}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/50{border-color:color-mix(in oklab,var(--color-amber-500) 50%,transparent)}}.border-amber-600\/30{border-color:#dd74004d}@supports (color:color-mix(in lab,red,red)){.border-amber-600\/30{border-color:color-mix(in oklab,var(--color-amber-600) 30%,transparent)}}.border-border{border-color:#d4c5b0}.border-border\/70{border-color:#d4c5b0b3}.border-border\/80{border-color:#d4c5b0cc}.border-error\/15{border-color:#cc333326}.border-error\/30{border-color:#cc33334d}.border-error\/40{border-color:#c336}.border-foreground\/40{border-color:#2c181066}.border-green-300{border-color:var(--color-green-300)}.border-green-700\/25{border-color:#00813840}@supports (color:color-mix(in lab,red,red)){.border-green-700\/25{border-color:color-mix(in oklab,var(--color-green-700) 25%,transparent)}}.border-green-700\/30{border-color:#0081384d}@supports (color:color-mix(in lab,red,red)){.border-green-700\/30{border-color:color-mix(in oklab,var(--color-green-700) 30%,transparent)}}.border-green-700\/40{border-color:#00813866}@supports (color:color-mix(in lab,red,red)){.border-green-700\/40{border-color:color-mix(in oklab,var(--color-green-700) 40%,transparent)}}.border-muted\/40{border-color:#8b735566}.border-red-700\/30{border-color:#bf000f4d}@supports (color:color-mix(in lab,red,red)){.border-red-700\/30{border-color:color-mix(in oklab,var(--color-red-700) 30%,transparent)}}.border-transparent{border-color:#0000}.bg-\[\#f4efe6\]\/85{background-color:#f4efe6d9}.bg-\[\#f8f5ef\]{background-color:#f8f5ef}.bg-accent{background-color:#8b4513}.bg-accent\/5{background-color:#8b45130d}.bg-accent\/10{background-color:#8b45131a}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-950\/10{background-color:#4619011a}@supports (color:color-mix(in lab,red,red)){.bg-amber-950\/10{background-color:color-mix(in oklab,var(--color-amber-950) 10%,transparent)}}.bg-background{background-color:#e8dfd0}.bg-background\/40{background-color:#e8dfd066}.bg-background\/50{background-color:#e8dfd080}.bg-background\/60{background-color:#e8dfd099}.bg-background\/70{background-color:#e8dfd0b3}.bg-error{background-color:#c33}.bg-error\/5{background-color:#cc33330d}.bg-error\/10{background-color:#cc33331a}.bg-foreground{background-color:#2c1810}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-600{background-color:var(--color-green-600)}.bg-green-600\/10{background-color:#00a5441a}@supports (color:color-mix(in lab,red,red)){.bg-green-600\/10{background-color:color-mix(in oklab,var(--color-green-600) 10%,transparent)}}.bg-green-700\/10{background-color:#0081381a}@supports (color:color-mix(in lab,red,red)){.bg-green-700\/10{background-color:color-mix(in oklab,var(--color-green-700) 10%,transparent)}}.bg-green-950\/5{background-color:#032e150d}@supports (color:color-mix(in lab,red,red)){.bg-green-950\/5{background-color:color-mix(in oklab,var(--color-green-950) 5%,transparent)}}.bg-muted\/40{background-color:#8b735566}.bg-muted\/50{background-color:#8b735580}.bg-surface{background-color:#f0ebe1}.bg-surface\/35{background-color:#f0ebe159}.bg-surface\/40{background-color:#f0ebe166}.bg-surface\/50{background-color:#f0ebe180}.bg-surface\/60{background-color:#f0ebe199}.bg-surface\/70{background-color:#f0ebe1b3}.bg-surface\/80{background-color:#f0ebe1cc}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.fill-white\/95{fill:#fffffff2}@supports (color:color-mix(in lab,red,red)){.fill-white\/95{fill:color-mix(in oklab,var(--color-white) 95%,transparent)}}.stroke-\[\#1a1a1a\]{stroke:#1a1a1a}.stroke-accent{stroke:#8b4513}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-16{padding-right:calc(var(--spacing) * 16)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.14em\]{--tw-tracking:.14em;letter-spacing:.14em}.tracking-\[0\.16em\]{--tw-tracking:.16em;letter-spacing:.16em}.tracking-\[0\.18em\]{--tw-tracking:.18em;letter-spacing:.18em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#1a1a1a\]{color:#1a1a1a}.text-\[\#3a3a3a\]{color:#3a3a3a}.text-accent{color:#8b4513}.text-accent-dim{color:#6b3410}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-background{color:#e8dfd0}.text-error{color:#c33}.text-error\/70{color:#cc3333b3}.text-foreground{color:#2c1810}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-muted{color:#8b7355}.text-muted\/70{color:#8b7355b3}.text-red-700{color:var(--color-red-700)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-accent{--tw-ring-color:#8b4513}.ring-amber-500{--tw-ring-color:var(--color-amber-500)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-muted\/50::placeholder{color:#8b735580}@media(hover:hover){.hover\:border-accent:hover{border-color:#8b4513}.hover\:border-error:hover{border-color:#c33}.hover\:bg-accent-dim:hover{background-color:#6b3410}.hover\:bg-accent\/5:hover{background-color:#8b45130d}.hover\:bg-accent\/10:hover{background-color:#8b45131a}.hover\:bg-amber-500\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.hover\:bg-border\/50:hover{background-color:#d4c5b080}.hover\:bg-error\/5:hover{background-color:#cc33330d}.hover\:bg-error\/10:hover{background-color:#cc33331a}.hover\:bg-green-700\/5:hover{background-color:#0081380d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-green-700\/5:hover{background-color:color-mix(in oklab,var(--color-green-700) 5%,transparent)}}.hover\:bg-surface:hover{background-color:#f0ebe1}.hover\:text-accent:hover{color:#8b4513}.hover\:text-accent-dim:hover{color:#6b3410}.hover\:text-error:hover{color:#c33}.hover\:text-foreground:hover{color:#2c1810}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-80:hover{opacity:.8}}.focus\:border-accent:focus{border-color:#8b4513}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media(hover:hover){.disabled\:hover\:border-border:disabled:hover{border-color:#d4c5b0}.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}@media(min-width:40rem){.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}:root{--bg:#e8dfd0;--bg-surface:#f0ebe1;--bg-shelf:#ddd3c2;--text:#2c1810;--text-muted:#8b7355;--accent:#8b4513;--accent-dim:#6b3410;--border:#d4c5b0;--error:#c33;--paper-bg:#f5f0e8}body{background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,system-ui,-apple-system,sans-serif}::selection{background:var(--accent);color:#fff}h1,h2,h3,h4{font-family:Lora,Georgia,Times New Roman,serif}.prose{--tw-prose-body:var(--text);--tw-prose-headings:var(--text);--tw-prose-links:var(--accent);--tw-prose-bold:var(--text);--tw-prose-quotes:var(--text-muted);--tw-prose-quote-borders:var(--border);--tw-prose-code:var(--text);--tw-prose-hr:var(--border)}.prose,.prose p,.prose li,.prose blockquote{font-family:Lora,Georgia,Times New Roman,serif}code,pre{font-family:Geist Mono,ui-monospace,monospace}.cartoon-awaiting-upload{border-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.cartoon-awaiting-upload{border-color:color-mix(in srgb,var(--accent) 30%,transparent)}}.cartoon-awaiting-upload{background:var(--accent)}@supports (color:color-mix(in lab,red,red)){.cartoon-awaiting-upload{background:color-mix(in srgb,var(--accent) 5%,transparent)}}.xterm .xterm-dim{opacity:1!important;color:#8b7355!important}.xterm,.xterm-viewport{border:none!important;outline:none!important}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
+ */.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-serif:ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-700:oklch(50.5% .213 27.518);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-950:oklch(27.9% .077 45.635);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-300:oklch(87.1% .15 154.449);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-950:oklch(26.6% .065 152.934);--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--aspect-video:16 / 9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent;font-family:Inter,system-ui,-apple-system,sans-serif;line-height:1.5}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.start\!{inset-inline-start:var(--spacing)!important}.end{inset-inline-end:var(--spacing)}.-top-1\.5{top:calc(var(--spacing) * -1.5)}.top-1{top:calc(var(--spacing) * 1)}.-right-1\.5{right:calc(var(--spacing) * -1.5)}.right-0{right:calc(var(--spacing) * 0)}.right-1{right:calc(var(--spacing) * 1)}.bottom-0{bottom:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-3{margin:calc(var(--spacing) * 3)}.-mx-1{margin-inline:calc(var(--spacing) * -1)}.mx-auto{margin-inline:auto}.prose{color:var(--tw-prose-body);max-width:65ch}.prose :where(p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where([class~=lead]):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-lead);margin-top:1.2em;margin-bottom:1.2em;font-size:1.25em;line-height:1.6}.prose :where(a):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-links);font-weight:500;text-decoration:underline}.prose :where(strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-bold);font-weight:600}.prose :where(a strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote strong):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:decimal}.prose :where(ol[type=A]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=A s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-alpha}.prose :where(ol[type=a s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-alpha}.prose :where(ol[type=I]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type=I s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:upper-roman}.prose :where(ol[type=i s]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:lower-roman}.prose :where(ol[type="1"]):not(:where([class~=not-prose],[class~=not-prose] *)){list-style-type:decimal}.prose :where(ul):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em;padding-inline-start:1.625em;list-style-type:disc}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-counters);font-weight:400}.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *))::marker{color:var(--tw-prose-bullets)}.prose :where(dt):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.25em;font-weight:600}.prose :where(hr):not(:where([class~=not-prose],[class~=not-prose] *)){border-color:var(--tw-prose-hr);border-top-width:1px;margin-top:3em;margin-bottom:3em}.prose :where(blockquote):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-quotes);border-inline-start-width:.25rem;border-inline-start-color:var(--tw-prose-quote-borders);quotes:"“""”""‘""’";margin-top:1.6em;margin-bottom:1.6em;padding-inline-start:1em;font-style:italic;font-weight:500}.prose :where(blockquote p:first-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):before{content:open-quote}.prose :where(blockquote p:last-of-type):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:close-quote}.prose :where(h1):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:0;margin-bottom:.888889em;font-size:2.25em;font-weight:800;line-height:1.11111}.prose :where(h1 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:900}.prose :where(h2):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:2em;margin-bottom:1em;font-size:1.5em;font-weight:700;line-height:1.33333}.prose :where(h2 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:800}.prose :where(h3):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.6em;margin-bottom:.6em;font-size:1.25em;font-weight:600;line-height:1.6}.prose :where(h3 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(h4):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);margin-top:1.5em;margin-bottom:.5em;font-weight:600;line-height:1.5}.prose :where(h4 strong):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-weight:700}.prose :where(img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(picture):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em;display:block}.prose :where(video):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(kbd):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-kbd);box-shadow:0 0 0 1px var(--tw-prose-kbd-shadows),0 3px 0 var(--tw-prose-kbd-shadows);padding-top:.1875em;padding-inline-end:.375em;padding-bottom:.1875em;border-radius:.3125rem;padding-inline-start:.375em;font-family:inherit;font-size:.875em;font-weight:500}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-code);font-size:.875em;font-weight:600}.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:"`"}.prose :where(a code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h1 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(h2 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.875em}.prose :where(h3 code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit;font-size:.9em}.prose :where(h4 code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(blockquote code):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(thead th code):not(:where([class~=not-prose],[class~=not-prose] *)){color:inherit}.prose :where(pre):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-pre-code);background-color:var(--tw-prose-pre-bg);padding-top:.857143em;padding-inline-end:1.14286em;padding-bottom:.857143em;border-radius:.375rem;margin-top:1.71429em;margin-bottom:1.71429em;padding-inline-start:1.14286em;font-size:.875em;font-weight:400;line-height:1.71429;overflow-x:auto}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)){font-weight:inherit;color:inherit;font-size:inherit;font-family:inherit;line-height:inherit;background-color:#0000;border-width:0;border-radius:0;padding:0}.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):before,.prose :where(pre code):not(:where([class~=not-prose],[class~=not-prose] *)):after{content:none}.prose :where(table):not(:where([class~=not-prose],[class~=not-prose] *)){table-layout:auto;width:100%;margin-top:2em;margin-bottom:2em;font-size:.875em;line-height:1.71429}.prose :where(thead):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-th-borders)}.prose :where(thead th):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-headings);vertical-align:bottom;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em;font-weight:600}.prose :where(tbody tr):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:1px;border-bottom-color:var(--tw-prose-td-borders)}.prose :where(tbody tr:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){border-bottom-width:0}.prose :where(tbody td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:baseline}.prose :where(tfoot):not(:where([class~=not-prose],[class~=not-prose] *)){border-top-width:1px;border-top-color:var(--tw-prose-th-borders)}.prose :where(tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){vertical-align:top}.prose :where(th,td):not(:where([class~=not-prose],[class~=not-prose] *)){text-align:start}.prose :where(figure>*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(figcaption):not(:where([class~=not-prose],[class~=not-prose] *)){color:var(--tw-prose-captions);margin-top:.857143em;font-size:.875em;line-height:1.42857}.prose{--tw-prose-body:oklch(37.3% .034 259.733);--tw-prose-headings:oklch(21% .034 264.665);--tw-prose-lead:oklch(44.6% .03 256.802);--tw-prose-links:oklch(21% .034 264.665);--tw-prose-bold:oklch(21% .034 264.665);--tw-prose-counters:oklch(55.1% .027 264.364);--tw-prose-bullets:oklch(87.2% .01 258.338);--tw-prose-hr:oklch(92.8% .006 264.531);--tw-prose-quotes:oklch(21% .034 264.665);--tw-prose-quote-borders:oklch(92.8% .006 264.531);--tw-prose-captions:oklch(55.1% .027 264.364);--tw-prose-kbd:oklch(21% .034 264.665);--tw-prose-kbd-shadows:oklab(21% -.00316127 -.0338527/.1);--tw-prose-code:oklch(21% .034 264.665);--tw-prose-pre-code:oklch(92.8% .006 264.531);--tw-prose-pre-bg:oklch(27.8% .033 256.848);--tw-prose-th-borders:oklch(87.2% .01 258.338);--tw-prose-td-borders:oklch(92.8% .006 264.531);--tw-prose-invert-body:oklch(87.2% .01 258.338);--tw-prose-invert-headings:#fff;--tw-prose-invert-lead:oklch(70.7% .022 261.325);--tw-prose-invert-links:#fff;--tw-prose-invert-bold:#fff;--tw-prose-invert-counters:oklch(70.7% .022 261.325);--tw-prose-invert-bullets:oklch(44.6% .03 256.802);--tw-prose-invert-hr:oklch(37.3% .034 259.733);--tw-prose-invert-quotes:oklch(96.7% .003 264.542);--tw-prose-invert-quote-borders:oklch(37.3% .034 259.733);--tw-prose-invert-captions:oklch(70.7% .022 261.325);--tw-prose-invert-kbd:#fff;--tw-prose-invert-kbd-shadows:#ffffff1a;--tw-prose-invert-code:#fff;--tw-prose-invert-pre-code:oklch(87.2% .01 258.338);--tw-prose-invert-pre-bg:#00000080;--tw-prose-invert-th-borders:oklch(44.6% .03 256.802);--tw-prose-invert-td-borders:oklch(37.3% .034 259.733);font-size:1rem;line-height:1.75}.prose :where(picture>img):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0;margin-bottom:0}.prose :where(li):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;margin-bottom:.5em}.prose :where(ol>li):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(ul>li):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:.375em}.prose :where(.prose>ul>li p):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(.prose>ul>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ul>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(.prose>ol>li>p:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em}.prose :where(.prose>ol>li>p:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:1.25em}.prose :where(ul ul,ul ol,ol ul,ol ol):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.75em;margin-bottom:.75em}.prose :where(dl):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:1.25em;margin-bottom:1.25em}.prose :where(dd):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:.5em;padding-inline-start:1.625em}.prose :where(hr+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h2+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h3+*):not(:where([class~=not-prose],[class~=not-prose] *)),.prose :where(h4+*):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(thead th:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(thead th:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(tbody td,tfoot td):not(:where([class~=not-prose],[class~=not-prose] *)){padding-top:.571429em;padding-inline-end:.571429em;padding-bottom:.571429em;padding-inline-start:.571429em}.prose :where(tbody td:first-child,tfoot td:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-start:0}.prose :where(tbody td:last-child,tfoot td:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){padding-inline-end:0}.prose :where(figure):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:2em;margin-bottom:2em}.prose :where(.prose>:first-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-top:0}.prose :where(.prose>:last-child):not(:where([class~=not-prose],[class~=not-prose] *)){margin-bottom:0}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-3{margin-left:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-video{aspect-ratio:var(--aspect-video)}.h-0\.5{height:calc(var(--spacing) * .5)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-\[calc\(100vh-3\.5rem\)\]{height:calc(100vh - 3.5rem)}.h-full{height:100%}.h-screen{height:100vh}.max-h-72{max-height:calc(var(--spacing) * 72)}.max-h-\[32rem\]{max-height:32rem}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-28{min-height:calc(var(--spacing) * 28)}.min-h-56{min-height:calc(var(--spacing) * 56)}.min-h-\[22rem\]{min-height:22rem}.w-0\.5{width:calc(var(--spacing) * .5)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-14{width:calc(var(--spacing) * 14)}.w-16{width:calc(var(--spacing) * 16)}.w-56{width:calc(var(--spacing) * 56)}.w-64{width:calc(var(--spacing) * 64)}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-\[32rem\]{max-width:32rem}.max-w-\[120px\]{max-width:120px}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-none{max-width:none}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[140px\]{min-width:140px}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-move{cursor:move}.cursor-pointer{cursor:pointer}.cursor-se-resize{cursor:se-resize}.resize{resize:both}.resize-none{resize:none}.resize-y{resize:vertical}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-2{border-bottom-style:var(--tw-border-style);border-bottom-width:2px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent{border-color:#8b4513}.border-accent-dim\/30{border-color:#6b34104d}.border-accent\/30{border-color:#8b45134d}.border-accent\/40{border-color:#8b451366}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-500{border-color:var(--color-amber-500)}.border-amber-500\/40{border-color:#f99c0066}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/40{border-color:color-mix(in oklab,var(--color-amber-500) 40%,transparent)}}.border-amber-500\/50{border-color:#f99c0080}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/50{border-color:color-mix(in oklab,var(--color-amber-500) 50%,transparent)}}.border-amber-600\/30{border-color:#dd74004d}@supports (color:color-mix(in lab,red,red)){.border-amber-600\/30{border-color:color-mix(in oklab,var(--color-amber-600) 30%,transparent)}}.border-border{border-color:#d4c5b0}.border-border\/70{border-color:#d4c5b0b3}.border-border\/80{border-color:#d4c5b0cc}.border-error\/15{border-color:#cc333326}.border-error\/30{border-color:#cc33334d}.border-error\/40{border-color:#c336}.border-foreground\/40{border-color:#2c181066}.border-green-300{border-color:var(--color-green-300)}.border-green-700\/25{border-color:#00813840}@supports (color:color-mix(in lab,red,red)){.border-green-700\/25{border-color:color-mix(in oklab,var(--color-green-700) 25%,transparent)}}.border-green-700\/30{border-color:#0081384d}@supports (color:color-mix(in lab,red,red)){.border-green-700\/30{border-color:color-mix(in oklab,var(--color-green-700) 30%,transparent)}}.border-green-700\/40{border-color:#00813866}@supports (color:color-mix(in lab,red,red)){.border-green-700\/40{border-color:color-mix(in oklab,var(--color-green-700) 40%,transparent)}}.border-muted\/40{border-color:#8b735566}.border-red-700\/30{border-color:#bf000f4d}@supports (color:color-mix(in lab,red,red)){.border-red-700\/30{border-color:color-mix(in oklab,var(--color-red-700) 30%,transparent)}}.border-transparent{border-color:#0000}.bg-\[\#f4efe6\]\/85{background-color:#f4efe6d9}.bg-\[\#f8f5ef\]{background-color:#f8f5ef}.bg-accent{background-color:#8b4513}.bg-accent\/5{background-color:#8b45130d}.bg-accent\/10{background-color:#8b45131a}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-500{background-color:var(--color-amber-500)}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-950\/10{background-color:#4619011a}@supports (color:color-mix(in lab,red,red)){.bg-amber-950\/10{background-color:color-mix(in oklab,var(--color-amber-950) 10%,transparent)}}.bg-background{background-color:#e8dfd0}.bg-background\/40{background-color:#e8dfd066}.bg-background\/50{background-color:#e8dfd080}.bg-background\/60{background-color:#e8dfd099}.bg-background\/70{background-color:#e8dfd0b3}.bg-error{background-color:#c33}.bg-error\/5{background-color:#cc33330d}.bg-error\/10{background-color:#cc33331a}.bg-foreground{background-color:#2c1810}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-600{background-color:var(--color-green-600)}.bg-green-600\/10{background-color:#00a5441a}@supports (color:color-mix(in lab,red,red)){.bg-green-600\/10{background-color:color-mix(in oklab,var(--color-green-600) 10%,transparent)}}.bg-green-700\/10{background-color:#0081381a}@supports (color:color-mix(in lab,red,red)){.bg-green-700\/10{background-color:color-mix(in oklab,var(--color-green-700) 10%,transparent)}}.bg-green-950\/5{background-color:#032e150d}@supports (color:color-mix(in lab,red,red)){.bg-green-950\/5{background-color:color-mix(in oklab,var(--color-green-950) 5%,transparent)}}.bg-muted\/40{background-color:#8b735566}.bg-muted\/50{background-color:#8b735580}.bg-surface{background-color:#f0ebe1}.bg-surface\/35{background-color:#f0ebe159}.bg-surface\/40{background-color:#f0ebe166}.bg-surface\/50{background-color:#f0ebe180}.bg-surface\/60{background-color:#f0ebe199}.bg-surface\/70{background-color:#f0ebe1b3}.bg-surface\/80{background-color:#f0ebe1cc}.bg-surface\/95{background-color:#f0ebe1f2}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.fill-white\/95{fill:#fffffff2}@supports (color:color-mix(in lab,red,red)){.fill-white\/95{fill:color-mix(in oklab,var(--color-white) 95%,transparent)}}.stroke-\[\#1a1a1a\]{stroke:#1a1a1a}.stroke-accent{stroke:#8b4513}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pr-16{padding-right:calc(var(--spacing) * 16)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.14em\]{--tw-tracking:.14em;letter-spacing:.14em}.tracking-\[0\.16em\]{--tw-tracking:.16em;letter-spacing:.16em}.tracking-\[0\.18em\]{--tw-tracking:.18em;letter-spacing:.18em}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#1a1a1a\]{color:#1a1a1a}.text-\[\#3a3a3a\]{color:#3a3a3a}.text-accent{color:#8b4513}.text-accent-dim{color:#6b3410}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-background{color:#e8dfd0}.text-error{color:#c33}.text-error\/70{color:#cc3333b3}.text-foreground{color:#2c1810}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-muted{color:#8b7355}.text-muted\/70{color:#8b7355b3}.text-red-700{color:var(--color-red-700)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.overline{text-decoration-line:overline}.underline{text-decoration-line:underline}.opacity-90{opacity:.9}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-accent{--tw-ring-color:#8b4513}.ring-amber-500{--tw-ring-color:var(--color-amber-500)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.placeholder\:text-muted\/50::placeholder{color:#8b735580}@media(hover:hover){.hover\:border-accent:hover{border-color:#8b4513}.hover\:border-error:hover{border-color:#c33}.hover\:bg-accent-dim:hover{background-color:#6b3410}.hover\:bg-accent\/5:hover{background-color:#8b45130d}.hover\:bg-accent\/10:hover{background-color:#8b45131a}.hover\:bg-amber-500\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.hover\:bg-border\/50:hover{background-color:#d4c5b080}.hover\:bg-error\/5:hover{background-color:#cc33330d}.hover\:bg-error\/10:hover{background-color:#cc33331a}.hover\:bg-green-700\/5:hover{background-color:#0081380d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-green-700\/5:hover{background-color:color-mix(in oklab,var(--color-green-700) 5%,transparent)}}.hover\:bg-surface:hover{background-color:#f0ebe1}.hover\:text-accent:hover{color:#8b4513}.hover\:text-accent-dim:hover{color:#6b3410}.hover\:text-error:hover{color:#c33}.hover\:text-foreground:hover{color:#2c1810}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-80:hover{opacity:.8}}.focus\:border-accent:focus{border-color:#8b4513}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}@media(hover:hover){.disabled\:hover\:border-border:disabled:hover{border-color:#d4c5b0}.disabled\:hover\:bg-transparent:disabled:hover{background-color:#0000}}@media(min-width:40rem){.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}:root{--bg:#e8dfd0;--bg-surface:#f0ebe1;--bg-shelf:#ddd3c2;--text:#2c1810;--text-muted:#8b7355;--accent:#8b4513;--accent-dim:#6b3410;--border:#d4c5b0;--error:#c33;--paper-bg:#f5f0e8}body{background:var(--bg);color:var(--text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:Inter,system-ui,-apple-system,sans-serif}::selection{background:var(--accent);color:#fff}h1,h2,h3,h4{font-family:Lora,Georgia,Times New Roman,serif}.prose{--tw-prose-body:var(--text);--tw-prose-headings:var(--text);--tw-prose-links:var(--accent);--tw-prose-bold:var(--text);--tw-prose-quotes:var(--text-muted);--tw-prose-quote-borders:var(--border);--tw-prose-code:var(--text);--tw-prose-hr:var(--border)}.prose,.prose p,.prose li,.prose blockquote{font-family:Lora,Georgia,Times New Roman,serif}code,pre{font-family:Geist Mono,ui-monospace,monospace}.cartoon-awaiting-upload{border-color:var(--accent)}@supports (color:color-mix(in lab,red,red)){.cartoon-awaiting-upload{border-color:color-mix(in srgb,var(--accent) 30%,transparent)}}.cartoon-awaiting-upload{background:var(--accent)}@supports (color:color-mix(in lab,red,red)){.cartoon-awaiting-upload{background:color-mix(in srgb,var(--accent) 5%,transparent)}}.xterm .xterm-dim{opacity:1!important;color:#8b7355!important}.xterm,.xterm-viewport{border:none!important;outline:none!important}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
diff --git a/app/web/dist/index.html b/app/web/dist/index.html
index c8a0649..945db14 100644
--- a/app/web/dist/index.html
+++ b/app/web/dist/index.html
@@ -7,8 +7,8 @@
-
-
+
+