1const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-CU1pmUEt.js","assets/react-vendor-CR6PEHFZ.js","assets/MangaScanAssistant-DARMIoT0.js","assets/index-4BgFHtDy.js","assets/charts-B4FZmgI2.js","assets/motion-CJOt5odT.js","assets/sentry-vendor-TOuwz_QY.js","assets/index-CUNhJJWQ.css","assets/draft-store-DH5pQtab.js","assets/camera-restored-BKDmeAJy.js","assets/rotate-cw-PjidL_px.js","assets/users-D9aOiDv4.js","assets/rotate-ccw-CmJRy1RL.js","assets/chevron-right-DpQDBVGz.js","assets/trash-2-CKdhC_W2.js","assets/copy-Bo9hK7aO.js","assets/image-plus-Bl5FO-YI.js","assets/arrow-left-B0N2HE9_.js","assets/triangle-alert-BSz8P4Zw.js","assets/shield-check-Cz-R6yjW.js","assets/PaintedText-C3MsEoHx.js","assets/PaintedText-B6L5zXof.css","assets/useWCTabScrollReset-BPl6Zvom.js","assets/onboarding-tour-queue-C1gdrxkC.js","assets/useVisualViewportRect-D1a4QLn_.js","assets/onboarding-tour-queue-CHKIFB_1.css","assets/useOnboardingFlags-D5_aYXjw.js","assets/jszip.min-CIuVNJzu.js","assets/TokenHoverPanel-BPJCNrJq.js","assets/skeleton-Dqg2zJt1.js","assets/SpeakButton-Bf7X3Knc.js","assets/index-Dzam33Lf.js","assets/lesson-audio-cache-BBYDfZEq.js","assets/volume-2-Dv69TRyb.js","assets/PitchAccentCarousel-Dyzc6lO4.js","assets/PitchAccentSVG-DQwSD2bK.js","assets/FuriganaText-D7mGyRZV.js","assets/HeroMangaDemo-BIOdmhrU.js","assets/deinflect-_j_61N1_.js","assets/dictionary-store-Cz5Fufi7.js","assets/HeroMangaDemo-CeoAqPdV.css","assets/reader-theater-_cvP9JZb.css","assets/frequency-label-DG0_6bpz.js","assets/sanitize-html-B826E86q.js","assets/purify.es-2FREwzWT.js","assets/example-highlight-goh9CouE.js","assets/types-DOXej13I.js","assets/swipe-gesture-Dmets-y-.js","assets/popup-positioning-exIlhfJJ.js","assets/index-qrFtx_x8.js","assets/TokenHoverPanel-SFm-jOLJ.css","assets/index-BnQD89Lm.js","assets/index-BdQq_4o_.js","assets/index-COLRoJoj.js","assets/switch-DfMS08QT.js","assets/label-CovdD990.js","assets/index-B_LjxDKQ.js","assets/keyboard-hint-U5-MhE8J.js","assets/client-CEnDzE1Z.js","assets/api-DytoebzF.js","assets/book-open-BUUeTAgN.js","assets/list-aNX20yg4.js","assets/settings-BJGNVyk8.js","assets/useCreditWallet-ChOMb_5V.js","assets/WCFilterSelect-Dbe6tJKu.js","assets/loader-circle-DgPKf1KX.js","assets/useRovingRadioGroup-aQT8rihS.js","assets/media-mnemonic-coverage-BtoubcyO.js","assets/media-mnemonic-coverage-Da5trjYc.css","assets/RailArtwork-Cp1Qge4W.js","assets/RailArtwork-CGQs6hw6.css","assets/WCSidebarSelection-Cb1TWNa8.js","assets/WCEmptyState-B8IO2YhP.js","assets/WCPagination-CMPekwbu.js","assets/select-FQw6rmPW.js","assets/sliders-horizontal-DJKNB2Z4.js","assets/heart-CXtFyYSY.js","assets/square-B8hjxiHH.js","assets/AnimatedCursor-DSpjVTQ-.js","assets/ModuleNextUp-DSNvsQCL.js","assets/module-next-up-UZuMEJeE.css","assets/WCSignupGate-D4ErDc4r.js","assets/bookmark-plus-CpgAFK0A.js","assets/SourceTypewriter-CgJBTIXy.js","assets/pause-COwvhF_2.js","assets/play-B3bwd9OM.js","assets/keyboard-CLLv-0VQ.js","assets/layers-Df5PU6Jc.js","assets/circle-check-CUzFLvbA.js","assets/atmosphereSafeZones-B11pJ5DC.js","assets/immersion-logged-CarrPWYq.css"])))=>i.map(i=>d[i]); 2import{z as ja,w as ue,e as ps,aR as Gl,i as ne,_ as Rs,E as bs,bw as cs,as as Fo,bx as $a,Y as Ps,A as Xu,u as xo,a$ as Yl,b as xn,j as Xn,by as Jl,bz as eo,bA as Xl,bB as Ql,bC as to,a4 as Qa,C as Ys,a3 as Qu,bD as Ap,bE as rn,bF as Gr,aT as rs,aM as Zu,aN as Ip,a2 as vs,ah as em,ai as In,bG as Zl,ak as ec,q as tc,ao as Rp,aq as $p,ar as rd,bH as Do,bI as ar,bJ as Lo,b1 as tm,bv as dr,b5 as ds,n as zp,W as ac,bK as Hn,bL as Gs,X as Yn,s as sc,ag as am,bM as Fp,a as Dp}from"./index-4BgFHtDy.js";import{j as e,r as o,b as hi,d as Os,f as nc,L as Wn,h as Lp}from"./react-vendor-CR6PEHFZ.js";import{P as Op}from"./PaintedText-C3MsEoHx.js";import{u as Bp}from"./useWCTabScrollReset-BPl6Zvom.js";import{G as qp,a as id}from"./onboarding-tour-queue-C1gdrxkC.js";import{u as sm}from"./useOnboardingFlags-D5_aYXjw.js";import{J as _r,U as Sr,B as Up,F as Rn}from"./jszip.min-CIuVNJzu.js";import{R as Kt,c as rc,a as ic,u as oc,T as lc}from"./TokenHoverPanel-BPJCNrJq.js";import{A as Oa,m as ze,u as wn}from"./motion-CJOt5odT.js";import{R as Vp,T as Kp,a as Hp,b as Wp}from"./index-BnQD89Lm.js";import{S as $n}from"./switch-DfMS08QT.js";import{n as cc,a as nm,m as rm,e as Gp,b as od,i as ld,l as Yp,g as dc,N as si,c as Jp,d as Xp,H as im,f as Qp}from"./HeroMangaDemo-BIOdmhrU.js";import{L as Zp,M as ef,C as Oi,P as cd,a as tf,b as af,S as om,F as lm}from"./label-CovdD990.js";import{a as sf}from"./keyboard-hint-U5-MhE8J.js";import{c as nf}from"./client-CEnDzE1Z.js";import{u as rf,c as of}from"./api-DytoebzF.js";import{u as lf}from"./useVisualViewportRect-D1a4QLn_.js";import{a as cf}from"./SpeakButton-Bf7X3Knc.js";import{F as df}from"./FuriganaText-D7mGyRZV.js";import{A as Za}from"./arrow-left-B0N2HE9_.js";import{B as ss}from"./book-open-BUUeTAgN.js";import{C as As}from"./chevron-right-DpQDBVGz.js";import{L as uf}from"./list-aNX20yg4.js";import{S as cm}from"./settings-BJGNVyk8.js";import{u as dm}
2from"./useCreditWallet-ChOMb_5V.js";import{T as ni}from"./triangle-alert-BSz8P4Zw.js";import{W as Yr,F as on,T as Jr}from"./WCFilterSelect-Dbe6tJKu.js";import{L as Sa}from"./loader-circle-DgPKf1KX.js";import{u as mf}from"./useRovingRadioGroup-aQT8rihS.js";import{A as hf,C as Xr}from"./media-mnemonic-coverage-BtoubcyO.js";import{S as pf}from"./shield-check-Cz-R6yjW.js";import{M as ff,S as gf}from"./RailArtwork-Cp1Qge4W.js";import{W as yf,a as bf}from"./WCSidebarSelection-Cb1TWNa8.js";/* empty css */import{o as Is,a as Ks,n as Ya,c as xf,s as Ka}from"./lesson-audio-cache-BBYDfZEq.js";import{W as Br}from"./WCEmptyState-B8IO2YhP.js";import{W as wf}from"./WCPagination-CMPekwbu.js";import{S as Oo,a as Bo,b as qo,c as Uo,d as Si}from"./select-FQw6rmPW.js";import{S as vf}from"./sliders-horizontal-DJKNB2Z4.js";import{H as um}from"./heart-CXtFyYSY.js";import{S as wo,U as mm,E as ri,a as xr,C as Ws,P as hm}from"./users-D9aOiDv4.js";import{P as vo,S as jf}from"./square-B8hjxiHH.js";import{R as pi}from"./rotate-ccw-CmJRy1RL.js";import{T as Ns}from"./trash-2-CKdhC_W2.js";import{A as kf}from"./AnimatedCursor-DSpjVTQ-.js";import{M as dd}from"./ModuleNextUp-DSNvsQCL.js";import{W as _f}from"./WCSignupGate-D4ErDc4r.js";import{B as Sf}from"./bookmark-plus-CpgAFK0A.js";import{S as Nf}from"./SourceTypewriter-CgJBTIXy.js";/* empty css *//* empty css */import{P as Cf}from"./pause-COwvhF_2.js";import{P as Ef}from"./play-B3bwd9OM.js";import{V as Tf}from"./volume-2-Dv69TRyb.js";import{K as Mf}from"./keyboard-CLLv-0VQ.js";import{L as Pf}from"./layers-Df5PU6Jc.js";import{C as Vo}from"./circle-check-CUzFLvbA.js";import{u as Af}from"./atmosphereSafeZones-B11pJ5DC.js";const If=[["path",{d:"M12 17V3",key:"1cwfxf"}],["path",{d:"m6 11 6 6 6-6",key:"12ii2o"}],["path",{d:"M19 21H5",key:"150jfl"}]],Rf=ja("arrow-down-to-line",If);const $f=[["path",{d:"M2 10v3",key:"1fnikh"}],["path",{d:"M6 6v11",key:"11sgs0"}],["path",{d:"M10 3v18",key:"yhl04a"}],["path",{d:"M14 8v7",key:"3a1oy3"}],["path",{d:"M18 5v13",key:"123xd1"}],["path",{d:"M22 10v3",key:"154ddg"}]],pm=ja("audio-lines",$f);const zf=[["path",{d:"M10 2v8l3-3 3 3V2",key:"sqw3rj"}],["path",{d:"M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H19a1 1 0 0 1 1 1v18a1 1 0 0 1-1 1H6.5a1 1 0 0 1 0-5H20",key:"k3hazp"}]],ud=ja("book-marked",zf);const Ff=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"10",x2:"10",y1:"15",y2:"9",key:"c1nkhi"}],["line",{x1:"14",x2:"14",y1:"15",y2:"9",key:"h65svq"}]],Df=ja("circle-pause",Ff);const Lf=[["path",{d:"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3Z",key:"1tn4o7"}],["path",{d:"m6.2 5.3 3.1 3.9",key:"iuk76l"}],["path",{d:"m12.4 3.4 3.1 4",key:"6hsd6n"}],["path",{d:"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z",key:"ltgou9"}]],md=ja("clapperboard",Lf);const Of=[["path",{d:"M17.5 19H9a7 7 0 1 1 6.71-9h1.79a4.5 4.5 0 1 1 0 9Z",key:"p7xjir"}]],Js=ja("cloud",Of);const Bf=[["path",{d:"M11.562 3.266a.5.5 0 0 1 .876 0L15.39 8.87a1 1 0 0 0 1.516.294L21.183 5.5a.5.5 0 0 1 .798.519l-2.834 10.246a1 1 0 0 1-.956.734H5.81a1 1 0 0 1-.957-.734L2.02 6.02a.5.5 0 0 1 .798-.519l4.276 3.664a1 1 0 0 0 1.516-.294z",key:"1vdc57"}],["path",{d:"M5 21h14",key:"11awu3"}]],fm=ja("crown",Bf);const qf=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"12",cy:"5",r:"1",key:"gxeob9"}],["circle",{cx:"12",cy:"19",r:"1",key:"lyex9k"}]],ao=ja("ellipsis-vertical",qf);const Uf=[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"19",cy:"12",r:"1",key:"1wjl8i"}],["circle",{cx:"5",cy:"12",r:"1",key:"1pcz8c"}]],jo=ja("ellipsis",Uf);const Vf=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M12 9v4",key:"juzpu7"}],["path",{d:"M12 17h.01",key:"p32p05"}]],Kf=ja("file-exclamation-point",Vf);const Hf=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M15.033 13.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56v-4.704a.645.645 0 0 1 .967-.56z",key:"1tzo1f"}]],hd=ja("file-play",Hf);const Wf=[["path",{d:"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z",key:"1oefj6"}],["path",{d:"M14 2v5a1 1 0 0 0 1 1h5",key:"wfsgrz"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]],Gf=ja("file-up",Wf);const Yf=[["path",{d:"M2 9V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-1",key:"fm4g5t"}],["path",{d:"M2 13h10",key:"pgb2dq"}],["path",{d:"m9 16 3-3-3-3",key:"6m91ic"}]],so=ja("folder-input",Yf);const Jf=[["path",{d:"M2 7.5V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-1.5",key:"1yk7aj"}],["path",{d:"M2 13h10",key:"pgb2dq"}],["path",{d:"m5 10-3 3 3 3",key:"1r8ie0"}]],Xf=ja("folder-output",Jf);const Qf=[["path",{d:"M12 10v6",key:"1bos4e"}],["path",{d:"M9 13h6",key:"1uhe8q"}],["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}
2]],pd=ja("folder-plus",Qf);const Zf=[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z",key:"1kt360"}]],eg=ja("folder",Zf);const tg=[["line",{x1:"22",x2:"2",y1:"12",y2:"12",key:"1y58io"}],["path",{d:"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z",key:"oot6mr"}],["line",{x1:"6",x2:"6.01",y1:"16",y2:"16",key:"sgf278"}],["line",{x1:"10",x2:"10.01",y1:"16",y2:"16",key:"1l4acy"}]],ii=ja("hard-drive",tg);const ag=[["path",{d:"m16 6 4 14",key:"ji33uf"}],["path",{d:"M12 6v14",key:"1n7gus"}],["path",{d:"M8 8v12",key:"1gg7y9"}],["path",{d:"M4 4v16",key:"6qkkli"}]],fd=ja("library",ag);const sg=[["path",{d:"M8 3H5a2 2 0 0 0-2 2v3",key:"1dcmit"}],["path",{d:"M21 8V5a2 2 0 0 0-2-2h-3",key:"1e4gt3"}],["path",{d:"M3 16v3a2 2 0 0 0 2 2h3",key:"wsl5sc"}],["path",{d:"M16 21h3a2 2 0 0 0 2-2v-3",key:"18trek"}]],ng=ja("maximize",sg);const rg=[["path",{d:"M8 3v3a2 2 0 0 1-2 2H3",key:"hohbtr"}],["path",{d:"M21 8h-3a2 2 0 0 1-2-2V3",key:"5jw1f3"}],["path",{d:"M3 16h3a2 2 0 0 1 2 2v3",key:"198tvr"}],["path",{d:"M16 21v-3a2 2 0 0 1 2-2h3",key:"ph8mxp"}]],ig=ja("minimize",rg);const og=[["path",{d:"M5 12h14",key:"1ays0h"}]],lg=ja("minus",og);const cg=[["path",{d:"M15.033 9.44a.647.647 0 0 1 0 1.12l-4.065 2.352a.645.645 0 0 1-.968-.56V7.648a.645.645 0 0 1 .967-.56z",key:"vbtd3f"}],["path",{d:"M12 17v4",key:"1riwvh"}],["path",{d:"M8 21h8",key:"1ev6f3"}],["rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",key:"x3v2xh"}]],gm=ja("monitor-play",cg);const dg=[["path",{d:"M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401",key:"kfwtm"}]],ym=ja("moon",dg);const ug=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9h18",key:"1pudct"}]],mg=ja("panel-top",ug);const hg=[["path",{d:"m17 2 4 4-4 4",key:"nntrym"}],["path",{d:"M3 11v-1a4 4 0 0 1 4-4h14",key:"84bu3i"}],["path",{d:"m7 22-4-4 4-4",key:"1wqhfi"}],["path",{d:"M21 13v1a4 4 0 0 1-4 4H3",key:"1rx37r"}]],pg=ja("repeat",hg);const fg=[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2",key:"aa7l1z"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2",key:"4qcy5o"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2",key:"6vwrx8"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2",key:"ioqczr"}],["path",{d:"M7 12h10",key:"b7w52i"}]],gg=ja("scan-line",fg);const yg=[["path",{d:"M3 7V5a2 2 0 0 1 2-2h2",key:"aa7l1z"}],["path",{d:"M17 3h2a2 2 0 0 1 2 2v2",key:"4qcy5o"}],["path",{d:"M21 17v2a2 2 0 0 1-2 2h-2",key:"6vwrx8"}],["path",{d:"M7 21H5a2 2 0 0 1-2-2v-2",key:"ioqczr"}],["path",{d:"M7 8h8",key:"1jbsf9"}],["path",{d:"M7 12h10",key:"b7w52i"}],["path",{d:"M7 16h6",key:"1vyc9m"}]],gd=ja("scan-text",yg);const bg=[["path",{d:"M17.971 4.285A2 2 0 0 1 21 6v12a2 2 0 0 1-3.029 1.715l-9.997-5.998a2 2 0 0 1-.003-3.432z",key:"15892j"}],["path",{d:"M3 20V4",key:"1ptbpl"}]],xg=ja("skip-back",bg);const wg=[["circle",{cx:"12",cy:"12",r:"4",key:"4exip2"}],["path",{d:"M12 2v2",key:"tus03m"}],["path",{d:"M12 20v2",key:"1lh1kg"}],["path",{d:"m4.93 4.93 1.41 1.41",key:"149t6j"}],["path",{d:"m17.66 17.66 1.41 1.41",key:"ptbguv"}],["path",{d:"M2 12h2",key:"1t8f8n"}],["path",{d:"M20 12h2",key:"1q8mjw"}],["path",{d:"m6.34 17.66-1.41 1.41",key:"1m8zz5"}],["path",{d:"m19.07 4.93-1.41 1.41",key:"1shlcs"}]],bm=ja("sun",wg);const vg=[["path",{d:"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z",key:"uqj9uw"}],["line",{x1:"22",x2:"16",y1:"9",y2:"15",key:"1ewh16"}],["line",{x1:"16",x2:"22",y1:"9",y2:"15",key:"5ykzw1"}]],jg=ja("volume-x",vg);const kg=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}],["path",{d:"M3 9a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2",key:"4125el"}],["path",{d:"M3 11h3c.8 0 1.6.3 2.1.9l1.1.9c1.6 1.6 4.1 1.6 5.7 0l1.1-.9c.5-.5 1.3-.9 2.1-.9H21",key:"1dpki6"}]],yd=ja("wallet-cards",kg);function bd({isOpen:t,children:a,className:s=""}){return e.jsx(Oa,{children:t&&e.jsx(ze.div,{initial:{height:0,opacity:0},animate:{height:"auto",opacity:1},exit:{height:0,opacity:0}
2,transition:{type:"spring",stiffness:400,damping:30},className:`wc-row-manage ${s}`,children:e.jsx("div",{className:"wc-row-manage-inner",children:a})})})}const _g=new Set(["queued","planning","ready","failed","expired","superseded"]),Sg=new Set(["queued","publishing_deck","waiting_for_source","planning_media","media_queued","media_active","complete","partial","failed","stopped"]),Ng=new Set(["pending","publishing","complete","all_known","failed"]),Cg=new Set(["not_requested","waiting_for_source","quoting","queued","processing","complete","partial","failed","stopped"]),Eg=new Set(["none","refresh_plan","buy_credits","free_storage","retry","stop_media","continue_media","wait_for_source"]),Gn=t=>!!t&&typeof t=="object"&&!Array.isArray(t),Ha=t=>Number.isSafeInteger(t)&&t>=0,Tg=t=>t===null||Ha(t),Qr=t=>t===null||typeof t=="string",fr=(t,a)=>{const s=Object.keys(t);return s.length===a.length&&s.every(n=>a.includes(n))},Mg=["id","state","cardCount","knownCount","blacklistedCount","mediaEligibleCount","existingMediaCount","unsupportedCount","creditUnits","affordableMediaCount","remainderCount","estimatedStorageBytes","productCopyVersion","consentVersion","expiresAt","failureReason","continuationForBuildId","limitingConstraint"],Pg=["id","mode","state","reason","deck","media","recoveryAction","createdAt","updatedAt"],Ag=["state","cardCount","publishedCount","deckId"],Ig=["state","selectedCount","readyCount","processingCount","unsupportedCount","remainderCount","reservedCreditUnits","settledCreditUnits","refundedCreditUnits","estimatedRemainingSeconds"];function Rg(t){return Gn(t)?fr(t,Mg)&&typeof t.id=="string"&&_g.has(String(t.state))&&Ha(t.cardCount)&&Ha(t.knownCount)&&Ha(t.blacklistedCount)&&Ha(t.mediaEligibleCount)&&Ha(t.existingMediaCount)&&Ha(t.unsupportedCount)&&Ha(t.creditUnits)&&Ha(t.affordableMediaCount)&&Ha(t.remainderCount)&&Ha(t.estimatedStorageBytes)&&typeof t.productCopyVersion=="string"&&Ha(t.consentVersion)&&Qr(t.expiresAt)&&Qr(t.failureReason)&&Qr(t.continuationForBuildId)&&(t.limitingConstraint==="none"||t.limitingConstraint==="credits"||t.limitingConstraint==="storage"):!1}function $g(t){if(!Gn(t)||!Gn(t.deck)||!Gn(t.media))return!1;const a=t.deck,s=t.media;return fr(t,Pg)&&fr(a,Ag)&&fr(s,Ig)&&typeof t.id=="string"&&(t.mode==="deck_only"||t.mode==="deck_with_media")&&Sg.has(String(t.state))&&Qr(t.reason)&&Ng.has(String(a.state))&&Ha(a.cardCount)&&Ha(a.publishedCount)&&Qr(a.deckId)&&Cg.has(String(s.state))&&Ha(s.selectedCount)&&Ha(s.readyCount)&&Ha(s.processingCount)&&Ha(s.unsupportedCount)&&Ha(s.remainderCount)&&Ha(s.reservedCreditUnits)&&Ha(s.settledCreditUnits)&&Ha(s.refundedCreditUnits)&&Tg(s.estimatedRemainingSeconds)&&Eg.has(String(t.recoveryAction))&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"}function zg(t){if(!Gn(t)||!Gn(t.source))return!1;const a=t.source;return fr(t,["orchestratorEnabled","source","plan","build"])&&fr(a,["kind","id","revision","role"])&&typeof t.orchestratorEnabled=="boolean"&&(a.kind==="reading_material"||a.kind==="video_session")&&typeof a.id=="string"&&typeof a.revision=="string"&&(a.role==="image"||a.role==="video_clip")&&(t.plan===null||Rg(t.plan))&&(t.build===null||$g(t.build))}function Ko(t){const a=encodeURIComponent(t.id);return t.kind==="reading_material"?`/api/reading/materials/${a}/study-build`:`/api/video/sessions/${a}/study-build`}async function sr(t,a,s){const n=await a();if(!n)throw new Error("Please sign in to build a study deck.");const r=await fetch(`${ue()}${t}`,{...s,headers:{Accept:"application/json",Authorization:`Bearer ${n}`,...s?.body?{"Content-Type":"application/json"}:{},...s?.headers}}),i=await r.json().catch(()=>null);if(!r.ok){const l=Gn(i)&&typeof i.error=="string"?i.error:"The study build could not be updated.";throw new Error(l)}if(!zg(i))throw new Error("The study build returned an invalid status.");return i}const Ar={get(t,a){return sr(Ko(t),a)},plan(t,a){return sr(`${Ko(t)}/plan`,a,{method:"POST"})},create(t,a,s){return sr(Ko(t),s,{method:"POST",body:JSON.stringify(a)})},getBuild(t,a){return sr(`/api/study-builds/${encodeURIComponent(t)}`,a)},stopMedia(t,a){return sr(`/api/study-builds/${encodeURIComponent(t)}/stop-media`,a,{method:"POST"})},continueMedia(t,a){return sr(`/api/study-builds/${encodeURIComponent(t)}/continue-media`,a,{method:"POST"})}},Fg=2500,Dg="shizen.study-builds.v1";function Lg(t){return t?.orchestratorEnabled?!t.plan||t.plan.state==="queued"||t.plan.state==="planning"?!0:!!(t.build&&!["complete","partial","failed","
2stopped"].includes(t.build.state)):!1}function Og(){return!0}function Bg(t,a){const{getAccessToken:s}=ps(),[n,r]=o.useState(null),[i,l]=o.useState(!1),[c,d]=o.useState(!1),[m,u]=o.useState(null),h=o.useRef(!0),p=o.useRef(null),g=t.kind,f=t.id,b=o.useMemo(()=>({kind:g,id:f}),[f,g]),y=`${g}:${f}`,x=o.useRef(null),v=o.useRef(null);o.useEffect(()=>(h.current=!0,()=>{h.current=!1}),[]),o.useEffect(()=>{p.current=null,r(null),u(null)},[y]);const w=o.useCallback(A=>(h.current&&(p.current=A,r(A),u(null)),A),[]),j=o.useCallback(async()=>{if(!a)return null;l(A=>A||p.current===null);try{const A=await Ar.get(b,s);return w(A)}catch(A){return h.current&&u(A instanceof Error?A.message:"Could not load study build."),null}finally{h.current&&l(!1)}},[w,a,s,b]),T=o.useCallback(()=>{x.current?.postMessage({sourceKey:y})},[y]),P=o.useCallback(async A=>{d(!0),u(null);try{const k=w(await A());return T(),k}catch(k){return h.current&&u(k instanceof Error?k.message:"Could not update study build."),null}finally{h.current&&d(!1)}},[w,T]),N=o.useCallback(()=>P(()=>Ar.plan(b,s)),[s,P,b]),_=o.useCallback(A=>P(()=>Ar.create(b,A,s)),[s,P,b]),L=o.useCallback(()=>n?.build?P(()=>Ar.stopMedia(n.build.id,s)):Promise.resolve(null),[s,P,n?.build]),q=o.useCallback(()=>n?.build?P(()=>Ar.continueMedia(n.build.id,s)):Promise.resolve(null),[s,P,n?.build]),O=o.useCallback(async()=>{const A=await j();return A?.orchestratorEnabled&&A.plan===null?N():A},[j,N]);return o.useEffect(()=>{if(!a||typeof BroadcastChannel>"u")return;const A=new BroadcastChannel(Dg);return x.current=A,A.onmessage=k=>{k.data?.sourceKey===y&&j()},()=>{x.current=null,A.close()}},[a,j,y]),o.useEffect(()=>{a&&v.current!==y&&(v.current=y,O())},[a,O,y]),o.useEffect(()=>{if(!a||!Lg(n))return;const A=window.setTimeout(()=>{if(!n?.plan&&!n?.build){N();return}j()},Fg);return()=>window.clearTimeout(A)},[a,j,N,n]),o.useEffect(()=>{if(!a)return;const A=()=>{document.visibilityState==="visible"&&j()};return window.addEventListener("focus",A),document.addEventListener("visibilitychange",A),()=>{window.removeEventListener("focus",A),document.removeEventListener("visibilitychange",A)}},[a,j]),o.useMemo(()=>({snapshot:n,loading:i,mutating:c,error:m,refresh:j,refreshAndPlan:O,requestPlan:N,create:_,stopMedia:L,continueMedia:q}),[q,_,m,i,c,j,O,N,n,L])}const vl="reading.video.preferences.v1",jl=1,nr={annotationsEnabled:"reading.annotationsDefault",autoPause:"reading.video.autoPause",blurSubs:"reading.video.blurSubs",showKnownColoring:"reading.video.showKnownColoring",subtitlePlacement:"reading.video.subtitlePlacement",theaterTheme:"reading.theaterTheme"},Xa=Object.freeze({annotationsEnabled:!0,showFurigana:!0,showKnownColoring:!1,blurSubs:!1,fontSizeIdx:2,playbackSpeed:1,volume:1,muted:!1,autoPause:"off",subtitlePlacement:"standard",theaterTheme:null});function xm(t){if(t!==void 0)return t;try{return typeof localStorage>"u"?null:localStorage}catch{return null}}function En(t,a){try{return t.getItem(a)}catch{return null}}function no(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Ir(t,a){return typeof t=="boolean"?t:a}function Ho(t,a){return typeof t=="number"&&Number.isFinite(t)?t:a}function Wo(t,a,s){return Math.min(s,Math.max(a,t))}function wm(t,a){return t==="off"||t==="start"||t==="end"?t:a}function vm(t,a){return t==="near"||t==="standard"||t==="high"?t:a}function jm(t,a){return t==="light"||t==="dark"?t:a}function km(t){const a=no(t)?t:{},s=Ho(a.fontSizeIdx,Xa.fontSizeIdx),n=Ho(a.playbackSpeed,Xa.playbackSpeed),r=Ho(a.volume,Xa.volume);return{annotationsEnabled:Ir(a.annotationsEnabled,Xa.annotationsEnabled),showFurigana:Ir(a.showFurigana,Xa.showFurigana),showKnownColoring:Ir(a.showKnownColoring,Xa.showKnownColoring),blurSubs:Ir(a.blurSubs,Xa.blurSubs),fontSizeIdx:Math.round(Wo(s,0,3)),playbackSpeed:Wo(n,.25,3),volume:Wo(r,0,1),muted:Ir(a.muted,Xa.muted),autoPause:wm(a.autoPause,Xa.autoPause),subtitlePlacement:vm(a.subtitlePlacement,Xa.subtitlePlacement),theaterTheme:jm(a.theaterTheme,Xa.theaterTheme)}}function uc(t,a){const s=xm(a);if(!s)return!1;const n=En(s,vl);if(n!==null)try{const i=JSON.parse(n);if(no(i)&&typeof i.version=="number"&&i.version>jl)return!1}catch{}const r={version:jl,...km(t)};try{return s.setItem(vl,JSON.stringify(r)),!0}catch{return!1}}function Go(t,a){return t==="true"?!0:t==="false"?!1:a}function qg(t){const a=En(t,nr.annotationsEnabled),s=En(t,nr.autoPause),n=En(t,nr.blurSubs),r=En(t,nr.showKnownColoring),i=En(t,nr.subtitlePlacement),l=En(t,nr.theaterTheme);return{found:[a,s,n,r,i,l].some(c=>c!==null),preferences:{...Xa,annotationsEnabled:Go(a,Xa.annotationsEnabled),autoPause:wm(s,Xa.autoPause),blurSubs:Go(n,Xa.blurSubs),showKnownColoring:Go(r,Xa.showKnownColoring),subtitlePlacement:vm(i,
2Xa.subtitlePlacement),theaterTheme:jm(l,Xa.theaterTheme)}}}function kl(t){const a=xm(t);if(!a)return{...Xa};const s=En(a,vl);if(s!==null)try{const r=JSON.parse(s);if(no(r)&&r.version===jl)return km(r);if(no(r)&&typeof r.version=="number")return{...Xa}}catch{}const n=qg(a);return n.found&&uc(n.preferences,a),n.preferences}function mc(){const{isDark:t}=Gl(),[a,s]=o.useState(()=>{try{const r=kl().theaterTheme;if(r==="dark")return!0;if(r==="light")return!1}catch{}return t});o.useEffect(()=>{try{uc({...kl(),theaterTheme:a?"dark":"light"})}catch{}},[a]);const n=o.useCallback(()=>s(r=>!r),[]);return{isDark:a,toggleTheme:n,theaterThemeClass:a?"theater-dark":"theater-light"}}function _m(t,a,s){const[n,r]=o.useState(null);return o.useEffect(()=>{if(!a||!t){r(null);return}let i=!1;return(async()=>{try{const l=await s();if(!l){i||r(null);return}const c=await fetch(`${ue()}/api/reading/materials/${t}/known-status`,{headers:{Authorization:`Bearer ${l}`}});if(!c.ok){i||r(null);return}const d=await c.json();if(i)return;const m=new Map;for(const u of d.unseen||[])m.set(u,"unseen");for(const u of d.learning||[])m.set(u,"learning");r(m)}catch{i||r(null)}})(),()=>{i=!0}},[t,a,s]),n}function Sm(t,a){const[s,n]=o.useState(null);return o.useEffect(()=>{if(!t){n(null);return}let r=!1;return(async()=>{try{const i=await a();if(!i){r||n(null);return}const l=await fetch(`${ue()}/api/vocab/known-status`,{headers:{Authorization:`Bearer ${i}`}});if(!l.ok){r||n(null);return}const c=await l.json();if(r)return;const d=new Map;for(const m of c.learning||[])d.set(m,"learning");for(const m of c.known||[])d.set(m,"known");n(d)}catch{r||n(null)}})(),()=>{r=!0}},[t,a]),s}function Ug({enabled:t,isAuthenticated:a,isPublicSample:s,isDemo:n}){return!t||n||!a?"none":s?"global":"material"}function Vg({isAuthenticated:t,isDemo:a}){return!a&&t}const Kg="jpapp-manga",Hg=2,js="manga_pages",Xs="manga_metadata";function mn(){return new Promise((t,a)=>{const s=indexedDB.open(Kg,Hg);s.onupgradeneeded=n=>{const r=s.result;n.oldVersion<1&&(r.createObjectStore(js,{keyPath:["materialId","pageNumber"]}).createIndex("by_material","materialId",{unique:!1}),r.createObjectStore(Xs,{keyPath:"materialId"}))},s.onsuccess=()=>t(s.result),s.onerror=()=>a(s.error)})}function Nr(t,a,s,n){return new Promise((r,i)=>{const l=t.transaction(a,s),c=n(l);c.onsuccess=()=>r(c.result),c.onerror=()=>i(c.error),l.onerror=()=>i(l.error)})}async function Wg(t,a,s,n,r){const i=await mn();try{const l={materialId:t,pageNumber:a,blob:s,mimeType:s.type||"image/jpeg",width:n,height:r};await Nr(i,js,"readwrite",c=>c.objectStore(js).put(l))}finally{i.close()}}async function Gg(t,a,s){if(a.length===0)return;const n=100,r=await mn();try{for(let i=0;i<a.length;i+=n){const l=a.slice(i,i+n);await new Promise((c,d)=>{const m=r.transaction(js,"readwrite"),u=m.objectStore(js);for(const h of l){const p={materialId:t,pageNumber:h.pageNumber,blob:h.blob,mimeType:h.blob.type||"image/jpeg",width:h.width,height:h.height};u.put(p)}m.oncomplete=()=>c(),m.onerror=()=>d(m.error),m.onabort=()=>d(m.error)}),s?.(Math.min(i+l.length,a.length))}}finally{r.close()}}async function Bi(t){const a=await mn();try{await Nr(a,Xs,"readwrite",s=>s.objectStore(Xs).put(t))}finally{a.close()}}async function hc(t,a){const s=await mn();try{return await Nr(s,js,"readonly",r=>r.objectStore(js).get([t,a]))??null}finally{s.close()}}async function Nm(t,a){const s=await hc(t,a);return s?URL.createObjectURL(s.blob):null}async function oi(t){const a=await mn();try{const s=await Nr(a,Xs,"readonly",r=>r.objectStore(Xs).get(t));return s?await new Promise((r,i)=>{const m=a.transaction(js,"readonly").objectStore(js).index("by_material").count(t);m.onsuccess=()=>r(m.result),m.onerror=()=>i(m.error)})>=s.totalPages:!1}finally{a.close()}}async function Mn(t){const a=await mn();try{await new Promise((s,n)=>{const r=a.transaction(js,"readwrite"),c=r.objectStore(js).index("by_material").openCursor(t);c.onsuccess=()=>{const d=c.result;d?(d.delete(),d.continue()):s()},c.onerror=()=>n(c.error),r.onerror=()=>n(r.error)}),await Nr(a,Xs,"readwrite",s=>s.objectStore(Xs).delete(t))}finally{a.close()}}async function pc(){const t=await mn();try{return await new Promise((a,s)=>{const i=t.transaction(Xs,"readonly").objectStore(Xs).getAll();i.onsuccess=()=>a(i.result),i.onerror=()=>s(i.error)})}finally{t.close()}}async function Yg(t){const a=await mn();try{return await Nr(a,Xs,"readonly",n=>n.objectStore(Xs).get(t))??null}finally{a.close()}}async function Nn(t,a="legacy-upload"){const s=[...t.entries()].sort(([u],[h])=>u.localeCompare(h)),n=a==="manga-camera-scan",r=[];for(const[u,h]of s){if(!n){r.push(`${u}:${h.size}`);continue}const p=typeof h.arrayBuffer=="function"?await h.arrayBuffer():await new Promise((b,y)=>{const x=new FileReader;x.onload=()=>b(x.result),x.onerror=()=>y(x.error??new Error("Could not read scanner page for fingerprinting.")),x.readAsArrayBuffer(h)}),g=new Uint8Array(await crypto.subtle.digest("SHA-256",p)),f=Array.from(g).map(b=>b.toString(16).padStart(2,"0")).join("");r.push(`${u}:${h.size}:${f}`)}const i=n?`scanner-v2 3${r.join(` 4`)}`:r.join(` 5`),l=new TextEncoder().encode(i),c=await crypto.subtle.digest("SHA-256",l),d=new Uint8Array(c),m=Array.from(d).map(u=>u.toString(16).padStart(2,"0")).join("");return n?`scanner-v2:${m}`:m}async function Jg(t){const a=await mn();try{const s=[];return await new Promise((n,r)=>{const i=a.transaction(js,"readonly"),d=i.objectStore(js).index("by_material").openCursor(t);d.onsuccess=()=>{const m=d.result;if(m){const u=m.value;s.push({pageNumber:u.pageNumber,sizeBytes:u.blob.size}),m.continue()}else n()},d.onerror=()=>r(d.error),i.onerror=()=>r(i.error)}),s.sort((n,r)=>n.pageNumber-r.pageNumber),s}finally{a.close()}}async function Xg(t){const a=await mn();try{let s=0;return await new Promise((n,r)=>{const d=a.transaction(js,"readonly").objectStore(js).index("by_material").openCursor(t);d.onsuccess=()=>{const m=d.result;if(m){const u=m.value;s+=u.blob.size,m.continue()}else n()},d.onerror=()=>r(d.error)}),s}finally{a.close()}}const xd=3e3*1e3,Qg=15,Zg=4,ey=60*1e3,ty=30*1e3;
5class Hs extends Error{materialId;pageNumber;constructor(a,s,n){super(n),this.name="CloudPageError",this.materialId=a,this.pageNumber=s}}const Yo=new Map;class ay{materialId;getAccessToken;fetchFn;dims;prefetchEnabled;batch=null;batchInFlight=null;pageInFlight=new Map;negativeCache=new Map;knownCached=new Set;lastForcedRefreshAt=Number.NEGATIVE_INFINITY;missCount=0;firstMissEmitted=!1;disposed=!1;constructor(a,s){this.materialId=a,this.getAccessToken=s.getAccessToken,this.fetchFn=s.fetchFn??fetch,this.dims=s.dims??new Map,this.prefetchEnabled=s.prefetch??!0}setDims(a){this.dims.clear();for(const[s,n]of a)this.dims.set(s,n)}async getPage(a,s){const n=await this.resolvePage(a,!0);return this.prefetchEnabled&&this.prefetchAround(a,s?.direction??"forward"),n}async resolvePage(a,s){const n=await hc(this.materialId,a);if(n)return this.knownCached.add(a),this.negativeCache.delete(a),n.blob;const r=this.pageInFlight.get(a);if(r)return r;s&&this.recordForegroundMiss(a);const i=this.fetchAndStore(a,!1,s).then(l=>(this.negativeCache.delete(a),l)).catch(l=>{throw this.negativeCache.set(a,Date.now()+ey),l}).finally(()=>{this.pageInFlight.delete(a)});return this.pageInFlight.set(a,i),i}async fetchAndStore(a,s,n){const i=(await this.ensureBatch(s&&n)).urls.get(a);if(!i){if(n&&!s)return this.fetchAndStore(a,!0,!0);throw new Hs(this.materialId,a,`No presigned URL for page ${a}`)}let l;try{l=await this.fetchFn(i)}catch(m){if(n&&!s)return this.fetchAndStore(a,!0,!0);throw new Hs(this.materialId,a,`Network error fetching page ${a}: ${m instanceof Error?m.message:String(m)}`)}if(!l.ok){if(n&&!s)return this.fetchAndStore(a,!0,!0);throw new Hs(this.materialId,a,`Fetch page ${a} failed: HTTP ${l.status}`)}const c=await l.blob(),d=this.dims.get(a)??{width:0,height:0};try{await Wg(this.materialId,a,c,d.width,d.height),this.knownCached.add(a)}catch{}return c}async ensureBatch(a=!1){const s=Date.now();if(a){if(s-this.lastForcedRefreshAt<ty){const n=this.freshBatch(s);if(n)return n}this.lastForcedRefreshAt=s,this.batch=null,Yo.delete(this.materialId)}else{const n=this.freshBatch(s);if(n)return n}return this.batchInFlight?this.batchInFlight:(this.batchInFlight=this.fetchBatch().then(n=>(this.batch=n,Yo.set(this.materialId,n),n)).finally(()=>{this.batchInFlight=null}),this.batchInFlight)}freshBatch(a){if(this.batch&&a<this.batch.refreshAfter)return this.batch;const s=Yo.get(this.materialId);return s&&a<s.refreshAfter?(this.batch=s,s):null}async fetchBatch(){const a=await this.getAccessToken(),s={"Content-Type":"application/json"};a&&(s.Authorization=`Bearer ${a}`);const n=`${ue()}/api/reading/materials/${this.materialId}/page-urls`;let r;try{r=await this.fetchFn(n,{headers:s})}catch(u){throw new Hs(this.materialId,-1,`page-urls fetch failed: ${u instanceof Error?u.message:String(u)}`)}if(!r.ok)throw new Hs(this.materialId,-1,`page-urls returned HTTP ${r.status}`);const i=await r.json(),l=new Map;for(const u of i.urls??[])typeof u?.pageNumber=="number"&&typeof u?.url=="string"&&l.set(u.pageNumber,u.url);const c=typeof i.ttlSeconds=="number"&&i.ttlSeconds>0?i.ttlSeconds*1e3*.9:xd,d=Date.now()+Math.min(xd,c),m=typeof i.pageCount=="number"&&i.pageCount>0?i.pageCount:l.size;return{urls:l,pageCount:m,refreshAfter:d}}async prefetchAround(a,s){const n=s==="back"?-1:1,r=Date.now(),i=this.batch?.pageCount??Number.POSITIVE_INFINITY,l=[];for(let u=1;u<=Qg;u++){const h=a+n*u;if(h<1||h>i)break;if(this.knownCached.has(h)||this.pageInFlight.has(h))continue;const p=this.negativeCache.get(h);if(p!==void 0){if(r<p)continue;this.negativeCache.delete(h)}l.push(h)}if(l.length===0)return;let c=0;const d=async()=>{for(;;){const u=l[c++];if(u===void 0)return;try{await this.resolvePage(u,!1)}catch{}}},m=Math.min(Zg,l.length);await Promise.all(Array.from({length:m},()=>d()))}recordForegroundMiss(a){this.missCount+=1,this.firstMissEmitted||(this.firstMissEmitted=!0,ne("cloud_stream_page_miss",{phase:"first_miss",miss_count:this.missCount}))}dispose(){this.disposed||(this.disposed=!0,this.missCount>0&&ne("cloud_stream_page_miss",{phase:"summary",miss_count:this.missCount,page_count:this.batch?.page
5Count}))}}async function sy(t,a,s=fetch){const n=await a(),r={"Content-Type":"application/json"};n&&(r.Authorization=`Bearer ${n}`);const i=`${ue()}/api/reading/materials/${t}/page-urls`;let l;try{l=await s(i,{headers:r})}catch(d){throw new Hs(t,-1,`page-urls fetch failed: ${d instanceof Error?d.message:String(d)}`)}if(!l.ok)throw new Hs(t,-1,`page-urls returned HTTP ${l.status}`);return(await l.json()).file??null}async function ny(t,a,s=fetch){const n=await sy(t,a,s);if(!n)throw new Hs(t,-1,"No cloud EPUB URL available");let r;try{r=await s(n)}catch(i){throw new Hs(t,-1,`EPUB download failed: ${i instanceof Error?i.message:String(i)}`)}if(!r.ok)throw new Hs(t,-1,`EPUB download HTTP ${r.status}`);return r.blob()}const fc=400;async function gc(t,a,s=fc){let n=setTimeout(()=>{n=null,a(!0)},s);try{return await t}finally{n&&(clearTimeout(n),n=null),a(!1)}}const ry="jpapp-epub",iy=1,ln="epub_files";function ko(){return new Promise((t,a)=>{const s=indexedDB.open(ry,iy);s.onupgradeneeded=()=>{const n=s.result;n.objectStoreNames.contains(ln)||n.createObjectStore(ln,{keyPath:"materialId"})},s.onsuccess=()=>t(s.result),s.onerror=()=>a(s.error)})}function yc(t,a,s,n){return new Promise((r,i)=>{const l=t.transaction(a,s),c=n(l);c.onsuccess=()=>r(c.result),c.onerror=()=>i(c.error),l.onerror=()=>i(l.error)})}async function bc(t,a,s="epub"){const n=await ko();try{const r={materialId:t,blob:a,filename:a.name,fileSize:a.size,storedAt:new Date().toISOString(),format:s};await yc(n,ln,"readwrite",i=>i.objectStore(ln).put(r))}finally{n.close()}}async function gr(t){const a=await ko();try{return await yc(a,ln,"readonly",n=>n.objectStore(ln).get(t))??null}finally{a.close()}}async function _o(t){const a=await ko();try{await yc(a,ln,"readwrite",s=>s.objectStore(ln).delete(t))}finally{a.close()}}async function li(t){return await gr(t)!==null}async function xc(){const t=await ko();try{return await new Promise((a,s)=>{const i=t.transaction(ln,"readonly").objectStore(ln).getAll();i.onsuccess=()=>a(i.result),i.onerror=()=>s(i.error)})}finally{t.close()}}class gs extends Error{constructor(a){super(a),this.name="MokuroParseError"}}function Cm(t){if(!t||typeof t!="object")throw new gs("Invalid mokuro data: not an object");const a=t;if(typeof a.version!="string")throw new gs("Invalid mokuro data: missing version");if(!Array.isArray(a.pages))throw new gs("Invalid mokuro data: missing pages array");if(a.pages.length>2e3)throw new gs(`Too many pages: ${a.pages.length} (max 2000)`);const s=a.pages.map((n,r)=>{if(!n||typeof n!="object")throw new gs(`Invalid page at index ${r}`);const i=n;if(typeof i.img_width!="number"||i.img_width<1||i.img_width>1e4)throw new gs(`Invalid img_width at page ${r}: ${i.img_width}`);if(typeof i.img_height!="number"||i.img_height<1||i.img_height>1e4)throw new gs(`Invalid img_height at page ${r}: ${i.img_height}`);if(typeof i.img_path!="string")throw new gs(`Missing img_path at page ${r}`);const l=oy(i.blocks,r);return{version:typeof i.version=="string"?i.version:a.version,img_path:i.img_path,img_width:i.img_width,img_height:i.img_height,blocks:l}});return{version:a.version,title:typeof a.title=="string"?a.title:void 0,title_uuid:typeof a.title_uuid=="string"?a.title_uuid:void 0,volume:typeof a.volume=="string"?a.volume:void 0,volume_uuid:typeof a.volume_uuid=="string"?a.volume_uuid:void 0,pages:s}}function oy(t,a){if(!Array.isArray(t))throw new gs(`Invalid blocks at page ${a}: not an array`);if(t.length>1e3)throw new gs(`Too many blocks at page ${a}: ${t.length}`);return t.map((s,n)=>{if(!s||typeof s!="object")throw new gs(`Invalid block at page ${a}, block ${n}`);const r=s;if(!Array.isArray(r.box)||r.box.length!==4||!r.box.every(l=>typeof l=="number"))throw new gs(`Invalid box at page ${a}, block ${n}`);if(typeof r.vertical!="boolean")throw new gs(`Invalid vertical at page ${a}, block ${n}`);if(typeof r.font_size!="number")throw new gs(`Invalid font_size at page ${a}, block ${n}`);if(!Array.isArray(r.lines)||!r.lines.every(l=>typeof l=="string"))throw new gs(`Invalid lines at page ${a}, block ${n}`);const i=Array.isArray(r.lines_coords)?r.lines_coords:[];return{box:r.box,vertical:r.vertical,font_size:r.font_size,lines:r.lines,lines_coords:i}})}function So(t){let a;try{a=JSON.parse(t)}catch{throw new gs("Invalid JSON in .mokuro file")}return Cm(a)}function ys(t){return wc(t).replace(/\d+/g,a=>a.padStart(10,"0"))}function wc(t){return t.replace(/[ï¼-ï¼]/g,a=>
5String.fromCharCode(a.charCodeAt(0)-65296+48))}function Em(t){return t.replace(/\\/g,"/").split("/").some(a=>a.startsWith(".")||a==="__MACOSX"||a==="Thumbs.db")}const fi=4*1024**3,wr=200*1024**2,ci=100,yr="This file appears to be a decompression bomb. If this is a legitimate file, please contact support.";function Cr(t){return new Promise(a=>{const s=URL.createObjectURL(t),n=new Image;n.onload=()=>{URL.revokeObjectURL(s),a({width:n.naturalWidth,height:n.naturalHeight})},n.onerror=()=>{URL.revokeObjectURL(s),a(null)},n.src=s})}const gi=/\.(jpg|jpeg|png|webp)$/i,vc=/\.mokuro$/i,ly=/\.pdf$/i,cy=1*1024*1024*1024,Tm="Archive too large to open safely";function di(t){const a=t._data;return{uncompressed:a?.uncompressedSize??0,compressed:a?.compressedSize??0}}const yi=Em;async function Mm(t,a){a?.({phase:"reading",current:0,total:1});const s=await _r.loadAsync(t);if(Object.values(s.files).reduce((h,p)=>h+di(p).uncompressed,0)>fi)throw new Error(Tm);const r=[];let i=null;s.forEach((h,p)=>{if(p.dir||yi(h))return;const{uncompressed:g,compressed:f}=di(p);if(g>wr){console.warn(`[cbz-extractor] Skipping oversize entry "${h}": ${g} bytes > cap ${wr}`);return}if(f>0&&g/f>ci){console.warn(`[cbz-extractor] Skipping high-ratio entry "${h}": ${(g/f).toFixed(1)}:1 > ${ci}:1`);return}vc.test(h)?i=p:gi.test(h)&&r.push({path:h,file:p})}),r.sort((h,p)=>ys(h.path).localeCompare(ys(p.path)));let l=null;if(i!==null){const h=await i.async("string");l=So(h)}const c=new Map,d=new Map,m=r.length;for(let h=0;h<m;h++){const p=r[h];a?.({phase:"extracting",current:h+1,total:m});const g=await p.file.async("blob"),f=p.path.split(".").pop()?.toLowerCase()||"jpeg",b=f==="png"?"image/png":f==="webp"?"image/webp":"image/jpeg",y=new Blob([g],{type:b}),x=p.path.split("/").pop()||p.path;if(c.set(x,y),l){const v=l.pages.find(w=>w.img_path===p.path||w.img_path===x);v&&d.set(x,{width:v.img_width,height:v.img_height})}}const u=[...c.entries()].filter(([h])=>!d.has(h));for(const[h,p]of u){const g=await Cr(p);g&&d.set(h,g)}return{images:c,mokuroJson:l,dimensions:d}}async function dy(t){try{const a=await _r.loadAsync(t);let s=0;return a.forEach((n,r)=>{r.dir||yi(n)||gi.test(n)&&s++}),s}catch{return 0}}class ro extends Error{constructor(){super("The PDF inside this ZIP is larger than 1 GB â extract it and split the volume before uploading."),this.name="ArchivePdfTooLargeError"}}async function wd(t,a=cy){try{const s=await _r.loadAsync(t);let n=null,r="",i=0,l=0,c=0;if(s.forEach((u,h)=>{h.dir||yi(u)||(ly.test(u)?(i+=1,n=h,r=u):gi.test(u)?l+=1:vc.test(u)&&(c+=1))}),i!==1||l!==0||c!==0||n===null)return null;const d=await n.async("blob");if(d.size>a)throw new ro;const m=r.split("/").pop()||r;return new File([d],m,{type:"application/pdf"})}catch(s){if(s instanceof ro)throw s;return null}}async function uy(t){const a=await _r.loadAsync(t);if(Object.values(a.files).reduce((r,i)=>r+di(i).uncompressed,0)>fi)throw new Error(Tm);const n=[];return a.forEach((r,i)=>{if(i.dir||yi(r)||!gi.test(r)&&!vc.test(r))return;const{uncompressed:l}=di(i);n.push({path:r,name:r.split("/").pop()||r,size:l})}),{zip:a,entries:n}}async function my(t,a,s,n){const{zip:r}=t;let i=null;if(s){const u=r.file(s);if(u){const h=await u.async("string");i=So(h)}}const l=new Map,c=new Map,d=a.length;for(let u=0;u<d;u++){const h=a[u];n?.({phase:"extracting",current:u+1,total:d});const p=r.file(h);if(!p)continue;const{uncompressed:g,compressed:f}=di(p);if(g>wr){console.warn(`[cbz-extractor] Skipping oversize entry "${h}": ${g} bytes > cap ${wr}`);continue}if(f>0&&g/f>ci){console.warn(`[cbz-extractor] Skipping high-ratio entry "${h}": ${(g/f).toFixed(1)}:1 > ${ci}:1`);continue}const b=await p.async("blob"),y=h.split(".").pop()?.toLowerCase()||"jpeg",x=y==="png"?"image/png":y==="webp"?"image/webp":"image/jpeg",v=new Blob([b],{type:x}),w=h.split("/").pop()||h;if(l.set(w,v),i){const j=i.pages.find(T=>T.img_path===h||T.img_path===w||T.img_path.endsWith("/"+w));j&&c.set(w,{width:j.img_width,height:j.img_height})}}const m=[...l.entries()].filter(([u])=>!c.has(u));for(const[u,h]of m){const p=await Cr(h);p&&c.set(u,p)}return{images:l,mokuroJson:i,dimensions:c}}async function No(t,a){const s=t.filter(l=>gi.test(l.name)&&!yi(l.name)).sort((l,c)=>ys(l.name).localeCompare(ys(c.name))),n=new Map,r=new Map,i=s.length;for(let l=0;l<i;l++){const c=s[l];a?.({phase:"extracting",current:l+1,total:i}),n.set(c.name,c)}for(const[l,c]of n){const d=await Cr(c);d&&r.set(l,d)}return{images:n,mokuroJson:null,dimensions:r}}async function Pm(t,a,s){let n;try{n=So(await a.text())}
5catch{return No(t,s)}const r=[...t].sort((m,u)=>ys(m.name).localeCompare(ys(u.name))),i=new Map,l=new Map,c=r.length;for(let m=0;m<c;m++){const u=r[m];s?.({phase:"extracting",current:m+1,total:c}),i.set(u.name,u);const h=n.pages.find(p=>p.img_path===u.name||p.img_path.endsWith("/"+u.name));h&&l.set(u.name,{width:h.img_width,height:h.img_height})}const d=[...i.entries()].filter(([m])=>!l.has(m));for(const[m,u]of d){const h=await Cr(u);h&&l.set(m,h)}return{images:i,mokuroJson:n,dimensions:l}}const Am=/^image\/(jpeg|png|webp|gif|bmp|tiff)$/i;function hy(t){const a=t._data;return{uncompressed:a?.uncompressedSize??0,compressed:a?.compressedSize??0}}function Im(t){let a=0;for(const s of Object.values(t.files)){if(s.dir)continue;const{uncompressed:n,compressed:r}=hy(s);if(n>wr)throw new Error(yr);if(r>0&&n/r>ci)throw new Error(yr);if(a+=n,a>fi)throw new Error(yr)}}async function jc(t){const a=await _r.loadAsync(t);Im(a);const s=await a.file("META-INF/container.xml")?.async("string");if(!s)throw new Error("Invalid EPUB: META-INF/container.xml not found");const r=new DOMParser().parseFromString(s,"application/xml").querySelector("rootfile")?.getAttribute("full-path");if(!r)throw new Error("Invalid EPUB: content.opf path not found");const i=await a.file(r)?.async("string");if(!i)throw new Error(`content.opf not found at ${r}`);const l=new DOMParser().parseFromString(i,"application/xml"),c=l.querySelectorAll("spine itemref"),d=Array.from(c).map(h=>h.getAttribute("idref")).filter(Boolean),m=new Map;l.querySelectorAll("manifest item").forEach(h=>{const p=h.getAttribute("id"),g=h.getAttribute("href"),f=h.getAttribute("media-type")||"";p&&g&&m.set(p,{href:g,mediaType:f})});const u=r.split("/").slice(0,-1).join("/");return{zip:a,manifestMap:m,idrefList:d,basePath:u,opfDoc:l}}function py(t){const s=new DOMParser().parseFromString(t,"text/html").querySelector("body");if(!s)return!0;const n=s.cloneNode(!0);return n.querySelectorAll("img, svg, image").forEach(i=>i.remove()),(n.textContent?.trim()||"").length<20}function io(t,a){const s=decodeURIComponent(a);if(!t)return s;const n=`${t}/${s}`.split("/"),r=[];for(const i of n)i===".."?r.pop():i!=="."&&r.push(i);return r.join("/")}async function fy(t){const a=await _r.loadAsync(t);Im(a);const s=await a.file("META-INF/container.xml")?.async("string");if(!s)return null;const r=new DOMParser().parseFromString(s,"application/xml").querySelector("rootfile")?.getAttribute("full-path");if(!r)return null;const i=await a.file(r)?.async("string");return i&&new DOMParser().parseFromString(i,"application/xml").querySelector("metadata")?.getElementsByTagName("dc:title")?.[0]?.textContent?.trim()||null}async function gy(t){const{zip:a,manifestMap:s,idrefList:n,basePath:r}=await jc(t);let i=0,l=0;for(const c of n){const d=s.get(c);if(d){if(Am.test(d.mediaType)){i++,l++;continue}if(d.mediaType.includes("html")||d.mediaType.includes("xml")){const m=io(r,d.href),u=await a.file(m)?.async("string");if(!u)continue;l++,py(u)&&i++}}}return l===0?"text":i/l>.6?"image":"text"}async function Rm(t,a){a?.({phase:"reading",current:0,total:1});const{zip:s,manifestMap:n,idrefList:r,basePath:i}=await jc(t),l=[];for(const u of r){const h=n.get(u);if(!h)continue;const p=io(i,h.href);if(Am.test(h.mediaType)){l.push(p);continue}if(h.mediaType.includes("html")||h.mediaType.includes("xml")){const g=await s.file(p)?.async("string");if(!g)continue;const f=new DOMParser().parseFromString(g,"text/html"),b=p.split("/").slice(0,-1).join("/");f.querySelectorAll("img, image").forEach(y=>{const x=y.getAttribute("src")||y.getAttribute("xlink:href")||y.getAttributeNS("http://www.w3.org/1999/xlink","href");if(!x)return;const v=io(b,x);l.includes(v)||l.push(v)})}}const c=new Map,d=new Map,m=l.length;for(let u=0;u<m;u++){a?.({phase:"extracting",current:u+1,total:m});const h=l[u],p=await s.file(h)?.async("blob");if(!p)continue;const g=h.split(".").pop()?.toLowerCase()||"jpeg",f=g==="png"?"image/png":g==="webp"?"image/webp":"image/jpeg",b=new Blob([p],{type:f}),y=`page_${String(u+1).padStart(4,"0")}.${g}`;c.set(y,b);const x=await Cr(b);x&&d.set(y,x)}return{images:c,mokuroJson:null,dimensions:d}}async function oo(t){const{zip:a,manifestMap:s,idrefList:n,basePath:r}=await jc(t),i=[];for(let l=0;l<n.length;l++){const c=s.get(n[l]);if(!c)continue;
5const d=io(r,c.href),m=await a.file(d)?.async("string");if(!m)continue;const u=new DOMParser().parseFromString(m,"text/html"),h=u.querySelector("h1")?.textContent?.trim()||u.querySelector("h2")?.textContent?.trim()||u.querySelector("title")?.textContent?.trim()||`Chapter ${l+1}`,p=u.querySelector("body");if(!p)continue;const g=[];p.querySelectorAll("p").forEach(f=>{const b=f.textContent?.trim();b&&g.push(b)}),g.length===0&&(p.textContent?.trim()||"").split(/\n\n+/).forEach(b=>{const y=b.trim();y&&g.push(y)}),g.length>0&&i.push({title:h,order:l+1,paragraphs:g})}if(i.length===0)throw new Error("No chapters extracted from EPUB");return i}const yy=20,qi=500,Jo=5e4,by="/pdfjs/cmaps/",xy="/pdfjs/standard_fonts/",$m=globalThis.process,_l=!!$m?.versions?.node;let Ni=null,zm="",Fm="";async function Co(){return Ni||(Ni=(async()=>{if(_l){const n=await import("pdfjs-dist/legacy/build/pdf.mjs"),r=($m?.cwd?.()??".").replace(/\\/g,"/").replace(/\/+$/,"");return zm=`${r}/node_modules/pdfjs-dist/cmaps/`,Fm=`${r}/node_modules/pdfjs-dist/standard_fonts/`,n}const t=await Rs(()=>import("./pdf-DMRcuM1e.js"),[]),a=(await Rs(async()=>{const{default:s}=await import("./pdf.worker.min-CevBI0zc.js");return{default:s}},[])).default;return t.GlobalWorkerOptions.workerSrc=a,t})(),Ni)}function Eo(t){return{data:t,cMapUrl:_l?zm:by,cMapPacked:!0,standardFontDataUrl:_l?Fm:xy,isEvalSupported:!1}}async function bi(t){return new Uint8Array(await t.arrayBuffer())}function Ci(t,...a){const s=t?.asString;if(typeof s!="function")return!1;const n=s.call(t),r=n.startsWith("/")?n.slice(1):n;return a.includes(r)}function vd(t){const a=t?.asNumber;return typeof a=="function"?a.call(t):null}function wy(t,a,s){const{PDFName:n,PDFArray:r,PDFDict:i,PDFRawStream:l}=s,c=t.getPage(a);if(c.getRotation().angle%360!==0)return null;const d=c.node.Resources();if(!d)return null;const m=d.lookup(n.of("XObject"),i);if(!m)return null;let u=null,h=0;for(const[,x]of m.entries()){const v=t.context.lookup(x);if(!(v instanceof l))continue;const w=v.dict;if(Ci(w.lookup(n.of("Subtype")),"Image")){if(h+=1,h>1)return null;u=v}}if(h!==1||!u)return null;const p=u.dict,g=p.lookup(n.of("Filter"));let f=Ci(g,"DCTDecode");if(!f&&g instanceof r&&g.size()===1&&(f=Ci(g.lookup(0),"DCTDecode")),!f||!Ci(p.lookup(n.of("ColorSpace")),"DeviceRGB","RGB")||p.get(n.of("SMask"))!==void 0||p.get(n.of("Decode"))!==void 0)return null;const b=vd(p.lookup(n.of("Width"))),y=vd(p.lookup(n.of("Height")));return b==null||y==null?null:{bytes:u.contents,width:b,height:y}}function vy(){if(typeof document>"u")return!1;try{const t=document.createElement("canvas");return typeof t.toBlob=="function"&&!!t.getContext("2d")}catch{return!1}}async function kc(t,a){const s=await bi(t),{PDFDocument:n,PDFName:r,PDFArray:i,PDFDict:l,PDFRawStream:c}=await Rs(async()=>{const{PDFDocument:y,PDFName:x,PDFArray:v,PDFDict:w,PDFRawStream:j}=await import("./index-CU1pmUEt.js");return{PDFDocument:y,PDFName:x,PDFArray:v,PDFDict:w,PDFRawStream:j}},__vite__mapDeps([0,1])),d=await n.load(s,{ignoreEncryption:!0,updateMetadata:!1}),m=d.isEncrypted,u=d.getPageCount();a?.({phase:"reading",current:0,total:u});const h=new Map,p=new Map;let g=null,f=null,b=null;try{for(let y=0;y<u;y++){a?.({phase:"extracting",current:y+1,total:u});const x=`page_${String(y+1).padStart(4,"0")}.jpg`,v=m?null:wy(d,y,{PDFName:r,PDFArray:i,PDFDict:l,PDFRawStream:c});if(v){h.set(x,new Blob([v.bytes],{type:"image/jpeg"})),p.set(x,{width:v.width,height:v.height});continue}if(!vy())throw new Error(`pdf-extractor: page ${y+1} is not raw-JPEG-eligible and canvas rendering is unavailable in this environment`);g||(g=await Co(),b=g.getDocument(Eo(s)),f=await b.promise);const w=await f.getPage(y+1),j=w.getViewport({scale:1}),T=document.createElement("canvas");T.width=Math.max(1,Math.ceil(j.width)),T.height=Math.max(1,Math.ceil(j.height));const P=T.getContext("2d");if(!P)throw w.cleanup(),new Error(`pdf-extractor: could not acquire a 2d canvas context for page ${y+1}`);await w.render({canvasContext:P,viewport:j,canvas:T}).promise;const N=await new Promise((_,L)=>{T.toBlob(q=>q?_(q):L(new Error("canvas.toBlob returned null")),"image/jpeg",.92)});h.set(x,N),p.set(x,{width:T.width,height:T.height}),w.cleanup()}}finally{b&&await b.destroy()}return{images:h,mokuroJson:null,dimensions:p}}async function Sl(t,a){const s=a??await bi(t),{PDFDocument:n}=await Rs(async()=>{const{PDFDocument:i}=await import("./index-CU1pmUEt.js");return{PDFDocument:i}},__vite__mapDeps([0,1]));return(await n.load(s,{ignoreEncryption:!0,updateMetadata:!1})).getPageCount()}function jy(t){let a=0;for(const s of t)typeof s.str=="string"&&(a+=s.str.replace(/\s+/g,"").length);return a}
5async function Xo(t,a){const s=await Co(),n=a??await bi(t),r=s.getDocument(Eo(n)),i=await r.promise;try{const l=Math.min(10,i.numPages);if(l===0)return"image";let c=0;for(let d=1;d<=l;d++){const m=await i.getPage(d),u=await m.getTextContent();m.cleanup(),jy(u.items)>=yy&&(c+=1)}return c/l>.6?"text":"image"}finally{await r.destroy()}}function Dm(t){const a=[];for(const v of t){const w=typeof v.str=="string"?v.str:"";if(w==="")continue;const j=v.transform&&v.transform.length>=6?v.transform:[1,0,0,1,0,0],[T,P,N,_,L,q]=j,O=Math.abs(P)+Math.abs(N)>Math.abs(T)+Math.abs(_),A=v.height||Math.abs(_)||Math.hypot(T,P)||12;a.push({str:w,x:L,y:q,size:A,vertical:O})}if(a.length===0)return[];const s=a.filter(v=>v.vertical).length<=a.length/2,n=a.map(v=>v.size).sort((v,w)=>v-w),r=n[Math.floor(n.length/2)]||12,i=Math.max(r*.6,2),l=v=>s?v.y:v.x,c=(v,w)=>s?v.x-w.x:w.y-v.y,d=[...a].sort((v,w)=>{const j=l(w)-l(v);return Math.abs(j)>i?j:c(v,w)}),m=[];let u=[];const h=()=>{if(u.length===0)return;u.sort(c);const v=u.map(w=>w.str).join("").replace(/\s+/g," ").trim();v&&m.push({cross:l(u[0]),text:v}),u=[]};for(const v of d)u.length===0||Math.abs(l(v)-l(u[0]))<=i||h(),u.push(v);if(h(),m.length===0)return[];const p=[];for(let v=1;v<m.length;v++)p.push(Math.abs(m[v-1].cross-m[v].cross));const g=[...p].sort((v,w)=>v-w),f=g.length?g[Math.floor(g.length/2)]:0,b=Math.max(f*1.6,r*1.8),y=[];let x=[];for(let v=0;v<m.length;v++)v>0&&Math.abs(m[v-1].cross-m[v].cross)>b&&(x.length&&y.push(x.join("").trim()),x=[]),x.push(m[v].text);return x.length&&y.push(x.join("").trim()),y.filter(v=>v.length>0)}async function ky(t,a){try{let s=a.dest;if(typeof s=="string"&&(s=await t.getDestination(s)),!Array.isArray(s)||s.length===0)return null;const n=s[0];return n&&typeof n=="object"&&"num"in n?await t.getPageIndex(n):null}catch{return null}}function _y(t){const a=t.length,s=Math.max(1,Math.ceil(a/qi)),n=[];for(let r=0;r<a;r+=s){const i=Math.min(r+s,a),l=[];for(let c=r;c<i;c++)l.push(...t[c]);n.push({title:`Pages ${r+1}â${i}`,order:n.length+1,paragraphs:l})}return n}function Sy(t){let a=t;a.length>qi&&(console.warn(`[pdf-extractor] Clamping ${a.length} chapters to ${qi}`),a=a.slice(0,qi));let s=0,n=!1;const r=[];for(const i of a){if(s>=Jo){n=!0;break}const l=Jo-s,c=i.paragraphs.length>l?i.paragraphs.slice(0,l):i.paragraphs;c.length<i.paragraphs.length&&(n=!0),s+=c.length,r.push({...i,paragraphs:c})}return n&&console.warn(`[pdf-extractor] Clamping paragraphs to ${Jo} total`),r}async function jd(t){const a=await Co(),s=await bi(t),n=a.getDocument(Eo(s)),r=await n.promise;let i;try{const d=r.numPages,m=[];for(let h=1;h<=d;h++){const p=await r.getPage(h),g=await p.getTextContent();p.cleanup(),m.push(Dm(g.items))}const u=await r.getOutline();if(i=[],u&&u.length>0){const h=[];for(const p of u){const g=await ky(r,p);if(g!=null){const f=(p.title||"").trim()||`Chapter ${h.length+1}`;h.push({title:f,startPage:g})}}h.sort((p,g)=>p.startPage-g.startPage);for(let p=0;p<h.length;p++){const g=h[p].startPage,f=p+1<h.length?h[p+1].startPage:d,b=[];for(let y=g;y<f;y++)y>=0&&y<m.length&&b.push(...m[y]);i.push({title:h[p].title,order:p+1,paragraphs:b})}}i.length===0&&(i=_y(m))}finally{await n.destroy()}i=Sy(i);const l=i.filter(d=>d.paragraphs.length>0),c=(l.length>0?l:i).map((d,m)=>({...d,order:m+1}));if(c.length===0)throw new Error("No text extracted from PDF");return c}async function Ny(t){const a=await Co(),s=await bi(t),n=a.getDocument(Eo(s)),r=await n.promise;try{try{const l=(await r.getMetadata())?.info;if(l&&typeof l.Title=="string"&&l.Title.trim())return l.Title.trim()}catch{}try{const i=await r.getPage(1),l=await i.getTextContent();i.cleanup();const c=Dm(l.items);if(c.length&&c[0].trim())return c[0].trim()}catch{}return null}finally{await n.destroy()}}const Qo=[80,75,3,4],Ui=60,Vi="BOOKMOBI",Cy=Ui+Vi.length;async function Ey(t,a){const s=t.slice(0,a);if(typeof s.arrayBuffer=="function")return new Uint8Array(await s.arrayBuffer());const n=await new Promise((r,i)=>{const l=new FileReader;l.onload=()=>r(l.result),l.onerror=()=>i(l.error),l.readAsArrayBuffer(s)});return new Uint8Array(n)}async function lo(t){try{if(t.size<Qo.length)return null;const a=await Ey(t,Cy);return a.length>=Qo.length&&Qo.every((s,n)=>a[n]===s)?"epub":a.length>=Ui+Vi.length&&new TextDecoder("latin1").decode(a.subarray(Ui,Ui+Vi.length))===Vi?"kindle":null}catch{return null}}function Lm(t,a){return t==="kindle"?"kindle":t==="epub"?"epub":a==="kindle"?"kindle":"epub"}
5const Om="This Kindle file is copy-protected (DRM) and canât be imported. Shizen only reads DRM-free files. If this is your own book, convert it to a DRM-free EPUB or AZW3 first, then upload that.",Bm="This doesnât look like a valid Kindle book (MOBI/AZW/AZW3). If itâs a KFX file, Kindle canât be imported â convert it to a DRM-free EPUB or AZW3 first.",qm="This Kindle file looks incomplete or corrupted and canât be read. Try re-downloading it, or convert it to a DRM-free EPUB first.";function co(t){if(t.ok)return"";switch(t.reason){case"drm":return Om;case"not-mobi":return Bm;case"too-small":case"truncated":return qm}}const Zo=78,Ty=60,My=76,el=12;async function kd(t,a,s){const n=t.slice(a,s);return typeof n.arrayBuffer=="function"?n.arrayBuffer():new Promise((r,i)=>{const l=new FileReader;l.onload=()=>r(l.result),l.onerror=()=>i(l.error),l.readAsArrayBuffer(n)})}async function vr(t){if(t.size<Zo+8)return{ok:!1,reason:"too-small"};const a=await kd(t,0,Zo+8),s=new DataView(a);if(new TextDecoder("latin1").decode(new Uint8Array(a,Ty,8))!=="BOOKMOBI")return{ok:!1,reason:"not-mobi"};if(s.getUint16(My,!1)<1)return{ok:!1,reason:"truncated"};const i=s.getUint32(Zo,!1);if(i+el+2>t.size)return{ok:!1,reason:"truncated"};const l=await kd(t,i+el,i+el+2),c=new DataView(l).getUint16(0,!1);return c===0?{ok:!0,encryption:0}:c===1||c===2?{ok:!1,reason:"drm",encryption:c}:{ok:!1,reason:"drm",encryption:2}}async function xi(t){let a,s;try{({MOBI:a}=await Rs(()=>import("./mobi-Du_U6_-5.js"),[])),{unzlibSync:s}=await Rs(()=>import("./fflate-CtUkkcu7.js"),[])}catch{throw new Error("Failed to load the Kindle parser.")}try{return await new a({unzlib:s}).open(t)}catch(n){throw new Error(`Couldnât read this Kindle file: ${n instanceof Error?n.message:"parse failed"}`)}}function _c(t){return t.sections.filter(a=>!!a&&a.linear!=="no"&&typeof a.createDocument=="function")}function Py(t){const a=t.querySelector("body");if(!a)return[];const s=[];return a.querySelectorAll("p").forEach(n=>{const r=n.textContent?.trim();r&&s.push(r)}),s.length===0&&(a.textContent?.trim()||"").split(/\n\n+/).forEach(r=>{const i=r.trim();i&&s.push(i)}),s}function Ay(t){const a=t.querySelector("body");if(!a)return!0;if(!(a.querySelector("img, image, svg")!=null))return!1;const n=a.cloneNode(!0);return n.querySelectorAll("img, svg, image").forEach(i=>i.remove()),(n.textContent?.trim()||"").length<20}async function Iy(t){try{return(await vr(t)).ok&&(await xi(t)).metadata?.title?.trim()||null}catch{return null}}async function Um(t){const a=await xi(t);if(a.rendition?.layout==="pre-paginated")return"image";const s=_c(a);if(s.length===0)return"text";const n=Math.min(s.length,20);let r=0,i=0;for(let l=0;l<n;l++){const c=await s[l].createDocument();i++,Ay(c)&&r++}return i===0?"text":r/i>.6?"image":"text"}async function Vm(t){const a=await xi(t);return Km(a)}async function Km(t){const a=_c(t),s=[];let n=0;for(let r=0;r<a.length;r++){const i=await a[r].createDocument(),l=i.querySelector("h1")?.textContent?.trim()||i.querySelector("h2")?.textContent?.trim()||i.querySelector("title")?.textContent?.trim()||`Chapter ${r+1}`,c=Py(i);if(c.length!==0){for(const d of c)n+=d.length;if(n*2>fi)throw new Error(yr);s.push({title:l,order:s.length+1,paragraphs:c})}}if(s.length===0)throw new Error("No chapters extracted from Kindle file");return s}async function Hm(t){try{if(!(await vr(t)).ok)return{title:null,chapters:null};const s=await xi(t),n=s.metadata?.title?.trim()||null;if(s.rendition?.layout==="pre-paginated")return{title:n,chapters:null};try{const r=await Km(s);return{title:n,chapters:r}}catch{return{title:n,chapters:null}}}catch{return{title:null,chapters:null}}}async function Wm(t,a){a?.({phase:"reading",current:0,total:1});const s=await xi(t),n=_c(s).filter(h=>typeof h.load=="function"),r=new Set,i=[],l=[];for(const h of n){const p=await h.load();l.push(p);const g=await(await fetch(p)).text();new DOMParser().parseFromString(g,"text/html").querySelectorAll("img, image").forEach(b=>{const y=b.getAttribute("src")||b.getAttribute("xlink:href")||b.getAttributeNS("http://www.w3.org/1999/xlink","href");y&&(r.has(y)||(r.add(y),i.push(y)))})}const c=new Map,d=new Map,m=i.length;let u=0;try{for(let h=0;h<m;h++){a?.({phase:"extracting",current:h+1,total:m});const p=i[h];let g;
5try{g=await(await fetch(p)).blob()}catch{continue}if(g.size>wr)throw new Error(yr);if(u+=g.size,u>fi)throw new Error(yr);const f=g.type==="image/png"?"png":g.type==="image/webp"?"webp":g.type==="image/gif"?"gif":"jpeg",b=`page_${String(h+1).padStart(4,"0")}.${f}`;c.set(b,g);const y=await Cr(g);y&&d.set(b,y)}}finally{for(const h of l)try{URL.revokeObjectURL(h)}catch{}}return{images:c,mokuroJson:null,dimensions:d}}const Gm=Object.freeze(Object.defineProperty({__proto__:null,KINDLE_DRM_MESSAGE:Om,KINDLE_NOT_MOBI_MESSAGE:Bm,KINDLE_TRUNCATED_MESSAGE:qm,checkKindleDrm:vr,detectKindleType:Um,extractKindleChapters:Vm,extractKindleImages:Wm,extractKindleTitle:Iy,extractKindleTitleAndChapters:Hm,kindleDrmMessage:co},Symbol.toStringTag,{value:"Module"}));async function Ym(t){const a=await t.arrayBuffer();return Ry(a)}async function Ry(t){const a=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(a)).map(s=>s.toString(16).padStart(2,"0")).join("")}let Ei=null;function Jm(){return Ei||(Ei=(async()=>{try{return typeof navigator>"u"||!navigator.storage?.persist?!1:typeof navigator.storage.persisted=="function"&&await navigator.storage.persisted()?!0:await navigator.storage.persist()}catch{return!1}})(),Ei)}const $y=1600,zy=.8,Fy=3;function Dy(t,a){return a>0&&a<t}function Zr(t,a=0,s=0){return{pageNumber:t.pageNumber,blob:t.blob,mimeType:t.mimeType||t.blob.type||"image/jpeg",width:a,height:s,originalBytes:t.blob.size,transcodedBytes:t.blob.size,skipped:!0}}function Ly(t,a){return!a||!Dy(t.blob.size,a.blob.size)?Zr(t):{pageNumber:t.pageNumber,blob:a.blob,mimeType:"image/webp",width:a.width,height:a.height,originalBytes:t.blob.size,transcodedBytes:a.blob.size,skipped:!1}}function _d(){return typeof OffscreenCanvas<"u"&&typeof createImageBitmap=="function"&&typeof OffscreenCanvas.prototype.convertToBlob=="function"}async function Oy(t,a={}){const s=t.length,n=a.onProgress;if(s===0)return{pages:[],supported:_d(),errors:[]};if(!_d()){const h=t.map(p=>Zr(p));return n?.(s,s),{pages:h,supported:!1,errors:[]}}const r=a.maxLongEdge??$y,i=a.quality??zy,l=Math.max(1,a.concurrency??Fy),c=new Worker(new URL("/assets/page-transcode.worker-XjtZwIZm.js",import.meta.url),{type:"module"}),d=new Array(s),m=[];let u=0;try{await new Promise((h,p)=>{let g=0,f=0,b=!1;const y=()=>{b||(b=!0,p(new DOMException("Transcode aborted","AbortError")))};if(a.signal){if(a.signal.aborted){y();return}a.signal.addEventListener("abort",y,{once:!0})}const x=()=>{u+=1,n?.(u,s),f-=1,v()},v=()=>{if(!b){if(u===s){b=!0,h();return}for(;f<l&&g<s;){const w=g++,j=t[w];f+=1;const T={id:w,blob:j.blob,maxLongEdge:r,quality:i};c.postMessage(T)}}};c.onmessage=w=>{const j=w.data,T=j.id;if(T<0||T>=s||d[T]!==void 0)return;const P=t[T];j.ok?d[T]=Ly(P,{blob:j.blob,width:j.width,height:j.height}):(m.push({pageNumber:P.pageNumber,message:j.error}),d[T]=Zr(P)),x()},c.onerror=w=>{b||(b=!0,p(new Error(w.message||"Transcode worker crashed")))},v()})}catch(h){if(h?.name==="AbortError")throw c.terminate(),h;for(let p=0;p<s;p++)d[p]||(d[p]=Zr(t[p]),m.push({pageNumber:t[p].pageNumber,message:h instanceof Error?h.message:"Transcode failed"}));n?.(s,s)}finally{c.terminate()}return{pages:d,supported:!0,errors:m}}const By=20;function Ki(t,a){const s=[];let n=0;for(const[r,i]of t)s.push({pageNumber:n+1,blob:i,mimeType:i.type||"image/jpeg",dims:a.get(r)||{width:0,height:0}}),n+=1;return s}async function Hi(t,a,s={}){const n=a.length;if(n===0)return;const{onProgress:r,signal:i}=s,l=Math.max(1,s.chunkSize??By),c=()=>{if(i?.aborted)throw new DOMException("Transcode aborted","AbortError")};let d=0,m=!1;for(let u=0;u<n;u+=l){c();const h=Math.min(u+l,n),p=[];for(let x=u;x<h;x++){const v=a[x];v&&p.push(v)}if(p.length===0)continue;const g=p.map(x=>({pageNumber:x.pageNumber,blob:x.blob,mimeType:x.mimeType})),f=await Oy(g,{signal:i}),b=p.map((x,v)=>{const w=f.pages[v];return w&&!w.skipped?{pageNumber:x.pageNumber,blob:w.blob,width:w.width,height:w.height}:{pageNumber:x.pageNumber,blob:w?.blob??x.blob,width:x.dims.width,height:x.dims.height}});c(),await Gg(t,b),m||(m=!0,Jm());for(let x=u;x<h;x++)a[x]=null;d+=p.length;const y=f.supported?"optimizing":"saving";r?.(d,n,y)}}const Xm=/\.epub$/i,qy=/\.(cbz|zip)$/i,Uy=/\.pdf$/i,Vy=/\.(mobi|azw|azw3|prc)$/i,Ky=/\.(epub|mobi|azw|azw3|prc)$/i;function Sc(t){return t.content_type==="novel"||t.file_type==="epub"?"novel-epub":t.original_filename&&Xm.test(t.original_filename)?"manga-from-epub"
5:"manga-archive"}function Qm(t){switch(t){case"novel-epub":return".epub,.mobi,.azw,.azw3,.prc";case"manga-from-epub":return".cbz,.zip,.jpg,.jpeg,.png,.webp,.epub";default:return".cbz,.zip,.jpg,.jpeg,.png,.webp,.pdf"}}function Hy(t){return t!=="novel-epub"}async function Zm(t,a,s,n){const r=Sc(t);return r==="novel-epub"?Gy(t,a,s):Wy(t,a,r,s)}async function Wy(t,a,s,n){const r=a.find(w=>Xm.test(w.name))??null,i=a.find(w=>Uy.test(w.name))??null,l=a.find(w=>qy.test(w.name))??null,c=w=>n?.({phase:w.phase==="reading"?"reading":"extracting",current:w.current,total:w.total});let d,m,u=0,h=s;if(r){h="manga-from-epub",u=r.size;const w=await Rm(r,c);d=w.images,m=w.dimensions}else if(i){h="manga-archive",u=i.size;const w=await kc(i,c);d=w.images,m=w.dimensions}else if(l){h="manga-archive",u=l.size;const w=await Mm(l,c);d=w.images,m=w.dimensions}else{u=a.reduce((j,T)=>j+T.size,0);const w=await No(a,c);d=w.images,m=w.dimensions}if(d.size===0)throw new Error("No images found in file");const p=await Nn(d),g=t.total_pages??0,f=d.size,y=(await Yg(t.id))?.contentFingerprint||t.content_sha256||null,x=y?p===y:null,v=r?.name||i?.name||l?.name||a[0]?.name||"reimport";return{fingerprintMatch:x,countMatches:f===g,newCount:f,expectedCount:g,payload:{kind:h,images:d,dimensions:m,fingerprint:p,archiveName:v,fileSizeBytes:u}}}async function Gy(t,a,s){const n=a.find(p=>Ky.test(p.name))??a[0];if(!n)throw new Error("No book file selected");const r=Vy.test(n.name);let i=r?"kindle":"epub";if(r){const p=await vr(n);if(!p.ok)throw new Error(co(p))}else if(await lo(n)==="kindle"){const g=await vr(n);if(!g.ok)throw new Error(co(g));i="kindle"}s?.({phase:"reading",current:0,total:1});const l=await Ym(n);s?.({phase:"reading",current:1,total:1});const c=n.size,d=t.file_size_bytes??0;let m;t.content_sha256?m=l===t.content_sha256:m=null;const u=!t.original_filename||t.original_filename===n.name;return{fingerprintMatch:m,countMatches:(d===0||c===d)&&u,newCount:c,expectedCount:d,payload:{kind:"novel-epub",file:n,fingerprint:l,archiveName:n.name,fileSizeBytes:n.size,format:i}}}function Yy(t){return t.countMatches&&(t.fingerprintMatch===!0||t.fingerprintMatch===null)}async function eh(t,a,s){if(a.kind==="novel-epub"){s?.({phase:"saving",current:0,total:1}),await bc(t,a.file,a.format),s?.({phase:"saving",current:1,total:1});return}const n=a.images.size,r=Ki(a.images,a.dimensions);a.images.clear(),await Hi(t,r,{onProgress:(i,l)=>{s?.({phase:"saving",current:i,total:l})}}),await Bi({materialId:t,totalPages:n,importedAt:new Date().toISOString(),originalFilename:a.archiveName,contentFingerprint:a.fingerprint,fileSizeBytes:a.fileSizeBytes})}function To(t){const{material:a,onRestored:s}=t,n=Sc(a),[r,i]=o.useState("idle"),[l,c]=o.useState(""),[d,m]=o.useState(null),u=o.useRef(s);u.current=s;const h=o.useCallback(x=>{if(x.phase==="reading")c("Reading fileâ¦");else if(x.phase==="extracting"){const v=x.total>0?Math.round(x.current/x.total*100):0;c(`Extracting ${v}%`)}else c(`Saving ${x.current}/${x.total}â¦`)},[]),p=o.useCallback(async x=>{i("working"),m(null),c("Savingâ¦");try{await eh(a.id,x.payload,h),c("Done! Reloadingâ¦"),i("done"),await u.current?.()}catch(v){console.error("[local-restore] commit failed:",v),c("Import failed â try again"),i("error")}},[a.id,h]),g=o.useCallback(async x=>{const v=x.target,w=v.files;if(!w||w.length===0)return;const j=Array.from(w);v.value="",i("working"),m(null),c("Reading fileâ¦");try{const T=await Zm(a,j,h);if(Yy(T)){await p(T);return}m(T),i("mismatch"),c("")}catch(T){console.error("[local-restore] validation failed:",T);const P=T instanceof Error?T.message:"Import failed â try again";c(P==="No images found in file"?P:"Import failed â try again"),i("error")}},[a,h,p]),f=o.useCallback(()=>{d&&p(d)},[d,p]),b=o.useCallback(()=>{m(null),i("idle"),c("")},[]),y=o.useCallback(()=>{m(null),i("idle"),c("")},[]);return{status:r,progress:l,validation:d,kind:n,accept:Qm(n),multiple:Hy(n),onFilesPicked:g,confirmMismatch:f,cancelMismatch:b,reset:y}}const tl="var(--theater-warning)";function Mo({restore:t,title:a="Local file missing",filenameHint:s,detailHint:n,portal:r=!1,onClose:i,dismissable:l=!0}){const c=wn(),d=o.useRef(null),{status:m,progress:u,validation:h,accept:p,multiple:g,onFilesPicked:f}=t,b=r,y=b?"wc-cta-square wc-cta-square--ink wc-restore-btn":"theater-btn theater-btn--primary",x=b?"wc-cta-square wc-cta-square-quiet--ink wc-restore-btn":"theater-btn theater-btn--secondary",v=b?"wc-cta-square wc-cta-square--maple wc-restore-btn":"theater-btn theater-btn--destructive";o.useEffect(()=>{const j=d.current;return()=>{j&&(j.value="")}},[]);const w=e.jsxs("div",{className:"mobile-viewport-modal-stage fixed inset-0 z-[200] flex items-center justify-center theater-scrim","data-mobile-viewport-surface":"local-file-restore",onClick:l?i:void 0,children:[e.jsx("input",{ref:d,type:"file",accept:p,multiple:g,className:"hidden",onChange:f}),e.jsxs("div",{className:"mobile-viewport-modal-panel theater-panel max-w-sm w-full p-6 text-center",role:"dialog","aria-modal":"true","aria-label":a,onClick:j=>j.stopPropagation(),children:[e.jsx("div",{"data-mobile-viewport-modal-body":!0,children:e.jsx(Oa,{mode:"wait",children:m==="mismatch"&&h?e.jsxs(ze.div,{initial:{opacity:0,y:12}
5,animate:{opacity:1,y:0},exit:{opacity:0,y:-12},transition:{duration:.25},className:"space-y-4",style:{position:"relative",zIndex:1},children:[e.jsx(Kt,{name:"warning",size:48,className:"mx-auto"}),e.jsx("p",{className:"text-lg font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:"File mismatch detected"}),e.jsxs("div",{className:"theater-panel p-3 text-left text-sm space-y-2",children:[!h.countMatches&&h.payload.kind!=="novel-epub"&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("span",{style:{color:tl},className:"shrink-0 mt-0.5",children:e.jsx(Kt,{name:"warning",size:14})}),e.jsxs("span",{style:{color:"var(--theater-text)"},children:["Expected ",e.jsx("strong",{children:h.expectedCount})," pages, found"," ",e.jsx("strong",{children:h.newCount}),h.newCount<h.expectedCount?` â ${h.expectedCount-h.newCount} page${h.expectedCount-h.newCount===1?"":"s"} missing`:` â ${h.newCount-h.expectedCount} extra page${h.newCount-h.expectedCount===1?"":"s"}`]})]}),!h.countMatches&&h.payload.kind==="novel-epub"&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("span",{style:{color:tl},className:"shrink-0 mt-0.5",children:e.jsx(Kt,{name:"warning",size:14})}),e.jsx("span",{style:{color:"var(--theater-text)"},children:"This file differs from the one originally imported (different name or size)."})]}),h.fingerprintMatch===!1&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("span",{style:{color:tl},className:"shrink-0 mt-0.5",children:e.jsx(Kt,{name:"warning",size:14})}),e.jsx("span",{style:{color:"var(--theater-text)"},children:"File content differs from original â possibly a different edition or re-scan"})]}),h.countMatches&&h.fingerprintMatch===!1&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx("span",{style:{color:"hsl(var(--module-accent))"},className:"shrink-0 mt-0.5",children:e.jsx(Kt,{name:"check-circle",size:14})}),e.jsx("span",{style:{color:"var(--theater-text-soft)"},children:h.payload.kind==="novel-epub"?"File size matches â text should still align":"Page count matches â OCR overlays should still align"})]}),!h.countMatches&&h.payload.kind!=="novel-epub"&&e.jsx("p",{className:"text-xs",style:{color:"var(--theater-text-muted)"},children:"OCR text overlays may not align correctly for affected pages."})]})]},"mismatch"):m==="working"?e.jsxs(ze.div,{initial:{opacity:0}
5,animate:{opacity:1},exit:{opacity:0},className:"space-y-4 flex flex-col items-center",style:{position:"relative",zIndex:1},children:[!c&&e.jsx(bs,{image:cs,size:96,duration:1.2,repeatDelay:999}),e.jsx("p",{className:"text-lg font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:"Restoring"}),e.jsx("p",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:u})]},"progress"):m==="error"?e.jsxs(ze.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:-12},transition:{duration:.25},className:"space-y-4",style:{position:"relative",zIndex:1},children:[e.jsx(Kt,{name:"warning",size:48,className:"mx-auto"}),e.jsx("p",{className:"text-lg font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:u||"Import failed â try again"})]},"error"):e.jsxs(ze.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:-12},transition:{duration:.25},className:"space-y-4",style:{position:"relative",zIndex:1},children:[e.jsx(Kt,{name:"folder",size:48,className:"mx-auto"}),e.jsx("p",{className:"text-lg font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:a}),e.jsx("p",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Select the original file to restore it on this device."}),s&&e.jsxs("p",{className:"text-xs truncate px-2",style:{color:"var(--theater-text-muted)",fontFamily:"'JetBrains Mono', monospace"},children:[s,n?` â ${n}`:""]})]},"initial")})}),m!=="working"&&e.jsx("div",{"data-mobile-viewport-modal-footer":!0,className:"flex shrink-0 flex-wrap gap-2 pt-4",children:m==="mismatch"?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>{t.cancelMismatch(),d.current?.click()},className:`${x} flex-1`,children:"Choose different file"}),e.jsx("button",{type:"button",onClick:t.confirmMismatch,className:`${v} flex-1`,children:"Import anyway"})]}):m==="error"?e.jsxs(e.Fragment,{children:[l&&e.jsx("button",{type:"button",onClick:i,className:`${x} flex-1`,children:"Close"}),e.jsx("button",{type:"button",onClick:()=>{t.reset(),d.current?.click()},className:`${y} flex-1`,children:"Try again"})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>d.current?.click(),className:`${y} flex-1`,children:"Select file"}),l&&e.jsx("button",{type:"button",onClick:i,className:`${x} flex-1`,children:"Continue without it"})]})})]})]});return r&&typeof document<"u"?hi.createPortal(e.jsx("div",{className:"wc-modal-root reader-theater wc-restore-paper",children:w}),document.body):w}function Jy({className:t,defaultValue:a,value:s,min:n=0,max:r=100,...i}){const l=o.useMemo(()=>Array.isArray(s)?s:Array.isArray(a)?a:[n,r],[s,a,n,r]);return e.jsxs(Vp,{"data-slot":"slider",defaultValue:a,value:s,min:n,max:r,className:Fo("relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col",t),...i,children:[e.jsx(Kp,{"data-slot":"slider-track",className:Fo("bg-muted relative grow overflow-hidden rounded-full data-[orientation=horizontal]:h-1.5 data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5"),children:e.jsx(Hp,{"data-slot":"slider-range",className:Fo("bg-primary absolute data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full")})}),Array.from({length:l.length},(c,d)=>e.jsx(Wp,{"data-slot":"slider-thumb",className:"border-primary bg-white dark:bg-zinc-800 ring-ring/50 block size-4 shrink-0 rounded-full border shadow-sm transition-[color,box-shadow] hover:ring-4 focus-visible:ring-4 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50"},d))]})}const Sd=.04;function mr(t,a,s){return Math.min(s,Math.max(a,t))}function Wi(t){const a=mr(Number.isFinite(t.width)?t.width:.6,Sd,1),s=mr(Number.isFinite(t.height)?t.height:.6,Sd,1);return{x:mr(Number.isFinite(t.x)?t.x:(1-a)/2,0,1-a),y:mr(Number.isFinite(t.y)?t.y:(1-s)/2,0,1-s),width:a,height:s}}function Xy(t){if(![t.x,t.y,t.width,t.height].every(Number.isFinite)||t.width<=0||t.height<=0)return{x:.2,y:.2,width:.6,height:.6};const a=mr(Math.max(t.width*3,.38),.25,.85),s=mr(Math.max(t.height*3,.28),.2,.75);return Wi({x:t.x+t.width/2-a/2,y:t.y+t.height/2-s/2,width:a,height:s})}const Ds=.04;function nn(t,a,s){return Math.min(s,Math.max(a,t))}function Qy(t,a,s,n){let r=t.x,i=t.y,l=t.x+t.width,c=t.y+t.height;
5return a.includes("w")&&(r=nn(r+s,0,l-Ds)),a.includes("e")&&(l=nn(l+s,r+Ds,1)),a.includes("n")&&(i=nn(i+n,0,c-Ds)),a.includes("s")&&(c=nn(c+n,i+Ds,1)),{x:r,y:i,width:l-r,height:c-i}}function Zy({imageUrl:t,initialBounds:a,onConfirm:s,onCancel:n}){const r=o.useRef(null),i=o.useRef(null),l=o.useRef(null),[c,d]=o.useState(()=>Wi(a));o.useEffect(()=>{r.current?.focus()},[]),o.useEffect(()=>{const f=b=>{b.defaultPrevented||b.key==="Escape"&&(b.preventDefault(),n())};return window.addEventListener("keydown",f),()=>window.removeEventListener("keydown",f)},[n]);const m=f=>{const b=i.current?.getBoundingClientRect();return!b||b.width<=0||b.height<=0?null:{x:nn((f.clientX-b.left)/b.width,0,1),y:nn((f.clientY-b.top)/b.height,0,1)}},u=(f,b,y)=>{const x=m(f);x&&(f.preventDefault(),f.stopPropagation(),f.currentTarget.setPointerCapture(f.pointerId),l.current={kind:b,handle:y,pointerId:f.pointerId,startX:x.x,startY:x.y,startBounds:c},b==="draw"&&d(Wi({x:nn(x.x-Ds/2,0,1-Ds),y:nn(x.y-Ds/2,0,1-Ds),width:Ds,height:Ds})))},h=f=>{const b=l.current,y=m(f);if(!b||b.pointerId!==f.pointerId||!y)return;f.preventDefault();const x=y.x-b.startX,v=y.y-b.startY;if(b.kind==="move")d({...b.startBounds,x:nn(b.startBounds.x+x,0,1-b.startBounds.width),y:nn(b.startBounds.y+v,0,1-b.startBounds.height)});else if(b.kind==="resize"&&b.handle)d(Qy(b.startBounds,b.handle,x,v));else if(b.kind==="draw"){const w=Math.min(b.startX,y.x),j=Math.min(b.startY,y.y),T=Math.max(b.startX,y.x),P=Math.max(b.startY,y.y);d(Wi({x:w,y:j,width:Math.max(Ds,T-w),height:Math.max(Ds,P-j)}))}},p=f=>{l.current?.pointerId===f.pointerId&&(l.current=null,f.currentTarget.hasPointerCapture(f.pointerId)&&f.currentTarget.releasePointerCapture(f.pointerId))},g=f=>{if(f.key!=="Tab")return;const b=Array.from(r.current?.querySelectorAll("button:not(:disabled)")??[]);if(b.length===0)return;const y=b[0],x=b[b.length-1];f.shiftKey&&(document.activeElement===y||document.activeElement===r.current)?(f.preventDefault(),x.focus()):!f.shiftKey&&document.activeElement===x&&(f.preventDefault(),y.focus())};return e.jsxs("div",{ref:r,className:"manga-crop-tool",role:"dialog","aria-modal":"true","aria-labelledby":"manga-crop-title",tabIndex:-1,onKeyDown:g,onPointerDown:f=>f.stopPropagation(),children:[e.jsxs("header",{className:"manga-crop-tool__header",children:[e.jsxs("div",{children:[e.jsxs("p",{className:"theater-rail-eyebrow",children:[e.jsx(Kt,{name:"crop",size:15})," Mnemonic image"]}),e.jsx("h2",{id:"manga-crop-title",children:"Frame the part of the page you want to save"}),e.jsx("p",{children:"Drag inside the frame to move it, use the handles to resize it, or drag elsewhere to draw a new frame."})]}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn",onClick:n,"aria-label":"Cancel image crop",children:e.jsx(Kt,{name:"close",size:24})})]}),e.jsx("div",{className:"manga-crop-tool__viewport",children:e.jsxs("div",{ref:i,className:"manga-crop-tool__stage",onPointerDown:f=>u(f,"draw"),onPointerMove:h,onPointerUp:p,onPointerCancel:p,children:[e.jsx("img",{src:t,alt:"Manga page to crop",draggable:!1}),e.jsx("div",{className:"manga-crop-tool__selection",style:{left:`${c.x*100}%`,top:`${c.y*100}%`,width:`${c.width*100}%`,height:`${c.height*100}%`},onPointerDown:f=>u(f,"move"),"aria-label":"Selected manga image area",children:["nw","n","ne","e","se","s","sw","w"].map(f=>e.jsx("span",{className:`manga-crop-tool__handle manga-crop-tool__handle--${f}`,onPointerDown:b=>u(b,"resize",f),"aria-hidden":"true"},f))})]})}),e.jsxs("footer",{className:"manga-crop-tool__footer",children:[e.jsxs("p",{"aria-live":"polite",children:["Selected ",Math.round(c.width*100),"% Ã ",Math.round(c.height*100),"% of the page"]}),e.jsxs("div",{className:"manga-crop-tool__actions",children:[e.jsx("button",{type:"button",className:"theater-btn theater-btn--secondary",onClick:n,children:"Cancel"}),e.jsxs("button",{type:"button",className:"theater-btn theater-btn--primary",onClick:()=>s(c),children:[e.jsx(Kt,{name:"check",size:24})," Use this frame"]})]})]})]})}const eb=1.1,tb=8;function Nl(t,a,s){let n=0;for(const i of a)n+=i.charCodeAt(0)>255?1:.55;if(n<=0||s<=0||!Number.isFinite(s))return{size:t,clip:!1};const r=s*eb/n;return r>=t?{size:t,clip:!1}:{size:Math.max(tb,r),clip:r<t*.6}}function Nd(t){const a=t.orientation==="vertical";return t.lines.some((s,n)=>{const r=t.linesCoords?.[n];let i;if(r&&r.length>0){const l=a?1:0;let c=1/0,d=-1/0;for(const m of r)m[l]<c&&(c=m[l]),m[l]>d&&(d=m[l]);i=d-c}else i=a?t.boxHeightPx:t.boxWidthPx;return Nl(t.baseFontSize,s,i).clip})}const ab=480,sb=160*1024;function nb(t){return typeof t.box_index=="number"&&Number.isSafeInteger(t.box_index)&&t.box_index>
5=0?t.box_index:null}function rb(t,a){return new Promise((s,n)=>{t.toBlob(r=>{if(!r||r.type!=="image/webp"){n(new Error("WebP encoding is unavailable"));return}s(r)},"image/webp",a)})}function Cd(t,a,s){const n=document.createElement("canvas");n.width=Math.max(1,Math.round(a)),n.height=Math.max(1,Math.round(s));const r=n.getContext("2d");if(!r)throw new Error("Canvas is unavailable");return r.imageSmoothingEnabled=!0,r.imageSmoothingQuality="high",r.drawImage(t,0,0,n.width,n.height),n}async function th(t,a,s){if(!(a>0)||!(s>0))throw new Error("Source image has no dimensions");const n=Math.min(1,ab/Math.max(a,s));let r=Cd(t,a*n,s*n);for(let i=0;i<5;i++){for(const l of[.82,.72,.62,.52,.42]){const c=await rb(r,l);if(c.size<=sb)return c}if(r.width<=96||r.height<=96)break;r=Cd(r,r.width*.82,r.height*.82)}throw new Error("Image could not be encoded within the cloud storage limit")}function Nc(t,a,s=5e3){return new Promise((n,r)=>{const i=window.setTimeout(()=>{t.removeEventListener(a,l),r(new Error(`Timed out waiting for ${a}`))},s),l=()=>{window.clearTimeout(i),t.removeEventListener(a,l),n()};t.addEventListener(a,l,{once:!0})})}async function Ed(t,a){if(Math.abs(t.currentTime-a)<=.004&&t.readyState>=2)return;const s=Nc(t,"seeked");t.currentTime=a,await s}async function ib(t,a){if(!Number.isFinite(a)||a<0)throw new Error("Invalid clicked video time");const s=a/1e3,n=t.currentTime,r=t.paused;t.pause();try{if(await Ed(t,s),t.readyState<2&&await Nc(t,"loadeddata"),Math.abs(t.currentTime-s)>.012)throw new Error("The clicked video frame is no longer available");return{blob:await th(t,t.videoWidth,t.videoHeight),usedFullPageFallback:!1,provenance:{captureMode:"video_frame",sourceWidth:t.videoWidth,sourceHeight:t.videoHeight,cropBounds:{x:0,y:0,width:t.videoWidth,height:t.videoHeight}}}}finally{try{await Ed(t,n)}catch{}r||t.play().catch(()=>{})}}function ob(t,a){const n=a.x+a.width/2,r=a.y+a.height/2;return t.x<=n+1&&t.y<=r+1&&t.x+t.width+1>=n&&t.y+t.height+1>=r}function ah(t,a,s){const n=Math.max(0,Math.floor(t.x)),r=Math.max(0,Math.floor(t.y)),i=Math.min(a,Math.ceil(t.x+t.width)),l=Math.min(s,Math.ceil(t.y+t.height));return i<=n||l<=r?null:{x:n,y:r,width:i-n,height:l-r}}function lb(t,a,s){return![t.x,t.y,t.width,t.height,a,s].every(Number.isFinite)||a<=0||s<=0||t.x<0||t.y<0||t.width<=0||t.height<=0||t.x+t.width>1+Number.EPSILON*8||t.y+t.height>1+Number.EPSILON*8?null:ah({x:t.x*a,y:t.y*s,width:t.width*a,height:t.height*s},a,s)}async function cb(t){const a=new Image;a.crossOrigin="anonymous";const s=Nc(a,"load");return a.src=t,await s,a}async function db(t){const a=await cb(t.imageUrl),s={x:0,y:0,width:a.naturalWidth,height:a.naturalHeight},n=t.manualCropNormalized?lb(t.manualCropNormalized,a.naturalWidth,a.naturalHeight):null;if(t.manualCropNormalized&&!n)throw new Error("The selected manga crop is outside the source page");const r=t.ocrBoxNormalized?{x:t.ocrBoxNormalized.x*a.naturalWidth,y:t.ocrBoxNormalized.y*a.naturalHeight,width:t.ocrBoxNormalized.width*a.naturalWidth,height:t.ocrBoxNormalized.height*a.naturalHeight}:t.ocrBox,i=t.panelAnalyzedWidth&&t.panelAnalyzedWidth>0?a.naturalWidth/t.panelAnalyzedWidth:1,l=t.panelAnalyzedHeight&&t.panelAnalyzedHeight>0?a.naturalHeight/t.panelAnalyzedHeight:1,c=t.panelBounds?{x:t.panelBounds.x*i,y:t.panelBounds.y*l,width:t.panelBounds.width*i,height:t.panelBounds.height*l}:void 0,d=c&&r&&ob(c,r)?ah(c,a.naturalWidth,a.naturalHeight):null,m=n??d??s,u=document.createElement("canvas");u.width=m.width,u.height=m.height;const h=u.getContext("2d");if(!h)throw new Error("Canvas is unavailable");return h.drawImage(a,m.x,m.y,m.width,m.height,0,0,m.width,m.height),{blob:await th(u,m.width,m.height),usedFullPageFallback:!n&&d===null,provenance:{captureMode:n?"manual_crop":d===null?"full_page":"detected_frame",sourceWidth:a.naturalWidth,sourceHeight:a.naturalHeight,cropBounds:m}}}const sh="reading.grammarProgress",al="shizen:grammar-progress-preference";let nh=!1;function Td(){if(typeof window>"u")return!1;try{return window.localStorage.getItem(sh)==="true"}catch{return nh}}function Cc(){const[t,a]=o.useState(Td);o.useEffect(()=>{const n=()=>a(Td());return window.addEventListener("storage",n),window.addEventListener(al,n),()=>{window.removeEventListener("storage",n),window.removeEventListener(al,n)}},[]);const s=o.useCallback(n=>{nh=n,a(n);try{window.localStorage.setItem(sh,String(n))}catch{}typeof window<"u"&&window.dispatchEvent(new Event(al))},[]);return[t,s]}function ub(t,a,s){if(!a?.length||t.length===0)return new Map;const n=t.map((c,d)=>{const m=cc(c),u=m.start_char??d,h=m.end_char??u+m.surface.length;return{index:d,token:m,startChar:u,endChar:h}}),r=new Map;for(const c of a){const d=c;if((d.isProperNoun??d.is_proper_noun)!==!0)continue;const m=d.startChar??d.start_char,u=d.endChar??d.end_char;if(typeof m!="number"||typeof u!="number"||m<0||u<=m)continue;const h=n.filter(O=>O.startChar<u&&O.endChar>m).sort((O,A)=>O.startChar-A.startChar||O.endChar-A.endChar);if(h.length<1||h[0].startChar!==m||h[h.length-1].endChar!==u||h.some(O=>O.startChar<m||O.endChar>u))continue;let p=m,g="",f=!0;for(const O of h){if(O.startChar!==p||O.endChar<=O.startChar){f=!1;break}g+=O.token.surface,p=O.endChar}if(!f||p!==u||!d.surface||g!==d.surface)continue;const b=d,y=O=>Object.prototype.hasOwnProperty.call(b,O),x=(O,A,k)=>y(O)&&b[O]!==void 0?b[O]:y(A)&&b[A]!==void 0?b[A]:k,v=x("reading","reading",g),w=x("lemmaSurface","lemma",g),j=h[0],T=nm(j.token,s,j.index),P={...T,surface:g,reading:v,pos:"propn",posTags:["propn"],lemmaSurface:w,startChar:m,endChar:u,originalStartChar:m,originalEndChar:u,head:typeof T.id=="number"?T.id:T.head,children:[],grammarKey:null,grammarGloss:null,grammarPointId:null,grammarPoint:null,grammarCandidates:[],conjugationMeta:void 0,conjugation:void 0,baseLemma:w,displaySurface:g},N=x("vocabId","vocab_id",null),_=x("lemmaKey","lemma_key",null),L=d.mappingStatus??d.mapping_status??(N==null?"stored-null":"stored-match"),q=JSON.stringify([m,u,g,v,w,N,_,L]);r.has(q)||r.set(q,{startChar:m,endChar:u,projection:{token:rm(P,d),coveredIndexes:h.map(O=>O.index)}})}const i=[...r.values()],l=new Map;for(const c of i)i.some(m=>m!==c&&m.startChar<c.endChar&&m.endChar>c.startChar)||l.set(c.projection.coveredIndexes[0],c.projection);return l}function Ec({materialId:t,getAccessToken:a,currentPageNumber:s,isPublic:n=!1,lookupNLPToken:r=Yp}
5){const[i,l]=o.useState(null),[c,d]=o.useState(!1),[m,u]=o.useState(),[h,p]=o.useState(new Map),[g,f]=o.useState(null),b=o.useRef(s);o.useEffect(()=>{b.current=s},[s]);const y=o.useRef(0),x=o.useRef(0),v=o.useRef(new Map),w=o.useCallback((k,J,M,H)=>`${t}|${k??""}|${J??""}|${M??""}|${H}`,[t]),j=o.useCallback(k=>v.current.get(k),[]),T=o.useCallback((k,J)=>{const H=v.current;for(H.has(k)&&H.delete(k),H.set(k,J);H.size>200;){const ee=H.keys().next().value;if(ee===void 0)break;H.delete(ee)}},[]),P=o.useCallback(async k=>{const J=++x.current;try{const M=n?`${ue()}/api/reading/public/material/${t}/tokens?pageNumber=${k}`:`${ue()}/api/reading/materials/${t}/tokens?pageNumber=${k}`,H={};if(!n){const de=await a();if(!de)return;H.Authorization=`Bearer ${de}`}const ee=await fetch(M,{headers:H});if(!ee.ok){console.warn("Failed to load page tokens:",ee.status);return}const Pe=await ee.json();if(J!==x.current)return;const D=new Map;for(const de of Pe.tokens)D.has(de.box_id)||D.set(de.box_id,[]),D.get(de.box_id).push(de);p(de=>new Map([...de,...D]))}catch(M){console.error("Error loading page tokens:",M)}},[t,a,n]),N=o.useCallback(k=>{if(k.processedData?.tokens&&k.processedData.tokens.length>0){const J=h.get(k.id),M=ub(k.processedData.tokens,J,k.id),H=new Set([...M.values()].flatMap(D=>D.coveredIndexes.slice(1))),ee=new Map,Pe=new Map;if(J)for(const D of J){const de=D.startChar??D.start_char??-1,fe=D.endChar??D.end_char??-1;de>=0&&fe>=de&&ee.set(`${de}-${fe}`,D),de>=0&&D.conjugationMeta&&Pe.set(de,D.conjugationMeta)}return k.processedData.tokens.flatMap((D,de)=>{const fe=M.get(de);if(fe)return[fe.token];if(H.has(de))return[];const Me=cc(D);let U=nm(Me,k.id,de);const ve=Me.start_char??de,yt=Me.end_char??ve+Me.surface.length,ut=ee.get(`${ve}-${yt}`);ut&&(U=rm(U,ut));const St=Pe.get(ve);if(St&&(U.conjugationMeta=St),ut)return[U];const je=Gp(U,J??[]);return je?.diagnostic&&console.warn("[reader] Ignoring malformed stored numeric partition",{boxId:k.id,startChar:ve,endChar:yt,diagnostic:je.diagnostic}),je?.tokens??[U]})}return h.get(k.id)||[]},[h]),_=o.useCallback((k,J)=>{const M=k.posTags&&k.posTags.length>0?k.posTags:k.pos?Array.isArray(k.pos)?k.pos:[k.pos]:["unknown"],H=typeof k.id=="number"?k.id:J+(k.startChar??0),ee=k.conjugationMeta?{descriptors:k.conjugationMeta.descriptors,grammarPointIds:k.conjugationMeta.grammarPointIds,grammarTagDetails:k.conjugationMeta.grammarTagDetails,rootSurface:k.conjugationMeta.rootSurface,clusterKind:k.conjugationMeta.clusterKind}:void 0;return{id:H,surface:k.surface,lemma:k.lemmaSurface||k.surface,pos:M,reading:k.reading,head:typeof k.head=="number"?k.head:H,dep:k.dep??"dep",bunsetsu_index:k.bunsetsuIndex??null,is_bunsetsu_head:k.isBunsetsuHead??!1,ent_type:k.entType??null,children:k.children?.filter(Pe=>typeof Pe=="number")??[],start_char:k.originalStartChar??k.startChar??0,end_char:k.originalEndChar??k.endChar??0,grammar_key:k.grammarKey??null,grammar_point_id:k.grammarPointId??null,character_readings:k.characterReadings??null,meanings:k.meanings??null,vocabId:k.vocabId??null,vocab_id:k.vocabId??null,lexemeVocabId:k.lexemeVocabId??null,lexeme_vocab_id:k.lexemeVocabId??null,lemma_key:k.lemmaKey??null,is_proper_noun:k.isProperNoun??!1,analysis_confidence:k.confidence??null,mappingStatus:k.mappingStatus,analysisMetadata:k.analysisMetadata??null,analysis_metadata:k.analysisMetadata??null,conjugationMeta:ee,conjugation:k.conjugation}},[]),L=o.useCallback(async(k,J,M)=>{const H=++y.current;u({x:J.clientX,y:J.clientY,writingMode:M});const ee={id:k.id??0,surface:k.surface,lemma:k.lemmaSurface||k.lemma||k.surface,pos:Array.isArray(k.pos)?k.pos:k.posTags||(k.pos?[k.pos]:[]),reading:k.reading,head:k.head??0,dep:k.dep??"dep",bunsetsu_index:k.bunsetsu_index??k.bunsetsuIndex??null,is_bunsetsu_head:k.is_bunsetsu_head??k.isBunsetsuHead??!1,ent_type:k.ent_type??k.entType??null,children:k.children??[],start_char:k.originalStartChar??k.start_char??k.startChar??0,end_char:k.originalEndChar??k.end_char??k.endChar??0,grammar_key:k.grammar_key??k.grammarKey??null,grammar_point_id:k.grammar_point_id??k.grammarPointId??null,grammar_points:k.grammar_points??[],character_readings:k.character_readings??k.characterReadings??null,meanings:k.meanings??null,vocabId:k.vocabId??k.vocab_id??null,vocab_id:k.vocabId??k.vocab_id??null,lexemeVocabId:k.lexemeVocabId??k.lexeme_vocab_id??null,lexeme_vocab_id:k.lexemeVocabId??k.lexeme_vocab_id??null,mappingStatus:k.mappingStatus,analysisMetadata:k.analysisMetadata??k.analysis_metadata??null,analysis_metadata:k.analysisMetadata??k.analysis_metadata??null,conjugationMeta:k.conjugationMeta,conjugation:k.conjugation},Pe={reading:k.reading,vocab_id:k.vocabId??k.vocab_id??null,lexemeVocabId:k.lexemeVocabId??k.lexeme_vocab_id??null,meanings:k.meanings??null,lemma_key:k.lemmaKey??k.lemma_key??null,is_proper_noun:k.isProperNoun??k.is_proper_noun??!1,confidence:k.confidence??k.analysis_confidence??null,mappingStatus:k.mappingStatus??"no-occurrence",anal
5ysisMetadata:k.analysisMetadata??k.analysis_metadata??null},D=od(ee,k.boxId,{vocabToken:Pe});if(l(D),D.mappingStatus==="stored-null"){H===y.current&&d(!1);return}if(D.mappingStatus!=="stored-match"&&ld(D)){H===y.current&&d(!1);return}const de=w(k.boxId||"",ee.start_char,ee.end_char,ee.surface),fe=j(de);if(fe){H===y.current&&(l(fe),d(!1));return}d(!0);try{const Me=n?void 0:await a()??void 0;if(!n&&!Me)return;const{final:U}=await r({materialId:t,authToken:Me,isPublic:n,nlpToken:ee,boxId:k.boxId||"",pageNumber:b.current,vocabToken:Pe}),ve={...U,boxId:D.boxId??U.boxId,originalStartChar:D.originalStartChar??D.startChar??U.originalStartChar??U.startChar,originalEndChar:D.originalEndChar??D.endChar??U.originalEndChar??U.endChar};T(de,ve),H===y.current&&l(ve)}catch(Me){console.error("Error fetching token data:",Me)}finally{H===y.current&&d(!1)}},[t,a,n,r,w,j,T]),q=o.useCallback(async(k,J,M,H,ee)=>{const Pe=++y.current;H&&u({x:H.clientX,y:H.clientY});const D=od(k,J,{vocabToken:ee?{reading:ee.reading,vocab_id:ee.vocab_id,lexemeVocabId:ee.lexemeVocabId,lexeme_vocab_id:ee.lexeme_vocab_id,meanings:ee.meanings,lemma_key:ee.lemma_key,is_proper_noun:ee.is_proper_noun,confidence:ee.analysis_confidence,mappingStatus:ee.mappingStatus??(ee.vocab_id==null?"stored-null":"stored-match"),analysisMetadata:ee.analysisMetadata}:void 0});if(l(D),D.mappingStatus==="stored-null"){Pe===y.current&&d(!1);return}if(D.mappingStatus!=="stored-match"&&ld(D)){Pe===y.current&&d(!1);return}const de=w(J,k.start_char,k.end_char,k.surface),fe=j(de);if(fe){Pe===y.current&&(l(fe),d(!1));return}d(!0);try{const Me=n?void 0:await a()??void 0;if(!n&&!Me)return;const{final:U}=await r({materialId:t,authToken:Me,isPublic:n,nlpToken:k,boxId:J,pageNumber:M??b.current,vocabToken:ee?{reading:ee.reading,vocab_id:ee.vocab_id,lexemeVocabId:ee.lexemeVocabId,lexeme_vocab_id:ee.lexeme_vocab_id,meanings:ee.meanings,lemma_key:ee.lemma_key,is_proper_noun:ee.is_proper_noun,confidence:ee.analysis_confidence,mappingStatus:ee.mappingStatus??(ee.vocab_id==null?"stored-null":"stored-match"),analysisMetadata:ee.analysisMetadata}:void 0});T(de,U),Pe===y.current&&l(U)}catch(Me){console.error("Token lookup error:",Me)}finally{Pe===y.current&&d(!1)}},[t,a,n,r,w,j,T]),O=o.useCallback(()=>{y.current+=1,l(null),u(void 0),d(!1)},[]),A=o.useCallback(()=>{f(null)},[]);return{selectedToken:i,setSelectedToken:l,tokenPanelPosition:m,setTokenPanelPosition:u,tokenPanelLoading:c,pageTokens:h,loadPageTokens:P,getContainerTokens:N,tokenDataToNLPToken:_,handleTokenClick:L,handleNLPTokenClick:q,closeTokenPanel:O,boxHoveredCluster:g,setBoxHoveredCluster:f,clearClusterHover:A}}const Md=()=>$a()?"Your shared AI & processing credit balance cannot cover this AI Help request. Upgrade your plan for a larger monthly allowance.":"Your shared AI & processing credit balance cannot cover this AI Help request.",Pd=t=>t==="CREDIT_WALLET_INSUFFICIENT"||t==="QUOTA_EXCEEDED"||t==="TOKEN_QUOTA_EXCEEDED"||t==="QUOTA_REFUSED",Tc="shizen:ai-help:pending:v1",uo=new Map;function rh(t){const a=JSON.stringify(t);let s=2166136261,n=2654435769;for(let r=0;r<a.length;r++){const i=a.charCodeAt(r);s=Math.imul(s^i,16777619),n=Math.imul(n^i,2246822507)}return`${a.length.toString(36)}:${(s>>>0).toString(36)}:${(n>>>0).toString(36)}`}function mb(t){if(!t)return"anonymous";try{const a=t.split(".")[1];if(!a)return"authenticated";const s=a.replace(/-/g,"+").replace(/_/g,"/"),n=JSON.parse(atob(s.padEnd(Math.ceil(s.length/4)*4,"=")));return typeof n?.sub=="string"&&n.sub?rh(n.sub):"authenticated"}catch{return"authenticated"}}function Cl(){try{const t=localStorage.getItem(Tc);return t?JSON.parse(t):{}}catch{return{}}}function Ad(t,a){const s=`${mb(t)}:${rh(a)}`,r=Cl()[s]||uo.get(s)||crypto.randomUUID();uo.set(s,r);try{const i=Cl();i[s]=r,localStorage.setItem(Tc,JSON.stringify(i))}catch{}return{identity:s,operationKey:r}}function Ti(t){uo.get(t.identity)===t.operationKey&&uo.delete(t.identity);try{const a=Cl();if(a[t.identity]!==t.operationKey)return;delete a[t.identity],localStorage.setItem(Tc,JSON.stringify(a))}catch{}}function qr(t){return t==="AI_HELP_IN_PROGRESS"||t==="AI_HELP_SETTLEMENT_PENDING"||t==="AI_HELP_HISTORY_RECOVERY_PENDING"||t==="AI_HELP_RECOVERY_PENDING"}async function Id(t,a,s){const n=JSON.stringify(a),r=()=>fetch(`${ue()}/api/reading/ai-help`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t}`},body:n}),i=[200,400,800,1600];let l=!1;for(let c=0;;c++){if(!s())throw new DOMException("AI Help request superseded","AbortError");let d;try{d=await r()}catch(h){if(!l){l=!0;continue}throw h}const m=d.ok?null:await d.clone().json().catch(()=>null);
5if(!qr(m?.error)||c>=i.length)return d;await new Promise(h=>setTimeout(h,i[c]))}}function Rd(t){return t.cached===!0?{state:"no_charge",label:"Cached AI Help result · no credits charged"}:t.replayed===!0?{state:"recovered",label:"Original AI Help result recovered · no new charge"}:{state:"settled",label:"AI Help delivered · final charge recorded in credit history"}}function $d(t){return t==="AI_HELP_SETTLEMENT_PENDING"?"AI Help finished, but credit settlement is still being reconciled. Retry keeps the same operation and will not start new provider work.":t==="AI_HELP_HISTORY_RECOVERY_PENDING"?"AI Help finished, but its saved conversation is still being recovered. Retry keeps the same operation and will not create a new charge.":t==="AI_HELP_RECOVERY_PENDING"?"AI Help could not complete and its credit release is still being reconciled. Retry keeps the same operation.":"AI Help is still processing. Retry keeps the same operation and will not create a second charge."}function Mc(t){const a=t.processedData?.tokens;return a?.length?a.slice(0,30).map(s=>{const n={surface:s.surface,reading:s.reading||null,lemma:s.lemma||null,pos:s.pos||null},r=s.grammar_key??s.grammarKey,i=s.grammar_point_id??s.grammarPointId;r&&(n.grammarKey=r),i&&(n.grammarPointId=i);const l=s.conjugationMeta;return l&&(l.descriptors?.length&&(n.descriptors=l.descriptors),l.grammarTagDetails?.length&&(n.grammarTagDetails=l.grammarTagDetails.map(c=>({label:c.label,meaning:c.meaning||null})))),n}):[]}function Pc(t,a){const[s,n]=o.useState([]),[r,i]=o.useState(!1),[l,c]=o.useState(null),[d,m]=o.useState(!1),[u,h]=o.useState(""),[p,g]=o.useState(""),f=o.useRef(null),b=o.useRef(0),y=o.useCallback(async w=>{const j=++b.current,{material:T,pageNumber:P,focus:N}=w,_=w.surroundingTexts.slice(0,10),L=w.tokenMetadata??[],q={clickedBoxText:w.text,surroundingTexts:_,materialTitle:T.title,materialTitleJp:T.title_jp||null,series:T.series||null,pageNumber:P,tokenMetadata:L,focus:N??null,conversationId:null};f.current=q,h(w.text),g(T.title_jp||T.title),n([]),c(null),m(!1),i(!0);try{const O=await t(),A={kind:"initial",materialId:T.id,...q},k=Ad(O,A),J=await Id(O,{...q,operationKey:k.operationKey},()=>j===b.current);if(!J.ok){const H=await J.json().catch(()=>({message:"Request failed"}));if(qr(H.error)||Ti(k),j!==b.current)return;if(Pd(H.error)){ne("quota_limit_reached",{feature:"ai_help",current_tier:"unknown"}),c(Md()),m(!0),i(!1);return}if(qr(H.error)){c($d(H.error)),i(!1);return}if(J.status===429){c("AI Help is receiving too many requests right now. Wait a moment and try again."),i(!1);return}throw new Error(H.message||`HTTP ${J.status}`)}const M=await J.json();if(Ti(k),j!==b.current)return;f.current&&typeof M?.conversationId=="string"&&(f.current.conversationId=M.conversationId),n([{role:"assistant",content:M.explanation,creditReceipt:Rd(M)}]),a?.()}catch(O){if(j!==b.current)return;c(O.message||"Failed to get explanation")}finally{j===b.current&&i(!1)}},[t,a]),x=o.useCallback(async(w,j,T,P,N)=>{const _=j.findIndex(A=>A.id===w.id),L=Math.max(0,_-5),q=Math.min(j.length,_+6),O=j.slice(L,q).filter(A=>A.id!==w.id).map(A=>A.text);await y({text:w.text,surroundingTexts:O,tokenMetadata:Mc(w),material:T,pageNumber:P,focus:N})},[y]),v=o.useCallback(async w=>{if(!f.current||!w.trim())return;const j=f.current.conversationId;if(!j){c("Conversation context lost â please close and re-open AI Help.");return}const T=++b.current,P={role:"user",content:w.trim()};n(N=>[...N,P]),i(!0),c(null);try{const N=await t(),_=w.trim(),q=Ad(N,{kind:"follow_up",conversationId:j,followUp:_}),O=await Id(N,{conversationId:j,followUp:_,operationKey:q.operationKey},()=>T===b.current);if(!O.ok){const k=await O.json().catch(()=>({message:"Request failed"}));if(qr(k.error)||Ti(q),T!==b.current)return;if(Pd(k.error)){ne("quota_limit_reached",{feature:"ai_help",current_tier:"unknown"}),c(Md()),m(!0),i(!1);return}if(qr(k.error)){c($d(k.error)),i(!1);return}if(O.status===429){c("AI Help is receiving too many requests right now. Wait a moment and try again."),i(!1);return}if(k.error==="CONVERSATION_NOT_FOUND"||k.error==="MISSING_CONVERSATION"){c("Conversation expired â please close and re-open AI Help."),i(!1);return}throw new Error(k.message||`HTTP ${O.status}`)}const A=await O.json();if(Ti(q),T!==b.current)return;n(k=>[...k,{role:"assistant",content:A.explanation,creditReceipt:Rd(A)}]),a?.()}catch(N){if(T!==b.current)return;c(N.message||"Failed to get response")}finally{T===b.current&&i(!1)}},[t,a]);return o.useMemo(()=>({triggerHelp:x,explain:y,sendFollowUp:v,messages:s,isLoading:r,error:l,quotaExceeded:d,contextText:u,materialTitle:p}),[x,y,v,s,r,l,d,u,p])}
5const Gi={width:1684,height:2528,imageUrl:"/optimized/demomanga-1684w.webp",textBoxes:[{id:"demo-box-2",text:"åç½ãå¼·ãããï¼ï¼ï¼ä¿ºã®æ¬æãã骨é«ã«å·ä¸ã¤ä»ããããã",x_norm:.819477,y_norm:.03125,w_norm:.180523,h_norm:.22587,orientation:"vertical",rendering_data:{lines:["åç½ãå¼·ãããï¼ï¼ï¼","ä¿ºã®æ¬æãã","骨é«ã«å·ä¸ã¤ä»ããããã"],font_size:40,lines_coords:[[[1483,81],[1518,81],[1518,404],[1483,404]],[[1427,79],[1469,79],[1474,323],[1432,323]],[[1380,79],[1422,79],[1422,570],[1380,570]]]},tokens:[{id:0,surface:"åç½",lemma:"åç½",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ãããã",head:2,dep:"nsubj",children:[1],start_char:0,end_char:2,meanings:["calamity","disaster","accident"],character_readings:[{char:"å",reading:"ãã",index:0},{char:"ç½",reading:"ãã",index:1}]},{id:1,surface:"ã",lemma:"ã",pos:["å©è©","æ ¼å©è©"],reading:"ã",head:0,dep:"case",children:[],start_char:2,end_char:3,grammar_key:"particle:ã",grammar_point_id:"particle:ã:spotlight",character_readings:[{char:"ã",reading:"ã",index:0}]},{id:2,surface:"å¼·",lemma:"å¼·ã",pos:["形容è©","ä¸è¬","形容è©","èªå¹¹-ä¸è¬"],reading:"ã¤ã",head:16,dep:"advcl",children:[0,3,4,5,6],start_char:3,end_char:4,meanings:["strong","potent","competent","domineering","tough"],grammar_key:"morph:adj-i-adv",grammar_point_id:"morph:adj-i:adverbial",conjugation:{surface:"å¼·ããã",reading:"ã¤ãããã",startChar:3,endChar:7,memberIds:[2,3],hasWhitespace:!1},conjugationMeta:{clusterKind:"conjugation",rootSurface:"å¼·",grammarPointIds:["construction:ããã:excessive"],grammarTagDetails:[{label:"ããã",meaning:"too much / excessively",surface:"ããã",grammarPointId:"construction:ããã:excessive"}]},character_readings:[{char:"å¼·",reading:"ã¤ã",index:0}]},{id:3,surface:"ããã",lemma:"ããã",pos:["åè©","éèªç«å¯è½","ä¸ä¸æ®µ-ã¬è¡","çµæ¢å½¢-ä¸è¬"],reading:"ããã",head:2,dep:"advcl",children:[],start_char:4,end_char:7,grammar_key:"construction:ããã",grammar_point_id:"construction:ããã:excessive",character_readings:[{char:"ã",reading:"ã",index:0},{char:"ã",reading:"ã",index:1},{char:"ã",reading:"ã",index:2}]},{id:4,surface:"ï¼",lemma:".",pos:["è£å©è¨å·","å¥ç¹"],reading:"ï¼",head:2,dep:"punct",children:[],start_char:7,end_char:8},{id:5,surface:"ï¼",lemma:".",pos:["è£å©è¨å·","å¥ç¹"],reading:"ï¼",head:2,dep:"punct",children:[],start_char:8,end_char:9},{id:6,surface:"ï¼",lemma:".",pos:["è£å©è¨å·","å¥ç¹"],reading:"ï¼",head:2,dep:"punct",children:[],start_char:9,end_char:10},{id:7,surface:"俺",lemma:"俺",pos:["代åè©"],reading:"ãã",head:9,dep:"nmod",children:[8],start_char:10,end_char:11,meanings:["I","me"],character_readings:[{char:"俺",reading:"ãã",index:0}]},{id:8,surface:"ã®",lemma:"ã®",pos:["å©è©","æ ¼å©è©"],reading:"ã®",head:7,dep:"case",children:[],start_char:11,end_char:12,grammar_key:"particle:ã®",grammar_point_id:"particle:ã®:linking",character_readings:[{char:"ã®",reading:"ã®",index:0}]},{id:9,surface:"æ¬æ",lemma:"æ¬æ",pos:["åè©","æ®éåè©","ãµå¤å¯è½"],reading:"ãããã",head:15,dep:"nmod",children:[7,10],start_char:12,end_char:14,meanings:["slash","slashing attack"],character_readings:[{char:"æ¬",reading:"ãã",index:0},{char:"æ",reading:"ãã",index:1}]},{id:10,surface:"ãã",lemma:"ãã",pos:["å©è©","æ ¼å©è©"],reading:"ãã",head:9,dep:"case",children:[],start_char:14,end_char:16,character_readings:[{char:"ã",reading:"ã",index:0},{char:"ã",reading:"ã",index:1}]},{id:11,surface:"骨é«",lemma:"骨é«",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ãã¤ãã",head:15,dep:"obl",children:[12],start_char:16,end_char:18,meanings:["bone marrow","medulla"],character_readings:[{char:"骨",reading:"ãã¤",index:0},{char:"é«",reading:"ãã",index:1}]},{id:12,surface:"ã«",lemma:"ã«",pos:["å©è©","æ ¼å©è©"],reading:"ã«",head:11,dep:"case",children:[],start_char:18,end_char:19,grammar_key:"particle:ã«",grammar_point_id:"particle:ã«:target",character_readings:[{char:"ã«",reading:"ã«",index:0}]},{id:13,surface:"å·",lemma:"å·",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ãã",head:15,dep:"compound",children:[],start_char:19,end_char:20,meanings:["wound","injury","cut","gash","bruise","scratch","scrape","scar"],character_readings:[{char:"å·",reading:"ãã",index:0}]},{id:14,surface:"ä¸",lemma:"ä¸",pos:["åè©","æ°è©"],reading:"ã²ã¨",head:15,dep:"nummod",children:[],start_char:20,end_char:21,ent_type:"C
5ountx_Other",character_readings:[{char:"ä¸",reading:"ã²ã¨",index:0}]},{id:15,surface:"ã¤",lemma:"ã¤",pos:["æ¥å°¾è¾","åè©ç","婿°è©"],reading:"ã¤",head:16,dep:"obl",children:[9,11,13,14],start_char:21,end_char:22,ent_type:"Countx_Other",grammar_key:"counter:ã¤",grammar_point_id:"counter:ã¤:general",character_readings:[{char:"ã¤",reading:"ã¤",index:0}]},{id:16,surface:"ä»ã",lemma:"ä»ãã",pos:["åè©","éèªç«å¯è½","ä¸ä¸æ®µ-ã«è¡","æªç¶å½¢-ä¸è¬"],reading:"ã¤ã",head:16,dep:"ROOT",children:[2,15,17,18],start_char:22,end_char:24,meanings:["to attach","to join","to connect","to add","to append","to affix","to stick","to glue","to fasten","to sew on"],grammar_key:"construction:å身",grammar_point_id:"construction:å身:passive",conjugation:{surface:"ä»ããããã",reading:"ã¤ããããã",startChar:22,endChar:28,memberIds:[16,17,18],hasWhitespace:!1},conjugationMeta:{clusterKind:"conjugation",rootSurface:"ä»ã",grammarPointIds:["morph:å身:passive","aux:ãªã:contracted-nee"],grammarTagDetails:[{label:"å身ãããã¿ã",meaning:"(passive voice)",surface:"ãã",grammarPointId:"morph:å身:passive",children:[{vibe:"The Receiving End",meaning:"(passive) / can / (honorific)",surface:"ãã",displayName:"ããã",grammarPointId:"aux:ããã:passive"}]},{label:"ãã",meaning:"not / can't (rough, masculine)",surface:"ãã",grammarPointId:"aux:ãªã:contracted-nee"}]},character_readings:[{char:"ä»",reading:"ã¤",index:0},{char:"ã",reading:"ã",index:1}]},{id:17,surface:"ãã",lemma:"ããã",pos:["å©åè©","å©åè©-ã¬ã«","æªç¶å½¢-ä¸è¬"],reading:"ãã",head:16,dep:"aux",children:[],start_char:24,end_char:26,grammar_key:"aux:ããã",grammar_point_id:"aux:ããã:passive",character_readings:[{char:"ã",reading:"ã",index:0},{char:"ã",reading:"ã",index:1}]},{id:18,surface:"ãã",lemma:"ãã",pos:["å©åè©","å©åè©-ãã¤","çµæ¢å½¢-ä¸è¬"],reading:"ãã",head:16,dep:"mark",children:[],grammar_key:"aux:ãªã",grammar_point_id:"aux:ãªã:contracted-nee",start_char:26,end_char:28,character_readings:[{char:"ã",reading:"ã",index:0},{char:"ã",reading:"ã",index:1}]}]},{id:"demo-box-4",text:"èºè
ãã¨ç¼ãå°½ããã¤ããã ã",x_norm:.378266,y_norm:.476266,w_norm:.4038,h_norm:.523734,orientation:"vertical",rendering_data:{lines:["èºè
ãã¨ç¼ãå°½ããã¤ããã ã"],font_size:42,lines_coords:[[[637,1204],[679,1204],[679,1641],[637,1641]]]},tokens:[{id:0,surface:"èºè
",lemma:"èºè
",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ã¯ããµ",head:1,dep:"compound",children:[],start_char:0,end_char:2,meanings:["lungs","bottom of one's heart","vital point"],character_readings:[{char:"èº",reading:"ã¯ã",index:0},{char:"è
",reading:"ãµ",index:1}]},{id:1,surface:"ãã¨",lemma:"ãã¨",pos:["æ¥å°¾è¾","åè©ç","å¯è©å¯è½"],reading:"ãã¨",head:4,dep:"nmod",children:[0],start_char:2,end_char:4,meanings:["together with","including"],character_readings:[{char:"ã",reading:"ã",index:0},{char:"ã¨",reading:"ã¨",index:1}]},{id:2,surface:"ç¼ã",lemma:"ç¼ã",pos:["åè©","ä¸è¬","äºæ®µ-ã«è¡","é£ç¨å½¢-ä¸è¬"],reading:"ãã",head:4,dep:"acl",children:[3],start_char:4,end_char:6,meanings:["to burn","to roast","to broil","to grill","to bake","to toast","to barbecue"],grammar_key:"morph:stem-formation",grammar_point_id:"morph:stem:godan-ã«è¡",conjugation:{surface:"ç¼ãå°½ãã",reading:"ããã¤ãã",startChar:4,endChar:9,memberIds:[2,3],hasWhitespace:!1},conjugationMeta:{clusterKind:"conjugation",rootSurface:"ç¼",grammarPointIds:["morph:stem:godan-ã«è¡","construction:å°½ãã:exhaust"],grammarTagDetails:[{label:"V + å°½ãã",meaning:"exhaust / use up completely",surface:"ãå°½ãã",grammarPointId:"construction:å°½ãã:exhaust"}]},character_readings:[{char:"ç¼",reading:"ã",index:0},{char:"ã",reading:"ã",index:1}]},{id:3,surface:"å°½ãã",lemma:"å°½ãã",pos:["åè©","éèªç«å¯è½","äºæ®µ-ãµè¡","é£ä½å½¢-ä¸è¬"],reading:"ã¤ãã",head:2,dep:"aux",children:[],start_char:6,end_char:9,meanings:["to do to exhaustion","to do completely","to do fully"],grammar_key:"c
5onstruction:å°½ãã",grammar_point_id:"construction:å°½ãã:exhaust",character_readings:[{char:"å°½",reading:"ã¤",index:0},{char:"ã",reading:"ã",index:1},{char:"ã",reading:"ã",index:2}]},{id:4,surface:"ã¤ãã",lemma:"ã¤ãã",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ã¤ãã",head:4,dep:"ROOT",children:[1,2,5,6],start_char:9,end_char:12,meanings:["intention","plan"],grammar_key:"construction:ã¤ããã ",grammar_point_id:"construction:ã¤ããã :intention",conjugation:{surface:"ã¤ãã",reading:"ã¤ãã",startChar:9,endChar:12,memberIds:[4],hasWhitespace:!1},conjugationMeta:{clusterKind:"set-phrase",rootSurface:"ã¤ãã",grammarPointIds:["construction:ã¤ããã :intention"],grammarTagDetails:[{label:"ã¤ããã ",meaning:"intend to / plan to",surface:"ã¤ãã",grammarPointId:"construction:ã¤ããã :intention"}]},character_readings:[{char:"ã¤",reading:"ã¤",index:0},{char:"ã",reading:"ã",index:1},{char:"ã",reading:"ã",index:2}]},{id:5,surface:"ã ",lemma:"ã ",pos:["å©åè©","å©åè©-ã","çµæ¢å½¢-ä¸è¬"],reading:"ã ",head:4,dep:"cop",children:[],start_char:12,end_char:13,grammar_key:"aux:ã ",grammar_point_id:"aux:ã :plain-copula",conjugation:{surface:"ã ",reading:"ã ",startChar:12,endChar:13,memberIds:[5],hasWhitespace:!1},conjugationMeta:{clusterKind:"set-phrase",rootSurface:"ã ",grammarPointIds:["aux:ã :plain-copula"],grammarTagDetails:[{label:"ã ",meaning:"[it] is (plain)",surface:"ã ",grammarPointId:"aux:ã :plain-copula"}]},character_readings:[{char:"ã ",reading:"ã ",index:0}]},{id:6,surface:"ã",lemma:"ã",pos:["è£å©è¨å·","å¥ç¹"],reading:"ã",head:4,dep:"punct",children:[],start_char:13,end_char:14}]},{id:"demo-box-6",text:"幻影æ³ãåãå",x_norm:.910333,y_norm:.684335,w_norm:.0896675,h_norm:.315665,orientation:"vertical",rendering_data:{lines:["幻影æ³ãåãå"],font_size:62,lines_coords:[[[1533,1730],[1595,1730],[1600,2140],[1538,2140]]]},tokens:[{id:0,surface:"幻影",lemma:"幻影",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ãããã",head:1,dep:"compound",children:[],start_char:0,end_char:2,ent_type:"Law",meanings:["phantom","vision","illusion"],character_readings:[{char:"å¹»",reading:"ãã",index:0},{char:"å½±",reading:"ãã",index:1}]},{id:1,surface:"æ³",lemma:"æ³",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ã»ã",head:5,dep:"nmod",children:[0,2],start_char:2,end_char:3,ent_type:"Law",meanings:["dharma","law"],character_readings:[{char:"æ³",reading:"ã»ã",index:0}]},{id:2,surface:"ã",lemma:"ã",pos:["è£å©è¨å·","èªç¹"],reading:"ã",head:1,dep:"punct",children:[],start_char:3,end_char:4,ent_type:"Law"},{id:3,surface:"å",lemma:"å",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ãã",head:5,dep:"compound",children:[],start_char:4,end_char:5,ent_type:"Law",character_readings:[{char:"å",reading:"ãã",index:0}]},{id:4,surface:"ã",lemma:"ã",pos:["å©è©","æ ¼å©è©"],reading:"ã®",head:5,dep:"compound",children:[],start_char:5,end_char:6,ent_type:"Law",character_readings:[{char:"ã",reading:"ã®",index:0}]},{id:5,surface:"å",lemma:"å",pos:["åè©","æ®éåè©","ä¸è¬"],reading:"ãã",head:5,dep:"ROOT",children:[1,3,4],start_char:6,end_char:7,ent_type:"Law",meanings:["mold","mould","model","pattern","template","impression"],character_readings:[{char:"å",reading:"ãã",index:0}]}]}]},hb={id:"demo-onboarding",title:"Demo Manga",total_pages:1,current_page:0,processing_status:"completed",created_at:new Date().toISOString()},zd=[{pageNumber:1,imageUrl:Gi.imageUrl,width:Gi.width,height:Gi.height}],pb=Gi.textBoxes.map(t=>({id:t.id,text:t.text,x_norm:t.x_norm,y_norm:t.y_norm,w_norm:t.w_norm,h_norm:t.h_norm,orientation:t.orientation,rendering_data:t.rendering_data,processedData:{tokens:t.tokens}}));function Po({num:t,label:a,jp:s}){return e.jsxs("div",{className:"theater-rail-eyebrow",children:[e.jsx("span",{className:"num jp",children:t}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:a}),e.jsx("span",{className:"jp",children:s})]})}function fb(t){const{fontSize:a,fontRange:s,onFontSizeChange:n,lineSpacing:r,lineSpacingRange:i,onLineSpacingChange:l}=t;return e.jsxs("div",{className:"theater-panel p-5 space-y-4",children:[e.jsx(Po,{num:"ä¸",label:"Typography",jp:"åä½"}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"text-sm font-medium block mb-2",style:{color:"var(--theater-text)"},children:["Font Size:"," ",e.jsxs("span",{style:{color:"hsl(var(--module-accent))"},children:[a,"px"]})]}),e.jsx("input",{type:"range",min:s.min,max:s.max,step:s.step??1,value:a,onChange:c=>n(parseInt(c.target.value)),className:"w-full accent-[hsl(var(--module-accent))]"})]}),r!==void 0&&i&&l&&e.jsxs("div",{children:[e.jsxs("label",{className:"text-sm font-medium block mb-2",style:{color:"var(--theater-text)"},children:["Line Spacing:"," ",e.jsx("span",{style:{color:"hsl(var(--module-accent))"},children:r.toFixed(1)})]}),e.jsx("input",{type:"range",min:i.min,max:i.max,step:i.step??.1,value:r,onChange:c=>l(parseFloat(c.target.value)),className:"w-full accent-[hsl(var(--module-accent))]"})]})]})]})}function gb(t){const{showFurigana:a,onShowFuriganaChange:s,furiganaMode:n,onFuriganaModeChange:r,showSpacing:i,onShowSpacingChange:l,children:c,title:d="Display"}=t;return e.jsxs("div",{className:"theater-panel p-5 space-y-4",children:[e.jsx(Po,{num:"äº",label:d,jp:"表示"}),e.jsxs("div",{className:"space-y-3",children:[a!==void 0&&s&&e.jsx(ei,{label:"Show Furigana",checked:a,onCheckedChange:s}),a&&n&&r&&e.jsxs("div",{className:"theater-pencil-rule-left pl-3 ml-2 space-y-2",children:[e.jsx("div",{className:"text-[10.5px] uppercase tracking-[0.28em]",style:{color:"var(--theater-text-soft)",fontFamily:"'JetBrains Mono', monospace"},children:"Furigana Layout"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:[{key:"token",label:"Whole word"},{key:"perKanji",label:"Per kanji"}].map(({key:m,label:u})=>{const h=n===m;return e.jsx("button",{type:"button",onClick:()=>r(m),className:`theater-btn ${h?"theater-btn--primary":"theater-btn--secondary"}`,"aria-pressed":h,children:u},m)})})]}),i!==void 0&&l&&e.jsx(ei,{label:"Word Spacing",checked:i,onCheckedChange:l}),c]})]})}function ih(t){const{isDark:a,onToggleDarkMode:s}=t,n=[{key:"light",label:"Light",icon:"sun",jp:"æ¼"},{key:"dark",label:"Dark",icon:"moon",jp:"å¤"}];return e.jsxs("div",{className:"theater-panel p-5 space-y-4",children:[e.jsx(Po,{num:"ä¸",label:"Theme",jp:"表示è²"}),e.jsx("div",{className:"grid grid-cols-2 gap-3",children:n.map(r=>{const i=r.key==="dark"?a:!a;return e.jsxs("button",{type:"button",onClick:i?void 0:s,className:`theater-btn ${i?"theater-btn--primary":"theater-btn--secondary"} flex-col gap-1.5`,style:{minHeight:64,padding:"8px 10px"},"aria-pressed":i,children:[e.jsx(Kt,{name:r.icon,size:24}),e.jsx("span",{className:"text-xs font-semibold",children:r.label})]},r.key)})})]})}function yb(t){const{shortcuts:a}=t;return e.jsxs("div",{className:"theater-panel p-5 space-y-2 text-xs",children:[e.jsx(Po,{num:"å",label:"Keyboard Shortcuts",jp:"éµ"}),e.jsx("div",{className:"space-y-1.5",children:a.map(s=>e.jsxs("p",{style:{color:"var(--theater-text)"},children:[e.jsx(sf,{className:"reader-pencil-outline mr-2 rounded-[var(--wc-radius-ink)] bg-[var(--theater-surface-hover)] border-transparent text-[var(--theater-text-soft)]",children:s.combo}),e.jsx("span",{style:{color:"var(--theater-text-soft)"},children:s.description})]},s.combo))})]})}function ei(t){const{label:a,description:s,checked:n,onCheckedChange:r}=t,i=`toggle-${a.toLowerCase().replace(/\s+/g,"-")}`;return e.jsxs("div",{className:"reader-pencil-outline flex items-center justify-between px-3 py-2.5",style:{background:"var(--theater-surface-hover)",borderRadius:"var(--wc-radius-ink)",border:0},children:[e.jsx("div",{className:"flex-1",children:e.jsxs(Zp,{htmlFor:i,className:"text-sm font-medium cursor-pointer",style:{color:"var(--theater-text)"},children:[a,s&&e.jsx("span",{className:"block text-xs font-normal mt-0.5",style:{color:"var(--theater-text-soft)"},children:s})]})}),e.jsx($n,{id:i,checked:n,onCheckedChange:r,className:"ml-3 flex-shrink-0 data-[state=checked]:bg-[hsl(var(--module-accent))]"})]})}async function oh(){try{const{data:{session:t}}=await Ps.auth.getSession();return t?.access_token??null}catch{return null}}async function lh(t,a,s={}){if(!(!t||a.currentPage===void 0&&a.position===void 0))try{const n=await oh();if(!n)return;await fetch(`${ue()}/api/reading/materials/${t}/position`,{method:"PATCH",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/json"},body:JSON.stringify(a),...s.keepalive?{keepalive:!0}:{}})}catch{}}async function bb(t){if(!t)return null;try{const a=await oh();if(!a)return null;const s=await fetch(`${ue()}/api/reading/materials/${t}`,{headers:{Authorization:`Bearer ${a}`}});if(!s.ok)return null;const n=await s.json();return{currentPage:typeof n?.current_page=="number"?n.current_page:typeof n?.currentPage=="number"?n.currentPage:null,position:n?.readingPosition??n?.reading_position??null}}catch{return null}}function xb(t=1500){let a=null,s=null;const n=()=>
5{if(a=null,!s)return;const{materialId:r,payload:i}=s;s=null,lh(r,i)};return(r,i)=>{s={materialId:r,payload:{...s?.payload??{},...i}},a&&clearTimeout(a),a=setTimeout(n,t)}}async function wb(){const{data:{session:t}}=await Ps.auth.getSession();return t?.access_token??null}const Ac={api:nf,memoryAidsApi:of({baseUrl:Xu,getAccessToken:wb}),canManageMemoryAidFavorites:!0,uploadImage:rf};function Fd(t){window.open(t,"_blank","noopener,noreferrer")}const jr={onOpenWord:(t,a)=>Fd(`/dictionary/vocabulary/${encodeURIComponent(a)}`),onOpenKanji:t=>Fd(`/dictionary/kanji/${encodeURIComponent(t)}`)};function vb(t){return{vocabId:t.id,surface:t.surface,reading:t.reading,readingSegments:null,pos:t.pos,freqRank:null,jlptLevel:null,writingStyle:"both",usuallyKana:!1,glosses:t.glosses,otherSenses:[],examples:[],kanji:[],alternateWritings:[],composedOf:[],compounds:[],compoundsTotal:0,systemMnemonics:{meaning:null,sound:null},mnemonicImageUrl:null}}const ch=[{id:"demo-rich-sugoi",surface:"ããã",reading:"ããã",pos:"adjective",glosses:["amazing","wonderful","terrific"],aliases:["ããã"]},{id:"demo-rich-app",surface:"ã¢ããª",reading:"ã¢ããª",pos:"noun",glosses:["application","app"]},{id:"demo-rich-aru",surface:"ãã",reading:"ãã",pos:"verb",glosses:["to exist","to have"],aliases:["ãã"]},{id:"demo-rich-nani",surface:"ä½",reading:"ãªã«",pos:"pronoun",glosses:["what"]},{id:"demo-rich-yomeru",surface:"èªãã",reading:"ããã",pos:"verb",glosses:["can read","to be readable"]},{id:"demo-rich-tsukeru",surface:"ä»ãã",reading:"ã¤ãã",pos:"verb",glosses:["to attach","to apply"],aliases:["ä»ã"]},{id:"demo-rich-yakusai",surface:"åç½",reading:"ãããã",pos:"noun",glosses:["calamity","disaster"]},{id:"demo-rich-zangeki",surface:"æ¬æ",reading:"ãããã",pos:"noun",glosses:["slash","slashing attack"]}],jb=Object.freeze(Object.fromEntries(ch.map(t=>[t.id,vb(t)]))),mo=new Map;for(const t of ch){mo.set(t.surface,t.id);for(const a of t.aliases??[])mo.set(a,t.id)}const kb={async fetchRich(t){return jb[t]??null}};function _b(t){if(t.lexemeVocabId||t.vocabId)return t;const a=mo.get(t.lemmaSurface)??mo.get(t.surface);return a?{...t,vocabId:a,lexemeVocabId:a}:t}const dh={loading:"Preparing Japanese voicesâ¦",speaking:"Reading speech bubbleâ¦",stopped:"Ready to listen",error:"Audio could not play"};function Sb({status:t,error:a}){return e.jsx("p",{className:"text-xs",style:{color:"var(--theater-text-muted)"},role:"status","aria-live":"polite",children:a?.message||dh[t]})}function Nb({active:t,status:a,onToggle:s}){const n=a==="loading";return e.jsx("button",{type:"button",className:`bubble-listen-toolbar-button theater-chrome-icon-btn min-h-11 min-w-11 ${t?"is-active":""}`,"aria-label":t?"Exit speech bubble listening mode":"Listen to a speech bubble","aria-pressed":t,"aria-busy":n,disabled:n&&!t,onClick:s,children:e.jsx(Kt,{name:"speaker",size:24})})}function Cb({selection:t,status:a,error:s,onListen:n,onStop:r,onEditGrouping:i,onRetryLocal:l,canRetryLocal:c=!1}){const d=a==="speaking",m=a==="loading";return e.jsxs("section",{className:"bubble-listening theater-panel p-4","aria-label":"Speech bubble audio",children:[e.jsxs("div",{className:"theater-rail-eyebrow",children:[e.jsx("span",{className:"num jp",children:"è´"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Listen"}),e.jsx("span",{className:"jp",children:"å¹ãåºã"})]}),e.jsx("p",{className:"jp mt-3 text-base",style:{color:"var(--theater-text)"},children:t.text}),t.requiresConfirmation&&e.jsx("p",{className:"mt-2 text-sm",style:{color:"var(--theater-text-soft)"},children:"Check which text blocks belong to this speech bubble before listening."}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsxs("button",{type:"button",className:"theater-btn theater-btn--primary min-h-11",onClick:t.requiresConfirmation?i:d?r:n,disabled:m||!t.text.trim(),"aria-busy":m,children:[e.jsx(Kt,{name:d&&!t.requiresConfirmation?"stop":t.requiresConfirmation?"edit":"speaker",size:24}),e.jsx("span",{children:t.requiresConfirmation?"Confirm bubble":d?"Stop":"Listen to bubble"})]}),e.jsxs("button",{type:"button",className:"theater-btn theater-btn--secondary min-h-11",onClick:i,children:[e.jsx(Kt,{name:"edit",size:24}),e.jsx("span",{children:"Edit grouping"})]}),a==="error"&&c&&l&&e.jsx("button",{type:"button",className:"theater-btn theater-btn--secondary min-h-11",onClick:l,children:"Try device voice"})]}),e.jsx("div",{className:"mt-3",children:e.jsx(Sb,{status:a,error:s})})]})}function Eb({boxes:t,orderedBoxIds:a,onChange:s,onSaveAndListen:n,onCancel:r,status:i="stopped"}){const l=new Map(t.map(p=>[p.id,p])),c=a.flatMap(p=>l.has(p)?[l.get(p)]:[]),d=c.map(p=>p.text).join(""),m=i==="loading"||i==="speaking",u=p=>{s(a.includes(p)?a.filter(g=>g!==p):[...a,p])},h=(p,g)=>{const f=p+g;if(f<0||f>=a.length)return;const b=[...a];[b[p],b[f]]=[b[f],b[p]],s(b)};return e.jsxs("section",{className:"bubble-listening theater-panel p-5","aria-labelledby":"bubble-grouping-title",children:[e.jsxs("div",{className:"theater-rail-eyebrow",children:[e.jsx("span",{className:"num jp",children:"æ´"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Speech bubble"}),e.jsx("span",{className:"jp",children:"èªãé çª"})]}),e.jsx("h2",{id:"bubble-grouping-title",className:"mt-3 text-xl",style:{color:"var(--theater-text)",fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:"Choose the text blocks"}),e.jsx("p",{className:"mt-1 text-sm",style:{color:"var(--theater-text-soft)"}
5,children:"Tap every block in the speech bubble, then arrange the reading order."}),e.jsx("div",{className:"mt-4 grid gap-2",role:"group","aria-label":"Available text blocks",children:t.map(p=>{const g=a.indexOf(p.id);return e.jsxs("button",{type:"button",className:"theater-btn theater-btn--secondary min-h-11 justify-start text-left","aria-pressed":g>=0,onClick:()=>u(p.id),children:[e.jsx("span",{className:"w-6 font-mono","aria-hidden":"true",children:g>=0?g+1:"â"}),e.jsx("span",{className:"jp whitespace-normal",children:p.text})]},p.id)})}),c.length>0&&e.jsx("ol",{className:"mt-4 grid gap-2","aria-label":"Reading order",children:c.map((p,g)=>e.jsxs("li",{className:"flex items-center gap-2",style:{color:"var(--theater-text)"},children:[e.jsx("span",{className:"w-6 text-center font-mono",children:g+1}),e.jsx("span",{className:"jp min-w-0 flex-1",children:p.text}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn theater-chrome-icon-btn--sm min-h-11 min-w-11","aria-label":`Move ${p.text} earlier`,disabled:g===0,onClick:()=>h(g,-1),children:e.jsx(Kt,{name:"chevron-up",size:24})}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn theater-chrome-icon-btn--sm min-h-11 min-w-11","aria-label":`Move ${p.text} later`,disabled:g===c.length-1,onClick:()=>h(g,1),children:e.jsx(Kt,{name:"chevron-down",size:24})})]},p.id))}),e.jsxs("div",{className:"mt-4 p-3",style:{background:"var(--theater-surface-hover)",borderRadius:"var(--wc-radius-ink)"},children:[e.jsx("p",{className:"font-mono text-xs uppercase tracking-wider",style:{color:"var(--theater-text-muted)"},children:"Text preview"}),e.jsx("p",{className:"jp mt-1",style:{color:"var(--theater-text)"},"aria-live":"polite",children:d||"No text blocks selected"})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsxs("button",{type:"button",className:"theater-btn theater-btn--primary min-h-11",disabled:!d||m,"aria-busy":m,onClick:n,children:[e.jsx(Kt,{name:"speaker",size:24}),e.jsx("span",{children:m?dh[i]:"Save and listen"})]}),e.jsx("button",{type:"button",className:"theater-btn theater-btn--secondary min-h-11",disabled:m,onClick:r,children:"Cancel"})]})]})}function Dd({rate:t,voices:a,selectedVoiceId:s,onRateChange:n,onVoiceChange:r}){return e.jsxs("section",{className:"bubble-listening theater-panel p-4","aria-labelledby":"manga-listening-settings-title",children:[e.jsxs("div",{className:"theater-rail-eyebrow",children:[e.jsx("span",{className:"num jp",children:"声"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Bubble audio"}),e.jsx("span",{className:"jp",children:"é³å£°"})]}),e.jsx("h3",{id:"manga-listening-settings-title",className:"mt-3 text-lg",style:{color:"var(--theater-text)",fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:"Japanese voice"}),e.jsxs("label",{className:"mt-3 grid gap-1 text-sm",style:{color:"var(--theater-text-soft)"},children:["Voice",e.jsxs("select",{className:"bubble-listening-select reader-pencil-outline min-h-11 px-3",style:{background:"var(--theater-surface)",color:"var(--theater-text)",border:0,borderRadius:"var(--wc-radius-ink)"},value:s,onChange:i=>r(i.target.value),children:[e.jsx("option",{value:"auto",children:"Automatic"}),a.map(i=>e.jsxs("option",{value:i.id,children:[i.name,i.local?" · device":""]},i.id))]})]}),e.jsxs("div",{className:"mt-4 grid gap-2 text-sm",style:{color:"var(--theater-text-soft)"},children:[e.jsxs("span",{id:"manga-bubble-speech-rate-label",children:["Speed ",e.jsxs("output",{className:"font-mono",htmlFor:"manga-bubble-speech-rate",children:[t.toFixed(1),"Ã"]})]}),e.jsx("input",{id:"manga-bubble-speech-rate","aria-labelledby":"manga-bubble-speech-rate-label",type:"range",min:"0.5",max:"1.5",step:"0.1",value:t,onChange:i=>n(Number(i.target.value))})]})]})}const uh="shizen-bubble-player-layout-v1";function Tb(){try{const t=JSON.parse(localStorage.getItem(uh)||"{}");return{position:Number.isFinite(t.position?.x)&&Number.isFinite(t.position?.y)?t.position:null,expanded:t.expanded===!0}}catch{return{position:null,expanded:!1}}}function Mb({theme:t,speaking:a,text:s,onPlay:n,onStop:r,onClose:i,children:l}
5){const[c,d]=o.useState(Tb),m=o.useRef(null),u=o.useRef(null),h=g=>{const f=m.current?.getBoundingClientRect(),b=window.visualViewport,y=b?.offsetLeft??0,x=b?.offsetTop??0;return{x:Math.max(y+8,Math.min(g.x,y+(b?.width??innerWidth)-(f?.width??280)-8)),y:Math.max(x+8,Math.min(g.y,x+(b?.height??innerHeight)-(f?.height??56)-8))}},p=g=>d(f=>({...f,position:h(g)}));return o.useLayoutEffect(()=>{const g=()=>d(b=>{const y=h(b.position??{x:innerWidth-310,y:innerHeight-155});return b.position?.x===y.x&&b.position?.y===y.y?b:{...b,position:y}});g();const f=new ResizeObserver(g);return m.current&&f.observe(m.current),window.addEventListener("resize",g),window.visualViewport?.addEventListener("resize",g),window.visualViewport?.addEventListener("scroll",g),()=>{f.disconnect(),window.removeEventListener("resize",g),window.visualViewport?.removeEventListener("resize",g),window.visualViewport?.removeEventListener("scroll",g)}},[]),o.useLayoutEffect(()=>{try{localStorage.setItem(uh,JSON.stringify(c))}catch{}},[c]),e.jsxs("div",{ref:m,className:`wc-root im-logged reader-theater ${t} bubble-listening-panel bubble-player ${c.expanded?"is-expanded":"is-compact"}`,style:{position:"fixed",minHeight:0,zIndex:160,left:c.position?.x??8,top:c.position?.y??8,right:"auto",bottom:"auto"},"data-reader-ui":!0,onKeyDown:g=>{g.stopPropagation(),g.key==="Escape"&&(g.preventDefault(),i())},children:[e.jsxs("div",{className:"bubble-player-bar",children:[e.jsxs("button",{type:"button",className:"bubble-player-drag","aria-label":"Move listening player",title:"Drag to move · arrow keys to reposition",onPointerDown:g=>{if(!g.isPrimary||g.button!==0)return;g.preventDefault(),g.stopPropagation();const f=m.current.getBoundingClientRect();u.current={id:g.pointerId,x:g.clientX,y:g.clientY,origin:{x:f.x,y:f.y}},g.currentTarget.setPointerCapture(g.pointerId)},onPointerMove:g=>{const f=u.current;f?.id===g.pointerId&&p({x:f.origin.x+g.clientX-f.x,y:f.origin.y+g.clientY-f.y})},onPointerUp:()=>{u.current=null},onPointerCancel:()=>{u.current=null},onKeyDown:g=>{const b={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[g.key];if(!b)return;g.preventDefault(),g.stopPropagation();const y=m.current.getBoundingClientRect(),x=g.shiftKey?40:10;p({x:y.x+b[0]*x,y:y.y+b[1]*x})},children:[e.jsx(Kt,{name:"grip",size:24}),e.jsx("span",{children:"Listen"})]}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn","aria-label":a?"Stop bubble audio":"Play bubble audio",onClick:a?r:n,children:e.jsx(Kt,{name:a?"stop":"play",size:24})}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn","aria-label":c.expanded?"Collapse listening player":"Expand listening options","aria-expanded":c.expanded,onClick:()=>d(g=>({...g,expanded:!g.expanded})),children:e.jsx(Kt,{name:c.expanded?"chevron-down":"chevron-up",size:24})}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn","aria-label":"Close bubble listening panel",onClick:i,children:e.jsx(Kt,{name:"close",size:24})})]}),!c.expanded&&e.jsx("p",{className:"bubble-player-summary",title:s,children:s}),c.expanded&&e.jsx("div",{className:"bubble-player-options",children:l})]})}const mh="shizen-manga-audio-settings-v1",Ld={preferredVoiceId:"auto",speechRate:1},hh=t=>Math.max(.5,Math.min(1.5,t));function Pb(){if(typeof localStorage>"u")return Ld;try{const t=JSON.parse(localStorage.getItem(mh)??"{}");return{preferredVoiceId:t.preferredVoiceId||"auto",speechRate:hh(Number(t.speechRate)||1)}}catch{return Ld}}function Ab(){const[t,a]=o.useState(Pb),s=o.useCallback(n=>{a(r=>{const i=typeof n=="function"?n(r):n,l={preferredVoiceId:i.preferredVoiceId||"auto",speechRate:hh(i.speechRate)};try{typeof localStorage<"u"&&localStorage.setItem(mh,JSON.stringify(l))}catch{}return l})},[]);return{settings:t,setSettings:s}}const ph="coordinates-v1",Ib="coordinates-connected-v3.1",Bs=1e-9;function zn(t){return[t.x,t.y,t.width,t.height].every(Number.isFinite)&&t.x>=0&&t.y>=0&&t.width>0&&t.height>0&&t.x+t.width<=1+Bs&&t.y+t.height<=1+Bs}function Ic(t){if(t.length===0)return{x:0,y:0,width:0,height:0};const a=Math.min(...t.map(i=>i.x)),s=Math.min(...t.map(i=>i.y)),n=Math.max(...t.map(i=>i.x+i.width)),r=Math.max(...t.map(i=>i.y+i.height));return{x:a,y:s,width:n-a,height:r-s}}function qs(t,a,s,n){return Math.max(0,Math.min(t+a,s+n)-Math.max(t,s))/Math.max(Bs,Math.min(a,n))}function Us(t,a,s,n){return Math.max(0,Math.max(t,s)-Math.min(t+a,s+n))}
5function Rb(t,a){if(t.orientation!==a.orientation||!zn(t.rect)||!zn(a.rect))return!1;const s=t.rect,n=a.rect,r=t.orientation==="vertical",i=r?Us(s.x,s.width,n.x,n.width):Us(s.y,s.height,n.y,n.height),l=r?qs(s.y,s.height,n.y,n.height):qs(s.x,s.width,n.x,n.width),c=r?Math.max(s.width,n.width):Math.max(s.height,n.height);if(l>=.25&&i<=Math.min(.085,Math.max(.018,c*.95)))return!0;const d=r?Us(s.y,s.height,n.y,n.height):Us(s.x,s.width,n.x,n.width),m=r?qs(s.x,s.width,n.x,n.width):qs(s.y,s.height,n.y,n.height),u=r?Math.max(s.height,n.height):Math.max(s.width,n.width);return m>=.6&&d<=Math.min(.035,Math.max(.012,u*.35))}function $b(t){if(t.length===0)return null;const a=[...t].sort((s,n)=>s-n);return a[Math.floor(a.length/2)]}function fh(t){if(t.length<3||t.some(n=>!Number.isFinite(n.x)||!Number.isFinite(n.y)||n.x<0||n.x>1||n.y<0||n.y>1))return!1;const a=Math.max(...t.map(n=>n.x))-Math.min(...t.map(n=>n.x)),s=Math.max(...t.map(n=>n.y))-Math.min(...t.map(n=>n.y));return a>Bs&&s>Bs}function Od(t){const a=(t.linePolygons??[]).map(s=>{if(!fh(s))return 0;const n=Math.max(...s.map(i=>i.x))-Math.min(...s.map(i=>i.x)),r=Math.max(...s.map(i=>i.y))-Math.min(...s.map(i=>i.y));return t.orientation==="vertical"?n:r}).filter(s=>s>Bs);return $b(a)}function gh(t){if(!fh(t))return null;const a=Math.min(...t.map(i=>i.x)),s=Math.min(...t.map(i=>i.y)),n=Math.max(...t.map(i=>i.x)),r=Math.max(...t.map(i=>i.y));return{x:a,y:s,width:n-a,height:r-s}}function zb(t){const a=(t.linePolygons??[]).map(gh).filter(s=>s!==null);return a.length?Ic(a):null}function hr(t,a){if(t.linePolygons?.length!==1)return!1;const s=gh(t.linePolygons[0]),n=zb(a);return!!(s&&n&&s.x<=n.x+Bs&&s.y<=n.y+Bs&&s.x+s.width>=n.x+n.width-Bs&&s.y+s.height>=n.y+n.height-Bs)}function Fb(t,a){return hr(t,a)||hr(a,t)}function Db(t,a){if(t.orientation!==a.orientation||!zn(t.rect)||!zn(a.rect))return!1;const s=Od(t),n=Od(a);if(!s||!n||Math.max(s,n)/Math.min(s,n)>1.4)return!1;const r=Math.max(s,n),i=!!(t.linePolygons?.length&&t.linePolygons.length===a.linePolygons?.length),l=t.orientation==="vertical",c=l?Us(t.rect.x,t.rect.width,a.rect.x,a.rect.width):Us(t.rect.y,t.rect.height,a.rect.y,a.rect.height),d=l?Us(t.rect.y,t.rect.height,a.rect.y,a.rect.height):Us(t.rect.x,t.rect.width,a.rect.x,a.rect.width),m=l?qs(t.rect.y,t.rect.height,a.rect.y,a.rect.height):qs(t.rect.x,t.rect.width,a.rect.x,a.rect.width),u=l?qs(t.rect.x,t.rect.width,a.rect.x,a.rect.width):qs(t.rect.y,t.rect.height,a.rect.y,a.rect.height);return c<=r&&m>=.25||i&&c<=r*2&&m>=.25||d<=r*.5&&u>=.6}function yh(t,a){if(t.orientation!==a.orientation)return 0;const s=t.rect,n=a.rect;if(!zn(s)||!zn(n))return 0;const r=t.orientation==="vertical",i=r?Us(s.x,s.width,n.x,n.width):Us(s.y,s.height,n.y,n.height),l=r?qs(s.y,s.height,n.y,n.height):qs(s.x,s.width,n.x,n.width),c=r?Math.max(s.width,n.width):Math.max(s.height,n.height),d=Math.min(.032,c*.9),m=l>=.58&&i<=d?.55+.3*l+.15*(1-i/Math.max(Bs,d)):0,u=r?Us(s.y,s.height,n.y,n.height):Us(s.x,s.width,n.x,n.width),h=r?qs(s.x,s.width,n.x,n.width):qs(s.y,s.height,n.y,n.height),p=Math.min(.016,(r?Math.max(s.height,n.height):Math.max(s.width,n.width))*.25),g=h>=.68&&u<=p?.55+.3*h+.15*(1-u/Math.max(Bs,p)):0;return Math.min(1,Math.max(m,g))}function bh(t,a){if(t.length<2)return[...t];const s=l=>a==="vertical"?l.rect.x+l.rect.width/2:l.rect.y+l.rect.height/2,n=(l,c)=>l.rect.x-c.rect.x||l.rect.y-c.rect.y||l.rect.width-c.rect.width||l.rect.height-c.rect.height||l.text.localeCompare(c.text),r=[...t].sort((l,c)=>(a==="vertical"?s(c)-s(l):s(l)-s(c))||n(l,c)),i=[];for(const l of r){const c=i[i.length-1];!c||Math.abs(s(l)-s(c[0]))>.012?i.push([l]):c.push(l)}for(const l of i)l.sort((c,d)=>hr(c,d)&&!hr(d,c)?1:hr(d,c)&&!hr(c,d)?-1:a==="vertical"?c.rect.y-d.rect.y||s(d)-s(c)||n(c,d):c.rect.x-d.rect.x||s(c)-s(d)||n(c,d));return i.flat()}function Lb(t,a){return bh(t,a).map(s=>s.text.replace(/[\r\n]+/g,"").trim()).filter(Boolean).join("")}const Ob=.78,Bb=.08;function qb(t){const a=new Map;for(const s of t){const n=t.filter(r=>r.id!==s.id).map(r=>({id:r.id,affinity:yh(s,r)})).filter(r=>r.affinity>=Ob).sort((r,i)=>i.affinity-r.affinity);n[0]&&a.set(s.id,{...n[0],ambiguous:!!(n[1]&&n[0].affinity-n[1].affinity<Bb)})}return a}function Ub(t,a,s,n,r){const i=a[0]?.orientation??"vertical",l=bh(a,i),c=l.length===1?.7:Math.min(...l.flatMap((d,m)=>l.slice(m+1).map(u=>yh(d,u))));return{pageKey:t,region:{kind:"box-union",boxes:l.map(d=>d.rect),bounds:Ic(l.map(d=>d.rect))},orderedBoxIds:l.map(d=>d.id),text:Lb(l,i),origin:"automatic",confidence:Number.isFinite(c)?c:.7,requiresConfirmation:s,reason:n?"connected-neighbor":s?"ambiguous-neighbor":a.length===1?"single-box":"mutual-neighbor",groupingVersion:r}}function Vb(t,a,s={}){const n=new Map;for(const y of a)y.id&&n.set(y.id,(n.get(y.id)??0)+1);const r=a.filter(y=>y.id&&n.get(y.id)===1&&zn(y.rect)),i=[...new Set(a.filter(y=>!y.id||n.get(y.id)!==1||!zn(y.rect)).map(y=>y.id))],c=s.mergeMutualNeighbors||s.mergeConnectedNeighbors?qb(r):new Map,d=new Map,m=new Set,u=new Set,h=new Set,p=(y,x)=>y<x?`${y}\0${x}`:`${x}\0${y}`;for(const y of r)d.set(y.id,new Set);for(const y of r){const x=c.get(y.id);if(!x)continue;if(x.ambiguous){m.add(y.id);continue}const v=c.get(x.id);v?.id===y.id&&!v.ambiguous&&(d.get(y.id)?.add(x.id),d.get(x.id)?.add(y.id))}if(s.mergeConnectedNeighbors){const y=new Set;for(const v of r)for(const w of d.get(v.id)??[]){const j=r.find(T=>T.id===w);j&&Fb(v,j)&&(y.add(v.id),y.add(j.id))}const x=[];for(let v=0;v<r.length;v+=1)for(let w=v+1;w<r.length;w+=1){const j=r[v],T=r[w];Rb(j,T)&&x.push([j,T])}for(const[v,w]of x){if(!y.has(v.id)&&!y.has(w.id))continue;const j=p(v.id,w.id);d.get(v.id)?.has(w.id)||u.add(j),d.get(v.id)?.add(w.id),d.get(w.id)?.add(v.id)}for(let v=0;v<r.length;v+=1)for(let w=v+1;w<r.length;w+=1){const j=r[v],T=r[w];if(!Db(j,T))continue;const P=p(j.id,T.id);d.get(j.id)?.has(T.id)||h.add(P),d.get(j.id)?.add(T.id),d.get(T.id)?.add(j.id)}}const g=new Map(r.map(y=>[y.id,y])),f=new Set,b=[];for(const y of r){if(f.has(y.id))continue;const x=[y.id],v=[];for(;x.length;){const N=x.pop();if(f.has(N))continue;f.add(N);const _=g.get(N);_&&v.push(_);for(const L of d.get(N)??[])x.push(L)}const w=new Set(v.map(N=>N.orientation)).size>1,j=v.some((N,_)=>v.slice(_+1).some(L=>N.rect.x===L.rect.x&&N.rect.y===L.rect.y&&N.rect.width===L.rect.width&&N.rect.height===L.rect.height)),T=w||!!(s.mergeConnectedNeighbors&&v.length>1)||j||v.some(N=>
5m.has(N.id))||v.some((N,_)=>v.slice(_+1).some(L=>u.has(p(N.id,L.id))))||v.some((N,_)=>v.slice(_+1).some(L=>h.has(p(N.id,L.id))))||v.some(N=>!N.text.trim()),P=v.some((N,_)=>v.slice(_+1).some(L=>u.has(p(N.id,L.id))||h.has(p(N.id,L.id))));b.push(Ub(t,v,T,P,s.mergeConnectedNeighbors?Ib:ph))}return{selections:b,excludedBoxIds:i}}function Bd(t,a,s){const n=new Map;for(const c of a)n.set(c.id,(n.get(c.id)??0)+1);const r=s.find(c=>(n.get(c)??0)>1);if(r)throw new Error(`Manual bubble selection has an ambiguous duplicate text box id: ${r}`);const i=new Map(a.map(c=>[c.id,c])),l=s.map(c=>i.get(c)).filter(c=>!!c);if(l.length===0)throw new Error("A manual bubble selection requires at least one valid text box");return{pageKey:t,region:{kind:"box-union",boxes:l.map(c=>c.rect),bounds:Ic(l.map(c=>c.rect))},orderedBoxIds:l.map(c=>c.id),text:l.map(c=>c.text.replace(/[\r\n]+/g,"").trim()).filter(Boolean).join(""),origin:"manual",confidence:1,requiresConfirmation:!1,reason:"single-box",groupingVersion:ph}}const Kb=8;function Hb(t,a){return`reader.bubbleListening.groups.v1:${t}:${a}`}function qd(t){if(typeof window>"u")return{};for(const a of[window.localStorage,window.sessionStorage])try{const s=a.getItem(t);if(s)return JSON.parse(s)}catch{}return{}}function Wb(t,a){for(const s of[window.localStorage,window.sessionStorage])try{s.setItem(t,JSON.stringify(a));return}catch{}}const Gb=o.forwardRef(function({active:a,materialId:s,pageNumber:n,pageWidth:r,pageHeight:i,boxes:l,theaterThemeClass:c="",onActiveChange:d},m){const u=`${s}:${n}`,h=Hb(s,n),p=o.useMemo(()=>l.map(D=>({id:D.id,text:D.text,orientation:D.orientation,rect:{x:D.x_norm,y:D.y_norm,width:D.w_norm,height:D.h_norm},linePolygons:D.rendering_data?.lines_coords?.map(de=>de.map(([fe,Me])=>({x:fe/r,y:Me/i})))})),[l,i,r]),[g,f]=o.useState(()=>qd(h)),[b,y]=o.useState(null),[x,v]=o.useState(!1),[w,j]=o.useState([]),{settings:T,setSettings:P}=Ab(),N=cf(T.speechRate,T.preferredVoiceId==="auto"?"":T.preferredVoiceId),_=o.useRef(null);o.useEffect(()=>{const D=de=>{de.pointerType==="touch"&&!de.isPrimary&&(_.current=null)};return document.addEventListener("pointerdown",D,!0),()=>document.removeEventListener("pointerdown",D,!0)},[]),o.useEffect(()=>{f(qd(h)),y(null),v(!1),N.stop()},[h]),o.useEffect(()=>()=>N.stop(),[N.stop]),o.useEffect(()=>{a||(N.stop(),v(!1),y(null))},[a,N.stop]);const L=o.useMemo(()=>{const D=new Set,de=[];for(const U of Object.values(g)){const ve=U.join("\0");if(!(!U.length||D.has(ve))){D.add(ve);try{de.push(Bd(u,p,U))}catch{}}}const fe=new Set(de.flatMap(U=>U.orderedBoxIds)),Me=p.filter(U=>!fe.has(U.id));return[...de,...Vb(u,Me,{mergeConnectedNeighbors:!0}).selections]},[p,g,u]),q=o.useCallback(D=>L.find(de=>de.orderedBoxIds.includes(D))??null,[L]),O=o.useCallback(D=>{if(N.isSpeaking&&b?.orderedBoxIds.join("\0")===D.orderedBoxIds.join("\0")){N.stop();return}y(D),v(!1),N.isAvailable&&N.speak(D.text)},[b,N]),A=o.useCallback(D=>{const de=q(D);de&&(a||d(!0),O(de))},[a,d,O,q]);o.useImperativeHandle(m,()=>({stop:N.stop,listenBox:A}),[A,N.stop]);const k=o.useCallback(()=>{b&&(N.stop(),j(b.orderedBoxIds),v(!0))},[b,N.stop]),J=o.useCallback(()=>{if(!b||w.length===0)return;const D=Bd(u,p,w),de={...g},fe=new Set([...b.orderedBoxIds,...w]);for(const[Me,U]of Object.entries(de))U.some(ve=>fe.has(ve))&&delete de[Me];for(const Me of D.orderedBoxIds)de[Me]=D.orderedBoxIds;f(de),Wb(h,de),O(D)},[p,w,g,u,h,O,b]),M=D=>{if(D.pointerType==="touch"&&!D.isPrimary){_.current=null;return}_.current={id:D.pointerId,x:D.clientX,y:D.clientY,moved:!1},D.currentTarget.setPointerCapture?.(D.pointerId)},H=D=>{const de=_.current;!de||de.id!==D.pointerId||Math.hypot(D.clientX-de.x,D.clientY-de.y)>Kb&&(de.moved=!0)},ee=(D,de)=>{const fe=_.current;_.current=null,!(!fe||fe.id!==D.pointerId||fe.moved)&&(D.preventDefault(),D.stopPropagation(),O(de))},Pe=N.status;return e.jsxs(e.Fragment,{children:[a&&L.map(D=>{const de=D.region.bounds,fe=b?.orderedBoxIds.some(Me=>D.orderedBoxIds.includes(Me));return e.jsx("button",{type:"button",className:`bubble-listening-hit-region ${fe?"is-selected":""}`,style:{left:de.x*r,top:de.y*i,width:de.width*r,height:de.height*i},"aria-label":`Listen to speech bubble: ${D.text}`,onPointerDown:M,onPointerMove:H,onPointerCancel:()=>{_.current=null},onPointerUp:Me=>ee(Me,D),onClick:Me=>{Me.preventDefault(),Me.stopPropagation(),Me.detail===0&&O(D)}},D.orderedBoxIds.join("|"))}),typeof document<"u"&&b&&hi.createPortal(e.jsx(Mb,{theme:c,speaking:N.isSpeaking,text:b.text,onPlay:()=>O(b),onStop:N.stop,onClose:()=>{N.stop(),y(null),v(!1)},children:x?e.jsxs(e.Fragment,{children:[e.jsx(Eb,{boxes:l.map(D=>({id:D.id,text:D.text})),orderedBoxIds:w,onChange:j,onSaveAndListen:J,onCancel:()=>{v(!1),j([])},status:Pe}),e.jsx("div",{className:"mt-3",children:e.jsx(Dd,{rate:T.speechRate,voices:N.voices,selectedVoiceId:T.preferredVoiceId,onRateChange:D=>P(de=>({...de,speechRate:D})),onVoiceChange:D=>P(de=>({...de,preferredVoiceId:D}))})})]}):e.jsxs(e.Fragment,{children:[e.jsx(Cb,{selection:{...b,requiresConfirmation:!1},status:N.isAvailable?Pe:"error",error:N.isAvailable?N.error:new Error("No Japanese voice is available on this device."),onListen:()=>O(b),onStop:N.stop,onEditGrouping:k,onRetryLocal:()=>{N.retryLocal(b.text)},canRetryLocal:N.canRetryLocal}),e.jsx("div",{className:"mt-3",children:e.jsx(Dd,{rate:T.speechRate,voices:N.voices,selectedVoiceId:T.preferredVoiceId,onRateChange:D=>P(de=>({...de,speechRate:D})),onVoiceChange:D=>P(de=>({...de,preferredVoiceId:D}))})})]})}),document.body)]})}),Ud=30,Yb="demo-box-2",Jb="demo-reader-textbox",Xb=.1,Qb=5,sl=t=>Math.max(Xb,Math.min(Qb,t)),Zb=176,ex=3e3,tx=2e3,nl=5e3,ax=3e4,sx=10,Vd=t=>t?.closest(".bubble-listening-hit-region")?!1:!!t?.closest('.theater-chrome-bar, .theater-panel, button, [role="button"], [role="dialog"]');function nx({textBoxes:t,containerRef:a,zoom:s}){const[n,r]=o.useState(new Map),i=o.useRef("");return o.useEffect(()=>{let l,c=!0;const d=()=>
5{if(!c)return;const m=a.current;if(m){const u=new Map,h=[];for(const g of t){const f=m.querySelectorAll(`[data-box-id="${g.id}"]`);if(f.length===0)continue;let b=1/0,y=1/0,x=-1/0,v=-1/0;for(const w of f){const j=w.getBoundingClientRect();j.width===0&&j.height===0||(b=Math.min(b,j.top),y=Math.min(y,j.left),x=Math.max(x,j.bottom),v=Math.max(v,j.right))}b<1/0&&(u.set(g.id,new DOMRect(y,b,v-y,x-b)),h.push(`${g.id}:${b|0},${y|0},${v-y|0},${x-b|0}`))}const p=h.join(";");p!==i.current&&u.size>0&&(i.current=p,r(u))}l=requestAnimationFrame(d)};return l=requestAnimationFrame(d),()=>{c=!1,cancelAnimationFrame(l)}},[t,a,s]),e.jsx(e.Fragment,{children:t.map(l=>{const c=n.get(l.id);return!c||c.width===0||l.id!==Yb?null:e.jsx("div",{"data-tour-id":Jb,className:"fixed pointer-events-none",style:{top:c.top,left:c.left,width:c.width,height:c.height}},`tour-marker-${l.id}`)})})}const rl=({title:t,icon:a,children:s})=>{const r={eye:{num:"ä¸",jp:"表示"},zoom:{num:"äº",jp:"è¦é"},sparkles:{num:"ä¸",jp:"è§£æ"},palette:{num:"å",jp:"è²å½©"},book:{num:"å",jp:"èªã¿"}}[a];return e.jsx("div",{className:"theater-panel p-4 space-y-3",children:e.jsxs("div",{style:{position:"relative",zIndex:1},className:"space-y-3",children:[e.jsxs("div",{className:"theater-rail-eyebrow",style:{marginBottom:4},children:[e.jsx("span",{className:"num jp",children:r.num}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:t}),e.jsx("span",{className:"jp",children:r.jp})]}),e.jsx("div",{className:"space-y-3",children:s})]})})},_n=({label:t,description:a,checked:s,onChange:n})=>e.jsxs("label",{className:"flex items-center justify-between cursor-pointer group py-1.5",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"text-sm font-medium transition-colors block",style:{color:"var(--theater-text)"},children:t}),a&&e.jsx("span",{className:"text-xs block truncate",style:{color:"var(--theater-text-soft)"},children:a})]}),e.jsx("div",{className:"ml-3 flex-shrink-0",children:e.jsx($n,{checked:s,onCheckedChange:n,className:"data-[state=checked]:bg-[hsl(var(--module-accent))]"})})]});function Kd({materialId:t,onBack:a,demoMode:s,onDemoReady:n,isPublicSample:r=!1,bubbleListeningEnabled:i=!1}){const{getAccessToken:l,user:c}=ps(),{openAuthModal:d}=xo(),m=o.useMemo(()=>Yl(l),[l]),{isDark:u,toggleTheme:h,theaterThemeClass:p}=mc(),g=wn(),f=lf(),b=o.useRef(f);b.current=f;const y=o.useRef(f),x=o.useRef(!1),v=o.useRef(!1),w=o.useRef(Date.now()),j=o.useRef(0),T=o.useRef(0),P=o.useRef(0),N=o.useRef(0),_=o.useRef(0),L=o.useRef(!1),q=o.useRef(xb(1500)),{openUpgradeModal:O}=xn(),{isPro:A,refresh:k}=Xn(),J=Pc(l,k);o.useEffect(()=>{J.quotaExceeded&&$a()&&O("ai_help","quota_exceeded")},[J.quotaExceeded,O]);const[M,H]=o.useState(!0);Os.useEffect(()=>{const S=setTimeout(()=>{H(!1)},3e3);return()=>clearTimeout(S)},[]),Os.useEffect(()=>{const S=document.createElement("style");return S.textContent=` 6 :root { 7 --textBoxFontSize: 16px; 8 } 9 10 .textBox { 11 font-family: "Noto Sans CJK JP", "Hiragino Sans", "Yu Gothic", "Meiryo", sans-serif; 12 position: absolute; 13 padding: 0; 14 line-height: 1.1em; 15 white-space: nowrap; 16 border: none !important; 17 cursor: pointer; 18 outline: none !important; 19 box-shadow: none !important; 20 } 21 22 .textBox:hover { 23 background: var(--theater-ocr-bg-hover) !important; 24 border: none !important; 25 /* Local OCR sibling ordering only. The fixed manga root establishes 26 the global z100 stacking context, so this cannot escape into D9. */ 27 z-index: 999 !important; 28 } 29 30 .textBox p, 31 .textBox div { 32 display: none; 33 white-space: nowrap; 34 letter-spacing: 0.1em; 35 line-height: 1.1em; 36 margin: 0; 37 background-color: var(--theater-ocr-bg-hover); 38 color: var(--theater-text) !important; 39 } 40 41 .overlay-always .textBox div { 42 display: table !important; 43 } 44 45 .overlay-always .textBox { 46 background: var(--theater-ocr-bg) !important; 47 border: none !important; 48 outline: none !important; 49 box-shadow: none !important; 50 color: var(--theater-text) !important; 51 } 52 53 .overlay-hover .textBox:hover div { 54 display: table; 55 } 56 `,document.head.appendChild(S),()=>{document.head.removeChild(S)}},[]);const[ee,Pe]=o.useState(s?hb:null),[D,de]=o.useState(s?zd:[]),[fe,Me]=o.useState(0),[U,ve]=o.useState(s?pb:[]),[yt,ut]=o.useState(s?zd[0]?.pageNumber??null:null),St=o.useMemo(()=>U.length===0?!1:U.every(S=>!S.processedData?.tokens?.length),[U]),[je,lt]=o.useState(!s),[Et,Ct]=o.useState(null),[aa,vt]=o.useState(!1),[Le,jt]=o.useState(0),[Ft,ct]=o.useState(0),[se,ft]=o.useState(null),[Oe,pt]=o.useState(!1),[kt,Ve]=o.useState(!0),[Be,Ke]=o.useState(1),[At,Jt]=o.useState(.8),[ta,zt]=o.useState(!1),[K,_t]=o.useState(!1),qt=o.useRef(null),sa={text:"var(--theater-text)"}
56,[la,Dt]=o.useState("1024w"),[ba,da]=o.useState(!1),[xa,ma]=o.useState(!0),[Na,Da]=o.useState(()=>{try{const S=localStorage.getItem("reader.annotationsEnabled");return S!==null?S!=="false":localStorage.getItem("reading.annotationsDefault")!=="false"}catch{return!0}}),[wa,Wt]=o.useState(()=>{try{return localStorage.getItem("reader.showFurigana")==="true"}catch{return!1}}),[ua,ca]=o.useState(()=>{try{return localStorage.getItem("reader.showKnownColoring")==="true"}catch{return!1}}),[ha,za]=Cc(),ea=o.useMemo(()=>rc(),[]),Ea=o.useMemo(()=>ic(),[]),pa=o.useMemo(()=>Jl(l,{offlineSrsPaidAccess:A}),[l,A]),Ca=o.useMemo(()=>{const S=new Set;for(const z of U)for(const Z of z.processedData?.tokens??[])for(const ie of dc(Z,()=>!0))S.add(ie);return Array.from(S)},[U]),Gt=!!c&&!s&&ha,{knowledgeMap:Ba}=oc(Gt?pa:void 0,Ca),ka="token",Wa="natural",es=ua?"known":"none",Ta=Ug({enabled:ua,isAuthenticated:!!c,isPublicSample:r,isDemo:!!s}),va=_m(t,Ta==="material",l),ia=Sm(Ta==="global",l),oe=Ta==="global"?ia:va,me=Vg({isAuthenticated:!!c,isDemo:!!s}),Ge=!0,[gt,I]=o.useState(()=>{try{return localStorage.getItem("reader.showMaskLayer")==="true"}catch{return!1}}),xe=`color-mix(in srgb, var(--theater-ocr-bg) ${Math.round(At*100)}%, transparent)`,[Ne,tt]=o.useState(()=>{try{return localStorage.getItem("reader.readingDirection.v2")==="ltr"?"ltr":"rtl"}catch{return"rtl"}}),[Mt,Ma]=o.useState(()=>{try{return localStorage.getItem("reader.autoHideChrome")==="true"}catch{return!1}}),[It,Nt]=o.useState(!1),Lt=o.useRef(null),qa=o.useRef(null),F=o.useRef(null);o.useEffect(()=>{for(const S of[qa.current,F.current])S&&(It?S.setAttribute("inert",""):S.removeAttribute("inert"))},[It]);const Q=o.useRef(null),W=o.useRef(Be),[E,G]=o.useState({x:0,y:0}),[re,pe]=o.useState(!1),[te,Fe]=o.useState({x:0,y:0}),ke=o.useRef(!1),Qe=o.useRef({x:0,y:0}),Y=o.useRef({x:0,y:0}),Ze=o.useRef(null),Ut=o.useCallback(()=>{Ze.current=null;const S=Q.current;if(!S)return;const{x:z,y:Z}=Y.current;S.style.transform=`translate(calc(-50% + ${z}px), calc(-50% + ${Z}px)) scale(${W.current})`},[]),Ot=o.useCallback(()=>{Ze.current==null&&(Ze.current=requestAnimationFrame(Ut))},[Ut]);o.useEffect(()=>()=>{Ze.current!=null&&cancelAnimationFrame(Ze.current)},[]);const is=o.useRef(null),os=o.useCallback((S,z)=>{const Z=is.current;if(!Z)return S;const ie=b.current,ce=ie.width||window.innerWidth,Ce=ie.height||window.innerHeight,$e=Math.max(0,(Z.width*z-ce)/2),et=Math.max(0,(Z.height*z-(Ce-Zb))/2);return{x:Math.max(-$e,Math.min($e,S.x)),y:Math.max(-et,Math.min(et,S.y))}},[]);o.useEffect(()=>{const S=D[fe];is.current=S?{width:S.width,height:S.height}:null},[D,fe]);const Qs=o.useCallback(()=>{const S=os(Y.current,W.current),z=Y.current;Math.abs(S.x-z.x)<.5&&Math.abs(S.y-z.y)<.5||(Y.current=S,G(S),Ot())},[os,Ot]);o.useEffect(()=>{const S=y.current;if(!(Math.max(Math.abs(f.width-S.width),Math.abs(f.height-S.height),Math.abs(f.left-S.left),Math.abs(f.top-S.top))<=80)){if(y.current=f,x.current){v.current=!0;return}Qs()}},[f,Qs]);const{selectedToken:C,setSelectedToken:V,tokenPanelPosition:le,setTokenPanelPosition:ye,tokenPanelLoading:it,pageTokens:fa,loadPageTokens:Xt,getContainerTokens:ga,tokenDataToNLPToken:Tt,handleTokenClick:Pa,closeTokenPanel:oa,boxHoveredCluster:Aa,setBoxHoveredCluster:Fa}=Ec({materialId:t,getAccessToken:l,currentPageNumber:D[fe]?.pageNumber,isPublic:r}),[us,xs]=o.useState(null),Ga=o.useRef(null),Cs=o.useRef(null),Dn=o.useCallback(()=>{const S=Ga.current;Ga.current=null,xs(null),S?.(!1)},[]),Tr=o.useCallback(S=>{if(!us)return;Cs.current={sourceKey:us.sourceKey,bounds:S};const z=Ga.current;Ga.current=null,xs(null),z?.(!0)},[us]);o.useEffect(()=>()=>{Ga.current?.(!1),Ga.current=null},[]);const Ja=o.useMemo(()=>{if(!(!ee||s))return{messages:J.messages,isLoading:J.isLoading,error:J.error,quotaExceeded:J.quotaExceeded,contextText:J.contextText,materialTitle:J.materialTitle,sendFollowUp:J.sendFollowUp,onUpgrade:()=>O("ai_help","quota_exceeded"),start:async S=>{const z=U.find(ie=>ie.id===C?.boxId),Z=D[fe];!z||!Z||(ne("immersion_ai_help_triggered",{material_type:"manga",source:"lookup_panel"}),await J.triggerHelp(z,U,ee,Z.pageNumber,S))}}},[ee,s,J,U,C?.boxId,D,fe,O]),Es=o.useMemo(()=>
56{if(!C?.boxId||r||s)return;const S=D[fe],z=U.find(Ee=>Ee.id===C.boxId)??null,Z=z?nb(z):null;if(!S||!z||Z===null||!S.imageUrl)return;const ie=C.originalStartChar??C.startChar??C.start_char,ce=C.originalEndChar??C.endChar??C.end_char;if(typeof ie!="number"||typeof ce!="number"||!Number.isInteger(ie)||!Number.isInteger(ce)||ce<=ie)return;const Ce=fa.get(z.id)?.find(Ee=>{const De=Ee.originalStartChar??Ee.startChar??Ee.start_char,Te=Ee.originalEndChar??Ee.endChar??Ee.end_char;return De===ie&&Te===ce}),$e=Ce?Ce.id:void 0,et=typeof $e=="string"?$e:void 0,ot=S.imageUrl,ht={x:z.x_norm,y:z.y_norm,width:z.w_norm,height:z.h_norm},we=[t,S.pageNumber,z.id,Z,ie,ce].join(":");return{source:{kind:"reading_material",materialId:t,pageNumber:S.pageNumber,boxId:z.id,boxIndex:Z,...et?{readingOccurrenceId:et}:{},highlightStart:ie,highlightEnd:ce},selectImageCrop:()=>new Promise(Ee=>{Ga.current?.(!1),Ga.current=Ee;const De=Cs.current;xs({sourceKey:we,imageUrl:ot,initialBounds:De?.sourceKey===we?De.bounds:Xy(ht)})}),captureImage:async Ee=>{const De=Cs.current;if(!De||De.sourceKey!==we)throw new Error("Choose a manga crop before saving the mnemonic image");return db({imageUrl:ot,ocrBoxNormalized:ht,manualCropNormalized:De.bounds})}}},[C,r,s,D,fe,U,fa,t]),$s=o.useCallback(S=>ga(S),[ga]);o.useEffect(()=>{!s||!n||n({simulateTokenClick:(S,z)=>{const Z=U.find($e=>$e.id===S),ie=Z?.processedData?.tokens;if(!Z||!ie?.[z])return;const ce=ie[z],Ce={clientX:window.innerWidth*.3,clientY:window.innerHeight*.4};Pa({...ce,boxId:Z.id,originalStartChar:ce.start_char,originalEndChar:ce.end_char},Ce,Z.orientation==="vertical"?"vertical-rl":void 0)},closeTokenPanel:oa,hoverCluster:(S,z)=>{const Z=U.find($e=>$e.id===S),ie=Z?.processedData?.tokens;if(!Z||!ie?.[z])return;const ce=ie[z],Ce=ce.conjugation;Ce?.memberIds&&Fa({boxId:Z.id,memberIds:new Set(Ce.memberIds),rootToken:ce})},clearClusterHover:()=>Fa(null),getTextBoxRect:S=>{const z=document.querySelectorAll(`[data-box-id="${S}"]`);if(z.length===0)return null;let Z=1/0,ie=1/0,ce=-1/0,Ce=-1/0;return z.forEach($e=>{const et=$e.getBoundingClientRect();Z=Math.min(Z,et.top),ie=Math.min(ie,et.left),ce=Math.max(ce,et.bottom),Ce=Math.max(Ce,et.right)}),new DOMRect(ie,Z,Ce-ie,ce-Z)},getClusterRect:(S,z)=>{const Z=U.find(Te=>Te.id===S),Ce=Z?.processedData?.tokens?.[z]?.conjugation?.memberIds;if(!Z||!Ce?.length)return null;const $e=document.querySelectorAll(`[data-box-id="${S}"]`);if($e.length===0)return null;const et=new Set(Ce.map(String));let ot=1/0,ht=1/0,we=-1/0,Ee=-1/0,De=!1;return $e.forEach(Te=>{Te.querySelectorAll("[data-token-id]").forEach(Se=>{const He=Se.dataset.tokenId;if(!He||!et.has(He))return;const We=Se.getBoundingClientRect();ot=Math.min(ot,We.top),ht=Math.min(ht,We.left),we=Math.max(we,We.bottom),Ee=Math.max(Ee,We.right),De=!0})}),De?new DOMRect(ht,ot,Ee-ht,we-ot):null}})},[s,n,U,Pa,oa,Fa]);const Zn=o.useMemo(()=>u?{backgroundImage:` 57 radial-gradient(1200px 700px at 16% 22%, hsl(var(--module-accent) / 0.06), transparent 62%), 58 radial-gradient(1000px 600px at 82% 28%, hsl(var(--module-accent) / 0.05), transparent 62%), 59 radial-gradient(900px 520px at 40% 88%, hsl(var(--module-accent) / 0.04), transparent 60%)`}:{},[u]),Ln=o.useMemo(()=>{const S=new Map;for(const z of U){const Z=$s(z);if(Z.length===0){S.set(z.id,new Map);continue}const ie=z.rendering_data?.lines||z.text.split(` 60`),Ce=z.text.includes(` 61`)?1:0,$e=[];let et=0;for(const Ee of ie)$e.push({start:et,end:et+Ee.length}),et+=Ee.length+Ce;const ot=new Map;for(const Ee of Z){const De=Ee.start_char??Ee.startChar??0;Ee.id!==void 0&&ot.set(Ee.id,De)}const ht=Ee=>$e.findIndex(De=>Ee>=De.start&&Ee<De.end+Ce),we=new Map;for(const Ee of Z){const De=Ee.conjugation?.memberIds;if(!De||De.length<=1)continue;const Te=Ee.start_char??Ee.startChar??0,Se=ht(Te);if(De.some(We=>{const Vt=ot.get(We);return Vt!==void 0&&ht(Vt)!==Se}))for(const We of De)we.set(We,De)}S.set(z.id,we)}return S},[U,$s]),er=o.useMemo(()=>{const S=new Map;for(const z of U){const Z=z.rendering_data?.lines||z.text.split(` 62`),ie=$s(z),Ce=z.text.includes(` 63`)?1:0,$e=[];let et=0;for(const ht of Z)$e.push({start:et,end:et+ht.length}),et+=ht.length+Ce;const ot=Z.map((ht,we)=>{const Ee=$e[we].start,De=$e[we].end,Se=ie.filter(He=>{const We=He.start_char??He.startChar??0;return We>=Ee&&We<De}).map(He=>{const We=He.start_char??He.startChar??0,Vt=He.end_char??He.endChar??0;return{...He,lemmaSurface:He.lemmaSurface||He.lemma||He.surface,boxId:z.id,originalStartChar:We,originalEndChar:Vt,start_char:Math.max(0,We-Ee),end_char:Math.min(ht.length,Vt-Ee),startChar:Math.max(0,We-Ee),endChar:Math.min(ht.length,Vt-Ee)}}).map((He,We)=>Tt(He,we*1e3+We));return{lineText:ht,rendererTokens:Se}});S.set(z.id,ot)}return S},[U,$s,Tt]);o.useEffect(()=>{W.current=Be},[Be]),o.useEffect(()=>{ke.current=re},[re]),o.useEffect(()=>{Qe.current=te},[te]),o.useEffect(()=>{Y.current=E},[E]),Os.useEffect(()=>{const S=Q.current;if(!S)return;let z;const Z=ie=>{if(!Vd(ie.target)&&(ie.ctrlKey||ie.metaKey)){ie.preventDefault();const ce=ie.deltaY>0?-.1:.1;W.current=sl(W.current+ce),Y.current=os(Y.current,W.current),Ot(),z&&window.clearTimeout(z),z=window.setTimeout(()=>{Ke(W.current),G(Y.current)},120)}};return S.addEventListener("wheel",Z,{passive:!1}),()=>{S.removeEventListener("wheel",Z),z&&window.clearTimeout(z)}},[Ot,os]),Os.useEffect(()=>{let S=0,z=W.current,Z={x:0,y:0},ie={x:0,y:0},ce=!1;const Ce=Te=>Math.hypot(Te[1].clientX-Te[0].clientX,Te[1].clientY-Te[0].clientY),$e=Te=>({x:(Te[0].clientX+Te[1].clientX)/2,y:(Te[0].clientY+Te[1].clientY)/2}),et=Te=>{Te.touches.length===2&&(Te.preventDefault(),ot(Te.touches),ce=!0,x.current=!0)},ot=Te=>{S=Ce(Te)||1,z=W.current,Z=$e(Te),ie={...Y.current}},ht=Te=>{if(ce&&Te.touches.length===2){Te.preventDefault();const Se=Ce(Te.touches)/S;W.current=sl(z*Se);const He=$e(Te.touches);
63Y.current=os({x:ie.x+(He.x-Z.x),y:ie.y+(He.y-Z.y)},W.current),Ot()}},we=()=>{ce&&(ce=!1,x.current=!1,Ke(W.current),G(Y.current),v.current&&(v.current=!1,Qs()))},Ee=Te=>{Te.touches.length<2?we():ce&&Te.touches.length===2&&ot(Te.touches)},De=Q.current;if(De)return De.addEventListener("touchstart",et,{passive:!1}),De.addEventListener("touchmove",ht,{passive:!1}),De.addEventListener("touchend",Ee,{passive:!0}),De.addEventListener("touchcancel",we,{passive:!0}),()=>{De.removeEventListener("touchstart",et),De.removeEventListener("touchmove",ht),De.removeEventListener("touchend",Ee),De.removeEventListener("touchcancel",we)}},[Ot,os,Qs]),Os.useEffect(()=>{const S=ce=>{if(xa&&ce.button===0&&!Vd(ce.target)){const Ce={x:ce.clientX-Y.current.x,y:ce.clientY-Y.current.y};ke.current=!0,Qe.current=Ce,pe(!0),Fe(Ce),ce.preventDefault()}},z=ce=>{ke.current&&xa&&(Y.current=os({x:ce.clientX-Qe.current.x,y:ce.clientY-Qe.current.y},W.current),Ot(),ce.preventDefault())},Z=()=>{ke.current&&(ke.current=!1,pe(!1),G(Y.current))},ie=Q.current;if(ie)return ie.addEventListener("mousedown",S),document.addEventListener("mousemove",z),document.addEventListener("mouseup",Z),()=>{ie.removeEventListener("mousedown",S),document.removeEventListener("mousemove",z),document.removeEventListener("mouseup",Z)}},[xa,Ot,os]),Os.useEffect(()=>{G({x:0,y:0})},[fe]);const Zs=async()=>{try{const S=r?`${ue()}/api/reading/public/material/${t}?include=pages,progress`:`${ue()}/api/reading/materials/${t}?include=pages,progress`,z={"Content-Type":"application/json"};if(!r){const ce=await l();if(!ce)throw new Error("Please log in first");z.Authorization=`Bearer ${ce}`}const Z=await fetch(S,{headers:z});if(!Z.ok)throw new Error("Failed to load material");const ie=await Z.json();return Pe(ie.material),!L.current&&!s&&(L.current=!0,w.current=Date.now(),ne("immersion_session_started",{material_type:"manga",nlp_annotated:ie.material?.processing_status==="completed",page_count:ie.material?.total_pages})),ie.progress&&ie.progress.currentPage&&Me(Math.max(0,ie.progress.currentPage-1)),ie.material??null}catch(S){return Ct(S instanceof Error?S.message:"Failed to load material"),null}},[Ts,en]=o.useState(!1),[Vs,vn]=o.useState(!1),[Ms,tr]=o.useState(!1),hn=o.useRef(null),tn=o.useRef(null);o.useEffect(()=>{ta?(tn.current=document.activeElement??null,requestAnimationFrame(()=>hn.current?.focus())):tn.current&&(tn.current.focus?.(),tn.current=null)},[ta]);const jn=o.useRef([]),On=o.useRef(0),$=o.useRef(new Set),he=o.useRef(null),_e=ee?.cloud_sync_status==="synced",Pt=o.useMemo(()=>new Map(D.map(S=>[S.pageNumber,{width:S.width,height:S.height}])),[D.length]);o.useEffect(()=>{_e&&t&&!r?he.current?he.current.setDims(Pt):he.current=new ay(t,{getAccessToken:l,dims:Pt}):he.current&&(he.current.dispose(),he.current=null)},[_e,t,r,l,Pt]),o.useEffect(()=>()=>{he.current?.dispose(),he.current=null},[]);const[Rt,Ia]=o.useState(!1),[ts,Ra]=o.useState(!1),[Ua,La]=o.useState(0),fs=o.useRef(0),ls=o.useRef("forward"),Zt=o.useRef([]);o.useEffect(()=>()=>{jn.current.forEach(S=>URL.revokeObjectURL(S)),jn.current=[],Zt.current.forEach(({url:S})=>URL.revokeObjectURL(S)),Zt.current=[]},[]);const zs=async(S=la,z)=>{try{const Z=S==="native"?"":"?size=1024w",ie=r?`${ue()}/api/reading/public/material/${t}/pages${Z}`:`${ue()}/api/reading/materials/${t}/pages${Z}`,ce={"Content-Type":"application/json"};if(!r){const Te=await l();if(!Te)throw new Error("Please log in first");ce.Authorization=`Bearer ${Te}`}const Ce=await fetch(ie,{headers:ce});if(!Ce.ok)throw new Error("Failed to load pages");const et=(await Ce.json()).pages||[],ot=z??ee?.cloud_sync_status==="synced",ht=[],we=await Promise.all(et.map(async Te=>{if(Te.localOnly&&!Te.imageUrl){const Se=await Nm(t,Te.pageNumber);return Se?(ht.push(Se),{...Te,imageUrl:Se}):ot?{...Te,cloudBacked:!0}:Te}return Te})),Ee=jn.current;jn.current=ht,Ee.forEach(Te=>URL.revokeObjectURL(Te)),de(we);const De=we.some(Te=>Te.localOnly&&!Te.imageUrl&&!Te.cloudBacked);en(De)}catch(Z){console.error("Failed to load pages:",Z)}},ks=o.useRef(zs);ks.current=zs;const Fs=To({material:{id:t,content_type:ee?.content_type??null,file_type:ee?.file_type??null,total_pages:ee?.total_pages??null,content_sha256:ee?.content_sha256??null,original_filename:ee?.original_filename??null,file_size_bytes:ee?.file_size_bytes??null},onRestored:async()=>{tr(!0),vn(!1),await ks.current()}});o.useEffect(()=>{Ts&&!Ms&&vn(!0)},[Ts,Ms]);const Mr=o.useCallback(()=>{vn(!1),tr(!0),Fs.reset()},[Fs]),Bn=o.useCallback(()=>{Fs.reset(),vn(!0)},[Fs]),ad=async S=>{const z=++On.current,Z=()=>z===On.current;try{vt(!0);const ie=r?`${ue()}/api/reading/public/material/${t}/pages/${S}/overlay`:`${ue()}/api/reading/materials/${t}/pages/${S}/overlay`,ce={"Content-Type":"application/json"};if(!r){const $e=await l();if(!$e)return;ce.Authorization=`Bearer ${$e}`}const Ce=await fetch(ie,{headers:ce});if(!Z())return;if(Ce.ok){const $e=await Ce.json();if(!Z())return;const et=($e.boxes||[]).map(ot=>({...ot,processedData:ot.processedData??ot.processed_data??null}));ve(et),ut(S)}else ve([]),ut(S)}catch(ie){Z()&&(console.error("Failed to load text boxes:",ie),ve([]),ut(S))}finally{Z()&&vt(!1)}};o.useEffect(()=>{if(s)return;(async()=>{lt(!0);const z=await Zs();await zs(la,z?.cloud_sync_status==="synced"),lt(!1)})()},[t,Le]),o.useEffect(()=>{if(s||r||je||!ee)return;const S=ee.processing_status;if(S!=="processing"&&S!=="pending")return;let z=!1,Z=0,ie=0;pt(!1);const ce=$e=>{if($e.kind==="terminal"){pt(!0);return}if(ie+=1,ie>sx){pt(!0);return}Z=window.setTimeout(Ce,to(ie,{baseMs:nl,maxMs:ax,retryAfterMs:$e.retryAfterMs}))};
63async function Ce(){if(!z){if(typeof document<"u"&&document.visibilityState==="hidden"){Z=window.setTimeout(Ce,nl);return}try{const $e=await l();if(z)return;if(!$e){pt(!0);return}const et=await fetch(`${ue()}/api/reading/materials/${t}/status`,{headers:{Authorization:`Bearer ${$e}`}});if(z)return;if(!et.ok){ce(Xl(et));return}const ot=await et.json();if(z)return;ie=0,ft({currentStep:typeof ot?.currentStep=="string"?ot.currentStep:null,progress:typeof ot?.progress=="number"?ot.progress:null});const ht=typeof ot?.processingStatus=="string"?ot.processingStatus:null;if(ht&&ht!=="processing"&&ht!=="pending"){jt(we=>we+1);return}Z=window.setTimeout(Ce,nl)}catch($e){if(z)return;ce(Ql($e))}}}return Z=window.setTimeout(Ce,Ft>0?eo:tx),()=>{z=!0,window.clearTimeout(Z)}},[s,r,je,ee,t,l,Ft]);const ki=o.useRef(!1),qn=o.useCallback(()=>{if(!L.current||ki.current)return;ki.current=!0;const S=w.current,z=Date.now(),Z=z-S,ie=P.current,ce=j.current;ne("immersion_session_ended",{material_type:"manga",pages_read:ie,session_duration_ms:Z,tokens_clicked:ce,words_added_to_deck:T.current}),(async()=>{try{const Ce=await l();if(!Ce)return;await fetch(`${ue()}/api/immersion/sessions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ce}`},body:JSON.stringify({materialId:t,materialType:"manga",startedAt:new Date(S).toISOString(),endedAt:new Date(z).toISOString(),durationMs:Z,pagesRead:ie,tokensClicked:ce}),keepalive:!0})}catch{}})()},[t,l]);o.useEffect(()=>{const S=()=>qn(),z=()=>{document.visibilityState==="hidden"&&qn()};return window.addEventListener("pagehide",S),document.addEventListener("visibilitychange",z),()=>{window.removeEventListener("pagehide",S),document.removeEventListener("visibilitychange",z),qn()}},[qn]),o.useEffect(()=>{s||D.length>0&&zs(la)},[la]),o.useEffect(()=>{if(!s&&D.length>0&&fe>=0&&fe<D.length){const S=D[fe];ad(S.pageNumber)}},[fe,D]),o.useEffect(()=>{try{localStorage.setItem("reader.annotationsEnabled",String(Na))}catch{}},[Na]),o.useEffect(()=>{try{localStorage.setItem("reader.showFurigana",String(wa))}catch{}},[wa]),o.useEffect(()=>{try{localStorage.setItem("reader.showKnownColoring",String(ua))}catch{}},[ua]),o.useEffect(()=>{try{localStorage.setItem("reader.showMaskLayer",String(gt))}catch{}},[gt]),o.useEffect(()=>{try{localStorage.setItem("reader.readingDirection.v2",Ne)}catch{}},[Ne]),o.useEffect(()=>{try{localStorage.setItem("reader.autoHideChrome",String(Mt))}catch{}},[Mt]),o.useEffect(()=>{if(!s&&D.length>0&&fe>=0&&fe<D.length){const S=D[fe];Xt(S.pageNumber)}},[fe,D,t]),o.useEffect(()=>{if(D.length>0&&!ba){const S=Xe();Ke(S),da(!0)}},[D,ba]),o.useEffect(()=>{if(s)return;const z=D[fe]?.imageUrl;if(!z||z.startsWith("blob:"))return;let Z=!1;const ie=new Image;return ie.onload=()=>{Z||[D[fe+1],D[fe-1]].forEach(ce=>{const Ce=ce?.imageUrl;if(Ce&&!Ce.startsWith("blob:")){const $e=new Image;$e.src=Ce}})},ie.onerror=()=>{Z||$.current.has(z)||($.current.add(z),zs(la))},ie.src=z,()=>{Z=!0,ie.onload=null,ie.onerror=null}},[fe,D,s]);const R=o.useCallback((S,z)=>{const Z=Zt.current;Z.push({pageNumber:S,url:z});const ie=new Set;if(Z.length>Ud){const ce=[...Z].sort(($e,et)=>Math.abs(et.pageNumber-S)-Math.abs($e.pageNumber-S)),Ce=Z.length-Ud;for(const $e of ce){if(ie.size>=Ce)break;$e.pageNumber!==S&&(URL.revokeObjectURL($e.url),ie.add($e.pageNumber))}Zt.current=Z.filter($e=>!ie.has($e.pageNumber))}return ie},[]);o.useEffect(()=>{if(s)return;const S=D[fe];if(!S||!S.cloudBacked||S.imageUrl)return;const z=he.current;if(!z)return;const Z=++fs.current,ie=()=>Z===fs.current,ce=S.pageNumber;Ra(!1),Ia(!1),(async()=>{try{const Ce=await gc(z.getPage(ce,{direction:ls.current}),ot=>{ie()&&Ia(ot)},fc);if(!ie())return;const $e=URL.createObjectURL(Ce),et=R(ce,$e);de(ot=>ot.map(ht=>ht.pageNumber===ce?{...ht,imageUrl:$e}:et.has(ht.pageNumber)?{...ht,imageUrl:null}:ht))}catch{ie()&&Ra(!0)}})()},[fe,D,s,Ua]);const B=o.useCallback(()=>{if(fe<D.length-1){qt.current?.stop(),ls.current="forward";const S=fe+1,z=fe+2;Me(Z=>Z+1),S>N.current&&(N.current=S,P.current++),_.current++,!s&&t&&q.current(t,{currentPage:z}),!s&&_.current%10===0&&ne("immersion_page_turned",{material_type:"manga",page:z,direction:"forward"})}},[fe,D.length,s,t]),X=o.useCallback(()=>
63{if(fe>0){qt.current?.stop(),ls.current="back";const S=fe;Me(z=>z-1),_.current++,!s&&t&&q.current(t,{currentPage:S}),!s&&_.current%10===0&&ne("immersion_page_turned",{material_type:"manga",page:S,direction:"back"})}},[fe,s,t]),ae=Ne==="rtl",ge=ae?B:X,be=ae?X:B,Je=ae?fe>=D.length-1:fe===0,nt=ae?fe===0:fe>=D.length-1,bt=ae?"Next page":"Previous page",st=ae?"Previous page":"Next page",$t=o.useCallback(()=>{Lt.current!=null&&window.clearTimeout(Lt.current),Lt.current=window.setTimeout(()=>Nt(!0),ex)},[]),_a=o.useCallback(()=>{Nt(!1),$t()},[$t]);o.useEffect(()=>{if(!Mt){Lt.current!=null&&(window.clearTimeout(Lt.current),Lt.current=null),Nt(!1);return}$t();const S=()=>_a();return window.addEventListener("pointerdown",S,{passive:!0}),window.addEventListener("keydown",S,{passive:!0}),()=>{window.removeEventListener("pointerdown",S),window.removeEventListener("keydown",S),Lt.current!=null&&(window.clearTimeout(Lt.current),Lt.current=null)}},[Mt,$t,_a]);const na=o.useCallback(()=>{const S=D[fe];if(!S)return;const z=b.current,Z=(z.width||window.innerWidth)-32,ie=(z.height||window.innerHeight)-96-80-32,ce=Math.min(Z/S.width,ie/S.height,1);W.current=ce,Ke(ce),G({x:0,y:0}),Y.current={x:0,y:0}},[D,fe]);o.useEffect(()=>{const S=z=>{if(z.defaultPrevented)return;const Z=z.target;if(!Z?.closest(".bubble-listening-panel")&&!(Z&&(Z.tagName==="INPUT"||Z.tagName==="TEXTAREA"||Z.tagName==="SELECT"||Z.isContentEditable))){if(us){z.preventDefault(),z.key==="Escape"&&Dn();return}if(z.key==="Escape"){if(Vs){Mr();return}if(ta){zt(!1);return}if(C){oa();return}a();return}z.key==="ArrowLeft"||z.key==="a"?(Ne==="rtl"?B:X)():z.key==="ArrowRight"||z.key==="d"?(Ne==="rtl"?X:B)():z.key==="o"?Ve(ie=>!ie):(z.key==="f"||z.key==="F")&&na()}};return window.addEventListener("keydown",S),()=>window.removeEventListener("keydown",S)},[B,X,a,na,oa,ta,C,Vs,Mr,Ne,us,Dn]);const qe=async(S,z)=>{if(Na&&(s||(j.current++,ne("immersion_token_clicked",{material_type:"manga",source:"manga_bubble"})),!!Ye))try{const Z=z.currentTarget,ce=z.target.closest("[data-token-surface]");if(ce&&ce.dataset.tokenSurface){const Se=ce.dataset.tokenId?parseInt(ce.dataset.tokenId,10):void 0,He=ce.dataset.startChar?parseInt(ce.dataset.startChar,10):void 0,We=ce.dataset.endChar?parseInt(ce.dataset.endChar,10):void 0,wt=$s(S).find(ra=>{if(Se!==void 0&&ra.id===Se)return!0;const Bt=ra.originalStartChar??ra.startChar??ra.start_char??He??0,Qt=ra.originalEndChar??ra.endChar??ra.end_char??Bt+(ra.surface?.length??0);return He!==void 0&&We!==void 0&&Bt===He&&Qt===We});if(wt){const Bt={...Tt(wt,wt.id||0),character_readings:wt.characterReadings??null,boxId:S.id,originalStartChar:wt.originalStartChar??wt.startChar??wt.start_char??He??0,originalEndChar:wt.originalEndChar??wt.endChar??wt.end_char??We??(wt.originalStartChar??wt.startChar??wt.start_char??He??0)+(wt.surface?.length??0)};await Pa(Bt,z,S.orientation==="vertical"?"vertical-rl":void 0);return}}let Ce=-1;if(document.caretPositionFromPoint){const Se=document.caretPositionFromPoint(z.clientX,z.clientY);Se&&Se.offsetNode&&Se.offsetNode.textContent&&(Ce=Se.offset)}else if(document.caretRangeFromPoint){const Se=document.caretRangeFromPoint(z.clientX,z.clientY);Se&&Se.startContainer&&Se.startContainer.textContent&&(Ce=Se.startOffset)}if(Ce===-1){const Se=Z.getBoundingClientRect(),He=Math.max(0,Math.min(1,(z.clientX-Se.left)/Se.width));Ce=Math.floor(S.text.length*He)}Ce=Math.max(0,Math.min(Ce,S.text.length-1));const et=$s(S).find(Se=>{const He=Se.originalStartChar??Se.startChar??Se.start_char??0,We=Se.originalEndChar??Se.endChar??Se.end_char??He;return Ce>=He&&Ce<We&&Se.conjugationMeta});if(et){const Se={...et,boxId:S.id,originalStartChar:et.originalStartChar??et.startChar??et.start_char,originalEndChar:et.originalEndChar??et.endChar??et.end_char};await Pa(Se,z,S.orientation==="vertical"?"vertical-rl":void 0);return}const ot=r?void 0:await l();if(!r&&!ot)return;const ht={pageNumber:Ye.pageNumber,boxId:S.id,startChar:Ce,endChar:Ce+1},we=r?`${ue()}/api/reading/public/material/${t}/tokens/lookup`:`${ue()}/api/reading/materials/${t}/tokens/lookup`,Ee={"Content-Type":"application/json"};ot&&(Ee.Authorization=`Bearer ${ot}`);const De=await fetch(we,{method:"POST",headers:Ee,body:JSON.stringify(ht)});if(!De.ok){console.error("Token lookup failed:",De.status);return}const Te=await De.json();if(Te.token){const Se=Te.token.originalStartChar??Te.token.startChar??Te.token.start_char,He=Te.token.originalEndChar??Te.token.endChar??Te.token.end_char;let We={...Te.token,alternatives:Te.alternatives,boxId:S.id,originalStartChar:Se,originalEndChar:He};if(Jp(We)){const Vt=await Xp(We.surface,We.reading,We.lemmaSurface);Vt&&(We={...We,...Vt})}V(We),ye({x:z.clientX,y:z.clientY,writingMode:S.orientation==="vertical"?"vertical-rl":void 0})}}catch(Z){console.error("Token lookup error:",Z)}},rt=(S,z,Z,ie,ce)=>{const Ce=$s(S);return e.jsx("div",{style:{margin:0,backgroundColor:gt?xe:"transparent",color:sa.text,writingMode:S.orientation==="vertical"?"vertical-rl":"horizontal-tb",textOrientation:S.orientation==="vertical"?"upright":"mixed"},children:Na?e.jsx(si,{tokens:Z,vocabTokens:[],onTokenClick:($e,et)=>{const ot={...$e,boxId:S.id,originalStartChar:$e.start_char,originalEndChar:$e.end_char};Pa(ot,et,S.orientation==="vertical"?"vertical-rl":void 0)},externalHoveredMemberIds:Aa?.boxId===S.id?Aa.memberIds:void 0,externalClusterRootToken:Aa?.boxId===S.id?Aa.rootToken:void 0,clusterMemberMap:ce,onClusterHover:$e=>{const et=new Set($e),ot=Ce.find(we=>we.conjugation?.memberIds&&$e.every(Ee=>we.conjugation.memberIds.includes(Ee))),ht=ot?Tt(ot,0):void 0;Fa({boxId:S.id,memberIds:et,rootToken:ht})}
63,onClusterLeave:()=>Fa(null),showFurigana:wa,furiganaMode:ka,spacingMode:Wa,colorMode:es,knownStatusMap:oe,deriveUnseenByPos:Ta==="global",showGrammarProgress:Gt,grammarKnowledgeMap:Ba,grammarProgressWritingMode:S.orientation==="vertical"?"vertical-rl":"horizontal-tb",simplifyMode:"off",showGhostSubjects:!1,groupVerbConjugations:Ge,className:"inline-flex flex-wrap gap-0.5"}):e.jsx("span",{style:{userSelect:"text"},children:z})},ie)};o.useEffect(()=>{oa()},[fe,oa]);const Xe=()=>{if(!D[fe])return 1;const S=D[fe],z=b.current,Z=(z.width||window.innerWidth)-32,ie=(z.height||window.innerHeight)-96-80-32,ce=Z/S.width,Ce=ie/S.height;return Math.min(ce,Ce,1)},Ae=()=>{if(!D[fe])return 1;const S=D[fe],Z=(b.current.width||window.innerWidth)-32;return Math.min(Z/S.width,1)},Re=(S,z=!1)=>{const Z=sl(S);W.current=Z,Ke(Z);const ie=z?{x:0,y:0}:os(Y.current,Z);Y.current=ie,G(ie)},at=()=>Re(W.current*1.2),Ie=()=>Re(W.current/1.2),Ue=()=>Re(1,!0),mt=()=>Re(Xe(),!0),xt=()=>Re(Ae(),!0),Yt={textSecondary:"var(--theater-text-soft)",textMuted:"var(--theater-text-muted)",buttonBg:"var(--theater-surface-hover)"};if(Et)return e.jsx("div",{className:"wc-root im-logged wc-error-page",children:e.jsxs("div",{className:"wc-error-card wc-pencil-frame wc-pencil-frame--lg",children:[e.jsx("span",{className:"wc-error-glyph jp",children:"è¿·"}),e.jsx("h2",{className:"wc-error-title serif",children:"Failed to load material"}),e.jsx("p",{className:"wc-error-message",children:Et}),e.jsxs("div",{className:"wc-error-actions",children:[e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:()=>window.location.reload(),children:"Retry"}),e.jsxs("button",{type:"button",className:"wc-hero-link",onClick:a,children:[e.jsx("span",{className:"arrow","aria-hidden":"true",children:"â"})," Back to library"]})]})]})});if(!je&&!ee)return null;if(!je&&ee&&ee.processing_status!=="completed"){const S=ee.processing_status==="processing",z=!s&&!r&&(ee.processing_status==="processing"||ee.processing_status==="pending"),Z=se?.currentStep,ie=typeof se?.progress=="number"?Math.max(0,Math.min(100,se.progress)):null;return e.jsx("div",{className:"wc-root im-logged",children:e.jsx("div",{className:`reader-theater ${p} min-h-screen flex items-center justify-center p-6`,children:e.jsx("div",{className:"theater-panel max-w-md w-full p-8 text-center space-y-5",children:e.jsxs("div",{style:{position:"relative",zIndex:1},className:"space-y-5",children:[e.jsxs("div",{className:"theater-rail-eyebrow justify-center",children:[e.jsx("span",{className:"num jp",children:"å¦"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:S?"Processing":"Not Ready"}),e.jsx("span",{className:"jp",children:S?"å¦çä¸":"æªæºå"})]}),S?g?e.jsx(Kt,{name:"book",size:40,className:"mx-auto"}):e.jsx(bs,{image:cs,size:112,duration:1.2,repeatDelay:999}):e.jsx(Kt,{name:"warning",size:40,className:"mx-auto"}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"text-xl serif",style:{fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:S?"Processing Material":"Material Not Ready"}),e.jsx("p",{style:{color:"var(--theater-text-soft)"},children:S?"Your material is being processed. This usually takes a few minutes.":`Status: ${ee.processing_status}`})]}),z&&e.jsxs("div",{className:"space-y-2",role:"status","aria-live":"polite",children:[e.jsx("p",{style:{color:"var(--theater-text-muted)",fontFamily:"'JetBrains Mono', monospace",fontSize:11,letterSpacing:"0.2em",textTransform:"uppercase"},children:Oe?"Status check paused":Z?`${Z}${ie!==null?` · ${ie}%`:""}`:"Checking statusâ¦"}),!Oe&&ie!==null&&ie>0&&e.jsx("div",{style:{height:4,borderRadius:"var(--wc-radius-ink)",background:"var(--theater-surface-hover)",overflow:"hidden"},"aria-hidden":"true",children:e.jsx("div",{style:{height:"100%",width:`${ie}%`,background:"hsl(var(--module-accent))",borderRadius:"var(--wc-radius-ink)",transition:"width 400ms cubic-bezier(0.22, 1, 0.36, 1)"}})}),e.jsx("p",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:Oe?"Couldn't reach the server for an update. Your material keeps processing in the background.":"This page opens by itself the moment it finishes â no need to reload."})]}),e.jsxs("div",{className:"flex items-center justify-center gap-3 flex-wrap",children:[e.jsxs("button",{type:"button",onClick:a,className:"theater-btn theater-btn--primary",children:[e.jsx(Kt,{name:"arrow-left",size:24}),"Back to Library"]}),z&&e.jsxs("button",{type:"button",onClick:()=>{pt(!1),ct(ce=>ce+1)},className:"theater-btn theater-btn--secondary",children:[e.jsx(Kt,{name:"refresh",size:24}),"Check now"]})]})]})})})})}if(!je&&D.length===0)return e.jsx("div",{className:"wc-root im-logged",children:e.jsx("div",{className:`reader-theater ${p} min-h-screen flex items-center justify-center p-6`,children:e.jsx("div",{className:"theater-panel max-w-md w-full p-8 text-center space-y-5",children:e.jsxs("div",{style:{position:"relative",zIndex:1},className:"space-y-5",children:[e.jsxs("div",{className:"theater-rail-eyebrow justify-center",children:[e.jsx("span",{className:"num jp",children:"空"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"No Pages"}),e.jsx("span",{className:"jp",children:"é ãªã"})]}),e.jsx(Kt,{name:"book",size:40,className:"mx-auto"}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"text-xl serif",style:{fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:"No Pages Available"}),e.jsx("p",{style:{color:"var(--theater-text-soft)"},children:"This material doesn't have any readable pages yet."})]}),e.jsxs("button",{type:"button",onClick:a,className:"theater-btn theater-btn--primary",children:[e.jsx(Kt,{name:"arrow-left",size:24}),"Back to Library"]})]})})})});const Ye=D[fe],dt=()=>{const S=Yt;return e.jsxs("div",{className:"space-y-5",children:[e.jsxs(rl,{title:"Display",icon:"eye",children:[e.jsx(_n,{label:"Text Analysis",description:"NLP annotations & grammar lookups",checked:Na,onChange:z=>{Da(z),s||ne("immersion_setting_changed",{setting:"annotations",value:z,previous:Na})}}),e.jsx(_n,{label:"Show Furigana",description:"Reading aids above kanji",checked:wa,onChange:z=>{Wt(z),s||ne("immersion_setting_changed",{setting:"furigana",value:z,previous:wa})}}),me&&e.jsx(_n,{label:"Vocabulary Colors",description:"New = blue · Learning = amber · Known = plain",checked:ua,onChange:z=>{ca(z),s||ne("immersion_setting_changed",{setting:"known_coloring",value:z,previous:ua})}}),c&&!s&&e.jsx(_n,{label:"Grammar progress",description:"Blue dots · amber dashes · green solid",checked:ha,onChange:z=>{za(z),ne("immersion_setting_changed",{setting:"grammar_progress",value:z,previous:ha})}}),e.jsx(_n,{label:"Text Overlay",description:"Show processed text on image",checked:kt,onChange:Ve}
63),e.jsx(_n,{label:"Background Mask",description:"Theme-colored layer behind text",checked:gt,onChange:I}),e.jsxs("div",{className:"pt-2",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("span",{className:"text-sm",style:{color:S.textSecondary},children:"Overlay Opacity"}),e.jsxs("span",{className:"text-xs font-mono px-2 py-0.5 rounded-[var(--wc-radius-ink)]",style:{color:S.textMuted,backgroundColor:S.buttonBg},children:[Math.round(At*100),"%"]})]}),e.jsx(Jy,{value:[At],onValueChange:([z])=>Jt(z),max:1,min:.1,step:.1,className:"w-full"})]})]}),e.jsxs(rl,{title:"View",icon:"zoom",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:Ie,className:"theater-btn theater-btn--secondary flex-1",children:e.jsx(Kt,{name:"zoom-out",size:24})}),e.jsx("div",{className:"flex-1 text-center",children:e.jsxs("span",{className:"text-lg font-semibold",style:{color:"var(--theater-text)"},children:[Math.round(Be*100),"%"]})}),e.jsx("button",{onClick:at,className:"theater-btn theater-btn--secondary flex-1",children:e.jsx(Kt,{name:"zoom-in",size:24})})]}),e.jsx("div",{className:"grid grid-cols-3 gap-2 pt-2",children:[{label:"Fit",action:mt},{label:"Width",action:xt},{label:"100%",action:Ue}].map(z=>e.jsx("button",{onClick:z.action,className:"theater-btn theater-btn--secondary",children:z.label},z.label))}),e.jsxs("div",{className:"pt-2",children:[e.jsx("span",{className:"text-sm block mb-2",style:{color:"var(--theater-text-soft)"},children:"Image Quality"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:[{value:"1024w",label:"Optimized",desc:"Faster"},{value:"native",label:"Native",desc:"Full res"}].map(z=>{const Z=la===z.value;return e.jsxs("button",{onClick:()=>Dt(z.value),className:`theater-btn ${Z?"theater-btn--primary":"theater-btn--secondary"} flex-col items-start text-left`,style:{minHeight:50,padding:"6px 10px"},"aria-pressed":Z,children:[e.jsx("span",{className:"text-sm font-medium block",children:z.label}),e.jsx("span",{className:"text-xs opacity-80",children:z.desc})]},z.value)})})]}),e.jsx(_n,{label:"Drag to Pan",description:"Click and drag to move image",checked:xa,onChange:ma})]}),e.jsx(ih,{isDark:u,onToggleDarkMode:()=>{h(),s||ne("immersion_setting_changed",{setting:"theme",value:u?"light":"dark",previous:u?"dark":"light"})}}),e.jsxs(rl,{title:"Reading",icon:"book",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-sm block mb-2",style:{color:"var(--theater-text-soft)"},children:"Page Direction"}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:[{value:"ltr",label:"Left â Right",desc:"Western"},{value:"rtl",label:"Right â Left",desc:"Manga"}].map(z=>{const Z=Ne===z.value;return e.jsxs("button",{onClick:()=>{tt(z.value),s||ne("immersion_setting_changed",{setting:"reading_direction",value:z.value,previous:Ne})},className:`theater-btn ${Z?"theater-btn--primary":"theater-btn--secondary"} flex-col items-start text-left`,style:{minHeight:50,padding:"6px 10px"},"aria-pressed":Z,children:[e.jsx("span",{className:"text-sm font-medium block",children:z.label}),e.jsx("span",{className:"text-xs opacity-80",children:z.desc})]},z.value)})})]}),e.jsx(_n,{label:"Auto-hide Controls",description:"Fade the toolbar while reading; tap to show",checked:Mt,onChange:z=>{Ma(z),s||ne("immersion_setting_changed",{setting:"auto_hide_chrome",value:z,previous:Mt})}})]}),e.jsxs("details",{className:"group",children:[e.jsxs("summary",{className:"flex items-center gap-2 cursor-pointer text-sm transition-colors py-1",style:{color:"var(--theater-text-soft)"},children:[e.jsx(Kt,{name:"chevron-right",size:24,className:"transition-transform group-open:rotate-90"}),"Keyboard Shortcuts"]}),e.jsx("div",{className:"mt-2 space-y-1.5 pl-6",children:[{combo:"â / â",desc:"Navigate pages"},{combo:"O",desc:"Toggle overlay"},{combo:"F",desc:"Fit to screen"},{combo:"ESC",desc:"Back to library"}].map(z=>e.jsxs("div",{className:"flex items-center gap-2 text-xs",children:[e.jsx("kbd",{className:"px-1.5 py-0.5 border",style:{background:"var(--theater-surface-hover)",borderColor:"var(--theater-surface-border)",color:"var(--theater-text-soft)",borderRadius:"var(--wc-radius-ink)",fontFamily:"'JetBrains Mono', monospace"},children:z.combo}),e.jsx("span",{style:{color:"var(--theater-text-muted)"},children:z.desc})]},z.combo))})]})]})};return e.jsx("div",{className:"wc-root im-logged",children:e.jsxs("div",{className:`reader-theater mobile-viewport-takeover z-[100] ${p}`,"data-mobile-viewport-surface":"manga-reader",style:Zn,...s?{"data-tour-id":"demo-reader-page"}:{},children:[Vs&&e.jsx(Mo,{restore:Fs,title:"Local images missing",filenameHint:ee?.original_filename??null,detailHint:ee?`${ee.total_pages} pages`:null,dismissable:!0,onClose:Mr}),e.jsx(Oa,{children:us&&e.jsx(ze.div,{className:"mobile-viewport-takeover fixed inset-0 z-[23
630]","data-mobile-viewport-surface":"manga-crop",initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},transition:{duration:g?0:.16},children:e.jsx(Zy,{imageUrl:us.imageUrl,initialBounds:us.initialBounds,onConfirm:Tr,onCancel:Dn})},us.sourceKey)}),e.jsx("div",{ref:qa,className:"mobile-viewport-safe-top fixed top-0 inset-x-0 z-50 pointer-events-none","aria-hidden":It,children:e.jsx(ze.button,{type:"button",onClick:a,className:"theater-chrome-icon-btn theater-chrome-icon-btn--floating pointer-events-auto","aria-label":"Back",animate:{opacity:It?0:1},transition:{duration:.35,ease:"easeInOut"},style:{pointerEvents:It?"none":"auto"},children:e.jsx(Kt,{name:"arrow-left",size:24})})}),e.jsx(Oa,{children:M&&e.jsx(ze.div,{initial:{opacity:0,y:-20},animate:{opacity:1,y:0},exit:{opacity:0,y:-20},transition:{duration:.5},className:"absolute left-1/2 transform -translate-x-1/2 z-40",style:{top:"max(1rem, var(--safe-area-top))"},onClick:()=>H(!0),children:e.jsx("div",{className:"theater-panel px-6 py-3",children:e.jsxs("div",{className:"text-center",style:{color:"var(--theater-text)"},children:[e.jsx("h1",{className:"text-lg serif",style:{fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:ee?.title}),ee?.title_jp&&e.jsx("p",{className:"text-sm opacity-70 jp",style:{fontFamily:"var(--font-jp, sans-serif)"},children:ee.title_jp})]})})})}),e.jsx(Oa,{children:ta&&e.jsxs(e.Fragment,{children:[e.jsx(ze.div,{initial:{opacity:0}
63,animate:{opacity:1},exit:{opacity:0},className:"fixed inset-0 z-40 theater-scrim",onClick:()=>zt(!1)}),e.jsx(ze.div,{initial:{opacity:0,scale:.9,y:30},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.9,y:30},transition:{type:"spring",damping:25,stiffness:300},className:"mobile-viewport-modal-stage fixed inset-0 z-[200] flex items-center justify-center","data-mobile-viewport-surface":"manga-reader-settings",onClick:()=>zt(!1),children:e.jsxs("div",{ref:hn,role:"dialog","aria-modal":"true","aria-label":"Reader settings",tabIndex:-1,className:"mobile-viewport-modal-panel theater-panel w-full max-w-[380px] flex flex-col overflow-hidden outline-none",onClick:S=>S.stopPropagation(),children:[e.jsxs("div",{className:"theater-pencil-rule-bottom flex items-center justify-between px-5 pt-5 pb-3",style:{position:"relative",zIndex:1},children:[e.jsxs("div",{className:"theater-rail-eyebrow",style:{marginBottom:0},children:[e.jsx("span",{className:"num jp",children:"è¨"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Settings"}),e.jsx("span",{className:"jp",children:"è¨å®"})]}),e.jsx("button",{type:"button",onClick:()=>zt(!1),className:"theater-chrome-icon-btn reader-control-unframed","aria-label":"Close settings",children:e.jsx(Kt,{name:"close",size:24})})]}),e.jsx("div",{"data-mobile-viewport-modal-body":!0,className:"flex-1 overflow-y-auto p-4 space-y-4",style:{position:"relative",zIndex:1},children:dt()})]})})]})}),e.jsx("div",{className:"absolute inset-0 overflow-auto",children:e.jsxs("div",{className:"relative w-full h-full",children:[je&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center","aria-hidden":"true",children:g?e.jsx(Kt,{name:"book",size:40,style:{opacity:.6}}):e.jsx(bs,{image:cs,size:144,duration:1.2,repeatDelay:999})}),e.jsx("div",{ref:Q,className:"absolute shadow-2xl",style:{left:"50%",top:"50%",transform:`translate(calc(-50% + ${E.x}px), calc(-50% + ${E.y}px)) scale(${Be})`,transformOrigin:"center center",cursor:xa?re?"grabbing":"grab":"default",touchAction:"none"},children:Ye&&e.jsxs("div",{className:"relative",style:{width:`${Ye.width}px`,height:`${Ye.height}px`,backgroundImage:Ye.imageUrl?`url("${Ye.imageUrl}")`:"none",backgroundColor:Ye.imageUrl?void 0:"var(--theater-bg)",backgroundSize:"contain",backgroundRepeat:"no-repeat",backgroundPosition:"center",overflow:"hidden"},children:[!Ye.imageUrl&&Ye.cloudBacked&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center text-center p-8","aria-live":"polite",children:ts?e.jsxs("div",{className:"space-y-3",children:[e.jsx(Kt,{name:"warning",size:40,className:"mx-auto opacity-40"}),e.jsx("p",{className:"text-sm font-medium opacity-80",children:"Couldn't load this page"}),e.jsxs("div",{className:"flex flex-col items-center gap-2",children:[e.jsx("button",{type:"button",onClick:()=>{Ra(!1),fs.current++,La(S=>S+1)},className:"theater-btn theater-btn--primary",children:"Retry"}),e.jsx("button",{type:"button",onClick:Bn,className:"theater-btn theater-btn--secondary",children:"Re-import from file"})]})]}):Rt&&!g?e.jsx("div",{"aria-hidden":"true",children:e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999})}):Rt?e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Loadingâ¦"}):null}),!Ye.imageUrl&&Ye.localOnly&&!Ye.cloudBacked&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center text-center p-8",children:e.jsxs("div",{className:"space-y-3",children:[e.jsx(Kt,{name:"folder",size:40,className:"mx-auto opacity-40"}),e.jsx("p",{className:"text-sm font-medium opacity-80",children:"Images not available locally"}),Fs.status==="working"?e.jsxs("div",{className:"flex flex-col items-center justify-center gap-2 text-xs opacity-70",children:[g?e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Restoringâ¦"}):e.jsx(bs,{image:cs,size:72,duration:1.1,repeatDelay:999}),Fs.progress]}):e.jsx("button",{type:"button",onClick:Bn,className:"theater-btn theater-btn--primary",children:"Select original file to restore"})]})}),St&&($a()?e.jsxs("div",{role:"button",tabIndex:0,"aria-label":"View plans for more shared credits",className:"absolute top-2 left-1/2 -translate-x-1/2 z-10 px-3 py-1.5 text-xs font-medium flex items-center gap-1.5 cursor-pointer transition-colors",style:{background:"var(--theater-surface)",color:"var(--theater-text)",border:"1px solid var(--theater-surface-border)",borderRadius:"var(--wc-radius-leaf)"},onClick:()=>O("enrichment","quota_exceeded"),onKeyDown:S=>{(S.key==="Enter"||S.key===" ")&&(S.preventDefault(),O("enrichment","quota_exceeded"))},children:[e.jsx(Kt,{name:"crown",size:12}),"Plain text â Shared credits needed for full analysis"]}):e.jsx("div",{className:"absolute top-2 left-1/2 -translate-x-1/2 z-10 px-3 py-1.5 text-xs font-medium flex items-center gap-1.5",style:{background:"var(--theater-surface)",color:"var(--theater-text)",border:"1px solid var(--theater-surface-border)",borderRadius:"var(--wc-radius-leaf)"},children:"Plain text"})),i&&yt===Ye.pageNumber&&e.jsx(Gb,{ref:qt,active:K&&!aa,materialId:t,pageNumber:Ye.pageNumber,pageWidth:Ye.width,pageHeight:Ye.height,boxes:U,theaterThemeClass:p,onActiveChange:_t}),kt&>&&U.length>0&&e.jsx("div",{className:"absolute inset-0",style:{pointerEvents:"none"},children:U.flatMap(S=>{if(Nd({baseFontSize:Math.max(12,Math.min(32,S.rendering_data?.font_size||16)),orientation:S.orientation,lines:S.rendering_data?.lines||S.text.split(` 64`),linesCoords:S.rendering_data?.lines_coords,boxWidthPx:S.w_norm*Ye.width,boxHeightPx:S.h_norm*Ye.height}))return[];const z=S.orientation==="vertical",Z=z?2:1.3,ie=z?1.3:2;if(S.rendering_data?.lines_coords&&S.rendering_data.lines&&S.rendering_data.lines_coords.length>0)return S.rendering_data.lines_coords.map((He,We)=>{const Vt=He.map(zo=>zo[0]),wt=He.map(zo=>zo[1]),ra=Math.min(...Vt),Bt=Math.max(...Vt),Qt=Math.min(...wt),ya=Math.max(...wt),_s=Math.max(1,Math.round(Bt-ra)),_i=Math.max(1,Math.round(ya-
64Qt)),Pr=Math.min(Ye.width,Math.round(_s*Z)),kn=Math.min(Ye.height,Math.round(_i*ie)),sd=Math.max(0,Math.round(ra-(Pr-_s)/2)),nd=Math.max(0,Math.round(Qt-(kn-_i)/2)),Mp=Math.min(Ye.width-sd,Pr),Pp=Math.min(Ye.height-nd,kn);return e.jsx("div",{className:"absolute",style:{left:`${sd}px`,top:`${nd}px`,width:`${Mp}px`,height:`${Pp}px`,backgroundColor:xe}},`mask-${S.id}-line-${We}`)});const ce=1.08,Ce=Math.round(S.x_norm*Ye.width),$e=Math.round(S.y_norm*Ye.height),et=Math.round(S.w_norm*Ye.width),ot=Math.round(S.h_norm*Ye.height),ht=Math.min(Ye.width,Math.round(et*ce)),we=Math.min(Ye.height,Math.round(ot*ce)),Ee=Math.max(0,Math.round(Ce-(ht-et)/2)),De=Math.max(0,Math.round($e-(we-ot)/2)),Te=Math.min(Ye.width-Ee,ht),Se=Math.min(Ye.height-De,we);return[e.jsx("div",{className:"absolute",style:{left:`${Ee}px`,top:`${De}px`,width:`${Te}px`,height:`${Se}px`,backgroundColor:xe}},`mask-${S.id}`)]})}),kt&&U.length>0&&e.jsx("div",{className:`absolute inset-0 overlay-always ${K?"bubble-listening-lookup-disabled":""}`,children:U.map(S=>{const z=S.rendering_data?.font_size||16,Z=Math.max(12,Math.min(32,z)),ie=S.rendering_data?.lines||S.text.split(` 65`);if(Nd({baseFontSize:Z,orientation:S.orientation,lines:ie,linesCoords:S.rendering_data?.lines_coords,boxWidthPx:S.w_norm*Ye.width,boxHeightPx:S.h_norm*Ye.height}))return null;const ce=er.get(S.id)??[],Ce=Ln.get(S.id)??new Map,$e={},et=Se=>({role:"button",tabIndex:K?-1:0,"aria-label":Se,onKeyDown:He=>{(He.key==="Enter"||He.key===" ")&&(He.preventDefault(),qe(S,He))}});if(S.rendering_data?.lines_coords&&S.rendering_data.lines&&S.rendering_data.lines_coords.length>0)return S.rendering_data.lines.map((He,We)=>{const Vt=S.rendering_data?.lines_coords?.[We];if(!Vt||Vt.length===0)return null;const wt=Vt.map(kn=>kn[0]),ra=Vt.map(kn=>
65kn[1]),Bt=Math.min(...wt),Qt=Math.max(...wt),ya=Math.min(...ra),_s=Math.max(...ra),_i=ce[We]?.rendererTokens??[],Pr=Nl(Z,He,S.orientation==="vertical"?_s-ya:Qt-Bt);return e.jsx("div",{"data-box-id":S.id,...et(S.text),className:"textBox absolute cursor-pointer",style:{left:`${Bt}px`,top:`${ya}px`,width:`${Qt-Bt}px`,height:`${_s-ya}px`,fontSize:`${Pr.size}px`,overflow:Pr.clip?"hidden":void 0,writingMode:S.orientation==="vertical"?"vertical-rl":"horizontal-tb",textOrientation:S.orientation==="vertical"?"upright":"mixed",lineHeight:"1.1",padding:"0",border:"none",whiteSpace:"nowrap",display:"flex",alignItems:"center",justifyContent:"center",fontFamily:'"Noto Sans CJK JP","Hiragino Sans","Yu Gothic","Meiryo",sans-serif',...$e},onClick:kn=>qe(S,kn),children:rt(S,He,_i,`${S.id}-inner-${We}`,Ce)},`${S.id}-line-${We}`)});const ot=Math.round(S.x_norm*Ye.width),ht=Math.round(S.y_norm*Ye.height),we=Math.round(S.w_norm*Ye.width),Ee=Math.round(S.h_norm*Ye.height),De=ie.reduce((Se,He)=>He.length>Se.length?He:Se,""),Te=Nl(Z,De,
65S.orientation==="vertical"?Ee:we);return e.jsx("div",{"data-box-id":S.id,...et(S.text),className:"textBox absolute cursor-pointer",style:{left:`${ot}px`,top:`${ht}px`,width:`${we}px`,height:`${Ee}px`,fontSize:`${Te.size}px`,overflow:Te.clip?"hidden":void 0,writingMode:S.orientation==="vertical"?"vertical-rl":"horizontal-tb",textOrientation:S.orientation==="vertical"?"upright":"mixed",lineHeight:"1.1",padding:"0",border:"none",whiteSpace:"nowrap",fontFamily:'"Noto Sans CJK JP","Hiragino Sans","Yu Gothic","Meiryo",sans-serif',...$e},onClick:Se=>qe(S,Se),children:ie.map((Se,He)=>rt(S,Se,ce[He]?.rendererTokens??[],He,Ce))},S.id)})}),aa&&e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",style:{background:"var(--theater-scrim)"},"aria-live":"polite",children:g?e.jsx("div",{className:"theater-panel px-4 py-2 text-sm",style:{color:"var(--theater-text-soft)"},children:"Loading textâ¦"}):e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999})})]})})]})}),e.jsx("div",{ref:F,className:"mobile-viewport-safe-bottom fixed bottom-0 left-0 right-0 z-50 flex justify-center pointer-events-none","aria-hidden":It,children:e.jsxs(ze.div,{initial:{y:20,opacity:0},animate:{y:It?24:0,opacity:It?0:1},transition:{delay:.2,type:"spring",stiffness:300,damping:30},className:"theater-chrome-bar pointer-events-auto",style:{pointerEvents:It?"none":"auto"},children:[e.jsx("button",{type:"button",onClick:ge,disabled:Je,className:"theater-chrome-icon-btn","aria-label":bt,children:e.jsx(Kt,{name:"chevron-left",size:24})}),e.jsxs("div",{className:"theater-chrome-bar-counter",children:[e.jsx(Kt,{name:"book",size:14}),e.jsxs("span",{className:"tabular-nums",children:[fe+1,e.jsx("span",{style:{opacity:.5},children:" / "}),D.length]})]}),e.jsx("button",{type:"button",onClick:be,disabled:nt,className:"theater-chrome-icon-btn","aria-label":st,children:e.jsx(Kt,{name:"chevron-right",size:24})}),e.jsx("div",{className:"theater-chrome-bar-divider","aria-hidden":"true"}),i&&e.jsx(Nb,{active:K,status:"stopped",onToggle:()=>{K&&qt.current?.stop(),_t(S=>!S)}}),Ts&&Ms&&!Vs&&e.jsx("button",{type:"button",onClick:Bn,className:"theater-chrome-icon-btn","aria-label":"Restore local images",title:"Restore local images",children:e.jsx(Kt,{name:"storage",size:24})}),e.jsx("button",{type:"button",onClick:h,className:"theater-chrome-icon-btn","aria-label":u?"Switch to light mode":"Switch to dark mode",children:e.jsx(Kt,{name:u?"sun":"moon",size:24})}),e.jsx("button",{type:"button",onClick:S=>{S.stopPropagation(),zt(!ta)},className:`theater-chrome-icon-btn ${ta?"is-active":""}`,"aria-label":"Settings","aria-pressed":ta,children:e.jsx(Kt,{name:"settings",size:24})})]})}),C&&e.jsx("div",{...s?{"data-tour-id":"demo-token-panel"}:{},children:e.jsx(lc,{token:s?_b(C):C,position:le,writingMode:le?.writingMode,isLoading:it,onClose:oa,deckApi:m,mediaSourceContext:Es,isMediaContextPaid:A,onMediaContextUpgrade:$a()?()=>O("source_memory","single_word_save"):void 0,grammarKnowledgeApi:!s&&c?pa:void 0,aiHelpApi:Ja,richLookupApi:s?kb:ea,kanjiDetailApi:s?void 0:Ea,mnemonicsApi:!s&&c?Ac:void 0,onOpenWord:s?void 0:jr.onOpenWord,onOpenKanji:s?void 0:jr.onOpenKanji,onDeckToggle:S=>{S&&!s&&(T.current++,ne("immersion_word_added_to_deck",{material_type:"manga",source:"manga_bubble"}))},onUnauthorizedAction:r&&!c?()=>d("signup"):void 0})}),s&&e.jsx(nx,{textBoxes:U,containerRef:Q,zoom:Be})]})})}const rx=[],Hd=[];function Mi(t){const a=[],s=/[^ãï¼ï¼!?ã]*[ãï¼ï¼!?ã]/g;let n;for(;(n=s.exec(t))!==null;){const l=n[0],c=l.trim();if(c){const d=l.length-l.trimStart().length;a.push({text:c,startChar:n.index+d})}}const r=a.length>0?a[a.length-1].startChar+a[a.length-1].text.length:0,i=t.slice(r).trim();return i&&a.push({text:i,startChar:r}),a}function ix({materialId:t,onBack:a}){const{getAccessToken:s,user:n}=ps(),r=o.useMemo(()=>Yl(s),[s]),{isDark:i,toggleTheme:l,theaterThemeClass:c}=mc(),{openUpgradeModal:d}=xn(),{isPro:m,refresh:u}=Xn(),h=Pc(s,u);o.useEffect(()=>{h.quotaExceeded&&$a()&&d("ai_help","quota_exceeded")},[h.quotaExceeded,d]);
65const[p,g]=o.useState(null),[f,b]=o.useState([]),[y,x]=o.useState([]),[v,w]=o.useState(new Set),[j,T]=o.useState(!0),[P,N]=o.useState(null),[_,L]=o.useState(null),[q,O]=o.useState(0),[A,k]=o.useState(!1),[J,M]=o.useState(!1),[H,ee]=o.useState(!0),[Pe,D]=o.useState(!1),[de,fe]=o.useState(!1);o.useEffect(()=>{const E=setTimeout(()=>ee(!1),3e3);return()=>clearTimeout(E)},[]);const[Me,U]=o.useState(!0),ve=o.useRef(void 0),yt=o.useRef(null),ut=o.useCallback(()=>{U(!0),ve.current&&clearTimeout(ve.current),ve.current=setTimeout(()=>U(!1),3e3)},[]);o.useEffect(()=>(window.addEventListener("mousemove",ut),window.addEventListener("scroll",ut,{passive:!0}),window.addEventListener("touchstart",ut,{passive:!0}),window.addEventListener("keydown",ut),ut(),()=>{window.removeEventListener("mousemove",ut),window.removeEventListener("scroll",ut),window.removeEventListener("touchstart",ut),window.removeEventListener("keydown",ut),ve.current&&clearTimeout(ve.current)}),[ut]),o.useEffect(()=>{(A||J)&&(U(!0),ve.current&&clearTimeout(ve.current))},[A,J]),o.useEffect(()=>{const E=yt.current;E&&(Me?E.removeAttribute("inert"):E.setAttribute("inert",""))},[Me]),o.useEffect(()=>{const E=A?qt.current:J?sa.current:null;E?(la.current=document.activeElement??null,(E.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')??E).focus()):la.current&&(la.current.focus(),la.current=null)},[A,J]);const[St,je]=o.useState(()=>{const E=localStorage.getItem("novelReader.fontSize");return E?parseInt(E,10):18}),[lt,Et]=o.useState(()=>{const E=localStorage.getItem("novelReader.lineSpacing");return E?parseFloat(E):1.8}),[Ct,aa]=o.useState(()=>{const E=localStorage.getItem("novelReader.annotationsEnabled");return E!==null?E!=="false":localStorage.getItem("reading.annotationsDefault")!=="false"}),[vt,Le]=o.useState(()=>localStorage.getItem("novelReader.showFurigana")==="true"),[jt,Ft]=o.useState(()=>localStorage.getItem("novelReader.showKnownColoring")==="true"),[ct,se]=Cc(),ft=o.useMemo(()=>rc(),[]),Oe=o.useMemo(()=>ic(),[]),pt=o.useMemo(()=>Jl(s,{offlineSrsPaidAccess:m}),[s,m]),kt=o.useMemo(()=>{const E=new Set;for(const G of y){if(!G)continue;const re=[G.processedData?.tokens??[],...(G.paragraphs??[]).map(pe=>pe.processedData?.tokens??[])];for(const pe of re)for(const te of pe)for(const Fe of dc(te,()=>!0))E.add(Fe)}return Array.from(E)},[y]),Ve=!!n&&ct,{knowledgeMap:Be}=oc(Ve?pt:void 0,kt),Ke=_m(t,jt,s),At=jt?"known":"none",[Jt,ta]=o.useState(()=>localStorage.getItem("novelReader.furiganaMode")==="perKanji"?"perKanji":"token"),[zt,K]=o.useState(()=>localStorage.getItem("novelReader.showSpacing")!=="false"),_t=wn(),qt=o.useRef(null),sa=o.useRef(null),la=o.useRef(null),[Dt,ba]=o.useState(0),da=o.useRef(!1),xa=o.useRef(0),ma=o.useRef(f),Na=o.useRef(0),Da=o.useRef([]),wa=o.useRef(new Set),[Wt,ua]=o.useState(!1),ca=o.useRef(!1),ha=o.useRef(!1),za=o.useRef(null),ea=o.useRef(null),Ea=o.useRef(Date.now()),pa=o.useRef(0),Ca=o.useRef(0),Gt=o.useRef(0),Ba=o.useRef(!1),ka=o.useRef(!1),Wa=o.useRef(new Set),es=o.useCallback(async(E,G,re,pe)=>{const te=await lo(E);if(re?.())return 0;const Fe=Lm(te,pe);let ke;if(Fe==="kindle"){const{checkKindleDrm:Y,extractKindleChapters:Ze}=await Rs(async()=>{const{checkKindleDrm:Ot,extractKindleChapters:is}=await Promise.resolve().then(()=>Gm);return{checkKindleDrm:Ot,extractKindleChapters:is}},void 0);if(re?.())return 0;const Ut=await Y(E);if(re?.())return 0;if(!Ut.ok)throw new Error("This Kindle file canât be read (copy-protected or corrupted).");ke=await Ze(new File([E],G,{type:"application/octet-stream"}))}else ke=await oo(new File([E],G,{type:"application/epub+zip"}));if(re?.())return 0;const Qe=ke.map(Y=>({chapterNumber:Y.order,chapterTitle:Y.title,paragraphCount:Y.paragraphs.length}));return b(Qe),za.current=ke.map(Y=>({materialId:t,chapterNumber:Y.order,chapterTitle:Y.title,paragraphs:Y.paragraphs.map((Ze,Ut)=>({id:`local-${Y.order}-${Ut}`,index:Ut,text:Ze,type:"text",tokens:[],processedData:null}))})),Qe.length},[t]),Ta=To({material:{id:t,content_type:p?.content_type??"novel",file_type:p?.file_type??"epub",total_pages:p?.total_pages??null,content_sha256:p?.content_sha256??null,original_filename:p?.original_filename??null,file_size_bytes:p?.file_size_bytes??null},onRestored:async()=>{const E=await gr(t);if(E){T(!0);try{const G=await es(E.blob,E.filename,void 0,E.format);D(!1),Ba.current||(Ba.current=!0,Ea.current=Date.now(),ne("immersion_session_started",{material_type:"novel",nlp_annotated:!1,page_count:G}))}
65catch(G){N(G instanceof Error?G.message:"Failed to load novel")}finally{T(!1)}}}}),va=o.useRef(new WeakMap),ia=o.useCallback(E=>{if(!E||E.length===0)return rx;const G=va.current,re=G.get(E);if(re)return re;const pe=E.map(cc);return G.set(E,pe),pe},[]),{selectedToken:oe,tokenPanelPosition:me,tokenPanelLoading:Ge,loadPageTokens:gt,handleNLPTokenClick:I,closeTokenPanel:xe}=Ec({materialId:t,getAccessToken:s,currentPageNumber:f[Dt]?.chapterNumber});o.useEffect(()=>{localStorage.setItem("novelReader.annotationsEnabled",String(Ct))},[Ct]),o.useEffect(()=>{localStorage.setItem("novelReader.fontSize",St.toString())},[St]),o.useEffect(()=>{localStorage.setItem("novelReader.lineSpacing",lt.toString())},[lt]),o.useEffect(()=>{localStorage.setItem("novelReader.showFurigana",vt.toString())},[vt]),o.useEffect(()=>{localStorage.setItem("novelReader.showKnownColoring",jt.toString())},[jt]),o.useEffect(()=>{localStorage.setItem("novelReader.furiganaMode",Jt)},[Jt]),o.useEffect(()=>{localStorage.setItem("novelReader.showSpacing",String(zt))},[zt]),o.useEffect(()=>{let E=!1;const G=new AbortController;return(async()=>{try{T(!0);const pe=await s(),te=await fetch(`${ue()}/api/reading/materials/${t}`,{headers:{Authorization:`Bearer ${pe}`},signal:G.signal});if(!te.ok)throw new Error("Failed to fetch material");const Fe=await te.json();if(E)return;g(Fe);let ke=0;if(Fe.processing_status==="local_only"){ha.current=!0;let Qe=await gr(t);if(E)return;if(!Qe){if(Fe.cloud_sync_status==="synced"){try{const Y=await gc(ny(t,s),is=>{E||fe(is)},fc);if(E)return;const Ze=await lo(Y);if(E)return;const Ut=Ze==="kindle"?"kindle":"epub",Ot=Fe.original_filename??`${t}.${Ut==="kindle"?"mobi":"epub"}`;await bc(t,new File([Y],Ot,{type:"application/octet-stream"}),Ut),Qe=await gr(t)}catch(Y){if(Y instanceof Hs||Y instanceof Error){E||(D(!0),T(!1));return}throw Y}if(E)return}if(!Qe){D(!0),T(!1);return}}if(ke=await es(Qe.blob,Qe.filename,()=>E,Qe.format),E)return}else{ha.current=!1;const Qe=await fetch(`${ue()}/api/reading/novels/${t}/chapters`,{headers:{Authorization:`Bearer ${pe}`},signal:G.signal});if(!Qe.ok)throw new Error("Failed to fetch chapters");const Y=await Qe.json();if(E)return;b(Y.chapters),ke=Y.chapters?.length??0}Ba.current||(Ba.current=!0,Ea.current=Date.now(),ne("immersion_session_started",{material_type:"novel",nlp_annotated:Fe.processing_status==="completed",page_count:ke})),T(!1)}catch(pe){if(E||pe instanceof DOMException&&pe.name==="AbortError")return;N(pe instanceof Error?pe.message:"Failed to load novel"),T(!1)}})(),()=>{E=!0,G.abort()}},[t,s,es]),o.useEffect(()=>{const E=()=>{if(!Ba.current||ka.current)return;ka.current=!0;const G=Ea.current,re=Date.now(),pe=re-G,te=Gt.current,Fe=pa.current;ne("immersion_session_ended",{material_type:"novel",pages_read:te,session_duration_ms:pe,tokens_clicked:Fe,words_added_to_deck:Ca.current}),(async()=>{try{const ke=await s();if(!ke)return;await fetch(`${ue()}/api/immersion/sessions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${ke}`},body:JSON.stringify({materialId:t,materialType:"novel",startedAt:new Date(G).toISOString(),endedAt:new Date(re).toISOString(),durationMs:pe,pagesRead:te,tokensClicked:Fe}),keepalive:!0})}catch{}})()};return window.addEventListener("pagehide",E),()=>{window.removeEventListener("pagehide",E),E()}},[t]),o.useEffect(()=>{wa.current=v},[v]);const Ne=o.useCallback(async(E,G)=>{const re=ma.current,pe=E.filter(Y=>Y>=0&&Y<re.length&&!wa.current.has(Y));if(pe.length===0)return!0;const te=await s(),Fe=await Promise.allSettled(pe.map(async Y=>{const Ze=re[Y],Ut=await fetch(`${ue()}/api/reading/novels/${t}/chapters/${Ze.chapterNumber}`,{headers:{Authorization:`Bearer ${te}`},signal:G});if(!Ut.ok)throw new Error(`Chapter ${Ze.chapterNumber} failed (${Ut.status})`);const Ot=await Ut.json();if(!Ot||typeof Ot.chapterNumber!="number")throw new Error(`Chapter ${Ze.chapterNumber} returned a non-chapter payload`);return{index:Y,data:Ot}}));if(G?.aborted)return!1;const ke=Fe.filter(Y=>Y.status==="fulfilled"),Qe=Fe.length-ke.length;if(ke.length>0){const Y=new Set(wa.current);ke.forEach(({value:Ze})=>Y.add(Ze.index)),wa.current=Y,x(Ze=>{const Ut=Ze.slice();return Ut.length=Math.max(Ut.length,re.length),ke.forEach(({value:Ot})=>{Ut[Ot.index]=Ot.data}),Ut}),w(Y);for(const{value:Ze}of ke)Ze.data?.chapterNumber!=null&>(Ze.data.chapterNumber)}if(Qe>0){const Y=Fe.find(Ze=>Ze.status==="rejected");return Y&&Y.reason?.name!=="AbortError"&&(console.error("Failed to load chapters:",Y.reason),L("Some chapters failed to load.")),!1}return L(null),!0},[t,s,gt]);o.useEffect(()=>{if(f.length===0)return;if(ha.current&&za.current){x(za.current),w(new Set(f.map((re,pe)=>pe)));return}const E=new AbortController,G=Math.min(7,f.length);return Ne(Array.from({length:G},(re,pe)=>pe),E.signal),()=>E.abort()},[f,Ne,q]),o.useEffect(()=>{if(ha.current)return;const E=new AbortController,G=()=>{const te=ma.current;if(te.length===0)return[];const Fe=new Set,ke=Math.max(0,Na.current);for(let Y=ke;Y<Math.min(ke+4,te.length);Y++)Fe.add(Y);const Qe=ea.current;if(Qe!=null)for(let Y=Math.max(0,Qe-1);Y<Math.min(Qe+4,te.length);Y++)Fe.add(Y);return[...Fe].filter(Y=>!wa.current.has(Y))},pe=setTimeout(async()=>
65{if(E.signal.aborted||ca.current)return;let te=G();if(te.length!==0){ca.current=!0,ua(!0);try{for(;te.length>0&&!E.signal.aborted&&await Ne(te,E.signal);)te=G()}finally{ca.current=!1,E.signal.aborted||ua(!1)}}},100);return()=>{clearTimeout(pe),E.abort()}},[Dt,f.length,Ne]),o.useEffect(()=>{ma.current=f},[f]),o.useEffect(()=>{Na.current=Dt},[Dt]),o.useEffect(()=>{const E=()=>{const te=xa.current,Fe=document.documentElement.scrollHeight,ke=document.documentElement.clientHeight,Qe=Fe>ke&&te>0?te/(Fe-ke)*100:0,Y=Na.current,Ze=document.getElementById(`chapter-${ma.current[Y]?.chapterNumber}`),Ut=Ze?Math.max(0,te-Ze.offsetTop):0;return{scrollY:te,progress:Qe,visibleChapter:Y,chapterNumber:ma.current[Y]?.chapterNumber,chapterOffset:Ut,timestamp:Date.now()}},G=()=>{if(!t||!da.current)return;const te=E();localStorage.setItem(`novelReader.position.${t}`,JSON.stringify(te)),lh(t,{position:te})},re=()=>{if(!t||!da.current)return;const te=E();localStorage.setItem(`novelReader.position.${t}`,JSON.stringify(te)),(async()=>{try{const Fe=await s();if(!Fe)return;await fetch(`${ue()}/api/reading/materials/${t}/position`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Fe}`},body:JSON.stringify({position:te}),keepalive:!0})}catch{}})()},pe=setInterval(G,5e3);return window.addEventListener("pagehide",re),window.addEventListener("beforeunload",re),()=>{clearInterval(pe),window.removeEventListener("pagehide",re),window.removeEventListener("beforeunload",re),da.current&&G()}},[t,s]),o.useEffect(()=>{if(!t)return;let E=!1,G=0,re;const pe=()=>{da.current=!0},te=ke=>{const Qe=typeof ke.chapterNumber=="number",Y=typeof ke.scrollY=="number";if(!Qe&&!Y){pe();return}Qe&&typeof ke.visibleChapter=="number"&&(ea.current=ke.visibleChapter,ba(ke.visibleChapter));const Ze=(Ut=0)=>{if(E)return;const Ot=Qe?document.getElementById(`chapter-${ke.chapterNumber}`):null;if(Ot){const is=Ot.offsetTop+Math.max(0,ke.chapterOffset??0);window.scrollTo({top:is,behavior:"auto"}),xa.current=is,ea.current=null,pe();return}if(!Qe){const is=document.documentElement.scrollHeight,os=document.documentElement.clientHeight;if(is-os>=ke.scrollY){window.scrollTo({top:ke.scrollY,behavior:"auto"}),xa.current=ke.scrollY,typeof ke.visibleChapter=="number"&&ba(ke.visibleChapter),pe();return}}Ut<30?re=setTimeout(()=>Ze(Ut+1),250):(ea.current=null,pe())};G=requestAnimationFrame(()=>{re=setTimeout(()=>Ze(0),300)})},Fe=localStorage.getItem(`novelReader.position.${t}`);if(Fe)try{return te(JSON.parse(Fe)),()=>{E=!0,cancelAnimationFrame(G),re&&clearTimeout(re)}}catch(ke){console.error("Failed to parse local position:",ke)}return bb(t).then(ke=>{E||(ke?.position?te(ke.position):re=setTimeout(()=>{E||pe()},1500))}),()=>{E=!0,cancelAnimationFrame(G),re&&clearTimeout(re)}},[t]),o.useEffect(()=>{Da.current=y},[y]),o.useEffect(()=>{if(!t)return;const E=()=>{xa.current=window.scrollY;const G=ma.current,re=Da.current;if(G.length===0)return;const pe=window.scrollY+200;let te=0;for(let Fe=0;Fe<re.length;Fe++){const ke=re[Fe];if(!ke)continue;const Qe=document.getElementById(`chapter-${ke.chapterNumber}`);Qe&&Qe.offsetTop<=pe&&(te=Fe)}ba(te)};return window.addEventListener("scroll",E,{passive:!0}),E(),()=>window.removeEventListener("scroll",E)},[t]);const tt=o.useRef(!1);o.useEffect(()=>{if(!(Dt<0)){if(!tt.current){tt.current=!0,Wa.current.add(Dt);return}Wa.current.has(Dt)||(Wa.current.add(Dt),Gt.current++)}},[Dt]);const Mt=o.useCallback(E=>{const G=ma.current;if(E<0||E>=G.length)return;k(!1);const re=G[E].chapterNumber,pe=(te=0)=>{const Fe=document.getElementById(`chapter-${re}`);Fe?(Fe.scrollIntoView({behavior:te===0?"smooth":"auto",block:"start"}),ea.current=null):te<30?setTimeout(()=>pe(te+1),200):ea.current=null};wa.current.has(E)||ha.current?pe():(ea.current=E,ba(E),Ne([Math.max(0,E-1),E,Math.min(G.length-1,E+1)]).then(()=>pe()))},[Ne]),Ma=o.useCallback(E=>{const G=ma.current.findIndex(re=>re.chapterNumber===E);G>=0&&Mt(G)},[Mt]);o.useEffect(()=>{const E=G=>{if(G.defaultPrevented)return;const re=G.target;re&&(re.tagName==="INPUT"||re.tagName==="TEXTAREA"||re.tagName==="SELECT"||re.isContentEditable)||(G.key==="ArrowRight"&&Dt<f.length-1?Mt(Dt+1):G.key==="ArrowLeft"&&Dt>0?Mt(Dt-1):G.key==="Escape"?(k(!1),M(!1)):G.key==="s"&&!G.ctrlKey&&!G.metaKey?M(pe=>!pe):G.key==="c"&&!G.ctrlKey&&!G.metaKey&&k(pe=>!pe))};return window.addEventListener("keydown",E),()=>window.removeEventListener("keydown",E)},[Dt,f.length,Mt]);const It=o.useRef(null),Nt=o.useCallback((E,G,re,pe)=>
65{G&&(It.current={paragraphId:G.id,startChar:E.start_char??0}),pa.current++,ne("immersion_token_clicked",{material_type:"novel",source:"novel_paragraph",has_grammar_tag:!!(E.grammar_key||E.grammar_point_id),has_srs_entry:!!G?.tokens?.find(Fe=>Fe.start_char===E.start_char&&Fe.end_char===E.end_char)?.vocab_id});const te=G?.tokens?.find(Fe=>Fe.start_char===E.start_char&&Fe.end_char===E.end_char);I(E,G?.id,re,pe,te?{reading:te.reading,vocab_id:te.vocab_id,lexemeVocabId:te.lexemeVocabId,lexeme_vocab_id:te.lexeme_vocab_id,meanings:te.meanings,lemma_key:te.lemma_key,is_proper_noun:te.is_proper_noun,analysis_confidence:te.analysis_confidence,mappingStatus:te.mappingStatus,analysisMetadata:te.analysisMetadata}:void 0)},[I]),Lt=o.useCallback((E,G,re)=>{It.current={paragraphId:G.id,startChar:E.start_char??0},pa.current++,ne("immersion_token_clicked",{material_type:"novel",source:"novel_paragraph",has_grammar_tag:!1,has_srs_entry:!!E.vocab_id});const pe={id:0,surface:E.surface,lemma:E.lemma_surface||E.surface,pos:[E.pos],reading:E.reading,head:0,dep:"dep",bunsetsu_index:null,is_bunsetsu_head:!1,ent_type:null,children:[],start_char:E.start_char,end_char:E.end_char,grammar_key:null,grammar_point_id:null,character_readings:null,meanings:E.meanings??null},te=y.find(ke=>ke?.paragraphs.some(Qe=>Qe.id===G.id))?.chapterNumber,Fe={reading:E.reading,vocab_id:E.vocab_id,lexemeVocabId:E.lexemeVocabId,lexeme_vocab_id:E.lexeme_vocab_id,meanings:E.meanings,lemma_key:E.lemma_key,is_proper_noun:E.is_proper_noun,analysis_confidence:E.analysis_confidence,mappingStatus:E.mappingStatus,analysisMetadata:E.analysisMetadata};I(pe,G.id,te,re,Fe)},[I,y]),qa=o.useCallback((E,G,re)=>{const pe=G.processedData?.tokens||[],te=E.startChar+E.text.length,Fe=pe.filter(Ot=>Ot.start_char!=null&&Ot.start_char>=E.startChar&&Ot.start_char<te),ke=Mi(G.text),Qe=ke.findIndex(Ot=>Ot.startChar===E.startChar),Y=[],Ze=re.paragraphs??[],Ut=Ze.findIndex(Ot=>Ot.id===G.id);if(Qe>0)Y.push(ke[Qe-1].text);else if(Ut>0){const Ot=Mi(Ze[Ut-1].text);Ot.length>0&&Y.push(Ot[Ot.length-1].text)}if(Qe<ke.length-1)Y.push(ke[Qe+1].text);else if(Ut<Ze.length-1){const Ot=Mi(Ze[Ut+1].text);Ot.length>0&&Y.push(Ot[0].text)}return{text:E.text,surroundingTexts:Y,processedData:Fe.length>0?{tokens:Fe}:G.processedData}},[]),F=o.useMemo(()=>{if(p)return{messages:h.messages,isLoading:h.isLoading,error:h.error,quotaExceeded:h.quotaExceeded,contextText:h.contextText,materialTitle:h.materialTitle,sendFollowUp:h.sendFollowUp,onUpgrade:()=>d("ai_help","quota_exceeded"),start:async E=>{const G=It.current;if(!G)return;const re=y.find(Qe=>Qe?.paragraphs.some(Y=>Y.id===G.paragraphId)),pe=re?.paragraphs.find(Qe=>Qe.id===G.paragraphId);if(!re||!pe)return;const te=Mi(pe.text),Fe=te.find(Qe=>G.startChar>=Qe.startChar&&G.startChar<Qe.startChar+Qe.text.length)??te[0];if(!Fe)return;const ke=qa(Fe,pe,re);ne("immersion_ai_help_triggered",{material_type:"novel",source:"lookup_panel"}),await h.explain({text:ke.text,surroundingTexts:ke.surroundingTexts,tokenMetadata:Mc({id:`${pe.id}-s${Fe.startChar}`,text:ke.text,processedData:ke.processedData}),material:p,pageNumber:re.chapterNumber,focus:E})}}},[p,h,y,qa,d]),Q=(E,G)=>{if(!Ct)return E.text;const re=E.processedData?.tokens||null;if(re&&re.length>0){const ke=ia(re),Qe=(Y,Ze)=>Nt(Y,E,G?.chapterNumber,Ze);return e.jsx(si,{tokens:ke,onTokenClick:Qe,vocabTokens:E.tokens||Hd,showFurigana:vt,furiganaMode:Jt,spacingMode:"natural",colorMode:At,knownStatusMap:Ke,showGrammarProgress:Ve,grammarKnowledgeMap:Be,simplifyMode:"off",showGhostSubjects:!1,groupVerbConjugations:!0,showSpacing:zt,className:""})}const pe=G?.processedData?.tokens||null;if(pe&&pe.length>0){const ke=ia(pe),Qe=(Y,Ze)=>Nt(Y,void 0,G?.chapterNumber,Ze);return e.jsx(si,{tokens:ke,onTokenClick:Qe,vocabTokens:E?.tokens||Hd,showFurigana:vt,furiganaMode:Jt,spacingMode:"natural",colorMode:At,knownStatusMap:Ke,showGrammarProgress:Ve,grammarKnowledgeMap:Be,simplifyMode:"off",showGhostSubjects:!1,groupVerbConjugations:!0,showSpacing:zt,className:""})}if(!E.tokens||E.tokens.length===0)return E.text;const te=[];let Fe=0;return E.tokens.forEach((ke,Qe)=>{ke.start_char>Fe&&te.push(E.text.substring(Fe,ke.start_char));const Y=ke.vocab_id||["noun","verb","adj-i","adj-na","adv","propn"].includes(ke.pos);te.push(e.jsx("span",{className:`${Y?"cursor-pointer hover:underline hover:bg-[hsl(var(--module-accent))]/10 transition-colors px-0.5 rounded-[var(--wc-radius-ink)]":""}`,onClick:Y?Ze=>Lt(ke,E,Ze):void 0,role:Y?"button":void 0,tabIndex:Y?0:void 0,onKeyDown:Y?Ze=>
65{(Ze.key==="Enter"||Ze.key===" ")&&(Ze.preventDefault(),Lt(ke,E,Ze))}:void 0,children:vt&&ke.reading?e.jsx(df,{surface:ke.surface,reading:ke.reading,mode:Jt,rtClassName:"text-[0.5em] leading-none"}):ke.surface},`t-${Qe}`)),Fe=ke.end_char}),Fe<E.text.length&&te.push(E.text.substring(Fe)),e.jsx(e.Fragment,{children:te})},W=o.useMemo(()=>{const E=[];y.forEach((re,pe)=>{re&&E.push({index:pe,chapter:re})}),E.sort((re,pe)=>re.index-pe.index);const G=[];for(let re=0;re<E.length;re++){const{index:pe,chapter:te}=E[re];if(re>0){const Fe=E[re-1].index;pe>Fe+1&&G.push({kind:"gap",fromIndex:Fe+1,toIndex:pe-1})}G.push({kind:"chapter",index:pe,chapter:te})}return G},[y]);if(Pe){const E=p?.file_size_bytes!=null?`${(p.file_size_bytes/1048576).toFixed(1)} MB`:null;return e.jsx("div",{className:"wc-root im-logged",children:e.jsxs("div",{className:`reader-theater reader-theater--novel mobile-viewport-takeover z-[100] ${c}`,"data-mobile-viewport-surface":"novel-restore",style:{fontFamily:"var(--font-sans)"},children:[e.jsx("div",{className:"mobile-viewport-safe-top fixed top-0 inset-x-0 z-50 pointer-events-none",children:e.jsx("button",{type:"button",onClick:a,className:"theater-chrome-icon-btn theater-chrome-icon-btn--floating pointer-events-auto","aria-label":"Back",children:e.jsx(Za,{className:"w-5 h-5"})})}),e.jsx(Mo,{restore:Ta,title:"Local file missing",filenameHint:p?.original_filename??null,detailHint:E,dismissable:!1})]})})}return P?e.jsx("div",{className:"wc-root im-logged",children:e.jsx("div",{className:`reader-theater reader-theater--novel mobile-viewport-takeover mobile-viewport-contained z-[100] ${c} flex items-center justify-center`,"data-mobile-viewport-surface":"novel-error",children:e.jsx("div",{className:"theater-panel max-w-md w-full p-8 text-center space-y-5",children:e.jsxs("div",{style:{position:"relative",zIndex:1},className:"space-y-5",children:[e.jsxs("div",{className:"theater-rail-eyebrow justify-center",children:[e.jsx("span",{className:"num jp",children:"è¿·"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Error"}),e.jsx("span",{className:"jp",children:"èªè¾¼å¤±æ"})]}),e.jsx(Qa,{className:"w-10 h-10 mx-auto",style:{color:"hsl(var(--module-accent))"}}),e.jsx("h2",{className:"text-xl serif",style:{fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600,color:"var(--theater-text)"},children:"Error Loading Novel"}),e.jsx("p",{style:{color:"var(--theater-text-soft)"},children:P}),e.jsx("button",{type:"button",onClick:a,className:"theater-btn theater-btn--primary",children:"Go Back"})]})})})}):e.jsx("div",{className:"wc-root im-logged",children:e.jsxs("div",{className:`reader-theater reader-theater--novel z-[100] ${c} min-h-screen w-full transition-colors duration-300`,"data-mobile-viewport-surface":"novel-reader",style:{fontFamily:"var(--font-sans)",minHeight:"100dvh"},children:[e.jsx("div",{className:"mobile-viewport-safe-top fixed top-0 inset-x-0 z-50 pointer-events-none",children:e.jsx("button",{type:"button",onClick:a,className:"theater-chrome-icon-btn theater-chrome-icon-btn--floating pointer-events-auto","aria-label":"Back",children:e.jsx(Za,{className:"w-5 h-5"})})}),e.jsx(Oa,{children:H&&e.jsx(ze.div,{initial:_t?!1:{opacity:0,y:-20},animate:{opacity:1,y:0},exit:_t?{opacity:0}:{opacity:0,y:-20},transition:{duration:_t?0:.5},className:"fixed left-1/2 transform -translate-x-1/2 z-40 pointer-events-none",style:{top:"max(1rem, var(--safe-area-top))"},children:e.jsx("div",{className:"theater-panel px-6 py-3",children:e.jsxs("div",{className:"text-center",style:{color:"var(--theater-text)"},children:[e.jsx("h1",{className:"text-lg serif",style:{fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:p?.title}),e.jsxs("p",{className:"text-sm opacity-70",style:{color:"var(--theater-text-soft)"},children:[f.length," chapters"]})]})})})}),e.jsx(Oa,{children:A&&e.jsx(ze.div,{className:"mobile-viewport-modal-stage fixed inset-0 z-[200] theater-scrim","data-mobile-viewport-surface":"novel-chapters",initial:{opacity:0}
65,animate:{opacity:1},exit:{opacity:0},onClick:()=>k(!1),children:e.jsx(ze.div,{className:"h-full w-full sm:w-96 max-w-full min-h-0 justify-self-end",initial:{x:"100%"},animate:{x:0},exit:{x:"100%"},transition:{type:"spring",damping:25,stiffness:300},onClick:E=>E.stopPropagation(),children:e.jsxs("div",{ref:qt,role:"dialog","aria-modal":"true","aria-label":"Chapters",tabIndex:-1,className:"mobile-viewport-modal-panel theater-panel h-full flex flex-col outline-none",style:{background:"var(--theater-surface)",color:"var(--theater-text)"},children:[e.jsxs("div",{className:"theater-pencil-rule-bottom px-6 pt-6 pb-4",children:[e.jsxs("div",{className:"theater-rail-eyebrow",children:[e.jsx("span",{className:"num jp",children:"ç« "}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Chapters"}),e.jsx("span",{className:"jp",children:"ç®æ¬¡"})]}),e.jsxs("h2",{className:"text-lg tracking-tight serif",style:{color:"var(--theater-text)",fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600},children:[f.length," chapters total"]})]}),e.jsx("nav",{"data-mobile-viewport-modal-body":!0,className:"flex-1 overflow-y-auto p-4 space-y-3",children:f.map((E,G)=>{const re=G===Dt;return e.jsx("button",{onClick:()=>Ma(E.chapterNumber),className:"w-full text-left theater-panel p-4 transition-transform group hover:-translate-y-0.5",style:{color:"var(--theater-text)"},children:e.jsxs("div",{style:{position:"relative",zIndex:1},children:[e.jsx("div",{className:"font-semibold text-sm mb-1 group-hover:text-[hsl(var(--module-accent))] transition-colors serif",style:{color:re?"hsl(var(--module-accent))":"var(--theater-text)",fontFamily:"var(--font-ui, Nunito, sans-serif)"},children:E.chapterTitle}),e.jsxs("div",{className:"text-xs",style:{color:"var(--theater-text-soft)",fontFamily:"'JetBrains Mono', monospace"},children:[E.paragraphCount," paragraphs"]}),re&&e.jsxs("div",{className:"mt-2 flex items-center gap-1 text-xs",style:{color:"hsl(var(--module-accent))"},children:[e.jsx(Ys,{className:"w-3 h-3"}),"Currently reading"]})]})},E.chapterNumber)})})]})})})}),e.jsx(Oa,{children:J&&e.jsxs(e.Fragment,{children:[e.jsx(ze.div,{initial:{opacity:0}
65,animate:{opacity:1},exit:{opacity:0},className:"fixed inset-0 z-40 theater-scrim",onClick:()=>M(!1)}),e.jsx(ze.div,{initial:{opacity:0,scale:.9,y:30},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.9,y:30},transition:{type:"spring",damping:25,stiffness:300},className:"mobile-viewport-modal-stage fixed inset-0 z-[200] flex items-center justify-center","data-mobile-viewport-surface":"novel-settings",onClick:()=>M(!1),children:e.jsxs("div",{ref:sa,role:"dialog","aria-modal":"true","aria-label":"Reader settings",tabIndex:-1,className:"mobile-viewport-modal-panel theater-panel w-full max-w-[380px] flex flex-col overflow-hidden outline-none",onClick:E=>E.stopPropagation(),children:[e.jsxs("div",{className:"theater-pencil-rule-bottom flex items-center justify-between px-5 pt-5 pb-3",style:{position:"relative",zIndex:1},children:[e.jsxs("div",{className:"theater-rail-eyebrow",style:{marginBottom:0},children:[e.jsx("span",{className:"num jp",children:"è¨"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Settings"}),e.jsx("span",{className:"jp",children:"è¨å®"})]}),e.jsx("button",{type:"button",onClick:()=>M(!1),className:"theater-chrome-icon-btn theater-chrome-icon-btn--sm","aria-label":"Close settings",children:e.jsx("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12"})})})]}),e.jsxs("div",{"data-mobile-viewport-modal-body":!0,className:"flex-1 overflow-y-auto p-4 space-y-4",style:{position:"relative",zIndex:1},children:[e.jsx(fb,{fontSize:St,fontRange:{min:14,max:28},onFontSizeChange:E=>{ne("immersion_setting_changed",{setting:"font_size",value:E,previous:St}),je(E)},lineSpacing:lt,lineSpacingRange:{min:1.4,max:2.4,step:.1},onLineSpacingChange:E=>{ne("immersion_setting_changed",{setting:"line_spacing",value:E,previous:lt}),Et(E)}}),e.jsxs(gb,{showFurigana:vt,onShowFuriganaChange:E=>{ne("immersion_setting_changed",{setting:"furigana",value:E,previous:vt}),Le(E)},furiganaMode:Jt,onFuriganaModeChange:E=>{ne("immersion_setting_changed",{setting:"furigana_mode",value:E,previous:Jt}),ta(E)},showSpacing:zt,onShowSpacingChange:E=>{ne("immersion_setting_changed",{setting:"spacing",value:E,previous:zt}),K(E)},children:[e.jsx(ei,{label:"Text Analysis",checked:Ct,onCheckedChange:E=>{ne("immersion_setting_changed",{setting:"annotations",value:E,previous:Ct}),aa(E)}}),e.jsx(ei,{label:"Vocabulary Colors",description:"New = blue · Learning = amber · Known = plain",checked:jt,onCheckedChange:E=>{ne("immersion_setting_changed",{setting:"known_coloring",value:E,previous:jt}),Ft(E)}}),e.jsx(ei,{label:"Grammar progress",description:"Blue dots · amber dashes · green solid",checked:ct,onCheckedChange:E=>{ne("immersion_setting_changed",{setting:"grammar_progress",value:E,previous:ct}),se(E)}})]}),e.jsx(ih,{isDark:i,onToggleDarkMode:()=>{ne("immersion_setting_changed",{setting:"theme",value:i?"light":"dark",previous:i?"dark":"light"}),l()}}),e.jsx(yb,{shortcuts:[{combo:"â / â",description:"Navigate chapters"},{combo:"S",description:"Toggle settings"},{combo:"C",description:"Toggle chapters list"},{combo:"ESC",description:"Close panels"}]})]})]})})]})}),e.jsx("main",{className:"max-w-4xl mx-auto px-6 sm:px-8 py-12",children:e.jsxs(ze.article,{initial:_t?!1:{opacity:0},animate:{opacity:1},transition:{duration:_t?0:.6,delay:_t?0:.2},style:{fontSize:`${St}px`,lineHeight:lt,fontFamily:'"Noto Serif JP", "Yu Mincho", "Hiragino Mincho ProN", "MS Mincho", serif',color:"var(--theater-text)"},children:[j&&e.jsxs("div",{className:"flex flex-col items-center justify-center py-24 gap-4","aria-live":"polite",children:[_t?e.jsx("img",{src:cs,alt:"",width:144,height:144,style:{opacity:.6},"aria-hidden":"true"}):e.jsx("div",{"aria-hidden":"true",children:e.jsx(bs,{image:cs,size:144,duration:1.2,repeatDelay:999})}),de&&e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Fetching from your libraryâ¦"})]}),_&&e.jsxs("div",{className:"mx-auto max-w-prose mb-8 px-4 py-3 text-sm flex items-center gap-2",style:{background:"var(--theater-destructive-bg)",border:"1px solid var(--theater-destructive-border)",borderRadius:"var(--wc-radius-ink)",color:"var(--theater-text-soft)"},role:"alert",children:[e.jsx(Qa,{className:"w-4 h-4 flex-shrink-0",style:{color:"var(--theater-destructive)"}}),e.jsx("span",{children:_}),e.jsx("button",{type:"button",onClick:()=>{L(null),O(E=>E+1)},className:"ml-auto theater-btn theater-btn--secondary",children:"Retry"})]}),W.map((E,G)=>
65{if(E.kind==="gap"){const ke=ma.current[E.fromIndex],Qe=E.fromIndex===E.toIndex?`Chapter ${E.fromIndex+1} not loaded`:`Chapters ${E.fromIndex+1}â${E.toIndex+1} not loaded`;return e.jsxs("div",{className:"my-16 flex flex-col items-center gap-3 text-center",children:[e.jsx("div",{className:"w-full max-w-prose",style:{borderTop:"1px dashed var(--theater-surface-border-strong)"}}),e.jsx("p",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:Qe}),e.jsxs("button",{type:"button",onClick:()=>Mt(E.fromIndex),className:"theater-btn theater-btn--secondary",children:["Continue from ",ke?.chapterTitle||`chapter ${E.fromIndex+1}`]})]},`gap-${E.fromIndex}-${E.toIndex}`)}const{index:re,chapter:pe}=E,te=Math.max(400,(pe.paragraphs?.length??0)*Math.round(St*lt*2.2)),Fe=_t?0:Math.min(G*.06,.3);return e.jsxs(ze.section,{id:`chapter-${pe.chapterNumber}`,className:"mb-20",style:{contentVisibility:"auto",containIntrinsicSize:`auto ${te}px`},initial:_t?!1:{opacity:0,y:20},animate:{opacity:1,y:0},transition:{duration:.5,delay:Fe},children:[e.jsx("h2",{className:"text-center font-bold mb-12 pb-4 border-b serif",style:{fontSize:`${St*1.4}px`,borderColor:"var(--theater-surface-border)",fontFamily:"var(--font-ui, Nunito, sans-serif)"},children:pe.chapterTitle}),e.jsx("div",{className:"space-y-6",children:(pe.paragraphs??[]).map(ke=>e.jsx("div",{style:{textIndent:"1em",wordBreak:"normal",overflowWrap:"break-word",whiteSpace:"normal",fontSize:`${St}px`,lineHeight:lt},lang:"ja",children:Q(ke,pe)},ke.id))}),G===W.length-1&&re<f.length-1&&Wt&&e.jsxs("div",{className:"flex flex-col items-center py-8 gap-3","aria-hidden":"true",children:[_t?e.jsx("img",{src:cs,alt:"",width:72,height:72,style:{opacity:.6}}):e.jsx(bs,{image:cs,size:72,duration:1.2,repeatDelay:999}),e.jsx("p",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Loading next chapter..."})]})]},pe.chapterNumber)}),f.length>0&&v.size===f.length&&e.jsx(ze.div,{className:"text-center py-12 flex justify-center",initial:_t?!1:{opacity:0},animate:{opacity:1},transition:{delay:.5},children:e.jsx("div",{className:"theater-panel inline-block px-12 py-8",children:e.jsxs("div",{style:{position:"relative",zIndex:1},children:[e.jsx("p",{className:"jp",style:{fontFamily:"'Noto Serif JP', serif",fontSize:"48px",fontWeight:500,color:"hsl(var(--module-accent))",lineHeight:1,marginBottom:8},children:"çµ"}),e.jsx("p",{className:"text-lg serif",style:{fontFamily:"var(--font-ui, Nunito, sans-serif)",fontWeight:600,color:"var(--theater-text)"},children:"End of book"})]})})})]})}),e.jsx("div",{ref:yt,className:"mobile-viewport-safe-bottom fixed bottom-0 left-0 right-0 z-30 flex justify-center pointer-events-none","aria-hidden":!Me,children:e.jsxs("div",{className:"theater-chrome-bar pointer-events-auto",style:{opacity:Me?1:0,transform:Me?"translateY(0)":"translateY(16px)",pointerEvents:Me?"auto":"none",transition:"opacity 0.3s ease, transform 0.3s ease"},children:[e.jsx("button",{type:"button",onClick:()=>Mt(Dt-1),disabled:Dt===0,className:"theater-chrome-icon-btn","aria-label":"Previous chapter",children:e.jsx(Qu,{className:"w-5 h-5"})}),e.jsxs("div",{className:"theater-chrome-bar-counter",children:[e.jsx(ss,{size:14,style:{color:"hsl(var(--module-accent))"}}),e.jsxs("span",{className:"tabular-nums",children:[Dt+1,e.jsx("span",{style:{opacity:.5},children:" / "}),f.length]})]}),e.jsx("button",{type:"button",onClick:()=>Mt(Dt+1),disabled:Dt===f.length-1,className:"theater-chrome-icon-btn","aria-label":"Next chapter",children:e.jsx(As,{className:"w-5 h-5"})}),e.jsx("div",{className:"theater-chrome-bar-divider","aria-hidden":"true"}),e.jsx("button",{type:"button",onClick:E=>{E.stopPropagation(),k(!A)},className:`theater-chrome-icon-btn ${A?"is-active":""}`,"aria-label":"Chapters","aria-pressed":A,children:e.jsx(uf,{className:"w-5 h-5"})}),e.jsx("button",{type:"button",onClick:()=>{ne("immersion_setting_changed",{setting:"theme",value:i?"light":"dark",previous:i?"dark":"light"}),l()},className:"theater-chrome-icon-btn","aria-label":i?"Switch to light mode":"Switch to dark mode",children:i?e.jsx(bm,{className:"w-5 h-5"}):e.jsx(ym,{className:"w-5 h-5"})}),e.jsx("button",{type:"button",onClick:E=>{E.stopPropagation(),M(!J)},className:`theater-chrome-icon-btn ${J?"is-active":""}`,"aria-label":"Settings","aria-pressed":J,children:e.jsx(cm,{className:"w-5 h-5"})})]})}),oe&&e.jsx(lc,{token:oe,position:me,isLoading:Ge,onClose:xe,deckApi:r,grammarKnowledgeApi:n?pt:void 0,aiHelpApi:F,richLookupApi:ft,kanjiDetailApi:Oe,mnemonicsApi:n?Ac:void 0,onOpenWord:jr.onOpenWord,onOpenKanji:jr.onOpenKanji,onDeckToggle:E=>
65{E&&(Ca.current++,ne("immersion_word_added_to_deck",{material_type:"novel",source:"novel_paragraph"}))}})]})})}function Ur(t){if(t.processing_status==="processing"||t.enrichment_status==="pending"||t.enrichment_status==="processing")return"none";const a=t.content_type==="novel"||t.file_type==="epub",s=t.total_text_boxes;return!a&&t.local_images&&s===0||t.processing_status==="completed"&&t.enrichment_status==="completed"?"none":t.processing_status==="local_only"&&a||typeof s=="number"&&s>0||s==null&&t.enrichment_status!=="completed"?"analyze":"none"}function Wd(t){return!!t?.pages.some(a=>a.blocks.length>0)}async function El(t,a){const s=await t.json().catch(()=>({}));return new Error(s.message||s.error||a)}const ox={process_srt:{noun:"SRT subtitle",unit:"uploads"},process_video_subs:{noun:"video subtitle",unit:"episodes"},vocab_extract:{noun:"vocabulary extraction",unit:"jobs"},analyze_text_boxes:{noun:"text analysis",unit:"jobs"},process_media_mokuro:{noun:"manga OCR",unit:"jobs"},create_media_deck:{noun:"media deck",unit:"creations"},create_reading_deck:{noun:"reading deck",unit:"creations"},create_video_deck:{noun:"video deck",unit:"creations"},process_jimaku_queue:{noun:"subtitle import",unit:"runs"},reimport_season:{noun:"season reimport",unit:"jobs"}};function lx(t){if(!t||typeof t!="object")return!1;const a=t;return a.error==="RATE_LIMITED"&&typeof a.jobType=="string"&&typeof a.limit=="number"&&typeof a.current=="number"&&typeof a.intervalSeconds=="number"}function cx(){return"Take a short break"}function xh(t){const a=ox[t.jobType]??{noun:"background",unit:"jobs"},s=Math.max(1,Math.round(t.intervalSeconds/60)),n=s===1?"minute":"minutes";return`You've ${a.unit==="episodes"?"queued":"started"} ${t.limit} ${a.noun} ${a.unit} in the last ${s} ${n}. Wait a moment before starting another.`}function wh(t){return"This keeps any single userâs batch from blocking others. Your earlier uploads are still processing in the background â they arenât affected."}function fn(t){return`${xh(t)} ${wh()}`}class an extends Error{heading;hint;body;constructor(a){super(xh(a)),this.name="EnqueueRateLimitError",this.heading=cx(),this.hint=wh(),this.body=a}}async function ws(t){if(t.status!==429)return null;try{const s=await t.clone().json();return lx(s)?s:null}catch{return null}}const dx={reading:"reading",manga:"manga",video:"video",audio:"audio",avatar:"avatar",cloud_sync:"cloud library"},ux={free:"Free",pro:"Pro",premium:"Premium"};function mx(t){if(!t||typeof t!="object")return!1;const a=t;return a.error==="storage_quota_exceeded"&&typeof a.category=="string"&&typeof a.current_mb=="number"&&typeof a.limit_mb=="number"&&typeof a.tier=="string"}function hx(){return"Storage limit reached"}function px(t){const a=dx[t.category]??t.category,s=ux[t.tier]??"Free";return`You've used ${t.current_mb} MB of your ${t.limit_mb} MB ${a} storage on the ${s} plan.`}function Cn(t){return`${hx()} â ${px(t)}`}async function Ls(t){if(t.status!==413)return null;try{const s=await t.clone().json();return mx(s)?s:null}catch{return null}}const fx=/\.(jpe?g|png|webp)$/i,gx=/\.mokuro$/i;function yx(t){const a=t.replace(/\\/g,"/"),s=a.lastIndexOf("/");return s===-1?"":a.slice(0,s)}function bx(t){const a=t.replace(/\\/g,"/"),s=a.lastIndexOf("/");return s===-1?a:a.slice(s+1)}function vh(t){return t.replace(/\.[^./\\]+$/,"")}const xx=Em;function jh(t){const a=wc(t),s=a.match(/(?:v(?:ol)?\.?\s*|第\s*)(\d{1,4})\s*å·»?\s*$/i);if(s)return parseInt(s[1],10);const n=a.match(/(\d{1,4})\D*$/);return n?parseInt(n[1],10):null}function kh(t){if(t.length===0)return"";if(t.length===1)return Gd(t[0]);const a=t.map(n=>[...n]);let s=a[0];for(let n=1;n<a.length;n++){const r=a[n];let i=0;for(;i<s.length&&i<r.length&&s[i]===r[i];)i++;if(s=s.slice(0,i),s.length===0)break}return Gd(s.join(""))}function Gd(t){return wc(t).replace(/(?:[\s._\-ââ]*)(?:v(?:ol)?\.?\s*)?(?:第\s*)?\d{1,4}\s*(?:å·»)?\s*$/i,"").replace(/[\s._\-ââ]+$/,"").trim()}function _h(t){const a=[],s=[];for(const f of t)xx(f.relativePath)||(gx.test(f.name)?a.push(f):fx.test(f.name)&&s.push(f));const n=new Map;for(const f of s){const b=yx(f.relativePath),y=n.get(b);y?y.push(f):n.set(b,[f])}
65for(const f of n.values())f.sort((b,y)=>ys(b.name).localeCompare(ys(y.name)));const r=new Map;for(const f of n.keys()){const b=bx(f),y=r.get(b);y?y.push(f):r.set(b,[f])}const i=a.length>=2,l=[],c=[],d=new Set,m=[],u=[...a].sort((f,b)=>ys(f.name).localeCompare(ys(b.name)));for(const f of u){const b=vh(f.name),y=jh(b),v=r.get(b)?.find(w=>!d.has(w))??null;if(v){d.add(v);const w=n.get(v)??[],j=f.size+w.reduce((T,P)=>T+P.size,0);l.push({key:f.relativePath,name:b,volumeNumber:y,mokuroPath:f.relativePath,images:w,sizeBytes:j,hasMokuro:!0})}else c.push({mokuroPath:f.relativePath,basename:b,volumeNumber:y,size:f.size})}const h=new Map;for(const[f,b]of n)if(!d.has(f)&&(h.set(f,b),i&&c.length===0)){const y=f===""?`${b.length} loose image(s)`:`"${f}"`;m.push(`Images with no matching .mokuro were skipped (${y}).`)}l.sort((f,b)=>{if(f.volumeNumber!=null&&b.volumeNumber!=null){if(f.volumeNumber!==b.volumeNumber)return f.volumeNumber-b.volumeNumber}else{if(f.volumeNumber!=null)return-1;if(b.volumeNumber!=null)return 1}return ys(f.name).localeCompare(ys(b.name))});const p=[...l.map(f=>f.name),...c.map(f=>f.basename)],g=kh(p);return{isMultiVolume:i,volumes:l,seriesTitle:g,unresolvedMokuro:c,looseImageDirs:h,notices:m}}function Yd(t){const a=t.webkitRelativePath&&t.webkitRelativePath.length>0?t.webkitRelativePath:t.name;return{name:t.name,relativePath:a,size:t.size}}function Rc(t,a,s){return{volumes:s,seriesTitle:t,notices:a,totalPages:s.reduce((n,r)=>n+r.pageCount,0),totalBytes:s.reduce((n,r)=>n+r.sizeBytes,0)}}function wx(t){const a=t.replace(/\\/g,"/"),s=a.lastIndexOf("/");return s===-1?"":a.slice(0,s)}function Tl(t){const a=t.replace(/\\/g,"/"),s=a.lastIndexOf("/");return s===-1?a:a.slice(s+1)}async function Sh(t,a,s){const n=[],r=[],i=new Set,l=new Map;for(const c of a.keys()){const d=Tl(c),m=l.get(d);m?m.push(c):l.set(d,[c])}for(const c of t){let d;try{const h=So(await s(c.mokuroPath)),p=new Set;for(const g of h.pages)p.add(Tl(wx(g.img_path)));d=[...p]}catch{r.push(c);continue}const m=[];for(const h of d){const g=l.get(h)?.find(f=>!i.has(f));g&&m.push(g)}if(m.length===0){r.push(c);continue}const u=[];for(const h of m)i.add(h),u.push(...a.get(h)??[]);u.sort((h,p)=>ys(h.name).localeCompare(ys(p.name))),n.push({key:c.mokuroPath,name:c.basename,volumeNumber:c.volumeNumber,mokuroPath:c.mokuroPath,images:u,sizeBytes:c.size+u.reduce((h,p)=>h+p.size,0),hasMokuro:!0})}for(const c of i)a.delete(c);return{recovered:n,stillUnresolved:r}}function Nh(t,a){if(t.volumeNumber!=null&&a.volumeNumber!=null){if(t.volumeNumber!==a.volumeNumber)return t.volumeNumber-a.volumeNumber}else{if(t.volumeNumber!=null)return-1;if(a.volumeNumber!=null)return 1}return ys(t.name).localeCompare(ys(a.name))}function Ch(t,a){const s=[...t,...a];return s.sort(Nh),s}function Eh(t,a){const s=[...t.notices];for(const n of a)s.push(`Couldn't match "${Tl(n.mokuroPath)}" to an image folder â this volume will be skipped.`);return s}function vx(t,a){return t.map(s=>{const n=s.images.map(i=>a.get(i.relativePath)).filter(i=>i!=null),r=s.mokuroPath?a.get(s.mokuroPath)??null:null;return{key:s.key,name:s.name,volumeNumber:s.volumeNumber,pageCount:s.images.length,sizeBytes:s.sizeBytes,hasMokuro:r!=null,resolve:r?i=>Pm(n,r,i):i=>No(n,i)}})}async function jx(t){const a=t.map(Yd),s=_h(a);if(!s.isMultiVolume)return null;const n=new Map;for(const d of t)n.set(Yd(d).relativePath,d);const{recovered:r,stillUnresolved:i}=await Sh(s.unresolvedMokuro,s.looseImageDirs,async d=>{const m=n.get(d);if(!m)throw new Error("mokuro file not in hand");return m.text()}),l=Ch(s.volumes,r),c=vx(l,n);return Rc(s.seriesTitle,Eh(s,i),c)}function kx(t,a){return a.map(s=>{const n=s.images.map(i=>i.relativePath),r=s.mokuroPath;return{key:s.key,name:s.name,volumeNumber:s.volumeNumber,pageCount:s.images.length,sizeBytes:s.sizeBytes,hasMokuro:s.hasMokuro,resolve:i=>my(t,n,r,i)}})}async function _x(t){const a=t.entries.map(c=>({name:c.name,relativePath:c.path,size:c.size})),s=_h(a);if(!s.isMultiVolume)return null;const{recovered:n,stillUnresolved:r}=await Sh(s.unresolvedMokuro,s.looseImageDirs,async c=>{const d=t.zip.file(c);if(!d)throw new Error("mokuro entry not in archive");return d.async("string")}),i=Ch(s.volumes,n),l=kx(t,i);return Rc(s.seriesTitle,Eh(s,r),l)}async function Jd(t){if(t.length<2)return null;const a=[];for(let s=0;s<t.length;s++){const n=t[s],r=vh(n.name);let i=0;try{i=await Sl(n)}catch{i=0}a.push({key:`${n.name}::${s}`,name:r,volumeNumber:jh(r),pageCount:i,sizeBytes:n.size,hasMokuro:!1,resolve:l=>kc(n,l)})}return a.sort(Nh),Rc(kh(a.map(s=>s.name)),[],a)}function Sx(t,a){const s=t.filter(m=>m.status==="imported"||m.status==="deferred").length,n=t.filter(m=>m.status==="skipped").length,r=t.filter(m=>m.status==="deferred").length,i=t.filter(m=>m.status==="failed"),l=[];l.push(`${s} of ${a} imported`),n>0&&l.push(`${n} already in your library`),r>0&&l.push(`${r} queued for processing later`),i.length>0&&l.push(`${i.length} failed (${i.map(m=>m.name).join(", ")})`);const c=l.join(" · ");return{status:s===0&&i.length>0?"error":"completed",message:c,imported:s,skipped:n,deferred:r,failed:i.length}}const Nx=5,Xd=3,Cx=3,Ex=500,Tx=2e3,Mx=4,Px=6e4,Ax=200;function Ix(t){return{fetch:(...a)=>fetch(...a),getAccessToken:t,getMangaPage:(a,s)=>hc(a,s),getEpubBlob:a=>gr(a),listPageSizes:a=>Jg(a),apiBase:ue,sleep:a=>new Promise(s=>setTimeout(s,a)),random:()=>Math.random()}}function Rx(t){const a=t.match(/\/p\/(\d+)\.webp$/);return a?parseInt(a[1],10):null}async function $x(t,a,s,n){const{materialId:r,kind:i}=t,l=a.apiBase();let c,d,m;if(i==="manga"){const x=await a.listPageSizes(r),v=new Map(x.map(_=>[_.pageNumber,_.sizeBytes])),w=[];for(let _=1;_<=t.totalPages;_++){const L=v.get(_);if(L==null)return{kind:"error",retryable:!1,message:`Local page ${_} missing â re-import to sync`};w.push({page:_,size:L})}d=t.totalPages,c=w.reduce((_,L)=>_+L.size,0);const j=await a.getAccessToken();if(!j)return{kind:"error",retryable:!0,message:"Not authenticated"};const T=await a.fetch(`${l}/api/reading/materials/${r}/cloud-sync/init`,{method:"POST",headers:{Authorization:`Bearer ${j}`,"Content-Type":"application/json"},body:JSON.stringify({pages:w}),signal:n}),P=await Qd(T,c);if(P)return P;m=(await T.json()).uploads??[]}else{const x=await a.getEpubBlob(r);if(!x)return{kind:"error",retryable:!1,message:"Local EPUB missing â re-import to sync"};c=x.blob.size,d=1;const v=await a.getAccessToken();if(!v)return{kind:"error",retryable:!0,message:"Not authenticated"};const w=await a.fetch(`${l}/api/reading/materials/${r}/cloud-sync/init`,{method:"POST",headers:{Authorization:`Bearer ${v}`,"Content-Type":"application/json"},body:JSON.stringify({sizeBytes:x.blob.size}),signal:n}),j=await Qd(w,c);if(j)return j;m=(await w.json()).uploads??[]}const u=i==="manga"?t.totalPages:1,h=m.length;let p=u-h;s?.(p,u);const f=await Fx(m,Nx,async x=>{if(n?.aborted)return{kind:"error",retryable:!0,message:"Aborted"};let v=null;if(i==="manga"){const j=Rx(x.key);if(j==null)return{kind:"error",retryable:!1,message:`Bad key ${x.key}`};v=(await a.getMangaPage(r,j))?.blob??null}else v=(await a.getEpubBlob(r))?.blob??null;if(!v)return{kind:"error",retryable:!1,message:"Local bytes vanished mid-sync"};const w=await zx(a,x.url,v,n);return w.ok?(p+=1,s?.(p,u),null):{kind:"error",retryable:w.retryable,message:w.message}},n);if(f)return f;const b=await a.getAccessToken();if(!b)return{kind:"error",retryable:!0,message:"Not authenticated"};const y=await a.fetch(`${l}/api/reading/materials/${r}/cloud-sync/complete`,{method:"POST",headers:{Authorization:`Bearer ${b}`,"Content-Type":"application/json"},body:JSON.stringify({declaredBytes:c,declaredPages:d}),signal:n});if(y.status===503)return{kind:"unavailable"};
65if(y.status===413)return{kind:"quota_exceeded",quota:await Ls(y)??void 0,bytes:c};if(y.status===409)return{kind:"error",retryable:!0,message:"Upload verification failed â will retry"};if(y.status===401)return{kind:"error",retryable:!0,message:"complete 401"};if(!y.ok){const x=Th(y);return{kind:"error",retryable:y.status>=500,message:`complete ${y.status}`,retryAfterMs:x}}return{kind:"synced",bytes:c}}function Th(t){const a=t.headers.get("retry-after");if(!a)return;const s=Number(a);if(Number.isFinite(s))return Math.max(0,s*1e3);const n=Date.parse(a);if(Number.isFinite(n))return Math.max(0,n-Date.now())}async function Qd(t,a){if(t.ok)return null;if(t.status===503)return{kind:"unavailable"};if(t.status===403)return{kind:"error",retryable:!1,message:"Cloud sync requires Pro"};if(t.status===404)return{kind:"error",retryable:!1,message:"Material not found"};if(t.status===413)return{kind:"quota_exceeded",quota:await Ls(t)??void 0,bytes:a};const s=t.status!==400,n=Th(t);return{kind:"error",retryable:s,message:`init ${t.status}`,retryAfterMs:n}}async function zx(t,a,s,n){let r="";for(let i=1;i<=Xd;i++){if(n?.aborted)return{ok:!1,retryable:!0,message:"Aborted"};try{const l=await t.fetch(a,{method:"PUT",body:s,headers:{"Content-Type":s.type||"application/octet-stream"},signal:n});if(l.ok)return{ok:!0,retryable:!1,message:""};if(r=`PUT ${l.status}`,!(l.status>=500||l.status===429))return{ok:!1,retryable:!1,message:r}}catch(l){r=l instanceof Error?l.message:"network error"}i<Xd&&await t.sleep(Ex*2**(i-1))}return{ok:!1,retryable:!0,message:r||"upload failed"}}async function Fx(t,a,s,n){if(t.length===0)return null;let r=0,i=null;const l=Array.from({length:Math.min(a,t.length)},async()=>{for(;r<t.length&&!i;){if(n?.aborted){i=i??{kind:"error",retryable:!0,message:"Aborted"};return}const c=r++,d=await s(t[c]);if(d){i=i??d;return}}});return await Promise.all(l),i}function Dx(t){const a=t.toLowerCase();return a.includes("not authenticated")||a.includes("401")?"auth":a.includes("local")&&(a.includes("missing")||a.includes("vanished"))?"local_bytes_missing":a.includes("requires pro")?"tier":a.includes("not found")||a.includes("404")?"not_found":a.includes("verification")?"verify":a.includes("abort")?"aborted":a.includes("init")?"init":a.includes("complete")?"complete":a.includes("put")?"put":a.includes("network")?"network":"other"}function Lx(t,a){const s=Tx*Mx**t,n=.5+a();return Math.min(s*n,Px)}class Ox{deps=null;items=[];states=new Map;listeners=new Set;running=!1;currentAbort=null;currentMaterialId=null;cancelled=new Set;unavailable=!1;emitTimer=null;emitPending=!1;configure(a){this.deps=Ix(a),this.items.length>0&&this.pump()}_setDeps(a){this.deps=a,this.unavailable=!1,this.items.length>0&&this.pump()}_reset(){this.deps=null,this.items=[],this.states.clear(),this.cancelled.clear(),this.currentMaterialId=null,this.unavailable=!1,this.running=!1,this.currentAbort?.abort(),this.currentAbort=null,this.emitTimer&&(clearTimeout(this.emitTimer),this.emitTimer=null),this.emitPending=!1}subscribe(a){return this.listeners.add(a),a(new Map(this.states)),()=>{this.listeners.delete(a)}}getState(a){return this.states.get(a)??{status:"idle"}}clearState(a){this.items=this.items.filter(s=>s.materialId!==a),this.cancelled.add(a),this.currentMaterialId===a&&this.currentAbort?.abort(),this.states.delete(a)&&this.emit(!0)}isTerminal(a){return a.status==="synced"||a.status==="error"||a.status==="quota_exceeded"||a.status==="unavailable"||a.status==="idle"}flushEmit(){this.emitTimer&&(clearTimeout(this.emitTimer),this.emitTimer=null),this.emitPending=!1;const a=new Map(this.states);for(const s of this.listeners)s(a)}emit(a){if(a){this.flushEmit();return}this.emitPending=!0,!this.emitTimer&&(this.emitTimer=setTimeout(()=>{this.emitTimer=null,this.emitPending&&this.flushEmit()},Ax))}setState(a,s){this.states.set(a,s),this.emit(this.isTerminal(s))}enqueue(a){if(this.unavailable||this.items.some(n=>n.materialId===a.materialId))return;const s=this.states.get(a.materialId);s?.status==="uploading"||s?.status==="queued"||(this.cancelled.delete(a.materialId),this.items.push({...a,attempts:0}),this.setState(a.materialId,{status:"queued"}),this.pump())}
65retry(a){this.unavailable||(this.states.delete(a.materialId),this.items=this.items.filter(s=>s.materialId!==a.materialId),this.enqueue({...a,trigger:"retry"}))}async _drain(){for(;this.running||this.items.length>0;)await new Promise(a=>setTimeout(a,0));this.flushEmit()}async pump(){if(!this.running&&this.deps){this.running=!0;try{for(;this.items.length>0&&!this.unavailable;){const a=this.items.shift();if(this.cancelled.has(a.materialId))continue;this.currentMaterialId=a.materialId,a.attempts===0&&a.startedAt==null&&(a.startedAt=Date.now(),ne("cloud_sync_started",{kind:a.kind,page_count:a.totalPages,trigger:a.trigger??"import"})),this.setState(a.materialId,{status:"uploading",uploaded:0,total:a.totalPages}),this.currentAbort=new AbortController;let s;try{s=await $x(a,this.deps,(n,r)=>{this.cancelled.has(a.materialId)||this.setState(a.materialId,{status:"uploading",uploaded:n,total:r})},this.currentAbort.signal)}catch(n){s={kind:"error",retryable:!0,message:n instanceof Error?n.message:"sync failed"}}this.currentMaterialId=null,this.currentAbort=null,!this.cancelled.has(a.materialId)&&await this.applyOutcome(a,s)}}finally{this.running=!1,this.currentAbort=null,this.currentMaterialId=null}}}durationOf(a){return a.startedAt!=null?Math.max(0,Date.now()-a.startedAt):void 0}async applyOutcome(a,s){const n=a.trigger??"import";switch(s.kind){case"synced":ne("cloud_sync_completed",{kind:a.kind,page_count:a.totalPages,bytes:s.bytes,duration_ms:this.durationOf(a),trigger:n}),this.setState(a.materialId,{status:"synced"});return;case"unavailable":this.unavailable=!0;for(const r of this.items){const i=this.states.get(r.materialId)?.status;(i==="uploading"||i==="queued")&&this.states.delete(r.materialId)}this.items=[],this.setState(a.materialId,{status:"unavailable"});return;case"quota_exceeded":ne("cloud_quota_hit",{kind:a.kind,tier:s.quota?.tier,bytes:s.bytes,trigger:n}),this.setState(a.materialId,{status:"quota_exceeded",quota:s.quota});return;case"error":if(s.retryable&&a.attempts+1<Cx){this.setState(a.materialId,{status:"queued"});const r=s.retryAfterMs??Lx(a.attempts,this.deps.random);if(await this.deps.sleep(r),this.unavailable)return;if(this.cancelled.has(a.materialId)){this.states.delete(a.materialId),this.emit(!0);return}this.items.push({...a,attempts:a.attempts+1})}else ne("cloud_sync_failed",{kind:a.kind,page_count:a.totalPages,error_kind:Dx(s.message),retryable:s.retryable,attempts:a.attempts+1,duration_ms:this.durationOf(a),trigger:n}),this.setState(a.materialId,{status:"error",retryable:s.retryable,message:s.message});return}}}const kr=new Ox;function Ao(t){return t.file_type==="epub"?"epub":"manga"}async function Mh(t){try{return Ao(t)==="epub"?await li(t.id):await oi(t.id)}catch{return!1}}async function Pn(t,a){if(!a)return;const s=Ao(t),n=s==="manga"?t.total_pages??0:1;s==="manga"&&n<=0||await Mh(t)&&kr.enqueue({materialId:t.id,kind:s,totalPages:n,trigger:"import"})}async function Ph(t,a){if(a)for(const s of t){if(s.cloud_sync_status!=="uploading")continue;const n=Ao(s),r=n==="manga"?s.total_pages??0:1;n==="manga"&&r<=0||await Mh(s)&&kr.enqueue({materialId:s.id,kind:n,totalPages:r,trigger:"resume"})}}function Bx(t,a,s,n){const r=[];for(const i of t){if(i.cloud_sync_status!=null)continue;const l=Ao(i);if(!(l==="epub"?s.has(i.id):a.has(i.id)))continue;const d=l==="manga"?i.total_pages??0:1;l==="manga"&&d<=0||r.push({materialId:i.id,kind:l,totalPages:d,material:i})}return r}async function qx(t,a){let s=new Set,n=new Set;try{const[r,i]=await Promise.all([pc(),xc()]);s=new Set(r.map(l=>l.materialId)),n=new Set(i.map(l=>l.materialId))}catch{return[]}return Bx(t,s,n)}function Ux(t){t.length>0&&ne("cloud_backfill_started",{material_count:t.length});for(const a of t)kr.enqueue({materialId:a.materialId,kind:a.kind,totalPages:a.totalPages,trigger:"backfill"})}function Vx(t){let a=0;for(const s of t)s.includes("[Script Info]")||s.includes("Dialogue:")?a+=s.split(` 66`).filter(n=>n.trimStart().startsWith("Dialogue:")).length:a+=s.replace(/\r\n/g,` 67`).split(/\n\n+/).filter(n=>n.trim()).length;return a}async function Rr(t){try{return Vx(await Promise.all(t.map(a=>a.text())))}catch{return null}}const Zd=50,Kx=2e3,Hx="v1",Wx="shizen:ocr-pending:v1:",Ml=new Map;function Ah(t,a,s){return`${Wx}account:${encodeURIComponent(t)}:${a}
67:chunk:${s}`}function Gx(t,a,s){const n=Ah(t,a,s);let r=null;try{r=globalThis.localStorage?.getItem(n)??null}catch{}if(r??=Ml.get(n)??null,r)return r;const i=`mokuro:web:${Hx}:${crypto.randomUUID()}:chunk:${s}:content:${a}`;Ml.set(n,i);try{globalThis.localStorage?.setItem(n,i)}catch{}return i}function il(t,a,s){const n=Ah(t,a,s);Ml.delete(n);try{globalThis.localStorage?.removeItem(n)}catch{}}let ol=null,Pi=new Map;async function ll(t,a,s,n){if(!n?.trim())throw new ms("OCR requires a stable image-set fingerprint.");const r=await Xx(n),{data:{session:i}}=await Ps.auth.getSession(),l=i?.access_token,c=i?.user?.id;if(!l||!c)throw new ms("Not signed in â cannot run OCR.");const d=t.size;if(d===0)throw new ms("No images to OCR.");const m=[...t.entries()],u=`${Ap()}/api/media-vocab/mokuro-ocr`;(!n||n!==ol)&&(ol=n??null,Pi=new Map);let h=null;for(let p=0;p<d;p+=Zd){if(s?.aborted)throw new DOMException("OCR cancelled","AbortError");const g=m.slice(p,p+Zd),f=p+g.length,b=p+1,y=f,x=n?Pi.get(p):void 0;if(x){a?.({phase:"processing",message:`Reusing OCR result for pages ${b}-${y} of ${d}...`}),h===null?h={...x,pages:[...x.pages],creditQuotes:[...x.creditQuotes]}:(h.pages.push(...x.pages),h.creditQuotes.push(...x.creditQuotes));continue}a?.({phase:"uploading",message:`Uploading pages ${b}-${y} of ${d}...`});const v=new FormData;for(const[N,_]of g){const L=new File([_],N,{type:_.type||"image/jpeg"});v.append("files",L,N)}a?.({phase:"processing",message:`Running OCR on pages ${b}-${y} of ${d}...`});const w=Gx(c,r,p);await Yx(`${u}/preview`,l,v,w,s);const j=await Jx(u,l,v,g.length,w,s);if(!j.ok){j.status===409&&il(c,r,p);let N=j.statusText,_=null;try{_=await j.json(),N=_?.detail||_?.error||N}catch{try{N=await j.text()}catch{}}if(j.status===429&&(_?.error==="ocr_quota_exceeded"||_?.code==="OCR_RECONCILIATION_REFUSED")&&il(c,r,p),j.status===401)throw new ms("Authentication required. Please sign in again.");if(j.status===429){if(_?.error==="ocr_quota_exceeded"){const L=typeof _.current_usage=="number"?_.current_usage:void 0,q=typeof _.limit=="number"?_.limit:void 0,O=L!==void 0&&q!==void 0?` (${L}/${q} pages)`:"",A=typeof _.message=="string"?_.message:"";throw new ms(A||`Monthly OCR page limit reached${O}. Upgrade your plan or wait for your quota to reset.`)}throw new ms("OCR temporarily rate-limited â wait a minute and try again.")}throw j.status===413?new ms("OCR request too large. The volume may have unusually large page images â try lowering image quality before re-uploading."):j.status===500&&/not configured/i.test(N)?new ms("Mokuro proxy not configured on the server. Set MOKURO_SHARED_SECRET and MOKURO_ENDPOINT in the API environment."):new ms(`Mokuro processing failed for pages ${b}-${y} (${j.status}): ${N}`)}const T=await j.json();if(il(c,r,p),T.status==="error")throw new ms(T.error||"Mokuro processing failed");if(!T.mokuro_data)throw new ms("Mokuro response missing mokuro_data");const P={...Cm(T.mokuro_data),creditQuotes:T.creditQuote?[Ih(T.creditQuote)]:[]};n&&Pi.set(p,P),h===null?h={...P,pages:[...P.pages],creditQuotes:[...P.creditQuotes]}:(h.pages.push(...P.pages),h.creditQuotes.push(...P.creditQuotes))}if(h===null)throw new ms("OCR produced no pages.");return h.pages.length!==d&&console.warn(`OCR page-count mismatch: expected ${d}, got ${h.pages.length}. Proceeding with the pages Mokuro returned.`),ol=null,Pi=new Map,a?.({phase:"done",message:"OCR complete"}),h}function Ih(t){if(!t||typeof t!="object"||Array.isArray(t))throw new ms("OCR response contained an invalid credit quote.");const a=t,s=n=>{const r=a[n];if(typeof r!="number"||!Number.isSafeInteger(r)||r<0)throw new ms("OCR response contained an invalid credit quote.");return Number(r)};
67if(typeof a.quoteId!="string"||typeof a.rateVersion!="string"||typeof a.expiresAt!="string"||Number.isNaN(Date.parse(a.expiresAt))||typeof a.affordable!="boolean"||!a.breakdown||typeof a.breakdown!="object"||Array.isArray(a.breakdown))throw new ms("OCR response contained an invalid credit quote.");return{quoteId:a.quoteId,maximumReservation:s("maximumReservation"),expectedCharge:s("expectedCharge"),affordableReservation:s("affordableReservation"),requestedUnitCount:s("requestedUnitCount"),selectedUnitCount:s("selectedUnitCount"),affordable:a.affordable,breakdown:a.breakdown,rateVersion:a.rateVersion,expiresAt:a.expiresAt}}async function Yx(t,a,s,n,r){let i;try{i=await fetch(t,{method:"POST",headers:{Authorization:`Bearer ${a}`,"X-Credit-Operation-Key":n},body:s,signal:r})}catch(d){if(d?.name==="AbortError")throw d;return}if(i.status===404)return;let l=null;try{l=await i.json()}catch{}if(!i.ok||l?.previewAvailable!==!0)return;const c=Ih(l.creditQuote);if(!c.affordable||c.selectedUnitCount===0)throw new ms("Not enough shared credits to start this OCR chunk. Reduce the workload or wait for reset.")}async function Jx(t,a,s,n,r,i){const l={method:"POST",headers:{Authorization:`Bearer ${a}`,"X-Mokuro-Page-Count":String(n),"X-Credit-Operation-Key":r},body:s,signal:i};let c=null;try{const d=await fetch(t,l);if(d.status!==425)return d}catch(d){if(d?.name==="AbortError")throw d;c=d}if(await new Promise(d=>setTimeout(d,Kx)),i?.aborted)throw new DOMException("OCR cancelled","AbortError");try{return await fetch(t,l)}catch(d){const m=d?.message||String(d),u=c?` (first attempt: ${c?.message||String(c)})`:"";throw new ms(`Network error contacting OCR proxy: ${m}${u}`)}}async function Xx(t){const a=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(t));return Array.from(new Uint8Array(a),s=>s.toString(16).padStart(2,"0")).join("")}class ms extends Error{constructor(a){super(a),this.name="MokuroServiceError"}}const Qx=[/[/\\](?:Season|ã·ã¼ãºã³|Saison)\s*(\d+)[/\\]/i,/[/\\]S(\d{1,2})[/\\]/i,/[/\\](?:Part|ãã¼ã|Arc)\s*(\d+)[/\\]/i,/[/\\](?:Cour)\s*(\d+)[/\\]/i],Zx=[/[/\\](?:Movie|Movies|æ ç»|åå ´ç)[/\\]/i,/[/\\](?:Film|Films)[/\\]/i,/[/\\](?:OVA|OAV)s?[/\\]/i,/[/\\](?:Special|Specials|SP)[/\\]/i,/[/\\]Movie\s+/i,/[/\\]Film\s+/i,/[/\\]OVA\s+/i,/[/\\]Special\s+/i,/(?:Movie|Film|æ ç»|åå ´ç)/i,/(?:OVA|OAV)\s*\d*/i,/(?:Special|SP)\s*\d*/i,/(?:Gekijouban|gekijÅban)/i],ew=[/S(\d{1,2})E\d+/i,/(\d{1,2})x\d+/i,/\[(\d{1,2})x\d+\]/i],eu=[/S\d{1,2}E(\d+)/i,/\d{1,2}x(\d+)/i,/\[?\d{1,2}x(\d+)\]?/i,/(?:EP?|Episode|Ep\.)\s*(\d+)/i,/第\s*(\d+)\s*(?:話|é|ç« )/,/(?:Chapter|Ch\.?|話|ç« )\s*(\d+)/i,/(?:#)\s*(\d+)/,/[-â]\s*(\d{1,4})(?:\s*[[(]|$)/,/^(\d{1,4})\s*[-._\s]/,/[-._\s](\d{1,4})\s*(?:\.[^.]+)?$/,/[[(](\d{1,3})[\])](?!p)/i,new RegExp("(?<!\\d)(\\d{1,3})(?![0-9pnd])","i")];function tw(t,a){const s=t+"/"+a;for(const n of Zx)if(n.test(s))return!0;return!1}function aw(t,a){for(const s of Qx){const n=t.match(s);if(n)return{season:parseInt(n[1],10),confidence:"high"}}for(const s of ew){const n=a.match(s);if(n)return{season:parseInt(n[1],10),confidence:"high"}}return{season:1,confidence:"low"}}function sw(t){const a=t.replace(/\.[^/.]+$/,"");for(let s=0;s<eu.length;s++){const n=eu[s],r=a.match(n);if(r){const i=parseInt(r[1],10);if(i>0&&i<1e4){const l=s<4?"high":s<7?"medium":"low";return{episode:i,confidence:l}}}}return{episode:0,confidence:"low"}}function nw(t,a,s,n,r){return n?r.replace(/\.[^/.]+$/,"").replace(/[[(].*?[\])]/g,"").replace(/[-._]/g," ").trim()||"Movie":a===0?"Unknown":s&&t>0?`S${t} E${a}`:`Episode ${a}`}function Pl(t){const a=t.webkitRelativePath||t.name,s=t.name,n=tw(a,s),r=aw(a,s),i=sw(s),l=r.confidence!=="low";let c;return n||r.confidence==="high"&&i.confidence==="high"?c="high":l||i.confidence==="high"?c="medium":c="low",{seasonNumber:n?0:r.season,episodeNumber:i.episode,label:nw(r.season,i.episode,l,n,s),relativePath:a,fileName:s,confidence:c,isMovie:n}}const ns=-1;function Rh(t,a){const s=t[a];if(s===void 0)throw new Error("EBML vint id: out of bounds");const n=$h(s);let r=0;for(let i=0;i<n;
67i++){const l=t[a+i];if(l===void 0)throw new Error("EBML vint id: truncated");r=r*256+l}return{value:r,length:n}}function ho(t,a){const s=t[a];if(s===void 0)throw new Error("EBML vint size: out of bounds");const n=$h(s),r=(1<<8-n)-1;let i=s&r,l=i===r;for(let c=1;c<n;c++){const d=t[a+c];if(d===void 0)throw new Error("EBML vint size: truncated");i=i*256+d,d!==255&&(l=!1)}return l?{value:ns,length:n}:{value:i,length:n}}function $h(t){if(t===0)throw new Error("EBML vint: invalid leading byte 0x00");let a=128,s=1;for(;(t&a)===0;)a>>=1,s++;return s}function bn(t,a,s){let n=0;for(let r=0;r<s;r++)n=n*256+t[a+r];return n}function rw(t,a,s){let n=bn(t,a,s);const r=Math.pow(2,s*8-1);return n>=r&&(n-=r*2),n}function iw(t,a,s){if(s===0)return 0;const n=new DataView(t.buffer,t.byteOffset+a,s);if(s===4)return n.getFloat32(0,!1);if(s===8)return n.getFloat64(0,!1);throw new Error("EBML float: unsupported length "+s)}const ow=new TextDecoder("utf-8");function $r(t,a,s){const n=t.subarray(a,a+s);let r=n.length;for(;r>0&&n[r-1]===0;)r--;return ow.decode(n.subarray(0,r))}async function lw(t){return typeof t.arrayBuffer=="function"?t.arrayBuffer():new Promise((a,s)=>{const n=new FileReader;n.onload=()=>a(n.result),n.onerror=()=>s(n.error??new Error("FileReader failed")),n.readAsArrayBuffer(t)})}class Al{size;blob;chunkSize;signal;offset=0;buffer=new Uint8Array(0);bufferStart=0;constructor(a,s){this.blob=a,this.size=a.size,this.chunkSize=s?.chunkSize??4*1024*1024,this.signal=s?.signal}get pos(){return this.offset}get eof(){return this.offset>=this.size}get progress(){return this.size===0?1:this.offset/this.size}seek(a){if(a<0||a>this.size)throw new Error("seek out of range: "+a);this.offset=a,(a<this.bufferStart||a>=this.bufferStart+this.buffer.length)&&(this.buffer=new Uint8Array(0),this.bufferStart=a)}async readBytes(a){if(a<0)throw new Error("readBytes: negative length");if(this.offset+a>this.size)throw new Error("readBytes: past end of blob");await this.ensure(a);const s=this.offset-this.bufferStart,n=this.buffer.slice(s,s+a);return this.offset+=a,n}skip(a){if(a<0)throw new Error("skip: negative length");this.offset+=a,this.offset>this.size&&(this.offset=this.size),(this.offset<this.bufferStart||this.offset>=this.bufferStart+this.buffer.length)&&(this.buffer=new Uint8Array(0),this.bufferStart=this.offset)}async ensure(a){const s=this.offset-this.bufferStart,n=this.buffer.length-s;s>=0&&n>=a||await this.fill(a)}async fill(a){this.throwIfAborted();const s=this.offset,n=Math.max(a,this.chunkSize),r=Math.min(this.size,s+n),i=await lw(this.blob.slice(s,r));if(this.throwIfAborted(),this.buffer=new Uint8Array(i),this.bufferStart=s,this.buffer.length<a)throw new Error("readBytes: past end of blob")}throwIfAborted(){if(this.signal?.aborted)throw new DOMException("Aborted","AbortError")}}const Ht={EBML:440786851,Segment:408125543,SeekHead:290298740,Seek:19899,SeekID:21419,SeekPosition:21420,Info:357149030,TimestampScale:2807729,Duration:17545,Tracks:374648427,TrackEntry:174,TrackNumber:215,TrackType:131,CodecID:134,CodecPrivate:25506,TrackName:21358,Language:2274716,LanguageBCP47:2274717,FlagDefault:136,FlagForced:21930,Cluster:524531317,ClusterTimestamp:231,SimpleBlock:163,BlockGroup:160,Block:161,BlockDuration:155},cw=17,dw=1e6,zh=2e3,uw=4;
67class Ss extends Error{code;constructor(a,s){super(s??a),this.name="MkvParseError",this.code=a}}function mw(t){return t==="S_TEXT/UTF8"?"srt":t==="S_TEXT/ASS"||t==="S_TEXT/SSA"?"ass":"unsupported"}async function hs(t){if(t.eof)return null;const a=t.size-t.pos,s=Math.min(12,a);if(s<1)return null;const n=t.pos,r=await t.readBytes(s),i=Rh(r,0),l=ho(r,i.length),c=i.length+l.length;return t.seek(n+c),{id:i.value,size:l.value,headerLength:c}}async function hw(t){const a=new Al(t),s=await Fh(a);return{tracks:s.tracks.map(pw),durationMs:s.durationMs}}function pw(t){const{codecPrivate:a,...s}=t;return s}async function Fh(t){if(t.size<uw)throw new Ss("not_mkv","file too small to be MKV");let a;try{a=await hs(t)}catch(m){throw m instanceof DOMException&&m.name==="AbortError"?m:new Ss("not_mkv","not an EBML stream")}if(!a||a.id!==Ht.EBML)throw new Ss("not_mkv","missing EBML header");if(a.size===ns)throw new Ss("not_mkv","unknown-size EBML header");t.skip(a.size);const s=await hs(t);if(!s||s.id!==Ht.Segment)throw new Ss("not_mkv","missing Segment");const n=t.pos,r=s.size===ns?t.size:n+s.size,i={tracks:[],durationMs:null,timestampScale:dw,firstClusterPos:null},l=await fw(t,n,r);let c=!1,d=!1;if(l){if(l.infoPos!==null){t.seek(l.infoPos);const m=await hs(t);m&&m.id===Ht.Info&&m.size!==ns&&(await tu(t,t.pos+m.size,i),d=!0)}if(l.tracksPos!==null){t.seek(l.tracksPos);const m=await hs(t);m&&m.id===Ht.Tracks&&m.size!==ns&&(await au(t,t.pos+m.size,i),c=!0)}l.firstClusterPos!==null&&(i.firstClusterPos=l.firstClusterPos)}if(!c||!d)for(t.seek(n);t.pos<r;){const m=await hs(t);if(!m)break;const u=t.pos;if(m.id===Ht.Cluster){if(i.firstClusterPos===null&&(i.firstClusterPos=u-m.headerLength),!c)throw new Ss("parse","Tracks not found before first Cluster");break}if(m.size===ns)throw new Ss("parse","unexpected unknown-size top-level element");const h=u+m.size;m.id===Ht.Tracks&&!c?(await au(t,h,i),c=!0):m.id===Ht.Info&&!d&&(await tu(t,h,i),d=!0),t.seek(h)}if(!c)throw new Ss("parse","Tracks element not found");return i}async function fw(t,a,s){t.seek(a);let n=null,r=0;for(;t.pos<s&&r<16;){r++;const i=await hs(t);if(!i)break;const l=t.pos;if(i.size===ns)return n;const c=l+i.size;if(i.id===Ht.SeekHead)return n=await gw(t,c,a),t.seek(c),n;if(i.id===Ht.Cluster||i.id===Ht.Tracks||i.id===Ht.Info)return n;t.seek(c)}return n}async function gw(t,a,s){const n={tracksPos:null,infoPos:null,firstClusterPos:null};for(;t.pos<a;){const r=await hs(t);if(!r)break;const i=t.pos;if(r.size===ns)break;const l=i+r.size;if(r.id===Ht.Seek){let c=null,d=null;for(;t.pos<l;){const m=await hs(t);if(!m||m.size===ns)break;const h=t.pos+m.size;if(m.id===Ht.SeekID){const p=await t.readBytes(m.size);c=Rh(p,0).value}else if(m.id===Ht.SeekPosition){const p=await t.readBytes(m.size);d=bn(p,0,m.size)}t.seek(h)}if(c!==null&&d!==null){const m=s+d;c===Ht.Tracks?n.tracksPos=m:c===Ht.Info?n.infoPos=m:c===Ht.Cluster&&n.firstClusterPos===null&&(n.firstClusterPos=m)}}t.seek(l)}return n}async function tu(t,a,s){let n=null;for(;t.pos<a;){const r=await hs(t);if(!r||r.size===ns)break;const l=t.pos+r.size;if(r.id===Ht.TimestampScale){const c=await t.readBytes(r.size);s.timestampScale=bn(c,0,r.size)}else if(r.id===Ht.Duration){const c=await t.readBytes(r.size);n=iw(c,0,r.size)}t.seek(l)}n!==null&&(s.durationMs=Math.round(n*s.timestampScale/1e6))}async function au(t,a,s){for(;t.pos<a;){const n=await hs(t);if(!n||n.size===ns)break;const i=t.pos+n.size;if(n.id===Ht.TrackEntry){const l=await yw(t,i);l&&s.tracks.push(l)}t.seek(i)}}async function yw(t,a){let s=null,n=null,r="",i=null,l=null,c=null,d=null,m=!0,u=!1;for(;t.pos<a;){const p=await hs(t);if(!p||p.size===ns)break;const f=t.pos+p.size;switch(p.id){case Ht.TrackNumber:{const b=await t.readBytes(p.size);s=bn(b,0,p.size);break}case Ht.TrackType:{const b=await t.readBytes(p.size);n=bn(b,0,p.size);break}case Ht.CodecID:{const b=await t.readBytes(p.size);r=$r(b,0,p.size);break}case Ht.CodecPrivate:{const b=await t.readBytes(p.size);i=$r(b,0,p.size);break}case Ht.TrackName:{const b=await t.readBytes(p.size);l=$r(b,0,p.size);break}case Ht.Language:{const b=await t.readBytes(p.size);c=$r(b,0,p.size);break}case Ht.LanguageBCP47:{const b=await t.readBytes(p.size);d=$r(b,0,p.size);break}case Ht.FlagDefault:{const b=await t.readBytes(p.size);m=bn(b,0,p.size)!==0;break}case Ht.FlagForced:{const b=await t.readBytes(p.size);u=bn(b,0,p.size)!==0;break}}t.seek(f)}if(n!==cw||s===null)return null;const h=d??c??"eng";return{trackNumber:s,codecId:r,kind:mw(r),language:h,name:l,isDefault:m,isForced:u,codecPrivate:i}}async function bw(t,a,s){const n=s?.signal,r=s?.onProgress,i=new Al(t,{signal:n}),l=await Fh(i),c=l.tracks.find(x=>x.trackNumber===a);if(!c)throw new Ss("parse","track "+a+" not found");if(c.kind==="unsupported")throw new Ss("parse","track "+a+" is not a text subtitle track");const d=l.timestampScale/1e6,m=new Al(t,{signal:n}),u=await xw(m,l);m.seek(u);const h=[];let p=0;const g=()=>p++;let f=0;const b=x=>{const v=Math.max(f,Math.min(1,Math.max(0,x)));f=v,r?.(v)};for(b(0);!m.eof;){Tw(n);const x=await hs(m);if(!x)break;const v=m.pos;if(x.id===Ht.Cluster){const w=x.size===ns?null:v+x.size;await ww(m,w,a,d,h,g)}else{if(x.size===ns)break;m.skip(x.size)}b(m.progress)}
67return b(1),c.kind==="ass"?{format:"ass",content:Nw(c.codecPrivate,h),cueCount:h.length}:{format:"srt",content:Ew(h),cueCount:h.length}}async function xw(t,a){if(a.firstClusterPos!==null)return a.firstClusterPos;t.seek(0);const s=await hs(t);if(!s||s.size===ns)throw new Ss("parse","bad EBML header");t.skip(s.size);const n=await hs(t);if(!n)throw new Ss("parse","missing Segment");const r=t.pos,i=n.size===ns?t.size:r+n.size;for(t.seek(r);t.pos<i;){const l=t.pos,c=await hs(t);if(!c)break;if(c.id===Ht.Cluster)return l;if(c.size===ns)break;t.skip(c.size)}return t.size}async function ww(t,a,s,n,r,i){let l=0;for(;a===null?!t.eof:t.pos<a;){const c=t.pos,d=await hs(t);if(!d)break;const m=t.pos;if(a===null&&_w(d.id)){t.seek(c);return}if(d.size===ns){t.seek(c);return}const u=m+d.size;if(d.id===Ht.ClusterTimestamp){const h=await t.readBytes(d.size);l=bn(h,0,d.size),t.seek(u)}else if(d.id===Ht.SimpleBlock){const h=await t.readBytes(d.size);Dh(h,s,l,n,null,r,i),t.seek(u)}else d.id===Ht.BlockGroup?(await vw(t,u,s,l,n,r,i),t.seek(u)):t.skip(d.size)}}async function vw(t,a,s,n,r,i,l){let c=null,d=null;for(;t.pos<a;){const m=await hs(t);if(!m||m.size===ns)break;const h=t.pos+m.size;if(m.id===Ht.Block)c=await t.readBytes(m.size);else if(m.id===Ht.BlockDuration){const p=await t.readBytes(m.size);d=bn(p,0,m.size)}t.seek(h)}if(c){const m=d!==null?d*r:null;Dh(c,s,n,r,m,i,l)}}function Dh(t,a,s,n,r,i,l){let c=0;const d=ho(t,c);if(c+=d.length,d.value!==a)return;const m=rw(t,c,2);c+=2;const u=t[c];c+=1;const h=(s+m)*n,p=(u&6)>>1,g=[];if(p===0)g.push(t.subarray(c));else{const b=t[c]+1;c+=1;const y=[];if(p===2){const x=Math.floor((t.length-c)/b);for(let v=0;v<b;v++)y.push(x)}else if(p===1){let x=0;for(let v=0;v<b-1;v++){let w=0,j;do j=t[c++],w+=j;while(j===255);y.push(w),x+=w}y.push(t.length-c-x)}else{const x=ho(t,c);c+=x.length;let v=x.value;y.push(v);let w=v;for(let j=1;j<b-1;j++){const T=jw(t,c);c+=T.length,v+=T.value,y.push(v),w+=v}y.push(t.length-c-w)}for(const x of y)g.push(t.subarray(c,c+x)),c+=x}const f=new TextDecoder("utf-8");for(const b of g){const y=f.decode(b);i.push({startMs:h,endMs:r!==null?h+r:null,payload:y,readOrder:kw(y),blockSeq:l()})}}function jw(t,a){const s=ho(t,a),n=Math.pow(2,7*s.length-1)-1;return{value:s.value-n,length:s.length}}function kw(t){const a=t.indexOf(","),s=a===-1?t:t.slice(0,a),n=parseInt(s.trim(),10);return Number.isFinite(n)?n:0}function _w(t){return t===Ht.Cluster||t===Ht.Tracks||t===Ht.Info||t===Ht.SeekHead||t===Ht.Segment||t===Ht.EBML||t===475249515||t===423732329||t===272869232||t===307544935}function Vn(t,a){let s=String(Math.floor(t));for(;s.length<a;)s="0"+s;return s}function su(t){const a=Math.round(t/10),s=a%100,n=Math.floor(a/100),r=n%60,i=Math.floor(n/60)%60;return Math.floor(n/3600)+":"+Vn(i,2)+":"+Vn(r,2)+"."+Vn(s,2)}function nu(t){const a=Math.floor(t%1e3),s=Math.floor(t/1e3),n=s%60,r=Math.floor(s/60)%60,i=Math.floor(s/3600);return Vn(i,2)+":"+Vn(r,2)+":"+Vn(n,2)+","+Vn(a,3)}const Lh=`Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text 68`,Sw=`[Events] 69`+Lh;function Nw(t,a){const s=[...a].sort((c,d)=>c.startMs!==d.startMs?c.startMs-d.startMs:c.readOrder-d.readOrder);let n=(t??"").replace(/\r\n/g,` 70`).replace(/\r/g,` 71`);const r=n.toLowerCase(),i=r.indexOf("[events]");if(i===-1)n.length>0&&!n.endsWith(` 72`)&&(n+=` 73`),n+=Sw;else{const c=r.slice(i);/\n\s*format\s*:/i.test(c)||(n.endsWith(` 74`)||(n+=` 75`),n+=Lh)}n.endsWith(` 76`)||(n+=` 77`);const l=[];for(const c of s){const d=Cw(c.payload,8);if(d.length<9)continue;const[,m,u,h,p,g,f,b,y]=d,x=su(c.startMs),v=su(c.endMs??c.startMs+zh);l.push("Dialogue: "+[m,x,v,u,h,p,g,f,b,y].join(","))}return n+l.join(` 78`)+(l.length?` 79`:"")}function Cw(t,a){const s=[];let n=0;for(let r=0;r<a;r++){const i=t.indexOf(",",n);if(i===-1)return s.push(t.slice(n)),s;s.push(t.slice(n,i)),n=i+1}return s.push(t.slice(n)),s}function Ew(t){const a=[...t].sort((r,i)=>r.startMs!==i.startMs?r.startMs-i.startMs:r.blockSeq-i.blockSeq),s=[];let n=0;for(const r of a){const i=r.payload.replace(/\r\n/g,` 80`).replace(/\r/g,` 81`).trim();if(!i)continue;n++;const l=nu(r.startMs),c=nu(r.endMs??r.startMs+zh);s.push(n+` 82`+l+" --> "+c+` 83`+i+` 84`)}return s.join(` 85`)}function Tw(t){if(t?.aborted)throw new DOMException("Aborted","AbortError")}const Mw=1048576,Pw="Only MKV embedded-subtitle extraction is supported â extract the track to .srt/.ass externally for other containers.",Yi="No text subtitle tracks foun
85d â image-based (PGS/VobSub) subs arenât supported.",Aw="Embedded track exceeds the 1 MB subtitle limit";function Iw(t){return t.toLowerCase().trim().endsWith(".mkv")}function Il(t){return`${t.codecId}|${t.language??""}|${t.name??""}`}function Rw(t){return t.map(Il).sort().join("||")}function gn(t){return t.kind==="ass"||t.kind==="srt"}function $w(t){const a=t.filter(r=>r.tracks&&r.tracks.some(gn));return a.length===0||a.every(r=>(r.tracks??[]).filter(gn).length===1)?"auto":new Set(a.map(r=>Rw(r.tracks??[]))).size===1?"batch":"per-file"}const Oh=["mp4","mkv","webm","m4v","avi","mov"],Bh=Oh.map(t=>`.${t}`);function zw(t){const a=String(t??"").toLowerCase().trim();return Bh.some(s=>a.endsWith(s))}const Fw=Bh.filter(t=>t!==".mkv"),Dw=[".srt",".ass",".ssa"];function $c(t){return t.toLowerCase().trim()}function Lw(t){return t.replace(/\.[^.\\/]+$/,"")}function Ow(t){const a=$c(t);return Fw.some(s=>a.endsWith(s))}function Bw(t){const a=$c(t);return Dw.some(s=>a.endsWith(s))}const ru=Iw;function iu(t){return Lw($c(t))}function ou(t){const a=Pl({name:t});return a.episodeNumber>0?`S${a.seasonNumber}E${a.episodeNumber}`:null}function qw(t){const a=[],s=[],n=[];for(const h of t){const p=h.file.name;ru(p)?a.push(h):Ow(p)?s.push(h):Bw(p)&&n.push(h)}const r=[],i=[],l=[],c=[],d=new Set,m=[...s,...a];if(m.length===1&&n.length===1)i.push({subtitle:n[0].file,videoFile:m[0].file,videoFilename:m[0].file.name,handle:m[0].handle}),d.add(0);else{const h=new Map,p=new Map;n.forEach((f,b)=>{const y=iu(f.file.name);(h.get(y)??h.set(y,[]).get(y)).push(b);const x=ou(f.file.name);x&&(p.get(x)??p.set(x,[]).get(x)).push(b)});const g=f=>{if(!f)return null;for(const b of f)if(!d.has(b))return b;return null};for(const f of m){let b=g(h.get(iu(f.file.name)));if(b==null){const y=ou(f.file.name);y&&(b=g(p.get(y)))}b!=null?(d.add(b),i.push({subtitle:n[b].file,videoFile:f.file,videoFilename:f.file.name,handle:f.handle})):ru(f.file.name)?r.push(f):(l.push(f.file.name),c.push(f))}}const u=[];return n.forEach((h,p)=>{d.has(p)||u.push(h.file)}),{mkv:r,paired:i,looseSubtitles:u,unpairedVideoNames:l,unpairedVideos:c}}function Uw(t){return`${t} is ready. Add it to Cloud Library, then generate Japanese subtitles from its audio.`}const Vw="jpapp-video-file-handles",Kw=1,cn="handles",zc=new Map,dn=typeof window<"u"&&typeof indexedDB<"u"&&typeof window.showOpenFilePicker=="function";function ui(t,a){zc.set(t,a)}function qh(t){return zc.get(t)??null}function Io(){return new Promise((t,a)=>{const s=indexedDB.open(Vw,Kw);s.onupgradeneeded=()=>{const n=s.result;n.objectStoreNames.contains(cn)||n.createObjectStore(cn,{keyPath:"episodeId"})},s.onsuccess=()=>t(s.result),s.onerror=()=>a(s.error)})}async function po(t,a){if(dn)try{const s=await Io();try{await new Promise((n,r)=>{const i=s.transaction(cn,"readwrite");i.objectStore(cn).put({episodeId:t,handle:a,name:a.name}),i.oncomplete=()=>n(),i.onerror=()=>r(i.error),i.onabort=()=>r(i.error)})}finally{s.close()}}catch{}}async function Uh(t){if(!dn)return null;try{const a=await Io();try{return(await new Promise((n,r)=>{const l=a.transaction(cn,"readonly").objectStore(cn).get(t);l.onsuccess=()=>n(l.result),l.onerror=()=>r(l.error)}))?.name??null}finally{a.close()}}catch{return null}}async function fo(t){const a=qh(t);if(a)return a;if(!dn)return null;try{const s=await Io();let n;try{n=(await new Promise((d,m)=>{const h=s.transaction(cn,"readonly").objectStore(cn).get(t);h.onsuccess=()=>d(h.result),h.onerror=()=>m(h.error)}))?.handle}finally{s.close()}if(!n)return null;const r={mode:"read"};let i=await n.queryPermission(r);if(i!=="granted"&&(i=await n.requestPermission(r)),i!=="granted")return null;const l=await n.getFile();return ui(t,l),l}catch{return null}}async function Hw(t){if(zc.delete(t),!!dn)try{const a=await Io();try{await new Promise((s,n)=>{const r=a.transaction(cn,"readwrite");r.objectStore(cn).delete(t),r.oncomplete=()=>s(),r.onerror=()=>n(r.error),r.onabort=()=>n(r.error)})}finally{a.close()}}catch{}}function Fc(t,a,s){try{if(typeof localStorage>"u")return s;const n=localStorage.getItem(t);if(!n)return s;const r=JSON.parse(n);return a(r)??s}catch{return s}}function Dc(t,a){try{if(typeof localStorage>"u")return;localStorage.setItem(t,JSON.stringify(a))}catch{}}const Lc=64*1024*1024,Ww=3,lu=3,Gw=2e3,Yw=Oh;function cu(t,a=Lc){return!Number.isFinite(t)||t<=0?0:Math.ceil(t/a)}function Jw(t,a,s=Lc){const n=(t-1)*s,r=Math.min(n+s,a);return{start:n,end:r}}function Xw(t){const a=/\.([a-z0-9]+)$/i.exec(t.trim());if(!a)return null;const s=a[1].toLowerCase();return Yw.includes(s)?s:null}function Qw(t,a){return t.fileName===a.name&&t.declaredBytes===a.size&&t.lastModified===a.lastModified}const Zw="immersion.cloud.videoLedger.v1.";function Oc(t){return`${Zw}${t}`}function ev(t){return Fc(Oc(t),a=>{if(!a||typeof a!="object")return null;const s=a;if(typeof s.uploadId!="string"||typeof s.declaredBytes!="number"||typeof s.partCount!="number"||typeof s.ext!="string")return null;const n={};if(s.uploadedParts&&typeof s.uploadedParts=="object")for(const[r,i]of Object.entries(s.uploadedParts)){const l=Number(r);Number.isInteger(l)&&typeof i=="string"&&(n[l]=i)}return{episodeId:t,uploadId:s.uploadId,declaredBytes:s.declaredBytes,ext:s.ext,partCount:s.partCount,fileName:typeof s.fileName=="string"?s.fileName:"",lastModified:typeof s.lastModified=="number"?s.lastModified:-1,uploadedParts:n}},null)}function du(t){Dc(Oc(t.episodeId),t)}function ur(t){try{if(typeof localStorage>"u")return;localStorage.removeItem(Oc(t))}catch{}}function Bc(t){return{fetch:(...a)=>fetch(...a),getAccessToken:t,apiBase:ue,sleep:a=>new Promise(s=>setTimeout(s,a))}}async function Vh(t,a,s,n){const{episodeId:r,file:i}=t,l=a.apiBase(),c=Xw(i.name);if(!c)return{kind:"error",retryable:!1,message:"Unsupported video type â MP4, MKV, WebM, M4V, AVI or MOV only"};const d=i.size;if(d<=0)return{kind:"error",retryable:!1,message:"Empty video file"};const m=cu(d);let u=ev(r);u&&!Qw(u,i)&&(u=null,ur(r));const h=await a.getAccessToken();if(!h)return{kind:"error",retryable:!0,message:"Not authenticated"};let p;try{p=await a.fetch(`${l}/api/video/episodes/${r}/cloud-sync/init`,{method:"POST",headers:{Authorization:`Bearer ${h}`,"Content-Type":"application/json"},body:JSON.stringify({declaredBytes:d,ext:c,partCount:m}),signal:n})}catch(k){return n?.aborted?{kind:"aborted"}:{kind:"error",retryable:!0,message:k instanceof Error?k.message:"init network error"}}const g=await tv(p);if(g)return g;const f=await p.json();if(f.alreadySynced)return ur(r),{kind:"synced",bytes:d};const b=typeof f.partSizeBytes=="number"&&f.partSizeBytes>0?f.partSizeBytes:Lc,y=typeof f.partCount=="number"&&f.partCount>0?f.partCount:m,x=cu(d,b);if(y!==x)return ur(r),{kind:"error",retryable:!1,message:`Part-count mismatch: server ${y} vs local ${x} (partSize ${b})`};const v=f.parts??[],w={};for(const k of f.uploadedParts??[])k.partNumber>=1&&k.partNumber<=y&&typeof k.etag=="string"&&k.etag&&(w[k.partNumber]=k.etag);const j=new Set(v.map(k=>k.partNumber));if(u&&u.uploadId===f.uploadId)for(const[k,J]of Object.entries(u.uploadedParts)){const M=Number(k);M>=1&&M<=y&&!j.has(M)&&!(M in w)&&(w[M]=J)}u={episodeId:r,uploadId:f.uploadId,declaredBytes:d,ext:c,partCount:y,fileName:i.name,lastModified:i.lastModified,uploadedParts:w},du(u);let T=y-v.length;s?.(T,y);const N=await sv(v,Ww,async k=>
85{if(n?.aborted)return{kind:"aborted"};const{start:J,end:M}=Jw(k.partNumber,d,b),H=i.slice(J,M),ee=await av(a,k.url,H,n);return ee.ok?(u.uploadedParts[k.partNumber]=ee.etag,du(u),T+=1,s?.(T,y),null):ee.aborted?{kind:"aborted"}:{kind:"error",retryable:ee.retryable,message:ee.message}},n);if(N)return N;const _=[];for(let k=1;k<=y;k++){const J=u.uploadedParts[k];if(!J)return{kind:"error",retryable:!0,message:`Missing ETag for part ${k}`};_.push({partNumber:k,etag:J})}const L=await a.getAccessToken();if(!L)return{kind:"error",retryable:!0,message:"Not authenticated"};let q;try{q=await a.fetch(`${l}/api/video/episodes/${r}/cloud-sync/complete`,{method:"POST",headers:{Authorization:`Bearer ${L}`,"Content-Type":"application/json"},body:JSON.stringify({parts:_,declaredBytes:d}),signal:n})}catch(k){return n?.aborted?{kind:"aborted"}:{kind:"error",retryable:!0,message:k instanceof Error?k.message:"complete network error"}}if(q.status===503)return{kind:"unavailable"};if(q.status===413){const k=await Ls(q)??void 0;return ur(r),{kind:"quota_exceeded",quota:k}}if(q.status===409)return{kind:"error",retryable:!0,message:"Upload verification failed â will retry"};if(q.status===401)return{kind:"error",retryable:!0,message:"complete 401"};if(!q.ok)return{kind:"error",retryable:q.status>=500,message:`complete ${q.status}`};const O=await q.json().catch(()=>({}));return ur(r),{kind:"synced",bytes:typeof O.cloud_size_bytes=="number"?O.cloud_size_bytes:typeof O.bytes=="number"?O.bytes:d}}async function tv(t){if(t.ok)return null;if(t.status===503)return{kind:"unavailable"};
85if(t.status===413)return{kind:"quota_exceeded",quota:await Ls(t)??void 0};if(t.status===403){const s=await t.json().catch(()=>({}));return s.error==="ATTESTATION_REQUIRED"||s.code==="ATTESTATION_REQUIRED"?{kind:"attestation_required"}:{kind:"error",retryable:!1,message:"Cloud video requires Pro"}}return t.status===404?{kind:"error",retryable:!1,message:"Episode not found"}:{kind:"error",retryable:t.status!==400,message:`init ${t.status}`}}async function av(t,a,s,n){let r="";for(let i=1;i<=lu;i++){if(n?.aborted)return{ok:!1,etag:"",retryable:!0,aborted:!0,message:"Aborted"};try{const l=await t.fetch(a,{method:"PUT",body:s,headers:{"Content-Type":s.type||"application/octet-stream"},signal:n});if(l.ok){const d=(l.headers.get("ETag")??l.headers.get("etag")??"").replace(/"/g,"");return d?{ok:!0,etag:d,retryable:!1,aborted:!1,message:""}:{ok:!1,etag:"",retryable:!1,aborted:!1,message:"Part PUT missing ETag"}}if(r=`PUT ${l.status}`,!(l.status>=500||l.status===429))return{ok:!1,etag:"",retryable:!1,aborted:!1,message:r}}catch(l){if(n?.aborted)return{ok:!1,etag:"",retryable:!0,aborted:!0,message:"Aborted"};r=l instanceof Error?l.message:"network error"}i<lu&&await t.sleep(Gw*2**(i-1))}return{ok:!1,etag:"",retryable:!0,aborted:!1,message:r||"part upload failed"}}async function sv(t,a,s,n){if(t.length===0)return null;let r=0,i=null;const l=Array.from({length:Math.min(a,t.length)},async()=>{for(;r<t.length&&!i;){if(n?.aborted){i=i??{kind:"aborted"};return}const c=r++,d=await s(t[c]);if(d){i=i??d;return}}});return await Promise.all(l),i}async function Kh(t,a){ur(t);const s=await a.getAccessToken();if(!s)return!1;try{return(await a.fetch(`${a.apiBase()}/api/video/episodes/${t}/cloud-sync/abort`,{method:"POST",headers:{Authorization:`Bearer ${s}`}})).ok}catch{return!1}}const nv="immersion.cloud.videoAttested.v1";function Hh(t){const a=(t??"").trim();return a?`${nv}:${a}`:null}function Wh(t){try{if(typeof localStorage>"u")return!1;const a=Hh(t);return a?localStorage.getItem(a)==="1":!1}catch{return!1}}function rv(t){try{if(typeof localStorage>"u")return;const a=Hh(t);if(!a)return;localStorage.setItem(a,"1")}catch{}}async function iv(t,a){const s=await t.getAccessToken();if(!s)return{ok:!1,status:401,message:"Not authenticated"};let n;try{n=await t.fetch(`${t.apiBase()}/api/video/cloud-video/attest`,{method:"POST",headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json"},body:JSON.stringify({})})}catch(i){return{ok:!1,status:0,message:i instanceof Error?i.message:"Network error"}}if(!n.ok)return{ok:!1,status:n.status,message:`attest failed (${n.status})`};const r=await n.json().catch(()=>({}));return rv(a),{ok:!0,attestedAt:r.attestedAt}}async function Gh(t,a,s=fetch){const n=await a();if(!n)return{ok:!1,status:401,message:"Not authenticated"};let r;try{r=await s(`${ue()}/api/video/episodes/${t}/stream-url`,{headers:{Authorization:`Bearer ${n}`}})}catch(l){return{ok:!1,status:0,message:l instanceof Error?l.message:"Network error"}}if(r.status===409){const l=await r.json().catch(()=>({}));return{ok:!1,status:409,code:l.error??l.code??"NOT_SYNCED",message:"Episode not synced"}}if(!r.ok)return{ok:!1,status:r.status,message:`stream-url failed (${r.status})`};const i=await r.json().catch(()=>null);return!i||typeof i.url!="string"?{ok:!1,status:r.status,message:"Malformed stream-url response"}:{ok:!0,url:i.url,ttlSeconds:typeof i.ttlSeconds=="number"?i.ttlSeconds:3e3}}const ov=Object.freeze({status:"idle"});function lv(t){const a=t.toLowerCase();return a.includes("not authenticated")||a.includes("401")?"auth":a.includes("unsupported")||a.includes("empty")?"bad_file":a.includes("requires pro")?"tier":a.includes("not found")||a.includes("404")?"not_found":a.includes("verification")?"verify":a.includes("etag")?"etag":a.includes("init")?"init":a.includes("complete")?"complete":a.includes("put")?"put":a.includes("network")?"network":"other"}class cv{deps=null;queue=[];states=new Map;listeners=new Set;running=!1;currentAbort=null;currentEpisodeId=null;cancelled=new Set;unavailable=!1;quotaHit=!1;startedAt=new Map;configure(a){this.deps=Bc(a),this.queue.length>0&&this.pump()}_setDeps(a){this.deps=a,this.unavailable=!1,this.queue.length>0&&this.pump()}_reset(){this.deps=null,this.queue=[],this.states.clear(),this.cancelled.clear(),this.startedAt.clear(),this.currentEpisodeId=null,this.unavailable=!1,this.quotaHit=!1,this.running=!1,this.currentAbort?.abort(),this.currentAbort=null}subscribe(a){return this.listeners.add(a),a(new Map(this.states)),()=>{this.listeners.delete(a)}}getState(a){return this.states.get(a)??ov}seasonProgress(){let a=0,s=0,n=0,r=0;for(const l of this.states.values())switch(l.status){case"synced":a++;break;case"error":s++;break;case"quota_exceeded":s++;break;case"skipped_quota":n++;break;case"queued":case"uploading":r++;break}const i=this.states.size;return{total:i,synced:a,failed:s,skipped:n,done:i>0&&r===0,quotaHit:this.quotaHit}}emit(){const a=new Map(this.states);for(const s of this.listeners)s(a)}
85setState(a,s){this.states.set(a,s),this.emit()}clearState(a){this.queue=this.queue.filter(s=>s.episodeId!==a),this.cancelled.add(a),this.currentEpisodeId===a&&this.currentAbort?.abort(),this.states.delete(a)&&this.emit()}enqueue(a){if(this.unavailable||this.queue.some(n=>n.episodeId===a.episodeId))return;const s=this.states.get(a.episodeId);s?.status==="uploading"||s?.status==="queued"||(this.cancelled.delete(a.episodeId),this.queue.push(a),this.setState(a.episodeId,{status:"queued"}),this.pump())}enqueueSeason(a){this.unavailable=!1,this.quotaHit=!1;for(const s of a)this.enqueue(s)}async cancel(a){this.clearState(a),this.deps&&await Kh(a,this.deps)}async _drain(){for(;this.running||this.queue.length>0;)await new Promise(a=>setTimeout(a,0))}durationOf(a){const s=this.startedAt.get(a);return s!=null?Math.max(0,Date.now()-s):void 0}async pump(){if(!this.running&&this.deps){this.running=!0;try{for(;this.queue.length>0&&!this.unavailable;){const a=this.queue.shift();if(this.cancelled.has(a.episodeId))continue;this.currentEpisodeId=a.episodeId,this.startedAt.set(a.episodeId,Date.now()),ne("cloud_video_sync_started",{bytes:a.file.size}),this.setState(a.episodeId,{status:"uploading",uploaded:0,total:0}),this.currentAbort=new AbortController;let s;try{s=await Vh(a,this.deps,(n,r)=>{this.cancelled.has(a.episodeId)||this.setState(a.episodeId,{status:"uploading",uploaded:n,total:r})},this.currentAbort.signal)}catch(n){s={kind:"error",retryable:!0,message:n instanceof Error?n.message:"sync failed"}}this.currentEpisodeId=null,this.currentAbort=null,!this.cancelled.has(a.episodeId)&&this.applyOutcome(a,s)}}finally{this.running=!1,this.currentEpisodeId=null,this.currentAbort=null}}}applyOutcome(a,s){const{episodeId:n}=a;switch(s.kind){case"synced":ne("cloud_video_sync_completed",{bytes:s.bytes,duration_ms:this.durationOf(n)}),this.setState(n,{status:"synced"});return;case"attestation_required":this.setState(n,{status:"error",retryable:!0,message:"Attestation required â retry from the episode"});return;case"unavailable":this.unavailable=!0;for(const r of this.queue){const i=this.states.get(r.episodeId)?.status;(i==="uploading"||i==="queued")&&this.states.delete(r.episodeId)}this.queue=[],this.setState(n,{status:"unavailable"});return;case"quota_exceeded":ne("cloud_video_sync_failed",{bytes:a.file.size,error_kind:"quota",duration_ms:this.durationOf(n)}),this.quotaHit=!0,this.setState(n,{status:"quota_exceeded"});for(const r of this.queue)this.states.set(r.episodeId,{status:"skipped_quota"});this.queue=[],this.emit();return;case"aborted":this.states.delete(n),this.emit();return;case"error":ne("cloud_video_sync_failed",{bytes:a.file.size,error_kind:lv(s.message),retryable:s.retryable,duration_ms:this.durationOf(n)}),this.setState(n,{status:"error",retryable:s.retryable,message:s.message});return}}}const Jn=new cv,cl=2e3,dv=15e3,Yh=6e4,Rl=30*6e4,uv=.2;class mv extends Error{constructor(){super("Material status request timed out"),this.name="MaterialStatusRequestTimeoutError"}}async function hv(t,a={}){const s=new AbortController;let n=!1;a.onController?.(s);const r=setTimeout(()=>{n=!0,s.abort()},Math.max(1,a.timeoutMs??dv));try{return await t(s.signal)}catch(i){throw n?new mv:i}finally{clearTimeout(r)}}function pv(t){const a=Yh-t.transientElapsedMs,s=Rl-t.totalElapsedMs,n=Math.min(a,s),r=s<=a?"total":"transient";if(n<=0)return{kind:"expire",delayMs:0,reason:r};const i=to(t.consecutiveFailures,{retryAfterMs:t.retryAfterMs});if(t.retryAfterMs!=null&&i>n||n<eo)return{kind:"expire",delayMs:n,reason:r};const l=Math.min(1,Math.max(0,t.randomValue??Math.random())),c=t.retryAfterMs==null?1+(l*2-1)*uv:1,d=Math.max(eo,Math.round(i*c));return d>=n?{kind:"expire",delayMs:n,reason:r}:{kind:"retry",delayMs:d}}const uu=t=>{let a;const s=new Set,n=(m,u)=>{const h=typeof m=="function"?m(a):m;if(!Object.is(h,a)){const p=a;a=u??(typeof h!="object"||h===null)?h:Object.assign({}
85,a,h),s.forEach(g=>g(a,p))}},r=()=>a,c={setState:n,getState:r,getInitialState:()=>d,subscribe:m=>(s.add(m),()=>s.delete(m))},d=a=t(n,r,c);return c},fv=(t=>t?uu(t):uu),gv=t=>t;function yv(t,a=gv){const s=Os.useSyncExternalStore(t.subscribe,Os.useCallback(()=>a(t.getState()),[t,a]),Os.useCallback(()=>a(t.getInitialState()),[t,a]));return Os.useDebugValue(s),s}const mu=t=>{const a=fv(t),s=n=>yv(a,n);return Object.assign(s,a),s},bv=(t=>t?mu(t):mu);function Jh(t,a){let s;try{s=t()}catch{return}return{getItem:r=>{var i;const l=d=>d===null?null:JSON.parse(d,void 0),c=(i=s.getItem(r))!=null?i:null;return c instanceof Promise?c.then(l):l(c)},setItem:(r,i)=>s.setItem(r,JSON.stringify(i,void 0)),removeItem:r=>s.removeItem(r)}}const $l=t=>a=>{try{const s=t(a);return s instanceof Promise?s:{then(n){return $l(n)(s)},catch(n){return this}}}catch(s){return{then(n){return this},catch(n){return $l(n)(s)}}}},xv=(t,a)=>(s,n,r)=>{let i={storage:Jh(()=>window.localStorage),partialize:y=>y,version:0,merge:(y,x)=>({...x,...y}),...a},l=!1,c=0;const d=new Set,m=new Set;let u=i.storage;if(!u)return t((...y)=>{console.warn(`[zustand persist middleware] Unable to update item '${i.name}', the given storage is currently unavailable.`),s(...y)},n,r);const h=()=>{const y=i.partialize({...n()});return u.setItem(i.name,{state:y,version:i.version})},p=r.setState;r.setState=(y,x)=>(p(y,x),h());const g=t((...y)=>(s(...y),h()),n,r);r.getInitialState=()=>g;let f;const b=()=>{var y,x;if(!u)return;const v=++c;l=!1,d.forEach(j=>{var T;return j((T=n())!=null?T:g)});const w=((x=i.onRehydrateStorage)==null?void 0:x.call(i,(y=n())!=null?y:g))||void 0;return $l(u.getItem.bind(u))(i.name).then(j=>{if(j)if(typeof j.version=="number"&&j.version!==i.version){if(i.migrate){const T=i.migrate(j.state,j.version);return T instanceof Promise?T.then(P=>[!0,P]):[!0,T]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return[!1,j.state];return[!1,void 0]}).then(j=>{var T;if(v!==c)return;const[P,N]=j;if(f=i.merge(N,(T=n())!=null?T:g),s(f,!0),P)return h()}).then(()=>{v===c&&(w?.(n(),void 0),f=n(),l=!0,m.forEach(j=>j(f)))}).catch(j=>{v===c&&w?.(void 0,j)})};return r.persist={setOptions:y=>{i={...i,...y},y.storage&&(u=y.storage)},clearStorage:()=>{u?.removeItem(i.name)},getOptions:()=>i,rehydrate:()=>b(),hasHydrated:()=>l,onHydrate:y=>(d.add(y),()=>{d.delete(y)}),onFinishHydration:y=>(m.add(y),()=>{m.delete(y)})},i.skipHydration||b(),f||g},wv=xv,Ji={status:"idle",progress:0,message:""},zl={title:"",description:""};function vv(){if(typeof window>"u"||!window.localStorage)return;const t="uploader.store";if(window.localStorage.getItem(t)!==null)return;const a=window.localStorage.getItem("uploader.uploadState"),s=window.localStorage.getItem("uploader.metadata"),n=window.localStorage.getItem("uploader.enableOcr"),r=window.localStorage.getItem("uploader.enableProcessing");if(a===null&&s===null&&n===null&&r===null)return;let i=Ji,l=zl,c=!0,d=!0;if(a!==null)try{const u=JSON.parse(a);u&&typeof u=="object"&&typeof u.status=="string"&&(i=u)}catch{}if(s!==null)try{const u=JSON.parse(s);u&&typeof u=="object"&&(l={title:typeof u.title=="string"?u.title:"",description:typeof u.description=="string"?u.description:""})}catch{}n!==null&&(c=n==="true"),r!==null&&(d=r==="true");const m={state:{uploadState:i,metadata:l,enableOcr:c,enableProcessing:d},version:1};window.localStorage.setItem(t,JSON.stringify(m)),window.localStorage.removeItem("uploader.uploadState"),window.localStorage.removeItem("uploader.metadata"),window.localStorage.removeItem("uploader.enableOcr"),window.localStorage.removeItem("uploader.enableProcessing")}vv();let ti=null;function Ai(){return ti}function rr(t){ti=t}function Xh(){ti&&(clearInterval(ti),ti=null)}let Qh=null;function jv(t){Qh=t}function kv(){Qh?.(),as.getState().resetUploader()}const as=bv()(wv(t=>({uploadState:Ji,metadata:zl,enableOcr:!0,enableProcessing:!0,uploadFiles:[],setUploadState:a=>t({uploadState:a}),updateUploadState:a=>t(s=>({uploadState:a(s.uploadState)})),setMetadata:a=>t({metadata:a}),updateMetadata:a=>t(s=>({metadata:a(s.metadata)})),setEnableOcr:a=>t({enableOcr:a}),setEnableProcessing:a=>t({enableProcessing:a}),setUploadFiles:a=>t({uploadFiles:a}),updateUploadFiles:a=>t(s=>({uploadFiles:a(s.uploadFiles)})),resetUploader:()=>t({uploadState:Ji,metadata:zl,uploadFiles:[]})}),{name:"uploader.store",storage:Jh(()=>localStorage),partialize:t=>({uploadState:t.uploadState,metadata:t.metadata,enableOcr:t.enableOcr,enableProcessing:t.enableProcessing}),onRehydrateStorage:()=>(t,a)=>{if(a||!t)return;const s=t.uploadState,n=s.status==="completed"||s.status==="error"||s.status==="processing"&&!!s.materialId;s.status!=="idle"&&!n&&t.setUploadState(Ji)},version:1}));function _v({header:t,children:a}){return e.jsxs("div",{className:"im-uploader-shell",children:[t,e.jsx(Oa,{mode:"wait",children:a})]})}function Zh({label:t="Back",onClick:a}){return e.jsxs("button",{type:"button",className:"im-uploader-back",onClick:a,children:[e.jsx(Za,{"aria-hidden":"true"}),t]})}function Er({eyebrow:t,title:a,lede:s}){return e.jsxs("header",{className:"im-uploader-step-head",children:[e.jsx("p",{className:"eyebrow",children:t}),e.jsx("h2",{children:a}),s&&e.jsx("p",{children:s})]})}function Sv({message:t,hint:a,heading:s,hideRetry:n,onRetry:r,onDismiss:i}){const l=!n&&!!r;return e.jsxs(ze.div,{initial:{opacity:0,y:8}
85,animate:{opacity:1,y:0},exit:{opacity:0,y:-8},transition:{duration:.3},className:"im-uploader-error",role:"alert",children:[e.jsx(Qa,{"aria-hidden":"true"}),e.jsxs("div",{className:"body",children:[e.jsx("span",{className:"heading",children:s??"Something went wrong"}),e.jsx("span",{children:t}),a&&e.jsx("span",{style:{display:"block",marginTop:6,opacity:.85},children:a}),(l||i)&&e.jsxs("div",{style:{display:"flex",gap:12,marginTop:10},children:[l&&e.jsx("button",{type:"button",onClick:r,className:"wc-cta-square wc-cta-square-quiet--maple",children:"Try again"}),i&&e.jsx("button",{type:"button",onClick:i,className:"wc-cta-square wc-cta-square-quiet--ink",children:"Dismiss"})]})]})]},"upload-error")}function Nv(t,a){const s=t??a;return{enableOcr:s.enableOcr,enableProcessing:s.enableProcessing}}function hu(t,a){return t==="store"?{enableOcr:!1,enableProcessing:!1}:{enableOcr:a,enableProcessing:!0}}function Cv(t){return t.enableProcessing?"readable":"store"}function Ev(t,a="page"){const s=Number.isFinite(t?.total)?Math.max(0,Math.floor(t.total)):0,n=Number.isFinite(t?.analyzed)?Math.max(0,Math.floor(t.analyzed)):0,r=Math.min(n,s),i=Math.max(0,s-r),l=s>0?Math.min(100,Math.round(r/s*100)):0;return{isPartial:s>0&&r>0&&r<s,analyzed:r,total:s,remaining:i,percent:l,unit:a}}function Tv(t){switch(t.status){case"queued":return"Queued";case"uploading":return t.total>0?`${t.uploaded}/${t.total}`:"Syncingâ¦";case"synced":return"Stored";case"error":return"Failed";case"quota_exceeded":return"Cloud full";case"skipped_quota":return"Skipped";case"unavailable":return"";default:return""}}function Mv(t){return t.status==="synced"?1:t.status==="uploading"&&t.total>0?t.uploaded/t.total:0}function Pv(t,a){let s=0,n=!1,r=0;for(const d of t){const m=a.get(d.episodeId)??{status:"queued"};m.status==="synced"&&s++,(m.status==="quota_exceeded"||m.status==="skipped_quota")&&(n=!0),(m.status==="queued"||m.status==="uploading")&&r++}const i=r===0,l=n?`${s} of ${t.length} synced â cloud space full`:i?`Stored ${s} of ${t.length} to your cloud library`:"Syncing to your cloud libraryâ¦";return{synced:s,quotaHit:n,done:i,inFlight:!i&&!n,summaryText:l}}function Av({rows:t}){const[a,s]=o.useState(()=>new Map);if(o.useEffect(()=>Jn.subscribe(l=>s(new Map(l))),[]),t.length===0)return null;const{summaryText:n,inFlight:r}=Pv(t,a);return e.jsxs("div",{className:"im-uploader-season-sync",children:[e.jsxs("div",{className:"im-uploader-season-sync-head",children:[e.jsx(Js,{"aria-hidden":"true"}),e.jsx("span",{children:n})]}),r&&e.jsx("p",{className:"im-uploader-season-sync-note",children:"You can leave this page â syncing continues in the background, and you can watch each episodeâs progress on the show page."}),e.jsx("ul",{className:"im-uploader-season-sync-list",children:t.map(i=>{const l=a.get(i.episodeId)??{status:"queued"},c=l.status==="error"||l.status==="quota_exceeded";return e.jsxs("li",{className:"im-uploader-season-sync-row",children:[e.jsx("span",{className:"ep-label",title:i.label,children:i.label}),e.jsxs("span",{className:`ep-state${c?" is-warn":""}`,children:[c&&e.jsx(Qa,{"aria-hidden":"true",size:11}),Tv(l)]}),e.jsx("span",{className:"ep-bar","aria-hidden":"true",children:e.jsx("span",{className:`fill${l.status==="synced"?" is-done":""}`,style:{width:`${Math.round(Mv(l)*100)}%`}})})]},i.episodeId)})})]})}function Iv({message:t,onOpen:a,onAnother:s,coverage:n,partialWithoutCounts:r=!1,coverageUnit:i="page",onFinishProcessing:l,seasonSyncRows:c}){const d=Ev(n,i),m=d.isPartial||r,u=d.isPartial,h=p=>`${d.unit}${p===1?"":"s"}`;return e.jsxs(ze.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.45,ease:[.22,1,.36,1]},className:"im-uploader-complete",children:[e.jsx("span",{className:"im-uploader-complete-glyph","aria-hidden":"true",style:m?{color:"hsl(38 92% 50%)"}:void 0,children:m?e.jsx(Qa,{}):e.jsx(rn,{})}),e.jsx("h3",{children:m?"Added â partly analyzed":"Added to your library"}),m?e.jsx(e.Fragment,{children:u?e.jsxs(e.Fragment,{children:[e.jsxs("p",{children:["We analyzed ",e.jsx("strong",{children:d.analyzed})," of ",e.jsx("strong",{children:d.total})," ",h(d.total)," before your shared credits ran out. The remaining"," ",e.jsx("strong",{children:d.remaining})," ",h(d.remaining)," are readable as plain text. You can finish analyzing anytime from your library â when your credits reset, or after upgrading."]}),e.jsxs("div",{className:"im-uploader-cost-block",style:{width:"100%",maxWidth:360},children:[e.jsxs("div",{className:"im-uploader-cost-head",children:[e.jsx("span",{children:"Analyzed"}),e.jsxs("span",{className:"ratio",children:[d.analyzed," / ",d.total," ",h(d.total)]})]}),e.jsx("div",{className:"progress-bar","aria-hidden":"true",children:e.jsx("div",{className:"fill",style:{width:`${d.percent}%`}})})]})]}):e.jsx("p",{children:"The server completed the affordable prefix before your shared credits ran out. Your analyzed content is saved; the exact delivered count is still being reconciled. You can finish analyzing after your credits reset or after upgrading."})}):e.jsx("p",{children:t||"Your reading material is ready. Open it now or add another."}),c&&c.length>0&&e.jsx(Av,{rows:c}),e.jsxs("div",{className:"im-uploader-complete-actions",children:[a&&e.jsx("button",{type:"button",onClick:a,className:"wc-cta-square wc-cta-square--ink",children:m?"Open & read":"Open material"}),m&&l&&e.jsx("button",{type:"button",onClick:l,className:a?"wc-cta-square wc-cta-square-secondary--dusk":"wc-cta-square wc-cta-square--ink",children:"Finish analyzing"}),s&&e.jsx("button",{type:"button",onClick:s,className:a||m&&l?"wc-cta-square wc-cta-square-quiet--ink":"wc-cta-square wc-cta-square--ink",children:"Add another"})]})]},"upload-complete")}function Rv({info:t,onOpenExisting:a,onUploadAnyway:s}){const n=t.source==="pre-ocr",r=n?"Already in your library":"Already in your library â duplicate detected",i=n?`You already have "${t.title}" in your library. Open the existing copy and skip OCR (saves ~60 seconds and Modal cost), or upload again anyway.`:`Heads up â "${t.title}" was already in your library. The new upload turned out to be the same content, so we'll show you the existing copy. You can choose to keep going if this was intentional.`;return e.jsxs(ze.div,{initial:{opacity:0,y:16}
85,animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.45,ease:[.22,1,.36,1]},className:"im-uploader-complete",children:[e.jsx("span",{className:"im-uploader-complete-glyph","aria-hidden":"true",children:e.jsx(ni,{})}),e.jsx("h3",{children:r}),e.jsx("p",{children:i}),e.jsxs("div",{className:"im-uploader-complete-actions",children:[e.jsx("button",{type:"button",onClick:a,className:"wc-cta-square wc-cta-square--ink",children:"Open existing"}),e.jsx("button",{type:"button",onClick:s,className:"wc-cta-square wc-cta-square-quiet--ink",children:"Upload anyway"})]})]},"upload-duplicate-confirm")}const $v={idle:"Working",ready_to_confirm:"Working",extracting:"Extracting pages",ocr_pending:"Reading the text",saving_local:"Saving to this device",uploading_text:"Uploading text data",uploading:"Adding to your library",processing:"Analyzing your content",completed:"Working",error:"Working"};function zv(t){switch(t){case"extracting":case"ocr_pending":case"saving_local":case"uploading_text":case"uploading":return{tone:"hold",lead:"Keep this tab open",body:"This step runs here in your browser. Switching to other apps or tabs is fine â but closing or reloading this tab will cancel the import."};case"processing":return{tone:"free",lead:"You can leave this page",body:"The rest runs on our servers. Feel free to close this tab or keep browsing â your material appears in your library when itâs ready."};default:return null}}function pu({uploadState:t,onCancel:a}){const s=!!t.indeterminate,n=Math.max(0,Math.min(100,t.progress||0)),r=zv(t.status);return e.jsxs(ze.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.4,ease:[.22,1,.36,1]},className:"im-uploader-status","aria-live":"polite",children:[e.jsx("span",{className:"im-uploader-status-glyph","aria-hidden":"true",children:e.jsx(bs,{image:cs,size:96,duration:1.6})}),e.jsx("h3",{children:$v[t.status]??"Working"}),e.jsx("p",{children:t.message||"Please wait while we process your filesâ¦"}),e.jsx("div",{className:`im-uploader-status-bar${s?" is-indeterminate":""}`,"aria-hidden":"true",children:e.jsx("div",{className:"fill",style:s?void 0:{width:`${n}%`}})}),!s&&e.jsxs("p",{style:{fontFamily:"'JetBrains Mono', monospace",fontSize:11,letterSpacing:"0.1em"},children:[n,"% complete"]}),r&&e.jsxs("div",{className:`im-uploader-tab-note im-uploader-tab-note--${r.tone}`,role:"note",children:[e.jsx("span",{className:"im-uploader-tab-note-lead",children:r.lead}),e.jsx("span",{className:"im-uploader-tab-note-body",children:r.body})]}),a&&e.jsx("button",{type:"button",onClick:a,className:"im-uploader-back",style:{marginTop:8},children:"Cancel"})]},"upload-progress")}const Fv=[{key:"manga",label:"Manga",desc:"Scans, CBZ, ZIP, PDF, EPUB, Kindle, images"},{key:"series",label:"Series",desc:"Anime, TV shows, dramas"},{key:"movie",label:"Movie",desc:"Films, specials"},{key:"novel",label:"Novel",desc:"EPUB, Kindle, light novels, text"}];function Dv({onSelect:t}){return e.jsxs(ze.div,{"data-tour-id":"uploader-category-selector",initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.4,ease:[.22,1,.36,1]},style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsx(Er,{eyebrow:"Add content",jp:"追å ",title:"What are you adding?",lede:"Pick the kind of content you'd like to import. You can mix categories later â every upload lands in the same library."}),e.jsx("div",{className:"im-uploader-category-grid",children:Fv.map(({key:a,label:s,desc:n})=>e.jsxs("button",{type:"button",className:"im-uploader-category-card",onClick:()=>{ne("immersion_upload_category_selected",{category:a}),t(a)},"data-tour-id":`uploader-category-${a}`,children:[e.jsx("span",{className:"im-uploader-category-card-label",children:s}),e.jsx("span",{className:"im-uploader-category-card-sub",children:n})]},a))})]},"category-selector")}const Lv=10*1024*1024,Ov=300*1024,Bv=512,qv=[.8,.7,.6];function Uv(){const[t,a]=o.useState(!1),[s,n]=o.useState(null),r=o.useRef(null);return{pickImage:o.useCallback(async()=>{if(n(null),!r.current){const d=document.createElement("input");d.type="file",d.accept="image/*",d.style.display="none",document.body.appendChild(d),r.current=d}const l=r.current,c=await new Promise(d=>{const m=()=>{const h=l.files?.[0]??null;l.value="",d(h)};l.addEventListener("change",m,{once:!0}),l.click();const u=()=>{window.removeEventListener("focus",u),setTimeout(()=>{l.files?.length||(l.removeEventListener("change",m),d(null))},300)};window.addEventListener("focus",u)});if(!c)return null;if(c.size>Lv)return n(`Image too large (max 10 MB; you picked ${(c.size/1024/1024).toFixed(1)} MB).`),null;a(!0);try{const d=await Vv(c);if(!d)return n("Could not compress this image small enough. Try a simpler picture."),null;const{data:{session:m}}=await Ps.auth.getSession(),u=m?.access_token;if(!u)return n("Not signed in."),null;const h=await fetch(`${Xu}/api/reading/cover-images/upload-url`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${u}`},body:JSON.stringify({})});if(!h.ok)return n("Could not request upload URL."),null;const{signedUrl:p,path:g}=await h.json();if(!p||!g)return n("Upload URL response was malformed."),null;const f=await fetch(p,{method:"PUT",body:d,headers:{"Content-Type":"image/webp"}});return f.ok?{path:g,previewUrl:URL.createObjectURL(d)}:(n(`Upload failed (HTTP ${f.status}).`),null)}catch(d){return console.error("Cover image upload failed",d),n("Upload failed. Try again."),null}finally{a(!1)}},[]),isUploading:t,error:s}}async function Vv(t){const a=await Kv(t),s=document.createElement("canvas"),n=Math.min(1,Bv/Math.max(a.width,a.height));s.width=Math.round(a.width*n),s.height=Math.round(a.height*n);const r=s.getContext("2d");if(!r)return null;r.drawImage(a,0,0,s.width,s.height);for(const i of qv){const l=await new Promise(c=>s.toBlob(d=>c(d),"image/webp",i));if(l&&l.size<=Ov)return l}return null}function Kv(t){return new Promise((a,s)=>{const n=URL.createObjectURL(t),r=new Image;r.onload=()=>{URL.revokeObjectURL(n),a(r)},r.onerror=i=>{URL.revokeObjectURL(n),s(i)},r.src=n})}function Qn({currentCoverUrl:t,onChange:a,label:s="Cover image (optional)",compact:n=!1}){const{pickImage:r,isUploading:i,error:l}
85=Uv(),[c,d]=o.useState(null),m=c??t??null,u=!!m,h=async()=>{const g=await r();g&&(d(g.previewUrl),a(g.path,g.previewUrl))},p=()=>{d(null),a(null)};return e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("span",{className:"im-uploader-field-label",children:s}),e.jsxs("div",{className:`im-uploader-cover-field${n?" im-uploader-cover-field--compact":""}`,children:[!n&&e.jsxs("div",{className:"im-uploader-cover-thumb","aria-hidden":!u,children:[u?e.jsx("img",{src:m,alt:"",loading:"lazy",decoding:"async"}):e.jsx("span",{className:"im-uploader-cover-thumb-placeholder",children:e.jsx(Gr,{"aria-hidden":"true"})}),i&&e.jsx("span",{className:"im-uploader-cover-thumb-loading","aria-hidden":"true",children:e.jsx(Sa,{className:"spin"})})]}),e.jsxs("div",{className:"im-uploader-cover-actions",children:[e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk",onClick:h,disabled:i,children:[e.jsx(Sr,{size:13,"aria-hidden":"true",style:{marginRight:6}}),i?"Uploadingâ¦":u?"Replace cover":"Upload cover"]}),u&&!i&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink",onClick:p,children:[e.jsx(rs,{size:13,"aria-hidden":"true",style:{marginRight:4}}),"Remove"]})]})]}),l&&e.jsx("p",{className:"im-uploader-cover-error",children:l})]})}function Hv({title:t,onTitleChange:a,coverUrl:s,onCoverChange:n,existingSeries:r,selectedSeriesId:i,onSelectedSeriesIdChange:l,onCreate:c,onAttach:d,onStandalone:m}){const u=t.trim().length>0,h=!!i,p=u&&!h,g=h;return e.jsxs(ze.div,{"data-tour-id":"uploader-series-picker",initial:{opacity:0,x:24},animate:{opacity:1,x:0},exit:{opacity:0,x:-24},transition:{duration:.4,ease:[.22,1,.36,1]},style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsx(Er,{eyebrow:"Import manga",jp:"漫ç»",title:"Tell us about this manga",lede:"Group every volume under a series so they show up together in your library â or upload it as a one-off."}),e.jsxs("div",{className:"im-uploader-panel",children:[e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"manga-title",children:"Series title"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"manga-title",type:"text",value:t,onChange:f=>a(f.target.value),placeholder:"e.g. One Piece, Yotsuba&!",className:"im-uploader-input",disabled:h})})]}),e.jsx(Qn,{currentCoverUrl:s,onChange:n}),r.length>0&&e.jsx(Yr,{label:"Or add to existing series",value:i||"",onChange:f=>{if(l(f||null),f){const b=r.find(y=>y.id===f);b&&a(b.title)}},options:[{value:"",label:"New series"},...r.map(f=>({value:f.id,label:f.title}))]}),e.jsxs("div",{className:"im-uploader-mode-row",children:[e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",disabled:!p&&!g,onClick:()=>{ne("immersion_upload_series_mode_selected",{mode:h?"existing_series":"new_series"}),h?d():c()},children:h?"Add to series":"Create series"}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--dusk",onClick:()=>{ne("immersion_upload_series_mode_selected",{mode:"standalone"}),m()},children:"Upload without series"})]})]})]},"manga-series-picker")}function Wv({title:t,onTitleChange:a,coverUrl:s,onCoverChange:n,onCreate:r,onStandalone:i}){const l=t.trim().length>0;return e.jsxs(ze.div,{initial:{opacity:0,x:24},animate:{opacity:1,x:0},exit:{opacity:0,x:-24},transition:{duration:.4,ease:[.22,1,.36,1]},style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsx(Er,{eyebrow:"Import novel",jp:"å°èª¬",title:"Tell us about this novel",lede:"Light novels and prose work best as a series so volumes line up. Standalone uploads work too."}),e.jsxs("div",{className:"im-uploader-panel",children:[e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"novel-title",children:"Series title"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"novel-title",type:"text",value:t,onChange:c=>a(c.target.value),placeholder:"e.g. Sword Art Online, Classroom of the Elite",className:"im-uploader-input"})})]}),e.jsx(Qn,{currentCoverUrl:s,onChange:n}),e.jsxs("div",{className:"im-uploader-mode-row",children:[e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",disabled:!l,onClick:r,children:"Create series"}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--dusk",onClick:i,children:"Upload without series"})]})]})]},"novel-series-picker")}
85function Gv({title:t,onTitleChange:a,coverUrl:s,onCoverChange:n,onCreate:r,onStandalone:i}){const l=t.trim().length>0;return e.jsxs(ze.div,{initial:{opacity:0,x:24},animate:{opacity:1,x:0},exit:{opacity:0,x:-24},transition:{duration:.4,ease:[.22,1,.36,1]},style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsx(Er,{eyebrow:"Import movie",jp:"æ ç»",title:"Tell us about this movie",lede:"Group sequels and specials under a franchise â or upload it standalone if it's a one-off film."}),e.jsxs("div",{className:"im-uploader-panel",children:[e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"movie-title",children:"Franchise title"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"movie-title",type:"text",value:t,onChange:c=>a(c.target.value),placeholder:"e.g. Studio Ghibli, Harry Potter",className:"im-uploader-input"})})]}),e.jsx(Qn,{currentCoverUrl:s,onChange:n}),e.jsxs("div",{className:"im-uploader-mode-row",children:[e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",disabled:!l,onClick:r,children:"Create franchise"}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--dusk",onClick:i,children:"Upload without franchise"})]})]})]},"movie-franchise-picker")}function Yv({category:t,isDragging:a,onDragOver:s,onDragLeave:n,onDrop:r,onSelectFiles:i,onSelectFolder:l,onSelectImages:c,onScanPhysicalManga:d}){const m=t==="manga",u=a?"Drop files here":t==="novel"?"Add a novel to your library":"Add manga to your library",h=t==="novel"?"Drag & drop an EPUB or Kindle (MOBI/AZW3) file, or pick one from your computer. It stays on this device unless you sync it to your cloud library â your progress and notes sync to your account either way.":"Drag & drop manga files (CBZ, ZIP, PDF, EPUB, Kindle, or images), or pick from your computer. Files stay on this device unless you sync them to your cloud library â your progress and notes sync to your account either way.";return e.jsxs(ze.div,{"data-tour-id":"uploader-drop-zone",initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.4,ease:[.22,1,.36,1]},className:`im-uploader-dropzone${a?" is-dragging":""}`,onDragOver:s,onDragLeave:n,onDrop:r,role:"button",tabIndex:0,onClick:i,onKeyDown:p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),i())},children:[e.jsx("span",{className:"im-uploader-dropzone-glyph","aria-hidden":"true",children:e.jsx(Sr,{})}),e.jsx("h3",{className:"im-uploader-dropzone-title",children:u}),e.jsx("p",{className:"im-uploader-dropzone-sub",children:h}),e.jsxs("div",{className:"im-uploader-dropzone-actions",onClick:p=>p.stopPropagation(),children:[e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:i,children:[e.jsx(Gf,{size:14,"aria-hidden":"true",style:{marginRight:6}}),"Select files"]}),m&&l&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk",onClick:l,children:[e.jsx(eg,{size:14,"aria-hidden":"true",style:{marginRight:6}}),"Select folder"]}),m&&c&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk",onClick:c,children:[e.jsx(Gr,{size:14,"aria-hidden":"true",style:{marginRight:6}}),"Select images"]}),m&&d&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk",onClick:d,children:[e.jsx(gg,{size:14,"aria-hidden":"true",style:{marginRight:6}}),"Scan physical manga"]})]})]},"drop-zone")}function Jv(t){if(t.some(s=>s.type==="epub"||s.type==="kindle"))return!0;const a=t.filter(s=>s.type==="pdf");return a.length===1&&a[0].pdfKind==="text"}function Xv(t,a){if(t?.some(n=>n.type==="subtitle")){const n=t.filter(r=>r.type==="subtitle").length;return`${n}
85 subtitle file${n===1?"":"s"} selected`}const s=t&&Jv(t)?"paragraph":"page";return`${a} ${s}${a===1?"":"s"} planned`}function Qv({estimatedOcrUnits:t,estimatedEnrichmentUnits:a,sharedCreditAvailable:s,ocrEnabled:n,enrichmentEnabled:r,planningPending:i=!1,walletPending:l=!1,files:c}){if(!n&&!r)return null;const d=l?"Loading balanceâ¦":s==null?"Checked at processing start":`${new Intl.NumberFormat().format(s)} available`;return e.jsxs("div",{className:"im-uploader-cost-block",children:[e.jsxs("div",{className:"im-uploader-cost-head",children:[e.jsx("span",{children:"Flexible AI & processing credits"}),e.jsx("span",{className:"ratio",children:"One shared balance"})]}),e.jsxs("div",{className:"im-uploader-cost-grid",children:[e.jsxs("div",{className:"im-uploader-cost-row",children:[e.jsxs("div",{className:"im-uploader-cost-row-head",children:[e.jsx("strong",{children:"Shared balance"}),e.jsx("span",{className:"ratio",children:d})]}),e.jsx("p",{className:"im-uploader-cost-after",children:"OCR and annotations draw from this same monthly allowance."})]}),n&&e.jsxs("div",{className:"im-uploader-cost-row",children:[e.jsxs("div",{className:"im-uploader-cost-row-head",children:[e.jsx("strong",{children:"Text recognition"}),e.jsx("span",{className:"ratio",children:i?"Counting pagesâ¦":`${t} page${t===1?"":"s"} planned`})]}),e.jsx("p",{className:"im-uploader-cost-after",children:t===0&&!i?"Text is already included, so OCR is skipped.":"Page count is a workload hint, not a credit quote."})]}),r&&e.jsxs("div",{className:"im-uploader-cost-row",children:[e.jsxs("div",{className:"im-uploader-cost-row-head",children:[e.jsx("strong",{children:"Grammar & vocabulary annotations"}),e.jsx("span",{className:"ratio",children:i?"Inspecting contentâ¦":Xv(c,a)})]}),e.jsx("p",{className:"im-uploader-cost-after",children:"Content length and candidate density determine the final charge."})]})]}),e.jsx("p",{className:"im-uploader-cost-explainer",children:"This preview describes planned work only; it is not an exact credit quote. The server is the billing authority. If the full request is not affordable, batch processing keeps canonical order and stops at the largest affordable prefix. Storing the original material is separate and uses no processing credits."})]})}const zr=new Intl.NumberFormat;function Zv(t){if(!t)return null;const a=new Date(t);return Number.isFinite(a.valueOf())?new Intl.DateTimeFormat(void 0,{month:"short",day:"numeric"}).format(a):null}function ej({availableCredits:t,expectedCharge:a,requestedUnits:s,selectedUnits:n,unitLabel:r="unit",resetAt:i,canUpgrade:l=!1,onUpgrade:c,canStoreWithoutProcessing:d=!0}){const m=Zv(i),u=a!=null,h=s!=null&&n!=null&&s>n&&n>=0,p=g=>`${r}${g===1?"":"s"}`;return e.jsxs("div",{className:"im-uploader-quota-prompt",children:[l&&e.jsx("span",{className:"im-uploader-quota-prompt-glyph","aria-hidden":"true",children:e.jsx(fm,{})}),e.jsx("h4",{children:"Not enough shared credits for the full request"}),e.jsx("p",{children:u?e.jsxs(e.Fragment,{children:["This request needs ",e.jsxs("strong",{children:[zr.format(a)," shared credits"]}),", but you have ",e.jsx("strong",{children:zr.format(t)})," available."]}):e.jsxs(e.Fragment,{children:["You have ",e.jsxs("strong",{children:[zr.format(t)," shared credits"]})," available. The exact charge is checked from the staged material before processing starts."]})}),h&&e.jsxs("p",{children:["Your balance covers the first ",e.jsxs("strong",{children:[zr.format(n)," of ",zr.format(s)," ",p(s)]})," in canonical order."]}),e.jsxs("p",{children:[d?"You can add the material without processing":"You can try again",m?`, or continue after your credits reset on ${m}.`:", or continue after your credits reset."]}),l&&c&&e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:c,children:"View plans"})]})}function tj({onUpgrade:t,isPro:a=!1,availableCredits:s,resetAt:n,expectedCharge:r,requestedUnits:i,selectedUnits:l,unitLabel:c}){return e.jsx(ej,{availableCredits:s,expectedCharge:r,requestedUnits:i,selectedUnits:l,unitLabel:c,resetAt:n,canUpgrade:!a&&$a(),onUpgrade:t})}const aj=Object.freeze({status:"idle"});function sj(t){const a=t.toLowerCase();return a.includes("not authenticated")||a.includes("401")?"auth":a.includes("unsupported")||a.includes("empty")?"bad_file":a.includes("requires pro")?"tier":a.includes("not found")||a.includes("404")?"not_found":a.includes("verification")?"verify":a.includes("etag")?"etag":a.includes("init")?"init":a.includes("complete")?"complete":a.includes("put")?"put":a.includes("network")?"network":"other"}class nj{deps=null;queue=[];states=new Map;listeners=new Set;running=!1;currentAbort=null;currentEpisodeId=null;cancelled=new Set;unavailable=!1;startedAt=new Map;configure(a){this.deps=Bc(a),this.queue.length>0&&this.pump()}_setDeps(a){this.deps=a,this.unavailable=!1,this.queue.length>0&&this.pump()}_reset(){this.deps=null,this.queue=[],this.states.clear(),this.cancelled.clear(),this.startedAt.clear(),this.currentEpisodeId=null,this.unavailable=!1,this.running=!1,this.currentAbort?.abort(),this.currentAbort=null}subscribe(a){return this.listeners.add(a),a(new Map(this.states)),()=>{this.listeners.delete(a)}}getState(a){return this.states.get(a)??aj}emit(){const a=new Map(this.states);for(const s of this.listeners)s(a)}
85setState(a,s){this.states.set(a,s),this.emit()}clearState(a){this.queue=this.queue.filter(s=>s.episodeId!==a),this.cancelled.add(a),this.currentEpisodeId===a&&this.currentAbort?.abort(),this.states.delete(a)&&this.emit()}enqueue(a){if(this.unavailable||this.queue.some(n=>n.episodeId===a.episodeId))return;const s=this.states.get(a.episodeId);s?.status==="uploading"||s?.status==="queued"||(this.cancelled.delete(a.episodeId),this.queue.push(a),this.setState(a.episodeId,{status:"queued"}),this.pump())}retry(a){this.unavailable||(this.states.delete(a.episodeId),this.queue=this.queue.filter(s=>s.episodeId!==a.episodeId),this.enqueue(a))}async cancel(a){this.clearState(a),this.deps&&await Kh(a,this.deps),ne("cloud_video_sync_failed",{error_kind:"aborted"})}async _drain(){for(;this.running||this.queue.length>0;)await new Promise(a=>setTimeout(a,0))}async pump(){if(!this.running&&this.deps){this.running=!0;try{for(;this.queue.length>0&&!this.unavailable;){const a=this.queue.shift();if(this.cancelled.has(a.episodeId))continue;this.currentEpisodeId=a.episodeId,this.startedAt.set(a.episodeId,Date.now()),ne("cloud_video_sync_started",{bytes:a.file.size}),this.setState(a.episodeId,{status:"uploading",uploaded:0,total:0}),this.currentAbort=new AbortController;let s;try{s=await Vh(a,this.deps,(n,r)=>{this.cancelled.has(a.episodeId)||this.setState(a.episodeId,{status:"uploading",uploaded:n,total:r})},this.currentAbort.signal)}catch(n){s={kind:"error",retryable:!0,message:n instanceof Error?n.message:"sync failed"}}this.currentEpisodeId=null,this.currentAbort=null,!this.cancelled.has(a.episodeId)&&this.applyOutcome(a,s)}}finally{this.running=!1,this.currentEpisodeId=null,this.currentAbort=null}}}durationOf(a){const s=this.startedAt.get(a);return s!=null?Math.max(0,Date.now()-s):void 0}applyOutcome(a,s){const{episodeId:n}=a;switch(s.kind){case"synced":ne("cloud_video_sync_completed",{bytes:s.bytes,duration_ms:this.durationOf(n)}),this.setState(n,{status:"synced"});return;case"attestation_required":this.setState(n,{status:"attestation_required"});return;case"unavailable":this.unavailable=!0;for(const r of this.queue){const i=this.states.get(r.episodeId)?.status;(i==="uploading"||i==="queued")&&this.states.delete(r.episodeId)}this.queue=[],this.setState(n,{status:"unavailable"});return;case"quota_exceeded":ne("cloud_video_sync_failed",{bytes:a.file.size,error_kind:"quota",duration_ms:this.durationOf(n)}),this.setState(n,{status:"quota_exceeded"});return;case"aborted":this.states.delete(n),this.emit();return;case"error":ne("cloud_video_sync_failed",{bytes:a.file.size,error_kind:sj(s.message),retryable:s.retryable,duration_ms:this.durationOf(n)}),this.setState(n,{status:"error",retryable:s.retryable,message:s.message});return}}}const yn=new nj,ep="immersion.cloud.offlinePins.v1";function tp(t,a){const s=new Set(t);return s.delete(a),s}function rj(t,a){const s=new Set(t);return s.has(a)?s.delete(a):s.add(a),s}function ai(){return Fc(ep,t=>Array.isArray(t)?new Set(t.filter(a=>typeof a=="string")):null,new Set)}function Fl(t){Dc(ep,[...t])}function br(t){if(!Number.isFinite(t)||t<=0)return"0 MB";const a=t/(1024*1024*1024);if(a>=1)return`${a.toFixed(a>=10?0:1)} GB`;const s=t/(1024*1024);if(s>=1)return`${s.toFixed(s>=10?0:1)} MB`;const n=t/1024;return`${Math.max(1,Math.round(n))} KB`}async function ij(t,a){const s=a.fetchFn??fetch,n=ue(),r=await a.getAccessToken();if(!r)return{ok:!1,status:401,message:"Not authenticated"};let i;try{i=await s(`${n}/api/reading/materials/${t}/cloud-sync`,{method:"DELETE",headers:{Authorization:`Bearer ${r}`}})}catch(l){return{ok:!1,status:0,message:l instanceof Error?l.message:"Network error"}}if(i.ok){const l=await i.json().catch(()=>({}));return{ok:!0,alreadyUnsynced:l.alreadyUnsynced,objectsDeleted:l.objectsDeleted}}return{ok:!1,status:i.status,message:`unsync failed (${i.status})`}}async function go(t,a,s,n){const r=await ij(t,{getAccessToken:a,fetchFn:s});if(!r.ok)return{ok:!1,message:r.message};ne("cloud_unsync",{kind:n?.kind,bytes:n?.bytes,objects_deleted:r.objectsDeleted}),kr.clearState(t);const i=ai();return i.has(t)&&Fl(tp(i,t)),{ok:!0}}async function oj(t,a,s,n){const r=fetch,i=ue(),l=await a();if(!l)return{ok:!1,message:"Not authenticated"};yn.clearState(t);let c;try{c=await r(`${i}/api/video/episodes/${t}/cloud-sync`,{method:"DELETE",headers:{Authorization:`Bearer ${l}`}})}catch(d){return{ok:!1,message:d instanceof Error?d.message:"Network error"}}return c.ok?(ne("cloud_video_unsync",{bytes:n?.bytes}),{ok:!0}):{ok:!1,message:`unsync failed (${c.status})`}}
85async function ap(t){const a=t.fetchFn??fetch,s=ue(),n=await t.getAccessToken();if(!n)return{ok:!1,status:401,message:"Not authenticated"};let r;try{r=await a(`${s}/api/reading/cloud-usage`,{headers:{Authorization:`Bearer ${n}`}})}catch(l){return{ok:!1,status:0,message:l instanceof Error?l.message:"Network error"}}if(!r.ok)return{ok:!1,status:r.status,message:`cloud-usage failed (${r.status})`};const i=await r.json().catch(()=>null);return!i||typeof i.bytes_used!="number"?{ok:!1,status:r.status,message:"Malformed cloud-usage response"}:{ok:!0,usage:{tier:i.tier,bytes_used:i.bytes_used,limit_bytes:i.limit_bytes,limit_mb:i.limit_mb,default_limit_mb:i.default_limit_mb,materials:Array.isArray(i.materials)?i.materials:[]}}}function qc(t,a){return!Number.isFinite(a)||a<=0?0:Math.max(0,Math.min(1,t/a))}function lj(t,a){return qc(t,a)>.85}function sp({kind:t,enabled:a,onChange:s,estimate:n,usage:r,isPro:i,onUpgrade:l}){if(!i)return e.jsxs("p",{className:"im-uploader-cloud-upsell",children:["Pro syncs your library to the cloud â"," ",e.jsx("button",{type:"button",className:"im-uploader-cloud-upsell-link",onClick:l,children:"read on any device"}),"."]});const c=t==="video"?"files":t==="epub"?"book":"pages",d=r!==null&&r!=="unavailable",m=d?r.usedBytes:0,u=d?r.limitBytes:0,h=Math.max(0,u-m),p=qc(m,u),g=d&&n.bytes!=null&&u>0&&n.bytes>h,f=n.bytes==null?null:`this upload ${n.approximate?"â ":""}${br(n.bytes)}`;return e.jsxs("div",{className:"im-uploader-toggle-row im-uploader-cloud-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsxs("span",{className:"row-head",children:[e.jsx(Js,{"aria-hidden":"true"}),"Store in your cloud library"]}),e.jsxs("p",{className:"row-desc",children:["The ",c," sync to your account so you can read on any device â no re-import. Your vocab, OCR text and progress sync either way."]}),d?e.jsxs("div",{className:"im-uploader-cloud-quota",children:[e.jsxs("div",{className:"im-uploader-cloud-quota-label",children:[e.jsxs("span",{children:[br(m)," of ",br(u)]}),f&&e.jsx("span",{className:"est",children:f})]}),e.jsx("div",{className:`im-uploader-cloud-quota-bar${g?" is-full":""}`,"aria-hidden":"true",children:e.jsx("span",{className:"fill",style:{width:`${Math.round(p*100)}%`}})}),g&&e.jsx("p",{className:"im-uploader-cloud-quota-warn",children:"Won't fully fit â sync stops when your space is full. Your file still imports."})]}):f&&e.jsx("div",{className:"im-uploader-cloud-quota",children:e.jsx("div",{className:"im-uploader-cloud-quota-label",children:e.jsx("span",{className:"est",children:f})})})]}),e.jsx($n,{checked:a,onCheckedChange:s,"aria-label":"Store in y
85our cloud library",style:{"--primary":"var(--brand-chat)"}})]})}function np({malType:t,initialQuery:a,value:s,onSelect:n,onClear:r}){const[i,l]=o.useState(a??""),[c,d]=o.useState([]),[m,u]=o.useState("idle"),h=o.useRef(0),p=o.useCallback(async g=>{const f=g.trim(),b=++h.current;if(f.length<2){d([]),u("idle");return}u("searching");try{const{data:y}=await Ps.auth.getSession(),x=y.session?.access_token;if(!x){b===h.current&&(d([]),u("idle"));return}const v=`${ue()}/api/jikan/search?q=${encodeURIComponent(f)}&type=${t}&namesOnly=true&limit=8`,w=await fetch(v,{headers:{Authorization:`Bearer ${x}`}});if(b!==h.current)return;if(!w.ok){d([]),u("error");return}const j=await w.json(),T=Array.isArray(j.results)?j.results:[];d(T),u(T.length===0?"empty":"idle")}catch{b===h.current&&(d([]),u("error"))}},[t]);return o.useEffect(()=>{if(s)return;const g=setTimeout(()=>{p(i)},350);return()=>clearTimeout(g)},[i,s,p]),s?e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("span",{className:"im-uploader-field-label",children:"Recognized series"}),e.jsxs("div",{className:"im-uploader-mal-selected",children:[e.jsx("span",{className:"im-uploader-mal-selected-check","aria-hidden":"true",children:e.jsx(Ys,{})}),e.jsx("span",{className:"im-uploader-mal-selected-title",children:s.title}),e.jsxs("button",{type:"button",className:"im-uploader-mal-clear",onClick:r,"aria-label":"Remove series",children:[e.jsx(rs,{"aria-hidden":"true"})," Change"]})]}),e.jsx("p",{className:"im-uploader-field-hint",children:"We'll use this series' character names to keep names from being mis-read as words or grammar."})]}):e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"mal-match-search",children:"Recognize character names â optional"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"mal-match-search",type:"text",value:i,onChange:g=>l(g.target.value),placeholder:"Search the series title to recognize its charactersâ¦",className:"im-uploader-input",autoComplete:"off"})}),m==="searching"&&e.jsxs("p",{className:"im-uploader-mal-status",children:[e.jsx(Zu,{"aria-hidden":"true"})," Searchingâ¦"]}),m==="empty"&&e.jsx("p",{className:"im-uploader-mal-status",children:"No matches â you can skip this and import anyway."}),m==="error"&&e.jsx("p",{className:"im-uploader-mal-status",children:"Couldn't reach the match service â skip this and import anyway."}),c.length>0&&e.jsx("ul",{className:"im-uploader-mal-list",children:c.map(g=>{const f=[g.title_japanese,g.title_english&&g.title_english!==g.title?g.title_english:null,g.year?String(g.year):null,g.type].filter(Boolean).join(" · ");return e.jsx("li",{children:e.jsxs("button",{type:"button",className:"im-uploader-mal-option",onClick:()=>n({malId:g.mal_id,malType:t,title:g.title}),children:[e.jsx("span",{className:"mal-title",children:g.title}),f&&e.jsx("span",{className:"mal-sub",children:f})]})},g.mal_id)})}),e.jsx("p",{className:"im-uploader-field-hint",children:"Linking is optional â it lets us recognize character names so they aren't mistaken for vocabulary or grammar. No cover images are shown."})]})}const dl=["readable","store"];function cj({metadata:t,onTitleChange:a,onDescriptionChange:s,category:n,files:r,coverUrl:i,onCoverChange:l,enableOcr:c,onEnableOcrChange:d,enableProcessing:m,onEnableProcessingChange:u,estimatedOcrUnits:h,estimatedEnrichmentUnits:p,planningPending:g=!1,sharedCreditAvailable:f,walletPending:b=!1,walletResetAt:y,isPro:x,cloudSyncKind:v,cloudSyncEnabled:w,onCloudSyncEnabledChange:j,cloudSyncEstimate:T,cloudSyncUsage:P,volumeList:N,volumesDetecting:_,malMatch:L,onMalSelect:q,onMalClear:O,onUpgrade:A,onConfirm:k,onCancel:J,confirmLabel:M,confirmDisabled:H=!1,authed:ee=!0}){const D=n==="manga"&&r.filter(ct=>ct.type==="pdf").length>=2||r.some(ct=>ct.type==="pdf"&&ct.pdfKind!=="text"),de=r.some(ct=>ct.type==="pdf"&&ct.pdfKind==="text"),fe=r.some(ct=>ct.type==="image"||ct.type==="cbz"||ct.type==="archive")||D,Me=r.some(ct=>ct.type==="epub"||ct.type==="kindle"),U=Me||de,ve=fe||Me&&n==="manga";o.useEffect(()=>{ve&&m&&!c&&d(!0)},[ve,c,m,d]);const yt=!b&&f===0&&(c||m),ut=fe||U,St=fe?"Pages":"Files",je=Cv({enableProcessing:m}),[lt,Et]=o.useState(!1),Ct=ct=>{const se=hu(ct,ve);d(se.enableOcr),u(se.enableProcessing)},{getRadioProps:aa}=mf({count:dl.length,selectedIndex:dl.indexOf(je),onSelect:ct=>Ct(dl[ct])}),vt=ve&&!c,jt=ee?M??(m?"Add to library & analyze":"Add to library"):"Create a free account to continue",Ft=ee?"wc-cta-square wc-cta-square--ink":"wc-cta-square wc-cta-square-secondary--dusk";return e.jsxs(ze.div,{"data-tour-id":"uploader-confirm-step",initial:{opacity:0,y:16}
85,animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.4,ease:[.22,1,.36,1]},className:"im-uploader-panel",children:[e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"confirm-title",children:"Title"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"confirm-title",type:"text",value:t.title,onChange:ct=>a(ct.target.value),placeholder:"What should we call this?",className:"im-uploader-input"})})]}),e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"confirm-description",children:"Description (optional)"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("textarea",{id:"confirm-description",value:t.description,onChange:ct=>s(ct.target.value),placeholder:"A short note about this â what it is, where you're up to, anything useful.",className:"im-uploader-textarea",rows:3})})]}),q&&O&&e.jsx(np,{malType:"manga",initialQuery:t.title,value:L??null,onSelect:q,onClear:O}),n==="novel"&&e.jsx(Qn,{currentCoverUrl:i,onChange:l}),_&&!N&&e.jsx("div",{className:"im-uploader-field",children:e.jsx("p",{className:"im-uploader-volume-notice",style:{margin:0},children:"Reading volumesâ¦"})}),N&&(N.volumes.length>0||N.notices.length>0)&&e.jsxs("div",{className:"im-uploader-field",children:[N.volumes.length>0&&e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"im-uploader-field-label",children:[N.volumes.length," volumes in this series"]}),e.jsx("ul",{className:"im-uploader-volume-list",children:N.volumes.map(ct=>e.jsxs("li",{className:"im-uploader-volume-row",children:[e.jsx("span",{className:"vol-num","aria-hidden":"true",children:ct.volumeNumber!=null?String(ct.volumeNumber).padStart(2,"0"):"â"}),e.jsx("span",{className:"vol-name",children:ct.name}),e.jsxs("span",{className:"vol-pages",children:[ct.pageCount," pages"]})]},ct.key))})]}),N.notices.map((ct,se)=>e.jsx("p",{className:"im-uploader-volume-notice",children:ct},se))]}),e.jsxs("div",{className:"im-uploader-field",role:"radiogroup","aria-label":"What should we do with this?",children:[e.jsx("span",{className:"im-uploader-field-label",children:"What should we do with this?"}),e.jsxs("div",{className:"im-uploader-choice-grid",children:[e.jsxs("button",{type:"button",role:"radio","aria-checked":je==="readable",className:`im-uploader-choice${je==="readable"?" is-selected":""}`,onClick:()=>Ct("readable"),...aa(0),children:[e.jsx("span",{className:"im-uploader-choice-check","aria-hidden":"true",children:e.jsx(Ys,{})}),e.jsx("span",{className:"im-uploader-choice-glyph","aria-hidden":"true",children:e.jsx(Up,{})}),e.jsxs("span",{className:"im-uploader-choice-head",children:["Make it readable & tappable",e.jsx("span",{className:"im-uploader-choice-rec",children:"Recommended"})]}),e.jsx("span",{className:"im-uploader-choice-desc",children:ve?"We recognize the Japanese text so you can tap any word to look it up, and analyze it for grammar and vocabulary as you read.":"We analyze the text for grammar and vocabulary, so words and patterns are annotated as you read."})]}),e.jsxs("button",{type:"button",role:"radio","aria-checked":je==="store",className:`im-uploader-choice${je==="store"?" is-selected":""}`,onClick:()=>Ct("store"),...aa(1),children:[e.jsx("span",{className:"im-uploader-choice-check","aria-hidden":"true",children:e.jsx(Ys,{})}),e.jsx("span",{className:"im-uploader-choice-glyph","aria-hidden":"true",children:e.jsx(hf,{})}),e.jsx("span",{className:"im-uploader-choice-head",children:"Just store it"}),e.jsx("span",{className:"im-uploader-choice-desc",children:"Add it to your library as-is. No tapping to look up words, no analysis â you can turn this on later from the library."})]})]}),e.jsxs("div",{className:"im-uploader-advanced",children:[e.jsxs("button",{type:"button",className:"im-uploader-advanced-toggle","aria-expanded":lt,onClick:()=>Et(ct=>!ct),children:[e.jsx(Ip,{"aria-hidden":"true",style:{transform:lt?"rotate(180deg)":"none",transition:"transform 160ms"}}),"Advanced"]}),lt&&e.jsxs("div",{className:"im-uploader-advanced-body",children:[ve&&e.jsxs("div",{className:"im-uploader-toggle-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsxs("span",{className:"row-head",children:[e.jsx(gd,{"aria-hidden":"true"}),"Recognize Japanese text (OCR)"]}),e.jsx("p",{className:"row-desc",children:c?"Japanese text in your images becomes selectable â tap any word to look it up.":"Images are kept as-is. Text won't be tappable."})]}),e.jsx($n,{checked:c,onCheckedChange:ct=>{d(ct),ct||u(!1)},style:{"--primary":"var(--brand-chat)"}})]}),e.jsxs("div",{className:"im-uploader-toggle-row",style:{opacity:vt?.55:1},children:[e.jsxs("div",{className:"row-text",children:[e.jsxs("span",{className:"row-head",children:[e.jsx(vs,{"aria-hidden":"true"}),"Analyze grammar & vocabulary"]}),e.jsx("p",{className:"row-desc",children:vt?"Turn on text recognition first to unlock analysis.":m?"Text is analyzed for grammar patterns and vocabulary, with annotations as you read.":"Import without analysis. You can analyze it later from the library."})]}),e.jsx($n,{checked:m,onCheckedChange:u,disabled:vt,style:{"--primary":"var(--brand-chat)"}})]})]})]})]}),e.jsx(sp,{kind:v,enabled:w,onChange:j,estimate:T,usage:P,isPro:x,onUpgrade:A}),ut&&e.jsx("div",{className:"im-uploader-toggle-row im-uploader-toggle-row--info",children:e.jsxs("div",{className:"row-text",children:[e.jsxs("span",{className:"row-head",children:[e.jsx(ii,{"aria-hidden":"true"}),St," stay on this device"]}),e.jsxs("p",{className:"row-desc",children:["The actual ",St.toLowerCase()," are saved in this browser, not uploaded to our servers â your looked-up words, grammar notes and reading progress sync to your account. If your browser clears space, or you want to read on another device, just re-import the same file and everything carries over."]})]})}),D&&e.jsx("div",{className:"im-uploader-toggle-row im-uploader-toggle-row--info",children:e.jsxs("div",{className:"row-text",children:[e.jsxs("span",{className:"row-head",children:[e.jsx(gd,{"aria-hidden":"true"}),"PDFs are read as scanned images"]}),e.jsx("p",{className:"row-desc",children:"We run OCR on every PDF page, which is ideal for scanned manga. If this is a text novel, an EPUB or DRM-free Kindle file gives cleaner, more accurate results."})]})}),(c||m)&&e.jsx(Qv,{estimatedOcrUnits:h,estimatedEnrichmentUnits:p,planningPending:g,walletPending:b,sharedCreditAvailable:f,ocrEnabled:c,enrichmentEnabled:m,files:r}),yt&&e.jsx(tj,{isPro:x,onUpgrade:A,availableCredits:f,resetAt:y}),e.jsxs("div",{className:"im-uploader-mode-row",style:{marginTop:8},children:[e.jsx("button",{type:"button",className:Ft,onClick:()=>k(hu(je,ve)),disabled:H||!t.title.trim(),children:jt}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--dusk",onClick:J,children:"Cancel"})]})]},"confirm-step")}function dj({category:t,title:a,onTitleChange:s,coverUrl:n,onCoverChange:r,existingShows:i,selectedShowId:l,onSelectedShowIdChange:c,seasonNumber:d,onSeasonNumberChange:m,seasonLabel:u,onSeasonLabelChange:h,uploadFiles:p,videoPairingBytes:g,unpairedVideoNames:f,isDragging:b,onDragOver:y,onDragLeave:x,onDrop:v,onSelectSubtitles:w,onSelectFolder:j,onRemoveFile:T,enableProcessing:P,onEnableProcessingChange:N,isPro:_,sharedCreditAvailable:L=null,walletPending:q=!1,cloudSyncEnabled:O,onCloudSyncEnabledChange:A,cloudSyncEstimate:k,cloudSyncUsage:J,onUpgrade:M,malMatch:H,onMalSelect:ee,onMalClear:Pe,onUpload:D}){const de=p.filter(ve=>ve.type==="subtitle"||ve.type==="video"),fe=de.some(ve=>ve.type==="video"),Me=t==="movie",U=de.length>0&&(!!l||a.trim().length>0)&&(!fe||_&&O);return e.jsxs(ze.div,{initial:{opacity:0,x:24}
85,animate:{opacity:1,x:0},exit:{opacity:0,x:-24},transition:{duration:.4,ease:[.22,1,.36,1]},style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsx(Er,{eyebrow:Me?"Import movie":"Import series",jp:Me?"æ ç»":"å",title:Me?"Add a movie or subtitles":"Add this season's episodes",lede:Me?"Upload a video by itself to generate Japanese subtitles from its audio, or add your own .srt/.ass. Videos must be stored in Cloud Library for transcription.":"Upload videos by themselves to generate Japanese subtitles from their audio, or add your own .srt/.ass. Episode numbers are detected from file names."}),e.jsxs("div",{className:"im-uploader-panel",children:[!l&&!Me&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-uploader-field",children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"show-title",children:"Show title"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"show-title",type:"text",value:a,onChange:ve=>s(ve.target.value),placeholder:"e.g. Steins;Gate",className:"im-uploader-input"})})]}),e.jsx(Qn,{currentCoverUrl:n,onChange:r}),ee&&Pe&&e.jsx(np,{malType:"anime",initialQuery:a,value:H??null,onSelect:ee,onClear:Pe})]}),!Me&&i.length>0&&e.jsx(Yr,{label:"Or attach to existing show",value:l||"",onChange:ve=>{if(c(ve||null),ve){const yt=i.find(ut=>ut.id===ve);yt&&s(yt.title)}},options:[{value:"",label:"New show"},...i.map(ve=>({value:ve.id,label:ve.title}))]}),!Me&&e.jsxs("div",{style:{display:"flex",gap:12},children:[e.jsxs("div",{className:"im-uploader-field",style:{flex:1},children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"season-number",children:"Season number"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"season-number",type:"number",min:1,value:d,onChange:ve=>m(parseInt(ve.target.value)||1),className:"im-uploader-input"})})]}),e.jsxs("div",{className:"im-uploader-field",style:{flex:1},children:[e.jsx("label",{className:"im-uploader-field-label",htmlFor:"season-label",children:"Season label"}),e.jsx("div",{className:"im-uploader-input-frame",children:e.jsx("input",{id:"season-label",type:"text",value:u,onChange:ve=>h(ve.target.value),placeholder:`Season ${d}`,className:"im-uploader-input"})})]})]}),e.jsxs("div",{className:"im-uploader-field",children:[e.jsxs("label",{className:"im-uploader-field-label",children:["Video or subtitle files ",Me?"":"· one per episode"]}),e.jsx("div",{className:`im-uploader-dropzone${b?" is-dragging":""}`,style:{padding:24},onDragOver:y,onDragLeave:x,onDrop:v,onClick:w,role:"button",tabIndex:0,onKeyDown:ve=>{(ve.key==="Enter"||ve.key===" ")&&(ve.preventDefault(),w())},children:de.length>0?e.jsxs("div",{className:"im-uploader-file-list",style:{width:"100%"},onClick:ve=>ve.stopPropagation(),children:[de.map(ve=>{const yt=g?.[ve.id];return e.jsxs("div",{className:"im-uploader-file-row",children:[e.jsx(Rn,{size:14,"aria-hidden":"true",style:{color:"hsl(var(--brand-chat))"}}),e.jsx("span",{className:"name",title:ve.file.name,children:ve.file.name}),yt!=null&&e.jsxs("span",{className:"im-uploader-file-video-tag",title:"A video file is attached to this episode and will sync to your cloud library if enabled.",children:["video · ",(yt/(1024*1024)).toFixed(0)," MB"]}),e.jsx("span",{className:"size",children:ve.type==="video"?`${(ve.file.size/(1024*1024)).toFixed(0)} MB`:`${(ve.file.size/1024).toFixed(1)} KB`}),e.jsx("button",{type:"button",className:"remove",onClick:ut=>{ut.stopPropagation(),T(ve.id)},"aria-label":`Remove ${ve.file.name}`,children:e.jsx(rs,{"aria-hidden":"true"})})]},ve.id)}),e.jsx("p",{className:"im-uploader-field-hint",style:{textAlign:"center",marginTop:6},children:"Click anywhere to add more, or drag files in."})]}):e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"im-uploader-dropzone-glyph","aria-hidden":"true",children:e.jsx(Rn,{})}),e.jsx("p",{className:"im-uploader-dropzone-sub",children:b?"Drop video or subtitle files here":"Drop .mp4 / .mkv / .srt / .ass files here, or click to browse."})]})}),!Me&&j&&e.jsx("button",{type:"button",className:"im-uploader-back",style:{marginTop:6,alignSelf:"flex-start"},onClick:j,children:"+ Select entire folder"}),e.jsxs("details",{className:"im-uploader-guide",children:[e.jsx("summary",{children:"How do I import? (subtitles, video + your own subs, whole seasons)"}),e.jsxs("div",{className:"im-uploader-guide-body",children:[e.jsxs("div",{className:"im-uploader-guide-method",children:[e.jsx("h5",{children:"Just a subtitle"}),e.jsxs("p",{children:["Drop a ",e.jsx("code",{children:".srt"})," or ",e.jsx("code",{children:".ass"})," on its own â perfect for shows you watch elsewhere. ",Me?"One file per movie.":"One file per episode."]}
85)]}),e.jsxs("div",{className:"im-uploader-guide-method",children:[e.jsx("h5",{children:"Video + your own subtitle (choose the track)"}),e.jsxs("p",{children:["Drop the video (",e.jsx("code",{children:".mp4"}),", ",e.jsx("code",{children:".mkv"}),", ",e.jsx("code",{children:".avi"}),", ",e.jsx("code",{children:".mov"}),"â¦) together with a ",e.jsx("code",{children:".srt"}),"/",e.jsx("code",{children:".ass"})," that has the ",e.jsx("strong",{children:"same filename"}),". That subtitle is ",e.jsx("strong",{children:"always what we read"})," â the video's own subtitles (an MKV's embedded track, or subs burned into the picture) are never used. The video stays on this device unless you enable cloud library sync."]})]}),e.jsxs("div",{className:"im-uploader-guide-method",children:[e.jsx("h5",{children:"MKV embedded subtitle"}),e.jsxs("p",{children:["Drop an ",e.jsx("code",{children:".mkv"})," on its own and we read its embedded text tracks in your browser so you can pick one. This is a fallback, used only when you ",e.jsx("em",{children:"didn't"}),"supply your own subtitle. Other containers (",e.jsx("code",{children:".mp4"}),", ",e.jsx("code",{children:".avi"}),",",e.jsx("code",{children:".mov"}),"â¦) can instead be stored in Cloud Library and transcribed from audio."]})]}),!Me&&e.jsxs("div",{className:"im-uploader-guide-method",children:[e.jsx("h5",{children:"A whole season at once"}),e.jsxs("p",{children:["Put every episode's video and its matching subtitle in one folder â give each pair the ",e.jsx("strong",{children:"same name"})," (or at least the same episode number) â then use",e.jsx("em",{children:" â+ Select entire folderâ"})," above."]}),e.jsx("div",{className:"im-uploader-guide-tree","aria-hidden":"true",children:`One Piece S01/ 86ââ One_Piece_-_001.mkv 87ââ One_Piece_-_001.srt â used; the MKV's own subs are ignored 88ââ One_Piece_-_002.mkv 89ââ One_Piece_-_002.srt`}),e.jsxs("p",{className:"im-uploader-guide-tip",children:[e.jsx("strong",{children:"Tip:"})," matching names is what makes each video pair to your chosen subtitle â so the native video track is skipped every time. An episode with no matching subtitle falls back to its MKV embedded track (or, for other formats, asks for a subtitle)."]})]})]})]}),f&&f.length>0&&e.jsx("div",{style:{marginTop:8,display:"flex",flexDirection:"column",gap:2},children:f.map(ve=>e.jsx("p",{className:"im-uploader-cloud-quota-warn",style:{margin:0},children:Uw(ve)},ve))})]}),e.jsxs("div",{className:"im-uploader-toggle-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsxs("span",{className:"row-head",children:[e.jsx(vs,{"aria-hidden":"true"}),"NLP enrichment"]}),e.jsx("p",{className:"row-desc",children:fe?"After cloud upload, generate subtitles from the episode row. The generated transcript then enters annotation automatically.":P?"Subtitles will be analyzed for grammar and vocabulary annotations.":"Import as plain subtitles. You can process them later from the library."}),P&&e.jsxs("p",{className:"row-desc",style:{display:"inline-flex",alignItems:"center",gap:6,marginTop:4},children:[e.jsx(fm,{size:12,"aria-hidden":"true"}),"Processing uses your shared credit balance",q?" (loading balanceâ¦).":L==null?".":` (${new Intl.NumberFormat().format(L)} available).`]})]}),e.jsx($n,{checked:P,onCheckedChange:N,style:{"--primary":"var(--brand-chat)"}})]}),(!_||k.bytes!=null)&&e.jsx(sp,{kind:"video",enabled:O,onChange:A,estimate:k,usage:J,isPro:_,onUpgrade:M}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:D,disabled:!U,style:{alignSelf:"flex-start"},children:fe?"Add to Cloud Library":P?"Add to library & analyze":"Add to library"}),fe&&(!_||!O)&&e.jsx("p",{className:"im-uploader-cloud-quota-warn",style:{margin:0},children:"Video subtitle generation requires Premium Cloud Library storage."})]})]},"series-movie-form")}function uj(t){const a=t.filter(n=>gn(n));return a.length===0?null:(a.find(n=>n.isDefault)??a[0]).trackNumber}function rp(t){return t&&t.language?t.language.toUpperCase():"â"}function mj({staged:t,onExtracted:a,onCancel:s}){const n=o.useMemo(()=>t.filter(P=>P.tracks&&P.tracks.some(N=>gn(N))),[t]),r=o.useMemo(()=>t.filter(P=>!P.tracks||!P.tracks.some(N=>gn(N))),[t]),i=o.useMemo(()=>$w(t),[t]),[l,c]=o.useState(()=>{const P={};for(const N of n){const _=uj(N.tracks??[]);_!=null&&(P[N.id]=_)}return P}
89),[d,m]=o.useState("select"),[u,h]=o.useState(0),[p,g]=o.useState(0),[f,b]=o.useState(0),y=o.useRef(null),x=o.useMemo(()=>i!=="batch"||n.length===0?[]:(n[0].tracks??[]).slice(),[i,n]),v=o.useCallback(P=>{c(N=>{const _={...N};for(const L of n){const q=(L.tracks??[]).find(O=>gn(O)&&Il(O)===P);q&&(_[L.id]=q.trackNumber)}return _})},[n]),w=o.useCallback((P,N)=>{c(_=>({..._,[P]:N}))},[]),j=o.useCallback(async()=>{m("extracting"),h(0),g(0),b(0);const P=new AbortController;y.current=P;const N=[];let _=0;for(let L=0;L<n.length;L++){if(P.signal.aborted)return;const q=n[L];h(L),g(0);const O=l[q.id];if(O==null){N.push({id:q.id,file:q.file,handle:q.handle,error:Yi}),_+=1;continue}try{const A=await bw(q.file,O,{onProgress:k=>{P.signal.aborted||g(k)},signal:P.signal});if(P.signal.aborted)return;if(A.content.length>Mw){N.push({id:q.id,file:q.file,handle:q.handle,error:Aw}),_+=1;continue}N.push({id:q.id,file:q.file,handle:q.handle,result:{format:A.format,content:A.content}})}catch(A){if(A?.name==="AbortError")return;const k=A instanceof Ss||A instanceof Error?A.message:"Extraction failed";N.push({id:q.id,file:q.file,handle:q.handle,error:k}),_+=1}}for(const L of r)N.push({id:L.id,file:L.file,handle:L.handle,error:L.error??Yi}),_+=1;P.signal.aborted||(y.current=null,b(_),a(N))},[n,r,l,a]),T=o.useCallback(()=>{y.current&&(y.current.abort(),y.current=null),s()},[s]);if(d==="extracting"){const P=n[u],N=n.length>0?Math.round((u+p)/n.length*100):0;return e.jsxs(ze.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.4,ease:[.22,1,.36,1]},className:"im-uploader-status",children:[e.jsx("span",{className:"im-uploader-status-glyph","aria-hidden":"true",children:e.jsx(Sa,{className:"spin"})}),e.jsx("h3",{children:"Extracting subtitles"}),e.jsx("p",{children:P?P.file.name:"Preparingâ¦"}),e.jsxs("p",{style:{fontFamily:"'JetBrains Mono', monospace",fontSize:11,letterSpacing:"0.1em"},children:["File ",Math.min(u+1,n.length)," / ",n.length]}),e.jsx("div",{className:"im-uploader-status-bar","aria-hidden":"true",children:e.jsx("div",{className:"fill",style:{width:N+"%"}})}),e.jsxs("p",{style:{fontFamily:"'JetBrains Mono', monospace",fontSize:11,letterSpacing:"0.1em"},children:[N,"% complete"]}),e.jsx("button",{type:"button",onClick:T,className:"im-uploader-back",style:{marginTop:8},children:"Cancel extraction"})]},"mkv-extracting")}return e.jsxs(ze.div,{initial:{opacity:0,x:24},animate:{opacity:1,x:0},exit:{opacity:0,x:-24},transition:{duration:.4,ease:[.22,1,.36,1]},style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsx(Zh,{onClick:T,label:"Back to files"}),e.jsx(Er,{eyebrow:"Embedded subtitles",jp:"åå¹",title:i==="auto"?"Ready to extract":"Choose a subtitle track",lede:i==="auto"?"We found a text subtitle track in each MKV. We will extract it and feed it into the episode form - your video never leaves this device.":i==="batch"?"These MKVs share the same tracks. Pick one track and we will extract it from every file.":"These MKVs have different tracks. Pick a track for each file."}),e.jsxs("div",{className:"im-uploader-panel",children:[i==="batch"&&n.length>0&&e.jsxs("div",{className:"im-mkv-track-group",children:[e.jsxs("span",{className:"im-uploader-field-label",children:[n.length," file",n.length===1?"":"s"," · ",n[0].file.name]}),e.jsx("div",{className:"im-mkv-track-list",role:"radiogroup","aria-label":"Subtitle track",children:x.map(P=>{const N=gn(P),_=Il(P),L=N&&l[n[0].id]===P.trackNumber;return e.jsx(fu,{track:P,supported:N,selected:L,onSelect:()=>{N&&v(_)}},P.trackNumber)})})]}),i==="per-file"&&n.map(P=>e.jsxs("div",{className:"im-mkv-track-group",children:[e.jsx("span",{className:"im-uploader-field-label",children:P.file.name}),e.jsx("div",{className:"im-mkv-track-list",role:"radiogroup","aria-label":"Subtitle track for "+P.file.name,children:(P.tracks??[]).map(N=>{const _=gn(N),L=_&&l[P.id]===N.trackNumber;return e.jsx(fu,{track:N,supported:_,selected:L,onSelect:()=>{_&&w(P.id,N.trackNumber)}},N.trackNumber)})})]},P.id)),i==="auto"&&e.jsx("div",{className:"im-mkv-auto-list",children:n.map(P=>{const N=(P.tracks??[]).find(_=>_.trackNumber===l[P.id]);return e.jsxs("div",{className:"im-uploader-file-row",children:[e.jsx(on,{size:14,"aria-hidden":"true",style:{color:"hsl(var(--brand-chat))",flex:"0 0 auto"}}),e.jsx("span",{className:"name",title:P.file.name,children:P.file.name}),N&&e.jsx("span",{className:"im-mkv-codec-badge","data-kind":N.kind,children:N.kind.toUpperCase()}),e.jsx("span",{className:"size",children:rp(N)})]},P.id)})}),r.length>0&&e.jsx("div",{className:"im-mkv-failed-list",children:r.map(P=>e.jsxs("div",{className:"im-mkv-failed-row",children:[e.jsx(ni,{size:14,"aria-hidden":"true"}),e.jsx("span",{className:"name",title:P.file.name,children:P.file.name}),e.jsx("span",{className:"note",children:P.error??Yi})]},P.id))}),f>0&&e.jsxs("p",{className:"im-uploader-cost-shortfall",children:[f," file(s) could not be extracted."]}),e.jsxs("div",{style:{display:"flex",gap:12,alignItems:"center"},children:[e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:j,disabled:n.length===0,children:[e.jsx(on,{size:14,"aria-hidden":"true",style:{marginRight:6}}
89),n.length===0?"No extractable tracks":"Extract "+n.length+" subtitle track"+(n.length===1?"":"s")]}),e.jsx("button",{type:"button",className:"im-uploader-back",onClick:T,children:"Cancel"})]})]})]},"mkv-select")}function fu({track:t,supported:a,selected:s,onSelect:n}){const r="im-mkv-track-row"+(s?" is-selected":"")+(a?"":" is-unsupported");return e.jsxs("button",{type:"button",role:"radio","aria-checked":s,disabled:!a,onClick:n,className:r,children:[e.jsx("span",{className:"im-mkv-track-radio","aria-hidden":"true",children:s?e.jsx(Ys,{size:12}):null}),e.jsx("span",{className:"im-mkv-codec-badge","data-kind":t.kind,children:a?t.kind.toUpperCase():"IMG"}),e.jsx("span",{className:"im-mkv-track-lang",children:rp(t)}),e.jsx("span",{className:"im-mkv-track-name",title:t.name??void 0,children:t.name??(a?"Untitled track":"image-based - unsupported")}),t.isDefault&&a&&e.jsx("span",{className:"im-mkv-track-flag",children:"default"}),t.isForced&&a&&e.jsx("span",{className:"im-mkv-track-flag",children:"forced"})]})}function hj({files:t,category:a,enabled:s,pageCredits:n,archiveHasMokuro:r,volumes:i}){if(!s||t.length===0)return 0;if(i&&i.length>0)return i.reduce((d,m)=>d+(m.hasMokuro?0:m.pageCount),0);if(t.some(d=>d.type==="subtitle"))return 0;const l=t.filter(d=>d.type==="pdf");return l.length===1&&l[0].pdfKind==="text"||a!=="manga"&&t.some(d=>d.type==="epub"||d.type==="kindle")||t.some(d=>d.type==="mokuro")||t.some(d=>d.type==="archive"||d.type==="cbz")&&r===!0?0:t.some(d=>d.type==="image"||d.type==="archive"||d.type==="cbz"||d.type==="pdf"||(d.type==="epub"||d.type==="kindle")&&a==="manga")?Math.max(0,n):0}function Uc({episodeLabel:t,onConfirmed:a,onCancel:s}){const{getAccessToken:n,user:r}=ps(),[i,l]=o.useState(!1),[c,d]=o.useState(!1),[m,u]=o.useState(null),h=async()=>{if(!i||c)return;d(!0),u(null);const g=await iv(Bc(n),r?.id??null);d(!1),g.ok?(ne("cloud_video_attested",{}),a()):u(g.status===401?"Please sign in again to continue.":"Could not record your confirmation â please try again.")},p=()=>{ne("cloud_video_attest_declined",{}),s()};return e.jsx("div",{className:"wc-root im-logged",role:"dialog","aria-modal":"true","aria-label":"Store your video in your cloud library",children:e.jsx(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},className:"im-modal-backdrop",onClick:g=>{g.target===g.currentTarget&&p()},children:e.jsxs(ze.div,{initial:{opacity:0,scale:.96,y:16},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.97,y:12},transition:{duration:.2,ease:[.22,1,.36,1]},className:"im-modal",onClick:g=>g.stopPropagation(),children:[e.jsxs("div",{className:"im-modal-head",children:[e.jsxs("div",{className:"left",children:[e.jsx("div",{className:"icon-box",children:e.jsx(Js,{size:18})}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h3",{children:"Store your video in your cloud library"}),e.jsx("p",{children:t})]})]}),e.jsx("button",{className:"close",onClick:p,"aria-label":"Close",disabled:c,children:e.jsx(rs,{size:18})})]}),e.jsx("p",{className:"im-attest-body",children:"Your file is stored privately for your account only. It is not shared with or accessible to other users. It is kept so you can play it on your other devices, and is removed if you unsync it, delete the episode, or 30 days after your subscription lapses."}),e.jsxs("label",{className:"im-attest-check",children:[e.jsx("input",{type:"checkbox",checked:i,onChange:g=>l(g.target.checked),disabled:c}),e.jsx("span",{children:"I confirm I lawfully possess this file and have the right to store a private copy."})]}),m&&e.jsx("p",{className:"im-attest-error",role:"alert",children:m}),e.jsxs("div",{className:"im-modal-actions",children:[e.jsx("button",{className:"im-modal-textbtn",onClick:p,disabled:c,children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--ink im-modal-cta",onClick:()=>{h()},disabled:!i||c,children:[c?e.jsx("span",{className:"im-cloud-sync-dot","aria-hidden":"true"}):e.jsx(pf,{size:14}),"Confirm & store"]})]})]})})})}const gu=250,pj=Object.freeze({grayscale:!1,contrast:1}),OS=Object.freeze({filters:pj});function fj(t,a=()=>crypto.randomUUID()){if(t.length===0)throw new RangeError("A scan handoff needs at least one page.");if(t.length>gu)throw new RangeError(`A scan handoff cannot exceed ${gu} pages.`);return t.map((s,n)=>{const r=`page-${String(n+1).padStart(4,"0")}.`;if(!s.name.startsWith(r)||!s.type.startsWith("image/"))throw new TypeError("Scanner pages must be ordered, numbered image files.");return{id:a(),file:s,type:"image",status:"pending",progress:0}})}function yu(t,a){return t!==null&&a!==null&&t.ownerUserId===a}function Dl(t){return t.current?(t.current=null,!0):!1}function gj(t,a){return Dl(t)?(a(),!0):!1}function yj(t,a){return a!==null&&(t==="manga-mode"||t==="novel-mode")}function bj(t,a){return a(t.ownerUserId,t.draftId,{expectedRevision:t.revision})}function xj(t,a,s){return a==="failed"?Promise.resolve(!1):bj(t,s)}const wj=o.lazy(()=>Rs(()=>import("./MangaScanAssistant-DARMIoT0.js"),__vite__mapDeps([2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90])).then(t=>({default:t.MangaScanAssistant})));async function bu(t){const a=await t.arrayBuffer(),s=await crypto.subtle.digest("SHA-256",a),n=new Uint8Array(s);let r="";for(let i=0;i<n.length;i++)r+=n[i].toString(16).padStart(2,"0");return r}function Sn(t){return t?.name==="AbortError"}function vj(t,a){return new Promise((s,n)=>{if(a.aborted){n(new DOMException("Upload cancelled","AbortError"));return}const r=setTimeout(()=>{a.removeEventListener("abort",i),s()},t),i=()=>{clearTimeout(r),n(new DOMException("Upload cancelled","AbortError"))};a.addEventListener("abort",i,{once:!0})})}function Fr(t,a){const s=t?.name;return s==="QuotaExceededError"?"Browser storage is full â delete old local manga or free up space, then try again.":s==="NotFoundError"?"The selected file is no longer available â choose it again, then retry the upload.":t instanceof Error?t.message:a}let Ll=0,Xi=null,pr=null;function Vr(){Ll+=1,pr?.abort(),pr=null,Xi=null,Xh()}jv(Vr);const mi=o.forwardRef(function({onUploadComplete:a,onUploadError:s,prefillMangaSeriesId:n,prefillMangaSeriesTitle:r,prefillShowId:i,prefillShowTitle:l,onExit:c,startScanner:d=!1},m){const{user:u}=ps(),{openAuthModal:h}=xo(),{openUpgradeModal:p}=xn(),{isPro:g,tier:f}=Xn(),{wallet:b,loading:y,available:x,refresh:v}=dm(),w=o.useRef(null),[j,T]=o.useState(d),P=o.useCallback((R,B)=>{const X=w.current;if(!X){a(R,B);return}Rs(async()=>{const{discardScanDraft:ae}=await import("./draft-store-DH5pQtab.js").then(ge=>ge.k);return{discardScanDraft:ae}},__vite__mapDeps([8,9])).then(({discardScanDraft:ae})=>xj(X,B?.duplicate?"existing-duplicate":"imported",ae)).then(()=>{const ae=w.current;ae?.draftId===X.draftId&&ae.revision===X.revision&&(w.current=null)}
89).catch(ae=>{ne("immersion_scan_failed",{failure_stage:"post-import-draft-cleanup",reason:ae instanceof Error&&ae.name==="ScanDraftChangedError"?"draft-changed":"storage-error"})}).finally(()=>a(R,B))},[a]),N=x&&b?b.available:null;o.useImperativeHandle(m,()=>({setContentCategory:R=>ve(R),setMangaSeriesMode:R=>Ve(R),reset:()=>{Vr(),ve(null),Ve(null),Dt(null),da(null),O([]),M({status:"idle",progress:0,message:""}),D({title:"",description:""}),Wt(null),ca(null),za(null),Ea(null),Ca(new Map),_t(null)},showConfirmStep:()=>{ve("manga"),Ve("standalone"),O([{id:"demo-file",file:new globalThis.File([],"demo-manga-vol1.cbz"),type:"cbz",status:"completed",progress:100}]),D({title:"My Manga Vol. 1",description:""}),M({status:"ready_to_confirm",progress:0,message:""})}}));const _=as(R=>R.uploadFiles),L=as(R=>R.setUploadFiles),q=as(R=>R.updateUploadFiles),O=o.useCallback(R=>{typeof R=="function"?q(R):L(R)},[L,q]),A=as(R=>R.uploadState),k=as(R=>R.setUploadState),J=as(R=>R.updateUploadState),M=o.useCallback(R=>{typeof R=="function"?J(R):k(R)},[k,J]),H=as(R=>R.metadata),ee=as(R=>R.setMetadata),Pe=as(R=>R.updateMetadata),D=o.useCallback(R=>{typeof R=="function"?Pe(R):ee(R)},[ee,Pe]),de=as(R=>R.resetUploader),[fe,Me]=o.useState(!1),[U,ve]=o.useState(null),[yt,ut]=o.useState(null),[St,je]=o.useState(null),lt=o.useCallback((R,B)=>{ut(R),je(R?B??null:null)},[]),[Et,Ct]=o.useState([]),[aa,vt]=o.useState(null),[Le,jt]=o.useState(1),[Ft,ct]=o.useState(""),[se,ft]=o.useState([]),[Oe,pt]=o.useState(null),[kt,Ve]=o.useState(null),Be=o.useRef(!1);o.useEffect(()=>{!d||Be.current||(Be.current=!0,ve("manga"),T(!0))},[d]);const[Ke,At]=o.useState(null),[Jt,ta]=o.useState(null),zt=o.useCallback((R,B)=>{At(R),ta(R?B??null:null)},[]),[K,_t]=o.useState(null),qt=o.useCallback(R=>_t(R),[]),sa=o.useCallback(()=>_t(null),[]),[la,Dt]=o.useState(null),[ba,da]=o.useState(null),xa=as(R=>R.enableOcr),ma=as(R=>R.setEnableOcr),Na=as(R=>R.enableProcessing),Da=as(R=>R.setEnableProcessing),[wa,Wt]=o.useState(null),[ua,ca]=o.useState(null),[ha,za]=o.useState(null),[ea,Ea]=o.useState(null),[pa,Ca]=o.useState(new Map),[Gt,Ba]=o.useState(!0),[ka,Wa]=o.useState(null),[es,Ta]=o.useState([]),[va,ia]=o.useState(null),oe=o.useRef(!1),[me,Ge]=o.useState(null),[gt,I]=o.useState(!1),xe=o.useRef(0),Ne=o.useRef(null),[tt,Mt]=o.useState(null),Ma=o.useCallback(R=>new Promise(B=>{Mt({info:R,resolve:B})}),[]),It=o.useCallback(()=>{tt?.resolve(!1),Mt(null)},[tt]),Nt=o.useCallback(()=>{tt?.resolve(!0),Mt(null)},[tt]),Lt=o.useCallback(R=>Wh(u?.id??null)?Promise.resolve(!0):new Promise(B=>{ia({episodeLabel:R,resolve:B})}),[u?.id]),qa=o.useCallback(()=>{va?.resolve(!0),ia(null)},[va]),F=o.useCallback(()=>{va?.resolve(!1),ia(null)},[va]),[Q,W]=o.useState(!1),[E,G]=o.useState([]),[re,pe]=o.useState(!1),[te,Fe]=o.useState([]),ke=o.useRef([]),Qe=o.useRef(new Map),Y=o.useRef(new Map),Ze=o.useRef(0),Ut=o.useMemo(()=>{if(_.length===0)return 0;const R=_.some(be=>be.type==="subtitle"),B=_.some(be=>be.type==="epub"||be.type==="kindle");if(R)return wa!=null?Math.ceil(wa/10):0;if(B&&ua)return ua.totalParagraphs;if(B)return _.length;if(_.find(be=>be.type==="archive"||be.type==="cbz"))return ha&&ha>0?ha:_.length;const ae=_.filter(be=>be.type==="pdf");if(ae.length>0){if(ae.length===1&&ae[0].pdfKind==="text"&&ua)return ua.totalParagraphs;if(me&&me.totalPages>0)return me.totalPages;const be=ae.map(Je=>pa.get(Je.id));return be.some(Je=>Je===void 0)?0:be.reduce((Je,nt)=>Je+(nt??0),0)}const ge=_.filter(be=>be.type==="image").length;return ge>0?ge:_.length},[_,wa,ua,ha,pa,me]),Ot=Na?Ut:0,is=o.useMemo(()=>hj({files:_,category:U,enabled:xa,pageCredits:Ut,archiveHasMokuro:ea,volumes:me?.volumes}),[_,U,xa,Ut,ea,me]),os=o.useMemo(()=>{const R=_.filter(B=>B.type==="pdf");return R.length===0||R.length===1&&R[0].pdfKind==="text"&&ua||me&&me.totalPages>0?!1:R.some(B=>!pa.has(B.id))},[_,ua,me,pa]),Qs=_.some(R=>(R.type==="archive"||R.type==="cbz")&&R.file.size>0)&&ea===null,C=os||Qs,V=o.useRef(null),le=o.useRef(!1),ye=o.useRef(!1);o.useEffect(()=>{ye.current||(n?(ye.current=!0,ve("manga"),Ve("existing"),pt(n),r&&D(R=>({...R,title:r}))):i&&(ye.current=!0,ve("series"),vt(i),l&&D(R=>({...R,title:l}))))},[]);const it=o.useRef(null),fa=o.useRef(null),Xt=o.useRef(null),ga=o.useRef(null),Tt=o.useRef(null),Pa=o.useRef(!1),oa=o.useRef(u?.id??null);o.useEffect(()=>{const R=u?.id??null;if(oa.current===R)return;oa.current=R;const B=w.current;!B||yu(B,R)||(Dl(w),Pa.current=!1,Tt.current?.abort(),Tt.current=null,Vr(),O([]),M({status:"idle",progress:0,message:""}),D({title:"",description:""}),ve(null),Ve(null),pt(null),zt(null),T(!1))},[u?.id,O,M,D,zt]);const Aa=o.useRef(null),Fa=R=>{const B=R.name.toLowerCase().trim();return B.endsWith(".mokuro")?"mokuro":B.endsWith(".cbz")?"cbz":B.endsWith(".epub")?"epub":B.endsWith(".mobi")||B.endsWith(".azw")||B.endsWith(".azw3")||B.endsWith(".prc")?"kindle":B.endsWith(".srt")||B.endsWith(".ass")||B.endsWith(".ssa")?"subtitle":zw(B)?"video":B.endsWith(".pdf")?"pdf":B.endsWith(".zip")||B.endsWith(".mbz")?"archive":B.endsWith(".jpg")||B.endsWith(".jpeg")||B.endsWith(".png")||B.endsWith(".webp")?"image":"unknown"},us=500*1024*1024,xs=2*1024*1024*1024,Ga=1*1024*1024*1024,Cs=R=>{const B=R.name.toLowerCase().trim();if(B.endsWith(".kfx")||B.endsWith(".kfx-zip"))return"KFX files are always copy-protected and canât be imported. If this is your own book, convert it to a DRM-free EPUB or AZW3 first, then upload that.";const X=Fa(R);if(X==="unknown")return`Unsupported file type: ${R.name}`;const ae=X==="archive"||X==="cbz",ge=X==="pdf",be=ge?Ga:ae?xs:us;if(R.size>be){if(ae)return`Archive too large: ${R.name} (max 2 GB â a zip is read entirely into memory). Extract it and select the FOLDER instead; folders of any size import one volume at a time.`;if(ge)return`PDF too large: ${R.name} (max 1 GB â a PDF is loaded entirely into memory to read). Split the volume into smaller PDFs and upload those.`;const Je=Math.round(be/(1024*1024));return`File too large: ${R.name} (max ${Je} MB)`}return null},Dn=R=>R.some(B=>B.type==="subtitle"||B.type==="video")?"subtitle":R.some(B=>
89B.type==="epub"||B.type==="kindle")||R.some(B=>B.type==="pdf"&&B.pdfKind==="text")?"epub":"manga",Tr=R=>R.some(B=>B.type==="subtitle"||B.type==="video")||R.some(B=>B.type==="epub"||B.type==="kindle")||R.some(B=>B.type==="pdf"&&B.pdfKind==="text")?"cloud":"local",Ja=o.useCallback(R=>{const B=R.filter(st=>st.type==="mokuro"),X=R.filter(st=>st.type==="image"),ae=R.filter(st=>st.type==="archive"),ge=R.filter(st=>st.type==="cbz"),be=R.filter(st=>st.type==="pdf"),Je=R.filter(st=>st.type==="epub"||st.type==="kindle"),nt=R.filter(st=>st.type==="subtitle"),bt=R.filter(st=>st.type==="video");return be.length>0&&(ae.length>0||ge.length>0)?{isValid:!1,error:"Please upload PDFs and CBZ/ZIP archives separately."}:be.length>=2&&U!=="manga"?{isValid:!1,error:"Multiple PDFs are supported for manga series â switch to the Manga category, or upload novels one PDF at a time."}:nt.length>0?{isValid:!0}:bt.length>0?{isValid:!0}:Je.length>0?{isValid:!0}:ae.length>0?{isValid:!0}:ge.length>0?{isValid:!0}:be.length>0?{isValid:!0}:X.length>0&&B.length===0?{isValid:!0}:B.length===0?{isValid:!1,error:"At least one .mokuro file is required, or upload only images for raw manga processing."}:X.length===0?{isValid:!1,error:"At least one image file is required. Please add image files or folders to continue."}:{isValid:!0}},[U]),Es=o.useCallback(R=>{const B=Array.from(R),X=[];for(const qe of B){const rt=Cs(qe);if(rt){const Re=qe.name.toLowerCase().trim(),at=Re.endsWith(".kfx")||Re.endsWith(".kfx-zip");at&&ne("kindle_import_refused",{reason:"kfx"}),M({status:"error",progress:0,message:"",error:rt,...at?{errorHeading:"This file canât be imported",errorNoRetry:!0}:{}});return}const Xe=Fa(qe);if(U==="novel"&&(Xe==="image"||Xe==="cbz"||Xe==="archive")){M({status:"error",progress:0,message:"",error:"Image/scan files can't be imported as novels. Go back and choose the Manga path instead â it handles scans, CBZ, and image files."});return}if(U==="novel"&&Xe==="subtitle"){M({status:"error",progress:0,message:"",error:"Subtitle files can't be imported as novels. Go back and choose the Series or Movie path instead."});return}if(U==="manga"&&Xe==="subtitle"){M({status:"error",progress:0,message:"",error:"Subtitle files can't be imported as manga. Go back and choose the Series or Movie path instead."});return}const Ae={id:crypto.randomUUID(),file:qe,type:Xe,status:"pending",progress:0,isFromFolder:!1};X.push(Ae)}const ae=X[0]?.type??"unknown";ne("immersion_upload_started",{file_type:{archive:"cbz",cbz:"cbz",pdf:"pdf",epub:"epub",kindle:"kindle",subtitle:"subtitle",video:"video"}[ae]??"other",file_count:X.length}),O(qe=>{const rt=[...qe,...X];return M(Xe=>({...Xe,status:Xe.status==="ready_to_confirm"?"ready_to_confirm":"idle",progress:0,message:`Added ${X.length} file${X.length===1?"":"s"} successfully!`})),setTimeout(()=>{M(Xe=>({...Xe,message:""}))},3e3),rt});const be=X.filter(qe=>qe.type==="subtitle");be.length>0&&Rr(be.map(qe=>qe.file)).then(qe=>{qe!=null&&Wt(rt=>(rt??0)+qe)});const Je=X.find(qe=>qe.type==="epub");if(Je){const qe=oo(Je.file);Aa.current={file:Je.file,promise:qe},qe.then(rt=>{const Xe=rt.reduce((Re,at)=>Re+at.paragraphs.length,0),Ae=rt.reduce((Re,at)=>Re+at.paragraphs.reduce((Ie,Ue)=>Ie+Ue.length,0),0);ca({chapters:rt.length,totalParagraphs:Xe,totalChars:Ae})}).catch(()=>{})}const nt=X.find(qe=>qe.type==="kindle");nt&&Hm(nt.file).then(({title:qe,chapters:rt})=>{if(rt){Aa.current={file:nt.file,promise:Promise.resolve(rt)};const Xe=rt.reduce((Re,at)=>Re+at.paragraphs.length,0),Ae=rt.reduce((Re,at)=>Re+at.paragraphs.reduce((Ie,Ue)=>Ie+Ue.length,0),0);ca({chapters:rt.length,totalParagraphs:Xe,totalChars:Ae})}qe&&D(Xe=>Xe.title===""||Xe.title===nt.file.name.replace(/\.[^/.]+$/,"")?{...Xe,title:qe}:Xe)}).catch(()=>{});const bt=X.find(qe=>qe.type==="archive"||qe.type==="cbz");bt&&bt.file.size>0&&U!=="manga"&&dy(bt.file).then(qe=>{qe>0&&za(qe)}).catch(()=>{});const st=(qe,rt,Xe=!0)=>{const Ae=Re=>{Ca(at=>{const Ie=new Map(at);return Ie.set(rt,Re>0?Re:0),Ie})};return qe.arrayBuffer().then(Re=>{const at=new Uint8Array(Re);return Sl(qe,at).then(Ie=>{Ae(Ie)}).catch(()=>{Ae(0)}).then(()=>Xe?Xo(qe,at):null).then(Ie=>{if(Ie&&(O(Ue=>Ue.map(mt=>mt.id===rt?{...mt,pdfKind:Ie}:mt)),Ie==="text")){const Ue=jd(qe);Aa.current={file:qe,promise:Ue},Ue.then(mt=>{const xt=mt.reduce((Ye,dt)=>Ye+dt.paragraphs.length,0),Yt=mt.reduce((Ye,dt)=>Ye+dt.paragraphs.reduce((S,z)=>S+z.length,0),0);ca({chapters:mt.length,totalParagraphs:xt,totalChars:Yt})}).catch(()=>{})}}).catch(()=>{})}).catch(()=>{Ae(0)})},$t=X.filter(qe=>qe.type==="pdf"&&qe.file.size===0);$t.length>0&&Ca(qe=>{const rt=new Map(qe);for(const Xe of $t)rt.set(Xe.id,0);return rt});const _a=X.filter(qe=>qe.type==="pdf"&&qe.file.size>0);if(_a.length>0){const qe=!(U==="manga"&&_a.length>=2);_a.reduce((rt,Xe)=>rt.then(()=>st(Xe.file,Xe.id,qe)),Promise.resolve())}const na=X.filter(qe=>(qe.type==="archive"||qe.type==="cbz")&&qe.file.size>0);for(const qe of na)wd(qe.file).then(rt=>{rt&&(O(Xe=>Xe.map(Ae=>Ae.id===qe.id?{...Ae,type:"pdf",file:rt,pdfKind:void 0}:Ae)),st(rt,qe.id))}).catch(rt=>{rt instanceof ro&&M({status:"error",progress:0,message:"",error:rt.message})});if(H.title===""){const qe=X.find(Ue=>Ue.type==="epub"),rt=X.find(Ue=>
89Ue.type==="kindle"),Xe=qe||rt;qe&&fy(qe.file).then(Ue=>{Ue&&D(mt=>mt.title===""||mt.title===qe.file.name.replace(/\.[^/.]+$/,"")?{...mt,title:Ue}:mt)}).catch(()=>{});const Ae=X.find(Ue=>Ue.type==="mokuro"),Re=X.find(Ue=>Ue.type==="archive"),at=X.find(Ue=>Ue.type==="cbz"),Ie=Ae?.file.name||Re?.file.name||at?.file.name||Xe?.file.name||X[0]?.file.name||"";D(Ue=>({...Ue,title:Ie.replace(/\.[^/.]+$/,"")}))}},[H.title,Ja,U]),$s=o.useCallback(R=>{const B=[];if(Array.from(R).forEach(X=>{Cs(X)||B.push(X)}),B.length>0){if(U==="manga"&&B.some(Je=>Fa(Je)==="subtitle")){M({status:"error",progress:0,message:"",error:"Subtitle files can't be imported as manga. Go back and choose the Series or Movie path instead."});return}if(U==="novel"&&B.some(Je=>{const nt=Fa(Je);return nt==="image"||nt==="cbz"||nt==="archive"})){M({status:"error",progress:0,message:"",error:"Image/scan files can't be imported as novels. Go back and choose the Manga path instead."});return}const X=B.map(be=>({id:crypto.randomUUID(),file:be,type:Fa(be),status:"pe
89nding",progress:0,isFromFolder:!0}));O(be=>{const Je=[...be,...X];return M(nt=>({...nt,status:nt.status==="ready_to_confirm"?"ready_to_confirm":"idle",progress:0,message:`Added ${X.length} file${X.length===1?"":"s"} from folder successfully!`})),setTimeout(()=>{M(nt=>({...nt,message:""}))},3e3),Je});const ae=X.filter(be=>be.type==="pdf");ae.length>0&&ae.reduce((be,Je)=>be.then(async()=>{let nt=0;if(Je.file.size>0)try{nt=await Sl(Je.file)}catch{}Ca(bt=>{const st=new Map(bt);return st.set(Je.id,nt),st})}),Promise.resolve());const ge=X.filter(be=>be.type==="subtitle");ge.length>0&&Rr(ge.map(be=>be.file)).then(be=>{be!=null&&Wt(Je=>(Je??0)+be)})}},[Ja,U]),Zn=o.useCallback(R=>{R.preventDefault(),Me(!0)},[]),Ln=o.useCallback(R=>{R.preventDefault(),Me(!1)},[]),er=o.useCallback(R=>{R.preventDefault(),Me(!1);const B=Array.from(R.dataTransfer.items),X=[];B.forEach(ae=>{if(ae.kind==="file"){if(ae.webkitGetAsEntry&&ae.webkitGetAsEntry()?.isDirectory)return;const ge=ae.getAsFile();ge&&X.push(ge)}}),X.length>0&&Es(X)},[Es]),Zs=o.useCallback(async R=>{if(R.length===0)return;const B=++Ze.current;pe(!0);const X=[];for(const{file:ae,handle:ge}of R){if(B!==Ze.current)return;const be=crypto.randomUUID();try{const Je=await hw(ae);Je.tracks.some(nt=>gn(nt))?X.push({id:be,file:ae,handle:ge,tracks:Je.tracks,error:null}):X.push({id:be,file:ae,handle:ge,tracks:Je.tracks,error:Yi})}catch(Je){const nt=Je instanceof Ss&&Je.code==="not_mkv"?Pw:Je instanceof Error?Je.message:"Could not read this MKV file.";X.push({id:be,file:ae,handle:ge,tracks:null,error:nt})}}B===Ze.current&&(pe(!1),G(X))},[]),Ts=o.useCallback(R=>{if(R.length===0)return;const B=[];for(const X of R){const ae=X.subtitle.name.toLowerCase().endsWith(".srt")?"srt":X.subtitle.name.toLowerCase().endsWith(".ssa")?"ssa":"ass",be=`${X.videoFilename.replace(/\.[^.]+$/,"")}.${ae}`,Je=new globalThis.File([X.subtitle],be,{type:"text/plain"}),nt=crypto.randomUUID();Y.current.set(nt,{handle:X.handle,videoFilename:X.videoFilename,file:X.videoFile}),B.push({id:nt,file:Je,type:"subtitle",status:"pending",progress:0,isFromFolder:!1})}O(X=>[...X,...B]),Rr(B.map(X=>X.file)).then(X=>{X!=null&&Wt(ae=>(ae??0)+X)})},[O,Wt]),en=o.useCallback(R=>{const B=[...ke.current,...R],{mkv:X,paired:ae,looseSubtitles:ge,unpairedVideoNames:be,unpairedVideos:Je}=qw(B);ke.current=Je,Fe(be);const nt=new Set;for(const st of ae){const $t=Qe.current.get(st.videoFile);$t&&(nt.add($t),Qe.current.delete(st.videoFile),Y.current.delete($t))}const bt=[];for(const st of Je){if(Qe.current.has(st.file))continue;const $t=crypto.randomUUID();Qe.current.set(st.file,$t),Y.current.set($t,{handle:st.handle,videoFilename:st.file.name,file:st.file}),bt.push({id:$t,file:st.file,type:"video",status:"pending",progress:0,isFromFolder:!1})}(nt.size>0||bt.length>0)&&O(st=>[...st.filter($t=>!nt.has($t.id)),...bt]),ge.length>0&&Es(ge),ae.length>0&&Ts(ae),X.length>0&&Zs(X.map(st=>({file:st.file,handle:st.handle})))},[Es,Ts,Zs,Fe,O]),Vs=o.useCallback(R=>{R.preventDefault(),Me(!1);const B=Array.from(R.dataTransfer.items),X=[];for(const ae of B){if(ae.kind!=="file")continue;const ge=ae.webkitGetAsEntry?.();if(ge&&ge.isDirectory)continue;const be=ae.getAsFile();if(!be)continue;const Je=ae.getAsFileSystemHandle;dn&&typeof Je=="function"?X.push(Je.call(ae).then(nt=>({file:be,handle:nt&&nt.kind==="file"?nt:null})).catch(()=>({file:be,handle:null}))):X.push(Promise.resolve({file:be,handle:null}))}Promise.all(X).then(ae=>{const ge=ae.filter(be=>be!==null);ge.length>0&&en(ge)})},[en,Me]),vn=o.useCallback(R=>{const B=R.target.files;!B||B.length===0||(en(Array.from(B).map(X=>({file:X,handle:null}))),R.target.value="")},[en]),Ms=o.useCallback(R=>{const B=R.target.files;!B||B.length===0||(en(Array.from(B).map(X=>({file:X,handle:null}))),R.target.value="")},[en]),tr=o.useCallback(R=>{const B=[],X=[];for(const ae of R)if(ae.result){const be=ae.file.name.replace(/\.mkv$/i,"")+"."+ae.result.format,Je=new globalThis.File([ae.result.content],be,{type:"text/plain"}),nt=crypto.randomUUID();Y.current.set(nt,{handle:ae.handle,videoFilename:ae.file.name,file:ae.file}),B.push({id:nt,file:Je,type:"subtitle",status:"pending",progress:0,isFromFolder:!1})}else ae.error&&X.push(ae.file.name+": "+ae.error);if(G([]),B.length>0&&(O(ae=>[...ae,...B]),Rr(B.map(ae=>ae.file)).then(ae=>{ae!=null&&Wt(ge=>(ge??0)+ae)})),X.length>0&&B.length===0){const ae=X.length===1?X[0]:X.length+" embedded subtitle track(s) could not be extracted.";M({status:"error",progress:0,message:"",error:ae})}},[O,M]),hn=o.useCallback(()=>{Ze.current++,G([]),pe(!1)},[]),tn=o.useCallback(R=>{const B=R.target.files;B&&B.length>0&&Es(B)},[Es]),jn=o.useCallback(R=>{const B=R.target.files;B&&B.length>0&&$s(B)},[$s]),On=o.useCallback(R=>{O(B=>{const X=B.find(ge=>ge.id===R),ae=B.filter(ge=>ge.id!==R);if(X?.type==="video"&&(ke.current=ke.current.filter(ge=>ge.file!==X.file),Qe.current.delete(X.file),Y.current.delete(R),Fe(ke.current.map(ge=>ge.file.name))),M({status:"idle",progress:0,message:""}),X?.type==="subtitle"){const ge=ae.filter(be=>be.type==="subtitle");ge.length===0?Wt(null):Rr(ge.map(be=>be.file)).then(be=>{Wt(be)})}return X?.type==="epub"&&(ca(null),Aa.current=null),(X?.type==="archive"||X?.type==="cbz")&&ae.filter(be=>be.type==="archive"||be.type==="cbz").length===0&&(za(null),Ea(null)),X?.type==="pdf"&&(Ca(ge=>{if(!ge.has(X.id))return ge;
89const be=new Map(ge);return be.delete(X.id),be}),Aa.current?.file===X.file&&(ca(null),Aa.current=null)),ae})},[O,M]),$=o.useCallback(async()=>{const{data:{session:R}}=await Ps.auth.getSession();return R?.access_token||null},[]),he=o.useCallback(R=>{Vr();const B=Ll;Xi=R;let X=0,ae=null;const ge=Date.now();let be=!1;const Je=()=>Ll!==B,nt=()=>{Je()||(Xh(),Xi=null,pr=null)},bt=qe=>{Je()||(nt(),ne("immersion_upload_failed",{category:U,file_type:_[0]?.type??"unknown",error_stage:"processing"}),M({status:"error",progress:0,message:"",error:qe}))},st=qe=>{if(Je())return;const rt=setTimeout(()=>{Ai()===rt&&rr(null),na()},Math.max(eo,Math.round(qe)));rr(rt)},$t=(qe,rt)=>{if(Je())return;const Xe=setTimeout(()=>{Ai()===Xe&&rr(null),bt(rt)},Math.max(0,Math.round(qe)));rr(Xe)},_a=qe=>{if(Je())return;const rt=Date.now();ae??=rt;const Xe=rt-ae;X+=1;const Ae=pv({consecutiveFailures:X,transientElapsedMs:Xe,totalElapsedMs:rt-ge,retryAfterMs:qe.retryAfterMs});if(Ae.kind==="expire"){$t(Ae.delayMs,Ae.reason==="total"?"Processing is taking longer than expected â please reload to check its status, or retry.":"Could not check processing status â processing may still be running. Please reload to check again.");return}st(Ae.delayMs)},na=async()=>{if(Je()||be)return;if(Date.now()-ge>=Rl){bt("Processing is taking longer than expected â please reload to check its status, or retry.");return}if(ae!=null&&Date.now()-ae>=Yh){bt("Could not check processing status â processing may still be running. Please reload to check again.");return}be=!0;let qe=null;try{const rt=await $();if(Je())return;if(!rt){bt("Your session expired while processing continued. Please sign in again, then reload to check its status.");return}const Xe=await hv(xt=>fetch(`${ue()}/api/reading/materials/${R}/status`,{headers:{Authorization:`Bearer ${rt}`},signal:xt}),{onController:xt=>{qe=xt,pr=xt}});if(Je())return;if(!Xe.ok){const xt=Xl(Xe);console.warn(`Material status check returned HTTP ${Xe.status}`),xt.kind==="transient"?_a(xt):Xe.status===401||Xe.status===403?bt("Your session expired while processing continued. Please sign in again, then reload to check its status."):Xe.status===404||Xe.status===410?bt("This material is no longer available. Return to your library and try the import again."):bt(`Could not check processing status (HTTP ${Xe.status}). Processing may still be running; please reload to check again.`);return}X=0,ae=null;const Ae=await Xe.json();if(Je())return;const Re=Ae.processingStatus,at=Ae.enrichmentStatus;if(Re==="completed"&&(at==="pending"||at==="processing")){const xt=as.getState().uploadState;xt.status==="processing"&&xt.materialId===R&&M({...xt,progress:Math.min(99,Math.max(xt.progress??0,95)),indeterminate:!0,message:"Finishing vocabulary and grammar annotationsâ¦"}),st(cl);return}if(Re==="completed"){console.log("â
Processing completed for material:",R),nt();const xt=V.current,Yt=at==="partial";le.current=Yt;let Ye="Added to your library.";Yt&&!xt&&(Ye=Ae.enrichmentError?`Text imported. Analysis was partial: ${Ae.enrichmentError} You can analyze the rest later.`:"Text imported â analysis was partial (you ran out of credits). You can analyze the rest later."),M({status:"completed",progress:100,message:Ye,...Yt&&xt?{analyzedUnits:xt.analyzed,totalUnits:xt.total,coverageUnit:xt.unit}:{}}),O([]),ne("immersion_upload_completed",{category:U,file_type:_[0]?.type??"unknown",ocr_enabled:xa,nlp_enabled:Na,cloud_sync_opted:Gt,tier:f}),P(R);return}if(Re==="failed"||Re==="error"){console.log("â Processing failed, stopping polling"),nt(),ne("immersion_upload_failed",{category:U,file_type:_[0]?.type??"unknown",error_stage:"processing"}),M({status:"error",progress:0,message:"",error:"Processing failed. Please try again."});return}const Ue=as.getState().uploadState;if(Ue.status==="processing"&&Ue.materialId===R){const xt=typeof Ae.progress=="number"?Ae.progress:null,Yt=Ae.currentStep||"Analyzing grammar and vocabularyâ¦";M(xt!=null&&xt>0?{...Ue,progress:Math.min(99,xt),indeterminate:!1,message:Yt}:{...Ue,indeterminate:!0,message:Yt})}const mt=Rl-(Date.now()-ge);mt<=cl?$t(Math.max(0,mt),"Processing is taking longer than expected â please reload to check its status, or retry."):st(cl)}catch(rt){if(Je()||Sn(rt))return;console.error("Error polling processing status:",rt),_a(Ql(rt))}finally{be=!1,pr===qe&&(pr=null)}};na()},[P,U,xa,Na,Gt,f,_,$,O,M]),_e=o.useCallback((R,B,X)=>{const ae=X?.maxAttempts??300,ge=X?.skippedForQuotaCount??0,be=X?.failedToQueueCount??0;let Je=0;const nt=st=>{clearInterval(st),Ai()===st&&rr(null)},bt=setInterval(async()=>{try{const st=await $();if(!st){nt(bt);return}const $t=await fetch(`${ue()}/api/video/episodes/${R}/status`,{headers:{Authorization:`Bearer ${st}`}});if(!$t.ok){nt(bt);const na=`Subtitle processing status check failed (HTTP ${$t.status})`;M({status:"error",progress:0,message:"",error:na,materialId:B}),ne("immersion_upload_failed",{category:U,file_type:"subtitle",error_stage:"processing"}),s(na);return}const _a=await $t.json();if(_a.status==="completed"){nt(bt);const na=[];ge>0&&na.push(`${ge} skipped â no credits left`),be>0&&na.push(`${be} failed to queue`),M({status:"completed",progress:100,message:na.length>0?`Subtitle analysis complete (${na.join("; ")}).`:"Subtitle analysis complete!",materialId:B}),ne("immersion_upload_completed",{category:U,file_type:"subtitle",ocr_enabled:xa,nlp_enabled:Na}),P(B);return}if(_a.status==="error"||_a.status==="failed"){nt(bt);const na=_a.error||_a.message||"Subtitle processing failed";M({status:"error",progress:0,message:"",error:na,materialId:B}),ne("immersion_upload_failed",{category:U,file_type:"subtitle",error_stage:"processing"}),s(na);return}Je+=1,Je>=ae&&(nt(bt),M({status:"completed",progress:100,message:"Subtitles are still being analyzed â you can leave this page; theyâll appear in your library shortly.",materialId:B,uploadType:"subtitle"}),ne("immersion_upload_completed",{category:U,file_type:"subtitle",ocr_enabled:xa,nlp_enabled:Na}),P(B))}catch(st){nt(bt);const $t=st instanceof Error?st.message:"Network error during subtitle processing";M({status:"error",progress:0,message:"",error:$t,materialId:B}),ne("immersion_upload_failed",{category:U,file_type:"subtitle",error_stage:"processing"}),s($t)}},2e3);rr(bt)},[$,M,P,s,U,xa,Na]);Os.useEffect(()=>{if(A.status==="processing"&&A.materialId){if(A.uploadType==="subtitle"){if(Ai())return;A.episodeId?(console.log("ð Resuming subtitle status poll for episode:",A.episodeId),_e(A.episodeId,A.materialId)):M({status:"completed",progress:100,message:"Subtitles added â analysis continues in the background.",materialId:A.materialId,uploadType:"subtitle"});return}if(Xi===A.materialId)return;console.log("ð Auto-restarting polling for material:",A.materialId),he(A.materialId)}},[A.status,A.materialId,A.uploadType,A.episodeId,he,_e,M]);const Pt=o.useCallback(async R=>{const{images:B,mokuroJson:X,dimensions:ae,title:ge,originalFilename:be,fileSizeBytes:Je,mangaSeriesId:nt,malId:bt,accessToken:st,signal:$t,onSaveProgress:_a,onTextPhase:na,processingSelection:qe,onMaterialCreated:rt}=R,Xe=()=>{if($t.aborted)throw new DOMException("Upload cancelled","AbortError")},Ae=await Nn(B),Re=await fetch(`${ue()}/api/reading/materials/local-import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${st}`},body:JSON.stringify({title:ge.trim(),totalPages:B.size,mokuroVersion:X?.version,originalFilename:be,fileSizeBytes:Je,contentFingerprint:Ae,forceDuplicate:!1,mangaSeriesId:nt||void 0,...bt?{malId:bt,malType:"manga"}:{},coverImagePath:null}),signal:$t});if(!Re.ok){if(Re.status===409)return B.clear(),{kind:"skipped"};const S=await Re.json().catch(()=>({message:"Failed to create material"}));throw new Error(S.message||"Failed to initialize import")}const Ie=(await Re.json()).materialId;rt?.(Ie);const Ue=B.size,mt=[...B.keys()],xt=Ki(B,ae);B.clear(),await Hi(Ie,xt,{signal:$t,onProgress:(S,z,Z)=>{$t.aborted||_a(S,z,Z)}}),Xe(),await Bi({materialId:Ie,totalPages:Ue,importedAt:new Date().toISOString(),originalFilename:be,contentFingerprint:Ae,fileSizeBytes:Je}),Xe(),na();const Yt=X?X.pages.map((S,z)=>({pageNumber:z+1,width:S.img_width,height:S.img_height,blocks:S.blocks.map(Z=>({box:Z.box,vertical:Z.vertical,font_size:Z.font_size,lines:Z.lines,lines_coords:Z.lines_coords}
89))})):mt.map((S,z)=>{const Z=ae.get(S)||{width:0,height:0};return{pageNumber:z+1,width:Z.width,height:Z.height,blocks:[]}}),Ye=3;let dt=!1;for(let S=0;;S++){Xe();const z=await fetch(`${ue()}/api/reading/materials/${Ie}/text-boxes/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${st}`},body:JSON.stringify({pages:Yt,skipNlp:!qe.enableProcessing}),signal:$t});if(z.ok)break;const Z=await Ls(z);if(Z)throw Z.tier==="free"&&p("storage","quota_exceeded"),new Error(Cn(Z));if(await ws(z)||z.status===429){if(S<Ye){await vj(2e3*2**S,$t);continue}dt=!0;break}const ce=await z.json().catch(()=>({message:"Failed to import text boxes"}));throw new Error(ce.message||"Failed to import text boxes")}return Gt&&Pn({id:Ie,content_type:"manga",file_type:"local_cbz",total_pages:Ue},g),dt?{kind:"deferred",materialId:Ie}:{kind:"imported",materialId:Ie}},[Gt,g,p]),Rt=o.useCallback(async(R,B,X,ae)=>{const{enableOcr:ge,enableProcessing:be}=ae,Je=()=>{if(X.aborted)throw new DOMException("Upload cancelled","AbortError")},nt=R.volumes.length;let bt=Oe;const st=(H.title||R.seriesTitle).trim();if(kt!=="existing"&&st){const rt=await fetch(`${ue()}/api/manga/series`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${B}`},body:JSON.stringify({title:st,coverImagePath:Ke||null}),signal:X});rt.ok&&(bt=(await rt.json()).seriesId)}const $t=[];let _a=null;for(let rt=0;rt<nt;rt++){Je();const Xe=R.volumes[rt],Ae=`Volume ${rt+1} of ${nt}`,Re=Ie=>Math.round((rt+Ie)/nt*100);let at=null;try{M({status:"extracting",progress:Re(0),message:`${Ae} â extracting ${Xe.name}â¦`,uploadType:"local_manga"});const Ie=await Xe.resolve(mt=>{if(X.aborted)return;const xt=mt.total>0?mt.current/mt.total*.3:0;M({status:"extracting",progress:Re(xt),message:`${Ae} â extracting page ${mt.current}/${mt.total}â¦`,uploadType:"local_manga"})});if(Je(),Ie.images.size===0){$t.push({status:"failed",name:Xe.name,error:"No images found"});continue}if(ge&&!Wd(Ie.mokuroJson)){M({status:"ocr_pending",progress:Re(.3),message:`${Ae} â recognizing textâ¦`,uploadType:"local_manga"});const mt=await Nn(Ie.images);Ie.mokuroJson=await ll(Ie.images,xt=>{X.aborted||M({status:"ocr_pending",progress:Re(.3),message:`${Ae} â ${xt.message}`,uploadType:"local_manga"})},X,mt);for(const xt of Ie.mokuroJson.pages){const Yt=xt.img_path.split("/").pop()||xt.img_path;Ie.dimensions.has(Yt)||Ie.dimensions.set(Yt,{width:xt.img_width,height:xt.img_height})}}Je();const Ue=await Pt({images:Ie.images,mokuroJson:Ie.mokuroJson,dimensions:Ie.dimensions,title:Xe.name,originalFilename:Xe.name,fileSizeBytes:Xe.sizeBytes,mangaSeriesId:bt,malId:K?.malId,accessToken:B,signal:X,processingSelection:ae,onSaveProgress:(mt,xt,Yt)=>{const Ye=Yt==="optimizing"?"Optimizing":"Saving",dt=.3+(xt>0?mt/xt*.65:0);M({status:"saving_local",progress:Re(dt),message:`${Ae} â ${Ye.toLowerCase()} page ${mt}/${xt}â¦`,uploadType:"local_manga"})},onTextPhase:()=>{M({status:"uploading_text",progress:Re(.95),message:`${Ae} â uploading text dataâ¦`,uploadType:"local_manga"})},onMaterialCreated:mt=>{at=mt}});Ue.kind==="skipped"?$t.push({status:"skipped",name:Xe.name}):Ue.kind==="deferred"?(_a||(_a=Ue.materialId),$t.push({status:"deferred",name:Xe.name,materialId:Ue.materialId})):(_a||(_a=Ue.materialId),$t.push({status:"imported",name:Xe.name,materialId:Ue.materialId}))}catch(Ie){if(at){const Ue=at;try{await Mn(Ue)}catch{}try{await $()&&await Ps.from("reading_materials").update({processing_status:"error",processing_error:Sn(Ie)?"Upload cancelled":Ie instanceof Error?Ie.message:"Import failed"}).eq("id",Ue)}catch{}}if(Sn(Ie))throw Ie;console.error(`[multi-volume] volume "${Xe.name}" failed:`,Ie),$t.push({status:"failed",name:Xe.name,error:Ie instanceof Error?Ie.message:"Import failed"})}}const na=Sx($t,nt),{message:qe}=na;if(ne("immersion_upload_completed",{category:"manga",file_type:"cbz",ocr_enabled:ge,nlp_enabled:be,cloud_sync_opted:Gt,tier:f,volume_count:nt}),na.status==="error"){ne("immersion_upload_failed",{category:"manga",file_type:"cbz",error_stage:"extraction"}),M({status:"error",progress:0,message:"",error:qe}),s(qe);return}M({status:"completed",progress:100,message:qe,materialId:_a??void 0}),_a&&na.failed===0&&P(_a,{duplicate:!1,message:qe})},[Oe,kt,H.title,Ke,Gt,f,Pt,M,P,s,$,K]),Ia=o.useCallback(async R=>{const B=Nv(R,as.getState()),{enableOcr:X,enableProcessing:ae}=B;if(_.length===0){console.error("â No files to upload");return}if(A.status==="uploading"||A.status==="processing"){console.warn("â ï¸ Upload already in progress, ignoring duplicate request"),console.log("Current status:",A.status);return}console.log("ð Starting upload process..."),console.log("ð Upload stats:",{fileCount:_.length,mokuroCount:_.filter(Ae=>Ae.type==="mokuro").length,imageCount:_.filter(Ae=>Ae.type==="image").length,metadata:H}
89),Tt.current&&Tt.current.abort(),Tt.current=new AbortController;const ge=Tt.current.signal,be=()=>{if(ge.aborted)throw new DOMException("Upload cancelled","AbortError")};if(!u){Pa.current=!0,h("signup");return}const Je=yu(w.current,u.id)?"manga-camera-scan":"legacy-upload",nt=Ja(_);if(!nt.isValid){ne("immersion_upload_failed",{category:U,file_type:_[0]?.type??"unknown",error_stage:"upload"}),M({status:"error",progress:0,message:"",error:nt.error});return}let bt=_;for(const Ae of bt.filter(Re=>(Re.type==="archive"||Re.type==="cbz")&&Re.file.size>0)){let Re=null;try{Re=await wd(Ae.file)}catch(Ie){const Ue=Ie instanceof ro?Ie.message:"Import failed";ne("immersion_upload_failed",{category:U,file_type:"cbz",error_stage:"extraction"}),M({status:"error",progress:0,message:"",error:Ue}),s(Ue);return}if(be(),!Re)continue;let at="image";try{at=await Xo(Re)}catch{at="image"}be(),bt=bt.map(Ie=>Ie.id===Ae.id?{...Ie,type:"pdf",file:Re,pdfKind:at}:Ie),O(bt)}const st=bt.filter(Ae=>Ae.type==="pdf"),$t=U==="manga"&&st.length>=2,_a=$t?void 0:bt.find(Ae=>Ae.type==="pdf"&&Ae.pdfKind===void 0);if(_a&&_a.file.size>0){let Ae="image";try{Ae=await Xo(_a.file)}catch{Ae="image"}be(),bt=bt.map(Re=>Re.id===_a.id?{...Re,pdfKind:Ae}:Re),O(bt)}let na=me;if($t&&(!na||!(Re=>{if(Re.volumes.length!==st.length)return!1;const at=Re.volumes.map(Ue=>{const mt=Ue.key.lastIndexOf("::");return mt===-1?"\0":Ue.key.slice(0,mt)}).sort(),Ie=st.map(Ue=>Ue.file.name).sort();return at.every((Ue,mt)=>Ue===Ie[mt])})(na))){try{na=await Jd(st.map(Re=>Re.file))}catch{na=null}be(),na&&Ge(na)}const qe=Dn(bt),rt=Tr(bt);if(ne("immersion_upload_processing_options_set",{ocr_enabled:X,nlp_enabled:ae,...na?{volume_count:na.volumes.length}:{}}),V.current=null,le.current=!1,na&&U==="manga"&&(rt==="local"||$t)){try{const Ae=await $();if(!Ae)throw new Error("No access token");M({status:"extracting",progress:0,message:`Importing ${na.volumes.length} volumesâ¦`,uploadType:"local_manga"}),await Rt(na,Ae,ge,B)}catch(Ae){if(Sn(Ae))return;console.error("Multi-volume manga import error:",Ae),ne("immersion_upload_failed",{category:"manga",file_type:$t?"pdf":"cbz",error_stage:"extraction"});const Re=Ae instanceof an,at=Fr(Ae,"Import failed");M({status:"error",progress:0,message:"",error:at,...Re?{errorHeading:Ae.heading,errorHint:Ae.hint}:{}}),s(at)}return}if(rt==="local"){M({status:"extracting",progress:0,message:"Extracting archive...",uploadType:"local_manga"});let Re=null,at=!1;try{const Ie=await $();if(!Ie)throw new Error("No access token");const Ue=bt.find(Se=>Se.type==="archive"||Se.type==="cbz"),mt=bt.find(Se=>Se.type==="pdf"),xt=Ue?.file??mt?.file??null,Yt=bt.filter(Se=>Se.type==="image");let Ye,dt,S;const z=Ue?.file??mt?.file??null;if(z){const Se=await bu(z),He=await fetch(`${ue()}/api/reading/materials/check-duplicate`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ie}`},body:JSON.stringify({archiveSha256:Se,originalFilename:z.name,fileSizeBytes:z.size}),signal:ge});if(He.ok){const We=await He.json();if(We.duplicate&&We.existing?.materialId){const Vt=await Ma({materialId:We.existing.materialId,title:We.existing.title,contentType:We.existing.contentType,totalPages:We.existing.totalPages,source:"pre-ocr"});if(be(),!Vt){const wt={status:"completed",progress:100,message:`Already imported "${We.existing.title}" â opening it.`,materialId:We.existing.materialId};M(wt),P(We.existing.materialId,{duplicate:!0,message:`"${We.existing.title}" was already in your library. Showing the existing copy.`});return}at=!0}}}const Z=Se=>{if(ge.aborted)return;const We={status:"extracting",progress:Se.total>0?Math.round(Se.current/Se.total*100):0,message:Se.phase==="reading"?"Reading file...":`Extracting page ${Se.current}/${Se.total}`};M(We)};if(Ue){const Se=await Mm(Ue.file,Z);Ye=Se.images,dt=Se.mokuroJson,S=Se.dimensions}
89else if(mt){const Se=await kc(mt.file,Z);Ye=Se.images,dt=Se.mokuroJson,S=Se.dimensions}else if(Yt.length>0){const Se=new Map(Yt.map(Qt=>[Qt.file.name,Qt.file])),He=await Nn(Se,Je),We=await fetch(`${ue()}/api/reading/materials/check-duplicate`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ie}`},body:JSON.stringify({archiveSha256:He}),signal:ge});if(We.ok){const Qt=await We.json();if(Qt.duplicate&&Qt.existing?.materialId){const ya=await Ma({materialId:Qt.existing.materialId,title:Qt.existing.title,contentType:Qt.existing.contentType,totalPages:Qt.existing.totalPages,source:"pre-ocr"});if(be(),!ya){const _s={status:"completed",progress:100,message:`Already imported "${Qt.existing.title}" â opening it.`,materialId:Qt.existing.materialId};M(_s),P(Qt.existing.materialId,{duplicate:!0,message:`"${Qt.existing.title}" was already in your library. Showing the existing copy.`});return}at=!0}}const Vt=Yt.map(Qt=>Qt.file),wt=bt.filter(Qt=>Qt.type==="mokuro"),ra=wt.length===1?wt[0].file:null,Bt=ra?await Pm(Vt,ra,Z):await No(Vt,Z);Ye=Bt.images,dt=Bt.mokuroJson,S=Bt.dimensions}else throw new Error("No files to process");if(be(),Ye.size===0)throw new Error("No images found in archive");if(X&&!Wd(dt)){M({status:"ocr_pending",progress:0,message:"Checking Mokuro service..."});const He=await Nn(Ye,Je);dt=await ll(Ye,We=>{if(ge.aborted)return;const Vt={status:"ocr_pending",message:We.message,progress:We.phase==="health_check"?10:We.phase==="uploading"?30:We.phase==="processing"?60:100};M(Vt)},ge,He);for(const We of dt.pages){const Vt=We.img_path.split("/").pop()||We.img_path;S.has(Vt)||S.set(Vt,{width:We.img_width,height:We.img_height})}}be(),M({status:"saving_local",progress:0,message:"Saving images locally..."});let ce=Oe;if(kt==="new"&&H.title.trim()){const Se=await fetch(`${ue()}/api/manga/series`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ie}`},body:JSON.stringify({title:H.title.trim(),coverImagePath:Ke||null}),signal:ge});Se.ok&&(ce=(await Se.json()).seriesId)}const Ce=await Nn(Ye,Je),$e=xt?.size||0,et=H.title||Ue?.file.name.replace(/\.(cbz|zip)$/i,"")||"Manga Import",ot=await fetch(`${ue()}/api/reading/materials/local-import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ie}`},body:JSON.stringify({title:et.trim(),totalPages:Ye.size,mokuroVersion:dt?.version,originalFilename:xt?.name||et,fileSizeBytes:$e,contentFingerprint:Ce,forceDuplicate:at,mangaSeriesId:ce||void 0,...K?{malId:K.malId,malType:K.malType}:{},coverImagePath:ce?null:Ke||null}),signal:ge});if(!ot.ok){const Se=await ot.json().catch(()=>({message:"Failed to create material"}));if(ot.status===409&&Se?.existing?.materialId){const He={status:"completed",progress:100,message:`"${Se.existing.title}" was already imported â opening it.`,materialId:Se.existing.materialId};M(He),P(Se.existing.materialId,{duplicate:!0,message:`"${Se.existing.title}" was already in your library. Showing the existing copy (the new upload was a duplicate).`});return}throw new Error(Se.message||"Failed to initialize import")}const we=(await ot.json()).materialId;Re=we;const Ee=Ye.size,De=[...Ye.keys()],Te=Ki(Ye,S);Ye.clear(),await Hi(we,Te,{signal:ge,onProgress:(Se,He,We)=>{if(ge.aborted)return;const Vt=We==="optimizing"?"Optimizing":"Saving";M({status:"saving_local",progress:Math.round(Se/He*100),message:`${Vt} page ${Se}/${He}...`,materialId:we})}}),be(),await Bi({materialId:we,totalPages:Ee,importedAt:new Date().toISOString(),originalFilename:xt?.name||et,contentFingerprint:Ce,fileSizeBytes:$e});{be(),M({status:"uploading_text",progress:0,message:"Uploading text data...",materialId:we});let He;dt?He=dt.pages.map((Vt,wt)=>({pageNumber:wt+1,width:Vt.img_width,height:Vt.img_height,blocks:Vt.blocks.map(ra=>({box:ra.box,vertical:ra.vertical,font_size:ra.font_size,lines:ra.lines,lines_coords:ra.lines_coords}))})):He=De.map((Vt,wt)=>{const ra=S.get(Vt)||{width:0,height:0};return{pageNumber:wt+1,width:ra.width,height:ra.height,blocks:[]}});const We=await fetch(`${ue()}/api/reading/materials/${we}/text-boxes/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ie}`},body:JSON.stringify({pages:He,skipNlp:!ae}),signal:ge});if(!We.ok){const Vt=await Ls(We);if(Vt)throw Vt.tier==="free"&&$a()&&p("storage","quota_exceeded"),new Error(Cn(Vt));const wt=await ws(We);if(wt)throw new an(wt);const ra=await We.json().catch(()=>({message:"Failed to import text boxes"}));throw new Error(ra.message||"Failed to import text boxes")}}
89be(),Gt&&Pn({id:we,content_type:U==="novel"?"novel":"manga",file_type:"local_cbz",total_pages:Ee},g),ae?(M({status:"processing",progress:0,indeterminate:!0,message:"Analyzing grammar and vocabularyâ¦",materialId:we,uploadType:"local_manga"}),he(we)):(await Ps.from("reading_materials").update({processing_status:"completed"}).eq("id",we),M({status:"completed",progress:100,message:"Import complete",materialId:we}),ne("immersion_upload_completed",{category:U,file_type:_[0]?.type??"unknown",ocr_enabled:X,nlp_enabled:ae,cloud_sync_opted:Gt,tier:f}),P(we))}catch(Ie){if(Sn(Ie)){if(Re){try{await Mn(Re)}catch{}try{await $()&&await Ps.from("reading_materials").update({processing_status:"error",processing_error:"Upload cancelled"}).eq("id",Re)}catch{}}return}console.error("Local manga import error:",Ie),ne("immersion_upload_failed",{category:U,file_type:_[0]?.type??"unknown",error_stage:"extraction"});const Ue=Ie instanceof an;if(!Ue&&Re){try{await $()&&await Ps.from("reading_materials").update({processing_status:"error",processing_error:Ie instanceof Error?Ie.message:"Import failed"}).eq("id",Re)}catch(Yt){console.error("Failed to mark material as error:",Yt)}try{await Mn(Re)}catch(Yt){console.error("Failed to clean up local pages:",Yt)}}const mt=Fr(Ie,"Import failed"),xt={status:"error",progress:0,message:"",error:mt,...Ue?{errorHeading:Ie.heading,errorHint:Ie.hint}:{}};M(xt),s(mt)}return}const Xe=bt.find(Ae=>Ae.type==="pdf"&&Ae.pdfKind==="text");if(Xe){M({status:"uploading",progress:0,message:"Analyzing PDF structure...",uploadType:"epub"});try{const Ae=await $();if(!Ae)throw new Error("No access token");let Re=null;if(U==="novel"&&la==="new"&&H.title.trim())try{const Ye=await fetch(`${ue()}/api/manga/series`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ae}`},body:JSON.stringify({title:H.title.trim(),coverImagePath:Ke||null})});Ye.ok&&(Re=(await Ye.json()).seriesId)}catch(Ye){console.warn("Failed to create novel series:",Ye)}M({status:"uploading",progress:10,message:"Extracting chapters from PDF..."});const at=Aa.current,Ie=at&&at.file===Xe.file?await at.promise:await jd(Xe.file);be();const Ue=H.title||await Ny(Xe.file).catch(()=>null)||Xe.file.name.replace(/\.[^/.]+$/,"");M({status:"uploading",progress:40,message:`Importing ${Ie.length} chapters...`});const mt=await fetch(`${ue()}/api/reading/upload/epub/import-chapters`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ae}`},body:JSON.stringify({title:Ue,description:H.description,filename:Xe.file.name,fileSize:Xe.file.size,coverImagePath:Ke||yt||null,mangaSeriesId:Re||void 0,...K?{malId:K.malId,malType:K.malType}:{},chapters:Ie}),signal:ge});if(!mt.ok){const Ye=await Ls(mt);if(Ye)throw Ye.tier==="free"&&$a()&&p("enrichment","quota_exceeded"),new Error(Cn(Ye));const dt=await ws(mt);if(dt)throw new an(dt);const S=await mt.json().catch(()=>({}));throw new Error(S.message||S.error||"Failed to import PDF chapters")}const Yt=(await mt.json()).materialId;M({status:"processing",progress:0,indeterminate:!0,message:"Tokenizing text⦠this may take a few minutes",materialId:Yt,uploadType:"epub"}),he(Yt)}catch(Ae){if(Sn(Ae))return;console.error("â PDF novel upload error:",Ae),ne("immersion_upload_failed",{category:U,file_type:"pdf",error_stage:"upload"});const Re=Ae instanceof an,at=Fr(Ae,"PDF upload failed");M({status:"error",progress:0,message:"",error:at,...Re?{errorHeading:Ae.heading,errorHint:Ae.hint}:{}}),s(at)}return}if(qe==="epub"){const Ae=_.some(dt=>dt.type==="kindle"),Re=Ae?"Kindle":"EPUB",at=dt=>dt.replace(/\.[^/.]+$/,""),Ie=Ae?Um:gy,Ue=Ae?Wm:Rm,mt=Ae?Vm:oo,xt={status:"uploading",progress:0,message:`Analyzing ${Re} structure...`,uploadType:"epub"};M(xt);let Yt=!1,Ye=null;try{const dt=_.find(ie=>ie.type==="epub"||ie.type==="kindle");if(Ae){const ie=await vr(dt.file);if(!ie.ok){const ce=co(ie);ne("kindle_import_refused",{reason:"drm"}),M({status:"error",progress:0,message:"",error:ce,errorHeading:"This file canât be imported",errorNoRetry:!0}),s(ce);return}}const S=await $();if(!S)throw new Error("No access token");{const ie=await bu(dt.file),ce=await fetch(`${ue()}/api/reading/materials/check-duplicate`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify({archiveSha256:ie,originalFilename:dt.file.name,fileSizeBytes:dt.file.size}),signal:ge});if(ce.ok){const Ce=await ce.json();
89if(Ce.duplicate&&Ce.existing?.materialId){const $e=await Ma({materialId:Ce.existing.materialId,title:Ce.existing.title,contentType:Ce.existing.contentType,totalPages:Ce.existing.totalPages,source:"pre-ocr"});if(be(),!$e){const et={status:"completed",progress:100,message:`Already imported "${Ce.existing.title}" â opening it.`,materialId:Ce.existing.materialId};M(et),P(Ce.existing.materialId,{duplicate:!0,message:`"${Ce.existing.title}" was already in your library. Showing the existing copy.`});return}Yt=!0}}}let z=null;if(U==="novel"&&la==="new"&&H.title.trim())try{const ie=await fetch(`${ue()}/api/manga/series`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify({title:H.title.trim(),coverImagePath:Ke||null})});ie.ok&&(z=(await ie.json()).seriesId)}catch(ie){console.warn("Failed to create novel series:",ie)}const Z=await Ie(dt.file);if(console.log(`ð ${Re} detected as: ${Z}`),Z==="image"){const ie={status:"extracting",progress:0,message:`Extracting pages from ${Re}...`};M(ie);const{images:ce,dimensions:Ce}=await Ue(dt.file,Bt=>{if(ge.aborted)return;const ya={status:"extracting",progress:Bt.total>0?Math.round(Bt.current/Bt.total*100):0,message:`Extracting page ${Bt.current}/${Bt.total}`};M(ya)});if(be(),ce.size===0)throw new Error(`No images found in ${Re}`);let $e=null;if(X){M({status:"ocr_pending",progress:0,message:"Checking Mokuro service..."});const Qt=await Nn(ce);$e=await ll(ce,ya=>{if(ge.aborted)return;const _s={status:"ocr_pending",message:ya.message,progress:ya.phase==="health_check"?10:ya.phase==="uploading"?30:ya.phase==="processing"?60:100};M(_s)},ge,Qt);for(const ya of $e.pages){const _s=ya.img_path.split("/").pop()||ya.img_path;Ce.has(_s)||Ce.set(_s,{width:ya.img_width,height:ya.img_height})}}be(),M({status:"saving_local",progress:0,message:"Saving images locally..."});const ot=H.title||at(dt.file.name),ht=[...ce.entries()],we=await Nn(ce),Ee=dt.file.size,De=await fetch(`${ue()}/api/reading/materials/local-import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify({title:ot,description:H.description,totalPages:ht.length,coverImagePath:Ke||yt||null,contentType:U==="novel"?"novel":"manga",mangaSeriesId:z||void 0,...K?{malId:K.malId,malType:K.malType}:{},contentFingerprint:we,forceDuplicate:Yt,fileSizeBytes:Ee}),signal:Tt.current?.signal});if(!De.ok){const Bt=await De.json().catch(()=>({message:"Failed to create material"}));if(De.status===409&&Bt?.existing?.materialId){const Qt={status:"completed",progress:100,message:`"${Bt.existing.title}" was already imported â opening it.`,materialId:Bt.existing.materialId};M(Qt),P(Bt.existing.materialId,{duplicate:!0,message:`"${Bt.existing.title}" was already in your library. Showing the existing copy (the new upload was a duplicate).`});return}throw new Error(Bt.message||"Failed to create material")}const{materialId:Te}=await De.json();Ye=Te;const Se=ce.size,He=[...ce.keys()],We=Ki(ce,Ce);ce.clear(),ht.length=0,await Hi(Te,We,{signal:ge,onProgress:(Bt,Qt,ya)=>{if(ge.aborted)return;const _s=ya==="optimizing"?"Optimizing":"Saving";M({status:"saving_local",progress:Math.round(Bt/Qt*100),message:`${_s} page ${Bt}/${Qt}...`})}}),be(),await Bi({materialId:Te,totalPages:Se,importedAt:new Date().toISOString(),originalFilename:dt.file.name,contentFingerprint:we,fileSizeBytes:Ee}),be(),M({status:"uploading_text",progress:0,message:"Uploading text data...",materialId:Te});let wt;$e?wt=$e.pages.map((Bt,Qt)=>({pageNumber:Qt+1,width:Bt.img_width,height:Bt.img_height,blocks:Bt.blocks.map(ya=>({box:ya.box,vertical:ya.vertical,font_size:ya.font_size,lines:ya.lines,lines_coords:ya.lines_coords}))})):wt=He.map((Bt,Qt)=>{const ya=Ce.get(Bt)||{width:0,height:0};return{pageNumber:Qt+1,width:ya.width,height:ya.height,blocks:[]}});const ra=await fetch(`${ue()}/api/reading/materials/${Te}/text-boxes/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify({pages:wt,skipNlp:!ae}),signal:ge});if(!ra.ok){const Bt=await Ls(ra);if(Bt)throw Bt.tier==="free"&&$a()&&p("storage","quota_exceeded"),new Error(Cn(Bt));const Qt=await ws(ra);if(Qt)throw new an(Qt);const ya=await ra.json().catch(()=>({message:"Failed to import text boxes"}));throw new Error(ya.message||"Failed to import text boxes")}be(),Gt&&Pn({id:Te,content_type:"manga",file_type:"local_cbz",total_pages:Se},g),ae?(M({status:"processing",progress:0,indeterminate:!0,message:"Analyzing grammar and vocabularyâ¦",materialId:Te,uploadType:"epub"}),he(Te)):(await Ps.from("reading_materials").update({processing_status:"completed"}).eq("id",Te),M({status:"completed",progress:100,message:"Import complete",materialId:Te}),ne("immersion_upload_completed",{category:U,file_type:_[0]?.type??"unknown",source_format:Ae?"kindle":"epub",ocr_enabled:X,nlp_enabled:ae,cloud_sync_opted:Gt,tier:f}),P(Te))}else if(ae){console.log(`ð Extracting ${Re} chapters client-side...`);const ie={status:"uploading",progress:10,message:`Extracting chapters from ${Re}...`};M(ie);const ce=Aa.current,Ce=ce&&ce.file===dt.file?await ce.promise:await mt(dt.file);console.log(`â
Extracted ${Ce.length} chapters`);const $e={status:"uploading",progress:40,message:`Importing ${Ce.length} chapters...`};M($e);const et=await fetch(`${ue()}
89/api/reading/upload/epub/import-chapters`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify({title:H.title||at(dt.file.name),description:H.description,filename:dt.file.name,fileSize:dt.file.size,coverImagePath:Ke||yt||null,mangaSeriesId:z||void 0,...K?{malId:K.malId,malType:K.malType}:{},chapters:Ce}),signal:Tt.current?.signal});if(!et.ok){const Ee=await Ls(et);if(Ee)throw Ee.tier==="free"&&$a()&&p("enrichment","quota_exceeded"),new Error(Cn(Ee));const De=await ws(et);if(De)throw new an(De);const Te=await et.json().catch(()=>({}));throw new Error(Te.message||Te.error||`Failed to import ${Re} chapters`)}const ot=await et.json(),ht=ot.materialId;console.log("â
EPUB chapters imported:",ot),M({status:"processing",progress:0,indeterminate:!0,message:"Tokenizing text⦠this may take a few minutes",materialId:ht,uploadType:"epub"}),he(ht)}else{console.log(`ð Registering local ${Re}...`);const ie=await Ym(dt.file),ce=await fetch(`${ue()}/api/reading/upload/epub/register-local`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify({title:H.title||at(dt.file.name),description:H.description,filename:dt.file.name,fileSize:dt.file.size,coverImagePath:Ke||yt||null,mangaSeriesId:z||void 0,...K?{malId:K.malId,malType:K.malType}:{},contentFingerprint:ie}),signal:Tt.current?.signal});if(!ce.ok){const ht=await Ls(ce);if(ht)throw ht.tier==="free"&&$a()&&p("enrichment","quota_exceeded"),new Error(Cn(ht));const we=await ce.json().catch(()=>({}));if(ce.status===409&&we?.existing?.materialId){const Ee={status:"completed",progress:100,message:`"${we.existing.title}" was already imported â opening it.`,materialId:we.existing.materialId};M(Ee),P(we.existing.materialId,{duplicate:!0,message:`"${we.existing.title}" was already in your library. Showing the existing copy (the new upload was a duplicate).`});return}throw new Error(we.message||we.error||`Failed to register ${Re}`)}const $e=(await ce.json()).materialId,et={status:"uploading",progress:50,message:`Saving ${Re} to local storage...`,materialId:$e};M(et),await bc($e,dt.file,Ae?"kindle":"epub"),Jm(),console.log(`â
${Re} stored in IndexedDB`),Gt&&Pn({id:$e,content_type:"novel",file_type:"epub",total_pages:1},g),M({status:"completed",progress:100,message:"Import complete (stored locally)",materialId:$e}),ne("immersion_upload_completed",{category:U,file_type:_[0]?.type??"unknown",source_format:Ae?"kindle":"epub",ocr_enabled:X,nlp_enabled:ae,cloud_sync_opted:Gt,tier:f}),P($e)}}catch(dt){if(Sn(dt)){if(Ye)try{await Mn(Ye)}catch{}return}if(console.error(`â ${Re} upload error:`,dt),ne("immersion_upload_failed",{category:U,file_type:_[0]?.type??"unknown",error_stage:"upload"}),Ye)try{await Mn(Ye)}catch(ie){console.error("Failed to clean up local pages:",ie)}const S=dt instanceof an,z=Fr(dt,`${Re} upload failed`),Z={status:"error",progress:0,message:"",error:z,...S?{errorHeading:dt.heading,errorHint:dt.hint}:{}};M(Z),s(z)}}else if(qe==="subtitle"){oe.current=!1;const Ae=_.some(at=>(at.type==="subtitle"||at.type==="video")&&Y.current.get(at.id)?.file!=null);if(Gt&&g&&Ae){const at=_.map(Ue=>Ue.type==="subtitle"||Ue.type==="video"?Y.current.get(Ue.id):void 0).find(Ue=>Ue?.file!=null),Ie=await Lt(at?.videoFilename??"your video");if(oe.current=Ie,!Ie&&_.some(Ue=>Ue.type==="video"))throw new Error("Cloud storage confirmation is required to generate subtitles from a video.")}M({status:"uploading",progress:0,message:"Processing subtitle files...",uploadType:"subtitle"});try{const at=await $();if(!at)throw new Error("No access token");const Ie=_.filter(we=>we.type==="subtitle"),Ue=_.filter(we=>we.type==="video"),mt=Ie[0]??Ue[0],xt=H.title||mt.file.name.replace(/\.[^.]+$/i,""),Yt=[],Ye=1048576;for(let we=0;we<Ie.length;we++){const Ee=Ie[we],De=await Ee.file.text();if(De.length>Ye){const We=(De.length/1048576).toFixed(2);throw new Error(`Subtitle file too large (max 1 MB). File: ${Ee.file.name} is ${We} MB.`)}const Te=Ee.file.name.toLowerCase().endsWith(".srt")?"srt":"ass",Se=Pl(Ee.file),He=Y.current.get(Ee.id);Yt.push({label:Se.label||Ee.file.name.replace(/\.[^.]+$/,""),indexInParent:we,seasonNumber:Se.seasonNumber??Le,episodeNumber:Se.episodeNumber??(Ie.length===1?1:we+1),primarySubContent:De,primarySubFormat:Te,videoFilename:He?.videoFilename,__uploadFileId:Ee.id})}for(let we=0;we<Ue.length;we++){const Ee=Ue[we],De=Pl(Ee.file),Te=Y.current.get(Ee.id);Yt.push({label:De.label||Ee.file.name.replace(/\.[^.]+$/,""),indexInParent:Ie.length+we,seasonNumber:De.seasonNumber??Le,episodeNumber:De.episodeNumber??(Ue.length===1?1:we+1),videoFilename:Te?.videoFilename??Ee.file.name,__uploadFileId:Ee.id})}Yt.sort((we,Ee)=>we.seasonNumber!==Ee.seasonNumber?we.seasonNumber-Ee.seasonNumber:(we.episodeNumber??0)-(Ee.episodeNumber??0)),Yt.forEach((we,Ee)=>{we.indexInParent=Ee});const dt=new Map;for(const we of Yt)dt.set(we.indexInParent,we.__uploadFileId);const S=Yt.map(we=>({label:we.label,indexInParent:we.indexInParent,seasonNumber:we.seasonNumber,episodeNumber:we.episodeNumber,...we.primarySubContent?{primarySubContent:we.primarySubContent}:{},...we.primarySubFormat?{primarySubFormat:we.primarySubFormat}:{},...we.videoFilename?{videoFilename:we.videoFilename}:{}}));let z,Z;U==="series"||U==="movie"?aa?(z=`${ue()}/api/video/shows/${aa}/sessions`,Z={seasonNumber:Le,seasonLabel:Ft||`Season ${Le}`,episodes:S,skipNlp:!ae}):(z=`${ue()}/api/video/shows`,Z={title:xt,showType:U==="movie"?"movie":"series",coverImagePath:yt||null,...K?{malId:K.malId}:{},seasonNumber:U==="movie"?0:Le,seasonLabel:U==="movie"?"Movie":Ft||`Season ${Le}`,episodes:S,skipNlp:!ae}):(z=`${ue()}/api/video/sessions`,Z={title:xt,titleJp:null,episodes:S,skipNlp:!ae});const ie=await fetch(z,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${at}`},body:JSON.stringify(Z),signal:Tt.current?.signal});if(!ie.ok){const we=await Ls(ie);if(we)throw we.tier==="free"&&$a()&&p("storage","quota_exceeded"),new Error(Cn(we));const Ee=await ws(ie);if(Ee)throw new an(Ee);const De=await ie.json().catch(()=>({}));if(ie.status===402)throw $a()&&p("enrichment","quota_exceeded"),new Error(De.error||"Not enough shared credits to start analysis");const Te=De;throw new Error(Te.message||Te.error||"Failed to create video session")}const ce=await ie.json(),Ce=ce.showId||ce.sessionId||ce.id;
89if(Array.isArray(ce.episodes))for(const we of ce.episodes){if(!we.id||we.indexInParent==null)continue;const Ee=dt.get(we.indexInParent);if(!Ee)continue;const De=Y.current.get(Ee);De?.file&&ui(we.id,De.file),dn&&De?.handle&&po(we.id,De.handle).catch(()=>{})}let $e=0;if(Gt&&g&&oe.current&&Array.isArray(ce.episodes)){const we=[],Ee=[];for(const De of ce.episodes){if(!De.id||De.indexInParent==null)continue;const Te=dt.get(De.indexInParent);if(!Te)continue;const Se=Y.current.get(Te);if(!Se)continue;if(!Se.file){$e+=1;continue}const He=De.label||Se.videoFilename;we.push({episodeId:De.id,file:Se.file,label:He}),Ee.push({episodeId:De.id,label:He})}we.length>0&&(Jn.configure($),Jn.enqueueSeason(we),Ta(Ee))}const et=_.reduce((we,Ee)=>we+((Ee.type==="subtitle"||Ee.type==="video")&&Y.current.get(Ee.id)?.file!=null?1:0),0),ot={category:U,file_type:"subtitle",ocr_enabled:X,nlp_enabled:ae,cloud_sync_opted:Gt&&g&&oe.current&&et>0,episode_count:Yt.length,video_files_count:et,cloud_sync_misses:$e,tier:f},ht=$e>0?` ${$e} episode${$e===1?"":"s"} will need manual sync from the show page.`:"";if(Ue.length>0&&Ie.length===0){const we={status:"completed",progress:100,message:`Video added to Cloud Library. Generate subtitles from the episode row when sync completes.${ht}`,materialId:Ce};M(we),ne("immersion_upload_completed",ot),P(Ce)}else if(ae){const we=new Set((ce.skippedForQuota||[]).map(wt=>wt.id)),Ee=new Set((ce.failedToQueue||[]).map(wt=>wt.id)),De=ce.episodesSkippedForQuota||0,Te=ce.episodesFailedToQueue||0,Se=ce.episodes||[],He=Se.filter(wt=>!we.has(wt.id)&&!Ee.has(wt.id));if(He.length===0){const wt=[];De>0&&wt.push(`${De} episode${De===1?"":"s"} skipped â shared credits ran out`),Te>0&&wt.push(`${Te} episode${Te===1?"":"s"} failed to queue`),De>0&&De>=Se.length&&$a()&&p("enrichment","quota_exceeded");const ra={status:"completed",progress:100,message:(wt.length>0?`Added to your library. ${wt.join("; ")}.`:"Added to your library.")+ht,materialId:Ce};M(ra),ne("immersion_upload_completed",ot),P(Ce);return}const We=He[0]?.id;if(M({status:"processing",progress:0,indeterminate:!0,message:"Analyzing subtitlesâ¦",materialId:Ce,episodeId:We,uploadType:"subtitle"}),We){const wt=Math.min(450,120+He.length*20);_e(We,Ce,{maxAttempts:wt,skippedForQuotaCount:De,failedToQueueCount:Te})}else{const wt={status:"completed",progress:100,message:`Added to your library.${ht}`,materialId:Ce};M(wt),ne("immersion_upload_completed",ot),P(Ce)}}else{const we={status:"completed",progress:100,message:`Added to your library (no analysis).${ht}`,materialId:Ce};M(we),ne("immersion_upload_completed",ot),P(Ce)}}catch(at){if(Sn(at))return;console.error("Subtitle upload error:",at),ne("immersion_upload_failed",{category:U,file_type:_[0]?.type??"unknown",error_stage:"upload"});const Ie=at instanceof an,Ue=Fr(at,"Subtitle upload failed"),mt={status:"error",progress:0,message:"",error:Ue,...Ie?{errorHeading:at.heading,errorHint:at.hint}:{}};M(mt),s(Ue)}}},[P,s,$,Ja,_,O,H,u,he,_e,U,yt,aa,Le,Ft,kt,Oe,Ke,la,h,A.status,g,p,Gt,me,Rt,Lt,K]);o.useEffect(()=>{u&&Pa.current&&(Pa.current=!1,Ia())},[u,Ia]);const ts=o.useCallback(()=>{w.current=null,T(!1),Tt.current&&(Tt.current.abort(),Tt.current=null),tt&&(tt.resolve(!1),Mt(null)),de(),v(),Wt(null),ca(null),za(null),Ea(null),Ca(new Map),Aa.current=null,Ba(!0),Wa(null),Ta([]),_t(null),va&&(va.resolve(!1),ia(null)),oe.current=!1,xe.current++,Ge(null),I(!1),Ne.current=null,Ze.current++,G([]),pe(!1),Fe([]),ke.current=[],Qe.current.clear(),Y.current.clear(),n?(ve("manga"),Ve("existing"),pt(n),r&&D(R=>({...R,title:r}))):i?(ve("series"),vt(i),l&&D(R=>({...R,title:l}))):(ve(null),lt(null),vt(null),jt(1),ct(""),Ve(null),pt(null),zt(null),Dt(null),da(null)),Vr()},[n,r,i,l,tt,va,de,v,D,lt,zt]),Ra=o.useCallback(()=>{if(["uploading","processing","extracting","ocr_pending","saving_local","uploading_text"].includes(A.status)){W(!0);return}ts()},[A.status,ts]),Ua=o.useCallback(()=>{console.log("â ï¸ Upload cancelled by user"),W(!1),ts()},[ts]),La=o.useCallback(()=>{W(!1)},[]),fs=o.useCallback(async()=>{const R=A.materialId;if(!R)return;const B=A.uploadType==="subtitle";try{const X=await $();if(!X){P(R);return}const ae=B?`${ue()}/api/video/shows/${R}/process-remaining`:`${ue()}/api/reading/materials/${R}/process-remaining`,ge=await fetch(ae,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${X}`},body:JSON.stringify({})});if(ge.status===402){$a()?p("enrichment","quota_exceeded"):P(R),v();return}if(!ge.ok){P(R);return}if(B){P(R);return}M({status:"processing",progress:0,indeterminate:!0,message:"Analyzing the restâ¦",materialId:R,uploadType:A.uploadType}),he(R)}catch{P(R)}},[A.materialId,A.uploadType,$,P,p,v,M,he]);o.useEffect(()=>{if(U!=="series")return;let R=!1;return(async()=>{try{const B=await $();if(!B||R)return;const X=await fetch(`${ue()}/api/video/shows`,{headers:{Authorization:`Bearer ${B}`}});if(X.ok&&!R){const ae=await X.json();Ct((ae.shows||[]).map(ge=>({id:ge.id,title:ge.title})))}}catch{}})(),()=>{R=!0}},[U,$]),o.useEffect(()=>{if(U!=="manga")return;let R=!1;return(async()=>{try{const B=await $();if(!B||R)return;const X=await fetch(`${ue()}/api/manga/series`,{headers:{Authorization:`Bearer ${B}`}});if(X.ok&&!R){const ae=await X.json();ft((ae.series||[]).map(ge=>({id:ge.id,title:ge.title})))}}catch{}})(),()=>{R=!0}},[U,$]),o.useEffect(()=>{const R=A.status==="extracting"||A.status==="ocr_pending"||A.status==="saving_local"||A.status==="uploading_text"||A.status==="uploading",B=_.length>0&&(A.status==="idle"||A.status==="ready_to_confirm");if(!R&&!B)return;const X=ae=>(ae.preventDefault(),ae.returnValue="","");return window.addEventListener("beforeunload",X),()=>window.removeEventListener("beforeunload",X)},[_.length,A.status]);const ls=o.useRef(null);ls.current=tt,o.useEffect(()=>()=>{ls.current&&(ls.current.resolve(!1),ls.current=null),Tt.current&&(Tt.current.abort(),Tt.current=null),gj(w,()=>{as.getState().setUploadFiles([])})},[]);const Zt=tt?"duplicate-confirm":A.status==="completed"?"complete":A.status==="error"?"error":A.status==="extracting"||A.status==="ocr_pending"||A.status==="saving_local"||A.status==="uploading_text"||A.status==="uploading"||A.status==="processing"?"progress":re||E.length>0?"mkv-extract":U===null?"category":U==="series"?"series-episodes":U==="movie"?ba===null?"movie-mode":"series-episodes":U==="manga"&&j&&u?"scan":U==="manga"&&kt===null?"manga-mode":U==="novel"&&la===null?"novel-mode":U==="manga"&&j?"scan":_.length>0?"confirm":"dropzone";o.useEffect(()=>{const R=++xe.current;if(U!=="manga"){Ea(null),Ge(null),I(!1);return}const B=_.filter(ge=>ge.type==="mokuro").length,X=_.find(ge=>ge.type==="archive"||ge.type==="cbz");if(X&&X.file.size>0){Ea(null);let ge=!1;return I(!0),uy(X.file).then(async be=>{const Je=be.entries.filter(st=>!/\.mokuro$/i.test(st.name)).length,nt=be.entries.some(st=>/\.mokuro$/i.test(st.name));return{plan:await _x(be),imageCount:Je,hasMokuro:nt}}).then(({plan:be,imageCount:Je,hasMokuro:nt})=>{ge||R!==xe.current||(Je>0&&za(Je),Ea(nt),Ge(be),I(!1))}).catch(()=>{ge||R!==xe.current||(Ea(!1),Ge(null),I(!1))}),()=>{ge=!0}}Ea(null);const ae=_.filter(ge=>ge.type==="pdf");if(ae.length>=2){let ge=!1;return I(!0),Jd(ae.map(be=>be.file)).then(be=>{ge||R!==xe.current||(Ge(be),I(!1))}).catch(()=>{ge||R!==xe.current||(Ge(null),I(!1))}),()=>{ge=!0}}if(I(!1),B>=2){let ge=!1;return jx(_.map(be=>be.file)).then(be=>{ge||R!==xe.current||Ge(be)}
89).catch(()=>{ge||R!==xe.current||Ge(null)}),()=>{ge=!0}}Ge(null)},[_,U]),o.useEffect(()=>{if(!me){Ne.current=null;return}const R=me.seriesTitle||me.volumes.map(B=>B.key).join("|");Ne.current!==R&&(Ne.current=R,me.seriesTitle&&D(B=>({...B,title:me.seriesTitle})),Ve(B=>B==="existing"?B:"new"))},[me,D]);const zs=o.useMemo(()=>{const R=_.filter(B=>B.type==="pdf");return _.some(B=>B.type==="epub"||B.type==="kindle")||R.length===1&&R[0].pdfKind==="text"?"epub":"manga"},[_]),ks=o.useMemo(()=>{if(_.length===0)return{bytes:null,approximate:zs==="manga"};if(zs==="epub"){const ae=_.find(ge=>ge.type==="epub"||ge.type==="kindle");return{bytes:ae?ae.file.size:null,approximate:!0,itemCount:1}}if(me){const ae=me.totalPages*250*1024;return{bytes:me.totalBytes>0?Math.min(me.totalBytes,ae):ae,approximate:!0,itemCount:me.totalPages}}const R=_.reduce((ae,ge)=>ae+ge.file.size,0),B=ha&&ha>0?ha:_.filter(ae=>ae.type==="image").length||_.length,X=B*250*1024;return{bytes:Math.min(R,X),approximate:!0,itemCount:B}},[_,zs,ha,me]),Fs=o.useMemo(()=>{let R=0,B=0;for(const X of _){if(X.type!=="subtitle"&&X.type!=="video")continue;const ae=Y.current.get(X.id);ae?.file&&(R+=ae.file.size,B+=1)}return B===0?{bytes:null,approximate:!1}:{bytes:R,approximate:!1,itemCount:B}},[_]),Mr=o.useMemo(()=>{const R={};for(const B of _){if(B.type!=="subtitle")continue;const X=Y.current.get(B.id);X?.file&&(R[B.id]=X.file.size)}return R},[_]);o.useEffect(()=>{if(Zt!=="confirm"&&Zt!=="series-episodes"||!g)return;let R=!1;return Wa(null),ap({getAccessToken:$}).then(B=>{R||(B.ok?Wa({usedBytes:B.usage.bytes_used,limitBytes:B.usage.limit_bytes,tier:B.usage.tier}):Wa("unavailable"))}),()=>{R=!0}},[Zt,g,$]);const Bn=Zt==="category",ki=!Q&&(Zt==="category"||Zt==="manga-mode"||Zt==="novel-mode"||Zt==="movie-mode"||Zt==="dropzone"||Zt==="series-episodes"||Zt==="scan")&&(!Bn||!!c),qn=()=>{switch(yj(Zt,w.current)&&(Dl(w),O([]),M({status:"idle",progress:0,message:""})),Zt){case"manga-mode":case"novel-mode":ve(null),zt(null);break;case"movie-mode":ve(null),lt(null);break;case"dropzone":U==="novel"?Dt(null):Ve(null);break;case"scan":T(!1);break;case"series-episodes":ke.current=[],Qe.current.clear(),Fe([]),U==="movie"?(da(null),O([])):(ve(null),lt(null),vt(null),O([]));break}};return o.useEffect(()=>{Zt==="confirm"&&A.status==="idle"&&Ja(_).isValid&&M(R=>({...R,status:"ready_to_confirm"}))},[Zt,A.status,_,Ja]),e.jsxs(e.Fragment,{children:[e.jsxs(_v,{stepKey:Q?"cancel-confirm":Zt,header:ki?e.jsx(Zh,{onClick:Bn?()=>c?.():qn,label:Bn?"Back to library":"Back to previous step"}):void 0,children:[Q?e.jsxs(ze.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},exit:{opacity:0,y:-16},transition:{duration:.45,ease:[.22,1,.36,1]},className:"im-uploader-complete",role:"alertdialog","aria-labelledby":"upload-cancel-confirm-heading","aria-describedby":"upload-cancel-confirm-body",children:[e.jsx("span",{className:"im-uploader-complete-glyph","aria-hidden":"true",children:e.jsx(ni,{})}),e.jsx("h3",{id:"upload-cancel-confirm-heading",children:"Cancel this upload?"}),e.jsx("p",{id:"upload-cancel-confirm-body",children:"The upload is still in progress. If you cancel now, any progress will be lost and you'll need to start over."}),e.jsxs("div",{className:"im-uploader-complete-actions",children:[e.jsx("button",{type:"button",onClick:Ua,className:"wc-cta-square wc-cta-square--maple",children:"Yes, cancel"}),e.jsx("button",{type:"button",onClick:La,className:"wc-cta-square im-uploader-quiet-cta",autoFocus:!0,children:"Keep uploading"})]})]},"upload-cancel-confirm"):null,!Q&&Zt==="category"&&e.jsx(Dv,{onSelect:R=>{ve(R),R!=="manga"&&T(!1)}}),!Q&&Zt==="manga-mode"&&e.jsx(Hv,{title:H.title,onTitleChange:R=>D(B=>({...B,title:R})),coverUrl:Jt,onCoverChange:zt,existingSeries:se,selectedSeriesId:Oe,onSelectedSeriesIdChange:pt,onCreate:()=>Ve("new"),onAttach:()=>Ve("existing"),onStandalone:()=>Ve("standalone")}),!Q&&Zt==="novel-mode"&&e.jsx(Wv,{title:H.title,onTitleChange:R=>D(B=>({...B,title:R})),coverUrl:Jt,onCoverChange:zt,onCreate:()=>Dt("new"),onStandalone:()=>Dt("standalone")}),!Q&&Zt==="movie-mode"&&e.jsx(Gv,{title:H.title,onTitleChange:R=>D(B=>({...B,title:R})),coverUrl:St,onCoverChange:lt,onCreate:()=>da("new"),onStandalone:()=>da("standalone")}),!Q&&Zt==="dropzone"&&U&&e.jsx(Yv,{category:U,isDragging:fe,onDragOver:Zn,onDragLeave:Ln,onDrop:er,onSelectFiles:()=>it.current?.click(),onSelectFolder:U==="manga"?()=>fa.current?.click():void 0,onSelectImages:U==="manga"?()=>Xt.current?.click():void 0,onScanPhysicalManga:U==="manga"?()=>{if(!u){h("signin");return}T(!0)}:void 0}),!Q&&Zt==="scan"&&e.jsx(o.Suspense,{fallback:e.jsxs("div",{className:"im-scan-loading",role:"status","aria-live":"polite",children:[e.jsx("span",{className:"wc-enso-loader","aria-hidden":"true"}),e.jsx("p",{children:"Opening the manga scannerâ¦"})]}),children:u?e.jsx(wj,{ownerUserId:u.id,onBack:qn,onFinish:({draftId:R,revision:B,files:X})=>{w.current={draftId:R,revision:B,ownerUserId:u.id},O(fj(X)),T(!1),ne("manga_scan_handoff",{page_count_bucket:X.length<=10?"1-10":X.length<=50?"11-50":X.length<=100?"51-100":"101-250"})}}):e.jsx("div",{className:"im-uploader-panel",role:"status",children:"Sign in to start scanning physical manga."})}),!Q&&Zt==="series-episodes"&&e.jsx(dj,{category:U,title:H.title,onTitleChange:R=>D(B=>({...B,title:R})),coverUrl:St,onCoverChange:lt,existingShows:Et,selectedShowId:aa,onSelectedShowIdChange:vt,seasonNumber:Le,onSeasonNumberChange:jt,seasonLabel:Ft,onSeasonLabelChange:ct,uploadFiles:_,videoPairingBytes:Mr,unpairedVideoNames:te,isDragging:fe,onDragOver:Zn,onDragLeave:Ln,onDrop:Vs,onSelectSubtitles:()=>ga.current?.click(),onSelectFolder:U==="series"?()=>fa.current?.click():void 0,onRemoveFile:On,enableProcessing:Na,onEnableProcessingChange:Da,isPro:g,sharedCreditAvailable:N,walletPending:!!u&&y,cloudSyncEnabled:Gt,onCloudSyncEnabledChange:Ba,cloudSyncEstimate:Fs,cloudSyncUsage:ka,onUpgrade:()=>p("enrichment","upload_warning"),malMatch:K,onMalSelect:qt,onMalClear:sa,onUpload:()=>Ia()}),!Q&&Zt==="confirm"&&e.jsx(cj,{authed:!!u,metadata:H,onTitleChange:R=>D(B=>({...B,title:R})),onDescriptionChange:R=>D(B=>({...B,description:R})),category:U,files:_,coverUrl:Jt,onCoverChange:zt,enableOcr:xa,onEnableOcrChange:ma,enableProcessing:Na,onEnableProcessingChange:Da,estimatedOcrUnits:is,estimatedEnrichmentUnits:Ot,planningPending:C,sharedCreditAvailable:N,walletPending:!!u&&y,walletResetAt:b?.resetAt??null,isPro:g,cloudSyncKind:zs,cloudSyncEnabled:Gt,onCloudSyncEnabledChange:Ba,cloudSyncEstimate:ks,cloudSyncUsage:ka,volumeList:me?{volumes:me.volumes.map(R=>({key:R.key,name:R.name,volumeNumber:R.volumeNumber,pageCount:R.pageCount})),notices:me.notices}:null,volumesDetecting:gt&&!me,malMatch:K,onMalSelect:qt,onMalClear:sa,onUpgrade:()=>p("enrichment","upload_warning"),onConfirm:R=>Ia(R),onCancel:()=>Ra()}),!Q&&Zt==="progress"&&e.jsx(pu,{uploadState:A,onCancel:()=>Ra()}),!Q&&Zt==="mkv-extract"&&(re?e.jsx(pu,{uploadState:{status:"extracting",progress:0,message:"Reading subtitle tracksâ¦"},onCancel:()=>hn()}):e.jsx(mj,{staged:E,onExtracted:tr,onCancel:()=>hn()})),!Q&&Zt==="duplicate-confirm"&&tt&&e.jsx(Rv,{info:tt.info,onOpenExisting:It,onUploadAnyway:Nt}),!Q&&Zt==="complete"&&e.jsx(Iv,{message:A.message||void 0,onOpen:A.materialId?()=>P(A.materialId):void 0,onAnother:()=>Ra(),coverage:A.totalUnits!=null?{analyzed:A.analyzedUnits??0,total:A.totalUnits}:null,coverageUnit:A.coverageUnit,partialWithoutCounts:le.current,onFinishProcessing:A.materialId?()=>{fs()}:void 0,seasonSyncRows:es}),!Q&&Zt==="error"&&e.jsx(Sv,{heading:A.errorHeading,message:A.error||"Something went wrong while uploading.",hint:A.errorHint,hideRetry:A.errorNoRetry,onRetry:()=>M({status:"idle",progress:0,message:""}),onDismiss:()=>Ra()})]}),e.jsx("input",{ref:it,type:"file",multiple:!0,accept:".mokuro,.mbz,.zip,.cbz,.pdf,.epub,.mobi,.azw,.azw3,.prc,.srt,.ass,.ssa,.jpg,.jpeg,.png,.webp",onChange:tn,className:"hidden"}
89),e.jsx("input",{ref:fa,type:"file",webkitdirectory:"",multiple:!0,onChange:U==="series"||U==="movie"?Ms:jn,className:"hidden"}),e.jsx("input",{ref:Xt,type:"file",accept:"image/jpeg,image/png,image/webp,.jpg,.jpeg,.png,.webp",multiple:!0,onChange:tn,className:"hidden"}),e.jsx("input",{ref:ga,type:"file",accept:".srt,.ass,.ssa,.mkv,.mp4,.webm,.m4v,.avi,.mov",multiple:U==="series"||U==="movie",onChange:vn,className:"hidden"}),va&&e.jsx(Uc,{episodeLabel:va.episodeLabel,onConfirmed:qa,onCancel:F})]})}),jj=[{id:"overview",label:"Overview",iconSrc:em},{id:"library",label:"Library",iconSrc:In},...tc()?[]:[{id:"extension",label:"Extension",iconSrc:Zl}],{id:"settings",label:"Settings",iconSrc:ec}];function kj({activeSection:t,onSectionChange:a,publicOverview:s=!1}){return e.jsxs("nav",{className:`im-sidebar${s?" ml-sidebar":""}`,"aria-label":"Immersion sections",children:[e.jsx("div",{className:"im-sidebar-items",children:e.jsx(yf,{id:"immersion-sidebar-selection",children:jj.map(n=>{const r=t===n.id;return e.jsxs("button",{type:"button",className:`im-sidebar-item wc-sidebar-selection-host${s?" ml-nav-item":""}${r?" is-active":""}`,"data-tour-id":`immersion-sidebar-${n.id}`,"aria-current":r?"page":void 0,onClick:()=>a(n.id),children:[r&&e.jsx(bf,{layoutId:"active-tab"}),e.jsx("span",{className:"im-sidebar-item-iconwrap",children:n.icon?e.jsx(n.icon,{size:22,className:"im-sidebar-item-iconsvg"}):e.jsx("img",{src:n.iconSrc,alt:"","aria-hidden":"true",className:"im-sidebar-item-iconimg","data-icon":n.id})}),e.jsx("span",{className:"im-sidebar-item-text",children:e.jsx("span",{className:"en",children:n.label})})]},n.id)})})}),e.jsx(ff,{module:"immersion"})]})}function _j({pagesReadTotal:t,pagesReadToday:a}){const{plan:s}=Rp(),{streak:n,last7Days:r}=$p(),i=s?.input.dailyMinutes??30;return e.jsxs("aside",{className:"im-stats-rail wc-stats-rail","aria-label":"Immersion stats",tabIndex:0,"data-tour-id":"immersion-stats-rail",children:[e.jsxs("div",{className:"im-stats-tile im-stats-tile--pages",children:[e.jsx(gf,{module:"immersion",className:"im-stats-heading",children:"Pages read"}),e.jsxs("div",{className:"wc-stat-compact",children:[e.jsx("span",{className:"wc-stat-compact-label",children:"Pages"}),e.jsx("span",{className:"wc-stat-compact-value",children:t})]}),e.jsx("div",{className:"im-stats-bignum",children:t}),e.jsx("div",{className:"im-stats-bignum-sub",children:"Pages read"})]}),e.jsxs("div",{className:"im-stats-tile",children:[e.jsx("h3",{className:"im-stats-heading",children:"Daily study time goal"}),e.jsxs("div",{className:"wc-stat-compact",children:[e.jsx("span",{className:"wc-stat-compact-label",children:"Goal"}),e.jsxs("span",{className:"wc-stat-compact-value",children:[i,e.jsx("span",{className:"u",children:"min"})]})]}),e.jsx("div",{className:"im-stats-goal",children:e.jsxs("div",{className:"im-stats-goal-head",children:[e.jsxs("span",{className:"label",children:[i," minutes across your learning"]}),e.jsx("span",{className:"ratio",children:a>0?`${a} pages`:"â"})]})}),e.jsx("p",{className:"im-stats-goal-note",children:"Inherited from your study plan. Adjust in Profile â Study plan."})]}),e.jsxs("div",{className:"im-stats-tile",children:[e.jsx("h3",{className:"im-stats-heading",children:"Day streak"}),e.jsxs("div",{className:"wc-stat-compact",children:[e.jsx("span",{className:"wc-stat-compact-label",children:"Streak"}),e.jsxs("span",{className:"wc-stat-compact-value",children:[e.jsx("img",{src:rd,alt:"","aria-hidden":"true",className:"wc-stat-compact-flame"}),n]})]}),e.jsxs("div",{className:"im-stats-streak-row",children:[e.jsx("img",{src:rd,alt:"","aria-hidden":"true",className:"im-stats-streak-flame"}),e.jsxs("span",{className:"im-stats-streak-days",children:[e.jsx("span",{className:"num",children:n})," ",n===1?"day":"days"]})]}),e.jsx("p",{className:"im-stats-streak-msg",children:n>0?"Nice â keep the rhythm going.":"Read today to start your streak."}),e.jsx("div",{className:"im-stats-streak-week","aria-hidden":"true",children:["M","T","W","T","F","S","S"].map((l,c)=>e.jsxs("div",{className:"day",children:[e.jsx("span",{className:"lbl",children:l}),e.jsx("span",{className:`dot${r[c]?" is-on":""}`})]},c))})]})]})}
89function Sj(){const[t,a]=o.useState(()=>localStorage.getItem("reading.annotationsDefault")!=="false");return o.useEffect(()=>{localStorage.setItem("reading.annotationsDefault",String(t))},[t]),e.jsx("div",{className:"im-settings",children:e.jsxs("div",{className:"im-settings-grid",children:[e.jsxs("section",{className:"im-settings-panel is-full",children:[e.jsxs("header",{className:"im-settings-head",children:[e.jsx("span",{className:"num","aria-hidden":"true",children:"ä¸"}),e.jsx("h3",{children:"Text analysis"})]}),e.jsx("p",{className:"im-settings-sub",children:"NLP annotations, grammar lookups, and token clustering across every reader."}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("label",{htmlFor:"toggle-annotations-default",className:"row-label",children:"Enable annotations by default"}),e.jsx("p",{className:"row-desc",children:"Each new reading session opens with annotations on. Tap a token to look it up."})]}),e.jsx($n,{id:"toggle-annotations-default",checked:t,onCheckedChange:a})]})]}),e.jsxs("section",{className:"im-settings-panel",children:[e.jsxs("header",{className:"im-settings-head",children:[e.jsx("span",{className:"num","aria-hidden":"true",children:"äº"}),e.jsx("h3",{children:"Grammar highlighting"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Highlight mode"}),e.jsx("p",{className:"row-desc",children:"Show structures youâve learned (sage) or havenât (sakura)."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Click behavior"}),e.jsx("p",{className:"row-desc",children:"Open a mini-lesson when clicking unknown grammar."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]})]}),e.jsxs("section",{className:"im-settings-panel",children:[e.jsxs("header",{className:"im-settings-head",children:[e.jsx("span",{className:"num","aria-hidden":"true",children:"ä¸"}),e.jsx("h3",{children:"Vocabulary"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Known words highlighting"}),e.jsx("p",{className:"row-desc",children:"Mark vocabulary already in your SRS deck."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Auto-add to SRS"}),e.jsx("p",{className:"row-desc",children:"Send looked-up words straight to your SRS deck."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]})]}),e.jsxs("section",{className:"im-settings-panel is-full",children:[e.jsxs("header",{className:"im-settings-head",children:[e.jsx("span",{className:"num","aria-hidden":"true",children:"å"}),e.jsx("h3",{children:"Reader preferences"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Lookup panel position"}),e.jsx("p",{className:"row-desc",children:"Bottom dock, side rail, or floating popup."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Font size"}),e.jsx("p",{className:"row-desc",children:"Comfortable reading scale across novels."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]}),e.jsxs("div",{className:"im-settings-row",children:[e.jsxs("div",{className:"row-text",children:[e.jsx("span",{className:"row-label",children:"Reading mode"}),e.jsx("p",{className:"row-desc",children:"Vertical or horizontal layout for novels."})]}),e.jsx("span",{className:"row-soon",children:"Soon"})]})]})]})})}function Nj(t){if(!t)return null;const a=new Date(t);return Number.isFinite(a.getTime())?new Intl.DateTimeFormat("en",{day:"numeric",month:"short",...a.getFullYear()!==new Date().getFullYear()?{year:"numeric"}:{}}).format(a):null}function Cj({candidate:t,onContinue:a,onAddContent:s}){const n="/watercolor/system-v2/next-up/immersion-scene-v1.webp";if(!t)return e.jsx(dd,{className:"im-overview-next",label:"Start with something you love",title:"Make room for a little Japanese.",description:"Bring a manga, a book, or video subtitles. Choose something you're curious about, and take it at your own pace.",detail:e.jsxs("div",{className:"im-resume-context",children:[e.jsx("p",{className:"im-resume-context-label",children:"A little help as you go"}),e.jsx("p",{className:"im-resume-help",children:"Look up words, explore grammar in context, and save the words you want to remember."})]}),scene:n,action:"Add your first content",onAction:s,variant:"dusk"});const r=t.contentType==="novel",i=r?"Chapter":"Page",l=r?"chapters":"pages",c=t.hasProgress&&t.currentPage>0,d=c?"Pick up where you left off":"Most recently added",m=r?"Novel":t.contentType==="manga"?"Manga":"From your library",u=t.author?.trim(),h=c?i+" "+t.currentPage+(t.totalPages>0?" of "+t.totalPages:""):"Not started yet",p=t.totalPages>0?Math.max(0,Math.min(100,t.currentPage/t.totalPages*100)):0,g=c?Nj(t.lastReadAt):null;return e.jsx(dd,{className:"im-overview-next",label:d,meta:g?e.jsxs("time",{dateTime:t.lastReadAt,children:["Last read ",g]}
89):void 0,title:t.title,subtitle:e.jsxs("span",{className:"im-resume-kind",children:[e.jsx("img",{src:In,alt:"","aria-hidden":"true"}),m,u&&e.jsxs("span",{children:["· ",u]})]}),description:"Read at your own pace. Tap a word or grammar pattern for help, and save useful words as you go.",detail:e.jsxs("div",{className:"im-resume-context",children:[e.jsx("p",{className:"im-resume-context-label",children:c?"Your saved place":"A new story to explore"}),e.jsxs("div",{className:"im-resume-position",children:[e.jsx("p",{children:h}),!c&&t.totalPages>0&&e.jsxs("span",{children:[t.totalPages," ",t.totalPages===1?i.toLowerCase():l]})]}),c&&t.totalPages>0&&e.jsx("span",{className:"ov-progress","aria-hidden":"true",children:e.jsx("span",{style:{width:p+"%"}})})]}),scene:n,thumbnail:t.thumbnailUrl,action:c?"Continue reading":"Open content",actionLabel:(c?"Continue reading":"Open content")+": "+t.title,onAction:()=>a(t.id),variant:"dusk"})}const Ej=!1,Tj=[{id:"upload",title:"Bring your own content",description:"Make your manga, books and video subtitles a little easier to follow.",detail:"CBZ, PDF, EPUB, DRM-free Kindle, ZIP, SRT & ASS",image:"/watercolor/system-v2/public-pages/concepts/content-shelf.webp",action:"Add content",tourId:"immersion-upload-card"},{id:"discover",title:"Find your next story",description:"Browse manga, anime, novels, dramas and movies by genre and popularity.",detail:"Something for your next reading session",image:"/watercolor/system-v2/public-pages/concepts/immersion-garden.webp",action:"Explore content"},{id:"extension",title:"Take Shizen into your browser",description:"Look up words as you browse. Use tappable subtitles on streaming sites after processing the episode in Shizen.",detail:"Look up in context · Save words to your decks",image:"/watercolor/system-v2/overviews/immersion-browser.webp",action:"See how it works",tourId:"immersion-extension-card"}];function Mj({onSelect:t}){const a=Tj.filter(s=>s.id!=="discover"&&(!tc()||s.id!=="extension"));return e.jsxs("section",{className:"ov-immersion-paths","aria-labelledby":"ov-paths-title",children:[e.jsxs("div",{className:"ov-section-heading",children:[e.jsx("h2",{id:"ov-paths-title",children:"More Japanese, on your terms."}),e.jsx("p",{children:a.some(s=>s.id==="extension")?"Read here, or take your learning tools into the browser.":"Bring the stories you want to spend time with."})]}),e.jsx("div",{className:"ov-path-list","data-tour-id":"immersion-path-cards",children:a.map(s=>e.jsxs("button",{type:"button",className:"ov-path",onClick:()=>t(s.id),"data-tour-id":s.tourId,children:[e.jsx("img",{src:s.image,alt:"","aria-hidden":"true",loading:"lazy"}),e.jsxs("span",{className:"ov-path-copy",children:[e.jsx("span",{className:"ov-option-title",children:s.title}),e.jsx("span",{className:"ov-option-description",children:s.description}),e.jsx("span",{className:"ov-meta",children:s.detail}),e.jsxs("span",{className:"ov-option-action",children:[s.action," ",e.jsx("span",{"aria-hidden":"true",children:"â"})]})]})]},s.id))})]})}const xu="https://api.jikan.moe/v4",ip=Is({current_page:Ya(),last_visible_page:Ya(),has_next_page:xf(),items:Is({total:Ya()}).optional()}),An=Is({name:Ka()}),Pj=Is({mal_id:Ya(),url:Ka(),title:Ka(),title_japanese:Ka().nullable().optional(),title_english:Ka().nullable().optional(),images:Is({jpg:Is({large_image_url:Ka().nullable().optional(),image_url:Ka().nullable().optional()}).optional()}).optional(),synopsis:Ka().nullable().optional(),score:Ya().nullable().optional(),scored_by:Ya().nullable().optional(),rank:Ya().nullable().optional(),popularity:Ya().nullable().optional(),members:Ya().nullable().optional(),favorites:Ya().nullable().optional(),status:Ka().nullable().optional(),type:Ka().nullable().optional(),episodes:Ya().nullable().optional(),season:Ka().nullable().optional(),year:Ya().nullable().optional(),source:Ka().nullable().optional(),genres:Ks(An).optional(),themes:Ks(An).optional(),demographics:Ks(An).optional(),studios:Ks(An).optional(),trailer:Is({url:Ka().nullable().optional()}).optional()}),Aj=Is({mal_id:Ya(),url:Ka(),title:Ka(),title_japanese:Ka().nullable().optional(),title_english:Ka().nullable().optional(),images:Is({jpg:Is({large_image_url:Ka().nullable().optional(),image_url:Ka().nullable().optional()}).optional()}).optional(),synopsis:Ka().nullable().optional(),score:Ya().nullable().optional(),scored_by:Ya().nullable().optional(),rank:Ya().nullable().optional(),popularity:Ya().nullable().optional(),members:Ya().nullable().optional(),favorites:Ya().nullable().optional(),status:Ka().nullable().optional(),chapters:Ya().nullable().optional(),volumes:Ya().nullable().optional(),genres:Ks(An).optional(),themes:Ks(An).optional(),demographics:Ks(An).optional(),authors:Ks(Is({name:Ka()})).optional(),serializations:Ks(An).optional()}),Ij=Is({pagination:ip,data:Ks(Pj)}
89),Rj=Is({pagination:ip,data:Ks(Aj)});function $j(t,a){return{mal_id:t.mal_id,url:t.url,kind:a,title:t.title,title_japanese:t.title_japanese??null,title_english:t.title_english??null,cover:t.images?.jpg?.large_image_url??t.images?.jpg?.image_url??null,synopsis:t.synopsis??null,score:t.score??null,scored_by:t.scored_by??null,rank:t.rank??null,popularity:t.popularity??null,members:t.members??null,favorites:t.favorites??null,status:t.status??null,genres:(t.genres??[]).map(s=>s.name),themes:(t.themes??[]).map(s=>s.name),demographics:(t.demographics??[]).map(s=>s.name),type:t.type??null,episodes:t.episodes??null,season:t.season??null,year:t.year??null,studios:(t.studios??[]).map(s=>s.name),source:t.source??null,trailer_url:t.trailer?.url??null,chapters:null,volumes:null,authors:[],serialization:null}}function zj(t,a){return{mal_id:t.mal_id,url:t.url,kind:a,title:t.title,title_japanese:t.title_japanese??null,title_english:t.title_english??null,cover:t.images?.jpg?.large_image_url??t.images?.jpg?.image_url??null,synopsis:t.synopsis??null,score:t.score??null,scored_by:t.scored_by??null,rank:t.rank??null,popularity:t.popularity??null,members:t.members??null,favorites:t.favorites??null,status:t.status??null,genres:(t.genres??[]).map(s=>s.name),themes:(t.themes??[]).map(s=>s.name),demographics:(t.demographics??[]).map(s=>s.name),type:null,episodes:null,season:null,year:null,studios:[],source:null,trailer_url:null,chapters:t.chapters??null,volumes:t.volumes??null,authors:(t.authors??[]).map(s=>s.name),serialization:t.serializations?.[0]?.name??null}}async function Fj(t){const{kind:a,search:s,page:n=1,limit:r=20,orderBy:i,sort:l,status:c,genres:d,signal:m,sfw:u=!0}=t,h=a==="anime"||a==="movie",p=h?`${xu}/anime`:`${xu}/manga`,g=new URLSearchParams;a==="anime"?g.set("type","tv"):a==="movie"?g.set("type","movie"):a==="novel"?g.set("type","novel"):a==="lightnovel"?g.set("type","lightnovel"):g.set("type","manga"),i&&g.set("order_by",i),l&&g.set("sort",l),u&&g.set("sfw","true"),g.set("page",String(n)),g.set("limit",String(Math.min(r,25))),s?.trim()&&g.set("q",s.trim()),c&&g.set("status",c),d&&d.length>0&&g.set("genres",d.join(","));const f=`${p}?${g.toString()}`,b=await fetch(f,{signal:m});if(!b.ok)throw new Error(`Jikan API error: ${b.status}`);const y=await b.json();if(h){const x=Ij.parse(y);return{items:x.data.map(v=>$j(v,a)),pageInfo:{currentPage:x.pagination.current_page,lastPage:x.pagination.last_visible_page,hasNextPage:x.pagination.has_next_page,total:x.pagination.items?.total??0}}}else{const x=Rj.parse(y);return{items:x.data.map(v=>zj(v,a)),pageInfo:{currentPage:x.pagination.current_page,lastPage:x.pagination.last_visible_page,hasNextPage:x.pagination.has_next_page,total:x.pagination.items?.total??0}}}}const Dj=[{value:"members",label:"Popularity"},{value:"score",label:"Score"},{value:"favorites",label:"Favorites"},{value:"start_date",label:"Newest"}],Lj=[{value:"",label:"Any status"},{value:"airing",label:"Airing"},{value:"complete",label:"Finished"},{value:"upcoming",label:"Upcoming"}],Oj=[{value:"",label:"Any status"},{value:"publishing",label:"Publishing"},{value:"complete",label:"Finished"},{value:"hiatus",label:"Hiatus"}],Ol={Action:1,Adventure:2,Comedy:4,Drama:8,Fantasy:10,Horror:14,Mystery:7,Romance:22,"Sci-Fi":24,"Slice of Life":36,Historical:13,School:23},Vc="reading.wishlist",Bl="wishlist-sync";function Ii(){try{const t=localStorage.getItem(Vc);return t?JSON.parse(t):[]}catch{return[]}}function ul(t){localStorage.setItem(Vc,JSON.stringify(t)),window.dispatchEvent(new CustomEvent(Bl))}async function Kc(){try{const{data:{session:t}}=await Ps.auth.getSession();return t?.access_token??null}catch{return null}}async function Bj(){const t=await Kc();if(!t)return null;try{const a=await fetch(`${ue()}/api/user/wishlist`,{headers:{Authorization:`Bearer ${t}`}});if(!a.ok)return null;const s=await a.json();return Array.isArray(s?.items)?s.items:[]}catch{return null}}async function wu(t){const a=await Kc();if(a)try{await fetch(`${ue()}/api/user/wishlist`,{method:"POST",headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"},body:JSON.stringify({item:t})})}catch{}}async function vu(t){const a=await Kc();if(a)try{await fetch(`${ue()}/api/user/wishlist/${t}`,{method:"DELETE",headers:{Authorization:`Bearer ${a}`}})}catch{}}function qj(){const{user:t}=ps(),[a,s]=o.useState(Ii);o.useEffect(()=>{const l=()=>s(Ii());window.addEventListener(Bl,l);const c=d=>{d.key===Vc&&s(Ii())};return window.addEventListener("storage",c),()=>{window.removeEventListener(Bl,l),window.removeEventListener("storage",c)}},[]),o.useEffect(()=>{if(!t)return;let l=!1;return(async()=>{const c=await Bj();if(!(l||!c)){if(c.length===0){const d=Ii();d.length>0&&await Promise.allSettled(d.map(m=>wu(m)));return}s(c),ul(c)}})(),()=>{l=!0}},[t?.id]);const n=o.useCallback(l=>a.some(c=>c.mal_id===l),[a]),r=o.useCallback(l=>{s(c=>{const d=c.some(u=>u.mal_id===l.mal_id),m=d?c.filter(u=>u.mal_id!==l.mal_id):[l,...c];return ul(m),d?vu(l.mal_id):wu(l),m})},[]),i=o.useCallback(l=>{s(c=>{const d=c.filter(m=>m.mal_id!==l);return ul(d),vu(l),d})},[]);return{wishlist:a,toggleWishlist:r,isWishlisted:n,removeFromWishlist:i}}const ju=[{id:"manga",label:"Manga",kanji:"ä¸",kind:"manga",icon:ss},{id:"anime",label:"Anime",kanji:"äº",kind:"anime",icon:Jr},{id:"movies",label:"Movies",kanji:"ä¸",kind:"movie",icon:on},{id:"novels",label:"Novels",kanji:"å",kind:"novel",icon:ud},{id:"lightnovel",label:"Light Novels",kanji:"äº",kind:"lightnovel",icon:ud}],Hc=t=>t==="anime"||t==="movie",ql={manga:"Manga",anime:"Anime",movie:"Movie",novel:"Novel",lightnovel:"Light Novel"},Uj=[{label:"Any genre",value:"ALL"},...Object.keys(Ol).map(t=>({label:t,value:t}))],Vj=Dj.map(t=>({label:t.label,value:t.value})),Kj=20;function Hj(t){const a=t.title_japanese??t.title,s=encodeURIComponent(a);return{amazon:`https://www.amazon.co.jp/s?k=${s}`,bookwalker:`https://bookwalker.jp/search/?q=${s}`}}function Wj({item:t,onSelect:a,isWishlisted:s,onToggleWishlist:n}){const r=Hc(t.kind),i=t.title_japanese??t.title,l=t.title_english&&t.title_english!==i?t.title_english:null,c=r?t.type??ql[t.kind]:ql[t.kind],d=o.useMemo(()=>
89{if(r){const u=[];return t.episodes&&u.push(`${t.episodes} ep`),t.studios[0]&&u.push(t.studios[0]),u.join(" · ")||null}const m=[];return t.chapters&&m.push(`${t.chapters} ch`),t.authors[0]&&m.push(t.authors[0]),m.join(" · ")||null},[t,r]);return e.jsxs(ds,{size:"md",className:"im-disc-card",onClick:()=>a(t),animate:!1,children:[e.jsxs(ds.Cover,{className:"im-disc-card-cover",children:[t.cover?e.jsx("img",{src:t.cover,alt:i,loading:"lazy",decoding:"async"}):e.jsx("div",{className:"im-disc-card-cover-fallback","aria-hidden":"true",children:r?e.jsx(on,{size:48}):e.jsx(ss,{size:48})}),e.jsx("span",{className:"im-disc-card-badge im-disc-card-badge-kind",children:c}),t.score&&e.jsxs("span",{className:"im-disc-card-badge im-disc-card-badge-score",children:[e.jsx(wo,{size:12,"aria-hidden":"true"}),t.score.toFixed(1)]}),e.jsx("span",{role:"button",tabIndex:0,"aria-label":s?"Remove from wishlist":"Add to wishlist",className:`im-disc-card-wish${s?" is-on":""}`,onClick:m=>{m.stopPropagation(),n(t)},onKeyDown:m=>{(m.key==="Enter"||m.key===" ")&&(m.preventDefault(),m.stopPropagation(),n(t))},children:e.jsx(um,{size:15,className:s?"is-fill":""})}),(t.members||t.status)&&e.jsxs("div",{className:"im-disc-card-cover-foot",children:[t.members&&e.jsxs("span",{className:"meta",children:[e.jsx(mm,{size:12,"aria-hidden":"true"}),Intl.NumberFormat("en",{notation:"compact"}).format(t.members)]}),t.status&&e.jsx("span",{className:"status",children:t.status.toLowerCase()})]})]}),e.jsxs(ds.Body,{className:"im-disc-card-body",children:[e.jsx("h4",{className:"im-disc-card-title",title:i,children:i}),l&&e.jsx("p",{className:"im-disc-card-subtitle",children:l}),d&&e.jsx("p",{className:"im-disc-card-meta",children:d}),e.jsx("p",{className:"im-disc-card-syn",children:t.synopsis||"No synopsis available."}),t.genres.length>0&&e.jsxs("div",{className:"im-disc-card-genres",children:[t.genres.slice(0,3).map(m=>e.jsx("span",{className:"im-disc-chip",children:m},m)),t.genres.length>3&&e.jsxs("span",{className:"im-disc-chip im-disc-chip-quiet",children:["+",t.genres.length-3]})]})]}),e.jsxs(ds.Foot,{className:"im-disc-card-foot",children:[e.jsxs("span",{className:"im-disc-card-cta",children:["View details ",e.jsx("span",{className:"arrow","aria-hidden":"true",children:"â"})]}),e.jsxs("a",{href:t.url,target:"_blank",rel:"noopener noreferrer",className:"im-disc-card-mal",title:"Open on MyAnimeList",onClick:m=>m.stopPropagation(),children:["MAL",e.jsx(dr,{size:11,"aria-hidden":"true"})]})]})]})}function Gj({item:t,onBack:a,isWishlisted:s,onToggleWishlist:n}){const r=Hc(t.kind),i=Hj(t),l=t.title_japanese??t.title,c=t.title_english&&t.title_english!==l?t.title_english:null,[d,m]=o.useState(!1);return e.jsxs("div",{className:"im-disc-detail",children:[e.jsxs("div",{className:"im-disc-detail-bar",children:[e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink im-disc-detail-back",onClick:a,children:[e.jsx(Za,{size:14,"aria-hidden":"true"}),"Back to results"]}),e.jsxs("button",{type:"button",className:`wc-cta-square im-disc-detail-wish${s?" wc-cta-square-secondary--maple is-on":" wc-cta-square-quiet--ink"}`,onClick:()=>n(t),children:[e.jsx(um,{size:14,className:s?"is-fill":""}),s?"In wishlist":"Add to wishlist"]})]}),e.jsxs("div",{className:"im-disc-detail-grid",children:[e.jsx("div",{className:"im-disc-detail-cover",children:t.cover?e.jsx("img",{src:t.cover,alt:l}):e.jsx("div",{className:"im-disc-detail-cover-fallback","aria-hidden":"true",children:r?e.jsx(on,{size:56}):e.jsx(ss,{size:56})})}),e.jsxs("div",{className:"im-disc-detail-info",children:[e.jsxs("div",{className:"im-disc-detail-badges",children:[e.jsxs("span",{className:"im-disc-pill",children:[r?e.jsx(on,{size:11}):e.jsx(ss,{size:11}),t.type??ql[t.kind]]}),t.score&&e.jsxs("span",{className:"im-disc-pill",children:[e.jsx(wo,{size:11,"aria-hidden":"true"}),t.score.toFixed(1)]}),t.status&&e.jsx("span",{className:"im-disc-pill",children:t.status}),t.members&&e.jsxs("span",{className:"im-disc-pill",children:[e.jsx(mm,{size:11,"aria-hidden":"true"}),Intl.NumberFormat("en",{notation:"compact"}).format(t.members)]})]}),e.jsx("h1",{className:"im-disc-detail-title",children:l}),c&&e.jsx("p",{className:"im-disc-detail-subtitle",children:c}),t.genres.length>0&&e.jsx("div",{className:"im-disc-detail-genres",children:t.genres.slice(0,6).map(u=>e.jsx("span",{className:"im-disc-chip",children:u},u))}),t.synopsis&&e.jsxs("div",{className:"im-disc-detail-syn",children:[e.jsx("p",{className:d?"":"is-clamped",children:t.synopsis}),t.synopsis.length>200&&e.jsx("button",{type:"button",className:"im-disc-detail-syn-toggle",onClick:()=>m(u=>!u),children:d?"Show less":"Show more"})]}),e.jsxs("div",{className:"im-disc-detail-stats",children:[r?e.jsxs(e.Fragment,{children:[t.episodes&&e.jsxs("span",{children:[e.jsx(Jr,{size:14,"aria-hidden":"true"}),t.episodes," episode",t.episodes!==1?"s":""]}),t.studios[0]&&e.jsx("span",{children:t.studios[0]})]}):e.jsxs(e.Fragment,{children:[t.chapters&&e.jsxs("span",{children:[e.jsx(ss,{size:14,"aria-hidden":"true"}),t.chapters," chapter",t.chapters!==1?"s":""]}),t.volumes&&e.jsxs("span",{children:[t.volumes," vol",t.volumes!==1?"s":""]})]}),[...t.demographics,...t.themes].slice(0,4).map(u=>e.jsx("span",{children:u},u))]})]})]}),e.jsxs("div",{className:"im-disc-detail-find",children:[e.jsxs("div",{className:"im-disc-detail-find-head",children:[e.jsx("span",{className:"lbl",children:"Where to find it"}),e.jsx("span",{className:"jp",children:"å
¥æå
"})]}),e.jsx("p",{className:"im-disc-detail-find-lede",children:r?"Get the video file and Jap
89anese subtitle track (.srt or .ass), then add the show to Shizen. Play the video with rich subtitles â hover any word for instant definitions. Shizen analyzes every line to annotate grammar and calculate how much of the show you already understand based on your SRS progress.":"Upload the file and Shizen will annotate every sentence with vocabulary definitions, grammar breakdowns, and a live comprehensibility score showing how much you can read right now."}),e.jsxs("div",{className:"im-disc-detail-find-grid",children:[e.jsxs("a",{href:i.amazon,target:"_blank",rel:"noopener noreferrer",className:"im-disc-find-tile",children:[e.jsx("span",{className:"im-disc-find-mark im-disc-find-mark--text",children:"Amazon"}),e.jsx("span",{children:"Physical & digital editions"}),e.jsx(dr,{size:11,"aria-hidden":"true"})]}),!r&&e.jsxs("a",{href:i.bookwalker,target:"_blank",rel:"noopener noreferrer",className:"im-disc-find-tile",children:[e.jsx("span",{className:"im-disc-find-mark im-disc-find-mark--text",children:"BookWalker"}),e.jsx("span",{children:"Digital manga & novels (JP)"}),e.jsx(dr,{size:11,"aria-hidden":"true"})]}),r&&e.jsxs("a",{href:`https://www.crunchyroll.com/search?q=${encodeURIComponent(t.title)}`,target:"_blank",rel:"noopener noreferrer",className:"im-disc-find-tile",children:[e.jsx("span",{className:"im-disc-find-mark im-disc-find-mark--text",children:"Crunchyroll"}),e.jsx("span",{children:"Stream with JP audio & subs"}),e.jsx(dr,{size:11,"aria-hidden":"true"})]}),e.jsxs("a",{href:t.url,target:"_blank",rel:"noopener noreferrer",className:"im-disc-find-tile",children:[e.jsx("span",{className:"im-disc-find-mark im-disc-find-mark--text",children:"MyAnimeList"}),e.jsx("span",{children:"Ratings, reviews & community"}),e.jsx(dr,{size:11,"aria-hidden":"true"})]}),r&&e.jsxs("a",{href:`https://www.netflix.com/search?q=${encodeURIComponent(t.title)}`,target:"_blank",rel:"noopener noreferrer",className:"im-disc-find-tile",children:[e.jsx("span",{className:"im-disc-find-mark im-disc-find-mark--text",children:"Netflix"}),e.jsx("span",{children:"Stream (if available)"}),e.jsx(dr,{size:11,"aria-hidden":"true"})]})]})]})]})}function Yj({searchQuery:t="",isActive:a,initialSelectedItem:s,onInitialItemHandled:n}){const[r,i]=o.useState("manga"),[l,c]=o.useState("members"),[d,m]=o.useState(""),[u,h]=o.useState("ALL"),[p,g]=o.useState(1),[f,b]=o.useState(t),[y,x]=o.useState(t),[v,w]=o.useState(!1),[j,T]=o.useState(null),[P,N]=o.useState(!1),[_,L]=o.useState(null),[q,O]=o.useState(null),[A,k]=o.useState(0),[J,M]=o.useState(0),{isWishlisted:H,toggleWishlist:ee}=qj(),Pe=o.useRef(!1);o.useEffect(()=>{a&&!Pe.current&&(Pe.current=!0,ne("immersion_discovery_opened",{entry_point:"path_choice"}))},[a]);const D=o.useRef(!1);o.useEffect(()=>{if(!D.current){D.current=!0;return}ne("immersion_discovery_filter_applied",{media_type:r,genre_count:u!=="ALL"?1:0,sort:l})},[r,u,l]),o.useEffect(()=>{s&&(O(s),n?.())},[s,n]),o.useEffect(()=>{const Le=setTimeout(()=>x(f.trim()),400);return()=>clearTimeout(Le)},[f]),o.useEffect(()=>{g(1)},[y,r,l,d,u]),o.useEffect(()=>{c("members"),m(""),h("ALL")},[r]);const de=ju.find(Le=>Le.id===r),fe=de.kind,Me=Hc(fe);o.useEffect(()=>{if(!a)return;N(!0),M(Ft=>Ft+1),L(null);const Le=new AbortController,jt=u!=="ALL"&&Ol[u]?[Ol[u]]:void 0;return Fj({kind:fe,search:y||void 0,page:p,limit:Kj,orderBy:l,sort:"desc",status:d||void 0,genres:jt,signal:Le.signal}).then(Ft=>T(Ft)).catch(Ft=>{Ft.name!=="AbortError"&&L(Ft instanceof Error?Ft.message:"Failed to fetch discovery catalogue")}).finally(()=>{Le.signal.aborted||N(!1)}),()=>Le.abort()},[fe,y,p,l,d,u,A,a]);const U=j?.items??[],ve=j?.pageInfo,yt=()=>k(Le=>Le+1),ut=()=>{c("members"),m(""),h("ALL"),g(1)},St=Me?Lj:Oj,je=(d!==""?1:0)+(u!=="ALL"?1:0)+(l!=="members"?1:0),lt=y?`Results for "${y}"`:`${de.label} â Top Picks`,Et=y?"Showing titles matching your search":"Popular titles from MyAnimeList",Ct=Le=>{ne("immersion_discovery_item_opened",{media_type:r,mal_id:Le.mal_id}),O(Le)},aa=Le=>{H(Le.mal_id)||ne("immersion_wishlist_item_added",{media_type:Le.kind,mal_id:Le.mal_id}),ee(Le)},vt=ve?.lastPage??1;return e.jsx("div",{className:"im-disc",children:e.jsx(Oa,{mode:"wait",children:q?e.jsx(ze.div,{initial:{opacity:0}
89,animate:{opacity:1,transition:{duration:Lo,ease:ar}},exit:{opacity:0,transition:{duration:Do,ease:"easeIn"}},children:e.jsx(Gj,{item:q,onBack:()=>O(null),isWishlisted:H(q.mal_id),onToggleWishlist:aa})},"detail"):e.jsxs(ze.div,{initial:{opacity:0},animate:{opacity:1,transition:{duration:Lo,ease:ar}},exit:{opacity:0,transition:{duration:Do,ease:"easeIn"}},children:[e.jsx("div",{className:"im-disc-tabs",role:"tablist",children:ju.map(Le=>{const jt=Le.icon,Ft=Le.id===r;return e.jsxs("button",{role:"tab","aria-selected":Ft,type:"button",className:`im-disc-tab${Ft?" is-active":""}`,onClick:()=>i(Le.id),children:[e.jsx(jt,{size:14,"aria-hidden":"true"}),e.jsx("span",{children:Le.label}),Ft&&e.jsx("span",{className:"brush","aria-hidden":"true"})]},Le.id)})}),e.jsxs("header",{className:"im-disc-head",children:[e.jsxs("div",{className:"im-disc-head-eyebrow",children:[e.jsx("span",{className:"num jp",children:de.kanji}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsxs("span",{className:"lbl",children:["Discover ",de.label]}),e.jsx("span",{className:"jp",children:"ä½åãæ¢ã"})]}),e.jsxs("div",{className:"im-disc-head-row",children:[e.jsxs("div",{className:"im-disc-head-titleblock",children:[e.jsx("h2",{className:"im-disc-head-title",children:lt}),e.jsx("p",{className:"im-disc-head-subtitle",children:Et})]}),e.jsxs("div",{className:"im-disc-head-actions",children:[e.jsx("span",{className:"im-disc-count",children:P?"Loadingâ¦":`${U.length} item${U.length===1?"":"s"}`}),e.jsxs("button",{type:"button",className:`im-disc-filter-toggle${v?" is-open":""}`,onClick:()=>w(Le=>!Le),"aria-expanded":v,children:[e.jsx(vf,{size:14,"aria-hidden":"true"}),"Filters",je>0&&e.jsx("span",{className:"badge",children:je})]})]})]}),e.jsxs("div",{className:"im-disc-toolbar wc-pencil-frame wc-pencil-frame--md",children:[e.jsx(tm,{type:"search",value:f,onChange:b,placeholder:`Search ${de.label.toLowerCase()}â¦`}),e.jsx(Oa,{initial:!1,children:v&&e.jsxs(ze.div,{initial:{opacity:0,height:0},animate:{opacity:1,height:"auto",transition:{duration:Lo,ease:ar}},exit:{opacity:0,height:0,transition:{duration:Do,ease:ar}},className:"im-disc-filters",children:[e.jsxs("div",{className:"im-disc-filters-inner",children:[e.jsxs("label",{className:"im-disc-filter",children:[e.jsx("span",{className:"lbl",children:"Status"}),e.jsxs(Oo,{value:d||"__all__",onValueChange:Le=>m(Le==="__all__"?"":Le),children:[e.jsx(Bo,{className:"im-disc-filter-trigger",children:e.jsx(qo,{placeholder:"All statuses"})}),e.jsxs(Uo,{className:"im-disc-filter-pop",children:[e.jsx(Si,{value:"__all__",children:"All statuses"}),St.map(Le=>e.jsx(Si,{value:Le.value,children:Le.label},Le.value))]})]})]}),e.jsxs("label",{className:"im-disc-filter",children:[e.jsx("span",{className:"lbl",children:"Genre"}),e.jsxs(Oo,{value:u,onValueChange:h,children:[e.jsx(Bo,{className:"im-disc-filter-trigger",children:e.jsx(qo,{placeholder:"Any genre"})}),e.jsx(Uo,{className:"im-disc-filter-pop",children:Uj.map(Le=>e.jsx(Si,{value:Le.value,children:Le.label},Le.value))})]})]}),e.jsxs("label",{className:"im-disc-filter",children:[e.jsx("span",{className:"lbl",children:"Sort by"}),e.jsxs(Oo,{value:l,onValueChange:Le=>c(Le),children:[e.jsx(Bo,{className:"im-disc-filter-trigger",children:e.jsx(qo,{placeholder:"Members"})}),e.jsx(Uo,{className:"im-disc-filter-pop",children:Vj.map(Le=>e.jsx(Si,{value:Le.value,children:Le.label},Le.value))})]})]})]}),je>0&&e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink im-disc-filters-reset",onClick:ut,children:"Reset filters"})]},"filters")})]})]}),_&&e.jsxs("div",{className:"im-disc-error",role:"alert",children:[e.jsx("span",{children:_}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--maple",onClick:yt,children:"Retry"})]}),e.jsxs("div",{className:"im-disc-result-slot",children:[e.jsx(Oa,{children:P&&e.jsx(ze.div,{className:"im-disc-loader",initial:{opacity:0,scale:.96},animate:{opacity:1,scale:1},exit:{opacity:0,scale:.98},transition:{opacity:{duration:.55,ease:ar},scale:{duration:.7,ease:ar}},"aria-hidden":"true",children:e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999})},`enso-${J}`)}),!P&&U.length===0&&!_&&e.jsx(Br,{variant:"plain",icon:Zu,title:"No titles found",description:"Try adjusting your filters or search terms to discover more content.",action:je>0?e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink im-disc-empty-reset",onClick:ut,children:"Reset filters"}):null}),!P&&U.length>0&&e.jsx("div",{className:"im-disc-grid",children:U.map(Le=>e.jsx(Wj,{item:Le,onSelect:Ct,isWishlisted:H(Le.mal_id),onToggleWishlist:aa},Le.mal_id))})]}),!P&&ve&&e.jsx(wf,{variant:"plain",currentPage:ve.currentPage,totalPages:vt,hasNextPage:ve.hasNextPage,onPageChange:g})]},"list")})})}const Jj={library:{icon:In,heading:"Sign up to build your library",body:"Your library holds the manga, novels, and shows youâve uploaded â with reading progress, lookups, and OCR linked to your account. Create a free account to start collecting."},reader:{icon:In,heading:"Sign up to keep reading",body:"Pick up where you left off â page progress, vocab lookups, and reading time are saved per title. Create a free account to unlock the reader."},settings:{icon:ec,heading:"Sign up to customize",body:"Reader preferences â annotations, lookups, layout â are saved to your account. Create a free account to set them."},wishlist:{icon:In,heading:"Sign up to build a wishlist",body:"Save manga and shows from Discover for later, and weâll surface them when youâre ready to read. Create a free account to start your wishlist."}};function Xj({reason:t,onSignup:a,onDismiss:s}){const n=Jj[t];return e.jsx(_f,{icon:e.jsx("img",{className:"im-gate-icon",src:n.icon,alt:""}),heading:n.heading,body:n.body,ctaVariant:"dusk",onSignup:a,onDismiss:s})}const ku=["--brand-kana","--brand-grammar","--brand-vocab","--brand-dict","--brand-chat","--brand-reading","--brand-video"];function Qj(t){let a=5381;for(let s=0;s<t.length;s++)a=(a<<5)+a+t.charCodeAt(s)|0;return Math.abs(a)}function Ul(t){return/[ã-ã¿ã-ä¶¿ä¸-é¿¿ï¤-ï«¿]/.test(t)}function Zj(t,a){const s=a&&Ul(a)?a:Ul(t)?t:"";if(s){const r=s.match(/[ã-ã¿ã-ä¶¿ä¸-é¿¿ï¤-ï«¿]/);if(r)return r[0]}const n=t.trim();return n?n[0].toUpperCase():"æ¬"}function wi({title:t,titleJp:a,className:s}){const n=(t||"").trim()||"Untitled",i=`hsl(var(${ku[Qj(n)%ku.length]}))`,l=Zj(n,a),c=Ul(n);return e.jsxs("div",{className:`wc-generated-cover ${s??""}`,"aria-hidden":"true",style:{position:"absolute",inset:0,display:"flex",flexDirection:"column",justifyContent:"flex-end",overflow:"hidden",padding:"14px",background:"var(--paper)",border:"1px solid rgba(42, 53, 64, 0.12)",borderRadius:"var(--wc-radius-leaf)"},children:[e.jsx("span",{style:{position:"absolute",top:"-0.18em",right:"0.04em",fontFamily:"'Noto Serif JP', serif",fontWeight:700,fontSize:"128px",lineHeight:1,color:i,opacity:.1,userSelect:"none",pointerEvents:"none"},children:l}),e.jsx("span",{style:{width:"24px",height:"2px",marginBottom:"8px",background:i,borderRadius:"var(--wc-radius-ink)",opacity:.85}}),e.jsx("span",{style:{position:"relative",fontFamily:c?"'Noto Serif JP', serif":"'Shippori Mincho', serif",fontWeight:600,fontSize:"15px",lineHeight:1.3,color:"var(--ink)",display:"-webkit-box",WebkitLineClamp:4,WebkitBoxOrient:"vertical",overflow:"hidden",
89wordBreak:"break-word"},children:n})]})}const ek=[{icon:In,title:"Start with the content you enjoy",body:"Add a manga archive or PDF, a novel (EPUB or Kindle), or a videoâs subtitle file. We extract the Japanese from speech bubbles, subtitles, and prose."},{icon:Zl,title:"Get help with words and grammar",body:"The text is matched to our dictionary and grammar lessons, giving you tappable explanations and vocabulary decks."},{icon:In,title:"Keep your original files",body:"Manga pages and videos play from your own device. Keep your originals handy when you come back to read or watch."}],op="shizen.immersion.library.howItWorks.dismissed";function tk(){try{return localStorage.getItem(op)==="true"}catch{return!1}}function _u(){const[t,a]=o.useState(tk);if(t)return null;const s=()=>{try{localStorage.setItem(op,"true")}catch{}a(!0)};return e.jsxs("div",{className:"im-upload-guide wc-pencil-frame wc-pencil-frame--md",children:[e.jsxs("details",{children:[e.jsxs("summary",{children:["How adding content works ",e.jsx("span",{"aria-hidden":"true",children:"â"})]}),e.jsx("ul",{children:ek.map(n=>e.jsxs("li",{children:[e.jsx("img",{src:n.icon,alt:"","aria-hidden":"true"}),e.jsxs("div",{children:[e.jsx("strong",{children:n.title}),e.jsx("p",{children:n.body})]})]},n.title))})]}),e.jsx("button",{type:"button",className:"im-upload-guide-dismiss wc-cta-square wc-cta-square-quiet--dusk",onClick:s,"aria-label":"Dismiss this guide permanently",title:"Donât show this guide again",children:e.jsx("img",{src:zp,alt:"","aria-hidden":"true"})})]})}const ak="https://chromewebstore.google.com/detail/shizen-learn/doifgjcpjgglmfkjokjkghooandiimoa",sk=[{icon:ef,title:"Shift+hover lookup, anywhere â always on",body:"Hold Shift and hover any Japanese word on any website for an instant dictionary lookup. It deinflects the word for you (è¦ã â è¦ã), so conjugated forms just work. No setup, nothing to process."},{icon:Oi,title:"Grammar-enriched subtitles on streaming",body:"Process a showâs subtitles in Shizen first, then overlay that grammar-aware, tappable track on Netflix, YouTube, and 20+ sites â tap a line for full grammar-point breakdowns, not just dictionary entries."},{icon:Sf,title:"Save words straight to your decks",body:"Found a word worth keeping? Send it to your SRS decks without leaving the page youâre reading."}],nk=[{icon:Sr,title:"Process the episode in the app first",body:"In Immersion â Upload, add the episode as a Series or Movie and drop its .srt or .ass subtitle file. Leave analysis on and let it finish â this is what adds the grammar-aware annotations."},{icon:vo,title:"Install the extension & sign in",body:"Add the Shizen extension to your browser, then sign in with the same account. (Shift+hover lookups already work on every site at this point â this step is for the subtitle track.)"},{icon:gm,title:"On the streaming page, pull it back",body:"Open the extension on Netflix, YouTube, or any of 20+ sites, choose Enable Video Subtitles, open the âFrom Libraryâ tab, and pick the episode you processed. The grammar-enriched track now overlays the video."}];function rk(){return e.jsxs("div",{className:"space-y-8",style:{maxWidth:920,margin:"0 auto",width:"100%"},children:[e.jsx("div",{className:"wc-pencil-frame wc-pencil-frame--md",style:{position:"relative",isolation:"isolate",padding:"24px 28px"},children:e.jsxs("div",{style:{position:"relative",zIndex:1,display:"flex",flexDirection:"column",gap:18},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[e.jsx("p",{className:"serif",style:{margin:0,fontFamily:"'Shippori Mincho', serif",fontSize:20,fontWeight:600,color:"var(--ink)"},children:"Take Shizen across the web."}),e.jsx("p",{style:{margin:0,fontSize:14.5,lineHeight:1.6,color:"var(--ink-soft)"},children:"Install the extension and Shift+hover dictionary lookups work on every site straight away â no processing required. Process a showâs subtitles in Shizen first, and the extension brings that grammar-enriched, tappable track back onto the video youâre watching."})]}),e.jsx("ul",{style:{listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:12},children:sk.map(t=>{const a=t.icon;return e.jsxs("li",{style:{display:"flex",gap:14,alignItems:"flex-start"},children:[e.jsx("span",{"aria-hidden":"true",style:{flexShrink:0,width:38,height:38,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:"var(--wc-radius-leaf)",background:"hsl(var(--brand-chat) / 0.12)",border:"1px solid hsl(var(--brand-chat) / 0.20)",color:"hsl(var(--brand-chat))"},children:e.jsx(a,{size:19})}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2,paddingTop:1},children:[e.jsx("p",{style:{margin:0,fontSize:14.5,fontWeight:600,color:"var(--ink)"},children:t.title}),e.jsx("p",{style:{margin:0,fontSize:13.5,lineHeight:1.5,color:"var(--ink-soft)"},children:t.body})]})]},t.title)})})]})}),e.jsx("div",{className:"wc-pencil-frame wc-pencil-frame--md",style:{position:"relative",isolation:"isolate",padding:"24px 28px"},children:e.jsxs("div",{style:{position:"relative",zIndex:1,display:"flex",flexDirection:"column",gap:18},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[e.jsx("p",{className:"serif",style:{margin:0,fontFamily:"'Shippori Mincho', serif",fontSize:18,fontWeight:600,color:"var(--ink)"},children:"How grammar-enriched subtitles work"}),e.jsx("p",{style:{margin:0,fontSize:13.5,lineHeight:1.55,color:"var(--ink-soft)"},children:"Shift+hover lookups need none of this â they work the moment you install. The grammar-enriched subtitle track is the part that runs backwards: you process an episodeâs subtitles in Shizen first, then the extension overlays that track onto the video."})]}),e.jsx("ol",{style:{listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:14},children:nk.map((t,a)=>{const s=t.icon;return e.jsxs("li",{style:{display:"flex",gap:14,alignItems:"flex-start"},children:[e.jsxs("span",{"aria-hidden":"true",style:{position:"relative",flexShrink:0,width:40,height:40,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:"var(--wc-radius-leaf)",background:"hsl(var(--brand-chat) / 0.12)",border:"1px solid hsl(var(--brand-chat) / 0.20)",color:"hsl(var(--brand-chat))"},children:[e.jsx(s,{size:20}),e.jsx("span",{style:{position:"absolute",top:-6,left:-6,width:18,height:18,dis
89play:"flex",alignItems:"center",justifyContent:"center",borderRadius:"var(--wc-radius-ink)",background:"hsl(var(--brand-chat))",color:"#fff",fontSize:11,fontWeight:600,fontFamily:"'JetBrains Mono', monospace"},children:a+1})]}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2,paddingTop:1},children:[e.jsx("p",{style:{margin:0,fontSize:14.5,fontWeight:600,color:"var(--ink)"},children:t.title}),e.jsx("p",{style:{margin:0,fontSize:13.5,lineHeight:1.5,color:"var(--ink-soft)"},children:t.body})]})]},t.title)})}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:16,flexWrap:"wrap",borderTop:"1px solid var(--wc-hairline)",paddingTop:18},children:[e.jsx(ac,{href:ak,target:"_blank",rel:"noopener noreferrer",variant:"dusk",children:"Add to Chrome"}),e.jsx("span",{style:{fontSize:12.5,color:"var(--ink-soft)",opacity:.85},children:"Available now on the Chrome Web Store. Firefox Add-ons coming soon."})]})]})})]})}function Qi(t,a,s){if(s&&s.status!=="idle")return s;switch(t){case"synced":return{status:"synced"};case"uploading":return{status:"interrupted"};case"error":return{status:"error",retryable:!0,message:"Sync failed"};default:return{status:"idle"}}}function lp({state:t,onRetry:a,retryUnavailable:s=!1,isPro:n=!0,variant:r="badge"}){if(!n)return null;const i=r==="inline"?"im-cloud-sync im-cloud-sync--inline":"im-cloud-sync";switch(t.status){case"queued":return e.jsxs("span",{className:`${i} is-queued`,title:"Queued for cloud sync",children:[e.jsx("span",{className:"im-cloud-sync-dot is-static","aria-hidden":"true"}),e.jsx("span",{className:"im-cloud-sync-count",children:"Queued"})]});case"uploading":return e.jsxs("span",{className:`${i} is-uploading`,title:"Syncing to your cloud library",children:[e.jsx("span",{className:"im-cloud-sync-dot","aria-hidden":"true"}),e.jsx("span",{className:"im-cloud-sync-count",children:t.total>0?`${t.uploaded}/${t.total}`:"Syncing"})]});case"synced":return e.jsx("span",{className:`${i} is-synced`,title:"Synced to your cloud library",children:e.jsx(Js,{"aria-hidden":"true"})});case"quota_exceeded":return e.jsxs("span",{className:`${i} is-warn`,title:$a()?"Cloud library full â remove something or upgrade":"Cloud library full â free up space",children:[e.jsx(Qa,{"aria-hidden":"true"}),e.jsx("span",{className:"im-cloud-sync-count",children:"Cloud full"})]});case"interrupted":return e.jsxs("span",{className:`${i} is-warn`,title:"A previous sync was interrupted",children:[e.jsx(Qa,{"aria-hidden":"true"}),e.jsx("span",{className:"im-cloud-sync-count",children:s?"Resume from the device with the files":"Sync interrupted"}),!s&&a&&e.jsx("button",{type:"button",className:"im-cloud-sync-retry",onClick:l=>{l.stopPropagation(),a()},children:"Retry"})]});case"error":return e.jsxs("span",{className:`${i} is-warn`,title:"Cloud sync failed",children:[e.jsx(Qa,{"aria-hidden":"true"}),s?e.jsx("span",{className:"im-cloud-sync-count",children:"Resume from the device with the files"}):a?e.jsx("button",{type:"button",className:"im-cloud-sync-retry",onClick:l=>{l.stopPropagation(),a()},children:"Retry sync"}):e.jsx("span",{className:"im-cloud-sync-count",children:"Sync failed"})]});default:return null}}function Wc(t="actions"){const[a,s]=o.useState(t),n=o.useCallback(()=>s("actions"),[]);return{mode:a,setMode:s,reset:n,isActions:a==="actions",isManage:a==="manage",isAddToSeries:a==="addToSeries",isCreateSeries:a==="createSeries",isConfirmingDelete:a==="confirmDelete"}}function Ro(t){return t.content_type==="novel"?t.total_text_boxes??0:t.total_pages??0}function Gc(t){if(t.enrichment_status==="partial")return!0;const a=Ro(t);return t.enriched_page_limit!=null&&a>0&&t.enriched_page_limit<a}function cp(t){const a=Ro(t);return t.enriched_page_limit!=null&&a>0&&t.enriched_page_limit<a?t.enriched_page_limit:null}const Va=new Intl.NumberFormat;function Su(t){if(t<=0)return"No additional cloud storage";const a=["B","KB","MB","GB"];let s=t,n=0;for(;s>=1024&&n<a.length-1;)s/=1024,n+=1;return`${s>=10||n===0?Math.round(s):s.toFixed(1)} ${a[n]}`}function ik(t){return t==null||t<=0?"":t<60?`about ${Math.max(1,Math.ceil(t/5)*5)} sec left`:`about ${Math.ceil(t/60)} min left`}function ok(){const t=o.useRef(null),[a,s]=o.useState(()=>typeof IntersectionObserver>"u");return o.useEffect(()=>{if(a||!t.current||typeof IntersectionObserver>"u")return;const n=new IntersectionObserver(([r])=>{r.isIntersecting&&(s(!0),n.disconnect())},{rootMargin:"240px 0px"});return n.observe(t.current),()=>n.disconnect()},[a]),[t,a]}function Nu(t){switch(t){case"queued":return"Queued";case"publishing_deck":return"Publishing word deck";case"waiting_for_source":return"Waiting for cloud source";case"planning_media":return"Checking missing media";case"media_queued":return"Media queued";case"media_active":return"Creating media";case"complete":return"Study build complete";case"partial":return"Affordable media complete";case"stopped":return"Remaining media stopped";case"failed":return"Study build needs attention";default:return"Updating study build"}}function vi({sourceKind:t,sourceId:a,presentation:s="card",hasDeck:n=!1,featureEnabled:r=Og(),className:i="",onDeckReady:l}){const[c,d]=ok(),m=o.useMemo(()=>({kind:t,id:a}),[a,t]),u=Bg(m,r&&d),{openUpgradeModal:h}=xn(),[p,g]=o.useState(n?"deck_with_media":"deck_only"),[f,b]=o.useState(!1),[y,x]=o.use
89State(!1),v=o.useRef(null),w=o.useRef(null),j=o.useRef(null),T=o.useRef(null),P=u.snapshot,N=P?.plan??null,_=P?.build??null,L=P?.source.role??(t==="reading_material"?"image":"video_clip"),q=L==="image"?"panel image":"memory clip",O=L==="image"?"panel images":"memory clips",A=!!(N&&N.mediaEligibleCount>0&&N.affordableMediaCount>0);o.useEffect(()=>{const U=_?.deck.deckId??null;U&&U!==v.current&&(v.current=U,l?.(U))},[_?.deck.deckId,l]),o.useEffect(()=>{g(n?"deck_with_media":"deck_only"),b(!1),x(!1),w.current=null},[n,a]);const k=U=>{U&&g(U),w.current=crypto.randomUUID(),b(!0)},J=U=>{["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"].includes(U.key)&&(U.preventDefault(),p==="deck_only"&&A?(g("deck_with_media"),T.current?.focus()):(g("deck_only"),j.current?.focus()))},M=async()=>{if(!N||N.state!=="ready")return;const U={mode:p,idempotencyKey:w.current??crypto.randomUUID(),...p==="deck_with_media"?{productCopyVersion:N.productCopyVersion,consentVersion:N.consentVersion,confirmedCreditUnits:N.creditUnits}:{}};await u.create(U)&&(w.current=null,b(!1),x(!1))},H=()=>{if(!N||N.state!=="ready"){u.requestPlan();return}u.create({mode:_?.mode??p,idempotencyKey:crypto.randomUUID(),...(_?.mode??p)==="deck_with_media"?{productCopyVersion:N.productCopyVersion,consentVersion:N.consentVersion,confirmedCreditUnits:N.creditUnits}:{}})},ee=_?.recoveryAction??"none",Pe=!!(_&&N?.state==="ready"&&N.continuationForBuildId===_.id),D=!!(Pe&&N&&N.affordableMediaCount>0),de=(()=>{switch(ee){case"refresh_plan":return{label:"Refresh exact counts",run:()=>{u.requestPlan()}};case"buy_credits":return{label:"View plans",run:()=>h("media_mnemonics","study_build_shortfall")};case"free_storage":return{label:"Check storage again",run:()=>{u.continueMedia()}};case"retry":return{label:"Retry",run:H};case"stop_media":return{label:`Stop remaining ${O}`,run:()=>{u.stopMedia()},quiet:!0};case"continue_media":return{label:D?"Confirm remaining media":Pe&&N?.limitingConstraint==="credits"?"View plans":Pe&&N?.limitingConstraint==="storage"?"Check storage again":"Get exact quote",run:Pe&&N?.limitingConstraint==="credits"?()=>h("media_mnemonics","study_build_shortfall"):()=>{u.continueMedia()}};case"wait_for_source":return{label:"Check source",run:()=>{u.refresh()},quiet:!0};default:return null}})();if(!r)return null;const fe=`study-build study-build--${s} ${i}`.trim(),Me=_?Nu(_.state):N?`Study plan ${N.state}`:"Preparing study plan";return e.jsxs("div",{ref:c,className:fe,onClick:U=>U.stopPropagation(),onKeyDown:U=>U.stopPropagation(),children:[e.jsx("span",{className:"study-build-sr","aria-live":"polite","aria-atomic":"true",children:Me}),!d&&e.jsx("span",{className:"study-build-placeholder","aria-hidden":"true"}),d&&!_&&(u.loading||!P||N?.state==="queued"||N?.state==="planning")&&e.jsxs("div",{className:"study-build-planning",role:"status",children:[e.jsx("span",{className:"study-build-ink-pulse","aria-hidden":"true"}),e.jsxs("span",{children:["Preparing exact deck and ",q," countsâ¦"]})]}),d&&P&&!P.orchestratorEnabled&&e.jsx("p",{className:"study-build-note",children:"Study building is temporarily unavailable. Your material is safe."}),d&&u.error&&e.jsxs("div",{className:"study-build-recovery",role:"alert",children:[e.jsx("span",{children:u.error}),e.jsx("button",{type:"button",className:"study-build-link",onClick:()=>{u.refreshAndPlan()},children:"Try again"})]}),d&&!_&&N&&["failed","expired","superseded"].includes(N.state)&&e.jsxs("div",{className:"study-build-recovery",children:[e.jsx("span",{children:N.failureReason||"The source changed before the exact plan was confirmed."}),e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk",onClick:()=>{u.requestPlan()},disabled:u.mutating,children:[e.jsx(Hn,{"aria-hidden":"true"})," Replan"]})]}),d&&!_&&N?.state==="ready"&&!f&&!n&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"study-build-heading",children:[e.jsx("strong",{children:"Build study deck"}),e.jsxs("span",{children:[Va.format(N.cardCount)," new cards"]})]}),e.jsxs("div",{className:"study-build-choices",role:"radiogroup","aria-label":"Study deck type",onKeyDown:J,children:[e.jsxs("label",{className:p==="deck_only"?"is-selected":"",children:[e.jsx("input",{ref:j,type:"radio",name:`study-build-${t}-${a}`,value:"deck_only",checked:p==="deck_only",onChange:()=>g("deck_only")}),e.jsx("span",{className:"study-build-choice-mark","aria-hidden":"true",children:p==="deck_only"?e.jsx(Ys,{}):e.jsx(jf,{})}),e.jsxs("span",{children:[e.jsx("strong",{children:"Word deck"}),e.jsxs("small",{children:[Va.format(N.cardCount)," cards · Free"]})]})]}),e.jsxs("label",{className:`${p==="deck_with_media"?"is-selected":""} ${A?"":"is-disabled"}`.trim(),children:[e.jsx("input",{ref:T,type:"radio",name:`study-build-${t}-${a}`,value:"deck_with_media",checked:p==="deck_with_media",onChange:()=>g("deck_with_media"),disabled:!A}),e.jsx("span",{className:"study-build-choice-mark","aria-hidden":"true",children:L==="image"?e.jsx(Gr,{}):e.jsx(on,{})}),e.jsxs("span",{children:[e.jsxs("strong",{children:["Word deck + ",O]}),e.jsx("small",{children:A?`${Va.format(N.cardCount)} cards · ${Va.format(N.affordableMediaCount)} ${O} · Premium`:`No ${O} can be created now · Word deck remains free`})]})]})]}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink study-build-primary",onClick:()=>k(),children:"Continue"}),!A&&N.mediaEligibleCount>0&&N.limitingConstraint!=="none"&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk",onClick:N.limitingConstraint==="credits"?()=>h("media_mnemonics","study_build_shortfall"):()=>{u.requestPlan()},disabled:u.mutating,children:[N.limitingConstraint==="credits"?e.jsx(yd,{"aria-hidden":"true"}):e.jsx(Hn,{"aria-hidden":"true"}),N.limitingConstraint==="credits"?"View plans":"Check storage again"]})]}),d&&!_&&N?.state==="ready"&&!f&&n&&A&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--ink study-build-primary",onClick:()=>k("deck_with_media"),children:[L==="image"?e.jsx(Gr,{"aria-hidden":"true"}):e.jsx(on,{"aria-hidden":"true"}),"Add ",O]}),d&&!_&&N?.state==="ready"&&!f&&n&&!A&&e.jsx("p",{className:"study-build-note",children:N.existingMediaCount>0&&N.mediaEligibleCount===0?`All eligible words already have ${O}.`:`No missing ${O} can be created right now.`}),d&&!_&&N?.state==="ready"&&f&&e.jsxs("div",{className:"study-build-confirm","aria-label":"Confirm study build",children:[e.jsxs("div",{className:"study-build-heading",children:[e.jsx("strong",{children:p==="deck_only"?"Create free word deck":`Create deck with ${O}`}),e.jsxs("span",{children:[Va.format(N.cardCount)," cards"]})]}),p==="deck_with_media"?e.jsxs(e.Fragment,{children:[e.jsxs("dl",{className:"study-build-quote",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Media now"}),e.jsxs("dd",{children:[Va.format(N.affordableMediaCount)," / ",Va.format(N.mediaEligibleCount)]})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Exact reservation"}),e.jsxs("dd",{children:[Va.format(N.creditUnits)," credits"]})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Remaining later"}),e.jsx("dd",{children:Va.format(N.remainderCount)})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Estimated storage"}),e.jsx("dd",{children:Su(N.estimatedStorageBytes)})]})]}),e.jsxs("p",{className:"study-build-note",children:["Existing media is kept. Missing ",O," are created in source order; unused reserved credits are refunded."]}),e.jsxs("label",{className:"study-build-consent",children:[e.jsx("input",{type:"checkbox",checked:y,onChange:U=>x(U.target.checked)}),e.jsx("span",{children:"I approve this exact credit reservation and separate cloud storage use."})]})]}):e.jsx("p",{className:"study-build-note",children:"Creates the complete new-word deck with
89no media work, credit reservation, or storage use."}),e.jsxs("div",{className:"study-build-actions",children:[e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink",onClick:()=>{w.current=null,b(!1),x(!1)},disabled:u.mutating,children:"Cancel"}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:()=>{M()},disabled:u.mutating||p==="deck_with_media"&&(!y||!A),children:u.mutating?"Queuingâ¦":p==="deck_only"?"Create word deck":"Create deck + media"})]})]}),d&&_&&e.jsxs("div",{className:`study-build-progress is-${_.state}`,children:[e.jsxs("div",{className:"study-build-heading",children:[e.jsx("strong",{children:Nu(_.state)}),_.reason&&!["user_stopped_media","media_stopped"].includes(_.reason)&&e.jsx("span",{children:_.reason})]}),e.jsxs("div",{className:"study-build-phase",children:[e.jsx("span",{className:"study-build-phase-icon","aria-hidden":"true",children:_.deck.state==="complete"||_.deck.state==="all_known"?e.jsx(Ys,{}):e.jsx(Js,{})}),e.jsxs("span",{children:[e.jsx("strong",{children:"Word deck"}),e.jsx("small",{children:_.deck.state==="all_known"?"All words already known · no deck created":`${Va.format(_.deck.publishedCount)} / ${Va.format(_.deck.cardCount)} cards · ${_.deck.state.replace("_"," ")}`})]})]}),_.mode==="deck_with_media"&&e.jsxs("div",{className:"study-build-phase",children:[e.jsx("span",{className:"study-build-phase-icon","aria-hidden":"true",children:L==="image"?e.jsx(Gr,{}):e.jsx(on,{})}),e.jsxs("span",{children:[e.jsx("strong",{children:O[0].toUpperCase()+O.slice(1)}),e.jsxs("small",{children:[Va.format(_.media.readyCount)," / ",Va.format(_.media.selectedCount)," ready · ",_.media.state.replace(/_/g," "),_.media.state==="processing"&&_.media.estimatedRemainingSeconds!=null?` · ${ik(_.media.estimatedRemainingSeconds)}`:""]})]})]}),["complete","partial","stopped"].includes(_.state)&&e.jsxs("p",{className:"study-build-note",children:[Va.format(_.deck.publishedCount)," cards · ",Va.format(_.media.readyCount)," media ready · ",Va.format(_.media.unsupportedCount)," unsupported",_.media.remainderCount>0?` · ${Va.format(_.media.remainderCount)} remaining`:""]}),_.deck.deckId&&["complete","partial","stopped"].includes(_.state)&&e.jsx("div",{className:"study-build-actions",children:e.jsxs("a",{className:"wc-cta-square wc-cta-square-secondary--dusk",href:`/vocabulary/decks/mine?deckId=${encodeURIComponent(_.deck.deckId)}`,children:[e.jsx(ss,{"aria-hidden":"true"})," Open deck"]})}),ee==="continue_media"&&D&&N&&e.jsxs("div",{className:"study-build-confirm study-build-continuation","aria-label":"Confirm remaining media",children:[e.jsxs("div",{className:"study-build-heading",children:[e.jsxs("strong",{children:["Continue remaining ",O]}),e.jsxs("span",{children:[Va.format(N.affordableMediaCount)," now"]})]}),e.jsxs("dl",{className:"study-build-quote",children:[e.jsxs("div",{children:[e.jsx("dt",{children:"Media now"}),e.jsxs("dd",{children:[Va.format(N.affordableMediaCount)," / ",Va.format(N.mediaEligibleCount)]})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Exact reservation"}),e.jsxs("dd",{children:[Va.format(N.creditUnits)," credits"]})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Remaining later"}),e.jsx("dd",{children:Va.format(N.remainderCount)})]}),e.jsxs("div",{children:[e.jsx("dt",{children:"Estimated storage"}),e.jsx("dd",{children:Su(N.estimatedStorageBytes)})]})]}),e.jsxs("label",{className:"study-build-consent",children:[e.jsx("input",{type:"checkbox",checked:y,onChange:U=>x(U.target.checked)}),e.jsx("span",{children:"I approve this fresh exact credit reservation and separate cloud storage use."})]})]}),de&&e.jsx("div",{className:"study-build-actions",children:e.jsxs("button",{type:"button",className:`wc-cta-square ${de.quiet?"wc-cta-square-quiet--ink":"wc-cta-square-secondary--dusk"}`,onClick:de.run,disabled:u.mutating||ee==="continue_media"&&D&&!y,children:[ee==="buy_credits"?e.jsx(yd,{"aria-hidden":"true"}):ee==="stop_media"?e.jsx(rs,{"aria-hidden":"true"}):e.jsx(Hn,{"aria-hidden":"true"}),de.label]})})]})]})}const lk=t=>t==="local_only"?"Local":t,ck=t=>{switch(t){case"completed":return e.jsx(rn,{});case"local_only":return e.jsx(Gs,{});case"processing":return e.jsx(Sa,{className:"animate-spin"});
89case"pending":return e.jsx(Yn,{});case"error":return e.jsx(Qa,{});default:return e.jsx(Rn,{})}};function dk({material:t,coverage:a,onSelect:s,onDelete:n,onRetry:r,onProcess:i,onProcessRemaining:l,onCreateDeck:c,onViewDeck:d,onAddToSeries:m,onCreateSeries:u,isDeleting:h,isCreatingDeck:p,availableSeries:g,cloudSyncState:f,onRetrySync:b,onSyncToCloud:y,isPro:x=!1,onUnsynced:v,isPinned:w=!1,onTogglePin:j,onRenamed:T}){const{getAccessToken:P}=ps(),N=Qi(t.cloud_sync_status,t.total_pages,f),{mode:_,setMode:L}=Wc(),[q,O]=o.useState(""),A=t.processing_status==="completed"||t.processing_status==="local_only",k=t.content_type==="novel",J=Gc(t),M=cp(t),H=Ro(t),ee=Ur(t),Pe=t.processing_status==="completed"&&(t.enrichment_status==="pending"||t.enrichment_status==="processing"),[D,de]=o.useState(""),[fe,Me]=o.useState(!1),[U,ve]=o.useState(null),yt=async()=>{const K=D.trim();if(!K||K===t.title){L("actions");return}Me(!0),ve(null);try{const _t=await P();if(!_t){ve("Please log in first");return}(await fetch(`${ue()}/api/reading/materials/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${_t}`},body:JSON.stringify({title:K})})).ok?(T?.(t.id,K),L("actions")):ve("Could not rename. Please try again.")}catch{ve("Could not rename. Please try again.")}finally{Me(!1)}},[ut,St]=o.useState(!1),je=t.cloud_sync_status==="synced";o.useEffect(()=>{if(!t.local_images||je){St(!1);return}let K=!1;return(t.file_type==="epub"?li(t.id):oi(t.id)).then(sa=>{K||St(!sa)}).catch(()=>{K||St(!0)}),()=>{K=!0}},[t.id,t.local_images,t.file_type,je]);const lt=je&&w,[Et,Ct]=o.useState(null),[aa,vt]=o.useState(!1),[Le,jt]=o.useState(null),Ft=je&&Et===null&&(_==="manage"||_==="confirmUnsync");o.useEffect(()=>{if(!je){Ct(null);return}if(_!=="manage"&&_!=="confirmUnsync"||Et!==null)return;let K=!1;return(t.file_type==="epub"?li(t.id):oi(t.id)).then(sa=>{K||Ct(sa)}).catch(()=>{K||Ct(!1)}),()=>{K=!0}},[t.id,t.file_type,je,_,Et]),o.useEffect(()=>{_==="actions"&&(Ct(null),jt(null))},[_]);const ct=async()=>{vt(!0),jt(null);try{const K=await go(t.id,P,void 0,{kind:t.file_type==="epub"?"epub":"manga",bytes:t.cloud_size_bytes??void 0});K.ok?(v?.(t.id),L("actions")):jt(K.message??"Could not remove from cloud")}finally{vt(!1)}},[se,ft]=o.useState(null),[Oe,pt]=o.useState(0),[kt,Ve]=o.useState(!1),Be=To({material:{id:t.id,content_type:t.content_type??null,file_type:t.file_type??null,total_pages:t.total_pages??null,content_sha256:t.content_sha256??null,original_filename:t.original_filename??null,file_size_bytes:t.file_size_bytes??null},onRestored:()=>{St(!1),Ve(!1),pt(K=>K+1)}});o.useEffect(()=>{if(t.cover_image_url||k||t.processing_status!=="completed"&&t.processing_status!=="local_only")return;let K=!1,_t=null;return t.local_images?Nm(t.id,1).then(qt=>{!K&&qt?(_t=qt,ft(qt)):qt&&URL.revokeObjectURL(qt)}):P().then(qt=>{K||!qt||fetch(`${ue()}/api/reading/materials/${t.id}/pages?range=1-1&size=512w`,{headers:{Authorization:`Bearer ${qt}`}}).then(sa=>sa.ok?sa.json():null).then(sa=>{!K&&sa?.pages?.[0]?.imageUrl&&ft(sa.pages[0].imageUrl)}).catch(()=>{})}),()=>{K=!0,_t&&URL.revokeObjectURL(_t)}},[t.id,t.local_images,t.processing_status,k,P,Oe]);const Ke=()=>{A&&s(t.id)},At=t.cover_image_url,ta=At||(!k&&!At&&se?se:null),zt=ut||t.processing_status==="error"?"im-library-card-chip--warn":t.processing_status==="completed"?"im-library-card-chip--ok":t.processing_status==="processing"||t.processing_status==="pending"?"im-library-card-chip--busy":"";return e.jsxs(ds,{as:"div",size:"md",className:"im-library-card",onClick:A?Ke:void 0,onKeyDown:K=>{A&&(K.key==="Enter"||K.key===" ")&&(K.preventDefault(),Ke())},animate:!1,children:[e.jsx(ds.Cover,{className:"im-library-card-cover",children:ta?e.jsx("img",{src:ta,alt:t.title,loading:"lazy",decoding:"async"}):e.jsx(wi,{title:t.title,titleJp:t.title_jp??void 0})}),e.jsx("div",{className:"im-library-card-main",children:e.jsx(Oa,{mode:"wait",initial:!1,children:_==="actions"?e.jsxs(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},style:{display:"flex",flexDirection:"column",flex:1},children:[e.jsxs("div",{className:"im-library-card-body",children:[e.jsxs("div",{className:"im-library-card-tags",children:[e.jsx("span",{className:"im-library-card-chip",children:k?"Novel":"Manga"}),e.jsxs("span",{className:`im-library-card-chip ${zt}`,children:[ut?e.jsx(ii,{}):ck(t.processing_status),e.jsx("span",{children:ut?"Re-import":lk(t.processing_status)})]}),e.jsx(lp,{state:N,isPro:x,retryUnavailable:ut,onRetry:b?()=>b(t.id):void 0,variant:"inline"}),x&<&&e.jsxs("span",{className:"im-library-card-chip",title:"Kept offline on this device",children:[e.jsx(cd,{"aria-hidden":"true"})," Offline"]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"im-library-card-title",children:t.title}),t.title_jp&&e.jsx("p",{className:"im-library-card-title-jp",children:t.title_jp})]}),(t.author||t.series)&&e.jsxs("div",{className:"im-library-card-meta",children:[t.author&&e.jsx("span",{children:t.author}),t.series&&e.jsxs("span",{children:[t.series,t.volume&&` Vol. ${t.volume}`,t.chapter&&` Ch. ${t.chapter}`]})]}),t.processing_status==="completed"&&t.total_pages>0&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-library-card-meta",children:[e.jsxs("span",{children:[t.current_page,"/",t.total_pages," ",k?"ch.":"pg."]}),e.jsxs("span",{children:[e.jsx(Rn,{}),t.total_text_boxes]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${t.current_page/t.total_pages*100}%`}})})]}),t.processing_status==="completed"&&(t.unique_vocab_count??0)>0&&e.jsxs("span",{className:"im-library-card-vocab-chip",children:[e.jsx(Gs,{}),(t.unique_vocab_count??0).toLocaleString()]}),J&&e.jsxs("span",{className:"im-library-card-partial",title:"Analysis stopped when shared credits ran out â finish analyzing below",children:[e.jsx(Qa,{}),"Partially analyzed",e.jsx("span",{className:"ratio",children:M!=null&&M>0&&H>0?`· ${M}/${H} · shared credits ran out`:"· shared credits ran out"})]}),t.processing_status==="completed"&&a&&(a.vocabTotal>0||a.grammarTotal>0)&&e.jsxs("div",{className:"im-library-card-coverage",children:[e.jsx("span",{className:"im-library-card-coverage-label",children:"Knowledge Coverage"}),a.vocabTotal>0&&e.jsxs("div",{className:"im-library-card-coverage-row",children:[e.jsxs("div",{className:"head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(Gs,{}),"Vocab"]}),e.jsxs("span",{className:"val",children:[a.vocabPct!=null?`${a.vocabPct}%`:"0%",e.jsxs("span",{className:"ratio",children:["(",a.vocabKnown,"/",a.vocabTotal,")"]})]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${a.vocabPct??0}%`}})})]}),a.grammarTotal>0&&e.jsxs("div",{className:"im-library-card-coverage-row",children:[e.jsxs("div",{className:"head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(Rn,{}),"Grammar"]}),e.jsxs("span",{className:"val",children:[a.grammarPct!=null?`${a.grammarPct}%`:"0%",e.jsxs("span",{className:"ratio",children:["(",a.grammarKnown,"/",a.grammarTotal,")"]})]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${a.grammarPct??0}%`}})})]})]}),t.content_type==="manga"&&(!!t.deck_id||t.processing_status==="completed"&&t.enrichment_status==="completed")&&e.jsx(vi,{sourceKind:"reading_material",sourceId:t.id,hasDeck:!!t.deck_id,presentation:"card"}),!1,t.processing_status==="error"&&t.processing_error&&e.jsxs("div",{className:"im-library-card-error",children:[e.jsx(Qa,{}),e.jsx("span",{children:t.processing_error})]}),t.last_read_at&&e.jsxs("span",{className:"im-library-card-last",children:[e.jsx(Yn,{}),"Last read · ",new Date(t.last_read_at).toLocaleDateString()]})]}),e.jsxs("div",{className:"im-library-card-footer",children:[e.jsx("div",{className:"im-library-card-footer-row is-stretch",children:t.processing_status==="completed"||t.processing_status==="local_only"?e.jsx("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-library-card-cta",onClick:K=>{K.stopPropagation(),ut?(Be.reset(),Ve(!0)):s(t.id)},children:ut?e.jsxs(e.Fragment,{children:[e.jsx(ii,{})," Re-import"]}):e.jsxs(e.Fragment,{children:[e.jsx(ri,{})," Read"]})}):t.processing_status==="processing"?e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",disabled:!0,children:[e.jsx(Sa,{className:"animate-spin"})," Processingâ¦"]}):t.processing_status==="error"&&ee==="analyze"?e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",onClick:K=>
89{K.stopPropagation(),r(t.id)},children:[e.jsx(pi,{})," Retry"]}):ee==="analyze"?e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",onClick:K=>{K.stopPropagation(),i(t.id)},children:[e.jsx(vs,{})," Analyze"]}):e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",disabled:!0,children:[e.jsx(Qa,{})," No text found"]})}),e.jsxs("div",{className:"im-library-card-footer-row",children:[t.processing_status==="local_only"&&ee==="analyze"&&e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",onClick:K=>{K.stopPropagation(),i(t.id)},children:[e.jsx(vs,{})," Analyze"]}),Pe?e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",disabled:!0,children:[e.jsx(Sa,{className:"animate-spin"})," Finishing analysisâ¦"]}):t.processing_status==="completed"&&J?e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-library-card-cta-quiet",onClick:K=>{K.stopPropagation(),l(t.id)},children:[e.jsx(vs,{})," Finish analyzing"]}):Pe?e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",disabled:!0,children:[e.jsx(Sa,{className:"animate-spin"})," Finishing analysisâ¦"]}):t.processing_status==="completed"&&ee==="analyze"&&e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",onClick:K=>{K.stopPropagation(),i(t.id)},children:[e.jsx(vs,{})," Analyze"]}),t.processing_status==="completed"&&(t.unique_vocab_count??0)>0&&(t.deck_id?e.jsxs("button",{className:"wc-cta-square im-library-card-cta-quiet",onClick:K=>{K.stopPropagation(),d(t.deck_id)},children:[e.jsx(fd,{})," View deck"]}):k?e.jsx("button",{className:"wc-cta-square im-library-card-cta-quiet",onClick:K=>{K.stopPropagation(),c(t.id)},disabled:p,children:p?e.jsxs(e.Fragment,{children:[e.jsx(Sa,{className:"animate-spin"})," Creatingâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsx(fd,{})," Create deck"]})}):null),e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",style:{marginLeft:"auto","--wc-cta-sq-h":"28px","--wc-cta-sq-bw":"8px 10px"},onClick:K=>{K.stopPropagation(),L("manage")},"aria-label":"More actions",children:e.jsx(jo,{})})]})]})]},"actions"):e.jsxs(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:`im-library-card-footer${_==="manage"?" is-manage-menu":""}`,style:{flex:1,borderTop:"none"},children:[_==="manage"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-library-card-footer-row",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",onClick:K=>{K.stopPropagation(),L("actions")},"aria-label":"Back",children:e.jsx(Za,{})}),e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",style:{marginLeft:"auto"},onClick:K=>{K.stopPropagation(),L("confirmDelete")},"aria-label":"Delete",children:e.jsx(Ns,{})})]}),e.jsxs("div",{className:"im-library-card-menulist",children:[e.jsxs("button",{onClick:K=>{K.stopPropagation(),de(t.title),ve(null),L("rename")},children:[e.jsx(xr,{})," Rename",e.jsx(As,{className:"chev"})]}),!t.manga_series_id&&e.jsxs("button",{onClick:K=>{K.stopPropagation(),L("addToSeries")},children:[e.jsx(so,{})," Add to series",e.jsx(As,{className:"chev"})]}),!t.manga_series_id&&e.jsxs("button",{onClick:K=>{K.stopPropagation(),L("createSeries")},children:[e.jsx(pd,{})," New series",e.jsx(As,{className:"chev"})]}),x&&!je&&t.local_images&&N.status==="idle"&&y&&e.jsxs("button",{onClick:K=>{K.stopPropagation(),y(t.id),L("actions")},children:[e.jsx(Js,{})," Sync to cloud"]}),x&&je&&j&&e.jsx("button",{onClick:K=>{K.stopPropagation(),j(t.id)},children:lt?e.jsxs(e.Fragment,{children:[e.jsx(tf,{})," Don't keep offline"]}):e.jsxs(e.Fragment,{children:[e.jsx(cd,{})," Keep offline"]})}),x&&je&&e.jsxs("button",{onClick:K=>{K.stopPropagation(),L("confirmUnsync")},children:[e.jsx(Ws,{})," Remove from cloud",e.jsx(As,{className:"chev"})]})]})]}),_==="addToSeries"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-library-card-footer-row",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",onClick:K=>{K.stopPropagation(),L("manage")},"aria-label":"Back",children:e.jsx(Za,{})}),e.jsx("span",{className:"im-library-card-modehead",children:"Add to series"})]}),e.jsx("div",{className:"im-library-card-menulist",children:(()=>{const K=g.filter(_t=>!_t.content_type||_t.content_type===t.content_type);return K.length===0?e.jsxs("div",{className:"empty",children:["No ",t.content_type??"matching"," series yet â create one first"]}):K.map(_t=>e.jsxs("button",{onClick:qt=>{qt.stopPropagation(),m(t.id,_t.id),L("actions")},children:[e.jsx("span",{style:{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",flex:1},children:_t.title}),e.jsx(As,{className:"chev"})]},_t.id))})()})]}),_==="createSeries"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-library-card-footer-row",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",onClick:K=>{K.stopPropagation(),L("manage"),O("")},"aria-label":"Back",children:e.jsx(Za,{})}),e.jsx("span",{className:"im-library-card-modehead",children:"New series"})]}),e.jsx("input",{type:"text",className:"im-library-card-input",value:q,onChange:K=>O(K.target.value),placeholder:"Series titleâ¦",onClick:K=>K.stopPropagation(),onKeyDown:K=>{K.stopPropagation(),K.key==="Enter"&&q.trim()&&(u(t.id,q.trim()),L("actions"),O("")),K.key==="Escape"&&(L("manage"),O(""))},autoFocus:!0}),e.jsxs("div",{className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-cancel",onClick:K=>{K.stopPropagation(),L("manage"),O("")},children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--ink im-library-card-cta",onClick:K=>{K.stopPropagation(),u(t.id,q.trim()),L("actions"),O("")},disabled:!q.trim(),children:[e.jsx(pd,{})," Create"]})]})]}),_==="rename"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-library-card-footer-row",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",onClick:K=>{K.stopPropagation(),L("manage")},"aria-label":"Back",children:e.jsx(Za,{})}),e.jsx("span",{className:"im-library-card-modehead",children:"Rename"})]}),e.jsx("input",{type:"text",className:"im-library-card-input",value:D,onChange:K=>de(K.target.value),placeholder:"Titleâ¦",onClick:K=>K.stopPropagation(),onKeyDown:K=>{K.stopPropagation(),K.key==="Enter"&&D.trim()&&yt(),K.key==="Escape"&&L("manage")},disabled:fe,autoFocus:!0}),U&&e.jsx("p",{className:"im-library-card-unsync-error",role:"alert",children:U}),e.jsxs("div",{className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{className:"wc-cta-square wc-cta-square-quiet--ink im-library-card-cta",onClick:K=>{K.stopPropagation(),L("manage")},disabled:fe,children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--ink im-library-card-cta",onClick:K=>{K.stopPropagation(),yt()},disabled:fe||!D.trim()||D.trim()===t.title,children:[fe?e.jsx(Sa,{className:"animate-spin"}):e.jsx(xr,{}),"Save"]})]})]}),_==="confirmDelete"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"im-library-card-modehead",style:{marginBottom:4},children:"Delete this item?"}),e.jsxs("div",{className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-cancel",onClick:K=>{K.stopPropagation(),L("manage")},children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--maple im-library-card-cta",onClick:K=>{K.stopPropagation(),L("actions"),n(t.id)},disabled:h,children:[h?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ns,{}),"Delete"]})]})]}),_==="confirmUnsync"&&e.jsxs("div",{onClick:K=>K.stopPropagation(),onKeyDown:K=>K.stopPropagation(),children:[e.jsx("span",{className:"im-library-card-modehead",style:{marginBottom:4},children:"Remove from cloud?"}),e.jsxs("p",{className:"im-library-card-unsync-copy",children:["Removes the cloud copy. Your vocab, OCR text and progress are kept",Et===!1&&e.jsxs(e.Fragment,{children:[" ","â but to read it again you'll need the original file"]}),"."]}),Le&&e.jsx("p",{className:"im-library-card-unsync-error",role:"alert",children:Le}),e.jsxs("div",{className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{className:"wc-cta-square wc-cta-square-quiet--ink im-library-card-cta",onClick:K=>{K.stopPropagation(),L("manage")},disabled:aa,children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--maple im-library-card-cta",onClick:K=>{K.stopPropagation(),ct()},disabled:aa||Ft,children:[aa?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ws,{}),"Remove"]})]})]})]},"manage")})}),kt&&e.jsx(Mo,{restore:Be,title:k?"Local file missing":"Local images missing",filenameHint:t.original_filename??null,detailHint:k?t.file_size_bytes!=null?`${(t.file_size_bytes/(1024*1024)).toFixed(1)} MB`:null:t.total_pages>0?`${t.total_pages} pages`:null,portal:!0,dismissable:!0,onClose:()=>{Be.reset(),Ve(!1)}})]})}const uk=o.memo(dk);function mk({series:t,onOpen:a,onDelete:s,isDeleting:n,coverage:r,onCreateDeck:i,creatingDeckForId:l}){const{isConfirmingDelete:c,isManage:d,setMode:m,reset:u}=Wc(),h=t.reading_materials.reduce((j,T)=>j+(T.total_pages||0),0),p=t.reading_materials.reduce((j,T)=>j+(T.current_page||0),0),g=h>0?Math.round(p/h*100):0,f=t.reading_materials.length,b=t.reading_materials.filter(j=>j.processing_status==="completed").length,y=b===f&&f>0,x=f===1?t.reading_materials[0]:null;t.reading_materials.filter(j=>!!j.deck_id),x&&x.processing_status==="completed"&&x.enrichment_status==="completed"&&(x.unique_vocab_count??0)>0&&x.deck_id;const v=t.reading_materials.filter(Gc).length,w=()=>{a&&a(t)};return e.jsxs(ds,{as:"div",size:"md",className:"im-library-card",onClick:w,onKeyDown:j=>{j.target===j.currentTarget&&(j.key==="Enter"||j.key===" ")&&(j.preventDefault(),w())},animate:!1,children:[e.jsx(ds.Cover,{className:"im-library-card-cover",children:t.cover_image_url?e.jsx("img",{src:t.cover_image_url,alt:t.title,loading:"lazy",decoding:"async"}):e.jsx(wi,{title:t.title,titleJp:t.title_jp??void 0})}),e.jsxs("div",{className:"im-library-card-main",children:[e.jsxs(ds.Body,{className:"im-library-card-body",children:[e.jsxs("div",{className:"im-library-card-tags",children:[e.jsx("span",{className:"im-library-card-chip",children:"Series"}),e.jsxs("span",{className:`im-library-card-chip ${y?"im-library-card-chip--ok":"im-library-card-chip--busy"}`,children:[y?e.jsx(rn,{}):b<f?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Yn,{}),e.jsx("span",{children:y?"Ready":`${b}/${f}`})]})]}),e.jsx("h3",{className:"im-library-card-title",children:t.title}),e.jsxs("div",{className:"im-library-card-meta",children:[e.jsxs("span",{children:[e.jsx(ss,{}),f," vol",f!==1?"s":""," · ",h," pg."]}),p>0&&e.jsxs("span",{children:[e.jsx(ri,{}),g,"% read"]})]}),h>0&&e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${g}%`}})}),v>0&&e.jsxs("span",{className:"im-library-card-partial",title:"Analysis
89stopped when shared credits ran out â open the series to finish analyzing",children:[e.jsx(Qa,{}),"Partially analyzed",e.jsxs("span",{className:"ratio",children:["· shared credits ran out",f>1?` · ${v} vol${v!==1?"s":""}`:""]})]}),r&&(r.vocabTotal>0||r.grammarTotal>0)&&e.jsxs("div",{className:"im-library-card-coverage",children:[e.jsx("span",{className:"im-library-card-coverage-label",children:"Knowledge Coverage"}),r.vocabTotal>0&&e.jsxs("div",{className:"im-library-card-coverage-row",children:[e.jsxs("div",{className:"head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(Gs,{}),"Vocab"]}),e.jsxs("span",{className:"val",children:[r.vocabPct!=null?`${r.vocabPct}%`:"0%",e.jsxs("span",{className:"ratio",children:["(",r.vocabKnown,"/",r.vocabTotal,")"]})]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${r.vocabPct??0}%`}})})]}),r.grammarTotal>0&&e.jsxs("div",{className:"im-library-card-coverage-row",children:[e.jsxs("div",{className:"head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(Rn,{}),"Grammar"]}),e.jsxs("span",{className:"val",children:[r.grammarPct!=null?`${r.grammarPct}%`:"0%",e.jsxs("span",{className:"ratio",children:["(",r.grammarKnown,"/",r.grammarTotal,")"]})]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${r.grammarPct??0}%`}})})]})]}),e.jsx("div",{className:"study-build-children",role:"list","aria-label":"Study builds by volume",children:t.reading_materials.filter(j=>!!j.deck_id||j.processing_status==="completed"&&j.enrichment_status==="completed").map(j=>e.jsxs("div",{role:"listitem",className:"study-build-child",children:[e.jsx("span",{className:"study-build-child-label",children:j.volume?`Volume ${j.volume}`:j.title}),e.jsx(vi,{sourceKind:"reading_material",sourceId:j.id,hasDeck:!!j.deck_id,presentation:"row"})]},j.id))}),!1,!1,e.jsxs("span",{className:"im-library-card-last",children:[e.jsx(Yn,{}),"Added · ",new Date(t.created_at).toLocaleDateString()]})]}),e.jsx(ds.Foot,{className:"im-library-card-footer",children:e.jsx(Oa,{mode:"wait",initial:!1,children:c?e.jsxs(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-cancel",onClick:j=>{j.stopPropagation(),u()},children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--maple im-library-card-cta",onClick:j=>{j.stopPropagation(),u(),s(t.id)},disabled:n,children:[n?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ns,{}),"Delete"]})]},"confirm"):d?e.jsxs(ze.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:"im-library-card-footer",style:{flex:1,borderTop:"none"},children:[e.jsx("div",{className:"im-library-card-footer-row",children:e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",onClick:j=>{j.stopPropagation(),u()},"aria-label":"Back",children:e.jsx(Za,{})})}),e.jsx("div",{className:"im-library-card-menulist",children:e.jsxs("button",{onClick:j=>{j.stopPropagation(),m("confirmDelete")},children:[e.jsx(Ns,{})," Delete",e.jsx(As,{className:"chev"})]})})]},"manage"):e.jsxs(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:"im-library-card-footer-actions",children:[e.jsx("div",{className:"im-library-card-footer-row is-stretch",children:e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-library-card-cta",onClick:j=>{j.stopPropagation(),a?.(t)},children:[e.jsx(ss,{})," View"]})}),e.jsxs("div",{className:"im-library-card-footer-row",children:[!1,e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",style:{marginLeft:"auto"},onClick:j=>{j.stopPropagation(),m("manage")},"aria-label":"More actions",children:e.jsx(jo,{})})]})]},"actions")})})]})]})}function hk(t){return t.primary_sub_status==="pending"||t.primary_sub_status==="processing"}function Yc(t){return t.enrichment_cursor!=null||(t.enriched_entry_count??0)>0}function ml(t){return t.primary_sub_status==="completed"&&!Yc(t)}function pk(t,a,s){return t.cloud_sync_status==="synced"||a?.status==="synced"||s?.status==="synced"}function fk({show:t,onOpen:a,onDelete:s,isDeleting:n,coverage:r,onCreateDeck:i,creatingDeckForId:l}){const{isConfirmingDelete:c,isManage:d,setMode:m,reset:u}=Wc(),h=t.video_sessions.reduce((w,j)=>w+(j.video_episodes?.length||0),0),p=t.video_sessions.flatMap(w=>w.video_episodes||[]),g=p.filter(w=>w.primary_sub_status==="completed").length,f=p.filter(w=>w.watch_completed).length,b=g===h&&h>0,y=t.show_type==="movie",x=t.video_sessions.length===1?t.video_sessions[0]:null;t.video_sessions.filter(w=>!!w.deck_id),x&&b&&!x.deck_id&&(r?.vocabTotal??0)>0;const v=()=>{a&&a(t)};return e.jsxs(ds,{as:"div",size:"md",className:"im-library-card",onClick:v,onKeyDown:w=>{w.target===w.currentTarget&&(w.key==="Enter"||w.key===" ")&&(w.preventDefault(),v())},animate:!1,children:[e.jsx(ds.Cover,{className:"im-library-card-cover",children:t.cover_image_url?e.jsx("img",{src:t.cover_image_url,alt:t.title,loading:"lazy",decoding:"async"}):e.jsx(wi,{title:t.title,titleJp:t.title_jp??void 0})}),e.jsxs("div",{className:"im-library-card-main",children:[e.jsxs(ds.Body,{className:"im-library-card-body",children:[e.jsxs("div",{className:"im-library-card-tags",children:[e.jsx("span",{className:"im-library-card-chip",children:y?"Movie":"Series"}),e.jsxs("span",{className:`im-library-card-chip ${b?"im-library-card-chip--ok":"im-library-card-chip--busy"}`,children:[b?e.jsx(rn,{}):g<h?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Yn,{}),e.jsx("span",{children:b?"Ready":`${g}/${h}`})]})]}),e.jsxs("div",{children:[e.jsx("h3",{className:"im-library-card-title",children:t.title}),t.title_jp&&e.jsx("p",{className:"im-library-card-title-jp",children:t.title_jp})]}),e.jsxs("div",{className:"im-library-card-meta",children:[e.jsxs("span",{children:[e.jsx(on,{}),y?"Movie":`${t.video_sessions.length} season${t.video_sessions.length!==1?"s":""} · ${h} ep.`]}),f>0&&e.jsxs("span",{children:[e.jsx(ri,{}),f," watched"]})]}),h>0&&e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${f/h*100}%`}})}),r&&(r.vocabTotal>0||r.grammarTotal>0)&&e.jsxs("div",{className:"im-library-card-coverage",children:[e.jsx("span",{className:"im-library-card-coverage-label",children:"Knowledge Coverage"}),r.vocabTotal>0&&e.jsxs("div",{className:"im-library-card-coverage-row",children:[e.jsxs("div",{className:"head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(Gs,{}),"Vocab"]}),e.jsxs("span",{className:"val",children:[r.vocabPct,"%",e.jsxs("span",{className:"ratio",children:["(",r.vocabKnown,"/",r.vocabTotal,")"]})]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${r.vocabPct}%`}})})]}),r.grammarTotal>0&&e.jsxs("div",{className:"im-library-card-coverage-row",children:[e.jsxs("div",{className:"head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(Rn,{}),"Grammar"]}),e.jsxs("span",{className:"val",children:[r.grammarPct,"%",e.jsxs("span",{className:"ratio",children:["(",r.grammarKnown,"/",r.grammarTotal,")"]})]})]}),e.jsx("div",{className:"im-library-card-bar",children:e.jsx("span",{className:"fill",style:{width:`${r.grammarPct}%`}})})]})]}),e.jsx("div",{className:"study-build-children",role:"list","aria-label":"Study builds by season",children:t.video_sessions.filter(w=>{const j=(w.video_episodes||[]).filter(T=>T.source!=="extension");return!!w.deck_id||j.length>0&&j.every(T=>T.primary_sub_status==="completed"&&Yc(T))}).map(w=>e.jsxs("div",{role:"listitem",className:"study-build-child",children:[e.jsx("span",{className:"study-build-child-label",children:w.season_label||w.title||`Season ${w.season_number}`}),e.jsx(vi,{sourceKind:"video_session",sourceId:w.id,hasDeck:!!w.deck_id,presentation:"row"})]},w.id))}),!1,!1,e.jsxs("span",{className:"im-library-card-last",children:[e.jsx(Yn,{}),"Added · ",new Date(t.created_at).toLocaleDateString()]})]}),e.jsx(ds.Foot,{className:"im-library-card-footer",children:e.jsx(Oa,{mode:"wait",initial:!1,children:c?e.jsxs(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{className:"wc-cta-square im-library-card-cta-cancel",onClick:w=>{w.stopPropagation(),u()},children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--maple im-library-card-cta",onClick:w=>{w.stopPropagation(),u(),s(t.id)},disabled:n,children:[n?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ns,{}),"Delete"]})]},"confirm"):d?e.jsxs(ze.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:"im-library-card-footer",style:{flex:1,borderTop:"none"},children:[e.jsx("div",{className:"im-library-card-footer-row",children:e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",onClick:w=>{w.stopPropagation(),u()},"aria-label":"Back",children:e.jsx(Za,{})})}),e.jsx("div",{className:"im-library-card-menulist",children:e.jsxs("button",{onClick:w=>{w.stopPropagation(),m("confirmDelete")},children:[e.jsx(Ns,{})," Delete",e.jsx(As,{className:"chev"})]})})]},"manage"):e.jsxs(ze.div,{initial:{opacity:0}
89,animate:{opacity:1},exit:{opacity:0},transition:{duration:.15},className:"im-library-card-footer-actions",children:[e.jsx("div",{className:"im-library-card-footer-row is-stretch",children:e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-library-card-cta",onClick:w=>{w.stopPropagation(),a?.(t)},children:[e.jsx(Xr,{})," View"]})}),e.jsxs("div",{className:"im-library-card-footer-row",children:[!1,e.jsx("button",{className:"wc-cta-square im-library-card-cta-icon",style:{marginLeft:"auto"},onClick:w=>{w.stopPropagation(),m("manage")},"aria-label":"More actions",children:e.jsx(jo,{})})]})]},"actions")})})]})]})}function gk({series:t,onOpen:a,onRemove:s}){const n=()=>a(t.slug??t.id),[r,i]=o.useState(!1),[l,c]=o.useState(!1),[d,m]=o.useState(null),u=async()=>{if(!(!s||l)){c(!0),m(null);try{await s(t.id)}catch(h){m(h instanceof Error?h.message:"Could not remove this manga"),c(!1)}}};return e.jsxs(ds,{as:"div",size:"md",className:"im-library-card",onClick:n,onKeyDown:h=>{(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),n())},animate:!1,children:[e.jsx(ds.Cover,{className:"im-library-card-cover",children:t.cover_url?e.jsx("img",{src:t.cover_url,alt:t.title,loading:"lazy",decoding:"async"}):e.jsx(wi,{title:t.title,titleJp:t.title_jp??void 0})}),e.jsxs("div",{className:"im-library-card-main",children:[e.jsxs(ds.Body,{className:"im-library-card-body",children:[e.jsx("div",{className:"im-library-card-tags",children:e.jsx("span",{className:"im-library-card-chip",children:"Public"})}),e.jsx("h3",{className:"im-library-card-title",children:t.title}),t.title_jp&&e.jsx("span",{className:"im-public-shelf-jp jp",children:t.title_jp}),e.jsx("div",{className:"im-library-card-meta",children:e.jsxs("span",{children:[e.jsx(ss,{}),t.volume_count," vol",t.volume_count!==1?"s":""]})})]}),e.jsx(ds.Foot,{className:"im-library-card-footer",children:r?e.jsxs("div",{onClick:h=>h.stopPropagation(),onKeyDown:h=>h.stopPropagation(),children:[e.jsx("span",{className:"im-library-card-modehead",style:{marginBottom:4},children:"Remove from your library?"}),e.jsx("p",{className:"im-library-card-unsync-copy",children:"It stays public and available to everyone else."}),d&&e.jsx("p",{className:"im-library-card-unsync-error",role:"alert",children:d}),e.jsxs("div",{className:"im-library-card-footer-row is-stretch",children:[e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink im-library-card-cta",onClick:()=>{i(!1),m(null)},disabled:l,children:"Cancel"}),e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--maple im-library-card-cta",onClick:()=>{u()},disabled:l,children:[l?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ns,{}),"Remove"]})]})]}):e.jsxs("div",{className:"im-library-card-footer-row is-stretch",children:[e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk im-library-card-cta",onClick:h=>{h.stopPropagation(),n()},children:[e.jsx(ss,{})," Read"]}),s&&e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink im-library-card-cta-icon",onClick:h=>{h.stopPropagation(),i(!0)},"aria-label":`More actions for ${t.title}`,children:e.jsx(jo,{})})]})})]})]})}function dp(){const{getAccessToken:t}=ps(),[a,s]=o.useState(new Map),n=o.useRef(!1);return o.useEffect(()=>(n.current||(kr.configure(t),n.current=!0),kr.subscribe(s)),[t]),a}const yk=.6,bk=4*1024*1024*1024;function xk(t){return typeof t!="number"||!Number.isFinite(t)||t<=0?0:Math.min(Math.floor(t*yk),bk)}function wk(t,a,s,n){const r=t.reduce((d,m)=>d+Math.max(0,m.sizeBytes),0);if(a<=0||r<=a)return{toEvict:[],reclaimedBytes:0,totalBytes:r,budgetBytes:a};const i=t.filter(d=>d.status==="synced"&&!s.has(d.materialId)&&d.materialId!==n&&d.sizeBytes>0).sort((d,m)=>(d.lastOpenedAt??0)-(m.lastOpenedAt??0)),l=[];let c=0;for(const d of i){if(r-c<=a)break;l.push(d.materialId),c+=d.sizeBytes}return{toEvict:l,reclaimedBytes:c,totalBytes:r,budgetBytes:a}}const up="immersion.cloud.lastOpened.v1";function mp(){return Fc(up,t=>{if(!t||typeof t!="object"||Array.isArray(t))return null;const a={};for(const[s,n]of Object.entries(t))typeof n=="number"&&Number.isFinite(n)&&(a[s]=n);return a},{})}function Cu(t,a=Date.now()){const s=mp();s[t]=a,Dc(up,s)}async function vk(t,a=null){const s=await t.estimateStorage().catch(()=>({})),n=xk(s.quota);if(n<=0||typeof s.usage=="number"&&Number.isFinite(s.usage)&&s.usage<=n)return{toEvict:[],reclaimedBytes:0,totalBytes:s.usage??0,budgetBytes:n};const r=await t.listLocalMaterials().catch(()=>[]),i=t.loadPins(),l=wk(r,n,i,a);for(const c of l.toEvict)try{await t.deleteLocal(c)}catch{}return l}async function jk(t){const a=new Map;for(const l of t)a.set(l.id,l.cloud_sync_status??null);const s=mp(),[n,r]=await Promise.all([pc(),xc()]),i=[];for(const l of n){const c=await Xg(l.materialId).catch(()=>0);i.push({materialId:l.materialId,status:a.get(l.materialId)??null,lastOpenedAt:s[l.materialId],sizeBytes:c})}for(const l of r)i.some(c=>c.materialId===l.materialId)||i.push({materialId:l.materialId,status:a.get(l.materialId)??null,lastOpenedAt:s[l.materialId],sizeBytes:l.blob?.size??l.fileSize??0});return i}async function kk(){try{if(typeof navigator>"u"||!navigator.storage?.estimate)return{};const t=await navigator.storage.estimate();return{quota:typeof t.quota=="number"?t.quota:void 0,usage:typeof t.usage=="number"?t.usage:void 0}}catch{return{}}}async function _k(t){await Promise.allSettled([Mn(t),_o(t)])}async function Sk(t,a=null){return vk({estimateStorage:kk,listLocalMaterials:()=>jk(t),deleteLocal:_k,loadPins:ai},a)}function Nk({materials:t,onClose:a,onUnsynced:s,onBackfillStarted:n}){const{getAccessToken:r}=ps(),{openUpgradeModal:i}
89=xn(),l=wn(),[c,d]=o.useState(!0),[m,u]=o.useState(null),[h,p]=o.useState({bytesUsed:0,limitBytes:0,rows:[]}),[g,f]=o.useState(null),[b,y]=o.useState(null),[x,v]=o.useState(null),[w,j]=o.useState([]),[T,P]=o.useState(!1),N=o.useRef(t),_=o.useCallback(async()=>{d(!0),u(null);const J=await ap({getAccessToken:r});J.ok?p({bytesUsed:J.usage.bytes_used,limitBytes:J.usage.limit_bytes,rows:J.usage.materials}):u(J.message),d(!1)},[r]);o.useEffect(()=>{_()},[_]),o.useEffect(()=>{let J=!1;return qx(N.current).then(M=>{J||j(M)}),()=>{J=!0}},[]);const L=async(J,M)=>{y(J),v(null);try{const H=M?.kind==="video"?await oj(J,r,void 0,{bytes:M.bytes}):await go(J,r,void 0,M);H.ok?(f(null),s?.(J),_()):v({id:J,message:H.message??"Could not remove from cloud"})}finally{y(null)}},q=()=>{Ux(w),P(!0),j([]),n?.()},O=qc(h.bytesUsed,h.limitBytes),A=lj(h.bytesUsed,h.limitBytes),k=e.jsx("div",{className:"wc-root im-logged",role:"dialog","aria-modal":"true","aria-label":"Cloud storage",children:e.jsx("div",{className:"im-modal-backdrop",onClick:a,children:e.jsxs(ze.div,{className:"im-modal im-cloud-panel",initial:{opacity:0,scale:.98},animate:{opacity:1,scale:1},transition:{duration:.18},onClick:J=>J.stopPropagation(),children:[e.jsxs("header",{className:"im-cloud-panel-head",children:[e.jsxs("div",{className:"im-cloud-panel-eyebrow",children:[e.jsx("span",{className:"num jp",children:"èµ"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Cloud storage"}),e.jsx("span",{className:"jp",children:"ã¯ã©ã¦ãä¿ç®¡"})]}),e.jsx("button",{type:"button",className:"im-cloud-panel-close",onClick:a,"aria-label":"Close",children:e.jsx(rs,{"aria-hidden":"true"})})]}),c?e.jsx("div",{className:"im-cloud-panel-loading","aria-live":"polite",children:l?e.jsx("span",{children:"Loadingâ¦"}):e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999})}):m?e.jsxs("div",{className:"im-cloud-panel-error",children:[e.jsx("span",{children:m}),e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink",onClick:()=>{_()},children:[e.jsx(pi,{"aria-hidden":"true"})," Retry"]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-cloud-usage",children:[e.jsxs("div",{className:"im-cloud-usage-label",children:[e.jsxs("span",{children:[br(h.bytesUsed)," of ",br(h.limitBytes)]}),e.jsxs("span",{className:"pct",children:[Math.round(O*100),"%"]})]}),e.jsx("div",{className:`im-cloud-usage-bar${A?" is-full":""}`,children:e.jsx("span",{className:"fill",style:{width:`${Math.round(O*100)}%`}})}),A&&e.jsx("div",{className:"im-cloud-usage-warn",children:$a()?e.jsxs(e.Fragment,{children:[e.jsx("span",{children:"Your cloud library is nearly full â remove something or upgrade."}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink",onClick:()=>i("cloud_sync","cloud_quota"),children:"Upgrade"})]}):e.jsx("span",{children:"Your cloud library is nearly full â free up space."})})]}),e.jsxs("section",{className:"im-cloud-section",children:[e.jsx("h3",{className:"im-cloud-section-head",children:"Synced materials"}),h.rows.length===0?e.jsx("p",{className:"im-cloud-empty",children:"Nothing synced to the cloud yet."}):e.jsx("ul",{className:"im-cloud-rows",children:h.rows.map(J=>e.jsxs("li",{className:"im-cloud-row",children:[e.jsx("span",{className:"im-cloud-row-title",title:J.title,children:J.title}),e.jsx("span",{className:"im-cloud-row-size",children:br(J.cloud_size_bytes)}),g===J.id?e.jsxs("span",{className:"im-cloud-row-confirm",children:[x?.id===J.id&&e.jsx("span",{className:"im-cloud-row-error",role:"alert",children:x.message}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink",onClick:()=>{f(null),v(null)},disabled:b===J.id,children:"Cancel"}),e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--maple",onClick:()=>{L(J.id,{kind:J.kind,bytes:J.cloud_size_bytes})},disabled:b===J.id,children:[b===J.id?e.jsx(Sa,{className:"animate-spin","aria-hidden":"true"}):e.jsx(Ws,{"aria-hidden":"true"}),"Remove"]})]}):e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink im-cloud-row-remove",onClick:()=>{f(J.id),v(null)},"aria-label":`Remove ${J.title} from cloud`,children:[e.jsx(Ws,{"aria-hidden":"true"})," Remove"]})]},J.id))})]}),w.length>0&&e.jsxs("section",{className:"im-cloud-section",children:[e.jsx("h3",{className:"im-cloud-section-head",children:"Sync your library"}),e.jsxs("p",{className:"im-cloud-backfill-copy",children:[w.length," item",w.length!==1?"s":""," on this device",w.length!==1?" aren't":" isn't"," synced yet."]}),e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square--ink im-cloud-backfill-btn",onClick:q,disabled:T,children:T?"Syncingâ¦":`Sync all (${w.length})`})]})]})]})})});return hi.createPortal(k,document.body)}const Ck=2;function Ek(t){return{mediaContext:{mode:t.mode,skipKnownWords:!0,consentVersion:t.mode==="simple"?
891:Ck}}}function Eu(t){return t&&typeof t=="object"&&!Array.isArray(t)?t:null}function yo(t,a){const s=Eu(t);if(!s)return null;const n=typeof s.status=="string"?s.status:"",r=typeof s.outcome=="string"?s.outcome:"";if(s.allKnown===!0||["allKnown","all_known"].includes(n)||["allKnown","all_known"].includes(r))return{phase:"allKnown",title:"You are already caught up",message:"Every word in this material is already in your SRS. No duplicate deck was created.",terminal:!0,retryable:!1};if(["cancelled","canceled","aborted"].includes(n))return{phase:"failed",title:"Deck creation stopped",message:"This deck job was cancelled before it finished. You can start it again.",terminal:!0,retryable:!0,retryLabel:"Retry deck creation"};if(a==="simple")return n==="queued"?{phase:"queued",title:"Deck creation queued",message:"Your deck request is waiting for a worker. You can leave this page; progress will resume when you return.",terminal:!1,retryable:!1}:["processing","running"].includes(n)?{phase:"processing",title:"Creating your new-word deck",message:"Your new-word cards are still being prepared. You can leave this page; progress will resume when you return.",terminal:!1,retryable:!1}:null;const i=Eu(s.mediaContext),l=typeof i?.status=="string"?i.status:"",c=n==="completed"&&typeof s.deckId=="string"&&s.deckId.length>0,d=c&&(i?.role==="image"||i?.role==="video_clip")?{deckId:s.deckId,role:i.role}:null;if(l==="awaiting_confirmation"&&c){const m=typeof i?.constraint=="string"?i.constraint:null;return m==="feature_disabled"?{phase:"partial",title:"Full deck ready without media",message:i?.message||"Media mnemonics are disabled in this deployment. The complete vocabulary deck is ready to study.",terminal:!0,retryable:!1}:{phase:"partial",title:m==="blocked_source"?"Full deck ready; media is waiting for cloud sync":"Full deck ready; choose media",message:i?.message||(m==="blocked_source"?"The deck is ready to study. Finish cloud sync, then continue media from the new deck.":"The complete deck is ready. Review exact coverage and confirm media from the new deck."),terminal:!0,retryable:!1,...d?{coverageTarget:d}:{}}}return l==="ready"&&c?{phase:"ready",title:"Deck and source memories are ready",message:"Your new-word deck was created and its private source memories are ready to review.",terminal:!0,retryable:!1}:["partial","retryable_error","source_unavailable"].includes(l)&&c?{phase:"partial",title:"Deck ready; some memories need attention",message:"Your new-word deck succeeded. Check cloud sync and your separate Cloud Library storage allowance, then retry the source memories.",terminal:!0,retryable:!0}:["not_entitled","entitlement_unavailable"].includes(l)&&c?{phase:"partial",title:"Deck ready without source memories",message:i?.message||"The base deck succeeded, but Premium access could not be confirmed for source memories.",terminal:!0,retryable:!1}:l==="not_started"&&c?{phase:"partial",title:"Full deck ready",message:"Your complete new-word deck is ready. You can add chronological media mnemonics from any deck or source screen later.",terminal:!0,retryable:!1}:l==="blocked_source"&&c?{phase:"partial",title:"Full deck ready; media is waiting for cloud sync",message:"The deck is ready to study. Finish cloud sync, then continue media from this deck or source.",terminal:!0,retryable:!1,...d?{coverageTarget:d}:{}}:l==="feature_disabled"&&c?{phase:"partial",title:"Full deck ready without media",message:"Media mnemonics are disabled in this deployment. The complete vocabulary deck is ready to study.",terminal:!0,retryable:!1}:["queued","pending"].includes(l)||n==="queued"?{phase:"queued",title:"Deck creation queued",message:"New-word cards will be created first; source memories will follow in the background.",terminal:!1,retryable:!1}:["processing","running"].includes(l)||["processing","running"].includes(n)?{phase:"processing",title:s.deckId?"Deck ready; source memories processing":"Creating your new-word deck",message:s.deckId?"You can use the deck now. Private source memories are still being prepared.":"The base deck is being prepared before source-memory capture starts.",terminal:!1,retryable:!1}:n==="completed"&&s.deckId?{phase:"processing",title:"Deck ready; source memories processing",message:"You can use the deck now. Private source memories are still being prepared.",terminal:!1,retryable:!1}:null}function Tu(t){return{phase:"failed",title:"Deck creation was not queued",message:t||"The request was rejected before a deck job started. Check your access and source, then try again.",terminal:!0,retryable:!0,retryLabel:"Retry deck creation"}}function Zi(t){return t===403?{phase:"failed",title:"Deck status access ended",message:"You no longer have access to this deck job. Sign in with the owning account, then start again.",terminal:!0,retryable:!1}:t===404?{phase:"failed",title:"Deck source is no longer available",message:"This material or video was removed. Reopen your library and choose an available source.",terminal:!0,retryable:!1}:null}const Tk="shizen.mediaContextDeckPolls.v1",Mk=10080*60*1e3,Mu=30,ir=2e3,Pu=15e3;function Vl(t){return`${Tk}:${t}`}function Pk(t){if(!t||typeof t!="object"||Array.isArray(t))return!1;const a=t,s=String(a.mode),n=a.consentVersion;return["simple","image","clip"].includes(s)&&a.skipKnownWords===!0&&["skip","add"].includes(String(a.existingMemoryPolicy))&&Number.isSafeInteger(n)&&(s==="simple"?n===1:Number(n)>=2)}
89function Jc(t){if(typeof window>"u"||!t)return[];try{const a=JSON.parse(window.localStorage.getItem(Vl(t))??"[]");if(!Array.isArray(a))return[];const s=Date.now()-Mk;return a.filter(n=>{if(!n||typeof n!="object"||Array.isArray(n))return!1;const r=n;return r.version===1&&r.userId===t&&(r.kind==="manga"||r.kind==="video")&&typeof r.id=="string"&&r.id.length>0&&Pk(r.selection)&&typeof r.updatedAt=="number"&&Number.isFinite(r.updatedAt)&&r.updatedAt>=s&&typeof r.terminal=="boolean"})}catch{return[]}}function hp(t,a){if(!(typeof window>"u"||!t))try{a.length===0?window.localStorage.removeItem(Vl(t)):window.localStorage.setItem(Vl(t),JSON.stringify(a))}catch{}}function sn(t){const a=Jc(t.userId).filter(s=>s.kind!==t.kind||s.id!==t.id);a.push({...t,updatedAt:Date.now()}),hp(t.userId,a)}function pn(t,a,s){hp(t,Jc(t).filter(n=>n.kind!==a||n.id!==s))}const Ak=[{label:"Recently Updated",value:"recent"},{label:"Title A-Z",value:"title"},{label:"Reading Progress",value:"progress"}],Ik=[{label:"All Status",value:"all"},{label:"Ready to Read",value:"completed"},{label:"Local",value:"local_only"},{label:"Processing",value:"processing"},{label:"Pending",value:"pending"},{label:"Failed",value:"error"}];async function Rk(t){try{const[a,s]=await Promise.all([pc(),xc()]);for(const n of a)t.has(n.materialId)||await Mn(n.materialId).catch(()=>{});for(const n of s)t.has(n.materialId)||await _o(n.materialId).catch(()=>{})}catch{}}function $k({onSelectMaterial:t,onDeleteMaterial:a,onOpenVideoShow:s,onOpenMangaSeries:n,onUploadComplete:r,refreshTrigger:i,uploaderOpen:l,demoMaterials:c,publicSeries:d,onOpenPublicSeries:m,onRemovePublicSeries:u,onUploaderOpenChange:h,startScanner:p}){const{user:g,getAccessToken:f}=ps(),{openUpgradeModal:b}=xn(),{isPro:y,isLoading:x,refresh:v}=Xn(),w=dp(),[j,T]=o.useState(()=>ai()),[P,N]=o.useState(!1),_=o.useRef(!1),L=Array.isArray(d)&&d.length>0,q=!g&&(L||Array.isArray(c)&&c.length>0),O=nc(),[A,k]=o.useState(null),[J,M]=o.useState(!1),H=l??J,ee=o.useCallback(C=>{h?h(C):M(C)},[h]),[Pe,D]=o.useState([]),de=o.useRef(!1),fe=o.useRef(!1),Me=o.useRef(!1),[U,ve]=o.useState([]),[yt,ut]=o.useState(!0),[St,je]=o.useState(null),[lt,Et]=o.useState(""),[Ct,aa]=o.useState("recent"),[vt,Le]=o.useState("all"),[jt,Ft]=o.useState("all"),[ct,se]=o.useState(null),[ft,Oe]=o.useState(null),[pt,kt]=o.useState(null),[Ve,Be]=o.useState(null),[Ke,At]=o.useState(null),[Jt,ta]=o.useState(null),zt=o.useRef(new Map),K=o.useRef(!0),_t=o.useRef(null),[qt,sa]=o.useState({}),[la,Dt]=o.useState({}),[ba,da]=o.useState([]),[xa,ma]=o.useState(null),[Na,Da]=o.useState(null),wa=o.useRef([]),Wt=o.useRef({handleDelete:async()=>{},retryProcessing:async()=>{},processImport:async()=>{},processRemaining:async()=>{},createDeck:async()=>{},addMaterialToSeries:async()=>{},createSeriesForMaterial:async()=>{},handleRetrySync:()=>{},handleSyncToCloud:()=>{},handleUnsynced:()=>{},handleTogglePin:()=>{},handleRenamed:()=>{}}),ua=o.useCallback(C=>{Wt.current.handleDelete(C)},[]),ca=o.useCallback(C=>{Wt.current.retryProcessing(C)},[]),ha=o.useCallback(C=>{Wt.current.processImport(C)},[]),za=o.useCallback(C=>{Wt.current.processRemaining(C)},[]),ea=o.useCallback(C=>{const V=wa.current.find(le=>le.id===C);if(V?.content_type==="novel"){Wt.current.createDeck(C);return}At({kind:"manga",id:C,cloudSyncStatus:V?.cloud_sync_status??null})},[]),Ea=o.useCallback((C,V)=>{Wt.current.addMaterialToSeries(C,V)},[]),pa=o.useCallback((C,V)=>{Wt.current.createSeriesForMaterial(C,V)},[]),Ca=o.useCallback(C=>{Wt.current.handleRetrySync(C)},[]),Gt=o.useCallback(C=>{Wt.current.handleSyncToCloud(C)},[]),Ba=o.useCallback(C=>{Wt.current.handleUnsynced(C)},[]),ka=o.useCallback(C=>{Wt.current.handleTogglePin(C)},[]),Wa=o.useCallback((C,V)=>{Wt.current.handleRenamed(C,V)},[]),es=o.useCallback(C=>{O(`/vocabulary/decks/mine?deckId=${encodeURIComponent(C)}`)},[O]),Ta=async()=>{try{const C=await f();if(!C)return;const V=await fetch(`${ue()}/api/reading/materials/coverage`,{headers:{Authorization:`Bearer ${C}`,"Content-Type":"application/json"}});if(!V.ok)return;const le=await V.json(),ye={};for(const it of le.coverage||[])ye[it.materialId]=it;sa(ye)}catch(C){console.warn("[ReadingLibrary] Failed to load coverage:",C)}},va=async()=>{try{const C=await f();if(!C)return;const V=await fetch(`${ue()}/api/video/shows/coverage`,{headers:{Authorization:`Bearer ${C}`,"Content-Type":"application/json"}});if(!V.ok)return;const le=await V.json(),ye={};for(const it of le.coverage||[])ye[it.showId]=it;Dt(ye)}catch(C){console.warn("[ReadingLibrary] Failed to load video coverage:",C)}},ia=async()=>{try{ut(!0),je(null);const C=new URLSearchParams({limit:"50",sort:Ct});lt.trim()&&C.set("q",lt.trim());const V=await f();if(!V){D([]),ut(!1);return}const le=await fetch(`${ue()}/api/reading/materials?${C}`,{headers:{Authorization:`Bearer ${V}`,"Content-Type":"application/json"}});if(!le.ok)throw new Error("Failed to load materials");const ye=await le.json(),it=ye.materials||[];D(it);const fa=!lt.trim()&&ye.hasMore===!1;if(fe.current=fa,!de.current&&fa){de.current=!0;const Xt=new Set(it.map(ga=>ga.id));Rk(Xt)}}catch(C){je(C instanceof Error?C.message:"Failed to load materials"),console.error("Load materials error:",C)}finally{ut(!1)}},oe=async()=>{try{const C=await f();if(!C)return;const V=await fetch(`${ue()}/api/video/shows`,{headers:{Authorization:`Bearer ${C}`}});if(V.ok){const le=await V.json();ve(le.shows||[])}}catch(C){console.warn("[ReadingLibrary] Failed to load video shows:",C)}},me=async()=>{try{const C=await f();if(!C)return;const V=await fetch(`${ue()}/api/manga/series`,{headers:{Authorization:`Bearer ${C}`}});if(V.ok){const le=await V.json();da(le.series||[])}}catch(C){console.warn("[ReadingLibrary] Failed to load manga series:",C)}},Ge=async(C,V)=>{try{const le=await f();if(!le)return;await fetch(`${ue()}/api/manga/series/${V}/materials/${C}`,{method:"PATCH",headers:{Authorization:`Bearer ${le}`,"Content-Type":"application/json"}}),await ia(),await me()}catch(le){console.error("Add to series error:",le)}},gt=async(C,V)=>{try{const le=await f();if(!le)return;const ye=await fetch(`${ue()}/api/manga/series`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${le}`},body:JSON.stringify({title:V})});if(!ye.ok)return;const{seriesId:it}=await ye.json();ne("immersion_series_created",{volume_count:1}),await fetch(`${ue()}/api/manga/series/${it}/materials/${C}`,{method:"PATCH",headers:{Authorization:`Bearer ${le}`,"Content-Type":"application/json"}}),await ia(),await me()}catch(le){console.error("Create series error:",le)}},I=async C=>{try{const V=await f();if(!V)throw new Error("Please log in first");const le=await fetch(`${ue()}/api/reading/materials/${C}/retry`,{method:"POST",headers:{Authorization:`Bearer ${V}`,"Content-Type":"application/json"}});if(le.status===402){je("Not enough shared credits to start processing."),$a()&&b("enrichment","quota_exceeded"),v(
89);return}if(!le.ok){const ye=await ws(le);if(ye){je(fn(ye));return}throw await El(le,"Failed to retry processing")}await ia()}catch(V){console.error("Retry processing error:",V),je(V instanceof Error?V.message:"Failed to retry processing")}},xe=async C=>{try{const V=await f();if(!V)throw new Error("Please log in first");const le=Pe.find(ye=>ye.id===C);if(le?.processing_status==="local_only"&&le.file_type==="epub"){const ye=await gr(C);if(!ye)throw new Error("EPUB file not found in local storage");const it=await lo(ye.blob),fa=Lm(it,ye.format);let Xt;if(fa==="kindle"){const{checkKindleDrm:Tt,extractKindleChapters:Pa}=await Rs(async()=>{const{checkKindleDrm:Aa,extractKindleChapters:Fa}=await Promise.resolve().then(()=>Gm);return{checkKindleDrm:Aa,extractKindleChapters:Fa}},void 0);if(!(await Tt(ye.blob)).ok)throw ne("kindle_import_refused",{reason:"drm"}),new Error("This Kindle file canât be imported (copy-protected or corrupted).");Xt=await Pa(new File([ye.blob],ye.filename,{type:"application/octet-stream"}))}else Xt=await oo(new File([ye.blob],ye.filename,{type:"application/epub+zip"}));const ga=await fetch(`${ue()}/api/reading/upload/epub/import-chapters`,{method:"POST",headers:{Authorization:`Bearer ${V}`,"Content-Type":"application/json"},body:JSON.stringify({materialId:C,chapters:Xt})});if(!ga.ok){const Tt=await Ls(ga);if(Tt)throw Tt.tier==="free"&&$a()&&b("enrichment","quota_exceeded"),new Error(Cn(Tt));const Pa=await ws(ga);if(Pa){je(fn(Pa));return}const oa=await ga.json().catch(()=>({}));throw new Error(oa.message||oa.error||"Failed to import EPUB chapters")}await _o(C)}else{const ye=await fetch(`${ue()}/api/reading/materials/${C}/retry`,{method:"POST",headers:{Authorization:`Bearer ${V}`,"Content-Type":"application/json"}});if(ye.status===402){je("Not enough shared credits to start processing."),$a()&&b("enrichment","quota_exceeded"),v();return}if(!ye.ok){const it=await ws(ye);if(it){je(fn(it));return}throw await El(ye,"Failed to start processing")}}await ia()}catch(V){console.error("Process import error:",V),je(V instanceof Error?V.message:"Failed to start processing")}},Ne=async C=>{try{const V=await f();if(!V)throw new Error("Please log in first");const le=await fetch(`${ue()}/api/reading/materials/${C}/process-remaining`,{method:"POST",headers:{Authorization:`Bearer ${V}`,"Content-Type":"application/json"}});if(le.status===402){je("Not enough shared credits to continue. Your analyzed pages are saved."),$a()&&b("enrichment","quota_exceeded"),v();return}if(!le.ok){const ye=await ws(le);if(ye){je(fn(ye));return}throw new Error("Failed to resume analysis")}v(),await ia()}catch(V){console.error("Process remaining error:",V),je(V instanceof Error?V.message:"Failed to resume analysis")}},tt=(C,V)=>{D(le=>le.map(ye=>ye.id===C?{...ye,title:V}:ye))},Mt=(C,V,le)=>{const ye=yo(C,V.mode);return ye&&ta({progress:ye,target:le,selection:V}),ye},Ma=(C,V)=>`${C}:${V}`,It=(C,V)=>{const le=Ma(C,V),ye=zt.current.get(le);ye&&clearTimeout(ye),zt.current.delete(le)},Nt=(C,V,le)=>{if(!K.current)return;It(C.kind,C.id);const ye=Ma(C.kind,C.id),it=setTimeout(()=>{zt.current.delete(ye),K.current&&le()},V);zt.current.set(ye,it)},Lt=async(C,V=0)=>{if(!K.current)return;const le={kind:"manga",id:C.id};if(V>Mu){const ye=C.lastStatus??{status:"processing"};Mt(ye,C.selection,le),sn({...C,terminal:!1,lastStatus:ye}),Nt({...C},Pu,()=>Lt({...C,lastStatus:ye},0));return}try{const ye=await f();if(!K.current)return;if(!ye)throw new Error("Authentication unavailable");const it=await fetch(`${ue()}/api/reading/materials/${C.id}/deck-status`,{headers:{Authorization:`Bearer ${ye}`}});if(!K.current)return;const fa=Zi(it.status);if(fa){It(C.kind,C.id),pn(C.userId,C.kind,C.id),ta({progress:fa,target:le,selection:C.selection}),kt(null);return}if(!it.ok)throw new Error("Failed to check deck status");const Xt=await it.json();if(!K.current)return;const ga=C.lastStatus&&typeof C.lastStatus=="object"?C.lastStatus:null,Tt=Xt.mediaContext||!ga?.mediaContext?Xt:{...Xt,mediaContext:ga.mediaContext},Pa=Mt(Tt,C.selection,le),oa={...C,lastStatus:Tt};if(Pa?.phase==="allKnown"){It(C.kind,C.id),sn({...oa,terminal:!0}),kt(null);return}if(Xt.deckId&&(D(Aa=>Aa.map(Fa=>Fa.id===C.id?{...Fa,deck_id:Xt.deckId}:Fa)),kt(null)),Pa?.terminal){It(C.kind,C.id),sn({...oa,terminal:!0}),kt(null);return}if(Xt.status==="completed"&&C.selection.mode==="simple"){It(C.kind,C.id),pn(C.userId,C.kind,C.id),ta(null),kt(null);return}if(Xt.status==="failed"){It(C.kind,C.id),pn(C.userId,C.kind,C.id),je("Deck creation failed. Please try again."),kt(null);return}sn({...oa,terminal:!1}),Nt(oa,ir,()=>Lt(oa,V+1))}catch{Nt(C,ir,()=>Lt(C,V+1))}},qa=async(C,V=0)=>
89{if(!K.current)return;const le={kind:"video",id:C.id};if(V>Mu){const ye=C.lastStatus??{status:"processing"};Mt(ye,C.selection,le),sn({...C,terminal:!1,lastStatus:ye}),Nt({...C},Pu,()=>qa({...C,lastStatus:ye},0));return}try{const ye=await f();if(!K.current)return;if(!ye)throw new Error("Authentication unavailable");const it=await fetch(`${ue()}/api/video/sessions/${C.id}/deck-status`,{headers:{Authorization:`Bearer ${ye}`}});if(!K.current)return;const fa=Zi(it.status);if(fa){It(C.kind,C.id),pn(C.userId,C.kind,C.id),ta({progress:fa,target:le,selection:C.selection}),Be(null);return}if(!it.ok)throw new Error("Failed to check deck status");const Xt=await it.json();if(!K.current)return;const ga=C.lastStatus&&typeof C.lastStatus=="object"?C.lastStatus:null,Tt=Xt.mediaContext||!ga?.mediaContext?Xt:{...Xt,mediaContext:ga.mediaContext},Pa=Mt(Tt,C.selection,le),oa={...C,lastStatus:Tt};if(Pa?.phase==="allKnown"){It(C.kind,C.id),sn({...oa,terminal:!0}),await Promise.all([oe(),va()]),Be(null);return}if(Xt.deckId&&Be(null),Pa?.terminal){It(C.kind,C.id),sn({...oa,terminal:!0}),await Promise.all([oe(),va()]),Be(null);return}if(Xt.status==="completed"&&C.selection.mode==="simple"){It(C.kind,C.id),pn(C.userId,C.kind,C.id),ta(null),await Promise.all([oe(),va()]),Be(null);return}if(Xt.status==="failed"){It(C.kind,C.id),pn(C.userId,C.kind,C.id),je("Deck creation failed. Please try again."),Be(null);return}sn({...oa,terminal:!1}),Nt(oa,ir,()=>qa(oa,V+1))}catch{Nt(C,ir,()=>qa(C,V+1))}},F=async(C,V)=>{const le=V??{mode:"simple",skipKnownWords:!0,existingMemoryPolicy:"skip",consentVersion:1},ye={kind:"manga",id:C};try{kt(C),Mt({status:"queued"},le,ye);const it=await f();if(!it)throw new Error("Please log in first");const fa=await fetch(`${ue()}/api/reading/materials/${C}/create-deck`,{method:"POST",headers:{Authorization:`Bearer ${it}`,"Content-Type":"application/json"},body:JSON.stringify(Ek(le))}),Xt=fa.clone(),ga=await fa.json().catch(()=>({}));if(fa.status===409){if(ga.error!=="DECK_EXISTS")throw new Error(ga.message||"Deck creation prerequisites changed. Please reopen the deck options.");const oa=await fetch(`${ue()}/api/reading/materials/${C}/deck-status`,{headers:{Authorization:`Bearer ${it}`}}),Aa=Zi(oa.status);if(Aa){It(ye.kind,ye.id),g?.id&&pn(g.id,ye.kind,ye.id),ta({progress:Aa,target:ye,selection:le}),kt(null);return}const Fa=oa.ok?await oa.json():{status:"processing"};Fa.deckId&&D(Ga=>Ga.map(Cs=>Cs.id===C?{...Cs,deck_id:Fa.deckId}:Cs));const us=ga.mediaContext?{...Fa,mediaContext:ga.mediaContext}:Fa,xs=Mt(us,le,ye);if(g?.id&&xs){const Ga={version:1,userId:g.id,kind:ye.kind,id:ye.id,selection:le,updatedAt:Date.now(),terminal:xs.terminal,lastStatus:us};sn(Ga),xs.terminal||Nt(Ga,ir,()=>Lt(Ga))}kt(null);return}if(!fa.ok){const oa=await ws(Xt);if(oa){const Aa=fn(oa);It(ye.kind,ye.id),g?.id&&pn(g.id,ye.kind,ye.id),ta({progress:Tu(Aa),target:ye,selection:le}),je(Aa),kt(null);return}throw new Error(ga.message||"Failed to create deck")}if(!g?.id)throw new Error("Please log in first");const Tt=ga.mediaContext?{status:"queued",mediaContext:ga.mediaContext}:{status:"queued"},Pa={version:1,userId:g.id,kind:ye.kind,id:ye.id,selection:le,updatedAt:Date.now(),terminal:!1,lastStatus:Tt};sn(Pa),Nt(Pa,ir,()=>Lt(Pa))}catch(it){console.error("Create deck error:",it);const fa=it instanceof Error?it.message:"Failed to create deck";It(ye.kind,ye.id),g?.id&&pn(g.id,ye.kind,ye.id),ta({progress:Tu(fa),target:ye,selection:le}),je(fa),kt(null)}};o.useEffect(()=>{K.current=!0;const C=zt.current;return()=>{K.current=!1;for(const V of C.values())clearTimeout(V);C.clear()}},[]),o.useEffect(()=>{if(q||!g?.id||_t.current===g.id)return;for(const V of zt.current.values())clearTimeout(V);zt.current.clear(),_t.current=g.id;const C=Jc(g.id).sort((V,le)=>V.updatedAt-le.updatedAt);for(const V of C){const le=yo(V.lastStatus,V.selection.mode);V.terminal?le&&ta({progress:le,target:{kind:V.kind,id:V.id},selection:V.selection}):(Mt(V.lastStatus??{status:"processing"},V.selection,{kind:V.kind,id:V.id}),V.kind==="manga"?(kt(V.id),Lt(V)):(Be(V.id),qa(V)))}},[q,g?.id]),o.useEffect(()=>{if(q){D(c??[]),ut(!1);return}ia().then(()=>Ta()),oe(),va(),me()},[Ct,i,q]),o.useEffect(()=>{if(!q)return sc(()=>{Promise.all([Ta(),va()])})},[q,f]),o.useEffect(()=>{if(q||lt==="")return;const C=setTimeout(()=>{ia().then(()=>Ta())},500);return()=>clearTimeout(C)},[lt]),o.useEffect(()=>{q||Me.current||yt||x||(Me.current=!0,Ph(wa.current,y))},[yt,x,y,q]),o.useEffect(()=>{if(q||_.current||yt||x||!y||!fe.current)return;_.current=!0;const C=wa.current.map(V=>({id:V.id,file_type:V.file_type??null,cloud_sync_status:V.cloud_sync_status??null}));Sk(C,null)},[yt,x,y,q,Pe]);const Q=o.useMemo(()=>Pe.filter(C=>C.processing_status==="processing"||C.processing_status==="pending").map(C=>C.id).sort().join(","),[Pe]);o.useEffect(()=>{if(Q==="")return;const C=Q.split(",");let V=!1;const le=setInterval(async()=>
89{if(!V)try{const{data:ye,error:it}=await Ps.from("reading_materials").select("id, processing_status").in("id",C);if(it||!ye||V)return;ye.some(Xt=>Xt.processing_status==="processing"||Xt.processing_status==="pending")||ia().then(()=>Ta())}catch{}},5e3);return()=>{V=!0,clearInterval(le)}},[Q]);const W=new Set;for(const C of ba)for(const V of C.reading_materials)W.add(V.id);const E={};for(const C of ba){let V=0,le=0,ye=0,it=0;for(const fa of C.reading_materials){const Xt=qt[fa.id];Xt&&(V+=Xt.vocabTotal,le+=Xt.vocabKnown,ye+=Xt.grammarTotal,it+=Xt.grammarKnown)}E[C.id]={vocabTotal:V,vocabKnown:le,vocabPct:V>0?Math.round(le/V*1e3)/10:null,grammarTotal:ye,grammarKnown:it,grammarPct:ye>0?Math.round(it/ye*1e3)/10:null}}const G=(()=>{const C=[];if(jt==="all"||jt==="manga"||jt==="novel")for(const V of Pe)W.has(V.id)||jt==="manga"&&V.content_type==="novel"||jt==="novel"&&V.content_type!=="novel"||vt!=="all"&&V.processing_status!==vt||C.push({kind:"reading",data:V});if(jt==="all"||jt==="manga")for(const V of ba){if(lt.trim()){const le=lt.toLowerCase();if(!V.title.toLowerCase().includes(le)&&!V.title_jp?.toLowerCase().includes(le))continue}C.push({kind:"manga_series",data:V})}if(L&&(jt==="all"||jt==="manga"))for(const V of d){if(lt.trim()){const le=lt.toLowerCase();if(!V.title.toLowerCase().includes(le)&&!V.title_jp?.toLowerCase().includes(le))continue}C.push({kind:"public_series",data:V})}if(jt==="all"||jt==="video")for(const V of U){if(lt.trim()){const le=lt.toLowerCase();if(!V.title.toLowerCase().includes(le)&&!V.title_jp?.toLowerCase().includes(le))continue}C.push({kind:"video",data:V})}if(Ct==="recent"){const V=le=>{if(le.kind==="public_series")return 0;const ye=le.kind==="reading"&&(le.data.last_read_at||le.data.updated_at)||le.data.created_at,it=new Date(ye).getTime();return Number.isNaN(it)?0:it};C.sort((le,ye)=>V(ye)-V(le))}else Ct==="title"&&C.sort((V,le)=>V.data.title.localeCompare(le.data.title));return C})(),re=()=>{Et(""),aa("recent"),Le("all"),Ft("all")},pe=!!lt||Ct!=="recent"||vt!=="all"||jt!=="all",te=async C=>{const V=Pe.find(le=>le.id===C);try{await a(C,se),ne("immersion_material_deleted",{material_type:V?.content_type??"unknown",was_completed:V?V.current_page===V.total_pages:!1}),D(le=>le.filter(ye=>ye.id!==C)),sa(le=>{const ye={...le};return delete ye[C],ye})}catch(le){Oe(le instanceof Error?le.message:"Failed to delete material")}},Fe=async C=>{try{ma(C);const V=await f();if(!V)return;(await fetch(`${ue()}/api/video/shows/${C}`,{method:"DELETE",headers:{Authorization:`Bearer ${V}`}})).ok?ve(ye=>ye.filter(it=>it.id!==C)):Oe("Could not delete video show. Please try again.")}catch(V){console.warn("[ReadingLibrary] Failed to delete video show:",V),Oe("Could not delete video show. Please try again.")}finally{ma(null)}},ke=async C=>{try{Da(C);const V=await f();if(!V)return;(await fetch(`${ue()}/api/manga/series/${C}`,{method:"DELETE",headers:{Authorization:`Bearer ${V}`}})).ok?da(ye=>ye.filter(it=>it.id!==C)):Oe("Could not delete series. Please try again.")}catch(V){console.warn("[ReadingLibrary] Failed to delete manga series:",V),Oe("Could not delete series. Please try again.")}finally{Da(null)}},Qe=(C,V)=>{ia(),r?.(C,V)},Y=C=>{const V=Pe.find(le=>le.id===C);V&&(ne("cloud_sync_action",{action:"retry_sync",source:"library_card",kind:V.content_type??"unknown"}),Pn(V,y))},Ze=C=>{const V=Pe.find(le=>le.id===C);V&&(ne("cloud_sync_action",{action:"sync_to_cloud",source:"library_card",kind:V.content_type??"unknown"}),Pn(V,y))},Ut=C=>{const V=Pe.find(ye=>ye.id===C);ne("cloud_sync_action",{action:"remove_from_cloud",source:"library_card",kind:V?.content_type??"unknown"}),D(ye=>ye.map(it=>it.id===C?{...it,cloud_sync_status:null,cloud_size_bytes:null,cloud_page_count:null}:it));const le=tp(ai(),C);Fl(le),T(le)},Ot=C=>{const V=rj(ai(),C);Fl(V),T(V)};wa.current=Pe,Wt.current={handleDelete:te,retryProcessing:I,processImport:xe,processRemaining:Ne,createDeck:F,addMaterialToSeries:Ge,createSeriesForMaterial:gt,handleRetrySync:Y,handleSyncToCloud:Ze,handleUnsynced:Ut,handleTogglePin:Ot,handleRenamed:tt};const is=C=>{k(C),C.includes("limit reached")&&$a()&&b("enrichment","quota_exceeded")},os=o.useMemo(()=>ba.map(C=>{const V=new Set(C.reading_materials.map(le=>
89le.content_type).filter(Boolean));return{id:C.id,title:C.title,content_type:V.size===1?[...V][0]:void 0}}),[ba]);return!!g&&!yt&&Pe.length===0&&U.length===0&&ba.length===0&&!H?e.jsxs("div",{style:{width:"100%",maxWidth:920,margin:"0 auto"},children:[e.jsx(_u,{}),A&&e.jsx("div",{className:"mb-6",children:e.jsx(Br,{variant:"framed",icon:Qa,title:"Upload failed",description:A,action:e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--maple",onClick:()=>k(null),children:"Dismiss"})})}),e.jsx(mi,{onUploadComplete:Qe,onUploadError:is,startScanner:p})]}):e.jsxs("div",{className:"im-library","data-tour-id":"immersion-library-grid",children:[e.jsx(_u,{}),!H&&e.jsxs("div",{className:"im-library-header",children:[e.jsxs("div",{className:"im-library-titlebar",children:[e.jsx("div",{className:"im-library-titlebar-head",children:q?e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:"Free to read"}),e.jsx("div",{className:"sub",children:"No account needed â tap any word or grammar point in context."})]}):e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:"My Library"}),e.jsxs("div",{className:"sub",children:[G.length," item",G.length!==1?"s":""]})]})}),e.jsxs("div",{className:"im-library-actions",children:[y&&e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk im-library-cloud-btn",onClick:()=>N(!0),children:[e.jsx(Js,{"aria-hidden":"true"})," Cloud storage"]}),e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--ink im-library-add",onClick:()=>{kv(),ee(!0)},children:[e.jsx(hm,{}),e.jsx("span",{children:"Add content"})]})]})]}),e.jsxs("div",{className:"im-library-controls wc-pencil-frame wc-pencil-frame--md",children:[e.jsx(tm,{value:lt,onChange:Et,placeholder:"Search your libraryâ¦",ariaLabel:"Search library"}),e.jsxs("div",{className:"im-library-filters",children:[e.jsx(Yr,{label:"Type",value:jt,onChange:C=>Ft(C),options:[{value:"all",label:"All"},{value:"manga",label:"Manga"},{value:"novel",label:"Novel"},{value:"video",label:"Video"}],ariaLabel:"Filter by type"}),e.jsx(Yr,{label:"Sort",value:Ct,onChange:aa,options:Ak,ariaLabel:"Sort"}),e.jsx(Yr,{label:"Status",value:vt,onChange:Le,options:Ik,ariaLabel:"Filter by status"}),pe&&e.jsx("button",{className:"im-library-reset",onClick:re,children:"Reset"})]})]})]}),!1,H?e.jsxs("div",{className:"im-library-inline-uploader",children:[A&&e.jsx("div",{className:"mb-6",children:e.jsx(Br,{variant:"framed",icon:Qa,title:"Upload failed",description:A,action:e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--maple",onClick:()=>k(null),children:"Dismiss"})})}),e.jsx(mi,{onUploadComplete:(C,V)=>{Qe(C,V),ee(!1)},onUploadError:is,onExit:()=>ee(!1),startScanner:p})]}):yt?e.jsx("div",{className:"im-library-skeleton",children:Array.from({length:6}).map((C,V)=>e.jsx("div",{className:"im-library-skeleton-card"},V))}):St?e.jsx(Br,{variant:"framed",icon:Qa,title:"Couldn't load your library",description:St,action:e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--maple",onClick:ia,children:[e.jsx(pi,{size:14,"aria-hidden":"true"})," Retry"]})}):G.length===0?(()=>{const C=Pe.length===0&&U.length===0&&ba.length===0;return e.jsx(Br,{icon:ss,title:C?"Your library is empty":"No items match your filters",description:C?"Upload manga, novels, or subtitle files to get started.":"Try adjusting your search or filter settings.",action:pe?e.jsx("button",{type:"button",className:"wc-cta-square wc-cta-square-quiet--ink",onClick:re,children:"Clear filters"}):null})})():e.jsx("div",{className:"im-library-grid",children:G.map(C=>C.kind==="video"?e.jsx(fk,{show:C.data,onOpen:s,onDelete:Fe,isDeleting:xa===C.data.id,coverage:la[C.data.id],onCreateDeck:V=>{const le=U.flatMap(it=>it.video_sessions).find(it=>it.id===V),ye=!!le&&le.video_episodes.length>0&&le.video_episodes.every(it=>it.cloud_sync_status==="synced");At({kind:"video",id:V,cloudSyncStatus:ye?"synced":null})},creatingDeckForId:Ve},C.data.id):C.kind==="manga_series"?e.jsx(mk,{series:C.data,onOpen:n,onDelete:ke,isDeleting:Na===C.data.id,coverage:E[C.data.id],onCreateDeck:ea,creatingDeckForId:pt},C.data.id):C.kind==="public_series"?e.jsx(gk,{series:C.data,onOpen:V=>m?.(V),onRemove:u},C.data.id):e.jsx(uk,{material:C.data,coverage:qt[C.data.id],onSelect:t,onDelete:ua,onRetry:ca,onProcess:ha,onProcessRemaining:za,onCreateDeck:ea,onViewDeck:es,onAddToSeries:Ea,onCreateSeries:p
89a,isDeleting:ct===C.data.id,isCreatingDeck:pt===C.data.id,availableSeries:os,cloudSyncState:w.get(C.data.id),onRetrySync:Ca,onSyncToCloud:Gt,isPro:y,onUnsynced:Ba,isPinned:j.has(C.data.id),onTogglePin:ka,onRenamed:Wa},C.data.id))}),!H&&!yt&&!St&&(Pe.length>0||U.length>0||ba.length>0)&&e.jsxs("section",{className:"im-library-stats",children:[e.jsxs("div",{className:"im-library-stats-head",children:[e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{children:"Library"}),e.jsx("span",{"aria-hidden":"true",children:"·"}),e.jsx("span",{className:"rule","aria-hidden":"true"})]}),e.jsxs("div",{className:"im-library-stats-grid",children:[e.jsxs("div",{className:"im-library-stats-cell",children:[e.jsx("span",{className:"num",children:Pe.filter(C=>C.content_type!=="novel").length}),e.jsx("span",{className:"lbl",children:"Manga"})]}),e.jsxs("div",{className:"im-library-stats-cell",children:[e.jsx("span",{className:"num",children:ba.length}),e.jsx("span",{className:"lbl",children:"Series"})]}),e.jsxs("div",{className:"im-library-stats-cell",children:[e.jsx("span",{className:"num",children:U.length}),e.jsx("span",{className:"lbl",children:U.length===1?"Show":"Shows"})]}),e.jsxs("div",{className:"im-library-stats-cell",children:[e.jsx("span",{className:"num",children:Pe.filter(C=>C.content_type==="novel").length}),e.jsx("span",{className:"lbl",children:Pe.filter(C=>C.content_type==="novel").length===1?"Novel":"Novels"})]})]})]}),P&&y&&e.jsx(Nk,{materials:Pe,onClose:()=>N(!1),onUnsynced:Ut,onBackfillStarted:()=>{}}),!1,e.jsx(Oa,{children:ft&&e.jsxs(ze.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},exit:{opacity:0,y:8},transition:{duration:.2},className:"im-library-feedback",role:"alert",children:[e.jsx(Qa,{}),e.jsx("span",{children:ft}),e.jsx("button",{className:"dismiss",onClick:()=>Oe(null),"aria-label":"Dismiss",children:e.jsx(rs,{size:14})})]})})]})}const zk=o.forwardRef(function({onUploadComplete:a,initialSelectedItem:s,onInitialItemHandled:n,onViewWishlistItem:r,onAuthRequired:i,onNavigatePath:l},c){const[d,m]=o.useState("none"),u=o.useRef(null);o.useImperativeHandle(c,()=>({setSelectedPath:m,uploaderRef:u}),[]);const{openUpgradeModal:h}=xn();o.useEffect(()=>{},[s]);const p="https://chromewebstore.google.com/detail/shizen-dictionary",g=y=>{if(i){i();return}if(l&&(y==="upload"||y==="extension")){l(y);return}m(y)},f=()=>{ne("immersion_extension_cta_clicked",{source:"path_choice"}),window.open(p,"_blank","noopener")},b=()=>{m("none")};return e.jsx("div",{className:"space-y-8",children:e.jsx(Oa,{mode:"wait",children:d==="none"?e.jsxs(ze.div,{initial:{opacity:0,y:20},animate:{opacity:1,y:0},exit:{opacity:0,y:-20},transition:{duration:.4,ease:"easeOut"},className:"space-y-8",children:[e.jsx(Mj,{onSelect:g}),Ej]},"choice"):d==="upload"?e.jsxs(ze.div,{initial:{opacity:0,x:50},animate:{opacity:1,x:0},exit:{opacity:0,x:-50},transition:{duration:.4,ease:"easeOut"},className:"im-discover-wrap",children:[e.jsx("div",{className:"im-discover-back",children:e.jsxs("button",{type:"button",className:"im-discover-back-btn",onClick:b,children:[e.jsx(Za,{className:"w-3.5 h-3.5","aria-hidden":"true"}),"Back to all paths"]})}),e.jsx(mi,{ref:u,onUploadComplete:a,onUploadError:y=>{console.error("Upload error:",y),typeof y=="string"&&y.includes("limit reached")&&$a()&&h("enrichment","quota_exceeded")}})]},"upload"):d==="extension"?e.jsxs(ze.div,{initial:{opacity:0,x:50},animate:{opacity:1,x:0},exit:{opacity:0,x:-50},transition:{duration:.4,ease:"easeOut"},className:"im-discover-wrap",children:[e.jsxs("div",{className:"im-discover-back",children:[e.jsxs("button",{type:"button",className:"im-discover-back-btn",onClick:b,children:[e.jsx(Za,{className:"w-3.5 h-3.5","aria-hidden":"true"}),"Back to all paths"]}),e.jsxs("div",{className:"im-discover-back-title",children:[e.jsx("span",{className:"glyph","aria-hidden":"true",children:e.jsx(vo,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{children:"Browser Extension"}),e.jsx("p",{children:"Tappable subtitles & lookups on Netflix, YouTube & 20+ sites"})]})]})]}),e.jsx(Dk,{onInstall:f})]},"extension"):e.jsxs(ze.div,{"data-tour-id":"immersion-discover-grid",initial:{opacity:0,x:50}
89,animate:{opacity:1,x:0},exit:{opacity:0,x:-50},transition:{duration:.4,ease:"easeOut"},className:"im-discover-wrap",children:[e.jsxs("div",{className:"im-discover-back",children:[e.jsxs("button",{type:"button",className:"im-discover-back-btn",onClick:b,children:[e.jsx(Za,{className:"w-3.5 h-3.5","aria-hidden":"true"}),"Back to all paths"]}),e.jsxs("div",{className:"im-discover-back-title",children:[e.jsx("span",{className:"glyph","aria-hidden":"true",children:e.jsx(af,{size:18})}),e.jsxs("div",{children:[e.jsx("h3",{children:"Discover Content"}),e.jsx("p",{children:"Browse manga, anime, novels, J-dramas & movies"})]})]})]}),e.jsx(Yj,{isActive:!0,initialSelectedItem:s,onInitialItemHandled:n})]},"discover")})})}),Fk=[{icon:Sr,title:"Process the episode in the app first",body:"In Immersion â Upload, add the episode as a Series or Movie and drop its .srt or .ass subtitle file. Leave analysis on and let it finish â this is what makes each word tappable."},{icon:vo,title:"Install the extension & sign in",body:"Add the Shizen extension to your browser, then sign in with the same account so it can reach your processed library."},{icon:gm,title:"On the streaming page, pull it back",body:"Open the extension on Netflix, YouTube, or any of 20+ sites, choose Enable Video Subtitles, open the âFrom Libraryâ tab, and pick the episode you processed. Every word is now tappable."}];function Dk({onInstall:t}){return e.jsx("div",{className:"wc-pencil-frame wc-pencil-frame--md",style:{position:"relative",isolation:"isolate",padding:"28px 28px 24px"},children:e.jsxs("div",{style:{position:"relative",zIndex:1,display:"flex",flexDirection:"column",gap:20},children:[e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[e.jsx("p",{className:"serif",style:{margin:0,fontFamily:"'Shippori Mincho', serif",fontSize:20,fontWeight:600,color:"var(--ink)"},children:"Tappable subtitles, anywhere you watch."}),e.jsx("p",{style:{margin:0,fontSize:14.5,lineHeight:1.55,color:"var(--ink-soft)"},children:"The flow runs backwards from what youâd expect: you process an episodeâs subtitles in Shizen first, then the extension overlays that processed track onto the video. It also gives you Shift+hover dictionary lookups on any website."})]}),e.jsx("ol",{style:{listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:14},children:Fk.map((a,s)=>{const n=a.icon;return e.jsxs("li",{style:{display:"flex",gap:14,alignItems:"flex-start"},children:[e.jsxs("span",{"aria-hidden":"true",style:{position:"relative",flexShrink:0,width:40,height:40,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:"var(--wc-radius-leaf)",background:"hsl(var(--brand-chat) / 0.12)",border:"1px solid hsl(var(--brand-chat) / 0.20)",color:"hsl(var(--brand-chat))"},children:[e.jsx(n,{size:20}),e.jsx("span",{style:{position:"absolute",top:-6,left:-6,width:18,height:18,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:"var(--wc-radius-ink)",background:"hsl(var(--brand-chat))",color:"#fff",fontSize:11,fontWeight:600,fontFamily:"'JetBrains Mono', monospace"},children:s+1})]}),e.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:2,paddingTop:1},children:[e.jsx("p",{style:{margin:0,fontSize:14.5,fontWeight:600,color:"var(--ink)"},children:a.title}),e.jsx("p",{style:{margin:0,fontSize:13.5,lineHeight:1.5,color:"var(--ink-soft)"},children:a.body})]})]},a.title)})}),e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:16,flexWrap:"wrap"},children:[e.jsx(ac,{as:"button",variant:"ink",onClick:t,style:{background:"hsl(var(--brand-chat))",borderColor:"hsl(var(--brand-chat))",color:"#fff"},children:"Install the extension"}),e.jsx("span",{style:{fontSize:12.5,color:"var(--ink-soft)",opacity:.8},children:"Opens the Chrome Web Store in a new tab."})]}),e.jsx(Lk,{})]})})}function Lk(){return e.jsx("p",{style:{margin:0,fontSize:12,lineHeight:1.5,color:"var(--ink-soft)",opacity:.75,borderTop:"1px solid var(--wc-hairline)",paddingTop:14},children:"Only episodes youâve processed (the extensionâs âFrom Libraryâ tab) are tappable. The âAuto-detectedâ and âFrom Fileâ tabs show plain subtitles."})}function Ok(t){const a=()=>t.setCursorState({visible:!1,x:0,y:0,clicking:!1}),s=[],n=(i,l)=>{const c=setTimeout(l,i);return s.push(c),c},r=()=>{for(;s.length>0;){const i=s.pop();i!==void 0&&clearTimeout(i)}};return[{id:"welcome",type:"card",content:e.jsxs("div",{className:"im-tour-welcome",children:[e.jsx("img",{className:"wc-tour-welcome-art",src:"/watercolor/system-v2/modules/journey-immersion.webp",width:"96",height:"96",alt:""}),e.jsx("h2",{className:"im-tour-welcome-title",children:"Read, Watch, Listen"}),e.jsx("p",{className:"im-tour-welcome-lede",children:"Bring supported manga, books or video subtitles. Look up words, explore grammar in context, and keep your place in the story."}),e.jsx("p",{className:"im-tour-welcome-hint",children:"Manga · Anime · N
89ovels · Subtitles"})]})},{id:"path-cards",type:"navigate",targetId:"immersion-path-cards",title:"Two Ways In",position:"top",spotlightPadding:12,onEnter:()=>t.navigateToTab("overview"),content:e.jsxs("p",{children:[e.jsx("strong",{children:"Upload"})," what you already have, or install the"," ",e.jsx("strong",{children:"browser extension"})," to learn on any website."]})},{id:"extension-card",type:"navigate",targetId:"immersion-extension-card",title:"Take It Everywhere",position:"top",spotlightPadding:12,onEnter:()=>{t.navigateToTab("overview"),ne("immersion_extension_cta_clicked",{source:"tour"})},content:e.jsxs("p",{children:["Install the ",e.jsx("strong",{children:"browser extension"})," to learn beyond Shizen: Shift+hover for instant word lookups on any site, and"," ",e.jsx("strong",{children:"tappable subtitles"})," on Netflix, YouTube, and 20+ streaming services. The trick â ",e.jsx("strong",{children:"process an episodeâs subtitles in the app first"}),", then the extension pulls that track back onto the video."]})},{id:"uploader-category",type:"navigate",targetId:"uploader-category-selector",title:"Pick Your Content",position:"bottom",spotlightPadding:12,onEnter:()=>t.openUploader(),content:e.jsxs("p",{children:[e.jsx("strong",{children:"Manga"})," handles scans, CBZ, PDF, and EPUB with images."," ",e.jsx("strong",{children:"Novel"})," handles text EPUB, Kindle (DRM-free), or scanned pages."," ",e.jsx("strong",{children:"Series"})," and ",e.jsx("strong",{children:"Movie"})," are for subtitle files."]})},{id:"demo-reader",type:"navigate",targetId:"demo-reader-textbox",title:"Your Reading Experience",position:"left",spotlightPadding:12,onEnter:()=>{t.resetUploader(),t.openDemoReader()},content:e.jsxs("p",{children:["Once processed, every ",e.jsx("strong",{children:"word becomes tappable"}),". Furigana appears above kanji, and grammar patterns are annotated so you can see conjugation at a glance."]})},{id:"demo-lookup-and-ai",type:"navigate",targetId:"demo-token-panel",title:"Tap a Word, Ask the AI",position:"left",spotlightPadding:8,onEnter:()=>{t.openDemoReader(),n(500,()=>{t.hoverCluster("demo-box-2",16),n(50,()=>{const i=t.getClusterRect("demo-box-2",16)??t.getTextBoxRect("demo-box-2");if(!i)return;const l=i.left+i.width/2,c=i.top+i.height/2;t.setCursorState({visible:!0,x:l,y:c,clicking:!1}),n(800,()=>{t.setCursorState({visible:!0,x:l,y:c,clicking:!0}),n(400,()=>{t.simulateTokenClick("demo-box-2",16),a()})})})})},onExit:()=>{r(),t.clearClusterHover(),t.closeTokenPanel(),a()},content:e.jsxs("p",{children:["Tap any word for its ",e.jsx("strong",{children:"reading"}),","," ",e.jsx("strong",{children:"dictionary form"}),", and ",e.jsx("strong",{children:"meanings"})," â the conjugation cluster lights up, and grammar patterns link to mini- lessons. Stuck? ",e.jsx("strong",{children:"AI help"})," is a tab inside the same lookup â ask about that exact word in context."]})}]}function Bk({onComplete:t,onSkip:a,tourActions:s}){const n=o.useRef(t);n.current=t;const r=o.useRef(a);r.current=a;const i=o.useMemo(()=>({id:"immersion-tour",steps:Ok(s),storageKey:"reading.onboarding.completed",onComplete:()=>{ne("immersion_onboarding_completed"),n.current()},onSkip:c=>{ne("immersion_onboarding_skipped",{step:c}),s.setCursorState({visible:!1,x:0,y:0,clicking:!1}),s.clearClusterHover(),s.closeTokenPanel(),s.closeDemoReader(),s.navigateToTab("overview"),s.resetUploader(),r.current()}}),[s]),{markCompleted:l}=sm("reading");return e.jsx(qp,{config:i,autoStart:!0,finishLabel:"Start",accent:"dusk",onPersistCompletion:()=>{l()}})}let Kn=null,Dr=null;const Xc=300*1e3,Qc=new Set;async function pp(){return Kn&&Date.now()-Kn.fetchedAt<Xc?Kn.material:Dr||(Dr=(async()=>{try{const t=await fetch(`${ue()}/api/reading/public/sample`);if(!t.ok)return null;const s=(await t.json())?.material??null;return Kn={material:s,fetchedAt:Date.now()},s?.id&&Qc.add(s.id),s}catch{return null}finally{Dr=null}})(),Dr)}function qk(){const[t,a]=o.useState(Kn?.material??null),[s,n]=o.useState(!Kn);return o.useEffect(()=>{let r=!1;return pp().then(i=>{r||(a(i),n(!1))}),()=>{r=!0}},[]),{material:t,loading:s}}function Uk(t){return t?Kn?.material?.id===t:!1}function Vk(t){return t?Qc.has(t)||Uk(t):!1}let Tn=null,Lr=null;async function fp(){return Tn&&Date.now()-Tn.fetchedAt<Xc?Tn.list:Lr||(Lr=(async()=>{try{const t=await fetch(`${ue()}/api/reading/public/series`);
89if(!t.ok)return Tn?.list??[];const a=await t.json(),s=Array.isArray(a)?a:[];return Tn={list:s,fetchedAt:Date.now()},s}catch{return Tn?.list??[]}finally{Lr=null}})(),Lr)}const hl=new Map,pl=new Map;async function Ri(t){const a=hl.get(t);if(a&&Date.now()-a.fetchedAt<Xc)return a.detail;const s=pl.get(t);if(s)return s;const n=(async()=>{try{const r=await fetch(`${ue()}/api/reading/public/series/${encodeURIComponent(t)}`);if(!r.ok)return hl.set(t,{detail:null,fetchedAt:Date.now()}),null;const i=await r.json();hl.set(t,{detail:i,fetchedAt:Date.now()});for(const l of i?.volumes??[])l?.id&&Qc.add(l.id);return i}catch{return null}finally{pl.delete(t)}})();return pl.set(t,n),n}function Kk(){const[t,a]=o.useState(Tn?.list??[]),[s,n]=o.useState(!Tn);return o.useEffect(()=>{let r=!1;return fp().then(i=>{r||(a(i),n(!1))}),()=>{r=!0}},[]),{series:t,loading:s}}function Kl(t){return(t??"").toLowerCase().trim().replace(/[^a-z0-9ã-é¿¿]+/g,"-").replace(/^-+|-+$/g,"")}function Hl(t){const a=(t??"").trim();return/^\d+$/.test(a)?parseInt(a,10):null}function Hk(t){return[...t].sort((a,s)=>{const n=Hl(a.volume),r=Hl(s.volume);if(n!==r)return n===null?1:r===null?-1:n-r;const i=a.created_at??"",l=s.created_at??"";return i!==l?i<l?-1:1:(a.id??"")<(s.id??"")?-1:a.id===s.id?0:1})}function Wk(t,a){return`volume-${Hl(t)??a}`}function gp(t){const a=Hk(t),s=new Map;return a.forEach((n,r)=>s.set(n.id,Wk(n.volume,r+1))),s}function yp(t){const a=Kl(t.title),s=(t.id||"").slice(0,8);return a?`${a}-${s}`:s||"material"}function Un(t,a,s){if(a&&a.slug){const r=s.isPublic?"public":Kl(s.ownerName)||"me",i=s.volumeSlug??gp(a.volumes??[t]).get(t.id)??"volume-1";return`/immersion/read/${r}/${a.slug}/${i}`}return s.isPublic?`/immersion/library/read/${t.id}`:`/immersion/read/${Kl(s.ownerName)||"me"}/${yp(t)}`}function Gk({detail:t,onBack:a,onOpenVolume:s}){const{series:n,volumes:r}=t,i=r.reduce((l,c)=>l+(c.total_pages||0),0);return e.jsxs("div",{className:"im-public-detail",children:[e.jsx("div",{className:"wc-back-cap",style:{marginBottom:16},children:e.jsxs("button",{type:"button",className:"im-lesson-back",onClick:a,children:[e.jsx(Za,{size:15,"aria-hidden":"true"}),"Back to Library"]})}),e.jsxs("header",{className:"im-public-detail-hero wc-pencil-frame wc-pencil-frame--md",children:[n.cover_url&&e.jsx("div",{className:"im-public-detail-cover",children:e.jsx("img",{src:n.cover_url,alt:n.title,loading:"lazy",decoding:"async"})}),e.jsxs("div",{className:"im-public-detail-heroinfo",children:[e.jsxs("span",{className:"im-public-detail-eyebrow",children:[e.jsx("span",{className:"lbl",children:"Public series"}),e.jsx("span",{"aria-hidden":"true",children:"·"}),e.jsx("span",{className:"jp",children:"å ¬éã·ãªã¼ãº"})]}),e.jsx("h1",{className:"im-public-detail-title",children:n.title}),n.title_jp&&e.jsx("p",{className:"im-public-detail-title-jp jp",children:n.title_jp}),e.jsxs("div",{className:"im-public-detail-meta",children:[e.jsxs("span",{children:[e.jsx(ss,{size:15,"aria-hidden":"true"}),r.length," volume",r.length!==1?"s":""]}),i>0&&e.jsxs("span",{children:[i," page",i!==1?"s":""]})]})]})]}),e.jsxs("section",{className:"im-public-detail-vols",children:[e.jsxs("div",{className:"im-public-detail-vols-head",children:[e.jsx("span",{className:"rule wc-pencil-rule-h","aria-hidden":"true"}),e.jsx("span",{children:"Volumes"}),e.jsx("span",{"aria-hidden":"true",children:"·"}),e.jsx("span",{className:"jp",children:"å·»"}),e.jsx("span",{className:"rule wc-pencil-rule-h","aria-hidden":"true"})]}),r.length===0?e.jsxs("div",{className:"im-public-detail-empty",children:[e.jsx(ss,{"aria-hidden":"true"}),e.jsx("p",{children:"No volumes available yet."})]}):e.jsx("ul",{className:"im-public-detail-vollist",children:r.map((l,c)=>e.jsx("li",{children:e.jsxs("button",{type:"button",className:"im-public-detail-volrow wc-pencil-frame wc-pencil-frame--xs",onClick:()=>s(l.id),children:[e.jsx("span",{className:"num jp","aria-hidden":"true",children:c+1}),e.jsx("span",{className:"im-public-detail-volname",children:l.title}),l.total_pages>0&&e.jsxs("span",{className:"im-public-detail-volpages",children:[l.total_pages," pg."]}),e.jsxs("span",{className:"im-public-detail-volread wc-cta-square wc-cta-square--ink",children:["Read ",e.jsx(As,{size:14,"aria-hidden":"true"})]})]})},l.id))})]})]})}function bp({sourceLink:t=!1}){return e.jsxs("div",{className:"im-hero-demo","aria-label":"Interactive manga reader preview",children:[e.jsx("style",{children:` 90 .im-hero-demo { width: 100%; display: flex; flex-direction: column; } 91 92 /* HeroMangaDemo renders its own homepage caption ("Tap any word"); hide 93 it here and render the standard two-tone module tip below instead. */ 94 .im-hero-demo .hero-manga-demo__hint { display: none; } 95 96 /* Crop the portrait manga page (~1.33:1) into the canonical square hero 97 box (340Ã334) so immersion matches kana/grammar/vocab/chat. The stage's 98 own inline height (page.height à scale) is overridden to the demo height; 99 the stage's overflow:hidden clips the bottom of the page. !important 100 beats the inline style React sets on the stage. (Top + sides are cropped 101 by the frameCrop prop below, which trims the page's printed border.) */ 102 .im-hero-demo .hero-manga-demo__stage { 103 height: var(--wc-hero-demo-h, 334px) !important; 104 } 105 106 /* Pencil outline around the manga window â the same painted 9-slice 107 border the vocab/kana/grammar cards wear (.wc-pencil-frame--xs), drawn 108 OVER the page edges (z-index above the scaled layer) so it reads as the 109 demo's frame now that the page's own printed border is cropped away. */ 110 .im-hero-demo .hero-manga-demo__stage::before { 111 content: ''; 112 position: absolute; 113 inset: 0; 114 pointer-events: none; 115 border-style: solid; 116 border-color: transparent; 117 border-width: 10px 14px; 118 border-image-source: var(--wc-asset-pencil-container); 119 border-image-slice: 80 120 fill; 120 border-image-width: 10px 14px; 121 border-image-repeat: stretch; 122 /* Heavier than the 0.55 system default: this frame is painted OVER the 123 manga art (not on plain paper like the vocab/kana cards), so at 0.55 124 the busy art shows through and it reads as if it's behind the image. 125 0.92 makes the graphite sit clearly in the forefront. */ 126 opacity: 0.92; 127 filter: var(--wc-pencil-filter); 128 z-index: 2; 129 } 130 131 /* Tip under the panel â same format as the vocab/kana/grammar/chat hero 132 tips (mono, uppercase, two-tone .key accent). */ 133 .im-hero-tip { 134 flex-shrink: 0; 135 margin: 11px 0 0; 136 font-family: 'JetBrains Mono', monospace; 137 font-size: 10px; 138 letter-spacing: 0.06em; 139 text-transform: uppercase; 140 color: var(--ink-soft, #55606c); 141 text-align: center; 142 } 143 .im-hero-tip .key { color: hsl(var(--module-accent)); font-weight: 700; } 144 145 /* ââ Hero layout: copy | demo two-column on desktop, fit-to-viewport 146 single column on mobile. Mirrors the chat/vocab/kana/grammar
147 heroes. Scoped to the unlogged immersion hero via 148 :has(.im-hero-demo). ââ */ 149 @media (min-width: 768px) { 150 .wc-root.im-logged .im-page-header:has(.im-hero-demo) { 151 display: grid; 152 grid-template-columns: minmax(0, 1fr) clamp(248px, 24vw, 340px); 153 grid-template-areas: 154 "eyebrow eyebrow" 155 "title art" 156 "lede art" 157 "ctas art"; 158 column-gap: clamp(24px, 3vw, 48px); 159 align-items: start; 160 } 161 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-page-eyebrow { grid-area: eyebrow; } 162 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-page-title { grid-area: title; } 163 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .hero-lede { grid-area: lede; } 164 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-hero-ctas { grid-area: ctas; margin: 18px 0 0; } 165 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-hero-demo { 166 grid-area: art; 167 justify-self: end; 168 align-self: center; 169 width: 100%; 170 max-width: var(--wc-hero-demo-w, 340px); 171 } 172 } 173 174 @media (max-width: 767px) { 175 .wc-root.im-logged .im-page-header:has(.im-hero-demo) { 176 display: flex; 177 flex-direction: column; 178 align-items: stretch; 179 gap: clamp(2px, 0.6vh, 6px); 180 } 181 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-page-eyebrow, 182 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-page-title { margin: 0; } 183 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-page-title--image img { 184 max-height: clamp(38px, 6.5vh, 56px); 185 width: auto; 186 } 187 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .hero-lede { 188 font-size: clamp(12px, 3.2vw, 14px); 189 line-height: 1.45; 190 margin: 0; 191 } 192 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-hero-demo { 193 align-self: center; 194 width: min(300px, 82vw); 195 margin: clamp(8px, 1.6vh, 14px) auto 0; 196 --wc-hero-demo-h: clamp(298px, 44vh, 334px); 197 } 198 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-hero-ctas { 199 width: 100%; 200 align-items: stretch; 201 justify-content: center; 202 margin: clamp(6px, 1.2vh, 12px) 0 0; 203 } 204 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-hero-ctas .btn-wc { width: 100%; min-width: 0; justify-content: center; } 205 .wc-root.im-logged .im-page-header:has(.im-hero-demo) .im-hero-ctas .wc-hero-link { display: none; } 206 } 207 `}),e.jsx(im,{frameCrop:{sides:7,top:7}}),t?e.jsx("p",{className:"im-hero-tip",children:e.jsx("a",{href:"/#reading-demo",children:"Try the interactive word & grammar lookup"})}):e.jsxs("p",{className:"im-hero-tip","aria-hidden":"true",children:[e.jsx("span",{className:"key",children:"Tap any word"})," â reading, meaning, grammar"]})]})}const Yk="/assets/hero-manga-demo-HIXM-iZC.webp",or=[["library","Library"],["lookup","Lookup"],["help","Sentence help"]];function Jk(){const[t,a]=o.useState("library"),[s,n]=o.useState("meaning"),r=o.useRef({}),i=o.useRef(null),l=(d,m=!1,u=!1)=>{a(d),m&&requestAnimationFrame(()=>r.current[d]?.focus({preventScroll:!0})),u&&requestAnimationFrame(()=>{const h=i.current;!h||h.getBoundingClientRect().top>=(document.querySelector(".app-header")?.getBoundingClientRect().bottom??64)+8||h.scrollIntoView({behavior:window.matchMedia?.("(prefers-reduced-motion: reduce)").matches?"instant":"smooth",block:"start"})})},c=(d,m)=>{const u=d.key==="ArrowRight"?(m+1)%or.length:d.key==="ArrowLeft"?(m+or.length-1)%or.length:d.key==="Home"?0:d.key==="End"?or.length-1:-1;u<0||(d.preventDefault(),l(or[u][0],!0))};return e.jsx("div",{className:"mi-lesson","data-immersion-lesson":"",children:e.jsxs("div",{className:"mi-paper",children:[e.jsx("div",{className:"mi-tabs",role:"tablist","aria-label":"Explore the immersion tools",ref:i,children:or.map(([d,m],u)=>e.jsx("button",{ref:h=>{r.current[d]=h},type:"button",id:`mi-tab-${d}`,role:"tab","aria-controls":`mi-${d}`,"aria-selected":t===d,tabIndex:t===d?0:-1,onClick:()=>l(d),onKeyDown:h=>c(h,u),children:m},d))}),e.jsxs("div",{className:"mi-panels",children:[e.jsxs("section",{className:"mi-panel",id:"mi-library",role:"tabpanel","aria-labelledby":"mi-tab-library",tabIndex:0,hidden:t!=="library",children:[e.jsx("p",{className:"mi-label",children:"A small place to begin"}),e.jsx("h3",{children:"Pick a page. See where it takes you."}),e.jsxs("div",{className:"mi-library-layout",children:[e.jsxs("button",{type:"button",className:"mi-sample",onClick:()=>l("lookup",!0,!0),"aria-label":"Open the Shizen manga sample",children:[e.jsx("img",{src:Yk,width:"1086",height:"1448",loading:"lazy",alt:"A manga character talking about reading Japanese with an app"}),e.jsxs("span",{className:"mi-sample-copy",children:[e.jsx("span",{className:"mi-label",children:"Manga · sample page"}),e.jsx("strong",{children:"A little Japanese, in context."}),e.jsxs("span",{className:"mi-sample-action",children:["Open this page ",e.jsx("span",{"aria-hidden":"true",children:"â"})]})]})]}),e.jsxs("div",{className:"mi-library-copy",children:[e.jsx("h4",{children:"Your interests choose the starting point."}),e.jsx("p",{children:"Bring supported manga, books or video into your library. Vocabulary and grammar coverage help you see how much looks familiar before you begin."}
207),e.jsx("p",{children:"For now, try this short manga exchange. Its words and grammar are ready to explore."}),e.jsxs("button",{type:"button",className:"mi-soft-action",onClick:()=>l("lookup",!0,!0),children:["Try the manga lookup ",e.jsx("span",{"aria-hidden":"true",children:"â"})]}),e.jsx("p",{className:"mi-note",children:"Coverage reflects recorded knowledge, not a comprehension score."})]})]})]}),e.jsxs("section",{className:"mi-panel",id:"mi-lookup",role:"tabpanel","aria-labelledby":"mi-tab-lookup",tabIndex:0,hidden:t!=="lookup",children:[e.jsx("p",{className:"mi-label",children:"Help beside the words"}),e.jsx("h3",{children:"Stay with the story. Open what you need."}),e.jsxs("div",{className:"mi-reader-layout",children:[e.jsxs("div",{className:"mi-reader-guide",children:[e.jsxs("p",{children:["The lookup is open on ",e.jsx("span",{lang:"ja",children:"ããã°"}),". Try another highlighted word in the speech bubbles."]}),e.jsxs("ol",{children:[e.jsxs("li",{children:[e.jsx("strong",{children:"Find the word."}),e.jsx("span",{children:"Explore its meaning, examples, connected words and picture mnemonic."})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"See how it works."}),e.jsx("span",{children:"Switch to Grammar for the patternâs mini lesson and building blocks."})]}),e.jsxs("li",{children:[e.jsx("strong",{children:"Keep it for later."}),e.jsx("span",{children:"Try Save to deck, or choose a grammar learning stage. Changes stay in this demo."})]})]}),e.jsxs("button",{type:"button",className:"mi-text-action",onClick:()=>l("help",!0,!0),children:["Look at the whole sentence ",e.jsx("span",{"aria-hidden":"true",children:"â"})]})]}),e.jsx("div",{className:"mi-reader",children:e.jsx("div",{className:"mi-manga-frame",children:e.jsx(im,{mode:"immersion-inline",initialSurface:"ããã°"})})})]})]}),e.jsxs("section",{className:"mi-panel",id:"mi-help",role:"tabpanel","aria-labelledby":"mi-tab-help",tabIndex:0,hidden:t!=="help",children:[e.jsx("p",{className:"mi-label",children:"When a whole line needs a little help"}),e.jsx("h3",{children:"Ask about the part that hasnât clicked."}),e.jsxs("div",{className:"mi-sentence",children:[e.jsx("span",{lang:"ja",children:"ãã®ã¢ããªãããã°ãä½ã§ãèªãããã "}),e.jsx("p",{children:"The same line from the manga. Choose a question below."})]}),e.jsxs("div",{className:"mi-help-layout",children:[e.jsxs("div",{className:"mi-questions",role:"group","aria-label":"Choose a sample question",children:[e.jsx("button",{type:"button","aria-expanded":s==="meaning","aria-controls":"mi-answer-meaning",onClick:()=>n("meaning"),children:"What does this line mean?"}),e.jsx("button",{type:"button","aria-expanded":s==="pieces","aria-controls":"mi-answer-pieces",onClick:()=>n("pieces"),children:"How do the pieces fit?"}),e.jsxs("button",{type:"button","aria-expanded":s==="ending","aria-controls":"mi-answer-ending",onClick:()=>n("ending"),children:["What does ",e.jsx("span",{lang:"ja",children:"ãã "})," add?"]})]}),e.jsxs("div",{className:"mi-answers","aria-live":"polite","aria-atomic":"true",children:[e.jsxs("div",{id:"mi-answer-meaning",hidden:s!=="meaning",children:[e.jsx("h4",{children:"âWith this app, I can read anything.â"}),e.jsx("p",{children:"More literally: âIf I have this app, I can read anything.â The speaker is explaining what the app makes possible."})]}),e.jsxs("div",{id:"mi-answer-pieces",hidden:s!=="pieces",children:[e.jsx("h4",{children:"One idea, built from smaller pieces."}),e.jsxs("dl",{children:[e.jsxs("div",{children:[e.jsx("dt",{lang:"ja",children:"ãã®ã¢ããªãããã°"}),e.jsxs("dd",{children:["If I have this app â ",e.jsx("span",{lang:"ja",children:"ããã°"})," is the conditional form of ",e.jsx("span",{lang:"ja",children:"ãã"}),"."]})]}),e.jsxs("div",{children:[e.jsx("dt",{lang:"ja",children:"ä½ã§ã"}),e.jsx("dd",{children:"Anything â it leaves the choice open."})]}),e.jsxs("div",{children:[e.jsx("dt",{lang:"ja",children:"èªãããã "}),e.jsxs("dd",{children:["I can read â ",e.jsx("span",{lang:"ja",children:"èªãã"})," expresses ability, and ",e.jsx("span",{lang:"ja",children:"ãã "})," adds an explanatory tone."]})]})]})]}),e.jsxs("div",{id:"mi-answer-ending",hidden:s!=="ending",children:[e.jsx("h4",{children:"A little âhereâs the thingâ¦â"}),e.jsxs("p",{children:[e.jsx("span",{lang:"ja",children:"ãã "})," is the conversational form of ",e.jsx("span",{lang:"ja",children:"ã®ã "}),". It presents the statement as an explanation or realisation, rather than only stating the fact."]}),e.jsx("p",{children:"Here, it helps convey the speakerâs discovery: with this app, reading all sorts of things becomes possible."})]})]})]}),e.jsxs("div",{className:"mi-help-footer",children:[e.jsxs("button",{type:"button",className:"mi-text-action",onClick:()=>l("lookup",!0,!0),children:["Back to the words and grammar ",e.jsx("span",{"aria-hidden":"true",children:"â"})]}),e.jsx("p",{className:"mi-note",children:"A fictional exchange for exploring the reading tools. Sample AI reading help with prepared answers. No live AI request or credits used."})]})]})]}),e.jsxs("div",{className:"mi-footer",children:[e.jsx("span",{children:"Explore here without an account · demo changes arenât saved"}),e.jsxs(Wn,{to:"/immersion/library",children:["Explore your library ",e.jsx("span",{"aria-hidden":"true",children:"â"})]})]})]})})}const Au="/watercolor/system-v2/public-pages/concepts",Xk=[["Do I need to finish the course first?","No. Try a small piece alongside kana, vocabulary and grammar study. Familiar characters and basic patterns can make the experience more comfortable; choose the amount of help and reading that suits you."],["Which files can I bring?","The readers support manga scans, digital books and video subtitles. Accepted formats and import options depend on the source; check the live upload flow before preparing a library."],["What can I do when lookup is not enough?","Connected grammar explanations can help you unpack a pattern. Optional AI reading assistance can also examine a sentence in context, using credits."],["What is free, and what uses credits?","Kana, vocabulary and grammar learning are free. Some immersion processing, AI assistance and mnemonic tools use credits, and paid options provide additional allowances or storage. Check the current plans for details."],["How do I return to words I meet?","Save useful vocabulary to study and review, or prepare a deck from a title you want to explore. Your next study session can connect to the Japanese you have been reading."]];function Qk(){return e.jsxs("header",{className:"im-page-header ml-hero im-public-hero",children:[e.jsx("h1",{className:"im-page-title",children:"A little help. More of the story."}),e.jsxs("p",{className:"hero-lede wc-herolede-full",children:[e.jsx(Nf,{page:"immersion",ariaLabel:"Module features",lead:"Learn from your content with",phrases:[{text:"Manga, books & video",accent:"chat",paint:"purple"},{text:"Contextual word meanings",accent:"chat",paint:"purple"},{text:"Grammar explained in context",accent:"chat",paint:"purple"},{text:"Vocab & grammar coverage",accent:"chat",paint:"purple"},{text:"Content-based study decks",accent:"chat",paint:"purple"},{text:"Mnemonics from your content",accent:"chat",paint:"purple"}]}),e.jsx("span",{className:"hero-rotation__intro",children:"Bring supported manga, books or video subtitles. Explore a word, understand a pattern, and find your way to the next line."})]}),e.jsx(bp,{sourceLink:!0}
207),e.jsxs("div",{className:"hero-ctas",children:[e.jsx(Wn,{className:"ml-button",to:"/immersion/library",children:"Open the library"}),e.jsxs("a",{className:"ml-link ml-hero-link",href:"#module-preview",children:[e.jsx("span",{children:"Try the reading demo"}),e.jsx("span",{className:"ml-hero-link-arrow","aria-hidden":"true",children:"â"})]})]}),e.jsxs("p",{className:"ml-hero-proof",children:["Some content processing and assistance tools use credits. ",e.jsx(Wn,{to:"/#pricing",children:"See current plans for allowances and storage."})]})]})}function Zk(){return e.jsxs("div",{className:"wc-root im-overview im-anon-marketing ml-immersion-story",children:[e.jsxs("section",{className:"ml-section ml-feature-row ml-story-opening",children:[e.jsxs("div",{className:"ml-copy",children:[e.jsx("p",{className:"ml-eyebrow",children:"Let your interests lead"}),e.jsx("h2",{children:"Start with something you want to spend time with."}),e.jsx("p",{children:"A familiar scene. A few pages. A show you keep returning to. You can study the basics and explore real Japanese alongside them."}),e.jsx("p",{children:"Choose a manageable piece, use the help you need, and leave room to enjoy it."})]}),e.jsx("img",{className:"ml-art ml-content-shelf",src:`${Au}/content-shelf.webp`,alt:"Manga, a book and a tablet together on a painted shelf",loading:"lazy"})]}),e.jsxs("section",{className:"ml-section ml-demo-section imm-section",id:"module-preview",children:[e.jsxs("div",{className:"ml-section-head",children:[e.jsx("p",{className:"ml-eyebrow",children:"Try a little reading"}),e.jsx("h2",{children:"From your library to a line that makes sense."}),e.jsx("p",{className:"ml-lede",children:"Open a page, tap a word, or explore the grammar behind a sentence. Try the tools at your own pace."})]}),e.jsx(Jk,{})]}),e.jsxs("section",{className:"ml-section",children:[e.jsxs("div",{className:"ml-section-head",children:[e.jsx("p",{className:"ml-eyebrow",children:"Help beside the Japanese"}),e.jsx("h2",{children:"A word, a pattern, a useful next step."})]}),e.jsxs("div",{className:"ml-steps",children:[e.jsxs("article",{className:"ml-step",children:[e.jsx("span",{className:"ml-step-number",children:"1"}),e.jsx("h3",{children:"Find the meaning here."}),e.jsx("p",{children:"Word lookups bring readings and meanings close to the text. Context helps distinguish words that share the same spelling."})]}),e.jsxs("article",{className:"ml-step",children:[e.jsx("span",{className:"ml-step-number",children:"2"}),e.jsx("h3",{children:"Open the grammar behind it."}),e.jsx("p",{children:"Grammar annotations connect to mini lessons, familiar building blocks and the course that teaches the pattern."})]}),e.jsxs("article",{className:"ml-step",children:[e.jsx("span",{className:"ml-step-number",children:"3"}),e.jsx("h3",{children:"Bring something back to study."}),e.jsx("p",{children:"Save useful vocabulary, prepare a content-based study deck, and revisit words with review and mnemonic support."})]})]})]}),e.jsxs("section",{className:"ml-section ml-feature-row ml-coverage-story",children:[e.jsx("img",{className:"ml-art",src:`${Au}/immersion-garden.webp`,alt:"An open book and headphones beside a quiet stream",loading:"lazy"}),e.jsxs("div",{className:"ml-copy",children:[e.jsx("p",{className:"ml-eyebrow",children:"Choose what to try"}),e.jsx("h2",{children:"See what looks familiar. Then see how it feels."}),e.jsx("p",{children:"Separate vocabulary and grammar coverage estimates compare a title with your recorded knowledge. Manga and novels can also show kanji coverage."}),e.jsx("p",{children:"Use them to find a starting point or prepare a study deck. Your experience of reading still matters."}),e.jsx("p",{className:"ml-note",children:"Coverage is not a comprehension score or a promise that a title will feel easy."})]})]}),e.jsxs("section",{className:"ml-section",children:[e.jsxs("div",{className:"ml-section-head",children:[e.jsx("p",{className:"ml-eyebrow",children:"Your content, different ways in"}),e.jsx("h2",{children:"Pages, chapters and subtitles."}),e.jsx("p",{className:"ml-lede",children:"Import supported files you have access to. The available tools depen
207d on the reader and source."})]}),e.jsxs("div",{className:"ml-cards ml-format-cards",children:[e.jsxs("article",{className:"ml-card",children:[e.jsx("h3",{children:"Manga"}),e.jsx("p",{children:"Explore supported manga scans with word and grammar help beside the dialogue."})]}),e.jsxs("article",{className:"ml-card",children:[e.jsx("h3",{children:"Books"}),e.jsx("p",{children:"Read supported digital books by chapter, with lookup help when a sentence needs a closer look."})]}),e.jsxs("article",{className:"ml-card",children:[e.jsx("h3",{children:"Video"}),e.jsx("p",{children:"Work with supported video and subtitle files. Processed subtitles connect the spoken line to word and grammar help."})]})]}),e.jsxs("div",{className:"ml-extension-note",children:[e.jsx("h3",{children:"Take supported reading help into your browser."}),e.jsx("p",{children:"Look up Japanese on a webpage, or bring annotated subtitles from your Shizen library into a supported video site."}),e.jsx(Wn,{className:"ml-link",to:"/immersion/extension",children:"Explore the browser extension"})]}),e.jsx("p",{className:"ml-note",children:"Study decks do not include the underlying manga, book or video. Content-based mnemonic generation and other assistance may use credits."})]}),e.jsxs("section",{className:"ml-section ml-faq",children:[e.jsxs("div",{className:"ml-section-head",children:[e.jsx("p",{className:"ml-eyebrow",children:"A few things to know"}),e.jsx("h2",{children:"Make yourself comfortable."})]}),Xk.map(([t,a])=>e.jsxs("details",{children:[e.jsx("summary",{children:t}),e.jsx("p",{children:a})]},t))]}),e.jsxs("section",{className:"ml-section ml-closer",children:[e.jsx("img",{className:"ml-closing-nature",src:"/watercolor/system-v2/modules/journey-immersion.webp",alt:"",loading:"lazy"}),e.jsx("h2",{children:"Your next page can be a small one."}),e.jsx("p",{children:"Bring something you are curious about. Learn a little, explore a little, and keep going at your pace."}),e.jsxs("div",{className:"ml-closing-actions",children:[e.jsx(Wn,{className:"ml-button",to:"/immersion/library",children:"Explore immersion"}),e.jsx(Wn,{className:"ml-button ml-button--secondary",to:"/#pricing",children:"See current plans"})]})]})]})}const Iu={sm:"text-sm",base:"text-base",lg:"text-lg",xl:"text-xl"};function e0({primaryTokens:t,primaryPlainText:a,onTokenClick:s,showFurigana:n,colorMode:r="none",knownStatusMap:i,deriveUnseenByPos:l=!1,showGrammarProgress:c=!1,grammarKnowledgeMap:d,fontSize:m="lg",blur:u=!1,revealed:h=!1,onReveal:p,bottomOffsetPx:g=104}){const f=o.useRef(!1),b=t&&t.length>0,y=!!a;if(!b&&!y)return null;const x=u&&!h,v=j=>{x&&(f.current=!0,j.preventDefault(),j.stopPropagation(),p?.())},w=j=>{if(!x&&!f.current)return;const T=f.current;f.current=!1,j.preventDefault(),j.stopPropagation(),T||p?.()};return e.jsx("div",{className:"video-subtitle-overlay fixed left-1/2 -translate-x-1/2 max-w-[85%] pointer-events-auto z-50",style:{bottom:`max(1rem, ${Math.round(g)}px)`},children:e.jsx("div",{className:"theater-panel video-subtitle-card px-5 py-3",onMouseEnter:()=>{x&&p?.()},onPointerDownCapture:v,onClickCapture:w,onKeyDown:j=>{!x||j.key!=="Enter"&&j.key!==" "||(j.preventDefault(),j.stopPropagation(),p?.())},role:x?"button":void 0,tabIndex:x?0:void 0,"aria-label":x?"Reveal blurred subtitles":void 0,children:e.jsxs("div",{role:"region","aria-live":"polite","aria-atomic":"true","aria-label":"Video subtitles",style:{filter:x?"blur(8px)":"none",transition:"filter 0.15s ease",cursor:x?"pointer":void 0},children:[b&&e.jsx("div",{className:`${Iu[m]} text-center leading-relaxed`,style:{color:"var(--theater-text)"},children:e.jsx(si,{tokens:t,onTokenClick:s,groupVerbConjugations:!0,showFurigana:n,colorMode:r,knownStatusMap:i,deriveUnseenByPos:l,showGrammarProgress:c,grammarKnowledgeMap:d,showGhostSubjects:!1})}),!b&&y&&e.jsx("div",{className:`${Iu[m]} text-center leading-relaxed`,style:{color:"var(--theater-text)"},children:a})]})})})}const Kr=100;function t0({label:t,offsetMs:a,onChange:s}){return e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("span",{className:"w-5 text-right",style:{color:"var(--theater-text-muted)"},children:t}),e.jsx("button",{onClick:()=>
207s(a-Kr),className:"ss-offset-btn",title:`Subtitle earlier (-${Kr}ms)`,children:e.jsx(lg,{size:14})}),e.jsxs("span",{className:"min-w-[4.5rem] text-center font-mono tabular-nums",children:[a>=0?"+":"",a,"ms"]}),e.jsx("button",{onClick:()=>s(a+Kr),className:"ss-offset-btn",title:`Subtitle later (+${Kr}ms)`,children:e.jsx(hm,{size:14})}),a!==0&&e.jsx("button",{onClick:()=>s(0),className:"ss-offset-btn",title:"Reset offset",children:e.jsx(pi,{size:12})})]})}function a0({primaryOffsetMs:t,onPrimaryOffsetChange:a}){return e.jsxs("div",{className:"flex flex-col gap-1 text-xs select-none",style:{color:"var(--theater-text-soft)"},children:[e.jsx("style",{children:` 208 .ss-offset-btn { 209 display: inline-flex; 210 align-items: center; 211 justify-content: center; 212 padding: 2px; 213 border-radius: var(--wc-radius-ink); 214 color: var(--theater-text-soft); 215 background: transparent; 216 transition: color 160ms cubic-bezier(0.22, 1, 0.36, 1), 217 background 160ms cubic-bezier(0.22, 1, 0.36, 1); 218 } 219 .ss-offset-btn:hover { 220 color: var(--theater-text); 221 background: hsl(var(--module-accent) / 0.14); 222 } 223 `}),e.jsx(t0,{label:"Sync",offsetMs:t,onChange:a})]})}const xp=20,s0=64;function n0(t,a){return t-a}function $o(t,a){return t.startMs+a}function wp(t,a){return t.endMs+a}function r0(t,a){let s=0,n=t.length-1,r=-1;for(;s<=n;){const l=s+n>>>1;t[l].startMs<=a?(r=l,s=l+1):n=l-1}if(r<0)return-1;const i=Math.max(0,r-s0);for(let l=r;l>=i;l--)if(a<=t[l].endMs)return l;return-1}function Ru(t,a,s){return r0(t,n0(a,s))}function fl(t,a){return Math.max(0,$o(t,a)/1e3)}function i0(t,a,s){return t>=wp(a,s)}function o0(t,a,s){for(let n=0;n<t.length;n++)if($o(t[n],s)>a+xp)return n;return-1}function l0(t,a,s){for(let n=t.length-1;n>=0;n--)if($o(t[n],s)<a-xp)return n;return-1}function c0(t){const{liveIdx:a,watchedIdx:s,latchedIdx:n,atEndReachedForWatched:r,justSeeked:i,loopEnabled:l,autoPauseEnabled:c,autoPauseAt:d}=t;if(i)return{action:"none",nextWatchedIdx:a,nextLatchedIdx:-1};if(s>=0&&r){if(l)return c&&d==="end"?n!==s?{action:"pauseEnd",nextWatchedIdx:s,nextLatchedIdx:s}:{action:"loop",nextWatchedIdx:s,nextLatchedIdx:-1}:c&&d==="start"?{action:"loopPauseStart",nextWatchedIdx:s,nextLatchedIdx:s}:{action:"loop",nextWatchedIdx:s,nextLatchedIdx:n};if(c&&d==="end"&&n!==s)return{action:"pauseEnd",nextWatchedIdx:s,nextLatchedIdx:s}}return a>=0&&a!==s?c&&d==="start"&&n!==a?{action:"pauseStart",nextWatchedIdx:a,nextLatchedIdx:a}:{action:"none",nextWatchedIdx:a,nextLatchedIdx:n}:{action:"none",nextWatchedIdx:s,nextLatchedIdx:n}}const $u={offsetMs:0,leadInMs:120,leadOutMs:200,mergeGapMs:400};function zu(t,a,s){const{offsetMs:n,leadInMs:r,leadOutMs:i,mergeGapMs:l}=a,c=typeof s=="number"&&Number.isFinite(s)&&s>0?s:1/0,d=[];for(const u of t){if(!Number.isFinite(u.startMs)||!Number.isFinite(u.endMs)||u.endMs<=u.startMs)continue;const h=Math.max(0,$o(u,n)-r),p=Math.min(c,wp(u,n)+i);p<=h||d.push({startMs:h,endMs:p})}if(d.length===0)return[];d.sort((u,h)=>u.startMs-h.startMs||u.endMs-h.endMs);const m=[{...d[0]}];for(let u=1;u<d.length;u++){const h=m[m.length-1],p=d[u];p.startMs-h.endMs<=l?p.endMs>h.endMs&&(h.endMs=p.endMs):m.push({...p})}return m}function vp(t){let a=0;for(const s of t)a+=s.endMs-s.startMs;return a}const d0="/ffmpeg/ffmpeg-core.js",u0="/ffmpeg/ffmpeg-core.wasm",jp=Math.floor(1.25*1024*1024*1024);function kp(t){return Number.isFinite(t)&&t>0&&t<=jp}function m0(t){const a=(t.startMs/1e3).toFixed(3),s=(t.endMs/1e3).toFixed(3);return`between(t,${a},${s})`}function h0(t){return`aselect='${t.filter(s=>Number.isFinite(s.startMs)&&Number.isFinite(s.endMs)&&s.endMs>s.startMs).map(m0).join("+")}',asetpts=N/SR/TB`}function p0(t){for(let a=t.length-1;a>=0;a--){const s=t[a].trim();if(/error|invalid|not found|failed|no such|unsupported|could not/i.test(s))return s}return""}function lr(){return new DOMException("Condensed audio export was cancelled.","AbortError")}async function f0(t,a,s={}){const{onProgress:n,signal:r,bitrateKbps:i=128,mono:l=!0}=s;if(!kp(t.size))throw new Error("This video is too large to process in the browser. Try a shorter clip or a lower-resolution file.");const c=a.filter(j=>j.endMs>j.startMs);if(c.length===0)throw new Error("There is no dialogue to export for this selection.");
223if(r?.aborted)throw lr();const[{FFmpeg:d},{fetchFile:m,toBlobURL:u}]=await Promise.all([Rs(()=>import("./index-DfgTfcu_.js"),[]),Rs(()=>import("./index-607UPNXL.js"),[])]),h=new d;let p=!1;const g=()=>{if(!p){p=!0;try{h.terminate()}catch{}}},f=()=>g(),b=[],y=({message:j})=>{b.push(j),b.length>60&&b.shift()},x=({progress:j})=>{n&&Number.isFinite(j)&&n(Math.min(1,Math.max(0,j)))},v="input.bin";let w=null;try{if(h.on("log",y),h.on("progress",x),r?.aborted)throw lr();try{if(w=await u(d0,"text/javascript"),r?.aborted)throw lr();await h.load({coreURL:w,wasmURL:u0},{signal:r})}catch(H){if(r?.aborted)throw lr();const ee=H instanceof Error?H.message:String(H);throw new Error(`Couldn't load the Condensed Audio engine. Reload the page and try again.${ee?` (${ee})`:""}`)}if(r?.addEventListener("abort",f,{once:!0}),r?.aborted)throw lr();const j=[],T=({message:H})=>{j.push(H)};h.on("log",T),await h.exec(["-hide_banner","-encoders"],-1,{signal:r}),h.off("log",T);const P=j.some(H=>H.includes("libmp3lame")),N=P?"libmp3lame":"aac",_=P?"mp3":"m4a",L=P?"audio/mpeg":"audio/mp4",q=`output.${_}`;if(await h.writeFile(v,await m(t),{signal:r}),r?.aborted)throw lr();const O=["-i",v,"-vn","-af",h0(c)];if(l&&O.push("-ac","1"),O.push("-c:a",N,"-b:a",`${i}k`,q),b.length=0,await h.exec(O,-1,{signal:r})!==0){const H=p0(b),ee=H?` (ffmpeg: ${H})`:"";throw/invalid data|decod|codec|no such|unsupported|could not find/i.test(H)?new Error(`This video's audio couldn't be decoded â its codec may be unsupported.${ee}`):new Error(`Condensing the audio failed.${ee}`)}const k=await h.readFile(q,void 0,{signal:r}),J=typeof k=="string"?new TextEncoder().encode(k):k,M=new Blob([J],{type:L});try{await h.deleteFile(v),await h.deleteFile(q)}catch{}return{blob:M,mimeType:L,ext:_,durationMs:vp(c)}}finally{r?.removeEventListener("abort",f),h.off("log",y),h.off("progress",x),g(),w&&URL.revokeObjectURL(w)}}function g0(t,a){const s=URL.createObjectURL(t),n=document.createElement("a");n.href=s,n.download=a,n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.click(),n.remove(),window.setTimeout(()=>URL.revokeObjectURL(s),1e3)}function Fu(t){const a=Math.max(0,Math.round(t/1e3)),s=Math.floor(a/60),n=a%60;return`${s}:${String(n).padStart(2,"0")}`}function y0(t){return(t||"").split("").map(s=>s.charCodeAt(0)<32?" ":s).join("").replace(/[<>:"/\\|?*]/g," ").replace(/\s+/g," ").replace(/^[.\s]+|[.\s]+$/g,"").trim()||"condensed-audio"}function b0({cues:t,offsetMs:a,totalDurationMs:s,getVideoBlob:n,canGenerate:r,disabledReason:i,onChooseLocalFile:l,filenameBase:c}){const d=wn(),[m,u]=o.useState("idle"),[h,p]=o.useState(0),[g,f]=o.useState(null),[b,y]=o.useState(null),x=o.useRef(null),v=o.useMemo(()=>zu(t,{...$u,offsetMs:a},s),[t,a,s]),w=o.useMemo(()=>vp(v),[v]);o.useEffect(()=>()=>x.current?.abort(),[]);const j=o.useCallback(async()=>{const _=zu(t,{...$u,offsetMs:a},s),L=new AbortController;x.current=L,u("generating"),p(0),y(null),f(null);try{const q=await n(L.signal);if(L.signal.aborted)return;if(!q)throw new Error("Couldn't load the video file. Reload it and try again.");if(!kp(q.size))throw new Error("This video is too large to process in the browser. Try a shorter clip or a lower-resolution file.");const O=await f0(q,_,{mono:!0,signal:L.signal,onProgress:A=>p(A)});if(L.signal.aborted)return;f(O),u("done"),ne("condensed_audio_generated",{episode_cue_count:t.length,segment_count:_.length,output_ms:O.durationMs,output_bytes:O.blob.size,ext:O.ext})}catch(q){if(q instanceof DOMException&&q.name==="AbortError"){u("idle");return}const O=q instanceof Error?q.message:String(q);y(O),u("error"),ne("condensed_audio_failed",{reason:String(O??"unknown")})}finally{x.current===L&&(x.current=null)}},[t,a,s,n]),T=o.useCallback(()=>{x.current?.abort()},[]),P=o.useCallback(()=>{g&&g0(g.blob,`${y0(c)} (condensed).${g.ext}`)},[g,c]),N=e.jsx("label",{className:"text-[11px] uppercase tracking-wide block mb-1.5",style:{color:"var(--theater-text-muted)"},children:"Condensed Audio"});return r?e.jsxs("div",{children:[N,e.jsxs("div",{"aria-live":"polite",children:[m==="idle"&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-xs mb-2",style:{color:"var(--theater-text-soft)"},children:"Dialogue-only audio for passive re-listening â silence and music removed."}),e.jsxs("div",{className:"flex items-center justify-between mb-2 text-xs",style:{color:"var(--theater-text-muted)"},children:[e.jsx("span",{children:"Estimated output"}),e.jsxs("span",{className:"font-mono tabular-nums",style:{color:"var(--theater-text-soft)"},children:[Fu(w)," · ",v.length," ",v.length===1?"segment":"segments"]})]}),e.jsx("button",{type:"button",className:"theater-btn theater-btn--primary w-full",onClick:j,disabled:v.length===0,children:"Generate"})]}),m==="generating"&&e.jsxs("div",{className:"flex flex-col items-center gap-1 py-1",children:[d?e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},role:"status",children:"Condensing audioâ¦"}):e.jsxs(e.Fragment,{children:[e.jsx("div",{"aria-hidden":"true",children:e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999})}),e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},role:"status",children:"Condensing audioâ¦"})]}),e.jsxs("span",{className:"text-xs font-mono tabular-nums",style:{color:"var(--theater-text-muted)"},children:[Math.round(h*100),"%"]}),e.jsx("button",{type:"button",className:"theater-btn theater-btn--secondary mt-1",onClick:T,children:"Cancel"})]}),m==="done"&&g&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2 text-xs",style:{color:"var(--theater-text-muted)"},children:[e.jsx("span",{children:"Ready"}),e.jsxs("span",{className:"font-mono tabular-nums",style:{color:"var(--theater-text-soft)"},children:[Fu(g.durationMs)," ·"," ",(g.blob.size/(1024*1024)).toFixed(1)," MB"]})]}),e.jsx("button",{type:"button",className:"theater-btn theater-btn--primary w-full",onClick:P,children:"Download"}),e.jsx("button",{type:"button",onClick:j,className:"text-xs mt-2 block mx-auto",style:{color:"var(--theater-text-muted)"},children:"Generate again"})]}),m==="error"&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"text-sm mb-2",style:{color:"var(--theater-destructive)"},role:"alert",children:b}),e.jsx("button",{type:"button",className:"theater-btn theater-btn--secondary",onClick:j,children:"Try again"})]})]})]}):e.jsxs("div",{children:[N,e.jsx("p",{className:"text-xs",style:{color:"var(--theater-text-muted)"},children:i||"Load the video file to generate condensed audio."}),l&&e.jsx("button",{type:"button",className:"theater-btn theater-btn--secondary w-full mt-2",onClick:l,children:"Choose local video file"})]})}function $i(t){if(!isFinite(t)||t<0)return"0:00";const a=Math.floor(t/3600),s=Math.floor(t%3600/60),n=Math.floor(t%60),r=a>0?String(s).padStart(2,"0"):String(s),i=String(n).padStart(2,"0");return a>0?`${a}:${r}:${i}`:`${r}:${i}`}function x0({videoRef:t,containerRef:a,isFullscreen:s,onToggleFullscreen:n,settingsContent:r,settingsOpen:i,onSettingsOpenChange:l,stacked:c=!1,verticalToggleVisible:d=!1,verticalEnabled:m=!1,onToggleVertical:u,onShowShortcuts:h,onReservedHeightChange:p,onVisibilityChange:g,onPrevCue:f,onNextCue:b,onReplayCue:y,loopEnabled:x,onToggleLoop:v,autoPauseEnabled:w,onToggleAutoPause:j,cueNavAvailable:T,onVolumePreferenceChange:P}){const[N,_]=o.useState(!1),[L,q]=o.useState(0),[O,A]=o.useState(0),[k,J]=o.useState(!1),[M,H]=o.use
223State(1),ee=o.useRef(!1),[Pe,D]=o.useState(!1),de=c||!Pe,fe=i,Me=l,U=o.useRef(void 0),ve=o.useRef(null),yt=o.useRef(null),ut=o.useRef(null),St=o.useRef(null),je=o.useRef(null),lt=o.useRef(null),Et=o.useId();o.useEffect(()=>{const se=t.current;if(!se)return;const ft=()=>_(!0),Oe=()=>_(!1),pt=()=>{ee.current||q(se.currentTime)},kt=()=>A(se.duration||0),Ve=()=>{H(se.volume),J(se.muted),P?.(se.volume,se.muted)};return se.addEventListener("play",ft),se.addEventListener("pause",Oe),se.addEventListener("timeupdate",pt),se.addEventListener("durationchange",kt),se.addEventListener("volumechange",Ve),A(se.duration||0),q(se.currentTime),_(!se.paused),H(se.volume),J(se.muted),()=>{se.removeEventListener("play",ft),se.removeEventListener("pause",Oe),se.removeEventListener("timeupdate",pt),se.removeEventListener("durationchange",kt),se.removeEventListener("volumechange",Ve)}},[t,P]);const Ct=o.useCallback(()=>{D(!1),clearTimeout(U.current),!c&&(U.current=setTimeout(()=>{fe||D(!0)},3e3))},[fe,c]);o.useEffect(()=>{const se=a.current;if(se)return se.addEventListener("mousemove",Ct),se.addEventListener("mouseenter",Ct),se.addEventListener("touchstart",Ct,{passive:!0}),Ct(),()=>{se.removeEventListener("mousemove",Ct),se.removeEventListener("mouseenter",Ct),se.removeEventListener("touchstart",Ct),clearTimeout(U.current)}},[a,Ct]),o.useEffect(()=>{g?.(de)},[de,g]),o.useEffect(()=>{const se=ve.current;if(!se||!p)return;const ft=()=>{const pt=se.getBoundingClientRect().height;p(Math.ceil(Math.max(52,pt)))};if(ft(),typeof ResizeObserver>"u")return window.addEventListener("resize",ft),()=>window.removeEventListener("resize",ft);const Oe=new ResizeObserver(ft);return Oe.observe(se),()=>Oe.disconnect()},[p]),o.useEffect(()=>{const se=ut.current;se&&(de?se.removeAttribute("inert"):se.setAttribute("inert",""))},[de]),o.useEffect(()=>{D(!1),Ct()},[s,Ct]),o.useEffect(()=>{if(!fe)return;const se=ft=>{const Oe=ft.target;!je.current?.contains(Oe)&&!lt.current?.contains(Oe)&&(Me(!1),setTimeout(()=>je.current?.focus(),0))};return document.addEventListener("mousedown",se),()=>document.removeEventListener("mousedown",se)},[fe]),o.useEffect(()=>{if(!fe)return;const se=lt.current;if(!se)return;const ft='button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])',Oe=()=>Array.from(se.querySelectorAll(ft));(Oe()[0]??se).focus();const pt=kt=>{if(kt.key==="Escape"){kt.preventDefault(),Me(!1),je.current?.focus();return}if(kt.key!=="Tab")return;const Ve=Oe();if(Ve.length===0){kt.preventDefault(),se.focus();return}const Be=Ve[0],Ke=Ve[Ve.length-1];kt.shiftKey&&document.activeElement===Be?(kt.preventDefault(),Ke.focus()):!kt.shiftKey&&document.activeElement===Ke&&(kt.preventDefault(),Be.focus())};return document.addEventListener("keydown",pt),()=>document.removeEventListener("keydown",pt)},[fe]);const aa=o.useCallback(()=>{const se=t.current;se&&(se.paused?se.play():se.pause())},[t]),vt=o.useCallback(se=>{const ft=t.current,Oe=yt.current;if(!ft||!Oe)return;ee.current=!0;try{Oe.setPointerCapture(se.pointerId)}catch{}const pt=Oe.getBoundingClientRect(),kt=(se.clientX-pt.left)/pt.width*O;ft.currentTime=Math.max(0,Math.min(O,kt)),q(ft.currentTime);const Ve=Ke=>{const At=Oe.getBoundingClientRect(),Jt=(Ke.clientX-At.left)/At.width*O;ft.currentTime=Math.max(0,Math.min(O,Jt)),q(ft.currentTime)},Be=()=>{ee.current=!1,document.removeEventListener("pointermove",Ve),document.removeEventListener("pointerup",Be),document.removeEventListener("pointercancel",Be)};document.addEventListener("pointermove",Ve),document.addEventListener("pointerup",Be),document.addEventListener("pointercancel",Be)},[t,O]),Le=o.useCallback(se=>{const ft=t.current;if(!ft||O<=0)return;let Oe=null;switch(se.key){case"ArrowLeft":Oe=ft.currentTime-(se.shiftKey?10:5);break;case"ArrowRight":Oe=ft.currentTime+(se.shiftKey?10:5);break;case"Home":Oe=0;break;case"End":Oe=O;break;default:return}se.preventDefault();const pt=Math.max(0,Math.min(O,Oe));ft.currentTime=pt,q(pt)},[t,O]),jt=o.useCallback(()=>{const se=t.current;se&&(se.muted=!se.muted)},[t]),Ft=o.useCallback(se=>
223{const ft=t.current;if(!ft)return;const Oe=Number(se.currentTarget.value);ft.volume=Oe,Oe>0&&ft.muted&&(ft.muted=!1)},[t]),ct=O>0?L/O*100:0;return e.jsx("div",{ref:ve,className:c?"relative z-[60] shrink-0":`mobile-viewport-safe-bottom absolute bottom-0 inset-x-0 z-[60] transition-opacity duration-300 pointer-events-none ${de?"opacity-100":"opacity-0"}`,"aria-hidden":c?void 0:!de,children:e.jsx("div",{className:c?"pt-2 pb-2 px-3 flex flex-col items-stretch gap-2":"pt-12 pb-3 px-3 pointer-events-none flex flex-col items-stretch gap-2",style:c?void 0:{background:"linear-gradient(to top, var(--theater-scrim), transparent)"},children:e.jsxs("div",{ref:ut,className:`${de?"pointer-events-auto":"pointer-events-none"} flex flex-col items-stretch gap-2`,onClick:se=>se.stopPropagation(),onDoubleClick:se=>se.stopPropagation(),children:[fe&&e.jsxs("div",{id:Et,className:c?"theater-panel w-full overflow-y-auto px-4 pb-4 pt-0 space-y-4 outline-none":"theater-panel self-center w-[min(92vw,360px)] max-h-[calc(100dvh-8rem)] overflow-y-auto px-4 pb-4 pt-0 space-y-4 outline-none",style:c?{position:"fixed",left:0,right:0,bottom:0,zIndex:70,maxHeight:"70dvh"}:void 0,ref:lt,role:"dialog","aria-modal":"true","aria-label":"Video settings",tabIndex:-1,children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 -mx-4 px-4 pt-4 pb-2",style:{position:"sticky",top:0,zIndex:2,background:"var(--theater-surface)",borderBottom:"1px solid var(--theater-surface-border)"},children:[e.jsx("span",{className:"text-[11px] uppercase tracking-[0.2em]",style:{color:"var(--theater-text-muted)",fontFamily:"'JetBrains Mono', monospace"},children:"Settings"}),e.jsx("button",{type:"button",onClick:()=>{Me(!1),je.current?.focus()},className:"theater-chrome-icon-btn theater-chrome-icon-btn--sm","aria-label":"Close settings",title:"Close settings",children:e.jsx(rs,{size:16})})]}),r]}),e.jsxs("div",{ref:yt,className:"group relative h-1 hover:h-1.5 rounded-[var(--wc-radius-ink)] cursor-pointer transition-all touch-none focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[hsl(var(--module-accent))]",style:{background:"var(--theater-surface-border-strong)"},onPointerDown:vt,onKeyDown:Le,role:"slider",tabIndex:0,"aria-label":"Seek","aria-valuemin":0,"aria-valuemax":O>0?O:0,"aria-valuenow":L,"aria-valuetext":`${$i(L)} of ${$i(O)}`,children:[e.jsx("div",{className:"absolute inset-y-0 left-0 rounded-[var(--wc-radius-ink)]",style:{width:`${ct}%`,background:"hsl(var(--module-accent))"}}),e.jsx("div",{className:"absolute top-1/2 -translate-y-1/2 w-3 h-3 rounded-[var(--wc-radius-ink)] opacity-0 group-hover:opacity-100 transition-opacity",style:{left:`${ct}%`,marginLeft:"-6px",background:"hsl(var(--module-accent))"}})]}),e.jsxs("div",{ref:St,className:"theater-chrome-bar self-center flex-wrap justify-center",children:[e.jsx("button",{onClick:aa,className:"theater-chrome-icon-btn",title:N?"Pause":"Play","aria-label":N?"Pause":"Play",children:N?e.jsx(Cf,{size:20}):e.jsx(Ef,{size:20})}),e.jsxs("span",{className:"theater-chrome-bar-counter tabular-nums",children:[$i(L),e.jsx("span",{style:{opacity:.5},children:" / "}),$i(O)]}),e.jsx("button",{onClick:jt,className:"theater-chrome-icon-btn",title:k?"Unmute":"Mute","aria-label":k?"Unmute":"Mute",children:k||M===0?e.jsx(jg,{size:18}):e.jsx(Tf,{size:18})}),e.jsx("input",{type:"range",min:"0",max:"1",step:"0.05",value:k?0:M,onChange:Ft,className:"w-20 h-1 cursor-pointer accent-[hsl(var(--module-accent))]","aria-label":"Volume","aria-valuetext":`${Math.round((k?0:M)*100)}%`}),(f||b||y)&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"theater-chrome-bar-divider","aria-hidden":"true"}),e.jsx("button",{onClick:f,disabled:!T,className:"theater-chrome-icon-btn",title:"Previous line (A)","aria-label":"Previous line",children:e.jsx(xg,{size:18})}),e.jsx("button",{onClick:y,disabled:!T,className:"theater-chrome-icon-btn",title:"Replay line (R)","aria-label":"Replay line",children:e.jsx(pi,{size:18})}),e.jsx("button",{onClick:b,disabled:!T,className:"theater-chrome-icon-btn",title:"Next line (D)","aria-label":"Next line",children:e.jsx(om,{size:18})}),e.jsx("button",{onClick:v,disabled:!T,className:`theater-chrome-icon-btn ${x?"is-active":""}`,title:"Loop line (L)","aria-label":"Loop line","aria-pressed":x,children:e.jsx(pg,{size:18})}),e.jsx("button",{onClick:j,disabled:!T,className:`theater-chrome-icon-btn ${w?"
223is-active":""}`,title:"Auto-pause per line (P)","aria-label":"Auto-pause per line","aria-pressed":w,children:e.jsx(Df,{size:18})})]}),e.jsx("div",{className:"theater-chrome-bar-divider","aria-hidden":"true"}),d&&u&&e.jsx("button",{onClick:u,className:`theater-chrome-icon-btn ${m?"is-active":""}`,title:"Stacked layout (V)","aria-label":"Stacked layout","aria-pressed":m,children:e.jsx(mg,{size:18})}),h&&e.jsx("button",{onClick:h,className:"theater-chrome-icon-btn",title:"Keyboard shortcuts (?)","aria-label":"Keyboard shortcuts",children:e.jsx(Mf,{size:18})}),e.jsx("button",{ref:je,onClick:()=>Me(!fe),className:`theater-chrome-icon-btn ${fe?"is-active":""}`,title:"Settings","aria-label":"Settings","aria-haspopup":"dialog","aria-controls":Et,"aria-expanded":fe,children:e.jsx(cm,{size:18})}),e.jsx("button",{onClick:n,className:"theater-chrome-icon-btn",title:s?"Exit fullscreen":"Fullscreen","aria-label":s?"Exit fullscreen":"Fullscreen",children:s?e.jsx(ig,{size:18}):e.jsx(ng,{size:18})})]})]})})})}const w0=6e3,v0=.32,j0={sm:"text-sm",base:"text-base",lg:"text-lg",xl:"text-xl"};function Du(t){const a=Math.max(0,Math.round(t/1e3)),s=Math.floor(a/60),n=a%60;return`${s}:${String(n).padStart(2,"0")}`}function k0({entries:t,currentIndex:a,onSeekToIndex:s,onTokenClick:n,annotationsEnabled:r,showFurigana:i,colorMode:l="none",knownStatusMap:c,deriveUnseenByPos:d=!1,showGrammarProgress:m=!1,grammarKnowledgeMap:u,fontSize:h="base",blur:p=!1,revealed:g=!1,onReveal:f}){const b=wn(),y=o.useRef(null),x=o.useRef(new Map),v=o.useRef(void 0),[w,j]=o.useState(!0),T=o.useCallback((L,q)=>{const O=y.current,A=x.current.get(L);if(!O||!A)return;const k=A.offsetTop-O.clientHeight*v0;O.scrollTo({top:Math.max(0,k),behavior:q&&!b?"smooth":"auto"})},[b]);o.useEffect(()=>{!w||a<0||T(a,!0)},[a,w,T]);const P=o.useCallback(()=>{j(!1),clearTimeout(v.current),v.current=setTimeout(()=>j(!0),w0)},[]);o.useEffect(()=>()=>clearTimeout(v.current),[]);const N=o.useCallback(()=>{clearTimeout(v.current),j(!0),a>=0&&T(a,!0)},[a,T]),_=o.useCallback(L=>{clearTimeout(v.current),j(!0),s(L)},[s]);return e.jsxs("div",{className:"relative flex-1 min-h-0",children:[e.jsxs("div",{ref:y,className:"mobile-viewport-safe-bottom h-full overflow-y-auto overscroll-contain px-3 py-4",style:{background:"var(--theater-surface)"},onWheel:P,onTouchMove:P,onPointerDown:P,onKeyDown:L=>{["ArrowUp","ArrowDown","PageUp","PageDown","Home","End"].includes(L.key)&&P()},onClick:L=>L.stopPropagation(),onDoubleClick:L=>L.stopPropagation(),children:[e.jsx("ul",{className:"mx-auto w-full max-w-[46rem] space-y-1",children:t.map((L,q)=>{const O=q===a,A=a>=0&&q<a,k=p&&!A&&!(O&&g),J=L.tokens,M=r&&!!J&&J.length>0;return e.jsx("li",{ref:H=>{H?x.current.set(q,H):x.current.delete(q)},className:"rounded-[var(--wc-radius-leaf)] transition-colors",style:{background:O?"var(--theater-surface-hover)":"transparent",borderLeft:`2px solid ${O?"hsl(var(--module-accent))":"transparent"}`},children:e.jsxs("div",{className:"flex items-start gap-2 px-2.5 py-2",children:[e.jsx("button",{type:"button",onClick:()=>_(q),className:"shrink-0 mt-1 text-[10px] tabular-nums rounded-[var(--wc-radius-ink)] px-1 py-0.5",style:{fontFamily:"'JetBrains Mono', monospace",color:O?"hsl(var(--module-accent))":"var(--theater-text-muted)"},"aria-label":`Play from ${Du(L.startMs)}`,children:Du(L.startMs)}),e.jsx("div",{className:`flex-1 min-w-0 ${j0[h]} leading-relaxed`,style:{color:O?"var(--theater-text-strong)":"var(--theater-text)",filter:k?"blur(7px)":"none",transition:"filter 0.15s ease",cursor:k?"pointer":void 0},onClickCapture:H=>{k&&(H.preventDefault(),H.stopPropagation(),O?f?.():_(q))},onKeyDown:H=>{!k||H.key!=="Enter"&&H.key!==" "||(H.preventDefault(),O?f?.():_(q))},...k?{role:"button",tabIndex:0,"aria-label":O?"Reveal this line":"Play from this line"}:{},children:M?e.jsx(si,{tokens:J,onTokenClick:(H,ee)=>n(H,ee,q),groupVerbConjugations:!0,showFurigana:i,colorMode:l,knownStatusMap:c,deriveUnseenByPos:d,showGrammarProgress:m,grammarKnowledgeMap:u,showGhostSubjects:!1}):L.text})]})},`${L.index}-${L.startMs}`)})}),e.jsx("div",{"aria-hidden":"true",style:{height:"40vh"}})]}),!w&&e.jsxs("button",{type:"button",onClick:L=>{L.stopPropagation(),N()},className:"theater-btn theater-btn--primary absolute bottom-4 left-1/2 -translate-x-1/2 z-10",children:[e.jsx(Rf,{size:14}),"Jump to the current line"]})]})}const _0=[{num:"ä¸",title:"Playback",jp:"åç",items:[{keys:["Space","K"],label:"Play / pause"},{keys:["â","â"],label:"Back / forward 5 seconds"},{keys:["Shift â","Shift â"],label:"Back / forward 10 seconds"},{keys:["0"],label:"Jump to the start"},{keys:["1"],label:"Jump 10% in (2 = 20%, ⦠9 = 90%)"},{keys:["Home","End"],label:"Jump to start / end"},{keys:[",","."],label:"Slower / faster (0.05à steps)"}]},{num:"äº",title:"Per line",jp:"ä¸è¡ãã¤",items:[{keys:["A"],label:"Previous line"},{keys:["D"],label:"Next line"},{keys:["R"],label:"Replay this line"},{keys:["L"],label:"Loop this line"},{keys:["P"],label:"Auto-pause on every line"},{keys:["B"],label:"Blur subtitles until you look"},{keys:["â","â"],label:"Nudge subtitle timing later / earlier"}]},{num:"ä¸",title:"Sound & view",jp:"é³ã¨è¡¨ç¤º",items:[{keys:["M"],label:"Mute / unmute"},{keys:["Shift â","Shift â"],label:"Volume up / down"},{keys:["F"],label:"Fullscreen"},{keys:["V"],label:"Stacked (vertical) layout"},{keys:["T"],label:"Text analysis on / off"},{keys:["G"],label:"Furigana on / off"},{keys:["S"],label:"Settings"},{keys:["?"],label:"This list"}]}],Lu=.05,Ou=.05,zi=5;function S0(t,a){const s=t;if(s&&(s.tagName==="INPUT"||s.tagName==="TEXTAREA"||s.isContentEditable))return!0;const n=t??a;return n?n.tagName==="BUTTON"||n.getAttribute("role")==="slider"||!!n.closest('button,[role="slider"],a[href],select'):!1}
223function N0(t){const{key:a,shiftKey:s=!1,shortcutsOpen:n=!1}=t;if(t.ctrlKey||t.altKey||t.metaKey)return null;if(n)return a==="?"||a==="Escape"?{type:"closeShortcuts"}:null;if(a.length===1&&a>="0"&&a<="9")return{type:"seekToFraction",fraction:Number(a)/10};switch(a){case" ":case"k":case"K":return{type:"playPause"};case"ArrowLeft":return{type:"seekBy",seconds:s?-zi*2:-zi};case"ArrowRight":return{type:"seekBy",seconds:s?zi*2:zi};case"ArrowUp":return s?{type:"volumeBy",delta:Lu}:{type:"nudgeSubtitleOffset",direction:1};case"ArrowDown":return s?{type:"volumeBy",delta:-Lu}:{type:"nudgeSubtitleOffset",direction:-1};case"Home":return{type:"seekToFraction",fraction:0};case"End":return{type:"seekToEnd"};case",":case"<":return{type:"speedBy",delta:-Ou};case".":case">":return{type:"speedBy",delta:Ou};case"m":case"M":return{type:"toggleMute"};case"f":case"F":return{type:"toggleFullscreen"};case"v":case"V":return{type:"toggleVertical"};case"t":case"T":return{type:"toggleAnnotations"};case"g":case"G":return{type:"toggleFurigana"};case"s":case"S":return{type:"toggleSettings"};case"?":return{type:"openShortcuts"};case"a":case"A":return{type:"prevCue"};case"d":case"D":return{type:"nextCue"};case"r":case"R":return{type:"replayCue"};case"l":case"L":return{type:"toggleLoop"};case"p":case"P":return{type:"toggleAutoPause"};case"b":case"B":return{type:"toggleBlur"};default:return null}}function C0({onClose:t}){const a=o.useRef(null),s=o.useRef(null);return o.useEffect(()=>{const n=r=>{r.key==="Escape"&&(r.preventDefault(),r.stopPropagation(),t())};return document.addEventListener("keydown",n,!0),s.current?.focus(),()=>document.removeEventListener("keydown",n,!0)},[t]),e.jsx("div",{className:"absolute inset-0 z-[70] flex items-center justify-center p-4",style:{background:"var(--theater-scrim)"},onClick:n=>{n.stopPropagation(),t()},onDoubleClick:n=>n.stopPropagation(),children:e.jsxs("div",{ref:a,className:"theater-panel w-[min(94vw,720px)] max-h-[calc(100vh-4rem)] overflow-y-auto p-5",role:"dialog","aria-modal":"true","aria-label":"Keyboard shortcuts",onClick:n=>n.stopPropagation(),children:[e.jsxs("div",{className:"flex items-start justify-between gap-4 mb-4",children:[e.jsxs("div",{className:"theater-rail-eyebrow",children:[e.jsx("span",{className:"num jp",children:"éµ"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Keyboard"}),e.jsx("span",{className:"jp",children:"æä½ãã¼"})]}),e.jsx("button",{ref:s,type:"button",onClick:t,className:"theater-chrome-icon-btn","aria-label":"Close keyboard shortcuts",children:e.jsx(rs,{size:18})})]}),e.jsx("div",{className:"grid gap-5 sm:grid-cols-2 lg:grid-cols-3",children:_0.map(n=>e.jsxs("section",{children:[e.jsxs("h3",{className:"text-[11px] uppercase tracking-[0.2em] mb-2",style:{color:"var(--theater-text-muted)",fontFamily:"'JetBrains Mono', monospace"},children:[e.jsx("span",{className:"jp mr-2",style:{fontFamily:"var(--font-jp, sans-serif)"},children:n.num}),n.title]}),e.jsx("ul",{className:"space-y-1.5",children:n.items.map(r=>e.jsxs("li",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("span",{className:"text-[13px]",style:{color:"var(--theater-text-soft)"},children:r.label}),e.jsx("span",{className:"shrink-0 flex items-center gap-1",children:r.keys.map(i=>e.jsx("kbd",{className:"px-1.5 py-0.5 text-[10px] rounded-[var(--wc-radius-ink)] whitespace-nowrap",style:{fontFamily:"'JetBrains Mono', monospace",background:"var(--theater-surface-hover)",color:"var(--theater-text)",border:"1px solid var(--theater-surface-border)"},children:i},i))})]},r.label))})]},n.title))}),e.jsx("p",{className:"mt-4 text-[11px]",style:{color:"var(--theater-text-muted)"},children:"Shortcuts pause while you're typing in a field or a player control has focus."})]})})}const _p="(max-width: 900px) and (orientation: portrait)";function E0(){return typeof window>"u"||typeof window.matchMedia!="function"?!1:window.matchMedia(_p).matches}function T0(){const[t,a]=o.useState(E0),[s,n]=o.useState(null);o.useEffect(()=>{if(typeof window>"u"||typeof window.matchMedia!="function")return;const l=window.matchMedia(_p),c=d=>{a(d.matches),n(null)};return typeof l.addEventListener=="function"?l.addEventListener("change",c):l.addListener(c),a(l.matches),(
223)=>{typeof l.removeEventListener=="function"?l.removeEventListener("change",c):l.removeListener(c)}},[]);const r=s??t,i=o.useCallback(()=>n(!r),[r]);return{enabled:r,isPortraitMobile:t,toggle:i}}function M0(t){const a=t.rawStartMs+t.subtitleOffsetMs,s=t.rawEndMs+t.subtitleOffsetMs;return{episodeId:t.episodeId,cueIndex:t.cueIndex,startMs:t.rawStartMs,endMs:t.rawEndMs,subtitleOffsetMs:t.subtitleOffsetMs,clickedMediaTimeMs:Math.max(a,Math.min(s,Math.round(t.clickedMediaTimeMs))),sentenceText:t.sentenceText,highlightStart:t.highlightStart,highlightEnd:t.highlightEnd}}function P0(t){const{session:a}=ps(),[s,n]=o.useState(null),r=o.useCallback(async()=>a?.access_token??null,[a?.access_token]),{selectedToken:i,tokenPanelPosition:l,tokenPanelLoading:c,handleNLPTokenClick:d,closeTokenPanel:m}=Ec({materialId:`video:${t}`,getAccessToken:r,currentPageNumber:void 0,lookupNLPToken:Qp}),u=o.useCallback((p,g,f)=>{g.stopPropagation(),n(f??null),d(p,f?`cue:${f.cueIndex}`:void 0,void 0,g)},[d]),h=o.useCallback(()=>{n(null),m()},[m]);return{selectedToken:i,tokenPanelPosition:l,tokenPanelLoading:c,selectedOccurrence:s,handleTokenClick:u,closeTokenPanel:h}}const A0=5;function I0(t,a,s=A0){if(a===null||!Number.isInteger(a)||a<0||a>=t.length)return null;const n=t[a];if(!n?.text)return null;const r=Math.max(0,a-s),i=Math.min(t.length,a+s+1),l=t.slice(r,i).filter((c,d)=>r+d!==a).map(c=>c.text).filter(c=>!!c);return{text:n.text,surroundingTexts:l,tokens:n.tokens??null}}const R0="jpapp-video-subs",$0=2,Fn="processed_entries",bo="secondary_entries",un="video_meta";function ji(){return new Promise((t,a)=>{const s=indexedDB.open(R0,$0);s.onupgradeneeded=()=>{const n=s.result;n.objectStoreNames.contains(Fn)||n.createObjectStore(Fn,{keyPath:["episodeId","index"]}).createIndex("by_episode","episodeId",{unique:!1}),n.objectStoreNames.contains(bo)||n.createObjectStore(bo,{keyPath:["episodeId","index"]}).createIndex("by_episode","episodeId",{unique:!1}),n.objectStoreNames.contains(un)||n.createObjectStore(un,{keyPath:"episodeId"})},s.onsuccess=()=>t(s.result),s.onerror=()=>a(s.error)})}function Zc(t,a,s,n){return new Promise((r,i)=>{const l=t.transaction(a,s),c=n(l);c.onsuccess=()=>r(c.result),c.onerror=()=>i(c.error),l.onerror=()=>i(l.error)})}async function z0(t,a,s,n=null){const r=await ji();try{await new Promise((i,l)=>{const c=r.transaction([Fn,un],"readwrite"),d=c.objectStore(Fn),m=d.index("by_episode");c.oncomplete=()=>i(),c.onerror=()=>l(c.error),c.onabort=()=>l(c.error);const u=m.openCursor(IDBKeyRange.only(t));u.onsuccess=()=>{const h=u.result;if(h){h.delete(),h.continue();return}try{for(const p of a)d.put({...p,episodeId:t});c.objectStore(un).put({episodeId:t,entryCount:a.length,secondaryEntryCount:0,processedAt:new Date().toISOString(),totalDurationMs:s,serverUpdatedAt:n})}catch(p){c.abort(),l(p)}}})}finally{r.close()}}async function F0(t){const a=await ji();try{return await new Promise((s,n)=>{const c=a.transaction(Fn,"readonly").objectStore(Fn).index("by_episode").getAll(t);c.onsuccess=()=>{const d=c.result;d.sort((m,u)=>m.index-u.index),s(d)},c.onerror=()=>n(c.error)})}finally{a.close()}}async function D0(t){const a=await ji();try{const s=await Zc(a,un,"readonly",n=>n.objectStore(un).get(t));return!!s&&s.entryCount>0}finally{a.close()}}async function L0(t){const a=await ji();try{return await Zc(a,un,"readonly",n=>n.objectStore(un).get(t))??null}finally{a.close()}}async function O0(t){const a=await ji();try{await new Promise((s,n)=>{const r=a.transaction(Fn,"readwrite"),c=r.objectStore(Fn).index("by_episode").openCursor(t);c.onsuccess=()=>{const d=c.result;d?(d.delete(),d.continue()):s()},c.onerror=()=>n(c.error),r.onerror=()=>n(r.error)}),await new Promise((s,n)=>{const r=a.transaction(bo,"readwrite"),c=r.objectStore(bo).index("by_episode").openCursor(t);c.onsuccess=()=>{const d=c.result;d?(d.delete(),d.continue()):s()},c.onerror=()=>n(c.error),r.onerror=()=>n(r.error)}),await Zc(a,un,"readwrite",s=>s.objectStore(un).delete(t))}finally{a.close()}}const B0=2700*1e3;class ed{fetcher;now;currentUrl=null;issuedAt=0;refetchSpent=!1;refetchInFlight=!1;constructor(a,s=()=>Date.now()){this.fetcher=a,this.now=s}static forEpisode(a,s,n=fetch){return new ed(()=>Gh(a,s,n))}get isStreaming(){return this.currentUrl!==null}async resolve(){const a=await this.fetcher();return a.ok&&(this.currentUrl=a.url,this.issuedAt=this.now(),this.refetchSpent=!1),a}notePlaybackProgress(){this.refetchSpent=!1}async handlePlaybackError(a){if(!this.currentUrl)return{recovered:!1};if(this.refetchInFlight)return{recovered:!1};if(this.refetchSpent)return{recovered:!1};if(this.now()-this.issuedAt<B0)return{recovered:!1};this.refetchInFlight=!0,this.refetchSpent=!0;let n;try{n=await this.fetcher()}catch{return this.refetchInFlight=!1,{recovered:!1}}return this.refetchInFlight=!1,n.ok&&n.url?(this.currentUrl=n.url,this.issuedAt=this.now(),{recovered:!0,url:n.url,resumeAtSeconds:Math.max(0,a)}):{recovered:!1}}}async function q0(t,a,s={}){const n=s.fetchFn??fetch,r=await Gh(t,a,n);if(!r.ok)throw new Error("Couldn't load the cloud-synced video. Try again in a moment.");const i=await n(r.url,{signal:s.signal});if(!i.ok)throw new Error("Couldn't download the cloud-synced video. Try again in a moment.");const l=Number(i.headers.get("content-length"));if(Number.isFinite(l)&&l>jp)throw await i.body?.cancel(),new Error("This video is too large to process in the browser. Try a shorter clip or a lower-resolution file.");return i.blob()}const Bu=1e4,U0={now:()=>Date.now(),setTimeout:(t,a)=>globalThis.setTimeout(t,a),clearTimeout:t=>globalThis.clearTimeout(t)};function Fi(t){return{positionMs:t.positionMs,subtitleOffsetMs:t.subtitleOffsetMs,watchCompleted:t.watchCompleted}}function qu(t,a){return t===a||!!t&&!!a&&t.positionMs===a.positionMs&&t.subtitleOffsetMs===a.subtitleOffsetMs&&t.watchCompleted===a.watchCompleted}function V0({send:t,minimumIntervalMs:a=Bu,clock:s=U0,onSendError:n}){const r=Number.isFinite(a)?Math.max(0,a):Bu;let i=null,l=null,c=!1,d=null,m=null,u=null,h=null,p=null,g=!1,f=0,b=!1,y=!1;const x=()=>i!==null&&!qu(i,l),v=()=>{m!==null&&(s.clearTimeout(m),m=null)},w=()=>
223{if(!x())return"noop";if(u)return b=!0,"queued";if(m!==null)return"scheduled";const L=d===null?r:Math.max(0,s.now()-d),q=Math.max(0,r-L);return q>0?(m=s.setTimeout(()=>{m=null,T(!1)},q),"scheduled"):(T(!1),"sent")},j=L=>{if(L===f){if(u=null,h=null,p=null,g=!1,y){y=!1,b=!1,x()&&T(!0);return}b&&(b=!1,w())}};function T(L){if(!x())return;if(u){L?y=!0:b=!0;return}const q=Fi(i),O=++f,A=new AbortController;h=A,p=q,g=L;const k=L?{keepalive:!0,reason:"lifecycle"}:{keepalive:!1,reason:"normal"};L||(d=s.now());let J;try{J=Promise.resolve(t(q,k,A.signal))}catch(M){J=Promise.reject(M)}u=J.then(()=>{O===f&&(l=q)}).catch(M=>{if(!(O!==f||A.signal.aborted))try{n?.(M,k)}catch{}}).then(()=>j(O),()=>j(O))}return{update:L=>{c=c||L.watchCompleted,i={...Fi(L),watchCompleted:c},u&&x()&&(b=!0)},flush:w,flushLifecycle:()=>{if(!x())return"noop";if(v(),u){if(g&&qu(i,p))return"queued";h?.abort(),u=null,h=null,p=null,g=!1,b=!1,y=!1}return T(!0),"sent"},cancelScheduledFlush:v,waitForIdle:async()=>{for(;u;)await u},getLatestSnapshot:()=>i?Fi(i):null,getLastSuccessfulSnapshot:()=>l?Fi(l):null}}const K0=90,H0=5e3,W0=800;function G0({episodeId:t,videoRef:a,videoSrc:s,subtitleOffsetMs:n,initialOffsetMs:r,accessTokenRef:i,enabled:l}){const c=o.useRef(n),d=o.useRef(void 0),m=o.useRef(r);c.current=n;const u=o.useMemo(()=>V0({send:async(p,g,f)=>{const b=i.current;if(!b)throw new Error("Authentication unavailable while saving video progress");const y=await fetch(`${ue()}/api/video/episodes/${t}/progress`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${b}`},body:JSON.stringify({lastPositionMs:p.positionMs,subtitleOffsetMs:p.subtitleOffsetMs,...p.watchCompleted?{watchCompleted:!0}:{}}),keepalive:g.keepalive,signal:f});if(!y.ok)throw new Error(`Progress save failed (${y.status})`)}}),[i,t]),h=o.useCallback(()=>{const p=a.current;return!p||!s||(!Number.isFinite(p.duration)||p.duration<=0)&&p.currentTime<=0?!1:(u.update({positionMs:Math.round(p.currentTime*1e3),subtitleOffsetMs:c.current,watchCompleted:p.duration>0&&p.currentTime/p.duration*100>=K0}),!0)},[u,a,s]);o.useEffect(()=>{if(!l||!s)return;const p=setInterval(()=>{const g=a.current;!g||g.paused||h()&&u.flush()},H0);return()=>clearInterval(p)},[l,u,h,a,s]),o.useEffect(()=>{if(!l||!s)return;const p=a.current;if(!p)return;const g=()=>{h()&&u.flush()},f=()=>{h()&&u.flushLifecycle()},b=()=>{document.visibilityState==="hidden"&&f()};return p.addEventListener("pause",g),document.addEventListener("visibilitychange",b),window.addEventListener("pagehide",f),()=>{p.removeEventListener("pause",g),document.removeEventListener("visibilitychange",b),window.removeEventListener("pagehide",f),f(),u.cancelScheduledFlush()}},[l,u,h,a,s]),o.useEffect(()=>{if(!l||n===m.current)return;const p=a.current;if(!p||!p.paused){m.current=n;return}return clearTimeout(d.current),d.current=setTimeout(()=>{m.current=n,h()&&u.flush()},W0),()=>clearTimeout(d.current)},[l,u,n,h,a])}function Y0(t){const a=t.vocabStartChar??t.vocab_start_char??t.start_char,s=t.vocabEndChar??t.vocab_end_char??t.end_char;return Number.isInteger(a)&&Number.isInteger(s)&&s>a?{start:a,end:s}:null}function J0(t){const a=Array.isArray(t.pos)?t.pos:t.pos?[t.pos]:["åè©"],s=t.vocabId??t.vocab_id??null,n=t.lexemeVocabId??t.lexeme_vocab_id??null,r=t.vocabSurface??t.vocab_surface??null,i=t.vocabStartChar??t.vocab_start_char??null,l=t.vocabEndChar??t.vocab_end_char??null,c=t.lemmaKey??t.lemma_key??null,d=t.isProperNoun??t.is_proper_noun??!1;return{id:t.id??0,surface:t.surface,lemma:t.lemma??t.surface,pos:a,reading:t.reading??null,head:t.head??0,dep:t.dep??"dep",children:t.children??[],start_char:t.start_char??t.startChar??0,end_char:t.end_char??t.endChar??0,bunsetsu_index:t.bunsetsu_index??t.bunsetsuIndex??null,is_bunsetsu_head:t.is_bunsetsu_head??t.isBunsetsuHead??!1,ent_type:t.ent_type??t.entType??null,grammar_key:t.grammar_key??t.grammarKey??null,grammar_point_id:t.grammar_point_id??t.grammarPointId??null,grammar_points:t.grammar_points??t.grammarPoints??null,character_readings:t.character_readings??t.characterReadings??null,meanings:t.meanings??null,conjugation:t.conjugation??void 0,conjugationMeta:t.conjugationMeta??void 0,vocabId:s,vocab_id:s,lexemeVocabId:n,lexeme_vocab_id:n,vocabSurface:r,vocab_surface:r,vocabStartChar:i,vocab_start_char:i,vocabEndChar:l,vocab_end_char:l,lemmaKey:c,lemma_key:c,isProperNoun:d,is_proper_noun:d}}function X0(t,a){return{api:"requestFullscreen",platform:t,reason:a}}async function Q0(t){const a=t.requestFullscreen;if(typeof a!="function")return"unsupported";try{return await a.call(t),"entered"}catch{return"rejected"}}const Uu=8,Vu=3e3,Ku=3e4,Z0={near:12,standard:40,high:88};function e_({episodeId:t,episodeLabel:a,videoFilename:s,initialPositionMs:n,initialOffsetMs:r,cloudSyncStatus:i,openCondensedAudio:l=!1,onBack:c}){const{session:d}=ps(),{isPro:m}=Xn(),{openUpgradeModal:u}=xn(),{isDark:h,toggleTheme:p,theaterThemeClass:g}=mc(),{setIsInReader:f}=am(),b=wn(),y=o.useRef(null),x=o.useRef(null),v=o.useRef(null),w=o.useRef(void 0),j=o.useRef(!1),T=o.useRef(null),P=o.useRef(null),[N]=o.useState(kl),_=o.useRef(d?.access_token??null);o.useEffect(()=>{_.current=d?.access_token??null},[d?.access_token]);const L=o.useRef({startMs:0,tokensClicked:0,wordsAdded:0,fired:!1,milestones:new Set,watchedMs:0,playSegmentStart:null}),q=o.useRef(void 0),[O,A]=o.useState(!1),[k,J]=o.useState(!1),[M,H]=o.use
223State(!1),[ee,Pe]=o.useState(!1),[D,de]=o.useState(null),fe=o.useRef(null),Me=o.useRef(!1),U=o.useRef(!1),[ve,yt]=o.useState(!1),[ut,St]=o.useState(!1);o.useEffect(()=>(f(!0),()=>f(!1)),[f]);const[je,lt]=o.useState([]),[Et,Ct]=o.useState(-1),[aa,vt]=o.useState(!0),[Le,jt]=o.useState(!1),[Ft,ct]=o.useState(void 0);o.useEffect(()=>{j.current=je.length>0},[je]);const[se,ft]=o.useState(null),[Oe,pt]=o.useState(r),kt=o.useRef(r);o.useEffect(()=>{if(Oe!==kt.current)return clearTimeout(q.current),q.current=setTimeout(()=>{kt.current=Oe,ne("immersion_subtitle_offset_adjusted",{offset_ms:Oe})},1e3),()=>clearTimeout(q.current)},[Oe]);const[Ve,Be]=o.useState(N.annotationsEnabled),[Ke,At]=o.useState(N.showFurigana),[Jt,ta]=o.useState(N.showKnownColoring?"known":"none"),[zt,K]=Cc(),_t=["sm","base","lg","xl"],[qt,sa]=o.useState(N.fontSizeIdx),la=_t[qt],[Dt,ba]=o.useState(72),[da,xa]=o.useState(N.subtitlePlacement),[ma,Na]=o.useState(N.playbackSpeed),[Da,wa]=o.useState(N.volume),[Wt,ua]=o.useState(N.muted),ca=o.useCallback(($,he)=>{wa($),ua(he)},[]),ha=o.useCallback($=>{const he=y.current;if(!he)return;const _e=Math.round(Math.max(0,Math.min(1,he.volume+$))*100)/100;he.volume=_e,_e>0&&he.muted&&(he.muted=!1)},[]),za=o.useCallback($=>{Na(he=>{const _e=Math.round(Math.max(.25,Math.min(3,he+$))*100)/100;return y.current&&(y.current.playbackRate=_e),ne("immersion_playback_speed_changed",{speed:_e,previous_speed:he}),_e})},[]),[ea,Ea]=o.useState(N.autoPause!=="off"),[pa,Ca]=o.useState(N.autoPause==="start"?"start":"end"),[Gt,Ba]=o.useState(!1),[ka,Wa]=o.useState(N.blurSubs),[es,Ta]=o.useState(!1),va=o.useRef(null),ia=o.useRef(-1),oe=o.useRef(-1),me=o.useRef(!1),Ge=o.useRef(!1),gt=.005,I=o.useRef(Gt),xe=o.useRef(ea),Ne=o.useRef(pa);o.useEffect(()=>{I.current=Gt},[Gt]),o.useEffect(()=>{xe.current=ea},[ea]),o.useEffect(()=>{Ne.current=pa},[pa]),o.useEffect(()=>{uc({annotationsEnabled:Ve,showFurigana:Ke,showKnownColoring:Jt==="known",blurSubs:ka,fontSizeIdx:qt,playbackSpeed:ma,volume:Da,muted:Wt,autoPause:ea?pa:"off",subtitlePlacement:da,theaterTheme:h?"dark":"light"})},[Ve,pa,ea,ka,Jt,qt,h,Wt,ma,Ke,da,Da]),o.useEffect(()=>{const $=y.current;$&&($.volume=Da,$.muted=Wt)},[Wt,se,Da]),o.useEffect(()=>{Ta(!1)},[Et]);const tt=o.useCallback($=>{const he=y.current;if(!he)return;const _e=je[$];if(!_e)return;va.current=$,ia.current=$,oe.current=$,Ct($);const Pt=fl(_e,Oe)+gt;Math.abs(he.currentTime-Pt)>.004&&(me.current=!0,he.currentTime=Pt),he.play().catch(()=>{})},[je,Oe]),Mt=o.useCallback(()=>{const $=y.current;if(!$||je.length===0)return;const he=ia.current;let _e;if(he>=0)_e=Math.max(0,he-1);else if(_e=l0(je,$.currentTime*1e3,Oe),_e<0)return;tt(_e)},[je,Oe,tt]),Ma=o.useCallback(()=>{const $=y.current;if(!$||je.length===0)return;const he=ia.current;let _e;if(he>=0){if(_e=he+1,_e>je.length-1)return}else if(_e=o0(je,$.currentTime*1e3,Oe),_e<0)return;tt(_e)},[je,Oe,tt]),It=o.useCallback(()=>{if(!y.current||je.length===0)return;const he=ia.current>=0?ia.current:oe.current;he<0||!je[he]||tt(he)},[je,tt]),Nt=o.useCallback(()=>{Ba($=>!$),ne("immersion_setting_changed",{setting:"loop",value:!Gt,previous:Gt})},[Gt]),Lt=o.useCallback(()=>{const $=ea?pa:"off",he=ea?"off":pa;Ea(_e=>!_e),ne("immersion_setting_changed",{setting:"auto_pause",value:he,previous:$})},[ea,pa]),qa=o.useCallback($=>{const he=ea?pa:"off";$!==he&&($==="off"?Ea(!1):(Ea(!0),Ca($)),ne("immersion_setting_changed",{setting:"auto_pause",value:$,previous:he}))},[ea,pa]),F=o.useCallback(()=>{Wa($=>!$),ne("immersion_setting_changed",{setting:"blur_subtitles",value:!ka,previous:ka})},[ka]),{selectedToken:Q,tokenPanelPosition:W,tokenPanelLoading:E,selectedOccurrence:G,handleTokenClick:re,closeTokenPanel:pe}=P0(t),te=o.useRef(null),Fe=o.useCallback(($,he,_e)=>{L.current.tokensClicked++,ne("immersion_token_clicked",{material_type:"video",source:"video_subtitle",has_grammar_tag:!!($.grammar_points?.length||$.grammar_key),has_srs_entry:!!$.lemma});const Pt=_e??Et,Rt=Pt>=0?je[Pt]:null,Ia=y.current,ts=Y0($);!Rt||!Ia||!ts||(te.current=Pt,Ia.pause(),re($,he,M0({episodeId:t,cueIndex:Rt.index,rawStartMs:Rt.startMs,rawEndMs:Rt.endMs,subtitleOffsetMs:Oe,clickedMediaTimeMs:Pt===Et?Ia.currentTime*1e3:fl(Rt,Oe)*1e3,sentenceText:Rt.text,highlightStart:ts.start,highlightEnd:ts.end})))},[re,Et,je,t,Oe]),ke=o.useCallback(async()=>d?.access_token??null,[d?.access_token]),Qe=o.useMemo(()=>rc(),[]),Y=o.useMemo(()=>ic(),[]),Ze=o.useMemo(()=>Jl(ke,{offlineSrsPaidAccess:m}),[ke,m]),Ut=Sm(Jt==="known",ke),Ot=o.useCallback(async $=>{const he=qh(t);if(he)return he;if(se?.startsWith("blob:"))try{const _e=await fetch(se,{signal:$});return _e.ok?_e.blob():null}catch(_e){throw _e instanceof DOMException&&_e.name==="AbortError"?_e:new Error("Couldn't read the selected video file. Choose it again and retry.")}return i==="synced"?q0(t,ke,{signal:$}):null},[se,i,t,ke]),is=o.useMemo(()=>Yl(ke),[ke]),os=i==="synced"&&!!se?.startsWith("http"),Qs=!tc()||!1,C=os&&!Qs,V=o.useMemo(()=>
223{if(G)return{source:{kind:"video_episode",episodeId:G.episodeId,cueIndex:G.cueIndex,startMs:G.startMs,endMs:G.endMs,subtitleOffsetMs:G.subtitleOffsetMs,clickedMediaTimeMs:G.clickedMediaTimeMs,highlightStart:G.highlightStart,highlightEnd:G.highlightEnd},captureImage:async $=>{if(C)throw new Error("Cloud-video frame capture is not enabled for this native origin");const he=$.frameHint;if(he?.kind==="video"&&he.clickedMediaTimeMs!==G.clickedMediaTimeMs)throw new Error("Capture ticket does not match the clicked frame");const _e=y.current;if(!_e)throw new Error("Video is unavailable");return ib(_e,G.clickedMediaTimeMs)},...C?{imageCaptureUnavailableReason:"Mnemonic image capture is unavailable for cloud video in this native build."}:{},...i!=="synced"?{clipCaptureUnavailableReason:"Cloud sync this episode before requesting a private video clip."}:{}}},[G,C,i]),le=Pc(ke),ye=o.useMemo(()=>{if(Q)return{messages:le.messages,isLoading:le.isLoading,error:le.error,quotaExceeded:le.quotaExceeded,contextText:le.contextText,materialTitle:le.materialTitle,sendFollowUp:le.sendFollowUp,start:async $=>{const he=te.current,_e=I0(je,he);!_e||he===null||(ne("immersion_ai_help_triggered",{material_type:"video",source:"lookup_panel"}),await le.explain({text:_e.text,surroundingTexts:_e.surroundingTexts,tokenMetadata:Mc({text:_e.text,processedData:{tokens:_e.tokens??void 0}}),material:{id:t,title:a},pageNumber:1,focus:$}))}}},[Q,je,t,a,le]),[it,fa]=o.useState(l),[Xt,ga]=o.useState(!1),Tt=T0(),[Pa,oa]=o.useState(!1),[Aa,Fa]=o.useState(null),us=o.useCallback($=>{Fa($),ne("video_fullscreen_request_failed",X0(Fp(),$))},[]),xs=o.useCallback(async()=>{const $=v.current;if(!$)return;if(document.fullscreenElement){try{await document.exitFullscreen()}catch{}return}const he=await Q0($);if(he==="entered"){Fa(null);return}us(he)},[us]);o.useEffect(()=>{const $=()=>oa(!!document.fullscreenElement);return document.addEventListener("fullscreenchange",$),()=>document.removeEventListener("fullscreenchange",$)},[]);const Ga=o.useRef(void 0),Cs=o.useRef(!0),Dn=o.useCallback(()=>{if(Q){pe();return}Cs.current&&(clearTimeout(Ga.current),Ga.current=setTimeout(()=>{const $=y.current;$&&$.isConnected&&($.paused?$.play().catch(()=>{}):$.pause())},200))},[pe,Q]),Tr=o.useCallback(()=>{clearTimeout(Ga.current),xs()},[xs]);o.useEffect(()=>()=>clearTimeout(Ga.current),[]);const Ja=o.useRef(!1),Es=o.useRef(void 0),[$s,Zn]=o.useState(0),Ln=o.useCallback($=>{L.current.fired||(L.current.fired=!0,L.current.startMs=Date.now(),ne("immersion_session_started",{material_type:"video",has_primary_subs:$,has_secondary_subs:!1}))},[]);o.useEffect(()=>{Ja.current=!1;async function $(he=0,_e=0){if(Ja.current)return;vt(!0),A(!1),J(!1),H(!1);const Pt=await D0(t);let Rt=!1,Ia;if(Pt){const Ra=await F0(t);Ra.length>0&&Ra.some(La=>La.tokens?.length>0)?(Ia=(await L0(t))?.serverUpdatedAt,Ja.current||(lt(Ra),jt(!0),vt(!1)),Rt=!0):await O0(t)}if(!d?.access_token){!Ja.current&&!Rt&&(vt(!1),A(!0));return}let ts=!1;try{const Ra=await fetch(`${ue()}/api/video/episodes/${t}/tokens`,{headers:{Authorization:`Bearer ${d.access_token}`}});if(!Ra.ok){if(Ja.current||Rt)return;const La=Xl(Ra);if(La.kind==="transient"&&_e<Uu){Es.current=setTimeout(()=>$(he,_e+1),to(_e+1,{baseMs:Vu,maxMs:Ku,retryAfterMs:La.retryAfterMs}));return}vt(!1),A(!0);return}const Ua=await Ra.json();if(ts=!0,Rt&&Ua.status!=="processing"){const La=Ua.updatedAt??null;if(Ia&&La&&Ia===La)return}if(Ua.status==="processing"){if(Rt)return;const La=70;if(!Ja.current)if(he<La){const fs=he<20?3e3:6e3;Es.current=setTimeout(()=>$(he+1),fs)}else vt(!1),J(!0);return}if(Ua.entries&&Array.isArray(Ua.entries)){const La=Ua.entries.map((ls,Zt)=>({episodeId:t,index:ls.index??Zt,startMs:ls.startMs,endMs:ls.endMs,text:ls.text,tokens:(ls.tokens||[]).map(J0)})),fs=La.length>0?La[La.length-1].endMs:0;await z0(t,La,fs,Ua.updatedAt??null),Ja.current||(lt(La),jt(!0),vt(!1))}else Ua.source==="extension"&&!Rt?Ja.current||(vt(!1),H(!0)):Rt||Ja.current||(vt(!1),A(!0))}catch(Ra){if(Ja.current||Rt)return;const Ua=Ql(Ra);if(!ts&&Ua.kind==="transient"&&_e<Uu){Es.current=setTimeout(()=>$(he,_e+1),to(_e+1,{baseMs:Vu,maxMs:Ku,retryAfterMs:Ua.retryAfterMs}));return}vt(!1),A(!0)}}return $(),()=>
223{Ja.current=!0,clearTimeout(Es.current)}},[t,d?.access_token,$s]);const er=o.useCallback(()=>Zn($=>$+1),[]),Zs=o.useCallback(()=>{const $=L.current;$.playSegmentStart!==null&&($.watchedMs+=Date.now()-$.playSegmentStart,$.playSegmentStart=null)},[]);o.useEffect(()=>()=>{if(!L.current.fired)return;Zs();const $=L.current.startMs,he=Date.now(),_e=he-$,Pt=L.current.watchedMs,Rt=L.current.tokensClicked;if(Pt<=0)return;ne("immersion_session_ended",{material_type:"video",session_duration_ms:_e,tokens_clicked:Rt,words_added_to_deck:L.current.wordsAdded,watch_duration_ms:Math.max(0,Pt),subtitle_interactions:Rt});const Ia=_.current;Ia&&fetch(`${ue()}/api/immersion/sessions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${Ia}`},body:JSON.stringify({materialId:null,materialType:"video",startedAt:new Date($).toISOString(),endedAt:new Date(he).toISOString(),durationMs:Math.round(Pt),tokensClicked:Rt}),keepalive:!0}).catch(()=>{})},[t,Zs]),o.useEffect(()=>{const $=sessionStorage.getItem(`video-blob-${t}`);$&&(sessionStorage.removeItem(`video-blob-${t}`),Me.current=!1,ft($))},[t]),o.useEffect(()=>{if(U.current||i!=="synced")return;let $=!0;const he=setTimeout(()=>{if(!$||se||U.current)return;U.current=!0;const _e=ed.forEpisode(t,ke);fe.current=_e,St(!1),gc(_e.resolve(),Pt=>{$&&yt(Pt)}).then(Pt=>{$&&Pt.ok&&(Me.current=!0,ft(Pt.url),ne("cloud_video_stream_started",{resumed_after_expiry:!1}))}).catch(()=>{})},0);return()=>{$=!1,clearTimeout(he)}},[t,ke,se,i]),o.useEffect(()=>{if(!dn)return;let $=!0;return Uh(t).then(he=>{$&&de(he)}),()=>{$=!1}},[t]);const Ts=o.useCallback($=>{se&&!Me.current&&URL.revokeObjectURL(se),Me.current=!1,St(!1),Pe(!1);const he=URL.createObjectURL($);ui(t,$),ft(he);const _e=$.webkitRelativePath||$.name;d?.access_token&&fetch(`${ue()}/api/video/episodes/${t}/video-path`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${d.access_token}`},body:JSON.stringify({videoPath:_e,videoFilename:$.name})}).catch(()=>{})},[se,d?.access_token,t]),en=o.useCallback($=>{const he=$.target.files?.[0];he&&Ts(he)},[Ts]),Vs=o.useCallback(()=>{if(!dn){x.current?.click();return}(async()=>{try{const[$]=await window.showOpenFilePicker({types:[{description:"Video",accept:{"video/*":[".mkv",".mp4",".webm",".m4v",".avi",".mov"]}}],multiple:!1,excludeAcceptAllOption:!1});if(!$)return;const he=await $.getFile();Ts(he),po(t,$).then(()=>{de($.name)})}catch{}})()},[Ts,t]),vn=o.useCallback(()=>{(async()=>{const $=await fo(t);$?Ts($):Vs()})()},[t,Ts,Vs]);o.useEffect(()=>{const $=Me.current;return()=>{se&&!$&&URL.revokeObjectURL(se)}},[se]),o.useEffect(()=>{const $=y.current;if(!$||!se)return;ct(void 0);const he=()=>{Ln(j.current),L.current.playSegmentStart===null&&(L.current.playSegmentStart=Date.now())},_e=()=>Zs(),Pt=()=>{$.playbackRate=ma;const Rt=Number.isFinite($.duration)&&$.duration>0?$.duration:null;ct(Rt?Math.round(Rt*1e3):void 0);const Ia=P.current,ts=`${t}\0${se}`,Ra=T.current!==ts?n/1e3:null,Ua=Ia??Ra;if(Ua!==null&&Ua>0){const La=Rt?Math.min(Ua,Rt):Ua;$.currentTime=Math.max(0,La)}P.current=null,T.current=ts,Ia!==null&&$.play().catch(()=>{})};return $.addEventListener("play",he),$.addEventListener("pause",_e),$.addEventListener("ended",_e),$.addEventListener("loadedmetadata",Pt),$.readyState>=HTMLMediaElement.HAVE_METADATA?Pt():$.playbackRate=ma,$.paused||he(),()=>{Zs(),$.removeEventListener("play",he),$.removeEventListener("pause",_e),$.removeEventListener("ended",_e),$.removeEventListener("loadedmetadata",Pt)}},[se,ma,Zs,Ln,t,n]),o.useEffect(()=>{const $=y.current;if(!$||!Le)return;let he=null;me.current=!1,Ge.current=!1;let _e=-1;const Pt=Ua=>{const La=$.currentTime*1e3;if(je.length>0){const fs=Ru(je,La,Oe),ls=ia.current,Zt=ls>=0?je[ls]:null,zs=Ge.current||$.seeking&&!me.current;Ge.current=!1;const ks=c0({liveIdx:fs,watchedIdx:ls,latchedIdx:va.current??-1,atEndReachedForWatched:!!Zt&&i0(La,Zt,Oe),justSeeked:zs,loopEnabled:I.current,autoPauseEnabled:xe.current,autoPauseAt:Ne.current});if(ia.current=ks.nextWatchedIdx,va.current=ks.nextLatchedIdx<0?null:ks.nextLatchedIdx,fs>=0&&(oe.current=fs),ks.action==="loop"||ks.action==="loopPauseStart"){const Fs=je[ks.nextWatchedIdx];Fs&&(me.current=!0,$.currentTime=fl(Fs,Oe)+gt,ks.action==="loopPauseStart"&&$.pause()),Ua&&(he=requestAnimationFrame(()=>Pt(!0)));return}(ks.action==="pauseEnd"||ks.action==="pauseStart")&&$.pause(),fs!==_e&&(_e=fs,Ct(fs))}Ua&&(he=requestAnimationFrame(()=>Pt(!0)))},Rt=()=>{he===null&&(he=requestAnimationFrame(()=>Pt(!0)))},Ia=()=>{he!==null&&(cancelAnimationFrame(he),he=null)},ts=()=>{me.current?me.current=!1:Ge.current=!0,Pt(!1)};$.addEventListener("play",Rt),$.addEventListener("pause",Ia),$.addEventListener("ended",Ia),$.addEventListener("seeked",ts);const Ra=je.length>0?Ru(je,$.currentTime*1e3,Oe):-1;return ia.current=Ra,Ra>=0&&(oe.current=Ra),xe.current&&Ne.current==="start"&&(va.current=Ra),Ct(Ra),_e=Ra,$.paused||Rt(),(
223)=>{Ia(),$.removeEventListener("play",Rt),$.removeEventListener("pause",Ia),$.removeEventListener("ended",Ia),$.removeEventListener("seeked",ts)}},[je,Oe,Le,se]),G0({episodeId:t,videoRef:y,videoSrc:se,subtitleOffsetMs:Oe,initialOffsetMs:r,accessTokenRef:_,enabled:!!d?.access_token}),o.useEffect(()=>{if(!d?.access_token)return;const $=()=>{const _e=y.current;if(!_e||!(_e.duration>0))return;const Pt=_e.currentTime/_e.duration*100;for(const Rt of[25,50,75,100])Pt>=Rt&&L.current.milestones.add(Rt)},he=y.current;return he&&(he.duration>0?$():he.addEventListener("loadedmetadata",$,{once:!0})),w.current=setInterval(()=>{const _e=y.current;if(!(!_e||_e.paused)&&_e.duration>0){const Pt=_e.currentTime/_e.duration*100;for(const Rt of[25,50,75,100])Pt>=Rt&&!L.current.milestones.has(Rt)&&(L.current.milestones.add(Rt),ne("immersion_video_milestone_reached",{milestone:Rt}))}},5e3),()=>{clearInterval(w.current),he&&he.removeEventListener("loadedmetadata",$)}},[t,d?.access_token]),o.useEffect(()=>{const $=y.current;if(!$||!se)return;const he=()=>{Me.current&&fe.current?.notePlaybackProgress()};return $.addEventListener("playing",he),$.addEventListener("timeupdate",he),()=>{$.removeEventListener("playing",he),$.removeEventListener("timeupdate",he)}},[se]),o.useEffect(()=>{const $=he=>{const _e=y.current;if(!_e||he.defaultPrevented||S0(he.target,document.activeElement))return;const Pt=N0({key:he.key,shiftKey:he.shiftKey,ctrlKey:he.ctrlKey,altKey:he.altKey,metaKey:he.metaKey,shortcutsOpen:Xt});if(Pt)switch(he.preventDefault(),Pt.type){case"playPause":_e.paused?_e.play().catch(()=>{}):_e.pause();break;case"seekBy":_e.currentTime=Math.max(0,_e.currentTime+Pt.seconds);break;case"seekToFraction":_e.duration>0?_e.currentTime=Pt.fraction*_e.duration:Pt.fraction===0&&(_e.currentTime=0);break;case"seekToEnd":_e.duration>0&&(_e.currentTime=_e.duration);break;case"nudgeSubtitleOffset":pt(Rt=>Rt+Pt.direction*Kr);break;case"volumeBy":ha(Pt.delta);break;case"toggleMute":_e.muted=!_e.muted;break;case"speedBy":za(Pt.delta);break;case"toggleFullscreen":xs();break;
223case"toggleVertical":Tt.toggle();break;case"toggleAnnotations":Be(!Ve),ne("immersion_setting_changed",{setting:"annotations",value:!Ve,previous:Ve});break;case"toggleFurigana":At(!Ke),ne("immersion_setting_changed",{setting:"furigana",value:!Ke,previous:Ke});break;case"toggleSettings":fa(Rt=>!Rt);break;case"openShortcuts":ga(!0);break;case"closeShortcuts":ga(!1);break;case"prevCue":Mt();break;case"nextCue":Ma();break;case"replayCue":It();break;case"toggleLoop":Nt();break;case"toggleAutoPause":Lt();break;case"toggleBlur":F();break}};return window.addEventListener("keydown",$),()=>window.removeEventListener("keydown",$)},[xs,pt,Mt,Ma,It,Nt,Lt,F,Xt,za,ha,Tt,Ve,Ke]);const Ms=o.useMemo(()=>Et<0||!je[Et]?null:je[Et].tokens,[je,Et]),tr=o.useMemo(()=>{const $=new Set;for(const he of Ms??[])for(const _e of dc(he,()=>!0))$.add(_e);return Array.from($)},[Ms]),hn=!!d&&zt,{knowledgeMap:tn}=oc(hn?Ze:void 0,tr),jn=o.useMemo(()=>Et<0||!je[Et]?null:je[Et].text,[je,Et]),On=se?e.jsx("video",{ref:y,playsInline:!0,crossOrigin:os&&Qs?"anonymous":void 0,src:se,className:"absolute inset-0 w-full h-full object-contain pointer-events-none",onError:()=>{const $=y.current;if(Me.current&&fe.current){const he=$?.currentTime??0;fe.current.handlePlaybackError(he).then(_e=>{_e.recovered?(Me.current=!0,P.current=_e.resumeAtSeconds,ft(_e.url),ne("cloud_video_stream_started",{resumed_after_expiry:!0})):(Me.current=!1,ft(null),St(!0))});return}se&&URL.revokeObjectURL(se),ft(null),Pe(!0)}}):ve?e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:b?e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},role:"status","aria-live":"polite",children:"Loading from your cloud libraryâ¦"}):e.jsx("div",{"aria-hidden":"true",children:e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999})})}):e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsxs("div",{className:"text-center",children:[ut&&e.jsx("p",{className:"text-sm mb-2",style:{color:"var(--theater-text-soft)"},children:"Couldn't stream from your cloud library â select the file to play it locally."}),ee&&e.jsx("p",{className:"text-sm mb-2",style:{color:"var(--theater-text-soft)"},children:"The video file needs to be re-selected after a reload."}),e.jsx("p",{className:"text-sm mb-4",style:{color:"var(--theater-text-muted)"},children:s?`Select "${s}" from your device`:"Select a video file to play"}),e.jsxs("div",{className:"flex flex-col items-center gap-2",children:[D&&e.jsxs("button",{type:"button",className:"theater-btn theater-btn--primary",onClick:$=>{$.stopPropagation(),vn()},children:[e.jsx(ri,{size:16}),"Resume â ",D]}),e.jsxs("button",{type:"button",className:D?"theater-btn theater-btn--secondary":"theater-btn theater-btn--primary",onClick:$=>{$.stopPropagation(),Vs()},children:[!D&&e.jsx(ri,{size:16}),"Choose Video File"]})]})]})});return e.jsxs("div",{className:`wc-root im-logged video-theater mobile-viewport-takeover ${g} fixed inset-0 z-[100]${Tt.enabled?" flex flex-col":""}`,"data-mobile-viewport-surface":"video-theater",ref:v,onClick:Dn,onDoubleClick:Tr,style:{background:"var(--theater-bg)",...Tt.enabled?{overflow:"hidden"}:{}},children:[e.jsx("input",{ref:x,type:"file",accept:"video/*",className:"hidden",onChange:en}),Tt.enabled&&se?e.jsx("div",{className:"relative w-full shrink-0",style:{aspectRatio:"16 / 9",background:"var(--theater-bg)"},children:On}):On,se&&Le&&!Tt.enabled&&e.jsx(e0,{primaryTokens:Ve&&Ms&&Ms.length>0?Ms:null,primaryPlainText:!Ve||Ms&&Ms.length===0?jn:null,onTokenClick:Fe,showFurigana:Ve&&Ke,colorMode:Ve?Jt:"none",knownStatusMap:Ut,deriveUnseenByPos:!0,showGrammarProgress:hn,grammarKnowledgeMap:tn,fontSize:la,blur:ka,revealed:es,onReveal:()=>Ta(!0),bottomOffsetPx:Dt+Z0[da]}),se&&e.jsx(x0,{videoRef:y,containerRef:v,isFullscreen:Pa,onToggleFullscreen:xs,onVisibilityChange:$=>{Cs.current=$},onReservedHeightChange:ba,onPrevCue:Mt,onNextCue:Ma,onReplayCue:It,loopEnabled:Gt,onToggleLoop:Nt,autoPauseEnabled:ea,onToggleAutoPause:Lt,cueNavAvailable:Le&&je.length>0,settingsOpen:it,onSettingsOpenChange:fa,stacked:Tt.enabled,verticalToggleVisible:Tt.isPortraitMobile||Tt.enabled,verticalEnabled:Tt.enabled,onToggleVertical:Tt.toggle,onShowShortcuts:()=>ga(!0),onVolumePreferenceChange:ca,settingsContent:e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"text-xs font-medium truncate max-w-[200px]",style:{color:"var(--theater-text)"},children:a}),e.jsx("div",{"data-condensed-audio-control":!0,children:e.jsx(b0,{cues:je,offsetMs:Oe,totalDurationMs:Ft,getVideoBlob:Ot,canGenerate:(se.startsWith("blob:")||i==="synced")&&Le&&je.length>
2230,disabledReason:Le?je.length===0?"No dialogue cues were found for this episode.":"Load the video to generate condensed audio.":"Preparing the episode subtitlesâ¦",onChooseLocalFile:!se.startsWith("blob:")&&i!=="synced"?Vs:void 0,filenameBase:a||t||"condensed-audio"})}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] uppercase tracking-wide block mb-1.5",style:{color:"var(--theater-text-muted)"},children:"Font Size"}),e.jsx("div",{className:"flex gap-1",children:_t.map(($,he)=>e.jsx("button",{onClick:()=>{const _e=_t[qt];sa(he),$!==_e&&ne("immersion_setting_changed",{setting:"font_size",value:$,previous:_e})},className:"flex-1 py-1 rounded-[var(--wc-radius-ink)] text-xs font-medium transition-colors",style:qt===he?{background:"var(--theater-surface-hover)",color:"var(--theater-text)"}:{color:"var(--theater-text-soft)"},children:$==="sm"?"S":$==="base"?"M":$==="lg"?"L":"XL"},$))})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",id:"vv-text-analysis-label",style:{color:"var(--theater-text-soft)"},children:"Text Analysis"}),e.jsx("button",{role:"switch","aria-checked":Ve,"aria-labelledby":"vv-text-analysis-label",onClick:()=>{Be($=>!$),ne("immersion_setting_changed",{setting:"annotations",value:!Ve,previous:Ve})},className:"w-10 h-5 rounded-[var(--wc-radius-ink)] transition-colors",style:{background:Ve?"hsl(var(--module-accent))":"var(--theater-surface-hover)"},children:e.jsx("div",{className:`w-4 h-4 rounded-[var(--wc-radius-ink)] shadow transition-transform mx-0.5 ${Ve?"translate-x-5":"translate-x-0"}`,style:{background:"var(--theater-text-on-active)"}})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",id:"vv-furigana-label",style:{color:"var(--theater-text-soft)"},children:"Furigana"}),e.jsx("button",{role:"switch","aria-checked":Ke,"aria-labelledby":"vv-furigana-label",onClick:()=>{At($=>!$),ne("immersion_setting_changed",{setting:"furigana",value:!Ke,previous:Ke})},className:"w-10 h-5 rounded-[var(--wc-radius-ink)] transition-colors",style:{background:Ke?"hsl(var(--module-accent))":"var(--theater-surface-hover)"},children:e.jsx("div",{className:`w-4 h-4 rounded-[var(--wc-radius-ink)] shadow transition-transform mx-0.5 ${Ke?"translate-x-5":"translate-x-0"}`,style:{background:"var(--theater-text-on-active)"}})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("span",{id:"vv-vocabulary-colors-label",className:"block text-sm",style:{color:"var(--theater-text-soft)"},children:"Vocabulary colors"}),e.jsx("span",{className:"block text-[11px]",style:{color:"var(--theater-text-muted)"},children:"Based on your learning progress"})]}),e.jsx("button",{role:"switch","aria-checked":Jt==="known","aria-labelledby":"vv-vocabulary-colors-label",onClick:()=>{const $=Jt==="known"?"none":"known";ta($),ne("immersion_setting_changed",{setting:"known_coloring",value:$==="known",previous:Jt==="known"})},className:"w-10 h-5 shrink-0 rounded-[var(--wc-radius-ink)] transition-colors",style:{background:Jt==="known"?"hsl(var(--module-accent))":"var(--theater-surface-hover)"},children:e.jsx("div",{className:`w-4 h-4 rounded-[var(--wc-radius-ink)] shadow transition-transform mx-0.5 ${Jt==="known"?"translate-x-5":"translate-x-0"}`,style:{background:"var(--theater-text-on-active)"}})})]}),e.jsxs("div",{className:"flex flex-wrap gap-x-3 gap-y-1 text-[11px]",style:{color:"var(--theater-text-muted)"},"aria-hidden":"true",children:[e.jsxs("span",{children:[e.jsx("span",{className:"text-blue-400",children:"â"})," New"]}),e.jsxs("span",{children:[e.jsx("span",{className:"text-amber-400",children:"â"})," Learning"]}),e.jsx("span",{children:"Known: plain"})]})]}),e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("span",{id:"vv-grammar-progress-label",className:"block text-sm",style:{color:"var(--theater-text-soft)"},children:"Grammar progress"}),e.jsx("span",{className:"block text-[11px]",style:{color:"var(--theater-text-muted)"},children:"Blue dots · amber dashes · green solid"})]}),e.jsx("button",{role:"switch","aria-checked":zt,"aria-labelledby":"vv-grammar-progress-label",onClick:()=>{K(!zt),ne("immersion_setting_changed",{setting:"grammar_progress",value:!zt,previous:zt})},className:"w-10 h-5 shrink-0 rounded-[var(--wc-radius-ink)] transition-colors",style:{background:zt?"hsl(var(--module-accent))":"var(--theater-surface-hover)"},children:e.jsx("div",{className:`w-4 h-4 rounded-[var(--wc-radius-ink)] shadow transition-transform mx-0.5 ${zt?"translate-x-5":"translate-x-0"}`,style:{background:"var(--theater-text-on-active)"}})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Speed"}),e.jsxs("div",{className:"flex items-center gap-2",style:{color:"var(--theater-text)"},children:[e.jsx("button",{onClick:()=>
223za(-.05),className:"text-sm px-1",style:{color:"var(--theater-text-soft)"},"aria-label":"Slower",children:"â"}),e.jsxs("span",{className:"text-xs font-mono tabular-nums w-10 text-center",children:[ma.toFixed(2),"x"]}),e.jsx("button",{onClick:()=>za(.05),className:"text-sm px-1",style:{color:"var(--theater-text-soft)"},"aria-label":"Faster",children:"+"}),ma!==1&&e.jsx("button",{onClick:()=>za(1-ma),className:"text-xs",style:{color:"var(--theater-text-muted)"},"aria-label":"Reset speed",children:"âº"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] uppercase tracking-wide block mb-1.5",style:{color:"var(--theater-text-muted)"},children:"Subtitle Sync"}),e.jsx(a0,{primaryOffsetMs:Oe,onPrimaryOffsetChange:pt})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] uppercase tracking-wide block mb-1.5",style:{color:"var(--theater-text-muted)"},children:"Subtitle position"}),e.jsx("div",{className:"grid grid-cols-3 gap-1.5",role:"group","aria-label":"Subtitle vertical position",children:[["near","Near"],["standard","Default"],["high","Higher"]].map(([$,he])=>e.jsx("button",{type:"button",onClick:()=>{const _e=da;xa($),$!==_e&&ne("immersion_setting_changed",{setting:"subtitle_position",value:$,previous:_e})},className:`theater-btn ${da===$?"theater-btn--primary":"theater-btn--secondary"} px-2`,"aria-pressed":da===$,children:he},$))}),e.jsx("p",{className:"mt-1.5 text-[11px]",style:{color:"var(--theater-text-muted)"},children:"Captions always clear the controls; move them higher for dense scenes."})]}),e.jsxs("div",{children:[e.jsx("label",{className:"text-[11px] uppercase tracking-wide block mb-1.5",style:{color:"var(--theater-text-muted)"},children:"Auto-pause per line"}),e.jsx("div",{className:"flex gap-1",children:[["off","Off"],["start","At start"],["end","At end"]].map(([$,he])=>{const _e=ea?pa:"off";return e.jsx("button",{onClick:()=>qa($),className:"flex-1 py-1 rounded-[var(--wc-radius-ink)] text-xs font-medium transition-colors",style:_e===$?{background:"var(--theater-surface-hover)",color:"var(--theater-text)"}:{color:"var(--theater-text-soft)"},children:he},$)})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",id:"vv-blur-label",style:{color:"var(--theater-text-soft)"},children:"Blur subtitles"}),e.jsx("button",{role:"switch","aria-checked":ka,"aria-labelledby":"vv-blur-label",onClick:F,className:"w-10 h-5 rounded-[var(--wc-radius-ink)] transition-colors",style:{background:ka?"hsl(var(--module-accent))":"var(--theater-surface-hover)"},children:e.jsx("div",{className:`w-4 h-4 rounded-[var(--wc-radius-ink)] shadow transition-transform mx-0.5 ${ka?"translate-x-5":"translate-x-0"}`,style:{background:"var(--theater-text-on-active)"}})})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Player theme"}),e.jsxs("button",{onClick:()=>{ne("immersion_setting_changed",{setting:"theme",value:h?"light":"dark",previous:h?"dark":"light"}),p()},className:"flex items-center gap-1.5 px-2 py-1 rounded-[var(--wc-radius-ink)] text-xs transition-colors",style:{color:"var(--theater-text-soft)"},title:h?"Switch to light mode":"Switch to dark mode",children:[h?e.jsx(bm,{size:14}):e.jsx(ym,{size:14}),e.jsx("span",{children:h?"Light":"Dark"})]})]}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Keyboard shortcuts"}),e.jsx("button",{onClick:()=>{fa(!1),ga(!0)},className:"theater-btn theater-btn--secondary px-2",children:"View"})]})]})}),se&&Le&&Tt.enabled&&e.jsx(k0,{entries:je,currentIndex:Et,onSeekToIndex:tt,onTokenClick:Fe,annotationsEnabled:Ve,showFurigana:Ve&&Ke,colorMode:Ve?Jt:"none",knownStatusMap:Ut,deriveUnseenByPos:!0,showGrammarProgress:hn,grammarKnowledgeMap:tn,fontSize:la,blur:ka,revealed:es,onReveal:()=>Ta(!0)}),aa&&se&&e.jsx("div",{className:"absolute left-1/2 -translate-x-1/2 z-20 flex flex-col items-center gap-1",style:{bottom:`${Dt+12}px`},children:b?e.jsx("div",{className:"theater-panel px-4 py-2 text-sm",style:{color:"var(--theater-text-soft)"},role:"status","aria-live":"polite",children:"Processing subtitles..."}):e.jsxs(e.Fragment,{children:[e.jsx(bs,{image:cs,size:112,duration:1.1,repeatDelay:999}),e.jsx("span",{className:"text-sm",style:{color:"var(--theater-text-soft)"},role:"status","aria-live":"polite",children:"Processing subtitles..."})]})}),M&&se&&e.jsxs("div",{className:"theater-panel absolute left-1/2 -translate-x-1/2 z-20 flex items-start gap-3 px-4 py-3 text-sm",style:{bottom:`${Dt+12}px`,color:"var(--theater-text-soft)",maxWidth:"min(90vw, 30rem)"},role:"status",children:[e.jsx(vo,{size:18,className:"mt-0.5 shrink-0",style:{color:"var(--theater-text-soft)"}}),e.jsx("span",{children:"This episode was annotated with the Shizen browser extension. Open it on the streaming site with the extension installed to watch with tap-to-lookup."})]}),O&&!M&&se&&e.jsxs("div",{className:"theater-panel absolute left-1/2 -translate-x-1/2 z-20 flex items-center gap-3 px-4 py-2 text-sm",style:{bottom:`${Dt+12}px`,color:"var(--theater-text-soft)"},role:"alert",children:[e.jsx("span",{children:"Couldn't load subtitles."}),e.jsx("button",{onClick:er,className:"theater-btn theater-btn--secondary",children:"Retry"})]}),k&&!O&&se&&e.jsxs("div",{className:"theater-panel absolute left-1/2 -translate-x-1/2 z-20 flex items-center gap-3 px-4 py-2 text-sm",style:{bottom:`${Dt+12}px`,color:"var(--theater-text-soft)"},role:"status","aria-live":"polite",children:[e.jsx("span",{children:"Still analyzing subtitles â you can keep watching or leave; theyâll appear shortly."}),e.jsx("button",{onClick:er,className:"theater-btn theater-btn--secondary",children:"Check again"})]}),Aa&&e.jsxs("div",{className:"theater-panel absolute top-16 left-1/2 -translate-x-1/2 flex items-start gap-3 px-4 py-3 text-sm",style:{color:"var(--theater-text-soft)",maxWidth:"min(90vw, 32rem)"},role:"alert","aria-live":"assertive",onClick:$=>$.stopPropagation(),children:[e.jsxs("span",{children:[Aa==="unsupported"?"Fullscreen is not available in this browser.":"Fullscreen could not be opened."," ","The video will stay inline so subtitles, lookup, and controls remain available."]}),e.jsx("button",{type:"button",className:"theater-chrome-icon-btn theater-chrome-icon-btn--sm shrink-0",onClick:()=>Fa(null),"aria-label":"Dismiss fullscreen message",children:e.jsx(rs,{size:15,"aria-hidden":"true"})})]}),Xt&&e.jsx(C0,{onClose:()=>ga(!1)}),e.jsx("div",{className:"mobile-viewport-safe-top absolute top-0 inset-x-0 z-50 pointer-events-none",children:e.jsx("button",{onClick:$=>{$.stopPropagation(),c()},className:"theater-chrome-icon-btn theater-chrome-icon-btn--floating pointer-events-auto",title:"Back","aria-label":"Back to library",children:e.jsx(Za,{size:20})})}),e.jsx(lc,{token:Q,position:W,isLoading:E,onClose:pe,deckApi:is,mediaSourceContext:V,isMediaContextPaid:m,onMediaContextUpgrade:$a()?()=>u("source_memory","single_word_save"):void 0,grammarKnowledgeApi:d?Ze:void 0,aiHelpApi:ye,richLookupApi:Qe,kanjiDetailApi:Y,mnemonicsApi:d?Ac:void 0,onOpenWord:jr.onOpenWord,onOpenKanji:jr.onOpenKanji,onDeckToggle:$=>
223{$&&(L.current.wordsAdded++,ne("immersion_word_added_to_deck",{material_type:"video",source:"video_subtitle"}))}})]})}function t_({state:t,onBack:a,onRetry:s}){const n=t.status==="loading";return e.jsxs("div",{className:"wc-root im-logged video-theater mobile-viewport-takeover fixed inset-0 z-[100] flex items-center justify-center","data-mobile-viewport-surface":"video-playback-bootstrap",style:{background:"var(--theater-bg, #111014)",color:"var(--theater-text, #f7f3f1)"},children:[e.jsx("div",{className:"mobile-viewport-safe-top absolute top-0 inset-x-0 pointer-events-none",children:e.jsxs("button",{type:"button",onClick:a,className:"pointer-events-auto inline-flex items-center gap-2 rounded-full px-4 py-2 text-sm",style:{background:"var(--theater-surface, rgba(255,255,255,.1))"},children:[e.jsx(Za,{className:"h-4 w-4","aria-hidden":"true"}),"Back to library"]})}),e.jsx("div",{className:"mobile-viewport-contained max-w-md text-center",role:n?"status":"alert","aria-live":"polite",children:n?e.jsxs(e.Fragment,{children:[e.jsx(Sa,{className:"mx-auto mb-4 h-8 w-8 animate-spin","aria-hidden":"true"}),e.jsx("p",{className:"text-sm",children:"Loading episodeâ¦"})]}):e.jsxs(e.Fragment,{children:[e.jsx("h1",{className:"text-xl font-semibold",children:t.status==="not-found"?"Episode unavailable":"Could not load episode"}),e.jsx("p",{className:"mt-2 text-sm opacity-75",children:t.message}),t.status==="error"&&e.jsxs("button",{type:"button",onClick:s,className:"mt-5 inline-flex items-center gap-2 rounded-full px-5 py-2.5 text-sm font-medium",style:{background:"var(--theater-accent, #c6a7d2)",color:"#17131a"},children:[e.jsx(Hn,{className:"h-4 w-4","aria-hidden":"true"}),"Try again"]})]})})]})}function Sp({title:t,titleJp:a,coverImageUrl:s,titleSlot:n,badges:r,genres:i,description:l,quickStats:c,coverageStats:d,actions:m,coverSlotBelow:u,onBack:h,backLabel:p="Back",isLoading:g=!1,className:f}){const[b,y]=o.useState(!1);return g?e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",className:"wc-cdhero-back",onClick:h,children:[e.jsx("span",{className:"arrow","aria-hidden":"true",children:"â"}),p]}),e.jsx("section",{className:`wc-cdhero ${f??""}`,children:e.jsxs("div",{className:"wc-cdhero-grid",children:[e.jsx("div",{className:"wc-cdhero-coverwrap",children:e.jsx("div",{className:"wc-cdhero-skel-cover"})}),e.jsxs("div",{className:"wc-cdhero-info",children:[e.jsx("div",{className:"wc-cdhero-skel-line",style:{width:"40%"}}),e.jsx("div",{className:"wc-cdhero-skel-line h-lg",style:{width:"70%"}}),e.jsx("div",{className:"wc-cdhero-skel-line h-md",style:{width:"50%"}}),e.jsx("div",{className:"wc-cdhero-skel-line",style:{width:"95%"}}),e.jsx("div",{className:"wc-cdhero-skel-line",style:{width:"88%"}}),e.jsx("div",{className:"wc-cdhero-skel-line",style:{width:"72%"}})]})]})})]}):e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",className:"wc-cdhero-back",onClick:h,children:[e.jsx("span",{className:"arrow","aria-hidden":"true",children:"â"}),p]}),e.jsx(ze.section,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},transition:{duration:.35,ease:[.22,1,.36,1]},className:`wc-cdhero ${f??""}`,children:e.jsxs("div",{className:"wc-cdhero-grid",children:[e.jsxs("div",{className:"wc-cdhero-coverwrap",children:[e.jsx("div",{className:"wc-cdhero-cover",children:s?e.jsx("img",{src:s,alt:t,loading:"lazy"}):e.jsx(wi,{title:t,titleJp:a})}),u]}),e.jsxs("div",{className:"wc-cdhero-info",children:[r&&e.jsx("div",{className:"wc-cdhero-badges",children:r}),n||e.jsx("h1",{className:"wc-cdhero-title",children:t}),a&&e.jsx("p",{className:"wc-cdhero-titlejp",children:a}),i&&e.jsx("div",{className:"wc-cdhero-genres",children:i}),l&&e.jsxs(e.Fragment,{children:[e.jsx("p",{className:`wc-cdhero-desc ${b?"":"is-clamped"}`,children:l}),l.length>200&&e.jsx("button",{type:"button",className:"wc-cdhero-desc-toggle",onClick:()=>y(!b),children:b?"Show less":"Show more"})]}),c&&e.jsx("div",{className:"wc-cdhero-quick",children:c}),d&&d.length>0&&e.jsx("div",{className:"wc-cdhero-coverage",children:d.map(x=>e.jsxs("div",{className:"wc-cdhero-coverage-row",children:[e.jsxs("div",{className:"wc-cdhero-coverage-head",children:[e.jsxs("span",{className:"lbl",children:[e.jsx(x.icon,{size:12}),x.label]}),e.jsxs("span",{className:"val",children:[x.pct,"%",e.jsxs("span",{className:"ratio",children:["(",x.known.toLocaleStr
223ing(),"/",x.total.toLocaleString(),")"]})]})]}),e.jsx("div",{className:"wc-cdhero-coverage-bar",children:e.jsx("span",{className:"fill",style:{width:`${Math.min(100,Math.max(0,x.pct))}%`}})})]},x.label))}),m&&e.jsx("div",{className:"wc-cdhero-actions",children:m})]})]})})]})}function a_({isExpanded:t,onToggle:a,icon:s,iconBadge:n=!1,title:r,titleSize:i="sm",subtitle:l,headerActions:c,managementPanel:d,animationDelay:m=0,isDark:u=!1,className:h="",children:p}){const g=i==="lg",f=n?e.jsx("div",{className:"shrink-0 flex items-center justify-center",style:{width:40,height:40,borderRadius:"var(--wc-radius-leaf)",background:"hsl(var(--module-accent) / 0.15)"},children:s}):e.jsx("div",{className:"shrink-0",children:s}),b=e.jsxs("div",{className:`flex items-center justify-between cursor-pointer select-none transition-colors ${g?"p-5 gap-4":"p-4 gap-3"}`,onClick:a,style:{color:"var(--ink)"},children:[e.jsxs("div",{className:`flex items-center min-w-0 ${g?"gap-4":"gap-3"}`,children:[e.jsx(ze.div,{animate:{rotate:t?90:0},transition:{duration:.2},className:"shrink-0",style:{color:"var(--ink-soft)"},children:e.jsx(As,{size:g?20:16})}),f,e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:`truncate ${g?"font-semibold text-lg":"text-sm font-medium"}`,style:{color:"var(--ink)"},children:r}),e.jsx("p",{className:`flex items-center flex-wrap gap-x-1 gap-y-0.5 mt-0.5 ${g?"text-sm":"text-xs"}`,style:{color:"var(--ink-soft)"},children:l})]})]}),e.jsx("div",{className:`flex items-center shrink-0 ml-3 ${g?"gap-3":"gap-1.5"}`,onClick:x=>x.stopPropagation(),children:c})]}),y=e.jsx(Oa,{children:t&&e.jsx(ze.div,{initial:{height:0,opacity:0},animate:{height:"auto",opacity:1},exit:{height:0,opacity:0},transition:{duration:.2},className:"overflow-hidden",style:{borderTop:"1px solid hsl(var(--module-accent) / 0.15)"},children:e.jsx("div",{className:"px-3 pt-2 pb-3 space-y-1",children:p})})});return e.jsxs(ze.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{duration:.25,delay:m},className:`overflow-hidden ${h}`,style:{borderRadius:"var(--wc-radius-leaf)",border:"1px solid hsl(var(--module-accent) / 0.18)",background:u?"hsl(var(--module-accent) / 0.06)":"var(--paper)"},children:[b,d,y]})}function Np({icon:t,label:a,rightControls:s,onClick:n,isActive:r=!1,highlighted:i=!1,animationDelay:l=0,className:c="",style:d}){const m=!!n&&!r,u=["wc-row",m?"is-clickable":"",r?"is-active":"",i?"is-highlighted":"",c].filter(Boolean).join(" ");return e.jsxs(ze.div,{initial:{opacity:0,y:6},animate:{opacity:1,y:0},transition:{duration:.22,delay:l,ease:[.22,1,.36,1]},onClick:m?n:void 0,className:u,style:d,children:[e.jsx("div",{className:"wc-row-icon",children:t}),e.jsx("div",{className:"wc-row-label",children:a}),e.jsx("div",{className:"wc-row-controls",onClick:h=>h.stopPropagation(),children:s})]})}const Di=Object.freeze({status:"idle"});async function gl(t){return fo(t)}function s_(t){return t.status==="skipped_quota"?{status:"error",retryable:!0,message:"Skipped â cloud space full"}:t}function n_({episode:t,isPro:a}){const{getAccessToken:s}=ps(),[n,r]=o.useState(Di),[i,l]=o.useState(Di),[c,d]=o.useState(null),[m,u]=o.useState(null),[h,p]=o.useState(null);o.useEffect(()=>a?(yn.configure(s),yn.subscribe(P=>{r(P.get(t.id)??Di)})):void 0,[a,s,t.id]),o.useEffect(()=>a?Jn.subscribe(P=>{const N=P.get(t.id);l(N?s_(N):Di)}):void 0,[a,t.id]);const g=i.status!=="idle"?i:n;o.useEffect(()=>{if(!a||!dn)return;let T=!0;return Uh(t.id).then(P=>{T&&d(P)}),()=>{T=!1}},[a,t.id]);const f=o.useCallback(T=>{p(null),yn.enqueue({episodeId:t.id,file:T})},[t.id]),b=o.useCallback(()=>{(async()=>{p(null);const T=await gl(t.id);if(!T){p("Open the episode and pick its file first, then store it.");return}u(T)})()},[t.id]),y=o.useCallback(()=>{const T=m;u(null),T&&f(T)},[m,f]);o.useEffect(()=>{if(g.status!=="attestation_required")return;let T=!0;return gl(t.id).then(P=>{T&&P&&u(P)}),()=>{T=!1}},[g.status,t.id]);const x=o.useCallback(()=>{(async()=>{const T=await gl(t.id);if(!T){p("Open the episode and pick its file first, then retry.");return}Jn.clearState(t.id),yn.retry({episodeId:t.id,file:T})})()},[t.id]),v=o.useCallback(()=>{yn.cancel(t.id)},[t.id]);if(!a)return null;const w=t.cloud_sync_status,j=g.status!=="idle"?g.status:w==="synced"?"synced":w==="error"?"error":w==="uploading"?"interrupted":"local-only";return e.jsxs(e.Fragment,{children:[m&&e.jsx(Uc,{episodeLabel:t.label,onConfirmed:y,onCancel:()=>u(null)}),(()=>{switch(j){case"queued":return e.jsxs("span",{className:"im-ep-cloud",title:"Queued for cloud storage",children:[e.jsx("span",{className:"im-ep-cloud-dot","aria-hidden":"true"}),"Queued"]});case"uploading":{const T=g;return e.jsxs("span",{className:"im-ep-cloud",title:"Storing in y
223our cloud library",children:[e.jsx("span",{className:"im-ep-cloud-dot","aria-hidden":"true"}),T.total>0?`${T.uploaded}/${T.total}`:"Storing",e.jsx("button",{type:"button",className:"im-ep-cloud-cancel",onClick:P=>{P.stopPropagation(),v()},children:"Cancel"})]})}case"synced":return e.jsxs("span",{className:"im-ep-cloud",title:"Stored in your cloud library",children:[e.jsx(Js,{"aria-hidden":"true"})," Stored"]});case"quota_exceeded":return e.jsxs("span",{className:"im-ep-cloud is-warn",title:$a()?"Cloud library full â remove something or upgrade":"Cloud library full â free up space",children:[e.jsx(Qa,{"aria-hidden":"true"})," Cloud full"]});case"unavailable":return null;case"attestation_required":return null;case"error":case"interrupted":{const T=g.status==="error"?g.message:null;return e.jsxs("span",{className:"im-ep-cloud is-warn",title:T??"Cloud storage failed",children:[e.jsx(Qa,{"aria-hidden":"true"}),T&&e.jsx("span",{className:"im-ep-cloud-msg",style:{maxWidth:160,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:T}),e.jsx("button",{type:"button",className:"im-ep-cloud-retry",onClick:P=>{P.stopPropagation(),x()},children:"Retry"})]})}default:return e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",onClick:T=>{T.stopPropagation(),b()},title:c?`Store "${c}" in your cloud library`:"Store this episode in your cloud library",children:[e.jsx(Ws,{size:11})," Store in cloud"]})}})(),h&&e.jsx("span",{className:"im-ep-cloud is-warn",role:"alert",style:{maxWidth:220,whiteSpace:"normal"},children:h})]})}const Or=new Intl.NumberFormat;function r_({quote:t,availableCredits:a,breakdown:s=[]}){const n=Math.max(0,a-t.expectedCharge);return e.jsxs("div",{className:"im-uploader-cost-block","data-credit-quote-id":t.quoteId,children:[e.jsxs("div",{className:"im-uploader-cost-head",children:[e.jsx("span",{children:"Shared-credit quote"}),e.jsxs("span",{className:"ratio",children:["Rate ",t.rateVersion]})]}),e.jsxs("div",{className:"im-uploader-cost-grid",children:[e.jsxs("div",{className:"im-uploader-cost-row",children:[e.jsxs("div",{className:"im-uploader-cost-row-head",children:[e.jsx("strong",{children:"Expected charge"}),e.jsxs("span",{className:"ratio",children:[Or.format(t.expectedCharge)," credits"]})]}),e.jsxs("p",{className:"im-uploader-cost-after",children:[Or.format(a)," available now · about ",Or.format(n)," left afterward."]})]}),e.jsxs("div",{className:"im-uploader-cost-row",children:[e.jsxs("div",{className:"im-uploader-cost-row-head",children:[e.jsx("strong",{children:"Maximum reservation"}),e.jsxs("span",{className:"ratio",children:[Or.format(t.maximumReservation)," credits"]})]}),e.jsx("p",{className:"im-uploader-cost-after",children:"Unused reserved credits are released after the delivered work is measured."})]})]}),s.length>0&&e.jsx("ul",{className:"im-uploader-volume-list","aria-label":"Credit quote breakdown",children:s.map(r=>e.jsxs("li",{className:"im-uploader-volume-row",children:[e.jsx("span",{className:"vol-name",children:r.label}),e.jsxs("span",{className:"vol-pages",children:[Or.format(r.credits)," credits"]})]},r.label))})]})}function Cp(t){return t!==null&&typeof t=="object"&&!Array.isArray(t)?t:null}function Hr(t){return typeof t=="number"&&Number.isSafeInteger(t)&&t>=0}function i_(t){return typeof t=="string"&&Number.isFinite(Date.parse(t))}function Ep(t){const a=Cp(t);
223return!a||typeof a.quoteId!="string"||a.quoteId.length===0||!Hr(a.maximumReservation)||!Hr(a.expectedCharge)||!Hr(a.requestedUnitCount)||!Hr(a.selectedUnitCount)||typeof a.affordable!="boolean"||typeof a.rateVersion!="string"||a.rateVersion.length===0||!i_(a.expiresAt)?null:{quoteId:a.quoteId,maximumReservation:a.maximumReservation,expectedCharge:a.expectedCharge,requestedUnitCount:a.requestedUnitCount,selectedUnitCount:a.selectedUnitCount,affordable:a.affordable,rateVersion:a.rateVersion,expiresAt:a.expiresAt}}function o_(t){const a=Cp(t),s=Ep(a?.quote);return!a||!s||!Hr(a.durationMilliseconds)?null:{quote:s,durationMilliseconds:a.durationMilliseconds}}function yl(t){switch(t){case"reserved":return"Queued for transcription";case"submitting":return"Starting transcription with a protected provider claim";case"submitted":return"Transcribing audio with ElevenLabs";case"delivery_staged":return"Transcript delivered; finalizing the credit receipt";case"published":return"Transcript ready; paid language annotation was not started";case"provider_failed":return"Transcription could not be started; unused credits were released";case"reconciliation_pending":return"Provider usage is being reconciled; no further work will start"}}function l_(t){const a=Math.max(1,Math.ceil(t/6e4));if(a<60)return`about ${a} minute${a===1?"":"s"}`;const s=Math.floor(a/60),n=a%60;return n===0?`about ${s} hour${s===1?"":"s"}`:`about ${s}h ${n}m`}function cr(t){switch(t){case"CLOUD_VIDEO_REQUIRED":return"Store this episode in your Cloud Library before generating subtitles.";case"SUBTITLE_WALLET_NOT_ACTIVE":return"Subtitle generation is not available yet.";case"INSUFFICIENT_CREDITS":return"Your shared-credit balance cannot fund this transcription.";case"SUBTITLE_PROVIDER_UNAVAILABLE":return"ElevenLabs could not complete the request. Any unused reservation will be released or reconciled.";default:return"Subtitle generation is temporarily unavailable. Please try again."}}function Hu({episodeId:t,episodeLabel:a,cloudSynced:s,availableCredits:n,getAccessToken:r,onPublished:i,onWalletChanged:l}){const[c,d]=o.useState(!1),[m,u]=o.useState("idle"),[h,p]=o.useState(null),[g,f]=o.useState(null),[b,y]=o.useState(null),x=async(P,N={})=>{const _=await r();if(!_)throw new Error("AUTH_REQUIRED");return fetch(`${ue()}${P}`,{...N,headers:{...N.headers,Authorization:`Bearer ${_}`}})},v=async()=>{if(d(!0),!s){u("error"),y(cr("CLOUD_VIDEO_REQUIRED"));return}u("previewing"),y(null);try{const P=await x(`/api/video/episodes/${t}/subtitles/preview`,{method:"POST"}),N=await P.json().catch(()=>({}));if(P.status===409&&N.error==="SUBTITLE_ALREADY_EXISTS"){u("reuse"),y("Subtitles already exist â no credits charged."),i();return}const _=o_(N);if(!P.ok||!_){p(_),u("error"),y(cr(String(N.error??"SUBTITLE_UNAVAILABLE")));return}p(_),u("quoted")}catch{u("error"),y(cr("SUBTITLE_UNAVAILABLE"))}},w=async()=>{if(h){u("starting"),y(null);try{const P=await x(`/api/video/episodes/${t}/subtitles/generate`,{method:"POST"}),N=await P.json().catch(()=>({})),_=Ep(N.quote);if(_&&p(q=>q&&{...q,quote:_}),P.status===409&&N.error==="SUBTITLE_ALREADY_EXISTS"){u("reuse"),y("Subtitles already exist â no credits charged."),i();return}if(!P.ok||typeof N.jobId!="string"){if(typeof N.jobId=="string"){f(N.jobId),u("checking"),l();return}u("error"),y(cr(String(N.error??"SUBTITLE_UNAVAILABLE"))),P.status===402&&l();return}const L=String(N.state);if(!["reserved","submitting","submitted","delivery_staged","published"].includes(L)){u("error"),y(cr("SUBTITLE_UNAVAILABLE"));return}f(N.jobId),u(L),l(),L==="published"&&i()}catch{u("error"),y(cr("SUBTITLE_UNAVAILABLE"))}}};o.useEffect(()=>{if(!g||!["reserved","submitting","submitted","delivery_staged","checking"].includes(m))return;let P=!1,N=null;const _=async()=>{try{const L=await x(`/api/video/subtitle-jobs/${g}`),q=await L.json().catch(()=>({}));if(!L.ok||!["reserved","submitting","submitted","delivery_staged","published","provider_failed","reconciliation_pending"].includes(String(q.state)))throw new Error("STATUS_UNAVAILABLE");if(P)return;const O=String(q.state);if(u(O),O==="published"){l(),i();return}if(O==="provider_failed"||O==="reconciliation_pending"){l();return}N=setTimeout(_,2500)}catch{P||(N=setTimeout(_,5e3))}};return _(),()=>{P=!0,N&&clearTimeout(N)}}
223,[g,m,i,l]);const j=["previewing","starting","checking","reserved","submitting","submitted","delivery_staged"].includes(m),T=m==="reserved"||m==="submitting"||m==="submitted"||m==="delivery_staged"?yl(m):m==="published"||m==="reuse"?"Subtitles ready":"Generate subtitles";return e.jsxs(e.Fragment,{children:[e.jsxs("button",{type:"button",onClick:P=>{P.stopPropagation(),v()},className:"wc-cta-square wc-cta-square-secondary--iris im-detail-row-cta",disabled:j,title:s?"Generate Japanese subtitles from this video":"Store the video in your Cloud Library first",children:[e.jsx(Oi,{"aria-hidden":"true"}),T]}),e.jsxs(c_,{open:c,onClose:()=>d(!1),children:[e.jsxs("div",{className:"im-modal-head",children:[e.jsxs("div",{className:"left",children:[e.jsx("div",{className:"icon-box",children:e.jsx(Oi,{size:18})}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h3",{id:"subtitle-generation-title",children:"Generate Japanese subtitles"}),e.jsx("p",{children:a})]})]}),e.jsx("button",{className:"close theater-chrome-icon-btn theater-chrome-icon-btn--sm",onClick:()=>d(!1),"aria-label":"Close",children:e.jsx(rs,{size:18})})]}),m==="previewing"&&e.jsx(bl,{children:"Reading the stored video and preparing an exact quoteâ¦"}),h&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"im-modal-hint",children:["Decoded audio: ",e.jsx("strong",{children:l_(h.durationMilliseconds)}),". This quote covers transcription only."]}),n!==null?e.jsx(r_,{quote:h.quote,availableCredits:n,breakdown:[{label:"Japanese subtitle transcription",credits:h.quote.expectedCharge}]}):e.jsxs("div",{className:"im-modal-hint",children:["Expected charge: ",e.jsxs("strong",{children:[h.quote.expectedCharge.toLocaleString()," shared credits"]})," ","· maximum temporary reservation: ",h.quote.maximumReservation.toLocaleString(),"."]})]}),m==="reuse"&&e.jsx("div",{className:"im-modal-hint",role:"status",children:b}),m==="error"&&e.jsx("div",{className:"im-modal-hint",role:"alert",children:b}),m==="checking"&&e.jsx(bl,{children:"Checking the provider outcome before any further work starts."}),["reserved","submitting","submitted","delivery_staged","published","provider_failed","reconciliation_pending"].includes(m)&&(j?e.jsxs(bl,{children:[yl(m),"."]}):e.jsxs("div",{className:"im-modal-hint",role:"status","aria-live":"polite",children:[m==="published"?e.jsx(rn,{size:16,"aria-hidden":"true"}):null,yl(m),".",m==="published"&&e.jsx(e.Fragment,{children:" Final transcription charge is recorded in credit history; any unused reservation was released."})]})),j&&e.jsx("div",{className:"im-modal-hint",role:"note",children:"Closing this dialog does not cancel the server job. Transcription continues and the wallet is settled from the provider outcome."}),e.jsxs("div",{className:"im-modal-hint",children:["Paid language annotation will not start without a separate authoritative shared-credit confirmation."," ","Cached or reused transcripts cost zero."]}),e.jsxs("div",{className:"im-modal-actions",children:[e.jsx("button",{className:"theater-btn theater-btn--secondary im-modal-cta",onClick:()=>d(!1),children:m==="published"||m==="reuse"?"Done":"Close"}),m==="quoted"&&h&&e.jsxs("button",{className:"theater-btn theater-btn--primary im-modal-cta",onClick:()=>{w()},disabled:!h.quote.affordable,children:[e.jsx(Oi,{size:14}),h.quote.affordable?"Generate subtitles":"Not enough credits"]})]})]})]})}function bl({children:t}){const a=wn();return e.jsxs("div",{className:"theater-panel im-modal-hint",role:"status","aria-live":"polite",style:{display:"flex",alignItems:"center",gap:12},children:[a?e.jsx("span",{"aria-hidden":"true",style:{width:12,height:12,flexShrink:0,borderRadius:"var(--wc-radius-ink)",background:"hsl(var(--module-accent))"}}):e.jsx("span",{"aria-hidden":"true",style:{width:96,height:96,flexShrink:0},children:e.jsx(bs,{image:cs,size:96,duration:1.1,repeatDelay:999})}),e.jsx("span",{children:t})]})}function c_({open:t,onClose:a,children:s}){const n=o.useRef(null),r=o.useRef(a);return r.current=a,o.useEffect(()=>{if(!t)return;const i=document.activeElement instanceof HTMLElement?document.activeElement:null,l=n.current,c=()=>Array.from(l?.querySelectorAll('button:not(:disabled), [href], input
223:not(:disabled), [tabindex]:not([tabindex="-1"])')??[]);c()[0]?.focus();const d=m=>{if(m.key==="Escape"){m.preventDefault(),r.current();return}if(m.key!=="Tab")return;const u=c();if(u.length===0)return;const h=u[0],p=u[u.length-1];m.shiftKey&&document.activeElement===h?(m.preventDefault(),p.focus()):!m.shiftKey&&document.activeElement===p&&(m.preventDefault(),h.focus())};return document.addEventListener("keydown",d),()=>{document.removeEventListener("keydown",d),i?.focus()}},[t]),!t||typeof document>"u"?null:hi.createPortal(e.jsx("div",{className:"wc-root im-logged video-theater",children:e.jsx("div",{className:"im-modal-backdrop",onClick:i=>{i.stopPropagation(),i.target===i.currentTarget&&a()},children:e.jsx("div",{ref:n,className:"im-modal theater-panel",role:"dialog","aria-modal":"true","aria-labelledby":"subtitle-generation-title",onClick:i=>i.stopPropagation(),children:s})})}),document.body)}const d_="shizen.mediaContextDeckPolls.v1",u_=10080*60*1e3,m_=30,Wu=2e3,h_=15e3;function Wl(t){return`${d_}:${t}`}function p_(t){if(!t||typeof t!="object"||Array.isArray(t))return!1;const a=t,s=String(a.mode),n=a.consentVersion;return["simple","image","clip"].includes(s)&&a.skipKnownWords===!0&&["skip","add"].includes(String(a.existingMemoryPolicy))&&Number.isSafeInteger(n)&&(s==="simple"?n===1:Number(n)>=2)}function td(t){if(typeof window>"u"||!t)return[];try{const a=JSON.parse(window.localStorage.getItem(Wl(t))??"[]");if(!Array.isArray(a))return[];const s=Date.now()-u_;return a.filter(n=>{if(!n||typeof n!="object"||Array.isArray(n))return!1;const r=n;return r.version===1&&r.userId===t&&(r.kind==="manga"||r.kind==="video")&&typeof r.id=="string"&&r.id.length>0&&p_(r.selection)&&typeof r.updatedAt=="number"&&Number.isFinite(r.updatedAt)&&r.updatedAt>=s&&typeof r.terminal=="boolean"})}catch{return[]}}function Tp(t,a){if(!(typeof window>"u"||!t))try{a.length===0?window.localStorage.removeItem(Wl(t)):window.localStorage.setItem(Wl(t),JSON.stringify(a))}catch{}}function xl(t){const a=td(t.userId).filter(s=>s.kind!==t.kind||s.id!==t.id);a.push({...t,updatedAt:Date.now()}),Tp(t.userId,a)}function wl(t,a,s){Tp(t,td(t).filter(n=>n.kind!==a||n.id!==s))}function f_({episode:t,intent:a,offerCloudSync:s,onConfirm:n,onCancel:r}){const i=o.useRef(null),[l,c]=o.useState(null),[d,m]=o.useState(null),[u,h]=o.useState(s),[p,g]=o.useState(!1),f=x=>{const v=x.target.files?.[0];v&&(c(v),m(null))},b=x=>{x.preventDefault(),g(!1);const v=x.dataTransfer.files?.[0];if(!v||!v.type.startsWith("video/"))return;c(v),m(null);const j=x.dataTransfer.items?.[0]?.getAsFileSystemHandle?.();j&&j.then(T=>{T?.kind==="file"&&m(T)}).catch(()=>{})},y=()=>{if(!dn){i.current?.click();return}(async()=>{try{const[x]=await window.showOpenFilePicker({types:[{description:"Video",accept:{"video/*":[".mkv",".mp4",".webm",".m4v",".avi",".mov"]}}],multiple:!1,excludeAcceptAllOption:!1});if(!x)return;const v=await x.getFile();c(v),m(x)}catch{}})()};return e.jsx(ze.div,{initial:{opacity:0}
223,animate:{opacity:1},exit:{opacity:0},className:"im-modal-backdrop",onClick:x=>{x.target===x.currentTarget&&r()},children:e.jsxs(ze.div,{initial:{opacity:0,scale:.96,y:16},animate:{opacity:1,scale:1,y:0},exit:{opacity:0,scale:.97,y:12},transition:{duration:.2,ease:[.22,1,.36,1]},className:"im-modal",role:"dialog","aria-modal":"true","aria-labelledby":"video-file-modal-title",children:[e.jsxs("div",{className:"im-modal-head",children:[e.jsxs("div",{className:"left",children:[e.jsx("div",{className:"icon-box",children:e.jsx(hd,{size:18})}),e.jsxs("div",{style:{minWidth:0},children:[e.jsx("h3",{id:"video-file-modal-title",children:a==="condense"?"Create condensed audio":"Select video file"}),e.jsx("p",{children:t.label})]})]}),e.jsx("button",{className:"close",onClick:r,"aria-label":"Close",children:e.jsx(rs,{size:18})})]}),t.video_filename&&e.jsxs("div",{className:"im-modal-hint",children:["Expected file: ",e.jsx("strong",{children:t.video_filename})]}),e.jsxs("div",{className:`im-modal-drop ${p?"is-dragover":""} ${l?"has-file":""}`,onClick:y,onDragOver:x=>{x.preventDefault(),g(!0)},onDragLeave:()=>g(!1),onDrop:b,children:[e.jsx("input",{ref:i,type:"file",accept:"video/*",className:"hidden",style:{display:"none"},onChange:f}),l?e.jsxs(e.Fragment,{children:[e.jsx(hd,{}),e.jsx("p",{className:"filename",children:l.name}),e.jsxs("p",{className:"size",children:[(l.size/(1024*1024)).toFixed(1)," MB"]})]}):e.jsxs(e.Fragment,{children:[e.jsx(lm,{}),e.jsx("p",{children:"Drop a video file here or click to browse"}),e.jsx("p",{className:"formats",children:"MP4 · MKV · AVI · WebM"})]})]}),s&&e.jsxs("div",{className:"im-modal-cloud-row",children:[e.jsxs("div",{className:"im-modal-cloud-copy",children:[e.jsxs("span",{className:"im-modal-cloud-title",children:[e.jsx(Js,{"aria-hidden":"true"}
223)," Store in your cloud library"]}),e.jsx("p",{children:"Play it on your other devices without selecting the file again."})]}),e.jsx($n,{checked:u,onCheckedChange:h,"aria-label":"Store in your cloud library",style:{"--primary":"var(--brand-chat)"}})]}),e.jsxs("div",{className:"im-modal-actions",children:[e.jsx("button",{className:"wc-cta-square wc-cta-square-secondary--iris im-modal-cta",onClick:r,children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--iris im-modal-cta",onClick:()=>l&&n(l,{syncToCloud:u,handle:d}),disabled:!l,children:[a==="condense"?e.jsx(pm,{size:14}):e.jsx(Xr,{size:14}),a==="condense"?"Open condenser":"Play"]})]})]})})}const g_={season:{kind:"idle"},episode:{kind:"idle"}};function y_(t,a){switch(a.type){case"season:toggle":{const s=t.season.kind==="open"&&t.season.id===a.id;return{...t,season:s?{kind:"idle"}:{kind:"open",id:a.id,mode:"options"}}}case"season:set-mode":return t.season.kind!=="open"?t:{...t,season:{...t.season,mode:a.mode}};case"season:close":return{...t,season:{kind:"idle"}};case"episode:toggle":{const s=t.episode.kind==="open"&&t.episode.id===a.id;return{...t,episode:s?{kind:"idle"}:{kind:"open",id:a.id,mode:"options"}}}case"episode:set-mode":return t.episode.kind!=="open"?t:{...t,episode:{...t.episode,mode:a.mode}};case"episode:close":return{...t,episode:{kind:"idle"}};default:return t}}function b_({show:t,onBack:a,onPlayEpisode:s,onDelete:n,onRefresh:r,onUploadComplete:i}){nc();const{session:l,user:c,getAccessToken:d}=ps(),{isDark:m}=Gl(),{refresh:u,isPro:h}=Xn(),{wallet:p,refresh:g}=dm(),{openUpgradeModal:f}=xn(),[b,y]=o.useState(null),[x,v]=o.useState(null),[w,j]=o.useState(null),[T,P]=o.useState(!1),[N,_]=o.useState(new Set),[L,q]=o.useState(null),[O,A]=o.useState(null),[k,J]=o.useState(null),[M,H]=o.useState({}),[ee,Pe]=o.useState({}),[D,de]=o.useState(null),[fe,Me]=o.useState(null),[U,ve]=o.useState(null),[yt,ut]=o.useState(null),[St,je]=o.useState(!1),[lt,Et]=o.useState(new Set),[Ct,aa]=o.useState(null),[vt,Le]=o.useState(t.cover_image_url||null),[jt,Ft]=o.useState(!1),[ct,se]=o.useState(!1),[ft,Oe]=o.useState(t.title),pt=async()=>{const F=ft.trim();if(!F||F===t.title||!l?.access_token){se(!1),Oe(t.title);return}try{await fetch(`${ue()}/api/video/shows/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({title:F})}),ne("immersion_series_updated",{field:"title",kind:"video_show"}),r()}catch(Q){console.warn("[VideoShowDetail] Failed to save title:",Q)}se(!1)},[kt,Ve]=o.useReducer(y_,g_),Be=kt.season,Ke=kt.episode,At=o.useRef(new Map),Jt=o.useRef(!0),ta=o.useRef(null),[zt,K]=o.useState(0);o.useEffect(()=>sc(()=>{K(F=>F+1)}),[]),o.useEffect(()=>{if(t.video_sessions.length>0){const F=[...t.video_sessions].sort((Q,W)=>Q.season_number-W.season_number);_(new Set([F[0].id]))}},[t.id]),o.useEffect(()=>{Jt.current=!0;const F=At.current;return()=>{Jt.current=!1;for(const Q of F.values())clearTimeout(Q);F.clear()}},[]),o.useEffect(()=>{!t.mal_id||!l?.access_token||(P(!0),fetch(`${ue()}/api/jikan/anime/${t.mal_id}`,{headers:{Authorization:`Bearer ${l.access_token}`}}).then(F=>F.json()).then(F=>{F.detail&&j(F.detail)}).catch(()=>{}).finally(()=>P(!1)))},[t.mal_id,l?.access_token]),o.useEffect(()=>{l?.access_token&&fetch(`${ue()}/api/video/shows/coverage`,{headers:{Authorization:`Bearer ${l.access_token}`}}).then(F=>F.ok?F.json():null).then(F=>{if(!F)return;const Q=re=>({vocabTotal:re.vocabTotal,vocabKnown:re.vocabKnown,vocabPct:re.vocabPct,grammarTotal:re.grammarTotal??0,grammarKnown:re.grammarKnown??0,grammarPct:re.grammarPct??0}),W=(F.coverage||[]).find(re=>re.showId===t.id);W&&J(Q(W));const E={};for(const re of F.sessions||[])re.showId===t.id&&(E[re.sessionId]=Q(re));H(E);const G={};for(const re of F.episodes||[])re.showId===t.id&&(G[re.episodeId]=Q(re));Pe(G)}).catch(()=>{})},[t.id,l?.access_token,zt]);const _t=t.video_sessions.reduce((F,Q)=>F+(Q.video_episodes?.length||0),0),qt=t.video_sessions.reduce((F,Q)=>F+(Q.video_episodes?.filter(W=>W.watch_completed).length||0),0),sa=F=>{_(Q=>{const W=new Set(Q);return W.has(F)?W.delete(F):W.add(F),W})},la=F=>{if(F===0)return"";const Q=Math.floor(F/6e4),W=Math.floor(F%6e4/1e3);return`${Q}:${W.toString().padStart(2,"0")}`},Dt=(F,Q)=>{if(pk(F,Jn.getState(F.id),yn.getState(F.id))){s({id:Q.id,title:Q.title,title_jp:t.title_jp,deck_id:Q.deck_id},{...F,cloud_sync_status:"synced"});return}yt!==F.id&&(ut(F.id),fo(F.id).then(W=>{W?ba(W,F,Q,"play"):de({episode:F,season:Q,intent:"play"})}).finally(()=>ut(null)))},ba=(F,Q,W,E,G=null)=>{if(ui(Q.id,F),G&&po(Q.id,G),l?.access_token){const te=F.webkitRelativePath||F.name;fetch(`${ue()}/api/video/episodes/${Q.id}/video-path`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({videoPath:te,videoFilename:F.name})}).catch(()=>{})}const re=sessionStorage.getItem(`video-blob-${Q.id}`);re&&URL.revokeObjectURL(re);const pe=URL.createObjectURL(F);sessionStorage.setItem(`video-blob-${Q.id}`,pe),de(null),s({id:W.id,title:W.title,title_jp:t.title_jp,deck_id:W.deck_id},{...Q,video_filename:F.name},{openCondensedAudio:E==="condense"})},da=(F,Q)=>{yn.configure(d),Jn.clearState(F.id),yn.enqueue({episodeId:F.id,file:Q})},xa=(F,Q)=>{if(!D)return;const{episode:W,season:E,intent:G}=D;if(ui(W.id,F),Q.handle&&po(W.id,Q.handle),Q.syncToCloud&&h&&W.cloud_sync_status!=="synced"){Wh(c?.id??null)?(da(W,F),ba(F,W,E,G,Q.handle)):(de(null),Me({file:F,handle:Q.handle,episode:W,season:E,intent:G}));return}ba(F,W,E,G,Q.handle)},ma=F=>{const Q=fe;Q&&(Me(null),F&&da(Q.episode,Q.file),ba(Q.file,Q.episode,Q.season,Q.intent,Q.handle))},Na=(F,Q)=>{ve(F.id),fo(F.id).then(W=>{W?ba(W,F,Q,"condense"):de({episode:F,season:Q,intent:"condense"})}).finally(()=>ve(null))},Da=async F=>{if(l?.access_token){Et(Q=>new Set(Q).add(F)),y(null);try{const Q=await fetch(`${ue()}/api/video/episodes/${F}/retry-processing`,{method:"POST",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"}});if(!Q.ok){if(Q.status===402){$a()?f("enrichment","quota_exceeded"):y("Not enough shared credits to continue. Your progress is saved."),u();return}const W=await ws(Q);if(W){y(fn(W));return}const E=await Q.json().catch(()=>({}));y(E.error||"Failed to retry episode processing.");return}u(),r()}catch(Q){y(Q instanceof Error?Q.message:"Failed to retry episode processing.")}finally{Et(Q=>{const W=new Set(Q);return W.delete(F),W})}}},wa=async F=>{const Q=F.video_episodes.filter(ml);for(const W of Q)await Da(W.id)}
223,[Wt,ua]=o.useState(!1),ca=async()=>{if(l?.access_token){ua(!0),y(null);try{const F=t.video_sessions?.map(Q=>Q.id)||[];for(const Q of F){const W=await fetch(`${ue()}/api/video/shows/${Q}/process-remaining`,{method:"POST",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"}});if(W.status===402){$a()?f("enrichment","quota_exceeded"):y("Not enough shared credits to continue. Your progress is saved.");break}const E=W.ok?null:await ws(W);if(E){y(fn(E));break}if(!W.ok){const G=await W.json().catch(()=>({}));y(G.error||"Failed to process remaining episodes.");break}}u(),r()}catch(F){y(F instanceof Error?F.message:"Failed to process remaining episodes.")}finally{ua(!1)}}},[ha,za]=o.useState(""),[ea,Ea]=o.useState(!1),pa=async(F,Q)=>{const W=ha.trim();if(!W||W===Q||!l?.access_token){Ve({type:"episode:close"});return}Ea(!0);try{(await fetch(`${ue()}/api/video/episodes/${F}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({label:W})})).ok?(ne("immersion_material_renamed",{kind:"video_episode"}),Ve({type:"episode:close"}),r()):y("Could not rename episode. Please try again.")}catch(E){console.warn("[VideoShowDetail] Failed to rename episode:",E),y("Could not rename episode. Please try again.")}finally{Ea(!1)}},[Ca,Gt]=o.useState(null),[Ba,ka]=o.useState(null),Wa=async F=>{if(l?.access_token){Gt(F),ka(null);try{ne("cloud_sync_action",{action:"remove",source:"show_detail",kind:"video"});const Q=await fetch(`${ue()}/api/video/episodes/${F}/cloud-sync`,{method:"DELETE",headers:{Authorization:`Bearer ${l.access_token}`}});if(Q.ok)Ve({type:"episode:close"}),r();else{const W=await Q.json().catch(()=>({}));ka({id:F,message:W.error||"Could not remove from cloud"})}}catch(Q){console.warn("[VideoShowDetail] Failed to unsync episode:",Q),ka({id:F,message:"Could not remove from cloud"})}finally{Gt(null)}}},es=async F=>{if(l?.access_token){aa(F);try{await fetch(`${ue()}/api/video/episodes/${F}`,{method:"DELETE",headers:{Authorization:`Bearer ${l.access_token}`}}),Hw(F),r()}catch{}finally{aa(null)}}},[Ta,va]=o.useState([]);o.useEffect(()=>{l?.access_token&&fetch(`${ue()}/api/video/shows`,{headers:{Authorization:`Bearer ${l.access_token}`}}).then(F=>F.ok?F.json():null).then(F=>{F?.shows&&va(F.shows.filter(Q=>Q.id!==t.id).map(Q=>({id:Q.id,title:Q.title,sessions:(Q.video_sessions||[]).map(W=>({id:W.id,title:W.title}))})))}).catch(()=>{})},[t.id,l?.access_token]);const ia=async(F,Q)=>{if(l?.access_token)try{await fetch(`${ue()}/api/video/sessions/${F}/move`,{method:"PATCH",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"},body:JSON.stringify({targetShowId:Q})}),r()}catch{}},oe=async(F,Q)=>{if(l?.access_token)try{await fetch(`${ue()}/api/video/episodes/${F}/move`,{method:"PATCH",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"},body:JSON.stringify({targetSessionId:Q})}),r()}catch{}},me=F=>{const Q=At.current.get(F);Q&&clearTimeout(Q),At.current.delete(F)},Ge=(F,Q,W)=>{if(!Jt.current)return;me(F.id);const E=setTimeout(()=>{At.current.delete(F.id),Jt.current&&W()},Q);At.current.set(F.id,E)},gt=(F,Q)=>{const W=yo(Q,F.selection.mode);return W&&v({progress:W,sessionId:F.id,selection:F.selection}),W},I=async(F,Q=0)=>{if(Jt.current){if(Q>m_){const W=F.lastStatus??{status:"processing"};gt(F,W);const E={...F,terminal:!1,lastStatus:W};xl(E),Ge(E,h_,()=>I(E));return}try{const W=await d();if(!Jt.current)return;if(!W)throw new Error("Authentication unavailable");const E=await fetch(`${ue()}/api/video/sessions/${F.id}/deck-status`,{headers:{Authorization:`Bearer ${W}`}});if(!Jt.current)return;const G=Zi(E.status);if(G){me(F.id),wl(F.userId,F.kind,F.id),v({progress:G,sessionId:F.id,selection:F.selection}),q(null);return}if(!E.ok)throw new Error("Failed to check deck status");const re=await E.json();if(!Jt.current)return;const pe=F.lastStatus&&typeof F.lastStatus=="object"?F.lastStatus:null,te=re.mediaContext||!pe?.mediaContext?re:{...re,mediaContext:pe.mediaContext},Fe=gt(F,te),ke={...F,lastStatus:te};
223if(Fe?.terminal){me(F.id),xl({...ke,terminal:!0}),q(null),r();return}if(re.deckId&&(q(null),r()),re.status==="completed"&&F.selection.mode==="simple"){me(F.id),wl(F.userId,F.kind,F.id),v(null),q(null),r();return}if(re.status==="failed"){me(F.id),wl(F.userId,F.kind,F.id),y("Deck creation failed. Please try again."),q(null),r();return}xl({...ke,terminal:!1}),Ge(ke,Wu,()=>I(ke,Q+1))}catch{Ge(F,Wu,()=>I(F,Q+1))}}};o.useEffect(()=>{const F=c?.id,Q=F?`${F}:${t.id}`:null;if(!F||!Q||ta.current===Q)return;for(const G of At.current.values())clearTimeout(G);At.current.clear(),ta.current=Q;const W=new Set(t.video_sessions.map(G=>G.id)),E=td(F).filter(G=>G.kind==="video"&&W.has(G.id)).sort((G,re)=>G.updatedAt-re.updatedAt);for(const G of E){const re=yo(G.lastStatus,G.selection.mode);G.terminal?re&&v({progress:re,sessionId:G.id,selection:G.selection}):(gt(G,G.lastStatus??{status:"processing"}),q(G.id),I(G))}},[t.id,t.video_sessions,c?.id]);const xe=async(F,Q)=>{if(Le(F?Q??vt:null),Ft(!1),!!l?.access_token)try{await fetch(`${ue()}/api/video/shows/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({coverImagePath:F})}),r()}catch{}},Ne=e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"im-detail-badge wc-cta-square-secondary--dusk",children:[t.show_type==="movie"?e.jsx(md,{size:12}):e.jsx(Jr,{size:12}),w?.type||(t.show_type==="movie"?"Movie":"TV Series")]}),w?.score&&e.jsxs("span",{className:"im-detail-badge is-soft wc-cta-square-secondary--dusk",children:[e.jsx(wo,{size:12,className:"fill-yellow-400 text-yellow-400"}),w.score.toFixed(1)]}),w?.status&&e.jsx("span",{className:`im-detail-badge wc-cta-square-secondary--dusk ${w.status==="Currently Airing"?"":"is-muted"}`,children:w.status==="Finished Airing"?"Complete":w.status==="Currently Airing"?"Ongoing":w.status==="Not yet aired"?"Upcoming":w.status})]}),tt=w?.genres&&w.genres.length>0?e.jsx(e.Fragment,{children:w.genres.slice(0,6).map(F=>e.jsx("span",{className:"im-detail-genre wc-cta-square-secondary--dusk",children:F},F))}):null,Mt=e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(Xr,{size:16}),_t," episode",_t!==1?"s":""]}),qt>0&&e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(rn,{size:16}),qt," watched"]}),t.video_sessions.length>1&&e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(Pf,{size:16}),t.video_sessions.length," season",t.video_sessions.length!==1?"s":""]})]}),Ma=k&&k.vocabTotal>0?[{label:"Vocabulary",icon:Gs,pct:k.vocabPct,known:k.vocabKnown,total:k.vocabTotal},...k.grammarTotal>0?[{label:"Grammar",icon:Gs,pct:k.grammarPct,known:k.grammarKnown,total:k.grammarTotal}]:[]]:[],It=ct?e.jsxs("div",{className:"im-detail-title-edit",children:[e.jsx("input",{type:"text",value:ft,onChange:F=>Oe(F.target.value),onKeyDown:F=>{F.key==="Enter"&&pt(),F.key==="Escape"&&(se(!1),Oe(t.title))},autoFocus:!0}),e.jsx("button",{onClick:pt,className:"im-detail-title-edit-btn",style:{opacity:1},"aria-label":"Save title",children:e.jsx(Ys,{className:"w-5 h-5"})}),e.jsx("button",{onClick:()=>{se(!1),Oe(t.title)},className:"im-detail-title-edit-btn",style:{opacity:1},"aria-label":"Cancel",children:e.jsx(rs,{className:"w-5 h-5"})})]}):e.jsxs("div",{className:"im-detail-title-row",children:[e.jsx("h1",{children:t.title}),e.jsx("button",{onClick:()=>{Oe(t.title),se(!0)},className:"im-detail-title-edit-btn","aria-label":"Edit title",children:e.jsx(xr,{className:"w-4 h-4"})})]}),Nt=!vt||jt?e.jsxs("div",{className:"w-48 md:w-56",children:[e.jsx(Qn,{currentCoverUrl:vt,onChange:xe,label:"Show cover (optional)",compact:!0}),jt&&e.jsx("button",{onClick:()=>Ft(!1),className:"wc-cta-square wc-cta-square-quiet--ink im-detail-cover-cancel",children:"Cancel"})]}):e.jsxs("button",{onClick:()=>Ft(!0),className:"wc-cta-square wc-cta-square-quiet--ink im-detail-cover-link",children:[e.jsx(Hn,{size:12}),"Change cover"]}),Lt=O?t.video_sessions.find(F=>F.id===O):null;return Lt&&Lt.video_episodes.length>0&&Lt.video_episodes.every(F=>F.cloud_sync_status==="synced"),e.jsxs("div",{className:"im-detail max-w-6xl mx-auto",children:[!1,e.jsxs(Oa,{children:[D&&e.jsx(f_,{episode:D.episode,intent:D.intent,offerCloudSync:h&&D.episode.cloud_sync_status!=="synced",onConfirm:xa,onCancel:()=>de(null)},D.episode.id),fe&&e.jsx(Uc,{episodeLabel:fe.episode.label,onConfirmed:()=>ma(!0),onCancel:()=>ma(!1)},`attest-${fe.episode.id}`)]}),e.jsx(Sp,{title:t.title,titleJp:t.title_jp??void 0,coverImageUrl:vt||t.cover_image_url||void 0,coverFallback:t.show_type==="movie"?md:Jr,titleSlot:It,badges:Ne,genres:tt,description:w?.synopsis??void 0,isLoading:T,quickStats:Mt,coverageStats:Ma,c
223overSlotBelow:Nt,onBack:a,backLabel:"Back to Library"}),e.jsx(Oa,{mode:"wait",children:St?e.jsxs(ze.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:10},transition:{duration:.25},className:"im-detail-uploader-wrap",children:[e.jsx("button",{onClick:()=>je(!1),className:"wc-cta-square wc-cta-square-quiet--ink im-detail-uploader-close","aria-label":"Close uploader",children:e.jsx(rs,{size:18})}),e.jsx(mi,{prefillShowId:t.id,prefillShowTitle:t.title,onUploadComplete:(F,Q)=>{ne("immersion_episode_uploaded",{show_id:t.id,show_type:t.show_type}),je(!1),r(),i(F,Q)},onUploadError:()=>{}})]},"uploader"):e.jsxs(ze.section,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:10},transition:{duration:.25},className:"im-detail-section",children:[e.jsxs("header",{className:"im-detail-section-head",children:[e.jsx("h2",{children:"Seasons & episodes"}),e.jsxs("div",{className:"im-detail-section-actions",children:[e.jsxs("button",{className:"wc-cta-square wc-cta-square--ink im-detail-action-cta im-detail-show-action",onClick:()=>je(!0),children:[e.jsx(Sr,{size:12})," ",t.show_type==="movie"?"Add movie":"Add episode"]}),e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--maple im-detail-action-cta im-detail-show-action",onClick:()=>n(t.id),children:[e.jsx(Ns,{size:12})," Delete show"]})]})]}),b&&e.jsxs("div",{role:"alert",className:"rounded-[var(--wc-radius-leaf)] px-3 py-2 mb-3 flex items-center justify-between gap-2 text-sm",style:{border:"1px solid var(--wc-border-destructive)",background:"var(--wc-bg-destructive)"},children:[e.jsx("span",{style:{color:"var(--wc-text-destructive)"},children:b}),e.jsx("button",{type:"button",onClick:()=>y(null),className:"opacity-70 hover:opacity-100","aria-label":"Dismiss",children:e.jsx(rs,{size:14})})]}),!1,e.jsx("div",{className:"space-y-3",children:[...t.video_sessions].sort((F,Q)=>F.season_number-Q.season_number).map((F,Q)=>{const W=[...F.video_episodes||[]].sort((pe,te)=>pe.index_in_parent-te.index_in_parent),E=W.some(pe=>pe.source==="extension"),G=W.filter(pe=>pe.source!=="extension"),re=G.length>0&&G.every(pe=>pe.primary_sub_status==="completed"&&Yc(pe));return e.jsxs(a_,{isDark:m,id:F.id,isExpanded:N.has(F.id),onToggle:()=>sa(F.id),icon:e.jsx(Jr,{size:16,style:{color:"hsl(var(--brand-chat) / 0.7)"}}),title:F.season_label||`Season ${F.season_number}`,subtitle:e.jsxs(e.Fragment,{children:[W.length," episode",W.length!==1?"s":"",M[F.id]?.vocabTotal>0&&e.jsxs("span",{className:"ml-2",children:["· ",M[F.id].vocabPct,"% vocab (",M[F.id].vocabKnown,"/",M[F.id].vocabTotal,")"]}),M[F.id]?.grammarTotal>0&&e.jsxs("span",{className:"ml-2",children:["· ",M[F.id].grammarPct,"% grammar (",M[F.id].grammarKnown,"/",M[F.id].grammarTotal,")"]})]}),headerActions:e.jsxs(e.Fragment,{children:[W.some(ml)&&e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-action-cta",onClick:()=>wa(F),children:[e.jsx(vs,{size:12})," Analyze season"]}),W.some(pe=>pe.primary_sub_status==="partial")&&e.jsx("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-action-cta",onClick:ca,disabled:Wt,children:Wt?e.jsxs(e.Fragment,{children:[e.jsx(Sa,{size:12,className:"animate-spin"})," Analyzingâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsx(vs,{size:12})," Finish analyzing"]})}),W.some(hk)&&e.jsxs("span",{className:"im-detail-row-status is-processing",children:[e.jsx(Sa,{className:"animate-spin"})," Analyzingâ¦"]}),!1,F.deck_id&&e.jsxs("span",{className:"im-detail-row-status is-done",children:[e.jsx(rn,{})," Deck"]}),E&&!F.deck_id&&e.jsx("span",{className:"im-detail-row-status",style:{opacity:.75},children:"Extension-annotated episodes canât be added to a vocab deck"}),Ta.length>0&&e.jsx("button",{type:"button",onClick:pe=>{pe.stopPropagation(),Ve({type:"season:toggle",id:F.id})},className:`im-detail-row-menutoggle ${Be.kind==="open"&&Be.id===F.id?"is-active":""}`,"aria-label":"Season options",children:e.jsx(ao,{})})]}),managementPanel:e.jsx(bd,{isOpen:Be.kind==="open"&&Be.id===F.id,className:"border-t border-[hsl(var(--brand-chat)/.1)]",children:e.jsxs(Oa,{mode:"wait",initial:!1,children:[Be.kind==="open"&&Be.id===F.id&&Be.mode==="options"&&e.jsx(ze.div,{initial:{opacity:0,x:-12}
223,animate:{opacity:1,x:0},exit:{opacity:0,x:12},transition:{duration:.15},className:"flex items-center gap-1.5",children:e.jsxs("button",{type:"button",onClick:pe=>{pe.stopPropagation(),Ve({type:"season:set-mode",mode:"moveTo"})},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(so,{})," Move to show"]})},"opts"),Be.kind==="open"&&Be.id===F.id&&Be.mode==="moveTo"&&e.jsxs(ze.div,{initial:{opacity:0,x:12},animate:{opacity:1,x:0},exit:{opacity:0,x:-12},transition:{duration:.15},className:"im-detail-movetolist",children:[e.jsxs("div",{className:"modehead",children:[e.jsx("button",{onClick:pe=>{pe.stopPropagation(),Ve({type:"season:set-mode",mode:"options"})},"aria-label":"Back",children:e.jsx(Za,{})}),e.jsx("span",{children:"Move to show"})]}),Ta.map(pe=>e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),ia(F.id,pe.id),Ve({type:"season:close"})},children:[e.jsx("span",{className:"label",children:pe.title}),e.jsx(As,{})]},pe.id))]},"moveTo")]})}),animationDelay:Q*.05,children:[(!!F.deck_id||re&&M[F.id]?.vocabTotal>0)&&e.jsx(vi,{sourceKind:"video_session",sourceId:F.id,hasDeck:!!F.deck_id,presentation:"row",className:"im-detail-media-coverage",onDeckReady:r}),!1,qa(W,F)]},F.id)})})]},"seasons")})]});function qa(F,Q){return e.jsx("div",{className:"space-y-1",children:F.map(W=>{const E=W.primary_sub_status==="completed"||W.primary_sub_status==="partial",G=W.primary_sub_status==="partial",re=W.primary_sub_status==="processing",pe=W.primary_sub_status==="pending",te=W.primary_sub_status==="error",Fe=lt.has(W.id),ke=ml(W)&&!Fe,Qe=W.source!=="extension"&&!E&&W.cloud_sync_status==="synced";return e.jsxs("div",{children:[e.jsx(Np,{isDark:m,onClick:()=>Dt(W,Q),isActive:Ke.kind==="open"&&Ke.id===W.id,highlighted:W.last_position_ms>0,icon:e.jsx(Xr,{size:18,className:"shrink-0 transition-colors",style:{color:W.last_position_ms>0||E?"hsl(var(--brand-chat) / 0.7)":"var(--ink-soft)"}}),label:e.jsxs("div",{children:[e.jsxs("div",{className:"im-vol-nameline",children:[e.jsx("span",{className:"im-vol-name text-sm opacity-80",children:W.label}),G?e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),ca()},className:"im-vol-hovercta wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",disabled:Wt,children:[e.jsx(vs,{})," Finish analyzing"]}):ke?e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Da(W.id)},className:"im-vol-hovercta wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(vs,{})," Analyze"]}):null]}),e.jsxs("div",{className:"flex items-center gap-2",children:[W.last_position_ms>0&&e.jsxs("span",{className:"text-[10px] flex items-center gap-1",style:{color:"var(--ink-soft)"},children:[e.jsx(Yn,{size:10})," ",la(W.last_position_ms)]}),ee[W.id]?.vocabTotal>0&&e.jsxs("span",{className:"text-[10px] flex items-center gap-1",style:{color:"var(--ink-soft)"},children:[e.jsx(Gs,{size:10})," ",ee[W.id].vocabPct,"% vocab"]}),ee[W.id]?.grammarTotal>0&&e.jsxs("span",{className:"text-[10px] flex items-center gap-1",style:{color:"var(--ink-soft)"},children:["· ",ee[W.id].grammarPct,"% grammar"]}),G&&e.jsx("span",{className:"text-[10px] text-amber-500 flex items-center gap-1",children:"· Partially analyzed"})]})]}),rightControls:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Na(W,Q)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",disabled:!E||U===W.id,title:E?"Generate and download dialogue-only audio":"Available when subtitles are ready",children:[U===W.id?e.jsx(Sa,{className:"animate-spin"}):e.jsx(pm,{}),"Condensed audio"]}),e.jsx(n_,{episode:W,isPro:h}),Qe&&e.jsx("div",{onClick:Y=>Y.stopPropagation(),children:e.jsx(Hu,{episodeId:W.id,episodeLabel:W.label,cloudSynced:!0,availableCredits:p?.available??null,getAccessToken:d,onPublished:r,onWalletChanged:g})}),!1,Qe?null:W.watch_completed?e.jsxs("span",{className:"im-detail-row-status is-done",children:[e.jsx(rn,{})," Done"]}):E?e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--iris im-detail-row-cta",onClick:Y=>{Y.stopPropagation(),Dt(W,Q)},children:[e.jsx(Xr,{})," Play"]}):re||Fe?e.jsxs("span",{className:"im-detail-row-status is-processing",children:[e.jsx(Sa,{className:"animate-spin"})," Analyzingâ¦"]}):pe?e.jsxs("span",{className:"im-detail-row-status is-processing",children:[e.jsx(Sa,{className:"animate-spin"})," Analysis queued"]}):te?e.jsx("span",{className:"im-detail-row-status is-error",children:"Error"}):e.jsx("span",{className:"im-detail-row-status is-pending",children:"Pending"}),Ct===W.id||lt.has(W.id)?e.jsx(Sa,{size:14,className:"animate-spin",style:{color:"rgba(42,53,64,0.45)"}}):e.jsx("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Ve({type:"episode:toggle",id:W.id})},className:`im-detail-row-menutoggle ${Ke.kind==="open"&&Ke.id===W.id?"is-active":""}`,"aria-label":"More options",children:e.jsx(ao,{})})]})}),e.jsx(bd,{isOpen:Ke.kind==="open"&&Ke.id===W.id,children:e.jsxs(Oa,{mode:"wait",initial:!1,children:[Ke.kind==="open"&&Ke.id===W.id&&Ke.mode==="options"&&e.jsxs(ze.div,{initial:{opacity:0,x:-12}
223,animate:{opacity:1,x:0},exit:{opacity:0,x:12},transition:{duration:.15},className:"flex items-center gap-1.5 flex-wrap",children:[W.source!=="extension"&&!E&&!Qe&&e.jsx(Hu,{episodeId:W.id,episodeLabel:W.label,cloudSynced:W.cloud_sync_status==="synced",availableCredits:p?.available??null,getAccessToken:d,onPublished:r,onWalletChanged:g}),ke&&e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Da(W.id),Ve({type:"episode:close"})},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(vs,{})," Analyze"]}),te&&!Fe&&e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Da(W.id),Ve({type:"episode:close"})},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(Hn,{})," Retry analysis"]}),e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),za(W.label),Ve({type:"episode:set-mode",mode:"rename"})},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(xr,{})," Rename"]}),[...t.video_sessions.filter(Ze=>Ze.id!==Q.id).map(Ze=>({id:Ze.id,label:Ze.season_label||Ze.title,showTitle:null})),...Ta.flatMap(Ze=>Ze.sessions.map(Ut=>({id:Ut.id,label:Ut.title,showTitle:Ze.title})))].length===0?null:e.jsxs("button",{type:"button",onClick:Ze=>{Ze.stopPropagation(),Ve({type:"episode:set-mode",mode:"moveTo"})},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(so,{})," Move to season"]}),h&&W.cloud_sync_status==="synced"&&e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),ka(null),Ve({type:"episode:set-mode",mode:"confirmUnsync"})},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(Ws,{})," Remove from cloud"]}),e.jsx("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Ve({type:"episode:set-mode",mode:"confirmDelete"})},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta","aria-label":"Delete",children:e.jsx(Ns,{})})]},"opts"),Ke.kind==="open"&&Ke.id===W.id&&Ke.mode==="rename"&&e.jsxs(ze.div,{initial:{opacity:0,x:12},animate:{opacity:1,x:0},exit:{opacity:0,x:-12},transition:{duration:.15},className:"flex items-center gap-1.5 min-w-0",children:[e.jsx("input",{type:"text",value:ha,onChange:Y=>za(Y.target.value),onClick:Y=>Y.stopPropagation(),onKeyDown:Y=>{Y.stopPropagation(),Y.key==="Enter"&&pa(W.id,W.label),Y.key==="Escape"&&Ve({type:"episode:close"})},className:"im-detail-rename-input","aria-label":"Episode label",autoFocus:!0}),e.jsx("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Ve({type:"episode:close"})},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",disabled:ea,children:"Cancel"}),e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),pa(W.id,W.label)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",disabled:ea,children:[ea?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ys,{})," Save"]})]},"rename"),Ke.kind==="open"&&Ke.id===W.id&&Ke.mode==="confirmUnsync"&&e.jsxs(ze.div,{initial:{opacity:0,x:12},animate:{opacity:1,x:0},exit:{opacity:0,x:-12},transition:{duration:.15},className:"flex items-center gap-2",children:[Ba?.id===W.id?e.jsx("span",{className:"text-[10px]",style:{color:"var(--wc-warn-deep)"},role:"alert",children:Ba.message}):e.jsx("span",{className:"text-[10px]",style:{color:"var(--ink-soft)"},children:"Keeps vocab & progress"}),e.jsx("button",{type:"button",onClick:Y=>{Y.stopPropagation(),ka(null),Ve({type:"episode:set-mode",mode:"options"})},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",disabled:Ca===W.id,children:"Cancel"}),e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Wa(W.id)},className:"wc-cta-square wc-cta-square--maple im-detail-row-cta",disabled:Ca===W.id,children:[Ca===W.id?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ws,{})," Remove from cloud"]})]},"confirmUnsync"),Ke.kind==="open"&&Ke.id===W.id&&Ke.mode==="moveTo"&&e.jsxs(ze.div,{initial:{opacity:0,x:12},animate:{opacity:1,x:0},exit:{opacity:0,x:-12},transition:{duration:.15},className:"im-detail-movetolist",children:[e.jsxs("div",{className:"modehead",children:[e.jsx("button",{onClick:Y=>{Y.stopPropagation(),Ve({type:"episode:set-mode",mode:"options"})},"aria-label":"Back",children:e.jsx(Za,{})}),e.jsx("span",{children:"Move to season"})]}),[...t.video_sessions.filter(Y=>Y.id!==Q.id).map(Y=>({id:Y.id,label:Y.season_label||Y.title,showTitle:null})),...Ta.flatMap(Y=>Y.sessions.map(Ze=>({id:Ze.id,label:Ze.title,showTitle:Y.title})))].map(Y=>e.jsxs("button",{type:"button",onClick:Ze=>{Ze.stopPropagation(),oe(W.id,Y.id),Ve({type:"episode:close"})},children:[e.jsx("span",{className:"label",children:Y.showTitle?`${Y.showTitle} â ${Y.label}`:Y.label}),e.jsx(As,{})]},Y.id))]},"moveTo"),Ke.kind==="open"&&Ke.id===W.id&&Ke.mode==="confirmDelete"&&e.jsxs(ze.div,{initial:{opacity:0,x:12}
223,animate:{opacity:1,x:0},exit:{opacity:0,x:-12},transition:{duration:.15},className:"flex items-center gap-2",children:[e.jsx("span",{className:"im-detail-confirm-strip",children:e.jsx("span",{className:"label",children:"Delete this episode?"})}),e.jsx("button",{type:"button",onClick:Y=>{Y.stopPropagation(),Ve({type:"episode:set-mode",mode:"options"})},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",children:"Cancel"}),e.jsxs("button",{type:"button",onClick:Y=>{Y.stopPropagation(),es(W.id),Ve({type:"episode:close"})},className:"wc-cta-square wc-cta-square--maple im-detail-row-cta",children:[e.jsx(Ns,{})," Delete"]})]},"confirmDelete")]})})]},W.id)})})}}class Wr extends Error{constructor(a,s){super(a),this.status=s,this.name="EpisodePlaybackRequestError"}status}function x_(t,a){return{id:a.id,session_id:t.id??"",session_title:t.title,label:a.label,video_filename:a.video_filename,video_path:a.video_path,last_position_ms:a.last_position_ms??0,subtitle_offset_ms:a.subtitle_offset_ms??0,watch_completed:a.watch_completed??!1,cloud_sync_status:a.cloud_sync_status??null,cloud_size_bytes:a.cloud_size_bytes??null,primary_sub_status:a.primary_sub_status,source:a.source??"web"}}function w_(t){if(!t||typeof t!="object")return!1;const a=t;return typeof a.id=="string"&&typeof a.session_title=="string"&&typeof a.label=="string"&&typeof a.last_position_ms=="number"&&typeof a.subtitle_offset_ms=="number"}async function v_(t,a){const s=await a.getAccessToken();if(!s)throw new Wr("Your session has expired. Sign in again to play this episode.",401);const n=a.fetchImpl??fetch;let r;try{r=await n(`${a.apiBaseUrl??ue()}/api/video/episodes/${encodeURIComponent(t)}/playback`,{headers:{Authorization:`Bearer ${s}`},signal:a.signal})}catch(c){throw c instanceof DOMException&&c.name==="AbortError"?c:new Wr("Could not connect to the video library.",null)}let i=null;try{i=await r.json()}catch{}if(!r.ok){const c=i&&typeof i=="object"&&typeof i.message=="string"?i.message:null;throw new Wr(c??(r.status===404?"Episode not found.":"Unable to load this episode."),r.status)}const l=i&&typeof i=="object"?i.playback:null;if(!w_(l)||l.id!==t)throw new Wr("The server returned an invalid playback record.",r.status);return l}function j_({episodeId:t,enabled:a,seed:s,getAccessToken:n,loadPlayback:r=v_}){const[i,l]=o.useState({status:"idle"}),[c,d]=o.useState(0);o.useEffect(()=>{if(!t){l({status:"idle"});return}if(s?.id===t){l({status:"ready",playback:s});return}if(!a){l({status:"loading"});return}const h=new AbortController;let p=!0;return l({status:"loading"}),r(t,{getAccessToken:n,signal:h.signal}).then(g=>{p&&l({status:"ready",playback:g})}).catch(g=>{if(!(!p||g instanceof DOMException&&g.name==="AbortError")){if(g instanceof Wr&&(g.status===403||g.status===404)){l({status:"not-found",message:"This episode does not exist or is not in your library."});return}l({status:"error",message:g instanceof Error?g.message:"Unable to load this episode."})}}),()=>{p=!1,h.abort()}},[c,a,t,n,r,s]);const m=o.useCallback(()=>d(h=>h+1),[]);return{state:o.useMemo(()=>t&&s?.id===t?{status:"ready",playback:s}:i.status==="ready"&&i.playback.id!==t?{status:"loading"}:i,[t,s,i]),retry:m}}function k_({material:t,title:a,filenameHint:s,detailHint:n,onRestored:r,onClose:i}){const l=To({material:t,onRestored:r});return e.jsx(Mo,{restore:l,title:a,filenameHint:s,detailHint:n,portal:!0,dismissable:!0,onClose:()=>{l.reset(),i()}})}const Li="var(--theater-warning)";function __(t,a){const s=new Set,n=t.map(i=>({volume:i,file:null,via:null,include:!1}));for(const i of n){const l=i.volume.material.original_filename;if(!l)continue;const c=a.find(d=>!s.has(d)&&d.name===l);c&&(s.add(c),i.file=c,i.via="filename",i.include=!0)}for(const i of n){if(i.file)continue;const l=i.volume.material.file_size_bytes;if(l==null||l<=0)continue;const c=a.find(d=>!s.has(d)&&d.size===l);c&&(s.add(c),i.file=c,i.via="size",i.include=!0)}const r=a.filter(i=>!s.has(i));return{matches:n,unmatchedFiles:r}}function S_({volumes:t,onComplete:a,onClose:s}){const n=wn(),r=o.useRef(null),[i,l]=o.useState("pick"),[c,d]=o.use
223State([]),[m,u]=o.useState([]),[h,p]=o.useState(0),[g,f]=o.useState(0),[b,y]=o.useState(""),[x,v]=o.useState(""),[w,j]=o.useState(new Map),T=o.useMemo(()=>{const A=new Set;for(const k of t){const J=Sc(k.material);for(const M of Qm(J).split(",")){const H=M.trim();H&&A.add(H)}}return[...A].join(",")},[t]);o.useEffect(()=>{const A=r.current;return()=>{A&&(A.value="")}},[]);const P=A=>{const k=A.target,J=k.files;if(!J||J.length===0)return;const M=Array.from(J);k.value="";const{matches:H,unmatchedFiles:ee}=__(t,M);d(H),u(ee),l("review")},N=A=>{d(k=>k.map(J=>J.volume.material.id===A&&J.file?{...J,include:!J.include}:J))},_=c.filter(A=>A.include&&A.file),L=async()=>{const A=c.filter(M=>M.include&&M.file);if(A.length===0)return;l("running"),f(A.length);const k=new Map(A.map(M=>[M.volume.material.id,"pending"]));j(new Map(k));const J=M=>{if(M.phase==="reading")v("Reading fileâ¦");else if(M.phase==="extracting"){const H=M.total>0?Math.round(M.current/M.total*100):0;v(`Extracting ${H}%`)}else v(`Saving ${M.current}/${M.total}â¦`)};for(let M=0;M<A.length;M++){const{volume:H,file:ee}=A[M];if(ee){p(M+1),y(H.title),v("Reading fileâ¦");try{const Pe=await Zm(H.material,[ee],J);if(Pe.fingerprintMatch===!1||!Pe.countMatches){k.set(H.material.id,"skipped"),j(new Map(k));continue}await eh(H.material.id,Pe.payload,J),k.set(H.material.id,"restored"),j(new Map(k))}catch(Pe){console.error("[bulk-restore] volume failed:",H.material.id,Pe),k.set(H.material.id,"failed"),j(new Map(k))}}}l("summary"),await a?.()},q=o.useMemo(()=>{let A=0,k=0,J=0;for(const M of w.values())M==="restored"?A++:M==="skipped"?k++:M==="failed"&&J++;return{restored:A,skipped:k,failed:J}},[w]),O=e.jsxs("div",{className:"mobile-viewport-modal-stage fixed inset-0 z-[200] flex items-center justify-center theater-scrim","data-mobile-viewport-surface":"bulk-restore",onClick:i==="running"?void 0:s,children:[e.jsx("input",{ref:r,type:"file",accept:T,multiple:!0,className:"hidden",onChange:P}),e.jsxs("div",{className:"mobile-viewport-modal-panel theater-panel w-full max-w-md p-6",role:"dialog","aria-modal":"true","aria-label":"Restore volumes",onClick:A=>A.stopPropagation(),children:[e.jsxs("div",{className:"theater-rail-eyebrow mb-4",children:[e.jsx("span",{className:"num jp",children:"å·»"}),e.jsx("span",{className:"rule","aria-hidden":"true"}),e.jsx("span",{className:"lbl",children:"Restore volumes"}),e.jsx("span",{className:"jp",children:"復å
"})]}),e.jsx("div",{"data-mobile-viewport-modal-body":!0,children:e.jsx(Oa,{mode:"wait",children:i==="pick"?e.jsxs(ze.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:-12},transition:{duration:.25},className:"space-y-4 text-center",style:{position:"relative",zIndex:1},children:[e.jsx(lm,{className:"w-12 h-12 mx-auto",style:{color:"var(--theater-text-muted)"}}),e.jsxs("p",{className:"text-lg font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:[t.length," volume",t.length===1?"":"s"," missing locally"]}),e.jsx("p",{className:"text-sm",style:{color:"var(--theater-text-soft)"},children:"Select the original files for these volumes. We'll match each file to its volume by name, then restore them one at a time."})]},"pick"):i==="review"?e.jsxs(ze.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:-12},transition:{duration:.25},className:"space-y-4",style:{position:"relative",zIndex:1},children:[e.jsx("p",{className:"text-base font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:"Review matches"}),e.jsx("div",{className:"space-y-1.5 max-h-64 overflow-y-auto pr-1 text-left",style:{scrollbarWidth:"thin"},children:c.map(A=>{const k=A.volume.material.id,J=!!A.file;return e.jsxs("label",{className:"theater-panel flex items-center gap-2.5 p-2.5 text-sm cursor-pointer",style:{cursor:J?"pointer":"default"},children:[e.jsx("input",{type:"checkbox",checked:A.include,disabled:!J,onChange:()=>N(k),className:"shrink-0",style:{accentColor:"hsl(var(--module-accent))"},"aria-label":`Include ${A.volume.title}`}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("p",{className:"truncate",style:{color:"var(--theater-text)"}
223,children:A.volume.title}),J?e.jsxs("p",{className:"truncate text-xs",style:{color:"var(--theater-text-muted)",fontFamily:"'JetBrains Mono', monospace"},children:[A.file.name,A.via==="size"?" (matched by size)":""]}):e.jsxs("p",{className:"text-xs flex items-center gap-1",style:{color:Li},children:[e.jsx(Kf,{className:"w-3 h-3"})," No matching file"]})]}),J&&A.include&&e.jsx(Vo,{className:"w-4 h-4 shrink-0",style:{color:"hsl(var(--module-accent))"}})]},k)})}),m.length>0&&e.jsxs("div",{className:"theater-panel p-2.5 text-xs text-left space-y-1",children:[e.jsxs("p",{className:"flex items-center gap-1.5",style:{color:"var(--theater-text-soft)"},children:[e.jsx(ni,{className:"w-3.5 h-3.5",style:{color:Li}}),m.length," file",m.length===1?"":"s"," not matched to any volume:"]}),m.map(A=>e.jsx("p",{className:"truncate pl-5",style:{color:"var(--theater-text-muted)",fontFamily:"'JetBrains Mono', monospace"},children:A.name},A.name+A.size))]})]},"review"):i==="running"?e.jsxs(ze.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"space-y-4 flex flex-col items-center text-center",style:{position:"relative",zIndex:1},children:[!n&&e.jsx(bs,{image:cs,size:96,duration:1.2,repeatDelay:999}),e.jsxs("p",{className:"text-lg font-semibold serif",style:{fontFamily:"'Shippori Mincho', serif"},children:["Restoring ",h," / ",g]}),e.jsx("p",{className:"text-sm truncate max-w-full px-2",style:{color:"var(--theater-text)"},children:b}),e.jsx("p",{className:"text-xs",style:{color:"var(--theater-text-soft)"},children:x})]},"running"):e.jsxs(ze.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},exit:{opacity:0,y:-12},transition:{duration:.25},className:"space-y-4",style:{position:"relative",zIndex:1},children:[e.jsx(Vo,{className:"w-12 h-12 mx-auto",style:{color:"hsl(var(--module-accent))"}}),e.jsx("p",{className:"text-lg font-semibold serif text-center",style:{fontFamily:"'Shippori Mincho', serif"},children:"Restore complete"}),e.jsxs("div",{className:"theater-panel p-3 text-sm space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Vo,{className:"w-4 h-4 shrink-0",style:{color:"hsl(var(--module-accent))"}}),e.jsxs("span",{style:{color:"var(--theater-text)"},children:[e.jsx("strong",{children:q.restored})," restored"]})]}),q.skipped>0&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(om,{className:"w-4 h-4 shrink-0 mt-0.5",style:{color:Li}}),e.jsxs("span",{style:{color:"var(--theater-text-soft)"},children:[e.jsx("strong",{children:q.skipped})," skipped (file didn't match the original) â restore these individually from the volume row."]})]}),q.failed>0&&e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(ni,{className:"w-4 h-4 shrink-0 mt-0.5",style:{color:Li}}),e.jsxs("span",{style:{color:"var(--theater-text-soft)"},children:[e.jsx("strong",{children:q.failed})," failed â try again individually."]})]})]})]},"summary")})}),i!=="running"&&e.jsx("div",{"data-mobile-viewport-modal-footer":!0,className:"flex shrink-0 flex-wrap gap-2 pt-4",children:i==="pick"?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:s,className:"theater-btn theater-btn--secondary flex-1",children:"Cancel"}),e.jsx("button",{type:"button",onClick:()=>r.current?.click(),className:"theater-btn theater-btn--primary flex-1",children:"Select files"})]}):i==="review"?e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>r.current?.click(),className:"theater-btn theater-btn--secondary flex-1",children:"Choose different files"}),e.jsxs("button",{type:"button",onClick:L,disabled:_.length===0,className:"theater-btn theater-btn--primary flex-1",children:["Restore ",_.length," volume",_.length===1?"":"s"]})]}):e.jsx("button",{type:"button",onClick:s,className:"theater-btn theater-btn--primary flex-1",children:"Done"})}),i!=="running"&&e.jsx("button",{type:"button",onClick:s,className:"absolute top-3 right-3 theater-chrome-icon-btn","aria-label":"Close",children:e.jsx(rs,{className:"w-4 h-4"})})]})]});return typeof document>"u"?O:hi.createPortal(e.jsx("div",{className:"wc-modal-root reader-theater",children:O}),document.body)}const N_=new Intl.Collator(void 0,{numeric:!0,sensitivity:"base"});function Gu(t){const a=cp(t),s=Ro(t);return a!=null&&a>0&&s>0?`${a}/${s} analyzed`:"partially analyzed"}function C_({series:t,onBack:a,onOpenMaterial:s,onDelete:n,onRefresh:r,onUploadComplete:i}){const{session:l}=ps(),{isDark:c}=Gl(),{refresh:d,isPro:m}
223=Xn(),u=dp(),[h,p]=o.useState(null),[g,f]=o.useState(!1),[b,y]=o.useState(!1),[x,v]=o.useState(new Set),[w,j]=o.useState(null),[T,P]=o.useState(null),[N,_]=o.useState(!1),[L,q]=o.useState(!1),[O,A]=o.useState(!1),[k,J]=o.useState(!1),[M,H]=o.useState(null),[ee,Pe]=o.useState(null),[D,de]=o.useState("options"),[fe,Me]=o.useState(""),[U,ve]=o.useState(!1),[yt,ut]=o.useState(null),[St,je]=o.useState(null),[lt,Et]=o.useState(new Set),[Ct,aa]=o.useState(null),[vt,Le]=o.useState(!1),[jt,Ft]=o.useState(!1),[ct,se]=o.useState(t.title),ft=async()=>{const I=ct.trim();if(!I||I===t.title||!l?.access_token){Ft(!1),se(t.title);return}try{await fetch(`${ue()}/api/manga/series/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({title:I})}),ne("immersion_series_updated",{field:"title"}),r()}catch(xe){console.warn("[MangaSeriesDetail] Failed to save title:",xe)}Ft(!1)},[Oe,pt]=o.useState(t.cover_image_url||null),[kt,Ve]=o.useState(!1),[Be,Ke]=o.useState(null),[At,Jt]=o.useState({}),[ta,zt]=o.useState(0);o.useEffect(()=>sc(()=>{zt(I=>I+1)}),[]),o.useEffect(()=>{!t.mal_id||!l?.access_token||(f(!0),fetch(`${ue()}/api/jikan/manga/${t.mal_id}`,{headers:{Authorization:`Bearer ${l.access_token}`}}).then(I=>I.json()).then(I=>{I.detail&&p(I.detail)}).catch(()=>{}).finally(()=>f(!1)))},[t.mal_id,l?.access_token]),o.useEffect(()=>{l?.access_token&&fetch(`${ue()}/api/reading/materials/coverage`,{headers:{Authorization:`Bearer ${l.access_token}`}}).then(I=>I.ok?I.json():null).then(I=>{if(!I)return;const xe=new Set(t.reading_materials.map(Nt=>Nt.id));let Ne=0,tt=0,Mt=0,Ma=0;const It={};for(const Nt of I.coverage||[]){if(!xe.has(Nt.materialId))continue;const Lt={vocabTotal:Nt.vocabTotal??0,vocabKnown:Nt.vocabKnown??0,vocabPct:Number(Nt.vocabPct??0),grammarTotal:Nt.grammarTotal??0,grammarKnown:Nt.grammarKnown??0,grammarPct:Number(Nt.grammarPct??0)};It[Nt.materialId]=Lt,Ne+=Lt.vocabTotal,tt+=Lt.vocabKnown,Mt+=Lt.grammarTotal,Ma+=Lt.grammarKnown}Jt(It),(Ne>0||Mt>0)&&Ke({vocabTotal:Ne,vocabKnown:tt,vocabPct:Ne>0?Math.round(tt/Ne*1e3)/10:0,grammarTotal:Mt,grammarKnown:Ma,grammarPct:Mt>0?Math.round(Ma/Mt*1e3)/10:0})}).catch(()=>{})},[t.id,t.reading_materials,l?.access_token,ta]);const K=[...t.reading_materials].sort((I,xe)=>{const Ne=Number(I.volume),tt=Number(xe.volume);if(Number.isFinite(Ne)&&Number.isFinite(tt)&&Ne!==tt)return Ne-tt;const Mt=N_.compare(I.title,xe.title);return Mt!==0?Mt:new Date(I.created_at).getTime()-new Date(xe.created_at).getTime()});o.useEffect(()=>{Ph(t.reading_materials,m)},[t.reading_materials.map(I=>I.id).join(","),m]);const _t=I=>{Pn(I,m)},qt=async I=>{if(l?.access_token){ut(I),je(null);try{const xe=t.reading_materials.find(tt=>tt.id===I),Ne=await go(I,async()=>l.access_token??null,void 0,{kind:xe?.file_type==="epub"?"epub":"manga",bytes:xe?.cloud_size_bytes??void 0});Ne.ok?(Pe(null),r()):je({id:I,message:Ne.message??"Could not remove from cloud"})}finally{ut(null)}}},sa=m?t.reading_materials.filter(I=>I.cloud_sync_status!=="synced"&&!!I.local_images&&Qi(I.cloud_sync_status,I.total_pages,u.get(I.id)).status==="idle"):[],la=m?t.reading_materials.filter(I=>I.cloud_sync_status==="synced"):[],Dt=()=>{ne("cloud_sync_action",{action:"sync_all",source:"series_detail",kind:"manga",volume_count:sa.length});for(const I of sa)Pn(I,m)},ba=async()=>{if(!l?.access_token)return;ne("cloud_sync_action",{action:"remove_all",source:"series_detail",kind:"manga",volume_count:la.length}),J(!0),H(null);let I=!1;try{for(const xe of la){const Ne=await go(xe.id,async()=>l.access_token??null,void 0,{kind:xe.file_type==="epub"?"epub":"manga",bytes:xe.cloud_size_bytes??void 0});if(!Ne.ok){H(Ne.message??"Could not remove all from cloud");return}I=!0}A(!1)}finally{J(!1),I&&r()}},da=K.reduce((I,xe)=>I+xe.total_pages,0),xa=K.reduce((I,xe)=>I+xe.current_page,0),ma=da>0?Math.round(xa/da*100):0,Na=t.reading_materials.filter(I=>I.local_images).map(I=>`${I.id}:${I.file_type}`).join(",");o.useEffect(()=>{const I=t.reading_materials.filter(Ne=>Ne.local_images);if(I.length===0){Et(new Set);return}let xe=!1;return Promise.all(I.map(async Ne=>
223{const tt=Ne.file_type==="epub"?await li(Ne.id).catch(()=>!1):await oi(Ne.id).catch(()=>!1);return{id:Ne.id,missing:!tt}})).then(Ne=>{xe||Et(new Set(Ne.filter(tt=>tt.missing).map(tt=>tt.id)))}),()=>{xe=!0}},[Na]);const Da=I=>({id:I.id,content_type:I.content_type??null,file_type:I.file_type??null,total_pages:I.total_pages??null,content_sha256:I.content_sha256??null,original_filename:I.original_filename??null,file_size_bytes:I.file_size_bytes??null}),wa=I=>{Et(xe=>{const Ne=new Set(xe);return Ne.delete(I),Ne})},Wt=async()=>{const I=t.reading_materials.filter(Ne=>Ne.local_images),xe=await Promise.all(I.map(async Ne=>{const tt=Ne.file_type==="epub"?await li(Ne.id).catch(()=>!1):await oi(Ne.id).catch(()=>!1);return{id:Ne.id,missing:!tt}}));Et(new Set(xe.filter(Ne=>Ne.missing).map(Ne=>Ne.id)))},ua=K.filter(I=>lt.has(I.id)),ca=Ct?K.find(I=>I.id===Ct)??null:null,ha=async I=>{if(l?.access_token){v(xe=>new Set(xe).add(I));try{const xe=await fetch(`${ue()}/api/reading/materials/${I}/retry`,{method:"POST",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"}});if(xe.status===402){j("Not enough shared credits to start processing."),d();return}if(!xe.ok){const Ne=await ws(xe);if(Ne){j(fn(Ne));return}const tt=await El(xe,"Could not start processing. Please try again.");j(tt.message);return}r()}catch(xe){console.warn("[MangaSeriesDetail] Failed to process volume:",xe),j("Could not start processing. Please try again.")}finally{v(xe=>{const Ne=new Set(xe);return Ne.delete(I),Ne})}}},za=async()=>{j(null);const I=K.filter(xe=>Ur(xe)==="analyze");for(const xe of I)await ha(xe.id)},ea=async I=>{if(l?.access_token){v(xe=>new Set(xe).add(I));try{const xe=await fetch(`${ue()}/api/reading/materials/${I}/process-remaining`,{method:"POST",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"}});if(xe.status===402){j("Not enough shared credits to continue. Your analyzed pages are saved."),d();return}if(!xe.ok){const Ne=await ws(xe);if(Ne)j(fn(Ne));else{const tt=await xe.json().catch(()=>({}));console.warn("Process remaining failed:",tt.error)}}d(),r()}catch(xe){console.warn("[MangaSeriesDetail] Failed to process remaining:",xe),j("Could not start processing. Please try again.")}finally{v(xe=>{const Ne=new Set(xe);return Ne.delete(I),Ne})}}},Ea=async I=>{const xe=fe.trim(),Ne=t.reading_materials.find(tt=>tt.id===I)?.title??"";if(!xe||xe===Ne||!l?.access_token){Pe(null);return}ve(!0);try{(await fetch(`${ue()}/api/reading/materials/${I}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({title:xe})})).ok?(ne("immersion_material_renamed",{kind:"manga_volume"}),Pe(null),r()):j("Could not rename volume. Please try again.")}catch(tt){console.warn("[MangaSeriesDetail] Failed to rename volume:",tt),j("Could not rename volume. Please try again.")}finally{ve(!1)}},pa=async I=>{if(l?.access_token){P(I);try{await fetch(`${ue()}/api/reading/materials/${I}`,{method:"DELETE",headers:{Authorization:`Bearer ${l.access_token}`}}),r()}catch(xe){console.warn("[MangaSeriesDetail] Failed to delete volume:",xe),j("Could not delete volume. Please try again.")}finally{P(null)}}},[Ca,Gt]=o.useState([]),Ba=t.reading_materials[0]?.content_type;o.useEffect(()=>{l?.access_token&&fetch(`${ue()}/api/manga/series`,{headers:{Authorization:`Bearer ${l.access_token}`}}).then(I=>I.ok?I.json():null).then(I=>{I?.series&&Gt(I.series.filter(xe=>{if(xe.id===t.id)return!1;const Ne=xe.reading_materials?.[0]?.content_type;return!Ba||!Ne?!0:Ne===Ba}).map(xe=>({id:xe.id,title:xe.title})))}).catch(I=>{console.warn("[MangaSeriesDetail] Failed to load other series:",I)})},[t.id,Ba,l?.access_token]);const ka=async(I,xe)=>{if(l?.access_token)try{const Ne=await fetch(`${ue()}/api/manga/series/${xe}/materials/${I}`,{method:"PATCH",headers:{Authorization:`Bearer ${l.access_token}`,"Content-Type":"application/json"}});Ne.ok?ne("immersion_material_moved_to_series"):console.error("Move to series failed:",await Ne.text()),r()}catch(Ne){console.error("Move to series error:",Ne)}},Wa=async I=>{if(l?.access_token)try{await fetch(`${ue()}/api/manga/series/${t.id}/materials/${I}`,{method:"DELETE",headers:{Authorization:`Bearer ${l.access_token}`}}),r()}catch(xe){console.warn("[MangaSeriesDetail] Failed to remove from series:",xe)}},es=async(I,xe)=>{if(pt(I?xe??Oe:null),Ve(!1),!!l?.access_token)try{await fetch(`${ue()}/api/manga/series/${t.id}`,{method:"PATCH",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l.access_token}`},body:JSON.stringify({coverImagePath:I})}),I&&ne("immersion_series_updated",{field:"cover"}),r()}catch(Ne){console.warn("[MangaSeriesDetail] Failed to update cover:",Ne)}},Ta=K.some(I=>Ur(I)==="analyze"),va=e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"im-detail-badge",children:[e.jsx(ss,{size:12}),h?.type||"Manga"]}),h?.score&&e.jsxs("span",{className:"im-detail-badge is-soft",children:[e.jsx(wo,{size:12,className:"fill-yellow-400 text-yellow-400"}),h.score.toFixed(1)]}),h?.status&&e.jsx("span",{className:`im-detail-badge ${h.status==="Publishing"?"":"is-muted"}`,children:h.status==="Finished"?"Complete":h.status==="Publishing"?"Ongoing":h.status==="On Hiatus"?"Hiatus":h.status==="Discontinued"?"Discontinued":h.status==="Not yet published"?"Upcoming":h.status})]}),ia=h?.genres&&h.genres.length>0?e.jsx(e.Fragment,{children:h.genres.slice(0,6).map(I=>e.jsx("span",{className:"im-detail-genre",children:I},I))}):null,oe=e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(ss,{size:16}),K.length," volume",K.length!==1?"s":""]}),e.jsxs("span",{className:"flex items-center gap-1.5",children:[da," page",da!==1?"s":""]}),xa>0&&e.jsxs("span",{className:"flex items-center gap-1.5",children:[e.jsx(rn,{size:16}),xa," read (",ma,"%)"]})]}),me=Be&&Be.vocabTotal>0?[{label:"Vocabulary",icon:Gs,pct:Be.vocabPct,known:Be.vocabKnown,total:Be.vocabTotal},...Be.grammarTotal>0?[{label:"Grammar",icon:Rn,pct:Be.grammarPct,known:Be.grammarKnown,total:Be.grammarTotal}]:[]]:[],Ge=jt?e.jsxs("div",{className:"im-detail-title-edit",children:[e.jsx("input",{type:"text",value:ct,onChange:I=>se(I.target.value),onKeyDown:I=>{I.key==="Enter"&&ft(),I.key==="Escape"&&(Ft(!1),se(t.title))},autoFocus:!0}),e.jsx("button",{onClick:ft,className:"im-detail-title-edit-btn",style:{opacity:1},"aria-label":"Save title",children:e.jsx(Ys,{className:"w-5 h-5"})}),e.jsx("button",{onClick:()=>{Ft(!1),se(t.title)},className:"im-detail-title-edit-btn",style:{opacity:1},"aria-label":"Cancel",children:e.jsx(rs,{className:"w-5 h-5"})})]}):e.jsxs("div",{className:"im-detail-title-row",children:[e.jsx("h1",{children:t.title}),e.jsx("button",{onClick:()=>{se(t.title),Ft(!0)},className:"im-detail-title-edit-btn","aria-label":"Edit title",children:e.jsx(xr,{className:"w-4 h-4"})})]}),gt=!Oe||kt?e.jsxs("div",{className:"w-48 md:w-56",children:[e.jsx(Qn,{currentCoverUrl:Oe,onChange:es,label:"Series cover (optional)",compact:!0}),kt&&e.jsx("button",{onClick:()=>Ve(!1),className:"wc-cta-square wc-cta-square-quiet--ink im-detail-cover-cancel",children:"Cancel"})]}):e.jsxs("button",{onClick:()=>Ve(!0),className:"wc-cta-square wc-cta-square-quiet--ink im-detail-cover-link",children:[e.jsx(Hn,{size:12}),"Change cover"]});return e.jsxs("div",{className:"im-detail max-w-6xl mx-auto",children:[e.jsx(Sp,{title:t.title,titleJp:t.title_jp??void 0,coverImageUrl:Oe||t.cover_image_url||void 0,titleSlot:Ge,badges:va,genres:ia,description:h?.synopsis??void 0,isLoading:g,quickStats:oe,coverageStats:me,coverSlotBelow:gt,onBack:a,backLabel:"Back to Library"}),e.jsx(Oa,{mode:"wait",children:b?e.jsxs(ze.div,{initial:{opacity:0,y:10}
223,animate:{opacity:1,y:0},exit:{opacity:0,y:10},transition:{duration:.25},className:"im-detail-uploader-wrap",children:[e.jsx("button",{onClick:()=>y(!1),className:"wc-cta-square wc-cta-square-quiet--ink im-detail-uploader-close","aria-label":"Close uploader",children:e.jsx(rs,{size:18})}),e.jsx(mi,{prefillMangaSeriesId:t.id,prefillMangaSeriesTitle:t.title,onUploadComplete:(I,xe)=>{y(!1),r(),i(I,xe)},onUploadError:()=>{}})]},"uploader"):e.jsxs(ze.section,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:10},transition:{duration:.25},className:"im-detail-section",children:[e.jsxs("header",{className:"im-detail-section-head",children:[!(L||N||O)&&e.jsx("h2",{children:"Volumes"}),e.jsx(Oa,{mode:"wait",initial:!1,children:N?e.jsxs(ze.div,{initial:{opacity:0,x:12},animate:{opacity:1,x:0},exit:{opacity:0,x:12},transition:{duration:.15},className:"im-detail-confirm-strip",children:[e.jsx("span",{className:"label",children:"Delete this series?"}),e.jsx("button",{className:"wc-cta-square wc-cta-square-quiet--ink im-detail-action-cta",onClick:()=>_(!1),children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--maple im-detail-action-cta",onClick:()=>{_(!1),n(t.id)},children:[e.jsx(Ns,{size:12})," Delete"]})]},"confirm-delete"):O?e.jsxs(ze.div,{initial:{opacity:0,x:12},animate:{opacity:1,x:0},exit:{opacity:0,x:12},transition:{duration:.15},className:"im-detail-confirm-strip",children:[M?e.jsx("span",{className:"label",style:{color:"var(--wc-warn-deep)"},role:"alert",children:M}):e.jsxs("span",{className:"label",children:["Remove ",la.length," from cloud?"]}),e.jsx("button",{className:"wc-cta-square wc-cta-square-quiet--ink im-detail-action-cta",onClick:()=>{A(!1),H(null)},disabled:k,children:"Cancel"}),e.jsxs("button",{className:"wc-cta-square wc-cta-square--maple im-detail-action-cta",onClick:()=>{ba()},disabled:k,children:[k?e.jsx(Sa,{size:12,className:"animate-spin"}):e.jsx(Ws,{size:12})," Remove all"]})]},"confirm-unsync-all"):e.jsx(ze.div,{initial:{opacity:0,x:-12},animate:{opacity:1,x:0},exit:{opacity:0,x:-12},transition:{duration:.15},className:"im-detail-section-actions",children:L?e.jsxs(ze.div,{initial:{opacity:0,x:10},animate:{opacity:1,x:0},transition:{duration:.18,ease:[.22,1,.36,1]},className:"im-detail-actions-cluster im-detail-actions-menu",children:[e.jsx("button",{type:"button",className:"im-detail-row-menutoggle",onClick:()=>q(!1),"aria-label":"Back",children:e.jsx(Za,{size:14})}),ua.length>=2&&e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-action-cta",onClick:()=>{Le(!0),q(!1)},children:[e.jsx(ii,{size:12})," Restore ",ua.length,e.jsx("span",{className:"im-lbl-tail",children:" volumesâ¦"})]}),Ta&&e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-action-cta",onClick:()=>{za(),q(!1)},children:[e.jsx(vs,{size:12})," Analyze all"]}),sa.length>0&&e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-action-cta",onClick:()=>{Dt(),q(!1)},children:[e.jsx(Js,{size:12})," Sync all",e.jsx("span",{className:"im-lbl-tail",children:" volumes"})]}),la.length>0&&e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-action-cta",onClick:()=>{A(!0),H(null),q(!1)},children:[e.jsx(Ws,{size:12})," Remove all",e.jsx("span",{className:"im-lbl-tail",children:" from cloud"})]}),e.jsxs("button",{className:"wc-cta-square wc-cta-square-secondary--maple im-detail-action-cta",onClick:()=>{_(!0),q(!1)},children:[e.jsx(Ns,{size:12})," Delete",e.jsx("span",{className:"im-lbl-tail",children:" series"})]})]},"unfolded"):e.jsxs(ze.div,{initial:{opacity:0,x:-6},animate:{opacity:1,x:0},transition:{duration:.18,ease:[.22,1,.36,1]},className:"im-detail-actions-cluster",children:[e.jsxs("button",{className:"wc-cta-square wc-cta-square--ink im-detail-action-cta",onClick:()=>y(!0),children:[e.jsx(Sr,{size:12})," Add volume"]}),e.jsx("button",{type:"button",className:"im-detail-row-menutoggle",onClick:()=>q(!0),"aria-label":"More series actions",children:e.jsx(ao,{})})]},"collapsed")},"actions")})]}),w&&e.jsxs("div",{role:"alert",className:"rounded-[var(--wc-radius-leaf)] px-3 py-2 mb-3 flex items-start justify-between gap-3 text-sm",style:{border:"1px solid var(--wc-border-destructive)",background:"var(--wc-bg-destructive)"},children:[e.jsx("span",{className:"leading-snug",style:{color:"var(--wc-text-destructive)"},children:w}),e.jsx("button",{type:"button",onClick:()=>j(null),className:"opacity-70 hover:opacity-100 flex-shrink-0","aria-label":"Dismiss",children:e.jsx(rs,{className:"w-4 h-4"})})]}),K.length===0?e.jsxs("div",{className:"im-detail-empty",children:[e.jsx(ss,{}),e.jsx("p",{children:"No volumes yet. Upload manga to add to this series."})]}):e.jsx("div",{className:"space-y-1",children:K.map((I,xe)=>{const Ne=I.processing_status==="completed",tt=I.processing_status==="processing",Mt=I.processing_status==="error",Ma=I.current_page>0,It=I.total_pages>0?Math.round(I.current_page/I.total_pages*100):0,Nt=At[I.id],Lt=ee===I.id,qa=I.cloud_sync_status==="synced",F=!qa&<.has(I.id),Q=Qi(I.cloud_sync_status,I.total_pages,u.get(I.id)),W=m&&!qa&&!!I.local_images&&Q.status==="idle",E=x.has(I.id),G=Ur(I)==="analyze"&&!tt&&!E,re=Gc(I),pe=re&&!E;return e.jsxs("div",{children:[e.jsx(Np,{isDark:c,onClick:()=>{F?aa(I.id):s(I.id)},isActive:Lt,highlighted:Ma,animationDelay:xe*.05,icon:e.jsx(ss,{size:18,className:"shrink-0 transition-colors",style:{color:Ma||Ne?"hsl(var(--brand-chat) / 0.7)":"hsl(0 0% 0% / 0.25)"}}),label:e.jsxs("div",{children:[e.jsxs("div",{className:"im-vol-nameline",children:[e.jsx("span",{className:"im-vol-name text-sm opacity-80",children:I.title}),!Lt&&e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),Me(I.title),Pe(I.id),de("rename")},className:"im-vol-rename-btn","aria-label":"Rename volume",children:e.jsx(xr,{})}),!F&&(pe||G)&&e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),pe?ea(I.id):ha(I.id)},className:"im-vol-hovercta wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(vs,{})," ",pe?"Finish analyzing":"Analyze"]})]}),e.jsxs("div",{className:"hidden sm:flex items-center gap-2 flex-wrap",children:[I.total_pages>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground",children:[I.current_page,"/",I.total_pages," pages"]}),Ma&&e.jsxs("span",{className:"text-[10px] text-muted-foreground",children:["(",It,"%)"]}),Nt&&Nt.vocabTotal>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground flex items-center gap-1",children:[e.jsx(Gs,{size:10})," ",Nt.vocabPct,"% vocab"]}),Nt&&Nt.grammarTotal>0&&e.jsxs("span",{className:"text-[10px] text-muted-foreground flex items-center gap-1",children:["· ",Nt.grammarPct,"% grammar"]}),re&&e.jsxs("span",{className:"text-[10px] text-amber-500 flex items-center gap-1",children:["· ",Gu(I)," (shared credits ran out)"]})]})]}),rightControls:Lt?D==="moveTo"?e.jsxs(ze.div,{initial:{opacity:0,x:8}
223,animate:{opacity:1,x:0},exit:{opacity:0,x:-8},transition:{duration:.15},className:"flex items-center gap-1.5 min-w-0",children:[e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),de("options")},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",children:"Back"}),e.jsx(Qu,{size:10,className:"text-muted-foreground/40 shrink-0 -mx-0.5"}),e.jsx("div",{className:"im-detail-movetoscroll",children:Ca.map(te=>e.jsxs("button",{type:"button",onClick:Fe=>{Fe.stopPropagation(),ka(I.id,te.id),Pe(null)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[te.title,e.jsx(As,{size:9})]},te.id))})]},"moveTo"):D==="confirmDelete"?e.jsxs(ze.div,{initial:{opacity:0,x:8},animate:{opacity:1,x:0},exit:{opacity:0,x:-8},transition:{duration:.15},className:"flex items-center gap-1.5",children:[e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),de("options")},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",children:"Cancel"}),e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),pa(I.id),Pe(null)},className:"wc-cta-square wc-cta-square--maple im-detail-row-cta",children:[e.jsx(Ns,{})," Delete"]})]},"confirmDelete"):D==="confirmUnsync"?e.jsxs(ze.div,{initial:{opacity:0,x:8},animate:{opacity:1,x:0},exit:{opacity:0,x:-8},transition:{duration:.15},className:"flex items-center gap-1.5",children:[St?.id===I.id?e.jsx("span",{className:"text-[10px] hidden sm:inline",style:{color:"var(--wc-warn-deep)"},role:"alert",children:St.message}):e.jsx("span",{className:"text-[10px] text-muted-foreground hidden sm:inline",children:"Keeps vocab & progress"}),e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),de("options"),je(null)},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",disabled:yt===I.id,children:"Cancel"}),e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),qt(I.id)},className:"wc-cta-square wc-cta-square--maple im-detail-row-cta",disabled:yt===I.id,children:[yt===I.id?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ws,{})," Remove from cloud"]})]},"confirmUnsync"):D==="rename"?e.jsxs(ze.div,{initial:{opacity:0,x:8},animate:{opacity:1,x:0},exit:{opacity:0,x:-8},transition:{duration:.15},className:"flex items-center gap-1.5 min-w-0",children:[e.jsx("input",{type:"text",value:fe,onChange:te=>Me(te.target.value),onClick:te=>te.stopPropagation(),onKeyDown:te=>{te.stopPropagation(),te.key==="Enter"&&Ea(I.id),te.key==="Escape"&&Pe(null)},className:"im-detail-rename-input","aria-label":"Volume title",autoFocus:!0}),e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),Pe(null)},className:"wc-cta-square wc-cta-square-quiet--ink im-detail-row-cta",disabled:U,children:"Cancel"}),e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),Ea(I.id)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",disabled:U,children:[U?e.jsx(Sa,{className:"animate-spin"}):e.jsx(Ys,{})," Save"]})]},"rename"):e.jsxs(ze.div,{initial:{opacity:0,x:8},animate:{opacity:1,x:0},exit:{opacity:0,x:-8},transition:{duration:.15},className:"im-detail-row-manage flex items-center gap-1 flex-wrap flex-1 min-w-0",children:[e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),Pe(null)},className:"im-detail-row-menutoggle","aria-label":"Back",children:e.jsx(Za,{size:12})}),Ur(I)==="analyze"&&!tt&&e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),ha(I.id),Pe(null)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(vs,{})," Analyze"]}),I.enriched_page_limit!=null&&I.enriched_page_limit<I.total_pages&&!tt&&e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),ea(I.id),Pe(null)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(vs,{})," Finish analyzing"]}),Ca.length>0&&e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),de("moveTo")},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(so,{})," Move"]}),e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),Wa(I.id),Pe(null)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(Xf,{})," Remove"]}),W&&e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),_t(I),Pe(null)},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(Js,{})," Sync"]}),m&&qa&&e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),de("confirmUnsync")},className:"wc-cta-square wc-cta-square-secondary--dusk im-detail-row-cta",children:[e.jsx(Ws,{})," Remove from cloud"]}),e.jsxs("button",{type:"button",onClick:te=>{te.stopPropagation(),de("confirmDelete")},className:"wc-cta-square wc-cta-square-secondary--maple im-detail-row-cta",children:[e.jsx(Ns,{})," Delete"]})]},"manage"):e.jsxs(ze.div,{initial:{opacity:0,x:-8}
223,animate:{opacity:1,x:0},exit:{opacity:0,x:8},transition:{duration:.15},className:"flex items-center gap-2",children:[F?e.jsxs("span",{className:"im-detail-row-status",style:{color:"var(--ink-soft)"},children:[e.jsx(ii,{})," Re-import here"]}):It===100?e.jsxs("span",{className:"im-detail-row-status is-done",children:[e.jsx(rn,{})," Done"]}):Ne?e.jsxs("button",{type:"button",className:"wc-cta-square wc-cta-square--ink im-detail-row-cta",onClick:()=>s(I.id),children:[e.jsx(ss,{})," Read"]}):tt?e.jsxs("span",{className:"im-detail-row-status is-processing",children:[e.jsx(Sa,{className:"animate-spin"})," Processing"]}):Mt?e.jsxs("span",{className:"im-detail-row-status is-error",children:[e.jsx(Qa,{})," Error"]}):e.jsx("span",{className:"im-detail-row-status is-pending",children:"Pending"}),!F&&e.jsx(lp,{variant:"inline",isPro:m,retryUnavailable:lt.has(I.id),state:Qi(I.cloud_sync_status,I.total_pages,u.get(I.id)),onRetry:()=>_t(I)}),T===I.id||x.has(I.id)?e.jsx(Sa,{size:14,className:"animate-spin text-muted-foreground/40"}):e.jsx("button",{type:"button",onClick:te=>{te.stopPropagation(),Pe(I.id),de("options")},className:"im-detail-row-menutoggle","aria-label":"More options",children:e.jsx(ao,{})})]},"status")}),(!!I.deck_id||I.processing_status==="completed"&&I.enrichment_status==="completed")&&e.jsx(vi,{sourceKind:"reading_material",sourceId:I.id,hasDeck:!!I.deck_id,presentation:"row",className:"im-detail-media-coverage",onDeckReady:r}),!1,!Lt&&e.jsxs("div",{className:"flex sm:hidden items-center gap-x-2 gap-y-0.5 flex-wrap mt-0.5 pl-7 text-[10px] text-muted-foreground",children:[I.total_pages>0&&e.jsxs("span",{children:[I.current_page,"/",I.total_pages," pages"]}),Ma&&e.jsxs("span",{children:["(",It,"%)"]}),Nt&&Nt.vocabTotal>0&&e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx(Gs,{size:10})," ",Nt.vocabPct,"% vocab"]}),Nt&&Nt.grammarTotal>0&&e.jsxs("span",{className:"flex items-center gap-1",children:["· ",Nt.grammarPct,"% grammar"]}),re&&e.jsxs("span",{className:"text-amber-500 flex items-center gap-1",children:["· ",Gu(I)," (shared credits ran out)"]})]})]},I.id)})})]},"volumes")}),ca&&e.jsx(k_,{material:Da(ca),title:ca.content_type==="novel"?"Local file missing":"Local images missing",filenameHint:ca.original_filename??ca.title,detailHint:ca.content_type==="novel"?ca.file_size_bytes!=null?`${(ca.file_size_bytes/(1024*1024)).toFixed(1)} MB`:null:ca.total_pages>0?`${ca.total_pages} pages`:null,onRestored:()=>{wa(ca.id),aa(null)},onClose:()=>aa(null)}),vt&&e.jsx(S_,{volumes:ua.map(I=>({material:Da(I),title:I.title})),onComplete:Wt,onClose:()=>Le(!1)})]})}const E_=` 224attribute vec2 a_position; 225varying vec2 v_uv; 226void main() { 227 v_uv = a_position * 0.5 + 0.5; 228 gl_Position = vec4(a_position, 0.0, 1.0); 229} 230`,T_=(t,a)=>` 231#extension GL_EXT_shader_texture_lod : enable 232precision highp float; 233 234varying vec2 v_uv; 235uniform vec3 iResolution; 236uniform float iTime; 237uniform vec4 iMouse; 238uniform sampler2D iChannel0; 239 240${t?"#define HAS_HEART":""} 241${a?"#define ENHANCE_MOBILE_MOTION":""} 242#define S(a, b, t) smoothstep(a, b, t) 243 244vec3 N13(float p) { 245 vec3 p3 = fract(vec3(p) * vec3(.1031, .11369, .13787)); 246 p3 += dot(p3, p3.yzx + 19.19); 247 return fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x)); 248} 249 250float N(float t) { 251 return fract(sin(t*12345.564)*7658.76); 252} 253 254float Saw(float b, float t) { 255 return S(0., b, t) * S(1., b, t); 256} 257 258vec2 DropLayer2(vec2 uv, float t) { 259 vec2 UV = uv; 260 uv.y += t*0.75; 261 vec2 a = vec2(6., 1.); 262 vec2 grid = a*2.; 263 vec2 id = floor(uv*grid); 264 265 float colShift = N(id.x); 266 uv.y += colShift; 267 268 id = floor(uv*grid); 269 vec3 n = N13(id.x*35.2 + id.y*2376.1); 270 vec2 st = fract(uv*grid) - vec2(.5, 0); 271 272 // Population gate â only the top ~6.25% of cells (n.y > .9375) produce a 273 // drop. Cuts the count, not the opacity. Uses n.y so x-offset (n.x) and 274 // timing (n.z) keep their natural distribution across the surviving drops. 275#ifdef ENHANCE_MOBILE_MOTION 276 float keep = step(.875, n.y); 277#else 278 float keep = step(.9375, n.y); 279#endif 280 281 float x = n.x - .5; 282 float y = UV.y*20.; 283 float wiggle = sin(y + sin(y)); 284 x += wiggle*(.5 - abs(x))*(n.z - .5); 285 x *= .7; 286 float ti = fract(t + n.z); 287 y = (Saw(.85, ti) - .5)*.9 + .5; 288 vec2 p = vec2(x, y); 289 290 float d = length((st - p)*a.yx); 291 float mainDrop = S(.4, .0, d); 292 293 float r = sqrt(S(1., y, st.y)); 294 float cd = abs(st.x - x); 295 float trail = S(.23*r, .15*r*r, cd); 296 float trailFront = S(-.02, .02, st.y - y); 297 trail *= trailFront*r*r; 298 299 y = UV.y; 300 float trail2 = S(.2*r, .0, cd); 301 float droplets = max(0., (sin(y*(1. - y)*120.) - st.y))*trail2*trailFront*n.z; 302 y = fract(y*10.) + (st.y - .5); 303 float dd = length(st - vec2(x, y)); 304 droplets = S(.3, 0., dd); 305 float m = mainDrop + droplets*r*trailFront; 306 307 return vec2(m, trail) * keep; 308} 309 310float StaticDrops(vec2 uv, float t) { 311 uv *= 40.; 312 vec2 id = floor(uv); 313 uv = fract(uv) - .5; 314 vec3 n = N13(id.x*107.45 + id.y*3543.654); 315 // Population gate â independent hash so position/timing distributions are 316 // untouched. Only the top ~6.25% of the 40Ã40 cells produce a static drop. 317 float keep = step(.9375, N(id.x*0.731 + id.y*2.917)); 318 vec2 p = (n.xy - .5)*.7; 319 float d = length(uv - p); 320 float fade = Saw(.025, fract(t + n.z)); 321 float c = S(.3, 0., d)*fract(n.z*10.)*fade; 322 return c * keep; 323} 324 325vec2 Drops(vec2 uv, float t, float l0, float l1, float l2) { 326 float s = StaticDrops(uv, t)*l0; 327 vec2 m1 = DropLayer2(uv, t)*l1; 328 vec2 m2 = DropLayer2(uv*1.85, t)*l2; 329 float c = s + m1.x + m2.x; 330 c = S(.3, 1., c); 331 return vec2(c, max(m1.y*l0, m2.y*l1)); 332} 333 334// Blurred texture lookup. WebGL1 has no built-in textureLod for fragment 335// shaders; we use GL_EXT_shader_texture_lod when available, otherwise fall 336// back to a small 5-tap blur whose radius scales with focus. 337vec3 sampleBlur(vec2 uv, float focus) { 338#ifdef GL_EXT_shader_texture_lod 339 return texture2DLodEXT(iChannel0, uv, focus).rgb; 340#else 341 float r = focus * 0.004; 342 vec3 sum = texture2D(iChannel0, uv).rgb; 343 sum += texture2D(iChannel0, uv + vec2( r, 0.0)).rgb; 344 sum += texture2D(iChannel0, uv + vec2(-r, 0.0)).rgb; 345 sum += texture2D(iChannel0, uv + vec2(0.0, r)).rgb; 346 sum += texture2D(iChannel0, uv + vec2(0.0, -r)).rgb; 347 return sum / 5.0; 348#endif 349} 350 351void main() { 352 vec2 fragCoord = v_uv * iResolution.xy; 353 vec2 uv = (fragCoord - .5*iResolution.xy) / iResolution.y; 354 vec2 UV = fragCoord / iResolution.xy; 355 vec3 M = iMouse.xyz / iResolution.xyz; 356 float T = iTime + M.x*2.; 357 358#ifdef HAS_HEART 359 T = mod(iTime, 102.); 360 T = mix(T, M.x*102., M.z > 0. ? 1. : 0.); 361#endif 362 363#ifdef ENHANCE_MOBILE_MOTION 364 float t = T*.32; 365#else 366 float t = T*.2; 367#endif 368 float rainAmount = iMouse.z > 0. ? M.y : sin(T*.05)*.3 + .7; 369 370 // Dezoom â pull the camera back so drops shrink and tile more densely. 371 // (Multiplies the drop-grid frequency without changing the physics.) 372 uv *= 2.0; 373 374 float maxBlur = mix(3., 6., rainAmount); 375 float minBlur = 2.; 376 377 float story = 0.; 378 float heart = 0.; 379 380#ifdef HAS_HEART 381 story = S(0., 70., T); 382 t = min(1., T/70.); 383 t = 1. - t; 384 t = (1. - t*t)*70.; 385 386 float zoom = mix(.3, 1.2, story); 387 uv *= zoom; 388 minBlur = 4. + S(.5, 1., story)*3.; 389 maxBlur = 6. + S(.5, 1., story)*1.5; 390 391 vec2 hv = uv - vec2(.0, -.1); 392 hv.x *= .5; 393 float sHeart = S(110., 70., T); 394 hv.y -= sqrt(abs(hv.x))*.5*sHeart; 395 heart = length(hv); 396 heart = S(.4*sHeart, .2*sHeart, heart)*sHeart; 397 rainAmount = heart; 398 399 maxBlur -= heart; 400 uv *= 1.5; 401 t *= .25; 402 403 UV = (UV - .5)*(.9 + 0.1) + .5; 404#endif 405 // No camera breathing â uv and UV stay at their natural scale. 406 407 float staticDrops = S(-.5, 1., rainAmount)*2.; 408 float layer1 = S(.25, .75, rainAmount); 409 float layer2 = S(.0, .5, rainAmount); 410 411 vec2 c = Drops(uv, t, staticDrops, layer1, layer2); 412 413 // Expensive normals â two extra Drops() calls. 414 vec2 e = vec2(.001, 0.); 415 float cx = Drops(uv + e, t, staticDrops, layer1, layer2).x; 416 float cy = Drops(uv + e.yx, t, staticDrops, layer1, layer2).x; 417 vec2 n = vec2(cx - c.x, cy - c.x); 418 419#ifdef HAS_HEART 420 n *= 1. - S(60., 85., T); 421 c.y *= 1. - S(80., 100., T)*.8; 422#endif 423
424 float focus = mix(maxBlur - c.y, minBlur, S(.1, .2, c.x)); 425 vec3 col = sampleBlur(UV + n, focus); 426 427 // Soft start-fade â apply to the alpha mask, NOT the color. Darkening 428 // col during fade-in turned droplets near-black/grey for several seconds 429 // while the shader smoothstep ramped up. Multiplying the mask fades the 430 // drops in transparency-wise so they show real refracted color from 431 // frame 1. 432 float fade = S(0., 3., T); 433#ifdef HAS_HEART 434 fade *= S(102., 97., T); 435#endif 436 437 // Reveal the refracted texture ONLY inside droplets + trails so the 438 // background image stays invisible and the page sees-through to whatever 439 // CSS sits behind the canvas. c.x = main drop mask, c.y = trail mask 440 // (trail contribution further reduced â ~5% of its earlier weight). 441 // Global multiplier softens the whole rain layer. 442#ifdef ENHANCE_MOBILE_MOTION 443 float mask = clamp(max(c.x, c.y * 0.12) * 0.72, 0.0, 1.0) * fade; 444#else 445 float mask = clamp(max(c.x, c.y * 0.04) * 0.6, 0.0, 1.0) * fade; 446#endif 447 gl_FragColor = vec4(col * mask, mask); 448} 449`;function Yu(t,a,s){const n=t.createShader(a);return n?(t.shaderSource(n,s),t.compileShader(n),t.getShaderParameter(n,t.COMPILE_STATUS)?n:(console.warn("[RainOnGlass] shader compile failed:",t.getShaderInfoLog(n)),t.deleteShader(n),null)):null}function M_({src:t,className:a,noHeart:s=!0,clipTo:n}){const r=o.useRef(null);Af(r);const[i,l]=o.useState(!1),[c,d]=o.useState(0);return o.useEffect(()=>{const m=r.current;if(!m)return;if(!n||n.length===0){m.style.clipPath="";return}const u=()=>{const f=[];for(const y of n)document.querySelectorAll(y).forEach(x=>{const v=x.getBoundingClientRect();v.width>0&&v.height>0&&f.push(v)});
449if(f.length===0){m.style.clipPath="polygon(0 0, 0 0, 0 0)";return}const b=[];f.forEach((y,x)=>{const v=y.left,w=y.top,j=y.right,T=y.bottom;x>0&&b.push("0px 0px"),b.push(`${v}px ${w}px`),b.push(`${j}px ${w}px`),b.push(`${j}px ${T}px`),b.push(`${v}px ${T}px`),b.push(`${v}px ${w}px`)}),m.style.clipPath=`polygon(${b.join(", ")})`};u();const h=new ResizeObserver(u),p=new Set;for(const f of n)document.querySelectorAll(f).forEach(b=>{h.observe(b),p.add(b)});const g=new MutationObserver(()=>{for(const f of n)document.querySelectorAll(f).forEach(b=>{p.has(b)||(h.observe(b),p.add(b))});u()});return g.observe(document.body,{childList:!0,subtree:!0}),window.addEventListener("resize",u),window.addEventListener("scroll",u,{passive:!0,capture:!0}),()=>{h.disconnect(),g.disconnect(),window.removeEventListener("resize",u),window.removeEventListener("scroll",u,{capture:!0})}},[n]),o.useEffect(()=>{const m=r.current;if(!m)return;const u=m.getContext("webgl",{premultipliedAlpha:!0,alpha:!0,antialias:!1});if(!u)return;u.getExtension("OES_standard_derivatives"),u.getExtension("EXT_shader_texture_lod");const h=typeof window.matchMedia=="function"?window.matchMedia("(max-width: 767px)").matches:window.innerWidth<768,p=Yu(u,u.VERTEX_SHADER,E_),g=Yu(u,u.FRAGMENT_SHADER,T_(!s,h));if(!p||!g)return;const f=u.createProgram();if(!f)return;if(u.attachShader(f,p),u.attachShader(f,g),u.bindAttribLocation(f,0,"a_position"),u.linkProgram(f),!u.getProgramParameter(f,u.LINK_STATUS)){console.warn("[RainOnGlass] link failed:",u.getProgramInfoLog(f));return}u.useProgram(f);const b=u.createBuffer();u.bindBuffer(u.ARRAY_BUFFER,b),u.bufferData(u.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]),u.STATIC_DRAW),u.enableVertexAttribArray(0),u.vertexAttribPointer(0,2,u.FLOAT,!1,0,0);const y=u.getUniformLocation(f,"iResolution"),x=u.getUniformLocation(f,"iTime"),v=u.getUniformLocation(f,"iMouse"),w=u.getUniformLocation(f,"iChannel0"),j=u.createTexture();u.activeTexture(u.TEXTURE0),u.bindTexture(u.TEXTURE_2D,j),u.texImage2D(u.TEXTURE_2D,0,u.RGBA,1,1,0,u.RGBA,u.UNSIGNED_BYTE,new Uint8Array([240,240,240,255])),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_WRAP_S,u.CLAMP_TO_EDGE),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_WRAP_T,u.CLAMP_TO_EDGE),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MIN_FILTER,u.LINEAR),u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MAG_FILTER,u.LINEAR),u.uniform1i(w,0),u.clearColor(0,0,0,0),u.enable(u.BLEND),u.blendFuncSeparate(u.ONE,u.ONE_MINUS_SRC_ALPHA,u.ONE,u.ONE_MINUS_SRC_ALPHA);const T=()=>{const M=Math.min(window.devicePixelRatio||1,2),H=Math.max(1,Math.floor(m.clientWidth*M)),ee=Math.max(1,Math.floor(m.clientHeight*M));(m.width!==H||m.height!==ee)&&(m.width=H,m.height=ee),u.viewport(0,0,m.width,m.height)};T();const P=new ResizeObserver(T);P.observe(m);let N=0,_=performance.now(),L=!0,q=!1;const O=M=>{M.preventDefault(),L=!1,cancelAnimationFrame(N),l(!1)},A=()=>{d(M=>M+1)};m.addEventListener("webglcontextlost",O),m.addEventListener("webglcontextrestored",A);const k=()=>{if(!L||!q)return;const M=(performance.now()-_)/1e3;u.useProgram(f),u.clear(u.COLOR_BUFFER_BIT),u.uniform3f(y,m.width,m.height,1),u.uniform1f(x,M),u.uniform4f(v,0,0,0,0),u.activeTexture(u.TEXTURE0),u.bindTexture(u.TEXTURE_2D,j),u.drawArrays(u.TRIANGLES,0,6),N=requestAnimationFrame(k)},J=new Image;return J.crossOrigin="anonymous",J.onload=()=>{if(!L)return;u.bindTexture(u.TEXTURE_2D,j),u.pixelStorei(u.UNPACK_FLIP_Y_WEBGL,!0),u.texImage2D(u.TEXTURE_2D,0,u.RGBA,u.RGBA,u.UNSIGNED_BYTE,J);const M=H=>(H&H-1)===0;M(J.width)&&M(J.height)?(u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MIN_FILTER,u.LINEAR_MIPMAP_LINEAR),u.generateMipmap(u.TEXTURE_2D)):u.texParameteri(u.TEXTURE_2D,u.TEXTURE_MIN_FILTER,u.LINEAR),q=!0,_=performance.now(),L&&(N=requestAnimationFrame(k)),l(!0)},J.src=t,()=>{L=!1,cancelAnimationFrame(N),P.disconnect(),m.removeEventListener("webglcontextlost",O),m.removeEventListener("webglcontextrestored",A),u.isContextLost()||(u.deleteTexture(j),u.deleteBuffer(b),u.deleteProgram(f),u.deleteShader(p),u.deleteShader(g))}},[c,t,s]),e.jsx("canvas",{ref:r,"aria-hidden":"true",className:a,style:{position:"fixed",inset:0,width:"100vw",height:"100vh",pointerEvents:"none",opacity:i?1:0,transition:"opacity 3000ms ease-out"}})}const P_="/assets/chat_background_gray-DtngF395.webp";function A_({onUploadComplete:t,onViewWishlistItem:a,wishlistViewItem:s,onWishlistViewHandled:n,pathChoiceRef:r,onAuthRequired:i,onNavigatePath:l}){return e.jsx(zk,{ref:r,onUploadComplete:t,initialSelectedItem:s,onInitialItemHandled:n,onViewWishlistItem:a,onAuthRequired:i,onNavigatePath:c=>{(c==="upload"||c==="extension")&&l?.(c)}})}function I_({onMaterialOpen:t,onOpenVideoShow:a,selectedVideoShow:s,onBackFromVideoShow:n,onPlayEpisode:r,onDeleteVideoShow:i,onRefreshVideoShow:l,onOpenM
449angaSeries:c,selectedMangaSeries:d,onBackFromMangaSeries:m,onDeleteMangaSeries:u,onRefreshMangaSeries:h,refreshTrigger:p,onUploadComplete:g,uploaderOpen:f,demoMaterials:b,onUploaderOpenChange:y,selectedPublicSeries:x,onBackFromPublicSeries:v,onOpenPublicSeries:w,startScanner:j}){const{user:T,getAccessToken:P}=ps(),{openAuthModal:N}=xo(),{series:_}=Kk(),[L,q]=o.useState([]);o.useEffect(()=>{let M=!1;return T?(q([]),P().then(async H=>{if(!H||M)return;const ee=await fetch(`${ue()}/api/reading/library/public-series`,{headers:{Authorization:`Bearer ${H}`}});if(!ee.ok)throw new Error("Failed to load public manga for this library");const Pe=await ee.json();M||q(Array.isArray(Pe)?Pe:[])}).catch(H=>{console.warn("[ReadingLibrary] Failed to load account public manga:",H),M||q([])}),()=>{M=!0}):()=>{M=!0}},[T,P,_]);const O=o.useCallback(async M=>{const H=await P();if(!H)throw new Error("Please sign in first");if(!(await fetch(`${ue()}/api/reading/library/public-series/${encodeURIComponent(M)}`,{method:"DELETE",headers:{Authorization:`Bearer ${H}`}})).ok)throw new Error("Could not remove this manga from your library");q(Pe=>Pe.filter(D=>D.id!==M))},[P]);if(x)return e.jsx(Gk,{detail:x,onBack:()=>v?.(),onOpenVolume:t});if(d)return e.jsx(C_,{series:d,onBack:m,onOpenMaterial:t,onDelete:u,onRefresh:h,onUploadComplete:(M,H)=>g?.(M,H)});if(s)return e.jsx(b_,{show:s,onBack:n,onPlayEpisode:r,onDelete:i,onRefresh:l,onUploadComplete:(M,H)=>g?.(M,H)});const A=M=>{if(!T){if(b?.some(H=>H.id===M)){t(M);return}N("signup");return}t(M)},k=async(M,H)=>{if(!T){N("signup");return}try{H&&H(M);const ee=await P();if(!ee)throw new Error("Please log in first");if(!(await fetch(`${ue()}/api/reading/materials/${M}`,{method:"DELETE",headers:{Authorization:`Bearer ${ee}`,"Content-Type":"application/json"}})).ok)throw new Error("Failed to delete material");try{await Promise.allSettled([Mn(M),_o(M)])}catch{}H&&H(null)}catch(ee){throw console.error("Delete error:",ee),ee}finally{H&&H(null)}},J=T?L:_;return e.jsx($k,{onSelectMaterial:A,onDeleteMaterial:(M,H)=>k(M,H),onOpenVideoShow:a,onOpenMangaSeries:c,onUploadComplete:g,refreshTrigger:p,uploaderOpen:f,publicSeries:J,onOpenPublicSeries:w,onRemovePublicSeries:T?O:void 0,demoMaterials:J.length>0?void 0:b,onUploaderOpenChange:y,startScanner:j})}const Ju=["overview","library","extension","settings"],R_={overview:{title:"Immersion",lede:"Read manga, novels, or watch anime â with every word explained."},library:{title:"Library",lede:"Everything you've added â manga series, novels, and shows. Open one to keep reading."},extension:{title:"Extension",lede:"Take Shizen across the web â hover-to-look-up and tappable subtitles on the sites you already use."},settings:{title:"Settings",lede:"Tune how each reader behaves â annotations, lookups, and reading layout."}};function $_(){const{user:t,loading:a,getAccessToken:s}=ps(),{openAuthModal:n}=xo(),{isInScanSession:r,setIsInReader:i}=am(),l=nc(),{slug:c,tab:d,owner:m,seriesSlug:u,volumeSlug:h}=Lp(),p=window.location.pathname,g=p==="/immersion/scan",[f,b]=o.useState(g),y=o.useRef(!1);o.useEffect(()=>{g&&b(!0)},[g]);const x=c&&p.startsWith("/immersion/manga/")?c:null,v=c&&p.startsWith("/immersion/show/")?c:null,w=c&&p.startsWith("/immersion/library/read/")?c:null,j=c&&p.startsWith("/immersion/library/play/")?c:null,T=p.startsWith("/immersion/read/"),[P,N]=o.useState(null),[_,L]=o.useState(!1),q=w??P,[O,A]=o.useState(null),[k,J]=o.useState(null),[M,H]=o.useState(null),[ee,Pe]=o.useState(0),[D,de]=o.useState(!1),[fe,Me]=o.useState(null),[U,ve]=o.useState(null),[yt,ut]=o.useState(null),[St,je]=o.useState(null),[lt,Et]=o.useState(null),[Ct,aa]=o.useState(null),[vt,Le]=o.useState(!1),jt=j_({episodeId:j,enabled:!a&&!!t,seed:Ct,getAccessToken:s}),{loading:Ft,completed:ct}=sm("reading"),[se,ft]=o.useState(!1),Oe=!Ft&&!ct&&!se;o.useEffect(()=>{if(!Oe)return;const oe=document.documentElement,me=oe.style.getPropertyValue("--module-accent");return oe.style.setProperty("--module-accent","var(--brand-chat)"),()=>oe.style.setProperty("--module-accent",me)},[Oe]);const[pt,kt]=o.useState({materialsCount:0,pagesRead:0,pagesRemaining:0,pagesTotal:0,readingStreak:0,pagesReadToday:0,lastMaterialId:null,lastMaterialTitle:null,lastMaterialThumbnail:null,lastMaterialCurrentPage:0,lastMaterialTotalPages:0,lastMaterialHasProgress:!1,lastMaterialContentType:null,lastMaterialAuthor:null,lastMaterialLastReadAt:null}),Be=g||!!(x||v||q||j)?"library":Ju.includes(d??"")?d:"overview";Bp(Be);const Ke=o.useCallback(oe=>{o.startTransition(()=>l(`/immersion/${oe}`))},[l]);o.useEffect(()=>{if(!(a||!g)){if(!t){y.current||(y.current=!0,n("signin"));return}de(!0),l("/immersion/library",{replace:!0})}},[a,g,t,n,l]),o.useEffect(()=>{if(g||!f||!D)return;const oe=window.setTimeout(()=>b(!1),0);return()=>window.clearTimeout(oe)},[g,D,f]);const{material:At}=qk(),ta=!!q&&(!t||T&&m==="public"||Vk(q)),zt=o.useMemo(()=>At?[{id:At.id,title:At.title??"Sample",title_jp:At.title_jp,author:At.author??void 0,content_type:At.content_type??"manga",total_pages:At.total_pages??0,current_page:0,processing_status:"completed",unique_vocab_count:At.unique_vocab_count??void 0,cover_image_url:At.cover_image_url,created_at:new Date().toISOString()}]:[],[At]);o.useEffect(()=>{!a&&!t&&(v||j)&&l("/immersion/overview",{replace:!0})},[a,t,v,j,l]),o.useEffect(()=>{async function oe(){try{const me=await s();if(!me)return;const Ge=await fetch(`${ue()}/api/reading/materials`,{headers:{Authorization:`Bearer ${me}`}});if(Ge.ok){const I=(await Ge.json()).materials||[],xe=I.length,Ne=I.reduce((G,re)=>G+(re.total_pages||0),0),tt=I.reduce((G,re)=>G+(re.current_page||0),0),Mt=Math.max(0,Ne-tt),Ma=localStorage.getItem("reading.lastReadDate"),It=parseInt(localStorage.getItem("reading.streakCount")||"0",10),Nt=ne
449w Date().toDateString(),Lt=new Date(Date.now()-864e5).toDateString();let qa=0;(Ma===Nt||Ma===Lt)&&(qa=It);const F=localStorage.getItem("reading.pagesReadToday"),W=localStorage.getItem("reading.pagesReadTodayDate")===Nt?parseInt(F||"0",10):0;let E=null;I.length>0&&(E=I.find(G=>G.current_page>0)||I[0]),kt({materialsCount:xe,pagesRead:tt,pagesRemaining:Mt,pagesTotal:Ne,readingStreak:qa,pagesReadToday:W,lastMaterialId:E?.id||null,lastMaterialTitle:E?.title||null,lastMaterialThumbnail:E?.cover_image_url||null,lastMaterialCurrentPage:E?.current_page||0,lastMaterialTotalPages:E?.total_pages||0,lastMaterialHasProgress:(E?.current_page||0)>0,lastMaterialContentType:E?.content_type||null,lastMaterialAuthor:E?.author||null,lastMaterialLastReadAt:E?.last_read_at||null})}}catch(me){console.error("Failed to fetch reading stats:",me)}}oe()},[s,ee]),o.useEffect(()=>{if(!t){H(null);return}let oe=!1;return(async()=>{try{const{apiClient:me}=await Rs(async()=>{const{apiClient:gt}=await import("./index-4BgFHtDy.js").then(I=>I.cW);return{apiClient:gt}},__vite__mapDeps([3,1,4,5,6,7])),Ge=await me.getMe();oe||H(Ge?.user?.name||null)}catch{}})(),()=>{oe=!0}},[t]);const K=o.useRef(null),[_t,qt]=o.useState(!1),sa=o.useRef(null),[la,Dt]=o.useState({visible:!1,x:0,y:0,clicking:!1}),ba=o.useRef(la),da=o.useCallback(oe=>{ba.current=oe,Dt(oe)},[]),xa=o.useMemo(()=>({navigateToTab:oe=>Ke(oe),openUploader:()=>{Ke("overview"),K.current?.setSelectedPath("upload")},resetUploader:()=>{K.current?.uploaderRef?.current?.reset(),K.current?.setSelectedPath("none")},selectCategory:oe=>{K.current?.setSelectedPath("upload"),setTimeout(()=>{K.current?.uploaderRef?.current?.setContentCategory(oe)},100)},selectSeriesMode:oe=>{K.current?.uploaderRef?.current?.setMangaSeriesMode(oe)},showUploaderConfirm:()=>{K.current?.setSelectedPath("upload");const oe=me=>{const Ge=K.current?.uploaderRef?.current;Ge?Ge.showConfirmStep():me<10&&setTimeout(()=>oe(me+1),100)};setTimeout(()=>oe(0),150)},openDiscover:()=>{K.current?.setSelectedPath("discover")},backToPathChoice:()=>{K.current?.uploaderRef?.current?.reset(),K.current?.setSelectedPath("none")},openDemoReader:()=>qt(!0),closeDemoReader:()=>qt(!1),simulateTokenClick:(oe,me)=>{sa.current?.simulateTokenClick(oe,me)},closeTokenPanel:()=>{sa.current?.closeTokenPanel()},hoverCluster:(oe,me)=>{sa.current?.hoverCluster(oe,me)},clearClusterHover:()=>{sa.current?.clearClusterHover()},getTextBoxRect:oe=>sa.current?.getTextBoxRect(oe)??null,getClusterRect:(oe,me)=>sa.current?.getClusterRect(oe,me)??null,setCursorState:da}),[da,Ke]),ma=()=>{ft(!0);const oe=id();oe&&l(oe,{replace:!0})},Na=()=>{ft(!0);const oe=id();oe&&l(oe,{replace:!0})},Da=o.useMemo(()=>[{id:"overview",label:"Overview",iconSrc:em,description:"Immersion overview",isHub:!0},{id:"library",label:"Library",iconSrc:In,description:"Your library"},{id:"extension",label:"Extension",iconSrc:Zl,description:"Browser extension"},{id:"settings",label:"Settings",iconSrc:ec,description:"Immersion preferences"}],[]);Dp(Da,Be,oe=>{Ju.includes(oe)&&Ke(oe)},"hsl(var(--brand-chat))");const wa=o.useCallback(async oe=>{if(lt?.series?.slug){const me=lt.volumes.find(Ge=>Ge.id===oe);if(me)return Un({id:me.id,title:me.title,volume:me.volume},{slug:lt.series.slug},{isPublic:!0,volumeSlug:me.slug})}if(St?.slug){const me=St.reading_materials.find(Ge=>Ge.id===oe);if(me)return Un({id:me.id,title:me.title,volume:me.volume??null,created_at:me.created_at},{slug:St.slug,volumes:St.reading_materials.map(Ge=>({id:Ge.id,volume:Ge.volume??null,created_at:Ge.created_at}))},{isPublic:!1,ownerName:M})}if(At?.id===oe&&At.title)return Un({id:At.id,title:At.title},null,{isPublic:!0});try{const me=await fp();for(const gt of me){if(!gt.slug)continue;const xe=(await Ri(gt.slug))?.volumes.find(Ne=>Ne.id===oe);if(xe)return Un({id:xe.id,title:xe.title,volume:xe.volume},{slug:gt.slug},{isPublic:!0,volumeSlug:xe.slug})}const Ge=await pp();if(Ge?.id===oe&&Ge.title)return Un({id:Ge.id,title:Ge.title},null,{isPublic:!0})}catch{}if(!t)return null;try{const me=await s();if(!me)return null;const Ge=await fetch(`${ue()}/api/reading/materials/${oe}`,{headers:{Authorization:`Bearer ${me}`}});if(!Ge.ok)return null;const gt=await Ge.json();if(gt.manga_series_id){const I=await fetch(`${ue()}/api/manga/series/${gt.manga_series_id}`,{headers:{Authorization:`Bearer ${me}`}});if(I.ok){const xe=(await I.json())?.series;if(xe?.slug)return Un({id:gt.id,title:gt.title,volume:gt.volume??null,created_at:gt.created_at},{slug:xe.slug,volumes:(xe.reading_materials??[]).map(Ne=>({id:Ne.id,volume:Ne.volume??null,created_at:Ne.created_at}))},{isPublic:!1,ownerName:M})}return null}return Un({id:gt.id,title:gt.title,volume:gt.volume??null,created_at:gt.created_at},null,{isPublic:!1,ownerName:M})}catch{return null}},[lt,St,At,M,t,s]),Wt=oe=>{Cu(oe),(async()=>{const me=await wa(oe);l(me??`/immersion/library/read/${oe}`)})()},ua=()=>{A(null),J(null),N(null),L(!1),aa(null),Le(!1),l(yt?`/immersion/show/${yt.slug??yt.id}`:"/immersion/library")},ca=oe=>{ut(oe),l(`/immersion/show/${oe.slug??oe.id}`)},ha=()=>{ut(null),l("/immersion/library")},za=oe=>{je(oe),l(`/immersion/manga/${oe.slug??oe.id}`)},ea=()=>{je(null),l("/immersion/library")}
449,Ea=async oe=>{const me=await Ri(oe);me&&(Ca.current=oe,Et(me),je(null)),l(`/immersion/manga/${oe}`)},pa=()=>{Et(null),Ca.current=null,l("/immersion/library")},Ca=o.useRef(null);o.useEffect(()=>{x&&x!==Ca.current&&!St&&!lt&&(Ca.current=x,(async()=>{const oe=t?await s():null;if(oe){const Ge=await fetch(`${ue()}/api/manga/series/by-slug/${x}`,{headers:{Authorization:`Bearer ${oe}`}});if(Ge.ok){const gt=await Ge.json();je(gt.series??gt),Et(null),Ke("library");return}}const me=await Ri(x);me?(Et(me),je(null),Ke("library")):t||l("/immersion/overview",{replace:!0})})()),v&&v!==Ca.current&&!yt&&(Ca.current=v,(async()=>{const oe=await s();if(!oe)return;const me=await fetch(`${ue()}/api/video/shows/by-slug/${v}`,{headers:{Authorization:`Bearer ${oe}`}});if(me.ok){const Ge=await me.json();ut(Ge.show??Ge),Ke("library")}})())},[x,v]);const Gt=async oe=>{if(confirm("Delete this manga series? Individual manga will remain in your library."))try{const me=await s();if(!me)return;await fetch(`${ue()}/api/manga/series/${oe}`,{method:"DELETE",headers:{Authorization:`Bearer ${me}`}}),je(null),Pe(Ge=>Ge+1)}catch{}},Ba=(oe,me,Ge)=>{aa(x_(oe,me)),Le(Ge?.openCondensedAudio??!1),l(`/immersion/library/play/${me.id}`)},ka=async oe=>{if(confirm("Delete this show and all its seasons/episodes?"))try{const me=await s();if(!me)return;await fetch(`${ue()}/api/video/shows/${oe}`,{method:"DELETE",headers:{Authorization:`Bearer ${me}`}}),ut(null),Pe(Ge=>Ge+1)}catch{}},Wa=!!q||!!j;Os.useEffect(()=>{i(Wa)},[Wa,i]);const es=(oe,me)=>{console.log("â
Upload completed for material:",oe),Pe(Ge=>Ge+1),de(!1),me?.duplicate?Me(me.message):Me(null),Ke("library")};o.useEffect(()=>{!T&&!w&&(N(null),L(!1))},[T,w]),o.useEffect(()=>{if(!T){L(!1);return}if(m!=="public"&&!t){l("/immersion/overview",{replace:!0});return}let oe=!1;return L(!1),(async()=>{let me=null;try{if(m==="public")u&&(me=(await Ri(u))?.volumes.find(gt=>gt.slug===h)?.id??null);else{const Ge=await s();if(Ge)if(u){const gt=await fetch(`${ue()}/api/manga/series/by-slug/${u}`,{headers:{Authorization:`Bearer ${Ge}`}});if(gt.ok){const xe=((await gt.json())?.series?.reading_materials??[]).map(tt=>({id:tt.id,volume:tt.volume??null,created_at:tt.created_at}));me=[...gp(xe).entries()].find(([,tt])=>tt===h)?.[0]??null}}else{const gt=await fetch(`${ue()}/api/reading/materials`,{headers:{Authorization:`Bearer ${Ge}`}});gt.ok&&(me=((await gt.json()).materials??[]).find(Ne=>!Ne.manga_series_id&&(Ne.id===h||yp({id:Ne.id,title:Ne.title})===h))?.id??null)}}}catch{me=null}oe||(me?(N(me),L(!1)):L(!0))})(),()=>{oe=!0}},[T,m,u,h,t,s,l]);const Ta=o.useRef(wa);Ta.current=wa;const va=o.useRef(null);if(o.useEffect(()=>{if(!w||!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(w)||va.current===w)return;va.current=w;let me=!1;return(async()=>{const Ge=await Ta.current(w);me||!Ge||(N(w),l(Ge,{replace:!0}))})(),()=>{me=!0}},[w,l]),o.useEffect(()=>{q&&(O===q&&k||(ta||Cu(q),A(q),J(null),(async()=>{try{const oe=ta,me=oe?`${ue()}/api/reading/public/material/${q}`:`${ue()}/api/reading/materials/${q}`,Ge={};if(!oe){const I=await s();I&&(Ge.Authorization=`Bearer ${I}`)}const gt=await fetch(me,{headers:Ge});if(gt.ok){const I=await gt.json(),xe=I.content_type==="novel"?"novel":I.local_images?"manga":I.content_type||"manga";J(xe)}else J("manga")}catch{J("manga")}})()))},[q,ta]),T&&!q&&!_)return null;if(j){if(jt.state.status!=="ready"){const me=jt.state.status==="idle"?{status:"loading"}:jt.state;return e.jsx(t_,{state:me,onBack:ua,onRetry:jt.retry})}const oe=jt.state.playback;return e.jsx(e_,{episodeId:oe.id,episodeLabel:`${oe.session_title} â ${oe.label}`,videoFilename:oe.video_filename,initialPositionMs:oe.last_position_ms,initialOffsetMs:oe.subtitle_offset_ms,cloudSyncStatus:oe.cloud_sync_status,openCondensedAudio:vt,onBack:ua},oe.id)}if(q)return k==="novel"?e.jsx(ix,{materialId:q,onBack:ua}):e.jsx(Kd,{materialId:q,onBack:ua,isPublicSample:ta});const ia=pt.lastMaterialId&&pt.lastMaterialTitle?{id:pt.lastMaterialId,title:pt.lastMaterialTitle,thumbnailUrl:pt.lastMaterialThumbnail,currentPage:pt.lastMaterialCurrentPage,totalPages:pt.lastMaterialTotalPages,hasProgress:pt.lastMaterialHasProgress,contentType:pt.lastMaterialContentType,author:pt.lastMaterialAuthor,lastReadAt:pt.lastMaterialLastReadAt}:null;return e.jsxs("div",{className:`wc-root im-logged${t&&Be==="overview"?" wc-overview-refresh":""}${!t&&Be==="overview"?" wc-module-public module-landing":""}`,"data-module":"reading",children:[!r&&e.jsx(M_,{src:P_,className:"im-page-rain"}),Oe&&e.jsxs(e.Fragment,{children:[e.jsx(Bk,{onComplete:ma,onSkip:Na,tourActions:xa}),e.jsx(kf,{x:la.x,y:la.y,visible:la.visible,clicking:la.clicking})]}),_t&&e.jsx(Kd,{materialId:"demo-onboarding",onBack:()=>qt(!1),demoMode:!0,onDemoReady:oe=>{sa.current=oe}}),!_t&&e.jsx("div",{className:"im-logged-content",children:e.jsxs("div",{className:`im-shell${!t&&Be==="overview"?" ml-shell":""}${!t&&Be!=="overview"?" im-guest-app":""}`,children:[e.jsx(kj,{activeSection:Be,onSectionChange:oe=>Ke(oe),publicOverview:!t&&Be==="overview"}),e.jsxs("div",{className:`im-body${!t&&Be==="overview"?" ml-body":""}`,"data-active-tab":Be,children:[!t&&Be==="overview"?e.jsx(Qk,{}):e.jsxs("header",{className:"im-page-header",children:[e.jsx("h1",{className:"im-page-title",children:e.jsx(Op,{paint:"purple",children:R_[Be].title})}),Be==="overview"?t?e.jsx("p",{className:"im-page-lede",children:"Read manga, novels, or watch anime â with every word explained."}):e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"hero-lede wc-herolede-full",children:[e.jsxs("span",{className:"break",children:["The manga, anime, and novels that made you want to learn Japanese â ",e.jsx("em",{children:"finally readable"}),"."]}),"Bring your own, and Shizen turns any of it into text you can actually read: every word and grammar point made understandable in context,",e.jsx("span",{className:"break",children:"furigana on ta
449p, your place never lost."}),"Look it up, learn the grammar, save whatâs new â all without leaving the page."]}),e.jsxs("p",{className:"hero-lede wc-herolede-mobile",children:["The manga, anime, and novels that made you want to learn Japanese â ",e.jsx("em",{children:"finally readable"}),". Every word tappable, grammar explained in context, your place never lost."]})]}):null,!t&&Be==="overview"&&e.jsxs(e.Fragment,{children:[e.jsx(bp,{}),e.jsxs("div",{className:"hero-ctas im-hero-ctas",children:[e.jsx(ac,{as:"button",onClick:()=>n("signup"),variant:"dusk",children:"Sign up for free"}),e.jsxs(Wn,{to:"/immersion/library",className:"wc-hero-link",children:["Browse the library ",e.jsx("span",{className:"arrow","aria-hidden":"true",children:"â"})]})]})]}),Be!=="overview"&&e.jsxs("p",{className:"im-page-lede",children:[Be==="library"&&"Everything you've added â manga series, novels, and shows. Open one to keep reading.",Be==="settings"&&"Tune how each reader behaves â annotations, lookups, and reading layout."]})]}),Be==="overview"&&t&&e.jsx(Cj,{candidate:ia,onContinue:Wt,onAddContent:()=>{de(!0),Ke("library")}}),e.jsxs("div",{className:`im-main${!t&&Be==="overview"?" ml-main":""}`,children:[Be==="overview"&&(t?e.jsx(A_,{onUploadComplete:es,onViewWishlistItem:oe=>ve(oe),wishlistViewItem:U,onWishlistViewHandled:()=>ve(null),pathChoiceRef:K,onAuthRequired:void 0,onNavigatePath:oe=>{oe==="upload"?(de(!0),Ke("library")):Ke("extension")}}):e.jsx(Zk,{})),Be==="library"&&t&&fe&&e.jsxs("div",{role:"status",style:{maxWidth:920,margin:"0 auto 16px",padding:"12px 16px",background:"rgba(82, 157, 215, 0.08)",border:"1px solid rgba(82, 157, 215, 0.32)",borderRadius:8,color:"var(--ink, #2a3540)",display:"flex",alignItems:"flex-start",gap:12,fontSize:14,lineHeight:1.5},children:[e.jsx("span",{style:{flex:1},children:fe}),e.jsx("button",{type:"button",onClick:()=>Me(null),"aria-label":"Dismiss notice",style:{background:"transparent",border:"none",cursor:"pointer",color:"var(--ink-soft, #55606c)",padding:2,lineHeight:1},children:"â"})]}),Be==="library"&&e.jsx(I_,{onMaterialOpen:Wt,onOpenVideoShow:ca,selectedVideoShow:yt,onBackFromVideoShow:ha,onPlayEpisode:Ba,onDeleteVideoShow:ka,onRefreshVideoShow:async()=>{const oe=await s();if(!oe)return;const me=await fetch(`${ue()}/api/video/shows`,{headers:{Authorization:`Bearer ${oe}`}});if(me.ok){const I=((await me.json()).shows||[]).find(xe=>xe.id===yt?.id);I&&ut(I)}},onOpenMangaSeries:za,selectedMangaSeries:St,onBackFromMangaSeries:ea,onDeleteMangaSeries:Gt,onRefreshMangaSeries:async()=>{const oe=await s();if(!oe)return;const me=await fetch(`${ue()}/api/manga/series`,{headers:{Authorization:`Bearer ${oe}`}});if(me.ok){const I=((await me.json()).series||[]).find(xe=>xe.id===St?.id);I&&je(I)}},refreshTrigger:ee,onUploadComplete:es,uploaderOpen:D,demoMaterials:t?void 0:zt,onUploaderOpenChange:de,selectedPublicSeries:lt,onBackFromPublicSeries:pa,onOpenPublicSeries:Ea,startScanner:f}),Be==="extension"&&e.jsx(rk,{}),Be==="settings"&&t&&e.jsx(Sj,{}),Be==="settings"&&!t&&e.jsx(Xj,{reason:"settings",onSignup:()=>n("signup"),onDismiss:()=>l("/immersion/overview")})]}),t&&e.jsx(_j,{pagesReadTotal:pt.pagesRead,pagesReadToday:pt.pagesReadToday})]},Be)]})})]})}const BS=Object.freeze(Object.defineProperty({__proto__:null,ReadingInterface:$_},Symbol.toStringTag,{value:"Module"}));export{OS as D,gu as M,BS as R,gg as S,Er as U,Jm as e};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.