karaoke-gen 0.105.4__py3-none-any.whl → 0.107.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. backend/api/routes/users.py +14 -3
  2. backend/config.py +3 -0
  3. backend/services/encoding_interface.py +4 -0
  4. backend/services/job_notification_service.py +4 -21
  5. backend/tests/test_job_notification_service.py +24 -58
  6. backend/tests/test_video_worker_orchestrator.py +189 -0
  7. backend/workers/video_worker_orchestrator.py +7 -0
  8. karaoke_gen/instrumental_review/server.py +145 -35
  9. karaoke_gen/nextjs_frontend/__init__.py +98 -0
  10. karaoke_gen/nextjs_frontend/out/404/index.html +1 -0
  11. karaoke_gen/nextjs_frontend/out/404.html +1 -0
  12. karaoke_gen/nextjs_frontend/out/__next.__PAGE__.txt +9 -0
  13. karaoke_gen/nextjs_frontend/out/__next._full.txt +22 -0
  14. karaoke_gen/nextjs_frontend/out/__next._head.txt +8 -0
  15. karaoke_gen/nextjs_frontend/out/__next._index.txt +9 -0
  16. karaoke_gen/nextjs_frontend/out/__next._tree.txt +2 -0
  17. karaoke_gen/nextjs_frontend/out/_next/static/chunks/01a7f8fe40f1ff47.js +1 -0
  18. karaoke_gen/nextjs_frontend/out/_next/static/chunks/112f346e31f991df.js +4 -0
  19. karaoke_gen/nextjs_frontend/out/_next/static/chunks/16d1a4dd9d8a873a.js +3 -0
  20. karaoke_gen/nextjs_frontend/out/_next/static/chunks/1ab85c362b8b0e86.js +9 -0
  21. karaoke_gen/nextjs_frontend/out/_next/static/chunks/247eb132b7f7b574.js +1 -0
  22. karaoke_gen/nextjs_frontend/out/_next/static/chunks/2b80d15cc95e4818.js +1 -0
  23. karaoke_gen/nextjs_frontend/out/_next/static/chunks/32c7eba5cd46c1bc.js +7 -0
  24. karaoke_gen/nextjs_frontend/out/_next/static/chunks/483f26794eae53d0.js +1 -0
  25. karaoke_gen/nextjs_frontend/out/_next/static/chunks/550c3b02e85f196a.js +1 -0
  26. karaoke_gen/nextjs_frontend/out/_next/static/chunks/55c5ade44387bef8.js +1 -0
  27. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5628d92b5893add2.css +1 -0
  28. karaoke_gen/nextjs_frontend/out/_next/static/chunks/56ebf7665e4341c8.js +7 -0
  29. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5997132b61dec430.js +1 -0
  30. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5ea55255bce3eb9e.js +5 -0
  31. karaoke_gen/nextjs_frontend/out/_next/static/chunks/5eda89a57490b3cd.js +1 -0
  32. karaoke_gen/nextjs_frontend/out/_next/static/chunks/692f5d9e0d700c76.js +3 -0
  33. karaoke_gen/nextjs_frontend/out/_next/static/chunks/71d7a05b14f9f0f4.js +1 -0
  34. karaoke_gen/nextjs_frontend/out/_next/static/chunks/81ac355749ef3302.js +1 -0
  35. karaoke_gen/nextjs_frontend/out/_next/static/chunks/95f7e5934dbb0e5d.js +1 -0
  36. karaoke_gen/nextjs_frontend/out/_next/static/chunks/9bce8f19eaa46940.js +1 -0
  37. karaoke_gen/nextjs_frontend/out/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  38. karaoke_gen/nextjs_frontend/out/_next/static/chunks/a9ed54eed3e14c92.js +2 -0
  39. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b35cd41238ecfb17.js +1 -0
  40. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5bc3c3d5ebd49eb.js +1 -0
  41. karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5c078c08db5ae32.js +5 -0
  42. karaoke_gen/nextjs_frontend/out/_next/static/chunks/be9c44a178104187.js +1 -0
  43. karaoke_gen/nextjs_frontend/out/_next/static/chunks/c4c840e18cb4861c.js +1 -0
  44. karaoke_gen/nextjs_frontend/out/_next/static/chunks/c645af7d6b65f73e.js +1 -0
  45. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d2c5e2575df784d4.js +1 -0
  46. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d30af02b96d81462.js +1 -0
  47. karaoke_gen/nextjs_frontend/out/_next/static/chunks/d9bdf64f4ec1e9b7.js +7 -0
  48. karaoke_gen/nextjs_frontend/out/_next/static/chunks/dcde6ed684dacd0e.js +5 -0
  49. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e422cbe931246000.js +1 -0
  50. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e483af34fc792d38.js +1 -0
  51. karaoke_gen/nextjs_frontend/out/_next/static/chunks/e57422aad6b897da.js +1 -0
  52. karaoke_gen/nextjs_frontend/out/_next/static/chunks/ef02697fb404726a.js +1 -0
  53. karaoke_gen/nextjs_frontend/out/_next/static/chunks/ff1a16fafef87110.js +1 -0
  54. karaoke_gen/nextjs_frontend/out/_next/static/chunks/turbopack-2d9ca3017a9deedf.js +3 -0
  55. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_buildManifest.js +11 -0
  56. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_clientMiddlewareManifest.json +1 -0
  57. karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_ssgManifest.js +1 -0
  58. karaoke_gen/nextjs_frontend/out/_not-found/__next._full.txt +18 -0
  59. karaoke_gen/nextjs_frontend/out/_not-found/__next._head.txt +8 -0
  60. karaoke_gen/nextjs_frontend/out/_not-found/__next._index.txt +9 -0
  61. karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.__PAGE__.txt +5 -0
  62. karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.txt +4 -0
  63. karaoke_gen/nextjs_frontend/out/_not-found/__next._tree.txt +2 -0
  64. karaoke_gen/nextjs_frontend/out/_not-found/index.html +1 -0
  65. karaoke_gen/nextjs_frontend/out/_not-found/index.txt +18 -0
  66. karaoke_gen/nextjs_frontend/out/admin/__next._full.txt +25 -0
  67. karaoke_gen/nextjs_frontend/out/admin/__next._head.txt +8 -0
  68. karaoke_gen/nextjs_frontend/out/admin/__next._index.txt +9 -0
  69. karaoke_gen/nextjs_frontend/out/admin/__next._tree.txt +2 -0
  70. karaoke_gen/nextjs_frontend/out/admin/__next.admin.__PAGE__.txt +9 -0
  71. karaoke_gen/nextjs_frontend/out/admin/__next.admin.txt +7 -0
  72. karaoke_gen/nextjs_frontend/out/admin/beta/__next._full.txt +25 -0
  73. karaoke_gen/nextjs_frontend/out/admin/beta/__next._head.txt +8 -0
  74. karaoke_gen/nextjs_frontend/out/admin/beta/__next._index.txt +9 -0
  75. karaoke_gen/nextjs_frontend/out/admin/beta/__next._tree.txt +2 -0
  76. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.__PAGE__.txt +9 -0
  77. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.txt +4 -0
  78. karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.txt +7 -0
  79. karaoke_gen/nextjs_frontend/out/admin/beta/index.html +1 -0
  80. karaoke_gen/nextjs_frontend/out/admin/beta/index.txt +25 -0
  81. karaoke_gen/nextjs_frontend/out/admin/index.html +1 -0
  82. karaoke_gen/nextjs_frontend/out/admin/index.txt +25 -0
  83. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._full.txt +25 -0
  84. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._head.txt +8 -0
  85. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._index.txt +9 -0
  86. karaoke_gen/nextjs_frontend/out/admin/jobs/__next._tree.txt +2 -0
  87. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.__PAGE__.txt +9 -0
  88. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.txt +4 -0
  89. karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.txt +7 -0
  90. karaoke_gen/nextjs_frontend/out/admin/jobs/index.html +1 -0
  91. karaoke_gen/nextjs_frontend/out/admin/jobs/index.txt +25 -0
  92. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._full.txt +25 -0
  93. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._head.txt +8 -0
  94. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._index.txt +9 -0
  95. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._tree.txt +2 -0
  96. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.__PAGE__.txt +9 -0
  97. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.txt +4 -0
  98. karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.txt +7 -0
  99. karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.html +1 -0
  100. karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.txt +25 -0
  101. karaoke_gen/nextjs_frontend/out/admin/searches/__next._full.txt +25 -0
  102. karaoke_gen/nextjs_frontend/out/admin/searches/__next._head.txt +8 -0
  103. karaoke_gen/nextjs_frontend/out/admin/searches/__next._index.txt +9 -0
  104. karaoke_gen/nextjs_frontend/out/admin/searches/__next._tree.txt +2 -0
  105. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.__PAGE__.txt +9 -0
  106. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.txt +4 -0
  107. karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.txt +7 -0
  108. karaoke_gen/nextjs_frontend/out/admin/searches/index.html +1 -0
  109. karaoke_gen/nextjs_frontend/out/admin/searches/index.txt +25 -0
  110. karaoke_gen/nextjs_frontend/out/admin/users/__next._full.txt +25 -0
  111. karaoke_gen/nextjs_frontend/out/admin/users/__next._head.txt +8 -0
  112. karaoke_gen/nextjs_frontend/out/admin/users/__next._index.txt +9 -0
  113. karaoke_gen/nextjs_frontend/out/admin/users/__next._tree.txt +2 -0
  114. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.txt +7 -0
  115. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.__PAGE__.txt +9 -0
  116. karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.txt +4 -0
  117. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._full.txt +25 -0
  118. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._head.txt +8 -0
  119. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._index.txt +9 -0
  120. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._tree.txt +2 -0
  121. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.txt +7 -0
  122. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.__PAGE__.txt +9 -0
  123. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.txt +4 -0
  124. karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.txt +4 -0
  125. karaoke_gen/nextjs_frontend/out/admin/users/detail/index.html +1 -0
  126. karaoke_gen/nextjs_frontend/out/admin/users/detail/index.txt +25 -0
  127. karaoke_gen/nextjs_frontend/out/admin/users/index.html +1 -0
  128. karaoke_gen/nextjs_frontend/out/admin/users/index.txt +25 -0
  129. karaoke_gen/nextjs_frontend/out/app/__next._full.txt +22 -0
  130. karaoke_gen/nextjs_frontend/out/app/__next._head.txt +8 -0
  131. karaoke_gen/nextjs_frontend/out/app/__next._index.txt +9 -0
  132. karaoke_gen/nextjs_frontend/out/app/__next._tree.txt +2 -0
  133. karaoke_gen/nextjs_frontend/out/app/__next.app.__PAGE__.txt +9 -0
  134. karaoke_gen/nextjs_frontend/out/app/__next.app.txt +4 -0
  135. karaoke_gen/nextjs_frontend/out/app/index.html +1 -0
  136. karaoke_gen/nextjs_frontend/out/app/index.txt +22 -0
  137. karaoke_gen/nextjs_frontend/out/app/jobs/__next._full.txt +19 -0
  138. karaoke_gen/nextjs_frontend/out/app/jobs/__next._head.txt +8 -0
  139. karaoke_gen/nextjs_frontend/out/app/jobs/__next._index.txt +9 -0
  140. karaoke_gen/nextjs_frontend/out/app/jobs/__next._tree.txt +2 -0
  141. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  142. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.txt +4 -0
  143. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.txt +4 -0
  144. karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.txt +4 -0
  145. karaoke_gen/nextjs_frontend/out/app/jobs/index.html +1 -0
  146. karaoke_gen/nextjs_frontend/out/app/jobs/index.txt +19 -0
  147. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._full.txt +19 -0
  148. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._head.txt +8 -0
  149. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._index.txt +9 -0
  150. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._tree.txt +2 -0
  151. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  152. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.txt +4 -0
  153. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.txt +4 -0
  154. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.txt +4 -0
  155. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.html +1 -0
  156. karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.txt +19 -0
  157. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._full.txt +19 -0
  158. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._head.txt +8 -0
  159. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._index.txt +9 -0
  160. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._tree.txt +2 -0
  161. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
  162. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.txt +4 -0
  163. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.txt +4 -0
  164. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.txt +4 -0
  165. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.html +1 -0
  166. karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.txt +19 -0
  167. karaoke_gen/nextjs_frontend/out/auth/verify/__next._full.txt +22 -0
  168. karaoke_gen/nextjs_frontend/out/auth/verify/__next._head.txt +8 -0
  169. karaoke_gen/nextjs_frontend/out/auth/verify/__next._index.txt +9 -0
  170. karaoke_gen/nextjs_frontend/out/auth/verify/__next._tree.txt +2 -0
  171. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.txt +4 -0
  172. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.__PAGE__.txt +9 -0
  173. karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.txt +4 -0
  174. karaoke_gen/nextjs_frontend/out/auth/verify/index.html +1 -0
  175. karaoke_gen/nextjs_frontend/out/auth/verify/index.txt +22 -0
  176. karaoke_gen/nextjs_frontend/out/index.html +1 -0
  177. karaoke_gen/nextjs_frontend/out/index.txt +22 -0
  178. karaoke_gen/nextjs_frontend/out/manifest.webmanifest +31 -0
  179. karaoke_gen/nextjs_frontend/out/order/success/__next._full.txt +22 -0
  180. karaoke_gen/nextjs_frontend/out/order/success/__next._head.txt +8 -0
  181. karaoke_gen/nextjs_frontend/out/order/success/__next._index.txt +9 -0
  182. karaoke_gen/nextjs_frontend/out/order/success/__next._tree.txt +2 -0
  183. karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.__PAGE__.txt +9 -0
  184. karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.txt +4 -0
  185. karaoke_gen/nextjs_frontend/out/order/success/__next.order.txt +4 -0
  186. karaoke_gen/nextjs_frontend/out/order/success/index.html +1 -0
  187. karaoke_gen/nextjs_frontend/out/order/success/index.txt +22 -0
  188. karaoke_gen/nextjs_frontend/out/payment/success/__next._full.txt +22 -0
  189. karaoke_gen/nextjs_frontend/out/payment/success/__next._head.txt +8 -0
  190. karaoke_gen/nextjs_frontend/out/payment/success/__next._index.txt +9 -0
  191. karaoke_gen/nextjs_frontend/out/payment/success/__next._tree.txt +2 -0
  192. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.__PAGE__.txt +9 -0
  193. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.txt +4 -0
  194. karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.txt +4 -0
  195. karaoke_gen/nextjs_frontend/out/payment/success/index.html +1 -0
  196. karaoke_gen/nextjs_frontend/out/payment/success/index.txt +22 -0
  197. karaoke_gen/nextjs_frontend/out/screenshots/email-action_reminder.png +0 -0
  198. karaoke_gen/nextjs_frontend/out/screenshots/email-beta_welcome.png +0 -0
  199. karaoke_gen/nextjs_frontend/out/screenshots/email-job_completion.png +0 -0
  200. karaoke_gen/nextjs_frontend/out/screenshots/example-output.avif +0 -0
  201. karaoke_gen/nextjs_frontend/out/screenshots/homepage-full.png +0 -0
  202. karaoke_gen/nextjs_frontend/out/screenshots/homepage-hero.png +0 -0
  203. karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.avif +0 -0
  204. karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.png +0 -0
  205. karaoke_gen/nextjs_frontend/out/screenshots/job-dashboard.avif +0 -0
  206. karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.avif +0 -0
  207. karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.png +0 -0
  208. karaoke_gen/nextjs_frontend/out/sw.js +183 -0
  209. karaoke_gen/utils/cli_args.py +3 -3
  210. karaoke_gen/utils/gen_cli.py +4 -0
  211. karaoke_gen/utils/remote_cli.py +8 -40
  212. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/METADATA +1 -1
  213. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/RECORD +227 -121
  214. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/WHEEL +1 -1
  215. lyrics_transcriber/correction/agentic/agent.py +83 -60
  216. lyrics_transcriber/correction/anchor_sequence.py +48 -3
  217. lyrics_transcriber/correction/corrector.py +92 -58
  218. lyrics_transcriber/review/server.py +165 -33
  219. lyrics_transcriber/utils/tracing.py +214 -0
  220. karaoke_gen/instrumental_review/static/index.html +0 -1721
  221. lyrics_transcriber/frontend/.gitignore +0 -24
  222. lyrics_transcriber/frontend/.yarn/releases/yarn-4.7.0.cjs +0 -935
  223. lyrics_transcriber/frontend/.yarnrc.yml +0 -3
  224. lyrics_transcriber/frontend/README.md +0 -50
  225. lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -210
  226. lyrics_transcriber/frontend/__init__.py +0 -25
  227. lyrics_transcriber/frontend/e2e/agentic-corrections.spec.ts +0 -207
  228. lyrics_transcriber/frontend/e2e/fixtures/agentic-correction-data.json +0 -226
  229. lyrics_transcriber/frontend/eslint.config.js +0 -28
  230. lyrics_transcriber/frontend/index.html +0 -22
  231. lyrics_transcriber/frontend/package-lock.json +0 -4553
  232. lyrics_transcriber/frontend/package.json +0 -48
  233. lyrics_transcriber/frontend/playwright.config.ts +0 -69
  234. lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
  235. lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
  236. lyrics_transcriber/frontend/src/App.tsx +0 -243
  237. lyrics_transcriber/frontend/src/api.ts +0 -262
  238. lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -111
  239. lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -114
  240. lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -204
  241. lyrics_transcriber/frontend/src/components/AppHeader.tsx +0 -65
  242. lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -180
  243. lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -175
  244. lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -359
  245. lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -281
  246. lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -162
  247. lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -257
  248. lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -94
  249. lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -720
  250. lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -592
  251. lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -431
  252. lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -77
  253. lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -467
  254. lyrics_transcriber/frontend/src/components/Header.tsx +0 -520
  255. lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -1526
  256. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +0 -216
  257. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +0 -721
  258. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/UpcomingWordsBar.tsx +0 -80
  259. lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +0 -999
  260. lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -51
  261. lyrics_transcriber/frontend/src/components/ModeSelectionModal.tsx +0 -127
  262. lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -67
  263. lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -23
  264. lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -177
  265. lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -268
  266. lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -336
  267. lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -354
  268. lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -64
  269. lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -383
  270. lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -131
  271. lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -266
  272. lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -191
  273. lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -466
  274. lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -56
  275. lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -89
  276. lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -30
  277. lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -180
  278. lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -13
  279. lyrics_transcriber/frontend/src/components/shared/types.js +0 -2
  280. lyrics_transcriber/frontend/src/components/shared/types.ts +0 -135
  281. lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -177
  282. lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -78
  283. lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -75
  284. lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -360
  285. lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -110
  286. lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -22
  287. lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -537
  288. lyrics_transcriber/frontend/src/main.tsx +0 -11
  289. lyrics_transcriber/frontend/src/theme.ts +0 -406
  290. lyrics_transcriber/frontend/src/types/global.d.ts +0 -9
  291. lyrics_transcriber/frontend/src/types.js +0 -2
  292. lyrics_transcriber/frontend/src/types.ts +0 -199
  293. lyrics_transcriber/frontend/src/validation.ts +0 -132
  294. lyrics_transcriber/frontend/src/vite-env.d.ts +0 -1
  295. lyrics_transcriber/frontend/tsconfig.app.json +0 -26
  296. lyrics_transcriber/frontend/tsconfig.json +0 -25
  297. lyrics_transcriber/frontend/tsconfig.node.json +0 -23
  298. lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -1
  299. lyrics_transcriber/frontend/update_version.js +0 -11
  300. lyrics_transcriber/frontend/vite.config.d.ts +0 -2
  301. lyrics_transcriber/frontend/vite.config.js +0 -15
  302. lyrics_transcriber/frontend/vite.config.ts +0 -16
  303. lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
  304. lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
  305. lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
  306. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js +0 -44465
  307. lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js.map +0 -1
  308. lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
  309. lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
  310. lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
  311. lyrics_transcriber/frontend/web_assets/index.html +0 -22
  312. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
  313. lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.svg +0 -5
  314. lyrics_transcriber/frontend/yarn.lock +0 -3711
  315. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/apple-touch-icon.png +0 -0
  316. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-16x16.png +0 -0
  317. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-32x32.png +0 -0
  318. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon.ico +0 -0
  319. {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/nomad-karaoke-logo.svg +0 -0
  320. /lyrics_transcriber/frontend/public/nomad-karaoke-logo.png → /karaoke_gen/nextjs_frontend/out/nomad-logo.png +0 -0
  321. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/entry_points.txt +0 -0
  322. {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/licenses/LICENSE +0 -0
@@ -10,7 +10,6 @@ Similar pattern to LyricsTranscriber's ReviewServer.
10
10
 
11
11
  import logging
12
12
  import os
13
- from pathlib import Path
14
13
  import socket
15
14
  import threading
16
15
  import webbrowser
@@ -18,7 +17,7 @@ from typing import List, Optional
18
17
 
19
18
  from fastapi import FastAPI, HTTPException, UploadFile, File
20
19
  from fastapi.middleware.cors import CORSMiddleware
21
- from fastapi.responses import FileResponse, HTMLResponse
20
+ from fastapi.responses import FileResponse
22
21
  from pydantic import BaseModel
23
22
  import shutil
24
23
  import tempfile
@@ -104,7 +103,7 @@ class InstrumentalReviewServer:
104
103
  def _create_app(self) -> FastAPI:
105
104
  """Create and configure the FastAPI application."""
106
105
  app = FastAPI(title="Instrumental Review", docs_url=None, redoc_url=None)
107
-
106
+
108
107
  # Configure CORS
109
108
  app.add_middleware(
110
109
  CORSMiddleware,
@@ -113,19 +112,138 @@ class InstrumentalReviewServer:
113
112
  allow_methods=["*"],
114
113
  allow_headers=["*"],
115
114
  )
116
-
115
+
116
+ # Determine which frontend to use
117
+ self._use_nextjs_frontend = self._setup_nextjs_frontend(app)
118
+
117
119
  # Register routes
118
120
  self._register_routes(app)
119
-
121
+
120
122
  return app
123
+
124
+ def _setup_nextjs_frontend(self, app: FastAPI) -> bool:
125
+ """Set up the unified Next.js frontend.
126
+
127
+ Returns True if Next.js frontend is set up successfully.
128
+ Raises FileNotFoundError if Next.js assets are not available.
129
+ """
130
+ import os
131
+ from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir, is_nextjs_frontend_available
132
+
133
+ if not is_nextjs_frontend_available():
134
+ raise FileNotFoundError(
135
+ "Next.js frontend assets not found. Please ensure the frontend is built "
136
+ "and copied to karaoke_gen/nextjs_frontend/out/"
137
+ )
138
+
139
+ frontend_dir = str(get_nextjs_assets_dir())
140
+ logger.info(f"Using Next.js frontend from {frontend_dir}")
141
+
142
+ # Mount static files for Next.js assets
143
+ from fastapi.staticfiles import StaticFiles
144
+ app.mount("/_next", StaticFiles(directory=os.path.join(frontend_dir, "_next")), name="nextjs_static")
145
+
146
+ return True
121
147
 
122
148
  def _register_routes(self, app: FastAPI) -> None:
123
149
  """Register API routes."""
124
-
150
+
125
151
  @app.get("/")
126
152
  async def serve_frontend():
127
- """Serve the frontend HTML."""
128
- return HTMLResponse(content=self._get_frontend_html())
153
+ """Redirect to Next.js instrumental review route."""
154
+ from fastapi.responses import RedirectResponse
155
+ return RedirectResponse(url="/app/jobs/local/instrumental", status_code=302)
156
+
157
+ # Local instrumental route - serve pre-rendered HTML for local mode
158
+ @app.get("/app/jobs/local/instrumental")
159
+ async def serve_local_instrumental():
160
+ """Serve pre-rendered local instrumental page with patched chunk loading."""
161
+ from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir
162
+ from fastapi.responses import HTMLResponse
163
+ import glob
164
+ frontend_dir = get_nextjs_assets_dir()
165
+ if frontend_dir:
166
+ import os
167
+ local_instrumental_html = os.path.join(str(frontend_dir), "app", "jobs", "local", "instrumental", "index.html")
168
+ if os.path.exists(local_instrumental_html):
169
+ # Read the HTML and inject the missing chunk script
170
+ # This works around a Turbopack static export issue
171
+ with open(local_instrumental_html, 'r', encoding='utf-8') as f:
172
+ html_content = f.read()
173
+
174
+ # Find the chunk containing module 78280 (JobRouterClient)
175
+ chunks_dir = os.path.join(str(frontend_dir), "_next", "static", "chunks")
176
+ for chunk_file in glob.glob(os.path.join(chunks_dir, "*.js")):
177
+ chunk_name = os.path.basename(chunk_file)
178
+ with open(chunk_file, 'r', encoding='utf-8') as cf:
179
+ chunk_content = cf.read(500)
180
+ if ",78280," in chunk_content:
181
+ script_tag = f'<script src="/_next/static/chunks/{chunk_name}" async=""></script>'
182
+ if chunk_name not in html_content:
183
+ html_content = html_content.replace('</head>', f'{script_tag}</head>')
184
+ break
185
+
186
+ return HTMLResponse(content=html_content, media_type="text/html")
187
+ # Fallback to jobs index
188
+ jobs_html = os.path.join(str(frontend_dir), "app", "jobs", "index.html")
189
+ if os.path.exists(jobs_html):
190
+ return FileResponse(jobs_html, media_type="text/html")
191
+ raise HTTPException(status_code=404, detail="Instrumental page not found")
192
+
193
+ # Job routes - serve the jobs page HTML for client-side routing
194
+ @app.get("/app/jobs/{full_path:path}")
195
+ async def serve_jobs_routes(full_path: str):
196
+ """Serve jobs index.html for all /app/jobs/* routes (SPA routing)."""
197
+ from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir
198
+ frontend_dir = get_nextjs_assets_dir()
199
+ if frontend_dir:
200
+ import os
201
+ jobs_html = os.path.join(str(frontend_dir), "app", "jobs", "index.html")
202
+ if os.path.exists(jobs_html):
203
+ return FileResponse(jobs_html, media_type="text/html")
204
+ raise HTTPException(status_code=404, detail="Jobs page not found")
205
+
206
+ # Other app routes - serve the app index.html
207
+ @app.get("/app/{full_path:path}")
208
+ async def serve_app_routes(full_path: str):
209
+ """Serve app index.html for other /app/* routes."""
210
+ from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir
211
+ frontend_dir = get_nextjs_assets_dir()
212
+ if frontend_dir:
213
+ import os
214
+ app_html = os.path.join(str(frontend_dir), "app", "index.html")
215
+ if os.path.exists(app_html):
216
+ return FileResponse(app_html, media_type="text/html")
217
+ # Fallback to root index.html
218
+ index_html = os.path.join(str(frontend_dir), "index.html")
219
+ if os.path.exists(index_html):
220
+ return FileResponse(index_html, media_type="text/html")
221
+ raise HTTPException(status_code=404, detail="Frontend not found")
222
+
223
+ # Tenant config endpoint (returns default config for local mode)
224
+ @app.get("/api/tenant/config")
225
+ async def get_tenant_config():
226
+ """Get tenant configuration for local mode."""
227
+ return {
228
+ "tenant": None,
229
+ "is_default": True
230
+ }
231
+
232
+ # Mock job endpoint for local mode (required by unified frontend)
233
+ @app.get("/api/jobs/local")
234
+ async def get_local_job():
235
+ """Get mock job data for local mode."""
236
+ return {
237
+ "job_id": "local",
238
+ "status": "awaiting_instrumental_selection",
239
+ "progress": 50,
240
+ "created_at": None,
241
+ "updated_at": None,
242
+ "artist": self.base_name.split(" - ")[0] if " - " in self.base_name else "",
243
+ "title": self.base_name.split(" - ")[1] if " - " in self.base_name else self.base_name,
244
+ "user_email": "local@localhost",
245
+ "audio_hash": "local",
246
+ }
129
247
 
130
248
  @app.get("/api/jobs/local/instrumental-analysis")
131
249
  async def get_analysis():
@@ -188,9 +306,8 @@ class InstrumentalReviewServer:
188
306
  logger.exception(f"Error generating waveform data: {e}")
189
307
  raise HTTPException(status_code=500, detail=str(e)) from e
190
308
 
191
- @app.get("/api/audio/{stem_type}")
192
- async def stream_audio(stem_type: str):
193
- """Stream audio file."""
309
+ def _get_audio_path(stem_type: str) -> Optional[str]:
310
+ """Get the path for a given stem type."""
194
311
  path_map = {
195
312
  "clean_instrumental": self.clean_instrumental_path,
196
313
  "backing_vocals": self.backing_vocals_path,
@@ -199,11 +316,14 @@ class InstrumentalReviewServer:
199
316
  "uploaded_instrumental": self.uploaded_instrumental_path,
200
317
  "original": self.original_audio_path,
201
318
  }
202
-
203
- audio_path = path_map.get(stem_type)
319
+ return path_map.get(stem_type)
320
+
321
+ def _stream_audio_file(stem_type: str):
322
+ """Stream an audio file by stem type."""
323
+ audio_path = _get_audio_path(stem_type)
204
324
  if not audio_path or not os.path.exists(audio_path):
205
325
  raise HTTPException(status_code=404, detail=f"Audio file not found: {stem_type}")
206
-
326
+
207
327
  # Determine content type
208
328
  ext = os.path.splitext(audio_path)[1].lower()
209
329
  content_types = {
@@ -212,8 +332,18 @@ class InstrumentalReviewServer:
212
332
  ".wav": "audio/wav",
213
333
  }
214
334
  content_type = content_types.get(ext, "application/octet-stream")
215
-
335
+
216
336
  return FileResponse(audio_path, media_type=content_type)
337
+
338
+ @app.get("/api/audio/{stem_type}")
339
+ async def stream_audio(stem_type: str):
340
+ """Stream audio file (legacy route)."""
341
+ return _stream_audio_file(stem_type)
342
+
343
+ @app.get("/api/jobs/{job_id}/audio-stream/{stem_type}")
344
+ async def stream_audio_cloud(job_id: str, stem_type: str):
345
+ """Stream audio file (cloud-compatible route)."""
346
+ return _stream_audio_file(stem_type)
217
347
 
218
348
  @app.get("/api/waveform")
219
349
  async def get_waveform_image():
@@ -338,26 +468,6 @@ class InstrumentalReviewServer:
338
468
 
339
469
  return {"status": "success", "selection": request.selection}
340
470
 
341
- @staticmethod
342
- def _get_static_dir() -> Path:
343
- """Get the path to the static assets directory."""
344
- return Path(__file__).parent / "static"
345
-
346
- def _get_frontend_html(self) -> str:
347
- """Return the frontend HTML by reading from the static file."""
348
- static_file = self._get_static_dir() / "index.html"
349
- if static_file.exists():
350
- return static_file.read_text(encoding="utf-8")
351
- else:
352
- # Fallback error message if file is missing
353
- return """<!DOCTYPE html>
354
- <html>
355
- <head><title>Error</title></head>
356
- <body style="background:#1a1a1a;color:#fff;font-family:sans-serif;padding:2rem;">
357
- <h1>Frontend assets not found</h1>
358
- <p>The static/index.html file is missing from the instrumental_review module.</p>
359
- </body>
360
- </html>"""
361
471
 
362
472
  @staticmethod
363
473
  def _is_port_available(host: str, port: int) -> bool:
@@ -0,0 +1,98 @@
1
+ """Next.js frontend module for karaoke-gen unified web interface.
2
+
3
+ This module provides utilities for serving the consolidated Next.js frontend
4
+ for both lyrics review and instrumental selection in local CLI mode.
5
+
6
+ The Next.js frontend is built with `npm run build` in the frontend/ directory
7
+ and produces a static export in frontend/out/ which can be served by the
8
+ local review servers.
9
+ """
10
+
11
+ import os
12
+ from pathlib import Path
13
+ from typing import Optional
14
+
15
+
16
+ # Get the directory containing this module
17
+ _MODULE_DIR = Path(__file__).parent.absolute()
18
+
19
+ # The Next.js static export location relative to the repo root
20
+ # When packaged, it will be at karaoke_gen/nextjs_frontend/out/
21
+ # In development, it's at frontend/out/
22
+ _PACKAGED_DIR = _MODULE_DIR / "out"
23
+ _DEV_DIR = _MODULE_DIR.parent.parent / "frontend" / "out"
24
+
25
+
26
+ def get_nextjs_assets_dir() -> Optional[Path]:
27
+ """Get the path to the Next.js static export directory.
28
+
29
+ Returns:
30
+ Path to the frontend/out directory containing the Next.js static export,
31
+ or None if the assets are not available.
32
+ """
33
+ # Check packaged location first
34
+ if _PACKAGED_DIR.exists() and (_PACKAGED_DIR / "index.html").exists():
35
+ return _PACKAGED_DIR
36
+
37
+ # Check development location
38
+ if _DEV_DIR.exists() and (_DEV_DIR / "index.html").exists():
39
+ return _DEV_DIR
40
+
41
+ return None
42
+
43
+
44
+ def is_nextjs_frontend_available() -> bool:
45
+ """Check if the Next.js frontend is available for serving."""
46
+ return get_nextjs_assets_dir() is not None
47
+
48
+
49
+ def get_spa_index_html(assets_dir: Path) -> Path:
50
+ """Get the path to the SPA index.html file for routing."""
51
+ return assets_dir / "index.html"
52
+
53
+
54
+ def get_route_html_path(assets_dir: Path, route: str) -> Optional[Path]:
55
+ """Get the path to a specific route's HTML file.
56
+
57
+ For Next.js static export, routes like /app/jobs/local/review
58
+ are pre-rendered to /app/jobs/[...slug].html or similar.
59
+
60
+ Args:
61
+ assets_dir: Path to the Next.js static export directory
62
+ route: The URL route being requested (e.g., "/app/jobs/local/review")
63
+
64
+ Returns:
65
+ Path to the HTML file for this route, or None if not found.
66
+ """
67
+ # Clean the route
68
+ route = route.strip("/")
69
+ if not route:
70
+ return assets_dir / "index.html"
71
+
72
+ # Try exact path match first
73
+ exact_path = assets_dir / route / "index.html"
74
+ if exact_path.exists():
75
+ return exact_path
76
+
77
+ # Try .html extension
78
+ html_path = assets_dir / f"{route}.html"
79
+ if html_path.exists():
80
+ return html_path
81
+
82
+ # For dynamic routes like /app/jobs/[[...slug]],
83
+ # Next.js creates /app/jobs.html or /app/jobs/[[...slug]].html
84
+ # We need to fall back to the catch-all route
85
+ parts = route.split("/")
86
+ for i in range(len(parts), 0, -1):
87
+ parent = "/".join(parts[:i])
88
+ # Try the [...slug] catch-all pattern
89
+ catch_all = assets_dir / parent / "[[...slug]].html"
90
+ if catch_all.exists():
91
+ return catch_all
92
+ # Try parent index
93
+ parent_index = assets_dir / parent / "index.html"
94
+ if parent_index.exists():
95
+ return parent_index
96
+
97
+ # Fallback to main index.html for SPA routing
98
+ return assets_dir / "index.html"
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><!--zpw__rjFIDV5tlPPtnvRI--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/5628d92b5893add2.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/95f7e5934dbb0e5d.js"/><script src="/_next/static/chunks/112f346e31f991df.js" async=""></script><script src="/_next/static/chunks/a9ed54eed3e14c92.js" async=""></script><script src="/_next/static/chunks/c645af7d6b65f73e.js" async=""></script><script src="/_next/static/chunks/5997132b61dec430.js" async=""></script><script src="/_next/static/chunks/turbopack-2d9ca3017a9deedf.js" async=""></script><script src="/_next/static/chunks/ef02697fb404726a.js" async=""></script><script src="/_next/static/chunks/e483af34fc792d38.js" async=""></script><script src="/_next/static/chunks/247eb132b7f7b574.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Nomad Karaoke: Generator</title><meta name="description" content="Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"/><link rel="manifest" href="/manifest.webmanifest"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="font-sans antialiased" style="background:var(--bg);color:var(--text)"><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","dark",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/95f7e5934dbb0e5d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[72285,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ServiceWorkerRegistration\"]\n3:I[89554,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ThemeProvider\"]\n4:I[57091,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"TenantProvider\"]\n5:I[48030,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ImpersonationBannerWrapper\"]\n6:I[39756,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n8:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ViewportBoundary\"]\nd:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"MetadataBoundary\"]\nf:I[68027,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n:HL[\"/_next/static/chunks/5628d92b5893add2.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"zpw_-rjFIDV5tlPPtnvRI\",\"c\":[\"\",\"_not-found\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/5628d92b5893add2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/ef02697fb404726a.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/e483af34fc792d38.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/247eb132b7f7b574.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"font-sans antialiased\",\"style\":{\"background\":\"var(--bg)\",\"color\":\"var(--text)\"},\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"$L3\",null,{\"attribute\":\"class\",\"defaultTheme\":\"dark\",\"enableSystem\":true,\"disableTransitionOnChange\":true,\"children\":[\"$\",\"$L4\",null,{\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$Lb\",null,{\"children\":\"$@c\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$@e\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[27201,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"IconMark\"]\ne:[[\"$\",\"title\",\"0\",{\"children\":\"Nomad Karaoke: Generator\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/manifest.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$L10\",\"7\",{}]]\na:null\n"])</script></body></html>
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><!--zpw__rjFIDV5tlPPtnvRI--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/5628d92b5893add2.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/95f7e5934dbb0e5d.js"/><script src="/_next/static/chunks/112f346e31f991df.js" async=""></script><script src="/_next/static/chunks/a9ed54eed3e14c92.js" async=""></script><script src="/_next/static/chunks/c645af7d6b65f73e.js" async=""></script><script src="/_next/static/chunks/5997132b61dec430.js" async=""></script><script src="/_next/static/chunks/turbopack-2d9ca3017a9deedf.js" async=""></script><script src="/_next/static/chunks/ef02697fb404726a.js" async=""></script><script src="/_next/static/chunks/e483af34fc792d38.js" async=""></script><script src="/_next/static/chunks/247eb132b7f7b574.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Nomad Karaoke: Generator</title><meta name="description" content="Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"/><link rel="manifest" href="/manifest.webmanifest"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="font-sans antialiased" style="background:var(--bg);color:var(--text)"><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","dark",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/95f7e5934dbb0e5d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[72285,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ServiceWorkerRegistration\"]\n3:I[89554,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ThemeProvider\"]\n4:I[57091,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"TenantProvider\"]\n5:I[48030,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ImpersonationBannerWrapper\"]\n6:I[39756,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n8:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ViewportBoundary\"]\nd:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"MetadataBoundary\"]\nf:I[68027,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n:HL[\"/_next/static/chunks/5628d92b5893add2.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"zpw_-rjFIDV5tlPPtnvRI\",\"c\":[\"\",\"_not-found\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/5628d92b5893add2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/ef02697fb404726a.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/e483af34fc792d38.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/247eb132b7f7b574.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"font-sans antialiased\",\"style\":{\"background\":\"var(--bg)\",\"color\":\"var(--text)\"},\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"$L3\",null,{\"attribute\":\"class\",\"defaultTheme\":\"dark\",\"enableSystem\":true,\"disableTransitionOnChange\":true,\"children\":[\"$\",\"$L4\",null,{\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$Lb\",null,{\"children\":\"$@c\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$@e\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[27201,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"IconMark\"]\ne:[[\"$\",\"title\",\"0\",{\"children\":\"Nomad Karaoke: Generator\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/manifest.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$L10\",\"7\",{}]]\na:null\n"])</script></body></html>
@@ -0,0 +1,9 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[47257,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ClientPageRoot"]
3
+ 3:I[31713,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js","/_next/static/chunks/55c5ade44387bef8.js","/_next/static/chunks/692f5d9e0d700c76.js","/_next/static/chunks/dcde6ed684dacd0e.js"],"default"]
4
+ 6:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"OutletBoundary"]
5
+ 7:"$Sreact.suspense"
6
+ 0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/55c5ade44387bef8.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/692f5d9e0d700c76.js","async":true}],["$","script","script-2",{"src":"/_next/static/chunks/dcde6ed684dacd0e.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
7
+ 4:{}
8
+ 5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
9
+ 8:null
@@ -0,0 +1,22 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[72285,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ServiceWorkerRegistration"]
3
+ 3:I[89554,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ThemeProvider"]
4
+ 4:I[57091,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"TenantProvider"]
5
+ 5:I[48030,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ImpersonationBannerWrapper"]
6
+ 6:I[39756,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
7
+ 7:I[37457,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
8
+ 8:I[47257,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ClientPageRoot"]
9
+ 9:I[31713,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js","/_next/static/chunks/55c5ade44387bef8.js","/_next/static/chunks/692f5d9e0d700c76.js","/_next/static/chunks/dcde6ed684dacd0e.js"],"default"]
10
+ c:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"OutletBoundary"]
11
+ d:"$Sreact.suspense"
12
+ f:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ViewportBoundary"]
13
+ 11:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"MetadataBoundary"]
14
+ 13:I[68027,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
15
+ :HL["/_next/static/chunks/5628d92b5893add2.css","style"]
16
+ 0:{"P":null,"b":"zpw_-rjFIDV5tlPPtnvRI","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/5628d92b5893add2.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/01a7f8fe40f1ff47.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/e483af34fc792d38.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"font-sans antialiased","style":{"background":"var(--bg)","color":"var(--text)"},"children":[["$","$L2",null,{}],["$","$L3",null,{"attribute":"class","defaultTheme":"dark","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L4",null,{"children":[["$","$L5",null,{}],["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]]}]}]]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L8",null,{"Component":"$9","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@a","$@b"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/55c5ade44387bef8.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/692f5d9e0d700c76.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/_next/static/chunks/dcde6ed684dacd0e.js","async":true,"nonce":"$undefined"}]],["$","$Lc",null,{"children":["$","$d",null,{"name":"Next.MetadataOutlet","children":"$@e"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lf",null,{"children":"$@10"}],["$","div",null,{"hidden":true,"children":["$","$L11",null,{"children":["$","$d",null,{"name":"Next.Metadata","children":"$@12"}]}]}],null]}],false]],"m":"$undefined","G":["$13",[]],"S":true}
17
+ a:{}
18
+ b:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
19
+ 10:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
20
+ 14:I[27201,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"IconMark"]
21
+ 12:[["$","title","0",{"children":"Nomad Karaoke: Generator"}],["$","meta","1",{"name":"description","content":"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"}],["$","link","2",{"rel":"manifest","href":"/manifest.webmanifest","crossOrigin":"$undefined"}],["$","link","3",{"rel":"icon","href":"/favicon.ico","sizes":"any"}],["$","link","4",{"rel":"icon","href":"/favicon-16x16.png","sizes":"16x16","type":"image/png"}],["$","link","5",{"rel":"icon","href":"/favicon-32x32.png","sizes":"32x32","type":"image/png"}],["$","link","6",{"rel":"apple-touch-icon","href":"/apple-touch-icon.png"}],["$","$L14","7",{}]]
22
+ e:null
@@ -0,0 +1,8 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ViewportBoundary"]
3
+ 4:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"MetadataBoundary"]
4
+ 5:"$Sreact.suspense"
5
+ 7:I[27201,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"IconMark"]
6
+ 0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":"$@3"}],["$","div",null,{"hidden":true,"children":["$","$L4",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$@6"}]}]}],null]}],"loading":null,"isPartial":false}
7
+ 3:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
8
+ 6:[["$","title","0",{"children":"Nomad Karaoke: Generator"}],["$","meta","1",{"name":"description","content":"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"}],["$","link","2",{"rel":"manifest","href":"/manifest.webmanifest"}],["$","link","3",{"rel":"icon","href":"/favicon.ico","sizes":"any"}],["$","link","4",{"rel":"icon","href":"/favicon-16x16.png","sizes":"16x16","type":"image/png"}],["$","link","5",{"rel":"icon","href":"/favicon-32x32.png","sizes":"32x32","type":"image/png"}],["$","link","6",{"rel":"apple-touch-icon","href":"/apple-touch-icon.png"}],["$","$L7","7",{}]]
@@ -0,0 +1,9 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[72285,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ServiceWorkerRegistration"]
3
+ 3:I[89554,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ThemeProvider"]
4
+ 4:I[57091,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"TenantProvider"]
5
+ 5:I[48030,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ImpersonationBannerWrapper"]
6
+ 6:I[39756,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
7
+ 7:I[37457,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
8
+ :HL["/_next/static/chunks/5628d92b5893add2.css","style"]
9
+ 0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/5628d92b5893add2.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/01a7f8fe40f1ff47.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/e483af34fc792d38.js","async":true}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"font-sans antialiased","style":{"background":"var(--bg)","color":"var(--text)"},"children":[["$","$L2",null,{}],["$","$L3",null,{"attribute":"class","defaultTheme":"dark","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L4",null,{"children":[["$","$L5",null,{}],["$","$L6",null,{"parallelRouterKey":"children","template":["$","$L7",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]]}]}]]}]}]]}],"loading":null,"isPartial":false}
@@ -0,0 +1,2 @@
1
+ :HL["/_next/static/chunks/5628d92b5893add2.css","style"]
2
+ 0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
@@ -0,0 +1 @@
1
+ (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,41947,e=>{"use strict";let t=(0,e.i(75254).default)("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);e.s(["default",()=>t])},37727,e=>{"use strict";var t=e.i(41947);e.s(["X",()=>t.default])},54858,e=>{"use strict";var t=e.i(47167);let a="localhost"===window.location.hostname?"":t.default.env.NEXT_PUBLIC_API_URL||"https://api.nomadkaraoke.com";function r(e){localStorage.setItem("karaoke_access_token",e)}function i(){return localStorage.getItem("karaoke_access_token")}function n(){localStorage.removeItem("karaoke_access_token")}function s(){let e={},t=i();return t&&(e.Authorization=`Bearer ${t}`),e}class o extends Error{status;data;constructor(e,t,a){super(e),this.name="ApiError",this.status=t,this.data=a}}async function l(e){if(!e.ok){let t;try{t=await e.json()}catch{t={detail:e.statusText}}throw new o(function(e,t){if("string"==typeof e?.detail)return e.detail;if("string"==typeof e?.message)return e.message;if("string"==typeof e?.error)return e.error;if(e?.detail?.message)return String(e.detail.message);if(e?.detail?.error)return String(e.detail.error);if(e?.detail&&"object"==typeof e.detail)try{return JSON.stringify(e.detail)}catch{}return t}(t,`Request failed with status ${e.status}`),e.status,t)}return e.json()}function c(e){return{async submitCorrections(t){let r=await fetch(`${a}/api/jobs/${e}/corrections`,{method:"PUT",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)});await l(r)},async submitAnnotations(t){let r=await fetch(`${a}/api/jobs/${e}/annotations`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({annotations:t})});await l(r)},updateHandlers:async t=>l(await fetch(`${a}/api/jobs/${e}/handlers`,{method:"PATCH",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({enabled_handlers:t})})),addLyrics:async(t,r)=>l(await fetch(`${a}/api/jobs/${e}/lyrics`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({source:t,lyrics:r})})),getAudioUrl(e){let t=i(),r=`${a}/api/audio/${e}`;return t?`${r}?token=${encodeURIComponent(t)}`:r},generatePreviewVideo:async t=>l(await fetch(`${a}/api/jobs/${e}/preview-video`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)})),getPreviewVideoUrl(e){let t=i(),r=`${a}/api/preview-video/${e}`;return t?`${r}?token=${encodeURIComponent(t)}`:r}}}e.s(["API_BASE_URL",0,a,"ApiError",()=>o,"adminApi",0,{async getStats(e){let t=new URLSearchParams;e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/admin/stats/overview${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},async listUsers(e){let t=new URLSearchParams;e?.limit&&t.set("limit",String(e.limit)),e?.offset&&t.set("offset",String(e.offset)),e?.search&&t.set("search",e.search),e?.sort_by&&t.set("sort_by",e.sort_by),e?.sort_order&&t.set("sort_order",e.sort_order),e?.include_inactive&&t.set("include_inactive","true"),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/users/admin/users${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},getUserDetail:async e=>l(await fetch(`${a}/api/users/admin/users/${encodeURIComponent(e)}/detail`,{headers:s()})),addCredits:async(e,t,r)=>l(await fetch(`${a}/api/users/admin/credits`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({email:e,amount:t,reason:r})})),impersonateUser:async e=>l(await fetch(`${a}/api/admin/users/${encodeURIComponent(e)}/impersonate`,{method:"POST",headers:s()})),enableUser:async e=>l(await fetch(`${a}/api/users/admin/users/${encodeURIComponent(e)}/enable`,{method:"POST",headers:s()})),disableUser:async e=>l(await fetch(`${a}/api/users/admin/users/${encodeURIComponent(e)}/disable`,{method:"POST",headers:s()})),async listAllJobs(e){let t=new URLSearchParams;e?.status&&t.set("status",e.status),e?.user_email&&t.set("user_email",e.user_email),e?.environment&&t.set("environment",e.environment),e?.created_after&&t.set("created_after",e.created_after),e?.created_before&&t.set("created_before",e.created_before),e?.limit&&t.set("limit",String(e.limit)),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/jobs${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},async getBetaStats(e){let t=new URLSearchParams;e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/users/admin/beta/stats${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},getBetaFeedback:async(e=50)=>l(await fetch(`${a}/api/users/admin/beta/feedback?limit=${e}`,{headers:s()})),deleteJob:async(e,t=!0)=>l(await fetch(`${a}/api/jobs/${e}?delete_files=${t}`,{method:"DELETE",headers:s()})),async listAudioSearches(e){let t=new URLSearchParams;e?.limit&&t.set("limit",String(e.limit)),e?.status_filter&&t.set("status_filter",e.status_filter),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/admin/audio-searches${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},clearAudioSearchCache:async e=>l(await fetch(`${a}/api/admin/audio-searches/${e}/clear-cache`,{method:"POST",headers:s()})),clearAllCache:async()=>l(await fetch(`${a}/api/admin/cache`,{method:"DELETE",headers:s()})),getCacheStats:async()=>l(await fetch(`${a}/api/admin/cache/stats`,{headers:s()})),getCompletionMessage:async e=>l(await fetch(`${a}/api/admin/jobs/${e}/completion-message`,{headers:s()})),sendCompletionEmail:async(e,t,r=!0)=>l(await fetch(`${a}/api/admin/jobs/${e}/send-completion-email`,{method:"POST",headers:{...s(),"Content-Type":"application/json"},body:JSON.stringify({to_email:t,cc_admin:r})})),getJobFiles:async e=>l(await fetch(`${a}/api/admin/jobs/${e}/files`,{headers:s()})),updateJob:async(e,t)=>l(await fetch(`${a}/api/admin/jobs/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)})),resetJob:async(e,t)=>l(await fetch(`${a}/api/admin/jobs/${e}/reset`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({target_state:t})})),deleteJobOutputs:async e=>l(await fetch(`${a}/api/admin/jobs/${e}/delete-outputs`,{method:"POST",headers:s()})),getRateLimitStats:async()=>l(await fetch(`${a}/api/admin/rate-limits/stats`,{headers:s()})),getUserRateLimitStatus:async e=>l(await fetch(`${a}/api/admin/rate-limits/users/${encodeURIComponent(e)}`,{headers:s()})),getBlocklists:async()=>l(await fetch(`${a}/api/admin/rate-limits/blocklists`,{headers:s()})),addDisposableDomain:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/disposable-domains`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({domain:e})})),removeDisposableDomain:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/disposable-domains/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()})),addBlockedEmail:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-emails`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({email:e})})),removeBlockedEmail:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-emails/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()})),addBlockedIP:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-ips`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({ip_address:e})})),removeBlockedIP:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-ips/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()})),getUserOverrides:async()=>l(await fetch(`${a}/api/admin/rate-limits/overrides`,{headers:s()})),setUserOverride:async(e,t)=>l(await fetch(`${a}/api/admin/rate-limits/overrides/${encodeURIComponent(e)}`,{method:"PUT",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)})),removeUserOverride:async e=>l(await fetch(`${a}/api/admin/rate-limits/overrides/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()}))},"api",0,{async listJobs(e){let t=new URLSearchParams;e?.status&&t.set("status",e.status),e?.limit&&t.set("limit",String(e.limit)),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/jobs${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},getJob:async e=>l(await fetch(`${a}/api/jobs/${e}`,{headers:s()})),async uploadJob(e,t,r,i){let n=new FormData;return n.append("file",e),n.append("artist",t),n.append("title",r),i?.enable_cdg!==void 0&&n.append("enable_cdg",String(i.enable_cdg)),i?.enable_txt!==void 0&&n.append("enable_txt",String(i.enable_txt)),i?.brand_prefix&&n.append("brand_prefix",i.brand_prefix),i?.enable_youtube_upload!==void 0&&n.append("enable_youtube_upload",String(i.enable_youtube_upload)),i?.theme_id&&n.append("theme_id",i.theme_id),i?.color_overrides&&n.append("color_overrides",JSON.stringify(i.color_overrides)),i?.non_interactive!==void 0&&n.append("non_interactive",String(i.non_interactive)),l(await fetch(`${a}/api/jobs/upload`,{method:"POST",headers:s(),body:n}))},async createJobFromUrl(e,t,r,i){let n={url:e};return t&&(n.artist=t),r&&(n.title=r),i?.enable_cdg!==void 0&&(n.enable_cdg=i.enable_cdg),i?.enable_txt!==void 0&&(n.enable_txt=i.enable_txt),i?.brand_prefix&&(n.brand_prefix=i.brand_prefix),i?.enable_youtube_upload!==void 0&&(n.enable_youtube_upload=i.enable_youtube_upload),i?.theme_id&&(n.theme_id=i.theme_id),i?.color_overrides&&(n.color_overrides=i.color_overrides),i?.non_interactive!==void 0&&(n.non_interactive=i.non_interactive),l(await fetch(`${a}/api/jobs/create-from-url`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(n)}))},getReviewData:async e=>l(await fetch(`${a}/api/jobs/${e}/review-data`,{headers:s()})),completeReview:async e=>l(await fetch(`${a}/api/jobs/${e}/complete-review`,{method:"POST",headers:s()})),getInstrumentalOptions:async e=>l(await fetch(`${a}/api/jobs/${e}/instrumental-options`,{headers:s()})),selectInstrumental:async(e,t)=>l(await fetch(`${a}/api/jobs/${e}/select-instrumental`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({selection:t})})),getInstrumentalAnalysis:async e=>l(await fetch(`${a}/api/jobs/${e}/instrumental-analysis`,{headers:s()})),getWaveformData:async(e,t=1e3)=>l(await fetch(`${a}/api/jobs/${e}/waveform-data?num_points=${t}`,{headers:s()})),async uploadCustomInstrumental(e,t){let r=new FormData;return r.append("file",t),l(await fetch(`${a}/api/jobs/${e}/upload-instrumental`,{method:"POST",headers:s(),body:r}))},createCustomInstrumental:async(e,t)=>l(await fetch(`${a}/api/jobs/${e}/create-custom-instrumental`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({mute_regions:t})})),getAudioStreamUrl(e,t){let r=i(),n=`${a}/api/jobs/${e}/audio-stream/${t}`;return r?`${n}?token=${encodeURIComponent(r)}`:n},getDownloadUrls:async e=>l(await fetch(`${a}/api/jobs/${e}/download-urls`,{headers:s()})),cancelJob:async(e,t)=>l(await fetch(`${a}/api/jobs/${e}/cancel`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({reason:t||"Cancelled by user"})})),deleteJob:async(e,t=!0)=>l(await fetch(`${a}/api/jobs/${e}?delete_files=${t}`,{method:"DELETE",headers:s()})),getDownloadUrl(e,t,r){let n=`${a}/api/jobs/${e}/download/${t}/${r}`,s=i();return s?`${n}?token=${encodeURIComponent(s)}`:n},async searchAudio(e,t,r=!1,i){let n={artist:e,title:t,auto_download:r};return i?.enable_cdg!==void 0&&(n.enable_cdg=i.enable_cdg),i?.enable_txt!==void 0&&(n.enable_txt=i.enable_txt),i?.brand_prefix&&(n.brand_prefix=i.brand_prefix),i?.enable_youtube_upload!==void 0&&(n.enable_youtube_upload=i.enable_youtube_upload),i?.theme_id&&(n.theme_id=i.theme_id),i?.color_overrides&&(n.color_overrides=i.color_overrides),i?.non_interactive!==void 0&&(n.non_interactive=i.non_interactive),i?.display_artist&&(n.display_artist=i.display_artist),i?.display_title&&(n.display_title=i.display_title),l(await fetch(`${a}/api/audio-search/search`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(n)}))},getAudioSearchResults:async e=>l(await fetch(`${a}/api/audio-search/${e}/results`,{headers:s()})),selectAudioResult:async(e,t)=>l(await fetch(`${a}/api/audio-search/${e}/select`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({selection_index:t})})),async getJobLogs(e,t=100){let r=await fetch(`${a}/api/jobs/${e}/logs?limit=${t}`,{headers:s()});return(await l(r)).logs||[]},retryJob:async e=>l(await fetch(`${a}/api/jobs/${e}/retry`,{method:"POST",headers:s()})),async listThemes(){let e=await fetch(`${a}/api/themes`,{headers:s()});return(await l(e)).themes},async getTheme(e){let t=await fetch(`${a}/api/themes/${e}`,{headers:s()});return(await l(t)).theme},async getThemePreview(e){let t=await fetch(`${a}/api/themes/${e}/preview`,{headers:s()});return(await l(t)).preview_url},async getThemeYoutubeDescription(e){let t=await fetch(`${a}/api/themes/${e}/youtube-description`,{headers:s()});return(await l(t)).description},sendMagicLink:async e=>l(await fetch(`${a}/api/users/auth/magic-link`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e})})),verifyMagicLink:async e=>l(await fetch(`${a}/api/users/auth/verify?token=${encodeURIComponent(e)}`,{method:"GET"})),getCurrentUser:async()=>l(await fetch(`${a}/api/users/me`,{headers:s()})),logout:async()=>l(await fetch(`${a}/api/users/auth/logout`,{method:"POST",headers:s()})),async getBackendInfo(){let e=a?`${a}/`:"/backend-info";return l(await fetch(e,{headers:s()}))},getEncodingWorkerHealth:async()=>l(await fetch(`${a}/api/health/encoding-worker`)),async getCreditPackages(){let e=await fetch(`${a}/api/users/credits/packages`);return(await l(e)).packages},async createCheckout(e,t){let r=await fetch(`${a}/api/users/credits/checkout`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({package_id:e,email:t.toLowerCase()})});return(await l(r)).checkout_url},async createMadeForYouCheckout(e){let t=await fetch(`${a}/api/users/made-for-you/checkout`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e.email.toLowerCase(),artist:e.artist,title:e.title,source_type:e.source_type,youtube_url:e.youtube_url,notes:e.notes})}),r=await l(t);if(!r.checkout_url)throw Error("No checkout URL received");return r.checkout_url},enrollBetaTester:async(e,t,r)=>l(await fetch(`${a}/api/users/beta/enroll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e.toLowerCase(),promise_text:t,accept_corrections_work:r})})),getVapidPublicKey:async()=>l(await fetch(`${a}/api/push/vapid-public-key`)),subscribePush:async(e,t,r)=>l(await fetch(`${a}/api/push/subscribe`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({endpoint:e,keys:t,device_name:r})})),unsubscribePush:async e=>l(await fetch(`${a}/api/push/unsubscribe`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({endpoint:e})})),listPushSubscriptions:async()=>l(await fetch(`${a}/api/push/subscriptions`,{headers:s()}))},"clearAccessToken",()=>n,"createLyricsReviewApiClient",()=>c,"getAccessToken",()=>i,"lyricsReviewApi",0,{getCorrectionData:async e=>l(await fetch(`${a}/api/jobs/${e}/corrections`,{headers:s()})),getAudioUrl(e){let t=i(),r=`${a}/api/audio/${e}`;return t?`${r}?token=${encodeURIComponent(t)}`:r}},"setAccessToken",()=>r])},68834,e=>{"use strict";var t=e.i(71645);let a=e=>{let t,a=new Set,r=(e,r)=>{let i="function"==typeof e?e(t):e;if(!Object.is(i,t)){let e=t;t=(null!=r?r:"object"!=typeof i||null===i)?i:Object.assign({},t,i),a.forEach(a=>a(t,e))}},i=()=>t,n={setState:r,getState:i,getInitialState:()=>s,subscribe:e=>(a.add(e),()=>a.delete(e))},s=t=e(r,i,n);return n},r=e=>{let r=e?a(e):a,i=e=>(function(e,a=e=>e){let r=t.default.useSyncExternalStore(e.subscribe,t.default.useCallback(()=>a(e.getState()),[e,a]),t.default.useCallback(()=>a(e.getInitialState()),[e,a]));return t.default.useDebugValue(r),r})(r,e);return Object.assign(i,r),i},i=e=>e?r(e):r;e.s(["create",()=>i],68834)},79473,e=>{"use strict";let t=e=>a=>{try{let r=e(a);if(r instanceof Promise)return r;return{then:e=>t(e)(r),catch(e){return this}}}catch(e){return{then(e){return this},catch:a=>t(a)(e)}}},a=(e,a)=>(r,i,n)=>{let s,o={storage:function(e,t){let a;try{a=e()}catch(e){return}return{getItem:e=>{var t;let r=e=>null===e?null:JSON.parse(e,void 0),i=null!=(t=a.getItem(e))?t:null;return i instanceof Promise?i.then(r):r(i)},setItem:(e,t)=>a.setItem(e,JSON.stringify(t,void 0)),removeItem:e=>a.removeItem(e)}}(()=>localStorage),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...a},l=!1,c=new Set,d=new Set,u=o.storage;if(!u)return e((...e)=>{console.warn(`[zustand persist middleware] Unable to update item '${o.name}', the given storage is currently unavailable.`),r(...e)},i,n);let m=()=>{let e=o.partialize({...i()});return u.setItem(o.name,{state:e,version:o.version})},p=n.setState;n.setState=(e,t)=>(p(e,t),m());let h=e((...e)=>(r(...e),m()),i,n);n.getInitialState=()=>h;let y=()=>{var e,a;if(!u)return;l=!1,c.forEach(e=>{var t;return e(null!=(t=i())?t:h)});let n=(null==(a=o.onRehydrateStorage)?void 0:a.call(o,null!=(e=i())?e:h))||void 0;return t(u.getItem.bind(u))(o.name).then(e=>{if(e)if("number"!=typeof e.version||e.version===o.version)return[!1,e.state];else{if(o.migrate){let t=o.migrate(e.state,e.version);return t instanceof Promise?t.then(e=>[!0,e]):[!0,t]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}return[!1,void 0]}).then(e=>{var t;let[a,n]=e;if(r(s=o.merge(n,null!=(t=i())?t:h),!0),a)return m()}).then(()=>{null==n||n(s,void 0),s=i(),l=!0,d.forEach(e=>e(s))}).catch(e=>{null==n||n(void 0,e)})};return n.persist={setOptions:e=>{o={...o,...e},e.storage&&(u=e.storage)},clearStorage:()=>{null==u||u.removeItem(o.name)},getOptions:()=>o,rehydrate:()=>y(),hasHydrated:()=>l,onHydrate:e=>(c.add(e),()=>{c.delete(e)}),onFinishHydration:e=>(d.add(e),()=>{d.delete(e)})},o.skipHydration||y(),s||h};e.s(["persist",()=>a])},38036,e=>{"use strict";var t=e.i(68834),a=e.i(79473),r=e.i(54858);let i=(0,t.create)()((0,a.persist)((e,t)=>({user:null,isLoading:!1,error:null,isImpersonating:!1,originalAdminToken:null,impersonatedUserEmail:null,sendMagicLink:async t=>{e({isLoading:!0,error:null});try{return await r.api.sendMagicLink(t),e({isLoading:!1}),!0}catch(t){return e({isLoading:!1,error:t instanceof Error?t.message:"Failed to send magic link"}),!1}},verifyMagicLink:async t=>{e({isLoading:!0,error:null});try{let a=await r.api.verifyMagicLink(t);(0,r.setAccessToken)(a.session_token);let i={token:a.session_token,email:a.user.email,role:a.user.role,credits:a.user.credits,display_name:a.user.display_name,total_jobs_created:a.user.total_jobs_created,total_jobs_completed:a.user.total_jobs_completed};return e({user:i,isLoading:!1}),!0}catch(t){return e({isLoading:!1,error:t instanceof Error?t.message:"Invalid or expired link"}),!1}},fetchUser:async()=>{let t=(0,r.getAccessToken)();if(!t)return e({user:null}),!1;e({isLoading:!0});try{let a=await r.api.getCurrentUser(),i={token:t,email:a.user.email,role:a.user.role,credits:a.user.credits,display_name:a.user.display_name,total_jobs_created:a.user.total_jobs_created,total_jobs_completed:a.user.total_jobs_completed};return e({user:i,isLoading:!1}),!0}catch{return(0,r.clearAccessToken)(),e({user:null,isLoading:!1}),!1}},logout:async()=>{try{await r.api.logout()}catch{}(0,r.clearAccessToken)(),e({user:null,error:null})},updateCredits:t=>e(e=>({user:e.user?{...e.user,credits:t}:null})),clearError:()=>e({error:null}),loginWithToken:async t=>{e({isLoading:!0,error:null});try{(0,r.setAccessToken)(t);let a=await r.api.getCurrentUser(),i={token:t,email:a.user.email,role:a.user.role,credits:a.user.credits,display_name:a.user.display_name,total_jobs_created:a.user.total_jobs_created,total_jobs_completed:a.user.total_jobs_completed};return e({user:i,isLoading:!1}),!0}catch{return(0,r.clearAccessToken)(),e({user:null,isLoading:!1,error:"Invalid token or server unavailable"}),!1}},startImpersonation:async a=>{if(t().isImpersonating)return e({error:"Already impersonating a user. End current impersonation first."}),!1;e({isLoading:!0,error:null});let i=(0,r.getAccessToken)();try{let t;if(!i)throw Error("No active session to preserve");let n=await r.adminApi.impersonateUser(a);(0,r.setAccessToken)(n.session_token);try{t=await r.api.getCurrentUser()}catch(e){throw(0,r.setAccessToken)(i),e}let s={token:n.session_token,email:t.user.email,role:t.user.role,credits:t.user.credits,display_name:t.user.display_name,total_jobs_created:t.user.total_jobs_created,total_jobs_completed:t.user.total_jobs_completed};return e({user:s,isLoading:!1,isImpersonating:!0,originalAdminToken:i,impersonatedUserEmail:a}),!0}catch(t){return e({isLoading:!1,error:t instanceof Error?t.message:"Failed to impersonate user"}),!1}},endImpersonation:()=>{let{originalAdminToken:a}=t();a&&((0,r.setAccessToken)(a),e({isImpersonating:!1,originalAdminToken:null,impersonatedUserEmail:null}),t().fetchUser())}}),{name:"nomad-karaoke-auth",partialize:e=>({user:e.user})}));(0,r.getAccessToken)()&&i.getState().fetchUser(),e.s(["useAuth",0,i])},86536,e=>{"use strict";let t=(0,e.i(75254).default)("Eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);e.s(["Eye",()=>t],86536)},24672,e=>{"use strict";var t=e.i(68834),a=e.i(54858);let r={logo_url:null,logo_height:40,primary_color:"#ff5bb8",secondary_color:"#8b5cf6",accent_color:"#ffdf6b",background_color:null,favicon_url:null,site_title:"Nomad Karaoke Generator",tagline:null},i={audio_search:!0,file_upload:!0,youtube_url:!0,youtube_upload:!0,dropbox_upload:!0,gdrive_upload:!0,theme_selection:!0,color_overrides:!0,enable_cdg:!0,enable_4k:!0,admin_access:!0},n={theme_id:null,locked_theme:null,distribution_mode:"all"},s=(0,t.create)()((e,t)=>({tenant:null,isDefault:!0,isLoading:!1,error:null,isInitialized:!1,get branding(){let{tenant:e}=t();return e?.branding??r},get features(){let{tenant:e}=t();return e?.features??i},get defaults(){let{tenant:e}=t();return e?.defaults??n},get tenantId(){let{tenant:e}=t();return e?.id??null},fetchTenantConfig:async()=>{if(!t().isLoading){e({isLoading:!0,error:null});try{let t=function(){let e=window.location.hostname.toLowerCase();if("localhost"===e||"127.0.0.1"===e)return new URLSearchParams(window.location.search).get("tenant");if(e.includes("nomadkaraoke.com")){let t=e.split(".");if((3===t.length||4===t.length&&"gen"===t[1])&&!["gen","api","www","buy","admin","app","beta"].includes(t[0]))return t[0]}return null}(),r=`${a.API_BASE_URL}/api/tenant/config`;t&&(r+=`?tenant=${encodeURIComponent(t)}`);let i=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json",...t?{"X-Tenant-ID":t}:{}}});if(!i.ok)throw Error("Failed to fetch tenant configuration");let n=await i.json();e({tenant:n.tenant,isDefault:n.is_default,isLoading:!1,isInitialized:!0}),n.tenant&&o(n.tenant.branding)}catch(t){console.error("Failed to fetch tenant config:",t),e({tenant:null,isDefault:!0,isLoading:!1,error:t instanceof Error?t.message:"Failed to load tenant configuration",isInitialized:!0})}}},setTenant:(t,a)=>{e({tenant:t,isDefault:a,isInitialized:!0}),t&&o(t.branding)},clearError:()=>e({error:null})}));function o(e){if("undefined"==typeof document)return;let t=document.documentElement;if(t.style.setProperty("--tenant-primary",e.primary_color),t.style.setProperty("--tenant-secondary",e.secondary_color),e.accent_color&&t.style.setProperty("--tenant-accent",e.accent_color),e.background_color&&t.style.setProperty("--tenant-background",e.background_color),e.site_title&&(document.title=e.site_title),e.favicon_url){let t=document.querySelector("link[rel~='icon']");t&&(t.href=e.favicon_url)}}e.s(["useTenant",0,s])},89554,e=>{"use strict";var t=e.i(43476),a=e.i(71645),r=(e,t,a,r,i,n,s,o)=>{let l=document.documentElement,c=["light","dark"];function d(t){var a;(Array.isArray(e)?e:[e]).forEach(e=>{let a="class"===e,r=a&&n?i.map(e=>n[e]||e):i;a?(l.classList.remove(...r),l.classList.add(n&&n[t]?n[t]:t)):l.setAttribute(e,t)}),a=t,o&&c.includes(a)&&(l.style.colorScheme=a)}if(r)d(r);else try{let e=localStorage.getItem(t)||a,r=s&&"system"===e?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;d(r)}catch(e){}},i=["light","dark"],n="(prefers-color-scheme: dark)",s="undefined"==typeof window,o=a.createContext(void 0),l=e=>a.useContext(o)?a.createElement(a.Fragment,null,e.children):a.createElement(d,{...e}),c=["light","dark"],d=({forcedTheme:e,disableTransitionOnChange:t=!1,enableSystem:r=!0,enableColorScheme:s=!0,storageKey:l="theme",themes:d=c,defaultTheme:y=r?"system":"light",attribute:f="data-theme",value:g,children:b,nonce:_,scriptProps:w})=>{let[v,$]=a.useState(()=>m(l,y)),[S,k]=a.useState(()=>"system"===v?h():v),T=g?Object.values(g):d,j=a.useCallback(e=>{let a=e;if(!a)return;"system"===e&&r&&(a=h());let n=g?g[a]:a,o=t?p(_):null,l=document.documentElement,c=e=>{"class"===e?(l.classList.remove(...T),n&&l.classList.add(n)):e.startsWith("data-")&&(n?l.setAttribute(e,n):l.removeAttribute(e))};if(Array.isArray(f)?f.forEach(c):c(f),s){let e=i.includes(y)?y:null,t=i.includes(a)?a:e;l.style.colorScheme=t}null==o||o()},[_]),C=a.useCallback(e=>{let t="function"==typeof e?e(v):e;$(t);try{localStorage.setItem(l,t)}catch(e){}},[v]),O=a.useCallback(t=>{k(h(t)),"system"===v&&r&&!e&&j("system")},[v,e]);a.useEffect(()=>{let e=window.matchMedia(n);return e.addListener(O),O(e),()=>e.removeListener(O)},[O]),a.useEffect(()=>{let e=e=>{e.key===l&&(e.newValue?$(e.newValue):C(y))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[C]),a.useEffect(()=>{j(null!=e?e:v)},[e,v]);let E=a.useMemo(()=>({theme:v,setTheme:C,forcedTheme:e,resolvedTheme:"system"===v?S:v,themes:r?[...d,"system"]:d,systemTheme:r?S:void 0}),[v,C,e,S,r,d]);return a.createElement(o.Provider,{value:E},a.createElement(u,{forcedTheme:e,storageKey:l,attribute:f,enableSystem:r,enableColorScheme:s,defaultTheme:y,value:g,themes:d,nonce:_,scriptProps:w}),b)},u=a.memo(({forcedTheme:e,storageKey:t,attribute:i,enableSystem:n,enableColorScheme:s,defaultTheme:o,value:l,themes:c,nonce:d,scriptProps:u})=>{let m=JSON.stringify([i,t,o,e,c,l,n,s]).slice(1,-1);return a.createElement("script",{...u,suppressHydrationWarning:!0,nonce:"undefined"==typeof window?d:"",dangerouslySetInnerHTML:{__html:`(${r.toString()})(${m})`}})}),m=(e,t)=>{let a;if(!s){try{a=localStorage.getItem(e)||void 0}catch(e){}return a||t}},p=e=>{let t=document.createElement("style");return e&&t.setAttribute("nonce",e),t.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(t),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(t)},1)}},h=e=>(e||(e=window.matchMedia(n)),e.matches?"dark":"light");function y({children:e,...a}){return(0,t.jsx)(l,{...a,children:e})}e.s(["ThemeProvider",()=>y],89554)},57091,e=>{"use strict";var t=e.i(43476),a=e.i(71645),r=e.i(24672);function i({children:e}){let{fetchTenantConfig:i,isInitialized:n}=(0,r.useTenant)();return(0,a.useEffect)(()=>{n||i()},[i,n]),(0,t.jsx)(t.Fragment,{children:e})}function n(){let{isInitialized:e,isLoading:t}=(0,r.useTenant)();return e&&!t}function s({children:e,fallback:a}){return n()?(0,t.jsx)(t.Fragment,{children:e}):a??null}e.s(["TenantProvider",()=>i,"TenantReady",()=>s,"useTenantReady",()=>n])},48030,e=>{"use strict";var t=e.i(43476),a=e.i(38036),r=e.i(67881),i=e.i(37727),n=e.i(86536);function s(){let{isImpersonating:e,impersonatedUserEmail:s,endImpersonation:o}=(0,a.useAuth)();return e?(0,t.jsxs)("div",{className:"bg-amber-500 text-amber-950 px-4 py-2 flex items-center justify-between gap-4 text-sm font-medium",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(n.Eye,{className:"w-4 h-4"}),(0,t.jsxs)("span",{children:["Viewing as ",(0,t.jsx)("strong",{children:s})]})]}),(0,t.jsxs)(r.Button,{variant:"outline",size:"sm",onClick:o,className:"bg-amber-100 hover:bg-amber-200 text-amber-950 border-amber-600 h-7 px-3",children:[(0,t.jsx)(i.X,{className:"w-3 h-3 mr-1"}),"Stop Impersonating"]})]}):null}function o(){return(0,t.jsx)(s,{})}e.s(["ImpersonationBannerWrapper",()=>o],48030)},72285,e=>{"use strict";var t=e.i(71645);function a(){return(0,t.useEffect)(()=>{let e="localhost"===window.location.hostname;"https:"===window.location.protocol||e?"serviceWorker"in navigator?navigator.serviceWorker.register("/sw.js",{scope:"/"}).then(e=>{console.log("[SW] Service worker registered:",e.scope),e.addEventListener("updatefound",()=>{let t=e.installing;t&&(console.log("[SW] New service worker installing..."),t.addEventListener("statechange",()=>{"installed"===t.state&&navigator.serviceWorker.controller&&console.log("[SW] New service worker installed, refresh for updates")}))})}).catch(e=>{console.error("[SW] Service worker registration failed:",e)}):console.log("[SW] Service workers not supported"):console.log("[SW] Skipping service worker registration: requires HTTPS")},[]),null}e.s(["ServiceWorkerRegistration",()=>a])}]);