@polderlabs/bizar 4.5.0 → 4.5.2

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 (77) hide show
  1. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
  2. package/bizar-dash/dist/assets/__vite-browser-external-BIHI7g3E.js.map +1 -0
  3. package/bizar-dash/dist/assets/main-B4OfGAwz.js +361 -0
  4. package/bizar-dash/dist/assets/main-B4OfGAwz.js.map +1 -0
  5. package/bizar-dash/dist/assets/main-DAlLdW8I.css +1 -0
  6. package/bizar-dash/dist/assets/{mobile--0FBIKX3.js → mobile-BRhoDOUz.js} +1 -2
  7. package/bizar-dash/dist/assets/{mobile--0FBIKX3.js.map → mobile-BRhoDOUz.js.map} +1 -1
  8. package/bizar-dash/dist/assets/{mobile-OgRp8VIb.js → mobile-lbH6szyX.js} +2 -3
  9. package/bizar-dash/dist/assets/mobile-lbH6szyX.js.map +1 -0
  10. package/bizar-dash/dist/index.html +3 -3
  11. package/bizar-dash/dist/mobile.html +2 -2
  12. package/bizar-dash/skills/bizar/SKILL.md +20 -0
  13. package/bizar-dash/skills/headroom/SKILL.md +94 -0
  14. package/bizar-dash/skills/lightrag/SKILL.md +11 -0
  15. package/bizar-dash/skills/obsidian/SKILL.md +13 -0
  16. package/bizar-dash/src/server/api.mjs +6 -0
  17. package/bizar-dash/src/server/headroom.mjs +647 -0
  18. package/bizar-dash/src/server/memory-lightrag.mjs +281 -6
  19. package/bizar-dash/src/server/memory-obsidian.mjs +230 -0
  20. package/bizar-dash/src/server/memory-store.mjs +151 -0
  21. package/bizar-dash/src/server/mods-loader.mjs +13 -5
  22. package/bizar-dash/src/server/providers-store.mjs +73 -1
  23. package/bizar-dash/src/server/routes/_shared.mjs +17 -0
  24. package/bizar-dash/src/server/routes/chat.mjs +38 -0
  25. package/bizar-dash/src/server/routes/headroom.mjs +126 -0
  26. package/bizar-dash/src/server/routes/lightrag.mjs +6 -2
  27. package/bizar-dash/src/server/routes/memory.mjs +439 -4
  28. package/bizar-dash/src/server/schedules-runner.mjs +4 -4
  29. package/bizar-dash/src/server/server.mjs +55 -37
  30. package/bizar-dash/src/server/watcher.mjs +2 -2
  31. package/bizar-dash/src/web/App.tsx +42 -6
  32. package/bizar-dash/src/web/components/HeadroomSettings.tsx +418 -0
  33. package/bizar-dash/src/web/components/HeadroomStatus.tsx +158 -0
  34. package/bizar-dash/src/web/components/Toast.tsx +1 -1
  35. package/bizar-dash/src/web/components/Topbar.tsx +3 -1
  36. package/bizar-dash/src/web/lib/api.ts +12 -11
  37. package/bizar-dash/src/web/lib/types.ts +16 -0
  38. package/bizar-dash/src/web/main.tsx +1 -0
  39. package/bizar-dash/src/web/styles/chat.css +2 -0
  40. package/bizar-dash/src/web/styles/main.css +52 -23
  41. package/bizar-dash/src/web/styles/memory.css +955 -0
  42. package/bizar-dash/src/web/styles/tasks.css +2 -0
  43. package/bizar-dash/src/web/views/Memory.tsx +141 -0
  44. package/bizar-dash/src/web/views/MiniMaxUsage.tsx +3 -2
  45. package/bizar-dash/src/web/views/Overview.tsx +7 -2
  46. package/bizar-dash/src/web/views/Settings.tsx +32 -1
  47. package/bizar-dash/src/web/views/Skills.tsx +3 -2
  48. package/bizar-dash/src/web/views/Tasks.tsx +4 -3
  49. package/bizar-dash/src/web/views/memory/ConfigPanel.tsx +289 -0
  50. package/bizar-dash/src/web/views/memory/GitSyncPanel.tsx +220 -0
  51. package/bizar-dash/src/web/views/memory/LightragPanel.tsx +307 -0
  52. package/bizar-dash/src/web/views/memory/MemoryOverview.tsx +356 -0
  53. package/bizar-dash/src/web/views/memory/MemoryStatusCard.tsx +160 -0
  54. package/bizar-dash/src/web/views/memory/ObsidianPanel.tsx +642 -0
  55. package/bizar-dash/src/web/views/memory/SemanticSearchPanel.tsx +194 -0
  56. package/bizar-dash/tests/cli-bugfixes.test.mjs +151 -0
  57. package/bizar-dash/tests/frontend-bugfixes.test.mjs +151 -0
  58. package/bizar-dash/tests/headroom-install.test.mjs +173 -0
  59. package/bizar-dash/tests/headroom-settings.test.mjs +126 -0
  60. package/bizar-dash/tests/headroom-status.test.mjs +117 -0
  61. package/bizar-dash/tests/memory-lightrag-extended.test.mjs +162 -0
  62. package/bizar-dash/tests/memory-obsidian.test.mjs +269 -0
  63. package/bizar-dash/tests/memory-tab.test.mjs +322 -0
  64. package/bizar-dash/tests/mod-upgrade.node.test.mjs +1 -1
  65. package/bizar-dash/tests/server-bugfixes.test.mjs +318 -0
  66. package/bizar-dash/tests/submit-feedback.test.mjs +6 -6
  67. package/cli/artifact.mjs +11 -4
  68. package/cli/bin.mjs +211 -12
  69. package/cli/doctor.mjs +5 -3
  70. package/cli/memory.mjs +65 -21
  71. package/cli/provision.mjs +8 -2
  72. package/install.sh +1 -2
  73. package/package.json +3 -3
  74. package/bizar-dash/dist/assets/main-CDFKHzBg.css +0 -1
  75. package/bizar-dash/dist/assets/main-NYFpS2wY.js +0 -312
  76. package/bizar-dash/dist/assets/main-NYFpS2wY.js.map +0 -1
  77. package/bizar-dash/dist/assets/mobile-OgRp8VIb.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"mappings":"+zBAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,GAAiBC,EAAiB,iBAAkB,CACxD,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,4BAA6B,IAAK,QAAQ,CAAE,EAC1D,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,EAC9C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECfD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMC,GAAYD,EAAiB,YAAa,CAC9C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAME,GAAYF,EAAiB,YAAa,CAC9C,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,EAC/C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMG,GAAUH,EAAiB,UAAW,CAC1C,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,EAC9C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMI,GAAQJ,EAAiB,QAAS,CACtC,CACE,OACA,CACE,EAAG,uFACH,IAAK,OACX,CACA,EACE,CACE,OACA,CACE,EAAG,uFACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,6CAA8C,IAAK,QAAQ,CAAE,EAC3E,CAAC,OAAQ,CAAE,EAAG,mCAAoC,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,EAAG,mCAAoC,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,EAAG,oCAAqC,IAAK,QAAQ,CAAE,EAClE,CAAC,OAAQ,CAAE,EAAG,kCAAmC,IAAK,QAAQ,CAAE,EAChE,CAAC,OAAQ,CAAE,EAAG,6BAA8B,IAAK,QAAQ,CAAE,EAC3D,CAAC,OAAQ,CAAE,EAAG,iCAAkC,IAAK,QAAQ,CAAE,CACjE,CAAC,EC/BD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMK,GAAWL,EAAiB,WAAY,CAC5C,CAAC,OAAQ,CAAE,EAAG,SAAU,IAAK,QAAQ,CAAE,EACvC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMM,GAAoBN,EAAiB,oBAAqB,CAC9D,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,EAClE,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,CAClE,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMO,GAAQP,EAAiB,QAAS,CAAC,CAAC,OAAQ,CAAE,EAAG,kBAAmB,IAAK,QAAQ,CAAE,CAAC,CAAC,ECT3F;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMQ,GAAcR,EAAiB,cAAe,CAClD,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC,ECXD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMS,GAAiBT,EAAiB,iBAAkB,CACxD,CAAC,OAAQ,CAAE,EAAG,kCAAmC,IAAK,QAAQ,CAAE,EAChE,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMU,GAAmBV,EAAiB,mBAAoB,CAC5D,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,SAAU,EACzD,CAAC,OAAQ,CAAE,EAAG,2CAA4C,IAAK,QAAQ,CAAE,EACzE,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMW,GAAaX,EAAiB,aAAc,CAChD,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,SAAU,EACzD,CAAC,UAAW,CAAE,OAAQ,wBAAyB,IAAK,QAAQ,CAAE,CAChE,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMY,GAAUZ,EAAiB,UAAW,CAC1C,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,SAAU,EACzD,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMa,GAASb,EAAiB,SAAU,CACxC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,QAAQ,CAAE,CAC3D,CAAC,ECXD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMc,GAAQd,EAAiB,QAAS,CACtC,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,IAAK,EAAG,IAAK,IAAK,SAAU,EACtD,CAAC,OAAQ,CAAE,EAAG,kCAAmC,IAAK,QAAQ,CAAE,EAChE,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,8BAA+B,IAAK,QAAQ,CAAE,CAC9D,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMe,GAAMf,EAAiB,MAAO,CAClC,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,SAAU,IAAK,QAAQ,CAAE,EACvC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,SAAU,IAAK,QAAQ,CAAE,EACvC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,CAC1C,CAAC,ECpBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMgB,GAAWhB,EAAiB,WAAY,CAC5C,CAAC,UAAW,CAAE,GAAI,KAAM,GAAI,IAAK,GAAI,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAClE,CAAC,OAAQ,CAAE,EAAG,4BAA6B,IAAK,QAAQ,CAAE,EAC1D,CAAC,OAAQ,CAAE,EAAG,wBAAyB,IAAK,QAAQ,CAAE,CACxD,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMiB,GAAUjB,EAAiB,UAAW,CAC1C,CACE,OACA,CACE,EAAG,wIACH,IAAK,QACX,CACA,CACA,CAAC,ECjBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMkB,GAAWlB,EAAiB,WAAY,CAC5C,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,WAAY,CAAE,OAAQ,mBAAoB,IAAK,QAAQ,CAAE,EAC1D,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,CACnE,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMmB,GAAWnB,EAAiB,WAAY,CAC5C,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CACzD,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMoB,GAASpB,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,iGACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,uCAAwC,IAAK,QAAQ,CAAE,EACrE,CACE,OACA,CACE,EAAG,+FACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC,EC1BD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMqB,GAAMrB,EAAiB,MAAO,CAClC,CACE,OACA,CACE,EAAG,wGACH,IAAK,QACX,CACA,EACE,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CAC1D,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMsB,GAAYtB,EAAiB,YAAa,CAC9C,CAAC,OAAQ,CAAE,EAAG,kDAAmD,IAAK,QAAQ,CAAE,EAChF,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,EAC9C,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,CAChD,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMuB,GAAWvB,EAAiB,WAAY,CAC5C,CAAC,OAAQ,CAAE,EAAG,sBAAuB,IAAK,QAAQ,CAAE,EACpD,CAAC,OAAQ,CAAE,EAAG,uBAAwB,IAAK,QAAQ,CAAE,EACrD,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,6DAA8D,IAAK,QAAQ,CAAE,CAC7F,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMwB,GAAWxB,EAAiB,WAAY,CAC5C,CAAC,OAAQ,CAAE,EAAG,6DAA8D,IAAK,QAAQ,CAAE,EAC3F,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,CAC5C,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMyB,GAAOzB,EAAiB,OAAQ,CACpC,CAAC,OAAQ,CAAE,EAAG,6DAA8D,IAAK,QAAQ,CAAE,EAC3F,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,CAC1D,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM0B,GAAS1B,EAAiB,SAAU,CACxC,CAAC,UAAW,CAAE,OAAQ,8CAA+C,IAAK,QAAQ,CAAE,CACtF,CAAC,ECXD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM2B,GAAa3B,EAAiB,aAAc,CAChD,CACE,OACA,CACE,EAAG,oLACH,IAAK,QACX,CACA,CACA,CAAC,ECjBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM4B,GAAa5B,EAAiB,aAAc,CAChD,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CACE,OACA,CACE,EAAG,yHACH,IAAK,QACX,CACA,CACA,CAAC,ECnBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM6B,GAAe7B,EAAiB,eAAgB,CACpD,CACE,OACA,CACE,EAAG,8GACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,EAC/C,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CAC1D,CAAC,ECnBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM8B,GAAY9B,EAAiB,YAAa,CAC9C,CAAC,OAAQ,CAAE,GAAI,IAAK,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,IAAK,QAAQ,CAAE,EAC/D,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,IAAK,EAAG,IAAK,IAAK,SAAU,EACvD,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACvD,CAAC,OAAQ,CAAE,EAAG,sBAAuB,IAAK,QAAQ,CAAE,CACtD,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM+B,GAAsB/B,EAAiB,sBAAuB,CAClE,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,EAChE,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,CACpE,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMgC,GAAWhC,EAAiB,WAAY,CAC5C,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,IAAK,EAAG,IAAK,IAAK,SAAU,EACtD,CAAC,OAAQ,CAAE,EAAG,wBAAyB,IAAK,QAAQ,CAAE,CACxD,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMiC,GAAiBjC,EAAiB,iBAAkB,CACxD,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,IAAK,EAAG,IAAK,IAAK,SAAU,EACtD,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,GAAI,IAAK,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,IAAK,OAAO,CAAE,CAChE,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMkC,GAAQlC,EAAiB,QAAS,CACtC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,SAAU,EACzD,CAAC,OAAQ,CAAE,EAAG,kDAAmD,IAAK,QAAQ,CAAE,EAChF,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAC3C,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMmC,GAAQnC,EAAiB,QAAS,CACtC,CAAC,OAAQ,CAAE,EAAG,6CAA8C,IAAK,QAAQ,CAAE,EAC3E,CACE,OACA,CACE,EAAG,gHACH,IAAK,QACX,CACA,CACA,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMoC,GAAQpC,EAAiB,QAAS,CACtC,CAAC,WAAY,CAAE,OAAQ,oCAAqC,IAAK,QAAQ,CAAE,EAC3E,CACE,OACA,CACE,EAAG,6GACH,IAAK,QACX,CACA,CACA,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMqC,GAAWrC,EAAiB,WAAY,CAC5C,CACE,OACA,CACE,EAAG,6KACH,IAAK,QACX,CACA,EACE,CAAC,SAAU,CAAE,GAAI,OAAQ,GAAI,MAAO,EAAG,KAAM,KAAM,eAAgB,IAAK,QAAQ,CAAE,CACpF,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMsC,GAAStC,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,+GACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,+CAAgD,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,EAAG,+CAAgD,IAAK,QAAQ,CAAE,CAC/E,CAAC,ECnBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMuC,GAAkBvC,EAAiB,kBAAmB,CAC1D,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,KAAM,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,KAAM,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,CAC/E,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMwC,GAAiBxC,EAAiB,iBAAkB,CACxD,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,IAAK,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,IAAK,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,MAAO,IAAK,OAAQ,IAAK,EAAG,KAAM,EAAG,KAAM,GAAI,IAAK,IAAK,QAAQ,CAAE,CAChF,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMyC,GAAezC,EAAiB,eAAgB,CACpD,CAAC,OAAQ,CAAE,EAAG,8BAA+B,IAAK,QAAQ,CAAE,CAC9D,CAAC,ECXD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM0C,GAAS1C,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,uGACH,IAAK,QACX,CACA,EACE,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CAC1D,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM2C,GAAM3C,EAAiB,MAAO,CAClC,CACE,OACA,CACE,EAAG,gPACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,eAAgB,IAAK,QAAQ,CAAE,EAC7C,CAAC,OAAQ,CAAE,EAAG,cAAe,IAAK,QAAQ,CAAE,CAC9C,CAAC,ECnBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM4C,GAAY5C,EAAiB,YAAa,CAC9C,CAAC,WAAY,CAAE,OAAQ,iBAAkB,IAAK,QAAQ,CAAE,EACxD,CAAC,WAAY,CAAE,OAAQ,iBAAkB,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,IAAK,QAAQ,CAAE,CACnE,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM6C,GAAQ7C,EAAiB,QAAS,CAAC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,CAAC,CAAC,ECTpF;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM8C,GAAe9C,EAAiB,eAAgB,CACpD,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,EAC3C,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CACE,OACA,CACE,EAAG,gPACH,IAAK,QACX,CACA,CACA,CAAC,ECnBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM+C,GAAU/C,EAAiB,UAAW,CAC1C,CACE,OACA,CACE,EAAG,2HACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,8CAA+C,IAAK,QAAQ,CAAE,EAC5E,CAAC,OAAQ,CAAE,EAAG,mBAAoB,IAAK,QAAQ,CAAE,CACnD,CAAC,ECpBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMgD,GAAUhD,EAAiB,UAAW,CAC1C,CAAC,SAAU,CAAE,GAAI,OAAQ,GAAI,MAAO,EAAG,KAAM,KAAM,eAAgB,IAAK,QAAQ,CAAE,EAClF,CAAC,SAAU,CAAE,GAAI,OAAQ,GAAI,OAAQ,EAAG,KAAM,KAAM,eAAgB,IAAK,QAAQ,CAAE,EACnF,CAAC,SAAU,CAAE,GAAI,MAAO,GAAI,MAAO,EAAG,KAAM,KAAM,eAAgB,IAAK,QAAQ,CAAE,EACjF,CAAC,SAAU,CAAE,GAAI,MAAO,GAAI,OAAQ,EAAG,KAAM,KAAM,eAAgB,IAAK,QAAQ,CAAE,EAClF,CACE,OACA,CACE,EAAG,2NACH,IAAK,QACX,CACA,CACA,CAAC,ECrBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMiD,GAAiBjD,EAAiB,iBAAkB,CACxD,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMkD,GAAgBlD,EAAiB,gBAAiB,CACtD,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,CAChD,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMmD,GAAgBnD,EAAiB,gBAAiB,CACtD,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,EAC9E,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,CAC1C,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMoD,GAAMpD,EAAiB,MAAO,CAClC,CACE,OACA,CACE,EAAG,mIACH,IAAK,QACX,CACA,CACA,CAAC,ECjBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMqD,GAAOrD,EAAiB,OAAQ,CACpC,CAAC,OAAQ,CAAE,EAAG,YAAa,IAAK,QAAQ,CAAE,EAC1C,CAAC,OAAQ,CAAE,EAAG,SAAU,IAAK,QAAQ,CAAE,EACvC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,CAC5E,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMsD,GAAWtD,EAAiB,WAAY,CAC5C,CAAC,OAAQ,CAAE,EAAG,iCAAkC,IAAK,QAAQ,CAAE,EAC/D,CAAC,OAAQ,CAAE,EAAG,mCAAoC,IAAK,QAAQ,CAAE,EACjE,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,QAAQ,CAAE,EACxC,CAAC,OAAQ,CAAE,EAAG,aAAc,IAAK,QAAQ,CAAE,CAC7C,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMuD,GAASvD,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,gdACH,IAAK,QACX,CACA,CACA,CAAC,ECjBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMwD,GAAQxD,EAAiB,QAAS,CACtC,CAAC,OAAQ,CAAE,EAAG,iCAAkC,IAAK,QAAQ,CAAE,EAC/D,CAAC,OAAQ,CAAE,EAAG,mCAAoC,IAAK,QAAQ,CAAE,EACjE,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,EAAG,kCAAmC,IAAK,QAAQ,CAAE,EAChE,CAAC,OAAQ,CAAE,EAAG,mCAAoC,IAAK,QAAQ,CAAE,CACnE,CAAC,ECfD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMyD,GAAQzD,EAAiB,QAAS,CACtC,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,EAC/C,CAAC,OAAQ,CAAE,EAAG,yDAA0D,IAAK,QAAQ,CAAE,CACzF,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM0D,GAAS1D,EAAiB,SAAU,CACxC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,IAAK,EAAG,IAAK,IAAK,SAAU,EACvD,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACvD,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,OAAQ,CAAE,GAAI,OAAQ,GAAI,QAAS,GAAI,QAAS,GAAI,QAAS,IAAK,QAAQ,CAAE,EAC7E,CAAC,OAAQ,CAAE,GAAI,QAAS,GAAI,OAAQ,GAAI,OAAQ,GAAI,QAAS,IAAK,QAAQ,CAAE,CAC9E,CAAC,ECfD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM2D,GAAc3D,EAAiB,cAAe,CAClD,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,EACE,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,CAChD,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM4D,GAAS5D,EAAiB,SAAU,CACxC,CACE,OACA,CACE,EAAG,qKACH,IAAK,QACX,CACA,CACA,CAAC,ECjBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM6D,GAAY7D,EAAiB,YAAa,CAC9C,CAAC,OAAQ,CAAE,EAAG,6DAA8D,IAAK,QAAQ,CAAE,EAC3F,CACE,OACA,CACE,EAAG,0HACH,IAAK,QACX,CACA,CACA,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM8D,GAAS9D,EAAiB,SAAU,CACxC,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,QAAQ,CAAE,CAChF,CAAC,ECXD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAM+D,GAAM/D,EAAiB,MAAO,CAClC,CACE,OACA,CACE,EAAG,uJACH,IAAK,QACX,CACA,EACE,CAAC,SAAU,CAAE,GAAI,MAAO,GAAI,MAAO,EAAG,KAAM,KAAM,eAAgB,IAAK,QAAQ,CAAE,CACnF,CAAC,EClBD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMgE,GAAShE,EAAiB,SAAU,CACxC,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,KAAM,IAAK,SAAU,EACzD,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,SAAU,EACxD,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,KAAM,EAAG,IAAK,IAAK,QAAQ,CAAE,CAC1D,CAAC,ECbD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMiE,GAAQjE,EAAiB,QAAS,CACtC,CAAC,OAAQ,CAAE,EAAG,gBAAiB,IAAK,QAAQ,CAAE,EAC9C,CAAC,OAAQ,CAAE,EAAG,2DAA4D,IAAK,QAAQ,CAAE,CAC3F,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMkE,GAAOlE,EAAiB,OAAQ,CACpC,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,SAAU,CAAE,GAAI,KAAM,GAAI,IAAK,EAAG,IAAK,IAAK,QAAQ,CAAE,CACzD,CAAC,ECZD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMmE,GAAQnE,EAAiB,QAAS,CACtC,CAAC,OAAQ,CAAE,EAAG,4CAA6C,IAAK,QAAQ,CAAE,EAC1E,CAAC,SAAU,CAAE,GAAI,IAAK,GAAI,IAAK,EAAG,IAAK,IAAK,QAAS,EACrD,CAAC,OAAQ,CAAE,EAAG,6BAA8B,IAAK,QAAQ,CAAE,EAC3D,CAAC,OAAQ,CAAE,EAAG,4BAA6B,IAAK,QAAQ,CAAE,CAC5D,CAAC,ECdD;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMoE,GAAMpE,EAAiB,MAAO,CAClC,CACE,OACA,CACE,EAAG,8JACH,IAAK,QACX,CACA,CACA,CAAC,ECUKqE,GAAY,IACZC,GAAS,EAAI,GAAK,IAIlBC,OAAa,IAEnB,SAASC,GAASC,EAAuC,CACvD,MAAMC,EAAQH,GAAO,IAAIE,CAAI,EAC7B,OAAKC,EACD,KAAK,MAAQA,EAAM,GAAKJ,IAAUC,GAAO,OAAOE,CAAI,EAAU,MAC3DC,EAAM,KAFM,IAGrB,CAEA,SAASC,GAASF,EAAcG,EAAwB,CAClDL,GAAO,MAAQF,IAEF,CAAC,GAAGE,GAAO,SAAS,EAChC,KAAK,CAACM,EAAGC,IAAMD,EAAE,CAAC,EAAE,GAAKC,EAAE,CAAC,EAAE,EAAE,EAChC,MAAM,EAAG,EAAE,EACX,IAAI,CAAC,CAACC,CAAC,IAAMA,CAAC,EACV,QAASA,GAAMR,GAAO,OAAOQ,CAAC,CAAC,EAExCR,GAAO,IAAIE,EAAM,CAAE,KAAAG,EAAM,GAAI,KAAK,MAAO,CAC3C,CAIA,SAASI,GAAaC,EAA8C,CAClE,GAAI,CAACA,GAAKA,IAAM,IAAK,MAAO,CAAC,CAAE,MAAO,IAAK,KAAM,IAAK,EACtD,MAAMC,EAAQD,EAAE,MAAM,GAAG,EAAE,OAAO,OAAO,EACnCE,EAA4C,GAClD,IAAIC,EAAc,GAClB,QAASC,EAAI,EAAGA,EAAIH,EAAM,OAAQG,IAChCD,GAAe,IAAMF,EAAMG,CAAC,EAC5BF,EAAO,KAAK,CAAE,MAAOD,EAAMG,CAAC,EAAG,KAAMD,EAAa,EAEpD,OAAOD,CACT,CAEA,SAASG,GAAYC,EAA6C,CAChE,MAAO,CAAC,GAAGA,CAAO,EAAE,KAAK,CAACV,EAAGC,IACvBD,EAAE,QAAUC,EAAE,MAAcD,EAAE,MAAQ,GAAK,EACxCA,EAAE,KAAK,cAAcC,EAAE,KAAM,OAAW,CAAE,YAAa,OAAQ,CACvE,CACH,CAOO,SAASU,GAAgBC,EAA4D,CAC1F,MAAMC,EAAUD,EAAK,OACrB,OAAKC,EACDA,IAAYD,EAAa,CAAE,GAAI,GAAO,OAAQ,oDAC9CC,IAAY,IAAY,CAAE,GAAI,GAAO,OAAQ,uBAC7CA,IAAY,KAAa,CAAE,GAAI,GAAO,OAAQ,wBAC9CA,EAAQ,WAAW,GAAG,EAAU,CAAE,GAAI,GAAO,OAAQ,+BACrDA,EAAQ,OAAS,IAAY,CAAE,GAAI,GAAO,OAAQ,8CAClD,eAAe,KAAKA,CAAO,EACtB,CAAE,GAAI,GAAO,OAAQ,0CAEvB,CAAE,GAAI,IATQ,CAAE,GAAI,GAAO,OAAQ,wBAU5C,CAIO,SAASC,GAAY,CAC1B,MAAAC,EACA,SAAAC,EACA,YAAAC,EACA,kBAAAC,EACA,UAAAC,EAAY,OACZ,OAAAC,EAAS,GACX,EAAqB,CACnB,KAAM,CAACC,EAAaC,CAAc,EAAIC,WACpCN,GAAeC,GAAqB,IAEhC,CAACM,EAAUC,CAAW,EAAIF,WAAsB,IAAI,GAAK,EACzD,CAACG,EAAaC,CAAc,EAAIJ,WAAiB,EAAE,EACnD,CAACK,EAASC,CAAU,EAAIN,WAAkC,IAAI,EAC9D,CAACO,EAAaC,CAAc,EAAIR,WAA2C,EAAE,EAC7E,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAK,EACtC,CAACW,EAAOC,CAAQ,EAAIZ,WAAwB,IAAI,EAChD,CAACa,EAAWC,CAAY,EAAId,WAAS,EAAK,EAC1C,CAACe,EAAWC,CAAY,EAAIhB,WAAS,EAAE,EACvC,CAACiB,EAAYC,CAAa,EAAIlB,WAAwB,IAAI,EAC1D,CAACmB,EAAcC,CAAe,EAAIpB,WAAS,EAAK,EAChDqB,EAAgBC,SAAgC,IAAI,EAEpDC,EAAeC,cAAY,MAAOnD,GAAmD,CACzF,GAAI,CACF,MAAMoD,GAASrD,GAASC,CAAI,EAC5B,GAAIoD,GAAQ,OAAOA,GACnB,MAAMjD,GAAO,MAAMkD,EAAI,IAAsB,YAAc,mBAAmBrD,CAAI,CAAC,EACnF,OAAAE,GAASF,EAAMG,EAAI,EACZA,EACT,MAAQ,CACN,OAAO,IACT,CACF,EAAG,EAAE,EAECmD,EAAOH,cAAY,MAAOnD,GAAiB,QAC/CqC,EAAW,EAAI,EACfE,EAAS,IAAI,EACb,GAAI,CACF,MAAMpC,GAAO,MAAMkD,EAAI,IAAsB,YAAc,mBAAmBrD,CAAI,CAAC,EACnFE,GAASF,EAAMG,EAAI,EACnB8B,EAAW9B,EAAI,EACf4B,EAAe,EAAE,CACnB,OAASwB,GAAK,CACZ,MAAMC,KAAOC,GAAAF,GAA0D,OAA1D,YAAAE,GAAgE,UACvEF,GAAc,SACf,2BACLhB,EAASiB,EAAG,CACd,SACEnB,EAAW,EAAK,CAClB,CACF,EAAG,EAAE,EAGLqB,YAAU,IAAM,CACTjC,EAYH6B,EAAK7B,CAAW,EAVhB4B,EAAI,IAAsB,KAAK,EAAE,KAAMlD,GAAS,CAC9CD,GAAS,GAAIC,CAAI,EACjB8B,EAAW9B,CAAI,EACfuB,EAAevB,EAAK,IAAI,EACpBA,EAAK,OAASgB,GAAOC,EAASjB,EAAK,IAAI,CAC7C,CAAC,EAAE,MAAM,IAAM,CACboC,EAAS,qCAAqC,EAC9CF,EAAW,EAAK,CAClB,CAAC,CAKL,EAAG,CAACZ,CAAW,CAAC,EAGhBiC,YAAU,IAAM,CACVvC,GAASA,IAAUM,GACrBC,EAAeP,CAAK,CAExB,EAAG,CAACA,CAAK,CAAC,EAEV,MAAML,EAAUkB,EAAUnB,GAAYmB,EAAQ,OAAO,EAAI,GAEnD2B,EAAO7C,EAAQ,OAAQ8C,GAAMA,EAAE,KAAK,EACpCC,EAAa/C,EAIbgD,EAAgB7D,GAA0B,CACzCA,EAAM,QACXyB,EAAezB,EAAM,IAAI,EACzBmB,EAASnB,EAAM,IAAI,EACrB,EAEM8D,GAAa,IAAM,CAClB/B,GAAA,MAAAA,EAAS,SACdN,EAAeM,EAAQ,MAAM,EAC7BZ,EAASY,EAAQ,MAAM,EACzB,EAEMgC,GAAchE,GAAiB,CAC/BA,IAASyB,IACbC,EAAe1B,CAAI,EACnBoB,EAASpB,CAAI,EACf,EAEMiE,EAAS,SAAY,CACzB,MAAMC,EAAO,MAAMhB,EAAa,EAAE,EAC9BgB,IACFxC,EAAewC,EAAK,IAAI,EACxB9C,EAAS8C,EAAK,IAAI,EAEtB,EAEMC,EAAa,SAAY,CAC7B,GAAI,CAAC7C,EAAmB,OACxB,MAAM8C,EAAK,MAAMlB,EAAa5B,CAAiB,EAC3C8C,IACF1C,EAAe0C,EAAG,IAAI,EACtBhD,EAASgD,EAAG,IAAI,EAEpB,EAKMC,GAAY,IAAM,CACtB5B,EAAa,EAAI,EACjBE,EAAa,EAAE,EACfE,EAAc,IAAI,EAElB,WAAW,WAAM,OAAAY,EAAAT,EAAc,UAAd,YAAAS,EAAuB,SAAS,CAAC,CACpD,EAEMa,EAAc,IAAM,CACxB7B,EAAa,EAAK,EAClBE,EAAa,EAAE,EACfE,EAAc,IAAI,CACpB,EAEM0B,GAAc,SAAY,QAC9B,MAAMC,EAAIzD,GAAgB2B,CAAS,EACnC,GAAI,CAAC8B,EAAE,GAAI,CACT3B,EAAc2B,EAAE,MAAM,EACtB,MACF,CACAzB,EAAgB,EAAI,EACpBF,EAAc,IAAI,EAClB,GAAI,CACF,MAAMnC,GAAS,MAAM2C,EAAI,KAAoB,YAAa,CACxD,OAAQ5B,EACR,KAAMiB,EAAU,MAAK,CACN,EAEjB5C,GAAO,OAAO2B,CAAW,EACzB,MAAM6B,EAAK7B,CAAW,EAEtBL,EAASV,GAAO,IAAI,EACpB+B,EAAa,EAAK,EAClBE,EAAa,EAAE,CACjB,OAASY,GAAK,CACZ,MAAMkB,GAASlB,GACXkB,GAAO,SAAW,IACpB5B,EAAc,mBAAmBH,EAAU,MAAM,mBAAmB,EAEpEG,IACEY,GAAAgB,GAAO,OAAP,YAAAhB,GAAa,UACZF,GAAc,SACf,2BAGN,SACER,EAAgB,EAAK,CACvB,CACF,EAEM2B,GAAsBd,GAA6C,CACnEA,EAAE,MAAQ,SACZA,EAAE,iBACFW,GAAA,GACSX,EAAE,MAAQ,WACnBA,EAAE,iBACFU,EAAA,EAEJ,EAEMK,EAAgB3E,GAAiB,CACrC6B,EAAa+C,IAAS,CACpB,MAAMC,GAAO,IAAI,IAAID,EAAI,EACzB,OAAIC,GAAK,IAAI7E,CAAI,EAAG6E,GAAK,OAAO7E,CAAI,EAC/B6E,GAAK,IAAI7E,CAAI,EACX6E,EACT,CAAC,EAEI3C,EAAYlC,CAAI,GACnBkD,EAAalD,CAAI,EAAE,KAAMG,IAAS,CAC5BA,IAAMgC,EAAgByC,KAAU,CAAE,GAAGA,GAAM,CAAC5E,CAAI,EAAGG,GAAK,QAAQ,OAAQyD,IAAMA,GAAE,KAAK,GAAI,CAC/F,CAAC,CAEL,EAIMkB,EAAiBlB,GAA2B,CAChD,GAAI,CAAC5B,EAAS,OACd,MAAM2B,GAAOE,EAAW,OAAQkB,IAAMA,GAAE,KAAK,EACvCC,GAAQnB,EAAW,OAAQkB,IAAM,CAACA,GAAE,KAAK,EACzCE,GAAa,CAAC,GAAGtB,GAAM,GAAGqB,EAAK,EAErC,GAAIpB,EAAE,MAAQ,YACZA,EAAE,iBACF7B,EAAgBmD,IAAM,KAAK,IAAIA,GAAI,EAAGD,GAAW,OAAS,CAAC,CAAC,UACnDrB,EAAE,MAAQ,UACnBA,EAAE,iBACF7B,EAAgBmD,IAAM,KAAK,IAAIA,GAAI,EAAG,CAAC,CAAC,UAC/BtB,EAAE,MAAQ,SAAWA,EAAE,MAAQ,IAAK,CAC7CA,EAAE,iBACF,MAAMuB,GAAMF,GAAWnD,CAAW,EAC9BqD,KACEvB,EAAE,MAAQ,SAAWuB,GAAI,QAAoBA,EAAG,EAC1CA,GAAI,OACT/D,EAAS+D,GAAI,IAAI,EAE1B,MAAWvB,EAAE,MAAQ,cACnBA,EAAE,iBACFG,GAAA,EAEJ,EAIMqB,EAAW7E,IAAayB,GAAA,YAAAA,EAAS,OAAQP,GAAe,GAAG,EAC3D4D,EAAarD,GAAA,YAAAA,EAAS,OACtBsD,EAAUD,GAAe,KAEzBE,EAAW9D,EAAY,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,GAAG,EAAE,GAAK,IAElE,cACG,OAAI,UAAU,eAAe,UAAWqD,EAAe,SAAU,GAEhE,UAAAU,MAAC,OAAI,UAAU,0BAA0B,KAAK,aAAa,aAAW,kBACnE,SAAAJ,EAAS,IAAI,CAACK,EAAK7E,KAClB8E,OAAC,QAAoB,UAAU,+BAC5B,UAAA9E,GAAI,GAAK4E,MAAC,QAAK,UAAU,8BAA8B,cAAW,GAAC,aAAC,EACrEA,MAAC,UACC,KAAK,SACL,UAAU,8BACV,QAAS,IAAMxB,GAAWyB,EAAI,IAAI,EAClC,MAAOA,EAAI,KAEV,cAAM,EAAKA,EAAI,OAAS,IAAM,IAAMlE,EAAakE,EAAI,OACxD,GATSA,EAAI,IAUf,CACD,EACH,EAGAC,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC,OAAI,UAAU,4BACb,UAAAF,MAAC,UACC,KAAK,SACL,UAAU,wBACV,QAASzB,GACT,SAAU,CAACuB,EACX,MAAM,oBACN,aAAW,kBAEX,SAAAE,MAAC/J,GAAA,CAAU,KAAM,GAAI,IAGvB+J,MAAC,UACC,KAAK,SACL,UAAU,wBACV,QAAS,IAAMlC,EAAK7B,CAAW,EAC/B,SAAUW,EACV,MAAM,UACN,aAAW,UAEX,eAACuD,GAAA,CAAU,KAAM,GAAI,UAAWvD,EAAU,OAAS,GAAI,IAGzDoD,MAAC,UACC,KAAK,SACL,UAAU,wBACV,QAASnB,GACT,MAAM,aACN,aAAW,oBAEX,SAAAmB,MAACrI,GAAA,CAAW,KAAM,GAAI,IAGxBuI,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,UAAO,KAAK,SAAS,UAAU,oBAAoB,QAASzB,EAC3D,UAAAuB,MAACI,GAAA,CAAK,KAAM,GAAI,EAAE,IAAErE,CAAA,EACtB,EACCD,GACCoE,OAAC,UAAO,KAAK,SAAS,UAAU,oBAAoB,QAASvB,EAAY,MAAO7C,EAC9E,UAAAkE,MAACtI,GAAA,CAAW,KAAM,GAAI,EAAE,IAAEoE,EAAkB,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,GAAG,EAAE,GAAK,YACnF,GAEJ,GACF,EAECkB,EACCkD,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC,SACC,IAAKxC,EACL,KAAK,OACL,UAAU,2BACV,YAAY,cACZ,MAAON,EACP,SAAWkB,GAAM,CACfjB,EAAaiB,EAAE,OAAO,KAAK,EAC3Bf,EAAc,IAAI,CACpB,EACA,UAAW6B,GACX,aAAW,kBACX,eAAc9B,EAAa,OAAS,OACpC,mBAAkBA,EAAa,cAAgB,OAC/C,SAAUE,EACV,UAAW,MAEZF,EACC4C,MAAC,QAAK,GAAG,cAAc,UAAU,2BAA2B,KAAK,QAC9D,WACH,EAEAA,MAAC,QAAK,UAAU,0BAA0B,0CAE1C,GAEJ,EAEAA,MAAC,QAAK,UAAU,0BACb,SAAApD,EAAU,IAAM,GAAGtB,EAAQ,MAAM,OAAOyE,CAAQ,GACnD,GAEJ,EAGCjD,GACCoD,OAAC,OAAI,UAAU,qBACb,UAAAF,MAACK,GAAA,CAAY,KAAM,GAAI,EACvBL,MAAC,QAAM,SAAAlD,CAAA,CAAM,EACbkD,MAAC,UAAO,KAAK,SAAS,UAAU,qBAAqB,QAAS,IAAMlC,EAAK7B,CAAW,EAAG,iBAEvF,GACF,SAID,OAAI,UAAU,oBAAoB,MAAO,CAAE,OAAAD,GAE1C,UAAAgE,MAAC,OAAI,UAAU,sCAAsC,aAAW,cAC7D,YAAW,CAACxD,EACXwD,MAACM,GAAA,EAAa,EAEdN,MAACO,GAAA,CACC,KAAMtE,EACN,QAASkC,EACT,SAAA/B,EACA,YAAAM,EACA,SAAUyC,EACV,WAAYb,EACZ,MAAO,IAGb,EAGA4B,OAAC,OAAI,UAAU,sCAAsC,aAAW,qBAC9D,UAAAA,OAAC,OAAI,UAAU,2BACb,UAAAF,MAAC,QAAK,gBAAI,EACVA,MAAC,QAAK,gBAAI,GACZ,EAECpD,GAAW,CAACJ,EACXwD,MAACQ,GAAA,EAAa,EAEdN,OAAAO,WAAA,CAEG,WAAAjE,GAAA,YAAAA,EAAS,YACR0D,OAAC,OAAI,UAAU,gCAAgC,KAAK,SAAS,kCACrC1D,EAAQ,aAAa,oDAE7C,EAGD6B,EAAW,SAAW,EACrB2B,MAAC,OAAI,UAAU,qBAAqB,gCAAoB,EAExDA,MAAC,OAAI,UAAU,yBACZ,WAAW,IAAI,CAACvF,EAAOiG,KAAQ,CAC9B,MAAMC,GAAQlG,EAAM,MACdmG,GAAaF,KAAQpE,EACrBuE,GAAWpG,EAAM,OAASkB,EAChC,OACEuE,OAAC,OAEC,KAAK,SACL,gBAAeW,GACf,UAAW,CACT,mBACAF,GAAQ,wBAA0B,yBAClCC,IAAc,6BACdC,IAAYF,IAAS,2BACrB,CAACA,IAAS,8BACV,OAAO,OAAO,EAAE,KAAK,GAAG,EAC1B,QAAS,IAAM,CACTA,KACFpE,EAAemE,EAAG,EAClB9E,EAASnB,EAAM,IAAI,EAEvB,EACA,cAAe,IAAM,CACfkG,MAAoBlG,CAAK,CAC/B,EACA,MAAOA,EAAM,KAEb,UAAAuF,MAAC,QAAK,UAAU,wBACb,SAAAW,GAAQX,MAACc,GAAA,CAAO,KAAM,GAAI,EAAKd,MAACxI,GAAA,CAAK,KAAM,GAAI,EAClD,EACAwI,MAAC,QAAK,UAAU,wBAAyB,WAAM,KAAK,QACnD,QAAK,UAAU,wBACb,SAAAW,GAAQ,SAAW,GACtB,IA3BKlG,EAAM,KA8BjB,CAAC,EACH,GAEJ,GAEJ,GACF,EAGAyF,OAAC,OAAI,UAAU,2BAA2B,kDACHF,MAAC,OAAI,aAAC,EAAM,IAACA,MAAC,OAAI,aAAC,EAAM,iBAAcA,MAAC,OAAI,iBAAK,EAAM,gBAC9F,GACF,CAEJ,CAIA,SAASO,GAAS,CAChB,KAAA/F,EACA,QAAAc,EACA,SAAAc,EACA,YAAAM,EACA,SAAAqE,EACA,WAAAC,EACA,MAAAC,CACF,EAQG,CACD,OACEjB,MAAC,MAAG,UAAU,yBAAyB,KAAK,QACzC,SAAA1E,EAAQ,IAAKb,GAAU,CACtB,MAAMyG,EAAa9E,EAAS,IAAI3B,EAAM,IAAI,EACpC0G,EAAOzE,EAAYjC,EAAM,IAAI,GAAK,GACxC,OACEyF,OAAC,MAAoB,UAAU,yBAC7B,UAAAA,OAAC,OACC,UAAW,CACT,wBACAgB,GAAc,mCACd,OAAO,OAAO,EAAE,KAAK,GAAG,EAC1B,MAAO,CAAE,YAAa,GAAGD,EAAQ,GAAK,CAAC,MAEvC,UAAAjB,MAAC,UACC,KAAK,SACL,UAAU,2BACV,QAAU5B,GAAM,CAAEA,EAAE,kBAAmB2C,EAAStG,EAAM,IAAI,CAAG,EAC7D,aAAYyG,EAAa,WAAa,SAErC,UAAAC,EAAK,OAAS,EACbD,EAAalB,MAACoB,GAAA,CAAY,KAAM,GAAI,QAAMC,GAAA,CAAa,KAAM,GAAI,EAErC,GAIhCnB,OAAC,UACC,KAAK,SACL,UAAU,yBACV,QAAS,IAAMc,EAAWvG,CAAK,EAC/B,MAAOA,EAAM,KAEb,UAAAuF,MAACc,GAAA,CAAO,KAAM,GAAI,EAClBd,MAAC,QAAM,SAAAvF,EAAM,KAAK,IACpB,IAGDyG,GAAcC,EAAK,OAAS,GAC3BnB,MAACO,GAAA,CACC,KAAM9F,EAAM,KACZ,QAAS0G,EACT,SAAA/E,EACA,YAAAM,EACA,SAAAqE,EACA,WAAAC,EACA,MAAOC,EAAQ,GACjB,GAzCKxG,EAAM,IA2Cf,CAEJ,CAAC,EACH,CAEJ,CAIA,SAAS6F,IAAe,CACtB,OACEN,MAAC,OAAI,UAAU,6BACZ,UAAC,GAAI,GAAI,GAAI,GAAI,EAAE,EAAE,IAAI,CAACsB,EAAGlG,IAC5B4E,MAAC,OAAY,UAAU,4BAA4B,MAAO,CAAE,MAAOsB,CAAA,CAAE,EAA3DlG,CAA8D,CACzE,EACH,CAEJ,CAEA,SAASoF,IAAe,CACtB,OACER,MAAC,OAAI,UAAU,6BACZ,UAAC,GAAI,GAAI,GAAI,GAAI,GAAI,EAAE,EAAE,IAAI,CAACsB,EAAGlG,IAChC4E,MAAC,OAAY,UAAU,4BAA4B,MAAO,CAAE,MAAOsB,CAAA,CAAE,EAA3DlG,CAA8D,CACzE,EACH,CAEJ,CChlBO,MAAMmG,GAAiB,CAC5B,CAAE,GAAI,WAAY,MAAO,WAAY,KAAMjJ,EAAA,EAC3C,CAAE,GAAI,OAAQ,MAAO,OAAQ,KAAMkJ,EAAA,EACnC,CAAE,GAAI,SAAU,MAAO,SAAU,KAAMC,EAAA,EACvC,CAAE,GAAI,YAAa,MAAO,SAAU,KAAM/I,EAAA,EAC1C,CAAE,GAAI,QAAS,MAAO,QAAS,KAAMgJ,EAAA,EACrC,CAAE,GAAI,WAAY,MAAO,WAAY,KAAMC,EAAA,EAC3C,CAAE,GAAI,aAAc,MAAO,SAAU,KAAMpI,EAAA,EAC3C,CAAE,GAAI,SAAU,MAAO,SAAU,KAAMqI,EAAA,EACvC,CAAE,GAAI,SAAU,MAAO,SAAU,KAAMzL,EAAA,EACvC,CAAE,GAAI,OAAQ,MAAO,OAAQ,KAAMmD,EAAA,EACnC,CAAE,GAAI,YAAa,MAAO,YAAa,KAAMuI,EAAA,EAC7C,CAAE,GAAI,UAAW,MAAO,UAAW,KAAMC,EAAA,EACzC,CAAE,GAAI,UAAW,MAAO,QAAS,KAAMjL,EAAA,EACvC,CAAE,GAAI,WAAY,MAAO,WAAY,KAAMkL,EAAA,CAC7C,EAiCO,SAASC,GAAO,CACrB,UAAAC,EACA,YAAAC,EACA,SAAAC,EACA,QAAAC,EACA,cAAAC,EACA,SAAAC,EACA,gBAAAC,EACA,kBAAAC,EACA,aAAAC,EACA,SAAAC,EACA,UAAAC,EACA,kBAAAC,EACA,SAAAC,EAAW,GACX,UAAAC,CACF,EAAgB,CACd,OACE5C,OAAC,UAAO,UAAU,SAChB,UAAAA,OAAC,OAAI,UAAU,aACb,UAAAA,OAAC,OAAI,UAAU,QACb,UAAAF,MAAC,QAAK,UAAU,aAAa,cAAY,OAAO,aAAC,EACjDA,MAAC,QAAK,UAAU,cAAc,iBAAK,EACnCA,MAAC,QAAK,UAAU,gBAAiB,SAAAoC,CAAA,CAAQ,GAC3C,EACApC,MAAC+C,GAAA,CACC,cAAAV,EACA,SAAAC,EACA,SAAUC,EACV,UAAWC,EACX,SAAUE,GAAY,OAExBxC,OAAC,UACC,KAAK,SACL,UAAU,gBACV,QAASuC,EACT,MAAM,sBACN,aAAW,cAEX,UAAAzC,MAACgD,GAAA,CAAW,KAAM,GAAI,EACtBhD,MAAC,QAAK,UAAU,QAAQ,mBAAO,EAC/BA,MAAC,OAAI,cAAE,KAETA,MAAC,OAAI,UAAU,gBAAgB,EAC/BE,OAAC,OAAI,UAAU,eACZ,UAAA0C,EACAD,EACDzC,OAAC,OAAI,UAAW+C,EAAG,YAAa,MAAMd,CAAQ,EAAE,EAAG,MAAO,cAAcA,CAAQ,GAC9E,UAAAnC,MAAC,QAAK,UAAU,SAAS,EACzBA,MAAC,QAAK,UAAU,WAAY,SAAAmC,CAAA,CAAS,GACvC,GACF,GACF,EACCU,UACE,OAAI,UAAU,WAAW,KAAK,UAAU,aAAW,eACjD,UAAAtB,GAAK,IAAK2B,GAAQ,CACjB,MAAMC,EAAOD,EAAI,KACXE,EAASF,EAAI,KAAOjB,EAC1B,OACE/B,OAAC,UAEC,KAAK,SACL,KAAK,MACL,gBAAekD,EACf,UAAWH,EAAG,MAAOG,GAAU,YAAY,EAC3C,QAAS,IAAMlB,EAAYgB,EAAI,EAAE,EACjC,MAAOA,EAAI,MAEX,UAAAlD,MAACmD,EAAA,CAAK,KAAM,GAAI,UAAU,WAAW,EACrCnD,MAAC,QAAK,UAAU,YAAa,WAAI,MAAM,IATlCkD,EAAI,GAYf,CAAC,EACAJ,GAAaA,EAAU,OAAS,GAC/B5C,OAAAO,WAAA,CACE,UAAAT,MAAC,QAAK,UAAU,gBAAgB,cAAY,OAAO,EAClD8C,EAAU,IAAKI,GAAQ,CACtB,MAAMC,EAAOD,EAAI,KACXE,EAASF,EAAI,KAAOjB,EAC1B,OACE/B,OAAC,UAEC,KAAK,SACL,KAAK,MACL,gBAAekD,EACf,UAAWH,EAAG,MAAO,UAAWG,GAAU,YAAY,EACtD,QAAS,IAAMlB,EAAYgB,EAAI,EAAE,EACjC,MAAO,GAAGA,EAAI,KAAK,SAEnB,UAAAlD,MAACmD,EAAA,CAAK,KAAM,GAAI,UAAU,WAAW,EACrCnD,MAAC,QAAK,UAAU,YAAa,WAAI,MAAM,EACvCA,MAAC,QAAK,UAAU,YAAY,eAAG,IAV1BkD,EAAI,GAaf,CAAC,GACH,GAEJ,GAEJ,CAEJ,CAEA,SAASH,GAAgB,CACvB,cAAAV,EACA,SAAAC,EACA,SAAA1G,EACA,UAAAyH,EACA,SAAAX,CACF,EAMG,CACD,KAAM,CAACY,EAAMC,CAAO,EAAIpH,WAAS,EAAK,EAChCqH,EAAQC,GAAA,EAEdvF,YAAU,IAAM,CACd,GAAI,CAACoF,EAAM,OACX,MAAMI,EAAU,IAAMH,EAAQ,EAAK,EACnC,gBAAS,iBAAiB,QAASG,CAAO,EACnC,IAAM,SAAS,oBAAoB,QAASA,CAAO,CAC5D,EAAG,CAACJ,CAAI,CAAC,EAET,MAAMK,EAAQ,IAAM,CAClBH,EAAM,KAAK,CACT,MAAO,cACP,SACExD,MAAC4D,GAAA,CACC,SAAAlB,EACA,MAAO,MAAOlI,EAAcgB,IAAwB,CAClD,GAAI,CACF,MAAMqC,EAAI,KAAK,YAAa,CAAE,KAAArD,EAAM,KAAAgB,EAAM,EAC1C6H,EAAA,EACAE,EAAQ,EAAK,EACbC,EAAM,OACR,OAASzF,EAAK,CACZ,MAAM,eAAgBA,EAAc,OAAO,EAAE,CAC/C,CACF,IAGJ,OACEiC,MAAC,OAAI,UAAU,uBACb,SAAAA,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC9D,EAEH,CACH,EAEA,OACEtD,OAAC,OAAI,UAAU,mBAAmB,QAAU9B,GAAMA,EAAE,kBAClD,UAAA8B,OAAC,UACC,KAAK,SACL,UAAU,uBACV,QAAS,IAAMqD,EAASvE,GAAM,CAACA,CAAC,EAChC,MAAM,wBACN,gBAAc,OACd,gBAAesE,EAEf,UAAAtD,MAACc,GAAA,CAAO,KAAM,GAAI,QACjB,QAAK,UAAU,wBACb,UAAAuB,GAAA,YAAAA,EAAe,OAAQ,eAC1B,EACArC,MAACoB,GAAA,CAAY,KAAM,GAAI,KAExBkC,GACCpD,OAAC,OAAI,UAAU,wBACb,UAAAA,OAAC,OAAI,UAAU,6BACb,UAAAA,OAAC,QAAK,UAAU,QAAS,UAAAoC,EAAS,OAAO,WAASA,EAAS,SAAW,EAAI,GAAK,KAAI,EACnFpC,OAAC,OAAI,UAAU,gCACb,UAAAF,MAAC,UAAO,KAAK,SAAS,UAAU,WAAW,QAASqD,EAAW,MAAM,UAAU,aAAW,mBACxF,SAAArD,MAACG,GAAA,CAAU,KAAM,GAAI,EACvB,QACC,UAAO,KAAK,SAAS,UAAU,WAAW,QAASwD,EAAO,MAAM,cAAc,aAAW,cACxF,SAAA3D,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAClB,GACF,GACF,EACA5D,OAAC,MAAG,UAAU,wBACX,UAAAoC,EAAS,SAAW,GACnBtC,MAAC,MAAG,UAAU,+BAA+B,0CAA8B,EAE5EsC,EAAS,IAAKtH,SACZ,MACC,SAAAkF,OAAC,UACC,KAAK,SACL,UAAW+C,EAAG,yBAAyBZ,GAAA,YAAAA,EAAe,MAAOrH,EAAE,IAAM,QAAQ,EAC7E,QAAS,IAAM,CACbY,EAASZ,EAAE,EAAE,EACbuI,EAAQ,EAAK,CACf,EAEA,UAAAvD,MAAC,QAAK,UAAU,6BAA8B,SAAAhF,EAAE,KAAK,EACrDgF,MAAC,QAAK,UAAU,+BAAgC,WAAE,OAAO,IAC3D,EAXOhF,EAAE,EAYX,CACD,GACH,GACF,GAEJ,CAEJ,CAIA,SAAS4I,GAAuB,CAC9B,SAAAlB,EACA,MAAAiB,CACF,EAGG,SACD,KAAM,CAACnJ,EAAMuJ,CAAO,EAAI5H,aAAS8B,EAAAyE,GAAA,YAAAA,EAAU,YAAV,YAAAzE,EAAqB,oBAAqB,EAAE,EACvE,CAACzC,EAAMwI,CAAO,EAAI7H,WAAS,EAAE,EAC7B,CAAC8H,EAAcC,CAAe,EAAI/H,WAAS,EAAK,EAChD,CAACgI,EAAgBC,CAAiB,EAAIjI,WAAwB,IAAI,EAElEkI,EAAY,SAAY,OAC5B,GAAK7J,EACL,CAAA0J,EAAgB,EAAI,EACpBE,EAAkB,IAAI,EACtB,GAAI,CAEF,MAAMvG,EAAI,IAAsB,YAAc,mBAAmBrD,CAAI,CAAC,EACtEmJ,EAAMnJ,EAAMgB,GAAQ,IAAI,CAC1B,OAASuC,EAAK,CACZ,MAAMkB,EAASlB,EACXkB,EAAO,SAAW,IACpBmF,EAAkB,6CAA6C,EAE/DA,IACEnG,EAAAgB,EAAO,OAAP,YAAAhB,EAAa,UAAYF,EAAc,SAAW,qBAGxD,SACEmG,EAAgB,EAAK,CACvB,EACF,EAEA,cACG,OACC,UAAAlE,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCA,MAACtE,GAAA,CACC,MAAOlB,EACP,SAAWQ,GAAM,CACf+I,EAAQ/I,CAAC,EACToJ,EAAkB,IAAI,CACxB,EACA,mBAAmBE,EAAA5B,GAAA,YAAAA,EAAU,YAAV,YAAA4B,EAAqB,kBACxC,OAAQ,MAETH,GACCnE,MAAC,KAAE,UAAU,aAAa,MAAO,CAAE,MAAO,eAAgB,UAAW,GAClE,SAAAmE,CAAA,CACH,SAED,OAAI,MAAO,CAAE,UAAW,kBACvB,UAAAnE,MAAC,SAAM,UAAU,cAAc,QAAQ,0BAA0B,2BAAe,EAChFA,MAAC,SACC,GAAG,0BACH,UAAU,QACV,KAAK,OACL,YAAY,SACZ,MAAOxE,EACP,SAAW4C,GAAM4F,EAAQ5F,EAAE,OAAO,KAAK,GACzC,EACF,EACA4B,MAAC,OAAI,MAAO,CAAE,UAAW,iBAAkB,QAAS,OAAQ,eAAgB,YAC1E,SAAAE,OAAC2D,EAAA,CACC,QAAQ,UACR,QAASQ,EACT,SAAU,CAAC7J,GAAQyJ,EAElB,UAAAA,EAAejE,MAAC,QAAK,UAAU,cAAc,EAAK,KAClDiE,EAAe,YAAc,QAChC,CACF,GACF,CAEJ,CCxWO,SAASM,GAAQ,CAAE,KAAAC,EAAM,UAAAvC,EAAW,YAAAC,GAA6B,CAItE,MAAMuC,EAAUD,EAAK,OAAQE,GAAM,CAAEA,EAAmC,KAAK,EACvEC,EAAUH,EAAK,OAAQE,GAAOA,EAAmC,KAAK,EAE5E,OACE1E,MAAC,SAAM,UAAU,UAAU,aAAW,qBACpC,SAAAE,OAAC,OAAI,UAAU,cAAc,KAAK,UAC/B,UAAAuE,EAAQ,IAAKC,GAAM,CAClB,MAAMvB,EAAOuB,EAAE,KACTtB,EAASsB,EAAE,KAAOzC,EACxB,OACE/B,OAAC,UAEC,KAAK,SACL,KAAK,MACL,gBAAekD,EACf,UAAWH,EAAG,cAAeG,GAAU,oBAAoB,EAC3D,QAAS,IAAMlB,EAAYwC,EAAE,EAAE,EAC/B,MAAOA,EAAE,MAET,UAAA1E,MAACmD,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAC5BnD,MAAC,QAAK,UAAU,oBAAqB,WAAE,MAAM,IATxC0E,EAAE,GAYb,CAAC,EACAC,EAAQ,OAAS,GAChBzE,OAAAO,WAAA,CACE,UAAAT,MAAC,OAAI,UAAU,0BAA0B,cAAY,OAAO,EAC5DA,MAAC,OAAI,UAAU,wBAAwB,gBAAI,EAC1C2E,EAAQ,IAAKD,GAAM,CAClB,MAAMvB,EAAOuB,EAAE,KACTtB,EAASsB,EAAE,KAAOzC,EACxB,OACE/B,OAAC,UAEC,KAAK,SACL,KAAK,MACL,gBAAekD,EACf,UAAWH,EAAG,cAAe,kBAAmBG,GAAU,oBAAoB,EAC9E,QAAS,IAAMlB,EAAYwC,EAAE,EAAE,EAC/B,MAAO,GAAGA,EAAE,KAAK,SAEjB,UAAA1E,MAACmD,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAC5BnD,MAAC,QAAK,UAAU,oBAAqB,WAAE,MAAM,IATxC0E,EAAE,GAYb,CAAC,GACH,GAEJ,EACF,CAEJ,CCnDA,MAAME,GAAS,CACb,CAAE,GAAI,MAAO,MAAO,OACpB,CAAE,GAAI,WAAY,MAAO,YACzB,CAAE,GAAI,SAAU,MAAO,UACvB,CAAE,GAAI,QAAS,MAAO,SACtB,CAAE,GAAI,OAAQ,MAAO,QACrB,CAAE,GAAI,YAAa,MAAO,aAC1B,CAAE,GAAI,WAAY,MAAO,YACzB,CAAE,GAAI,WAAY,MAAO,WAC3B,EAEMC,GAA6E,CACjF,IAAK,KACL,SAAU,UACV,OAAQ,QACR,MAAO,OACP,KAAM,MACN,UAAW,WACX,SAAU,UACV,SAAU,SACZ,EAEO,SAASC,GAAY,CAAE,KAAAxB,EAAM,QAAAyB,EAAS,SAAAC,GAAmB,CAC9D,MAAMC,EAAQC,GAAA,EACR,CAACC,EAAGC,CAAI,EAAIjJ,WAAS,EAAE,EACvB,CAACkJ,EAAOC,CAAQ,EAAInJ,WAAsC,KAAK,EAC/D,CAACoJ,EAASC,CAAU,EAAIrJ,WAAyB,EAAE,EACnD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAK,EACtC,CAACsJ,EAAWC,CAAY,EAAIvJ,WAAS,CAAC,EACtCwJ,EAAWlI,SAAyB,IAAI,EACxCmI,EAAmBnI,SAA2B,IAAI,EAkDxD,GAhDAS,YAAU,IAAM,CACd,IAAI2H,EACJ,OAAIvC,IACFsC,EAAiB,QAAU,SAAS,yBAAyB,YACzD,SAAS,cACT,KACJR,EAAK,EAAE,EACPI,EAAW,EAAE,EACbE,EAAa,CAAC,EACdG,EAAa,OAAO,WAAW,WAAM,OAAA5H,EAAA0H,EAAS,UAAT,YAAA1H,EAAkB,SAAS,EAAE,GAE7D,IAAM,CAEX,GADI4H,GAAY,OAAO,aAAaA,CAAU,EAC1C,CAACvC,EAAM,OACX,MAAMwC,EAAWF,EAAiB,QAC9BE,GAAYA,EAAS,aAAaA,EAAS,OACjD,CACF,EAAG,CAACxC,CAAI,CAAC,EAETpF,YAAU,IAAM,CACd,GAAI,CAACoF,EAAM,OACX,GAAI,CAAC6B,EAAE,OAAQ,CACbK,EAAW,EAAE,EACbE,EAAa,CAAC,EACd,MACF,CACA,IAAIK,EAAY,GAChBlJ,EAAW,EAAI,EACf,MAAM6H,EAAI,WAAW,IAAM,CACzB7G,EACG,IAAiC,aAAa,mBAAmBsH,CAAC,CAAC,UAAUE,CAAK,EAAE,EACpF,KAAM3F,GAAM,CACPqG,IACJP,EAAW9F,EAAE,SAAW,EAAE,EAC1BgG,EAAa,CAAC,EAChB,CAAC,EACA,MAAO3H,GAAQ,CACVgI,GACJd,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CAAC,EACA,QAAQ,IAAM,CAACgI,GAAalJ,EAAW,EAAK,CAAC,CAClD,EAAG,GAAG,EACN,MAAO,IAAM,CACXkJ,EAAY,GACZ,aAAarB,CAAC,CAChB,CACF,EAAG,CAACS,EAAGE,EAAO/B,EAAM2B,CAAK,CAAC,EAEtB,CAAC3B,EAAM,OAAO,KAElB,MAAM0C,EAA0C,GAChD,UAAWtG,KAAK6F,EAAS,CACvB,MAAMU,EAAOvG,EAAE,KAAK,cACpBsG,EAAQC,CAAI,EAAID,EAAQC,CAAI,GAAK,GACjCD,EAAQC,CAAI,EAAE,KAAKvG,CAAC,CACtB,CAEA,MAAMwG,EAAuB,GAC7B,UAAWb,KAAST,GAAO,IAAKuB,GAAMA,EAAE,EAAE,EAAG,CAC3C,MAAMC,EAAavB,GAAqBQ,CAAK,EACzCe,GAAcJ,EAAQI,CAAU,KAAQ,KAAK,GAAGJ,EAAQI,CAAU,CAAC,CACzE,CAEA,MAAMC,EAASjI,GAA2B,CACxC,GAAIA,EAAE,MAAQ,SACZ2G,EAAA,UACS3G,EAAE,MAAQ,YAAa,CAEhC,GADAA,EAAE,iBACE8H,EAAK,SAAW,EAAG,OACvBR,EAActK,GAAM,KAAK,IAAIA,EAAI,EAAG8K,EAAK,OAAS,CAAC,CAAC,CACtD,SAAW9H,EAAE,MAAQ,UAAW,CAE9B,GADAA,EAAE,iBACE8H,EAAK,SAAW,EAAG,OACvBR,EAActK,GAAM,KAAK,IAAIA,EAAI,EAAG,CAAC,CAAC,CACxC,MAAWgD,EAAE,MAAQ,SAAW8H,EAAKT,CAAS,IAC5CrH,EAAE,iBACF4G,EAASkB,EAAKT,CAAS,CAAC,EACxBV,EAAA,EAEJ,EAEA,OACE/E,MAAC,OAAI,UAAU,wBAAwB,QAAS+E,EAC9C,SAAA7E,OAAC,OAAI,UAAU,eAAe,KAAK,SAAS,aAAW,OAAO,kBAAgB,qBAAqB,QAAU9B,GAAMA,EAAE,kBACnH,UAAA8B,OAAC,OAAI,UAAU,oBACb,UAAAF,MAACsG,GAAA,CAAO,KAAM,GAAI,QACjB,QAAK,GAAG,qBAAqB,UAAU,UAAU,kBAAM,EACxDtG,MAAC,SACC,IAAK2F,EACL,UAAU,qBACV,YAAY,4CACZ,MAAOR,EACP,SAAW/G,GAAMgH,EAAKhH,EAAE,OAAO,KAAK,EACpC,UAAWiI,CAAA,GAEbrG,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,QACX,QAAS+E,EAET,SAAA/E,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,QACC,OAAI,UAAU,sBACZ,SAAA3B,GAAO,IAAKuB,GACXnG,MAAC,UAEC,KAAK,SACL,UAAWiD,EAAG,eAAgBoC,IAAUc,EAAE,IAAM,qBAAqB,EACrE,QAAS,IAAMb,EAASa,EAAE,EAAE,EAE3B,SAAAA,EAAE,OALEA,EAAE,GAOV,EACH,EACAjG,OAAC,OAAI,UAAU,oBACZ,UAAAtD,GAAWoD,MAAC,OAAI,UAAU,QAAQ,sBAAU,EAC5C,CAACpD,GAAWuI,GAAKe,EAAK,SAAW,GAAKlG,MAAC,OAAI,UAAU,QAAQ,uBAAW,EACxE,CAACpD,GAAW,CAACuI,SAAM,OAAI,UAAU,QAAQ,2BAAe,EACxDP,GAAO,IAAKuB,GAAM,CACjB,MAAMC,EAAavB,GAAqBsB,EAAE,EAAE,EAC5C,GAAI,CAACC,EAAY,OAAO,KACxB,MAAMI,EAAOR,EAAQI,CAAU,EAC/B,MAAI,CAACI,GAAQA,EAAK,SAAW,EAAU,KAErCtG,OAAC,OAAe,UAAU,eACxB,UAAAF,MAAC,OAAI,UAAU,oBAAqB,SAAAmG,EAAE,MAAM,EAC3CK,EAAK,IAAK9G,GAAM,CACf,MAAM+G,EAAUP,EAAK,QAAQxG,CAAC,EAC9B,OACEQ,OAAC,UACC,KAAK,SAEL,UAAW+C,EAAG,gBAAiBwD,IAAYhB,GAAa,sBAAsB,EAC9E,aAAc,IAAMC,EAAae,CAAO,EACxC,QAAS,IAAM,CACbzB,EAAStF,CAAC,EACVqF,EAAA,CACF,EAEA,UAAA/E,MAAC,QAAK,UAAU,qBAAsB,SAAAN,EAAE,KAAK,QAC5C,QAAK,UAAU,sBACb,SAAAgH,GAAUhH,CAAC,EACd,IAXK,GAAGA,EAAE,IAAI,IAAI+G,CAAO,GAc/B,CAAC,IArBON,EAAE,EAsBZ,CAEJ,CAAC,GACH,EACAnG,MAAC,OAAI,UAAU,oBACb,eAAC,QAAK,UAAU,QAAQ,4CAAgC,EAC1D,GACF,EACF,CAEJ,CAEA,SAAS0G,GAAUhH,EAAyB,CAC1C,MAAMtE,EAAIsE,EAAE,MAAQ,GACpB,GAAIA,EAAE,OAAS,UAAW,MAAO,GAAGtE,EAAE,IAAI,MAAMA,EAAE,IAAI,GACtD,GAAIsE,EAAE,OAAS,QAAS,MAAO,GAAGtE,EAAE,IAAI,MAAMA,EAAE,aAAeA,EAAE,OAAS,EAAE,GAC5E,GAAIsE,EAAE,OAAS,OAAQ,MAAO,GAAGtE,EAAE,KAAK,MAAOA,EAAE,QAAU,EAAG,GAC9D,GAAIsE,EAAE,OAAS,MAAO,MAAO,GAAGtE,EAAE,IAAI,KAAKA,EAAE,OAAO,MAAMA,EAAE,aAAe,EAAE,GAC7E,GAAIsE,EAAE,OAAS,WAAY,MAAO,GAAGtE,EAAE,IAAI,KAAKA,EAAE,IAAI,KAAKA,EAAE,QAAQ,IACrE,GAAIsE,EAAE,OAAS,UAAW,MAAO,GAAGtE,EAAE,IAAI,MAAMA,EAAE,aAAe,EAAE,GACnE,GAAIsE,EAAE,OAAS,UAAW,CACxB,MAAMiH,EAAMvL,EAAE,QAAU,MAAQA,EAAE,QAAU,OACxC,GACA,OAAOA,EAAE,OAAU,SACjB,MAAMA,EAAE,KAAK,GACb,MAAM,KAAK,UAAUA,EAAE,KAAK,CAAC,GACnC,MAAO,GAAGA,EAAE,KAAK,GAAGuL,CAAG,QAAQvL,EAAE,MAAQ,EAAE,GAAG,MAChD,CACA,OAAO,KAAK,UAAUA,CAAC,EAAE,MAAM,EAAG,EAAE,CACtC,CCrNA,MAAMwL,GAAqC,CACzC,KAAMC,GACN,QAASC,GACT,QAASC,GACT,MAAO1G,EACT,EASO,SAAS2G,GAAc,CAAE,cAAAC,EAAe,YAAAC,GAAsB,CACnE,MAAMjC,EAAQC,GAAA,EACR,CAAC5B,EAAMC,CAAO,EAAIpH,WAAS,EAAK,EAChC,CAACgL,EAAOC,CAAQ,EAAIjL,WAAyB,EAAE,EAC/C,CAACkL,EAAOC,CAAQ,EAAInL,WAAmC,IAAI,EAC3D,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAK,EACtCoL,EAAU9J,SAA8B,IAAI,EAC5C+J,EAAY/J,SAAO,CAAC,EAEpBgK,EAAS,SAAY,OACzB,GAAI,CACF5K,EAAW,EAAI,EACf,MAAM6C,EAAI,MAAM7B,EAAI,IAClB,4BAEFuJ,EAAS1H,EAAE,eAAiB,EAAE,EAC9B4H,EAAS5H,EAAE,OAAS,IAAI,EACxB8H,EAAU,UAAUvJ,EAAAyB,EAAE,QAAF,YAAAzB,EAAS,SAAU,EACvCgJ,GAAA,MAAAA,EAAgBO,EAAU,QAC5B,OAASzJ,EAAK,CAGZ,QAAQ,KAAK,iCAAmCA,EAAc,OAAO,CACvE,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,EAAE,EAGLvJ,YAAU,IACHgJ,EACOA,EAAalJ,GAAQ,CAC/B,GAAIA,EAAI,OAAS,mBAAoB,CACnC,MAAM0J,EAAW1J,EAAI,aACrBoJ,EAAUO,GAAQ,CAACD,EAAU,GAAGC,EAAI,OAAQC,GAAMA,EAAE,KAAOF,EAAS,EAAE,CAAC,CAAC,EAEnEA,EAAS,OACZF,EAAU,SAAW,EACrBF,EAAUK,GACRA,EAAM,CAAE,GAAGA,EAAK,QAASA,EAAI,QAAU,GAAK,GAAM,CAAE,MAAO,EAAG,OAAQ,EAAG,OAAQD,EAAS,GAAI,OAAQ,CAAE,CAACA,EAAS,UAAY,MAAM,EAAG,EAAE,CAAE,EAE7IT,GAAA,MAAAA,EAAgBO,EAAU,SAE9B,MAAWxJ,EAAI,OAAS,wBAEtByJ,EAAA,CAEJ,CAAC,EAjBiB,OAoBjB,CAACP,CAAW,CAAC,EAGhBhJ,YAAU,IAAM,CACd,GAAI,CAACoF,EAAM,OACX,MAAMuE,EAAczJ,GAAkB,CAC/BmJ,EAAQ,UACRA,EAAQ,QAAQ,SAASnJ,EAAE,MAAc,GAC5CmF,EAAQ,EAAK,EAEjB,EACMuE,EAAa1J,GAAqB,CAClCA,EAAE,MAAQ,UAAUmF,EAAQ,EAAK,CACvC,EACA,gBAAS,iBAAiB,YAAasE,CAAU,EACjD,SAAS,iBAAiB,UAAWC,CAAS,EACvC,IAAM,CACX,SAAS,oBAAoB,YAAaD,CAAU,EACpD,SAAS,oBAAoB,UAAWC,CAAS,CACnD,CACF,EAAG,CAACxE,CAAI,CAAC,EAET,MAAMyE,EAAgB,SAAY,CAChC,GAAI,CACF,MAAMlK,EAAI,KAAK,0BAA2B,EAAE,EAC5CuJ,EAAUO,GAAQA,EAAI,IAAKC,IAAO,CAAE,GAAGA,EAAG,KAAM,IAAO,CAAC,EACxDN,EAAUK,GAASA,GAAM,CAAE,GAAGA,EAAK,OAAQ,EAAU,EACrDH,EAAU,QAAU,EACpBP,GAAA,MAAAA,EAAgB,GAChBhC,EAAM,QAAQ,oCAAqC,IAAI,CACzD,OAASlH,EAAK,CACZkH,EAAM,MAAM,WAAYlH,EAAc,OAAO,EAAE,CACjD,CACF,EAEMiK,EAAa,MAAOC,GAAe,CACvC,GAAI,CACF,MAAMpK,EAAI,KAAK,kBAAkB,mBAAmBoK,CAAE,CAAC,QAAS,EAAE,EAClEb,EAAUO,GAAQA,EAAI,IAAKC,GAAOA,EAAE,KAAOK,EAAK,CAAE,GAAGL,EAAG,KAAM,IAASA,CAAE,CAAC,EAC1EN,EAAUK,GAASA,GAAM,CAAE,GAAGA,EAAK,OAAQ,KAAK,IAAI,GAAIA,EAAI,QAAU,GAAK,CAAC,EAAU,EACtFH,EAAU,QAAU,KAAK,IAAI,EAAGA,EAAU,QAAU,CAAC,EACrDP,GAAA,MAAAA,EAAgBO,EAAU,QAC5B,OAASzJ,EAAK,CACZkH,EAAM,MAAM,WAAYlH,EAAc,OAAO,EAAE,CACjD,CACF,EAEMmK,EAAW,MAAOD,GAAe,CACrC,GAAI,CACF,MAAMpK,EAAI,IAAI,kBAAkB,mBAAmBoK,CAAE,CAAC,EAAE,EACxDb,EAAUO,GAAQ,CAChB,MAAMQ,EAAUR,EAAI,KAAMC,GAAMA,EAAE,KAAOK,CAAE,EAC3C,OAAIE,GAAW,CAACA,EAAQ,OACtBX,EAAU,QAAU,KAAK,IAAI,EAAGA,EAAU,QAAU,CAAC,EACrDF,EAAUc,GAAcA,GAAW,CAAE,GAAGA,EAAU,OAAQ,KAAK,IAAI,EAAGA,EAAS,OAAS,CAAC,EAAe,EACxGnB,GAAA,MAAAA,EAAgBO,EAAU,UAErBG,EAAI,OAAQC,GAAMA,EAAE,KAAOK,CAAE,CACtC,CAAC,CACH,OAASlK,EAAK,CACZkH,EAAM,MAAM,WAAYlH,EAAc,OAAO,EAAE,CACjD,CACF,EAEMsK,GAAShB,GAAA,YAAAA,EAAO,SAAU,EAEhC,OACEnH,OAAC,OAAI,UAAU,qBAAqB,IAAKqH,EACvC,UAAArH,OAAC,UACC,KAAK,SACL,UAAW+C,EAAG,qCAAsCK,GAAQ,SAAS,EACrE,QAAS,IAAMC,EAAS,GAAM,CAAC,CAAC,EAChC,MAAM,gBACN,aAAW,gBACX,gBAAc,OACd,gBAAeD,EAEf,UAAAtD,MAACsI,GAAA,CAAK,KAAM,GAAI,EACfD,EAAS,GAAKrI,MAAC,QAAK,UAAU,sBAAuB,SAAAqI,EAAS,GAAK,MAAQA,CAAA,CAAO,KAEpF/E,UACE,OAAI,UAAU,sBAAsB,KAAK,SAAS,aAAW,gBAC5D,UAAApD,OAAC,UAAO,UAAU,2BAChB,UAAAA,OAAC,OACC,UAAAF,MAAC,UAAO,yBAAa,EACpBqI,EAAS,GAAKnI,OAAC,QAAK,UAAU,gBAAgB,gBAAImI,EAAO,WAAO,GACnE,EACAnI,OAAC,OAAI,UAAU,mCACb,UAAAA,OAAC2D,EAAA,CAAO,KAAK,KAAK,QAAQ,QAAQ,QAASkE,EAAe,SAAUM,IAAW,EAC7E,UAAArI,MAAC1J,GAAA,CAAM,KAAM,GAAI,EAAE,kBACrB,EACA0J,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAMuD,EAAQ,EAAK,EAC5B,aAAW,QACX,MAAM,QAEN,SAAAvD,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,GACF,EACAvG,MAAC,OAAI,UAAU,qBACZ,SAAApD,GAAWuK,EAAM,SAAW,EAC3BnH,MAAC,OAAI,UAAU,4BAA4B,oBAAQ,EACjDmH,EAAM,SAAW,EACnBnH,MAAC,OAAI,UAAU,4BAA4B,iCAAqB,EAEhEmH,EAAM,IAAKS,GAAM,CACf,MAAMzE,EAAOyD,GAAMgB,EAAE,QAAQ,GAAKf,GAClC,OACE3G,OAAC,OAEC,UAAW+C,EAAG,oBAAqB,CAAC2E,EAAE,MAAQ,YAAa,YAAYA,EAAE,QAAQ,EAAE,EAEnF,UAAA5H,MAACmD,GAAK,KAAM,GAAI,UAAW,8BAA8ByE,EAAE,QAAQ,GAAI,EACvE1H,OAAC,OAAI,UAAU,oBACZ,UAAA0H,EAAE,OAAS5H,MAAC,OAAI,UAAU,qBAAsB,WAAE,MAAM,EACzDA,MAAC,OAAI,UAAU,mBAAoB,WAAE,QAAQ,EAC7CE,OAAC,OAAI,UAAU,0BACb,UAAAF,MAAC,QAAK,UAAU,OAAQ,SAAA4H,EAAE,OAAO,EACjC5H,MAAC,QAAK,aAAC,EACPA,MAAC,QAAM,SAAAuI,GAAeX,EAAE,EAAE,EAAE,GAC9B,GACF,EACA1H,OAAC,OAAI,UAAU,uBACZ,WAAC0H,EAAE,MACF5H,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAMgI,EAAWJ,EAAE,EAAE,EAC9B,MAAM,eACN,aAAW,eAEX,SAAA5H,MAAC1J,GAAA,CAAM,KAAM,GAAI,IAGrB0J,MAAC,UACC,KAAK,SACL,UAAU,2BACV,QAAS,IAAMkI,EAASN,EAAE,EAAE,EAC5B,MAAM,SACN,aAAW,SAEX,SAAA5H,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,IAlCKqB,EAAE,GAqCb,CAAC,EAEL,EACA5H,MAAC,UAAO,UAAU,2BAChB,SAAAA,MAAC,QAAK,UAAU,gBACb,SAAAqH,EAAQ,GAAGA,EAAM,KAAK,iBAAiBkB,GAAelB,EAAM,QAAU,IAAI,OAAO,aAAa,CAAC,GAAK,GACvG,EACF,GACF,GAEJ,CAEJ,CCvOO,SAASmB,GAAiB,CAAE,KAAA7N,EAAM,QAAAoK,GAAkC,CACzE,MAAM0D,EAAU9N,GAAA,YAAAA,EAAM,QACEA,GAAA,MAAAA,EAAM,gBAC9B,MAAM+N,EAAO/N,GAAA,YAAAA,EAAM,KACbgO,EAAkBhO,GAAA,YAAAA,EAAM,gBACxBiO,EAAejO,GAAA,YAAAA,EAAM,aAErBkO,EAAaH,IAAS,SAE5B,cACG,OACE,UAAAG,EACC3I,OAAC,KAAE,MAAO,CAAE,aAAc,GAAI,WAAY,KAAO,uCACrBF,MAAC,UAAQ,SAAAyI,EAAU,UAAY,WAAW,EAAS,IAC5EA,EACG,6EACA,sDACN,EAEAvI,OAAC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAA,OAAC,KAAE,MAAO,CAAE,aAAc,EAAG,WAAY,KAAO,0BACjCF,MAAC,QAAK,MAAO,CAAE,MAAOyI,EAAU,uBAAyB,sBACnE,SAAAA,EAAU,KAAO,MACpB,GACF,EACAzI,MAAC,KAAE,MAAO,CAAE,WAAY,IAAK,MAAO,qBAAsB,SAAU,IAAM,2HAE1E,EACC2I,GACCzI,OAAC,KAAE,MAAO,CAAE,UAAW,EAAG,SAAU,GAAI,MAAO,sBAAwB,+BACnDF,MAAC,QAAM,SAAA2I,CAAA,CAAgB,GAC3C,EAEDC,UACE,KAAE,MAAO,CAAE,SAAU,GAAI,MAAO,sBAAwB,6BACvC5I,MAAC,QAAM,SAAA4I,CAAA,CAAa,GACtC,EAEF1I,OAAC,KAAE,MAAO,CAAE,UAAW,GAAI,SAAU,GAAI,MAAO,sBAAwB,iBAClEF,MAAC,QAAK,2BAAe,EAAO,OAAIA,MAAC,QAAK,4BAAgB,EAAO,eACnE,GACF,QAED,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,eAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAASkB,EAAS,iBAAK,EACjD,GACF,CAEJ,CC9CA,MAAM+D,GAAkB,CACtB,QACA,iBACA,oBACA,kBACA,aACA,UACF,EAEO,SAASC,GAAqB,CAAE,KAAApO,EAAM,QAAAoK,GAAsC,CACjF,MAAMiE,GAAarO,GAAA,YAAAA,EAAM,YAA0BmO,GAC7CH,GAAmBhO,GAAA,YAAAA,EAAM,kBAA8B,QAEvD,CAACsO,EAAMC,CAAO,EAAI/M,WAAS,EAAE,EAC7B,CAACgN,EAAkBC,CAAmB,EAAIjN,WAASwM,CAAe,EAClE,CAACU,EAAUC,CAAW,EAAInN,WAAS,EAAK,EACxC,CAACW,EAAOC,CAAQ,EAAIZ,WAAwB,IAAI,EAEhDoN,EAAe,SAAY,CAC/B,GAAI,CAACN,EAAK,OAAQ,CAChBlM,EAAS,mBAAmB,EAC5B,MACF,CACA,GAAI,CAAC,4BAA4B,KAAKkM,CAAI,EAAG,CAC3ClM,EAAS,uGAAuG,EAChH,MACF,CACAuM,EAAY,EAAI,EAChBvM,EAAS,IAAI,EACb,GAAI,CACF,MAAMc,EAAI,KAAK,aAAc,CAAE,KAAAoL,EAAM,SAAUE,EAAkB,EACjEpE,EAAA,CACF,OAAShH,EAAK,CACZhB,EAAUgB,EAAc,OAAO,EAC/BuL,EAAY,EAAK,CACnB,CACF,EAEA,cACG,OACC,UAAApJ,OAAC,KAAE,MAAO,CAAE,aAAc,GAAI,MAAO,qBAAsB,SAAU,IAAM,2DAC3BF,MAAC,QAAK,sBAAU,EAAO,sBACvE,SAEC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAA,MAAC,SAAM,UAAU,cAAc,QAAQ,YAAY,qBAAS,EAC5DA,MAAC,SACC,GAAG,YACH,UAAU,QACV,KAAK,OACL,YAAY,kBACZ,MAAOiJ,EACP,SAAW7K,GAAM,CAAE8K,EAAQ9K,EAAE,OAAO,KAAK,EAAGrB,EAAS,IAAI,CAAG,EAC5D,UAAS,IACX,EACF,SAEC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAiD,MAAC,SAAM,UAAU,cAAc,QAAQ,gBAAgB,oBAAQ,EAC/DA,MAAC,UACC,GAAG,gBACH,UAAU,SACV,MAAOmJ,EACP,SAAW/K,GAAMgL,EAAoBhL,EAAE,OAAO,KAAK,EAElD,SAAA4K,EAAU,IAAKtE,GACd1E,MAAC,UAAe,MAAO0E,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,EACF,EAEC5H,GACCkD,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,MAAO,sBAAuB,SAAU,IAAO,SAAAlD,CAAA,CAAM,EAGrFoD,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,UAAAF,MAAC6D,GAAO,QAAQ,QAAQ,QAASkB,EAAS,SAAUsE,EAAU,kBAAM,EACpErJ,MAAC6D,EAAA,CAAO,QAAQ,UAAU,QAAS0F,EAAc,SAAUF,GAAY,CAACJ,EAAK,OAC1E,SAAAI,EAAW,YAAc,SAC5B,GACF,GACF,CAEJ,CCrFO,SAASG,GAAmB,CAAE,KAAA7O,EAAM,QAAAoK,GAAoC,CAC7E,MAAM0E,GAAS9O,GAAA,YAAAA,EAAM,QAAsB,GACrC+O,GAAS/O,GAAA,YAAAA,EAAM,QAAoB8O,EAAM,OAEzCE,EAAcV,GAAiB,CACnC,OAAO,KAAK,cAAcA,CAAI,IAAK,QAAQ,CAC7C,EAEA,cACG,OACE,UAAAQ,EAAM,SAAW,EAChBvJ,OAAC,KAAE,MAAO,CAAE,aAAc,GAAI,MAAO,sBAAwB,kDACtBF,MAAC,QAAK,gCAA0B,EAAO,mBAC9E,EAEAE,OAAC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAA,OAAC,KAAE,MAAO,CAAE,aAAc,GAAI,SAAU,GAAI,MAAO,sBAChD,UAAAwJ,EAAM,QAAMA,IAAU,EAAI,IAAM,GAAG,sBACtC,EACA1J,MAAC,MAAG,MAAO,CAAE,UAAW,OAAQ,QAAS,EAAG,OAAQ,GACjD,SAAAyJ,EAAM,IAAKR,GACV/I,OAAC,MAEC,MAAO,CACL,QAAS,OACT,WAAY,SACZ,eAAgB,gBAChB,QAAS,QACT,aAAc,iCAGhB,UAAAF,MAAC,QAAK,MAAO,CAAE,SAAU,IAAO,SAAAiJ,EAAK,EACrCjJ,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS,IAAM8F,EAAWV,CAAI,EAAG,gBAEnE,IAZKA,CAAA,CAcR,EACH,GACF,QAED,OAAI,MAAO,CAAE,QAAS,OAAQ,eAAgB,YAC7C,SAAAjJ,MAAC6D,GAAO,QAAQ,QAAQ,QAASkB,EAAS,iBAAK,EACjD,GACF,CAEJ,CC3CO,SAAS6E,GAAW,CAAE,KAAAjP,EAAM,QAAAoK,GAA4B,CAC7D,MAAM8E,GAAYlP,GAAA,YAAAA,EAAM,WAA2B,GAC7CqO,GAAarO,GAAA,YAAAA,EAAM,YAA0B,GAC7CmP,GAAYnP,GAAA,YAAAA,EAAM,WAAyB,GAEjD,cACG,OACE,UAAAkP,EAAS,OAAS,EACjB7J,MAAC,SAAM,MAAO,CAAE,MAAO,OAAQ,eAAgB,WAAY,aAAc,GAAI,SAAU,IACrF,SAAAA,MAAC,SACE,SAAA6J,EAAS,IAAKpP,GACbyF,OAAC,MAAmB,MAAO,CAAE,aAAc,iCACzC,UAAAF,MAAC,MAAG,MAAO,CAAE,QAAS,gBAAiB,WAAY,UACjD,SAAAA,MAAC,QAAK,MAAO,CAAE,SAAU,IAAO,SAAAvF,EAAM,IAAI,EAC5C,EACAuF,MAAC,MAAG,MAAO,CAAE,QAAS,QAAS,MAAO,sBAAyB,SAAAvF,EAAM,KAAK,IAJnEA,EAAM,GAKf,CACD,EACH,EACF,EAEAuF,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,MAAO,sBAAwB,kCAAsB,EAGpFgJ,EAAU,OAAS,GAClB9I,OAAC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAF,MAAC,KAAE,MAAO,CAAE,SAAU,GAAI,MAAO,qBAAsB,aAAc,GAAK,gCAAoB,EAC9FA,MAAC,KAAE,MAAO,CAAE,SAAU,IAAO,SAAAgJ,EAAU,KAAK,IAAI,EAAE,GACpD,EAGDc,EAAS,OAAS,GACjB5J,OAAC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAF,MAAC,KAAE,MAAO,CAAE,SAAU,GAAI,MAAO,qBAAsB,aAAc,GAAK,+BAAmB,EAC7FA,MAAC,KAAE,MAAO,CAAE,SAAU,IAAO,SAAA8J,EAAS,KAAK,IAAI,EAAE,GACnD,QAGD,OAAI,MAAO,CAAE,QAAS,OAAQ,eAAgB,YAC7C,SAAA9J,MAAC6D,GAAO,QAAQ,QAAQ,QAASkB,EAAS,iBAAK,EACjD,GACF,CAEJ,CCrCO,SAASgF,GAAY,CAAE,KAAApP,EAAM,QAAAoK,GAA6B,CAC/D,KAAM,CAACiF,EAASC,CAAU,EAAI9N,WAAS,EAAK,EACtC,CAACjB,EAAQgP,CAAS,EAAI/N,WAA6B,IAAI,EAEvDgO,EAAiB,SAAY,CACjCF,EAAW,EAAI,EACfC,EAAU,IAAI,EACd,GAAI,CAIF,MAAME,EAAM,MAAMvM,EAAI,KAAkB,cAAe,EAAE,EACzDqM,EAAUE,CAAG,CACf,OAASrM,EAAK,CACZmM,EAAU,CAAE,GAAI,GAAO,SAAU,GAAI,MAAQnM,EAAc,QAAS,CACtE,SACEkM,EAAW,EAAK,CAClB,CACF,EAEA,OACEjK,MAAC,OACE,SAAA9E,IAAW,KACVgF,OAAAO,WAAA,CACE,UAAAT,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,WAAY,KAAO,0JAEjD,EACAE,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAASkB,EAAS,kBAAM,EAChD/E,MAAC6D,EAAA,CAAO,QAAQ,UAAU,QAASsG,EAAgB,SAAUH,EAC1D,SAAAA,EAAU,WAAa,YAC1B,GACF,GACF,EAEA9J,OAAAO,WAAA,CACG,UAAAvF,EAAO,UACL,OACC,UAAA8E,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,WAAY,IAAK,MAAO,wBAA0B,2CAEhF,EACC9E,EAAO,SAAS,OAAS,GACxB8E,MAAC,MAAG,MAAO,CAAE,aAAc,GAAI,YAAa,IACzC,SAAA9E,EAAO,SAAS,IAAI,CAACmP,EAAGjP,IACvB4E,MAAC,MAAW,MAAO,CAAE,aAAc,EAAG,SAAU,IAAO,SAAAqK,CAAA,EAA9CjP,CAAgD,CAC1D,EACH,GAEJ,SAEC,KAAE,MAAO,CAAE,aAAc,GAAI,MAAO,uBAAyB,2BAC7CF,EAAO,OAAS,iBACjC,QAED,OAAI,MAAO,CAAE,QAAS,OAAQ,eAAgB,YAC7C,SAAA8E,MAAC6D,GAAO,QAAQ,QAAQ,QAASkB,EAAS,iBAAK,EACjD,GACF,EAEJ,CAEJ,CClEA,SAASuF,GAAc,CAAE,OAAAC,EAAQ,QAAAxF,GAA8D,CAC7F,GAAI,CAACwF,EAAO,KACV,cACG,OACC,UAAAvK,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,WAAY,KACvC,qBAAYuK,EAAO,OAAO,GAC7B,QACC,OAAI,MAAO,CAAE,QAAS,OAAQ,eAAgB,YAC7C,SAAAvK,MAAC,UAAO,KAAK,SAAS,UAAU,MAAM,QAAS+E,EAAS,iBAAK,EAC/D,GACF,EAIJ,KAAM,CAAE,QAAAyF,EAAS,OAAAC,EAAQ,IAAAC,CAAA,EAAQH,EAAO,KAExC,cACG,OACC,UAAAvK,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,WAAY,KACvC,SAAAwK,GAAW,YAAYD,EAAO,OAAO,GACxC,EACCE,GACCzK,MAAC,KAAE,MAAO,CAAE,aAAc,GAAI,MAAO,qBAAsB,SAAU,IAClE,SAAAyK,CAAA,CACH,EAEDC,GACC1K,MAAC,KAAE,MAAO,CAAE,aAAc,IACxB,SAAAA,MAAC,KAAE,KAAM0K,EAAK,OAAO,SAAS,IAAI,sBAAuB,WAAI,EAC/D,QAED,OAAI,MAAO,CAAE,QAAS,OAAQ,eAAgB,YAC7C,SAAA1K,MAAC,UAAO,KAAK,SAAS,UAAU,MAAM,QAAS+E,EAAS,iBAAK,EAC/D,GACF,CAEJ,CAEO,SAAS4F,GAAc,CAAE,OAAAJ,EAAQ,QAAAxF,GAA8D,CACpG,OAAQwF,EAAO,WACb,IAAK,kBACH,OAAOvK,MAACwI,GAAA,CAAiB,KAAM+B,EAAO,KAAM,QAAAxF,EAAkB,EAChE,IAAK,kBACH,OAAO/E,MAAC+I,GAAA,CAAqB,KAAMwB,EAAO,KAAM,QAAAxF,EAAkB,EACpE,IAAK,gBACH,OAAO/E,MAACwJ,GAAA,CAAmB,KAAMe,EAAO,KAAM,QAAAxF,EAAkB,EAClE,IAAK,OACH,OAAO/E,MAAC4J,GAAA,CAAW,KAAMW,EAAO,KAAM,QAAAxF,EAAkB,EAC1D,IAAK,QACH,OAAO/E,MAAC+J,GAAA,CAAY,KAAMQ,EAAO,KAAM,QAAAxF,EAAkB,EAC3D,QACE,OAAO/E,MAACsK,GAAA,CAAc,OAAAC,EAAgB,QAAAxF,CAAA,CAAkB,EAE9D,CCtDO,SAAS6F,EAAK,CACnB,QAAAC,EAAU,WACV,YAAAC,EAAc,GACd,UAAAC,EACA,SAAAC,EACA,GAAGC,CACL,EAAc,CACZ,OACEjL,MAAC,OACC,UAAWiD,EACT,OACA,QAAQ4H,CAAO,GACfC,GAAe,mBACfC,CAAA,EAED,GAAGE,EAEH,SAAAD,CAAA,EAGP,CAEO,SAASE,GAAU,CAAE,SAAAF,EAAU,UAAAD,GAA0D,CAC9F,aAAQ,MAAG,UAAW9H,EAAG,aAAc8H,CAAS,EAAI,SAAAC,EAAS,CAC/D,CAEO,SAASG,GAAS,CAAE,SAAAH,EAAU,UAAAD,GAA0D,CAC7F,aAAQ,OAAI,UAAW9H,EAAG,YAAa8H,CAAS,EAAI,SAAAC,EAAS,CAC/D,CCHO,SAASI,GAAiB,CAAE,aAAAC,EAAc,WAAAC,EAAa,GAAY,OACxE,KAAM,CAAC3Q,EAAM4Q,CAAO,EAAIpP,WAAgC,IAAI,EACtD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EAErCsL,EAAS,SAAY,CACzB5K,EAAW,EAAI,EACf,GAAI,CACF,KAAM,CAAC2O,EAAQC,EAAQC,CAAQ,EAAI,MAAM,QAAQ,IAAI,CACnD7N,EAAI,IAAoB,gBAAgB,EAAE,MAAM,IAAM,IAAI,EAC1DA,EAAI,IACF,kBACA,MAAM,IAAM,IAAI,EAClBA,EAAI,IAAiD,wBAAwB,EAAE,MAAM,IAAM,IAAI,EAChG,EACD0N,EAAQ,CACN,YAAa,CAAC,EAACC,GAAA,MAAAA,EAAQ,aACvB,KAAMA,GAAA,YAAAA,EAAQ,KACd,UAAWA,GAAA,YAAAA,EAAQ,UACnB,UAAWA,GAAA,YAAAA,EAAQ,UACnB,OAAQA,GAAA,YAAAA,EAAQ,OAChB,SAAUA,GAAA,YAAAA,EAAQ,SAClB,WAAWA,GAAA,YAAAA,EAAQ,YAAa,EAChC,YAAaC,GAAA,YAAAA,EAAQ,MACrB,aAAcA,GAAA,YAAAA,EAAQ,OACtB,SAAUC,EAAW,CAAE,QAASA,EAAS,QAAS,cAAeA,EAAS,eAAkB,OAC7F,CACH,MAAQ,CACNH,EAAQ,CAAE,YAAa,GAAO,CAChC,SACE1O,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,CAAC6D,CAAU,CAAC,EAEf,MAAMK,EAAa,IAAMN,EAAa,QAAQ,EAExCO,GACJjR,GAAA,YAAAA,EAAM,gBAAiB,UAAY,kBACnCA,GAAA,YAAAA,EAAM,gBAAiB,WAAa,kBACpCA,GAAA,YAAAA,EAAM,gBAAiB,YAAc,eACrC,kBAEF,OACEuF,OAAC0K,EAAA,CAAK,UAAU,uBACd,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,UACnB+J,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,MAAO,CAAE,WAAY,QAAU,QAAS8H,EAAY,yBACxE3L,MAAC6L,GAAA,CAAa,KAAM,GAAI,GACtC,QACChI,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS4D,EAAQ,aAAW,UAAU,MAAM,UAC5E,SAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EACvB,GACF,EACAH,MAACmL,IAAS,kFAEV,EAEExQ,GAAA,MAAAA,EAAM,YAKNuF,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC,OAAI,UAAU,2BACb,UAAAF,MAAC2B,GAAA,CAAS,KAAM,GAAI,EAAE,WACxB,QACC,OAAI,UAAU,2BAA2B,MAAO,CAAE,MAAOiK,GACvD,SAAAjR,EAAK,cAAgB,OAAY,GAAGA,EAAK,WAAW,OAAS,IAChE,QACC,OAAI,UAAU,+BAAgC,SAAAA,EAAK,cAAgB,IAAI,GAC1E,EAEAuF,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC,OAAI,UAAU,2BACb,UAAAF,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,aACrB,EACA6J,MAAC,OAAI,UAAU,2BACZ,cAAK,mBAAU,QAAU,UAAY,UACxC,EACAA,MAAC,OAAI,UAAU,+BACZ,SAAArF,EAAK,SAAW,GAAGA,EAAK,SAAS,aAAa,UAAY,IAC7D,GACF,EAEAuF,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC,OAAI,UAAU,2BACb,UAAAF,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAAE,UACxB,EACA5L,OAAC,OAAI,UAAU,2BAA4B,UAAAvF,EAAK,UAAU,UAAM,EAChEqF,MAAC,OAAI,UAAU,wCAAwC,MAAOrF,EAAK,WAAa,GAC7E,SAAAA,EAAK,UAAYA,EAAK,UAAU,MAAM,GAAG,EAAE,MAAM,EAAE,EAAE,KAAK,GAAG,EAAI,IACpE,GACF,EAEAuF,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC,OAAI,UAAU,2BACb,UAAAF,MAACnI,GAAA,CAAU,KAAM,GAAI,EAAE,QACzB,EACAmI,MAAC,OAAI,UAAU,2BACZ,WAAK,WAAa,KACfrF,EAAK,OAAS,aAAe,aAAe,IAC5CA,EAAK,SAAW,QAAU,QAChC,EACAqF,MAAC,OAAI,UAAU,+BACZ,WAAK,OAAS,UAAUrF,EAAK,MAAM,GAAKoR,GAAWpR,EAAK,QAAU,EAAE,GAAK,IAC5E,GACF,GACF,EAlDAuF,OAAC,OAAI,UAAU,QAAQ,2CACSF,MAAC,UAAO,uBAAW,EAAS,kBAC5D,EAmDDpD,GAAW,CAACjC,SACV,OAAI,UAAU,gBAAgB,oBAAQ,GAE3C,CAEJ,CC9IO,SAASqR,GAAW,CACzB,KAAAC,EACA,MAAAC,EACA,QAAA1B,EACA,OAAA2B,EACA,UAAApB,CACF,EAAoB,CAClB,cACG,OAAI,UAAW9H,EAAG,cAAe8H,CAAS,EACzC,UAAA/K,MAAC,OAAI,UAAU,aAAc,SAAAiM,SAAS9T,GAAA,CAAM,KAAM,GAAI,EAAG,EACzD6H,MAAC,OAAI,UAAU,cAAe,SAAAkM,EAAM,EACnC1B,GAAWxK,MAAC,OAAI,UAAU,gBAAiB,SAAAwK,EAAQ,EACnD2B,GAAUnM,MAAC,OAAI,UAAU,eAAgB,SAAAmM,CAAA,CAAO,GACnD,CAEJ,CCsBA,SAASC,GAAc,CACrB,SAAAC,EACA,SAAA3J,EACA,aAAA2I,EACA,gBAAAiB,CACF,EAAU,aACR,MAAMrH,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACRkC,EAAWlI,SAAmC,IAAI,EAClD,CAAC8O,EAAUC,CAAW,EAAIrQ,WAC9BkQ,EAAS,UAAY,MAEjB,CAACzP,EAASC,CAAU,EAAIV,WAAS,CAACkQ,EAAS,QAAQ,EACnD,CAAC/J,EAAUmK,CAAW,EAAItQ,WAA0BkQ,EAAS,UAAY,EAAE,EAC3E,CAACK,EAAUC,CAAW,EAAIxQ,aAC9B8B,EAAAoO,EAAS,gBAAT,YAAApO,EAAwB,KAAM,MAE1B,CAAC2O,EAAMC,CAAO,EAAI1Q,WAAgBkQ,EAAS,MAAQ,EAAE,EACrD,CAACS,EAAYC,CAAa,EAAI5Q,WAAS,EAAK,EAE5C,CAAC6Q,EAAeC,CAAgB,EAAI9Q,aACxCmI,GAAA+H,EAAS,WAAT,YAAA/H,GAAmB,iBAAkB,EAAC,EAElC,CAAC4I,EAAkBC,CAAmB,EAAIhR,WAAS,EAAK,EAIxD,CAACiR,EAAYC,CAAa,EAAIlR,WAAsB,IAAI,GAAK,EAGnE+B,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAC,SAAY,CACX,GAAI,CACF,MAAMrG,EAAI,MAAM7B,EAAI,IAA0B,kBAAkB,EAC3DkI,GAAWsH,EAAc,IAAI,IAAI3N,EAAE,QAAU,EAAE,CAAC,CACvD,MAAQ,CAAkB,CAC5B,KACO,IAAM,CAAEqG,EAAY,EAAM,CACnC,EAAG,EAAE,EAGL,MAAMuH,EAAU,CAACC,EAAkB7M,IAAwB,CACzD,MAAM5F,GAAI,GAAGyS,EAAG,MAAQ,EAAE,IAAIA,EAAG,IAAM,EAAE,IAAKA,EAAG,MAAoBA,EAAG,OAAoB,EAAE,IAAI7M,CAAG,GAErG,IAAI8M,EAAI,EACR,QAASpS,GAAI,EAAGA,GAAIN,GAAE,OAAQM,KAAKoS,GAAMA,GAAK,GAAKA,EAAI1S,GAAE,WAAWM,EAAC,EAAK,EAC1E,OAAO,KAAK,IAAIoS,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAAE,MAAM,EAAG,EAAE,CAC9D,EAEMC,EAAS,MAAOC,GAAgB,CACpC,MAAMrO,EAAO,IAAI,IAAI+N,CAAU,EAC/B/N,EAAK,IAAIqO,CAAG,EACZL,EAAchO,CAAI,EAClB,GAAI,CACF,MAAMxB,EAAI,KAAK,iBAAkB,CAAE,KAAM,CAAC6P,CAAG,EAAG,CAClD,OAAS3P,GAAK,CAEZ,MAAM4P,EAAW,IAAI,IAAIP,CAAU,EACnCC,EAAcM,CAAQ,EACtB1I,EAAM,MAAM,gBAAiBlH,GAAc,OAAO,EAAE,CACtD,CACF,EAEM6P,EAAa,SAAY,CAC7B,GAAI,CAAC,QAAQ,mGAAmG,EAAG,OACnH,MAAMC,EAAMb,EAAc,IAAI,CAACO,GAAI7M,IAAQ4M,EAAQC,GAAI7M,CAAG,CAAC,EACrDrB,EAAO,IAAI,IAAI+N,CAAU,EAC/BS,EAAI,QAAS/S,IAAMuE,EAAK,IAAIvE,EAAC,CAAC,EAC9BuS,EAAchO,CAAI,EAClB,GAAI,CACF,MAAMxB,EAAI,KAAK,iBAAkB,CAAE,KAAMgQ,EAAK,EAC9C5I,EAAM,QAAQ,UAAU4I,EAAI,MAAM,oDAAoD,CACxF,OAAS9P,GAAK,CACZkH,EAAM,MAAM,iBAAkBlH,GAAc,OAAO,EAAE,CACvD,CACF,EAEM+P,EAAe,SAAY,CAC/BT,EAAc,IAAI,GAAK,EACvB,GAAI,CACF,MAAMxP,EAAI,IAAI,gBAAgB,EAC9BoH,EAAM,QAAQ,+CAA+C,CAC/D,OAASlH,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAGAG,YAAU,IAAM,OACVmO,EAAS,WACXG,EAAYH,EAAS,QAAQ,EAC7BY,EAAiBZ,EAAS,SAAS,gBAAkB,EAAE,EACvDxP,EAAW,EAAK,GAElB4P,EAAYJ,EAAS,UAAY,EAAE,EACnCM,IAAY1O,EAAAoO,EAAS,gBAAT,YAAApO,EAAwB,KAAM,IAAI,EAC9C4O,EAAQR,EAAS,MAAQ,EAAE,CAC7B,EAAG,CAACA,EAAS,SAAUA,EAAS,SAAUA,EAAS,cAAeA,EAAS,IAAI,CAAC,EAKhFnO,YAAU,IAAM,CACd,IAAI6P,EACJ,GAAI,CACF,MAAMC,EAAMnQ,EAAI,WACV6M,GAAMsD,EACR,8BAA8B,mBAAmBA,CAAG,CAAC,GACrD,uBACJD,EAAK,IAAI,YAAYrD,EAAG,EACxBqD,EAAG,iBAAiB,WAAa3P,GAAM,CACrC,GAAI,CACF,MAAM6P,GAAS,KAAK,MAAO7P,EAAmB,IAAI,EAClD6O,EAAiB,MAAM,QAAQgB,GAAO,MAAM,EAAIA,GAAO,OAAO,MAAM,EAAG,EAAE,EAAI,EAAE,CACjF,MAAQ,CAA4B,CACtC,CAAC,EACDF,EAAG,iBAAiB,WAAa3P,GAAM,CACrC,GAAI,CACF,MAAM3D,GAAQ,KAAK,MAAO2D,EAAmB,IAAI,EACjD6O,EAAkBtF,IAAQ,CAAClN,GAAO,GAAGkN,EAAG,EAAE,MAAM,EAAG,EAAE,CAAC,CACxD,MAAQ,CAA4B,CACtC,CAAC,CACH,MAAQ,CAAsD,CAC9D,MAAO,IAAM,CAAE,GAAI,CAAEoG,GAAA,MAAAA,EAAI,OAAS,MAAQ,CAAe,CAAE,CAC7D,EAAG,EAAE,EAEL,MAAM1K,EAAY,SAAY,CAC5B4B,EAAM,KAAK,cAAe,IAAI,EAC9B,MAAMqH,EAAA,EACN,GAAI,CACF,MAAM3R,EAAO,MAAMkD,EAAI,IAA0D,WAAW,EAC5F4O,EAAY9R,EAAK,UAAY,EAAE,EAC/BgS,EAAYhS,EAAK,QAAU,IAAI,CACjC,MAAQ,CAAe,CACzB,EAEMuT,EAAe,IAAM,CACzB1K,EAAM,KAAK,CACT,MAAO,cACP,SACExD,MAACmO,GAAA,CACC,SAAAzL,EACA,MAAO,MAAOlI,EAAcgB,IAAwB,CAClD,GAAI,CACF,MAAMkE,GAAI,MAAM7B,EAAI,KAAoB,YAAa,CAAE,KAAArD,EAAM,KAAAgB,EAAM,EACnEiR,EAAa9E,GAAQ,CAAC,GAAGA,EAAI,OAAQ3M,IAAMA,GAAE,KAAO0E,GAAE,EAAE,EAAGA,EAAC,CAAC,EAC7DuF,EAAM,QAAQ,gBAAgB,EAC9BzB,EAAM,OACR,OAASzF,GAAK,CACZkH,EAAM,MAAM,eAAgBlH,GAAc,OAAO,EAAE,CACrD,CACF,IAGJ,OACEiC,MAAC,OAAI,UAAU,uBACb,SAAAA,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC9D,EAEH,CACH,EAEM4K,EAAkB,SAAY,OAClC,GAAI,CACF,MAAMzT,EAAO,MAAMkD,EAAI,KACrB,yBAEF4O,EAAY9R,EAAK,UAAY,EAAE,EAC/BgS,EAAYhS,EAAK,QAAU,IAAI,EAC/B,MAAM0T,IAAYpQ,EAAAtD,EAAK,WAAL,YAAAsD,EAAe,KAAMjD,GAAMA,EAAE,KAAOL,EAAK,QAC3DsK,EAAM,QAAQoJ,GAAY,WAAWA,GAAU,IAAI,GAAK,qBAAqB,EAC7E,MAAM/B,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,CACF,EAEMuQ,EAAa,MAAOrG,GAAe,CACvC,GAAI,CACF,MAAMpK,EAAI,KAAK,aAAa,mBAAmBoK,CAAE,CAAC,WAAW,EAC7D0E,EAAY1E,CAAE,EACdhD,EAAM,QAAQ,oBAAoB,EAClC,MAAMqH,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,oBAAqBlH,EAAc,OAAO,EAAE,CAC1D,CACF,EAEMmK,EAAW,MAAOD,GAAe,CACrC,GAAK,QAAQ,mBAAmBA,CAAE,sBAAsB,EACxD,GAAI,CACF,MAAMpK,EAAI,IAAI,aAAa,mBAAmBoK,CAAE,CAAC,EAAE,EACnDwE,EAAa9E,GAAQA,EAAI,OAAQ3M,IAAMA,GAAE,KAAOiN,CAAE,CAAC,EAC/CyE,IAAazE,GAAI0E,EAAY,IAAI,EACrC1H,EAAM,QAAQ,kBAAkB,CAClC,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEA,OAAInB,GAAW,CAAC2P,EAEZrM,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,6BAAiB,GACtB,EAKFE,OAAC,OAAI,UAAU,qBAEb,UAAAA,OAAC,OAAI,UAAU,wBACb,UAAAF,MAAC,MAAG,mCAAuB,EAC3BA,MAAC,KAAE,UAAU,yBAAyB,kJAGtC,EACAE,OAAC,QACC,UAAU,6BACV,SAAU,MAAO9B,GAAM,UACrBA,EAAE,iBACF,MAAMoQ,KAAQvQ,GAAA0H,EAAS,UAAT,YAAA1H,GAAkB,QAAS,IAAI,OAC7C,GAAKuQ,EACL,CAAAzB,EAAc,EAAI,EAClB,GAAI,CACF,MAAMrN,GAAI,MAAM7B,EAAI,KAA+B,gBAAiB,CAAE,MAAO2Q,EAAM,EACnFvJ,EAAM,QAAQ,wBAAuBX,EAAA5E,GAAE,WAAF,YAAA4E,EAAY,SAAU,CAAE,UAAU,EACnEqB,EAAS,UAASA,EAAS,QAAQ,MAAQ,IAC/C,MAAM2G,EAAA,CACR,OAASvO,GAAK,CACZkH,EAAM,MAAM,WAAYlH,GAAc,OAAO,EAAE,CACjD,SACEgP,EAAc,EAAK,CACrB,EACF,EAEA,UAAA/M,MAAC,YACC,IAAK2F,EACL,UAAU,sBACV,YAAY,sLACZ,SAAUmH,CAAA,GAEZ5M,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,iBAAkB,WAAY,SAAU,SAAU,QACpF,UAAAA,OAAC2D,EAAA,CACC,KAAK,SACL,QAAQ,UACR,KAAK,KACL,SAAUiJ,EAET,UAAAA,EAAa9M,MAACuO,IAAQ,KAAK,KAAK,EAAKvO,MAACyO,GAAA,CAAK,KAAM,GAAI,EAAG,oBAG3DvO,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,IACzC,UAAAF,MAAC4B,GAAA,CAAS,KAAM,GAAI,MAAO,CAAE,QAAS,SAAU,cAAe,GAAI,MAAO,gBAAgB,CAAG,EAC5F,IAAI,yCACP,GACF,WAGD,OAAI,UAAU,6BACZ,UAAC,oBAAqB,UAAW,WAAY,cAAe,YAAa,WAAY,WAAY,QAAQ,EAAE,IAAKuK,GAC/GnM,MAAC,UAEC,KAAK,SACL,UAAU,sBACV,QAAS,IAAM,CACT2F,EAAS,UACXA,EAAS,QAAQ,MAAQwG,EACzBxG,EAAS,QAAQ,QAErB,EAEC,SAAAwG,CAAA,EAVIA,CAAA,CAYR,EACH,GACF,EAEAjM,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC,MAAG,2BAAe,EACnBE,OAAC,OAAI,UAAU,6BACZ,UAAAkN,EAAW,KAAO,GACjBlN,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASiK,EAAc,MAAM,wCAC7D,UAAA9N,MAAC5I,GAAA,CAAI,KAAM,GAAI,EAAE,SAAOgW,EAAW,KAAK,WAC1C,EAEDJ,EAAc,OAAS,SACrBnJ,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS,IAAMsJ,EAAqBnO,GAAM,CAACA,CAAC,EAC3E,SAAAkO,EAAmB,YAAc,WACpC,EAEDF,EAAc,OAAS,GACtB9M,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS+J,EAAY,MAAM,oDAC3D,UAAA5N,MAAC7I,GAAA,CAAO,KAAM,GAAI,EAAE,aACtB,GAEJ,GACF,EACCiW,EAAW,KAAO,GACjBlN,OAAC,OAAI,UAAU,yBAAyB,KAAK,SAC3C,UAAAA,OAAC,QACC,UAAAF,MAAC7I,GAAA,CAAO,KAAM,GAAI,MAAO,CAAE,cAAe,GAAI,YAAa,EAAE,CAAG,EAC/DiW,EAAW,KAAK,QAAMA,EAAW,OAAS,EAAI,GAAK,IAAI,8BAC1D,SACCvJ,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASiK,EACzC,UAAA9N,MAAC5I,GAAA,CAAI,KAAM,GAAI,EAAE,oBACnB,GACF,EAED4V,EAAc,SAAW,EACxBhN,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,SAAU,SAAU,IAAM,0FAEnE,EAEAE,OAAC,OAAI,UAAW+C,EAAG,0BAA2B,CAACiK,GAAoB,mCAAmC,EACpG,UAAAlN,MAAC,OAAI,UAAU,qBACZ,SAAAgN,EAAc,MAAM,EAAG,EAAE,EAAE,IAAI,CAACO,EAAI7M,IAAQ,CAC3C,MAAM5F,GAAIwS,EAAQC,EAAI7M,CAAG,EACzB,OAAI0M,EAAW,IAAItS,EAAC,EAAU,KAE5BkF,MAAC0O,GAAA,CAEC,KAAMnB,EACN,YAAazS,GACb,WAAYuQ,EACZ,OAAAoC,CAAA,EAJK,GAAGF,EAAG,EAAE,IAAI7M,CAAG,GAO1B,CAAC,EACH,EACC,CAACwM,GAAoBF,EAAc,OAAS,SAAM,OAAI,UAAU,qBAAqB,cAAY,OAAO,GAC3G,GAEJ,EAGA9M,OAAC0K,EAAA,CAAK,UAAU,iBACd,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACc,GAAA,CAAO,KAAM,GAAI,EAAE,YACpBZ,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,MAAO,CAAE,WAAY,QAAU,QAASqK,EACxE,UAAAlO,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,QACpB,EACA5D,OAAC2D,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAASuK,EAAiB,MAAM,qCAChE,UAAApO,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,gBACpB,IACC6K,GAAAjM,GAAA,YAAAA,EAAU,YAAV,YAAAiM,GAAqB,oBACpBzO,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,MAAO,QAAQnB,EAAS,UAAU,iBAAiB,gBACnD,QAAS,SAAY,CACnB,GAAI,CACF,MAAMhD,EAAI,MAAM7B,EAAI,KAAiB,gBAAgB,EACjD6B,EAAE,MACJuF,EAAM,MAAMvF,EAAE,KAAK,EAEnBuF,EAAM,QAAQ,SAASvF,EAAE,MAAM,MAAM,aAAaA,EAAE,OAAO,GAAG,EAEhE,MAAM4M,EAAA,EACN,MAAM3R,EAAO,MAAMkD,EAAI,IAA0D,WAAW,EAC5F4O,EAAY9R,EAAK,UAAY,EAAE,EAC/BgS,EAAYhS,EAAK,QAAU,IAAI,CACjC,OAASoD,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEA,UAAAiC,MAACpI,GAAA,CAAa,KAAM,GAAI,EAAE,WAG9BoI,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASR,EAAW,MAAM,UAC1D,SAAArD,MAACG,GAAA,CAAU,KAAM,GAAI,EACvB,GACF,SACCgL,GAAA,CACE,UAAA7I,EAAS,OAAO,WAASA,EAAS,SAAW,EAAI,GAAK,IAAI,KAC1D,IAAKiK,EAAS,OAAO,OAAO,YAC5B,IAAKA,EAAS,OAAO,SAAS,WAASA,EAAS,OAAO,WAAa,EAAI,GAAK,KAChF,EACCjK,EAAS,SAAW,EACnBtC,MAACgM,GAAA,CACC,KAAMhM,MAACc,GAAA,CAAO,KAAM,GAAI,EACxB,MAAM,kBACN,QAAQ,mEACR,OACEZ,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,UAAU,QAASuK,EACjC,UAAApO,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,0BACpB,QACCD,EAAA,CAAO,QAAQ,YAAY,QAASqK,EAAc,wBAEnD,GACF,UAIH,OAAI,UAAU,eACZ,SAAA5L,EAAS,IAAKtH,GACbgF,MAAC4O,GAAA,CAEC,QAAS5T,EACT,OAAQ0R,IAAa1R,EAAE,GACvB,OAAQ,IAAMsT,EAAWtT,EAAE,EAAE,EAC7B,SAAU,IAAMkN,EAASlN,EAAE,EAAE,GAJxBA,EAAE,GAMV,EACH,GAEJ,EAEAgF,MAACoL,IAAiB,aAAAC,EAA4B,EAE9CnL,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC0K,EAAA,CACC,UAAA5K,MAACkL,IAAU,gBAAI,SACdC,GAAA,CAAS,wCAA2BnL,MAAC,QAAK,iCAAqB,GAAO,EACtE4M,EAAK,SAAW,EACf5M,MAAC,OAAI,UAAU,QAAQ,8BAAkB,EAEzCA,MAAC,MAAG,UAAU,gBACX,WAAK,IAAK6O,GACT3O,OAAC,MAAc,UAAU,WACvB,UAAAF,MAAC,QAAK,UAAU,gBAAiB,SAAA6O,EAAE,KAAK,EACxC3O,OAAC,QAAK,UAAU,gBAAgB,cAAE2O,EAAE,QAAQ,MAAIA,EAAE,MAAK,EACvD7O,MAAC,QAAK,UAAW,iBAAiB6O,EAAE,QAAU,mBAAqB,mBAAmB,GACnF,SAAAA,EAAE,QAAU,KAAO,MACtB,IALOA,EAAE,EAMX,CACD,EACH,GAEJ,SAECjE,EAAA,CACC,UAAA5K,MAACkL,IAAU,uBAAW,EACtBlL,MAACmL,IAAS,2BAAe,EACzBjL,OAAC,MAAG,UAAU,YACZ,UAAAF,MAAC,MAAG,gBAAI,QACP,MAAG,UAAU,OAAQ,SAAAuM,EAAS,SAAS,KAAK,EAC7CvM,MAAC,MAAG,oBAAQ,QACX,MAAG,UAAU,OAAQ,SAAAuM,EAAS,SAAS,SAAS,EACjDvM,MAAC,MAAG,wBAAY,EAChBA,MAAC,MAAG,UAAU,gBAAgB,MAAOuM,EAAS,SAAS,YACpD,SAAAA,EAAS,SAAS,YACrB,EACAvM,MAAC,MAAG,sBAAU,EACdA,MAAC,MAAG,UAAU,gBAAgB,MAAOuM,EAAS,SAAS,UACpD,SAAAA,EAAS,SAAS,UACrB,EACAvM,MAAC,MAAG,qBAAS,QACZ,MAAG,UAAU,oBACX,SAAA+L,GAAWQ,EAAS,WAAW,EAClC,GACF,GACF,GACF,GACF,CAEJ,CASA,SAAS4B,GAAiB,CACxB,SAAAzL,EACA,MAAAiB,CACF,EAGG,SACD,KAAM,CAACnJ,EAAMuJ,CAAO,EAAI5H,aAAS8B,EAAAyE,GAAA,YAAAA,EAAU,YAAV,YAAAzE,EAAqB,oBAAqB,EAAE,EACvE,CAACzC,EAAMwI,CAAO,EAAI7H,WAAS,EAAE,EAC7B,CAAC8H,EAAcC,CAAe,EAAI/H,WAAS,EAAK,EAChD,CAACgI,EAAgBC,CAAiB,EAAIjI,WAAwB,IAAI,EAElEkI,EAAY,SAAY,OAC5B,GAAK7J,EACL,CAAA0J,EAAgB,EAAI,EACpBE,EAAkB,IAAI,EACtB,GAAI,CAEF,MAAMvG,EAAI,IAAsB,YAAc,mBAAmBrD,CAAI,CAAC,EAEtEmJ,EAAMnJ,EAAMgB,GAAQ,IAAI,CAC1B,OAASuC,EAAK,CACZ,MAAMkB,EAASlB,EACXkB,EAAO,SAAW,IACpBmF,EAAkB,6CAA6C,EAE/DA,IACEnG,EAAAgB,EAAO,OAAP,YAAAhB,EAAa,UAAYF,EAAc,SAAW,qBAGxD,SACEmG,EAAgB,EAAK,CACvB,EACF,EAEA,cACG,OACC,UAAAlE,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCA,MAACtE,GAAA,CACC,MAAOlB,EACP,SAAWQ,GAAM,CACf+I,EAAQ/I,CAAC,EACToJ,EAAkB,IAAI,CACxB,EACA,mBAAmBE,EAAA5B,GAAA,YAAAA,EAAU,YAAV,YAAA4B,EAAqB,kBACxC,OAAQ,MAETH,GACCnE,MAAC,KAAE,UAAU,aAAa,MAAO,CAAE,MAAO,eAAgB,UAAW,GAClE,SAAAmE,CAAA,CACH,SAED,OAAI,MAAO,CAAE,UAAW,kBACvB,UAAAnE,MAAC,SAAM,UAAU,cAAc,QAAQ,mBAAmB,2BAAe,EACzEA,MAAC,SACC,GAAG,mBACH,UAAU,QACV,KAAK,OACL,YAAY,SACZ,MAAOxE,EACP,SAAW4C,GAAM4F,EAAQ5F,EAAE,OAAO,KAAK,IAEzC4B,MAAC,KAAE,UAAU,aAAa,MAAO,CAAE,UAAW,GAAK,uEAEnD,GACF,EACAA,MAAC,OAAI,MAAO,CAAE,UAAW,iBAAkB,QAAS,OAAQ,eAAgB,YAC1E,SAAAE,OAAC2D,EAAA,CACC,QAAQ,UACR,QAASQ,EACT,SAAU,CAAC7J,GAAQyJ,EAElB,UAAAA,EAAejE,MAAC,QAAK,UAAU,cAAc,EAAK,KAClDiE,EAAe,YAAc,QAChC,CACF,GACF,CAEJ,CAEA,SAAS2K,GAAY,CACnB,QAAAE,EACA,OAAA1L,EACA,OAAA2L,EACA,SAAA7G,CACF,EAKG,CACD,MAAM8G,EAAc,CAClB,OAAQ,YACR,SAAU,iBACV,MAAO,gBACPF,EAAQ,MAAM,GAAK,iBACrB,cACG,OAAI,UAAW,gBAAgB1L,EAAS,sBAAwB,EAAE,GACjE,UAAAlD,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAW,uBAAuBgP,CAAW,GAChD,WAAQ,OACX,EACAhP,MAAC,OAAI,UAAU,oBAAqB,WAAQ,KAAK,EACjDA,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,iBACX,MAAM,SACN,QAAU5B,GAAM,CACdA,EAAE,kBACF8J,EAAA,CACF,EAEA,SAAAlI,MAACiP,GAAA,CAAO,KAAM,GAAI,GACpB,EACF,EACAjP,MAAC,OAAI,UAAU,kCAAkC,MAAO8O,EAAQ,KAC7D,WAAQ,KACX,EACA9O,MAAC,OAAI,UAAU,oBACZ,WAAQ,cACPE,OAAC,QAAK,UAAU,QAAQ,yBAAaqI,GAAeuG,EAAQ,YAAY,GAAE,EAE9E,EACA9O,MAAC,OAAI,UAAU,uBACb,eAAC6D,EAAA,CAAO,QAAST,EAAS,QAAU,UAAW,KAAK,KAAK,QAAS2L,EAC/D,WAAS7O,OAAAO,WAAA,CAAE,UAAAT,MAACkP,GAAA,CAAM,KAAM,GAAI,EAAE,WAAO,EAAMlP,MAAAS,WAAA,CAAE,gBAAI,EACpD,EACF,GACF,CAEJ,CAEA,SAAS0O,GAAa,EAAmB,CACvC,OAAK,GACE,EAAE,OAAO,CAAC,EAAE,cAAgB,EAAE,MAAM,CAAC,CAC9C,CAEA,SAASC,GAAaC,EAAsB,CAC1C,MAAMC,EAAcD,EAAoB,OAAO,cAAc,QAAQ,QAAS,GAAG,EAC3E,CAACE,EAAUC,EAAY,SAAS,EAAIF,EAAW,MAAM,GAAG,EACxDG,EAAmC,CACvC,SAAU,WACV,KAAM,OACN,MAAO,OACP,MAAO,QACP,OAAQ,QACR,KAAM,OACN,MAAO,OACP,GAAI,iBACJ,WAAY,iBACZ,QAAS,UACT,IAAK,MACL,KAAM,MACN,SAAU,WACV,UAAW,YAEPC,EAAoC,CACxC,OAAQ,UAAW,QAAS,UAC5B,IAAK,QAAS,MAAO,QACrB,OAAQ,UAAW,QAAS,UAC5B,SAAU,YAAa,UAAW,YAClC,OAAQ,UAAW,QAAS,UAC5B,QAAS,YAAa,UAAW,YACjC,OAAQ,UAAW,QAAS,UAC5B,OAAQ,UAAW,QAAS,UAC5B,QAAS,WAAY,SAAU,WAC/B,QAAS,WAAY,SAAU,WAC/B,SAAU,YAAa,UAAW,YAClC,KAAM,SAAU,OAAQ,SACxB,MAAO,UAAW,MAAO,gBAErBrK,EAAQoK,EAASF,CAAQ,GAAKJ,GAAaI,EAAS,QAAQ,KAAM,GAAG,CAAC,EACtEpD,EAASuD,EAAUF,CAAS,GAAKA,EAAU,QAAQ,KAAM,GAAG,EAClE,MAAO,GAAGnK,CAAK,IAAI8G,CAAM,GAAG,MAC9B,CAEA,SAASwD,GAAYpC,EAAkBqC,EAAwB,CAC7D,UAAWlC,KAAOkC,EAAM,CACtB,MAAMjU,EAAQ4R,EAAGG,CAAG,EACpB,GAAI,OAAO/R,GAAU,UAAYA,EAAM,OAAQ,OAAOA,EAAM,MAC9D,CACA,MAAO,EACT,CAEA,SAASkU,GAAsBtC,EAA0B,CACvD,MAAMuC,EAASH,GAAYpC,EAAI,CAAC,UAAW,OAAQ,SAAU,QAAS,MAAM,CAAC,EAC7E,GAAIuC,EAAQ,OAAOA,EACnB,MAAM7U,EAAkB,GAClBgO,EAAO0G,GAAYpC,EAAI,CAAC,MAAM,CAAC,EAC/BwC,EAAQJ,GAAYpC,EAAI,CAAC,QAAS,QAAQ,CAAC,EAC3C/B,EAASmE,GAAYpC,EAAI,CAAC,QAAQ,CAAC,EACzC,OAAItE,GAAMhO,EAAM,KAAK,QAAQgO,CAAI,EAAE,EAC/B8G,GAAO9U,EAAM,KAAK8U,CAAK,EACvBvE,GAAQvQ,EAAM,KAAKuQ,CAAM,EACtBvQ,EAAM,OAASA,EAAM,KAAK,KAAK,EAAI,wBAC5C,CAGA,SAAS+U,GAAmBC,EAAoB,CAC9C,OAAO1H,GAAe0H,CAAE,CAC1B,CAGA,SAASC,GAAiB3C,EAA4D,CACpF,MAAMzS,GAAMyS,EAAG,MAAmB,IAAI,cAChCpH,GAAMoH,EAAG,QAAqB,IAAI,cACxC,OAAIzS,EAAE,SAAS,OAAO,GAAKqL,IAAM,SAAWA,IAAM,UAAkB,QAChErL,EAAE,SAAS,MAAM,GAAKqL,IAAM,UAAkB,UAC9CrL,EAAE,SAAS,MAAM,GAAKA,EAAE,SAAS,SAAS,GAAKqL,IAAM,OAAe,UACjE,MACT,CAGA,SAASgK,GAAad,EAAc,CAClC,MAAMvU,EAAIuU,EAAK,cACf,OAAIvU,IAAM,OAAe4G,GACrB5G,IAAM,QAAgB2G,GACtB3G,IAAM,OAAepC,GACrBoC,EAAE,SAAS,IAAI,GAAKA,EAAE,SAAS,YAAY,GAAKA,EAAE,SAAS,KAAK,EAAUX,GAC1EW,IAAM,MAAcxB,GACpBwB,IAAM,QAAgB8G,GACtB9G,EAAE,SAAS,OAAO,GAAKA,EAAE,SAAS,SAAS,EAAUsV,GACrDtV,EAAE,SAAS,MAAM,EAAUiM,GACxBpF,EACT,CAGA,SAAS0O,GAAkBhB,EAA6B,CACtD,MAAMvU,EAAIuU,EAAK,cACf,OAAIvU,IAAM,OAAe,QACrBA,IAAM,QAAgB,SACtBA,IAAM,OAAe,YACrBA,EAAE,SAAS,IAAI,GAAKA,EAAE,SAAS,YAAY,EAAU,WACrDA,IAAM,MAAc,OACpBA,IAAM,QAAgB,SACnB,IACT,CAGA,SAAS4T,GAAiB,CACxB,KAAA4B,EACA,YAAAC,EACA,WAAAvP,EACA,OAAAyM,CACF,EAKG,CACD,MAAM+C,EAAWN,GAAiBI,CAAI,EAChCnN,EAAOgN,GAAaG,EAAK,MAAQ,EAAE,EACnCpE,EAAQkD,GAAakB,EAAK,MAAQ,UAAU,EAC5CtS,EAAM6R,GAAsBS,CAAI,EAChCG,EAAYJ,GAAkBC,EAAK,MAAQ,EAAE,EAE7CI,EACJF,IAAa,QAAU,eACvBA,IAAa,UAAY,iBACzBA,IAAa,UAAY,iBACzB,gBAEF,OACEtQ,OAAC,OAAI,UAAW+C,EAAG,oBAAqB,qBAAqBuN,CAAQ,EAAE,EACrE,UAAAtQ,OAAC,UACC,KAAK,SACL,UAAU,yBACV,QAAS,IAAM,CAAMuQ,KAAsBA,CAAS,CAAG,EACvD,MAAOA,EAAY,QAAQA,CAAS,GAAKvE,EAEzC,UAAAlM,MAAC,OAAI,UAAU,qBAAqB,MAAO,CAAE,MAAO0Q,CAAA,EAClD,SAAA1Q,MAACmD,EAAA,CAAK,KAAM,GAAI,EAClB,EACAjD,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OAAI,UAAU,0BACb,UAAAF,MAAC,OAAI,UAAU,sBAAuB,SAAAkM,EAAM,QAC3C,OAAI,UAAU,gDAAiD,SAAA8D,GAAmBM,EAAK,EAAE,EAAE,GAC9F,EACAtQ,MAAC,OAAI,UAAU,gCAAiC,SAAAhC,CAAA,CAAI,GACtD,KAEFgC,MAAC,UACC,KAAK,SACL,UAAU,yBACV,QAAS,IAAMyN,EAAO8C,CAAW,EACjC,MAAM,gEACN,aAAW,qBAEX,SAAAvQ,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,CAEJ,CACA,MAAMoK,GAAeC,GAAM,KAAKxE,EAAa,EC5wBtC,SAASyE,GAAe,CAC7B,QAAAC,EACA,KAAApI,EACA,OAAAqI,EACA,YAAAC,EACA,eAAAC,EACA,OAAAC,EACA,gBAAAC,EACA,gBAAAC,EACA,gBAAAC,EACA,QAAAtM,CACF,EAAwB,CACtB,MAAMuM,EAAM7T,SAA8B,IAAI,EAGxC8T,EAAM,KAAK,MAAMR,EAAO,KAAK,OAAS,CAAC,EACvCS,EAAQ,KAAK,IAAI,EAAG,KAAK,MAAM,OAAO,WAAaT,EAAO,KAAK,KAAK,CAAC,EAG3E7S,YAAU,IAAM,CACd,MAAMuT,EAAUrT,GAAkB,CAChC,MAAMsG,EAAItG,EAAE,OACR,CAACkT,EAAI,SAAW,CAAC5M,GACjB4M,EAAI,QAAQ,SAAS5M,CAAC,GAC1BK,EAAA,CACF,EACMsB,EAASjI,GAAqB,CAC9BA,EAAE,MAAQ,UAAU2G,EAAA,CAC1B,EAGMkD,EAAK,OAAO,WAAW,IAAM,CACjC,SAAS,iBAAiB,YAAawJ,CAAM,EAC7C,SAAS,iBAAiB,UAAWpL,CAAK,CAC5C,EAAG,CAAC,EACJ,MAAO,IAAM,CACX,OAAO,aAAa4B,CAAE,EACtB,SAAS,oBAAoB,YAAawJ,CAAM,EAChD,SAAS,oBAAoB,UAAWpL,CAAK,CAC/C,CACF,EAAG,CAACtB,CAAO,CAAC,EAGZ7G,YAAU,IAAM,CACd,GAAIwK,IAAS,SAAU,OACvB,MAAMT,EAAK,OAAO,WAAW,IAAM,OACjC,MAAMyJ,GAAQzT,EAAAqT,EAAI,UAAJ,YAAArT,EAAa,cAAgC,gCAC3DyT,GAAA,MAAAA,EAAO,QACPA,GAAA,MAAAA,EAAO,QACT,EAAG,CAAC,EACJ,MAAO,IAAM,OAAO,aAAazJ,CAAE,CACrC,EAAG,CAACS,CAAI,CAAC,EAET,MAAMiJ,EACJzR,OAAC,OACC,IAAAoR,EACA,UAAU,mBACV,KAAK,OACL,aAAY,eAAeR,EAAQ,KAAK,GACxC,MAAO,CAAE,SAAU,QAAS,IAAAS,EAAK,MAAAC,CAAA,EACjC,QAAUpT,GAAMA,EAAE,kBAEjB,UAAAsK,IAAS,QACRxI,OAAAO,WAAA,CACE,UAAAP,OAAC,UACC,KAAK,SACL,UAAU,wBACV,KAAK,WACL,QAAU9B,GAAM,CACdA,EAAE,kBACF8S,EAAA,CACF,EAEA,UAAAlR,MAAC4R,GAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAC5B5R,MAAC,QAAK,kBAAM,EACZA,MAAC,OAAI,aAAC,KAERE,OAAC,UACC,KAAK,SACL,UAAU,qDACV,KAAK,WACL,QAAU9B,GAAM,CACdA,EAAE,kBACF+S,EAAA,CACF,EAEA,UAAAnR,MAACiP,GAAA,CAAO,KAAM,GAAI,cAAW,GAAC,EAC9BjP,MAAC,QAAK,kBAAM,EACZA,MAAC,OAAI,aAAC,IACR,EACF,EAED0I,IAAS,UACRxI,OAAC,OAAI,UAAU,0BACb,UAAAF,MAAC,OAAI,UAAU,0CAA0C,0BAAc,EACvEA,MAAC,SACC,KAAK,OACL,UAAU,yBACV,MAAOgR,EACP,SAAW5S,GAAM6S,EAAe7S,EAAE,OAAO,KAAK,EAC9C,UAAYA,GAAM,CACZA,EAAE,MAAQ,SACZA,EAAE,iBACFiT,EAAA,GACSjT,EAAE,MAAQ,WACnBA,EAAE,iBACF2G,EAAA,EAEJ,EACA,QAAU3G,GAAMA,EAAE,kBAClB,aAAW,qBAEb8B,OAAC,OAAI,UAAU,kCACb,UAAAF,MAAC,UACC,KAAK,SACL,UAAU,gBACV,QAAU5B,GAAM,CACdA,EAAE,kBACF2G,EAAA,CACF,EACD,oBAGD/E,MAAC,UACC,KAAK,SACL,UAAU,kBACV,QAAU5B,GAAM,CACdA,EAAE,kBACFiT,EAAA,CACF,EACD,iBAED,EACF,GACF,EAED3I,IAAS,kBACRxI,OAAC,OAAI,UAAU,0BACb,UAAAF,MAAC,OAAI,UAAU,0CAA0C,gCAAoB,EAC7EE,OAAC,OAAI,UAAU,kCAAkC,cAC7C4Q,EAAQ,MAAM,yCAClB,EACA5Q,OAAC,OAAI,UAAU,kCACb,UAAAF,MAAC,UACC,KAAK,SACL,UAAU,gBACV,QAAU5B,GAAM,CACdA,EAAE,kBACF2G,EAAA,CACF,EACD,oBAGD/E,MAAC,UACC,KAAK,SACL,UAAU,iBACV,QAAU5B,GAAM,CACdA,EAAE,kBACFgT,EAAA,CACF,EACD,mBAED,EACF,GACF,KAKN,OAAOS,gBAAaF,EAAM,SAAS,IAAI,CACzC,CCxKO,SAASG,GAAU,CACxB,KAAAC,EACA,MAAAC,EAAQ,EACR,YAAAC,EAAc,GACd,OAAAC,EAAS,GACT,KAAMC,EACN,SAAApR,CACF,EAAU,OACR,KAAM,CAACqR,EAAcC,CAAe,EAAIlW,WAAkB8V,CAAW,EAC/DK,EAAeH,IAAmB,OAClC7O,EAAOgP,EAAeH,EAAiBC,EACvC7O,EAAWlE,GAAkB,CAC5BiT,GAAcD,EAAgBhT,CAAI,EACvC0B,GAAA,MAAAA,EAAW1B,EACb,EAEMkT,KAAetU,EAAA8T,EAAK,WAAL,YAAA9T,EAAe,SAAU,GAAK,EAE7CuU,EACJtS,OAAAO,WAAA,CACG,UAAAwR,GACCjS,MAAC,QACC,UAAW,sBAAsBsD,EAAO,OAAS,EAAE,GACnD,cAAW,GACZ,eAIHtD,MAAC,QACC,UAAW,yBAAyB+R,EAAK,MAAM,GAC/C,cAAW,KAEb/R,MAAC,QAAK,UAAU,kBAAmB,WAAK,KAAK,EAC5C+R,EAAK,MAAQ/R,MAAC,QAAK,UAAU,4BAA6B,WAAK,KAAK,EACrEA,MAAC,QAAK,UAAW,0BAA0B+R,EAAK,MAAM,GAAK,WAAK,OAAO,GACzE,EAGF,OACE7R,OAAC,OACC,UAAW,CACT,aACA,SAAS8R,CAAK,GACd,UAAUD,EAAK,MAAM,GACrBzO,EAAO,OAAS,SAChB4O,EAAS,OAAS,IAEjB,OAAO,OAAO,EACd,KAAK,GAAG,EAEV,UAAAD,EACCjS,MAAC,UACC,KAAK,SACL,UAAW,0BAA0B+R,EAAK,MAAM,eAChD,QAAU3T,GAAM,CACdA,EAAE,kBACFmF,EAAQ,CAACD,CAAI,CACf,EACA,gBAAeA,EAEd,SAAAkP,CAAA,SAGF,OAAI,UAAW,0BAA0BT,EAAK,MAAM,GAClD,SAAAS,CAAA,CACH,EAEDlP,GACCpD,OAAAO,WAAA,CACG,UAAAsR,EAAK,SACJ/R,MAAC,OAAI,UAAU,qBAAsB,WAAK,QAAQ,EAEnDuS,GACCvS,MAAC,OAAI,UAAU,sBACZ,WAAK,SAAU,IAAI,CAACyS,EAAOrX,IAC1B4E,MAAC8R,GAAA,CAEC,KAAMW,EACN,MAAOT,EAAQ,EACf,YAAa,GACb,OAAQ5W,IAAM2W,EAAK,SAAU,OAAS,GAJjCU,EAAM,GAMd,EACH,GAEJ,IAIR,CChGA,SAASC,GAAWC,EAAkE,CACpF,OAAQA,EAAwB,OAAS,MAC3C,CAEO,SAASC,GAAUD,EAA0C,CAClE,MAAMrP,EAAOqP,EAAM,MAAQ,GAE3B,GAAID,GAAWC,CAAK,EAClB,aACG,OAAI,UAAW,sBAAsBA,EAAM,SAAW,MAAM,GAC3D,SAAA3S,MAAC8R,GAAA,CAAU,KAAMa,EAAM,KAAK,KAAM,MAAO,EAAG,KAAArP,EAAY,EAC1D,EAKJ,MAAMkD,EAAOmM,EAAM,UAAY,GAC/B,aACG,OAAI,UAAW,sBAAsBA,EAAM,OAAO,4BACjD,SAAA3S,MAAC,OAAI,UAAU,2BACZ,SAAAwG,EAAK,IAAI,CAACiM,EAAOrX,UACfqF,WAAA,CACC,SAAAT,MAAC8R,GAAA,CACC,KAAMW,EACN,MAAO,EACP,YAAa,GACb,KAAAnP,EACA,OAAQlI,IAAMoL,EAAK,OAAS,GAC9B,EAPaiM,EAAM,EAQrB,CACD,EACH,EACF,CAEJ,CAIO,SAASI,GAAa,CAC3B,SAAA7H,EACA,QAAAH,EAAU,OACV,KAAAvH,EAAO,EACT,EAIG,CACD,OAAKA,EACEtD,MAAC4S,GAAA,CAAU,QAAA/H,EAAkB,KAAAvH,EAAY,SAAA0H,CAAA,CAAoB,EADlD,IAEpB,CChBA,MAAM8H,GAAiB,CAAC,QAAS,YAAa,YAAa,SAAS,EAEpE,SAASC,GAAUnY,EAASC,EAAS,CACnC,OACED,EAAE,gBAAkBC,EAAE,eACtBD,EAAE,aAAeC,EAAE,YACnBD,EAAE,YAAcC,EAAE,SAEtB,CAEA,SAASmY,GAAQpY,EAASC,EAAS,CACjC,MAAMoY,EAAKrY,EAAE,UAAYC,EAAE,UAC3B,OAAO,KAAK,MAAMoY,GAAM,IAAO,GAAK,GAAK,GAAG,CAC9C,CAEA,SAASC,GAAeC,EAA8D,CACpF,MAAMC,MAAU,KACVC,EAAY,IAAI,KAAKD,CAAG,EAC9BC,EAAU,QAAQA,EAAU,UAAY,CAAC,EACzC,MAAMC,EAAU,IAAI,KAAKF,CAAG,EAC5BE,EAAQ,QAAQA,EAAQ,UAAY,CAAC,EAErC,MAAMC,EAA2C,CAC/C,MAAO,GACP,UAAW,GACX,YAAa,GACb,QAAS,EAAC,EAGZ,UAAWpN,KAAKgN,EAAU,CACxB,MAAMK,EAAI,IAAI,KAAK,OAAOrN,EAAE,KAAK,GAAK,KAAK,KAAK,EAC5C4M,GAAUS,EAAGJ,CAAG,EAAGG,EAAO,MAAM,KAAKpN,CAAC,EACjC4M,GAAUS,EAAGH,CAAS,EAAGE,EAAO,UAAU,KAAKpN,CAAC,EAChD6M,GAAQI,EAAKI,CAAC,EAAI,EAAGD,EAAO,WAAW,EAAE,KAAKpN,CAAC,EACnDoN,EAAO,QAAQ,KAAKpN,CAAC,CAC5B,CACA,OAAOoN,CACT,CAEA,SAASxH,GAAW0H,EAAuB,CAEzC,OADU,IAAI,KAAK,OAAOA,CAAK,GAAK,KAAK,KAAK,EACrC,mBAAmB,OAAW,CACrC,KAAM,UACN,OAAQ,UACR,OAAQ,GACT,CACH,CAEA,SAASC,GAAsB,CAC7B,MAAAC,EACA,MAAA5D,CACF,EAGG,CACD,OAAI4D,IAAU,YAEV3T,MAAC,QACC,UAAU,wCACV,MAAO,GAAG+P,GAAS,MAAM,gBAI3B4D,IAAU,WAEV3T,MAAC,QACC,UAAU,uCACV,MAAM,sBACN,cAAW,KAIb2T,IAAU,OACL3T,MAAC,QAAK,UAAU,mCAAmC,cAAW,GAAC,EAEjE,IACT,CAEO,SAAS4T,GAAS,CACvB,SAAAT,EACA,iBAAAU,EAAmB,GACnB,gBAAAC,EACA,wBAAAC,EACA,cAAA1R,EACA,SAAAgH,EACA,gBAAA2K,EACA,gBAAAC,EACA,wBAAAC,EACA,gBAAAC,EACA,gBAAAC,EACA,QAAAC,CACF,EAAU,OACR,MAAMC,EAAcC,UAClB,IAAM,CAAC,GAAGpB,EAAU,GAAGU,CAAgB,EACvC,CAACV,EAAUU,CAAgB,GAEvBW,EAASD,UACb,IAAM,CAAC,GAAGD,CAAW,EAAE,KAAK,CAAC1Z,EAAGC,KAAM,OAAOA,GAAE,OAAS,CAAC,EAAI,OAAOD,EAAE,OAAS,CAAC,CAAC,EACjF,CAAC0Z,CAAW,GAGRtO,EAAUuO,UACd,IAAOF,EAAUA,EAAQG,CAAM,EAAItB,GAAesB,CAAM,EACxD,CAACH,EAASG,CAAM,GAMZ,CAACC,EAAUC,CAAW,EAAIvY,WAAkC,EAAE,EAC9DwY,EAAc1M,GAAewM,EAASxM,CAAE,IAAM,GAG9C,CAAC2M,EAAYC,CAAa,EAAI1Y,WAAwB,IAAI,EAC1D,CAAC2Y,EAAUC,CAAW,EAAI5Y,WAA0B,MAAM,EAC1D,CAAC6U,EAAaC,CAAc,EAAI9U,WAAS,EAAE,EAC3C,CAAC6Y,EAAYC,CAAa,EAAI9Y,WAA+C,IAAI,EACjF+Y,EAAUzX,SAA8C,EAAE,EAE1D0X,EAAc,CAAClN,EAAYS,GAAwB,SAAW,CAClE,MAAM0M,GAAMF,EAAQ,QAAQjN,CAAE,EAC9B,GAAI,CAACmN,GAAK,OACV,MAAMC,EACJ3M,KAAS,OACL0M,GACAA,GAAI,cAA2B,8BAA8B,GAAKA,GAIxE,GAHAH,EAAc,CAAE,GAAAhN,EAAI,KAAMoN,EAAO,wBAAyB,EAC1DR,EAAc5M,CAAE,EAChB8M,EAAYrM,EAAI,EACZA,KAAS,SAAU,CACrB,MAAMvC,EAAI,CAAC,GAAGgN,EAAU,GAAGU,CAAgB,EAAE,KAAMtU,IAAMA,GAAE,KAAO0I,CAAE,EACpEgJ,GAAe9K,GAAA,YAAAA,EAAG,SAASA,GAAA,YAAAA,EAAG,KAAM,EAAE,CACxC,CACF,EACMmP,EAAY,IAAM,CACtBT,EAAc,IAAI,EAClBE,EAAY,MAAM,EAClB9D,EAAe,EAAE,EACjBgE,EAAc,IAAI,CACpB,EAEMM,EAAgBpP,GAAsB,CAC1C,GAAIA,EAAE,SAAW,WAAY,CAC3B+N,EAAwB/N,CAAC,EACzB,MACF,CACA8N,EAAgB9N,EAAE,EAAE,CACtB,EAEMqP,EAAsB,IAAM,CAChC,GAAI,CAACR,EAAY,OACjB,MAAMS,EAAMT,EAAW,GACjB3V,GAAO2R,EAAY,OACzB,GAAI,CAAC3R,GAAM,CACTiW,EAAA,EACA,MACF,CACAnB,GAAA,MAAAA,EAAkBsB,EAAKpW,IACvBiW,EAAA,CACF,EAEMI,EAAsB,IAAM,CAC3BV,IACLZ,GAAA,MAAAA,EAAkBY,EAAW,IAC7BM,EAAA,EACF,EAEMK,EAAmDtB,EACrD,OAAO,QAAQrO,CAAO,EACtB8M,GAAe,OAAQ8C,GAAA,QAAM,OAAA3X,GAAA+H,EAAQ4P,CAAC,IAAT,YAAA3X,GAAY,OAAM,EAAE,IAC9C2X,GAAM,CAACA,EAAG5P,EAAQ4P,CAAC,CAAC,GAG3B,OACE1V,OAAC,SAAM,UAAU,YACf,UAAAF,MAAC,OAAI,UAAU,iBACb,SAAAE,OAAC,UACC,KAAK,SACL,UAAU,eACV,QAAS8T,EACT,SAAU3K,GAAY,CAAChH,EACvB,MAAOA,EAAgB,qBAAuB,uBAC9C,aAAW,qBAEX,UAAArC,MAAC8D,GAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAC5B9D,MAAC,QAAM,SAAAqJ,EAAW,YAAc,cAAc,KAElD,EAECmL,EAAO,SAAW,EACjBxU,MAAC,OAAI,UAAU,sBACb,SAAAA,MAACgM,GAAA,CACC,KAAMhM,MAAC8D,GAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAClC,MAAOzB,EAAgB,kBAAoB,aAC3C,QACEA,EACI,+CACA,uDAGV,EAEArC,MAAC,OAAI,UAAU,iBACZ,SAAA2V,EAAc,IAAI,CAAC,CAACE,EAAO1O,EAAK,IAC/BjH,OAAC,OAAgB,UAAU,kBACzB,UAAAF,MAAC,OAAI,UAAU,wBAAyB,SAAA6V,EAAM,EAC7C1O,GAAM,IAAKhB,IAAM,UAChB,MAAM2P,EAAa3P,GAAE,SAAW,WAC1BtF,EAAWiV,EACb/B,IAA4B5N,GAAE,GAC9B2N,IAAoB3N,GAAE,GACpB4P,GAAO5P,GAAE,KACToM,EAAc,CAAC,GAAEtU,GAAA8X,IAAA,YAAAA,GAAM,OAAN,MAAA9X,GAAY,UAAY8X,GAAK,KAAK,SAAS,OAAS,GACrEC,GAAWrB,EAAWxO,GAAE,EAAE,EAChC,cACG1F,WAAA,CACC,UAAAP,OAAC,OACC,IAAM+V,GAAO,CACXf,EAAQ,QAAQ/O,GAAE,EAAE,EAAI8P,CAC1B,EACA,KAAK,SACL,SAAU,EACV,UAAW,wBAAwB9P,GAAE,OAAS,MAAM,GAAGtF,EAAW,UAAY,EAAE,GAChF,QAAS,IAAM0U,EAAapP,EAAC,EAC7B,UAAY/H,GAAM,EACZA,EAAE,MAAQ,SAAWA,EAAE,MAAQ,OACjCA,EAAE,iBACFmX,EAAapP,EAAC,EAElB,EACA,eAActF,EAAW,OAAS,OAElC,UAAAb,MAAC0T,IAAsB,MAAOvN,GAAE,OAAS,OAAQ,MAAOA,GAAE,MAAO,EACjEjG,OAAC,OAAI,UAAU,uBACZ,UAAAiG,GAAE,QACDnG,MAAC,QAAK,UAAU,gBAAgB,cAAW,GAAC,aAE5C,EAED8V,GACC9V,MAAC6L,GAAA,CACC,KAAM,GACN,MAAO,CAAE,MAAO,oBAAqB,WAAY,GACjD,cAAW,WAGd,QAAK,UAAU,gBAAiB,SAAA1F,GAAE,OAASA,GAAE,GAAG,GACnD,EACAjG,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,QAAK,UAAU,2BACb,SAAAmG,GAAE,MAAQ4F,GAAW5F,GAAE,KAAK,EAC/B,GACEA,GAAE,QAAU,GAAK,SAChB,QAAK,UAAU,kBAAmB,SAAAA,GAAE,OAAO,GAEhD,EACAnG,MAAC,UACC,KAAK,SACL,UAAW,8BAA8B4U,IAAezO,GAAE,GAAK,QAAU,EAAE,GAC3E,aAAY,uBAAuBA,GAAE,OAASA,GAAE,EAAE,GAClD,gBAAc,OACd,gBAAeyO,IAAezO,GAAE,GAChC,QAAU/H,GAAM,CACdA,EAAE,kBACEwW,IAAezO,GAAE,GAAImP,EAAA,EACpBH,EAAYhP,GAAE,GAAI,MAAM,CAC/B,EAEA,SAAAjG,OAAC,OAAI,QAAQ,YAAY,cAAW,GAClC,UAAAF,MAAC,UAAO,GAAG,IAAI,GAAG,IAAI,EAAE,MAAM,KAAK,eAAe,EAClDA,MAAC,UAAO,GAAG,IAAI,GAAG,IAAI,EAAE,MAAM,KAAK,eAAe,EAClDA,MAAC,UAAO,GAAG,KAAK,GAAG,IAAI,EAAE,MAAM,KAAK,eAAe,GACrD,IAEDa,GAAY0R,GACXvS,MAAC,UACC,KAAK,SACL,UAAW,yBAAyBgW,GAAW,QAAU,EAAE,GAC3D,aAAYA,GAAW,sBAAwB,oBAC/C,gBAAeA,GACf,QAAU5X,GAAM,CACdA,EAAE,kBACFsW,EAAa/M,IAAS,CAAE,GAAGA,EAAK,CAACxB,GAAE,EAAE,EAAG,CAACwB,EAAIxB,GAAE,EAAE,GAAI,CACvD,EAEA,SAAAnG,MAAC,OAAI,QAAQ,YAAY,cAAW,GAClC,SAAAA,MAAC,YAAS,OAAO,kBAAkB,EACrC,GACF,IAGHa,GAAY0R,GAAeyD,MAAY1R,EAAAyR,IAAA,YAAAA,GAAM,OAAN,YAAAzR,EAAY,WAClDtE,MAAC6S,GAAA,CAAa,SAAUkD,GAAK,KAAK,SAAU,QAAQ,OAAO,KAAI,GAAC,IA7ErDD,EAAa,MAAM3P,GAAE,EAAE,GAAKA,GAAE,EA+E7C,CAEJ,CAAC,IA5FO0P,CA6FV,CACD,EACH,EAGDjB,GAAcI,GACbhV,MAAC6Q,GAAA,CACC,QAAS,CACP,GAAImE,EAAW,GACf,QACE/W,EAAA,CAAC,GAAGkV,EAAU,GAAGU,CAAgB,EAAE,KAAMtU,GAAMA,EAAE,KAAOyV,EAAW,EAAE,IAArE,YAAA/W,EACI,QAAS+W,EAAW,IAE5B,KAAMF,EACN,OAAQE,EACR,YAAAhE,EACA,eAAAC,EACA,OAAQ,IAAMkE,EAAYP,EAAY,QAAQ,EAC9C,gBAAiB,IAAMO,EAAYP,EAAY,gBAAgB,EAC/D,gBAAiBc,EACjB,gBAAiBF,EACjB,QAASF,CAAA,EACX,EAEJ,CAEJ,CCjWO,SAASY,GAAavD,EAAc,CACzC,KAAM,CAAE,KAAAnE,EAAM,QAAA2H,EAAS,OAAAC,EAAQ,aAAAC,GAAiB1D,EAC1C,CAAC2D,EAAWC,CAAY,EAAIpa,WAAS,EAAK,EAE1Cqa,EAAa,IAAM,CACnB,CAAChI,EAAK,QAAU2H,IACpBI,EAAa,EAAI,EACjBH,EAAA,EACA,OAAO,WAAW,IAAMG,EAAa,EAAK,EAAG,GAAG,EAClD,EAEA,OACErW,OAAC,OACC,UAAW,2CAA2CmW,GAAgB,MAAM,GAE5E,UAAArW,MAAC,OAAI,UAAW,qBAAqBsW,EAAY,WAAa,EAAE,GAC9D,SAAAtW,MAACyW,GAAA,CAAU,GAAG9D,EAAO,OAAQ6D,EAAY,EAC3C,EACAtW,OAAC,OAAI,UAAU,gCACb,UAAAA,OAAC,QACC,UAAAF,MAAC,OAAI,aAAC,EAAM,SACd,SACC,QACC,UAAAA,MAAC,OAAI,cAAE,EAAM,YACf,SACC,QACC,UAAAA,MAAC,OAAI,aAAC,EAAM,aACd,EACCqW,IAAiB,YAChBrW,MAAC,QAAK,UAAU,4BAA4B,sBAAU,EAEvDqW,IAAiB,SAChBrW,MAAC,QAAK,UAAU,4BAA4B,wBAAY,EAEzDmW,GAAWnW,MAAC,QAAK,UAAU,4BAA4B,oBAAQ,GAClE,IAGN,CCxBA,SAAS0W,GAAa9O,EAAmB,CACvC,OAAOA,EAAE,gBACX,CAGA,SAAS+O,GAAkBC,EAAuB,CAEhD,MADI,CAACA,GACD,CAACA,EAAM,SAAS,GAAG,EAAU,GAC1BA,EAAM,MAAM,GAAG,EAAE,CAAC,CAC3B,CAIA,SAASC,GAAgBD,EAAuB,CAC9C,GAAI,CAACA,EAAO,MAAO,GACnB,MAAM/H,EAAI+H,EAAM,cAChB,OAAI/H,EAAE,SAAS,MAAM,EAAU,GAC3BA,EAAE,SAAS,QAAQ,EAAU,EAC7BA,EAAE,SAAS,OAAO,EAAU,GAC5BA,EAAE,SAAS,QAAQ,EAAU,EAC7BA,EAAE,SAAS,OAAO,EAAU,GAC5BA,EAAE,SAAS,UAAU,EAAU,IAC/BA,EAAE,SAAS,SAAS,EAAU,GAC9BA,EAAE,SAAS,eAAe,EAAU,IACjC,CACT,CAEO,SAASiI,GAAc,CAC5B,UAAAC,EACA,SAAAC,EACA,OAAAC,EACA,MAAAlH,EACA,MAAA6G,EACA,OAAAM,EACA,KAAAC,EACA,YAAAC,EACA,aAAAf,EAAe,QACf,SAAAgB,EACA,SAAAC,EACA,SAAAC,EACA,KAAAC,CACF,EAAU,CAIR,KAAM,CAACC,EAAOC,CAAQ,EAAIvb,WAA0B,IAAI,EACxD+B,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAC,SAAY,CACX,GAAI,CACF,MAAMqE,EAAM,MAAM,MAAM,uBAAwB,CAC9C,QAAS,CAAE,OAAQ,mBAAmB,CACvC,EACD,GAAI,CAACA,EAAI,GAAI,OACb,MAAMuH,EAAQ,MAAMvH,EAAI,OACnBrE,GAAW2R,EAAS/F,CAAI,CAC/B,MAAQ,CAER,CACF,KACO,IAAM,CACX5L,EAAY,EACd,CACF,EAAG,CAACgR,CAAS,CAAC,EAEd,MAAMY,GAAWX,GAAA,YAAAA,EAAU,SAAU,EAC/BY,GAAcX,GAAA,YAAAA,EAAQ,OAAQ,EAI9BY,EAAab,EAAS,OAC1B,CAACpP,EAAGiH,IAAMjH,GAAMiH,EAAE,SAAWA,EAAE,SAAW,IAAe,OACzD,GAEIiJ,EAAe,KAAK,MAAMD,EAAa,CAAC,EACxCE,EAAOlB,GAAgBD,CAAK,EAC5BoB,EAAiBF,EAAe,IAAaC,EAC7CE,GAAaR,GAAA,YAAAA,EAAO,cAAeK,EACnCI,GAAUT,GAAA,YAAAA,EAAO,UAAWO,EAC5BG,EAAc,MACdC,EAAWzB,GAAkBC,CAAK,EAExC,OACE1W,OAAC,SAAM,UAAU,YACf,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,OAAI,UAAU,yBACb,UAAAA,OAAC,MACC,UAAAF,MAACwB,GAAA,CACC,KAAM,GACN,MAAO,CAAE,YAAa,EAAG,cAAe,IACxC,cAAW,KACV,IAAI,WAET,EACAxB,MAAC,QACC,UAAW,iCAAiCqW,GAAgB,MAAM,GAClE,MAAO,CAAE,WAAY,QAEpB,SAAAA,IAAiB,WAAa,WAAa,cAC9C,EACF,QACC,OAAI,UAAU,+BAA+B,MAAOU,EAClD,YAAa,OAChB,EACA7W,OAAC,OAAI,UAAU,iBACZ,UAAAwW,GAAaiB,CAAQ,EAAE,WAASA,IAAa,EAAI,GAAK,IACtDC,EAAc,GAAK,MAAMA,CAAW,WACvC,GACF,EAEA1X,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,MACC,UAAAF,MAACyB,GAAA,CAAI,KAAM,GAAI,MAAO,CAAE,YAAa,EAAG,cAAe,IAAM,cAAW,GAAC,EAAG,IAAI,SAElF,EACAzB,MAAC,OAAI,UAAU,kBAAmB,YAAS,IAAI,GACjD,EAEAE,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,MACC,UAAAF,MAACqY,GAAA,CAAO,KAAM,GAAI,MAAO,CAAE,YAAa,EAAG,cAAe,IAAM,cAAW,GAAC,EAAG,IAAI,SAErF,QACC,OAAI,UAAU,0BAA0B,MAAOzB,EAC7C,YAAS,IACZ,EACCwB,GACClY,OAAC,OAAI,UAAU,iBAAiB,wBAAYkY,CAAA,EAAS,GAEzD,EAEAlY,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,MAAG,kBAAM,EACVE,OAAC,OAAI,UAAU,YACZ,UAAAwW,GAAauB,CAAU,EAAE,MAAIvB,GAAayB,CAAW,GACxD,EACAnY,MAAC,OAAI,UAAU,gBAAgB,cAAW,GACxC,SAAAA,MAAC,OACC,UAAU,qBACV,MAAO,CACL,MAAO,GAAG,KAAK,IAAI,IAAMiY,EAAa,KAAK,IAAI,EAAGE,CAAW,EAAK,GAAG,CAAC,IACxE,EACF,CACF,GACF,EAEAjY,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,MACC,UAAAF,MAACvJ,GAAA,CACC,KAAM,GACN,MAAO,CAAE,YAAa,EAAG,cAAe,IACxC,cAAW,KACV,IAAI,QAET,EACAyJ,OAAC,OAAI,UAAU,YAAY,cAAEgY,EAAQ,QAAQ,CAAC,GAAE,EAC/C,CAACT,GACAzX,MAAC,OAAI,UAAU,iBAAiB,sCAA0B,GAE9D,EAEAE,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,MACC,UAAAF,MAACyB,GAAA,CACC,KAAM,GACN,MAAO,CAAE,YAAa,EAAG,cAAe,IACxC,cAAW,KACV,IAAI,mBAET,EACCyV,GAAA,MAAAA,EAAQ,OACPlX,MAAC,OAAI,UAAU,mBACZ,SAAAkX,EAAO,IAAKtc,GACXoF,MAAC,QAAkB,UAAU,kBAC1B,SAAApF,EAAE,MADMA,EAAE,IAEb,CACD,EACH,EAEAoF,MAAC,OAAI,UAAU,iBAAiB,yBAAa,GAEjD,EAEAE,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,MACC,UAAAF,MAACqY,GAAA,CACC,KAAM,GACN,MAAO,CAAE,YAAa,EAAG,cAAe,IACxC,cAAW,KACV,IAAI,QAET,EACClB,GAAA,MAAAA,EAAM,OACLnX,MAAC,OAAI,UAAU,mBACZ,SAAAmX,EAAK,IAAKtI,GACT7O,MAAC,QAAgB,UAAU,kBACxB,SAAA6O,EAAE,IADMA,EAAE,EAEb,CACD,EACH,EAEA7O,MAAC,OAAI,UAAU,iBAAiB,8BAAkB,GAEtD,EAEAE,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,MACC,UAAAF,MAACsY,GAAA,CACC,KAAM,GACN,MAAO,CAAE,YAAa,EAAG,cAAe,IACxC,cAAW,KACV,IAAI,kBAET,EACApY,OAAC,OAAI,UAAU,iBAAkB,WAAAkX,GAAA,YAAAA,EAAa,SAAU,EAAE,cAAU,GACtE,GAEEC,GAAYC,GAAYC,IACxBrX,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,MAAG,mBAAO,EACXE,OAAC,OAAI,UAAU,oBACZ,UAAAmX,GACCnX,OAAC,UACC,KAAK,SACL,UAAU,uBACV,QAASmX,EACT,SAAUG,GAAA,YAAAA,EAAM,OAChB,MAAM,iBAEN,UAAAxX,MAACuY,GAAA,CAAO,KAAM,GAAI,cAAW,GAAC,EAAE,aAGnChB,GACCrX,OAAC,UACC,KAAK,SACL,UAAU,uBACV,QAASqX,EACT,MAAM,oBAEN,UAAAvX,MAAC/I,GAAA,CAAS,KAAM,GAAI,cAAW,GAAC,EAAE,aAGrCqgB,GACCpX,OAAC,UACC,KAAK,SACL,UAAU,kCACV,QAASoX,EACT,SAAUE,GAAA,YAAAA,EAAM,OAChB,MAAM,iBAEN,UAAAxX,MAACiP,GAAA,CAAO,KAAM,GAAI,cAAW,GAAC,EAAE,YAClC,EAEJ,GACF,GAEJ,CAEJ,CC7RO,SAASuJ,GAAa,CAC3B,UAAAC,EACA,gBAAAC,EACA,QAAAhV,EACA,eAAAiV,EAAiB,kBACnB,EAAU,CACR,OACE3Y,MAAC,UACC,KAAK,SACL,UAAW,iBAAiByY,EAAY,gBAAkB,EAAE,GAC5D,QAAA/U,EACA,aAAW,yBACX,MAAM,8BAEL,WACCxD,OAAAO,WAAA,CACE,UAAAP,OAAC,QAAK,UAAU,YAAY,cAAW,GACrC,UAAAF,MAAC,SAAK,QACL,SAAK,QACL,SAAK,GACR,EACAA,MAAC,QAAM,SAAA2Y,CAAA,CAAe,EACrBD,EAAkB,GACjB1Y,MAAC,QAAK,UAAU,6BAA6B,gBAAI,GAErD,EAEAE,OAAAO,WAAA,CACE,UAAAT,MAAChK,GAAA,CAAU,KAAM,GAAI,cAAW,GAAC,EACjCgK,MAAC,QAAK,0BAAc,EACnB0Y,EAAkB,GACjBxY,OAAC,QAAK,UAAU,aAAc,UAAAwY,EAAgB,QAAI,GAEtD,GAIR,CCbO,SAASE,GAAK,CACnB,SAAAvM,EACA,SAAA3J,EACA,aAAA2I,EACA,cAAAwN,EACA,cAAAC,CACF,EAAU,CACR,MAAM7T,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EAERsV,EAAOC,GAAQ3M,EAAU3J,EAAUmW,GAAiB,EAAE,EAG5D3a,YAAU,IAAM,CACd6a,EAAK,SAAS,CACZ,MAAQ/a,GAAgBiH,EAAM,MAAMjH,CAAG,EACvC,QAAUA,GAAgBiH,EAAM,QAAQjH,CAAG,EAC3C,KAAOA,GAAgBiH,EAAM,KAAKjH,CAAG,EACrC,QAAUA,GAAgBiH,EAAM,QAAQjH,CAAG,EAC5C,CACH,EAAG,CAAC+a,EAAM9T,CAAK,CAAC,EAGhB,KAAM,CAACuJ,EAAMyK,CAAO,EAAI9c,WAAS,EAAE,EAC7B,CAAC4T,EAAOmJ,CAAQ,EAAI/c,WAASuG,EAAS,cAAgB,MAAM,EAC5D,CAACkU,EAAOuC,CAAQ,EAAIhd,WAASuG,EAAS,cAAgB,EAAE,EACxD,CAAC0W,EAAaC,CAAc,EAAIld,WAAmB,EAAE,EAErDmd,EAAe7b,SAAyB,IAAI,EAG5C,CAAE,YAAA2Z,EAAa,YAAAmC,EAAa,SAAAC,CAAA,EAAaC,GAAiBpN,CAAQ,EAExEnO,YAAU,IAAM,CACdsb,EAAShL,CAAI,CACf,EAAG,CAACA,EAAMgL,CAAQ,CAAC,EAGnB,MAAME,EAAW,WAAM,OAAAzb,EAAAqb,EAAa,UAAb,YAAArb,EAAsB,SACvC0b,EAAWvb,GAA2C,CAC1D,MAAMoB,EAAQpB,EAAE,OAAO,MACvB,GAAI,CAACoB,EAAO,OACZ,MAAMH,GAAiB,GACvB,QAASjE,GAAI,EAAGA,GAAIoE,EAAM,OAAQpE,KAAKiE,GAAK,KAAKG,EAAMpE,EAAC,EAAE,IAAI,EAC9Die,EAAgB1R,IAAQ,CACtB,MAAMiS,EAAWva,GAAK,OAAQuI,GAAM,CAACD,GAAI,SAASC,CAAC,CAAC,EACpD,MAAO,CAAC,GAAGD,GAAK,GAAGiS,CAAQ,CAC7B,CAAC,EACGN,EAAa,UAASA,EAAa,QAAQ,MAAQ,GACzD,EAGM9C,EAAa,SAAY,CAC7B,MAAMxY,EAAMwQ,EAAK,OACjB,GAAI,CAACxQ,EAAK,OACVib,EAAQ,EAAE,EACVO,EAAS,EAAE,GACI,MAAMT,EAAK,OAAO/a,EAAK+R,EAAO6G,EAAOwC,CAAW,GACpD,IAAIL,EAAK,cACtB,EAGMc,EAAsB,SAAY,CAClCd,EAAK,KAAK,QACd,MAAMA,EAAK,iBACb,EAGMe,EAAgBpZ,GAAgB,CACpC8C,EAAM,KAAK,CACT,MAAO,kBACP,eAAW,KAAE,MAAO,CAAE,OAAQ,GAAK,yCAA6B,EAChE,OACEtD,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAML,EAAM,QAAS,kBAEpE,EACAxD,MAAC6D,EAAA,CACC,QAAQ,SACR,KAAK,KACL,QAAS,IAAM,CACbL,EAAM,QACNuV,EAAK,cAAcrY,CAAG,CACxB,EACD,mBAED,EACF,EAEH,CACH,EAGMqZ,EAAe,CAAC9R,EAAY+R,IAAyB,CACzD,IAAI3a,GAAO,GACXmE,EAAM,KAAK,CACT,MAAO,iBACP,SACExD,MAAC,SACC,UAAS,GACT,aAAcga,EACd,SAAW5b,IAAM,CACfiB,GAAOjB,GAAE,OAAO,KAClB,EACA,UAAYA,IAAM,CACZA,GAAE,MAAQ,UACZA,GAAE,iBACFoF,EAAM,QACNuV,EAAK,cAAc9Q,EAAI5I,EAAI,EAAE,KAAM4a,GAAO,CACpCA,GACFhV,EAAM,QAAQ,UAAU,CAE5B,CAAC,EAEL,EACA,MAAO,CACL,MAAO,OACP,QAAS,WACT,WAAY,YACZ,OAAQ,0BACR,aAAc,mBACd,MAAO,cACP,KAAM,4BACN,UAAW,EACb,GAGJ,OACE/E,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAML,EAAM,QAAS,kBAEpE,EACAxD,MAAC6D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,QAAS,IAAM,CACbL,EAAM,QACNuV,EAAK,cAAc9Q,EAAI5I,EAAI,CAC7B,EACD,iBAED,EACF,EAEH,CACH,EAGM6a,EAAsB,CAACjS,EAAYiE,IAAkB,CACzD1I,EAAM,KAAK,CACT,MAAO,kBACP,SACEtD,OAAC,KAAE,MAAO,CAAE,OAAQ,GAAK,oBAChBF,MAAC,UAAQ,SAAAkM,CAAA,CAAM,EAAS,4EAEjC,EAEF,OACEhM,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAML,EAAM,QAAS,kBAEpE,EACAxD,MAAC6D,EAAA,CACC,QAAQ,SACR,KAAK,KACL,QAAS,SAAY,CACnBL,EAAM,QACN,MAAMuV,EAAK,cAAc9Q,CAAE,CAC7B,EACD,mBAED,EACF,EAEH,CACH,EAGMkS,EAAe,IAAM,CACzB,MAAMpD,EACJgC,EAAK,eAAiB,WAClBA,EAAK,wBACLA,EAAK,UACX,GAAI,CAAChC,EAAW,OAKhB,MAAMvI,IAHJuK,EAAK,eAAiB,WAClBA,EAAK,iBACLA,EAAK,eAER,IAAKlK,IAAM,CACV,MAAMoB,EAAKpB,GAAE,IAAM,GACbuL,IAAOvL,GAAE,MAAQ,WAAW,cAC5BwL,GAAIxL,GAAE,SAAWA,GAAE,SAAW,GACpC,MAAO,IAAIoB,CAAE,KAAKmK,EAAG,KAAKC,EAAC,EAC7B,CAAC,EACA,KAAK;AAAA;AAAA,CAAM,EACRC,GAAO,IAAI,KAAK,CAAC9L,EAAI,EAAG,CAAE,KAAM,2BAA4B,EAC5D9D,EAAM,IAAI,gBAAgB4P,EAAI,EAC9B1f,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAO8P,EACT9P,EAAE,SAAW,GAAGmc,CAAS,OACzB,SAAS,KAAK,YAAYnc,CAAC,EAC3BA,EAAE,QACF,SAAS,KAAK,YAAYA,CAAC,EAC3B,IAAI,gBAAgB8P,CAAG,CACzB,EAGM6P,EAAkBhG,UACtB,IAAMwE,EAAK,SAAS,IAAK5S,GAAM4S,EAAK,kBAAkB5S,CAAC,CAAC,EACxD,CAAC4S,EAAK,SAAUA,EAAK,iBAAiB,GAElCyB,EAA0BjG,UAC9B,IAAMwE,EAAK,iBAAiB,IAAK5S,GAAM4S,EAAK,kBAAkB5S,CAAC,CAAC,EAChE,CAAC4S,EAAK,iBAAkBA,EAAK,iBAAiB,GAI1C0B,EAAuBlG,UAAQ,IAAM,CACzC,MAAMtM,EACJ8Q,EAAK,eAAiB,WAClBA,EAAK,yBAA2B,GAChCA,EAAK,UACX,OAAK9Q,EAEHsS,EAAgB,KAAMpU,GAAMA,EAAE,KAAO8B,CAAE,GACvCuS,EAAwB,KAAMrU,GAAMA,EAAE,KAAO8B,CAAE,GAC/C,KAJc,IAMlB,EAAG,CACD8Q,EAAK,aACLA,EAAK,wBACLA,EAAK,UACLwB,EACAC,CAAA,CACD,EAEKE,GAAkB,IAAM,QAC5B,MAAMC,EAAO,GAAG5K,GAAS,MAAM,QAAM9R,GAAAoO,EAAS,gBAAT,YAAApO,GAAwB,OAAQ,YAAY,GAC3E0V,GAAQ8G,GAAA,YAAAA,EAAsB,QAAS,OAC7C,OAAI9G,IAAU,YAAoB,cAAcgH,CAAI,GAChDhH,IAAU,WAAmB,eAAegH,CAAI,GAC7C,GAAGA,CAAI,SAChB,KAGMC,EACJ7B,EAAK,eAAiB,WAAa,WAAa,aAElD,OACE7Y,OAAC,OAAI,UAAU,aACb,UAAAF,MAAC6a,GAAA,CACC,cAAexO,EAAS,cACxB,aAAc0M,EAAK,SAAS,OAC5B,aAAc,GACd,SAAU,GACV,iBAAkB,IAAM,CAAC,EACzB,aAAc,IAAM,CAAC,EACrB,eAAgB,IAAM1N,GAAA,YAAAA,EAAe,WAAU,GAEjDnL,OAAC,OAAI,UAAU,YAEb,UAAAF,MAAC4T,GAAA,CACC,SAAU2G,EACV,iBAAkBC,EAClB,gBAAiBzB,EAAK,UACtB,wBAAyBA,EAAK,wBAC9B,cAAe1M,EAAS,cACxB,SAAU0M,EAAK,KAAK,OACpB,gBAAiBc,EACjB,gBAAiBd,EAAK,mBACtB,wBAA0B5S,GAAM4S,EAAK,oBAAoB5S,EAAE,EAAE,EAC7D,gBAAiB4T,EACjB,gBAAkB9R,GAAO,CACvB,MAAM9B,EAAI4S,EAAK,SAAS,KAAM5S,IAAMA,GAAE,KAAO8B,CAAE,GAAK8Q,EAAK,iBAAiB,KAAM5S,IAAMA,GAAE,KAAO8B,CAAE,EACjGiS,EAAoBjS,GAAI9B,GAAA,YAAAA,EAAG,QAAS,EAAE,CACxC,IAIFjG,OAAC,WAAQ,UAAU,sBACjB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,OACC,UAAAA,OAAC,OAAI,UAAU,wBACb,UAAAF,MAAC,OAAI,UAAU,oBACZ,2BAAsB,QAAS+Y,EAAK,WAAa,WACpD,EACA/Y,MAAC,QACC,UAAW,iCACT+Y,EAAK,cAAgB,MACvB,GACA,MACEA,EAAK,eAAiB,WAClB,0CACA,sCAGL,SAAA6B,CAAA,EACH,EACF,EACA1a,OAAC,OACC,UAAW,qCACTua,GAAA,YAAAA,EAAsB,QAAS,MACjC,GAEA,UAAAza,MAAC,QAAK,UAAU,kBAAkB,EACjC0a,CAAA,IAEF3B,EAAK,eACJ/Y,MAAC,OAAI,UAAU,oBAAoB,KAAK,QACrC,SAAA+Y,EAAK,cACR,GAEJ,EACA7Y,OAAC,OAAI,UAAU,sBACZ,UAAAua,GACCva,OAAC,UACC,UAAU,gBACV,MAAM,iBACN,KAAK,SACL,SAAU6Y,EAAK,KAAK,OACpB,QAAS,IACPgB,EACEU,EAAqB,GACrBA,EAAqB,OAAS,IAIlC,UAAAza,MAACuY,GAAA,CAAO,KAAM,GAAI,cAAW,GAAC,EAAG,IACjCvY,MAAC,QAAK,UAAU,OAAO,kBAAM,KAGhCya,GACCva,OAAC,UACC,UAAU,2BACV,MAAM,iBACN,KAAK,SACL,SAAU6Y,EAAK,KAAK,OACpB,QAAS,IACPmB,EACEO,EAAqB,GACrBA,EAAqB,OAASA,EAAqB,IAIvD,UAAAza,MAACiP,GAAA,CAAO,KAAM,GAAI,cAAW,GAAC,EAAG,IACjCjP,MAAC,QAAK,UAAU,OAAO,kBAAM,KAGjCA,MAAC,UACC,UAAU,gBACV,MAAM,oBACN,KAAK,SACL,QAASma,EAET,SAAAna,MAAC,QAAK,UAAU,OAAO,kBAAM,GAC/B,EACF,GACF,EAEAA,MAAC,OACC,UAAU,qBACV,IAAK+Y,EAAK,QACV,SAAUA,EAAK,aAEf,SAAA/Y,MAAC8a,GAAA,CACC,SACE/B,EAAK,eAAiB,WAClBA,EAAK,iBACLA,EAAK,cAEX,QAASA,EAAK,QACd,cAAe1M,EAAS,cACxB,UACE0M,EAAK,eAAiB,WAClBA,EAAK,yBAA2BA,EAAK,UACrCA,EAAK,UAEX,OAAQA,EAAK,OACb,aAAcA,EAAK,aACnB,iBAAmBrU,GAAMuU,EAAQvU,CAAC,EAClC,OAASmK,GACPkK,EAAK,YAAYlK,CAA2C,EAE9D,SAAUiL,EACV,YAAaf,EAAK,UAClB,aAAcA,EAAK,cACrB,GAGD,CAACA,EAAK,eACL/Y,MAACwY,GAAA,CACC,WAAWiC,GAAA,YAAAA,EAAsB,SAAU,YAC3C,gBAAiB1B,EAAK,gBACtB,QAASA,EAAK,eAIlB/Y,MAACkW,GAAA,CACC,MAAAnG,EACA,SAAAmJ,EACA,MAAAtC,EACA,SAAAuC,EACA,KAAA3K,EACA,QAAAyK,EACA,QAASF,EAAK,QACd,aAAcA,EAAK,aACnB,OAAQvC,EACR,YAAA4C,EACA,eAAAC,EACA,YAAAE,EACA,iBAAmBwB,GAAQ9B,EAAQ,GAAG8B,EAAI,MAAM,GAAG,EAAE,CAAC,CAAC,GAAG,EAC1D,OAAQ1O,EAAS,QAAU,GAC3B,SAAAqN,CAAA,GAEF1Z,MAAC,SACC,IAAKsZ,EACL,KAAK,OACL,SAAQ,GACR,MAAO,CAAE,QAAS,QAClB,SAAUK,CAAA,EACZ,EACF,EAGA3Z,MAAC8W,GAAA,CACC,UACEiC,EAAK,eAAiB,WAClBA,EAAK,yBAA2BA,EAAK,UACrCA,EAAK,UAEX,SACEA,EAAK,eAAiB,WAClBA,EAAK,iBACLA,EAAK,cAEX,OAAQA,EAAK,OACb,MAAAhJ,EACA,MAAA6G,EACA,OAAQvK,EAAS,QAAU,GAC3B,KAAMA,EAAS,MAAQ,GACvB,YAAA+K,EACA,aAAc2B,EAAK,aACnB,SAAU,IAAM,CACV0B,GACFV,EACEU,EAAqB,GACrBA,EAAqB,OAAS,GAGpC,EACA,SAAU,IAAM,CACVA,GACFP,EACEO,EAAqB,GACrBA,EAAqB,OAASA,EAAqB,GAGzD,EACA,SAAUN,EACV,KAAMpB,EAAK,MACb,EACF,GACF,CAEJ,CCjfO,SAASiC,GAAY,CAC1B,KAAA3L,EAAO,UACP,SAAArE,EACA,UAAAD,EACA,IAAAkQ,EAAM,EACR,EAAqB,CACnB,OACE/a,OAAC,QAAK,UAAW+C,EAAG,QAAS,SAASoM,CAAI,GAAItE,CAAS,EACpD,UAAAkQ,GAAOjb,MAAC,QAAK,UAAU,YAAY,EACnCgL,CAAA,EACH,CAEJ,CCiBA,MAAMkQ,GAAe,CAAC,OAAQ,OAAQ,OAAQ,QAAS,WAAY,YAAa,OAAQ,OAAQ,MAAM,EAChGC,GAAS,CACb,8BACA,6BACA,gBACA,qBACA,gCACA,iCACF,EAEMC,GAAa,CACjB,CAAE,GAAI,YAAa,MAAO,YAAa,MAAO,iBAC9C,CAAE,GAAI,OAAQ,MAAO,OAAQ,MAAO,eACpC,CAAE,GAAI,SAAU,MAAO,SAAU,MAAO,kBACxC,CAAE,GAAI,WAAY,MAAO,WAAY,MAAO,kBAC5C,CAAE,GAAI,SAAU,MAAO,SAAU,MAAO,gBACxC,CAAE,GAAI,WAAY,MAAO,WAAY,MAAO,kBAC9C,EAEA,SAASC,GAAcC,EAAiC,OACtD,QAAOrd,EAAAmd,GAAW,KAAMf,GAAMA,EAAE,KAAOiB,CAAG,IAAnC,YAAArd,EAAsC,QAAS,iBACxD,CAEA,SAASsd,GAAU,CAAE,OAAA/P,EAAQ,QAAAgQ,GAAmD,CAC9E,MAAMC,EACJD,EAAU,eACRhQ,IAAW,UAAY,cACvBA,IAAW,QAAU,eACrB,kBACJ,OAAOxL,MAAC,QAAK,UAAU,mBAAmB,MAAO,CAAE,WAAYyb,GAAS,CAC1E,CAEA,SAASC,GAAW,CAAE,MAAA3L,GAA2B,CAC/C,GAAIA,EAAM,QACR,aAAQiL,GAAA,CAAY,KAAK,QAAQ,IAAG,GAAC,iBAAK,EAE5C,MAAMxP,EAASuE,EAAM,QAAU,OAC/B,OAAIvE,IAAW,UAAkBxL,MAACgb,IAAY,KAAK,OAAO,IAAG,GAAC,mBAAO,EACjExP,IAAW,QAAgBxL,MAACgb,IAAY,KAAK,QAAQ,IAAG,GAAC,iBAAK,QAC1DA,GAAA,CAAY,KAAK,UAAU,IAAG,GAAC,gBAAI,CAC7C,CAEO,SAASW,GAAO,CAAE,SAAAtP,EAAU,gBAAAC,GAA0B,CAC3D,MAAMrH,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACR,CAACyT,EAAQ0E,CAAS,EAAIzf,WAAkBkQ,EAAS,QAAU,EAAE,EAC7D,CAACzP,EAASC,CAAU,EAAIV,WAAS,CAACkQ,EAAS,MAAM,EACjD,CAACwP,EAAgBC,CAAiB,EAAI3f,WAAiB,EAAE,EACzD,CAAC4f,EAAQC,CAAS,EAAI7f,WAAS,EAAE,EAEvC+B,YAAU,IAAM,CACd0d,EAAUvP,EAAS,QAAU,EAAE,EAC/BxP,EAAW,CAACwP,EAAS,MAAM,CAC7B,EAAG,CAACA,EAAS,MAAM,CAAC,EAEpB,MAAM5E,EAAS,SAAY,CACzB,GAAI,CACF,MAAM+L,EAAI,MAAM3V,EAAI,IAAyB,SAAS,EACtD+d,EAAUpI,EAAE,QAAU,EAAE,CAC1B,OAASzV,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,SACElB,EAAW,EAAK,CAClB,CACF,EAEM2X,EAASD,UAAQ,IAAM,CAC3B,IAAI0H,EAAM,CAAC,GAAG/E,CAAM,EAIpB,GAHI2E,IACFI,EAAMA,EAAI,OAAQrhB,GAAMihB,IAAmB,WAAa,CAAEjhB,EAAE,UAAmBA,EAAE,UAAY,MAAQihB,CAAc,GAEjHE,EAAQ,CACV,MAAM5W,EAAI4W,EAAO,cACjBE,EAAMA,EAAI,OACPrhB,GACCA,EAAE,KAAK,cAAc,SAASuK,CAAC,IAC9BvK,EAAE,aAAe,IAAI,cAAc,SAASuK,CAAC,IAC7CvK,EAAE,MAAQ,IAAI,KAAM8J,GAAMA,EAAE,cAAc,SAASS,CAAC,CAAC,EAE5D,CACA,OAAO8W,EAAI,KAAK,CAACrhB,EAAGC,IAAMD,EAAE,KAAK,cAAcC,EAAE,IAAI,CAAC,CACxD,EAAG,CAACqc,EAAQ2E,EAAgBE,CAAM,CAAC,EAE7BG,EAAU3H,UAAQ,IAAM,CAC5B,MAAM4H,MAAU,IAChB,UAAWvhB,KAAKsc,EAAQ,UAAWxS,KAAK9J,EAAE,MAAQ,GAAIuhB,EAAI,IAAIzX,CAAC,EAC/D,OAAO,MAAM,KAAKyX,CAAG,EAAE,MACzB,EAAG,CAACjF,CAAM,CAAC,EAELkF,EAAW,IAAM,CACrB,IAAIC,EAAkC,KAClCC,EAAkC,KAClCC,EAAoC,KACpCC,EAAmC,KACnCC,EAAmC,KACnCC,EAAuC,KACvCC,EAAwC,KACxCC,EAAkC,KAClCC,EAAuC,KAE3CrZ,EAAM,KAAK,CACT,MAAO,YACP,MAAO,IACP,SACEtD,OAAC,OAAI,UAAU,aACb,UAAAF,MAAC,SAAM,UAAU,cAAc,mCAAuB,EACtDA,MAAC,SACC,IAAMiW,GAAQoG,EAASpG,EACvB,UAAU,QACV,KAAK,OACL,YAAY,WACZ,UAAS,KAEXjW,MAAC,SAAM,UAAU,cAAc,uBAAW,EAC1CA,MAAC,SACC,IAAMiW,GAAO,CAAEqG,EAASrG,CAAI,EAC5B,UAAU,QACV,KAAK,OACL,YAAY,6BAEd/V,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,iBAAK,EACpCE,OAAC,UAAO,IAAM+V,GAAQsG,EAAUtG,EAAK,UAAU,SAAS,aAAa,GACnE,UAAAjW,MAAC,UAAO,MAAM,GAAG,8BAAkB,EAClCmb,GAAO,IAAKtM,GACX7O,MAAC,UAAe,MAAO6O,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,GACF,EACA3O,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCE,OAAC,UAAO,IAAM+V,GAAQuG,EAASvG,EAAK,UAAU,SAAS,aAAa,WAClE,UAAAjW,MAAC,UAAO,MAAM,UAAU,mBAAO,EAC/BA,MAAC,UAAO,MAAM,WAAW,oBAAQ,EACjCA,MAAC,UAAO,MAAM,MAAM,eAAG,GACzB,GACF,EACAE,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,YAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,iBAAK,EACpCA,MAAC,SAAM,IAAMiW,GAAQwG,EAAUxG,EAAK,UAAU,QAAQ,KAAK,QAAQ,aAAa,UAAU,GAC5F,GACF,EACA/V,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,oBAAQ,EACvCE,OAAC,UAAO,IAAM+V,GAAQ4G,EAAa5G,EAAK,UAAU,SAAS,aAAa,GACtE,UAAAjW,MAAC,UAAO,MAAM,GAAG,kBAAM,EACtBob,GAAW,IAAKf,GACfra,MAAC,UAAkB,MAAOqa,EAAE,GAAK,SAAAA,EAAE,OAAtBA,EAAE,EAA0B,CAC1C,GACH,GACF,EACAna,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,kCAAsB,EACrDA,MAAC,SAAM,IAAMiW,GAAQ2G,EAAS3G,EAAK,UAAU,QAAQ,KAAK,OAAO,YAAY,4BAA4B,GAC3G,GACF,EACAjW,MAAC,SAAM,UAAU,cAAc,iBAAK,QACnC,OAAI,IAAMiW,GAAQ0G,EAAiB1G,EAAK,UAAU,cAChD,SAAAiF,GAAa,IAAKxW,GACjBxE,OAAC,SAAc,UAAU,eACvB,UAAAF,MAAC,SAAM,KAAK,WAAW,MAAO0E,EAAG,EACjC1E,MAAC,QAAM,SAAA0E,CAAA,CAAE,IAFCA,CAGZ,CACD,EACH,EACA1E,MAAC,SAAM,UAAU,cAAc,yBAAa,EAC5CA,MAAC,YACC,IAAMiW,GAAQyG,EAAWzG,EACzB,UAAU,WACV,KAAM,EACN,YAAY,gBACd,EACF,EAEF,OACE/V,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC5DtD,OAAC2D,EAAA,CACC,QAAQ,UACR,QAAS,SAAY,CACnB,MAAMrI,IAAQ6gB,GAAA,YAAAA,EAAQ,QAAS,IAAI,OACnC,GAAI,CAAC,6BAA6B,KAAK7gB,CAAI,EAAG,CAC5CyJ,EAAM,QAAQ,kCAAkC,EAChD,MACF,CACA,MAAM6X,EAAkB,GACpBH,GACFA,EAAe,iBAAmC,gCAAgC,EAAE,QAASI,GAAO,CAClGD,EAAM,KAAKC,EAAG,KAAK,CACrB,CAAC,EAEH,MAAMC,IAAQJ,GAAA,YAAAA,EAAQ,QAAS,IAAI,MAAM,GAAG,EAAE,IAAKlY,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,EACjF,GAAI,CACF,MAAMuY,EAAU,MAAMpf,EAAI,KAAY,UAAW,CAC/C,KAAArC,EACA,cAAc8gB,GAAA,YAAAA,EAAQ,QAAS,IAAI,OACnC,OAAOC,GAAA,YAAAA,EAAS,QAAS,GACzB,MAAMC,GAAA,YAAAA,EAAQ,QAAS,WACvB,OAAOC,GAAA,YAAAA,EAAS,QAAS,GACzB,MAAAK,EACA,KAAAE,EACA,UAAUH,GAAA,YAAAA,EAAY,QAAS,GAC/B,QAAQH,GAAA,YAAAA,EAAU,QAAS,GAC5B,EACDd,EAAWjU,GAAQ,CAAC,GAAGA,EAAKsV,CAAO,CAAC,EACpChY,EAAM,QAAQ,gBAAgB,EAC9BzB,EAAM,QACN,MAAM8I,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEA,UAAAiC,MAACkd,GAAA,CAAK,KAAM,GAAI,EAAE,YACpB,EACF,EAEH,CACH,EAEMhM,EAAS,MAAOtW,GAAa,CACjC,IAAI0hB,EAAkC,KAClCC,EAAoC,KACpCC,EAAmC,KACnCC,EAAmC,KACnCC,EAAuC,KACvCC,EAAwC,KACxCC,EAAkC,KAClCC,EAAuC,KAC3C,GAAI,CACF,MAAMM,EAAO,MAAMtf,EAAI,IAAW,WAAW,mBAAmBjD,EAAE,IAAI,CAAC,EAAE,EACzE4I,EAAM,KAAK,CACT,MAAO,QAAQ5I,EAAE,IAAI,GACrB,MAAO,IACP,SACEsF,OAAC,OAAI,UAAU,aACb,UAAAA,OAAC,OAAI,UAAU,QAAQ,mBACfF,MAAC,QAAM,SAAAmd,EAAK,KAAK,GACzB,EACAnd,MAAC,SAAM,UAAU,cAAc,uBAAW,EAC1CA,MAAC,SACC,IAAMiW,GAAO,CAAEqG,EAASrG,CAAI,EAC5B,UAAU,QACV,KAAK,OACL,aAAckH,EAAK,cAErBjd,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,iBAAK,EACpCE,OAAC,UAAO,IAAM+V,GAAQsG,EAAUtG,EAAK,UAAU,SAAS,aAAckH,EAAK,MACzE,UAAAnd,MAAC,UAAO,MAAM,GAAG,8BAAkB,EAClCmb,GAAO,IAAKtM,GACX7O,MAAC,UAAe,MAAO6O,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,GACF,EACA3O,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCE,OAAC,UAAO,IAAM+V,GAAQuG,EAASvG,EAAK,UAAU,SAAS,aAAckH,EAAK,MAAQ,WAChF,UAAAnd,MAAC,UAAO,MAAM,UAAU,mBAAO,EAC/BA,MAAC,UAAO,MAAM,WAAW,oBAAQ,EACjCA,MAAC,UAAO,MAAM,MAAM,eAAG,GACzB,GACF,EACAE,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,YAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,iBAAK,EACpCA,MAAC,SAAM,IAAMiW,GAAQwG,EAAUxG,EAAK,UAAU,QAAQ,KAAK,QAAQ,aAAckH,EAAK,OAAS,UAAW,GAC5G,GACF,EACAjd,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,oBAAQ,EACvCE,OAAC,UAAO,IAAM+V,GAAQ4G,EAAa5G,EAAK,UAAU,SAAS,aAAckH,EAAK,UAAY,GACxF,UAAAnd,MAAC,UAAO,MAAM,GAAG,kBAAM,EACtBob,GAAW,IAAKf,GACfra,MAAC,UAAkB,MAAOqa,EAAE,GAAK,SAAAA,EAAE,OAAtBA,EAAE,EAA0B,CAC1C,GACH,GACF,EACAna,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,kCAAsB,EACrDA,MAAC,SACC,IAAMiW,GAAQ2G,EAAS3G,EACvB,UAAU,QACV,KAAK,OACL,cAAekH,EAAK,MAAQ,IAAI,KAAK,IAAI,GAC3C,EACF,GACF,EACAnd,MAAC,SAAM,UAAU,cAAc,iBAAK,QACnC,OAAI,IAAMiW,GAAQ0G,EAAiB1G,EAAK,UAAU,cAChD,SAAAiF,GAAa,IAAKxW,GAAA,OACjBxE,cAAC,SAAc,UAAU,eACvB,UAAAF,MAAC,SAAM,KAAK,WAAW,MAAO0E,EAAG,gBAAgBzG,EAAAkf,EAAK,QAAL,YAAAlf,EAAY,SAASyG,EAAC,CAAG,EAC1E1E,MAAC,QAAM,SAAA0E,CAAA,CAAE,IAFCA,CAGZ,EACD,EACH,EACA1E,MAAC,SAAM,UAAU,cAAc,yBAAa,EAC5CA,MAAC,YACC,IAAMiW,GAAQyG,EAAWzG,EACzB,UAAU,WACV,KAAM,EACN,aAAckH,EAAK,QAAU,IAC/B,EACF,EAEF,OACEjd,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC5DtD,OAAC2D,EAAA,CACC,QAAQ,UACR,QAAS,SAAY,CACnB,MAAMiZ,EAAkB,GACpBH,GACFA,EAAe,iBAAmC,gCAAgC,EAAE,QAASI,GAAO,CAClGD,EAAM,KAAKC,EAAG,KAAK,CACrB,CAAC,EAEH,MAAMC,IAAQJ,GAAA,YAAAA,EAAQ,QAAS,IAAI,MAAM,GAAG,EAAE,IAAKlY,GAAMA,EAAE,MAAM,EAAE,OAAO,OAAO,EACjF,GAAI,CACF,MAAM0Y,EAAU,MAAMvf,EAAI,IACxB,WAAW,mBAAmBjD,EAAE,IAAI,CAAC,GACrC,CACE,cAAc0hB,GAAA,YAAAA,EAAQ,QAAS,IAAI,OACnC,OAAOC,GAAA,YAAAA,EAAS,QAAS,GACzB,MAAMC,GAAA,YAAAA,EAAQ,QAAS,WACvB,OAAOC,GAAA,YAAAA,EAAS,QAAS,GACzB,MAAAK,EACA,KAAAE,EACA,UAAUH,GAAA,YAAAA,EAAY,QAAS,GAC/B,QAAQH,GAAA,YAAAA,EAAU,QAAS,GAC7B,EAEFd,EAAWjU,GAAQA,EAAI,IAAKpI,IAAOA,GAAE,OAAS3E,EAAE,KAAOwiB,EAAU7d,EAAE,CAAC,EACpE0F,EAAM,QAAQ,cAAc,EAC5BzB,EAAM,QACN,MAAM8I,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEA,UAAAiC,MAACkd,GAAA,CAAK,KAAM,GAAI,EAAE,UACpB,EACF,EAEH,CACH,OAASnf,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEMuZ,EAAW,MAAO1c,GAAa,CACnC,GAAK,QAAQ,iBAAiBA,EAAE,IAAI,mBAAmBA,EAAE,IAAI,GAAG,EAChE,GAAI,CACF,MAAMiD,EAAI,IAAI,WAAW,mBAAmBjD,EAAE,IAAI,CAAC,EAAE,EACrDghB,EAAWjU,GAAQA,EAAI,OAAQpI,GAAMA,EAAE,OAAS3E,EAAE,IAAI,CAAC,EACvDqK,EAAM,QAAQ,gBAAgB,CAChC,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEMsf,EAAW,MAAOziB,GAAa,CACnC,IAAI8hB,EAAuC,KAC3ClZ,EAAM,KAAK,CACT,MAAO,UAAU5I,EAAE,IAAI,GACvB,SACEsF,OAAC,OAAI,UAAU,cACb,UAAAA,OAAC,KAAE,UAAU,8BAA+B,UAAAtF,EAAE,OAAS,IAAI,MAAIA,EAAE,MAAK,EACtEoF,MAAC,KAAE,UAAU,mBAAoB,WAAE,YAAY,QAC9C,SAAM,UAAU,cAAc,QAAQ,gBAAgB,kBAAM,EAC7DA,MAAC,YACC,IAAMiW,GAAQyG,EAAWzG,EACzB,GAAG,gBACH,UAAU,WACV,KAAM,EACN,YAAY,6BACZ,UAAS,IACX,EACF,EAEF,OACE/V,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC5DtD,OAAC2D,EAAA,CACC,QAAQ,UACR,QAAS,SAAY,CACnB,MAAMyZ,IAAUZ,GAAA,YAAAA,EAAU,QAAS,IAAI,OACvC,GAAI,CAACY,EAAQ,CACXrY,EAAM,QAAQ,qBAAqB,EACnC,MACF,CACA,GAAI,CACF,MAAMpH,EAAI,KAAK,WAAW,mBAAmBjD,EAAE,IAAI,CAAC,UAAW,CAAE,OAAA0iB,CAAA,CAAQ,EACzErY,EAAM,QAAQ,WAAWrK,EAAE,IAAI,GAAG,EAClC4I,EAAM,OACR,OAASzF,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEA,UAAAiC,MAACud,GAAA,CAAK,KAAM,GAAI,EAAE,YACpB,EACF,EAEH,CACH,EAEMC,EAAY,MAAO5iB,GAAa,CACpC,GAAI,CACF,MAAMwiB,EAAU,MAAMvf,EAAI,KAAY,WAAW,mBAAmBjD,EAAE,IAAI,CAAC,UAAU,EACrFghB,EAAWjU,GAAQA,EAAI,IAAKpI,GAAOA,EAAE,OAAS3E,EAAE,KAAOwiB,EAAU7d,CAAE,CAAC,EACpE0F,EAAM,QAAQ,GAAGrK,EAAE,IAAI,aAAa,CACtC,OAASmD,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAEM0f,EAAc,MAAO7iB,EAAU4Q,IAAyC,CAC5E,GAAI,CACF,MAAM4R,EAAU,MAAMvf,EAAI,KAAY,WAAW,mBAAmBjD,EAAE,IAAI,CAAC,UAAW,CAAE,OAAA4Q,CAAA,CAAQ,EAChGoQ,EAAWjU,GAAQA,EAAI,IAAKpI,GAAOA,EAAE,OAAS3E,EAAE,KAAOwiB,EAAU7d,CAAE,CAAC,CACtE,OAASxB,EAAK,CACZkH,EAAM,MAAM,yBAA0BlH,EAAc,OAAO,EAAE,CAC/D,CACF,EAEA,OACEmC,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAACyB,GAAA,CAAI,KAAM,GAAI,EAAE,YAAU+S,EAAO,OAAO,KAC3C,EACAtU,OAAC,KAAE,UAAU,gBAAgB,wCACAF,MAAC,OAAI,gBAAI,EAAM,iBAAcA,MAAC,OAAI,kBAAM,EAAM,iBAC3E,GACF,EACAE,OAAC,OAAI,UAAU,eACb,UAAAF,MAAC,OAAI,UAAU,eACb,SAAAA,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,UACZ,MAAO+b,EACP,SAAW3d,GAAM4d,EAAU5d,EAAE,OAAO,KAAK,IAE7C,EACA8B,OAAC,UACC,UAAU,mBACV,MAAO2b,EACP,SAAWzd,GAAM0d,EAAkB1d,EAAE,OAAO,KAAK,EAEjD,UAAA4B,MAAC,UAAO,MAAM,GAAG,0BAAc,EAC9Bob,GAAW,IAAKf,GACfra,MAAC,UAAkB,MAAOqa,EAAE,GAAK,SAAAA,EAAE,OAAtBA,EAAE,EAA0B,CAC1C,EACDra,MAAC,UAAO,MAAM,WAAW,yBAAa,YAEvC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS4D,EAC7C,UAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,SACC0D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASuY,EAC3C,UAAApc,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,cACpB,GACF,GACF,EAECoY,EAAQ,OAAS,GAChBhc,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC0d,GAAA,CAAQ,KAAM,GAAI,EAClBxB,EAAQ,IAAKxX,GACZ1E,MAAC,QAAa,UAAU,MAAO,SAAA0E,CAAA,EAApBA,CAAsB,CAClC,GACH,EAGD9H,EACCoD,MAAC,OAAI,UAAU,eAAe,SAAAA,MAACuO,GAAA,CAAQ,KAAK,KAAK,EAAE,EACjDiG,EAAO,SAAW,EACpBxU,MAACgM,GAAA,CACC,KAAMhM,MAACyB,GAAA,CAAI,KAAM,GAAI,EACrB,MAAM,kBACN,QAAQ,sDAGT,OAAI,UAAU,aACZ,SAAA+S,EAAO,IAAK5Z,GACXoF,MAAC2d,GAAA,CAEC,MAAO/iB,EACP,SAAU,IAAMyiB,EAASziB,CAAC,EAC1B,OAAQ,IAAMsW,EAAOtW,CAAC,EACtB,SAAU,IAAM0c,EAAS1c,CAAC,EAC1B,UAAW,IAAM4iB,EAAU5iB,CAAC,EAC5B,YAAcuL,GAAMsX,EAAY7iB,EAAGuL,CAAC,GAN/BvL,EAAE,KAQV,EACH,GAEJ,CAEJ,CAEA,SAAS+iB,GAAU,CACjB,MAAA5N,EACA,SAAAsN,EACA,OAAAnM,EACA,SAAAoG,EACA,UAAAkG,EACA,YAAAC,CACF,EAOG,CACD,KAAM,CAACrhB,EAAUC,CAAW,EAAIF,WAAS,EAAK,EACxCyhB,EAAWvC,GAActL,EAAM,QAAQ,EACvC8N,GAAa9N,EAAM,SAAW,WAAa,CAAC,CAACA,EAAM,gBAAkB,CAACA,EAAM,QAClF,OACE7P,OAAC0K,EAAA,CACC,QAAQ,WACR,YAAW,GACX,UAAW3H,EACT,aACA4a,GAAa,aACb9N,EAAM,SAAW,YAGnB,UAAA7P,OAAC,OAAI,UAAU,kBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAACub,IAAU,OAAQxL,EAAM,OAAQ,QAASA,EAAM,QAAS,EACxDA,EAAM,MACT,EACA7P,OAAC,OAAI,UAAU,oBACZ,UAAA6P,EAAM,UACL/P,MAAC,QACC,UAAU,sBACV,MAAO,CAAE,WAAY,sBAAsB4d,CAAQ,qBAAsB,MAAOA,CAAA,EAE/E,SAAA7N,EAAM,WAGX/P,MAAC0b,IAAW,MAAA3L,CAAA,CAAc,GAC5B,GACF,EACA/P,MAAC,KAAE,UAAU,kBAAmB,YAAS+P,EAAM,YAAa,GAAG,EAAE,EACjE7P,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,QAAK,UAAU,OAAO,MAAO+P,EAAM,OAAS,GAC1C,SAAAA,EAAM,OAAS,IAClB,QACC,QAAK,UAAU,qBAAsB,SAAAxH,GAAewH,EAAM,KAAK,EAAE,GACpE,EACCA,EAAM,MAAQA,EAAM,KAAK,OAAS,GACjC/P,MAAC,OAAI,UAAU,kBACZ,SAAA+P,EAAM,KAAK,IAAKrL,GACf1E,MAAC,QAAa,UAAU,iBAAkB,SAAA0E,CAAA,EAA/BA,CAAiC,CAC7C,EACH,GAEAmZ,GAAa9N,EAAM,WACnB7P,OAAC,OAAI,UAAU,sBACZ,UAAA6P,EAAM,eACL7P,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC2B,GAAA,CAAS,KAAM,GAAI,EACpB3B,MAAC,QAAK,UAAU,QAAQ,sBAAU,EAClCA,MAAC,QAAK,UAAU,OAAQ,WAAM,cAAc,GAC9C,EAED+P,EAAM,UAAY,CAACA,EAAM,eACxB7P,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC8G,GAAA,CAAa,KAAM,GAAI,EACxB9G,MAAC,QAAK,UAAU,QAAQ,gBAAI,QAC3B,QAAK,UAAU,OAAQ,SAAA+P,EAAM,SAAS,GAAG,EAC1C/P,MAAC,QAAK,UAAU,qBAAsB,YAAe+P,EAAM,SAAS,UAAU,EAAE,GAClF,EAEDA,EAAM,YAAc,MAAQA,EAAM,WAAa,GAC9C7P,OAAC,OAAI,UAAU,iBACb,UAAAF,MAACpJ,GAAA,CAAO,KAAM,GAAI,EAClBoJ,MAAC,QAAK,UAAU,QAAQ,wBAAY,EACpCE,OAAC,QAAK,UAAU,eAAgB,eAAK,OAAO6P,EAAM,aAAe,GAAK,GAAG,EAAE,KAAC,EAC5E7P,OAAC,QAAK,UAAU,qBAAqB,cAAE6P,EAAM,eAAe,IAAEA,EAAM,WAAW,KAAC,GAClF,GAEJ,EAEDA,EAAM,WACL7P,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,EACzB7G,OAAC,QAAK,UAAU,QAAQ,yBAAa6P,EAAM,UAAU,SAAQ,GAC/D,EAEF7P,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC2D,GAAO,QAAQ,UAAU,KAAK,KAAK,QAASwZ,EAC3C,UAAArd,MAACud,GAAA,CAAK,KAAM,GAAI,EAAE,WACpB,SACC1Z,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASqN,EAC7C,UAAAlR,MAACuY,GAAA,CAAO,KAAM,GAAI,EAAE,SACtB,GACExI,EAAM,SAAWA,EAAM,SAAW,WAAaA,EAAM,SAAW,UAChE7P,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS2Z,EAAW,MAAM,qBAC1D,UAAAxd,MAAC8d,GAAA,CAAS,KAAM,GAAI,EAAE,YACxB,EAEF9d,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASyT,EACzC,SAAAtX,MAACiP,GAAA,CAAO,KAAM,GAAI,EACpB,EACAjP,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAY5D,EAAW,WAAa,SACpC,QAAS,IAAMC,EAAa2C,GAAM,CAACA,CAAC,EACpC,MAAO,CAAE,WAAY,QAEpB,SAAA5C,QAAYgF,GAAA,CAAY,KAAM,GAAI,EAAKpB,MAACqB,GAAA,CAAa,KAAM,GAAI,GAClE,EACF,EACCjF,GACC8D,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,OAAI,UAAU,4BACb,UAAAF,MAAC,QAAK,UAAU,gBAAgB,uBAAW,EAC3CA,MAAC6D,EAAA,CACC,QAASkM,EAAM,SAAW,OAAS,UAAY,QAC/C,KAAK,KACL,QAAS,IAAM0N,EAAY,MAAM,EAClC,kBAGDzd,MAAC6D,EAAA,CACC,QAASkM,EAAM,SAAW,UAAY,UAAY,QAClD,KAAK,KACL,QAAS,IAAM0N,EAAY,SAAS,EACrC,qBAGDzd,MAAC6D,EAAA,CACC,QAASkM,EAAM,SAAW,QAAU,UAAY,QAChD,KAAK,KACL,QAAS,IAAM0N,EAAY,OAAO,EACnC,kBAED,EACF,EACAvd,OAAC,OAAI,UAAU,kBACb,UAAAF,MAACc,GAAA,CAAO,KAAM,GAAI,EAClBd,MAAC,QAAK,UAAU,uBAAwB,WAAM,KAAK,GACrD,GACF,IAIR,CCpqBO,SAAS+d,GAAS,CAAE,GAAA9V,EAAI,SAAA+C,GAA2B,CACxD,OACEhL,MAAC,OACC,GAAAiI,EACA,gBAAeA,EACf,UAAWhF,EAAG,gBAAgB,EAC9B,MAAO+a,GAEP,eAACC,GAAA,CAAc,cAAe,CAACC,EAAS,EAAI,SAAAlT,CAAA,CAAS,GAG3D,CAQA,MAAMmT,GAED,CACH,KAAS,CAAE,GAAI,6CAA+C,OAAQ,cAAkB,GAAI,cAAkB,KAAMtX,GAAiB,MAAO,QAC5I,KAAS,CAAE,GAAI,gDAAiD,OAAQ,iBAAkB,GAAI,iBAAkB,KAAME,GAAgB,MAAO,WAC7I,QAAS,CAAE,GAAI,gDAAiD,OAAQ,iBAAkB,GAAI,iBAAkB,KAAMD,GAAgB,MAAO,WAC7I,OAAS,CAAE,GAAI,+CAAiD,OAAQ,eAAkB,GAAI,eAAkB,KAAMsX,GAAgB,MAAO,SAC/I,EAEO,SAASC,GAAQ,CAAE,GAAApW,EAAI,KAAAqW,EAAO,OAAQ,SAAAtT,GAA0B,CACrE,MAAMtG,EAAIyZ,GAAaG,CAAI,EACrBnb,EAAOuB,EAAE,KACf,OACExE,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAWhF,EAAG,gBAAiB,iBAAiBqb,CAAI,EAAE,EACtD,MAAO,CACL,QAAS,OACT,IAAK,GACL,QAAS,YACT,OAAQ,SACR,WAAY,aAAa5Z,EAAE,MAAM,GACjC,WAAYA,EAAE,GACd,aAAc,EACd,MAAO,eAET,KAAM4Z,IAAS,UAAYA,IAAS,OAAS,QAAU,OAEvD,UAAAte,MAAC,OAAI,MAAO,CAAE,WAAY,EAAG,MAAO0E,EAAE,GAAI,WAAY,GACpD,SAAA1E,MAACmD,EAAA,CAAK,KAAM,GAAI,EAClB,EACAjD,OAAC,OAAI,MAAO,CAAE,KAAM,EAAG,SAAU,GAC/B,UAAAF,MAAC,OAAI,MAAO,CAAE,WAAY,IAAK,SAAU,GAAI,MAAO0E,EAAE,GAAI,aAAc,GACrE,WAAE,MACL,QACC,OAAI,UAAU,iBAAiB,MAAO,CAAE,GAAGsZ,GAAY,SAAU,IAChE,eAACC,GAAA,CAAc,cAAe,CAACC,EAAS,EAAI,SAAAlT,EAAS,EACvD,GACF,IAGN,CAYO,SAASuT,GAAU,CAAE,GAAAtW,EAAI,MAAAd,GAAyB,CACvD,OACEnH,MAAC,MACC,GAAAiI,EACA,gBAAeA,EACf,UAAU,kBACV,MAAO,CACL,UAAW,OACX,QAAS,EACT,OAAQ,SACR,QAAS,OACT,cAAe,SACf,IAAK,GAGN,SAAAd,EAAM,IAAKmJ,GACVpQ,OAAC,MAEC,MAAO,CACL,QAAS,OACT,WAAY,aACZ,IAAK,GACL,QAAS,WACT,aAAc,EACd,WAAY,iBACZ,OAAQ,0BACR,SAAU,IAGZ,UAAAF,MAAC,QACC,cAAW,GACX,MAAO,CACL,WAAY,EACZ,UAAW,EACX,MAAO,GACP,OAAQ,GACR,aAAc,EACd,OAAQ,eAAesQ,EAAK,QAAU,iBAAmB,sBAAsB,GAC/E,WAAYA,EAAK,QAAU,iBAAmB,cAC9C,MAAO,YACP,QAAS,cACT,WAAY,SACZ,eAAgB,UAGjB,SAAAA,EAAK,QAAUtQ,MAAC1J,GAAA,CAAM,KAAM,GAAI,YAAa,EAAG,EAAK,OAExD0J,MAAC,QAAK,MAAO,CACX,MAAOsQ,EAAK,QAAU,kBAAoB,cAC1C,eAAgBA,EAAK,QAAU,eAAiB,OAChD,UAAW,cAEV,WAAK,MACR,IApCKA,EAAK,GAsCb,GAGP,CAQO,SAASkO,GAAM,CAAE,GAAAvW,EAAI,QAAAwW,EAAS,KAAAC,GAAoB,CACvD,OACE1e,MAAC,OACC,GAAAiI,EACA,gBAAeA,EACf,UAAU,mBACV,MAAO,CACL,OAAQ,SACR,OAAQ,0BACR,aAAc,EACd,SAAU,OACV,WAAY,kBAGd,SAAA/H,OAAC,SACC,MAAO,CACL,MAAO,OACP,eAAgB,WAChB,SAAU,IAGZ,UAAAF,MAAC,SACC,SAAAA,MAAC,MACE,WAAQ,IAAI,CAACqa,EAAGjf,IACf4E,MAAC,MAEC,MAAO,CACL,UAAW,OACX,QAAS,WACT,aAAc,iCACd,WAAY,YACZ,MAAO,kBACP,WAAY,IACZ,SAAU,GACV,cAAe,YACf,cAAe,GACf,WAAY,UAGb,SAAAqa,CAAA,EAdIjf,CAAA,CAgBR,EACH,EACF,EACA4E,MAAC,SACE,SAAA0e,EAAK,IAAI,CAACtJ,EAAKuJ,UACb,MAAY,MAAO,CAAE,UAAWA,IAAO,EAAI,OAAS,2BAClD,SAAAvJ,EAAI,IAAI,CAACwJ,EAAMC,IACd7e,MAAC,MAEC,MAAO,CACL,QAAS,WACT,MAAO,cACP,cAAe,MACf,UAAW,cAGZ,SAAA4e,CAAA,EARIC,CAAA,CAUR,GAbMF,CAcT,CACD,EACH,IACF,EAGN,CAcO,SAASG,GAAS,CAAE,GAAA7W,EAAI,KAAAzD,GAAuB,OACpD,KAAM,CAACkI,EAAUC,CAAW,EAAIxQ,aAAiB8B,EAAAuG,EAAK,CAAC,IAAN,YAAAvG,EAAS,KAAM,EAAE,EAC5DmF,EAASmR,UACb,IAAM/P,EAAK,KAAME,GAAMA,EAAE,KAAOgI,CAAQ,GAAKlI,EAAK,CAAC,EACnD,CAACA,EAAMkI,CAAQ,GAGjB,OACExM,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,iBACV,MAAO,CACL,OAAQ,SACR,OAAQ,0BACR,aAAc,EACd,SAAU,SACV,WAAY,kBAGd,UAAAjI,MAAC,OACC,KAAK,UACL,MAAO,CACL,QAAS,OACT,IAAK,EACL,QAAS,EACT,WAAY,YACZ,aAAc,0BACd,UAAW,QAGZ,SAAAwE,EAAK,IAAKE,GAAM,CACf,MAAMqa,EAAWra,EAAE,MAAOtB,GAAA,YAAAA,EAAQ,IAClC,OACElD,OAAC,UAEC,KAAK,SACL,KAAK,MACL,gBAAe6e,EACf,QAAS,IAAMpS,EAAYjI,EAAE,EAAE,EAC/B,MAAO,CACL,QAAS,WACT,SAAU,GACV,WAAY,mBACZ,aAAc,EACd,OAAQ,OACR,OAAQ,UACR,WAAYqa,EAAW,iBAAmB,cAC1C,MAAOA,EAAW,qBAAuB,kBACzC,UAAWA,EAAW,0BAA4B,OAClD,WAAY,UAGd,UAAA/e,MAAC,QAAM,WAAE,MAAM,EACd0E,EAAE,UACD1E,MAAC,QAAK,MAAO,CAAE,WAAY,EAAG,MAAO,kBAAmB,SAAU,IAC/D,WAAE,SACL,IAtBG0E,EAAE,GA0Bb,CAAC,IAEFtB,GACClD,OAAAO,WAAA,CACE,UAAAT,MAAC,OACC,MAAO,CACL,OAAQ,EACR,QAAS,GACT,UAAW,OACX,WAAY,mBACZ,SAAU,KACV,WAAY,KACZ,MAAO,cACP,WAAY,kBAGd,SAAAA,MAAC,QAAM,SAAAoD,EAAO,KAAK,IAEpBA,EAAO,SACNpD,MAAC,OACC,MAAO,CACL,QAAS,WACT,UAAW,0BACX,SAAU,GACV,MAAO,kBACP,WAAY,aAGb,SAAAoD,EAAO,SACV,EAEJ,IAIR,CAeO,SAAS4b,GAAS,CAAE,GAAA/W,EAAI,MAAAiE,EAAO,SAAA+S,EAAU,QAAAC,GAA0B,CACxE,OACEhf,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,iBACV,MAAO,CACL,OAAQ,SACR,QAAS,GACT,OAAQ,0BACR,aAAc,GACd,WAAY,kBAGb,UAAAiE,GACClM,MAAC,MAAG,MAAO,CAAE,OAAQ,EAAG,aAAc,EAAG,SAAU,GAAI,WAAY,IAAK,MAAO,sBAC5E,SAAAkM,EACH,EAED+S,GACCjf,MAAC,KAAE,MAAO,CAAE,OAAQ,EAAG,aAAc,GAAI,SAAU,GAAI,MAAO,mBAC3D,SAAAif,EACH,EAEFjf,MAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,GAAI,oBAAqB,wCAC1D,SAAAkf,EAAQ,IAAKC,GAAQ,CACpB,MAAMC,EAAQ,CAAC,CAACD,EAAI,YACpB,OACEjf,OAAC,OAEC,MAAO,CACL,SAAU,WACV,QAAS,GACT,aAAc,EACd,OAAQkf,EAAQ,2BAA6B,0BAC7C,WAAYA,EAAQ,sBAAwB,aAG7C,UAAAA,GACCpf,MAAC,QACC,MAAO,CACL,SAAU,WACV,IAAK,IACL,MAAO,GACP,QAAS,UACT,SAAU,GACV,WAAY,IACZ,MAAO,YACP,WAAY,iBACZ,aAAc,KAEjB,yBAIHA,MAAC,OAAI,MAAO,CAAE,WAAY,IAAK,SAAU,GAAI,MAAO,qBAAsB,aAAc,GACrF,WAAI,MACP,EACAA,MAAC,OAAI,MAAO,CAAE,SAAU,GAAI,MAAO,eAChC,SAAAmf,EAAI,OACP,IA/BKA,EAAI,GAkCf,CAAC,EACH,IAGN,CAaO,SAASE,GAAc,CAAE,GAAApX,EAAI,UAAAqX,GAAiC,CACnE,KAAM,CAACC,EAASC,CAAU,EAAIrjB,WAA4C,EAAE,EAE5E,SAASsjB,EAAUC,EAAa/jB,EAA0B,CACxD6jB,EAAYpgB,IAAU,CAAE,GAAGA,EAAM,CAACsgB,CAAG,EAAG/jB,CAAA,EAAQ,CAClD,CAEA,OACEuE,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,sBACV,MAAO,CACL,OAAQ,SACR,QAAS,GACT,OAAQ,0BACR,aAAc,GACd,WAAY,iBACZ,QAAS,OACT,cAAe,SACf,IAAK,IAGP,UAAAjI,MAAC,OAAI,MAAO,CAAE,SAAU,GAAI,WAAY,IAAK,MAAO,sBAAwB,0BAE5E,EACCsf,EAAU,IAAKna,UACb,OAAe,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,GACtE,UAAAnF,MAAC,SACC,QAAS,MAAMmF,EAAE,EAAE,GACnB,MAAO,CAAE,SAAU,GAAI,MAAO,cAAe,WAAY,KAExD,SAAAA,EAAE,QAEJA,EAAE,OAAS,UACVjF,OAAC,UACC,GAAI,MAAMiF,EAAE,EAAE,GACd,MAAQoa,EAAQpa,EAAE,EAAE,GAAgB,GACpC,SAAW/G,GAAMqhB,EAAUta,EAAE,GAAI/G,EAAE,OAAO,KAAK,EAC/C,MAAOuhB,GAEP,UAAA3f,MAAC,UAAO,MAAM,GAAG,sBAAU,GACzBmF,EAAE,SAAW,IAAI,IAAKga,GACtBnf,MAAC,UAAiB,MAAOmf,EAAM,SAAAA,CAAA,EAAlBA,CAAsB,CACpC,KAGJha,EAAE,OAAS,QACVnF,MAAC,SACC,GAAI,MAAMmF,EAAE,EAAE,GACd,KAAK,OACL,MAAQoa,EAAQpa,EAAE,EAAE,GAAgB,GACpC,SAAW/G,GAAMqhB,EAAUta,EAAE,GAAI/G,EAAE,OAAO,KAAK,EAC/C,MAAOuhB,EAAA,GAGVxa,EAAE,OAAS,SACVnF,MAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,GACzD,UAAAmF,EAAE,SAAW,IAAI,IAAKga,GAAQ,CAC9B,MAAMS,EAAWL,EAAQpa,EAAE,EAAE,GAAkB,GACzC0a,EAAUD,EAAQ,SAAST,CAAG,EACpC,OACEjf,OAAC,SAEC,MAAO,CACL,QAAS,OACT,WAAY,SACZ,IAAK,EACL,SAAU,GACV,MAAO,cACP,OAAQ,WAGV,UAAAF,MAAC,SACC,KAAK,WACL,QAAA6f,EACA,SAAU,IAAM,CACd,MAAMxgB,EAAOwgB,EACTD,EAAQ,OAAQE,GAAMA,IAAMX,CAAG,EAC/B,CAAC,GAAGS,EAAST,CAAG,EACpBM,EAAUta,EAAE,GAAI9F,CAAI,CACtB,IAEFW,MAAC,QAAM,SAAAmf,CAAA,CAAI,IApBNA,CAAA,CAuBX,CAAC,EACH,IA5DMha,EAAE,EA8DZ,CACD,IAGP,CAEA,MAAMwa,GAAkC,CACtC,QAAS,WACT,SAAU,GACV,aAAc,EACd,OAAQ,iCACR,WAAY,YACZ,MAAO,cACP,WAAY,SACd,EAaMI,GAA0F,CAC9F,MAAU,CAAE,GAAI,sBAAuB,GAAI,iBAAkB,MAAO,KACpE,SAAU,CAAE,GAAI,6CAA8C,GAAI,cAAe,MAAO,KACxF,QAAU,CAAE,GAAI,oBAAqB,GAAI,eAAgB,MAAO,KAChE,QAAU,CAAE,GAAI,2BAA4B,GAAI,gBAAiB,MAAO,IAC1E,EAEO,SAASC,GAAS,CAAE,GAAA/X,EAAI,MAAAiE,EAAO,QAAA5Q,GAA0B,CAC9D,OACE4E,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,iBACV,MAAO,CACL,OAAQ,SACR,QAASiE,EAAQ,GAAK,EACtB,OAAQ,0BACR,aAAc,EACd,WAAY,kBAGb,UAAAA,GACClM,MAAC,OACC,MAAO,CACL,SAAU,GACV,WAAY,IACZ,MAAO,kBACP,cAAe,YACf,cAAe,GACf,aAAc,GAGf,SAAAkM,CAAA,GAGLlM,MAAC,MAAG,MAAO,CAAE,UAAW,OAAQ,QAAS,EAAG,OAAQ,EAAG,QAAS,OAAQ,cAAe,SAAU,IAAK,GACnG,SAAA1E,EAAQ,IAAK8C,GAAM,CAClB,MAAMsG,EAAIqb,GAAY3hB,EAAE,MAAM,EAC9B,OACE8B,OAAC,MAEC,MAAO,CACL,QAAS,OACT,WAAY,SACZ,IAAK,GACL,QAAS,UACT,aAAc,EACd,SAAU,IAGZ,UAAAF,MAAC,QACC,aAAY5B,EAAE,OACd,MAAOA,EAAE,OACT,MAAO,CACL,WAAY,EACZ,MAAO,GACP,OAAQ,GACR,aAAc,EACd,WAAYsG,EAAE,GACd,MAAOA,EAAE,GACT,QAAS,cACT,WAAY,SACZ,eAAgB,SAChB,SAAU,GACV,WAAY,IACZ,WAAY,oBAGb,SAAAA,EAAE,QAEL1E,MAAC,QACC,MAAO,CACL,WAAY,mBACZ,MAAO,cACP,UAAW,YACX,KAAM,GAGP,SAAA5B,EAAE,OAEJA,EAAE,MACD4B,MAAC,QAAK,MAAO,CAAE,SAAU,GAAI,MAAO,mBACjC,SAAA5B,EAAE,KACL,IA3CGA,EAAE,KA+Cb,CAAC,EACH,IAGN,CAWO,SAAS6hB,GAAK,CAAE,GAAAhY,EAAI,SAAAiY,EAAU,SAAAC,EAAU,KAAAzX,EAAO,UAAW,OAAA0X,EAAQ,MAAAC,GAAoB,CAC3F,MAAMC,EAAcF,EAAO,MAAM;AAAA,CAAI,EAC/BG,EAAaF,EAAM,MAAM;AAAA,CAAI,EAE7BG,EACJtgB,OAAC,OACC,MAAO,CACL,QAAS,OACT,WAAY,SACZ,IAAK,EACL,QAAS,WACT,WAAY,YACZ,aAAc,0BACd,SAAU,GACV,MAAO,kBACP,WAAY,oBAGd,UAAAF,MAAC3I,GAAA,CAAU,KAAM,GAAI,EACrB2I,MAAC,QAAK,MAAO,CAAE,MAAO,eAAkB,YAAY,OAAO,EAC1DmgB,UAAa,QAAK,eAAGA,CAAA,EAAS,EAC/BngB,MAAC,QAAK,MAAO,CAAE,WAAY,OAAQ,cAAe,YAAa,cAAe,IAC3E,SAAA0I,CAAA,CACH,KAIE+X,EAAiC,CACrC,OAAQ,EACR,QAAS,EACT,WAAY,mBACZ,SAAU,KACV,WAAY,KACZ,MAAO,cACP,WAAY,kBAGRC,EAAU,CAACC,EAAcC,EAAiBvR,IAAgC,CAC9E,MAAMwR,EAAsC,CAC1C,IAAK,oBACL,IAAK,sBACL,IAAK,eAEDC,EAAyC,CAC7C,IAAK,eACL,IAAK,iBACL,IAAK,mBAEP,OACE5gB,OAAC,OACC,MAAO,CACL,QAAS,OACT,QAAS,SACT,WAAY2gB,EAAOxR,CAAI,GAGzB,UAAArP,MAAC,QAAK,MAAO,CAAE,MAAO,GAAI,MAAO8gB,EAAUzR,CAAI,EAAG,WAAY,OAAQ,WAAY,GAAM,SAAAsR,EAAK,EAC7F3gB,MAAC,QAAK,MAAO,CAAE,WAAY,MAAO,KAAM,EAAG,UAAW,QAAW,SAAA4gB,GAAW,IAAI,IAGtF,EAEA,OACE1gB,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,aACV,MAAO,CACL,OAAQ,SACR,OAAQ,0BACR,aAAc,EACd,SAAU,SACV,WAAY,kBAGb,UAAAuY,EACA9X,IAAS,UACRxI,OAAC,OAAI,MAAOugB,EACT,UAAAH,EAAY,IAAI,CAACS,EAAG3lB,UAClB,OAAmB,SAAAslB,EAAQ,IAAKK,EAAG,KAAK,GAA/B,IAAI3lB,CAAC,EAA4B,CAC5C,EACAmlB,EAAW,IAAI,CAACQ,EAAG3lB,IAClB4E,MAAC,OAAmB,SAAA0gB,EAAQ,IAAKK,EAAG,KAAK,GAA/B,IAAI3lB,CAAC,EAA4B,CAC5C,GACH,SAEC,OAAI,MAAO,CAAE,QAAS,OAAQ,oBAAqB,WAClD,UAAA4E,MAAC,OAAI,MAAO,CAAE,GAAGygB,EAAW,YAAa,2BACtC,SAAAH,EAAY,IAAI,CAACS,EAAG3lB,IACnB4E,MAAC,OAAa,SAAA0gB,EAAQ,IAAKK,EAAG,KAAK,GAAzB3lB,CAA2B,CACtC,EACH,QACC,OAAI,MAAOqlB,EACT,SAAAF,EAAW,IAAI,CAACQ,EAAG3lB,IAClB4E,MAAC,OAAa,WAAQ,IAAK+gB,EAAG,KAAK,GAAzB3lB,CAA2B,CACtC,EACH,GACF,IAIR,CAUA,MAAM4lB,GAA0G,CAC9G,GAAM,CAAE,GAAI,iBAAkB,KAAM5f,GAAa,MAAO,eACxD,KAAM,CAAE,GAAI,eAAkB,KAAMA,GAAa,MAAO,iBACxD,KAAM,CAAE,GAAI,kBAAmB,KAAMxI,GAAY,MAAO,OAC1D,EAEO,SAASqoB,GAAK,CAAE,GAAAhZ,EAAI,MAAAiZ,EAAO,MAAAvlB,EAAO,MAAAwlB,EAAO,KAAAC,GAAmB,CACjE,MAAM1c,EAAIyc,EAAQH,GAAYG,CAAK,EAAI,KACvC,OACEjhB,OAAC,OACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,aACV,MAAO,CACL,QAAS,GACT,OAAQ,0BACR,aAAc,GACd,WAAY,iBACZ,QAAS,OACT,cAAe,SACf,IAAK,EACL,SAAU,KAGZ,UAAAjI,MAAC,OAAI,MAAO,CAAE,SAAU,GAAI,MAAO,kBAAmB,cAAe,YAAa,cAAe,IAC9F,SAAAkhB,EACH,EACAhhB,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,WAAY,WAAY,IAAK,GAC1D,UAAAF,MAAC,QAAK,MAAO,CAAE,SAAU,GAAI,WAAY,IAAK,MAAO,sBAClD,SAAArE,CAAA,CACH,EACC+I,GACC1E,MAAC,QACC,aAAY0E,EAAE,MACd,MAAO,CACL,QAAS,cACT,WAAY,SACZ,MAAOA,EAAE,GACT,UAAWA,EAAE,OAAStD,IAAe+f,IAAU,KAAO,iBAAmB,QAG3E,SAAAnhB,MAAC0E,EAAE,KAAF,CAAO,KAAM,GAAI,GACpB,EAEJ,EACC0c,GACCphB,MAAC,OAAI,MAAO,CAAE,SAAU,GAAI,MAAO,mBAChC,SAAAohB,CAAA,CACH,IAIR,CAkBA,MAAMC,GAA0F,CAC9F,KAAU,CAAE,OAAQ,cAAkB,KAAM,iBAAkB,GAAI,eAClE,SAAU,CAAE,OAAQ,iBAAkB,KAAM,iBAAkB,GAAI,eAClE,KAAU,CAAE,OAAQ,uBAAwB,KAAM,YAAa,GAAI,kBACrE,EAEMC,GAAQ,IACRC,GAAQ,GACRC,GAAQ,GACRC,GAAQ,GAEP,SAASC,GAAS,CAAE,GAAAzZ,EAAI,MAAA0Z,EAAO,YAAAC,EAAc,IAAqB,CACvE,GAAID,EAAM,SAAW,EACnB,OACE3hB,MAAC,OAAI,GAAAiI,EAAQ,gBAAeA,EAAI,UAAU,iBACxC,SAAAjI,MAAC6hB,GAAA,CAAM,GAAA5Z,CAAA,CAAQ,EACjB,EAIJ,MAAM6Z,EAAO,IAAI,IAAIH,EAAM,IAAKxb,GAAM,CAACA,EAAE,GAAIA,CAAC,CAAU,CAAC,EACnD4b,EAASC,GAAYL,CAAK,EAE1BM,EAAO,KAAK,IAAI,GAAGF,EAAO,IAAK/mB,GAAMA,EAAE,GAAG,CAAC,EAAI,EAC/C0jB,EAAO,KAAK,IAAI,GAAGqD,EAAO,IAAK/mB,GAAMA,EAAE,GAAG,CAAC,EAAI,EAC/CknB,EAAQD,GAAQX,GAAQE,IAASA,GACjCxlB,EAAS0iB,GAAQ6C,GAAQE,IAASA,GAExC,SAASU,EAAWC,EAAiD,CAEnE,GAAI,CADSN,EAAK,IAAIM,CAAM,EACjB,OAAO,KAClB,MAAMC,EAAMN,EAAO,KAAM/mB,GAAMA,EAAE,KAAOonB,CAAM,EAC9C,OAAKC,EACE,CACL,EAAGb,GAAQa,EAAI,KAAOf,GAAQE,IAASF,GAAQ,EAC/C,EAAGG,GAAQY,EAAI,KAAOd,GAAQE,IAASF,GAAQ,GAHhC,IAKnB,CAEA,OACEvhB,MAAC,OACC,GAAAiI,EACA,gBAAeA,EACf,UAAU,iBACV,MAAO,CACL,OAAQ,SACR,QAAS,GACT,OAAQ,0BACR,aAAc,GACd,WAAY,iBACZ,SAAU,QAGZ,SAAA/H,OAAC,OACC,KAAK,MACL,aAAW,mBACX,MAAAgiB,EACA,OAAAlmB,EACA,MAAO,CAAE,QAAS,QAAS,SAAU,QAErC,UAAAgE,MAAC,QACC,SAAAA,MAAC,UACC,GAAI,SAASiI,CAAE,GACf,QAAQ,YACR,KAAK,IACL,KAAK,IACL,YAAY,IACZ,aAAa,IACb,OAAO,qBAEP,SAAAjI,MAAC,QAAK,EAAE,wBAAwB,KAAK,kBAAkB,IAE3D,EAEC4hB,EAAY,IAAI,CAACvH,EAAGjf,IAAM,CACzB,MAAMknB,EAAOH,EAAW9H,EAAE,IAAI,EACxBkI,EAAKJ,EAAW9H,EAAE,EAAE,EAC1B,GAAI,CAACiI,GAAQ,CAACC,EAAI,OAAO,KACzB,MAAMC,EAAKD,EAAG,EAAID,EAAK,EACjBG,EAAKF,EAAG,EAAID,EAAK,EACjBI,EAAQF,GAAM,EAAIF,EAAK,EAAIhB,GAAQ,EAAIgB,EAAK,EAAIhB,GAAQ,EACxDqB,EAAMH,GAAM,EAAID,EAAG,EAAIjB,GAAQ,EAAIiB,EAAG,EAAIjB,GAAQ,EAClDsB,EAAQH,GAAM,EAAIH,EAAK,EAAIf,GAAQ,EAAIe,EAAK,EAAIf,GAAQ,EACxDsB,EAAMJ,GAAM,EAAIF,EAAG,EAAIhB,GAAQ,EAAIgB,EAAG,EAAIhB,GAAQ,EAClDuB,GAAQJ,EAAQC,GAAO,EACvBI,GAAQH,EAAQC,GAAO,EAC7B,cACG,KACC,UAAA7iB,MAAC,QACC,GAAI0iB,EACJ,GAAIE,EACJ,GAAID,EACJ,GAAIE,EACJ,OAAO,kBACP,YAAa,IACb,UAAW,cAAc5a,CAAE,MAE5BoS,EAAE,OACDra,MAAC,QACC,EAAG8iB,EACH,EAAGC,EAAO,EACV,SAAU,GACV,KAAK,kBACL,WAAW,SACX,WAAW,mBAEV,SAAA1I,EAAE,OACL,GApBIjf,CAsBR,CAEJ,CAAC,EAEAumB,EAAM,IAAKxb,GAAM,CAChB,MAAMkc,EAAMN,EAAO,KAAM/mB,GAAMA,EAAE,KAAOmL,EAAE,EAAE,EAC5C,GAAI,CAACkc,EAAK,OAAO,KACjB,MAAM9iB,EAAIiiB,GAAQa,EAAI,KAAOf,GAAQE,IAC/BwB,EAAIvB,GAAQY,EAAI,KAAOd,GAAQE,IAC/BpH,EAAIgH,GAAYlb,EAAE,IAAI,EAC5B,GAAIA,EAAE,OAAS,WAAY,CACzB,MAAM8c,EAAK1jB,EAAI+hB,GAAQ,EACjB4B,EAAKF,EAAIzB,GAAQ,EACjB4B,EAAS,CACb,CAACF,EAAID,CAAC,EACN,CAACzjB,EAAI+hB,GAAO4B,CAAE,EACd,CAACD,EAAID,EAAIzB,EAAK,EACd,CAAChiB,EAAG2jB,CAAE,GAEL,IAAKloB,GAAMA,EAAE,KAAK,GAAG,CAAC,EACtB,KAAK,GAAG,EACX,cACG,KACC,UAAAgF,MAAC,WACC,OAAAmjB,EACA,KAAM9I,EAAE,KACR,OAAQA,EAAE,OACV,YAAa,IAEfra,MAAC,iBAAc,EAAGT,EAAI,EAAG,EAAG2jB,EAAK,GAAI,MAAO5B,GAAQ,GAAI,OAAQ,GAC9D,SAAAphB,OAAC,OACC,MAAO,CACL,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,IAAK,EACL,SAAU,GACV,MAAOma,EAAE,GACT,UAAW,SACX,WAAY,IACZ,UAAW,SACX,OAAQ,QAGV,UAAAra,MAAChJ,GAAA,CAAQ,KAAM,GAAI,EAClBmP,EAAE,QACL,CACF,IAzBMA,EAAE,EA0BV,CAEJ,CACA,MAAMid,EAASjd,EAAE,OAAS,OAC1B,cACG,KACC,UAAAnG,MAAC,QACC,EAAAT,EACA,EAAAyjB,EACA,MAAO1B,GACP,OAAQC,GACR,GAAI,EACJ,KAAMlH,EAAE,KACR,OAAQA,EAAE,OACV,YAAa+I,EAAS,EAAI,EAC1B,gBAAiBA,EAAS,MAAQ,SAEpCpjB,MAAC,iBAAc,EAAGT,EAAI,EAAG,EAAGyjB,EAAI,EAAG,MAAO1B,GAAQ,GAAI,OAAQC,GAAQ,GACpE,SAAArhB,OAAC,OACC,MAAO,CACL,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,IAAK,EACL,SAAU,GACV,MAAOma,EAAE,GACT,UAAW,SACX,WAAY,KACZ,UAAW+I,EAAS,SAAW,SAC/B,OAAQ,QAGT,UAAAA,GAAUpjB,MAACqjB,GAAA,CAAW,KAAM,GAAI,EAChCld,EAAE,QACL,CACF,IA9BMA,EAAE,EA+BV,CAEJ,CAAC,IACH,EAGN,CAEA,SAAS0b,GAAM,CAAE,GAAA5Z,GAAsB,CACrC,OACEjI,MAAC,OACC,GAAAiI,EACA,MAAO,CACL,QAAS,GACT,UAAW,SACX,MAAO,kBACP,SAAU,IAEb,+BAIL,CAIA,SAAS+Z,GAAYL,EAAoC,CACvD,OAAIA,EAAM,SAAW,EAAU,GACxBA,EAAM,IAAI,CAACxb,EAAG/K,KAAO,CAAE,GAAI+K,EAAE,GAAI,IAAK/K,EAAG,IAAK,GAAI,CAC3D,CAEA,MAAM4iB,GAAkC,CACtC,SAAU,GACV,WAAY,IACZ,MAAO,aACT,EAcO,SAASsF,GAAO,CAAE,GAAArb,EAAI,MAAAiE,EAAO,EAAA3M,EAAG,EAAAyjB,EAAG,EAAA1hB,EAAG,EAAAkM,EAAG,KAAA+V,GAAqB,CACnE,OACErjB,OAAC,UACC,GAAA+H,EACA,gBAAeA,EACf,UAAU,eACV,MAAO,CAAE,MAAO3G,EAAG,UAAWkM,CAAA,EAE7B,UAAAtB,GAASlM,MAAC,cAAW,UAAU,qBAAsB,SAAAkM,EAAM,EAC5DhM,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,SAAK,QACL,SAAK,QACL,SAAK,GACR,EACAA,MAAC,OACC,UAAU,oBACV,wBAAyB,CAAE,OAAQujB,CAAA,CAAK,EAC1C,EACF,IAGN,CC//BA,MAAMC,WAA2B5S,GAAM,SAA4D,CAAnG,kCACE6S,GAAA,aAAiC,CAAE,IAAK,OACxC,OAAO,yBAAyB1lB,EAAqC,CACnE,MAAO,CAAE,IAAAA,CAAA,CACX,CACA,kBAAkBA,EAAY2lB,EAA6B,CACzD,GAAI,CACF,KAAK,MAAM,QAAQ,KAAK,MAAM,QAAS,KAAK,MAAM,UAAW3lB,EAAK2lB,CAAI,CACxE,MAAQ,CAER,CACF,CACA,QAA0B,CACxB,OAAI,KAAK,MAAM,IAEXxjB,OAAC,OACC,UAAU,oBACV,KAAK,QACL,MAAO,CACL,OAAQ,kCACR,WAAY,0BACZ,aAAc,EACd,QAAS,YACT,OAAQ,SACR,MAAO,cACP,WAAY,4CACZ,SAAU,GACV,WAAY,MAGd,UAAAA,OAAC,UAAO,MAAO,CAAE,MAAO,wBAAyB,WAAY,0CAA2C,QAAS,QAAS,aAAc,GACrI,eAAK,MAAM,UAAU,kBACxB,EACAA,OAAC,OAAI,MAAO,CAAE,MAAO,oBAAqB,aAAc,GAAK,uBACjDF,MAAC,QAAM,cAAK,MAAM,QAAQ,GACtC,QACC,OAAI,MAAO,CAAE,OAAQ,EAAG,WAAY,WAAY,UAAW,aAAc,MAAO,eAC9E,cAAK,MAAM,IAAI,QAClB,KAIC,KAAK,MAAM,QACpB,CACF,CAYA,SAAS2jB,GAAc9oB,EAAuD,CAC5E,MAAMF,EAAQE,EAAE,MAAQ,GACxB,OAAQA,EAAE,MACR,IAAK,WACH,MAAO,CAAE,GAAI,IACf,IAAK,UACH,MAAO,CAAE,GAAI,IACf,IAAK,YACH,OAAK,MAAM,QAAQF,EAAK,KAAK,EACtB,CAAE,GAAI,IAD0B,CAAE,GAAI,GAAO,MAAO,gDAE7D,IAAK,QACH,OAAK,MAAM,QAAQA,EAAK,OAAO,EAC1B,MAAM,QAAQA,EAAK,IAAI,EACxBA,EAAK,KAAK,OAAS,GAAK,CAAC,MAAM,QAAQA,EAAK,KAAK,CAAC,CAAC,EAAU,CAAE,GAAI,GAAO,MAAO,oDAC9E,CAAE,GAAI,IAFyB,CAAE,GAAI,GAAO,MAAO,2CADjB,CAAE,GAAI,GAAO,MAAO,8CAI/D,IAAK,WACH,OAAK,MAAM,QAAQA,EAAK,IAAI,EACrB,CAAE,GAAI,IADyB,CAAE,GAAI,GAAO,MAAO,8CAE5D,IAAK,WACH,OAAK,MAAM,QAAQA,EAAK,OAAO,EACxB,CAAE,GAAI,IAD4B,CAAE,GAAI,GAAO,MAAO,iDAE/D,IAAK,gBACH,OAAK,MAAM,QAAQA,EAAK,SAAS,EAC1B,CAAE,GAAI,IAD8B,CAAE,GAAI,GAAO,MAAO,wDAEjE,IAAK,WACH,GAAI,CAAC,MAAM,QAAQA,EAAK,OAAO,EAAG,MAAO,CAAE,GAAI,GAAO,MAAO,iDAI7D,UAAWyD,KAAKzD,EAAK,QACnB,GAAIyD,IAAM,MAAQ,OAAOA,GAAM,UAAY,MAAM,QAAQA,CAAC,EACxD,MAAO,CAAE,GAAI,GAAO,MAAO,wCAAwC,KAAK,UAAUA,CAAC,CAAC,IAGxF,MAAO,CAAE,GAAI,IACf,IAAK,OACH,OAAI,OAAOzD,EAAK,QAAW,SAAiB,CAAE,GAAI,GAAO,MAAO,4CAC5D,OAAOA,EAAK,OAAU,SAAiB,CAAE,GAAI,GAAO,MAAO,2CACxD,CAAE,GAAI,IACf,IAAK,OACH,OAAIA,EAAK,QAAU,QAAaA,EAAK,QAAU,KAAa,CAAE,GAAI,GAAO,MAAO,4BAC5EA,EAAK,QAAU,QAAaA,EAAK,QAAU,KAAa,CAAE,GAAI,GAAO,MAAO,4BACzE,CAAE,GAAI,IACf,IAAK,WACH,OAAK,MAAM,QAAQA,EAAK,KAAK,EACtB,CAAE,GAAI,IAD0B,CAAE,GAAI,GAAO,MAAO,+CAE7D,IAAK,SACH,OAAI,OAAOA,EAAK,MAAS,SAAiB,CAAE,GAAI,GAAO,MAAO,4CACvD,CAAE,GAAI,IACf,IAAK,UACH,OAAI,OAAOA,EAAK,UAAa,SAAiB,CAAE,GAAI,GAAO,MAAO,iDAC3D,CAAE,GAAI,IACf,QACE,MAAO,CAAE,GAAI,GAAO,MAAO,uBAAwBE,EAAuB,IAAI,GAAG,CAEvF,CA2CA,MAAM+oB,GAAsC,CAC1C,SAAU,WACV,eAAgB,sBAChB,sBAAuB,sBACvB,UAAW,iBACX,iBAAkB,iBAClB,yBAA0B,iBAC1B,SAAU,WACV,QAAS,SACX,EAOA,SAASC,GAAwBC,EAA4B,CAC3D,MAAMC,EAAsB,GAC5B,IAAInE,EAAmB,CAAE,QAAS,KAAM,OAAQ,EAAC,EAEjD,UAAW/kB,KAAKipB,EAAQ,CACtB,MAAME,EAAUJ,GAAY/oB,EAAE,EAAE,GAAK,KACjCmpB,IAEEpE,EAAQ,OAAO,OAAS,GAAKA,EAAQ,UAAY,OACnDmE,EAAS,KAAKnE,CAAO,EAEvBA,EAAU,CAAE,QAAAoE,EAAS,OAAQ,CAACnpB,CAAC,IAE/B+kB,EAAQ,OAAO,KAAK/kB,CAAC,CAEzB,CACA,OAAI+kB,EAAQ,OAAO,OAAS,GAAKA,EAAQ,UAAY,OACnDmE,EAAS,KAAKnE,CAAO,EAEhBmE,CACT,CAiBO,SAASE,GAAc,CAAE,KAAAhb,EAAM,QAAAlE,EAAS,eAAAmf,GAAyB,eACtE,MAAMjf,EAAQC,GAAA,EACR,CAACif,EAAUC,CAAW,EAAIjoB,WAA+B,IAAI,EAC7D,CAACkoB,EAAUC,CAAW,EAAInoB,WAAuB,EAAE,EACnD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACW,EAAOC,CAAQ,EAAIZ,WAAwB,IAAI,EAEhD,CAACooB,EAAWC,CAAY,EAAIroB,WAAwB,IAAI,EACxD,CAAC2Q,EAAYC,CAAa,EAAI5Q,WAAS,EAAK,EAC5C,CAACsoB,EAAYC,CAAa,EAAIvoB,WAAS,EAAK,EAG5C,CAACwoB,EAASC,CAAU,EAAIzoB,WAA0E,IAAI,EACtG,CAAC0oB,EAAeC,CAAgB,EAAI3oB,WAAoD,IAAI,EAC5F,CAAC4oB,EAAcC,CAAe,EAAI7oB,WAAS,EAAE,EAG7C,CAAC8oB,EAAWC,CAAY,EAAI/oB,WAAwB,IAAI,EAMxD,CAACgpB,EAAaC,CAAc,EAAIjpB,WAEpC,EAAE,EACEkpB,EAAmBzU,GAAM,YAC7B,CAAC0U,EAAiBC,EAAmBxnB,IAAe,CAClDqnB,EAAgBhmB,GAGVA,EAAK,KAAMhB,GAAMA,EAAE,UAAYknB,CAAO,EAAUlmB,EAC7C,CAAC,GAAGA,EAAM,CAAE,QAAAkmB,EAAS,UAAAC,EAAW,QAASxnB,EAAI,SAAW,OAAOA,CAAG,EAAG,CAC7E,CACH,EACA,EAAC,EAGGynB,EAAY/nB,SAAuB,IAAI,EAGvCsmB,EAAWxP,UACf,IAAO4P,EAAWN,GAAwBM,EAAS,MAAM,EAAI,GAC7D,CAACA,CAAQ,GAIXjmB,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,MAAM0f,EAAa,IAEnB,OAAC,SAAY,CACX5oB,EAAW,EAAI,EACfE,EAAS,IAAI,EACb,GAAI,CAIF,MAAM2oB,EAAiB,IAAI,QAAQ,CAACC,GAAGC,KACrC,WAAW,IAAMA,GAAO,IAAI,MAAM,4BAA4B,CAAC,EAAGH,CAAU,GAGxE,CAACI,EAAYC,CAAY,EAAI,MAAM,QAAQ,KAAK,CACpD,QAAQ,IAAI,CACVjoB,EAAI,IAAmB,cAAc,mBAAmBoL,CAAI,CAAC,SAAS,EACtEpL,EAAI,IACF,cAAc,mBAAmBoL,CAAI,CAAC,GACxC,CACD,EACDyc,CAAA,CACD,EAED,GAAI3f,EAAW,OACfqe,EAAYyB,CAAU,EACtB,MAAME,GAAYD,GAAA,YAAAA,EAAsB,WAAY,GACpDxB,EAAY,MAAM,QAAQyB,CAAQ,EAAIA,EAAW,EAAE,CACrD,OAAShoB,EAAK,CACZ,GAAI,CAACgI,EAAW,CACd,MAAM/H,EAAOD,EAAc,QAC3BhB,EAASiB,CAAG,EACZwmB,EAAaxmB,CAAG,CAClB,CACF,SACO+H,GAAWlJ,EAAW,EAAK,CAClC,CACF,KACO,IAAM,CACXkJ,EAAY,EACd,CACF,EAAG,CAACkD,CAAI,CAAC,EAGT,SAAS+c,EAAuB5nB,EAAqB,CACnD,GAAI,CAAConB,EAAU,QAAS,OACxBpnB,EAAE,iBACF,MAAM6nB,EAAOT,EAAU,QAAQ,wBAC/BZ,EAAW,CACT,EAAGxmB,EAAE,QACL,EAAGA,EAAE,QACL,OAAQA,EAAE,QAAU6nB,EAAK,KACzB,OAAQ7nB,EAAE,QAAU6nB,EAAK,IAC1B,CACH,CAEA,eAAeC,GAAgB,CAC7B,GAAI,GAACrB,GAAiB,CAACE,EAAa,QACpC,GAAI,CACF,MAAM9H,EAAU,MAAMpf,EAAI,KACxB,cAAc,mBAAmBoL,CAAI,CAAC,YACtC,CACE,EAAG4b,EAAc,OACjB,EAAGA,EAAc,OACjB,KAAME,EAAa,OACnB,OAAQ,SACV,EAEFT,EAAallB,GAAS,CACpB,GAAGA,EACH,CACE,GAAI6d,EAAQ,IAAM,OAAO,KAAK,KAAK,GACnC,EAAG4H,EAAc,OACjB,EAAGA,EAAc,OACjB,KAAME,EAAa,OACnB,OAAQ,SACR,QAAS,IAAI,OAAO,aAAY,CAClC,CACD,EACDD,EAAiB,IAAI,EACrBE,EAAgB,EAAE,EAClBJ,EAAW,IAAI,EACfV,GAAA,MAAAA,IACAjf,EAAM,QAAQ,eAAe,CAC/B,OAASlH,EAAK,CACZkH,EAAM,MAAM,0BAA2BlH,EAAc,OAAO,EAAE,CAChE,CACF,CAKA,eAAeooB,GAAiB,CAC9B,GAAI,CAAArZ,EACJ,CAAAC,EAAc,EAAI,EAClB,GAAI,CACF,MAAM7R,EAAS,MAAM2C,EAAI,KACvB,cAAc,mBAAmBoL,CAAI,CAAC,UACtC,CAAE,QAAS,GAAI,UAAW,SAAS,EAEjC/N,GAAA,MAAAA,EAAQ,IACV+J,EAAM,QAAQ,oDAAoD,EAClEif,GAAA,MAAAA,KAEAjf,EAAM,MAAM,8CAA8C,CAE9D,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,SACEgP,EAAc,EAAK,CACrB,EACF,CAEA,SAASqZ,GAAmB,CAC1B1B,EAAe1lB,GAAM,CAACA,CAAC,CACzB,CAKA,MAAMqnB,GAAexrB,GAAa,CAChC,MAAMoN,EAAKpN,EAAE,GACPF,EAAQE,EAAE,MAAQ,GAIlByrB,EAAa3C,GAAc9oB,CAAC,EAClC,OAAKyrB,EAAW,GAiCdtmB,MAACwjB,GAAA,CAA4B,QAASvb,EAAI,UAAWpN,EAAE,KAAM,QAASwqB,EACnE,SAAAkB,GAAiB1rB,EAAGoN,EAAItN,CAAI,GADNsN,CAEzB,EAjCE/H,OAAC,OAEC,GAAA+H,EACA,UAAU,oBACV,KAAK,QACL,MAAO,CACL,OAAQ,kCACR,WAAY,0BACZ,aAAc,EACd,QAAS,YACT,OAAQ,SACR,MAAO,cACP,WAAY,4CACZ,SAAU,GACV,WAAY,MAGd,UAAA/H,OAAC,UAAO,MAAO,CAAE,MAAO,wBAAyB,WAAY,0CAA2C,QAAS,QAAS,aAAc,GACrI,UAAArF,EAAE,KAAK,kBACV,EACAqF,OAAC,OAAI,MAAO,CAAE,MAAO,oBAAqB,aAAc,GAAK,uBACjDF,MAAC,QAAM,SAAAiI,CAAA,CAAG,GACtB,EACAjI,MAAC,OAAI,MAAO,CAAE,OAAQ,EAAG,WAAY,WAAY,UAAW,cAAiB,SAAAsmB,EAAW,MAAM,IAtBzFre,CAAA,CAkCb,EAIMse,GAAmB,CAAC1rB,EAAUoN,EAAYtN,IAAkC,CAChF,OAAQE,EAAE,MACR,IAAK,WACH,aAAQkjB,GAAA,CAAkB,GAAA9V,EAAS,SAAApN,EAAE,kBAAoB,IAAnCoN,CAAsC,EAC9D,IAAK,UACH,OACEjI,MAACqe,GAAA,CAAiB,GAAApW,EAAQ,KAAOtN,EAAK,MAA+D,OAClG,SAAAE,EAAE,kBAAoB,IADXoN,CAEd,EAEJ,IAAK,YACH,OACEjI,MAACue,IAAmB,GAAAtW,EAAQ,MAAQtN,EAAK,OAAiB,IAA1CsN,CAA8C,EAElE,IAAK,QACH,OACEjI,MAACwe,GAAA,CAAe,GAAAvW,EAAQ,QAAUtN,EAAK,SAAwB,GAAI,KAAOA,EAAK,MAAuB,IAA1FsN,CAA8F,EAE9G,IAAK,WACH,OACEjI,MAAC8e,IAAkB,GAAA7W,EAAQ,KAAOtN,EAAK,MAAgB,IAAxCsN,CAA4C,EAE/D,IAAK,WACH,OACEjI,MAACgf,GAAA,CAEC,GAAA/W,EACA,MAAOtN,EAAK,MACZ,SAAUA,EAAK,SACf,QAAUA,EAAK,SAAmB,EAAC,EAJ9BsN,CAAA,EAOX,IAAK,gBACH,OACEjI,MAACqf,GAAA,CAEC,GAAApX,EACA,UAAYtN,EAAK,WAAqB,EAAC,EAFlCsN,CAAA,EAKX,IAAK,WACH,OACEjI,MAACggB,GAAA,CAEC,GAAA/X,EACA,MAAOtN,EAAK,MACZ,QAAUA,EAAK,SAAmB,EAAC,EAH9BsN,CAAA,EAMX,IAAK,OACH,OACEjI,MAACigB,GAAA,CAEC,GAAAhY,EACA,SAAUtN,EAAK,SACf,SAAUA,EAAK,SACf,KAAOA,EAAK,MAA4C,UACxD,OAASA,EAAK,QAAqB,GACnC,MAAQA,EAAK,OAAoB,IAN5BsN,CAAA,EASX,IAAK,OACH,OACEjI,MAACihB,GAAA,CAEC,GAAAhZ,EACA,MAAQtN,EAAK,OAAoB,GACjC,MAAOA,EAAK,MACZ,MAAOA,EAAK,MACZ,KAAMA,EAAK,MALNsN,CAAA,EAQX,IAAK,WACH,OACEjI,MAAC0hB,GAAA,CAEC,GAAAzZ,EACA,MAAQtN,EAAK,OAAiB,GAC9B,YAAaA,EAAK,aAHbsN,CAAA,EAMX,IAAK,SACH,OACEjI,MAACsjB,GAAA,CAEC,GAAArb,EACA,MAAOtN,EAAK,MACZ,EAAGA,EAAK,EACR,EAAGA,EAAK,EACR,EAAGA,EAAK,EACR,EAAGA,EAAK,EACR,KAAOA,EAAK,MAAmB,IAP1BsN,CAAA,EAUX,IAAK,UACH,aACG,OAAa,GAAAA,EAAQ,UAAU,0BAC9B,gBAAC,MAAG,uBAAWA,CAAA,EAAG,GADVA,CAEV,EAGR,EAEA,GAAIrL,EACF,OACEoD,MAAC,OAAI,UAAU,yCACZ,WACCE,OAAAO,WAAA,CACE,UAAAT,MAAC,UAAO,iCAAqB,EAC7BA,MAAC,OAAK,SAAAukB,CAAA,CAAU,GAClB,EAEArkB,OAAAO,WAAA,CACE,UAAAT,MAACuO,GAAA,EAAQ,EAAE,mBACb,EAEJ,EAIJ,GAAIzR,GAAS,CAACqnB,EACZ,OACEjkB,OAAC,OAAI,UAAU,uCACb,UAAAF,MAAC,UAAO,iCAAqB,EAC7BA,MAAC,OAAK,SAAAlD,GAAS,gBAAgB,GACjC,EAIJ,MAAMoP,IAASjO,EAAAkmB,EAAS,cAAT,YAAAlmB,EAAsB,QAAoBgL,EACnDuC,IAAUlH,GAAA6f,EAAS,cAAT,YAAA7f,GAAsB,SAAqB,QACrDkiB,GAAenC,EAAS,OAE9B,OACEnkB,OAAC,OACC,UAAW,gBAAgBukB,EAAa,2BAA6B,EAAE,GACvE,IAAKe,EACL,cAAeQ,EAGf,UAAA9lB,OAAC,OAAI,UAAU,yBACb,UAAAA,OAAC,UACC,UAAU,+CACV,QAASimB,EACT,SAAUrZ,EACV,MAAM,oFAEN,UAAA9M,MAACyO,GAAA,CAAK,KAAM,GAAI,EAChBzO,MAAC,QAAK,yBAAa,EACnBA,MAAC,QAAK,UAAU,kBAAmB,SAAAwmB,EAAA,CAAa,KAGlDxmB,MAAC,QAAK,UAAU,wBAAwB,EAExCA,MAAC,UACC,UAAU,iBACV,MAAM,QACN,QAAS,IAAM,CACT,OAAO,OAAW,KAAe,UAAU,YAC7C,UAAU,UAAU,UAAU,OAAO,SAAS,IAAI,EAAE,MAAM,IAAM,CAAC,CAAC,EAClEiF,EAAM,QAAQ,aAAa,EAE/B,EAEA,SAAAjF,MAACvG,GAAA,CAAO,KAAM,GAAI,IAEpBuG,MAAC,UAAO,UAAU,iBAAiB,MAAM,OAAO,SAAQ,GACtD,SAAAA,MAAChG,GAAA,CAAM,KAAM,GAAI,EACnB,EACAgG,MAAC,UAAO,UAAU,iBAAiB,MAAM,OAAO,SAAQ,GACtD,SAAAA,MAACxG,GAAA,CAAM,KAAM,GAAI,EACnB,EACAwG,MAAC,UACC,UAAU,iBACV,MAAOykB,EAAa,kBAAoB,aACxC,QAAS2B,EAET,SAAApmB,MAACrH,GAAA,CAAU,KAAM,GAAI,IAEvBqH,MAAC,UAAO,UAAU,iBAAiB,MAAM,OACvC,SAAAA,MAACymB,GAAA,CAAe,KAAM,GAAI,EAC5B,EACAzmB,MAAC,QAAK,UAAU,wBAAwB,EACxCE,OAAC,UACC,UAAU,iBACV,MAAM,gBACN,aAAW,gBAEX,UAAAF,MAACwB,GAAA,CAAc,KAAM,GAAI,EACzBxB,MAAC,QAAK,UAAU,uBAAwB,SAAAwmB,EAAA,CAAa,KAEtDzhB,GACC/E,MAAC,UACC,UAAU,uCACV,MAAM,QACN,QAAS+E,EACT,aAAW,QAEX,SAAA/E,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EAEJ,EAGArG,OAAC,OAAI,UAAU,uBAEb,UAAAA,OAAC,UAAO,UAAU,qBAChB,UAAAF,MAAC,MAAG,UAAU,cAAe,SAAAkM,EAAM,EACnChM,OAAC,OAAI,UAAU,aACb,UAAAF,MAAC,QAAK,UAAW,8BAA8BwL,CAAM,GAAK,SAAAA,EAAO,EACjExL,MAAC,QAAK,UAAU,aAAc,SAAAiJ,CAAA,CAAK,GACrC,GACF,GASEkc,EAAY,OAAS,KAAKxW,GAAAwV,EAAS,SAAT,YAAAxV,GAAiB,QAAS,IACpDzO,OAAC,OACC,UAAU,sBACV,KAAK,QACL,MAAO,CACL,OAAQ,kCACR,WAAY,0BACZ,aAAc,EACd,QAAS,YACT,OAAQ,aACR,MAAO,eAGT,UAAAF,MAAC,UAAO,MAAO,CAAE,MAAO,wBAAyB,QAAS,QAAS,aAAc,GAC9E,SAAAmlB,EAAY,OAAS,EAClB,GAAGA,EAAY,MAAM,SAASA,EAAY,SAAW,EAAI,GAAK,GAAG,oBACjE,oBACN,EACAjlB,OAAC,MAAG,MAAO,CAAE,OAAQ,EAAG,YAAa,GAAI,WAAY,4CAA6C,SAAU,GAAI,WAAY,KACzH,UAAAilB,EAAY,IAAI,CAAC/mB,EAAGhD,WAClB,MACC,UAAA4E,MAAC,UAAQ,WAAE,UAAU,EAAS,KAAEA,MAAC,QAAM,SAAA5B,EAAE,QAAQ,EAAO,MAAIA,EAAE,UADvD,MAAMhD,CAAC,EAEhB,CACD,GACAsrB,EAAAvC,EAAS,SAAT,YAAAuC,EAAiB,IAAI,CAACtoB,EAAGhD,WACvB,MACE,UAAAgD,EAAE,KAAO,QAAQA,EAAE,IAAI,KAAO,GAAIA,EAAE,UAD9B,MAAMhD,CAAC,EAEhB,EACD,EACH,KAKJ4E,MAAC,OAAI,UAAU,iBACZ,WAAS,IAAI,CAAC2mB,EAASvrB,IACtB8E,OAAC,WAEC,UAAW,iBAAiBymB,EAAQ,QAAU,wBAA0B,sBAAsB,GAE7F,UAAAA,EAAQ,SACP3mB,MAAC,MAAG,UAAU,wBAAyB,WAAQ,QAAQ,EAEzDA,MAAC,OAAI,UAAU,uBACZ,WAAQ,OAAO,IAAIqmB,EAAW,EACjC,IARK,OAAOjrB,CAAC,IAAIurB,EAAQ,SAAW,WAAW,GAUlD,EACH,GACF,EAGCtC,EAAS,IAAKhK,GACbna,OAAC,UAEC,UAAW,aAAa+kB,IAAc5K,EAAE,GAAK,oBAAsB,EAAE,GACrE,MAAO,CAAE,KAAMA,EAAE,EAAG,IAAKA,EAAE,GAC3B,QAAUjc,GAAM,CACdA,EAAE,kBACF8mB,EAAaD,IAAc5K,EAAE,GAAK,KAAOA,EAAE,EAAE,CAC/C,EACA,MAAOA,EAAE,KAET,UAAAra,MAACvH,GAAA,CAAO,KAAM,GAAI,EACjBwsB,IAAc5K,EAAE,IACfna,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,OAAI,UAAU,iBAAkB,SAAAqa,EAAE,KAAK,EACxCna,OAAC,OAAI,UAAU,iBACZ,UAAAma,EAAE,QAAU,YAAY,MAAIA,EAAE,QAAU,IAAI,KAAKA,EAAE,OAAO,EAAE,iBAAmB,IAClF,GACF,IAhBGA,EAAE,GAmBV,EAGAsK,GACC3kB,MAAC,OACC,UAAU,iBACV,MAAO,CAAE,KAAM2kB,EAAQ,EAAG,IAAKA,EAAQ,GACvC,QAAUvmB,GAAMA,EAAE,kBAElB,SAAA8B,OAAC,UACC,UAAU,iBACV,QAAS,IAAM,CACb4kB,EAAiB,CAAE,OAAQH,EAAQ,OAAQ,OAAQA,EAAQ,OAAQ,EACnEC,EAAW,IAAI,CACjB,EAEA,UAAA5kB,MAACvH,GAAA,CAAO,KAAM,GAAI,EAAE,sBACtB,GAKHosB,GACC7kB,MAAC,OAAI,UAAU,sBAAsB,QAAS,IAAM8kB,EAAiB,IAAI,EACvE,SAAA5kB,OAAC,OAAI,UAAU,cAAc,QAAU9B,GAAMA,EAAE,kBAC7C,UAAA8B,OAAC,MAAG,6BAAiB,KAAK,MAAM2kB,EAAc,MAAM,EAAE,KAAG,KAAK,MAAMA,EAAc,MAAM,EAAE,KAAC,EAC3F7kB,MAAC,YACC,UAAS,GACT,MAAO+kB,EACP,SAAW3mB,GAAM4mB,EAAgB5mB,EAAE,OAAO,KAAK,EAC/C,YAAY,8CACZ,KAAM,EACN,UAAU,yBAEZ8B,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,UAAO,UAAU,6BAA6B,QAAS,IAAM8kB,EAAiB,IAAI,EAAG,kBAEtF,EACA9kB,MAAC,UAAO,UAAU,+BAA+B,QAASkmB,EAAe,SAAU,CAACnB,EAAa,OAAQ,uBAEzG,GACF,GACF,EACF,IAIR,CAGA,SAASxW,IAAU,CACjB,aAAQ,QAAK,UAAU,gBAAgB,aAAW,UAAU,aAAC,CAC/D,CCjwBA,SAASqY,GAAepb,EAAiF,CACvG,OAAQA,EAAA,CACN,IAAK,WACL,IAAK,OACH,MAAO,UACT,IAAK,cACL,IAAK,QACH,MAAO,OACT,IAAK,WACH,MAAO,QACT,IAAK,WACH,MAAO,UACT,IAAK,QACL,QACE,MAAO,UAEb,CAcO,SAASqb,GAAU,CAAE,SAAAxa,EAAU,gBAAAC,GAA0B,CAC9D,MAAMrH,EAAQC,GAAA,EACR,CAAC4hB,EAAWC,CAAQ,EAAI5qB,WAAqBkQ,EAAS,WAAa,EAAE,EACrE,CAACzP,EAASC,CAAU,EAAIV,WAAS,CAACkQ,EAAS,SAAS,EACpD,CAAC2a,EAAYC,CAAa,EAAI9qB,WAAwB,IAAI,EAC1D,CAAC+qB,EAAQC,CAAS,EAAIhrB,WAAS,EAAE,EACjC,CAACirB,EAAcC,CAAe,EAAIlrB,WAAS,EAAK,EAEtD+B,YAAU,IAAM,CACVmO,EAAS,YACX0a,EAAS1a,EAAS,SAAS,EAC3BxP,EAAW,EAAK,EAEpB,EAAG,CAACwP,EAAS,SAAS,CAAC,EAEvB,MAAM5E,EAAS,SAAY,CACzB,GAAI,CACF,MAAM+L,EAAI,MAAM3V,EAAI,IAA+B,YAAY,EAC/DkpB,EAASvT,EAAE,WAAa,EAAE,EAC1B3W,EAAW,EAAK,CAClB,OAASkB,EAAK,CACZkH,EAAM,MAAM,0BAA2BlH,EAAc,OAAO,EAAE,EAC9DlB,EAAW,EAAK,CAClB,CACF,EAEMyqB,EAAW/S,UAAQ,IAAM,CAC7B,IAAI0H,EAAM6K,EACV,GAAII,EAAQ,CACV,MAAM/hB,EAAI+hB,EAAO,cACjBjL,EAAMA,EAAI,OACPjhB,IACEA,EAAE,MAAQ,IAAI,cAAc,SAASmK,CAAC,IACtCnK,EAAE,OAAS,IAAI,cAAc,SAASmK,CAAC,EAE9C,CACA,OAAKiiB,IACHnL,EAAMA,EAAI,OAAQjhB,GAAMA,EAAE,SAAW,UAAU,GAE1CihB,CACT,EAAG,CAAC6K,EAAWI,EAAQE,CAAY,CAAC,EAE9BhL,EAAW,MAAOnT,EAAciD,IAAmB,CACvD,GAAI,CACF,MAAMqb,EAAW,MAAM1pB,EAAI,KAAuB,aAAc,CAAE,KAAAoL,EAAM,MAAAiD,EAAO,EAC/EjH,EAAM,QAAQ,aAAasiB,EAAS,IAAI,YAAY,EACpDN,EAAcM,EAAS,IAAI,EAC3B,MAAM9f,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEMuZ,EAAW,MAAOrO,GAAiB,CACvC,GAAK,QAAQ,oBAAoBA,CAAI,4CAA4C,EACjF,GAAI,CACF,MAAMpL,EAAI,IAAI,cAAc,mBAAmBoL,CAAI,CAAC,EAAE,EACtDhE,EAAM,QAAQ,mBAAmB,EAC7B+hB,IAAe/d,GAAMge,EAAc,IAAI,EAC3C,MAAMxf,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEA,OAAIipB,EAKA9mB,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC,OAAI,UAAU,yBACb,SAAAE,OAAC2D,GAAO,QAAQ,QAAQ,QAAS,IAAM,CAAEojB,EAAc,IAAI,EAAGxf,EAAA,CAAU,EACtE,UAAAzH,MAAC/J,GAAA,CAAU,KAAM,GAAI,EAAE,sBACzB,EACF,EACA+J,MAACikB,GAAA,CACC,KAAM+C,EACN,QAAS,IAAM,CAAEC,EAAc,IAAI,EAAGxf,EAAA,CAAU,EAChD,eAAgB,IAAMA,EAAA,CAAO,EAC/B,EACF,EAKFvH,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAACwnB,GAAA,CAAQ,KAAM,GAAI,EAAE,YAAUV,EAAU,OAAO,KAClD,EACA9mB,MAAC,KAAE,UAAU,gBAAgB,+EAE7B,GACF,EACAE,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,eACb,UAAAF,MAACsG,GAAA,CAAO,KAAM,GAAI,EAClBtG,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,UACZ,MAAOknB,EACP,SAAW9oB,GAAM+oB,EAAU/oB,EAAE,OAAO,KAAK,GAC3C,EACF,EACA8B,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAS,IAAMwjB,EAAiBroB,GAAM,CAACA,CAAC,EACxC,MAAOooB,EAAe,gBAAkB,gBAEvC,UAAAA,EAAepnB,MAAClK,IAAe,KAAM,GAAI,EAAKkK,MAACynB,GAAA,CAAQ,KAAM,GAAI,EACjEL,EAAe,gBAAkB,0BAEnCvjB,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS4D,EAC7C,UAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,GACF,GACF,EAEAH,MAAC0nB,IAAY,SAAAtL,EAAoB,EAEhCxf,EACCoD,MAAC,OAAI,UAAU,eACb,SAAAA,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACrB,EACE+Y,EAAS,SAAW,EACtBtnB,MAACgM,GAAA,CACC,KAAMhM,MAACwnB,GAAA,CAAQ,KAAM,GAAI,EACzB,MAAOJ,EAAe,eAAiB,mBACvC,QACEA,EACI,0DACA,2CAIP,OAAI,UAAU,iBACZ,SAAAE,EAAS,IAAKtsB,GACbgF,MAAC2nB,GAAA,CAEC,SAAU3sB,EACV,OAAQ,IAAMisB,EAAcjsB,EAAE,IAAI,EAClC,SAAU,IAAMsc,EAAStc,EAAE,IAAI,GAH1BA,EAAE,KAKV,EACH,GAEJ,CAEJ,CAEA,SAAS0sB,GAAY,CAAE,SAAAtL,GAAkE,CACvF,KAAM,CAACnT,EAAMC,CAAO,EAAI/M,WAAS,EAAE,EAC7B,CAAC+P,EAAO0b,CAAQ,EAAIzrB,WAAS,EAAE,EACrC,OACE+D,OAAC0K,EAAA,CAAK,UAAU,eACd,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,iBACpB,EACA9D,MAACmL,IAAS,oEAAwD,EAClEjL,OAAC,QACC,UAAU,oBACV,SAAW9B,GAAM,CACfA,EAAE,iBACG6K,EAAK,SACVmT,EAASnT,EAAK,OAAQiD,EAAM,QAAU,MAAS,EAC/ChD,EAAQ,EAAE,EACV0e,EAAS,EAAE,EACb,EAEA,UAAA5nB,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,6BACZ,QAAQ,0BACR,SAAQ,GACR,MAAOiJ,EACP,SAAW7K,GAAM8K,EAAQ9K,EAAE,OAAO,KAAK,IAEzC4B,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,mBACZ,MAAOkM,EACP,SAAW9N,GAAMwpB,EAASxpB,EAAE,OAAO,KAAK,UAEzCyF,EAAA,CAAO,QAAQ,UAAU,KAAK,SAAS,kBAExC,IACF,EACF,CAEJ,CAEA,SAAS8jB,GAAS,CAChB,SAAAJ,EACA,OAAAxY,EACA,SAAAuI,CACF,EAIG,CACD,MAAMjI,EAAOuX,GAAeW,EAAS,QAAU,OAAO,EACtD,OACErnB,OAAC0K,EAAA,CACC,QAAQ,WACR,YAAW,GACX,UAAU,gBACV,QAASmE,EAET,UAAA7O,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC,OAAI,UAAU,sBAAuB,SAAAunB,EAAS,OAASA,EAAS,KAAK,EACtEvnB,MAACgb,GAAA,CAAY,KAAA3L,EAAa,SAAAkY,EAAS,QAAU,QAAQ,GACvD,EACArnB,OAAC,OAAI,UAAU,0BAA2B,UAAAqnB,EAAS,KAAK,MAAIA,EAAS,QAAO,EAC5ErnB,OAAC,OAAI,UAAU,qBACZ,UAAAqnB,EAAS,cAAgB,MAAQrnB,OAAC,QAAM,UAAAqnB,EAAS,aAAa,aAAS,EACvEA,EAAS,cAAgB,MAAQrnB,OAAC,QAAK,gBAAIqnB,EAAS,aAAa,aAAS,SAC1E,QAAK,uBAAWhf,GAAegf,EAAS,KAAK,GAAE,GAClD,EACArnB,OAAC,OAAI,UAAU,wBACb,UAAAA,OAAC2D,GAAO,QAAQ,UAAU,KAAK,KAAK,QAAUzF,GAAM,CAAEA,EAAE,kBAAmB2Q,EAAA,CAAU,EAAG,iBAEtF/O,MAACqB,GAAA,CAAa,KAAM,GAAI,GAC1B,EACAnB,OAAC2D,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAAUzF,GAAM,CAAEA,EAAE,kBAAmBkZ,EAAA,CAAY,EACnF,UAAAtX,MAACiP,GAAA,CAAO,KAAM,GAAI,EAAE,WACtB,GACF,IAGN,CCxUO,SAASnV,GAAI,CAAE,SAAAkR,EAAU,UAAAD,EAAW,SAAA7C,GAAsB,CAC/D,cACG,QAAK,UAAWjF,EAAG,MAAO8H,CAAS,EACjC,UAAAC,EACA9C,GACClI,MAAC,UACC,KAAK,SACL,UAAU,aACV,aAAY,UAAU,OAAOgL,GAAa,SAAWA,EAAW,KAAK,GACrE,QAAS9C,EACV,cAED,EAEJ,CAEJ,CCFA,SAAS2f,GAAY,CAAE,KAAAC,EAAM,OAAA5Q,EAAQ,UAAA6Q,EAAW,SAAAzQ,EAAU,OAAApG,EAAQ,UAAA7N,GAA+B,OAC/F,MAAM4B,EAAQC,GAAA,EAER8iB,EAAgB,SAAY,CAChC,GAAI,CACF,MAAMnqB,EAAI,KAAK,UAAU,mBAAmBiqB,EAAK,EAAE,CAAC,UAAU,EAC9D7iB,EAAM,QAAQ,sBAAuB,IAAI,EACzC8iB,EAAUD,EAAK,EAAE,CACnB,OAAS/pB,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAEM+b,EAAe,SAAY,CAC/B,GAAK,QAAQ,mBAAmB,EAChC,GAAI,CACF,MAAMjc,EAAI,IAAI,UAAU,mBAAmBiqB,EAAK,EAAE,CAAC,EAAE,EACrD7iB,EAAM,QAAQ,WAAY,IAAI,EAC9BqS,EAASwQ,EAAK,EAAE,CAClB,OAAS/pB,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEMkqB,EAAsC,CAC1C,KAAM,iBACN,OAAQ,cACR,IAAK,gBAGP,cACG,OAAI,UAAU,eAAe,eAAcH,EAAK,GAC/C,UAAA5nB,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QACC,UAAU,eACV,MAAO,CAAE,WAAYioB,EAAYH,EAAK,QAAQ,GAAK,cAAc,GAEnE9nB,MAAC,QAAK,UAAU,qBAAsB,WAAK,MAAM,EAChD8nB,EAAK,UACJ5nB,OAAC,QAAK,UAAU,qBAAqB,cAAE4nB,EAAK,UAAS,IAEtD7pB,EAAA6pB,EAAK,OAAL,YAAA7pB,EAAW,QAAS,GACnB+B,MAAC,QAAK,UAAU,qBAAsB,SAAA8nB,EAAK,KAAK,KAAK,IAAI,EAAE,GAE/D,EACCA,EAAK,aACJ9nB,MAAC,OAAI,UAAU,oBAAqB,SAAA8nB,EAAK,YAAY,MAAM,EAAG,GAAG,EAAE,EAErE5nB,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,QAAK,UAAU,6BACb,SAAAuI,GAAeuf,EAAK,SAAS,EAChC,EACA5nB,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC,UACC,KAAK,SACL,UAAU,WACV,MAAM,oBACN,QAASgoB,EAET,SAAAhoB,MAAC9J,GAAA,CAAQ,KAAM,GAAI,IAErB8J,MAAC,UACC,KAAK,SACL,UAAU,WACV,MAAM,OACN,QAAS,IAAMkR,EAAO4W,CAAI,EAE1B,SAAA9nB,MAAC4B,GAAA,CAAS,KAAM,GAAI,IAEtB5B,MAAC,UACC,KAAK,SACL,UAAU,2BACV,MAAM,SACN,QAAS8Z,EAET,SAAA9Z,MAACiP,GAAA,CAAO,KAAM,GAAI,GACpB,EACF,GACF,GACF,CAEJ,CASO,SAASiZ,GAAa,CAAE,OAAAhR,EAAQ,UAAA7T,GAAoB,CACzD,MAAM4B,EAAQC,GAAA,EACR,CAACijB,EAAOC,CAAQ,EAAIjsB,WAAiB,EAAE,EACvC,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAK,EAEtC2B,EAAO,SAAY,CACvB,GAAI,CACFjB,EAAW,EAAI,EACf,MAAM6C,EAAI,MAAM7B,EAAI,IAAuB,gBAAgB,EAC3DuqB,EAAS,MAAM,QAAQ1oB,EAAE,KAAK,EAAIA,EAAE,MAAQ,EAAE,CAChD,OAAS3B,EAAK,CACZkH,EAAM,MAAM,wBAAyBlH,EAAc,OAAO,EAAE,CAC9D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CAAEJ,EAAA,CAAQ,EAAG,EAAE,EAE/B,MAAMkqB,EAAgB,MAAO/f,GAAe,CAC1CmgB,EAAUzgB,GAAQA,EAAI,OAAQjD,GAAMA,EAAE,KAAOuD,CAAE,CAAC,EAChD,MAAM5E,EAAA,CACR,EAEMyW,EAAe,MAAO7R,GAAe,CACzCmgB,EAAUzgB,GAAQA,EAAI,OAAQjD,GAAMA,EAAE,KAAOuD,CAAE,CAAC,EAChD,MAAM5E,EAAA,CACR,EAEMglB,EAAcC,GAAgB,CAIpC,EAEMC,EAAmB,SAAY,OACnC,GAAIJ,EAAM,SAAW,EACrB,GAAI,CAIF,MAAMlO,IAAKhc,GAHD,MAAMJ,EAAI,KAAkD,uBAAwB,CAC5F,IAAKsqB,EAAM,IAAKzjB,GAAMA,EAAE,EAAE,EAC3B,GACY,WAAF,YAAAzG,EAAY,OAAQrD,GAAMA,EAAE,IAAI,SAAU,EACrDqK,EAAM,QAAQ,YAAYgV,CAAE,YAAa,GAAI,EAC7CmO,EAAS,EAAE,EACX,MAAM/kB,EAAA,CACR,OAAStF,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,CACF,EAEA,OACEmC,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC,QAAK,UAAU,sBACd,UAAAF,MAAC7H,GAAA,CAAM,KAAM,GAAI,EAAE,YACTgwB,EAAM,OAAO,KACzB,EACAjoB,OAAC,OAAI,UAAU,+BACZ,UAAAioB,EAAM,OAAS,GACdjoB,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS0kB,EAAkB,MAAM,wBACjE,UAAAvoB,MAAC9J,GAAA,CAAQ,KAAM,GAAI,EAAE,gBACvB,EAEF8J,MAAC6D,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS/F,EAAM,MAAM,kBAAkB,aAAW,kBAClF,SAAAkC,MAACG,IAAU,KAAM,GAAI,UAAWvD,EAAU,eAAiB,GAAI,EACjE,GACF,GACF,EAECA,EACCoD,MAAC,OAAI,UAAU,gBAAgB,oBAAQ,EACrCmoB,EAAM,SAAW,EACnBjoB,OAAC,OAAI,UAAU,gBACb,UAAAF,MAAC7H,GAAA,CAAM,KAAM,GAAI,EACjB6H,MAAC,QAAK,6BAAiB,GACzB,QAEC,OAAI,UAAU,eACZ,SAAAmoB,EAAM,IAAKzjB,GACV1E,MAAC6nB,GAAA,CAEC,KAAMnjB,EACN,OAAAwS,EACA,UAAW8Q,EACX,SAAUlO,EACV,OAAQuO,EACR,UAAAhlB,CAAA,EANKqB,EAAE,GAQV,EACH,GAEJ,CAEJ,CC5IA,MAAM8jB,GAAqE,CACzE,CAAE,GAAI,SAAW,MAAO,OAAe,KAAM,QAC7C,CAAE,GAAI,QAAW,MAAO,cAAe,KAAM,UAC7C,CAAE,GAAI,OAAW,MAAO,OAAe,KAAM,WAC7C,CAAE,GAAI,UAAW,MAAO,SAAe,KAAM,QAC/C,EAEMC,GAAa,CAAC,MAAO,SAAU,MAAM,EAG3C,SAASC,GAAW,CAAE,SAAArc,EAAU,gBAAAC,EAAiB,aAAAjB,GAAuB,CACtE,MAAMpG,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACR,CAAC0kB,EAAOC,CAAQ,EAAIjsB,WAAiBkQ,EAAS,OAAS,EAAE,EACzD,CAACzP,EAASC,CAAU,EAAIV,WAAS,CAACkQ,EAAS,KAAK,EAChD,CAAC6a,EAAQC,CAAS,EAAIhrB,WAAS,EAAE,EACjC,CAACwsB,EAAgBC,CAAiB,EAAIzsB,WAAiB,EAAE,EACzD,CAAC0sB,EAAaC,CAAc,EAAI3sB,WAAS,EAAK,EAC9C,CAAC4sB,EAAMC,CAAO,EAAI7sB,WAAS,CAAC,EAE5BsL,EAAS,SAAY,CACzB,GAAI,CACF,MAAM9M,EAAO,MAAMkD,EAAI,IAAY,QAAQ,EAC3CuqB,EAAS,MAAM,QAAQztB,CAAI,EAAIA,EAAO,EAAE,CAC1C,OAASoD,EAAK,CACZkH,EAAM,MAAM,sBAAuBlH,EAAc,OAAO,EAAE,CAC5D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACVmO,EAAS,QACX+b,EAAS/b,EAAS,KAAK,EACvBxP,EAAW,EAAK,EAEpB,EAAG,CAACwP,EAAS,KAAK,CAAC,EAGnBnO,YAAU,IAAM,CACd,MAAM+J,EAAK,YAAY,IAAM+gB,EAAStkB,GAAMA,EAAI,CAAC,EAAG,GAAM,EAC1D,MAAO,IAAM,cAAcuD,CAAE,CAC/B,EAAG,EAAE,EAEL,MAAMqf,EAAW/S,UAAQ,IAAM,CAC7B,IAAI0H,EAAMkM,EAAM,OAAQzjB,GAAMA,EAAE,SAAW,SAAS,EAIpD,GAHIikB,IACF1M,EAAMA,EAAI,OAAQvX,IAAOA,EAAE,UAAY,YAAcikB,CAAc,GAEjEzB,EAAO,OAAQ,CACjB,MAAM/hB,EAAI+hB,EAAO,cACjBjL,EAAMA,EAAI,OAAQvX,IACfA,EAAE,OAAS,IAAI,cAAc,SAASS,CAAC,IACvCT,EAAE,aAAe,IAAI,cAAc,SAASS,CAAC,EAElD,CACA,OAAO8W,CACT,EAAG,CAACkM,EAAOjB,EAAQyB,CAAc,CAAC,EAE5BnU,EAASD,UAAQ,IAAM,CAC3B,MAAM0U,EAAiB,CAAE,KAAM,EAAG,OAAQ,EAAG,IAAK,GAClD,MAAO,CAAC,GAAG3B,CAAQ,EAAE,KAAK,CAAC1sB,EAAGC,IAAM,CAClC,MAAMquB,EAAKD,EAAeruB,EAAE,QAAQ,GAAK,EACnCuuB,EAAKF,EAAepuB,EAAE,QAAQ,GAAK,EACzC,OAAIquB,IAAOC,EAAWD,EAAKC,EACpB,IAAI,KAAKtuB,EAAE,SAAS,EAAE,UAAY,IAAI,KAAKD,EAAE,SAAS,EAAE,SACjE,CAAC,CACH,EAAG,CAAC0sB,CAAQ,CAAC,EAEP8B,EAAejB,EAAM,OAAQzjB,GAAMA,EAAE,SAAW,SAAS,EAAE,OAI3D2kB,EAAW,MAAOC,EAAgBC,IAAsB,CAC5D,MAAM7kB,EAAIyjB,EAAM,KAAM5oB,GAAMA,EAAE,KAAO+pB,CAAM,EAC3C,GAAI,CAAC5kB,EAAG,OACR,MAAMtF,EAAOsF,EAAE,OACf0jB,EAAUzgB,GACRA,EAAI,IAAKpI,GAAOA,EAAE,KAAO+pB,EAAS,CAAE,GAAG/pB,EAAG,OAAQgqB,CAAA,EAAchqB,CAAE,GAEpE,GAAI,CACF,MAAM1B,EAAI,MAAM,UAAU,mBAAmByrB,CAAM,CAAC,UAAW,CAC7D,OAAQC,CAAA,CACT,EACDtkB,EAAM,QAAQ,YAAYskB,CAAS,IAAK,IAAI,CAC9C,OAASxrB,EAAK,CACZqqB,EAAUzgB,GACRA,EAAI,IAAKpI,GAAOA,EAAE,KAAO+pB,EAAS,CAAE,GAAG/pB,EAAG,OAAQH,CAAA,EAASG,CAAE,GAE/D0F,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEMyrB,EAAa,MAAOF,GAAmB,CAC3C,GAAK,QAAQ,mBAAmB,EAChC,GAAI,CACF,MAAMzrB,EAAI,IAAI,UAAU,mBAAmByrB,CAAM,CAAC,EAAE,EACpDlB,EAAUzgB,GAAQA,EAAI,OAAQjD,GAAMA,EAAE,KAAO4kB,CAAM,CAAC,EACpDrkB,EAAM,QAAQ,gBAAiB,IAAI,CACrC,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEM0rB,EAAY,MAAOH,GAAmB,CAC1C,GAAI,CAGF,MAAM5pB,EAAI,MAAM7B,EAAI,KAClB,UAAU,mBAAmByrB,CAAM,CAAC,UAElC5pB,GAAKA,EAAE,MACT0oB,EAAUzgB,GAAQA,EAAI,IAAKjD,GAAOA,EAAE,KAAO4kB,EAAS5pB,EAAE,KAAOgF,CAAE,CAAC,EAElEO,EAAM,QAAQ,oBAAqB,IAAI,CACzC,OAASlH,EAAK,CACZkH,EAAM,MAAM,iBAAkBlH,EAAc,OAAO,EAAE,CACvD,CACF,EAEM2rB,EAAe,MAAOJ,GAAmB,CAC7C,MAAM5kB,EAAIyjB,EAAM,KAAM5oB,GAAMA,EAAE,KAAO+pB,CAAM,EAC3C,GAAK5kB,EACL,GAAI,CAIF,MAAMhF,EAAI,MAAM7B,EAAI,KAAuC,gBAAiB,CAC1E,MAAO6G,EAAE,MACT,YAAaA,EAAE,YACf,SAAUA,EAAE,SACZ,KAAMA,EAAE,KACT,EACKgF,GAAShK,EAAE,UAAY,IAAI,OACjCuF,EAAM,QACJyE,EAAQ,EACJ,sBAAsBA,CAAK,aAC3B,gBACJ,MAEEhK,EAAE,UAAYA,EAAE,SAAS,OAAS,GACpC0oB,EAAUzgB,GAAQ,CAACjI,EAAE,KAAM,GAAGA,EAAE,SAAU,GAAGiI,EAAI,OAAQpI,GAAMA,EAAE,KAAOmF,EAAE,EAAE,CAAC,CAAC,EAEhF,MAAM4H,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEA,OACEmC,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,UAAO,UAAU,cAChB,SAAAE,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC0B,GAAA,CAAY,KAAM,GAAI,EAAE,WAAS8S,EAAO,OAAO,KAClD,EACAxU,MAAC,KAAE,UAAU,gBAAgB,kGAE7B,GACF,EACF,EAGAE,OAAC,OAAI,UAAU,gBACb,UAAAF,MAAC,OAAI,UAAU,sBACb,SAAAE,OAAC,OAAI,UAAU,eAAe,MAAO,CAAE,MAAO,KAC5C,UAAAF,MAACsG,GAAA,CAAO,KAAM,GAAI,EAClBtG,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,UACZ,MAAOknB,EACP,SAAW9oB,GAAM+oB,EAAU/oB,EAAE,OAAO,KAAK,IAE1C8oB,GACClnB,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,eACX,QAAS,IAAMmnB,EAAU,EAAE,EAE3B,SAAAnnB,MAAC2pB,GAAA,CAAM,KAAM,GAAI,GACnB,EAEJ,EACF,EAEA3pB,MAAC,OAAI,UAAU,wBAAwB,EAEvCE,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,QAAK,UAAU,sBAAsB,oBAAQ,EAC9CE,OAAC,UACC,UAAU,mBACV,MAAOyoB,EACP,SAAWvqB,GAAMwqB,EAAkBxqB,EAAE,OAAO,KAAK,EACjD,MAAM,qBAEN,UAAA4B,MAAC,UAAO,MAAM,GAAG,eAAG,EACnByoB,GAAW,IAAKztB,GACfgF,MAAC,UAAe,MAAOhF,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,IACH,EACF,EAEAgF,MAAC,OAAI,UAAU,uBAAuB,EAEtCE,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS4D,EAAQ,MAAM,UAAU,aAAW,gBAC5E,SAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EACvB,EACCipB,EAAe,GACdlpB,OAAC2D,EAAA,CACC,QAASglB,EAAc,SAAW,QAClC,KAAK,KACL,QAAS,IAAMC,EAAgB9pB,GAAM,CAACA,CAAC,EACvC,MAAO6pB,EAAc,eAAiB,eAEtC,UAAA7oB,MAAC7H,GAAA,CAAM,KAAM,GAAI,EAAE,UAEnB6H,MAAC,QAAK,UAAU,QAAS,SAAAopB,CAAA,CAAa,KAG1ClpB,OAAC2D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,QAAS,IAAM+lB,GAAoBpmB,EAAOyB,EAAOmjB,EAAU3gB,EAAQ6E,CAAe,EAElF,UAAAtM,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,cACpB,EACF,GACF,EAEC+kB,GAAeO,EAAe,GAC7BppB,MAACkoB,GAAA,CACC,OAAQ7b,EAAS,QAAU,GAC3B,UAAWC,CAAA,GAId1P,EACCoD,MAAC,OAAI,UAAU,eAAe,SAAAA,MAACuO,IAAQ,KAAK,KAAK,EAAE,QAElD,OAAI,UAAU,SACZ,SAAAia,GAAQ,IAAKqB,GACZ7pB,MAAC8pB,GAAA,CAEC,OAAQD,EACR,MAAOrV,EAAO,OAAQ9P,GAAMA,EAAE,SAAWmlB,EAAI,EAAE,EAC/C,OAAQR,EACR,SAAUG,EACV,QAASC,EACT,OAAS/kB,GAAMqlB,GAAkBvmB,EAAOyB,EAAOP,EAAG0jB,EAAU3gB,EAAQ6E,CAAe,EACnF,eAAgBod,EAChB,KAAAX,CAAA,EARKc,EAAI,GAUZ,EACH,GAEJ,CAEJ,CAIA,SAASC,GAAa,CACpB,OAAAE,EACA,MAAA7B,EACA,OAAA8B,EACA,SAAA3S,EACA,QAAA4S,EACA,OAAAhZ,EACA,eAAAiZ,EACA,KAAApB,CACF,EASG,CACD,KAAM,CAACqB,EAAUC,CAAW,EAAIluB,WAAS,EAAK,EAC9C,OACE+D,OAAC,OACC,UAAW+C,EAAG,gBAAiBmnB,GAAY,oBAAoB,EAC/D,cAAaJ,EAAO,GACpB,WAAa5rB,GAAM,CAAEA,EAAE,iBAAkBisB,EAAY,EAAI,CAAG,EAC5D,YAAa,IAAMA,EAAY,EAAK,EACpC,OAASjsB,GAAM,CACbA,EAAE,iBACFisB,EAAY,EAAK,EACjB,MAAMpiB,EAAK7J,EAAE,aAAa,QAAQ,cAAc,EAC5C6J,GAAIgiB,EAAOhiB,EAAI+hB,EAAO,EAAE,CAC9B,EAEA,UAAA9pB,OAAC,OAAI,UAAU,oBACb,UAAAA,OAACgL,GAAA,CACC,UAAAlL,MAAC,QAAK,UAAWiD,EAAG,aAAc,UAAU+mB,EAAO,IAAI,EAAE,EAAG,EAC3DA,EAAO,OACV,EACAhqB,MAAC,QAAK,UAAU,gCAAiC,WAAM,OAAO,GAChE,QACC,OAAI,UAAU,kBACZ,SAAAmoB,EAAM,SAAW,EAChBnoB,MAAC,OAAI,UAAU,eAAe,oBAAQ,EAEtCmoB,EAAM,IAAKzjB,GACT1E,MAACsqB,GAAA,CAEC,KAAM5lB,EACN,OAAS6lB,GAAQ,CAEf,MAAMlrB,EADMmpB,GAAQ,UAAWnO,GAAMA,EAAE,KAAO3V,EAAE,MAAM,EACnC6lB,EACflrB,GAAQ,GAAKA,EAAOmpB,GAAQ,QAAQyB,EAAOvlB,EAAE,GAAI8jB,GAAQnpB,CAAI,EAAE,EAAE,CACvE,EACA,OAAQ,IAAM6R,EAAOxM,CAAC,EACtB,SAAU,IAAM4S,EAAS5S,EAAE,EAAE,EAC7B,QAAS,IAAMwlB,EAAQxlB,EAAE,EAAE,EAC3B,eAAgB,IAAMylB,EAAezlB,EAAE,EAAE,EACzC,KAAAqkB,CAAA,EAXKrkB,EAAE,GAaV,EAEL,IAGN,CAIA,SAAS4lB,GAAS,CAChB,KAAAxC,EACA,OAAAmC,EACA,OAAA/Y,EACA,SAAAoG,EACA,QAAA4S,EACA,eAAAC,EACA,KAAApB,CACF,EAQG,CACD,MAAMyB,EAAgB1C,EAAK,UAAYA,EAAK,UAAY,KACxD,OACE5nB,OAAC,OACC,UAAW+C,EAAG,YAAa,YAAY6kB,EAAK,QAAQ,EAAE,EACtD,eAAcA,EAAK,GACnB,UAAS,GACT,YAAc1pB,GAAM,CAClBA,EAAE,aAAa,QAAQ,eAAgB0pB,EAAK,EAAE,EAC9C1pB,EAAE,aAAa,cAAgB,MACjC,EACA,YAAW2qB,EAEX,UAAA7oB,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC,QACC,UAAU,eACV,MAAO,CAAE,WAAYyqB,GAAe3C,EAAK,QAAQ,GAAK,cAAc,GAEtE9nB,MAAC,OAAI,UAAU,kBAAmB,WAAK,MAAM,GAC/C,EACC8nB,EAAK,aACJ9nB,MAAC,OAAI,UAAU,iBAAkB,SAAA8nB,EAAK,YAAY,MAAM,EAAG,GAAG,EAAE,EAElE5nB,OAAC,OAAI,UAAU,mBACZ,UAAAsqB,UACE,QAAK,UAAU,kBAAkB,MAAO,qBAAqBA,CAAa,GACzE,UAAAxqB,MAACyB,GAAA,CAAI,KAAM,GAAI,EAAE,KAAG+oB,CAAA,EACtB,EAED1C,EAAK,UACJ5nB,OAAC,QAAK,UAAU,kBACd,UAAAF,MAAC6B,GAAA,CAAM,KAAM,GAAI,EAAE,IAAE,KAAK,OAAOimB,EAAK,WAAa,GAAK,EAAE,EAAE,KAC9D,EACE,KACHA,EAAK,MAAQA,EAAK,KAAK,OAAS,GAAKA,EAAK,KAAK,MAAM,EAAG,CAAC,EAAE,IAAK4C,SAC9D5wB,GAAA,CAAe,SAAA4wB,CAAA,EAANA,CAAU,CACrB,GACH,EACAxqB,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,QAAK,UAAU,oCACb,SAAAuI,GAAeuf,EAAK,SAAS,EAChC,EACA5nB,OAAC,OAAI,UAAU,oBAAoB,QAAU9B,GAAMA,EAAE,kBACnD,UAAA4B,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,YACX,MAAM,YACN,QAAS,IAAMiqB,EAAO,EAAE,EAExB,SAAAjqB,MAACzJ,GAAA,CAAY,KAAM,GAAI,IAEzByJ,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,OACX,MAAM,OACN,QAASkR,EAET,SAAAlR,MAAC2qB,GAAA,CAAM,KAAM,GAAI,IAEnB3qB,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,iBACX,MAAM,sBACN,QAASmqB,EAET,SAAAnqB,MAACyO,GAAA,CAAK,KAAM,GAAI,IAElBzO,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,QACX,MAAM,QACN,QAASkqB,EAET,SAAAlqB,MAAC8d,GAAA,CAAS,KAAM,GAAI,IAEtB9d,MAAC,UACC,KAAK,SACL,UAAU,2BACV,aAAW,SACX,MAAM,SACN,QAASsX,EAET,SAAAtX,MAACiP,GAAA,CAAO,KAAM,GAAI,IAEpBjP,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,aACX,MAAM,aACN,QAAS,IAAMiqB,EAAO,CAAC,EAEvB,SAAAjqB,MAACqB,GAAA,CAAa,KAAM,GAAI,GAC1B,EACF,GACF,IAGN,CAQA,SAASuoB,GACPpmB,EACAyB,EACAmjB,EACA3gB,EACA6E,EACA,CACA,IAAIse,EAAmC,KACnCtO,EAAqC,KACrCM,EAAkC,KAClCiO,EAAuC,KAE3C,MAAMC,EAAS,MAAO1sB,GAA6B,CAC7CA,GAAK,OAAOA,EAAE,gBAAmB,cAAc,iBACnD,MAAM8N,IAAS0e,GAAA,YAAAA,EAAS,QAAS,IAAI,OAC/BG,IAAezO,GAAA,YAAAA,EAAQ,QAAS,IAAI,OAC1C,GAAI,CAACpQ,EAAO,CACVjH,EAAM,QAAQ,oBAAoB,EAClC2lB,GAAA,MAAAA,EAAS,QACT,MACF,CACA,MAAMI,GAAYH,GAAA,YAAAA,EAAY,QAAS,SACjC7N,IAAQJ,GAAA,YAAAA,EAAQ,QAAS,IAC5B,MAAM,GAAG,EACT,IAAKzW,GAAMA,EAAE,MAAM,EACnB,OAAO,OAAO,EAEjB,GAAI,CACF,MAAM8W,EAAU,MAAMpf,EAAI,KAAW,SAAU,CAC7C,MAAAqO,EACA,YAAA6e,EACA,SAAAC,EACA,KAAAhO,CAAA,CAED,EACDxZ,EAAM,QACF,OAAO,OAAW,KACpB,OAAO,cAAc,IAAI,WAAW,WAAW,CAAC,EAElD4kB,EAAUzgB,GAAQ,CAACsV,EAAS,GAAGtV,CAAG,CAAC,EACnC1C,EAAM,QAAQ,gBAAiB,IAAI,EACnC,MAAMqH,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEMktB,EAAkB7sB,GAA6C,CAC/DA,EAAE,MAAQ,SAAW,CAACA,EAAE,WAC1BA,EAAE,iBACF0sB,EAAO1sB,CAAC,EAEZ,EAEAoF,EAAM,KAAK,CACT,MAAO,WACP,MAAO,IACP,SACEtD,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,aAAa,mBAAO,EAC3DA,MAAC,SACC,IAAMiW,GAAO,CAAE2U,EAAU3U,CAAI,EAC7B,GAAG,aACH,UAAU,QACV,KAAK,OACL,UAAW,IACX,YAAY,yBACZ,UAAS,GACT,UAAWgV,CAAA,SAEZ,SAAM,UAAU,cAAc,QAAQ,YAAY,uBAAW,EAC9D/qB,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,WAAY,cACjD,UAAAF,MAAC,YACC,IAAMiW,GAAO,CAAEqG,EAASrG,CAAI,EAC5B,GAAG,YACH,UAAU,WACV,KAAM,EACN,YAAY,iDACZ,MAAO,CAAE,KAAM,EAAE,GAEnBjW,MAAC,UACC,KAAK,SACL,UAAU,yBACV,MAAM,kBACN,QAAS,SAAY,OACnB,GAAI,GAAC/B,EAAAqe,GAAA,YAAAA,EAAQ,QAAR,MAAAre,EAAe,QAAQ,OAC5B,MAAMitB,EAAW,MAAMC,GAAc7O,EAAO,KAAK,EAC7C4O,IAAa5O,EAAO,QAAOA,EAAO,MAAQ4O,EAChD,EACD,cAED,EACF,EACAhrB,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,SAAM,QAAQ,gBAAgB,UAAU,kBAAkB,0BAEzDF,MAAC,UACC,IAAMiW,GAAO,CAAE4U,EAAa5U,CAAI,EAChC,GAAG,gBACH,UAAU,SACV,aAAa,SAEZ,SAAAwS,GAAW,IAAKztB,GACfgF,MAAC,UAAe,MAAOhF,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,EACF,EACAkF,OAAC,SAAM,QAAQ,YAAY,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAAK,kBACpEF,MAAC,QAAK,UAAU,aAAa,6BAAiB,EACnDA,MAAC,SACC,IAAMiW,GAAO,CAAE2G,EAAS3G,CAAI,EAC5B,GAAG,YACH,UAAU,QACV,KAAK,OACL,YAAY,yBACd,EACF,GACF,EACAjW,MAAC,KAAE,UAAU,gBAAgB,MAAO,CAAE,UAAW,GAAK,8EAEtD,GACF,EAEF,OACEE,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC5DtD,OAAC2D,EAAA,CAAO,QAAQ,UAAU,KAAK,SAAS,QAAUzF,GAAM0sB,EAAO1sB,CAAC,EAC9D,UAAA4B,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,gBACpB,GACF,EAEH,CACH,CAEA,SAASimB,GACPvmB,EACAyB,EACA6iB,EACAM,EACA3gB,EACA6E,EACA,CACA,IAAIse,EAAmC,KACnCtO,EAAqC,KACrCM,EAAkC,KAClCiO,EAAuC,KAE3C,MAAMC,EAAS,SAAY,CACzB,MAAM5e,IAAS0e,GAAA,YAAAA,EAAS,QAAS,IAAI,OAC/BG,IAAezO,GAAA,YAAAA,EAAQ,QAAS,IAAI,OAC1C,GAAI,CAACpQ,EAAO,CACVjH,EAAM,QAAQ,oBAAoB,EAClC2lB,GAAA,MAAAA,EAAS,QACT,MACF,CACA,MAAMI,GAAYH,GAAA,YAAAA,EAAY,QAAS,SACjC7N,IAAQJ,GAAA,YAAAA,EAAQ,QAAS,IAC5B,MAAM,GAAG,EACT,IAAKzW,GAAMA,EAAE,MAAM,EACnB,OAAO,OAAO,EAEjB,GAAI,CACF,MAAMiX,EAAU,MAAMvf,EAAI,IAAU,UAAU,mBAAmBiqB,EAAK,EAAE,CAAC,GAAI,CAC3E,MAAA5b,EACA,YAAA6e,EACA,SAAAC,EACA,KAAAhO,CAAA,CACD,EACDxZ,EAAM,QACF,OAAO,OAAW,KACpB,OAAO,cAAc,IAAI,WAAW,WAAW,CAAC,EAElD4kB,EAAUzgB,GAAQA,EAAI,IAAKpI,GAAOA,EAAE,KAAOuoB,EAAK,GAAK1K,EAAU7d,CAAE,CAAC,EAClE0F,EAAM,QAAQ,gBAAiB,IAAI,EACnC,MAAMqH,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEAyF,EAAM,KAAK,CACT,MAAO,YACP,MAAO,IACP,SACEtD,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,kBAAkB,mBAAO,EAChEA,MAAC,SACC,IAAMiW,GAAO,CAAE2U,EAAU3U,CAAI,EAC7B,GAAG,kBACH,UAAU,QACV,KAAK,OACL,UAAW,IACX,aAAc6R,EAAK,MACnB,UAAS,WAEV,SAAM,UAAU,cAAc,QAAQ,iBAAiB,uBAAW,EACnE9nB,MAAC,YACC,IAAMiW,GAAO,CAAEqG,EAASrG,CAAI,EAC5B,GAAG,iBACH,UAAU,WACV,KAAM,EACN,aAAc6R,EAAK,aAAe,KAEpC5nB,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,SAAM,QAAQ,qBAAqB,UAAU,kBAAkB,0BAE9DF,MAAC,UACC,IAAMiW,GAAO,CAAE4U,EAAa5U,CAAI,EAChC,GAAG,qBACH,UAAU,SACV,aAAc6R,EAAK,UAAY,SAE9B,SAAAW,GAAW,IAAKztB,GACfgF,MAAC,UAAe,MAAOhF,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,EACF,EACAkF,OAAC,SAAM,QAAQ,iBAAiB,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAAK,iBAE9EF,MAAC,SACC,IAAMiW,GAAO,CAAE2G,EAAS3G,CAAI,EAC5B,GAAG,iBACH,UAAU,QACV,KAAK,OACL,cAAe6R,EAAK,MAAQ,IAAI,KAAK,IAAI,EACzC,YAAY,mBACd,EACF,GACF,SACCld,EAAA,CACC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC0d,GAAA,CAAQ,KAAM,GAAI,EAAE,WAAO,SACtCvS,GAAA,CAAS,sBACCnL,MAAC,UAAQ,SAAA8nB,EAAK,OAAO,EAC7BA,EAAK,UAAY5nB,OAAAO,WAAA,CAAE,2BAAeqnB,EAAK,UAAS,EAChDA,EAAK,UAAY,CAACA,EAAK,UAAY5nB,OAAAO,WAAA,CAAE,0BAAcqnB,EAAK,UAAS,GACpE,GACF,GACF,EAEF,OACE5nB,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC5DtD,OAAC2D,EAAA,CAAO,QAAQ,UAAU,QAASinB,EACjC,UAAA9qB,MAAClK,GAAA,CAAe,KAAM,GAAI,EAAE,SAC9B,GACF,EAEH,CACH,CACO,MAAMs1B,GAAQxa,GAAM,KAAK8X,EAAU,ECroB1C,SAAS2C,GAAsBC,EAA4B,CACzD,OAAOztB,EAAI,aAAa,cAAc,mBAAmBytB,CAAU,CAAC,UAAU,CAChF,CAKO,SAASC,GACdC,EACAF,EACM,CACN,MAAM5gB,EAAM2gB,GAAsBC,CAAU,EAC5C,OAAO,KAAK5gB,EAAK,SAAU,qBAAqB,CAClD,CC5DA,MAAM+gB,GAAc,CAClB,KAAM,GAAK,IACX,KAAM,EAAI,GAAK,IACf,MAAO,GAAK,GAAK,IACjB,KAAM,GAAK,GAAK,GAClB,EAGMC,GAAc,GACdC,GAAmB,GACnBC,GAAsB,GACtBC,GAAgB,EAChBC,GAAiB,GAIjBC,GAAwC,CAC5C,QAAS,iBACT,QAAS,iBACT,MAAO,cACP,OAAQ,cACR,KAAM,iBACN,QAAS,iBACT,QAAS,iBACT,MAAO,eACP,OAAQ,eACR,MAAO,iBACP,OAAQ,eACR,KAAM,kBACN,QAAS,cACT,UAAW,gBACb,EAEA,SAAS/c,GAAY,EAAsC,CACzD,OAAK,GACE+c,GAAc,CAAC,GAAKA,GAAc,IAC3C,CAEA,SAASC,GAAW,EAA8BpkB,EAAI,GAAY,CAChE,OAAK,EACD,EAAE,QAAUA,EAAU,EACnB,EAAE,MAAM,EAAGA,EAAI,CAAC,EAAI,IAFZ,EAGjB,CAIA,SAASqkB,GAAQhc,EAAgD,CAC/D,GAAIA,GAAM,KAAM,MAAO,GACvB,GAAI,OAAOA,GAAO,SAAU,OAAOA,EACnC,MAAM,EAAI,IAAI,KAAKA,CAAE,EAAE,UACvB,OAAO,OAAO,MAAM,CAAC,EAAI,EAAI,CAC/B,CAEA,SAASic,GAAYxnB,EAAiB,CAEpC,MAAMuL,EAAMvL,EAA+B,YAC3C,OAAI,OAAOuL,GAAO,UAAYA,EAAK,EAAUA,EACtCgc,GAAQvnB,EAAE,SAAS,GAAK,KAAK,KACtC,CAEA,SAASynB,GAAUznB,EAAS0O,EAAqB,CAC/C,OAAI1O,EAAE,SAAW,QAAUA,EAAE,SAAW,YAAcA,EAAE,SAAW,UAAYA,EAAE,SAAW,YACnFunB,GAAQvnB,EAAE,WAAW,GAAKunB,GAAQvnB,EAAE,SAAS,IAAK0O,CAI7D,CAEA,SAASgZ,GAAUvxB,EAAuB,CACxC,OAAO,OAAOA,EAAE,WAAc,UAAYA,EAAE,UAAY,EAAIA,EAAE,UAAY,KAAK,KACjF,CAEA,SAASwxB,GAAQxxB,EAAeuY,EAAqB,CACnD,OACEvY,EAAE,SAAW,QACVA,EAAE,SAAW,WACbA,EAAE,SAAW,UACbA,EAAE,SAAW,UACbA,EAAE,SAAW,SACbA,EAAE,SAAW,eAETA,EAAE,aAAeA,EAAE,cAAeuY,CAG7C,CAEA,SAASkZ,GAAeC,EAAyB,CAC/C,OAAIA,GAAW,IAAe,IAC1BA,GAAW,IAAgB,IAC3BA,GAAW,KAAkB,IAC1B,GACT,CAEA,SAASC,GAAgB9nB,EAAW6nB,EAAyB,CAC3D,MAAM/Y,EAAI,IAAI,KAAK9O,CAAC,EACpB,OAAI6nB,GAAW,IACN/Y,EAAE,mBAAmB,QAAS,CAAE,OAAQ,GAAO,EAEjDA,EAAE,mBAAmB,QAAS,CAAE,OAAQ,GAAO,KAAM,UAAW,OAAQ,UAAW,CAC5F,CA6CO,SAAS7R,GAAS,CAAE,SAAA0K,EAAU,gBAAAC,GAA0B,CAC7D,MAAMrH,EAAQC,GAAA,EACRunB,EAAgBhvB,SAA8B,IAAI,EAGlD,CAACiL,EAAMgkB,CAAO,EAAIvwB,WAA2B,MAAM,EACnD,CAACwwB,EAAMC,CAAO,EAAIzwB,WAAkB,IAAI,EACxC,CAAC0wB,EAAYC,CAAa,EAAI3wB,WAAS,IACvC,OAAO,OAAW,IAAoB,GACnC,OAAO,WAAa,GAC5B,EAGK,CAAC4wB,EAAaC,CAAc,EAAI7wB,WAAuB,EAAE,EACzD,CAAC8wB,EAAQC,CAAS,EAAI/wB,WAA0B,EAAE,EAClD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACgxB,EAAaC,CAAc,EAAIjxB,WAAS,CAAC,EAG1C,CAACkxB,EAASC,CAAU,EAAInxB,WAAiB,KAAK,KAAK,EACnD,CAACoxB,EAAWC,CAAY,EAAIrxB,WAAiB,IAAM,KAAK,MAAQsvB,GAAY,IAAI,EAAI,EAAG,EAGvF,CAACgC,EAAYC,CAAa,EAAIvxB,WAA4C,CAAE,MAAO,IAAK,OAAQ,IAAK,EAGrG,CAACwxB,EAAcC,CAAe,EAAIzxB,WAA8B,IAAI,EAGpE,CAAC0xB,EAAaC,CAAc,EAAI3xB,WAAS,EAAE,EAC3C,CAACkoB,EAAUC,CAAW,EAAInoB,WAA0B,EAAE,EACtD,CAAC4xB,EAAWC,CAAY,EAAI7xB,WAAS,EAAE,EACvC,CAAC8xB,EAAcC,CAAe,EAAI/xB,WAAS,QAAQ,EACnD,CAACgyB,EAAWC,EAAY,EAAIjyB,WAAS,EAAE,EACvC,CAACkyB,GAAUC,CAAW,EAAInyB,WAAS,EAAE,EACrC,CAACoyB,EAAcC,EAAe,EAAIryB,WAAS,EAAK,EAChD,CAACsyB,EAAgBC,EAAiB,EAAIvyB,WAAS,EAAK,EAEpD,CAACwyB,GAAeC,CAAgB,EAAIzyB,WAAmB,EAAE,EAEzDqH,EAAQC,GAAA,EAERyT,EAAS7K,EAAS,QAAU,GAC5B8b,EAAQ9b,EAAS,OAAS,GAC1BkgB,EAAUd,GAAYkB,CAAI,EAC1BkC,EAAatB,EACbuB,EAAWvB,EAAYhB,EAGvBwC,GAAYpxB,cAAY,SAAY,CACxC,GAAI,CACF,KAAM,CAACqxB,EAAOC,CAAK,EAAI,MAAM,QAAQ,IAAI,CACvCpxB,EAAI,IAAiC,aAAa,EAAE,MAAM,KAAO,CAAE,UAAW,EAAC,EAAI,EACnFA,EAAI,IAAiC,qBAAqB,EAAE,MAAM,KAAO,CAAE,OAAQ,IAAK,EACzF,EACDmvB,EAAegC,EAAM,WAAa,EAAE,EACpC9B,EAAU+B,EAAM,QAAU,EAAE,CAC9B,OAASlxB,EAAK,CACZ,QAAQ,KAAK,0BAA2BA,CAAG,CAC7C,SACElB,EAAW,EAAK,CAClB,CACF,EAAG,EAAE,EAELqB,YAAU,IAAM,CACd6wB,GAAA,EACA,MAAM9mB,EAAK,YAAY8mB,GAAW,GAAI,EACtC,MAAO,IAAM,cAAc9mB,CAAE,CAC/B,EAAG,CAAC8mB,EAAS,CAAC,EAGd7wB,YAAU,IAAM,CACdkvB,EAAgB1oB,GAAMA,EAAI,CAAC,CAE7B,EAAG,CAACyjB,EAAM,OAAQjR,EAAO,MAAM,CAAC,EAGhChZ,YAAU,IAAM,CACd,GAAIwK,IAAS,QAAS,OACtB4kB,EAAW,KAAK,KAAK,EACrB,MAAMrlB,EAAK,YAAY,IAAMqlB,EAAW,KAAK,KAAK,EAAG,GAAI,EACzD,MAAO,IAAM,cAAcrlB,CAAE,CAC/B,EAAG,CAACS,EAAMykB,CAAW,CAAC,EAGtBjvB,YAAU,IAAM,CACd,GAAIwK,IAAS,QAAS,QACJ2kB,EAAUE,GAAahB,EAC1BT,IACb0B,EAAaH,EAAUd,EAAU,EAAG,CAExC,EAAG,CAACc,EAASE,EAAWhB,EAAS7jB,CAAI,CAAC,EAGtCxK,YAAU,IAAM,CACdsvB,EAAa,KAAK,MAAQjB,EAAU,EAAG,CAEzC,EAAG,CAACI,CAAI,CAAC,EAGTzuB,YAAU,IAAM,CACVwK,IAAS,QACX8kB,EAAa,KAAK,MAAQjB,EAAU,EAAG,CAG3C,EAAG,CAAC7jB,CAAI,CAAC,EAGTwmB,kBAAgB,IAAM,CACpB,MAAMjZ,EAAKwW,EAAc,QACzB,GAAI,CAACxW,EAAI,OACT,MAAMkZ,EAAK,IAAI,eAAgB7zB,IAAY,CACzC,UAAWb,MAASa,GAAS,CAC3B,KAAM,CAAE,MAAA4mB,GAAO,OAAAlmB,EAAA,EAAWvB,GAAM,YAChCizB,EAAc,CACZ,MAAO,KAAK,IAAI,IAAK,KAAK,MAAMxL,EAAK,CAAC,EACtC,OAAQ,KAAK,IAAI,IAAK,KAAK,MAAMlmB,EAAM,CAAC,EACzC,CACH,CACF,CAAC,EACD,OAAAmzB,EAAG,QAAQlZ,CAAE,EACN,IAAMkZ,EAAG,YAClB,EAAG,EAAE,EAGL,MAAMC,GAAgB7a,UAAQ,IAAM,CAClC,MAAM0H,EAAc,GACpB,IAAIvb,EAAM,EAGV,UAAW2uB,MAAMtC,EAAa,CAC5B,MAAMuC,GAAQlD,GAAUiD,EAAE,EACpBE,GAAMlD,GAAQgD,GAAIhC,CAAO,EAC3BkC,GAAMV,GAAcS,GAAQR,GAChC7S,EAAI,KAAK,CACP,KAAM,KACN,GAAI,MAAMoT,GAAG,UAAU,GACvB,MAAO3uB,IACP,MAAO,MAAMsrB,GAAWqD,GAAG,cAAe,EAAE,GAAKA,GAAG,WAAW,MAAM,EAAG,EAAE,CAAC,GAC3E,IAAKA,GAAG,QAAU,UAClB,MAAAC,GACA,IAAAC,GACA,KAAMF,EAAA,CACP,CACH,CAGA,MAAM7a,GAAS,CAAC,GAAG2T,CAAK,EAAE,KAAK,CAACvtB,GAAGC,KAAMqxB,GAAYtxB,EAAC,EAAIsxB,GAAYrxB,EAAC,CAAC,EAClE20B,GAAyB,GAC/B,UAAW9qB,MAAK8P,GAAQ,CACtB,MAAMrO,GAAI+lB,GAAYxnB,EAAC,EACjBtG,GAAI+tB,GAAUznB,GAAG2oB,CAAO,EAC9B,GAAIjvB,GAAIywB,GAAc1oB,GAAI2oB,EAAU,SACpC,IAAIW,GAAW,GACf,QAASr0B,GAAI,EAAGA,GAAIo0B,GAAa,OAAQp0B,KACvC,GAAIo0B,GAAap0B,EAAC,GAAK+K,GAAG,CACxBqpB,GAAap0B,EAAC,EAAIgD,GAClBqxB,GAAWr0B,GACX,KACF,CAEEq0B,KAAa,KACfD,GAAa,KAAKpxB,EAAC,EACnBqxB,GAAWD,GAAa,OAAS,GAEnCvT,EAAI,KAAK,CACP,KAAM,OACN,GAAI,QAAQvX,GAAE,EAAE,GAChB,MAAOhE,EAAM+uB,GACb,MAAOzD,GAAWtnB,GAAE,MAAO,EAAE,EAC7B,IAAKA,GAAE,OACP,MAAOyB,GACP,IAAK/H,GACL,KAAMsG,EAAA,CACP,CACH,CAEA,OAAOuX,CACT,EAAG,CAAC8Q,EAAa5E,EAAOkF,EAASwB,EAAYC,CAAQ,CAAC,EAEhDY,GAAWnb,UAAQ,IAAM,CAC7B,MAAM1F,MAAQ,IACd,UAAWkS,KAAKqO,GAAOvgB,EAAE,IAAIkS,EAAE,GAAIA,CAAC,EACpC,OAAOlS,CACT,EAAG,CAACugB,EAAK,CAAC,EAGJO,GAAUhyB,cACb+G,GACK6nB,GAAW,EAAU,GAChB7nB,EAAImqB,GAActC,EAAWkB,EAAW,MAEnD,CAACoB,EAAYtC,EAASkB,EAAW,KAAK,GAIlCmC,GAAQrb,UAAQ,IAAM,CAC1B,MAAMsb,EAAOvD,GAAeC,CAAO,EAC7BrxB,EAAoD,GAEpD40B,GAAe,KAAK,MAAMjB,EAAagB,CAAI,EAAIA,EACrD,QAASnrB,GAAIorB,GAAcprB,IAAKoqB,EAAWe,EAAMnrB,IAAKmrB,EAAM,CAC1D,GAAInrB,GAAImqB,EAAagB,EAAM,SAC3B,GAAInrB,GAAIoqB,EAAU,MAClB,MAAMvvB,GAAIowB,GAAQjrB,EAAC,EACfnF,GAAI,KAAOA,GAAIkuB,EAAW,MAAQ,IACtCvyB,EAAO,KAAK,CAAE,EAAAwJ,GAAG,EAAAnF,GAAG,MAAOitB,GAAgB9nB,GAAG6nB,CAAO,EAAG,CAC1D,CACA,OAAOrxB,CACT,EAAG,CAAC2zB,EAAYC,EAAUvC,EAASkB,EAAW,MAAOkC,EAAO,CAAC,EAGvDI,GAAkBxb,UAAQ,IAAM,CACpC,MAAM0H,EAAiB,GACvB,UAAW+T,KAAQZ,GAAO,CACxB,GAAIY,EAAK,OAAS,SAAU,SAC5B,MAAMC,GAAe,KAAK,IAAID,EAAK,MAAOnB,CAAU,EAC9CqB,GAAa,KAAK,IAAIF,EAAK,IAAKlB,CAAQ,EAC9C,GAAIoB,GAAarB,GAAcoB,GAAenB,EAAU,SACxD,MAAMvvB,GAAIowB,GAAQM,EAAY,EACxBE,GAAOR,GAAQO,EAAU,EACzB5uB,GAAI,KAAK,IAAIuqB,GAAesE,GAAO5wB,EAAC,EACpCyjB,GAAI2I,GAAmBC,GAAsBoE,EAAK,MAAQtE,GAAc,EACxEle,GAAIke,GAAc,GAExB,IAAI0E,GAAsC,QAC1C,GAAIJ,EAAK,OAAS,KAAM,CACtB,MAAM7pB,GAAI6pB,EAAK,KAAK,QAAU,UAC1B7pB,KAAM,QAAUA,KAAM,UAAWiqB,GAAc,OAC1CjqB,KAAM,UAAYA,KAAM,UAAYA,KAAM,QAASiqB,GAAc,SACjEjqB,KAAM,UAAYA,KAAM,UAAWiqB,GAAc,SACjDjqB,KAAM,WAAaA,KAAM,QAASiqB,GAAc,UACpDA,GAAc,OACrB,KAAO,CACL,MAAMjqB,GAAI6pB,EAAK,KAAK,OAChB7pB,KAAM,QAAUA,KAAM,WAAYiqB,GAAc,OAC3CjqB,KAAM,UAAYA,KAAM,SAAUiqB,GAAc,SAChDjqB,KAAM,SAAUiqB,GAAc,SAC9BjqB,KAAM,UAAWiqB,GAAc,UACnCA,GAAc,OACrB,CAEA,MAAMrR,IAAW4O,GAAA,YAAAA,EAAc,MAAOqC,EAAK,GAE3C/T,EAAI,KAAK,CACP,GAAI+T,EAAK,GACT,UAAWA,EAAK,MAChB,EAAAzwB,GACA,EAAAyjB,GACA,EAAA1hB,GACA,EAAAkM,GACA,MAAOwiB,EAAK,MACZ,YAAAI,GACA,SAAArR,GACA,KAAMiR,EAAK,KACX,KAAMA,EAAK,KACX,MAAOA,EAAK,MACZ,IAAKA,EAAK,IACX,CACH,CACA,OAAO/T,CACT,EAAG,CAACmT,GAAOO,GAAShC,EAAckB,EAAYC,CAAQ,CAAC,EAGjDuB,GAA8B9b,UAAQ,IAAM,CAChD,MAAM0H,EAAqB,GAC3B,UAAWqU,KAAMrD,EAAQ,CACvB,MAAMhd,GAAKgc,GAAQqE,EAAG,EAAE,EACxB,GAAIrgB,GAAK4e,EAAa,KAAQ5e,GAAK6e,EAAW,IAAM,SACpD,MAAMvvB,GAAIowB,GAAQ1f,EAAE,EAGpB,IAAI+S,GAAI2I,GAAmB,GAC3B,GAAI2E,EAAG,OAAQ,CACb,MAAMN,GAAON,GAAS,IAAI,QAAQY,EAAG,MAAM,EAAE,EACzCN,KAAMhN,GAAI2I,GAAmBC,GAAsBoE,GAAK,MAAQtE,GAAcA,GAAc,EAClG,SAAW4E,EAAG,OAAQ,CACpB,MAAMroB,GAAK,OAAOqoB,EAAG,MAAM,EACrBN,GAAON,GAAS,IAAIznB,GAAG,WAAW,OAAO,GAAKA,GAAG,WAAW,KAAK,EAAIA,GAAK,QAAQA,EAAE,EAAE,EACxF+nB,KAAMhN,GAAI2I,GAAmBC,GAAsBoE,GAAK,MAAQtE,GAAcA,GAAc,EAClG,CAEAzP,EAAI,KAAK,CACP,GAAI,GAAGqU,EAAG,EAAE,IAAIA,EAAG,IAAI,IAAIA,EAAG,QAAU,EAAE,IAAIA,EAAG,QAAU,EAAE,GAC7D,EAAA/wB,GACA,EAAAyjB,GACA,KAAMsN,EAAG,MAAQ,QACjB,GAAArgB,GACA,KAAM,OAAOqgB,EAAG,MAAQA,EAAG,MAAQ,EAAE,EACrC,OAAQA,EAAG,OACZ,CACH,CACA,OAAOrU,CACT,EAAG,CAACgR,EAAQ4B,EAAYC,EAAUa,GAASD,EAAQ,CAAC,EAG9Ca,GAAYhc,UAAQ,IACjB6a,GAAM,IAAKY,IAAU,CAC1B,GAAIA,EAAK,GACT,EAAGrE,GAAmBC,GAAsBoE,EAAK,MAAQtE,GACzD,EAAGA,EAAA,EACH,EACD,CAAC0D,EAAK,CAAC,EAGJoB,GAAOjc,UAAQ,IAAM,CACzB,MAAMhV,EAAIowB,GAAQtC,CAAO,EACzB,OAAO,KAAK,IAAI,EAAG,KAAK,IAAII,EAAW,MAAOluB,CAAC,CAAC,CAClD,EAAG,CAACowB,GAAStC,EAASI,EAAW,KAAK,CAAC,EAGjCgD,GAAc9yB,cAAa+yB,GAAiB,CAEhD,MAAMpgB,GAAqB,CACzB,GAFSogB,EAAI,GAGb,KAAMA,EAAI,KACV,MAAOA,EAAI,MACX,OAAQA,EAAI,YACZ,KAAMA,EAAI,MAEZ9C,EAAgBtd,EAAI,CACtB,EAAG,EAAE,EAGLpS,YAAU,IAAM,CACd,GAAI,CAACyvB,EAAc,CACjBrJ,EAAY,EAAE,EACdgK,EAAY,EAAE,EACdM,EAAiB,EAAE,EACnB,MACF,CACAd,EAAe,EAAE,EACjBE,EAAa,EAAE,EACfI,GAAa,EAAE,EACfQ,EAAiB,EAAE,GAClB,SAAY,CACX,GAAI,CACF,MAAMlvB,EAAI,MAAM7B,EAAI,IAClB,oBAAoB,mBAAmB8vB,EAAa,EAAE,CAAC,aAEzDrJ,EAAY5kB,EAAE,QAAU,EAAE,CAC5B,MAAQ,CACN4kB,EAAY,EAAE,CAChB,CACA,GAAIqJ,EAAa,OAAS,KAAM,CAC9B,MAAMgD,EAAShD,EAAa,KAC5B,GAAI,CACF,MAAMjuB,EAAI,MAAM7B,EAAI,IAClB,eAAe,mBAAmB8yB,EAAO,UAAU,CAAC,oBAEtDrC,EAAY5uB,EAAE,QAAU,EAAE,CAC5B,MAAQ,CACN4uB,EAAY,EAAE,CAChB,CAEA,GAAIqC,EAAO,OACT,GAAI,CACF,MAAMC,EAAO,MAAM/yB,EAAI,IACrB,UAAU,mBAAmB8yB,EAAO,MAAM,CAAC,cAE7C/B,GAAkBgC,EAAK,WAAa,IAAI,IAAKh2B,IAAMA,GAAE,EAAE,CAAC,CAC1D,MAAQ,CACNg0B,EAAiB,EAAE,CACrB,CAEJ,CACF,IACF,EAAG,CAACjB,CAAY,CAAC,EAGjB,MAAMkD,GAAe,SAAY,CAC/B,GAAI,GAAClD,GAAgB,CAACE,EAAY,QAClC,CAAAa,GAAkB,EAAI,EACtB,GAAI,CACF,MAAM7wB,EAAI,KAAK,YAAa,CAAE,OAAQ8vB,EAAa,GAAI,KAAME,EAAa,OAAQ,OAAQ,EAC1FC,EAAe,EAAE,EACjB,MAAMpuB,EAAI,MAAM7B,EAAI,IAClB,oBAAoB,mBAAmB8vB,EAAa,EAAE,CAAC,aAEzDrJ,EAAY5kB,EAAE,QAAU,EAAE,EAC1BuF,EAAM,QAAQ,gBAAgB,CAChC,OAASlH,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,SACE2wB,GAAkB,EAAK,CACzB,EACF,EAEMoC,GAAuB,SAAY,CACvC,GAAI,GAACnD,GAAgB,CAACI,EAAU,QAChC,CAAAS,GAAgB,EAAI,EACpB,GAAI,CACF,MAAM3wB,EAAI,KAAK,UAAU,mBAAmB8vB,EAAa,EAAE,CAAC,SAAU,CACpE,MAAOI,EACP,YAAa,mCAAmCJ,EAAa,EAAE,IAC/D,SAAUM,CAAA,CACX,EACDD,EAAa,EAAE,EACf/oB,EAAM,QAAQ,eAAe,EAC7B,MAAMqH,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,SACEywB,GAAgB,EAAK,CACvB,EACF,EAEMuC,GAAkB,SAAY,CAClC,GAAI,CAACpD,GAAgBA,EAAa,OAAS,MAAQ,CAACQ,EAAU,OAAQ,OACtE,MAAMwC,EAAShD,EAAa,KAC5B,GAAI,CACF,MAAMjuB,EAAI,MAAM7B,EAAI,KAClB,eAAe,mBAAmB8yB,EAAO,UAAU,CAAC,WACpD,CAAE,QAASxC,CAAA,CAAU,EAEnBzuB,EAAE,IACJuF,EAAM,QAAQ,eAAe,EAC7BmpB,GAAa,EAAE,GAEfnpB,EAAM,QAAQvF,EAAE,OAAS,aAAa,CAE1C,OAAS3B,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEMizB,GAAW,SAAY,CAE3B,GADI,CAACrD,GAAgBA,EAAa,OAAS,MACvC,CAAC,QAAQ,gCAAgC,EAAG,OAChD,MAAMgD,EAAShD,EAAa,KAC5B,GAAI,CACF,MAAMjuB,EAAI,MAAM7B,EAAI,IAClB,eAAe,mBAAmB8yB,EAAO,UAAU,CAAC,IAElDjxB,EAAE,GAAIuF,EAAM,QAAQ,iBAAiB,EACpCA,EAAM,QAAQvF,EAAE,OAAS,aAAa,EAC3C,MAAMqvB,GAAA,CACR,OAAShxB,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEMkzB,GAAgB,SAAY,CAChC,GAAI,CAACtD,GAAgBA,EAAa,OAAS,KAAM,OACjD,MAAMgD,EAAShD,EAAa,KAC5B,GAAI,CACF,MAAMjuB,EAAI,MAAM7B,EAAI,IAClB,eAAe,mBAAmB8yB,EAAO,UAAU,CAAC,oBAEtDrC,EAAY5uB,EAAE,QAAU,EAAE,CAC5B,MAAQ,CAER,CACF,EAGAxB,YAAU,IAAM,CACd,MAAMmI,EAASjI,GAAqB,CAC9BA,EAAE,MAAQ,UAAUwvB,EAAgB,IAAI,CAC9C,EACA,cAAO,iBAAiB,UAAWvnB,CAAK,EACjC,IAAM,OAAO,oBAAoB,UAAWA,CAAK,CAC1D,EAAG,EAAE,EAGL,MAAM6qB,GAAU,IAAM,CACpB9D,EAAgB1oB,GAAMA,EAAI,CAAC,EAC3BqqB,GAAA,CACF,EAGMoC,GAAgBxF,GAAmBC,GAAsBwD,GAAM,OAAS1D,GAG9E,OACExrB,OAAC,OAAI,UAAU,qBAEb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAACoxB,GAAA,CAAa,KAAM,GAAI,EAAE,aAC5B,EACApxB,MAAC,KAAE,UAAU,gBAAgB,kHAE7B,GACF,QACC,OAAI,UAAU,eACb,SAAAE,OAAC,OAAI,UAAU,iBACb,UAAAA,OAAC2D,EAAA,CACC,QAAS6E,IAAS,OAAS,UAAY,YACvC,KAAK,KACL,QAAS,IAAMgkB,EAAQhkB,IAAS,OAAS,QAAU,MAAM,EACzD,MAAOA,IAAS,OAAS,iBAAmB,kBAE3C,UAAAA,IAAS,aAAU2oB,GAAA,CAAM,KAAM,GAAI,EAAKrxB,MAACud,GAAA,CAAK,KAAM,GAAI,EACxD7U,IAAS,OAAS,OAAS,YAE9B1I,MAAC,OAAI,UAAU,gBACX,UAAC,KAAM,KAAM,MAAO,IAAI,EAAgB,IAAKsxB,GAC7CtxB,MAAC,UACC,KAAK,SAEL,UAAWiD,EAAG,cAAe0pB,IAAS2E,GAAK,oBAAoB,EAC/D,QAAS,IAAM1E,EAAQ0E,CAAC,EACxB,MAAO,WAAWA,CAAC,GAElB,SAAAA,CAAA,EALIA,CAAA,CAOR,EACH,EACApxB,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAASqtB,GAAS,MAAM,UAC5D,UAAAlxB,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,GACF,EACF,GACF,EAECvD,SACE,OAAI,UAAU,eAAe,SAAAoD,MAACuO,GAAA,CAAQ,KAAK,KAAK,EAAE,EAGpD,CAAC3R,GAAWsa,EAAO,SAAW,GAAKiR,EAAM,SAAW,GAAK4E,EAAY,SAAW,GAAKE,EAAO,SAAW,EACtGjtB,MAACgM,GAAA,CACC,KAAMhM,MAACoxB,GAAA,CAAa,KAAM,GAAI,EAC9B,MAAM,kBACN,QAAQ,6FAGVpxB,MAAC,OAAI,UAAWiD,EAAG,UAAW0qB,GAAgB,qBAAqB,EACjE,SAAAztB,OAAC,OAAI,UAAW+C,EAAG,UAAW,CAAC4pB,GAAc,0BAA0B,EAErE,UAAA3sB,OAAC,SAAM,UAAW+C,EAAG,YAAa,CAAC4pB,GAAc,qBAAqB,EACpE,UAAA3sB,OAAC,OAAI,UAAU,iBACb,UAAAA,OAAC,MACC,UAAAF,MAACuxB,GAAA,CAAQ,KAAM,GAAI,EAAE,gBACvB,EACAvxB,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAM8sB,EAAc,EAAK,EAClC,MAAM,oBACN,aAAW,oBAEX,SAAA9sB,MAAChH,GAAA,CAAe,KAAM,GAAI,GAC5B,EACF,EACAgH,MAAC,OAAI,UAAU,iBACZ,SAAAitB,EAAO,SAAW,EACjBjtB,MAAC,OAAI,UAAU,kBACb,SAAAA,MAAC,KAAE,0BAAc,EACnB,EAEA,CAAC,GAAGitB,CAAM,EAAE,UAAU,IAAI,CAACqD,EAAIl1B,IAAM,CACnC,MAAM+H,GACJmtB,EAAG,OAAS7uB,GAAM6uB,EAAG,OAAS,OAAS5uB,GAAc4uB,EAAG,OAAS,KAAOx5B,GAAMs6B,GAChF,OACElxB,OAAC,OAA0B,UAAU,kBACnC,UAAAF,MAAC,QAAK,UAAU,uBACb,aAAI,KAAKswB,EAAG,EAAE,EAAE,mBAAmB,QAAS,CAAE,OAAQ,GAAO,EAChE,QACC,QAAK,UAAU,uBAAuB,MAAO,CAAE,MAAOthB,GAAYshB,EAAG,IAAI,GACxE,SAAAtwB,MAACmD,GAAA,CAAK,KAAM,GAAI,EAClB,EACAnD,MAAC,QAAK,UAAU,uBACb,WAAG,QAAUswB,EAAG,MAAQA,EAAG,KAC9B,IATQ,GAAGA,EAAG,EAAE,IAAIl1B,CAAC,EAUvB,CAEJ,CAAC,EAEL,GACF,EAGA8E,OAAC,OAAI,UAAU,iBAAiB,IAAKusB,EACnC,UAAAvsB,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,OAAI,UAAU,yBACZ,WAAC2sB,GACA3sB,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAS,IAAMipB,EAAc,EAAI,EACjC,MAAM,oBAEN,UAAA9sB,MAAC/G,GAAA,CAAc,KAAM,GAAI,EAAE,mBAG9B,QAAK,UAAU,iBACb,SAAAyP,IAAS,OAAS,SAAW,WAChC,EACAxI,OAAC,QAAK,UAAU,kBACb,cAAI,KAAK2uB,CAAU,EAAE,mBAAmB,QAAS,CAAE,OAAQ,GAAO,EAAE,KAAG,IACvE,IAAI,KAAKC,CAAQ,EAAE,mBAAmB,QAAS,CAAE,OAAQ,GAAO,GACnE,GACF,EACA5uB,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAAC,QAAK,UAAU,gBAAgB,MAAO,CAAE,WAAY,kBAAoB,EAAE,WAAO,EACnHE,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAAC,QAAK,UAAU,qCAAqC,MAAO,CAAE,YAAa,eAAiB,EAAE,WAAO,EACtIE,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAAC,QAAK,UAAU,gBAAgB,MAAO,CAAE,WAAY,kBAAoB,EAAE,YAAQ,EACpHE,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAAC,QAAK,UAAU,gBAAgB,MAAO,CAAE,WAAY,gBAAkB,EAAE,UAAM,EAChHA,MAAC,QAAK,UAAU,gBAAgB,EAChCE,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAAC3H,GAAA,CAAO,KAAM,GAAI,EAAE,UAAM,EAC3D6H,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAACjG,GAAA,CAAO,KAAM,GAAI,EAAE,SAAK,EAC1DmG,OAAC,QAAK,UAAU,iBAAiB,UAAAF,MAAClJ,GAAA,CAAI,KAAM,GAAI,EAAE,OAAG,GACvD,GACF,EAEAkJ,MAAC,OAAI,UAAU,mBACb,SAAAE,OAAC,OACC,UAAU,YACV,MAAOutB,EAAW,MAClB,OAAQ,KAAK,IAAIA,EAAW,OAAQ0D,EAAa,EACjD,KAAK,cACL,aAAW,oBAEX,UAAAnxB,MAAC,QACC,SAAAA,MAAC,WACC,GAAG,iBACH,MAAOytB,EAAW,MAClB,OAAQ/B,GACR,aAAa,iBAEb,SAAA1rB,MAAC,QACC,EAAG,aAAa0rB,EAAW,GAC3B,KAAK,OACL,OAAO,gBACP,YAAa,GACb,QAAS,KACX,GAEJ,QACC,QAAK,MAAM,OAAO,OAAO,OAAO,KAAK,uBAAuB,EAG5D6E,GAAU,IAAKiB,GACdxxB,MAAC,QAEC,UAAU,aACV,EAAG,EACH,EAAGwxB,EAAG,EACN,MAAO/D,EAAW,MAClB,OAAQ+D,EAAG,EACX,KAAMA,EAAG,GAAG,WAAWA,EAAG,GAAG,OAAS,CAAC,EAAI,IAAM,EAAI,mBAAqB,iBAC1E,QAAS,IAPJ,MAAMA,EAAG,EAAE,GASnB,EAGDxxB,MAAC,KAAE,UAAU,eACV,YAAM,IAAK0E,GACVxE,OAAC,KACC,UAAAF,MAAC,QACC,GAAI0E,EAAE,EACN,GAAI,EACJ,GAAIA,EAAE,EACN,GAAIysB,GACJ,OAAO,gBACP,YAAa,GACb,gBAAgB,MAChB,QAAS,KAEXnxB,MAAC,QACC,EAAG0E,EAAE,EAAI,EACT,EAAGinB,GAAmB,EACtB,SAAU,GACV,WAAW,mBACX,KAAK,kBAEJ,SAAAjnB,EAAE,OACL,GAnBM,QAAQA,EAAE,CAAC,EAoBnB,CACD,EACH,EAGC0qB,GAAM,IAAKY,GAAS,CACnB,MAAMhN,EAAI2I,GAAmBC,GAAsBoE,EAAK,MAAQtE,GAAcA,GAAc,EAC5F,OACExrB,OAAC,KAA2B,UAAU,sBACpC,UAAAF,MAAC,QACC,EAAG,EACH,EAAGgjB,EAAI,EACP,UAAU,gBACV,WAAW,QAEV,SAAAgJ,GAAWgE,EAAK,MAAO,EAAE,IAE5BhwB,MAAC,QACC,EAAG,EACH,EAAGgjB,EAAI,GACP,UAAU,oBACV,WAAW,QAEV,SAAAgN,EAAK,KACR,GAhBM,SAASA,EAAK,EAAE,EAiBxB,CAEJ,CAAC,EAGAD,GAAK,IAAKW,GAAQ,CACjB,MAAMe,EAAYziB,GAAY0hB,EAAI,WAAW,EACvC9vB,GAAa8vB,EAAI,MAAO/C,GAAA,YAAAA,EAAc,IAC5C,OACEztB,OAAC,KAEC,UAAW+C,EAAG,cAAe,eAAeytB,EAAI,WAAW,GAAI9vB,IAAc,sBAAsB,EACnG,QAAS,IAAM6vB,GAAYC,CAAG,EAE9B,UAAA1wB,MAAC,QACC,EAAG0wB,EAAI,EACP,EAAGA,EAAI,EACP,MAAOA,EAAI,EACX,OAAQA,EAAI,EACZ,GAAI,EACJ,KAAMe,EACN,YAAaf,EAAI,cAAgB,OAAS,IAAOA,EAAI,cAAgB,SAAW,IAAO,IACvF,OAAQe,EACR,YAAa7wB,GAAa,IAAM,IAChC,cAAe8vB,EAAI,cAAgB,OAAS,GAAM,EAClD,gBAAiBA,EAAI,cAAgB,SAAW,MAAQ,OACxD,MAAO,CAAE,OAAQ,UAAU,GAE5BA,EAAI,EAAI,IACP1wB,MAAC,QACC,EAAG0wB,EAAI,EAAI,EACX,EAAGA,EAAI,EAAIA,EAAI,EAAI,EAAI,EACvB,SAAU,GACV,WAAW,mBACX,WAAY,IACZ,KAAK,qBACL,MAAO,CAAE,cAAe,QACxB,QAASA,EAAI,cAAgB,OAAS,GAAM,EAE3C,SAAA1E,GAAW0E,EAAI,MAAO,KAAK,IAAI,EAAG,KAAK,MAAMA,EAAI,EAAI,CAAC,CAAC,CAAC,GAC3D,GA9BG,OAAOA,EAAI,EAAE,GAkCxB,CAAC,EAGAL,GAAa,IAAKxhB,GAAM,CACvB,MAAM4M,EAAQzM,GAAYH,EAAE,IAAI,EAChC,OACE3O,OAAC,KAAqB,UAAU,wBAC9B,UAAAF,MAAC,QACC,GAAI6O,EAAE,EACN,GAAIA,EAAE,EAAI,EACV,GAAIA,EAAE,EACN,GAAIA,EAAE,EAAI,EACV,OAAQ4M,EACR,YAAa,IACb,QAAS,KAEXzb,MAAC,UACC,GAAI6O,EAAE,EACN,GAAIA,EAAE,EACN,EAAG,EACH,KAAM4M,EACN,QAAS,GAET,SAAAzb,MAAC,SACE,YAAG6O,EAAE,IAAI,GAAGA,EAAE,OAAS,MAAMA,EAAE,MAAM,GAAK,EAAE,MAAM,IAAI,KAAKA,EAAE,EAAE,EAAE,mBAAmB,QAAS,CAAE,OAAQ,GAAO,CAAC,GAClH,GACF,GApBM,MAAMA,EAAE,EAAE,EAqBlB,CAEJ,CAAC,EAGD7O,MAAC,QACC,UAAU,cACV,GAAIwwB,GACJ,GAAI,EACJ,GAAIA,GACJ,GAAIW,GACJ,OAAO,eACP,YAAa,IACb,QAAS,KAEXjxB,OAAC,KAAE,UAAU,gBACX,UAAAF,MAAC,UAAO,GAAIwwB,GAAM,GAAI7E,GAAmB,EAAG,EAAG,EAAG,KAAK,eAAe,EACtE3rB,MAAC,QACC,EAAGwwB,GAAO,EACV,EAAG7E,GAAmB,EACtB,SAAU,GACV,WAAY,IACZ,KAAK,eACL,WAAW,mBACZ,gBAED,EACF,IACF,CACF,GACF,EAGCgC,GACC3tB,MAAC,SAAM,UAAU,4BACf,gBAAC4K,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACE,UAAAyiB,EAAa,OAAS,SAAW3tB,MAACyB,GAAA,CAAI,KAAM,GAAI,EAChDksB,EAAa,OAAS,QAAU3tB,MAAC0B,GAAA,CAAY,KAAM,GAAI,EACvDisB,EAAa,OAAS,MAAQ3tB,MAAClJ,GAAA,CAAI,KAAM,GAAI,EAC7C62B,EAAa,MACd3tB,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAM4tB,EAAgB,IAAI,EACnC,MAAM,QACN,aAAW,wBACX,MAAO,CAAE,WAAY,QAErB,SAAA5tB,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,EACArG,OAAC,OAAI,UAAU,iBACb,UAAAA,OAAC,OAAI,UAAAF,MAAC,QAAK,UAAU,QAAQ,gBAAI,EAAO,IAAE2tB,EAAa,MAAK,SAC3D,OAAI,UAAA3tB,MAAC,QAAK,UAAU,QAAQ,kBAAM,EAAO,IAACA,MAAC,QAAM,SAAA2tB,EAAa,OAAO,GAAO,EAC5EA,EAAa,OAAS,UAAY,IAAM,CACvC,MAAM/yB,EAAI+yB,EAAa,KACvB,OACEztB,OAAAO,WAAA,CACG,UAAA7F,EAAE,aAAS,OAAI,UAAAoF,MAAC,QAAK,UAAU,QAAQ,gBAAI,EAAO,IAAEpF,EAAE,MAAK,EAC3DA,EAAE,OAASsF,OAAC,OAAI,UAAAF,MAAC,QAAK,UAAU,QAAQ,iBAAK,EAAO,IAAEpF,EAAE,OAAM,GACjE,CAEJ,KACC+yB,EAAa,OAAS,SAAW,IAAM,CACtC,MAAMjpB,EAAIipB,EAAa,KACvB,OACEztB,OAAAO,WAAA,CACG,UAAAiE,EAAE,iBAAa,OAAI,UAAA1E,MAAC,QAAK,UAAU,QAAQ,oBAAQ,EAAO,KAAG0E,EAAE,UAAS,EACxEA,EAAE,UAAYxE,OAAC,OAAI,UAAAF,MAAC,QAAK,UAAU,QAAQ,oBAAQ,EAAO,IAAE0E,EAAE,UAAS,EACvEA,EAAE,WAAaxE,OAAC,OAAI,UAAAF,MAAC,QAAK,UAAU,QAAQ,mBAAO,EAAO,IAAE,IAAI,KAAK0E,EAAE,SAAS,EAAE,gBAAe,EAAE,GACtG,CAEJ,KACCipB,EAAa,OAAS,OAAS,IAAM,CACpC,MAAM9yB,EAAI8yB,EAAa,KACvB,OACEztB,OAAAO,WAAA,CACG,UAAA5F,EAAE,kBAAc,OAAI,UAAAmF,MAAC,QAAK,UAAU,QAAQ,mBAAO,EAAO,IAAE,IAAI,KAAKnF,EAAE,SAAS,EAAE,gBAAe,EAAE,EACnGA,EAAE,aAAeqF,OAAC,OAAI,UAAAF,MAAC,QAAK,UAAU,QAAQ,gBAAI,EAAO,IAACA,MAAC,QAAM,SAAAnF,EAAE,YAAY,EAAO,IAAEA,EAAE,WAAamF,MAAC,QAAK,UAAU,kBAAkB,kBAAM,EAAUA,MAAC,QAAK,UAAU,MAAM,oBAAQ,GAAQ,GAClM,CAEJ,IAAG,EACL,EACC2tB,EAAa,OAAS,QAAWA,EAAa,KAAc,aAC3D3tB,MAAC,OAAI,UAAU,iBAAmB,SAAA2tB,EAAa,KAAc,YAAY,EAE1EA,EAAa,OAAS,MAASA,EAAa,KAAoB,eAC/D3tB,MAAC,OAAI,UAAU,iBAAmB,SAAA2tB,EAAa,KAAoB,cAAc,EAGlFA,EAAa,OAAS,MACrBztB,OAAC,OAAI,UAAU,eACb,UAAAF,MAAC,OAAI,UAAU,eAAgB,SAAAquB,IAAY,kDAAkD,EAC7FnuB,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC2D,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAASotB,GACzC,UAAAjxB,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,mBACzB,EACCwuB,GAAc,OAAS,GACtBzuB,OAAC2D,EAAA,CACC,QAAQ,YACR,KAAK,KACL,QAAS,IAAM0nB,GAAmB/nB,EAAOmrB,GAAc,CAAC,CAAC,EAEzD,UAAA3uB,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAAE,2BAGzBjI,EAAA,CAAO,QAAQ,SAAS,KAAK,KAAK,QAASmtB,GAC1C,UAAAhxB,MAACiP,GAAA,CAAO,KAAM,GAAI,EAAE,iBACtB,GACF,EACA/O,OAAC,OAAI,UAAU,cACb,UAAAF,MAAC,SACC,UAAU,QACV,YAAY,qCACZ,MAAOmuB,EACP,SAAW/vB,GAAMgwB,GAAahwB,EAAE,OAAO,KAAK,EAC5C,UAAYA,GAAM,CACZA,EAAE,MAAQ,SAAS2yB,GAAA,CACzB,IAEF7wB,OAAC2D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,SAAU,CAACsqB,EAAU,OAAQ,QAAS4C,GACxE,UAAA/wB,MAACyO,GAAA,CAAK,KAAM,GAAI,EAAE,SACpB,GACF,GACF,EAGDkf,EAAa,OAAS,MACrBztB,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,OAAI,UAAU,cAAc,iCAAqB,EAClDA,MAAC,SACC,UAAU,QACV,YAAY,aACZ,MAAO+tB,EACP,SAAW3vB,GAAM4vB,EAAa5vB,EAAE,OAAO,KAAK,IAE9C8B,OAAC,OAAI,UAAU,cACb,UAAAA,OAAC,UACC,UAAU,SACV,MAAO+tB,EACP,SAAW7vB,GAAM8vB,EAAgB9vB,EAAE,OAAO,KAAK,EAE/C,UAAA4B,MAAC,UAAO,MAAM,MAAM,eAAG,EACvBA,MAAC,UAAO,MAAM,SAAS,kBAAM,EAC7BA,MAAC,UAAO,MAAM,OAAO,gBAAI,KAE3BE,OAAC2D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,SAAU,CAACkqB,EAAU,QAAUQ,EAC/B,QAASuC,GAET,UAAA9wB,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,cACpB,EACF,GACF,EAGF5D,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OAAI,UAAU,cACb,UAAAF,MAACwB,GAAA,CAAc,KAAM,GAAI,EAAE,wBAC7B,EACAtB,OAAC,MAAG,UAAU,eACX,UAAAmkB,EAAS,SAAW,GAAKrkB,MAAC,MAAG,UAAU,QAAQ,4BAAgB,EAC/DqkB,EAAS,IAAI,CAAChK,EAAGjf,IAChB8E,OAAC,MAAkB,UAAU,eAC3B,UAAAA,OAAC,OAAI,UAAU,eACb,UAAAF,MAAC,UAAQ,SAAAqa,EAAE,QAAU,SAAS,EAC9Bna,OAAC,QAAK,UAAU,QACb,UAAAma,EAAE,KAAK,MAAI,IAAI,KAAKA,EAAE,EAAE,EAAE,gBAAe,EAC5C,GACF,EACCA,EAAE,MAAQra,MAAC,OAAI,UAAU,eAAgB,WAAE,KAAK,EAChDqa,EAAE,QACDna,OAAC,OAAI,UAAU,QAAQ,oBACdF,MAAC,QAAM,gBAAOqa,EAAE,MAAM,EAAE,GACjC,IAXK,KAAKjf,CAAC,EAaf,CACD,GACH,EACA8E,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,SACC,UAAU,QACV,YAAY,iBACZ,MAAO6tB,EACP,SAAWzvB,GAAM0vB,EAAe1vB,EAAE,OAAO,KAAK,EAC9C,UAAYA,GAAM,CACZA,EAAE,MAAQ,SAAW,CAACA,EAAE,UAAUyyB,GAAA,CACxC,IAEF3wB,OAAC2D,EAAA,CACC,QAAQ,YACR,KAAK,KACL,SAAU,CAACgqB,EAAY,QAAUY,EACjC,QAASoC,GAET,UAAA7wB,MAACyO,GAAA,CAAK,KAAM,GAAI,EAAE,UACpB,EACF,GACF,GACF,GAxKgDkf,EAAa,EAyK/D,GAEJ,EACF,GAEJ,CAEJ,CCzoCA,MAAM+D,GAAkB,CACtB,CAAE,MAAO,YAAa,MAAO,aAC7B,CAAE,MAAO,SAAU,MAAO,UAC1B,CAAE,MAAO,oBAAqB,MAAO,uBACrC,CAAE,MAAO,iBAAkB,MAAO,mBACpC,EAOO,SAASC,GAAqB,CAAE,SAAAjvB,EAAU,QAAAkvB,GAAkB,CACjE,MAAM3sB,EAAQC,GAAA,EACR,CAACsG,EAAQqmB,CAAS,EAAI11B,WAAgC,IAAI,EAC1D,CAACkL,EAAOC,CAAQ,EAAInL,WAA+B,IAAI,EACvD,CAAC21B,EAAeC,CAAgB,EAAI51B,WAAS,EAAK,EAClD,CAAC61B,EAAYC,CAAa,EAAI91B,WAAS,EAAK,EAC5C,CAAC+1B,EAAUC,CAAW,EAAIh2B,WAAS,EAAK,EACxC,CAACi2B,EAAYC,CAAa,EAAIl2B,WAAS,EAAK,EAC5C,CAACm2B,EAAeC,CAAgB,EAAIp2B,WAAS,EAAK,EAClD,CAACq2B,EAAeC,CAAgB,EAAIt2B,WAAS,EAAK,EAElDu2B,EAAa/0B,cAAY,SAAY,CACzCo0B,EAAiB,EAAI,EACrB,GAAI,CACF,KAAM,CAAC5rB,EAAGwsB,CAAE,EAAI,MAAM,QAAQ,IAAI,CAChC90B,EAAI,IAAoB,kBAAkB,EAC1CA,EAAI,IAAmB,0BAA0B,EAAE,MAAM,KAAO,CAAE,MAAO,YAAa,EACvF,EACDg0B,EAAU1rB,CAAC,EACNwsB,EAAG,OAAOrrB,EAASqrB,CAAE,CAC5B,OAAS50B,EAAK,CACZkH,EAAM,MAAM,mCAAoClH,EAAc,OAAO,EAAE,CACzE,SACEg0B,EAAiB,EAAK,CACxB,CACF,EAAG,CAAC9sB,CAAK,CAAC,EAEV/G,YAAU,IAAM,CACdw0B,EAAA,CACF,EAAG,CAACA,CAAU,CAAC,EAEf,MAAME,EAAgB,SAAY,CAChCX,EAAc,EAAI,EAClB,GAAI,CACF,MAAMvyB,EAAI,MAAM7B,EAAI,KAA0D,oBAAqB,CAAE,MAAO,GAAM,EAC9G6B,EAAE,WACJuF,EAAM,QAAQ,0BAA0BvF,EAAE,MAAM,GAAG,EACnD,MAAMgzB,EAAA,GAENztB,EAAM,MAAM,8DAA8D,CAE9E,OAASlH,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,SACEk0B,EAAc,EAAK,CACrB,CACF,EAEMY,EAAa,SAAY,CAC7BV,EAAY,EAAI,EAChB,GAAI,EACQ,MAAMt0B,EAAI,KAAsB,iBAAkB,CAAE,KAAM6E,EAAS,KAAM,GAC7E,IACJuC,EAAM,QAAQ,iCAAiC,EAC/C,MAAMytB,EAAA,GAENztB,EAAM,MAAM,cAAc,CAE9B,OAASlH,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,SACEo0B,EAAY,EAAK,CACnB,CACF,EAEMW,EAAe,SAAY,CAC/BT,EAAc,EAAI,EAClB,GAAI,EACQ,MAAMx0B,EAAI,KAAsB,kBAAkB,GACtD,IACJoH,EAAM,QAAQ,mCAAmC,EACjD,MAAMytB,EAAA,GAENztB,EAAM,MAAM,gBAAgB,CAEhC,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,SACEs0B,EAAc,EAAK,CACrB,CACF,EAEMU,EAAmB,SAAY,CACnCR,EAAiB,EAAI,EACrB,GAAI,EACQ,MAAM10B,EAAI,KAAsB,wBAAyB,CACjE,KAAM6E,EAAS,KACf,KAAMA,EAAS,KAChB,GACK,IACJuC,EAAM,QAAQ,6BAA6BvC,EAAS,IAAI,IAAIA,EAAS,IAAI,GAAG,EAC5E,MAAMgwB,EAAA,GAENztB,EAAM,MAAM,qBAAqB,CAErC,OAASlH,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,SACEw0B,EAAiB,EAAK,CACxB,CACF,EAEMS,EAAkB,SAAY,CAClCP,EAAiB,EAAI,EACrB,GAAI,EACQ,MAAM50B,EAAI,KAAsB,sBAAsB,GAC1D,IACJoH,EAAM,QAAQ,yBAAyB,EACvC,MAAMytB,EAAA,GAENztB,EAAM,MAAM,oBAAoB,CAEpC,OAASlH,EAAK,CACZkH,EAAM,MAAM,sBAAuBlH,EAAc,OAAO,EAAE,CAC5D,SACE00B,EAAiB,EAAK,CACxB,CACF,EAEMQ,EAAsB,SAAY,CACtC,GAAI,CACF,KAAM,CAAE,MAAAC,CAAA,EAAU,MAAAC,GAAA,sBAAAD,GAAA,KAAM,QAAO,uCAAoB,eAAAA,CAAA,OACnDA,EAAM,WAAY,CAAC,WAAW,EAAG,CAAE,SAAU,GAAM,MAAO,SAAU,CACtE,MAAQ,CACNjuB,EAAM,MAAM,uEAAuE,CACrF,CACF,EAEM,CAAE,UAAAmuB,EAAW,QAAAhxB,EAAS,aAAAixB,EAAc,UAAAC,EAAW,QAAAC,CAAA,EAAY/nB,GAAU,GACrEgoB,GAAQnsB,GAAA,YAAAA,EAAO,mBAAoB,EACnCosB,GAAQpsB,GAAA,YAAAA,EAAO,cAAe,EAEpC,aACG,OAAI,GAAG,oBAAoB,eAAa,WACvC,gBAACuD,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC2B,GAAA,CAAS,KAAM,GAAI,MAAO,CAAE,MAAO0xB,EAAe,iBAAmB,kBAAkB,CAAG,EAAE,WAE5FD,GAAahxB,GACZlC,OAAC,QAAK,MAAO,CAAE,SAAU,GAAI,MAAO,kBAAmB,WAAY,GAAK,cACpEkC,EAAQ,IAAEixB,EAAe,IAAM,KACnC,EAED,CAACD,GACApzB,MAAC,QAAK,MAAO,CAAE,SAAU,GAAI,MAAO,eAAgB,WAAY,GAAK,yBAAa,GAEtF,EACAA,MAACmL,IAAS,oJAGV,EAGAjL,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,GAAI,SAAU,OAAQ,UAAW,GAAI,aAAc,IACrF,UAAAA,OAAC,OAAI,UAAU,uBACZ,UAAAkzB,QACEM,GAAA,CAAY,KAAM,GAAI,MAAO,CAAE,MAAO,iBAAiB,CAAG,EAE3D1zB,MAACoe,IAAQ,KAAM,GAAI,MAAO,CAAE,MAAO,gBAAkB,EAEvDpe,MAAC,QAAM,SAAAozB,EAAY,YAAc,gBAAgB,GACnD,EACAlzB,OAAC,OAAI,UAAU,uBACZ,UAAAmzB,QACEK,GAAA,CAAY,KAAM,GAAI,MAAO,CAAE,MAAO,iBAAiB,CAAG,EAE3D1zB,MAACoe,IAAQ,KAAM,GAAI,MAAO,CAAE,MAAO,mBAAqB,SAEzD,QAAK,mBAAOiV,EAAe,GAAGC,CAAS,KAAO,WAAU,GAC3D,EACApzB,OAAC,OAAI,UAAU,uBACZ,UAAAqzB,QACEG,GAAA,CAAY,KAAM,GAAI,MAAO,CAAE,MAAO,iBAAiB,CAAG,EAE3D1zB,MAACoe,IAAQ,KAAM,GAAI,MAAO,CAAE,MAAO,mBAAqB,SAEzD,QAAK,sBAAUmV,EAAU,UAAY,eAAc,GACtD,GACF,GAGEE,EAAQ,GAAKD,EAAQ,WACpB,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,GAAI,aAAc,IACpD,UAAAtzB,OAAC,OACC,UAAAF,MAAC,OAAI,MAAO,CAAE,SAAU,GAAI,WAAY,IAAK,MAAO,kBACjD,SAAAwzB,EAAQ,EAAI,GAAG,KAAK,MAAMA,EAAQ,GAAG,CAAC,IAAM,IAC/C,EACAxzB,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,SAAU,IAAM,6BAAiB,GACnE,SACC,OACC,UAAAA,MAAC,OAAI,MAAO,CAAE,SAAU,GAAI,WAAY,IAAK,MAAO,iBACjD,SAAAyzB,EAAQ,EAAIA,EAAM,iBAAmB,IACxC,EACAzzB,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,SAAU,IAAM,8BAAkB,GACpE,GACF,EAIFE,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,SAAU,OAAQ,aAAc,GACpE,UAACkzB,EAMAlzB,OAAAO,WAAA,CACE,UAAAP,OAAC2D,EAAA,CACC,QAAQ,YACR,KAAK,KACL,QAASgvB,EACT,SAAUX,GAAYqB,EACtB,MAAOA,EAAU,8BAAgC,gDAEhD,UAAArB,EAAWlyB,MAAC,QAAK,UAAU,cAAc,EAAKA,MAAC7F,GAAA,CAAI,KAAM,GAAI,EAC7D+3B,EAAW,YAAcqB,EAAU,YAAc,mBAEnDA,GACCrzB,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASivB,EAAc,SAAUV,EAChE,UAAAA,EAAapyB,MAAC,QAAK,UAAU,cAAc,EAAKA,MAACG,GAAA,CAAU,KAAM,GAAI,EACrEiyB,EAAa,cAAgB,UAChC,GAEJ,EAtBAlyB,OAAC2D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAAS+uB,EAAe,SAAUZ,EACnE,UAAAA,EAAahyB,MAAC,QAAK,UAAU,cAAc,EAAKA,MAAC/I,GAAA,CAAS,KAAM,GAAI,EACpE+6B,EAAa,cAAgB,oBAChC,EAsBDoB,GACClzB,OAAAO,WAAA,CACG,UAAA4yB,EACCnzB,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAASmvB,EAAiB,SAAUR,EACvE,UAAAA,EAAgBxyB,MAAC,QAAK,UAAU,cAAc,EAAKA,MAACnG,GAAA,CAAO,KAAM,GAAI,EACrE24B,EAAgB,YAAc,cACjC,EAEAtyB,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASkvB,EAAkB,SAAUT,EACxE,UAAAA,EAAgBtyB,MAAC,QAAK,UAAU,cAAc,EAAKA,MAACud,GAAA,CAAK,KAAM,GAAI,EACnE+U,EAAgB,YAAc,eACjC,SAEDzuB,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASovB,EACzC,UAAAjzB,MAAC6L,GAAA,CAAa,KAAM,GAAI,EAAE,aAE5B,GACF,QAGDhI,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS6uB,EAAY,SAAUZ,EAC/D,SAAA9xB,MAACG,IAAU,KAAM,GAAI,UAAW2xB,EAAgB,OAAS,GAAI,EAC/D,GACF,SAGC,OAAI,MAAO,CAAE,UAAW,IACvB,UAAA5xB,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,QAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,QAASxzB,EAAE,OAAO,QAAS,IAExD4B,MAAC,QAAK,2BAAe,GACvB,EACAE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,YAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,YAAaxzB,EAAE,OAAO,QAAS,IAE5D4B,MAAC,QAAK,wDAA4C,GACpD,EACAE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,UAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,UAAWxzB,EAAE,OAAO,QAAS,IAE1D4B,MAAC,QAAK,iDAAqC,GAC7C,EACAE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,SAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,SAAUxzB,EAAE,OAAO,QAAS,IAEzD4B,MAAC,QAAK,mDAAuC,GAC/C,EACAE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,kBAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,kBAAmBxzB,EAAE,OAAO,QAAS,IAElE4B,MAAC,QAAK,sDAA0C,GAClD,EAEAE,OAAC,OAAI,UAAU,gBAAgB,MAAO,CAAE,UAAW,IACjD,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,sBAAU,EACzCA,MAAC,SACC,KAAK,SACL,UAAU,QACV,MAAO0C,EAAS,KAChB,IAAK,EACL,IAAK,MACL,SAAWtE,GAAMwzB,EAAQ,CAAE,KAAM,KAAK,IAAI,EAAG,KAAK,IAAI,MAAO,SAASxzB,EAAE,OAAO,MAAO,EAAE,GAAK,IAAI,CAAC,EAAG,GACvG,EACF,EACA8B,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,sBAAU,EACzCA,MAAC,SACC,KAAK,OACL,UAAU,QACV,MAAO0C,EAAS,KAChB,SAAWtE,GAAMwzB,EAAQ,CAAE,KAAMxzB,EAAE,OAAO,MAAO,GACnD,EACF,GACF,EAEA8B,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,mBAAO,EACtCA,MAAC,UACC,UAAU,SACV,MAAO0C,EAAS,QAChB,SAAWtE,GAAMwzB,EAAQ,CAAE,QAASxzB,EAAE,OAAO,MAAO,EAEnD,SAAAszB,GAAgB,IAAK5R,GACpB9f,MAAC,UAAqB,MAAO8f,EAAE,MAAQ,SAAAA,EAAE,OAA5BA,EAAE,KAAgC,CAChD,GACH,EACF,EACA5f,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gCAAoB,EACnDA,MAAC,SACC,KAAK,SACL,UAAU,QACV,MAAO0C,EAAS,OAChB,IAAK,EACL,KAAM,EACN,SAAWtE,GAAMwzB,EAAQ,CAAE,OAAQ,KAAK,IAAI,EAAG,WAAWxzB,EAAE,OAAO,KAAK,GAAK,CAAC,EAAG,IAEnF4B,MAAC,QAAK,UAAU,aAAa,yBAAa,GAC5C,GACF,EAEAE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,aAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,aAAcxzB,EAAE,OAAO,QAAS,IAE7D4B,MAAC,QAAK,gCAAoB,GAC5B,EACAE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,UAClB,SAAWtE,GAAMwzB,EAAQ,CAAE,UAAWxzB,EAAE,OAAO,QAAS,IAE1D4B,MAAC,QAAK,4BAAgB,GACxB,GACF,GACF,EACF,CAEJ,CCvWA,MAAM2zB,GAA+D,CACnE,CAAE,GAAI,OAAQ,MAAO,OAAQ,KAAMC,EAAA,EACnC,CAAE,GAAI,QAAS,MAAO,QAAS,KAAMC,EAAA,EACrC,CAAE,GAAI,SAAU,MAAO,SAAU,KAAMC,EAAA,CACzC,EAGMC,GAAgB,CACpB,CAAE,KAAM,SAAU,OAAQ,WAC1B,CAAE,KAAM,OAAQ,OAAQ,WACxB,CAAE,KAAM,QAAS,OAAQ,WACzB,CAAE,KAAM,SAAU,OAAQ,WAC1B,CAAE,KAAM,MAAO,OAAQ,WACvB,CAAE,KAAM,OAAQ,OAAQ,WACxB,CAAE,KAAM,OAAQ,OAAQ,WACxB,CAAE,KAAM,OAAQ,OAAQ,UAC1B,EAGMC,GAA4B,CAChC,QAAS,GACT,YAAa,GACb,KAAM,KACN,KAAM,YACN,aAAc,GACd,UAAW,GACX,OAAQ,EACR,QAAS,YACT,UAAW,GACX,SAAU,GACV,kBAAmB,EACrB,EAEMC,GAAgB,CACpB,QACA,YACA,WACA,SACA,iBACA,UACA,eACF,EAUA,SAASC,GAAgBjhB,EAAoB,CAC3C,GAAIA,GAAM,EAAG,MAAO,UACpB,MAAM9M,EAAI,KAAK,MAAM8M,EAAK,GAAI,EACxBpE,EAAI,KAAK,MAAM1I,EAAI,EAAE,EACrBzG,EAAIyG,EAAI,GACd,MAAO,GAAG0I,CAAC,IAAI,OAAOnP,CAAC,EAAE,SAAS,EAAG,GAAG,CAAC,EAC3C,CAEA,SAASy0B,IAAiB,CACxB,MAAMlvB,EAAQC,GAAA,EACR,CAACkvB,EAAMC,CAAO,EAAIl4B,WAA6B,IAAI,EACnD,CAACm4B,EAASC,CAAU,EAAIp4B,WAAS,EAAK,EACtC,CAACq4B,EAAWC,CAAY,EAAIt4B,WAAwB,IAAI,EACxD,CAACiX,EAAKshB,CAAM,EAAIv4B,WAAS,KAAK,KAAK,EAEnCmzB,EAAQ3xB,cAAY,SAAY,CACpC42B,EAAW,EAAI,EACfE,EAAa,IAAI,EACjB,GAAI,CACF,MAAMrqB,EAAM,MAAMvM,EAAI,KAAkB,aAAa,EACrDw2B,EAAQjqB,CAAG,CACb,OAASrM,EAAK,CACZ02B,GAAc12B,GAAA,YAAAA,EAAe,UAAW,yBAAyB,EACjEkH,EAAM,MAAM,iBAAiB,CAC/B,SACEsvB,EAAW,EAAK,CAClB,CACF,EAAG,CAACtvB,CAAK,CAAC,EAEV/G,YAAU,IAAM,CACd,GAAI,CAACk2B,EAAM,OACX,MAAM1vB,EAAI,YAAY,IAAMgwB,EAAO,KAAK,KAAK,EAAG,GAAI,EACpD,MAAO,IAAM,cAAchwB,CAAC,CAC9B,EAAG,CAAC0vB,CAAI,CAAC,EAET,MAAMO,EAAYP,EAAOA,EAAK,UAAYhhB,EAAM,EAC1CwhB,EAAUR,GAAQ,MAAQO,GAAa,EAE7C,OACEz0B,OAAC0K,EAAA,CAAK,GAAG,mBAAmB,eAAa,UACvC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC60B,GAAA,CAAW,KAAM,GAAI,EAAE,kBAC1B,SACC1pB,GAAA,CAAS,8BACSnL,MAAC,KAAE,KAAK,yCAAyC,OAAO,SAAS,IAAI,sBAAsB,2BAAe,EAAI,4CAEjI,EAEAE,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,GAAI,WAAY,aAAc,SAAU,QAC1E,UAAAF,MAAC,OAAI,MAAO,CAAE,KAAM,YACjB,SAAAo0B,GAAQ,CAACQ,EACR50B,MAAC,OAAI,MAAO,CAAE,WAAY,OAAQ,QAAS,GAAI,aAAc,IAC3D,SAAAA,MAAC80B,GAAA,CAAU,MAAOV,EAAK,UAAW,KAAM,IAAK,MAAM,IAAI,cAAe,GAAO,EAC/E,EAEAp0B,MAAC,OACC,MAAO,CACL,MAAO,IACP,OAAQ,IACR,aAAc,GACd,WAAY,4BACZ,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,MAAO,6BACP,SAAU,GACV,UAAW,SACX,QAAS,GACT,OAAQ,qCAGT,SAAAo0B,GAAQQ,EAAU,aAAe,wBAGxC,EAEA10B,OAAC,OAAI,MAAO,CAAE,KAAM,YAAa,SAAU,KACxC,WAACk0B,UACCvwB,EAAA,CAAO,QAAQ,UAAU,QAASyrB,EAAO,SAAUgF,EAClD,UAAAt0B,MAAC+0B,GAAA,CAAO,KAAM,GAAI,EAAE,IAAET,EAAU,cAAgB,oBAClD,EAGDF,GAAQ,CAACQ,GACR10B,OAAAO,WAAA,CACE,UAAAP,OAAC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAF,MAAC,UAAO,sBAAU,EAAS,UAAE,QAAK,UAAU,OAAQ,SAAAk0B,GAAgBS,CAAS,EAAE,GACjF,SACC,OAAI,MAAO,CAAE,aAAc,GAC1B,UAAA30B,MAAC,UAAO,gBAAI,EAAS,IAACA,MAAC,QAAK,UAAU,OAAO,MAAO,CAAE,UAAW,aAAgB,SAAAo0B,EAAK,UAAU,GAClG,SACC,OAAI,MAAO,CAAE,aAAc,IAC1B,UAAAp0B,MAAC,UAAO,kBAAM,EAAU,IACxBE,OAAC,QAAK,UAAU,OAAO,MAAO,CAAE,UAAW,YAAa,SAAU,IAC/D,UAAAk0B,EAAK,MAAM,MAAM,EAAG,EAAE,EAAE,IAAEA,EAAK,MAAM,MAAM,EAAE,GAChD,GACF,SACCvwB,EAAA,CAAO,QAAQ,YAAY,QAASyrB,EAAO,SAAUgF,EACpD,UAAAt0B,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,eACzB,GACF,EAGDi0B,GAAQQ,GACP10B,OAAAO,WAAA,CACE,UAAAT,MAAC,OAAI,MAAO,CAAE,aAAc,GAAI,MAAO,yBAA2B,8DAElE,EACAE,OAAC2D,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAM,CAAEwwB,EAAQ,IAAI,EAAG/E,EAAA,CAAS,EACjE,UAAAtvB,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,oBACzB,GACF,EAGDq0B,GACCx0B,MAAC,OAAI,MAAO,CAAE,UAAW,GAAI,MAAO,wBAAyB,SAAU,IACpE,SAAAw0B,CAAA,CACH,GAEJ,GACF,GACF,CAEJ,CAEA,MAAMQ,GAAU,CACd,CAAE,GAAI,SAAU,MAAO,WACvB,CAAE,GAAI,UAAW,MAAO,WACxB,CAAE,GAAI,OAAQ,MAAO,OACvB,EAUA,SAASC,IAAc,CACrB,MAAMhwB,EAAQC,GAAA,EACR,CAACsG,EAAQqmB,CAAS,EAAI11B,WASzB,CACD,QAAS,GACT,OAAQ,KACR,SAAU,GACV,SAAU,GACV,WAAY,GACZ,gBAAiB,GACjB,WAAY,EAAC,CACd,EAGD+B,YAAU,IAAM,CACd,MAAMg3B,EAAK,IAAIC,GACf,OAAAD,EAAG,GAAIl3B,GAAiC,EAClCA,EAAI,OAAS,mBAAqBA,EAAI,OAAS,cAAgBA,EAAI,OAAS,oBAC9E6zB,EAAW1rB,GAAM,CACf,GAAInI,EAAI,OAAS,kBACf,MAAO,CACL,GAAGmI,EACH,SAAU,GACV,gBAAiB,EAASnI,EAAsC,eAAe,EAGnF,GAAIA,EAAI,OAAS,aAAc,CAC7B,MAAM6Q,EAAI7Q,EACJo3B,EAAWjvB,EAAE,WAAW0I,EAAE,GAAG,GAAK,CAAE,KAAM,EAAC,EACjD,MAAO,CACL,GAAG1I,EACH,WAAY,CACV,GAAGA,EAAE,WACL,CAAC0I,EAAE,GAAG,EAAG,CACP,GAAGumB,EACH,KAAM,CAAC,IAAIA,EAAS,MAAQ,IAAI,MAAM,GAAG,EAAGvmB,EAAE,IAAI,EACpD,CACF,CAEJ,CAEA,MAAMA,EAAI7Q,EACV,MAAO,CACL,GAAGmI,EACH,WAAY,CACV,GAAGA,EAAE,WACL,CAAC0I,EAAE,GAAG,EAAG,CACP,GAAG1I,EAAE,WAAW0I,EAAE,GAAG,EACrB,OAAQA,EAAE,OACV,MAAOA,EAAE,MACT,WAAYA,EAAE,WAChB,CACF,CAEJ,CAAC,CAEL,CAAC,EACM,IAAMqmB,EAAG,OAClB,EAAG,EAAE,EAGLh3B,YAAU,IAAM,CACdL,EAAI,IAAgD,iBAAiB,EAClE,KAAM6B,GAAMmyB,EAAW1rB,IAAO,CAAE,GAAGA,EAAG,QAASzG,EAAE,SAAU,CAAC,EAC5D,MAAOtB,GAAMyzB,EAAW1rB,IAAO,CAAE,GAAGA,EAAG,MAAO/H,EAAE,SAAU,CAAC,CAChE,EAAG,EAAE,EAEL,MAAMi3B,EAAQ,SAAY,CACxBxD,EAAW1rB,IAAO,CAAE,GAAGA,EAAG,SAAU,GAAM,MAAO,QAAY,EAC7D,GAAI,CACF,MAAMzG,EAAI,MAAM7B,EAAI,IAIjB,gBAAgB,EACnBg0B,EAAW1rB,IAAO,CAChB,GAAGA,EACH,SAAU,GACV,QAASzG,EAAE,QACX,OAAQA,EAAE,OACV,WAAYA,EAAE,YACd,CACJ,OAAS3B,EAAK,CACZ8zB,EAAW1rB,IAAO,CAAE,GAAGA,EAAG,SAAU,GAAO,MAAQpI,EAAc,SAAU,CAC7E,CACF,EAEMu3B,EAAc,SAAY,CAC9B,GAAK,QAAQ,kEAAkE,EAC/E,CAAAzD,EAAW1rB,IAAO,CAChB,GAAGA,EACH,SAAU,GACV,gBAAiB,GACjB,WAAY,GACZ,MAAO,QACP,EACF,GAAI,CACF,MAAMtI,EAAI,KAAK,iBAAkB,CAAE,SAAU,CAAC,QAAS,aAAc,cAAc,EAAG,CAExF,OAASE,EAAK,CACZ8zB,EAAW1rB,IAAO,CAAE,GAAGA,EAAG,SAAU,GAAO,MAAQpI,EAAc,SAAU,CAC7E,EACF,EAEMw3B,EAAU,SAAY,CAC1B,GAAK,QAAQ,0DAA0D,EACvE,GAAI,CACF,MAAM13B,EAAI,KAAK,UAAU,EACzBoH,EAAM,KAAK,cAAe,GAAI,EAC9B,WAAW,IAAM,OAAO,SAAS,SAAU,GAAI,CACjD,MAAQ,CACNA,EAAM,MAAM,gBAAgB,CAC9B,CACF,EAEMuwB,EAAW,CACf,CAAE,GAAI,QAAS,KAAM,aACrB,CAAE,GAAI,aAAc,KAAM,aAC1B,CAAE,GAAI,eAAgB,KAAM,kBAAkB,EAG1CC,EAASjqB,EAAO,UAAYA,EAAO,SAEzC,OACEtL,OAAC0K,EAAA,CAAK,GAAG,mBAAmB,eAAa,UACvC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC/I,GAAA,CAAS,KAAM,GAAI,EAAE,YAAQ,EACzC+I,MAACmL,IAAS,uEAA2D,EAErEjL,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,MAAG,8BAAkB,QACrB,MACE,SAAAw1B,EAAS,IAAKx6B,UACZ,MACC,UAAAgF,MAAC,QAAM,WAAE,KAAK,EACdA,MAAC,QAAK,UAAU,OAAQ,WAAO,QAAQhF,EAAE,EAAE,GAAK,IAAI,IAF7CA,EAAE,EAGX,CACD,EACH,GACF,EAGCwQ,EAAO,QACNtL,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC,MAAG,4BAAgB,EACpBA,MAAC,MACE,SAAAw1B,EAAS,IAAKx6B,GAAM,OACnB,MAAM2M,EAAM6D,EAAO,QAAQxQ,EAAE,EAAE,EACzB06B,GAAMz3B,EAAAuN,EAAO,SAAP,YAAAvN,EAAgBjD,EAAE,IACxB26B,EAAahuB,GAAO+tB,GAAO/tB,IAAQ+tB,EACzC,OACEx1B,OAAC,MAAc,UAAWy1B,EAAa,mBAAqB,0BAC1D,UAAA31B,MAAC,QAAM,WAAE,KAAK,EACdE,OAAC,QAAK,UAAU,OACb,UAAAw1B,GAAO,IACPC,GAAc31B,MAAC,QAAK,UAAU,gBAAgB,4BAAgB,GACjE,IALOhF,EAAE,EAMX,CAEJ,CAAC,EACH,GACF,EAIDwQ,EAAO,UACNxL,MAAC,OAAI,UAAU,wBACZ,SAAAw1B,EAAS,IAAKx6B,GAAM,CACnB,MAAM46B,EAAYpqB,EAAO,WAAWxQ,EAAE,EAAE,GAAK,CAAE,OAAQ,OAAQ,KAAM,EAAC,EACtE,OACEkF,OAAC,OAAe,UAAU,kBACxB,UAAAA,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC,QAAK,UAAU,mBAAoB,SAAAhF,EAAE,KAAK,EAC3CkF,OAAC,OAAI,UAAU,qBACZ,UAAA01B,EAAU,SAAW,YAAc51B,MAAC,QAAK,UAAU,cAAc,EACjE41B,EAAU,SAAW,cAAgB51B,MAAC,QAAK,UAAU,cAAc,EACnE41B,EAAU,SAAW,QAAU51B,MAAC0zB,IAAY,KAAM,GAAI,UAAU,eAAe,EAC/EkC,EAAU,SAAW,SAAW51B,MAACK,IAAY,KAAM,GAAI,UAAU,aAAa,EAC/EL,MAAC,QAAM,SAAA41B,EAAU,OAAO,EACvBA,EAAU,YACT11B,OAAC,QAAK,UAAU,OAAO,MAAO,CAAE,SAAU,IAAM,eAAG01B,EAAU,YAAW,GAE5E,GACF,EACCA,EAAU,KAAK,OAAS,GACvB11B,OAAC,WAAQ,UAAU,mBACjB,UAAAA,OAAC,WAAQ,yBAAa01B,EAAU,KAAK,OAAO,WAAO,QAClD,OAAK,SAAAA,EAAU,KAAK,KAAK;AAAA,CAAI,EAAE,GAClC,EAEDA,EAAU,SAAW,SAAWA,EAAU,OACzC11B,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,EAAE,IAAE6uB,EAAU,OACzC,IAvBM56B,EAAE,EAyBZ,CAEJ,CAAC,EACH,EAIFkF,OAAC,OAAI,UAAU,kBACb,UAAAA,OAAC2D,EAAA,CAAO,QAASwxB,EAAO,SAAUI,EAC/B,UAAAjqB,EAAO,eAAY,QAAK,UAAU,cAAc,EAAKxL,MAACG,GAAA,CAAU,KAAM,GAAI,EAAG,qBAEhF,EACAD,OAAC2D,EAAA,CACC,QAAQ,UACR,QAASyxB,EACT,SAAU,CAAC9pB,EAAO,YAAcA,EAAO,SAEtC,UAAAA,EAAO,eAAY,QAAK,UAAU,cAAc,EAAKxL,MAAC/I,GAAA,CAAS,KAAM,GAAI,EACzEuU,EAAO,SAAW,YAAeA,EAAO,WAAa,aAAe,gBAEtEA,EAAO,iBACNtL,OAAC2D,GAAO,QAAQ,SAAS,QAAS0xB,EAChC,UAAAv1B,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,sBACzB,GAEJ,EAECqL,EAAO,OACNtL,OAAC,OAAI,UAAU,gBACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,EACzB/G,MAAC,QAAM,SAAAwL,EAAO,MAAM,GACtB,GAEJ,CAEJ,CAEA,SAASqqB,GAAkB,CAAE,SAAUC,EAAS,gBAAAxpB,GAA0B,sBACxE,MAAMrH,EAAQC,GAAA,EACR,CAACxC,EAAUqzB,CAAW,EAAI55B,WAAmB25B,CAAO,EACpD,CAACE,EAAOC,CAAQ,EAAI95B,WAAS,EAAK,EAClC,CAAC+5B,EAAQC,CAAS,EAAIh6B,WAAS,EAAK,EACpC,CAACi6B,EAAWC,CAAY,EAAIl6B,WAAiC,IAAI,EACjE,CAACm6B,EAAgBC,CAAiB,EAAIp6B,WAAS,CAAE,KAAM,KAAM,MAAO,GAAM,SAAU,GAAI,EACxF,CAACq6B,EAAeC,CAAgB,EAAIt6B,WAAiC,EAAE,EAE7E+B,YAAU,IAAM,CACd63B,EAAYD,CAAO,EACnBG,EAAS,EAAK,EACVH,EAAQ,OAAOY,GAAiBZ,EAAQ,KAAK,CACnD,EAAG,CAACA,CAAO,CAAC,EAEZ53B,YAAU,IAAM,CACTk4B,GACLG,EAAkB,CAChB,KAAMH,EAAU,SAAS,KACzB,MAAOA,EAAU,SAAS,QAAU,GACpC,SAAUA,EAAU,SAAS,UAAY,GAC1C,CACH,EAAG,CAACA,CAAS,CAAC,EAEdl4B,YAAU,IAAM,CACdL,EAAI,IAAqB,mBAAmB,EAAE,KAAKw4B,CAAY,EAAE,MAAM,MAAe,CACxF,EAAG,EAAE,EAELn4B,YAAU,IAAM,CACdL,EAAI,IAA4B,0BAA0B,EACvD,KAAK44B,CAAgB,EACrB,MAAM,IAAM,CAAyC,CAAC,CAC3D,EAAG,EAAE,EAEL,MAAME,EAAcC,GAAsC,CACxDb,EAAapuB,GAAQ,CACnB,MAAMtI,EAAO,CAAE,GAAGsI,EAAK,MAAO,CAAE,GAAGA,EAAI,MAAO,GAAGivB,EAAM,EACvD,OAAAF,GAAiBr3B,EAAK,KAAK,EACpBA,CACT,CAAC,EACD42B,EAAS,EAAI,CACf,EAEMY,EAAWD,GAAmC,CAClDb,EAAapuB,IAAS,CAAE,GAAGA,EAAK,GAAI,CAAE,GAAGA,EAAI,GAAI,GAAGivB,CAAA,GAAU,EAC9DX,EAAS,EAAI,CACf,EAEMa,EAAW,CAA2BppB,EAAQ/R,IAAuB,CACzEo6B,EAAapuB,IAAS,CAAE,GAAGA,EAAK,CAAC+F,CAAG,EAAG/R,CAAA,EAAQ,EAC/Cs6B,EAAS,EAAI,CACf,EAEMc,EAAsBH,GAA8C,CACxEb,EAAapuB,IAAS,CAAE,GAAGA,EAAK,cAAe,CAAE,GAAGA,EAAI,cAAe,GAAGivB,CAAA,GAAU,EACpFX,EAAS,EAAI,CACf,EAEMe,EAAeJ,GAAuC,CAC1Db,EAAapuB,IAAS,CAAE,GAAGA,EAAK,OAAQ,CAAE,GAAGA,EAAI,OAAQ,GAAGivB,CAAA,GAAU,EACtEX,EAAS,EAAI,CACf,EAUMgB,EAAsD,CAC1D,CAAE,GAAI,QAAS,MAAO,SACtB,CAAE,GAAI,SAAU,MAAO,UACvB,CAAE,GAAI,UAAW,MAAO,WACxB,CAAE,GAAI,UAAW,MAAO,WACxB,CAAE,GAAI,YAAa,MAAO,aAC1B,CAAE,GAAI,gBAAiB,MAAO,iBAC9B,CAAE,GAAI,OAAQ,MAAO,QACrB,CAAE,GAAI,SAAU,MAAO,UACvB,CAAE,GAAI,YAAa,MAAO,aAC1B,CAAE,GAAI,aAAc,MAAO,cAC3B,CAAE,GAAI,aAAc,MAAO,cAC3B,CAAE,GAAI,WAAY,MAAO,YACzB,CAAE,GAAI,UAAW,MAAO,WACxB,CAAE,GAAI,eAAgB,MAAO,YAC7B,CAAE,GAAI,QAAS,MAAO,QAAQ,EAE1B,CAACC,EAAeC,CAAgB,EAAIh7B,WAAwB,IAAM,CAEtE,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,MAAMi7B,EAAO,OAAO,SAAS,KAAK,QAAQ,cAAe,EAAE,EAC3D,OAAOH,EAAc,KAAM9wB,GAAMA,EAAE,KAAOixB,CAAI,EAAIA,EAAO,IAC3D,CAAC,EACKC,EAAiBpvB,GAAsB,CAC3CkvB,EAAiBlvB,CAAE,EACnB,GAAI,CACF,MAAMyC,EAAMzC,EAAK,aAAaA,CAAE,GAAK,OAAO,SAAS,SAErD,GADA,QAAQ,aAAa,KAAM,GAAIyC,CAAG,EAC9BzC,EAAI,CACN,MAAMgO,EAAK,SAAS,eAAe,YAAYhO,CAAE,EAAE,EAC/CgO,KAAO,eAAe,CAAE,SAAU,SAAU,MAAO,QAAS,CAClE,MACE,OAAO,SAAS,CAAE,IAAK,EAAG,SAAU,SAAU,CAElD,MAAQ,CAAe,CACzB,EAMMqhB,EAAkBV,GAA0C,CAChEb,EAAapuB,IAAS,CAAE,GAAGA,EAAK,UAAW,CAAE,GAAGA,EAAI,UAAW,GAAGivB,CAAA,GAAU,EAC5EX,EAAS,EAAI,CACf,EAEMsB,EAAS,SAAY,CACzBpB,EAAU,EAAI,EACd,GAAI,CACF,MAAMz2B,EAAI,MAAM7B,EAAI,IAAsB,YAAa6E,CAAQ,EAC/DqzB,EAAYr2B,EAAE,IAAI,EAClBu2B,EAAS,EAAK,EACduB,GAAW93B,EAAE,KAAK,KAAK,EACvBg3B,GAAiBh3B,EAAE,KAAK,KAAK,EAC7BuF,EAAM,QAAQ,iBAAiB,EAC/B,MAAMqH,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,SACEo4B,EAAU,EAAK,CACjB,CACF,EAEMsB,EAAW,SAAY,CAC3B,GAAI,CACF,MAAM/3B,EAAI,MAAM7B,EAAI,IAAsB,WAAW,EACrDk4B,EAAYr2B,EAAE,IAAI,EAClBu2B,EAAS,EAAK,EACduB,GAAW93B,EAAE,KAAK,KAAK,EACvBg3B,GAAiBh3B,EAAE,KAAK,KAAK,EAC7BuF,EAAM,KAAK,qBAAsB,IAAI,CACvC,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEM25B,EAAU,SAAY,CAC1B,GAAK,QAAQ,iCAAiC,EAC9C,GAAI,CACF,MAAMh4B,EAAI,MAAM7B,EAAI,KAAuB,iBAAiB,EAC5Dk4B,EAAYr2B,EAAE,IAAI,EAClBu2B,EAAS,EAAK,EACduB,GAAW93B,EAAE,KAAK,KAAK,EACvBg3B,GAAiBh3B,EAAE,KAAK,KAAK,EAC7BuF,EAAM,QAAQ,iBAAiB,EAC/B,MAAMqH,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,iBAAkBlH,EAAc,OAAO,EAAE,CACvD,CACF,EAEM45B,EAAoB,SAAY,CACpC,GAAI,CACEvB,GAAA,MAAAA,EAAW,SAAS,SACtB,MAAMv4B,EAAI,KAAK,oBAAoB,EACnCoH,EAAM,QAAQ,2BAA2B,IAEzC,MAAMpH,EAAI,KAAK,oBAAqB,CAClC,KAAMy4B,EAAe,MAAQ,KAC7B,MAAOA,EAAe,MACtB,SAAUA,EAAe,UAAY,GACtC,EACDrxB,EAAM,QAAQ,0BAA0B,GAE1C,MAAMvF,EAAI,MAAM7B,EAAI,IAAqB,mBAAmB,EAC5Dw4B,EAAa32B,CAAC,CAChB,OAAS3B,EAAK,CACZkH,EAAM,MAAM,qBAAsBlH,EAAc,OAAO,EAAE,CAC3D,CACF,EAEM65B,EAAQl1B,EAAS,OAAS,CAC9B,QAAS,QACT,SAAU,yCACV,QAAS,OAOL,CAACm1B,EAAWC,CAAY,EAAI37B,WAAiB0B,EAAI,UAAU,EAC3D,CAACk6B,EAAYC,CAAa,EAAI77B,WAAwE,IAAI,EAC1G,CAAC87B,EAAeC,EAAgB,EAAI/7B,WAAiB,EAAE,EAK7D+B,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAC,SAAY,CACX,GAAI,CACF,MAAMrG,EAAI,MAAM7B,EAAI,kBACfkI,GAAWiyB,EAAct4B,CAAC,CACjC,MAAQ,CACDqG,GACHiyB,EAAc,CAAE,SAAU,GAAM,SAAU,GAAO,KAAM,GAAI,CAK/D,CACF,KACO,IAAM,CAAEjyB,EAAY,EAAM,CACnC,EAAG,EAAE,EAEL,MAAMoyB,GAAc,SAAY,CAC9B,GAAI,CACF,MAAMz4B,EAAI,MAAM7B,EAAI,IAAuB,cAAc,EACzDq6B,GAAiBx4B,EAAE,KAAK,EACxBo4B,EAAap4B,EAAE,KAAK,EACpB7B,EAAI,SAAS6B,EAAE,KAAK,EACpB,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,EAAE,KAAK,EAC3CuF,EAAM,QAAQ,4BAA4B,CAC5C,MAAQ,CACNA,EAAM,QAAQ,6CAA6C,CAC7D,CACF,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEMq6B,EAAoB,SAAY,CACpC,GAAK,QAAQ,0GAA0G,EAGvH,GAAI,CACF,MAAM14B,EAAI,MAAM7B,EAAI,KAAwB,kBAAkB,EAC9Dq6B,GAAiBx4B,EAAE,KAAK,EACxBo4B,EAAap4B,EAAE,KAAK,EACpB7B,EAAI,SAAS6B,EAAE,KAAK,EACpB,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,EAAE,KAAK,EAC3CuF,EAAM,QAAQ,8CAA8C,CAC9D,MAAQ,CACNA,EAAM,QAAQ,4EAA4E,CAC5F,CACF,OAASlH,EAAK,CACZkH,EAAM,MAAM,sBAAuBlH,EAAc,OAAO,EAAE,CAC5D,CACF,EAEMs6B,EAAc,IAAM,CACxBx6B,EAAI,SAASg6B,EAAU,MAAM,EAC7B5yB,EAAM,QAAQ,6DAA6D,CAC7E,EAEA,OACE/E,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC+B,GAAA,CAAQ,KAAM,GAAI,EAAE,aACvB,EACA7B,OAAC,KAAE,UAAU,gBAAgB,uDACgB,IAC3CF,MAAC,QAAK,yCAA6B,EAAO,KAC5C,GACF,EACAE,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC2D,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS6zB,EACzC,UAAA13B,MAACs4B,GAAA,CAAU,KAAM,GAAI,EAAE,UACzB,SACCz0B,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS4zB,EAC7C,UAAAz3B,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,WACzB,EACAD,OAAC2D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,SAAU,CAACmyB,GAASE,EACpB,QAASqB,EAER,UAAArB,EAASl2B,MAAC,QAAK,UAAU,cAAc,EAAKA,MAACkd,GAAA,CAAK,KAAM,GAAI,EAC5DgZ,EAAS,UAAY,SACxB,EACF,GACF,EAEAh2B,OAAC,OAAI,UAAU,kBAAkB,aAAW,oBAC1C,UAAAF,MAAC,UACC,KAAK,SACL,UAAWiD,EAAG,yBAA0B,6BAA8Bi0B,IAAkB,MAAQ,+BAA+B,EAC/H,QAAS,IAAMG,EAAc,IAAI,EACjC,MAAM,6BACP,iBAGAJ,EAAc,IAAK9wB,GAClBnG,MAAC,UAEC,KAAK,SACL,UAAWiD,EAAG,yBAA0Bi0B,IAAkB/wB,EAAE,IAAM,+BAA+B,EACjG,QAAS,IAAMkxB,EAAclxB,EAAE,EAAE,EAEhC,SAAAA,EAAE,OALEA,EAAE,GAOV,GACH,EAEAjG,OAAC,OACC,UAAW+C,EAAG,gBAAiBi0B,GAAiB,wBAAwB,EACxE,sBAAqBA,GAAiB,OAIrC,UAAAA,GACCh3B,OAAC,OAAI,UAAU,yBACb,UAAAA,OAAC,QAAK,0BACSF,MAAC,UAAQ,UAAA/B,GAAAg5B,EAAc,KAAM9wB,GAAMA,EAAE,KAAO+wB,CAAa,IAAhD,YAAAj5B,GAAmD,MAAM,EAAS,KAC1F,EACA+B,MAAC,UACC,KAAK,SACL,UAAU,wBACV,QAAS,IAAMq3B,EAAc,IAAI,EAClC,8BAED,EACF,QAED,OAAI,eAAa,QAAQ,MAAO,CAAC,QAAUH,IAAkB,MAAQA,IAAkB,QAAW,QAAU,QACrH,SAAAh3B,OAAC0K,GAAK,GAAG,iBAAiB,eAAa,QAC7B,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACjH,GAAA,CAAQ,KAAM,GAAI,EAAE,UAAM,EACtCiH,MAACmL,IAAS,gEAAoD,EAG9DjL,OAAC,OAAI,UAAU,QAAQ,kBAAgB,gBACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,0BAAc,QAC5C,OAAI,UAAU,gBACZ,SAAA+zB,GAAc,IAAKrvB,GAClBxE,OAAC,UAEC,KAAK,SACL,UAAW+C,EACT,eACAP,EAAS,MAAM,SAAWgC,EAAE,QAAU,uBAExC,QAAS,IAAMiyB,EAAW,CAAE,OAAQjyB,EAAE,OAAQ,EAC9C,MAAOA,EAAE,KAET,UAAA1E,MAAC,QACC,UAAU,sBACV,MAAO,CAAE,WAAY0E,EAAE,OAAO,GAEhC1E,MAAC,QAAK,UAAU,oBAAqB,WAAE,KAAK,IAbvC0E,EAAE,KAeV,EACH,GACF,EAEAxE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,aACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,OAAI,UAAU,YACZ,SAAA2zB,GAAO,IAAI,CAAC,CAAE,GAAA1rB,EAAI,MAAAiZ,EAAO,KAAA/d,CAAA,IAAW,CACnC,MAAMC,EAASV,EAAS,MAAM,OAASuF,EACvC,OACE/H,OAAC,UAEC,KAAK,SACL,UAAW+C,EAAG,aAAcG,GAAU,mBAAmB,EACzD,QAAS,IAAMuzB,EAAW,CAAE,KAAM1uB,EAAI,EAEtC,UAAAjI,MAACmD,EAAA,CAAK,KAAM,GAAI,EAChBnD,MAAC,QAAK,UAAU,mBAAoB,SAAAkhB,EAAM,EAC1ClhB,MAAC,QACC,UAAWiD,EACT,oBACA,qBAAqBgF,CAAE,GACzB,EACF,GAZKA,CAAA,CAeX,CAAC,EACH,GACF,EAEA/H,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,QAAQ,kBAAgB,eACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCE,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SACC,KAAK,QACL,UAAU,oBACV,MAAO0C,EAAS,MAAM,OACtB,SAAWtE,GAAMu4B,EAAW,CAAE,OAAQv4B,EAAE,OAAO,MAAO,EACtD,aAAW,iBAEb4B,MAAC,SACC,KAAK,OACL,UAAU,QACV,MAAO0C,EAAS,MAAM,OACtB,SAAWtE,GAAMu4B,EAAW,CAAE,OAAQv4B,EAAE,OAAO,MAAO,GACxD,EACF,GACF,EACA8B,OAAC,OAAI,UAAU,QAAQ,kBAAgB,gBACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,mBAAO,EACtCE,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SACC,KAAK,QACL,UAAU,oBACV,MAAO0C,EAAS,MAAM,QACtB,SAAWtE,GAAMu4B,EAAW,CAAE,QAASv4B,EAAE,OAAO,MAAO,EACvD,aAAW,kBAEb4B,MAAC,SACC,KAAK,OACL,UAAU,QACV,MAAO0C,EAAS,MAAM,QACtB,SAAWtE,GAAMu4B,EAAW,CAAE,QAASv4B,EAAE,OAAO,MAAO,GACzD,EACF,GACF,EACA8B,OAAC,OAAI,UAAU,QAAQ,kBAAgB,gBACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,mBAAO,EACtCE,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SACC,KAAK,QACL,UAAU,oBACV,MAAO0C,EAAS,MAAM,QACtB,SAAWtE,GAAMu4B,EAAW,CAAE,QAASv4B,EAAE,OAAO,MAAO,EACvD,aAAW,kBAEb4B,MAAC,SACC,KAAK,OACL,UAAU,QACV,MAAO0C,EAAS,MAAM,QACtB,SAAWtE,GAAMu4B,EAAW,CAAE,QAASv4B,EAAE,OAAO,MAAO,GACzD,EACF,GACF,EACA8B,OAAC,OAAI,UAAU,QAAQ,kBAAgB,cACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,iBAAK,EACpCE,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SACC,KAAK,QACL,UAAU,oBACV,MAAO0C,EAAS,MAAM,MACtB,SAAWtE,GAAMu4B,EAAW,CAAE,MAAOv4B,EAAE,OAAO,MAAO,EACrD,aAAW,gBAEb4B,MAAC,SACC,KAAK,OACL,UAAU,QACV,MAAO0C,EAAS,MAAM,MACtB,SAAWtE,GAAMu4B,EAAW,CAAE,MAAOv4B,EAAE,OAAO,MAAO,GACvD,EACF,GACF,EACA8B,OAAC,OAAI,UAAU,QAAQ,kBAAgB,aACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCE,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,SACC,KAAK,QACL,UAAU,oBACV,MAAO0C,EAAS,MAAM,KACtB,SAAWtE,GAAMu4B,EAAW,CAAE,KAAMv4B,EAAE,OAAO,MAAO,EACpD,aAAW,eAEb4B,MAAC,SACC,KAAK,OACL,UAAU,QACV,MAAO0C,EAAS,MAAM,KACtB,SAAWtE,GAAMu4B,EAAW,CAAE,KAAMv4B,EAAE,OAAO,MAAO,GACtD,EACF,GACF,GACF,EAEA8B,OAAC,OAAI,UAAU,QAAQ,kBAAgB,mBACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,uBAAW,EAC1CA,MAAC,UACC,UAAU,SACV,MAAO0C,EAAS,MAAM,WACtB,SAAWtE,GAAMu4B,EAAW,CAAE,WAAYv4B,EAAE,OAAO,MAAO,EAEzD,SAAA61B,GAAc,IAAK5pB,GAClBrK,MAAC,UAAe,MAAOqK,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,EACF,EACAnK,OAAC,OAAI,UAAU,QAAQ,kBAAgB,iBACrC,UAAAA,OAAC,SAAM,UAAU,cAAc,wBAAYwC,EAAS,MAAM,SAAS,MAAE,EACrE1C,MAAC,SACC,KAAK,QACL,IAAK,GACL,IAAK,GACL,MAAO0C,EAAS,MAAM,SACtB,SAAWtE,GAAMu4B,EAAW,CAAE,SAAU,OAAOv4B,EAAE,OAAO,KAAK,EAAG,GAClE,EACF,EACA8B,OAAC,SAAM,UAAU,eAAe,kBAAgB,oBAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,MAAM,YACxB,SAAWtE,GAAMu4B,EAAW,CAAE,YAAav4B,EAAE,OAAO,QAAS,IAE/D4B,MAAC,QAAK,oCAAwB,GAChC,EACAE,OAAC,SAAM,UAAU,eAAe,kBAAgB,mBAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,MAAM,WACxB,SAAWtE,GAAMu4B,EAAW,CAAE,WAAYv4B,EAAE,OAAO,QAAS,IAE9D4B,MAAC,QAAK,6BAAiB,GACzB,GACF,EACR,QAES,OAAI,eAAa,UAAU,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,UAAa,QAAU,QAC/G,SAAAl3B,MAACi1B,KAAY,EACf,QAEC,OAAI,eAAa,SAAS,MAAO,CAAC,QAAUiC,IAAkB,MAAQA,IAAkB,SAAY,QAAU,QACvH,SAAAh3B,OAAC0K,GAAK,GAAG,kBAAkB,eAAa,SAC9B,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACu4B,GAAA,CAAW,KAAM,GAAI,EAAE,cAAU,EAC7Cv4B,MAACmL,IAAS,+DAAmD,EAC7DnL,MAAC,OAAI,UAAU,aAAa,kBAAgB,YACzC,SAAAg1B,GAAQ,IAAKjU,GACZ/gB,MAAC,UAEC,KAAK,SACL,UAAWiD,EAAG,cAAeP,EAAS,GAAG,SAAWqe,EAAE,IAAM,oBAAoB,EAChF,QAAS,IAAM8V,EAAQ,CAAE,OAAQ9V,EAAE,GAAI,EAEvC,SAAA/gB,MAAC,QAAK,UAAU,oBAAqB,WAAE,MAAM,GALxC+gB,EAAE,GAOV,EACH,EACA7gB,OAAC,SAAM,UAAU,eAAe,kBAAgB,gBAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,GAAG,WACrB,SAAWtE,GAAMy4B,EAAQ,CAAE,WAAYz4B,EAAE,OAAO,QAAS,IAE3D4B,MAAC,QAAK,uBAAW,GACnB,EACAE,OAAC,SAAM,UAAU,eAAe,kBAAgB,mBAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,GAAG,cACrB,SAAWtE,GAAMy4B,EAAQ,CAAE,cAAez4B,EAAE,OAAO,QAAS,IAE9D4B,MAAC,QAAK,2BAAe,GACvB,EACAE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,gBACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,uBAAW,EAC1CE,OAAC,UACC,UAAU,SACV,MAAOwC,EAAS,GAAG,WACnB,SAAWtE,GAAMy4B,EAAQ,CAAE,WAAYz4B,EAAE,OAAO,MAAO,EAEvD,UAAA4B,MAAC,UAAO,MAAM,WAAW,oBAAQ,EACjCA,MAAC,UAAO,MAAM,OAAO,gBAAI,EACzBA,MAAC,UAAO,MAAM,SAAS,kBAAM,EAC7BA,MAAC,UAAO,MAAM,YAAY,iBAAK,EAC/BA,MAAC,UAAO,MAAM,WAAW,oBAAQ,EACjCA,MAAC,UAAO,MAAM,QAAQ,iBAAK,EAC3BA,MAAC,UAAO,MAAM,SAAS,kBAAM,EAC7BA,MAAC,UAAO,MAAM,WAAW,oBAAQ,EACjCA,MAAC,UAAO,MAAM,OAAO,gBAAI,EACzBA,MAAC,UAAO,MAAM,YAAY,qBAAS,IACrC,EACF,GACF,EACR,QAES,OAAI,eAAa,UAAU,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,UAAa,QAAU,QACzH,SAAAh3B,OAAC0K,GAAK,GAAG,mBAAmB,eAAa,UAC/B,UAAA5K,MAACkL,IAAU,mBAAO,EAClBlL,MAACmL,IAAS,2CAA+B,EACzCjL,OAAC,OAAI,UAAU,QAAQ,kBAAgB,eACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,oBAAoB,yBAAa,EACxEA,MAAC,SACC,GAAG,oBACH,UAAU,QACV,KAAK,OACL,YAAY,YACZ,MAAO0C,EAAS,cAAgB,GAChC,SAAWtE,GAAM04B,EAAS,eAAgB14B,EAAE,OAAO,KAAK,GAC1D,EACF,EACA8B,OAAC,OAAI,UAAU,QAAQ,kBAAgB,eACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,oBAAoB,0BAAc,EACzEA,MAAC,SACC,GAAG,oBACH,UAAU,QACV,KAAK,OACL,YAAY,qCACZ,MAAO0C,EAAS,cAAgB,GAChC,SAAWtE,GAAM04B,EAAS,eAAgB14B,EAAE,OAAO,KAAK,GAC1D,EACF,GACF,EACR,QAES,OAAI,eAAa,UAAU,MAAO,CAAC,QAAU84B,IAAkB,MAAQA,IAAkB,UAAa,QAAU,QACzH,SAAAh3B,OAAC0K,GAAK,GAAG,mBAAmB,eAAa,UAC/B,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACw4B,GAAA,CAAW,KAAM,GAAI,EAAE,YAAQ,EAC3Cx4B,MAACmL,IAAS,kDAAsC,EAChDnL,MAAC,OAAI,kBAAgB,kBAClB,WACCE,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,KAAE,2BACQ,UAAQ,SAAAk2B,GAAA,MAAAA,EAAW,SAAS,QAAU,UAAY,WAAW,EACrE,IAAI,0BAAuBp2B,MAAC,UAAQ,SAAAo2B,EAAU,UAAY,MAAQ,KAAK,EACvE,IAAI,oBAAiBp2B,MAAC,UAAQ,SAAAo2B,EAAU,cAAgB,MAAQ,KAAK,GACxE,EACAl2B,OAAC,KAAE,UAAU,QAAQ,iBACfF,MAAC,QAAK,+BAAmB,EAAO,MAAGA,MAAC,QAAK,8BAAkB,EAAO,4CAExE,GACF,EAEAA,MAAC,KAAE,UAAU,QAAQ,mCAAuB,EAEhD,GACF,EACR,QAES,OAAI,eAAa,YAAY,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,YAAe,QAAU,QAC7H,SAAAh3B,OAAC0K,GAAK,GAAG,qBAAqB,eAAa,YACjC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC5G,GAAA,CAAK,KAAM,GAAI,EAAE,oBAAgB,EAC7C4G,MAACmL,IAAS,6DAAiD,EAC1DirB,EACCl2B,OAAAO,WAAA,CACE,UAAAP,OAAC,KAAE,wBACUF,MAAC,UAAQ,SAAAo2B,EAAU,UAAY,MAAQ,KAAK,EAAU,IAChEA,EAAU,SAAWl2B,OAAC,QAAK,UAAU,QAAQ,cAAEk2B,EAAU,QAAQ,KAAC,GACrE,SACC,KAAE,4BACcp2B,MAAC,UAAQ,SAAAo2B,EAAU,cAAgB,MAAQ,KAAK,GACjE,SACC,KAAE,kCACe,UAAQ,SAAAA,EAAU,SAAS,QAAU,MAAQ,KAAK,GACpE,EACAl2B,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,SACC,KAAK,SACL,UAAU,QACV,MAAOs2B,EAAe,KACtB,SAAWl4B,GAAMm4B,EAAmB5uB,IAAS,CAAE,GAAGA,EAAK,KAAM,OAAOvJ,EAAE,OAAO,KAAK,GAAK,MAAO,GAChG,EACF,EACA8B,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,qBAAS,EACxCA,MAAC,SACC,KAAK,WACL,QAASs2B,EAAe,MACxB,SAAWl4B,GAAMm4B,EAAmB5uB,IAAS,CAAE,GAAGA,EAAK,MAAOvJ,EAAE,OAAO,SAAU,GACnF,EACF,GACF,EACA4B,MAAC6D,EAAA,CAAO,QAAQ,UAAU,QAAS8zB,EAChC,SAAAvB,EAAU,SAAS,QAAU,gBAAkB,eAClD,GACF,EAEAp2B,MAAC,KAAE,UAAU,QAAQ,qCAAyB,GAElD,EACR,QAES,OAAI,eAAa,gBAAgB,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,gBAAmB,QAAU,QACrI,SAAAh3B,OAAC0K,GAAK,GAAG,yBAAyB,eAAa,gBACrC,UAAA5K,MAACkL,IAAU,yBAAa,EACxBlL,MAACmL,IAAS,gDAAoC,EAC9CjL,OAAC,SAAM,UAAU,eAAe,kBAAgB,gCAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS,CAAC,CAAC0C,EAAS,cAAc,gBAClC,SAAWtE,GAAM24B,EAAmB,CAAE,gBAAiB34B,EAAE,OAAO,QAAS,IAE3E4B,MAAC,QAAK,qDAAyC,GACjD,EACAE,OAAC,SAAM,UAAU,eAAe,kBAAgB,+BAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS,CAAC,CAAC0C,EAAS,cAAc,eAClC,SAAWtE,GAAM24B,EAAmB,CAAE,eAAgB34B,EAAE,OAAO,QAAS,IAE1E4B,MAAC,QAAK,6CAAiC,GACzC,GACF,EACR,QAOS,OAAI,eAAa,OAAO,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,OAAU,QAAU,QACnH,SAAAh3B,OAAC0K,GAAK,GAAG,gBAAgB,eAAa,OAC5B,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACrG,GAAA,CAAO,KAAM,GAAI,EAAE,mBAAe,EAC9CqG,MAACmL,IAAS,kKAIV,EACAjL,OAAC,OAAI,UAAU,QAAQ,kBAAgB,cACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,yBAAa,SAC3C,KAAE,MAAO,CAAE,OAAQ,SAAW,2BACd,UACd,UAAQ,SAAA+3B,EAAcA,EAAW,SAAW,MAAQ,KAAQ,WAAW,GAC1E,SACC,KAAE,MAAO,CAAE,OAAQ,SAAW,wBACjB,UACX,UACE,SAAAA,EACIA,EAAW,SAAW,0BAA4B,SACnD,WACN,GACF,SACC,KAAE,MAAO,CAAE,OAAQ,SAAW,0BACf,IACbA,GAAA,MAAAA,EAAY,KAAO/3B,MAAC,QAAM,SAAA+3B,EAAW,KAAK,EAAU/3B,MAAC,QAAK,UAAU,QAAQ,oBAAQ,GACvF,EACAE,OAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,OAAQ,SAAW,wNAGO,IACpEF,MAAC,QAAK,0CAA8B,EAAO,KAC7C,EACAE,OAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,OAAQ,SAAW,sEACH,IAC1DF,MAAC,QAAK,4CAAgC,EAAO,iBAC/C,EAEAA,MAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,OAAQ,SAAW,oKAI/D,GACF,EACAE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,aACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,gCAAoB,EACnDA,MAAC,SACC,KAAK,WACL,UAAU,aACV,MAAO63B,EACP,SAAWz5B,GAAM05B,EAAa15B,EAAE,OAAO,KAAK,EAC5C,YAAY,oDACZ,WAAY,GACZ,aAAa,QAEf8B,OAAC,OAAI,UAAU,gBAAgB,MAAO,CAAE,UAAW,GACjD,UAAAA,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAASw0B,EAC7C,UAAAr4B,MAAC5H,GAAA,CAAS,KAAM,GAAI,EAAE,eACxB,SACCyL,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASs0B,GACzC,UAAAn4B,MAACy4B,GAAA,CAAK,KAAM,GAAI,EAAE,+BACpB,SACC50B,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASu0B,EACzC,UAAAp4B,MAACs4B,GAAA,CAAU,KAAM,GAAI,EAAE,eACzB,GACF,EACCL,EACC/3B,OAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,UAAW,GAAK,6CAC1BF,MAAC,QAAK,UAAU,OAAQ,SAAAi4B,CAAA,CAAc,GACxE,EACE,KACJj4B,MAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,UAAW,GAAK,uIAG5D,GACF,GACF,EACR,QAES,OAAI,eAAa,SAAS,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,SAAY,QAAU,QACvH,SAAAh3B,OAAC0K,GAAK,GAAG,kBAAkB,eAAa,SAC9B,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACw4B,GAAA,CAAW,KAAM,GAAI,EAAE,mBAAe,EAClDx4B,MAACmL,IAAS,8DAAkD,EAC5DjL,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,qBAAqB,gCAElCF,MAAC,QAAK,UAAU,aAAa,sBAAU,GACzC,EACAA,MAAC,SACC,GAAG,qBACH,KAAK,SACL,IAAK,EACL,IAAK,GACL,QAAOsE,EAAA5B,EAAS,SAAT,YAAA4B,EAAiB,cAAe,EACvC,SAAWlG,GAAM44B,EAAY,CAAE,YAAa,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,SAAS54B,EAAE,OAAO,MAAO,EAAE,GAAK,CAAC,CAAC,EAAG,GAC5G,EACF,EACA8B,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,0BAA0B,iCAEvCF,MAAC,QAAK,UAAU,aAAa,oCAAwB,GACvD,EACAA,MAAC,SACC,GAAG,0BACH,KAAK,SACL,IAAK,IACL,IAAK,KACL,KAAM,IACN,QAAO2O,GAAAjM,EAAS,SAAT,YAAAiM,GAAiB,mBAAoB,IAC5C,SAAWvQ,GAAM44B,EAAY,CAAE,iBAAkB,KAAK,IAAI,IAAO,KAAK,IAAI,KAAS,SAAS54B,EAAE,OAAO,MAAO,EAAE,GAAK,GAAM,CAAC,EAAG,GAC/H,EACF,EACA8B,OAAC,SAAM,UAAU,eAAe,kBAAgB,qBAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS,CAAC,GAAC0mB,GAAAhkB,EAAS,SAAT,MAAAgkB,GAAiB,aAC5B,SAAWtoB,GAAM44B,EAAY,CAAE,YAAa54B,EAAE,OAAO,QAAS,IAEhE4B,MAAC,QAAK,qCAAyB,GACjC,GACF,EACR,QAES,OAAI,eAAa,YAAY,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,YAAe,QAAU,QAC7H,SAAAh3B,OAAC0K,GAAK,GAAG,qBAAqB,eAAa,YACjC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC/H,GAAA,CAAM,KAAM,GAAI,EAAE,cAAU,SACvCkT,GAAA,CAAS,0BAAanL,MAAC,QAAK,iBAAK,EAAO,eAAW,EACpDE,OAAC,SAAM,UAAU,eAAe,kBAAgB,0BAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS0C,EAAS,UAAU,gBAAkB,GAC9C,SAAWtE,GAAMk5B,EAAe,CAAE,cAAel5B,EAAE,OAAO,QAAS,IAErE4B,MAAC,QAAK,4CAAgC,GACxC,EAEAE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,8BAA8B,MAAO,CAAE,UAAW,kBACvF,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,yBAAyB,8BAAkB,EAClFA,MAAC,SACC,GAAG,yBACH,UAAU,QACV,KAAK,OACL,YAAY,sBACZ,MAAO0C,EAAS,UAAU,mBAAqB,GAC/C,SAAWtE,GAAMk5B,EAAe,CAAE,kBAAmBl5B,EAAE,OAAO,MAAO,IAEvE4B,MAAC,KAAE,UAAU,aAAa,sJAG1B,EACC0C,EAAS,UAAU,mBAClBxC,OAAAO,WAAA,CACG,WAAC,iBAAiB,KAAKiC,EAAS,UAAU,iBAAiB,GAC1D1C,MAAC,KAAE,MAAO,CAAE,MAAO,iBAAkB,SAAU,GAAI,UAAW,GAAK,8FAEnE,EAED0C,EAAS,UAAU,kBAAkB,SAAS,IAAI,GACjD1C,MAAC,KAAE,MAAO,CAAE,MAAO,eAAgB,SAAU,GAAI,UAAW,GAAK,2EAEjE,GAEJ,GAEJ,EAGAE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,yBAAyB,MAAO,CAAE,UAAW,kBAClF,UAAAA,OAAC,SAAM,UAAU,cAAc,QAAQ,oBAAoB,sCAChCF,MAAC,QAAK,UAAU,QAAQ,sBAAU,GAC7D,EACAA,MAAC,YACC,GAAG,oBACH,UAAU,WACV,KAAM,EACN,YAAY;AAAA,eACZ,OAAQ0C,EAAS,UAAU,cAAgB,IAAI,KAAK;AAAA,CAAI,EACxD,SAAWtE,GAAM,CACf,MAAMs6B,EAAQt6B,EAAE,OAAO,MACpB,MAAM;AAAA,CAAI,EACV,IAAK2iB,GAAMA,EAAE,MAAM,EACnB,OAAO,OAAO,EACjBuW,EAAe,CAAE,aAAcoB,EAAO,CACxC,IAEF14B,MAAC,KAAE,UAAU,aAAa,uLAI1B,GACE,IAAM,CACN,MAAM24B,GAAYj2B,EAAS,UAAU,cAAgB,IAAI,KAAK;AAAA,CAAI,EAAE,MAAM;AAAA,CAAI,EACxEk2B,EAAoD,GAC1D,OAAAD,EAAS,QAAQ,CAACE,EAAMz9B,IAAM,CACvBy9B,EAAK,SACL,iBAAiB,KAAKA,CAAI,GAC7BD,EAAS,KAAK,CACZ,IAAK,SAASx9B,CAAC,GACf,IACE8E,OAAC,KAAE,MAAO,CAAE,MAAO,iBAAkB,SAAU,GAAI,UAAW,GAAK,kBAC3D9E,EAAI,EAAE,MAAIy9B,EAAK,4DACvB,EAEH,EAECA,EAAK,SAAS,IAAI,GACpBD,EAAS,KAAK,CACZ,IAAK,QAAQx9B,CAAC,GACd,IACE8E,OAAC,KAAE,MAAO,CAAE,MAAO,eAAgB,SAAU,GAAI,UAAW,GAAK,kBACzD9E,EAAI,EAAE,MAAIy9B,EAAK,gDACvB,EAEH,EAEL,CAAC,EACMD,EAAS,IAAKt3B,GAAMA,EAAE,GAAG,CAClC,IAAG,EACL,GACF,EACR,QAES,OAAI,eAAa,aAAa,MAAO,CAAC,QAAU41B,IAAkB,MAAQA,IAAkB,aAAgB,QAAU,QAC/H,SAAAh3B,OAAC0K,GAAK,GAAG,sBAAsB,eAAa,aAClC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACw4B,GAAA,CAAW,KAAM,GAAI,EAAE,sBAAkB,EACrDx4B,MAACmL,IAAS,4EAAgE,EAE1EjL,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,mBAAmB,qCAEhCF,MAAC,QAAK,UAAU,aAAa,sBAAU,GACzC,EACAA,MAAC,SACC,GAAG,mBACH,KAAK,SACL,IAAK,EACL,IAAK,GACL,MAAOw2B,EAAc,wBAA0B,EAC/C,SAAWp4B,GAAMq4B,EAAkB9uB,IAAS,CAAE,GAAGA,EAAK,uBAAwB,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,SAASvJ,EAAE,OAAO,MAAO,EAAE,GAAK,CAAC,CAAC,GAAI,IAE/I8B,OAAC,SAAM,UAAU,QAAQ,4BAAeF,MAAC,QAAK,kCAAsB,GAAO,GAC7E,EAEAE,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,iBAAiB,0BAE9BF,MAAC,QAAK,UAAU,aAAa,wBAAY,GAC3C,EACAA,MAAC,SACC,GAAG,iBACH,KAAK,SACL,IAAK,EACL,IAAK,IACL,MAAOw2B,EAAc,uBAAyB,IAC9C,SAAWp4B,GAAMq4B,EAAkB9uB,IAAS,CAAE,GAAGA,EAAK,sBAAuB,KAAK,IAAI,EAAG,KAAK,IAAI,IAAM,SAASvJ,EAAE,OAAO,MAAO,EAAE,GAAK,GAAG,CAAC,GAAI,IAElJ8B,OAAC,SAAM,UAAU,QAAQ,4BAAeF,MAAC,QAAK,iCAAqB,GAAO,GAC5E,EAEAE,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,kBAAkB,+BAE/BF,MAAC,QAAK,UAAU,aAAa,2BAAe,GAC9C,EACAA,MAAC,SACC,GAAG,kBACH,KAAK,SACL,IAAK,IACL,IAAK,IACL,KAAM,IACN,MAAOw2B,EAAc,0BAA4B,KACjD,SAAWp4B,GAAMq4B,EAAkB9uB,IAAS,CAAE,GAAGA,EAAK,yBAA0B,KAAK,IAAI,IAAO,KAAK,IAAI,IAAQ,SAASvJ,EAAE,OAAO,MAAO,EAAE,GAAK,IAAM,CAAC,GAAI,IAE9J8B,OAAC,SAAM,UAAU,QAAQ,4BAAeF,MAAC,QAAK,oCAAwB,GAAO,GAC/E,EAEAE,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,yBAAyB,uCAEtCF,MAAC,QAAK,UAAU,aAAa,2BAAe,GAC9C,EACAA,MAAC,SACC,GAAG,yBACH,KAAK,SACL,IAAK,IACL,IAAK,IACL,KAAM,IACN,MAAOw2B,EAAc,iCAAmC,IACxD,SAAWp4B,GAAMq4B,EAAkB9uB,IAAS,CAAE,GAAGA,EAAK,gCAAiC,KAAK,IAAI,IAAO,KAAK,IAAI,IAAQ,SAASvJ,EAAE,OAAO,MAAO,EAAE,GAAK,GAAM,CAAC,GAAI,IAErK8B,OAAC,SAAM,UAAU,QAAQ,4BAAeF,MAAC,QAAK,2CAA+B,GAAO,GACtF,EAEAE,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC,SAAM,QAAQ,sBAAsB,8BAEnCF,MAAC,QAAK,UAAU,aAAa,sBAAU,GACzC,EACAA,MAAC,SACC,GAAG,sBACH,KAAK,SACL,IAAK,EACL,IAAK,EACL,MAAOw2B,EAAc,4BAA8B,EACnD,SAAWp4B,GAAMq4B,EAAkB9uB,IAAS,CAAE,GAAGA,EAAK,2BAA4B,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,SAASvJ,EAAE,OAAO,MAAO,EAAE,GAAK,CAAC,CAAC,GAAI,IAElJ8B,OAAC,SAAM,UAAU,QAAQ,4BAAeF,MAAC,QAAK,sCAA0B,GAAO,GACjF,EAEAE,OAAC,OAAI,UAAU,WACb,UAAAA,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,SAAY,CACzD,GAAI,CACF,MAAMhG,EAAI,IAAI,2BAA4B24B,CAAa,EACvDvxB,EAAM,QAAQ,sDAAsD,CACtE,OAASlH,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EACE,UAAAiC,MAACkd,GAAA,CAAK,KAAM,GAAI,EAAE,wBACpB,QAECrZ,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,SAAY,CACzD,GAAI,CAMF,MAAM3I,EAAS,MALL,MAAM,MAAM,0BAA2B,CAC/C,OAAQ,OACR,QAAS,CAAE,eAAgB,oBAC3B,KAAM,KAAK,UAAU,CAAE,WAAY,EAAG,EACvC,GACsB,OACvB+J,EAAM,QAAQ,cAAc/J,EAAO,OAAO,iBAAiB,CAC7D,OAAS6C,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAAG,2CAEH,GACF,EAEAiC,MAAC,OAAI,UAAU,WACb,gBAAC,SAAM,sEAAyDA,MAAC,QAAK,wBAAY,EAAO,cAAU,EACrG,GACF,EACR,WAGS,OAAI,eAAa,aAAa,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,aAAgB,QAAU,QAC/H,SAAAh3B,OAAC0K,GAAK,GAAG,sBAAsB,eAAa,aAClC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC4B,GAAA,CAAS,KAAM,GAAI,EAAE,mBAAe,EAChD5B,MAACmL,IAAS,oIAGV,EAEAjL,OAAC,SAAM,UAAU,eAAe,kBAAgB,oBAC9C,UAAAF,MAAC,SACC,KAAK,WACL,QAAS,CAAC,GAAC84B,EAAAp2B,EAAS,YAAT,MAAAo2B,EAAoB,SAC/B,SAAW16B,GAAM,CACf,MAAMuJ,EAAMjF,EAAS,WAAa,CAAE,QAAS,GAAM,SAAU,WAAY,MAAO,mCAChFo0B,EAAS,YAAa,CAAE,GAAGnvB,EAAK,QAASvJ,EAAE,OAAO,QAAS,CAC7D,IAEF4B,MAAC,QAAK,mCAAuB,GAC/B,EAEAE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,qBAAqB,MAAO,CAAE,UAAW,kBAC9E,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,0BAA0B,oBAAQ,EACzEE,OAAC,UACC,GAAG,0BACH,UAAU,SACV,QAAO64B,EAAAr2B,EAAS,YAAT,YAAAq2B,EAAoB,WAAY,WACvC,SAAW36B,GAAM,CACf,MAAMuJ,EAAMjF,EAAS,WAAa,CAAE,QAAS,GAAM,SAAU,WAAY,MAAO,mCAChFo0B,EAAS,YAAa,CAAE,GAAGnvB,EAAK,SAAUvJ,EAAE,OAAO,MAAO,CAC5D,EAEA,UAAA4B,MAAC,UAAO,MAAM,WAAW,oBAAQ,EACjCA,MAAC,UAAO,MAAM,aAAa,sBAAU,EACrCA,MAAC,UAAO,MAAM,UAAU,mBAAO,IACjC,EACF,EAEAE,OAAC,OAAI,UAAU,QAAQ,kBAAgB,kBACrC,UAAAF,MAAC,SAAM,UAAU,cAAc,QAAQ,uBAAuB,iBAAK,EACnEA,MAAC,SACC,GAAG,uBACH,UAAU,aACV,KAAK,OACL,YAAY,kCACZ,QAAOg5B,EAAAt2B,EAAS,YAAT,YAAAs2B,EAAoB,QAAS,kCACpC,SAAW56B,GAAM,CACf,MAAMuJ,EAAMjF,EAAS,WAAa,CAAE,QAAS,GAAM,SAAU,WAAY,MAAO,mCAChFo0B,EAAS,YAAa,CAAE,GAAGnvB,EAAK,MAAOvJ,EAAE,OAAO,MAAO,CACzD,IAEF8B,OAAC,KAAE,UAAU,aAAa,sCACCF,MAAC,QAAK,qBAAS,EAAO,yEAEjD,GACF,SAEC,OAAI,MAAO,CAAE,UAAW,kBACvB,UAAAA,MAAC,MAAG,MAAO,CAAE,OAAQ,sBAAwB,mCAAuB,EACpEE,OAAC,MAAG,UAAU,wBAAwB,MAAO,CAAE,OAAQ,EAAG,YAAa,iBAAkB,WAAY,KACnG,UAAAF,MAAC,MAAG,uDAA2C,EAC/CA,MAAC,MAAG,+CAAmC,EACvCA,MAAC,MAAG,qDAAyC,EAC7CA,MAAC,MAAG,wDAA4C,EAChDA,MAAC,MAAG,UAAU,QAAQ,MAAO,CAAE,SAAU,IAAM,4DAAgD,GACjG,GACF,GACF,EACR,EAEQA,MAAC,OAAI,eAAa,WAAW,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,WAAc,QAAU,QACjH,SAAAl3B,MAAC2xB,GAAA,CACC,SAAUjvB,EAAS,UAAYsxB,GAC/B,QAAU4C,GAAU,CAClBb,EAAapuB,IAAS,CACpB,GAAGA,EACH,SAAU,CAAE,GAAIA,EAAI,UAAYqsB,GAA4B,GAAG4C,CAAA,CAAM,EACrE,EACFX,EAAS,EAAI,CACf,IAEJ,QAED9B,GAAA,EAAe,QAEf,OAAI,MAAO,CAAC,QAAU+C,IAAkB,MAAQA,IAAkB,eAAkB,QAAU,QAC/F,SAAAl3B,MAAC,OAAI,eAAa,eAAe,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,eAAkB,QAAU,QAC3H,eAAC,WAAQ,GAAG,wBAAwB,eAAa,eAAe,UAAU,wBAC5D,eAAC+B,GAAA,EAAgB,EACnB,EAClB,EACA,EAEMj5B,MAAC,OAAI,MAAO,CAAC,QAAUk3B,IAAkB,MAAQA,IAAkB,QAAW,QAAU,QACxF,eAAC,OAAI,eAAa,QAAQ,MAAO,CAAC,QAAUA,IAAkB,MAAQA,IAAkB,QAAW,QAAU,QAC7G,SAAAh3B,OAAC0K,EAAA,CAAK,GAAG,iBAAiB,eAAa,QACzB,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC6G,GAAA,CAAK,KAAM,GAAI,EAAE,UAAM,EACnC7G,MAACmL,IAAS,2BAAe,EACzBjL,OAAC,MAAG,UAAU,cACZ,UAAAF,MAAC,MAAG,mBAAO,EACXA,MAAC,MAAG,UAAU,OAAQ,WAAM,QAAQ,EACpCA,MAAC,MAAG,oBAAQ,EACZA,MAAC,MACC,SAAAA,MAAC,KAAE,KAAM43B,EAAM,SAAU,OAAO,SAAS,IAAI,sBAC1C,SAAAA,EAAM,SACT,EACF,EACA53B,MAAC,MAAG,mBAAO,EACXA,MAAC,MAAI,SAAA43B,EAAM,QAAQ,GACrB,GACF,EAClB,EACA,GACI,CAEJ,CAYA,SAASqB,IAAkB,CACzB,MAAMh0B,EAAQC,GAAA,EACR,CAACiC,EAAOC,CAAQ,EAAIjL,WAAiF,EAAE,EACvG,CAAC+8B,EAAQC,CAAS,EAAIh9B,WAAsB,IAAI,GAAK,EACrD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAAC+qB,EAAQC,CAAS,EAAIhrB,WAAS,EAAE,EACjC,CAACi9B,EAAYC,CAAa,EAAIl9B,WAAS,EAAI,EAE3C+0B,EAAUvzB,cAAY,SAAY,CACtCd,EAAW,EAAI,EACf,GAAI,CACF,KAAM,CAACy8B,EAAKC,CAAG,EAAI,MAAM,QAAQ,IAAI,CACnC17B,EAAI,IAAuF,WAAW,EACtGA,EAAI,IAA0B,kBAAkB,EACjD,EACDuJ,EAAS,MAAM,QAAQkyB,EAAI,KAAK,EAAIA,EAAI,MAAQ,EAAE,EAClDH,EAAU,IAAI,IAAII,EAAI,QAAU,EAAE,CAAC,CACrC,OAASx7B,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,SACElB,EAAW,EAAK,CAClB,CACF,EAAG,CAACoI,CAAK,CAAC,EAEV/G,YAAU,IAAM,CAAEgzB,EAAA,CAAW,EAAG,CAACA,CAAO,CAAC,EAEzC,MAAMsI,EAAQ,CAACjsB,EAAmD7M,IAAgB,CAChF,MAAM5F,EAAI,GAAGyS,EAAG,MAAQ,EAAE,IAAIA,EAAG,IAAM,EAAE,IAAIA,EAAG,MAAQ,EAAE,IAAI7M,CAAG,GACjE,IAAI8M,EAAI,EACR,QAASpS,EAAI,EAAGA,EAAIN,EAAE,OAAQM,IAAKoS,GAAMA,GAAK,GAAKA,EAAI1S,EAAE,WAAWM,CAAC,EAAK,EAC1E,OAAO,KAAK,IAAIoS,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,EAAG,GAAG,EAAE,MAAM,EAAG,EAAE,CAC9D,EAEMM,EAAe,SAAY,CAC/B,GAAI,CACF,MAAMjQ,EAAI,IAAI,gBAAgB,EAC9Bs7B,EAAU,IAAI,GAAK,EACnBl0B,EAAM,QAAQ,+BAA+B,CAC/C,OAASlH,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAEM07B,EAAe,MAAO/rB,GAAgB,CAC1C,GAAI,CACF,MAAM7P,EAAI,IAAI,kBAAkB,mBAAmB6P,CAAG,CAAC,EAAE,EACzD,MAAMrO,EAAO,IAAI,IAAI65B,CAAM,EAC3B75B,EAAK,OAAOqO,CAAG,EACfyrB,EAAU95B,CAAI,CAChB,OAAStB,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAEMupB,EAAWngB,EAAM,OAAO,CAACoG,EAAI7M,IAAQ,CACzC,MAAM5F,EAAI0+B,EAAMjsB,EAAI7M,CAAG,EACvB,GAAI,CAAC04B,GAAcF,EAAO,IAAIp+B,CAAC,EAAG,MAAO,GACzC,GAAI,CAACosB,EAAQ,MAAO,GACpB,MAAM/hB,EAAI+hB,EAAO,cACjB,MAAO,CAAC3Z,EAAG,KAAMA,EAAG,KAAMA,EAAG,OAAO,EAAE,KAAMvO,GAAM,OAAOA,GAAM,UAAYA,EAAE,cAAc,SAASmG,CAAC,CAAC,CACxG,CAAC,EAED,OACEjF,OAAC0K,EAAA,CAAK,GAAG,uBAAuB,eAAa,cAC3C,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC2B,GAAA,CAAS,KAAM,GAAI,EAAE,gBACtBzB,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,WAAY,IAAK,WAAY,EAAG,SAAU,IACxE,UAAAiH,EAAM,OAAO,YAAU+xB,EAAO,KAAK,WACtC,QACCr1B,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,MAAO,CAAE,WAAY,QAAU,QAASqtB,EAAS,MAAM,SACvF,eAAC/wB,GAAA,CAAU,KAAM,GAAI,EACvB,GACF,SACCgL,GAAA,CAAS,+BACUnL,MAAC,QAAK,iCAAqB,EAAO,gFACtD,EAEAE,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC,OAAI,UAAU,sBACb,UAAAF,MAACsG,GAAA,CAAO,KAAM,GAAI,EAClBtG,MAAC,SACC,KAAK,OACL,UAAU,QACV,YAAY,oCACZ,MAAOknB,EACP,SAAW9oB,GAAM+oB,EAAU/oB,EAAE,OAAO,KAAK,GAC3C,EACF,EACA8B,OAAC,SAAM,UAAU,sBACf,UAAAF,MAAC,SACC,KAAK,WACL,QAASo5B,EACT,SAAWh7B,GAAMi7B,EAAcj7B,EAAE,OAAO,OAAO,IAC/C,eAEJ,EACA8B,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,SAAUq1B,EAAO,OAAS,EAC1B,QAASprB,EACT,MAAM,2CAEN,UAAA9N,MAAC5I,GAAA,CAAI,KAAM,GAAI,EAAE,iBACnB,EACF,EAECwF,EACCoD,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,SAAU,SAAU,IAAM,oBAAQ,EACzEsnB,EAAS,SAAW,EACtBtnB,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,SAAU,SAAU,IAC1D,SAAAmH,EAAM,SAAW,EAAI,mBAAqB,qCAC7C,EAEAjH,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC,SAAM,UAAU,qBACf,UAAAF,MAAC,SACC,gBAAC,MACC,UAAAA,MAAC,MAAG,gBAAI,EACRA,MAAC,MAAG,kBAAM,EACVA,MAAC,MAAG,gBAAI,QACP,OAAG,GACN,EACF,EACAA,MAAC,SACE,SAAAsnB,EAAS,MAAM,EAAG,GAAG,EAAE,IAAI,CAAC/Z,EAAI7M,IAAQ,CACvC,MAAM5F,EAAI0+B,EAAMjsB,EAAI7M,CAAG,EACjBg5B,EAAWR,EAAO,IAAIp+B,CAAC,EAC7B,cACG,MAA2B,UAAWmI,EAAGy2B,GAAY,yBAAyB,EAC7E,UAAA15B,MAAC,MAAG,UAAU,oBAAqB,SAAAuN,EAAG,MAAQ,WAAW,EACzDvN,MAAC,MAAG,UAAU,sBACX,WAAG,SAAWuN,EAAG,MAAQ,IAC5B,EACAvN,MAAC,MAAG,UAAU,yBACX,SAAAuN,EAAG,GAAK,IAAI,KAAKA,EAAG,EAAE,EAAE,iBAAmB,IAC9C,EACAvN,MAAC,MACE,SAAA05B,EACC15B,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS,IAAM41B,EAAa3+B,CAAC,EAAG,MAAM,sBACtE,SAAAkF,MAAC5I,GAAA,CAAI,KAAM,GAAI,EACjB,EAEA4I,MAAC,QAAK,UAAU,yBAAyB,iBAAK,EAElD,IAhBO,GAAGuN,EAAG,EAAE,IAAI7M,CAAG,EAiBxB,CAEJ,CAAC,EACH,GACF,EACC4mB,EAAS,OAAS,KACjBpnB,OAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,QAAS,SAAW,kCAC1ConB,EAAS,OAAO,KACxC,GAEJ,GAEJ,CAEJ,CACO,MAAMqS,GAAe/oB,GAAM,KAAKilB,EAAiB,EC7uDjD,SAAS+D,GAAK,CAAE,SAAAvtB,EAAU,gBAAAC,GAA0B,CACzD,MAAMrH,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EAMR,CAACmJ,EAAMC,CAAO,EAAI1Q,WAAgB,MAAM,QAAQkQ,EAAS,IAAI,EAAIA,EAAS,KAAO,EAAE,EACnF,CAACzP,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAAC4iB,EAAU8a,CAAW,EAAI19B,WAAwB,IAAI,EACtD,CAAC29B,EAAUC,CAAW,EAAI59B,WAAoB,EAAE,EAChD,CAAC69B,EAAWC,CAAY,EAAI99B,WAAwB,IAAI,EAExD,CAAC+9B,EAAcC,CAAe,EAAIh+B,WAAS,EAAK,EAChD,CAACi+B,EAAUC,CAAW,EAAIl+B,WAkBtB,IAAI,EACR,CAACm+B,EAAiBC,CAAkB,EAAIp+B,WAAS,EAAK,EACtD,CAAC61B,EAAYC,CAAa,EAAI91B,WAAkC,EAAE,EAElEq+B,EAAe,SAAY,WAC/BD,EAAmB,EAAI,EACvB,GAAI,CACF,MAAM76B,EAAI,MAAM7B,EAAI,IAejB,gBAAgB,EACnBw8B,EAAY,CACV,SAAQp8B,EAAAyB,EAAE,WAAF,YAAAzB,EAAY,SAAU,GAC9B,SAASqG,EAAA5E,EAAE,WAAF,YAAA4E,EAAY,QACrB,WAAWqK,EAAAjP,EAAE,WAAF,YAAAiP,EAAY,UACvB,KAAMjP,EAAE,MAAQ,EAAC,CAClB,CACH,OAAS3B,EAAK,CACZs8B,EAAY,CAAE,OAAQ,GAAI,KAAM,GAAI,MAAQt8B,EAAc,QAAS,CACrE,SACEw8B,EAAmB,EAAK,CAC1B,CACF,EAEME,EAAwB,MAAOxyB,GAAe,CAClDgqB,EAAetqB,IAAS,CAAE,GAAGA,EAAK,CAACM,CAAE,EAAG,IAAO,EAC/C,GAAI,CACF,MAAM4G,EAAI,MAAMhR,EAAI,KAAU,QAAS,CAAE,GAAAoK,EAAI,EAC7C4E,EAASlF,GAAQ,CAAC,GAAGA,EAAI,OAAQpI,GAAMA,EAAE,KAAOsP,EAAE,EAAE,EAAGA,CAAC,CAAC,EACzD5J,EAAM,QAAQ,QAAQ4J,EAAE,EAAE,4BAA4B,EACtD,MAAMvC,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,SACEk0B,EAAetqB,IAAS,CAAE,GAAGA,EAAK,CAACM,CAAE,EAAG,IAAQ,CAClD,CACF,EAKMyyB,EAAwB,MAAOzyB,EAAY0yB,EAAS,KAAU,CAClE1I,EAAetqB,IAAS,CAAE,GAAGA,EAAK,CAACM,CAAE,EAAG,IAAO,EAC/C,GAAI,CACF,MAAMvI,EAAI,MAAM7B,EAAI,KAMjB,SAAS,mBAAmBoK,CAAE,CAAC,WAAY,CAAE,OAAA0yB,CAAA,CAAQ,EACxD9tB,EAASlF,GAAQ,CAAC,GAAGA,EAAI,OAAQpI,IAAMA,GAAE,KAAOG,EAAE,IAAI,EAAE,EAAGA,EAAE,GAAG,CAAC,EACjE,MAAMk7B,EAAal7B,EAAE,WAAa,eAAeA,EAAE,UAAU,IAAM,GACnEuF,EAAM,QAAQ,QAAQgD,CAAE,eAAevI,EAAE,IAAI,OAAOA,EAAE,EAAE,GAAGk7B,CAAU,GAAG,EACxE,MAAMtuB,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,SACEk0B,EAAetqB,IAAS,CAAE,GAAGA,EAAK,CAACM,CAAE,EAAG,IAAQ,CAClD,CACF,EAEMR,EAAS,SAAY,CACzB,GAAI,CAIF,MAAM/H,EAAI,MAAM7B,EAAI,IAAqB,OAAO,EAChDgP,EAAQnN,EAAE,MAAQ,EAAE,EACpB,GAAI,CACF,MAAMV,EAAI,MAAMnB,EAAI,IAA0B,aAAa,EAC3Dk8B,EAAY/6B,EAAE,OAAS,EAAE,CAC3B,MAAQ,CACN+6B,EAAY,EAAE,CAChB,CACF,OAASh8B,EAAK,CACZkH,EAAM,MAAM,qBAAsBlH,EAAc,OAAO,EAAE,CAC3D,SAIElB,EAAW,EAAK,CAClB,CACF,EAGAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,EAAE,EAILvJ,YAAU,IAAM,CACV,MAAM,QAAQmO,EAAS,IAAI,GAAKA,EAAS,OAASO,GACpDC,EAAQR,EAAS,IAAI,CAGzB,EAAG,CAACA,EAAS,IAAI,CAAC,EAElB,MAAMwuB,EAAY,IAAM,CACtB,IAAIC,EAAkC,KACtCt3B,EAAM,KAAK,CACT,MAAO,cACP,gBACG,OACC,UAAAtD,OAAC,KAAE,UAAU,QAAQ,4EAEjBF,MAAC,QAAK,oBAAQ,EAAO,kCACtB,IAAIA,MAAC,QAAK,sCAAgC,EAAO,KACpD,EACAA,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,SACC,IAAMiW,GAAQ6kB,EAAS7kB,EACvB,UAAU,QACV,KAAK,OACL,YAAY,kBACZ,UAAS,IACX,EACF,EAEF,OACE/V,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,kBAAM,EAC5DxD,MAAC6D,EAAA,CACC,QAAQ,UACR,QAAS,SAAY,CACnB,MAAMrJ,IAAQsgC,GAAA,YAAAA,EAAQ,QAAS,IAAI,OACnC,GAAI,CAACtgC,EAAM,CACTyK,EAAM,QAAQ,mBAAmB,EACjC,MACF,CACA,GAAI,CACF,MAAM4J,EAAI,MAAMhR,EAAI,KAAU,QAAS,CAAE,KAAArD,EAAM,EAC/CqS,EAASlF,GAAQ,CAAC,GAAGA,EAAKkH,CAAC,CAAC,EAC5B5J,EAAM,QAAQ,QAAQ4J,EAAE,EAAE,cAAc,EACxCrL,EAAM,QACN,MAAM8I,EAAA,CACR,OAASvO,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EACD,oBAED,EACF,EAEH,CACH,EAEMg9B,EAAc,MAAO9yB,GAAe,CACxC,GAAK,QAAQ,kBAAkBA,CAAE,wDAAwD,EACzF,GAAI,CACF,MAAMpK,EAAI,IAAI,SAAS,mBAAmBoK,CAAE,CAAC,EAAE,EAC/C4E,EAASlF,GAAQA,EAAI,OAAQkH,GAAMA,EAAE,KAAO5G,CAAE,CAAC,EAC3C8W,IAAa9W,GAAI4xB,EAAY,IAAI,EACrC50B,EAAM,QAAQ,kBAAkB,CAClC,OAASlH,EAAK,CACZkH,EAAM,MAAM,qBAAsBlH,EAAc,OAAO,EAAE,CAC3D,CACF,EAEMi9B,EAAkB,MAAOC,GAAa,CAC1C,GAAI,CACF,MAAM57B,EAAO,MAAMxB,EAAI,IAAS,SAAS,mBAAmBo9B,EAAI,EAAE,CAAC,GAAI,CAAE,QAAS,CAACA,EAAI,QAAS,EAChGpuB,EAASlF,GAAQA,EAAI,IAAKkH,GAAOA,EAAE,KAAOosB,EAAI,GAAK57B,EAAOwP,CAAE,CAAC,EAC7D5J,EAAM,QAAQ,OAAO5F,EAAK,QAAU,UAAY,UAAU,GAAG,CAC/D,OAAStB,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEM4B,EAAMiN,EAAK,KAAMiC,GAAMA,EAAE,KAAOkQ,CAAQ,GAAK,KAEnD,OAAIniB,EAEAoD,MAAC,OAAI,UAAU,eACb,eAACuO,GAAA,CAAQ,KAAK,KAAK,EACrB,EAKFrO,OAAC,OAAI,UAAU,iBACb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC1G,GAAA,CAAO,KAAM,GAAI,EAAE,UAAQsT,EAAK,OAAO,KAC1C,EACA1M,OAAC,KAAE,UAAU,gBAAgB,qCACHF,MAAC,QAAK,iCAAqB,EAAO,uDAE5D,GACF,EACAE,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAAS4D,EAC7C,UAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,SACC0D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASg3B,EAC3C,UAAA76B,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,gBACpB,GACF,GACF,EAEC8I,EAAK,SAAW,EACf5M,MAACgM,GAAA,CACC,KAAMhM,MAAC1G,GAAA,CAAO,KAAM,GAAI,EACxB,MAAM,oBACN,QAAQ,2GAGV4G,OAAC,OAAI,UAAU,cACb,UAAAF,MAAC,OAAI,UAAU,YACZ,SAAA4M,EAAK,IAAKiC,GACT3O,OAAC,OAEC,UAAW+C,EAAG,gBAAiB8b,IAAalQ,EAAE,IAAM,sBAAsB,EAC1E,QAAS,IAAMgrB,EAAYhrB,EAAE,EAAE,EAE/B,UAAA3O,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OACC,UAAAF,MAAC,OAAI,UAAU,qBAAsB,SAAA6O,EAAE,KAAK,EAC5C3O,OAAC,OAAI,UAAU,qBAAqB,cAAE2O,EAAE,QAAQ,MAAIA,EAAE,KAAK,MAAIA,EAAE,QAAO,GAC1E,EACA3O,OAAC,OAAI,UAAU,wBAAwB,QAAU9B,GAAMA,EAAE,kBACvD,UAAA4B,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,iBACX,MAAO6O,EAAE,QAAU,UAAY,SAC/B,QAAS,IAAMmsB,EAAgBnsB,CAAC,EAEhC,SAAA7O,MAACkP,GAAA,CAAM,KAAM,GAAI,IAEnBlP,MAAC,UACC,KAAK,SACL,UAAU,2BACV,aAAW,YACX,MAAM,YACN,QAAS,IAAM+6B,EAAYlsB,EAAE,EAAE,EAE/B,SAAA7O,MAACiP,GAAA,CAAO,KAAM,GAAI,GACpB,EACF,GACF,EACAjP,MAAC,OAAI,UAAU,gCAAgC,MAAO6O,EAAE,YACrD,WAAE,YACL,QACC,OAAI,UAAU,uBACb,SAAA7O,MAAC,QAAK,UAAW,iBAAiB6O,EAAE,QAAU,mBAAqB,mBAAmB,GACnF,WAAE,QAAU,UAAY,WAC3B,EACF,IArCKA,EAAE,GAuCV,EACH,EACClP,GAAOK,MAACk7B,GAAA,CAAW,IAAKv7B,CAAA,CAAK,GAChC,EAIFO,OAAC0K,EAAA,CAAK,UAAU,qBACd,UAAA1K,OAAC,OAAI,UAAU,qBAAqB,QAAS,IAAM,CAC7C,CAACk6B,GAAY,CAACE,GAAiBE,EAAA,EACnCL,EAAiBn7B,GAAM,CAACA,CAAC,CAC3B,EACE,UAAAgB,MAAC/H,GAAA,CAAM,KAAM,GAAI,EACjB+H,MAAC,QAAK,UAAU,sBAAsB,wBAAY,QACjD,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,IACxC,SAAAo6B,GAAA,MAAAA,EAAU,KAAO,GAAGA,EAAS,KAAK,MAAM,aAAe,kBAC1D,EACAp6B,MAAC,QAAK,UAAU,uBAAuB,EACtCk6B,QAAgB94B,GAAA,CAAY,KAAM,GAAI,EAAKpB,MAACqB,GAAA,CAAa,KAAM,GAAI,GACtE,EACC64B,GACCl6B,MAAC,OAAI,UAAU,qBACZ,WACCA,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,GAAI,SAAU,IAAM,6BAAiB,EAC5Eo6B,GAAA,MAAAA,EAAU,MACZl6B,OAAC,OAAI,UAAU,sBACb,UAAAF,MAACtG,GAAA,CAAY,KAAM,GAAI,EAAE,6BAA2B0gC,EAAS,OAC/D,EACE,CAACA,GAAYA,EAAS,KAAK,SAAW,QACvC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,GAAI,SAAU,IAAM,+CAE7D,EAEAl6B,OAAAO,WAAA,CACG,UAAA25B,EAAS,QACRl6B,OAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,aAAc,GAAK,qBACvDF,MAAC,QAAM,SAAAo6B,EAAS,OAAO,GACjC,EAEFp6B,MAAC,OAAI,UAAU,qBACZ,WAAS,KAAK,IAAKm7B,GAAO,CACzB,MAAM/H,EAAYxmB,EAAK,KAAMiC,GAAMA,EAAE,KAAOssB,EAAG,EAAE,EAC3CC,EAAe,CAAC,CAACpJ,EAAWmJ,EAAG,EAAE,EACvC,OACEj7B,OAAC,OAAgB,UAAU,oBACzB,UAAAA,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC,OAAI,UAAU,yBAA0B,SAAAm7B,EAAG,KAAK,EAChDA,EAAG,QACFj7B,OAAC,QAAK,UAAW+C,EAAG,uBAAwBk4B,EAAG,kBAAoB,8BAA8B,EAAG,cAChGA,EAAG,OAAQA,EAAG,iBAAmB,KAAO,IAC5C,GAEJ,EACCA,EAAG,aACFn7B,MAAC,OAAI,UAAU,yBAA0B,WAAG,YAAY,EAE1DE,OAAC,OAAI,UAAU,yBACZ,UAAAi7B,EAAG,QAAUj7B,OAAC,QAAK,UAAU,QAAQ,gBAAIi7B,EAAG,QAAO,EACnDA,EAAG,UACFn7B,MAAC,KAAE,KAAMm7B,EAAG,SAAU,OAAO,SAAS,IAAI,sBAAsB,UAAU,oBAAoB,oBAE9F,GAEJ,GACEA,EAAG,aAAe,IAAI,OAAS,GAC/Bj7B,OAAC,OAAI,UAAU,qBACb,UAAAF,MAACtG,GAAA,CAAY,KAAM,GAAI,GACrByhC,EAAG,aAAe,IAAI,MAAM,EAAG,CAAC,EAAE,IAAKngC,GACvCgF,MAAC,QAAa,UAAU,oBAAqB,SAAAhF,CAAA,EAAlCA,CAAoC,CAChD,GACCmgC,EAAG,aAAe,IAAI,OAAS,GAC/Bj7B,OAAC,QAAK,UAAU,yBAAyB,cAAEi7B,EAAG,YAAa,OAAS,GAAE,GAE1E,EAEFj7B,OAAC,OAAI,UAAU,4BACZ,WAACkzB,GACApzB,MAAC6D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,SAAUu3B,EACV,QAAS,IAAMX,EAAsBU,EAAG,EAAE,EAC1C,MAAM,wBAEL,WAAen7B,MAACuO,GAAA,CAAQ,KAAK,KAAK,EAAMrO,OAAAO,WAAA,CAAE,UAAAT,MAAC/I,GAAA,CAAS,KAAM,GAAI,EAAE,YAAQ,IAG5Em8B,GAAa+H,EAAG,kBACfn7B,MAAC6D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,SAAUu3B,EACV,QAAS,IAAMV,EAAsBS,EAAG,EAAE,EAC1C,MAAO,iBAAiBA,EAAG,kBAAoB,GAAG,QAAQA,EAAG,gBAAgB,GAE5E,WAAen7B,MAACuO,GAAA,CAAQ,KAAK,KAAK,EAAMrO,OAAAO,WAAA,CAAE,UAAAT,MAAC/I,GAAA,CAAS,KAAM,GAAI,EAAE,gBAAckkC,EAAG,kBAAiB,IAGtG/H,GAAa,CAAC+H,EAAG,kBAChBj7B,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,SAAQ,GACR,MAAO,cAAcs3B,EAAG,kBAAoB,GAAG,GAChD,wBACaA,EAAG,kBAAoB,MACrC,EAEJ,IAhEQA,EAAG,EAiEb,CAEJ,CAAC,EACH,GACF,EAEJ,GAEJ,EAKCrB,EAAS,OAAS,GACjB55B,OAAC0K,EAAA,CAAK,UAAU,iBACd,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC/H,GAAA,CAAM,KAAM,GAAI,EAAE,cAAU,SACvCkT,GAAA,CACE,UAAA2uB,EAAS,OAAO,qBAAmBA,EAAS,SAAW,EAAI,GAAK,IAAI,8DACxD95B,MAAC,UAAO,gBAAI,EAAS,0CACpC,GACF,EAIDg6B,GACC95B,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC,QAAK,wBAAWF,MAAC,KAAE,KAAMg6B,EAAW,OAAO,SAAS,IAAI,aAAc,SAAAA,CAAA,CAAU,GAAI,EACrFh6B,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,eACX,QAAS,IAAMi6B,EAAa,IAAI,EAEhC,SAAAj6B,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,EACAvG,MAAC,UACC,IAAKg6B,EACL,UAAU,aACV,MAAM,WACN,QAAQ,4DACV,EACF,GAEJ,CAEJ,CAEA,SAASkB,GAAW,CAAE,IAAAD,GAAqB,CACzC,MAAMh2B,EAAQC,GAAA,EACR,CAACm2B,EAAcC,CAAe,EAAIn/B,WAO9B,IAAI,EACR,CAACo/B,EAAqBC,CAAsB,EAAIr/B,WAAS,EAAK,EAC9D,CAACs/B,EAAkBC,CAAmB,EAAIv/B,WAAS,EAAK,EACxD,CAACw/B,EAAcC,CAAe,EAAIz/B,WAAwB,IAAI,EAE9D0/B,EAAmB,SAAY,CACnCL,EAAuB,EAAI,EAC3B,GAAI,CACF,MAAM97B,EAAI,MAAM7B,EAAI,IAAyB,SAASo9B,EAAI,EAAE,eAAe,EAC3EK,EAAgB57B,CAAC,EACjBg8B,EAAoB,EAAI,CAC1B,OAAS39B,EAAK,CACZkH,EAAM,MAAM,gCAAiClH,EAAc,OAAO,EAAE,CACtE,SACEy9B,EAAuB,EAAK,CAC9B,CACF,EAEMM,EAA0B,SAAY,CAC1C,GAAI,CACF,MAAMp8B,EAAI,MAAM7B,EAAI,KAClB,SAASo9B,EAAI,EAAE,0BACf,EAAC,EAEHh2B,EAAM,QAAQ,gBAAgBvF,EAAE,OAAO,MAAM,YAAYA,EAAE,OAAO,QAAQ,cAAcA,EAAE,OAAO,MAAM,YAAYA,EAAE,OAAO,YAAY,gBAAgB,EACxJ,MAAMm8B,EAAA,CACR,OAAS99B,EAAK,CACZkH,EAAM,MAAM,qBAAsBlH,EAAc,OAAO,EAAE,CAC3D,CACF,EAEA,OACEmC,OAAC0K,EAAA,CAAK,UAAU,cACd,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAAE,kBAAgBmvB,EAAI,MAAK,QACzD9vB,GAAA,CACC,SAAAnL,MAAC,QAAM,SAAAi7B,EAAI,KAAK,EAClB,EACA/6B,OAAC,MAAG,UAAU,YACZ,UAAAF,MAAC,MAAG,cAAE,EACNA,MAAC,MAAG,UAAU,OAAQ,WAAI,GAAG,EAC7BA,MAAC,MAAG,mBAAO,EACXA,MAAC,MAAG,UAAU,OAAQ,WAAI,QAAQ,EAClCA,MAAC,MAAG,gBAAI,EACRA,MAAC,MAAG,UAAU,OAAQ,WAAI,KAAK,EAC/BA,MAAC,MAAG,kBAAM,QACT,MAAG,UAAU,OAAQ,SAAAi7B,EAAI,QAAU,IAAI,EACxCj7B,MAAC,MAAG,iBAAK,QACR,MAAG,UAAU,OAAQ,SAAAi7B,EAAI,OAAS,IAAI,EACvCj7B,MAAC,MAAG,mBAAO,EACXA,MAAC,MAAI,SAAAi7B,EAAI,QAAU,MAAQ,KAAK,EAChCj7B,MAAC,MAAG,uBAAW,SACd,MACG,WAAAi7B,EAAI,aAAe,IAAI,IAAKjgC,GAC5BgF,MAAC,QAAa,UAAU,MAAO,SAAAhF,CAAA,EAApBA,CAAsB,CAClC,GACCigC,EAAI,aAAe,IAAI,SAAW,GAAKj7B,MAAC,QAAK,UAAU,QAAQ,kBAAM,GACzE,GACF,EACAE,OAAC,OAAI,UAAU,YACb,UAAAF,MAAC,OAAI,UAAU,QAAQ,iBAAK,EAC5BA,MAAC,MACG,UAAAi7B,EAAI,OAAS,IAAI,IAAK5wB,GACtBnK,OAAC,MACC,UAAAF,MAAC,QAAK,UAAU,eAAgB,SAAAqK,EAAE,SAAS,EAC3CrK,MAAC,QAAK,UAAU,OAAQ,WAAE,KAAK,IAFxBqK,EAAE,IAGX,CACD,EACH,GACF,EAGAnK,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,OAAI,UAAU,wBAAwB,QAAS,IAAM,CAChD,CAACm7B,GAAgB,CAACE,GAAqBM,EAAA,EAC3CH,EAAqB18B,GAAM,CAACA,CAAC,CAC/B,EACE,UAAAgB,MAAC1I,GAAA,CAAS,KAAM,GAAI,EACpB0I,MAAC,QAAK,kCAAsB,EAC5BA,MAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,IACxC,SAAAq7B,EAAe,GAAGA,EAAa,KAAK,SAAW,gBAClD,EACAr7B,MAAC,QAAK,UAAU,0BAA0B,EACzCy7B,QAAoBr6B,GAAA,CAAY,KAAM,GAAI,EAAKpB,MAACqB,GAAA,CAAa,KAAM,GAAI,GAC1E,EACCo6B,GAAoBJ,GACnBn7B,OAAC,OAAI,UAAU,wBACZ,UAAAm7B,EAAa,OAAO,OAAS,GAC5Bn7B,OAAC,OAAI,UAAU,2BACb,UAAAA,OAAC,OAAI,UAAU,iCACb,UAAAF,MAAC/F,GAAA,CAAK,KAAM,GAAI,EAAE,YAAUohC,EAAa,OAAO,OAAO,KACzD,EACCA,EAAa,OAAO,IAAKhxB,GACxBnK,OAAC,OAAqB,UAAU,wBAC9B,UAAAA,OAAC,OACC,UAAU,6BACV,QAAS,IAAM07B,EAAiBj0B,GAAQA,IAAQ0C,EAAE,SAAW,KAAOA,EAAE,QAAQ,EAE9E,UAAArK,MAAC,QAAK,UAAU,OAAQ,SAAAqK,EAAE,SAAS,EACnCnK,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,IAAM,0BACjCmK,EAAE,UAClB,KAEDsxB,IAAiBtxB,EAAE,UAClBrK,MAAC,OAAI,UAAU,2BACZ,SAAAqK,EAAE,SAAWrK,MAAC,MAAG,UAAU,QAAQ,kCAAsB,EAC5D,IAbMqK,EAAE,QAeZ,CACD,GACH,EAEDgxB,EAAa,SAAS,OAAS,GAC9Bn7B,OAAC,OAAI,UAAU,2BACb,UAAAA,OAAC,OAAI,UAAU,iCACb,UAAAF,MAACsY,GAAA,CAAS,KAAM,GAAI,EAAE,cAAY+iB,EAAa,SAAS,OAAO,KACjE,EACCA,EAAa,SAAS,IAAKhxB,GAC1BnK,OAAC,OAAqB,UAAU,wBAC9B,UAAAA,OAAC,OACC,UAAU,6BACV,QAAS,IAAM07B,EAAiBj0B,GAAQA,IAAQ0C,EAAE,SAAW,KAAOA,EAAE,QAAQ,EAE9E,UAAArK,MAAC,QAAK,UAAU,OAAQ,SAAAqK,EAAE,SAAS,EACnCnK,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,IAAM,0BACjCmK,EAAE,UAClB,KAEDsxB,IAAiBtxB,EAAE,UAClBrK,MAAC,OAAI,UAAU,2BACZ,SAAAqK,EAAE,SAAWrK,MAAC,MAAG,UAAU,QAAQ,kCAAsB,EAC5D,IAbMqK,EAAE,QAeZ,CACD,GACH,EAEDgxB,EAAa,OAAO,OAAS,GAC5Bn7B,OAAC,OAAI,UAAU,2BACb,UAAAA,OAAC,OAAI,UAAU,iCACb,UAAAF,MAAC+7B,GAAA,CAAS,KAAM,GAAI,EAAE,YAAUV,EAAa,OAAO,OAAO,KAC7D,EACCA,EAAa,OAAO,IAAKl1B,GACxBjG,OAAC,OAAiB,UAAU,wBAC1B,UAAAA,OAAC,OACC,UAAU,6BACV,QAAS,IAAM07B,EAAiBj0B,GAAQA,IAAQxB,EAAE,KAAO,KAAOA,EAAE,IAAI,EAEtE,UAAAnG,MAAC,QAAK,UAAU,OAAQ,SAAAmG,EAAE,KAAK,EAC/BjG,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,IAAM,0BACjCiG,EAAE,UAClB,KAEDw1B,IAAiBx1B,EAAE,MAClBnG,MAAC,OAAI,UAAU,2BACZ,SAAAmG,EAAE,SAAWnG,MAAC,MAAG,UAAU,QAAQ,kCAAsB,EAC5D,IAbMmG,EAAE,IAeZ,CACD,GACH,EAEDk1B,EAAa,QAAU,GACtBn7B,OAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,EAAG,SAAU,IAAM,+GACwCF,MAAC,QAAK,2BAAe,EAAO,QAAKA,MAAC,QAAK,mBAAO,EAAO,iBAAcA,MAAC,QAAK,qBAAS,EAAO,oBAAiBA,MAAC,QAAK,mBAAO,EAAO,eAClO,EAEFA,MAAC,OAAI,UAAU,2BACb,SAAAE,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASi4B,EACzC,UAAA97B,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,8BACzB,EACF,GACF,GAEJ,GACF,CAEJ,CC/oBO,SAAS67B,GAAQ,CAAE,OAAAC,EAAQ,UAAAC,EAAW,aAAA7wB,GAAuB,CAClE,MAAMpG,EAAQC,GAAA,EACR,CAACi3B,EAAMC,CAAO,EAAIjgC,WAAyB,IAAI,EAC/C,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACkgC,EAAcC,CAAe,EAAIngC,WAAS,CAAC,EAmBlD,GAjBA+B,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAC,SAAY,CACX,GAAI,CACF,MAAMrG,EAAI,MAAM7B,EAAI,IAA0B,aAAa,EAC3D,GAAIkI,EAAW,OACf,MAAMw2B,GAAS78B,EAAE,OAAS,IAAI,KAAMV,GAAMA,EAAE,KAAOi9B,CAAM,EACzDG,EAAQG,GAAS,IAAI,CACvB,OAASx+B,EAAK,CACZkH,EAAM,MAAM,4BAA6BlH,EAAc,OAAO,EAAE,CAClE,SACOgI,GAAWlJ,EAAW,EAAK,CAClC,CACF,KACO,IAAM,CAAEkJ,EAAY,EAAM,CACnC,EAAG,CAACk2B,EAAQh3B,CAAK,CAAC,EAEdrI,EACF,OAAOoD,MAACgM,GAAA,CAAW,MAAM,oBAAoB,EAG/C,GAAI,CAACmwB,EACH,OACEn8B,MAACgM,GAAA,CACC,MAAM,qBACN,QAAS,oBAAoBiwB,CAAM,4BACnC,OAAQj8B,MAAC6D,EAAA,CAAO,QAAS,IAAMwH,EAAa,MAAM,EAAG,QAAQ,UAAU,KAAK,KAAK,qBAEjF,IAMN,GAAI8wB,EAAK,OAAS,SAAU,CAC1B,MAAMK,EAAM,aAAaL,EAAK,KAAK,qBAAqBE,GAAgBH,GAAa,EAAE,GACvF,OACEh8B,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC,OAAI,UAAU,yBACb,UAAAA,OAAC,QAAK,UAAU,wBACd,UAAAF,MAAC/H,GAAA,CAAM,KAAM,GAAI,EAChBkkC,EAAK,MACNj8B,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,WAAY,KAAO,gBAAIi8B,EAAK,OAAM,GACnF,EACAj8B,OAAC,OAAI,UAAU,0BACb,UAAAA,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAS,IAAMy4B,EAAiB10B,GAAMA,EAAI,CAAC,EAC3C,MAAM,mBAEN,UAAA5H,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,aAEzBH,MAAC,KACC,KAAMw8B,EACN,OAAO,SACP,IAAI,sBACJ,UAAU,WACV,MAAM,kBAEN,SAAAx8B,MAAC6L,GAAA,CAAa,KAAM,GAAI,GAC1B,EACF,GACF,EACA7L,MAAC,UAEC,IAAAw8B,EACA,UAAU,kBACV,MAAOL,EAAK,OAHPE,GAAgBH,GAAa,GAIpC,EACF,CAEJ,CAMA,GAAIC,EAAK,UAAW,CAGlB,MAAMM,EAAwBN,EAAK,UAC7BO,EAAgBP,EAAK,MACrBQ,EAAeC,OAAK,IAAAzJ,GAAA,IACxB,OAEE,aAAa,mBAAmBuJ,CAAK,CAAC,UAAU,mBAAmBD,CAAa,CAAC,QACjF,KAAM5tB,IAAO,CAAE,QAASA,EAAE,UAAY,IAAM,OAAQ,GAExD,OACE3O,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,OAAI,UAAU,yBACb,SAAAE,OAAC,QAAK,UAAU,wBACd,UAAAF,MAACzH,GAAA,CAAe,KAAM,GAAI,EACzB4jC,EAAK,MACNj8B,OAAC,QAAK,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,WAAY,KAAO,gBAAIi8B,EAAK,OAAM,GACnF,EACF,EACAn8B,MAAC,OAAI,UAAU,oBACb,eAAC68B,GAAA,CAAc,MAAOV,EAAK,MAAO,UAAWA,EAAK,UAChD,SAAAn8B,MAAC88B,YAAS,SAAU58B,OAAC,OAAI,MAAO,CAAE,QAAS,IAAM,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EAAE,IAACvO,MAAC,QAAK,UAAU,QAAQ,6BAAiB,GAAO,EACrH,SAAAA,MAAC28B,EAAA,EAAa,EAChB,EACF,EACF,GACF,CAEJ,CAGA,cACG/xB,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACzH,GAAA,CAAe,KAAM,GAAI,EAAE,IAAE4jC,EAAK,OACrC,SACChxB,GAAA,CAAS,gBAAIgxB,EAAK,OAAM,EACxBA,EAAK,aAAen8B,MAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,UAAW,GAAM,SAAAm8B,EAAK,YAAY,EACrFj8B,OAAC,KAAE,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,UAAW,IAAM,6GAErDF,MAAC,QAAK,qBAAS,EAAO,gBAAaA,MAAC,QAAK,uBAAW,EAAO,6BAA0BA,MAAC,QAAK,kBAAM,EAAO,KAChH,QACC,OAAI,MAAO,CAAE,UAAW,IACvB,SAAAA,MAAC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAMwH,EAAa,MAAM,EAAG,0BAE3E,EACF,GACF,CAEJ,CAUA,MAAMwxB,WAAsBE,WAG1B,CAHF,kCAIEtZ,GAAA,aAAQ,CAAE,MAAO,OACjB,OAAO,yBAAyB3mB,EAAc,CAC5C,MAAO,CAAE,MAAAA,CAAA,CACX,CACS,mBAAoB,CAE7B,CACS,QAAS,CAChB,OAAI,KAAK,MAAM,MAEXoD,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,EACzB/G,MAAC,UAAO,qCAAyB,EACjCE,OAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,SAAU,GAAI,UAAW,GACtD,eAAK,MAAM,MAAM,MAAI,KAAK,MAAM,UAAU,KAAG,KAAK,MAAM,MAAM,SACjE,GACF,EAGG,KAAK,MAAM,QACpB,CACF,CC5KA,MAAM88B,GAAQ,CAAC,WAAY,OAAQ,MAAM,EACnCC,GAAU,CAAC,UAAW,QAAS,SAAS,EAIxCC,GAAqD,CACzD,CAAE,MAAO,MAAO,MAAO,OACvB,CAAE,MAAO,mBAAoB,MAAO,yBACpC,CAAE,MAAO,sBAAuB,MAAO,4BACvC,CAAE,MAAO,kBAAmB,MAAO,wBACnC,CAAE,MAAO,gBAAiB,MAAO,sBACjC,CAAE,MAAO,gBAAiB,MAAO,uBACjC,CAAE,MAAO,aAAc,MAAO,mBAChC,EAEMC,GAAiB,MAAM,KAAK,CAAE,OAAQ,IAAM,CAACxX,EAAGvqB,IAAMA,EAAI,CAAC,EAC3DgiC,GAAe,MAAM,KAAK,CAAE,OAAQ,IAAM,CAACzX,EAAGnY,KAAO,CACzD,MAAOA,EACP,MAAOA,IAAM,EAAI,QAAUA,EAAI,GAAK,GAAGA,CAAC,MAAQA,IAAM,GAAK,QAAU,GAAGA,EAAI,EAAE,KAChF,EAAE,EACI6vB,GAAuD,CAC3D,CAAE,MAAO,IAAK,MAAO,aACrB,CAAE,MAAO,IAAK,MAAO,UACrB,CAAE,MAAO,IAAK,MAAO,UACrB,CAAE,MAAO,IAAK,MAAO,WACrB,CAAE,MAAO,IAAK,MAAO,aACrB,CAAE,MAAO,IAAK,MAAO,YACrB,CAAE,MAAO,IAAK,MAAO,UACrB,CAAE,MAAO,IAAK,MAAO,WACvB,EAEMC,GAA0D,CAC9D,CAAE,MAAO,IAAK,MAAO,WACrB,CAAE,MAAO,IAAK,MAAO,WACrB,CAAE,MAAO,IAAK,MAAO,SACrB,CAAE,MAAO,IAAK,MAAO,OACvB,EAIA,SAASC,GAAgBC,EAAoE,CAC3F,GAAI,OAAOA,GAAS,SAAU,OAAO,KACrC,MAAMviC,EAAQuiC,EAAK,OAAO,MAAM,KAAK,EACrC,GAAIviC,EAAM,SAAW,EAAG,OAAO,KAC/B,KAAM,CAAC4T,EAAGrB,EAAA,EAAOiwB,CAAG,EAAIxiC,EAGlByiC,EAAS,SAAS7uB,EAAG,EAAE,EACvB8uB,EAAU,SAASnwB,EAAG,EAAE,EAE9B,GADI,CAAC,OAAO,SAASkwB,CAAM,GAAK,CAAC,OAAO,SAASC,CAAO,GACpD9uB,IAAM,OAAO6uB,CAAM,GAAKlwB,IAAM,OAAOmwB,CAAO,EAAG,OAAO,KAC1D,MAAMC,EAAWH,IAAQ,IAAM,IAAM,SAASA,EAAK,EAAE,EACrD,OAAIG,IAAa,MAASH,IAAQ,KAAO,CAAC,OAAO,SAASG,CAAQ,EAAW,KACtE,CAAE,OAAQF,EAAQ,KAAMC,EAAS,IAAKF,IAAQ,IAAM,IAAM,OAAOG,CAAQ,EAClF,CAEA,SAASC,GAAmB,EAA+C,CACzE,GAAI,OAAO,GAAM,SAAU,OAAO,KAClC,MAAMhvB,EAAI,sBAAsB,KAAK,EAAE,MAAM,EAC7C,OAAKA,EACE,CAAE,EAAG,SAASA,EAAE,CAAC,EAAG,EAAE,EAAG,KAAMA,EAAE,CAAC,EAAE,aAAY,EADxC,IAEjB,CAwBA,SAASivB,GAAkBhI,EAAiC,SAC1D,GAAI,CAACA,EACH,MAAO,CACL,KAAM,GACN,KAAM,OACN,WAAY,EACZ,SAAU,GACV,QAAS,IACT,aAAc,GACd,QAAS,aACT,UAAW,GACX,aAAc,IACd,OAAQ,GACR,SAAU,MACV,eAAgB,GAChB,WAAY,QACZ,aAAc,GACd,aAAc,GACd,gBAAiB,GACjB,cAAe,EACf,QAAS,GACT,WAAY,IAGhB,MAAM7nB,EAAS6nB,EAAQ,OAAS,OAASyH,GAAgBzH,EAAQ,QAAQ,EAAI,KACvEiI,EAAiBjI,EAAQ,OAAS,WAAa+H,GAAmB/H,EAAQ,QAAQ,EAAI,KACtFkI,EAAKlI,EAAQ,UAAY,MACzBmI,EAAUf,GAAU,KAAMx4B,GAAMA,EAAE,QAAUs5B,CAAE,EACpD,MAAO,CACL,KAAMlI,EAAQ,MAAQ,GACtB,KAAMA,EAAQ,KACd,YAAY7nB,GAAA,YAAAA,EAAQ,SAAU,EAC9B,UAAUA,GAAA,YAAAA,EAAQ,OAAQ,EAC1B,SAASA,GAAA,YAAAA,EAAQ,MAAO,IACxB,aAAc,CAACA,EACf,QAAS6nB,EAAQ,SACjB,WAAWiI,GAAA,YAAAA,EAAgB,IAAK,GAChC,cAAcA,GAAA,YAAAA,EAAgB,OAAQ,IACtC,OAAQjI,EAAQ,OAAS,OAASoI,GAAgBpI,EAAQ,QAAQ,EAAI,GACtE,SAAUmI,EAAUD,EAAK,SACzB,eAAgBC,EAAU,GAAKD,EAC/B,WAAYlI,EAAQ,OAAO,KAC3B,aAAcA,EAAQ,OAAO,QAAU,GACvC,aAAcA,EAAQ,OAAO,QAAU,GACvC,gBAAiB,CAAC,GAAC73B,EAAA63B,EAAQ,cAAR,MAAA73B,EAAqB,iBACxC,cAAe,OAAO,UAASqG,EAAAwxB,EAAQ,cAAR,YAAAxxB,EAAqB,aAAa,EAC7DwxB,EAAQ,YAAa,cACrB,EACJ,QAASA,EAAQ,UAAY,GAC7B,WAAY,GAEhB,CAEA,SAASoI,GAAgBC,EAAqB,CAC5C,GAAI,CAACA,EAAK,MAAO,GACjB,GAAI,CACF,MAAM3qB,EAAI,IAAI,KAAK2qB,CAAG,EACtB,GAAI,OAAO,MAAM3qB,EAAE,SAAS,EAAG,MAAO,GAEtC,MAAM4qB,EAAOx2B,GAAc,OAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,EACpD,MAAO,GAAG4L,EAAE,aAAa,IAAI4qB,EAAI5qB,EAAE,WAAa,CAAC,CAAC,IAAI4qB,EAAI5qB,EAAE,SAAS,CAAC,IAAI4qB,EAAI5qB,EAAE,UAAU,CAAC,IAAI4qB,EAAI5qB,EAAE,YAAY,CAAC,EACpH,MAAQ,CACN,MAAO,EACT,CACF,CAGA,SAAS6qB,GAAgB,EAA0D,WACjF,GAAI,EAAE,OAAS,OAAQ,CACrB,GAAI,EAAE,aACJ,MAAO,CAAE,SAAU,EAAE,QAAQ,OAAQ,WAAY,EAAE,YAAc,EAAE,QAAQ,MAAK,EAElF,MAAMC,EAAO,GAAG,EAAE,UAAU,IAAI,EAAE,QAAQ,QAAQ,EAAE,OAAO,GACrDC,IAAUtgC,EAAAo/B,GAAY,KAAM7pB,GAAMA,EAAE,QAAU,EAAE,OAAO,IAA7C,YAAAvV,EAAgD,QAAS,GACnEugC,IAAYl6B,EAAA84B,GAAa,KAAM5vB,GAAMA,EAAE,QAAU,EAAE,QAAQ,IAA/C,YAAAlJ,EAAkD,QAAS,GAAG,EAAE,QAAQ,GACpFm6B,EAAS,OAAO,EAAE,UAAU,EAAE,SAAS,EAAG,GAAG,EAC7CC,EACJH,IAAY,YACR,gBAAgBC,EAAU,QAAQ,IAAK,EAAE,CAAC,SAASC,CAAM,IACzD,SAASF,CAAO,OAAOC,EAAU,QAAQ,IAAK,EAAE,CAAC,SAASC,CAAM,IACtE,MAAO,CAAE,SAAUH,EAAM,WAAY,EAAE,YAAcI,CAAA,CACvD,CACA,GAAI,EAAE,OAAS,WAAY,CACzB,MAAMC,IAAOhwB,EAAA2uB,GAAe,KAAMsB,GAAMA,EAAE,QAAU,EAAE,YAAY,IAArD,YAAAjwB,EAAwD,QAAS,EAAE,aAEhF,MAAO,CACL,SAFe,GAAG,EAAE,SAAS,GAAG,EAAE,YAAY,GAG9C,WAAY,EAAE,YAAc,SAAS,EAAE,SAAS,IAAIgwB,CAAI,GAE5D,CAEA,OAAK,EAAE,OAEA,CACL,SAFU,IAAI,KAAK,EAAE,MAAM,EAAE,cAG7B,WAAY,EAAE,YAAc,IAAI,KAAK,EAAE,MAAM,EAAE,gBAAe,EAJ1C,CAAE,SAAU,GAAI,WAAY,EAAE,YAAc,GAMpE,CAEO,SAASE,GAAU,CAAE,SAAAxyB,EAAU,gBAAAC,GAA0B,OAC9D,MAAMrH,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACR,CAACq7B,EAAWC,CAAY,EAAI5iC,WAAqBkQ,EAAS,WAAa,EAAE,EACzE,CAACzP,EAASC,CAAU,EAAIV,WAAS,CAACkQ,EAAS,SAAS,EAEpD5E,EAAS,SAAY,CACzB,GAAI,CACF,MAAM/H,EAAI,MAAM7B,EAAI,IAClB,8BAEFkhC,EAAar/B,EAAE,WAAa,EAAE,CAChC,OAAS3B,EAAK,CACZkH,EAAM,MAAM,0BAA2BlH,EAAc,OAAO,EAAE,CAChE,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,OACd,IAAID,EAAAoO,EAAS,YAAT,MAAApO,EAAoB,QAAUoO,EAAS,UAAW,CACpD0yB,EAAa1yB,EAAS,WAAa,EAAE,EACrCxP,EAAW,EAAK,EAChB,MACF,CACA4K,EAAA,CAEF,EAAG,CAAC4E,EAAS,SAAS,CAAC,EAEvB,MAAM2yB,EAAclJ,GAAuB,CACzCtyB,EAAM,KAAK,CACT,MAAOsyB,EAAU,kBAAkBA,EAAQ,IAAI,GAAK,eACpD,MAAO,IACP,SACE91B,MAACi/B,GAAA,CACC,QAAAnJ,EACA,QAAStyB,EAAM,MACf,YAAa,MAAOiwB,GAAU,CAC5BsL,EAAcp3B,GAAQ,CACpB,MAAMjH,EAAMiH,EAAI,UAAWxB,GAAMA,EAAE,KAAOstB,EAAM,EAAE,EAClD,GAAI/yB,IAAQ,GAAI,MAAO,CAAC,GAAGiH,EAAK8rB,CAAK,EACrC,MAAMyL,EAAOv3B,EAAI,QACjB,OAAAu3B,EAAKx+B,CAAG,EAAI+yB,EACLyL,CACT,CAAC,EACDj6B,EAAM,QAAQ6wB,EAAU,oBAAsB,mBAAmB,EACjEtyB,EAAM,QACN,MAAM8I,EAAA,CACR,EACA,QAAUtO,GAAQiH,EAAM,MAAMjH,CAAG,GACnC,CAEH,CACH,EAEMmhC,EAAQ,MAAOh5B,GAAgB,OACnC,GAAI,CACF,MAAMzG,EAAI,MAAM7B,EAAI,KAClB,cAAc,mBAAmBsI,EAAE,EAAE,CAAC,QAExClB,EAAM,QAAQvF,EAAE,GAAK,gBAAkB,iBAAezB,EAAAyB,EAAE,YAAF,YAAAzB,EAAa,QAAS,SAAS,EAAE,EACvF,MAAMwJ,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,eAAgBlH,EAAc,OAAO,EAAE,CACrD,CACF,EAEMuZ,EAAW,MAAOnR,GAAgB,CACtC,GAAK,QAAQ,oBAAoBA,EAAE,IAAI,IAAI,EAC3C,GAAI,CACF,MAAMtI,EAAI,IAAI,cAAc,mBAAmBsI,EAAE,EAAE,CAAC,EAAE,EACtD44B,EAAcp3B,GAAQA,EAAI,OAAQpI,GAAMA,EAAE,KAAO4G,EAAE,EAAE,CAAC,EACtDlB,EAAM,QAAQ,mBAAmB,CACnC,OAASlH,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEA,OAAInB,EAEAoD,MAAC,OAAI,UAAU,eAAe,eAACuO,GAAA,CAAQ,KAAK,KAAK,EAAE,EAKrDrO,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC6B,GAAA,CAAM,KAAM,GAAI,EAAE,eAAai9B,EAAU,OAAO,KACnD,EACA5+B,OAAC,KAAE,UAAU,gBAAgB,qDACaF,MAAC,UAAQ,WAAA/B,EAAAoO,EAAS,gBAAT,YAAApO,EAAwB,OAAQ,SAAS,EAAS,iDAErG,GACF,EACAiC,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAAS4D,EAC7C,UAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,EACAD,OAAC2D,GAAO,QAAQ,UAAU,KAAK,KAAK,QAAS,IAAMm7B,EAAA,EACjD,UAAAh/B,MAAC8D,GAAA,CAAK,KAAM,GAAI,EAAE,iBACpB,GACF,GACF,EAECg7B,EAAU,SAAW,EACpB9+B,MAACgM,GAAA,CACC,KAAMhM,MAAC6B,GAAA,CAAM,KAAM,GAAI,EACvB,MAAM,eACN,QACEwK,EAAS,cACL,kGACA,iDAIRrM,MAAC,OAAI,UAAU,gBACZ,SAAA8+B,EAAU,IAAK34B,GAAA,OACdjG,cAAC0K,EAAA,CAAgB,UAAU,gBACzB,UAAA1K,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OACC,UAAAF,MAACkL,GAAA,CAAW,WAAE,KAAK,SAClBC,GAAA,CACC,UAAAnL,MAAC,QAAM,WAAE,KAAK,EAAO,KAAG,IACxBA,MAAC,QAAK,MAAOmG,EAAE,SAAW,SAAAi5B,GAAiBj5B,CAAC,GAAKA,EAAE,SAAS,EAC3DA,EAAE,UAAYA,EAAE,WAAa,MAAQjG,OAAAO,WAAA,CAAE,gBAAGT,MAAC,QAAM,SAAAmG,EAAE,SAAS,GAAO,EAAM,KACzE,MACDnG,MAAC,QAAK,UAAWmG,EAAE,QAAU,YAAc,iBACxC,SAAAA,EAAE,QAAU,UAAY,WAC3B,GACF,GACF,EACAjG,OAAC,OAAI,UAAU,wBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAMm7B,EAAW74B,CAAC,EAC/D,UAAAnG,MAACuY,GAAA,CAAO,KAAM,GAAI,EAAE,SACtB,EACArY,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAMs7B,EAAMh5B,CAAC,EAC1D,UAAAnG,MAACq/B,GAAA,CAAW,KAAM,GAAI,EAAE,YAC1B,EACAr/B,MAAC,UACC,KAAK,SACL,UAAU,2BACV,aAAW,SACX,MAAM,SACN,QAAS,IAAMsX,EAASnR,CAAC,EAEzB,SAAAnG,MAACiP,GAAA,CAAO,KAAM,GAAI,GACpB,EACF,GACF,EACA/O,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC,QAAK,UAAU,QAAQ,mBAAO,EAAQ,WACtC,QACE,UAAAmG,EAAE,OAAO,KAAK,IAAEA,EAAE,OAAO,QAC5B,EACCA,EAAE,OAAO,OAAS,SAAWA,EAAE,OAAO,QACrCjG,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC,QAAK,UAAU,QAAQ,mBAAO,EAAO,IAAEmG,EAAE,OAAO,QACnD,GAEJ,IACClI,EAAAkI,EAAE,cAAF,YAAAlI,EAAe,kBACdiC,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC,QAAK,UAAU,QAAQ,wBAAY,EAAQ,IAAI,wBAC1BmG,EAAE,YAAY,eAAiB,GACvD,EAEFjG,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,OACC,UAAAF,MAAC,QAAK,UAAU,QAAQ,gBAAI,EAAQ,IACnCmG,EAAE,QAAUoC,GAAepC,EAAE,OAAO,EAAI,IACxCA,EAAE,YACDnG,MAAC,QAAK,UAAW,OAAOs/B,GAAen5B,EAAE,UAAU,CAAC,GAAK,SAAAA,EAAE,WAAW,EAEvEA,EAAE,WACDjG,OAAC,QAAK,UAAU,4BAA4B,MAAOiG,EAAE,UAClD,cAAI,KAAGo5B,GAASp5B,EAAE,UAAW,EAAE,GAClC,GAEJ,SACC,OACC,UAAAnG,MAAC,QAAK,UAAU,QAAQ,gBAAI,EAAQ,IACnCmG,EAAE,QACDnG,MAAC,QAAK,MAAO,IAAI,KAAKmG,EAAE,OAAO,EAAE,cAC9B,SAAAq5B,GAAcr5B,EAAE,QAASA,EAAE,QAAQ,EACtC,EAEA,IAEDA,EAAE,SACDjG,OAAC,QAAK,UAAU,QAAQ,gBAAIqI,GAAepC,EAAE,OAAO,GAAE,GAE1D,GACF,EACCA,EAAE,SAAWA,EAAE,QAAQ,OAAS,GAC/BjG,OAAC,WAAQ,UAAU,wBACjB,UAAAA,OAAC,WACC,UAAAF,MAACuxB,GAAA,CAAQ,KAAM,GAAI,EAAE,IAAEprB,EAAE,QAAQ,OAAO,OAAKA,EAAE,QAAQ,SAAW,EAAI,GAAK,KAC7E,EACAnG,MAAC,MACE,SAAAmG,EAAE,QAAQ,MAAM,GAAG,EAAE,UAAU,IAAI,CAACqH,EAAGpS,WACrC,MACC,UAAA4E,MAAC,QAAK,UAAU,qBAAsB,SAAAuI,GAAeiF,EAAE,EAAE,EAAE,EAAQ,IACnExN,MAAC,QAAK,UAAW,OAAOs/B,GAAe9xB,EAAE,MAAM,CAAC,GAAK,SAAAA,EAAE,OAAO,EAC7DA,EAAE,OAAStN,OAAC,QAAK,UAAU,QAAQ,gBAAIq/B,GAAS/xB,EAAE,MAAO,EAAE,GAAE,IAHvDpS,CAIT,CACD,EACH,GACF,IA1FO+K,EAAE,EA4Fb,EACD,EACH,GAEJ,CAEJ,CAMA,SAAS84B,GAAoB,CAC3B,QAAAnJ,EACA,QAAA/wB,EACA,YAAA06B,EACA,QAAAC,CACF,EAKG,CACD,KAAM,CAAC/rB,EAAOgsB,CAAQ,EAAIxjC,WAAsB,IAAM2hC,GAAkBhI,CAAO,CAAC,EAC1E,CAAChpB,EAAYC,CAAa,EAAI5Q,WAAS,EAAK,EAC5CyjC,EAAgBrrB,UAAQ,IACxB2oB,GAAU,KAAMx4B,GAAMA,EAAE,QAAUiP,EAAM,QAAQ,EAAUA,EAAM,SAC7D,SACN,CAACA,EAAM,QAAQ,CAAC,EAEbksB,EAAS,CAA8BnyB,EAAQ/R,IAA0B,CAC7EgkC,EAAUh4B,IAAS,CAAE,GAAGA,EAAK,CAAC+F,CAAG,EAAG/R,CAAA,EAAQ,CAC9C,EAEMmkC,EAAe,MAAO1hC,GAAuB,CACjDA,EAAE,iBACF,MAAM2hC,EAAcpsB,EAAM,KAAK,OAC/B,GAAI,CAACosB,EAAa,CAChBL,EAAQ,mBAAmB,EAC3B,MACF,CACA,MAAMM,EAAW3B,GAAgB1qB,CAAK,EACtC,GAAI,CAACqsB,EAAS,SAAU,CACtBN,EAAQ,6BAA6B,EACrC,MACF,CACA,GAAI,CAAC/rB,EAAM,aAAa,OAAQ,CAC9B+rB,EAAQ,4BAA4B,EACpC,MACF,CACA,MAAM1B,EAAKrqB,EAAM,WAAa,SAAWA,EAAM,eAAe,OAASA,EAAM,SACvEssB,EAAyC,CAC7C,KAAMtsB,EAAM,WACZ,OAAQA,EAAM,aAAa,MAAK,EAE9BA,EAAM,aAAe,SAAWA,EAAM,aAAa,SACrDssB,EAAc,OAAStsB,EAAM,aAAa,QAE5C,MAAMusB,EAAmC,CACvC,KAAMH,EACN,KAAMpsB,EAAM,KACZ,SAAUqsB,EAAS,SACnB,SAAUhC,GAAM,MAChB,OAAQiC,EACR,YAAa,CACX,cAAetsB,EAAM,cACrB,gBAAiBA,EAAM,iBAEzB,QAASA,EAAM,SAEjB5G,EAAc,EAAI,EAClB,GAAI,CACF,MAAM0mB,EAAQqC,EACV,MAAMj4B,EAAI,IAAc,cAAc,mBAAmBi4B,EAAQ,EAAE,CAAC,GAAIoK,CAAO,EAC/E,MAAMriC,EAAI,KAAe,aAAcqiC,CAAO,EAClD,MAAMT,EAAYhM,CAAK,CACzB,OAAS11B,EAAK,CACZ2hC,EAAQ,GAAG5J,EAAU,SAAW,QAAQ,YAAa/3B,EAAc,OAAO,EAAE,CAC9E,SACEgP,EAAc,EAAK,CACrB,CACF,EAEA,OACE7M,OAAC,QAAK,UAAU,gBAAgB,SAAU4/B,EACxC,UAAA9/B,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,qBACZ,MAAO2T,EAAM,KACb,SAAWvV,GAAMyhC,EAAO,OAAQzhC,EAAE,OAAO,KAAK,EAC9C,UAAS,WAGV,OAAI,UAAU,gBACb,SAAA8B,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,UACC,UAAU,SACV,MAAO2T,EAAM,KACb,SAAWvV,GAAMyhC,EAAO,OAAQzhC,EAAE,OAAO,KAA4B,EAEpE,SAAA4+B,GAAM,IAAKt4B,GACV1E,MAAC,UAAe,MAAO0E,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,EACF,EACF,EAECiP,EAAM,OAAS,QACdzT,OAAC,OAAI,UAAU,sBACZ,WAACyT,EAAM,cACN3T,MAAAS,WAAA,CACE,SAAAP,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,uBAAW,EAC1CA,MAAC,UACC,UAAU,SACV,MAAO2T,EAAM,QACb,SAAWvV,GAAMyhC,EAAO,UAAWzhC,EAAE,OAAO,KAAK,EAEhD,SAAAi/B,GAAY,IAAK7pB,GAChBxT,MAAC,UAAqB,MAAOwT,EAAE,MAAQ,SAAAA,EAAE,OAA5BA,EAAE,KAAgC,CAChD,GACH,EACF,EACAtT,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,UACC,UAAU,SACV,MAAO,OAAO2T,EAAM,QAAQ,EAC5B,SAAWvV,GAAMyhC,EAAO,WAAY,SAASzhC,EAAE,OAAO,MAAO,EAAE,CAAC,EAE/D,SAAAg/B,GAAa,IAAK,SAChB,UAAqB,MAAO,OAAO,EAAE,KAAK,EAAI,WAAE,OAApC,EAAE,KAAwC,CACxD,GACH,EACF,EACAl9B,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCA,MAAC,UACC,UAAU,SACV,MAAO,OAAO2T,EAAM,UAAU,EAC9B,SAAWvV,GAAMyhC,EAAO,aAAc,SAASzhC,EAAE,OAAO,MAAO,EAAE,CAAC,EAEjE,YAAe,IAAKyQ,GACnB7O,MAAC,UAAe,MAAO,OAAO6O,CAAC,EAAI,gBAAOA,CAAC,EAAE,SAAS,EAAG,GAAG,GAA/CA,CAAiD,CAC/D,GACH,EACF,GACF,EACF,EAED8E,EAAM,cACLzT,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,2BAAe,EAC9CA,MAAC,SACC,UAAU,QACV,KAAK,OACL,MAAO2T,EAAM,QACb,SAAWvV,GAAMyhC,EAAO,UAAWzhC,EAAE,OAAO,KAAK,EACjD,YAAY,cACd,EACF,EAEF8B,OAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAM2/B,EAAO,eAAgB,CAAClsB,EAAM,YAAY,EAEzD,UAAA3T,MAACoB,GAAA,CACC,KAAM,GACN,MAAO,CACL,UAAWuS,EAAM,aAAe,iBAAmB,OACnD,WAAY,kBACd,GAEDA,EAAM,aAAe,gBAAkB,wBAC1C,EACF,EAGDA,EAAM,OAAS,YACdzT,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,iBAAK,EACpCA,MAAC,SACC,UAAU,QACV,KAAK,SACL,IAAK,EACL,MAAO2T,EAAM,UACb,SAAWvV,GAAMyhC,EAAO,YAAa,SAASzhC,EAAE,OAAO,MAAO,EAAE,GAAK,CAAC,GACxE,EACF,EACA8B,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,UACC,UAAU,SACV,MAAO2T,EAAM,aACb,SAAWvV,GAAMyhC,EAAO,eAAgBzhC,EAAE,OAAO,KAAK,EAErD,SAAAk/B,GAAe,IAAKsB,GACnB5+B,MAAC,UAAqB,MAAO4+B,EAAE,MAAQ,SAAAA,EAAE,OAA5BA,EAAE,KAAgC,CAChD,GACH,EACF,GACF,EAGDjrB,EAAM,OAAS,QACdzT,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCA,MAAC,SACC,UAAU,QACV,KAAK,iBACL,MAAO2T,EAAM,OACb,SAAWvV,GAAMyhC,EAAO,SAAUzhC,EAAE,OAAO,KAAK,GAClD,EACF,EAGF8B,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,oBAAQ,EACvCE,OAAC,UACC,UAAU,SACV,MAAO0/B,EACP,SAAWxhC,GAAMyhC,EAAO,WAAYzhC,EAAE,OAAO,KAAK,EAEjD,UAAA8+B,GAAU,IAAKx4B,GACd1E,MAAC,UAAqB,MAAO0E,EAAE,MAAQ,SAAAA,EAAE,OAA5BA,EAAE,KAAgC,CAChD,EACD1E,MAAC,UAAO,MAAM,SAAS,kBAAM,IAC/B,EACF,EACC2T,EAAM,WAAa,UAClBzT,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,qBAAS,EACxCA,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,eACZ,MAAO2T,EAAM,eACb,SAAWvV,GAAMyhC,EAAO,iBAAkBzhC,EAAE,OAAO,KAAK,GAC1D,EACF,GAEJ,EAEA8B,OAAC,OAAI,UAAU,gBACb,UAAAA,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCA,MAAC,UACC,UAAU,SACV,MAAO2T,EAAM,WACb,SAAWvV,GAAMyhC,EAAO,aAAczhC,EAAE,OAAO,KAAkC,EAEhF,SAAA6+B,GAAQ,IAAKv4B,GACZ1E,MAAC,UAAe,MAAO0E,EAAI,SAAAA,CAAA,EAAdA,CAAgB,CAC9B,GACH,EACF,EACAxE,OAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,KAAM,GAC9C,UAAAF,MAAC,SAAM,UAAU,cAAc,kBAAM,EACrCA,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAa2T,EAAM,aAAe,UAAY,cAAgBA,EAAM,aAAe,QAAU,yBAA2B,UACxH,MAAOA,EAAM,aACb,SAAWvV,GAAMyhC,EAAO,eAAgBzhC,EAAE,OAAO,KAAK,GACxD,EACF,GACF,EAECuV,EAAM,aAAe,SACpBzT,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,2CAA+B,EAC9DA,MAAC,YACC,UAAU,QACV,KAAM,EACN,YAAY,sEACZ,MAAO2T,EAAM,aACb,SAAWvV,GAAMyhC,EAAO,eAAgBzhC,EAAE,OAAO,KAAK,GACxD,EACF,EAGF8B,OAAC,YAAS,UAAU,uBAClB,UAAAF,MAAC,UAAO,6BAAiB,EACzBE,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS2T,EAAM,gBACf,SAAWvV,GAAMyhC,EAAO,kBAAmBzhC,EAAE,OAAO,OAAO,IAE7D4B,MAAC,QAAK,6EAAiE,GACzE,EACAE,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,mCAAuB,EACtDA,MAAC,SACC,UAAU,QACV,KAAK,SACL,IAAK,EACL,IAAK,GACL,MAAO2T,EAAM,cACb,SAAWvV,GAAMyhC,EAAO,gBAAiB,SAASzhC,EAAE,OAAO,MAAO,EAAE,GAAK,CAAC,EAC1E,SAAU,CAACuV,EAAM,iBACnB,EACF,GACF,EAEAzT,OAAC,SAAM,UAAU,eACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS2T,EAAM,QACf,SAAWvV,GAAMyhC,EAAO,UAAWzhC,EAAE,OAAO,OAAO,IAErD4B,MAAC,QAAK,mBAAO,GACf,EAEAE,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,SAAS,QAASkB,EAAS,SAAU+H,EAAY,kBAE9E,EACA9M,MAAC6D,EAAA,CAAO,QAAQ,UAAU,KAAK,SAAS,SAAUiJ,EAC/C,SAAAgpB,EAAU,OAAS,SACtB,GACF,GACF,CAEJ,CAMA,SAASsJ,GAAiB,EAAqB,SAC7C,GAAI,EAAE,OAAS,OAAQ,OAAO,EAAE,SAChC,MAAMnxB,EAASsvB,GAAgB,EAAE,QAAQ,EACzC,GAAI,CAACtvB,EAAQ,OAAO,EAAE,SACtB,MAAMswB,IAAUtgC,EAAAo/B,GAAY,KAAM7pB,GAAMA,EAAE,QAAUvF,EAAO,GAAG,IAA9C,YAAAhQ,EAAiD,QAAS,GACpEugC,IAAYl6B,EAAA84B,GAAa,KAAM5vB,GAAMA,EAAE,QAAUS,EAAO,IAAI,IAAhD,YAAA3J,EAAmD,QAAS,GAAG2J,EAAO,IAAI,GACtFwwB,EAAS,OAAOxwB,EAAO,MAAM,EAAE,SAAS,EAAG,GAAG,EACpD,OAAIswB,IAAY,YAAoB,gBAAgBC,CAAS,KAAKC,CAAM,GACjE,SAASF,CAAO,OAAOC,CAAS,KAAKC,CAAM,EACpD,CAEA,SAASe,GAAcrB,EAAaH,EAA4B,CAC9D,GAAI,CACF,OAAO,IAAI,KAAKG,CAAG,EAAE,eAAe,OAAW,CAC7C,SAAUH,GAAM,OAChB,QAAS,OACT,KAAM,UACN,OAAQ,UACR,MAAO,QACP,IAAK,UACN,CACH,MAAQ,CACN,OAAO,IAAI,KAAKG,CAAG,EAAE,gBACvB,CACF,CAEA,SAASmB,GAAepkC,EAAwB,CAC9C,OAAIA,IAAW,UAAkB,cAC7BA,IAAW,UAAkB,cAC1B,WACT,CAEA,SAASqkC,GAAS,EAAWY,EAAqB,CAChD,OAAI,EAAE,QAAUA,EAAY,EACrB,EAAE,MAAM,EAAGA,EAAM,CAAC,EAAI,GAC/B,CCxvBA,MAAM5+B,GAAc,CAClB,CAAE,GAAI,MAAW,MAAO,MAAW,KAAMK,EAAA,EACzC,CAAE,GAAI,UAAW,MAAO,UAAW,KAAM9I,EAAA,EACzC,CAAE,GAAI,OAAW,MAAO,OAAW,KAAMoB,EAAA,EACzC,CAAE,GAAI,UAAW,MAAO,UAAW,KAAM4G,EAAA,CAC3C,EAEMs/B,GAAuC,CAC3C,QAAS,UACT,KAAS,OACT,QAAS,SACX,EAEMC,GAA8C,CAClD,QAASvnC,GACT,KAASoB,GACT,QAAS4G,EACX,EAEA,SAASw/B,GAAY,CAAE,SAAAj0B,EAAU,gBAAAC,GAA0B,CACzD,MAAMrH,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACR,CAAC88B,EAAQC,CAAS,EAAUrkC,WAAkB,EAAE,EAChD,CAACskC,EAAQC,CAAS,EAAUvkC,WAAS,CAAE,QAAS,EAAG,KAAM,EAAG,QAAS,EAAG,IAAK,EAAG,EAChF,CAACS,EAASC,CAAU,EAAQV,WAAS,EAAI,EACzC,CAAC8F,EAAWoJ,CAAY,EAAKlP,WAAiD,KAAK,EACnF,CAACwkC,EAASC,CAAU,EAAQzkC,WAAS,EAAE,EACvC,CAAC0kC,EAAeC,CAAgB,EAAI3kC,WAAyB,IAAI,EACjE,CAAC4kC,EAAWC,CAAY,EAAI7kC,WAAS,EAAK,EAE1CsL,EAAS,SAAY,WACzB5K,EAAW,EAAI,EACf,GAAI,CACF,MAAM2W,EAAI,MAAM3V,EAAI,IAAyD,SAAS,EACtF2iC,EAAUhtB,EAAE,QAAU,EAAE,EACxBktB,EAAU,CAAE,UAASziC,EAAAuV,EAAE,SAAF,YAAAvV,EAAU,UAAW,EAAG,OAAMqG,EAAAkP,EAAE,SAAF,YAAAlP,EAAU,OAAQ,EAAG,UAASqK,EAAA6E,EAAE,SAAF,YAAA7E,EAAU,UAAW,EAAG,KAAM6E,EAAE,QAAU,IAAI,OAAQ,CACzI,OAASzV,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CAAEuJ,EAAA,CAAU,EAAG,EAAE,EAGjCvJ,YAAU,IAAM,CACd,GAAI,CAACyiC,EAAQ,OAAQ,CACnBG,EAAiB,IAAI,EACrB,MACF,CACAE,EAAa,EAAI,EACjB,MAAM/4B,EAAK,WAAW,SAAY,CAChC,GAAI,CACF,MAAMuL,EAAI,MAAM3V,EAAI,IAClB,oBAAoB,mBAAmB8iC,EAAQ,MAAM,CAAC,IAExDG,EAAiBttB,EAAE,SAAW,EAAE,CAClC,OAASzV,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,SACEijC,EAAa,EAAK,CACpB,CACF,EAAG,GAAG,EACN,MAAO,IAAM,aAAa/4B,CAAE,CAC9B,EAAG,CAAC04B,CAAO,CAAC,EAEZ,MAAMM,EAAY1sB,UAAiB,IAC7BssB,IAAkB,KAAaA,EAC/B5+B,IAAc,MAAcs+B,EACzBA,EAAO,OAAQp6B,GAAMA,EAAE,SAAWlE,CAAS,EACjD,CAACs+B,EAAQt+B,EAAW4+B,CAAa,CAAC,EAE/Bx9B,EAAY,SAAY,CAC5B,GAAI,CACF,MAAMxF,EAAI,KAAK,kBAAmB,EAAE,EACpCoH,EAAM,QAAQ,mBAAmB,EACjC,MAAMwC,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EAEMmjC,EAAe,MAAOC,GAAiB,CAC3C,GAAI,CACF,MAAMhkB,EAAO,MAAMtf,EAAI,IACrB,WAAW,mBAAmBsjC,EAAM,MAAM,CAAC,IAAI,mBAAmBA,EAAM,IAAI,CAAC,IAE/E39B,EAAM,KAAK,CACT,MAAO2Z,EAAK,KACZ,MAAO,IACP,SACEjd,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAU,qBAAqB,cAAamd,EAAK,OACpD,SAAAijB,GAAajjB,EAAK,MAAM,GAAKA,EAAK,OACrC,EACAnd,MAAC,QAAK,UAAU,qBAAsB,WAAK,KAAK,GAClD,EACCmd,EAAK,aACJnd,MAAC,KAAE,UAAU,oBAAqB,WAAK,YAAY,EAEpDmd,EAAK,MACJnd,MAAC,OAAI,UAAU,oBACb,SAAAA,MAAC,OAAI,UAAU,iBAAkB,SAAAmd,EAAK,KAAK,EAC7C,GAEJ,EAEF,OACEnd,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,iBAAK,EAE9D,CACH,MAAQ,CAENA,EAAM,KAAK,CACT,MAAO29B,EAAM,KACb,MAAO,IACP,SACEjhC,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAU,qBAAqB,cAAamhC,EAAM,OACrD,SAAAf,GAAae,EAAM,MAAM,GAAKA,EAAM,OACvC,EACAnhC,MAAC,QAAK,UAAU,qBAAsB,WAAM,KAAK,GACnD,EACCmhC,EAAM,aACLnhC,MAAC,KAAE,UAAU,oBAAqB,WAAM,YAAY,GAExD,EAEF,OACEA,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAML,EAAM,QAAS,iBAAK,EAE9D,CACH,CACF,EAEA,OACEtD,OAAC,OAAI,UAAU,mBAEb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC4B,GAAA,CAAS,KAAM,GAAI,EAAE,WACxB,EACA5B,MAAC,KAAE,UAAU,gBAAgB,2EAE7B,GACF,EACAE,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,eACb,UAAAF,MAACsG,GAAA,CAAO,KAAM,GAAI,EAClBtG,MAAC,SACC,UAAU,QACV,KAAK,OACL,YAAY,iBACZ,MAAO2gC,EACP,SAAWviC,GAAMwiC,EAAWxiC,EAAE,OAAO,KAAK,IAE3CuiC,GACC3gC,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,eACX,QAAS,IAAM4gC,EAAW,EAAE,EAE5B,SAAA5gC,MAACoe,GAAA,CAAQ,KAAM,GAAI,GACrB,EAEJ,SACCva,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASR,EAC7C,UAAArD,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,GACF,GACF,EAGC,CAACwgC,EAAQ,QACR3gC,MAAC,OAAI,UAAU,cACZ,SAAAuB,GAAK,IAAK2B,GAAQ,CACjB,MAAMC,EAAOD,EAAI,KACXwG,EAAQxG,EAAI,KAAO,MACrBu9B,EAAO,IACPA,EAAOv9B,EAAI,EAAyB,GAAK,EAC7C,OACEhD,OAAC,UAEC,KAAK,SACL,UAAW+C,EAAG,aAAchB,IAAciB,EAAI,IAAM,mBAAmB,EACvE,QAAS,IAAMmI,EAAanI,EAAI,EAAE,EAElC,UAAAlD,MAACmD,EAAA,CAAK,KAAM,GAAI,EAChBnD,MAAC,QAAM,SAAAkD,EAAI,MAAM,EACjBlD,MAAC,QAAK,UAAU,mBAAoB,SAAA0J,CAAA,CAAM,IAPrCxG,EAAI,GAUf,CAAC,EACH,EAIDy9B,EAAQ,QACPzgC,OAAC,WAAQ,UAAU,iBACjB,UAAAA,OAAC,MAAG,UAAU,uBACZ,UAAAF,MAACsG,GAAA,CAAO,KAAM,GAAI,EAAE,kBACnBy6B,GAAa/gC,MAACuO,GAAA,CAAQ,KAAK,KAAK,GACnC,EACCwyB,EACC/gC,MAAC,OAAI,UAAU,cACZ,UAAC,EAAG,EAAG,CAAC,EAAE,IAAK5E,GACd4E,MAAC,OAAY,UAAU,kCAAb5E,CAA8C,CACzD,EACH,EACEylC,GAAiBA,EAAc,SAAW,EAC5C7gC,MAACgM,GAAA,CACC,KAAMhM,MAACsG,GAAA,CAAO,KAAM,GAAI,EACxB,MAAM,aACN,QAAS,oBAAoBq6B,CAAO,OAGtC3gC,MAAC,OAAI,UAAU,cACX,UAAA6gC,GAAiB,IAAI,IAAI,CAAC16B,EAAG/K,IAC7B4E,MAACohC,GAAA,CAEC,MAAOj7B,EACP,OAAQ,IAAM+6B,EAAa/6B,CAAC,EAC5B,QAAAw6B,CAAA,EAHK,UAAUvlC,CAAC,GAKnB,EACH,GAEJ,EAID,CAACulC,EAAQ,cACP,WAAQ,UAAU,iBAChB,SAAA/jC,EACCoD,MAAC,OAAI,UAAU,eAAe,eAACuO,GAAA,CAAQ,KAAK,KAAK,EAAE,EACjD0yB,EAAU,SAAW,EACvBjhC,MAACgM,GAAA,CACC,KAAMhM,MAAC+7B,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,iBACN,QACE95B,IAAc,MACV,mGACA,oBAAoBm+B,GAAan+B,CAAS,CAAC,gBAIlD,OAAI,UAAU,cACZ,SAAAg/B,EAAU,IAAI,CAAC96B,EAAG/K,IACjB4E,MAACohC,GAAA,CAEC,MAAOj7B,EACP,OAAQ,IAAM+6B,EAAa/6B,CAAC,GAFvB,GAAGA,EAAE,MAAM,IAAIA,EAAE,IAAI,IAAI/K,CAAC,GAIlC,EACH,EAEJ,EAID,CAACulC,EAAQ,QACR3gC,MAAC,UAAO,UAAU,cAChB,SAAAE,OAAC,QAAK,UAAU,gBAAgB,uCACH,IAC3BF,MAAC,QAAK,+BAAmB,EAAO,IAAE,IAClCA,MAAC,QAAK,6BAAiB,EAAO,IAAE,IAChCA,MAAC,QAAK,8BAAkB,EAAO,oCACjC,EACF,GAEJ,CAEJ,CAIA,SAASohC,GAAU,CACjB,MAAAD,EACA,OAAAE,EACA,QAAAV,EAAU,EACZ,EAIG,CACD,MAAMx9B,EAAOk9B,GAAYc,EAAM,MAAM,GAAKroC,GACpCwoC,EAAOH,EAAM,YACfA,EAAM,YAAY,OAAS,IACzBA,EAAM,YAAY,MAAM,EAAG,GAAG,EAAI,IAClCA,EAAM,YACR,kBAEJ,cACGv2B,EAAA,CAAK,QAAQ,WAAW,YAAW,GAAC,UAAU,aAC7C,UAAA1K,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,OACC,UAAU,kBACV,MAAO,CAAE,WAAY,sDAErB,SAAAA,MAACmD,EAAA,CAAK,KAAM,GAAI,IAElBjD,OAAC,OAAI,UAAU,wBACb,UAAAF,MAAC,OAAI,UAAU,mBACZ,YAAemhC,EAAM,KAAMR,CAAO,EACrC,EACA3gC,MAAC,QAAK,UAAU,qBAAqB,cAAamhC,EAAM,OACrD,SAAAf,GAAae,EAAM,MAAM,GAAKA,EAAM,OACvC,GACF,GACF,EACAnhC,MAAC,KAAE,UAAU,kBAAmB,SAAAshC,EAAK,EACrCthC,MAAC,OAAI,UAAU,qBACb,SAAAE,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASw9B,EACzC,UAAArhC,MAAC6L,GAAA,CAAa,KAAM,GAAI,EAAE,SAC5B,EACF,GACF,CAEJ,CAGA,SAAS01B,GAAe/yB,EAAcrJ,EAA4B,CAChE,GAAI,CAACA,EAAE,OAAQ,OAAOqJ,EACtB,MAAM9N,EAAM8N,EAAK,cAAc,QAAQrJ,EAAE,aAAa,EACtD,OAAIzE,EAAM,EAAU8N,EAElBtO,OAAAO,WAAA,CACG,UAAA+N,EAAK,MAAM,EAAG9N,CAAG,EAClBV,MAAC,QAAK,UAAU,kBAAmB,SAAAwO,EAAK,MAAM9N,EAAKA,EAAMyE,EAAE,MAAM,EAAE,EAClEqJ,EAAK,MAAM9N,EAAMyE,EAAE,MAAM,GAC5B,CAEJ,CACO,MAAMq8B,GAAS5wB,GAAM,KAAK0vB,EAAW,EC5RrC,SAASmB,GAAe,CAAE,WAAAn2B,EAAY,UAAAjI,EAAW,kBAAAq+B,GAA4B,CAClF,MAAMz8B,EAAQC,GAAA,EACR,CAACvK,EAAM4Q,CAAO,EAAIpP,WAAoC,IAAI,EAC1D,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EAErCsL,EAAS,MAAOk6B,GAAyB,CAC7C9kC,EAAW,EAAI,EACf,GAAI,CACF,KAAM,CAAC4O,EAAQD,EAAQE,EAAUk2B,CAAO,EAAI,MAAM,QAAQ,IAAI,CAC5D/jC,EAAI,IAAoB,iBAAkB8jC,CAAM,EAAE,MAAM,IAAM,IAAI,EAClE9jC,EAAI,IAAkB,iBAAkB8jC,CAAM,EAAE,MAAM,IAAM,IAAI,EAChE9jC,EAAI,IAAmB,yBAA0B8jC,CAAM,EAAE,MAAM,IAAM,IAAI,EACzE9jC,EAAI,IAAkB,kBAAmB8jC,CAAM,EAAE,MAAM,IAAM,IAAI,EAClE,EACDp2B,EAAQ,CACN,OAAQE,GAAU,CAChB,MAAO,EACP,OAAQ,eACR,OAAQ,GACR,QAAS,0BAEX,MAAO,CACL,OAAQ,CAAC,EAACD,GAAA,MAAAA,EAAQ,aAClB,WAAWA,GAAA,YAAAA,EAAQ,YAAa,GAChC,MAAMA,GAAA,YAAAA,EAAQ,OAAQ,aACtB,WAAWA,GAAA,YAAAA,EAAQ,YAAa,EAChC,WAAWo2B,iBAAS,QAAS,EAC7B,YAAa,EACb,QAAS,GACT,aAAc,KACd,UAAUp2B,GAAA,YAAAA,EAAQ,WAAY,KAC9B,WAAWA,GAAA,YAAAA,EAAQ,SAAU,MAE/B,SAAUE,GAAY,CACpB,QAAS,GACT,IAAK,KACL,KAAM,YACN,KAAM,KACN,cAAe,EACf,kBAAmB,EACnB,cAAe,MAEjB,QAASk2B,GAAW,CAAE,MAAO,EAAG,UAAW,EAAC,CAAE,CAC/C,CACH,OAAS7jC,EAAK,CACZkH,EAAM,MAAM,2BAA4BlH,EAAc,OAAO,EAAE,CACjE,SACElB,EAAW,EAAK,CAClB,CACF,EASA,GAPAqB,YAAU,IAAM,CACd,MAAM2jC,EAAO,IAAI,gBACjB,OAAKp6B,EAAOo6B,EAAK,MAAM,EAChB,IAAMA,EAAK,OAEpB,EAAG,CAACv2B,CAAU,CAAC,EAEX1O,GAAW,CAACjC,EACd,OACEuF,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,oCAAwB,GAC7B,EAGJ,GAAI,CAACrF,EACH,OAAOqF,MAAC,OAAI,UAAU,QAAQ,qCAAyB,EAGzD,KAAM,CAAE,OAAAyL,EAAQ,MAAAq2B,EAAO,SAAAp2B,EAAU,QAAAk2B,GAAYjnC,EACvConC,EACJt2B,EAAO,OAAS,GAAK,iBACrBA,EAAO,OAAS,GAAK,iBACrB,eAEF,OACEvL,OAAC,OAAI,UAAU,kBAEb,UAAAA,OAAC0K,EAAA,CAAK,QAAQ,WAAW,UAAU,qBACjC,UAAA1K,OAAC,OAAI,UAAU,sBAAsB,MAAO,CAAE,YAAa6hC,GACzD,UAAA/hC,MAAC,QAAK,UAAU,4BAA4B,MAAO,CAAE,MAAO+hC,CAAA,EACzD,SAAAt2B,EAAO,MACV,EACAzL,MAAC,QAAK,UAAU,4BAA4B,iBAAK,GACnD,EACAE,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,MAAG,UAAU,sBACZ,UAAAF,MAAC2B,GAAA,CAAS,KAAM,GAAI,EAAE,kBACN,IAChB3B,MAAC,QAAK,MAAO,CAAE,MAAO+hC,GAAe,WAAO,OAAO,GACrD,EACA/hC,MAAC,KAAE,UAAU,wBAAyB,WAAO,QAAQ,SACpD6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASR,EACzC,UAAArD,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,GACF,GACF,EAGAD,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,UACC,KAAK,SACL,UAAU,qBACV,QAAS,IAAMwhC,EAAkB,UAAU,EAE3C,UAAA1hC,MAAC7J,GAAA,CAAM,KAAM,GAAI,EACjB6J,MAAC,QAAK,oBAAQ,EACdA,MAAC,QAAK,UAAWiD,EAAG,4BAA6ByI,EAAS,QAAU,KAAO,KAAK,EAC7E,SAAAA,EAAS,QAAU,UAAY,UAClC,KAEFxL,OAAC,UACC,KAAK,SACL,UAAU,qBACV,QAAS,IAAMwhC,EAAkB,UAAU,EAE3C,UAAA1hC,MAAC8L,GAAA,CAAS,KAAM,GAAI,EACpB9L,MAAC,QAAK,0BAAc,EACpBE,OAAC,QAAK,UAAW+C,EAAG,4BAA6B6+B,EAAM,OAAS,KAAO,KAAK,EACzE,UAAAA,EAAM,UAAU,UACnB,KAEF5hC,OAAC,UACC,KAAK,SACL,UAAU,qBACV,QAAS,IAAMwhC,EAAkB,KAAK,EAEtC,UAAA1hC,MAACnI,GAAA,CAAU,KAAM,GAAI,EACrBmI,MAAC,QAAK,oBAAQ,EACdA,MAAC,QAAK,UAAWiD,EACf,4BACA6+B,EAAM,WAAa,KAAO,KAAOA,EAAM,SAAW,KAAO,QAExD,WAAM,WAAa,KAAO,IAAMA,EAAM,SAAW,QAAU,QAC9D,KAEF5hC,OAAC,UACC,KAAK,SACL,UAAU,qBACV,QAAS,IAAMwhC,EAAkB,UAAU,EAE3C,UAAA1hC,MAACsG,GAAA,CAAO,KAAM,GAAI,EAClBtG,MAAC,QAAK,2BAAe,EACrBA,MAAC,QAAK,UAAU,+BAA+B,wBAAY,IAC7D,EACF,EAGAE,OAAC,OAAI,UAAU,mBACb,UAAAF,MAACgiC,GAAA,CACC,KAAMhiC,MAAC7J,GAAA,CAAM,KAAM,GAAI,EACvB,MAAM,WACN,MAAOuV,EAAS,QAAU,aAAaA,EAAS,iBAAiB,SAAW,UAC5E,IAAKA,EAAS,QAAU,GAAGA,EAAS,aAAa,kBAAoB,gCACrE,QAAS,IAAMg2B,EAAkB,UAAU,IAE7C1hC,MAACgiC,GAAA,CACC,KAAMhiC,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,WACN,MAAO,GAAGg2B,EAAM,SAAS,SACzB,IAAKA,EAAM,YAAc,EAAI,GAAGA,EAAM,WAAW,WAAa,iBAC9D,QAAS,IAAMJ,EAAkB,UAAU,IAE7C1hC,MAACgiC,GAAA,CACC,KAAMhiC,MAACnI,GAAA,CAAU,KAAM,GAAI,EAC3B,MAAM,MACN,MAAOiqC,EAAM,UAAY,UAAUA,EAAM,SAAS,GAAK,aACvD,IACEA,EAAM,WAAa,KAAO,iBAC1BA,EAAM,SAAW,qBACjB,yBAEF,QAAS,IAAMJ,EAAkB,KAAK,IAExC1hC,MAACgiC,GAAA,CACC,KAAMhiC,MAACjJ,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,UACN,MAAOkrC,GAAYL,EAAQ,KAAK,EAChC,IAAKA,EAAQ,UAAU,OAAS,EAC5B,GAAGA,EAAQ,UAAU,MAAM,gBAC3B,2BAEN5hC,MAACgiC,GAAA,CACC,KAAMhiC,MAAC4B,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,eACN,MAAO8J,EAAS,cAAgBK,GAAWL,EAAS,aAAa,EAAI,QACrE,IAAI,kBACJ,QAAS,IAAMg2B,EAAkB,UAAU,IAE7C1hC,MAACgiC,GAAA,CACC,KAAMhiC,MAACtG,GAAA,CAAY,KAAM,GAAI,EAC7B,MAAM,SACN,MAAO,GAAG+R,EAAO,KAAK,OACtB,IAAKA,EAAO,OACZ,QAAS,IAAMi2B,EAAkB,QAAQ,GAC3C,EACF,EAGCj2B,EAAO,OAAO,OAAS,UACrBb,EAAA,CACC,UAAA5K,MAACkL,IAAU,yBAAa,EACxBlL,MAACmL,IAAS,wDAA4C,EACtDnL,MAAC,MAAG,UAAU,oBACX,SAAAyL,EAAO,OAAO,IAAK4O,GAClBna,OAAC,MAAgB,UAAU,mBACzB,UAAAF,MAAC,QAAK,UAAU,oBACb,SAAAqa,EAAE,KACCra,MAAC8G,GAAA,CAAa,KAAM,GAAI,MAAO,CAAE,MAAO,kBAAoB,EAC5DuT,EAAE,KAAK,SAAS,SAAS,GAAKA,EAAE,KAAK,SAAS,QAAQ,QACnDtT,GAAA,CAAc,KAAM,GAAI,MAAO,CAAE,MAAO,kBAAoB,EAC7D/G,MAACoe,GAAA,CAAQ,KAAM,GAAI,MAAO,CAAE,MAAO,gBAAkB,EAC7D,EACApe,MAAC,QAAK,UAAU,oBAAqB,WAAE,KAAK,EAC5CA,MAAC,QAAK,UAAU,4BAA6B,WAAE,OAAO,IAT/Cqa,EAAE,IAUX,CACD,EACH,GACF,GAEJ,CAEJ,CAEA,SAAS2nB,GAAS,CAChB,KAAA/1B,EACA,MAAAiV,EACA,MAAAvlB,EACA,IAAAumC,EACA,QAAAx+B,CACF,EAMG,CACD,MAAMy+B,EAAOz+B,EAAU,SAAW,MAClC,OACExD,OAACiiC,EAAA,CACC,KAAMz+B,EAAU,SAAW,OAC3B,QAAAA,EACA,UAAWT,EAAG,mBAAoBS,GAAW,4BAA4B,EAEzE,UAAA1D,MAAC,OAAI,UAAU,mBAAoB,SAAAiM,EAAK,EACxC/L,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,OAAI,UAAU,oBAAqB,SAAAkhB,EAAM,EAC1ClhB,MAAC,OAAI,UAAU,oBAAqB,SAAArE,EAAM,EAC1CqE,MAAC,OAAI,UAAU,wBAAyB,SAAAkiC,CAAA,CAAI,GAC9C,IAGN,CAEA,SAASD,GAAYr6B,EAAmB,CACtC,OAAIA,EAAI,KAAa,GAAGA,CAAC,KACrBA,EAAI,KAAO,KAAa,IAAIA,EAAI,MAAM,QAAQ,CAAC,CAAC,MAChDA,EAAI,KAAO,KAAO,KAAa,IAAIA,GAAK,KAAO,OAAO,QAAQ,CAAC,CAAC,MAC7D,IAAIA,GAAK,KAAO,KAAO,OAAO,QAAQ,CAAC,CAAC,KACjD,CC7SO,SAASw6B,GAAc,CAAE,WAAA92B,GAAqB,CACnD,MAAMrG,EAAQC,GAAA,EACR,CAACmC,EAAOC,CAAQ,EAAInL,WAAuB,IAAI,EAC/C,CAACkmC,EAAQC,CAAS,EAAInmC,WAAwB,IAAI,EAClD,CAAComC,EAASC,CAAU,EAAIrmC,WAAmB,EAAE,EAC7C,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACqb,EAAMirB,CAAO,EAAItmC,WAAwB,IAAI,EAC9C,CAACumC,EAAOlpB,CAAQ,EAAIrd,WAAS,EAAE,EAC/B,CAACwmC,EAAaC,CAAc,EAAIzmC,WAA+C,IAAI,EAEnFsL,EAAS,SAAY,CACzB5K,EAAW,EAAI,EACf,GAAI,CACF,KAAM,CAACsJ,EAAGkU,EAAGif,CAAG,EAAI,MAAM,QAAQ,IAAI,CACpCz7B,EAAI,IAAW,wBAAwB,EAAE,MAAM,IAAM,IAAI,EACzDA,EAAI,IAA2B,gBAAgB,EAAE,KAAM6B,IAAMA,GAAA,YAAAA,EAAG,WAAY,IAAI,EAAE,MAAM,IAAM,IAAI,EAClG7B,EAAI,IAAyB,sBAAsB,EAAE,MAAM,KAAO,CAAE,MAAO,IAAK,EACjF,EACDyJ,EAASnB,CAAC,EACVm8B,EAAUjoB,CAAC,EACXmoB,GAAWlJ,GAAA,YAAAA,EAAK,QAAS,EAAE,CAC7B,OAASv7B,EAAK,CACZkH,EAAM,MAAM,2BAA4BlH,EAAc,OAAO,EAAE,CACjE,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,CAAC6D,CAAU,CAAC,EAEf,MAAMu3B,EAAa,MAAOn1B,EAAao1B,EAA4BC,IAAuB,CACxFN,EAAQ/0B,CAAG,EACX,GAAI,CACF,MAAMo1B,EAAA,EACN79B,EAAM,QAAQ89B,CAAU,EACxB,MAAMt7B,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,GAAGyI,CAAG,YAAa3P,EAAc,OAAO,EAAE,CACxD,SACE0kC,EAAQ,IAAI,CACd,CACF,EAEMO,EAAU,IAAMH,EAAW,QAAS,IAAMhlC,EAAI,KAAK,yBAA0B,EAAE,EAAG,oBAAoB,EACtGolC,EAAS,IAAMJ,EAAW,OAAQ,IAAMhlC,EAAI,KAAK,wBAAyB,EAAE,EAAG,oBAAoB,EACnG2f,EAAY,SAAY,CAC5BilB,EAAQ,SAAS,EACjB,GAAI,CACF,MAAM5kC,EAAI,KAAK,wBAAyB,EAAE,EAAE,MAAM,IAAM,CAAC,CAAC,EAC1D,MAAM,IAAI,QAAS6B,GAAM,WAAWA,EAAG,GAAG,CAAC,EAC3C,MAAM7B,EAAI,KAAK,yBAA0B,EAAE,EAC3CoH,EAAM,QAAQ,qBAAqB,EACnC,MAAMwC,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,SACE0kC,EAAQ,IAAI,CACd,CACF,EACMS,EAAY,IAAML,EAAW,UAAW,IAAMhlC,EAAI,KAAK,2BAA4B,EAAE,EAAG,mBAAmB,EAC3GslC,EAAY,IAAMN,EAAW,UAAW,IAAMhlC,EAAI,KAAK,iCAAkC,EAAE,EAAG,gBAAgB,EAE9GulC,EAAU,SAAY,WAC1B,GAAKV,EAAM,OACX,CAAAD,EAAQ,OAAO,EACf,GAAI,CACF,MAAM/iC,EAAI,MAAM7B,EAAI,IAClB,mBAAmB,mBAAmB6kC,CAAK,CAAC,WAExCl0B,GAAOvQ,EAAAyB,GAAA,YAAAA,EAAG,WAAH,MAAAzB,EAAa,SACrB,OAAOyB,EAAE,SAAS,UAAa,SAC9BA,EAAE,SAAS,SACX,KAAK,UAAUA,EAAE,SAAS,QAAQ,IACnC4E,EAAA5E,GAAA,YAAAA,EAAG,WAAH,YAAA4E,EAAa,QAAS,cAC3Bs+B,EAAe,CAAE,GAAI,CAAC,GAACj0B,EAAAjP,GAAA,YAAAA,EAAG,WAAH,MAAAiP,EAAa,IAAI,KAAAH,EAAM,CAChD,OAASzQ,EAAK,CACZ6kC,EAAe,CAAE,GAAI,GAAO,KAAO7kC,EAAc,QAAS,CAC5D,SACE0kC,EAAQ,IAAI,CACd,EACF,EAEA,OAAI7lC,GAAW,CAACyK,EAEZnH,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,oCAAwB,GAC7B,EAGCqH,EAKHnH,OAAC,OAAI,UAAU,uBAEb,UAAAA,OAAC0K,EAAA,CAAK,QAAQ,WACZ,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,WAEnB6J,MAAC,QAAK,UAAWiD,EAAG,4BAA6BoE,EAAM,QAAU,KAAO,KAAK,EAC1E,SAAAA,EAAM,QAAU,UAAY,UAC/B,GACF,EACArH,MAACmL,GAAA,CACE,SAAA9D,EAAM,QACHnH,OAAAO,WAAA,CAAE,iBAAIT,MAAC,QAAM,SAAAqH,EAAM,IAAI,EAAO,MAAIA,EAAM,KAAK,IAAEA,EAAM,MAAK,EAC1DrH,MAAAS,WAAA,CAAE,oEAAwD,EAChE,EACAP,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASm/B,EAAS,SAAU,CAAC,CAACxrB,GAAQnQ,EAAM,QAC7E,UAAAmQ,IAAS,QAAUxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACud,GAAA,CAAK,KAAM,GAAI,EAAG,SAEzF,EACArd,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASo/B,EAAQ,SAAU,CAAC,CAACzrB,GAAQ,CAACnQ,EAAM,QAC/E,UAAAmQ,IAAS,OAASxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAAC3G,GAAA,CAAS,KAAM,GAAI,EAAG,QAE5F,EACA6G,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS2Z,EAAW,SAAU,CAAC,CAAChG,EACnE,UAAAA,IAAS,UAAYxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACkP,GAAA,CAAM,KAAM,GAAI,EAAG,WAE5F,EACAhP,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASq/B,EAAW,SAAU,CAAC,CAAC1rB,EAC/D,UAAAA,IAAS,UAAYxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAG,eAEhG,EACAD,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASs/B,EAAW,SAAU,CAAC,CAAC3rB,EAAM,MAAM,0CAC3E,UAAAA,IAAS,UAAYxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAAC8d,GAAA,CAAS,KAAM,GAAI,EAAG,iBAE/F,GACF,GACF,EAGA5d,OAAC,OAAI,UAAU,mBACb,UAAAF,MAACsjC,GAAA,CAAQ,KAAMtjC,MAACjJ,GAAA,CAAS,KAAM,GAAI,EAAI,MAAM,0BAA0B,MAAO,OAAOsQ,EAAM,aAAa,EAAG,EAC3GrH,MAACsjC,GAAA,CAAQ,KAAMtjC,MAACujC,IAAc,EAAGl8B,EAAM,UAAW,EAAI,MAAM,iBAAiB,MAAO,OAAOA,EAAM,SAAS,EAAG,EAC7GrH,MAACsjC,GAAA,CAAQ,KAAMtjC,MAAC7F,IAAI,KAAM,GAAI,EAAI,MAAM,mBAAmB,MAAO,OAAOkN,EAAM,iBAAiB,EAAG,EACnGrH,MAACsjC,GAAA,CACC,KAAMtjC,MAAC4B,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,eACN,MAAOyF,EAAM,gBAAkB,KAAO,GAAGA,EAAM,aAAa,MAAQ,MAEtErH,MAACsjC,GAAA,CACC,KAAMj8B,EAAM,oBAAiBP,GAAA,CAAa,KAAM,GAAI,EAAKO,EAAM,gBAAkB,GAAQrH,MAACoe,IAAQ,KAAM,GAAI,EAAKpe,MAACG,GAAA,CAAU,KAAM,GAAI,EACtI,MAAM,eACN,MAAOkH,EAAM,cAAgB0E,GAAW1E,EAAM,aAAa,EAAI,QAC/D,IAAKA,EAAM,sBAAwB,KAC/B,GAAGA,EAAM,mBAAmB,YAAYA,EAAM,kBAAoB,KAAKA,EAAM,iBAAiB,UAAY,EAAE,GAC5G,QACN,EACF,SAGCuD,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACgD,GAAA,CAAW,KAAM,GAAI,EAAE,iBAC1B,EACAhD,MAACmL,IAAS,gEAAoD,EAC9DjL,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,SACC,KAAK,OACL,UAAU,QACV,YAAY,gDACZ,MAAO0iC,EACP,SAAWtkC,GAAMob,EAASpb,EAAE,OAAO,KAAK,EACxC,UAAYA,GAAM,CACZA,EAAE,MAAQ,SAASglC,EAAA,CACzB,EACA,SAAU5rB,IAAS,UAErBtX,OAAC2D,EAAA,CAAO,QAAQ,UAAU,QAASu/B,EAAS,SAAU5rB,IAAS,SAAW,CAACkrB,EAAM,OAC9E,UAAAlrB,IAAS,QAAUxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACgD,GAAA,CAAW,KAAM,GAAI,EAAG,SAE/F,GACF,EACC2/B,GACC3iC,MAAC,OAAI,UAAWiD,EAAG,sBAAuB0/B,EAAY,GAAK,KAAO,KAAK,EACrE,SAAA3iC,MAAC,OAAI,UAAU,eAAgB,SAAA2iC,EAAY,KAAK,EAClD,GAEJ,EAGCN,UACEz3B,EAAA,CACC,UAAA5K,MAACkL,IAAU,yBAAa,SACvBC,GAAA,CAAS,mCAAsBnL,MAAC,QAAK,8BAAkB,EAAO,oBAAgB,EAC/EE,OAAC,MAAG,UAAU,oBACZ,UAAAF,MAAC,MAAG,uBAAW,SACd,MAAG,UAAAA,MAAC,QAAM,WAAO,WAAW,EAAO,MAAGA,MAAC,QAAM,SAAAqiC,EAAO,SAAS,GAAO,EACrEriC,MAAC,MAAG,qBAAS,SACZ,MAAG,UAAAA,MAAC,QAAM,WAAO,iBAAiB,EAAO,MAAGA,MAAC,QAAM,SAAAqiC,EAAO,eAAe,GAAO,EACjFriC,MAAC,MAAG,gBAAI,EACRA,MAAC,MAAG,SAAAE,OAAC,QAAM,UAAAmiC,EAAO,KAAK,IAAEA,EAAO,MAAK,EAAO,EAC5CriC,MAAC,MAAG,uBAAW,EACfA,MAAC,MAAG,UAAU,gBAAgB,MAAOqiC,EAAO,WAAa,WAAO,WAAW,GAC7E,GACF,EAIDE,EAAQ,OAAS,GAChBriC,OAAC0K,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,sBACzB,SACCgL,GAAA,CAAS,kBAAMo3B,EAAQ,OAAO,eAAYviC,MAAC,QAAK,wBAAY,GAAO,QACnE,OAAI,UAAU,+BACZ,SAAAuiC,EAAQ,KAAK;AAAA,CAAI,EACpB,GACF,GAEJ,EA3HOviC,MAAC,OAAI,UAAU,QAAQ,uCAA2B,CA6H7D,CAEA,SAASsjC,GAAQ,CACf,KAAAr3B,EACA,MAAAiV,EACA,MAAAvlB,EACA,IAAAumC,CACF,EAKG,CACD,OACEhiC,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,OAAI,UAAU,mBAAoB,SAAAiM,EAAK,EACxC/L,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,OAAI,UAAU,oBAAqB,SAAAkhB,EAAM,EAC1ClhB,MAAC,OAAI,UAAU,oBAAqB,SAAArE,EAAM,EACzCumC,GAAOliC,MAAC,OAAI,UAAU,wBAAyB,SAAAkiC,CAAA,CAAI,GACtD,GACF,CAEJ,CAEA,SAASqB,GAAc,CAAE,EAAA37B,GAAoB,CAE3C,OACE1H,OAAC,QAAK,MAAO,CAAE,SAAU,WAAY,QAAS,gBAC5C,UAAAF,MAACgD,GAAA,CAAW,KAAM,GAAI,EACtBhD,MAAC,QAAK,UAAU,oBAAqB,SAAA4H,CAAA,CAAE,GACzC,CAEJ,CC9PO,SAAS47B,GAAc,CAAE,WAAAl4B,GAAqB,CACnD,MAAMrG,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACR,CAACggC,EAAOC,CAAQ,EAAIvnC,WAAiB,EAAE,EACvC,CAAC4Z,EAAM4tB,CAAO,EAAIxnC,WAA0B,IAAI,EAChD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACwkC,EAASC,CAAU,EAAIzkC,WAAS,EAAE,EACnC,CAAC0kC,EAAeC,CAAgB,EAAI3kC,WAAwB,IAAI,EAChE,CAAC4kC,EAAWC,CAAY,EAAI7kC,WAAS,EAAK,EAC1C,CAAC4iB,EAAU8a,CAAW,EAAI19B,WAAwB,IAAI,EACtD,CAACynC,EAAWC,CAAY,EAAI1nC,WAAqB,EAAE,EAEnDsL,EAAS,SAAY,OACzB5K,EAAW,EAAI,EACf,GAAI,CACF,KAAM,CAAC+K,EAAGlD,CAAC,EAAI,MAAM,QAAQ,IAAI,CAC/B7G,EAAI,IAAuB,eAAe,EAAE,MAAM,KAAO,CAAE,MAAO,EAAC,EAAI,EACvEA,EAAI,IAA+B,uBAAuB,EAAE,MAAM,KAAO,CAAE,KAAM,MAAO,EACzF,EACD6lC,EAAS97B,EAAE,OAAS,EAAE,EACtB+7B,EAAQj/B,EAAE,IAAI,EACVqa,GAAY,GAAC9gB,EAAA2J,EAAE,QAAF,MAAA3J,EAAS,KAAMsB,GAAMA,EAAE,UAAYwf,MAClD8a,EAAY,IAAI,EAChBgK,EAAa,EAAE,EAEnB,OAAS9lC,EAAK,CACZkH,EAAM,MAAM,sBAAuBlH,EAAc,OAAO,EAAE,CAC5D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,CAAC6D,CAAU,CAAC,EAGfpN,YAAU,IAAM,CACd,GAAI,CAACyiC,EAAQ,OAAQ,CACnBG,EAAiB,IAAI,EACrB,MACF,CACAE,EAAa,EAAI,EACjB,MAAMt8B,EAAI,WAAW,SAAY,CAC/B,GAAI,CACF,MAAMhF,EAAI,MAAM7B,EAAI,IAClB,oBAAoB,mBAAmB8iC,CAAO,CAAC,aAE3CmD,EAAU,IAAI,KAAKpkC,EAAE,SAAW,IAAI,IAAKH,GAAMA,EAAE,OAAO,CAAC,EAC/DuhC,EAAiB2C,EAAM,OAAQ77B,GAAMk8B,EAAQ,IAAIl8B,EAAE,OAAO,CAAC,CAAC,CAC9D,OAAS7J,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,SACEijC,EAAa,EAAK,CACpB,CACF,EAAG,GAAG,EACN,MAAO,IAAM,aAAat8B,CAAC,CAC7B,EAAG,CAACi8B,EAAS8C,EAAOx+B,CAAK,CAAC,EAE1B,MAAMD,EAAW,MAAO++B,GAAoB,CAC1ClK,EAAYkK,CAAO,EACnB,GAAI,CACF,MAAMrkC,EAAI,MAAM7B,EAAI,IAClB,mCAAmC,mBAAmBkmC,CAAO,CAAC,IAEhEF,EAAankC,EAAE,WAAa,EAAE,CAChC,MAAQ,CACNmkC,EAAa,EAAE,CACjB,CACF,EAEMznB,EAAW,IAAM,CACrB5Y,EAAM,KAAK,CACT,MAAO,WACP,MAAO,IACP,SACExD,MAACgkC,GAAA,CACC,KAAK,SACL,OAAQ,MAAOD,EAASE,EAAatyB,IAAS,CAC5C,GAAI,CACF,MAAM9T,EAAI,KAAK,gBAAiB,CAAE,KAAMkmC,EAAS,YAAAE,EAAa,KAAAtyB,EAAM,EACpE1M,EAAM,QAAQ,WAAW8+B,CAAO,GAAG,EACnCvgC,EAAM,QACN,MAAMiE,EAAA,EACNzC,EAAS++B,CAAO,CAClB,OAAShmC,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EACA,SAAU,IAAMyF,EAAM,OAAM,EAC9B,CAEH,CACH,EAEM0N,EAAS,MAAO6yB,GAAoB,CACxC,GAAI,CACF,MAAMG,EAAO,MAAMrmC,EAAI,IAAU,iBAAiBkmC,EAAQ,MAAM,GAAG,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG,CAAC,EAAE,EACxGvgC,EAAM,KAAK,CACT,MAAO,QAAQugC,CAAO,GACtB,MAAO,IACP,SACE/jC,MAACgkC,GAAA,CACC,KAAK,OACL,QAAS,CAAE,QAASE,EAAK,QAAS,YAAaA,EAAK,YAAa,KAAMA,EAAK,MAC5E,OAAQ,MAAOC,EAAIF,EAAatyB,IAAS,CACvC,GAAI,CACF,MAAM9T,EAAI,IAAI,iBAAiBsmC,EAAG,MAAM,GAAG,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG,CAAC,GAAI,CAChF,YAAAF,EAAa,KAAAtyB,CAAA,CACd,EACD1M,EAAM,QAAQ,SAASk/B,CAAE,GAAG,EAC5B3gC,EAAM,QACN,MAAMiE,EAAA,EACNzC,EAASm/B,CAAE,CACb,OAASpmC,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EACA,SAAU,IAAMyF,EAAM,OAAM,EAC9B,CAEH,CACH,OAASzF,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EAEMuZ,EAAW,MAAOysB,GAAoB,CAC1C,GAAK,QAAQ,UAAUA,CAAO,0BAA0B,EACxD,GAAI,CACF,MAAMlmC,EAAI,IAAI,iBAAiBkmC,EAAQ,MAAM,GAAG,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG,CAAC,EAAE,EACrF9+B,EAAM,QAAQ,WAAW8+B,CAAO,GAAG,EAC/BhlB,IAAaglB,GAASlK,EAAY,IAAI,EAC1C,MAAMpyB,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,CACxD,CACF,EAEMqmC,EAAc7vB,UAAQ,IACnB,CAAC,GAAGkvB,CAAK,EAAE,KAAK,CAAC7oC,EAAGC,IAAMA,EAAE,MAAQD,EAAE,KAAK,EACjD,CAAC6oC,CAAK,CAAC,EAEJxC,EAAYJ,GAAiBuD,EAEnC,OAAIxnC,GAAW,CAAC6mC,EAAM,OAElBvjC,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,0BAAc,GACnB,EAKFE,OAAC,OAAI,UAAU,4CAEb,UAAAA,OAAC0K,EAAA,CAAK,QAAQ,WAAW,UAAU,mBACjC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACc,GAAA,CAAO,KAAM,GAAI,EAAE,YACtB,EACAd,MAACmL,IAAU,SAAA4K,EAAO,GAAGsuB,GAAatuB,CAAI,CAAC,aAAe,WAAW,EACjE/V,MAAC,OAAI,UAAU,mBACZ,WAAOA,MAACskC,GAAA,CAAS,KAAMvuB,EAAM,MAAO,EAAG,SAAA/Q,EAAoB,SAAA+Z,CAAA,CAAoB,EAAK,KACvF,GACF,EAGA7e,OAAC,OAAI,UAAU,2BACb,UAAAA,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,OAAI,UAAU,eACb,UAAAF,MAACgD,GAAA,CAAW,KAAM,GAAI,EACtBhD,MAAC,SACC,KAAK,OACL,UAAU,QACV,YAAY,gBACZ,MAAO2gC,EACP,SAAWviC,GAAMwiC,EAAWxiC,EAAE,OAAO,KAAK,IAE3CuiC,GACC3gC,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAM4gC,EAAW,EAAE,EAC5B,aAAW,eAEX,SAAA5gC,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EAEJ,SACC1C,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASuY,EAC3C,UAAApc,MAACzI,GAAA,CAAS,KAAM,GAAI,EAAE,aACxB,EACAyI,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS4D,EAAQ,MAAM,UACvD,SAAAzH,MAACG,GAAA,CAAU,KAAM,GAAI,EACvB,GACF,EACC4gC,GAAa/gC,MAAC,OAAI,UAAU,gBAAgB,sBAAU,EACtDihC,EAAU,SAAW,EACpBjhC,MAACgM,GAAA,CACC,KAAMhM,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,WACN,QACE23B,EAAM,SAAW,EACb,8DACA,mBAAmB9C,CAAO,aAIjC,MAAG,UAAU,mBACX,SAAAM,EAAU,IAAKr5B,GACd1H,OAAC,MAEC,UAAW+C,EAAG,mBAAoB8b,IAAanX,EAAE,SAAW,yBAAyB,EAErF,UAAA1H,OAAC,UACC,KAAK,SACL,UAAU,wBACV,QAAS,IAAM8E,EAAS4C,EAAE,OAAO,EAEjC,UAAA1H,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC8L,GAAA,CAAS,KAAM,GAAI,EACpB9L,MAAC,QAAM,SAAAukC,GAAQ38B,CAAC,EAAE,GACpB,EACA1H,OAAC,OAAI,UAAU,wBACb,UAAAF,MAAC,QAAK,UAAU,QAAS,SAAA4H,EAAE,QAAQ,EACnC1H,OAAC,QAAK,UAAU,QAAQ,eAAGqI,GAAeX,EAAE,KAAK,GAAE,EAClD,CAACA,EAAE,mBAAgB,QAAK,UAAU,mBAAmB,kBAAM,GAC9D,KAEF1H,OAAC,OAAI,UAAU,2BACb,UAAAF,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAMkR,EAAOtJ,EAAE,OAAO,EAC/B,aAAY,QAAQA,EAAE,OAAO,GAC7B,MAAM,OAEN,SAAA5H,MAACuY,GAAA,CAAO,KAAM,GAAI,IAEpBvY,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAMsX,EAAS1P,EAAE,OAAO,EACjC,aAAY,UAAUA,EAAE,OAAO,GAC/B,MAAM,SAEN,SAAA5H,MAACiP,GAAA,CAAO,KAAM,GAAI,GACpB,EACF,IArCKrH,EAAE,QAuCV,EACH,GAEJ,EAGA5H,MAAC,OAAI,UAAU,6BACZ,WACCA,MAACwkC,GAAA,CAAW,QAASzlB,EAAU,QAAS,IAAM8a,EAAY,IAAI,EAAG,EAEjE75B,MAACgM,GAAA,CACC,KAAMhM,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAC1B,MAAM,cACN,QAAQ,gFACV,CAEJ,GACF,CAEJ,CAQA,SAASy4B,GAAQ38B,EAAiB,OAChC,MAAM,GAAI3J,EAAA2J,EAAE,cAAF,YAAA3J,EAAe,MACzB,OAAI,OAAO,GAAM,UAAY,EAAE,OAAe,EACvC2J,EAAE,QAAQ,QAAQ,SAAU,EAAE,CACvC,CAEA,SAAS08B,GAAS,CAChB,KAAAvyB,EACA,MAAAC,EACA,SAAAhN,EACA,SAAA+Z,CACF,EAKG,CACD,KAAM,CAACzb,EAAMC,CAAO,EAAIpH,WAAS6V,EAAQ,CAAC,EAC1C,OAAID,EAAK,OAAS,OAEd7R,OAAC,UACC,KAAK,SACL,UAAW+C,EAAG,yCAA0C8b,IAAahN,EAAK,MAAQ,yBAAyB,EAC3G,MAAO,CAAE,YAAa,EAAIC,EAAQ,IAClC,QAAS,IAAMhN,EAAS+M,EAAK,IAAI,EAEjC,UAAA/R,MAAC8L,GAAA,CAAS,KAAM,GAAI,EACpB9L,MAAC,QAAM,SAAA+R,EAAK,KAAK,KAKrB7R,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,UACC,KAAK,SACL,UAAU,2CACV,MAAO,CAAE,YAAa,EAAI8R,EAAQ,IAClC,QAAS,IAAMzO,EAASvE,GAAM,CAACA,CAAC,EAE/B,UAAAsE,EAAOtD,MAACoB,IAAY,KAAM,GAAI,EAAKpB,MAACqB,GAAA,CAAa,KAAM,GAAI,EAC5DrB,MAACc,GAAA,CAAO,KAAM,GAAI,EAClBd,MAAC,QAAM,SAAA+R,EAAK,MAAQ,QAAQ,EAC3BA,EAAK,UAAYA,EAAK,SAAS,OAAS,GACvC/R,MAAC,QAAK,UAAU,gBAAiB,SAAA+R,EAAK,SAAS,OAAO,KAGzDzO,GAAQyO,EAAK,UACZ/R,MAAC,OAAI,UAAU,uBACZ,SAAA+R,EAAK,SAAS,IAAI,CAACsI,EAAGjf,IACrB4E,MAACskC,GAAA,CAAgC,KAAMjqB,EAAG,MAAOrI,EAAQ,EAAG,SAAAhN,EAAoB,SAAA+Z,CAAA,EAAjE,GAAG1E,EAAE,IAAI,IAAIjf,CAAC,EAAuE,CACrG,EACH,GAEJ,CAEJ,CAEA,SAASipC,GAAatyB,EAAwB,CAC5C,OAAIA,EAAK,OAAS,OAAe,EAC1B,GAAKA,EAAK,UAAY,IAAI,OAAO,CAAC0yB,EAAKpqB,IAAMoqB,EAAMJ,GAAahqB,CAAC,EAAG,CAAC,CAC9E,CAIA,SAASmqB,GAAW,CAAE,QAAAT,EAAS,QAAAh/B,GAAqD,SAClF,KAAM,CAACm/B,EAAMQ,CAAO,EAAIvoC,WAAsB,IAAI,EAC5C,CAACynC,EAAWC,CAAY,EAAI1nC,WAAqB,EAAE,EACnD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EAuB3C,GArBA+B,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAAlJ,EAAW,EAAI,GACd,SAAY,CACX,GAAI,CACF,KAAM,CAAC+K,EAAG/M,CAAC,EAAI,MAAM,QAAQ,IAAI,CAC/BgD,EAAI,IAAU,iBAAiBkmC,EAAQ,MAAM,GAAG,EAAE,IAAI,kBAAkB,EAAE,KAAK,GAAG,CAAC,EAAE,EACrFlmC,EAAI,IAA+B,mCAAmC,mBAAmBkmC,CAAO,CAAC,EAAE,EACpG,EACD,GAAIh+B,EAAW,OACf2+B,EAAQ98B,CAAC,EACTi8B,EAAahpC,EAAE,WAAa,EAAE,CAChC,MAAQ,CACDkL,GAAW2+B,EAAQ,IAAI,CAC9B,SACO3+B,GAAWlJ,EAAW,EAAK,CAClC,CACF,KACO,IAAM,CAAEkJ,EAAY,EAAM,CACnC,EAAG,CAACg+B,CAAO,CAAC,EAERnnC,EACF,OACEoD,MAAC,OAAI,UAAU,eAAe,eAACuO,GAAA,CAAQ,KAAK,KAAK,EAAE,EAGvD,GAAI,CAAC21B,EAAM,aAAQ,OAAI,UAAU,QAAQ,2BAAe,EAExD,MAAMlnB,EAAO,MAAM,SAAQ/e,EAAAimC,EAAK,cAAL,YAAAjmC,EAAkB,IAAI,EAAIimC,EAAK,YAAY,KAAO,GACvES,EAAQ,MAAM,SAAQrgC,EAAA4/B,EAAK,cAAL,YAAA5/B,EAAkB,KAAK,EAAI4/B,EAAK,YAAY,MAAQ,GAEhF,OACEhkC,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OAAI,UAAU,0BACb,UAAAF,MAAC,MAAI,SAAAukC,GAAQL,CAAI,EAAE,EACnBlkC,MAAC,UAAO,KAAK,SAAS,UAAU,WAAW,QAAS+E,EAAS,aAAW,QACtE,SAAA/E,MAACuG,GAAA,CAAE,KAAM,GAAI,EACf,GACF,EACArG,OAAC,OAAI,UAAU,0BACb,UAAAF,MAAC,QAAM,SAAA+jC,CAAA,CAAQ,EACf7jC,OAAC,QAAK,UAAU,QAAQ,wBAAY6L,GAAWm4B,EAAK,KAAK,GAAE,GAC7D,EACClnB,EAAK,OAAS,GACbhd,MAAC,OAAI,UAAU,iBACZ,WAAK,IAAI,CAAC0E,EAAGtJ,IACZ4E,MAAC,QAAa,UAAU,aAAc,gBAAO0E,CAAC,GAAnCtJ,CAAqC,CACjD,EACH,EAEF4E,MAAC,OAAI,UAAU,gCAAiC,WAAK,KAAK,EACzD4jC,EAAU,OAAS,GAClB1jC,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,MAAG,qBAAS,QACZ,MACE,SAAA4jC,EAAU,IAAK/oC,UACb,MACC,UAAAmF,MAAC,QAAM,WAAE,YAAY,EACrBA,MAAC,KAAE,UAAU,gBAAiB,WAAE,QAAQ,IAFjCnF,EAAE,WAGX,CACD,EACH,GACF,EAED8pC,EAAM,OAAS,GACdzkC,OAAC,OAAI,UAAU,mBACb,UAAAF,MAAC,MAAG,yBAAa,QAChB,MACE,SAAA2kC,EAAM,IAAI,CAAC5jB,EAAG3lB,IACb4E,MAAC,MAAW,SAAAA,MAAC,QAAM,gBAAO+gB,CAAC,EAAE,GAApB3lB,CAA2B,CACrC,EACH,GACF,GAEJ,CAEJ,CAIA,SAAS4oC,GAAW,CAClB,KAAAt7B,EACA,QAAAotB,EACA,OAAAyB,EACA,SAAAqN,CACF,EAKG,CACD,KAAM,CAACb,EAASc,CAAU,EAAI1oC,YAAS25B,GAAA,YAAAA,EAAS,UAAW,aAAa,EAClE,CAACgP,EAAiBC,CAAkB,EAAI5oC,WAC5C25B,GAAA,MAAAA,EAAS,YAAckP,GAAclP,EAAQ,WAAW,EAAI;AAAA;AAAA,GAExD,CAACnkB,EAAMszB,CAAO,EAAI9oC,YAAS25B,GAAA,YAAAA,EAAS,OAAQ,EAAE,EAC9C,CAACte,EAAMirB,CAAO,EAAItmC,WAAS,EAAK,EAChC8I,EAAQC,GAAA,EAERggC,EAAW,SAAY,CAC3B,GAAI,CAACnB,EAAQ,SAAS,KAAK,EAAG,CAC5B9+B,EAAM,MAAM,sBAAsB,EAClC,MACF,CACA,IAAIkgC,EACJ,GAAI,CACFA,EAAKC,GAAUN,CAAe,GAAK,EACrC,OAAS/mC,EAAK,CACZkH,EAAM,MAAM,6BAA8BlH,EAAc,OAAO,EAAE,EACjE,MACF,CACA0kC,EAAQ,EAAI,EACZ,GAAI,CACF,MAAMlL,EAAOwM,EAASoB,EAAIxzB,CAAI,CAChC,SACE8wB,EAAQ,EAAK,CACf,CACF,EAEA,OACEviC,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,SAAM,UAAU,cAAc,gBAAI,EACnCA,MAAC,SACC,KAAK,OACL,UAAU,aACV,MAAO+jC,EACP,SAAW3lC,GAAMymC,EAAWzmC,EAAE,OAAO,KAAK,EAC1C,SAAUsK,IAAS,OACnB,YAAY,qBAEd1I,MAAC,SAAM,UAAU,cAAc,MAAO,CAAE,UAAW,IAAM,8BAAkB,EAC3EA,MAAC,YACC,UAAU,sCACV,KAAM,EACN,MAAO8kC,EACP,SAAW1mC,GAAM2mC,EAAmB3mC,EAAE,OAAO,KAAK,IAEpD4B,MAAC,SAAM,UAAU,cAAc,MAAO,CAAE,UAAW,IAAM,2BAAe,EACxEA,MAAC,YACC,UAAU,sCACV,KAAM,GACN,MAAO2R,EACP,SAAWvT,GAAM6mC,EAAQ7mC,EAAE,OAAO,KAAK,IAEzC8B,OAAC,OAAI,UAAU,uBAAuB,MAAO,CAAE,UAAW,IACxD,UAAAF,MAAC6D,GAAO,QAAQ,QAAQ,QAAS+gC,EAAU,SAAUptB,EAAM,kBAAM,SAChE3T,EAAA,CAAO,QAAQ,UAAU,QAASqhC,EAAU,SAAU1tB,EACpD,UAAAA,GAAQxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EACnD36B,IAAS,SAAW,SAAW,QAClC,GACF,GACF,CAEJ,CAIA,SAASs8B,GAAcK,EAAsC,CAG3D,MAAM3M,EAAkB,GACxB,SAAW,CAAC59B,EAAGkE,CAAC,IAAK,OAAO,QAAQqmC,CAAG,EACrC,GAAIrmC,GAAM,KACV,GAAI,MAAM,QAAQA,CAAC,EAAG,CACpB,GAAIA,EAAE,SAAW,EAAG,CAAE05B,EAAM,KAAK,GAAG59B,CAAC,MAAM,EAAG,QAAU,CACxD49B,EAAM,KAAK,GAAG59B,CAAC,GAAG,EAClB,UAAWwV,KAAQtR,EAAG05B,EAAM,KAAK,OAAO4M,GAAWh1B,CAAI,CAAC,EAAE,CAC5D,SAAW,OAAOtR,GAAM,SAAU,CAChC05B,EAAM,KAAK,GAAG59B,CAAC,GAAG,EAClB,SAAW,CAACyqC,EAAIC,CAAE,IAAK,OAAO,QAAQxmC,CAA4B,EAChE05B,EAAM,KAAK,KAAK6M,CAAE,KAAKD,GAAWE,CAAE,CAAC,EAAE,CAE3C,MACE9M,EAAM,KAAK,GAAG59B,CAAC,KAAKwqC,GAAWtmC,CAAC,CAAC,EAAE,EAGvC,OAAO05B,EAAM,KAAK;AAAA,CAAI,CACxB,CAEA,SAAS4M,GAAWtmC,EAAoB,CACtC,OAAI,OAAOA,GAAM,SACX,WAAW,KAAKA,CAAC,GAAKA,IAAM,GAAW,KAAK,UAAUA,CAAC,EACpDA,EAEL,OAAOA,GAAM,UAAY,OAAOA,GAAM,UAAkB,OAAOA,CAAC,EAC7D,KAAK,UAAUA,CAAC,CACzB,CAEA,SAASomC,GAAU,EAAoC,CACrD,MAAMnpB,EAA+B,GAC/Byc,EAAQ,EAAE,MAAM,OAAO,EAC7B,IAAI,EAAI,EACR,KAAO,EAAIA,EAAM,QAAQ,CACvB,MAAMG,EAAOH,EAAM,CAAC,EACpB,GAAI,CAACG,EAAK,QAAUA,EAAK,OAAO,WAAW,GAAG,EAAG,CAAE,IAAK,QAAU,CAClE,MAAMhqB,EAAIgqB,EAAK,MAAM,6BAA6B,EAClD,GAAI,CAAChqB,EAAG,CAAE,IAAK,QAAU,CACzB,KAAM,EAAGnB,EAAKzC,CAAI,EAAI4D,EACtB,GAAI5D,IAAS,GAAI,CAEf,MAAMw6B,EAAiC,GACjCj/B,EAAkB,GACxB,IAAIk/B,EAAS,GACTC,EAAQ,GACZ,KAAO,EAAI,EAAIjN,EAAM,QAAQ,CAC3B,MAAMr5B,EAAOq5B,EAAM,EAAI,CAAC,EACxB,GAAI,CAACr5B,EAAK,WAAW,IAAI,EAAG,MAC5B,GAAIA,EAAK,WAAW,MAAM,EACxBqmC,EAAS,GACTl/B,EAAK,KAAKo/B,GAAYvmC,EAAK,MAAM,CAAC,CAAC,CAAC,EACpC,QACK,CACLsmC,EAAQ,GACR,MAAME,EAAKxmC,EAAK,MAAM,+BAA+B,EACjDwmC,IACFJ,EAAMI,EAAG,CAAC,CAAC,EAAID,GAAYC,EAAG,CAAC,CAAC,GAElC,GACF,CACF,CACA5pB,EAAIvO,CAAG,EAAIg4B,GAAU,CAACC,EAAQn/B,EAAQm/B,EAAQF,EAAQ,EACxD,MACExpB,EAAIvO,CAAG,EAAIk4B,GAAY36B,CAAI,EAE7B,GACF,CACA,OAAOgR,CACT,CAEA,SAAS2pB,GAAY5mC,EAAoB,CACvC,MAAM,EAAIA,EAAE,OACZ,OAAI,IAAM,GAAW,GACjB,IAAM,OAAe,GACrB,IAAM,QAAgB,GACtB,IAAM,QAAU,IAAM,IAAY,KAClC,UAAU,KAAK,CAAC,EAAU,SAAS,EAAG,EAAE,EACxC,eAAe,KAAK,CAAC,EAAU,WAAW,CAAC,EAC1C,EAAE,WAAW,GAAG,GAAK,EAAE,SAAS,GAAG,GAAO,EAAE,WAAW,GAAG,GAAK,EAAE,SAAS,GAAG,EACzE,EAAE,MAAM,EAAG,EAAE,EAEf,CACT,CCxlBO,SAAS8mC,GAAa,CAAE,WAAAx6B,GAAqB,aAClD,MAAMrG,EAAQC,GAAA,EACR,CAACsG,EAAQqmB,CAAS,EAAI11B,WAA2B,IAAI,EACrD,CAAC4pC,EAAMC,CAAO,EAAI7pC,WAAyB,IAAI,EAC/C,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACqb,EAAMirB,CAAO,EAAItmC,WAAwB,IAAI,EAC9C,CAACkmC,EAAQC,CAAS,EAAInmC,WAAgG,IAAI,EAE1HsL,EAAS,SAAY,OACzB5K,EAAW,EAAI,EACf,GAAI,CACF,KAAM,CAACsJ,EAAGqN,EAAGoC,CAAC,EAAI,MAAM,QAAQ,IAAI,CAClC/X,EAAI,IAAe,oBAAoB,EAAE,MAAM,IAAM,IAAI,EACzDA,EAAI,IAAa,kBAAkB,EAAE,MAAM,IAAM,IAAI,EACrDA,EAAI,IACF,yBACA,MAAM,IAAM,IAAI,EACnB,EACDg0B,EAAU1rB,CAAC,EACX6/B,EAAQxyB,CAAC,EACT8uB,IAAUrkC,EAAA2X,GAAA,YAAAA,EAAG,SAAH,YAAA3X,EAAW,MAAO,IAAI,CAClC,OAASF,EAAK,CACZkH,EAAM,MAAM,sBAAuBlH,EAAc,OAAO,EAAE,CAC5D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,CAAC6D,CAAU,CAAC,EAEf,MAAM26B,EAAM,MAAOv4B,EAAao1B,EAA4B9kC,IAAgB,CAC1EykC,EAAQ/0B,CAAG,EACX,GAAI,CACF,MAAMo1B,EAAA,EACN79B,EAAM,QAAQjH,CAAG,EACjB,MAAMyJ,EAAA,CACR,OAAS1J,EAAK,CACZkH,EAAM,MAAM,GAAGyI,CAAG,YAAa3P,EAAc,OAAO,EAAE,CACxD,SACE0kC,EAAQ,IAAI,CACd,CACF,EAEMyD,EAAS,IAAMD,EAAI,OAAQ,IAAMpoC,EAAI,KAAK,mBAAoB,EAAE,EAAG,gBAAgB,EACnFsoC,EAAS,IAAMF,EAAI,OAAQ,IAAMpoC,EAAI,KAAK,mBAAoB,EAAE,EAAG,gBAAgB,EACnFuoC,EAAW,IAAM,CACrB,MAAM57B,EAAU,OAAO,kBAAmB,iBAAiB,IAAI,OAAO,cAAc,MAAM,EAAG,EAAE,CAAC,aAAa,EACxGA,GACLy7B,EAAI,SAAU,IAAMpoC,EAAI,KAAK,qBAAsB,CAAE,QAAA2M,EAAS,EAAG,YAAY,CAC/E,EACM67B,EAAU,IAAMJ,EAAI,QAAS,IAAMpoC,EAAI,KAAK,mBAAoB,CAAE,KAAM,GAAO,EAAG,iBAAiB,EAEzG,GAAIjB,GAAW,CAAC4O,EACd,OACEtL,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,+BAAmB,GACxB,EAGJ,GAAI,CAACwL,EACH,OAAOxL,MAAC,OAAI,UAAU,QAAQ,kCAAsB,EAGtD,MAAMsmC,EAAU96B,EAAO,OAAS,aAEhC,OACEtL,OAAC,OAAI,UAAU,uBAEb,UAAAA,OAAC0K,EAAA,CAAK,QAAQ,WACZ,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACnI,GAAA,CAAU,KAAM,GAAI,EAAE,YACtByuC,QACE,QAAK,UAAU,+BAA+B,sBAAU,QAExD,QAAK,UAAWrjC,EAAG,4BAA6BuI,EAAO,MAAQ,KAAO,MAAM,EAC1E,SAAAA,EAAO,MAAQ,QAAU,QAC5B,GAEJ,EACAxL,MAACmL,GAAA,CACE,SAAAm7B,EACG,iGACApmC,OAAAO,WAAA,CAAE,oBAAOT,MAAC,QAAM,SAAAwL,EAAO,QAAU,IAAI,EAAQA,EAAO,MAAQtL,OAAAO,WAAA,CAAE,sBAAU+K,EAAO,OAAM,EAAM,KAAMA,EAAO,OAAStL,OAAAO,WAAA,CAAE,uBAAW+K,EAAO,QAAO,EAAM,MAAK,EAC7J,EAEC,CAAC86B,GACApmC,OAAC,OAAI,UAAU,wBACb,UAAAF,MAACumC,IAAK,GAAI/6B,EAAO,OAAS,GAAO,MAAM,eAAe,EACtDxL,MAACumC,GAAA,CAAK,IAAK/6B,EAAO,OAAS,KAAO,EAAG,MAAO,UAAUA,EAAO,OAAS,CAAC,GAAI,EAC3ExL,MAACumC,GAAA,CAAK,IAAK/6B,EAAO,QAAU,KAAO,EAAG,MAAO,WAAWA,EAAO,QAAU,CAAC,GAAI,EAC9ExL,MAACumC,GAAA,CAAK,MAAKtoC,EAAAuN,EAAO,WAAP,YAAAvN,EAAiB,SAAU,KAAO,EAAG,MAAO,eAAaqG,EAAAkH,EAAO,WAAP,YAAAlH,EAAiB,SAAU,CAAC,GAAI,EACpGtE,MAACumC,GAAA,CAAK,MAAK53B,EAAAnD,EAAO,YAAP,YAAAmD,EAAkB,SAAU,KAAO,EAAG,MAAO,gBAAc+X,EAAAlb,EAAO,YAAP,YAAAkb,EAAkB,SAAU,CAAC,GAAI,GACzG,EAGFxmB,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASqiC,EAAQ,SAAU,CAAC,CAAC1uB,GAAQ8uB,EACxE,UAAA9uB,IAAS,OAASxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAAChK,GAAA,CAAU,KAAM,GAAI,EAAG,QAE7F,EACAkK,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASsiC,EAAQ,SAAU,CAAC,CAAC3uB,GAAQ8uB,EACxE,UAAA9uB,IAAS,OAASxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAAC9J,GAAA,CAAQ,KAAM,GAAI,EAAG,QAE3F,EACAgK,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASuiC,EAAU,SAAU,CAAC,CAAC5uB,GAAQ8uB,EAC1E,UAAA9uB,IAAS,SAAWxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACwmC,GAAA,CAAU,KAAM,GAAI,EAAG,UAE/F,EACAtmC,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASwiC,EAAS,SAAU,CAAC,CAAC7uB,GAAQ8uB,EACrE,UAAA9uB,IAAS,QAAUxX,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAAChI,GAAA,CAAe,KAAM,GAAI,EAAG,gBAEnG,EACAkI,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS4D,EAAQ,SAAU,CAAC,CAAC+P,EAC7D,UAAAxX,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,GACF,GACF,EAGCkiC,UACEz3B,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACymC,GAAA,CAAS,KAAM,GAAI,EAAE,eACxB,SACCt7B,GAAA,CAAS,yBAAYnL,MAAC,QAAK,8CAAkC,EAAO,iBAAa,EAClFE,OAAC,MAAG,UAAU,oBACZ,UAAAF,MAAC,MAAG,gBAAI,EACRA,MAAC,MAAG,UAAU,gBAAgB,MAAOqiC,EAAO,SAAW,SAAAA,EAAO,UAAY,IAAI,EAC9EriC,MAAC,MAAG,kBAAM,EACVA,MAAC,MAAG,UAAU,gBAAgB,MAAOqiC,EAAO,UAAY,SAAAA,EAAO,WAAa,IAAI,EAChFriC,MAAC,MAAG,kBAAM,QACT,MAAG,SAAAA,MAAC,QAAM,SAAAqiC,EAAO,QAAU,OAAO,EAAO,EAC1CriC,MAAC,MAAG,qBAAS,EACbA,MAAC,MAAI,SAAAqiC,EAAO,SAAW,UAAY,WAAW,GAChD,GACF,SAIDz3B,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACjI,GAAA,CAAS,KAAM,GAAI,EAAE,sBACxB,EACAiI,MAACmL,IACE,SAAA46B,GAAA,MAAAA,EAAM,QACH,GAAGA,EAAK,MAAM,MAAM,mBACpB,0BACN,EACCA,GAAQA,EAAK,MAAM,OAAS,GAC3B/lC,MAAC,MAAG,UAAU,oBACX,SAAA+lC,EAAK,MAAM,IAAK17B,SACd,MACC,SAAArK,MAAC,QAAM,SAAAqK,CAAA,CAAE,GADFA,CAET,CACD,EACH,EAED07B,GAAQA,EAAK,MAAM,OAAS,SAC1B,OAAI,UAAU,+BACZ,SAAAA,EAAK,MAAM,MAAM,EAAG,GAAG,EAAE,KAAK;AAAA,CAAI,EACrC,GAEJ,GACF,CAEJ,CAEA,SAASQ,GAAK,CAAE,GAAAtsB,EAAI,MAAAiH,GAAyC,CAC3D,OACEhhB,OAAC,QAAK,UAAW+C,EAAG,yBAA0BgX,EAAK,KAAO,MAAM,EAC7D,UAAAA,EAAKja,MAAC8G,GAAA,CAAa,KAAM,GAAI,QAAMu8B,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAC7EniB,CAAA,EACH,CAEJ,CCpMO,SAASwlB,GAAoB,CAAE,WAAAp7B,GAAqB,CACzD,MAAMrG,EAAQC,GAAA,EACR,CAACC,EAAGC,CAAI,EAAIjJ,WAAS,EAAE,EACvB,CAACwqC,EAASC,CAAU,EAAIzqC,WAAmD,CAAE,SAAU,GAAM,SAAU,GAAM,EAC7G,CAACoJ,EAASC,CAAU,EAAIrJ,WAA0B,IAAI,EACtD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAK,EACtC,CAAC0qC,EAAWC,CAAY,EAAI3qC,WAAS,EAAE,EAEvC4qC,EAAW,MAAOrE,GAAkB,CACxC,GAAKA,EAAM,OACX,CAAA7lC,EAAW,EAAI,EACfiqC,EAAapE,CAAK,EAClB,GAAI,CACF,MAAMsE,EAAgB,CACpB,GAAIL,EAAQ,SAAW,CAAC,UAAmB,EAAI,GAC/C,GAAIA,EAAQ,SAAW,CAAC,UAAmB,EAAI,EAAC,EAE5CjnC,EAAI,MAAM7B,EAAI,KAClB,0BACA,CAAE,MAAA6kC,EAAO,MAAO,GAAI,QAASsE,CAAA,CAAc,EAE7CxhC,EAAW9F,EAAE,SAAW,EAAE,CAC5B,OAAS3B,EAAK,CACZkH,EAAM,MAAM,kBAAmBlH,EAAc,OAAO,EAAE,EACtDyH,EAAW,EAAE,CACf,SACE3I,EAAW,EAAK,CAClB,EACF,EAGAqB,YAAU,IAAM,CACV2oC,KAAoBA,CAAS,CAEnC,EAAG,CAACF,CAAO,CAAC,EAGZzoC,YAAU,IAAM,CACV2oC,KAAoBA,CAAS,CAEnC,EAAG,CAACv7B,CAAU,CAAC,EAEf,MAAMtF,EAAUuO,UAAQ,IAAM,CAC5B,MAAM0yB,GAAO1hC,GAAW,IAAI,OAAQ7F,GAAMA,EAAE,SAAW,UAAU,EAC3D8xB,GAAMjsB,GAAW,IAAI,OAAQ7F,GAAMA,EAAE,SAAW,UAAU,EAChE,MAAO,CAAE,IAAAunC,EAAK,GAAAzV,CAAA,CAChB,EAAG,CAACjsB,CAAO,CAAC,EAEZ,OACErF,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC0K,EAAA,CAAK,QAAQ,WACZ,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAACgD,GAAA,CAAW,KAAM,GAAI,EAAE,oBAC1B,EACAhD,MAACmL,IAAS,iFAAqE,EAC/EjL,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,SACC,KAAK,OACL,UAAU,QACV,YAAY,8BACZ,MAAOmF,EACP,SAAW/G,GAAMgH,EAAKhH,EAAE,OAAO,KAAK,EACpC,UAAYA,GAAM,CACZA,EAAE,MAAQ,SAAS2oC,EAAS5hC,CAAC,CACnC,EACA,SAAUvI,CAAA,GAEZsD,OAAC2D,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAMkjC,EAAS5hC,CAAC,EAAG,SAAUvI,GAAW,CAACuI,EAAE,OAC3E,UAAAvI,EAAUoD,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACgD,GAAA,CAAW,KAAM,GAAI,EAAG,UAEtF,GACF,EACA9C,OAAC,OAAI,UAAU,2BACb,UAAAF,MAACknC,GAAA,CACC,OAAQP,EAAQ,SAChB,SAAU,IAAMC,EAAYzgC,IAAO,CAAE,GAAGA,EAAG,SAAU,CAACA,EAAE,UAAW,EACnE,MAAM,WACN,KAAMnG,MAAC8L,GAAA,CAAS,KAAM,GAAI,IAE5B9L,MAACknC,GAAA,CACC,OAAQP,EAAQ,SAChB,SAAU,IAAMC,EAAYzgC,IAAO,CAAE,GAAGA,EAAG,SAAU,CAACA,EAAE,UAAW,EACnE,MAAM,WACN,KAAMnG,MAAC7J,GAAA,CAAM,KAAM,GAAI,IAExBgP,SACE,UAAO,KAAK,SAAS,UAAU,WAAW,QAAS,IAAM,CAAEC,EAAK,EAAE,EAAGI,EAAW,IAAI,EAAGshC,EAAa,EAAE,CAAG,EAAG,aAAW,QACtH,eAACvgC,GAAA,CAAE,KAAM,GAAI,EACf,GAEJ,GACF,EAEC3J,SACE,OAAI,UAAU,eACb,SAAAoD,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACrB,EAGD,CAAC3R,GAAW2I,GAAWA,EAAQ,SAAW,GACzCvF,MAACgM,GAAA,CACC,KAAMhM,MAACgD,GAAA,CAAW,KAAM,GAAI,EAC5B,MAAM,aACN,QAAS,6BAA6B6jC,CAAS,OAIlD7gC,EAAQ,IAAI,OAAS,UACnB4E,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAAE,cAAY9F,EAAQ,IAAI,OAAO,KACvD,EACAhG,MAAC,MAAG,UAAU,4BACX,SAAAgG,EAAQ,IAAI,IAAI,CAACtG,EAAGtE,IACnB8E,OAAC,MAAoB,UAAU,uBAC7B,UAAAA,OAAC,OAAI,UAAU,4BACb,UAAAF,MAAC,QAAM,WAAE,QAAQ,EACjBE,OAAC,QAAK,UAAU,gBAAgB,mBAAOR,EAAE,MAAM,QAAQ,CAAC,GAAE,GAC5D,EACAM,MAAC,KAAE,UAAU,gBAAiB,WAAE,QAAQ,IALjC,OAAO5E,CAAC,EAMjB,CACD,EACH,GACF,EAGD4K,EAAQ,GAAG,OAAS,UAClB4E,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,cAAY6P,EAAQ,GAAG,OAAO,KACnD,EACAhG,MAAC,OAAI,UAAU,4BACZ,SAAAgG,EAAQ,GAAG,IAAI,CAACtG,EAAGtE,IAClB8E,OAAC,OAAoB,UAAU,uBAC7B,UAAAA,OAAC,OAAI,UAAU,4BACb,UAAAA,OAAC,QAAK,UAAU,qBAAqB,UAAAF,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,aAAS,EAChEuJ,EAAE,OAASQ,OAAC,QAAK,UAAU,gBAAgB,oBAAQR,EAAE,OAAM,GAC9D,EACAM,MAAC,KAAE,UAAU,UAAW,WAAE,QAAQ,IAL1B,MAAM5E,CAAC,EAMjB,CACD,EACH,GACF,GAEJ,CAEJ,CAEA,SAAS8rC,GAAW,CAClB,OAAA9jC,EACA,SAAArC,EACA,MAAAmgB,EACA,KAAAjV,CACF,EAKG,CACD,OACE/L,OAAC,UACC,KAAK,SACL,UAAW+C,EAAG,qBAAsBG,GAAU,2BAA2B,EACzE,QAASrC,EACT,eAAcqC,EAEb,UAAA6I,EACDjM,MAAC,QAAM,SAAAkhB,CAAA,CAAM,IAGnB,CCtKO,SAASimB,GAAY,CAAE,WAAA77B,GAAqB,6BACjD,MAAMrG,EAAQC,GAAA,EACR,CAACkiC,EAAKC,CAAM,EAAIlrC,WAA8B,IAAI,EAClD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAAC+5B,EAAQC,CAAS,EAAIh6B,WAAS,EAAK,EACpC,CAACmrC,EAAOC,CAAQ,EAAIprC,WAAwE,IAAI,EAChG,CAACqrC,EAASC,CAAU,EAAItrC,WAAS,EAAK,EAEtCsL,EAAS,SAAY,CACzB5K,EAAW,EAAI,EACf,GAAI,CACF,MAAM6C,EAAI,MAAM7B,EAAI,IAA8B,uBAAuB,EACzEwpC,EAAO3nC,EAAE,MAAM,CACjB,OAAS3B,EAAK,CACZkH,EAAM,MAAM,uBAAwBlH,EAAc,OAAO,EAAE,CAC7D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACduJ,EAAA,CAEF,EAAG,CAAC6D,CAAU,CAAC,EAEf,MAAMu0B,EAAS,CAAC4F,EAA2B/3B,EAAa/R,IAAmB,CACzE0rC,EAAQ1/B,GAAQA,GAAM,CAAE,GAAGA,EAAK,CAAC89B,CAAK,EAAG,CAAE,GAAI99B,EAAI89B,CAAK,GAAK,GAAK,CAAC/3B,CAAG,EAAG/R,CAAA,CAAM,CAAS,CAC1F,EAEM47B,EAAS,SAAY,CACzB,GAAK6P,EACL,CAAAjR,EAAU,EAAI,EACd,GAAI,CACF,MAAMt4B,EAAI,IAAI,wBAAyBupC,CAAG,EAC1CniC,EAAM,QAAQ,eAAe,CAC/B,OAASlH,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,SACEo4B,EAAU,EAAK,CACjB,EACF,EAEMuR,EAAS,SAAY,CACzBD,EAAW,EAAI,EACf,GAAI,CACF,MAAM/nC,EAAI,MAAM7B,EAAI,KAClB,mBACA,EAAC,EAEH0pC,EAAS7nC,EAAE,MAAM,CACnB,OAAS3B,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,SACE0pC,EAAW,EAAK,CAClB,CACF,EAEA,OAAI7qC,GAAW,CAACwqC,EAEZlnC,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,2BAAe,GACpB,EAGConC,EAGHlnC,OAAC,OAAI,UAAU,uBAEb,UAAAA,OAAC0K,EAAA,CACC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,aAAS,SACtCgV,GAAA,CAAS,8DAAiDnL,MAAC,QAAK,kCAAsB,EAAO,KAAC,EAC/FE,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC2nC,GAAA,CAAI,MAAM,UAAU,OAAM,GACzB,SAAAznC,OAAC,SAAM,UAAU,gBACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS,CAAC,GAAC/B,EAAAmpC,EAAI,WAAJ,MAAAnpC,EAAc,SACzB,SAAWG,GAAMyhC,EAAO,WAAY,UAAWzhC,EAAE,OAAO,OAAO,UAEhE,QAAM,UAAAkG,EAAA8iC,EAAI,WAAJ,MAAA9iC,EAAc,QAAU,KAAO,MAAM,GAC9C,EACF,EACAtE,MAAC2nC,GAAA,CAAI,MAAM,MACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO2O,EAAAy4B,EAAI,WAAJ,YAAAz4B,EAAc,MAAO,GAC5B,SAAWvQ,GAAMyhC,EAAO,WAAY,MAAOzhC,EAAE,OAAO,KAAK,EACzD,YAAY,0BAEhB,EACA4B,MAAC2nC,GAAA,CAAI,MAAM,YACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO0mB,EAAA0gB,EAAI,WAAJ,YAAA1gB,EAAc,MAAO,GAC5B,SAAWtoB,GAAMyhC,EAAO,WAAY,MAAOzhC,EAAE,OAAO,KAAK,EACzD,YAAY,wBAEhB,EACA4B,MAAC2nC,GAAA,CAAI,MAAM,YACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO84B,EAAAsO,EAAI,WAAJ,YAAAtO,EAAc,YAAa,GAClC,SAAW16B,GAAMyhC,EAAO,WAAY,YAAazhC,EAAE,OAAO,KAAK,EAC/D,YAAY,mCACd,CACF,GACF,GACF,SAGCwM,EAAA,CACC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAAE,mBAAe,EAChD9L,MAACmL,IAAS,uDAA2C,EACrDjL,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC2nC,GAAA,CAAI,MAAM,aACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO+4B,EAAAqO,EAAI,WAAJ,YAAArO,EAAc,YAAa,GAClC,SAAW36B,GAAMyhC,EAAO,WAAY,YAAazhC,EAAE,OAAO,KAAK,EAC/D,YAAY,mBAEhB,EACA4B,MAAC2nC,GAAA,CAAI,MAAM,0BACT,SAAA3nC,MAAC,SACC,KAAK,SACL,IAAK,EACL,IAAK,OACL,UAAU,aACV,QAAOg5B,EAAAoO,EAAI,WAAJ,YAAApO,EAAc,eAAgB,IACrC,SAAW56B,GAAMyhC,EAAO,WAAY,eAAgB,OAAOzhC,EAAE,OAAO,KAAK,CAAC,GAC5E,CACF,GACF,GACF,SAGCwM,EAAA,CACC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACnI,GAAA,CAAU,KAAM,GAAI,EAAE,aAAS,EAC3CmI,MAACmL,IAAS,4DAAgD,EAC1DjL,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC2nC,GAAA,CAAI,MAAM,YACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO4nC,EAAAR,EAAI,MAAJ,YAAAQ,EAAS,WAAY,GAC5B,SAAWxpC,GAAMyhC,EAAO,MAAO,WAAYzhC,EAAE,OAAO,KAAK,EACzD,YAAY,kBAEhB,EACA4B,MAAC2nC,GAAA,CAAI,MAAM,aACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO6nC,EAAAT,EAAI,MAAJ,YAAAS,EAAS,YAAa,GAC7B,SAAWzpC,GAAMyhC,EAAO,MAAO,YAAazhC,EAAE,OAAO,KAAK,EAC1D,YAAY,gCAEhB,EACA4B,MAAC2nC,GAAA,CAAI,MAAM,SACT,SAAA3nC,MAAC,SACC,KAAK,OACL,UAAU,aACV,QAAO8nC,EAAAV,EAAI,MAAJ,YAAAU,EAAS,SAAU,OAC1B,SAAW1pC,GAAMyhC,EAAO,MAAO,SAAUzhC,EAAE,OAAO,KAAK,EACvD,YAAY,SAEhB,EACA4B,MAAC2nC,IAAI,MAAM,YAAY,OAAM,GAC3B,SAAAznC,OAAC,SAAM,UAAU,gBACf,UAAAF,MAAC,SACC,KAAK,WACL,QAAS,CAAC,GAAC+nC,EAAAX,EAAI,MAAJ,MAAAW,EAAS,UACpB,SAAW3pC,GAAMyhC,EAAO,MAAO,WAAYzhC,EAAE,OAAO,OAAO,UAE5D,QAAM,UAAA4pC,EAAAZ,EAAI,MAAJ,MAAAY,EAAS,SAAW,KAAO,MAAM,GAC1C,EACF,GACF,GACF,SAGCp9B,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC4B,GAAA,CAAS,KAAM,GAAI,EAAE,kCACxB,EACA5B,MAACmL,IAAS,yHAGV,EACAnL,MAAC,OAAI,UAAU,gBAAgB,iJAG/B,GACF,SAGC4K,EAAA,CACC,UAAA1K,OAACgL,GAAA,CACC,UAAAlL,MAAC5G,GAAA,CAAK,KAAM,GAAI,EAAE,qBACpB,EACA4G,MAACmL,IAAS,6DAAiD,EAC3DjL,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC2D,GAAO,QAAQ,YAAY,QAAS6jC,EAAQ,SAAUF,EACpD,UAAAA,EAAUxnC,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAAC5G,GAAA,CAAK,KAAM,GAAI,EAAG,uBAEhF,SACCyK,EAAA,CAAO,QAAQ,UAAU,QAAS0zB,EAAQ,SAAUrB,EAClD,UAAAA,EAASl2B,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,cAAc,EAAKrjC,MAACkd,GAAA,CAAK,KAAM,GAAI,EAAG,eAE/E,GACF,EACCoqB,GAASA,EAAM,OAAS,SACtB,MAAG,UAAU,oBAAoB,MAAO,CAAE,UAAW,IACnD,WAAM,IAAI,CAAC5iC,EAAGtJ,IACb8E,OAAC,MAAW,UAAU,mBACpB,UAAAF,MAAC,QAAK,UAAU,oBACd,SAAAA,MAAC,QAAK,UAAWiD,EAAG,cAAeyB,EAAE,KAAO,iBAAmB,kBAAkB,EAC9E,WAAE,KAAO,KAAO,OACnB,EACF,EACA1E,MAAC,QAAK,UAAU,oBAAqB,WAAE,KAAK,EAC5CA,MAAC,QAAK,UAAU,4BAA6B,WAAE,OAAO,IAP/C5E,CAQT,CACD,EACH,GAEJ,GACF,QAxKgB,OAAI,UAAU,QAAQ,gCAAoB,CA0K9D,CAEA,SAASusC,GAAI,CACX,MAAAzmB,EACA,SAAAlW,EACA,OAAAi9B,CACF,EAIG,CACD,OAAIA,EAEA/nC,OAAC,OAAI,UAAU,2BACb,UAAAF,MAAC,OAAI,UAAU,0BAA2B,SAAAkhB,EAAM,EAChDlhB,MAAC,OAAI,UAAU,4BAA6B,SAAAgL,CAAA,CAAS,GACvD,EAIF9K,OAAC,SAAM,UAAU,0BACf,UAAAF,MAAC,QAAM,SAAAkhB,CAAA,CAAM,EACZlW,CAAA,EACH,CAEJ,CCxPA,MAAMk9B,GAID,CACH,CAAE,GAAI,WAAY,MAAO,WAAY,KAAM5vC,EAAA,EAC3C,CAAE,GAAI,WAAY,MAAO,WAAY,KAAMnC,EAAA,EAC3C,CAAE,GAAI,WAAY,MAAO,iBAAkB,KAAM2V,EAAA,EACjD,CAAE,GAAI,MAAO,MAAO,WAAY,KAAMjU,EAAA,EACtC,CAAE,GAAI,WAAY,MAAO,kBAAmB,KAAMmL,EAAA,EAClD,CAAE,GAAI,SAAU,MAAO,SAAU,KAAMjB,EAAA,CACzC,EAEA,SAASomC,GAAYC,EAAe,CAClC,MAAMnjC,EAAQC,GAAA,EACR,CAAC9B,EAAQilC,CAAS,EAAIlsC,WAAmB,UAAU,EACnD,CAACmP,EAAYg9B,CAAa,EAAInsC,WAAS,CAAC,EAExC+0B,EAAUvzB,cAAY,IAAM,CAChC2qC,EAAextC,GAAMA,EAAI,CAAC,CAC5B,EAAG,EAAE,EAECytC,EAAe5qC,cAAY,SAAY,CAC3CuzB,EAAA,EACAjsB,EAAM,KAAK,qBAAsB,IAAI,CACvC,EAAG,CAACisB,EAASjsB,CAAK,CAAC,EAEbujC,EAAc,IAAM,CACxB,OAAQplC,EAAA,CACN,IAAK,WACH,aAAQq+B,GAAA,CAAe,WAAAn2B,EAAwB,UAAW4lB,EAAS,kBAAmBmX,EAAW,EACnG,IAAK,WACH,OAAOroC,MAACoiC,IAAc,WAAA92B,EAAwB,EAChD,IAAK,WACH,OAAOtL,MAACwjC,IAAc,WAAAl4B,EAAwB,EAChD,IAAK,MACH,OAAOtL,MAAC8lC,IAAa,WAAAx6B,EAAwB,EAC/C,IAAK,WACH,OAAOtL,MAAC0mC,IAAoB,WAAAp7B,EAAwB,EACtD,IAAK,SACH,OAAOtL,MAACmnC,IAAY,WAAA77B,EAAwB,EAC9C,QACE,cAAQV,EAAA,CAAK,4BAAgBxH,CAAA,EAAO,EAE1C,EAEA,OACElD,OAAC,OAAI,UAAU,8BAEb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC7J,GAAA,CAAM,KAAM,GAAI,EAAE,WACrB,EACA6J,MAAC,KAAE,UAAU,gBAAgB,uFAE7B,GACF,EACAA,MAAC,OAAI,UAAU,eACb,SAAAA,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAASuoC,EACT,aAAW,iBACX,MAAM,UAEN,SAAAvoC,MAACG,GAAA,CAAU,KAAM,GAAI,GACvB,CACF,GACF,EAEAD,OAAC,OAAI,UAAU,kBAEb,UAAAF,MAAC,OAAI,UAAU,qBAAqB,aAAW,iBAC5C,SAAAkoC,GAAQ,IAAK/hC,GAAM,CAClB,MAAMhD,EAAOgD,EAAE,KACTtF,EAAWuC,IAAW+C,EAAE,GAC9B,OACEjG,OAAC,UAEC,KAAK,SACL,KAAK,MACL,gBAAeW,EACf,UAAWoC,EAAG,uBAAwBpC,GAAY,6BAA6B,EAC/E,QAAS,IAAMwnC,EAAUliC,EAAE,EAAE,EAE7B,UAAAnG,MAACmD,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAC5BnD,MAAC,QAAM,SAAAmG,EAAE,MAAM,IARVA,EAAE,GAWb,CAAC,EACH,QAGC,OAAI,UAAU,cACZ,SAAAqiC,EAAA,GAD+BplC,CAElC,GACF,GACF,CAEJ,CACO,MAAMqlC,GAAS73B,GAAM,KAAKu3B,EAAW,ECjFtCO,GAAc,CAClB,CAAE,GAAI,KAAM,MAAO,YAAa,GAAI,GAAK,GAAK,KAC9C,CAAE,GAAI,KAAM,MAAO,WAAY,GAAI,GAAK,GAAK,GAAK,KAClD,CAAE,GAAI,KAAM,MAAO,cAAe,GAAI,EAAI,GAAK,GAAK,GAAK,KACzD,CAAE,GAAI,MAAO,MAAO,eAAgB,GAAI,GAAK,GAAK,GAAK,GAAK,KAC5D,CAAE,GAAI,MAAO,MAAO,WAAY,GAAI,EACtC,EAEO,SAASnX,GAAQ,CAAE,SAAAllB,GAAmB,SAC3C,MAAMpH,EAAQC,GAAA,EACR,CAACvK,EAAM4Q,CAAO,EAAIpP,WAAiC,IAAI,EACvD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACwsC,EAASC,CAAU,EAAIzsC,WAAiB,IAAI,EAC7C,CAACC,EAAUC,CAAW,EAAIF,WAAsB,IAAI,GAAK,EACzD,CAAC4sB,EAAMC,CAAO,EAAI7sB,WAAS,CAAC,EAE5B2B,EAAO,MAAO+qC,GAAmB,CACrC,GAAI,CACF,MAAM1jC,EAAI0jC,EAAQ,UAAU,mBAAmBA,CAAK,CAAC,cAAgB,cAC/DnpC,EAAI,MAAM7B,EAAI,IAAqB,WAAWsH,CAAC,EAAE,EACvDoG,EAAQ7L,CAAC,EACTrD,EACE,IAAI,IACFqD,EAAE,SACC,OAAQoP,GAAYpP,EAAE,OAAO,KAAM4wB,GAAQA,EAA8B,YAAcxhB,EAAQ,EAAE,CAAC,EAClG,IAAKA,GAAYA,EAAQ,EAAE,EAChC,CAEJ,OAAS/Q,EAAK,CACZkH,EAAM,MAAM,wBAAyBlH,EAAc,OAAO,EAAE,CAC9D,SACElB,EAAW,EAAK,CAClB,CACF,EAEAqB,YAAU,IAAM,CACdrB,EAAW,EAAI,EACf,MAAMisC,EAAQJ,GAAY,KAAMhpC,GAAMA,EAAE,KAAOipC,CAAO,GAAKD,GAAY,CAAC,EACxE,GAAII,EAAM,GAAK,EAAG,CAChB,MAAMD,EAAQ,IAAI,KAAK,KAAK,MAAQC,EAAM,EAAE,EAAE,cAC9ChrC,EAAK+qC,CAAK,CACZ,MACE/qC,EAAA,CAGJ,EAAG,CAAC6qC,CAAO,CAAC,EAEZzqC,YAAU,IAAM,CACd,MAAM+J,EAAK,YAAY,IAAM+gB,EAAStkB,GAAMA,EAAI,CAAC,EAAG,GAAM,EAC1D,MAAO,IAAM,cAAcuD,CAAE,CAC/B,EAAG,EAAE,EAGL,MAAM8gC,MAAsB,IAC5B,UAAWzY,KAAM31B,GAAA,YAAAA,EAAM,SAAU,GAAI,CACnC,MAAMquC,EAAO1Y,EAA8B,WAAa,SACnDyY,EAAgB,IAAIC,CAAG,GAAGD,EAAgB,IAAIC,EAAK,EAAE,EAC1DD,EAAgB,IAAIC,CAAG,EAAG,KAAK1Y,CAAE,CACnC,CAEA,MAAM2Y,EAAiBhhC,GAAe,CACpC5L,EAAasL,GAAQ,CACnB,MAAMtI,EAAO,IAAI,IAAIsI,CAAG,EACxB,OAAItI,EAAK,IAAI4I,CAAE,EAAG5I,EAAK,OAAO4I,CAAE,EAC3B5I,EAAK,IAAI4I,CAAE,EACT5I,CACT,CAAC,CACH,EAEM6pC,EAAe,IAAM,CACzB,GAAI,CAACvuC,EAAM,OACX,MAAM2f,EAAO,IAAI,KAAK,CAAC,KAAK,UAAU3f,EAAM,KAAM,CAAC,CAAC,EAAG,CAAE,KAAM,mBAAoB,EAC7E+P,EAAM,IAAI,gBAAgB4P,CAAI,EAC9B1f,EAAI,SAAS,cAAc,GAAG,EACpCA,EAAE,KAAO8P,EACT9P,EAAE,SAAW,iBAAiB,IAAI,OAAO,cAAc,QAAQ,QAAS,GAAG,CAAC,QAC5EA,EAAE,QACF,IAAI,gBAAgB8P,CAAG,EACvBzF,EAAM,QAAQ,mBAAmB,CACnC,EAEA,OACE/E,OAAC,OAAI,UAAU,oBAAoB,YAAW6oB,EAC5C,UAAA7oB,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC8B,GAAA,CAAY,KAAM,GAAI,EAAE,YAC3B,EACA5B,OAAC,KAAE,UAAU,gBAAgB,iEAE1BjC,EAAAtD,GAAA,YAAAA,EAAM,QAAN,YAAAsD,EAAa,SACZiC,OAAAO,WAAA,CAAE,2BAAe8H,GAAe5N,EAAK,MAAM,MAAM,GAAE,GAEvD,GACF,EACAuF,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,sBACb,UAAAF,MAACvI,IAAO,KAAM,GAAI,MAAO,CAAE,MAAO,mBAAqB,EACvDuI,MAAC,UACC,UAAU,mBACV,MAAO2oC,EACP,SAAWvqC,GAAMwqC,EAAWxqC,EAAE,OAAO,KAAK,EAC1C,MAAM,aAEL,SAAAsqC,GAAY,IAAKhpC,GAChBM,MAAC,UAAkB,MAAON,EAAE,GAAK,SAAAA,EAAE,OAAtBA,EAAE,EAA0B,CAC1C,GACH,EACF,EACAQ,OAAC2D,EAAA,CACC,QAAQ,QACR,KAAK,KACL,QAAS,IAAM,CACbhH,EAAW,EAAI,EACf,MAAMisC,EAAQJ,GAAY,KAAMhpC,GAAMA,EAAE,KAAOipC,CAAO,GAAKD,GAAY,CAAC,EACpEI,EAAM,GAAK,EACbhrC,EAAK,IAAI,KAAK,KAAK,MAAQgrC,EAAM,EAAE,EAAE,aAAa,EAElDhrC,EAAA,CAEJ,EAEA,UAAAkC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,qBAExB0D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASqlC,EAC7C,UAAAlpC,MAAC/I,GAAA,CAAS,KAAM,GAAI,EAAE,WACxB,GACF,GACF,EAEC2F,GACCsD,OAAC,OAAI,UAAU,eACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,4BAAgB,GACrB,EAGD,CAACpD,GAAWjC,GACXuF,OAAC,OAAI,UAAU,eACZ,UAAAvF,EAAK,SAAS,SAAW,GACxBuF,OAAC0K,EAAA,CACC,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACc,GAAA,CAAO,KAAM,GAAI,EAAE,gBAAY,EAC3Cd,MAACmL,IAAS,qEAAyD,GACrE,EAGDxQ,EAAK,SAAS,IAAKK,GAAM,CACxB,MAAMiyB,EAAS8b,EAAgB,IAAI/tC,EAAE,EAAE,GAAK,GACtCmuC,EAAS/sC,EAAS,IAAIpB,EAAE,EAAE,EAChC,OACEkF,OAAC0K,EAAA,CAAgB,UAAU,kBACzB,UAAA1K,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,EAAG,SAAU,EAAG,KAAM,GACjF,UAAAA,OAAC,OAAI,UAAU,uBACb,UAAAF,MAACc,GAAA,CAAO,KAAM,GAAI,EAAE,IAAE9F,EAAE,MAC1B,EACAgF,MAAC,OAAI,UAAU,uBAAwB,WAAE,KAAK,GAChD,EACAE,OAAC,OAAI,UAAU,wBACb,UAAAA,OAAC,QAAK,UAAU,uBACd,UAAAF,MAAC,QAAK,UAAU,2BAA4B,SAAAhF,EAAE,MAAM,KAAK,EACzDkF,OAAC,QAAK,UAAU,QAAQ,eAAGlF,EAAE,MAAM,MAAM,SAAK,GAChD,EACCA,EAAE,MAAM,MAAQ,GACfkF,OAAC,QAAK,UAAU,uBACd,UAAAF,MAAC,QAAK,UAAU,2BAA4B,SAAAhF,EAAE,MAAM,MAAM,EAC1DgF,MAAC,QAAK,UAAU,QAAQ,iBAAK,GAC/B,EAEDhF,EAAE,MAAM,QAAU,GACjBkF,OAAC,QAAK,UAAU,uBACd,UAAAF,MAAC,QAAK,UAAU,2BAA4B,SAAAhF,EAAE,MAAM,QAAQ,EAC5DgF,MAAC,QAAK,UAAU,QAAQ,mBAAO,GACjC,EAEFE,OAAC,QAAK,UAAU,uBACd,UAAAF,MAAC8L,GAAA,CAAS,KAAM,GAAI,EAAE,IAAC9L,MAAC,QAAK,UAAU,2BAA4B,WAAE,MAAM,EAC3EE,OAAC,QAAK,UAAU,QAAQ,kBAAMlF,EAAE,QAAU,EAAI,GAAK,KAAI,GACzD,EACCA,EAAE,cACDgF,MAAC,QAAK,UAAU,uBACd,SAAAE,OAAC,QAAK,UAAU,QAAQ,yBAAaqI,GAAevN,EAAE,YAAY,GAAE,EACtE,GAEJ,EACAgF,MAAC,UACC,KAAK,SACL,UAAU,WACV,QAAS,IAAMipC,EAAcjuC,EAAE,EAAE,EACjC,aAAYmuC,EAAS,WAAa,SAEjC,SAAAA,QAAU/nC,GAAA,CAAY,KAAM,GAAI,EAAKpB,MAACqB,GAAA,CAAa,KAAM,GAAI,GAChE,EACF,EAEC8nC,GACCnpC,MAAC,OAAI,UAAU,wBACZ,SAAAitB,EAAO,SAAW,EACjBjtB,MAAC,OAAI,UAAU,QAAQ,MAAO,CAAE,QAAS,WAAY,SAAU,IAAM,yCAErE,EAEAitB,EAAO,MAAM,IAAI,EAAE,UAAU,IAAI,CAACqD,EAAIl1B,IACpC8E,OAAC,OAAY,UAAU,uBACrB,UAAAF,MAAC,QAAK,UAAU,sBACb,aAAI,KAAKswB,EAAG,EAAE,EAAE,oBAAmB,CACtC,QACC,QAAK,UAAU,wBAAyB,SAAAA,EAAG,MAAQ,QAAQ,EAC5DpwB,OAAC,QAAK,UAAU,uBAAuB,MAAO,OAAOowB,EAAG,MAAQA,EAAG,OAAS,EAAE,EAC3E,UAAAA,EAAG,OAAS,IAAIA,EAAG,MAAM,IAAM,GAC/B,OAAOA,EAAG,MAAQA,EAAG,OAASA,EAAG,MAAQ,EAAE,GAC9C,IARQl1B,CASV,CACD,EAEL,IAjEOJ,EAAE,EAmEb,CAEJ,CAAC,EAGA+tC,EAAgB,IAAI,QAAQ,GAC3B7oC,OAAC0K,EAAA,CAAK,UAAU,kBACd,UAAA5K,MAAC,OAAI,UAAU,uBACb,SAAAE,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,EAAG,SAAU,EAAG,KAAM,GACjF,UAAAA,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC8B,GAAA,CAAY,KAAM,GAAI,EAAE,kBAC3B,EACA9B,MAAC,OAAI,UAAU,uBAAuB,mDAEtC,GACF,EACF,EACAA,MAAC,OAAI,UAAU,wBACX,YAAgB,IAAI,QAAQ,GAAK,IAAI,MAAM,IAAI,EAAE,UAAU,IAAI,CAACswB,EAAIl1B,IACpE8E,OAAC,OAAY,UAAU,uBACrB,UAAAF,MAAC,QAAK,UAAU,sBACb,aAAI,KAAKswB,EAAG,EAAE,EAAE,oBAAmB,CACtC,QACC,QAAK,UAAU,wBAAyB,SAAAA,EAAG,MAAQ,QAAQ,EAC5DpwB,OAAC,QAAK,UAAU,uBAAuB,MAAO,OAAOowB,EAAG,MAAQA,EAAG,OAAS,EAAE,EAC3E,UAAAA,EAAG,OAAS,IAAIA,EAAG,MAAM,IAAM,GAC/B,OAAOA,EAAG,MAAQA,EAAG,OAASA,EAAG,MAAQ,EAAE,GAC9C,IARQl1B,CASV,CACD,EACH,GACF,IAGDkJ,EAAA3J,EAAK,QAAL,YAAA2J,EAAY,SAAU,OAAO,KAAK3J,EAAK,MAAM,MAAM,EAAE,OAAS,GAC7DuF,OAAC0K,EAAA,CACC,UAAA5K,MAACkL,IAAU,gCAAoB,SAC9BC,GAAA,CAAU,UAAAxQ,EAAK,MAAM,MAAM,uBAAmB,QAC9C,OAAI,MAAO,CAAE,QAAS,OAAQ,SAAU,OAAQ,IAAK,EAAG,UAAW,GACjE,gBAAO,QAAQA,EAAK,MAAM,MAAM,EAC9B,KAAK,CAACC,EAAGC,IAAMA,EAAE,CAAC,EAAID,EAAE,CAAC,CAAC,EAC1B,MAAM,EAAG,EAAE,EACX,IAAI,CAAC,CAACyU,EAAM3F,CAAK,IAChBxJ,OAAC,QAEC,UAAW+C,EAAG,MAAO,aAAa,EAClC,MAAO,CAAE,WAAY,oBAEpB,UAAAoM,EAAK,KAAG3F,CAAA,GAJJ2F,CAAA,CAMR,EACL,GACF,GAEJ,GAEJ,CAEJ,CC3TA,MAAM+5B,GAAU,CAAE,IAAK,GAAI,MAAO,GAAI,OAAQ,GAAI,KAAM,IAEjD,SAASC,GAAW,CAAE,OAAAC,EAAQ,OAAAttC,EAAS,IAAK,QAAAutC,EAAS,UAAAx+B,GAAoB,CAC9E,MAAMy+B,EAAe/rC,SAAuB,IAAI,EAC1C,CAACgsC,EAASC,CAAU,EAAIvtC,WAAyD,IAAI,EAErF,CAAE,OAAAwtC,EAAQ,SAAAC,EAAU,OAAAC,CAAA,EAAWP,EAC/B1hC,EAAI+hC,EAAO,OACjB,GAAI/hC,IAAM,EACR,OACE5H,MAAC,OAAI,UAAWiD,EAAG,oBAAqB8H,CAAS,EAAG,MAAO,CAAE,OAAA/O,CAAA,EAC3D,SAAAgE,MAAC,QAAK,kCAAsB,EAC9B,EAIJ,MAAM8pC,EAAS,IAAMV,GAAQ,KAAOA,GAAQ,MACtCW,EAAS/tC,EAASotC,GAAQ,IAAMA,GAAQ,OAExCY,EAAS,KAAK,IAAI,GAAGJ,EAAU,CAAC,EAChCK,EAAS,KAAK,IAAI,GAAGJ,EAAQ,CAAC,EAE9BK,EAAO,KAAK,IAAI,EAAG,KAAK,IAAI,GAAI,KAAK,MAAMJ,EAASliC,CAAC,EAAI,CAAC,CAAC,EAC3DuiC,GAAOL,EAASI,EAAOtiC,IAAMA,EAAI,GAEvC,SAASwiC,EAAKhvC,EAAW,CACvB,OAAOguC,GAAQ,KAAOe,EAAM/uC,GAAK8uC,EAAOC,EAC1C,CAEA,SAASE,EAAKrrC,EAAW,CACvB,OAAQA,EAAIgrC,EAAUD,EAAS,GACjC,CAEA,SAASO,EAAMtrC,EAAW,CACxB,OAAOoqC,GAAQ,IAAMW,EAAU/qC,EAAIirC,EAAUF,EAAS,GACxD,CAGA,MAAMQ,EAAaV,EAChB,IAAI,CAAC7qC,EAAG5D,IAAM,GAAGgvC,EAAKhvC,CAAC,EAAI8uC,EAAO,CAAC,IAAII,EAAMtrC,CAAC,CAAC,EAAE,EACjD,KAAK,GAAG,EAGLwrC,EAAY,CAAC,EAAG,IAAM,GAAK,IAAM,CAAC,EAAE,IAAI9lC,IAAM,CAClD,EAAG0kC,GAAQ,IAAMW,EAASrlC,EAAIqlC,EAAS,IACvC,MAAOrlC,IAAM,EAAI,IAAM,GAAG,KAAK,MAAMslC,EAAStlC,CAAC,EAAE,gBAAgB,IACjE,EAGI+lC,EAAa,CAAC,EAAG,IAAM,GAAK,IAAM,CAAC,EAAE,IAAI/lC,IAAM,CACnD,EAAG0kC,GAAQ,IAAMW,EAASrlC,EAAIqlC,EAAS,IACvC,MAAOrlC,IAAM,EAAI,IAAM,GAAG,KAAK,MAAMulC,EAASvlC,EAAI,GAAI,CAAC,KACvD,EAGIgmC,EAAY,KAAK,IAAI,EAAG,KAAK,MAAM9iC,EAAI,CAAC,CAAC,EACzC+iC,EAAUhB,EAAO,IAAI,CAAC5oB,EAAG3lB,KAAO,CAAE,EAAAA,EAAG,EAAA2lB,EAAG,EAAGqpB,EAAKhvC,CAAC,EAAI8uC,EAAO,GAAI,EAAE,OAAO,CAACvkB,EAAGvqB,IAAMA,EAAIsvC,IAAc,CAAC,EAEtGE,EAAkBjtC,cACrBS,GAAuC,CACtC,GAAI,CAACorC,EAAa,QAAS,OAC3B,MAAMvjB,EAAOujB,EAAa,QAAQ,wBAC5BqB,GAAQzsC,EAAE,QAAU6nB,EAAK,OAAS,IAAMA,EAAK,OAC7C6kB,GAAQ1sC,EAAE,QAAU6nB,EAAK,MAAQjqB,EAASiqB,EAAK,QAE/C8kB,EAAOF,EAAOzB,GAAQ,KACtBhuC,EAAI,KAAK,OAAO2vC,EAAOZ,EAAM,IAAMD,EAAOC,EAAI,EAC9Ca,EAAU,KAAK,IAAI,EAAG,KAAK,IAAIpjC,EAAI,EAAGxM,CAAC,CAAC,EAC9CsuC,EAAW,CAAE,MAAOsB,EAAS,EAAG5sC,EAAE,QAAU6nB,EAAK,KAAM,EAAG7nB,EAAE,QAAU6nB,EAAK,IAAK,EAChFsjB,GAAA,MAAAA,EAAUyB,EAASH,EAAMC,EAC3B,EACA,CAACljC,EAAGsiC,EAAMC,EAAKZ,EAASvtC,CAAM,GAG1BivC,EAAmBttC,cAAY,IAAM,CACzC+rC,EAAW,IAAI,EACfH,GAAA,MAAAA,EAAU,KAAM,EAAG,EACrB,EAAG,CAACA,CAAO,CAAC,EAEN2B,EAAMzB,EAEZ,OACEvpC,OAAC,OAAI,IAAKspC,EAAc,UAAWvmC,EAAG,cAAe8H,CAAS,EAAG,MAAO,CAAE,SAAU,YAClF,UAAA7K,OAAC,OACC,QAAS,WAAWlE,CAAM,GAC1B,MAAM,OACN,OAAAA,EACA,MAAO,CAAE,QAAS,QAAS,SAAU,WACrC,YAAa4uC,EACb,aAAcK,EAGb,UAAAT,EAAU,IAAI,CAACzhB,EAAM3tB,IACpB4E,MAAC,QAEC,GAAIopC,GAAQ,KACZ,GAAIrgB,EAAK,EACT,GAAI,IAAMqgB,GAAQ,MAClB,GAAIrgB,EAAK,EACT,OAAO,gBACP,YAAa,EACb,gBAAgB,MAChB,QAAS,IARJ,QAAQ3tB,CAAC,GAUjB,EAGAovC,EAAU,IAAI,CAACzhB,EAAM3tB,IACpB4E,MAAC,QAEC,EAAGopC,GAAQ,KAAO,EAClB,EAAGrgB,EAAK,EAAI,EACZ,WAAW,MACX,SAAU,GACV,KAAK,oBACL,WAAW,4CAEV,SAAAA,EAAK,OARD,MAAM3tB,CAAC,GAUf,EAGAqvC,EAAW,IAAI,CAAC1hB,EAAM3tB,IACrB4E,MAAC,QAEC,EAAG,IAAMopC,GAAQ,MAAQ,EACzB,EAAGrgB,EAAK,EAAI,EACZ,WAAW,QACX,SAAU,GACV,KAAK,oBACL,WAAW,4CAEV,SAAAA,EAAK,OARD,MAAM3tB,CAAC,GAUf,EAGAwuC,EAAS,IAAI,CAAC5qC,EAAG5D,IAAM,CACtB,MAAM+vC,EAAKd,EAAKrrC,CAAC,EACXosC,EAAKhB,EAAKhvC,CAAC,EACXiwC,EAAKjC,GAAQ,IAAMW,EAASoB,EAClC,OACEnrC,MAAC,QAEC,EAAGorC,EACH,EAAGC,EACH,MAAOnB,EACP,OAAQiB,EACR,GAAI,EACJ,OAAMD,GAAA,YAAAA,EAAK,SAAU9vC,EAAI,iBACzB,SAAS8vC,GAAA,YAAAA,EAAK,SAAU9vC,EAAI,EAAI,IAChC,MAAO,CAAE,WAAY,qBAAqB,EARrC,OAAOA,CAAC,GAWnB,CAAC,EAGD4E,MAAC,YACC,OAAQuqC,EACR,KAAK,OACL,OAAO,0BACP,YAAa,EACb,eAAe,QACf,cAAc,QACd,QAAS,KAIVV,EAAO,IAAI,CAAC7qC,EAAG5D,IACd4E,MAAC,UAEC,GAAIoqC,EAAKhvC,CAAC,EAAI8uC,EAAO,EACrB,GAAII,EAAMtrC,CAAC,EACX,GAAGksC,GAAA,YAAAA,EAAK,SAAU9vC,EAAI,EAAI,EAC1B,KAAK,0BACL,SAAS8vC,GAAA,YAAAA,EAAK,SAAU9vC,EAAI,EAAI,GAChC,MAAO,CAAE,WAAY,eAAe,EAN/B,OAAOA,CAAC,GAQhB,EAGAuvC,EAAQ,IAAI,CAAC,CAAE,EAAAvvC,EAAG,EAAA2lB,EAAG,EAAAxhB,KACpBS,MAAC,QAEC,EAAAT,EACA,EAAG6pC,GAAQ,IAAMW,EAAS,GAC1B,WAAW,SACX,SAAU,GACV,KAAK,oBACL,WAAW,4CAEV,SAAAhpB,CAAA,EARI,MAAM3lB,CAAC,GAUf,EAGD4E,MAAC,QACC,GAAIopC,GAAQ,KACZ,GAAIA,GAAQ,IAAMW,EAClB,GAAI,IAAMX,GAAQ,MAClB,GAAIA,GAAQ,IAAMW,EAClB,OAAO,gBACP,YAAa,GACf,IAIDmB,IAAQ,MACPhrC,OAAC,OACC,UAAU,sBACV,MAAO,CACL,KAAM,KAAK,IAAIgrC,EAAI,EAAI,GAAI,GAAS,EACpC,IAAKA,EAAI,EAAI,IAGf,UAAAlrC,MAAC,OAAI,UAAU,qBAAsB,SAAA2pC,EAAOuB,EAAI,KAAK,EAAE,EACvDhrC,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAU,oBAAoB,MAAO,CAAE,WAAY,iBAAmB,EAC5EA,MAAC,QAAK,qBAAS,QACd,UAAQ,SAAA4pC,EAASsB,EAAI,KAAK,EAAE,gBAAe,CAAE,GAChD,EACAhrC,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAU,oBAAoB,MAAO,CAAE,WAAY,2BAA6B,EACtFA,MAAC,QAAK,mBAAO,QACZ,UAAQ,SAAA6pC,EAAOqB,EAAI,KAAK,EAAE,gBAAe,CAAE,GAC9C,IACF,EAEJ,CAEJ,CC3NA,SAASI,GAAW,CAAE,MAAApqB,EAAO,IAAA2I,EAAK,QAAA0hB,EAAS,QAAAC,EAAS,OAAAC,GAEjD,CACD,MAAMroC,EAASmoC,IAAY1hB,EAC3B,OACE3pB,OAAC,MACC,UAAW+C,EAAG,oBAAqBG,GAAU,WAAW,EACxD,QAAS,IAAMqoC,EAAO5hB,CAAG,EACzB,YAAWzmB,EAAUooC,IAAY,MAAQ,YAAc,aAAgB,OAEvE,UAAAxrC,MAAC,QAAM,SAAAkhB,CAAA,CAAM,EACblhB,MAAC,QAAK,UAAU,kBACb,WAAUwrC,IAAY,MAAQ,KAAO,KAAQ,KAChD,IAGN,CAEO,SAASE,GAAW,CAAE,KAAAhtB,EAAM,QAAA6sB,EAAS,QAAAC,EAAS,OAAAC,GAAiB,CACpE,aACG,OAAI,UAAU,mBACb,SAAAvrC,OAAC,SAAM,UAAU,cACf,UAAAF,MAAC,SACC,gBAAC,MACC,UAAAA,MAACsrC,IAAW,MAAM,QAAe,IAAI,UAAiB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,EAAgB,EAC1GzrC,MAACsrC,IAAW,MAAM,WAAc,IAAI,WAAkB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,EAAgB,EAC1GzrC,MAACsrC,IAAW,MAAM,aAAc,IAAI,eAAkB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,EAAgB,EAC1GzrC,MAACsrC,IAAW,MAAM,YAAc,IAAI,mBAAmB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,EAAgB,EAC3GzrC,MAACsrC,IAAW,MAAM,YAAc,IAAI,cAAkB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,EAAgB,EAC1GzrC,MAACsrC,IAAW,MAAM,cAAc,IAAI,eAAiB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,EAAgB,EACzGzrC,MAACsrC,IAAW,MAAM,SAAa,IAAI,SAAkB,QAAAC,EAAkB,QAAAC,EAAkB,OAAAC,CAAA,CAAgB,GAC3G,EACF,EACAzrC,MAAC,SACE,SAAA0e,EAAK,SAAW,EACf1e,MAAC,MACC,eAAC,MAAG,QAAS,EAAG,UAAU,oBAAoB,kCAAsB,EACtE,EAEA0e,EAAK,IAAKtJ,GACRlV,OAAC,MACC,UAAAF,MAAC,MAAG,UAAU,oBACZ,eAAC,QAAM,SAAAoV,EAAI,QAAQ,EACrB,QACC,MAAG,UAAU,OAAQ,SAAAA,EAAI,SAAS,iBAAiB,QACnD,MAAG,UAAU,OAAQ,SAAAA,EAAI,aAAa,iBAAiB,QACvD,MAAG,UAAU,OAAQ,SAAAA,EAAI,iBAAiB,iBAAiB,QAC3D,MAAG,UAAU,OAAQ,SAAAA,EAAI,YAAY,iBAAiB,EACvDlV,OAAC,MAAG,UAAU,OAAQ,UAAAkV,EAAI,aAAa,MAAE,EACzCpV,MAAC,MAAG,UAAWiD,EAAG,OAAQmS,EAAI,OAAS,GAAK,QAAQ,EACjD,SAAAA,EAAI,OAAS,EAAIA,EAAI,OAAS,IACjC,IAXO,GAAGA,EAAI,UAAU,KAAKA,EAAI,OAAO,EAY1C,CACD,EAEL,GACF,EACF,CAEJ,CC6GA,SAASu2B,GAAkB,CAAE,UAAA1pC,EAAW,aAAAoJ,GAAuB,CAE7D,KAAM,CAAC8wB,EAAMC,CAAO,EAAIjgC,WAAgC,OAAO,EACzD8I,EAAQC,GAAA,EAGd,OACEhF,OAAC,OAAI,UAAU,oCAEb,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,UACC,UAAW+C,EAAG,kBAAmBk5B,IAAS,SAAW,WAAW,EAChE,QAAS,IAAMC,EAAQ,OAAO,EAE9B,UAAAp8B,MAACnJ,GAAA,CAAM,KAAM,GAAI,EAAE,iBAErBqJ,OAAC,UACC,UAAW+C,EAAG,kBAAmBk5B,IAAS,aAAe,WAAW,EACpE,QAAS,IAAMC,EAAQ,WAAW,EAElC,UAAAp8B,MAAC4rC,GAAA,CAAU,KAAM,GAAI,EAAE,qBACzB,EACF,EAECzP,IAAS,QACNn8B,MAAC6rC,GAAA,CAAU,UAAA5pC,EAAsB,aAAAoJ,CAAA,CAA4B,EAC7DrL,MAAC8rC,GAAA,CAAc,MAAA7mC,CAAA,CAAc,GAEnC,CAEJ,CAIA,SAAS4mC,GAAU,CAAE,UAAA5pC,EAAW,aAAAoJ,GAA2D,QACzF,MAAMpG,EAAQC,GAAA,EACR,CAACsG,EAAQqmB,CAAS,EAAI11B,WAAwB,IAAI,EAClD,CAAC4vC,EAASC,CAAU,EAAI7vC,WAAiC,IAAI,EAC7D,CAAC8vC,EAAYC,CAAa,EAAI/vC,WAAiC,IAAI,EACnE,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACgwC,EAAYC,CAAa,EAAIjwC,WAAS,EAAK,EAC5C,CAACW,EAAOC,CAAQ,EAAIZ,WAAwB,IAAI,EAChD,CAACkwC,EAAYC,CAAa,EAAInwC,WAA4B,IAAI,EAC9D,CAACqrC,EAASC,CAAU,EAAItrC,WAAS,EAAK,EACtC,CAACowC,EAAYC,CAAa,EAAIrwC,WAAS,CAAC,EACxC,CAACswC,EAAiBC,CAAkB,EAAIvwC,WAAS,EAAK,EACtD,CAACwwC,EAAoBC,CAAqB,EAAIzwC,WAA4B,IAAI,EAC9E,CAAC0wC,EAAUC,CAAW,EAAI3wC,WAAS,EAAE,EACrC,CAAC4wC,EAASC,CAAU,EAAI7wC,WAAS,EAAK,EACtC,CAAC8wC,EAAWC,CAAY,EAAI/wC,WAAS,EAAK,EAE1C2B,EAAOH,cAAY,SAAY,CACnCd,EAAW,EAAI,EACfE,EAAS,IAAI,EACb,GAAI,CACF,KAAM,CAACoJ,EAAGzG,GAAGogB,EAAC,EAAI,MAAM,QAAQ,IAAI,CAClCjiB,EAAI,IAAY,iBAAiB,EACjCA,EAAI,IAAqB,kBAAkB,EAC3CA,EAAI,IAAqB,qBAAqB,EAC/C,EACDg0B,EAAU1rB,CAAC,EACX6lC,EAAWtsC,EAAC,EACZwsC,EAAcpsB,EAAC,EACX3Z,EAAE,YAAYqmC,EAAc,CAAC,CACnC,OAASzuC,EAAK,CACZhB,EAAUgB,EAAc,SAAW,6BAA6B,CAClE,SACElB,EAAW,EAAK,CAClB,CACF,EAAG,EAAE,EAELqB,YAAU,IAAM,CAAEJ,EAAA,CAAQ,EAAG,CAACA,CAAI,CAAC,EAEnC,MAAMqvC,EAAgBxvC,cAAY,SAAY,CAC5C,GAAI,CACF,MAAME,EAAI,KAAK,sBAAuB,CAAE,YAAa,KAAK,MAAO,EACjEquC,EAAepsB,GAAMA,GAAI,CAAE,GAAGA,EAAG,YAAa,KAAK,KAAI,CAAO,CAChE,MAAQ,CAAoB,CAC9B,EAAG,EAAE,EAECstB,EAAsBzvC,cAAY,SAAY,CAClD,GAAI,CAACkvC,EAAS,OAAQ,CAAE5nC,EAAM,MAAM,iCAAiC,EAAG,MAAQ,CAChFynC,EAAmB,EAAI,EACvBE,EAAsB,IAAI,EAC1B,GAAI,CACF,MAAMltC,EAAI,MAAM7B,EAAI,KAAiB,gBAAiB,CACpD,OAAQ,iCACR,MAAO,aACP,UAAW,GACZ,EAED,GADA+uC,EAAsBltC,CAAC,EACnBA,EAAE,GAAI,CACR8sC,EAAc,CAAC,EACfvnC,EAAM,QAAQ,oBAAoB,EAClC,GAAI,CACF,MAAMpH,EAAI,KAAK,+BAAgC,CAAE,IAAKgvC,EAAS,OAAQ,QAAS,UAAW,EAC3FQ,GAAA,EACApoC,EAAM,QAAQ,yBAAyB,CACzC,OAASlH,GAAK,CAAEkH,EAAM,MAAM,gBAAiBlH,GAAc,OAAO,EAAE,CAAG,CAClED,EAAA,CACP,MACEmH,EAAM,MAAM,wBAAwBvF,EAAE,SAAWA,EAAE,OAAS,SAAS,EAAE,CAE3E,OAAS3B,EAAK,CAAEkH,EAAM,MAAM,wBAAyBlH,EAAc,OAAO,EAAE,CAAG,SACrE2uC,EAAmB,EAAK,CAAG,CACvC,EAAG,CAACG,EAAU5nC,EAAOnH,CAAI,CAAC,EAEpBwvC,EAAU3vC,cAAY,SAAY,CACtC,GAAI,CAACkvC,EAAS,OAAQ,CAAE5nC,EAAM,MAAM,iCAAiC,EAAG,MAAQ,CAChFioC,EAAa,EAAI,EACjB,GAAI,CACF,MAAMxtC,EAAI,MAAM7B,EAAI,KAClB,+BAAgC,CAAE,IAAKgvC,EAAS,OAAQ,QAAS,UAAU,EAE7E,GAAI,CAACntC,EAAE,GAAI,CAAEuF,EAAM,MAAM,gBAAgBvF,EAAE,SAAWA,EAAE,OAAS,SAAS,EAAE,EAAG,MAAQ,CACvFotC,EAAY,EAAE,EACdO,GAAA,EACApoC,EAAM,QAAQ,wCAAwC,EACjDnH,EAAA,CACP,OAASC,EAAK,CAAEkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CAAG,SAC7DmvC,EAAa,EAAK,CAAG,CACjC,EAAG,CAACL,EAAU5nC,EAAOnH,CAAI,CAAC,EAEpBuvC,GAA0B1vC,cAAY,SAAY,CACtD,GAAI,CAAE,MAAME,EAAI,IAAI,gBAAgB,CAAG,MAAQ,CAAoB,CACrE,EAAG,EAAE,EAECqzB,GAAUvzB,cAAY,SAAY,CACtCyuC,EAAc,EAAI,EAClBrvC,EAAS,IAAI,EACb,GAAI,CACF,MAAMc,EAAI,KAAK,0BAA0B,EACzC,MAAMC,EAAA,EACNmH,EAAM,QAAQ,WAAW,CAC3B,OAASlH,EAAK,CAAEkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CAAG,SAChEquC,EAAc,EAAK,CAAG,CAClC,EAAG,CAACtuC,EAAMmH,CAAK,CAAC,EAEVsoC,EAAW5vC,cAAY,SAAY,OACvC8pC,EAAW,EAAI,EACf6E,EAAc,IAAI,EAClB,GAAI,CACF,MAAM5sC,GAAI,MAAM7B,EAAI,KAAiB,gBAAiB,CACpD,OAAQ,iCACR,MAAO,aACP,UAAW,GACZ,EACDyuC,EAAc5sC,EAAC,EACXA,GAAE,GAAIuF,EAAM,QAAQ,oBAAkBhH,EAAAyB,GAAE,QAAF,YAAAzB,EAAS,eAAgB,GAAG,SAAS,EAC1EgH,EAAM,MAAM,gBAAgBvF,GAAE,SAAWA,GAAE,OAAS,SAAS,EAAE,CACtE,OAAS3B,GAAK,CAAEkH,EAAM,MAAM,wBAAyBlH,GAAc,OAAO,EAAE,CAAG,SACrE0pC,EAAW,EAAK,CAAG,CAC/B,EAAG,CAACxiC,CAAK,CAAC,EAEV,OAAIrI,GAAW,CAAC4O,EACPtL,OAAC,OAAI,UAAU,iBAAiB,UAAAF,MAACuO,GAAA,EAAQ,EAAE,0BAAsB,EAErE/C,EAWc,CAACA,EAAO,aAAeygC,GAAA,YAAAA,EAAY,cAAe,MAASM,EAAa,EAElFvsC,MAACwtC,GAAA,CACN,KAAMjB,EAAY,QAASC,EAC3B,SAAAK,EAAoB,YAAAC,EACpB,QAAAC,EAAkB,WAAAC,EAClB,UAAWP,EAAiB,aAAcE,EAC1C,SAAUS,EACV,OAAQ,SAAY,CAAE,MAAMD,EAAA,EAAiBloC,EAAM,QAAQ,UAAU,CAAG,EACxE,gBAAiBqoC,EAAS,UAAAL,EAAsB,OAAAzhC,CAAA,GAKlDtL,OAAAO,WAAA,CACE,UAAAP,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAACnJ,GAAA,CAAM,KAAM,GAAI,MAAO,CAAE,cAAe,cAAe,YAAa,EAAE,CAAG,EAAE,sBAE9E,EACAqJ,OAAC,KAAE,UAAU,gBAAgB,yEACkC,IAC7DF,MAAC,QAAK,gDAAoC,EAAO,KACnD,GACF,EACAE,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAMwH,EAAa,UAAU,EAAG,MAAM,kCACnF,UAAArL,MAAC5H,GAAA,CAAS,KAAM,GAAI,EAAE,IAAEoT,EAAO,WAAa,OAAOA,EAAO,UAAU,GAAK,WAC3E,EACAtL,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAASqtB,GAAS,SAAUib,EAC/D,UAAAA,EAAansC,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,OAAO,EAAKrjC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAG,YACjF,GACF,GACF,EAEC4rC,GAAW,CAACA,EAAQ,IACnB7rC,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,SACxB,QAAK,UAAA/G,MAAC,UAAO,+BAAmB,EAAS,KAAG+rC,EAAQ,SAAWA,EAAQ,OAAS,iBAAgB,GACnG,GAGDA,GAAA,YAAAA,EAAS,KAAMA,EAAQ,QACtB7rC,OAAAO,WAAA,CACE,UAAAP,OAAC,OAAI,UAAU,oBACb,UAAAF,MAACihB,GAAA,CAAK,MAAM,iBAAiB,MAAO,OAAO8qB,EAAQ,OAAO,MAAM,EAAG,KAAK,4CAA4C,EACpH/rC,MAACihB,GAAA,CAAK,MAAM,eAAe,MAAO8qB,EAAQ,UAAY0B,GAAa1B,EAAQ,SAAS,EAAI,IAAK,KAAK,kCAAkC,EACpI/rC,MAACihB,IAAK,MAAM,QAAQ,MAAO8qB,EAAQ,SAAW,IAAK,KAAK,2CAA2C,EACnG/rC,MAACihB,IAAK,MAAM,UAAU,MAAO8qB,EAAQ,YAAc,IAAK,KAAK,8CAA8C,GAC7G,QACC,OAAI,UAAU,sBACZ,SAAAA,EAAQ,OAAO,IAAKl9B,GAAM7O,MAAC0tC,IAAkC,MAAO7+B,CAAA,EAArBA,EAAE,UAAsB,CAAE,EAC5E,GACF,EAGDrD,EAAO,YACNtL,OAAC0K,EAAA,CAAK,GAAG,eACP,UAAA1K,OAACgL,GAAA,CAAU,UAAAlL,MAACyO,GAAA,CAAK,KAAM,GAAI,EAAE,qBAAiB,SAC7CtD,GAAA,CAAS,gDAA6B,QAAM,UAAAK,EAAO,YAAY,qBAAiB,EAAO,KAAC,EACzFtL,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAS0pC,EAAU,SAAU/F,EAAS,QAAQ,UAAU,KAAK,KAClE,UAAAA,EAAUxnC,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,OAAO,EAAKrjC,MAACyO,GAAA,CAAK,KAAM,GAAI,EAAG,qBACzE,EACAzO,MAAC,QAAK,UAAU,sBAAsB,4CAAgC,GACxE,EACCqsC,GACCnsC,OAAC,OAAI,UAAW+C,EAAG,sBAAuBopC,EAAW,GAAK,KAAO,KAAK,EACnE,UAAAA,EAAW,SAAMvlC,GAAA,CAAa,KAAM,GAAI,EAAK9G,MAAC+G,GAAA,CAAc,KAAM,GAAI,QACtE,OAAI,UAAU,oBACZ,SAAAslC,EAAW,GACVnsC,OAAAO,WAAA,CACE,UAAAP,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,UAAO,kBAAM,EAAS,IAACA,MAAC,QAAM,SAAAqsC,EAAW,MAAM,EAAO,KAAG,IAC1DrsC,MAAC,UAAO,mBAAO,EAAS,IAAEqsC,EAAW,cAAgB,KACvD,EACCA,EAAW,SACVrsC,MAAC,OAAI,UAAU,uBAAuB,SAAAA,MAAC,QAAM,SAAAqsC,EAAW,QAAQ,EAAO,EAExEA,EAAW,OACVnsC,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC,UAAO,kBAAM,EAAS,UAAOA,MAAC,QAAM,SAAAqsC,EAAW,MAAM,cAAgB,IAAI,EAAO,YAAU,IAC3FrsC,MAAC,QAAM,SAAAqsC,EAAW,MAAM,eAAiB,IAAI,EAAO,gBAAc,IAClErsC,MAAC,QAAM,SAAAqsC,EAAW,MAAM,mBAAqB,IAAI,IAChDpuC,GAAAouC,EAAW,MAAM,wBAAjB,YAAApuC,GAAwC,gBAAiB,MACxDiC,OAAAO,WAAA,CAAE,uBAAUT,MAAC,QAAM,SAAAqsC,EAAW,MAAM,sBAAsB,cAAc,GAAO,GAEnF,GAEJ,QAEC,OAAK,SAAAA,EAAW,SAAWA,EAAW,OAAS,gBAAgB,EAEpE,GACF,GAEJ,GAEJ,QA5GG,OAAI,UAAU,iBACb,SAAAnsC,OAAC,OAAI,UAAU,aACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,SACxB,OAAI,UAAA/G,MAAC,UAAO,wCAA4B,EAASA,MAAC,OAAK,SAAAlD,GAAS,gBAAgB,GAAM,GACzF,EACF,CAyGN,CAIA,SAASgvC,GAAc,CAAE,MAAA7mC,GAAiD,CACxE,KAAM,CAAC6jC,EAAO6E,CAAQ,EAAIxxC,WAAoB,KAAK,EAC7C,CAACyxC,EAAYC,CAAa,EAAI1xC,WAAS,EAAE,EACzC,CAAC2xC,EAAUC,CAAW,EAAI5xC,WAAS,EAAE,EACrC,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACsb,EAAOC,CAAQ,EAAIvb,WAAkC,IAAI,EAC1D,CAAC6xC,EAAQC,CAAS,EAAI9xC,WAAyB,EAAE,EACjD,CAACovC,EAAS2C,CAAU,EAAI/xC,WAAS,UAAU,EAC3C,CAACqvC,EAAS2C,CAAU,EAAIhyC,WAAyB,MAAM,EACvD,CAACgwC,EAAYC,CAAa,EAAIjwC,WAAS,EAAK,EAE5C2B,EAAOH,cAAY,MAAO+B,EAAc0uC,EAAiBC,IAAkB,CAC/ExxC,EAAW,EAAI,EACf,GAAI,CACF,MAAMyxC,EAAS,IAAI,gBAAgB,CAAE,MAAO5uC,EAAG,EAC3CA,IAAM,UAAY0uC,GAAUC,IAC9BC,EAAO,IAAI,OAAQ,OAAOF,CAAM,CAAC,EACjCE,EAAO,IAAI,KAAM,OAAOD,CAAI,CAAC,GAE/B,KAAM,CAACzP,EAAG2P,CAAG,EAAI,MAAM,QAAQ,IAAI,CACjC1wC,EAAI,IAAsB,UAAUywC,EAAO,UAAU,EAAE,EACvDzwC,EAAI,IAAkE,wBAAwB,EAC/F,EACD6Z,EAASknB,CAAC,EACVqP,EAAUM,EAAI,OAAO,CACvB,OAASxwC,EAAK,CACZkH,EAAM,MAAM,8BAA+BlH,EAAc,OAAO,EAAE,CACpE,SACElB,EAAW,EAAK,CAClB,CACF,EAAG,CAACoI,CAAK,CAAC,EAEV/G,YAAU,IAAM,CACd,GAAI4qC,IAAU,SAAU,CACtB,MAAMxmB,EAAOsrB,EAAa,IAAI,KAAKA,CAAU,EAAE,UAAY,KAAK,MAAQ,OAClErrB,EAAOurB,EAAa,IAAI,KAAKA,CAAQ,EAAE,UAAc,KAAK,MAC3DhwC,EAAK,SAAUwkB,EAAMC,CAAE,CAC9B,MACOzkB,EAAKgrC,CAAK,CAEnB,EAAG,CAACA,EAAOhrC,CAAI,CAAC,EAEhB,MAAM0wC,EAAa7wC,cAAa+P,GAAgB,CAC1C69B,IAAY79B,EAAKygC,KAAgB36B,IAAM,MAAQ,OAAS,KAAK,GAC1D06B,EAAWxgC,CAAG,EAAGygC,EAAW,MAAM,EAC3C,EAAG,CAAC5C,CAAO,CAAC,EAENkD,EAAel6B,UAAQ,IACtBkD,GAAA,MAAAA,EAAO,SACL,CAAC,GAAGA,EAAM,QAAQ,EAAE,KAAK,CAAC7c,EAAGC,IAAM,CACxC,MAAM6zC,EAAM9zC,EAA8B2wC,CAAO,GAAK,EAChDoD,EAAM9zC,EAA8B0wC,CAAO,GAAK,EAChDqD,EAAM,OAAOF,GAAO,UAAY,OAAOC,GAAO,SAAWD,EAAKC,EAAK,OAAOD,CAAE,EAAE,cAAc,OAAOC,CAAE,CAAC,EAC5G,OAAOnD,IAAY,MAAQoD,EAAM,CAACA,CACpC,CAAC,EAN4B,GAO5B,CAACn3B,GAAA,YAAAA,EAAO,SAAU8zB,EAASC,CAAO,CAAC,EAEhCqD,EAAct6B,UAAQ,IACrBkD,GAAA,MAAAA,EAAO,MACL,CACL,OAAUA,EAAM,MAAM,OAASjE,EAAE,KAAK,MAAM,CAAC,CAAC,EAC9C,SAAUiE,EAAM,MAAM,IAAIjE,GAAKA,EAAE,QAAQ,EACzC,OAAUiE,EAAM,MAAM,IAAIjE,GAAKA,EAAE,WAAW,GAJpB,CAAE,OAAQ,GAAgB,SAAU,GAAgB,OAAQ,EAAC,EAMtF,CAACiE,GAAA,YAAAA,EAAO,KAAK,CAAC,EAEXyZ,EAAUvzB,cAAY,SAAY,CACtCyuC,EAAc,EAAI,EAClB,MAAMtuC,EAAKgrC,IAAU,SAAW,SAAWA,EACzCA,IAAU,UAAY8E,EAAa,IAAI,KAAKA,CAAU,EAAE,UAAY,OACpE9E,IAAU,UAAYgF,EAAa,IAAI,KAAKA,CAAQ,EAAE,UAAc,QACtE1B,EAAc,EAAK,CACrB,EAAG,CAACtuC,EAAMgrC,EAAO8E,EAAYE,CAAQ,CAAC,EAEtC,GAAIlxC,GAAW,CAAC6a,EACd,OAAOvX,OAAC,OAAI,UAAU,iBAAiB,UAAAF,MAACuO,GAAA,EAAQ,EAAE,wBAAoB,EAGxE,MAAM7J,EAAI+S,GAAA,YAAAA,EAAO,OACXq3B,GAASr3B,GAAA,YAAAA,EAAO,SAAU,GAC1Bs3B,GAASt3B,GAAA,YAAAA,EAAO,SAAU,GAEhC,OACEvX,OAAAO,WAAA,CAEE,UAAAP,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC4rC,GAAA,CAAU,KAAM,GAAI,MAAO,CAAE,cAAe,cAAe,YAAa,EAAE,CAAG,EAAE,mBAElF,EACA1rC,OAAC,KAAE,UAAU,gBAAgB,6BACXF,MAAC,QAAK,4CAAgC,EAAO,kDAE/D,GACF,EACAA,MAAC,OAAI,UAAU,sBACb,SAAAE,OAAC2D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAASqtB,EAAS,SAAUib,EAC/D,UAAAA,EAAansC,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,OAAO,EAAKrjC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAG,YACjF,EACF,GACF,EAGAD,OAAC,OAAI,UAAU,mBACX,WAAC,MAAO,KAAM,MAAO,QAAQ,EAAkB,IAAIR,GACnDM,MAAC,UAEC,UAAWiD,EAAG,mBAAoB6lC,IAAUppC,GAAK,WAAW,EAC5D,QAAS,IAAMiuC,EAASjuC,CAAC,EAExB,SAAAA,IAAM,SAAW,SAAWA,EAAE,aAAY,EAJtCA,CAAA,CAMR,EACAopC,IAAU,UACT5oC,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC,SACC,KAAK,OACL,UAAU,mBACV,MAAO4tC,EACP,SAAUxvC,GAAKyvC,EAAczvC,EAAE,OAAO,KAAK,IAE7C4B,MAAC,QAAK,MAAO,CAAE,MAAO,oBAAqB,SAAU,IAAM,cAAE,EAC7DA,MAAC,SACC,KAAK,OACL,UAAU,mBACV,MAAO8tC,EACP,SAAU1vC,GAAK2vC,EAAY3vC,EAAE,OAAO,KAAK,GAC3C,EACF,GAEJ,EAGA8B,OAAC,OAAI,UAAU,gBACb,UAAAF,MAACgvC,GAAA,CACC,MAAM,iBACN,OAAOtqC,GAAA,YAAAA,EAAG,SAAS,mBAAoB,IACvC,IAAKA,EAAI,GAAGA,EAAE,MAAM,UAAY,OAChC,KAAMA,GAAKA,EAAE,OAASA,EAAE,SAAW,GAAM,OAAS,SAEpD1E,MAACgvC,GAAA,CACC,MAAM,eACN,MAAOtqC,EAAKA,EAAE,aAAe,IAAO,GAAG,KAAK,MAAMA,EAAE,YAAc,GAAI,CAAC,IAAM,OAAOA,EAAE,WAAW,EAAK,IACtG,IAAKA,EAAI,GAAGA,EAAE,aAAa,gBAAgB,aAAaA,EAAE,iBAAiB,gBAAgB,cAAgB,SAE7G1E,MAACgvC,GAAA,CACC,MAAM,SACN,MAAO,QAAOtqC,GAAA,YAAAA,EAAG,SAAU,GAAG,EAC9B,IAAKoqC,EAAO,OAAS,EAAI,GAAGA,EAAO,CAAC,EAAE,IAAI,KAAKA,EAAO,CAAC,EAAE,KAAK,GAAK,OACnE,KAAMpqC,GAAKA,EAAE,OAAS,EAAI,MAAQ,SAEpC1E,MAACgvC,GAAA,CACC,MAAM,cACN,OAAOtqC,GAAA,YAAAA,EAAG,eAAgB,KAAO,GAAGA,EAAE,YAAY,KAAO,IACzD,KAAKA,GAAA,YAAAA,EAAG,eAAgB,KAAO,OAAOA,EAAE,YAAY,KAAO,SAE7D1E,MAACgvC,GAAA,CACC,MAAM,YACN,OAAOtqC,GAAA,YAAAA,EAAG,eAAgB,MAAQA,EAAE,aAAe,EAAI,IAAIA,EAAE,aAAa,QAAQ,CAAC,CAAC,GAAK,IACzF,IAAI,kBACJ,KAAM,QACR,EACF,EAGAxE,OAAC0K,EAAA,CAAK,UAAU,mBACd,UAAA5K,MAAC,OAAI,UAAU,mBACb,SAAAA,MAACqpC,IAAW,OAAQwF,EAAa,OAAQ,IAAK,EAChD,EACA3uC,OAAC,OAAI,UAAU,eACb,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,OAAI,UAAU,mBAAmB,MAAO,CAAE,WAAY,iBAAmB,EAC1EA,MAAC,QAAK,0BAAc,GACtB,EACAE,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,OAAI,UAAU,oBAAoB,MAAO,CAAE,WAAY,2BAA6B,EACrFA,MAAC,QAAK,yBAAa,GACrB,GACF,GACF,SAGC4K,EAAA,CACC,UAAA5K,MAACkL,IAAU,+BAAmB,EAC9BlL,MAAC0rC,GAAA,CACC,KAAM+C,EACN,QAAAlD,EACA,QAAAC,EACA,OAAQgD,CAAA,EACV,EACF,EAGCO,EAAO,OAAS,GACf7uC,OAAC0K,EAAA,CACC,UAAA5K,MAACkL,IAAU,oBAAQ,QAClB,OAAI,UAAU,gBACZ,SAAA6jC,EAAO,IAAIj0C,GACVoF,OAAC,QAEC,UAAW+C,EAAG,kBAAmBnI,EAAE,SAAW,YAAc,WAAW,EAEvE,UAAAkF,MAAC,QAAK,UAAU,gBAAgB,EAC/BlF,EAAE,UACFA,EAAE,SAAW,YAAc,YAC3B,MACAA,EAAE,SAAS,SAPPA,EAAE,UASV,EACH,GACF,EAIDkzC,EAAO,OAAS,GACf9tC,OAAC0K,EAAA,CACC,UAAA5K,MAACkL,IAAU,2BAAe,QACzB,OAAI,UAAU,oBACZ,SAAA8iC,EAAO,IAAI,CAACtuC,EAAGtE,IACd8E,OAAC,OAAgC,UAAW+C,EAAG,oBAAqBvD,EAAE,OAAS,QAAQ,EACrF,UAAAM,MAAC,QAAK,UAAU,oBACb,aAAI,KAAKN,EAAE,EAAE,EAAE,oBAAmB,CACrC,EACAM,MAAC,QAAK,UAAU,qBACd,eAAC,QAAM,SAAAN,EAAE,QAAQ,EACnB,EACAQ,OAAC,QAAK,UAAU,sBACb,UAAAR,EAAE,YAAY,iBAAiB,QAClC,EACAQ,OAAC,QAAK,UAAU,uBACb,UAAAR,EAAE,UAAU,MACf,EACAM,MAAC,QAAK,UAAU,wBAAyB,WAAE,SAAS,IAb5C,GAAGN,EAAE,SAAS,IAAItE,CAAC,EAc7B,CACD,EACH,GACF,GAEJ,CAEJ,CAIA,SAAS4zC,GAAQ,CAAE,MAAA9tB,EAAO,MAAAvlB,EAAO,IAAAumC,EAAK,KAAA5jB,GAAsF,CAC1H,OACEpe,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC,OAAI,UAAU,kBAAmB,SAAAkhB,EAAM,EACxClhB,MAAC,OAAI,UAAWiD,EAAG,kBAAmBqb,GAAQ,MAAMA,CAAI,EAAE,EAAI,SAAA3iB,CAAA,CAAM,EACnEumC,GAAOliC,MAAC,OAAI,UAAU,gBAAiB,SAAAkiC,CAAA,CAAI,GAC9C,CAEJ,CAIA,SAASjhB,GAAK,CAAE,MAAAC,EAAO,MAAAvlB,EAAO,KAAAylB,GAAyD,CACrF,OACElhB,OAAC,OAAI,UAAU,OACb,UAAAF,MAAC,OAAI,UAAU,aAAc,SAAAkhB,EAAM,EACnClhB,MAAC,OAAI,UAAU,aAAc,SAAArE,EAAM,EAClCylB,GAAQphB,MAAC,OAAI,UAAU,YAAa,SAAAohB,CAAA,CAAK,GAC5C,CAEJ,CAEA,SAASssB,GAAe,CAAE,MAAA92B,GAAkC,CAC1D,MAAMq4B,EAAUC,GAAMt4B,EAAM,oCAAsC,EAAG,EAAG,GAAG,EACrEu4B,EAAUD,GAAMt4B,EAAM,kCAAoC,EAAG,EAAG,GAAG,EACnEw4B,EAAeF,GAAM,IAAMD,EAAS,EAAG,GAAG,EAC1CI,EAAeH,GAAM,IAAMC,EAAS,EAAG,GAAG,EAChD,OACEjvC,OAAC0K,GAAK,GAAI,iBAAiBgM,EAAM,UAAU,GAAI,UAAU,qBACvD,UAAA1W,OAAC,OAAI,UAAU,qBACb,UAAAF,MAAC,OAAI,UAAU,qBAAsB,SAAA4W,EAAM,WAAW,EACtD1W,OAAC,OAAI,UAAW+C,EAAG,uBAAwBgsC,EAAU,IAAME,EAAU,GAAK,UAAY,OAAO,EAC1F,UAAAv4B,EAAM,0BAA4B,EAAI,SAAW,OAAO,KAAG,IAC3DA,EAAM,wBAA0B,EAAI,cAAgB,aACvD,GACF,EACA1W,OAAC,OAAI,UAAU,qBACb,UAAAF,MAACsvC,GAAA,CACC,KAAMtvC,MAAC2B,GAAA,CAAS,KAAM,GAAI,EAAI,MAAM,iBACpC,aAAcstC,EAAS,YAAaG,EACpC,KAAMx4B,EAAM,8BAAgC,EAAG,MAAOA,EAAM,8BAAgC,EAC5F,QAASA,EAAM,qBAAsB,SAAUA,EAAM,aAEvD5W,MAACsvC,GAAA,CACC,KAAMtvC,MAAC5J,GAAA,CAAS,KAAM,GAAI,EAAI,MAAM,SACpC,aAAc+4C,EAAS,YAAaE,EACpC,KAAMz4B,EAAM,4BAA8B,EAAG,MAAOA,EAAM,4BAA8B,EACxF,QAASA,EAAM,mBAAoB,SAAUA,EAAM,kBACrD,EACF,GACF,CAEJ,CAEA,SAAS04B,GAAS,CAAE,KAAArjC,EAAM,MAAAiV,EAAO,aAAAquB,EAAc,YAAAC,EAAa,KAAAC,EAAM,MAAAC,EAAO,QAAAC,EAAS,SAAAC,GAG/E,CACD,MAAMtxB,EAAOixB,GAAgB,GAAK,OAASA,GAAgB,GAAK,OAAS,MACzE,OACErvC,OAAC,OAAI,UAAW,wBAAwBoe,CAAI,GAC1C,UAAApe,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,QAAK,UAAU,sBAAuB,UAAA+L,EAAK,IAAEiV,CAAA,EAAM,EACpDhhB,OAAC,QAAK,UAAU,0BAA2B,UAAAqvC,EAAa,eAAW,GACrE,QACC,OAAI,UAAU,cACb,SAAAvvC,MAAC,OAAI,UAAU,mBAAmB,MAAO,CAAE,MAAO,GAAGwvC,CAAW,KAAO,aAAY,GAAGA,CAAW,aAAc,EACjH,EACAtvC,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,QAAK,UAAAF,MAAC,UAAQ,SAAAyvC,CAAA,CAAK,EAAS,MAAIC,GAAS,IAAI,aAAS,EACvD1vC,MAAC,QAAK,MAAO4vC,EAAW,WAAU,aAAaD,CAAO,GAAK,IAAI,GACjE,GACF,CAEJ,CAEA,SAAST,GAAMtnC,EAAWioC,EAAYC,EAAY,CAChD,OAAO,KAAK,IAAID,EAAI,KAAK,IAAIC,EAAIloC,CAAC,CAAC,CACrC,CAEA,SAAS6lC,GAAax9B,EAAoB,CACxC,MAAMgD,EAAK,KAAK,MAAQhD,EACxB,OAAIgD,EAAK,IAAc,WACnBA,EAAK,IAAe,GAAG,KAAK,MAAMA,EAAK,GAAI,CAAC,QAC5CA,EAAK,KAAkB,GAAG,KAAK,MAAMA,EAAK,GAAM,CAAC,QAC9C,GAAG,KAAK,MAAMA,EAAK,IAAS,CAAC,OACtC,CAaA,SAASu6B,GAAiB,CAAE,KAAA3d,EAAM,QAAAkgB,EAAS,SAAAlD,EAAU,YAAAC,EAAa,QAAAC,EAAS,WAAAC,EAAY,UAAAgD,EAAW,aAAAC,EAAc,SAAAC,EAAU,OAAAC,EAAQ,gBAAAC,EAAiB,UAAAnD,EAAW,OAAAzhC,GAA2B,CACvL,OACEtL,OAAC,OAAI,UAAU,yCACb,UAAAA,OAAC,UAAO,UAAU,cAChB,UAAAA,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,MAAG,UAAU,aACZ,UAAAF,MAAC4B,GAAA,CAAS,KAAM,GAAI,MAAO,CAAE,cAAe,cAAe,YAAa,EAAE,CAAG,EAAE,sCAEjF,EACA5B,MAAC,KAAE,UAAU,gBAAgB,2EAA+D,GAC9F,EACAA,MAAC,OAAI,UAAU,sBACb,SAAAE,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASssC,EAAQ,UAAAnwC,MAACuG,GAAA,CAAE,KAAM,GAAI,EAAE,iBAAa,EACjF,GACF,EAEAvG,MAAC,OAAI,UAAU,yBACX,UAAC,UAAW,YAAa,eAAgB,MAAM,EAAG,IAAI,CAACkhB,EAAO9lB,IAC9D8E,OAAC,OAAgB,UAAW+C,EAAG,sBAAuB7H,IAAMy0B,GAAQ,aAAcz0B,EAAIy0B,GAAQ,UAAWz0B,EAAIy0B,GAAQ,SAAS,EAC5H,UAAA7vB,MAAC,OAAI,UAAU,6BAA8B,SAAA5E,EAAIy0B,EAAO7vB,MAACqwC,GAAA,CAAY,KAAM,GAAI,EAAKj1C,EAAI,EAAE,EAC1F4E,MAAC,OAAI,UAAU,4BAA6B,SAAAkhB,CAAA,CAAM,IAF1CA,CAGV,CACD,EACH,EAEAhhB,OAAC0K,EAAA,CAAK,GAAG,sBACN,UAAAilB,IAAS,GACR3vB,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,MAAG,UAAU,uBAAuB,mBAAO,EAC5CE,OAAC,KAAE,UAAU,uBAAuB,uGAEzBF,MAAC,UAAO,0BAAc,EAAS,QAAKA,MAAC,UAAO,kBAAM,EAAS,aACtE,EACAE,OAAC,MAAG,UAAU,sBACZ,UAAAA,OAAC,MAAG,uBAAUF,MAAC,QAAK,6CAAiC,EAAO,KAAC,EAC7DA,MAAC,MAAG,+CAAmC,EACvCA,MAAC,MAAG,iCAAqB,GAC3B,EACAA,MAAC,OAAI,UAAU,yBACb,gBAAC6D,EAAA,CAAO,QAAS,IAAMksC,EAAQ,CAAC,EAAG,QAAQ,UAAU,KAAK,KAAK,+BAAa,QAAK,MAAO,CAAE,WAAY,GAAK,aAAC,GAAO,EACrH,GACF,EAGDlgB,IAAS,GACR3vB,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,MAAG,UAAU,uBAAuB,qCAAyB,EAC9DA,MAAC,KAAE,UAAU,uBAAuB,qEAAyD,EAC7FE,OAAC,MAAG,UAAU,sBACZ,UAAAA,OAAC,MAAG,kBAAKA,OAAC,KAAE,KAAK,6DAA6D,OAAO,SAAS,IAAI,aAAa,UAAU,sBAAsB,UAAAF,MAAC6L,GAAA,CAAa,KAAM,GAAI,EAAE,wBAAoB,GAAI,SAChM,MAAG,mBAAM7L,MAAC,UAAO,iCAAqB,EAAS,KAAC,EACjDA,MAAC,MAAG,wCAA4B,GAClC,EACAE,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAMksC,EAAQ,CAAC,EAAG,kBAAM,EACvE7vC,OAAC2D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAAS,IAAMksC,EAAQ,CAAC,EAAG,iCAAe,QAAK,MAAO,CAAE,WAAY,GAAK,aAAC,GAAO,GACvH,GACF,EAGDlgB,IAAS,GACR3vB,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,MAAG,UAAU,uBAAuB,wBAAgB,EACrDA,MAAC,KAAE,UAAU,uBAAuB,mFAAuE,QAC1G,OAAI,UAAU,kBACb,SAAAE,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC5H,GAAA,CAAS,KAAM,GAAI,UAAU,mBAAmB,EACjD4H,MAAC,SAAM,KAAM+sC,EAAU,OAAS,WAAY,MAAOF,EAAU,SAAUzuC,GAAK0uC,EAAY1uC,EAAE,OAAO,KAAK,EACpG,YAAY,YAAY,WAAY,GAAO,aAAa,MAAM,UAAU,oBAAoB,UAAS,KACvG4B,MAAC,UAAO,KAAK,SAAS,QAAS,IAAMgtC,EAAWhuC,GAAK,CAACA,CAAC,EAAG,UAAU,qBAAqB,aAAY+tC,EAAU,WAAa,WACzH,SAAAA,EAAU/sC,MAAC7I,GAAA,CAAO,KAAM,GAAI,EAAK6I,MAAC5I,GAAA,CAAI,KAAM,GAAI,EACnD,GACF,EACF,EACC64C,GAAgB,CAACA,EAAa,IAC7B/vC,OAAC,OAAI,UAAU,uBAAuB,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,SAAG,QAAK,UAAA/G,MAAC,UAAO,gCAAoB,EAAS,IAAEiwC,EAAa,SAAWA,EAAa,OAAM,GAAO,EAElK/vC,OAAC,OAAI,UAAU,yBACb,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,IAAMksC,EAAQ,CAAC,EAAG,kBAAM,EACvE7vC,OAAC2D,EAAA,CAAO,QAAQ,UAAU,KAAK,KAAK,QAASqsC,EAAU,SAAUF,GAAa,CAACnD,EAAS,OACrF,UAAAmD,EAAYhwC,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,OAAO,EAAKrjC,MAACtG,GAAA,CAAY,KAAM,GAAI,EAC5Es2C,EAAY,WAAa,uBAC5B,GACF,EACA9vC,OAAC,KAAE,UAAU,mDAAmD,uCACpCF,MAAC,KAAE,KAAK,IAAI,QAAS5B,GAAK,CAAEA,EAAE,iBAAkBgyC,EAAA,CAAmB,EAAG,UAAU,sBAAsB,gCAAoB,GACtJ,GACF,EAGDvgB,IAAS,GACR3vB,OAAC,OAAI,UAAU,sBACb,UAAAA,OAAC,MAAG,UAAU,uBAAuB,UAAAF,MAACqwC,GAAA,CAAY,KAAM,GAAI,MAAO,CAAE,cAAe,cAAe,YAAa,EAAE,CAAG,EAAE,WAAO,EAC9HrwC,MAAC,KAAE,UAAU,uBAAuB,iFAAqE,QACxG,OAAI,UAAU,yBACb,SAAAA,MAAC6D,GAAO,QAAQ,UAAU,KAAK,KAAK,QAAS,IAAM,OAAO,SAAS,SAAU,6BAAiB,EAChG,GACF,EAGF3D,OAAC,OAAI,UAAU,wBACb,UAAAF,MAACtG,GAAA,CAAY,KAAM,GAAI,SACtB,QAAK,4BAAesG,MAAC,QAAK,6CAAiC,EAAO,oBAAgB,GACrF,GACF,GACF,CAEJ,CACO,MAAMswC,GAAe1/B,GAAM,KAAK+6B,EAAiB,ECt5BlD4E,GAAwD,CAC5D,QAAS,OACT,QAAS,SACT,KAAM,UACN,OAAQ,QACR,OAAQ,UACR,UAAW,SACb,EAEMC,GAAwC,CAC5C,QAAS,UACT,QAAS,UACT,KAAM,OACN,OAAQ,SACR,OAAQ,SACR,UAAW,WACb,EAEO,SAASC,GAAc,CAAE,OAAAjlC,EAAQ,IAAAyP,GAA0C,CAChF,MAAM5L,EAAOkhC,GAAY/kC,CAAM,GAAK,UAC9B0V,EAAQsvB,GAAchlC,CAAM,GAAKA,EACvC,OACExL,MAACgb,GAAA,CAAY,KAAA3L,EAAY,IAAA4L,EACtB,SAAAiG,EACH,CAEJ,CCJO,SAASwvB,GAAkB,CAAE,WAAAC,EAAY,aAAAC,EAAc,UAAAC,EAAW,QAAA9rC,GAAmC,CAC1G,cACG,OACC,UAAA7E,OAAC,KAAE,MAAO,CAAE,aAAc,GAAI,WAAY,KAAO,sBACtCF,MAAC,QAAM,SAAA2wC,CAAA,CAAW,EAC1BC,EAAe1wC,OAAAO,WAAA,CAAE,eAAGmwC,EAAa,KAAC,EAAM,KAAK,+CAEhD,EACA1wC,OAAC,OAAI,MAAO,CAAE,QAAS,OAAQ,IAAK,EAAG,eAAgB,YACrD,UAAAF,MAAC6D,EAAA,CAAO,QAAQ,QAAQ,QAASkB,EAAS,kBAAM,EAChD/E,MAAC6D,EAAA,CACC,QAAQ,SACR,QAAS,SAAY,CACnB,MAAMgtC,EAAA,EACN9rC,EAAA,CACF,EACD,iBAED,EACF,GACF,CAEJ,CAMO,SAAS+rC,GACdttC,EACAyB,EACA0rC,EACAC,EACAG,EACA,CACAvtC,EAAM,KAAK,CACT,MAAO,iBACP,MAAO,IACP,SACExD,MAAC0wC,GAAA,CACC,WAAAC,EACA,aAAAC,EACA,UAAW,SAAY,CACrB,GAAI,CAEF,MAAMj2C,EAAO,MADH,MAAM,MAAM,mBAAmB,mBAAmBg2C,CAAU,CAAC,GAAI,CAAE,OAAQ,SAAU,GAC1E,OACjBh2C,EAAK,IACPsK,EAAM,QAAQ,YAAY0rC,CAAU,UAAU,EAC9CI,GAAA,MAAAA,KAEA9rC,EAAM,MAAM,gBAAgBtK,EAAK,OAAS,eAAe,EAAE,CAE/D,OAASoD,EAAK,CACZkH,EAAM,MAAM,gBAAiBlH,EAAc,OAAO,EAAE,CACtD,CACF,EACA,QAAS,IAAMyF,EAAM,OAAM,EAC7B,CAEH,CACH,CCpEO,SAASwtC,GAAe,CAAE,SAAAC,GAAiC,CAChE,MAAMhsC,EAAQC,GAAA,EACR,CAACgsC,EAASC,CAAU,EAAIh1C,WAAS,EAAK,EAEtCi1C,EAAcH,EAAS,YACvBI,EAAgBD,EAAc,kBAAkBA,CAAW,GAAK,KAEhEE,EAAc,SAAY,CAC9B,GAAKD,EACL,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,CAAa,EACjDpsC,EAAM,QAAQ,uBAAuB,CACvC,MAAQ,CACNA,EAAM,MAAM,6BAA6B,CAC3C,CACF,EAEMssC,EAAe,SAAY,CAC/B,GAAI,GAACN,EAAS,YAAc,CAACG,GAC7B,CAAAD,EAAW,EAAI,EACf,GAAI,CACF,MAAMj2C,EAAS,MAAM2C,EAAI,KACvB,eAAe,mBAAmBozC,EAAS,UAAU,CAAC,iBACtD,CAAE,SAAU,SAAS,EAEvB,GAAI/1C,EAAO,GACT+J,EAAM,QAAQ,mBAAmB,UAEjCA,EAAM,MAAM/J,EAAO,OAAS,yBAAyB,EAEjDm2C,EACF,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,CAAa,EACjDpsC,EAAM,QAAQ,6BAA6B,CAC7C,MAAQ,CAAa,CAG3B,OAASlH,EAAK,CAGZ,GAFAkH,EAAM,MAAM,WAAYlH,EAAc,OAAO,EAAE,EAE3CszC,EACF,GAAI,CACF,MAAM,UAAU,UAAU,UAAUA,CAAa,EACjDpsC,EAAM,QAAQ,6BAA6B,CAC7C,MAAQ,CAAa,CAEzB,SACEksC,EAAW,EAAK,CAClB,EACF,EAGA,OAAKC,EAgBHlxC,OAAC0K,EAAA,CAAK,QAAQ,WAAW,UAAU,eACjC,UAAA1K,OAAC,OAAI,UAAU,sBACb,UAAAF,MAACsY,GAAA,CAAS,KAAM,GAAI,EACpBtY,MAAC,QAAK,wBAAY,EACjBixC,EAAS,aAAe,GACvBjxC,MAAC,QAAK,UAAU,sBAAsB,gBAAI,EAE1CA,MAAC,QAAK,UAAU,sBAAsB,oBAAQ,GAElD,EAEAA,MAAC,QAAK,UAAU,4BAA6B,SAAAoxC,EAAY,EAEzDpxC,MAAC,KAAE,UAAU,qBAAqB,iGAGlC,EAEAE,OAAC,OAAI,UAAU,uBACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASytC,EAAa,MAAM,sBAC5D,UAAAtxC,MAACy4B,GAAA,CAAK,KAAM,GAAI,EAAE,SACpB,EACAv4B,OAAC2D,EAAA,CACC,QAAQ,UACR,KAAK,KACL,QAAS0tC,EACT,QAASL,EACT,MAAM,0BAEN,UAAAlxC,MAACsY,GAAA,CAAS,KAAM,GAAI,EAAE,mBACxB,EACF,GACF,EA9CEpY,OAAC0K,EAAA,CAAK,QAAQ,WAAW,UAAU,iCACjC,UAAA1K,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,EACzB/G,MAAC,QAAK,2BAAe,GACvB,EACAA,MAAC,KAAE,UAAU,qBAAqB,mIAGlC,GACF,CAuCN,CC7EA,MAAMwxC,GAAmB,IACnBC,GAAoB,IACpBC,GAAkB,IAExB,SAAS7wC,GAAShG,EAAwB,CACxC,OAAOA,EAAE,SAAW,WAAaA,EAAE,SAAW,SAChD,CAEA,SAAS82C,GAAe1+B,EAAoB,CAC1C,GAAI,CAAC,OAAO,SAASA,CAAE,GAAKA,EAAK,EAAG,MAAO,IAC3C,MAAMy8B,EAAQ,KAAK,MAAMz8B,EAAK,GAAI,EAC5BzF,EAAI,KAAK,MAAMkiC,EAAQ,IAAI,EAC3B7gC,EAAI,KAAK,MAAO6gC,EAAQ,KAAQ,EAAE,EAClCvpC,EAAIupC,EAAQ,GAClB,OAAIliC,EAAI,EAAU,GAAGA,CAAC,KAAKqB,CAAC,KAAK1I,CAAC,IAC9B0I,EAAI,EAAU,GAAGA,CAAC,KAAK1I,CAAC,IACrB,GAAGA,CAAC,GACb,CAEO,SAASyrC,GAAiBxJ,EAAe,CAC9C,MAAMnjC,EAAQC,GAAA,EACR1B,EAAQC,GAAA,EACR,CAACouC,EAAWC,CAAY,EAAI31C,WAAuB,EAAE,EACrD,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACW,EAAOC,CAAQ,EAAIZ,WAAwB,IAAI,EAChD,EAAG6sB,CAAO,EAAI7sB,WAAS,CAAC,EAExB2B,EAAOH,cAAY,SAAY,CACnC,GAAI,CACF,MAAMyM,EAAM,MAAMvM,EAAI,IAA4B,aAAa,EAC/Di0C,EAAa,MAAM,QAAQ1nC,GAAA,YAAAA,EAAK,SAAS,EAAIA,EAAI,UAAY,EAAE,EAC/DrN,EAAS,IAAI,CACf,OAASgB,EAAK,CACZhB,GAAUgB,GAAA,YAAAA,EAAe,UAAW,mCAAmC,CACzE,SACElB,EAAW,EAAK,CAClB,CACF,EAAG,EAAE,EAGLqB,YAAU,IAAM,CACdJ,EAAA,EACA,MAAMmK,EAAK,YAAYnK,EAAM0zC,EAAgB,EAC7C,MAAO,IAAM,cAAcvpC,CAAE,CAC/B,EAAG,CAACnK,CAAI,CAAC,EAGTI,YAAU,IAAM,CACd,MAAM+J,EAAK,YAAY,IAAM+gB,EAAStkB,IAAOA,EAAI,GAAK,GAAS,EAAG,GAAI,EACtE,MAAO,IAAM,cAAcuD,CAAE,CAC/B,EAAG,EAAE,EAML/J,YAAU,IAAM,CACd,MAAMg3B,EAAK,IAAIC,GACT4c,EAAM7c,EAAG,GAAIl3B,GAAQ,CACzB,MAAM0G,EAAK1G,EAA0B,MACjC0G,IAAM,qBAAuBA,IAAM,uBACrC5G,EAAA,CAEJ,CAAC,EACD,MAAO,IAAM,CACXi0C,EAAA,EACA7c,EAAG,OACL,CACF,EAAG,CAACp3B,CAAI,CAAC,EAET,MAAMsF,EAASyuC,EAAU,OAAOhxC,EAAQ,EAIlCmxC,EAAgBn3C,GAAkB,CACtCo3C,GAAgBzuC,EAAO3I,CAAC,CAC1B,EAEMq3C,EAAa,MAAOr3C,GAAkB,CAC1C,GAAI,CACF,MAAM6oB,EAAO,MAAM7lB,EAAI,IACrB,eAAe,mBAAmBhD,EAAE,UAAU,CAAC,SAEjDs3C,GAAc3uC,EAAOkgB,CAAI,CAC3B,OAAS3lB,EAAK,CACZkH,EAAM,MAAM,qBAAsBlH,EAAc,OAAO,EAAE,CAC3D,CACF,EAEMq0C,EAAUv3C,GAAkB,CAChCi2C,GAAsBttC,EAAOyB,EAAOpK,EAAE,WAAYA,EAAE,OAASA,EAAE,OAAQ,IAAM,CAE3Ei3C,EAAcnqC,GAAQA,EAAI,OAAQpI,GAAMA,EAAE,aAAe1E,EAAE,UAAU,CAAC,CACxE,CAAC,CACH,EAIA,OAAI+B,QAEC,OAAI,UAAU,iBACb,SAAAsD,OAAC,OAAI,UAAU,oBACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,QAAK,sCAA0B,GAClC,EACF,EAIAlD,EAEAkD,MAAC,OAAI,UAAU,iBACb,SAAAA,MAACgM,GAAA,CACC,KAAMhM,MAACoxB,GAAA,CAAa,KAAM,GAAI,EAC9B,MAAM,kCACN,QAASt0B,EACT,OACEoD,OAAC2D,EAAA,CAAO,QAAQ,UAAU,QAAS/F,EACjC,UAAAkC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,UACzB,IAGN,EAKFD,OAAC,OAAI,UAAU,iBACb,UAAAA,OAAC,OAAI,UAAU,mBACb,UAAAA,OAAC,OAAI,UAAU,wBACb,UAAAF,MAAC,MAAG,UAAU,kBAAkB,oCAAwB,EACxDE,OAAC,KAAE,UAAU,2BACV,UAAAkD,EAAO,OAAO,aAAWyuC,EAAU,OAAO,mBAC7C,GACF,EACA3xC,OAAC2D,GAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS/F,EAAM,MAAM,cACrD,UAAAkC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,GACF,EAECiD,EAAO,SAAW,EACjBpD,MAACgM,GAAA,CACC,KAAMhM,MAACoxB,GAAA,CAAa,KAAM,GAAI,EAC9B,MAAM,8BACN,QAAQ,gFAGT,OAAI,UAAU,iBACZ,SAAAhuB,EAAO,IAAKvI,GACXmF,MAACqyC,GAAA,CAEC,KAAMx3C,EACN,aAAc,IAAMm3C,EAAan3C,CAAC,EAClC,WAAY,IAAMq3C,EAAWr3C,CAAC,EAC9B,OAAQ,IAAMu3C,EAAOv3C,CAAC,GAJjBA,EAAE,WAMV,EACH,GAEJ,CAEJ,CAIA,SAASw3C,GAAoB,CAC3B,KAAAC,EACA,aAAAC,EACA,WAAAL,EACA,OAAAE,CACF,EAKG,CACD,MAAMI,EAAY,OAAOF,EAAK,WAAc,SAAWA,EAAK,UAAY,EAClEG,EAAeD,EAAYzmC,GAAWymC,CAAS,EAAI,IACnDE,EAAaF,EAAY,KAAK,MAAQA,EAAY,EAClDl1B,EAASiiB,GAAS+S,EAAK,OAAQZ,EAAe,EAEpD,OACExxC,OAAC0K,EAAA,CAAK,UAAU,iBAAiB,QAAQ,WACvC,UAAA1K,OAAC,OAAI,UAAU,qBACb,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAU,OAAQ,SAAAsyC,EAAK,WAAW,QACvC7B,GAAA,CAAc,OAAQ6B,EAAK,QAAU,UAAW,IAAG,GAAC,GACvD,EACApyC,OAAC,OAAI,UAAU,uBACb,UAAAF,MAAC,QAAK,UAAU,6BAA6B,iBAAK,QACjD,QAAK,UAAU,4BAA6B,SAAAsyC,EAAK,OAAS,UAAU,GACvE,GACF,EAECh1B,GAAUtd,MAAC,OAAI,UAAU,mBAAoB,SAAAsd,EAAO,EAEpDg1B,EAAK,aACJpyC,OAAC,OAAI,UAAU,iBACb,UAAAF,MAAC,QAAK,UAAU,uBAAuB,iBAAK,EAC5CA,MAAC,QAAK,UAAU,uBAAwB,WAAK,YAAY,GAC3D,EAGD,OAAOsyC,EAAK,UAAa,iBACvB,OAAI,UAAU,eAAe,aAAW,WACvC,UAAAtyC,MAAC,OACC,UAAU,gBACV,MAAO,CAAE,MAAO,GAAG,KAAK,IAAI,EAAG,KAAK,IAAI,IAAKsyC,EAAK,QAAQ,CAAC,CAAC,IAAI,GAElEpyC,OAAC,QAAK,UAAU,iBAAkB,eAAK,MAAMoyC,EAAK,QAAQ,EAAE,KAAC,GAC/D,EAGFpyC,OAAC,OAAI,UAAU,iBACb,UAAAA,OAAC,QAAK,MAAOuyC,EACX,UAAAzyC,MAAC,UAAO,oBAAQ,EAAS,IAAEyyC,CAAA,EAC7B,SACC,QACC,UAAAzyC,MAAC,UAAO,qBAAS,EAAS,IAAE2xC,GAAee,CAAU,GACvD,SACC,QACC,UAAA1yC,MAAC,UAAO,uBAAW,EAAS,IAAEsyC,EAAK,eAAiB,GACtD,EACCA,EAAK,aACJpyC,OAAC,QAAK,UAAW+C,EAAGqvC,EAAK,YAAc,0BAA0B,EAC/D,UAAAtyC,MAAC,UAAO,iBAAK,EAAS,IAACA,MAAC,QAAK,UAAU,OAAQ,WAAK,YAAY,EAC/DsyC,EAAK,WAAa,UAAY,IACjC,GAEJ,EAEApyC,OAAC,OAAI,UAAU,oBACb,UAAAA,OAAC2D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAAS0uC,EAC7C,UAAAvyC,MAAC5I,GAAA,CAAI,KAAM,GAAI,EAAE,gBACnB,SACCyM,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASquC,EACzC,UAAAlyC,MAACsY,GAAA,CAAS,KAAM,GAAI,EAAE,iBACxB,SACCzU,EAAA,CAAO,QAAQ,SAAS,KAAK,KAAK,QAASuuC,EAC1C,UAAApyC,MAACiP,GAAA,CAAO,KAAM,GAAI,EAAE,SACtB,GACF,EAEAjP,MAACgxC,GAAA,CAAe,SAAUsB,CAAA,CAAM,GAClC,CAEJ,CAIA,SAASL,GACPzuC,EACA8uC,EACA,CACA9uC,EAAM,KAAK,CACT,MAAO,YAAY8uC,EAAK,OAASA,EAAK,UAAU,GAChD,MAAO,IACP,SAAUtyC,MAAC2yC,GAAA,CAAgB,WAAYL,EAAK,WAAY,EACzD,CACH,CAEA,SAASK,GAAgB,CAAE,WAAAhC,GAAsC,CAC/D,MAAM1rC,EAAQC,GAAA,EACR,CAAC0tC,EAAQC,CAAS,EAAI12C,WAAiB,EAAE,EACzC,CAACS,EAASC,CAAU,EAAIV,WAAS,EAAI,EACrC,CAACW,EAAOC,CAAQ,EAAIZ,WAAwB,IAAI,EAChD,CAAC22C,EAAWC,CAAY,EAAI52C,WAAS,EAAI,EACzC62C,EAAYv1C,SAA8B,IAAI,EAC9Cw1C,EAAgBx1C,SAAO,EAAI,EAE3BK,EAAOH,cAAY,SAAY,CACnC,GAAI,CACF,MAAM+B,EAAI,MAAM7B,EAAI,IAClB,eAAe,mBAAmB8yC,CAAU,CAAC,qBAE/CkC,GAAUnzC,GAAA,YAAAA,EAAG,SAAU,EAAE,EACzBqzC,GAAarzC,GAAA,YAAAA,EAAG,aAAc,EAAK,EACnC3C,EAAS,IAAI,CACf,OAASgB,EAAK,CACZhB,GAAUgB,GAAA,YAAAA,EAAe,UAAW,wBAAwB,CAC9D,SACElB,EAAW,EAAK,CAClB,CACF,EAAG,CAAC8zC,CAAU,CAAC,EAEfzyC,YAAU,IAAM,CACdJ,EAAA,EACA,MAAMmK,EAAK,YAAYnK,EAAM2zC,EAAiB,EAC9C,MAAO,IAAM,cAAcxpC,CAAE,CAC/B,EAAG,CAACnK,CAAI,CAAC,EAGTI,YAAU,IAAM,OACT+0C,EAAc,WACnBh1C,EAAA+0C,EAAU,UAAV,MAAA/0C,EAAmB,eAAe,CAAE,SAAU,OAAQ,MAAO,QAC/D,EAAG,CAAC20C,CAAM,CAAC,EAEX,MAAMM,EAAY90C,GAA+B,CAC/C,MAAM6X,EAAK7X,EAAE,cACP+0C,EAAWl9B,EAAG,aAAeA,EAAG,UAAYA,EAAG,aAAe,GACpEg9B,EAAc,QAAUE,CAC1B,EAEMjU,EAAO,SAAY,CACvB,GAAI,CACF,MAAM,UAAU,UAAU,UAAU0T,CAAM,EAC1C3tC,EAAM,QAAQ,gBAAgB,CAChC,MAAQ,CAER,CACF,EAEA,OACE/E,OAAC,OAAI,UAAU,kBACb,UAAAA,OAAC,OAAI,UAAU,oBACb,UAAAF,MAAC,QAAK,UAAU,QACb,SAAA8yC,EAAY,GAAGF,EAAO,MAAM,2BAA6B,qBAC5D,EACA1yC,OAAC,OAAI,UAAU,4BACb,UAAAA,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAAS/F,EAAM,MAAM,cACrD,UAAAkC,MAACG,GAAA,CAAU,KAAM,GAAI,EAAE,YACzB,EACAD,OAAC2D,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,QAASq7B,EAAM,SAAU,CAAC0T,EAC1D,UAAA5yC,MAACy4B,GAAA,CAAK,KAAM,GAAI,EAAE,SACpB,GACF,GACF,EACC77B,GAAW,CAACg2C,EACX1yC,OAAC,OAAI,UAAU,oBACb,UAAAF,MAACqjC,GAAA,CAAQ,KAAM,GAAI,UAAU,OAAO,EAAE,aACxC,EACEvmC,EACFkD,MAAC,OAAI,UAAU,kBAAmB,SAAAlD,CAAA,CAAM,EACrC81C,SAGF,OAAI,UAAU,mBAAmB,SAAAM,EAChC,UAAAlzC,MAAC,OAAI,UAAU,qBACb,SAAAA,MAAC,QAAM,WAAO,EAChB,EACAA,MAAC,OAAI,IAAKgzC,CAAA,CAAW,GACvB,QAPC,OAAI,UAAU,wBAAwB,mCAAuB,CAO9D,EAEJ,CAEJ,CAIA,SAASb,GACP3uC,EACAkgB,EACA,CACA,MAAM3I,EAAM2I,EAAK,eAAiBA,EAAK,SAAW,GAClDlgB,EAAM,KAAK,CACT,MAAO,iBACP,MAAO,IACP,SAAUxD,MAACozC,GAAA,CAAc,KAAA1vB,EAAY,IAAA3I,CAAA,CAAU,EAChD,CACH,CAEA,SAASq4B,GAAc,CAAE,KAAA1vB,EAAM,IAAA3I,GAAsD,CACnF,KAAM,CAACs4B,EAAQC,CAAS,EAAIn3C,WAAS,EAAK,EACpCo3C,EAAS,SAAY,CACzB,GAAI,CACF,MAAM,UAAU,UAAU,UAAUx4B,CAAG,EACvCu4B,EAAU,EAAI,EACd,OAAO,WAAW,IAAMA,EAAU,EAAK,EAAG,IAAI,CAChD,MAAQ,CAER,CACF,EAEA,OACEtzC,MAAC,OAAI,UAAU,gBACZ,SAAC+a,EAGA7a,OAAAO,WAAA,CACE,UAAAP,OAAC,KAAE,UAAU,eACV,UAAAwjB,EAAK,OACJ1jB,MAAC,QAAK,UAAU,sBAAsB,wBAAY,EAElDE,OAAC,QAAK,UAAU,sBAAsB,gCAChBwjB,EAAK,OAAS,MAAMA,EAAK,MAAM,GAAK,IAC1D,EAEDA,EAAK,SACJxjB,OAAC,QAAK,UAAU,wBAAwB,uBAC5BF,MAAC,QAAK,UAAU,OAAQ,WAAK,QAAQ,GACjD,GAEJ,EACAA,MAAC,SAAM,UAAU,cAAc,0BAAc,EAC7CE,OAAC,OAAI,UAAU,sBACb,UAAAF,MAAC,QAAK,UAAU,uBAAwB,SAAA+a,EAAI,SAC3ClX,EAAA,CAAO,QAAQ,YAAY,KAAK,KAAK,QAAS0vC,EAC7C,UAAAvzC,MAACy4B,GAAA,CAAK,KAAM,GAAI,EAAE,IAAE4a,EAAS,SAAW,QAC1C,GACF,EACArzC,MAAC,KAAE,UAAU,qBAAqB,uHAGlC,GACF,EA5BAA,MAAC,KAAE,UAAU,QAAQ,sDAA0C,CA4B/D,CAEJ,CAEJ,CCnYA,MAAMwzC,GAA8D,CAClE,SAAUC,GACV,KAAM76B,GACN,OAAQ+C,GACR,UAAWkL,GACX,OAAQ4hB,GACR,MAAOrd,GACP,SAAUzpB,GACV,WAAYiwC,GACZ,OAAQ8B,GACR,SAAU/Z,GACV,KAAMC,GACN,UAAWiF,GACX,OAAQ2C,GACR,QAASjQ,GACT,QAAS+e,EACX,EAEMqD,GAAU,SAOhB,SAASC,GACP3xC,EACA4xC,EACA/Z,EACAoC,EACiB,CACjB,GAAIsX,GAASvxC,CAAS,EAAG,CACvB,MAAM6xC,EAAIN,GAASvxC,CAAS,EAC5B,OAAOjC,MAAC8zC,EAAA,CAAG,GAAGD,CAAA,CAAW,CAC3B,CAEA,MAAME,EAAKja,EAAS,KAAM96B,GAAMA,EAAE,KAAOiD,CAAS,EAClD,GAAI8xC,EACF,OACE/zC,MAACg8B,GAAA,CACC,OAAQ+X,EAAG,GACX,UAAA7X,EACA,UAAW2X,EAAU,UACrB,aAAcA,EAAU,eAK9B,MAAMC,EAAIN,GAAS,SACnB,OAAOxzC,MAAC8zC,EAAA,CAAG,GAAGD,CAAA,CAAW,CAC3B,CAMA,SAASG,GAAe,CAAE,QAAAC,GAAoC,CAC5D,KAAM,CAACt4C,EAAOu4C,CAAQ,EAAI/3C,WAAS,EAAE,EAC/BwJ,EAAWlI,SAAyB,IAAI,EAG9CS,YAAU,IAAM,QACdD,EAAA0H,EAAS,UAAT,MAAA1H,EAAkB,OACpB,EAAG,EAAE,EAEL,MAAM6sB,EAAS,IAAM,CACnB,MAAM9c,EAAMrS,EAAM,OACbqS,IACLnQ,EAAI,SAASmQ,CAAG,EAChBimC,EAAA,EACF,EAEM30C,EAAiBlB,GAA2B,CAC5CA,EAAE,MAAQ,WACZA,EAAE,iBACF61C,EAAA,GAEE71C,EAAE,MAAQ,UACZA,EAAE,iBACF0sB,EAAA,EAEJ,EAEA,OACE5qB,OAAC,QACC,UAAU,mBACV,SAAW9B,GAAM,CAAEA,EAAE,iBAAkB0sB,EAAA,CAAU,EAEjD,UAAA5qB,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,SACC,IAAK2F,EACL,KAAK,WACL,UAAU,aACV,MAAAhK,EACA,SAAWyC,GAAM81C,EAAS91C,EAAE,OAAO,KAAK,EACxC,YAAY,mBACZ,WAAY,GACZ,aAAa,MACb,UAAWkB,CAAA,GAEbU,MAAC6D,EAAA,CAAO,KAAK,SAAS,QAAQ,UAAU,KAAK,KAAK,SAAU,CAAClI,EAAM,OAAQ,wBAE3E,GACF,EACAuE,OAAC,KAAE,UAAU,mBAAmB,uDACa,IAC3CF,MAAC,QAAK,4CAAgC,EAAO,+EAE/C,IAGN,CAEO,SAASm0C,IAAM,CACpB,aACGC,GAAA,CACC,SAAAp0C,MAACq0C,IACC,SAAAr0C,MAACs0C,GAAA,EAAM,EACT,EACF,CAEJ,CAEA,SAASA,IAAQ,aACf,MAAMrvC,EAAQC,GAAA,EACRqvC,EAAW9wC,GAAA,EACX,CAAE,YAAA+wC,GAAgBD,EAClBE,EAAiBh3C,SAAO,EAAK,EAC7B,CAACwE,EAAWoJ,CAAY,EAAIlP,WAAiB,UAAU,EACvD,CAACkQ,EAAUqoC,CAAW,EAAIv4C,WAA0B,IAAI,EACxD,CAACuG,EAAUqzB,CAAW,EAAI55B,WAA0B,IAAI,EACxD,CAACgG,EAAUwyC,CAAW,EAAIx4C,WAAmB,YAAY,EACzD,CAACy4C,EAAWC,CAAY,EAAI14C,WAAwB,IAAI,EACxD,CAAC24C,EAAgBC,CAAiB,EAAI54C,WAAS,EAAK,EACpD,CAAC64C,EAAYC,CAAa,EAAI94C,WAAS,EAAK,EAC5C,CAAC+4C,EAAaC,CAAc,EAAIh5C,WAA6B,EAAE,EAC/D,CAACi5C,EAAsBC,CAAuB,EAAIl5C,WAAS,EAAK,EAGhE,CAAC29B,EAAUC,CAAW,EAAI59B,WAAwB,EAAE,EACpD,CAACm5C,EAAmBC,CAAoB,EAAIp5C,WAAS,CAAC,EACtDq5C,EAAQ/3C,SAAkB,IAAI,EAC9B,CAACy3B,EAAIugB,CAAK,EAAIt5C,WAAoB,IAAI,EAI5C+B,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAC,SAAY,CACX,GAAI,CACF,MAAMrG,EAAI,MAAM7B,EAAI,IAA8B,aAAa,EAC/D,GAAIkI,EAAW,OACfg0B,EAAYr6B,EAAE,OAAS,EAAE,CAC3B,MAAQ,CACDqG,GAAWg0B,EAAY,EAAE,CAChC,CACF,KACO,IAAM,CAAEh0B,EAAY,EAAM,CACnC,EAAG,CAACuvC,EAAmBjpC,GAAA,YAAAA,EAAU,IAAI,CAAC,EAGtCnO,YAAU,IAAM,CACd,GAAI,CAACg3B,EAAI,OACT,MAAM6c,EAAM7c,EAAG,GAAIl3B,GAA2B,GACxCA,GAAA,YAAAA,EAAK,QAAS,eAAgBA,GAAA,YAAAA,EAAK,QAAS,gBAAiBA,GAAA,YAAAA,EAAK,QAAS,kBAC7Eu3C,EAAsB3tC,GAAMA,EAAI,CAAC,CAErC,CAAC,EACD,MAAO,IAAMmqC,EAAA,CACf,EAAG,CAAC7c,CAAE,CAAC,EAGPh3B,YAAU,IAAM,CACVwE,GAAA,MAAAA,EAAU,QACZ80B,GAAW90B,EAAS,KAAK,EACzBg0B,GAAiBh0B,EAAS,KAAK,EAEnC,EAAG,CAACA,GAAA,YAAAA,EAAU,KAAK,CAAC,EAOpBxE,YAAU,IAAM,CACdu2C,EAAe,QAAUD,CAC3B,EAAG,CAACA,CAAW,CAAC,EAGhBt2C,YAAU,IAAM,OACd,KAAID,EAAAyE,GAAA,YAAAA,EAAU,QAAV,YAAAzE,EAAiB,QAAS,SAAU,OACxC,MAAMy3C,EAAM,OAAO,WAAW,+BAA+B,EACvDC,EAAU,IAAMne,GAAW90B,EAAS,MAAM,IAAI,EACpD,OAAAgzC,EAAI,iBAAiB,SAAUC,CAAO,EAC/B,IAAMD,EAAI,oBAAoB,SAAUC,CAAO,CACxD,EAAG,EAAC13C,EAAAyE,GAAA,YAAAA,EAAU,QAAV,YAAAzE,EAAiB,IAAI,CAAC,EAI1B,MAAM23C,EAAYj4C,cAAY,SAAY,CACxC,IAAIoI,EAAY,GAEhB,MAAM8vC,EAAe,IACnB,QAAQ,IAAI,CACVh4C,EAAI,IAAc,WAAW,EAAE,MAAM,IAAM,IAAI,EAC/CA,EAAI,IAAsB,WAAW,EAAE,MAAM,IAAM,IAAI,EACvDA,EAAI,IAAmC,eAAe,EAAE,MAAM,IAAM,IAAI,EACzE,EAEGi4C,EAAgB,CACpBC,EACA55B,EACA65B,IACG,CACCD,KAAkBA,CAAI,EACtB55B,GAAA,MAAAA,EAAK,MAAM4Z,EAAY5Z,EAAI,IAAI,EAC/B65B,GAAA,MAAAA,EAAO,OAAOb,EAAea,EAAM,KAAK,CAC9C,EAEA,GAAI,CACF,MAAMC,EAAO,MAAMp4C,EAAI,kBACjB,CAACk4C,EAAM55B,EAAK65B,CAAK,EAAI,MAAMH,EAAA,EAIjC,GADAC,EAAcC,EAAM55B,EAAK65B,CAAK,EAC1BD,GAAQ55B,EAAK,CACf04B,EAAa,IAAI,EACjB,MACF,CAEA,GAAI,CAACoB,EAAK,SAAU,CAClBpB,EAAa,+BAA+B,EAC5C,MACF,CAEA,MAAM,IAAI,QAASqB,IAAY,WAAWA,GAAS,GAAI,CAAC,EAGxD,KAAM,CAACC,GAAWC,GAAUC,EAAU,EAAI,MAAMR,EAAA,EAGhDC,EAAcK,GAAWC,GAAUC,EAAU,EACzC,CAACF,IAAa,CAACC,IACjBvB,EAAa,+BAA+B,CAEhD,OAAS92C,EAAK,CAEZ,MAAMC,GAAOD,GAAA,YAAAA,EAAe,UAAW,gBAGvC,GAAIA,aAAeu4C,IAAYv4C,EAAI,SAAW,IAAK,CACjD82C,EAAa72C,CAAG,EAChB+2C,EAAkB,EAAI,EACtB9vC,EAAM,MAAM,kBAAkBjH,CAAG,EAAE,EACnC,MACF,CACA62C,EAAa72C,CAAG,EAChBiH,EAAM,MAAM,mBAAmBjH,CAAG,EAAE,CACtC,CACF,EAAG,CAACiH,CAAK,CAAC,EAGV/G,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,MAAMkC,EAAK,WAAW,IAAM,CACrBlC,GAAW6vC,EAAA,CAClB,EAAG,CAAC,EACJ,MAAO,IAAM,CACX7vC,EAAY,GACZ,aAAakC,CAAE,CACjB,CACF,EAAG,CAAC2tC,CAAS,CAAC,EAGd13C,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,OAAAlI,EAAI,IAAsB,WAAW,EAClC,KAAMse,GAAQ,SACb,GAAIpW,EAAW,OACf,MAAMwwC,GAAajyC,GAAArG,EAAAke,GAAA,YAAAA,EAAK,OAAL,YAAAle,EAAW,KAAX,YAAAqG,EAAe,WAC9BiyC,KAAyBA,CAAU,CACzC,CAAC,EACA,MAAM,MAAe,EACjB,IAAM,CACXxwC,EAAY,EACd,CACF,EAAG,EAAE,EAIL7H,YAAU,IAAM,CACd,IAAI6H,EAAY,GAChB,MAAMgjB,EAAO,SAAY,CACvB,GAAI,CACF,MAAMrpB,EAAI,MAAM7B,EAAI,IAAmC,eAAe,EACjEkI,GACHovC,EAAgBxtC,GAAQ,CACtB,MAAMtI,EAAOK,EAAE,OAAS,GAExB,OADiBiI,EAAI,SAAW,GAChBtI,EAAK,OAAS,GAC5B4F,EAAM,QAAQ,GAAG5F,EAAK,MAAM,SAASA,EAAK,SAAW,EAAI,GAAK,GAAG,SAAU,GAAI,EAE1EA,CACT,CAAC,CAEL,MAAQ,CAER,CACF,EACM4I,EAAK,YAAY8gB,EAAM,GAAM,EACnC,OAAAA,EAAA,EACO,IAAM,CACXhjB,EAAY,GACZ,cAAckC,CAAE,CAClB,CAEF,EAAG,EAAE,EAGL/J,YAAU,IAAM,CACd,MAAMg3B,EAAK,IAAIC,GACfqgB,EAAM,QAAUtgB,EAChBugB,EAAMvgB,CAAE,EACR,MAAMshB,EAAYthB,EAAG,SAAU/uB,GAAMwuC,EAAYxuC,CAAC,CAAC,EAC7CswC,EAASvhB,EAAG,GAAIl3B,GAAmB,OACvC,GAAIA,EAAI,OAAS,YAAc,SAAUA,GAAOA,EAAI,KAClD02C,EAAa/sC,IAAS,CAAE,GAAIA,GAAQ,GAAkB,GAAG3J,EAAI,MAAO,UAC3DA,EAAI,OAAS,SAAU,CAChC,MAAM6Q,EAAI7Q,EACJ04C,IAAOz4C,EAAA4Q,EAAE,OAAF,YAAA5Q,EAAQ,MAAM,KAAK,QAAS4Q,EAAE,MAAQ,GACnD5J,EAAM,KAAK,iBAAiByxC,CAAI,GAAI,IAAI,CAC1C,SAAW14C,EAAI,OAAS,eAAgB,CACtC,MAAM6Q,EAAI7Q,EACV02C,EAAa/sC,GAAQ,CACnB,GAAI,CAACA,EAAK,OAAOA,EACjB,MAAMwgB,IAASxgB,EAAI,OAAS,IAAI,IAAKjD,IACnCA,GAAE,KAAOmK,EAAE,KAAK,GAAKA,EAAE,KAAOnK,EAAA,EAE1BiyC,GAASxuB,GAAM,KAAMzjB,IAAMA,GAAE,KAAOmK,EAAE,KAAK,EAAE,EACnD,MAAO,CAAE,GAAGlH,EAAK,MAAOgvC,GAASxuB,GAAQ,CAACtZ,EAAE,KAAM,GAAGsZ,EAAK,EAC5D,CAAC,CACH,SAAWnqB,EAAI,OAAS,eAAgB,CACtC,MAAM6Q,EAAI7Q,EACV02C,EAAa/sC,GACXA,GACI,CAAE,GAAGA,EAAK,OAAQA,EAAI,OAAS,IAAI,OAAQjD,IAAMA,GAAE,KAAOmK,EAAE,EAAE,EAC9D,CAER,SAAW7Q,EAAI,OAAS,kBAAmB,CACzC,MAAM6Q,EAAI7Q,EACN6Q,EAAE,UAAUknB,EAAYlnB,EAAE,QAAQ,CACxC,SAAW7Q,EAAI,OAAS,iBAEtBH,EACG,IAAc,WAAW,EACzB,KAAMsI,GAAMuuC,EAAa/sC,IAAS,CAAE,GAAIA,GAAQ,GAAkB,GAAGxB,CAAA,EAAI,CAAC,EAC1E,MAAM,MAAe,UACfnI,EAAI,OAAS,iBAAmBA,EAAI,OAAS,mBACtDH,EACG,IAAc,WAAW,EACzB,KAAMsI,GAAMuuC,EAAa/sC,IAAS,CAAE,GAAIA,GAAQ,GAAkB,GAAGxB,CAAA,EAAI,CAAC,EAC1E,MAAM,MAAe,UACfnI,EAAI,OAAS,gBAAkBA,EAAI,OAAS,kBAAmB,CACxE,MAAM6Q,EAAI7Q,EACV02C,EAAa/sC,GAAQ,CACnB,GAAI,CAACA,EAAK,OAAOA,EACjB,MAAMuP,IAAUvP,EAAI,QAAU,IAAI,IAAK/M,IAAOA,GAAE,OAASiU,EAAE,MAAM,KAAOA,EAAE,MAAQjU,EAAE,EACpF,MAAO,CAAE,GAAG+M,EAAK,OAAAuP,EAAA,CACnB,CAAC,CACH,SAAWlZ,EAAI,OAAS,kBAEtBH,EACG,IAA+B,YAAY,EAC3C,KAAM2V,GAAM,CACXkhC,EAAa/sC,GAASA,GAAM,CAAE,GAAGA,EAAK,UAAW6L,EAAE,WAAa,EAAC,CAAU,CAC7E,CAAC,EACA,MAAM,MAAe,UACfxV,EAAI,OAAS,cAEtBm3C,EADUn3C,EACO,QAAU,EAAE,UACpBA,EAAI,OAAS,cAAe,CAErC,MAAM6Q,EAAI7Q,EACN6Q,EAAE,QACJ0lC,EAAS,KAAK,CACZ,MAAO1lC,EAAE,OAAO,MAChB,MAAO,IACP,SAAU7O,MAAC2K,GAAA,CAAc,OAAQkE,EAAE,OAAQ,QAAS,IAAM0lC,EAAS,OAAM,CAAG,EAC7E,CAEL,CACF,CAAC,EACD,MAAO,IAAM,CACXiC,EAAA,EACAC,EAAA,EACAvhB,EAAG,QACHugB,EAAM,IAAI,CACZ,CACF,EAAG,CAACxwC,CAAK,CAAC,EAEV,MAAM2xC,EAAgBj5C,cAAaof,GAC5BmY,EACEA,EAAG,GAAGnY,CAAE,EADC,OAEf,CAACmY,CAAE,CAAC,EAiBD2hB,EAAep5C,SAAO,CAAC,EAC7BS,YAAU,IAAM,CACd,MAAM44C,EAAO,IAAM,CACjBD,EAAa,QAAU,KAAK,MAAQ,IACtC,EACA,gBAAS,iBAAiB,YAAaC,EAAM,EAAI,EACjD,SAAS,iBAAiB,QAASA,EAAM,EAAI,EAC7C,SAAS,iBAAiB,UAAWA,EAAM,EAAI,EAC/C,SAAS,iBAAiB,UAAWA,EAAM,EAAI,EACxC,IAAM,CACX,SAAS,oBAAoB,YAAaA,EAAM,EAAI,EACpD,SAAS,oBAAoB,QAASA,EAAM,EAAI,EAChD,SAAS,oBAAoB,UAAWA,EAAM,EAAI,EAClD,SAAS,oBAAoB,UAAWA,EAAM,EAAI,CACpD,CACF,EAAG,EAAE,EAGL54C,YAAU,IAAM,CACd,MAAM64C,EAA8B,GACpCx1C,GAAK,QAAQ,CAACmD,EAAGtJ,IAAM,CACrB27C,EAAI,OAAO37C,EAAI,CAAC,CAAC,EAAIsJ,EAAE,EACzB,CAAC,EACD,MAAMixC,EAAWv3C,GAAqB,iBACpC,IAAKA,EAAE,SAAWA,EAAE,UAAYA,EAAE,IAAI,gBAAkB,IAAK,CAC3DA,EAAE,iBACF62C,EAAc,EAAI,EAClB,MACF,CACA,GAAI72C,EAAE,MAAQ,KAAO,CAACA,EAAE,SAAW,CAACA,EAAE,QAAS,CAC7C,MAAMsG,IAAKJ,IAAArG,GAAAG,EAAE,SAAF,YAAAH,GAAiC,UAAjC,YAAAqG,GAA0C,cACrD,GAAII,KAAM,SAAWA,KAAM,YAAc,GAAGiK,GAAAvQ,EAAE,SAAF,MAAAuQ,GAA0B,mBAAoB,CACxFvQ,EAAE,iBACF62C,EAAc,EAAI,EAClB,MACF,CACF,CA4BA,MAAM+B,EAAW,SAAS,cAE1B,GADuB,CAACA,GAAYA,IAAa,SAAS,MAAQA,IAAa,SAAS,gBAMtF,OAEF,MAAM3hC,EAASjX,EAAE,OACXssB,GAAMhE,GAAArR,GAAA,YAAAA,EAAQ,UAAR,YAAAqR,GAAiB,cACvBuwB,GACJvsB,IAAQ,SACRA,IAAQ,YACRA,IAAQ,UACRA,IAAQ,UACRA,IAAQ,UACRA,IAAQ,SACR,CAAC,EAACrV,GAAA,MAAAA,EAAQ,mBAEZ,IAAI6hC,GAAS,GAYb,GAXI7hC,GAAU,OAAOA,EAAO,SAAY,aACtC6hC,GAAS,CAAC,CAAC7hC,EAAO,QAAQ,yDAAyD,GAMjFjX,EAAE,QAGFq2C,EAAe,SAEjBwC,IACAC,IACA94C,EAAE,SACFA,EAAE,SACFA,EAAE,QACFA,EAAE,UACF,KAAK,MAAQy4C,EAAa,QAE1B,OACF,MAAM5uC,GAAK8uC,EAAI34C,EAAE,GAAG,EAChB6J,KACF7J,EAAE,iBACFiN,EAAapD,EAAE,EAEnB,EACA,gBAAS,iBAAiB,UAAW0tC,CAAO,EACrC,IAAM,SAAS,oBAAoB,UAAWA,CAAO,CAC9D,EAAG,EAAE,EAEL,MAAMrpC,EAAkBiI,UACtB,IAAM,SAAY,CAChB,GAAI,CACF,MAAMpO,EAAI,MAAMtI,EAAI,IAAc,WAAW,EAC7C62C,EAAa/sC,IAAS,CAAE,GAAIA,GAAQ,GAAkB,GAAGxB,CAAA,EAAI,CAC/D,OAASpI,EAAK,CACZkH,EAAM,MAAM,mBAAoBlH,EAAc,OAAO,EAAE,CACzD,CACF,EACA,CAACkH,CAAK,GAOFkyC,EAAa5iC,UAAQ,IAAM,CAC/B,MAAM5P,EAAUm1B,EAAS,IAAK96B,IAAO,CACnC,GAAIA,EAAE,GACN,MAAOA,EAAE,MACT,KAAMA,EAAE,OAAS,SAAW/G,GAAQM,GACpC,MAAO,GACP,MAAOyG,EAAE,OACT,EACF,MAAO,CAAC,GAAGuC,GAAM,GAAGoD,CAAO,CAC7B,EAAG,CAACm1B,CAAQ,CAAC,EAIPsd,EAAe7iC,UAAQ,IACvBlI,GAAY3J,EAQPkxC,GAAiB3xC,EAPK,CAC3B,SAAAoK,EACA,SAAA3J,EACA,UAAAT,EACA,aAAAoJ,EACA,gBAAAiB,CAAA,EAE4CwtB,EAAUwb,CAAiB,EAEpE,KACN,CAACrzC,EAAWoK,EAAU3J,EAAUo3B,EAAUwb,EAAmBhpC,CAAe,CAAC,EAE1E+qC,GAAkB,SAAY,CAClC,GAAI,CACF,MAAM33C,EAAI,MAAM7B,EAAI,IAA0D,WAAW,EACzF62C,EAAa/sC,UACX,OAAAA,GAAM,CAAE,GAAGA,EAAK,SAAUjI,EAAE,UAAY,GAAI,gBAAezB,EAAAyB,EAAE,WAAF,YAAAzB,EAAY,KAAM,GAAM,EAAE,KAAOyB,EAAE,UAAW,MAAS,CAEtH,OAAS3B,EAAK,CACZkH,EAAM,MAAM,4BAA6BlH,EAAc,OAAO,EAAE,CAClE,CACF,EAEMu5C,GAAoB,MAAOrvC,GAAe,CAC9C,GAAI,CACF,MAAMpK,EAAI,KAAK,aAAa,mBAAmBoK,CAAE,CAAC,WAAW,EAE7DysC,EAAa/sC,GACNA,GACE,CACL,GAAGA,EACH,cAAeA,EAAI,SAAS,KAAM3M,GAAMA,EAAE,KAAOiN,CAAE,GAAK,KAE3D,CACH,OAASlK,EAAK,CACZkH,EAAM,MAAM,oBAAqBlH,EAAc,OAAO,EAAE,CAC1D,CACF,EAEMw5C,EAAkB73C,GAAoB,CAC1C,MAAMgF,EAAIhF,EAAE,KACZ,GAAIgF,IAAM,QAAS2G,EAAa,QAAQ,UAC/B3G,IAAM,OAAQ2G,EAAa,OAAO,UAClC3G,IAAM,MAAO2G,EAAa,MAAM,UAChC3G,IAAM,WAAY2G,EAAa,WAAW,UAC1C3G,IAAM,UAAW,CACxB,MAAMuD,EAAMvI,EAAE,KAAuB,GACrC43C,GAAkBrvC,CAAE,CACtB,SAAWvD,IAAM,UAEfO,EAAM,KAAK,IAAKvF,EAAE,KAA0B,IAAI,sBAAuB,IAAI,UAClEgF,IAAM,UAAW,CAE1B,MAAM8yC,EAAa93C,EAAE,KAAwC,IACvDA,EAAE,KAA2B,MAC9B,GACL2L,EAAa,UAAU,EAIvB,MAAMosC,EAAaC,GAAkB,CACnC,GAAIA,GAAS,EAAG,OAChB,MAAMzhC,EAAKuhC,EACP,SAAS,cAAc,qBAAqB,IAAI,OAAOA,CAAS,CAAC,IAAI,EACrE,KACAvhC,GACDA,EAAmB,eAAe,CAAE,SAAU,SAAU,MAAO,SAAU,EAC1EA,EAAG,UAAU,OAAO,eAAe,EAE7BA,EAAmB,YACzBA,EAAG,UAAU,IAAI,eAAe,EAChC,OAAO,WAAW,IAAMA,EAAG,UAAU,OAAO,eAAe,EAAG,IAAI,GAElE,OAAO,WAAW,IAAMwhC,EAAUC,EAAQ,CAAC,EAAG,EAAE,CAEpD,EACA,OAAO,WAAW,IAAMD,EAAU,EAAE,EAAG,EAAE,CAC3C,CACF,EAEM11B,IAASzd,GAAA5B,GAAA,YAAAA,EAAU,KAAV,YAAA4B,GAAc,SAAU,SACjCqzC,KAAahpC,GAAAjM,GAAA,YAAAA,EAAU,KAAV,YAAAiM,GAAc,cAAe,GAEhD,cACG,OAAI,UAAU,MAAM,cAAaoT,EAAQ,kBAAiB9f,EACxD,UAAA01C,IACC33C,MAACgC,GAAA,CACC,UAAAC,EACA,YAAaoJ,EACb,SAAAlJ,EACA,QAASwxC,GACT,eAAetnC,GAAA,YAAAA,EAAU,gBAAiB,KAC1C,UAAUA,GAAA,YAAAA,EAAU,WAAY,GAChC,gBAAiBirC,GACjB,kBAAmBD,GACnB,aAAc,IAAMpC,EAAc,EAAI,EACtC,SAAAvyC,EACA,kBAAmB1C,MAACgH,GAAA,CAAc,YAAa4vC,CAAA,CAAe,EAC9D,SAAU70B,IAAW,SACrB,UAAWo1B,CAAA,GAGdjC,EAAY,OAAS,GAAK,CAACE,UACzB,OAAI,UAAU,eAAe,KAAK,QACjC,UAAAp1C,MAAC+G,GAAA,CAAc,KAAM,GAAI,SACxB,QACC,UAAA/G,MAAC,UAAQ,WAAY,OAAO,EAAS,SAAOk1C,EAAY,SAAW,EAAI,GAAK,IAAI,UAAQ,IACxFl1C,MAAC,QAAK,UAAU,OACb,SAAAk1C,EAAY,IAAKt6C,GAAMA,EAAE,IAAI,EAAE,KAAK,IAAI,EAC3C,GACF,EACAoF,MAAC6D,EAAA,CACC,QAAQ,YACR,KAAK,KACL,QAAS,IAAM,CACbwH,EAAa,QAAQ,EACrBgqC,EAAwB,EAAI,CAC9B,EACD,oBAGDr1C,MAAC,UACC,KAAK,SACL,UAAU,WACV,aAAW,UACX,QAAS,IAAMq1C,EAAwB,EAAI,EAE3C,SAAAr1C,MAACuG,GAAA,CAAE,KAAM,GAAI,GACf,EACF,EAEFrG,OAAC,OAAI,UAAU,cACZ,UAAA6hB,IAAW,UACV/hB,MAACuE,GAAA,CACC,KAAM4yC,EACN,UAAAl1C,EACA,YAAaoJ,CAAA,GAGjBnL,OAAC,QAAK,UAAU,UACb,UAAA00C,GACC10C,OAAC,OAAI,UAAU,aACb,UAAAF,MAAC,MAAG,iCAAqB,EACzBA,MAAC,KAAG,SAAA40C,CAAA,CAAU,EACbE,GACC90C,MAACg0C,GAAA,CACC,QAAS,IAAM,CACbe,EAAkB,EAAK,EACvBa,EAAA,CACF,IAGJ11C,OAAC,KAAE,UAAU,kBAAkB,iEACwB,IACrDF,MAAC,QAAK,4BAAgB,EAAO,sBAC/B,GACF,EAED,CAAC40C,IAAc,CAACvoC,GAAY,CAAC3J,IAC5BxC,OAAC,OAAI,UAAU,UACb,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EACnBvO,MAAC,KAAE,0BAAc,GACnB,EAEDo3C,GACCp3C,MAAC88B,WAAA,CAAS,SAAU58B,OAAC,OAAI,UAAU,UAAU,UAAAF,MAACuO,GAAA,CAAQ,KAAK,KAAK,EAAEvO,MAAC,KAAE,oBAAQ,GAAI,EAC/E,SAAAA,MAAC43C,GAAA,CAAmB,SAAAR,CAAA,CAAa,EACnC,GAEJ,GACF,EACAp3C,MAAC8E,GAAA,CACC,KAAMkwC,EACN,QAAS,IAAMC,EAAc,EAAK,EAClC,SAAUsC,CAAA,EACZ,EACF,CAEJ,CAMA,MAAMK,WAA0BC,WAG9B,CAHF,kCAIEp0B,GAAA,aAA+B,CAAE,IAAK,OAQtCA,GAAA,aAAQ,IAAM,KAAK,SAAS,CAAE,IAAK,KAAM,GAPzC,OAAO,yBAAyB1lB,EAAmC,CACjE,MAAO,CAAE,IAAAA,CAAA,CACX,CACA,kBAAkBA,EAAY2lB,EAAmC,CAE/D,QAAQ,MAAM,2CAA4C3lB,EAAK2lB,GAAA,YAAAA,EAAM,cAAc,CACrF,CAES,QAAS,CAChB,OAAI,KAAK,MAAM,IAEXxjB,OAAC,OAAI,UAAU,sBAAsB,KAAK,QACxC,UAAAF,MAAC+G,GAAA,CAAc,KAAM,GAAI,EACzB7G,OAAC,OAAI,UAAU,kBACb,UAAAF,MAAC,UAAO,8BAAkB,EAC1BA,MAAC,OAAK,cAAK,MAAM,IAAI,QAAQ,EAC7BA,MAAC6D,GAAO,QAAQ,YAAY,KAAK,KAAK,QAAS,KAAK,MAAO,iBAAK,GAClE,GACF,EAGG,KAAK,MAAM,QACpB,CACF,CC9zBA,SAASi0C,IAAO,CACd,KAAM,CAACC,EAAUC,CAAW,EAAI77C,WAAS,IACnC,OAAO,OAAW,IAAoB,GACnC,OAAO,WAAW,oBAAoB,EAAE,OAChD,EAED+B,mBAAU,IAAM,CACd,MAAMw3C,EAAM,OAAO,WAAW,oBAAoB,EAC5CC,EAAWv3C,GAA2B45C,EAAY55C,EAAE,OAAO,EACjE,OAAAs3C,EAAI,iBAAiB,SAAUC,CAAO,EAC/B,IAAMD,EAAI,oBAAoB,SAAUC,CAAO,CACxD,EAAG,EAAE,EAEEoC,EAAW/3C,MAACi4C,GAAA,EAAU,QAAM9D,GAAA,EAAI,CACzC,CAEA,MAAM+D,GAAO,SAAS,eAAe,MAAM,EAC3C,GAAI,CAACA,GAAM,MAAM,IAAI,MAAM,8BAA8B,EACzDC,GAAWD,EAAI,EAAE,OACfl4C,MAACo4C,aAAA,CACC,SAAAp4C,MAAC83C,GAAA,EAAK,EACR,CACF","names":["ArchiveRestore","createLucideIcon","ArrowDown","ArrowLeft","ArrowUp","Brain","Calendar","ChartNoAxesColumn","Check","ChevronLeft","CircleCheckBig","CircleDollarSign","CirclePlay","CircleX","Circle","Coins","Cpu","Database","Diamond","Download","Ellipsis","EyeOff","Eye","FileCode2","FileCode","FilePlus","File","Filter","FolderOpen","FolderPlus","FolderSearch","GitBranch","GitCommitHorizontal","GitMerge","GitPullRequest","Globe","House","Inbox","KeyRound","Layers","LayoutDashboard","LayoutTemplate","LoaderCircle","MapPin","Map","Maximize2","Minus","OctagonAlert","Package","Palette","PanelLeftClose","PanelLeftOpen","PanelsTopLeft","Pen","Plug","PowerOff","Puzzle","Radio","Redo2","Share2","ShieldCheck","Shield","SquarePen","Square","Tag","Target","Undo2","User","Users","Zap","MAX_CACHE","TTL_MS","_cache","cacheGet","path","entry","cacheSet","data","a","b","k","pathSegments","p","parts","result","accumulated","i","sortEntries","entries","validateDirName","name","trimmed","FileBrowser","value","onChange","initialPath","projectsDirectory","rootLabel","height","currentPath","setCurrentPath","useState","expanded","setExpanded","selectedRow","setSelectedRow","listing","setListing","childrenMap","setChildrenMap","loading","setLoading","error","setError","mkdirOpen","setMkdirOpen","mkdirName","setMkdirName","mkdirError","setMkdirError","mkdirLoading","setMkdirLoading","mkdirInputRef","useRef","fetchListing","useCallback","cached","api","load","err","msg","_a","useEffect","dirs","e","allEntries","navigateInto","navigateUp","navigateTo","goHome","home","goProjects","pd","openMkdir","cancelMkdir","submitMkdir","v","apiErr","handleMkdirKeyDown","toggleExpand","prev","next","handleKeyDown","x","files","selectable","r","sel","segments","parentPath","canGoUp","basename","jsx","seg","jsxs","RefreshCw","Home","AlertCircle","TreeSkeleton","TreeNode","FlatSkeleton","Fragment","idx","isDir","isSelected","isActive","Folder","onToggle","onNavigate","level","isExpanded","kids","ChevronDown","ChevronRight","w","TABS","MessageSquare","Bot","CheckSquare","Activity","Sparkles","Clock","HistoryIcon","Sliders","Topbar","activeTab","onTabChange","wsStatus","version","activeProject","projects","onProjectChange","onProjectsRefresh","onOpenSearch","settings","rightSlot","notificationsSlot","showTabs","extraTabs","ProjectSelector","SearchIcon","cn","tab","Icon","active","onRefresh","open","setOpen","modal","useModal","onClick","onAdd","TopbarAddProjectDialog","Button","Plus","setPath","setName","preflighting","setPreflighting","preflightError","setPreflightError","handleAdd","_b","Sidebar","tabs","builtIn","t","modTabs","SCOPES","RESULT_TYPE_BY_SCOPE","SearchModal","onClose","onSelect","toast","useToast","q","setQ","scope","setScope","results","setResults","activeIdx","setActiveIdx","inputRef","previousFocusRef","focusTimer","previous","cancelled","grouped","type","flat","s","resultType","onKey","Search","X","list","flatIdx","summarize","val","ICONS","Info","CheckCircle2","AlertTriangle","Notifications","onCountChange","wsSubscribe","items","setItems","stats","setStats","rootRef","unreadRef","reload","incoming","cur","n","onDocClick","onKeyDown","onMarkAllRead","onMarkRead","id","onRemove","removed","statsCur","unread","Bell","formatRelative","VisualPlanDialog","enabled","mode","defaultTemplate","lastUsedSlug","wasToggled","KNOWN_TEMPLATES","ArtifactCreateDialog","templates","slug","setSlug","selectedTemplate","setSelectedTemplate","creating","setCreating","handleCreate","ArtifactListDialog","plans","count","handleOpen","HelpDialog","commands","statuses","AuditDialog","running","setRunning","setResult","handleRunAudit","res","f","GenericDialog","dialog","message","detail","url","CommandDialog","Card","variant","interactive","className","children","rest","CardTitle","CardMeta","MemoryStatusCard","setActiveTab","refreshKey","setData","status","health","lightrag","openMemory","healthColor","ExternalLink","FileText","formatTime","EmptyState","icon","title","action","OverviewInner","snapshot","refreshSnapshot","overview","setOverview","setProjects","activeId","setActiveId","mods","setMods","submitting","setSubmitting","activityItems","setActivityItems","activityExpanded","setActivityExpanded","hiddenKeys","setHiddenKeys","itemKey","it","h","onHide","key","rollback","onClearAll","all","onRestoreAll","es","tok","parsed","onAddProject","AddProjectDialog","onUseCurrentDir","newActive","onActivate","Spinner","text","Send","ActivityFeedItem","_c","ProjectCard","m","project","onOpen","statusColor","Trash2","Power","sentenceCase","humanizeKind","kind","normalized","scopeRaw","actionRaw","scopeMap","actionMap","firstString","keys","formatActivitySummary","direct","agent","formatRelativeTime","ts","activitySeverity","activityIcon","AlertOctagon","activityNavTarget","item","activityKey","severity","navTarget","accentColor","OverviewMemo","React","SessionRowMenu","session","anchor","renameDraft","setRenameDraft","onEdit","onDeleteRequest","onConfirmDelete","onConfirmRename","ref","top","right","onDown","input","body","Edit","createPortal","AgentNode","node","depth","collapsible","isLast","controlledOpen","internalOpen","setInternalOpen","isControlled","hasChildren","headContent","child","isFullTree","props","AgentTree","SubAgentList","DEFAULT_GROUPS","isSameDay","dayDiff","ms","defaultGroupBy","sessions","now","yesterday","weekAgo","groups","d","mtime","SessionStateIndicator","state","ChatRail","opencodeSessions","activeSessionId","activeOpencodeSessionId","onCreateSession","onSelectSession","onSelectOpencodeSession","onRenameSession","onDeleteSession","groupBy","allSessions","useMemo","sorted","openTree","setOpenTree","isTreeOpen","openMenuId","setOpenMenuId","menuMode","setMenuMode","menuAnchor","setMenuAnchor","rowRefs","openMenuFor","row","target","closeMenu","handleSelect","handleConfirmRename","sid","handleConfirmDelete","orderedGroups","g","group","isOpencode","tree","treeOpen","el","ChatComposer","sending","onSend","activeSource","takingOff","setTakingOff","handleSend","Composer","formatNumber","providerFromModel","model","approxCostPer1M","ChatInfoPanel","sessionId","messages","pinned","agents","mcps","allCommands","onRename","onDelete","onExport","busy","usage","setUsage","msgCount","pinnedCount","totalChars","approxTokens","rate","approxCostUsd","tokensUsed","costUsd","tokensTotal","provider","Server","Terminal","Pencil","JumpToLatest","streaming","newMessageCount","streamingLabel","Chat","initialTaskId","onClearTaskId","chat","useChat","setText","setAgent","setModel","attachments","setAttachments","fileInputRef","suggestions","setQuery","useSlashCommands","onAttach","onFiles","newNames","handleCreateSession","handleDelete","handleRename","currentTitle","ok","handleDeleteSession","handleExport","who","c","blob","displaySessions","displayOpencodeSessions","activeSessionDisplay","threadSubtitle","base","sourceLabel","ChatTopBar","ChatThread","cmd","StatusBadge","dot","TOOL_OPTIONS","MODELS","CATEGORIES","categoryColor","cat","StatusDot","isStuck","color","StatusPill","Agents","setAgents","categoryFilter","setCategoryFilter","search","setSearch","out","allTags","set","onCreate","nameEl","descEl","modelEl","modeEl","colorEl","promptEl","toolsContainer","tagsEl","categoryEl","tools","cb","tags","created","Save","full","updated","onInvoke","prompt","Play","onRestart","onSetStatus","TagIcon","AgentCard","catColor","isWorking","RotateCw","RichText","proseStyle","ReactMarkdown","remarkGfm","CALLOUT_TONE","XCircle","Callout","tone","Checklist","Table","columns","rows","ri","cell","ci","CodeTabs","selected","Decision","question","options","opt","isRec","OpenQuestions","questions","answers","setAnswers","setAnswer","qid","inputStyle","current","checked","o","FILE_CHANGE","FileTree","Diff","filename","language","before","after","beforeLines","afterLines","header","codeStyle","lineRow","sign","content","colors","signColor","l","TREND_STYLE","Stat","label","trend","hint","STEP_COLORS","BOX_W","BOX_H","GAP_X","GAP_Y","Workflow","steps","connections","Empty","byId","layout","layoutSteps","cols","width","nodeCenter","stepId","pos","from","to","dx","dy","fromX","toX","fromY","toY","midX","midY","y","cx","cy","points","isNote","StickyNote","Mockup","html","BlockErrorBoundary","__publicField","info","validateBlock","SECTION_MAP","groupBlocksIntoSections","blocks","sections","heading","GlyphRenderer","onCommentAdded","compiled","setCompiled","comments","setComments","loadError","setLoadError","fullscreen","setFullscreen","ctxMenu","setCtxMenu","addingComment","setAddingComment","commentDraft","setCommentDraft","activePin","setActivePin","blockErrors","setBlockErrors","reportBlockError","blockId","blockType","canvasRef","TIMEOUT_MS","timeoutPromise","_","reject","renderData","artifactData","fromFile","onContainerContextMenu","rect","submitComment","submitFeedback","toggleFullscreen","renderBlock","validation","renderBlockInner","commentCount","MoreHorizontal","_d","section","planStatusKind","Artifacts","artifacts","setPlans","activeSlug","setActiveSlug","filter","setFilter","showArchived","setShowArchived","filtered","artifact","MapIcon","Archive","NewPlanCard","PlanCard","setTitle","BacklogItem","task","onPromote","handlePromote","priorityDot","BacklogPanel","tasks","setTasks","handleEdit","_task","handlePromoteAll","COLUMNS","PRIORITIES","TasksInner","priorityFilter","setPriorityFilter","showBacklog","setShowBacklog","tick","setTick","priorityWeight","pa","pb","backlogCount","moveTask","taskId","newStatus","deleteTask","retryTask","submitToOdin","XIcon","openCreateTaskModal","col","KanbanColumn","openEditTaskModal","column","onMove","onRetry","onSubmitToOdin","dragOver","setDragOver","TaskCard","dir","assignedAgent","priorityColors","tag","Edit2","titleEl","priorityEl","submit","description","priority","onTitleKeyDown","enhanced","enhancePrompt","Tasks","getArtifactContentUrl","artifactId","openArtifactViewer","_modal","ZOOM_RANGES","LANE_HEIGHT","TIME_AXIS_HEIGHT","EVENTS_STRIP_HEIGHT","MIN_BAR_WIDTH","REANCHOR_RATIO","STATUS_COLORS","shortLabel","parseTs","taskStartMs","taskEndMs","bgStartMs","bgEndMs","chooseTickStep","rangeMs","formatTickLabel","canvasWrapRef","setMode","zoom","setZoom","streamOpen","setStreamOpen","bgInstances","setBgInstances","events","setEvents","refreshTick","setRefreshTick","nowTick","setNowTick","viewStart","setViewStart","canvasSize","setCanvasSize","selectedItem","setSelectedItem","commentText","setCommentText","taskTitle","setTaskTitle","taskPriority","setTaskPriority","bgMessage","setBgMessage","bgOutput","setBgOutput","creatingTask","setCreatingTask","postingComment","setPostingComment","bgArtifactIds","setBgArtifactIds","rangeStart","rangeEnd","reloadAll","bgRes","evRes","useLayoutEffect","ro","lanes","bg","start","end","taskLaneEnds","assigned","laneById","timeToX","ticks","step","startAligned","bars","lane","visibleStart","visibleEnd","xEnd","statusClass","eventMarkers","ev","laneRects","nowX","onSelectBar","bar","bgData","artR","onAddComment","onCreateTaskFromNode","onSendBgMessage","onKillBg","refetchOutput","refresh","contentHeight","ActivityIcon","Pause","z","History","lr","fillColor","BACKEND_OPTIONS","HeadroomSettingsCard","onPatch","setStatus","loadingStatus","setLoadingStatus","installing","setInstalling","wrapping","setWrapping","unwrapping","setUnwrapping","startingProxy","setStartingProxy","stoppingProxy","setStoppingProxy","loadStatus","st","handleInstall","handleWrap","handleUnwrap","handleStartProxy","handleStopProxy","handleOpenDashboard","spawn","__vitePreload","installed","proxyRunning","proxyPort","wrapped","ratio","saved","CheckCircle","THEMES","Moon","Sun","Monitor","PRESET_THEMES","DEFAULT_HEADROOM_SETTINGS","FONT_FAMILIES","formatCountdown","PairDeviceCard","pair","setPair","pairing","setPairing","pairError","setPairError","setNow","remaining","expired","Smartphone","QRCodeSVG","QrCode","LAYOUTS","UpdatesCard","ws","Ws","existing","check","applyUpdate","restart","packages","isBusy","lat","isOutdated","pkgStatus","SettingsViewInner","initial","setSettings","dirty","setDirty","saving","setSaving","tailscale","setTailscale","tailscaleDraft","setTailscaleDraft","pluginOptions","setPluginOptions","applyThemeTokens","patchTheme","patch","patchUi","patchTop","patchNotifications","patchAgents","SECTION_LINKS","activeSection","setActiveSection","hash","onJumpSection","patchDashboard","onSave","applyTheme","onReload","onReset","onTailscaleToggle","about","authToken","setAuthToken","authStatus","setAuthStatus","revealedToken","setRevealedToken","onCopyToken","onRegenerateToken","onSaveToken","RotateCcw","LayoutIcon","ServerIcon","Copy","lines","rawLines","warnings","line","_e","_f","_g","ActivityLogCard","hidden","setHidden","showHidden","setShowHidden","log","hid","keyOf","onRestoreOne","isHidden","SettingsView","Mods","setSelected","modViews","setModViews","iframeUrl","setIframeUrl","registryOpen","setRegistryOpen","registry","setRegistry","registryLoading","setRegistryLoading","loadRegistry","onInstallFromRegistry","onUpgradeFromRegistry","backup","backupNote","onInstall","pathEl","onUninstall","onToggleEnabled","mod","ModDetails","rm","isInstalling","instructions","setInstructions","instructionsLoading","setInstructionsLoading","instructionsOpen","setInstructionsOpen","expandedFile","setExpandedFile","loadInstructions","onReinstallInstructions","BookOpen","ModView","viewId","reloadKey","view","setView","iframeReload","setIframeReload","found","src","componentPath","modId","ModComponent","lazy","ErrorBoundary","Suspense","ReactComponent","TYPES","ACTIONS","TIMEZONES","MINUTE_OPTIONS","HOUR_OPTIONS","DOW_OPTIONS","INTERVAL_UNITS","parseCronFields","expr","dow","minNum","hourNum","dowClean","parseIntervalParts","buildInitialState","parsedInterval","tz","tzKnown","toDatetimeLocal","iso","pad","composeSchedule","cron","dowName","hourLabel","minute","human","unit","u","Schedules","schedules","setSchedules","openEditor","ScheduleEditorModal","copy","onRun","humanizeSchedule","PlayCircle","resultTagClass","truncate","formatNextRun","onSubmitted","onError","setState","tzSelectValue","update","handleSubmit","trimmedName","composed","actionPayload","payload","max","SOURCE_LABEL","SOURCE_ICON","SkillsInner","skills","setSkills","counts","setCounts","searchQ","setSearchQ","searchResults","setSearchResults","searching","setSearching","displayed","onShowDetail","skill","SkillCard","onShow","desc","highlightMatch","Skills","MemoryOverview","setActiveSubPanel","signal","storage","ctrl","vault","scoreColor","StatCard","formatBytes","sub","Comp","LightragPanel","config","setConfig","logTail","setLogTail","setBusy","query","queryResult","setQueryResult","runCommand","fn","successMsg","onStart","onStop","onReindex","onRebuild","onQuery","Loader2","StatBox","FileTextCount","ObsidianPanel","notes","setNotes","setTree","backlinks","setBacklinks","pathSet","relPath","NoteEditor","frontmatter","note","rp","sortedNotes","countFolders","TreeView","titleOf","NoteDetail","acc","setNote","links","onCancel","setRelPath","frontmatterYaml","setFrontmatterYaml","yamlStringify","setBody","onSubmit","fm","yamlParse","obj","yamlScalar","kk","vv","block","isList","isMap","parseScalar","nm","GitSyncPanel","diff","setDiff","run","onPull","onPush","onCommit","onFetch","isLocal","Pill","GitCommit","Settings","SemanticSearchPanel","sources","setSources","lastQuery","setLastQuery","onSearch","activeSources","obs","ToggleChip","ConfigPanel","cfg","setCfg","tests","setTests","testing","setTesting","onTest","Row","_h","_i","_j","_k","_l","inline","SOURCES","MemoryInner","_props","setActive","setRefreshKey","onRefreshAll","renderPanel","Memory","TIME_RANGES","rangeId","setRangeId","since","range","eventsByProject","pid","toggleProject","onExportJson","isOpen","PADDING","UsageChart","series","onHover","containerRef","tooltip","setTooltip","labels","requests","tokens","innerW","innerH","maxReq","maxTok","barW","gap","barX","barH","lineY","linePoints","leftTicks","rightTicks","labelStep","xLabels","handleMouseMove","svgX","svgY","relX","clamped","handleMouseLeave","tip","bh","bx","by","SortHeader","sortKey","sortDir","onSort","UsageTable","MiniMaxUsageInner","BarChart2","QuotaView","AnalyticsView","remains","setRemains","onboarding","setOnboarding","refreshing","setRefreshing","testResult","setTestResult","wizardStep","setWizardStep","wizardVerifying","setWizardVerifying","wizardVerifyResult","setWizardVerifyResult","keyDraft","setKeyDraft","showKey","setShowKey","savingKey","setSavingKey","dismissWizard","verifyKeyBeforeSave","clearRemainsCacheClient","saveKey","sendTest","OnboardingWizard","relativeTime","ModelQuotaCard","setRange","customFrom","setCustomFrom","customTo","setCustomTo","recent","setRecent","setSortKey","setSortDir","fromMs","toMs","params","rec","handleSort","sortedModels","av","bv","cmp","chartSeries","errors","perKey","KpiCard","fivePct","clamp","weekPct","fiveConsumed","weekConsumed","QuotaBar","remainingPct","consumedPct","used","total","resetIn","resetISO","lo","hi","setStep","verifying","verifyResult","onVerify","onSkip","onManualKeySave","CircleCheck","MiniMaxUsage","STATUS_KIND","STATUS_LABELS","BgStatusBadge","KillConfirmDialog","instanceId","instanceName","onConfirm","openKillConfirmDialog","onSuccess","TmuxAttachCard","instance","opening","setOpening","sessionName","attachCommand","copyCommand","openTerminal","POLL_INTERVAL_MS","OUTPUT_REFRESH_MS","PROMPT_TRUNCATE","formatDuration","BackgroundAgents","instances","setInstances","off","onOpenOutput","openOutputModal","onOpenTmux","openTmuxModal","onKill","BackgroundAgentCard","inst","onViewOutput","startedMs","startedLabel","durationMs","OutputModalBody","output","setOutput","available","setAvailable","refBottom","refAutoscroll","onScroll","atBottom","TmuxModalBody","copied","setCopied","onCopy","VIEW_MAP","Overview","Config","VERSION","renderActiveView","viewProps","V","mv","TokenEntryForm","onSaved","setValue","App","ToastProvider","ModalProvider","Shell","modalApi","isModalOpen","isModalOpenRef","setSnapshot","setWsStatus","bootError","setBootError","authPromptOpen","setAuthPromptOpen","searchOpen","setSearchOpen","stuckAgents","setStuckAgents","stuckBannerDismissed","setStuckBannerDismissed","modViewsReloadKey","setModViewsReloadKey","wsRef","setWs","mql","handler","retryBoot","loadBootData","applyBootData","snap","stuck","auth","resolve","retrySnap","retrySet","retryStuck","ApiError","defaultTab","offStatus","offMsg","file","exists","subscribeToWs","safeUntilRef","bump","map","activeEl","isFormControl","inForm","mergedTabs","renderedView","refreshProjects","onActivateProject","onSearchSelect","settingId","tryScroll","tries","showHeader","ViewErrorBoundary","Component","Root","isMobile","setIsMobile","MobileApp","root","createRoot","StrictMode"],"ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68],"sources":["../../../node_modules/lucide-react/dist/esm/icons/archive-restore.js","../../../node_modules/lucide-react/dist/esm/icons/arrow-down.js","../../../node_modules/lucide-react/dist/esm/icons/arrow-left.js","../../../node_modules/lucide-react/dist/esm/icons/arrow-up.js","../../../node_modules/lucide-react/dist/esm/icons/brain.js","../../../node_modules/lucide-react/dist/esm/icons/calendar.js","../../../node_modules/lucide-react/dist/esm/icons/chart-no-axes-column.js","../../../node_modules/lucide-react/dist/esm/icons/check.js","../../../node_modules/lucide-react/dist/esm/icons/chevron-left.js","../../../node_modules/lucide-react/dist/esm/icons/circle-check-big.js","../../../node_modules/lucide-react/dist/esm/icons/circle-dollar-sign.js","../../../node_modules/lucide-react/dist/esm/icons/circle-play.js","../../../node_modules/lucide-react/dist/esm/icons/circle-x.js","../../../node_modules/lucide-react/dist/esm/icons/circle.js","../../../node_modules/lucide-react/dist/esm/icons/coins.js","../../../node_modules/lucide-react/dist/esm/icons/cpu.js","../../../node_modules/lucide-react/dist/esm/icons/database.js","../../../node_modules/lucide-react/dist/esm/icons/diamond.js","../../../node_modules/lucide-react/dist/esm/icons/download.js","../../../node_modules/lucide-react/dist/esm/icons/ellipsis.js","../../../node_modules/lucide-react/dist/esm/icons/eye-off.js","../../../node_modules/lucide-react/dist/esm/icons/eye.js","../../../node_modules/lucide-react/dist/esm/icons/file-code-2.js","../../../node_modules/lucide-react/dist/esm/icons/file-code.js","../../../node_modules/lucide-react/dist/esm/icons/file-plus.js","../../../node_modules/lucide-react/dist/esm/icons/file.js","../../../node_modules/lucide-react/dist/esm/icons/filter.js","../../../node_modules/lucide-react/dist/esm/icons/folder-open.js","../../../node_modules/lucide-react/dist/esm/icons/folder-plus.js","../../../node_modules/lucide-react/dist/esm/icons/folder-search.js","../../../node_modules/lucide-react/dist/esm/icons/git-branch.js","../../../node_modules/lucide-react/dist/esm/icons/git-commit-horizontal.js","../../../node_modules/lucide-react/dist/esm/icons/git-merge.js","../../../node_modules/lucide-react/dist/esm/icons/git-pull-request.js","../../../node_modules/lucide-react/dist/esm/icons/globe.js","../../../node_modules/lucide-react/dist/esm/icons/house.js","../../../node_modules/lucide-react/dist/esm/icons/inbox.js","../../../node_modules/lucide-react/dist/esm/icons/key-round.js","../../../node_modules/lucide-react/dist/esm/icons/layers.js","../../../node_modules/lucide-react/dist/esm/icons/layout-dashboard.js","../../../node_modules/lucide-react/dist/esm/icons/layout-template.js","../../../node_modules/lucide-react/dist/esm/icons/loader-circle.js","../../../node_modules/lucide-react/dist/esm/icons/map-pin.js","../../../node_modules/lucide-react/dist/esm/icons/map.js","../../../node_modules/lucide-react/dist/esm/icons/maximize-2.js","../../../node_modules/lucide-react/dist/esm/icons/minus.js","../../../node_modules/lucide-react/dist/esm/icons/octagon-alert.js","../../../node_modules/lucide-react/dist/esm/icons/package.js","../../../node_modules/lucide-react/dist/esm/icons/palette.js","../../../node_modules/lucide-react/dist/esm/icons/panel-left-close.js","../../../node_modules/lucide-react/dist/esm/icons/panel-left-open.js","../../../node_modules/lucide-react/dist/esm/icons/panels-top-left.js","../../../node_modules/lucide-react/dist/esm/icons/pen.js","../../../node_modules/lucide-react/dist/esm/icons/plug.js","../../../node_modules/lucide-react/dist/esm/icons/power-off.js","../../../node_modules/lucide-react/dist/esm/icons/puzzle.js","../../../node_modules/lucide-react/dist/esm/icons/radio.js","../../../node_modules/lucide-react/dist/esm/icons/redo-2.js","../../../node_modules/lucide-react/dist/esm/icons/share-2.js","../../../node_modules/lucide-react/dist/esm/icons/shield-check.js","../../../node_modules/lucide-react/dist/esm/icons/shield.js","../../../node_modules/lucide-react/dist/esm/icons/square-pen.js","../../../node_modules/lucide-react/dist/esm/icons/square.js","../../../node_modules/lucide-react/dist/esm/icons/tag.js","../../../node_modules/lucide-react/dist/esm/icons/target.js","../../../node_modules/lucide-react/dist/esm/icons/undo-2.js","../../../node_modules/lucide-react/dist/esm/icons/user.js","../../../node_modules/lucide-react/dist/esm/icons/users.js","../../../node_modules/lucide-react/dist/esm/icons/zap.js","../../src/web/components/FileBrowser.tsx","../../src/web/components/Topbar.tsx","../../src/web/components/Sidebar.tsx","../../src/web/components/SearchModal.tsx","../../src/web/components/Notifications.tsx","../../src/web/components/VisualPlanDialog.tsx","../../src/web/components/ArtifactCreateDialog.tsx","../../src/web/components/ArtifactListDialog.tsx","../../src/web/components/HelpDialog.tsx","../../src/web/components/AuditDialog.tsx","../../src/web/components/CommandDialog.tsx","../../src/web/components/Card.tsx","../../src/web/views/memory/MemoryStatusCard.tsx","../../src/web/components/EmptyState.tsx","../../src/web/views/Overview.tsx","../../src/web/components/chat/SessionRowMenu.tsx","../../src/web/components/chat/AgentNode.tsx","../../src/web/components/chat/AgentTree.tsx","../../src/web/components/chat/ChatRail.tsx","../../src/web/components/chat/ChatComposer.tsx","../../src/web/components/chat/ChatInfoPanel.tsx","../../src/web/components/chat/JumpToLatest.tsx","../../src/web/views/Chat.tsx","../../src/web/components/StatusBadge.tsx","../../src/web/views/Agents.tsx","../../src/web/views/glyphs/components.tsx","../../src/web/views/glyphs/GlyphRenderer.tsx","../../src/web/views/Artifacts.tsx","../../src/web/components/Tag.tsx","../../src/web/components/tasks/BacklogPanel.tsx","../../src/web/views/Tasks.tsx","../../src/web/components/ArtifactViewer.tsx","../../src/web/views/Activity.tsx","../../src/web/components/HeadroomSettings.tsx","../../src/web/views/Settings.tsx","../../src/web/views/Mods.tsx","../../src/web/views/ModView.tsx","../../src/web/views/Schedules.tsx","../../src/web/views/Skills.tsx","../../src/web/views/memory/MemoryOverview.tsx","../../src/web/views/memory/LightragPanel.tsx","../../src/web/views/memory/ObsidianPanel.tsx","../../src/web/views/memory/GitSyncPanel.tsx","../../src/web/views/memory/SemanticSearchPanel.tsx","../../src/web/views/memory/ConfigPanel.tsx","../../src/web/views/Memory.tsx","../../src/web/views/History.tsx","../../src/web/components/UsageChart.tsx","../../src/web/components/UsageTable.tsx","../../src/web/views/MiniMaxUsage.tsx","../../src/web/components/BgStatusBadge.tsx","../../src/web/components/KillConfirmDialog.tsx","../../src/web/components/background/TmuxAttachCard.tsx","../../src/web/views/BackgroundAgents.tsx","../../src/web/App.tsx","../../src/web/main.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArchiveRestore = createLucideIcon(\"ArchiveRestore\", [\n [\"rect\", { width: \"20\", height: \"5\", x: \"2\", y: \"3\", rx: \"1\", key: \"1wp1u1\" }],\n [\"path\", { d: \"M4 8v11a2 2 0 0 0 2 2h2\", key: \"tvwodi\" }],\n [\"path\", { d: \"M20 8v11a2 2 0 0 1-2 2h-2\", key: \"1gkqxj\" }],\n [\"path\", { d: \"m9 15 3-3 3 3\", key: \"1pd0qc\" }],\n [\"path\", { d: \"M12 12v9\", key: \"192myk\" }]\n]);\n\nexport { ArchiveRestore as default };\n//# sourceMappingURL=archive-restore.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowDown = createLucideIcon(\"ArrowDown\", [\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }],\n [\"path\", { d: \"m19 12-7 7-7-7\", key: \"1idqje\" }]\n]);\n\nexport { ArrowDown as default };\n//# sourceMappingURL=arrow-down.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowLeft = createLucideIcon(\"ArrowLeft\", [\n [\"path\", { d: \"m12 19-7-7 7-7\", key: \"1l729n\" }],\n [\"path\", { d: \"M19 12H5\", key: \"x3x0zl\" }]\n]);\n\nexport { ArrowLeft as default };\n//# sourceMappingURL=arrow-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ArrowUp = createLucideIcon(\"ArrowUp\", [\n [\"path\", { d: \"m5 12 7-7 7 7\", key: \"hav0vg\" }],\n [\"path\", { d: \"M12 19V5\", key: \"x0mq9r\" }]\n]);\n\nexport { ArrowUp as default };\n//# sourceMappingURL=arrow-up.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Brain = createLucideIcon(\"Brain\", [\n [\n \"path\",\n {\n d: \"M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z\",\n key: \"l5xja\"\n }\n ],\n [\n \"path\",\n {\n d: \"M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z\",\n key: \"ep3f8r\"\n }\n ],\n [\"path\", { d: \"M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4\", key: \"1p4c4q\" }],\n [\"path\", { d: \"M17.599 6.5a3 3 0 0 0 .399-1.375\", key: \"tmeiqw\" }],\n [\"path\", { d: \"M6.003 5.125A3 3 0 0 0 6.401 6.5\", key: \"105sqy\" }],\n [\"path\", { d: \"M3.477 10.896a4 4 0 0 1 .585-.396\", key: \"ql3yin\" }],\n [\"path\", { d: \"M19.938 10.5a4 4 0 0 1 .585.396\", key: \"1qfode\" }],\n [\"path\", { d: \"M6 18a4 4 0 0 1-1.967-.516\", key: \"2e4loj\" }],\n [\"path\", { d: \"M19.967 17.484A4 4 0 0 1 18 18\", key: \"159ez6\" }]\n]);\n\nexport { Brain as default };\n//# sourceMappingURL=brain.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Calendar = createLucideIcon(\"Calendar\", [\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"4\", rx: \"2\", key: \"1hopcy\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }]\n]);\n\nexport { Calendar as default };\n//# sourceMappingURL=calendar.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChartNoAxesColumn = createLucideIcon(\"ChartNoAxesColumn\", [\n [\"line\", { x1: \"18\", x2: \"18\", y1: \"20\", y2: \"10\", key: \"1xfpm4\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"20\", y2: \"4\", key: \"be30l9\" }],\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"20\", y2: \"14\", key: \"1r4le6\" }]\n]);\n\nexport { ChartNoAxesColumn as default };\n//# sourceMappingURL=chart-no-axes-column.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Check = createLucideIcon(\"Check\", [[\"path\", { d: \"M20 6 9 17l-5-5\", key: \"1gmf2c\" }]]);\n\nexport { Check as default };\n//# sourceMappingURL=check.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ChevronLeft = createLucideIcon(\"ChevronLeft\", [\n [\"path\", { d: \"m15 18-6-6 6-6\", key: \"1wnfg3\" }]\n]);\n\nexport { ChevronLeft as default };\n//# sourceMappingURL=chevron-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleCheckBig = createLucideIcon(\"CircleCheckBig\", [\n [\"path\", { d: \"M21.801 10A10 10 0 1 1 17 3.335\", key: \"yps3ct\" }],\n [\"path\", { d: \"m9 11 3 3L22 4\", key: \"1pflzl\" }]\n]);\n\nexport { CircleCheckBig as default };\n//# sourceMappingURL=circle-check-big.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleDollarSign = createLucideIcon(\"CircleDollarSign\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\", key: \"1h4pet\" }],\n [\"path\", { d: \"M12 18V6\", key: \"zqpxq5\" }]\n]);\n\nexport { CircleDollarSign as default };\n//# sourceMappingURL=circle-dollar-sign.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CirclePlay = createLucideIcon(\"CirclePlay\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"polygon\", { points: \"10 8 16 12 10 16 10 8\", key: \"1cimsy\" }]\n]);\n\nexport { CirclePlay as default };\n//# sourceMappingURL=circle-play.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleX\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Circle = createLucideIcon(\"Circle\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }]\n]);\n\nexport { Circle as default };\n//# sourceMappingURL=circle.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Coins = createLucideIcon(\"Coins\", [\n [\"circle\", { cx: \"8\", cy: \"8\", r: \"6\", key: \"3yglwk\" }],\n [\"path\", { d: \"M18.09 10.37A6 6 0 1 1 10.34 18\", key: \"t5s6rm\" }],\n [\"path\", { d: \"M7 6h1v4\", key: \"1obek4\" }],\n [\"path\", { d: \"m16.71 13.88.7.71-2.82 2.82\", key: \"1rbuyh\" }]\n]);\n\nexport { Coins as default };\n//# sourceMappingURL=coins.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Cpu = createLucideIcon(\"Cpu\", [\n [\"rect\", { width: \"16\", height: \"16\", x: \"4\", y: \"4\", rx: \"2\", key: \"14l7u7\" }],\n [\"rect\", { width: \"6\", height: \"6\", x: \"9\", y: \"9\", rx: \"1\", key: \"5aljv4\" }],\n [\"path\", { d: \"M15 2v2\", key: \"13l42r\" }],\n [\"path\", { d: \"M15 20v2\", key: \"15mkzm\" }],\n [\"path\", { d: \"M2 15h2\", key: \"1gxd5l\" }],\n [\"path\", { d: \"M2 9h2\", key: \"1bbxkp\" }],\n [\"path\", { d: \"M20 15h2\", key: \"19e6y8\" }],\n [\"path\", { d: \"M20 9h2\", key: \"19tzq7\" }],\n [\"path\", { d: \"M9 2v2\", key: \"165o2o\" }],\n [\"path\", { d: \"M9 20v2\", key: \"i2bqo8\" }]\n]);\n\nexport { Cpu as default };\n//# sourceMappingURL=cpu.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Database = createLucideIcon(\"Database\", [\n [\"ellipse\", { cx: \"12\", cy: \"5\", rx: \"9\", ry: \"3\", key: \"msslwz\" }],\n [\"path\", { d: \"M3 5V19A9 3 0 0 0 21 19V5\", key: \"1wlel7\" }],\n [\"path\", { d: \"M3 12A9 3 0 0 0 21 12\", key: \"mv7ke4\" }]\n]);\n\nexport { Database as default };\n//# sourceMappingURL=database.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Diamond = createLucideIcon(\"Diamond\", [\n [\n \"path\",\n {\n d: \"M2.7 10.3a2.41 2.41 0 0 0 0 3.41l7.59 7.59a2.41 2.41 0 0 0 3.41 0l7.59-7.59a2.41 2.41 0 0 0 0-3.41l-7.59-7.59a2.41 2.41 0 0 0-3.41 0Z\",\n key: \"1f1r0c\"\n }\n ]\n]);\n\nexport { Diamond as default };\n//# sourceMappingURL=diamond.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Download = createLucideIcon(\"Download\", [\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"polyline\", { points: \"7 10 12 15 17 10\", key: \"2ggqvy\" }],\n [\"line\", { x1: \"12\", x2: \"12\", y1: \"15\", y2: \"3\", key: \"1vk2je\" }]\n]);\n\nexport { Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Ellipsis = createLucideIcon(\"Ellipsis\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"1\", key: \"41hilf\" }],\n [\"circle\", { cx: \"19\", cy: \"12\", r: \"1\", key: \"1wjl8i\" }],\n [\"circle\", { cx: \"5\", cy: \"12\", r: \"1\", key: \"1pcz8c\" }]\n]);\n\nexport { Ellipsis as default };\n//# sourceMappingURL=ellipsis.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst EyeOff = createLucideIcon(\"EyeOff\", [\n [\n \"path\",\n {\n d: \"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49\",\n key: \"ct8e1f\"\n }\n ],\n [\"path\", { d: \"M14.084 14.158a3 3 0 0 1-4.242-4.242\", key: \"151rxh\" }],\n [\n \"path\",\n {\n d: \"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143\",\n key: \"13bj9a\"\n }\n ],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { EyeOff as default };\n//# sourceMappingURL=eye-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Eye = createLucideIcon(\"Eye\", [\n [\n \"path\",\n {\n 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\",\n key: \"1nclc0\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }]\n]);\n\nexport { Eye as default };\n//# sourceMappingURL=eye.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileCode2 = createLucideIcon(\"FileCode2\", [\n [\"path\", { d: \"M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4\", key: \"1pf5j1\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"m5 12-3 3 3 3\", key: \"oke12k\" }],\n [\"path\", { d: \"m9 18 3-3-3-3\", key: \"112psh\" }]\n]);\n\nexport { FileCode2 as default };\n//# sourceMappingURL=file-code-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileCode = createLucideIcon(\"FileCode\", [\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z\", key: \"1mlx9k\" }]\n]);\n\nexport { FileCode as default };\n//# sourceMappingURL=file-code.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FilePlus = createLucideIcon(\"FilePlus\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M9 15h6\", key: \"cctwl0\" }],\n [\"path\", { d: \"M12 18v-6\", key: \"17g6i2\" }]\n]);\n\nexport { FilePlus as default };\n//# sourceMappingURL=file-plus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst File = createLucideIcon(\"File\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n]);\n\nexport { File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Filter = createLucideIcon(\"Filter\", [\n [\"polygon\", { points: \"22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3\", key: \"1yg77f\" }]\n]);\n\nexport { Filter as default };\n//# sourceMappingURL=filter.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderOpen = createLucideIcon(\"FolderOpen\", [\n [\n \"path\",\n {\n d: \"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H18a2 2 0 0 1 2 2v2\",\n key: \"usdka0\"\n }\n ]\n]);\n\nexport { FolderOpen as default };\n//# sourceMappingURL=folder-open.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderPlus = createLucideIcon(\"FolderPlus\", [\n [\"path\", { d: \"M12 10v6\", key: \"1bos4e\" }],\n [\"path\", { d: \"M9 13h6\", key: \"1uhe8q\" }],\n [\n \"path\",\n {\n d: \"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z\",\n key: \"1kt360\"\n }\n ]\n]);\n\nexport { FolderPlus as default };\n//# sourceMappingURL=folder-plus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FolderSearch = createLucideIcon(\"FolderSearch\", [\n [\n \"path\",\n {\n d: \"M10.7 20H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.9a2 2 0 0 1 1.69.9l.81 1.2a2 2 0 0 0 1.67.9H20a2 2 0 0 1 2 2v4.1\",\n key: \"1bw5m7\"\n }\n ],\n [\"path\", { d: \"m21 21-1.9-1.9\", key: \"1g2n9r\" }],\n [\"circle\", { cx: \"17\", cy: \"17\", r: \"3\", key: \"18b49y\" }]\n]);\n\nexport { FolderSearch as default };\n//# sourceMappingURL=folder-search.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GitBranch = createLucideIcon(\"GitBranch\", [\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"3\", y2: \"15\", key: \"17qcm7\" }],\n [\"circle\", { cx: \"18\", cy: \"6\", r: \"3\", key: \"1h7g24\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M18 9a9 9 0 0 1-9 9\", key: \"n2h4wq\" }]\n]);\n\nexport { GitBranch as default };\n//# sourceMappingURL=git-branch.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GitCommitHorizontal = createLucideIcon(\"GitCommitHorizontal\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"3\", key: \"1v7zrd\" }],\n [\"line\", { x1: \"3\", x2: \"9\", y1: \"12\", y2: \"12\", key: \"1dyftd\" }],\n [\"line\", { x1: \"15\", x2: \"21\", y1: \"12\", y2: \"12\", key: \"oup4p8\" }]\n]);\n\nexport { GitCommitHorizontal as default };\n//# sourceMappingURL=git-commit-horizontal.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GitMerge = createLucideIcon(\"GitMerge\", [\n [\"circle\", { cx: \"18\", cy: \"18\", r: \"3\", key: \"1xkwt0\" }],\n [\"circle\", { cx: \"6\", cy: \"6\", r: \"3\", key: \"1lh9wr\" }],\n [\"path\", { d: \"M6 21V9a9 9 0 0 0 9 9\", key: \"7kw0sc\" }]\n]);\n\nexport { GitMerge as default };\n//# sourceMappingURL=git-merge.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst GitPullRequest = createLucideIcon(\"GitPullRequest\", [\n [\"circle\", { cx: \"18\", cy: \"18\", r: \"3\", key: \"1xkwt0\" }],\n [\"circle\", { cx: \"6\", cy: \"6\", r: \"3\", key: \"1lh9wr\" }],\n [\"path\", { d: \"M13 6h3a2 2 0 0 1 2 2v7\", key: \"1yeb86\" }],\n [\"line\", { x1: \"6\", x2: \"6\", y1: \"9\", y2: \"21\", key: \"rroup\" }]\n]);\n\nexport { GitPullRequest as default };\n//# sourceMappingURL=git-pull-request.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Globe = createLucideIcon(\"Globe\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", key: \"13o1zl\" }],\n [\"path\", { d: \"M2 12h20\", key: \"9i4pu4\" }]\n]);\n\nexport { Globe as default };\n//# sourceMappingURL=globe.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst House = createLucideIcon(\"House\", [\n [\"path\", { d: \"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8\", key: \"5wwlr5\" }],\n [\n \"path\",\n {\n d: \"M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z\",\n key: \"1d0kgt\"\n }\n ]\n]);\n\nexport { House as default };\n//# sourceMappingURL=house.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Inbox = createLucideIcon(\"Inbox\", [\n [\"polyline\", { points: \"22 12 16 12 14 15 10 15 8 12 2 12\", key: \"o97t9d\" }],\n [\n \"path\",\n {\n d: \"M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z\",\n key: \"oot6mr\"\n }\n ]\n]);\n\nexport { Inbox as default };\n//# sourceMappingURL=inbox.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst KeyRound = createLucideIcon(\"KeyRound\", [\n [\n \"path\",\n {\n d: \"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z\",\n key: \"1s6t7t\"\n }\n ],\n [\"circle\", { cx: \"16.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"w0ekpg\" }]\n]);\n\nexport { KeyRound as default };\n//# sourceMappingURL=key-round.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Layers = createLucideIcon(\"Layers\", [\n [\n \"path\",\n {\n d: \"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z\",\n key: \"8b97xw\"\n }\n ],\n [\"path\", { d: \"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65\", key: \"dd6zsq\" }],\n [\"path\", { d: \"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65\", key: \"ep9fru\" }]\n]);\n\nexport { Layers as default };\n//# sourceMappingURL=layers.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutDashboard = createLucideIcon(\"LayoutDashboard\", [\n [\"rect\", { width: \"7\", height: \"9\", x: \"3\", y: \"3\", rx: \"1\", key: \"10lvy0\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"14\", y: \"3\", rx: \"1\", key: \"16une8\" }],\n [\"rect\", { width: \"7\", height: \"9\", x: \"14\", y: \"12\", rx: \"1\", key: \"1hutg5\" }],\n [\"rect\", { width: \"7\", height: \"5\", x: \"3\", y: \"16\", rx: \"1\", key: \"ldoo1y\" }]\n]);\n\nexport { LayoutDashboard as default };\n//# sourceMappingURL=layout-dashboard.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LayoutTemplate = createLucideIcon(\"LayoutTemplate\", [\n [\"rect\", { width: \"18\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"f1a2em\" }],\n [\"rect\", { width: \"9\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"jqznyg\" }],\n [\"rect\", { width: \"5\", height: \"7\", x: \"16\", y: \"14\", rx: \"1\", key: \"q5h2i8\" }]\n]);\n\nexport { LayoutTemplate as default };\n//# sourceMappingURL=layout-template.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst LoaderCircle = createLucideIcon(\"LoaderCircle\", [\n [\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]\n]);\n\nexport { LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst MapPin = createLucideIcon(\"MapPin\", [\n [\n \"path\",\n {\n d: \"M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0\",\n key: \"1r0f0z\"\n }\n ],\n [\"circle\", { cx: \"12\", cy: \"10\", r: \"3\", key: \"ilqhr7\" }]\n]);\n\nexport { MapPin as default };\n//# sourceMappingURL=map-pin.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Map = createLucideIcon(\"Map\", [\n [\n \"path\",\n {\n d: \"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z\",\n key: \"169xi5\"\n }\n ],\n [\"path\", { d: \"M15 5.764v15\", key: \"1pn4in\" }],\n [\"path\", { d: \"M9 3.236v15\", key: \"1uimfh\" }]\n]);\n\nexport { Map as default };\n//# sourceMappingURL=map.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Maximize2 = createLucideIcon(\"Maximize2\", [\n [\"polyline\", { points: \"15 3 21 3 21 9\", key: \"mznyad\" }],\n [\"polyline\", { points: \"9 21 3 21 3 15\", key: \"1avn1i\" }],\n [\"line\", { x1: \"21\", x2: \"14\", y1: \"3\", y2: \"10\", key: \"ota7mn\" }],\n [\"line\", { x1: \"3\", x2: \"10\", y1: \"21\", y2: \"14\", key: \"1atl0r\" }]\n]);\n\nexport { Maximize2 as default };\n//# sourceMappingURL=maximize-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Minus = createLucideIcon(\"Minus\", [[\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }]]);\n\nexport { Minus as default };\n//# sourceMappingURL=minus.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst OctagonAlert = createLucideIcon(\"OctagonAlert\", [\n [\"path\", { d: \"M12 16h.01\", key: \"1drbdi\" }],\n [\"path\", { d: \"M12 8v4\", key: \"1got3b\" }],\n [\n \"path\",\n {\n d: \"M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z\",\n key: \"1fd625\"\n }\n ]\n]);\n\nexport { OctagonAlert as default };\n//# sourceMappingURL=octagon-alert.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Package = createLucideIcon(\"Package\", [\n [\n \"path\",\n {\n d: \"M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z\",\n key: \"1a0edw\"\n }\n ],\n [\"path\", { d: \"M12 22V12\", key: \"d0xqtd\" }],\n [\"path\", { d: \"m3.3 7 7.703 4.734a2 2 0 0 0 1.994 0L20.7 7\", key: \"yx3hmr\" }],\n [\"path\", { d: \"m7.5 4.27 9 5.15\", key: \"1c824w\" }]\n]);\n\nexport { Package as default };\n//# sourceMappingURL=package.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Palette = createLucideIcon(\"Palette\", [\n [\"circle\", { cx: \"13.5\", cy: \"6.5\", r: \".5\", fill: \"currentColor\", key: \"1okk4w\" }],\n [\"circle\", { cx: \"17.5\", cy: \"10.5\", r: \".5\", fill: \"currentColor\", key: \"f64h9f\" }],\n [\"circle\", { cx: \"8.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"fotxhn\" }],\n [\"circle\", { cx: \"6.5\", cy: \"12.5\", r: \".5\", fill: \"currentColor\", key: \"qy21gx\" }],\n [\n \"path\",\n {\n d: \"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z\",\n key: \"12rzf8\"\n }\n ]\n]);\n\nexport { Palette as default };\n//# sourceMappingURL=palette.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelLeftClose = createLucideIcon(\"PanelLeftClose\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"m16 15-3-3 3-3\", key: \"14y99z\" }]\n]);\n\nexport { PanelLeftClose as default };\n//# sourceMappingURL=panel-left-close.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelLeftOpen = createLucideIcon(\"PanelLeftOpen\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"m14 9 3 3-3 3\", key: \"8010ee\" }]\n]);\n\nexport { PanelLeftOpen as default };\n//# sourceMappingURL=panel-left-open.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PanelsTopLeft = createLucideIcon(\"PanelsTopLeft\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M9 21V9\", key: \"1oto5p\" }]\n]);\n\nexport { PanelsTopLeft as default };\n//# sourceMappingURL=panels-top-left.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Pen = createLucideIcon(\"Pen\", [\n [\n \"path\",\n {\n d: \"M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z\",\n key: \"1a8usu\"\n }\n ]\n]);\n\nexport { Pen as default };\n//# sourceMappingURL=pen.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Plug = createLucideIcon(\"Plug\", [\n [\"path\", { d: \"M12 22v-5\", key: \"1ega77\" }],\n [\"path\", { d: \"M9 8V2\", key: \"14iosj\" }],\n [\"path\", { d: \"M15 8V2\", key: \"18g5xt\" }],\n [\"path\", { d: \"M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z\", key: \"osxo6l\" }]\n]);\n\nexport { Plug as default };\n//# sourceMappingURL=plug.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst PowerOff = createLucideIcon(\"PowerOff\", [\n [\"path\", { d: \"M18.36 6.64A9 9 0 0 1 20.77 15\", key: \"dxknvb\" }],\n [\"path\", { d: \"M6.16 6.16a9 9 0 1 0 12.68 12.68\", key: \"1x7qb5\" }],\n [\"path\", { d: \"M12 2v4\", key: \"3427ic\" }],\n [\"path\", { d: \"m2 2 20 20\", key: \"1ooewy\" }]\n]);\n\nexport { PowerOff as default };\n//# sourceMappingURL=power-off.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Puzzle = createLucideIcon(\"Puzzle\", [\n [\n \"path\",\n {\n d: \"M15.39 4.39a1 1 0 0 0 1.68-.474 2.5 2.5 0 1 1 3.014 3.015 1 1 0 0 0-.474 1.68l1.683 1.682a2.414 2.414 0 0 1 0 3.414L19.61 15.39a1 1 0 0 1-1.68-.474 2.5 2.5 0 1 0-3.014 3.015 1 1 0 0 1 .474 1.68l-1.683 1.682a2.414 2.414 0 0 1-3.414 0L8.61 19.61a1 1 0 0 0-1.68.474 2.5 2.5 0 1 1-3.014-3.015 1 1 0 0 0 .474-1.68l-1.683-1.682a2.414 2.414 0 0 1 0-3.414L4.39 8.61a1 1 0 0 1 1.68.474 2.5 2.5 0 1 0 3.014-3.015 1 1 0 0 1-.474-1.68l1.683-1.682a2.414 2.414 0 0 1 3.414 0z\",\n key: \"w46dr5\"\n }\n ]\n]);\n\nexport { Puzzle as default };\n//# sourceMappingURL=puzzle.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Radio = createLucideIcon(\"Radio\", [\n [\"path\", { d: \"M4.9 19.1C1 15.2 1 8.8 4.9 4.9\", key: \"1vaf9d\" }],\n [\"path\", { d: \"M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5\", key: \"u1ii0m\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"2\", key: \"1c9p78\" }],\n [\"path\", { d: \"M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5\", key: \"1j5fej\" }],\n [\"path\", { d: \"M19.1 4.9C23 8.8 23 15.1 19.1 19\", key: \"10b0cb\" }]\n]);\n\nexport { Radio as default };\n//# sourceMappingURL=radio.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Redo2 = createLucideIcon(\"Redo2\", [\n [\"path\", { d: \"m15 14 5-5-5-5\", key: \"12vg1m\" }],\n [\"path\", { d: \"M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13\", key: \"6uklza\" }]\n]);\n\nexport { Redo2 as default };\n//# sourceMappingURL=redo-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Share2 = createLucideIcon(\"Share2\", [\n [\"circle\", { cx: \"18\", cy: \"5\", r: \"3\", key: \"gq8acd\" }],\n [\"circle\", { cx: \"6\", cy: \"12\", r: \"3\", key: \"w7nqdw\" }],\n [\"circle\", { cx: \"18\", cy: \"19\", r: \"3\", key: \"1xt0gg\" }],\n [\"line\", { x1: \"8.59\", x2: \"15.42\", y1: \"13.51\", y2: \"17.49\", key: \"47mynk\" }],\n [\"line\", { x1: \"15.41\", x2: \"8.59\", y1: \"6.51\", y2: \"10.49\", key: \"1n3mei\" }]\n]);\n\nexport { Share2 as default };\n//# sourceMappingURL=share-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst ShieldCheck = createLucideIcon(\"ShieldCheck\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n]);\n\nexport { ShieldCheck as default };\n//# sourceMappingURL=shield-check.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Shield = createLucideIcon(\"Shield\", [\n [\n \"path\",\n {\n d: \"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\",\n key: \"oel41y\"\n }\n ]\n]);\n\nexport { Shield as default };\n//# sourceMappingURL=shield.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SquarePen = createLucideIcon(\"SquarePen\", [\n [\"path\", { d: \"M12 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\", key: \"1m0v6g\" }],\n [\n \"path\",\n {\n d: \"M18.375 2.625a1 1 0 0 1 3 3l-9.013 9.014a2 2 0 0 1-.853.505l-2.873.84a.5.5 0 0 1-.62-.62l.84-2.873a2 2 0 0 1 .506-.852z\",\n key: \"ohrbg2\"\n }\n ]\n]);\n\nexport { SquarePen as default };\n//# sourceMappingURL=square-pen.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Square = createLucideIcon(\"Square\", [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n]);\n\nexport { Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Tag = createLucideIcon(\"Tag\", [\n [\n \"path\",\n {\n d: \"M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z\",\n key: \"vktsd0\"\n }\n ],\n [\"circle\", { cx: \"7.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"kqv944\" }]\n]);\n\nexport { Tag as default };\n//# sourceMappingURL=tag.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Target = createLucideIcon(\"Target\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"6\", key: \"1vlfrh\" }],\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"2\", key: \"1c9p78\" }]\n]);\n\nexport { Target as default };\n//# sourceMappingURL=target.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Undo2 = createLucideIcon(\"Undo2\", [\n [\"path\", { d: \"M9 14 4 9l5-5\", key: \"102s5s\" }],\n [\"path\", { d: \"M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11\", key: \"f3b9sd\" }]\n]);\n\nexport { Undo2 as default };\n//# sourceMappingURL=undo-2.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst User = createLucideIcon(\"User\", [\n [\"path\", { d: \"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2\", key: \"975kel\" }],\n [\"circle\", { cx: \"12\", cy: \"7\", r: \"4\", key: \"17ys0d\" }]\n]);\n\nexport { User as default };\n//# sourceMappingURL=user.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Users = createLucideIcon(\"Users\", [\n [\"path\", { d: \"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\", key: \"1yyitq\" }],\n [\"circle\", { cx: \"9\", cy: \"7\", r: \"4\", key: \"nufk8\" }],\n [\"path\", { d: \"M22 21v-2a4 4 0 0 0-3-3.87\", key: \"kshegd\" }],\n [\"path\", { d: \"M16 3.13a4 4 0 0 1 0 7.75\", key: \"1da9ce\" }]\n]);\n\nexport { Users as default };\n//# sourceMappingURL=users.js.map\n","/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst Zap = createLucideIcon(\"Zap\", [\n [\n \"path\",\n {\n d: \"M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z\",\n key: \"1xq2db\"\n }\n ]\n]);\n\nexport { Zap as default };\n//# sourceMappingURL=zap.js.map\n","// src/components/FileBrowser.tsx — Interactive directory browser with tree + flat pane.\n// Replaces raw path text inputs in Add Project dialogs.\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { ChevronRight, ChevronDown, FolderOpen, Folder, File, RefreshCw, ArrowLeft, Home, AlertCircle, FolderPlus } from 'lucide-react';\nimport { api } from '../lib/api';\nimport type { DirectoryEntry, DirectoryListing, MkdirRequest, MkdirResponse } from '../lib/types';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type FileBrowserProps = {\n /** Currently selected directory (absolute path). */\n value: string;\n /** Fires when the user selects a directory. */\n onChange: (path: string) => void;\n /** Where the browser starts (default: homedir via GET /api/fs with no path). */\n initialPath?: string;\n /** If set, used as default initialPath and shown as a quick-jump chip. */\n projectsDirectory?: string;\n /** Label for the filesystem-root breadcrumb (default: \"Home\"). */\n rootLabel?: string;\n /** Scroll viewport height in px (default: 360). */\n height?: number;\n};\n\n// ─── Cache (LRU-ish, 200 entries max, 5-minute TTL) ───────────────────────────\n\nconst MAX_CACHE = 200;\nconst TTL_MS = 5 * 60 * 1000;\n\ntype CacheEntry = { data: DirectoryListing; ts: number };\n\nconst _cache = new Map<string, CacheEntry>();\n\nfunction cacheGet(path: string): DirectoryListing | null {\n const entry = _cache.get(path);\n if (!entry) return null;\n if (Date.now() - entry.ts > TTL_MS) { _cache.delete(path); return null; }\n return entry.data;\n}\n\nfunction cacheSet(path: string, data: DirectoryListing) {\n if (_cache.size >= MAX_CACHE) {\n // Evict oldest 50\n const oldest = [..._cache.entries()]\n .sort((a, b) => a[1].ts - b[1].ts)\n .slice(0, 50)\n .map(([k]) => k);\n oldest.forEach((k) => _cache.delete(k));\n }\n _cache.set(path, { data, ts: Date.now() });\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction pathSegments(p: string): { label: string; path: string }[] {\n if (!p || p === '/') return [{ label: '/', path: '/' }];\n const parts = p.split('/').filter(Boolean);\n const result: { label: string; path: string }[] = [];\n let accumulated = '';\n for (let i = 0; i < parts.length; i++) {\n accumulated += '/' + parts[i];\n result.push({ label: parts[i], path: accumulated });\n }\n return result;\n}\n\nfunction sortEntries(entries: DirectoryEntry[]): DirectoryEntry[] {\n return [...entries].sort((a, b) => {\n if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;\n return a.name.localeCompare(b.name, undefined, { sensitivity: 'base' });\n });\n}\n\n/**\n * Validates a directory name against the same denylist the server enforces.\n * Returns an ok object or { ok: false, reason }.\n * Mirrors the validation in POST /api/fs/mkdir on the server side.\n */\nexport function validateDirName(name: string): { ok: true } | { ok: false; reason: string } {\n const trimmed = name.trim();\n if (!trimmed) return { ok: false, reason: 'Name cannot be empty.' };\n if (trimmed !== name) return { ok: false, reason: 'Name cannot have leading or trailing whitespace.' };\n if (trimmed === '.') return { ok: false, reason: \"Name cannot be '.'.\" };\n if (trimmed === '..') return { ok: false, reason: \"Name cannot be '..'.\" };\n if (trimmed.startsWith('-')) return { ok: false, reason: \"Name cannot start with '-'.\" };\n if (trimmed.length > 255) return { ok: false, reason: 'Name cannot be longer than 255 characters.' };\n if (/[/\\0:*?\"<>|]/.test(trimmed)) {\n return { ok: false, reason: \"Name cannot contain / \\\\ : * ? \\\" < > |\" };\n }\n return { ok: true };\n}\n\n// ─── Component ─────────────────────────────────────────────────────────────────\n\nexport function FileBrowser({\n value,\n onChange,\n initialPath,\n projectsDirectory,\n rootLabel = 'Home',\n height = 360,\n}: FileBrowserProps) {\n const [currentPath, setCurrentPath] = useState<string>(\n initialPath ?? projectsDirectory ?? '',\n );\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [selectedRow, setSelectedRow] = useState<number>(-1);\n const [listing, setListing] = useState<DirectoryListing | null>(null);\n const [childrenMap, setChildrenMap] = useState<Record<string, DirectoryEntry[]>>({});\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [mkdirOpen, setMkdirOpen] = useState(false);\n const [mkdirName, setMkdirName] = useState('');\n const [mkdirError, setMkdirError] = useState<string | null>(null);\n const [mkdirLoading, setMkdirLoading] = useState(false);\n const mkdirInputRef = useRef<HTMLInputElement | null>(null);\n\n const fetchListing = useCallback(async (path: string): Promise<DirectoryListing | null> => {\n try {\n const cached = cacheGet(path);\n if (cached) return cached;\n const data = await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n cacheSet(path, data);\n return data;\n } catch {\n return null;\n }\n }, []);\n\n const load = useCallback(async (path: string) => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n cacheSet(path, data);\n setListing(data);\n setSelectedRow(-1);\n } catch (err) {\n const msg = (err as { data?: { message?: string }; message?: string }).data?.message\n ?? (err as Error).message\n ?? 'Failed to load directory';\n setError(msg);\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Load current path on mount or when currentPath changes\n useEffect(() => {\n if (!currentPath) {\n // Default to homedir by fetching empty-path listing\n api.get<DirectoryListing>('/fs').then((data) => {\n cacheSet('', data);\n setListing(data);\n setCurrentPath(data.path);\n if (data.path !== value) onChange(data.path);\n }).catch(() => {\n setError('Could not determine home directory.');\n setLoading(false);\n });\n } else {\n load(currentPath);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [currentPath]);\n\n // Keep selected path in sync when value changes externally (e.g. breadcrumb click)\n useEffect(() => {\n if (value && value !== currentPath) {\n setCurrentPath(value);\n }\n }, [value]);\n\n const entries = listing ? sortEntries(listing.entries) : [];\n\n const dirs = entries.filter((e) => e.isDir);\n const allEntries = entries;\n\n // ─── Navigation helpers ──────────────────────────────────────────────────────\n\n const navigateInto = (entry: DirectoryEntry) => {\n if (!entry.isDir) return;\n setCurrentPath(entry.path);\n onChange(entry.path);\n };\n\n const navigateUp = () => {\n if (!listing?.parent) return;\n setCurrentPath(listing.parent);\n onChange(listing.parent);\n };\n\n const navigateTo = (path: string) => {\n if (path === currentPath) return;\n setCurrentPath(path);\n onChange(path);\n };\n\n const goHome = async () => {\n const home = await fetchListing('');\n if (home) {\n setCurrentPath(home.path);\n onChange(home.path);\n }\n };\n\n const goProjects = async () => {\n if (!projectsDirectory) return;\n const pd = await fetchListing(projectsDirectory);\n if (pd) {\n setCurrentPath(pd.path);\n onChange(pd.path);\n }\n };\n\n // ─── New folder ────────────────────────────────────────────────────────────\n\n // Open the inline mkdir input, focusing it on the next tick\n const openMkdir = () => {\n setMkdirOpen(true);\n setMkdirName('');\n setMkdirError(null);\n // Autofocus after the input renders\n setTimeout(() => mkdirInputRef.current?.focus(), 0);\n };\n\n const cancelMkdir = () => {\n setMkdirOpen(false);\n setMkdirName('');\n setMkdirError(null);\n };\n\n const submitMkdir = async () => {\n const v = validateDirName(mkdirName);\n if (!v.ok) {\n setMkdirError(v.reason);\n return;\n }\n setMkdirLoading(true);\n setMkdirError(null);\n try {\n const result = await api.post<MkdirResponse>('/fs/mkdir', {\n parent: currentPath,\n name: mkdirName.trim(),\n } as MkdirRequest);\n // Invalidate cache for the current path so the new folder appears\n _cache.delete(currentPath);\n await load(currentPath);\n // Select the new directory\n onChange(result.path);\n setMkdirOpen(false);\n setMkdirName('');\n } catch (err) {\n const apiErr = err as { data?: { message?: string }; status?: number };\n if (apiErr.status === 409) {\n setMkdirError(`A folder named \"${mkdirName.trim()}\" already exists.`);\n } else {\n setMkdirError(\n apiErr.data?.message ??\n (err as Error).message ??\n 'Failed to create folder.',\n );\n }\n } finally {\n setMkdirLoading(false);\n }\n };\n\n const handleMkdirKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n submitMkdir();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n cancelMkdir();\n }\n };\n\n const toggleExpand = (path: string) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (next.has(path)) next.delete(path);\n else next.add(path);\n return next;\n });\n // Lazy-load children when expanding\n if (!childrenMap[path]) {\n fetchListing(path).then((data) => {\n if (data) setChildrenMap((prev) => ({ ...prev, [path]: data.entries.filter((e) => e.isDir) }));\n });\n }\n };\n\n // ─── Keyboard handler ────────────────────────────────────────────────────────\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (!listing) return;\n const dirs = allEntries.filter((x) => x.isDir);\n const files = allEntries.filter((x) => !x.isDir);\n const selectable = [...dirs, ...files];\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedRow((r) => Math.min(r + 1, selectable.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedRow((r) => Math.max(r - 1, 0));\n } else if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n const sel = selectable[selectedRow];\n if (sel) {\n if (e.key === 'Enter' && sel.isDir) navigateInto(sel);\n else if (!sel.isDir) { /* files are not selectable */ }\n else onChange(sel.path);\n }\n } else if (e.key === 'Backspace') {\n e.preventDefault();\n navigateUp();\n }\n };\n\n // ─── Render ─────────────────────────────────────────────────────────────────\n\n const segments = pathSegments(listing?.path ?? currentPath ?? '/');\n const parentPath = listing?.parent;\n const canGoUp = parentPath !== null && parentPath !== undefined;\n\n const basename = currentPath.split('/').filter(Boolean).at(-1) ?? '/';\n\n return (\n <div className=\"file-browser\" onKeyDown={handleKeyDown} tabIndex={-1}>\n {/* Breadcrumb */}\n <div className=\"file-browser-breadcrumb\" role=\"navigation\" aria-label=\"Path breadcrumb\">\n {segments.map((seg, i) => (\n <span key={seg.path} className=\"file-browser-breadcrumb-item\">\n {i > 0 && <span className=\"file-browser-breadcrumb-sep\" aria-hidden>/</span>}\n <button\n type=\"button\"\n className=\"file-browser-breadcrumb-btn\"\n onClick={() => navigateTo(seg.path)}\n title={seg.path}\n >\n {i === 0 ? (seg.path === '/' ? '/' : rootLabel) : seg.label}\n </button>\n </span>\n ))}\n </div>\n\n {/* Toolbar */}\n <div className=\"file-browser-toolbar\">\n <div className=\"file-browser-toolbar-left\">\n <button\n type=\"button\"\n className=\"file-browser-tool-btn\"\n onClick={navigateUp}\n disabled={!canGoUp}\n title=\"Go up (Backspace)\"\n aria-label=\"Go up one level\"\n >\n <ArrowLeft size={13} />\n </button>\n\n <button\n type=\"button\"\n className=\"file-browser-tool-btn\"\n onClick={() => load(currentPath)}\n disabled={loading}\n title=\"Refresh\"\n aria-label=\"Refresh\"\n >\n <RefreshCw size={13} className={loading ? 'spin' : ''} />\n </button>\n\n <button\n type=\"button\"\n className=\"file-browser-tool-btn\"\n onClick={openMkdir}\n title=\"New folder\"\n aria-label=\"Create new folder\"\n >\n <FolderPlus size={13} />\n </button>\n\n <div className=\"file-browser-chips\">\n <button type=\"button\" className=\"file-browser-chip\" onClick={goHome}>\n <Home size={11} /> {rootLabel}\n </button>\n {projectsDirectory && (\n <button type=\"button\" className=\"file-browser-chip\" onClick={goProjects} title={projectsDirectory}>\n <FolderOpen size={11} /> {projectsDirectory.split('/').filter(Boolean).at(-1) ?? 'Projects'}\n </button>\n )}\n </div>\n </div>\n\n {mkdirOpen ? (\n <div className=\"file-browser-mkdir\">\n <input\n ref={mkdirInputRef}\n type=\"text\"\n className=\"file-browser-mkdir-input\"\n placeholder=\"Folder name\"\n value={mkdirName}\n onChange={(e) => {\n setMkdirName(e.target.value);\n setMkdirError(null);\n }}\n onKeyDown={handleMkdirKeyDown}\n aria-label=\"New folder name\"\n aria-invalid={mkdirError ? 'true' : undefined}\n aria-describedby={mkdirError ? 'mkdir-error' : undefined}\n disabled={mkdirLoading}\n maxLength={255}\n />\n {mkdirError ? (\n <span id=\"mkdir-error\" className=\"file-browser-mkdir-error\" role=\"alert\">\n {mkdirError}\n </span>\n ) : (\n <span className=\"file-browser-mkdir-hint\">\n Enter to create, Esc to cancel\n </span>\n )}\n </div>\n ) : (\n <span className=\"file-browser-count-hint\">\n {loading ? '…' : `${entries.length} in ${basename}`}\n </span>\n )}\n </div>\n\n {/* Error banner */}\n {error && (\n <div className=\"file-browser-error\">\n <AlertCircle size={13} />\n <span>{error}</span>\n <button type=\"button\" className=\"file-browser-retry\" onClick={() => load(currentPath)}>\n Retry\n </button>\n </div>\n )}\n\n {/* Body: tree (left) + flat (right) */}\n <div className=\"file-browser-body\" style={{ height }}>\n {/* Left: tree */}\n <div className=\"file-browser-pane file-browser-tree\" aria-label=\"Folder tree\">\n {loading && !listing ? (\n <TreeSkeleton />\n ) : (\n <TreeNode\n path={currentPath}\n entries={dirs}\n expanded={expanded}\n childrenMap={childrenMap}\n onToggle={toggleExpand}\n onNavigate={navigateInto}\n level={0}\n />\n )}\n </div>\n\n {/* Right: flat listing */}\n <div className=\"file-browser-pane file-browser-flat\" aria-label=\"Directory contents\">\n <div className=\"file-browser-flat-header\">\n <span>Name</span>\n <span>Type</span>\n </div>\n\n {loading && !listing ? (\n <FlatSkeleton />\n ) : (\n <>\n {/* Truncation notice */}\n {listing?.truncated && (\n <div className=\"file-browser-truncated-banner\" role=\"status\">\n Showing first 500 of {listing.totalEntries} entries.\n Navigate into a subfolder to see more.\n </div>\n )}\n\n {allEntries.length === 0 ? (\n <div className=\"file-browser-empty\">This folder is empty</div>\n ) : (\n <div className=\"file-browser-flat-list\">\n {allEntries.map((entry, idx) => {\n const isDir = entry.isDir;\n const isSelected = idx === selectedRow;\n const isActive = entry.path === value;\n return (\n <div\n key={entry.path}\n role=\"option\"\n aria-selected={isActive}\n className={[\n 'file-browser-row',\n isDir ? 'file-browser-row--dir' : 'file-browser-row--file',\n isSelected && 'file-browser-row--selected',\n isActive && isDir && 'file-browser-row--active',\n !isDir && 'file-browser-row--disabled',\n ].filter(Boolean).join(' ')}\n onClick={() => {\n if (isDir) {\n setSelectedRow(idx);\n onChange(entry.path);\n }\n }}\n onDoubleClick={() => {\n if (isDir) navigateInto(entry);\n }}\n title={entry.path}\n >\n <span className=\"file-browser-row-icon\">\n {isDir ? <Folder size={13} /> : <File size={13} />}\n </span>\n <span className=\"file-browser-row-name\">{entry.name}</span>\n <span className=\"file-browser-row-type\">\n {isDir ? 'Folder' : ''}\n </span>\n </div>\n );\n })}\n </div>\n )}\n </>\n )}\n </div>\n </div>\n\n {/* Footer hint */}\n <div className=\"file-browser-footer-hint\">\n Select a folder, then click Add. Use <kbd>↑</kbd> <kbd>↓</kbd> to navigate, <kbd>Enter</kbd> to confirm.\n </div>\n </div>\n );\n}\n\n// ─── TreeNode ─────────────────────────────────────────────────────────────────\n\nfunction TreeNode({\n path,\n entries,\n expanded,\n childrenMap,\n onToggle,\n onNavigate,\n level,\n}: {\n path: string;\n entries: DirectoryEntry[];\n expanded: Set<string>;\n childrenMap: Record<string, DirectoryEntry[]>;\n onToggle: (p: string) => void;\n onNavigate: (e: DirectoryEntry) => void;\n level: number;\n}) {\n return (\n <ul className=\"file-browser-tree-list\" role=\"group\">\n {entries.map((entry) => {\n const isExpanded = expanded.has(entry.path);\n const kids = childrenMap[entry.path] ?? [];\n return (\n <li key={entry.path} className=\"file-browser-tree-node\">\n <div\n className={[\n 'file-browser-tree-row',\n isExpanded && 'file-browser-tree-row--expanded',\n ].filter(Boolean).join(' ')}\n style={{ paddingLeft: `${level * 16 + 8}px` }}\n >\n <button\n type=\"button\"\n className=\"file-browser-tree-toggle\"\n onClick={(e) => { e.stopPropagation(); onToggle(entry.path); }}\n aria-label={isExpanded ? 'Collapse' : 'Expand'}\n >\n {kids.length > 0 || true ? (\n isExpanded ? <ChevronDown size={11} /> : <ChevronRight size={11} />\n ) : (\n <span style={{ width: 11 }} />\n )}\n </button>\n\n <button\n type=\"button\"\n className=\"file-browser-tree-name\"\n onClick={() => onNavigate(entry)}\n title={entry.path}\n >\n <Folder size={12} />\n <span>{entry.name}</span>\n </button>\n </div>\n\n {isExpanded && kids.length > 0 && (\n <TreeNode\n path={entry.path}\n entries={kids}\n expanded={expanded}\n childrenMap={childrenMap}\n onToggle={onToggle}\n onNavigate={onNavigate}\n level={level + 1}\n />\n )}\n </li>\n );\n })}\n </ul>\n );\n}\n\n// ─── Skeletons ────────────────────────────────────────────────────────────────\n\nfunction TreeSkeleton() {\n return (\n <div className=\"file-browser-skeleton-wrap\">\n {[80, 60, 90, 55, 70].map((w, i) => (\n <div key={i} className=\"file-browser-skeleton-row\" style={{ width: w }} />\n ))}\n </div>\n );\n}\n\nfunction FlatSkeleton() {\n return (\n <div className=\"file-browser-skeleton-wrap\">\n {[60, 90, 70, 50, 80, 65].map((w, i) => (\n <div key={i} className=\"file-browser-skeleton-row\" style={{ width: w }} />\n ))}\n </div>\n );\n}\n","// src/components/Topbar.tsx — header with brand, project selector, search, tabs, ws status.\nimport { useEffect, useState } from 'react';\nimport type { ReactNode } from 'react';\nimport {\n LayoutDashboard,\n MessageSquare,\n Bot,\n Map,\n Folder,\n CheckSquare,\n Settings2,\n Sliders,\n Puzzle,\n Clock,\n History as HistoryIcon,\n Search as SearchIcon,\n ChevronDown,\n Plus,\n RefreshCw,\n Power,\n Sparkles,\n Activity,\n Radio,\n Coins,\n Brain,\n type LucideIcon,\n} from 'lucide-react';\nimport { cn } from '../lib/utils';\nimport type { ProjectRecord, WsStatus, WsMessage, Settings, DirectoryListing } from '../lib/types';\nimport { api } from '../lib/api';\nimport { useModal } from './Modal';\nimport { FileBrowser } from './FileBrowser';\nimport { Button } from './Button';\n\nexport type TabDef = {\n id: string;\n label: string;\n icon: LucideIcon;\n};\n\nexport const TABS: TabDef[] = [\n { id: 'overview', label: 'Overview', icon: LayoutDashboard },\n { id: 'chat', label: 'Chat', icon: MessageSquare },\n { id: 'agents', label: 'Agents', icon: Bot },\n { id: 'artifacts', label: 'Glyphs', icon: Map },\n { id: 'tasks', label: 'Tasks', icon: CheckSquare },\n { id: 'activity', label: 'Activity', icon: Activity },\n { id: 'background', label: 'Active', icon: Radio },\n { id: 'skills', label: 'Skills', icon: Sparkles },\n { id: 'memory', label: 'Memory', icon: Brain },\n { id: 'mods', label: 'Mods', icon: Puzzle },\n { id: 'schedules', label: 'Schedules', icon: Clock },\n { id: 'history', label: 'History', icon: HistoryIcon },\n { id: 'minimax', label: 'Usage', icon: Coins },\n { id: 'settings', label: 'Settings', icon: Sliders },\n];\n\nexport type TopbarProps = {\n activeTab: string;\n onTabChange: (id: string) => void;\n wsStatus: WsStatus;\n version: string;\n activeProject: ProjectRecord | null;\n projects: ProjectRecord[];\n onProjectChange: (id: string) => void;\n onProjectsRefresh: () => void;\n onOpenSearch: () => void;\n settings?: Settings | null;\n rightSlot?: ReactNode;\n /**\n * v3.3.0 — Optional slot for the notifications bell. The host\n * (App.tsx) mounts the Notifications component here so it can\n * subscribe to the same WebSocket the rest of the app uses.\n */\n notificationsSlot?: ReactNode;\n /**\n * Whether to render the tabs row. In sidebar/both layouts the sidebar\n * carries navigation, so we hide this row to keep the topbar slim.\n */\n showTabs?: boolean;\n /**\n * v3.20.3 — Optional extra tabs (mod views) appended after the built-in\n * tabs. Each entry is the same shape as TabDef with an `id` matching\n * the mod view id (e.g. 'graphify:web').\n */\n extraTabs?: TabDef[];\n};\n\nexport function Topbar({\n activeTab,\n onTabChange,\n wsStatus,\n version,\n activeProject,\n projects,\n onProjectChange,\n onProjectsRefresh,\n onOpenSearch,\n settings,\n rightSlot,\n notificationsSlot,\n showTabs = true,\n extraTabs,\n}: TopbarProps) {\n return (\n <header className=\"topbar\">\n <div className=\"topbar-row\">\n <div className=\"brand\">\n <span className=\"brand-logo\" aria-hidden=\"true\">ᛒ</span>\n <span className=\"brand-title\">Bizar</span>\n <span className=\"brand-version\">{version}</span>\n </div>\n <ProjectSelector\n activeProject={activeProject}\n projects={projects}\n onChange={onProjectChange}\n onRefresh={onProjectsRefresh}\n settings={settings ?? null}\n />\n <button\n type=\"button\"\n className=\"topbar-search\"\n onClick={onOpenSearch}\n title=\"Search (Ctrl/Cmd+K)\"\n aria-label=\"Open search\"\n >\n <SearchIcon size={14} />\n <span className=\"muted\">Search…</span>\n <kbd>⌘K</kbd>\n </button>\n <div className=\"topbar-spacer\" />\n <div className=\"topbar-right\">\n {notificationsSlot}\n {rightSlot}\n <div className={cn('ws-status', `ws-${wsStatus}`)} title={`WebSocket: ${wsStatus}`}>\n <span className=\"ws-dot\" />\n <span className=\"ws-label\">{wsStatus}</span>\n </div>\n </div>\n </div>\n {showTabs && (\n <nav className=\"tabs-row\" role=\"tablist\" aria-label=\"Primary tabs\">\n {TABS.map((tab) => {\n const Icon = tab.icon;\n const active = tab.id === activeTab;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('tab', active && 'tab-active')}\n onClick={() => onTabChange(tab.id)}\n title={tab.label}\n >\n <Icon size={14} className=\"tab-icon\" />\n <span className=\"tab-label\">{tab.label}</span>\n </button>\n );\n })}\n {extraTabs && extraTabs.length > 0 && (\n <>\n <span className=\"tab-separator\" aria-hidden=\"true\" />\n {extraTabs.map((tab) => {\n const Icon = tab.icon;\n const active = tab.id === activeTab;\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('tab', 'tab-mod', active && 'tab-active')}\n onClick={() => onTabChange(tab.id)}\n title={`${tab.label} (mod)`}\n >\n <Icon size={14} className=\"tab-icon\" />\n <span className=\"tab-label\">{tab.label}</span>\n <span className=\"tab-badge\">mod</span>\n </button>\n );\n })}\n </>\n )}\n </nav>\n )}\n </header>\n );\n}\n\nfunction ProjectSelector({\n activeProject,\n projects,\n onChange,\n onRefresh,\n settings,\n}: {\n activeProject: ProjectRecord | null;\n projects: ProjectRecord[];\n onChange: (id: string) => void;\n onRefresh: () => void;\n settings: Settings | null;\n}) {\n const [open, setOpen] = useState(false);\n const modal = useModal();\n\n useEffect(() => {\n if (!open) return;\n const onClick = () => setOpen(false);\n document.addEventListener('click', onClick);\n return () => document.removeEventListener('click', onClick);\n }, [open]);\n\n const onAdd = () => {\n modal.open({\n title: 'Add project',\n children: (\n <TopbarAddProjectDialog\n settings={settings}\n onAdd={async (path: string, name: string | null) => {\n try {\n await api.post('/projects', { path, name });\n onRefresh();\n setOpen(false);\n modal.close();\n } catch (err) {\n alert(`Add failed: ${(err as Error).message}`);\n }\n }}\n />\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n </div>\n ),\n });\n };\n\n return (\n <div className=\"project-selector\" onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n className=\"project-selector-btn\"\n onClick={() => setOpen((v) => !v)}\n title=\"Switch active project\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n >\n <Folder size={14} />\n <span className=\"project-selector-name\">\n {activeProject?.name || '(no project)'}\n </span>\n <ChevronDown size={12} />\n </button>\n {open && (\n <div className=\"project-selector-menu\">\n <div className=\"project-selector-menu-head\">\n <span className=\"muted\">{projects.length} project{projects.length === 1 ? '' : 's'}</span>\n <div className=\"project-selector-menu-actions\">\n <button type=\"button\" className=\"icon-btn\" onClick={onRefresh} title=\"Refresh\" aria-label=\"Refresh projects\">\n <RefreshCw size={12} />\n </button>\n <button type=\"button\" className=\"icon-btn\" onClick={onAdd} title=\"Add project\" aria-label=\"Add project\">\n <Plus size={12} />\n </button>\n </div>\n </div>\n <ul className=\"project-selector-list\">\n {projects.length === 0 && (\n <li className=\"muted project-selector-empty\">No projects. Add one to start.</li>\n )}\n {projects.map((p) => (\n <li key={p.id}>\n <button\n type=\"button\"\n className={cn('project-selector-item', activeProject?.id === p.id && 'active')}\n onClick={() => {\n onChange(p.id);\n setOpen(false);\n }}\n >\n <span className=\"project-selector-item-name\">{p.name}</span>\n <span className=\"project-selector-item-status\">{p.status}</span>\n </button>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n\n// ─── TopbarAddProjectDialog ───────────────────────────────────────────────────\n\nfunction TopbarAddProjectDialog({\n settings,\n onAdd,\n}: {\n settings: Settings | null;\n onAdd: (path: string, name: string | null) => void;\n}) {\n const [path, setPath] = useState(settings?.dashboard?.projectsDirectory ?? '');\n const [name, setName] = useState('');\n const [preflighting, setPreflighting] = useState(false);\n const [preflightError, setPreflightError] = useState<string | null>(null);\n\n const handleAdd = async () => {\n if (!path) return;\n setPreflighting(true);\n setPreflightError(null);\n try {\n // Pre-flight: verify the path still exists\n await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n onAdd(path, name || null);\n } catch (err) {\n const apiErr = err as { status?: number; data?: { message?: string } };\n if (apiErr.status === 404) {\n setPreflightError('That folder no longer exists. Pick another.');\n } else {\n setPreflightError(\n apiErr.data?.message ?? (err as Error).message ?? 'Validation failed.',\n );\n }\n } finally {\n setPreflighting(false);\n }\n };\n\n return (\n <div>\n <label className=\"field-label\">Folder</label>\n <FileBrowser\n value={path}\n onChange={(p) => {\n setPath(p);\n setPreflightError(null);\n }}\n projectsDirectory={settings?.dashboard?.projectsDirectory}\n height={320}\n />\n {preflightError && (\n <p className=\"field-help\" style={{ color: 'var(--error)', marginTop: 4 }}>\n {preflightError}\n </p>\n )}\n <div style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"topbar-add-project-name\">Name (optional)</label>\n <input\n id=\"topbar-add-project-name\"\n className=\"input\"\n type=\"text\"\n placeholder=\"My App\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n </div>\n <div style={{ marginTop: 'var(--space-3)', display: 'flex', justifyContent: 'flex-end' }}>\n <Button\n variant=\"primary\"\n onClick={handleAdd}\n disabled={!path || preflighting}\n >\n {preflighting ? <span className=\"btn-spinner\" /> : null}\n {preflighting ? 'Checking…' : 'Add'}\n </Button>\n </div>\n </div>\n );\n}\n","// src/components/Sidebar.tsx — vertical navigation rail for sidebar/both layouts.\nimport type { TabDef } from './Topbar';\nimport { cn } from '../lib/utils';\n\nexport type SidebarProps = {\n tabs: TabDef[];\n activeTab: string;\n onTabChange: (id: string) => void;\n};\n\nexport function Sidebar({ tabs, activeTab, onTabChange }: SidebarProps) {\n // Split tabs into built-in (no `isMod` flag) and mod-added entries.\n // Render a separator + small \"Mods\" label between them so users can\n // tell what's part of Bizar vs what an installed mod contributed.\n const builtIn = tabs.filter((t) => !(t as TabDef & { isMod?: boolean }).isMod);\n const modTabs = tabs.filter((t) => (t as TabDef & { isMod?: boolean }).isMod);\n\n return (\n <aside className=\"sidebar\" aria-label=\"Primary navigation\">\n <nav className=\"sidebar-nav\" role=\"tablist\">\n {builtIn.map((t) => {\n const Icon = t.icon;\n const active = t.id === activeTab;\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('sidebar-tab', active && 'sidebar-tab-active')}\n onClick={() => onTabChange(t.id)}\n title={t.label}\n >\n <Icon size={18} aria-hidden />\n <span className=\"sidebar-tab-label\">{t.label}</span>\n </button>\n );\n })}\n {modTabs.length > 0 && (\n <>\n <div className=\"sidebar-section-divider\" aria-hidden=\"true\" />\n <div className=\"sidebar-section-label\">Mods</div>\n {modTabs.map((t) => {\n const Icon = t.icon;\n const active = t.id === activeTab;\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n className={cn('sidebar-tab', 'sidebar-tab-mod', active && 'sidebar-tab-active')}\n onClick={() => onTabChange(t.id)}\n title={`${t.label} (mod)`}\n >\n <Icon size={18} aria-hidden />\n <span className=\"sidebar-tab-label\">{t.label}</span>\n </button>\n );\n })}\n </>\n )}\n </nav>\n </aside>\n );\n}\n","// src/components/SearchModal.tsx — fuzzy search modal opened by / or Cmd/Ctrl+K.\nimport { useEffect, useRef, useState } from 'react';\nimport { Search, X } from 'lucide-react';\nimport { useToast } from './Toast';\nimport { api } from '../lib/api';\nimport type { SearchResult } from '../lib/types';\nimport { cn } from '../lib/utils';\n\ntype Props = {\n open: boolean;\n onClose: () => void;\n onSelect: (r: SearchResult) => void;\n};\n\nconst SCOPES = [\n { id: 'all', label: 'All' },\n { id: 'projects', label: 'Projects' },\n { id: 'agents', label: 'Agents' },\n { id: 'tasks', label: 'Tasks' },\n { id: 'mods', label: 'Mods' },\n { id: 'schedules', label: 'Schedules' },\n { id: 'commands', label: 'Commands' },\n { id: 'settings', label: 'Settings' },\n] as const;\n\nconst RESULT_TYPE_BY_SCOPE: Record<(typeof SCOPES)[number]['id'], string | null> = {\n all: null,\n projects: 'project',\n agents: 'agent',\n tasks: 'task',\n mods: 'mod',\n schedules: 'schedule',\n commands: 'command',\n settings: 'setting',\n};\n\nexport function SearchModal({ open, onClose, onSelect }: Props) {\n const toast = useToast();\n const [q, setQ] = useState('');\n const [scope, setScope] = useState<typeof SCOPES[number]['id']>('all');\n const [results, setResults] = useState<SearchResult[]>([]);\n const [loading, setLoading] = useState(false);\n const [activeIdx, setActiveIdx] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const previousFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n let focusTimer: number | undefined;\n if (open) {\n previousFocusRef.current = document.activeElement instanceof HTMLElement\n ? document.activeElement\n : null;\n setQ('');\n setResults([]);\n setActiveIdx(0);\n focusTimer = window.setTimeout(() => inputRef.current?.focus(), 30);\n }\n return () => {\n if (focusTimer) window.clearTimeout(focusTimer);\n if (!open) return;\n const previous = previousFocusRef.current;\n if (previous && previous.isConnected) previous.focus();\n };\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n if (!q.trim()) {\n setResults([]);\n setActiveIdx(0);\n return;\n }\n let cancelled = false;\n setLoading(true);\n const t = setTimeout(() => {\n api\n .get<{ results: SearchResult[] }>(`/search?q=${encodeURIComponent(q)}&scope=${scope}`)\n .then((r) => {\n if (cancelled) return;\n setResults(r.results || []);\n setActiveIdx(0);\n })\n .catch((err) => {\n if (cancelled) return;\n toast.error(`Search failed: ${(err as Error).message}`);\n })\n .finally(() => !cancelled && setLoading(false));\n }, 150);\n return () => {\n cancelled = true;\n clearTimeout(t);\n };\n }, [q, scope, open, toast]);\n\n if (!open) return null;\n\n const grouped: Record<string, SearchResult[]> = {};\n for (const r of results) {\n const type = r.type.toLowerCase();\n grouped[type] = grouped[type] || [];\n grouped[type].push(r);\n }\n\n const flat: SearchResult[] = [];\n for (const scope of SCOPES.map((s) => s.id)) {\n const resultType = RESULT_TYPE_BY_SCOPE[scope];\n if (resultType && grouped[resultType]) flat.push(...grouped[resultType]);\n }\n\n const onKey = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose();\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (flat.length === 0) return;\n setActiveIdx((i) => Math.min(i + 1, flat.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (flat.length === 0) return;\n setActiveIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === 'Enter' && flat[activeIdx]) {\n e.preventDefault();\n onSelect(flat[activeIdx]);\n onClose();\n }\n };\n\n return (\n <div className=\"search-modal-backdrop\" onClick={onClose}>\n <div className=\"search-modal\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"search-modal-title\" onClick={(e) => e.stopPropagation()}>\n <div className=\"search-modal-head\">\n <Search size={14} />\n <span id=\"search-modal-title\" className=\"sr-only\">Search</span>\n <input\n ref={inputRef}\n className=\"search-modal-input\"\n placeholder=\"Search tasks, agents, settings, projects…\"\n value={q}\n onChange={(e) => setQ(e.target.value)}\n onKeyDown={onKey}\n />\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n <X size={14} />\n </button>\n </div>\n <div className=\"search-modal-scopes\">\n {SCOPES.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n className={cn('search-scope', scope === s.id && 'search-scope-active')}\n onClick={() => setScope(s.id)}\n >\n {s.label}\n </button>\n ))}\n </div>\n <div className=\"search-modal-body\">\n {loading && <div className=\"muted\">Searching…</div>}\n {!loading && q && flat.length === 0 && <div className=\"muted\">No results.</div>}\n {!loading && !q && <div className=\"muted\">Type to search…</div>}\n {SCOPES.map((s) => {\n const resultType = RESULT_TYPE_BY_SCOPE[s.id];\n if (!resultType) return null;\n const list = grouped[resultType];\n if (!list || list.length === 0) return null;\n return (\n <div key={s.id} className=\"search-group\">\n <div className=\"search-group-head\">{s.label}</div>\n {list.map((r) => {\n const flatIdx = flat.indexOf(r);\n return (\n <button\n type=\"button\"\n key={`${r.type}-${flatIdx}`}\n className={cn('search-result', flatIdx === activeIdx && 'search-result-active')}\n onMouseEnter={() => setActiveIdx(flatIdx)}\n onClick={() => {\n onSelect(r);\n onClose();\n }}\n >\n <span className=\"search-result-type\">{r.type}</span>\n <span className=\"search-result-label\">\n {summarize(r)}\n </span>\n </button>\n );\n })}\n </div>\n );\n })}\n </div>\n <div className=\"search-modal-foot\">\n <span className=\"muted\">↑↓ navigate · ↵ open · esc close</span>\n </div>\n </div>\n </div>\n );\n}\n\nfunction summarize(r: SearchResult): string {\n const i = r.item || {};\n if (r.type === 'project') return `${i.name} — ${i.path}`;\n if (r.type === 'agent') return `${i.name} — ${i.description || i.model || ''}`;\n if (r.type === 'task') return `${i.title} — ${(i.status || '')}`;\n if (r.type === 'mod') return `${i.name} v${i.version} — ${i.description || ''}`;\n if (r.type === 'schedule') return `${i.name} (${i.type}: ${i.schedule})`;\n if (r.type === 'command') return `${i.name} — ${i.description || ''}`;\n if (r.type === 'setting') {\n const val = i.value === null || i.value === undefined\n ? ''\n : typeof i.value === 'string'\n ? ` = ${i.value}`\n : ` = ${JSON.stringify(i.value)}`;\n return `${i.label}${val} — ${i.desc || ''}`.trim();\n }\n return JSON.stringify(i).slice(0, 80);\n}\n","// src/components/Notifications.tsx — v3.3.0 bell icon + dropdown panel.\n\nimport { useEffect, useRef, useState } from 'react';\nimport { Bell, Check, X, Info, AlertTriangle, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { Button } from './Button';\nimport { useToast } from './Toast';\nimport { api } from '../lib/api';\nimport { cn, formatRelative } from '../lib/utils';\nimport type { Notification, NotificationStats, WsMessage } from '../lib/types';\n\nconst ICONS: Record<string, typeof Info> = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n error: AlertCircle,\n};\n\ntype Props = {\n /** Setter for unread count so the rest of the app can react. */\n onCountChange?: (unread: number) => void;\n /** Optional hook to subscribe to incoming WS messages. */\n wsSubscribe?: (cb: (msg: WsMessage) => void) => () => void;\n};\n\nexport function Notifications({ onCountChange, wsSubscribe }: Props) {\n const toast = useToast();\n const [open, setOpen] = useState(false);\n const [items, setItems] = useState<Notification[]>([]);\n const [stats, setStats] = useState<NotificationStats | null>(null);\n const [loading, setLoading] = useState(false);\n const rootRef = useRef<HTMLDivElement | null>(null);\n const unreadRef = useRef(0);\n\n const reload = async () => {\n try {\n setLoading(true);\n const r = await api.get<{ notifications: Notification[]; stats: NotificationStats }>(\n '/notifications?limit=200',\n );\n setItems(r.notifications || []);\n setStats(r.stats || null);\n unreadRef.current = r.stats?.unread || 0;\n onCountChange?.(unreadRef.current);\n } catch (err) {\n // Soft-fail: the bell just shows no items.\n // eslint-disable-next-line no-console\n console.warn('[notifications] reload failed:', (err as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Subscribe to incoming notification:new events.\n useEffect(() => {\n if (!wsSubscribe) return;\n const off = wsSubscribe((msg) => {\n if (msg.type === 'notification:new') {\n const incoming = msg.notification;\n setItems((cur) => [incoming, ...cur.filter((n) => n.id !== incoming.id)]);\n // Bump unread count.\n if (!incoming.read) {\n unreadRef.current += 1;\n setStats((cur) =>\n cur ? { ...cur, unread: (cur.unread || 0) + 1 } : { total: 1, unread: 1, lastTs: incoming.ts, counts: { [incoming.severity || 'info']: 1 } },\n );\n onCountChange?.(unreadRef.current);\n }\n } else if (msg.type === 'notifications:change') {\n // External change (mark-all-read, etc.) — refresh from server.\n reload();\n }\n });\n return off;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [wsSubscribe]);\n\n // Close the panel on outside click.\n useEffect(() => {\n if (!open) return;\n const onDocClick = (e: MouseEvent) => {\n if (!rootRef.current) return;\n if (!rootRef.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('mousedown', onDocClick);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('mousedown', onDocClick);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const onMarkAllRead = async () => {\n try {\n await api.post('/notifications/read-all', {});\n setItems((cur) => cur.map((n) => ({ ...n, read: true })));\n setStats((cur) => (cur ? { ...cur, unread: 0 } : cur));\n unreadRef.current = 0;\n onCountChange?.(0);\n toast.success('All notifications marked as read.', 1500);\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const onMarkRead = async (id: string) => {\n try {\n await api.post(`/notifications/${encodeURIComponent(id)}/read`, {});\n setItems((cur) => cur.map((n) => (n.id === id ? { ...n, read: true } : n)));\n setStats((cur) => (cur ? { ...cur, unread: Math.max(0, (cur.unread || 1) - 1) } : cur));\n unreadRef.current = Math.max(0, unreadRef.current - 1);\n onCountChange?.(unreadRef.current);\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const onRemove = async (id: string) => {\n try {\n await api.del(`/notifications/${encodeURIComponent(id)}`);\n setItems((cur) => {\n const removed = cur.find((n) => n.id === id);\n if (removed && !removed.read) {\n unreadRef.current = Math.max(0, unreadRef.current - 1);\n setStats((statsCur) => (statsCur ? { ...statsCur, unread: Math.max(0, statsCur.unread - 1) } : statsCur));\n onCountChange?.(unreadRef.current);\n }\n return cur.filter((n) => n.id !== id);\n });\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n }\n };\n\n const unread = stats?.unread || 0;\n\n return (\n <div className=\"notifications-root\" ref={rootRef}>\n <button\n type=\"button\"\n className={cn('topbar-icon-btn notifications-bell', open && 'is-open')}\n onClick={() => setOpen((v) => !v)}\n title=\"Notifications\"\n aria-label=\"Notifications\"\n aria-haspopup=\"true\"\n aria-expanded={open}\n >\n <Bell size={16} />\n {unread > 0 && <span className=\"notifications-badge\">{unread > 99 ? '99+' : unread}</span>}\n </button>\n {open && (\n <div className=\"notifications-panel\" role=\"dialog\" aria-label=\"Notifications\">\n <header className=\"notifications-panel-head\">\n <div>\n <strong>Notifications</strong>\n {unread > 0 && <span className=\"muted text-sm\"> · {unread} unread</span>}\n </div>\n <div className=\"notifications-panel-head-actions\">\n <Button size=\"sm\" variant=\"ghost\" onClick={onMarkAllRead} disabled={unread === 0}>\n <Check size={12} /> Mark all read\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setOpen(false)}\n aria-label=\"Close\"\n title=\"Close\"\n >\n <X size={14} />\n </button>\n </div>\n </header>\n <div className=\"notifications-list\">\n {loading && items.length === 0 ? (\n <div className=\"notifications-empty muted\">Loading…</div>\n ) : items.length === 0 ? (\n <div className=\"notifications-empty muted\">No notifications yet.</div>\n ) : (\n items.map((n) => {\n const Icon = ICONS[n.severity] || Info;\n return (\n <div\n key={n.id}\n className={cn('notification-item', !n.read && 'is-unread', `severity-${n.severity}`)}\n >\n <Icon size={14} className={`notification-icon severity-${n.severity}`} />\n <div className=\"notification-body\">\n {n.title && <div className=\"notification-title\">{n.title}</div>}\n <div className=\"notification-msg\">{n.message}</div>\n <div className=\"notification-meta muted\">\n <span className=\"mono\">{n.source}</span>\n <span>·</span>\n <span>{formatRelative(n.ts)}</span>\n </div>\n </div>\n <div className=\"notification-actions\">\n {!n.read && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => onMarkRead(n.id)}\n title=\"Mark as read\"\n aria-label=\"Mark as read\"\n >\n <Check size={12} />\n </button>\n )}\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n onClick={() => onRemove(n.id)}\n title=\"Remove\"\n aria-label=\"Remove\"\n >\n <X size={12} />\n </button>\n </div>\n </div>\n );\n })\n )}\n </div>\n <footer className=\"notifications-panel-foot\">\n <span className=\"muted text-sm\">\n {stats ? `${stats.total} total · last ${formatRelative(stats.lastTs || new Date().toISOString())}` : ''}\n </span>\n </footer>\n </div>\n )}\n </div>\n );\n}\n","// src/components/VisualPlanDialog.tsx — Dialog for /visual-plan command.\n\nimport { Button } from './Button';\n\ntype VisualPlanDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\nexport function VisualPlanDialog({ data, onClose }: VisualPlanDialogProps) {\n const enabled = data?.enabled as boolean | undefined;\n const previousEnabled = data?.previousEnabled as boolean | undefined;\n const mode = data?.mode as string | undefined;\n const defaultTemplate = data?.defaultTemplate as string | undefined;\n const lastUsedSlug = data?.lastUsedSlug as string | null | undefined;\n\n const wasToggled = mode === 'toggle';\n\n return (\n <div>\n {wasToggled ? (\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n Visual plan mode has been <strong>{enabled ? 'enabled' : 'disabled'}</strong>.\n {enabled\n ? ' The agent will create a plan and wait for your feedback on complex tasks.'\n : ' The agent will work without a visual plan canvas.'}\n </p>\n ) : (\n <div style={{ marginBottom: 16 }}>\n <p style={{ marginBottom: 8, fontWeight: 600 }}>\n Visual Plan: <span style={{ color: enabled ? 'var(--color-success)' : 'var(--color-muted)' }}>\n {enabled ? 'ON' : 'OFF'}\n </span>\n </p>\n <p style={{ lineHeight: 1.6, color: 'var(--color-muted)', fontSize: 13 }}>\n When enabled, the agent creates a visual plan and waits for your feedback before proceeding with complex tasks.\n </p>\n {defaultTemplate && (\n <p style={{ marginTop: 8, fontSize: 13, color: 'var(--color-muted)' }}>\n Default template: <code>{defaultTemplate}</code>\n </p>\n )}\n {lastUsedSlug && (\n <p style={{ fontSize: 13, color: 'var(--color-muted)' }}>\n Last used plan: <code>{lastUsedSlug}</code>\n </p>\n )}\n <p style={{ marginTop: 12, fontSize: 13, color: 'var(--color-muted)' }}>\n Use <code>/visual-plan on</code> or <code>/visual-plan off</code> to toggle.\n </p>\n </div>\n )}\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </div>\n );\n}\n","// src/components/ArtifactCreateDialog.tsx — Dialog for /artifact new command.\n\nimport { useState } from 'react';\nimport { Button } from './Button';\nimport { api } from '../lib/api';\n\ntype ArtifactCreateDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\nconst KNOWN_TEMPLATES = [\n 'blank',\n 'feature-design',\n 'bug-investigation',\n 'decision-record',\n 'horizontal',\n 'vertical',\n];\n\nexport function ArtifactCreateDialog({ data, onClose }: ArtifactCreateDialogProps) {\n const templates = (data?.templates as string[]) ?? KNOWN_TEMPLATES;\n const defaultTemplate = (data?.defaultTemplate as string) ?? 'blank';\n\n const [slug, setSlug] = useState('');\n const [selectedTemplate, setSelectedTemplate] = useState(defaultTemplate);\n const [creating, setCreating] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const handleCreate = async () => {\n if (!slug.trim()) {\n setError('Slug is required.');\n return;\n }\n if (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(slug)) {\n setError('Invalid slug. Use lowercase letters, numbers, and hyphens. Must start with an alphanumeric character.');\n return;\n }\n setCreating(true);\n setError(null);\n try {\n await api.post('/artifacts', { slug, template: selectedTemplate });\n onClose();\n } catch (err) {\n setError((err as Error).message);\n setCreating(false);\n }\n };\n\n return (\n <div>\n <p style={{ marginBottom: 16, color: 'var(--color-muted)', fontSize: 13 }}>\n Create a new visual plan. Plans are stored in <code>artifacts/</code> in your worktree.\n </p>\n\n <div style={{ marginBottom: 12 }}>\n <label className=\"field-label\" htmlFor=\"plan-slug\">Plan slug</label>\n <input\n id=\"plan-slug\"\n className=\"input\"\n type=\"text\"\n placeholder=\"e.g. my-feature\"\n value={slug}\n onChange={(e) => { setSlug(e.target.value); setError(null); }}\n autoFocus\n />\n </div>\n\n <div style={{ marginBottom: 16 }}>\n <label className=\"field-label\" htmlFor=\"plan-template\">Template</label>\n <select\n id=\"plan-template\"\n className=\"select\"\n value={selectedTemplate}\n onChange={(e) => setSelectedTemplate(e.target.value)}\n >\n {templates.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n\n {error && (\n <p style={{ marginBottom: 12, color: 'var(--color-danger)', fontSize: 13 }}>{error}</p>\n )}\n\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose} disabled={creating}>Cancel</Button>\n <Button variant=\"primary\" onClick={handleCreate} disabled={creating || !slug.trim()}>\n {creating ? 'Creating…' : 'Create'}\n </Button>\n </div>\n </div>\n );\n}\n","// src/components/ArtifactListDialog.tsx — Dialog for /plan list command.\n\nimport { Button } from './Button';\n\ntype ArtifactListDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\nexport function ArtifactListDialog({ data, onClose }: ArtifactListDialogProps) {\n const plans = (data?.plans as string[]) ?? [];\n const count = (data?.count as number) ?? plans.length;\n\n const handleOpen = (slug: string) => {\n window.open(`/artifacts/${slug}/`, '_blank');\n };\n\n return (\n <div>\n {plans.length === 0 ? (\n <p style={{ marginBottom: 16, color: 'var(--color-muted)' }}>\n No plans found in this worktree. Use <code>/artifact new &lt;slug&gt;</code> to create one.\n </p>\n ) : (\n <div style={{ marginBottom: 16 }}>\n <p style={{ marginBottom: 12, fontSize: 13, color: 'var(--color-muted)' }}>\n {count} plan{count !== 1 ? 's' : ''} in this worktree:\n </p>\n <ul style={{ listStyle: 'none', padding: 0, margin: 0 }}>\n {plans.map((slug) => (\n <li\n key={slug}\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '6px 0',\n borderBottom: '1px solid var(--color-border)',\n }}\n >\n <code style={{ fontSize: 13 }}>{slug}</code>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => handleOpen(slug)}>\n Open\n </Button>\n </li>\n ))}\n </ul>\n </div>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </div>\n );\n}\n","// src/components/HelpDialog.tsx — Dialog for /help and /bizar commands.\n\nimport { Button } from './Button';\n\ntype HelpDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\ntype CmdEntry = { cmd: string; desc: string };\n\nexport function HelpDialog({ data, onClose }: HelpDialogProps) {\n const commands = (data?.commands as CmdEntry[]) ?? [];\n const templates = (data?.templates as string[]) ?? [];\n const statuses = (data?.statuses as string[]) ?? [];\n\n return (\n <div>\n {commands.length > 0 ? (\n <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: 16, fontSize: 13 }}>\n <tbody>\n {commands.map((entry) => (\n <tr key={entry.cmd} style={{ borderBottom: '1px solid var(--color-border)' }}>\n <td style={{ padding: '5px 8px 5px 0', whiteSpace: 'nowrap' }}>\n <code style={{ fontSize: 12 }}>{entry.cmd}</code>\n </td>\n <td style={{ padding: '5px 0', color: 'var(--color-muted)' }}>{entry.desc}</td>\n </tr>\n ))}\n </tbody>\n </table>\n ) : (\n <p style={{ marginBottom: 16, color: 'var(--color-muted)' }}>No commands available.</p>\n )}\n\n {templates.length > 0 && (\n <div style={{ marginBottom: 12 }}>\n <p style={{ fontSize: 12, color: 'var(--color-muted)', marginBottom: 4 }}>Available templates:</p>\n <p style={{ fontSize: 13 }}>{templates.join(', ')}</p>\n </div>\n )}\n\n {statuses.length > 0 && (\n <div style={{ marginBottom: 12 }}>\n <p style={{ fontSize: 12, color: 'var(--color-muted)', marginBottom: 4 }}>Available statuses:</p>\n <p style={{ fontSize: 13 }}>{statuses.join(', ')}</p>\n </div>\n )}\n\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </div>\n );\n}\n","// src/components/AuditDialog.tsx — Dialog for /audit command.\n\nimport { useState } from 'react';\nimport { Button } from './Button';\nimport { api } from '../lib/api';\n\ntype AuditDialogProps = {\n data?: Record<string, unknown>;\n onClose: () => void;\n};\n\ntype AuditResult = {\n ok: boolean;\n findings: string[];\n error?: string;\n};\n\nexport function AuditDialog({ data, onClose }: AuditDialogProps) {\n const [running, setRunning] = useState(false);\n const [result, setResult] = useState<AuditResult | null>(null);\n\n const handleRunAudit = async () => {\n setRunning(true);\n setResult(null);\n try {\n // The audit is run by posting to /api/chat with an /audit message,\n // which forwards to the opencode serve child where the plugin handles it.\n // We poll for a response via the chat session.\n const res = await api.post<AuditResult>('/chat/audit', {});\n setResult(res);\n } catch (err) {\n setResult({ ok: false, findings: [], error: (err as Error).message });\n } finally {\n setRunning(false);\n }\n };\n\n return (\n <div>\n {result === null ? (\n <>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n Run a security audit of your Bizar agent configuration. The audit checks for common misconfigurations, exposed secrets, and insecure defaults.\n </p>\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Cancel</Button>\n <Button variant=\"primary\" onClick={handleRunAudit} disabled={running}>\n {running ? 'Running…' : 'Run Audit'}\n </Button>\n </div>\n </>\n ) : (\n <>\n {result.ok ? (\n <div>\n <p style={{ marginBottom: 12, fontWeight: 600, color: 'var(--color-success)' }}>\n Audit passed — no issues found.\n </p>\n {result.findings.length > 0 && (\n <ul style={{ marginBottom: 16, paddingLeft: 20 }}>\n {result.findings.map((f, i) => (\n <li key={i} style={{ marginBottom: 4, fontSize: 13 }}>{f}</li>\n ))}\n </ul>\n )}\n </div>\n ) : (\n <p style={{ marginBottom: 16, color: 'var(--color-danger)' }}>\n Audit failed: {result.error ?? 'unknown error'}\n </p>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Close</Button>\n </div>\n </>\n )}\n </div>\n );\n}\n","// src/components/CommandDialog.tsx — Generic dialog wrapper that routes to the\n// correct specific dialog component based on the DialogDescriptor's `component` field.\n\nimport { VisualPlanDialog } from './VisualPlanDialog';\nimport { ArtifactCreateDialog } from './ArtifactCreateDialog';\nimport { ArtifactListDialog } from './ArtifactListDialog';\nimport { HelpDialog } from './HelpDialog';\nimport { AuditDialog } from './AuditDialog';\nimport type { DialogDescriptor } from '../lib/types';\n\nexport type { DialogDescriptor };\n\nfunction GenericDialog({ dialog, onClose }: { dialog: DialogDescriptor; onClose: () => void }) {\n if (!dialog.data) {\n return (\n <div>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n {`Command: ${dialog.command}`}\n </p>\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <button type=\"button\" className=\"btn\" onClick={onClose}>Close</button>\n </div>\n </div>\n );\n }\n\n const { message, detail, url } = dialog.data as { message?: string; detail?: string; url?: string };\n\n return (\n <div>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n {message ?? `Command: ${dialog.command}`}\n </p>\n {detail && (\n <p style={{ marginBottom: 16, color: 'var(--color-muted)', fontSize: 13 }}>\n {detail}\n </p>\n )}\n {url && (\n <p style={{ marginBottom: 16 }}>\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\">{url}</a>\n </p>\n )}\n <div style={{ display: 'flex', justifyContent: 'flex-end' }}>\n <button type=\"button\" className=\"btn\" onClick={onClose}>Close</button>\n </div>\n </div>\n );\n}\n\nexport function CommandDialog({ dialog, onClose }: { dialog: DialogDescriptor; onClose: () => void }) {\n switch (dialog.component) {\n case 'visual-artifact':\n return <VisualPlanDialog data={dialog.data} onClose={onClose} />;\n case 'artifact-create':\n return <ArtifactCreateDialog data={dialog.data} onClose={onClose} />;\n case 'artifact-list':\n return <ArtifactListDialog data={dialog.data} onClose={onClose} />;\n case 'help':\n return <HelpDialog data={dialog.data} onClose={onClose} />;\n case 'audit':\n return <AuditDialog data={dialog.data} onClose={onClose} />;\n default:\n return <GenericDialog dialog={dialog} onClose={onClose} />;\n }\n}\n","// src/components/Card.tsx — wrapper card.\n\nimport type { HTMLAttributes, ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type CardProps = HTMLAttributes<HTMLDivElement> & {\n variant?: 'elevated' | 'outlined' | 'filled';\n interactive?: boolean;\n children?: ReactNode;\n};\n\nexport function Card({\n variant = 'elevated',\n interactive = false,\n className,\n children,\n ...rest\n}: CardProps) {\n return (\n <div\n className={cn(\n 'card',\n `card-${variant}`,\n interactive && 'card-interactive',\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\nexport function CardTitle({ children, className }: { children: ReactNode; className?: string }) {\n return <h3 className={cn('card-title', className)}>{children}</h3>;\n}\n\nexport function CardMeta({ children, className }: { children: ReactNode; className?: string }) {\n return <div className={cn('card-meta', className)}>{children}</div>;\n}\n","// src/web/views/memory/MemoryStatusCard.tsx — overview status card for the Memory subsystem.\n//\n// Slimmed-down version of MemoryOverview: a single Card with lightrag status,\n// vault note count, git sync state, and a button to open the full Memory tab.\nimport { useEffect, useState } from 'react';\nimport {\n Activity,\n Brain,\n ExternalLink,\n FileText,\n GitBranch,\n RefreshCw,\n} from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { api } from '../../lib/api';\nimport { formatTime, cn } from '../../lib/utils';\n\ntype MemoryCardData = {\n initialized: boolean;\n mode?: string;\n projectId?: string;\n vaultRoot?: string;\n branch?: string;\n gitClean?: boolean | null;\n noteCount?: number;\n healthScore?: number;\n healthStatus?: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured';\n lightrag?: { running: boolean; indexedApprox: number };\n};\n\ntype Props = {\n setActiveTab: (id: string) => void;\n refreshKey?: number;\n};\n\nexport function MemoryStatusCard({ setActiveTab, refreshKey = 0 }: Props) {\n const [data, setData] = useState<MemoryCardData | null>(null);\n const [loading, setLoading] = useState(true);\n\n const reload = async () => {\n setLoading(true);\n try {\n const [status, health, lightrag] = await Promise.all([\n api.get<MemoryCardData>('/memory/status').catch(() => null),\n api.get<{ score: number; status: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured' }>(\n '/memory/health',\n ).catch(() => null),\n api.get<{ running: boolean; indexedApprox: number }>('/memory/lightrag/stats').catch(() => null),\n ]);\n setData({\n initialized: !!status?.initialized,\n mode: status?.mode,\n projectId: status?.projectId,\n vaultRoot: status?.vaultRoot,\n branch: status?.branch,\n gitClean: status?.gitClean,\n noteCount: status?.noteCount || 0,\n healthScore: health?.score,\n healthStatus: health?.status,\n lightrag: lightrag ? { running: lightrag.running, indexedApprox: lightrag.indexedApprox } : undefined,\n });\n } catch {\n setData({ initialized: false });\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n const openMemory = () => setActiveTab('memory');\n\n const healthColor =\n data?.healthStatus === 'healthy' ? 'var(--success)' :\n data?.healthStatus === 'degraded' ? 'var(--warning)' :\n data?.healthStatus === 'unhealthy' ? 'var(--error)' :\n 'var(--text-dim)';\n\n return (\n <Card className=\"memory-overview-card\">\n <CardTitle>\n <Brain size={14} /> Memory\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={openMemory}>\n Open Memory <ExternalLink size={12} />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={reload} aria-label=\"Refresh\" title=\"Refresh\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n LightRAG + Obsidian vault + git sync — opens the dedicated Memory tab.\n </CardMeta>\n\n {!data?.initialized ? (\n <div className=\"muted\">\n Memory not initialised. Click <strong>Open Memory</strong> to set it up.\n </div>\n ) : (\n <div className=\"memory-status-card-grid\">\n <div className=\"memory-status-card-cell\">\n <div className=\"memory-status-card-label\">\n <Activity size={11} /> Health\n </div>\n <div className=\"memory-status-card-value\" style={{ color: healthColor }}>\n {data.healthScore !== undefined ? `${data.healthScore}/100` : '—'}\n </div>\n <div className=\"memory-status-card-sub muted\">{data.healthStatus || '—'}</div>\n </div>\n\n <div className=\"memory-status-card-cell\">\n <div className=\"memory-status-card-label\">\n <Brain size={11} /> LightRAG\n </div>\n <div className=\"memory-status-card-value\">\n {data.lightrag?.running ? 'running' : 'stopped'}\n </div>\n <div className=\"memory-status-card-sub muted\">\n {data.lightrag ? `${data.lightrag.indexedApprox} chunks` : '—'}\n </div>\n </div>\n\n <div className=\"memory-status-card-cell\">\n <div className=\"memory-status-card-label\">\n <FileText size={11} /> Vault\n </div>\n <div className=\"memory-status-card-value\">{data.noteCount} notes</div>\n <div className=\"memory-status-card-sub muted ellipsis\" title={data.vaultRoot || ''}>\n {data.vaultRoot ? data.vaultRoot.split('/').slice(-2).join('/') : '—'}\n </div>\n </div>\n\n <div className=\"memory-status-card-cell\">\n <div className=\"memory-status-card-label\">\n <GitBranch size={11} /> Git\n </div>\n <div className=\"memory-status-card-value\">\n {data.gitClean === null\n ? data.mode === 'local-only' ? 'local-only' : '—'\n : data.gitClean ? 'clean' : 'dirty'}\n </div>\n <div className=\"memory-status-card-sub muted\">\n {data.branch ? `branch ${data.branch}` : formatTime(data.branch || '') || '—'}\n </div>\n </div>\n </div>\n )}\n\n {loading && !data && (\n <div className=\"muted text-sm\">Loading…</div>\n )}\n </Card>\n );\n}\n\n// Allow css class composition without TS complaining about missing module declarations.\nvoid cn;","// src/components/EmptyState.tsx — friendly empty / error placeholder.\n\nimport type { ReactNode } from 'react';\nimport { Inbox } from 'lucide-react';\nimport { cn } from '../lib/utils';\n\nexport type EmptyStateProps = {\n icon?: ReactNode;\n title: string;\n message?: ReactNode;\n action?: ReactNode;\n className?: string;\n};\n\nexport function EmptyState({\n icon,\n title,\n message,\n action,\n className,\n}: EmptyStateProps) {\n return (\n <div className={cn('empty-state', className)}>\n <div className=\"empty-icon\">{icon ?? <Inbox size={32} />}</div>\n <div className=\"empty-title\">{title}</div>\n {message && <div className=\"empty-message\">{message}</div>}\n {action && <div className=\"empty-action\">{action}</div>}\n </div>\n );\n}\n","// src/views/Overview.tsx — v3.7.0 activity cards + SSE stream.\nimport React, { useEffect, useRef, useState } from 'react';\nimport {\n Bot,\n CheckSquare,\n Folder,\n LayoutDashboard,\n Map,\n MessageSquare,\n RefreshCw,\n PlayCircle,\n ShieldCheck,\n FileText,\n Zap,\n Plus,\n Trash2,\n Power,\n Send,\n Sparkles,\n AlertOctagon,\n AlertTriangle,\n CheckCircle2,\n Activity,\n Puzzle,\n Clock,\n FolderSearch,\n EyeOff,\n Eye,\n X,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { MemoryStatusCard } from './memory/MemoryStatusCard';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { FileBrowser } from '../components/FileBrowser';\nimport { api } from '../lib/api';\nimport { formatRelative, formatTime } from '../lib/utils';\nimport type { Overview, Settings, Snapshot, ActivityItem, ProjectRecord, Mod, ScanResult, DirectoryListing } from '../lib/types';\nimport { cn } from '../lib/utils';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nfunction OverviewInner({\n snapshot,\n settings,\n setActiveTab,\n refreshSnapshot,\n}: Props) {\n const toast = useToast();\n const modal = useModal();\n const inputRef = useRef<HTMLTextAreaElement | null>(null);\n const [overview, setOverview] = useState<Overview | null>(\n snapshot.overview ?? null,\n );\n const [loading, setLoading] = useState(!snapshot.overview);\n const [projects, setProjects] = useState<ProjectRecord[]>(snapshot.projects || []);\n const [activeId, setActiveId] = useState<string | null>(\n snapshot.activeProject?.id || null,\n );\n const [mods, setMods] = useState<Mod[]>(snapshot.mods || []);\n const [submitting, setSubmitting] = useState(false);\n // v3.7.0 — Live activity feed via SSE\n const [activityItems, setActivityItems] = useState<ActivityItem[]>(\n snapshot.overview?.recentActivity ?? [],\n );\n const [activityExpanded, setActivityExpanded] = useState(false);\n // v3.15.0 — Hidden event keys are stored server-side; we just track\n // the set in client state. Hiding does NOT delete — see Settings →\n // Activity Log for the full feed.\n const [hiddenKeys, setHiddenKeys] = useState<Set<string>>(new Set());\n\n // v3.15.0 — Load hidden set once on mount\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.get<{ hidden: string[] }>('/activity/hidden');\n if (!cancelled) setHiddenKeys(new Set(r.hidden || []));\n } catch { /* non-fatal */ }\n })();\n return () => { cancelled = true; };\n }, []);\n\n // v3.15.0 — Helper: stable key per activity item\n const itemKey = (it: ActivityItem, idx: number): string => {\n const k = `${it.kind || ''}|${it.ts || ''}|${(it.slug as string) || (it.title as string) || ''}|${idx}`;\n // hash to a short key (matches server-side activityKey derivation)\n let h = 0;\n for (let i = 0; i < k.length; i++) h = ((h << 5) - h + k.charCodeAt(i)) | 0;\n return Math.abs(h).toString(16).padStart(8, '0').slice(0, 16);\n };\n\n const onHide = async (key: string) => {\n const next = new Set(hiddenKeys);\n next.add(key);\n setHiddenKeys(next);\n try {\n await api.post('/activity/hide', { keys: [key] });\n } catch (err) {\n // rollback on failure\n const rollback = new Set(hiddenKeys);\n setHiddenKeys(rollback);\n toast.error(`Hide failed: ${(err as Error).message}`);\n }\n };\n\n const onClearAll = async () => {\n if (!confirm('Hide every recent activity item from the overview? The full log stays in Settings → Activity Log.')) return;\n const all = activityItems.map((it, idx) => itemKey(it, idx));\n const next = new Set(hiddenKeys);\n all.forEach((k) => next.add(k));\n setHiddenKeys(next);\n try {\n await api.post('/activity/hide', { keys: all });\n toast.success(`Hidden ${all.length} item(s). Restore them in Settings → Activity Log.`);\n } catch (err) {\n toast.error(`Clear failed: ${(err as Error).message}`);\n }\n };\n\n const onRestoreAll = async () => {\n setHiddenKeys(new Set());\n try {\n await api.del('/activity/hide');\n toast.success('All hidden activity restored to the overview.');\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n // v3.7.0 — Sync initial snapshot data\n useEffect(() => {\n if (snapshot.overview) {\n setOverview(snapshot.overview);\n setActivityItems(snapshot.overview.recentActivity ?? []);\n setLoading(false);\n }\n setProjects(snapshot.projects || []);\n setActiveId(snapshot.activeProject?.id || null);\n setMods(snapshot.mods || []);\n }, [snapshot.overview, snapshot.projects, snapshot.activeProject, snapshot.mods]);\n\n // v3.7.0 — Subscribe to SSE activity stream\n // v3.6.0 — Append ?token=… for auth. EventSource can't set custom\n // headers, so the server accepts the token via query string too.\n useEffect(() => {\n let es: EventSource;\n try {\n const tok = api.getToken();\n const url = tok\n ? `/api/activity/stream?token=${encodeURIComponent(tok)}`\n : '/api/activity/stream';\n es = new EventSource(url);\n es.addEventListener('snapshot', (e) => {\n try {\n const parsed = JSON.parse((e as MessageEvent).data) as { events: ActivityItem[]; generatedAt?: string };\n setActivityItems(Array.isArray(parsed.events) ? parsed.events.slice(0, 50) : []);\n } catch { /* ignore parse errors */ }\n });\n es.addEventListener('activity', (e) => {\n try {\n const entry = JSON.parse((e as MessageEvent).data) as ActivityItem;\n setActivityItems((cur) => [entry, ...cur].slice(0, 50));\n } catch { /* ignore parse errors */ }\n });\n } catch { /* SSE not available — fallback to snapshot data */ }\n return () => { try { es?.close(); } catch { /* ignore */ } };\n }, []);\n\n const onRefresh = async () => {\n toast.info('Refreshing…', 1500);\n await refreshSnapshot();\n try {\n const data = await api.get<{ projects: ProjectRecord[]; active: string | null }>('/projects');\n setProjects(data.projects || []);\n setActiveId(data.active || null);\n } catch { /* ignore */ }\n };\n\n const onAddProject = () => {\n modal.open({\n title: 'Add project',\n children: (\n <AddProjectDialog\n settings={settings}\n onAdd={async (path: string, name: string | null) => {\n try {\n const r = await api.post<ProjectRecord>('/projects', { path, name });\n setProjects((cur) => [...cur.filter((p) => p.id !== r.id), r]);\n toast.success('Project added.');\n modal.close();\n } catch (err) {\n toast.error(`Add failed: ${(err as Error).message}`);\n }\n }}\n />\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n </div>\n ),\n });\n };\n\n const onUseCurrentDir = async () => {\n try {\n const data = await api.post<{ projects: ProjectRecord[]; active: string | null }>(\n '/projects/auto-detect',\n );\n setProjects(data.projects || []);\n setActiveId(data.active || null);\n const newActive = data.projects?.find((p) => p.id === data.active);\n toast.success(newActive ? `Active: ${newActive.name}` : 'Projects refreshed.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Auto-detect failed: ${(err as Error).message}`);\n }\n };\n\n const onActivate = async (id: string) => {\n try {\n await api.post(`/projects/${encodeURIComponent(id)}/activate`);\n setActiveId(id);\n toast.success('Project activated.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Activate failed: ${(err as Error).message}`);\n }\n };\n\n const onRemove = async (id: string) => {\n if (!confirm(`Remove project \"${id}\" from the registry?`)) return;\n try {\n await api.del(`/projects/${encodeURIComponent(id)}`);\n setProjects((cur) => cur.filter((p) => p.id !== id));\n if (activeId === id) setActiveId(null);\n toast.success('Project removed.');\n } catch (err) {\n toast.error(`Remove failed: ${(err as Error).message}`);\n }\n };\n\n if (loading || !overview) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading overview…</p>\n </div>\n );\n }\n\n return (\n <div className=\"view view-overview\">\n {/* v3.4.0 — Hero takes the spotlight. No card wrapper. */}\n <div className=\"overview-hero-noframe\">\n <h1>What do you want to do?</h1>\n <p className=\"overview-hero-subtitle\">\n Describe what you want — Odin will split it into tasks, create a plan,\n delegate to background agents, and track progress in real time.\n </p>\n <form\n className=\"overview-hero-form-noframe\"\n onSubmit={async (e) => {\n e.preventDefault();\n const text = (inputRef.current?.value || '').trim();\n if (!text) return;\n setSubmitting(true);\n try {\n const r = await api.post<{ subtasks?: unknown[] }>('/tasks/submit', { title: text });\n toast.success(`Odin split it into ${(r.subtasks?.length || 1)} task(s)`);\n if (inputRef.current) inputRef.current.value = '';\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n } finally {\n setSubmitting(false);\n }\n }}\n >\n <textarea\n ref={inputRef}\n className=\"overview-input-hero\"\n placeholder=\"e.g. Implement user authentication with email + password, including registration, login, password reset, and integration tests. Use Bcrypt, JWT tokens, and the existing API style.\"\n disabled={submitting}\n />\n <div style={{ display: 'flex', gap: 'var(--space-2)', alignItems: 'center', flexWrap: 'wrap' }}>\n <Button\n type=\"submit\"\n variant=\"primary\"\n size=\"lg\"\n disabled={submitting}\n >\n {submitting ? <Spinner size=\"sm\" /> : <Send size={16} />}\n Submit to Odin\n </Button>\n <span className=\"muted\" style={{ fontSize: 12 }}>\n <Sparkles size={12} style={{ display: 'inline', verticalAlign: -2, color: 'var(--accent)' }} />\n {' '}Odin + 12 specialist agents available\n </span>\n </div>\n </form>\n\n <div className=\"overview-quick-actions-row\">\n {['Implement feature', 'Fix bug', 'Refactor', 'Investigate', 'Add tests', 'Document', 'Optimize', 'Deploy'].map((action) => (\n <button\n key={action}\n type=\"button\"\n className=\"overview-quick-chip\"\n onClick={() => {\n if (inputRef.current) {\n inputRef.current.value = action;\n inputRef.current.focus();\n }\n }}\n >\n {action}\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"overview-feed\">\n <div className=\"overview-feed-head\">\n <h2>Recent activity</h2>\n <div className=\"overview-feed-head-actions\">\n {hiddenKeys.size > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onRestoreAll} title=\"Restore hidden items to this overview\">\n <Eye size={12} /> Show {hiddenKeys.size} hidden\n </Button>\n )}\n {activityItems.length > 8 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => setActivityExpanded((v) => !v)}>\n {activityExpanded ? 'Show less' : 'Show all'}\n </Button>\n )}\n {activityItems.length > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onClearAll} title=\"Hide every item from the overview (full log kept)\">\n <EyeOff size={12} /> Hide all\n </Button>\n )}\n </div>\n </div>\n {hiddenKeys.size > 0 && (\n <div className=\"activity-hidden-banner\" role=\"status\">\n <span>\n <EyeOff size={12} style={{ verticalAlign: -2, marginRight: 6 }} />\n {hiddenKeys.size} item{hiddenKeys.size === 1 ? '' : 's'} hidden from the overview.\n </span>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRestoreAll}>\n <Eye size={12} /> Show them again\n </Button>\n </div>\n )}\n {activityItems.length === 0 ? (\n <div className=\"muted\" style={{ padding: '24px 0', fontSize: 13 }}>\n No activity yet. Use the chat above or invoke a Bizar command to start a feed.\n </div>\n ) : (\n <div className={cn('activity-feed-list-wrap', !activityExpanded && 'activity-feed-list-wrap-collapsed')}>\n <div className=\"activity-feed-list\">\n {activityItems.slice(0, 30).map((it, idx) => {\n const k = itemKey(it, idx);\n if (hiddenKeys.has(k)) return null;\n return (\n <ActivityFeedItem\n key={`${it.ts}-${idx}`}\n item={it}\n activityKey={k}\n onNavigate={setActiveTab}\n onHide={onHide}\n />\n );\n })}\n </div>\n {!activityExpanded && activityItems.length > 8 && <div className=\"activity-feed-fade\" aria-hidden=\"true\" />}\n </div>\n )}\n </div>\n\n {/* v3.4.0 — Below-the-fold: projects + meta (compact) */}\n <Card className=\"project-picker\">\n <CardTitle>\n <Folder size={14} /> Projects\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={onAddProject}>\n <Plus size={12} /> Add\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onUseCurrentDir} title=\"Use the server's working directory\">\n <Plus size={12} /> Auto-detect\n </Button>\n {settings?.dashboard?.projectsDirectory && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n title={`Scan ${settings.dashboard.projectsDirectory} for projects`}\n onClick={async () => {\n try {\n const r = await api.post<ScanResult>('/projects/scan');\n if (r.error) {\n toast.error(r.error);\n } else {\n toast.success(`Added ${r.added.length}, skipped ${r.skipped}.`);\n }\n await refreshSnapshot();\n const data = await api.get<{ projects: ProjectRecord[]; active: string | null }>('/projects');\n setProjects(data.projects || []);\n setActiveId(data.active || null);\n } catch (err) {\n toast.error(`Scan failed: ${(err as Error).message}`);\n }\n }}\n >\n <FolderSearch size={12} /> Scan\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={onRefresh} title=\"Refresh\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n {projects.length} project{projects.length === 1 ? '' : 's'} ·\n {' '}{overview.counts.agents} agents ·\n {' '}{overview.counts.sessions} session{overview.counts.sessions === 1 ? '' : 's'}\n </CardMeta>\n {projects.length === 0 ? (\n <EmptyState\n icon={<Folder size={32} />}\n title=\"No projects yet\"\n message=\"Add a project to start tracking its tasks, plans, and schedules.\"\n action={\n <div className=\"empty-state-actions\">\n <Button variant=\"primary\" onClick={onUseCurrentDir}>\n <Plus size={14} /> Use current directory\n </Button>\n <Button variant=\"secondary\" onClick={onAddProject}>\n Add by path…\n </Button>\n </div>\n }\n />\n ) : (\n <div className=\"project-grid\">\n {projects.map((p) => (\n <ProjectCard\n key={p.id}\n project={p}\n active={activeId === p.id}\n onOpen={() => onActivate(p.id)}\n onRemove={() => onRemove(p.id)}\n />\n ))}\n </div>\n )}\n </Card>\n\n <MemoryStatusCard setActiveTab={setActiveTab} />\n\n <div className=\"overview-cols\">\n <Card>\n <CardTitle>Mods</CardTitle>\n <CardMeta>Extensions installed under <code>~/.config/bizar/mods/</code></CardMeta>\n {mods.length === 0 ? (\n <div className=\"muted\">No mods installed.</div>\n ) : (\n <ul className=\"mod-mini-list\">\n {mods.map((m) => (\n <li key={m.id} className=\"mod-mini\">\n <span className=\"mod-mini-name\">{m.name}</span>\n <span className=\"mod-mini-meta\">v{m.version} · {m.type}</span>\n <span className={`mod-mini-pill ${m.enabled ? 'mod-mini-pill-on' : 'mod-mini-pill-off'}`}>\n {m.enabled ? 'on' : 'off'}\n </span>\n </li>\n ))}\n </ul>\n )}\n </Card>\n\n <Card>\n <CardTitle>Environment</CardTitle>\n <CardMeta>Runtime + paths</CardMeta>\n <dl className=\"env-table\">\n <dt>Node</dt>\n <dd className=\"mono\">{overview.versions.node}</dd>\n <dt>Platform</dt>\n <dd className=\"mono\">{overview.versions.platform}</dd>\n <dt>Project root</dt>\n <dd className=\"mono ellipsis\" title={overview.versions.projectRoot}>\n {overview.versions.projectRoot}\n </dd>\n <dt>Bizar root</dt>\n <dd className=\"mono ellipsis\" title={overview.versions.bizarRoot}>\n {overview.versions.bizarRoot}\n </dd>\n <dt>Generated</dt>\n <dd className=\"mono tabular-nums\">\n {formatTime(overview.generatedAt)}\n </dd>\n </dl>\n </Card>\n </div>\n </div>\n );\n}\n\n// ─── AddProjectDialog ─────────────────────────────────────────────────────────\n\n/**\n * Pre-flight approach: before POST /projects we verify the selected path\n * still exists (GET /fs?path=...). This avoids the ugly 404 toast when a\n * directory is deleted between selection and submit.\n */\nfunction AddProjectDialog({\n settings,\n onAdd,\n}: {\n settings: Settings;\n onAdd: (path: string, name: string | null) => void;\n}) {\n const [path, setPath] = useState(settings?.dashboard?.projectsDirectory ?? '');\n const [name, setName] = useState('');\n const [preflighting, setPreflighting] = useState(false);\n const [preflightError, setPreflightError] = useState<string | null>(null);\n\n const handleAdd = async () => {\n if (!path) return;\n setPreflighting(true);\n setPreflightError(null);\n try {\n // Pre-flight: verify the path still exists\n await api.get<DirectoryListing>('/fs?path=' + encodeURIComponent(path));\n // Path is valid — proceed with the POST\n onAdd(path, name || null);\n } catch (err) {\n const apiErr = err as { status?: number; data?: { message?: string } };\n if (apiErr.status === 404) {\n setPreflightError('That folder no longer exists. Pick another.');\n } else {\n setPreflightError(\n apiErr.data?.message ?? (err as Error).message ?? 'Validation failed.',\n );\n }\n } finally {\n setPreflighting(false);\n }\n };\n\n return (\n <div>\n <label className=\"field-label\">Folder</label>\n <FileBrowser\n value={path}\n onChange={(p) => {\n setPath(p);\n setPreflightError(null);\n }}\n projectsDirectory={settings?.dashboard?.projectsDirectory}\n height={320}\n />\n {preflightError && (\n <p className=\"field-help\" style={{ color: 'var(--error)', marginTop: 4 }}>\n {preflightError}\n </p>\n )}\n <div style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"add-project-name\">Name (optional)</label>\n <input\n id=\"add-project-name\"\n className=\"input\"\n type=\"text\"\n placeholder=\"My App\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <p className=\"field-help\" style={{ marginTop: 4 }}>\n Display name for this project. Defaults to the folder name.\n </p>\n </div>\n <div style={{ marginTop: 'var(--space-3)', display: 'flex', justifyContent: 'flex-end' }}>\n <Button\n variant=\"primary\"\n onClick={handleAdd}\n disabled={!path || preflighting}\n >\n {preflighting ? <span className=\"btn-spinner\" /> : null}\n {preflighting ? 'Checking…' : 'Add'}\n </Button>\n </div>\n </div>\n );\n}\n\nfunction ProjectCard({\n project,\n active,\n onOpen,\n onRemove,\n}: {\n project: ProjectRecord;\n active: boolean;\n onOpen: () => void;\n onRemove: () => void;\n}) {\n const statusColor = {\n active: 'status-on',\n inactive: 'status-neutral',\n error: 'status-error',\n }[project.status] || 'status-neutral';\n return (\n <div className={`project-card ${active ? 'project-card-active' : ''}`}>\n <div className=\"project-card-head\">\n <span className={`project-card-status ${statusColor}`}>\n {project.status}\n </span>\n <div className=\"project-card-name\">{project.name}</div>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Remove project\"\n title=\"Remove\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n >\n <Trash2 size={12} />\n </button>\n </div>\n <div className=\"project-card-path mono ellipsis\" title={project.path}>\n {project.path}\n </div>\n <div className=\"project-card-meta\">\n {project.lastAccessed && (\n <span className=\"muted\">Last opened {formatRelative(project.lastAccessed)}</span>\n )}\n </div>\n <div className=\"project-card-actions\">\n <Button variant={active ? 'ghost' : 'primary'} size=\"sm\" onClick={onOpen}>\n {active ? <><Power size={12} /> Active</> : <>Open</>}\n </Button>\n </div>\n </div>\n );\n}\n\nfunction sentenceCase(s: string): string {\n if (!s) return s;\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction humanizeKind(kind: string): string {\n const normalized = (kind || 'activity').trim().toLowerCase().replace(/[:_]/g, '.');\n const [scopeRaw, actionRaw = 'updated'] = normalized.split('.');\n const scopeMap: Record<string, string> = {\n settings: 'Settings',\n task: 'Task',\n tasks: 'Task',\n agent: 'Agent',\n agents: 'Agent',\n plan: 'Plan',\n plans: 'Plan',\n bg: 'Background job',\n background: 'Background job',\n session: 'Session',\n mod: 'Mod',\n mods: 'Mod',\n provider: 'Provider',\n providers: 'Provider',\n };\n const actionMap: Record<string, string> = {\n create: 'created', created: 'created',\n add: 'added', added: 'added',\n update: 'updated', updated: 'updated',\n delegate: 'delegated', delegated: 'delegated',\n invoke: 'invoked', invoked: 'invoked',\n restart: 'restarted', restarted: 'restarted',\n delete: 'deleted', deleted: 'deleted',\n remove: 'removed', removed: 'removed',\n archive: 'archived', archived: 'archived',\n restore: 'restored', restored: 'restored',\n complete: 'completed', completed: 'completed',\n fail: 'failed', failed: 'failed',\n error: 'errored', stuck: 'marked stuck',\n };\n const scope = scopeMap[scopeRaw] || sentenceCase(scopeRaw.replace(/-/g, ' '));\n const action = actionMap[actionRaw] || actionRaw.replace(/-/g, ' ');\n return `${scope} ${action}`.trim();\n}\n\nfunction firstString(it: ActivityItem, keys: string[]): string {\n for (const key of keys) {\n const value = it[key];\n if (typeof value === 'string' && value.trim()) return value.trim();\n }\n return '';\n}\n\nfunction formatActivitySummary(it: ActivityItem): string {\n const direct = firstString(it, ['message', 'text', 'prompt', 'title', 'name']);\n if (direct) return direct;\n const parts: string[] = [];\n const slug = firstString(it, ['slug']);\n const agent = firstString(it, ['agent', 'author']);\n const status = firstString(it, ['status']);\n if (slug) parts.push(`Plan ${slug}`);\n if (agent) parts.push(agent);\n if (status) parts.push(status);\n return parts.length ? parts.join(' · ') : 'No additional details.';\n}\n\n// v3.7.0 — Format a timestamp as a relative string (\"2m ago\", \"1h ago\")\nfunction formatRelativeTime(ts: string): string {\n return formatRelative(ts);\n}\n\n// v3.7.0 — Get severity color token from kind or status field\nfunction activitySeverity(it: ActivityItem): 'error' | 'warning' | 'success' | 'info' {\n const k = ((it.kind as string) || '').toLowerCase();\n const s = ((it.status as string) || '').toLowerCase();\n if (k.includes('error') || s === 'error' || s === 'failure') return 'error';\n if (k.includes('warn') || s === 'blocked') return 'warning';\n if (k.includes('done') || k.includes('success') || s === 'done') return 'success';\n return 'info';\n}\n\n// v3.7.0 — Map activity kind to icon\nfunction activityIcon(kind: string) {\n const k = kind.toLowerCase();\n if (k === 'task') return CheckSquare;\n if (k === 'agent') return Bot;\n if (k === 'plan') return Map;\n if (k.includes('bg') || k.includes('background') || k.includes('job')) return Zap;\n if (k === 'mod') return Puzzle;\n if (k === 'skill') return Sparkles;\n if (k.includes('error') || k.includes('failure')) return AlertOctagon;\n if (k.includes('warn')) return AlertTriangle;\n return Activity;\n}\n\n// v3.7.0 — Navigate to the relevant tab when a card is clicked\nfunction activityNavTarget(kind: string): string | null {\n const k = kind.toLowerCase();\n if (k === 'task') return 'tasks';\n if (k === 'agent') return 'agents';\n if (k === 'plan') return 'artifacts';\n if (k.includes('bg') || k.includes('background')) return 'activity';\n if (k === 'mod') return 'mods';\n if (k === 'skill') return 'skills';\n return null;\n}\n\n// v3.7.0 — Activity card component\nfunction ActivityFeedItem({\n item,\n activityKey,\n onNavigate,\n onHide,\n}: {\n item: ActivityItem;\n activityKey: string;\n onNavigate: (tab: string) => void;\n onHide: (key: string) => void;\n}) {\n const severity = activitySeverity(item);\n const Icon = activityIcon(item.kind || '');\n const title = humanizeKind(item.kind || 'activity');\n const msg = formatActivitySummary(item);\n const navTarget = activityNavTarget(item.kind || '');\n\n const accentColor =\n severity === 'error' ? 'var(--error)' :\n severity === 'warning' ? 'var(--warning)' :\n severity === 'success' ? 'var(--success)' :\n 'var(--accent)';\n\n return (\n <div className={cn('activity-feed-row', `activity-feed-row-${severity}`)}>\n <button\n type=\"button\"\n className=\"activity-feed-row-main\"\n onClick={() => { if (navTarget) onNavigate(navTarget); }}\n title={navTarget ? `Open ${navTarget}` : title}\n >\n <div className=\"activity-feed-icon\" style={{ color: accentColor }}>\n <Icon size={14} />\n </div>\n <div className=\"activity-feed-body\">\n <div className=\"activity-feed-title-row\">\n <div className=\"activity-feed-title\">{title}</div>\n <div className=\"activity-feed-time text-xs muted tabular-nums\">{formatRelativeTime(item.ts)}</div>\n </div>\n <div className=\"activity-feed-summary text-sm\">{msg}</div>\n </div>\n </button>\n <button\n type=\"button\"\n className=\"activity-feed-hide-btn\"\n onClick={() => onHide(activityKey)}\n title=\"Hide this from the overview (kept in Settings → Activity Log)\"\n aria-label=\"Hide from overview\"\n >\n <X size={12} />\n </button>\n </div>\n );\n}\nconst OverviewMemo = React.memo(OverviewInner);\nexport { OverviewMemo as Overview };\n","// src/components/chat/SessionRowMenu.tsx — three-mode popover for a session rail row.\n//\n// Three modes:\n// 'main' — Rename + Delete buttons\n// 'rename' — Inline input with Cancel/Save\n// 'confirm-delete' — Inline confirmation with Cancel/Delete\n//\n// Rendered via createPortal on document.body so it isn't clipped by\n// the rail's overflow:auto scroll container. The parent row supplies\n// the anchor's bounding rect (or the menu uses an anchor prop).\n\nimport { useEffect, useRef } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Edit, Trash2 } from 'lucide-react';\n\nexport type SessionMenuMode = 'main' | 'rename' | 'confirm-delete';\n\nexport interface SessionRowMenuAnchor {\n /** Bounding rect of the trigger / row used to position the popover. */\n rect: DOMRect;\n}\n\nexport interface SessionRowMenuProps {\n session: { id: string; title: string };\n mode: SessionMenuMode;\n anchor: SessionRowMenuAnchor;\n renameDraft: string;\n setRenameDraft: (s: string) => void;\n onEdit: () => void;\n onDeleteRequest: () => void;\n onConfirmDelete: () => void;\n onConfirmRename: () => void;\n onClose: () => void;\n}\n\nexport function SessionRowMenu({\n session,\n mode,\n anchor,\n renameDraft,\n setRenameDraft,\n onEdit,\n onDeleteRequest,\n onConfirmDelete,\n onConfirmRename,\n onClose,\n}: SessionRowMenuProps) {\n const ref = useRef<HTMLDivElement | null>(null);\n\n // Position the popover just below the row's right edge.\n const top = Math.round(anchor.rect.bottom + 2);\n const right = Math.max(8, Math.round(window.innerWidth - anchor.rect.right));\n\n // Close on outside click + Esc.\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n const t = e.target as Node | null;\n if (!ref.current || !t) return;\n if (ref.current.contains(t)) return;\n onClose();\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n // Defer attaching the outside-click handler so the click that opened\n // the menu doesn't immediately close it.\n const id = window.setTimeout(() => {\n document.addEventListener('mousedown', onDown);\n document.addEventListener('keydown', onKey);\n }, 0);\n return () => {\n window.clearTimeout(id);\n document.removeEventListener('mousedown', onDown);\n document.removeEventListener('keydown', onKey);\n };\n }, [onClose]);\n\n // Auto-focus the rename input when entering rename mode.\n useEffect(() => {\n if (mode !== 'rename') return;\n const id = window.setTimeout(() => {\n const input = ref.current?.querySelector<HTMLInputElement>('input.session-row-menu-input');\n input?.focus();\n input?.select();\n }, 0);\n return () => window.clearTimeout(id);\n }, [mode]);\n\n const body = (\n <div\n ref={ref}\n className=\"session-row-menu\"\n role=\"menu\"\n aria-label={`Options for ${session.title}`}\n style={{ position: 'fixed', top, right }}\n onClick={(e) => e.stopPropagation()}\n >\n {mode === 'main' && (\n <>\n <button\n type=\"button\"\n className=\"session-row-menu-item\"\n role=\"menuitem\"\n onClick={(e) => {\n e.stopPropagation();\n onEdit();\n }}\n >\n <Edit size={13} aria-hidden />\n <span>Rename</span>\n <kbd>R</kbd>\n </button>\n <button\n type=\"button\"\n className=\"session-row-menu-item session-row-menu-item-danger\"\n role=\"menuitem\"\n onClick={(e) => {\n e.stopPropagation();\n onDeleteRequest();\n }}\n >\n <Trash2 size={13} aria-hidden />\n <span>Delete</span>\n <kbd>⌫</kbd>\n </button>\n </>\n )}\n {mode === 'rename' && (\n <div className=\"session-row-menu-inline\">\n <div className=\"session-row-menu-inline-label chat-mono\">Rename session</div>\n <input\n type=\"text\"\n className=\"session-row-menu-input\"\n value={renameDraft}\n onChange={(e) => setRenameDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n onConfirmRename();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n }}\n onClick={(e) => e.stopPropagation()}\n aria-label=\"New session name\"\n />\n <div className=\"session-row-menu-inline-actions\">\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n onClick={(e) => {\n e.stopPropagation();\n onClose();\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n onClick={(e) => {\n e.stopPropagation();\n onConfirmRename();\n }}\n >\n Save\n </button>\n </div>\n </div>\n )}\n {mode === 'confirm-delete' && (\n <div className=\"session-row-menu-inline\">\n <div className=\"session-row-menu-inline-label chat-mono\">Delete this session?</div>\n <div className=\"session-row-menu-inline-message\">\n \"{session.title}\" and its sub-agents will be removed.\n </div>\n <div className=\"session-row-menu-inline-actions\">\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n onClick={(e) => {\n e.stopPropagation();\n onClose();\n }}\n >\n Cancel\n </button>\n <button\n type=\"button\"\n className=\"btn btn-danger\"\n onClick={(e) => {\n e.stopPropagation();\n onConfirmDelete();\n }}\n >\n Delete\n </button>\n </div>\n </div>\n )}\n </div>\n );\n\n return createPortal(body, document.body);\n}","// src/components/chat/AgentNode.tsx — single card in the agent orchestration tree.\n//\n// Two modes:\n// collapsible=true — header is a button with a chevron; toggles its\n// own summary + children visibility.\n// collapsible=false — header is a static div (no chevron / no toggle).\n// Children render if present but cannot be\n// collapsed by the user.\n//\n// FIX #1 (session-collapsed-by-default) is handled at the *parent*\n// (SubAgentList / AgentTree) which decides whether to mount this\n// node's children at all. This component is purely presentational.\n\nimport { useState } from 'react';\n\nexport type AgentStatus = 'idle' | 'streaming' | 'done' | 'blocked' | 'awaiting';\n\nexport interface AgentTreeNode {\n id: string;\n name: string;\n role?: string;\n status: AgentStatus;\n summary?: string;\n children?: AgentTreeNode[];\n}\n\ninterface Props {\n node: AgentTreeNode;\n depth?: number;\n collapsible?: boolean;\n isLast?: boolean;\n /** Controlled open state — used by SubAgentList so the parent rail\n * row's tree-chevron is the single source of truth for collapse. */\n open?: boolean;\n onToggle?: (next: boolean) => void;\n}\n\nexport function AgentNode({\n node,\n depth = 0,\n collapsible = false,\n isLast = true,\n open: controlledOpen,\n onToggle,\n}: Props) {\n const [internalOpen, setInternalOpen] = useState<boolean>(collapsible);\n const isControlled = controlledOpen !== undefined;\n const open = isControlled ? controlledOpen : internalOpen;\n const setOpen = (next: boolean) => {\n if (!isControlled) setInternalOpen(next);\n onToggle?.(next);\n };\n\n const hasChildren = (node.children?.length ?? 0) > 0;\n\n const headContent = (\n <>\n {collapsible && (\n <span\n className={`agent-node-chevron ${open ? 'open' : ''}`}\n aria-hidden\n >\n ›\n </span>\n )}\n <span\n className={`agent-node-dot status-${node.status}`}\n aria-hidden\n />\n <span className=\"agent-node-name\">{node.name}</span>\n {node.role && <span className=\"agent-node-role chat-mono\">{node.role}</span>}\n <span className={`agent-node-pill status-${node.status}`}>{node.status}</span>\n </>\n );\n\n return (\n <div\n className={[\n 'agent-node',\n `depth-${depth}`,\n `status-${node.status}`,\n open ? 'open' : 'closed',\n isLast ? 'last' : '',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {collapsible ? (\n <button\n type=\"button\"\n className={`agent-node-head status-${node.status} collapsible`}\n onClick={(e) => {\n e.stopPropagation();\n setOpen(!open);\n }}\n aria-expanded={open}\n >\n {headContent}\n </button>\n ) : (\n <div className={`agent-node-head status-${node.status}`}>\n {headContent}\n </div>\n )}\n {open && (\n <>\n {node.summary && (\n <div className=\"agent-node-summary\">{node.summary}</div>\n )}\n {hasChildren && (\n <div className=\"agent-node-children\">\n {node.children!.map((child, i) => (\n <AgentNode\n key={child.id}\n node={child}\n depth={depth + 1}\n collapsible={false}\n isLast={i === node.children!.length - 1}\n />\n ))}\n </div>\n )}\n </>\n )}\n </div>\n );\n}","// src/components/chat/AgentTree.tsx — vertical chain of session cards connected by\n// backbone+L-stub connectors. Two modes:\n//\n// full tree (variant=\"full\") — renders the root card and all its children.\n// Used inside the thread head when the active session has sub-agents.\n//\n// children-only (variant=\"rail\" via SubAgentList) — renders only the children\n// of the root; the rail row above already shows the root card, so\n// re-rendering it would duplicate. Children hang directly off the\n// rail row via standard backbone + L-stub connectors.\n//\n// FIX #1 — the parent (ChatRail) passes `open=false` by default for a\n// freshly-clicked session so the tree is collapsed on first click; the\n// user can open it via the chevron in the row.\n\nimport { Fragment } from 'react';\nimport { AgentNode, type AgentTreeNode } from './AgentNode';\n\ninterface FullTreeProps {\n tree: { root: AgentTreeNode };\n variant?: 'full';\n open?: boolean;\n}\n\ninterface ChildrenOnlyProps {\n children: AgentTreeNode[];\n variant: 'rail' | 'thread';\n open?: boolean;\n}\n\nfunction isFullTree(props: FullTreeProps | ChildrenOnlyProps): props is FullTreeProps {\n return (props as FullTreeProps).tree !== undefined;\n}\n\nexport function AgentTree(props: FullTreeProps | ChildrenOnlyProps) {\n const open = props.open ?? true;\n\n if (isFullTree(props)) {\n return (\n <div className={`agent-tree variant-${props.variant ?? 'full'}`}>\n <AgentNode node={props.tree.root} depth={0} open={open} />\n </div>\n );\n }\n\n // Children-only path (used by SubAgentList hanging off the rail row).\n const list = props.children ?? [];\n return (\n <div className={`agent-tree variant-${props.variant} agent-tree-children-only`}>\n <div className=\"agent-tree-children-body\">\n {list.map((child, i) => (\n <Fragment key={child.id}>\n <AgentNode\n node={child}\n depth={0}\n collapsible={false}\n open={open}\n isLast={i === list.length - 1}\n />\n </Fragment>\n ))}\n </div>\n </div>\n );\n}\n\n/* ── SubAgentList — convenience wrapper used by the ChatRail to render\n the children of a session's tree directly under the active row. ── */\nexport function SubAgentList({\n children,\n variant = 'rail',\n open = true,\n}: {\n children: AgentTreeNode[];\n variant?: 'rail' | 'thread';\n open?: boolean;\n}) {\n if (!open) return null;\n return <AgentTree variant={variant} open={open} children={children} />;\n}","// src/components/chat/ChatRail.tsx — redesigned session rail (v3.22).\n//\n// Replaces the original SessionList. Layout follows the design HTML:\n// - sessions grouped by recency (Today / Yesterday / This week / Earlier)\n// - each row carries: status dot, title (with pin star), time + unread\n// badge, 3-dot menu trigger (hover-visible, top-right), and (when\n// active + has children) a collapse chevron (vertical-center,\n// right: 28px — to the LEFT of the 3-dot trigger so they never\n// overlap — see chat.css for the exact positioning).\n// - per-row 3-dot popover menu with three modes: main (rename/delete),\n// rename (inline input), confirm-delete (inline confirmation).\n// - active row hangs the agent orchestration tree below it (collapsed\n// by default on first click per FIX #1 — the user opens it via the\n// chevron).\n//\n// Props match the original SessionList so it can be swapped into\n// Chat.tsx without any further wiring. The new props are optional and\n// augment the rail with state + tree + menu behavior when supplied.\n\nimport { Fragment, useMemo, useRef, useState } from 'react';\nimport { Plus, ExternalLink } from 'lucide-react';\nimport type { ChatSession } from '../../lib/types';\nimport { EmptyState } from './EmptyState';\nimport { SessionRowMenu, type SessionMenuMode } from './SessionRowMenu';\nimport { SubAgentList } from './AgentTree';\nimport type { AgentTreeNode } from './AgentNode';\n\n/* ------------------------------------------------------------------ *\n * Display-augmented session shape. The data coming from the API is\n * a bare `ChatSession`; the rail overlays optional display fields.\n * ------------------------------------------------------------------ */\nexport type SessionState = 'idle' | 'streaming' | 'awaiting';\n\nexport interface DisplaySession extends ChatSession {\n state?: SessionState;\n unread?: number;\n pinned?: boolean;\n /** HH:MM display string; defaults derived from mtime */\n time?: string;\n /** Agent name shown in the row subtitle / status dot */\n agent?: string;\n /** Sub-agent tree for this session (root may have children). */\n tree?: { root: AgentTreeNode };\n}\n\ninterface Props {\n sessions: DisplaySession[];\n opencodeSessions?: DisplaySession[];\n activeSessionId: string;\n activeOpencodeSessionId: string | null;\n activeProject: { name: string } | null;\n creating: boolean;\n onCreateSession: () => void;\n onSelectSession: (id: string) => void;\n onSelectOpencodeSession: (s: DisplaySession) => void;\n /** Optional: rename / delete handlers. When omitted, those buttons\n * in the menu fall back to no-op + toast hint. */\n onRenameSession?: (id: string, title: string) => void;\n onDeleteSession?: (id: string) => void;\n /** Optional: group predicate. By default groups by day buckets. */\n groupBy?: (sessions: DisplaySession[]) => Record<string, DisplaySession[]>;\n}\n\nconst DEFAULT_GROUPS = ['Today', 'Yesterday', 'This week', 'Earlier'];\n\nfunction isSameDay(a: Date, b: Date) {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n}\n\nfunction dayDiff(a: Date, b: Date) {\n const ms = a.getTime() - b.getTime();\n return Math.floor(ms / (1000 * 60 * 60 * 24));\n}\n\nfunction defaultGroupBy(sessions: DisplaySession[]): Record<string, DisplaySession[]> {\n const now = new Date();\n const yesterday = new Date(now);\n yesterday.setDate(yesterday.getDate() - 1);\n const weekAgo = new Date(now);\n weekAgo.setDate(weekAgo.getDate() - 7);\n\n const groups: Record<string, DisplaySession[]> = {\n Today: [],\n Yesterday: [],\n 'This week': [],\n Earlier: [],\n };\n\n for (const s of sessions) {\n const d = new Date(Number(s.mtime) || Date.now());\n if (isSameDay(d, now)) groups.Today.push(s);\n else if (isSameDay(d, yesterday)) groups.Yesterday.push(s);\n else if (dayDiff(now, d) < 7) groups['This week'].push(s);\n else groups.Earlier.push(s);\n }\n return groups;\n}\n\nfunction formatTime(mtime: number): string {\n const d = new Date(Number(mtime) || Date.now());\n return d.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n}\n\nfunction SessionStateIndicator({\n state,\n agent,\n}: {\n state: SessionState;\n agent?: string;\n}) {\n if (state === 'streaming') {\n return (\n <span\n className=\"session-state session-state-streaming\"\n title={`${agent || 'Odin'} is typing…`}\n />\n );\n }\n if (state === 'awaiting') {\n return (\n <span\n className=\"session-state session-state-awaiting\"\n title=\"Awaiting your reply\"\n aria-hidden\n />\n );\n }\n if (state === 'idle') {\n return <span className=\"session-state session-state-idle\" aria-hidden />;\n }\n return null;\n}\n\nexport function ChatRail({\n sessions,\n opencodeSessions = [],\n activeSessionId,\n activeOpencodeSessionId,\n activeProject,\n creating,\n onCreateSession,\n onSelectSession,\n onSelectOpencodeSession,\n onRenameSession,\n onDeleteSession,\n groupBy,\n}: Props) {\n const allSessions = useMemo<DisplaySession[]>(\n () => [...sessions, ...opencodeSessions],\n [sessions, opencodeSessions],\n );\n const sorted = useMemo(\n () => [...allSessions].sort((a, b) => Number(b.mtime ?? 0) - Number(a.mtime ?? 0)),\n [allSessions],\n );\n\n const grouped = useMemo(\n () => (groupBy ? groupBy(sorted) : defaultGroupBy(sorted)),\n [groupBy, sorted],\n );\n\n // FIX #1 — collapse-by-default for the active session's sub-agent\n // tree. State is per-session-id so toggling one session doesn't\n // reset the others.\n const [openTree, setOpenTree] = useState<Record<string, boolean>>({});\n const isTreeOpen = (id: string) => openTree[id] === true;\n\n // Per-row menu state (which session's menu is open + which mode).\n const [openMenuId, setOpenMenuId] = useState<string | null>(null);\n const [menuMode, setMenuMode] = useState<SessionMenuMode>('main');\n const [renameDraft, setRenameDraft] = useState('');\n const [menuAnchor, setMenuAnchor] = useState<{ id: string; rect: DOMRect } | null>(null);\n const rowRefs = useRef<Record<string, HTMLDivElement | null>>({});\n\n const openMenuFor = (id: string, mode: SessionMenuMode = 'main') => {\n const row = rowRefs.current[id];\n if (!row) return;\n const target =\n mode === 'main'\n ? row\n : row.querySelector<HTMLElement>('.chat-rail-item-menu-trigger') ?? row;\n setMenuAnchor({ id, rect: target.getBoundingClientRect() });\n setOpenMenuId(id);\n setMenuMode(mode);\n if (mode === 'rename') {\n const s = [...sessions, ...opencodeSessions].find((x) => x.id === id);\n setRenameDraft(s?.title ?? s?.id ?? '');\n }\n };\n const closeMenu = () => {\n setOpenMenuId(null);\n setMenuMode('main');\n setRenameDraft('');\n setMenuAnchor(null);\n };\n\n const handleSelect = (s: DisplaySession) => {\n if (s.source === 'opencode') {\n onSelectOpencodeSession(s);\n return;\n }\n onSelectSession(s.id);\n };\n\n const handleConfirmRename = () => {\n if (!menuAnchor) return;\n const sid = menuAnchor.id;\n const next = renameDraft.trim();\n if (!next) {\n closeMenu();\n return;\n }\n onRenameSession?.(sid, next);\n closeMenu();\n };\n\n const handleConfirmDelete = () => {\n if (!menuAnchor) return;\n onDeleteSession?.(menuAnchor.id);\n closeMenu();\n };\n\n const orderedGroups: Array<[string, DisplaySession[]]> = groupBy\n ? Object.entries(grouped)\n : DEFAULT_GROUPS.filter((g) => grouped[g]?.length).map(\n (g) => [g, grouped[g]] as [string, DisplaySession[]],\n );\n\n return (\n <aside className=\"chat-rail\">\n <div className=\"chat-rail-head\">\n <button\n type=\"button\"\n className=\"chat-new-btn\"\n onClick={onCreateSession}\n disabled={creating || !activeProject}\n title={activeProject ? 'Create new session' : 'Pick a project first'}\n aria-label=\"Create new session\"\n >\n <Plus size={14} aria-hidden />\n <span>{creating ? 'Creating…' : 'New session'}</span>\n </button>\n </div>\n\n {sorted.length === 0 ? (\n <div className=\"chat-sessions-empty\">\n <EmptyState\n icon={<Plus size={20} aria-hidden />}\n title={activeProject ? 'No sessions yet' : 'No project'}\n message={\n activeProject\n ? 'Create your first session to start chatting.'\n : 'Pick a project in Overview to scope chat sessions.'\n }\n />\n </div>\n ) : (\n <div className=\"chat-rail-list\">\n {orderedGroups.map(([group, items]) => (\n <div key={group} className=\"chat-rail-group\">\n <div className=\"chat-rail-group-label\">{group}</div>\n {items.map((s) => {\n const isOpencode = s.source === 'opencode';\n const isActive = isOpencode\n ? activeOpencodeSessionId === s.id\n : activeSessionId === s.id;\n const tree = s.tree;\n const hasChildren = !!(tree?.root?.children && tree.root.children.length > 0);\n const treeOpen = isTreeOpen(s.id);\n return (\n <Fragment key={isOpencode ? `oc-${s.id}` : s.id}>\n <div\n ref={(el) => {\n rowRefs.current[s.id] = el;\n }}\n role=\"button\"\n tabIndex={0}\n className={`chat-rail-item state-${s.state ?? 'idle'}${isActive ? ' active' : ''}`}\n onClick={() => handleSelect(s)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleSelect(s);\n }\n }}\n aria-current={isActive ? 'true' : undefined}\n >\n <SessionStateIndicator state={s.state ?? 'idle'} agent={s.agent} />\n <div className=\"chat-rail-item-title\">\n {s.pinned && (\n <span className=\"chat-rail-pin\" aria-hidden>\n ★\n </span>\n )}\n {isOpencode && (\n <ExternalLink\n size={11}\n style={{ color: 'var(--text-muted)', flexShrink: 0 }}\n aria-hidden\n />\n )}\n <span className=\"chat-ellipsis\">{s.title || s.id}</span>\n </div>\n <div className=\"chat-rail-item-meta\">\n <span className=\"chat-rail-item-meta-time\">\n {s.time ?? formatTime(s.mtime)}\n </span>\n {(s.unread ?? 0) > 0 && (\n <span className=\"chat-rail-badge\">{s.unread}</span>\n )}\n </div>\n <button\n type=\"button\"\n className={`chat-rail-item-menu-trigger${openMenuId === s.id ? ' open' : ''}`}\n aria-label={`Session options for ${s.title || s.id}`}\n aria-haspopup=\"menu\"\n aria-expanded={openMenuId === s.id}\n onClick={(e) => {\n e.stopPropagation();\n if (openMenuId === s.id) closeMenu();\n else openMenuFor(s.id, 'main');\n }}\n >\n <svg viewBox=\"0 0 14 14\" aria-hidden>\n <circle cx=\"3\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" />\n <circle cx=\"7\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" />\n <circle cx=\"11\" cy=\"7\" r=\"1.2\" fill=\"currentColor\" />\n </svg>\n </button>\n {isActive && hasChildren && (\n <button\n type=\"button\"\n className={`chat-rail-tree-chevron${treeOpen ? ' open' : ''}`}\n aria-label={treeOpen ? 'Collapse sub-agents' : 'Expand sub-agents'}\n aria-expanded={treeOpen}\n onClick={(e) => {\n e.stopPropagation();\n setOpenTree((cur) => ({ ...cur, [s.id]: !cur[s.id] }));\n }}\n >\n <svg viewBox=\"0 0 10 10\" aria-hidden>\n <polyline points=\"3,1.5 7,5 3,8.5\" />\n </svg>\n </button>\n )}\n </div>\n {isActive && hasChildren && treeOpen && tree?.root?.children && (\n <SubAgentList children={tree.root.children} variant=\"rail\" open />\n )}\n </Fragment>\n );\n })}\n </div>\n ))}\n </div>\n )}\n\n {openMenuId && menuAnchor && (\n <SessionRowMenu\n session={{\n id: menuAnchor.id,\n title:\n [...sessions, ...opencodeSessions].find((x) => x.id === menuAnchor.id)\n ?.title ?? menuAnchor.id,\n }}\n mode={menuMode}\n anchor={menuAnchor}\n renameDraft={renameDraft}\n setRenameDraft={setRenameDraft}\n onEdit={() => openMenuFor(openMenuId, 'rename')}\n onDeleteRequest={() => openMenuFor(openMenuId, 'confirm-delete')}\n onConfirmDelete={handleConfirmDelete}\n onConfirmRename={handleConfirmRename}\n onClose={closeMenu}\n />\n )}\n </aside>\n );\n}","// src/components/chat/ChatComposer.tsx — bottom composer pill (v4.2.5).\n//\n// v4.2.5 — small refinement: the pill's border picks up the\n// activeSource color (opencode → accent border; bizar → neutral),\n// so the user has visual confirmation that their next message will\n// land in the right backend.\n\nimport { useState } from 'react';\nimport { Composer } from './Composer';\n\ninterface Props {\n agent: string;\n setAgent: (a: string) => void;\n model: string;\n setModel: (m: string) => void;\n text: string;\n setText: (t: string) => void;\n sending: boolean;\n onSend: () => void;\n attachments: string[];\n setAttachments: (a: string[] | ((prev: string[]) => string[])) => void;\n suggestions: Array<{ cmd: string; desc: string }>;\n onPickSuggestion: (cmd: string) => void;\n agents: Array<{ name: string }>;\n onAttach: () => void;\n /** Which stream will receive the next message. */\n activeSource?: 'bizar' | 'opencode' | null;\n /** Backward-compat — used to be page-level panel toggles. Ignored. */\n sessionsOpen?: boolean;\n /** Backward-compat — see sessionsOpen. */\n infoOpen?: boolean;\n}\n\nexport function ChatComposer(props: Props) {\n const { text, sending, onSend, activeSource } = props;\n const [takingOff, setTakingOff] = useState(false);\n\n const handleSend = () => {\n if (!text.trim() || sending) return;\n setTakingOff(true);\n onSend();\n window.setTimeout(() => setTakingOff(false), 320);\n };\n\n return (\n <div\n className={`chat-composer-wrap chat-composer-source-${activeSource ?? 'none'}`}\n >\n <div className={`chat-composer-pill${takingOff ? ' takeoff' : ''}`}>\n <Composer {...props} onSend={handleSend} />\n </div>\n <div className=\"chat-composer-hint chat-muted\">\n <span>\n <kbd>⏎</kbd> send\n </span>\n <span>\n <kbd>⇧⏎</kbd> newline\n </span>\n <span>\n <kbd>/</kbd> commands\n </span>\n {activeSource === 'opencode' && (\n <span className=\"chat-composer-source-hint\">→ opencode</span>\n )}\n {activeSource === 'bizar' && (\n <span className=\"chat-composer-source-hint\">→ bizar chat</span>\n )}\n {sending && <span className=\"chat-composer-source-hint\">sending…</span>}\n </div>\n </div>\n );\n}\n","// src/components/chat/ChatInfoPanel.tsx — right info panel (v4.2.5).\n//\n// v4.2.5 — overhauled: shows session metadata (id, agent, model,\n// provider, message count), the current `activeSource`, the model\n// in use, a section for usage/cost placeholders (filled in by the\n// MiniMax usage module when present), and rename / delete / export\n// actions wired to the parent.\n\nimport { useEffect, useState } from 'react';\nimport {\n MessageSquare,\n Bot,\n Server,\n Terminal,\n Pencil,\n Trash2,\n Download,\n CircleDollarSign,\n} from 'lucide-react';\nimport type { ChatMessage } from '../../lib/types';\n\ninterface Props {\n sessionId: string;\n messages: ChatMessage[];\n pinned: Set<number>;\n agent: string;\n model: string;\n agents: Array<{ name: string; model?: string; mode?: string }>;\n mcps: Array<{ id: string; command?: string; enabled?: boolean }>;\n allCommands: Array<{ cmd: string; desc: string; mod?: string }>;\n /** Which stream is currently displayed. */\n activeSource?: 'bizar' | 'opencode' | null;\n /** Optional rename/delete/export handlers wired by Chat.tsx. */\n onRename?: () => void;\n onDelete?: () => void;\n onExport?: () => void;\n /** Per-action busy flags — disable buttons while pending. */\n busy?: { rename?: boolean; delete?: boolean };\n}\n\ninterface UsageRow {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n costUsd: number;\n}\n\nfunction formatNumber(n: number): string {\n return n.toLocaleString();\n}\n\n/** Map a model id like \"opencode/deepseek-v4-flash-free\" → \"opencode\". */\nfunction providerFromModel(model: string): string {\n if (!model) return '';\n if (!model.includes('/')) return '';\n return model.split('/')[0];\n}\n\n/** Map a model id to a cost (USD/M-token) — placeholder rates; the\n * MiniMax usage module supplies real numbers where available. */\nfunction approxCostPer1M(model: string): number {\n if (!model) return 0;\n const m = model.toLowerCase();\n if (m.includes('opus')) return 15;\n if (m.includes('sonnet')) return 3;\n if (m.includes('haiku')) return 0.8;\n if (m.includes('gpt-4o')) return 5;\n if (m.includes('gpt-4')) return 10;\n if (m.includes('deepseek')) return 0.27;\n if (m.includes('minimax')) return 0.3;\n if (m.includes('llama-3.3-70b')) return 0.59;\n return 1;\n}\n\nexport function ChatInfoPanel({\n sessionId,\n messages,\n pinned,\n agent,\n model,\n agents,\n mcps,\n allCommands,\n activeSource = 'bizar',\n onRename,\n onDelete,\n onExport,\n busy,\n}: Props) {\n // Best-effort: pull usage summary from the MiniMax usage endpoint\n // when the session is opencode. Falls back silently if the module\n // isn't installed yet.\n const [usage, setUsage] = useState<UsageRow | null>(null);\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const res = await fetch('/api/usage?range=24h', {\n headers: { Accept: 'application/json' },\n });\n if (!res.ok) return;\n const body = (await res.json()) as UsageRow;\n if (!cancelled) setUsage(body);\n } catch {\n /* ignore — usage is non-essential */\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [sessionId]);\n\n const msgCount = messages?.length ?? 0;\n const pinnedCount = pinned?.size ?? 0;\n\n // Estimate tokens / cost from message length when no real usage\n // data is available. Real numbers come from the MiniMax module.\n const totalChars = messages.reduce(\n (n, m) => n + ((m.content || m.message || '') as string).length,\n 0,\n );\n const approxTokens = Math.round(totalChars / 4);\n const rate = approxCostPer1M(model);\n const approxCostUsd = (approxTokens / 1_000_000) * rate;\n const tokensUsed = usage?.totalTokens ?? approxTokens;\n const costUsd = usage?.costUsd ?? approxCostUsd;\n const tokensTotal = 128_000;\n const provider = providerFromModel(model);\n\n return (\n <aside className=\"chat-info\">\n <div className=\"chat-info-section\">\n <div className=\"chat-info-section-head\">\n <h4>\n <MessageSquare\n size={11}\n style={{ marginRight: 4, verticalAlign: -1 }}\n aria-hidden\n />{' '}\n Session\n </h4>\n <span\n className={`chat-source-badge chat-source-${activeSource ?? 'none'}`}\n style={{ marginLeft: 'auto' }}\n >\n {activeSource === 'opencode' ? 'opencode' : 'bizar chat'}\n </span>\n </div>\n <div className=\"chat-info-mono chat-ellipsis\" title={sessionId}>\n {sessionId || 'Live'}\n </div>\n <div className=\"chat-info-mono\">\n {formatNumber(msgCount)} message{msgCount === 1 ? '' : 's'}\n {pinnedCount > 0 && ` · ${pinnedCount} pinned`}\n </div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Bot size={11} style={{ marginRight: 4, verticalAlign: -1 }} aria-hidden />{' '}\n Agent\n </h4>\n <div className=\"chat-info-value\">{agent || '—'}</div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Server size={11} style={{ marginRight: 4, verticalAlign: -1 }} aria-hidden />{' '}\n Model\n </h4>\n <div className=\"chat-mono chat-ellipsis\" title={model}>\n {model || '—'}\n </div>\n {provider && (\n <div className=\"chat-info-mono\">provider · {provider}</div>\n )}\n </div>\n\n <div className=\"chat-info-section\">\n <h4>Tokens</h4>\n <div className=\"chat-mono\">\n {formatNumber(tokensUsed)} / {formatNumber(tokensTotal)}\n </div>\n <div className=\"chat-info-bar\" aria-hidden>\n <div\n className=\"chat-info-bar-fill\"\n style={{\n width: `${Math.min(100, (tokensUsed / Math.max(1, tokensTotal)) * 100)}%`,\n }}\n />\n </div>\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <CircleDollarSign\n size={11}\n style={{ marginRight: 4, verticalAlign: -1 }}\n aria-hidden\n />{' '}\n Cost\n </h4>\n <div className=\"chat-mono\">${costUsd.toFixed(4)}</div>\n {!usage && (\n <div className=\"chat-info-mono\">approx · live from MiniMax</div>\n )}\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Bot\n size={11}\n style={{ marginRight: 4, verticalAlign: -1 }}\n aria-hidden\n />{' '}\n Attached agents\n </h4>\n {agents?.length ? (\n <div className=\"chat-info-agents\">\n {agents.map((a) => (\n <span key={a.name} className=\"chat-info-agent\">\n {a.name}\n </span>\n ))}\n </div>\n ) : (\n <div className=\"chat-info-mono\">None attached</div>\n )}\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Server\n size={11}\n style={{ marginRight: 4, verticalAlign: -1 }}\n aria-hidden\n />{' '}\n MCPs\n </h4>\n {mcps?.length ? (\n <div className=\"chat-info-agents\">\n {mcps.map((m) => (\n <span key={m.id} className=\"chat-info-agent\">\n {m.id}\n </span>\n ))}\n </div>\n ) : (\n <div className=\"chat-info-mono\">No MCPs configured</div>\n )}\n </div>\n\n <div className=\"chat-info-section\">\n <h4>\n <Terminal\n size={11}\n style={{ marginRight: 4, verticalAlign: -1 }}\n aria-hidden\n />{' '}\n Slash commands\n </h4>\n <div className=\"chat-info-mono\">{allCommands?.length ?? 0} available</div>\n </div>\n\n {(onRename || onDelete || onExport) && (\n <div className=\"chat-info-section\">\n <h4>Actions</h4>\n <div className=\"chat-info-actions\">\n {onRename && (\n <button\n type=\"button\"\n className=\"btn btn-ghost btn-sm\"\n onClick={onRename}\n disabled={busy?.rename}\n title=\"Rename session\"\n >\n <Pencil size={12} aria-hidden /> Rename\n </button>\n )}\n {onExport && (\n <button\n type=\"button\"\n className=\"btn btn-ghost btn-sm\"\n onClick={onExport}\n title=\"Export transcript\"\n >\n <Download size={12} aria-hidden /> Export\n </button>\n )}\n {onDelete && (\n <button\n type=\"button\"\n className=\"btn btn-ghost btn-sm btn-danger\"\n onClick={onDelete}\n disabled={busy?.delete}\n title=\"Delete session\"\n >\n <Trash2 size={12} aria-hidden /> Delete\n </button>\n )}\n </div>\n </div>\n )}\n </aside>\n );\n}\n","// src/components/chat/JumpToLatest.tsx — floating pill above the composer.\n//\n// Two visual variants:\n// - streaming (current session is being replied to): pulsing indigo\n// border + 3-dot bounce + green \"live\" badge\n// - idle: neutral pill + down-arrow icon + \"N new\" badge\n//\n// Hidden entirely when the user is already at the bottom of the thread\n// (controlled by the parent's `stickToBottom` flag).\n\nimport { ArrowDown } from 'lucide-react';\n\ninterface Props {\n streaming: boolean;\n newMessageCount: number;\n onClick: () => void;\n /** Optional label override (e.g. \"Odin is replying\"). */\n streamingLabel?: string;\n}\n\nexport function JumpToLatest({\n streaming,\n newMessageCount,\n onClick,\n streamingLabel = 'Odin is replying',\n}: Props) {\n return (\n <button\n type=\"button\"\n className={`jump-to-latest${streaming ? ' is-streaming' : ''}`}\n onClick={onClick}\n aria-label=\"Jump to latest message\"\n title=\"Jump to latest (⌘/Ctrl+End)\"\n >\n {streaming ? (\n <>\n <span className=\"jump-dots\" aria-hidden>\n <span />\n <span />\n <span />\n </span>\n <span>{streamingLabel}</span>\n {newMessageCount > 0 && (\n <span className=\"jump-badge jump-badge-live\">live</span>\n )}\n </>\n ) : (\n <>\n <ArrowDown size={14} aria-hidden />\n <span>Jump to latest</span>\n {newMessageCount > 0 && (\n <span className=\"jump-badge\">{newMessageCount} new</span>\n )}\n </>\n )}\n </button>\n );\n}","// src/views/Chat.tsx — desktop chat view (v4.2.5 design).\n//\n// v4.2.5 — chat overhaul:\n// * 3-column grid preserved (rail / thread / info).\n// * Composer goes through `chat.onSend`, which transparently routes\n// to the right backend endpoint based on `activeSource`:\n// - opencode session active → POST /api/opencode-sessions/:id/send\n// - otherwise → POST /api/chat\n// * \"New session\" button calls `chat.onCreateSession` which tries\n// POST /api/opencode-sessions/new first (so the new session is a\n// fully-fledged opencode session, scoped to the active worktree),\n// falling back to the local jsonl store when the opencode plugin\n// is offline.\n// * Top-of-thread badge shows the active source (\"opencode\" or\n// \"bizar chat\") so the user always knows where messages are going.\n// * Info panel gets session metadata + rename/delete actions.\n//\n// The page-level grid and CSS classes are unchanged so the rail/info\n// widths in the .chat-page grid continue to apply.\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { Trash2, Pencil } from 'lucide-react';\nimport { ChatTopBar } from '../components/chat/ChatTopBar';\nimport { ChatRail } from '../components/chat/ChatRail';\nimport { ChatThread } from '../components/chat/ChatThread';\nimport { ChatComposer } from '../components/chat/ChatComposer';\nimport { ChatInfoPanel } from '../components/chat/ChatInfoPanel';\nimport { JumpToLatest } from '../components/chat/JumpToLatest';\nimport { useChat } from '../components/chat/useChat';\nimport { useSlashCommands } from '../components/chat/useSlashCommands';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { Button } from '../components/Button';\nimport type { Snapshot, Settings } from '../lib/types';\n\ninterface Props {\n snapshot: Snapshot;\n settings: Settings;\n setActiveTab?: (id: string) => void;\n refreshSnapshot?: () => Promise<void>;\n initialTaskId?: string | null;\n onClearTaskId?: () => void;\n}\n\nexport function Chat({\n snapshot,\n settings,\n setActiveTab,\n initialTaskId,\n onClearTaskId,\n}: Props) {\n const toast = useToast();\n const modal = useModal();\n\n const chat = useChat(snapshot, settings, initialTaskId ?? '');\n // Wire toast + modal surfaces to useChat so async ops can surface\n // feedback without each view passing handlers down.\n useEffect(() => {\n chat.setToast({\n error: (msg: string) => toast.error(msg),\n success: (msg: string) => toast.success(msg),\n info: (msg: string) => toast.info(msg),\n warning: (msg: string) => toast.warning(msg),\n });\n }, [chat, toast]);\n\n // ── Composer state (local) ───────────────────────────────────────────────\n const [text, setText] = useState('');\n const [agent, setAgent] = useState(settings.defaultAgent || 'odin');\n const [model, setModel] = useState(settings.defaultModel || '');\n const [attachments, setAttachments] = useState<string[]>([]);\n\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // ── Slash commands ───────────────────────────────────────────────────────\n const { allCommands, suggestions, setQuery } = useSlashCommands(snapshot);\n\n useEffect(() => {\n setQuery(text);\n }, [text, setQuery]);\n\n // ── File attach ──────────────────────────────────────────────────────────\n const onAttach = () => fileInputRef.current?.click();\n const onFiles = (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (!files) return;\n const next: string[] = [];\n for (let i = 0; i < files.length; i++) next.push(files[i].name);\n setAttachments((cur) => {\n const newNames = next.filter((n) => !cur.includes(n));\n return [...cur, ...newNames];\n });\n if (fileInputRef.current) fileInputRef.current.value = '';\n };\n\n // ── Send ─────────────────────────────────────────────────────────────────\n const handleSend = async () => {\n const msg = text.trim();\n if (!msg) return;\n setText('');\n setQuery('');\n const result = await chat.onSend(msg, agent, model, attachments);\n if (result.ok) chat.jumpToLatest();\n };\n\n // ── Create session ───────────────────────────────────────────────────────\n const handleCreateSession = async () => {\n if (chat.busy.create) return;\n await chat.onCreateSession();\n };\n\n // ── Delete message (via modal) ───────────────────────────────────────────\n const handleDelete = (idx: number) => {\n modal.open({\n title: 'Delete message?',\n children: <p style={{ margin: 0 }}>This action cannot be undone.</p>,\n footer: (\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => modal.close()}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n size=\"sm\"\n onClick={() => {\n modal.close();\n chat.deleteMessage(idx);\n }}\n >\n Delete\n </Button>\n </div>\n ),\n });\n };\n\n // ── Rename session (info panel action) ───────────────────────────────────\n const handleRename = (id: string, currentTitle: string) => {\n let next = '';\n modal.open({\n title: 'Rename session',\n children: (\n <input\n autoFocus\n defaultValue={currentTitle}\n onChange={(e) => {\n next = e.target.value;\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n modal.close();\n chat.renameSession(id, next).then((ok) => {\n if (ok) {\n toast.success('Renamed.');\n }\n });\n }\n }}\n style={{\n width: '100%',\n padding: '8px 10px',\n background: 'var(--bg)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n color: 'var(--text)',\n font: '13px/1.4 var(--font-sans)',\n marginTop: 6,\n }}\n />\n ),\n footer: (\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => modal.close()}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => {\n modal.close();\n chat.renameSession(id, next);\n }}\n >\n Save\n </Button>\n </div>\n ),\n });\n };\n\n // ── Delete session (info panel action) ───────────────────────────────────\n const handleDeleteSession = (id: string, title: string) => {\n modal.open({\n title: 'Delete session?',\n children: (\n <p style={{ margin: 0 }}>\n Delete <strong>{title}</strong>? Messages on the opencode serve\n will be removed. This cannot be undone.\n </p>\n ),\n footer: (\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => modal.close()}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n size=\"sm\"\n onClick={async () => {\n modal.close();\n await chat.deleteSession(id);\n }}\n >\n Delete\n </Button>\n </div>\n ),\n });\n };\n\n // ── Export transcript ────────────────────────────────────────────────────\n const handleExport = () => {\n const sessionId =\n chat.activeSource === 'opencode'\n ? chat.activeOpencodeSessionId\n : chat.sessionId;\n if (!sessionId) return;\n const msgs =\n chat.activeSource === 'opencode'\n ? chat.opencodeMessages\n : chat.bizarMessages;\n const text = msgs\n .map((m) => {\n const ts = m.ts ?? '';\n const who = (m.role || 'unknown').toUpperCase();\n const c = m.content || m.message || '';\n return `[${ts}] ${who}: ${c}`;\n })\n .join('\\n\\n');\n const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${sessionId}.txt`;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n };\n\n // ── Derived: sessions with display state overlaid ────────────────────────\n const displaySessions = useMemo(\n () => chat.sessions.map((s) => chat.getSessionDisplay(s)),\n [chat.sessions, chat.getSessionDisplay],\n );\n const displayOpencodeSessions = useMemo(\n () => chat.opencodeSessions.map((s) => chat.getSessionDisplay(s)),\n [chat.opencodeSessions, chat.getSessionDisplay],\n );\n\n // ── Current session for the thread head subtitle ────────────────────────\n const activeSessionDisplay = useMemo(() => {\n const id =\n chat.activeSource === 'opencode'\n ? chat.activeOpencodeSessionId ?? ''\n : chat.sessionId;\n if (!id) return null;\n return (\n displaySessions.find((s) => s.id === id) ??\n displayOpencodeSessions.find((s) => s.id === id) ??\n null\n );\n }, [\n chat.activeSource,\n chat.activeOpencodeSessionId,\n chat.sessionId,\n displaySessions,\n displayOpencodeSessions,\n ]);\n\n const threadSubtitle = (() => {\n const base = `${agent || 'Odin'} · ${snapshot.activeProject?.name ?? 'no project'}`;\n const state = activeSessionDisplay?.state ?? 'idle';\n if (state === 'streaming') return `Replying · ${base}`;\n if (state === 'awaiting') return `Your turn · ${base}`;\n return `${base} · idle`;\n })();\n\n // The badge in the thread head: \"opencode\" or \"bizar chat\".\n const sourceLabel =\n chat.activeSource === 'opencode' ? 'opencode' : 'bizar chat';\n\n return (\n <div className=\"chat-shell\">\n <ChatTopBar\n activeProject={snapshot.activeProject}\n sessionCount={chat.sessions.length}\n sessionsOpen={true}\n infoOpen={true}\n onToggleSessions={() => {}}\n onToggleInfo={() => {}}\n onOpenOverview={() => setActiveTab?.('overview')}\n />\n <div className=\"chat-page\">\n {/* ── rail ──────────────────────────────────────────────────────── */}\n <ChatRail\n sessions={displaySessions}\n opencodeSessions={displayOpencodeSessions}\n activeSessionId={chat.sessionId}\n activeOpencodeSessionId={chat.activeOpencodeSessionId}\n activeProject={snapshot.activeProject}\n creating={chat.busy.create}\n onCreateSession={handleCreateSession}\n onSelectSession={chat.selectBizarSession}\n onSelectOpencodeSession={(s) => chat.loadOpencodeSession(s.id)}\n onRenameSession={handleRename}\n onDeleteSession={(id) => {\n const s = chat.sessions.find((s) => s.id === id) ?? chat.opencodeSessions.find((s) => s.id === id);\n handleDeleteSession(id, s?.title ?? '');\n }}\n />\n\n {/* ── thread ───────────────────────────────────────────────────── */}\n <section className=\"chat-thread-section\">\n <div className=\"chat-thread-head\">\n <div>\n <div className=\"chat-thread-title-row\">\n <div className=\"chat-thread-title\">\n {activeSessionDisplay?.title ?? chat.sessionId ?? 'New chat'}\n </div>\n <span\n className={`chat-source-badge chat-source-${\n chat.activeSource ?? 'none'\n }`}\n title={\n chat.activeSource === 'opencode'\n ? 'Messages go to the opencode serve child'\n : 'Messages go to the local chat store'\n }\n >\n {sourceLabel}\n </span>\n </div>\n <div\n className={`chat-thread-sub chat-muted state-${\n activeSessionDisplay?.state ?? 'idle'\n }`}\n >\n <span className=\"chat-thread-dot\" />\n {threadSubtitle}\n </div>\n {chat.opencodeError && (\n <div className=\"chat-thread-error\" role=\"alert\">\n {chat.opencodeError}\n </div>\n )}\n </div>\n <div className=\"chat-thread-actions\">\n {activeSessionDisplay && (\n <button\n className=\"btn btn-ghost\"\n title=\"Rename session\"\n type=\"button\"\n disabled={chat.busy.rename}\n onClick={() =>\n handleRename(\n activeSessionDisplay.id,\n activeSessionDisplay.title ?? '',\n )\n }\n >\n <Pencil size={12} aria-hidden />{' '}\n <span className=\"mono\">rename</span>\n </button>\n )}\n {activeSessionDisplay && (\n <button\n className=\"btn btn-ghost btn-danger\"\n title=\"Delete session\"\n type=\"button\"\n disabled={chat.busy.delete}\n onClick={() =>\n handleDeleteSession(\n activeSessionDisplay.id,\n activeSessionDisplay.title ?? activeSessionDisplay.id,\n )\n }\n >\n <Trash2 size={12} aria-hidden />{' '}\n <span className=\"mono\">delete</span>\n </button>\n )}\n <button\n className=\"btn btn-ghost\"\n title=\"Export transcript\"\n type=\"button\"\n onClick={handleExport}\n >\n <span className=\"mono\">export</span>\n </button>\n </div>\n </div>\n\n <div\n className=\"chat-thread-scroll\"\n ref={chat.listRef}\n onScroll={chat.handleScroll}\n >\n <ChatThread\n messages={\n chat.activeSource === 'opencode'\n ? chat.opencodeMessages\n : chat.bizarMessages\n }\n loading={chat.loading}\n activeProject={snapshot.activeProject}\n sessionId={\n chat.activeSource === 'opencode'\n ? chat.activeOpencodeSessionId ?? chat.sessionId\n : chat.sessionId\n }\n pinned={chat.pinned}\n activeSource={chat.activeSource}\n onPickSuggestion={(t) => setText(t)}\n onCopy={(m) =>\n chat.copyMessage(m as Parameters<typeof chat.copyMessage>[0])\n }\n onDelete={handleDelete}\n onTogglePin={chat.togglePin}\n onRegenerate={chat.onRegenerate}\n />\n </div>\n\n {!chat.stickToBottom && (\n <JumpToLatest\n streaming={activeSessionDisplay?.state === 'streaming'}\n newMessageCount={chat.newMessageCount}\n onClick={chat.jumpToLatest}\n />\n )}\n\n <ChatComposer\n agent={agent}\n setAgent={setAgent}\n model={model}\n setModel={setModel}\n text={text}\n setText={setText}\n sending={chat.sending}\n activeSource={chat.activeSource}\n onSend={handleSend}\n attachments={attachments}\n setAttachments={setAttachments}\n suggestions={suggestions}\n onPickSuggestion={(cmd) => setText(`${cmd.split(' ')[0]} `)}\n agents={snapshot.agents || []}\n onAttach={onAttach}\n />\n <input\n ref={fileInputRef}\n type=\"file\"\n multiple\n style={{ display: 'none' }}\n onChange={onFiles}\n />\n </section>\n\n {/* ── info panel ──────────────────────────────────────────────── */}\n <ChatInfoPanel\n sessionId={\n chat.activeSource === 'opencode'\n ? chat.activeOpencodeSessionId ?? chat.sessionId\n : chat.sessionId\n }\n messages={\n chat.activeSource === 'opencode'\n ? chat.opencodeMessages\n : chat.bizarMessages\n }\n pinned={chat.pinned}\n agent={agent}\n model={model}\n agents={snapshot.agents || []}\n mcps={snapshot.mcps || []}\n allCommands={allCommands}\n activeSource={chat.activeSource}\n onRename={() => {\n if (activeSessionDisplay) {\n handleRename(\n activeSessionDisplay.id,\n activeSessionDisplay.title ?? '',\n );\n }\n }}\n onDelete={() => {\n if (activeSessionDisplay) {\n handleDeleteSession(\n activeSessionDisplay.id,\n activeSessionDisplay.title ?? activeSessionDisplay.id,\n );\n }\n }}\n onExport={handleExport}\n busy={chat.busy}\n />\n </div>\n </div>\n );\n}\n","// src/components/StatusBadge.tsx — small colored pill.\n\nimport type { ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type StatusBadgeProps = {\n kind?: 'success' | 'warning' | 'error' | 'info' | 'accent' | 'neutral';\n children: ReactNode;\n className?: string;\n dot?: boolean;\n};\n\nexport function StatusBadge({\n kind = 'neutral',\n children,\n className,\n dot = false,\n}: StatusBadgeProps) {\n return (\n <span className={cn('badge', `badge-${kind}`, className)}>\n {dot && <span className=\"badge-dot\" />}\n {children}\n </span>\n );\n}\n","// src/views/Agents.tsx — v3.1.0 agents with tags, categories, real-time status.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n Bot,\n Plus,\n RefreshCw,\n Pencil,\n Trash2,\n Play,\n Save,\n X,\n RotateCw,\n Activity,\n Tag as TagIcon,\n Folder,\n CheckCircle2,\n Clock,\n AlertTriangle,\n Circle,\n ChevronDown,\n ChevronRight,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { useModal } from '../components/Modal';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn, formatRelative, truncate } from '../lib/utils';\nimport type { Agent, Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst TOOL_OPTIONS = ['bash', 'read', 'edit', 'write', 'webfetch', 'websearch', 'task', 'glob', 'grep'];\nconst MODELS = [\n 'anthropic/claude-3-5-sonnet',\n 'anthropic/claude-3-5-haiku',\n 'openai/gpt-4o',\n 'openai/gpt-4o-mini',\n 'openrouter/minimax/minimax-m3',\n 'openrouter/minimax/minimax-m2.7',\n];\n\nconst CATEGORIES = [\n { id: 'reasoning', label: 'Reasoning', color: 'var(--accent)' },\n { id: 'code', label: 'Code', color: 'var(--info)' },\n { id: 'design', label: 'Design', color: 'var(--success)' },\n { id: 'planning', label: 'Planning', color: 'var(--warning)' },\n { id: 'gitops', label: 'GitOps', color: 'var(--error)' },\n { id: 'analysis', label: 'Analysis', color: 'var(--text-dim)' },\n];\n\nfunction categoryColor(cat: string | undefined): string {\n return CATEGORIES.find((c) => c.id === cat)?.color || 'var(--text-dim)';\n}\n\nfunction StatusDot({ status, isStuck }: { status?: string; isStuck?: boolean }) {\n const color =\n isStuck ? 'var(--error)'\n : status === 'working' ? 'var(--info)'\n : status === 'error' ? 'var(--error)'\n : 'var(--text-dim)';\n return <span className=\"agent-status-dot\" style={{ background: color }} />;\n}\n\nfunction StatusPill({ agent }: { agent: Agent }) {\n if (agent.isStuck) {\n return <StatusBadge kind=\"error\" dot>stuck</StatusBadge>;\n }\n const status = agent.status || 'idle';\n if (status === 'working') return <StatusBadge kind=\"info\" dot>working</StatusBadge>;\n if (status === 'error') return <StatusBadge kind=\"error\" dot>error</StatusBadge>;\n return <StatusBadge kind=\"neutral\" dot>idle</StatusBadge>;\n}\n\nexport function Agents({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [agents, setAgents] = useState<Agent[]>(snapshot.agents || []);\n const [loading, setLoading] = useState(!snapshot.agents);\n const [categoryFilter, setCategoryFilter] = useState<string>('');\n const [search, setSearch] = useState('');\n\n useEffect(() => {\n setAgents(snapshot.agents || []);\n setLoading(!snapshot.agents);\n }, [snapshot.agents]);\n\n const reload = async () => {\n try {\n const d = await api.get<{ agents: Agent[] }>('/agents');\n setAgents(d.agents || []);\n } catch (err) {\n toast.error(`Agents load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n const sorted = useMemo(() => {\n let out = [...agents];\n if (categoryFilter) {\n out = out.filter((a) => categoryFilter === '__none__' ? !(a.category || '') : (a.category || '') === categoryFilter);\n }\n if (search) {\n const q = search.toLowerCase();\n out = out.filter(\n (a) =>\n a.name.toLowerCase().includes(q) ||\n (a.description || '').toLowerCase().includes(q) ||\n (a.tags || []).some((t) => t.toLowerCase().includes(q)),\n );\n }\n return out.sort((a, b) => a.name.localeCompare(b.name));\n }, [agents, categoryFilter, search]);\n\n const allTags = useMemo(() => {\n const set = new Set<string>();\n for (const a of agents) for (const t of a.tags || []) set.add(t);\n return Array.from(set).sort();\n }, [agents]);\n\n const onCreate = () => {\n let nameEl: HTMLInputElement | null = null;\n let descEl: HTMLInputElement | null = null;\n let modelEl: HTMLSelectElement | null = null;\n let modeEl: HTMLSelectElement | null = null;\n let colorEl: HTMLInputElement | null = null;\n let promptEl: HTMLTextAreaElement | null = null;\n let toolsContainer: HTMLDivElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let categoryEl: HTMLSelectElement | null = null;\n\n modal.open({\n title: 'New agent',\n width: 640,\n children: (\n <div className=\"agent-form\">\n <label className=\"field-label\">Name (a-z, 0-9, dashes)</label>\n <input\n ref={(el) => (nameEl = el)}\n className=\"input\"\n type=\"text\"\n placeholder=\"my-agent\"\n autoFocus\n />\n <label className=\"field-label\">Description</label>\n <input\n ref={(el) => { descEl = el; }}\n className=\"input\"\n type=\"text\"\n placeholder=\"What does this agent do?\"\n />\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Model</label>\n <select ref={(el) => (modelEl = el)} className=\"select\" defaultValue=\"\">\n <option value=\"\">(provider default)</option>\n {MODELS.map((m) => (\n <option key={m} value={m}>{m}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Mode</label>\n <select ref={(el) => (modeEl = el)} className=\"select\" defaultValue=\"subagent\">\n <option value=\"primary\">primary</option>\n <option value=\"subagent\">subagent</option>\n <option value=\"all\">all</option>\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: '0 0 80px' }}>\n <label className=\"field-label\">Color</label>\n <input ref={(el) => (colorEl = el)} className=\"input\" type=\"color\" defaultValue=\"#8b5cf6\" />\n </div>\n </div>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Category</label>\n <select ref={(el) => (categoryEl = el)} className=\"select\" defaultValue=\"\">\n <option value=\"\">(none)</option>\n {CATEGORIES.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: 2 }}>\n <label className=\"field-label\">Tags (comma-separated)</label>\n <input ref={(el) => (tagsEl = el)} className=\"input\" type=\"text\" placeholder=\"reasoning, code, planning\" />\n </div>\n </div>\n <label className=\"field-label\">Tools</label>\n <div ref={(el) => (toolsContainer = el)} className=\"agent-tools\">\n {TOOL_OPTIONS.map((t) => (\n <label key={t} className=\"checkbox-row\">\n <input type=\"checkbox\" value={t} />\n <span>{t}</span>\n </label>\n ))}\n </div>\n <label className=\"field-label\">System prompt</label>\n <textarea\n ref={(el) => (promptEl = el)}\n className=\"textarea\"\n rows={6}\n placeholder=\"You are a...\"\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const name = (nameEl?.value || '').trim();\n if (!/^[a-z0-9][a-z0-9-]{0,63}$/i.test(name)) {\n toast.warning('Invalid name (a-z, 0-9, dashes).');\n return;\n }\n const tools: string[] = [];\n if (toolsContainer) {\n toolsContainer.querySelectorAll<HTMLInputElement>('input[type=\"checkbox\"]:checked').forEach((cb) => {\n tools.push(cb.value);\n });\n }\n const tags = (tagsEl?.value || '').split(',').map((t) => t.trim()).filter(Boolean);\n try {\n const created = await api.post<Agent>('/agents', {\n name,\n description: (descEl?.value || '').trim(),\n model: modelEl?.value || '',\n mode: modeEl?.value || 'subagent',\n color: colorEl?.value || '',\n tools,\n tags,\n category: categoryEl?.value || '',\n prompt: promptEl?.value || '',\n });\n setAgents((cur) => [...cur, created]);\n toast.success('Agent created.');\n modal.close();\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n }\n }}\n >\n <Save size={12} /> Create\n </Button>\n </div>\n ),\n });\n };\n\n const onEdit = async (a: Agent) => {\n let descEl: HTMLInputElement | null = null;\n let modelEl: HTMLSelectElement | null = null;\n let modeEl: HTMLSelectElement | null = null;\n let colorEl: HTMLInputElement | null = null;\n let promptEl: HTMLTextAreaElement | null = null;\n let toolsContainer: HTMLDivElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let categoryEl: HTMLSelectElement | null = null;\n try {\n const full = await api.get<Agent>(`/agents/${encodeURIComponent(a.name)}`);\n modal.open({\n title: `Edit ${a.name}`,\n width: 640,\n children: (\n <div className=\"agent-form\">\n <div className=\"muted\">\n File: <code>{full.path}</code>\n </div>\n <label className=\"field-label\">Description</label>\n <input\n ref={(el) => { descEl = el; }}\n className=\"input\"\n type=\"text\"\n defaultValue={full.description}\n />\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Model</label>\n <select ref={(el) => (modelEl = el)} className=\"select\" defaultValue={full.model}>\n <option value=\"\">(provider default)</option>\n {MODELS.map((m) => (\n <option key={m} value={m}>{m}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Mode</label>\n <select ref={(el) => (modeEl = el)} className=\"select\" defaultValue={full.mode || 'subagent'}>\n <option value=\"primary\">primary</option>\n <option value=\"subagent\">subagent</option>\n <option value=\"all\">all</option>\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: '0 0 80px' }}>\n <label className=\"field-label\">Color</label>\n <input ref={(el) => (colorEl = el)} className=\"input\" type=\"color\" defaultValue={full.color || '#8b5cf6'} />\n </div>\n </div>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Category</label>\n <select ref={(el) => (categoryEl = el)} className=\"select\" defaultValue={full.category || ''}>\n <option value=\"\">(none)</option>\n {CATEGORIES.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: 2 }}>\n <label className=\"field-label\">Tags (comma-separated)</label>\n <input\n ref={(el) => (tagsEl = el)}\n className=\"input\"\n type=\"text\"\n defaultValue={(full.tags || []).join(', ')}\n />\n </div>\n </div>\n <label className=\"field-label\">Tools</label>\n <div ref={(el) => (toolsContainer = el)} className=\"agent-tools\">\n {TOOL_OPTIONS.map((t) => (\n <label key={t} className=\"checkbox-row\">\n <input type=\"checkbox\" value={t} defaultChecked={full.tools?.includes(t)} />\n <span>{t}</span>\n </label>\n ))}\n </div>\n <label className=\"field-label\">System prompt</label>\n <textarea\n ref={(el) => (promptEl = el)}\n className=\"textarea\"\n rows={8}\n defaultValue={full.prompt || ''}\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const tools: string[] = [];\n if (toolsContainer) {\n toolsContainer.querySelectorAll<HTMLInputElement>('input[type=\"checkbox\"]:checked').forEach((cb) => {\n tools.push(cb.value);\n });\n }\n const tags = (tagsEl?.value || '').split(',').map((t) => t.trim()).filter(Boolean);\n try {\n const updated = await api.put<Agent>(\n `/agents/${encodeURIComponent(a.name)}`,\n {\n description: (descEl?.value || '').trim(),\n model: modelEl?.value || '',\n mode: modeEl?.value || 'subagent',\n color: colorEl?.value || '',\n tools,\n tags,\n category: categoryEl?.value || '',\n prompt: promptEl?.value || '',\n },\n );\n setAgents((cur) => cur.map((x) => (x.name === a.name ? updated : x)));\n toast.success('Agent saved.');\n modal.close();\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n <Save size={12} /> Save\n </Button>\n </div>\n ),\n });\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (a: Agent) => {\n if (!confirm(`Delete agent \"${a.name}\"? This removes ${a.path}.`)) return;\n try {\n await api.del(`/agents/${encodeURIComponent(a.name)}`);\n setAgents((cur) => cur.filter((x) => x.name !== a.name));\n toast.success('Agent deleted.');\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const onInvoke = async (a: Agent) => {\n let promptEl: HTMLTextAreaElement | null = null;\n modal.open({\n title: `Invoke ${a.name}`,\n children: (\n <div className=\"invoke-form\">\n <p className=\"muted invoke-form-meta mono\">{a.model || '—'} · {a.path}</p>\n <p className=\"invoke-form-desc\">{a.description}</p>\n <label className=\"field-label\" htmlFor=\"invoke-prompt\">Prompt</label>\n <textarea\n ref={(el) => (promptEl = el)}\n id=\"invoke-prompt\"\n className=\"textarea\"\n rows={5}\n placeholder=\"What should this agent do?\"\n autoFocus\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const prompt = (promptEl?.value || '').trim();\n if (!prompt) {\n toast.warning('Prompt is required.');\n return;\n }\n try {\n await api.post(`/agents/${encodeURIComponent(a.name)}/invoke`, { prompt });\n toast.success(`Invoked ${a.name}.`);\n modal.close();\n } catch (err) {\n toast.error(`Invoke failed: ${(err as Error).message}`);\n }\n }}\n >\n <Play size={14} /> Invoke\n </Button>\n </div>\n ),\n });\n };\n\n const onRestart = async (a: Agent) => {\n try {\n const updated = await api.post<Agent>(`/agents/${encodeURIComponent(a.name)}/restart`);\n setAgents((cur) => cur.map((x) => (x.name === a.name ? updated : x)));\n toast.success(`${a.name} restarted.`);\n } catch (err) {\n toast.error(`Restart failed: ${(err as Error).message}`);\n }\n };\n\n const onSetStatus = async (a: Agent, status: 'idle' | 'working' | 'error') => {\n try {\n const updated = await api.post<Agent>(`/agents/${encodeURIComponent(a.name)}/status`, { status });\n setAgents((cur) => cur.map((x) => (x.name === a.name ? updated : x)));\n } catch (err) {\n toast.error(`Status update failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <div className=\"view view-agents\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Bot size={18} /> Agents ({sorted.length})\n </h2>\n <p className=\"view-subtitle\">\n The Norse pantheon — click <kbd>Edit</kbd> to modify or <kbd>Invoke</kbd> to dispatch.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"search-input\">\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n />\n </div>\n <select\n className=\"select select-sm\"\n value={categoryFilter}\n onChange={(e) => setCategoryFilter(e.target.value)}\n >\n <option value=\"\">All categories</option>\n {CATEGORIES.map((c) => (\n <option key={c.id} value={c.id}>{c.label}</option>\n ))}\n <option value=\"__none__\">(no category)</option>\n </select>\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={onCreate}>\n <Plus size={14} /> New agent\n </Button>\n </div>\n </header>\n\n {allTags.length > 0 && (\n <div className=\"agent-tags-row\">\n <TagIcon size={12} />\n {allTags.map((t) => (\n <span key={t} className=\"tag\">{t}</span>\n ))}\n </div>\n )}\n\n {loading ? (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n ) : sorted.length === 0 ? (\n <EmptyState\n icon={<Bot size={32} />}\n title=\"No agents found\"\n message=\"Run bizar in the terminal to install Bizar.\"\n />\n ) : (\n <div className=\"agent-grid\">\n {sorted.map((a) => (\n <AgentCard\n key={a.name}\n agent={a}\n onInvoke={() => onInvoke(a)}\n onEdit={() => onEdit(a)}\n onDelete={() => onDelete(a)}\n onRestart={() => onRestart(a)}\n onSetStatus={(s) => onSetStatus(a, s)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction AgentCard({\n agent,\n onInvoke,\n onEdit,\n onDelete,\n onRestart,\n onSetStatus,\n}: {\n agent: Agent;\n onInvoke: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onRestart: () => void;\n onSetStatus: (s: 'idle' | 'working' | 'error') => void;\n}) {\n const [expanded, setExpanded] = useState(false);\n const catColor = categoryColor(agent.category);\n const isWorking = (agent.status === 'working' || !!agent.currentTaskId) && !agent.isStuck;\n return (\n <Card\n variant=\"elevated\"\n interactive\n className={cn(\n 'agent-card',\n isWorking && 'is-working',\n agent.isStuck && 'is-stuck',\n )}\n >\n <div className=\"agent-card-head\">\n <div className=\"agent-card-name\">\n <StatusDot status={agent.status} isStuck={agent.isStuck} />\n {agent.name}\n </div>\n <div className=\"agent-card-badges\">\n {agent.category && (\n <span\n className=\"agent-card-category\"\n style={{ background: `color-mix(in srgb, ${catColor} 18%, transparent)`, color: catColor }}\n >\n {agent.category}\n </span>\n )}\n <StatusPill agent={agent} />\n </div>\n </div>\n <p className=\"agent-card-desc\">{truncate(agent.description, 200)}</p>\n <div className=\"agent-card-meta\">\n <span className=\"mono\" title={agent.model || ''}>\n {agent.model || '—'}\n </span>\n <span className=\"tabular-nums muted\">{formatRelative(agent.mtime)}</span>\n </div>\n {agent.tags && agent.tags.length > 0 && (\n <div className=\"agent-card-tags\">\n {agent.tags.map((t) => (\n <span key={t} className=\"agent-card-tag\">{t}</span>\n ))}\n </div>\n )}\n {(isWorking || agent.lastTask) && (\n <div className=\"agent-card-activity\">\n {agent.currentTaskId && (\n <div className=\"agent-card-row\">\n <Activity size={12} />\n <span className=\"muted\">Working on</span>\n <code className=\"mono\">{agent.currentTaskId}</code>\n </div>\n )}\n {agent.lastTask && !agent.currentTaskId && (\n <div className=\"agent-card-row\">\n <CheckCircle2 size={12} />\n <span className=\"muted\">Last</span>\n <code className=\"mono\">{agent.lastTask.id}</code>\n <span className=\"muted tabular-nums\">{formatRelative(agent.lastTask.finishedAt)}</span>\n </div>\n )}\n {agent.tasksTotal != null && agent.tasksTotal > 0 && (\n <div className=\"agent-card-row\">\n <Circle size={12} />\n <span className=\"muted\">Success rate</span>\n <span className=\"tabular-nums\">{Math.round((agent.successRate || 0) * 100)}%</span>\n <span className=\"muted tabular-nums\">({agent.tasksSucceeded}/{agent.tasksTotal})</span>\n </div>\n )}\n </div>\n )}\n {agent.lastError && (\n <div className=\"agent-card-error\">\n <AlertTriangle size={12} />\n <span className=\"muted\">Last error: {agent.lastError.message}</span>\n </div>\n )}\n <div className=\"agent-card-actions\">\n <Button variant=\"primary\" size=\"sm\" onClick={onInvoke}>\n <Play size={12} /> Invoke\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onEdit}>\n <Pencil size={12} /> Edit\n </Button>\n {(agent.isStuck || agent.status === 'working' || agent.status === 'error') && (\n <Button variant=\"ghost\" size=\"sm\" onClick={onRestart} title=\"Reset agent status\">\n <RotateCw size={12} /> Restart\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={onDelete}>\n <Trash2 size={12} />\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label={expanded ? 'Collapse' : 'Expand'}\n onClick={() => setExpanded((v) => !v)}\n style={{ marginLeft: 'auto' }}\n >\n {expanded ? <ChevronDown size={12} /> : <ChevronRight size={12} />}\n </button>\n </div>\n {expanded && (\n <div className=\"agent-card-expanded\">\n <div className=\"agent-card-status-actions\">\n <span className=\"muted text-sm\">Set status:</span>\n <Button\n variant={agent.status === 'idle' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => onSetStatus('idle')}\n >\n Idle\n </Button>\n <Button\n variant={agent.status === 'working' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => onSetStatus('working')}\n >\n Working\n </Button>\n <Button\n variant={agent.status === 'error' ? 'primary' : 'ghost'}\n size=\"sm\"\n onClick={() => onSetStatus('error')}\n >\n Error\n </Button>\n </div>\n <div className=\"agent-card-meta\">\n <Folder size={11} />\n <code className=\"mono agent-card-path\">{agent.path}</code>\n </div>\n </div>\n )}\n </Card>\n );\n}\n","// Glyphs block vocabulary — renders MDX blocks from plan.mdx\n\nimport { useMemo, useState } from 'react';\nimport ReactMarkdown from 'react-markdown';\nimport remarkGfm from 'remark-gfm';\nimport {\n AlertTriangle,\n Check,\n CheckCircle2,\n ChevronDown,\n Diamond,\n FileCode2,\n Info,\n Minus,\n StickyNote,\n XCircle,\n} from 'lucide-react';\nimport { cn } from '../../lib/utils';\n\nexport interface RichTextProps {\n id: string;\n children: string;\n}\n\nexport function RichText({ id, children }: RichTextProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className={cn('glyph-richtext')}\n style={proseStyle}\n >\n <ReactMarkdown remarkPlugins={[remarkGfm]}>{children}</ReactMarkdown>\n </div>\n );\n}\n\nexport interface CalloutProps {\n id: string;\n tone?: 'info' | 'warn' | 'success' | 'danger';\n children: string;\n}\n\nconst CALLOUT_TONE: Record<NonNullable<CalloutProps['tone']>, {\n bg: string; border: string; fg: string; icon: typeof Info; label: string;\n}> = {\n info: { bg: 'var(--info-soft, rgba(96, 165, 250, 0.12))', border: 'var(--info)', fg: 'var(--info)', icon: Info, label: 'Note' },\n warn: { bg: 'var(--warning-soft, rgba(251, 191, 36, 0.15))', border: 'var(--warning)', fg: 'var(--warning)', icon: AlertTriangle, label: 'Warning' },\n success: { bg: 'var(--success-soft, rgba(52, 211, 153, 0.15))', border: 'var(--success)', fg: 'var(--success)', icon: CheckCircle2, label: 'Success' },\n danger: { bg: 'var(--error-soft, rgba(248, 113, 113, 0.12))', border: 'var(--error)', fg: 'var(--error)', icon: XCircle, label: 'Danger' },\n};\n\nexport function Callout({ id, tone = 'info', children }: CalloutProps) {\n const t = CALLOUT_TONE[tone];\n const Icon = t.icon;\n return (\n <div\n id={id}\n data-block-id={id}\n className={cn('glyph-callout', `glyph-callout-${tone}`)}\n style={{\n display: 'flex',\n gap: 12,\n padding: '12px 16px',\n margin: '12px 0',\n borderLeft: `3px solid ${t.border}`,\n background: t.bg,\n borderRadius: 8,\n color: 'var(--text)',\n }}\n role={tone === 'danger' || tone === 'warn' ? 'alert' : undefined}\n >\n <div style={{ flexShrink: 0, color: t.fg, paddingTop: 2 }}>\n <Icon size={18} />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ fontWeight: 600, fontSize: 13, color: t.fg, marginBottom: 4 }}>\n {t.label}\n </div>\n <div className=\"glyph-richtext\" style={{ ...proseStyle, fontSize: 14 }}>\n <ReactMarkdown remarkPlugins={[remarkGfm]}>{children}</ReactMarkdown>\n </div>\n </div>\n </div>\n );\n}\n\nexport interface ChecklistItem {\n id: string;\n label: string;\n checked: boolean;\n}\nexport interface ChecklistProps {\n id: string;\n items: ChecklistItem[];\n}\n\nexport function Checklist({ id, items }: ChecklistProps) {\n return (\n <ul\n id={id}\n data-block-id={id}\n className=\"glyph-checklist\"\n style={{\n listStyle: 'none',\n padding: 0,\n margin: '12px 0',\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n }}\n >\n {items.map((item) => (\n <li\n key={item.id}\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n gap: 10,\n padding: '6px 10px',\n borderRadius: 6,\n background: 'var(--bg-elev)',\n border: '1px solid var(--border)',\n fontSize: 14,\n }}\n >\n <span\n aria-hidden\n style={{\n flexShrink: 0,\n marginTop: 1,\n width: 16,\n height: 16,\n borderRadius: 4,\n border: `1.5px solid ${item.checked ? 'var(--success)' : 'var(--border-strong)'}`,\n background: item.checked ? 'var(--success)' : 'transparent',\n color: 'var(--bg)',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n {item.checked ? <Check size={12} strokeWidth={3} /> : null}\n </span>\n <span style={{\n color: item.checked ? 'var(--text-dim)' : 'var(--text)',\n textDecoration: item.checked ? 'line-through' : 'none',\n wordBreak: 'break-word',\n }}>\n {item.label}\n </span>\n </li>\n ))}\n </ul>\n );\n}\n\nexport interface TableProps {\n id: string;\n columns: string[];\n rows: string[][];\n}\n\nexport function Table({ id, columns, rows }: TableProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-table-wrap\"\n style={{\n margin: '12px 0',\n border: '1px solid var(--border)',\n borderRadius: 8,\n overflow: 'auto',\n background: 'var(--bg-elev)',\n }}\n >\n <table\n style={{\n width: '100%',\n borderCollapse: 'collapse',\n fontSize: 13,\n }}\n >\n <thead>\n <tr>\n {columns.map((c, i) => (\n <th\n key={i}\n style={{\n textAlign: 'left',\n padding: '8px 12px',\n borderBottom: '1px solid var(--border-strong)',\n background: 'var(--bg)',\n color: 'var(--text-dim)',\n fontWeight: 600,\n fontSize: 12,\n textTransform: 'uppercase',\n letterSpacing: 0.3,\n whiteSpace: 'nowrap',\n }}\n >\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, ri) => (\n <tr key={ri} style={{ borderTop: ri === 0 ? 'none' : '1px solid var(--border)' }}>\n {row.map((cell, ci) => (\n <td\n key={ci}\n style={{\n padding: '8px 12px',\n color: 'var(--text)',\n verticalAlign: 'top',\n wordBreak: 'break-word',\n }}\n >\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nexport interface CodeTab {\n id: string;\n label: string;\n language: string;\n code: string;\n caption?: string;\n}\nexport interface CodeTabsProps {\n id: string;\n tabs: CodeTab[];\n}\n\nexport function CodeTabs({ id, tabs }: CodeTabsProps) {\n const [activeId, setActiveId] = useState<string>(tabs[0]?.id ?? '');\n const active = useMemo(\n () => tabs.find((t) => t.id === activeId) ?? tabs[0],\n [tabs, activeId],\n );\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-codetabs\"\n style={{\n margin: '12px 0',\n border: '1px solid var(--border)',\n borderRadius: 8,\n overflow: 'hidden',\n background: 'var(--bg-elev)',\n }}\n >\n <div\n role=\"tablist\"\n style={{\n display: 'flex',\n gap: 2,\n padding: 4,\n background: 'var(--bg)',\n borderBottom: '1px solid var(--border)',\n overflowX: 'auto',\n }}\n >\n {tabs.map((t) => {\n const selected = t.id === active?.id;\n return (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n onClick={() => setActiveId(t.id)}\n style={{\n padding: '6px 12px',\n fontSize: 12,\n fontFamily: 'var(--font-mono)',\n borderRadius: 6,\n border: 'none',\n cursor: 'pointer',\n background: selected ? 'var(--bg-elev)' : 'transparent',\n color: selected ? 'var(--text-strong)' : 'var(--text-dim)',\n boxShadow: selected ? '0 0 0 1px var(--border)' : 'none',\n whiteSpace: 'nowrap',\n }}\n >\n <span>{t.label}</span>\n {t.language && (\n <span style={{ marginLeft: 6, color: 'var(--text-dim)', fontSize: 11 }}>\n {t.language}\n </span>\n )}\n </button>\n );\n })}\n </div>\n {active && (\n <>\n <pre\n style={{\n margin: 0,\n padding: 14,\n overflowX: 'auto',\n fontFamily: 'var(--font-mono)',\n fontSize: 12.5,\n lineHeight: 1.55,\n color: 'var(--text)',\n background: 'var(--bg-elev)',\n }}\n >\n <code>{active.code}</code>\n </pre>\n {active.caption && (\n <div\n style={{\n padding: '8px 14px',\n borderTop: '1px solid var(--border)',\n fontSize: 12,\n color: 'var(--text-dim)',\n background: 'var(--bg)',\n }}\n >\n {active.caption}\n </div>\n )}\n </>\n )}\n </div>\n );\n}\n\nexport interface DecisionOption {\n id: string;\n label: string;\n detail: string;\n recommended?: boolean;\n}\nexport interface DecisionProps {\n id: string;\n title?: string;\n question?: string;\n options: DecisionOption[];\n}\n\nexport function Decision({ id, title, question, options }: DecisionProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-decision\"\n style={{\n margin: '16px 0',\n padding: 16,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n }}\n >\n {title && (\n <h3 style={{ margin: 0, marginBottom: 4, fontSize: 15, fontWeight: 600, color: 'var(--text-strong)' }}>\n {title}\n </h3>\n )}\n {question && (\n <p style={{ margin: 0, marginBottom: 12, fontSize: 13, color: 'var(--text-dim)' }}>\n {question}\n </p>\n )}\n <div style={{ display: 'grid', gap: 10, gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))' }}>\n {options.map((opt) => {\n const isRec = !!opt.recommended;\n return (\n <div\n key={opt.id}\n style={{\n position: 'relative',\n padding: 12,\n borderRadius: 8,\n border: isRec ? '2px solid var(--success)' : '1px solid var(--border)',\n background: isRec ? 'var(--success-soft)' : 'var(--bg)',\n }}\n >\n {isRec && (\n <span\n style={{\n position: 'absolute',\n top: -10,\n right: 10,\n padding: '2px 8px',\n fontSize: 11,\n fontWeight: 600,\n color: 'var(--bg)',\n background: 'var(--success)',\n borderRadius: 999,\n }}\n >\n Recommended\n </span>\n )}\n <div style={{ fontWeight: 600, fontSize: 14, color: 'var(--text-strong)', marginBottom: 4 }}>\n {opt.label}\n </div>\n <div style={{ fontSize: 13, color: 'var(--text)' }}>\n {opt.detail}\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport interface OpenQuestion {\n id: string;\n label: string;\n kind: 'choice' | 'text' | 'multi';\n options?: string[];\n}\nexport interface OpenQuestionsProps {\n id: string;\n questions: OpenQuestion[];\n}\n\nexport function OpenQuestions({ id, questions }: OpenQuestionsProps) {\n const [answers, setAnswers] = useState<Record<string, string | string[]>>({});\n\n function setAnswer(qid: string, value: string | string[]) {\n setAnswers((prev) => ({ ...prev, [qid]: value }));\n }\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-openquestions\"\n style={{\n margin: '16px 0',\n padding: 16,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n display: 'flex',\n flexDirection: 'column',\n gap: 14,\n }}\n >\n <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-strong)' }}>\n Open questions\n </div>\n {questions.map((q) => (\n <div key={q.id} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <label\n htmlFor={`oq-${q.id}`}\n style={{ fontSize: 13, color: 'var(--text)', fontWeight: 500 }}\n >\n {q.label}\n </label>\n {q.kind === 'choice' && (\n <select\n id={`oq-${q.id}`}\n value={(answers[q.id] as string) ?? ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n style={inputStyle}\n >\n <option value=\"\">— select —</option>\n {(q.options ?? []).map((opt) => (\n <option key={opt} value={opt}>{opt}</option>\n ))}\n </select>\n )}\n {q.kind === 'text' && (\n <input\n id={`oq-${q.id}`}\n type=\"text\"\n value={(answers[q.id] as string) ?? ''}\n onChange={(e) => setAnswer(q.id, e.target.value)}\n style={inputStyle}\n />\n )}\n {q.kind === 'multi' && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>\n {(q.options ?? []).map((opt) => {\n const current = (answers[q.id] as string[]) ?? [];\n const checked = current.includes(opt);\n return (\n <label\n key={opt}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n fontSize: 13,\n color: 'var(--text)',\n cursor: 'pointer',\n }}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => {\n const next = checked\n ? current.filter((o) => o !== opt)\n : [...current, opt];\n setAnswer(q.id, next);\n }}\n />\n <span>{opt}</span>\n </label>\n );\n })}\n </div>\n )}\n </div>\n ))}\n </div>\n );\n}\n\nconst inputStyle: React.CSSProperties = {\n padding: '6px 10px',\n fontSize: 13,\n borderRadius: 6,\n border: '1px solid var(--border-strong)',\n background: 'var(--bg)',\n color: 'var(--text)',\n fontFamily: 'inherit',\n};\n\nexport interface FileTreeEntry {\n path: string;\n change: 'added' | 'modified' | 'removed' | 'renamed';\n note?: string;\n}\nexport interface FileTreeProps {\n id: string;\n title?: string;\n entries: FileTreeEntry[];\n}\n\nconst FILE_CHANGE: Record<FileTreeEntry['change'], { bg: string; fg: string; label: string }> = {\n added: { bg: 'var(--success-soft)', fg: 'var(--success)', label: 'A' },\n modified: { bg: 'var(--info-soft, rgba(96, 165, 250, 0.12))', fg: 'var(--info)', label: 'M' },\n removed: { bg: 'var(--error-soft)', fg: 'var(--error)', label: 'D' },\n renamed: { bg: 'rgba(139, 92, 246, 0.15)', fg: 'var(--accent)', label: 'R' },\n};\n\nexport function FileTree({ id, title, entries }: FileTreeProps) {\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-filetree\"\n style={{\n margin: '12px 0',\n padding: title ? 14 : 8,\n border: '1px solid var(--border)',\n borderRadius: 8,\n background: 'var(--bg-elev)',\n }}\n >\n {title && (\n <div\n style={{\n fontSize: 12,\n fontWeight: 600,\n color: 'var(--text-dim)',\n textTransform: 'uppercase',\n letterSpacing: 0.4,\n marginBottom: 8,\n }}\n >\n {title}\n </div>\n )}\n <ul style={{ listStyle: 'none', padding: 0, margin: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>\n {entries.map((e) => {\n const t = FILE_CHANGE[e.change];\n return (\n <li\n key={e.path}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n padding: '5px 8px',\n borderRadius: 5,\n fontSize: 13,\n }}\n >\n <span\n aria-label={e.change}\n title={e.change}\n style={{\n flexShrink: 0,\n width: 22,\n height: 18,\n borderRadius: 4,\n background: t.bg,\n color: t.fg,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: 10,\n fontWeight: 700,\n fontFamily: 'var(--font-mono)',\n }}\n >\n {t.label}\n </span>\n <span\n style={{\n fontFamily: 'var(--font-mono)',\n color: 'var(--text)',\n wordBreak: 'break-all',\n flex: 1,\n }}\n >\n {e.path}\n </span>\n {e.note && (\n <span style={{ fontSize: 12, color: 'var(--text-dim)' }}>\n {e.note}\n </span>\n )}\n </li>\n );\n })}\n </ul>\n </div>\n );\n}\n\nexport interface DiffProps {\n id: string;\n filename?: string;\n language?: string;\n mode?: 'split' | 'unified';\n before: string;\n after: string;\n}\n\nexport function Diff({ id, filename, language, mode = 'unified', before, after }: DiffProps) {\n const beforeLines = before.split('\\n');\n const afterLines = after.split('\\n');\n\n const header = (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 12px',\n background: 'var(--bg)',\n borderBottom: '1px solid var(--border)',\n fontSize: 12,\n color: 'var(--text-dim)',\n fontFamily: 'var(--font-mono)',\n }}\n >\n <FileCode2 size={14} />\n <span style={{ color: 'var(--text)' }}>{filename ?? 'diff'}</span>\n {language && <span>· {language}</span>}\n <span style={{ marginLeft: 'auto', textTransform: 'uppercase', letterSpacing: 0.3 }}>\n {mode}\n </span>\n </div>\n );\n\n const codeStyle: React.CSSProperties = {\n margin: 0,\n padding: 0,\n fontFamily: 'var(--font-mono)',\n fontSize: 12.5,\n lineHeight: 1.55,\n color: 'var(--text)',\n background: 'var(--bg-elev)',\n };\n\n const lineRow = (sign: string, content: string, kind: 'del' | 'add' | 'ctx') => {\n const colors: Record<typeof kind, string> = {\n del: 'var(--error-soft)',\n add: 'var(--success-soft)',\n ctx: 'transparent',\n };\n const signColor: Record<typeof kind, string> = {\n del: 'var(--error)',\n add: 'var(--success)',\n ctx: 'var(--text-dim)',\n };\n return (\n <div\n style={{\n display: 'flex',\n padding: '0 12px',\n background: colors[kind],\n }}\n >\n <span style={{ width: 18, color: signColor[kind], userSelect: 'none', flexShrink: 0 }}>{sign}</span>\n <span style={{ whiteSpace: 'pre', flex: 1, overflowX: 'auto' }}>{content || ' '}</span>\n </div>\n );\n };\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-diff\"\n style={{\n margin: '12px 0',\n border: '1px solid var(--border)',\n borderRadius: 8,\n overflow: 'hidden',\n background: 'var(--bg-elev)',\n }}\n >\n {header}\n {mode === 'unified' ? (\n <pre style={codeStyle}>\n {beforeLines.map((l, i) => (\n <div key={`b${i}`}>{lineRow('-', l, 'del')}</div>\n ))}\n {afterLines.map((l, i) => (\n <div key={`a${i}`}>{lineRow('+', l, 'add')}</div>\n ))}\n </pre>\n ) : (\n <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>\n <pre style={{ ...codeStyle, borderRight: '1px solid var(--border)' }}>\n {beforeLines.map((l, i) => (\n <div key={i}>{lineRow('-', l, 'del')}</div>\n ))}\n </pre>\n <pre style={codeStyle}>\n {afterLines.map((l, i) => (\n <div key={i}>{lineRow('+', l, 'add')}</div>\n ))}\n </pre>\n </div>\n )}\n </div>\n );\n}\n\nexport interface StatProps {\n id: string;\n label: string;\n value: string | number;\n trend?: 'up' | 'down' | 'flat';\n hint?: string;\n}\n\nconst TREND_STYLE: Record<NonNullable<StatProps['trend']>, { fg: string; Icon: typeof Minus; label: string }> = {\n up: { fg: 'var(--success)', Icon: ChevronDown, label: 'trending up' },\n down: { fg: 'var(--error)', Icon: ChevronDown, label: 'trending down' },\n flat: { fg: 'var(--text-dim)', Icon: Minus, label: 'flat' },\n};\n\nexport function Stat({ id, label, value, trend, hint }: StatProps) {\n const t = trend ? TREND_STYLE[trend] : null;\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-stat\"\n style={{\n padding: 14,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n minWidth: 140,\n }}\n >\n <div style={{ fontSize: 12, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: 0.4 }}>\n {label}\n </div>\n <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>\n <span style={{ fontSize: 24, fontWeight: 700, color: 'var(--text-strong)' }}>\n {value}\n </span>\n {t && (\n <span\n aria-label={t.label}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n color: t.fg,\n transform: t.Icon === ChevronDown && trend === 'up' ? 'rotate(180deg)' : undefined,\n }}\n >\n <t.Icon size={14} />\n </span>\n )}\n </div>\n {hint && (\n <div style={{ fontSize: 12, color: 'var(--text-dim)' }}>\n {hint}\n </div>\n )}\n </div>\n );\n}\n\nexport interface WorkflowStep {\n id: string;\n label: string;\n type: 'task' | 'decision' | 'note';\n}\nexport interface WorkflowConnection {\n from: string;\n to: string;\n label?: string;\n}\nexport interface WorkflowProps {\n id: string;\n steps: WorkflowStep[];\n connections?: WorkflowConnection[];\n}\n\nconst STEP_COLORS: Record<WorkflowStep['type'], { stroke: string; fill: string; fg: string }> = {\n task: { stroke: 'var(--info)', fill: 'var(--bg-elev)', fg: 'var(--text)' },\n decision: { stroke: 'var(--warning)', fill: 'var(--bg-elev)', fg: 'var(--text)' },\n note: { stroke: 'var(--border-strong)', fill: 'var(--bg)', fg: 'var(--text-dim)' },\n};\n\nconst BOX_W = 160;\nconst BOX_H = 56;\nconst GAP_X = 60;\nconst GAP_Y = 80;\n\nexport function Workflow({ id, steps, connections = [] }: WorkflowProps) {\n if (steps.length === 0) {\n return (\n <div id={id} data-block-id={id} className=\"glyph-workflow\">\n <Empty id={id} />\n </div>\n );\n }\n\n const byId = new Map(steps.map((s) => [s.id, s] as const));\n const layout = layoutSteps(steps);\n\n const cols = Math.max(...layout.map((p) => p.col)) + 1;\n const rows = Math.max(...layout.map((p) => p.row)) + 1;\n const width = cols * (BOX_W + GAP_X) + GAP_X;\n const height = rows * (BOX_H + GAP_Y) + GAP_Y;\n\n function nodeCenter(stepId: string): { x: number; y: number } | null {\n const step = byId.get(stepId);\n if (!step) return null;\n const pos = layout.find((p) => p.id === stepId);\n if (!pos) return null;\n return {\n x: GAP_X + pos.col * (BOX_W + GAP_X) + BOX_W / 2,\n y: GAP_Y + pos.row * (BOX_H + GAP_Y) + BOX_H / 2,\n };\n }\n\n return (\n <div\n id={id}\n data-block-id={id}\n className=\"glyph-workflow\"\n style={{\n margin: '12px 0',\n padding: 12,\n border: '1px solid var(--border)',\n borderRadius: 10,\n background: 'var(--bg-elev)',\n overflow: 'auto',\n }}\n >\n <svg\n role=\"img\"\n aria-label=\"Workflow diagram\"\n width={width}\n height={height}\n style={{ display: 'block', maxWidth: '100%' }}\n >\n <defs>\n <marker\n id={`arrow-${id}`}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"6\"\n markerHeight=\"6\"\n orient=\"auto-start-reverse\"\n >\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--text-dim)\" />\n </marker>\n </defs>\n\n {connections.map((c, i) => {\n const from = nodeCenter(c.from);\n const to = nodeCenter(c.to);\n if (!from || !to) return null;\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const fromX = dx >= 0 ? from.x + BOX_W / 2 : from.x - BOX_W / 2;\n const toX = dx >= 0 ? to.x - BOX_W / 2 : to.x + BOX_W / 2;\n const fromY = dy >= 0 ? from.y + BOX_H / 2 : from.y - BOX_H / 2;\n const toY = dy >= 0 ? to.y - BOX_H / 2 : to.y + BOX_H / 2;\n const midX = (fromX + toX) / 2;\n const midY = (fromY + toY) / 2;\n return (\n <g key={i}>\n <line\n x1={fromX}\n y1={fromY}\n x2={toX}\n y2={toY}\n stroke=\"var(--text-dim)\"\n strokeWidth={1.5}\n markerEnd={`url(#arrow-${id})`}\n />\n {c.label && (\n <text\n x={midX}\n y={midY - 4}\n fontSize={10}\n fill=\"var(--text-dim)\"\n textAnchor=\"middle\"\n fontFamily=\"var(--font-mono)\"\n >\n {c.label}\n </text>\n )}\n </g>\n );\n })}\n\n {steps.map((s) => {\n const pos = layout.find((p) => p.id === s.id);\n if (!pos) return null;\n const x = GAP_X + pos.col * (BOX_W + GAP_X);\n const y = GAP_Y + pos.row * (BOX_H + GAP_Y);\n const c = STEP_COLORS[s.type];\n if (s.type === 'decision') {\n const cx = x + BOX_W / 2;\n const cy = y + BOX_H / 2;\n const points = [\n [cx, y],\n [x + BOX_W, cy],\n [cx, y + BOX_H],\n [x, cy],\n ]\n .map((p) => p.join(','))\n .join(' ');\n return (\n <g key={s.id}>\n <polygon\n points={points}\n fill={c.fill}\n stroke={c.stroke}\n strokeWidth={2}\n />\n <foreignObject x={x + 8} y={cy - 14} width={BOX_W - 16} height={28}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n fontSize: 12,\n color: c.fg,\n textAlign: 'center',\n lineHeight: 1.2,\n fontStyle: 'italic',\n height: '100%',\n }}\n >\n <Diamond size={11} />\n {s.label}\n </div>\n </foreignObject>\n </g>\n );\n }\n const isNote = s.type === 'note';\n return (\n <g key={s.id}>\n <rect\n x={x}\n y={y}\n width={BOX_W}\n height={BOX_H}\n rx={8}\n fill={c.fill}\n stroke={c.stroke}\n strokeWidth={isNote ? 1 : 2}\n strokeDasharray={isNote ? '4 3' : undefined}\n />\n <foreignObject x={x + 6} y={y + 6} width={BOX_W - 12} height={BOX_H - 12}>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 6,\n fontSize: 12,\n color: c.fg,\n textAlign: 'center',\n lineHeight: 1.25,\n fontStyle: isNote ? 'italic' : 'normal',\n height: '100%',\n }}\n >\n {isNote && <StickyNote size={11} />}\n {s.label}\n </div>\n </foreignObject>\n </g>\n );\n })}\n </svg>\n </div>\n );\n}\n\nfunction Empty({ id }: { id: string }) {\n return (\n <div\n id={id}\n style={{\n padding: 20,\n textAlign: 'center',\n color: 'var(--text-dim)',\n fontSize: 13,\n }}\n >\n No workflow steps.\n </div>\n );\n}\n\ntype LayoutPos = { id: string; col: number; row: number };\n\nfunction layoutSteps(steps: WorkflowStep[]): LayoutPos[] {\n if (steps.length === 0) return [];\n return steps.map((s, i) => ({ id: s.id, col: i, row: 0 }));\n}\n\nconst proseStyle: React.CSSProperties = {\n fontSize: 14,\n lineHeight: 1.6,\n color: 'var(--text)',\n};\n\n// ─── Mockup ─────────────────────────────────────────────────────────────────\n\nexport interface MockupProps {\n id: string;\n title?: string;\n x?: number;\n y?: number;\n w?: number;\n h?: number;\n html: string;\n}\n\nexport function Mockup({ id, title, x, y, w, h, html }: MockupProps) {\n return (\n <figure\n id={id}\n data-block-id={id}\n className=\"glyph-mockup\"\n style={{ width: w, minHeight: h }}\n >\n {title && <figcaption className=\"glyph-mockup-title\">{title}</figcaption>}\n <div className=\"glyph-mockup-frame\">\n <div className=\"glyph-mockup-chrome\">\n <span />\n <span />\n <span />\n </div>\n <div\n className=\"glyph-mockup-body\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </div>\n </figure>\n );\n}\n","/**\n * GlyphRenderer.tsx — Renders a compiled glyph (from /api/artifacts/:slug/render)\n * with comment pin overlay + right-click to add comments.\n *\n * Uses the agent-native.com \"Visual Plans\" workflow (v3.22.0):\n * - Compiled glyph structure: { frontmatter, blocks: [{id, type, data, childrenMarkdown?}], errors }\n * - Each block renders via the components from ./components\n * - Comment pins from comments.json overlay on top, positioned absolutely\n * - Right-click anywhere → context menu with \"Add comment\" option\n * - Blocks are grouped into sections by id (overview, implementation, …)\n *\n * Layout (v3.22.0 — agent-native /visual-plan inspired, dark dashboard styling):\n * .glyph-canvas ← outer, dotted background\n * .glyph-toolbar-floating ← sticky top-right pill (Send to agent, share, …)\n * .glyph-canvas-content ← centered blocks area\n * .glyph-section ← section card with optional heading\n * .glyph-section-heading ← \"Overview\" / \"Implementation plan\" / …\n * .glyph-section-blocks ← block stack inside the section\n *\n * v3.22.0 — section grouping + floating toolbar rewrite (kept all prior pin/ctx-menu logic).\n */\n\nimport React, { useEffect, useMemo, useState, useRef } from 'react';\nimport {\n MapPin,\n MessageSquare,\n Send,\n Share2,\n Undo2,\n Redo2,\n MoreHorizontal,\n Maximize2,\n X,\n} from 'lucide-react';\nimport { api } from '../../lib/api';\nimport { useToast } from '../../components/Toast';\nimport {\n RichText,\n Callout,\n Checklist,\n Table,\n CodeTabs,\n Decision,\n OpenQuestions,\n FileTree,\n Diff,\n Stat,\n Workflow,\n Mockup,\n} from './components';\n\n// ---------------------------------------------------------------------------\n// BlockErrorBoundary — v4.4.8\n//\n// A single broken block (e.g. a FileTree whose `data.entries` ended up\n// not being an array because the parser silently produced a phantom\n// bareword entry) used to throw inside React, which propagated up and\n// blanked the whole canvas. The boundary catches throws per-block and\n// renders an inline error card instead. The boundary also exposes its\n// errors via a callback so we can surface them in the top-of-page\n// \"render errors\" banner.\n// ---------------------------------------------------------------------------\n\ninterface BlockErrorBoundaryProps {\n blockId: string;\n blockType: string;\n children: React.ReactNode;\n onError: (blockId: string, blockType: string, err: Error, info: React.ErrorInfo) => void;\n}\n\ninterface BlockErrorBoundaryState {\n err: Error | null;\n}\n\nclass BlockErrorBoundary extends React.Component<BlockErrorBoundaryProps, BlockErrorBoundaryState> {\n state: BlockErrorBoundaryState = { err: null };\n static getDerivedStateFromError(err: Error): BlockErrorBoundaryState {\n return { err };\n }\n componentDidCatch(err: Error, info: React.ErrorInfo): void {\n try {\n this.props.onError(this.props.blockId, this.props.blockType, err, info);\n } catch {\n /* ignore — the boundary itself must not throw */\n }\n }\n render(): React.ReactNode {\n if (this.state.err) {\n return (\n <div\n className=\"glyph-block-error\"\n role=\"alert\"\n style={{\n border: '1px solid var(--error, #f85149)',\n background: 'rgba(248, 81, 73, 0.06)',\n borderRadius: 8,\n padding: '12px 14px',\n margin: '12px 0',\n color: 'var(--text)',\n fontFamily: 'var(--font-mono, ui-monospace, monospace)',\n fontSize: 12,\n lineHeight: 1.55,\n }}\n >\n <strong style={{ color: 'var(--error, #f85149)', fontFamily: 'var(--font-sans, system-ui, sans-serif)', display: 'block', marginBottom: 4 }}>\n {this.props.blockType} block crashed\n </strong>\n <div style={{ color: 'var(--text-muted)', marginBottom: 6 }}>\n block id: <code>{this.props.blockId}</code>\n </div>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word', color: 'var(--text)' }}>\n {this.state.err.message}\n </pre>\n </div>\n );\n }\n return this.props.children;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Block validation — v4.4.8\n//\n// Before handing block data to the component switch, verify that the\n// shape matches the prop contract. Returns `{ ok: true }` when the\n// block can be rendered, or `{ ok: false, error }` when a field is\n// missing or wrong type. The renderer uses the error to skip the\n// component and surface an inline message instead of throwing.\n// ---------------------------------------------------------------------------\n\nfunction validateBlock(b: Block): { ok: true } | { ok: false; error: string } {\n const data = (b.data ?? {}) as Record<string, unknown>;\n switch (b.type) {\n case 'RichText':\n return { ok: true };\n case 'Callout':\n return { ok: true };\n case 'Checklist':\n if (!Array.isArray(data.items)) return { ok: false, error: 'Checklist requires data.items to be an array' };\n return { ok: true };\n case 'Table':\n if (!Array.isArray(data.columns)) return { ok: false, error: 'Table requires data.columns to be an array' };\n if (!Array.isArray(data.rows)) return { ok: false, error: 'Table requires data.rows to be an array' };\n if (data.rows.length > 0 && !Array.isArray(data.rows[0])) return { ok: false, error: 'Table.data.rows[0] must be an array (cell array)' };\n return { ok: true };\n case 'CodeTabs':\n if (!Array.isArray(data.tabs)) return { ok: false, error: 'CodeTabs requires data.tabs to be an array' };\n return { ok: true };\n case 'Decision':\n if (!Array.isArray(data.options)) return { ok: false, error: 'Decision requires data.options to be an array' };\n return { ok: true };\n case 'OpenQuestions':\n if (!Array.isArray(data.questions)) return { ok: false, error: 'OpenQuestions requires data.questions to be an array' };\n return { ok: true };\n case 'FileTree':\n if (!Array.isArray(data.entries)) return { ok: false, error: 'FileTree requires data.entries to be an array' };\n // v4.4.8 — also catch the phantom bareword entry the parser used\n // to emit (the v3-to-v4-consolidation glyph crash). An entry that\n // is not an object means the parser miscounted braces.\n for (const e of data.entries) {\n if (e === null || typeof e !== 'object' || Array.isArray(e)) {\n return { ok: false, error: `FileTree contains a malformed entry: ${JSON.stringify(e)}` };\n }\n }\n return { ok: true };\n case 'Diff':\n if (typeof data.before !== 'string') return { ok: false, error: 'Diff requires data.before to be a string' };\n if (typeof data.after !== 'string') return { ok: false, error: 'Diff requires data.after to be a string' };\n return { ok: true };\n case 'Stat':\n if (data.label === undefined || data.label === null) return { ok: false, error: 'Stat requires data.label' };\n if (data.value === undefined || data.value === null) return { ok: false, error: 'Stat requires data.value' };\n return { ok: true };\n case 'Workflow':\n if (!Array.isArray(data.steps)) return { ok: false, error: 'Workflow requires data.steps to be an array' };\n return { ok: true };\n case 'Mockup':\n if (typeof data.html !== 'string') return { ok: false, error: 'Mockup requires data.html to be a string' };\n return { ok: true };\n case 'Diagram':\n if (typeof data.dataHtml !== 'string') return { ok: false, error: 'Diagram requires data.dataHtml to be a string' };\n return { ok: true };\n default:\n return { ok: false, error: `Unknown block type: ${(b as { type: string }).type}` };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Types — match the server compiler output\n// ---------------------------------------------------------------------------\n\ntype Block =\n | { id: string; type: 'RichText'; data: Record<string, unknown>; childrenMarkdown?: string }\n | { id: string; type: 'Callout'; data: { tone?: 'info' | 'warn' | 'success' | 'danger' }; childrenMarkdown?: string }\n | { id: string; type: 'Checklist'; data: { items: { id: string; label: string; checked: boolean }[] } }\n | { id: string; type: 'Table'; data: { columns: string[]; rows: string[][] } }\n | { id: string; type: 'CodeTabs'; data: { tabs: { id: string; label: string; language: string; code: string; caption?: string }[] } }\n | { id: string; type: 'Decision'; data: { title?: string; question?: string; options: { id: string; label: string; detail: string; recommended?: boolean }[] } }\n | { id: string; type: 'OpenQuestions'; data: { questions: { id: string; label: string; kind: 'choice' | 'text' | 'multi'; options?: string[] }[] } }\n | { id: string; type: 'FileTree'; data: { title?: string; entries: { path: string; change: 'added' | 'modified' | 'removed' | 'renamed'; note?: string }[] } }\n | { id: string; type: 'Diff'; data: { filename?: string; language?: string; mode?: 'split' | 'unified'; before: string; after: string } }\n | { id: string; type: 'Stat'; data: { label: string; value: string | number; trend?: 'up' | 'down' | 'flat'; hint?: string } }\n | { id: string; type: 'Workflow'; data: { steps: { id: string; label: string; type: 'task' | 'decision' | 'note' }[]; connections?: { from: string; to: string; label?: string }[] } }\n | { id: string; type: 'Mockup'; data: { title?: string; x?: number; y?: number; w?: number; h?: number; html: string } }\n | { id: string; type: 'Diagram'; data: { title?: string; dataHtml: string; dataCss?: string } };\n\ninterface CompiledGlyph {\n slug: string;\n frontmatter: Record<string, unknown>;\n blocks: Block[];\n errors: Array<{ line?: number; message: string }>;\n compiledAt: string;\n}\n\ninterface CommentPin {\n id: string;\n elementId?: string | null;\n x: number;\n y: number;\n text: string;\n author?: string;\n created?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Section grouping — block ids → section headings\n// ---------------------------------------------------------------------------\n\nconst SECTION_MAP: Record<string, string> = {\n overview: 'Overview',\n implementation: 'Implementation plan',\n 'implementation-plan': 'Implementation plan',\n questions: 'Open questions',\n 'open-questions': 'Open questions',\n 'open-questions-for-you': 'Open questions',\n comments: 'Comments',\n handoff: 'Handoff',\n};\n\ninterface Section {\n heading: string | null;\n blocks: Block[];\n}\n\nfunction groupBlocksIntoSections(blocks: Block[]): Section[] {\n const sections: Section[] = [];\n let current: Section = { heading: null, blocks: [] };\n\n for (const b of blocks) {\n const heading = SECTION_MAP[b.id] ?? null;\n if (heading) {\n // Push any unheading prelude into a no-heading section so we don't lose it\n if (current.blocks.length > 0 || current.heading !== null) {\n sections.push(current);\n }\n current = { heading, blocks: [b] };\n } else {\n current.blocks.push(b);\n }\n }\n if (current.blocks.length > 0 || current.heading !== null) {\n sections.push(current);\n }\n return sections;\n}\n\n// ---------------------------------------------------------------------------\n// Props\n// ---------------------------------------------------------------------------\n\ninterface Props {\n slug: string;\n onClose?: () => void;\n /** Called after a comment is added so the parent can refresh. */\n onCommentAdded?: () => void;\n}\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport function GlyphRenderer({ slug, onClose, onCommentAdded }: Props) {\n const toast = useToast();\n const [compiled, setCompiled] = useState<CompiledGlyph | null>(null);\n const [comments, setComments] = useState<CommentPin[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n /** Error caught during the loading phase — shown inline so the user knows why. */\n const [loadError, setLoadError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n const [fullscreen, setFullscreen] = useState(false);\n\n // Context-menu state\n const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number; worldX: number; worldY: number } | null>(null);\n const [addingComment, setAddingComment] = useState<{ worldX: number; worldY: number } | null>(null);\n const [commentDraft, setCommentDraft] = useState('');\n\n // Active pin (expanded thread view)\n const [activePin, setActivePin] = useState<string | null>(null);\n\n // v4.4.8 — Per-block render errors caught by BlockErrorBoundary. The\n // boundary calls onError(err) which pushes into this array. We render\n // the array at the top of the canvas in a prominent red banner so the\n // user isn't left staring at a blank screen wondering what happened.\n const [blockErrors, setBlockErrors] = useState<\n Array<{ blockId: string; blockType: string; message: string }>\n >([]);\n const reportBlockError = React.useCallback(\n (blockId: string, blockType: string, err: Error) => {\n setBlockErrors((prev) => {\n // dedupe by blockId so the same block crashing twice doesn't\n // duplicate the entry\n if (prev.some((e) => e.blockId === blockId)) return prev;\n return [...prev, { blockId, blockType, message: err.message || String(err) }];\n });\n },\n [],\n );\n\n const canvasRef = useRef<HTMLDivElement>(null);\n\n // Section grouping — memoized so we don't re-walk the block array on every render\n const sections = useMemo(\n () => (compiled ? groupBlocksIntoSections(compiled.blocks) : []),\n [compiled],\n );\n\n // Load compiled glyph + comments\n useEffect(() => {\n let cancelled = false;\n const TIMEOUT_MS = 5000;\n\n (async () => {\n setLoading(true);\n setError(null);\n try {\n // Race the API calls against a 5-second timeout so the user\n // sees an error rather than a perpetual spinner if the server\n // hangs or the network drops.\n const timeoutPromise = new Promise((_, reject) =>\n setTimeout(() => reject(new Error('Request timed out after 5s')), TIMEOUT_MS)\n );\n\n const [renderData, artifactData] = await Promise.race([\n Promise.all([\n api.get<CompiledGlyph>(`/artifacts/${encodeURIComponent(slug)}/render`),\n api.get<{ comments?: CommentPin[]; commentsJson?: { comments?: CommentPin[] } }>(\n `/artifacts/${encodeURIComponent(slug)}`\n ),\n ]),\n timeoutPromise,\n ]) as [CompiledGlyph, { comments?: CommentPin[]; commentsJson?: { comments?: CommentPin[] } }];\n\n if (cancelled) return;\n setCompiled(renderData);\n const fromFile = (artifactData as any)?.comments ?? [];\n setComments(Array.isArray(fromFile) ? fromFile : []);\n } catch (err) {\n if (!cancelled) {\n const msg = (err as Error).message;\n setError(msg);\n setLoadError(msg);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [slug]);\n\n // Right-click context menu\n function onContainerContextMenu(e: React.MouseEvent) {\n if (!canvasRef.current) return;\n e.preventDefault();\n const rect = canvasRef.current.getBoundingClientRect();\n setCtxMenu({\n x: e.clientX,\n y: e.clientY,\n worldX: e.clientX - rect.left,\n worldY: e.clientY - rect.top,\n });\n }\n\n async function submitComment() {\n if (!addingComment || !commentDraft.trim()) return;\n try {\n const created = await api.post<{ id?: string }>(\n `/artifacts/${encodeURIComponent(slug)}/comments`,\n {\n x: addingComment.worldX,\n y: addingComment.worldY,\n text: commentDraft.trim(),\n author: 'drb0rk',\n }\n );\n setComments((prev) => [\n ...prev,\n {\n id: created.id ?? `cmt_${Date.now()}`,\n x: addingComment.worldX,\n y: addingComment.worldY,\n text: commentDraft.trim(),\n author: 'drb0rk',\n created: new Date().toISOString(),\n },\n ]);\n setAddingComment(null);\n setCommentDraft('');\n setCtxMenu(null);\n onCommentAdded?.();\n toast.success('Comment added');\n } catch (err) {\n toast.error(`Failed to add comment: ${(err as Error).message}`);\n }\n }\n\n // \"Send to agent\" — collects free-placed comments and any answers to\n // OpenQuestions, writes `feedback.md` on disk, and marks the artifact\n // `status: review` so the agent picks it up.\n async function submitFeedback() {\n if (submitting) return;\n setSubmitting(true);\n try {\n const result = await api.post<{ ok: boolean; commentCount?: number; questionCount?: number }>(\n `/artifacts/${encodeURIComponent(slug)}/submit`,\n { answers: [], submitter: 'drb0rk' },\n );\n if (result?.ok) {\n toast.success('Sent to agent — feedback.md written, status=review');\n onCommentAdded?.();\n } else {\n toast.error('Submit failed: server did not return ok=true');\n }\n } catch (err) {\n toast.error(`Submit failed: ${(err as Error).message}`);\n } finally {\n setSubmitting(false);\n }\n }\n\n function toggleFullscreen() {\n setFullscreen((v) => !v);\n }\n\n // Render a single block — wrapped in a BlockErrorBoundary so a single\n// broken block (e.g. wrong data shape from a parser bug) shows an inline\n// error card instead of blanking the whole canvas.\n const renderBlock = (b: Block) => {\n const id = b.id;\n const data = (b.data ?? {}) as Record<string, unknown>;\n // Validate data shape BEFORE handing to the component switch. A\n // validation failure shows an inline error card immediately, no\n // need for the boundary to catch it.\n const validation = validateBlock(b);\n if (!validation.ok) {\n return (\n <div\n key={id}\n id={id}\n className=\"glyph-block-error\"\n role=\"alert\"\n style={{\n border: '1px solid var(--error, #f85149)',\n background: 'rgba(248, 81, 73, 0.06)',\n borderRadius: 8,\n padding: '12px 14px',\n margin: '12px 0',\n color: 'var(--text)',\n fontFamily: 'var(--font-mono, ui-monospace, monospace)',\n fontSize: 12,\n lineHeight: 1.55,\n }}\n >\n <strong style={{ color: 'var(--error, #f85149)', fontFamily: 'var(--font-sans, system-ui, sans-serif)', display: 'block', marginBottom: 4 }}>\n {b.type} block invalid\n </strong>\n <div style={{ color: 'var(--text-muted)', marginBottom: 6 }}>\n block id: <code>{id}</code>\n </div>\n <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{validation.error}</pre>\n </div>\n );\n }\n // Wrap the actual render in an error boundary so even runtime\n // errors (bad component props, undefined data, etc.) don't crash\n // the whole canvas.\n return (\n <BlockErrorBoundary key={id} blockId={id} blockType={b.type} onError={reportBlockError}>\n {renderBlockInner(b, id, data)}\n </BlockErrorBoundary>\n );\n };\n\n // Inner renderer — split out so the outer renderBlock can validate +\n // wrap in an error boundary without nesting the switch in the JSX tree.\n const renderBlockInner = (b: Block, id: string, data: Record<string, unknown>) => {\n switch (b.type) {\n case 'RichText':\n return <RichText key={id} id={id}>{b.childrenMarkdown ?? ''}</RichText>;\n case 'Callout':\n return (\n <Callout key={id} id={id} tone={(data.tone as 'info' | 'warn' | 'success' | 'danger' | undefined) ?? 'info'}>\n {b.childrenMarkdown ?? ''}\n </Callout>\n );\n case 'Checklist':\n return (\n <Checklist key={id} id={id} items={(data.items as any) ?? []} />\n );\n case 'Table':\n return (\n <Table key={id} id={id} columns={(data.columns as string[]) ?? []} rows={(data.rows as string[][]) ?? []} />\n );\n case 'CodeTabs':\n return (\n <CodeTabs key={id} id={id} tabs={(data.tabs as any) ?? []} />\n );\n case 'Decision':\n return (\n <Decision\n key={id}\n id={id}\n title={data.title as string | undefined}\n question={data.question as string | undefined}\n options={(data.options as any) ?? []}\n />\n );\n case 'OpenQuestions':\n return (\n <OpenQuestions\n key={id}\n id={id}\n questions={(data.questions as any) ?? []}\n />\n );\n case 'FileTree':\n return (\n <FileTree\n key={id}\n id={id}\n title={data.title as string | undefined}\n entries={(data.entries as any) ?? []}\n />\n );\n case 'Diff':\n return (\n <Diff\n key={id}\n id={id}\n filename={data.filename as string | undefined}\n language={data.language as string | undefined}\n mode={(data.mode as 'split' | 'unified' | undefined) ?? 'unified'}\n before={(data.before as string) ?? ''}\n after={(data.after as string) ?? ''}\n />\n );\n case 'Stat':\n return (\n <Stat\n key={id}\n id={id}\n label={(data.label as string) ?? ''}\n value={data.value as string | number}\n trend={data.trend as 'up' | 'down' | 'flat' | undefined}\n hint={data.hint as string | undefined}\n />\n );\n case 'Workflow':\n return (\n <Workflow\n key={id}\n id={id}\n steps={(data.steps as any) ?? []}\n connections={data.connections as any}\n />\n );\n case 'Mockup':\n return (\n <Mockup\n key={id}\n id={id}\n title={data.title as string | undefined}\n x={data.x as number | undefined}\n y={data.y as number | undefined}\n w={data.w as number | undefined}\n h={data.h as number | undefined}\n html={(data.html as string) ?? ''}\n />\n );\n case 'Diagram':\n return (\n <div key={id} id={id} className=\"glyph-block-placeholder\">\n <em>[Diagram] {id}</em>\n </div>\n );\n }\n };\n\n if (loading) {\n return (\n <div className=\"glyph-renderer glyph-renderer--loading\">\n {loadError ? (\n <>\n <strong>Failed to load glyph.</strong>\n <pre>{loadError}</pre>\n </>\n ) : (\n <>\n <Spinner /> Loading glyph…\n </>\n )}\n </div>\n );\n }\n\n if (error || !compiled) {\n return (\n <div className=\"glyph-renderer glyph-renderer--error\">\n <strong>Failed to load glyph.</strong>\n <pre>{error ?? 'unknown error'}</pre>\n </div>\n );\n }\n\n const title = (compiled.frontmatter?.title as string) ?? slug;\n const status = (compiled.frontmatter?.status as string) ?? 'draft';\n const commentCount = comments.length;\n\n return (\n <div\n className={`glyph-canvas ${fullscreen ? 'glyph-canvas--fullscreen' : ''}`}\n ref={canvasRef}\n onContextMenu={onContainerContextMenu}\n >\n {/* Floating toolbar (sticky top-right pill) */}\n <div className=\"glyph-toolbar-floating\">\n <button\n className=\"glyph-btn glyph-btn--primary glyph-btn--send\"\n onClick={submitFeedback}\n disabled={submitting}\n title=\"Send comments + question answers to the agent — writes feedback.md, status=review\"\n >\n <Send size={14} />\n <span>Send to agent</span>\n <span className=\"glyph-btn-badge\">{commentCount}</span>\n </button>\n\n <span className=\"glyph-toolbar-divider\" />\n\n <button\n className=\"glyph-icon-btn\"\n title=\"Share\"\n onClick={() => {\n if (typeof window !== 'undefined' && navigator.clipboard) {\n navigator.clipboard.writeText(window.location.href).catch(() => {});\n toast.success('Link copied');\n }\n }}\n >\n <Share2 size={15} />\n </button>\n <button className=\"glyph-icon-btn\" title=\"Undo\" disabled>\n <Undo2 size={15} />\n </button>\n <button className=\"glyph-icon-btn\" title=\"Redo\" disabled>\n <Redo2 size={15} />\n </button>\n <button\n className=\"glyph-icon-btn\"\n title={fullscreen ? 'Exit fullscreen' : 'Fullscreen'}\n onClick={toggleFullscreen}\n >\n <Maximize2 size={15} />\n </button>\n <button className=\"glyph-icon-btn\" title=\"More\">\n <MoreHorizontal size={15} />\n </button>\n <span className=\"glyph-toolbar-divider\" />\n <button\n className=\"glyph-icon-btn\"\n title=\"Comment count\"\n aria-label=\"Comment count\"\n >\n <MessageSquare size={15} />\n <span className=\"glyph-icon-btn-count\">{commentCount}</span>\n </button>\n {onClose && (\n <button\n className=\"glyph-icon-btn glyph-icon-btn--close\"\n title=\"Close\"\n onClick={onClose}\n aria-label=\"Close\"\n >\n <X size={15} />\n </button>\n )}\n </div>\n\n {/* Canvas content — centered column of section cards */}\n <div className=\"glyph-canvas-content\">\n {/* Title strip (inside canvas, above sections) */}\n <header className=\"glyph-canvas-title\">\n <h1 className=\"glyph-title\">{title}</h1>\n <div className=\"glyph-meta\">\n <span className={`glyph-status glyph-status--${status}`}>{status}</span>\n <span className=\"glyph-slug\">{slug}</span>\n </div>\n </header>\n\n {/* v4.4.8 — Render errors banner. Two layers:\n 1. Compiler warnings from the MDX parser (e.g. unknown\n tag, unclosed block). Lightweight, yellow border.\n 2. Block render errors caught by BlockErrorBoundary. These\n are the \"one block crashed but the rest still rendered\"\n cases. Red border, prominent, listed first so the user\n sees them before scrolling. */}\n {(blockErrors.length > 0 || compiled.errors?.length > 0) && (\n <div\n className=\"glyph-render-errors\"\n role=\"alert\"\n style={{\n border: '1px solid var(--error, #f85149)',\n background: 'rgba(248, 81, 73, 0.08)',\n borderRadius: 8,\n padding: '12px 16px',\n margin: '0 0 16px 0',\n color: 'var(--text)',\n }}\n >\n <strong style={{ color: 'var(--error, #f85149)', display: 'block', marginBottom: 8 }}>\n {blockErrors.length > 0\n ? `${blockErrors.length} block${blockErrors.length === 1 ? '' : 's'} failed to render`\n : 'Compiler warnings'}\n </strong>\n <ul style={{ margin: 0, paddingLeft: 20, fontFamily: 'var(--font-mono, ui-monospace, monospace)', fontSize: 12, lineHeight: 1.6 }}>\n {blockErrors.map((e, i) => (\n <li key={`be-${i}`}>\n <strong>{e.blockType}</strong> (<code>{e.blockId}</code>): {e.message}\n </li>\n ))}\n {compiled.errors?.map((e, i) => (\n <li key={`ce-${i}`}>\n {e.line ? `line ${e.line}: ` : ''}{e.message}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* Sections */}\n <div className=\"glyph-sections\">\n {sections.map((section, i) => (\n <section\n key={`sec-${i}-${section.heading ?? 'ungrouped'}`}\n className={`glyph-section ${section.heading ? 'glyph-section--headed' : 'glyph-section--plain'}`}\n >\n {section.heading && (\n <h2 className=\"glyph-section-heading\">{section.heading}</h2>\n )}\n <div className=\"glyph-section-blocks\">\n {section.blocks.map(renderBlock)}\n </div>\n </section>\n ))}\n </div>\n </div>\n\n {/* Comment pin overlay */}\n {comments.map((c) => (\n <button\n key={c.id}\n className={`glyph-pin ${activePin === c.id ? 'glyph-pin--active' : ''}`}\n style={{ left: c.x, top: c.y }}\n onClick={(e) => {\n e.stopPropagation();\n setActivePin(activePin === c.id ? null : c.id);\n }}\n title={c.text}\n >\n <MapPin size={14} />\n {activePin === c.id && (\n <div className=\"glyph-pin-thread\">\n <div className=\"glyph-pin-text\">{c.text}</div>\n <div className=\"glyph-pin-meta\">\n {c.author ?? 'anonymous'} · {c.created ? new Date(c.created).toLocaleString() : ''}\n </div>\n </div>\n )}\n </button>\n ))}\n\n {/* Context menu (right-click) */}\n {ctxMenu && (\n <div\n className=\"glyph-ctx-menu\"\n style={{ left: ctxMenu.x, top: ctxMenu.y }}\n onClick={(e) => e.stopPropagation()}\n >\n <button\n className=\"glyph-ctx-item\"\n onClick={() => {\n setAddingComment({ worldX: ctxMenu.worldX, worldY: ctxMenu.worldY });\n setCtxMenu(null);\n }}\n >\n <MapPin size={14} /> Add comment here\n </button>\n </div>\n )}\n\n {/* Add-comment modal */}\n {addingComment && (\n <div className=\"glyph-modal-overlay\" onClick={() => setAddingComment(null)}>\n <div className=\"glyph-modal\" onClick={(e) => e.stopPropagation()}>\n <h3>Add comment at ({Math.round(addingComment.worldX)}, {Math.round(addingComment.worldY)})</h3>\n <textarea\n autoFocus\n value={commentDraft}\n onChange={(e) => setCommentDraft(e.target.value)}\n placeholder=\"What should the agent know about this area?\"\n rows={4}\n className=\"glyph-modal-textarea\"\n />\n <div className=\"glyph-modal-actions\">\n <button className=\"glyph-btn glyph-btn--ghost\" onClick={() => setAddingComment(null)}>\n Cancel\n </button>\n <button className=\"glyph-btn glyph-btn--primary\" onClick={submitComment} disabled={!commentDraft.trim()}>\n Add comment\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n// Tiny inline spinner (no extra dep)\nfunction Spinner() {\n return <span className=\"glyph-spinner\" aria-label=\"loading\">…</span>;\n}","// src/views/Artifacts.tsx — v3.1.0 artifact editor with fullscreen canvas + floating controls.\nimport React from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { GlyphRenderer } from './glyphs/GlyphRenderer';\nimport {\n ArrowLeft,\n Map as MapIcon,\n Plus,\n RefreshCw,\n Settings as SettingsIcon,\n MessageCircle,\n MessageSquare,\n Maximize2,\n Minimize2,\n X,\n Trash2,\n Pencil,\n Link2,\n Send,\n Check,\n Circle,\n StopCircle,\n AlertCircle,\n HelpCircle,\n CheckSquare,\n StickyNote,\n ChevronRight,\n Search,\n Activity,\n Filter,\n Archive,\n ArchiveRestore,\n Copy,\n ArrowUp,\n ArrowDown,\n Layers,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { CanvasContextMenu, type ContextMenuState } from '../components/CanvasContextMenu';\nimport { api } from '../lib/api';\nimport { cn, formatRelative, truncate } from '../lib/utils';\nimport type {\n Canvas,\n CanvasComment,\n CanvasConnection,\n CanvasElement,\n Artifact,\n Settings,\n Snapshot,\n} from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst ELEMENT_TYPES = [\n { id: 'task', label: 'Task', color: 'var(--info)', Icon: CheckSquare },\n { id: 'note', label: 'Note', color: 'var(--text-dim)', Icon: StickyNote },\n { id: 'decision', label: 'Decision', color: 'var(--accent)', Icon: Check },\n { id: 'question', label: 'Question', color: 'var(--warning)', Icon: HelpCircle },\n];\n\nconst PLAN_STATUSES = ['draft', 'approved', 'in-progress', 'done', 'rejected', 'archived'];\n\nfunction planStatusKind(status: string): 'success' | 'info' | 'error' | 'accent' | 'neutral' | 'warning' {\n switch (status) {\n case 'approved':\n case 'done':\n return 'success';\n case 'in-progress':\n case 'doing':\n return 'info';\n case 'rejected':\n return 'error';\n case 'archived':\n return 'warning';\n case 'draft':\n default:\n return 'neutral';\n }\n}\n\nfunction elementColor(type: string): string {\n return ELEMENT_TYPES.find((t) => t.id === type)?.color || 'var(--text-dim)';\n}\n\nfunction ElementIcon({ type, size = 12 }: { type: string; size?: number }) {\n const def = ELEMENT_TYPES.find((t) => t.id === type) || ELEMENT_TYPES[1];\n const Icon = def.Icon;\n return <Icon size={size} style={{ color: def.color }} />;\n}\n\n// ── List view ──────────────────────────────────────────────────────────\n\nexport function Artifacts({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const [artifacts, setPlans] = useState<Artifact[]>(snapshot.artifacts || []);\n const [loading, setLoading] = useState(!snapshot.artifacts);\n const [activeSlug, setActiveSlug] = useState<string | null>(null);\n const [filter, setFilter] = useState('');\n const [showArchived, setShowArchived] = useState(false);\n\n useEffect(() => {\n if (snapshot.artifacts) {\n setPlans(snapshot.artifacts);\n setLoading(false);\n }\n }, [snapshot.artifacts]);\n\n const reload = async () => {\n try {\n const d = await api.get<{ artifacts: Artifact[] }>('/artifacts');\n setPlans(d.artifacts || []);\n setLoading(false);\n } catch (err) {\n toast.error(`Artifacts load failed: ${(err as Error).message}`);\n setLoading(false);\n }\n };\n\n const filtered = useMemo(() => {\n let out = artifacts;\n if (filter) {\n const q = filter.toLowerCase();\n out = out.filter(\n (p) =>\n (p.slug || '').toLowerCase().includes(q) ||\n (p.title || '').toLowerCase().includes(q),\n );\n }\n if (!showArchived) {\n out = out.filter((p) => p.status !== 'archived');\n }\n return out;\n }, [artifacts, filter, showArchived]);\n\n const onCreate = async (slug: string, title?: string) => {\n try {\n const artifact = await api.post<{ slug: string }>('/artifacts', { slug, title });\n toast.success(`Artifact \"${artifact.slug}\" created.`);\n setActiveSlug(artifact.slug);\n await reload();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (slug: string) => {\n if (!confirm(`Delete artifact \"${slug}\"? This removes the directory permanently.`)) return;\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}`);\n toast.success('Artifact deleted.');\n if (activeSlug === slug) setActiveSlug(null);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n if (activeSlug) {\n // v3.21.0 — Use the new GlyphRenderer (agent-native-style MDX renderer)\n // instead of the hand-rolled PlanEditor canvas. Toggle available via the\n // \"Use MDX\" button in the header (TODO: surface this once stable).\n return (\n <div className=\"artifact-glyph-overlay\">\n <div className=\"artifact-glyph-toolbar\">\n <Button variant=\"ghost\" onClick={() => { setActiveSlug(null); reload(); }}>\n <ArrowLeft size={14} /> Back to artifacts\n </Button>\n </div>\n <GlyphRenderer\n slug={activeSlug}\n onClose={() => { setActiveSlug(null); reload(); }}\n onCommentAdded={() => reload()}\n />\n </div>\n );\n }\n\n return (\n <div className=\"view view-artifacts\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <MapIcon size={18} /> Glyphs ({artifacts.length})\n </h2>\n <p className=\"view-subtitle\">\n Visual artifacts with elements, connections, and threaded comments.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"search-input\">\n <Search size={14} />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setShowArchived((v) => !v)}\n title={showArchived ? 'Hide archived' : 'Show archived'}\n >\n {showArchived ? <ArchiveRestore size={14} /> : <Archive size={14} />}\n {showArchived ? 'Hide archived' : 'Show archived'}\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n </header>\n\n <NewPlanCard onCreate={onCreate} />\n\n {loading ? (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n </div>\n ) : filtered.length === 0 ? (\n <EmptyState\n icon={<MapIcon size={32} />}\n title={showArchived ? 'No artifacts' : 'No artifacts yet'}\n message={\n showArchived\n ? 'No artifacts match your filter (try Show archived off).'\n : 'Create one above to get started.'\n }\n />\n ) : (\n <div className=\"artifacts-grid\">\n {filtered.map((p) => (\n <PlanCard\n key={p.slug}\n artifact={p}\n onOpen={() => setActiveSlug(p.slug)}\n onDelete={() => onDelete(p.slug)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction NewPlanCard({ onCreate }: { onCreate: (slug: string, title?: string) => void }) {\n const [slug, setSlug] = useState('');\n const [title, setTitle] = useState('');\n return (\n <Card className=\"new-artifact\">\n <CardTitle>\n <Plus size={14} /> New artifact\n </CardTitle>\n <CardMeta>Slug must be lowercase, may contain hyphens, 1–64 chars.</CardMeta>\n <form\n className=\"new-artifact-form\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!slug.trim()) return;\n onCreate(slug.trim(), title.trim() || undefined);\n setSlug('');\n setTitle('');\n }}\n >\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"slug (e.g. dashboard-v3.1)\"\n pattern=\"[a-z0-9][a-z0-9-]{0,63}\"\n required\n value={slug}\n onChange={(e) => setSlug(e.target.value)}\n />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Title (optional)\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n />\n <Button variant=\"primary\" type=\"submit\">\n Create\n </Button>\n </form>\n </Card>\n );\n}\n\nfunction PlanCard({\n artifact,\n onOpen,\n onDelete,\n}: {\n artifact: Artifact;\n onOpen: () => void;\n onDelete: () => void;\n}) {\n const kind = planStatusKind(artifact.status || 'draft');\n return (\n <Card\n variant=\"elevated\"\n interactive\n className=\"artifact-card\"\n onClick={onOpen}\n >\n <div className=\"artifact-card-head\">\n <div className=\"artifact-card-title\">{artifact.title || artifact.slug}</div>\n <StatusBadge kind={kind}>{artifact.status || 'draft'}</StatusBadge>\n </div>\n <div className=\"artifact-card-slug mono\">{artifact.slug} · {artifact.source}</div>\n <div className=\"artifact-card-meta\">\n {artifact.elementCount != null && <span>{artifact.elementCount} elements</span>}\n {artifact.commentCount != null && <span> · {artifact.commentCount} comments</span>}\n <span> · edited {formatRelative(artifact.mtime)}</span>\n </div>\n <div className=\"artifact-card-actions\">\n <Button variant=\"primary\" size=\"sm\" onClick={(e) => { e.stopPropagation(); onOpen(); }}>\n Open\n <ChevronRight size={12} />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={(e) => { e.stopPropagation(); onDelete(); }}>\n <Trash2 size={12} /> Delete\n </Button>\n </div>\n </Card>\n );\n}\n\n// ── Artifact editor (fullscreen) ──────────────────────────────────────────\n\nfunction PlanEditor({\n slug,\n onBack,\n onDelete,\n}: {\n slug: string;\n onBack: () => void;\n onDelete: () => void;\n}) {\n const toast = useToast();\n const modal = useModal();\n const [canvas, setCanvas] = useState<Canvas | null>(null);\n const [meta, setMeta] = useState<{ title: string; status: string; tags: string[]; description?: string } | null>(null);\n const [loading, setLoading] = useState(true);\n const [selectedElId, setSelectedElId] = useState<string | null>(null);\n const [fullscreen, setFullscreen] = useState(false);\n const [showComments, setShowComments] = useState(true);\n const [contextMenu, setContextMenu] = useState<ContextMenuState>(null);\n const [contextMenuWorldPos, setContextMenuWorldPos] = useState<{ x: number; y: number } | null>(null);\n // v3.7.0 — Element-specific right-click context menu\n const [elementContextMenu, setElementContextMenu] = useState<ContextMenuState>(null);\n\n const moveElementLocally = (id: string, x: number, y: number) => {\n setCanvas((cur) => {\n if (!cur) return cur;\n return {\n ...cur,\n elements: cur.elements.map((el) => (el.id === id ? { ...el, x, y } : el)),\n };\n });\n };\n\n const reload = async () => {\n setLoading(true);\n try {\n const artifact = await api.get<{ meta: { title: string; status: string; tags: string[]; description?: string }; canvas: Canvas }>(\n `/artifacts/${encodeURIComponent(slug)}`,\n );\n setCanvas(artifact.canvas);\n setMeta(artifact.meta);\n } catch (err) {\n toast.error(`Could not load artifact: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setSelectedElId(null);\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [slug]);\n\n // Issue 3 fix — wire fullscreen state to browser Fullscreen API\n useEffect(() => {\n if (!fullscreen) {\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n }\n return;\n }\n // Sync state when user exits via ESC key — before entering, so we don't\n // double-set on the way in\n const onFullscreenChange = () => {\n if (!document.fullscreenElement) setFullscreen(false);\n };\n document.addEventListener('fullscreenchange', onFullscreenChange);\n // Attempt to enter fullscreen (fails silently if unsupported or blocked)\n document.documentElement.requestFullscreen().catch(() => {});\n return () => {\n document.removeEventListener('fullscreenchange', onFullscreenChange);\n if (document.fullscreenElement) {\n document.exitFullscreen().catch(() => {});\n }\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [fullscreen]);\n\n const totalComments = canvas?.comments.length ?? 0;\n\n const addElement = async (body: { type: string; title: string; content: string; x: number; y: number }, position?: { x: number; y: number }) => {\n try {\n const payload = position ? { ...body, x: position.x, y: position.y } : body;\n await api.post(`/artifacts/${encodeURIComponent(slug)}/elements`, payload);\n await reload();\n toast.success('Element added.');\n } catch (err) {\n toast.error(`Add element failed: ${(err as Error).message}`);\n }\n };\n\n const updateElement = async (id: string, body: Partial<CanvasElement>) => {\n try {\n await api.put(`/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(id)}`, body);\n await reload();\n } catch (err) {\n toast.error(`Update failed: ${(err as Error).message}`);\n }\n };\n\n const deleteElement = async (id: string) => {\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(id)}`);\n if (selectedElId === id) setSelectedElId(null);\n await reload();\n toast.success('Element deleted.');\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n // v3.7.0 — Duplicate an element with a small position offset\n const duplicateElement = async (id: string) => {\n const el = canvas?.elements.find((e) => e.id === id);\n if (!el) return;\n try {\n await api.post(`/artifacts/${encodeURIComponent(slug)}/elements`, {\n type: el.type,\n title: el.title ? `${el.title} (copy)` : 'Untitled',\n content: el.content || '',\n x: (el.x || 0) + 24,\n y: (el.y || 0) + 24,\n });\n await reload();\n toast.success('Element duplicated.');\n } catch (err) {\n toast.error(`Duplicate failed: ${(err as Error).message}`);\n }\n };\n\n // v3.7.0 — Change element type\n const changeElementType = async (id: string, newType: string) => {\n try {\n await api.put(`/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(id)}`, { type: newType });\n await reload();\n toast.success(`Type changed to ${newType}.`);\n } catch (err) {\n toast.error(`Change type failed: ${(err as Error).message}`);\n }\n };\n\n const addConnection = async (from: string, to: string, label?: string) => {\n try {\n await api.post(`/artifacts/${encodeURIComponent(slug)}/connections`, { from, to, label });\n await reload();\n toast.success('Connection added.');\n } catch (err) {\n toast.error(`Connection failed: ${(err as Error).message}`);\n }\n };\n\n const deleteConnection = async (id: string) => {\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}/connections/${encodeURIComponent(id)}`);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const addComment = async (text: string, elementId: string | null, worldPos?: { x: number; y: number }) => {\n try {\n const path = elementId\n ? `/artifacts/${encodeURIComponent(slug)}/elements/${encodeURIComponent(elementId)}/comments`\n : `/artifacts/${encodeURIComponent(slug)}/comments`;\n const body: { text: string; elementId: string | null; x?: number; y?: number } = { text, elementId };\n if (worldPos) { body.x = worldPos.x; body.y = worldPos.y; }\n await api.post(path, body);\n await reload();\n toast.success('Comment added.');\n } catch (err) {\n toast.error(`Comment failed: ${(err as Error).message}`);\n }\n };\n\n const deleteComment = async (cid: string) => {\n try {\n await api.del(`/artifacts/${encodeURIComponent(slug)}/comments/${encodeURIComponent(cid)}`);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const updatePositions = async (positions: { id: string; x: number; y: number }[]) => {\n try {\n await api.put(`/artifacts/${encodeURIComponent(slug)}/position`, { positions });\n } catch (err) {\n // non-fatal\n console.warn('Position update failed', err);\n }\n };\n\n const onConfigure = () => {\n if (!meta) return;\n let titleEl: HTMLInputElement | null = null;\n let descEl: HTMLTextAreaElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let statusEl: HTMLSelectElement | null = null;\n modal.open({\n title: 'Configure artifact',\n width: 560,\n children: (\n <div className=\"artifact-config-form\">\n <label className=\"field-label\">Title</label>\n <input ref={(el) => { titleEl = el; }} className=\"input\" type=\"text\" defaultValue={meta.title} />\n <label className=\"field-label\">Description (markdown)</label>\n <textarea ref={(el) => { descEl = el; }} className=\"textarea\" rows={3} defaultValue={meta.description || ''} />\n <label className=\"field-label\">Tags (comma-separated)</label>\n <input ref={(el) => { tagsEl = el; }} className=\"input\" type=\"text\" defaultValue={(meta.tags || []).join(', ')} />\n <label className=\"field-label\">Status</label>\n <select ref={(el) => { statusEl = el; }} className=\"select\" defaultValue={meta.status}>\n {PLAN_STATUSES.map((s) => (\n <option key={s} value={s}>{s}</option>\n ))}\n </select>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n try {\n const tags = (tagsEl?.value || '').split(',').map((t) => t.trim()).filter(Boolean);\n await api.put(`/artifacts/${encodeURIComponent(slug)}`, {\n title: (titleEl?.value || '').trim() || meta.title,\n description: descEl?.value || '',\n tags,\n status: statusEl?.value || meta.status,\n });\n await reload();\n toast.success('Artifact updated.');\n modal.close();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n Save\n </Button>\n </div>\n ),\n });\n };\n\n const onAddElement = (worldPos?: { x: number; y: number }) => {\n let typeEl: HTMLSelectElement | null = null;\n let titleEl: HTMLInputElement | null = null;\n let contentEl: HTMLTextAreaElement | null = null;\n modal.open({\n title: 'Add element',\n width: 520,\n children: (\n <div className=\"artifact-element-form\">\n <label className=\"field-label\">Type</label>\n <select ref={(el) => { typeEl = el; }} className=\"select\" defaultValue=\"task\">\n {ELEMENT_TYPES.map((t) => (\n <option key={t.id} value={t.id}>{t.label}</option>\n ))}\n </select>\n <label className=\"field-label\">Title</label>\n <input ref={(el) => { titleEl = el; }} className=\"input\" type=\"text\" placeholder=\"Element title\" autoFocus />\n <label className=\"field-label\">Content (markdown)</label>\n <textarea ref={(el) => { contentEl = el; }} className=\"textarea\" rows={4} placeholder=\"Description…\" />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (worldPos) {\n await addElement({\n type: typeEl?.value || 'note',\n title: (titleEl?.value || 'Untitled').trim(),\n content: contentEl?.value || '',\n x: worldPos.x,\n y: worldPos.y,\n });\n } else {\n const maxX = (canvas?.elements || []).reduce((acc, el) => Math.max(acc, el.x || 0), 0);\n const maxY = (canvas?.elements || []).reduce((acc, el) => Math.max(acc, el.y || 0), 0);\n await addElement({\n type: typeEl?.value || 'note',\n title: (titleEl?.value || 'Untitled').trim(),\n content: contentEl?.value || '',\n x: 80 + Math.min(maxX + 40, 200),\n y: 80 + Math.min(maxY + 40, 200),\n });\n }\n modal.close();\n }}\n >\n <Plus size={12} /> Add\n </Button>\n </div>\n ),\n });\n };\n\n const onCanvasComment = (worldPos?: { x: number; y: number }) => {\n let textEl: HTMLTextAreaElement | null = null;\n modal.open({\n title: 'Add canvas comment',\n width: 480,\n children: (\n <div>\n <label className=\"field-label\">Comment</label>\n <textarea ref={(el) => { textEl = el; }} className=\"textarea\" rows={4} placeholder=\"Comment for the whole artifact…\" autoFocus />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async (e) => {\n e.preventDefault();\n e.stopPropagation();\n const text = (textEl?.value || '').trim();\n if (!text) return;\n await addComment(text, null, worldPos);\n modal.close();\n }}\n >\n <Send size={12} /> Post\n </Button>\n </div>\n ),\n });\n };\n\n if (loading || !canvas || !meta) {\n return (\n <div className=\"view view-artifacts view-artifacts-fullscreen\">\n <PlanEditorHeader\n slug={slug}\n meta={meta || { title: slug, status: 'draft', tags: [] }}\n counts={{ elements: 0, comments: 0 }}\n onBack={onBack}\n onConfigure={() => undefined}\n onAddElement={() => undefined}\n onCanvasComment={() => undefined}\n onRefresh={reload}\n onDelete={onDelete}\n fullscreen={fullscreen}\n setFullscreen={setFullscreen}\n />\n <div className=\"view-loading\" style={{ flex: 1 }}>\n <Spinner size=\"lg\" />\n <p>Loading canvas…</p>\n </div>\n </div>\n );\n }\n\n const visibleComments = selectedElId\n ? canvas.comments.filter((c) => c.elementId === selectedElId)\n : canvas.comments;\n\n return (\n <div className={cn('view view-artifacts view-artifacts-fullscreen', !fullscreen && 'view-artifacts-embedded')}>\n {!fullscreen && (\n <PlanEditorHeader\n slug={slug}\n meta={meta}\n counts={{ elements: canvas.elements.length, comments: totalComments }}\n onBack={onBack}\n onConfigure={onConfigure}\n onAddElement={onAddElement}\n onCanvasComment={onCanvasComment}\n onRefresh={reload}\n onDelete={onDelete}\n fullscreen={fullscreen}\n setFullscreen={setFullscreen}\n />\n )}\n\n <div className=\"artifacts-body\">\n {/* Canvas wrapper with floating controls */}\n <div className=\"artifact-canvas-wrapper\">\n {fullscreen && (\n <div className=\"artifact-canvas-floating-controls\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onBack} title=\"Back to artifacts list\">\n <ArrowLeft size={14} /> Back\n </Button>\n <h3>{meta?.title || slug}</h3>\n {meta && <StatusBadge kind={planStatusKind(meta.status)}>{meta.status}</StatusBadge>}\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onAddElement()}>\n <Plus size={14} /> Element\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onCanvasComment()}>\n <MessageCircle size={14} /> Comment\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onConfigure} title=\"Configure artifact\" aria-label=\"Configure artifact\">\n <SettingsIcon size={14} />\n </Button>\n </div>\n )}\n\n <CanvasViewport\n canvas={canvas}\n selectedElId={selectedElId}\n onSelect={setSelectedElId}\n onMoveElement={moveElementLocally}\n onMoveEnd={updatePositions}\n onDeleteElement={deleteElement}\n onConnect={(from, to) => addConnection(from, to)}\n onDeleteConnection={deleteConnection}\n onEditElement={(el) => editElementInline(modal, slug, el, updateElement, toast)}\n onContextMenu={(e, worldPos) => {\n e.preventDefault();\n setElementContextMenu(null);\n setContextMenuWorldPos(worldPos);\n setContextMenu({\n x: e.clientX,\n y: e.clientY,\n items: [\n { label: 'Add element', icon: Plus, onClick: () => onAddElement(worldPos) },\n { label: 'Add comment', icon: MessageSquare, onClick: () => onCanvasComment(worldPos) },\n { type: 'separator' },\n { label: 'Configure artifact', icon: SettingsIcon, onClick: onConfigure },\n { label: 'Delete artifact', icon: Trash2, onClick: onDelete },\n ],\n });\n }}\n onElementContextMenu={(e, elementId, _worldPos) => {\n const el = canvas?.elements.find((x) => x.id === elementId);\n if (!el) return;\n setContextMenu(null);\n setElementContextMenu({\n x: e.clientX,\n y: e.clientY,\n items: [\n { label: 'Edit', icon: Pencil, onClick: () => { editElementInline(modal, slug, el, updateElement, toast); } },\n { label: 'Duplicate', icon: Copy, onClick: () => duplicateElement(elementId) },\n { type: 'separator' },\n { label: 'Change type', icon: Layers, onClick: () => {\n // Cycle through types: task -> note -> decision -> question -> task\n const types = ['task', 'note', 'decision', 'question'];\n const currentIdx = types.indexOf(el.type);\n const nextType = types[(currentIdx + 1) % types.length];\n changeElementType(elementId, nextType);\n }},\n { type: 'separator' },\n { label: `Delete`, icon: Trash2, onClick: () => { if (confirm(`Delete \"${el.title || el.type}\"?`)) deleteElement(elementId); } },\n ],\n });\n }}\n />\n\n {/* Canvas-level context menu */}\n <CanvasContextMenu menu={contextMenu} onClose={() => setContextMenu(null)} />\n {/* Element-level context menu */}\n <CanvasContextMenu menu={elementContextMenu} onClose={() => setElementContextMenu(null)} />\n </div>\n\n {showComments && (\n <CommentsPanel\n slug={slug}\n comments={visibleComments}\n selectedElId={selectedElId}\n onAdd={(text) => addComment(text, selectedElId)}\n onDelete={deleteComment}\n onClose={() => {\n setShowComments(false);\n setSelectedElId(null);\n }}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction PlanEditorHeader({\n slug,\n meta,\n counts,\n onBack,\n onConfigure,\n onAddElement,\n onCanvasComment,\n onRefresh,\n onDelete,\n fullscreen,\n setFullscreen,\n}: {\n slug: string;\n meta: { title: string; status: string; tags: string[] };\n counts: { elements: number; comments: number };\n onBack: () => void;\n onConfigure: () => void;\n onAddElement: () => void;\n onCanvasComment: () => void;\n onRefresh: () => void;\n onDelete: () => void;\n fullscreen: boolean;\n setFullscreen: (v: boolean) => void;\n}) {\n const kind = planStatusKind(meta.status);\n return (\n <header className=\"artifacts-editor-bar\">\n <div className=\"artifacts-editor-bar-left\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onBack} title=\"Back to artifacts list\">\n <ArrowLeft size={14} /> Back\n </Button>\n <div className=\"artifacts-editor-meta\">\n <span className=\"artifacts-editor-title\">{meta.title || slug}</span>\n <span className=\"artifacts-editor-slug mono\">{slug}</span>\n <StatusBadge kind={kind}>{meta.status}</StatusBadge>\n </div>\n </div>\n <div className=\"artifacts-editor-bar-right\">\n <span className=\"muted text-sm\">\n {counts.elements} element{counts.elements === 1 ? '' : 's'} · {counts.comments} comment{counts.comments === 1 ? '' : 's'}\n </span>\n <Button variant=\"secondary\" size=\"sm\" onClick={onAddElement}>\n <Plus size={14} /> Element\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onCanvasComment}>\n <MessageCircle size={14} /> Comment\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onConfigure} title=\"Configure artifact\" aria-label=\"Configure artifact\">\n <SettingsIcon size={14} />\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRefresh} title=\"Refresh canvas\" aria-label=\"Refresh canvas\">\n <RefreshCw size={14} />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setFullscreen(!fullscreen)}\n title={fullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}\n aria-label={fullscreen ? 'Exit fullscreen' : 'Enter fullscreen'}\n >\n {fullscreen ? <Minimize2 size={14} /> : <Maximize2 size={14} />}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onDelete} title=\"Delete artifact\" aria-label=\"Delete artifact\">\n <Trash2 size={14} />\n </Button>\n </div>\n </header>\n );\n}\n\nfunction editElementInline(\n modal: ReturnType<typeof useModal>,\n slug: string,\n el: CanvasElement,\n updateElement: (id: string, body: Partial<CanvasElement>) => Promise<void>,\n toast: ReturnType<typeof useToast>,\n) {\n let typeEl: HTMLSelectElement | null = null;\n let titleEl: HTMLInputElement | null = null;\n let contentEl: HTMLTextAreaElement | null = null;\n let statusEl: HTMLInputElement | null = null;\n modal.open({\n title: `Edit ${el.title || el.type}`,\n width: 520,\n children: (\n <div className=\"artifact-element-form\">\n <label className=\"field-label\">Type</label>\n <select ref={(el2) => { typeEl = el2; }} className=\"select\" defaultValue={el.type}>\n {ELEMENT_TYPES.map((t) => (\n <option key={t.id} value={t.id}>{t.label}</option>\n ))}\n </select>\n <label className=\"field-label\">Title</label>\n <input ref={(el2) => { titleEl = el2; }} className=\"input\" type=\"text\" defaultValue={el.title} />\n <label className=\"field-label\">Status</label>\n <input ref={(el2) => { statusEl = el2; }} className=\"input\" type=\"text\" defaultValue={el.status} placeholder=\"open / done / blocked …\" />\n <label className=\"field-label\">Content (markdown)</label>\n <textarea ref={(el2) => { contentEl = el2; }} className=\"textarea\" rows={5} defaultValue={el.content} />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n try {\n await updateElement(el.id, {\n type: typeEl?.value || el.type,\n title: titleEl?.value ?? el.title,\n content: contentEl?.value ?? el.content,\n status: statusEl?.value || el.status,\n });\n toast.success('Element saved.');\n modal.close();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n >\n Save\n </Button>\n </div>\n ),\n });\n}\n\n// ── Canvas viewport ───────────────────────────────────────────────────\n\ntype ViewportProps = {\n canvas: Canvas;\n selectedElId: string | null;\n onSelect: (id: string | null) => void;\n onMoveElement: (id: string, x: number, y: number) => void;\n onMoveEnd: (positions: { id: string; x: number; y: number }[]) => void;\n onDeleteElement: (id: string) => void;\n onConnect: (from: string, to: string) => void;\n onDeleteConnection: (id: string) => void;\n onEditElement: (el: CanvasElement) => void;\n onContextMenu?: (e: React.MouseEvent, worldPos: { x: number; y: number }) => void;\n // v3.7.0 — Element-specific context menu (right-click on an element)\n onElementContextMenu?: (e: React.MouseEvent, elementId: string, worldPos: { x: number; y: number }) => void;\n fitToView?: () => void;\n};\n\nfunction CanvasViewport({\n canvas,\n selectedElId,\n onSelect,\n onMoveElement,\n onMoveEnd,\n onDeleteElement,\n onConnect,\n onDeleteConnection,\n onEditElement,\n onContextMenu,\n onElementContextMenu,\n}: ViewportProps) {\n const rootRef = useRef<HTMLDivElement>(null);\n const innerRef = useRef<HTMLDivElement>(null);\n const elementsRef = useRef(canvas.elements);\n const stateRef = useRef({\n panning: false,\n startX: 0,\n startY: 0,\n ox: canvas.viewport.x || 0,\n oy: canvas.viewport.y || 0,\n scale: canvas.viewport.zoom || 1,\n dragging: null as null | { id: string; offsetX: number; offsetY: number; moved: boolean; origX: number; origY: number },\n connecting: null as null | { fromId: string; x: number; y: number },\n });\n\n useEffect(() => {\n elementsRef.current = canvas.elements;\n }, [canvas.elements]);\n\n useEffect(() => {\n const root = rootRef.current;\n const inner = innerRef.current;\n if (!root || !inner) return undefined;\n const apply = () => {\n const s = stateRef.current;\n inner.style.transform = `translate(${s.ox}px, ${s.oy}px) scale(${s.scale})`;\n };\n apply();\n\n const screenToWorld = (clientX: number, clientY: number) => {\n const rect = inner.getBoundingClientRect();\n const s = stateRef.current;\n // rect.left/rect.top is the *post-transform* top-left; account for scale\n const x = (clientX - rect.left) / s.scale;\n const y = (clientY - rect.top) / s.scale;\n return { x, y };\n };\n\n const onMouseDown = (e: MouseEvent) => {\n if (e.button === 2) return;\n const t = e.target as HTMLElement;\n if (\n t === root ||\n t.classList.contains('canvas-grid-bg') ||\n t.classList.contains('canvas-inner')\n ) {\n stateRef.current.panning = true;\n stateRef.current.startX = e.clientX - stateRef.current.ox;\n stateRef.current.startY = e.clientY - stateRef.current.oy;\n root.style.cursor = 'grabbing';\n return;\n }\n const elCard = t.closest('.canvas-element') as HTMLElement | null;\n if (elCard) {\n const id = elCard.dataset.elementId;\n if (!id) return;\n const headerHit = !!t.closest('.canvas-element-head');\n const handleHit = !!t.closest('.canvas-element-handle');\n if (headerHit || handleHit) {\n const world = screenToWorld(e.clientX, e.clientY);\n const el = elementsRef.current.find((x) => x.id === id);\n if (!el) return;\n stateRef.current.dragging = {\n id,\n offsetX: world.x - (el.x || 0),\n offsetY: world.y - (el.y || 0),\n moved: false,\n origX: el.x || 0,\n origY: el.y || 0,\n };\n onSelect(id);\n e.preventDefault();\n }\n }\n };\n const onMouseMove = (e: MouseEvent) => {\n const s = stateRef.current;\n if (s.panning) {\n s.ox = e.clientX - s.startX;\n s.oy = e.clientY - s.startY;\n apply();\n return;\n }\n if (s.dragging) {\n const world = screenToWorld(e.clientX, e.clientY);\n const newX = Math.max(0, world.x - s.dragging.offsetX);\n const newY = Math.max(0, world.y - s.dragging.offsetY);\n if (!s.dragging.moved) {\n const dx = Math.abs(newX - s.dragging.origX);\n const dy = Math.abs(newY - s.dragging.origY);\n if (dx < 2 && dy < 2) return;\n }\n s.dragging.moved = true;\n onMoveElement(s.dragging.id, newX, newY);\n return;\n }\n if (s.connecting) {\n const inner2 = innerRef.current;\n if (!inner2) return;\n const world = screenToWorld(e.clientX, e.clientY);\n s.connecting.x = world.x;\n s.connecting.y = world.y;\n // Trigger a custom event so the connecting SVG re-renders.\n inner2.dispatchEvent(new CustomEvent('canvas-move', { detail: { x: world.x, y: world.y } }));\n }\n };\n const onMouseUp = () => {\n const s = stateRef.current;\n if (s.panning) {\n s.panning = false;\n root.style.cursor = '';\n }\n if (s.dragging) {\n if (s.dragging.moved) {\n const el = elementsRef.current.find((x) => x.id === s.dragging?.id);\n if (el) {\n onMoveEnd([{ id: el.id, x: el.x || 0, y: el.y || 0 }]);\n }\n }\n s.dragging = null;\n }\n if (s.connecting) {\n s.connecting = null;\n innerRef.current?.dispatchEvent(new CustomEvent('canvas-move', { detail: { x: 0, y: 0 } }));\n }\n };\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n const delta = e.deltaY > 0 ? 0.9 : 1.1;\n const next = Math.min(\n Math.max(stateRef.current.scale * delta, 0.25),\n 2.5,\n );\n stateRef.current.scale = next;\n apply();\n };\n root.addEventListener('mousedown', onMouseDown);\n window.addEventListener('mousemove', onMouseMove);\n window.addEventListener('mouseup', onMouseUp);\n root.addEventListener('wheel', onWheel, { passive: false });\n return () => {\n root.removeEventListener('mousedown', onMouseDown);\n window.removeEventListener('mousemove', onMouseMove);\n window.removeEventListener('mouseup', onMouseUp);\n root.removeEventListener('wheel', onWheel);\n };\n }, [onMoveElement, onMoveEnd, onSelect]);\n\n const fitToView = () => {\n if (!rootRef.current || canvas.elements.length === 0) {\n stateRef.current.ox = 0;\n stateRef.current.oy = 0;\n stateRef.current.scale = 1;\n const inner = innerRef.current;\n if (inner) {\n inner.style.transform = `translate(0px, 0px) scale(1)`;\n }\n return;\n }\n const bbox = canvas.elements.reduce(\n (acc, el) => {\n const ex = el.x || 0;\n const ey = el.y || 0;\n const ex2 = ex + (el.width || 240);\n const ey2 = ey + (el.height || 120);\n return {\n minX: Math.min(acc.minX, ex),\n minY: Math.min(acc.minY, ey),\n maxX: Math.max(acc.maxX, ex2),\n maxY: Math.max(acc.maxY, ey2),\n };\n },\n { minX: Infinity, minY: Infinity, maxX: -Infinity, maxY: -Infinity },\n );\n const pad = 80;\n const root = rootRef.current;\n const w = root.clientWidth - pad * 2;\n const h = root.clientHeight - pad * 2;\n const bw = bbox.maxX - bbox.minX;\n const bh = bbox.maxY - bbox.minY;\n const scale = Math.min(w / Math.max(bw, 1), h / Math.max(bh, 1), 1.5);\n const ox = -bbox.minX * scale + pad;\n const oy = -bbox.minY * scale + pad;\n stateRef.current.ox = ox;\n stateRef.current.oy = oy;\n stateRef.current.scale = scale;\n const inner = innerRef.current;\n if (inner) {\n inner.style.transform = `translate(${ox}px, ${oy}px) scale(${scale})`;\n }\n };\n\n return (\n <div className=\"artifacts-canvas-wrap\">\n <div className=\"canvas-toolbar\">\n <button type=\"button\" className=\"icon-btn\" title=\"Fit to view\" aria-label=\"Fit canvas to view\" onClick={fitToView}>\n <Maximize2 size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n title=\"Reset zoom\"\n aria-label=\"Reset canvas zoom\"\n onClick={() => {\n stateRef.current.ox = 0;\n stateRef.current.oy = 0;\n stateRef.current.scale = 1;\n const inner = innerRef.current;\n if (inner) inner.style.transform = 'translate(0px, 0px) scale(1)';\n }}\n >\n <Circle size={14} />\n </button>\n <span className=\"muted text-sm\" style={{ marginLeft: 'auto' }}>\n Pan: drag empty · Zoom: scroll · Drag element header to move · Double-click to edit · Right-click element for actions\n </span>\n </div>\n <div className=\"canvas-root\" ref={rootRef} onContextMenu={(e) => {\n e.preventDefault();\n const rect = innerRef.current?.getBoundingClientRect();\n const s = stateRef.current;\n if (!rect) return;\n const worldPos = { x: (e.clientX - rect.left) / s.scale, y: (e.clientY - rect.top) / s.scale };\n onContextMenu?.(e, worldPos);\n }}>\n <div className=\"canvas-grid-bg\" />\n <div className=\"canvas-inner\" ref={innerRef}>\n {canvas.elements.length === 0 ? (\n <div className=\"canvas-empty\">\n <EmptyState\n icon={<MapIcon size={32} />}\n title=\"No elements yet\"\n message=\"Add an element from the toolbar above to get started.\"\n />\n </div>\n ) : (\n <>\n <ConnectionsLayer\n canvas={canvas}\n onDeleteConnection={onDeleteConnection}\n />\n {canvas.elements.map((el) => (\n <CanvasElementView\n key={el.id}\n element={el}\n selected={selectedElId === el.id}\n commentCount={canvas.comments.filter((c) => c.elementId === el.id).length}\n onSelect={() => onSelect(el.id)}\n onEdit={() => onEditElement(el)}\n onDelete={() => onDeleteElement(el.id)}\n onContextMenu={onElementContextMenu ? (e) => {\n e.preventDefault();\n e.stopPropagation();\n const rect = innerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const s = stateRef.current;\n const worldPos = { x: (e.clientX - rect.left) / s.scale, y: (e.clientY - rect.top) / s.scale };\n onElementContextMenu(e, el.id, worldPos);\n } : undefined}\n />\n ))}\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction CanvasElementView({\n element,\n selected,\n commentCount,\n onSelect,\n onEdit,\n onDelete,\n onContextMenu,\n}: {\n element: CanvasElement;\n selected: boolean;\n commentCount: number;\n onSelect: () => void;\n onEdit: () => void;\n onDelete: () => void;\n onContextMenu?: (e: React.MouseEvent) => void;\n}) {\n const x = element.x || 0;\n const y = element.y || 0;\n const w = element.width || 240;\n const h = element.height || 120;\n const color = elementColor(element.type);\n return (\n <div\n className={cn('canvas-element', selected && 'canvas-element-selected')}\n data-element-id={element.id}\n style={{\n left: x,\n top: y,\n width: w,\n minHeight: h,\n borderColor: color,\n }}\n onClick={(e) => {\n e.stopPropagation();\n onSelect();\n }}\n onDoubleClick={(e) => {\n e.stopPropagation();\n onEdit();\n }}\n onContextMenu={(e) => {\n if (onContextMenu) {\n e.stopPropagation();\n onContextMenu(e);\n } else {\n e.preventDefault();\n if (confirm(`Delete element \"${element.title || element.type}\"?`)) {\n onDelete();\n }\n }\n }}\n >\n <div className=\"canvas-element-head\" style={{ background: `color-mix(in srgb, ${color} 12%, transparent)` }}>\n <div className=\"canvas-element-type\">\n <ElementIcon type={element.type} size={12} />\n <span style={{ color }}>{element.type}</span>\n </div>\n <div className=\"canvas-element-actions\">\n {commentCount > 0 && (\n <span className=\"canvas-element-badge\" title={`${commentCount} comments`}>\n <MessageCircle size={10} />\n {commentCount}\n </span>\n )}\n <button type=\"button\" className=\"canvas-element-handle\" title=\"Drag to move\" aria-label=\"Drag\">\n ⋮⋮\n </button>\n </div>\n </div>\n <div className=\"canvas-element-title\">{element.title || 'Untitled'}</div>\n {element.content && (\n <div className=\"canvas-element-content\">{truncate(element.content, 240)}</div>\n )}\n {element.status && element.status !== 'open' && (\n <div className=\"canvas-element-status\">\n <StatusBadge kind={element.status === 'done' ? 'success' : element.status === 'blocked' ? 'error' : 'info'}>\n {element.status}\n </StatusBadge>\n </div>\n )}\n </div>\n );\n}\n\nfunction ConnectionsLayer({\n canvas,\n onDeleteConnection,\n}: {\n canvas: Canvas;\n onDeleteConnection: (id: string) => void;\n}) {\n if (canvas.connections.length === 0) return null;\n const els = canvas.elements;\n // Compute bounding box\n const bbox = els.reduce(\n (acc, el) => {\n const ex = el.x || 0;\n const ey = el.y || 0;\n const ex2 = ex + (el.width || 240);\n const ey2 = ey + (el.height || 120);\n return {\n minX: Math.min(acc.minX, ex),\n minY: Math.min(acc.minY, ey),\n maxX: Math.max(acc.maxX, ex2),\n maxY: Math.max(acc.maxY, ey2),\n };\n },\n { minX: 0, minY: 0, maxX: 0, maxY: 0 },\n );\n const pad = 80;\n const w = bbox.maxX - bbox.minX + pad * 2;\n const h = bbox.maxY - bbox.minY + pad * 2;\n const ox = -bbox.minX + pad;\n const oy = -bbox.minY + pad;\n return (\n <svg\n className=\"canvas-connections\"\n width={w}\n height={h}\n style={{ left: bbox.minX - pad, top: bbox.minY - pad }}\n >\n <defs>\n <marker id=\"artifact-arrow\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\">\n <path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--accent)\" />\n </marker>\n </defs>\n {canvas.connections.map((c) => {\n const from = els.find((e) => e.id === c.from || e.id === c.fromElementId);\n const to = els.find((e) => e.id === c.to || e.id === c.toElementId);\n if (!from || !to) return null;\n const x1 = ox + (from.x || 0) + (from.width || 240) / 2;\n const y1 = oy + (from.y || 0) + (from.height || 120);\n const x2 = ox + (to.x || 0) + (to.width || 240) / 2;\n const y2 = oy + (to.y || 0);\n const midX = (x1 + x2) / 2;\n const midY = (y1 + y2) / 2;\n return (\n <g key={c.id} className=\"canvas-connection\" onClick={() => onDeleteConnection(c.id)}>\n <line x1={x1} y1={y1} x2={x2} y2={y2} stroke=\"var(--accent)\" strokeWidth={1.5} markerEnd=\"url(#artifact-arrow)\" />\n {c.label && (\n <text x={midX} y={midY} className=\"canvas-connection-label\" textAnchor=\"middle\">\n {c.label}\n </text>\n )}\n </g>\n );\n })}\n </svg>\n );\n}\n\n// ── Comments panel ────────────────────────────────────────────────────\n\nfunction CommentsPanel({\n slug,\n comments,\n selectedElId,\n onAdd,\n onDelete,\n onClose,\n}: {\n slug: string;\n comments: CanvasComment[];\n selectedElId: string | null;\n onAdd: (text: string) => void;\n onDelete: (cid: string) => void;\n onClose: () => void;\n}) {\n const [text, setText] = useState('');\n return (\n <aside className=\"artifacts-comments-panel\">\n <header className=\"artifacts-comments-panel-head\">\n <h3 className=\"card-title\">\n <MessageCircle size={14} />\n {selectedElId ? 'Element comments' : 'Canvas comments'}\n </h3>\n <button type=\"button\" className=\"icon-btn\" onClick={onClose} title=\"Close panel\" aria-label=\"Close\">\n <X size={14} />\n </button>\n </header>\n <div className=\"artifacts-comments-panel-list\">\n {comments.length === 0 ? (\n <p className=\"muted text-sm\" style={{ padding: 'var(--space-4)' }}>\n {selectedElId ? 'No comments on this element yet.' : 'No comments on this artifact yet.'}\n </p>\n ) : (\n comments.map((c) => (\n <div key={c.id} className=\"artifact-comment\">\n <div className=\"artifact-comment-head\">\n <span className=\"artifact-comment-author mono\">{c.author}</span>\n <span className=\"artifact-comment-time tabular-nums muted\">{formatRelative(c.created)}</span>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete comment\"\n onClick={() => onDelete(c.id)}\n title=\"Delete\"\n >\n <Trash2 size={10} />\n </button>\n </div>\n <div className=\"artifact-comment-text\">{c.text}</div>\n </div>\n ))\n )}\n </div>\n <form\n className=\"artifacts-comments-panel-form\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!text.trim()) return;\n onAdd(text.trim());\n setText('');\n }}\n >\n <textarea\n className=\"textarea\"\n rows={2}\n placeholder={selectedElId ? 'Add a comment to this element…' : 'Add a canvas comment…'}\n value={text}\n onChange={(e) => setText(e.target.value)}\n />\n <Button variant=\"primary\" size=\"sm\" type=\"submit\" disabled={!text.trim()}>\n <Send size={12} /> Post\n </Button>\n </form>\n </aside>\n );\n}\n","// src/components/Tag.tsx — pill for tags.\n\nimport type { ReactNode } from 'react';\nimport { cn } from '../lib/utils';\n\nexport type TagProps = {\n children: ReactNode;\n className?: string;\n onRemove?: () => void;\n};\n\nexport function Tag({ children, className, onRemove }: TagProps) {\n return (\n <span className={cn('tag', className)}>\n {children}\n {onRemove && (\n <button\n type=\"button\"\n className=\"tag-remove\"\n aria-label={`Remove ${typeof children === 'string' ? children : 'tag'}`}\n onClick={onRemove}\n >\n ×\n </button>\n )}\n </span>\n );\n}\n","// src/web/components/tasks/BacklogPanel.tsx — v3.22\n// Backlog panel: lists parked tasks, promote individually or all-at-once.\nimport { useEffect, useState } from 'react';\nimport {\n ArrowUp,\n Trash2,\n Sparkles,\n RefreshCw,\n Inbox,\n} from 'lucide-react';\nimport { Button } from '../Button';\nimport { useToast } from '../Toast';\nimport { api } from '../../lib/api';\nimport { formatRelative } from '../../lib/utils';\nimport type { Task, Agent } from '../../lib/types';\n\ntype BacklogItemProps = {\n task: Task;\n agents: Agent[];\n onPromote: (id: string) => void;\n onDelete: (id: string) => void;\n onEdit: (task: Task) => void;\n onRefresh: () => Promise<void>;\n};\n\nfunction BacklogItem({ task, agents, onPromote, onDelete, onEdit, onRefresh }: BacklogItemProps) {\n const toast = useToast();\n\n const handlePromote = async () => {\n try {\n await api.post(`/tasks/${encodeURIComponent(task.id)}/promote`);\n toast.success('Promoted to queued.', 1500);\n onPromote(task.id);\n } catch (err) {\n toast.error(`Promote failed: ${(err as Error).message}`);\n }\n };\n\n const handleDelete = async () => {\n if (!confirm('Delete this task?')) return;\n try {\n await api.del(`/tasks/${encodeURIComponent(task.id)}`);\n toast.success('Deleted.', 1500);\n onDelete(task.id);\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const priorityDot: Record<string, string> = {\n high: 'var(--warning)',\n normal: 'var(--info)',\n low: 'var(--muted)',\n };\n\n return (\n <div className=\"backlog-item\" data-task-id={task.id}>\n <div className=\"backlog-item-head\">\n <span\n className=\"priority-dot\"\n style={{ background: priorityDot[task.priority] || 'var(--info)' }}\n />\n <span className=\"backlog-item-title\">{task.title}</span>\n {task.assignee && (\n <span className=\"backlog-item-badge\">@{task.assignee}</span>\n )}\n {task.tags?.length > 0 && (\n <span className=\"backlog-item-badge\">{task.tags.join(', ')}</span>\n )}\n </div>\n {task.description && (\n <div className=\"backlog-item-desc\">{task.description.slice(0, 120)}</div>\n )}\n <div className=\"backlog-item-footer\">\n <span className=\"muted text-sm tabular-nums\">\n {formatRelative(task.createdAt)}\n </span>\n <div className=\"backlog-item-actions\">\n <button\n type=\"button\"\n className=\"icon-btn\"\n title=\"Promote to queued\"\n onClick={handlePromote}\n >\n <ArrowUp size={13} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n title=\"Edit\"\n onClick={() => onEdit(task)}\n >\n <Sparkles size={13} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n title=\"Delete\"\n onClick={handleDelete}\n >\n <Trash2 size={13} />\n </button>\n </div>\n </div>\n </div>\n );\n}\n\ntype Props = {\n /** Current list of agents for the edit modal. */\n agents: Agent[];\n /** Called after any mutation so the parent can refresh snapshot. */\n onRefresh: () => Promise<void>;\n};\n\nexport function BacklogPanel({ agents, onRefresh }: Props) {\n const toast = useToast();\n const [tasks, setTasks] = useState<Task[]>([]);\n const [loading, setLoading] = useState(false);\n\n const load = async () => {\n try {\n setLoading(true);\n const r = await api.get<{ tasks: Task[] }>('/tasks/backlog');\n setTasks(Array.isArray(r.tasks) ? r.tasks : []);\n } catch (err) {\n toast.error(`Backlog load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => { load(); }, []);\n\n const handlePromote = async (id: string) => {\n setTasks((cur) => cur.filter((t) => t.id !== id));\n await onRefresh();\n };\n\n const handleDelete = async (id: string) => {\n setTasks((cur) => cur.filter((t) => t.id !== id));\n await onRefresh();\n };\n\n const handleEdit = (_task: Task) => {\n // Editing is wired through the parent Tasks view's modal helper.\n // Keep this no-op so the icon click is at least visible; the parent\n // provides the real edit affordance via the kanban.\n };\n\n const handlePromoteAll = async () => {\n if (tasks.length === 0) return;\n try {\n const r = await api.post<{ affected: { id: string; ok: boolean }[] }>('/tasks/promote-batch', {\n ids: tasks.map((t) => t.id),\n });\n const ok = r.affected?.filter((a) => a.ok).length ?? 0;\n toast.success(`Promoted ${ok} task(s).`, 2000);\n setTasks([]);\n await onRefresh();\n } catch (err) {\n toast.error(`Promote all failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <div className=\"backlog-panel\">\n <div className=\"backlog-panel-header\">\n <span className=\"backlog-panel-title\">\n <Inbox size={15} />\n Backlog ({tasks.length})\n </span>\n <div className=\"backlog-panel-header-actions\">\n {tasks.length > 0 && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handlePromoteAll} title=\"Promote all to queued\">\n <ArrowUp size={12} /> Promote all\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Refresh backlog\" aria-label=\"Refresh backlog\">\n <RefreshCw size={12} className={loading ? 'animate-spin' : ''} />\n </Button>\n </div>\n </div>\n\n {loading ? (\n <div className=\"backlog-empty\">Loading…</div>\n ) : tasks.length === 0 ? (\n <div className=\"backlog-empty\">\n <Inbox size={28} />\n <span>Backlog is empty.</span>\n </div>\n ) : (\n <div className=\"backlog-list\">\n {tasks.map((t) => (\n <BacklogItem\n key={t.id}\n task={t}\n agents={agents}\n onPromote={handlePromote}\n onDelete={handleDelete}\n onEdit={handleEdit}\n onRefresh={onRefresh}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n","// src/views/Tasks.tsx\n//\n// v4.6.0 — Simplified task board.\n//\n// Design goals (per Odin):\n// - Create flow = title + description (+ optional priority hint + tags).\n// No agent picker. Odin decides what to do with the task and which\n// agent picks it up; the UI just records intent.\n// - Tasks grouped by status into 5 columns:\n// Todo (api: queued)\n// In progress (api: doing)\n// Done (api: done)\n// Failed (api: blocked)\n// Backlog (api: backlog, parked ideas)\n// - Each task row shows title, status, priority, createdAt, and the\n// agent that auto-claimed it (read-only — set by the orchestrator).\n// - Per-task actions: edit, delete, retry, change status.\n// - Backlog view: parked ideas; one-click \"promote to Todo\".\n//\n// We keep the API contract (statuses: queued/doing/done/blocked/backlog)\n// so the dashboard doesn't break the existing server, tasks store, and\n// tests. The UI maps API statuses to friendlier labels.\nimport React, { useEffect, useMemo, useState } from 'react';\nimport {\n CheckSquare,\n Plus,\n Trash2,\n ChevronLeft,\n ChevronRight,\n Search,\n X as XIcon,\n Clock,\n Tag as TagIcon,\n ArchiveRestore,\n RefreshCw,\n Send,\n Inbox,\n Edit2,\n RotateCw,\n Bot,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Spinner } from '../components/Spinner';\nimport { Tag } from '../components/Tag';\nimport { useModal } from '../components/Modal';\nimport { useToast } from '../components/Toast';\nimport { api, enhancePrompt } from '../lib/api';\nimport { cn, formatRelative, priorityColors } from '../lib/utils';\nimport type { Settings, Snapshot, Task } from '../lib/types';\nimport { BacklogPanel } from '../components/tasks/BacklogPanel';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype StatusKind = 'info' | 'accent' | 'success' | 'warning' | 'error';\n\n/**\n * UI <-> API status mapping. We keep the existing API enum\n * (queued | doing | done | blocked | archived | backlog) and only\n * rename the labels here so the dashboard, server, and tests stay in\n * sync. Switch back if you need to expose the raw API value.\n */\nconst COLUMNS: { id: Task['status']; label: string; kind: StatusKind }[] = [\n { id: 'queued', label: 'Todo', kind: 'info' },\n { id: 'doing', label: 'In progress', kind: 'accent' },\n { id: 'done', label: 'Done', kind: 'success' },\n { id: 'blocked', label: 'Failed', kind: 'error' },\n];\n\nconst PRIORITIES = ['low', 'normal', 'high'] as const;\ntype Priority = (typeof PRIORITIES)[number];\n\nfunction TasksInner({ snapshot, refreshSnapshot, setActiveTab }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [tasks, setTasks] = useState<Task[]>(snapshot.tasks || []);\n const [loading, setLoading] = useState(!snapshot.tasks);\n const [filter, setFilter] = useState('');\n const [priorityFilter, setPriorityFilter] = useState<string>('');\n const [showBacklog, setShowBacklog] = useState(false);\n const [tick, setTick] = useState(0); // for live timer re-render\n\n const reload = async () => {\n try {\n const data = await api.get<Task[]>('/tasks');\n setTasks(Array.isArray(data) ? data : []);\n } catch (err) {\n toast.error(`Tasks load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n if (snapshot.tasks) {\n setTasks(snapshot.tasks);\n setLoading(false);\n }\n }, [snapshot.tasks]);\n\n // Periodic tick keeps relative-time labels fresh without a full reload.\n useEffect(() => {\n const id = setInterval(() => setTick((t) => t + 1), 30_000);\n return () => clearInterval(id);\n }, []);\n\n const filtered = useMemo(() => {\n let out = tasks.filter((t) => t.status !== 'backlog');\n if (priorityFilter) {\n out = out.filter((t) => (t.priority || 'normal') === priorityFilter);\n }\n if (filter.trim()) {\n const q = filter.toLowerCase();\n out = out.filter((t) =>\n (t.title || '').toLowerCase().includes(q) ||\n (t.description || '').toLowerCase().includes(q),\n );\n }\n return out;\n }, [tasks, filter, priorityFilter]);\n\n const sorted = useMemo(() => {\n const priorityWeight = { high: 0, normal: 1, low: 2 } as Record<string, number>;\n return [...filtered].sort((a, b) => {\n const pa = priorityWeight[a.priority] ?? 1;\n const pb = priorityWeight[b.priority] ?? 1;\n if (pa !== pb) return pa - pb;\n return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();\n });\n }, [filtered]);\n\n const backlogCount = tasks.filter((t) => t.status === 'backlog').length;\n\n // ─── Actions ─────────────────────────────────────────────────────────────\n\n const moveTask = async (taskId: string, newStatus: string) => {\n const t = tasks.find((x) => x.id === taskId);\n if (!t) return;\n const prev = t.status;\n setTasks((cur) =>\n cur.map((x) => (x.id === taskId ? { ...x, status: newStatus } : x)),\n );\n try {\n await api.patch(`/tasks/${encodeURIComponent(taskId)}/status`, {\n status: newStatus,\n });\n toast.success(`Moved to ${newStatus}.`, 1200);\n } catch (err) {\n setTasks((cur) =>\n cur.map((x) => (x.id === taskId ? { ...x, status: prev } : x)),\n );\n toast.error(`Move failed: ${(err as Error).message}`);\n }\n };\n\n const deleteTask = async (taskId: string) => {\n if (!confirm('Delete this task?')) return;\n try {\n await api.del(`/tasks/${encodeURIComponent(taskId)}`);\n setTasks((cur) => cur.filter((t) => t.id !== taskId));\n toast.success('Task deleted.', 1200);\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const retryTask = async (taskId: string) => {\n try {\n // Re-dispatch via the existing /tasks/:id/start endpoint. The\n // server returns 202 on accept; failures surface as 502/404.\n const r = await api.post<{ ok: boolean; task: Task }>(\n `/tasks/${encodeURIComponent(taskId)}/start`,\n );\n if (r && r.task) {\n setTasks((cur) => cur.map((t) => (t.id === taskId ? r.task : t)));\n }\n toast.success('Retry dispatched.', 1200);\n } catch (err) {\n toast.error(`Retry failed: ${(err as Error).message}`);\n }\n };\n\n const submitToOdin = async (taskId: string) => {\n const t = tasks.find((x) => x.id === taskId);\n if (!t) return;\n try {\n // The /tasks/submit endpoint takes a title + description and\n // hands the bundle to Odin for delegation. We re-use the task's\n // existing fields.\n const r = await api.post<{ main: Task; subtasks: Task[] }>('/tasks/submit', {\n title: t.title,\n description: t.description,\n priority: t.priority,\n tags: t.tags,\n });\n const count = (r.subtasks || []).length;\n toast.success(\n count > 1\n ? `Odin split it into ${count} subtasks.`\n : 'Sent to Odin.',\n 1500,\n );\n if (r.subtasks && r.subtasks.length > 0) {\n setTasks((cur) => [r.main, ...r.subtasks, ...cur.filter((x) => x.id !== t.id)]);\n }\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Submit failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <div className=\"view view-tasks\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <CheckSquare size={18} /> Tasks ({sorted.length})\n </h2>\n <p className=\"view-subtitle\">\n Add a task — title and description is all you need. Odin picks the agent and priority.\n </p>\n </div>\n </header>\n\n {/* Toolbar: search, filter, sort, actions */}\n <div className=\"tasks-toolbar\">\n <div className=\"tasks-toolbar-group\">\n <div className=\"search-input\" style={{ width: 200 }}>\n <Search size={12} />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n {filter && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Clear search\"\n onClick={() => setFilter('')}\n >\n <XIcon size={12} />\n </button>\n )}\n </div>\n </div>\n\n <div className=\"tasks-toolbar-divider\" />\n\n <div className=\"tasks-toolbar-group\">\n <span className=\"tasks-toolbar-label\">Priority</span>\n <select\n className=\"select select-sm\"\n value={priorityFilter}\n onChange={(e) => setPriorityFilter(e.target.value)}\n title=\"Filter by priority\"\n >\n <option value=\"\">All</option>\n {PRIORITIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n </div>\n\n <div className=\"tasks-toolbar-spacer\" />\n\n <div className=\"tasks-toolbar-group\">\n <Button variant=\"ghost\" size=\"sm\" onClick={reload} title=\"Refresh\" aria-label=\"Refresh tasks\">\n <RefreshCw size={14} />\n </Button>\n {backlogCount > 0 && (\n <Button\n variant={showBacklog ? 'accent' : 'ghost'}\n size=\"sm\"\n onClick={() => setShowBacklog((v) => !v)}\n title={showBacklog ? 'Hide backlog' : 'Show backlog'}\n >\n <Inbox size={14} />\n Backlog\n <span className=\"badge\">{backlogCount}</span>\n </Button>\n )}\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={() => openCreateTaskModal(modal, toast, setTasks, reload, refreshSnapshot)}\n >\n <Plus size={14} /> New task\n </Button>\n </div>\n </div>\n\n {showBacklog && backlogCount > 0 && (\n <BacklogPanel\n agents={snapshot.agents || []}\n onRefresh={refreshSnapshot}\n />\n )}\n\n {loading ? (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n ) : (\n <div className=\"kanban\">\n {COLUMNS.map((col) => (\n <KanbanColumn\n key={col.id}\n column={col}\n tasks={sorted.filter((t) => t.status === col.id)}\n onMove={moveTask}\n onDelete={deleteTask}\n onRetry={retryTask}\n onEdit={(t) => openEditTaskModal(modal, toast, t, setTasks, reload, refreshSnapshot)}\n onSubmitToOdin={submitToOdin}\n tick={tick}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ─── Column ────────────────────────────────────────────────────────────────\n\nfunction KanbanColumn({\n column,\n tasks,\n onMove,\n onDelete,\n onRetry,\n onEdit,\n onSubmitToOdin,\n tick,\n}: {\n column: { id: string; label: string; kind: StatusKind };\n tasks: Task[];\n onMove: (id: string, status: string) => void;\n onDelete: (id: string) => void;\n onRetry: (id: string) => void;\n onEdit: (t: Task) => void;\n onSubmitToOdin: (id: string) => void;\n tick: number;\n}) {\n const [dragOver, setDragOver] = useState(false);\n return (\n <div\n className={cn('kanban-column', dragOver && 'kanban-column-drop')}\n data-column={column.id}\n onDragOver={(e) => { e.preventDefault(); setDragOver(true); }}\n onDragLeave={() => setDragOver(false)}\n onDrop={(e) => {\n e.preventDefault();\n setDragOver(false);\n const id = e.dataTransfer.getData('text/task-id');\n if (id) onMove(id, column.id);\n }}\n >\n <div className=\"kanban-col-header\">\n <CardTitle>\n <span className={cn('status-dot', `status-${column.kind}`)} />\n {column.label}\n </CardTitle>\n <span className=\"kanban-col-count tabular-nums\">{tasks.length}</span>\n </div>\n <div className=\"kanban-col-body\">\n {tasks.length === 0 ? (\n <div className=\"kanban-empty\">No tasks</div>\n ) : (\n tasks.map((t) => (\n <TaskCard\n key={t.id}\n task={t}\n onMove={(dir) => {\n const idx = COLUMNS.findIndex((c) => c.id === t.status);\n const next = idx + dir;\n if (next >= 0 && next < COLUMNS.length) onMove(t.id, COLUMNS[next].id);\n }}\n onEdit={() => onEdit(t)}\n onDelete={() => onDelete(t.id)}\n onRetry={() => onRetry(t.id)}\n onSubmitToOdin={() => onSubmitToOdin(t.id)}\n tick={tick}\n />\n ))\n )}\n </div>\n </div>\n );\n}\n\n// ─── Card ──────────────────────────────────────────────────────────────────\n\nfunction TaskCard({\n task,\n onMove,\n onEdit,\n onDelete,\n onRetry,\n onSubmitToOdin,\n tick,\n}: {\n task: Task;\n onMove: (dir: -1 | 1) => void;\n onEdit: () => void;\n onDelete: () => void;\n onRetry: () => void;\n onSubmitToOdin: () => void;\n tick: number;\n}) {\n const assignedAgent = task.workedBy || task.assignee || null;\n return (\n <div\n className={cn('task-card', `priority-${task.priority}`)}\n data-task-id={task.id}\n draggable\n onDragStart={(e) => {\n e.dataTransfer.setData('text/task-id', task.id);\n e.dataTransfer.effectAllowed = 'move';\n }}\n data-tick={tick}\n >\n <div className=\"task-card-head\">\n <span\n className=\"priority-dot\"\n style={{ background: priorityColors[task.priority] || 'var(--info)' }}\n />\n <div className=\"task-card-title\">{task.title}</div>\n </div>\n {task.description && (\n <div className=\"task-card-desc\">{task.description.slice(0, 160)}</div>\n )}\n <div className=\"task-card-badges\">\n {assignedAgent && (\n <span className=\"task-card-badge\" title={`Auto-assigned to @${assignedAgent}`}>\n <Bot size={10} /> @{assignedAgent}\n </span>\n )}\n {task.timeSpent ? (\n <span className=\"task-card-badge\">\n <Clock size={10} /> {Math.round((task.timeSpent || 0) / 60)}m\n </span>\n ) : null}\n {task.tags && task.tags.length > 0 && task.tags.slice(0, 3).map((tag) => (\n <Tag key={tag}>{tag}</Tag>\n ))}\n </div>\n <div className=\"task-card-footer\">\n <span className=\"task-card-time tabular-nums muted\">\n {formatRelative(task.createdAt)}\n </span>\n <div className=\"task-card-actions\" onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Move left\"\n title=\"Move left\"\n onClick={() => onMove(-1)}\n >\n <ChevronLeft size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Edit\"\n title=\"Edit\"\n onClick={onEdit}\n >\n <Edit2 size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Submit to Odin\"\n title=\"Re-delegate to Odin\"\n onClick={onSubmitToOdin}\n >\n <Send size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Retry\"\n title=\"Retry\"\n onClick={onRetry}\n >\n <RotateCw size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete\"\n title=\"Delete\"\n onClick={onDelete}\n >\n <Trash2 size={14} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Move right\"\n title=\"Move right\"\n onClick={() => onMove(1)}\n >\n <ChevronRight size={14} />\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n// ─── Create / Edit modal ───────────────────────────────────────────────────\n//\n// Simplified: title, description, priority hint, optional tags. NO\n// agent dropdown. The store will default `assignee` and `workedBy` to\n// null; the orchestrator sets them when it picks the task up.\n\nfunction openCreateTaskModal(\n modal: ReturnType<typeof useModal>,\n toast: ReturnType<typeof useToast>,\n setTasks: (updater: (cur: Task[]) => Task[]) => void,\n reload: () => Promise<void>,\n refreshSnapshot: () => Promise<void>,\n) {\n let titleEl: HTMLInputElement | null = null;\n let descEl: HTMLTextAreaElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let priorityEl: HTMLSelectElement | null = null;\n\n const submit = async (e?: React.SyntheticEvent) => {\n if (e && typeof e.preventDefault === 'function') e.preventDefault();\n const title = (titleEl?.value || '').trim();\n const description = (descEl?.value || '').trim();\n if (!title) {\n toast.warning('Title is required.');\n titleEl?.focus();\n return;\n }\n const priority = (priorityEl?.value || 'normal') as Priority;\n const tags = (tagsEl?.value || '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n\n try {\n const created = await api.post<Task>('/tasks', {\n title,\n description,\n priority,\n tags,\n // No assignee / agent — Odin decides.\n });\n modal.close();\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new MouseEvent('mousedown'));\n }\n setTasks((cur) => [created, ...cur]);\n toast.success('Task created.', 1200);\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n }\n };\n\n const onTitleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n submit(e);\n }\n };\n\n modal.open({\n title: 'New task',\n width: 520,\n children: (\n <div className=\"task-form\">\n <label className=\"field-label\" htmlFor=\"task-title\">Title *</label>\n <input\n ref={(el) => { titleEl = el; }}\n id=\"task-title\"\n className=\"input\"\n type=\"text\"\n maxLength={200}\n placeholder=\"What needs to be done?\"\n autoFocus\n onKeyDown={onTitleKeyDown}\n />\n <label className=\"field-label\" htmlFor=\"task-desc\">Description</label>\n <div style={{ display: 'flex', gap: 6, alignItems: 'flex-start' }}>\n <textarea\n ref={(el) => { descEl = el; }}\n id=\"task-desc\"\n className=\"textarea\"\n rows={4}\n placeholder=\"Add any context Odin might need (markdown ok)…\"\n style={{ flex: 1 }}\n />\n <button\n type=\"button\"\n className=\"btn btn-ghost btn-icon\"\n title=\"Enhance with AI\"\n onClick={async () => {\n if (!descEl?.value?.trim()) return;\n const enhanced = await enhancePrompt(descEl.value);\n if (enhanced !== descEl.value) descEl.value = enhanced;\n }}\n >\n ✨\n </button>\n </div>\n <div className=\"task-form-row\">\n <label htmlFor=\"task-priority\" className=\"task-form-field\">\n Priority hint\n <select\n ref={(el) => { priorityEl = el; }}\n id=\"task-priority\"\n className=\"select\"\n defaultValue=\"normal\"\n >\n {PRIORITIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n </label>\n <label htmlFor=\"task-tags\" className=\"task-form-field\" style={{ flex: 2 }}>\n Tags <span className=\"field-hint\">(comma-separated)</span>\n <input\n ref={(el) => { tagsEl = el; }}\n id=\"task-tags\"\n className=\"input\"\n type=\"text\"\n placeholder=\"bug, frontend, urgent\"\n />\n </label>\n </div>\n <p className=\"muted text-sm\" style={{ marginTop: 8 }}>\n The agent and final priority are decided by Odin after you submit.\n </p>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button variant=\"primary\" type=\"button\" onClick={(e) => submit(e)}>\n <Plus size={14} /> Create task\n </Button>\n </div>\n ),\n });\n}\n\nfunction openEditTaskModal(\n modal: ReturnType<typeof useModal>,\n toast: ReturnType<typeof useToast>,\n task: Task,\n setTasks: (updater: (cur: Task[]) => Task[]) => void,\n reload: () => Promise<void>,\n refreshSnapshot: () => Promise<void>,\n) {\n let titleEl: HTMLInputElement | null = null;\n let descEl: HTMLTextAreaElement | null = null;\n let tagsEl: HTMLInputElement | null = null;\n let priorityEl: HTMLSelectElement | null = null;\n\n const submit = async () => {\n const title = (titleEl?.value || '').trim();\n const description = (descEl?.value || '').trim();\n if (!title) {\n toast.warning('Title is required.');\n titleEl?.focus();\n return;\n }\n const priority = (priorityEl?.value || 'normal') as Priority;\n const tags = (tagsEl?.value || '')\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n\n try {\n const updated = await api.put<Task>(`/tasks/${encodeURIComponent(task.id)}`, {\n title,\n description,\n priority,\n tags,\n });\n modal.close();\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new MouseEvent('mousedown'));\n }\n setTasks((cur) => cur.map((x) => (x.id === task.id ? updated : x)));\n toast.success('Task updated.', 1200);\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n };\n\n modal.open({\n title: 'Edit task',\n width: 520,\n children: (\n <div className=\"task-form\">\n <label className=\"field-label\" htmlFor=\"edit-task-title\">Title *</label>\n <input\n ref={(el) => { titleEl = el; }}\n id=\"edit-task-title\"\n className=\"input\"\n type=\"text\"\n maxLength={200}\n defaultValue={task.title}\n autoFocus\n />\n <label className=\"field-label\" htmlFor=\"edit-task-desc\">Description</label>\n <textarea\n ref={(el) => { descEl = el; }}\n id=\"edit-task-desc\"\n className=\"textarea\"\n rows={4}\n defaultValue={task.description || ''}\n />\n <div className=\"task-form-row\">\n <label htmlFor=\"edit-task-priority\" className=\"task-form-field\">\n Priority hint\n <select\n ref={(el) => { priorityEl = el; }}\n id=\"edit-task-priority\"\n className=\"select\"\n defaultValue={task.priority || 'normal'}\n >\n {PRIORITIES.map((p) => (\n <option key={p} value={p}>{p}</option>\n ))}\n </select>\n </label>\n <label htmlFor=\"edit-task-tags\" className=\"task-form-field\" style={{ flex: 2 }}>\n Tags\n <input\n ref={(el) => { tagsEl = el; }}\n id=\"edit-task-tags\"\n className=\"input\"\n type=\"text\"\n defaultValue={(task.tags || []).join(', ')}\n placeholder=\"comma-separated\"\n />\n </label>\n </div>\n <Card>\n <CardTitle><TagIcon size={12} /> Status</CardTitle>\n <CardMeta>\n Current: <strong>{task.status}</strong>\n {task.workedBy && <> · Worked by @{task.workedBy}</>}\n {task.assignee && !task.workedBy && <> · Assigned @{task.assignee}</>}\n </CardMeta>\n </Card>\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button variant=\"primary\" onClick={submit}>\n <ArchiveRestore size={14} /> Save\n </Button>\n </div>\n ),\n });\n}\nexport const Tasks = React.memo(TasksInner);\n","// src/web/components/ArtifactViewer.tsx — modal viewer for rendered HTML artifacts.\nimport { useEffect, useState } from 'react';\nimport { X, ExternalLink, Download, FileText } from 'lucide-react';\nimport { useModal } from './Modal';\nimport { Spinner } from './Spinner';\nimport { api } from '../lib/api';\n\ntype ArtifactMeta = {\n id: string;\n name: string;\n contentType: string;\n size: number;\n createdAt: string;\n};\n\ntype Props = {\n artifactId: string;\n onClose: () => void;\n};\n\nexport function ArtifactViewer({ artifactId, onClose }: Props) {\n const [meta, setMeta] = useState<ArtifactMeta | null>(null);\n const [content, setContent] = useState<string>('');\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n setLoading(true);\n try {\n const [metaData, contentData] = await Promise.all([\n api.get<ArtifactMeta>(`/artifacts/${encodeURIComponent(artifactId)}`),\n fetchRawContent(artifactId),\n ]);\n if (!cancelled) {\n setMeta(metaData);\n setContent(contentData);\n }\n } catch (err) {\n if (!cancelled) {\n console.error('Failed to load artifact:', err);\n }\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => { cancelled = true; };\n }, [artifactId]);\n\n return (\n <div className=\"modal-backdrop\" onClick={(e) => { e.stopPropagation(); if (e.target === e.currentTarget) onClose(); }}>\n <div className=\"modal artifact-viewer-modal\" role=\"dialog\" aria-modal=\"true\">\n <header className=\"modal-header\">\n <div className=\"modal-title-group\">\n <FileText size={16} />\n <h2 className=\"modal-title\">{meta?.name || 'Artifact'}</h2>\n {meta && (\n <span className=\"artifact-viewer-meta muted\">\n {meta.contentType} · {formatBytes(meta.size)}\n </span>\n )}\n </div>\n <div className=\"modal-header-actions\">\n {meta && (\n <>\n <a\n href={getArtifactContentUrl(artifactId)}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"icon-btn\"\n aria-label=\"Open artifact in new tab\"\n title=\"Open in new tab\"\n >\n <ExternalLink size={16} />\n </a>\n <a\n href={getArtifactContentUrl(artifactId)}\n download={meta.name || 'artifact.html'}\n className=\"icon-btn\"\n aria-label=\"Download artifact\"\n title=\"Download\"\n >\n <Download size={16} />\n </a>\n </>\n )}\n <button type=\"button\" className=\"icon-btn\" aria-label=\"Close\" onClick={onClose}>\n <X size={16} />\n </button>\n </div>\n </header>\n <div className=\"modal-body artifact-viewer-body\">\n {loading ? (\n <div className=\"artifact-viewer-loading\">\n <Spinner />\n <span className=\"muted\">Loading artifact…</span>\n </div>\n ) : content ? (\n <iframe\n srcDoc={content}\n className=\"artifact-viewer-iframe\"\n sandbox=\"allow-scripts allow-forms allow-popups allow-same-origin\"\n title={meta?.name || 'Artifact'}\n />\n ) : (\n <div className=\"artifact-viewer-empty muted\">\n <FileText size={32} />\n <p>No content available.</p>\n </div>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n// Fetch raw text content — bypasses the JSON api wrapper.\nasync function fetchRawContent(artifactId: string): Promise<string> {\n const r = await fetch(getArtifactContentUrl(artifactId));\n if (!r.ok) throw new Error(`HTTP ${r.status}`);\n return r.text();\n}\n\nfunction getArtifactContentUrl(artifactId: string): string {\n return api.urlWithToken(`/artifacts/${encodeURIComponent(artifactId)}/content`);\n}\n\n// v3.5.7 — Open the artifact in a new browser tab at full window size.\n// The artifact's own HTML renders edge-to-edge, which is what users want\n// for visual artifacts (they're meant to be viewed, not crammed in a modal).\nexport function openArtifactViewer(\n _modal: ReturnType<typeof useModal>,\n artifactId: string,\n): void {\n const url = getArtifactContentUrl(artifactId);\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n","// src/views/Activity.tsx — v3.5.4: timeline-based activity view (replaces the v3.5.2 graph+strip hybrid).\n// Layout: CSS grid with 3 sibling columns — left event stream, center timeline canvas, right detail panel.\n// X axis is time; Y axis is lanes (BG instances + tasks). Active tasks pulse; queued tasks are translucent\n// dashed; done tasks are faded. A red \"now\" line updates every 1s and re-anchors when it nears the right edge.\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n Activity as ActivityIcon,\n Bot,\n CheckSquare,\n Cpu,\n RefreshCw,\n Send,\n X,\n Plus,\n Trash2,\n MessageSquare,\n History,\n Pause,\n Play,\n PanelLeftClose,\n PanelLeftOpen,\n Layers,\n Target,\n FileText,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Settings, Snapshot, Task, Agent } from '../lib/types';\nimport { openArtifactViewer } from '../components/ArtifactViewer';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype BgInstance = {\n instanceId: string;\n agent?: string;\n status?: string;\n startedAt?: number;\n completedAt?: number;\n lastEventAt?: number;\n promptPreview?: string;\n resultPreview?: string;\n error?: string;\n parentAgent?: string;\n parentInstanceId?: string;\n tmuxSession?: string;\n tmuxActive?: boolean;\n taskId?: string; // v3.6.2 — linked task for artifact lookup\n _bgDir?: string;\n};\n\ntype ActivityEvent = {\n ts: string;\n kind: string;\n nodeId?: string;\n text?: string;\n author?: string;\n taskId?: string;\n [k: string]: unknown;\n};\n\n// ─── Time / layout constants ──────────────────────────────────────────\n\nconst ZOOM_RANGES = {\n '1m': 60 * 1000,\n '5m': 5 * 60 * 1000,\n '30m': 30 * 60 * 1000,\n '1h': 60 * 60 * 1000,\n} as const;\ntype ZoomKey = keyof typeof ZOOM_RANGES;\n\nconst LANE_HEIGHT = 56;\nconst TIME_AXIS_HEIGHT = 32;\nconst EVENTS_STRIP_HEIGHT = 22;\nconst MIN_BAR_WIDTH = 4;\nconst REANCHOR_RATIO = 0.9; // when now_x exceeds this fraction of canvas width, re-anchor viewStart\n\n// ─── Status → color ───────────────────────────────────────────────────\n\nconst STATUS_COLORS: Record<string, string> = {\n working: 'var(--success)',\n running: 'var(--success)',\n doing: 'var(--info)',\n queued: 'var(--info)',\n done: 'var(--success)',\n success: 'var(--success)',\n blocked: 'var(--warning)',\n error: 'var(--error)',\n failed: 'var(--error)',\n stuck: 'var(--warning)',\n killed: 'var(--error)',\n idle: 'var(--text-dim)',\n pending: 'var(--info)',\n timed_out: 'var(--warning)',\n};\n\nfunction statusColor(s: string | null | undefined): string {\n if (!s) return STATUS_COLORS.idle;\n return STATUS_COLORS[s] || STATUS_COLORS.idle;\n}\n\nfunction shortLabel(s: string | null | undefined, n = 24): string {\n if (!s) return '';\n if (s.length <= n) return s;\n return s.slice(0, n - 1) + '…';\n}\n\n// ─── Time helpers ─────────────────────────────────────────────────────\n\nfunction parseTs(ts: string | number | null | undefined): number {\n if (ts == null) return 0;\n if (typeof ts === 'number') return ts;\n const t = new Date(ts).getTime();\n return Number.isNaN(t) ? 0 : t;\n}\n\nfunction taskStartMs(t: Task): number {\n // v3.5.4 — prefer _timerStart (set when work begins), fall back to createdAt.\n const ts = (t as { _timerStart?: number })._timerStart;\n if (typeof ts === 'number' && ts > 0) return ts;\n return parseTs(t.createdAt) || Date.now();\n}\n\nfunction taskEndMs(t: Task, now: number): number {\n if (t.status === 'done' || t.status === 'archived' || t.status === 'failed' || t.status === 'killed') {\n return parseTs(t.completedAt) || parseTs(t.updatedAt) || now;\n }\n // Active tasks: pin to now.\n return now;\n}\n\nfunction bgStartMs(b: BgInstance): number {\n return typeof b.startedAt === 'number' && b.startedAt > 0 ? b.startedAt : Date.now();\n}\n\nfunction bgEndMs(b: BgInstance, now: number): number {\n if (\n b.status === 'done'\n || b.status === 'success'\n || b.status === 'killed'\n || b.status === 'failed'\n || b.status === 'error'\n || b.status === 'timed_out'\n ) {\n return b.completedAt || b.lastEventAt || now;\n }\n return now;\n}\n\nfunction chooseTickStep(rangeMs: number): number {\n if (rangeMs <= 60_000) return 10_000;\n if (rangeMs <= 300_000) return 30_000;\n if (rangeMs <= 1_800_000) return 300_000;\n return 600_000;\n}\n\nfunction formatTickLabel(t: number, rangeMs: number): string {\n const d = new Date(t);\n if (rangeMs <= 300_000) {\n return d.toLocaleTimeString('en-GB', { hour12: false });\n }\n return d.toLocaleTimeString('en-GB', { hour12: false, hour: '2-digit', minute: '2-digit' });\n}\n\n// ─── Lane + tick types ────────────────────────────────────────────────\n\ntype Lane =\n | { kind: 'bg'; id: string; index: number; label: string; sub: string; start: number; end: number; data: BgInstance }\n | { kind: 'task'; id: string; index: number; label: string; sub: string; start: number; end: number; data: Task }\n | { kind: 'events'; id: string; index: number; label: string; sub: string; start: number; end: number };\n\ntype SelectedItem = {\n id: string;\n kind: 'task' | 'bg' | 'agent';\n label: string;\n status: string;\n data: Task | BgInstance | Agent;\n};\n\ntype EventMarker = {\n id: string;\n x: number;\n y: number;\n kind: string;\n ts: number;\n text: string;\n author?: string;\n};\n\ntype TaskBar = {\n id: string;\n laneIndex: number;\n x: number;\n y: number;\n w: number;\n h: number;\n label: string;\n statusClass: 'doing' | 'done' | 'queued' | 'blocked' | 'failed';\n selected: boolean;\n data: Task | BgInstance;\n kind: 'task' | 'bg';\n start: number;\n end: number;\n};\n\n// ─── Component ────────────────────────────────────────────────────────\n\nexport function Activity({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const canvasWrapRef = useRef<HTMLDivElement | null>(null);\n\n // View state\n const [mode, setMode] = useState<'live' | 'pause'>('live');\n const [zoom, setZoom] = useState<ZoomKey>('5m');\n const [streamOpen, setStreamOpen] = useState(() => {\n if (typeof window === 'undefined') return true;\n return window.innerWidth > 900;\n });\n\n // Data\n const [bgInstances, setBgInstances] = useState<BgInstance[]>([]);\n const [events, setEvents] = useState<ActivityEvent[]>([]);\n const [loading, setLoading] = useState(true);\n const [refreshTick, setRefreshTick] = useState(0);\n\n // Time\n const [nowTick, setNowTick] = useState<number>(Date.now());\n const [viewStart, setViewStart] = useState<number>(() => Date.now() - ZOOM_RANGES['5m'] * 0.1);\n\n // Canvas size (observed)\n const [canvasSize, setCanvasSize] = useState<{ width: number; height: number }>({ width: 800, height: 400 });\n\n // Selection / detail\n const [selectedItem, setSelectedItem] = useState<SelectedItem | null>(null);\n\n // Detail panel local state\n const [commentText, setCommentText] = useState('');\n const [comments, setComments] = useState<ActivityEvent[]>([]);\n const [taskTitle, setTaskTitle] = useState('');\n const [taskPriority, setTaskPriority] = useState('normal');\n const [bgMessage, setBgMessage] = useState('');\n const [bgOutput, setBgOutput] = useState('');\n const [creatingTask, setCreatingTask] = useState(false);\n const [postingComment, setPostingComment] = useState(false);\n // v3.6.2 — artifact IDs fetched from the task linked to the selected bg instance.\n const [bgArtifactIds, setBgArtifactIds] = useState<string[]>([]);\n\n const modal = useModal();\n\n const agents = snapshot.agents || [];\n const tasks = snapshot.tasks || [];\n const rangeMs = ZOOM_RANGES[zoom];\n const rangeStart = viewStart;\n const rangeEnd = viewStart + rangeMs;\n\n // ─── Data polling ───────────────────────────────────────────────────\n const reloadAll = useCallback(async () => {\n try {\n const [bgRes, evRes] = await Promise.all([\n api.get<{ instances: BgInstance[] }>('/background').catch(() => ({ instances: [] })),\n api.get<{ events: ActivityEvent[] }>('/activity?limit=200').catch(() => ({ events: [] })),\n ]);\n setBgInstances(bgRes.instances || []);\n setEvents(evRes.events || []);\n } catch (err) {\n console.warn('activity reload failed:', err);\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n reloadAll();\n const id = setInterval(reloadAll, 3000);\n return () => clearInterval(id);\n }, [reloadAll]);\n\n // Trigger a re-fetch when the snapshot's task/agent counts change.\n useEffect(() => {\n setRefreshTick((t) => t + 1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [tasks.length, agents.length]);\n\n // ─── Now tick (1s) — paused when mode === 'pause' ───────────────────\n useEffect(() => {\n if (mode === 'pause') return;\n setNowTick(Date.now());\n const id = setInterval(() => setNowTick(Date.now()), 1000);\n return () => clearInterval(id);\n }, [mode, refreshTick]);\n\n // ─── Re-anchor viewStart when the now line nears the right edge ────\n useEffect(() => {\n if (mode === 'pause') return;\n const nowRatio = (nowTick - viewStart) / rangeMs;\n if (nowRatio > REANCHOR_RATIO) {\n setViewStart(nowTick - rangeMs * 0.1);\n }\n }, [nowTick, viewStart, rangeMs, mode]);\n\n // On zoom change, reset viewStart so now sits at 10% from the left.\n useEffect(() => {\n setViewStart(Date.now() - rangeMs * 0.1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [zoom]);\n\n // On resume from pause, re-anchor so the now line lands at 10%.\n useEffect(() => {\n if (mode === 'live') {\n setViewStart(Date.now() - rangeMs * 0.1);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [mode]);\n\n // ─── Canvas size observer ───────────────────────────────────────────\n useLayoutEffect(() => {\n const el = canvasWrapRef.current;\n if (!el) return;\n const ro = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n setCanvasSize({\n width: Math.max(200, Math.floor(width)),\n height: Math.max(120, Math.floor(height)),\n });\n }\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // ─── Lane allocation ────────────────────────────────────────────────\n const lanes: Lane[] = useMemo(() => {\n const out: Lane[] = [];\n let idx = 0;\n\n // BG instances — one lane each, at the top.\n for (const bg of bgInstances) {\n const start = bgStartMs(bg);\n const end = bgEndMs(bg, nowTick);\n if (end < rangeStart || start > rangeEnd) continue;\n out.push({\n kind: 'bg',\n id: `bg:${bg.instanceId}`,\n index: idx++,\n label: `BG ${shortLabel(bg.promptPreview, 20) || bg.instanceId.slice(0, 10)}`,\n sub: bg.status || 'pending',\n start,\n end,\n data: bg,\n });\n }\n\n // Tasks — greedy lane assignment (fill first lane that has no overlap).\n const sorted = [...tasks].sort((a, b) => taskStartMs(a) - taskStartMs(b));\n const taskLaneEnds: number[] = []; // end-time of last task placed in each lane\n for (const t of sorted) {\n const s = taskStartMs(t);\n const e = taskEndMs(t, nowTick);\n if (e < rangeStart || s > rangeEnd) continue;\n let assigned = -1;\n for (let i = 0; i < taskLaneEnds.length; i++) {\n if (taskLaneEnds[i] <= s) {\n taskLaneEnds[i] = e;\n assigned = i;\n break;\n }\n }\n if (assigned === -1) {\n taskLaneEnds.push(e);\n assigned = taskLaneEnds.length - 1;\n }\n out.push({\n kind: 'task',\n id: `task:${t.id}`,\n index: idx + assigned,\n label: shortLabel(t.title, 32),\n sub: t.status,\n start: s,\n end: e,\n data: t,\n });\n }\n\n return out;\n }, [bgInstances, tasks, nowTick, rangeStart, rangeEnd]);\n\n const laneById = useMemo(() => {\n const m = new Map<string, Lane>();\n for (const l of lanes) m.set(l.id, l);\n return m;\n }, [lanes]);\n\n // ─── Time → X coordinate ────────────────────────────────────────────\n const timeToX = useCallback(\n (t: number): number => {\n if (rangeMs <= 0) return 0;\n return ((t - rangeStart) / rangeMs) * canvasSize.width;\n },\n [rangeStart, rangeMs, canvasSize.width],\n );\n\n // ─── Tick marks for the time axis ───────────────────────────────────\n const ticks = useMemo(() => {\n const step = chooseTickStep(rangeMs);\n const result: { t: number; x: number; label: string }[] = [];\n // Align to step boundary.\n const startAligned = Math.floor(rangeStart / step) * step;\n for (let t = startAligned; t <= rangeEnd + step; t += step) {\n if (t < rangeStart - step) continue;\n if (t > rangeEnd) break;\n const x = timeToX(t);\n if (x < -40 || x > canvasSize.width + 40) continue;\n result.push({ t, x, label: formatTickLabel(t, rangeMs) });\n }\n return result;\n }, [rangeStart, rangeEnd, rangeMs, canvasSize.width, timeToX]);\n\n // ─── Build task/bg bars ─────────────────────────────────────────────\n const bars: TaskBar[] = useMemo(() => {\n const out: TaskBar[] = [];\n for (const lane of lanes) {\n if (lane.kind === 'events') continue;\n const visibleStart = Math.max(lane.start, rangeStart);\n const visibleEnd = Math.min(lane.end, rangeEnd);\n if (visibleEnd < rangeStart || visibleStart > rangeEnd) continue;\n const x = timeToX(visibleStart);\n const xEnd = timeToX(visibleEnd);\n const w = Math.max(MIN_BAR_WIDTH, xEnd - x);\n const y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + 8;\n const h = LANE_HEIGHT - 16;\n\n let statusClass: TaskBar['statusClass'] = 'doing';\n if (lane.kind === 'bg') {\n const s = lane.data.status || 'pending';\n if (s === 'done' || s === 'success') statusClass = 'done';\n else if (s === 'failed' || s === 'killed' || s === 'error') statusClass = 'failed';\n else if (s === 'queued' || s === 'pending') statusClass = 'queued';\n else if (s === 'blocked' || s === 'stuck') statusClass = 'blocked';\n else statusClass = 'doing';\n } else {\n const s = lane.data.status;\n if (s === 'done' || s === 'archived') statusClass = 'done';\n else if (s === 'failed' || s === 'killed') statusClass = 'failed';\n else if (s === 'queued') statusClass = 'queued';\n else if (s === 'blocked') statusClass = 'blocked';\n else statusClass = 'doing';\n }\n\n const selected = selectedItem?.id === lane.id;\n\n out.push({\n id: lane.id,\n laneIndex: lane.index,\n x,\n y,\n w,\n h,\n label: lane.label,\n statusClass,\n selected,\n data: lane.data,\n kind: lane.kind,\n start: lane.start,\n end: lane.end,\n });\n }\n return out;\n }, [lanes, timeToX, selectedItem, rangeStart, rangeEnd]);\n\n // ─── Build event markers (placed on the lane of their related entity) ─\n const eventMarkers: EventMarker[] = useMemo(() => {\n const out: EventMarker[] = [];\n for (const ev of events) {\n const ts = parseTs(ev.ts);\n if (ts < rangeStart - 5000 || ts > rangeEnd + 5000) continue;\n const x = timeToX(ts);\n\n // Try to find a related lane.\n let y = TIME_AXIS_HEIGHT + 12; // default: events strip\n if (ev.taskId) {\n const lane = laneById.get(`task:${ev.taskId}`);\n if (lane) y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + LANE_HEIGHT / 2;\n } else if (ev.nodeId) {\n const id = String(ev.nodeId);\n const lane = laneById.get(id.startsWith('task:') || id.startsWith('bg:') ? id : `task:${id}`);\n if (lane) y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + LANE_HEIGHT / 2;\n }\n\n out.push({\n id: `${ev.ts}-${ev.kind}-${ev.author ?? ''}-${ev.taskId ?? ''}`,\n x,\n y,\n kind: ev.kind || 'event',\n ts,\n text: String(ev.text || ev.kind || ''),\n author: ev.author as string | undefined,\n });\n }\n return out;\n }, [events, rangeStart, rangeEnd, timeToX, laneById]);\n\n // ─── Lane backgrounds (alternating) ─────────────────────────────────\n const laneRects = useMemo(() => {\n return lanes.map((lane) => ({\n id: lane.id,\n y: TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT,\n h: LANE_HEIGHT,\n }));\n }, [lanes]);\n\n // ─── Now line position ──────────────────────────────────────────────\n const nowX = useMemo(() => {\n const x = timeToX(nowTick);\n return Math.max(0, Math.min(canvasSize.width, x));\n }, [timeToX, nowTick, canvasSize.width]);\n\n // ─── Click on a bar → open detail panel ─────────────────────────────\n const onSelectBar = useCallback((bar: TaskBar) => {\n const id = bar.id; // 'task:xxx' or 'bg:xxx'\n const item: SelectedItem = {\n id,\n kind: bar.kind,\n label: bar.label,\n status: bar.statusClass,\n data: bar.data,\n };\n setSelectedItem(item);\n }, []);\n\n // ─── Detail panel: fetch related data when selection changes ────────\n useEffect(() => {\n if (!selectedItem) {\n setComments([]);\n setBgOutput('');\n setBgArtifactIds([]);\n return;\n }\n setCommentText('');\n setTaskTitle('');\n setBgMessage('');\n setBgArtifactIds([]);\n (async () => {\n try {\n const r = await api.get<{ events: ActivityEvent[] }>(\n `/activity?nodeId=${encodeURIComponent(selectedItem.id)}&limit=50`,\n );\n setComments(r.events || []);\n } catch {\n setComments([]);\n }\n if (selectedItem.kind === 'bg') {\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.get<{ output: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}/output?lines=80`,\n );\n setBgOutput(r.output || '');\n } catch {\n setBgOutput('');\n }\n // v3.6.2 — If the bg instance has a linked taskId, fetch its artifacts.\n if (bgData.taskId) {\n try {\n const artR = await api.get<{ artifacts: { id: string }[] }>(\n `/tasks/${encodeURIComponent(bgData.taskId)}/artifacts`,\n );\n setBgArtifactIds((artR.artifacts || []).map((a) => a.id));\n } catch {\n setBgArtifactIds([]);\n }\n }\n }\n })();\n }, [selectedItem]);\n\n // ─── Detail actions ─────────────────────────────────────────────────\n const onAddComment = async () => {\n if (!selectedItem || !commentText.trim()) return;\n setPostingComment(true);\n try {\n await api.post('/comments', { nodeId: selectedItem.id, text: commentText, author: 'user' });\n setCommentText('');\n const r = await api.get<{ events: ActivityEvent[] }>(\n `/activity?nodeId=${encodeURIComponent(selectedItem.id)}&limit=50`,\n );\n setComments(r.events || []);\n toast.success('Comment added.');\n } catch (err) {\n toast.error(`Comment failed: ${(err as Error).message}`);\n } finally {\n setPostingComment(false);\n }\n };\n\n const onCreateTaskFromNode = async () => {\n if (!selectedItem || !taskTitle.trim()) return;\n setCreatingTask(true);\n try {\n await api.post(`/nodes/${encodeURIComponent(selectedItem.id)}/tasks`, {\n title: taskTitle,\n description: `Created from timeline selection ${selectedItem.id}.`,\n priority: taskPriority,\n });\n setTaskTitle('');\n toast.success('Task created.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Task create failed: ${(err as Error).message}`);\n } finally {\n setCreatingTask(false);\n }\n };\n\n const onSendBgMessage = async () => {\n if (!selectedItem || selectedItem.kind !== 'bg' || !bgMessage.trim()) return;\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.post<{ ok: boolean; error?: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}/message`,\n { message: bgMessage },\n );\n if (r.ok) {\n toast.success('Message sent.');\n setBgMessage('');\n } else {\n toast.warning(r.error || 'Send failed');\n }\n } catch (err) {\n toast.error(`Send failed: ${(err as Error).message}`);\n }\n };\n\n const onKillBg = async () => {\n if (!selectedItem || selectedItem.kind !== 'bg') return;\n if (!confirm('Kill this bg instance session?')) return;\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.del<{ ok: boolean; error?: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}`,\n );\n if (r.ok) toast.success('Session killed.');\n else toast.warning(r.error || 'Kill failed');\n await reloadAll();\n } catch (err) {\n toast.error(`Kill failed: ${(err as Error).message}`);\n }\n };\n\n const refetchOutput = async () => {\n if (!selectedItem || selectedItem.kind !== 'bg') return;\n const bgData = selectedItem.data as BgInstance;\n try {\n const r = await api.get<{ output: string }>(\n `/background/${encodeURIComponent(bgData.instanceId)}/output?lines=80`,\n );\n setBgOutput(r.output || '');\n } catch {\n /* ignore */\n }\n };\n\n // ─── Keyboard helpers ───────────────────────────────────────────────\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setSelectedItem(null);\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, []);\n\n // ─── Refresh handler ────────────────────────────────────────────────\n const refresh = () => {\n setRefreshTick((t) => t + 1);\n reloadAll();\n };\n\n // ─── Derived: total content height (for SVG sizing) ─────────────────\n const contentHeight = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lanes.length * LANE_HEIGHT;\n\n // ─── Render ─────────────────────────────────────────────────────────\n return (\n <div className=\"view view-activity\">\n {/* Top header bar — title + live/pause + zoom + refresh */}\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <ActivityIcon size={18} /> Activity\n </h2>\n <p className=\"view-subtitle\">\n Live timeline of agents, tasks, and background sessions. Active tasks pulse; the red line marks &ldquo;now&rdquo;.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"tl-mode-toggle\">\n <Button\n variant={mode === 'live' ? 'primary' : 'secondary'}\n size=\"sm\"\n onClick={() => setMode(mode === 'live' ? 'pause' : 'live')}\n title={mode === 'live' ? 'Pause timeline' : 'Resume timeline'}\n >\n {mode === 'live' ? <Pause size={14} /> : <Play size={14} />}\n {mode === 'live' ? 'Live' : 'Paused'}\n </Button>\n <div className=\"tl-zoom-group\">\n {(['1m', '5m', '30m', '1h'] as ZoomKey[]).map((z) => (\n <button\n type=\"button\"\n key={z}\n className={cn('tl-zoom-btn', zoom === z && 'tl-zoom-btn-active')}\n onClick={() => setZoom(z)}\n title={`Zoom to ${z}`}\n >\n {z}\n </button>\n ))}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={refresh} title=\"Refresh\">\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n </div>\n </header>\n\n {loading && (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n )}\n\n {!loading && agents.length === 0 && tasks.length === 0 && bgInstances.length === 0 && events.length === 0 ? (\n <EmptyState\n icon={<ActivityIcon size={32} />}\n title=\"No activity yet\"\n message=\"Once agents, tasks, or background instances exist, they'll show up here on the timeline.\"\n />\n ) : (\n <div className={cn('tl-view', selectedItem && 'tl-view-detail-open')}>\n <div className={cn('tl-body', !streamOpen && 'tl-body-stream-collapsed')}>\n {/* Left column — event stream (sibling, not overlay) */}\n <aside className={cn('tl-stream', !streamOpen && 'tl-stream-collapsed')}>\n <div className=\"tl-stream-head\">\n <h3>\n <History size={13} /> Live events\n </h3>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setStreamOpen(false)}\n title=\"Hide event stream\"\n aria-label=\"Hide event stream\"\n >\n <PanelLeftClose size={14} />\n </button>\n </div>\n <div className=\"tl-stream-list\">\n {events.length === 0 ? (\n <div className=\"tl-stream-empty\">\n <p>No events yet.</p>\n </div>\n ) : (\n [...events].reverse().map((ev, i) => {\n const Icon =\n ev.author ? Bot : ev.kind === 'task' ? CheckSquare : ev.kind === 'bg' ? Cpu : ActivityIcon;\n return (\n <div key={`${ev.ts}-${i}`} className=\"tl-stream-event\">\n <span className=\"tl-stream-event-time\">\n {new Date(ev.ts).toLocaleTimeString('en-GB', { hour12: false })}\n </span>\n <span className=\"tl-stream-event-icon\" style={{ color: statusColor(ev.kind) }}>\n <Icon size={12} />\n </span>\n <span className=\"tl-stream-event-text\">\n {ev.author || ev.text || ev.kind}\n </span>\n </div>\n );\n })\n )}\n </div>\n </aside>\n\n {/* Center column — timeline canvas */}\n <div className=\"tl-canvas-wrap\" ref={canvasWrapRef}>\n <div className=\"tl-canvas-toolbar\">\n <div className=\"tl-canvas-toolbar-left\">\n {!streamOpen && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setStreamOpen(true)}\n title=\"Show event stream\"\n >\n <PanelLeftOpen size={14} /> Events\n </Button>\n )}\n <span className=\"tl-canvas-mode\">\n {mode === 'live' ? '● Live' : '⏸ Paused'}\n </span>\n <span className=\"tl-canvas-range\">\n {new Date(rangeStart).toLocaleTimeString('en-GB', { hour12: false })} →{' '}\n {new Date(rangeEnd).toLocaleTimeString('en-GB', { hour12: false })}\n </span>\n </div>\n <div className=\"tl-canvas-legend\">\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot\" style={{ background: 'var(--success)' }} /> active</span>\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot tl-legend-dot-dashed\" style={{ borderColor: 'var(--info)' }} /> queued</span>\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot\" style={{ background: 'var(--warning)' }} /> blocked</span>\n <span className=\"tl-legend-item\"><span className=\"tl-legend-dot\" style={{ background: 'var(--error)' }} /> error</span>\n <span className=\"tl-legend-sep\" />\n <span className=\"tl-legend-item\"><Layers size={11} /> agent</span>\n <span className=\"tl-legend-item\"><Target size={11} /> task</span>\n <span className=\"tl-legend-item\"><Cpu size={11} /> bg</span>\n </div>\n </div>\n\n <div className=\"tl-canvas-scroll\">\n <svg\n className=\"tl-canvas\"\n width={canvasSize.width}\n height={Math.max(canvasSize.height, contentHeight)}\n role=\"application\"\n aria-label=\"Activity timeline\"\n >\n <defs>\n <pattern\n id=\"tl-canvas-grid\"\n width={canvasSize.width}\n height={LANE_HEIGHT}\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n d={`M 0 0 L 0 ${LANE_HEIGHT}`}\n fill=\"none\"\n stroke=\"var(--border)\"\n strokeWidth={0.5}\n opacity={0.35}\n />\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill=\"url(#tl-canvas-grid)\" />\n\n {/* Lane backgrounds (alternating) */}\n {laneRects.map((lr) => (\n <rect\n key={`bg-${lr.id}`}\n className=\"tl-lane-bg\"\n x={0}\n y={lr.y}\n width={canvasSize.width}\n height={lr.h}\n fill={lr.id.charCodeAt(lr.id.length - 1) % 2 === 0 ? 'var(--bg-elev-2)' : 'var(--bg-elev)'}\n opacity={0.4}\n />\n ))}\n\n {/* Time axis tick lines + labels */}\n <g className=\"tl-time-axis\">\n {ticks.map((t) => (\n <g key={`tick-${t.t}`}>\n <line\n x1={t.x}\n y1={0}\n x2={t.x}\n y2={contentHeight}\n stroke=\"var(--border)\"\n strokeWidth={0.5}\n strokeDasharray=\"2,4\"\n opacity={0.5}\n />\n <text\n x={t.x + 4}\n y={TIME_AXIS_HEIGHT - 8}\n fontSize={10}\n fontFamily=\"var(--font-mono)\"\n fill=\"var(--text-dim)\"\n >\n {t.label}\n </text>\n </g>\n ))}\n </g>\n\n {/* Lane labels (rendered inside SVG, x=4) */}\n {lanes.map((lane) => {\n const y = TIME_AXIS_HEIGHT + EVENTS_STRIP_HEIGHT + lane.index * LANE_HEIGHT + LANE_HEIGHT / 2;\n return (\n <g key={`label-${lane.id}`} className=\"tl-lane-label-group\">\n <text\n x={6}\n y={y - 2}\n className=\"tl-lane-label\"\n textAnchor=\"start\"\n >\n {shortLabel(lane.label, 28)}\n </text>\n <text\n x={6}\n y={y + 10}\n className=\"tl-lane-label-sub\"\n textAnchor=\"start\"\n >\n {lane.sub}\n </text>\n </g>\n );\n })}\n\n {/* Task / BG bars */}\n {bars.map((bar) => {\n const fillColor = statusColor(bar.statusClass);\n const isSelected = bar.id === selectedItem?.id;\n return (\n <g\n key={`bar-${bar.id}`}\n className={cn('tl-task-bar', `tl-task-bar-${bar.statusClass}`, isSelected && 'tl-task-bar-selected')}\n onClick={() => onSelectBar(bar)}\n >\n <rect\n x={bar.x}\n y={bar.y}\n width={bar.w}\n height={bar.h}\n rx={6}\n fill={fillColor}\n fillOpacity={bar.statusClass === 'done' ? 0.35 : bar.statusClass === 'queued' ? 0.18 : 0.85}\n stroke={fillColor}\n strokeWidth={isSelected ? 2.5 : 1.5}\n strokeOpacity={bar.statusClass === 'done' ? 0.5 : 1}\n strokeDasharray={bar.statusClass === 'queued' ? '4 4' : undefined}\n style={{ cursor: 'pointer' }}\n />\n {bar.w > 36 && (\n <text\n x={bar.x + 8}\n y={bar.y + bar.h / 2 + 4}\n fontSize={11}\n fontFamily=\"var(--font-sans)\"\n fontWeight={500}\n fill=\"var(--text-strong)\"\n style={{ pointerEvents: 'none' }}\n opacity={bar.statusClass === 'done' ? 0.7 : 1}\n >\n {shortLabel(bar.label, Math.max(4, Math.floor(bar.w / 7)))}\n </text>\n )}\n </g>\n );\n })}\n\n {/* Event markers */}\n {eventMarkers.map((m) => {\n const color = statusColor(m.kind);\n return (\n <g key={`ev-${m.id}`} className=\"tl-event-marker-group\">\n <line\n x1={m.x}\n y1={m.y - 6}\n x2={m.x}\n y2={m.y + 6}\n stroke={color}\n strokeWidth={1.2}\n opacity={0.7}\n />\n <circle\n cx={m.x}\n cy={m.y}\n r={4}\n fill={color}\n opacity={0.9}\n >\n <title>\n {`${m.kind}${m.author ? ` · ${m.author}` : ''} · ${new Date(m.ts).toLocaleTimeString('en-GB', { hour12: false })}`}\n </title>\n </circle>\n </g>\n );\n })}\n\n {/* Now line (red, vertical) */}\n <line\n className=\"tl-now-line\"\n x1={nowX}\n y1={0}\n x2={nowX}\n y2={contentHeight}\n stroke=\"var(--error)\"\n strokeWidth={1.5}\n opacity={0.9}\n />\n <g className=\"tl-now-marker\">\n <circle cx={nowX} cy={TIME_AXIS_HEIGHT - 4} r={4} fill=\"var(--error)\" />\n <text\n x={nowX + 6}\n y={TIME_AXIS_HEIGHT - 4}\n fontSize={10}\n fontWeight={700}\n fill=\"var(--error)\"\n fontFamily=\"var(--font-mono)\"\n >\n now\n </text>\n </g>\n </svg>\n </div>\n </div>\n\n {/* Right column — detail panel */}\n {selectedItem && (\n <aside className=\"tl-detail tl-detail-enter\" key={selectedItem.id}>\n <Card>\n <CardTitle>\n {selectedItem.kind === 'agent' && <Bot size={14} />}\n {selectedItem.kind === 'task' && <CheckSquare size={14} />}\n {selectedItem.kind === 'bg' && <Cpu size={14} />}\n {selectedItem.label}\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setSelectedItem(null)}\n title=\"Close\"\n aria-label=\"Close activity detail\"\n style={{ marginLeft: 'auto' }}\n >\n <X size={14} />\n </button>\n </CardTitle>\n <div className=\"tl-detail-meta\">\n <div><span className=\"muted\">type</span> {selectedItem.kind}</div>\n <div><span className=\"muted\">status</span> <code>{selectedItem.status}</code></div>\n {selectedItem.kind === 'agent' && (() => {\n const a = selectedItem.data as Agent;\n return (\n <>\n {a.role && <div><span className=\"muted\">role</span> {a.role}</div>}\n {a.model && <div><span className=\"muted\">model</span> {a.model}</div>}\n </>\n );\n })()}\n {selectedItem.kind === 'task' && (() => {\n const t = selectedItem.data as Task;\n return (\n <>\n {t.assignee && <div><span className=\"muted\">assignee</span> @{t.assignee}</div>}\n {t.priority && <div><span className=\"muted\">priority</span> {t.priority}</div>}\n {t.createdAt && <div><span className=\"muted\">created</span> {new Date(t.createdAt).toLocaleString()}</div>}\n </>\n );\n })()}\n {selectedItem.kind === 'bg' && (() => {\n const b = selectedItem.data as BgInstance;\n return (\n <>\n {b.startedAt && <div><span className=\"muted\">started</span> {new Date(b.startedAt).toLocaleString()}</div>}\n {b.tmuxSession && <div><span className=\"muted\">tmux</span> <code>{b.tmuxSession}</code> {b.tmuxActive ? <span className=\"tag tag-success\">active</span> : <span className=\"tag\">inactive</span>}</div>}\n </>\n );\n })()}\n </div>\n {selectedItem.kind === 'task' && (selectedItem.data as Task).description && (\n <div className=\"tl-detail-desc\">{(selectedItem.data as Task).description}</div>\n )}\n {selectedItem.kind === 'bg' && (selectedItem.data as BgInstance).promptPreview && (\n <div className=\"tl-detail-desc\">{(selectedItem.data as BgInstance).promptPreview}</div>\n )}\n\n {selectedItem.kind === 'bg' && (\n <div className=\"tl-detail-bg\">\n <pre className=\"tl-bg-output\">{bgOutput || '(no output — start the session via tmux attach)'}</pre>\n <div className=\"tl-bg-output-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={refetchOutput}>\n <RefreshCw size={12} /> Refresh output\n </Button>\n {bgArtifactIds.length > 0 && (\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => openArtifactViewer(modal, bgArtifactIds[0])}\n >\n <FileText size={12} /> Open artifact\n </Button>\n )}\n <Button variant=\"danger\" size=\"sm\" onClick={onKillBg}>\n <Trash2 size={12} /> Kill session\n </Button>\n </div>\n <div className=\"tl-form-row\">\n <input\n className=\"input\"\n placeholder=\"Send a message to this bg session…\"\n value={bgMessage}\n onChange={(e) => setBgMessage(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSendBgMessage();\n }}\n />\n <Button variant=\"primary\" size=\"sm\" disabled={!bgMessage.trim()} onClick={onSendBgMessage}>\n <Send size={12} /> Send\n </Button>\n </div>\n </div>\n )}\n\n {selectedItem.kind !== 'bg' && (\n <div className=\"tl-detail-create\">\n <div className=\"field-label\">Create follow-up task</div>\n <input\n className=\"input\"\n placeholder=\"Task title\"\n value={taskTitle}\n onChange={(e) => setTaskTitle(e.target.value)}\n />\n <div className=\"tl-form-row\">\n <select\n className=\"select\"\n value={taskPriority}\n onChange={(e) => setTaskPriority(e.target.value)}\n >\n <option value=\"low\">Low</option>\n <option value=\"normal\">Normal</option>\n <option value=\"high\">High</option>\n </select>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!taskTitle.trim() || creatingTask}\n onClick={onCreateTaskFromNode}\n >\n <Plus size={12} /> Add task\n </Button>\n </div>\n </div>\n )}\n\n <div className=\"tl-detail-comments\">\n <div className=\"field-label\">\n <MessageSquare size={12} /> Comments &amp; activity\n </div>\n <ul className=\"comment-list\">\n {comments.length === 0 && <li className=\"muted\">No comments yet.</li>}\n {comments.map((c, i) => (\n <li key={`c-${i}`} className=\"comment-item\">\n <div className=\"comment-head\">\n <strong>{c.author || 'system'}</strong>\n <span className=\"muted\">\n {c.kind} · {new Date(c.ts).toLocaleString()}\n </span>\n </div>\n {c.text && <div className=\"comment-text\">{c.text}</div>}\n {c.taskId && (\n <div className=\"muted\">\n → task <code>{String(c.taskId)}</code>\n </div>\n )}\n </li>\n ))}\n </ul>\n <div className=\"comment-input-row\">\n <input\n className=\"input\"\n placeholder=\"Add a comment…\"\n value={commentText}\n onChange={(e) => setCommentText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) onAddComment();\n }}\n />\n <Button\n variant=\"secondary\"\n size=\"sm\"\n disabled={!commentText.trim() || postingComment}\n onClick={onAddComment}\n >\n <Send size={12} /> Post\n </Button>\n </div>\n </div>\n </Card>\n </aside>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n","// src/web/components/HeadroomSettings.tsx\n//\n// v1.0.0 — Headroom settings card for the Settings view.\n// Displays live status and provides controls for install, wrap, proxy, and configuration.\nimport React, { useEffect, useState, useCallback } from 'react';\nimport {\n Activity,\n CheckCircle,\n XCircle,\n Download,\n Play,\n Square,\n RefreshCw,\n ExternalLink,\n Zap,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { type HeadroomSettings } from '../lib/types';\n\ntype HeadroomStatus = {\n installed: boolean;\n version: string | null;\n proxyRunning: boolean;\n proxyPort: number | null;\n proxyPid: number | null;\n wrapped: boolean;\n healthy: 'ok' | 'warn' | 'fail';\n messages: string[];\n};\n\ntype HeadroomStats = {\n tokensSaved?: number;\n compressionRatio?: number;\n cacheHits?: number;\n transforms?: number;\n error?: string;\n};\n\nconst BACKEND_OPTIONS = [\n { value: 'anthropic', label: 'Anthropic' },\n { value: 'anyllm', label: 'AnyLLM' },\n { value: 'litellm-anthropic', label: 'LiteLLM (Anthropic)' },\n { value: 'litellm-openai', label: 'LiteLLM (OpenAI)' },\n];\n\ntype Props = {\n settings: HeadroomSettings;\n onPatch: (patch: Partial<HeadroomSettings>) => void;\n};\n\nexport function HeadroomSettingsCard({ settings, onPatch }: Props) {\n const toast = useToast();\n const [status, setStatus] = useState<HeadroomStatus | null>(null);\n const [stats, setStats] = useState<HeadroomStats | null>(null);\n const [loadingStatus, setLoadingStatus] = useState(false);\n const [installing, setInstalling] = useState(false);\n const [wrapping, setWrapping] = useState(false);\n const [unwrapping, setUnwrapping] = useState(false);\n const [startingProxy, setStartingProxy] = useState(false);\n const [stoppingProxy, setStoppingProxy] = useState(false);\n\n const loadStatus = useCallback(async () => {\n setLoadingStatus(true);\n try {\n const [s, st] = await Promise.all([\n api.get<HeadroomStatus>('/headroom/status'),\n api.get<HeadroomStats>('/headroom/stats?hours=24').catch(() => ({ error: 'no stats' })),\n ]);\n setStatus(s);\n if (!st.error) setStats(st);\n } catch (err) {\n toast.error(`Failed to load Headroom status: ${(err as Error).message}`);\n } finally {\n setLoadingStatus(false);\n }\n }, [toast]);\n\n useEffect(() => {\n loadStatus();\n }, [loadStatus]);\n\n const handleInstall = async () => {\n setInstalling(true);\n try {\n const r = await api.post<{ ok: boolean; installed: boolean; method: string }>('/headroom/install', { force: true });\n if (r.installed) {\n toast.success(`Headroom installed via ${r.method}.`);\n await loadStatus();\n } else {\n toast.error('Headroom install failed. Try: pip install \"headroom-ai[all]\"');\n }\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n } finally {\n setInstalling(false);\n }\n };\n\n const handleWrap = async () => {\n setWrapping(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/wrap', { port: settings.port });\n if (r.ok) {\n toast.success('opencode wrapped with Headroom.');\n await loadStatus();\n } else {\n toast.error('Wrap failed.');\n }\n } catch (err) {\n toast.error(`Wrap failed: ${(err as Error).message}`);\n } finally {\n setWrapping(false);\n }\n };\n\n const handleUnwrap = async () => {\n setUnwrapping(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/unwrap');\n if (r.ok) {\n toast.success('opencode unwrapped from Headroom.');\n await loadStatus();\n } else {\n toast.error('Unwrap failed.');\n }\n } catch (err) {\n toast.error(`Unwrap failed: ${(err as Error).message}`);\n } finally {\n setUnwrapping(false);\n }\n };\n\n const handleStartProxy = async () => {\n setStartingProxy(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/proxy/start', {\n port: settings.port,\n host: settings.host,\n });\n if (r.ok) {\n toast.success(`Headroom proxy started on ${settings.host}:${settings.port}.`);\n await loadStatus();\n } else {\n toast.error('Proxy start failed.');\n }\n } catch (err) {\n toast.error(`Proxy start failed: ${(err as Error).message}`);\n } finally {\n setStartingProxy(false);\n }\n };\n\n const handleStopProxy = async () => {\n setStoppingProxy(true);\n try {\n const r = await api.post<{ ok: boolean }>('/headroom/proxy/stop');\n if (r.ok) {\n toast.success('Headroom proxy stopped.');\n await loadStatus();\n } else {\n toast.error('Proxy stop failed.');\n }\n } catch (err) {\n toast.error(`Proxy stop failed: ${(err as Error).message}`);\n } finally {\n setStoppingProxy(false);\n }\n };\n\n const handleOpenDashboard = async () => {\n try {\n const { spawn } = await import('node:child_process');\n spawn('headroom', ['dashboard'], { detached: true, stdio: 'ignore' });\n } catch {\n toast.error('Could not open Headroom dashboard. Run `headroom dashboard` manually.');\n }\n };\n\n const { installed, version, proxyRunning, proxyPort, wrapped } = status || {};\n const ratio = stats?.compressionRatio ?? 0;\n const saved = stats?.tokensSaved ?? 0;\n\n return (\n <div id=\"settings-headroom\" data-section=\"headroom\">\n <Card>\n <CardTitle>\n <Activity size={14} style={{ color: proxyRunning ? 'var(--success)' : 'var(--text-dim)' }} />\n Headroom\n {installed && version && (\n <span style={{ fontSize: 11, color: 'var(--text-dim)', marginLeft: 6 }}>\n v{version} {proxyRunning ? '✓' : '✗'}\n </span>\n )}\n {!installed && (\n <span style={{ fontSize: 11, color: 'var(--error)', marginLeft: 6 }}>not installed</span>\n )}\n </CardTitle>\n <CardMeta>\n Context compression for token efficiency. Compresses tool outputs, logs, and conversation\n history by 60–95% before they reach the model.\n </CardMeta>\n\n {/* Live status row */}\n <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', marginTop: 12, marginBottom: 12 }}>\n <div className=\"headroom-status-item\">\n {installed ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--error)' }} />\n )}\n <span>{installed ? 'Installed' : 'Not installed'}</span>\n </div>\n <div className=\"headroom-status-item\">\n {proxyRunning ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--text-dim)' }} />\n )}\n <span>Proxy {proxyRunning ? `${proxyPort} ✓` : 'stopped'}</span>\n </div>\n <div className=\"headroom-status-item\">\n {wrapped ? (\n <CheckCircle size={12} style={{ color: 'var(--success)' }} />\n ) : (\n <XCircle size={12} style={{ color: 'var(--text-dim)' }} />\n )}\n <span>opencode {wrapped ? 'wrapped' : 'not wrapped'}</span>\n </div>\n </div>\n\n {/* Stats */}\n {(saved > 0 || ratio > 0) && (\n <div style={{ display: 'flex', gap: 24, marginBottom: 12 }}>\n <div>\n <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--success)' }}>\n {ratio > 0 ? `${Math.round(ratio * 100)}%` : '—'}\n </div>\n <div className=\"muted\" style={{ fontSize: 11 }}>Compression ratio</div>\n </div>\n <div>\n <div style={{ fontSize: 20, fontWeight: 700, color: 'var(--accent)' }}>\n {saved > 0 ? saved.toLocaleString() : '—'}\n </div>\n <div className=\"muted\" style={{ fontSize: 11 }}>Tokens saved (24h)</div>\n </div>\n </div>\n )}\n\n {/* Action buttons */}\n <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', marginBottom: 8 }}>\n {!installed ? (\n <Button variant=\"primary\" size=\"sm\" onClick={handleInstall} disabled={installing}>\n {installing ? <span className=\"btn-spinner\" /> : <Download size={13} />}\n {installing ? 'Installing…' : 'Install Headroom'}\n </Button>\n ) : (\n <>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleWrap}\n disabled={wrapping || wrapped}\n title={wrapped ? 'opencode is already wrapped' : 'Wrap opencode to route through Headroom proxy'}\n >\n {wrapping ? <span className=\"btn-spinner\" /> : <Zap size={13} />}\n {wrapping ? 'Wrapping…' : wrapped ? 'Wrapped ✓' : 'Wrap opencode'}\n </Button>\n {wrapped && (\n <Button variant=\"ghost\" size=\"sm\" onClick={handleUnwrap} disabled={unwrapping}>\n {unwrapping ? <span className=\"btn-spinner\" /> : <RefreshCw size={13} />}\n {unwrapping ? 'Unwrapping…' : 'Unwrap'}\n </Button>\n )}\n </>\n )}\n\n {installed && (\n <>\n {proxyRunning ? (\n <Button variant=\"secondary\" size=\"sm\" onClick={handleStopProxy} disabled={stoppingProxy}>\n {stoppingProxy ? <span className=\"btn-spinner\" /> : <Square size={13} />}\n {stoppingProxy ? 'Stopping…' : 'Stop proxy'}\n </Button>\n ) : (\n <Button variant=\"secondary\" size=\"sm\" onClick={handleStartProxy} disabled={startingProxy}>\n {startingProxy ? <span className=\"btn-spinner\" /> : <Play size={13} />}\n {startingProxy ? 'Starting…' : 'Start proxy'}\n </Button>\n )}\n <Button variant=\"ghost\" size=\"sm\" onClick={handleOpenDashboard}>\n <ExternalLink size={13} />\n Dashboard\n </Button>\n </>\n )}\n\n <Button variant=\"ghost\" size=\"sm\" onClick={loadStatus} disabled={loadingStatus}>\n <RefreshCw size={13} className={loadingStatus ? 'spin' : ''} />\n </Button>\n </div>\n\n {/* Settings */}\n <div style={{ marginTop: 16 }}>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.enabled}\n onChange={(e) => onPatch({ enabled: e.target.checked })}\n />\n <span>Enable Headroom</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoInstall}\n onChange={(e) => onPatch({ autoInstall: e.target.checked })}\n />\n <span>Auto-install if missing on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoStart}\n onChange={(e) => onPatch({ autoStart: e.target.checked })}\n />\n <span>Auto-start proxy on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.autoWrap}\n onChange={(e) => onPatch({ autoWrap: e.target.checked })}\n />\n <span>Auto-wrap opencode on dashboard startup</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.routeAllProviders}\n onChange={(e) => onPatch({ routeAllProviders: e.target.checked })}\n />\n <span>Route all providers through Headroom proxy</span>\n </label>\n\n <div className=\"task-form-row\" style={{ marginTop: 12 }}>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Proxy port</label>\n <input\n type=\"number\"\n className=\"input\"\n value={settings.port}\n min={1}\n max={65535}\n onChange={(e) => onPatch({ port: Math.max(1, Math.min(65535, parseInt(e.target.value, 10) || 8787)) })}\n />\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Proxy host</label>\n <input\n type=\"text\"\n className=\"input\"\n value={settings.host}\n onChange={(e) => onPatch({ host: e.target.value })}\n />\n </div>\n </div>\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Backend</label>\n <select\n className=\"select\"\n value={settings.backend}\n onChange={(e) => onPatch({ backend: e.target.value })}\n >\n {BACKEND_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>{o.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Monthly budget (USD)</label>\n <input\n type=\"number\"\n className=\"input\"\n value={settings.budget}\n min={0}\n step={1}\n onChange={(e) => onPatch({ budget: Math.max(0, parseFloat(e.target.value) || 0) })}\n />\n <span className=\"field-help\">0 = unlimited</span>\n </div>\n </div>\n\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.outputShaper}\n onChange={(e) => onPatch({ outputShaper: e.target.checked })}\n />\n <span>Enable output shaper</span>\n </label>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={settings.telemetry}\n onChange={(e) => onPatch({ telemetry: e.target.checked })}\n />\n <span>Enable telemetry</span>\n </label>\n </div>\n </Card>\n </div>\n );\n}\n","// src/views/Settings.tsx — v3 settings: theme colors, UI layout, defaults, Tailscale, service.\nimport React, { useEffect, useState, useCallback } from 'react';\nimport {\n Sliders,\n Save,\n RefreshCw,\n Sun,\n Moon,\n Monitor,\n Info,\n Globe,\n Palette,\n Layout as LayoutIcon,\n Server as ServerIcon,\n RotateCcw,\n Plug,\n Download,\n AlertTriangle,\n QrCode,\n Smartphone,\n CheckCircle,\n AlertCircle,\n Shield,\n Copy,\n KeyRound,\n Activity,\n EyeOff,\n Eye,\n Trash2,\n Search,\n Sparkles,\n} from 'lucide-react';\nimport { QRCodeSVG } from 'qrcode.react';\nimport { Button } from '../components/Button';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport { HeadroomSettingsCard } from '../components/HeadroomSettings';\nimport { Ws } from '../lib/ws';\nimport {\n applyTheme,\n applyThemeTokens,\n type Settings,\n type SettingsResponse,\n type Snapshot,\n type ThemeName,\n type TailscaleStatus,\n} from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst THEMES: { id: ThemeName; label: string; Icon: typeof Sun }[] = [\n { id: 'dark', label: 'Dark', Icon: Moon },\n { id: 'light', label: 'Light', Icon: Sun },\n { id: 'system', label: 'System', Icon: Monitor },\n];\n\n// v3.3.1 — One-click accent color presets.\nconst PRESET_THEMES = [\n { name: 'Purple', accent: '#8b5cf6' },\n { name: 'Blue', accent: '#3b82f6' },\n { name: 'Green', accent: '#10b981' },\n { name: 'Orange', accent: '#f97316' },\n { name: 'Red', accent: '#ef4444' },\n { name: 'Pink', accent: '#ec4899' },\n { name: 'Cyan', accent: '#06b6d4' },\n { name: 'Mono', accent: '#6b7280' },\n];\n\n// v5.0.0 — Headroom default settings\nconst DEFAULT_HEADROOM_SETTINGS = {\n enabled: true,\n autoInstall: true,\n port: 8787,\n host: '127.0.0.1',\n outputShaper: false,\n telemetry: false,\n budget: 0,\n backend: 'anthropic',\n autoStart: true,\n autoWrap: true,\n routeAllProviders: true,\n};\n\nconst FONT_FAMILIES = [\n 'Inter',\n 'system-ui',\n 'Segoe UI',\n 'Roboto',\n 'JetBrains Mono',\n 'SF Mono',\n 'Cascadia Code',\n];\n\n// v3.5.2 — Pair-with-mobile companion card.\ntype PairSession = {\n token: string;\n qrPayload: string;\n publicUrl: string;\n expiresAt: number;\n};\n\nfunction formatCountdown(ms: number): string {\n if (ms <= 0) return 'expired';\n const s = Math.floor(ms / 1000);\n const m = Math.floor(s / 60);\n const r = s % 60;\n return `${m}:${String(r).padStart(2, '0')}`;\n}\n\nfunction PairDeviceCard() {\n const toast = useToast();\n const [pair, setPair] = useState<PairSession | null>(null);\n const [pairing, setPairing] = useState(false);\n const [pairError, setPairError] = useState<string | null>(null);\n const [now, setNow] = useState(Date.now());\n\n const start = useCallback(async () => {\n setPairing(true);\n setPairError(null);\n try {\n const res = await api.post<PairSession>('/pair/start');\n setPair(res);\n } catch (err) {\n setPairError((err as Error)?.message || 'Failed to start pairing');\n toast.error('Pairing failed.');\n } finally {\n setPairing(false);\n }\n }, [toast]);\n\n useEffect(() => {\n if (!pair) return;\n const t = setInterval(() => setNow(Date.now()), 1000);\n return () => clearInterval(t);\n }, [pair]);\n\n const remaining = pair ? pair.expiresAt - now : 0;\n const expired = pair != null && remaining <= 0;\n\n return (\n <Card id=\"settings-updates\" data-section=\"updates\">\n <CardTitle>\n <Smartphone size={14} /> Companion App\n </CardTitle>\n <CardMeta>\n Scan the QR with <a href=\"https://github.com/DrB0rk/BizarHarness\" target=\"_blank\" rel=\"noopener noreferrer\">Bizar Companion</a> to pair.\n Tokens expire after 5 minutes.\n </CardMeta>\n\n <div style={{ display: 'flex', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>\n <div style={{ flex: '0 0 auto' }}>\n {pair && !expired ? (\n <div style={{ background: '#fff', padding: 12, borderRadius: 12 }}>\n <QRCodeSVG value={pair.qrPayload} size={192} level=\"M\" includeMargin={false} />\n </div>\n ) : (\n <div\n style={{\n width: 216,\n height: 216,\n borderRadius: 12,\n background: 'var(--surface-2, #161b22)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'var(--text-muted, #8b949e)',\n fontSize: 12,\n textAlign: 'center',\n padding: 16,\n border: '1px dashed var(--border, #30363d)',\n }}\n >\n {pair && expired ? 'QR expired' : 'No QR generated yet'}\n </div>\n )}\n </div>\n\n <div style={{ flex: '1 1 240px', minWidth: 220 }}>\n {!pair && (\n <Button variant=\"primary\" onClick={start} disabled={pairing}>\n <QrCode size={14} /> {pairing ? 'Generating…' : 'Generate QR Code'}\n </Button>\n )}\n\n {pair && !expired && (\n <>\n <div style={{ marginBottom: 10 }}>\n <strong>Expires in</strong> <span className=\"mono\">{formatCountdown(remaining)}</span>\n </div>\n <div style={{ marginBottom: 6 }}>\n <strong>URL:</strong> <span className=\"mono\" style={{ wordBreak: 'break-all' }}>{pair.publicUrl}</span>\n </div>\n <div style={{ marginBottom: 12 }}>\n <strong>Token:</strong>{' '}\n <span className=\"mono\" style={{ wordBreak: 'break-all', fontSize: 12 }}>\n {pair.token.slice(0, 16)}…{pair.token.slice(-6)}\n </span>\n </div>\n <Button variant=\"secondary\" onClick={start} disabled={pairing}>\n <RefreshCw size={14} /> Regenerate\n </Button>\n </>\n )}\n\n {pair && expired && (\n <>\n <div style={{ marginBottom: 12, color: 'var(--error, #f85149)' }}>\n Token expired — generate a fresh QR to pair again.\n </div>\n <Button variant=\"primary\" onClick={() => { setPair(null); start(); }}>\n <RefreshCw size={14} /> Generate new QR\n </Button>\n </>\n )}\n\n {pairError && (\n <div style={{ marginTop: 10, color: 'var(--error, #f85149)', fontSize: 12 }}>\n {pairError}\n </div>\n )}\n </div>\n </div>\n </Card>\n );\n}\n\nconst LAYOUTS = [\n { id: 'topnav', label: 'Top nav' },\n { id: 'sidebar', label: 'Sidebar' },\n { id: 'both', label: 'Both' },\n] as const;\n\n// v3.5.3 — Updates card with per-package selection, live progress, and auto-restart\ntype PkgStatus = {\n status: 'idle' | 'starting' | 'installing' | 'done' | 'error';\n error?: string;\n newVersion?: string;\n logs: string[];\n};\n\nfunction UpdatesCard() {\n const toast = useToast();\n const [status, setStatus] = useState<{\n current: Record<string, string | null>;\n latest: Record<string, string | null> | null;\n checking: boolean;\n updating: boolean;\n hasUpdates: boolean;\n requiresRestart: boolean;\n perPackage: Record<string, PkgStatus>;\n error?: string;\n }>({\n current: {},\n latest: null,\n checking: false,\n updating: false,\n hasUpdates: false,\n requiresRestart: false,\n perPackage: {},\n });\n\n // WebSocket subscription for live update progress (auto-reconnect via Ws class)\n useEffect(() => {\n const ws = new Ws();\n ws.on((msg: Record<string, unknown>) => {\n if (msg.type === 'update:progress' || msg.type === 'update:log' || msg.type === 'update:complete') {\n setStatus((s) => {\n if (msg.type === 'update:complete') {\n return {\n ...s,\n updating: false,\n requiresRestart: Boolean((msg as { requiresRestart?: boolean }).requiresRestart),\n };\n }\n if (msg.type === 'update:log') {\n const m = msg as { pkg: string; line: string };\n const existing = s.perPackage[m.pkg] || { logs: [] };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...existing,\n logs: [...(existing.logs || []).slice(-50), m.line],\n },\n },\n };\n }\n // update:progress\n const m = msg as { pkg: string; status: PkgStatus['status']; error?: string; newVersion?: string };\n return {\n ...s,\n perPackage: {\n ...s.perPackage,\n [m.pkg]: {\n ...s.perPackage[m.pkg],\n status: m.status,\n error: m.error,\n newVersion: m.newVersion,\n },\n },\n };\n });\n }\n });\n return () => ws.close();\n }, []);\n\n // Load current versions on mount\n useEffect(() => {\n api.get<{ current: Record<string, string | null> }>('/updates/status')\n .then((r) => setStatus((s) => ({ ...s, current: r.current })))\n .catch((e) => setStatus((s) => ({ ...s, error: e.message })));\n }, []);\n\n const check = async () => {\n setStatus((s) => ({ ...s, checking: true, error: undefined }));\n try {\n const r = await api.get<{\n current: Record<string, string | null>;\n latest: Record<string, string | null>;\n hasUpdates: boolean;\n }>('/updates/check');\n setStatus((s) => ({\n ...s,\n checking: false,\n current: r.current,\n latest: r.latest,\n hasUpdates: r.hasUpdates,\n }));\n } catch (err) {\n setStatus((s) => ({ ...s, checking: false, error: (err as Error).message }));\n }\n };\n\n const applyUpdate = async () => {\n if (!confirm('Update Bizar packages? The dashboard will restart automatically.')) return;\n setStatus((s) => ({\n ...s,\n updating: true,\n requiresRestart: false,\n perPackage: {},\n error: undefined,\n }));\n try {\n await api.post('/updates/apply', { packages: ['bizar', 'bizar-dash', 'bizar-plugin'] });\n // Progress streams via WebSocket\n } catch (err) {\n setStatus((s) => ({ ...s, updating: false, error: (err as Error).message }));\n }\n };\n\n const restart = async () => {\n if (!confirm('Restart the dashboard? You will be disconnected briefly.')) return;\n try {\n await api.post('/restart');\n toast.info('Restarting…', 3000);\n setTimeout(() => window.location.reload(), 3000);\n } catch {\n toast.error('Restart failed');\n }\n };\n\n const packages = [\n { id: 'bizar', name: 'Bizar CLI' },\n { id: 'bizar-dash', name: 'Dashboard' },\n { id: 'bizar-plugin', name: 'Opencode Plugin' },\n ];\n\n const isBusy = status.checking || status.updating;\n\n return (\n <Card id=\"settings-updates\" data-section=\"updates\">\n <CardTitle><Download size={14} /> Updates</CardTitle>\n <CardMeta>Check installed Bizar packages and apply dashboard updates.</CardMeta>\n {/* Current versions */}\n <div className=\"updates-current\">\n <h4>Installed versions</h4>\n <ul>\n {packages.map((p) => (\n <li key={p.id}>\n <span>{p.name}</span>\n <code className=\"mono\">{status.current[p.id] || '—'}</code>\n </li>\n ))}\n </ul>\n </div>\n\n {/* Latest + per-package status */}\n {status.latest && (\n <div className=\"updates-latest\">\n <h4>Latest available</h4>\n <ul>\n {packages.map((p) => {\n const cur = status.current[p.id];\n const lat = status.latest?.[p.id];\n const isOutdated = cur && lat && cur !== lat;\n return (\n <li key={p.id} className={isOutdated ? 'updates-outdated' : 'updates-current-version'}>\n <span>{p.name}</span>\n <code className=\"mono\">\n {lat || '—'}\n {isOutdated && <span className=\"updates-badge\">update available</span>}\n </code>\n </li>\n );\n })}\n </ul>\n </div>\n )}\n\n {/* Per-package progress rows (shown while updating) */}\n {status.updating && (\n <div className=\"updates-progress-rows\">\n {packages.map((p) => {\n const pkgStatus = status.perPackage[p.id] || { status: 'idle', logs: [] as string[] };\n return (\n <div key={p.id} className=\"updates-pkg-row\">\n <div className=\"updates-pkg-row-header\">\n <span className=\"updates-pkg-name\">{p.name}</span>\n <div className=\"updates-pkg-status\">\n {pkgStatus.status === 'starting' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'installing' && <span className=\"btn-spinner\" />}\n {pkgStatus.status === 'done' && <CheckCircle size={14} className=\"icon-success\" />}\n {pkgStatus.status === 'error' && <AlertCircle size={14} className=\"icon-error\" />}\n <span>{pkgStatus.status}</span>\n {pkgStatus.newVersion && (\n <code className=\"mono\" style={{ fontSize: 11 }}>→ {pkgStatus.newVersion}</code>\n )}\n </div>\n </div>\n {pkgStatus.logs.length > 0 && (\n <details className=\"updates-pkg-logs\">\n <summary>npm output ({pkgStatus.logs.length} lines)</summary>\n <pre>{pkgStatus.logs.join('\\n')}</pre>\n </details>\n )}\n {pkgStatus.status === 'error' && pkgStatus.error && (\n <div className=\"updates-pkg-error\">\n <AlertTriangle size={12} /> {pkgStatus.error}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"updates-actions\">\n <Button onClick={check} disabled={isBusy}>\n {status.checking ? <span className=\"btn-spinner\" /> : <RefreshCw size={14} />}\n Check for updates\n </Button>\n <Button\n variant=\"primary\"\n onClick={applyUpdate}\n disabled={!status.hasUpdates || status.updating}\n >\n {status.updating ? <span className=\"btn-spinner\" /> : <Download size={14} />}\n {status.updating ? 'Updating…' : (status.hasUpdates ? 'Update now' : 'Up to date')}\n </Button>\n {status.requiresRestart && (\n <Button variant=\"danger\" onClick={restart}>\n <RefreshCw size={14} /> Restart Dashboard\n </Button>\n )}\n </div>\n\n {status.error && (\n <div className=\"updates-error\">\n <AlertTriangle size={14} />\n <span>{status.error}</span>\n </div>\n )}\n </Card>\n );\n}\n\nfunction SettingsViewInner({ settings: initial, refreshSnapshot }: Props) {\n const toast = useToast();\n const [settings, setSettings] = useState<Settings>(initial);\n const [dirty, setDirty] = useState(false);\n const [saving, setSaving] = useState(false);\n const [tailscale, setTailscale] = useState<TailscaleStatus | null>(null);\n const [tailscaleDraft, setTailscaleDraft] = useState({ port: 4321, https: true, hostname: '' });\n const [pluginOptions, setPluginOptions] = useState<Record<string, number>>({});\n\n useEffect(() => {\n setSettings(initial);\n setDirty(false);\n if (initial.theme) applyThemeTokens(initial.theme);\n }, [initial]);\n\n useEffect(() => {\n if (!tailscale) return;\n setTailscaleDraft({\n port: tailscale.settings.port,\n https: tailscale.settings.https !== false,\n hostname: tailscale.settings.hostname || '',\n });\n }, [tailscale]);\n\n useEffect(() => {\n api.get<TailscaleStatus>('/tailscale/status').then(setTailscale).catch(() => undefined);\n }, []);\n\n useEffect(() => {\n api.get<Record<string, number>>('/settings/plugin-options')\n .then(setPluginOptions)\n .catch(() => { /* not persisted yet — use defaults */ });\n }, []);\n\n const patchTheme = (patch: Partial<Settings['theme']>) => {\n setSettings((cur) => {\n const next = { ...cur, theme: { ...cur.theme, ...patch } };\n applyThemeTokens(next.theme);\n return next;\n });\n setDirty(true);\n };\n\n const patchUi = (patch: Partial<Settings['ui']>) => {\n setSettings((cur) => ({ ...cur, ui: { ...cur.ui, ...patch } }));\n setDirty(true);\n };\n\n const patchTop = <K extends keyof Settings>(key: K, value: Settings[K]) => {\n setSettings((cur) => ({ ...cur, [key]: value }));\n setDirty(true);\n };\n\n const patchNotifications = (patch: Partial<Settings['notifications']>) => {\n setSettings((cur) => ({ ...cur, notifications: { ...cur.notifications, ...patch } }));\n setDirty(true);\n };\n\n const patchAgents = (patch: Partial<Settings['agents']>) => {\n setSettings((cur) => ({ ...cur, agents: { ...cur.agents, ...patch } }));\n setDirty(true);\n };\n\n // v3.17.0 — Settings subnav as a filter (not just scroll-to).\n // Clicking a subnav button shows ONLY that section; clicking \"All\"\n // restores the full layout. Anchors still work for deep-links but\n // the visible content is filtered, not just scrolled.\n //\n // v3.18.0 — IDs use the section NAME (not the `settings-X` element id)\n // because the inline-style wrap compares against the section name, not\n // the prefixed DOM id.\n const SECTION_LINKS: Array<{ id: string; label: string }> = [\n { id: 'theme', label: 'Theme' },\n { id: 'layout', label: 'Layout' },\n { id: 'general', label: 'General' },\n { id: 'service', label: 'Service' },\n { id: 'tailscale', label: 'Tailscale' },\n { id: 'notifications', label: 'Notifications' },\n { id: 'auth', label: 'Auth' },\n { id: 'agents', label: 'Agents' },\n { id: 'dashboard', label: 'Dashboard' },\n { id: 'background', label: 'Background' },\n { id: 'system-llm', label: 'System LLM' },\n { id: 'headroom', label: 'Headroom' },\n { id: 'updates', label: 'Updates' },\n { id: 'activity-log', label: 'Activity' },\n { id: 'about', label: 'About' },\n ];\n const [activeSection, setActiveSection] = useState<string | null>(() => {\n // Honour #settings-... deep-link on initial mount, otherwise null = All.\n if (typeof window === 'undefined') return null;\n const hash = window.location.hash.replace(/^#settings-/, '');\n return SECTION_LINKS.some((s) => s.id === hash) ? hash : null;\n });\n const onJumpSection = (id: string | null) => {\n setActiveSection(id);\n try {\n const url = id ? `#settings-${id}` : window.location.pathname;\n history.replaceState(null, '', url);\n if (id) {\n const el = document.getElementById(`settings-${id}`);\n if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });\n } else {\n window.scrollTo({ top: 0, behavior: 'smooth' });\n }\n } catch { /* ignore */ }\n };\n // The user picks a section via the subnav; their choice is respected.\n // (v3.18.0 — Removed auto-scroll-based detection; with the inline-style\n // filter approach, hidden sections still report bounding rects, so the\n // detector would race the user's explicit selection and switch tabs back.)\n\n const patchDashboard = (patch: Partial<Settings['dashboard']>) => {\n setSettings((cur) => ({ ...cur, dashboard: { ...cur.dashboard, ...patch } }));\n setDirty(true);\n };\n\n const onSave = async () => {\n setSaving(true);\n try {\n const r = await api.put<SettingsResponse>('/settings', settings);\n setSettings(r.data);\n setDirty(false);\n applyTheme(r.data.theme);\n applyThemeTokens(r.data.theme);\n toast.success('Settings saved.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const onReload = async () => {\n try {\n const r = await api.get<SettingsResponse>('/settings');\n setSettings(r.data);\n setDirty(false);\n applyTheme(r.data.theme);\n applyThemeTokens(r.data.theme);\n toast.info('Settings reloaded.', 1500);\n } catch (err) {\n toast.error(`Reload failed: ${(err as Error).message}`);\n }\n };\n\n const onReset = async () => {\n if (!confirm('Reset all settings to defaults?')) return;\n try {\n const r = await api.post<SettingsResponse>('/settings/reset');\n setSettings(r.data);\n setDirty(false);\n applyTheme(r.data.theme);\n applyThemeTokens(r.data.theme);\n toast.success('Settings reset.');\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Reset failed: ${(err as Error).message}`);\n }\n };\n\n const onTailscaleToggle = async () => {\n try {\n if (tailscale?.settings.enabled) {\n await api.post('/tailscale/disable');\n toast.success('Tailscale serve disabled.');\n } else {\n await api.post('/tailscale/enable', {\n port: tailscaleDraft.port || 4321,\n https: tailscaleDraft.https,\n hostname: tailscaleDraft.hostname || '',\n });\n toast.success('Tailscale serve enabled.');\n }\n const r = await api.get<TailscaleStatus>('/tailscale/status');\n setTailscale(r);\n } catch (err) {\n toast.error(`Tailscale failed: ${(err as Error).message}`);\n }\n };\n\n const about = settings.about || {\n version: '3.0.4',\n homepage: 'https://github.com/DrB0rk/BizarHarness',\n license: 'MIT',\n };\n\n // v3.6.0 — Auth token UI state. The Settings tab is the only place\n // the operator can read the token back out. We default the input\n // to whatever's already in localStorage so a page reload doesn't\n // wipe the entry.\n const [authToken, setAuthToken] = useState<string>(api.getToken());\n const [authStatus, setAuthStatus] = useState<{ required: boolean; loopback: boolean; peer: string } | null>(null);\n const [revealedToken, setRevealedToken] = useState<string>('');\n\n // Probe the server once on mount so we can show \"auth required\" vs\n // \"auth off\" in the UI. If /api/auth/status itself 401s, the token\n // we're using is bad — surface that distinctly.\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.probeAuthStatus();\n if (!cancelled) setAuthStatus(r);\n } catch {\n if (!cancelled) {\n setAuthStatus({ required: true, loopback: false, peer: '' });\n // Don't toast — the toast spam would be annoying on every\n // Settings tab open. The Copy/Regenerate buttons themselves\n // surface the real error if it happens there.\n }\n }\n })();\n return () => { cancelled = true; };\n }, []);\n\n const onCopyToken = async () => {\n try {\n const r = await api.get<{ token: string }>('/auth/reveal');\n setRevealedToken(r.token);\n setAuthToken(r.token);\n api.setToken(r.token);\n try {\n await navigator.clipboard.writeText(r.token);\n toast.success('Token copied to clipboard.');\n } catch {\n toast.success('Token revealed — copy from the field below.');\n }\n } catch (err) {\n toast.error(`Reveal failed: ${(err as Error).message}`);\n }\n };\n\n const onRegenerateToken = async () => {\n if (!confirm('Regenerate the auth token? Anything still using the old token will start getting 401 errors immediately.')) {\n return;\n }\n try {\n const r = await api.post<{ token: string }>('/auth/regenerate');\n setRevealedToken(r.token);\n setAuthToken(r.token);\n api.setToken(r.token);\n try {\n await navigator.clipboard.writeText(r.token);\n toast.success('New token generated and copied to clipboard.');\n } catch {\n toast.success('New token generated — copy from the field below. Old token is now invalid.');\n }\n } catch (err) {\n toast.error(`Regenerate failed: ${(err as Error).message}`);\n }\n };\n\n const onSaveToken = () => {\n api.setToken(authToken.trim());\n toast.success('Token saved. The dashboard will use it on the next request.');\n };\n\n return (\n <div className=\"view view-settings\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Sliders size={18} /> Settings\n </h2>\n <p className=\"view-subtitle\">\n Personal preferences. Changes are saved to{' '}\n <code>~/.config/bizar/settings.json</code>.\n </p>\n </div>\n <div className=\"view-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onReset}>\n <RotateCcw size={14} /> Reset\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onReload}>\n <RefreshCw size={14} /> Reload\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={!dirty || saving}\n onClick={onSave}\n >\n {saving ? <span className=\"btn-spinner\" /> : <Save size={14} />}\n {saving ? 'Saving…' : 'Save'}\n </Button>\n </div>\n </header>\n\n <nav className=\"settings-subnav\" aria-label=\"Settings sections\">\n <button\n type=\"button\"\n className={cn('settings-subnav-button', 'settings-subnav-button-all', activeSection === null && 'settings-subnav-button-active')}\n onClick={() => onJumpSection(null)}\n title=\"Show all settings sections\"\n >\n All\n </button>\n {SECTION_LINKS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n className={cn('settings-subnav-button', activeSection === s.id && 'settings-subnav-button-active')}\n onClick={() => onJumpSection(s.id)}\n >\n {s.label}\n </button>\n ))}\n </nav>\n\n <div\n className={cn('settings-grid', activeSection && 'settings-grid-filtered')}\n data-active-section={activeSection || undefined}\n >\n {/* When a section is active, render a banner above the grid so\n the user knows they're seeing a filtered view. */}\n {activeSection && (\n <div className=\"settings-filter-banner\">\n <span>\n Showing only <strong>{SECTION_LINKS.find((s) => s.id === activeSection)?.label}</strong>.\n </span>\n <button\n type=\"button\"\n className=\"settings-filter-clear\"\n onClick={() => onJumpSection(null)}\n >\n Show all sections\n </button>\n </div>\n )}\n <div data-section=\"theme\" style={{display: (activeSection === null || activeSection === 'theme') ? 'block' : 'none'}}>\n<Card id=\"settings-theme\" data-section=\"theme\">\n <CardTitle><Palette size={14} /> Theme</CardTitle>\n <CardMeta>Mode, accent, and colors. Live preview as you tweak.</CardMeta>\n\n {/* v3.3.1 — Accent color presets */}\n <div className=\"field\" data-setting-id=\"theme.presets\">\n <label className=\"field-label\">Accent presets</label>\n <div className=\"theme-presets\">\n {PRESET_THEMES.map((t) => (\n <button\n key={t.name}\n type=\"button\"\n className={cn(\n 'theme-preset',\n settings.theme.accent === t.accent && 'theme-preset-active',\n )}\n onClick={() => patchTheme({ accent: t.accent })}\n title={t.name}\n >\n <span\n className=\"theme-preset-swatch\"\n style={{ background: t.accent }}\n />\n <span className=\"theme-preset-name\">{t.name}</span>\n </button>\n ))}\n </div>\n </div>\n\n <div className=\"field\" data-setting-id=\"theme.mode\">\n <label className=\"field-label\">Mode</label>\n <div className=\"theme-row\">\n {THEMES.map(({ id, label, Icon }) => {\n const active = settings.theme.mode === id;\n return (\n <button\n key={id}\n type=\"button\"\n className={cn('theme-card', active && 'theme-card-active')}\n onClick={() => patchTheme({ mode: id })}\n >\n <Icon size={16} />\n <span className=\"theme-card-label\">{label}</span>\n <span\n className={cn(\n 'theme-card-swatch',\n `theme-card-swatch-${id}`,\n )}\n />\n </button>\n );\n })}\n </div>\n </div>\n\n <div className=\"theme-colors\">\n <div className=\"field\" data-setting-id=\"theme.accent\">\n <label className=\"field-label\">Accent</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.accent}\n onChange={(e) => patchTheme({ accent: e.target.value })}\n aria-label=\"Accent color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.accent}\n onChange={(e) => patchTheme({ accent: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.success\">\n <label className=\"field-label\">Success</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.success}\n onChange={(e) => patchTheme({ success: e.target.value })}\n aria-label=\"Success color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.success}\n onChange={(e) => patchTheme({ success: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.warning\">\n <label className=\"field-label\">Warning</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.warning}\n onChange={(e) => patchTheme({ warning: e.target.value })}\n aria-label=\"Warning color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.warning}\n onChange={(e) => patchTheme({ warning: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.error\">\n <label className=\"field-label\">Error</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.error}\n onChange={(e) => patchTheme({ error: e.target.value })}\n aria-label=\"Error color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.error}\n onChange={(e) => patchTheme({ error: e.target.value })}\n />\n </div>\n </div>\n <div className=\"field\" data-setting-id=\"theme.info\">\n <label className=\"field-label\">Info</label>\n <div className=\"color-row\">\n <input\n type=\"color\"\n className=\"input color-input\"\n value={settings.theme.info}\n onChange={(e) => patchTheme({ info: e.target.value })}\n aria-label=\"Info color\"\n />\n <input\n type=\"text\"\n className=\"input\"\n value={settings.theme.info}\n onChange={(e) => patchTheme({ info: e.target.value })}\n />\n </div>\n </div>\n </div>\n\n <div className=\"field\" data-setting-id=\"theme.fontFamily\">\n <label className=\"field-label\">Font family</label>\n <select\n className=\"select\"\n value={settings.theme.fontFamily}\n onChange={(e) => patchTheme({ fontFamily: e.target.value })}\n >\n {FONT_FAMILIES.map((f) => (\n <option key={f} value={f}>{f}</option>\n ))}\n </select>\n </div>\n <div className=\"field\" data-setting-id=\"theme.fontSize\">\n <label className=\"field-label\">Font size: {settings.theme.fontSize}px</label>\n <input\n type=\"range\"\n min={12}\n max={20}\n value={settings.theme.fontSize}\n onChange={(e) => patchTheme({ fontSize: Number(e.target.value) })}\n />\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"theme.compactMode\">\n <input\n type=\"checkbox\"\n checked={settings.theme.compactMode}\n onChange={(e) => patchTheme({ compactMode: e.target.checked })}\n />\n <span>Compact mode (denser UI)</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"theme.animations\">\n <input\n type=\"checkbox\"\n checked={settings.theme.animations}\n onChange={(e) => patchTheme({ animations: e.target.checked })}\n />\n <span>Enable animations</span>\n </label>\n </Card>\n</div>\n\n <div data-section=\"updates\" style={{display: (activeSection === null || activeSection === 'updates') ? 'block' : 'none'}}>\n <UpdatesCard />\n </div>\n\n <div data-section=\"layout\" style={{display: (activeSection === null || activeSection === 'layout') ? 'block' : 'none'}}>\n<Card id=\"settings-layout\" data-section=\"layout\">\n <CardTitle><LayoutIcon size={14} /> UI layout</CardTitle>\n <CardMeta>Choose how the dashboard's navigation is presented.</CardMeta>\n <div className=\"layout-row\" data-setting-id=\"ui.layout\">\n {LAYOUTS.map((l) => (\n <button\n key={l.id}\n type=\"button\"\n className={cn('layout-card', settings.ui.layout === l.id && 'layout-card-active')}\n onClick={() => patchUi({ layout: l.id })}\n >\n <span className=\"layout-card-label\">{l.label}</span>\n </button>\n ))}\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showHeader\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showHeader}\n onChange={(e) => patchUi({ showHeader: e.target.checked })}\n />\n <span>Show header</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"ui.showStatusBar\">\n <input\n type=\"checkbox\"\n checked={settings.ui.showStatusBar}\n onChange={(e) => patchUi({ showStatusBar: e.target.checked })}\n />\n <span>Show status bar</span>\n </label>\n <div className=\"field\" data-setting-id=\"ui.defaultTab\">\n <label className=\"field-label\">Default tab</label>\n <select\n className=\"select\"\n value={settings.ui.defaultTab}\n onChange={(e) => patchUi({ defaultTab: e.target.value })}\n >\n <option value=\"overview\">Overview</option>\n <option value=\"chat\">Chat</option>\n <option value=\"agents\">Agents</option>\n <option value=\"artifacts\">Plans</option>\n <option value=\"projects\">Projects</option>\n <option value=\"tasks\">Tasks</option>\n <option value=\"config\">Config</option>\n <option value=\"settings\">Settings</option>\n <option value=\"mods\">Mods</option>\n <option value=\"schedules\">Schedules</option>\n </select>\n </div>\n </Card>\n</div>\n\n <div data-section=\"general\" style={{display: (activeSection === null || activeSection === 'general') ? 'block' : 'none'}}>\n<Card id=\"settings-general\" data-section=\"general\">\n <CardTitle>General</CardTitle>\n <CardMeta>Default agent + model override.</CardMeta>\n <div className=\"field\" data-setting-id=\"defaultAgent\">\n <label className=\"field-label\" htmlFor=\"set-default-agent\">Default agent</label>\n <input\n id=\"set-default-agent\"\n className=\"input\"\n type=\"text\"\n placeholder=\"e.g. odin\"\n value={settings.defaultAgent || ''}\n onChange={(e) => patchTop('defaultAgent', e.target.value)}\n />\n </div>\n <div className=\"field\" data-setting-id=\"defaultModel\">\n <label className=\"field-label\" htmlFor=\"set-default-model\">Model override</label>\n <input\n id=\"set-default-model\"\n className=\"input\"\n type=\"text\"\n placeholder=\"(leave empty for provider default)\"\n value={settings.defaultModel || ''}\n onChange={(e) => patchTop('defaultModel', e.target.value)}\n />\n </div>\n </Card>\n</div>\n\n <div data-section=\"service\" style={{display: (activeSection === null || activeSection === 'service') ? 'block' : 'none'}}>\n<Card id=\"settings-service\" data-section=\"service\">\n <CardTitle><ServerIcon size={14} /> Service</CardTitle>\n <CardMeta>Background daemon that runs schedules.</CardMeta>\n <div data-setting-id=\"service.enabled\">\n {tailscale ? (\n <div className=\"service-card\">\n <p>\n Status: <strong>{tailscale?.settings.enabled ? 'enabled' : 'disabled'}</strong>\n {' '}· Tailscale installed: <strong>{tailscale.installed ? 'yes' : 'no'}</strong>\n {' '}· authenticated: <strong>{tailscale.authenticated ? 'yes' : 'no'}</strong>\n </p>\n <p className=\"muted\">\n Use <code>bizar service start</code> / <code>bizar service stop</code> in\n your terminal to control the daemon.\n </p>\n </div>\n ) : (\n <p className=\"muted\">Loading service status…</p>\n )}\n </div>\n </Card>\n</div>\n\n <div data-section=\"tailscale\" style={{display: (activeSection === null || activeSection === 'tailscale') ? 'block' : 'none'}}>\n<Card id=\"settings-tailscale\" data-section=\"tailscale\">\n <CardTitle><Plug size={14} /> Tailscale serve</CardTitle>\n <CardMeta>Expose the dashboard over your Tailscale network.</CardMeta>\n {tailscale ? (\n <>\n <p>\n Installed: <strong>{tailscale.installed ? 'yes' : 'no'}</strong>{' '}\n {tailscale.version && <span className=\"muted\">({tailscale.version})</span>}\n </p>\n <p>\n Authenticated: <strong>{tailscale.authenticated ? 'yes' : 'no'}</strong>\n </p>\n <p>\n Serve enabled: <strong>{tailscale.settings.enabled ? 'yes' : 'no'}</strong>\n </p>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Port</label>\n <input\n type=\"number\"\n className=\"input\"\n value={tailscaleDraft.port}\n onChange={(e) => setTailscaleDraft((cur) => ({ ...cur, port: Number(e.target.value) || 4321 }))}\n />\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Use HTTPS</label>\n <input\n type=\"checkbox\"\n checked={tailscaleDraft.https}\n onChange={(e) => setTailscaleDraft((cur) => ({ ...cur, https: e.target.checked }))}\n />\n </div>\n </div>\n <Button variant=\"primary\" onClick={onTailscaleToggle}>\n {tailscale.settings.enabled ? 'Disable serve' : 'Enable serve'}\n </Button>\n </>\n ) : (\n <p className=\"muted\">Loading Tailscale status…</p>\n )}\n </Card>\n</div>\n\n <div data-section=\"notifications\" style={{display: (activeSection === null || activeSection === 'notifications') ? 'block' : 'none'}}>\n<Card id=\"settings-notifications\" data-section=\"notifications\">\n <CardTitle>Notifications</CardTitle>\n <CardMeta>Toast triggers inside the dashboard.</CardMeta>\n <label className=\"checkbox-row\" data-setting-id=\"notifications.onAgentComplete\">\n <input\n type=\"checkbox\"\n checked={!!settings.notifications.onAgentComplete}\n onChange={(e) => patchNotifications({ onAgentComplete: e.target.checked })}\n />\n <span>Notify when an agent invocation completes</span>\n </label>\n <label className=\"checkbox-row\" data-setting-id=\"notifications.onPlanApproval\">\n <input\n type=\"checkbox\"\n checked={!!settings.notifications.onPlanApproval}\n onChange={(e) => patchNotifications({ onPlanApproval: e.target.checked })}\n />\n <span>Notify when a plan needs approval</span>\n </label>\n </Card>\n</div>\n\n {/* v3.6.0 — Auth token management. The Settings tab is the\n only place a human can read the token. The input + Save\n button lets the operator paste a token they got from\n server stderr or from another machine. Copy / Regenerate\n buttons act via the authed /api/auth/* endpoints. */}\n <div data-section=\"auth\" style={{display: (activeSection === null || activeSection === 'auth') ? 'block' : 'none'}}>\n<Card id=\"settings-auth\" data-section=\"auth\">\n <CardTitle><Shield size={14} /> Authentication</CardTitle>\n <CardMeta>\n Localhost and Tailscale browser access are auto-trusted via loopback.\n A bearer token is still available for non-loopback clients and\n forced-auth mode.\n </CardMeta>\n <div className=\"field\" data-setting-id=\"auth.status\">\n <label className=\"field-label\">Server status</label>\n <p style={{ margin: '4px 0' }}>\n Auth required:{' '}\n <strong>{authStatus ? (authStatus.required ? 'yes' : 'no') : 'probing…'}</strong>\n </p>\n <p style={{ margin: '4px 0' }}>\n Connection:{' '}\n <strong>\n {authStatus\n ? (authStatus.loopback ? 'loopback (auto-trusted)' : 'remote')\n : 'probing…'}\n </strong>\n </p>\n <p style={{ margin: '4px 0' }}>\n Peer address:{' '}\n {authStatus?.peer ? <code>{authStatus.peer}</code> : <span className=\"muted\">probing…</span>}\n </p>\n <p className=\"muted\" style={{ fontSize: 12, margin: '4px 0' }}>\n Localhost and Tailscale browser access are auto-trusted because the\n dashboard sees a loopback peer. Paste a token only for non-loopback\n API clients/scripts, or if you force auth for every connection with{' '}\n <code>BIZAR_DASHBOARD_REQUIRE_AUTH=1</code>.\n </p>\n <p className=\"muted\" style={{ fontSize: 12, margin: '4px 0' }}>\n Dashboard tokens are generated on first boot and saved to{' '}\n <code>~/.config/bizar/dashboard-secret</code> (mode 0600).\n </p>\n {/* v3.6.2 */}\n <p className=\"muted\" style={{ fontSize: 12, margin: '4px 0' }}>\n For Tailscale Serve or any reverse-proxy access, paste this token\n once via the boot screen — it is saved per-origin and works for all\n subsequent visits.\n </p>\n </div>\n <div className=\"field\" data-setting-id=\"auth.token\">\n <label className=\"field-label\">Token (this browser)</label>\n <input\n type=\"password\"\n className=\"input mono\"\n value={authToken}\n onChange={(e) => setAuthToken(e.target.value)}\n placeholder=\"Paste token from server stderr or another browser\"\n spellCheck={false}\n autoComplete=\"off\"\n />\n <div className=\"task-form-row\" style={{ marginTop: 8 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={onSaveToken}>\n <KeyRound size={14} /> Save token\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onCopyToken}>\n <Copy size={14} /> Reveal &amp; copy server token\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRegenerateToken}>\n <RotateCcw size={14} /> Regenerate\n </Button>\n </div>\n {revealedToken ? (\n <p className=\"muted\" style={{ fontSize: 12, marginTop: 8 }}>\n Last revealed token (one-time): <code className=\"mono\">{revealedToken}</code>\n </p>\n ) : null}\n <p className=\"muted\" style={{ fontSize: 12, marginTop: 8 }}>\n Regenerating invalidates the current token immediately. Anything\n still using the old token will see 401 until it's updated.\n </p>\n </div>\n </Card>\n</div>\n\n <div data-section=\"agents\" style={{display: (activeSection === null || activeSection === 'agents') ? 'block' : 'none'}}>\n<Card id=\"settings-agents\" data-section=\"agents\">\n <CardTitle><ServerIcon size={14} /> Agent Behavior</CardTitle>\n <CardMeta>Limits and timeouts for background agent dispatch.</CardMeta>\n <div className=\"form-row\">\n <label htmlFor=\"agents-maxParallel\">\n Max parallel agents\n <span className=\"meta-badge\">default: 6</span>\n </label>\n <input\n id=\"agents-maxParallel\"\n type=\"number\"\n min={1}\n max={20}\n value={settings.agents?.maxParallel ?? 6}\n onChange={(e) => patchAgents({ maxParallel: Math.max(1, Math.min(20, parseInt(e.target.value, 10) || 6)) })}\n />\n </div>\n <div className=\"form-row\">\n <label htmlFor=\"agents-stuckThresholdMs\">\n Stuck threshold (ms)\n <span className=\"meta-badge\">default: 600000 (10 min)</span>\n </label>\n <input\n id=\"agents-stuckThresholdMs\"\n type=\"number\"\n min={60000}\n max={3600000}\n step={60000}\n value={settings.agents?.stuckThresholdMs ?? 600000}\n onChange={(e) => patchAgents({ stuckThresholdMs: Math.max(60000, Math.min(3600000, parseInt(e.target.value, 10) || 600000)) })}\n />\n </div>\n <label className=\"checkbox-row\" data-setting-id=\"agents.autoRestart\">\n <input\n type=\"checkbox\"\n checked={!!settings.agents?.autoRestart}\n onChange={(e) => patchAgents({ autoRestart: e.target.checked })}\n />\n <span>Auto-restart stuck agents</span>\n </label>\n </Card>\n</div>\n\n <div data-section=\"dashboard\" style={{display: (activeSection === null || activeSection === 'dashboard') ? 'block' : 'none'}}>\n<Card id=\"settings-dashboard\" data-section=\"dashboard\">\n <CardTitle><Globe size={14} /> Dashboard</CardTitle>\n <CardMeta>Controls how <code>bizar</code> starts up.</CardMeta>\n <label className=\"checkbox-row\" data-setting-id=\"dashboard.autoLaunchWeb\">\n <input\n type=\"checkbox\"\n checked={settings.dashboard.autoLaunchWeb !== false}\n onChange={(e) => patchDashboard({ autoLaunchWeb: e.target.checked })}\n />\n <span>Auto-launch web UI alongside TUI</span>\n </label>\n\n <div className=\"field\" data-setting-id=\"dashboard.projectsDirectory\" style={{ marginTop: 'var(--space-4)' }}>\n <label className=\"field-label\" htmlFor=\"set-projects-directory\">Projects directory</label>\n <input\n id=\"set-projects-directory\"\n className=\"input\"\n type=\"text\"\n placeholder=\"/home/user/projects\"\n value={settings.dashboard.projectsDirectory ?? ''}\n onChange={(e) => patchDashboard({ projectsDirectory: e.target.value })}\n />\n <p className=\"field-help\">\n New projects created via the dashboard will land here, and existing project\n directories inside this folder are auto-recognized on startup.\n </p>\n {settings.dashboard.projectsDirectory && (\n <>\n {!/^\\/|^[A-Za-z]:/.test(settings.dashboard.projectsDirectory) && (\n <p style={{ color: 'var(--warning)', fontSize: 11, marginTop: 4 }}>\n Path should be absolute (start with / on Linux/Mac, or a drive letter on Windows).\n </p>\n )}\n {settings.dashboard.projectsDirectory.includes('..') && (\n <p style={{ color: 'var(--error)', fontSize: 11, marginTop: 4 }}>\n Path traversal not allowed — this will be rejected server-side.\n </p>\n )}\n </>\n )}\n </div>\n\n {/* allowedRoots textarea */}\n <div className=\"field\" data-setting-id=\"dashboard.allowedRoots\" style={{ marginTop: 'var(--space-4)' }}>\n <label className=\"field-label\" htmlFor=\"set-allowed-roots\">\n Additional allowed roots <span className=\"muted\">(advanced)</span>\n </label>\n <textarea\n id=\"set-allowed-roots\"\n className=\"textarea\"\n rows={4}\n placeholder=\"/workspace&#10;/srv/projects\"\n value={(settings.dashboard.allowedRoots ?? []).join('\\n')}\n onChange={(e) => {\n const lines = e.target.value\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n patchDashboard({ allowedRoots: lines });\n }}\n />\n <p className=\"field-help\">\n Optional. Add filesystem roots beyond your home directory that the file\n browser and project scanner can access. Each path must be inside your\n home directory. One per line.\n </p>\n {(() => {\n const rawLines = (settings.dashboard.allowedRoots ?? []).join('\\n').split('\\n');\n const warnings: { key: string; msg: React.ReactNode }[] = [];\n rawLines.forEach((line, i) => {\n if (!line.trim()) return;\n if (!/^\\/|^[A-Za-z]:/.test(line)) {\n warnings.push({\n key: `noabs-${i}`,\n msg: (\n <p style={{ color: 'var(--warning)', fontSize: 11, marginTop: 2 }}>\n Line {i + 1}: \"{line}\" — should be absolute (start with / or a drive letter).\n </p>\n ),\n });\n }\n if (line.includes('..')) {\n warnings.push({\n key: `dots-${i}`,\n msg: (\n <p style={{ color: 'var(--error)', fontSize: 11, marginTop: 2 }}>\n Line {i + 1}: \"{line}\" — contains '..' (server will reject this).\n </p>\n ),\n });\n }\n });\n return warnings.map((w) => w.msg);\n })()}\n </div>\n </Card>\n</div>\n\n <div data-section=\"background\" style={{display: (activeSection === null || activeSection === 'background') ? 'block' : 'none'}}>\n<Card id=\"settings-background\" data-section=\"background\">\n <CardTitle><ServerIcon size={14} /> Background Agents</CardTitle>\n <CardMeta>Tune plugin options. Changes take effect on next plugin restart.</CardMeta>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-maxConcurrent\">\n Max concurrent instances\n <span className=\"meta-badge\">default: 8</span>\n </label>\n <input\n id=\"bg-maxConcurrent\"\n type=\"number\"\n min={1}\n max={32}\n value={pluginOptions.maxConcurrentInstances ?? 8}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, maxConcurrentInstances: Math.max(1, Math.min(32, parseInt(e.target.value, 10) || 8)) }))}\n />\n <small className=\"muted\">Plugin option: <code>maxConcurrentInstances</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-toolCallCap\">\n Tool-call cap\n <span className=\"meta-badge\">default: 500</span>\n </label>\n <input\n id=\"bg-toolCallCap\"\n type=\"number\"\n min={1}\n max={5000}\n value={pluginOptions.backgroundToolCallCap ?? 500}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundToolCallCap: Math.max(1, Math.min(5000, parseInt(e.target.value, 10) || 500)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundToolCallCap</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-stallTimeout\">\n Stall timeout (ms)\n <span className=\"meta-badge\">default: 180000</span>\n </label>\n <input\n id=\"bg-stallTimeout\"\n type=\"number\"\n min={10000}\n max={600000}\n step={1000}\n value={pluginOptions.backgroundStallTimeoutMs ?? 180000}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundStallTimeoutMs: Math.max(10000, Math.min(600000, parseInt(e.target.value, 10) || 180000)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundStallTimeoutMs</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-thinkingLoopTimeout\">\n Thinking-loop timeout (ms)\n <span className=\"meta-badge\">default: 300000</span>\n </label>\n <input\n id=\"bg-thinkingLoopTimeout\"\n type=\"number\"\n min={30000}\n max={900000}\n step={1000}\n value={pluginOptions.backgroundThinkingLoopTimeoutMs ?? 300000}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundThinkingLoopTimeoutMs: Math.max(30000, Math.min(900000, parseInt(e.target.value, 10) || 300000)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundThinkingLoopTimeoutMs</code></small>\n </div>\n\n <div className=\"form-row\">\n <label htmlFor=\"bg-maxInterventions\">\n Max interventions\n <span className=\"meta-badge\">default: 1</span>\n </label>\n <input\n id=\"bg-maxInterventions\"\n type=\"number\"\n min={1}\n max={3}\n value={pluginOptions.backgroundMaxInterventions ?? 1}\n onChange={(e) => setPluginOptions((cur) => ({ ...cur, backgroundMaxInterventions: Math.max(1, Math.min(3, parseInt(e.target.value, 10) || 1)) }))}\n />\n <small className=\"muted\">Plugin option: <code>backgroundMaxInterventions</code></small>\n </div>\n\n <div className=\"form-row\">\n <Button variant=\"secondary\" size=\"sm\" onClick={async () => {\n try {\n await api.put('/settings/plugin-options', pluginOptions);\n toast.success('Saved — restart opencode for changes to take effect.');\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}>\n <Save size={14} /> Save plugin options\n </Button>\n\n <Button variant=\"secondary\" size=\"sm\" onClick={async () => {\n try {\n const r = await fetch('/api/background/cleanup', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ maxAgeDays: 7 }),\n });\n const result = await r.json();\n toast.success(`Cleaned up ${result.deleted} old instances.`);\n } catch (err) {\n toast.error(`Cleanup failed: ${(err as Error).message}`);\n }\n }}>\n Cleanup old instances (&gt;7 days)\n </Button>\n </div>\n\n <div className=\"form-row\">\n <small>Plugin options are read at startup. Save changes and run <code>bizar update</code> to apply.</small>\n </div>\n </Card>\n</div>\n </div>\n\n <div data-section=\"system-llm\" style={{display: (activeSection === null || activeSection === 'system-llm') ? 'block' : 'none'}}>\n<Card id=\"settings-system-llm\" data-section=\"system-llm\">\n <CardTitle><Sparkles size={14} /> System LLM API</CardTitle>\n <CardMeta>\n Configures the LLM used for automatic title generation, prompt enhancement,\n summarization, and other system-level calls.\n </CardMeta>\n\n <label className=\"checkbox-row\" data-setting-id=\"systemLlm.enabled\">\n <input\n type=\"checkbox\"\n checked={!!settings.systemLlm?.enabled}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, enabled: e.target.checked });\n }}\n />\n <span>Enable system LLM calls</span>\n </label>\n\n <div className=\"field\" data-setting-id=\"systemLlm.provider\" style={{ marginTop: 'var(--space-3)' }}>\n <label className=\"field-label\" htmlFor=\"set-system-llm-provider\">Provider</label>\n <select\n id=\"set-system-llm-provider\"\n className=\"select\"\n value={settings.systemLlm?.provider || 'opencode'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, provider: e.target.value });\n }}\n >\n <option value=\"opencode\">Opencode</option>\n <option value=\"openrouter\">OpenRouter</option>\n <option value=\"minimax\">MiniMax</option>\n </select>\n </div>\n\n <div className=\"field\" data-setting-id=\"systemLlm.model\">\n <label className=\"field-label\" htmlFor=\"set-system-llm-model\">Model</label>\n <input\n id=\"set-system-llm-model\"\n className=\"input mono\"\n type=\"text\"\n placeholder=\"opencode/deepseek-v4-flash-free\"\n value={settings.systemLlm?.model || 'opencode/deepseek-v4-flash-free'}\n onChange={(e) => {\n const cur = settings.systemLlm || { enabled: true, provider: 'opencode', model: 'opencode/deepseek-v4-flash-free' };\n patchTop('systemLlm', { ...cur, model: e.target.value });\n }}\n />\n <p className=\"field-help\">\n The API key is read from <code>auth.json</code> for the selected provider.\n Leave the default model for best results.\n </p>\n </div>\n\n <div style={{ marginTop: 'var(--space-4)' }}>\n <h4 style={{ margin: '0 0 var(--space-2)' }}>Features using this API</h4>\n <ul className=\"settings-feature-list\" style={{ margin: 0, paddingLeft: 'var(--space-4)', lineHeight: 1.8 }}>\n <li>Auto-title generation for new chat sessions</li>\n <li>Auto-title generation for new tasks</li>\n <li>\"Enhance prompt\" button in the task input</li>\n <li>\"Enhance prompt\" button in the chat composer</li>\n <li className=\"muted\" style={{ fontSize: 12 }}>Future: summarization, name generation, and more</li>\n </ul>\n </div>\n </Card>\n</div>\n\n <div data-section=\"headroom\" style={{display: (activeSection === null || activeSection === 'headroom') ? 'block' : 'none'}}>\n <HeadroomSettingsCard\n settings={settings.headroom || DEFAULT_HEADROOM_SETTINGS}\n onPatch={(patch) => {\n setSettings((cur) => ({\n ...cur,\n headroom: { ...(cur.headroom || DEFAULT_HEADROOM_SETTINGS), ...patch },\n }));\n setDirty(true);\n }}\n />\n </div>\n\n <PairDeviceCard />\n\n <div style={{display: (activeSection === null || activeSection === 'activity-log') ? 'block' : 'none'}}>\n <div data-section=\"activity-log\" style={{display: (activeSection === null || activeSection === 'activity-log') ? 'block' : 'none'}}>\n <section id=\"settings-activity-log\" data-section=\"activity-log\" className=\"settings-section-wrap\">\n <ActivityLogCard />\n </section>\n</div>\n</div>\n\n <div style={{display: (activeSection === null || activeSection === 'about') ? 'block' : 'none'}}>\n <div data-section=\"about\" style={{display: (activeSection === null || activeSection === 'about') ? 'block' : 'none'}}>\n <Card id=\"settings-about\" data-section=\"about\">\n <CardTitle><Info size={14} /> About</CardTitle>\n <CardMeta>Build metadata.</CardMeta>\n <dl className=\"about-table\">\n <dt>Version</dt>\n <dd className=\"mono\">{about.version}</dd>\n <dt>Homepage</dt>\n <dd>\n <a href={about.homepage} target=\"_blank\" rel=\"noopener noreferrer\">\n {about.homepage}\n </a>\n </dd>\n <dt>License</dt>\n <dd>{about.license}</dd>\n </dl>\n </Card>\n</div>\n</div>\n </div>\n );\n}\n\n/**\n * v3.15.0 — Full activity log + hidden set management.\n *\n * Two sources of truth:\n * - GET /activity — the full unfiltered log (incl. hidden entries)\n * - GET /activity/hidden — the list of keys the user chose to hide\n *\n * Hiding is non-destructive: hidden items still appear here so the\n * user can review / restore them.\n */\nfunction ActivityLogCard() {\n const toast = useToast();\n const [items, setItems] = useState<Array<{ kind?: string; ts?: string; slug?: string; message?: string }>>([]);\n const [hidden, setHidden] = useState<Set<string>>(new Set());\n const [loading, setLoading] = useState(true);\n const [filter, setFilter] = useState('');\n const [showHidden, setShowHidden] = useState(true);\n\n const refresh = useCallback(async () => {\n setLoading(true);\n try {\n const [log, hid] = await Promise.all([\n api.get<{ items: Array<{ kind?: string; ts?: string; slug?: string; message?: string }> }>('/activity'),\n api.get<{ hidden: string[] }>('/activity/hidden'),\n ]);\n setItems(Array.isArray(log.items) ? log.items : []);\n setHidden(new Set(hid.hidden || []));\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n }, [toast]);\n\n useEffect(() => { refresh(); }, [refresh]);\n\n const keyOf = (it: { kind?: string; ts?: string; slug?: string }, idx: number) => {\n const k = `${it.kind || ''}|${it.ts || ''}|${it.slug || ''}|${idx}`;\n let h = 0;\n for (let i = 0; i < k.length; i++) h = ((h << 5) - h + k.charCodeAt(i)) | 0;\n return Math.abs(h).toString(16).padStart(8, '0').slice(0, 16);\n };\n\n const onRestoreAll = async () => {\n try {\n await api.del('/activity/hide');\n setHidden(new Set());\n toast.success('All hidden activity restored.');\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const onRestoreOne = async (key: string) => {\n try {\n await api.del(`/activity/hide/${encodeURIComponent(key)}`);\n const next = new Set(hidden);\n next.delete(key);\n setHidden(next);\n } catch (err) {\n toast.error(`Restore failed: ${(err as Error).message}`);\n }\n };\n\n const filtered = items.filter((it, idx) => {\n const k = keyOf(it, idx);\n if (!showHidden && hidden.has(k)) return false;\n if (!filter) return true;\n const q = filter.toLowerCase();\n return [it.kind, it.slug, it.message].some((v) => typeof v === 'string' && v.toLowerCase().includes(q));\n });\n\n return (\n <Card id=\"settings-diagnostics\" data-section=\"diagnostics\">\n <CardTitle>\n <Activity size={14} /> Activity log\n <span className=\"muted\" style={{ fontWeight: 400, marginLeft: 8, fontSize: 12 }}>\n {items.length} total · {hidden.size} hidden\n </span>\n <Button variant=\"ghost\" size=\"sm\" style={{ marginLeft: 'auto' }} onClick={refresh} title=\"Reload\">\n <RefreshCw size={12} />\n </Button>\n </CardTitle>\n <CardMeta>\n Full history from <code>~/.bizar/activity.log</code>. Hiding an item in the Overview only hides it there — the entry stays here.\n </CardMeta>\n\n <div className=\"activity-log-toolbar\">\n <div className=\"activity-log-search\">\n <Search size={12} />\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"Filter by kind, slug, or message…\"\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n />\n </div>\n <label className=\"activity-log-toggle\">\n <input\n type=\"checkbox\"\n checked={showHidden}\n onChange={(e) => setShowHidden(e.target.checked)}\n />\n Show hidden\n </label>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={hidden.size === 0}\n onClick={onRestoreAll}\n title=\"Restore all hidden items to the Overview\"\n >\n <Eye size={12} /> Restore all\n </Button>\n </div>\n\n {loading ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>Loading…</div>\n ) : filtered.length === 0 ? (\n <div className=\"muted\" style={{ padding: '12px 0', fontSize: 12 }}>\n {items.length === 0 ? 'No activity yet.' : 'No items match the current filter.'}\n </div>\n ) : (\n <div className=\"activity-log-table-wrap\">\n <table className=\"activity-log-table\">\n <thead>\n <tr>\n <th>Kind</th>\n <th>Detail</th>\n <th>Time</th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n {filtered.slice(0, 200).map((it, idx) => {\n const k = keyOf(it, idx);\n const isHidden = hidden.has(k);\n return (\n <tr key={`${it.ts}-${idx}`} className={cn(isHidden && 'activity-log-row-hidden')}>\n <td className=\"activity-log-kind\">{it.kind || 'activity'}</td>\n <td className=\"activity-log-detail\">\n {it.message || it.slug || '—'}\n </td>\n <td className=\"activity-log-time mono\">\n {it.ts ? new Date(it.ts).toLocaleString() : '—'}\n </td>\n <td>\n {isHidden ? (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => onRestoreOne(k)} title=\"Restore to Overview\">\n <Eye size={12} />\n </Button>\n ) : (\n <span className=\"activity-log-state-tag\">shown</span>\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n {filtered.length > 200 && (\n <div className=\"muted\" style={{ fontSize: 11, padding: '8px 0' }}>\n Showing first 200 of {filtered.length}.\n </div>\n )}\n </div>\n )}\n </Card>\n );\n}\nexport const SettingsView = React.memo(SettingsViewInner);\n","// src/views/Mods.tsx — list, install, enable/disable mods + mod views.\nimport { useEffect, useState } from 'react';\nimport {\n Puzzle,\n Plus,\n Trash2,\n Power,\n RefreshCw,\n Folder,\n FileText,\n FileCode,\n User,\n Terminal,\n BookOpen,\n X,\n ExternalLink,\n Globe,\n LayoutTemplate,\n Download,\n ChevronDown,\n ChevronRight,\n ShieldCheck,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Mod, Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype ModView = {\n id: string;\n modId: string;\n kind: 'iframe' | 'tab';\n label: string;\n description?: string;\n path?: string;\n};\n\nexport function Mods({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n // v3.3.0 — Always start by loading from the server, not just the\n // snapshot. The snapshot can be stale if the user installed a mod\n // from the CLI or added files directly to ~/.config/bizar/mods.\n // We seed the initial state from the snapshot for instant paint\n // but always re-fetch on mount and after every mutation.\n const [mods, setMods] = useState<Mod[]>(Array.isArray(snapshot.mods) ? snapshot.mods : []);\n const [loading, setLoading] = useState(true);\n const [selected, setSelected] = useState<string | null>(null);\n const [modViews, setModViews] = useState<ModView[]>([]);\n const [iframeUrl, setIframeUrl] = useState<string | null>(null);\n // v3.16.0 — Registry browser\n const [registryOpen, setRegistryOpen] = useState(false);\n const [registry, setRegistry] = useState<{\n source: string;\n version?: number;\n updatedAt?: string;\n mods: Array<{\n id: string;\n name: string;\n latest?: string;\n description?: string;\n author?: string;\n tags?: string[];\n permissions?: string[];\n homepage?: string;\n installed?: boolean;\n installedVersion?: string | null;\n upgradeAvailable?: string | null;\n }>;\n error?: string;\n } | null>(null);\n const [registryLoading, setRegistryLoading] = useState(false);\n const [installing, setInstalling] = useState<Record<string, boolean>>({});\n\n const loadRegistry = async () => {\n setRegistryLoading(true);\n try {\n const r = await api.get<{\n registry?: { source?: string; version?: number; updatedAt?: string };\n mods?: Array<{\n id: string;\n name: string;\n latest?: string;\n description?: string;\n author?: string;\n tags?: string[];\n permissions?: string[];\n homepage?: string;\n installed?: boolean;\n installedVersion?: string | null;\n upgradeAvailable?: string | null;\n }>;\n }>('/mods/registry');\n setRegistry({\n source: r.registry?.source || '',\n version: r.registry?.version,\n updatedAt: r.registry?.updatedAt,\n mods: r.mods || [],\n });\n } catch (err) {\n setRegistry({ source: '', mods: [], error: (err as Error).message });\n } finally {\n setRegistryLoading(false);\n }\n };\n\n const onInstallFromRegistry = async (id: string) => {\n setInstalling((cur) => ({ ...cur, [id]: true }));\n try {\n const m = await api.post<Mod>('/mods', { id });\n setMods((cur) => [...cur.filter((x) => x.id !== m.id), m]);\n toast.success(`Mod \"${m.id}\" installed from registry.`);\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n } finally {\n setInstalling((cur) => ({ ...cur, [id]: false }));\n }\n };\n\n // v3.20.5 — Upgrade handler. Calls the dedicated `/mods/:id/upgrade`\n // endpoint (the install endpoint refuses if the mod is already on disk).\n // Reports oldVersion → newVersion in the success toast.\n const onUpgradeFromRegistry = async (id: string, backup = false) => {\n setInstalling((cur) => ({ ...cur, [id]: true }));\n try {\n const r = await api.post<{\n ok: boolean;\n from: string;\n to: string;\n backupPath: string | null;\n mod: Mod;\n }>(`/mods/${encodeURIComponent(id)}/upgrade`, { backup });\n setMods((cur) => [...cur.filter((x) => x.id !== r.mod.id), r.mod]);\n const backupNote = r.backupPath ? ` (backup at ${r.backupPath})` : '';\n toast.success(`Mod \"${id}\" upgraded v${r.from} → v${r.to}${backupNote}.`);\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Upgrade failed: ${(err as Error).message}`);\n } finally {\n setInstalling((cur) => ({ ...cur, [id]: false }));\n }\n };\n\n const reload = async () => {\n try {\n // Always pull fresh from the server. snapshot is fine for\n // optimistic initial render, but a fresh fetch makes the page\n // behave correctly even if the snapshot was empty or stale.\n const r = await api.get<{ mods: Mod[] }>('/mods');\n setMods(r.mods || []);\n try {\n const v = await api.get<{ views: ModView[] }>('/mods/views');\n setModViews(v.views || []);\n } catch {\n setModViews([]);\n }\n } catch (err) {\n toast.error(`Mods load failed: ${(err as Error).message}`);\n } finally {\n // v3.3.0 — Always clear loading even on failure so the empty\n // state can render. Without this, a network blip would leave\n // the user staring at a spinner forever.\n setLoading(false);\n }\n };\n\n // Initial load — runs once on mount.\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Re-sync from snapshot when it changes (other tabs may have\n // triggered a refreshSnapshot that updated the mod list).\n useEffect(() => {\n if (Array.isArray(snapshot.mods) && snapshot.mods !== mods) {\n setMods(snapshot.mods);\n }\n // eslint-disable-next-line react-hooks-exhaustive-deps\n }, [snapshot.mods]);\n\n const onInstall = () => {\n let pathEl: HTMLInputElement | null = null;\n modal.open({\n title: 'Install mod',\n children: (\n <div>\n <p className=\"muted\">\n Provide the absolute path to a mod folder (one that contains\n a <code>mod.json</code>). The folder will be copied to\n {' '}<code>~/.config/bizar/mods/&lt;id&gt;/</code>.\n </p>\n <label className=\"field-label\">Path</label>\n <input\n ref={(el) => (pathEl = el)}\n className=\"input\"\n type=\"text\"\n placeholder=\"/path/to/my-mod\"\n autoFocus\n />\n </div>\n ),\n footer: (\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" onClick={() => modal.close()}>Cancel</Button>\n <Button\n variant=\"primary\"\n onClick={async () => {\n const path = (pathEl?.value || '').trim();\n if (!path) {\n toast.warning('Path is required.');\n return;\n }\n try {\n const m = await api.post<Mod>('/mods', { path });\n setMods((cur) => [...cur, m]);\n toast.success(`Mod \"${m.id}\" installed.`);\n modal.close();\n await refreshSnapshot();\n } catch (err) {\n toast.error(`Install failed: ${(err as Error).message}`);\n }\n }}\n >\n Install\n </Button>\n </div>\n ),\n });\n };\n\n const onUninstall = async (id: string) => {\n if (!confirm(`Uninstall mod \"${id}\"? This removes the folder from ~/.config/bizar/mods/.`)) return;\n try {\n await api.del(`/mods/${encodeURIComponent(id)}`);\n setMods((cur) => cur.filter((m) => m.id !== id));\n if (selected === id) setSelected(null);\n toast.success('Mod uninstalled.');\n } catch (err) {\n toast.error(`Uninstall failed: ${(err as Error).message}`);\n }\n };\n\n const onToggleEnabled = async (mod: Mod) => {\n try {\n const next = await api.put<Mod>(`/mods/${encodeURIComponent(mod.id)}`, { enabled: !mod.enabled });\n setMods((cur) => cur.map((m) => (m.id === mod.id ? next : m)));\n toast.success(`Mod ${next.enabled ? 'enabled' : 'disabled'}.`);\n } catch (err) {\n toast.error(`Toggle failed: ${(err as Error).message}`);\n }\n };\n\n const sel = mods.find((m) => m.id === selected) || null;\n\n if (loading) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n </div>\n );\n }\n\n return (\n <div className=\"view view-mods\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Puzzle size={18} /> Mods ({mods.length})\n </h2>\n <p className=\"view-subtitle\">\n Extensions installed in <code>~/.config/bizar/mods/</code>.\n Mods can add agents, commands, routes, and views.\n </p>\n </div>\n <div className=\"view-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={onInstall}>\n <Plus size={14} /> Install mod\n </Button>\n </div>\n </header>\n\n {mods.length === 0 ? (\n <EmptyState\n icon={<Puzzle size={32} />}\n title=\"No mods installed\"\n message=\"Mods are folders with a mod.json. Install one to extend Bizar with custom agents, commands, and views.\"\n />\n ) : (\n <div className=\"mods-layout\">\n <div className=\"mods-list\">\n {mods.map((m) => (\n <div\n key={m.id}\n className={cn('mod-list-item', selected === m.id && 'mod-list-item-active')}\n onClick={() => setSelected(m.id)}\n >\n <div className=\"mod-list-item-head\">\n <div>\n <div className=\"mod-list-item-name\">{m.name}</div>\n <div className=\"mod-list-item-meta\">v{m.version} · {m.type} · {m.author}</div>\n </div>\n <div className=\"mod-list-item-actions\" onClick={(e) => e.stopPropagation()}>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Toggle enabled\"\n title={m.enabled ? 'Disable' : 'Enable'}\n onClick={() => onToggleEnabled(m)}\n >\n <Power size={12} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Uninstall\"\n title=\"Uninstall\"\n onClick={() => onUninstall(m.id)}\n >\n <Trash2 size={12} />\n </button>\n </div>\n </div>\n <div className=\"mod-list-item-desc ellipsis-2\" title={m.description}>\n {m.description}\n </div>\n <div className=\"mod-list-item-status\">\n <span className={`mod-mini-pill ${m.enabled ? 'mod-mini-pill-on' : 'mod-mini-pill-off'}`}>\n {m.enabled ? 'enabled' : 'disabled'}\n </span>\n </div>\n </div>\n ))}\n </div>\n {sel && <ModDetails mod={sel} />}\n </div>\n )}\n\n {/* v3.16.0 — Registry browser */}\n <Card className=\"mods-registry-card\">\n <div className=\"mods-registry-head\" onClick={() => {\n if (!registry && !registryLoading) loadRegistry();\n setRegistryOpen((v) => !v);\n }}>\n <Globe size={14} />\n <span className=\"mods-registry-title\">Mod registry</span>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n {registry?.mods ? `${registry.mods.length} available` : 'click to browse'}\n </span>\n <span className=\"mods-registry-spacer\" />\n {registryOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </div>\n {registryOpen && (\n <div className=\"mods-registry-body\">\n {registryLoading ? (\n <div className=\"muted\" style={{ padding: 12, fontSize: 12 }}>Loading registry…</div>\n ) : registry?.error ? (\n <div className=\"mods-registry-error\">\n <ShieldCheck size={12} /> Could not load registry: {registry.error}\n </div>\n ) : !registry || registry.mods.length === 0 ? (\n <div className=\"muted\" style={{ padding: 12, fontSize: 12 }}>\n No mods listed in the registry yet.\n </div>\n ) : (\n <>\n {registry.source && (\n <div className=\"muted\" style={{ fontSize: 11, marginBottom: 8 }}>\n Source: <code>{registry.source}</code>\n </div>\n )}\n <div className=\"mods-registry-grid\">\n {registry.mods.map((rm) => {\n const installed = mods.some((m) => m.id === rm.id);\n const isInstalling = !!installing[rm.id];\n return (\n <div key={rm.id} className=\"mod-registry-card\">\n <div className=\"mod-registry-card-head\">\n <div className=\"mod-registry-card-name\">{rm.name}</div>\n {rm.latest && (\n <span className={cn('mod-registry-version', rm.upgradeAvailable && 'mod-registry-version-upgrade')}>\n v{rm.latest}{rm.upgradeAvailable ? ' ↑' : ''}\n </span>\n )}\n </div>\n {rm.description && (\n <div className=\"mod-registry-card-desc\">{rm.description}</div>\n )}\n <div className=\"mod-registry-card-meta\">\n {rm.author && <span className=\"muted\">by {rm.author}</span>}\n {rm.homepage && (\n <a href={rm.homepage} target=\"_blank\" rel=\"noopener noreferrer\" className=\"mod-registry-link\">\n homepage\n </a>\n )}\n </div>\n {(rm.permissions || []).length > 0 && (\n <div className=\"mod-registry-perms\">\n <ShieldCheck size={10} />\n {(rm.permissions || []).slice(0, 4).map((p) => (\n <span key={p} className=\"mod-registry-perm\">{p}</span>\n ))}\n {(rm.permissions || []).length > 4 && (\n <span className=\"mod-registry-perm-more\">+{rm.permissions!.length - 4}</span>\n )}\n </div>\n )}\n <div className=\"mod-registry-card-actions\">\n {!installed && (\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={isInstalling}\n onClick={() => onInstallFromRegistry(rm.id)}\n title=\"Install from registry\"\n >\n {isInstalling ? <Spinner size=\"sm\" /> : (<><Download size={12} /> Install</>)}\n </Button>\n )}\n {installed && rm.upgradeAvailable && (\n <Button\n variant=\"primary\"\n size=\"sm\"\n disabled={isInstalling}\n onClick={() => onUpgradeFromRegistry(rm.id)}\n title={`Upgrade from v${rm.installedVersion || '?'} to v${rm.upgradeAvailable}`}\n >\n {isInstalling ? <Spinner size=\"sm\" /> : (<><Download size={12} /> Upgrade to v{rm.upgradeAvailable}</>)}\n </Button>\n )}\n {installed && !rm.upgradeAvailable && (\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled\n title={`Installed v${rm.installedVersion || '?'}`}\n >\n Installed v{rm.installedVersion || '?'}\n </Button>\n )}\n </div>\n </div>\n );\n })}\n </div>\n </>\n )}\n </div>\n )}\n </Card>\n\n {/* v3.20.3 — Mod views now appear in the sidebar nav as first-class\n tabs (handled by App.tsx), so this section is a hint pointing\n users to the sidebar. */}\n {modViews.length > 0 && (\n <Card className=\"mod-views-hint\">\n <CardTitle><Globe size={14} /> Mod views</CardTitle>\n <CardMeta>\n {modViews.length} mod-supplied view{modViews.length === 1 ? '' : 's'} are now available in the sidebar navigation.\n Look for the <strong>Mods</strong> section at the bottom of the sidebar.\n </CardMeta>\n </Card>\n )}\n\n {/* Iframe panel for mod web views */}\n {iframeUrl && (\n <div className=\"mod-iframe-panel\">\n <div className=\"mod-iframe-header\">\n <span>Mod view — <a href={iframeUrl} target=\"_blank\" rel=\"noreferrer\">{iframeUrl}</a></span>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Close iframe\"\n onClick={() => setIframeUrl(null)}\n >\n <X size={14} />\n </button>\n </div>\n <iframe\n src={iframeUrl}\n className=\"mod-iframe\"\n title=\"Mod view\"\n sandbox=\"allow-scripts allow-same-origin allow-forms allow-popups\"\n />\n </div>\n )}\n </div>\n );\n}\n\nfunction ModDetails({ mod }: { mod: Mod }) {\n const toast = useToast();\n const [instructions, setInstructions] = useState<{\n modId: string;\n modName: string;\n total: number;\n agents: Array<{ filename: string; path: string; fullPath: string; content: string | null }>;\n commands: Array<{ filename: string; path: string; fullPath: string; content: string | null }>;\n skills: Array<{ name: string; fullPath: string; content: string | null }>;\n } | null>(null);\n const [instructionsLoading, setInstructionsLoading] = useState(false);\n const [instructionsOpen, setInstructionsOpen] = useState(false);\n const [expandedFile, setExpandedFile] = useState<string | null>(null);\n\n const loadInstructions = async () => {\n setInstructionsLoading(true);\n try {\n const r = await api.get<typeof instructions>(`/mods/${mod.id}/instructions`);\n setInstructions(r);\n setInstructionsOpen(true);\n } catch (err) {\n toast.error(`Failed to load instructions: ${(err as Error).message}`);\n } finally {\n setInstructionsLoading(false);\n }\n };\n\n const onReinstallInstructions = async () => {\n try {\n const r = await api.post<{ ok: boolean; counts: { agents: number; commands: number; skills: number; instructions: number } }>(\n `/mods/${mod.id}/instructions/reinstall`,\n {},\n );\n toast.success(`Reinstalled: ${r.counts.agents} agents, ${r.counts.commands} commands, ${r.counts.skills} skills, ${r.counts.instructions} instructions.`);\n await loadInstructions();\n } catch (err) {\n toast.error(`Reinstall failed: ${(err as Error).message}`);\n }\n };\n\n return (\n <Card className=\"mod-details\">\n <CardTitle><FileText size={14} /> Mod details — {mod.name}</CardTitle>\n <CardMeta>\n <code>{mod.path}</code>\n </CardMeta>\n <dl className=\"env-table\">\n <dt>ID</dt>\n <dd className=\"mono\">{mod.id}</dd>\n <dt>Version</dt>\n <dd className=\"mono\">{mod.version}</dd>\n <dt>Type</dt>\n <dd className=\"mono\">{mod.type}</dd>\n <dt>Author</dt>\n <dd className=\"mono\">{mod.author || '—'}</dd>\n <dt>Bizar</dt>\n <dd className=\"mono\">{mod.bizar || '*'}</dd>\n <dt>Enabled</dt>\n <dd>{mod.enabled ? 'yes' : 'no'}</dd>\n <dt>Permissions</dt>\n <dd>\n {(mod.permissions || []).map((p) => (\n <span key={p} className=\"tag\">{p}</span>\n ))}\n {(mod.permissions || []).length === 0 && <span className=\"muted\">(none)</span>}\n </dd>\n </dl>\n <div className=\"mod-files\">\n <div className=\"muted\">Files</div>\n <ul>\n {(mod.files || []).map((f) => (\n <li key={f.path}>\n <span className=\"mod-file-cat\">{f.category}</span>\n <span className=\"mono\">{f.path}</span>\n </li>\n ))}\n </ul>\n </div>\n\n {/* v3.20 — Installed instructions (agents / commands / skills) */}\n <div className=\"mod-instructions\">\n <div className=\"mod-instructions-head\" onClick={() => {\n if (!instructions && !instructionsLoading) loadInstructions();\n setInstructionsOpen((v) => !v);\n }}>\n <FileCode size={14} />\n <span>Installed instructions</span>\n <span className=\"muted\" style={{ fontSize: 11 }}>\n {instructions ? `${instructions.total} files` : 'click to view'}\n </span>\n <span className=\"mod-instructions-spacer\" />\n {instructionsOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </div>\n {instructionsOpen && instructions && (\n <div className=\"mod-instructions-body\">\n {instructions.agents.length > 0 && (\n <div className=\"mod-instructions-section\">\n <div className=\"mod-instructions-section-title\">\n <User size={11} /> Agents ({instructions.agents.length})\n </div>\n {instructions.agents.map((f) => (\n <div key={f.filename} className=\"mod-instructions-file\">\n <div\n className=\"mod-instructions-file-head\"\n onClick={() => setExpandedFile((cur) => cur === f.filename ? null : f.filename)}\n >\n <span className=\"mono\">{f.filename}</span>\n <span className=\"muted\" style={{ fontSize: 10 }}>\n installed at {f.fullPath}\n </span>\n </div>\n {expandedFile === f.filename && (\n <pre className=\"mod-instructions-content\">\n {f.content || <em className=\"muted\">(file missing on disk)</em>}\n </pre>\n )}\n </div>\n ))}\n </div>\n )}\n {instructions.commands.length > 0 && (\n <div className=\"mod-instructions-section\">\n <div className=\"mod-instructions-section-title\">\n <Terminal size={11} /> Commands ({instructions.commands.length})\n </div>\n {instructions.commands.map((f) => (\n <div key={f.filename} className=\"mod-instructions-file\">\n <div\n className=\"mod-instructions-file-head\"\n onClick={() => setExpandedFile((cur) => cur === f.filename ? null : f.filename)}\n >\n <span className=\"mono\">{f.filename}</span>\n <span className=\"muted\" style={{ fontSize: 10 }}>\n installed at {f.fullPath}\n </span>\n </div>\n {expandedFile === f.filename && (\n <pre className=\"mod-instructions-content\">\n {f.content || <em className=\"muted\">(file missing on disk)</em>}\n </pre>\n )}\n </div>\n ))}\n </div>\n )}\n {instructions.skills.length > 0 && (\n <div className=\"mod-instructions-section\">\n <div className=\"mod-instructions-section-title\">\n <BookOpen size={11} /> Skills ({instructions.skills.length})\n </div>\n {instructions.skills.map((s) => (\n <div key={s.name} className=\"mod-instructions-file\">\n <div\n className=\"mod-instructions-file-head\"\n onClick={() => setExpandedFile((cur) => cur === s.name ? null : s.name)}\n >\n <span className=\"mono\">{s.name}</span>\n <span className=\"muted\" style={{ fontSize: 10 }}>\n installed at {s.fullPath}\n </span>\n </div>\n {expandedFile === s.name && (\n <pre className=\"mod-instructions-content\">\n {s.content || <em className=\"muted\">(file missing on disk)</em>}\n </pre>\n )}\n </div>\n ))}\n </div>\n )}\n {instructions.total === 0 && (\n <div className=\"muted\" style={{ padding: 8, fontSize: 12 }}>\n This mod did not install any instruction files. Mods install instructions by shipping a top-level <code>INSTRUCTIONS.md</code>, an <code>agents/</code> directory, a <code>commands/</code> directory, or a <code>skills/</code> directory.\n </div>\n )}\n <div className=\"mod-instructions-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onReinstallInstructions}>\n <RefreshCw size={11} /> Reinstall from mod folder\n </Button>\n </div>\n </div>\n )}\n </div>\n </Card>\n );\n}\n","// src/views/ModView.tsx — render an installed mod's view (iframe or TSX tab).\n//\n// Mounted as a top-level tab in App.tsx when a mod contributes a view via\n// `entry.view` or `web/index.html`. Mods become first-class nav items\n// alongside Overview, Chat, Mods, etc.\n\nimport { Suspense, lazy, useEffect, useState } from 'react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Button } from '../components/Button';\nimport { Spinner } from '../components/Spinner';\nimport { ExternalLink, Globe, LayoutTemplate, RefreshCw, AlertTriangle } from 'lucide-react';\nimport { api } from '../lib/api';\nimport { useToast } from '../components/Toast';\n\nexport type ModView = {\n id: string;\n modId: string;\n kind: 'iframe' | 'tab';\n label: string;\n description?: string;\n path?: string;\n icon?: string;\n component?: string | null;\n};\n\ntype Props = {\n /** Mod view id, e.g. 'graphify:web'. */\n viewId: string;\n /** Force a refresh of the iframe key — bumped when the user clicks Reload. */\n reloadKey?: number;\n /** Currently active tab id — kept on the Props surface so the parent\n * (App.tsx) doesn't have to know which props the mod view consumes. */\n activeTab?: string;\n setActiveTab: (id: string) => void;\n};\n\nexport function ModView({ viewId, reloadKey, setActiveTab }: Props) {\n const toast = useToast();\n const [view, setView] = useState<ModView | null>(null);\n const [loading, setLoading] = useState(true);\n const [iframeReload, setIframeReload] = useState(0);\n\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.get<{ views: ModView[] }>('/mods/views');\n if (cancelled) return;\n const found = (r.views || []).find((v) => v.id === viewId);\n setView(found || null);\n } catch (err) {\n toast.error(`Failed to load mod view: ${(err as Error).message}`);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => { cancelled = true; };\n }, [viewId, toast]);\n\n if (loading) {\n return <EmptyState title=\"Loading mod view…\" />;\n }\n\n if (!view) {\n return (\n <EmptyState\n title=\"Mod view not found\"\n message={`No view with id \"${viewId}\" is currently installed.`}\n action={<Button onClick={() => setActiveTab('mods')} variant=\"primary\" size=\"sm\">\n Open Mods\n </Button>}\n />\n );\n }\n\n // Iframe view: embed the mod's web/index.html in the dashboard.\n if (view.kind === 'iframe') {\n const src = `/api/mods/${view.modId}/web/index.html?t=${iframeReload + (reloadKey || 0)}`;\n return (\n <div className=\"mod-view-iframe-pane\">\n <div className=\"mod-view-iframe-header\">\n <span className=\"mod-view-iframe-label\">\n <Globe size={14} />\n {view.label}\n <span className=\"muted\" style={{ fontSize: 11, fontWeight: 400 }}>by {view.modId}</span>\n </span>\n <div className=\"mod-view-iframe-actions\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setIframeReload((n) => n + 1)}\n title=\"Reload this view\"\n >\n <RefreshCw size={11} /> Reload\n </Button>\n <a\n href={src}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"icon-btn\"\n title=\"Open in new tab\"\n >\n <ExternalLink size={12} />\n </a>\n </div>\n </div>\n <iframe\n key={iframeReload + (reloadKey || 0)}\n src={src}\n className=\"mod-view-iframe\"\n title={view.label}\n />\n </div>\n );\n }\n\n // v3.20.5 — Tab view (React component shipped with the mod). The\n // component is dynamically imported from /api/mods/<id>/views/<file>.\n // Mods ship a pre-built ES module (default export = React component).\n // If the registry declared a component path, we lazy-load it.\n if (view.component) {\n // Capture the narrowed values into locals so the lazy() closure\n // doesn't have to re-check nullability through `view`.\n const componentPath: string = view.component;\n const modId: string = view.modId;\n const ModComponent = lazy(() =>\n import(\n /* @vite-ignore */\n `/api/mods/${encodeURIComponent(modId)}/views/${encodeURIComponent(componentPath)}`\n ).then((m) => ({ default: m.default ?? (() => null) })),\n );\n return (\n <div className=\"mod-view-tab-pane\">\n <div className=\"mod-view-iframe-header\">\n <span className=\"mod-view-iframe-label\">\n <LayoutTemplate size={14} />\n {view.label}\n <span className=\"muted\" style={{ fontSize: 11, fontWeight: 400 }}>by {view.modId}</span>\n </span>\n </div>\n <div className=\"mod-view-tab-body\">\n <ErrorBoundary modId={view.modId} component={view.component}>\n <Suspense fallback={<div style={{ padding: 24 }}><Spinner size=\"md\" /> <span className=\"muted\">Loading mod view…</span></div>}>\n <ModComponent />\n </Suspense>\n </ErrorBoundary>\n </div>\n </div>\n );\n }\n\n // Tab kind with no component path — show a placeholder.\n return (\n <Card>\n <CardTitle>\n <LayoutTemplate size={14} /> {view.label}\n </CardTitle>\n <CardMeta>by {view.modId}</CardMeta>\n {view.description && <p className=\"muted\" style={{ marginTop: 8 }}>{view.description}</p>}\n <p className=\"muted\" style={{ fontSize: 12, marginTop: 12 }}>\n This mod declared a tab view but did not provide a component path in views/registry.json.\n Add a <code>component</code> field (e.g. <code>\"MyView.js\"</code>) and ship the file under <code>views/</code>.\n </p>\n <div style={{ marginTop: 12 }}>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => setActiveTab('mods')}>\n Open Mods page\n </Button>\n </div>\n </Card>\n );\n}\n\n/**\n * Minimal error boundary for dynamically imported mod views. Catches\n * a failure to load the module (404, syntax error in the mod's code,\n * React.render-time throw) and renders a clean fallback instead of\n * crashing the dashboard shell.\n */\nimport { Component as ReactComponent, type ReactNode } from 'react';\n\nclass ErrorBoundary extends ReactComponent<\n { children: ReactNode; modId: string; component: string },\n { error: Error | null }\n> {\n state = { error: null as Error | null };\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n override componentDidCatch() {\n /* swallow — error surfaced via state */\n }\n override render() {\n if (this.state.error) {\n return (\n <div className=\"mod-view-error\">\n <AlertTriangle size={16} />\n <strong>Failed to render mod view</strong>\n <div className=\"muted\" style={{ fontSize: 12, marginTop: 6 }}>\n {this.props.modId} → {this.props.component}: {this.state.error.message}\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","// src/views/Schedules.tsx — list, create, edit, run, delete schedules for the active project.\n//\n// v3.9.0 — overhauled with structured DOW/time/TZ pickers, a reusable\n// ScheduleEditorModal that handles both create and edit, a human-readable\n// schedule label on every card, and a timezone-aware next-run display.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n Clock,\n Plus,\n PlayCircle,\n Pencil,\n Trash2,\n RefreshCw,\n History,\n ChevronDown,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { formatRelative } from '../lib/utils';\nimport type { Schedule, Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst TYPES = ['interval', 'cron', 'once'] as const;\nconst ACTIONS = ['command', 'agent', 'webhook'] as const;\n\n// v3.9.0 — Curated IANA timezone list. \"Other…\" lets the operator type\n// any zone croner accepts (the backend passes the string through).\nconst TIMEZONES: Array<{ value: string; label: string }> = [\n { value: 'UTC', label: 'UTC' },\n { value: 'America/New_York', label: 'America/New_York (ET)' },\n { value: 'America/Los_Angeles', label: 'America/Los_Angeles (PT)' },\n { value: 'America/Chicago', label: 'America/Chicago (CT)' },\n { value: 'Europe/London', label: 'Europe/London (UK)' },\n { value: 'Europe/Berlin', label: 'Europe/Berlin (CET)' },\n { value: 'Asia/Tokyo', label: 'Asia/Tokyo (JST)' },\n];\n\nconst MINUTE_OPTIONS = Array.from({ length: 12 }, (_, i) => i * 5); // 0,5,10,…55\nconst HOUR_OPTIONS = Array.from({ length: 24 }, (_, h) => ({\n value: h,\n label: h === 0 ? '12 AM' : h < 12 ? `${h} AM` : h === 12 ? '12 PM' : `${h - 12} PM`,\n}));\nconst DOW_OPTIONS: Array<{ value: string; label: string }> = [\n { value: '*', label: 'Every day' },\n { value: '0', label: 'Sunday' },\n { value: '1', label: 'Monday' },\n { value: '2', label: 'Tuesday' },\n { value: '3', label: 'Wednesday' },\n { value: '4', label: 'Thursday' },\n { value: '5', label: 'Friday' },\n { value: '6', label: 'Saturday' },\n];\n\nconst INTERVAL_UNITS: Array<{ value: string; label: string }> = [\n { value: 's', label: 'seconds' },\n { value: 'm', label: 'minutes' },\n { value: 'h', label: 'hours' },\n { value: 'd', label: 'days' },\n];\n\n/** Best-effort cron parser — used to pre-populate the structured form\n * when editing a schedule the user originally saved with raw cron text. */\nfunction parseCronFields(expr: string): { minute: number; hour: number; dow: string } | null {\n if (typeof expr !== 'string') return null;\n const parts = expr.trim().split(/\\s+/);\n if (parts.length !== 5) return null;\n const [m, h, , , dow] = parts;\n // We only pre-populate when every field is a literal — wildcards and\n // ranges (other than `*`) leave the form blank rather than guess.\n const minNum = parseInt(m, 10);\n const hourNum = parseInt(h, 10);\n if (!Number.isFinite(minNum) || !Number.isFinite(hourNum)) return null;\n if (m !== String(minNum) || h !== String(hourNum)) return null;\n const dowClean = dow === '*' ? '*' : parseInt(dow, 10);\n if (dowClean === null || (dow !== '*' && !Number.isFinite(dowClean))) return null;\n return { minute: minNum, hour: hourNum, dow: dow === '*' ? '*' : String(dowClean) };\n}\n\nfunction parseIntervalParts(s: string): { n: number; unit: string } | null {\n if (typeof s !== 'string') return null;\n const m = /^(\\d+)\\s*([smhd])$/i.exec(s.trim());\n if (!m) return null;\n return { n: parseInt(m[1], 10), unit: m[2].toLowerCase() };\n}\n\ntype EditorState = {\n name: string;\n type: 'cron' | 'interval' | 'once';\n cronMinute: number;\n cronHour: number;\n cronDow: string;\n showAdvanced: boolean;\n rawCron: string;\n intervalN: number;\n intervalUnit: string;\n onceAt: string; // datetime-local string\n timezone: string;\n customTimezone: string;\n actionType: 'command' | 'agent' | 'webhook';\n actionTarget: string;\n actionPrompt: string;\n skipIfBudgetLow: boolean;\n maxConcurrent: number;\n enabled: boolean;\n humanLabel: string;\n};\n\nfunction buildInitialState(initial?: Schedule): EditorState {\n if (!initial) {\n return {\n name: '',\n type: 'cron',\n cronMinute: 0,\n cronHour: 13,\n cronDow: '0',\n showAdvanced: false,\n rawCron: '0 13 * * 0',\n intervalN: 30,\n intervalUnit: 'm',\n onceAt: '',\n timezone: 'UTC',\n customTimezone: '',\n actionType: 'agent',\n actionTarget: '',\n actionPrompt: '',\n skipIfBudgetLow: false,\n maxConcurrent: 6,\n enabled: true,\n humanLabel: '',\n };\n }\n const parsed = initial.type === 'cron' ? parseCronFields(initial.schedule) : null;\n const parsedInterval = initial.type === 'interval' ? parseIntervalParts(initial.schedule) : null;\n const tz = initial.timezone || 'UTC';\n const tzKnown = TIMEZONES.some((t) => t.value === tz);\n return {\n name: initial.name || '',\n type: initial.type,\n cronMinute: parsed?.minute ?? 0,\n cronHour: parsed?.hour ?? 9,\n cronDow: parsed?.dow ?? '*',\n showAdvanced: !parsed,\n rawCron: initial.schedule,\n intervalN: parsedInterval?.n ?? 30,\n intervalUnit: parsedInterval?.unit ?? 'm',\n onceAt: initial.type === 'once' ? toDatetimeLocal(initial.schedule) : '',\n timezone: tzKnown ? tz : 'Other…',\n customTimezone: tzKnown ? '' : tz,\n actionType: initial.action.type,\n actionTarget: initial.action.target || '',\n actionPrompt: initial.action.prompt || '',\n skipIfBudgetLow: !!initial.budgetCheck?.skipIfBudgetLow,\n maxConcurrent: Number.isFinite(initial.budgetCheck?.maxConcurrent)\n ? initial.budgetCheck!.maxConcurrent!\n : 6,\n enabled: initial.enabled !== false,\n humanLabel: '',\n };\n}\n\nfunction toDatetimeLocal(iso: string): string {\n if (!iso) return '';\n try {\n const d = new Date(iso);\n if (Number.isNaN(d.getTime())) return '';\n // datetime-local needs YYYY-MM-DDTHH:mm in *local* time.\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;\n } catch {\n return '';\n }\n}\n\n/** Compose the cron / interval / once schedule string + a human label. */\nfunction composeSchedule(s: EditorState): { schedule: string; humanLabel: string } {\n if (s.type === 'cron') {\n if (s.showAdvanced) {\n return { schedule: s.rawCron.trim(), humanLabel: s.humanLabel || s.rawCron.trim() };\n }\n const cron = `${s.cronMinute} ${s.cronHour} * * ${s.cronDow}`;\n const dowName = DOW_OPTIONS.find((d) => d.value === s.cronDow)?.label || '';\n const hourLabel = HOUR_OPTIONS.find((h) => h.value === s.cronHour)?.label || `${s.cronHour}`;\n const minute = String(s.cronMinute).padStart(2, '0');\n const human =\n dowName === 'Every day'\n ? `Every day at ${hourLabel.replace(' ', '')} (min ${minute})`\n : `Every ${dowName} at ${hourLabel.replace(' ', '')} (min ${minute})`;\n return { schedule: cron, humanLabel: s.humanLabel || human };\n }\n if (s.type === 'interval') {\n const unit = INTERVAL_UNITS.find((u) => u.value === s.intervalUnit)?.label || s.intervalUnit;\n const schedule = `${s.intervalN}${s.intervalUnit}`;\n return {\n schedule,\n humanLabel: s.humanLabel || `Every ${s.intervalN} ${unit}`,\n };\n }\n // once\n if (!s.onceAt) return { schedule: '', humanLabel: s.humanLabel || '' };\n const iso = new Date(s.onceAt).toISOString();\n return {\n schedule: iso,\n humanLabel: s.humanLabel || new Date(s.onceAt).toLocaleString(),\n };\n}\n\nexport function Schedules({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [schedules, setSchedules] = useState<Schedule[]>(snapshot.schedules || []);\n const [loading, setLoading] = useState(!snapshot.schedules);\n\n const reload = async () => {\n try {\n const r = await api.get<{ schedules: Schedule[]; projectId: string | null }>(\n '/projects/active/schedules',\n );\n setSchedules(r.schedules || []);\n } catch (err) {\n toast.error(`Schedules load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n if (snapshot.schedules?.length || snapshot.schedules) {\n setSchedules(snapshot.schedules || []);\n setLoading(false);\n return;\n }\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [snapshot.schedules]);\n\n const openEditor = (initial?: Schedule) => {\n modal.open({\n title: initial ? `Edit schedule: ${initial.name}` : 'New schedule',\n width: 640,\n children: (\n <ScheduleEditorModal\n initial={initial}\n onClose={modal.close}\n onSubmitted={async (saved) => {\n setSchedules((cur) => {\n const idx = cur.findIndex((s) => s.id === saved.id);\n if (idx === -1) return [...cur, saved];\n const copy = cur.slice();\n copy[idx] = saved;\n return copy;\n });\n toast.success(initial ? 'Schedule updated.' : 'Schedule created.');\n modal.close();\n await refreshSnapshot();\n }}\n onError={(msg) => toast.error(msg)}\n />\n ),\n });\n };\n\n const onRun = async (s: Schedule) => {\n try {\n const r = await api.post<{ ok: boolean; schedule: Schedule; runResult: { error?: string; stdout?: string } }>(\n `/schedules/${encodeURIComponent(s.id)}/run`,\n );\n toast.success(r.ok ? 'Schedule ran.' : `Run failed: ${r.runResult?.error || 'unknown'}`);\n await reload();\n } catch (err) {\n toast.error(`Run failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (s: Schedule) => {\n if (!confirm(`Delete schedule \"${s.name}\"?`)) return;\n try {\n await api.del(`/schedules/${encodeURIComponent(s.id)}`);\n setSchedules((cur) => cur.filter((x) => x.id !== s.id));\n toast.success('Schedule deleted.');\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n if (loading) {\n return (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n );\n }\n\n return (\n <div className=\"view view-schedules\">\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Clock size={18} /> Schedules ({schedules.length})\n </h2>\n <p className=\"view-subtitle\">\n Recurring tasks for the active project: <strong>{snapshot.activeProject?.name || '(none)'}</strong>.\n Service daemon runs them at the right time.\n </p>\n </div>\n <div className=\"view-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={reload}>\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={() => openEditor()}>\n <Plus size={14} /> New schedule\n </Button>\n </div>\n </header>\n\n {schedules.length === 0 ? (\n <EmptyState\n icon={<Clock size={32} />}\n title=\"No schedules\"\n message={\n snapshot.activeProject\n ? 'Add a schedule to run commands, webhooks, or agent tasks on a cron / interval / one-shot basis.'\n : 'Activate a project first to scope schedules.'\n }\n />\n ) : (\n <div className=\"schedule-grid\">\n {schedules.map((s) => (\n <Card key={s.id} className=\"schedule-card\">\n <div className=\"schedule-card-head\">\n <div>\n <CardTitle>{s.name}</CardTitle>\n <CardMeta>\n <code>{s.type}</code> ·{' '}\n <span title={s.schedule}>{humanizeSchedule(s) || s.schedule}</span>\n {s.timezone && s.timezone !== 'UTC' ? <> · <code>{s.timezone}</code></> : null}\n {' · '}\n <span className={s.enabled ? 'status-on' : 'status-neutral'}>\n {s.enabled ? 'enabled' : 'disabled'}\n </span>\n </CardMeta>\n </div>\n <div className=\"schedule-card-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={() => openEditor(s)}>\n <Pencil size={12} /> Edit\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => onRun(s)}>\n <PlayCircle size={12} /> Run now\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn icon-btn-danger\"\n aria-label=\"Delete\"\n title=\"Delete\"\n onClick={() => onDelete(s)}\n >\n <Trash2 size={12} />\n </button>\n </div>\n </div>\n <div className=\"schedule-card-action\">\n <span className=\"muted\">action:</span>{' '}\n <code>\n {s.action.type} {s.action.target}\n </code>\n {s.action.type === 'agent' && s.action.prompt && (\n <div className=\"schedule-card-prompt\">\n <span className=\"muted\">prompt:</span> {s.action.prompt}\n </div>\n )}\n </div>\n {s.budgetCheck?.skipIfBudgetLow && (\n <div className=\"schedule-card-budget\">\n <span className=\"muted\">budget gate:</span>{' '}\n skip if concurrent ≥ {s.budgetCheck.maxConcurrent ?? 6}\n </div>\n )}\n <div className=\"schedule-card-times\">\n <div>\n <span className=\"muted\">last</span>{' '}\n {s.lastRun ? formatRelative(s.lastRun) : '—'}\n {s.lastResult && (\n <span className={`tag ${resultTagClass(s.lastResult)}`}>{s.lastResult}</span>\n )}\n {s.lastError && (\n <span className=\"muted schedule-card-error\" title={s.lastError}>\n {' '}— {truncate(s.lastError, 80)}\n </span>\n )}\n </div>\n <div>\n <span className=\"muted\">next</span>{' '}\n {s.nextRun ? (\n <span title={new Date(s.nextRun).toISOString()}>\n {formatNextRun(s.nextRun, s.timezone)}\n </span>\n ) : (\n '—'\n )}\n {s.nextRun && (\n <span className=\"muted\"> · {formatRelative(s.nextRun)}</span>\n )}\n </div>\n </div>\n {s.history && s.history.length > 0 && (\n <details className=\"schedule-card-history\">\n <summary>\n <History size={12} /> {s.history.length} run{s.history.length === 1 ? '' : 's'}\n </summary>\n <ul>\n {s.history.slice(-10).reverse().map((h, i) => (\n <li key={i}>\n <span className=\"tabular-nums muted\">{formatRelative(h.ts)}</span>{' '}\n <span className={`tag ${resultTagClass(h.result)}`}>{h.result}</span>\n {h.error && <span className=\"muted\"> — {truncate(h.error, 80)}</span>}\n </li>\n ))}\n </ul>\n </details>\n )}\n </Card>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Editor modal */\n/* ------------------------------------------------------------------ */\n\nfunction ScheduleEditorModal({\n initial,\n onClose,\n onSubmitted,\n onError,\n}: {\n initial?: Schedule;\n onClose: () => void;\n onSubmitted: (saved: Schedule) => void | Promise<void>;\n onError: (msg: string) => void;\n}) {\n const [state, setState] = useState<EditorState>(() => buildInitialState(initial));\n const [submitting, setSubmitting] = useState(false);\n const tzSelectValue = useMemo(() => {\n if (TIMEZONES.some((t) => t.value === state.timezone)) return state.timezone;\n return 'Other…';\n }, [state.timezone]);\n\n const update = <K extends keyof EditorState>(key: K, value: EditorState[K]) => {\n setState((cur) => ({ ...cur, [key]: value }));\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n const trimmedName = state.name.trim();\n if (!trimmedName) {\n onError('Name is required.');\n return;\n }\n const composed = composeSchedule(state);\n if (!composed.schedule) {\n onError('Schedule value is required.');\n return;\n }\n if (!state.actionTarget.trim()) {\n onError('Action target is required.');\n return;\n }\n const tz = state.timezone === 'Other…' ? state.customTimezone.trim() : state.timezone;\n const actionPayload: Record<string, unknown> = {\n type: state.actionType,\n target: state.actionTarget.trim(),\n };\n if (state.actionType === 'agent' && state.actionPrompt.trim()) {\n actionPayload.prompt = state.actionPrompt.trim();\n }\n const payload: Record<string, unknown> = {\n name: trimmedName,\n type: state.type,\n schedule: composed.schedule,\n timezone: tz || 'UTC',\n action: actionPayload,\n budgetCheck: {\n maxConcurrent: state.maxConcurrent,\n skipIfBudgetLow: state.skipIfBudgetLow,\n },\n enabled: state.enabled,\n };\n setSubmitting(true);\n try {\n const saved = initial\n ? await api.put<Schedule>(`/schedules/${encodeURIComponent(initial.id)}`, payload)\n : await api.post<Schedule>('/schedules', payload);\n await onSubmitted(saved);\n } catch (err) {\n onError(`${initial ? 'Update' : 'Create'} failed: ${(err as Error).message}`);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <form className=\"schedule-form\" onSubmit={handleSubmit}>\n <label className=\"field-label\">Name</label>\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Weekly code review\"\n value={state.name}\n onChange={(e) => update('name', e.target.value)}\n autoFocus\n />\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Type</label>\n <select\n className=\"select\"\n value={state.type}\n onChange={(e) => update('type', e.target.value as EditorState['type'])}\n >\n {TYPES.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n </div>\n\n {state.type === 'cron' && (\n <div className=\"schedule-cron-group\">\n {!state.showAdvanced && (\n <>\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Day of week</label>\n <select\n className=\"select\"\n value={state.cronDow}\n onChange={(e) => update('cronDow', e.target.value)}\n >\n {DOW_OPTIONS.map((d) => (\n <option key={d.value} value={d.value}>{d.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Hour</label>\n <select\n className=\"select\"\n value={String(state.cronHour)}\n onChange={(e) => update('cronHour', parseInt(e.target.value, 10))}\n >\n {HOUR_OPTIONS.map((h) => (\n <option key={h.value} value={String(h.value)}>{h.label}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Minute</label>\n <select\n className=\"select\"\n value={String(state.cronMinute)}\n onChange={(e) => update('cronMinute', parseInt(e.target.value, 10))}\n >\n {MINUTE_OPTIONS.map((m) => (\n <option key={m} value={String(m)}>{String(m).padStart(2, '0')}</option>\n ))}\n </select>\n </div>\n </div>\n </>\n )}\n {state.showAdvanced && (\n <div className=\"task-form-field\">\n <label className=\"field-label\">Cron expression</label>\n <input\n className=\"input\"\n type=\"text\"\n value={state.rawCron}\n onChange={(e) => update('rawCron', e.target.value)}\n placeholder=\"0 13 * * 0\"\n />\n </div>\n )}\n <button\n type=\"button\"\n className=\"link-btn\"\n onClick={() => update('showAdvanced', !state.showAdvanced)}\n >\n <ChevronDown\n size={12}\n style={{\n transform: state.showAdvanced ? 'rotate(180deg)' : 'none',\n transition: 'transform 0.15s',\n }}\n />\n {state.showAdvanced ? 'Hide advanced' : 'Advanced (raw cron)'}\n </button>\n </div>\n )}\n\n {state.type === 'interval' && (\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Every</label>\n <input\n className=\"input\"\n type=\"number\"\n min={1}\n value={state.intervalN}\n onChange={(e) => update('intervalN', parseInt(e.target.value, 10) || 1)}\n />\n </div>\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Unit</label>\n <select\n className=\"select\"\n value={state.intervalUnit}\n onChange={(e) => update('intervalUnit', e.target.value)}\n >\n {INTERVAL_UNITS.map((u) => (\n <option key={u.value} value={u.value}>{u.label}</option>\n ))}\n </select>\n </div>\n </div>\n )}\n\n {state.type === 'once' && (\n <div className=\"task-form-field\">\n <label className=\"field-label\">Run at</label>\n <input\n className=\"input\"\n type=\"datetime-local\"\n value={state.onceAt}\n onChange={(e) => update('onceAt', e.target.value)}\n />\n </div>\n )}\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">Timezone</label>\n <select\n className=\"select\"\n value={tzSelectValue}\n onChange={(e) => update('timezone', e.target.value)}\n >\n {TIMEZONES.map((t) => (\n <option key={t.value} value={t.value}>{t.label}</option>\n ))}\n <option value=\"Other…\">Other…</option>\n </select>\n </div>\n {state.timezone === 'Other…' && (\n <div className=\"task-form-field\" style={{ flex: 1 }}>\n <label className=\"field-label\">IANA name</label>\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Europe/Paris\"\n value={state.customTimezone}\n onChange={(e) => update('customTimezone', e.target.value)}\n />\n </div>\n )}\n </div>\n\n <div className=\"task-form-row\">\n <div className=\"task-form-field\">\n <label className=\"field-label\">Action</label>\n <select\n className=\"select\"\n value={state.actionType}\n onChange={(e) => update('actionType', e.target.value as EditorState['actionType'])}\n >\n {ACTIONS.map((t) => (\n <option key={t} value={t}>{t}</option>\n ))}\n </select>\n </div>\n <div className=\"task-form-field\" style={{ flex: 2 }}>\n <label className=\"field-label\">Target</label>\n <input\n className=\"input\"\n type=\"text\"\n placeholder={state.actionType === 'webhook' ? 'https://...' : state.actionType === 'agent' ? 'agent name or task ref' : 'echo hi'}\n value={state.actionTarget}\n onChange={(e) => update('actionTarget', e.target.value)}\n />\n </div>\n </div>\n\n {state.actionType === 'agent' && (\n <div className=\"task-form-field\">\n <label className=\"field-label\">Prompt (what to send the agent)</label>\n <textarea\n className=\"input\"\n rows={3}\n placeholder=\"Review open PRs for stale code review comments and nudge reviewers.\"\n value={state.actionPrompt}\n onChange={(e) => update('actionPrompt', e.target.value)}\n />\n </div>\n )}\n\n <fieldset className=\"schedule-budget-card\">\n <legend>Budget pre-flight</legend>\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={state.skipIfBudgetLow}\n onChange={(e) => update('skipIfBudgetLow', e.target.checked)}\n />\n <span>Skip this run when too many background tasks are already running.</span>\n </label>\n <div className=\"task-form-field\">\n <label className=\"field-label\">Max concurrent bg tasks</label>\n <input\n className=\"input\"\n type=\"number\"\n min={1}\n max={64}\n value={state.maxConcurrent}\n onChange={(e) => update('maxConcurrent', parseInt(e.target.value, 10) || 6)}\n disabled={!state.skipIfBudgetLow}\n />\n </div>\n </fieldset>\n\n <label className=\"checkbox-row\">\n <input\n type=\"checkbox\"\n checked={state.enabled}\n onChange={(e) => update('enabled', e.target.checked)}\n />\n <span>Enabled</span>\n </label>\n\n <div className=\"modal-footer-actions\">\n <Button variant=\"ghost\" type=\"button\" onClick={onClose} disabled={submitting}>\n Cancel\n </Button>\n <Button variant=\"primary\" type=\"submit\" disabled={submitting}>\n {initial ? 'Save' : 'Create'}\n </Button>\n </div>\n </form>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction humanizeSchedule(s: Schedule): string {\n if (s.type !== 'cron') return s.schedule;\n const parsed = parseCronFields(s.schedule);\n if (!parsed) return s.schedule;\n const dowName = DOW_OPTIONS.find((d) => d.value === parsed.dow)?.label || '';\n const hourLabel = HOUR_OPTIONS.find((h) => h.value === parsed.hour)?.label || `${parsed.hour}`;\n const minute = String(parsed.minute).padStart(2, '0');\n if (dowName === 'Every day') return `Every day at ${hourLabel} :${minute}`;\n return `Every ${dowName} at ${hourLabel} :${minute}`;\n}\n\nfunction formatNextRun(iso: string, tz?: string | null): string {\n try {\n return new Date(iso).toLocaleString(undefined, {\n timeZone: tz || undefined,\n weekday: 'long',\n hour: 'numeric',\n minute: '2-digit',\n month: 'short',\n day: 'numeric',\n });\n } catch {\n return new Date(iso).toLocaleString();\n }\n}\n\nfunction resultTagClass(result: string): string {\n if (result === 'success') return 'tag-success';\n if (result === 'skipped') return 'tag-warning';\n return 'tag-error';\n}\n\nfunction truncate(s: string, max: number): string {\n if (s.length <= max) return s;\n return s.slice(0, max - 1) + '…';\n}","// src/views/Skills.tsx — v4.0.0 skills browser: scans all local SKILL.md sources.\nimport React, { useEffect, useMemo, useState } from 'react';\nimport {\n Sparkles,\n Search,\n RefreshCw,\n ExternalLink,\n XCircle,\n BookOpen,\n Folder,\n Users,\n Package,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { useModal } from '../components/Modal';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\nimport type { Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype Skill = {\n name: string;\n description: string;\n source: 'shipped' | 'user' | 'project';\n path: string;\n body?: string;\n};\n\ntype Tab = { id: 'all' | 'shipped' | 'user' | 'project'; label: string; icon: typeof Sparkles };\n\nconst TABS: Tab[] = [\n { id: 'all', label: 'All', icon: Sparkles },\n { id: 'shipped', label: 'Shipped', icon: Package },\n { id: 'user', label: 'User', icon: Users },\n { id: 'project', label: 'Project', icon: Folder },\n];\n\nconst SOURCE_LABEL: Record<string, string> = {\n shipped: 'Shipped',\n user: 'User',\n project: 'Project',\n};\n\nconst SOURCE_ICON: Record<string, typeof Package> = {\n shipped: Package,\n user: Users,\n project: Folder,\n};\n\nfunction SkillsInner({ snapshot, refreshSnapshot }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [skills, setSkills] = useState<Skill[]>([]);\n const [counts, setCounts] = useState({ shipped: 0, user: 0, project: 0, all: 0 });\n const [loading, setLoading] = useState(true);\n const [activeTab, setActiveTab] = useState<'all' | 'shipped' | 'user' | 'project'>('all');\n const [searchQ, setSearchQ] = useState('');\n const [searchResults, setSearchResults] = useState<Skill[] | null>(null);\n const [searching, setSearching] = useState(false);\n\n const reload = async () => {\n setLoading(true);\n try {\n const d = await api.get<{ skills: Skill[]; counts: Record<string, number> }>('/skills');\n setSkills(d.skills || []);\n setCounts({ shipped: d.counts?.shipped ?? 0, user: d.counts?.user ?? 0, project: d.counts?.project ?? 0, all: (d.skills || []).length });\n } catch (err) {\n toast.error(`Skills load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => { reload(); }, []);\n\n // Debounced search\n useEffect(() => {\n if (!searchQ.trim()) {\n setSearchResults(null);\n return;\n }\n setSearching(true);\n const id = setTimeout(async () => {\n try {\n const d = await api.get<{ results: Skill[] }>(\n `/skills/search?q=${encodeURIComponent(searchQ.trim())}`,\n );\n setSearchResults(d.results || []);\n } catch (err) {\n toast.error(`Search failed: ${(err as Error).message}`);\n } finally {\n setSearching(false);\n }\n }, 280);\n return () => clearTimeout(id);\n }, [searchQ]);\n\n const displayed = useMemo<Skill[]>(() => {\n if (searchResults !== null) return searchResults;\n if (activeTab === 'all') return skills;\n return skills.filter((s) => s.source === activeTab);\n }, [skills, activeTab, searchResults]);\n\n const onRefresh = async () => {\n try {\n await api.post('/skills/refresh', {});\n toast.success('Skills refreshed.');\n await reload();\n } catch (err) {\n toast.error(`Refresh failed: ${(err as Error).message}`);\n }\n };\n\n const onShowDetail = async (skill: Skill) => {\n try {\n const full = await api.get<Skill>(\n `/skills/${encodeURIComponent(skill.source)}/${encodeURIComponent(skill.name)}`,\n );\n modal.open({\n title: full.name,\n width: 640,\n children: (\n <div className=\"skill-detail\">\n <div className=\"skill-detail-meta\">\n <span className=\"skill-source-badge\" data-source={full.source}>\n {SOURCE_LABEL[full.source] || full.source}\n </span>\n <code className=\"mono text-sm muted\">{full.path}</code>\n </div>\n {full.description && (\n <p className=\"skill-detail-desc\">{full.description}</p>\n )}\n {full.body && (\n <div className=\"skill-detail-body\">\n <pre className=\"skill-body-pre\">{full.body}</pre>\n </div>\n )}\n </div>\n ),\n footer: (\n <Button variant=\"ghost\" onClick={() => modal.close()}>Close</Button>\n ),\n });\n } catch {\n // Fallback: show what we already have\n modal.open({\n title: skill.name,\n width: 560,\n children: (\n <div className=\"skill-detail\">\n <div className=\"skill-detail-meta\">\n <span className=\"skill-source-badge\" data-source={skill.source}>\n {SOURCE_LABEL[skill.source] || skill.source}\n </span>\n <code className=\"mono text-sm muted\">{skill.path}</code>\n </div>\n {skill.description && (\n <p className=\"skill-detail-desc\">{skill.description}</p>\n )}\n </div>\n ),\n footer: (\n <Button variant=\"ghost\" onClick={() => modal.close()}>Close</Button>\n ),\n });\n }\n };\n\n return (\n <div className=\"view view-skills\">\n {/* ── Header ─────────────────────────────────────────────────────── */}\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Sparkles size={18} /> Skills\n </h2>\n <p className=\"view-subtitle\">\n Browse all available skills — shipped, user, and project-local.\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"search-input\">\n <Search size={14} />\n <input\n className=\"input\"\n type=\"text\"\n placeholder=\"Search skills…\"\n value={searchQ}\n onChange={(e) => setSearchQ(e.target.value)}\n />\n {searchQ && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Clear search\"\n onClick={() => setSearchQ('')}\n >\n <XCircle size={12} />\n </button>\n )}\n </div>\n <Button variant=\"secondary\" size=\"sm\" onClick={onRefresh}>\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n </header>\n\n {/* ── Source tabs ────────────────────────────────────────────────── */}\n {!searchQ.trim() && (\n <div className=\"skills-tabs\">\n {TABS.map((tab) => {\n const Icon = tab.icon;\n const count = tab.id === 'all'\n ? counts.all\n : counts[tab.id as keyof typeof counts] ?? 0;\n return (\n <button\n key={tab.id}\n type=\"button\"\n className={cn('skills-tab', activeTab === tab.id && 'skills-tab-active')}\n onClick={() => setActiveTab(tab.id)}\n >\n <Icon size={14} />\n <span>{tab.label}</span>\n <span className=\"skills-tab-count\">{count}</span>\n </button>\n );\n })}\n </div>\n )}\n\n {/* ── Search results ───────────────────────────────────────────── */}\n {searchQ.trim() && (\n <section className=\"skills-section\">\n <h3 className=\"skills-section-title\">\n <Search size={14} /> Search results\n {searching && <Spinner size=\"sm\" />}\n </h3>\n {searching ? (\n <div className=\"skills-grid\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"skill-card skill-card-skeleton\" />\n ))}\n </div>\n ) : searchResults && searchResults.length === 0 ? (\n <EmptyState\n icon={<Search size={28} />}\n title=\"No matches\"\n message={`No skills match \"${searchQ}\".`}\n />\n ) : (\n <div className=\"skills-grid\">\n {(searchResults || []).map((s, i) => (\n <SkillCard\n key={`search-${i}`}\n skill={s}\n onShow={() => onShowDetail(s)}\n searchQ={searchQ}\n />\n ))}\n </div>\n )}\n </section>\n )}\n\n {/* ── Skills grid (tab view) ───────────────────────────────────── */}\n {!searchQ.trim() && (\n <section className=\"skills-section\">\n {loading ? (\n <div className=\"view-loading\"><Spinner size=\"lg\" /></div>\n ) : displayed.length === 0 ? (\n <EmptyState\n icon={<BookOpen size={28} />}\n title=\"No skills here\"\n message={\n activeTab === 'all'\n ? 'No skills found. Install skills with the skills CLI or add SKILL.md files to a skills directory.'\n : `No skills in the ${SOURCE_LABEL[activeTab]} tab.`\n }\n />\n ) : (\n <div className=\"skills-grid\">\n {displayed.map((s, i) => (\n <SkillCard\n key={`${s.source}-${s.name}-${i}`}\n skill={s}\n onShow={() => onShowDetail(s)}\n />\n ))}\n </div>\n )}\n </section>\n )}\n\n {/* ── Footer ────────────────────────────────────────────────────── */}\n {!searchQ.trim() && (\n <footer className=\"view-footer\">\n <span className=\"text-sm muted\">\n Skills are discovered from{' '}\n <code>~/.opencode/skills/</code>,{' '}\n <code>~/.agents/skills/</code>,{' '}\n <code>bizar-dash/skills/</code>, and project-local directories.\n </span>\n </footer>\n )}\n </div>\n );\n}\n\n// ── SkillCard ─────────────────────────────────────────────────────────────────\n\nfunction SkillCard({\n skill,\n onShow,\n searchQ = '',\n}: {\n skill: Skill;\n onShow: () => void;\n searchQ?: string;\n}) {\n const Icon = SOURCE_ICON[skill.source] || Package;\n const desc = skill.description\n ? skill.description.length > 200\n ? skill.description.slice(0, 200) + '…'\n : skill.description\n : 'No description.';\n\n return (\n <Card variant=\"elevated\" interactive className=\"skill-card\">\n <div className=\"skill-card-head\">\n <div\n className=\"skill-card-icon\"\n style={{ background: `color-mix(in srgb, var(--accent) 12%, transparent)` }}\n >\n <Icon size={18} />\n </div>\n <div className=\"skill-card-title-area\">\n <div className=\"skill-card-title\">\n {highlightMatch(skill.name, searchQ)}\n </div>\n <span className=\"skill-source-badge\" data-source={skill.source}>\n {SOURCE_LABEL[skill.source] || skill.source}\n </span>\n </div>\n </div>\n <p className=\"skill-card-desc\">{desc}</p>\n <div className=\"skill-card-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onShow}>\n <ExternalLink size={12} /> View\n </Button>\n </div>\n </Card>\n );\n}\n\n/** Simple substring highlight — wraps matched term in <mark>. */\nfunction highlightMatch(text: string, q: string): React.ReactNode {\n if (!q.trim()) return text;\n const idx = text.toLowerCase().indexOf(q.toLowerCase());\n if (idx < 0) return text;\n return (\n <>\n {text.slice(0, idx)}\n <mark className=\"skill-highlight\">{text.slice(idx, idx + q.length)}</mark>\n {text.slice(idx + q.length)}\n </>\n );\n}\nexport const Skills = React.memo(SkillsInner);\n","// src/web/views/memory/MemoryOverview.tsx — Memory tab overview panel (KPIs + sub-system pills).\nimport { useEffect, useState } from 'react';\nimport {\n Activity,\n Brain,\n CheckCircle2,\n Database,\n FileText,\n GitBranch,\n RefreshCw,\n Search,\n ShieldCheck,\n Sparkles,\n XCircle,\n AlertTriangle,\n} from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { Spinner } from '../../components/Spinner';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { formatTime, cn } from '../../lib/utils';\n\nexport type HealthResponse = {\n score: number;\n status: 'healthy' | 'degraded' | 'unhealthy' | 'unconfigured';\n checks: Array<{ name: string; pass: boolean; detail: string }>;\n message: string;\n};\n\nexport type VaultStats = {\n exists: boolean;\n vaultRoot: string;\n mode: string;\n noteCount: number;\n totalSize: number;\n folderCount: number;\n folders: string[];\n lastModified: number | null;\n gitClean: boolean | null;\n gitBranch: string | null;\n};\n\ntype MemoryStatus = {\n initialized: boolean;\n mode?: string;\n projectId?: string;\n vaultRoot?: string;\n branch?: string;\n gitClean?: boolean | null;\n noteCount?: number;\n lastSecretScan?: string | null;\n};\n\ntype LightragStats = {\n running: boolean;\n pid: number | null;\n host: string;\n port: number;\n indexedApprox: number;\n queryCountLast24h: number;\n lastReindexAt: string | null;\n avgResponseMs?: number | null;\n noteCount?: number;\n};\n\ntype StorageStats = {\n total: number;\n breakdown: Array<{ name: string; path: string; size: number }>;\n};\n\nexport type MemoryOverviewData = {\n health: HealthResponse;\n vault: VaultStats;\n lightrag: {\n running: boolean;\n pid: number | null;\n host: string;\n port: number;\n indexedApprox: number;\n queryCountLast24h: number;\n lastReindexAt: string | null;\n };\n storage: {\n total: number;\n breakdown: Array<{ name: string; path: string; size: number }>;\n };\n};\n\ntype Props = {\n refreshKey: number;\n onRefresh: () => void;\n setActiveSubPanel: (panel: 'overview' | 'lightrag' | 'obsidian' | 'git' | 'semantic' | 'config') => void;\n};\n\nexport function MemoryOverview({ refreshKey, onRefresh, setActiveSubPanel }: Props) {\n const toast = useToast();\n const [data, setData] = useState<MemoryOverviewData | null>(null);\n const [loading, setLoading] = useState(true);\n\n const reload = async (signal?: AbortSignal) => {\n setLoading(true);\n try {\n const [health, status, lightrag, storage] = await Promise.all([\n api.get<HealthResponse>('/memory/health', signal).catch(() => null),\n api.get<MemoryStatus>('/memory/status', signal).catch(() => null),\n api.get<LightragStats>('/memory/lightrag/stats', signal).catch(() => null),\n api.get<StorageStats>('/memory/storage', signal).catch(() => null),\n ]);\n setData({\n health: health || {\n score: 0,\n status: 'unconfigured',\n checks: [],\n message: 'memory not initialised',\n },\n vault: {\n exists: !!status?.initialized,\n vaultRoot: status?.vaultRoot || '',\n mode: status?.mode || 'local-only',\n noteCount: status?.noteCount || 0,\n totalSize: storage?.total || 0,\n folderCount: 0,\n folders: [],\n lastModified: null,\n gitClean: status?.gitClean ?? null,\n gitBranch: status?.branch || null,\n },\n lightrag: lightrag || {\n running: false,\n pid: null,\n host: '127.0.0.1',\n port: 9621,\n indexedApprox: 0,\n queryCountLast24h: 0,\n lastReindexAt: null,\n },\n storage: storage || { total: 0, breakdown: [] },\n });\n } catch (err) {\n toast.error(`Memory overview failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n const ctrl = new AbortController();\n void reload(ctrl.signal);\n return () => ctrl.abort();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n if (loading && !data) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading memory overview…</p>\n </div>\n );\n }\n if (!data) {\n return <div className=\"muted\">No memory data available.</div>;\n }\n\n const { health, vault, lightrag, storage } = data;\n const scoreColor =\n health.score >= 80 ? 'var(--success)' :\n health.score >= 50 ? 'var(--warning)' :\n 'var(--error)';\n\n return (\n <div className=\"memory-overview\">\n {/* ── Health score hero ─────────────────────────────────────────── */}\n <Card variant=\"elevated\" className=\"memory-health-hero\">\n <div className=\"memory-health-score\" style={{ borderColor: scoreColor }}>\n <span className=\"memory-health-score-value\" style={{ color: scoreColor }}>\n {health.score}\n </span>\n <span className=\"memory-health-score-label\">/ 100</span>\n </div>\n <div className=\"memory-health-meta\">\n <h3 className=\"memory-health-title\">\n <Activity size={16} />\n Memory health ·{' '}\n <span style={{ color: scoreColor }}>{health.status}</span>\n </h3>\n <p className=\"memory-health-message\">{health.message}</p>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRefresh}>\n <RefreshCw size={12} /> Refresh\n </Button>\n </div>\n </Card>\n\n {/* ── Source pills ─────────────────────────────────────────────── */}\n <div className=\"memory-source-pills\">\n <button\n type=\"button\"\n className=\"memory-source-pill\"\n onClick={() => setActiveSubPanel('lightrag')}\n >\n <Brain size={14} />\n <span>LightRAG</span>\n <span className={cn('memory-source-pill-status', lightrag.running ? 'on' : 'off')}>\n {lightrag.running ? 'running' : 'stopped'}\n </span>\n </button>\n <button\n type=\"button\"\n className=\"memory-source-pill\"\n onClick={() => setActiveSubPanel('obsidian')}\n >\n <FileText size={14} />\n <span>Obsidian Vault</span>\n <span className={cn('memory-source-pill-status', vault.exists ? 'on' : 'off')}>\n {vault.noteCount} notes\n </span>\n </button>\n <button\n type=\"button\"\n className=\"memory-source-pill\"\n onClick={() => setActiveSubPanel('git')}\n >\n <GitBranch size={14} />\n <span>Git Sync</span>\n <span className={cn(\n 'memory-source-pill-status',\n vault.gitClean === null ? 'na' : vault.gitClean ? 'on' : 'warn',\n )}>\n {vault.gitClean === null ? '—' : vault.gitClean ? 'clean' : 'dirty'}\n </span>\n </button>\n <button\n type=\"button\"\n className=\"memory-source-pill\"\n onClick={() => setActiveSubPanel('semantic')}\n >\n <Search size={14} />\n <span>Semantic Search</span>\n <span className=\"memory-source-pill-status na\">cross-source</span>\n </button>\n </div>\n\n {/* ── KPI grid ─────────────────────────────────────────────────── */}\n <div className=\"memory-stat-grid\">\n <StatCard\n icon={<Brain size={16} />}\n label=\"LightRAG\"\n value={lightrag.running ? `running · ${lightrag.queryCountLast24h} q/24h` : 'stopped'}\n sub={lightrag.running ? `${lightrag.indexedApprox} indexed chunks` : 'start from the LightRAG panel'}\n onClick={() => setActiveSubPanel('lightrag')}\n />\n <StatCard\n icon={<FileText size={16} />}\n label=\"Obsidian\"\n value={`${vault.noteCount} notes`}\n sub={vault.folderCount > 0 ? `${vault.folderCount} folders` : 'no folders yet'}\n onClick={() => setActiveSubPanel('obsidian')}\n />\n <StatCard\n icon={<GitBranch size={16} />}\n label=\"Git\"\n value={vault.gitBranch ? `branch ${vault.gitBranch}` : 'local-only'}\n sub={\n vault.gitClean === null ? 'not configured' :\n vault.gitClean ? 'clean working tree' :\n 'dirty — commit or pull'\n }\n onClick={() => setActiveSubPanel('git')}\n />\n <StatCard\n icon={<Database size={16} />}\n label=\"Storage\"\n value={formatBytes(storage.total)}\n sub={storage.breakdown.length > 0\n ? `${storage.breakdown.length} dirs tracked`\n : 'no memory data on disk'}\n />\n <StatCard\n icon={<Sparkles size={16} />}\n label=\"Last reindex\"\n value={lightrag.lastReindexAt ? formatTime(lightrag.lastReindexAt) : 'never'}\n sub=\"lightrag ingest\"\n onClick={() => setActiveSubPanel('lightrag')}\n />\n <StatCard\n icon={<ShieldCheck size={16} />}\n label=\"Health\"\n value={`${health.score}/100`}\n sub={health.status}\n onClick={() => setActiveSubPanel('config')}\n />\n </div>\n\n {/* ── Health checks detail ─────────────────────────────────────── */}\n {health.checks.length > 0 && (\n <Card>\n <CardTitle>Health checks</CardTitle>\n <CardMeta>Composite score across all memory subsystems</CardMeta>\n <ul className=\"memory-check-list\">\n {health.checks.map((c) => (\n <li key={c.name} className=\"memory-check-row\">\n <span className=\"memory-check-icon\">\n {c.pass\n ? <CheckCircle2 size={14} style={{ color: 'var(--success)' }} />\n : c.name.includes('secrets') || c.name.includes('schema')\n ? <AlertTriangle size={14} style={{ color: 'var(--warning)' }} />\n : <XCircle size={14} style={{ color: 'var(--error)' }} />}\n </span>\n <span className=\"memory-check-name\">{c.name}</span>\n <span className=\"memory-check-detail muted\">{c.detail}</span>\n </li>\n ))}\n </ul>\n </Card>\n )}\n </div>\n );\n}\n\nfunction StatCard({\n icon,\n label,\n value,\n sub,\n onClick,\n}: {\n icon: React.ReactNode;\n label: string;\n value: string;\n sub: string;\n onClick?: () => void;\n}) {\n const Comp = onClick ? 'button' : 'div';\n return (\n <Comp\n type={onClick ? 'button' : undefined}\n onClick={onClick}\n className={cn('memory-stat-card', onClick && 'memory-stat-card-clickable')}\n >\n <div className=\"memory-stat-icon\">{icon}</div>\n <div className=\"memory-stat-body\">\n <div className=\"memory-stat-label\">{label}</div>\n <div className=\"memory-stat-value\">{value}</div>\n <div className=\"memory-stat-sub muted\">{sub}</div>\n </div>\n </Comp>\n );\n}\n\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`;\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;\n if (n < 1024 * 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n return `${(n / (1024 * 1024 * 1024)).toFixed(2)} GB`;\n}","// src/web/views/memory/LightragPanel.tsx — LightRAG controls, stats, query.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n Brain,\n CheckCircle2,\n Database,\n Loader2,\n Play,\n Power,\n PowerOff,\n RefreshCw,\n RotateCw,\n Search as SearchIcon,\n Sparkles,\n XCircle,\n Zap,\n} from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Spinner } from '../../components/Spinner';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { formatTime, cn } from '../../lib/utils';\n\ntype Stats = {\n running: boolean;\n pid: number | null;\n host: string;\n port: number;\n workingDir: string;\n lastReindexAt: string | null;\n lastReindexOk: boolean | null;\n lastReindexInserted: number | null;\n lastReindexFailed: number | null;\n noteCount: number;\n indexedApprox: number;\n queryCountLast24h: number;\n avgResponseMs: number | null;\n};\n\ntype Config = {\n enabled: boolean;\n host: string;\n port: number;\n workingDir: string;\n llmBinding: string;\n embeddingBinding: string;\n llmModel: string;\n embeddingModel: string;\n};\n\ntype Props = { refreshKey: number };\n\nexport function LightragPanel({ refreshKey }: Props) {\n const toast = useToast();\n const [stats, setStats] = useState<Stats | null>(null);\n const [config, setConfig] = useState<Config | null>(null);\n const [logTail, setLogTail] = useState<string[]>([]);\n const [loading, setLoading] = useState(true);\n const [busy, setBusy] = useState<string | null>(null);\n const [query, setQuery] = useState('');\n const [queryResult, setQueryResult] = useState<{ ok: boolean; text: string } | null>(null);\n\n const reload = async () => {\n setLoading(true);\n try {\n const [s, c, log] = await Promise.all([\n api.get<Stats>('/memory/lightrag/stats').catch(() => null),\n api.get<{ lightrag?: Config }>('/memory/config').then((r) => r?.lightrag || null).catch(() => null),\n api.get<{ lines: string[] }>('/memory/lightrag/log').catch(() => ({ lines: [] })),\n ]);\n setStats(s);\n setConfig(c);\n setLogTail(log?.lines || []);\n } catch (err) {\n toast.error(`LightRAG status failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n const runCommand = async (key: string, fn: () => Promise<unknown>, successMsg: string) => {\n setBusy(key);\n try {\n await fn();\n toast.success(successMsg);\n await reload();\n } catch (err) {\n toast.error(`${key} failed: ${(err as Error).message}`);\n } finally {\n setBusy(null);\n }\n };\n\n const onStart = () => runCommand('start', () => api.post('/memory/lightrag/start', {}), 'LightRAG starting…');\n const onStop = () => runCommand('stop', () => api.post('/memory/lightrag/stop', {}), 'LightRAG stopping…');\n const onRestart = async () => {\n setBusy('restart');\n try {\n await api.post('/memory/lightrag/stop', {}).catch(() => {});\n await new Promise((r) => setTimeout(r, 600));\n await api.post('/memory/lightrag/start', {});\n toast.success('LightRAG restarted.');\n await reload();\n } catch (err) {\n toast.error(`Restart failed: ${(err as Error).message}`);\n } finally {\n setBusy(null);\n }\n };\n const onReindex = () => runCommand('reindex', () => api.post('/memory/lightrag/reindex', {}), 'Reindex complete.');\n const onRebuild = () => runCommand('rebuild', () => api.post('/memory/lightrag/rebuild-graph', {}), 'Graph rebuilt.');\n\n const onQuery = async () => {\n if (!query.trim()) return;\n setBusy('query');\n try {\n const r = await api.get<{ ok: boolean; q: string; semantic?: { ok: boolean; response?: unknown; error?: string } }>(\n `/memory/query?q=${encodeURIComponent(query)}&topK=8`,\n );\n const text = r?.semantic?.response\n ? (typeof r.semantic.response === 'string'\n ? r.semantic.response\n : JSON.stringify(r.semantic.response))\n : (r?.semantic?.error || 'No response');\n setQueryResult({ ok: !!r?.semantic?.ok, text });\n } catch (err) {\n setQueryResult({ ok: false, text: (err as Error).message });\n } finally {\n setBusy(null);\n }\n };\n\n if (loading && !stats) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading LightRAG status…</p>\n </div>\n );\n }\n if (!stats) {\n return <div className=\"muted\">No LightRAG data available.</div>;\n }\n\n return (\n <div className=\"memory-panel-content\">\n {/* ── Status header ───────────────────────────────────────────── */}\n <Card variant=\"elevated\">\n <CardTitle>\n <Brain size={14} />\n LightRAG\n <span className={cn('memory-source-pill-status', stats.running ? 'on' : 'off')}>\n {stats.running ? 'running' : 'stopped'}\n </span>\n </CardTitle>\n <CardMeta>\n {stats.running\n ? <>PID <code>{stats.pid}</code> · {stats.host}:{stats.port}</>\n : <>Server is not running. Start it from the controls below.</>}\n </CardMeta>\n <div className=\"memory-action-row\">\n <Button variant=\"primary\" size=\"sm\" onClick={onStart} disabled={!!busy || stats.running}>\n {busy === 'start' ? <Loader2 size={12} className=\"memory-spin\" /> : <Play size={12} />}\n Start\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onStop} disabled={!!busy || !stats.running}>\n {busy === 'stop' ? <Loader2 size={12} className=\"memory-spin\" /> : <PowerOff size={12} />}\n Stop\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onRestart} disabled={!!busy}>\n {busy === 'restart' ? <Loader2 size={12} className=\"memory-spin\" /> : <Power size={12} />}\n Restart\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onReindex} disabled={!!busy}>\n {busy === 'reindex' ? <Loader2 size={12} className=\"memory-spin\" /> : <RefreshCw size={12} />}\n Reindex all\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onRebuild} disabled={!!busy} title=\"Wipe working dir + reindex from scratch\">\n {busy === 'rebuild' ? <Loader2 size={12} className=\"memory-spin\" /> : <RotateCw size={12} />}\n Rebuild graph\n </Button>\n </div>\n </Card>\n\n {/* ── Stat cards ─────────────────────────────────────────────── */}\n <div className=\"memory-stat-grid\">\n <StatBox icon={<Database size={14} />} label=\"Indexed chunks (approx)\" value={String(stats.indexedApprox)} />\n <StatBox icon={<FileTextCount n={stats.noteCount} />} label=\"Notes in vault\" value={String(stats.noteCount)} />\n <StatBox icon={<Zap size={14} />} label=\"Queries last 24h\" value={String(stats.queryCountLast24h)} />\n <StatBox\n icon={<Sparkles size={14} />}\n label=\"Avg response\"\n value={stats.avgResponseMs !== null ? `${stats.avgResponseMs} ms` : '—'}\n />\n <StatBox\n icon={stats.lastReindexOk ? <CheckCircle2 size={14} /> : stats.lastReindexOk === false ? <XCircle size={14} /> : <RefreshCw size={14} />}\n label=\"Last reindex\"\n value={stats.lastReindexAt ? formatTime(stats.lastReindexAt) : 'never'}\n sub={stats.lastReindexInserted !== null\n ? `${stats.lastReindexInserted} inserted${stats.lastReindexFailed ? `, ${stats.lastReindexFailed} failed` : ''}`\n : undefined}\n />\n </div>\n\n {/* ── Quick search ───────────────────────────────────────────── */}\n <Card>\n <CardTitle>\n <SearchIcon size={14} /> Quick search\n </CardTitle>\n <CardMeta>Send a natural-language query to the LightRAG index.</CardMeta>\n <div className=\"memory-search-row\">\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"e.g. how does the memory service write notes?\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onQuery();\n }}\n disabled={busy === 'query'}\n />\n <Button variant=\"primary\" onClick={onQuery} disabled={busy === 'query' || !query.trim()}>\n {busy === 'query' ? <Loader2 size={12} className=\"memory-spin\" /> : <SearchIcon size={12} />}\n Query\n </Button>\n </div>\n {queryResult && (\n <div className={cn('memory-query-result', queryResult.ok ? 'ok' : 'err')}>\n <pre className=\"mono text-sm\">{queryResult.text}</pre>\n </div>\n )}\n </Card>\n\n {/* ── Config snapshot ────────────────────────────────────────── */}\n {config && (\n <Card>\n <CardTitle>Configuration</CardTitle>\n <CardMeta>Effective values from <code>.bizar/memory.json</code> + env defaults.</CardMeta>\n <dl className=\"memory-config-row\">\n <dt>LLM binding</dt>\n <dd><code>{config.llmBinding}</code> · <code>{config.llmModel}</code></dd>\n <dt>Embedding</dt>\n <dd><code>{config.embeddingBinding}</code> · <code>{config.embeddingModel}</code></dd>\n <dt>Host</dt>\n <dd><code>{config.host}:{config.port}</code></dd>\n <dt>Working dir</dt>\n <dd className=\"mono ellipsis\" title={config.workingDir}>{config.workingDir}</dd>\n </dl>\n </Card>\n )}\n\n {/* ── Log tail ───────────────────────────────────────────────── */}\n {logTail.length > 0 && (\n <Card>\n <CardTitle>\n <RefreshCw size={14} /> Server log (tail)\n </CardTitle>\n <CardMeta>Last {logTail.length} lines from <code>lightrag.log</code></CardMeta>\n <pre className=\"memory-log-tail mono text-xs\">\n {logTail.join('\\n')}\n </pre>\n </Card>\n )}\n </div>\n );\n}\n\nfunction StatBox({\n icon,\n label,\n value,\n sub,\n}: {\n icon: React.ReactNode;\n label: string;\n value: string;\n sub?: string;\n}) {\n return (\n <div className=\"memory-stat-card\">\n <div className=\"memory-stat-icon\">{icon}</div>\n <div className=\"memory-stat-body\">\n <div className=\"memory-stat-label\">{label}</div>\n <div className=\"memory-stat-value\">{value}</div>\n {sub && <div className=\"memory-stat-sub muted\">{sub}</div>}\n </div>\n </div>\n );\n}\n\nfunction FileTextCount({ n }: { n: number }) {\n // Stable icon — use FileText with a small badge\n return (\n <span style={{ position: 'relative', display: 'inline-block' }}>\n <SearchIcon size={14} />\n <span className=\"memory-mini-badge\">{n}</span>\n </span>\n );\n}","// src/web/views/memory/ObsidianPanel.tsx — vault browser + note CRUD + backlinks.\nimport { useEffect, useMemo, useState } from 'react';\nimport {\n ChevronDown,\n ChevronRight,\n FilePlus,\n FileText,\n Folder,\n Loader2,\n Pencil,\n RefreshCw,\n Search as SearchIcon,\n Trash2,\n X,\n} from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Spinner } from '../../components/Spinner';\nimport { useToast } from '../../components/Toast';\nimport { useModal } from '../../components/Modal';\nimport { api } from '../../lib/api';\nimport { formatTime, formatRelative, cn } from '../../lib/utils';\n\ntype Note = {\n relPath: string;\n frontmatter: Record<string, unknown>;\n body: string;\n raw: string;\n mtime: number;\n size: number;\n schemaValid: boolean;\n};\n\ntype TreeNode = {\n name: string;\n path: string;\n type: 'folder' | 'note';\n size?: number;\n mtime?: number;\n children?: TreeNode[];\n};\n\ntype Backlink = {\n fromRelPath: string;\n fromTitle: string;\n snippet: string;\n mtime: number;\n};\n\ntype Props = { refreshKey: number };\n\nexport function ObsidianPanel({ refreshKey }: Props) {\n const toast = useToast();\n const modal = useModal();\n const [notes, setNotes] = useState<Note[]>([]);\n const [tree, setTree] = useState<TreeNode | null>(null);\n const [loading, setLoading] = useState(true);\n const [searchQ, setSearchQ] = useState('');\n const [searchResults, setSearchResults] = useState<Note[] | null>(null);\n const [searching, setSearching] = useState(false);\n const [selected, setSelected] = useState<string | null>(null);\n const [backlinks, setBacklinks] = useState<Backlink[]>([]);\n\n const reload = async () => {\n setLoading(true);\n try {\n const [n, t] = await Promise.all([\n api.get<{ notes: Note[] }>('/memory/notes').catch(() => ({ notes: [] })),\n api.get<{ tree: TreeNode | null }>('/memory/obsidian/tree').catch(() => ({ tree: null })),\n ]);\n setNotes(n.notes || []);\n setTree(t.tree);\n if (selected && !n.notes?.find((x) => x.relPath === selected)) {\n setSelected(null);\n setBacklinks([]);\n }\n } catch (err) {\n toast.error(`Vault load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n // Debounced search\n useEffect(() => {\n if (!searchQ.trim()) {\n setSearchResults(null);\n return;\n }\n setSearching(true);\n const t = setTimeout(async () => {\n try {\n const r = await api.get<{ results: Array<{ relPath: string; snippet: string; score: number }> }>(\n `/memory/search?q=${encodeURIComponent(searchQ)}&limit=50`,\n );\n const pathSet = new Set((r.results || []).map((x) => x.relPath));\n setSearchResults(notes.filter((n) => pathSet.has(n.relPath)));\n } catch (err) {\n toast.error(`Search failed: ${(err as Error).message}`);\n } finally {\n setSearching(false);\n }\n }, 240);\n return () => clearTimeout(t);\n }, [searchQ, notes, toast]);\n\n const onSelect = async (relPath: string) => {\n setSelected(relPath);\n try {\n const r = await api.get<{ backlinks: Backlink[] }>(\n `/memory/obsidian/backlinks?note=${encodeURIComponent(relPath)}`,\n );\n setBacklinks(r.backlinks || []);\n } catch {\n setBacklinks([]);\n }\n };\n\n const onCreate = () => {\n modal.open({\n title: 'New note',\n width: 720,\n children: (\n <NoteEditor\n mode=\"create\"\n onSave={async (relPath, frontmatter, body) => {\n try {\n await api.post('/memory/notes', { path: relPath, frontmatter, body });\n toast.success(`Created ${relPath}.`);\n modal.close();\n await reload();\n onSelect(relPath);\n } catch (err) {\n toast.error(`Create failed: ${(err as Error).message}`);\n }\n }}\n onCancel={() => modal.close()}\n />\n ),\n });\n };\n\n const onEdit = async (relPath: string) => {\n try {\n const note = await api.get<Note>(`/memory/notes/${relPath.split('/').map(encodeURIComponent).join('/')}`);\n modal.open({\n title: `Edit ${relPath}`,\n width: 720,\n children: (\n <NoteEditor\n mode=\"edit\"\n initial={{ relPath: note.relPath, frontmatter: note.frontmatter, body: note.body }}\n onSave={async (rp, frontmatter, body) => {\n try {\n await api.put(`/memory/notes/${rp.split('/').map(encodeURIComponent).join('/')}`, {\n frontmatter, body,\n });\n toast.success(`Saved ${rp}.`);\n modal.close();\n await reload();\n onSelect(rp);\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n }\n }}\n onCancel={() => modal.close()}\n />\n ),\n });\n } catch (err) {\n toast.error(`Load failed: ${(err as Error).message}`);\n }\n };\n\n const onDelete = async (relPath: string) => {\n if (!confirm(`Delete ${relPath}? This cannot be undone.`)) return;\n try {\n await api.del(`/memory/notes/${relPath.split('/').map(encodeURIComponent).join('/')}`);\n toast.success(`Deleted ${relPath}.`);\n if (selected === relPath) setSelected(null);\n await reload();\n } catch (err) {\n toast.error(`Delete failed: ${(err as Error).message}`);\n }\n };\n\n const sortedNotes = useMemo(() => {\n return [...notes].sort((a, b) => b.mtime - a.mtime);\n }, [notes]);\n\n const displayed = searchResults ?? sortedNotes;\n\n if (loading && !notes.length) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading vault…</p>\n </div>\n );\n }\n\n return (\n <div className=\"memory-panel-content memory-obsidian-grid\">\n {/* ── Folder tree (left) ─────────────────────────────────────── */}\n <Card variant=\"outlined\" className=\"memory-tree-card\">\n <CardTitle>\n <Folder size={14} /> Folders\n </CardTitle>\n <CardMeta>{tree ? `${countFolders(tree)} folder(s)` : 'no vault'}</CardMeta>\n <div className=\"memory-tree-body\">\n {tree ? <TreeView node={tree} depth={0} onSelect={onSelect} selected={selected} /> : null}\n </div>\n </Card>\n\n {/* ── Note list (center) ─────────────────────────────────────── */}\n <div className=\"memory-obsidian-list-col\">\n <div className=\"memory-list-toolbar\">\n <div className=\"search-input\">\n <SearchIcon size={14} />\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"Search notes…\"\n value={searchQ}\n onChange={(e) => setSearchQ(e.target.value)}\n />\n {searchQ && (\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => setSearchQ('')}\n aria-label=\"Clear search\"\n >\n <X size={12} />\n </button>\n )}\n </div>\n <Button variant=\"primary\" size=\"sm\" onClick={onCreate}>\n <FilePlus size={12} /> New note\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={reload} title=\"Refresh\">\n <RefreshCw size={12} />\n </Button>\n </div>\n {searching && <div className=\"muted text-sm\">Searching…</div>}\n {displayed.length === 0 ? (\n <EmptyState\n icon={<FileText size={28} />}\n title=\"No notes\"\n message={\n notes.length === 0\n ? 'No notes in this vault yet. Click \"New note\" to create one.'\n : `No notes match \"${searchQ}\".`\n }\n />\n ) : (\n <ul className=\"memory-note-list\">\n {displayed.map((n) => (\n <li\n key={n.relPath}\n className={cn('memory-note-card', selected === n.relPath && 'memory-note-card-active')}\n >\n <button\n type=\"button\"\n className=\"memory-note-card-main\"\n onClick={() => onSelect(n.relPath)}\n >\n <div className=\"memory-note-card-title\">\n <FileText size={12} />\n <span>{titleOf(n)}</span>\n </div>\n <div className=\"memory-note-card-meta\">\n <code className=\"muted\">{n.relPath}</code>\n <span className=\"muted\">· {formatRelative(n.mtime)}</span>\n {!n.schemaValid && <span className=\"memory-pill-warn\">schema</span>}\n </div>\n </button>\n <div className=\"memory-note-card-actions\">\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => onEdit(n.relPath)}\n aria-label={`Edit ${n.relPath}`}\n title=\"Edit\"\n >\n <Pencil size={12} />\n </button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => onDelete(n.relPath)}\n aria-label={`Delete ${n.relPath}`}\n title=\"Delete\"\n >\n <Trash2 size={12} />\n </button>\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n {/* ── Detail pane (right) ────────────────────────────────────── */}\n <div className=\"memory-obsidian-detail-col\">\n {selected ? (\n <NoteDetail relPath={selected} onClose={() => setSelected(null)} />\n ) : (\n <EmptyState\n icon={<FileText size={28} />}\n title=\"Pick a note\"\n message=\"Select a note from the list to view its content, frontmatter, and backlinks.\"\n />\n )}\n </div>\n </div>\n );\n}\n\n// ── Tree view ─────────────────────────────────────────────────────────────\n\n/**\n * Coerce a note's title to a renderable string. frontmatter.title is\n * `unknown` per the schema, so this guards against non-string values.\n */\nfunction titleOf(n: Note): string {\n const t = n.frontmatter?.title;\n if (typeof t === 'string' && t.trim()) return t;\n return n.relPath.replace(/\\.md$/i, '');\n}\n\nfunction TreeView({\n node,\n depth,\n onSelect,\n selected,\n}: {\n node: TreeNode;\n depth: number;\n onSelect: (path: string) => void;\n selected: string | null;\n}) {\n const [open, setOpen] = useState(depth < 2);\n if (node.type === 'note') {\n return (\n <button\n type=\"button\"\n className={cn('memory-tree-node memory-tree-node-note', selected === node.path && 'memory-tree-node-active')}\n style={{ paddingLeft: 6 + depth * 12 }}\n onClick={() => onSelect(node.path)}\n >\n <FileText size={11} />\n <span>{node.name}</span>\n </button>\n );\n }\n return (\n <div className=\"memory-tree-folder\">\n <button\n type=\"button\"\n className=\"memory-tree-node memory-tree-node-folder\"\n style={{ paddingLeft: 6 + depth * 12 }}\n onClick={() => setOpen((v) => !v)}\n >\n {open ? <ChevronDown size={11} /> : <ChevronRight size={11} />}\n <Folder size={11} />\n <span>{node.name || 'vault'}</span>\n {node.children && node.children.length > 0 && (\n <span className=\"muted text-xs\">{node.children.length}</span>\n )}\n </button>\n {open && node.children && (\n <div className=\"memory-tree-children\">\n {node.children.map((c, i) => (\n <TreeView key={`${c.path}-${i}`} node={c} depth={depth + 1} onSelect={onSelect} selected={selected} />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction countFolders(node: TreeNode): number {\n if (node.type === 'note') return 0;\n return 1 + (node.children || []).reduce((acc, c) => acc + countFolders(c), 0);\n}\n\n// ── Note detail ───────────────────────────────────────────────────────────\n\nfunction NoteDetail({ relPath, onClose }: { relPath: string; onClose: () => void }) {\n const [note, setNote] = useState<Note | null>(null);\n const [backlinks, setBacklinks] = useState<Backlink[]>([]);\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n (async () => {\n try {\n const [n, b] = await Promise.all([\n api.get<Note>(`/memory/notes/${relPath.split('/').map(encodeURIComponent).join('/')}`),\n api.get<{ backlinks: Backlink[] }>(`/memory/obsidian/backlinks?note=${encodeURIComponent(relPath)}`),\n ]);\n if (cancelled) return;\n setNote(n);\n setBacklinks(b.backlinks || []);\n } catch {\n if (!cancelled) setNote(null);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n return () => { cancelled = true; };\n }, [relPath]);\n\n if (loading) {\n return (\n <div className=\"view-loading\"><Spinner size=\"sm\" /></div>\n );\n }\n if (!note) return <div className=\"muted\">Note not found.</div>;\n\n const tags = Array.isArray(note.frontmatter?.tags) ? note.frontmatter.tags : [];\n const links = Array.isArray(note.frontmatter?.links) ? note.frontmatter.links : [];\n\n return (\n <div className=\"memory-note-detail\">\n <div className=\"memory-note-detail-head\">\n <h3>{titleOf(note)}</h3>\n <button type=\"button\" className=\"icon-btn\" onClick={onClose} aria-label=\"Close\">\n <X size={12} />\n </button>\n </div>\n <div className=\"memory-note-detail-meta\">\n <code>{relPath}</code>\n <span className=\"muted\">· modified {formatTime(note.mtime)}</span>\n </div>\n {tags.length > 0 && (\n <div className=\"memory-tag-row\">\n {tags.map((t, i) => (\n <span key={i} className=\"memory-tag\">{String(t)}</span>\n ))}\n </div>\n )}\n <pre className=\"memory-note-body mono text-sm\">{note.body}</pre>\n {backlinks.length > 0 && (\n <div className=\"memory-backlinks\">\n <h4>Backlinks</h4>\n <ul>\n {backlinks.map((b) => (\n <li key={b.fromRelPath}>\n <code>{b.fromRelPath}</code>\n <p className=\"muted text-sm\">{b.snippet}</p>\n </li>\n ))}\n </ul>\n </div>\n )}\n {links.length > 0 && (\n <div className=\"memory-backlinks\">\n <h4>Forward links</h4>\n <ul>\n {links.map((l, i) => (\n <li key={i}><code>{String(l)}</code></li>\n ))}\n </ul>\n </div>\n )}\n </div>\n );\n}\n\n// ── Note editor modal body ────────────────────────────────────────────────\n\nfunction NoteEditor({\n mode,\n initial,\n onSave,\n onCancel,\n}: {\n mode: 'create' | 'edit';\n initial?: { relPath: string; frontmatter: Record<string, unknown>; body: string };\n onSave: (relPath: string, frontmatter: Record<string, unknown>, body: string) => void | Promise<void>;\n onCancel: () => void;\n}) {\n const [relPath, setRelPath] = useState(initial?.relPath || 'untitled.md');\n const [frontmatterYaml, setFrontmatterYaml] = useState(\n initial?.frontmatter ? yamlStringify(initial.frontmatter) : 'title: \"\"\\ntags: []\\n',\n );\n const [body, setBody] = useState(initial?.body || '');\n const [busy, setBusy] = useState(false);\n const toast = useToast();\n\n const onSubmit = async () => {\n if (!relPath.endsWith('.md')) {\n toast.error('Path must end in .md');\n return;\n }\n let fm: Record<string, unknown>;\n try {\n fm = yamlParse(frontmatterYaml) || {};\n } catch (err) {\n toast.error(`Frontmatter parse failed: ${(err as Error).message}`);\n return;\n }\n setBusy(true);\n try {\n await onSave(relPath, fm, body);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div className=\"memory-editor-modal\">\n <label className=\"field-label\">Path</label>\n <input\n type=\"text\"\n className=\"input mono\"\n value={relPath}\n onChange={(e) => setRelPath(e.target.value)}\n disabled={mode === 'edit'}\n placeholder=\"notes/example.md\"\n />\n <label className=\"field-label\" style={{ marginTop: 12 }}>Frontmatter (YAML)</label>\n <textarea\n className=\"memory-editor-textarea mono text-sm\"\n rows={6}\n value={frontmatterYaml}\n onChange={(e) => setFrontmatterYaml(e.target.value)}\n />\n <label className=\"field-label\" style={{ marginTop: 12 }}>Body (Markdown)</label>\n <textarea\n className=\"memory-editor-textarea mono text-sm\"\n rows={14}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n />\n <div className=\"modal-footer-actions\" style={{ marginTop: 12 }}>\n <Button variant=\"ghost\" onClick={onCancel} disabled={busy}>Cancel</Button>\n <Button variant=\"primary\" onClick={onSubmit} disabled={busy}>\n {busy && <Loader2 size={12} className=\"memory-spin\" />}\n {mode === 'create' ? 'Create' : 'Save'}\n </Button>\n </div>\n </div>\n );\n}\n\n// ── Tiny YAML helpers (avoid pulling a 100kB lib into the bundle) ────────\n\nfunction yamlStringify(obj: Record<string, unknown>): string {\n // Best-effort: dump top-level scalar / list / nested-map fields.\n // Good enough for the note editor — the server re-validates anyway.\n const lines: string[] = [];\n for (const [k, v] of Object.entries(obj)) {\n if (v === null || v === undefined) continue;\n if (Array.isArray(v)) {\n if (v.length === 0) { lines.push(`${k}: []`); continue; }\n lines.push(`${k}:`);\n for (const item of v) lines.push(` - ${yamlScalar(item)}`);\n } else if (typeof v === 'object') {\n lines.push(`${k}:`);\n for (const [kk, vv] of Object.entries(v as Record<string, unknown>)) {\n lines.push(` ${kk}: ${yamlScalar(vv)}`);\n }\n } else {\n lines.push(`${k}: ${yamlScalar(v)}`);\n }\n }\n return lines.join('\\n');\n}\n\nfunction yamlScalar(v: unknown): string {\n if (typeof v === 'string') {\n if (/[:#\\n\"']/.test(v) || v === '') return JSON.stringify(v);\n return v;\n }\n if (typeof v === 'number' || typeof v === 'boolean') return String(v);\n return JSON.stringify(v);\n}\n\nfunction yamlParse(s: string): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n const lines = s.split(/\\r?\\n/);\n let i = 0;\n while (i < lines.length) {\n const line = lines[i];\n if (!line.trim() || line.trim().startsWith('#')) { i++; continue; }\n const m = line.match(/^([A-Za-z_][\\w-]*):\\s*(.*)$/);\n if (!m) { i++; continue; }\n const [, key, rest] = m;\n if (rest === '') {\n // Nested mapping or list follows.\n const block: Record<string, unknown> = {};\n const list: unknown[] = [];\n let isList = false;\n let isMap = false;\n while (i + 1 < lines.length) {\n const next = lines[i + 1];\n if (!next.startsWith(' ')) break;\n if (next.startsWith(' - ')) {\n isList = true;\n list.push(parseScalar(next.slice(4)));\n i++;\n } else {\n isMap = true;\n const nm = next.match(/^ ([A-Za-z_][\\w-]*):\\s*(.*)$/);\n if (nm) {\n block[nm[1]] = parseScalar(nm[2]);\n }\n i++;\n }\n }\n out[key] = isList && !isMap ? list : (isMap ? block : {});\n } else {\n out[key] = parseScalar(rest);\n }\n i++;\n }\n return out;\n}\n\nfunction parseScalar(v: string): unknown {\n const t = v.trim();\n if (t === '') return '';\n if (t === 'true') return true;\n if (t === 'false') return false;\n if (t === 'null' || t === '~') return null;\n if (/^-?\\d+$/.test(t)) return parseInt(t, 10);\n if (/^-?\\d+\\.\\d+$/.test(t)) return parseFloat(t);\n if ((t.startsWith('\"') && t.endsWith('\"')) || (t.startsWith(\"'\") && t.endsWith(\"'\"))) {\n return t.slice(1, -1);\n }\n return t;\n}","// src/web/views/memory/GitSyncPanel.tsx — git status, pull/push/commit/fetch, diff viewer.\nimport { useEffect, useState } from 'react';\nimport {\n ArrowDown,\n ArrowUp,\n CheckCircle2,\n GitBranch,\n GitCommit,\n GitMerge,\n GitPullRequest,\n Loader2,\n RefreshCw,\n Settings,\n} from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { Spinner } from '../../components/Spinner';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { formatTime, cn } from '../../lib/utils';\n\ntype GitStatus = {\n ok: boolean;\n clean?: boolean;\n branch?: string;\n ahead?: number;\n behind?: number;\n modified?: string[];\n untracked?: string[];\n mode?: string;\n};\n\ntype GitDiff = {\n hasDiff: boolean;\n lines: string[];\n files: string[];\n mode: string;\n};\n\ntype Props = { refreshKey: number };\n\nexport function GitSyncPanel({ refreshKey }: Props) {\n const toast = useToast();\n const [status, setStatus] = useState<GitStatus | null>(null);\n const [diff, setDiff] = useState<GitDiff | null>(null);\n const [loading, setLoading] = useState(true);\n const [busy, setBusy] = useState<string | null>(null);\n const [config, setConfig] = useState<{ repoPath?: string; remoteUrl?: string; branch?: string; autoSync?: boolean } | null>(null);\n\n const reload = async () => {\n setLoading(true);\n try {\n const [s, d, g] = await Promise.all([\n api.get<GitStatus>('/memory/git/status').catch(() => null),\n api.get<GitDiff>('/memory/git/diff').catch(() => null),\n api.get<{ config?: { git?: { repoPath?: string; remoteUrl?: string; branch?: string; autoSync?: boolean } } }>(\n '/memory/config/global',\n ).catch(() => null),\n ]);\n setStatus(s);\n setDiff(d);\n setConfig(g?.config?.git || null);\n } catch (err) {\n toast.error(`Git status failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n const run = async (key: string, fn: () => Promise<unknown>, msg: string) => {\n setBusy(key);\n try {\n await fn();\n toast.success(msg);\n await reload();\n } catch (err) {\n toast.error(`${key} failed: ${(err as Error).message}`);\n } finally {\n setBusy(null);\n }\n };\n\n const onPull = () => run('pull', () => api.post('/memory/git/pull', {}), 'Pull complete.');\n const onPush = () => run('push', () => api.post('/memory/git/push', {}), 'Push complete.');\n const onCommit = () => {\n const message = prompt('Commit message:', `[memory-sync] ${new Date().toISOString().slice(0, 10)} vault sync`);\n if (!message) return;\n run('commit', () => api.post('/memory/git/commit', { message }), 'Committed.');\n };\n const onFetch = () => run('fetch', () => api.post('/memory/git/sync', { push: false }), 'Fetch complete.');\n\n if (loading && !status) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading git status…</p>\n </div>\n );\n }\n if (!status) {\n return <div className=\"muted\">No git data available.</div>;\n }\n\n const isLocal = status.mode === 'local-only';\n\n return (\n <div className=\"memory-panel-content\">\n {/* ── Status card ───────────────────────────────────────────── */}\n <Card variant=\"elevated\">\n <CardTitle>\n <GitBranch size={14} /> Git sync\n {isLocal ? (\n <span className=\"memory-source-pill-status na\">local-only</span>\n ) : (\n <span className={cn('memory-source-pill-status', status.clean ? 'on' : 'warn')}>\n {status.clean ? 'clean' : 'dirty'}\n </span>\n )}\n </CardTitle>\n <CardMeta>\n {isLocal\n ? 'Memory is in local-only mode. Configure a shared repo in Settings → Memory to enable git sync.'\n : <>Branch <code>{status.branch || '—'}</code>{status.ahead ? <> · ahead {status.ahead}</> : null}{status.behind ? <> · behind {status.behind}</> : null}</>}\n </CardMeta>\n\n {!isLocal && (\n <div className=\"memory-git-status-row\">\n <Pill ok={status.clean ?? false} label=\"Working tree\" />\n <Pill ok={(status.ahead ?? 0) === 0} label={`Ahead: ${status.ahead ?? 0}`} />\n <Pill ok={(status.behind ?? 0) === 0} label={`Behind: ${status.behind ?? 0}`} />\n <Pill ok={(status.modified?.length ?? 0) === 0} label={`Modified: ${status.modified?.length ?? 0}`} />\n <Pill ok={(status.untracked?.length ?? 0) === 0} label={`Untracked: ${status.untracked?.length ?? 0}`} />\n </div>\n )}\n\n <div className=\"memory-action-row\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onPull} disabled={!!busy || isLocal}>\n {busy === 'pull' ? <Loader2 size={12} className=\"memory-spin\" /> : <ArrowDown size={12} />}\n Pull\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onPush} disabled={!!busy || isLocal}>\n {busy === 'push' ? <Loader2 size={12} className=\"memory-spin\" /> : <ArrowUp size={12} />}\n Push\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onCommit} disabled={!!busy || isLocal}>\n {busy === 'commit' ? <Loader2 size={12} className=\"memory-spin\" /> : <GitCommit size={12} />}\n Commit\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onFetch} disabled={!!busy || isLocal}>\n {busy === 'fetch' ? <Loader2 size={12} className=\"memory-spin\" /> : <GitPullRequest size={12} />}\n Fetch + sync\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={reload} disabled={!!busy}>\n <RefreshCw size={12} /> Refresh\n </Button>\n </div>\n </Card>\n\n {/* ── Repo config snapshot ──────────────────────────────────── */}\n {config && (\n <Card>\n <CardTitle>\n <Settings size={14} /> Repository\n </CardTitle>\n <CardMeta>Snapshot of <code>~/.config/bizar/memory-config.json</code> → git block.</CardMeta>\n <dl className=\"memory-config-row\">\n <dt>Path</dt>\n <dd className=\"mono ellipsis\" title={config.repoPath}>{config.repoPath || '—'}</dd>\n <dt>Remote</dt>\n <dd className=\"mono ellipsis\" title={config.remoteUrl}>{config.remoteUrl || '—'}</dd>\n <dt>Branch</dt>\n <dd><code>{config.branch || 'main'}</code></dd>\n <dt>Auto-sync</dt>\n <dd>{config.autoSync ? 'enabled' : 'disabled'}</dd>\n </dl>\n </Card>\n )}\n\n {/* ── Working-tree diff ─────────────────────────────────────── */}\n <Card>\n <CardTitle>\n <GitMerge size={14} /> Working-tree diff\n </CardTitle>\n <CardMeta>\n {diff?.hasDiff\n ? `${diff.files.length} file(s) changed`\n : 'no working-tree changes'}\n </CardMeta>\n {diff && diff.files.length > 0 && (\n <ul className=\"memory-diff-files\">\n {diff.files.map((f) => (\n <li key={f}>\n <code>{f}</code>\n </li>\n ))}\n </ul>\n )}\n {diff && diff.lines.length > 1 && (\n <pre className=\"memory-log-tail mono text-xs\">\n {diff.lines.slice(0, 400).join('\\n')}\n </pre>\n )}\n </Card>\n </div>\n );\n}\n\nfunction Pill({ ok, label }: { ok: boolean; label: string }) {\n return (\n <span className={cn('memory-git-status-pill', ok ? 'ok' : 'warn')}>\n {ok ? <CheckCircle2 size={11} /> : <Loader2 size={11} className=\"memory-spin\" />}\n {label}\n </span>\n );\n}","// src/web/views/memory/SemanticSearchPanel.tsx — cross-source search (LightRAG + Obsidian).\nimport { useEffect, useMemo, useState } from 'react';\nimport { Brain, FileText, Loader2, Search as SearchIcon, X } from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Spinner } from '../../components/Spinner';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { cn } from '../../lib/utils';\n\ntype Result = {\n source: 'lightrag' | 'obsidian';\n relPath: string | null;\n snippet: string;\n score: number;\n mtime: number | null;\n raw?: unknown;\n error?: string;\n};\n\ntype Props = { refreshKey: number };\n\nexport function SemanticSearchPanel({ refreshKey }: Props) {\n const toast = useToast();\n const [q, setQ] = useState('');\n const [sources, setSources] = useState<{ lightrag: boolean; obsidian: boolean }>({ lightrag: true, obsidian: true });\n const [results, setResults] = useState<Result[] | null>(null);\n const [loading, setLoading] = useState(false);\n const [lastQuery, setLastQuery] = useState('');\n\n const onSearch = async (query: string) => {\n if (!query.trim()) return;\n setLoading(true);\n setLastQuery(query);\n try {\n const activeSources = [\n ...(sources.lightrag ? ['lightrag' as const] : []),\n ...(sources.obsidian ? ['obsidian' as const] : []),\n ];\n const r = await api.post<{ query: string; count: number; results: Result[] }>(\n '/memory/semantic-search',\n { query, limit: 20, sources: activeSources },\n );\n setResults(r.results || []);\n } catch (err) {\n toast.error(`Search failed: ${(err as Error).message}`);\n setResults([]);\n } finally {\n setLoading(false);\n }\n };\n\n // Re-run when sources toggle (if there's a last query).\n useEffect(() => {\n if (lastQuery) onSearch(lastQuery);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [sources]);\n\n // Re-run when the panel is re-mounted.\n useEffect(() => {\n if (lastQuery) onSearch(lastQuery);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n const grouped = useMemo(() => {\n const obs = (results || []).filter((r) => r.source === 'obsidian');\n const lr = (results || []).filter((r) => r.source === 'lightrag');\n return { obs, lr };\n }, [results]);\n\n return (\n <div className=\"memory-panel-content\">\n <Card variant=\"elevated\">\n <CardTitle>\n <SearchIcon size={14} /> Semantic search\n </CardTitle>\n <CardMeta>Query both LightRAG (graph-based) and the Obsidian vault in one shot.</CardMeta>\n <div className=\"memory-search-row\">\n <input\n type=\"text\"\n className=\"input\"\n placeholder=\"e.g. how are notes indexed?\"\n value={q}\n onChange={(e) => setQ(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') onSearch(q);\n }}\n disabled={loading}\n />\n <Button variant=\"primary\" onClick={() => onSearch(q)} disabled={loading || !q.trim()}>\n {loading ? <Loader2 size={12} className=\"memory-spin\" /> : <SearchIcon size={12} />}\n Search\n </Button>\n </div>\n <div className=\"memory-source-toggle-row\">\n <ToggleChip\n active={sources.obsidian}\n onToggle={() => setSources((s) => ({ ...s, obsidian: !s.obsidian }))}\n label=\"Obsidian\"\n icon={<FileText size={11} />}\n />\n <ToggleChip\n active={sources.lightrag}\n onToggle={() => setSources((s) => ({ ...s, lightrag: !s.lightrag }))}\n label=\"LightRAG\"\n icon={<Brain size={11} />}\n />\n {q && (\n <button type=\"button\" className=\"icon-btn\" onClick={() => { setQ(''); setResults(null); setLastQuery(''); }} aria-label=\"Clear\">\n <X size={12} />\n </button>\n )}\n </div>\n </Card>\n\n {loading && (\n <div className=\"view-loading\">\n <Spinner size=\"md\" />\n </div>\n )}\n\n {!loading && results && results.length === 0 && (\n <EmptyState\n icon={<SearchIcon size={28} />}\n title=\"No matches\"\n message={`Nothing in scope matched \"${lastQuery}\".`}\n />\n )}\n\n {grouped.obs.length > 0 && (\n <Card>\n <CardTitle>\n <FileText size={14} /> Obsidian ({grouped.obs.length})\n </CardTitle>\n <ul className=\"memory-search-result-list\">\n {grouped.obs.map((r, i) => (\n <li key={`obs-${i}`} className=\"memory-search-result\">\n <div className=\"memory-search-result-head\">\n <code>{r.relPath}</code>\n <span className=\"muted text-xs\">score {r.score.toFixed(1)}</span>\n </div>\n <p className=\"muted text-sm\">{r.snippet}</p>\n </li>\n ))}\n </ul>\n </Card>\n )}\n\n {grouped.lr.length > 0 && (\n <Card>\n <CardTitle>\n <Brain size={14} /> LightRAG ({grouped.lr.length})\n </CardTitle>\n <div className=\"memory-search-result-list\">\n {grouped.lr.map((r, i) => (\n <div key={`lr-${i}`} className=\"memory-search-result\">\n <div className=\"memory-search-result-head\">\n <span className=\"memory-source-pill\"><Brain size={11} /> LightRAG</span>\n {r.error && <span className=\"muted text-xs\">error: {r.error}</span>}\n </div>\n <p className=\"text-sm\">{r.snippet}</p>\n </div>\n ))}\n </div>\n </Card>\n )}\n </div>\n );\n}\n\nfunction ToggleChip({\n active,\n onToggle,\n label,\n icon,\n}: {\n active: boolean;\n onToggle: () => void;\n label: string;\n icon: React.ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n className={cn('memory-toggle-chip', active && 'memory-toggle-chip-active')}\n onClick={onToggle}\n aria-pressed={active}\n >\n {icon}\n <span>{label}</span>\n </button>\n );\n}","// src/web/views/memory/ConfigPanel.tsx — global memory config + per-system toggles.\nimport { useEffect, useState } from 'react';\nimport {\n Brain,\n Database,\n FileText,\n GitBranch,\n Loader2,\n Plug,\n Save,\n Sparkles,\n} from 'lucide-react';\nimport { Button } from '../../components/Button';\nimport { Card, CardMeta, CardTitle } from '../../components/Card';\nimport { Spinner } from '../../components/Spinner';\nimport { useToast } from '../../components/Toast';\nimport { api } from '../../lib/api';\nimport { cn } from '../../lib/utils';\n\ntype GlobalConfig = {\n lightrag?: { enabled?: boolean; url?: string; llm?: string; embedding?: string };\n obsidian?: { vaultPath?: string; syncInterval?: number };\n git?: { repoPath?: string; remoteUrl?: string; branch?: string; autoSync?: boolean };\n};\n\ntype Props = { refreshKey: number };\n\nexport function ConfigPanel({ refreshKey }: Props) {\n const toast = useToast();\n const [cfg, setCfg] = useState<GlobalConfig | null>(null);\n const [loading, setLoading] = useState(true);\n const [saving, setSaving] = useState(false);\n const [tests, setTests] = useState<Array<{ name: string; pass: boolean; detail: string }> | null>(null);\n const [testing, setTesting] = useState(false);\n\n const reload = async () => {\n setLoading(true);\n try {\n const r = await api.get<{ config: GlobalConfig }>('/memory/config/global');\n setCfg(r.config);\n } catch (err) {\n toast.error(`Config load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n reload();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [refreshKey]);\n\n const update = (block: keyof GlobalConfig, key: string, value: unknown) => {\n setCfg((cur) => cur ? { ...cur, [block]: { ...(cur[block] || {}), [key]: value } } : cur);\n };\n\n const onSave = async () => {\n if (!cfg) return;\n setSaving(true);\n try {\n await api.put('/memory/config/global', cfg);\n toast.success('Config saved.');\n } catch (err) {\n toast.error(`Save failed: ${(err as Error).message}`);\n } finally {\n setSaving(false);\n }\n };\n\n const onTest = async () => {\n setTesting(true);\n try {\n const r = await api.post<{ ok: boolean; checks: Array<{ name: string; pass: boolean; detail: string }> }>(\n '/memory/test-git',\n {},\n );\n setTests(r.checks);\n } catch (err) {\n toast.error(`Test failed: ${(err as Error).message}`);\n } finally {\n setTesting(false);\n }\n };\n\n if (loading && !cfg) {\n return (\n <div className=\"view-loading\">\n <Spinner size=\"md\" />\n <p>Loading config…</p>\n </div>\n );\n }\n if (!cfg) return <div className=\"muted\">No config available.</div>;\n\n return (\n <div className=\"memory-panel-content\">\n {/* ── LightRAG ──────────────────────────────────────────────── */}\n <Card>\n <CardTitle><Brain size={14} /> LightRAG</CardTitle>\n <CardMeta>URL + model overrides. Server-side defaults from <code>opencode Zen free tier</code>.</CardMeta>\n <div className=\"memory-config-form\">\n <Row label=\"Enabled\" inline>\n <label className=\"memory-switch\">\n <input\n type=\"checkbox\"\n checked={!!cfg.lightrag?.enabled}\n onChange={(e) => update('lightrag', 'enabled', e.target.checked)}\n />\n <span>{cfg.lightrag?.enabled ? 'on' : 'off'}</span>\n </label>\n </Row>\n <Row label=\"URL\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.lightrag?.url || ''}\n onChange={(e) => update('lightrag', 'url', e.target.value)}\n placeholder=\"http://127.0.0.1:9621\"\n />\n </Row>\n <Row label=\"LLM model\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.lightrag?.llm || ''}\n onChange={(e) => update('lightrag', 'llm', e.target.value)}\n placeholder=\"opencode/gpt-5-nano\"\n />\n </Row>\n <Row label=\"Embedding\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.lightrag?.embedding || ''}\n onChange={(e) => update('lightrag', 'embedding', e.target.value)}\n placeholder=\"opencode/text-embedding-3-small\"\n />\n </Row>\n </div>\n </Card>\n\n {/* ── Obsidian ──────────────────────────────────────────────── */}\n <Card>\n <CardTitle><FileText size={14} /> Obsidian vault</CardTitle>\n <CardMeta>Path + sync cadence for the markdown vault.</CardMeta>\n <div className=\"memory-config-form\">\n <Row label=\"Vault path\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.obsidian?.vaultPath || ''}\n onChange={(e) => update('obsidian', 'vaultPath', e.target.value)}\n placeholder=\"/home/me/vault\"\n />\n </Row>\n <Row label=\"Sync interval (seconds)\">\n <input\n type=\"number\"\n min={0}\n max={2592000}\n className=\"input mono\"\n value={cfg.obsidian?.syncInterval ?? 300}\n onChange={(e) => update('obsidian', 'syncInterval', Number(e.target.value))}\n />\n </Row>\n </div>\n </Card>\n\n {/* ── Git ───────────────────────────────────────────────────── */}\n <Card>\n <CardTitle><GitBranch size={14} /> Git sync</CardTitle>\n <CardMeta>Repo path, remote, branch, and auto-sync toggle.</CardMeta>\n <div className=\"memory-config-form\">\n <Row label=\"Repo path\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.git?.repoPath || ''}\n onChange={(e) => update('git', 'repoPath', e.target.value)}\n placeholder=\"/path/to/repo\"\n />\n </Row>\n <Row label=\"Remote URL\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.git?.remoteUrl || ''}\n onChange={(e) => update('git', 'remoteUrl', e.target.value)}\n placeholder=\"git@github.com:org/repo.git\"\n />\n </Row>\n <Row label=\"Branch\">\n <input\n type=\"text\"\n className=\"input mono\"\n value={cfg.git?.branch || 'main'}\n onChange={(e) => update('git', 'branch', e.target.value)}\n placeholder=\"main\"\n />\n </Row>\n <Row label=\"Auto-sync\" inline>\n <label className=\"memory-switch\">\n <input\n type=\"checkbox\"\n checked={!!cfg.git?.autoSync}\n onChange={(e) => update('git', 'autoSync', e.target.checked)}\n />\n <span>{cfg.git?.autoSync ? 'on' : 'off'}</span>\n </label>\n </Row>\n </div>\n </Card>\n\n {/* ── CCR (placeholder when Headroom is installed) ─────────── */}\n <Card>\n <CardTitle>\n <Sparkles size={14} /> CCR (Compress-Cache-Retrieve)\n </CardTitle>\n <CardMeta>\n Reversible compression for very long conversations. Enabled automatically\n when the Headroom mod is installed.\n </CardMeta>\n <div className=\"muted text-sm\">\n See Settings → Headroom for CCR configuration. This panel will surface\n retention + compression-ratio controls when the mod is active.\n </div>\n </Card>\n\n {/* ── Test all connections ─────────────────────────────────── */}\n <Card>\n <CardTitle>\n <Plug size={14} /> Connection tests\n </CardTitle>\n <CardMeta>Verify the configured git repo, remote, and path.</CardMeta>\n <div className=\"memory-action-row\">\n <Button variant=\"secondary\" onClick={onTest} disabled={testing}>\n {testing ? <Loader2 size={12} className=\"memory-spin\" /> : <Plug size={12} />}\n Test git connection\n </Button>\n <Button variant=\"primary\" onClick={onSave} disabled={saving}>\n {saving ? <Loader2 size={12} className=\"memory-spin\" /> : <Save size={12} />}\n Save config\n </Button>\n </div>\n {tests && tests.length > 0 && (\n <ul className=\"memory-check-list\" style={{ marginTop: 12 }}>\n {tests.map((t, i) => (\n <li key={i} className=\"memory-check-row\">\n <span className=\"memory-check-icon\">\n <span className={cn('memory-pill', t.pass ? 'memory-pill-ok' : 'memory-pill-warn')}>\n {t.pass ? 'OK' : 'FAIL'}\n </span>\n </span>\n <span className=\"memory-check-name\">{t.name}</span>\n <span className=\"memory-check-detail muted\">{t.detail}</span>\n </li>\n ))}\n </ul>\n )}\n </Card>\n </div>\n );\n}\n\nfunction Row({\n label,\n children,\n inline,\n}: {\n label: string;\n children: React.ReactNode;\n inline?: boolean;\n}) {\n if (inline) {\n return (\n <div className=\"memory-config-row-inline\">\n <div className=\"memory-config-row-label\">{label}</div>\n <div className=\"memory-config-row-control\">{children}</div>\n </div>\n );\n }\n return (\n <label className=\"memory-config-row-stack\">\n <span>{label}</span>\n {children}\n </label>\n );\n}\n\n","// src/web/views/Memory.tsx — v4.7.0 dedicated Memory tab.\n//\n// Three-column layout: left rail (source picker), main panel (per-source UI),\n// and a top stat row + a health hero at the top of every panel for context.\n//\n// The Memory subsystem has 4 sources (LightRAG, Obsidian vault, git sync,\n// semantic search) plus a config panel and a high-level overview. Each is a\n// standalone component under views/memory/.\n\nimport React, { useCallback, useState } from 'react';\nimport {\n Brain,\n FileText,\n GitBranch,\n LayoutDashboard,\n RefreshCw,\n Search as SearchIcon,\n Sliders,\n} from 'lucide-react';\nimport { Card } from '../components/Card';\nimport { useToast } from '../components/Toast';\nimport { cn } from '../lib/utils';\nimport { MemoryOverview } from './memory/MemoryOverview';\nimport { LightragPanel } from './memory/LightragPanel';\nimport { ObsidianPanel } from './memory/ObsidianPanel';\nimport { GitSyncPanel } from './memory/GitSyncPanel';\nimport { SemanticSearchPanel } from './memory/SemanticSearchPanel';\nimport { ConfigPanel } from './memory/ConfigPanel';\n\ntype SubPanel = 'overview' | 'lightrag' | 'obsidian' | 'git' | 'semantic' | 'config';\n\ntype Props = {\n snapshot: unknown;\n settings: unknown;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst SOURCES: Array<{\n id: SubPanel;\n label: string;\n icon: typeof LayoutDashboard;\n}> = [\n { id: 'overview', label: 'Overview', icon: LayoutDashboard },\n { id: 'lightrag', label: 'LightRAG', icon: Brain },\n { id: 'obsidian', label: 'Obsidian Vault', icon: FileText },\n { id: 'git', label: 'Git Sync', icon: GitBranch },\n { id: 'semantic', label: 'Semantic Search', icon: SearchIcon },\n { id: 'config', label: 'Config', icon: Sliders },\n];\n\nfunction MemoryInner(_props: Props) {\n const toast = useToast();\n const [active, setActive] = useState<SubPanel>('overview');\n const [refreshKey, setRefreshKey] = useState(0);\n\n const refresh = useCallback(() => {\n setRefreshKey((k) => k + 1);\n }, []);\n\n const onRefreshAll = useCallback(async () => {\n refresh();\n toast.info('Refreshing memory…', 1200);\n }, [refresh, toast]);\n\n const renderPanel = () => {\n switch (active) {\n case 'overview':\n return <MemoryOverview refreshKey={refreshKey} onRefresh={refresh} setActiveSubPanel={setActive} />;\n case 'lightrag':\n return <LightragPanel refreshKey={refreshKey} />;\n case 'obsidian':\n return <ObsidianPanel refreshKey={refreshKey} />;\n case 'git':\n return <GitSyncPanel refreshKey={refreshKey} />;\n case 'semantic':\n return <SemanticSearchPanel refreshKey={refreshKey} />;\n case 'config':\n return <ConfigPanel refreshKey={refreshKey} />;\n default:\n return <Card>Unknown panel: {active}</Card>;\n }\n };\n\n return (\n <div className=\"view view-memory memory-tab\">\n {/* ── Header ─────────────────────────────────────────────── */}\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <Brain size={18} /> Memory\n </h2>\n <p className=\"view-subtitle\">\n LightRAG, Obsidian vault, git sync, and semantic search — all in one place.\n </p>\n </div>\n <div className=\"view-actions\">\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={onRefreshAll}\n aria-label=\"Refresh memory\"\n title=\"Refresh\"\n >\n <RefreshCw size={14} />\n </button>\n </div>\n </header>\n\n <div className=\"memory-tab-body\">\n {/* ── Source rail ─────────────────────────────────────── */}\n <nav className=\"memory-source-rail\" aria-label=\"Memory sources\">\n {SOURCES.map((s) => {\n const Icon = s.icon;\n const isActive = active === s.id;\n return (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={isActive}\n className={cn('memory-source-button', isActive && 'memory-source-button-active')}\n onClick={() => setActive(s.id)}\n >\n <Icon size={16} aria-hidden />\n <span>{s.label}</span>\n </button>\n );\n })}\n </nav>\n\n {/* ── Main panel ─────────────────────────────────────── */}\n <div className=\"memory-main\" key={active}>\n {renderPanel()}\n </div>\n </div>\n </div>\n );\n}\nexport const Memory = React.memo(MemoryInner);\n","// src/views/History.tsx — v3.4.0: cross-project history view.\n// Shows per-project timelines (task events, plan events, project lifecycle)\n// aggregated from the activity log.\n\nimport { useEffect, useState } from 'react';\nimport {\n History as HistoryIcon,\n RefreshCw,\n Folder,\n CheckSquare,\n Filter,\n ChevronDown,\n ChevronRight,\n Download,\n FileText,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Spinner } from '../components/Spinner';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn, formatRelative } from '../lib/utils';\nimport type { Settings, Snapshot } from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype HistoryEvent = {\n ts: string;\n kind: string;\n nodeId?: string;\n text?: string;\n author?: string;\n taskId?: string;\n [k: string]: unknown;\n};\n\ntype ProjectHistory = {\n id: string;\n name: string;\n path: string;\n status: string;\n lastAccessed?: string | null;\n tasks: { total: number; done: number; doing: number; blocked: number; queued: number };\n plans: number;\n};\n\ntype HistoryResponse = {\n events: HistoryEvent[];\n projects: ProjectHistory[];\n stats: { file: string; size: number; lines: number; lastTs: string | null; counts: Record<string, number> };\n generatedAt: string;\n};\n\nconst TIME_RANGES = [\n { id: '1h', label: 'Last hour', ms: 60 * 60 * 1000 },\n { id: '1d', label: 'Last day', ms: 24 * 60 * 60 * 1000 },\n { id: '7d', label: 'Last 7 days', ms: 7 * 24 * 60 * 60 * 1000 },\n { id: '30d', label: 'Last 30 days', ms: 30 * 24 * 60 * 60 * 1000 },\n { id: 'all', label: 'All time', ms: 0 },\n];\n\nexport function History({ snapshot }: Props) {\n const toast = useToast();\n const [data, setData] = useState<HistoryResponse | null>(null);\n const [loading, setLoading] = useState(true);\n const [rangeId, setRangeId] = useState<string>('1d');\n const [expanded, setExpanded] = useState<Set<string>>(new Set());\n const [tick, setTick] = useState(0);\n\n const load = async (since?: string) => {\n try {\n const q = since ? `?since=${encodeURIComponent(since)}&limit=1000` : '?limit=1000';\n const r = await api.get<HistoryResponse>(`/history${q}`);\n setData(r);\n setExpanded(\n new Set(\n r.projects\n .filter((project) => r.events.some((ev) => (ev as { projectId?: string }).projectId === project.id))\n .map((project) => project.id),\n ),\n );\n } catch (err) {\n toast.error(`History load failed: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n setLoading(true);\n const range = TIME_RANGES.find((r) => r.id === rangeId) || TIME_RANGES[1];\n if (range.ms > 0) {\n const since = new Date(Date.now() - range.ms).toISOString();\n load(since);\n } else {\n load();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [rangeId]);\n\n useEffect(() => {\n const id = setInterval(() => setTick((t) => t + 1), 30_000);\n return () => clearInterval(id);\n }, []);\n\n // Group events by project — use projectId where present, otherwise 'global'\n const eventsByProject = new Map<string, HistoryEvent[]>();\n for (const ev of data?.events || []) {\n const pid = (ev as { projectId?: string }).projectId || 'global';\n if (!eventsByProject.has(pid)) eventsByProject.set(pid, []);\n eventsByProject.get(pid)!.push(ev);\n }\n\n const toggleProject = (id: string) => {\n setExpanded((cur) => {\n const next = new Set(cur);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n };\n\n const onExportJson = () => {\n if (!data) return;\n const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `bizar-history-${new Date().toISOString().replace(/[:.]/g, '-')}.json`;\n a.click();\n URL.revokeObjectURL(url);\n toast.success('History exported.');\n };\n\n return (\n <div className=\"view view-history\" data-tick={tick}>\n <header className=\"view-header\">\n <div className=\"view-header-text\">\n <h2 className=\"view-title\">\n <HistoryIcon size={18} /> History\n </h2>\n <p className=\"view-subtitle\">\n Cross-project history of events, tasks, and plans.\n {data?.stats?.lastTs && (\n <> · last event {formatRelative(data.stats.lastTs)}</>\n )}\n </p>\n </div>\n <div className=\"view-actions\">\n <div className=\"tasks-toolbar-group\">\n <Filter size={14} style={{ color: 'var(--text-dim)' }} />\n <select\n className=\"select select-sm\"\n value={rangeId}\n onChange={(e) => setRangeId(e.target.value)}\n title=\"Time range\"\n >\n {TIME_RANGES.map((r) => (\n <option key={r.id} value={r.id}>{r.label}</option>\n ))}\n </select>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n setLoading(true);\n const range = TIME_RANGES.find((r) => r.id === rangeId) || TIME_RANGES[1];\n if (range.ms > 0) {\n load(new Date(Date.now() - range.ms).toISOString());\n } else {\n load();\n }\n }}\n >\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={onExportJson}>\n <Download size={14} /> Export\n </Button>\n </div>\n </header>\n\n {loading && (\n <div className=\"view-loading\">\n <Spinner size=\"lg\" />\n <p>Loading history…</p>\n </div>\n )}\n\n {!loading && data && (\n <div className=\"history-list\">\n {data.projects.length === 0 && (\n <Card>\n <CardTitle><Folder size={14} /> No projects</CardTitle>\n <CardMeta>Register a project in Overview to start tracking history.</CardMeta>\n </Card>\n )}\n\n {data.projects.map((p) => {\n const events = eventsByProject.get(p.id) || [];\n const isOpen = expanded.has(p.id);\n return (\n <Card key={p.id} className=\"history-project\">\n <div className=\"history-project-head\">\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0, flex: 1 }}>\n <div className=\"history-project-name\">\n <Folder size={16} /> {p.name}\n </div>\n <div className=\"history-project-meta\">{p.path}</div>\n </div>\n <div className=\"history-project-stats\">\n <span className=\"history-project-stat\">\n <span className=\"history-project-stat-num\">{p.tasks.done}</span>\n <span className=\"muted\">/ {p.tasks.total} done</span>\n </span>\n {p.tasks.doing > 0 && (\n <span className=\"history-project-stat\">\n <span className=\"history-project-stat-num\">{p.tasks.doing}</span>\n <span className=\"muted\">doing</span>\n </span>\n )}\n {p.tasks.blocked > 0 && (\n <span className=\"history-project-stat\">\n <span className=\"history-project-stat-num\">{p.tasks.blocked}</span>\n <span className=\"muted\">blocked</span>\n </span>\n )}\n <span className=\"history-project-stat\">\n <FileText size={11} /> <span className=\"history-project-stat-num\">{p.plans}</span>\n <span className=\"muted\"> plan{p.plans === 1 ? '' : 's'}</span>\n </span>\n {p.lastAccessed && (\n <span className=\"history-project-stat\">\n <span className=\"muted\">last opened {formatRelative(p.lastAccessed)}</span>\n </span>\n )}\n </div>\n <button\n type=\"button\"\n className=\"icon-btn\"\n onClick={() => toggleProject(p.id)}\n aria-label={isOpen ? 'Collapse' : 'Expand'}\n >\n {isOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}\n </button>\n </div>\n\n {isOpen && (\n <div className=\"history-timeline-mini\">\n {events.length === 0 ? (\n <div className=\"muted\" style={{ padding: '12px 8px', fontSize: 12 }}>\n No events in this time range.\n </div>\n ) : (\n events.slice(-100).reverse().map((ev, i) => (\n <div key={i} className=\"history-timeline-row\">\n <span className=\"history-timeline-ts\">\n {new Date(ev.ts).toLocaleTimeString()}\n </span>\n <span className=\"history-timeline-kind\">{ev.kind || 'event'}</span>\n <span className=\"history-timeline-msg\" title={String(ev.text || ev.title || '')}>\n {ev.author ? `@${ev.author} ` : ''}\n {String(ev.text ?? ev.title ?? ev.name ?? '')}\n </span>\n </div>\n ))\n )}\n </div>\n )}\n </Card>\n );\n })}\n\n {/* Global / unassigned events */}\n {eventsByProject.has('global') && (\n <Card className=\"history-project\">\n <div className=\"history-project-head\">\n <div style={{ display: 'flex', flexDirection: 'column', gap: 4, minWidth: 0, flex: 1 }}>\n <div className=\"history-project-name\">\n <HistoryIcon size={16} /> Global events\n </div>\n <div className=\"history-project-meta\">\n Activity not tied to a specific project\n </div>\n </div>\n </div>\n <div className=\"history-timeline-mini\">\n {(eventsByProject.get('global') || []).slice(-100).reverse().map((ev, i) => (\n <div key={i} className=\"history-timeline-row\">\n <span className=\"history-timeline-ts\">\n {new Date(ev.ts).toLocaleTimeString()}\n </span>\n <span className=\"history-timeline-kind\">{ev.kind || 'event'}</span>\n <span className=\"history-timeline-msg\" title={String(ev.text || ev.title || '')}>\n {ev.author ? `@${ev.author} ` : ''}\n {String(ev.text ?? ev.title ?? ev.name ?? '')}\n </span>\n </div>\n ))}\n </div>\n </Card>\n )}\n\n {data.stats?.counts && Object.keys(data.stats.counts).length > 0 && (\n <Card>\n <CardTitle>Event counts by kind</CardTitle>\n <CardMeta>{data.stats.lines} total lines in log</CardMeta>\n <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 8 }}>\n {Object.entries(data.stats.counts)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 30)\n .map(([kind, count]) => (\n <span\n key={kind}\n className={cn('tag', 'tag-neutral')}\n style={{ fontFamily: 'var(--font-mono)' }}\n >\n {kind}: {count}\n </span>\n ))}\n </div>\n </Card>\n )}\n </div>\n )}\n </div>\n );\n}\n","// src/web/components/UsageChart.tsx\n//\n// Hand-rolled SVG chart. No external chart library — keeps bundle small.\n//\n// Props:\n// series: { labels: string[]; requests: number[]; tokens: number[] }\n// height?: number (default 280)\n// onHover?: (index: number | null, x: number, y: number) => void\n\nimport { useCallback, useRef, useState } from 'react';\nimport { cn } from '../lib/utils';\n\ntype Props = {\n series: { labels: string[]; requests: number[]; tokens: number[] };\n height?: number;\n onHover?: (index: number | null, x: number, y: number) => void;\n className?: string;\n};\n\nconst PADDING = { top: 16, right: 20, bottom: 40, left: 52 };\n\nexport function UsageChart({ series, height = 280, onHover, className }: Props) {\n const containerRef = useRef<HTMLDivElement>(null);\n const [tooltip, setTooltip] = useState<{ index: number; x: number; y: number } | null>(null);\n\n const { labels, requests, tokens } = series;\n const n = labels.length;\n if (n === 0) {\n return (\n <div className={cn('usage-chart-empty', className)} style={{ height }}>\n <span>No data for this range</span>\n </div>\n );\n }\n\n const innerW = 600 - PADDING.left - PADDING.right;\n const innerH = height - PADDING.top - PADDING.bottom;\n\n const maxReq = Math.max(...requests, 1);\n const maxTok = Math.max(...tokens, 1);\n // Two separate Y scales (left = requests, right = tokens)\n const barW = Math.max(4, Math.min(24, Math.floor(innerW / n) - 4));\n const gap = (innerW - barW * n) / (n + 1);\n\n function barX(i: number) {\n return PADDING.left + gap + i * (barW + gap);\n }\n\n function barH(v: number) {\n return (v / maxReq) * innerH * 0.75;\n }\n\n function lineY(v: number) {\n return PADDING.top + innerH - (v / maxTok) * innerH * 0.75;\n }\n\n // Build polyline points for the token line.\n const linePoints = tokens\n .map((v, i) => `${barX(i) + barW / 2},${lineY(v)}`)\n .join(' ');\n\n // Y-axis ticks (left, requests).\n const leftTicks = [0, 0.25, 0.5, 0.75, 1].map(t => ({\n y: PADDING.top + innerH - t * innerH * 0.75,\n label: t === 0 ? '0' : `${Math.round(maxReq * t).toLocaleString()}`,\n }));\n\n // Y-axis ticks (right, tokens).\n const rightTicks = [0, 0.25, 0.5, 0.75, 1].map(t => ({\n y: PADDING.top + innerH - t * innerH * 0.75,\n label: t === 0 ? '0' : `${Math.round(maxTok * t / 1000)}k`,\n }));\n\n // X-axis labels (show at most 7 to avoid crowding).\n const labelStep = Math.max(1, Math.floor(n / 7));\n const xLabels = labels.map((l, i) => ({ i, l, x: barX(i) + barW / 2 })).filter((_, i) => i % labelStep === 0);\n\n const handleMouseMove = useCallback(\n (e: React.MouseEvent<SVGSVGElement>) => {\n if (!containerRef.current) return;\n const rect = containerRef.current.getBoundingClientRect();\n const svgX = (e.clientX - rect.left) * (600 / rect.width);\n const svgY = (e.clientY - rect.top) * (height / rect.height);\n // Find closest bar.\n const relX = svgX - PADDING.left;\n const i = Math.round((relX - gap / 2) / (barW + gap));\n const clamped = Math.max(0, Math.min(n - 1, i));\n setTooltip({ index: clamped, x: e.clientX - rect.left, y: e.clientY - rect.top });\n onHover?.(clamped, svgX, svgY);\n },\n [n, barW, gap, onHover, height],\n );\n\n const handleMouseLeave = useCallback(() => {\n setTooltip(null);\n onHover?.(null, 0, 0);\n }, [onHover]);\n\n const tip = tooltip;\n\n return (\n <div ref={containerRef} className={cn('usage-chart', className)} style={{ position: 'relative' }}>\n <svg\n viewBox={`0 0 600 ${height}`}\n width=\"100%\"\n height={height}\n style={{ display: 'block', overflow: 'visible' }}\n onMouseMove={handleMouseMove}\n onMouseLeave={handleMouseLeave}\n >\n {/* Grid lines */}\n {leftTicks.map((tick, i) => (\n <line\n key={`grid-${i}`}\n x1={PADDING.left}\n y1={tick.y}\n x2={600 - PADDING.right}\n y2={tick.y}\n stroke=\"var(--border)\"\n strokeWidth={1}\n strokeDasharray=\"4,3\"\n opacity={0.5}\n />\n ))}\n\n {/* Left Y axis — requests */}\n {leftTicks.map((tick, i) => (\n <text\n key={`ly-${i}`}\n x={PADDING.left - 6}\n y={tick.y + 4}\n textAnchor=\"end\"\n fontSize={10}\n fill=\"var(--text-muted)\"\n fontFamily=\"var(--font-mono, ui-monospace, monospace)\"\n >\n {tick.label}\n </text>\n ))}\n\n {/* Right Y axis — tokens */}\n {rightTicks.map((tick, i) => (\n <text\n key={`ry-${i}`}\n x={600 - PADDING.right + 6}\n y={tick.y + 4}\n textAnchor=\"start\"\n fontSize={10}\n fill=\"var(--text-muted)\"\n fontFamily=\"var(--font-mono, ui-monospace, monospace)\"\n >\n {tick.label}\n </text>\n ))}\n\n {/* Bars — requests */}\n {requests.map((v, i) => {\n const bh = barH(v);\n const bx = barX(i);\n const by = PADDING.top + innerH - bh;\n return (\n <rect\n key={`bar-${i}`}\n x={bx}\n y={by}\n width={barW}\n height={bh}\n rx={2}\n fill={tip?.index === i ? 'var(--accent)' : 'var(--accent)'}\n opacity={tip?.index === i ? 1 : 0.75}\n style={{ transition: 'opacity 120ms ease' }}\n />\n );\n })}\n\n {/* Token line */}\n <polyline\n points={linePoints}\n fill=\"none\"\n stroke=\"var(--warning, #d29922)\"\n strokeWidth={2}\n strokeLinejoin=\"round\"\n strokeLinecap=\"round\"\n opacity={0.9}\n />\n\n {/* Token dots */}\n {tokens.map((v, i) => (\n <circle\n key={`dot-${i}`}\n cx={barX(i) + barW / 2}\n cy={lineY(v)}\n r={tip?.index === i ? 5 : 3}\n fill=\"var(--warning, #d29922)\"\n opacity={tip?.index === i ? 1 : 0.7}\n style={{ transition: 'r 120ms ease' }}\n />\n ))}\n\n {/* X axis labels */}\n {xLabels.map(({ i, l, x }) => (\n <text\n key={`xl-${i}`}\n x={x}\n y={PADDING.top + innerH + 18}\n textAnchor=\"middle\"\n fontSize={10}\n fill=\"var(--text-muted)\"\n fontFamily=\"var(--font-mono, ui-monospace, monospace)\"\n >\n {l}\n </text>\n ))}\n\n {/* X axis line */}\n <line\n x1={PADDING.left}\n y1={PADDING.top + innerH}\n x2={600 - PADDING.right}\n y2={PADDING.top + innerH}\n stroke=\"var(--border)\"\n strokeWidth={1}\n />\n </svg>\n\n {/* Floating tooltip */}\n {tip !== null && (\n <div\n className=\"usage-chart-tooltip\"\n style={{\n left: Math.min(tip.x + 12, 600 - 140),\n top: tip.y - 60,\n }}\n >\n <div className=\"usage-tooltip-date\">{labels[tip.index]}</div>\n <div className=\"usage-tooltip-row\">\n <span className=\"usage-tooltip-dot\" style={{ background: 'var(--accent)' }} />\n <span>Requests:</span>\n <strong>{requests[tip.index].toLocaleString()}</strong>\n </div>\n <div className=\"usage-tooltip-row\">\n <span className=\"usage-tooltip-dot\" style={{ background: 'var(--warning, #d29922)' }} />\n <span>Tokens:</span>\n <strong>{tokens[tip.index].toLocaleString()}</strong>\n </div>\n </div>\n )}\n </div>\n );\n}\n","// src/web/components/UsageTable.tsx\n//\n// Sortable compact table for per-model usage breakdown.\n//\n// Props:\n// rows: PerModelRow[]\n// sortKey: string\n// sortDir: 'asc' | 'desc'\n// onSort: (key: string) => void\n\nimport { cn } from '../lib/utils';\n\nexport type PerModelRow = {\n providerId: string;\n modelId: string;\n requests: number;\n totalTokens: number;\n promptTokens: number;\n completionTokens: number;\n errors: number;\n avgLatencyMs: number;\n};\n\ntype Props = {\n rows: PerModelRow[];\n sortKey: string;\n sortDir: 'asc' | 'desc';\n onSort: (key: string) => void;\n};\n\nfunction SortHeader({ label, col, sortKey, sortDir, onSort }: {\n label: string; col: string; sortKey: string; sortDir: 'asc' | 'desc'; onSort: (k: string) => void;\n}) {\n const active = sortKey === col;\n return (\n <th\n className={cn('usage-sort-header', active && 'is-active')}\n onClick={() => onSort(col)}\n aria-sort={active ? (sortDir === 'asc' ? 'ascending' : 'descending') : 'none'}\n >\n <span>{label}</span>\n <span className=\"usage-sort-icon\">\n {active ? (sortDir === 'asc' ? ' ↑' : ' ↓') : ' ↕'}\n </span>\n </th>\n );\n}\n\nexport function UsageTable({ rows, sortKey, sortDir, onSort }: Props) {\n return (\n <div className=\"usage-table-wrap\">\n <table className=\"usage-table\">\n <thead>\n <tr>\n <SortHeader label=\"Model\" col=\"modelId\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n <SortHeader label=\"Requests\" col=\"requests\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n <SortHeader label=\"Prompt Tok\" col=\"promptTokens\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n <SortHeader label=\"Compl Tok\" col=\"completionTokens\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n <SortHeader label=\"Total Tok\" col=\"totalTokens\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n <SortHeader label=\"Avg Latency\" col=\"avgLatencyMs\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n <SortHeader label=\"Errors\" col=\"errors\" sortKey={sortKey} sortDir={sortDir} onSort={onSort} />\n </tr>\n </thead>\n <tbody>\n {rows.length === 0 ? (\n <tr>\n <td colSpan={7} className=\"usage-table-empty\">No data for this range</td>\n </tr>\n ) : (\n rows.map((row) => (\n <tr key={`${row.providerId}::${row.modelId}`}>\n <td className=\"usage-table-model\">\n <code>{row.modelId}</code>\n </td>\n <td className=\"mono\">{row.requests.toLocaleString()}</td>\n <td className=\"mono\">{row.promptTokens.toLocaleString()}</td>\n <td className=\"mono\">{row.completionTokens.toLocaleString()}</td>\n <td className=\"mono\">{row.totalTokens.toLocaleString()}</td>\n <td className=\"mono\">{row.avgLatencyMs}ms</td>\n <td className={cn('mono', row.errors > 0 && 'is-err')}>\n {row.errors > 0 ? row.errors : '—'}\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n );\n}\n","// src/views/MiniMaxUsage.tsx — v4.6.0\n//\n// Full rewrite with two tabs:\n// 1. Token Plan — existing 5h + weekly remaining quota (unchanged)\n// 2. Usage Analytics — charts, KPIs, per-model breakdown, per-key status\n//\n// The usage data comes from the JSONL store at ~/.local/share/bizar/usage.jsonl\n// (written by minimax.mjs after every chatCompletion / fetchRemains call).\n// The Usage Analytics tab is only shown when the key is configured.\n\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport {\n Coins,\n RefreshCw,\n AlertTriangle,\n CheckCircle2,\n KeyRound,\n Send,\n Loader2,\n Calendar,\n Activity,\n Save,\n Eye,\n EyeOff,\n Sparkles,\n X,\n ExternalLink,\n ShieldCheck,\n CircleCheck,\n BarChart2,\n} from 'lucide-react';\nimport { Card, CardTitle, CardMeta } from '../components/Card';\nimport { Button } from '../components/Button';\nimport { Spinner } from '../components/Spinner';\nimport { UsageChart } from '../components/UsageChart';\nimport { UsageTable, type PerModelRow } from '../components/UsageTable';\nimport { useToast } from '../components/Toast';\nimport { api } from '../lib/api';\nimport { cn } from '../lib/utils';\n\n// ─── Types ───────────────────────────────────────────────────────────\n\ntype Props = {\n snapshot: unknown;\n settings: unknown;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\ntype RemainsModel = {\n model_name: string;\n current_interval_remaining_percent: number;\n current_weekly_remaining_percent: number;\n current_interval_consumed_percent?: number;\n weekly_consumed_percent?: number;\n current_interval_status: number;\n current_weekly_status: number;\n current_interval_total_count: number;\n current_interval_usage_count: number;\n current_weekly_total_count: number;\n current_weekly_usage_count: number;\n endTimeISO?: string;\n weeklyEndTimeISO?: string;\n intervalResetInMs?: number;\n weeklyResetInMs?: number;\n intervalResetInHuman?: string;\n weeklyResetInHuman?: string;\n intervalUsed?: number;\n intervalTotal?: number;\n weeklyUsed?: number;\n weeklyTotal?: number;\n};\n\ntype RemainsSnapshot = {\n ok: boolean;\n cached?: boolean;\n fetchedAt?: number;\n apiKeyHint?: string;\n keySource?: string;\n groupId?: string;\n baseUrl?: string;\n models?: RemainsModel[];\n baseResp?: { status_code: number; status_msg: string };\n error?: string;\n message?: string;\n};\n\ntype Status = {\n configured: boolean;\n apiKeyHint: string;\n source: string;\n groupId: string;\n tokenBaseUrl: string;\n chatBaseUrl: string;\n knownModels: string[];\n keyPatternValid: boolean | null;\n cache: { fetchedAt: number; apiKeyHint: string; modelCount: number } | null;\n};\n\ntype OnboardingState = {\n dismissedAt: number | null;\n hiddenModels: string[];\n};\n\ntype TestResult = {\n ok: boolean;\n error?: string;\n message?: string;\n model?: string;\n content?: string;\n reasoning?: string;\n finishReason?: string;\n usage?: {\n total_tokens?: number;\n prompt_tokens?: number;\n completion_tokens?: number;\n prompt_tokens_details?: { cached_tokens?: number };\n };\n status?: number;\n raw?: unknown;\n};\n\n// Usage analytics types.\ntype UsageTotals = {\n requests: number;\n errors: number;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n cachedTokens: number;\n reasoningTokens: number;\n avgLatencyMs: number;\n p95LatencyMs: number;\n costEstimate: number;\n};\n\ntype DailyBucket = {\n date: string;\n requests: number;\n totalTokens: number;\n promptTokens: number;\n completionTokens: number;\n errors: number;\n avgLatencyMs: number;\n};\n\ntype PerModelBucket = {\n providerId: string;\n modelId: string;\n requests: number;\n totalTokens: number;\n promptTokens: number;\n completionTokens: number;\n errors: number;\n avgLatencyMs: number;\n};\n\ntype PerKeyBucket = {\n keyEnvVar: string;\n isBackup: boolean;\n requests: number;\n errors: number;\n lastUsed: number | null;\n status: 'active' | 'backup';\n};\n\ntype UsageQueryResult = {\n totals: UsageTotals;\n daily: DailyBucket[];\n perModel: PerModelBucket[];\n perKey: PerKeyBucket[];\n errors: { code: string; message: string; count: number; lastOccurred: number | null }[];\n};\n\ntype RecentRecord = {\n ts: number;\n providerId: string;\n modelId: string;\n endpoint: string;\n requestId: string;\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n cachedTokens: number;\n reasoningTokens: number;\n latencyMs: number;\n finishReason: string | null;\n error: { code: string; message: string } | null;\n keyEnvVar: string;\n isBackup: boolean;\n cached: boolean;\n};\n\ntype TimeRange = '24h' | '7d' | '30d' | 'custom';\n\n// ─── Main component ────────────────────────────────────────────────────\n\nfunction MiniMaxUsageInner({ activeTab, setActiveTab }: Props) {\n // Share state between tabs.\n const [view, setView] = useState<'quota' | 'analytics'>('quota');\n const toast = useToast();\n\n // Load based on active view.\n return (\n <div className=\"view-container view-minimax-usage\">\n {/* Sub-tab switcher */}\n <div className=\"minimax-sub-tabs\">\n <button\n className={cn('minimax-sub-tab', view === 'quota' && 'is-active')}\n onClick={() => setView('quota')}\n >\n <Coins size={13} /> Token Plan\n </button>\n <button\n className={cn('minimax-sub-tab', view === 'analytics' && 'is-active')}\n onClick={() => setView('analytics')}\n >\n <BarChart2 size={13} /> Usage Analytics\n </button>\n </div>\n\n {view === 'quota'\n ? <QuotaView activeTab={activeTab} setActiveTab={setActiveTab} />\n : <AnalyticsView toast={toast} />\n }\n </div>\n );\n}\n\n// ─── Token Plan view (existing functionality) ──────────────────────────\n\nfunction QuotaView({ activeTab, setActiveTab }: Pick<Props, 'activeTab' | 'setActiveTab'>) {\n const toast = useToast();\n const [status, setStatus] = useState<Status | null>(null);\n const [remains, setRemains] = useState<RemainsSnapshot | null>(null);\n const [onboarding, setOnboarding] = useState<OnboardingState | null>(null);\n const [loading, setLoading] = useState(true);\n const [refreshing, setRefreshing] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [testResult, setTestResult] = useState<TestResult | null>(null);\n const [testing, setTesting] = useState(false);\n const [wizardStep, setWizardStep] = useState(0);\n const [wizardVerifying, setWizardVerifying] = useState(false);\n const [wizardVerifyResult, setWizardVerifyResult] = useState<TestResult | null>(null);\n const [keyDraft, setKeyDraft] = useState('');\n const [showKey, setShowKey] = useState(false);\n const [savingKey, setSavingKey] = useState(false);\n\n const load = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const [s, r, o] = await Promise.all([\n api.get<Status>('/minimax/status'),\n api.get<RemainsSnapshot>('/minimax/remains'),\n api.get<OnboardingState>('/minimax/onboarding'),\n ]);\n setStatus(s);\n setRemains(r);\n setOnboarding(o);\n if (s.configured) setWizardStep(4);\n } catch (err) {\n setError((err as Error).message || 'Failed to load MiniMax data');\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => { load(); }, [load]);\n\n const dismissWizard = useCallback(async () => {\n try {\n await api.post('/minimax/onboarding', { dismissedAt: Date.now() });\n setOnboarding((o) => o ? { ...o, dismissedAt: Date.now() } : o);\n } catch { /* best-effort */ }\n }, []);\n\n const verifyKeyBeforeSave = useCallback(async () => {\n if (!keyDraft.trim()) { toast.error('Paste a Subscription Key first.'); return; }\n setWizardVerifying(true);\n setWizardVerifyResult(null);\n try {\n const r = await api.post<TestResult>('/minimax/test', {\n prompt: 'Reply with a single word: pong',\n model: 'MiniMax-M3',\n maxTokens: 16,\n });\n setWizardVerifyResult(r);\n if (r.ok) {\n setWizardStep(3);\n toast.success('Key works. Saving…');\n try {\n await api.post('/minimax/onboarding/save-key', { key: keyDraft.trim(), groupId: 'default' });\n clearRemainsCacheClient();\n toast.success('Subscription Key saved.');\n } catch (err) { toast.error(`Save failed: ${(err as Error).message}`); }\n void load();\n } else {\n toast.error(`Verification failed: ${r.message ?? r.error ?? 'unknown'}`);\n }\n } catch (err) { toast.error(`Test request failed: ${(err as Error).message}`); }\n finally { setWizardVerifying(false); }\n }, [keyDraft, toast, load]);\n\n const saveKey = useCallback(async () => {\n if (!keyDraft.trim()) { toast.error('Paste a Subscription Key first.'); return; }\n setSavingKey(true);\n try {\n const r = await api.post<{ ok: boolean; path?: string; apiKeyHint?: string; error?: string; message?: string }>(\n '/minimax/onboarding/save-key', { key: keyDraft.trim(), groupId: 'default' },\n );\n if (!r.ok) { toast.error(`Save failed: ${r.message ?? r.error ?? 'unknown'}`); return; }\n setKeyDraft('');\n clearRemainsCacheClient();\n toast.success('Subscription Key saved. Loading quota…');\n void load();\n } catch (err) { toast.error(`Save failed: ${(err as Error).message}`); }\n finally { setSavingKey(false); }\n }, [keyDraft, toast, load]);\n\n const clearRemainsCacheClient = useCallback(async () => {\n try { await api.del('/minimax/cache'); } catch { /* best-effort */ }\n }, []);\n\n const refresh = useCallback(async () => {\n setRefreshing(true);\n setError(null);\n try {\n await api.post('/minimax/remains/refresh');\n await load();\n toast.success('Refreshed');\n } catch (err) { toast.error(`Refresh failed: ${(err as Error).message}`); }\n finally { setRefreshing(false); }\n }, [load, toast]);\n\n const sendTest = useCallback(async () => {\n setTesting(true);\n setTestResult(null);\n try {\n const r = await api.post<TestResult>('/minimax/test', {\n prompt: 'Reply with a single word: pong',\n model: 'MiniMax-M3',\n maxTokens: 16,\n });\n setTestResult(r);\n if (r.ok) toast.success(`Test ok — used ${r.usage?.total_tokens ?? '?'} tokens`);\n else toast.error(`Test failed: ${r.message ?? r.error ?? 'unknown'}`);\n } catch (err) { toast.error(`Test request failed: ${(err as Error).message}`); }\n finally { setTesting(false); }\n }, [toast]);\n\n if (loading && !status) {\n return <div className=\"view-container\"><Spinner /> Loading MiniMax data…</div>;\n }\n if (!status) {\n return (\n <div className=\"view-container\">\n <div className=\"error-card\">\n <AlertTriangle size={20} />\n <div><strong>Couldn't load MiniMax status</strong><pre>{error ?? 'unknown error'}</pre></div>\n </div>\n </div>\n );\n }\n\n const showWizard = !status.configured && (onboarding?.dismissedAt == null) && wizardStep < 4;\n if (showWizard) {\n return <OnboardingWizard\n step={wizardStep} setStep={setWizardStep}\n keyDraft={keyDraft} setKeyDraft={setKeyDraft}\n showKey={showKey} setShowKey={setShowKey}\n verifying={wizardVerifying} verifyResult={wizardVerifyResult}\n onVerify={verifyKeyBeforeSave}\n onSkip={async () => { await dismissWizard(); toast.success(\"Skipped.\"); }}\n onManualKeySave={saveKey} savingKey={savingKey} status={status}\n />;\n }\n\n return (\n <>\n <header className=\"view-header\">\n <div className=\"view-header-titles\">\n <h1 className=\"view-title\">\n <Coins size={20} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />\n MiniMax Token Plan\n </h1>\n <p className=\"view-subtitle\">\n Remaining 5-hour + weekly quota per model. Fetches live from{' '}\n <code>www.minimax.io/v1/token_plan/remains</code>.\n </p>\n </div>\n <div className=\"view-header-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={() => setActiveTab('settings')} title=\"Configure your Subscription Key\">\n <KeyRound size={14} /> {status.configured ? `Key ${status.apiKeyHint}` : 'Add key'}\n </Button>\n <Button variant=\"secondary\" size=\"sm\" onClick={refresh} disabled={refreshing}>\n {refreshing ? <Loader2 size={14} className=\"spin\" /> : <RefreshCw size={14} />} Refresh\n </Button>\n </div>\n </header>\n\n {remains && !remains.ok && (\n <div className=\"banner banner-err\">\n <AlertTriangle size={16} />\n <span><strong>Couldn't load quota</strong>: {remains.message ?? remains.error ?? 'unknown error'}</span>\n </div>\n )}\n\n {remains?.ok && remains.models && (\n <>\n <div className=\"minimax-stats-row\">\n <Stat label=\"Models tracked\" value={String(remains.models.length)} hint=\"Distinct model quotas returned by the API\" />\n <Stat label=\"Last fetched\" value={remains.fetchedAt ? relativeTime(remains.fetchedAt) : '—'} hint=\"Refreshed on demand + every 60s\" />\n <Stat label=\"Group\" value={remains.groupId ?? '—'} hint=\"Usually 'default' for an individual team\" />\n <Stat label=\"API key\" value={remains.apiKeyHint ?? '—'} hint=\"Masked; the real key never leaves auth.json\" />\n </div>\n <div className=\"minimax-models-grid\">\n {remains.models.map((m) => <ModelQuotaCard key={m.model_name} model={m} />)}\n </div>\n </>\n )}\n\n {status.configured && (\n <Card id=\"minimax-test\">\n <CardTitle><Send size={14} /> Test the API key</CardTitle>\n <CardMeta>One-shot chat completion to <code>{status.chatBaseUrl}/chat/completions</code>.</CardMeta>\n <div className=\"minimax-test-actions\">\n <Button onClick={sendTest} disabled={testing} variant=\"primary\" size=\"sm\">\n {testing ? <Loader2 size={14} className=\"spin\" /> : <Send size={14} />} Send test prompt\n </Button>\n <code className=\"minimax-test-prompt\">\"Reply with a single word: pong\"</code>\n </div>\n {testResult && (\n <div className={cn('minimax-test-result', testResult.ok ? 'ok' : 'err')}>\n {testResult.ok ? <CheckCircle2 size={14} /> : <AlertTriangle size={14} />}\n <div className=\"minimax-test-body\">\n {testResult.ok ? (\n <>\n <div className=\"minimax-test-line\">\n <strong>model:</strong> <code>{testResult.model}</code> ·{' '}\n <strong>finish:</strong> {testResult.finishReason ?? '—'}\n </div>\n {testResult.content && (\n <div className=\"minimax-test-content\"><code>{testResult.content}</code></div>\n )}\n {testResult.usage && (\n <div className=\"minimax-test-usage\">\n <strong>usage:</strong> total <code>{testResult.usage.total_tokens ?? '?'}</code> · prompt{' '}\n <code>{testResult.usage.prompt_tokens ?? '?'}</code> · completion{' '}\n <code>{testResult.usage.completion_tokens ?? '?'}</code>\n {testResult.usage.prompt_tokens_details?.cached_tokens != null && (\n <> · cached <code>{testResult.usage.prompt_tokens_details.cached_tokens}</code></>\n )}\n </div>\n )}\n </>\n ) : (\n <pre>{testResult.message ?? testResult.error ?? 'unknown error'}</pre>\n )}\n </div>\n </div>\n )}\n </Card>\n )}\n </>\n );\n}\n\n// ─── Analytics view ────────────────────────────────────────────────────\n\nfunction AnalyticsView({ toast }: { toast: ReturnType<typeof useToast> }) {\n const [range, setRange] = useState<TimeRange>('24h');\n const [customFrom, setCustomFrom] = useState('');\n const [customTo, setCustomTo] = useState('');\n const [loading, setLoading] = useState(true);\n const [usage, setUsage] = useState<UsageQueryResult | null>(null);\n const [recent, setRecent] = useState<RecentRecord[]>([]);\n const [sortKey, setSortKey] = useState('requests');\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('desc');\n const [refreshing, setRefreshing] = useState(false);\n\n const load = useCallback(async (r: TimeRange, fromMs?: number, toMs?: number) => {\n setLoading(true);\n try {\n const params = new URLSearchParams({ range: r });\n if (r === 'custom' && fromMs && toMs) {\n params.set('from', String(fromMs));\n params.set('to', String(toMs));\n }\n const [u, rec] = await Promise.all([\n api.get<UsageQueryResult>(`/usage?${params.toString()}`),\n api.get<{ records: RecentRecord[]; total: number; returned: number }>('/usage/recent?limit=20'),\n ]);\n setUsage(u);\n setRecent(rec.records);\n } catch (err) {\n toast.error(`Failed to load usage data: ${(err as Error).message}`);\n } finally {\n setLoading(false);\n }\n }, [toast]);\n\n useEffect(() => {\n if (range === 'custom') {\n const from = customFrom ? new Date(customFrom).getTime() : Date.now() - 7 * 86_400_000;\n const to = customTo ? new Date(customTo).getTime() : Date.now();\n void load('custom', from, to);\n } else {\n void load(range);\n }\n }, [range, load]);\n\n const handleSort = useCallback((key: string) => {\n if (sortKey === key) setSortDir(d => d === 'asc' ? 'desc' : 'asc');\n else { setSortKey(key); setSortDir('desc'); }\n }, [sortKey]);\n\n const sortedModels = useMemo(() => {\n if (!usage?.perModel) return [];\n return [...usage.perModel].sort((a, b) => {\n const av = (a as Record<string, unknown>)[sortKey] ?? 0;\n const bv = (b as Record<string, unknown>)[sortKey] ?? 0;\n const cmp = typeof av === 'number' && typeof bv === 'number' ? av - bv : String(av).localeCompare(String(bv));\n return sortDir === 'asc' ? cmp : -cmp;\n });\n }, [usage?.perModel, sortKey, sortDir]);\n\n const chartSeries = useMemo(() => {\n if (!usage?.daily) return { labels: [] as string[], requests: [] as number[], tokens: [] as number[] };\n return {\n labels: usage.daily.map(d => d.date.slice(5)), // \"MM-DD\"\n requests: usage.daily.map(d => d.requests),\n tokens: usage.daily.map(d => d.totalTokens),\n };\n }, [usage?.daily]);\n\n const refresh = useCallback(async () => {\n setRefreshing(true);\n await load(range === 'custom' ? 'custom' : range,\n range === 'custom' && customFrom ? new Date(customFrom).getTime() : undefined,\n range === 'custom' && customTo ? new Date(customTo).getTime() : undefined);\n setRefreshing(false);\n }, [load, range, customFrom, customTo]);\n\n if (loading && !usage) {\n return <div className=\"view-container\"><Spinner /> Loading usage data…</div>;\n }\n\n const t = usage?.totals;\n const errors = usage?.errors ?? [];\n const perKey = usage?.perKey ?? [];\n\n return (\n <>\n {/* Header */}\n <header className=\"view-header\">\n <div className=\"view-header-titles\">\n <h1 className=\"view-title\">\n <BarChart2 size={20} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />\n Usage Analytics\n </h1>\n <p className=\"view-subtitle\">\n Aggregated from <code>~/.local/share/bizar/usage.jsonl</code> —\n every chatCompletion and fetchRemains call.\n </p>\n </div>\n <div className=\"view-header-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={refresh} disabled={refreshing}>\n {refreshing ? <Loader2 size={14} className=\"spin\" /> : <RefreshCw size={14} />} Refresh\n </Button>\n </div>\n </header>\n\n {/* Time range selector */}\n <div className=\"usage-time-range\">\n {(['24h', '7d', '30d', 'custom'] as TimeRange[]).map(r => (\n <button\n key={r}\n className={cn('usage-range-chip', range === r && 'is-active')}\n onClick={() => setRange(r)}\n >\n {r === 'custom' ? 'Custom' : r.toUpperCase()}\n </button>\n ))}\n {range === 'custom' && (\n <div className=\"usage-custom-dates\">\n <input\n type=\"date\"\n className=\"usage-date-input\"\n value={customFrom}\n onChange={e => setCustomFrom(e.target.value)}\n />\n <span style={{ color: 'var(--text-muted)', fontSize: 12 }}>to</span>\n <input\n type=\"date\"\n className=\"usage-date-input\"\n value={customTo}\n onChange={e => setCustomTo(e.target.value)}\n />\n </div>\n )}\n </div>\n\n {/* KPI row */}\n <div className=\"usage-kpi-row\">\n <KpiCard\n label=\"Total Requests\"\n value={t?.requests.toLocaleString() ?? '—'}\n sub={t ? `${t.errors} errors` : undefined}\n tone={t && t.errors > t.requests * 0.1 ? 'warn' : undefined}\n />\n <KpiCard\n label=\"Total Tokens\"\n value={t ? (t.totalTokens >= 1000 ? `${Math.round(t.totalTokens / 1000)}k` : String(t.totalTokens)) : '—'}\n sub={t ? `${t.promptTokens.toLocaleString()} prompt · ${t.completionTokens.toLocaleString()} completion` : undefined}\n />\n <KpiCard\n label=\"Errors\"\n value={String(t?.errors ?? '—')}\n sub={errors.length > 0 ? `${errors[0].code}: ${errors[0].count}` : undefined}\n tone={t && t.errors > 0 ? 'err' : undefined}\n />\n <KpiCard\n label=\"Avg Latency\"\n value={t?.avgLatencyMs != null ? `${t.avgLatencyMs}ms` : '—'}\n sub={t?.p95LatencyMs != null ? `p95 ${t.p95LatencyMs}ms` : undefined}\n />\n <KpiCard\n label=\"Est. Cost\"\n value={t?.costEstimate != null && t.costEstimate > 0 ? `$${t.costEstimate.toFixed(4)}` : '—'}\n sub=\"approximate USD\"\n tone={undefined}\n />\n </div>\n\n {/* Chart */}\n <Card className=\"usage-chart-card\">\n <div className=\"usage-chart-wrap\">\n <UsageChart series={chartSeries} height={280} />\n </div>\n <div className=\"usage-legend\">\n <div className=\"usage-legend-item\">\n <div className=\"usage-legend-bar\" style={{ background: 'var(--accent)' }} />\n <span>Requests (bar)</span>\n </div>\n <div className=\"usage-legend-item\">\n <div className=\"usage-legend-line\" style={{ background: 'var(--warning, #d29922)' }} />\n <span>Tokens (line)</span>\n </div>\n </div>\n </Card>\n\n {/* Per-model table */}\n <Card>\n <CardTitle>Per-model breakdown</CardTitle>\n <UsageTable\n rows={sortedModels as PerModelRow[]}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={handleSort}\n />\n </Card>\n\n {/* Per-key status */}\n {perKey.length > 0 && (\n <Card>\n <CardTitle>API Keys</CardTitle>\n <div className=\"usage-key-row\">\n {perKey.map(k => (\n <span\n key={k.keyEnvVar}\n className={cn('usage-key-badge', k.isBackup ? 'is-backup' : 'is-active')}\n >\n <span className=\"usage-key-dot\" />\n {k.keyEnvVar}\n {k.isBackup ? ' (backup)' : ' (active)'}\n {' · '}\n {k.requests} req\n </span>\n ))}\n </div>\n </Card>\n )}\n\n {/* Recent activity */}\n {recent.length > 0 && (\n <Card>\n <CardTitle>Recent activity</CardTitle>\n <div className=\"usage-recent-list\">\n {recent.map((r, i) => (\n <div key={`${r.requestId}-${i}`} className={cn('usage-recent-item', r.error && 'is-err')}>\n <span className=\"usage-recent-time\">\n {new Date(r.ts).toLocaleTimeString()}\n </span>\n <span className=\"usage-recent-model\">\n <code>{r.modelId}</code>\n </span>\n <span className=\"usage-recent-tokens\">\n {r.totalTokens.toLocaleString()} tok\n </span>\n <span className=\"usage-recent-latency\">\n {r.latencyMs}ms\n </span>\n <span className=\"usage-recent-endpoint\">{r.endpoint}</span>\n </div>\n ))}\n </div>\n </Card>\n )}\n </>\n );\n}\n\n// ─── Kpi card ──────────────────────────────────────────────────────────\n\nfunction KpiCard({ label, value, sub, tone }: { label: string; value: string; sub?: string; tone?: 'warn' | 'err' | 'ok' }) {\n return (\n <div className=\"usage-kpi-card\">\n <div className=\"usage-kpi-label\">{label}</div>\n <div className={cn('usage-kpi-value', tone && `is-${tone}`)}>{value}</div>\n {sub && <div className=\"usage-kpi-sub\">{sub}</div>}\n </div>\n );\n}\n\n// ─── Sub-components (quota view) ───────────────────────────────────────\n\nfunction Stat({ label, value, hint }: { label: string; value: string; hint?: string }) {\n return (\n <div className=\"stat\">\n <div className=\"stat-label\">{label}</div>\n <div className=\"stat-value\">{value}</div>\n {hint && <div className=\"stat-hint\">{hint}</div>}\n </div>\n );\n}\n\nfunction ModelQuotaCard({ model }: { model: RemainsModel }) {\n const fivePct = clamp(model.current_interval_remaining_percent ?? 0, 0, 100);\n const weekPct = clamp(model.current_weekly_remaining_percent ?? 0, 0, 100);\n const fiveConsumed = clamp(100 - fivePct, 0, 100);\n const weekConsumed = clamp(100 - weekPct, 0, 100);\n return (\n <Card id={`minimax-model-${model.model_name}`} className=\"minimax-model-card\">\n <div className=\"minimax-model-head\">\n <div className=\"minimax-model-name\">{model.model_name}</div>\n <div className={cn('minimax-model-status', fivePct < 25 || weekPct < 25 ? 'is-warn' : 'is-ok')}>\n {model.current_interval_status === 1 ? 'active' : 'idle'} ·{' '}\n {model.current_weekly_status === 1 ? 'week active' : 'week idle'}\n </div>\n </div>\n <div className=\"minimax-quota-rows\">\n <QuotaBar\n icon={<Activity size={12} />} label=\"5-hour rolling\"\n remainingPct={fivePct} consumedPct={fiveConsumed}\n used={model.current_interval_usage_count ?? 0} total={model.current_interval_total_count ?? 0}\n resetIn={model.intervalResetInHuman} resetISO={model.endTimeISO}\n />\n <QuotaBar\n icon={<Calendar size={12} />} label=\"Weekly\"\n remainingPct={weekPct} consumedPct={weekConsumed}\n used={model.current_weekly_usage_count ?? 0} total={model.current_weekly_total_count ?? 0}\n resetIn={model.weeklyResetInHuman} resetISO={model.weeklyEndTimeISO}\n />\n </div>\n </Card>\n );\n}\n\nfunction QuotaBar({ icon, label, remainingPct, consumedPct, used, total, resetIn, resetISO }: {\n icon: React.ReactNode; label: string; remainingPct: number; consumedPct: number;\n used: number; total: number; resetIn?: string; resetISO?: string;\n}) {\n const tone = remainingPct >= 75 ? 'good' : remainingPct >= 25 ? 'warn' : 'low';\n return (\n <div className={`minimax-quota-row is-${tone}`}>\n <div className=\"minimax-quota-head\">\n <span className=\"minimax-quota-label\">{icon} {label}</span>\n <span className=\"minimax-quota-remaining\">{remainingPct}% remaining</span>\n </div>\n <div className=\"minimax-bar\">\n <div className=\"minimax-bar-fill\" style={{ width: `${consumedPct}%` }} aria-label={`${consumedPct}% consumed`} />\n </div>\n <div className=\"minimax-quota-meta\">\n <span><strong>{used}</strong> / {total || '—'} requests</span>\n <span title={resetISO}>{resetIn ? `resets in ${resetIn}` : '—'}</span>\n </div>\n </div>\n );\n}\n\nfunction clamp(n: number, lo: number, hi: number) {\n return Math.max(lo, Math.min(hi, n));\n}\n\nfunction relativeTime(ts: number): string {\n const ms = Date.now() - ts;\n if (ms < 5_000) return 'just now';\n if (ms < 60_000) return `${Math.floor(ms / 1000)}s ago`;\n if (ms < 3_600_000) return `${Math.floor(ms / 60_000)}m ago`;\n return `${Math.floor(ms / 3_600_000)}h ago`;\n}\n\n// ─── Onboarding wizard ─────────────────────────────────────────────────\n\ntype OnboardingProps = {\n step: number; setStep: (n: number) => void;\n keyDraft: string; setKeyDraft: (s: string) => void;\n showKey: boolean; setShowKey: React.Dispatch<React.SetStateAction<boolean>>;\n verifying: boolean; verifyResult: TestResult | null;\n onVerify: () => void; onSkip: () => void; onManualKeySave: () => void;\n savingKey: boolean; status: Status;\n};\n\nfunction OnboardingWizard({ step, setStep, keyDraft, setKeyDraft, showKey, setShowKey, verifying, verifyResult, onVerify, onSkip, onManualKeySave, savingKey, status }: OnboardingProps) {\n return (\n <div className=\"view-container view-minimax-onboarding\">\n <header className=\"view-header\">\n <div className=\"view-header-titles\">\n <h1 className=\"view-title\">\n <Sparkles size={20} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />\n Set up MiniMax Token Plan tracking\n </h1>\n <p className=\"view-subtitle\">We'll read your Subscription Key and show your remaining quota.</p>\n </div>\n <div className=\"view-header-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onSkip}><X size={14} /> Skip for now</Button>\n </div>\n </header>\n\n <div className=\"minimax-wizard-stepper\">\n {(['Welcome', 'Get a key', 'Paste & test', 'Done']).map((label, i) => (\n <div key={label} className={cn('minimax-wizard-step', i === step && 'is-current', i < step && 'is-done', i > step && 'is-todo')}>\n <div className=\"minimax-wizard-step-bullet\">{i < step ? <CircleCheck size={14} /> : i + 1}</div>\n <div className=\"minimax-wizard-step-label\">{label}</div>\n </div>\n ))}\n </div>\n\n <Card id=\"minimax-wizard-card\">\n {step === 0 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">Welcome</h3>\n <p className=\"minimax-wizard-prose\">\n BizarHarness shows you how much of your MiniMax Token Plan quota you have left —\n both the <strong>5-hour rolling</strong> and <strong>weekly</strong> windows.\n </p>\n <ul className=\"minimax-wizard-list\">\n <li>Stored in <code>~/.local/share/opencode/auth.json</code>.</li>\n <li>Read fresh on every dashboard load.</li>\n <li>Never logged in full.</li>\n </ul>\n <div className=\"minimax-wizard-actions\">\n <Button onClick={() => setStep(1)} variant=\"primary\" size=\"md\">Get started <span style={{ marginLeft: 6 }}>→</span></Button>\n </div>\n </div>\n )}\n\n {step === 1 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">Get your Subscription Key</h3>\n <p className=\"minimax-wizard-prose\">Go to the MiniMax console and copy your Subscription Key.</p>\n <ol className=\"minimax-wizard-list\">\n <li>Open <a href=\"https://platform.minimax.io/user-center/payment/token-plan\" target=\"_blank\" rel=\"noreferrer\" className=\"minimax-wizard-link\"><ExternalLink size={12} /> platform.minimax.io</a></li>\n <li>Click <strong>Copy Subscription Key</strong>.</li>\n <li>Come back here and paste it.</li>\n </ol>\n <div className=\"minimax-wizard-actions\">\n <Button variant=\"secondary\" size=\"md\" onClick={() => setStep(0)}>← Back</Button>\n <Button variant=\"primary\" size=\"md\" onClick={() => setStep(2)}>I have my key <span style={{ marginLeft: 6 }}>→</span></Button>\n </div>\n </div>\n )}\n\n {step === 2 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\">Paste &amp; test</h3>\n <p className=\"minimax-wizard-prose\">Paste your key below. We'll test it against the real API before saving.</p>\n <div className=\"minimax-key-row\">\n <div className=\"minimax-key-input-wrap\">\n <KeyRound size={12} className=\"minimax-key-icon\" />\n <input type={showKey ? 'text' : 'password'} value={keyDraft} onChange={e => setKeyDraft(e.target.value)}\n placeholder=\"sk-cp-...\" spellCheck={false} autoComplete=\"off\" className=\"minimax-key-input\" autoFocus />\n <button type=\"button\" onClick={() => setShowKey(v => !v)} className=\"minimax-key-toggle\" aria-label={showKey ? 'Hide key' : 'Show key'}>\n {showKey ? <EyeOff size={13} /> : <Eye size={13} />}\n </button>\n </div>\n </div>\n {verifyResult && !verifyResult.ok && (\n <div className=\"minimax-wizard-error\"><AlertTriangle size={14} /><span><strong>Verification failed:</strong> {verifyResult.message ?? verifyResult.error}</span></div>\n )}\n <div className=\"minimax-wizard-actions\">\n <Button variant=\"secondary\" size=\"md\" onClick={() => setStep(1)}>← Back</Button>\n <Button variant=\"primary\" size=\"md\" onClick={onVerify} disabled={verifying || !keyDraft.trim()}>\n {verifying ? <Loader2 size={14} className=\"spin\" /> : <ShieldCheck size={14} />}\n {verifying ? 'Testing…' : 'Test &amp; save key'}\n </Button>\n </div>\n <p className=\"minimax-wizard-prose minimax-wizard-prose--muted\">\n Don't want to test first? <a href=\"#\" onClick={e => { e.preventDefault(); onManualKeySave(); }} className=\"minimax-wizard-link\">Save without testing</a>\n </p>\n </div>\n )}\n\n {step === 3 && (\n <div className=\"minimax-wizard-body\">\n <h3 className=\"minimax-wizard-title\"><CircleCheck size={18} style={{ verticalAlign: 'text-bottom', marginRight: 6 }} />All set</h3>\n <p className=\"minimax-wizard-prose\">The key works and is saved. Reloading so you can see your live quota.</p>\n <div className=\"minimax-wizard-actions\">\n <Button variant=\"primary\" size=\"md\" onClick={() => window.location.reload()}>View your quota →</Button>\n </div>\n </div>\n )}\n\n <div className=\"minimax-wizard-footer\">\n <ShieldCheck size={11} />\n <span>Key written to <code>~/.local/share/opencode/auth.json</code> with mode 0600.</span>\n </div>\n </Card>\n </div>\n );\n}\nexport const MiniMaxUsage = React.memo(MiniMaxUsageInner);\n","// src/components/BgStatusBadge.tsx — status pill for background agent instances.\n// Maps BackgroundStatus values to badge kinds from StatusBadge.\n\nimport { StatusBadge, type StatusBadgeProps } from './StatusBadge';\n\nconst STATUS_KIND: Record<string, StatusBadgeProps['kind']> = {\n pending: 'info',\n running: 'accent',\n done: 'success',\n failed: 'error',\n killed: 'neutral',\n timed_out: 'warning',\n};\n\nconst STATUS_LABELS: Record<string, string> = {\n pending: 'Pending',\n running: 'Running',\n done: 'Done',\n failed: 'Failed',\n killed: 'Killed',\n timed_out: 'Timed out',\n};\n\nexport function BgStatusBadge({ status, dot }: { status: string; dot?: boolean }) {\n const kind = STATUS_KIND[status] || 'neutral';\n const label = STATUS_LABELS[status] || status;\n return (\n <StatusBadge kind={kind} dot={dot}>\n {label}\n </StatusBadge>\n );\n}\n","// src/components/KillConfirmDialog.tsx — confirmation dialog for killing bg instances.\n// Provides both a JSX component and a convenience `openKillConfirmDialog` function.\n\nimport { Button } from './Button';\nimport type { ModalApi } from './Modal';\n\nexport type KillConfirmDialogProps = {\n instanceId: string;\n instanceName?: string;\n onConfirm: () => void | Promise<void>;\n onClose: () => void;\n};\n\n/**\n * Render inline inside a modal body. Usage:\n *\n * modal.open({\n * title: 'Kill background instance?',\n * children: (\n * <KillConfirmDialog\n * instanceId=\"bgr_abc\"\n * onConfirm={async () => { await killIt(); modal.close(); }}\n * onClose={() => modal.close()}\n * />\n * ),\n * });\n */\nexport function KillConfirmDialog({ instanceId, instanceName, onConfirm, onClose }: KillConfirmDialogProps) {\n return (\n <div>\n <p style={{ marginBottom: 16, lineHeight: 1.6 }}>\n Instance <code>{instanceId}</code>\n {instanceName ? <> ({instanceName})</> : null} will be terminated.\n This cannot be undone.\n </p>\n <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>\n <Button variant=\"ghost\" onClick={onClose}>Cancel</Button>\n <Button\n variant=\"danger\"\n onClick={async () => {\n await onConfirm();\n onClose();\n }}\n >\n Kill\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Convenience wrapper: open a kill-confirmation modal programmatically.\n * Calls `DELETE /api/background/${instanceId}` on confirm and shows a toast.\n */\nexport function openKillConfirmDialog(\n modal: ModalApi,\n toast: { success: (msg: string, duration?: number) => void; error: (msg: string) => void },\n instanceId: string,\n instanceName?: string,\n onSuccess?: () => void,\n) {\n modal.open({\n title: `Kill instance?`,\n width: 400,\n children: (\n <KillConfirmDialog\n instanceId={instanceId}\n instanceName={instanceName}\n onConfirm={async () => {\n try {\n const r = await fetch(`/api/background/${encodeURIComponent(instanceId)}`, { method: 'DELETE' });\n const data = await r.json();\n if (data.ok) {\n toast.success(`Instance ${instanceId} killed.`);\n onSuccess?.();\n } else {\n toast.error(`Kill failed: ${data.error || 'unknown error'}`);\n }\n } catch (err) {\n toast.error(`Kill failed: ${(err as Error).message}`);\n }\n }}\n onClose={() => modal.close()}\n />\n ),\n });\n}\n","// src/components/background/TmuxAttachCard.tsx — per-instance tmux attach card\n// v3.22.0\n//\n// Shows the tmux session name, a \"Copy attach command\" button, and\n// an \"Open in terminal\" button that POSTs to /api/background/:id/open-terminal.\n// When tmux is missing on the host, shows a friendly warning instead.\n\nimport { useState } from 'react';\nimport { Copy, Terminal, AlertTriangle } from 'lucide-react';\nimport { Button } from '../Button';\nimport { Card } from '../Card';\nimport { useToast } from '../Toast';\nimport { api } from '../../lib/api';\nimport type { BgInstance } from '../../lib/types';\n\ntype TmuxAttachCardProps = {\n instance: BgInstance;\n};\n\nexport function TmuxAttachCard({ instance }: TmuxAttachCardProps) {\n const toast = useToast();\n const [opening, setOpening] = useState(false);\n\n const sessionName = instance.tmuxSession;\n const attachCommand = sessionName ? `tmux attach -t ${sessionName}` : null;\n\n const copyCommand = async () => {\n if (!attachCommand) return;\n try {\n await navigator.clipboard.writeText(attachCommand);\n toast.success('Attach command copied');\n } catch {\n toast.error('Could not copy to clipboard');\n }\n };\n\n const openTerminal = async () => {\n if (!instance.instanceId || !sessionName) return;\n setOpening(true);\n try {\n const result = await api.post<{ ok: boolean; command: string; error?: string }>(\n `/background/${encodeURIComponent(instance.instanceId)}/open-terminal`,\n { emulator: 'system' },\n );\n if (result.ok) {\n toast.success('Opening terminal…');\n } else {\n toast.error(result.error || 'Failed to open terminal');\n // Fallback: copy the command so the user can paste it manually.\n if (attachCommand) {\n try {\n await navigator.clipboard.writeText(attachCommand);\n toast.success('Command copied to clipboard');\n } catch { /* noop */ }\n }\n }\n } catch (err) {\n toast.error(`Failed: ${(err as Error).message}`);\n // Fallback: copy command on network error.\n if (attachCommand) {\n try {\n await navigator.clipboard.writeText(attachCommand);\n toast.success('Command copied to clipboard');\n } catch { /* noop */ }\n }\n } finally {\n setOpening(false);\n }\n };\n\n // Don't render anything if there's no tmux session to attach to.\n if (!sessionName) {\n return (\n <Card variant=\"outlined\" className=\"bg-tmux-card bg-tmux-card-warn\">\n <div className=\"bg-tmux-card-header\">\n <AlertTriangle size={14} />\n <span>No tmux session</span>\n </div>\n <p className=\"bg-tmux-hint muted\">\n This instance does not have a tmux session attached.\n Sessions are created automatically when a background agent starts.\n </p>\n </Card>\n );\n }\n\n return (\n <Card variant=\"outlined\" className=\"bg-tmux-card\">\n <div className=\"bg-tmux-card-header\">\n <Terminal size={14} />\n <span>tmux session</span>\n {instance.tmuxActive !== false ? (\n <span className=\"badge badge-success\">live</span>\n ) : (\n <span className=\"badge badge-warning\">inactive</span>\n )}\n </div>\n\n <code className=\"mono bg-tmux-session-name\">{sessionName}</code>\n\n <p className=\"muted bg-tmux-hint\">\n Attach to the agent's tmux session from a terminal on the host\n running the dashboard.\n </p>\n\n <div className=\"bg-tmux-card-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={copyCommand} title=\"Copy attach command\">\n <Copy size={14} /> Copy\n </Button>\n <Button\n variant=\"primary\"\n size=\"sm\"\n onClick={openTerminal}\n loading={opening}\n title=\"Open in system terminal\"\n >\n <Terminal size={14} /> Open terminal\n </Button>\n </div>\n </Card>\n );\n}\n","// src/views/BackgroundAgents.tsx — dashboard tab listing active background-agent\n// instances (status === 'pending' | 'running'). Polls /api/background every 5s\n// as a safety net and refreshes on `background:change` WS events for near-real-time\n// updates. Per-instance actions: View live output (auto-refreshing modal), Open\n// in tmux (shows attach command), Kill (with confirm dialog).\nimport { useCallback, useEffect, useRef, useState, type UIEvent } from 'react';\nimport {\n Activity as ActivityIcon,\n Copy,\n Eye,\n Loader2,\n RefreshCw,\n Terminal,\n Trash2,\n} from 'lucide-react';\nimport { Button } from '../components/Button';\nimport { Card } from '../components/Card';\nimport { EmptyState } from '../components/EmptyState';\nimport { Spinner } from '../components/Spinner';\nimport { useModal } from '../components/Modal';\nimport { useToast } from '../components/Toast';\nimport { BgStatusBadge } from '../components/BgStatusBadge';\nimport { openKillConfirmDialog } from '../components/KillConfirmDialog';\nimport { TmuxAttachCard } from '../components/background/TmuxAttachCard';\nimport { api } from '../lib/api';\nimport { Ws } from '../lib/ws';\nimport { cn, formatTime, truncate } from '../lib/utils';\nimport type {\n BackgroundListResponse,\n BackgroundOutputResponse,\n BackgroundTmuxResponse,\n BgInstance,\n Settings,\n Snapshot,\n} from '../lib/types';\n\ntype Props = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n};\n\nconst POLL_INTERVAL_MS = 5_000;\nconst OUTPUT_REFRESH_MS = 2_000;\nconst PROMPT_TRUNCATE = 120;\n\nfunction isActive(b: BgInstance): boolean {\n return b.status === 'pending' || b.status === 'running';\n}\n\nfunction formatDuration(ms: number): string {\n if (!Number.isFinite(ms) || ms < 0) return '—';\n const total = Math.floor(ms / 1000);\n const h = Math.floor(total / 3600);\n const m = Math.floor((total % 3600) / 60);\n const s = total % 60;\n if (h > 0) return `${h}h ${m}m ${s}s`;\n if (m > 0) return `${m}m ${s}s`;\n return `${s}s`;\n}\n\nexport function BackgroundAgents(_props: Props) {\n const toast = useToast();\n const modal = useModal();\n const [instances, setInstances] = useState<BgInstance[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [, setTick] = useState(0);\n\n const load = useCallback(async () => {\n try {\n const res = await api.get<BackgroundListResponse>('/background');\n setInstances(Array.isArray(res?.instances) ? res.instances : []);\n setError(null);\n } catch (err) {\n setError((err as Error)?.message || 'Failed to load background agents.');\n } finally {\n setLoading(false);\n }\n }, []);\n\n // Initial load + polling safety net.\n useEffect(() => {\n load();\n const id = setInterval(load, POLL_INTERVAL_MS);\n return () => clearInterval(id);\n }, [load]);\n\n // 1s tick to keep the duration strings fresh.\n useEffect(() => {\n const id = setInterval(() => setTick((t) => (t + 1) % 1_000_000), 1000);\n return () => clearInterval(id);\n }, []);\n\n // WS subscription — refetch on any background:change / cleanup event.\n // Matches the Settings.tsx pattern of opening a private WS instance.\n // Acceptable because background change volume is low and the dashboard\n // already creates parallel WS connections for other tabs.\n useEffect(() => {\n const ws = new Ws();\n const off = ws.on((msg) => {\n const t = (msg as { type?: string }).type;\n if (t === 'background:change' || t === 'background:cleanup') {\n load();\n }\n });\n return () => {\n off();\n ws.close();\n };\n }, [load]);\n\n const active = instances.filter(isActive);\n\n // ─── Handlers ─────────────────────────────────────────────────────────\n\n const onOpenOutput = (b: BgInstance) => {\n openOutputModal(modal, b);\n };\n\n const onOpenTmux = async (b: BgInstance) => {\n try {\n const info = await api.get<BackgroundTmuxResponse>(\n `/background/${encodeURIComponent(b.instanceId)}/tmux`,\n );\n openTmuxModal(modal, info);\n } catch (err) {\n toast.error(`Tmux info failed: ${(err as Error).message}`);\n }\n };\n\n const onKill = (b: BgInstance) => {\n openKillConfirmDialog(modal, toast, b.instanceId, b.agent || b.prompt, () => {\n // Optimistic remove — the WS broadcast + polling safety net will reconcile.\n setInstances((cur) => cur.filter((x) => x.instanceId !== b.instanceId));\n });\n };\n\n // ─── Render ───────────────────────────────────────────────────────────\n\n if (loading) {\n return (\n <div className=\"bg-active-view\">\n <div className=\"bg-active-loading\">\n <Spinner size=\"md\" />\n <span>Loading background agents…</span>\n </div>\n </div>\n );\n }\n\n if (error) {\n return (\n <div className=\"bg-active-view\">\n <EmptyState\n icon={<ActivityIcon size={32} />}\n title=\"Couldn't load background agents\"\n message={error}\n action={\n <Button variant=\"primary\" onClick={load}>\n <RefreshCw size={14} /> Retry\n </Button>\n }\n />\n </div>\n );\n }\n\n return (\n <div className=\"bg-active-view\">\n <div className=\"bg-active-header\">\n <div className=\"bg-active-header-text\">\n <h2 className=\"bg-active-title\">Active Background Agents</h2>\n <p className=\"bg-active-subtitle muted\">\n {active.length} active · {instances.length} total in store\n </p>\n </div>\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Refresh now\">\n <RefreshCw size={14} /> Refresh\n </Button>\n </div>\n\n {active.length === 0 ? (\n <EmptyState\n icon={<ActivityIcon size={32} />}\n title=\"No active background agents\"\n message=\"Spawn one from the Agents tab or via the bizar_spawn_background tool.\"\n />\n ) : (\n <div className=\"bg-active-list\">\n {active.map((b) => (\n <BackgroundAgentCard\n key={b.instanceId}\n inst={b}\n onViewOutput={() => onOpenOutput(b)}\n onOpenTmux={() => onOpenTmux(b)}\n onKill={() => onKill(b)}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\n// ─── Per-instance card ─────────────────────────────────────────────────────\n\nfunction BackgroundAgentCard({\n inst,\n onViewOutput,\n onOpenTmux,\n onKill,\n}: {\n inst: BgInstance;\n onViewOutput: () => void;\n onOpenTmux: () => void;\n onKill: () => void;\n}) {\n const startedMs = typeof inst.startedAt === 'number' ? inst.startedAt : 0;\n const startedLabel = startedMs ? formatTime(startedMs) : '—';\n const durationMs = startedMs ? Date.now() - startedMs : 0;\n const prompt = truncate(inst.prompt, PROMPT_TRUNCATE);\n\n return (\n <Card className=\"bg-active-card\" variant=\"elevated\">\n <div className=\"bg-active-card-top\">\n <div className=\"bg-active-card-id\">\n <code className=\"mono\">{inst.instanceId}</code>\n <BgStatusBadge status={inst.status || 'pending'} dot />\n </div>\n <div className=\"bg-active-card-agent\">\n <span className=\"bg-active-card-agent-label\">Agent</span>\n <span className=\"bg-active-card-agent-name\">{inst.agent || 'unknown'}</span>\n </div>\n </div>\n\n {prompt && <div className=\"bg-active-prompt\">{prompt}</div>}\n\n {inst.currentStep && (\n <div className=\"bg-active-step\">\n <span className=\"bg-active-step-label\">Step:</span>\n <span className=\"bg-active-step-value\">{inst.currentStep}</span>\n </div>\n )}\n\n {typeof inst.progress === 'number' && (\n <div className=\"progress-bar\" aria-label=\"Progress\">\n <div\n className=\"progress-fill\"\n style={{ width: `${Math.max(0, Math.min(100, inst.progress))}%` }}\n />\n <span className=\"progress-label\">{Math.round(inst.progress)}%</span>\n </div>\n )}\n\n <div className=\"bg-active-meta\">\n <span title={startedLabel}>\n <strong>Started:</strong> {startedLabel}\n </span>\n <span>\n <strong>Duration:</strong> {formatDuration(durationMs)}\n </span>\n <span>\n <strong>Tool calls:</strong> {inst.toolCallCount ?? 0}\n </span>\n {inst.tmuxSession && (\n <span className={cn(inst.tmuxActive && 'bg-active-meta-tmux-live')}>\n <strong>tmux:</strong> <code className=\"mono\">{inst.tmuxSession}</code>\n {inst.tmuxActive ? ' · live' : ''}\n </span>\n )}\n </div>\n\n <div className=\"bg-active-actions\">\n <Button variant=\"secondary\" size=\"sm\" onClick={onViewOutput}>\n <Eye size={14} /> View output\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={onOpenTmux}>\n <Terminal size={14} /> Open in tmux\n </Button>\n <Button variant=\"danger\" size=\"sm\" onClick={onKill}>\n <Trash2 size={14} /> Kill\n </Button>\n </div>\n\n <TmuxAttachCard instance={inst} />\n </Card>\n );\n}\n\n// ─── Output modal (auto-refresh) ───────────────────────────────────────────\n\nfunction openOutputModal(\n modal: ReturnType<typeof useModal>,\n inst: BgInstance,\n) {\n modal.open({\n title: `Output — ${inst.agent || inst.instanceId}`,\n width: 720,\n children: <OutputModalBody instanceId={inst.instanceId} />,\n });\n}\n\nfunction OutputModalBody({ instanceId }: { instanceId: string }) {\n const toast = useToast();\n const [output, setOutput] = useState<string>('');\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [available, setAvailable] = useState(true);\n const refBottom = useRef<HTMLDivElement | null>(null);\n const refAutoscroll = useRef(true);\n\n const load = useCallback(async () => {\n try {\n const r = await api.get<BackgroundOutputResponse>(\n `/background/${encodeURIComponent(instanceId)}/output?lines=200`,\n );\n setOutput(r?.output ?? '');\n setAvailable(r?.available !== false);\n setError(null);\n } catch (err) {\n setError((err as Error)?.message || 'Failed to load output.');\n } finally {\n setLoading(false);\n }\n }, [instanceId]);\n\n useEffect(() => {\n load();\n const id = setInterval(load, OUTPUT_REFRESH_MS);\n return () => clearInterval(id);\n }, [load]);\n\n // Auto-scroll to bottom only if user is already near the bottom.\n useEffect(() => {\n if (!refAutoscroll.current) return;\n refBottom.current?.scrollIntoView({ behavior: 'auto', block: 'end' });\n }, [output]);\n\n const onScroll = (e: UIEvent<HTMLDivElement>) => {\n const el = e.currentTarget;\n const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 24;\n refAutoscroll.current = atBottom;\n };\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(output);\n toast.success('Output copied.');\n } catch {\n // ignore — clipboard may be unavailable in some contexts\n }\n };\n\n return (\n <div className=\"bg-output-modal\">\n <div className=\"bg-output-toolbar\">\n <span className=\"muted\">\n {available ? `${output.length} chars · auto-refresh 2s` : 'Output unavailable'}\n </span>\n <div className=\"bg-output-toolbar-actions\">\n <Button variant=\"ghost\" size=\"sm\" onClick={load} title=\"Refresh now\">\n <RefreshCw size={14} /> Refresh\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={copy} disabled={!output}>\n <Copy size={14} /> Copy\n </Button>\n </div>\n </div>\n {loading && !output ? (\n <div className=\"bg-output-loading\">\n <Loader2 size={16} className=\"spin\" /> Loading…\n </div>\n ) : error ? (\n <div className=\"bg-output-error\">{error}</div>\n ) : !output ? (\n <div className=\"bg-output-empty muted\">No output captured yet.</div>\n ) : (\n <div className=\"bg-output-scroll\" onScroll={onScroll}>\n <pre className=\"bg-output-pre mono\">\n <code>{output}</code>\n </pre>\n <div ref={refBottom} />\n </div>\n )}\n </div>\n );\n}\n\n// ─── Tmux attach modal ─────────────────────────────────────────────────────\n\nfunction openTmuxModal(\n modal: ReturnType<typeof useModal>,\n info: BackgroundTmuxResponse,\n) {\n const cmd = info.attachCommand || info.session || '';\n modal.open({\n title: 'Attach to tmux',\n width: 520,\n children: <TmuxModalBody info={info} cmd={cmd} />,\n });\n}\n\nfunction TmuxModalBody({ info, cmd }: { info: BackgroundTmuxResponse; cmd: string }) {\n const [copied, setCopied] = useState(false);\n const onCopy = async () => {\n try {\n await navigator.clipboard.writeText(cmd);\n setCopied(true);\n window.setTimeout(() => setCopied(false), 1500);\n } catch {\n /* noop */\n }\n };\n\n return (\n <div className=\"bg-tmux-modal\">\n {!cmd ? (\n <p className=\"muted\">No tmux session attached to this instance.</p>\n ) : (\n <>\n <p className=\"bg-tmux-meta\">\n {info.exists ? (\n <span className=\"badge badge-success\">session live</span>\n ) : (\n <span className=\"badge badge-warning\">\n session not running{info.reason ? ` — ${info.reason}` : ''}\n </span>\n )}\n {info.session && (\n <span className=\"bg-tmux-session muted\">\n · session <code className=\"mono\">{info.session}</code>\n </span>\n )}\n </p>\n <label className=\"field-label\">Attach command</label>\n <div className=\"bg-tmux-command-row\">\n <code className=\"bg-tmux-command mono\">{cmd}</code>\n <Button variant=\"secondary\" size=\"sm\" onClick={onCopy}>\n <Copy size={14} /> {copied ? 'Copied' : 'Copy'}\n </Button>\n </div>\n <p className=\"muted bg-tmux-hint\">\n Paste this into a terminal on the host running the dashboard. The\n dashboard itself does not open terminals.\n </p>\n </>\n )}\n </div>\n );\n}","// src/App.tsx — root shell. Wires data + contexts + tab routing.\n\nimport { Component, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Topbar, TABS } from './components/Topbar';\nimport { Sidebar } from './components/Sidebar';\nimport { ModalProvider, useModal } from './components/Modal';\nimport { ToastProvider, useToast } from './components/Toast';\nimport { SearchModal } from './components/SearchModal';\nimport { Notifications } from './components/Notifications';\nimport { api, ApiError } from './lib/api';\nimport { CommandDialog, type DialogDescriptor } from './components/CommandDialog';\nimport { Ws } from './lib/ws';\nimport {\n applyTheme,\n applyThemeTokens,\n type Artifact,\n type Settings,\n type SettingsResponse,\n type Snapshot,\n type WsMessage,\n type WsStatus,\n type ProjectRecord,\n type SearchResult,\n} from './lib/types';\nimport { Overview } from './views/Overview';\nimport { Chat } from './views/Chat';\nimport { Agents } from './views/Agents';\nimport { Artifacts } from './views/Artifacts';\nimport { Tasks } from './views/Tasks';\nimport { Activity } from './views/Activity';\nimport { Config } from './views/Config';\nimport { SettingsView } from './views/Settings';\nimport { Mods } from './views/Mods';\nimport { ModView, type ModView as ModViewType } from './views/ModView';\nimport { Schedules } from './views/Schedules';\nimport { Skills } from './views/Skills';\nimport { Memory } from './views/Memory';\nimport { History } from './views/History';\nimport { MiniMaxUsage } from './views/MiniMaxUsage';\nimport { BackgroundAgents } from './views/BackgroundAgents';\nimport { Spinner } from './components/Spinner';\nimport { Button } from './components/Button';\nimport { AlertTriangle, Globe, LayoutTemplate, X } from 'lucide-react';\nimport './styles/main.css';\n\ntype ViewProps = {\n snapshot: Snapshot;\n settings: Settings;\n activeTab: string;\n setActiveTab: (id: string) => void;\n refreshSnapshot: () => Promise<void>;\n /**\n * v3.3.0 — Cross-view scratch state. The \"Open in chat\" button\n * on the Agents tab sets `pendingInitialAgent`, which the Chat\n * view reads on mount (and clears). Keeps the chat a true\n * one-click handoff without needing URL state.\n */\n crossState?: CrossViewState;\n setCrossState?: (patch: Partial<CrossViewState>) => void;\n};\n\nexport type CrossViewState = {\n initialAgent?: string | null;\n};\n\nconst VIEW_MAP: Record<string, (p: ViewProps) => React.ReactNode> = {\n overview: Overview,\n chat: Chat,\n agents: Agents,\n artifacts: Artifacts,\n memory: Memory,\n tasks: Tasks,\n activity: Activity,\n background: BackgroundAgents,\n config: Config,\n settings: SettingsView,\n mods: Mods,\n schedules: Schedules,\n skills: Skills,\n history: History,\n minimax: MiniMaxUsage,\n};\n\nconst VERSION = 'v4.5.0';\n\n/**\n * Render the active view. If `activeTab` matches a built-in tab id,\n * use VIEW_MAP. If it matches a mod view id (any id not in VIEW_MAP),\n * render the ModView component with that view id.\n */\nfunction renderActiveView(\n activeTab: string,\n viewProps: ViewProps,\n modViews: ModViewType[],\n reloadKey: number,\n): React.ReactNode {\n if (VIEW_MAP[activeTab]) {\n const V = VIEW_MAP[activeTab];\n return <V {...viewProps} />;\n }\n // Mod view — find by id\n const mv = modViews.find((v) => v.id === activeTab);\n if (mv) {\n return (\n <ModView\n viewId={mv.id}\n reloadKey={reloadKey}\n activeTab={viewProps.activeTab}\n setActiveTab={viewProps.setActiveTab}\n />\n );\n }\n // Fallback to Overview\n const V = VIEW_MAP.overview;\n return <V {...viewProps} />;\n}\n\n// v3.6.2 — Inline token-entry form shown on the boot-error screen when\n// the server returns 401 (reverse-proxy / Tailscale Serve scenario).\n// The user pastes the token, it is saved to localStorage, and boot is\n// retried. The form closes on Escape or on successful save.\nfunction TokenEntryForm({ onSaved }: { onSaved: () => void }) {\n const [value, setValue] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Auto-focus the input on mount\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n const submit = () => {\n const tok = value.trim();\n if (!tok) return;\n api.setToken(tok);\n onSaved();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onSaved();\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n submit();\n }\n };\n\n return (\n <form\n className=\"token-entry-form\"\n onSubmit={(e) => { e.preventDefault(); submit(); }}\n >\n <div className=\"token-entry-row\">\n <input\n ref={inputRef}\n type=\"password\"\n className=\"input mono\"\n value={value}\n onChange={(e) => setValue(e.target.value)}\n placeholder=\"Paste auth token\"\n spellCheck={false}\n autoComplete=\"off\"\n onKeyDown={handleKeyDown}\n />\n <Button type=\"submit\" variant=\"primary\" size=\"sm\" disabled={!value.trim()}>\n Save &amp; retry\n </Button>\n </div>\n <p className=\"token-entry-hint\">\n Where do I find this token? Check the file{' '}\n <code>~/.config/bizar/dashboard-secret</code> on the machine\n running the dashboard, or look for it in the server output.\n </p>\n </form>\n );\n}\n\nexport function App() {\n return (\n <ToastProvider>\n <ModalProvider>\n <Shell />\n </ModalProvider>\n </ToastProvider>\n );\n}\n\nfunction Shell() {\n const toast = useToast();\n const modalApi = useModal();\n const { isModalOpen } = modalApi;\n const isModalOpenRef = useRef(false);\n const [activeTab, setActiveTab] = useState<string>('overview');\n const [snapshot, setSnapshot] = useState<Snapshot | null>(null);\n const [settings, setSettings] = useState<Settings | null>(null);\n const [wsStatus, setWsStatus] = useState<WsStatus>('connecting');\n const [bootError, setBootError] = useState<string | null>(null);\n const [authPromptOpen, setAuthPromptOpen] = useState(false);\n const [searchOpen, setSearchOpen] = useState(false);\n const [stuckAgents, setStuckAgents] = useState<{ name: string }[]>([]);\n const [stuckBannerDismissed, setStuckBannerDismissed] = useState(false);\n // v3.20.3 — Mod views become first-class nav entries. Fetched on mount\n // and after every mod install/uninstall/enable toggle.\n const [modViews, setModViews] = useState<ModViewType[]>([]);\n const [modViewsReloadKey, setModViewsReloadKey] = useState(0);\n const wsRef = useRef<Ws | null>(null);\n const [ws, setWs] = useState<Ws | null>(null);\n\n // Fetch installed mod views (any enabled mod with a web/index.html or\n // a views/registry.json entry). These become top-level nav tabs.\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const r = await api.get<{ views: ModViewType[] }>('/mods/views');\n if (cancelled) return;\n setModViews(r.views || []);\n } catch {\n if (!cancelled) setModViews([]);\n }\n })();\n return () => { cancelled = true; };\n }, [modViewsReloadKey, snapshot?.mods]);\n\n // Re-fetch mod views when ws events arrive about mod changes.\n useEffect(() => {\n if (!ws) return;\n const off = ws.on((msg: { type?: string }) => {\n if (msg?.type === 'mod:change' || msg?.type === 'mod:enabled' || msg?.type === 'mod:installed') {\n setModViewsReloadKey((n) => n + 1);\n }\n });\n return () => off();\n }, [ws]);\n\n // Apply theme tokens\n useEffect(() => {\n if (settings?.theme) {\n applyTheme(settings.theme);\n applyThemeTokens(settings.theme);\n }\n }, [settings?.theme]);\n\n // v3.6.1 — Keep a ref in sync with isModalOpen so the keyboard handler\n // always reads the current value even between state updates and effect\n // re-runs. This closes the race window where modal.close() has cleared\n // the state but the old keyboard handler (with isModalOpen=false in\n // its closure) hasn't been replaced yet.\n useEffect(() => {\n isModalOpenRef.current = isModalOpen;\n }, [isModalOpen]);\n\n // System-mode listener\n useEffect(() => {\n if (settings?.theme?.mode !== 'system') return;\n const mql = window.matchMedia('(prefers-color-scheme: light)');\n const handler = () => applyTheme(settings.theme.mode);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, [settings?.theme?.mode]);\n\n // v3.6.2 — Boot logic extracted to retryBoot so it can be re-invoked\n // after the user pastes a token in the inline recovery form.\n const retryBoot = useCallback(async () => {\n let cancelled = false;\n\n const loadBootData = () =>\n Promise.all([\n api.get<Snapshot>('/snapshot').catch(() => null),\n api.get<SettingsResponse>('/settings').catch(() => null),\n api.get<{ stuck: { name: string }[] }>('/agents/stuck').catch(() => null),\n ]);\n\n const applyBootData = (\n snap: Snapshot | null,\n set: SettingsResponse | null,\n stuck: { stuck: { name: string }[] } | null,\n ) => {\n if (snap) setSnapshot(snap);\n if (set?.data) setSettings(set.data);\n if (stuck?.stuck) setStuckAgents(stuck.stuck);\n };\n\n try {\n const auth = await api.probeAuthStatus();\n const [snap, set, stuck] = await loadBootData();\n if (cancelled) return;\n\n applyBootData(snap, set, stuck);\n if (snap || set) {\n setBootError(null);\n return;\n }\n\n if (!auth.loopback) {\n setBootError('Dashboard server unreachable.');\n return;\n }\n\n await new Promise((resolve) => setTimeout(resolve, 1000));\n if (cancelled) return;\n\n const [retrySnap, retrySet, retryStuck] = await loadBootData();\n if (cancelled) return;\n\n applyBootData(retrySnap, retrySet, retryStuck);\n if (!retrySnap && !retrySet) {\n setBootError('Dashboard server unreachable.');\n }\n } catch (err) {\n if (cancelled) return;\n const msg = (err as Error)?.message ?? 'unknown error';\n // v3.6.2 — If we got a 401, the user needs to supply a token.\n // Surface the form inline instead of just the error message.\n if (err instanceof ApiError && err.status === 401) {\n setBootError(msg);\n setAuthPromptOpen(true);\n toast.error(`Auth required: ${msg}`);\n return;\n }\n setBootError(msg);\n toast.error(`Failed to load: ${msg}`);\n }\n }, [toast]);\n\n // Initial fetch — runs once on mount\n useEffect(() => {\n let cancelled = false;\n const id = setTimeout(() => {\n if (!cancelled) retryBoot();\n }, 0);\n return () => {\n cancelled = true;\n clearTimeout(id);\n };\n }, [retryBoot]);\n\n // Apply defaultTab ONCE on mount only — must NOT re-fire on toast changes\n useEffect(() => {\n let cancelled = false;\n api.get<SettingsResponse>('/settings')\n .then((set) => {\n if (cancelled) return;\n const defaultTab = set?.data?.ui?.defaultTab;\n if (defaultTab) setActiveTab(defaultTab);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, []); // empty deps — runs once on mount\n\n // v3.1.0 — Periodic stuck-agent poll. Light-weight; the server does\n // the threshold math and only returns the list.\n useEffect(() => {\n let cancelled = false;\n const tick = async () => {\n try {\n const r = await api.get<{ stuck: { name: string }[] }>('/agents/stuck');\n if (!cancelled) {\n setStuckAgents((cur) => {\n const next = r.stuck || [];\n const wasEmpty = cur.length === 0;\n if (wasEmpty && next.length > 0) {\n toast.warning(`${next.length} agent${next.length === 1 ? '' : 's'} stuck`, 5000);\n }\n return next;\n });\n }\n } catch {\n /* best-effort */\n }\n };\n const id = setInterval(tick, 30_000);\n tick();\n return () => {\n cancelled = true;\n clearInterval(id);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // WebSocket lifecycle\n useEffect(() => {\n const ws = new Ws();\n wsRef.current = ws;\n setWs(ws);\n const offStatus = ws.onStatus((s) => setWsStatus(s));\n const offMsg = ws.on((msg: WsMessage) => {\n if (msg.type === 'snapshot' && 'data' in msg && msg.data) {\n setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...msg.data }));\n } else if (msg.type === 'change') {\n const m = msg;\n const file = m.path?.split('/').pop() || m.path || '';\n toast.info(`File changed: ${file}`, 2500);\n } else if (msg.type === 'tasks:change') {\n const m = msg;\n setSnapshot((cur) => {\n if (!cur) return cur;\n const tasks = (cur.tasks || []).map((t) =>\n t.id === m.task.id ? m.task : t,\n );\n const exists = tasks.some((t) => t.id === m.task.id);\n return { ...cur, tasks: exists ? tasks : [m.task, ...tasks] };\n });\n } else if (msg.type === 'tasks:delete') {\n const m = msg;\n setSnapshot((cur) =>\n cur\n ? { ...cur, tasks: (cur.tasks || []).filter((t) => t.id !== m.id) }\n : cur,\n );\n } else if (msg.type === 'settings:change') {\n const m = msg;\n if (m.settings) setSettings(m.settings);\n } else if (msg.type === 'project:change') {\n // Refresh the whole snapshot to pick up the new active project\n api\n .get<Snapshot>('/snapshot')\n .then((s) => setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s })))\n .catch(() => undefined);\n } else if (msg.type === 'agents:change' || msg.type === 'schedules:change') {\n api\n .get<Snapshot>('/snapshot')\n .then((s) => setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s })))\n .catch(() => undefined);\n } else if (msg.type === 'agent:status' || msg.type === 'agent:restarted') {\n const m = msg;\n setSnapshot((cur) => {\n if (!cur) return cur;\n const agents = (cur.agents || []).map((a) => (a.name === m.agent.name ? m.agent : a));\n return { ...cur, agents };\n });\n } else if (msg.type === 'artifact:change') {\n // Artifacts list refreshes after any artifact mutation.\n api\n .get<{ artifacts: Artifact[] }>('/artifacts')\n .then((d) => {\n setSnapshot((cur) => (cur ? { ...cur, artifacts: d.artifacts || [] } : cur));\n })\n .catch(() => undefined);\n } else if (msg.type === 'agent:stuck') {\n const m = msg;\n setStuckAgents(m.agents || []);\n } else if (msg.type === 'dialog:show') {\n // v0.5.1: Open a command dialog received from the plugin via WS broadcast.\n const m = msg as { type: 'dialog:show'; dialog: DialogDescriptor };\n if (m.dialog) {\n modalApi.open({\n title: m.dialog.title,\n width: 520,\n children: <CommandDialog dialog={m.dialog} onClose={() => modalApi.close()} />,\n });\n }\n }\n });\n return () => {\n offStatus();\n offMsg();\n ws.close();\n setWs(null);\n };\n }, [toast]);\n\n const subscribeToWs = useCallback((cb: (msg: WsMessage) => void) => {\n if (!ws) return () => undefined;\n return ws.on(cb);\n }, [ws]);\n\n // v3.3.1 — Track recent user interactions. After any mousedown/click/\n // focusin/keydown we set a 1500ms \"safe\" window during which digit-key\n // shortcuts are suppressed. This protects against the case where a modal\n // closes on a click and the user's next key event (often a key-repeat)\n // would otherwise trigger setActiveTab(\"overview\").\n // v3.3.0 used 250ms which was too short (keyboard repeat can fire later).\n //\n // v3.5.4 (bug #4) — The safe window alone was not enough. Users were\n // still being bounced to overview after action grace windows expired\n // because the transientFocus check (activeElement === body) was nested\n // inside the safe-window branch. See the handler below for the new\n // two-gate model: (1) body/null focus ALWAYS blocks digit shortcuts;\n // (2) the safe window relaxes that block only for the first 1500ms\n // after an interaction. After the window passes, the user must\n // explicitly focus a real element before digit-key tab switches work.\n const safeUntilRef = useRef(0);\n useEffect(() => {\n const bump = () => {\n safeUntilRef.current = Date.now() + 1500;\n };\n document.addEventListener('mousedown', bump, true);\n document.addEventListener('click', bump, true);\n document.addEventListener('focusin', bump, true);\n document.addEventListener('keydown', bump, true);\n return () => {\n document.removeEventListener('mousedown', bump, true);\n document.removeEventListener('click', bump, true);\n document.removeEventListener('focusin', bump, true);\n document.removeEventListener('keydown', bump, true);\n };\n }, []);\n\n // Keyboard shortcuts\n useEffect(() => {\n const map: Record<string, string> = {};\n TABS.forEach((t, i) => {\n map[String(i + 1)] = t.id;\n });\n const handler = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {\n e.preventDefault();\n setSearchOpen(true);\n return;\n }\n if (e.key === '/' && !e.metaKey && !e.ctrlKey) {\n const t = (e.target as HTMLElement | null)?.tagName?.toLowerCase();\n if (t !== 'input' && t !== 'textarea' && !((e.target as HTMLElement)?.isContentEditable)) {\n e.preventDefault();\n setSearchOpen(true);\n return;\n }\n }\n // v3.2.0 — broader guard. Digit-key shortcuts must not fire while\n // the user is interacting with ANY focusable form control or a\n // modal/contentEditable region. Previously this only excluded\n // <input> and <textarea>, which let digit presses through when\n // focus was on a <select>, <button>, <label>, or contenteditable\n // node — causing mysterious tab switches (most often back to\n // \"overview\" via the `1` shortcut).\n //\n // v3.3.1 — \"click after modal close\" guard (extended). When a modal\n // closes (e.g. the user clicks \"Submit to Odin\" in the Tasks tab),\n // React portals the modal out of the DOM and the previously-focused\n // button is unmounted. Focus falls back to <body>. If the user then\n // accidentally taps a digit key (1/2/3/...) — or a key-repeat fires\n // while they're still mid-click — the handler would switch tabs.\n // The safe window is now 1500ms (up from 250ms) and covers all\n // interaction types (mousedown/click/focusin/keydown).\n //\n // v3.3.1 — transient-focus check. If active element is body/null,\n // treat it as a transient focus state (modal close → body fallback)\n // and bail. v3.5.4 (bug #4): this check is now independent of the\n // safe window — it ALWAYS applies. Previously it was only effective\n // inside the 1500ms grace window, which let digit-key presses through\n // once the window expired. The user would see themselves bounced back\n // to overview (digit `1`) after every action whose grace window had\n // already elapsed. The safe window now only relaxes the rule\n // temporarily for the action that JUST happened; it must be combined\n // with a real focus element for digit-key shortcuts to fire.\n const activeEl = document.activeElement;\n const transientFocus = !activeEl || activeEl === document.body || activeEl === document.documentElement;\n if (transientFocus) {\n // Even within the grace window, body/null focus means there is\n // no real input target — refuse to switch tabs. The user must\n // explicitly click into a focusable element (input, button, etc.)\n // to enable digit-key tab switching again.\n return;\n }\n const target = e.target as HTMLElement | null;\n const tag = target?.tagName?.toLowerCase();\n const isFormControl =\n tag === 'input' ||\n tag === 'textarea' ||\n tag === 'select' ||\n tag === 'button' ||\n tag === 'option' ||\n tag === 'label' ||\n !!target?.isContentEditable;\n // Inside a form? Even safer: walk up to check.\n let inForm = false;\n if (target && typeof target.closest === 'function') {\n inForm = !!target.closest('form, [role=\"dialog\"], [contenteditable], [data-no-key]');\n }\n // v3.5.2 — reject key-repeat events. When a user presses and holds\n // a digit key the browser fires repeated keydown events; we must only\n // act on the first (e.repeat === false). This prevents the modal-close\n // + key-repeat scenario from switching tabs after the safe window closes.\n if (e.repeat) return;\n // v3.6.1 — Check isModalOpenRef (not the closure variable) so we always\n // see the current value even between state update and effect re-run.\n if (isModalOpenRef.current) return;\n if (\n isFormControl ||\n inForm ||\n e.metaKey ||\n e.ctrlKey ||\n e.altKey ||\n e.shiftKey ||\n Date.now() < safeUntilRef.current\n )\n return;\n const id = map[e.key];\n if (id) {\n e.preventDefault();\n setActiveTab(id);\n }\n };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, []);\n\n const refreshSnapshot = useMemo(\n () => async () => {\n try {\n const s = await api.get<Snapshot>('/snapshot');\n setSnapshot((cur) => ({ ...(cur ?? ({} as Snapshot)), ...s }));\n } catch (err) {\n toast.error(`Refresh failed: ${(err as Error).message}`);\n }\n },\n [toast],\n );\n\n // v3.20.3 — Merge built-in tabs with installed mod views. Mod views\n // are appended after the built-in tabs and use the same rendering\n // surface; their tab ids are mod view ids (e.g. 'graphify:web').\n // Declared AFTER refreshSnapshot so the deps list has the right value.\n const mergedTabs = useMemo(() => {\n const modTabs = modViews.map((v) => ({\n id: v.id,\n label: v.label,\n icon: v.kind === 'iframe' ? Globe : LayoutTemplate,\n isMod: true,\n modId: v.modId,\n }));\n return [...TABS, ...modTabs];\n }, [modViews]);\n\n // Surface the underlying view for the active tab (built-in or mod).\n // Declared AFTER refreshSnapshot so its useMemo factory can capture it.\n const renderedView = useMemo(() => {\n if (snapshot && settings) {\n const viewProps: ViewProps = {\n snapshot,\n settings,\n activeTab,\n setActiveTab: setActiveTab,\n refreshSnapshot,\n };\n return renderActiveView(activeTab, viewProps, modViews, modViewsReloadKey);\n }\n return null;\n }, [activeTab, snapshot, settings, modViews, modViewsReloadKey, refreshSnapshot]);\n\n const refreshProjects = async () => {\n try {\n const r = await api.get<{ projects: ProjectRecord[]; active: string | null }>('/projects');\n setSnapshot((cur) =>\n cur ? { ...cur, projects: r.projects || [], activeProject: r.projects?.find((p) => p.id === r.active) || null } : cur,\n );\n } catch (err) {\n toast.error(`Projects refresh failed: ${(err as Error).message}`);\n }\n };\n\n const onActivateProject = async (id: string) => {\n try {\n await api.post(`/projects/${encodeURIComponent(id)}/activate`);\n // WS will fire project:change and refresh; but also reflect locally\n setSnapshot((cur) => {\n if (!cur) return cur;\n return {\n ...cur,\n activeProject: cur.projects.find((p) => p.id === id) || null,\n };\n });\n } catch (err) {\n toast.error(`Activate failed: ${(err as Error).message}`);\n }\n };\n\n const onSearchSelect = (r: SearchResult) => {\n const t = r.type;\n if (t === 'agent') setActiveTab('agents');\n else if (t === 'task') setActiveTab('tasks');\n else if (t === 'mod') setActiveTab('mods');\n else if (t === 'schedule') setActiveTab('schedules');\n else if (t === 'project') {\n const id = (r.item as ProjectRecord).id;\n onActivateProject(id);\n } else if (t === 'command') {\n // No command page; just toast\n toast.info(`/${(r.item as { name: string }).name} — run from the TUI`, 2500);\n } else if (t === 'setting') {\n // v3.0.4 — Jump to Settings view and scroll to the matching row.\n const settingId = (r.item as { id?: string; path?: string }).id\n || (r.item as { path?: string }).path\n || '';\n setActiveTab('settings');\n // Defer the scroll to allow the view to mount, then apply a brief\n // CSS highlight. We poll a few times because the Settings view\n // mounts lazily after tab switch.\n const tryScroll = (tries: number) => {\n if (tries <= 0) return;\n const el = settingId\n ? document.querySelector(`[data-setting-id=\"${CSS.escape(settingId)}\"]`)\n : null;\n if (el) {\n (el as HTMLElement).scrollIntoView({ behavior: 'smooth', block: 'center' });\n el.classList.remove('setting-flash');\n // Force reflow so the animation re-triggers on rapid jumps.\n void (el as HTMLElement).offsetWidth;\n el.classList.add('setting-flash');\n window.setTimeout(() => el.classList.remove('setting-flash'), 1500);\n } else {\n window.setTimeout(() => tryScroll(tries - 1), 80);\n }\n };\n window.setTimeout(() => tryScroll(15), 60);\n }\n };\n\n const layout = settings?.ui?.layout || 'topnav';\n const showHeader = settings?.ui?.showHeader !== false;\n\n return (\n <div className=\"app\" data-layout={layout} data-active-tab={activeTab}>\n {showHeader && (\n <Topbar\n activeTab={activeTab}\n onTabChange={setActiveTab}\n wsStatus={wsStatus}\n version={VERSION}\n activeProject={snapshot?.activeProject || null}\n projects={snapshot?.projects || []}\n onProjectChange={onActivateProject}\n onProjectsRefresh={refreshProjects}\n onOpenSearch={() => setSearchOpen(true)}\n settings={settings}\n notificationsSlot={<Notifications wsSubscribe={subscribeToWs} />}\n showTabs={layout === 'topnav'}\n extraTabs={mergedTabs}\n />\n )}\n {stuckAgents.length > 0 && !stuckBannerDismissed && (\n <div className=\"stuck-banner\" role=\"alert\">\n <AlertTriangle size={16} />\n <span>\n <strong>{stuckAgents.length}</strong> agent{stuckAgents.length === 1 ? '' : 's'} stuck:{' '}\n <span className=\"mono\">\n {stuckAgents.map((a) => a.name).join(', ')}\n </span>\n </span>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => {\n setActiveTab('agents');\n setStuckBannerDismissed(true);\n }}\n >\n Review\n </Button>\n <button\n type=\"button\"\n className=\"icon-btn\"\n aria-label=\"Dismiss\"\n onClick={() => setStuckBannerDismissed(true)}\n >\n <X size={14} />\n </button>\n </div>\n )}\n <div className=\"layout-body\">\n {layout !== 'topnav' && (\n <Sidebar\n tabs={mergedTabs}\n activeTab={activeTab}\n onTabChange={setActiveTab}\n />\n )}\n <main className=\"content\">\n {bootError && (\n <div className=\"boot-error\">\n <h2>Dashboard unavailable</h2>\n <p>{bootError}</p>\n {authPromptOpen && (\n <TokenEntryForm\n onSaved={() => {\n setAuthPromptOpen(false);\n retryBoot();\n }}\n />\n )}\n <p className=\"boot-error-hint\">\n Make sure the Bizar dashboard server is running. Try{' '}\n <code>bizar-dash start</code> in your terminal.\n </p>\n </div>\n )}\n {!bootError && (!snapshot || !settings) && (\n <div className=\"loading\">\n <Spinner size=\"lg\" />\n <p>Loading Bizar…</p>\n </div>\n )}\n {renderedView && (\n <Suspense fallback={<div className=\"loading\"><Spinner size=\"lg\" /><p>Loading…</p></div>}>\n <ViewErrorBoundary>{renderedView}</ViewErrorBoundary>\n </Suspense>\n )}\n </main>\n </div>\n <SearchModal\n open={searchOpen}\n onClose={() => setSearchOpen(false)}\n onSelect={onSearchSelect}\n />\n </div>\n );\n}\n\n// v4.5.x — Catches render-time errors in the active view so a single bad\n// component doesn't bring down the whole dashboard (topbar, sidebar, WS).\n// Falls back to a friendly error card with a Retry button that re-mounts\n// the wrapped subtree by remounting the boundary via React `key` bumps.\nclass ViewErrorBoundary extends Component<\n { children: React.ReactNode },\n { err: Error | null }\n> {\n state: { err: Error | null } = { err: null };\n static getDerivedStateFromError(err: Error): { err: Error | null } {\n return { err };\n }\n componentDidCatch(err: Error, info: { componentStack?: string }) {\n // eslint-disable-next-line no-console\n console.error('[ViewErrorBoundary] caught render error:', err, info?.componentStack);\n }\n reset = () => this.setState({ err: null });\n override render() {\n if (this.state.err) {\n return (\n <div className=\"view-error-fallback\" role=\"alert\">\n <AlertTriangle size={20} />\n <div className=\"view-error-body\">\n <strong>This view crashed.</strong>\n <pre>{this.state.err.message}</pre>\n <Button variant=\"secondary\" size=\"sm\" onClick={this.reset}>Retry</Button>\n </div>\n </div>\n );\n }\n return this.props.children;\n }\n}\n","// src/main.tsx — viewport-based entry: mobile or desktop\nimport { StrictMode, useEffect, useState } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { App } from './App';\nimport { MobileApp } from './MobileApp';\n// Import mobile CSS so the MobileApp renders with styles when served\n// from index.html (e.g. when the auto-redirect to /m is bypassed).\nimport './styles/main.css';\nimport './styles/mobile.css';\nimport './styles/glyphs.css';\nimport './styles/minimax-usage.css';\nimport './styles/skills.css';\nimport './styles/memory.css';\n\nfunction Root() {\n const [isMobile, setIsMobile] = useState(() => {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(max-width: 767px)').matches;\n });\n\n useEffect(() => {\n const mql = window.matchMedia('(max-width: 767px)');\n const handler = (e: MediaQueryListEvent) => setIsMobile(e.matches);\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, []);\n\n return isMobile ? <MobileApp /> : <App />;\n}\n\nconst root = document.getElementById('root');\nif (!root) throw new Error('Root element #root not found');\ncreateRoot(root).render(\n <StrictMode>\n <Root />\n </StrictMode>,\n);\n"],"file":"assets/main-B4OfGAwz.js"}