+2
-1
plain-html/game.html
······<!-- uncomment if you want to drop in some kind of commenting system and put in whatever script you're using -->
+1
plain-html/index.html
···
+2
-1
plain-html/submissions.html
···
+570
zola/sass/style.scss
···+@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
zola/static/images/android-chrome-192x192.png
This is a binary file and will not be displayed.
zola/static/images/android-chrome-512x512.png
This is a binary file and will not be displayed.
+1
zola/static/images/android.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M452.5 317.9C465.8 317.9 476.5 328.6 476.5 341.9C476.5 355.2 465.8 365.9 452.5 365.9C439.2 365.9 428.5 355.2 428.5 341.9C428.5 328.6 439.2 317.9 452.5 317.9zM187.4 317.9C200.7 317.9 211.4 328.6 211.4 341.9C211.4 355.2 200.7 365.9 187.4 365.9C174.1 365.9 163.4 355.2 163.4 341.9C163.4 328.6 174.1 317.9 187.4 317.9zM461.1 221.4L509 138.4C509.8 137.3 510.3 136 510.5 134.6C510.7 133.2 510.7 131.9 510.4 130.5C510.1 129.1 509.5 127.9 508.7 126.8C507.9 125.7 506.9 124.8 505.7 124.1C504.5 123.4 503.2 123 501.8 122.8C500.4 122.6 499.1 122.8 497.8 123.2C496.5 123.6 495.3 124.3 494.2 125.1C493.1 125.9 492.3 127.1 491.7 128.3L443.2 212.4C404.4 195 362.4 186 319.9 186C277.4 186 235.4 195 196.6 212.4L148.2 128.4C147.6 127.2 146.7 126.1 145.7 125.2C144.7 124.3 143.4 123.7 142.1 123.3C140.8 122.9 139.4 122.8 138.1 122.9C136.8 123 135.4 123.5 134.2 124.2C133 124.9 132 125.8 131.2 126.9C130.4 128 129.8 129.3 129.5 130.6C129.2 131.9 129.2 133.3 129.4 134.7C129.6 136.1 130.2 137.3 130.9 138.5L178.8 221.5C96.5 266.2 40.2 349.5 32 448L608 448C599.8 349.5 543.5 266.2 461.1 221.4z"/></svg>
zola/static/images/apple-touch-icon.png
This is a binary file and will not be displayed.
zola/static/images/favicon-16x16.png
This is a binary file and will not be displayed.
zola/static/images/favicon-32x32.png
This is a binary file and will not be displayed.
zola/static/images/favicon.ico
This is a binary file and will not be displayed.
+1
zola/static/images/linux.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M316.9 187.3C317.9 187.8 318.7 189 319.9 189C321 189 322.7 188.6 322.8 187.5C323 186.1 320.9 185.2 319.6 184.6C317.9 183.9 315.7 183.6 314.1 184.5C313.7 184.7 313.3 185.2 313.5 185.6C313.8 186.9 315.8 186.7 316.9 187.3zM295 189C296.2 189 297 187.8 298 187.3C299.1 186.7 301.1 186.9 301.5 185.7C301.7 185.3 301.3 184.8 300.9 184.6C299.3 183.7 297.1 184 295.4 184.7C294.1 185.3 292 186.2 292.2 187.6C292.3 188.6 294 189.1 295 189zM516 467.8C512.4 463.8 510.7 456.2 508.8 448.1C507 440 504.9 431.3 498.3 425.7C497 424.6 495.7 423.6 494.3 422.8C493 422 491.6 421.3 490.2 420.8C499.4 393.5 495.8 366.3 486.5 341.7C475.1 311.6 455.2 285.3 440 267.3C422.9 245.8 406.3 225.4 406.6 195.3C407.1 149.4 411.7 64.1 330.8 64C228.4 63.8 254 167.4 252.9 199.2C251.2 222.6 246.5 241 230.4 263.9C211.5 286.4 184.9 322.7 172.3 360.6C166.3 378.5 163.5 396.7 166.1 413.9C159.6 419.7 154.7 428.6 149.5 434.1C145.3 438.4 139.2 440 132.5 442.4C125.8 444.8 118.5 448.4 114 456.9C111.9 460.8 111.2 465 111.2 469.3C111.2 473.2 111.8 477.2 112.4 481.1C113.6 489.2 114.9 496.8 113.2 501.9C108 516.3 107.3 526.3 111 533.6C114.8 540.9 122.4 544.1 131.1 545.9C148.4 549.5 171.9 548.6 190.4 558.4C210.2 568.8 230.3 572.5 246.3 568.8C257.9 566.2 267.4 559.2 272.2 548.6C284.7 548.5 298.5 543.2 320.5 542C335.4 540.8 354.1 547.3 375.6 546.1C376.2 548.4 377 550.7 378.1 552.8L378.1 552.9C386.4 569.6 401.9 577.2 418.4 575.9C435 574.6 452.5 564.9 466.7 548C480.3 531.6 502.7 524.8 517.6 515.8C525 511.3 531 505.7 531.5 497.5C531.9 489.3 527.1 480.2 516 467.8zM319.8 151.3C329.6 129.1 354 129.5 363.8 150.9C370.3 165.1 367.4 181.8 359.5 191.3C357.9 190.5 353.6 188.7 346.9 186.4C348 185.2 350 183.7 350.8 181.8C355.6 170 350.6 154.8 341.7 154.5C334.4 154 327.8 165.3 329.9 177.5C325.8 175.5 320.5 174 316.9 173.1C315.9 166.2 316.6 158.5 319.8 151.3zM279.1 139.8C289.2 139.8 299.9 154 298.2 173.3C294.7 174.3 291.1 175.8 288 177.9C289.2 169 284.7 157.8 278.4 158.3C270 159 268.6 179.5 276.6 186.4C277.6 187.2 278.5 186.2 270.7 191.9C255.1 177.3 260.2 139.8 279.1 139.8zM265.5 200.5C271.7 195.9 279.1 190.5 279.6 190C284.3 185.6 293.1 175.8 307.5 175.8C314.6 175.8 323.1 178.1 333.4 184.7C339.7 188.8 344.7 189.1 356 194C364.4 197.5 369.7 203.7 366.5 212.2C363.9 219.3 355.5 226.6 343.8 230.3C332.7 233.9 324 246.3 305.6 245.2C301.7 245 298.6 244.2 296 243.1C288 239.6 283.8 232.7 276 228.1C267.4 223.3 262.8 217.7 261.3 212.8C259.9 207.9 261.3 203.8 265.5 200.5zM268.8 534.5C266.1 569.6 224.9 568.9 193.5 552.5C163.6 536.7 124.9 546 117 530.6C114.6 525.9 114.6 517.9 119.6 504.2L119.6 504C122 496.4 120.2 488 119 480.1C117.8 472.3 117.2 465.1 119.9 460.1C123.4 453.4 128.4 451 134.7 448.8C145 445.1 146.5 445.4 154.3 438.9C159.8 433.2 163.8 426 168.6 420.9C173.7 415.4 178.6 412.8 186.3 414C194.4 415.2 201.4 420.8 208.2 430L227.8 465.6C237.3 485.5 270.9 514 268.8 534.5zM267.4 508.6C263.3 502 257.8 495 253 489C260.1 489 267.2 486.8 269.7 480.1C272 473.9 269.7 465.2 262.3 455.2C248.8 437 224 422.7 224 422.7C210.5 414.3 202.9 404 199.4 392.8C195.9 381.6 196.4 369.5 199.1 357.6C204.3 334.7 217.7 312.4 226.3 298.4C228.6 296.7 227.1 301.6 217.6 319.2C209.1 335.3 193.2 372.5 215 401.6C215.6 380.9 220.5 359.8 228.8 340.1C240.8 312.7 266.1 265.2 268.1 227.4C269.2 228.2 272.7 230.6 274.3 231.5C278.9 234.2 282.4 238.2 286.9 241.8C299.3 251.8 315.4 251 329.3 243C335.5 239.5 340.5 235.5 345.2 234C355.1 230.9 363 225.4 367.5 219C375.2 249.4 393.2 293.3 404.7 314.7C410.8 326.1 423 350.2 428.3 379.3C431.6 379.2 435.3 379.7 439.2 380.7C453 345 427.5 306.5 415.9 295.8C411.2 291.2 411 289.2 413.3 289.3C425.9 300.5 442.5 323 448.5 348.3C451.3 359.9 451.8 372 448.9 384C465.3 390.8 484.8 401.9 479.6 418.8C477.4 418.7 476.4 418.8 475.4 418.8C478.6 408.7 471.5 401.2 452.6 392.7C433 384.1 416.6 384.1 414.3 405.2C402.2 409.4 396 419.9 392.9 432.5C390.1 443.7 389.3 457.2 388.5 472.4C388 480.1 384.9 490.4 381.7 501.4C349.6 524.3 305 534.3 267.4 508.6zM524.8 497.1C523.9 513.9 483.6 517 461.6 543.6C448.4 559.3 432.2 568 418 569.1C403.8 570.2 391.5 564.3 384.3 549.8C379.6 538.7 381.9 526.7 385.4 513.5C389.1 499.3 394.6 484.7 395.3 472.9C396.1 457.7 397 444.4 399.5 434.2C402.1 423.9 406.1 417 413.2 413.1C413.5 412.9 413.9 412.8 414.2 412.6C415 425.8 421.5 439.2 433 442.1C445.6 445.4 463.7 434.6 471.4 425.8C480.4 425.5 487.1 424.9 494 430.9C503.9 439.4 501.1 461.2 511.1 472.5C521.7 484.1 525.1 492 524.8 497.1zM269.4 212.7C271.4 214.6 274.1 217.2 277.4 219.8C284 225 293.2 230.4 304.7 230.4C316.3 230.4 327.2 224.5 336.5 219.6C341.4 217 347.4 212.6 351.3 209.2C355.2 205.8 357.2 202.9 354.4 202.6C351.6 202.3 351.8 205.2 348.4 207.7C344 210.9 338.7 215.1 334.5 217.5C327.1 221.7 315 227.7 304.6 227.7C294.2 227.7 285.9 222.9 279.7 218C276.6 215.5 274 213 272 211.1C270.5 209.7 270.1 206.5 267.7 206.2C266.3 206.1 265.9 209.9 269.4 212.7z"/></svg>
+1
zola/static/images/macos.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 176C311.2 176 304 168.8 304 160L304 144C304 99.8 339.8 64 384 64L400 64C408.8 64 416 71.2 416 80L416 96C416 140.2 380.2 176 336 176L320 176zM96 352C96 275.7 131.7 192 208 192C235.3 192 267.7 202.3 290.7 211.3C309.5 218.6 330.6 218.6 349.4 211.3C372.3 202.4 404.8 192 432.1 192C508.4 192 544.1 275.7 544.1 352C544.1 480 464.1 576 384.1 576C367.6 576 346 569.4 332.6 564.7C324.5 561.9 315.7 561.9 307.6 564.7C294.2 569.4 272.6 576 256.1 576C176.1 576 96.1 480 96.1 352z"/></svg>
+1
zola/static/images/random.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M467.8 98.4C479.8 93.4 493.5 96.2 502.7 105.3L566.7 169.3C572.7 175.3 576.1 183.4 576.1 191.9C576.1 200.4 572.7 208.5 566.7 214.5L502.7 278.5C493.5 287.7 479.8 290.4 467.8 285.4C455.8 280.4 448 268.9 448 256L448 224L416 224C405.9 224 396.4 228.7 390.4 236.8L358 280L318 226.7L339.2 198.4C357.3 174.2 385.8 160 416 160L448 160L448 128C448 115.1 455.8 103.4 467.8 98.4zM218 360L258 413.3L236.8 441.6C218.7 465.8 190.2 480 160 480L96 480C78.3 480 64 465.7 64 448C64 430.3 78.3 416 96 416L160 416C170.1 416 179.6 411.3 185.6 403.2L218 360zM502.6 534.6C493.4 543.8 479.7 546.5 467.7 541.5C455.7 536.5 448 524.9 448 512L448 480L416 480C385.8 480 357.3 465.8 339.2 441.6L185.6 236.8C179.6 228.7 170.1 224 160 224L96 224C78.3 224 64 209.7 64 192C64 174.3 78.3 160 96 160L160 160C190.2 160 218.7 174.2 236.8 198.4L390.4 403.2C396.4 411.3 405.9 416 416 416L448 416L448 384C448 371.1 455.8 359.4 467.8 354.4C479.8 349.4 493.5 352.2 502.7 361.3L566.7 425.3C572.7 431.3 576.1 439.4 576.1 447.9C576.1 456.4 572.7 464.5 566.7 470.5L502.7 534.5z"/></svg>
+1
zola/static/images/sort-asc.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M278.6 438.6L182.6 534.6C170.1 547.1 149.8 547.1 137.3 534.6L41.3 438.6C28.8 426.1 28.8 405.8 41.3 393.3C53.8 380.8 74.1 380.8 86.6 393.3L128 434.7L128 128C128 110.3 142.3 96 160 96C177.7 96 192 110.3 192 128L192 434.7L233.4 393.3C245.9 380.8 266.2 380.8 278.7 393.3C291.2 405.8 291.2 426.1 278.7 438.6zM352 96L384 96C401.7 96 416 110.3 416 128C416 145.7 401.7 160 384 160L352 160C334.3 160 320 145.7 320 128C320 110.3 334.3 96 352 96zM352 224L448 224C465.7 224 480 238.3 480 256C480 273.7 465.7 288 448 288L352 288C334.3 288 320 273.7 320 256C320 238.3 334.3 224 352 224zM352 352L512 352C529.7 352 544 366.3 544 384C544 401.7 529.7 416 512 416L352 416C334.3 416 320 401.7 320 384C320 366.3 334.3 352 352 352zM352 480L576 480C593.7 480 608 494.3 608 512C608 529.7 593.7 544 576 544L352 544C334.3 544 320 529.7 320 512C320 494.3 334.3 480 352 480z"/></svg>
+1
zola/static/images/sort-desc.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M278.6 438.6L182.6 534.6C170.1 547.1 149.8 547.1 137.3 534.6L41.3 438.6C28.8 426.1 28.8 405.8 41.3 393.3C53.8 380.8 74.1 380.8 86.6 393.3L128 434.7L128 128C128 110.3 142.3 96 160 96C177.7 96 192 110.3 192 128L192 434.7L233.4 393.3C245.9 380.8 266.2 380.8 278.7 393.3C291.2 405.8 291.2 426.1 278.7 438.6zM352 544C334.3 544 320 529.7 320 512C320 494.3 334.3 480 352 480L384 480C401.7 480 416 494.3 416 512C416 529.7 401.7 544 384 544L352 544zM352 416C334.3 416 320 401.7 320 384C320 366.3 334.3 352 352 352L448 352C465.7 352 480 366.3 480 384C480 401.7 465.7 416 448 416L352 416zM352 288C334.3 288 320 273.7 320 256C320 238.3 334.3 224 352 224L512 224C529.7 224 544 238.3 544 256C544 273.7 529.7 288 512 288L352 288zM352 160C334.3 160 320 145.7 320 128C320 110.3 334.3 96 352 96L576 96C593.7 96 608 110.3 608 128C608 145.7 593.7 160 576 160L352 160z"/></svg>
+1
zola/static/images/web.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M415.9 344L225 344C227.9 408.5 242.2 467.9 262.5 511.4C273.9 535.9 286.2 553.2 297.6 563.8C308.8 574.3 316.5 576 320.5 576C324.5 576 332.2 574.3 343.4 563.8C354.8 553.2 367.1 535.8 378.5 511.4C398.8 467.9 413.1 408.5 416 344zM224.9 296L415.8 296C413 231.5 398.7 172.1 378.4 128.6C367 104.2 354.7 86.8 343.3 76.2C332.1 65.7 324.4 64 320.4 64C316.4 64 308.7 65.7 297.5 76.2C286.1 86.8 273.8 104.2 262.4 128.6C242.1 172.1 227.8 231.5 224.9 296zM176.9 296C180.4 210.4 202.5 130.9 234.8 78.7C142.7 111.3 74.9 195.2 65.5 296L176.9 296zM65.5 344C74.9 444.8 142.7 528.7 234.8 561.3C202.5 509.1 180.4 429.6 176.9 344L65.5 344zM463.9 344C460.4 429.6 438.3 509.1 406 561.3C498.1 528.6 565.9 444.8 575.3 344L463.9 344zM575.3 296C565.9 195.2 498.1 111.3 406 78.7C438.3 130.9 460.4 210.4 463.9 296L575.3 296z"/></svg>
+1
zola/static/images/windows.svg
···+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M96 157.7L279.6 132.4L279.6 309.8L96 309.8L96 157.7zM96 482.3L279.6 507.6L279.6 332.4L96 332.4L96 482.3zM299.8 510.3L544 544L544 332.4L299.8 332.4L299.8 510.3zM299.8 129.7L299.8 309.8L544 309.8L544 96L299.8 129.7z"/></svg>
+2
zola/static/js/afs.modern.js
···+class t{constructor(t=!1,i="info"){this.enabled=t,this.level=i,this.levels={error:0,warn:1,info:2,debug:3}}t(t,...i){if(("error"===t||this.enabled)&&this.levels[t]<=this.levels[this.level]){const e=(new Date).toLocaleTimeString(),s=`[AFS ${t.toUpperCase()}]`;(console[t]||console.log).call(console,s,e,...i)}}error(...t){this.t("error",...t)}warn(...t){this.t("warn",...t)}info(...t){this.t("info",...t)}debug(...t){this.t("debug",...t)}setDebugMode(t,i="info"){const e=this.enabled;this.enabled=!!t,this.levels.hasOwnProperty(i)&&(this.level=i),(this.enabled||e)&&this.t("info",`Debug mode ${this.enabled?"enabled":"disabled"} with level: ${this.level}`)}getState(){return{enabled:this.enabled,level:this.level}}}class i{static defaults={containerSelector:".afs-filter-container",itemSelector:".afs-filter-item",filterButtonSelector:".afs-btn-filter",filterDropdownSelector:".afs-filter-dropdown",searchInputSelector:".afs-filter-search",counterSelector:".afs-filter-counter",sortButtonSelector:".afs-btn-sort",activeClass:"active",hiddenClass:"hidden",activeSortClass:"sort-active",transitionClass:"afs-transition",filterMode:"OR",groupMode:"AND",searchKeys:["title"],debounceTime:300,debug:!1,logLevel:"info",responsive:!0,preserveState:!1,stateExpiry:864e5,observeDOM:!1,dateFormat:"YYYY-MM-DD",counter:{template:"Showing {visible} of {total}",showFiltered:!0,filteredTemplate:"({filtered} filtered)",noResultsTemplate:"No items found",formatter(t){return t.toLocaleString()}},styles:{slider:{ui:{showHistogram:!1,bins:10,track:{radius:"0",background:"#e5e7eb"},selected:{background:"#000"},thumb:{radius:"50%",size:"16px",background:"#000"},histogram:{background:"#e5e7eb",bar:{background:"#000"}}}},pagination:{ui:{button:{background:"transparent",border:"1px solid #000",borderRadius:"4px",padding:"8px 12px",color:"#000",active:{background:"#000",color:"#fff"},hover:{background:"#000",color:"#fff"}}}},colors:{primary:"#000",background:"#e5e7eb",text:"#000",textHover:"#fff"}},slider:{containerClass:"afs-range-slider",trackClass:"afs-range-track",thumbClass:"afs-range-thumb",valueClass:"afs-range-value",selectedClass:"afs-range-selected"},pagination:{enabled:!1,itemsPerPage:10,container:".afs-pagination-container",pageButtonClass:"afs-page-button",activePageClass:"afs-page-active",containerClass:"afs-pagination",scrollToTop:!1,scrollOffset:50,scrollBehavior:"smooth"},animation:{type:"fade",duration:300,easing:"ease-out",inClass:"afs-animation-enter",outClass:"afs-animation-leave"}};constructor(t={}){this.options=this.mergeOptions(i.defaults,t),this.initializeStyles(),this.validate()}initializeStyles(){const t=i.defaults.styles,e=this.options.styles||{};this.options.styles=this.mergeOptions(t,e),this.options.styles.colors={...t.colors,...e.colors||{}}}mergeOptions(t,i){const e={...t};for(const s in i)null===i[s]||"object"!=typeof i[s]||Array.isArray(i[s])?void 0!==i[s]&&(e[s]=i[s]):(t[s]&&"object"==typeof t[s]||(e[s]={}),e[s]=this.mergeOptions(e[s],i[s]));return e}validate(){const t=["containerSelector","itemSelector"];for(const i of t)if("string"!=typeof this.options[i])throw Error(i+" must be a string");if("number"!=typeof this.options.animation?.duration||this.options.animation?.duration<0)throw Error("animation.duration must be a positive number");if(!["OR","AND"].includes(this.options.filterMode.toUpperCase()))throw Error('filterMode must be either "OR" or "AND"');if(!["OR","AND"].includes(this.options.groupMode.toUpperCase()))throw Error('groupMode must be either "OR" or "AND"');if(!Array.isArray(this.options.searchKeys)||0===this.options.searchKeys.length)throw Error("searchKeys must be a non-empty array");if(this.options.counter){if("string"!=typeof this.options.counter.template)throw Error("counter.template must be a string");"boolean"!=typeof this.options.counter.showFiltered&&(this.options.counter.showFiltered=!0),"function"!=typeof this.options.counter.formatter&&(this.options.counter.formatter=t=>t.toLocaleString())}else this.options.counter={...i.defaults.counter}}get(t){return t.split(".").reduce(((t,i)=>t?.[i]),this.options)}set(t,i){const e=t.split("."),s=e.pop();e.reduce(((t,i)=>(i in t||(t[i]={}),t[i])),this.options)[s]=i,this.validate()}update(t){this.options=this.mergeOptions(this.options,t),this.validate()}reset(){this.options={...i.defaults}}export(){return{...this.options}}}class e{constructor(){this.state={filters:{current:new Set(["*"]),groups:new Map,ranges:new Map,dateRanges:new Map,mode:"OR",groupMode:"OR"},search:{query:"",keys:["title"]},sort:{orders:{},current:null},items:{visible:new Set,total:0},pagination:{currentPage:1,itemsPerPage:10,totalPages:0}}}getState(){return this.state}setState(t,i){const e=t.split(".");let s=this.state;for(let t=0;t<e.length-1;t++)e[t]in s||(s[e[t]]={}),s=s[e[t]];s[e[e.length-1]]=i}export(){return{filters:{current:Array.from(this.state.filters.current),groups:Array.from(this.state.filters.groups.entries()),ranges:Array.from(this.state.filters.ranges.entries()),dateRanges:Array.from(this.state.filters.dateRanges.entries()),mode:this.state.filters.mode,groupMode:this.state.filters.groupMode},search:{...this.state.search},sort:{...this.state.sort},pagination:{...this.state.pagination}}}import(t){t.filters&&(this.state.filters.current=new Set(t.filters.current),this.state.filters.groups=new Map(t.filters.groups),this.state.filters.ranges=new Map(t.filters.ranges),this.state.filters.dateRanges=new Map(t.filters.dateRanges),this.state.filters.mode=t.filters.mode,this.state.filters.groupMode=t.filters.groupMode),t.search&&(this.state.search={...t.search}),t.sort&&(this.state.sort={...t.sort}),t.pagination&&(this.state.pagination={...t.pagination})}reset(){this.state={filters:{current:new Set(["*"]),groups:new Map,ranges:new Map,dateRanges:new Map,mode:"OR",groupMode:"OR"},search:{query:"",keys:["title"]},sort:{orders:{},current:null},items:{visible:new Set,total:0},pagination:{currentPage:1,itemsPerPage:10,totalPages:0}}}}class s{constructor(t){this.options=t,this.styleElement=null}createBaseStyles(){const t=this.options.get("hiddenClass")||"hidden",i=this.options.get("itemSelector")||".afs-filter-item",e=this.options.get("filterButtonSelector")||".afs-btn-filter",s=this.options.get("activeClass")||"active",n=this.options.get("animation.duration")||"300ms",r=this.options.get("animation.easing")||"ease-out",a=this.options.get("filterDropdownSelector")||".afs-filter-dropdown",o=this.options.get("styles.colors.primary")||"#000",h=this.options.get("styles.colors.background")||"#e5e7eb",c=this.options.get("styles.colors.text")||"#000",l=this.options.get("styles.colors.textHover")||"#fff",u=this.options.get("styles.button")||{},d=this.options.get("styles.dropdown")||{},p=this.options.get("styles.checkbox")||{},m=this.options.get("styles.radio")||{},f=u.padding||"4px 8px",g=d.padding||"4px 32px 4px 8px",b=u.border||"1px solid "+h,y=d.border||"1px solid "+h,w=u.borderRadius||"4px",$=d.borderRadius||"4px",v=u.fontSize||"14px",S=d.fontSize||"14px",x=u.fontFamily||"inherit",M=d.fontFamily||"inherit",F=u.fontWeight||"normal",C=d.fontWeight||"normal",R=u.lineHeight||"1.5",k=d.lineHeight||"1.5",A=u.letterSpacing||"normal",D=d.letterSpacing||"normal",P=u.textTransform||"none",T=d.textTransform||"none",I=u.boxShadow||"none",E=d.boxShadow||"none",N=u.background||"transparent",O=d.background||"transparent",L=u.color||c,z=d.color||c,U=p.border||"1px solid "+h,q=p.borderRadius||"4px",B=p.background||"transparent",H=p.color||c,Y=p.padding||"8px",_=p.height||"20px",V=p.width||"20px",j=p.activeBorder||"none",X=m.border||"1px solid "+h,G=m.borderRadius||"50%",K=m.background||"transparent",J=m.color||c,W=m.padding||"8px",Q=m.height||"20px",Z=m.width||"20px",tt=m.activeBorder||"none",it=o.match(/^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i),et=it?`rgba(${parseInt(it[1],16)}, ${parseInt(it[2],16)}, ${parseInt(it[3],16)}, 0.2)`:"rgba(0, 0, 0, 0.2)",st=`data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='${encodeURIComponent(c)}' d='M6 8L1 3h10z'/%3E%3C/svg%3E`;return`\n /* Hidden state */\n .${t} {\n display: none !important;\n }\n\n /* Filterable items */\n ${i} {\n opacity: 1;\n transform: scale(1);\n filter: blur(0);\n transition: opacity ${n} ${r},\n transform ${n} ${r},\n filter ${n} ${r};\n }\n\n ${i}.${t} {\n opacity: 0;\n transform: scale(0.95);\n filter: blur(5px);\n }\n\n /* Common styles for both buttons and dropdowns */\n ${e} {\n appearance: none;\n -webkit-appearance: none;\n padding: ${f};\n border: ${b};\n border-radius: ${w};\n font-size: ${v};\n font-family: ${x};\n font-weight: ${F};\n letter-spacing: ${A};\n text-transform: ${P};\n background-color: ${N};\n color: ${L};\n cursor: pointer;\n transition: all ${n} ${r};\n line-height: ${R};\n display: inline-flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n margin: 0;\n box-shadow: ${I};\n }\n\n ${a} {\n appearance: none;\n -webkit-appearance: none;\n padding: ${g};\n border: ${y};\n border-radius: ${$};\n font-size: ${S};\n font-family: ${M};\n font-weight: ${C};\n letter-spacing: ${D};\n text-transform: ${T};\n background-color: ${O};\n color: ${z};\n cursor: pointer;\n transition: all ${n} ${r};\n line-height: ${k};\n display: inline-flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n margin: 0;\n box-shadow: ${E};\n }\n\n /* Checkbox styles */\n ${e}[type="checkbox"] {\n position: relative;\n appearance: none;\n -webkit-appearance: none;\n padding: ${Y};\n background-color: ${B};\n color: ${H};\n border: ${U};\n border-radius: ${q};\n height: ${_};\n width: ${V};\n cursor: pointer;\n transition: all ${n} ${r};\n }\n\n ${e}[type="checkbox"]:hover:before {\n position: absolute;\n top: 0;\n left: 0;\n content: "";\n display: block;\n width: 100%;\n height: 100%;\n border-radius: ${q};\n border: ${j};\n }\n \n ${e}.${s}[type="checkbox"]:before {\n position: absolute;\n top: 0;\n left: 0;\n content: "";\n display: block;\n width: 100%;\n height: 100%;\n border-radius: ${q};\n border: ${j};\n }\n\n /* Radio button styles */\n ${e}[type="radio"] {\n position: relative;\n appearance: none;\n -webkit-appearance: none;\n padding: ${W};\n background-color: ${K};\n color: ${J};\n border: ${X};\n border-radius: ${G};\n height: ${Q};\n width: ${Z};\n cursor: pointer;\n transition: all ${n} ${r};\n }\n\n ${e}[type="radio"]:hover:before {\n position: absolute;\n top: 0;\n left: 0;\n content: "";\n display: block;\n width: 100%;\n height: 100%;\n border-radius: ${G};\n border: ${tt};\n }\n \n ${e}.${s}[type="radio"]:before {\n position: absolute;\n top: 0;\n left: 0;\n content: "";\n display: block;\n width: 100%;\n height: 100%;\n border-radius: ${G};\n border: ${tt};\n }\n\n /* Hover state */\n ${e}:hover,{\n border-color: ${o};\n background-color: ${o};\n color: ${l};\n box-shadow: ${u.hover?.boxShadow||d.hover?.boxShadow||"none"};\n }\n\n /* Focus state */\n ${e}:focus,\n ${a}:focus {\n outline: none;\n border-color: ${o};\n box-shadow: 0 0 0 2px ${et};\n }\n\n /* Active state */\n ${e}.${s} {\n background-color: ${o};\n border-color: ${o};\n color: ${l};\n box-shadow: ${u.active?.boxShadow||"none"};\n }\n\n /* Disabled state */\n ${e}:disabled,\n ${a}:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n background-color: ${h};\n }\n\n /* Dropdown specific styles */\n ${a} {\n padding: ${g};\n position: relative;\n background-image: url("${st}");\n background-repeat: no-repeat;\n background-position: right 12px center;\n text-align: left;\n }\n\n /* Mobile optimization */\n @media (max-width: 768px) {\n ${e},\n ${a} {\n width: 100%;\n justify-content: flex-start;\n }\n }\n `}addTransitionStyles(){const t=document.createElement("style");t.textContent="\n .afs-transition {\n transition: opacity 300ms ease-in-out,\n transform 300ms ease-in-out,\n filter 300ms ease-in-out !important;\n }\n .afs-hidden {\n opacity: 0;\n pointer-events: none;\n }\n ",document.head.appendChild(t)}createRangeStyles(){const t=this.options.get("styles"),i=this.options.get("slider")||{},e=t.slider,s=t.colors;return`\n /* Range Slider Styles */\n .${i.containerClass||"afs-range-slider"} {\n position: relative;\n width: auto;\n height: 40px;\n margin: 10px 0;\n padding: 0 8px;\n }\n\n .${i.trackClass||"afs-range-track"} {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n width: 100%;\n height: 4px;\n background: ${e.ui.track.background||s.background};\n border-radius: ${e.ui.track.radius||"0"};\n }\n\n .${i.thumbClass||"afs-range-thumb"} {\n position: absolute;\n top: 50%;\n width: ${e.ui.thumb.size||"16px"};\n height: ${e.ui.thumb.size||"16px"};\n background: ${e.ui.thumb.background||s.primary};\n border-radius: ${e.ui.thumb.radius||"50%"};\n transform: translate(-50%, -50%);\n cursor: pointer;\n z-index: 2;\n }\n\n .${i.valueClass||"afs-range-value"} {\n position: absolute;\n top: -20px;\n transform: translateX(-50%);\n font-size: 10px;\n color: ${s.text};\n }\n\n .${i.selectedClass||"afs-range-selected"} {\n position: absolute;\n height: 4px;\n background: ${e.ui.selected.background||s.primary};\n top: 50%;\n transform: translateY(-50%);\n }\n\n /* Histogram Styles */\n .afs-histogram {\n position: absolute;\n bottom: 22px;\n left: 8px;\n right: 8px;\n height: 20px;\n display: flex;\n align-items: flex-end;\n gap: 1px;\n opacity: 0.5;\n }\n\n .afs-histogram-bar {\n flex: 1;\n background-color: ${e.ui.histogram.background||s.background};\n min-height: 4px;\n transition: background-color 0.2s ease;\n }\n\n .afs-histogram-bar.active {\n background-color: ${e.ui.histogram.bar.background||s.primary};\n }\n `}createDateStyles(){const t=this.options.get("styles").colors;return`\n .afs-date-range-container {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin: 10px 0;\n }\n\n .afs-date-input-wrapper {\n flex: 1;\n }\n\n .afs-date-input-wrapper label {\n display: block;\n font-size: 0.875rem;\n color: ${t.text};\n margin-bottom: 0.5rem;\n }\n\n .afs-date-input {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid ${t.background};\n border-radius: 0.25rem;\n font-size: 0.875rem;\n color: ${t.text};\n transition: border-color 0.2s ease;\n }\n\n .afs-date-input:focus {\n outline: none;\n border-color: ${t.primary};\n }\n `}createInputRangeStyles(){const t=this.options.get("styles").colors;return`\n .afs-input-range-container {\n display: flex;\n flex-wrap: wrap;\n gap: 1rem;\n margin: 10px 0;\n }\n\n .afs-input-wrapper {\n flex: 1;\n }\n\n .afs-input-label {\n display: block;\n font-size: 0.875rem;\n color: ${t.text};\n margin-bottom: 0.5rem;\n }\n\n .afs-input {\n width: 100%;\n padding: 0.5rem;\n border: 1px solid ${t.background};\n border-radius: 0.25rem;\n font-size: 0.875rem;\n color: ${t.text};\n transition: border-color 0.2s ease;\n }\n\n .afs-input:focus {\n outline: none;\n border-color: ${t.primary};\n }\n `}applyStyles(){try{const t=`\n \n /* Global transition styles */\n ${this.addTransitionStyles()}\n\n /* Base styles */\n ${this.createBaseStyles()}\n\n /* Range slider styles */\n ${this.createRangeStyles()}\n\n /* Date filter styles */\n ${this.createDateStyles()}\n\n /* Pagination styles */\n ${this.createPaginationStyles()}\n\n /* Search styles */\n ${this.createSearchStyles()}\n\n /* Input range styles */\n ${this.createInputRangeStyles()}\n `;this.styleElement?this.styleElement.textContent=t:(this.styleElement=document.createElement("style"),this.styleElement.textContent=t,document.head.appendChild(this.styleElement))}catch(t){const i=this.createBaseStyles();this.styleElement?this.styleElement.textContent=i:(this.styleElement=document.createElement("style"),this.styleElement.textContent=i,document.head.appendChild(this.styleElement))}}createPaginationStyles(){const t=this.options.get("styles"),i=this.options.get("pagination")||{},e=this.options.get("styles").colors,s=i.pageButtonClass||"afs-page-button",n=t.pagination;return`\n .${i.containerClass||"afs-pagination"} {\n display: flex;\n justify-content: center;\n gap: 8px;\n margin-top: 20px;\n }\n\n .${s} {\n padding: ${n.ui.button.padding||"8px 12px"};\n border: ${n.ui.button.border||"1px solid "+e.primary};\n border-radius: ${n.ui.button.borderRadius||"4px"};\n cursor: pointer;\n transition: all 200ms ease-out;\n background: ${n.ui.button.background||"transparent"};\n color: ${n.ui.button.color||e.primary};\n }\n\n .${s}:hover {\n background: ${n.ui.button.hover.background||e.primary};\n color: ${n.ui.button.hover.color||"white"};\n }\n\n .${s}.${i.activePageClass||"afs-page-active"} {\n background: ${n.ui.button.active.background||e.primary};\n color: ${n.ui.button.active.color||"white"};\n }\n\n .${s}:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n `}createSearchStyles(){const t=this.options.get("searchInputClass")||"afs-search",i=this.options.get("styles").colors;return`\n .${t} {\n padding: 8px;\n border: 1px solid ${i.background};\n border-radius: 4px;\n width: 100%;\n max-width: 300px;\n transition: border-color 200ms ease-out;\n }\n\n .${t}:focus {\n outline: none;\n border-color: ${i.primary};\n }\n `}updateStyles(t){this.options=t,this.applyStyles()}removeStyles(){this.styleElement&&(this.styleElement.remove(),this.styleElement=null)}}class n{constructor(){this.events=new Map,this.onceEvents=new Map}on(t,i){return this.events.has(t)||this.events.set(t,new Set),this.events.get(t).add(i),()=>this.off(t,i)}once(t,i){const e=(...s)=>{this.off(t,e),i.apply(this,s)};return this.onceEvents.has(t)||this.onceEvents.set(t,new Map),this.onceEvents.get(t).set(i,e),this.on(t,e)}off(t,i){if(this.events.has(t)&&(this.events.get(t).delete(i),0===this.events.get(t).size&&this.events.delete(t)),this.onceEvents.has(t)){const e=this.onceEvents.get(t).get(i);e&&(this.events.get(t)?.delete(e),this.onceEvents.get(t).delete(i)),0===this.onceEvents.get(t).size&&this.onceEvents.delete(t)}}emit(t,...i){this.events.has(t)&&this.events.get(t).forEach((t=>{try{t.apply(this,i)}catch(t){}}))}removeAllListeners(t){t?(this.events.delete(t),this.onceEvents.delete(t)):(this.events.clear(),this.onceEvents.clear())}listenerCount(t){return(this.events.get(t)?.size||0)+(this.onceEvents.get(t)?.size||0)}}class r{constructor(t){this.afs=t,this.options=this.afs.options,this.animations={fade:{in:{opacity:1,transform:"scale(1)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"scale(0.95)",transitionTimingFunction:"ease-out"}},slide:{in:{opacity:1,transform:"translateY(0)",transitionTimingFunction:"ease-in-out"},out:{opacity:0,transform:"translateY(20px)",transitionTimingFunction:"ease-in-out"}},scale:{in:{opacity:1,transform:"scale(1)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"scale(0.8)",transitionTimingFunction:"ease-out"}},rotate:{in:{opacity:1,transform:"rotate(0deg) scale(1)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"rotate(90deg) scale(0.9)",transitionTimingFunction:"ease-out"}},flip:{in:{opacity:1,transform:"rotateY(0)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"rotateY(180deg)",transitionTimingFunction:"ease-out"}},zoom:{in:{opacity:1,transform:"scale(1.2)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"scale(0.8)",transitionTimingFunction:"ease-out"}},bounce:{in:{opacity:1,transform:"translateY(0)",animation:"bounce 1s cubic-bezier(0.68, -0.55, 0.27, 1.55)"},out:{opacity:0,transform:"translateY(-20px)",animation:"bounceOut 1s ease-out"}},blur:{in:{opacity:1,filter:"blur(0)",transitionTimingFunction:"ease-in"},out:{opacity:0,filter:"blur(5px)",transitionTimingFunction:"ease-out"}},skew:{in:{opacity:1,transform:"skew(0deg)",transitionTimingFunction:"ease-in-out"},out:{opacity:0,transform:"skew(10deg)",transitionTimingFunction:"ease-in-out"}},slideInLeft:{in:{opacity:1,transform:"translateX(0)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"translateX(-100%)",transitionTimingFunction:"ease-out"}},slideInRight:{in:{opacity:1,transform:"translateX(0)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"translateX(100%)",transitionTimingFunction:"ease-out"}},fadeInUp:{in:{opacity:1,transform:"translateY(0)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"translateY(10px)",transitionTimingFunction:"ease-out"}},fadeInDown:{in:{opacity:1,transform:"translateY(0)",transitionTimingFunction:"ease-in"},out:{opacity:0,transform:"translateY(-10px)",transitionTimingFunction:"ease-out"}},bounceIn:{in:{opacity:1,transform:"scale(1.05)",transitionTimingFunction:"cubic-bezier(0.68, -0.55, 0.27, 1.55)"},out:{opacity:0,transform:"scale(0.9)",transitionTimingFunction:"ease-out"}}}}applyShowAnimation(t,i="fade"){const e=this.animations[i]?.in||this.animations.fade.in;t.classList.add("afs-transition"),t.style.display=this.afs.filter.getItemDisplayType(t),t.style.visibility="visible",window.innerWidth<=768&&(t.style.filter="none"),requestAnimationFrame((()=>{Object.assign(t.style,{opacity:"0",transform:"scale(0.95)",display:this.afs.filter.getItemDisplayType(t)}),requestAnimationFrame((()=>{Object.assign(t.style,e)}))}));const s=this.afs.options.get("animation.duration")||300;setTimeout((()=>{window.innerWidth<=768?(t.style.transform="",t.style.opacity="1",t.style.filter="none",t.style.transition=""):this.afs.state.getState().items.visible.has(t)&&Object.assign(t.style,{transform:"",opacity:"1",filter:"none",display:this.afs.filter.getItemDisplayType(t)})}),s+50)}applyHideAnimation(t,i="fade"){const e=this.animations[i]?.out||this.animations.fade.out;t.classList.add("afs-transition"),t.style.display=this.afs.filter.getItemDisplayType(t),t.style.visibility="visible",requestAnimationFrame((()=>{Object.assign(t.style,e)}));const s=this.afs.options.get("animation.duration")||300;setTimeout((()=>{this.afs.state.getState().items.visible.has(t)||(t.style.display="none",t.style.visibility="hidden",t.style.opacity="0",t.style.transform="",t.style.filter="none",t.style.transition="")}),s+50)}updateOptions(t){const i=t.duration||300,e=t.timing||"ease-in-out",s=document.querySelector(".afs-transition");s&&(s.textContent=`\n .afs-transition {\n transition: opacity ${i}ms ${e},\n transform ${i}ms ${e},\n filter ${i}ms ${e} !important;\n }\n `)}setAnimation(t){this.animations[t]&&this.afs.options.set("animation.type",t)}}class a{constructor(t){this.afs=t,this.animation=new r(t),this.filterButtons=new Map,this.activeFilters=new Set(["*"]),this.currentFilters=new Set(["*"]),this.filterGroups=new Map,this.sortOrders=new Map,this.itemDisplayTypes=new Map,this.isScrolling=!1,this.scrollTimeout=null,this.setupFilters()}setupFilters(){this.afs.logger.debug("Setting up filters");const t=this.afs.options.get("filterButtonSelector");if(!t)return;document.querySelectorAll(t).forEach((t=>{const i=t.dataset.filter;i?(this.filterButtons.set(t,i),this.bindFilterEvent(t)):this.afs.logger.warn("Filter button missing data-filter attribute:",t)}));const i=this.afs.options.get("filterDropdownSelector");i&&document.querySelectorAll(i).forEach((t=>{this.bindDropdownEvent(t)})),this.afs.items.forEach((t=>{const i=window.getComputedStyle(t);this.itemDisplayTypes.set(t,"none"===i.display?"block":i.display)})),this.afs.logger.debug("Filters initialized")}setLogic(t){if("boolean"==typeof t)this.afs.options.set("filterMode",t?"AND":"OR");else{const i=t.toUpperCase();if(!["OR","AND"].includes(i))return void this.afs.logger.warn("Invalid filter mode: "+t);this.afs.options.set("filterMode",i)}this.afs.logger.debug("Filter logic set to: "+this.afs.options.get("filterMode")),this.applyFilters()}clearAllFilters(){this.afs.logger.debug("Clearing all filters and resetting selects"),this.activeFilters.clear(),this.activeFilters.add("*"),this.filterButtons.forEach(((t,i)=>{i.classList.remove(this.afs.options.get("activeClass"))})),this.filterGroups.clear();const t=this.findAllButton();t&&t.classList.add(this.afs.options.get("activeClass"));const i=this.afs.options.get("filterDropdownSelector")||".afs-filter-dropdown";document.querySelectorAll(i).forEach((t=>{const i=t.getAttribute("data-filter-type")||t.id.replace("Filter","").toLowerCase(),e=Array.from(t.options).find((t=>{const e=t.value;return"*"===e||e===i+":all"||e.endsWith(":all")}));if(e){t.value=e.value;const i=new Event("change",{bubbles:!0,cancelable:!0});t.dispatchEvent(i)}else{t.selectedIndex=0;const i=new Event("change",{bubbles:!0,cancelable:!0});t.dispatchEvent(i)}})),this.sortOrders.clear(),this.applyFilters(),this.afs.urlManager.updateURL(),this.afs.emit("filtersCleared"),this.afs.logger.debug("All filters cleared and selects reset")}bindDropdownEvent(t){this.afs.logger.debug("Binding filter event to dropdown:",t),t.addEventListener("change",(()=>{const i=t.value,[e]=i.split(":");"*"===i||i.endsWith(":all")||this.activeFilters.delete("*"),this.activeFilters.forEach((t=>{t.startsWith(e+":")&&this.activeFilters.delete(t)})),"*"===i||i.endsWith(":all")?0===this.activeFilters.size&&this.activeFilters.add("*"):this.activeFilters.add(i),!i&&t.options.length>0&&(t.selectedIndex=0,this.activeFilters.add(t.options[0].value)),this.applyFilters(),this.afs.urlManager.updateURL(),this.afs.emit("filterChanged",{type:e,value:i||t.options[0]?.value,activeFilters:Array.from(this.activeFilters)})}))}bindFilterEvent(t){this.afs.logger.debug("Binding filter event to button:",t),t.addEventListener("click",(()=>{const i=this.filterButtons.get(t);i&&("*"===i?this.resetFilters():this.toggleFilter(i,t),this.afs.urlManager.updateURL())}))}resetFilters(){this.afs.logger.debug("Resetting filters"),this.activeFilters.clear(),this.filterButtons.forEach(((t,i)=>{i.classList.remove(this.afs.options.get("activeClass"))})),this.activeFilters.add("*");const t=this.findAllButton();t&&t.classList.add(this.afs.options.get("activeClass")),this.filterGroups.clear();const i=[];this.afs.items.forEach((t=>{const e=new Promise((i=>{t.classList.remove(this.afs.options.get("hiddenClass")),requestAnimationFrame((()=>{this.animation.applyShowAnimation(t,this.afs.options.get("animation.type")),setTimeout(i,this.afs.options.get("animation.duration")||300)}))}));i.push(e)}));const e=new Set(this.afs.items);this.afs.state.setState("items.visible",e),Promise.all(i).then((()=>{this.afs.updateCounter(),this.afs.urlManager.updateURL(),this.afs.emit("filtersReset")}))}findAllButton(){for(const[t,i]of this.filterButtons.entries())if("*"===i)return t;return null}handleFilterClick(t){const i=t.dataset.filter;this.afs.logger.debug("Filter clicked:",i),"*"===i?this.resetFilters():this.toggleFilter(i,t),this.filter(),this.updateURL()}toggleFilter(t,i){this.activeFilters.delete("*");const e=this.findAllButton();if(e&&e.classList.remove(this.afs.options.get("activeClass")),"radio"===i.type||"radio"===i.getAttribute("type")){const e=i.name||i.getAttribute("name");e&&document.querySelectorAll(`input[name="${e}"]`).forEach((t=>{t.classList.remove(this.afs.options.get("activeClass"));const i=this.filterButtons.get(t);i&&this.activeFilters.delete(i)})),i.classList.add(this.afs.options.get("activeClass")),this.activeFilters.add(t)}else if(i.classList.contains(this.afs.options.get("activeClass"))){if(i.classList.remove(this.afs.options.get("activeClass")),this.activeFilters.delete(t),0===this.activeFilters.size)return void this.resetFilters()}else i.classList.add(this.afs.options.get("activeClass")),this.activeFilters.add(t);this.applyFilters(),this.afs.emit("filterToggled",{filter:t,activeFilters:Array.from(this.activeFilters)}),this.afs.logger.debug("Filter toggled:",t)}applyFilters(){const t=Array.from(this.activeFilters);this.afs.logger.debug("Active filters:",t);const i=new Set(this.afs.state.getState().items.visible),e=new Set;this.afs.items.forEach((t=>{(this.activeFilters.has("*")||this.itemMatchesFilters(t))&&e.add(t)})),this.afs.state.setState("items.visible",e),this.activeFilters.has("*");const s=[];this.afs.items.forEach((t=>{const i=new Promise((i=>{e.has(t)?(t.classList.remove(this.afs.options.get("hiddenClass")),t.style.display=this.getItemDisplayType(t),requestAnimationFrame((()=>{this.animation.applyShowAnimation(t,this.afs.options.get("animation.type")),setTimeout(i,parseFloat(this.afs.options.get("animation.duration"))||300)}))):(t.classList.add(this.afs.options.get("hiddenClass")),t.style.display="none",requestAnimationFrame((()=>{this.animation.applyHideAnimation(t,this.afs.options.get("animation.type")),setTimeout(i,parseFloat(this.afs.options.get("animation.duration"))||300)})))}));s.push(i)})),Promise.all(s).then((()=>{this.afs.items.forEach((t=>{e.has(t)?(this.showItem(t),t.style.display=this.getItemDisplayType(t),t.style.opacity="1"):(t.style.display="none",t.classList.add(this.afs.options.get("hiddenClass")))})),this.afs.updateCounter(),this.afs.urlManager.updateURL(),this.afs.emit("filtersApplied",{activeFilters:t,visibleItems:e.size})})),this.emitFilterEvents(i,e)}itemMatchesFilters(t){if(this.activeFilters.has("*"))return!0;const i=new Set(t.dataset.categories?.split(" ")||[]);return"AND"===(this.afs.options.get("filterMode")||"OR")?this.itemMatchesAllFilters(i):this.itemMatchesAnyFilter(i)}itemMatchesAnyFilter(t){return Array.from(this.activeFilters).some((i=>"*"===i||t.has(i)))}itemMatchesAllFilters(t){return Array.from(this.activeFilters).every((i=>"*"===i||t.has(i)))}itemMatchesFilterGroups(t){const i=Array.from(this.filterGroups.values()).map((i=>0===i.filters.size||("OR"===i.operator?Array.from(i.filters).some((i=>t.has(i))):Array.from(i.filters).every((i=>t.has(i))))));return"OR"===this.afs.options.get("groupMode")?i.some((t=>t)):i.every((t=>t))}emitFilterEvents(t,i){const e=new Set([...i].filter((i=>!t.has(i)))),s=new Set([...t].filter((t=>!i.has(t))));this.afs.emit("filter",{activeFilters:Array.from(this.activeFilters),visibleItems:i.size,added:e.size,removed:s.size}),e.size>0&&this.afs.emit("itemsShown",{items:e}),s.size>0&&this.afs.emit("itemsHidden",{items:s})}addFilterGroup(t,i,e="OR"){if(this.afs.logger.debug("Adding filter group: "+t),!Array.isArray(i))return void this.afs.logger.error("Filters must be an array");const s=e.toUpperCase();["AND","OR"].includes(s)||(this.afs.logger.warn(`Invalid operator: ${e}, defaulting to OR`),e="OR"),this.filterGroups.set(t,{filters:new Set(i),operator:s}),this.applyFilters()}removeFilterGroup(t){this.filterGroups.delete(t)&&(this.afs.logger.debug("Removed filter group: "+t),0===this.filterGroups.size?this.resetFilters():this.applyFilters())}setGroupMode(t){const i=t.toUpperCase();["AND","OR"].includes(i)?(this.afs.options.set("groupMode",i),this.afs.logger.debug("Set group mode to: "+i),this.applyFilters()):this.afs.logger.warn("Invalid group mode: "+t)}addFilter(t){if(this.afs.logger.debug("Adding filter: "+t),"*"===t)return void this.resetFilters();const[i]=t.split(":");this.activeFilters.forEach((t=>{t.startsWith(i+":")&&this.activeFilters.delete(t)})),this.activeFilters.delete("*"),this.activeFilters.add(t),this.filterButtons.forEach(((i,e)=>{i===t?e.classList.add(this.afs.options.get("activeClass")):"*"===i&&e.classList.remove(this.afs.options.get("activeClass"))})),this.applyFilters()}removeFilter(t){this.afs.logger.debug("Removing filter: "+t),this.activeFilters.delete(t),this.filterButtons.forEach(((i,e)=>{i===t&&e.classList.remove(this.afs.options.get("activeClass"))})),0===this.activeFilters.size?this.resetFilters():this.applyFilters()}setFilterMode(t){this.afs.logger.debug("Setting filter mode to: "+t);const i=t.toUpperCase();["AND","OR"].includes(i)?(this.afs.options.set("filterMode",i),this.afs.logger.debug("Set filter mode to: "+i),this.applyFilters()):this.afs.logger.warn("Invalid filter mode: "+t)}getActiveFilters(){return new Set(this.activeFilters)}getFilterGroups(){return new Map(this.filterGroups)}addFilterButton(t,i){i?(this.filterButtons.set(t,i),this.bindFilterEvent(t),this.afs.logger.debug("Added filter button for: "+i)):this.afs.logger.warn("Filter value required for new filter button")}sortWithOrder(t){this.afs.logger.debug("Sorting by "+t);try{const i=Array.from(this.afs.items),e="asc"===(this.sortOrders.get(t)||"asc")?"desc":"asc";this.sortOrders.set(t,e);const s=this.determineSortType(i[0],t);return i.sort(((i,n)=>{const r=this.getSortValue(i,t,s),a=this.getSortValue(n,t,s);return this.compareValues(r,a,e)})),this.reorderItems(i),this.afs.emit("sort",{key:t,order:e}),this.afs.logger.info(`Sorted items by ${t} in ${e} order`),e}catch(t){return this.afs.logger.error("Sort error:",t),null}}shuffle(){this.afs.logger.debug("Shuffling items");try{const t=Array.from(this.afs.items);for(let i=t.length-1;i>0;i--){const e=Math.floor(Math.random()*(i+1));[t[i],t[e]]=[t[e],t[i]]}this.reorderItems(t),this.sortOrders.clear(),this.afs.emit("shuffled",{itemCount:t.length}),this.afs.logger.debug("Items shuffled successfully")}catch(t){this.afs.logger.error("Shuffle error:",t)}}determineSortType(t,i){this.afs.logger.debug("Determining sort type for "+i);const e=t.dataset[i];return e?isNaN(e)?/^\d{4}-\d{2}-\d{2}/.test(e)?"date":"string":"number":"string"}getSortValue(t,i,e){const s=t.dataset[i];switch(e){case"number":return parseFloat(s)||0;case"date":return new Date(s).getTime()||0;default:return(s||"").toLowerCase()}}compareValues(t,i,e){if(null==t)return"asc"===e?1:-1;if(null==i)return"asc"===e?-1:1;const s=t<i?-1:t>i?1:0;return"asc"===e?s:-s}reorderItems(t){const i=document.createDocumentFragment();t.forEach((t=>i.appendChild(t))),this.afs.container.appendChild(i)}getCurrentSortOrder(t){return this.sortOrders.get(t)||"asc"}clearSortOrders(){this.afs.logger.debug("Clearing all sort orders"),this.sortOrders.clear(),this.afs.emit("sortCleared")}clearAllFilters(){this.afs.logger.debug("Clearing all filters and search"),this.activeFilters.clear(),this.activeFilters.add("*"),this.filterButtons.forEach(((t,i)=>{i.classList.remove(this.afs.options.get("activeClass"))}));const t=this.findAllButton();t&&t.classList.add(this.afs.options.get("activeClass")),document.querySelectorAll(this.afs.options.get("filterButtonSelector")+'[type="checkbox"]').forEach((t=>{t.classList.contains(this.afs.options.get("activeClass"))&&(t.checked=!1,t.classList.remove(this.afs.options.get("activeClass")))})),this.afs.search&&this.afs.search.setValue(""),this.filterGroups.clear(),this.sortOrders.clear(),this.applyFilters(),this.afs.urlManager&&this.afs.urlManager.updateURL(),this.afs.emit("filtersCleared"),this.afs.logger.info("All filters cleared")}refresh(){this.afs.logger.debug("Refreshing view"),this.applyFilters(),this.afs.updateCounter()}removeFilterButton(t){this.filterButtons.delete(t),t.removeEventListener("click",this.handleFilterClick)}destroy(){this.filterButtons.forEach(((t,i)=>{this.removeFilterButton(i)})),this.filterButtons.clear(),this.activeFilters.clear(),this.filterGroups.clear(),this.afs.logger.debug("Filter functionality destroyed")}getItemDisplayType(t){return this.itemDisplayTypes.get(t)||"block"}showItem(t){t.classList.remove(this.afs.options.get("hiddenClass"));const i=this.getItemDisplayType(t);"none"===t.style.display&&(t.style.display=i&&"none"!==i?i:""),t.style.opacity="1",t.style.visibility="visible",t.style.filter="none",t.style.transform=""}}const o=(t,i,e=!1)=>{let s;return function(...n){const r=this,a=e&&!s;clearTimeout(s),s=setTimeout((()=>{s=null,e||t.apply(r,n)}),i),a&&t.apply(r,n)}};class h{constructor(t){this.afs=t,this.activeRanges=new Map}addInputRange({key:t,container:i,min:e,max:s,step:n=1,label:r=""}){if(this.afs.logger.debug("Adding input range for "+t),!i)return void this.afs.logger.error("Container element required for input range");const a=this.calculateMinMax(t);e=e??a.min,s=s??a.max;const o=this.createInputElements(r),h=this.initializeState(e,s,n);this.appendElements(i,o),this.setupEventHandlers(o,h,t),this.activeRanges.set(t,{state:h,elements:o}),this.updateInputUI(t),this.afs.logger.info("Input range added for "+t)}calculateMinMax(t){try{const i=Array.from(this.afs.items).map((i=>{if(!i||!i.dataset||!i.dataset[t])return null;const e=parseFloat(i.dataset[t]);return isNaN(e)?null:e})).filter((t=>null!==t));return 0===i.length?{min:0,max:100}:{min:Math.min(...i),max:Math.max(...i)}}catch(t){return this.afs.logger.error("Error calculating range:",t),{min:0,max:100}}}createInputElements(t){const i=document.createElement("div");if(i.className="afs-input-range-container",t){const e=document.createElement("div");e.className="afs-input-range-label",e.textContent=t,i.appendChild(e)}const e=document.createElement("div");e.className="afs-input-wrapper";const s=document.createElement("label");s.textContent="Min",s.className="afs-input-label";const n=document.createElement("input");n.type="number",n.className="afs-input min",e.appendChild(s),e.appendChild(n);const r=document.createElement("div");r.className="afs-input-wrapper";const a=document.createElement("label");a.textContent="Max",a.className="afs-input-label";const o=document.createElement("input");return o.type="number",o.className="afs-input max",r.appendChild(a),r.appendChild(o),i.appendChild(e),i.appendChild(r),{container:i,minInput:n,maxInput:o}}initializeState(t,i,e){return{min:t,max:i,step:e,currentMin:t,currentMax:i}}appendElements(t,i){t.appendChild(i.container)}setupEventHandlers(t,i,e){const{minInput:s,maxInput:n}=t,r=o((()=>{const t=parseFloat(s.value),r=parseFloat(n.value);isNaN(t)||isNaN(r)||(i.currentMin=Math.max(i.min,Math.min(r,t)),i.currentMax=Math.min(i.max,Math.max(t,r)),this.updateInputUI(e),this.applyFilter(e))}),300);s.addEventListener("input",r),n.addEventListener("input",r)}updateInputUI(t){try{const{state:i,elements:e}=this.activeRanges.get(t),{minInput:s,maxInput:n}=e;s.min=i.min,s.max=i.max,s.step=i.step,n.min=i.min,n.max=i.max,n.step=i.step,s.value=i.currentMin,n.value=i.currentMax}catch(t){this.afs.logger.error("Error updating input UI:",t)}}applyFilter(t){this.afs.logger.info("Applying input filter for "+t);const{state:i}=this.activeRanges.get(t);this.afs.items.forEach((e=>{try{if(!e||!e.dataset||!e.dataset[t])return void this.afs.hideItem(e);const s=parseFloat(e.dataset[t]);if(isNaN(s))return void this.afs.hideItem(e);s>=i.currentMin&&s<=i.currentMax?this.afs.showItem(e):this.afs.hideItem(e)}catch(t){this.afs.logger.error("Error filtering item:",t),this.afs.hideItem(e)}})),this.afs.updateCounter(),this.afs.urlManager.updateURL(),this.afs.emit("inputRangeFilter",{key:t,min:i.currentMin,max:i.currentMax})}getRange(t){const i=this.activeRanges.get(t);return i?{min:i.state.currentMin,max:i.state.currentMax}:null}setRange(t,i,e){const s=this.activeRanges.get(t);s&&(s.state.currentMin=i,s.state.currentMax=e,this.updateInputUI(t),this.applyFilter(t))}removeInputRange(t){const i=this.activeRanges.get(t);i&&(i.elements.container.remove(),this.activeRanges.delete(t),this.afs.logger.info("Input range removed for "+t))}}class c{constructor(t){this.afs=t,this.searchInput=null,this.searchKeys=["title"],this.minSearchLength=2,this.highlightClass="afs-highlight",this.setupSearch()}setupSearch(){const t=this.afs.options.get("searchInputSelector");t&&(this.searchInput=document.querySelector(t),this.searchInput?(this.searchKeys=this.afs.options.get("searchKeys")||this.searchKeys,this.minSearchLength=this.afs.options.get("minSearchLength")||this.minSearchLength,this.bindSearchEvents(),this.afs.logger.debug("Search functionality initialized")):this.afs.logger.warn("Search input not found: "+t))}bindSearchEvents(){if(!this.searchInput)return;const t=o((t=>{this.search(t.target.value)}),this.afs.options.get("debounceTime")||300);this.searchInput.addEventListener("input",t),this.searchInput.addEventListener("search",(t=>{t.target.value||this.clearSearch()})),this.searchInput.addEventListener("keypress",(t=>{"Enter"===t.key&&(t.preventDefault(),this.search(t.target.value))}))}search(t){this.afs.logger.debug("Performing search:",t);const i=this.normalizeQuery(t);this.afs.state.setState("search.query",i);let e=0;if(i)if(i.length<this.minSearchLength)this.afs.logger.debug("Search query too short");else try{const t=this.createSearchRegex(i),s=[];this.afs.items.forEach((i=>{const n=this.getItemSearchText(i),r=t.test(n),a=new Promise((s=>{r?(this.afs.showItem(i),this.highlightMatches(i,t),e++):(this.afs.hideItem(i),this.removeHighlights(i)),setTimeout(s,this.afs.options.get("animation.duration")||300)}));s.push(a)})),Promise.all(s).then((()=>{this.afs.items.forEach((t=>{this.afs.state.getState().items.visible.has(t)?(t.style.display="",t.style.opacity="1"):t.style.display="none"})),this.afs.urlManager.updateURL(),this.afs.emit("search",{query:i,matches:e,total:this.afs.items.length}),this.afs.updateCounter(),this.afs.logger.info(`Search complete. Found ${e} matches`)}))}catch(t){this.afs.logger.error("Search error:",t)}else this.clearSearch()}normalizeQuery(t){return t.toLowerCase().trim().replace(/\s+/g," ")}createSearchRegex(t){const i=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").split(" ").filter(Boolean).map((t=>`(?=.*${t})`)).join("");return RegExp(i,"i")}getItemSearchText(t){return this.searchKeys.map((i=>t.dataset[i]||"")).join(" ").toLowerCase()}highlightMatches(t,i){this.afs.options.get("highlightMatches")&&this.searchKeys.forEach((i=>{const e=t.querySelector(`[data-search-key="${i}"]`);if(!e)return;const s=e.textContent,n=this.afs.state.getState().search.query.split(" ");let r=s;n.forEach((t=>{if(!t)return;const i=RegExp(`(${t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})`,"gi");r=r.replace(i,`<span class="${this.highlightClass}">$1</span>`)})),e.innerHTML=r}))}removeHighlights(t){this.afs.options.get("highlightMatches")&&this.searchKeys.forEach((i=>{const e=t.querySelector(`[data-search-key="${i}"]`);e&&e.querySelectorAll("."+this.highlightClass).forEach((t=>{t.replaceWith(t.textContent)}))}))}clearSearch(){this.afs.logger.debug("Clearing search"),this.searchInput&&(this.searchInput.value=""),this.afs.state.setState("search.query","");const t=[];this.afs.items.forEach((i=>{const e=new Promise((t=>{this.afs.showItem(i),this.removeHighlights(i),setTimeout(t,this.afs.options.get("animation.duration")||300)}));t.push(e)})),Promise.all(t).then((()=>{this.afs.items.forEach((t=>{t.style.display="",t.style.opacity="1"})),this.afs.urlManager.updateURL(),this.afs.emit("searchCleared"),this.afs.updateCounter()}))}setValue(t){this.searchInput&&(this.searchInput.value=t),this.search(t)}getValue(){return this.afs.state.getState().search.query}updateConfig({searchKeys:t,minSearchLength:i,highlightClass:e,debounceTime:s}={}){t&&(this.searchKeys=t),i&&(this.minSearchLength=i),e&&(this.highlightClass=e),s&&this.bindSearchEvents()}destroy(){this.searchInput&&(this.searchInput.removeEventListener("input",this.debouncedSearch),this.searchInput.removeEventListener("search",this.handleClear),this.searchInput.removeEventListener("keypress",this.handleEnter)),this.clearSearch()}}class l{constructor(t){this.afs=t,this.sortButtons=new Map,this.setupSort()}setupSort(){const t=this.afs.options.get("sortButtonSelector");if(!t)return;const i=document.querySelectorAll(t);0!==i.length?(i.forEach((t=>{const i=t.dataset.sortKey;i?(this.sortButtons.set(t,{key:i,direction:t.dataset.sortDirection||"asc"}),this.bindSortEvent(t)):this.afs.logger.warn("Sort button missing data-sort-key attribute:",t)})),this.afs.logger.debug("Sort functionality initialized")):this.afs.logger.warn("No sort buttons found with selector:",t)}bindSortEvent(t){this.afs.logger.debug("Binding sort event to button:",t),t.addEventListener("click",(()=>{const i=this.sortButtons.get(t);i&&(i.direction="asc"===i.direction?"desc":"asc",this.sortButtons.set(t,i),this.updateSortButtonState(t,i),this.sort(i.key,i.direction))}))}updateSortButtonState(t,i){this.sortButtons.forEach(((t,i)=>{i.classList.remove(this.afs.options.get("activeSortClass"))})),t.classList.add(this.afs.options.get("activeSortClass"));const e=t.querySelector(".sort-direction");e&&(e.textContent="asc"===i.direction?"↑":"↓")}sort(t,i="asc"){this.afs.logger.debug(`Sorting by ${t} in ${i} order`);try{if(!t)throw Error("Sort key is required");["asc","desc"].includes(i.toLowerCase())||(this.afs.logger.warn(`Invalid sort direction: ${i}, defaulting to "asc"`),i="asc"),this.afs.state.setState("sort.current",{key:t,direction:i});const e=Array.from(this.afs.items);if(0===e.length)return this.afs.logger.info("No items to sort"),!0;const s=this.determineSortType(e[0],t);return this.afs.logger.debug(`Determined sort type for key "${t}": ${s}`),e.sort(((e,n)=>{try{const r=this.getSortValue(e,t,s),a=this.getSortValue(n,t,s);return this.compareValues(r,a,i)}catch(t){return this.afs.logger.error("Error during sort comparison:",t),0}})),this.reorderItems(e),this.afs.urlManager.updateURL(),this.afs.emit("sort",{key:t,direction:i,sortType:s,itemCount:e.length}),this.afs.logger.info(`Sorted ${e.length} items by ${t} ${i} (${s})`),!0}catch(t){return this.afs.logger.error("Sort error:",t),!1}}determineSortType(t,i){if(!t)return this.afs.logger.warn("Cannot determine sort type: No items available for key "+i),"string";if(!t.dataset||!(i in t.dataset))return this.afs.logger.warn("Item missing dataset key: "+i,t),"string";const e=t.dataset[i];return null==e||""===e?"string":!isNaN(parseFloat(e))&&isFinite(e)?"number":/^\d{4}-\d{2}-\d{2}/.test(e)?isNaN(new Date(e).getTime())?"string":"date":"string"}getSortValue(t,i,e){if(!t)return this.afs.logger.warn("Undefined item in getSortValue"),null;if(!t.dataset||!{}.hasOwnProperty.call(t.dataset,i))return this.afs.logger.warn(`Missing data attribute: ${i} on item`,t),"number"===e||"date"===e?0:"";const s=t.dataset[i];if(null==s||""===s)return"number"===e||"date"===e?0:"";switch(e){case"number":const t=parseFloat(s);return isNaN(t)?0:t;case"date":const i=new Date(s).getTime();return isNaN(i)?0:i;default:return(s+"").toLowerCase()}}compareValues(t,i,e){const s="asc"===e?1:-1;return t===i?0:null==t?1:null==i?-1:t>i?s:-s}reorderItems(t){const i=this.afs.options.get("containerSelector"),e=document.querySelector(i);if(!e)return void this.afs.logger.error("Container not found:",i);let s=!1;for(let i=0;i<t.length-1;i++)if(!(t[i].compareDocumentPosition(t[i+1])&Node.DOCUMENT_POSITION_FOLLOWING)){s=!0;break}if(!s)return void this.afs.logger.debug("Items already in correct order, skipping DOM operations");const n=document.createDocumentFragment();t.forEach((t=>n.appendChild(t))),e.appendChild(n),this.afs.logger.debug(`Reordered ${t.length} items`)}sortMultiple(t){this.afs.logger.debug("Sorting by multiple criteria:",t);try{if(!Array.isArray(t)||0===t.length)throw Error("Sort criteria must be a non-empty array");t.forEach(((t,i)=>{if(!t.key)throw Error(`Sort criterion at index ${i} missing key property`);t.direction&&!["asc","desc"].includes(t.direction.toLowerCase())&&(this.afs.logger.warn(`Invalid sort direction in criterion ${i}: ${t.direction}, defaulting to "asc"`),t.direction="asc")}));const i=Array.from(this.afs.items);if(0===i.length)return this.afs.logger.info("No items to sort"),!0;const e={};return t.forEach((t=>{e[t.key]||(e[t.key]=this.determineSortType(i[0],t.key))})),i.sort(((i,s)=>{for(const{key:n,direction:r="asc"}of t)try{const t=e[n]||"string",a=this.getSortValue(i,n,t),o=this.getSortValue(s,n,t),h=this.compareValues(a,o,r);if(0!==h)return h}catch(t){this.afs.logger.error(`Error comparing values for key ${n}:`,t)}return 0})),this.reorderItems(i),t.length>0&&this.afs.state.setState("sort.current",t[0]),this.afs.urlManager.updateURL(),this.afs.emit("multiSort",{criteria:t,itemCount:i.length,sortTypes:e}),this.afs.logger.info(`Multi-sorted ${i.length} items with ${t.length} criteria`),!0}catch(t){return this.afs.logger.error("Multiple sort error:",t),!1}}sortWithComparator(t,i){this.afs.logger.debug(`Sorting by ${t} with custom comparator`);try{if(!t)throw Error("Sort key is required");if("function"!=typeof i)throw Error("Comparator must be a function");const e=Array.from(this.afs.items);return 0===e.length?(this.afs.logger.info("No items to sort"),!0):(e.sort(((e,s)=>{try{return e.dataset&&s.dataset&&t in e.dataset&&t in s.dataset?i(e.dataset[t],s.dataset[t]):(this.afs.logger.warn(`Missing data attribute ${t} in one or both items being compared`),0)}catch(t){return this.afs.logger.error("Error in custom comparator:",t),0}})),this.reorderItems(e),this.afs.emit("customSort",{key:t,comparatorName:i.name||"anonymous",itemCount:e.length}),this.afs.logger.info(`Custom sorted ${e.length} items by ${t}`),!0)}catch(t){return this.afs.logger.error("Custom sort error:",t),!1}}shuffle(){this.afs.logger.debug("Shuffling items");try{const t=Array.from(this.afs.items);if(0===t.length)return this.afs.logger.info("No items to shuffle"),!0;if(1===t.length)return this.afs.logger.info("Only one item to shuffle, no change needed"),!0;this.afs.logger.debug(`Shuffling ${t.length} items`);for(let i=t.length-1;i>0;i--){const e=Math.floor(Math.random()*(i+1));[t[i],t[e]]=[t[e],t[i]]}return this.reorderItems(t),this.afs.state.setState("sort.current",null),this.sortButtons.forEach(((t,i)=>{i.classList.remove(this.afs.options.get("activeSortClass"));const e=i.querySelector(".sort-direction");e&&(e.textContent="")})),this.afs.urlManager.updateURL(),this.afs.emit("shuffle",{itemCount:t.length}),this.afs.logger.info(`Shuffled ${t.length} items`),!0}catch(t){return this.afs.logger.error("Shuffle error:",t),!1}}reset(){this.afs.logger.debug("Resetting sort");try{this.afs.state.setState("sort.current",null),this.sortButtons.forEach(((t,i)=>{i.classList.remove(this.afs.options.get("activeSortClass"));const e=i.querySelector(".sort-direction");e&&(e.textContent="")}));let t=0;return this.sortButtons.forEach(((i,e)=>{i.direction="asc",this.sortButtons.set(e,i),t++})),this.afs.urlManager.updateURL(),this.afs.emit("sortReset",{buttonCount:t}),this.afs.logger.info(`Sort reset: ${t} sort buttons reset to default state`),!0}catch(t){return this.afs.logger.error("Sort reset error:",t),!1}}getCurrentSort(){return this.afs.state.getState().sort.current}addSortButton(t,i,e="asc"){i?(this.sortButtons.set(t,{key:i,direction:e}),this.bindSortEvent(t),this.afs.logger.debug("Added sort button for "+i)):this.afs.logger.warn("Sort key required for new sort button")}removeSortButton(t){this.sortButtons.has(t)&&(t.removeEventListener("click",this.bindSortEvent),this.sortButtons.delete(t),this.afs.logger.debug("Removed sort button"))}destroy(){this.sortButtons.forEach(((t,i)=>{this.removeSortButton(i)})),this.sortButtons.clear(),this.afs.logger.debug("Sort functionality destroyed")}}class u{constructor(t){this.afs=t,this.container=null,this.animation=new r(t),this.options=this.afs.options.get("pagination"),this.setupPagination()}setupPagination(){if(this.afs.logger.debug("Setting up pagination"),!this.afs.options.get("pagination.enabled"))return void this.afs.state.setState("pagination",{currentPage:1,itemsPerPage:this.options.itemsPerPage||10,totalPages:1});this.container=document.createElement("div"),this.container.className=this.options.containerClass;const t=document.querySelector(this.afs.options.get("pagination.container"));t?(t.appendChild(this.container),this.afs.state.setState("pagination",{currentPage:1,itemsPerPage:this.options.itemsPerPage,totalPages:0}),this.bindEvents(),this.update(),this.afs.logger.debug("Pagination initialized")):this.afs.logger.error("Items container not found.")}bindEvents(){this.afs.options.get("pagination.enabled")&&this.container&&(this.afs.on("filter",(()=>this.update())),this.afs.on("search",(()=>this.update())),this.afs.on("sort",(()=>this.update())),this.container.addEventListener("click",(t=>{const i=t.target.closest("button");if(!i)return;const e=i.dataset.page;e&&this.goToPage(parseInt(e,10))})))}update(){if(!this.afs.options.get("pagination.enabled"))return void this.showAllItems();const t=Array.from(this.afs.state.getState().items.visible),i=this.afs.state.getState().pagination.itemsPerPage,e=Math.max(1,Math.ceil(t.length/i)),s=this.afs.state.getState().pagination;let n=s.currentPage;n>e&&(n=e),this.afs.state.setState("pagination",{...s,currentPage:n,totalPages:e}),this.updateVisibility(t),this.container&&this.renderPagination(),this.afs.urlManager.updateURL(),this.afs.emit("pagination",{currentPage:n,totalPages:e,itemsPerPage:i,visibleItems:t.length})}updateVisibility(t){if(!this.afs.options.get("pagination.enabled"))return void this.showAllItems();const{currentPage:i,itemsPerPage:e}=this.afs.state.getState().pagination,s=(i-1)*e,n=s+e;this.afs.items.forEach((t=>{t.style.display="none",t.classList.add(this.afs.options.get("hiddenClass"))}));const r=t.slice(s,n);0===r.length&&t.length>0?this.goToPage(1):requestAnimationFrame((()=>{r.forEach((t=>{t.style.display="",t.classList.remove(this.afs.options.get("hiddenClass")),requestAnimationFrame((()=>{this.animation.applyShowAnimation(t,this.options.animationType||"fade")}))}))}))}renderPagination(){if(!this.container||!this.afs.options.get("pagination.enabled"))return;const{currentPage:t,totalPages:i}=this.afs.state.getState().pagination;if(this.container.innerHTML="",i<=1)return void(this.container.style.display="none");this.container.style.display="flex";const e=this.createPaginationControls(t,i);this.container.appendChild(e)}createPaginationControls(t,i){const e=document.createDocumentFragment();if(this.options.showPrevNext){const i=this.createPageButton("‹",t-1,{disabled:1===t,class:"afs-pagination-prev"});e.appendChild(i)}e.appendChild(this.createPageButton("1",1,{active:1===t}));const s=this.calculatePageRange(t,i);s.start>2&&e.appendChild(this.createEllipsis());for(let n=s.start;n<=s.end;n++)1!==n&&n!==i&&e.appendChild(this.createPageButton(""+n,n,{active:t===n}));if(s.end<i-1&&e.appendChild(this.createEllipsis()),i>1&&e.appendChild(this.createPageButton(""+i,i,{active:t===i})),this.options.showPrevNext){const s=this.createPageButton("›",t+1,{disabled:t===i,class:"afs-pagination-next"});e.appendChild(s)}return e}createPageButton(t,i,{active:e=!1,disabled:s=!1,class:n=""}={}){const r=document.createElement("button");return r.textContent=t,r.dataset.page=i,r.classList.add(this.options.pageButtonClass||"afs-page-button"),n&&r.classList.add(n),e&&r.classList.add(this.options.activePageClass||"afs-page-active"),s&&(r.disabled=!0),r}createEllipsis(){const t=document.createElement("span");return t.textContent="...",t.classList.add("afs-pagination-ellipsis"),t}calculatePageRange(t,i){const e=this.options.maxButtons||7;let s=Math.max(2,t-Math.floor((e-3)/2)),n=Math.min(i-1,s+e-3);return n-s<e-3&&(s=Math.max(2,n-(e-3))),{start:s,end:n}}goToPage(t){const i=this.afs.state.getState().pagination,e=Math.max(1,Math.min(t,i.totalPages));e!==i.currentPage&&(this.afs.state.setState("pagination.currentPage",e),this.update(),this.options.scrollToTop&&window.innerWidth>768&&setTimeout((()=>this.scrollToTop()),100),this.afs.emit("pageChanged",{previousPage:i.currentPage,currentPage:e,totalPages:i.totalPages}))}scrollToTop(){const t=document.querySelector(this.afs.options.get("pagination.container"));t?window.scrollTo({top:t.offsetTop-this.options.scrollOffset,behavior:"smooth"}):this.afs.logger.warn("Scroll container not found.")}setPaginationMode(t){this.afs.logger.debug("Setting pagination mode to: "+t),this.afs.options.set("pagination.enabled",t),t?this.setupPagination():(this.container.remove(),this.showAllItems()),this.afs.emit("paginationModeChanged",{enabled:t})}showAllItems(){try{const t=Array.from(this.afs.state.getState().items.visible),i=window.innerWidth<=768;requestAnimationFrame((()=>{t.forEach((t=>{t.style.display="",t.classList.remove(this.afs.options.get("hiddenClass")),i?(t.style.opacity="1",t.style.transform="",t.style.filter="none"):requestAnimationFrame((()=>{this.animation.applyShowAnimation(t,this.options?.animationType||"fade")}))})),i&&setTimeout((()=>{t.forEach((t=>{t.style.opacity="1",t.style.transform="",t.style.filter="none"}))}),50)}))}catch(t){this.afs.logger.error("Error in showAllItems:",t),this.afs.items.forEach((t=>{this.afs.state.getState().items.visible.has(t)&&(t.style.display="",t.classList.remove(this.afs.options.get("hiddenClass")),t.style.opacity="1",t.style.filter="none")}))}}}class d{constructor(t){this.afs=t,this.defaultParams=new URLSearchParams,this.setupPopStateHandler()}initialize(){this.loadFromURL()}setupPopStateHandler(){window.addEventListener("popstate",(()=>{this.loadFromURL()}))}updateURL(){this.afs.logger.debug("Updating URL state");const t=new URLSearchParams,i=this.afs.state.getState(),e=this.afs.filter.getActiveFilters();i.filters.current=e,this.addFiltersToURL(t,i),this.addRangesToURL(t,i),this.addSearchToURL(t,i),this.addSortToURL(t,i),this.addPaginationToURL(t,i),this.pushState(t)}addFiltersToURL(t,i){const e=i.filters;if(0===e.current.size||1===e.current.size&&e.current.has("*"))return;const s={};for(const t of e.current)if("*"!==t){const[i,e]=t.split(":");s[i]||(s[i]=new Set),s[i].add(e)}Object.entries(s).forEach((([i,e])=>{t.set(i,Array.from(e).join(","))})),"OR"!==e.mode&&t.set("filterMode",e.mode.toLowerCase()),e.groups.size>0&&"OR"!==e.groupMode&&t.set("groupMode",e.groupMode.toLowerCase()),e.groups.forEach(((i,e)=>{t.set("group_"+e,Array.from(i.filters).join(",")),"OR"!==i.operator&&t.set("groupOp_"+e,i.operator.toLowerCase())}))}addRangesToURL(t,i){i.filters.ranges.forEach(((i,e)=>{const{currentMin:s,currentMax:n}=i;s===i.min&&n===i.max||t.set("range_"+e,`${s},${n}`)})),i.filters.dateRanges.forEach(((i,e)=>{const{start:s,end:n}=i;t.set("dateRange_"+e,`${s.toISOString()},${n.toISOString()}`)}))}addSearchToURL(t,i){i.search.query&&t.set("search",i.search.query)}addSortToURL(t,i){if(i.sort.current){const{key:e,direction:s}=i.sort.current;t.set("sort",`${e},${s}`)}}addPaginationToURL(t,i){const{currentPage:e,itemsPerPage:s}=i.pagination;this.afs.options.get("pagination.enabled")&&(e>1&&t.set("page",""+e),s!==this.afs.options.get("pagination.itemsPerPage")&&t.set("perPage",""+s))}pushState(t){const i=""+t,e=`${window.location.pathname}${i?"?"+i:""}`;e!==window.location.href&&(window.history.pushState({},"",e),this.afs.logger.debug("URL updated:",e))}loadFromURL(){this.afs.logger.debug("Loading state from URL");const t=new URLSearchParams(window.location.search);try{this.afs.filter&&this.afs.filter.clearAllFilters();const i=t.get("filterMode");i&&this.afs.filter&&this.afs.filter.setFilterMode(i.toUpperCase());const e=Array.from(t.entries()).filter((([t])=>this.isRegularFilter(t)));e.length>0&&this.afs.filter&&(this.afs.filter.activeFilters.clear(),e.forEach((([t,i])=>{i&&i.split(",").forEach((i=>{this.afs.filter.addFilter(`${t}:${i}`)}))}))),this.afs.filter&&this.afs.filter.applyFilters(),this.processSearchFromURL(t),this.processSortFromURL(t),this.processPaginationFromURL(t),this.afs.emit("urlStateLoaded",{params:Object.fromEntries(t)}),this.afs.logger.info("State loaded from URL")}catch(t){this.afs.logger.error("Error loading state from URL:",t),this.afs.filter&&this.afs.filter.clearAllFilters()}}processFiltersFromURL(t){const i=this.afs.state.getState();let e=!1;const s=t.get("filterMode");s&&(i.filters.mode=s.toUpperCase());const n=t.get("groupMode");n&&(i.filters.groupMode=n.toUpperCase());for(const[s,n]of t.entries())this.isRegularFilter(s)&&n.split(",").filter(Boolean).forEach((t=>{e=!0,i.filters.current.add(`${s}:${t}`)}));for(const[e,s]of t.entries())if(e.startsWith("group_")){const n=e.replace("group_",""),r=t.get("groupOp_"+n)?.toUpperCase()||"OR";i.filters.groups.set(n,{filters:new Set(s.split(",")),operator:r})}e||0!==i.filters.groups.size||i.filters.current.add("*")}processRangesFromURL(t){const i=this.afs.state.getState();for(const[e,s]of t.entries())if(e.startsWith("range_")){const t=e.replace("range_",""),[n,r]=s.split(",").map(Number);i.filters.ranges.set(t,{currentMin:n,currentMax:r})}for(const[e,s]of t.entries())if(e.startsWith("dateRange_")){const t=e.replace("dateRange_",""),[n,r]=s.split(",").map((t=>new Date(t)));i.filters.dateRanges.set(t,{start:n,end:r})}}processSearchFromURL(t){const i=t.get("search")||"";this.afs.state.setState("search.query",i),this.afs.options.get("searchInput")&&(this.afs.options.get("searchInput").value=i)}processSortFromURL(t){const i=t.get("sort");if(i){const[t,e]=i.split(",");this.afs.state.setState("sort.current",{key:t,direction:e})}}processPaginationFromURL(t){const i=parseInt(t.get("page"))||1,e=parseInt(t.get("perPage"))||this.afs.options.get("pagination.itemsPerPage");this.afs.state.setState("pagination",{currentPage:i,itemsPerPage:e})}isRegularFilter(t){return!(["search","sort","page","perPage","filterMode","groupMode"].includes(t)||t.startsWith("group_")||t.startsWith("groupOp_")||t.startsWith("range_")||t.startsWith("dateRange_"))}clearURL(){window.history.pushState({},"",window.location.pathname),this.afs.state.reset(),this.afs.filter&&this.afs.filter.clearAllFilters()}getURLParams(){return new URLSearchParams(window.location.search)}hasParams(){return window.location.search.length>1}getParam(t){return new URLSearchParams(window.location.search).get(t)}}class p{constructor(t){this.afs=t,this.activeRanges=new Map,this.options=this.afs.options.get("slider"),this.afs.styleManager||(this.afs.styleManager=new s(this.afs.options)),this.afs.styleManager.applyStyles()}addRangeSlider({key:t,type:i,container:e,min:s,max:n,step:r=1,ui:a}){if(this.afs.logger.debug("Adding range slider for "+t),!e)return void this.afs.logger.error("Container element required for range slider");const o=this.calculateMinMax(t,i);s=s??o.min,n=n??o.max;const h={...this.afs.options.get("styles.slider.ui")||{showHistogram:!1,bins:10},...a},c=h.showHistogram?this.calculateHistogramData(t,h.bins):{counts:[],binEdges:[],max:0},l=this.createSliderElements(c,h),u=this.initializeState(s,n,r,i);u.ui=h,h.showHistogram&&(u.histogram=c),this.appendElements(e,l),this.setupEventHandlers(l,u,t),this.activeRanges.set(t,{state:u,elements:l}),this.updateSliderUI(t),h.showHistogram&&this.setupHistogramHighlight(l,u,c.binEdges),this.afs.logger.info("Range slider added for "+t)}calculateMinMax(t,i){const e=Array.from(this.afs.items).map((e=>{const s=e.dataset[t];return"date"===i?new Date(s).getTime():parseFloat(s)})).filter((t=>!isNaN(t)));return{min:Math.min(...e),max:Math.max(...e)}}createSliderElements(t,i){const e=(this.afs.options.get("styles")||this.afs.styleManager.defaultStyles).colors||this.afs.styleManager.defaultStyles.colors,s=this.afs.options.get("slider")||{},n=document.createElement("div");n.className="afs-range-container";const r=document.createElement("div");r.className=s.containerClass;const a=document.createElement("div");if(a.className=s.trackClass,i?.showHistogram&&t?.counts?.length>0){const i=this.createHistogramBars(t,e);r.appendChild(i)}const o=document.createElement("div");o.className=s.selectedClass;const h=document.createElement("div");h.className=s.thumbClass;const c=document.createElement("div");c.className=s.thumbClass;const l=document.createElement("div");l.className=s.valueClass;const u=document.createElement("div");return u.className=s.valueClass,r.appendChild(a),r.appendChild(o),r.appendChild(h),r.appendChild(c),r.appendChild(l),r.appendChild(u),n.appendChild(r),{container:n,slider:r,track:a,selectedRange:o,minThumb:h,maxThumb:c,minValue:l,maxValue:u}}createHistogram(t,i){const e=document.createElement("div");return e.className="afs-histogram",t.forEach(((t,s)=>{const n=document.createElement("div");n.className="afs-histogram-bar",n.style.height=t+"%",n.style.backgroundColor=i.histogram,e.appendChild(n)})),e}calculateHistogramData(t,i=10){try{const e=Array.from(this.afs.items).map((i=>parseFloat(i.dataset[t]))).filter((t=>!isNaN(t)));if(0===e.length)return{counts:[],binEdges:[],max:0};const s=Math.min(...e),n=Math.max(...e),r=(n-s)/i,a=Array(i).fill(0),o=Array(i+1);for(let t=0;t<=i;t++)o[t]=s+t*r;e.forEach((t=>{t!==n?a[Math.floor((t-s)/r)]++:a[a.length-1]++}));const h=Math.max(...a);return{counts:a.map((t=>Math.max(20,Math.round(t/h*100)))),binEdges:o,max:h,min:s,max:n}}catch(t){return this.afs.logger.error("Error calculating histogram:",t),{counts:[],binEdges:[],max:0}}}setupHistogramHighlight(t,i,e){const s=t.slider.querySelectorAll(".afs-histogram-bar"),n=()=>{const t=i.currentMin,n=i.currentMax;s.forEach(((i,s)=>{e[s]>=t&&e[s+1]<=n?i.classList.add("active"):i.classList.remove("active")}))};this.afs.on("rangeFilter",(()=>n())),n()}createHistogramBars(t,i){const{counts:e}=t,s=document.createElement("div");return s.className="afs-histogram",e.forEach((t=>{const i=document.createElement("div");i.className="afs-histogram-bar",i.style.height=t+"%",s.appendChild(i)})),s}initializeState(t,i,e,s){return{min:t,max:i,currentMin:t,currentMax:i,step:e,type:s,isDragging:!1}}appendElements(t,i){const{slider:e,track:s,selectedRange:n,minThumb:r,maxThumb:a,minValue:o,maxValue:h}=i;e.appendChild(s),e.appendChild(n),e.appendChild(r),e.appendChild(a),e.appendChild(o),e.appendChild(h),t.appendChild(e)}setupEventHandlers(t,i,e){const{minThumb:s,maxThumb:n}=t,r=s=>n=>{n.preventDefault(),i.isDragging=!0;const r=n=>{const r=(a=n).touches?a.touches[0]:a;var a;this.createMoveHandler(t,i,e,s)(r)},a=()=>{i.isDragging=!1,window.removeEventListener("mousemove",r),window.removeEventListener("mouseup",a),window.removeEventListener("touchmove",r),window.removeEventListener("touchend",a),window.removeEventListener("touchcancel",a),this.applyFilter(e)};window.addEventListener("mousemove",r),window.addEventListener("mouseup",a),window.addEventListener("touchmove",r,{passive:!1}),window.addEventListener("touchend",a),window.addEventListener("touchcancel",a)};s.addEventListener("mousedown",r(!0)),s.addEventListener("touchstart",r(!0),{passive:!1}),n.addEventListener("mousedown",r(!1)),n.addEventListener("touchstart",r(!1),{passive:!1})}updateSliderUI(t){const{state:i,elements:e}=this.activeRanges.get(t),{minThumb:s,maxThumb:n,selectedRange:r,minValue:a,maxValue:o}=e,h=i.max-i.min,c=(i.currentMax-i.min)/h*100,l=Math.max(0,Math.min((i.currentMin-i.min)/h*100,100)),u=Math.max(0,Math.min(c,100));s.style.left=l+"%",n.style.left=u+"%",r.style.left=l+"%",r.style.width=u-l+"%";const d="date"===i.type?t=>new Date(t).toLocaleDateString():t=>t.toFixed(2);a.textContent=d(i.currentMin),o.textContent=d(i.currentMax),a.style.left=l+"%",o.style.left=u+"%",a.style.transform=l<5?"translateX(0)":l>95?"translateX(-100%)":"translateX(-50%)",o.style.transform=u<5?"translateX(0)":u>95?"translateX(-100%)":"translateX(-50%)"}createMoveHandler(t,i,e,s){this.afs.logger.debug("Creating move handler for "+e);const{track:n}=t;return o((t=>{const r=t.touches?t.touches[0].clientX:t.clientX,a=n.getBoundingClientRect(),o=a.width,h=.05*o,c=Math.round((i.min+(i.max-i.min)*Math.min(Math.max(0,(r-a.left-h)/(o-2*h)),1))/i.step)*i.step;s?i.currentMin=Math.min(c,i.currentMax):i.currentMax=Math.max(c,i.currentMin),this.updateSliderUI(e)}),16)}applyFilter(t){this.afs.logger.debug("Applying range filter for "+t);const{state:i}=this.activeRanges.get(t);this.afs.items.forEach((e=>{const s="date"===i.type?new Date(e.dataset[t]).getTime():parseFloat(e.dataset[t]);s>=i.currentMin&&s<=i.currentMax?this.afs.showItem(e):this.afs.hideItem(e)})),this.afs.updateCounter(),this.afs.urlManager.updateURL(),this.afs.emit("rangeFilter",{key:t,min:i.currentMin,max:i.currentMax})}getRangeValues(t){const i=this.activeRanges.get(t);return i?{min:i.state.currentMin,max:i.state.currentMax,type:i.state.type}:null}setRangeValues(t,i,e){const s=this.activeRanges.get(t);s&&(s.state.currentMin=i,s.state.currentMax=e,this.updateSliderUI(t),this.applyFilter(t))}removeRangeSlider(t){const i=this.activeRanges.get(t);i&&(i.elements.slider.remove(),this.activeRanges.delete(t),this.afs.logger.info("Range slider removed for "+t))}}class m{constructor(t){this.afs=t,this.activeDateRanges=new Map,this.defaultFormat=this.afs.options.get("dateFormat")||"YYYY-MM-DD"}addDateRange({key:t,container:i,minDate:e,maxDate:s,format:n=this.defaultFormat}){if(this.afs.logger.debug("Adding date range for "+t),!i)return void this.afs.logger.error("Container element required for date range");const r=this.calculateMinMaxDates(t);e=e??r.min,s=s??r.max;const a=this.createDateElements(),o=this.initializeState(e,s,n);this.appendElements(i,a),this.setupEventHandlers(a,o,t),this.activeDateRanges.set(t,{state:o,elements:a}),this.updateDateUI(t),this.afs.logger.info("Date range added for "+t)}calculateMinMaxDates(t){try{const i=Array.from(this.afs.items).map((i=>{if(!i||!i.dataset||!i.dataset[t])return null;const e=new Date(i.dataset[t]);return isNaN(e.getTime())?null:e})).filter((t=>null!==t));if(0===i.length){const t=new Date;return{min:new Date(t.getFullYear(),0,1),max:new Date(t.getFullYear(),11,31)}}return{min:new Date(Math.min(...i)),max:new Date(Math.max(...i))}}catch(t){this.afs.logger.error("Error calculating date range:",t);const i=new Date;return{min:new Date(i.getFullYear(),0,1),max:new Date(i.getFullYear(),11,31)}}}createDateElements(){this.afs.logger.debug("Creating date picker elements");const t=document.createElement("div");t.className="afs-date-range-container";const i=document.createElement("div");i.className="afs-date-input-wrapper";const e=document.createElement("label");e.textContent="Start Date";const s=document.createElement("input");s.type="date",s.className="afs-date-input start-date";const n=document.createElement("div");n.className="afs-date-input-wrapper";const r=document.createElement("label");r.textContent="End Date";const a=document.createElement("input");return a.type="date",a.className="afs-date-input end-date",i.appendChild(e),i.appendChild(s),n.appendChild(r),n.appendChild(a),t.appendChild(i),t.appendChild(n),{container:t,startInput:s,endInput:a}}initializeState(t,i,e){return{minDate:t,maxDate:i,currentStartDate:t,currentEndDate:i,format:e}}appendElements(t,i){t.appendChild(i.container)}setupEventHandlers(t,i,e){this.afs.logger.debug("Setting up event handlers for date range "+e);const{startInput:s,endInput:n}=t,r=o((()=>{const t=new Date(s.value),r=new Date(n.value);isNaN(t.getTime())||isNaN(r.getTime())||(i.currentStartDate=t,i.currentEndDate=r,this.applyDateFilter(e))}),300);s.addEventListener("change",r),n.addEventListener("change",r)}updateDateUI(t){try{const{state:i,elements:e}=this.activeDateRanges.get(t),{startInput:s,endInput:n}=e,r=t=>{try{const i=new Date(t);if(isNaN(i.getTime()))throw Error("Invalid date");return i.toISOString().split("T")[0]}catch(t){return this.afs.logger.error("Error formatting date:",t),""}};s.min=r(i.minDate),s.max=r(i.maxDate),n.min=r(i.minDate),n.max=r(i.maxDate),s.value=r(i.currentStartDate),n.value=r(i.currentEndDate)}catch(t){this.afs.logger.error("Error updating date UI:",t)}}applyDateFilter(t){this.afs.logger.info("Applying date filter for "+t);const{state:i}=this.activeDateRanges.get(t);this.afs.items.forEach((e=>{try{if(!e||!e.dataset||!e.dataset[t])return void this.afs.hideItem(e);const s=new Date(e.dataset[t]);if(isNaN(s.getTime()))return void this.afs.hideItem(e);const n=new Date(i.currentStartDate);n.setHours(0,0,0,0);const r=new Date(i.currentEndDate);r.setHours(23,59,59,999);const a=new Date(s);a.setHours(0,0,0,0),a>=n&&a<=r?this.afs.showItem(e):this.afs.hideItem(e)}catch(t){this.afs.logger.error("Error filtering item by date:",t),this.afs.hideItem(e)}})),this.afs.updateCounter(),this.afs.urlManager.updateURL(),this.afs.emit("dateFilter",{key:t,startDate:i.currentStartDate,endDate:i.currentEndDate})}getDateRange(t){const i=this.activeDateRanges.get(t);return i?{startDate:i.state.currentStartDate,endDate:i.state.currentEndDate}:null}setDateRange(t,i,e){const s=this.activeDateRanges.get(t);s&&(s.state.currentStartDate=i,s.state.currentEndDate=e,this.updateDateUI(t),this.applyDateFilter(t))}removeDateRange(t){const i=this.activeDateRanges.get(t);i&&(i.elements.container.remove(),this.activeDateRanges.delete(t),this.afs.logger.info("Date range removed for "+t))}}const f="1.3.11";class g extends n{constructor(t={}){super(),this.initializeCore(t)}initializeCore(n){try{this.options=new i(n);const r=this.options.get("debug"),a=this.options.get("logLevel");this.logger=new t(r,a),this.logger.debug("Logger initialized with debug:",r,"level:",a),this.state=new e,this.styleManager=new s(this.options),this.initializeDOM(),this.initializeFeatures(),this.setupLifecycle()}catch(t){throw t}}initializeDOM(){if(this.logger.debug("Initializing DOM elements"),this.container=document.querySelector(this.options.get("containerSelector")),!this.container)throw Error("Container not found: "+this.options.get("containerSelector"));this.items=this.container.querySelectorAll(this.options.get("itemSelector")),0===this.items.length&&this.logger.warn("No items found in container"),this.state.setState("items.total",this.items.length),this.state.setState("items.visible",new Set(this.items))}initializeFeatures(){this.logger.debug("Initializing features"),this.filter=new a(this),this.search=new c(this),this.sort=new l(this),this.rangeFilter=new p(this),this.urlManager=new d(this),this.dateFilter=new m(this),this.pagination=new u(this),this.inputRangeFilter=new h(this),this.styleManager.applyStyles(),this.urlManager.initialize()}setupLifecycle(){this.options.get("responsive")&&window.addEventListener("resize",this.handleResize.bind(this)),this.options.get("preserveState")&&document.addEventListener("visibilitychange",this.handleVisibilityChange.bind(this)),this.options.get("observeDOM")&&this.setupMutationObserver(),this.emit("initialized",{itemCount:this.items.length,options:this.options.export()})}showItem(t){const i=this.state.getState().items.visible;i.add(t),this.state.setState("items.visible",i),t.classList.remove(this.options.get("hiddenClass")),t.style.opacity="0",t.style.transform="scale(0.95)",t.style.display="";const e=this.options.get("transitionClass");t.classList.contains(e)||t.classList.add(e),requestAnimationFrame((()=>{requestAnimationFrame((()=>{t.style.opacity="1",t.style.transform="scale(1)"}))}));const s=this.options.get("animation.duration")||300;setTimeout((()=>{i.has(t)&&(t.style.transform="",t.style.opacity="")}),s)}hideItem(t){const i=this.state.getState().items.visible;i.delete(t),this.state.setState("items.visible",i);const e=this.options.get("transitionClass");t.classList.contains(e)||t.classList.add(e),requestAnimationFrame((()=>{t.style.opacity="0",t.style.transform="scale(0.95)"}));const s=this.options.get("animation.duration")||300;setTimeout((()=>{i.has(t)||(t.classList.add(this.options.get("hiddenClass")),t.style.transform="",t.style.opacity="")}),s)}addItems(t){const i=Array.isArray(t)?t:[t],e=document.createDocumentFragment();i.forEach((t=>{e.appendChild(t),this.state.getState().items.visible.add(t)})),this.container.appendChild(e),this.items=this.container.querySelectorAll(this.options.get("itemSelector")),this.filter.applyFilters()}removeItems(t){const i=Array.isArray(t)?t:[t],e=this.state.getState().items.visible;i.forEach((t=>{e.delete(t),t.remove()})),this.items=this.container.querySelectorAll(this.options.get("itemSelector")),this.updateCounter()}saveState(){if(!this.options.get("preserveState"))return;const t={filters:Array.from(this.filter.getActiveFilters()),search:this.search.getValue(),sort:this.sort.getCurrentSort(),pagination:this.pagination.getPageInfo(),timestamp:Date.now()};sessionStorage.setItem("afs_state",JSON.stringify(t)),this.logger.debug("State saved")}restoreState(){if(this.options.get("preserveState"))try{const t=sessionStorage.getItem("afs_state");if(!t)return;const i=JSON.parse(t);if(Date.now()-i.timestamp>this.options.get("stateExpiry"))return void localStorage.removeItem("afs_state");this.setState(i),this.logger.debug("State restored")}catch(t){this.logger.error("Error restoring state:",t)}}getState(){return this.state.export()}setState(t){this.state.import(t),this.refresh()}updateCounter(){const t=document.querySelector(this.options.get("counterSelector"));if(t)try{const e=this.items.length,s=this.state.getState().items.visible.size,n=e-s,r=this.options.get("counter")||i.defaults.counter,a=r.template||"Showing {visible} of {total}",o=r.formatter||(t=>t.toLocaleString()),h=o(s),c=o(e),l=o(n);let u=a.replace("{visible}",h).replace("{total}",c).replace("{filtered}",l);n>0&&r.showFiltered&&(u+=" "+(r.filteredTemplate||"({filtered} filtered)").replace("{filtered}",l)),0===s&&r.noResultsTemplate&&(u=r.noResultsTemplate),t.textContent=u,this.emit("counterUpdated",{total:e,visible:s,filtered:n,formattedTotal:c,formattedVisible:h,formattedFiltered:l})}catch(i){this.logger.error("Error updating counter:",i),t.textContent=`${this.state.getState().items.visible.size}/${this.items.length}`}}updateOptions(t){this.options.update(t),this.styleManager.updateStyles(t),this.refresh()}refresh(){this.logger.debug("Refreshing AFS"),this.items=this.container.querySelectorAll(this.options.get("itemSelector")),this.state.setState("items.total",this.items.length),this.filter.applyFilters(),this.search.search(this.search.getValue()),this.options.get("pagination.enabled")&&this.pagination.update(),this.emit("refreshed",{itemCount:this.items.length})}handleResize=(()=>o((()=>{this.emit("resize")}),250))();handleVisibilityChange(){document.hidden?(this.emit("hidden"),this.saveState()):(this.emit("visible"),this.restoreState())}setupMutationObserver(){new MutationObserver((t=>{t.some((t=>"childList"===t.type))&&this.refresh()})).observe(this.container,{childList:!0,subtree:!0})}getVersion(){return f}isFeatureSupported(t){return!!{search:!!this.search,pagination:!0,animation:void 0!==document.createElement("div").style.transition,urlState:"function"==typeof window.history.pushState,localStorage:(()=>{try{return localStorage.setItem("test","test"),localStorage.removeItem("test"),!0}catch(t){return!1}})()}[t]}destroy(){this.logger.debug("Destroying AFS instance"),window.removeEventListener("resize",this.handleResize),document.removeEventListener("visibilitychange",this.handleVisibilityChange),this.filter.destroy(),this.search.destroy(),this.sort.destroy(),this.pagination.destroy(),this.rangeFilter.destroy(),this.styleManager.removeStyles(),this.state.reset(),sessionStorage.removeItem("afs_state"),this.items.forEach((t=>{t.style="",t.classList.remove(this.options.get("hiddenClass"),this.options.get("activeClass"))})),this.emit("destroyed")}}export{g as AFS,f as VERSION};
+170
zola/static/js/script.mjs
···+dates.innerHTML = `The jam is now over. It ran from <b>${startContent}</b> to <b>${endContent}</b>. <a href="submissions.html">View ${numEntries} ${numEntries !== 1 ? 'entries' : 'entry'}`+document.querySelectorAll('button.custom-sort:not([data-sort-key="shuffle"])').forEach((elt) => {+document.querySelectorAll('button.custom-sort:not([data-sort-key="'+btn.getAttribute('data-sort-key')+'"])').forEach((s) => {
+80
zola/templates/games/section.html
···+<li><button class="custom-sort" data-sort-key="date" data-sort-direction="desc"> <span class="afs-sort-direction"><img src="{{ config.base_url }}/images/sort-desc.svg" alt="Sort descending" /></span> Date</button></li>+<li><button class="custom-sort" data-sort-key="title" data-sort-direction="asc"> <span class="afs-sort-direction"><img src="{{ config.base_url }}/images/sort-asc.svg" alt="Sort descending" /></span> Title</button></li>+<li><button class="custom-sort" data-sort-key="shuffle" data-sort-direction="desc"> <span class="afs-sort-direction"><img src="{{ config.base_url }}/images/sort-desc.svg" alt="Sort descending" /></span> Random</button></li>+<li><button class="afs-btn-filter" data-filter="platforms:browser"><img src="{{ config.base_url }}/images/web.svg" alt="" class="icon" /> Play in browser</button></li>+<li><button class="afs-btn-filter" data-filter="platforms:windows"><img src="{{ config.base_url }}/images/windows.svg" alt="" class="icon" /> Windows</button></li>+<li><button class="afs-btn-filter" data-filter="platforms:macos"><img src="{{ config.base_url }}/images/macos.svg" alt="" class="icon" /> Mac OS</button></li>+<li><button class="afs-btn-filter" data-filter="platforms:linux"><img src="{{ config.base_url }}/images/linux.svg" alt="" class="icon" /> Linux</button></li>+<li><button class="afs-btn-filter" data-filter="platforms:android"><img src="{{ config.base_url }}/images/android.svg" alt="" class="icon" /> Android</button></li>+<article class="item" data-date="{{ page.date }}" data-categories="" data-title="{{ page.title }}" data-authors="{% if page.authors %}{{ page.authors | join(sep=", ") }}{% endif %}" data-platforms="">+<a href="{{ page.permalink }}"><img src="{{ page.components | join(sep="/") }}/{{ page.extra.thumbnail }}" alt="{{ page.title }} thumbnail image" /></a>
+36
zola/templates/index.html
···+<div class="dates" id="dates">Submissions open from <b id="startDate" data-raw="{{ config.extra.start_date }}">{{ config.extra.start_date | date(format="%B %d, %Y at %l:%m%P", timezone=config.extra.timezone) }}</b> to <b id="endDate" data-raw="{{ config.extra.end_date }}">{{ config.extra.end_date | date(format="%B %d, %Y at %l:%m%P", timezone=config.extra.timezone) }}</b></div>+<div class="hours"><span class="num" id="hours">#</span><span class="caption">hours</span></div>+<div class="minutes"><span class="num" id="minutes">#</span><span class="caption">minutes</span></div>+<div class="seconds"><span class="num" id="seconds">#</span><span class="caption">seconds</span></div>
+97
zola/templates/macros/macros.html
···+<span>| Posted by <a href="{{ page.extra.author.social }}" target="_blank">{{ page.extra.author.name }}</a></span>+<a href="{{ page.permalink }}"><img src="{{ page.extra.thumbnail }}" alt="{{ page.title }}" /></a>+<h2 class="title">{% if taxonomy %}{{ taxonomy.name }}{% else %}{{ page.title }}{% endif %}</h2>+Posted by <a href="{{ page.extra.author.social }}" target="_blank">{{ page.extra.author.name }}</a>+<a href="{{subpage.link}}"{% if subpage.target and subpage.target == '_blank' %} target="_blank"{% endif %}>
+62
zola/templates/page.html
···+<h2>{{ page.title }} {% if page.extra.website_link %}<a href="{{ page.extra.website_link }}" target="_blank">View game website →</a>{% endif %}</h2>+Submitted by {% if page.extra.authors %}{% for author in page.extra.authors %}{% if author.link != "" %}<a href="{{ author.link }}" target="_blank">{{ author.name }}</a>{% else %}{{ author.name }}{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% else %}Anonymous{% endif %} at <span class="submissiontime">{{ page.date | date(format="%B %d, %Y at %l:%m%P", timezone=config.extra.timezone) }}</span>+<button popovertarget="img{{ loop.index }}"><img src="{{ screenshot.url }}" alt="{{ screenshot.alt }}" /></button>+<li><a href="{{ dl.link }}" class="btn" download>Download</a> <b>{{ dl.filename }}</b> <span class="size">{{ dl.filesize }}</span> <span class="platforms"><span class="platforms-label">Platforms: </span>{% for p in dl.platforms %}<span class="icon {{ p }}" title="{{ p }}">{{ p }}</span>{% endfor %}</li>+<!-- uncomment if you want to drop in some kind of commenting system and put in whatever script you're using -->
+86
zola/templates/partials/head.html
···+<meta property="og:title" content="{% if page.title -%}{{ page.title | lower }}{% elif section.title %}{{ section.title | lower }}{% elif config.title -%}{{ config.title | lower }}{% else -%}post{% endif -%}" />+<link rel="stylesheet" type="text/css" media="screen" href="{{ config.base_url }}/style.css" />
+25
zola/templates/partials/header.html
···+<p class="hosted">Hosted by <a href="{{ config.extra.host_link }}" target="_blank">{{ config.extra.host_name }}</a> • {% if config.extra.jam_hashtag != "" %}<a href="{{ config.extra.jam_hashtag_link }}" target="_blank">#{{ config.extra.jam_hashtag }}</a>{% endif %}</p>+<li><a href="{{ config.base_url }}"{% if section and section.components | length == 0 %} class="current"{% endif %}>Overview</a></li>+<li><a href="{{ config.base_url }}/games"{% if page or (section and section.components | length > 0) %} class="current"{% endif %}>Submissions</a></li>
zola/templates/posts.html
This is a binary file and will not be displayed.
+27
zola/templates/resources/section.html
···+<a href={{ post.permalink }}><span class="date">{{ post.date }} /</span> <span class="title">{{ post.title }}</span></a>
+23
zola/templates/section.html
···+<a href={{ post.permalink }}><span class="date">{{ post.date }} /</span> <span class="title">{{ post.title }}</span></a>
+16
zola/templates/shortcodes/gallery.html
···+<a href="#gal-{% if loop.index-1 <= 0 %}{{ gallength }}{% else %}{{ loop.index-1}}{% endif %}" aria-label="Previous"><i class="fa-solid fa-arrow-left"></i></a>+<a href="#gal-{% if loop.index+1 > gallength %}1{% else %}{{ loop.index+1 }}{% endif %}" aria-label="Next"><i class="fa-solid fa-arrow-right"></i></a>
+9
zola/templates/shortcodes/links.html
+12
zola/templates/taxonomy_list.html
···+<li><a href="{{ get_taxonomy_url(kind=taxonomy.name, name=term.name) }}">{{ term.name }}</a></li>
+22
zola/templates/taxonomy_single.html
···+<a href={{ post.permalink }}><span class="date">{{ post.date }} /</span> <span class="title">{{ post.title }}</span></a>
+66
zola/theme.toml
···+joined_count_source = "manual" # options are "manual" / "airtable" / "google sheets" / "json" / "csv"