{"version":3,"mappings":";weACA,SAAgBA,EAAkB,EAAU,EAAQ,EAAO,EAAQ,CAC/D,GAAI,CAACC,EAAQ,OAAOC,GAAY,GAEhC,IAAMC,EAAaF,EACd,MAAM,GAAG,CAAC,CACV,IAAK,GAAW,CACb,IAAMG,EAAQC,EAAO,KAAK,CAAC,CAAC,MAAM,kBAAkB,EACpD,OAAOD,EAAQ,CAAE,IAAKA,EAAM,GAAI,MAAO,OAAOA,EAAM,EAAE,CAAE,EAAI,IAChE,CAAC,CAAC,CACD,OAAO,OAAO,CAAC,CACf,MAAM,EAAO,IAAWE,EAAM,MAAQC,EAAO,KAAK,EACvD,GAAI,CAACJ,EAAW,OAAQ,OAAOD,GAAY,GAG3C,IAAMM,EADe,KAAK,IAAI,OAAOC,CAAK,GAAK,EAAG,OAAOC,CAAM,GAAK,EAAG,CACxC,EAAI,KAAK,IAAI,EAAG,OAAO,kBAAoB,CAAC,EAC3E,OAAQP,EAAW,KAAM,GAAcQ,EAAU,OAASH,CAAW,GAAKL,EAAW,GAAG,EAAE,GACrF,GACT,CClBA,SAASS,EAAc,EAAM,EAAW,EAAU,CAAC,EAAG,CAClD,GAAI,CACA,OAAO,WAAW,mBAAmBC,EAAM,CACvC,YAAa,CAAC,OAAOC,CAAS,CAAC,EAC/B,eAAgB,iBAChB,OAAQ,SACR,GAAGC,CACP,CAAC,CACL,MAAQ,CAER,CACJ,CAEA,eAAeC,EAAmB,EAAM,EAAM,EAAQ,CAClD,IAAMC,EAASC,EAAK,cAAc,8BAA8B,EAC1DC,EAAYD,EAAK,cAAc,gCAAgC,EAC/DE,EAASF,EAAK,cAAc,gCAAgC,EAC5DJ,EAAYI,EAAK,QAAQ,UAC3BG,EAAS,KACTC,EAAoB,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,CAAC,aAAa,IAAI,oBAAoB,EACrFC,EAAiBL,EAAK,cAAc,wBAAwB,EAC5DM,EAAeN,EAAK,cAAc,wBAAwB,EAC1DO,EAAiB,GACnBC,EACM,4DACA,yBACVF,GAAc,iBAAiB,YAAeH,GAAQ,WAAW,CAAC,EAElEJ,GAAQ,iBAAiB,QAAS,SAAY,CAC1C,GAAII,EAAQ,CACRA,EAAO,KAAK,EACZ,MACJ,CACAT,EAAc,0BAA2BE,CAAS,EAClD,EAAO,SAAW,GAClBG,EAAO,aAAa,YAAa,MAAM,EACvC,EAAO,YAAc,+BACrBU,EAAO,gBAAgB,kBAAkB,EACzC,IAAIC,EAAoB,GACxB,GAAI,CACA,GAAM,CAAE,wBAAuB,gCAAAC,EAAA,UAAzB,IAAE,wBAAuB,0BAC3B,MAAM,OAAO,yCAA0D,SAAAC,EAAA,6FAKrEC,EAAU,MAAM,MAJC,MACnB,sFAAsF,mBAAmBjB,CAAS,IAClH,CAAE,YAAa,aAAc,CACjC,GAC+B,KAAK,EACpC,GAAI,CAACiB,EAAQ,SAAW,CAACA,EAAQ,MAAM,SAAS,QAC5C,MAAU,MAAMA,EAAQ,OAAS,uCAAuC,EAE5E,SAAS,KAAK,OAAOZ,CAAS,EAC9B,EAAS,IAAIa,EAAsB,CAC/B,YACA,OAAQC,EAAuBF,EAAQ,KAAK,OAAO,EACnD,eAAgB,CACZ,SAAUb,EAAK,QAAQ,eACvB,uBAAyB,GAAkB,CACvC,EAAa,OAAS,CAACQ,EAClBN,EAAO,SACR,EAAe,YAAcK,EAAcC,CAAa,EAChE,CACJ,EACA,QAAU,GAAW,CAIjB,GAHAQ,EAAK,iBACD,iEACJ,CAAC,CAAC,QAAS,GAAUC,EAAM,OAAO,CAAC,EAC/B,CAACC,GAAQ,UAAW,CACpBf,EAAO,oBAAoB,EAC3B,EAAO,OAAS,GAChBa,EAAK,cACD,IAAI,YAAY,oCAAqC,CACjD,QAAS,GACT,OAAQ,CAAE,aAAc,EAAM,CAClC,CAAC,CACL,EACA,IAAMG,EAAaH,EAAK,cAAc,2BAA2B,EAC7DhB,EAAK,QAAQ,mBAAqB,QAAUmB,IAC5C,EAAW,SAAW,IAE1B,MACJ,CACA,CACI,CAAC,yBAA0BD,EAAO,cAAc,EAChD,CAAC,wBAAyBA,EAAO,UAAU,CAC/C,CAAC,CAAC,SAAS,CAACvB,EAAMyB,KAAW,CACzB,IAAMH,EAAQ,SAAS,cAAc,OAAO,EAC5C,EAAM,KAAO,SACb,EAAM,KAAOtB,EACb,EAAM,MAAQyB,EACdJ,EAAK,OAAOC,CAAK,CACrB,CAAC,EACD,IAAII,EAAUnB,EAAO,cAAc,KAAK,EACnCmB,IACD,EAAU,SAAS,cAAc,KAAK,EACtC,EAAQ,IAAM,sBACd,EAAQ,MAAQ,IAChB,EAAQ,OAAS,IACjBnB,EAAO,QAAQmB,CAAO,GAE1B,EAAQ,IAAMH,EAAO,WACrB,EAAO,OAAS,GAChBf,EAAO,oBAAoB,EAC3B,EAAe,YAAcI,EACzBJ,EAAO,gBAAgB,aAC3B,EACA,IAAMgB,EAAaH,EAAK,cAAc,2BAA2B,EAC7DG,IAAY,EAAW,SAAW,IACtC,EAAO,YAAc,2BACrB,EAAO,QAAQ,WAAa,UAC5BH,EAAK,cACD,IAAI,YAAY,oCAAqC,CACjD,QAAS,GACT,OAAQ,CAAE,aAAc,EAAK,CACjC,CAAC,CACL,EACAtB,EAAc,6BAA8BE,EAAW,CACnD,YAAa,OAAOsB,EAAO,UAAU,GAAK,CAC9C,CAAC,CACL,EACA,aAAc,EAAM,IAAYxB,EAAcC,EAAMC,EAAWC,CAAO,CAC1E,CAAC,EACD,IAAMyB,EAAalB,EACnB,GAAIkB,GAAc,QAAQ,KAAKA,CAAU,EAAG,CAExC,EAAoB,KACpB,EAAoB,GACpB,IAAMC,EAAmB,MAAM,MAC3B,uDAAuD,mBAAmBD,CAAU,EAAE,cAAc,mBAAmB1B,CAAS,IAChI,CAAE,YAAa,aAAc,CACjC,EACM4B,EAAQ,MAAMD,EAAiB,KAAK,EAC1C,GAAI,CAACA,EAAiB,IAAM,CAACC,EAAM,QAC/B,MAAU,MAAMA,EAAM,OAAS,0CAA0C,EAC7E,MAAMrB,EAAO,gBAAgBqB,EAAM,MAAM,EACzCrB,EAAO,eAAeqB,CAAK,CAC/B,CACArB,EAAO,KAAK,EACZ,EAAO,YAAc,GACrBM,EAAO,gBAAgB,kBAAkB,CAC7C,OAASgB,EAAO,CACZtB,GAAQ,QAAQ,EAChB,EAAS,KACT,EAAO,YACHsB,aAAiB,MACXA,EAAM,QACN,iDACNf,IACA,EAAO,aACH,uEACR,EAAO,QAAQ,WAAa,QAC5BhB,EAAc,yBAA0BE,EAAW,CAAE,YAAa,gBAAiB,CAAC,CACxF,QAAU,CACN,EAAO,SAAW,GAClBG,EAAO,gBAAgB,WAAW,CACtC,CACJ,CAAC,EACDC,EAAK,cAAc,+BAA+B,CAAC,EAAE,iBAAiB,YAAe,CACjFG,GAAQ,SAAS,EACjBa,EAAK,iBACD,iEACJ,CAAC,CAAC,QAAS,GAAUC,EAAM,OAAO,CAAC,EACnC,EAAO,OAAS,GAChB,IAAME,EAAaH,EAAK,cAAc,2BAA2B,EAC7DhB,EAAK,QAAQ,mBAAqB,QAAUmB,IAAY,EAAW,SAAW,IAClFH,EAAK,cACD,IAAI,YAAY,oCAAqC,CACjD,QAAS,GACT,OAAQ,CAAE,aAAc,EAAM,CAClC,CAAC,CACL,EACAtB,EAAc,2BAA4BE,CAAS,CACvD,CAAC,EACG,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC,CAAC,aAAa,IAAI,oBAAoB,GAAGG,GAAQ,MAAM,CAC5F,CAEA,SAAgB2B,EAA4B,EAAW,EAAM,EAAQ,CACjE,IAAMC,EAAY1B,EAAU,cAAc,0BAA0B,EACpE0B,GAAW,iBAAiB,SAAU,SAAY,CAC9C,IAAMC,EAAc3B,EAAU,cAAc,sCAAsC,EAClF,EAAY,YAAc,GACrB0B,EAAU,QAYf,EAAY,aAAc,MADJ,MAVC,MAAM,2DAA4D,CACrF,OAAQ,OACR,YAAa,cACb,QAAS,CAAE,eAAgB,iDAAkD,EAC7E,KAAM,IAAI,gBAAgB,CACtB,WAAYX,EAAK,SAAS,WAAW,MACrC,aAAcW,EAAU,MACxB,SAAUX,EAAK,SAAS,SAAS,KACrC,CAAC,CACL,CAAC,GAC8B,KAAK,GACF,SAAW,GACjD,CAAC,EACDf,EAAU,iBAAiB,yBAAyB,CAAC,CAAC,QAAS,GAAS,CACpEH,EAAwBE,EAAMgB,EAAMP,CAAM,CAC9C,CAAC,CACL,CCrMA,SAASoB,EAAU,EAAQ,CAIvB,OAHI,OAAOC,GAAW,SAAiBA,EACnC,MAAM,QAAQA,CAAM,EAAUA,EAAO,IAAID,CAAS,CAAC,CAAC,KAAK,GAAG,EAC5DC,GAAU,OAAOA,GAAW,SAAiB,OAAO,OAAOA,CAAM,CAAC,CAAC,IAAID,CAAS,CAAC,CAAC,KAAK,GAAG,EACvF,EACX,CAEA,SAAgBE,EAA+B,EAAM,CACjD/B,EAAK,iBAAiB,kCAAkC,CAAC,CAAC,QAAS,GAAS,CACxEgB,EAAK,iBAAiB,SAAU,KAAO,IAAU,CAE7C,GADAgB,EAAM,eAAe,EACjB,CAAChB,EAAK,eAAe,EAAG,OAC5B,IAAMjB,EAASiB,EAAK,cAAc,iBAAiB,EAC7CP,EAASO,EAAK,cAAc,oCAAoC,EACtE,EAAO,SAAW,GAClBjB,EAAO,aAAa,YAAa,MAAM,EACvC,EAAO,YAAc,GACrBU,EAAO,gBAAgB,kBAAkB,EACzC,GAAI,CAOA,IAAMI,EAAU,MAAM,MANC,MAAMG,EAAK,OAAQ,CACtC,OAAQ,OACR,YAAa,cACb,KAAM,IAAI,SAASA,CAAI,EACvB,QAAS,CAAE,OAAQ,kBAAmB,CAC1C,CAAC,GAC8B,KAAK,EACpC,GAAI,CAACH,EAAQ,QACT,MAAU,MACNgB,EAAUhB,EAAQ,MAAM,GAAK,2CACjC,EACJ,EAAO,YACH,OAAOA,EAAQ,SAAY,SACrBA,EAAQ,QACR,gDACV,EAAO,QAAQ,WAAa,UAC5BG,EAAK,iBAAiB,4BAA4B,CAAC,CAAC,QAAS,GAAU,CAC/DiB,EAAM,OAAS,aAAY,EAAM,MAAQ,GACjD,CAAC,CACL,OAASR,EAAO,CACZ,EAAO,YACHA,aAAiB,MACXA,EAAM,QACN,4CACV,EAAO,QAAQ,WAAa,OAChC,QAAU,CACN,EAAO,SAAW,GAClB1B,EAAO,gBAAgB,WAAW,CACtC,CACJ,CAAC,CACL,CAAC,CACL,CClDA,IAAMmC,EAAS,IACTC,EAAwB,IAAI,KAAK,eAAe,QAAS,CAC3D,IAAK,UACL,MAAO,QACP,KAAM,UACN,SAAU,KACd,CAAC,EACKC,EAAwB,IAAI,KAAK,eAAe,QAAS,CAC3D,KAAM,UACN,MAAO,UACP,IAAK,UACL,SAAU,eACd,CAAC,EAED,SAASC,EAAmB,EAAO,CAC/B,GAAI,OAAOjB,GAAU,UAAY,CAAC,sBAAsB,KAAKA,CAAK,EAAG,MAAO,GAC5E,IAAMkB,EAAY,KAAK,MAAM,GAAGlB,EAAM,WAAW,EACjD,OAAO,OAAO,SAASkB,CAAS,EAAIH,EAAsB,OAAO,IAAI,KAAKG,CAAS,CAAC,EAAI,EAC5F,CAEA,SAASC,EAAc,EAAc,CACjC,IAAMC,EAAU,KAAK,KAAKC,EAAeP,CAAM,EACzCQ,EAAQ,KAAK,MAAMF,EAAU,EAAE,EAC/BG,EAAOH,EAAU,GAEvB,OADIE,EAAQ,EAAU,GAAGA,EAAM,OAAOC,EAAO,EAAI,IAAIA,EAAK,OAAS,KAC5D,GAAGH,EAAQ,MACtB,CAEA,SAASI,EAAW,EAAS,EAAS,CAClC,GAAI,CAACC,EAAS,OACd,IAAMC,EAAOD,EAAQ,cAAc,6BAA6B,GAAKA,EACjEC,EAAK,cAAgBC,IAAS,EAAK,YAAcA,GACjDF,EAAQ,SAAW,CAACE,IAAS,EAAQ,OAAS,CAACA,EACvD,CAEA,SAAgBC,EAAmB,EAAW,CAC1C,IAAMC,EAAMhD,EAAU,QAAQ,kBAC9B,GAAI,CAACgD,EAAK,OAEV,IAAMC,EAAQjD,EAAU,cAAc,0BAA0B,EAC1DkD,EAAWlD,EAAU,cAAc,kCAAkC,EACrEmD,EAAgBD,GAAU,cAAc,+BAA+B,EACvEE,EAAeF,GAAU,cAAc,8BAA8B,EACrEG,EAAWrD,EAAU,cAAc,kCAAkC,EACrEsD,EAAStD,EAAU,cAAc,8BAA8B,EAC/DuD,EAASvD,EAAU,cAAc,+BAA+B,EAChEe,EAAOf,EAAU,cAAc,eAAe,EAChDwD,EAAQ,KACRC,EAAe,EAAQzD,EAAU,cAAc,iCAAiC,EAChF0D,EAAc,EACdC,EAAgB,KAChBC,EAAe,EAEbC,MAAmB,CACrB,IAAMC,EAAU,IAAI,IAAId,EAAK,OAAO,SAAS,IAAI,EACjD,GAAI,CAACjC,EAAM,OAAO+C,EAClB/C,EAAK,iBAAiB,yDAAyD,CAAC,CAAC,QAC5E,GAAU,CACHiB,EAAM,OAAO8B,EAAQ,aAAa,OAAO9B,EAAM,KAAMA,EAAM,KAAK,CACxE,CACJ,EACA,IAAM+B,EAAWhD,EAAK,cAAc,mBAAmB,EAEvD,OADIgD,GAAUD,EAAQ,aAAa,IAAI,WAAYC,EAAS,KAAK,EAC1DD,CACX,EAEME,MAAe,CACjB,GAAI,CAACR,GAAS,CAACxD,EAAU,YAAa,OACtC,IAAMiE,EAAM,KAAK,IAAI,EAAIP,EACnBQ,EAAmB,KAAK,MAAMV,EAAM,WAAW,EAC/CW,EAAoBD,EAAmBD,EACvCG,EAAqBZ,EAAM,8BAAgCC,EAC3DY,EACF,OAAO,SAASF,CAAiB,GAAKA,EAAoB,GAAK,CAACC,EACpE,GAAIC,GAAgBlB,EAAe,CAC/B,IAAMmB,EACFnC,EAAsB,OAAO,IAAI,KAAK+B,CAAgB,CAAC,IACvD/B,EAAsB,OAAO,IAAI,KAAK8B,CAAG,CAAC,EACpC,uBACA,mBACNd,EAAc,cAAgBmB,IAAO,EAAc,YAAcA,EACzE,CACA,GAAIlB,EAAc,CACd,IAAMmB,EAAOF,EACP,4BAA4B/B,EAAc6B,CAAiB,IAC3D,GACFf,EAAa,cAAgBmB,IAAM,EAAa,YAAcA,EACtE,CACIrB,GAAYA,EAAS,SAAW,CAACmB,IAAc,EAAS,OAAS,CAACA,GAEtE,IAAMG,EAAepC,EAAmBoB,EAAM,aAAa,EACrDiB,EAAarC,EAAmBoB,EAAM,WAAW,EACjDkB,EACF,OAAOlB,EAAM,kBAAqB,SAAWA,EAAM,iBAAiB,KAAK,EAAI,GACjFb,EACIU,EACA,CAACe,GAAsBI,GAAgBC,GAAcC,EAC/C,mCAAmCA,EAAgB,IAAIF,IAAeA,IAAiBC,EAAa,GAAK,QAAQA,IAAa,GAC9H,EACV,CACJ,EAEME,MAAyB,CAE3B,GADA,OAAO,aAAahB,CAAa,EAC7B,CAACH,EAAO,OACZ,IAAMS,EAAM,KAAK,IAAI,EAAIP,EACnBkB,EAAO,CAACpB,EAAM,YAAaA,EAAM,UAAU,CAAC,CAC7C,IAAK,GAAa,KAAK,MAAMqB,CAAQ,CAAC,CAAC,CACvC,OAAQ,GAAa,OAAO,SAASA,CAAQ,GAAKA,EAAWZ,CAAG,CAAC,CACjE,MAAM,EAAG,IAAMa,EAAIC,CAAC,CAAC,CAAC,GACvBH,IAAS,SACb,EAAgB,OAAO,eACb,CACF,IAAMI,EAAU,KAAK,IAAI,EAAItB,EAC7B,GACI,CAACF,EAAM,YAAaA,EAAM,UAAU,CAAC,CAAC,KAAM,GAAa,CACrD,IAAMnB,EAAY,KAAK,MAAMwC,CAAQ,EACrC,OAAO,OAAO,SAASxC,CAAS,GAAKA,GAAa2C,CACtD,CAAC,EACH,CACEC,EAAa,EACb,MACJ,CACAjB,EAAO,EACPW,EAAiB,CACrB,EACA,KAAK,IAAIC,EAAOX,EAAM,GAAI,UAAa,CAC3C,EACJ,EAEMgB,EAAU,SAAY,CACxB,GAAI,CAACjF,EAAU,YAAa,OAC5B,IAAMkF,EAAQ,EAAEtB,EAChBL,GAAQ,aAAa,YAAa,MAAM,EACxC,GAAI,CACA,IAAM4B,EAAW,MAAM,MAAMtB,EAAW,EAAG,CACvC,YAAa,cACb,MAAO,UACX,CAAC,EACD,GAAI,CAACsB,EAAS,GAAI,MAAU,MAAM,2BAA2BA,EAAS,QAAQ,EAC9E,IAAMP,EAAO,MAAMO,EAAS,KAAK,EACjC,GAAI,CAACnF,EAAU,aAAekF,IAAUtB,EAAc,OACtD,EAAQgB,EACR,IAAMQ,EAAa,KAAK,MAAMR,EAAK,UAAU,EAC7C,EAAc,OAAO,SAASQ,CAAU,EAAIA,EAAa,KAAK,IAAI,EAAI,EACtE,IAAMrB,EAAW,OAAOa,EAAK,SAAS,EAChCS,EAAOrF,EAAU,QAAQ,kBAAoB,QAC7CsF,EAAatF,EAAU,QAAQ,wBAA0BqF,EAC/D1C,EACIM,EACA,OAAO,UAAUc,CAAQ,GAAKA,EAAW,EACnC,YAAYA,EAAS,GAAGA,IAAa,EAAIsB,EAAOC,EAAW,aAC3D,EACV,EACA,IAAMC,EAAS,OAAOX,EAAK,gBAAgB,EACrCY,EAAO,OAAOZ,EAAK,kBAAkB,EAC3CjC,EACIW,EACA,OAAO,UAAUiC,CAAM,GAAKA,EAAS,GAAK,OAAO,UAAUC,CAAI,GAAKA,EAAO,EACrE,GAAGD,EAAO,+BACV,EACV,EACAvB,EAAO,EACPW,EAAiB,CACrB,MAAQ,CACJ,GAAIO,IAAUtB,EAAc,OAC5B,EAAQ,KACR,OAAO,aAAaD,CAAa,EACjChB,EAAWM,EAAO,EAAE,EAChBC,IAAU,EAAS,OAAS,IAC5BE,IAAc,EAAa,YAAc,IAC7CT,EAAWU,EAAU,EAAE,EACvBV,EAAWW,EAAQ,EAAE,CACzB,QAAU,CACF4B,IAAUtB,GAAcL,GAAQ,aAAa,YAAa,OAAO,CACzE,CACJ,EAEA0B,EAAa,EACbjF,EAAU,iBAAiB,oCAAsC,GAAU,CACvE,EAAe+B,EAAM,QAAQ,eAAiB,GAC9CiC,EAAO,CACX,CAAC,EACDjD,GAAM,iBAAiB,SAAW,GAAU,CACpCgB,EAAM,QAAQ,QAAQ,sCAAsC,GAAGkD,EAAa,CACpF,CAAC,EACD,IAAMQ,EAAQ,OAAO,gBAAkB,CACnC,GAAI,CAACzF,EAAU,YAAa,CACxB,OAAO,cAAcyF,CAAK,EAC1B,MACJ,CACAzB,EAAO,CACX,EAAG/B,CAAM,EACT,SAAS,iBAAiB,uBAA0B,CAC5C,CAAC,SAAS,QAAUjC,EAAU,aAAaiF,EAAa,CAChE,CAAC,EACD,OAAO,iBAAiB,WAAa,GAAU,CACvClD,EAAM,WAAa/B,EAAU,aAAaiF,EAAa,CAC/D,CAAC,CACL,CC/LA,SAASS,EAAY,EAAW,EAAO,CACnC,IAAM1D,EAAQhC,EAAU,cAAc,+BAA+B,EAErE,GAAI,CAACgC,EAAO,OAEZ,IAAM2D,EAAU,OAAO3D,EAAM,GAAG,GAAK,EAC/B4D,EAAU,OAAO5D,EAAM,GAAG,GAAK,IACrC,EAAM,MAAQ,OAAO,KAAK,IAAI4D,EAAS,KAAK,IAAID,EAAS,OAAOxE,CAAK,GAAKwE,CAAO,CAAC,CAAC,EACnF3D,EAAM,cAAc,IAAI,MAAM,SAAU,CAAE,QAAS,EAAK,CAAC,CAAC,CAC9D,CAEA,SAAS6D,EAAa,EAAO,CACzB,IAAMC,EAAa,OAAO3E,GAAS,EAAE,CAAC,CACjC,QAAQ,YAAa,EAAE,CAAC,CACxB,QAAQ,IAAK,GAAG,EACrB,OAAO,OAAO,WAAW2E,CAAU,CACvC,CAEA,SAASC,EAAiB,EAAW,CACjC,IAAMC,EAAQhG,EAAU,cAAc,8BAA8B,EACpE,GAAI,CAACgG,EAAO,OACZ,IAAMC,EAASD,EAAM,cAAc,4BAA4B,EACzDE,EAAU,CACZ,GAAGlG,EAAU,iBACT,oFACJ,CACJ,EACMmG,MACFD,EACK,OAAQ,GACLlE,EAAM,QAAQ,gBAAgB,EAAIA,EAAM,QAAU,EAAQA,EAAM,KACpE,CAAC,CACA,IAAK,GAAU,CACZ,IAAMoE,EAAWpE,EAAM,QAAQ,QAAQ,EAAIA,EAAM,gBAAgB,GAAKA,EACtE,OAAO6D,EAAaO,GAAU,QAAQ,cAAgBA,GAAU,KAAK,CACzE,CAAC,CAAC,CACD,OAAQ,GAAU,OAAO,SAASjF,CAAK,GAAKA,EAAQ,CAAC,EACxDkF,EAAa,GACfC,EAAO,QACF,EAAO,EAAO,IACXN,EAAM,QAAQ,kBAAoB,QAAUO,EAAQ,EAC9CC,EAAQrF,EACRqF,EAAQrF,EAClB,CACJ,EACEsF,EAAUJ,EAAUF,EAAe,CAAC,EACpCO,EAAO,OAAOV,EAAM,QAAQ,SAAS,EACrCW,EAAWX,EAAM,QAAQ,eAAiB,MAC1CY,MAAe,CACjB,IAAM5B,EAAUqB,EAAUF,EAAe,CAAC,EAC1C,EAAO,YACHM,EAAU,GAAKzB,EAAU,GAAK0B,EAAO,EAC/B,IAAI,KAAK,aAAa,QAAS,CAAE,MAAO,WAAY,UAAS,CAAC,CAAC,CAAC,OAC3DA,EAAOD,EAAWzB,CACvB,EACA,oBACd,EACAkB,EAAQ,QAAS,GAAUlE,EAAM,iBAAiB,SAAU4E,CAAM,CAAC,EACnEV,EAAQ,QAAS,GAAUlE,EAAM,iBAAiB,QAAS4E,CAAM,CAAC,EAClEA,EAAO,CACX,CAEA,SAASC,EAAmB,EAAW,CACnC,IAAMC,EAAS9G,EAAU,cAAc,yBAAyB,EAC1D+G,EAAOD,GAAQ,cAAc,8BAA8B,EAC3DE,EAAWF,GAAQ,cAAc,kCAAkC,EACnEG,EAAcD,GAAU,cAC9B,GAAI,CAACF,GAAU,CAACC,GAAQ,CAACC,GAAY,CAACC,EAAa,OAEnD,IAAMC,EAAY,OAAOJ,EAAO,QAAQ,iBAAiB,GAAK,EAC1DK,EAAe,OAAOL,EAAO,QAAQ,oBAAoB,GAAK,EAC9DM,EAAsBN,EAAO,QAAQ,mBAAqB,OACxDH,EAAWG,EAAO,QAAQ,kBAAoB,MAC9CO,EAAY,IAAI,KAAK,aAAa,QAAS,CAC7C,MAAO,WACP,WACA,sBAAuB,CAC3B,CAAC,EAEKT,MAAe,CACjB,IAAMU,EAAUF,GAAuBF,GAAa,GAAKC,GAAgBD,EACnEK,EAAaD,EACb,IACA,KAAK,IAAI,EAAG,KAAK,IAAI,IAAM,IAAMH,EAAgBD,CAAS,CAAC,EAGjE,GADAH,EAAK,gBAAgB,EACjBO,EAAS,CACT,IAAMxE,EAAU,SAAS,cAAc,QAAQ,EAC/C,EAAQ,YAAc,0CACtBiE,EAAK,OAAOjE,CAAO,CACvB,KAAO,CACH,IAAM0E,EAAY,SAAS,cAAc,QAAQ,EACjD,EAAU,YAAcH,EAAU,OAAO,KAAK,IAAI,EAAGH,EAAYC,CAAY,CAAC,EAC9EJ,EAAK,OAAO,QAASS,EAAW,+BAA+B,CACnE,CAEA,EAAS,MAAM,MAAQ,GAAGD,EAAW,GACrCN,EAAY,aAAa,gBAAiB,OAAO,KAAK,MAAMM,CAAU,CAAC,CAAC,CAC5E,EAEME,EAAoB,GAAY,CAC7BC,IACL,EAAeA,EAAQ,yBACvB,EAAsBA,EAAQ,aAC9B,EAAO,QAAQ,qBAAuB,OAAOP,CAAY,EACzD,EAAO,QAAQ,iBAAmB,OAAOC,CAAmB,EAC5DN,EAAO,gBAAgB,2BAA2B,EAClDF,EAAO,EACX,EAEA,SAAS,iBAAiB,uBAAyB,GAAUa,EAAiB1F,EAAM,MAAM,CAAC,EAC3F,IAAM4F,EAAiBC,EAAe,EAClCD,EAAgBF,EAAiBE,CAAc,EACzCb,EAAO,aAAa,2BAA2B,GAAGF,EAAO,CACvE,CAEA,SAASiB,EAAa,EAAO,CAOzB,OANI,OAAOrG,GAAU,SAAiBA,EAClC,MAAM,QAAQA,CAAK,EAAUA,EAAM,IAAIqG,CAAY,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAC7ErG,GAAS,OAAOA,GAAU,SACnB,OAAO,OAAOA,CAAK,CAAC,CAAC,IAAIqG,CAAY,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAGnE,EACX,CAEA,SAASC,EAAU,EAAQ,EAAU,GAAI,EAAO,UAAW,CAClDtH,IACL,EAAO,YAAcsC,EACjBA,EAAS,EAAO,QAAQ,WAAaiF,EACpCvH,EAAO,gBAAgB,kBAAkB,EAClD,CAEA,SAASwH,EAAkB,EAAO,CAC9B,IAAMC,EAAU,SAAS,cAAc,UAAU,EACjD,EAAQ,UAAYJ,EAAarG,CAAK,CAAC,CAAC,QAAQ,WAAY,EAAE,EAC9D,IAAMsB,EAAUmF,EAAQ,MAAM,KAAK,EAUnC,MARI,CAACnF,GACDA,EAAQ,OAAS,KACjB,uFAAuF,KACnFA,CACJ,EAEO,oDAEJA,CACX,CAEA,SAASoF,EAAiB,EAAM,EAAQ,CACpCnH,EAAK,iBAAiB,4BAA4B,CAAC,CAAC,QAAS,GAAY,CACrE,IAAMoH,EAAW,CAAC,GAAGpH,EAAK,QAAQ,CAAC,CAAC,OAC/B,GAAYqH,EAAQ,QAAQ,iBAAmBtF,EAAQ,EAC5D,GACI,IAAWqF,EAAS,SAASE,CAAM,KACvCF,EAAS,QAAS,GAAY,CAC1B,IAAMG,GAAeF,EAAQ,aAAa,kBAAkB,GAAK,IAC5D,MAAM,KAAK,CAAC,CACZ,OAAQ,GAAOG,GAAMA,IAAOzF,EAAQ,EAAE,EACvCwF,EAAY,OAAQF,EAAQ,aAAa,mBAAoBE,EAAY,KAAK,GAAG,CAAC,EACjFF,EAAQ,gBAAgB,kBAAkB,EAC1CA,EAAQ,SAAS,MAElBA,EAAQ,QAAQ,wBAChBA,EAAQ,QAAQ,yBAA2B,OAE3CA,EAAQ,aAAa,eAAgBA,EAAQ,QAAQ,sBAAsB,EAC1EA,EAAQ,gBAAgB,cAAc,EANdA,EAAQ,aAAa,eAAgB,MAAM,EAOxE,OAAOA,EAAQ,QAAQ,eACvB,OAAOA,EAAQ,QAAQ,sBAC3B,CAAC,EACDtF,EAAQ,OAAO,EACnB,CAAC,CACL,CAEA,SAAS0F,EAAgB,EAAM,EAAQ,CACnC,GAAI,CAAC3G,GAAU,OAAOA,GAAW,SAAU,OAAO,KAClD,IAAM4G,EAAS,CAAC,EACZ5G,EAAO,QAAU,OAAOA,EAAO,QAAW,UAC1C,OAAO,QAAQA,EAAO,MAAM,CAAC,CAAC,SAAS,CAAC0G,EAAI/G,KAAW,CAC/C,QAAQ,KAAK+G,CAAE,GACfE,EAAO,KAAK,CACR,MAAO,CAAC,UAAUF,EAAG,GAAI,UAAUA,EAAG,IAAI,EAC1C,GAAI,UAAUA,IACd,OACJ,CAAC,CACT,CAAC,EAED1G,EAAO,WACP4G,EAAO,KAAK,CAAE,MAAO,CAAC,cAAc,EAAG,GAAI,YAAa,MAAO5G,EAAO,SAAU,CAAC,EACjFA,EAAO,UACP4G,EAAO,KAAK,CAAE,MAAO,CAAC,UAAU,EAAG,GAAI,WAAY,MAAO5G,EAAO,QAAS,CAAC,EAC/E,IAAI1C,EAAQ,KA0BZ,OAzBAsJ,EAAO,QAAS,GAAU,CACtB,IAAMN,EAAW,CAAC,GAAGpH,EAAK,QAAQ,CAAC,CAAC,OAAQ,GAAYC,EAAM,MAAM,SAASoH,EAAQ,IAAI,CAAC,EACpFM,EAAYP,EAAS,KACtB,GAAY,CAACC,EAAQ,UAAYA,EAAQ,OAAS,QACvD,EACA,GAAI,CAACM,EAAW,OAChB,IAAM5F,EAAU,SAAS,cAAc,GAAG,EAC1C,EAAQ,GAAK,mBAAmB9B,EAAM,KACtC,EAAQ,UAAY,kCACpB,EAAQ,QAAQ,kBAAoB,GACpC,EAAQ,YAAcgH,EAAkBhH,EAAM,KAAK,EACnD,IAAM2H,EAAQD,EAAU,QAAQ,mBAAmB,EAC/CC,EAAOA,EAAM,OAAO7F,CAAO,EAC1B4F,EAAU,sBAAsB,WAAY5F,CAAO,EACxDqF,EAAS,QAAS,GAAY,CAC1B,EAAQ,QAAQ,uBAAyBC,EAAQ,aAAa,cAAc,GAAK,GACjF,EAAQ,QAAQ,eAAiBtF,EAAQ,GACzCsF,EAAQ,aAAa,eAAgB,MAAM,EAC3CA,EAAQ,aACJ,mBACA,CAACA,EAAQ,aAAa,kBAAkB,EAAGtF,EAAQ,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,CACnF,CACJ,CAAC,EACD,CAAY3D,GAAQuJ,CACxB,CAAC,EACMvJ,CACX,CAEA,eAAsByJ,GAAsB,EAAW,EAAQ,EAAQ,CACnE,GAAKjJ,GAAa,GAAO,SACzB,GAAUa,CAAM,EAEhB,GAAI,CACA,IAAMqI,EAAS,MAAMC,EAAehJ,CAAM,EACtC+I,GACAf,EACItH,EACAqI,EAAO,MACD,kDACA,mDACV,CACR,OAASrH,EAAO,CACZsG,EACItH,EACAgB,aAAiB,MAAQA,EAAM,QAAU,8CACzC,OACJ,CACJ,CAjBgB,CAkBpB,CAEA,eAAeuH,GAAU,EAAM,EAAQ,EAAQ,EAAkB,GAAI,CACjE,EAAO,SAAW,GAClBjJ,EAAO,aAAa,YAAa,MAAM,EACvCgI,EAAUtH,CAAM,EAChB0H,EAAiBnH,CAAI,EAErB,GAAI,CACA,IAAMoE,EAAW,MAAM,MAAMpE,EAAK,OAAQ,CACtC,OAAQ,OACR,KAAM,IAAI,SAASA,CAAI,EACvB,QAAS,CAAE,OAAQ,kBAAmB,CAC1C,CAAC,EACD,GAAI,CAACoE,EAAS,GAAI,CACd,MAAM6D,EAAiB,CAAE,OAAM,UAAW,GAAM,WAAY7D,EAAS,MAAO,EAAGrF,CAAM,EACrF,MACJ,CAEA,IAAMG,EAAS,MAAMkF,EAAS,KAAK,EACnC,GAAI,CAAClF,GAAU,OAAOA,GAAW,UAAY,MAAM,QAAQA,CAAM,EAC7D,MAAU,MAAM,uBAAuB,EAE3C,GAAI,CAACA,EAAO,SAAWA,EAAO,MAAO,CACjC,IAAMd,EAAQqJ,EAAgBzH,EAAMd,EAAO,KAAK,EAC1CgJ,EAAWhJ,EAAO,UAAY,IAAS,EAAQA,EAAO,MAC5D,MAAM+I,EACF,CAAE,SAAQ,OAAM,aAAc7J,EAAO,UAAW,CAAC8J,CAAS,EAC1DnJ,CACJ,EACA,MACJ,CACA,GAAIG,EAAO,SAAU,CACjB,OAAO,SAAS,OAAOA,EAAO,QAAQ,EACtC,MACJ,CAEA,GADA,EAAO,yBAA2B,iBAC9BiJ,EAAiB,CACjB,OAAO,SAAS,OAAOA,CAAe,EACtC,MACJ,CACApB,EAAUtH,EAAQ,4CAA4C,EAC9D,SAAS,cAAc,IAAI,YAAY,qBAAsB,CAAE,OAAQP,CAAO,CAAC,CAAC,CACpF,MAAQ,CACJ,MAAM+I,EAAiB,CAAE,OAAM,UAAW,EAAK,EAAGlJ,CAAM,CAC5D,QAAU,CACN,EAAO,SAAW,GAClBA,EAAO,gBAAgB,WAAW,CACtC,CACJ,CAEA,SAAgBqJ,EAAoB,EAAW,CAC3CpG,EAAmB/C,CAAS,EAC5B,IAAMe,EAAOf,EAAU,cAAc,eAAe,EAC9CgC,EAAQhC,EAAU,cAAc,+BAA+B,EAErE,GAAI,CAACe,EAAM,OAEX,IAAMP,EAASR,EAAU,cAAc,6BAA6B,EACpEe,EAAK,iBAAiB,QAAU,GAAUmH,EAAiBnH,EAAMgB,EAAM,MAAM,CAAC,EAC9EhB,EAAK,iBAAiB,SAAW,GAAUmH,EAAiBnH,EAAMgB,EAAM,MAAM,CAAC,EAC/EN,EAA4BzB,EAAWe,EAAMP,CAAM,EACnDsB,EAA+B9B,CAAS,EACxC+F,EAAiB/F,CAAS,EAC1B6G,EAAmB7G,CAAS,EAExBgC,IACAA,EAAM,iBAAiB,aAAgB,CACnC,IAAMrC,EAAY,OAAOoB,EAAK,SAAS,YAAY,KAAK,GAAK,EAC7DqI,EAA2B,2BAA4B,CACnD,GAAIzJ,EAAY,EAAI,CAAE,YAAa,CAACA,CAAS,CAAE,EAAI,CAAC,EACpD,eAAgB,iBAChB,SAAU,OAAOqC,EAAM,KAAK,GAAK,CACrC,CAAC,CACL,CAAC,EAEDhC,EAAU,iBAAiB,yBAAyB,CAAC,CAAC,QAAS,GAAW,CACtEF,EAAO,iBAAiB,YAAe,CACnC4F,EACI1F,EACA,OAAOgC,EAAM,KAAK,EAAI,OAAOlC,EAAO,QAAQ,eAAe,CAC/D,CACJ,CAAC,CACL,CAAC,EAEDE,EAAU,iBAAiB,yBAAyB,CAAC,CAAC,QAAS,GAAW,CACtEF,EAAO,iBAAiB,YAAe,CACnCE,EAAU,iBAAiB,yBAAyB,CAAC,CAAC,QAAS,GAAS,CACpE,IAAMoG,EAAWiD,IAASvJ,EAC1BuJ,EAAK,UAAU,OAAO,qCAAsCjD,CAAQ,EACpEiD,EAAK,aAAa,eAAgB,OAAOjD,CAAQ,CAAC,CACtD,CAAC,EACDV,EAAY1F,EAAWF,EAAO,QAAQ,cAAc,CACxD,CAAC,CACL,CAAC,GAGLE,EAAU,iBAAiB,yBAAyB,CAAC,CAAC,QAAS,GAAW,CACtEsJ,EAAO,iBAAiB,aAAgB,CAEpCA,EADsB,QAAQ,2BACzB,CAAC,EACA,QAAQ,mBAAmB,CAAC,EAC5B,iBAAiB,2BAA2B,CAAC,CAC9C,QAAS,GAAS,CACfD,EAAK,UAAU,OACX,qCACA,EAAQA,EAAK,cAAc,OAAO,CAAC,EAAE,OACzC,CACJ,CAAC,CACT,CAAC,CACL,CAAC,EAEDrJ,EAAU,iBAAiB,4BAA4B,CAAC,CAAC,QAAS,GAAc,CAC5EuJ,EAAU,iBAAiB,aAAgB,CACvC,IAAMnI,EAAUmI,EAAU,eAAe,cACrC,oCACJ,EACA,GAAI,CAACnI,EAAS,OACdA,EAAQ,gBAAgB,EACxB,IAAMoI,EAAOD,EAAU,QAAQ,GAC/B,GAAI,CAACC,EAAM,OACX,IAAM9J,EAAO,SAAS,cAAc,MAAM,EAG1C,GAFA,EAAK,YAAc,UAAU8J,EAAK,OAClCpI,EAAQ,OAAO1B,CAAI,EACf,CAAC8J,EAAK,KAAK,WAAW,QAAQ,GAAKA,EAAK,OAAS,YAAa,OAClE,IAAMC,EAAQ,SAAS,cAAc,KAAK,EACpCvK,EAAS,IAAI,gBAAgBsK,CAAI,EACvC,EAAM,IAAMtK,EACZ,EAAM,IAAM,kCACZuK,EAAM,iBAAiB,WAAc,IAAI,gBAAgBvK,CAAM,EAAG,CAAE,KAAM,EAAK,CAAC,EAChFkC,EAAQ,OAAOqI,CAAK,CACxB,CAAC,CACL,CAAC,EAED,IAAMvI,EAAalB,EAAU,cAAc,2BAA2B,EACtEA,EAAU,cAAc,yBAAyB,CAAC,EAAE,iBAAiB,QAAU,GAAU,CACrF4I,GACI,OAAO7G,EAAM,cAAc,QAAQ,eAAe,EAClDA,EAAM,cACNvB,CACJ,CACJ,CAAC,EACDO,EAAK,iBAAiB,SAAW,GAAU,CACvCgB,EAAM,eAAe,EAChBhB,EAAK,eAAe,GACpBP,GAAWU,GAAc,GAAW,UACzC6H,GAAehI,EAAMG,EAAYV,CAAM,CAC3C,CAAC,CACL,CCnYA,IAAIkJ,EAA0B,KAE9B,SAASC,IAAuB,CAQ5B,MAPA,CACID,IAAAhJ,MACI,OAAO,6DAAuD,MAAO,GAAU,CAE3E,KADA,GAA0B,KACpBc,CACV,CAAC,EAEFkI,CACX,CAEA,SAAgBE,EAAmB,EAAS,CACxC,IAAMC,EAAYC,EAAQ,cAAc,6BAA6B,EAC/DC,EAAQD,EAAQ,cAAc,2BAA2B,EACzDE,EAAWF,EAAQ,cAAc,6BAA6B,EAC9DG,EAAOH,EAAQ,cAAc,6BAA6B,EAC1DI,EAAa,CAAC,GAAGJ,EAAQ,iBAAiB,8BAA8B,CAAC,EACzEK,EAAS,CAAC,GAAGL,EAAQ,iBAAiB,+BAA+B,CAAC,EAE5E,GAAI,CAACD,GAAa,CAACG,GAAY,CAACD,EAAO,OAEvC,IAAIK,EAAc,KAAK,IACnB,EACAF,EAAW,UAAW,GAAcG,EAAU,aAAa,cAAc,IAAM,MAAM,CACzF,EACIC,EAAQ,KACRC,EAAe,GACfC,EAAwB,GACxBC,EAAY,KACZC,EAAmB,CAAC,EACpBC,EAAoB,GACpBC,EAAsB,KACtBC,EAAkB,EAClBC,EAAwB,KACxBC,EAAe,KACfC,EAAa,EACbC,EAAmB,EACnBC,EAAmB,KACnBC,EAAiB,GACjBC,EAA2B,GAC3BC,EAAwB,GACxBC,EAAyB,GACzBC,EAAwB,GACxBC,EAA2B,EACzBC,EAAiB,IAAI,IAErBC,GAAS,EAAO,EAAS,IAAY,KAAK,IAAI9F,EAAS,KAAK,IAAID,EAASxE,CAAK,CAAC,EAErF,SAASwK,IAAe,CACpB,GAAKlB,EAGL,CAFAA,EAAU,MAAM,EAChBA,EAAU,gBAAgB,KAAK,EAC/BA,EAAU,gBAAgB,EAC1B,GAAI,CACAA,EAAU,KAAK,CACnB,OAASjJ,EAAO,CAGZ,GAAIA,EAAM,OAAS,aAAc,MAAMA,CAC3C,CACAiJ,EAAU,OAAO,EACjBG,GAAqB,OAAO,EAC5B,EAAY,KACZ,EAAmB,CAAC,EACpB,EAAsB,IAZI,CAa9B,CAEA,SAASgB,EAAU,EAAc,CAC7B,IAAMC,EAAWC,EAAa,KAAK,EAC/BD,GAAU,OACVA,EAAS,UAAY,CACjB,GAAIpB,IAAcqB,EAAc,OAChC,EAAa,MAAQ,GACrB,IAAMC,EAAgBD,EAAa,KAAK,EACpCC,GAAe,OAAOA,EAAc,UAAY,CAAC,CAAC,CAC1D,CAAC,CAET,CAEA,SAASC,EAAU,EAAW,EAAO,EAAU,EAAM,CACjD,GAAI,CAACvB,EAAW,CACZ,EAAY,SAAS,cAAc,OAAO,EAC1C,EAAU,UAAY,gCACtB,EAAU,SAAW,GACrB,EAAU,YAAc,GACxB,EAAU,QAAU,OACpB,EAAU,QAAQ,oBAAsB,GACxC,IAAMwB,EAAQxB,EACdA,EAAU,iBAAiB,YAAe,CACtC,GAAIA,IAAcwB,EAAO,OACzB,IAAMlN,EAAWmN,EAAiBD,EAAM,WAAYE,EAAiBF,CAAK,CAAC,EACtElN,GAAa+K,EAAQ,cAC1B,EAAU,IAAM/K,EAChB0L,EAAU,KAAK,GACXE,GAAqBsB,EAAM,QAAQ,eAAiB,SACpDL,EAAUnB,CAAS,EAC3B,CAAC,EACDA,EAAU,iBAAiB,WAAc,CACrC,EAAM,QAAQ,aAAe,MACjC,CAAC,EACDV,EAAM,OAAOU,CAAS,EAEtB,EAAsB,SAAS,cAAc,KAAK,EAClD,EAAoB,UAAY,mCAChCG,EAAoB,aAAa,cAAe,MAAM,EACtDA,EAAoB,iBAAiB,YAAe,CAC3CH,GAAa,KACdA,EAAU,OACVmB,EAAUnB,CAAS,EAChBA,EAAU,MAAM,EAC3B,CAAC,EACDV,EAAM,OAAOa,CAAmB,CACpC,CACA,EAAU,OAAS/L,EACfwL,EAAU,QAAQ,aAAeA,EAAU,QAAQ,MACnDA,EAAU,QAAQ,kBAClB+B,EAAK,MACLA,EAAK,MACT,EACA,IAAMC,EAAU,CACZ,IAAKhC,EAAU,QAAQ,MACvB,KAAMA,EAAU,QAAQ,WAAa,GACrC,SAAUA,EAAU,QAAQ,WAAa,WAC7C,EACA,GAAIK,EAAiB,MAAQ2B,EAAQ,KAAO3B,EAAiB,OAAS2B,EAAQ,KAAM,CAChF,EAAmBA,EACnB,OAAO5B,EAAU,QAAQ,aACzB,IAAM6B,EAAkBjC,EAAU,cAAc,sCAAsC,EAClFiC,GACA7B,EAAU,gBAAgB,KAAK,EAC/BA,EAAU,gBAAgB6B,EAAgB,QAAQ,UAAU,EAAI,CAAC,GAC9DC,EAAgB9B,EAAW4B,CAAO,EAGrCG,GAAU/B,EAAU,KAAK,CACjC,CACA,EAAoB+B,EACpB,EAAU,QAAQ,cAAgB,OAAOjG,EAAQ,CAAC,EAC9CiG,GAAUZ,EAAUnB,CAAS,CACrC,CAEA,SAASgC,EAAiB,EAAW,EAAO,EAAW,GAAM,CACzD,GAAI3B,IAA0BT,GAAaD,IAAgB7D,EAAO,OAClE,OAAO,aAAasE,CAAe,EACnC,EAAkB,EAClB,EAAwB,KACxB,IAAMuB,EAAO,CAAE,MAAOrC,EAAM,YAAa,OAAQA,EAAM,YAAa,EACpE,EAAS,OAAS,GAClBiC,EAAU3B,EAAW9D,EAAOiG,EAAUJ,CAAI,EACtCI,GAAUE,EAAW,uBAAwBrC,EAAW,MAAM,CACtE,CAEA,SAASsC,GAAoB,CACzB,OAAO,qBAAqB3B,CAAU,EACtC,OAAO,aAAaC,CAAgB,EACpC,EAAa,EACb,EAAmB,EACnB,EAAmB,KACnB,EAAiB,GACjB,EAAU,MAAM,UAAY,GACxBR,IAAW,EAAU,MAAM,UAAY,IAC3CM,GAAc,OAAO,EACrB,EAAe,KACfhB,EAAM,UAAU,OAAO,oCAAoC,EAC3DA,EAAM,MAAM,eAAe,qCAAqC,EAC5DuB,GAA0Bb,IAC1B,EAAS,OAAS,GAClB,EAAU,OAAS,GACfY,GAAuBO,EAAUnB,CAAS,GAElD,EAAwB,GACxB,EAAyB,EAC7B,CAEA,SAASmC,EAAa,EAAO,CACzB,IAAMvC,EAAYH,EAAW3D,GAC7B,GAAI,CAAC8D,GAAW,QAAQ,MAAO,OAAO,KACtC,IAAMnL,EAASmL,EAAU,QAAQ,MAC3BvL,EAASuL,EAAU,QAAQ,QAAU,GACrCwC,EAASpB,EAAe,IAAIlF,CAAK,EACvC,GAAIsG,GAAQ,SAAW3N,GAAU2N,EAAO,SAAW/N,EAAQ,OAAO+N,EAAO,MAEzE,IAAMpD,EAAQ,IAAI,MAYlB,MAXA,GAAM,UAAY,mCAClB,EAAM,IAAM,GACZ,EAAM,SAAW,QACjBA,EAAM,aAAa,gBAAiB,KAAK,EACzC,EAAM,MAAQI,EAAU,MACpB/K,IAAQ,EAAM,OAASA,GAC3B,EAAM,IAAMI,EACZ,EAAM,MAAM,UAAYmL,EAAU,QAAQ,YAAc,QAAU,QAAU,UAC5E,EAAM,MAAM,eAAiB,GAAGA,EAAU,QAAQ,iBAAmB,GAAG,IAAIA,EAAU,QAAQ,iBAAmB,GAAG,GAChHZ,EAAM,QAAQA,EAAW,OAAO,CAAC,CAAC,UAAY,CAAC,CAAC,EACpDgC,EAAe,IAAIlF,EAAO,CAAE,QAAO,SAAQ,QAAO,CAAC,EAC5CkD,CACX,CAEA,SAASqD,EAAmB,EAAO,CAC/BF,EAAarG,EAAQ,CAAC,EACtBqG,EAAarG,EAAQ,CAAC,EACtBkF,EAAe,SAAS,EAAG,IAAkB,CACrC,KAAK,IAAIsB,EAAgBxG,CAAK,EAAI,GAAGkF,EAAe,OAAOsB,CAAa,CAChF,CAAC,CACL,CAEA,SAASC,GAAwB,CAC7B,GAAI,CAACzB,GAAyB,CAAC1B,EAAU,UAAY,CAACA,EAAU,aAAc,OAC9E,IAAMoD,EAAa,EAAEzB,EACfjF,EAAQ6D,EACR8C,MAAa,CAEVpD,EAAQ,aACTmD,IAAezB,GACfjF,IAAU6D,GAGTP,EAAU,UAAaA,EAAU,eACtC,EAAwB,GACxBA,EAAU,oBAAoB,OAAQmD,CAAqB,EAC3DF,EAAmBvG,CAAK,EAC5B,EAEIsD,EAAU,OACVA,EACK,OAAO,CAAC,CACR,UAAY,CAAC,CAAC,CAAC,CACf,KAAKqD,CAAI,EACbA,EAAK,CACd,CAEArD,EAAU,iBAAiB,OAAQmD,CAAqB,EAExD,SAASG,GAAY,EAAO,CACxB,MAAO,CACH,CAACC,EAAM,MAAO,GAAG,EACjB,CAACA,EAAM,UAAW,GAAG,EACrB,CAACA,EAAM,aAAc,GAAG,EACxB,CAACA,EAAM,UAAW,GAAG,EACrB,CAACA,EAAM,iBAAkB,GAAG,EAC5B,CAACA,EAAM,iBAAkB,IAAI,CACjC,CAAC,CACI,QAAQ,CAAClO,KAAY,EAAQA,CAAO,CAAC,CACrC,KAAK,CAACA,EAAQI,KAAW,GAAGJ,EAAO,GAAGI,EAAM,EAAE,CAAC,CAC/C,KAAK,IAAI,CAClB,CAEA,SAAS+N,GAAY,EAAO,CACxB,MAAO,CACH,CAACD,EAAM,MAAOA,EAAM,YAAY,KAAK,EACrC,CAACA,EAAM,aAAcA,EAAM,mBAAmB,KAAK,CACvD,CAAC,CACI,QAAQ,CAAClO,EAAQI,KAAW,EAAQJ,GAAW,OAAOI,CAAK,EAAI,CAAC,CAAC,CACjE,KAAK,CAACJ,EAAQI,KAAW,GAAGJ,EAAO,GAAG,OAAOI,CAAK,EAAE,EAAE,CAAC,CACvD,KAAK,IAAI,CAClB,CAEA,SAASgO,EAAyB,EAAU,CACxC,GAAIC,EAAS,OAAS,QAAS,OAAO,KAGtC,IAAMC,EAAO3D,EAAU,sBAAsB,EACvCvK,EAAQ,OAAOiO,EAAS,KAAK,EAC7BhO,EAAS,OAAOgO,EAAS,MAAM,EACrC,GAAI,CAACC,EAAK,OAAS,CAACA,EAAK,QAAU,CAAClO,GAAS,CAACC,EAAQ,OAAO,KAE7D,IAAMkO,EAAa,iBAAiB5D,CAAS,EACvC6D,EAAQD,EAAW,YAAc,QACjCE,EAAQD,EACR,KAAK,IAAIF,EAAK,MAAQlO,EAAOkO,EAAK,OAASjO,CAAM,EACjD,KAAK,IAAIiO,EAAK,MAAQlO,EAAOkO,EAAK,OAASjO,CAAM,EACjDqO,EAAgBtO,EAAQqO,EACxBE,EAAiBtO,EAASoO,EAC1BG,EAAY,GAAU,CACxB,IAAMC,EAAU,OAAO,WAAW5M,CAAK,EACvC,OAAO,OAAO,SAAS4M,CAAO,EAAIrC,EAAMqC,EAAS,EAAG,GAAG,EAAI,IAAM,EACrE,EACM,CAACC,EAAiBC,GAAmBR,EAAW,eAAe,MAAM,GAAG,EACxES,EAAYR,EAAQI,EAASE,CAAe,EAAI,GAChDG,EAAYT,EAAQI,EAASG,CAAe,EAAI,GAChDG,GAAWZ,EAAK,MAAQI,GAAiBM,EACzCG,GAAWb,EAAK,OAASK,GAAkBM,EAC3CG,EAAS,CACX,EAAGd,EAAK,KAAOY,EACf,EAAGZ,EAAK,IAAMa,EACd,EAAGT,CACP,EAUA,OARIF,IACA,EAAO,UAAY,CACf,EAAGU,EACH,EAAGC,EACH,EAAGb,EAAK,MACR,EAAGA,EAAK,MACZ,GAEGc,CACX,CAEA,SAASC,EAAW,EAAO,CACvB,IAAMC,EAAe,CACjB,EAAG,KACH,EAAG,KACH,EAAG,KACH,EAAG,KACH,EAAG,KACH,EAAG,KACH,EAAG,IACP,EAEA,OAAO,OAAOrN,GAAS,EAAE,CAAC,CACrB,QAAQ,aAAe,GAAcqN,EAAaC,EAAU,CAAC,CAC7D,UAAU,KAAK,CAAC,CAChB,QAAQ,mBAAoB,EAAE,CAAC,CAC/B,YAAY,CAAC,CACb,QAAQ,cAAe,GAAG,CAAC,CAC3B,QAAQ,WAAY,EAAE,CAC/B,CAEA,SAASC,EAAwB,EAAY,EAAgB,EAAY,EAAgB,CACrF,IAAMC,EACFC,EAAe,MAAQC,EAAW,KAAO,GACzCD,EAAe,OAASC,EAAW,MAAQ,EAC3CC,EAAeF,EACfD,IACII,GAAcA,EAAW,MAAQF,EAAW,MAAQ,EACpD,EAAeE,EAEXC,GAAkBA,EAAe,KAAOH,EAAW,KAAO,IAC1D,EAAeG,IAG3B,IAAMC,EAAgBH,EAAa,KAAOD,EAAW,KAC/CK,EAAcJ,EAAa,MAAQD,EAAW,MAEpD,OADII,EAAgB,EAAUA,EACvBC,EAAc,EAAIA,EAAc,CAC3C,CAEA,IAAIC,EAA4B,EAC5BC,EAAuB,EACvBC,EAA2B,KACzBC,EACFrF,GAAQ,OAAO,qBAAyB,IAClC,IAAI,qBACC,GAAY,CACT,IAAMnG,EAAUuL,EAChB,GAAI,CAACvL,EAAS,OACd,GAAI,CAACgG,EAAQ,YAAa,CACtByF,EAAsB,EACtB,MACJ,CACA,IAAK,IAAMC,KAASC,EAChB,GAAK3L,EAAQ,OAAO,IAAI0L,EAAM,MAAM,GACpC,GAAK1L,EAAQ,MAAM,IAAI0L,EAAM,MAAM,GAAK,MAAaA,EAAM,MAC3D,IAAI,CAACA,EAAM,WAAY,CACnBD,EAAsB,EACtB,MACJ,CACAzL,EAAQ,OAAO,IAAI0L,EAAM,OAAQA,EAAM,kBAAkB,EACzD1L,EAAQ,MAAM,IAAI0L,EAAM,OAAQA,EAAM,IAAI,EACtCA,EAAM,MAAQ1L,EAAQ,WACtB,EAAQ,WAAa0L,EAAM,WAC3B,EAAQ,SAAWA,EAAM,KAL7B,CAQJ,GACI,CAAC1L,EAAQ,YACT,CAAC,GAAGA,EAAQ,OAAO,OAAO,CAAC,CAAC,CAAC,KAAM,GAAW,CAACwK,CAAM,EAErD,OACJ,IAAMoB,EAAWhB,EACb5K,EAAQ,WACRA,EAAQ,OAAO,IAAIA,EAAQ,SAAS,EACpCA,EAAQ,OAAO,IAAIoG,EAAWpG,EAAQ,MAAQ,EAAE,EAChDA,EAAQ,OAAO,IAAIoG,EAAWpG,EAAQ,MAAQ,EAAE,CACpD,EACAA,EAAQ,OAAO,SAAS,EAAG,IACvBwL,EAA0B,UAAUjH,CAAM,CAC9C,EACAiH,EAA0B,YAAY,EACtC,EAA2B,KACtBI,IACL,EAAuB,OAAO,0BAA4B,CACtD,EAAuB,EAEnB5L,EAAQ,aAAeqL,GACvB/E,IAAgBtG,EAAQ,OACvBgG,EAAQ,aAGbG,EAAK,SAAS,CAAE,KAAMyF,EAAU,SAAU,QAAS,CAAC,CACxD,CAAC,EACL,EACA,CAAE,KAAMzF,CAAK,CACjB,EACA,KAEV,SAASsF,GAAwB,CAC7B,GAA6B,EAC7B,OAAO,qBAAqBH,CAAoB,EAChD,EAAuB,EACvBC,GAA0B,OAAO,SAAS,EAAG,IACzCC,EAA0B,UAAUjH,CAAM,CAC9C,EACAiH,GAA2B,YAAY,EACvC,EAA2B,IAC/B,CAEA,SAASK,EAAuB,EAAW,CACvC,IAAMpJ,EAAQ2D,EAAW,QAAQG,CAAS,EACpCuF,EAAU,CAACvF,EAAWH,EAAW3D,EAAQ,GAAI2D,EAAW3D,EAAQ,EAAE,CAAC,CAAC,OAAO,OAAO,EACxF,EAA2B,CACvB,YACA,QACA,WAAY4I,EACZ,OAAQ,IAAI,IAAIS,EAAQ,IAAK,GAAW,CAACvH,EAAQ,IAAI,CAAC,CAAC,EACvD,MAAO,IAAI,IACX,WAAY,KACZ,SAAU,IACd,EACAuH,EAAQ,QAAS,GAAWN,EAA0B,QAAQjH,CAAM,CAAC,CACzE,CAEA,SAASwH,EAAgC,EAAW,CAChD,GAAI,CAAC5F,EAAM,MAAO,GAClB,IAAM1D,EAAQ2D,EAAW,QAAQG,CAAS,EAC1C,OAAOqE,EACHzE,EAAK,sBAAsB,EAC3BI,EAAU,sBAAsB,EAChCH,EAAW3D,EAAQ,EAAE,EAAE,sBAAsB,EAC7C2D,EAAW3D,EAAQ,EAAE,EAAE,sBAAsB,CACjD,CACJ,CAEA,SAASmG,EAAW,EAAM,EAAW,EAAiB,CAClD,IAAM/M,EAAY,OAAOmK,EAAQ,QAAQ,mBAAmB,CAAC,EAAE,QAAQ,SAAS,GAAK,EAC/EgE,EAAWzD,EAAYH,EAAW,QAAQG,CAAS,EAAI,EAAI,EACjEjB,EAA2B1J,EAAM,CAC7B,GAAIC,EAAY,EAAI,CAAE,YAAa,CAACA,CAAS,CAAE,EAAI,CAAC,EACpD,eAAgB,iBAChB,iBAAkBmQ,EAClB,WAAYzF,GAAW,QAAQ,MAAQ,QAAU,QACjD,eAAgByD,CACpB,CAAC,CACL,CAEA,SAASiC,IAAe,CACpB5F,EAAO,QAAS,GAAW,CACvB,IAAM6F,EAAY,OAAOlQ,EAAO,QAAQ,oBAAoB,EACtDmQ,EACF,CAAC/F,EAAW,QACX8F,EAAY,GAAK5F,IAAgB,GACjC4F,EAAY,GAAK5F,IAAgBF,EAAW,OAAS,EAC1D,EAAO,SAAW+F,EAClB,EAAO,OAASA,CACpB,CAAC,CACL,CAEA,SAASC,EACL,EACA,CACI,YAAY,GACZ,kBAAkB,KAClB,eAAe,GACf,gBAAgB,GAChB,SAAS,IACT,CAAC,EACP,CACE,IAAM3J,EAAQ2D,EAAW,QAAQG,CAAS,EAC1C,GAAI9D,EAAQ,EAAG,OACfgJ,EAAsB,EACtB,IAAMY,EACFC,GAAU,CAACd,EAA4BO,EAAgCxF,CAAS,EAAI,EAClFgG,EAAeF,EAAiBlG,EAAK,WAAakG,EAAiB,GACpElF,GAAoBE,IAAmB,CAACC,GAA0BuB,EAAkB,EACzF,OAAO,aAAa9B,CAAe,EACnC,EAAkB,EAClB,EAAwB,KACxBc,GAAa,EACb,EAAcpF,EACd,IAAMkD,EAAQY,EAAU,QAAQ,MAC1B4B,EAAQ5B,EAAU,QAAQ,MAEhC,EAAS,OAAS,GACdA,EAAU,QAAQ,OAAQ,EAAU,OAASA,EAAU,QAAQ,OAC9DR,EAAU,gBAAgB,QAAQ,EACnCJ,IAAO,EAAU,IAAMA,GACvBY,EAAU,QAAQ,MAAK,EAAU,IAAMA,EAAU,QAAQ,KACzDA,EAAU,QAAQ,QAAO,EAAS,KAAOA,EAAU,QAAQ,OAC/D,CAAC,cAAe,cAAe,aAAc,aAAa,CAAC,CAAC,QAAS,GAAQ,CACrEA,EAAU,QAAQiG,GAAM,EAAS,QAAQA,GAAOjG,EAAU,QAAQiG,GACjE,OAAOtG,EAAS,QAAQsG,EACjC,CAAC,EACD,EAAU,MAAM,UAAYjG,EAAU,QAAQ,YAAc,QAAU,QAAU,UAChF,EAAU,MAAM,eAAiB,GAAGA,EAAU,QAAQ,iBAAmB,GAAG,IAAIA,EAAU,QAAQ,iBAAmB,GAAG,GACpH4B,GAAS,CAACsE,IACV,EAAwBlG,EACxB,EAAkB,OAAO,eACfoC,EAAiBpC,EAAW9D,EAAOiK,CAAa,EACtD,GACJ,GAGJtG,EAAW,QAAS,GAAS,CACzB,IAAMuG,EAASpH,IAASgB,EACxBhB,EAAK,UAAU,OAAO,mCAAoCoH,CAAM,EAChEpH,EAAK,aAAa,eAAgB,OAAOoH,CAAM,CAAC,EAChD,EAAK,SAAWA,EAAS,EAAI,EACjC,CAAC,EACGlF,GACA,GAA4B,EAC5ByB,EAAsB,GACnBF,EAAmBvG,CAAK,EAC3B6J,GAAUd,EAA2BK,EAAuBtF,CAAS,EAChE8F,GAAgBlG,EAAK,SAAS,CAAE,KAAMkG,EAAgB,SAAU,QAAS,CAAC,EAC/EO,GAAaC,EAAmBtG,CAAS,GAAK8F,GAC9ClG,EAAK,SAAS,CAAE,KAAMoG,EAAc,SAAU,QAAS,CAAC,EAE5DN,GAAa,EACTD,GACApD,EAAW,uBAAwBrC,EAAWyF,CAAe,CAErE,CAEA5F,EAAW,QAAS,GAAc,CAC9BG,EAAU,iBAAiB,YACvB6F,EAAS7F,EAAW,CAAE,gBAAiB,QAAS,CAAC,CACrD,CACJ,CAAC,EAEDJ,GAAM,eAAe,UAAU,IAAI,kBAAkB,EAErD,SAAS2G,IAAc,CAEnB,GADA,EAAa,EACT,CAACtG,EAAO,OACZ,GAAM,CAAE,WAAU,aAAcA,EAC1BtF,EAAUyF,GAAa,CAACA,EAAU,OAASA,EAAYZ,EAE7D,GADA,EAAQ,MAAM,UAAY,eAAe6F,EAAS,WAC9C3E,EAAc,CACd,IAAM8F,EAASb,EAAY,EAAI,KAAO,IACtC,EAAa,MAAM,UAAY,oBAAoBa,EAAO,MAAMnB,EAAS,WAC7E,CACJ,CAEA,eAAeoB,GAAc,EAAQ,EAAiB,CAClD,IAAM1P,EAAU2J,EAChB,EAAmB,EACnB,EAAmB,KACnB,EAAiB,GACjB,EAA2B,GAC3BmF,EAAS7H,EAAQ,CAAE,iBAAgB,CAAC,EACpC,EAA2B,GAEvB,CAACA,EAAO,QAAQ,OAASwB,EAAU,OACnC,MAAM,QAAQ,KAAK,CACfA,EAAU,OAAO,CAAC,CAAC,UAAY,CAAC,CAAC,EACjC,IAAI,QAAS,GAAY,OAAO,WAAWkH,EAAS,GAAG,CAAC,CAC5D,CAAC,EAED,MAAM,IAAI,QAAS,GAAY,OAAO,sBAAsBA,CAAO,CAAC,EAEpEhG,IAAiB3J,GAASuL,EAAkB,CACpD,CAEA5C,EAAM,iBAAiB,cAAgB,GAAU,CAK7C,GAJIhI,EAAM,WAAaiI,EAAS,SAASjI,EAAM,MAAM,IACjD,EAAe,GACf,EAAwB,IAExB,GAACA,EAAM,WAAaA,EAAM,cAAgB,SAAWmI,EAAW,OAAS,IACzE,GAAM,OAAO,QAAQ,gCAAgC,EAEzD,IADIiB,GAAgBwB,EAAkB,EAClC1B,GAAoBC,EAAkB,CACtC,GAAM,CAAE,SAAQ,mBAAoBA,EACpCyB,EAAkB,EAClBuD,EAAS7H,EAAQ,CAAE,iBAAgB,CAAC,CACxC,MAAW4C,GAAkB0B,EAAkB,EAC/C,EAAe,GACf,EAAQ,CACJ,GAAI5K,EAAM,UACV,EAAGA,EAAM,QACT,EAAGA,EAAM,QACT,MAAOgI,EAAM,YACb,SAAU,EACV,UAAW,CACf,CAT+C,CAUnD,CAAC,EACDA,EAAM,iBAAiB,cAAgB,GAAU,CAC7C,GAAI,CAACO,GAASvI,EAAM,YAAcuI,EAAM,GAAI,OAC5C,IAAM0G,EAAajP,EAAM,QAAUuI,EAAM,EACnC2G,EAAWlP,EAAM,QAAUuI,EAAM,EACvC,GAAI,CAACA,EAAM,WAAaA,EAAM,YAAc,KAAK,KAAK0G,CAAU,EAAG,CAC/D,GAAI,KAAK,IAAIA,CAAU,EAAI,GAAK,KAAK,IAAIA,CAAU,GAAK,KAAK,IAAIC,CAAQ,EAAI,IACzE,OACJlG,GAAc,OAAO,EACrB,EAAe,KACf,EAAM,UAAYiG,EAAa,EAAI,EAAI,GACnCvG,GAAa,CAACA,EAAU,SACxB,EAAM,SAAW,GACjB,EAAM,YAAc,CAACA,EAAU,OAC/BA,EAAU,MAAM,EAChB,EAAU,OAAS,GACnB,EAAS,OAAS,IAEtB,EAAemC,EAAaxC,EAAcE,EAAM,SAAS,EACrDS,GACAhB,EAAM,OAAOgB,CAAY,CAEjC,CACA,IAAMmG,EAAa,EAAQhH,EAAWE,EAAc,KAAK,KAAK4G,CAAU,GACxE,EAAM,SAAWtF,EAAMsF,EAAY,CAAC1G,EAAM,MAAOA,EAAM,KAAK,GAAK4G,EAAa,EAAI,IAClF,CAAiBlG,GAAa,OAAO,sBAAsB4F,EAAW,CAC1E,CAAC,EACD7G,EAAM,iBAAiB,YAAc,GAAU,CAC3C,GAAI,CAACO,GAASvI,EAAM,YAAcuI,EAAM,GAAI,OAC5C,IAAM0G,EAAajP,EAAM,QAAUuI,EAAM,EACnC2G,EAAWlP,EAAM,QAAUuI,EAAM,EACjC6G,EAAY/G,EAAc,KAAK,KAAK4G,CAAU,EAC9CpM,EAAOsF,EAAWiH,GAClBC,EACFxM,GAAQ,KAAK,IAAIoM,CAAU,GAAK,IAAM,KAAK,IAAIA,CAAU,EAAI,KAAK,IAAIC,CAAQ,EAAI,IAChFI,EAAa,EAAQtG,EACrBzL,EAAQgL,EAAM,MAIpB,GAHA,EAAyB,CAAC8G,GAAiB,EAAQ9G,EAAM,SACzD,EAAwB,CAAC8G,GAAiB,EAAQ9G,EAAM,YACxD,EAAQ,KACJ,CAAC8G,EAAe,CAChB,GAAIC,EAAY,CACZ,IAAMC,EAAW,KAAK,MAAM5F,EAAO,KAAK,IAAIsF,CAAU,EAAI1R,EAAS,IAAK,GAAI,GAAG,CAAC,EAChFyK,EAAM,MAAM,YAAY,sCAAuC,GAAGuH,EAAS,GAAG,EAC9EvH,EAAM,UAAU,IAAI,oCAAoC,EACxD,EAAU,MAAM,UAAY,GACxBU,IAAW,EAAU,MAAM,UAAY,IAC3C,EAAa,MAAM,UAAY,eAAeuG,EAAa,EAAI,QAAU,OAAO,SAChF,EAAmB,OAAO,WAAWrE,EAAmB2E,EAAW,EAAE,CACzE,MAAO3E,EAAkB,EACzB,MACJ,CACA,EAAe,GACf,IAAMmD,EAAkBkB,EAAa,EAAI,OAAS,WAClD,GAAI,CAACK,EAAY,CACb1E,EAAkB,EAClBuD,EAAStL,EAAM,CAAE,iBAAgB,CAAC,EAClC,MACJ,CACA,EAAmB,CAAE,OAAQA,EAAM,iBAAgB,EACnD,IAAM0M,EAAW,KAAK,MAClB5F,GAAO,EAAI,KAAK,IAAI,EAAG,KAAK,IAAIsF,CAAU,EAAI1R,CAAK,GAAK,IAAK,GAAI,GAAG,CACxE,EACAyK,EAAM,MAAM,YAAY,sCAAuC,GAAGuH,EAAS,GAAG,EAC9EvH,EAAM,UAAU,IAAI,oCAAoC,EACxD,IAAMwH,EAAc,GAAGP,EAAa,EAAI,IAAM,KAAK1R,EAAM,IACzD,CAACmL,GAAa,CAACA,EAAU,OAASA,EAAYZ,EAAA,CAAW,MAAM,UAC3D,eAAe0H,EAAY,SAC/B,EAAa,MAAM,UAAY,uBAC/B,EAAmB,OAAO,eAAiB,CACvCT,GAAmBlM,EAAMkL,CAAe,CAC5C,EAAGwB,EAAW,EAAE,CACpB,CAAC,EACDvH,EAAM,iBAAiB,oBAAuB,CAC1C,EAAyB,EAAQO,GAAO,SACxC,EAAwB,EAAQA,GAAO,YACvC,EAAQ,KACRqC,EAAkB,CACtB,CAAC,EACD3C,EAAS,iBAAiB,UAAY,GAAU,EACxCjI,EAAM,MAAQ,SAAWA,EAAM,MAAQ,OACvC,EAAe,GACf,EAAwB,GAEhC,CAAC,EAEDiI,EAAS,iBAAiB,YAAc,GAAU,CAE1CjI,EAAM,cAAgB,SACtB,CAACA,EAAM,WACP,CAACuI,GACDvI,EAAM,YAAcuI,EAAM,IAC1BA,EAAM,WACN,KAAK,IAAIvI,EAAM,QAAUuI,EAAM,CAAC,GAAK,GACrC,KAAK,IAAIvI,EAAM,QAAUuI,EAAM,CAAC,GAAK,IAIzC,EAAwB,GACxB,OAAO,mBAAqB,CACxB,EAAe,GACfN,EAAS,MAAM,CACnB,CAAC,EACL,CAAC,EAEDC,GAAM,iBAAiB,UAAY,GAAU,CACzC,GAAI,CAAClI,EAAM,OAAO,QAAQ,8BAA8B,EAAG,OAC3D,IAAIoP,EAAY/G,EAChB,GAAIrI,EAAM,MAAQ,YAAa,SAC1B,GAAIA,EAAM,MAAQ,aAAc,GAAa,OAC7C,GAAIA,EAAM,MAAQ,OAAQ,EAAY,OACtC,GAAIA,EAAM,MAAQ,MAAO,EAAYmI,EAAW,OAAS,OACzD,OACLnI,EAAM,eAAe,EACrBmO,EAAShG,EAAW,KAAK,IAAI,EAAG,KAAK,IAAIA,EAAW,OAAS,EAAGiH,CAAS,CAAC,GAAI,CAC1E,UAAW,GACX,gBACIpP,EAAM,MAAQ,YACR,WACAA,EAAM,MAAQ,aACZ,OACA,QAChB,CAAC,CACL,CAAC,EAEDoI,EAAO,QAAS,GAAW,CACvBrK,EAAO,iBAAiB,YAAe,CACnC,IAAMqR,EAAY,KAAK,IACnB,EACA,KAAK,IACDjH,EAAW,OAAS,EACpBE,EAAc,OAAOtK,EAAO,QAAQ,oBAAoB,CAC5D,CACJ,EACAoQ,EAAShG,EAAWiH,GAAY,CAC5B,gBACI,OAAOrR,EAAO,QAAQ,oBAAoB,EAAI,EAAI,WAAa,MACvE,CAAC,CACL,CAAC,CACL,CAAC,EAEDgK,EAAQ,cAAc,yBAAyB,CAAC,EAAE,iBAAiB,QAAU,GAAU,CACnF,IAAMtJ,EAASsJ,EACV,QAAQ,mBAAmB,CAAC,EAC3B,cAAc,6BAA6B,EACjDlB,GACI,OAAO7G,EAAM,cAAc,QAAQ,eAAe,EAClDA,EAAM,cACNvB,CACJ,CACJ,CAAC,EAEDwJ,EAAS,iBAAiB,QAAS,KAAO,IAAU,CAChD,GAAIQ,GAAyBzI,EAAM,UAAW,CAC1CA,EAAM,eAAe,EACrB,EAAwB,GACxB,MACJ,CACA,GACI,IAAM,kBACNA,EAAM,SAAW,GACjBA,EAAM,SACNA,EAAM,SACNA,EAAM,UACNA,EAAM,QAGV,IAAIwI,EAAc,CACdxI,EAAM,eAAe,EACrB,EAAe,GACf,MACJ,CACA,GAAI+I,EAAuB,CACvB/I,EAAM,eAAe,EACrB0K,EAAiB3B,EAAuBV,CAAW,EACnD,MACJ,CAEA,GADArI,EAAM,eAAe,EACjBiI,EAAS,aAAa,WAAW,IAAM,OAG3C,CADA0C,EAAW,uBAAwBxC,EAAWE,GAAc,MAAM,EAClEJ,EAAS,aAAa,YAAa,MAAM,EAEzC,GAAI,CACA,GAAM,CAAE,wBAAyB,MAAML,GAAqB,EAC5D,GAAI,CAACG,EAAQ,YAAa,OAE1B,IAAM0H,EAAkBtH,EAAWE,GAC7BqH,EAASvH,EAAW,OACpBA,EAAW,IAAK,GACZG,EAAU,QAAQ,MACZ,CACI,KAAM,QACN,SAAUA,EAAU,QAAQ,MAC5B,UAAWA,EAAU,QAAQ,WAAa,GAC1C,UAAWA,EAAU,QAAQ,WAAa,YAC1C,OAAQA,EAAU,QAAQ,aAAeA,EAAU,QAAQ,MAC3D,aAAcA,EAAU,QAAQ,mBAAqB,GACrD,MAAO,OAAOA,EAAU,QAAQ,UAAU,GAAK,KAC/C,OAAQ,OAAOA,EAAU,QAAQ,WAAW,GAAK,KACjD,IAAKA,EAAU,QAAQ,KAAO,cAClC,EACA,CACI,IACIA,EAAU,QAAQ,aAClBA,EAAU,QAAQ,OAClBA,EAAU,QAAQ,MACtB,OAAQA,EAAU,QAAQ,aAAe,OACzC,MAAO,OAAOA,EAAU,QAAQ,UAAU,GAAK,KAC/C,OAAQ,OAAOA,EAAU,QAAQ,WAAW,GAAK,KACjD,KACIA,IAAcmH,GACR3H,EAAU,YACVQ,EAAU,QAAQ,MAC5B,IAAKA,EAAU,QAAQ,KAAOR,EAAU,IACxC,QAASG,EACT,aAAcK,EAAU,QAAQ,YAAc,OAClD,CACV,EACA,CACI,CACI,IAAKL,EAAS,QAAQ,aAAeA,EAAS,KAC9C,OAAQA,EAAS,QAAQ,aAAe,OACxC,MAAO,OAAOA,EAAS,QAAQ,UAAU,GAAK,KAC9C,OAAQ,OAAOA,EAAS,QAAQ,WAAW,GAAK,KAChD,KAAMH,EAAU,YAAcA,EAAU,IACxC,IAAKA,EAAU,IACf,QAASG,EACT,aAAc,iBAAiBH,CAAS,CAAC,CAAC,YAAc,OAC5D,CACJ,EACA6H,EAAa,KAAK,IAAI,EAAGxH,EAAW,QAAQsH,CAAe,CAAC,EAC9DG,EAAcD,EAElBE,EAAqB,CACjB,aAAc,GACd,SACA,MAAOF,EACP,eAAgBpE,EAChB,WAAcxD,EAAQ,UAAU,IAAI,gCAAgC,EACpE,SAAW,GAAc,CACrB,GAAIqH,IAAcQ,EAAa,OAC/B,EAAcR,EACd,IAAM9G,EAAYH,EAAWiH,GACzB9G,IACA6F,EAAS7F,EAAW,CAAE,gBAAiB,SAAU,aAAc,EAAK,CAAC,EACjEA,EAAU,QAAQ,OAClBqC,EAAW,uBAAwBrC,EAAW,QAAQ,EAElE,EACA,cAAiB,CACbP,EAAQ,UAAU,OAAO,gCAAgC,EACrDA,EAAQ,aAAeI,EAAWE,EAAY,EAAE,QAAQ,OACxD8F,EAAShG,EAAWE,GAAc,CAAE,cAAe,EAAM,CAAC,CAElE,CACJ,CAAC,CACL,MAAQ,CACJ,OAAO,SAAS,OAAOJ,EAAS,IAAI,CACxC,QAAU,CACNA,EAAS,gBAAgB,WAAW,CACxC,CAhFyC,CAVzC,CA2FJ,CAAC,EAED,SAAS6H,IAAwB,CAC7B,GAAI,CAAC/H,EAAQ,QAAQ,yBAA0B,MAAO,GAEtD,IAAIgI,EACJ,GAAI,CACA,EAAe,KAAK,MAAMhI,EAAQ,QAAQ,wBAAwB,CACtE,MAAQ,CACJ,MAAO,EACX,CAEA,IAAM1I,EAAU0I,EAAQ,cAAc,4CAA4C,EAC5EiI,EAAUjI,EAAQ,QAAQ,iBAAiB,EACjD,GAAI,CAAC1I,GAAW,CAAC2Q,GAAW,CAACD,GAAc,MAAO,MAAO,GAEzD,IAAME,EAAiB,GAAa,CAChC,IAAMtS,EAAO,UAAU,OAAOuS,CAAQ,EAAE,GACxC,OAAOF,EAAQ,cAAc,eAAerS,EAAK,2BAA2BA,EAAK,GAAG,CACxF,EACMwS,EAAc,GAAa,CAC7B,IAAM9J,EAAU4J,EAAcC,CAAQ,EACtC,OAAO7J,GAAS,QAAQ,QAAQ,EAC1BA,EAAQ,gBAAgB,EAAE,EAAE,QAAQ,WACpCA,GAAS,QAAQ,UAC3B,EACM+J,EAAmBJ,EAAQ,iBAC7B,sBAAsB,OAAOD,EAAa,oBAAoB,EAAE,2BAA2B,OAAOA,EAAa,oBAAoB,EAAE,IACzI,EACMM,EAAmBL,EAAQ,iBAC7B,sBAAsB,OAAOD,EAAa,oBAAoB,EAAE,2BAA2B,OAAOA,EAAa,oBAAoB,EAAE,IACzI,EAEMlL,MAAe,CACjB,IAAMyL,EAAaH,EAAWJ,EAAa,oBAAoB,EACzDQ,EAAaJ,EAAWJ,EAAa,oBAAoB,EACzD1E,EAAQ0E,EAAa,MAAM,GAAGvD,EAAW8D,CAAU,EAAE,GAAG9D,EAAW+D,CAAU,KACnF,GAAI,CAAClF,EAAO,OAEZ,EAAQ,QAAQ,MAAQA,EAAM,WAAaA,EAAM,OAAS,GAC1D,EAAQ,QAAQ,OAASD,GAAYC,CAAK,EAC1C,EAAQ,QAAQ,MAAQA,EAAM,OAASA,EAAM,WAAaA,EAAM,OAAS,GACzE,EAAQ,QAAQ,YAAcA,EAAM,cAAgBhM,EAAQ,QAAQ,MACpE,EAAQ,QAAQ,YAAciM,GAAYD,CAAK,EAC/C,EAAQ,QAAQ,WACZA,EAAM,mBAAmB,OAASA,EAAM,YAAY,OAAS,KACjE,EAAQ,QAAQ,YACZA,EAAM,mBAAmB,QAAUA,EAAM,YAAY,QAAU,KACnE,EAAQ,QAAQ,gBAAkBA,EAAM,oBAAsB,GAC9D,EAAQ,QAAQ,gBAAkBA,EAAM,oBAAsB,GAC9D,EAAQ,QAAQ,UAAYA,EAAM,mBAAqB,QAAU,QAAU,UAC3EhM,EAAQ,MAAM,YAAY,sBAAuB,GAAGA,EAAQ,QAAQ,gBAAgB,EAAE,EACtFA,EAAQ,MAAM,YAAY,sBAAuB,GAAGA,EAAQ,QAAQ,gBAAgB,EAAE,EACtF,OAAOA,EAAQ,QAAQ,MACvB,OAAOA,EAAQ,QAAQ,UACvB,OAAOA,EAAQ,QAAQ,UACvB,IAAMmR,EAAenR,EAAQ,cAAc,KAAK,EAC5CmR,GAAgBnF,EAAM,QACtB,EAAa,IAAMA,EAAM,MACzB,EAAa,OAASA,EAAM,aACtB,GAAGA,EAAM,MAAM,OAAOA,EAAM,aAAa,KACzCA,EAAM,OAEhB8C,EAAS9O,CAAO,CACpB,EAMA,MAJA,CAAC,GAAG+Q,EAAkB,GAAGC,CAAgB,CAAC,CAAC,QAAS,GAChDpQ,EAAM,iBAAiB,SAAU4E,CAAM,CAC3C,EACAA,EAAO,EACA,EACX,CAEA,GAAIiL,GAAsB,EAAG,OAC7B,IAAMW,GAAmBtI,EAAWE,GACpC,GAAI,CAACoI,GAAkB,CACnBzC,GAAa,EACb,MACJ,CAGAG,EAASsC,GAAkB,CAAE,cAAe,EAAM,CAAC,CACvD,CC56BA,SAASC,EAAoB,EAAQ,CACjCpK,EAAO,eAAe,CAAE,SAAU,SAAU,MAAO,QAAS,CAAC,EAC7D,OAAO,eAAiB,CAChBsI,EAAmBtI,CAAM,GACzBA,EAAO,eAAe,CAAE,SAAU,SAAU,MAAO,QAAS,CAAC,CAErE,EAAG,GAAG,CACV,CAEA,SAAgBqK,EAA0B,EAAQ,CAC9C,IAAMC,EAAW,SAAS,cAAc,yBAAyB,EAC3D5R,EAAO4R,GAAU,cAAc,eAAe,EAC9CzR,EAAayR,GAAU,cAAc,2BAA2B,EAChEC,EAAeC,EAAO,cAAc,4BAA4B,EAChEC,EAAcD,EAAO,cAAc,6BAA6B,EAChEE,EAAcF,EAAO,cAAc,6BAA6B,EAChEG,EAAcL,GAAU,cAAc,4BAA4B,EAClEM,EAAiBN,GAAU,cAAc,8BAA8B,EACvEO,EAAS,SAAS,cAAc,gBAAgB,EAEtD,GAAI,CAACP,GAAY,CAAC5R,GAAQ,CAACG,GAAc,CAAC0R,GAAgB,CAACE,EAAa,OAExE,IAAIK,EAAgB,GAChBC,EAAgB,GAChBC,EAAmB,KACnBC,EAAgB,EAChBC,EAAiB,GACjBC,EAAgB,GAChBC,EAAc,EACZzP,MAAe,CAEjB,GADA,EAAc,EACV,CAACqP,GAAoBF,EAAe,CAEpC,GADA,EAAiBjS,EAAW,sBAAsB,CAAC,CAAC,OAAS,EACzDgS,EAAQ,CACR,IAAM5E,EAAS4E,EAAO,sBAAsB,EAC5C,EAAgB5E,EAAO,IAAM,OAAO,aAAeA,EAAO,OAAS,CACvE,CACA,EAAgB,GAChB,EAAgB,EACpB,CACA,IAAMoF,EAAOxS,EAAW,aAAa,WAAW,IAAM,OAChDyS,EAAUP,GAAiBG,GAAkB,CAACC,EAChDX,EAAO,QAAQ,UAAY,OAAOc,CAAO,IACzC,EAAO,QAAQ,QAAU,OAAOA,CAAO,EACvC,SAAS,KAAK,UAAU,OAAO,yCAA0CA,CAAO,GAEhFf,EAAa,aAAa,WAAW,IAAM,OAAOc,CAAI,GACtDd,EAAa,aAAa,YAAa,OAAOc,CAAI,CAAC,EAEvD,IAAME,EACF1S,EAAW,UAAY+R,EAAiB,mBAAqB,mBAEjE,GADIH,EAAY,cAAgBc,IAAO,EAAY,YAAcA,GAC7Db,GAAeC,EAAa,CAC5B,IAAMhN,EAAQgN,EAAY,YAAY,KAAK,EACvCD,EAAY,cAAgB/M,IAAO,EAAY,YAAcA,EACrE,CACJ,EACM6N,MAAuB,CACzB,CAAkBJ,GAAc,OAAO,sBAAsBzP,CAAM,CACvE,EACM8P,MAA2B,CAC7B,GAAIT,EAAkB,CAClB,GAAIC,EAAe,OACnB,EAAgB,OAAO,0BAA4B,CAE/C,GADA,EAAgB,EACZ,CAACX,EAAS,YAAa,CACvBU,EAAiB,WAAW,EAC5B,MACJ,CAGAA,EAAiB,UAAUnS,CAAU,EACrCmS,EAAiB,YAAY,EAC7BA,EAAiB,QAAQnS,CAAU,CACvC,CAAC,EACD,MACJ,CACA,EAAgB,GAChB2S,EAAe,CACnB,EAyBA,GAvBI,OAAO,qBAAyB,MAChC,EAAmB,IAAI,qBAAsB,GAAY,CACrD,GAAI,CAAClB,EAAS,YAAa,CACvBU,EAAiB,WAAW,EAC5B,MACJ,CACA,IAAI7D,EAAQ,KACZ,IAAK,IAAMhQ,KAAaiQ,EAChBjQ,EAAU,SAAW0B,IAAe,CAACsO,GAAShQ,EAAU,MAAQgQ,EAAM,QACtE,EAAQhQ,GAEXgQ,IACL,EAAiBA,EAAM,mBAAmB,OAAS,EACnD,EAAgB,GAChBqE,EAAe,EACnB,CAAC,EACDR,EAAiB,QAAQnS,CAAU,GAGvC,OAAO,iBAAiB,SAAU4S,EAAoB,CAAE,QAAS,EAAK,CAAC,EACvE,OAAO,iBAAiB,SAAUA,EAAoB,CAAE,QAAS,EAAK,CAAC,EACvE,SAAS,iBAAiB,4BAA6BA,CAAkB,EACzEnB,EAAS,iBAAiB,OAAQmB,EAAoB,EAAI,EACtD,OAAO,eAAmB,IAAa,CACvC,IAAMC,EAAW,IAAI,eAAeD,CAAkB,EACtDC,EAAS,QAAQpB,CAAQ,EACzBoB,EAAS,QAAQ,SAAS,IAAI,CAClC,CAEIb,GAAU,OAAO,qBAAyB,KAC1C,IAAI,qBAAsB,GAAY,CAClC,IAAI1D,EAAQ,KACZ,IAAK,IAAMhQ,KAAaiQ,EAChBjQ,EAAU,SAAW0T,IAAW,CAAC1D,GAAShQ,EAAU,MAAQgQ,EAAM,QAClE,EAAQhQ,GAEXgQ,IACL,EAAgBA,EAAM,eACtBqE,EAAe,EACnB,CAAC,CAAC,CAAC,QAAQX,CAAM,EAGrB,IAAI,iBAAiBW,CAAc,CAAC,CAAC,QAAQ3S,EAAY,CACrD,WAAY,GACZ,gBAAiB,CAAC,WAAY,WAAW,CAC7C,CAAC,EACG8R,GACA,IAAI,iBAAiBa,CAAc,CAAC,CAAC,QAAQb,EAAa,CACtD,UAAW,GACX,cAAe,GACf,QAAS,EACb,CAAC,EAGLJ,EAAa,iBAAiB,YAAe,CACzC,GAAI1R,EAAW,aAAa,WAAW,IAAM,OAAQ,OAErD,IAAM8S,EAAUjT,EAAK,cAAc,UAAU,EAC7C,GAAIiT,EAAS,CACTvB,EAAoBuB,CAAO,EAC3B,OAAO,eAAiBjT,EAAK,eAAe,EAAG,GAAG,EAClD,MACJ,CAEA,GAAIG,EAAW,UAAY+R,EAAgB,CACvCA,EAAe,MAAM,EACrB,MACJ,CAEK/R,EAAW,UAAUA,EAAW,MAAM,CAC/C,CAAC,EAED,EAAO,OAAS,GACXmS,GAAkBQ,EAAe,CAC1C,CC5JA,SAAgBI,EAAyB,EAAM,CAC3C,GAAI,EAAE,mBAAoB,QAAS,OAEnC,IAAMC,EAAU,CAAC,GAAGC,EAAK,QAAQ,CAAC,CAAC,OAAQ,GACvCvR,EAAQ,aAAa,4BAA4B,CACrD,EACA,GAAI,CAACsR,EAAQ,OAAQ,OAErB,IAAME,EAAU,IAAI,IAChBC,EAAQ,EACNN,EAAW,IAAI,eAAgB,GAAY,CAE7C,IAAK,IAAMvE,KAASC,EAAS,CACzB,IAAMlQ,EAASiQ,EAAM,gBAAgB,EAAE,EAAE,WAAaA,EAAM,eAAe,UACvE,OAAO,SAASjQ,CAAM,GAAG6U,EAAQ,IAAI5E,EAAM,OAAQjQ,CAAM,CACjE,CACK6U,EAAQ,MAAQ,KACrB,EAAQ,OAAO,0BAA4B,CAEvC,GADA,EAAQ,EACJ,CAACD,EAAK,YAAa,CACnBJ,EAAS,WAAW,EACpBK,EAAQ,MAAM,EACd,MACJ,CACA,IAAK,GAAM,CAACE,EAAQ/U,KAAW6U,EAAS,CACpC,IAAMjT,EAAQ,GAAG5B,EAAO,IACpB+U,EAAO,MAAM,iBAAiB,kCAAkC,IAAMnT,GACtEmT,EAAO,MAAM,YAAY,mCAAoCnT,CAAK,EAElEmT,EAAO,aAAa,kCAAkC,IAAM/U,EAAS,GACrE+U,EAAO,gBAAgB,mCAAoC/U,EAAS,CAAC,CAE7E,CACA6U,EAAQ,MAAM,CAClB,CAAC,EACL,CAAC,EACDF,EAAQ,QAAS,GAAWH,EAAS,QAAQO,EAAQ,CAAE,IAAK,YAAa,CAAC,CAAC,CAC/E,CCrCA,SAAgBC,EAAoB,EAAQ,CACpC,OAAO,aAAa,QAAQ,iBAAiBC,EAAO,QAAQ,YAAY,IAAM,cAE9E,OAAOA,EAAO,WAAc,WAAYA,EAAO,UAAU,EACxDA,EAAO,aAAa,OAAQ,EAAE,EACnCA,EAAO,cAAc,mBAAmB,CAAC,EAAE,iBAAiB,YAAe,CACvE,OAAO,aAAa,QAAQ,iBAAiBA,EAAO,QAAQ,aAAc,WAAW,EACrF,SAAS,OAAS,4DACtB,CAAC,EACL,CCRA,SAAgBC,GAAmB,EAAM,CACrC,IAAMC,EAAO,CAAC,GAAG3U,EAAK,iBAAiB,cAAc,CAAC,EACtD,GAAI,CAAC2U,EAAK,OAAQ,OAElB,IAAMC,EAASD,EACV,IAAK,GAAQ,SAAS,eAAeE,EAAI,aAAa,eAAe,CAAC,CAAC,CAAC,CACxE,OAAO,OAAO,EACbC,EAAgB,OAAO,WAAW,kCAAkC,EACpEC,EAAe,GAAS,CAC1B,IAAM9R,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EACxC,EAAI,KAAO+R,EACX,QAAQ,aAAa,QAAQ,MAAO,GAAI/R,CAAG,CAC/C,EAEMkN,GAAY,EAAK,CAAE,QAAQ,GAAO,SAAS,GAAO,aAAa,IAAU,CAAC,IAAM,CAClFwE,EAAK,QAAS,GAAS,CACnB,IAAMjE,EAASpH,IAASuL,EACxBvL,EAAK,UAAU,OAAO,iCAAkCoH,CAAM,EAC9DpH,EAAK,aAAa,gBAAiB,OAAOoH,CAAM,CAAC,EACjD,EAAK,SAAWA,EAAS,EAAI,EACjC,CAAC,EACDkE,EAAO,QAAS,GAAU,CACtB,EAAM,OAASK,EAAM,KAAOJ,EAAI,aAAa,eAAe,CAChE,CAAC,EACGK,GAAOtE,EAAmBiE,CAAG,EAC7BxE,GACAwE,EAAI,eAAe,CACf,SAAUC,EAAc,QAAU,OAAS,SAC3C,MAAO,UACP,OAAQ,SACZ,CAAC,EAEDK,GAAYJ,EAAYF,EAAI,IAAI,CACxC,EAEA7U,EAAK,UAAU,IAAI,6BAA6B,EAChD2U,EAAK,SAAS,EAAK,IAAU,CACzBE,EAAI,iBAAiB,QAAU,GAAU,CACrC7S,EAAM,eAAe,EACrBmO,EAAS0E,EAAK,CAAE,OAAQ,GAAM,WAAY,EAAK,CAAC,CACpD,CAAC,EACDA,EAAI,iBAAiB,UAAY,GAAU,CACvC,IAAIzD,EACJ,GAAIpP,EAAM,MAAQ,YAAa,GAAawE,EAAQ,EAAImO,EAAK,QAAUA,EAAK,YACvE,GAAI3S,EAAM,MAAQ,aAAc,GAAawE,EAAQ,GAAKmO,EAAK,YAC/D,GAAI3S,EAAM,MAAQ,OAAQ,EAAY,OACtC,GAAIA,EAAM,MAAQ,MAAO,EAAY2S,EAAK,OAAS,OACnD,OACL3S,EAAM,eAAe,EACrBmO,EAASwE,EAAKvD,GAAY,CACtB,MAAO,GACP,OAAQ,GACR,WAAY,EAChB,CAAC,CACL,CAAC,CACL,CAAC,EAED,IAAMgE,EAAkBpV,EAAK,cAAc,iCAAiC,EACtEqV,EAAkBrV,EAAK,cAAc,iCAAiC,EACtEsV,EAAgBtV,EAAK,cAAc,2BAA2B,EAC9DuV,GAAuB,CAAE,aAAa,GAAM,SAAS,IAAS,CAAC,IAAM,CAClEF,GAAoBC,IACzBnF,EAASmF,CAAa,EACtB,EAAgB,KAAO,GACnBH,GAAYJ,EAAY,IAAIM,EAAgB,IAAI,EAChDhF,IACAgF,EAAgB,eAAe,CAC3B,SAAUP,EAAc,QAAU,OAAS,SAC3C,MAAO,OACX,CAAC,EACDlE,EAAmByE,EAAgB,cAAc,SAAS,CAAC,GAEnE,EAEAD,GAAiB,iBAAiB,QAAU,GAAU,CAClDpT,EAAM,eAAe,EACrBuT,EAAoB,CACxB,CAAC,EAED,IAAMC,EAAUb,EAAK,KAAM,GAAQE,EAAI,OAAS,OAAO,SAAS,IAAI,EAChEQ,GAAmB,OAAO,SAAS,OAAS,IAAIA,EAAgB,KAChEE,EAAoB,CAAE,WAAY,GAAO,OAAQ,EAAM,CAAC,EAExDpF,EAASqF,GAAWb,EAAK,EAAE,CAEnC,CCrFA,SAAgBc,GAAmB,EAAM,CACrC,IAAMhB,EAASzU,EAAK,cAAc,+BAA+B,EACjE,GAAI,CAACyU,GAAU,OAAO,kBAAsB,IAAa,OAEzD,IAAMiB,EAAOjB,EAAO,cAAc,6BAA6B,EAC3DkB,EACAC,EAEEC,EAAO,KAAO,IAAU,CAC1B,IAAM5S,EAAM,IAAI,IAAI7B,EAAO,OAAO,SAAS,IAAI,EAC/C,GAAI6B,EAAI,SAAW,OAAO,SAAS,OAAQ,MAAO,GAClD0S,GAAe,MAAM,EACrB,EAAgB,IAAI,gBACpB,EAAK,UACD,2GACJlB,EAAO,aAAa,YAAa,MAAM,EACvC,GAAI,CACA,IAAMrP,EAAW,MAAM,MAAMnC,EAAK,CAC9B,YAAa,cACb,QAAS,CAAE,OAAQ,WAAY,EAC/B,OAAQ0S,EAAc,MAC1B,CAAC,EACD,GAAI,CAACvQ,EAAS,GAAI,MAAU,MAAM,QAAQA,EAAS,QAAQ,EAO3D,MANA,GAAK,UAAY,MAAMA,EAAS,KAAK,EACrC,EAAO,QAAQ,OAASnC,EAAI,KAC5B,SAAS,cACL,IAAI,YAAY,4BAA6B,CAAE,OAAQ,CAAE,KAAMyS,CAAK,CAAE,CAAC,CAC3E,EACAA,EAAK,SAAS,CAAE,IAAK,EAAG,SAAU,MAAO,CAAC,EACnC,EACX,OAASjU,EAAO,CAIZ,OAHIA,aAAiB,cAAgBA,EAAM,OAAS,eACpD,EAAK,UACD,0JAFqE,EAI7E,QAAU,CACNgT,EAAO,gBAAgB,WAAW,CACtC,CACJ,EAEAzU,EAAK,QAAQ,mBAAmB,CAAC,EAC3B,iBAAiB,6BAA6B,CAAC,CAChD,QAAS,GAAS,CACf8V,EAAK,iBAAiB,QAAU,GAAU,CACtC9T,EAAM,eAAe,EACrB,EAAc8T,EACTrB,EAAO,MAAMA,EAAO,UAAU,EAC9BA,EAAO,QAAQ,QAAQoB,EAAUpB,EAAO,QAAQ,YAAY,CACrE,CAAC,CACL,CAAC,EACLA,EACK,cAAc,8BAA8B,CAAC,CAC7C,iBAAiB,YAAeA,EAAO,MAAM,CAAC,EACnDA,EAAO,iBAAiB,QAAU,GAAU,CACpCzS,EAAM,SAAWyS,GAAQA,EAAO,MAAM,CAC9C,CAAC,EACDA,EAAO,iBAAiB,YAAe7D,EAAmBgF,CAAW,CAAC,EACtEF,EAAK,iBAAiB,QAAU,GAAU,CACtC,IAAMI,EAAO9T,EAAM,OAAO,QAAQ,sCAAsC,EACnE8T,IACL9T,EAAM,eAAe,EACrB6T,EAAUC,EAAK,IAAI,EACvB,CAAC,CACL,CC9DA,SAASC,EAAiB,EAAM,CAC5B,IAAMC,EAAOhW,EAAK,cAAc,8BAA8B,EACxDiW,EAASD,GAAM,cAAc,gCAAgC,EAC7DnC,EAAQoC,GAAQ,cAAc,sCAAsC,EACpEC,EAAaF,GAAM,iBAAiB,+BAA+B,CAAC,CAAC,QAAU,EACrF,GAAI,CAACC,GAAU,CAACpC,GAAS,CAACqC,EAAY,OAEtC,IAAMC,EAAU,OAAO,WAAW,wBAAwB,EACtDC,EAAW,GAETC,MAAa,CACfL,EAAK,UAAU,OAAO,eAAgBG,EAAQ,SAAW,CAACC,CAAQ,EAClE,EAAO,OAAS,CAACD,EAAQ,QACzBF,EAAO,aAAa,gBAAiB,OAAO,CAACE,EAAQ,SAAWC,CAAQ,CAAC,EACzE,EAAM,YAAcA,EACd,mBACA,WAAWF,EAAW,oBAChC,EAEAD,EAAO,iBAAiB,YAAe,CACnC,EAAW,CAACG,EACZC,EAAK,CACT,CAAC,EACDF,EAAQ,iBAAiB,SAAUE,CAAI,EACvCA,EAAK,CACT,CAEA,SAAgBC,EAAiB,EAAM,CAC/BtW,EAAK,QAAQ,oBAAsB,SACvC,EAAK,QAAQ,kBAAoB,OACjCuW,EAAmBvW,CAAI,EACvB+V,EAAiB/V,CAAI,EACzB,CChCA,IAAMwW,EAAe,IAAI,QACrBC,EACAC,EAAe,GAEnB,SAASC,EAAiB,EAAM,CAC5B,GAAK3W,EAAK,aAAa,qBAAqB,GAAK,OAAO,OAAO,QAAW,WAG1E,IAAK,GAAM,CAAC4W,EAAKC,IAAS,CACtB,CAAC,aAAc,uBAAuB,EACtC,CAAC,UAAW,2BAA2B,CAC3C,EAAG,CACC,GAAI,SAAS,KAAK,cAAc,aAAaD,EAAI,WAAWC,EAAK,GAAG,EAAG,SACvE,IAAMf,EAAO,SAAS,cAAc,MAAM,EAC1C,EAAK,IAAMc,EACX,EAAK,KAAOC,EACRD,IAAQ,YAAW,EAAK,GAAK,UACjC,SAAS,KAAK,YAAYd,CAAI,CAClC,CACJ,CAEA,SAASgB,GAAqB,CAU1B,MAPA,KACInW,EAAA+V,MAAe,OAAO,qCAAgC,OAAO,iCAAvC,mCAAuC,EAC/D,MAAO,GAAU,CAGf,KAFA,GAAe,GACf,EAAgB,OACVjV,CACV,CAAC,EACMgV,CACX,CAEA,SAAgBM,EAA2B,EAAM,CAAE,gBAAgB,IAAU,CAAC,EAAG,CAC7E,GAAIP,EAAa,IAAIxW,CAAI,EAAG,OAAOwW,EAAa,IAAIxW,CAAI,EAExD,GAAI,CADSA,EAAK,QAAQ,MAClB,EAAG,CACPA,EAAK,gBAAgB,sBAAsB,EAC3CA,EAAK,gBAAgB,WAAW,EAChC,MACJ,CACA,IAAMgX,EAAUC,EAAmBjX,CAAI,EACjCkX,EAAelX,EAAK,cAAc,8BAA8B,EAChEmX,EAAa,IAAI,gBACnBnD,EACAoD,EACAC,EAAc,GACdC,EAAaC,EACbC,EAAS,GACTjE,EAGJvT,EAAK,aAAa,wBAAyB,EAAE,EAC7C,IAAMyX,MAAc,CAChB,GAAIJ,GAAeD,EAAgB,OAAOA,EAC1C,GAAKpX,EAAK,aAAgBwX,GAAWF,EAiCrC,OAhCAN,GAAS,SAAS,EAClBL,EAAiB3W,CAAI,EACrBA,EAAK,aAAa,uBAAwB,EAAE,EAC5CA,EAAK,aAAa,YAAa,MAAM,EACjCkX,IAAc,EAAa,YAAc,sCAC7C,EAAiBJ,EAAmB,CAAC,CAChC,MAAM,CAAE,wBAAyB,CAC9B,GAAI,CAAC9W,EAAK,YAAa,CACnBgU,GAAU,WAAW,EACrBmD,EAAW,MAAM,EACjB,qBAAqB5D,CAAa,EAClCvT,EAAK,gBAAgB,uBAAuB,EAC5C,MACJ,CAGA0X,EAAmB1X,CAAI,EACvB,EAAc,GACdgU,GAAU,WAAW,EACrBmD,EAAW,MAAM,EACjB,qBAAqB5D,CAAa,EAClCvT,EAAK,gBAAgB,uBAAuB,CAChD,CAAC,CAAC,CACD,UAAY,CACJqX,IAAa,EAAiB,QACnC,EAAa,GACbrX,EAAK,gBAAgB,sBAAsB,EAC3CA,EAAK,gBAAgB,WAAW,EAChCgX,GAAS,QAAQ,CAGrB,CAAC,EACEI,CACX,EACAZ,EAAa,IAAIxW,EAAMyX,CAAK,EAC5B,IAAME,MAAuB,CACzB,IAAMpJ,EAASvO,EAAK,sBAAsB,EACpCR,EAAS,SAAS,gBAAgB,aAClCD,EAAQ,SAAS,gBAAgB,YACjCqY,EAAUrJ,EAAO,MAAQ,GAAKA,EAAO,OAAS,EAC9C0C,EAAa1C,EAAO,MAAQ,GAAKA,EAAO,KAAOhP,EACrD,EAASqY,GAAW3G,GAAc1C,EAAO,OAAS,MAAQA,EAAO,IAAM/O,EAAS,IAChFiY,EAAW,CACf,EACMI,EAAiB,GAAU,CAGxB7V,EAAM,YACX,EAAa,GACT,OAAO,qBAAyB,IAAa2V,EAAe,EAC3DF,EAAW,EACpB,EACA,IAAK,IAAMzP,IAAQ,CACf,cACA,YACA,cACA,aACA,QACA,UACA,OACJ,EACI,SAAS,iBAAiBA,EAAM6P,EAAe,CAC3C,QAAS,GACT,QAAS,GACT,OAAQV,EAAW,MACvB,CAAC,EAEL,GAAI,OAAO,qBAAyB,IAAa,CAC7C,IAAMW,MAAyB,CAC3B,qBAAqBvE,CAAa,EAClC,EAAgB,sBAAsBoE,CAAc,CACxD,EACA,IAAK,IAAM3P,IAAQ,CAAC,SAAU,QAAQ,EAClC,OAAO,iBAAiBA,EAAM8P,EAAkB,CAC5C,QAAS,GACT,OAAQX,EAAW,MACvB,CAAC,EAELQ,EAAe,CACnB,KACI,GAAW,IAAI,qBACV,GAAY,CACT,EAASjI,EAAQ,KAAM,GAAUD,EAAM,cAAc,EACrDgI,EAAW,CACf,EACA,CAAE,WAAY,WAAY,CAC9B,EACAzD,EAAS,QAAQhU,CAAI,EAEzB,OAAOyX,CACX,CClJA,IAAMJ,EAAc,IAAI,QAExB,SAAgBU,EAA2B,EAAQ,CAC/C,GAAIV,EAAY,IAAI5C,CAAM,EAAG,OAC7B,IAAMxU,EAAYwU,EAAO,QAAQ,mBAAmB,EAC9CuD,EAAS/X,GAAW,cAAc,8BAA8B,EAChEqI,EAASrI,GAAW,cAAc,+BAA+B,EACjEe,EAAOyT,EAAO,cAAc,8BAA8B,EAChE,GAAI,CAACuD,GAAU,CAAC1P,GAAU,CAACtH,GAAQ,OAAOyT,EAAO,WAAc,WAAY,OAC3E4C,EAAY,IAAI5C,CAAM,EACtB,IAAMwD,EAASjX,EAAK,cAAc,iBAAiB,EAC7CP,EAASO,EAAK,cAAc,wBAAwB,EACtD2S,EAAO,GACPuE,EAAY,GACVC,MAAc,CACXxE,GAAMc,EAAO,MAAM,CAC5B,EACAuD,EAAO,iBAAiB,QAAU,GAAU,CACxChW,EAAM,eAAe,EACrByS,EAAO,UAAU,CACrB,CAAC,EACDA,EACK,iBAAiB,+BAA+B,CAAC,CACjD,QAAS,GAAW1U,EAAO,iBAAiB,QAASoY,CAAK,CAAC,EAChE1D,EAAO,iBAAiB,QAAU,GAAU,CACpCzS,EAAM,SAAWyS,GAAQ0D,EAAM,CACvC,CAAC,EACD1D,EAAO,iBAAiB,SAAW,GAAU,CACrCd,GAAM3R,EAAM,eAAe,CACnC,CAAC,EACDyS,EAAO,iBAAiB,YAAe,CACnC7D,EACIsH,EAAYjY,EAAU,cAAc,2BAA2B,EAAI+X,CACvE,CACJ,CAAC,EACDhX,EAAK,iBAAiB,SAAU,KAAO,IAAU,CAE7C,GADAgB,EAAM,eAAe,EACjB2R,GAAQ,CAAC3S,EAAK,eAAe,EAAG,OACpC,IAAMuW,EAAgBvV,EAAM,UAC5B,EAAO,OAAS,GAChBhB,EAAK,iBAAiB,uBAAuB,CAAC,CAAC,QAAS,GAAU,CAC9D,EAAM,OAAS,GACfA,EAAK,SAAS,UAAUS,EAAM,QAAQ,aAAa,CAAC,EAAE,gBAAgB,cAAc,CACxF,CAAC,EACD,IAAMiU,EAAO,IAAI,SAAS1U,CAAI,EAC9B,EAAO,GACP,EAAO,SAAW,GAClBA,EAAK,aAAa,YAAa,MAAM,EACrC,IAAMmW,EAAa,IAAI,gBACjBiB,EAAU,eAAiBjB,EAAW,MAAM,EAAG,GAAK,EAC1D,GAAI,CACA,IAAM/R,EAAW,MAAM,MAAMpE,EAAK,OAAQ,CACtC,OAAQ,OACR,OACA,YAAa,cACb,MAAO,WACP,QAAS,CAAE,OAAQ,kBAAmB,EACtC,OAAQmW,EAAW,MACvB,CAAC,EACKjX,EAAS,MAAMkF,EAAS,KAAK,CAAC,CAAC,UAAY,CAC7C,MAAU,MACN,8EACJ,CACJ,CAAC,EACD,GAAI,CAACA,EAAS,IAAMlF,EAAO,UAAY,GAAM,CACzC,IAAId,EACJ,IAAK,IAAMO,IAAQ,CAAC,UAAW,YAAY,EAAG,CAC1C,GAAI,CAACO,EAAO,SAASP,GAAO,SAC5B,IAAMsC,EAAQjB,EAAK,SAAS,UAAUrB,CAAI,EACpC8B,EAAQT,EAAK,cAAc,yBAAyBrB,EAAK,GAAG,EAClE,EAAM,YAAcO,EAAO,OAAOP,GAClC,EAAM,OAAS,GACfsC,EAAM,aAAa,eAAgB,MAAM,EACzC,IAAUA,CACd,CACA,GAAI7C,EAAOwR,EAAmBxR,CAAK,OAE/B,MAAU,MACNc,EAAO,OAAS,+CACpB,EACJ,MACJ,CACA,IAAMmY,EAAW,SAAS,cAAc,UAAU,EAClD,EAAS,UAAY,OAAOnY,EAAO,MAAS,SAAWA,EAAO,KAAO,GACrE,IAAMoY,EAAUD,EAAS,QAAQ,cAAc,wBAAwB,EACvE,GAAI,CAACC,EACD,MAAU,MACN,qEACJ,EACJ,EAAY,GACZ7D,EAAO,MAAM,EACbnM,EAAO,gBAAgB+P,EAAS,OAAO,EACvCtB,EAA2BuB,EAAS,CAAE,eAAc,CAAC,CACzD,OAAS7W,EAAO,CACZ,EAAO,YACHA,EAAM,OAAS,aACT,qEACAA,EAAM,OAAS,YACb,oEACAA,EAAM,SAAW,gDAC7B,EAAO,OAAS,EACpB,QAAU,CACN,aAAa2W,CAAO,EACpB,EAAO,GACP,EAAO,SAAW,GAClBpX,EAAK,gBAAgB,WAAW,CACpC,CACJ,CAAC,CACL,CCjGA,SAAS,iBAAiB,yBAAyB,CAAC,CAAC,QAAQkT,CAAwB,EACrF,SAAS,iBAAiB,wBAAwB,CAAC,CAAC,QAAQrK,CAAkB,EAC9E,SAAS,iBAAiB,yBAAyB,CAAC,CAAC,QAAQT,CAAmB,EAChF,SAAS,iBAAiB,wBAAwB,CAAC,CAAC,QAAQ2N,CAA0B,EACtF,SAAS,iBAAiB,gCAAgC,CAAC,CAAC,QAAQgB,CAA0B,EAC9F,SAAS,iBAAiB,gCAAgC,CAAC,CAAC,QAAQpF,CAAyB,EAC7F,SAAS,iBAAiB,yBAAyB,CAAC,CAAC,QAAQ6B,CAAmB,EAChF,SAAS,iBAAiB,wBAAwB,CAAC,CAAC,QAAQE,EAAkB,EAC9E,SAAS,iBAAiB,wBAAwB,CAAC,CAAC,QAAQe,EAAkB,EAC9E,SAAS,iBAAiB,sBAAsB,CAAC,CAAC,QAAQa,CAAgB,EAC1EiC,EAA2B,EAC3BC,EAAsB","names":["selectVideoPoster","srcset","fallback","candidates","match","source","first","second","targetWidth","width","height","candidate","trackDesigner","name","productId","details","initializeDesigner","button","root","container","result","editor","pendingTemplateId","templateStatus","manageButton","appliedStatus","authenticated","status","restoringTemplate","__vitePreload","n","payload","FabricEngravingEditor","prepareEngravingConfig","form","field","design","cartButton","value","preview","templateId","templateResponse","saved","error","initProductCommerceSpecials","recurring","description","errorText","errors","initProductAvailabilityActions","event","input","minute","deliveryDateFormatter","dispatchDateFormatter","formatDeliveryDate","timestamp","remainingTime","minutes","milliseconds","hours","rest","setMessage","element","text","message","initProductUrgency","url","stock","dispatch","dispatchTitle","dispatchTime","delivery","demand","region","state","personalized","clockOffset","deadlineTimer","refreshToken","requestUrl","request","quantity","render","now","dispatchDeadline","dispatchRemaining","unpersonalizedOnly","showDispatch","title","time","deliveryFrom","deliveryTo","deliveryCountry","scheduleDeadline","next","deadline","a","b","current","refresh","token","response","serverTime","unit","pluralUnit","orders","days","timer","setQuantity","minimum","maximum","numericValue","normalized","initDynamicPrice","price","output","options","selectedValues","selected","calculate","values","index","total","initial","base","currency","update","initShippingTeaser","teaser","copy","progress","progressbar","threshold","cartSubtotal","cartHasFreeShipping","formatter","reached","percentage","remaining","applyCartSummary","summary","initialSummary","getCartSummary","errorMessage","setStatus","type","validationMessage","decoder","clearFieldErrors","controls","control","target","describedBy","id","showFieldErrors","fields","focusable","group","toggleProductWishlist","change","toggleWishlist","addToCart","showCartAddError","rejected","successRedirect","initProductPurchase","trackStorefrontInteraction","item","option","fileInput","file","image","photoSwipeViewerPromise","loadPhotoSwipeViewer","initProductGallery","mainImage","gallery","stage","zoomLink","rail","thumbnails","arrows","activeIndex","thumbnail","swipe","suppressZoom","ignoreNativeZoomClick","mainVideo","mainVideoSources","mainVideoAutoplay","videoGestureSurface","videoStartTimer","pendingVideoThumbnail","swipePreview","swipeFrame","swipeFinishTimer","swipeDestination","swipeFinishing","applyingSwipeDestination","resumeVideoAfterSwipe","restoreVideoAfterSwipe","initialWarmingPending","initialWarmingGeneration","preparedImages","clamp","destroyVideo","playVideo","playback","videoElement","mutedPlayback","showVideo","video","videoMp4Fallback","readVideoSources","size","sources","preparedSources","setVideoSources","autoplay","startActiveVideo","trackMedia","clearSwipeVisuals","prepareImage","cached","warmAdjacentImages","preparedIndex","warmAfterPrimaryImage","generation","warm","mediaSrcset","media","popupSrcset","getPhotoSwipeThumbBounds","itemData","rect","imageStyle","cover","scale","renderedWidth","renderedHeight","position","percent","objectPositionX","objectPositionY","positionX","positionY","offsetX","offsetY","bounds","optionSlug","replacements","character","thumbnailScrollDistance","selectedVisible","selectedBounds","railBounds","targetBounds","nextBounds","previousBounds","startOverflow","endOverflow","thumbnailScrollGeneration","thumbnailScrollFrame","thumbnailGeometryRequest","thumbnailGeometryObserver","cancelThumbnailScroll","entry","entries","distance","observeThumbnailScroll","targets","fallbackThumbnailScrollDistance","interactionType","updateArrows","direction","unavailable","activate","scrollDistance","scroll","scrollTarget","key","insideViewer","autoplayVideo","active","moveFocus","focusWithoutScroll","renderSwipe","offset","completeSwipe","resolve","horizontal","vertical","canAdvance","nextIndex","shouldAdvance","hadPreview","duration","destination","activeThumbnail","slides","startIndex","viewerIndex","openPhotoSwipeViewer","initMediaCombinations","combinations","product","optionControl","optionId","optionName","backgroundInputs","foregroundInputs","background","foreground","previewImage","initialThumbnail","focusPurchaseTarget","initProductStickyPurchase","purchase","stickyButton","sticky","stickyLabel","stickyPrice","sourcePrice","designerButton","footer","geometryDirty","geometryReady","geometryObserver","geometryFrame","purchasePassed","footerVisible","renderFrame","busy","visible","label","scheduleRender","invalidateGeometry","observer","invalid","initProductStickyColumns","columns","area","pending","frame","column","initAgeVerification","dialog","initProductDetails","tabs","panels","tab","reducedMotion","replaceHash","hash","panel","focus","updateHash","descriptionMore","fullDescription","additionalTab","showFullDescription","hashTab","initProductReviews","body","activeRequest","returnFocus","load","link","initDownloadList","list","toggle","extraCount","compact","expanded","sync","initProductMedia","initMediaLibraries","initializers","modulePromise","moduleFailed","preloadStripeSdk","rel","href","loadProductExpress","initProductExpressOnDemand","loading","initExpressLoading","loadingLabel","controller","initialization","initialized","interacted","userActivated","nearby","start","initProductExpress","updateGeometry","hasArea","onInteraction","scheduleGeometry","initProductBusinessDetails","opener","submit","completed","close","timeout","fragment","express","initProductRecommendations","initContentComponents"],"ignoreList":[],"sources":["../../template/components/common/video-poster/video-poster.js","../../template/components/product/product-commerce-specials/product-commerce-specials.js","../../template/components/product/product-availability-actions/product-availability-actions.js","../../template/components/product/product-urgency/product-urgency.js","../../template/components/product/product-purchase/product-purchase.js","../../template/components/product/product-gallery/product-gallery.js","../../template/components/product/product-sticky-purchase/product-sticky-purchase.js","../../template/components/product/product-sticky-column/product-sticky-column.js","../../template/components/product/product-age-verification/product-age-verification.js","../../template/components/product/product-details/product-details.js","../../template/components/product/product-reviews/product-reviews.js","../../template/components/product/product-media-extras/product-media-extras.js","../../template/components/product/product-express/product-express-loader.js","../../template/components/product/product-business-details/product-business-details.js","../../src/entries/product/product.js"],"sourcesContent":["/** Choose a poster variant for native <video>, which does not support srcset. */\nexport function selectVideoPoster(fallback, srcset, width, height) {\n    if (!srcset) return fallback || '';\n\n    const candidates = srcset\n        .split(',')\n        .map((source) => {\n            const match = source.trim().match(/^(\\S+)\\s+(\\d+)w$/);\n            return match ? { url: match[1], width: Number(match[2]) } : null;\n        })\n        .filter(Boolean)\n        .sort((first, second) => first.width - second.width);\n    if (!candidates.length) return fallback || '';\n\n    const renderedSide = Math.max(Number(width) || 0, Number(height) || 0, 1);\n    const targetWidth = renderedSide * Math.max(1, window.devicePixelRatio || 1);\n    return (candidates.find((candidate) => candidate.width >= targetWidth) || candidates.at(-1))\n        .url;\n}\n","function trackDesigner(name, productId, details = {}) {\n    try {\n        window.analytics?.trackInteraction?.(name, {\n            product_ids: [Number(productId)],\n            source_context: 'product_detail',\n            editor: 'fabric',\n            ...details,\n        });\n    } catch {\n        // Product customization must never depend on analytics.\n    }\n}\n\nasync function initializeDesigner(root, form, status) {\n    const button = root.querySelector('[data-product-designer-open]');\n    const container = root.querySelector('[data-product-designer-editor]');\n    const result = root.querySelector('[data-product-designer-result]');\n    const productId = root.dataset.productId;\n    let editor = null;\n    let pendingTemplateId = new URL(window.location.href).searchParams.get('engraving_template');\n    const templateStatus = root.querySelector('[data-template-status]');\n    const manageButton = root.querySelector('[data-template-manage]');\n    const appliedStatus = (authenticated) =>\n        authenticated\n            ? 'Am Produkt übernommen. Speichern und Verwalten im Editor.'\n            : 'Am Produkt übernommen.';\n    manageButton?.addEventListener('click', () => editor?.openDrafts());\n\n    button?.addEventListener('click', async () => {\n        if (editor) {\n            editor.open();\n            return;\n        }\n        trackDesigner('product_designer_opened', productId);\n        button.disabled = true;\n        button.setAttribute('aria-busy', 'true');\n        status.textContent = 'Gravur-Editor wird geladen …';\n        status.removeAttribute('data-status-type');\n        let restoringTemplate = false;\n        try {\n            const { FabricEngravingEditor, prepareEngravingConfig } =\n                await import('../product-engraving-editor/product-engraving-editor.js');\n            const response = await fetch(\n                `/index.php?route=product/product/product_designer_options&editor=fabric&product_id=${encodeURIComponent(productId)}`,\n                { credentials: 'same-origin' },\n            );\n            const payload = await response.json();\n            if (!payload.success || !payload.data?.options?.surface)\n                throw new Error(payload.error || 'Keine Gravur-Konfiguration verfügbar.');\n            // Keep the fullscreen editor outside the sticky column's stacking context.\n            document.body.append(container);\n            editor = new FabricEngravingEditor({\n                container,\n                config: prepareEngravingConfig(payload.data.options),\n                customerDrafts: {\n                    loginUrl: root.dataset.draftsLoginUrl,\n                    onAuthenticationChange: (authenticated) => {\n                        manageButton.hidden = !authenticated;\n                        if (!result.hidden)\n                            templateStatus.textContent = appliedStatus(authenticated);\n                    },\n                },\n                onApply: (design) => {\n                    form.querySelectorAll(\n                        '[name=\"product_designer_print\"], [name=\"product_designer_full\"]',\n                    ).forEach((field) => field.remove());\n                    if (!design?.hasDesign) {\n                        editor.markTemplateApplied();\n                        result.hidden = true;\n                        form.dispatchEvent(\n                            new CustomEvent('zirbelino:personalization-changed', {\n                                bubbles: true,\n                                detail: { personalized: false },\n                            }),\n                        );\n                        const cartButton = form.querySelector('.z-product-purchase__cart');\n                        if (root.dataset.designerRequired === 'true' && cartButton) {\n                            cartButton.disabled = true;\n                        }\n                        return;\n                    }\n                    [\n                        ['product_designer_print', design.transparentPng],\n                        ['product_designer_full', design.previewPng],\n                    ].forEach(([name, value]) => {\n                        const field = document.createElement('input');\n                        field.type = 'hidden';\n                        field.name = name;\n                        field.value = value;\n                        form.append(field);\n                    });\n                    let preview = result.querySelector('img');\n                    if (!preview) {\n                        preview = document.createElement('img');\n                        preview.alt = 'Vorschau der Gravur';\n                        preview.width = 160;\n                        preview.height = 120;\n                        result.prepend(preview);\n                    }\n                    preview.src = design.previewPng;\n                    result.hidden = false;\n                    editor.markTemplateApplied();\n                    templateStatus.textContent = appliedStatus(\n                        editor.customerDrafts?.authenticated,\n                    );\n                    const cartButton = form.querySelector('.z-product-purchase__cart');\n                    if (cartButton) cartButton.disabled = false;\n                    status.textContent = 'Gravur wurde übernommen.';\n                    status.dataset.statusType = 'success';\n                    form.dispatchEvent(\n                        new CustomEvent('zirbelino:personalization-changed', {\n                            bubbles: true,\n                            detail: { personalized: true },\n                        }),\n                    );\n                    trackDesigner('product_designer_completed', productId, {\n                        layer_count: Number(design.layerCount) || 0,\n                    });\n                },\n                onAnalytics: (name, details) => trackDesigner(name, productId, details),\n            });\n            const templateId = pendingTemplateId;\n            if (templateId && /^\\d+$/.test(templateId)) {\n                // A missing/incompatible saved design must still allow a fresh design on retry.\n                pendingTemplateId = null;\n                restoringTemplate = true;\n                const templateResponse = await fetch(\n                    `/index.php?route=account/account/design&template_id=${encodeURIComponent(templateId)}&product_id=${encodeURIComponent(productId)}`,\n                    { credentials: 'same-origin' },\n                );\n                const saved = await templateResponse.json();\n                if (!templateResponse.ok || !saved.success)\n                    throw new Error(saved.error || 'Die Vorlage konnte nicht geladen werden.');\n                await editor.restoreTemplate(saved.design);\n                editor.selectTemplate(saved);\n            }\n            editor.open();\n            status.textContent = '';\n            status.removeAttribute('data-status-type');\n        } catch (error) {\n            editor?.destroy();\n            editor = null;\n            status.textContent =\n                error instanceof Error\n                    ? error.message\n                    : 'Der Gravur-Editor konnte nicht geladen werden.';\n            if (restoringTemplate)\n                status.textContent +=\n                    ' Klicken Sie auf „Gravur gestalten“, um eine neue Gravur anzulegen.';\n            status.dataset.statusType = 'error';\n            trackDesigner('product_designer_error', productId, { error_stage: 'initialization' });\n        } finally {\n            button.disabled = false;\n            button.removeAttribute('aria-busy');\n        }\n    });\n    root.querySelector('[data-product-designer-clear]')?.addEventListener('click', () => {\n        editor?.clearAll();\n        form.querySelectorAll(\n            '[name=\"product_designer_print\"], [name=\"product_designer_full\"]',\n        ).forEach((field) => field.remove());\n        result.hidden = true;\n        const cartButton = form.querySelector('.z-product-purchase__cart');\n        if (root.dataset.designerRequired === 'true' && cartButton) cartButton.disabled = true;\n        form.dispatchEvent(\n            new CustomEvent('zirbelino:personalization-changed', {\n                bubbles: true,\n                detail: { personalized: false },\n            }),\n        );\n        trackDesigner('product_designer_cleared', productId);\n    });\n    if (new URL(window.location.href).searchParams.has('engraving_template')) button?.click();\n}\n\nexport function initProductCommerceSpecials(container, form, status) {\n    const recurring = container.querySelector('[data-product-recurring]');\n    recurring?.addEventListener('change', async () => {\n        const description = container.querySelector('[data-product-recurring-description]');\n        description.textContent = '';\n        if (!recurring.value) return;\n        const response = await fetch('/index.php?route=product/product/getRecurringDescription', {\n            method: 'POST',\n            credentials: 'same-origin',\n            headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8' },\n            body: new URLSearchParams({\n                product_id: form.elements.product_id.value,\n                recurring_id: recurring.value,\n                quantity: form.elements.quantity.value,\n            }),\n        });\n        const payload = await response.json();\n        description.textContent = payload.success || '';\n    });\n    container.querySelectorAll('[data-product-designer]').forEach((root) => {\n        void initializeDesigner(root, form, status);\n    });\n}\n","function errorText(errors) {\n    if (typeof errors === 'string') return errors;\n    if (Array.isArray(errors)) return errors.map(errorText).join(' ');\n    if (errors && typeof errors === 'object') return Object.values(errors).map(errorText).join(' ');\n    return '';\n}\n\nexport function initProductAvailabilityActions(root) {\n    root.querySelectorAll('[data-product-availability-form]').forEach((form) => {\n        form.addEventListener('submit', async (event) => {\n            event.preventDefault();\n            if (!form.reportValidity()) return;\n            const button = form.querySelector('[type=\"submit\"]');\n            const status = form.querySelector('[data-product-availability-status]');\n            button.disabled = true;\n            button.setAttribute('aria-busy', 'true');\n            status.textContent = '';\n            status.removeAttribute('data-status-type');\n            try {\n                const response = await fetch(form.action, {\n                    method: 'POST',\n                    credentials: 'same-origin',\n                    body: new FormData(form),\n                    headers: { Accept: 'application/json' },\n                });\n                const payload = await response.json();\n                if (!payload.success)\n                    throw new Error(\n                        errorText(payload.errors) || 'Die Anfrage konnte nicht gesendet werden.',\n                    );\n                status.textContent =\n                    typeof payload.success === 'string'\n                        ? payload.success\n                        : 'Vielen Dank. Deine Anfrage wurde gespeichert.';\n                status.dataset.statusType = 'success';\n                form.querySelectorAll('input:not([type=\"hidden\"])').forEach((input) => {\n                    if (input.type !== 'checkbox') input.value = '';\n                });\n            } catch (error) {\n                status.textContent =\n                    error instanceof Error\n                        ? error.message\n                        : 'Die Anfrage konnte nicht gesendet werden.';\n                status.dataset.statusType = 'error';\n            } finally {\n                button.disabled = false;\n                button.removeAttribute('aria-busy');\n            }\n        });\n    });\n}\n","const minute = 60_000;\nconst deliveryDateFormatter = new Intl.DateTimeFormat('de-AT', {\n    day: 'numeric',\n    month: 'short',\n    year: 'numeric',\n    timeZone: 'UTC',\n});\nconst dispatchDateFormatter = new Intl.DateTimeFormat('de-AT', {\n    year: 'numeric',\n    month: '2-digit',\n    day: '2-digit',\n    timeZone: 'Europe/Vienna',\n});\n\nfunction formatDeliveryDate(value) {\n    if (typeof value !== 'string' || !/^\\d{4}-\\d{2}-\\d{2}$/.test(value)) return '';\n    const timestamp = Date.parse(`${value}T12:00:00Z`);\n    return Number.isFinite(timestamp) ? deliveryDateFormatter.format(new Date(timestamp)) : '';\n}\n\nfunction remainingTime(milliseconds) {\n    const minutes = Math.ceil(milliseconds / minute);\n    const hours = Math.floor(minutes / 60);\n    const rest = minutes % 60;\n    if (hours > 0) return `${hours} Std.${rest > 0 ? ` ${rest} Min.` : ''}`;\n    return `${minutes} Min.`;\n}\n\nfunction setMessage(element, message) {\n    if (!element) return;\n    const text = element.querySelector('[data-product-urgency-text]') || element;\n    if (text.textContent !== message) text.textContent = message;\n    if (element.hidden !== !message) element.hidden = !message;\n}\n\nexport function initProductUrgency(container) {\n    const url = container.dataset.productUrgencyUrl;\n    if (!url) return;\n\n    const stock = container.querySelector('[data-product-low-stock]');\n    const dispatch = container.querySelector('[data-product-dispatch-deadline]');\n    const dispatchTitle = dispatch?.querySelector('[data-product-dispatch-title]');\n    const dispatchTime = dispatch?.querySelector('[data-product-dispatch-time]');\n    const delivery = container.querySelector('[data-product-delivery-estimate]');\n    const demand = container.querySelector('[data-product-recent-orders]');\n    const region = container.querySelector('[data-product-urgency-region]');\n    const form = container.querySelector('#product-form');\n    let state = null;\n    let personalized = Boolean(container.querySelector('[name=\"product_designer_print\"]'));\n    let clockOffset = 0;\n    let deadlineTimer = null;\n    let refreshToken = 0;\n\n    const requestUrl = () => {\n        const request = new URL(url, window.location.href);\n        if (!form) return request;\n        form.querySelectorAll('input[name^=\"option[\"]:checked, select[name^=\"option[\"]').forEach(\n            (input) => {\n                if (input.value) request.searchParams.append(input.name, input.value);\n            },\n        );\n        const quantity = form.querySelector('[name=\"quantity\"]');\n        if (quantity) request.searchParams.set('quantity', quantity.value);\n        return request;\n    };\n\n    const render = () => {\n        if (!state || !container.isConnected) return;\n        const now = Date.now() + clockOffset;\n        const dispatchDeadline = Date.parse(state.dispatch_by);\n        const dispatchRemaining = dispatchDeadline - now;\n        const unpersonalizedOnly = state.dispatch_unpersonalized_only && personalized;\n        const showDispatch =\n            Number.isFinite(dispatchRemaining) && dispatchRemaining > 0 && !unpersonalizedOnly;\n        if (showDispatch && dispatchTitle) {\n            const title =\n                dispatchDateFormatter.format(new Date(dispatchDeadline)) ===\n                dispatchDateFormatter.format(new Date(now))\n                    ? 'Heute noch versendet'\n                    : 'Morgen versendet';\n            if (dispatchTitle.textContent !== title) dispatchTitle.textContent = title;\n        }\n        if (dispatchTime) {\n            const time = showDispatch\n                ? `Bestelle in den nächsten ${remainingTime(dispatchRemaining)}`\n                : '';\n            if (dispatchTime.textContent !== time) dispatchTime.textContent = time;\n        }\n        if (dispatch && dispatch.hidden !== !showDispatch) dispatch.hidden = !showDispatch;\n\n        const deliveryFrom = formatDeliveryDate(state.delivery_from);\n        const deliveryTo = formatDeliveryDate(state.delivery_to);\n        const deliveryCountry =\n            typeof state.delivery_country === 'string' ? state.delivery_country.trim() : '';\n        setMessage(\n            delivery,\n            !unpersonalizedOnly && deliveryFrom && deliveryTo && deliveryCountry\n                ? `Voraussichtliche Lieferung nach ${deliveryCountry}: ${deliveryFrom}${deliveryFrom === deliveryTo ? '' : ` bis ${deliveryTo}`}.`\n                : '',\n        );\n    };\n\n    const scheduleDeadline = () => {\n        window.clearTimeout(deadlineTimer);\n        if (!state) return;\n        const now = Date.now() + clockOffset;\n        const next = [state.dispatch_by, state.refresh_at]\n            .map((deadline) => Date.parse(deadline))\n            .filter((deadline) => Number.isFinite(deadline) && deadline > now)\n            .sort((a, b) => a - b)[0];\n        if (next === undefined) return;\n        deadlineTimer = window.setTimeout(\n            () => {\n                const current = Date.now() + clockOffset;\n                if (\n                    [state.dispatch_by, state.refresh_at].some((deadline) => {\n                        const timestamp = Date.parse(deadline);\n                        return Number.isFinite(timestamp) && timestamp <= current;\n                    })\n                ) {\n                    void refresh();\n                    return;\n                }\n                render();\n                scheduleDeadline();\n            },\n            Math.min(next - now + 25, 2_147_483_647),\n        );\n    };\n\n    const refresh = async () => {\n        if (!container.isConnected) return;\n        const token = ++refreshToken;\n        region?.setAttribute('aria-busy', 'true');\n        try {\n            const response = await fetch(requestUrl(), {\n                credentials: 'same-origin',\n                cache: 'no-store',\n            });\n            if (!response.ok) throw new Error(`Urgency request failed: ${response.status}`);\n            const next = await response.json();\n            if (!container.isConnected || token !== refreshToken) return;\n            state = next;\n            const serverTime = Date.parse(next.server_now);\n            clockOffset = Number.isFinite(serverTime) ? serverTime - Date.now() : 0;\n            const quantity = Number(next.low_stock);\n            const unit = container.dataset.productStockUnit || 'Stück';\n            const pluralUnit = container.dataset.productStockUnitPlural || unit;\n            setMessage(\n                stock,\n                Number.isInteger(quantity) && quantity > 0\n                    ? `Nur noch ${quantity} ${quantity === 1 ? unit : pluralUnit} auf Lager.`\n                    : '',\n            );\n            const orders = Number(next.orders_last_days);\n            const days = Number(next.orders_period_days);\n            setMessage(\n                demand,\n                Number.isInteger(orders) && orders > 0 && Number.isInteger(days) && days > 0\n                    ? `${orders} Mal in letzter Zeit bestellt`\n                    : '',\n            );\n            render();\n            scheduleDeadline();\n        } catch {\n            if (token !== refreshToken) return;\n            state = null;\n            window.clearTimeout(deadlineTimer);\n            setMessage(stock, '');\n            if (dispatch) dispatch.hidden = true;\n            if (dispatchTime) dispatchTime.textContent = '';\n            setMessage(delivery, '');\n            setMessage(demand, '');\n        } finally {\n            if (token === refreshToken) region?.setAttribute('aria-busy', 'false');\n        }\n    };\n\n    void refresh();\n    container.addEventListener('zirbelino:personalization-changed', (event) => {\n        personalized = event.detail?.personalized === true;\n        render();\n    });\n    form?.addEventListener('change', (event) => {\n        if (event.target?.matches('[name^=\"option[\"], [name=\"quantity\"]')) void refresh();\n    });\n    const timer = window.setInterval(() => {\n        if (!container.isConnected) {\n            window.clearInterval(timer);\n            return;\n        }\n        render();\n    }, minute);\n    document.addEventListener('visibilitychange', () => {\n        if (!document.hidden && container.isConnected) void refresh();\n    });\n    window.addEventListener('pageshow', (event) => {\n        if (event.persisted && container.isConnected) void refresh();\n    });\n}\n","import { initProductCommerceSpecials } from '../product-commerce-specials/product-commerce-specials.js';\nimport { initProductAvailabilityActions } from '../product-availability-actions/product-availability-actions.js';\nimport { trackStorefrontInteraction } from '../../common/storefront-tracking/storefront-tracking.js';\nimport { getCartSummary } from '../../common/cart-state/cart-state.js';\nimport { initProductUrgency } from '../product-urgency/product-urgency.js';\nimport { toggleWishlist } from '../../common/wishlist/wishlist.js';\nimport { showCartAddError } from '../../common/cart-add-error/cart-add-error-loader.js';\n\nfunction setQuantity(container, value) {\n    const input = container.querySelector('[data-product-quantity-input]');\n\n    if (!input) return;\n\n    const minimum = Number(input.min) || 1;\n    const maximum = Number(input.max) || Number.POSITIVE_INFINITY;\n    input.value = String(Math.min(maximum, Math.max(minimum, Number(value) || minimum)));\n    input.dispatchEvent(new Event('change', { bubbles: true }));\n}\n\nfunction numericValue(value) {\n    const normalized = String(value || '')\n        .replace(/[^\\d,.-]/g, '')\n        .replace(',', '.');\n    return Number.parseFloat(normalized);\n}\n\nfunction initDynamicPrice(container) {\n    const price = container.querySelector('[data-product-dynamic-price]');\n    if (!price) return;\n    const output = price.querySelector('[data-product-price-value]');\n    const options = [\n        ...container.querySelectorAll(\n            'input[data-dynamic-value], [data-dynamic-value-input], [data-dynamic-value-select]',\n        ),\n    ];\n    const selectedValues = () =>\n        options\n            .filter((input) =>\n                input.matches('[type=\"radio\"]') ? input.checked : Boolean(input.value),\n            )\n            .map((input) => {\n                const selected = input.matches('select') ? input.selectedOptions[0] : input;\n                return numericValue(selected?.dataset.dynamicValue || selected?.value);\n            })\n            .filter((value) => Number.isFinite(value) && value > 0);\n    const calculate = (values) =>\n        values.reduce(\n            (total, value, index) =>\n                price.dataset.dynamicMultiply === 'true' && index > 0\n                    ? total * value\n                    : total + value,\n            0,\n        );\n    const initial = calculate(selectedValues());\n    const base = Number(price.dataset.basePrice);\n    const currency = price.dataset.priceCurrency || 'EUR';\n    const update = () => {\n        const current = calculate(selectedValues());\n        output.textContent =\n            initial > 0 && current > 0 && base > 0\n                ? new Intl.NumberFormat('de-AT', { style: 'currency', currency }).format(\n                      (base / initial) * current,\n                  )\n                : 'Preis nach Auswahl';\n    };\n    options.forEach((input) => input.addEventListener('change', update));\n    options.forEach((input) => input.addEventListener('input', update));\n    update();\n}\n\nfunction initShippingTeaser(container) {\n    const teaser = container.querySelector('[data-product-shipping]');\n    const copy = teaser?.querySelector('[data-product-shipping-copy]');\n    const progress = teaser?.querySelector('[data-product-shipping-progress]');\n    const progressbar = progress?.parentElement;\n    if (!teaser || !copy || !progress || !progressbar) return;\n\n    const threshold = Number(teaser.dataset.shippingThreshold) || 0;\n    let cartSubtotal = Number(teaser.dataset.shippingCartSubtotal) || 0;\n    let cartHasFreeShipping = teaser.dataset.shippingCartFree === 'true';\n    const currency = teaser.dataset.shippingCurrency || 'EUR';\n    const formatter = new Intl.NumberFormat('de-AT', {\n        style: 'currency',\n        currency,\n        minimumFractionDigits: 2,\n    });\n\n    const update = () => {\n        const reached = cartHasFreeShipping || threshold <= 0 || cartSubtotal >= threshold;\n        const percentage = reached\n            ? 100\n            : Math.max(0, Math.min(100, (100 * cartSubtotal) / threshold));\n\n        copy.replaceChildren();\n        if (reached) {\n            const message = document.createElement('strong');\n            message.textContent = 'Deine Bestellung ist versandkostenfrei.';\n            copy.append(message);\n        } else {\n            const remaining = document.createElement('strong');\n            remaining.textContent = formatter.format(Math.max(0, threshold - cartSubtotal));\n            copy.append('Noch ', remaining, ' bis zum kostenlosen Versand.');\n        }\n\n        progress.style.width = `${percentage}%`;\n        progressbar.setAttribute('aria-valuenow', String(Math.round(percentage)));\n    };\n\n    const applyCartSummary = (summary) => {\n        if (!summary) return;\n        cartSubtotal = summary.subtotalWithoutGiftCards;\n        cartHasFreeShipping = summary.freeShipping;\n        teaser.dataset.shippingCartSubtotal = String(cartSubtotal);\n        teaser.dataset.shippingCartFree = String(cartHasFreeShipping);\n        teaser.removeAttribute('data-cart-summary-pending');\n        update();\n    };\n\n    document.addEventListener('zirbelino:cart-state', (event) => applyCartSummary(event.detail));\n    const initialSummary = getCartSummary();\n    if (initialSummary) applyCartSummary(initialSummary);\n    else if (!teaser.hasAttribute('data-cart-summary-pending')) update();\n}\n\nfunction errorMessage(error) {\n    if (typeof error === 'string') return error;\n    if (Array.isArray(error)) return error.map(errorMessage).filter(Boolean).join(' ');\n    if (error && typeof error === 'object') {\n        return Object.values(error).map(errorMessage).filter(Boolean).join(' ');\n    }\n\n    return '';\n}\n\nfunction setStatus(status, message = '', type = 'success') {\n    if (!status) return;\n    status.textContent = message;\n    if (message) status.dataset.statusType = type;\n    else status.removeAttribute('data-status-type');\n}\n\nfunction validationMessage(error) {\n    const decoder = document.createElement('textarea');\n    decoder.innerHTML = errorMessage(error).replace(/<[^>]*>/g, '');\n    const message = decoder.value.trim();\n    if (\n        !message ||\n        message.length > 500 ||\n        /SQLSTATE|stack trace|fatal error|uncaught|\\.php:\\d|failed to fetch|unexpected token/i.test(\n            message,\n        )\n    ) {\n        return 'Bitte prüfe deine Auswahl und versuche es erneut.';\n    }\n    return message;\n}\n\nfunction clearFieldErrors(form, target) {\n    form.querySelectorAll('[data-product-field-error]').forEach((message) => {\n        const controls = [...form.elements].filter(\n            (control) => control.dataset.productErrorId === message.id,\n        );\n        if (target && !controls.includes(target)) return;\n        controls.forEach((control) => {\n            const describedBy = (control.getAttribute('aria-describedby') || '')\n                .split(/\\s+/)\n                .filter((id) => id && id !== message.id);\n            if (describedBy.length) control.setAttribute('aria-describedby', describedBy.join(' '));\n            else control.removeAttribute('aria-describedby');\n            if (!control.validity.valid) control.setAttribute('aria-invalid', 'true');\n            else if (\n                control.dataset.productPreviousInvalid &&\n                control.dataset.productPreviousInvalid !== 'true'\n            )\n                control.setAttribute('aria-invalid', control.dataset.productPreviousInvalid);\n            else control.removeAttribute('aria-invalid');\n            delete control.dataset.productErrorId;\n            delete control.dataset.productPreviousInvalid;\n        });\n        message.remove();\n    });\n}\n\nfunction showFieldErrors(form, errors) {\n    if (!errors || typeof errors !== 'object') return null;\n    const fields = [];\n    if (errors.option && typeof errors.option === 'object') {\n        Object.entries(errors.option).forEach(([id, error]) => {\n            if (/^\\d+$/.test(id))\n                fields.push({\n                    names: [`option[${id}]`, `option[${id}][]`],\n                    id: `option-${id}`,\n                    error,\n                });\n        });\n    }\n    if (errors.recurring)\n        fields.push({ names: ['recurring_id'], id: 'recurring', error: errors.recurring });\n    if (errors.quantity)\n        fields.push({ names: ['quantity'], id: 'quantity', error: errors.quantity });\n    let first = null;\n    fields.forEach((field) => {\n        const controls = [...form.elements].filter((control) => field.names.includes(control.name));\n        const focusable = controls.find(\n            (control) => !control.disabled && control.type !== 'hidden',\n        );\n        if (!focusable) return;\n        const message = document.createElement('p');\n        message.id = `z-product-error-${field.id}`;\n        message.className = 'z-product-purchase__field-error';\n        message.dataset.productFieldError = '';\n        message.textContent = validationMessage(field.error);\n        const group = focusable.closest('.z-product-option');\n        if (group) group.append(message);\n        else focusable.insertAdjacentElement('afterend', message);\n        controls.forEach((control) => {\n            control.dataset.productPreviousInvalid = control.getAttribute('aria-invalid') || '';\n            control.dataset.productErrorId = message.id;\n            control.setAttribute('aria-invalid', 'true');\n            control.setAttribute(\n                'aria-describedby',\n                [control.getAttribute('aria-describedby'), message.id].filter(Boolean).join(' '),\n            );\n        });\n        if (!first) first = focusable;\n    });\n    return first;\n}\n\nexport async function toggleProductWishlist(productId, button, status) {\n    if (!productId || button.disabled) return;\n    setStatus(status);\n\n    try {\n        const change = await toggleWishlist(button);\n        if (change)\n            setStatus(\n                status,\n                change.saved\n                    ? 'Das Produkt wurde auf Ihre Wunschliste gesetzt.'\n                    : 'Das Produkt wurde von Ihrer Wunschliste entfernt.',\n            );\n    } catch (error) {\n        setStatus(\n            status,\n            error instanceof Error ? error.message : 'Die Wunschliste ist gerade nicht verfügbar.',\n            'error',\n        );\n    }\n}\n\nasync function addToCart(form, button, status, successRedirect = '') {\n    button.disabled = true;\n    button.setAttribute('aria-busy', 'true');\n    setStatus(status);\n    clearFieldErrors(form);\n\n    try {\n        const response = await fetch(form.action, {\n            method: 'POST',\n            body: new FormData(form),\n            headers: { Accept: 'application/json' },\n        });\n        if (!response.ok) {\n            await showCartAddError({ form, uncertain: true, statusCode: response.status }, button);\n            return;\n        }\n\n        const result = await response.json();\n        if (!result || typeof result !== 'object' || Array.isArray(result)) {\n            throw new Error('Invalid cart response');\n        }\n        if (!result.success || result.error) {\n            const first = showFieldErrors(form, result.error);\n            const rejected = result.success === false || Boolean(result.error);\n            await showCartAddError(\n                { result, form, firstInvalid: first, uncertain: !rejected },\n                button,\n            );\n            return;\n        }\n        if (result.redirect) {\n            window.location.assign(result.redirect);\n            return;\n        }\n        result.zirbelino_source_context = 'product_detail';\n        if (successRedirect) {\n            window.location.assign(successRedirect);\n            return;\n        }\n        setStatus(status, 'Das Produkt wurde in den Warenkorb gelegt.');\n        document.dispatchEvent(new CustomEvent('zirbelino:cart:add', { detail: result }));\n    } catch {\n        await showCartAddError({ form, uncertain: true }, button);\n    } finally {\n        button.disabled = false;\n        button.removeAttribute('aria-busy');\n    }\n}\n\nexport function initProductPurchase(container) {\n    initProductUrgency(container);\n    const form = container.querySelector('#product-form');\n    const input = container.querySelector('[data-product-quantity-input]');\n\n    if (!form) return;\n\n    const status = container.querySelector('.z-product-purchase__errors');\n    form.addEventListener('input', (event) => clearFieldErrors(form, event.target));\n    form.addEventListener('change', (event) => clearFieldErrors(form, event.target));\n    initProductCommerceSpecials(container, form, status);\n    initProductAvailabilityActions(container);\n    initDynamicPrice(container);\n    initShippingTeaser(container);\n\n    if (input) {\n        input.addEventListener('change', () => {\n            const productId = Number(form.elements.product_id?.value) || 0;\n            trackStorefrontInteraction('product_quantity_changed', {\n                ...(productId > 0 ? { product_ids: [productId] } : {}),\n                source_context: 'product_detail',\n                quantity: Number(input.value) || 0,\n            });\n        });\n\n        container.querySelectorAll('[data-product-quantity]').forEach((button) => {\n            button.addEventListener('click', () => {\n                setQuantity(\n                    container,\n                    Number(input.value) + Number(button.dataset.productQuantity),\n                );\n            });\n        });\n\n        container.querySelectorAll('[data-product-set-size]').forEach((button) => {\n            button.addEventListener('click', () => {\n                container.querySelectorAll('[data-product-set-size]').forEach((item) => {\n                    const selected = item === button;\n                    item.classList.toggle('z-product-option__choice--selected', selected);\n                    item.setAttribute('aria-pressed', String(selected));\n                });\n                setQuantity(container, button.dataset.productSetSize);\n            });\n        });\n    }\n\n    container.querySelectorAll('.z-product-option input').forEach((option) => {\n        option.addEventListener('change', () => {\n            const choice = option.closest('.z-product-option__choice');\n            choice\n                ?.closest('.z-product-option')\n                ?.querySelectorAll('.z-product-option__choice')\n                .forEach((item) => {\n                    item.classList.toggle(\n                        'z-product-option__choice--selected',\n                        Boolean(item.querySelector('input')?.checked),\n                    );\n                });\n        });\n    });\n\n    container.querySelectorAll('[data-product-option-file]').forEach((fileInput) => {\n        fileInput.addEventListener('change', () => {\n            const preview = fileInput.parentElement?.querySelector(\n                '[data-product-option-file-preview]',\n            );\n            if (!preview) return;\n            preview.replaceChildren();\n            const file = fileInput.files?.[0];\n            if (!file) return;\n            const name = document.createElement('span');\n            name.textContent = `Datei: ${file.name}`;\n            preview.append(name);\n            if (!file.type.startsWith('image/') || file.type === 'image/eps') return;\n            const image = document.createElement('img');\n            const source = URL.createObjectURL(file);\n            image.src = source;\n            image.alt = 'Vorschau der ausgewählten Datei';\n            image.addEventListener('load', () => URL.revokeObjectURL(source), { once: true });\n            preview.append(image);\n        });\n    });\n\n    const cartButton = container.querySelector('.z-product-purchase__cart');\n    container.querySelector('[data-product-wishlist]')?.addEventListener('click', (event) => {\n        void toggleProductWishlist(\n            Number(event.currentTarget.dataset.productWishlist),\n            event.currentTarget,\n            status,\n        );\n    });\n    form.addEventListener('submit', (event) => {\n        event.preventDefault();\n        if (!form.reportValidity()) return;\n        if (!status || !cartButton || cartButton.disabled) return;\n        void addToCart(form, cartButton, status);\n    });\n}\n","import { focusWithoutScroll } from '../../common/focus-without-scroll/focus-without-scroll.js';\nimport { trackStorefrontInteraction } from '../../common/storefront-tracking/storefront-tracking.js';\nimport { selectVideoPoster } from '../../common/video-poster/video-poster.js';\nimport {\n    readVideoSources,\n    setVideoSources,\n    videoMp4Fallback,\n} from '../../common/video-sources/video-sources.js';\nimport { toggleProductWishlist } from '../product-purchase/product-purchase.js';\n\nlet photoSwipeViewerPromise = null;\n\nfunction loadPhotoSwipeViewer() {\n    if (!photoSwipeViewerPromise) {\n        photoSwipeViewerPromise =\n            import('../../common/photoswipe-viewer/photoswipe-viewer.js').catch((error) => {\n                photoSwipeViewerPromise = null;\n                throw error;\n            });\n    }\n    return photoSwipeViewerPromise;\n}\n\nexport function initProductGallery(gallery) {\n    const mainImage = gallery.querySelector('[data-product-gallery-main]');\n    const stage = gallery.querySelector('.z-product-gallery__stage');\n    const zoomLink = gallery.querySelector('[data-product-gallery-zoom]');\n    const rail = gallery.querySelector('[data-product-gallery-rail]');\n    const thumbnails = [...gallery.querySelectorAll('[data-product-gallery-thumb]')];\n    const arrows = [...gallery.querySelectorAll('[data-product-gallery-scroll]')];\n\n    if (!mainImage || !zoomLink || !stage) return;\n\n    let activeIndex = Math.max(\n        0,\n        thumbnails.findIndex((thumbnail) => thumbnail.getAttribute('aria-pressed') === 'true'),\n    );\n    let swipe = null;\n    let suppressZoom = false;\n    let ignoreNativeZoomClick = false;\n    let mainVideo = null;\n    let mainVideoSources = {};\n    let mainVideoAutoplay = false;\n    let videoGestureSurface = null;\n    let videoStartTimer = 0;\n    let pendingVideoThumbnail = null;\n    let swipePreview = null;\n    let swipeFrame = 0;\n    let swipeFinishTimer = 0;\n    let swipeDestination = null;\n    let swipeFinishing = false;\n    let applyingSwipeDestination = false;\n    let resumeVideoAfterSwipe = false;\n    let restoreVideoAfterSwipe = false;\n    let initialWarmingPending = true;\n    let initialWarmingGeneration = 0;\n    const preparedImages = new Map();\n\n    const clamp = (value, minimum, maximum) => Math.min(maximum, Math.max(minimum, value));\n\n    function destroyVideo() {\n        if (!mainVideo) return;\n        mainVideo.pause();\n        mainVideo.removeAttribute('src');\n        mainVideo.replaceChildren();\n        try {\n            mainVideo.load();\n        } catch (error) {\n            // Firefox can synchronously report the cancelled media fetch when\n            // the visitor switches thumbnails while playback is starting.\n            if (error.name !== 'AbortError') throw error;\n        }\n        mainVideo.remove();\n        videoGestureSurface?.remove();\n        mainVideo = null;\n        mainVideoSources = {};\n        videoGestureSurface = null;\n    }\n\n    function playVideo(videoElement) {\n        const playback = videoElement.play();\n        if (playback?.catch) {\n            playback.catch(() => {\n                if (mainVideo !== videoElement) return;\n                videoElement.muted = true;\n                const mutedPlayback = videoElement.play();\n                if (mutedPlayback?.catch) mutedPlayback.catch(() => {});\n            });\n        }\n    }\n\n    function showVideo(thumbnail, index, autoplay, size) {\n        if (!mainVideo) {\n            mainVideo = document.createElement('video');\n            mainVideo.className = 'z-product-gallery__main-video';\n            mainVideo.controls = true;\n            mainVideo.playsInline = true;\n            mainVideo.preload = 'none';\n            mainVideo.dataset.productGalleryVideo = '';\n            const video = mainVideo;\n            mainVideo.addEventListener('error', () => {\n                if (mainVideo !== video) return;\n                const fallback = videoMp4Fallback(video.currentSrc, readVideoSources(video));\n                if (!fallback || !gallery.isConnected) return;\n                mainVideo.src = fallback;\n                mainVideo.load();\n                if (mainVideoAutoplay || video.dataset.videoStarted === 'true')\n                    playVideo(mainVideo);\n            });\n            mainVideo.addEventListener('play', () => {\n                video.dataset.videoStarted = 'true';\n            });\n            stage.append(mainVideo);\n\n            videoGestureSurface = document.createElement('div');\n            videoGestureSurface.className = 'z-product-gallery__video-gesture';\n            videoGestureSurface.setAttribute('aria-hidden', 'true');\n            videoGestureSurface.addEventListener('click', () => {\n                if (!mainVideo || suppressZoom) return;\n                if (mainVideo.paused) {\n                    playVideo(mainVideo);\n                } else mainVideo.pause();\n            });\n            stage.append(videoGestureSurface);\n        }\n        mainVideo.poster = selectVideoPoster(\n            thumbnail.dataset.videoPoster || thumbnail.dataset.image,\n            thumbnail.dataset.videoPosterSrcset,\n            size.width,\n            size.height,\n        );\n        const sources = {\n            mp4: thumbnail.dataset.video,\n            webm: thumbnail.dataset.videoWebm || '',\n            mp4_type: thumbnail.dataset.videoType || 'video/mp4',\n        };\n        if (mainVideoSources.mp4 !== sources.mp4 || mainVideoSources.webm !== sources.webm) {\n            mainVideoSources = sources;\n            delete mainVideo.dataset.videoStarted;\n            const preparedSources = thumbnail.querySelector('template[data-product-video-sources]');\n            if (preparedSources) {\n                mainVideo.removeAttribute('src');\n                mainVideo.replaceChildren(preparedSources.content.cloneNode(true));\n            } else setVideoSources(mainVideo, sources);\n            // Explicit load() can fetch bytes even with preload=\"none\". An\n            // initially paused player lets native controls begin loading later.\n            if (autoplay) mainVideo.load();\n        }\n        mainVideoAutoplay = autoplay;\n        mainVideo.dataset.videoPosition = String(index + 1);\n        if (autoplay) playVideo(mainVideo);\n    }\n\n    function startActiveVideo(thumbnail, index, autoplay = true) {\n        if (pendingVideoThumbnail !== thumbnail || activeIndex !== index) return;\n        window.clearTimeout(videoStartTimer);\n        videoStartTimer = 0;\n        pendingVideoThumbnail = null;\n        const size = { width: stage.clientWidth, height: stage.clientHeight };\n        zoomLink.hidden = true;\n        showVideo(thumbnail, index, autoplay, size);\n        if (autoplay) trackMedia('product_video_opened', thumbnail, 'open');\n    }\n\n    function clearSwipeVisuals() {\n        window.cancelAnimationFrame(swipeFrame);\n        window.clearTimeout(swipeFinishTimer);\n        swipeFrame = 0;\n        swipeFinishTimer = 0;\n        swipeDestination = null;\n        swipeFinishing = false;\n        mainImage.style.transform = '';\n        if (mainVideo) mainVideo.style.transform = '';\n        swipePreview?.remove();\n        swipePreview = null;\n        stage.classList.remove('z-product-gallery__stage--settling');\n        stage.style.removeProperty('--z-product-gallery-settle-duration');\n        if (restoreVideoAfterSwipe && mainVideo) {\n            zoomLink.hidden = true;\n            mainVideo.hidden = false;\n            if (resumeVideoAfterSwipe) playVideo(mainVideo);\n        }\n        resumeVideoAfterSwipe = false;\n        restoreVideoAfterSwipe = false;\n    }\n\n    function prepareImage(index) {\n        const thumbnail = thumbnails[index];\n        if (!thumbnail?.dataset.image) return null;\n        const source = thumbnail.dataset.image;\n        const srcset = thumbnail.dataset.srcset || '';\n        const cached = preparedImages.get(index);\n        if (cached?.source === source && cached.srcset === srcset) return cached.image;\n\n        const image = new Image();\n        image.className = 'z-product-gallery__swipe-preview';\n        image.alt = '';\n        image.decoding = 'async';\n        image.setAttribute('fetchpriority', 'low');\n        image.sizes = mainImage.sizes;\n        if (srcset) image.srcset = srcset;\n        image.src = source;\n        image.style.objectFit = thumbnail.dataset.objectFit === 'cover' ? 'cover' : 'contain';\n        image.style.objectPosition = `${thumbnail.dataset.objectPositionX || 50}% ${thumbnail.dataset.objectPositionY || 50}%`;\n        if (image.decode) void image.decode().catch(() => {});\n        preparedImages.set(index, { image, source, srcset });\n        return image;\n    }\n\n    function warmAdjacentImages(index) {\n        prepareImage(index - 1);\n        prepareImage(index + 1);\n        preparedImages.forEach((_, preparedIndex) => {\n            if (Math.abs(preparedIndex - index) > 1) preparedImages.delete(preparedIndex);\n        });\n    }\n\n    function warmAfterPrimaryImage() {\n        if (!initialWarmingPending || !mainImage.complete || !mainImage.naturalWidth) return;\n        const generation = ++initialWarmingGeneration;\n        const index = activeIndex;\n        const warm = () => {\n            if (\n                !gallery.isConnected ||\n                generation !== initialWarmingGeneration ||\n                index !== activeIndex\n            )\n                return;\n            if (!mainImage.complete || !mainImage.naturalWidth) return;\n            initialWarmingPending = false;\n            mainImage.removeEventListener('load', warmAfterPrimaryImage);\n            warmAdjacentImages(index);\n        };\n        // Decode the visible image before spending bandwidth/CPU on neighbors.\n        if (mainImage.decode)\n            void mainImage\n                .decode()\n                .catch(() => {})\n                .then(warm);\n        else warm();\n    }\n\n    mainImage.addEventListener('load', warmAfterPrimaryImage);\n\n    function mediaSrcset(media) {\n        return [\n            [media.image, 300],\n            [media.image_375, 375],\n            [media.retina_image, 600],\n            [media.image_617, 617],\n            [media.retina_image_375, 750],\n            [media.retina_image_617, 1234],\n        ]\n            .filter(([source]) => Boolean(source))\n            .map(([source, width]) => `${source} ${width}w`)\n            .join(', ');\n    }\n\n    function popupSrcset(media) {\n        return [\n            [media.popup, media.popup_size?.width],\n            [media.retina_popup, media.retina_popup_size?.width],\n        ]\n            .filter(([source, width]) => Boolean(source) && Number(width) > 0)\n            .map(([source, width]) => `${source} ${Number(width)}w`)\n            .join(', ');\n    }\n\n    function getPhotoSwipeThumbBounds(itemData) {\n        if (itemData.type === 'video') return null;\n        // PhotoSwipe's default bounds use the full <img> box and center a crop.\n        // The stage can letterbox the image or crop it at a custom position.\n        const rect = mainImage.getBoundingClientRect();\n        const width = Number(itemData.width);\n        const height = Number(itemData.height);\n        if (!rect.width || !rect.height || !width || !height) return null;\n\n        const imageStyle = getComputedStyle(mainImage);\n        const cover = imageStyle.objectFit === 'cover';\n        const scale = cover\n            ? Math.max(rect.width / width, rect.height / height)\n            : Math.min(rect.width / width, rect.height / height);\n        const renderedWidth = width * scale;\n        const renderedHeight = height * scale;\n        const position = (value) => {\n            const percent = Number.parseFloat(value);\n            return Number.isFinite(percent) ? clamp(percent, 0, 100) / 100 : 0.5;\n        };\n        const [objectPositionX, objectPositionY] = imageStyle.objectPosition.split(' ');\n        const positionX = cover ? position(objectPositionX) : 0.5;\n        const positionY = cover ? position(objectPositionY) : 0.5;\n        const offsetX = (rect.width - renderedWidth) * positionX;\n        const offsetY = (rect.height - renderedHeight) * positionY;\n        const bounds = {\n            x: rect.left + offsetX,\n            y: rect.top + offsetY,\n            w: renderedWidth,\n        };\n\n        if (cover) {\n            bounds.innerRect = {\n                x: offsetX,\n                y: offsetY,\n                w: rect.width,\n                h: rect.height,\n            };\n        }\n        return bounds;\n    }\n\n    function optionSlug(value) {\n        const replacements = {\n            ä: 'ae',\n            ö: 'oe',\n            ü: 'ue',\n            ß: 'ss',\n            Ä: 'Ae',\n            Ö: 'Oe',\n            Ü: 'Ue',\n        };\n\n        return String(value || '')\n            .replace(/[äöüßÄÖÜ]/g, (character) => replacements[character])\n            .normalize('NFD')\n            .replace(/[\\u0300-\\u036f]/g, '')\n            .toLowerCase()\n            .replace(/[^a-z0-9]+/g, '-')\n            .replace(/^-+|-+$/g, '');\n    }\n\n    function thumbnailScrollDistance(railBounds, selectedBounds, nextBounds, previousBounds) {\n        const selectedVisible =\n            selectedBounds.left >= railBounds.left - 1 &&\n            selectedBounds.right <= railBounds.right + 1;\n        let targetBounds = selectedBounds;\n        if (selectedVisible) {\n            if (nextBounds && nextBounds.right > railBounds.right + 1) {\n                targetBounds = nextBounds;\n            } else {\n                if (previousBounds && previousBounds.left < railBounds.left - 1)\n                    targetBounds = previousBounds;\n            }\n        }\n        const startOverflow = targetBounds.left - railBounds.left;\n        const endOverflow = targetBounds.right - railBounds.right;\n        if (startOverflow < 0) return startOverflow;\n        return endOverflow > 0 ? endOverflow : 0;\n    }\n\n    let thumbnailScrollGeneration = 0;\n    let thumbnailScrollFrame = 0;\n    let thumbnailGeometryRequest = null;\n    const thumbnailGeometryObserver =\n        rail && typeof IntersectionObserver !== 'undefined'\n            ? new IntersectionObserver(\n                  (entries) => {\n                      const request = thumbnailGeometryRequest;\n                      if (!request) return;\n                      if (!gallery.isConnected) {\n                          cancelThumbnailScroll();\n                          return;\n                      }\n                      for (const entry of entries) {\n                          if (!request.bounds.has(entry.target)) continue;\n                          if ((request.times.get(entry.target) ?? -Infinity) > entry.time) continue;\n                          if (!entry.rootBounds) {\n                              cancelThumbnailScroll();\n                              return;\n                          }\n                          request.bounds.set(entry.target, entry.boundingClientRect);\n                          request.times.set(entry.target, entry.time);\n                          if (entry.time >= request.railTime) {\n                              request.railBounds = entry.rootBounds;\n                              request.railTime = entry.time;\n                          }\n                      }\n                      if (\n                          !request.railBounds ||\n                          [...request.bounds.values()].some((bounds) => !bounds)\n                      )\n                          return;\n                      const distance = thumbnailScrollDistance(\n                          request.railBounds,\n                          request.bounds.get(request.thumbnail),\n                          request.bounds.get(thumbnails[request.index + 1]),\n                          request.bounds.get(thumbnails[request.index - 1]),\n                      );\n                      request.bounds.forEach((_, target) =>\n                          thumbnailGeometryObserver.unobserve(target),\n                      );\n                      thumbnailGeometryObserver.takeRecords();\n                      thumbnailGeometryRequest = null;\n                      if (!distance) return;\n                      thumbnailScrollFrame = window.requestAnimationFrame(() => {\n                          thumbnailScrollFrame = 0;\n                          if (\n                              request.generation !== thumbnailScrollGeneration ||\n                              activeIndex !== request.index ||\n                              !gallery.isConnected\n                          )\n                              return;\n                          rail.scrollBy({ left: distance, behavior: 'smooth' });\n                      });\n                  },\n                  { root: rail },\n              )\n            : null;\n\n    function cancelThumbnailScroll() {\n        thumbnailScrollGeneration += 1;\n        window.cancelAnimationFrame(thumbnailScrollFrame);\n        thumbnailScrollFrame = 0;\n        thumbnailGeometryRequest?.bounds.forEach((_, target) =>\n            thumbnailGeometryObserver.unobserve(target),\n        );\n        thumbnailGeometryObserver?.takeRecords();\n        thumbnailGeometryRequest = null;\n    }\n\n    function observeThumbnailScroll(thumbnail) {\n        const index = thumbnails.indexOf(thumbnail);\n        const targets = [thumbnail, thumbnails[index + 1], thumbnails[index - 1]].filter(Boolean);\n        thumbnailGeometryRequest = {\n            thumbnail,\n            index,\n            generation: thumbnailScrollGeneration,\n            bounds: new Map(targets.map((target) => [target, null])),\n            times: new Map(),\n            railBounds: null,\n            railTime: -Infinity,\n        };\n        targets.forEach((target) => thumbnailGeometryObserver.observe(target));\n    }\n\n    function fallbackThumbnailScrollDistance(thumbnail) {\n        if (!rail) return 0;\n        const index = thumbnails.indexOf(thumbnail);\n        return thumbnailScrollDistance(\n            rail.getBoundingClientRect(),\n            thumbnail.getBoundingClientRect(),\n            thumbnails[index + 1]?.getBoundingClientRect(),\n            thumbnails[index - 1]?.getBoundingClientRect(),\n        );\n    }\n\n    function trackMedia(name, thumbnail, interactionType) {\n        const productId = Number(gallery.closest('[data-product-id]')?.dataset.productId) || 0;\n        const position = thumbnail ? thumbnails.indexOf(thumbnail) + 1 : 1;\n        trackStorefrontInteraction(name, {\n            ...(productId > 0 ? { product_ids: [productId] } : {}),\n            source_context: 'product_detail',\n            interaction_type: interactionType,\n            media_type: thumbnail?.dataset.video ? 'video' : 'image',\n            media_position: position,\n        });\n    }\n\n    function updateArrows() {\n        arrows.forEach((button) => {\n            const direction = Number(button.dataset.productGalleryScroll);\n            const unavailable =\n                !thumbnails.length ||\n                (direction < 0 && activeIndex === 0) ||\n                (direction > 0 && activeIndex === thumbnails.length - 1);\n            button.disabled = unavailable;\n            button.hidden = unavailable;\n        });\n    }\n\n    function activate(\n        thumbnail,\n        {\n            moveFocus = false,\n            interactionType = null,\n            insideViewer = false,\n            autoplayVideo = true,\n            scroll = true,\n        } = {},\n    ) {\n        const index = thumbnails.indexOf(thumbnail);\n        if (index < 0) return;\n        cancelThumbnailScroll();\n        const scrollDistance =\n            scroll && !thumbnailGeometryObserver ? fallbackThumbnailScrollDistance(thumbnail) : 0;\n        const scrollTarget = scrollDistance ? rail.scrollLeft + scrollDistance : 0;\n        if ((swipeFinishTimer || swipeFinishing) && !applyingSwipeDestination) clearSwipeVisuals();\n        window.clearTimeout(videoStartTimer);\n        videoStartTimer = 0;\n        pendingVideoThumbnail = null;\n        destroyVideo();\n        activeIndex = index;\n        const image = thumbnail.dataset.image;\n        const video = thumbnail.dataset.video;\n\n        zoomLink.hidden = false;\n        if (thumbnail.dataset.srcset) mainImage.srcset = thumbnail.dataset.srcset;\n        else mainImage.removeAttribute('srcset');\n        if (image) mainImage.src = image;\n        if (thumbnail.dataset.alt) mainImage.alt = thumbnail.dataset.alt;\n        if (thumbnail.dataset.popup) zoomLink.href = thumbnail.dataset.popup;\n        ['popupRetina', 'popupSrcset', 'popupWidth', 'popupHeight'].forEach((key) => {\n            if (thumbnail.dataset[key]) zoomLink.dataset[key] = thumbnail.dataset[key];\n            else delete zoomLink.dataset[key];\n        });\n        mainImage.style.objectFit = thumbnail.dataset.objectFit === 'cover' ? 'cover' : 'contain';\n        mainImage.style.objectPosition = `${thumbnail.dataset.objectPositionX || 50}% ${thumbnail.dataset.objectPositionY || 50}%`;\n        if (video && !insideViewer) {\n            pendingVideoThumbnail = thumbnail;\n            videoStartTimer = window.setTimeout(\n                () => startActiveVideo(thumbnail, index, autoplayVideo),\n                180,\n            );\n        }\n\n        thumbnails.forEach((item) => {\n            const active = item === thumbnail;\n            item.classList.toggle('z-product-gallery__thumb--active', active);\n            item.setAttribute('aria-pressed', String(active));\n            item.tabIndex = active ? 0 : -1;\n        });\n        if (initialWarmingPending) {\n            initialWarmingGeneration += 1;\n            warmAfterPrimaryImage();\n        } else warmAdjacentImages(index);\n        if (scroll && thumbnailGeometryObserver) observeThumbnailScroll(thumbnail);\n        else if (scrollDistance) rail.scrollBy({ left: scrollDistance, behavior: 'smooth' });\n        if (moveFocus && focusWithoutScroll(thumbnail) && scrollDistance) {\n            rail.scrollTo({ left: scrollTarget, behavior: 'smooth' });\n        }\n        updateArrows();\n        if (interactionType) {\n            trackMedia('product_media_viewed', thumbnail, interactionType);\n        }\n    }\n\n    thumbnails.forEach((thumbnail) => {\n        thumbnail.addEventListener('click', () =>\n            activate(thumbnail, { interactionType: 'select' }),\n        );\n    });\n\n    rail?.parentElement?.classList.add('is-gallery-ready');\n\n    function renderSwipe() {\n        swipeFrame = 0;\n        if (!swipe) return;\n        const { distance, direction } = swipe;\n        const current = mainVideo && !mainVideo.hidden ? mainVideo : mainImage;\n        current.style.transform = `translate3d(${distance}px, 0, 0)`;\n        if (swipePreview) {\n            const offset = direction > 0 ? -100 : 100;\n            swipePreview.style.transform = `translate3d(calc(${offset}% + ${distance}px), 0, 0)`;\n        }\n    }\n\n    async function completeSwipe(target, interactionType) {\n        const preview = swipePreview;\n        swipeFinishTimer = 0;\n        swipeDestination = null;\n        swipeFinishing = true;\n        applyingSwipeDestination = true;\n        activate(target, { interactionType });\n        applyingSwipeDestination = false;\n\n        if (!target.dataset.video && mainImage.decode) {\n            await Promise.race([\n                mainImage.decode().catch(() => {}),\n                new Promise((resolve) => window.setTimeout(resolve, 500)),\n            ]);\n        } else {\n            await new Promise((resolve) => window.requestAnimationFrame(resolve));\n        }\n        if (swipePreview === preview) clearSwipeVisuals();\n    }\n\n    stage.addEventListener('pointerdown', (event) => {\n        if (event.isPrimary && zoomLink.contains(event.target)) {\n            suppressZoom = false;\n            ignoreNativeZoomClick = false;\n        }\n        if (!event.isPrimary || event.pointerType !== 'touch' || thumbnails.length < 2) return;\n        if (event.target.closest('video, [data-product-wishlist]')) return;\n        if (swipeFinishing) clearSwipeVisuals();\n        if (swipeFinishTimer && swipeDestination) {\n            const { target, interactionType } = swipeDestination;\n            clearSwipeVisuals();\n            activate(target, { interactionType });\n        } else if (swipeFinishTimer) clearSwipeVisuals();\n        suppressZoom = false;\n        swipe = {\n            id: event.pointerId,\n            x: event.clientX,\n            y: event.clientY,\n            width: stage.clientWidth,\n            distance: 0,\n            direction: 0,\n        };\n    });\n    stage.addEventListener('pointermove', (event) => {\n        if (!swipe || event.pointerId !== swipe.id) return;\n        const horizontal = event.clientX - swipe.x;\n        const vertical = event.clientY - swipe.y;\n        if (!swipe.direction || swipe.direction !== Math.sign(horizontal)) {\n            if (Math.abs(horizontal) < 8 || Math.abs(horizontal) <= Math.abs(vertical) * 1.2)\n                return;\n            swipePreview?.remove();\n            swipePreview = null;\n            swipe.direction = horizontal > 0 ? 1 : -1;\n            if (mainVideo && !mainVideo.hidden) {\n                swipe.wasVideo = true;\n                swipe.pausedVideo = !mainVideo.paused;\n                mainVideo.pause();\n                mainVideo.hidden = true;\n                zoomLink.hidden = false;\n            }\n            swipePreview = prepareImage(activeIndex - swipe.direction);\n            if (swipePreview) {\n                stage.append(swipePreview);\n            }\n        }\n        const canAdvance = Boolean(thumbnails[activeIndex - Math.sign(horizontal)]);\n        swipe.distance = clamp(horizontal, -swipe.width, swipe.width) * (canAdvance ? 1 : 0.2);\n        if (!swipeFrame) swipeFrame = window.requestAnimationFrame(renderSwipe);\n    });\n    stage.addEventListener('pointerup', (event) => {\n        if (!swipe || event.pointerId !== swipe.id) return;\n        const horizontal = event.clientX - swipe.x;\n        const vertical = event.clientY - swipe.y;\n        const nextIndex = activeIndex - Math.sign(horizontal);\n        const next = thumbnails[nextIndex];\n        const shouldAdvance =\n            next && Math.abs(horizontal) >= 48 && Math.abs(horizontal) > Math.abs(vertical) * 1.2;\n        const hadPreview = Boolean(swipePreview);\n        const width = swipe.width;\n        restoreVideoAfterSwipe = !shouldAdvance && Boolean(swipe.wasVideo);\n        resumeVideoAfterSwipe = !shouldAdvance && Boolean(swipe.pausedVideo);\n        swipe = null;\n        if (!shouldAdvance) {\n            if (hadPreview) {\n                const duration = Math.round(clamp((Math.abs(horizontal) / width) * 140, 70, 140));\n                stage.style.setProperty('--z-product-gallery-settle-duration', `${duration}ms`);\n                stage.classList.add('z-product-gallery__stage--settling');\n                mainImage.style.transform = '';\n                if (mainVideo) mainVideo.style.transform = '';\n                swipePreview.style.transform = `translate3d(${horizontal > 0 ? '-100%' : '100%'}, 0, 0)`;\n                swipeFinishTimer = window.setTimeout(clearSwipeVisuals, duration + 16);\n            } else clearSwipeVisuals();\n            return;\n        }\n        suppressZoom = true;\n        const interactionType = horizontal < 0 ? 'next' : 'previous';\n        if (!hadPreview) {\n            clearSwipeVisuals();\n            activate(next, { interactionType });\n            return;\n        }\n        swipeDestination = { target: next, interactionType };\n        const duration = Math.round(\n            clamp((1 - Math.min(1, Math.abs(horizontal) / width)) * 175, 70, 150),\n        );\n        stage.style.setProperty('--z-product-gallery-settle-duration', `${duration}ms`);\n        stage.classList.add('z-product-gallery__stage--settling');\n        const destination = `${horizontal < 0 ? '-' : ''}${width}px`;\n        (mainVideo && !mainVideo.hidden ? mainVideo : mainImage).style.transform =\n            `translate3d(${destination}, 0, 0)`;\n        swipePreview.style.transform = 'translate3d(0, 0, 0)';\n        swipeFinishTimer = window.setTimeout(() => {\n            void completeSwipe(next, interactionType);\n        }, duration + 16);\n    });\n    stage.addEventListener('pointercancel', () => {\n        restoreVideoAfterSwipe = Boolean(swipe?.wasVideo);\n        resumeVideoAfterSwipe = Boolean(swipe?.pausedVideo);\n        swipe = null;\n        clearSwipeVisuals();\n    });\n    zoomLink.addEventListener('keydown', (event) => {\n        if (event.key === 'Enter' || event.key === ' ') {\n            suppressZoom = false;\n            ignoreNativeZoomClick = false;\n        }\n    });\n\n    zoomLink.addEventListener('pointerup', (event) => {\n        if (\n            event.pointerType !== 'touch' ||\n            !event.isPrimary ||\n            !swipe ||\n            event.pointerId !== swipe.id ||\n            swipe.direction ||\n            Math.abs(event.clientX - swipe.x) >= 8 ||\n            Math.abs(event.clientY - swipe.y) >= 8\n        )\n            return;\n\n        ignoreNativeZoomClick = true;\n        window.queueMicrotask(() => {\n            suppressZoom = false;\n            zoomLink.click();\n        });\n    });\n\n    rail?.addEventListener('keydown', (event) => {\n        if (!event.target.closest('[data-product-gallery-thumb]')) return;\n        let nextIndex = activeIndex;\n        if (event.key === 'ArrowLeft') nextIndex -= 1;\n        else if (event.key === 'ArrowRight') nextIndex += 1;\n        else if (event.key === 'Home') nextIndex = 0;\n        else if (event.key === 'End') nextIndex = thumbnails.length - 1;\n        else return;\n        event.preventDefault();\n        activate(thumbnails[Math.max(0, Math.min(thumbnails.length - 1, nextIndex))], {\n            moveFocus: true,\n            interactionType:\n                event.key === 'ArrowLeft'\n                    ? 'previous'\n                    : event.key === 'ArrowRight'\n                      ? 'next'\n                      : 'select',\n        });\n    });\n\n    arrows.forEach((button) => {\n        button.addEventListener('click', () => {\n            const nextIndex = Math.max(\n                0,\n                Math.min(\n                    thumbnails.length - 1,\n                    activeIndex + Number(button.dataset.productGalleryScroll),\n                ),\n            );\n            activate(thumbnails[nextIndex], {\n                interactionType:\n                    Number(button.dataset.productGalleryScroll) < 0 ? 'previous' : 'next',\n            });\n        });\n    });\n\n    gallery.querySelector('[data-product-wishlist]')?.addEventListener('click', (event) => {\n        const status = gallery\n            .closest('[data-product-id]')\n            ?.querySelector('.z-product-purchase__errors');\n        void toggleProductWishlist(\n            Number(event.currentTarget.dataset.productWishlist),\n            event.currentTarget,\n            status,\n        );\n    });\n\n    zoomLink.addEventListener('click', async (event) => {\n        if (ignoreNativeZoomClick && event.isTrusted) {\n            event.preventDefault();\n            ignoreNativeZoomClick = false;\n            return;\n        }\n        if (\n            event.defaultPrevented ||\n            event.button !== 0 ||\n            event.metaKey ||\n            event.ctrlKey ||\n            event.shiftKey ||\n            event.altKey\n        )\n            return;\n        if (suppressZoom) {\n            event.preventDefault();\n            suppressZoom = false;\n            return;\n        }\n        if (pendingVideoThumbnail) {\n            event.preventDefault();\n            startActiveVideo(pendingVideoThumbnail, activeIndex);\n            return;\n        }\n        event.preventDefault();\n        if (zoomLink.getAttribute('aria-busy') === 'true') return;\n\n        trackMedia('product_media_viewed', thumbnails[activeIndex], 'open');\n        zoomLink.setAttribute('aria-busy', 'true');\n\n        try {\n            const { openPhotoSwipeViewer } = await loadPhotoSwipeViewer();\n            if (!gallery.isConnected) return;\n\n            const activeThumbnail = thumbnails[activeIndex];\n            const slides = thumbnails.length\n                ? thumbnails.map((thumbnail) =>\n                      thumbnail.dataset.video\n                          ? {\n                                type: 'video',\n                                videoSrc: thumbnail.dataset.video,\n                                videoWebm: thumbnail.dataset.videoWebm || '',\n                                videoType: thumbnail.dataset.videoType || 'video/mp4',\n                                poster: thumbnail.dataset.videoPoster || thumbnail.dataset.image,\n                                posterSrcset: thumbnail.dataset.videoPosterSrcset || '',\n                                width: Number(thumbnail.dataset.videoWidth) || 1500,\n                                height: Number(thumbnail.dataset.videoHeight) || 1500,\n                                alt: thumbnail.dataset.alt || 'Produktvideo',\n                            }\n                          : {\n                                src:\n                                    thumbnail.dataset.popupRetina ||\n                                    thumbnail.dataset.popup ||\n                                    thumbnail.dataset.image,\n                                srcset: thumbnail.dataset.popupSrcset || undefined,\n                                width: Number(thumbnail.dataset.popupWidth) || 1500,\n                                height: Number(thumbnail.dataset.popupHeight) || 1500,\n                                msrc:\n                                    thumbnail === activeThumbnail\n                                        ? mainImage.currentSrc || thumbnail.dataset.image\n                                        : thumbnail.dataset.image,\n                                alt: thumbnail.dataset.alt || mainImage.alt,\n                                element: zoomLink,\n                                thumbCropped: thumbnail.dataset.objectFit === 'cover',\n                            },\n                  )\n                : [\n                      {\n                          src: zoomLink.dataset.popupRetina || zoomLink.href,\n                          srcset: zoomLink.dataset.popupSrcset || undefined,\n                          width: Number(zoomLink.dataset.popupWidth) || 1500,\n                          height: Number(zoomLink.dataset.popupHeight) || 1500,\n                          msrc: mainImage.currentSrc || mainImage.src,\n                          alt: mainImage.alt,\n                          element: zoomLink,\n                          thumbCropped: getComputedStyle(mainImage).objectFit === 'cover',\n                      },\n                  ];\n            const startIndex = Math.max(0, thumbnails.indexOf(activeThumbnail));\n            let viewerIndex = startIndex;\n\n            openPhotoSwipeViewer({\n                productMedia: true,\n                slides,\n                index: startIndex,\n                getThumbBounds: getPhotoSwipeThumbBounds,\n                onOpen: () => gallery.classList.add('z-product-gallery--viewer-open'),\n                onChange: (nextIndex) => {\n                    if (nextIndex === viewerIndex) return;\n                    viewerIndex = nextIndex;\n                    const thumbnail = thumbnails[nextIndex];\n                    if (thumbnail) {\n                        activate(thumbnail, { interactionType: 'dialog', insideViewer: true });\n                        if (thumbnail.dataset.video)\n                            trackMedia('product_video_opened', thumbnail, 'dialog');\n                    }\n                },\n                onDestroy: () => {\n                    gallery.classList.remove('z-product-gallery--viewer-open');\n                    if (gallery.isConnected && thumbnails[activeIndex]?.dataset.video) {\n                        activate(thumbnails[activeIndex], { autoplayVideo: false });\n                    }\n                },\n            });\n        } catch {\n            window.location.assign(zoomLink.href);\n        } finally {\n            zoomLink.removeAttribute('aria-busy');\n        }\n    });\n\n    function initMediaCombinations() {\n        if (!gallery.dataset.productMediaCombinations) return false;\n\n        let combinations;\n        try {\n            combinations = JSON.parse(gallery.dataset.productMediaCombinations);\n        } catch {\n            return false;\n        }\n\n        const preview = gallery.querySelector('[data-product-gallery-combination-preview]');\n        const product = gallery.closest('.z-product-page');\n        if (!preview || !product || !combinations?.media) return false;\n\n        const optionControl = (optionId) => {\n            const name = `option[${Number(optionId)}]`;\n            return product.querySelector(`input[name=\"${name}\"]:checked, select[name=\"${name}\"]`);\n        };\n        const optionName = (optionId) => {\n            const control = optionControl(optionId);\n            return control?.matches('select')\n                ? control.selectedOptions[0]?.dataset.optionName\n                : control?.dataset.optionName;\n        };\n        const backgroundInputs = product.querySelectorAll(\n            `input[name=\"option[${Number(combinations.background_option_id)}]\"], select[name=\"option[${Number(combinations.background_option_id)}]\"]`,\n        );\n        const foregroundInputs = product.querySelectorAll(\n            `input[name=\"option[${Number(combinations.foreground_option_id)}]\"], select[name=\"option[${Number(combinations.foreground_option_id)}]\"]`,\n        );\n\n        const update = () => {\n            const background = optionName(combinations.background_option_id);\n            const foreground = optionName(combinations.foreground_option_id);\n            const media = combinations.media[`${optionSlug(background)}-${optionSlug(foreground)}`];\n            if (!media) return;\n\n            preview.dataset.image = media.image_617 || media.image || '';\n            preview.dataset.srcset = mediaSrcset(media);\n            preview.dataset.popup = media.popup || media.image_617 || media.image || '';\n            preview.dataset.popupRetina = media.retina_popup || preview.dataset.popup;\n            preview.dataset.popupSrcset = popupSrcset(media);\n            preview.dataset.popupWidth =\n                media.retina_popup_size?.width || media.popup_size?.width || 1500;\n            preview.dataset.popupHeight =\n                media.retina_popup_size?.height || media.popup_size?.height || 1500;\n            preview.dataset.objectPositionX = media.image_object_fit_x ?? 50;\n            preview.dataset.objectPositionY = media.image_object_fit_y ?? 50;\n            preview.dataset.objectFit = media.image_object_fit === 'cover' ? 'cover' : 'contain';\n            preview.style.setProperty('--z-product-image-x', `${preview.dataset.objectPositionX}%`);\n            preview.style.setProperty('--z-product-image-y', `${preview.dataset.objectPositionY}%`);\n            delete preview.dataset.video;\n            delete preview.dataset.videoType;\n            delete preview.dataset.videoWebm;\n            const previewImage = preview.querySelector('img');\n            if (previewImage && media.thumb) {\n                previewImage.src = media.thumb;\n                previewImage.srcset = media.retina_thumb\n                    ? `${media.thumb} 1x, ${media.retina_thumb} 2x`\n                    : media.thumb;\n            }\n            activate(preview);\n        };\n\n        [...backgroundInputs, ...foregroundInputs].forEach((input) =>\n            input.addEventListener('change', update),\n        );\n        update();\n        return true;\n    }\n\n    if (initMediaCombinations()) return;\n    const initialThumbnail = thumbnails[activeIndex];\n    if (!initialThumbnail) {\n        updateArrows();\n        return;\n    }\n    // An initial video keeps its poster and native controls without competing\n    // with the page's first image; visitor selections still start playback.\n    activate(initialThumbnail, { autoplayVideo: false });\n}\n","import { focusWithoutScroll } from '../../common/focus-without-scroll/focus-without-scroll.js';\nfunction focusPurchaseTarget(target) {\n    target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n    window.setTimeout(() => {\n        if (focusWithoutScroll(target)) {\n            target.scrollIntoView({ behavior: 'smooth', block: 'center' });\n        }\n    }, 300);\n}\n\nexport function initProductStickyPurchase(sticky) {\n    const purchase = document.querySelector('[data-product-purchase]');\n    const form = purchase?.querySelector('#product-form');\n    const cartButton = purchase?.querySelector('.z-product-purchase__cart');\n    const stickyButton = sticky.querySelector('[data-product-sticky-cart]');\n    const stickyLabel = sticky.querySelector('[data-product-sticky-label]');\n    const stickyPrice = sticky.querySelector('[data-product-sticky-price]');\n    const sourcePrice = purchase?.querySelector('[data-product-price-value]');\n    const designerButton = purchase?.querySelector('[data-product-designer-open]');\n    const footer = document.querySelector('.z-site-footer');\n\n    if (!purchase || !form || !cartButton || !stickyButton || !stickyLabel) return;\n\n    let geometryDirty = true;\n    let geometryReady = false;\n    let geometryObserver = null;\n    let geometryFrame = 0;\n    let purchasePassed = false;\n    let footerVisible = false;\n    let renderFrame = 0;\n    const render = () => {\n        renderFrame = 0;\n        if (!geometryObserver && geometryDirty) {\n            purchasePassed = cartButton.getBoundingClientRect().bottom < 0;\n            if (footer) {\n                const bounds = footer.getBoundingClientRect();\n                footerVisible = bounds.top < window.innerHeight && bounds.bottom > 0;\n            }\n            geometryDirty = false;\n            geometryReady = true;\n        }\n        const busy = cartButton.getAttribute('aria-busy') === 'true';\n        const visible = geometryReady && purchasePassed && !footerVisible;\n        if (sticky.dataset.visible !== String(visible)) {\n            sticky.dataset.visible = String(visible);\n            document.body.classList.toggle('zirbelino-page--product-sticky-visible', visible);\n        }\n        if (stickyButton.getAttribute('aria-busy') !== String(busy)) {\n            stickyButton.setAttribute('aria-busy', String(busy));\n        }\n        const label =\n            cartButton.disabled && designerButton ? 'Gravur gestalten' : 'In den Warenkorb';\n        if (stickyLabel.textContent !== label) stickyLabel.textContent = label;\n        if (stickyPrice && sourcePrice) {\n            const price = sourcePrice.textContent.trim();\n            if (stickyPrice.textContent !== price) stickyPrice.textContent = price;\n        }\n    };\n    const scheduleRender = () => {\n        if (!renderFrame) renderFrame = window.requestAnimationFrame(render);\n    };\n    const invalidateGeometry = () => {\n        if (geometryObserver) {\n            if (geometryFrame) return;\n            geometryFrame = window.requestAnimationFrame(() => {\n                geometryFrame = 0;\n                if (!purchase.isConnected) {\n                    geometryObserver.disconnect();\n                    return;\n                }\n                // A fresh observation supplies native layout geometry even when\n                // the CTA remains outside the viewport with the same ratio.\n                geometryObserver.unobserve(cartButton);\n                geometryObserver.takeRecords();\n                geometryObserver.observe(cartButton);\n            });\n            return;\n        }\n        geometryDirty = true;\n        scheduleRender();\n    };\n\n    if (typeof IntersectionObserver !== 'undefined') {\n        geometryObserver = new IntersectionObserver((entries) => {\n            if (!purchase.isConnected) {\n                geometryObserver.disconnect();\n                return;\n            }\n            let entry = null;\n            for (const candidate of entries) {\n                if (candidate.target === cartButton && (!entry || candidate.time >= entry.time))\n                    entry = candidate;\n            }\n            if (!entry) return;\n            purchasePassed = entry.boundingClientRect.bottom < 0;\n            geometryReady = true;\n            scheduleRender();\n        });\n        geometryObserver.observe(cartButton);\n    }\n\n    window.addEventListener('scroll', invalidateGeometry, { passive: true });\n    window.addEventListener('resize', invalidateGeometry, { passive: true });\n    document.addEventListener('zirbelino:content-updated', invalidateGeometry);\n    purchase.addEventListener('load', invalidateGeometry, true);\n    if (typeof ResizeObserver !== 'undefined') {\n        const observer = new ResizeObserver(invalidateGeometry);\n        observer.observe(purchase);\n        observer.observe(document.body);\n    }\n\n    if (footer && typeof IntersectionObserver !== 'undefined') {\n        new IntersectionObserver((entries) => {\n            let entry = null;\n            for (const candidate of entries) {\n                if (candidate.target === footer && (!entry || candidate.time >= entry.time))\n                    entry = candidate;\n            }\n            if (!entry) return;\n            footerVisible = entry.isIntersecting;\n            scheduleRender();\n        }).observe(footer);\n    }\n\n    new MutationObserver(scheduleRender).observe(cartButton, {\n        attributes: true,\n        attributeFilter: ['disabled', 'aria-busy'],\n    });\n    if (sourcePrice) {\n        new MutationObserver(scheduleRender).observe(sourcePrice, {\n            childList: true,\n            characterData: true,\n            subtree: true,\n        });\n    }\n\n    stickyButton.addEventListener('click', () => {\n        if (cartButton.getAttribute('aria-busy') === 'true') return;\n\n        const invalid = form.querySelector(':invalid');\n        if (invalid) {\n            focusPurchaseTarget(invalid);\n            window.setTimeout(() => form.reportValidity(), 320);\n            return;\n        }\n\n        if (cartButton.disabled && designerButton) {\n            designerButton.click();\n            return;\n        }\n\n        if (!cartButton.disabled) cartButton.click();\n    });\n\n    sticky.hidden = false;\n    if (!geometryObserver) scheduleRender();\n}\n","export function initProductStickyColumns(area) {\n    if (!('ResizeObserver' in window)) return;\n\n    const columns = [...area.children].filter((element) =>\n        element.hasAttribute('data-product-sticky-column'),\n    );\n    if (!columns.length) return;\n\n    const pending = new Map();\n    let frame = 0;\n    const observer = new ResizeObserver((entries) => {\n        // ResizeObserver supplies sizes after layout; scrolling needs no JS work.\n        for (const entry of entries) {\n            const height = entry.borderBoxSize?.[0]?.blockSize ?? entry.borderBoxSize?.blockSize;\n            if (Number.isFinite(height)) pending.set(entry.target, height);\n        }\n        if (!pending.size || frame) return;\n        frame = window.requestAnimationFrame(() => {\n            frame = 0;\n            if (!area.isConnected) {\n                observer.disconnect();\n                pending.clear();\n                return;\n            }\n            for (const [column, height] of pending) {\n                const value = `${height}px`;\n                if (column.style.getPropertyValue('--z-product-sticky-column-height') !== value) {\n                    column.style.setProperty('--z-product-sticky-column-height', value);\n                }\n                if (column.hasAttribute('data-product-sticky-column-ready') !== height > 0) {\n                    column.toggleAttribute('data-product-sticky-column-ready', height > 0);\n                }\n            }\n            pending.clear();\n        });\n    });\n    columns.forEach((column) => observer.observe(column, { box: 'border-box' }));\n}\n","export function initAgeVerification(dialog) {\n    if (window.localStorage.getItem(`zirbelino-age-${dialog.dataset.minimumAge}`) === 'confirmed')\n        return;\n    if (typeof dialog.showModal === 'function') dialog.showModal();\n    else dialog.setAttribute('open', '');\n    dialog.querySelector('[data-age-accept]')?.addEventListener('click', () => {\n        window.localStorage.setItem(`zirbelino-age-${dialog.dataset.minimumAge}`, 'confirmed');\n        document.cookie = 'age_verification=1; Path=/; Max-Age=31536000; SameSite=Lax';\n    });\n}\n","import { focusWithoutScroll } from '../../common/focus-without-scroll/focus-without-scroll.js';\nexport function initProductDetails(root) {\n    const tabs = [...root.querySelectorAll('[role=\"tab\"]')];\n    if (!tabs.length) return;\n\n    const panels = tabs\n        .map((tab) => document.getElementById(tab.getAttribute('aria-controls')))\n        .filter(Boolean);\n    const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');\n    const replaceHash = (hash) => {\n        const url = new URL(window.location.href);\n        url.hash = hash;\n        history.replaceState(history.state, '', url);\n    };\n\n    const activate = (tab, { focus = false, scroll = false, updateHash = false } = {}) => {\n        tabs.forEach((item) => {\n            const active = item === tab;\n            item.classList.toggle('z-product-details__tab--active', active);\n            item.setAttribute('aria-selected', String(active));\n            item.tabIndex = active ? 0 : -1;\n        });\n        panels.forEach((panel) => {\n            panel.hidden = panel.id !== tab.getAttribute('aria-controls');\n        });\n        if (focus) focusWithoutScroll(tab);\n        if (scroll) {\n            tab.scrollIntoView({\n                behavior: reducedMotion.matches ? 'auto' : 'smooth',\n                block: 'nearest',\n                inline: 'nearest',\n            });\n        }\n        if (updateHash) replaceHash(tab.hash);\n    };\n\n    root.classList.add('is-product-details-enhanced');\n    tabs.forEach((tab, index) => {\n        tab.addEventListener('click', (event) => {\n            event.preventDefault();\n            activate(tab, { scroll: true, updateHash: true });\n        });\n        tab.addEventListener('keydown', (event) => {\n            let nextIndex;\n            if (event.key === 'ArrowLeft') nextIndex = (index - 1 + tabs.length) % tabs.length;\n            else if (event.key === 'ArrowRight') nextIndex = (index + 1) % tabs.length;\n            else if (event.key === 'Home') nextIndex = 0;\n            else if (event.key === 'End') nextIndex = tabs.length - 1;\n            else return;\n            event.preventDefault();\n            activate(tabs[nextIndex], {\n                focus: true,\n                scroll: true,\n                updateHash: true,\n            });\n        });\n    });\n\n    const descriptionMore = root.querySelector('[data-product-description-more]');\n    const fullDescription = root.querySelector('[data-product-full-description]');\n    const additionalTab = root.querySelector('#z-product-additional-tab');\n    const showFullDescription = ({ updateHash = true, scroll = true } = {}) => {\n        if (!fullDescription || !additionalTab) return;\n        activate(additionalTab);\n        fullDescription.open = true;\n        if (updateHash) replaceHash(`#${fullDescription.id}`);\n        if (scroll) {\n            fullDescription.scrollIntoView({\n                behavior: reducedMotion.matches ? 'auto' : 'smooth',\n                block: 'start',\n            });\n            focusWithoutScroll(fullDescription.querySelector('summary'));\n        }\n    };\n\n    descriptionMore?.addEventListener('click', (event) => {\n        event.preventDefault();\n        showFullDescription();\n    });\n\n    const hashTab = tabs.find((tab) => tab.hash === window.location.hash);\n    if (fullDescription && window.location.hash === `#${fullDescription.id}`) {\n        showFullDescription({ updateHash: false, scroll: false });\n    } else {\n        activate(hashTab || tabs[0]);\n    }\n}\n","import { focusWithoutScroll } from '../../common/focus-without-scroll/focus-without-scroll.js';\nexport function initProductReviews(root) {\n    const dialog = root.querySelector('[data-product-reviews-dialog]');\n    if (!dialog || typeof HTMLDialogElement === 'undefined') return;\n\n    const body = dialog.querySelector('[data-product-reviews-body]');\n    let activeRequest;\n    let returnFocus;\n\n    const load = async (value) => {\n        const url = new URL(value, window.location.href);\n        if (url.origin !== window.location.origin) return false;\n        activeRequest?.abort();\n        activeRequest = new AbortController();\n        body.innerHTML =\n            '<p class=\"z-product-review-dialog__loading\"><span data-nosnippet>Bewertungen werden geladen …</span></p>';\n        dialog.setAttribute('aria-busy', 'true');\n        try {\n            const response = await fetch(url, {\n                credentials: 'same-origin',\n                headers: { Accept: 'text/html' },\n                signal: activeRequest.signal,\n            });\n            if (!response.ok) throw new Error(`HTTP ${response.status}`);\n            body.innerHTML = await response.text();\n            dialog.dataset.loaded = url.href;\n            document.dispatchEvent(\n                new CustomEvent('zirbelino:content-updated', { detail: { root: body } }),\n            );\n            body.scrollTo({ top: 0, behavior: 'auto' });\n            return true;\n        } catch (error) {\n            if (error instanceof DOMException && error.name === 'AbortError') return false;\n            body.innerHTML =\n                '<p class=\"z-product-review-dialog__error\"><span data-nosnippet>Die Bewertungen konnten nicht geladen werden. Bitte versuchen Sie es erneut.</span></p>';\n            return false;\n        } finally {\n            dialog.removeAttribute('aria-busy');\n        }\n    };\n\n    root.closest('[data-product-id]')\n        ?.querySelectorAll('[data-product-reviews-open]')\n        .forEach((link) => {\n            link.addEventListener('click', (event) => {\n                event.preventDefault();\n                returnFocus = link;\n                if (!dialog.open) dialog.showModal();\n                if (!dialog.dataset.loaded) void load(dialog.dataset.reviewSource);\n            });\n        });\n    dialog\n        .querySelector('[data-product-reviews-close]')\n        .addEventListener('click', () => dialog.close());\n    dialog.addEventListener('click', (event) => {\n        if (event.target === dialog) dialog.close();\n    });\n    dialog.addEventListener('close', () => focusWithoutScroll(returnFocus));\n    body.addEventListener('click', (event) => {\n        const link = event.target.closest('.z-product-review-list__pagination a');\n        if (!link) return;\n        event.preventDefault();\n        void load(link.href);\n    });\n}\n","import { initMediaLibraries } from '../../common/media-library/media-library.js';\n\nfunction initDownloadList(root) {\n    const list = root.querySelector('[data-product-download-list]');\n    const toggle = list?.querySelector('[data-product-download-toggle]');\n    const label = toggle?.querySelector('[data-product-download-toggle-label]');\n    const extraCount = list?.querySelectorAll('[data-product-download-extra]').length || 0;\n    if (!toggle || !label || !extraCount) return;\n\n    const compact = window.matchMedia('(max-width: 69.999rem)');\n    let expanded = false;\n\n    const sync = () => {\n        list.classList.toggle('is-collapsed', compact.matches && !expanded);\n        toggle.hidden = !compact.matches;\n        toggle.setAttribute('aria-expanded', String(!compact.matches || expanded));\n        label.textContent = expanded\n            ? 'Weniger anzeigen'\n            : `Weitere ${extraCount} Downloads anzeigen`;\n    };\n\n    toggle.addEventListener('click', () => {\n        expanded = !expanded;\n        sync();\n    });\n    compact.addEventListener('change', sync);\n    sync();\n}\n\nexport function initProductMedia(root) {\n    if (root.dataset.productMediaReady === 'true') return;\n    root.dataset.productMediaReady = 'true';\n    initMediaLibraries(root);\n    initDownloadList(root);\n}\n","import { initExpressLoading } from '../../common/advanced-payment-express/express-loading.js';\n\nconst initializers = new WeakMap();\nlet modulePromise;\nlet moduleFailed = false;\n\nfunction preloadStripeSdk(root) {\n    if (!root.hasAttribute('data-express-stripe') || typeof window.Stripe === 'function') return;\n    // Start the SDK download alongside the optional integration chunk. Keep\n    // the same proximity/input gate and let the adapter execute the script.\n    for (const [rel, href] of [\n        ['preconnect', 'https://js.stripe.com'],\n        ['preload', 'https://js.stripe.com/v3/'],\n    ]) {\n        if (document.head.querySelector(`link[rel=\"${rel}\"][href=\"${href}\"]`)) continue;\n        const link = document.createElement('link');\n        link.rel = rel;\n        link.href = href;\n        if (rel === 'preload') link.as = 'script';\n        document.head.appendChild(link);\n    }\n}\n\nfunction loadProductExpress() {\n    // A failed module fetch is cached for this document. The retry entry has a\n    // distinct Vite URL while reusing the same shared provider dependencies.\n    modulePromise ||= (\n        moduleFailed ? import('./product-express.js?retry') : import('./product-express.js')\n    ).catch((error) => {\n        moduleFailed = true;\n        modulePromise = undefined;\n        throw error;\n    });\n    return modulePromise;\n}\n\nexport function initProductExpressOnDemand(root, { userActivated = false } = {}) {\n    if (initializers.has(root)) return initializers.get(root);\n    const form = root.closest('form');\n    if (!form) {\n        root.removeAttribute('data-express-loading');\n        root.removeAttribute('aria-busy');\n        return;\n    }\n    const loading = initExpressLoading(root);\n    const loadingLabel = root.querySelector('[data-express-loading-label]');\n    const controller = new AbortController();\n    let observer;\n    let initialization;\n    let initialized = false;\n    let interacted = userActivated;\n    let nearby = false;\n    let geometryFrame;\n    // Retain the observation target and reserved layout after a chunk failure\n    // so another real interaction can retry the optional integration.\n    root.setAttribute('data-express-deferred', '');\n    const start = () => {\n        if (initialized || initialization) return initialization;\n        if (!root.isConnected || !nearby || !interacted) return;\n        loading?.startAll();\n        preloadStripeSdk(root);\n        root.setAttribute('data-express-loading', '');\n        root.setAttribute('aria-busy', 'true');\n        if (loadingLabel) loadingLabel.textContent = 'Express-Zahlarten werden geladen …';\n        initialization = loadProductExpress()\n            .then(({ initProductExpress }) => {\n                if (!root.isConnected) {\n                    observer?.disconnect();\n                    controller.abort();\n                    cancelAnimationFrame(geometryFrame);\n                    root.removeAttribute('data-express-deferred');\n                    return;\n                }\n                // The implementation reads the current form, including edits\n                // made while the SDK integration was still outside the viewport.\n                initProductExpress(root);\n                initialized = true;\n                observer?.disconnect();\n                controller.abort();\n                cancelAnimationFrame(geometryFrame);\n                root.removeAttribute('data-express-deferred');\n            })\n            .catch(() => {\n                if (!initialized) initialization = undefined;\n                interacted = false;\n                root.removeAttribute('data-express-loading');\n                root.removeAttribute('aria-busy');\n                loading?.failAll();\n                // Preserve the normal cart action; a later real interaction\n                // can retry a failed optional integration chunk.\n            });\n        return initialization;\n    };\n    initializers.set(root, start);\n    const updateGeometry = () => {\n        const bounds = root.getBoundingClientRect();\n        const height = document.documentElement.clientHeight;\n        const width = document.documentElement.clientWidth;\n        const hasArea = bounds.width > 0 && bounds.height > 0;\n        const horizontal = bounds.right > 0 && bounds.left < width;\n        nearby = hasArea && horizontal && bounds.bottom > -400 && bounds.top < height + 400;\n        void start();\n    };\n    const onInteraction = (event) => {\n        // Focus and scroll events may be trusted even when triggered by code.\n        // Listen to the physical input that causes them instead.\n        if (!event.isTrusted) return;\n        interacted = true;\n        if (typeof IntersectionObserver === 'undefined') updateGeometry();\n        else void start();\n    };\n    for (const type of [\n        'pointermove',\n        'mousemove',\n        'pointerdown',\n        'touchstart',\n        'wheel',\n        'keydown',\n        'click',\n    ]) {\n        document.addEventListener(type, onInteraction, {\n            capture: true,\n            passive: true,\n            signal: controller.signal,\n        });\n    }\n    if (typeof IntersectionObserver === 'undefined') {\n        const scheduleGeometry = () => {\n            cancelAnimationFrame(geometryFrame);\n            geometryFrame = requestAnimationFrame(updateGeometry);\n        };\n        for (const type of ['scroll', 'resize']) {\n            window.addEventListener(type, scheduleGeometry, {\n                passive: true,\n                signal: controller.signal,\n            });\n        }\n        updateGeometry();\n    } else {\n        observer = new IntersectionObserver(\n            (entries) => {\n                nearby = entries.some((entry) => entry.isIntersecting);\n                void start();\n            },\n            { rootMargin: '400px 0px' },\n        );\n        observer.observe(root);\n    }\n    return start;\n}\n","import { focusWithoutScroll } from '../../common/focus-without-scroll/focus-without-scroll.js';\nimport { initProductExpressOnDemand } from '../product-express/product-express-loader.js';\n\nconst initialized = new WeakSet();\n\nexport function initProductBusinessDetails(dialog) {\n    if (initialized.has(dialog)) return;\n    const container = dialog.closest('[data-product-id]');\n    const opener = container?.querySelector('[data-product-business-open]');\n    const target = container?.querySelector('[data-product-express-target]');\n    const form = dialog.querySelector('[data-product-business-form]');\n    if (!opener || !target || !form || typeof dialog.showModal !== 'function') return;\n    initialized.add(dialog);\n    const submit = form.querySelector('[type=\"submit\"]');\n    const status = form.querySelector('[data-business-status]');\n    let busy = false;\n    let completed = false;\n    const close = () => {\n        if (!busy) dialog.close();\n    };\n    opener.addEventListener('click', (event) => {\n        event.preventDefault();\n        dialog.showModal();\n    });\n    dialog\n        .querySelectorAll('[data-product-business-close]')\n        .forEach((button) => button.addEventListener('click', close));\n    dialog.addEventListener('click', (event) => {\n        if (event.target === dialog) close();\n    });\n    dialog.addEventListener('cancel', (event) => {\n        if (busy) event.preventDefault();\n    });\n    dialog.addEventListener('close', () => {\n        focusWithoutScroll(\n            completed ? container.querySelector('.z-product-purchase__cart') : opener,\n        );\n    });\n    form.addEventListener('submit', async (event) => {\n        event.preventDefault();\n        if (busy || !form.reportValidity()) return;\n        const userActivated = event.isTrusted;\n        status.hidden = true;\n        form.querySelectorAll('[data-business-error]').forEach((error) => {\n            error.hidden = true;\n            form.elements.namedItem(error.dataset.businessError)?.removeAttribute('aria-invalid');\n        });\n        const body = new FormData(form);\n        busy = true;\n        submit.disabled = true;\n        form.setAttribute('aria-busy', 'true');\n        const controller = new AbortController();\n        const timeout = setTimeout(() => controller.abort(), 30000);\n        try {\n            const response = await fetch(form.action, {\n                method: 'POST',\n                body,\n                credentials: 'same-origin',\n                cache: 'no-store',\n                headers: { Accept: 'application/json' },\n                signal: controller.signal,\n            });\n            const result = await response.json().catch(() => {\n                throw new Error(\n                    'Die Firmendaten konnten nicht geprüft werden. Bitte versuchen Sie es erneut.',\n                );\n            });\n            if (!response.ok || result.success !== true) {\n                let first;\n                for (const name of ['company', 'vat_number']) {\n                    if (!result.errors?.[name]) continue;\n                    const input = form.elements.namedItem(name);\n                    const error = form.querySelector(`[data-business-error=\"${name}\"]`);\n                    error.textContent = result.errors[name];\n                    error.hidden = false;\n                    input.setAttribute('aria-invalid', 'true');\n                    first ||= input;\n                }\n                if (first) focusWithoutScroll(first);\n                else\n                    throw new Error(\n                        result.error || 'Die Firmendaten konnten nicht geprüft werden.',\n                    );\n                return;\n            }\n            const fragment = document.createElement('template');\n            fragment.innerHTML = typeof result.html === 'string' ? result.html : '';\n            const express = fragment.content.querySelector('[data-product-express]');\n            if (!express)\n                throw new Error(\n                    'Express konnte nicht geladen werden. Bitte versuchen Sie es erneut.',\n                );\n            completed = true;\n            dialog.close();\n            target.replaceChildren(fragment.content);\n            initProductExpressOnDemand(express, { userActivated });\n        } catch (error) {\n            status.textContent =\n                error.name === 'AbortError'\n                    ? 'Die Prüfung dauert gerade zu lange. Bitte versuchen Sie es erneut.'\n                    : error.name === 'TypeError'\n                      ? 'Die Verbindung wurde unterbrochen. Bitte versuchen Sie es erneut.'\n                      : error.message || 'Die Firmendaten konnten nicht geprüft werden.';\n            status.hidden = false;\n        } finally {\n            clearTimeout(timeout);\n            busy = false;\n            submit.disabled = false;\n            form.removeAttribute('aria-busy');\n        }\n    });\n}\n","import '../../styles/pages/product.css';\nimport { initProductGallery } from '../../../template/components/product/product-gallery/product-gallery.js';\nimport { initProductPurchase } from '../../../template/components/product/product-purchase/product-purchase.js';\nimport { initProductStickyPurchase } from '../../../template/components/product/product-sticky-purchase/product-sticky-purchase.js';\nimport { initProductStickyColumns } from '../../../template/components/product/product-sticky-column/product-sticky-column.js';\nimport { initAgeVerification } from '../../../template/components/product/product-age-verification/product-age-verification.js';\nimport { initProductDetails } from '../../../template/components/product/product-details/product-details.js';\nimport { initProductReviews } from '../../../template/components/product/product-reviews/product-reviews.js';\nimport { initProductMedia } from '../../../template/components/product/product-media-extras/product-media-extras.js';\nimport { initProductRecommendations } from '../../../template/components/product/product-recommendations/product-recommendations.js';\nimport { initProductExpressOnDemand } from '../../../template/components/product/product-express/product-express-loader.js';\nimport { initProductBusinessDetails } from '../../../template/components/product/product-business-details/product-business-details.js';\nimport { initContentComponents } from '../../../template/components/content/content.js';\n\ndocument.querySelectorAll('[data-product-buy-area]').forEach(initProductStickyColumns);\ndocument.querySelectorAll('[data-product-gallery]').forEach(initProductGallery);\ndocument.querySelectorAll('[data-product-purchase]').forEach(initProductPurchase);\ndocument.querySelectorAll('[data-product-express]').forEach(initProductExpressOnDemand);\ndocument.querySelectorAll('[data-product-business-dialog]').forEach(initProductBusinessDetails);\ndocument.querySelectorAll('[data-product-sticky-purchase]').forEach(initProductStickyPurchase);\ndocument.querySelectorAll('[data-age-verification]').forEach(initAgeVerification);\ndocument.querySelectorAll('[data-product-details]').forEach(initProductDetails);\ndocument.querySelectorAll('[data-product-reviews]').forEach(initProductReviews);\ndocument.querySelectorAll('[data-product-media]').forEach(initProductMedia);\ninitProductRecommendations();\ninitContentComponents();\n"],"file":"product.js"}