templates for self-hosting game jams (or any other kind of jam tbh)

Compare changes

Choose any two refs to compare.

Changed files
+16040 -568
_raw-assets
astro
colorthemes
hugo
jekyll
plain-html
plain-php
wordpress
zola
+20 -5
README.md
···
there is also a folder called "colorthemes" that has, well, a bunch of color themes to replace the site variables with if you want something different and don't feel inspired.
+
if you are a developer, ./assets.sh will build/copy the scss and the images to all the projects from the `_raw-assets` folder. if you're not a developer you can safely ignore all that
+
some notes for each version follow below; please make sure and read the section for whichever framework you're working with!
## plain html
···
if you don't have a local server solution already set up, you could probably use something like [simple web server](https://simplewebserver.org). it doesn't have a linux build, but i supsect if you're a linux person you can figure out how to set up a temporary simple web server with python (http.server) or node (http-server).
-
also, you will have to fiddle with JSON for game data. unless you want to just code all them manually for some reason, in which case i salute you. i recommend using [json console](https://jsonconsole.com/json-editor) if you're not down with the brackets since the table and graph views are really useful for like. checking your work
+
replace things in the template files that are surrounded by double exclamation points (!!). there are some variables to set at the top of the `js/script.mjs` file, and some style variables to set at the top of `css/style.css`. if you want to add more css, there's a `css/custom.css` file you can tack new stuff onto.
+
+
also, you will have to fiddle with JSON for game data. unless you want to just code all them manually for some reason, in which case i salute you. i recommend using [jsonswiss](https://jsonswiss.com/json-table-editor) if you're not down with the brackets since it lets you edit in table view
## plain php
···
## jekyll
-
watch this space
+
watch this space.
## astro
please note that there's a bun.lock file because i use [bun](https://bun.sh) but you do not have to. you can use npm/pnpm/yarn/deno etc it's daijoubu
+
+
uses astro collections, so data files go in src/data/games
## hugo
···
## zola
-
watch this space
+
you'll probably want to copy the contents of the "content" folder to your main content folder since they contain some useful examples for how data in the front matter "extra" section should be formatted. also, look at the `theme.toml` file for variables you'll want to override in your `config.toml`.
+
+
there's also a section for news posts if you want to use something like that to update people on jam status, post hype, etc. you can show it on the front page if you want.
## wordpress
-
watch this space
+
WIP
+
+
run `bun i` and then `bun vite build` to compile assets (or run w/ npm/pnpm/yarn/deno if you prefer; if you don't know what any of these are you are most likely to have npm)
+
+
should not need any additional plugins to run. please understand this involved me ascending to another astral plane because trying to do this in a way that's nice and friendly without Advanced Custom Fields is bananas.
+
+
wordpress uses its own database for all of this, so you don't have to deal with any markdown or json files; just look to the left sidebar in the admin panel and you'll see a section for "games." you can also optionally use wordpress to manage your signups, but you don't have to and can still collect that data from google forms or airtable or a custom data feed yourself and pipe it in.
## additional notes
···
* default favicon by [supanut piyakanont](https://thenounproject.com/creator/supanutpiyakanont/)
* filtering uses [advanced filtering system](https://misits.github.io/advanced-filter-system/) by misits
-
* fonts provided by [google fonts](https://fonts.google.com/) but if you want to move those assets local i recommend fontsquirrel's [webfont generator](https://www.fontsquirrel.com/tools/webfont-generator) to generate and optimize the font formats
+
* fonts provided by [google fonts](https://fonts.google.com/) but if you want to move those assets local i recommend fontsquirrel's [webfont generator](https://www.fontsquirrel.com/tools/webfont-generator) to generate and optimize the font formats
+
* icons from [font awesome](https://fontawesome.com)
_raw-assets/images/android-chrome-192x192.png

This is a binary file and will not be displayed.

_raw-assets/images/android-chrome-512x512.png

This is a binary file and will not be displayed.

+1
_raw-assets/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>
_raw-assets/images/apple-touch-icon.png

This is a binary file and will not be displayed.

+1
_raw-assets/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
_raw-assets/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
_raw-assets/images/favicon-16x16.png

This is a binary file and will not be displayed.

_raw-assets/images/favicon-32x32.png

This is a binary file and will not be displayed.

_raw-assets/images/favicon.ico

This is a binary file and will not be displayed.

+1
_raw-assets/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
_raw-assets/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
_raw-assets/images/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></svg>
+1
_raw-assets/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
_raw-assets/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
_raw-assets/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
_raw-assets/images/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></svg>
+1
_raw-assets/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
_raw-assets/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>
+1
_raw-assets/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></svg>
+3
_raw-assets/scss/_partials/_fonts.scss
···
+
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+116
_raw-assets/scss/_partials/_game.scss
···
+
.game {
+
main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
+
h2 {
+
margin: 0;
+
+
a {
+
font-size: .9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
}
+
+
h3 {
+
margin: 0;
+
}
+
+
.blurb {
+
margin: 1em 0;
+
}
+
+
.game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
+
.jamsub {
+
font-size: .8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
}
+
+
.screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
+
.gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
+
a, button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
& > :first-child {
+
grid-area: featured;
+
}
+
}
+
}
+
+
.interaction {
+
grid-area: stuff;
+
}
+
+
.downloads {
+
padding: 20px;
+
+
ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
+
li {
+
margin-bottom: 10px;
+
}
+
}
+
+
.size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
+
.platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
+
.icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
+
.comments {
+
border-top: 1px var(--accent) solid;
+
}
+
}
+52
_raw-assets/scss/_partials/_game_list_item.scss
···
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
+
h3 {
+
margin: 0;
+
font-size: 1.25em;
+
+
a {
+
color: var(--foreground);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.thumb {
+
position: relative;
+
padding-top: 75%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
.authors {
+
font-size: .9em;
+
margin: 5px 0;
+
+
a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.blurb {
+
margin-top: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
}
+192
_raw-assets/scss/_partials/_global.scss
···
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
+
&:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
+
&.web {
+
mask: url(../images/web.svg);
+
}
+
+
&.windows {
+
mask: url(../images/windows.svg);
+
}
+
+
&.macos {
+
mask: url(../images/macos.svg);
+
}
+
+
&.linux {
+
mask: url(../images/linux.svg);
+
}
+
+
&.android {
+
mask: url(../images/android.svg);
+
}
+
+
&.random {
+
mask: url(../images/random.svg);
+
}
+
+
&.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
+
&.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
+
.active & {
+
background-color: var(--accent);
+
}
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
+
body.wide & {
+
max-width: none;
+
margin: 0;
+
}
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
+
h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
+
.hosted {
+
margin: 0;
+
}
+
+
.joined,
+
.entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
+
.count {
+
font-size: 2.25em;
+
display: block;
+
}
+
+
.caption {
+
font-size: .8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
}
+
+
nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
+
ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
+
li {
+
a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
+
&.current,
+
&:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
}
+
}
+
}
+
}
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
+
.submissions & {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
}
+
+
footer {
+
text-align: center;
+
font-size: .8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
+
a {
+
text-decoration: none;
+
}
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0,0,0,.5);
+
}
+83
_raw-assets/scss/_partials/_homepage.scss
···
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
+
.dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
+
.countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
+
.counters {
+
display: flex;
+
align-items: stretch;
+
+
& > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
+
&:last-child {
+
border-right: none;
+
}
+
}
+
+
span {
+
display: block;
+
text-align: center;
+
+
&.num {
+
font-weight: bold;
+
}
+
+
&.caption {
+
font-size: .8em;
+
font-style: italic;
+
}
+
}
+
}
+
}
+
+
.join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
+
.joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
}
+
+
.content {
+
text-align: left;
+
}
+17
_raw-assets/scss/_partials/_posts.scss
···
+
.post-list {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
text-align: left;
+
+
h3 {
+
font-weight: normal;
+
font-size: 1em;
+
+
.date {
+
margin-left: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
}
+106
_raw-assets/scss/_partials/_submissions.scss
···
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
+
#tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
+
button {
+
white-space: pre;
+
}
+
}
+
+
details {
+
margin-bottom: 10px;
+
+
ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
}
+
+
p.label,
+
details summary {
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
+
ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
+
li {
+
button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: .9em;
+
+
img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
+
&.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
}
+
}
+
}
+
+
.afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
+
&.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
}
+
+
.afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
+
.afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: .9em;
+
}
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+13
_raw-assets/scss/_partials/_variables.scss
···
+
/* display variables! skip the images if you don't want them */
+
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
+
--headingfont: 'Knewave', 'Arial Black', sans-serif;
+
--roundedCorners: 0px;
+
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+7
_raw-assets/scss/style.scss
···
+
@use '_partials/_fonts';
+
@use '_partials/_variables';
+
@use '_partials/_global';
+
@use '_partials/_homepage';
+
@use '_partials/_submissions';
+
@use '_partials/_game_list_item';
+
@use '_partials/_game';
+68
assets.sh
···
+
#!/usr/bin/env bash
+
+
# makes sure we have up-to-date copies of the styles across all the projects
+
# because this is a use case no one is prepared for apparently, me included
+
# and now i have to build something to deal with the consequences
+
+
# copy sass for zola, jekyll, hugo, wordpress
+
cp -r _raw-assets/scss/* zola/sass/
+
cp -r _raw-assets/scss/* jekyll/_sass/
+
cp -r _raw-assets/scss/* hugo/assets/scss/
+
cat _raw-assets/scss/style.scss >> wordpress/resources/css/app.scss
+
echo "" >> wordpress/resources/css/app.scss
+
echo "@source \"../views/\";" > wordpress/resources/css/app.scss
+
echo "@source \"../../app/\";" >> wordpress/resources/css/app.scss
+
cp -r _raw-assets/scss/_partials wordpress/resources/css/
+
+
# do a bunch of regex copying of partials for astro
+
fontscss=$(cat _raw-assets/scss/_partials/_fonts.scss)
+
variablescss=$(cat _raw-assets/scss/_partials/_variables.scss)
+
globalcss=$(cat _raw-assets/scss/_partials/_global.scss)
+
layoutcontent=$(cat astro/src/layouts/Layout.astro)
+
+
homepagecss=$(cat _raw-assets/scss/_partials/_homepage.scss)
+
homepagecontent=$(cat astro/src/components/Welcome.astro)
+
submissionscss=$(cat _raw-assets/scss/_partials/_submissions.scss)
+
submissionscontent=$(cat astro/src/components/Submissions.astro)
+
gamecardcss=$(cat _raw-assets/scss/_partials/_game_list_item.scss)
+
gamecardcontent=$(cat astro/src/components/GameCard.astro)
+
+
echo "$layoutcontent" | perl -0777 -pe "s/<style lang=\"scss\">[\s\S]+$//gs" > astro/src/layouts/Layout.astro
+
echo "<style lang=\"scss\">" >> astro/src/layouts/Layout.astro
+
echo "$fontscss" >> astro/src/layouts/Layout.astro
+
echo "$variablescss" >> astro/src/layouts/Layout.astro
+
echo "$globalcss" >> astro/src/layouts/Layout.astro
+
echo "</style>" >> astro/src/layouts/Layout.astro
+
+
echo "$homepagecontent" | perl -0777 -pe "s/<style lang=\"scss\">[\s\S]+$//gs" > astro/src/components/Welcome.astro
+
echo "<style lang=\"scss\">" >> astro/src/components/Welcome.astro
+
echo "$homepagecss" >> astro/src/components/Welcome.astro
+
echo "</style>" >> astro/src/components/Welcome.astro
+
+
echo "$submissionscontent" | perl -0777 -pe "s/<style lang=\"scss\">[\s\S]+$//gs" > astro/src/components/Submissions.astro
+
echo "<style lang=\"scss\">" >> astro/src/components/Submissions.astro
+
echo "$submissionscss" >> astro/src/components/Submissions.astro
+
echo "</style>" >> astro/src/components/Submissions.astro
+
+
echo "$gamecardcontent" | perl -0777 -pe "s/<style lang=\"scss\">[\s\S]+$//gs" > astro/src/components/GameCard.astro
+
echo "<style lang=\"scss\">" >> astro/src/components/GameCard.astro
+
echo "$gamecardcss" >> astro/src/components/GameCard.astro
+
echo "</style>" >> astro/src/components/GameCard.astro
+
+
# copy assets to each project
+
cp -r _raw-assets/images/* plain-html/images/
+
cp -r _raw-assets/images/* plain-php/images/
+
cp -r _raw-assets/images/* zola/static/images/
+
cp -r _raw-assets/images/* hugo/static/images/
+
cp -r _raw-assets/images/* wordpress/resources/images/
+
cp -r _raw-assets/images/* astro/src/assets/images/
+
+
# compile assets for wordpress
+
cd wordpress
+
bun i
+
bun vite build
+
cd ../
+
+
# compile scss for plain html and php
+
sass _raw-assets/scss/style.scss plain-html/css/style.css
+
sass _raw-assets/scss/style.scss plain-php/css/style.css
+4 -1
astro/astro.config.mjs
···
import { defineConfig } from 'astro/config';
// https://astro.build/config
-
export default defineConfig({});
+
export default defineConfig({
+
site: 'https://jam.veryroundbird.house', // your site url, e.g. https://example.com
+
base: '/', // base site path, e.g. '/'
+
});
+111
astro/bun.lock
···
"dependencies": {
"astro": "^5.13.4",
},
+
"devDependencies": {
+
"sass-embedded": "^1.92.1",
+
},
},
},
"packages": {
···
"@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
"@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
+
+
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.7.0", "", {}, "sha512-qn6tAIZEw5i/wiESBF4nQxZkl86aY4KoO0IkUa2Lh+rya64oTOdJQFlZuMwI1Qz9VBJQrQC4QlSA2DNek5gCOA=="],
"@capsizecss/unpack": ["@capsizecss/unpack@2.4.0", "", { "dependencies": { "blob-to-buffer": "^1.2.8", "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" } }, "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q=="],
···
"@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="],
+
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
+
+
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="],
+
+
"@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw=="],
+
+
"@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg=="],
+
+
"@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ=="],
+
+
"@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA=="],
+
+
"@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q=="],
+
+
"@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w=="],
+
+
"@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg=="],
+
+
"@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A=="],
+
+
"@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg=="],
+
+
"@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw=="],
+
+
"@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ=="],
+
+
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
+
"@rollup/pluginutils": ["@rollup/pluginutils@5.2.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw=="],
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.49.0", "", { "os": "android", "cpu": "arm" }, "sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA=="],
···
"blob-to-buffer": ["blob-to-buffer@1.2.9", "", {}, "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA=="],
"boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="],
+
+
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="],
+
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
+
"camelcase": ["camelcase@8.0.0", "", {}, "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA=="],
"ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
···
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
+
+
"colorjs.io": ["colorjs.io@0.5.2", "", {}, "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw=="],
"comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
···
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+
"flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="],
"fontace": ["fontace@0.3.0", "", { "dependencies": { "@types/fontkit": "^2.0.8", "fontkit": "^2.0.4" } }, "sha512-czoqATrcnxgWb/nAkfyIrRp6Q8biYj7nGnL6zfhTcX+JKKpWHFBnb8uNMw/kZr7u++3Y3wYSYoZgHkCcsuBpBg=="],
···
"h3": ["h3@1.15.4", "", { "dependencies": { "cookie-es": "^1.2.2", "crossws": "^0.3.5", "defu": "^6.1.4", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.2", "radix3": "^1.1.2", "ufo": "^1.6.1", "uncrypto": "^0.1.3" } }, "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ=="],
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
"hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="],
"hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="],
···
"http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
+
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
+
"import-meta-resolve": ["import-meta-resolve@4.1.0", "", {}, "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw=="],
"iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="],
···
"is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
+
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
+
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
+
+
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
"is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
···
"micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
+
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
···
"neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
"nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="],
+
+
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
···
"rollup": ["rollup@4.49.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.49.0", "@rollup/rollup-android-arm64": "4.49.0", "@rollup/rollup-darwin-arm64": "4.49.0", "@rollup/rollup-darwin-x64": "4.49.0", "@rollup/rollup-freebsd-arm64": "4.49.0", "@rollup/rollup-freebsd-x64": "4.49.0", "@rollup/rollup-linux-arm-gnueabihf": "4.49.0", "@rollup/rollup-linux-arm-musleabihf": "4.49.0", "@rollup/rollup-linux-arm64-gnu": "4.49.0", "@rollup/rollup-linux-arm64-musl": "4.49.0", "@rollup/rollup-linux-loongarch64-gnu": "4.49.0", "@rollup/rollup-linux-ppc64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-gnu": "4.49.0", "@rollup/rollup-linux-riscv64-musl": "4.49.0", "@rollup/rollup-linux-s390x-gnu": "4.49.0", "@rollup/rollup-linux-x64-gnu": "4.49.0", "@rollup/rollup-linux-x64-musl": "4.49.0", "@rollup/rollup-win32-arm64-msvc": "4.49.0", "@rollup/rollup-win32-ia32-msvc": "4.49.0", "@rollup/rollup-win32-x64-msvc": "4.49.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA=="],
+
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
+
+
"sass": ["sass@1.92.1", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ=="],
+
+
"sass-embedded": ["sass-embedded@1.92.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-all-unknown": "1.92.1", "sass-embedded-android-arm": "1.92.1", "sass-embedded-android-arm64": "1.92.1", "sass-embedded-android-riscv64": "1.92.1", "sass-embedded-android-x64": "1.92.1", "sass-embedded-darwin-arm64": "1.92.1", "sass-embedded-darwin-x64": "1.92.1", "sass-embedded-linux-arm": "1.92.1", "sass-embedded-linux-arm64": "1.92.1", "sass-embedded-linux-musl-arm": "1.92.1", "sass-embedded-linux-musl-arm64": "1.92.1", "sass-embedded-linux-musl-riscv64": "1.92.1", "sass-embedded-linux-musl-x64": "1.92.1", "sass-embedded-linux-riscv64": "1.92.1", "sass-embedded-linux-x64": "1.92.1", "sass-embedded-unknown-all": "1.92.1", "sass-embedded-win32-arm64": "1.92.1", "sass-embedded-win32-x64": "1.92.1" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-28YwLnF5atAhogt3E4hXzz/NB9dwKffyw08a7DEasLh94P7+aELkG3ENSHYCWB9QFN14hYNLfwr9ozUsPDhcDQ=="],
+
+
"sass-embedded-all-unknown": ["sass-embedded-all-unknown@1.92.1", "", { "dependencies": { "sass": "1.92.1" }, "cpu": [ "!arm", "!x64", "!arm64", ] }, "sha512-5t6/YZf+vhO3OY/49h8RCL6Cwo78luva0M+TnTM9gu9ASffRXAuOVLNKciSXa3loptyemDDS6IU5/dVH5w0KmA=="],
+
+
"sass-embedded-android-arm": ["sass-embedded-android-arm@1.92.1", "", { "os": "android", "cpu": "arm" }, "sha512-4EjpVVzuksERdgAd4BqeSXFnWtWN3DSRyEIUPJ7BhcS9sfDh2Gf6miI2kNTvIQLJ2XIJynDDcEQ8a1U9KwKUTQ=="],
+
+
"sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.92.1", "", { "os": "android", "cpu": "arm64" }, "sha512-Q+UruGb7yKawHagVmVDRRKsnc4mJZvWMBnuRCu2coJo2FofyqBmXohVGXbxko97sYceA9TJTrUEx3WVKQUNCbQ=="],
+
+
"sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.92.1", "", { "os": "android", "cpu": "none" }, "sha512-nCY5btLlX7W7Jc6cCL6D2Yklpiu540EJ2G08YVGu12DrAMCBzqM347CSRf2ojp1H8jyhvmLkaFwnrJWzh+6S+w=="],
+
+
"sass-embedded-android-x64": ["sass-embedded-android-x64@1.92.1", "", { "os": "android", "cpu": "x64" }, "sha512-qYWR3bftJ77aLYwYDFuzDI4dcwVVixxqQxlIQWNGkHRCexj614qGSSHemr18C2eVj3mjXAQxTQxU68U7pkGPAA=="],
+
+
"sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.92.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-g2yQ3txjMYLKMjL2cW1xRO9nnV3ijf95NbX/QShtV6tiVUETZNWDsRMDEwBNGYY6PTE/UZerjJL1R/2xpQg6WA=="],
+
+
"sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.92.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-eH+fgxLQhTEPjZPCgPAVuX5e514Qp/4DMAUMtlNShv4cr4TD5qOp1XlsPYR/b7uE7p2cKFkUpUn/bHNqJ2ay4A=="],
+
+
"sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.92.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cT3w8yoQTqrtZvWLJeutEGmawITDTY4J6oSVQjeDcPnnoPt0gOFxem8YMznraACXvahw/2+KJDH33BTNgiPo0A=="],
+
+
"sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.92.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-dNmlpGeZkry1BofhAdGFBXrpM69y9LlYuNnncf+HfsOOUtj8j0q1RwS+zb5asknhKFUOAG8GCGRY1df7Rwu35g=="],
+
+
"sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.92.1", "", { "os": "linux", "cpu": "arm" }, "sha512-nPBos6lI31ef2zQhqTZhFOU7ar4impJbLIax0XsqS269YsiCwjhk11VmUloJTpFlJuKMiVXNo7dPx+katxhD/Q=="],
+
+
"sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.92.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-TfiEBkCyNzVoOhjHXUT+vZ6+p0ueDbvRw6f4jHdkvljZzXdXMby4wh7BU1odl69rgRTkSvYKhgbErRLDR/F7pQ=="],
+
+
"sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.92.1", "", { "os": "linux", "cpu": "none" }, "sha512-R+RcJA4EYpJDE9JM1GgPYgZo7x94FlxZ6jPodOQkEaZ1S9kvXVCuP5X/0PXRPhu08KJOfeMsAElzfdAjUf7KJg=="],
+
+
"sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.92.1", "", { "os": "linux", "cpu": "x64" }, "sha512-/HolYRGXJjx8nLw6oj5ZrkR7PFM7X/5kE4MYZaFMpDIPIcw3bqB2fUXLo/MYlRLsw7gBAT6hJAMBrNdKuTphfw=="],
+
+
"sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.92.1", "", { "os": "linux", "cpu": "none" }, "sha512-b9bxe0CMsbSsLx3nrR0cq8xpIkoAC6X36o4DGMITF3m2v3KsojC7ru9X0Gz+zUFr6rwpq/0lTNzFLNu6sPNo3w=="],
+
+
"sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.92.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xuiK5Jp5NldW4bvlC7AuX1Wf7o0gLZ3md/hNg+bkTvxtCDgnUHtfdo8Q+xWP11bD9QX31xXFWpmUB8UDLi6XQQ=="],
+
+
"sass-embedded-unknown-all": ["sass-embedded-unknown-all@1.92.1", "", { "dependencies": { "sass": "1.92.1" }, "os": [ "!linux", "!win32", "!darwin", "!android", ] }, "sha512-AT9oXvtNY4N+Nd0wvoWqq9A5HjdH/X3aUH4boQUtXyaJ/9DUwnQmBpP5Gtn028ZS8exOGBdobmmWAuigv0k/OA=="],
+
+
"sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.92.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-KvmpQjY9yTBMtTYz4WBqetlv9bGaDW1aStcu7MSTbH7YiSybX/9fnxlCAEQv1WlIidQhcJAiyk0Eae+LGK7cIQ=="],
+
+
"sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.92.1", "", { "os": "win32", "cpu": "x64" }, "sha512-B6Nz/GbH7Vkpb2TkQHsGcczWM5t+70VWopWF1x5V5yxLpA8ZzVQ7NTKKi+jDoVY2Efu6ZyzgT9n5KgG2kWliXA=="],
+
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
···
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
+
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+
+
"sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="],
+
+
"sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="],
+
"tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="],
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
+
+
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
···
"unstorage": ["unstorage@1.17.0", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^4.0.3", "destr": "^2.0.5", "h3": "^1.15.4", "lru-cache": "^10.4.3", "node-fetch-native": "^1.6.7", "ofetch": "^1.4.1", "ufo": "^1.6.1" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6.0.3 || ^7.0.0", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12", "@vercel/kv": "^1.0.1", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-l9Z7lBiwtNp8ZmcoZ/dmPkFXFdtEdZtTZafCSnEIj3YvtkXeGAtL2rN8MQFy/0cs4eOLpuRJMp9ivdug7TCvww=="],
+
"varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="],
+
"vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
"vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
···
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
+
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
+
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
···
"anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
+
+
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
+21
astro/content.config.ts
···
+
import { z, defineCollection } from 'astro:content';
+
import { glob } from 'astro/loaders';
+
+
const games = defineCollection({
+
loader: glob({ pattern: '**/*.md', base: './src/data/games' }),
+
schema: z.object({
+
title: z.string(),
+
date: z.date(),
+
externalLink: z.httpUrl().optional(),
+
description: z.string().optional(),
+
authors: z.array(z.object()).optional(),
+
downloads: z.array(z.object()),
+
screenshots: z.array(z.file()).optional(),
+
permalink: z.string().optional(),
+
platforms: z.array(z.string())
+
}),
+
});
+
+
// Expose your defined collection to Astro
+
// with the `collections` export
+
export const collections = { games };
+3
astro/package.json
···
},
"dependencies": {
"astro": "^5.13.4"
+
},
+
"devDependencies": {
+
"sass-embedded": "^1.92.1"
}
}
-1
astro/src/assets/astro.svg
···
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="115" height="48"><path fill="#17191E" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="url(#a)" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="#17191E" d="M.02 30.31s4.02-1.95 8.05-1.95l3.04-9.4c.11-.45.44-.76.82-.76.37 0 .7.31.82.76l3.04 9.4c4.77 0 8.05 1.95 8.05 1.95L17 11.71c-.2-.56-.53-.91-.98-.91H7.83c-.44 0-.76.35-.97.9L.02 30.31Zm42.37-5.97c0 1.64-2.05 2.62-4.88 2.62-1.85 0-2.5-.45-2.5-1.41 0-1 .8-1.49 2.65-1.49 1.67 0 3.09.03 4.73.23v.05Zm.03-2.04a21.37 21.37 0 0 0-4.37-.36c-5.32 0-7.82 1.25-7.82 4.18 0 3.04 1.71 4.2 5.68 4.2 3.35 0 5.63-.84 6.46-2.92h.14c-.03.5-.05 1-.05 1.4 0 1.07.18 1.16 1.06 1.16h4.15a16.9 16.9 0 0 1-.36-4c0-1.67.06-2.93.06-4.62 0-3.45-2.07-5.64-8.56-5.64-2.8 0-5.9.48-8.26 1.19.22.93.54 2.83.7 4.06 2.04-.96 4.95-1.37 7.2-1.37 3.11 0 3.97.71 3.97 2.15v.57Zm11.37 3c-.56.07-1.33.07-2.12.07-.83 0-1.6-.03-2.12-.1l-.02.58c0 2.85 1.87 4.52 8.45 4.52 6.2 0 8.2-1.64 8.2-4.55 0-2.74-1.33-4.09-7.2-4.39-4.58-.2-4.99-.7-4.99-1.28 0-.66.59-1 3.65-1 3.18 0 4.03.43 4.03 1.35v.2a46.13 46.13 0 0 1 4.24.03l.02-.55c0-3.36-2.8-4.46-8.2-4.46-6.08 0-8.13 1.49-8.13 4.39 0 2.6 1.64 4.23 7.48 4.48 4.3.14 4.77.62 4.77 1.28 0 .7-.7 1.03-3.71 1.03-3.47 0-4.35-.48-4.35-1.47v-.13Zm19.82-12.05a17.5 17.5 0 0 1-6.24 3.48c.03.84.03 2.4.03 3.24l1.5.02c-.02 1.63-.04 3.6-.04 4.9 0 3.04 1.6 5.32 6.58 5.32 2.1 0 3.5-.23 5.23-.6a43.77 43.77 0 0 1-.46-4.13c-1.03.34-2.34.53-3.78.53-2 0-2.82-.55-2.82-2.13 0-1.37 0-2.65.03-3.84 2.57.02 5.13.07 6.64.11-.02-1.18.03-2.9.1-4.04-2.2.04-4.65.07-6.68.07l.07-2.93h-.16Zm13.46 6.04a767.33 767.33 0 0 1 .07-3.18H82.6c.07 1.96.07 3.98.07 6.92 0 2.95-.03 4.99-.07 6.93h5.18c-.09-1.37-.11-3.68-.11-5.65 0-3.1 1.26-4 4.12-4 1.33 0 2.28.16 3.1.46.03-1.16.26-3.43.4-4.43-.86-.25-1.81-.41-2.96-.41-2.46-.03-4.26.98-5.1 3.38l-.17-.02Zm22.55 3.65c0 2.5-1.8 3.66-4.64 3.66-2.81 0-4.61-1.1-4.61-3.66s1.82-3.52 4.61-3.52c2.82 0 4.64 1.03 4.64 3.52Zm4.71-.11c0-4.96-3.87-7.18-9.35-7.18-5.5 0-9.23 2.22-9.23 7.18 0 4.94 3.49 7.59 9.21 7.59 5.77 0 9.37-2.65 9.37-7.6Z"/><defs><linearGradient id="a" x1="6.33" x2="19.43" y1="40.8" y2="34.6" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient></defs></svg>
-1
astro/src/assets/background.svg
···
-
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1024" fill="none"><path fill="url(#a)" fill-rule="evenodd" d="M-217.58 475.75c91.82-72.02 225.52-29.38 341.2-44.74C240 415.56 372.33 315.14 466.77 384.9c102.9 76.02 44.74 246.76 90.31 366.31 29.83 78.24 90.48 136.14 129.48 210.23 57.92 109.99 169.67 208.23 155.9 331.77-13.52 121.26-103.42 264.33-224.23 281.37-141.96 20.03-232.72-220.96-374.06-196.99-151.7 25.73-172.68 330.24-325.85 315.72-128.6-12.2-110.9-230.73-128.15-358.76-12.16-90.14 65.87-176.25 44.1-264.57-26.42-107.2-167.12-163.46-176.72-273.45-10.15-116.29 33.01-248.75 124.87-320.79Z" clip-rule="evenodd" style="opacity:.154"/><path fill="url(#b)" fill-rule="evenodd" d="M1103.43 115.43c146.42-19.45 275.33-155.84 413.5-103.59 188.09 71.13 409 212.64 407.06 413.88-1.94 201.25-259.28 278.6-414.96 405.96-130 106.35-240.24 294.39-405.6 265.3-163.7-28.8-161.93-274.12-284.34-386.66-134.95-124.06-436-101.46-445.82-284.6-9.68-180.38 247.41-246.3 413.54-316.9 101.01-42.93 207.83 21.06 316.62 6.61Z" clip-rule="evenodd" style="opacity:.154"/><defs><linearGradient id="b" x1="373" x2="1995.44" y1="1100" y2="118.03" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient><linearGradient id="a" x1="107.37" x2="1130.66" y1="1993.35" y2="1026.31" gradientUnits="userSpaceOnUse"><stop stop-color="#3245FF"/><stop offset="1" stop-color="#BC52EE"/></linearGradient></defs></svg>
astro/src/assets/images/android-chrome-192x192.png

This is a binary file and will not be displayed.

astro/src/assets/images/android-chrome-512x512.png

This is a binary file and will not be displayed.

+1
astro/src/assets/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>
astro/src/assets/images/apple-touch-icon.png

This is a binary file and will not be displayed.

+1
astro/src/assets/images/astro.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="115" height="48"><path fill="#17191E" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="url(#a)" d="M7.77 36.35C6.4 35.11 6 32.51 6.57 30.62c.99 1.2 2.35 1.57 3.75 1.78 2.18.33 4.31.2 6.33-.78.23-.12.44-.27.7-.42.18.55.23 1.1.17 1.67a4.56 4.56 0 0 1-1.94 3.23c-.43.32-.9.61-1.34.91-1.38.94-1.76 2.03-1.24 3.62l.05.17a3.63 3.63 0 0 1-1.6-1.38 3.87 3.87 0 0 1-.63-2.1c0-.37 0-.74-.05-1.1-.13-.9-.55-1.3-1.33-1.32a1.56 1.56 0 0 0-1.63 1.26c0 .06-.03.12-.05.2Z"/><path fill="#17191E" d="M.02 30.31s4.02-1.95 8.05-1.95l3.04-9.4c.11-.45.44-.76.82-.76.37 0 .7.31.82.76l3.04 9.4c4.77 0 8.05 1.95 8.05 1.95L17 11.71c-.2-.56-.53-.91-.98-.91H7.83c-.44 0-.76.35-.97.9L.02 30.31Zm42.37-5.97c0 1.64-2.05 2.62-4.88 2.62-1.85 0-2.5-.45-2.5-1.41 0-1 .8-1.49 2.65-1.49 1.67 0 3.09.03 4.73.23v.05Zm.03-2.04a21.37 21.37 0 0 0-4.37-.36c-5.32 0-7.82 1.25-7.82 4.18 0 3.04 1.71 4.2 5.68 4.2 3.35 0 5.63-.84 6.46-2.92h.14c-.03.5-.05 1-.05 1.4 0 1.07.18 1.16 1.06 1.16h4.15a16.9 16.9 0 0 1-.36-4c0-1.67.06-2.93.06-4.62 0-3.45-2.07-5.64-8.56-5.64-2.8 0-5.9.48-8.26 1.19.22.93.54 2.83.7 4.06 2.04-.96 4.95-1.37 7.2-1.37 3.11 0 3.97.71 3.97 2.15v.57Zm11.37 3c-.56.07-1.33.07-2.12.07-.83 0-1.6-.03-2.12-.1l-.02.58c0 2.85 1.87 4.52 8.45 4.52 6.2 0 8.2-1.64 8.2-4.55 0-2.74-1.33-4.09-7.2-4.39-4.58-.2-4.99-.7-4.99-1.28 0-.66.59-1 3.65-1 3.18 0 4.03.43 4.03 1.35v.2a46.13 46.13 0 0 1 4.24.03l.02-.55c0-3.36-2.8-4.46-8.2-4.46-6.08 0-8.13 1.49-8.13 4.39 0 2.6 1.64 4.23 7.48 4.48 4.3.14 4.77.62 4.77 1.28 0 .7-.7 1.03-3.71 1.03-3.47 0-4.35-.48-4.35-1.47v-.13Zm19.82-12.05a17.5 17.5 0 0 1-6.24 3.48c.03.84.03 2.4.03 3.24l1.5.02c-.02 1.63-.04 3.6-.04 4.9 0 3.04 1.6 5.32 6.58 5.32 2.1 0 3.5-.23 5.23-.6a43.77 43.77 0 0 1-.46-4.13c-1.03.34-2.34.53-3.78.53-2 0-2.82-.55-2.82-2.13 0-1.37 0-2.65.03-3.84 2.57.02 5.13.07 6.64.11-.02-1.18.03-2.9.1-4.04-2.2.04-4.65.07-6.68.07l.07-2.93h-.16Zm13.46 6.04a767.33 767.33 0 0 1 .07-3.18H82.6c.07 1.96.07 3.98.07 6.92 0 2.95-.03 4.99-.07 6.93h5.18c-.09-1.37-.11-3.68-.11-5.65 0-3.1 1.26-4 4.12-4 1.33 0 2.28.16 3.1.46.03-1.16.26-3.43.4-4.43-.86-.25-1.81-.41-2.96-.41-2.46-.03-4.26.98-5.1 3.38l-.17-.02Zm22.55 3.65c0 2.5-1.8 3.66-4.64 3.66-2.81 0-4.61-1.1-4.61-3.66s1.82-3.52 4.61-3.52c2.82 0 4.64 1.03 4.64 3.52Zm4.71-.11c0-4.96-3.87-7.18-9.35-7.18-5.5 0-9.23 2.22-9.23 7.18 0 4.94 3.49 7.59 9.21 7.59 5.77 0 9.37-2.65 9.37-7.6Z"/><defs><linearGradient id="a" x1="6.33" x2="19.43" y1="40.8" y2="34.6" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient></defs></svg>
+1
astro/src/assets/images/background.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" width="1440" height="1024" fill="none"><path fill="url(#a)" fill-rule="evenodd" d="M-217.58 475.75c91.82-72.02 225.52-29.38 341.2-44.74C240 415.56 372.33 315.14 466.77 384.9c102.9 76.02 44.74 246.76 90.31 366.31 29.83 78.24 90.48 136.14 129.48 210.23 57.92 109.99 169.67 208.23 155.9 331.77-13.52 121.26-103.42 264.33-224.23 281.37-141.96 20.03-232.72-220.96-374.06-196.99-151.7 25.73-172.68 330.24-325.85 315.72-128.6-12.2-110.9-230.73-128.15-358.76-12.16-90.14 65.87-176.25 44.1-264.57-26.42-107.2-167.12-163.46-176.72-273.45-10.15-116.29 33.01-248.75 124.87-320.79Z" clip-rule="evenodd" style="opacity:.154"/><path fill="url(#b)" fill-rule="evenodd" d="M1103.43 115.43c146.42-19.45 275.33-155.84 413.5-103.59 188.09 71.13 409 212.64 407.06 413.88-1.94 201.25-259.28 278.6-414.96 405.96-130 106.35-240.24 294.39-405.6 265.3-163.7-28.8-161.93-274.12-284.34-386.66-134.95-124.06-436-101.46-445.82-284.6-9.68-180.38 247.41-246.3 413.54-316.9 101.01-42.93 207.83 21.06 316.62 6.61Z" clip-rule="evenodd" style="opacity:.154"/><defs><linearGradient id="b" x1="373" x2="1995.44" y1="1100" y2="118.03" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient><linearGradient id="a" x1="107.37" x2="1130.66" y1="1993.35" y2="1026.31" gradientUnits="userSpaceOnUse"><stop stop-color="#3245FF"/><stop offset="1" stop-color="#BC52EE"/></linearGradient></defs></svg>
+1
astro/src/assets/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
astro/src/assets/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
astro/src/assets/images/favicon-16x16.png

This is a binary file and will not be displayed.

astro/src/assets/images/favicon-32x32.png

This is a binary file and will not be displayed.

astro/src/assets/images/favicon.ico

This is a binary file and will not be displayed.

+1
astro/src/assets/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
astro/src/assets/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
astro/src/assets/images/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></svg>
+1
astro/src/assets/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
astro/src/assets/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
astro/src/assets/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
astro/src/assets/images/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></svg>
+1
astro/src/assets/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
astro/src/assets/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>
+1
astro/src/assets/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></svg>
+76
astro/src/components/GameCard.astro
···
+
---
+
const { game } = Astro.props;
+
---
+
<article class="item" data-date="{ game.date }" data-categories="" data-title="{ game.title }" data-authors={ game.authors.map(a => a.name).join(", ") }>
+
<div class="thumb">
+
<a href="/games/{ game.id }"><img src="{ game.thumbnail }" alt="{ game.title } thumbnail image" class="thumb-img" /></a>
+
<div class="platform-icons">
+
<span class="icon " title=""></span>
+
</div>
+
</div>
+
<h3><a href=`/games/${ game.id }`>{ game.title }</a></h3>
+
<div class="authors">
+
{ game.authors ? game.authors.map((a) => {
+
if (a.link && a.link !== "") {
+
return (<a href="{ a.link }" target="_blank">{ a.name }</a>)
+
} else {
+
return (a.name);
+
}
+
)}.join(", ") : 'Anonymous' }
+
</div>
+
</article>
+
+
<style lang="scss">
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
+
h3 {
+
margin: 0;
+
font-size: 1.25em;
+
+
a {
+
color: var(--foreground);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.thumb {
+
position: relative;
+
padding-top: 75%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
.authors {
+
font-size: .9em;
+
margin: 5px 0;
+
+
a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.blurb {
+
margin-top: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
}
+
</style>
+167
astro/src/components/Submissions.astro
···
+
---
+
import { getCollection, getEntry } from 'astro:content';
+
import GameCard from '../components/GameCard.astro';
+
const allGames = await getCollection('games');
+
---
+
<>
+
<aside id="filters">
+
<div class="afs-filter-container">
+
<!-- Filter Controls -->
+
<div class="afs-filter-controls">
+
<!-- Basic Filters -->
+
+
<!-- Search Input -->
+
<input type="text" class="afs-filter-search" placeholder="Search by title, author, or tags" />
+
+
<p class="label">Sort entries by:</p>
+
<ul id="sorts">
+
<li><button class="custom-sort" data-sort-key="date" data-sort-direction="desc"> <span class="afs-sort-direction"><span class="icon sort-desc"></span></span> Date</button></li>
+
<li><button class="custom-sort" data-sort-key="title" data-sort-direction="asc"> <span class="afs-sort-direction"><span class="icon sort-asc"></span></span> Title</button></li>
+
<li><button class="custom-sort" data-sort-key="shuffle" data-sort-direction="desc"><span class="icon random"></span></span> Random</button></li>
+
</ul>
+
+
<details open><summary>Platform</summary>
+
<ul>
+
<li><button class="afs-btn-filter" data-filter="platforms:browser"><span class="icon web"></span> Play in browser</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:windows"><span class="icon windows"></span> Windows</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:macos"><span class="icon macos"></span> Mac OS</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:linux"><span class="icon linux"></span> Linux</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:android"><span class="icon android"></span> Android</button></li>
+
</ul>
+
</details>
+
+
<details><summary>Tags</summary>
+
<div id="tags">
+
<button class="afs-btn-filter" data-filter="*">all</button>
+
+
</div>
+
</details>
+
+
<details><summary>Submission Date</summary>
+
<div id="date-filter"></div>
+
</details>
+
+
<!-- Results Counter -->
+
<div class="afs-filter-counter"></div>
+
</div>
+
+
<!-- Pagination Container -->
+
<div class="afs-pagination-container"></div>
+
</div>
+
</aside>
+
<section id="list">
+
{console.log(allGames)}
+
{allGames.map(game => (
+
<li><a href={`/games/${game.id}`}>{game.data.title}</a></li>
+
))}
+
</section>
+
</>
+
+
<style lang="scss">
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
+
#tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
+
button {
+
white-space: pre;
+
}
+
}
+
+
details {
+
margin-bottom: 10px;
+
+
ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
}
+
+
p.label,
+
details summary {
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
+
ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
+
li {
+
button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: .9em;
+
+
img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
+
&.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
}
+
}
+
}
+
+
.afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
+
&.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
}
+
+
.afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
+
.afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: .9em;
+
}
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+
</style>
+95 -195
astro/src/components/Welcome.astro
···
---
-
import astroLogo from '../assets/astro.svg';
-
import background from '../assets/background.svg';
+
import siteVars from '../site.config.ts';
---
-
<div id="container">
-
<img id="background" src={background.src} alt="" fetchpriority="high" />
-
<main>
-
<section id="hero">
-
<a href="https://astro.build"
-
><img src={astroLogo.src} width="115" height="48" alt="Astro Homepage" /></a
-
>
-
<h1>
-
To get started, open the <code><pre>src/pages</pre></code> directory in your project.
-
</h1>
-
<section id="links">
-
<a class="button" href="https://docs.astro.build">Read our docs</a>
-
<a href="https://astro.build/chat"
-
>Join our Discord <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36"
-
><path
-
fill="currentColor"
-
d="M107.7 8.07A105.15 105.15 0 0 0 81.47 0a72.06 72.06 0 0 0-3.36 6.83 97.68 97.68 0 0 0-29.11 0A72.37 72.37 0 0 0 45.64 0a105.89 105.89 0 0 0-26.25 8.09C2.79 32.65-1.71 56.6.54 80.21a105.73 105.73 0 0 0 32.17 16.15 77.7 77.7 0 0 0 6.89-11.11 68.42 68.42 0 0 1-10.85-5.18c.91-.66 1.8-1.34 2.66-2a75.57 75.57 0 0 0 64.32 0c.87.71 1.76 1.39 2.66 2a68.68 68.68 0 0 1-10.87 5.19 77 77 0 0 0 6.89 11.1 105.25 105.25 0 0 0 32.19-16.14c2.64-27.38-4.51-51.11-18.9-72.15ZM42.45 65.69C36.18 65.69 31 60 31 53s5-12.74 11.43-12.74S54 46 53.89 53s-5.05 12.69-11.44 12.69Zm42.24 0C78.41 65.69 73.25 60 73.25 53s5-12.74 11.44-12.74S96.23 46 96.12 53s-5.04 12.69-11.43 12.69Z"
-
></path></svg
-
>
-
</a>
-
</section>
-
</section>
-
</main>
+
<>
+
<div class="clock">
+
<div class="dates" id="dates">Submissions open from <b id="startDate" data-raw="{ siteVars.startDate }">{ siteVars.startDate }</b> to <b id="endDate" data-raw="{ siteVars.endDate }">{ siteVars.endDate }</b></div>
+
<div class="countdown">
+
<div class="counters">
+
<div class="verb">Starts in</div>
+
<div class="days"><span class="num" id="days">#</span><span class="caption">days</span></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>
+
</div>
+
</div>
+
<div class="join">
+
<a href="{ siteVars.joinLink }" class="joinbtn">Join Jam</a>
+
</div>
+
</div>
+
<div class="content">
+
<slot />
+
</div>
+
</>
-
<a href="https://astro.build/blog/astro-5/" id="news" class="box">
-
<svg width="32" height="32" fill="none" xmlns="http://www.w3.org/2000/svg"
-
><path
-
d="M24.667 12c1.333 1.414 2 3.192 2 5.334 0 4.62-4.934 5.7-7.334 12C18.444 28.567 18 27.456 18 26c0-4.642 6.667-7.053 6.667-14Zm-5.334-5.333c1.6 1.65 2.4 3.43 2.4 5.333 0 6.602-8.06 7.59-6.4 17.334C13.111 27.787 12 25.564 12 22.666c0-4.434 7.333-8 7.333-16Zm-6-5.333C15.111 3.555 16 5.556 16 7.333c0 8.333-11.333 10.962-5.333 22-3.488-.774-6-4-6-8 0-8.667 8.666-10 8.666-20Z"
-
fill="#111827"></path></svg
-
>
-
<h2>What's New in Astro 5.0?</h2>
-
<p>
-
From content layers to server islands, click to learn more about the new features and
-
improvements in Astro 5.0
-
</p>
-
</a>
-
</div>
-
-
<style>
-
#background {
-
position: fixed;
-
top: 0;
-
left: 0;
-
width: 100%;
-
height: 100%;
-
z-index: -1;
-
filter: blur(100px);
+
<style lang="scss">
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
+
.dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
}
-
-
#container {
-
font-family: Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif;
-
height: 100%;
-
}
-
-
main {
-
height: 100%;
-
display: flex;
-
justify-content: center;
-
}
-
-
#hero {
-
display: flex;
-
align-items: start;
-
flex-direction: column;
-
justify-content: center;
-
padding: 16px;
-
}
-
-
h1 {
-
font-size: 22px;
-
margin-top: 0.25em;
-
}
-
-
#links {
+
+
.countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
display: flex;
-
gap: 16px;
+
align-items: center;
+
justify-content: flex-end;
+
+
.counters {
+
display: flex;
+
align-items: stretch;
+
+
& > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
+
&:last-child {
+
border-right: none;
+
}
+
}
+
+
span {
+
display: block;
+
text-align: center;
+
+
&.num {
+
font-weight: bold;
+
}
+
+
&.caption {
+
font-size: .8em;
+
font-style: italic;
+
}
+
}
+
}
}
-
-
#links a {
+
+
.join {
display: flex;
align-items: center;
-
padding: 10px 12px;
-
color: #111827;
-
text-decoration: none;
-
transition: color 0.2s;
+
justify-content: flex-start;
+
padding: 20px;
}
-
-
#links a:hover {
-
color: rgb(78, 80, 86);
-
}
-
-
#links a svg {
-
height: 1em;
-
margin-left: 8px;
-
}
-
-
#links a.button {
-
color: white;
-
background: linear-gradient(83.21deg, #3245ff 0%, #bc52ee 100%);
-
box-shadow:
-
inset 0 0 0 1px rgba(255, 255, 255, 0.12),
-
inset 0 -2px 0 rgba(0, 0, 0, 0.24);
-
border-radius: 10px;
-
}
-
-
#links a.button:hover {
-
color: rgb(230, 230, 230);
-
box-shadow: none;
-
}
-
-
pre {
-
font-family:
-
ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono',
-
monospace;
-
font-weight: normal;
-
background: linear-gradient(14deg, #d83333 0%, #f041ff 100%);
-
-webkit-background-clip: text;
-
-webkit-text-fill-color: transparent;
-
background-clip: text;
-
margin: 0;
-
}
-
-
h2 {
-
margin: 0 0 1em;
-
font-weight: normal;
-
color: #111827;
-
font-size: 20px;
-
}
-
-
p {
-
color: #4b5563;
-
font-size: 16px;
-
line-height: 24px;
-
letter-spacing: -0.006em;
-
margin: 0;
-
}
-
-
code {
-
display: inline-block;
-
background:
-
linear-gradient(66.77deg, #f3cddd 0%, #f5cee7 100%) padding-box,
-
linear-gradient(155deg, #d83333 0%, #f041ff 18%, #f5cee7 45%) border-box;
-
border-radius: 8px;
-
border: 1px solid transparent;
-
padding: 6px 8px;
-
}
-
-
.box {
-
padding: 16px;
-
background: rgba(255, 255, 255, 1);
-
border-radius: 16px;
-
border: 1px solid white;
-
}
-
-
#news {
-
position: absolute;
-
bottom: 16px;
-
right: 16px;
-
max-width: 300px;
+
+
.joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
text-decoration: none;
-
transition: background 0.2s;
-
backdrop-filter: blur(50px);
-
}
-
-
#news:hover {
-
background: rgba(255, 255, 255, 0.55);
-
}
-
-
@media screen and (max-height: 368px) {
-
#news {
-
display: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
}
}
-
-
@media screen and (max-width: 768px) {
-
#container {
-
display: flex;
-
flex-direction: column;
-
}
-
-
#hero {
-
display: block;
-
padding-top: 10%;
-
}
-
-
#links {
-
flex-wrap: wrap;
-
}
-
-
#links a.button {
-
padding: 14px 18px;
-
}
-
-
#news {
-
right: 16px;
-
left: 16px;
-
bottom: 2.5rem;
-
max-width: 100%;
-
}
+
}
-
h1 {
-
line-height: 1.5;
-
}
-
}
+
.content {
+
text-align: left;
+
}
</style>
+22
astro/src/data/games/game-one.md
···
+
---
+
title: Game One
+
date: 2026-02-18T05:49:00Z
+
layout: game
+
authors: [{ name: "Carly Smallbird", link: "https://games.birdwrongs.sh" }]
+
description: Blurb goes here
+
tags: yuri horror
+
thumbnail: "game-one-1.jpg"
+
platforms: ["macos", "windows", "linux"]
+
screenshots: [
+
{ url: "game-one-1.jpg", alt: "descriptive text here" },
+
{ url: "game-one-2.jpg", alt: "descriptive text here" },
+
{ url: "game-one-3.jpg", alt: "descriptive text here" },
+
{ url: "game-one-4.jpg", alt: "descriptive text here" }
+
]
+
downloads: [
+
{ filename: "!! FILENAME HERE !!", link: "!! LINK URL HERE !!", filesize: "110MB", platforms: ["macos"] },
+
{ filename: "!! FILENAME HERE !!", link: "!! LINK URL HERE !!", filesize: "100MB", platforms: ["linux", "windows"] }
+
]
+
---
+
+
Longer blurb goes here to explain your game
astro/src/layouts/Home.astro

This is a binary file and will not be displayed.

+248 -8
astro/src/layouts/Layout.astro
···
+
---
+
import siteVars from '../site.config.ts';
+
const { bodyClass, currentPage } = Astro.props;
+
const announcementsClass = currentPage === 'posts' ? 'current' : '';
+
const homeClass = currentPage === 'home' ? 'current' : '';
+
const submissionsClass = currentPage === 'submissions' ? 'current' : '';
+
---
<!doctype html>
<html lang="en">
<head>
···
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
-
<title>Astro Basics</title>
+
<title>{ siteVars.siteName }</title>
</head>
-
<body>
-
<slot />
+
<body class={bodyClass}>
+
<div id="page">
+
<header>
+
<h1>{ siteVars.siteName }</h1>
+
<p class="hosted">Hosted by {siteVars.hostLink ? <a href="{ siteVars.hostLink }" target="_blank">{ siteVars.hostName }</a> : siteVars.hostName }{ siteVars.hashtag ? (siteVars.hashtagLink ? <>&bull; <a href="{siteVars.hashtagLink}" target="_blank">{ siteVars.hashtag }</a></> : <>&bull; { siteVars.hashtag }</>) : '' }</p>
+
+
<div class="joined">
+
<span class="count" id="joinedCount">
+
joined
+
</span>
+
<span class="caption">Joined</span>
+
</div>
+
<div class="entries">
+
<span class="count" id="entryCount">entries</span>
+
<span class="caption">Entries</span>
+
</div>
+
+
<nav>
+
<ul>
+
<li><a href="/" class={homeClass}>Overview</a></li>
+
{ siteVars.showAnnouncements && <li><a href="/posts" class={announcementsClass}>Announcements</a></li> }
+
{ siteVars.showCommunity && <li><a href="{ siteVars.communityLink }" target="_blank">Community</a></li> }
+
<li><a href="/games" class={submissionsClass}>Submissions</a></li>
+
</ul>
+
</nav>
+
</header>
+
<main>
+
<slot />
+
</main>
+
<footer>
+
<a href="https://veryroundbird.house" target="_blank">♥︎</a>
+
</footer>
+
</div>
</body>
</html>
-
<style>
-
html,
-
body {
+
<style lang="scss">
+
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+
/* display variables! skip the images if you don't want them */
+
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
+
--headingfont: 'Knewave', 'Arial Black', sans-serif;
+
--roundedCorners: 0px;
+
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
+
&:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
+
&.web {
+
mask: url(../images/web.svg);
+
}
+
+
&.windows {
+
mask: url(../images/windows.svg);
+
}
+
+
&.macos {
+
mask: url(../images/macos.svg);
+
}
+
+
&.linux {
+
mask: url(../images/linux.svg);
+
}
+
+
&.android {
+
mask: url(../images/android.svg);
+
}
+
+
&.random {
+
mask: url(../images/random.svg);
+
}
+
+
&.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
+
&.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
+
.active & {
+
background-color: var(--accent);
+
}
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
+
body.wide & {
+
max-width: none;
margin: 0;
-
width: 100%;
-
height: 100%;
}
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
+
h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
+
.hosted {
+
margin: 0;
+
}
+
+
.joined,
+
.entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
+
.count {
+
font-size: 2.25em;
+
display: block;
+
}
+
+
.caption {
+
font-size: .8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
}
+
+
nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
+
ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
+
li {
+
a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
+
&.current,
+
&:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
}
+
}
+
}
+
}
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
+
.submissions & {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
}
+
+
footer {
+
text-align: center;
+
font-size: .8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
+
a {
+
text-decoration: none;
+
}
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0,0,0,.5);
+
}
</style>
astro/src/layouts/Wide.astro

This is a binary file and will not be displayed.

+11
astro/src/pages/games/index.astro
···
+
---
+
import Layout from '../../layouts/Layout.astro';
+
import Submissions from '../../components/Submissions.astro';
+
+
const bodyClass = 'wide submissions';
+
const currentPage = 'submissions';
+
---
+
+
<Layout bodyClass={bodyClass} currentPage={currentPage}>
+
<Submissions />
+
</Layout>
+6 -2
astro/src/pages/index.astro
···
import Welcome from '../components/Welcome.astro';
import Layout from '../layouts/Layout.astro';
+
const currentPage = 'home';
+
// Welcome to Astro! Wondering what to do next? Check out the Astro documentation at https://docs.astro.build
// Don't want to use any of this? Delete everything in this file, the `assets`, `components`, and `layouts` directories, and start fresh.
---
-
<Layout>
-
<Welcome />
+
<Layout currentPage={currentPage}>
+
<Welcome>
+
Your content for the homepage goes here!!!
+
</Welcome>
</Layout>
+35
astro/src/site.config.ts
···
+
export default {
+
siteName: "Your Jam Name Here",
+
hostName: "!!YOUR NAME HERE!!",
+
hostLink: null,
+
hashtag: null,
+
hashtagLink: null,
+
joinLink: '#',
+
startDate: "2026-02-01T00:00:00",
+
endDate: "2026-02-28T23:59:59",
+
locale: "en-US",
+
timezone: "America/Chicago",
+
favicon: "images/android-chrome-512x512.png",
+
favicon32: "images/favicon-32x32.png",
+
appletouch: "images/favicon-192x192.png",
+
banner: null,
+
joinedCountSource: "manual", // options are "manual" / "airtable" / "airtablelive" / "gsheets" / "gsheetslive" / "json" / "csv"
+
joinedCount: 0, // only used with "manual"
+
joinedAirtableBaseId: "",
+
joinedAirtableTableName: "",
+
joinedAirtableToken: "",
+
joinedGoogleSheetId: "",
+
joinedJsonDataSource: "",
+
joinedCsvDataSource: "",
+
showAnnouncements: false,
+
showCommunityLink: false,
+
communityLink: "",
+
shareLinks: { bsky: true, mastodon: true, x: false, facebook: false },
+
customShareServices: [
+
// { name: "", iconPath: "", intentUrl: "" }
+
],
+
tinylytics_script_id: "",
+
goatcounter_id: "",
+
use_tinylytics_kudos: true, // will not be used if the tinylytics script id isn't provided
+
tinylytics_kudos_emoji: "❤️"
+
};
+7
colorthemes/blues.css
···
+
:root {
+
--background: #555879;
+
--foreground: #FAF7EE;
+
--accent: #98A1BC;
+
--background-blend: #000000;
+
--foreground-blend: #FFFFFF;
+
}
+7
colorthemes/newleaf.css
···
+
:root {
+
--background: #EEEFE0;
+
--foreground: #819A91;
+
--accent: #A7C1A8;
+
--background-blend: #FFFFFF;
+
--foreground-blend: #000000;
+
}
+62
hugo/.github/ISSUE_TEMPLATE/bug_report.yml
···
+
name: 🐛 Bug Report
+
description: Report a bug in Hugo ʕ•ᴥ•ʔ Bear Blog
+
labels: ["bug"]
+
body:
+
- type: markdown
+
attributes:
+
value: |
+
Thanks for taking the time to fill out this bug report! Before you proceed:
+
+
1. 🔍 Please search [existing issues](https://github.com/janraasch/hugo-bearblog/issues) to avoid duplicates
+
2. 💭 For general usage questions, consider posting on [Hugo Discourse](https://discourse.gohugo.io/)
+
+
- type: textarea
+
id: bug-description
+
attributes:
+
label: Describe the bug
+
description: A clear and concise description of what the bug is
+
placeholder: When I do X, Y happens instead of Z...
+
validations:
+
required: true
+
+
- type: textarea
+
id: reproduction
+
attributes:
+
label: Steps to reproduce
+
description: Steps to reproduce the behavior
+
placeholder: |
+
1. Go to '...'
+
2. Click on '....'
+
3. Scroll down to '....'
+
4. See error
+
validations:
+
required: true
+
+
- type: textarea
+
id: expected
+
attributes:
+
label: Expected behavior
+
description: A clear and concise description of what you expected to happen
+
validations:
+
required: true
+
+
- type: input
+
id: hugo-version
+
attributes:
+
label: Hugo version
+
description: Output of `hugo version`
+
placeholder: Hugo v0.92.0
+
validations:
+
required: true
+
+
- type: textarea
+
id: config
+
attributes:
+
label: Configuration
+
description: Relevant parts of your Hugo configuration
+
+
- type: textarea
+
id: additional
+
attributes:
+
label: Additional context
+
description: Add any other context about the problem here (screenshots, error messages, etc.)
+41
hugo/.github/ISSUE_TEMPLATE/feature_request.yml
···
+
name: ✨ Feature Request
+
description: Suggest an idea for Hugo ʕ•ᴥ•ʔ Bear Blog
+
labels: ["enhancement"]
+
body:
+
- type: markdown
+
attributes:
+
value: |
+
Thanks for your interest in improving Hugo ʕ•ᴥ•ʔ Bear Blog! Before proceeding:
+
+
1. 🔍 Please check [existing issues](https://github.com/janraasch/hugo-bearblog/issues) for similar suggestions
+
2. 🎯 Note that we aim to maintain a minimal feature set, similar to the original [Bear Blog](https://bearblog.dev)
+
3. 💡 Consider if your need could be met using existing Hugo features
+
+
- type: textarea
+
id: problem
+
attributes:
+
label: Is your feature request related to a problem?
+
description: A clear and concise description of what the problem is
+
placeholder: My site is slow because [...]
+
validations:
+
required: true
+
+
- type: textarea
+
id: solution
+
attributes:
+
label: Describe the solution you'd like
+
description: A clear and concise description of what you want to happen
+
validations:
+
required: true
+
+
- type: textarea
+
id: alternatives
+
attributes:
+
label: Describe alternatives you've considered
+
description: A clear and concise description of any alternative solutions or features you've considered
+
+
- type: textarea
+
id: context
+
attributes:
+
label: Additional context
+
description: How does this feature align with the theme's minimalist philosophy? Add any other context or screenshots about the feature request here
+52
hugo/.github/ISSUE_TEMPLATE/feedback_showcase.yml
···
+
name: 🎉 Share Your Story
+
description: Share how you're using Hugo ʕ•ᴥ•ʔ Bear Blog or give general feedback
+
labels: ["showcase", "feedback"]
+
body:
+
- type: markdown
+
attributes:
+
value: |
+
Thanks for sharing your Hugo ʕ•ᴥ•ʔ Bear Blog story! We love hearing how people are using the theme and what makes it special for them 💝
+
+
- type: dropdown
+
id: feedback-type
+
attributes:
+
label: Type of feedback
+
description: What kind of story would you like to share?
+
options:
+
- "📸 Showcase my site"
+
- "💡 Share my experience"
+
- "❤️ General appreciation"
+
- "💭 Other"
+
+
- type: textarea
+
id: story
+
attributes:
+
label: Your Story
+
description: Tell us about your experience with Hugo ʕ•ᴥ•ʔ Bear Blog!
+
placeholder: |
+
I'm using Hugo ʕ•ᴥ•ʔ Bear Blog for...
+
What I particularly love about it is...
+
You can find my site at... (if you'd like to share)
+
validations:
+
required: true
+
+
- type: textarea
+
id: customizations
+
attributes:
+
label: Customizations (optional)
+
description: Did you make any interesting customizations to the theme? Feel free to share!
+
placeholder: |
+
I modified...
+
I added...
+
+
- type: textarea
+
id: screenshots
+
attributes:
+
label: Screenshots (optional)
+
description: If you'd like to show off your site, you can add screenshots here!
+
+
- type: textarea
+
id: additional
+
attributes:
+
label: Additional thoughts
+
description: Anything else you'd like to share with the community?
+14
hugo/.github/dependabot.yml
···
+
# see https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates
+
version: 2
+
updates:
+
# Maintain dependencies for GitHub Actions
+
- package-ecosystem: "github-actions"
+
directory: "/"
+
schedule:
+
interval: "daily"
+
+
# Maintain dependencies for npm
+
- package-ecosystem: "npm"
+
directory: "/"
+
schedule:
+
interval: "daily"
+17
hugo/.github/stale.yml
···
+
# Number of days of inactivity before an issue becomes stale
+
daysUntilStale: 60
+
# Number of days of inactivity before a stale issue is closed
+
daysUntilClose: 7
+
# Issues with these labels will never be considered stale
+
exemptLabels:
+
- pinned
+
- security
+
# Label to use when marking an issue as stale
+
staleLabel: wontfix
+
# Comment to post when marking an issue as stale. Set to `false` to disable
+
markComment: >
+
This issue has been automatically marked as stale because it has not had
+
recent activity. It will be closed if no further activity occurs. Thank you
+
for your contributions.
+
# Comment to post when closing a stale issue. Set to `false` to disable
+
closeComment: false
+41
hugo/.github/workflows/auto-merge.yml
···
+
# see https://gist.github.com/xt0rted/46475099dc0a70ba63e16e3177407872
+
+
name: Dependabot auto-merge
+
+
on:
+
pull_request:
+
branches:
+
- master
+
+
permissions:
+
contents: read
+
pull-requests: read
+
+
jobs:
+
auto-merge:
+
runs-on: ubuntu-latest
+
+
if: github.actor == 'dependabot[bot]'
+
+
steps:
+
- name: Create token
+
id: create_token
+
uses: tibdex/github-app-token@v2
+
with:
+
app_id: ${{ secrets.BIG_MERGER_APP_ID }}
+
private_key: ${{ secrets.BIG_MERGER_PRIVATE_KEY }}
+
+
- name: Dependabot metadata
+
id: dependabot-metadata
+
uses: dependabot/fetch-metadata@v2
+
with:
+
github-token: "${{ secrets.GITHUB_TOKEN }}"
+
+
- name: Authenticate cli
+
run: echo "${{ steps.create_token.outputs.token }}" | gh auth login --with-token
+
+
- name: Enable auto-merge for Dependabot PRs
+
if: contains(fromJSON('["version-update:semver-patch", "version-update:semver-minor"]'), steps.dependabot-metadata.outputs.update-type)
+
run: gh pr merge --auto --squash "$PR_URL"
+
env:
+
PR_URL: ${{github.event.pull_request.html_url}}
+48
hugo/.github/workflows/ci.yml
···
+
name: CI
+
+
on:
+
push:
+
branches:
+
- master
+
pull_request:
+
branches:
+
- master
+
+
jobs:
+
build:
+
name: Build
+
runs-on: ubuntu-latest
+
+
steps:
+
- name: Checkout
+
uses: actions/checkout@v5
+
+
- name: Setup Hugo
+
uses: peaceiris/actions-hugo@v3.0.0
+
with:
+
hugo-version: latest
+
+
- name: Build local ./exampleSite
+
run: hugo --minify --gc --destination ../public --source ./exampleSite --themesDir ../.. --baseURL https://janraasch.github.io/hugo-bearblog/
+
+
- name: Upload Artifact
+
uses: actions/upload-artifact@v4
+
with:
+
name: build
+
path: ./public
+
+
deploy:
+
needs: build
+
name: Deploy to GitHub Pages
+
runs-on: ubuntu-latest
+
if: github.event_name == 'push'
+
steps:
+
- uses: actions/checkout@v5
+
- uses: actions/download-artifact@v5
+
with:
+
name: build
+
path: ./public
+
- uses: peaceiris/actions-gh-pages@v4.0.0
+
with:
+
github_token: ${{ secrets.GITHUB_TOKEN }}
+
publish_dir: ./public
+3
hugo/.gitignore
···
+
node_modules
+
public/
+
.hugo_build.lock
+27
hugo/.jsbeautifyrc
···
+
{
+
"indent_size": 2,
+
"indent_char": " ",
+
"indent_with_tabs": false,
+
"editorconfig": false,
+
"eol": "\n",
+
"end_with_newline": true,
+
"indent_level": 0,
+
"preserve_newlines": true,
+
"max_preserve_newlines": 10,
+
"space_in_paren": false,
+
"space_in_empty_paren": false,
+
"jslint_happy": false,
+
"space_after_anon_function": false,
+
"space_after_named_function": false,
+
"brace_style": "collapse",
+
"unindent_chained_methods": false,
+
"break_chained_methods": false,
+
"keep_array_indentation": false,
+
"unescape_strings": false,
+
"wrap_line_length": 0,
+
"e4x": false,
+
"comma_first": false,
+
"operator_position": "before-newline",
+
"indent_empty_lines": false,
+
"templating": ["auto"]
+
}
+20
hugo/LICENSE
···
+
The MIT License (MIT)
+
+
Copyright (c) 2020 Jan Raasch
+
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
+
this software and associated documentation files (the "Software"), to deal in
+
the Software without restriction, including without limitation the rights to
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+
the Software, and to permit persons to whom the Software is furnished to do so,
+
subject to the following conditions:
+
+
The above copyright notice and this permission notice shall be included in all
+
copies or substantial portions of the Software.
+
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+117
hugo/README.md
···
+
# Hugo ʕ•ᴥ•ʔ Bear Blog [![CI](https://github.com/janraasch/hugo-bearblog/actions/workflows/ci.yml/badge.svg)](https://github.com/janraasch/hugo-bearblog/actions/workflows/ci.yml)
+
+
🧸 A [Hugo](https://gohugo.io/)-theme based on [Bear Blog](https://bearblog.dev).
+
+
> Free, no-nonsense, super-fast blogging.
+
+
## Demo
+
+
For a current & working demo of this theme, please check out https://janraasch.github.io/hugo-bearblog/ 🎯.
+
+
## Screenshots
+
+
⬜️ [Light][light-screenshot]
+
+
⬛️ [Dark][dark-screenshot]
+
+
When the user's browser is running »dark mode«, the dark color scheme will be used automatically. The default is the light/white color scheme. Check out the [`style.html`](https://github.com/janraasch/hugo-bearblog/blob/master/layouts/partials/style.html)-file for the implementation.
+
+
## Installation
+
+
If you already have a Hugo site on your machine, you can simply add this theme via
+
+
```bash
+
git submodule add https://github.com/janraasch/hugo-bearblog.git themes/hugo-bearblog
+
```
+
+
Then, adjust the `hugo.toml` as detailed below.
+
+
For more information, read the official [setup guide][hugo-setup-guide] of Hugo.
+
+
## Adjust configuration / hugo.toml
+
+
Please check out the [hugo.toml](https://github.com/janraasch/hugo-bearblog/blob/master/exampleSite/hugo.toml) included in the [exampleSite](https://github.com/janraasch/hugo-bearblog/tree/master/exampleSite) of this theme.
+
+
## Content & structure
+
+
### Starting fresh
+
+
If you are starting fresh, simply copy over the contents of the `exampleSite`-directory included in this theme to your source directory. That should give you a good idea about how things work, and then you can go on from there to make the site your own.
+
+
### Adding / editing content
+
+
#### Index-Page
+
+
The contents of the `index`-page may be changed by editing your `content/_index.md`-file.
+
+
#### Page
+
+
You can add **a new page** via running
+
+
```bash
+
hugo new my-new-page.md
+
```
+
+
#### Blog-Post
+
+
You can add **a new blog-post** via running
+
+
```bash
+
hugo new blog/my-new-post.md
+
```
+
+
### Adding your branding / colors / css
+
+
Add a `custom_head.html`-file to your `layouts/partials`-directory. In there you may add a `<style>`-tag, *or* you may add a `<link>`-tag referencing your own `custom.css` (in case you prefer to have a separate `.css`-file). Check out the [`style.html`](https://github.com/janraasch/hugo-bearblog/blob/master/layouts/partials/style.html)-file to find out which CSS-styles are applied by default.
+
+
## Remixes 🎭
+
+
The community has created some interesting variations of Hugo ʕ•ᴥ•ʔ Bear Blog. While the main theme stays true to the minimal Bear Blog philosophy, these remixes experiment with additional features:
+
+
* [Hugo ʕ•ᴥ•ʔ Bear Blog ✨ Neo](https://github.com/rokcso/hugo-bearblog-neo/) - Features Chinese documentation and an innovative "Toast" upvote system.
+
+
* [ᕦʕ •ᴥ•ʔᕤ Bear Cub](https://github.com/clente/hugo-bearcub) - A multilingual variant with experimental features like automatic social card generation.
+
+
_Note: These are independent forks maintained by their respective creators._
+
+
## Contributing & Community 🤝
+
+
Interested in contributing to Hugo ʕ•ᴥ•ʔ Bear Blog? Thanks for your interest!
+
+
- Check out our [Contributing Guidelines](CONTRIBUTING.md) for code contributions and bug reports
+
- [Share your story](https://github.com/janraasch/hugo-bearblog/issues/new/choose) if you're using the theme - we'd love to see what you've built!
+
- Have questions? You can find help in our [GitHub issues](https://github.com/janraasch/hugo-bearblog/issues) or the [Hugo Discourse](https://discourse.gohugo.io/)
+
+
We aim to keep this theme as simple and fast as the original [Bear Blog](https://bearblog.dev), while making it a friendly space for everyone to contribute and share their experiences.
+
+
## Development
+
Run the `exampleSite` locally via
+
+
```bash
+
hugo server --source ./exampleSite --themesDir ../..
+
```
+
+
In case you want to test functionalities and use hugo commands, in the root directory, you'll have to append `--source ./exampleSite --themesDir ../..` to them.
+
+
For example:
+
+
```bash
+
hugo new blog/post.md --source ./exampleSite --themesDir ../..
+
```
+
+
Same thing for pages:
+
+
```bash
+
hugo new page.md --source ./exampleSite --themesDir ../..
+
```
+
+
## Special Thanks 🎁
+
+
A special thank you goes out to [Herman](https://herman.bearblog.dev), for creating the original [ʕ•ᴥ•ʔ Bear Blog](https://bearblog.dev/).
+
+
## License
+
[MIT License](http://en.wikipedia.org/wiki/MIT_License) © [Jan Raasch](https://www.janraasch.com)
+
+
[hugo-setup-guide]: https://gohugo.io/getting-started/installing
+
[light-screenshot]: https://raw.githubusercontent.com/janraasch/hugo-bearblog/master/images/screenshot.png
+
[dark-screenshot]: https://raw.githubusercontent.com/janraasch/hugo-bearblog/master/images/screenshot-dark.png
+13
hugo/archetypes/blog.md
···
+
+++
+
title = "{{ replace .Name "-" " " | title }}"
+
date = "{{ .Date }}"
+
+
#
+
# description is optional
+
#
+
# description = "An optional description for SEO. If not provided, an automatically created summary will be used."
+
+
tags = [{{ range $plural, $terms := .Site.Taxonomies }}{{ range $term, $val := $terms }}"{{ printf "%s" $term }}",{{ end }}{{ end }}]
+
+++
+
+
This is a page about »{{ replace .Name "-" " " | title }}«.
+22
hugo/archetypes/default.md
···
+
+++
+
title = "{{ replace .Name "-" " " | title }}"
+
date = "{{ .Date }}"
+
+
#
+
# Set menu to "main" to add this page to
+
# the main menu on top of the page
+
#
+
menu = "main"
+
+
#
+
# description is optional
+
#
+
# description = "An optional description for SEO. If not provided, an automatically created summary will be used."
+
+
#
+
# tags are optional
+
#
+
# tags = [{{ range $plural, $terms := .Site.Taxonomies }}{{ range $term, $val := $terms }}"{{ printf "%s" $term }}",{{ end }}{{ end }}]
+
+++
+
+
This is a page about »{{ replace .Name "-" " " | title }}«.
+9
hugo/archetypes/game.md
···
+
+++
+
title = "{{ replace .Name "-" " " | title }}"
+
date = "{{ .Date }}"
+
description = "Optional blurb goes here"
+
+
tags = [{{ range $plural, $terms := .Site.Taxonomies }}{{ range $term, $val := $terms }}"{{ printf "%s" $term }}",{{ end }}{{ end }}]
+
+++
+
+
This is the game »{{ replace .Name "-" " " | title }}«.
+2
hugo/assets/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};
+
//# sourceMappingURL=afs.modern.js.map
+66
hugo/assets/js/home.js
···
+
const startContent = document.getElementById('startDate') ? document.getElementById('startDate').textContent : null;
+
const startDate = document.getElementById('startDate') ? document.getElementById('startDate').getAttribute('data-raw') : null;
+
const endContent = document.getElementById('endDate') ? document.getElementById('endDate').textContent : null;
+
const endDate = document.getElementById('endDate') ? document.getElementById('endDate').getAttribute('data-raw') : null;
+
+
// Date formatting stuff. You probably only need to touch locale and time zone.
+
const locale = 'en-US';
+
const timeZone = 'America/Chicago';
+
+
// DON'T EDIT BELOW THIS LINE
+
// unless you know what you're doing.
+
+
const start = new Date(startDate);
+
const end = new Date(endDate);
+
const now = Date.now();
+
+
const dateElt = document.getElementById('dates');
+
+
const daysElt = document.getElementById('days');
+
const hoursElt = document.getElementById('hours');
+
const minutesElt = document.getElementById('minutes');
+
const secondsElt = document.getElementById('seconds');
+
+
const list = document.getElementById('list');
+
+
const dayMult = 24*60*60;
+
const hourMult = 60*60;
+
const minuteMult = 60;
+
+
const countdownTick = () => {
+
const now = Date.now();
+
let diff;
+
if (now < start.getTime()) {
+
// Jam hasn't started yet
+
diff = (start.getTime() - now) / 1000; // get total # of seconds
+
} else if (now < end.getTime()) {
+
// Jam has started but not ended
+
diff = (end.getTime() - now) / 1000;
+
} else {
+
// Jam has ended
+
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'}`
+
}
+
+
if (diff) {
+
const days = Math.floor(diff / dayMult);
+
diff = diff - (days * dayMult);
+
const hours = Math.floor(diff / hourMult);
+
diff = diff - (hours * hourMult);
+
const minutes = Math.floor(diff / minuteMult);
+
diff = diff - (minutes * minuteMult);
+
const seconds = Math.floor(diff);
+
daysElt.textContent = days;
+
hoursElt.textContent = hours;
+
minutesElt.textContent = minutes;
+
secondsElt.textContent = seconds;
+
}
+
}
+
+
if (document.querySelector('.clock')) {
+
countdownTick();
+
if (now < end.getTime()) {
+
setInterval(() => {
+
countdownTick();
+
}, 1000);
+
}
+
}
+3
hugo/assets/scss/_partials/_fonts.scss
···
+
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+116
hugo/assets/scss/_partials/_game.scss
···
+
.game {
+
main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
+
h2 {
+
margin: 0;
+
+
a {
+
font-size: .9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
}
+
+
h3 {
+
margin: 0;
+
}
+
+
.blurb {
+
margin: 1em 0;
+
}
+
+
.game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
+
.jamsub {
+
font-size: .8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
}
+
+
.screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
+
.gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
+
a, button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
& > :first-child {
+
grid-area: featured;
+
}
+
}
+
}
+
+
.interaction {
+
grid-area: stuff;
+
}
+
+
.downloads {
+
padding: 20px;
+
+
ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
+
li {
+
margin-bottom: 10px;
+
}
+
}
+
+
.size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
+
.platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
+
.icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
+
.comments {
+
border-top: 1px var(--accent) solid;
+
}
+
}
+52
hugo/assets/scss/_partials/_game_list_item.scss
···
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
+
h3 {
+
margin: 0;
+
font-size: 1.25em;
+
+
a {
+
color: var(--foreground);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.thumb {
+
position: relative;
+
padding-top: 75%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
.authors {
+
font-size: .9em;
+
margin: 5px 0;
+
+
a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.blurb {
+
margin-top: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
}
+192
hugo/assets/scss/_partials/_global.scss
···
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
+
&:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
+
&.web {
+
mask: url(../images/web.svg);
+
}
+
+
&.windows {
+
mask: url(../images/windows.svg);
+
}
+
+
&.macos {
+
mask: url(../images/macos.svg);
+
}
+
+
&.linux {
+
mask: url(../images/linux.svg);
+
}
+
+
&.android {
+
mask: url(../images/android.svg);
+
}
+
+
&.random {
+
mask: url(../images/random.svg);
+
}
+
+
&.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
+
&.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
+
.active & {
+
background-color: var(--accent);
+
}
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
+
body.wide & {
+
max-width: none;
+
margin: 0;
+
}
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
+
h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
+
.hosted {
+
margin: 0;
+
}
+
+
.joined,
+
.entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
+
.count {
+
font-size: 2.25em;
+
display: block;
+
}
+
+
.caption {
+
font-size: .8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
}
+
+
nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
+
ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
+
li {
+
a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
+
&.current,
+
&:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
}
+
}
+
}
+
}
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
+
.submissions & {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
}
+
+
footer {
+
text-align: center;
+
font-size: .8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
+
a {
+
text-decoration: none;
+
}
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0,0,0,.5);
+
}
+83
hugo/assets/scss/_partials/_homepage.scss
···
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
+
.dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
+
.countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
+
.counters {
+
display: flex;
+
align-items: stretch;
+
+
& > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
+
&:last-child {
+
border-right: none;
+
}
+
}
+
+
span {
+
display: block;
+
text-align: center;
+
+
&.num {
+
font-weight: bold;
+
}
+
+
&.caption {
+
font-size: .8em;
+
font-style: italic;
+
}
+
}
+
}
+
}
+
+
.join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
+
.joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
}
+
+
.content {
+
text-align: left;
+
}
+17
hugo/assets/scss/_partials/_posts.scss
···
+
.post-list {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
text-align: left;
+
+
h3 {
+
font-weight: normal;
+
font-size: 1em;
+
+
.date {
+
margin-left: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
}
+106
hugo/assets/scss/_partials/_submissions.scss
···
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
+
#tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
+
button {
+
white-space: pre;
+
}
+
}
+
+
details {
+
margin-bottom: 10px;
+
+
ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
}
+
+
p.label,
+
details summary {
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
+
ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
+
li {
+
button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: .9em;
+
+
img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
+
&.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
}
+
}
+
}
+
+
.afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
+
&.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
}
+
+
.afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
+
.afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: .9em;
+
}
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+13
hugo/assets/scss/_partials/_variables.scss
···
+
/* display variables! skip the images if you don't want them */
+
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
+
--headingfont: 'Knewave', 'Arial Black', sans-serif;
+
--roundedCorners: 0px;
+
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+7
hugo/assets/scss/style.scss
···
+
@use '_partials/_fonts';
+
@use '_partials/_variables';
+
@use '_partials/_global';
+
@use '_partials/_homepage';
+
@use '_partials/_submissions';
+
@use '_partials/_game_list_item';
+
@use '_partials/_game';
+6
hugo/layouts/404.html
···
+
{{ define "title" }}404{{ end }}
+
+
{{ define "main" }}
+
<h1>404</h1>
+
<h2>ʕノ•ᴥ•ʔノ ︵ ┻━┻</h2>
+
{{ end }}
+20
hugo/layouts/_partials/favicon.html
···
+
{{ with .Site.Params.favicon }}
+
{{ with resources.Get . }}
+
<link rel="shortcut icon" href="{{ .RelPermalink }}" />
+
{{ end }}
+
{{ end }}
+
{{ with .Site.Params.favicon32 }}
+
{{ with resources.Get . }}
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ .RelPermalink }}">
+
{{ end }}
+
{{ end }}
+
{{ with .Site.Params.favicon16 }}
+
{{ with resources.Get . }}
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ .RelPermalink }}">
+
{{ end }}
+
{{ end }}
+
{{ with .Site.Params.appletouchicon }}
+
{{ with resources.Get . }}
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ .RelPermalink }}">
+
{{ end }}
+
{{ end }}
+3
hugo/layouts/_partials/footer.html
···
+
<footer>
+
<a href="https://veryroundbird.house" target="_blank">♥︎</a>
+
</footer>
+9
hugo/layouts/_partials/header.html
···
+
<header>
+
<h1>{{ .Site.Title }}</h1>
+
<p class="hosted">Hosted by <a href="!!YOURLINK!!" target="_blank">!!YOURNAME!!</a> &bull; <a href="!!LINK TO HASHTAG FILTER!!" target="_blank">#!!HASHTAG!!</a></p>
+
<div class="joined">
+
<span class="count" id="joinedCount">!!#!!</span>
+
<span class="caption">Joined</span>
+
</div>
+
{{- partial "nav.html" . -}}
+
</header>
+3
hugo/layouts/_partials/home_scripts.html
···
+
{{ with resources.Get "js/home.js" }}
+
<script type="text/javascript" src="{{ .RelPermalink }}"></script>
+
{{ end }}
+8
hugo/layouts/_partials/nav.html
···
+
<nav>
+
<ul>
+
{{ $currentPage := . }}
+
{{ range .Site.Menus.main }}
+
<li><a href="{{ .URL }}"{{ if $currentPage.IsMenuCurrent .Menu . }} class="current"{{ end }}{{ if .Params.External }} rel="external" target="_blank"{{ end }}>{{ .Name }}</a></li>
+
{{ end }}
+
</ul>
+
</nav>
+19
hugo/layouts/_partials/post_navigator.html
···
+
<div style="font-size:0.8em;display:flex;gap:16px;justify-content:center;">
+
<p>
+
{{ if .PrevInSection }}
+
<a href="{{ .PrevInSection.Permalink }}">
+
<< Previous Post</a>
+
{{ else }}
+
<strike>
+
<< Previous Post</strike>
+
{{ end }}
+
</p>
+
<p>|</p>
+
<p>
+
{{ if .NextInSection }}
+
<a href="{{ .NextInSection.Permalink }}">Next Post >></a>
+
{{ else }}
+
<strike>Next Post >></strike>
+
{{ end }}
+
</p>
+
</div>
+13
hugo/layouts/_partials/seo_tags.html
···
+
<!-- Primary Meta Tags -->
+
<meta name="title" content="{{ with .Title }}{{ . }}{{ else }}{{ .Site.Title }}{{ end }}" />
+
<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{if .IsPage}}{{ .Summary }}{{ else }}{{ with .Site.Params.description }}{{ . }}{{ end }}{{ end }}{{ end }}" />
+
<meta name="keywords" content="{{ if .IsPage}}{{ range $index, $tag := .Params.tags }}{{ $tag }},{{ end }}{{ else }}{{ range $plural, $terms := .Site.Taxonomies }}{{ range $term, $val := $terms }}{{ printf "%s," $term }}{{ end }}{{ end }}{{ end }}" />
+
+
<!-- Open Graph / Facebook -->
+
{{ template "_internal/opengraph.html" . }}
+
+
<!-- Twitter -->
+
{{ template "_internal/twitter_cards.html" . }}
+
+
<!-- Microdata -->
+
{{ template "_internal/schema.html" . }}
+104
hugo/layouts/_partials/submissions_scripts.html
···
+
{{ with resources.Get "js/afs.modern.js" }}
+
<script type="module">
+
import { AFS } from '{{ .Permalink }}';
+
const afs = new AFS({
+
// Required Selectors
+
containerSelector: '#list',
+
itemSelector: '.item',
+
+
// CSS Classes
+
activeClass: 'active',
+
hiddenClass: 'hidden',
+
transitionClass: 'afs-transition',
+
searchKeys: ['title', 'authors', 'tags'],
+
debounceTime: 200, // search input delay
+
+
// Date Handling
+
dateFormat: 'YYYY-MM-DD',
+
dateFilter: {
+
enabled: true,
+
format: 'YYYY-MM-DDThh:mm:ss'
+
},
+
+
// Counter Configuration
+
counter: {
+
template: 'Showing {visible} of {total}',
+
showFiltered: true,
+
filteredTemplate: '({filtered} filtered)',
+
noResultsTemplate: 'No items found',
+
formatter: (num) => num.toLocaleString()
+
},
+
+
sort: {
+
enabled: true,
+
buttonSelector: '.afs-btn-sort'
+
},
+
+
// Animation Configuration
+
animation: {
+
type: 'fade',
+
duration: 200,
+
easing: 'ease-out',
+
inClass: 'afs-animation-enter',
+
outClass: 'afs-animation-leave'
+
},
+
+
// Lifecycle Options
+
responsive: true,
+
preserveState: false,
+
stateExpiry: 86400000, // 24 hours
+
observeDOM: false,
+
+
// Style Configuration
+
styles: {
+
colors: {
+
primary: '#000',
+
background: '#e5e7eb',
+
text: '#000',
+
textHover: '#fff'
+
}
+
}
+
});
+
+
// add date range filter
+
afs.dateFilter.addDateRange({
+
key: 'date',
+
container: document.querySelector('#date-filter'),
+
format: 'YYYY-MM-DD',
+
minDate: new Date("{{ site.Params.StartDate }}".match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0]),
+
maxDate: new Date("{{ site.Params.EndDate }}".match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0])
+
});
+
+
// fixes some behavior of the sort buttons
+
document.querySelectorAll('button.custom-sort:not([data-sort-key="shuffle"])').forEach((elt) => {
+
elt.addEventListener('click', (e) => {
+
e.preventDefault();
+
e.stopPropagation();
+
const btn = e.target.closest('button');
+
document.querySelectorAll('button.custom-sort:not([data-sort-key="'+btn.getAttribute('data-sort-key')+'"])').forEach((s) => {
+
s.classList.remove('sort-active');
+
});
+
if (btn.classList.contains('sort-active')) {
+
if (btn.getAttribute('data-sort-direction') === 'asc') {
+
btn.setAttribute('data-sort-direction', 'desc');
+
btn.querySelector('.icon').classList.remove('sort-asc');
+
btn.querySelector('.icon').classList.add('sort-desc');
+
} else {
+
btn.setAttribute('data-sort-direction', 'asc');
+
btn.querySelector('.icon').classList.remove('sort-desc');
+
btn.querySelector('.icon').classList.add('sort-asc');
+
}
+
afs.sort.sort(btn.getAttribute('data-sort-key'), btn.getAttribute('data-sort-direction'));
+
} else {
+
btn.classList.add('sort-active');
+
afs.sort.sort(btn.getAttribute('data-sort-key'), btn.getAttribute('data-sort-direction'));
+
}
+
});
+
});
+
+
// random sort button
+
document.querySelector('[data-sort-key="shuffle"]').addEventListener('click', (e) => {
+
afs.sort.shuffle();
+
});
+
</script>
+
{{ end }}
+36
hugo/layouts/baseof.html
···
+
<!DOCTYPE html>
+
<html lang="{{ with .Site.LanguageCode }}{{ . }}{{ else }}en-US{{ end }}">
+
+
<head>
+
<meta charset="utf-8">
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+
{{- partial "favicon.html" . -}}
+
<title>{{- block "title" . }}{{ .Site.Title }}{{ with .Title }} | {{ . }}{{ end }}{{- end }}</title>
+
+
{{- partial "seo_tags.html" . -}}
+
<meta name="referrer" content="no-referrer-when-downgrade" />
+
<link rel="manifest" href="./site.webmanifest">
+
+
{{ with .OutputFormats.Get "rss" -}}
+
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
+
{{ end -}}
+
+
{{- partial "style.html" . -}}
+
</head>
+
+
<body class="{{- block 'bodyClass' .}}{{- end }}">
+
<div id="banner">
+
<!-- uncomment the below line if banner is desired -->
+
<!-- <img src="!!YOURBANNER!!" alt="!!BANNERALT!!" /> -->
+
</div>
+
<div id="page">
+
{{- partial "header.html" . -}}
+
<main>
+
{{- block "main" . }}{{- end }}
+
</main>
+
<main>
+
{{- block "main" . }}{{- end }}
+
</main>
+
{{- partial "footer.html" . -}}
+
</body>
+
</html>
hugo/layouts/games/page.html

This is a binary file and will not be displayed.

+79
hugo/layouts/games/section.html
···
+
{{ define "bodyClass" }}submissions wide{{ end }}
+
+
{{ define "main" }}
+
<aside id="filters">
+
<div class="afs-filter-container">
+
<!-- Filter Controls -->
+
<div class="afs-filter-controls">
+
<!-- Basic Filters -->
+
+
<!-- Search Input -->
+
<input type="text" class="afs-filter-search" placeholder="Search by title, author, or tags" />
+
+
<p class="label">Sort entries by:</p>
+
<ul id="sorts">
+
<li><button class="custom-sort" data-sort-key="date" data-sort-direction="desc"> <span class="afs-sort-direction"><span class="icon sort-desc"></span></span> Date</button></li>
+
<li><button class="custom-sort" data-sort-key="title" data-sort-direction="asc"> <span class="afs-sort-direction"><span class="icon sort-desc"></span></span> Title</button></li>
+
<li><button class="custom-sort" data-sort-key="shuffle" data-sort-direction="desc"> <span class="afs-sort-direction"><span class="icon random"></span></span> Random</button></li>
+
</ul>
+
+
<details open><summary>Platform</summary>
+
<ul>
+
<li><button class="afs-btn-filter" data-filter="platforms:browser"><span class="icon web"></span> Play in browser</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:windows"><span class="icon windows"></span> Windows</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:macos"><span class="icon macos"></span> Mac OS</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:linux"><span class="icon linux"></span> Linux</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:android"><span class="icon android"></span> Android</button></li>
+
</ul>
+
</details>
+
+
<details><summary>Tags</summary>
+
<div id="tags"></div>
+
</details>
+
+
<details><summary>Submission Date</summary>
+
<div id="date-filter"></div>
+
</details>
+
+
<!-- Results Counter -->
+
<div class="afs-filter-counter"></div>
+
</div>
+
+
<!-- Pagination Container -->
+
<div class="afs-pagination-container"></div>
+
</div>
+
</aside>
+
<div id="list">
+
{{ range .Pages }}
+
<article class="item" data-date="{{ .Date }}" data-categories="" data-title="{{ .Title }}" data-authors="{{ if .Params.Authors }}{{ end }}">
+
<div class="thumb">
+
<a href="{{ .Permalink }}">
+
{{ $p := . }}
+
{{ with resources.Get .Params.Thumb }}
+
<img src="{{ .Permalink }}" alt="{{ $p.Title }} thumbnail image" class="thumb-img" />
+
{{ end }}
+
</a>
+
<div class="platform-icons">
+
{{ range .Params.Platforms }}
+
<span class="icon {{ . }}" title="{{ . }}">{{ . }}</span>
+
{{ end }}
+
</div>
+
</div>
+
<h3><a href="{{ .Permalink }}">{{ .Title }}</a></h3>
+
<div class="authors">
+
{{ if .Params.Authors }}
+
{{ range .Params.Authors }}
+
<a href="{{ .Link }}" target="_blank">{{ .Name }}</a>
+
{{ end }}
+
{{ else }}
+
Anonymous
+
{{ end }}
+
</div>
+
</article>
+
{{ end }}
+
</div>
+
{{ end }}
+
+
{{ define "scripts" }}
+
{{- partial "submissions_scripts.html" . -}}
+
{{ end }}
+33
hugo/layouts/home.html
···
+
{{ define "main" }}
+
<div class="clock">
+
<div class="dates" id="dates">
+
{{ $t2 := time.AsTime .Site.Params.EndDate }}
+
{{ if $t2.After time.Now }}
+
Submissions open from <b id="startDate" data-raw="{{ .Site.Params.StartDate }}">{{ .Site.Params.StartDate | time.Format "January 2, 2006 at 3:04pm" }}</b> to <b id="endDate" data-raw="{{ .Site.Params.EndDate}}">{{ .Site.Params.EndDate | time.Format "January 2, 2006 at 3:04pm" }}</b>
+
{{ else }}
+
The jam is now over. It ran from <b>{{ .Site.Params.StartDate | time.Format "January 2, 2006 at 3:04pm" }}</b> to <b>{{ .Site.Params.EndDate | time.Format "January 2, 2006 at 3:04pm" }}</b>. <a href="submissions.html">View X entr(y/ies)
+
{{ end }}
+
</div>
+
{{ if $t2.After time.Now }}
+
<div class="countdown">
+
<div class="counters">
+
<div class="verb">Starts in</div>
+
<div class="days"><span class="num" id="days">#</span><span class="caption">days</span></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>
+
</div>
+
</div>
+
<div class="join">
+
<a href="{{ .Site.Params.JoinLink }}" class="joinbtn">Join Jam</a>
+
</div>
+
{{ end }}
+
</div>
+
<div class="content">
+
{{ .Content }}
+
</div>
+
{{ end }}
+
+
{{ define "scripts" }}
+
{{- partial "home_scripts.html" . -}}
+
{{ end }}
+37
hugo/layouts/list.html
···
+
{{ define "main" }}
+
<content>
+
{{ if .Data.Singular }}
+
<h3 style="margin-bottom:0">Filtering for "{{ .Title }}"</h3>
+
<small>
+
<a href="{{ "blog" | relURL }}">Remove filter</a>
+
</small>
+
{{ end }}
+
<ul class="blog-posts">
+
{{ range .Pages }}
+
<li>
+
<span>
+
<i>
+
<time datetime='{{ .Date.Format "2006-01-02" }}'>
+
{{ .Date.Format (default "02 Jan, 2006" .Site.Params.dateFormat) }}
+
</time>
+
</i>
+
</span>
+
<a href="{{ .Permalink }}">{{ .Title }}</a>
+
</li>
+
{{ else }}
+
<li>
+
No posts yet
+
</li>
+
{{ end }}
+
</ul>
+
{{ if not .Data.Singular }}
+
<small>
+
<div>
+
{{ range .Site.Taxonomies.tags }}
+
<a href="{{ .Page.Permalink }}">#{{ .Page.Title }}</a>&nbsp;
+
{{ end }}
+
</div>
+
</small>
+
{{ end }}
+
</content>
+
{{ end }}
+2
hugo/layouts/robots.txt
···
+
User-Agent: *
+
Sitemap: {{ "sitemap.xml" | absURL }}
+25
hugo/layouts/single.html
···
+
{{ define "main" }}
+
{{ if eq .Type "blog" }}{{ if not .Params.menu }}
+
<h1>{{ .Title }}</h1>
+
<p>
+
<i>
+
<time datetime='{{ .Date.Format "2006-01-02" }}'>
+
{{ .Date.Format (default "02 Jan, 2006" .Site.Params.dateFormat) }}
+
</time>
+
</i>
+
</p>
+
{{ end }}{{ end }}
+
<content>
+
{{ .Content }}
+
</content>
+
+
{{ if eq .Type "blog" }}{{ if (.Param "enablePostNavigator")}}
+
{{- partial "post_navigator.html" . -}}
+
{{ end }}{{ end }}
+
+
<p>
+
{{ range (.GetTerms "tags") }}
+
<a href="{{ .Permalink }}">#{{ .LinkTitle }}</a>
+
{{ end }}
+
</p>
+
{{ end }}
+687
hugo/package-lock.json
···
+
{
+
"name": "hugo-bearblog",
+
"version": "1.0.0",
+
"lockfileVersion": 3,
+
"requires": true,
+
"packages": {
+
"": {
+
"name": "hugo-bearblog",
+
"version": "1.0.0",
+
"license": "MIT",
+
"devDependencies": {
+
"js-beautify": "^1.15.4"
+
}
+
},
+
"node_modules/@isaacs/cliui": {
+
"version": "8.0.2",
+
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+
"dev": true,
+
"license": "ISC",
+
"dependencies": {
+
"string-width": "^5.1.2",
+
"string-width-cjs": "npm:string-width@^4.2.0",
+
"strip-ansi": "^7.0.1",
+
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+
"wrap-ansi": "^8.1.0",
+
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+
},
+
"engines": {
+
"node": ">=12"
+
}
+
},
+
"node_modules/@one-ini/wasm": {
+
"version": "0.1.1",
+
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
+
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
+
"dev": true
+
},
+
"node_modules/@pkgjs/parseargs": {
+
"version": "0.11.0",
+
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+
"dev": true,
+
"license": "MIT",
+
"optional": true,
+
"engines": {
+
"node": ">=14"
+
}
+
},
+
"node_modules/abbrev": {
+
"version": "2.0.0",
+
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
+
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
+
"dev": true,
+
"license": "ISC",
+
"engines": {
+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+
}
+
},
+
"node_modules/ansi-regex": {
+
"version": "6.1.0",
+
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=12"
+
},
+
"funding": {
+
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
+
}
+
},
+
"node_modules/ansi-styles": {
+
"version": "6.2.1",
+
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=12"
+
},
+
"funding": {
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
+
}
+
},
+
"node_modules/balanced-match": {
+
"version": "1.0.2",
+
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+
"dev": true
+
},
+
"node_modules/brace-expansion": {
+
"version": "2.0.1",
+
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+
"dev": true,
+
"dependencies": {
+
"balanced-match": "^1.0.0"
+
}
+
},
+
"node_modules/color-convert": {
+
"version": "2.0.1",
+
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"color-name": "~1.1.4"
+
},
+
"engines": {
+
"node": ">=7.0.0"
+
}
+
},
+
"node_modules/color-name": {
+
"version": "1.1.4",
+
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+
"dev": true,
+
"license": "MIT"
+
},
+
"node_modules/commander": {
+
"version": "10.0.1",
+
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+
"dev": true,
+
"engines": {
+
"node": ">=14"
+
}
+
},
+
"node_modules/config-chain": {
+
"version": "1.1.13",
+
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+
"dev": true,
+
"dependencies": {
+
"ini": "^1.3.4",
+
"proto-list": "~1.2.1"
+
}
+
},
+
"node_modules/cross-spawn": {
+
"version": "7.0.6",
+
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"path-key": "^3.1.0",
+
"shebang-command": "^2.0.0",
+
"which": "^2.0.1"
+
},
+
"engines": {
+
"node": ">= 8"
+
}
+
},
+
"node_modules/eastasianwidth": {
+
"version": "0.2.0",
+
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+
"dev": true,
+
"license": "MIT"
+
},
+
"node_modules/editorconfig": {
+
"version": "1.0.4",
+
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
+
"integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
+
"dev": true,
+
"dependencies": {
+
"@one-ini/wasm": "0.1.1",
+
"commander": "^10.0.0",
+
"minimatch": "9.0.1",
+
"semver": "^7.5.3"
+
},
+
"bin": {
+
"editorconfig": "bin/editorconfig"
+
},
+
"engines": {
+
"node": ">=14"
+
}
+
},
+
"node_modules/emoji-regex": {
+
"version": "9.2.2",
+
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+
"dev": true,
+
"license": "MIT"
+
},
+
"node_modules/foreground-child": {
+
"version": "3.3.0",
+
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+
"dev": true,
+
"license": "ISC",
+
"dependencies": {
+
"cross-spawn": "^7.0.0",
+
"signal-exit": "^4.0.1"
+
},
+
"engines": {
+
"node": ">=14"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
}
+
},
+
"node_modules/glob": {
+
"version": "10.4.5",
+
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+
"dev": true,
+
"license": "ISC",
+
"dependencies": {
+
"foreground-child": "^3.1.0",
+
"jackspeak": "^3.1.2",
+
"minimatch": "^9.0.4",
+
"minipass": "^7.1.2",
+
"package-json-from-dist": "^1.0.0",
+
"path-scurry": "^1.11.1"
+
},
+
"bin": {
+
"glob": "dist/esm/bin.mjs"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
}
+
},
+
"node_modules/glob/node_modules/minimatch": {
+
"version": "9.0.5",
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+
"dev": true,
+
"license": "ISC",
+
"dependencies": {
+
"brace-expansion": "^2.0.1"
+
},
+
"engines": {
+
"node": ">=16 || 14 >=14.17"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
}
+
},
+
"node_modules/ini": {
+
"version": "1.3.8",
+
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+
"dev": true
+
},
+
"node_modules/is-fullwidth-code-point": {
+
"version": "3.0.0",
+
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/isexe": {
+
"version": "2.0.0",
+
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+
"dev": true,
+
"license": "ISC"
+
},
+
"node_modules/jackspeak": {
+
"version": "3.4.3",
+
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+
"dev": true,
+
"license": "BlueOak-1.0.0",
+
"dependencies": {
+
"@isaacs/cliui": "^8.0.2"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
},
+
"optionalDependencies": {
+
"@pkgjs/parseargs": "^0.11.0"
+
}
+
},
+
"node_modules/js-beautify": {
+
"version": "1.15.4",
+
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
+
"integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"config-chain": "^1.1.13",
+
"editorconfig": "^1.0.4",
+
"glob": "^10.4.2",
+
"js-cookie": "^3.0.5",
+
"nopt": "^7.2.1"
+
},
+
"bin": {
+
"css-beautify": "js/bin/css-beautify.js",
+
"html-beautify": "js/bin/html-beautify.js",
+
"js-beautify": "js/bin/js-beautify.js"
+
},
+
"engines": {
+
"node": ">=14"
+
}
+
},
+
"node_modules/js-cookie": {
+
"version": "3.0.5",
+
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
+
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+
"dev": true,
+
"engines": {
+
"node": ">=14"
+
}
+
},
+
"node_modules/lru-cache": {
+
"version": "6.0.0",
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+
"dev": true,
+
"dependencies": {
+
"yallist": "^4.0.0"
+
},
+
"engines": {
+
"node": ">=10"
+
}
+
},
+
"node_modules/minimatch": {
+
"version": "9.0.1",
+
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
+
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
+
"dev": true,
+
"dependencies": {
+
"brace-expansion": "^2.0.1"
+
},
+
"engines": {
+
"node": ">=16 || 14 >=14.17"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
}
+
},
+
"node_modules/minipass": {
+
"version": "7.1.2",
+
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+
"dev": true,
+
"license": "ISC",
+
"engines": {
+
"node": ">=16 || 14 >=14.17"
+
}
+
},
+
"node_modules/nopt": {
+
"version": "7.2.1",
+
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
+
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
+
"dev": true,
+
"license": "ISC",
+
"dependencies": {
+
"abbrev": "^2.0.0"
+
},
+
"bin": {
+
"nopt": "bin/nopt.js"
+
},
+
"engines": {
+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+
}
+
},
+
"node_modules/package-json-from-dist": {
+
"version": "1.0.1",
+
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+
"dev": true,
+
"license": "BlueOak-1.0.0"
+
},
+
"node_modules/path-key": {
+
"version": "3.1.1",
+
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/path-scurry": {
+
"version": "1.11.1",
+
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+
"dev": true,
+
"license": "BlueOak-1.0.0",
+
"dependencies": {
+
"lru-cache": "^10.2.0",
+
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+
},
+
"engines": {
+
"node": ">=16 || 14 >=14.18"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
}
+
},
+
"node_modules/path-scurry/node_modules/lru-cache": {
+
"version": "10.4.3",
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+
"dev": true,
+
"license": "ISC"
+
},
+
"node_modules/proto-list": {
+
"version": "1.2.4",
+
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+
"dev": true
+
},
+
"node_modules/semver": {
+
"version": "7.6.0",
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
+
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+
"dev": true,
+
"dependencies": {
+
"lru-cache": "^6.0.0"
+
},
+
"bin": {
+
"semver": "bin/semver.js"
+
},
+
"engines": {
+
"node": ">=10"
+
}
+
},
+
"node_modules/shebang-command": {
+
"version": "2.0.0",
+
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"shebang-regex": "^3.0.0"
+
},
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/shebang-regex": {
+
"version": "3.0.0",
+
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/signal-exit": {
+
"version": "4.1.0",
+
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+
"dev": true,
+
"license": "ISC",
+
"engines": {
+
"node": ">=14"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/isaacs"
+
}
+
},
+
"node_modules/string-width": {
+
"version": "5.1.2",
+
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"eastasianwidth": "^0.2.0",
+
"emoji-regex": "^9.2.2",
+
"strip-ansi": "^7.0.1"
+
},
+
"engines": {
+
"node": ">=12"
+
},
+
"funding": {
+
"url": "https://github.com/sponsors/sindresorhus"
+
}
+
},
+
"node_modules/string-width-cjs": {
+
"name": "string-width",
+
"version": "4.2.3",
+
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"emoji-regex": "^8.0.0",
+
"is-fullwidth-code-point": "^3.0.0",
+
"strip-ansi": "^6.0.1"
+
},
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/string-width-cjs/node_modules/ansi-regex": {
+
"version": "5.0.1",
+
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/string-width-cjs/node_modules/emoji-regex": {
+
"version": "8.0.0",
+
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+
"dev": true,
+
"license": "MIT"
+
},
+
"node_modules/string-width-cjs/node_modules/strip-ansi": {
+
"version": "6.0.1",
+
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"ansi-regex": "^5.0.1"
+
},
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/strip-ansi": {
+
"version": "7.1.0",
+
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"ansi-regex": "^6.0.1"
+
},
+
"engines": {
+
"node": ">=12"
+
},
+
"funding": {
+
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
+
}
+
},
+
"node_modules/strip-ansi-cjs": {
+
"name": "strip-ansi",
+
"version": "6.0.1",
+
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"ansi-regex": "^5.0.1"
+
},
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+
"version": "5.0.1",
+
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/which": {
+
"version": "2.0.2",
+
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+
"dev": true,
+
"license": "ISC",
+
"dependencies": {
+
"isexe": "^2.0.0"
+
},
+
"bin": {
+
"node-which": "bin/node-which"
+
},
+
"engines": {
+
"node": ">= 8"
+
}
+
},
+
"node_modules/wrap-ansi": {
+
"version": "8.1.0",
+
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"ansi-styles": "^6.1.0",
+
"string-width": "^5.0.1",
+
"strip-ansi": "^7.0.1"
+
},
+
"engines": {
+
"node": ">=12"
+
},
+
"funding": {
+
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+
}
+
},
+
"node_modules/wrap-ansi-cjs": {
+
"name": "wrap-ansi",
+
"version": "7.0.0",
+
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"ansi-styles": "^4.0.0",
+
"string-width": "^4.1.0",
+
"strip-ansi": "^6.0.0"
+
},
+
"engines": {
+
"node": ">=10"
+
},
+
"funding": {
+
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+
}
+
},
+
"node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+
"version": "5.0.1",
+
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+
"dev": true,
+
"license": "MIT",
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+
"version": "4.3.0",
+
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"color-convert": "^2.0.1"
+
},
+
"engines": {
+
"node": ">=8"
+
},
+
"funding": {
+
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
+
}
+
},
+
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+
"version": "8.0.0",
+
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+
"dev": true,
+
"license": "MIT"
+
},
+
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
+
"version": "4.2.3",
+
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"emoji-regex": "^8.0.0",
+
"is-fullwidth-code-point": "^3.0.0",
+
"strip-ansi": "^6.0.1"
+
},
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+
"version": "6.0.1",
+
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+
"dev": true,
+
"license": "MIT",
+
"dependencies": {
+
"ansi-regex": "^5.0.1"
+
},
+
"engines": {
+
"node": ">=8"
+
}
+
},
+
"node_modules/yallist": {
+
"version": "4.0.0",
+
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+
"dev": true
+
}
+
}
+
}
+28
hugo/package.json
···
+
{
+
"name": "homemade jam",
+
"private": true,
+
"version": "1.0.0",
+
"description": "A [Hugo](https://gohugo.io/) theme for running game (and other creative) jams.",
+
"main": "index.js",
+
"devDependencies": {
+
"js-beautify": "^1.15.4"
+
},
+
"scripts": {
+
"test": "npm run beautify",
+
"beautify": "js-beautify layouts/**/*.html -r"
+
},
+
"repository": {
+
"type": "git",
+
"url": "git+https://tangled.sh/@veryroundbird.house/homemadejam"
+
},
+
"author": {
+
"name": "Jan Raasch",
+
"email": "jan@janraasch.com",
+
"url": "https://www.janraasch.com"
+
},
+
"license": "MIT",
+
"bugs": {
+
"url": "https://tangled.sh/@veryroundbird.house/homemadejam/issues"
+
},
+
"homepage": "https://tangled.sh/@veryroundbird.house/homemadejam"
+
}
hugo/static/images/android-chrome-192x192.png

This is a binary file and will not be displayed.

hugo/static/images/android-chrome-512x512.png

This is a binary file and will not be displayed.

+1
hugo/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>
hugo/static/images/apple-touch-icon.png

This is a binary file and will not be displayed.

+1
hugo/static/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
hugo/static/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
hugo/static/images/favicon-16x16.png

This is a binary file and will not be displayed.

hugo/static/images/favicon-32x32.png

This is a binary file and will not be displayed.

hugo/static/images/favicon.ico

This is a binary file and will not be displayed.

+1
hugo/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
hugo/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
hugo/static/images/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></svg>
+1
hugo/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>
hugo/static/images/screenshot-dark.png

This is a binary file and will not be displayed.

hugo/static/images/screenshot.png

This is a binary file and will not be displayed.

+1
hugo/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
hugo/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>
hugo/static/images/tn.png

This is a binary file and will not be displayed.

+1
hugo/static/images/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></svg>
+1
hugo/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
hugo/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>
+1
hugo/static/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></svg>
+1
hugo/static/site.webmanifest
···
+
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
+20
hugo/theme.toml
···
+
name = "Homemade Jam"
+
license = "MIT"
+
licenselink = "i'll update this later"
+
description = "Theme for running game and other creative jams."
+
homepage = "https://tangled.sh/@veryroundbird/homemadejam"
+
demosite = ""
+
tags = []
+
features = []
+
min_version = "v0.110.0"
+
# https://gohugo.io/content-management/taxonomies#default-taxonomies
+
# https://gohugo.io/templates/taxonomy-templates/#example-list-tags-in-a-single-page-template
+
# https://gohugo.io/templates/taxonomy-templates/#example-list-all-site-tags
+
+
[author]
+
name = "Carly Smallbird"
+
homepage = "https://veryroundbird.house"
+
+
[taxonomies]
+
gametags = "gametags"
+
platforms = "platforms"
jekyll/_includes/banner.html

This is a binary file and will not be displayed.

+11 -1
jekyll/_includes/footer.html
···
-
<!-- Footer goes here. Such as your contact details, social media icons and copyright notice. -->
+
<footer>
+
<a href="https://veryroundbird.house" target="_blank">♥︎</a>
+
</footer>
+
<script type="module" src="{{ config.base_url }}/js/script.mjs"></script>
+
{% if config.extra.goatcounter_id %}
+
<script data-goatcounter="https://{{ config.goatcounter_id }}.goatcounter.com/count"
+
async src="//gc.zgo.at/count.js"></script>
+
{% endif %}
+
{% if config.extra.tinylytics_script_id %}
+
<script src="https://tinylytics.app/embed/{{ config.extra.tinylytics_script_id }}.js{% if config.extra.use_tinylytics_kudos %}?kudos={% if config.extra.tinylytics_kudos_emoji %}{{ config.extra.tinylytics_kudos_emoji }}{% else %}💖{% endif %}{% endif %}" defer></script>
+
{% endif %}
+24
jekyll/_includes/game_card.html
···
+
<article class="item" data-date="{{ include.page.date }}" data-categories="{% for tag in include.page.tags %}tags:{{ tag }}{% unless forloop.last %}&nbsp;{% endunless %}{% endfor %} {% for p in include.page.platforms %}platforms:{{ p }}{% unless forloop.last %}&nbsp;{% endunless %}{% endfor %}" data-title="{{ include.page.title }}" data-authors="{% if include.page.authors %}{{ include.page.authors | map: 'name' | join: ', ' }}{% endif %}">
+
<div class="thumb">
+
<a href="{{ include.page.url }}"><img src="{{ include.page.url }}/{{ include.page.thumbnail }}" alt="{{ include.page.title }} thumbnail image" class="thumb-img" /></a>
+
<div class="platform-icons">
+
{% for p in include.page.platforms %}
+
<span class="icon {{ p }}" title="{{ p }}">{{ p }}</span>
+
{% endfor %}
+
</div>
+
</div>
+
<h3><a href="{{ include.page.url }}">{{ include.page.title }}</a></h3>
+
<div class="authors">
+
{% if include.page.authors %}
+
{% for author in include.page.authors %}
+
{% if author.link != "" %}
+
<a href="{{ author.link }}" target="_blank">{{ author.name }}</a>
+
{% else %}
+
{{ author }}
+
{% endif -%}{% unless forloop.last -%}, {% endunless -%}
+
{% endfor -%}
+
{% else %}
+
Anonymous
+
{% endif %}
+
</div>
+
</article>
+84 -6
jekyll/_includes/head.html
···
-
<!-- Head goes here. Add your CSS and JavaScript -->
+
<head>
+
<meta charset="UTF-8">
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
{% if page.meta %}
+
<!-- the meta data config goes here -->
+
{% assign page_has_og_title = false -%}
+
{% assign page_has_og_description = false -%}
+
{% assign page_has_description = false -%}
+
{% for data in page.meta %}
+
<meta
+
{% for item in data %}
+
{% if item[0] == "property" and item[1] == "og:title"%}
+
{% assign page_has_og_title = true -%}
+
{% endif %}
+
{% if item[0] == "property" and item[1] == "og:description"%}
+
{% assign page_has_og_description = true -%}
+
{% endif %}
+
{% if item[0] == "name" and item[1] == "description"%}
+
{% assign page_has_description = true -%}
+
{% endif %}
+
{{ key }}="{{ value }}"
+
{% endfor %}
+
/>
+
{% endfor %}
+
{% endif %}
-
<style>
-
body {
-
font-family: Arial, Helvetica, Arial, sans-serif;
-
}
-
</style>
+
{% if current_path == "/" %}
+
<title>
+
{{ site.title }}
+
</title>
+
{% if not page_has_og_title %}
+
<meta property="og:title" content="{{ site.title }}" />
+
{% endif %}
+
{% else %}
+
<title>
+
{{ site.title }} > {% if page.title %} {{ page.title | lower }}
+
{% elsif section.title %} {{ section.title | lower }}
+
{% else %} post {% endif %}
+
</title>
+
+
{% if !page_has_og_title %}
+
<meta property="og:title" content="{% if page.title -%}{{ page.title | lower }}{% elsif section.title %}{{ section.title | lower }}{% elsif site.title -%}{{ site.title | lower }}{% else -%}post{% endif -%}" />
+
{% endif %}
+
{% endif %}
+
+
{% if !page_has_og_description %}
+
{% if page.description %}
+
<meta property="og:description" content="{{ page.description }}" />
+
{% elsif section.description %}
+
<meta property="og:description" content="{{ section.description }}" />
+
{% elsif site.description %}
+
<meta property="og:description" content="{{ site.description }}" />
+
{% endif %}
+
{% endif %}
+
+
{% if !page_has_description %}
+
{% if page.description %}
+
<meta name="description" content="{{ page.description }}" />
+
{% elsif section.description %}
+
<meta name="description" content="{{ section.description }}" />
+
{% elsif site.description %}
+
<meta name="description" content="{{ site.description }}" />
+
{% endif %}
+
{% endif %}
+
+
{% if site.favicon %}
+
<link rel="icon" type="image/png" sizes="16x16" href="{{ site.favicon }}" />
+
{% endif %}
+
+
{% if site.favicon32 %}
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ site.favicon32 }}" />
+
{% endif %}
+
+
{% if site.appletouch %}
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ site.appletouch }}" />
+
{% endif %}
+
+
{% if site.webmanifest %}
+
<link rel="manifest" href="{{ baseurl }}/site.webmanifest">
+
{% endif %}
+
+
<link rel="stylesheet" type="text/css" media="screen" href="{{ baseurl }}/style.css" />
+
</head>
+30 -1
jekyll/_includes/header.html
···
-
<!-- Header goes here. Such as your logo banner and navbar. -->
+
<header>
+
<h1>{{ site.title | safe }}</h1>
+
<p class="hosted">Hosted by <a href="{{ site.host_link }}" target="_blank">{{ site.host_name }}</a> &bull; {% if site.jam_hashtag != "" %}<a href="{{ site.jam_hashtag_link }}" target="_blank">#{{ site.jam_hashtag }}</a>{% endif %}</p>
+
{% if section and section.components | length == 0 %}
+
<div class="joined">
+
<span class="count" id="joinedCount">
+
+
</span>
+
<span class="caption">Joined</span>
+
</div>
+
{% else %}
+
{% assign games = get_section(path="games/_index.md") %}
+
<div class="entries">
+
<span class="count" id="entryCount">{{ games.pages | length }}</span>
+
<span class="caption">Entries</span>
+
</div>
+
{% endif %}
+
<nav>
+
<ul>
+
{% for link in site.navmenu %}
+
{% if link.path != '/' %}
+
{% assign link_full = link.path | append: '.html' %}
+
{% else %}
+
{% assign link_full = '/' %}
+
{% endif %}
+
<li><a href="{% unless link.external_link %}{{ baseurl }}{{ link.path }}{% else %}{{ link.external_url }}{% endunless %}"{% if link.newwin && link.newwin == true %} target="_blank"{% endif %}{% if link.path and page.url == link_full %} class="current"{% endif %}>{{ link.name }}</a></li>
+
{% endfor %}
+
</ul>
+
</nav>
+
</header>
+14 -20
jekyll/_layouts/default.html
···
-
<!DOCTYPE html>
-
<html lang="{{ page.lang | default: site.lang | default: "en" }}">
-
-
{% include head.html %}
-
-
<body>
-
-
{% include header.html %}
-
-
<main class="page-content" aria-label="Content">
-
<div class="wrapper">
-
{{ content }}
-
</div>
-
</main>
-
-
{% include footer.html %}
-
-
</body>
-
-
</html>
+
<!doctype html>
+
<html lang="{{ config.language }}">
+
{% include head.html %}
+
<body>
+
{% include banner.html %}
+
<div id="page" class="{{ layout.body_class }}">
+
{% include header.html %}
+
<main>
+
{{ content }}
+
</main>
+
{% include footer.html %}
+
</div>
+
</body>
+
</html>
+41
jekyll/_layouts/game.html
···
+
---
+
layout: default
+
body_class: game wide
+
---
+
<div class="game-header">
+
<p class="jamsub">A jam submission</p>
+
<h2>{{ page.title }} {% if page.website_link %}<a href="{{ page.website_link }}" target="_blank">View game website &rarr;</a>{% endif %}</h2>
+
<div class="blurb">
+
{{ page.description }}
+
</div>
+
<div class="authors">
+
Submitted by {% if page.authors %}{% for author in page.authors %}{% if author.link != "" %}<a href="{{ author.link }}" target="_blank">{{ author.name }}</a>{% else %}{{ author.name }}{% endif %}{% unless forloop.last %}, {% endunless %}{% endfor %}{% else %}Anonymous{% endif %} at <span class="submissiontime">{{ page.date }}</span>
+
</div>
+
</div>
+
<div class="screenshots">
+
<div class="gallery">
+
{% if page.screenshots %}
+
{% for screenshot in page.screenshots %}
+
<button popovertarget="img{{ loop.index }}"><img src="{{ screenshot.url }}" alt="{{ screenshot.alt }}" /></button>
+
<img src="{{ screenshot.url }}" alt="{{ screenshot.alt }}" popover id="img{{ forloop.index }}" />
+
{% endfor %}
+
{% endif %}
+
</div>
+
</div>
+
<div class="interaction">
+
<div class="downloads">
+
{{ content | safe }}
+
{% if page.downloads %}
+
<h3>Downloads</h3>
+
<ul>
+
{% for dl in page.downloads %}
+
<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>
+
{% endfor %}
+
</ul>
+
{% endif %}
+
</div>
+
<!-- uncomment if you want to drop in some kind of commenting system and put in whatever script you're using -->
+
<!--<div class="comments">
+
put comment code here
+
</div>-->
+
</div>
+18
jekyll/_layouts/home.html
···
+
---
+
layout: default
+
---
+
<div class="clock">
+
<div class="dates" id="dates">Submissions open from <b id="startDate" data-raw="{{ site.start_date }}">{{ site.start_date }}</b> to <b id="endDate" data-raw="{{ site.end_date }}">{{ site.end_date }}</b></div>
+
<div class="countdown">
+
<div class="counters">
+
<div class="verb">Starts in</div>
+
<div class="days"><span class="num" id="days">#</span><span class="caption">days</span></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>
+
</div>
+
</div>
+
<div class="join">
+
<a href="{{ site.join_link }}" class="joinbtn">Join Jam</a>
+
</div>
+
</div>
-7
jekyll/_layouts/page.html
···
-
---
-
layout: default
-
---
-
-
<h1>{{ page.title | escape }}</h1>
-
-
{{ content }}
-7
jekyll/_layouts/post.html
···
-
---
-
layout: default
-
---
-
-
<h1>{{ page.title | escape }}</h1>
-
-
{{ content }}
+61
jekyll/_layouts/submissions.html
···
+
---
+
body_class: submissions wide
+
layout: default
+
---
+
{{ content | safe }}
+
{{ page | jsonify }}
+
<aside id="filters">
+
<div class="afs-filter-container">
+
<!-- Filter Controls -->
+
<div class="afs-filter-controls">
+
<!-- Basic Filters -->
+
+
<!-- Search Input -->
+
<input type="text" class="afs-filter-search" placeholder="Search by title, author, or tags" />
+
+
<p class="label">Sort entries by:</p>
+
<ul id="sorts">
+
<li><button class="custom-sort" data-sort-key="date" data-sort-direction="desc"> <span class="afs-sort-direction"><span class="icon sort-desc"></span></span> Date</button></li>
+
<li><button class="custom-sort" data-sort-key="title" data-sort-direction="asc"> <span class="afs-sort-direction"><span class="icon sort-asc"></span></span> Title</button></li>
+
<li><button class="custom-sort" data-sort-key="shuffle" data-sort-direction="desc"><span class="icon random"></span></span> Random</button></li>
+
</ul>
+
+
<details open><summary>Platform</summary>
+
<ul>
+
<li><button class="afs-btn-filter" data-filter="platforms:browser"><span class="icon web"></span> Play in browser</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:windows"><span class="icon windows"></span> Windows</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:macos"><span class="icon macos"></span> Mac OS</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:linux"><span class="icon linux"></span> Linux</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:android"><span class="icon android"></span> Android</button></li>
+
</ul>
+
</details>
+
+
<details><summary>Tags</summary>
+
<div id="tags">
+
<button class="afs-btn-filter" data-filter="*">all</button>
+
{% for tag in site.tags %}
+
<button class="afs-btn-filter" data-filter="tags:{{ tag.name }}">#{{ tag.name }}</button>
+
{% endfor %}
+
</div>
+
</details>
+
+
<details><summary>Submission Date</summary>
+
<div id="date-filter"></div>
+
</details>
+
+
<!-- Results Counter -->
+
<div class="afs-filter-counter"></div>
+
</div>
+
+
<!-- Pagination Container -->
+
<div class="afs-pagination-container"></div>
+
</div>
+
</aside>
+
<section id="list">
+
{% for game in site.games %}
+
{%- if game.draft %}
+
{% continue %}
+
{% endif -%}
+
{% include game_card.html page=game %}
+
{% endfor %}
+
</section>
jekyll/_sass/.gitkeep

This is a binary file and will not be displayed.

+3
jekyll/_sass/_partials/_fonts.scss
···
+
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+116
jekyll/_sass/_partials/_game.scss
···
+
.game {
+
main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
+
h2 {
+
margin: 0;
+
+
a {
+
font-size: .9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
}
+
+
h3 {
+
margin: 0;
+
}
+
+
.blurb {
+
margin: 1em 0;
+
}
+
+
.game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
+
.jamsub {
+
font-size: .8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
}
+
+
.screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
+
.gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
+
a, button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
& > :first-child {
+
grid-area: featured;
+
}
+
}
+
}
+
+
.interaction {
+
grid-area: stuff;
+
}
+
+
.downloads {
+
padding: 20px;
+
+
ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
+
li {
+
margin-bottom: 10px;
+
}
+
}
+
+
.size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
+
.platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
+
.icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
+
.comments {
+
border-top: 1px var(--accent) solid;
+
}
+
}
+52
jekyll/_sass/_partials/_game_list_item.scss
···
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
+
h3 {
+
margin: 0;
+
font-size: 1.25em;
+
+
a {
+
color: var(--foreground);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.thumb {
+
position: relative;
+
padding-top: 75%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
.authors {
+
font-size: .9em;
+
margin: 5px 0;
+
+
a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.blurb {
+
margin-top: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
}
+192
jekyll/_sass/_partials/_global.scss
···
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
+
&:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
+
&.web {
+
mask: url(../images/web.svg);
+
}
+
+
&.windows {
+
mask: url(../images/windows.svg);
+
}
+
+
&.macos {
+
mask: url(../images/macos.svg);
+
}
+
+
&.linux {
+
mask: url(../images/linux.svg);
+
}
+
+
&.android {
+
mask: url(../images/android.svg);
+
}
+
+
&.random {
+
mask: url(../images/random.svg);
+
}
+
+
&.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
+
&.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
+
.active & {
+
background-color: var(--accent);
+
}
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
+
body.wide & {
+
max-width: none;
+
margin: 0;
+
}
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
+
h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
+
.hosted {
+
margin: 0;
+
}
+
+
.joined,
+
.entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
+
.count {
+
font-size: 2.25em;
+
display: block;
+
}
+
+
.caption {
+
font-size: .8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
}
+
+
nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
+
ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
+
li {
+
a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
+
&.current,
+
&:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
}
+
}
+
}
+
}
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
+
.submissions & {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
}
+
+
footer {
+
text-align: center;
+
font-size: .8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
+
a {
+
text-decoration: none;
+
}
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0,0,0,.5);
+
}
+83
jekyll/_sass/_partials/_homepage.scss
···
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
+
.dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
+
.countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
+
.counters {
+
display: flex;
+
align-items: stretch;
+
+
& > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
+
&:last-child {
+
border-right: none;
+
}
+
}
+
+
span {
+
display: block;
+
text-align: center;
+
+
&.num {
+
font-weight: bold;
+
}
+
+
&.caption {
+
font-size: .8em;
+
font-style: italic;
+
}
+
}
+
}
+
}
+
+
.join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
+
.joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
}
+
+
.content {
+
text-align: left;
+
}
+17
jekyll/_sass/_partials/_posts.scss
···
+
.post-list {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
text-align: left;
+
+
h3 {
+
font-weight: normal;
+
font-size: 1em;
+
+
.date {
+
margin-left: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
}
+106
jekyll/_sass/_partials/_submissions.scss
···
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
+
#tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
+
button {
+
white-space: pre;
+
}
+
}
+
+
details {
+
margin-bottom: 10px;
+
+
ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
}
+
+
p.label,
+
details summary {
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
+
ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
+
li {
+
button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: .9em;
+
+
img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
+
&.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
}
+
}
+
}
+
+
.afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
+
&.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
}
+
+
.afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
+
.afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: .9em;
+
}
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+13
jekyll/_sass/_partials/_variables.scss
···
+
/* display variables! skip the images if you don't want them */
+
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
+
--headingfont: 'Knewave', 'Arial Black', sans-serif;
+
--roundedCorners: 0px;
+
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+7
jekyll/_sass/style.scss
···
+
@use '_partials/_fonts';
+
@use '_partials/_variables';
+
@use '_partials/_global';
+
@use '_partials/_homepage';
+
@use '_partials/_submissions';
+
@use '_partials/_game_list_item';
+
@use '_partials/_game';
+409 -200
plain-html/css/style.css
···
-
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
@import url("https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap");
/* if you want to use different fonts, you can use other stuff from google fonts
if you don't want to use google, you may want to look into hosting your own fonts locally */
-
-
/* display variables! skip the images if you don't want them */
:root {
-
--background: #ECEBDE;
-
--foreground: #000000;
-
--accent: #A59D84;
-
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
-
--headingfont: 'Knewave', 'Arial Black', sans-serif;
-
--roundedCorners: 0px;
-
-
--pageBgImage: url();
-
--contentBgImage: url();
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: "Work Sans", Helvetica, Arial, sans-serif;
+
--headingfont: "Knewave", "Arial Black", sans-serif;
+
--roundedCorners: 0px;
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+
+
* {
+
box-sizing: border-box;
}
body {
-
background-color: var(--background);
-
background-image: url(--pageBgImage);
-
color: var(--foreground);
-
font-family: var(--mainfont);
-
font-size: 1em;
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
}
a {
-
color: var(--accent);
-
text-decoration: underline;
+
color: var(--accent);
+
text-decoration: underline;
+
}
+
a:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
}
+
.icon.web {
+
mask: url(../images/web.svg);
+
}
+
.icon.windows {
+
mask: url(../images/windows.svg);
+
}
+
.icon.macos {
+
mask: url(../images/macos.svg);
+
}
+
.icon.linux {
+
mask: url(../images/linux.svg);
+
}
+
.icon.android {
+
mask: url(../images/android.svg);
+
}
+
.icon.random {
+
mask: url(../images/random.svg);
+
}
+
.icon.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
.icon.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
.active .icon {
+
background-color: var(--accent);
}
-
a:hover {
-
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
}
+
.btn:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
}
#page {
-
max-width: 960px;
-
margin: 50px auto;
-
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
-
background-image: var(--contentBgImage);
-
border-radius: var(--roundedCorners);
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
}
-
body.wide #page {
-
max-width: none;
-
margin: 0;
+
max-width: none;
+
margin: 0;
}
header {
-
padding: 20px 20px 0;
-
position: relative;
-
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
}
-
header h1 {
-
font-size: 2.5em;
-
font-weight: bold;
-
margin: 0;
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
}
-
header .hosted {
-
margin: 0;
+
margin: 0;
}
-
header .joined,
header .entries {
-
text-align: center;
-
position: absolute;
-
top: 20px;
-
right: 20px;
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
}
-
header .joined .count,
header .entries .count {
-
font-size: 2.25em;
-
display: block;
+
font-size: 2.25em;
+
display: block;
}
-
header .joined .caption,
header .entries .caption {
-
font-size: .8em;c
-
display: block;
-
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
font-size: 0.8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
}
-
header nav {
-
margin-top: 20px;
-
padding-bottom: 10px;
+
margin-top: 20px;
+
padding-bottom: 10px;
}
-
header nav ul {
-
margin-bottom: 0;
-
display: flex;
-
gap: 10px;
-
list-style: none;
-
padding: 0;
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
}
-
header nav ul li a {
-
text-decoration: none;
-
padding: 5px 0;
-
border-bottom: 5px transparent solid;
-
color: var(--foreground);
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
}
-
-
header nav ul li a.current,
-
header nav ul li a:hover {
-
border-bottom: 5px var(--accent) solid;
-
color: var(--foreground);
+
header nav ul li a.current, header nav ul li a:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
}
main {
-
padding: 20px;
-
text-align: center;
+
padding: 20px;
+
text-align: center;
+
}
+
.submissions main {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
}
-
main .clock {
-
border: 1px var(--accent) solid;
-
border-radius: 5px;
-
display: inline-grid;
-
grid-template-areas: "date date" "countdown join";
-
margin: 50px auto;
+
footer {
+
text-align: center;
+
font-size: 0.8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
}
+
footer a {
+
text-decoration: none;
}
-
main .clock .dates {
-
border-bottom: 1px var(--accent) solid;
-
padding: 10px;
-
grid-area: date;
-
text-align: center;
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
}
-
main .clock .countdown {
-
grid-area: countdown;
-
border-right: 1px var(--accent) solid;
-
padding: 20px;
-
text-align: right;
-
display: flex;
-
align-items: center;
-
justify-content: flex-end;
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0, 0, 0, 0.5);
}
-
main .clock .countdown .counters {
-
display: flex;
-
align-items: stretch;
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
}
+
.clock .dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
.clock .countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
}
+
.clock .countdown .counters {
+
display: flex;
+
align-items: stretch;
+
}
+
.clock .countdown .counters > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
}
+
.clock .countdown .counters > div:last-child {
+
border-right: none;
+
}
+
.clock .countdown .counters span {
+
display: block;
+
text-align: center;
+
}
+
.clock .countdown .counters span.num {
+
font-weight: bold;
+
}
+
.clock .countdown .counters span.caption {
+
font-size: 0.8em;
+
font-style: italic;
+
}
+
.clock .join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
.clock .joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
}
+
.clock .joinbtn:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
}
-
main .clock .countdown .counters > div {
-
padding: 10px;
-
border-right: 2px var(--accent) solid;
-
display: flex;
-
flex-direction: column;
-
justify-content: center;
-
align-items: center;
-
white-space: pre;
+
.content {
+
text-align: left;
}
-
main .clock .countdown .counters > div:last-child {
-
border-right: none;
+
#filters {
+
grid-area: filters;
+
text-align: left;
}
-
-
main .clock .countdown .counters span {
-
display: block;
-
text-align: center;
+
#filters #tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
}
-
-
main .clock .countdown .counters span.num {
-
font-weight: bold;
+
#filters #tags button {
+
white-space: pre;
}
-
-
main .clock .countdown .counters span.caption {
-
font-size: .8em;
-
font-style: italic;
+
#filters details {
+
margin-bottom: 10px;
}
-
-
main .clock .join {
-
display: flex;
-
align-items: center;
-
justify-content: flex-start;
-
padding: 20px;
+
#filters details ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
}
-
-
main .clock .joinbtn {
-
padding: 10px 20px;
-
font-size: 1.25em;
-
font-weight: bold;
-
border-radius: 5px;
-
background-color: var(--accent);
-
color: var(--background);
-
text-decoration: none;
-
white-space: pre;
+
#filters p.label,
+
#filters details summary {
+
font-size: 0.8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
}
-
-
main .clock .joinbtn:hover {
-
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
#filters ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
}
-
-
main .content {
-
text-align: left;
+
#filters ul#sorts li button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: 0.9em;
}
-
-
footer {
-
text-align: center;
-
font-size: .8em;
-
padding: 5px 10px;
-
margin-top: 20px;
+
#filters ul#sorts li button img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
}
-
-
footer a {
-
text-decoration: none;
+
#filters ul#sorts li button.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
}
-
-
.submissions main {
-
display: grid;
-
grid-template-areas: "filters list";
-
grid-template-columns: 200px 1fr;
-
gap: 20px;
+
#filters .afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
}
-
-
.submissions #filters {
-
grid-area: filters;
+
#filters .afs-btn-filter.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
}
-
-
.submissions #list {
-
display: grid;
-
grid-area: list;
-
grid-template-columns: repeat(4, 1fr);
-
grid-template-rows: auto;
-
gap: 10px;
+
#filters .afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
}
-
-
.submissions #list .item {
-
text-align: left;
+
#filters .afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: 0.9em;
}
-
.submissions #list .item h3 {
-
margin: 0;
-
font-size: 1.25em;
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
}
-
.submissions #list .item h3 a {
-
color: var(--foreground);
-
text-decoration: none;
+
.item {
+
text-align: left;
+
border: 1px red solid;
}
-
-
.submissions #list .item h3 a:hover {
-
text-decoration: underline;
+
.item h3 {
+
margin: 0;
+
font-size: 1.25em;
}
-
-
.submissions #list .item .thumb {
-
position: relative;
-
padding-top: 75%;
+
.item h3 a {
+
color: var(--foreground);
+
text-decoration: none;
}
-
-
.submissions #list .item .thumb img {
-
position: absolute;
-
top: 0;
-
left: 0;
-
width: 100%;
-
height: 100%;
-
object-fit: cover;
+
.item h3 a:hover {
+
text-decoration: underline;
}
-
-
.submissions #list .item .authors {
-
font-size: .9em;
-
margin: 5px 0;
+
.item .thumb {
+
position: relative;
+
padding-top: 75%;
+
}
+
.item .thumb img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
}
-
-
.submissions #list .item .authors a {
-
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
-
text-decoration: none;
+
.item .authors {
+
font-size: 0.9em;
+
margin: 5px 0;
+
}
+
.item .authors a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
}
+
.item .authors a:hover {
+
text-decoration: underline;
+
}
+
.item .blurb {
+
margin-top: 5px;
+
font-size: 0.8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
}
-
.submissions #list .item .authors a:hover {
-
text-decoration: underline;
+
.game main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
}
+
.game main h2 {
+
margin: 0;
+
}
+
.game main h2 a {
+
font-size: 0.9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
.game main h3 {
+
margin: 0;
+
}
+
.game main .blurb {
+
margin: 1em 0;
+
}
+
.game main .game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
.game main .jamsub {
+
font-size: 0.8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
.game .screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
}
+
.game .screenshots .gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
}
+
.game .screenshots .gallery a, .game .screenshots .gallery button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
}
+
.game .screenshots .gallery a img, .game .screenshots .gallery button img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
.game .screenshots .gallery > :first-child {
+
grid-area: featured;
+
}
+
.game .interaction {
+
grid-area: stuff;
+
}
+
.game .downloads {
+
padding: 20px;
+
}
+
.game .downloads ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
}
+
.game .downloads ul li {
+
margin-bottom: 10px;
+
}
+
.game .downloads .size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
.game .downloads .platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
.game .downloads .icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
.game .comments {
+
border-top: 1px var(--accent) solid;
}
-
.submissions #list .item .blurb {
-
margin-top: 5px;
-
font-size: .8em;
-
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
-
}
+
/*# sourceMappingURL=style.css.map */
+1
plain-html/css/style.css.map
···
+
{"version":3,"sourceRoot":"","sources":["../../_raw-assets/scss/_partials/_fonts.scss","../../_raw-assets/scss/_partials/_variables.scss","../../_raw-assets/scss/_partials/_global.scss","../../_raw-assets/scss/_partials/_homepage.scss","../../_raw-assets/scss/_partials/_submissions.scss","../../_raw-assets/scss/_partials/_game_list_item.scss","../../_raw-assets/scss/_partials/_game.scss"],"names":[],"mappings":"AAAQ;AACR;AAAA;ACDA;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;;;ACXD;EACC;;;AAGD;EACC;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;;AAEA;EACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;;AAIF;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAGD;EACC;;AAGD;AAAA;EAEC;EACA;EACA;EACA;;AAEA;AAAA;EACC;EACA;;AAGD;AAAA;EACC;EACA;EACA;;AAIF;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;;AAGC;EACC;EACA;EACA;EACA;;AAEA;EAEC;EACA;;;AAQN;EACC;EACA;;AAEA;EACC;EACA;EACA;;;AAIF;EACC;EACA;EACA;EACA;;AAEA;EACC;;;AAIF;EACC;EACA;EACA;EACA;;;AAGD;EACC;;;AC9LD;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;;AAEA;EACC;;AAGD;EACC;EACA;;AAMJ;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;;AAKH;EACC;;;ACjFD;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;;AAEA;EACC;EACA;EACA;;AAIF;AAAA;EAEC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;;AAMJ;EACC;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAIF;EACC;EACC;EACA;EACA;EACA;EACA;EACA;EACD;EACA;;AAGD;EACC;EACA;EACA;;;AAIF;EACC;EACA;EACA;EACA;EACA;;;ACxGD;EACC;EACA;;AAEA;EACC;EACA;;AAEA;EACC;EACA;;AAEA;EACC;;AAKH;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;;AAIF;EACC;EACA;;AAEA;EACC;EACA;;AAEA;EACC;;AAKH;EACC;EACA;EACA;;;AChDD;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAIF;EACC;;AAGD;EACC;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;;AAIF;EACC;;AAKH;EACC;;AAGD;EACC;;AAEA;EACC;EACA;EACA;;AAEA;EACC;;AAIF;EACC;;AAGD;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAIF;EACC","file":"style.css"}
+1 -1
plain-html/data/games.json
···
"link": "https://games.birdwrongs.sh"
}
],
-
"platforms": ["win", "mac"],
+
"platforms": ["windows", "macos"],
"submitTime": "2026-02-15T11:05:45",
"thumbnail": "https://images.unsplash.com/photo-1658069778823-40c13a2dd2e4?q=80&w=1480&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
"tags": ["yuri", "horror"],
+80
plain-html/game.html
···
+
<!doctype html>
+
<html>
+
<head>
+
<title>!!YOUR GAME JAM TITLE!! | !! GAME NAME !!</title>
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
<link rel="stylesheet" type="text/css" href="./css/style.css" />
+
<link rel="stylesheet" type="text/css" href="./css/custom.css" />
+
<link rel="apple-touch-icon" sizes="180x180" href="./images/apple-touch-icon.png">
+
<link rel="icon" type="image/png" sizes="32x32" href="./images/favicon-32x32.png">
+
<link rel="icon" type="image/png" sizes="16x16" href="./images/favicon-16x16.png">
+
<link rel="manifest" href="./site.webmanifest">
+
</head>
+
<body class="wide game">
+
<div id="banner">
+
<!-- uncomment the below line if banner is desired -->
+
<!-- <img src="!!YOURBANNER!!" alt="!!BANNERALT!!" /> -->
+
</div>
+
<div id="page">
+
<header>
+
<h1>!!YOUR GAME JAM TITLE!!</h1>
+
<p class="hosted">Hosted by <a href="!!YOURLINK!!" target="_blank">!!YOURNAME!!</a> &bull; <a href="!!LINK TO HASHTAG FILTER!!" target="_blank">#!!HASHTAG!!</a></p>
+
<div class="entries">
+
<span class="count" id="entriesCount">!!#!!</span>
+
<span class="caption">Entries</span>
+
</div>
+
<nav>
+
<ul>
+
<li><a href="index.html">Overview</a></li>
+
<!-- uncomment the below if you have a discord or a forum or something -->
+
<!-- <li><a href="!!COMMUNITY LINK!!">Community</a></li> -->
+
<li><a href="submissions.html" class="current">Submissions</a></li>
+
</ul>
+
</nav>
+
</header>
+
<main>
+
<div class="game-header">
+
<p class="jamsub">A jam submission</p>
+
<h2>!! GAME TITLE !! <a href="#">View game website &rarr;</a></h2>
+
<div class="blurb">
+
!! BLURB GOES HERE !!
+
</div>
+
<div class="authors">
+
Submitted by <a href="#">Author 1</a>, <a href="#">Author 2</a> at <span class="submissiontime">!! SUBMISSION TIME !!</span>
+
</div>
+
</div>
+
<div class="screenshots">
+
<div class="gallery">
+
<button popovertarget="img1"><img src="https://images.unsplash.com/photo-1756151224665-eba765e8c3b5?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /></button>
+
<button popovertarget="img2"><img src="https://images.unsplash.com/photo-1754922493956-364a7623a016?q=80&w=2150&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /></button>
+
<button popovertarget="img3"><img src="https://images.unsplash.com/photo-1755429518361-1d6060edcf3c?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /></button>
+
<button popovertarget="img4"><img src="https://images.unsplash.com/photo-1755603461859-9da81ff3afea?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /></button>
+
<button popovertarget="img5"><img src="https://images.unsplash.com/photo-1755467020939-4c3e196545bd?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" /></button>
+
</div>
+
<img src="https://images.unsplash.com/photo-1756151224665-eba765e8c3b5?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" popover id="img1" />
+
<img src="https://images.unsplash.com/photo-1754922493956-364a7623a016?q=80&w=2150&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" popover id="img2" />
+
<img src="https://images.unsplash.com/photo-1755429518361-1d6060edcf3c?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" popover id="img3" />
+
<img src="https://images.unsplash.com/photo-1755603461859-9da81ff3afea?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" popover id="img4" />
+
<img src="https://images.unsplash.com/photo-1755467020939-4c3e196545bd?q=80&w=2340&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" popover id="img5" />
+
</div>
+
<div class="interaction">
+
<div class="downloads">
+
<h3>Downloads</h3>
+
<ul>
+
<li><a href="!! DL LINK !!" class="btn" download>Download</a> <b>!! FILE NAME !!</b> <span class="size">!! # MB !!</span> <span class="platforms"><span class="platforms-label">Platforms: </span><span class="icon windows" title="Windows">Windows</span><span class="icon linux" title="Linux">Linux</span></li>
+
<li><a href="!! DL LINK !!" class="btn" download>Download</a> <b>!! FILE NAME !!</b> <span class="size">!! # MB !!</span> <span class="platforms"><span class="platforms-label">Platforms: </span><span class="icon macos" title="MacOS">MacOS</span></li>
+
</ul>
+
</div>
+
<!-- uncomment if you want to drop in some kind of commenting system and put in whatever script you're using -->
+
<!--<div class="comments">
+
put comment code here
+
</div>-->
+
</div>
+
</main>
+
<footer>
+
<a href="https://veryroundbird.house">♥︎</a>
+
</footer>
+
</div>
+
<script type="module" src="./js/script.mjs"></script>
+
</body>
+
</html>
+1
plain-html/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>
+1
plain-html/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
plain-html/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
+1
plain-html/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
plain-html/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
plain-html/images/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></svg>
+1
plain-html/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
plain-html/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
plain-html/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
plain-html/images/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></svg>
+1
plain-html/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
plain-html/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>
+1
plain-html/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></svg>
+1
plain-html/index.html
···
<html>
<head>
<title>!!YOUR GAME JAM TITLE!!</title>
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="./css/style.css" />
<link rel="stylesheet" type="text/css" href="./css/custom.css" />
<link rel="apple-touch-icon" sizes="180x180" href="./images/apple-touch-icon.png">
+1 -1
plain-html/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",v=d.borderRadius||"4px",$=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: ${$};\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: ${v};\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.exclusiveFilterTypes=new Set,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{const e=this.afs.options.get("filterMode")||"OR",[s]=t.split(":"),n=this.exclusiveFilterTypes.has(s);if(("OR"===e||n)&&s&&t.includes(":")&&this.filterButtons.forEach(((i,e)=>{i!==t&&i.startsWith(s+":")&&(e.classList.remove(this.afs.options.get("activeClass")),this.activeFilters.delete(i))})),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.afs.emit("filterRemoved",{filter:t,activeFilters:Array.from(this.activeFilters)}),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)}setFilterTypeExclusive(t,i=!0){(Array.isArray(t)?t:[t]).forEach((t=>{i?(this.exclusiveFilterTypes.add(t),this.afs.logger.debug(`Set filter type '${t}' as exclusive`)):(this.exclusiveFilterTypes.delete(t),this.afs.logger.debug(`Removed exclusive behavior from filter type '${t}'`))})),this.applyFilters()}toggleFilterExclusive(t){this.afs.logger.debug("Toggling filter exclusively: "+t);const[i]=t.split(":");if(!i||!t.includes(":"))return void this.afs.logger.warn("Filter value must be in format 'type:value'");this.activeFilters.delete("*");const e=this.findAllButton();e&&e.classList.remove(this.afs.options.get("activeClass"));let s=null;if(this.filterButtons.forEach(((i,e)=>{i===t&&(s=e)})),!s)return void this.afs.logger.warn("No button found for filter: "+t);const n=this.activeFilters.has(t);if(this.filterButtons.forEach(((t,e)=>{t.startsWith(i+":")&&(e.classList.remove(this.afs.options.get("activeClass")),this.activeFilters.delete(t))})),n){if(0===this.activeFilters.size)return void this.resetFilters()}else s.classList.add(this.afs.options.get("activeClass")),this.activeFilters.add(t);this.applyFilters(),this.afs.urlManager.updateURL(),this.afs.emit("filterToggledExclusive",{filter:t,type:i,activeFilters:Array.from(this.activeFilters)})}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.4.1";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};
+
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};
//# sourceMappingURL=afs.modern.js.map
+105 -104
plain-html/js/script.mjs
···
// Basic variable replacements
const numJoined = 0;
-
const numEntries = 0;
// SEE HERE FOR DATE FORMAT INFO:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format
···
const list = document.getElementById('list');
+
const allTags = games.map(g => g.tags).reduce((g1, g2) => {
+
return g1.concat(g2);
+
}).filter((t, i, arr) => { return arr.indexOf(t) === i }).sort();
+
const dayMult = 24*60*60;
const hourMult = 60*60;
const minuteMult = 60;
if (joinedElt) joinedElt.textContent = numJoined;
-
if (entriesElt) entriesElt.textContent = numEntries;
+
if (entriesElt) entriesElt.textContent = games.length;
if (startDateElt) startDateElt.textContent = startString;
if (endDateElt) endDateElt.textContent = endString;
···
if (list) {
list.innerHTML = games.map((item, i) => {
-
return `<div class="item" id="item-${i}">
+
return `<div class="item" id="item-${i}" data-authors="${item.authors.map(a => a.name)}" data-categories="${item.tags.map(t => 'tags:'+t).join(" ")} ${item.platforms.map(p => 'platforms:'+p).join(" ")}" data-title="${item.title}" data-date="${item.submitTime}">
<div class="thumb">
-
<img src="${item.thumbnail}" alt="${item.title} thumbnail image" />
+
<a href="${item.page}"><img src="${item.thumbnail}" alt="${item.title} thumbnail image" /></a>
</div>
<h3><a href="${item.page}">${item.title}</a></h3>
<div class="authors">${item.authors.map((auth) => { return `<a href="${auth.link}" target="_blank">${auth.name}</a>`; }).join(", ")}</div>
<div class="blurb">${item.blurb}</div>
</div>`;
}).join("");
-
}
-
-
const afs = new AFS({
-
// Required Selectors
-
containerSelector: 'main',
-
itemSelector: '.item',
-
filterButtonSelector: '.afs-btn-filter',
-
searchInputSelector: '.afs-filter-search',
-
counterSelector: '.afs-filter-counter',
+
+
const tagsElt = document.getElementById('tags');
+
tagsElt.innerHTML = `<button class="afs-btn-filter" data-filter="*">all</button>`+allTags.map((t) => {
+
return `<button class="afs-btn-filter" data-filter="tags:${t}">#${t}</button>`
+
}).join("");
+
+
const afs = new AFS({
+
// Required Selectors
+
containerSelector: '#list',
+
itemSelector: '.item',
-
// CSS Classes
-
activeClass: 'active',
-
hiddenClass: 'hidden',
-
transitionClass: 'afs-transition',
+
// CSS Classes
+
activeClass: 'active',
+
hiddenClass: 'hidden',
+
transitionClass: 'afs-transition',
+
searchKeys: ['title', 'authors', 'tags'],
+
debounceTime: 200, // search input delay
-
// Filter & Search Configuration
-
filterMode: 'OR', // or 'AND'
-
groupMode: 'AND', // or 'OR'
-
searchKeys: ['title', 'categories', 'tags'],
-
debounceTime: 200, // search input delay
+
// Date Handling
+
dateFormat: 'YYYY-MM-DD',
+
dateFilter: {
+
enabled: true,
+
format: 'YYYY-MM-DDThh:mm:ss'
+
},
-
// Debug Options
-
debug: false,
-
logLevel: 'info', // 'debug', 'info', 'warn', 'error'
-
-
// Date Handling
-
dateFormat: 'YYYY-MM-DD',
-
-
// Counter Configuration
-
counter: {
-
template: 'Showing {visible} of {total}',
-
showFiltered: true,
-
filteredTemplate: '({filtered} filtered)',
-
noResultsTemplate: 'No items found',
-
formatter: (num) => num.toLocaleString()
-
},
-
-
// Slider Configuration
-
slider: {
-
containerClass: 'afs-range-slider',
-
trackClass: 'afs-range-track',
-
thumbClass: 'afs-range-thumb',
-
valueClass: 'afs-range-value',
-
selectedClass: 'afs-range-selected',
-
ui: {
-
showHistogram: false,
-
bins: 10,
-
track: {
-
radius: '0',
-
background: '#e5e7eb'
-
},
-
selected: {
-
background: '#000'
-
},
-
thumb: {
-
radius: '50%',
-
size: '16px',
-
background: '#000'
-
},
-
histogram: {
-
background: '#e5e7eb',
-
bar: {
-
background: '#000'
-
}
-
}
-
}
-
},
-
-
// Pagination Configuration
-
pagination: {
-
enabled: false,
-
itemsPerPage: 10,
-
container: '.afs-pagination-container',
-
pageButtonClass: 'afs-page-button',
-
activePageClass: 'afs-page-active',
-
containerClass: 'afs-pagination',
-
scrollToTop: false,
-
scrollOffset: 50,
-
scrollBehavior: 'smooth' // or 'auto'
-
},
+
// Counter Configuration
+
counter: {
+
template: 'Showing {visible} of {total}',
+
showFiltered: true,
+
filteredTemplate: '({filtered} filtered)',
+
noResultsTemplate: 'No items found',
+
formatter: (num) => num.toLocaleString()
+
},
+
+
sort: {
+
enabled: true,
+
buttonSelector: '.afs-btn-sort'
+
},
+
+
// Animation Configuration
+
animation: {
+
type: 'fade',
+
duration: 200,
+
easing: 'ease-out',
+
inClass: 'afs-animation-enter',
+
outClass: 'afs-animation-leave'
+
},
-
// Animation Configuration
-
animation: {
-
type: 'fade',
-
duration: 200,
-
easing: 'ease-out',
-
inClass: 'afs-animation-enter',
-
outClass: 'afs-animation-leave'
-
},
+
// Lifecycle Options
+
responsive: true,
+
preserveState: false,
+
stateExpiry: 86400000, // 24 hours
+
observeDOM: false,
-
// Lifecycle Options
-
responsive: true,
-
preserveState: false,
-
stateExpiry: 86400000, // 24 hours
-
observeDOM: false,
+
// Style Configuration
+
styles: {
+
colors: {
+
primary: '#000',
+
background: '#e5e7eb',
+
text: '#000',
+
textHover: '#fff'
+
}
+
}
+
});
+
+
// add date range filter
+
afs.dateFilter.addDateRange({
+
key: 'date',
+
container: document.querySelector('#date-filter'),
+
format: 'YYYY-MM-DD',
+
minDate: new Date(startDate.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0]),
+
maxDate: new Date(endDate.match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0])
+
});
+
+
// fixes some behavior of the sort buttons
+
document.querySelectorAll('button.custom-sort:not([data-sort-key="shuffle"])').forEach((elt) => {
+
elt.addEventListener('click', (e) => {
+
e.preventDefault();
+
e.stopPropagation();
+
const btn = e.target.closest('button');
+
document.querySelectorAll('button.custom-sort:not([data-sort-key="'+btn.getAttribute('data-sort-key')+'"])').forEach((s) => {
+
s.classList.remove('sort-active');
+
});
+
if (btn.classList.contains('sort-active')) {
+
if (btn.getAttribute('data-sort-direction') === 'asc') {
+
btn.setAttribute('data-sort-direction', 'desc');
+
btn.querySelector('img').src = './images/sort-desc.svg';
+
} else {
+
btn.setAttribute('data-sort-direction', 'asc');
+
btn.querySelector('img').src = './images/sort-asc.svg';
+
}
+
afs.sort.sort(btn.getAttribute('data-sort-key'), btn.getAttribute('data-sort-direction'));
+
} else {
+
btn.classList.add('sort-active');
+
afs.sort.sort(btn.getAttribute('data-sort-key'), btn.getAttribute('data-sort-direction'));
+
}
+
});
+
});
-
// Style Configuration
-
styles: {
-
colors: {
-
primary: '#000',
-
background: '#e5e7eb',
-
text: '#000',
-
textHover: '#fff'
-
}
-
}
-
});
+
// random sort button
+
document.querySelector('[data-sort-key="shuffle"]').addEventListener('click', (e) => {
+
afs.sort.shuffle();
+
});
+
}
+28 -7
plain-html/submissions.html
···
<!doctype html>
<html>
<head>
-
<title>!!YOUR GAME JAM TITLE!!</title>
+
<title>!!YOUR GAME JAM TITLE!! | Submissions</title>
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="./css/style.css" />
<link rel="stylesheet" type="text/css" href="./css/custom.css" />
<link rel="apple-touch-icon" sizes="180x180" href="./images/apple-touch-icon.png">
···
<!-- Filter Controls -->
<div class="afs-filter-controls">
<!-- Basic Filters -->
-
<div class="basic-filters">
-
<button class="afs-btn-filter" data-filter="*">All</button>
-
<button class="afs-btn-filter" data-filter="category:tech">Technology</button>
-
<button class="afs-btn-filter" data-filter="category:design">Design</button>
-
</div>
<!-- Search Input -->
-
<input type="text" class="afs-filter-search" placeholder="Search...">
+
<input type="text" class="afs-filter-search" placeholder="Search by title, author, or tags" />
+
+
<p class="label">Sort entries by:</p>
+
<ul id="sorts">
+
<li><button class="custom-sort" data-sort-key="date" data-sort-direction="desc"> <span class="afs-sort-direction"><img src="./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="./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="./images/sort-desc.svg" alt="Sort descending" /></span> Random</button></li>
+
</ul>
+
+
<details open><summary>Platform</summary>
+
<ul>
+
<li><button class="afs-btn-filter" data-filter="platforms:browser"><img src="./images/web.svg" alt="" class="icon" /> Play in browser</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:windows"><img src="./images/windows.svg" alt="" class="icon" /> Windows</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:macos"><img src="./images/macos.svg" alt="" class="icon" /> Mac OS</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:linux"><img src="./images/linux.svg" alt="" class="icon" /> Linux</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:android"><img src="./images/android.svg" alt="" class="icon" /> Android</button></li>
+
</ul>
+
</details>
+
+
<details><summary>Tags</summary>
+
<div id="tags"></div>
+
</details>
+
+
<details><summary>Submission Date</summary>
+
<div id="date-filter"></div>
+
</details>
<!-- Results Counter -->
<div class="afs-filter-counter"></div>
+490
plain-php/css/style.css
···
+
@import url("https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap");
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+
/* display variables! skip the images if you don't want them */
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: "Work Sans", Helvetica, Arial, sans-serif;
+
--headingfont: "Knewave", "Arial Black", sans-serif;
+
--roundedCorners: 0px;
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
}
+
a:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
}
+
.icon.web {
+
mask: url(../images/web.svg);
+
}
+
.icon.windows {
+
mask: url(../images/windows.svg);
+
}
+
.icon.macos {
+
mask: url(../images/macos.svg);
+
}
+
.icon.linux {
+
mask: url(../images/linux.svg);
+
}
+
.icon.android {
+
mask: url(../images/android.svg);
+
}
+
.icon.random {
+
mask: url(../images/random.svg);
+
}
+
.icon.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
.icon.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
.active .icon {
+
background-color: var(--accent);
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
}
+
.btn:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
}
+
body.wide #page {
+
max-width: none;
+
margin: 0;
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
}
+
header h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
header .hosted {
+
margin: 0;
+
}
+
header .joined,
+
header .entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
}
+
header .joined .count,
+
header .entries .count {
+
font-size: 2.25em;
+
display: block;
+
}
+
header .joined .caption,
+
header .entries .caption {
+
font-size: 0.8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
header nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
}
+
header nav ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
}
+
header nav ul li a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
}
+
header nav ul li a.current, header nav ul li a:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
}
+
.submissions main {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
+
footer {
+
text-align: center;
+
font-size: 0.8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
}
+
footer a {
+
text-decoration: none;
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0, 0, 0, 0.5);
+
}
+
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
}
+
.clock .dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
.clock .countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
}
+
.clock .countdown .counters {
+
display: flex;
+
align-items: stretch;
+
}
+
.clock .countdown .counters > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
}
+
.clock .countdown .counters > div:last-child {
+
border-right: none;
+
}
+
.clock .countdown .counters span {
+
display: block;
+
text-align: center;
+
}
+
.clock .countdown .counters span.num {
+
font-weight: bold;
+
}
+
.clock .countdown .counters span.caption {
+
font-size: 0.8em;
+
font-style: italic;
+
}
+
.clock .join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
.clock .joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
}
+
.clock .joinbtn:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
+
.content {
+
text-align: left;
+
}
+
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
}
+
#filters #tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
}
+
#filters #tags button {
+
white-space: pre;
+
}
+
#filters details {
+
margin-bottom: 10px;
+
}
+
#filters details ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
#filters p.label,
+
#filters details summary {
+
font-size: 0.8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
#filters ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
}
+
#filters ul#sorts li button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: 0.9em;
+
}
+
#filters ul#sorts li button img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
#filters ul#sorts li button.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
#filters .afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
}
+
#filters .afs-btn-filter.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
#filters .afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
#filters .afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: 0.9em;
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
}
+
.item h3 {
+
margin: 0;
+
font-size: 1.25em;
+
}
+
.item h3 a {
+
color: var(--foreground);
+
text-decoration: none;
+
}
+
.item h3 a:hover {
+
text-decoration: underline;
+
}
+
.item .thumb {
+
position: relative;
+
padding-top: 75%;
+
}
+
.item .thumb img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
.item .authors {
+
font-size: 0.9em;
+
margin: 5px 0;
+
}
+
.item .authors a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
}
+
.item .authors a:hover {
+
text-decoration: underline;
+
}
+
.item .blurb {
+
margin-top: 5px;
+
font-size: 0.8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
+
.game main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
}
+
.game main h2 {
+
margin: 0;
+
}
+
.game main h2 a {
+
font-size: 0.9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
.game main h3 {
+
margin: 0;
+
}
+
.game main .blurb {
+
margin: 1em 0;
+
}
+
.game main .game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
.game main .jamsub {
+
font-size: 0.8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
.game .screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
}
+
.game .screenshots .gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
}
+
.game .screenshots .gallery a, .game .screenshots .gallery button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
}
+
.game .screenshots .gallery a img, .game .screenshots .gallery button img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
.game .screenshots .gallery > :first-child {
+
grid-area: featured;
+
}
+
.game .interaction {
+
grid-area: stuff;
+
}
+
.game .downloads {
+
padding: 20px;
+
}
+
.game .downloads ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
}
+
.game .downloads ul li {
+
margin-bottom: 10px;
+
}
+
.game .downloads .size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
.game .downloads .platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
.game .downloads .icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
.game .comments {
+
border-top: 1px var(--accent) solid;
+
}
+
+
/*# sourceMappingURL=style.css.map */
+1
plain-php/css/style.css.map
···
+
{"version":3,"sourceRoot":"","sources":["../../_raw-assets/scss/_partials/_fonts.scss","../../_raw-assets/scss/_partials/_variables.scss","../../_raw-assets/scss/_partials/_global.scss","../../_raw-assets/scss/_partials/_homepage.scss","../../_raw-assets/scss/_partials/_submissions.scss","../../_raw-assets/scss/_partials/_game_list_item.scss","../../_raw-assets/scss/_partials/_game.scss"],"names":[],"mappings":"AAAQ;AACR;AAAA;ACDA;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;;;ACXD;EACC;;;AAGD;EACC;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;;AAEA;EACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;AAGD;EACC;;;AAIF;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;;AAIF;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAGD;EACC;;AAGD;AAAA;EAEC;EACA;EACA;EACA;;AAEA;AAAA;EACC;EACA;;AAGD;AAAA;EACC;EACA;EACA;;AAIF;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;;AAGC;EACC;EACA;EACA;EACA;;AAEA;EAEC;EACA;;;AAQN;EACC;EACA;;AAEA;EACC;EACA;EACA;;;AAIF;EACC;EACA;EACA;EACA;;AAEA;EACC;;;AAIF;EACC;EACA;EACA;EACA;;;AAGD;EACC;;;AC9LD;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;EACA;;AAEA;EACC;;AAGD;EACC;EACA;;AAMJ;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;;AAKH;EACC;;;ACjFD;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAEA;EACC;;AAIF;EACC;;AAEA;EACC;EACA;EACA;;AAIF;AAAA;EAEC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAGC;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;;AAMJ;EACC;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAIF;EACC;EACC;EACA;EACA;EACA;EACA;EACA;EACD;EACA;;AAGD;EACC;EACA;EACA;;;AAIF;EACC;EACA;EACA;EACA;EACA;;;ACxGD;EACC;EACA;;AAEA;EACC;EACA;;AAEA;EACC;EACA;;AAEA;EACC;;AAKH;EACC;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;;AAIF;EACC;EACA;;AAEA;EACC;EACA;;AAEA;EACC;;AAKH;EACC;EACA;EACA;;;AChDD;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;;AAEA;EACC;EACA;EACA;EACA;;AAIF;EACC;;AAGD;EACC;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;EACA;;AAIF;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;;AAEA;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;EACA;EACA;;AAIF;EACC;;AAKH;EACC;;AAGD;EACC;;AAEA;EACC;EACA;EACA;;AAEA;EACC;;AAIF;EACC;;AAGD;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;EACA;;AAIF;EACC","file":"style.css"}
plain-php/images/android-chrome-192x192.png

This is a binary file and will not be displayed.

plain-php/images/android-chrome-512x512.png

This is a binary file and will not be displayed.

+1
plain-php/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>
plain-php/images/apple-touch-icon.png

This is a binary file and will not be displayed.

+1
plain-php/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
plain-php/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
plain-php/images/favicon-16x16.png

This is a binary file and will not be displayed.

plain-php/images/favicon-32x32.png

This is a binary file and will not be displayed.

plain-php/images/favicon.ico

This is a binary file and will not be displayed.

+1
plain-php/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
plain-php/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
plain-php/images/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></svg>
+1
plain-php/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
plain-php/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
plain-php/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
plain-php/images/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></svg>
+1
plain-php/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
plain-php/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>
+1
plain-php/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></svg>
+25
wordpress/.editorconfig
···
+
root = true
+
+
[*]
+
charset = utf-8
+
end_of_line = lf
+
insert_final_newline = true
+
indent_style = space
+
indent_size = 2
+
trim_trailing_whitespace = true
+
quote_type = single
+
+
[*.md]
+
trim_trailing_whitespace = false
+
+
[*.php]
+
indent_size = 4
+
+
[*.blade.php]
+
indent_size = 2
+
+
[resources/views/**.php]
+
indent_size = 2
+
+
[index.php]
+
indent_size = 2
+6
wordpress/.gitignore
···
+
/node_modules
+
/vendor
+
/public/*
+
!/public/.gitkeep
+
.env
+
npm-debug.log
+19
wordpress/LICENSE.md
···
+
Copyright (c) Roots Software LLC
+
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
+
this software and associated documentation files (the "Software"), to deal in
+
the Software without restriction, including without limitation the rights to
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+
of the Software, and to permit persons to whom the Software is furnished to do
+
so, subject to the following conditions:
+
+
The above copyright notice and this permission notice shall be included in all
+
copies or substantial portions of the Software.
+
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+
SOFTWARE.
+31
wordpress/README.md
···
+
<p align="center">
+
<a href="https://roots.io/sage/"><img alt="Sage" src="https://cdn.roots.io/app/uploads/logo-sage.svg" height="100"></a>
+
</p>
+
+
<p align="center">
+
<a href="https://packagist.org/packages/roots/sage"><img alt="Packagist Installs" src="https://img.shields.io/packagist/dt/roots/sage?label=projects%20created&colorB=2b3072&colorA=525ddc&style=flat-square"></a>
+
<a href="https://github.com/roots/sage/actions/workflows/main.yml"><img alt="Build Status" src="https://img.shields.io/github/actions/workflow/status/roots/sage/main.yml?branch=main&logo=github&label=CI&style=flat-square"></a>
+
<a href="https://bsky.app/profile/roots.dev"><img alt="Follow roots.dev on Bluesky" src="https://img.shields.io/badge/follow-@roots.dev-0085ff?logo=bluesky&style=flat-square"></a>
+
</p>
+
+
# Sage
+
+
**Advanced hybrid WordPress starter theme with Laravel Blade and Tailwind CSS**
+
+
- 🔧 Clean, efficient theme templating with Laravel Blade
+
- ⚡️ Modern front-end development workflow powered by Vite
+
- 🎨 Out of the box support for Tailwind CSS
+
- 🚀 Harness the power of Laravel with [Acorn integration](https://github.com/roots/acorn)
+
- 📦 Block editor support built-in
+
+
Sage brings proper PHP templating and modern JavaScript tooling to WordPress themes. Write organized, component-based code using Laravel Blade, enjoy instant builds and CSS hot-reloading with Vite, and leverage Laravel's robust feature set through Acorn.
+
+
[Read the docs to get started](https://roots.io/sage/docs/installation/)
+
+
## Sponsors
+
+
Sage is an open source project and completely free to use. If you've benefited from our projects and would like to support our future endeavors, [please consider sponsoring us](https://github.com/sponsors/roots).
+
+
<div align="center">
+
<a href="https://carrot.com/"><img src="https://cdn.roots.io/app/uploads/carrot.svg" alt="Carrot" width="120" height="90"></a> <a href="https://wordpress.com/"><img src="https://cdn.roots.io/app/uploads/wordpress.svg" alt="WordPress.com" width="120" height="90"></a> <a href="https://worksitesafety.ca/careers/"><img src="https://cdn.roots.io/app/uploads/worksite-safety.svg" alt="Worksite Safety" width="120" height="90"></a> <a href="https://40q.agency/"><img src="https://cdn.roots.io/app/uploads/40q.svg" alt="40Q" width="120" height="90"></a> <a href="https://www.itineris.co.uk/"><img src="https://cdn.roots.io/app/uploads/itineris.svg" alt="Itineris" width="120" height="90"></a> <a href="https://bonsai.so/"><img src="https://cdn.roots.io/app/uploads/bonsai.svg" alt="Bonsai" width="120" height="90"></a>
+
</div>
+28
wordpress/app/Providers/ThemeServiceProvider.php
···
+
<?php
+
+
namespace App\Providers;
+
+
use Roots\Acorn\Sage\SageServiceProvider;
+
+
class ThemeServiceProvider extends SageServiceProvider
+
{
+
/**
+
* Register any application services.
+
*
+
* @return void
+
*/
+
public function register()
+
{
+
parent::register();
+
}
+
+
/**
+
* Bootstrap any application services.
+
*
+
* @return void
+
*/
+
public function boot()
+
{
+
parent::boot();
+
}
+
}
+25
wordpress/app/View/Composers/App.php
···
+
<?php
+
+
namespace App\View\Composers;
+
+
use Roots\Acorn\View\Composer;
+
+
class App extends Composer
+
{
+
/**
+
* List of views served by this composer.
+
*
+
* @var array
+
*/
+
protected static $views = [
+
'*',
+
];
+
+
/**
+
* Retrieve the site name.
+
*/
+
public function siteName(): string
+
{
+
return get_bloginfo('name', 'display');
+
}
+
}
+90
wordpress/app/View/Composers/Comments.php
···
+
<?php
+
+
namespace App\View\Composers;
+
+
use Roots\Acorn\View\Composer;
+
+
class Comments extends Composer
+
{
+
/**
+
* List of views served by this composer.
+
*
+
* @var array
+
*/
+
protected static $views = [
+
'partials.comments',
+
];
+
+
/**
+
* The comment title.
+
*/
+
public function title(): string
+
{
+
return sprintf(
+
/* translators: %1$s is replaced with the number of comments and %2$s with the post title */
+
_nx('%1$s response to &ldquo;%2$s&rdquo;', '%1$s responses to &ldquo;%2$s&rdquo;', get_comments_number(), 'comments title', 'sage'),
+
get_comments_number() === 1 ? _x('One', 'comments title', 'sage') : number_format_i18n(get_comments_number()),
+
get_the_title()
+
);
+
}
+
+
/**
+
* Retrieve the comments.
+
*/
+
public function responses(): ?string
+
{
+
if (! have_comments()) {
+
return null;
+
}
+
+
return wp_list_comments([
+
'style' => 'ol',
+
'short_ping' => true,
+
'echo' => false,
+
]);
+
}
+
+
/**
+
* The previous comments link.
+
*/
+
public function previous(): ?string
+
{
+
if (! get_previous_comments_link()) {
+
return null;
+
}
+
+
return get_previous_comments_link(
+
__('&larr; Older comments', 'sage')
+
);
+
}
+
+
/**
+
* The next comments link.
+
*/
+
public function next(): ?string
+
{
+
if (! get_next_comments_link()) {
+
return null;
+
}
+
+
return get_next_comments_link(
+
__('Newer comments &rarr;', 'sage')
+
);
+
}
+
+
/**
+
* Determine if the comments are paginated.
+
*/
+
public function paginated(): bool
+
{
+
return get_comment_pages_count() > 1 && get_option('page_comments');
+
}
+
+
/**
+
* Determine if the comments are closed.
+
*/
+
public function closed(): bool
+
{
+
return ! comments_open() && get_comments_number() != '0' && post_type_supports(get_post_type(), 'comments');
+
}
+
}
+67
wordpress/app/View/Composers/Post.php
···
+
<?php
+
+
namespace App\View\Composers;
+
+
use Roots\Acorn\View\Composer;
+
+
class Post extends Composer
+
{
+
/**
+
* List of views served by this composer.
+
*
+
* @var array
+
*/
+
protected static $views = [
+
'partials.page-header',
+
'partials.content',
+
'partials.content-*',
+
];
+
+
/**
+
* Retrieve the post title.
+
*/
+
public function title(): string
+
{
+
if ($this->view->name() !== 'partials.page-header') {
+
return get_the_title();
+
}
+
+
if (is_home()) {
+
if ($home = get_option('page_for_posts', true)) {
+
return get_the_title($home);
+
}
+
+
return __('Latest Posts', 'sage');
+
}
+
+
if (is_archive()) {
+
return get_the_archive_title();
+
}
+
+
if (is_search()) {
+
return sprintf(
+
/* translators: %s is replaced with the search query */
+
__('Search Results for %s', 'sage'),
+
get_search_query()
+
);
+
}
+
+
if (is_404()) {
+
return __('Not Found', 'sage');
+
}
+
+
return get_the_title();
+
}
+
+
/**
+
* Retrieve the pagination links.
+
*/
+
public function pagination(): string
+
{
+
return wp_link_pages([
+
'echo' => 0,
+
'before' => '<p>'.__('Pages:', 'sage'),
+
'after' => '</p>',
+
]);
+
}
+
}
+16
wordpress/app/filters.php
···
+
<?php
+
+
/**
+
* Theme filters.
+
*/
+
+
namespace App;
+
+
/**
+
* Add "… Continued" to the excerpt.
+
*
+
* @return string
+
*/
+
add_filter('excerpt_more', function () {
+
return sprintf(' &hellip; <a href="%s">%s</a>', get_permalink(), __('Continued', 'sage'));
+
});
+270
wordpress/app/setup.php
···
+
<?php
+
+
/**
+
* Theme setup.
+
*/
+
+
namespace App;
+
+
use Illuminate\Support\Facades\Vite;
+
+
/**
+
* Inject styles into the block editor.
+
*
+
* @return array
+
*/
+
add_filter('block_editor_settings_all', function ($settings) {
+
$style = Vite::asset('resources/css/editor.scss');
+
+
$settings['styles'][] = [
+
'css' => "@import url('{$style}')",
+
];
+
+
return $settings;
+
});
+
+
/**
+
* Inject scripts into the block editor.
+
*
+
* @return void
+
*/
+
add_filter('admin_head', function () {
+
if (! get_current_screen()?->is_block_editor()) {
+
return;
+
}
+
+
$dependencies = json_decode(Vite::content('editor.deps.json'));
+
+
foreach ($dependencies as $dependency) {
+
if (! wp_script_is($dependency)) {
+
wp_enqueue_script($dependency);
+
}
+
}
+
+
echo Vite::withEntryPoints([
+
'resources/js/editor.js',
+
])->toHtml();
+
});
+
+
/**
+
* Use the generated theme.json file.
+
*
+
* @return string
+
*/
+
add_filter('theme_file_path', function ($path, $file) {
+
return $file === 'theme.json'
+
? public_path('build/assets/theme.json')
+
: $path;
+
}, 10, 2);
+
+
/**
+
* Register the initial theme setup.
+
*
+
* @return void
+
*/
+
add_action('after_setup_theme', function () {
+
/**
+
* Disable full-site editing support.
+
*
+
* @link https://wptavern.com/gutenberg-10-5-embeds-pdfs-adds-verse-block-color-options-and-introduces-new-patterns
+
*/
+
remove_theme_support('block-templates');
+
+
\register_post_type('game', [
+
'label' => 'Games',
+
'public' => true,
+
'show_in_rest' => true,
+
'supports' => [
+
'title',
+
'editor',
+
'custom-fields',
+
'revisions',
+
'trackbacks',
+
'comments',
+
'author',
+
'excerpt',
+
'thumbnail'
+
],
+
'taxonomies' => [
+
'game_tag',
+
'game_platform'
+
],
+
'register_meta_box_cb' => function () {
+
\add_meta_box(
+
'screenshots',
+
'Screenshots',
+
function () {
+
global $post;
+
wp_enqueue_media();
+
wp_enqueue_script('media-upload');
+
wp_enqueue_style( 'screenshot_css', Vite::asset('resources/css/screenshot.scss') );
+
// Add an nonce field so we can check for it later.
+
wp_nonce_field( 'screenshots_metabox', 'screenshots_metabox' );
+
+
$value = get_post_custom_values('_screenshots', $post->ID);
+
+
// Display the form, using the current value.
+
?>
+
<label for="myplugin_new_field">
+
<?php _e( 'Screenshots', 'homemadejam' ); ?>
+
</label>
+
<div class="screenshots">
+
<div class="screenshot"><a href="#" id="open-gallery-screenshots">Add Screenshots</a></div>
+
<?php if ($value) : ?>
+
<?php foreach($value as $img) : ?>
+
<a href="#" class="gallery-img"><?php print_r($img); ?></a>
+
<?php endforeach; ?>
+
<?php endif; ?>
+
</div>
+
<input type="hidden" name="_screenshots" id="screenshots" value="<?php echo esc_attr($value); ?>" />
+
<?php
+
},
+
'game',
+
'normal',
+
'core'
+
);
+
\add_meta_box(
+
'downloads',
+
'Downloads',
+
function () {
+
+
},
+
'game',
+
'normal',
+
'core'
+
);
+
}
+
]);
+
+
\register_post_type('joined', [
+
'public' => false,
+
'show_ui' => true,
+
'supports' => [
+
'title',
+
'custom-fields',
+
'thumbnail'
+
]
+
]);
+
+
\register_taxonomy('game_tag', ['game'], [
+
'labels' => [
+
'name' => 'Tags',
+
'singular_name' => 'Tag'
+
],
+
'public' => true,
+
'show_in_rest' => true
+
]);
+
+
\register_taxonomy('game_platform', ['game'], [
+
'labels' => [
+
'name' => 'Platforms',
+
'singular_name' => 'Platform'
+
],
+
'hierarchical' => true,
+
'public' => true,
+
'show_in_rest' => true
+
]);
+
+
if (!term_exists('windows', 'game_platform')) {
+
\wp_insert_term('windows', 'game_platform');
+
}
+
+
if (!term_exists('macos', 'game_platform')) {
+
\wp_insert_term('macos', 'game_platform');
+
}
+
+
if (!term_exists('linux', 'game_platform')) {
+
\wp_insert_term('linux', 'game_platform');
+
}
+
+
if (!term_exists('android', 'game_platform')) {
+
\wp_insert_term('android', 'game_platform');
+
}
+
+
if (!term_exists('web', 'game_platform')) {
+
\wp_insert_term('web', 'game_platform');
+
}
+
+
/**
+
* Register the navigation menus.
+
*
+
* @link https://developer.wordpress.org/reference/functions/register_nav_menus/
+
*/
+
register_nav_menus([
+
'primary_navigation' => __('Primary Navigation', 'sage'),
+
]);
+
+
/**
+
* Disable the default block patterns.
+
*
+
* @link https://developer.wordpress.org/block-editor/developers/themes/theme-support/#disabling-the-default-block-patterns
+
*/
+
remove_theme_support('core-block-patterns');
+
+
/**
+
* Enable plugins to manage the document title.
+
*
+
* @link https://developer.wordpress.org/reference/functions/add_theme_support/#title-tag
+
*/
+
add_theme_support('title-tag');
+
+
/**
+
* Enable post thumbnail support.
+
*
+
* @link https://developer.wordpress.org/themes/functionality/featured-images-post-thumbnails/
+
*/
+
add_theme_support('post-thumbnails');
+
+
/**
+
* Enable responsive embed support.
+
*
+
* @link https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-support/#responsive-embedded-content
+
*/
+
add_theme_support('responsive-embeds');
+
+
/**
+
* Enable HTML5 markup support.
+
*
+
* @link https://developer.wordpress.org/reference/functions/add_theme_support/#html5
+
*/
+
add_theme_support('html5', [
+
'caption',
+
'comment-form',
+
'comment-list',
+
'gallery',
+
'search-form',
+
'script',
+
'style',
+
]);
+
+
/**
+
* Enable selective refresh for widgets in customizer.
+
*
+
* @link https://developer.wordpress.org/reference/functions/add_theme_support/#customize-selective-refresh-widgets
+
*/
+
add_theme_support('customize-selective-refresh-widgets');
+
}, 20);
+
+
/**
+
* Register the theme sidebars.
+
*
+
* @return void
+
*/
+
add_action('widgets_init', function () {
+
$config = [
+
'before_widget' => '<section class="widget %1$s %2$s">',
+
'after_widget' => '</section>',
+
'before_title' => '<h3>',
+
'after_title' => '</h3>',
+
];
+
+
register_sidebar([
+
'name' => __('Primary', 'sage'),
+
'id' => 'sidebar-primary',
+
] + $config);
+
+
register_sidebar([
+
'name' => __('Footer', 'sage'),
+
'id' => 'sidebar-footer',
+
] + $config);
+
});
+496
wordpress/bun.lock
···
+
{
+
"lockfileVersion": 1,
+
"workspaces": {
+
"": {
+
"name": "sage",
+
"devDependencies": {
+
"@roots/vite-plugin": "^1.0.0",
+
"@tailwindcss/vite": "^4.0.0",
+
"laravel-vite-plugin": "^2.0.0",
+
"sass-embedded": "^1.92.0",
+
},
+
},
+
},
+
"trustedDependencies": [
+
"@tailwindcss/oxide",
+
],
+
"packages": {
+
"@bufbuild/protobuf": ["@bufbuild/protobuf@2.7.0", "", {}, "sha512-qn6tAIZEw5i/wiESBF4nQxZkl86aY4KoO0IkUa2Lh+rya64oTOdJQFlZuMwI1Qz9VBJQrQC4QlSA2DNek5gCOA=="],
+
+
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
+
+
"@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
+
+
"@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.9", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="],
+
+
"@esbuild/android-x64": ["@esbuild/android-x64@0.25.9", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="],
+
+
"@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="],
+
+
"@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="],
+
+
"@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="],
+
+
"@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="],
+
+
"@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.9", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="],
+
+
"@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="],
+
+
"@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.9", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="],
+
+
"@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="],
+
+
"@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="],
+
+
"@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="],
+
+
"@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="],
+
+
"@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="],
+
+
"@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.9", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="],
+
+
"@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="],
+
+
"@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.9", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="],
+
+
"@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.9", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="],
+
+
"@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.9", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="],
+
+
"@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="],
+
+
"@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.9", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="],
+
+
"@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="],
+
+
"@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="],
+
+
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
+
+
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
+
+
"@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+
"@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
+
+
"@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+
"@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
+
+
"@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
+
+
"@parcel/watcher": ["@parcel/watcher@2.5.1", "", { "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", "micromatch": "^4.0.5", "node-addon-api": "^7.0.0" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.1", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-darwin-x64": "2.5.1", "@parcel/watcher-freebsd-x64": "2.5.1", "@parcel/watcher-linux-arm-glibc": "2.5.1", "@parcel/watcher-linux-arm-musl": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-arm64-musl": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", "@parcel/watcher-linux-x64-musl": "2.5.1", "@parcel/watcher-win32-arm64": "2.5.1", "@parcel/watcher-win32-ia32": "2.5.1", "@parcel/watcher-win32-x64": "2.5.1" } }, "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg=="],
+
+
"@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.1", "", { "os": "android", "cpu": "arm64" }, "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA=="],
+
+
"@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw=="],
+
+
"@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg=="],
+
+
"@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ=="],
+
+
"@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA=="],
+
+
"@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q=="],
+
+
"@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w=="],
+
+
"@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg=="],
+
+
"@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A=="],
+
+
"@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.1", "", { "os": "linux", "cpu": "x64" }, "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg=="],
+
+
"@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw=="],
+
+
"@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ=="],
+
+
"@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="],
+
+
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.0", "", { "os": "android", "cpu": "arm" }, "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ=="],
+
+
"@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.0", "", { "os": "android", "cpu": "arm64" }, "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw=="],
+
+
"@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg=="],
+
+
"@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw=="],
+
+
"@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ=="],
+
+
"@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA=="],
+
+
"@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w=="],
+
+
"@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg=="],
+
+
"@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g=="],
+
+
"@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ=="],
+
+
"@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ=="],
+
+
"@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg=="],
+
+
"@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA=="],
+
+
"@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ=="],
+
+
"@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ=="],
+
+
"@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA=="],
+
+
"@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw=="],
+
+
"@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.0", "", { "os": "none", "cpu": "arm64" }, "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q=="],
+
+
"@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg=="],
+
+
"@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw=="],
+
+
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg=="],
+
+
"@roots/vite-plugin": ["@roots/vite-plugin@1.1.0", "", { "dependencies": { "@wordpress/dependency-extraction-webpack-plugin": "^6.27.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-9nG9G452QCoOll/O8V6v9lqJKdjMTo9XCC7l9Ka1cne6yxR4ace1k6BIqxvRMXissnmKprhVGh9DQKTlfliEyA=="],
+
+
"@tailwindcss/node": ["@tailwindcss/node@4.1.13", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.5.1", "lightningcss": "1.30.1", "magic-string": "^0.30.18", "source-map-js": "^1.2.1", "tailwindcss": "4.1.13" } }, "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw=="],
+
+
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.13", "", { "dependencies": { "detect-libc": "^2.0.4", "tar": "^7.4.3" }, "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.13", "@tailwindcss/oxide-darwin-arm64": "4.1.13", "@tailwindcss/oxide-darwin-x64": "4.1.13", "@tailwindcss/oxide-freebsd-x64": "4.1.13", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", "@tailwindcss/oxide-linux-x64-musl": "4.1.13", "@tailwindcss/oxide-wasm32-wasi": "4.1.13", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" } }, "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA=="],
+
+
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.13", "", { "os": "android", "cpu": "arm64" }, "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew=="],
+
+
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ=="],
+
+
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw=="],
+
+
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.13", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ=="],
+
+
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.13", "", { "os": "linux", "cpu": "arm" }, "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw=="],
+
+
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ=="],
+
+
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg=="],
+
+
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.13", "", { "os": "linux", "cpu": "x64" }, "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ=="],
+
+
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.13", "", { "os": "linux", "cpu": "x64" }, "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.13", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@emnapi/wasi-threads": "^1.0.4", "@napi-rs/wasm-runtime": "^0.2.12", "@tybys/wasm-util": "^0.10.0", "tslib": "^2.8.0" }, "cpu": "none" }, "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA=="],
+
+
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg=="],
+
+
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.13", "", { "os": "win32", "cpu": "x64" }, "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw=="],
+
+
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.13", "", { "dependencies": { "@tailwindcss/node": "4.1.13", "@tailwindcss/oxide": "4.1.13", "tailwindcss": "4.1.13" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ=="],
+
+
"@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="],
+
+
"@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="],
+
+
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+
+
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
+
+
"@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="],
+
+
"@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="],
+
+
"@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="],
+
+
"@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="],
+
+
"@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="],
+
+
"@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="],
+
+
"@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="],
+
+
"@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="],
+
+
"@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="],
+
+
"@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="],
+
+
"@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="],
+
+
"@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="],
+
+
"@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="],
+
+
"@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="],
+
+
"@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="],
+
+
"@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="],
+
+
"@wordpress/dependency-extraction-webpack-plugin": ["@wordpress/dependency-extraction-webpack-plugin@6.30.0", "", { "dependencies": { "json2php": "^0.0.7" }, "peerDependencies": { "webpack": "^5.0.0" } }, "sha512-sms4yRJriS8vzlwbYHII/xqI64oSY5ALbfQy6HJBSCfLJCNxVOzC/2fCrhdV9ghd8nK3NMAJKhTCe09oMPCnIw=="],
+
+
"@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="],
+
+
"@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="],
+
+
"acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
+
+
"acorn-import-phases": ["acorn-import-phases@1.0.4", "", { "peerDependencies": { "acorn": "^8.14.0" } }, "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ=="],
+
+
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
+
+
"ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
+
+
"ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="],
+
+
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
+
+
"browserslist": ["browserslist@4.25.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg=="],
+
+
"buffer-builder": ["buffer-builder@0.2.0", "", {}, "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg=="],
+
+
"buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
+
+
"caniuse-lite": ["caniuse-lite@1.0.30001741", "", {}, "sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw=="],
+
+
"chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
+
+
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
+
+
"chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="],
+
+
"colorjs.io": ["colorjs.io@0.5.2", "", {}, "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw=="],
+
+
"commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
+
+
"detect-libc": ["detect-libc@2.0.4", "", {}, "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA=="],
+
+
"electron-to-chromium": ["electron-to-chromium@1.5.214", "", {}, "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q=="],
+
+
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
+
+
"es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
+
+
"esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
+
+
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+
"eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="],
+
+
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
+
+
"estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="],
+
+
"events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
+
+
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
+
+
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
+
+
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
+
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+
"glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="],
+
+
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+
+
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+
"immutable": ["immutable@5.1.3", "", {}, "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg=="],
+
+
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
+
+
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
+
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+
+
"jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="],
+
+
"jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="],
+
+
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
+
+
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
+
+
"json2php": ["json2php@0.0.7", "", {}, "sha512-dnSoUiLAoVaMXxFsVi4CrPVYMKOuDBXTghXSmMINX44RZ8WM9cXlY7UqrQnlAcODCVO7FV3+8t/5nDKAjimLfg=="],
+
+
"laravel-vite-plugin": ["laravel-vite-plugin@2.0.1", "", { "dependencies": { "picocolors": "^1.0.0", "vite-plugin-full-reload": "^1.1.0" }, "peerDependencies": { "vite": "^7.0.0" }, "bin": { "clean-orphaned-assets": "bin/clean.js" } }, "sha512-zQuvzWfUKQu9oNVi1o0RZAJCwhGsdhx4NEOyrVQwJHaWDseGP9tl7XUPLY2T8Cj6+IrZ6lmyxlR1KC8unf3RLA=="],
+
+
"lightningcss": ["lightningcss@1.30.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.30.1", "lightningcss-darwin-x64": "1.30.1", "lightningcss-freebsd-x64": "1.30.1", "lightningcss-linux-arm-gnueabihf": "1.30.1", "lightningcss-linux-arm64-gnu": "1.30.1", "lightningcss-linux-arm64-musl": "1.30.1", "lightningcss-linux-x64-gnu": "1.30.1", "lightningcss-linux-x64-musl": "1.30.1", "lightningcss-win32-arm64-msvc": "1.30.1", "lightningcss-win32-x64-msvc": "1.30.1" } }, "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg=="],
+
+
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ=="],
+
+
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA=="],
+
+
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig=="],
+
+
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.1", "", { "os": "linux", "cpu": "arm" }, "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q=="],
+
+
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw=="],
+
+
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ=="],
+
+
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw=="],
+
+
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ=="],
+
+
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA=="],
+
+
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.1", "", { "os": "win32", "cpu": "x64" }, "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg=="],
+
+
"loader-runner": ["loader-runner@4.3.0", "", {}, "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg=="],
+
+
"magic-string": ["magic-string@0.30.18", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ=="],
+
+
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
+
+
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+
+
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
+
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
+
+
"minizlib": ["minizlib@3.0.2", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA=="],
+
+
"mkdirp": ["mkdirp@3.0.1", "", { "bin": { "mkdirp": "dist/cjs/src/bin.js" } }, "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg=="],
+
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+
"neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="],
+
+
"node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
+
+
"node-releases": ["node-releases@2.0.20", "", {}, "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA=="],
+
+
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
+
+
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
+
"randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="],
+
+
"readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
+
+
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
+
+
"rollup": ["rollup@4.50.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.0", "@rollup/rollup-android-arm64": "4.50.0", "@rollup/rollup-darwin-arm64": "4.50.0", "@rollup/rollup-darwin-x64": "4.50.0", "@rollup/rollup-freebsd-arm64": "4.50.0", "@rollup/rollup-freebsd-x64": "4.50.0", "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", "@rollup/rollup-linux-arm-musleabihf": "4.50.0", "@rollup/rollup-linux-arm64-gnu": "4.50.0", "@rollup/rollup-linux-arm64-musl": "4.50.0", "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", "@rollup/rollup-linux-ppc64-gnu": "4.50.0", "@rollup/rollup-linux-riscv64-gnu": "4.50.0", "@rollup/rollup-linux-riscv64-musl": "4.50.0", "@rollup/rollup-linux-s390x-gnu": "4.50.0", "@rollup/rollup-linux-x64-gnu": "4.50.0", "@rollup/rollup-linux-x64-musl": "4.50.0", "@rollup/rollup-openharmony-arm64": "4.50.0", "@rollup/rollup-win32-arm64-msvc": "4.50.0", "@rollup/rollup-win32-ia32-msvc": "4.50.0", "@rollup/rollup-win32-x64-msvc": "4.50.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw=="],
+
+
"rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
+
+
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+
"sass": ["sass@1.92.0", "", { "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "optionalDependencies": { "@parcel/watcher": "^2.4.1" }, "bin": { "sass": "sass.js" } }, "sha512-KDNI0BxgIRDAfJgzNm5wuy+4yOCIZyrUbjSpiU/JItfih+KGXAVefKL53MTml054MmBA3DDKIBMSI/7XLxZJ3A=="],
+
+
"sass-embedded": ["sass-embedded@1.92.0", "", { "dependencies": { "@bufbuild/protobuf": "^2.5.0", "buffer-builder": "^0.2.0", "colorjs.io": "^0.5.0", "immutable": "^5.0.2", "rxjs": "^7.4.0", "supports-color": "^8.1.1", "sync-child-process": "^1.0.2", "varint": "^6.0.0" }, "optionalDependencies": { "sass-embedded-all-unknown": "1.92.0", "sass-embedded-android-arm": "1.92.0", "sass-embedded-android-arm64": "1.92.0", "sass-embedded-android-riscv64": "1.92.0", "sass-embedded-android-x64": "1.92.0", "sass-embedded-darwin-arm64": "1.92.0", "sass-embedded-darwin-x64": "1.92.0", "sass-embedded-linux-arm": "1.92.0", "sass-embedded-linux-arm64": "1.92.0", "sass-embedded-linux-musl-arm": "1.92.0", "sass-embedded-linux-musl-arm64": "1.92.0", "sass-embedded-linux-musl-riscv64": "1.92.0", "sass-embedded-linux-musl-x64": "1.92.0", "sass-embedded-linux-riscv64": "1.92.0", "sass-embedded-linux-x64": "1.92.0", "sass-embedded-unknown-all": "1.92.0", "sass-embedded-win32-arm64": "1.92.0", "sass-embedded-win32-x64": "1.92.0" }, "bin": { "sass": "dist/bin/sass.js" } }, "sha512-daqnoAA+AmXvcL1fvJRMd4RDPZM2s27qYxb51c5TYc1B1Zugu0gVGyA5leoXQJEzo6sDTQ95J8X0yFcdBNGNtw=="],
+
+
"sass-embedded-all-unknown": ["sass-embedded-all-unknown@1.92.0", "", { "dependencies": { "sass": "1.92.0" }, "cpu": [ "!arm", "!x64", "!arm64", ] }, "sha512-0VcRBilndf8Iot7zfKKEYH7Ig4JBRjltf7Ba9dNL6wtv0m1a36cm8FgZFofrXtDjUgVTV/aEH/Xw4zBUs6vFYA=="],
+
+
"sass-embedded-android-arm": ["sass-embedded-android-arm@1.92.0", "", { "os": "android", "cpu": "arm" }, "sha512-0NH0zElKL5gLdNcWFzYX/bqtpoFq5ogcU+4vLdmpBXA9Zl5NFPXAPRA6K8pgjQNWpnV7bG05JSIVPuNKZ60Ptg=="],
+
+
"sass-embedded-android-arm64": ["sass-embedded-android-arm64@1.92.0", "", { "os": "android", "cpu": "arm64" }, "sha512-m0JY0QyskN77AFpA8FKxqXZNWSzrPvKOvZqOu1DwEEipyHuSdiAVFDHZ6EpI3aABxCXE3jgkP+Ij2mb4hiLxFw=="],
+
+
"sass-embedded-android-riscv64": ["sass-embedded-android-riscv64@1.92.0", "", { "os": "android", "cpu": "none" }, "sha512-wfVRf2PFR15vCgJE3SWLZQRo+98xm7vKvpHiaPU4satutwMKC8yXxDvsc7hFBqQYBtqHNK5ap5dZSXlgdGGZrA=="],
+
+
"sass-embedded-android-x64": ["sass-embedded-android-x64@1.92.0", "", { "os": "android", "cpu": "x64" }, "sha512-bc1c3OMdfrYoiIzVzsMI3KBnIa4mEumg7jHzonkDUIUWrfUNsbzlO+UXX1CcRyfaOIqyKNNZLVvBCz8EwmUsbQ=="],
+
+
"sass-embedded-darwin-arm64": ["sass-embedded-darwin-arm64@1.92.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vZh1WCL2QlQyTlAD8snmC8W90XBZI/125o15bfKkGbUzV58dkZJf413hk6JVQS2+a0lZT4GxvrlGH1fSaSNTug=="],
+
+
"sass-embedded-darwin-x64": ["sass-embedded-darwin-x64@1.92.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-4vJsXpOQAgU+KrrW/3POvhnfkG9iJ4gU8ujeEDXqCSSY2M+5B/j0S6iXB7nu3Z9MfmCl8V4B6xyeB0EWE5Ul0g=="],
+
+
"sass-embedded-linux-arm": ["sass-embedded-linux-arm@1.92.0", "", { "os": "linux", "cpu": "arm" }, "sha512-HMjTDjIT8bHwAVd0c8r8QvGxGZwJg3H06/Y5ZiaiwVGiZtYS9jfef6LnrPw8LY5cOG8wm9RZ9AgVqvkL7E2jBQ=="],
+
+
"sass-embedded-linux-arm64": ["sass-embedded-linux-arm64@1.92.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-HH4LNY1svM2Lv6NCxqOQca42hzG/o55ON9X3T0R18Rl9kVb3y5qiJpdrHh7sSlZWF4qhHYbRc9BIc+Tw142oog=="],
+
+
"sass-embedded-linux-musl-arm": ["sass-embedded-linux-musl-arm@1.92.0", "", { "os": "linux", "cpu": "arm" }, "sha512-qJDCXm379yRT9+8wKSi6nHFCOODTmD6XmE8rqmMozKo6kvCM+Y3sAMlHrT/0+pfzlGh1JSamkoYIo/ODn+LRVA=="],
+
+
"sass-embedded-linux-musl-arm64": ["sass-embedded-linux-musl-arm64@1.92.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-xYzZDmcPb3BsaD6qlRTqZqtyMOZfGCSKJBZYj2ZRJiKDDr1sqPSIqKx6G8jc1wJAVdvoNp5tzENnCfY7NRkxNA=="],
+
+
"sass-embedded-linux-musl-riscv64": ["sass-embedded-linux-musl-riscv64@1.92.0", "", { "os": "linux", "cpu": "none" }, "sha512-ZD3a6c7YvAjp1lEkKyaQpHc5EuetQ0RU3YoTfjwHiyWwezsuJHZc4hkS7SXWbZNEvi7tc2U1bdt4nSdx9c5Qxw=="],
+
+
"sass-embedded-linux-musl-x64": ["sass-embedded-linux-musl-x64@1.92.0", "", { "os": "linux", "cpu": "x64" }, "sha512-ShivGoEKmpyL57hQB9K+EMEOWOo+LuwH5eIM2T0sRIHW5n28IS6h12R3WEJVf+PYtSi9FKWazy7kzeLefya6fQ=="],
+
+
"sass-embedded-linux-riscv64": ["sass-embedded-linux-riscv64@1.92.0", "", { "os": "linux", "cpu": "none" }, "sha512-CTZF8rMYBS4JsGGFMUwdPExq6DxhONXQv9omKpVmuleRw52Isx37GaMTQg5zSxunS6QfwqCyUysjWXTLe8khHA=="],
+
+
"sass-embedded-linux-x64": ["sass-embedded-linux-x64@1.92.0", "", { "os": "linux", "cpu": "x64" }, "sha512-jAY4tzhSUUDUYSl0m+GQub/ZpVk00Pn4ybHeUICAYSQj043A9rkag+LSKDGCvC/0MptMM+/HkIDAC06tRY4PeQ=="],
+
+
"sass-embedded-unknown-all": ["sass-embedded-unknown-all@1.92.0", "", { "dependencies": { "sass": "1.92.0" }, "os": [ "!linux", "!win32", "!darwin", "!android", ] }, "sha512-s0UF1jquqhrxg0dl/0E+L5tCH1zv1ueF+m3VgJukDkDSTW+nb7wpCGcm8csGoSXnP8+dq53jtUXVtt8sPLr8ZQ=="],
+
+
"sass-embedded-win32-arm64": ["sass-embedded-win32-arm64@1.92.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-K8x+q2W0VyGPBtO3b0AlpecGOk47ce2FkEX0WD1gEexpbRCytQ+udDACHQGXpwWYPgSIT9ky0IASzDVT1fjMcw=="],
+
+
"sass-embedded-win32-x64": ["sass-embedded-win32-x64@1.92.0", "", { "os": "win32", "cpu": "x64" }, "sha512-b0051n7EwSvH580u8LjsCAj2US1F59FY6/GbWJWlE2bidzY86/f8ovl4LsGY/uM3lNzWQlA/0BGmdAm44d/qJg=="],
+
+
"schema-utils": ["schema-utils@4.3.2", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ=="],
+
+
"serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="],
+
+
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
+
+
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+
"source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
+
+
"supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+
+
"sync-child-process": ["sync-child-process@1.0.2", "", { "dependencies": { "sync-message-port": "^1.0.0" } }, "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA=="],
+
+
"sync-message-port": ["sync-message-port@1.1.3", "", {}, "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg=="],
+
+
"tailwindcss": ["tailwindcss@4.1.13", "", {}, "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w=="],
+
+
"tapable": ["tapable@2.2.3", "", {}, "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg=="],
+
+
"tar": ["tar@7.4.3", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" } }, "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw=="],
+
+
"terser": ["terser@5.44.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w=="],
+
+
"terser-webpack-plugin": ["terser-webpack-plugin@5.3.14", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw=="],
+
+
"tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
+
+
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+
+
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+
"undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
+
+
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
+
+
"varint": ["varint@6.0.0", "", {}, "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="],
+
+
"vite": ["vite@7.1.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw=="],
+
+
"vite-plugin-full-reload": ["vite-plugin-full-reload@1.2.0", "", { "dependencies": { "picocolors": "^1.0.0", "picomatch": "^2.3.1" } }, "sha512-kz18NW79x0IHbxRSHm0jttP4zoO9P9gXh+n6UTwlNKnviTTEpOlum6oS9SmecrTtSr+muHEn5TUuC75UovQzcA=="],
+
+
"watchpack": ["watchpack@2.4.4", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA=="],
+
+
"webpack": ["webpack@5.101.3", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.3", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.2", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.11", "watchpack": "^2.4.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A=="],
+
+
"webpack-sources": ["webpack-sources@3.3.3", "", {}, "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg=="],
+
+
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
+
+
"@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="],
+
+
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+
"esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
+
+
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
+
+
"vite-plugin-full-reload/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
+
}
+
}
+63
wordpress/composer.json
···
+
{
+
"name": "roots/sage",
+
"type": "wordpress-theme",
+
"license": "MIT",
+
"description": "WordPress starter theme with a modern development workflow",
+
"homepage": "https://roots.io/sage/",
+
"authors": [
+
{
+
"name": "Ben Word",
+
"email": "ben@benword.com",
+
"homepage": "https://github.com/retlehs"
+
},
+
{
+
"name": "Scott Walkinshaw",
+
"email": "scott.walkinshaw@gmail.com",
+
"homepage": "https://github.com/swalkinshaw"
+
},
+
{
+
"name": "QWp6t",
+
"email": "hi@qwp6t.me",
+
"homepage": "https://github.com/qwp6t"
+
},
+
{
+
"name": "Brandon Nifong",
+
"email": "brandon@tendency.me",
+
"homepage": "https://github.com/log1x"
+
}
+
],
+
"keywords": [
+
"wordpress"
+
],
+
"support": {
+
"issues": "https://github.com/roots/sage/issues",
+
"forum": "https://discourse.roots.io/"
+
},
+
"autoload": {
+
"psr-4": {
+
"App\\": "app/"
+
}
+
},
+
"require": {
+
"php": ">=8.2",
+
"roots/acorn": "^5.0"
+
},
+
"require-dev": {
+
"laravel/pint": "^1.20"
+
},
+
"suggest": {
+
"log1x/sage-directives": "A collection of useful Blade directives for WordPress and Sage (^1.0)."
+
},
+
"config": {
+
"optimize-autoloader": true,
+
"preferred-install": "dist",
+
"sort-packages": true
+
},
+
"minimum-stability": "dev",
+
"prefer-stable": true,
+
"scripts": {
+
"post-autoload-dump": [
+
"Roots\\Acorn\\ComposerScripts::postAutoloadDump"
+
]
+
}
+
}
+6460
wordpress/composer.lock
···
+
{
+
"_readme": [
+
"This file locks the dependencies of your project to a known state",
+
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+
"This file is @generated automatically"
+
],
+
"content-hash": "16af317a7214006aae0c739a0f7d1061",
+
"packages": [
+
{
+
"name": "brick/math",
+
"version": "0.14.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/brick/math.git",
+
"reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/brick/math/zipball/113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+
"reference": "113a8ee2656b882d4c3164fa31aa6e12cbb7aaa2",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.2"
+
},
+
"require-dev": {
+
"php-coveralls/php-coveralls": "^2.2",
+
"phpstan/phpstan": "2.1.22",
+
"phpunit/phpunit": "^11.5"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Brick\\Math\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"description": "Arbitrary-precision arithmetic library",
+
"keywords": [
+
"Arbitrary-precision",
+
"BigInteger",
+
"BigRational",
+
"arithmetic",
+
"bigdecimal",
+
"bignum",
+
"bignumber",
+
"brick",
+
"decimal",
+
"integer",
+
"math",
+
"mathematics",
+
"rational"
+
],
+
"support": {
+
"issues": "https://github.com/brick/math/issues",
+
"source": "https://github.com/brick/math/tree/0.14.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/BenMorel",
+
"type": "github"
+
}
+
],
+
"time": "2025-08-29T12:40:03+00:00"
+
},
+
{
+
"name": "carbonphp/carbon-doctrine-types",
+
"version": "3.2.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/CarbonPHP/carbon-doctrine-types.git",
+
"reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/18ba5ddfec8976260ead6e866180bd5d2f71aa1d",
+
"reference": "18ba5ddfec8976260ead6e866180bd5d2f71aa1d",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.1"
+
},
+
"conflict": {
+
"doctrine/dbal": "<4.0.0 || >=5.0.0"
+
},
+
"require-dev": {
+
"doctrine/dbal": "^4.0.0",
+
"nesbot/carbon": "^2.71.0 || ^3.0.0",
+
"phpunit/phpunit": "^10.3"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Carbon\\Doctrine\\": "src/Carbon/Doctrine/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "KyleKatarn",
+
"email": "kylekatarnls@gmail.com"
+
}
+
],
+
"description": "Types to use Carbon in Doctrine",
+
"keywords": [
+
"carbon",
+
"date",
+
"datetime",
+
"doctrine",
+
"time"
+
],
+
"support": {
+
"issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues",
+
"source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/3.2.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/kylekatarnls",
+
"type": "github"
+
},
+
{
+
"url": "https://opencollective.com/Carbon",
+
"type": "open_collective"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-02-09T16:56:22+00:00"
+
},
+
{
+
"name": "doctrine/inflector",
+
"version": "2.1.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/doctrine/inflector.git",
+
"reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b",
+
"reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2 || ^8.0"
+
},
+
"require-dev": {
+
"doctrine/coding-standard": "^12.0 || ^13.0",
+
"phpstan/phpstan": "^1.12 || ^2.0",
+
"phpstan/phpstan-phpunit": "^1.4 || ^2.0",
+
"phpstan/phpstan-strict-rules": "^1.6 || ^2.0",
+
"phpunit/phpunit": "^8.5 || ^12.2"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Doctrine\\Inflector\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Guilherme Blanco",
+
"email": "guilhermeblanco@gmail.com"
+
},
+
{
+
"name": "Roman Borschel",
+
"email": "roman@code-factory.org"
+
},
+
{
+
"name": "Benjamin Eberlei",
+
"email": "kontakt@beberlei.de"
+
},
+
{
+
"name": "Jonathan Wage",
+
"email": "jonwage@gmail.com"
+
},
+
{
+
"name": "Johannes Schmitt",
+
"email": "schmittjoh@gmail.com"
+
}
+
],
+
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
+
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
+
"keywords": [
+
"inflection",
+
"inflector",
+
"lowercase",
+
"manipulation",
+
"php",
+
"plural",
+
"singular",
+
"strings",
+
"uppercase",
+
"words"
+
],
+
"support": {
+
"issues": "https://github.com/doctrine/inflector/issues",
+
"source": "https://github.com/doctrine/inflector/tree/2.1.0"
+
},
+
"funding": [
+
{
+
"url": "https://www.doctrine-project.org/sponsorship.html",
+
"type": "custom"
+
},
+
{
+
"url": "https://www.patreon.com/phpdoctrine",
+
"type": "patreon"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-10T19:31:58+00:00"
+
},
+
{
+
"name": "doctrine/lexer",
+
"version": "3.0.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/doctrine/lexer.git",
+
"reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/doctrine/lexer/zipball/31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+
"reference": "31ad66abc0fc9e1a1f2d9bc6a42668d2fbbcd6dd",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.1"
+
},
+
"require-dev": {
+
"doctrine/coding-standard": "^12",
+
"phpstan/phpstan": "^1.10",
+
"phpunit/phpunit": "^10.5",
+
"psalm/plugin-phpunit": "^0.18.3",
+
"vimeo/psalm": "^5.21"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Doctrine\\Common\\Lexer\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Guilherme Blanco",
+
"email": "guilhermeblanco@gmail.com"
+
},
+
{
+
"name": "Roman Borschel",
+
"email": "roman@code-factory.org"
+
},
+
{
+
"name": "Johannes Schmitt",
+
"email": "schmittjoh@gmail.com"
+
}
+
],
+
"description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.",
+
"homepage": "https://www.doctrine-project.org/projects/lexer.html",
+
"keywords": [
+
"annotations",
+
"docblock",
+
"lexer",
+
"parser",
+
"php"
+
],
+
"support": {
+
"issues": "https://github.com/doctrine/lexer/issues",
+
"source": "https://github.com/doctrine/lexer/tree/3.0.1"
+
},
+
"funding": [
+
{
+
"url": "https://www.doctrine-project.org/sponsorship.html",
+
"type": "custom"
+
},
+
{
+
"url": "https://www.patreon.com/phpdoctrine",
+
"type": "patreon"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-02-05T11:56:58+00:00"
+
},
+
{
+
"name": "dragonmantank/cron-expression",
+
"version": "v3.4.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/dragonmantank/cron-expression.git",
+
"reference": "8c784d071debd117328803d86b2097615b457500"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500",
+
"reference": "8c784d071debd117328803d86b2097615b457500",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2|^8.0",
+
"webmozart/assert": "^1.0"
+
},
+
"replace": {
+
"mtdowling/cron-expression": "^1.0"
+
},
+
"require-dev": {
+
"phpstan/extension-installer": "^1.0",
+
"phpstan/phpstan": "^1.0",
+
"phpunit/phpunit": "^7.0|^8.0|^9.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "3.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Cron\\": "src/Cron/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Chris Tankersley",
+
"email": "chris@ctankersley.com",
+
"homepage": "https://github.com/dragonmantank"
+
}
+
],
+
"description": "CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due",
+
"keywords": [
+
"cron",
+
"schedule"
+
],
+
"support": {
+
"issues": "https://github.com/dragonmantank/cron-expression/issues",
+
"source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/dragonmantank",
+
"type": "github"
+
}
+
],
+
"time": "2024-10-09T13:47:03+00:00"
+
},
+
{
+
"name": "egulias/email-validator",
+
"version": "4.0.4",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/egulias/EmailValidator.git",
+
"reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/egulias/EmailValidator/zipball/d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
+
"reference": "d42c8731f0624ad6bdc8d3e5e9a4524f68801cfa",
+
"shasum": ""
+
},
+
"require": {
+
"doctrine/lexer": "^2.0 || ^3.0",
+
"php": ">=8.1",
+
"symfony/polyfill-intl-idn": "^1.26"
+
},
+
"require-dev": {
+
"phpunit/phpunit": "^10.2",
+
"vimeo/psalm": "^5.12"
+
},
+
"suggest": {
+
"ext-intl": "PHP Internationalization Libraries are required to use the SpoofChecking validation"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "4.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Egulias\\EmailValidator\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Eduardo Gulias Davis"
+
}
+
],
+
"description": "A library for validating emails against several RFCs",
+
"homepage": "https://github.com/egulias/EmailValidator",
+
"keywords": [
+
"email",
+
"emailvalidation",
+
"emailvalidator",
+
"validation",
+
"validator"
+
],
+
"support": {
+
"issues": "https://github.com/egulias/EmailValidator/issues",
+
"source": "https://github.com/egulias/EmailValidator/tree/4.0.4"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/egulias",
+
"type": "github"
+
}
+
],
+
"time": "2025-03-06T22:45:56+00:00"
+
},
+
{
+
"name": "fruitcake/php-cors",
+
"version": "v1.3.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/fruitcake/php-cors.git",
+
"reference": "3d158f36e7875e2f040f37bc0573956240a5a38b"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/fruitcake/php-cors/zipball/3d158f36e7875e2f040f37bc0573956240a5a38b",
+
"reference": "3d158f36e7875e2f040f37bc0573956240a5a38b",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.4|^8.0",
+
"symfony/http-foundation": "^4.4|^5.4|^6|^7"
+
},
+
"require-dev": {
+
"phpstan/phpstan": "^1.4",
+
"phpunit/phpunit": "^9",
+
"squizlabs/php_codesniffer": "^3.5"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "1.2-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Fruitcake\\Cors\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fruitcake",
+
"homepage": "https://fruitcake.nl"
+
},
+
{
+
"name": "Barryvdh",
+
"email": "barryvdh@gmail.com"
+
}
+
],
+
"description": "Cross-origin resource sharing library for the Symfony HttpFoundation",
+
"homepage": "https://github.com/fruitcake/php-cors",
+
"keywords": [
+
"cors",
+
"laravel",
+
"symfony"
+
],
+
"support": {
+
"issues": "https://github.com/fruitcake/php-cors/issues",
+
"source": "https://github.com/fruitcake/php-cors/tree/v1.3.0"
+
},
+
"funding": [
+
{
+
"url": "https://fruitcake.nl",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/barryvdh",
+
"type": "github"
+
}
+
],
+
"time": "2023-10-12T05:21:21+00:00"
+
},
+
{
+
"name": "graham-campbell/result-type",
+
"version": "v1.1.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/GrahamCampbell/Result-Type.git",
+
"reference": "3ba905c11371512af9d9bdd27d99b782216b6945"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945",
+
"reference": "3ba905c11371512af9d9bdd27d99b782216b6945",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2.5 || ^8.0",
+
"phpoption/phpoption": "^1.9.3"
+
},
+
"require-dev": {
+
"phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"GrahamCampbell\\ResultType\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
}
+
],
+
"description": "An Implementation Of The Result Type",
+
"keywords": [
+
"Graham Campbell",
+
"GrahamCampbell",
+
"Result Type",
+
"Result-Type",
+
"result"
+
],
+
"support": {
+
"issues": "https://github.com/GrahamCampbell/Result-Type/issues",
+
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-07-20T21:45:45+00:00"
+
},
+
{
+
"name": "guzzlehttp/guzzle",
+
"version": "7.10.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/guzzle/guzzle.git",
+
"reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4",
+
"reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4",
+
"shasum": ""
+
},
+
"require": {
+
"ext-json": "*",
+
"guzzlehttp/promises": "^2.3",
+
"guzzlehttp/psr7": "^2.8",
+
"php": "^7.2.5 || ^8.0",
+
"psr/http-client": "^1.0",
+
"symfony/deprecation-contracts": "^2.2 || ^3.0"
+
},
+
"provide": {
+
"psr/http-client-implementation": "1.0"
+
},
+
"require-dev": {
+
"bamarni/composer-bin-plugin": "^1.8.2",
+
"ext-curl": "*",
+
"guzzle/client-integration-tests": "3.0.2",
+
"php-http/message-factory": "^1.1",
+
"phpunit/phpunit": "^8.5.39 || ^9.6.20",
+
"psr/log": "^1.1 || ^2.0 || ^3.0"
+
},
+
"suggest": {
+
"ext-curl": "Required for CURL handler support",
+
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
+
"psr/log": "Required for using the Log middleware"
+
},
+
"type": "library",
+
"extra": {
+
"bamarni-bin": {
+
"bin-links": true,
+
"forward-command": false
+
}
+
},
+
"autoload": {
+
"files": [
+
"src/functions_include.php"
+
],
+
"psr-4": {
+
"GuzzleHttp\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
},
+
{
+
"name": "Michael Dowling",
+
"email": "mtdowling@gmail.com",
+
"homepage": "https://github.com/mtdowling"
+
},
+
{
+
"name": "Jeremy Lindblom",
+
"email": "jeremeamia@gmail.com",
+
"homepage": "https://github.com/jeremeamia"
+
},
+
{
+
"name": "George Mponos",
+
"email": "gmponos@gmail.com",
+
"homepage": "https://github.com/gmponos"
+
},
+
{
+
"name": "Tobias Nyholm",
+
"email": "tobias.nyholm@gmail.com",
+
"homepage": "https://github.com/Nyholm"
+
},
+
{
+
"name": "Márk Sági-Kazár",
+
"email": "mark.sagikazar@gmail.com",
+
"homepage": "https://github.com/sagikazarmark"
+
},
+
{
+
"name": "Tobias Schultze",
+
"email": "webmaster@tubo-world.de",
+
"homepage": "https://github.com/Tobion"
+
}
+
],
+
"description": "Guzzle is a PHP HTTP client library",
+
"keywords": [
+
"client",
+
"curl",
+
"framework",
+
"http",
+
"http client",
+
"psr-18",
+
"psr-7",
+
"rest",
+
"web service"
+
],
+
"support": {
+
"issues": "https://github.com/guzzle/guzzle/issues",
+
"source": "https://github.com/guzzle/guzzle/tree/7.10.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/Nyholm",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-23T22:36:01+00:00"
+
},
+
{
+
"name": "guzzlehttp/promises",
+
"version": "2.3.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/guzzle/promises.git",
+
"reference": "481557b130ef3790cf82b713667b43030dc9c957"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957",
+
"reference": "481557b130ef3790cf82b713667b43030dc9c957",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2.5 || ^8.0"
+
},
+
"require-dev": {
+
"bamarni/composer-bin-plugin": "^1.8.2",
+
"phpunit/phpunit": "^8.5.44 || ^9.6.25"
+
},
+
"type": "library",
+
"extra": {
+
"bamarni-bin": {
+
"bin-links": true,
+
"forward-command": false
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"GuzzleHttp\\Promise\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
},
+
{
+
"name": "Michael Dowling",
+
"email": "mtdowling@gmail.com",
+
"homepage": "https://github.com/mtdowling"
+
},
+
{
+
"name": "Tobias Nyholm",
+
"email": "tobias.nyholm@gmail.com",
+
"homepage": "https://github.com/Nyholm"
+
},
+
{
+
"name": "Tobias Schultze",
+
"email": "webmaster@tubo-world.de",
+
"homepage": "https://github.com/Tobion"
+
}
+
],
+
"description": "Guzzle promises library",
+
"keywords": [
+
"promise"
+
],
+
"support": {
+
"issues": "https://github.com/guzzle/promises/issues",
+
"source": "https://github.com/guzzle/promises/tree/2.3.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/Nyholm",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-22T14:34:08+00:00"
+
},
+
{
+
"name": "guzzlehttp/psr7",
+
"version": "2.8.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/guzzle/psr7.git",
+
"reference": "21dc724a0583619cd1652f673303492272778051"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051",
+
"reference": "21dc724a0583619cd1652f673303492272778051",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2.5 || ^8.0",
+
"psr/http-factory": "^1.0",
+
"psr/http-message": "^1.1 || ^2.0",
+
"ralouphie/getallheaders": "^3.0"
+
},
+
"provide": {
+
"psr/http-factory-implementation": "1.0",
+
"psr/http-message-implementation": "1.0"
+
},
+
"require-dev": {
+
"bamarni/composer-bin-plugin": "^1.8.2",
+
"http-interop/http-factory-tests": "0.9.0",
+
"phpunit/phpunit": "^8.5.44 || ^9.6.25"
+
},
+
"suggest": {
+
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
+
},
+
"type": "library",
+
"extra": {
+
"bamarni-bin": {
+
"bin-links": true,
+
"forward-command": false
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"GuzzleHttp\\Psr7\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
},
+
{
+
"name": "Michael Dowling",
+
"email": "mtdowling@gmail.com",
+
"homepage": "https://github.com/mtdowling"
+
},
+
{
+
"name": "George Mponos",
+
"email": "gmponos@gmail.com",
+
"homepage": "https://github.com/gmponos"
+
},
+
{
+
"name": "Tobias Nyholm",
+
"email": "tobias.nyholm@gmail.com",
+
"homepage": "https://github.com/Nyholm"
+
},
+
{
+
"name": "Márk Sági-Kazár",
+
"email": "mark.sagikazar@gmail.com",
+
"homepage": "https://github.com/sagikazarmark"
+
},
+
{
+
"name": "Tobias Schultze",
+
"email": "webmaster@tubo-world.de",
+
"homepage": "https://github.com/Tobion"
+
},
+
{
+
"name": "Márk Sági-Kazár",
+
"email": "mark.sagikazar@gmail.com",
+
"homepage": "https://sagikazarmark.hu"
+
}
+
],
+
"description": "PSR-7 message implementation that also provides common utility methods",
+
"keywords": [
+
"http",
+
"message",
+
"psr-7",
+
"request",
+
"response",
+
"stream",
+
"uri",
+
"url"
+
],
+
"support": {
+
"issues": "https://github.com/guzzle/psr7/issues",
+
"source": "https://github.com/guzzle/psr7/tree/2.8.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/Nyholm",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-23T21:21:41+00:00"
+
},
+
{
+
"name": "guzzlehttp/uri-template",
+
"version": "v1.0.5",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/guzzle/uri-template.git",
+
"reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1",
+
"reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2.5 || ^8.0",
+
"symfony/polyfill-php80": "^1.24"
+
},
+
"require-dev": {
+
"bamarni/composer-bin-plugin": "^1.8.2",
+
"phpunit/phpunit": "^8.5.44 || ^9.6.25",
+
"uri-template/tests": "1.0.0"
+
},
+
"type": "library",
+
"extra": {
+
"bamarni-bin": {
+
"bin-links": true,
+
"forward-command": false
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"GuzzleHttp\\UriTemplate\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
},
+
{
+
"name": "Michael Dowling",
+
"email": "mtdowling@gmail.com",
+
"homepage": "https://github.com/mtdowling"
+
},
+
{
+
"name": "George Mponos",
+
"email": "gmponos@gmail.com",
+
"homepage": "https://github.com/gmponos"
+
},
+
{
+
"name": "Tobias Nyholm",
+
"email": "tobias.nyholm@gmail.com",
+
"homepage": "https://github.com/Nyholm"
+
}
+
],
+
"description": "A polyfill class for uri_template of PHP",
+
"keywords": [
+
"guzzlehttp",
+
"uri-template"
+
],
+
"support": {
+
"issues": "https://github.com/guzzle/uri-template/issues",
+
"source": "https://github.com/guzzle/uri-template/tree/v1.0.5"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/Nyholm",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/uri-template",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-22T14:27:06+00:00"
+
},
+
{
+
"name": "illuminate/auth",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/auth.git",
+
"reference": "d575fe350072eab99ebce696f6f1ea02a80e7b63"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/auth/zipball/d575fe350072eab99ebce696f6f1ea02a80e7b63",
+
"reference": "d575fe350072eab99ebce696f6f1ea02a80e7b63",
+
"shasum": ""
+
},
+
"require": {
+
"ext-hash": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/http": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/queue": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"suggest": {
+
"illuminate/console": "Required to use the auth:clear-resets command (^12.0).",
+
"illuminate/queue": "Required to fire login / logout events (^12.0).",
+
"illuminate/session": "Required to use the session based guard (^12.0)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Auth\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Auth package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-29T13:26:52+00:00"
+
},
+
{
+
"name": "illuminate/bus",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/bus.git",
+
"reference": "4acb2cbe9d788b25f74907cbb388bdfb1fbe26ff"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/bus/zipball/4acb2cbe9d788b25f74907cbb388bdfb1fbe26ff",
+
"reference": "4acb2cbe9d788b25f74907cbb388bdfb1fbe26ff",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/pipeline": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"suggest": {
+
"illuminate/queue": "Required to use closures when chaining jobs (^12.0)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Bus\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Bus package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-04T12:41:25+00:00"
+
},
+
{
+
"name": "illuminate/cache",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/cache.git",
+
"reference": "780fc90e9cf0ac7bbfd0d2df23945645382e5d25"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/cache/zipball/780fc90e9cf0ac7bbfd0d2df23945645382e5d25",
+
"reference": "780fc90e9cf0ac7bbfd0d2df23945645382e5d25",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"provide": {
+
"psr/simple-cache-implementation": "1.0|2.0|3.0"
+
},
+
"suggest": {
+
"ext-apcu": "Required to use the APC cache driver.",
+
"ext-filter": "Required to use the DynamoDb cache driver.",
+
"ext-memcached": "Required to use the memcache cache driver.",
+
"illuminate/database": "Required to use the database cache driver (^12.0).",
+
"illuminate/filesystem": "Required to use the file cache driver (^12.0).",
+
"illuminate/redis": "Required to use the redis cache driver (^12.0).",
+
"symfony/cache": "Required to use PSR-6 cache bridge (^7.2)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Cache\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Cache package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-31T15:01:05+00:00"
+
},
+
{
+
"name": "illuminate/collections",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/collections.git",
+
"reference": "2737a0477a3f4855a71bf8f3d0b8d32596ded628"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/collections/zipball/2737a0477a3f4855a71bf8f3d0b8d32596ded628",
+
"reference": "2737a0477a3f4855a71bf8f3d0b8d32596ded628",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/conditionable": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"php": "^8.2",
+
"symfony/polyfill-php84": "^1.33",
+
"symfony/polyfill-php85": "^1.33"
+
},
+
"suggest": {
+
"illuminate/http": "Required to convert collections to API resources (^12.0).",
+
"symfony/var-dumper": "Required to use the dump method (^7.2)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"functions.php",
+
"helpers.php"
+
],
+
"psr-4": {
+
"Illuminate\\Support\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Collections package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-02T15:31:06+00:00"
+
},
+
{
+
"name": "illuminate/conditionable",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/conditionable.git",
+
"reference": "ec677967c1f2faf90b8428919124d2184a4c9b49"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/conditionable/zipball/ec677967c1f2faf90b8428919124d2184a4c9b49",
+
"reference": "ec677967c1f2faf90b8428919124d2184a4c9b49",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Support\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Conditionable package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-05-13T15:08:45+00:00"
+
},
+
{
+
"name": "illuminate/config",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/config.git",
+
"reference": "06c8e1dc8fc890562eab7609d6454aa98f49da5c"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/config/zipball/06c8e1dc8fc890562eab7609d6454aa98f49da5c",
+
"reference": "06c8e1dc8fc890562eab7609d6454aa98f49da5c",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Config\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Config package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-07-02T22:34:43+00:00"
+
},
+
{
+
"name": "illuminate/console",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/console.git",
+
"reference": "f9a8659068db0b099f66a19401fce56676aa32a8"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/console/zipball/f9a8659068db0b099f66a19401fce56676aa32a8",
+
"reference": "f9a8659068db0b099f66a19401fce56676aa32a8",
+
"shasum": ""
+
},
+
"require": {
+
"ext-mbstring": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"illuminate/view": "^12.0",
+
"laravel/prompts": "^0.3.0",
+
"nunomaduro/termwind": "^2.0",
+
"php": "^8.2",
+
"symfony/console": "^7.2.0",
+
"symfony/polyfill-php83": "^1.33",
+
"symfony/process": "^7.2.0"
+
},
+
"suggest": {
+
"dragonmantank/cron-expression": "Required to use scheduler (^3.3.2).",
+
"ext-pcntl": "Required to use signal trapping.",
+
"guzzlehttp/guzzle": "Required to use the ping methods on schedules (^7.8).",
+
"illuminate/bus": "Required to use the scheduled job dispatcher (^12.0).",
+
"illuminate/container": "Required to use the scheduler (^12.0).",
+
"illuminate/filesystem": "Required to use the generator command (^12.0).",
+
"illuminate/queue": "Required to use closures for scheduled jobs (^12.0)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Console\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Console package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T01:38:37+00:00"
+
},
+
{
+
"name": "illuminate/container",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/container.git",
+
"reference": "c096f6fd0fc1879bb78fb88379e2955e2f8911f8"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/container/zipball/c096f6fd0fc1879bb78fb88379e2955e2f8911f8",
+
"reference": "c096f6fd0fc1879bb78fb88379e2955e2f8911f8",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/contracts": "^12.0",
+
"php": "^8.2",
+
"psr/container": "^1.1.1|^2.0.1",
+
"symfony/polyfill-php84": "^1.33",
+
"symfony/polyfill-php85": "^1.33"
+
},
+
"provide": {
+
"psr/container-implementation": "1.1|2.0"
+
},
+
"suggest": {
+
"illuminate/auth": "Required to use the Auth attribute",
+
"illuminate/cache": "Required to use the Cache attribute",
+
"illuminate/config": "Required to use the Config attribute",
+
"illuminate/database": "Required to use the DB attribute",
+
"illuminate/filesystem": "Required to use the Storage attribute",
+
"illuminate/log": "Required to use the Log or Context attributes"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Container\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Container package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-27T18:34:41+00:00"
+
},
+
{
+
"name": "illuminate/contracts",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/contracts.git",
+
"reference": "f1c4cf02c9ab81a9ce47940cf261fa2386ed6c5d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/contracts/zipball/f1c4cf02c9ab81a9ce47940cf261fa2386ed6c5d",
+
"reference": "f1c4cf02c9ab81a9ce47940cf261fa2386ed6c5d",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.2",
+
"psr/container": "^1.1.1|^2.0.1",
+
"psr/simple-cache": "^1.0|^2.0|^3.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Contracts\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Contracts package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-27T18:34:41+00:00"
+
},
+
{
+
"name": "illuminate/cookie",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/cookie.git",
+
"reference": "706dfca9e450c580ede5def71ae49b618aea5b94"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/cookie/zipball/706dfca9e450c580ede5def71ae49b618aea5b94",
+
"reference": "706dfca9e450c580ede5def71ae49b618aea5b94",
+
"shasum": ""
+
},
+
"require": {
+
"ext-hash": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2",
+
"symfony/http-foundation": "^7.2.0",
+
"symfony/http-kernel": "^7.2.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Cookie\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Cookie package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-03-19T20:10:05+00:00"
+
},
+
{
+
"name": "illuminate/database",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/database.git",
+
"reference": "a61d0d81bde2f0163bdba146b0fa2d2e646ffa98"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/database/zipball/a61d0d81bde2f0163bdba146b0fa2d2e646ffa98",
+
"reference": "a61d0d81bde2f0163bdba146b0fa2d2e646ffa98",
+
"shasum": ""
+
},
+
"require": {
+
"brick/math": "^0.11|^0.12|^0.13|^0.14",
+
"ext-pdo": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"laravel/serializable-closure": "^1.3|^2.0",
+
"php": "^8.2",
+
"symfony/polyfill-php85": "^1.33"
+
},
+
"suggest": {
+
"ext-filter": "Required to use the Postgres database driver.",
+
"fakerphp/faker": "Required to use the eloquent factory builder (^1.24).",
+
"illuminate/console": "Required to use the database commands (^12.0).",
+
"illuminate/events": "Required to use the observers with Eloquent (^12.0).",
+
"illuminate/filesystem": "Required to use the migrations (^12.0).",
+
"illuminate/http": "Required to convert Eloquent models to API resources (^12.0).",
+
"illuminate/pagination": "Required to paginate the result set (^12.0).",
+
"symfony/finder": "Required to use Eloquent model factories (^7.2)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Database\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Database package.",
+
"homepage": "https://laravel.com",
+
"keywords": [
+
"database",
+
"laravel",
+
"orm",
+
"sql"
+
],
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T16:43:20+00:00"
+
},
+
{
+
"name": "illuminate/encryption",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/encryption.git",
+
"reference": "bc4f74a9953e6d1d4ad9f6495819de4cc0ea7450"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/encryption/zipball/bc4f74a9953e6d1d4ad9f6495819de4cc0ea7450",
+
"reference": "bc4f74a9953e6d1d4ad9f6495819de4cc0ea7450",
+
"shasum": ""
+
},
+
"require": {
+
"ext-hash": "*",
+
"ext-mbstring": "*",
+
"ext-openssl": "*",
+
"illuminate/contracts": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Encryption\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Encryption package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-03-22T23:03:39+00:00"
+
},
+
{
+
"name": "illuminate/events",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/events.git",
+
"reference": "2017f20e234e1be566c739fc9d4518e33a34ecc3"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/events/zipball/2017f20e234e1be566c739fc9d4518e33a34ecc3",
+
"reference": "2017f20e234e1be566c739fc9d4518e33a34ecc3",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/bus": "^12.0",
+
"illuminate/collections": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"functions.php"
+
],
+
"psr-4": {
+
"Illuminate\\Events\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Events package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-20T13:36:50+00:00"
+
},
+
{
+
"name": "illuminate/filesystem",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/filesystem.git",
+
"reference": "d458bc675ced0b9db3ec4f10aa382b245a4b1cf6"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/filesystem/zipball/d458bc675ced0b9db3ec4f10aa382b245a4b1cf6",
+
"reference": "d458bc675ced0b9db3ec4f10aa382b245a4b1cf6",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2",
+
"symfony/finder": "^7.2.0"
+
},
+
"suggest": {
+
"ext-fileinfo": "Required to use the Filesystem class.",
+
"ext-ftp": "Required to use the Flysystem FTP driver.",
+
"ext-hash": "Required to use the Filesystem class.",
+
"illuminate/http": "Required for handling uploaded files (^12.0).",
+
"league/flysystem": "Required to use the Flysystem local driver (^3.25.1).",
+
"league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).",
+
"league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).",
+
"league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).",
+
"psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).",
+
"symfony/filesystem": "Required to enable support for relative symbolic links (^7.2).",
+
"symfony/mime": "Required to enable support for guessing extensions (^7.2)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"functions.php"
+
],
+
"psr-4": {
+
"Illuminate\\Filesystem\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Filesystem package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-19T13:36:00+00:00"
+
},
+
{
+
"name": "illuminate/hashing",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/hashing.git",
+
"reference": "1034320950a2208a4a343ecf9fc327ae5360b18f"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/hashing/zipball/1034320950a2208a4a343ecf9fc327ae5360b18f",
+
"reference": "1034320950a2208a4a343ecf9fc327ae5360b18f",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/contracts": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Hashing\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Hashing package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-03-19T20:10:05+00:00"
+
},
+
{
+
"name": "illuminate/http",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/http.git",
+
"reference": "9cd32b64bc921b8ddb886e4797bc9203db4364b0"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/http/zipball/9cd32b64bc921b8ddb886e4797bc9203db4364b0",
+
"reference": "9cd32b64bc921b8ddb886e4797bc9203db4364b0",
+
"shasum": ""
+
},
+
"require": {
+
"ext-filter": "*",
+
"fruitcake/php-cors": "^1.3",
+
"guzzlehttp/guzzle": "^7.8.2",
+
"guzzlehttp/uri-template": "^1.0",
+
"illuminate/collections": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/session": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2",
+
"symfony/http-foundation": "^7.2.0",
+
"symfony/http-kernel": "^7.2.0",
+
"symfony/mime": "^7.2.0",
+
"symfony/polyfill-php83": "^1.33",
+
"symfony/polyfill-php85": "^1.33"
+
},
+
"suggest": {
+
"ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image()."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Http\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Http package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T01:38:37+00:00"
+
},
+
{
+
"name": "illuminate/log",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/log.git",
+
"reference": "bcd4c0ac05b47c45f0693a83704b46399fec6414"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/log/zipball/bcd4c0ac05b47c45f0693a83704b46399fec6414",
+
"reference": "bcd4c0ac05b47c45f0693a83704b46399fec6414",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/contracts": "^12.0",
+
"illuminate/support": "^12.0",
+
"monolog/monolog": "^3.0",
+
"php": "^8.2",
+
"psr/log": "^1.0|^2.0|^3.0"
+
},
+
"provide": {
+
"psr/log-implementation": "1.0|2.0|3.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Log\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Log package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-22T14:22:42+00:00"
+
},
+
{
+
"name": "illuminate/macroable",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/macroable.git",
+
"reference": "e862e5648ee34004fa56046b746f490dfa86c613"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/macroable/zipball/e862e5648ee34004fa56046b746f490dfa86c613",
+
"reference": "e862e5648ee34004fa56046b746f490dfa86c613",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Support\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Macroable package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2024-07-23T16:31:01+00:00"
+
},
+
{
+
"name": "illuminate/pipeline",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/pipeline.git",
+
"reference": "b6a14c20d69a44bf0a6fba664a00d23ca71770ee"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/pipeline/zipball/b6a14c20d69a44bf0a6fba664a00d23ca71770ee",
+
"reference": "b6a14c20d69a44bf0a6fba664a00d23ca71770ee",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"suggest": {
+
"illuminate/database": "Required to use database transactions (^12.0)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Pipeline\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Pipeline package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-20T13:36:50+00:00"
+
},
+
{
+
"name": "illuminate/queue",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/queue.git",
+
"reference": "e8182047861d8218646b0eef6f727c7dba5141a1"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/queue/zipball/e8182047861d8218646b0eef6f727c7dba5141a1",
+
"reference": "e8182047861d8218646b0eef6f727c7dba5141a1",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/collections": "^12.0",
+
"illuminate/console": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/database": "^12.0",
+
"illuminate/filesystem": "^12.0",
+
"illuminate/pipeline": "^12.0",
+
"illuminate/support": "^12.0",
+
"laravel/serializable-closure": "^1.3|^2.0",
+
"php": "^8.2",
+
"ramsey/uuid": "^4.7",
+
"symfony/process": "^7.2.0"
+
},
+
"suggest": {
+
"aws/aws-sdk-php": "Required to use the SQS queue driver and DynamoDb failed job storage (^3.322.9).",
+
"ext-filter": "Required to use the SQS queue worker.",
+
"ext-mbstring": "Required to use the database failed job providers.",
+
"ext-pcntl": "Required to use all features of the queue worker.",
+
"ext-pdo": "Required to use the database queue worker.",
+
"ext-posix": "Required to use all features of the queue worker.",
+
"illuminate/redis": "Required to use the Redis queue driver (^12.0).",
+
"pda/pheanstalk": "Required to use the Beanstalk queue driver (^5.0.6|^7.0.0)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Queue\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Queue package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-04T12:41:25+00:00"
+
},
+
{
+
"name": "illuminate/routing",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/routing.git",
+
"reference": "de8fcff263059499966b03f24cbd5801d6772135"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/routing/zipball/de8fcff263059499966b03f24cbd5801d6772135",
+
"reference": "de8fcff263059499966b03f24cbd5801d6772135",
+
"shasum": ""
+
},
+
"require": {
+
"ext-filter": "*",
+
"ext-hash": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/http": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/pipeline": "^12.0",
+
"illuminate/session": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2",
+
"symfony/http-foundation": "^7.2.0",
+
"symfony/http-kernel": "^7.2.0",
+
"symfony/polyfill-php84": "^1.33",
+
"symfony/polyfill-php85": "^1.33",
+
"symfony/routing": "^7.2.0"
+
},
+
"suggest": {
+
"illuminate/console": "Required to use the make commands (^12.0).",
+
"php-http/discovery": "Required to use PSR-7 bridging features (^1.15).",
+
"symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^7.2)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Routing\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Routing package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-04T12:43:14+00:00"
+
},
+
{
+
"name": "illuminate/session",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/session.git",
+
"reference": "3160e1363a429566a3ea7d05a857e821044848de"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/session/zipball/3160e1363a429566a3ea7d05a857e821044848de",
+
"reference": "3160e1363a429566a3ea7d05a857e821044848de",
+
"shasum": ""
+
},
+
"require": {
+
"ext-ctype": "*",
+
"ext-session": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/filesystem": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2",
+
"symfony/finder": "^7.2.0",
+
"symfony/http-foundation": "^7.2.0"
+
},
+
"suggest": {
+
"illuminate/console": "Required to use the session:table command (^12.0)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Session\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Session package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-20T13:36:50+00:00"
+
},
+
{
+
"name": "illuminate/support",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/support.git",
+
"reference": "487bbe527806615b818e87c364d93ba91f27db9b"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/support/zipball/487bbe527806615b818e87c364d93ba91f27db9b",
+
"reference": "487bbe527806615b818e87c364d93ba91f27db9b",
+
"shasum": ""
+
},
+
"require": {
+
"doctrine/inflector": "^2.0",
+
"ext-ctype": "*",
+
"ext-filter": "*",
+
"ext-mbstring": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/conditionable": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"nesbot/carbon": "^3.8.4",
+
"php": "^8.2",
+
"symfony/polyfill-php83": "^1.33",
+
"symfony/polyfill-php85": "^1.33",
+
"voku/portable-ascii": "^2.0.2"
+
},
+
"conflict": {
+
"tightenco/collect": "<5.5.33"
+
},
+
"replace": {
+
"spatie/once": "*"
+
},
+
"suggest": {
+
"illuminate/filesystem": "Required to use the Composer class (^12.0).",
+
"laravel/serializable-closure": "Required to use the once function (^1.3|^2.0).",
+
"league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).",
+
"league/uri": "Required to use the Uri class (^7.5.1).",
+
"ramsey/uuid": "Required to use Str::uuid() (^4.7).",
+
"symfony/process": "Required to use the Composer class (^7.2).",
+
"symfony/uid": "Required to use Str::ulid() (^7.2).",
+
"symfony/var-dumper": "Required to use the dd function (^7.2).",
+
"vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"functions.php",
+
"helpers.php"
+
],
+
"psr-4": {
+
"Illuminate\\Support\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Support package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T16:23:04+00:00"
+
},
+
{
+
"name": "illuminate/testing",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/testing.git",
+
"reference": "40ca0e7f95316f7edb8f90bc729d9d1b7b3865ce"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/testing/zipball/40ca0e7f95316f7edb8f90bc729d9d1b7b3865ce",
+
"reference": "40ca0e7f95316f7edb8f90bc729d9d1b7b3865ce",
+
"shasum": ""
+
},
+
"require": {
+
"ext-mbstring": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2",
+
"symfony/polyfill-php83": "^1.33"
+
},
+
"suggest": {
+
"brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).",
+
"illuminate/console": "Required to assert console commands (^12.0).",
+
"illuminate/database": "Required to assert databases (^12.0).",
+
"illuminate/http": "Required to assert responses (^12.0).",
+
"mockery/mockery": "Required to use mocking (^1.6).",
+
"phpunit/phpunit": "Required to use assertions and run tests (^10.5.35|^11.5.3|^12.0.1)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Testing\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Testing package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T01:38:37+00:00"
+
},
+
{
+
"name": "illuminate/translation",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/translation.git",
+
"reference": "abcda868a5a791492bc215e6f9a6ead73f2b63dd"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/translation/zipball/abcda868a5a791492bc215e6f9a6ead73f2b63dd",
+
"reference": "abcda868a5a791492bc215e6f9a6ead73f2b63dd",
+
"shasum": ""
+
},
+
"require": {
+
"illuminate/collections": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/filesystem": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Translation\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Translation package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-08-13T16:46:48+00:00"
+
},
+
{
+
"name": "illuminate/validation",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/validation.git",
+
"reference": "214e1405f138bc327144ee5243891ee0ba12bd8e"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/validation/zipball/214e1405f138bc327144ee5243891ee0ba12bd8e",
+
"reference": "214e1405f138bc327144ee5243891ee0ba12bd8e",
+
"shasum": ""
+
},
+
"require": {
+
"brick/math": "^0.11|^0.12|^0.13|^0.14",
+
"egulias/email-validator": "^3.2.5|^4.0",
+
"ext-filter": "*",
+
"ext-mbstring": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"illuminate/translation": "^12.0",
+
"php": "^8.2",
+
"symfony/http-foundation": "^7.2",
+
"symfony/mime": "^7.2",
+
"symfony/polyfill-php83": "^1.33"
+
},
+
"suggest": {
+
"illuminate/database": "Required to use the database presence verifier (^12.0).",
+
"ramsey/uuid": "Required to use Validator::validateUuid() (^4.7)."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\Validation\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate Validation package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T01:38:37+00:00"
+
},
+
{
+
"name": "illuminate/view",
+
"version": "v12.28.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/illuminate/view.git",
+
"reference": "ca14db94c0cf456ff86ec8fb768bbfe84dd6b427"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/illuminate/view/zipball/ca14db94c0cf456ff86ec8fb768bbfe84dd6b427",
+
"reference": "ca14db94c0cf456ff86ec8fb768bbfe84dd6b427",
+
"shasum": ""
+
},
+
"require": {
+
"ext-tokenizer": "*",
+
"illuminate/collections": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/events": "^12.0",
+
"illuminate/filesystem": "^12.0",
+
"illuminate/macroable": "^12.0",
+
"illuminate/support": "^12.0",
+
"php": "^8.2"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "12.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Illuminate\\View\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
}
+
],
+
"description": "The Illuminate View package.",
+
"homepage": "https://laravel.com",
+
"support": {
+
"issues": "https://github.com/laravel/framework/issues",
+
"source": "https://github.com/laravel/framework"
+
},
+
"time": "2025-09-03T16:29:42+00:00"
+
},
+
{
+
"name": "laravel/prompts",
+
"version": "v0.3.6",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/laravel/prompts.git",
+
"reference": "86a8b692e8661d0fb308cec64f3d176821323077"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/laravel/prompts/zipball/86a8b692e8661d0fb308cec64f3d176821323077",
+
"reference": "86a8b692e8661d0fb308cec64f3d176821323077",
+
"shasum": ""
+
},
+
"require": {
+
"composer-runtime-api": "^2.2",
+
"ext-mbstring": "*",
+
"php": "^8.1",
+
"symfony/console": "^6.2|^7.0"
+
},
+
"conflict": {
+
"illuminate/console": ">=10.17.0 <10.25.0",
+
"laravel/framework": ">=10.17.0 <10.25.0"
+
},
+
"require-dev": {
+
"illuminate/collections": "^10.0|^11.0|^12.0",
+
"mockery/mockery": "^1.5",
+
"pestphp/pest": "^2.3|^3.4",
+
"phpstan/phpstan": "^1.11",
+
"phpstan/phpstan-mockery": "^1.1"
+
},
+
"suggest": {
+
"ext-pcntl": "Required for the spinner to be animated."
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-main": "0.3.x-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"src/helpers.php"
+
],
+
"psr-4": {
+
"Laravel\\Prompts\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"description": "Add beautiful and user-friendly forms to your command-line applications.",
+
"support": {
+
"issues": "https://github.com/laravel/prompts/issues",
+
"source": "https://github.com/laravel/prompts/tree/v0.3.6"
+
},
+
"time": "2025-07-07T14:17:42+00:00"
+
},
+
{
+
"name": "laravel/serializable-closure",
+
"version": "v1.3.7",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/laravel/serializable-closure.git",
+
"reference": "4f48ade902b94323ca3be7646db16209ec76be3d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d",
+
"reference": "4f48ade902b94323ca3be7646db16209ec76be3d",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.3|^8.0"
+
},
+
"require-dev": {
+
"illuminate/support": "^8.0|^9.0|^10.0|^11.0",
+
"nesbot/carbon": "^2.61|^3.0",
+
"pestphp/pest": "^1.21.3",
+
"phpstan/phpstan": "^1.8.2",
+
"symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "1.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Laravel\\SerializableClosure\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Taylor Otwell",
+
"email": "taylor@laravel.com"
+
},
+
{
+
"name": "Nuno Maduro",
+
"email": "nuno@laravel.com"
+
}
+
],
+
"description": "Laravel Serializable Closure provides an easy and secure way to serialize closures in PHP.",
+
"keywords": [
+
"closure",
+
"laravel",
+
"serializable"
+
],
+
"support": {
+
"issues": "https://github.com/laravel/serializable-closure/issues",
+
"source": "https://github.com/laravel/serializable-closure"
+
},
+
"time": "2024-11-14T18:34:49+00:00"
+
},
+
{
+
"name": "league/flysystem",
+
"version": "3.30.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/thephpleague/flysystem.git",
+
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2203e3151755d874bb2943649dae1eb8533ac93e",
+
"reference": "2203e3151755d874bb2943649dae1eb8533ac93e",
+
"shasum": ""
+
},
+
"require": {
+
"league/flysystem-local": "^3.0.0",
+
"league/mime-type-detection": "^1.0.0",
+
"php": "^8.0.2"
+
},
+
"conflict": {
+
"async-aws/core": "<1.19.0",
+
"async-aws/s3": "<1.14.0",
+
"aws/aws-sdk-php": "3.209.31 || 3.210.0",
+
"guzzlehttp/guzzle": "<7.0",
+
"guzzlehttp/ringphp": "<1.1.1",
+
"phpseclib/phpseclib": "3.0.15",
+
"symfony/http-client": "<5.2"
+
},
+
"require-dev": {
+
"async-aws/s3": "^1.5 || ^2.0",
+
"async-aws/simple-s3": "^1.1 || ^2.0",
+
"aws/aws-sdk-php": "^3.295.10",
+
"composer/semver": "^3.0",
+
"ext-fileinfo": "*",
+
"ext-ftp": "*",
+
"ext-mongodb": "^1.3|^2",
+
"ext-zip": "*",
+
"friendsofphp/php-cs-fixer": "^3.5",
+
"google/cloud-storage": "^1.23",
+
"guzzlehttp/psr7": "^2.6",
+
"microsoft/azure-storage-blob": "^1.1",
+
"mongodb/mongodb": "^1.2|^2",
+
"phpseclib/phpseclib": "^3.0.36",
+
"phpstan/phpstan": "^1.10",
+
"phpunit/phpunit": "^9.5.11|^10.0",
+
"sabre/dav": "^4.6.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"League\\Flysystem\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Frank de Jonge",
+
"email": "info@frankdejonge.nl"
+
}
+
],
+
"description": "File storage abstraction for PHP",
+
"keywords": [
+
"WebDAV",
+
"aws",
+
"cloud",
+
"file",
+
"files",
+
"filesystem",
+
"filesystems",
+
"ftp",
+
"s3",
+
"sftp",
+
"storage"
+
],
+
"support": {
+
"issues": "https://github.com/thephpleague/flysystem/issues",
+
"source": "https://github.com/thephpleague/flysystem/tree/3.30.0"
+
},
+
"time": "2025-06-25T13:29:59+00:00"
+
},
+
{
+
"name": "league/flysystem-local",
+
"version": "3.30.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/thephpleague/flysystem-local.git",
+
"reference": "6691915f77c7fb69adfb87dcd550052dc184ee10"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/thephpleague/flysystem-local/zipball/6691915f77c7fb69adfb87dcd550052dc184ee10",
+
"reference": "6691915f77c7fb69adfb87dcd550052dc184ee10",
+
"shasum": ""
+
},
+
"require": {
+
"ext-fileinfo": "*",
+
"league/flysystem": "^3.0.0",
+
"league/mime-type-detection": "^1.0.0",
+
"php": "^8.0.2"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"League\\Flysystem\\Local\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Frank de Jonge",
+
"email": "info@frankdejonge.nl"
+
}
+
],
+
"description": "Local filesystem adapter for Flysystem.",
+
"keywords": [
+
"Flysystem",
+
"file",
+
"files",
+
"filesystem",
+
"local"
+
],
+
"support": {
+
"source": "https://github.com/thephpleague/flysystem-local/tree/3.30.0"
+
},
+
"time": "2025-05-21T10:34:19+00:00"
+
},
+
{
+
"name": "league/mime-type-detection",
+
"version": "1.16.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/thephpleague/mime-type-detection.git",
+
"reference": "2d6702ff215bf922936ccc1ad31007edc76451b9"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/2d6702ff215bf922936ccc1ad31007edc76451b9",
+
"reference": "2d6702ff215bf922936ccc1ad31007edc76451b9",
+
"shasum": ""
+
},
+
"require": {
+
"ext-fileinfo": "*",
+
"php": "^7.4 || ^8.0"
+
},
+
"require-dev": {
+
"friendsofphp/php-cs-fixer": "^3.2",
+
"phpstan/phpstan": "^0.12.68",
+
"phpunit/phpunit": "^8.5.8 || ^9.3 || ^10.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"League\\MimeTypeDetection\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Frank de Jonge",
+
"email": "info@frankdejonge.nl"
+
}
+
],
+
"description": "Mime-type detection for Flysystem",
+
"support": {
+
"issues": "https://github.com/thephpleague/mime-type-detection/issues",
+
"source": "https://github.com/thephpleague/mime-type-detection/tree/1.16.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/frankdejonge",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/league/flysystem",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-21T08:32:55+00:00"
+
},
+
{
+
"name": "monolog/monolog",
+
"version": "3.9.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/Seldaek/monolog.git",
+
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6",
+
"reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.1",
+
"psr/log": "^2.0 || ^3.0"
+
},
+
"provide": {
+
"psr/log-implementation": "3.0.0"
+
},
+
"require-dev": {
+
"aws/aws-sdk-php": "^3.0",
+
"doctrine/couchdb": "~1.0@dev",
+
"elasticsearch/elasticsearch": "^7 || ^8",
+
"ext-json": "*",
+
"graylog2/gelf-php": "^1.4.2 || ^2.0",
+
"guzzlehttp/guzzle": "^7.4.5",
+
"guzzlehttp/psr7": "^2.2",
+
"mongodb/mongodb": "^1.8",
+
"php-amqplib/php-amqplib": "~2.4 || ^3",
+
"php-console/php-console": "^3.1.8",
+
"phpstan/phpstan": "^2",
+
"phpstan/phpstan-deprecation-rules": "^2",
+
"phpstan/phpstan-strict-rules": "^2",
+
"phpunit/phpunit": "^10.5.17 || ^11.0.7",
+
"predis/predis": "^1.1 || ^2",
+
"rollbar/rollbar": "^4.0",
+
"ruflin/elastica": "^7 || ^8",
+
"symfony/mailer": "^5.4 || ^6",
+
"symfony/mime": "^5.4 || ^6"
+
},
+
"suggest": {
+
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+
"elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+
"ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+
"ext-mbstring": "Allow to work properly with unicode symbols",
+
"ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+
"ext-openssl": "Required to send log messages using SSL",
+
"ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+
"mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+
"rollbar/rollbar": "Allow sending log messages to Rollbar",
+
"ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-main": "3.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Monolog\\": "src/Monolog"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Jordi Boggiano",
+
"email": "j.boggiano@seld.be",
+
"homepage": "https://seld.be"
+
}
+
],
+
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+
"homepage": "https://github.com/Seldaek/monolog",
+
"keywords": [
+
"log",
+
"logging",
+
"psr-3"
+
],
+
"support": {
+
"issues": "https://github.com/Seldaek/monolog/issues",
+
"source": "https://github.com/Seldaek/monolog/tree/3.9.0"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/Seldaek",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-03-24T10:02:05+00:00"
+
},
+
{
+
"name": "nesbot/carbon",
+
"version": "3.10.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/CarbonPHP/carbon.git",
+
"reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24",
+
"reference": "76b5c07b8a9d2025ed1610e14cef1f3fd6ad2c24",
+
"shasum": ""
+
},
+
"require": {
+
"carbonphp/carbon-doctrine-types": "<100.0",
+
"ext-json": "*",
+
"php": "^8.1",
+
"psr/clock": "^1.0",
+
"symfony/clock": "^6.3.12 || ^7.0",
+
"symfony/polyfill-mbstring": "^1.0",
+
"symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0"
+
},
+
"provide": {
+
"psr/clock-implementation": "1.0"
+
},
+
"require-dev": {
+
"doctrine/dbal": "^3.6.3 || ^4.0",
+
"doctrine/orm": "^2.15.2 || ^3.0",
+
"friendsofphp/php-cs-fixer": "^3.75.0",
+
"kylekatarnls/multi-tester": "^2.5.3",
+
"phpmd/phpmd": "^2.15.0",
+
"phpstan/extension-installer": "^1.4.3",
+
"phpstan/phpstan": "^2.1.17",
+
"phpunit/phpunit": "^10.5.46",
+
"squizlabs/php_codesniffer": "^3.13.0"
+
},
+
"bin": [
+
"bin/carbon"
+
],
+
"type": "library",
+
"extra": {
+
"laravel": {
+
"providers": [
+
"Carbon\\Laravel\\ServiceProvider"
+
]
+
},
+
"phpstan": {
+
"includes": [
+
"extension.neon"
+
]
+
},
+
"branch-alias": {
+
"dev-2.x": "2.x-dev",
+
"dev-master": "3.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Carbon\\": "src/Carbon/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Brian Nesbitt",
+
"email": "brian@nesbot.com",
+
"homepage": "https://markido.com"
+
},
+
{
+
"name": "kylekatarnls",
+
"homepage": "https://github.com/kylekatarnls"
+
}
+
],
+
"description": "An API extension for DateTime that supports 281 different languages.",
+
"homepage": "https://carbon.nesbot.com",
+
"keywords": [
+
"date",
+
"datetime",
+
"time"
+
],
+
"support": {
+
"docs": "https://carbon.nesbot.com/docs",
+
"issues": "https://github.com/CarbonPHP/carbon/issues",
+
"source": "https://github.com/CarbonPHP/carbon"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/sponsors/kylekatarnls",
+
"type": "github"
+
},
+
{
+
"url": "https://opencollective.com/Carbon#sponsor",
+
"type": "opencollective"
+
},
+
{
+
"url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-02T09:36:06+00:00"
+
},
+
{
+
"name": "nunomaduro/termwind",
+
"version": "v2.3.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/nunomaduro/termwind.git",
+
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/nunomaduro/termwind/zipball/dfa08f390e509967a15c22493dc0bac5733d9123",
+
"reference": "dfa08f390e509967a15c22493dc0bac5733d9123",
+
"shasum": ""
+
},
+
"require": {
+
"ext-mbstring": "*",
+
"php": "^8.2",
+
"symfony/console": "^7.2.6"
+
},
+
"require-dev": {
+
"illuminate/console": "^11.44.7",
+
"laravel/pint": "^1.22.0",
+
"mockery/mockery": "^1.6.12",
+
"pestphp/pest": "^2.36.0 || ^3.8.2",
+
"phpstan/phpstan": "^1.12.25",
+
"phpstan/phpstan-strict-rules": "^1.6.2",
+
"symfony/var-dumper": "^7.2.6",
+
"thecodingmachine/phpstan-strict-rules": "^1.0.0"
+
},
+
"type": "library",
+
"extra": {
+
"laravel": {
+
"providers": [
+
"Termwind\\Laravel\\TermwindServiceProvider"
+
]
+
},
+
"branch-alias": {
+
"dev-2.x": "2.x-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"src/Functions.php"
+
],
+
"psr-4": {
+
"Termwind\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nuno Maduro",
+
"email": "enunomaduro@gmail.com"
+
}
+
],
+
"description": "Its like Tailwind CSS, but for the console.",
+
"keywords": [
+
"cli",
+
"console",
+
"css",
+
"package",
+
"php",
+
"style"
+
],
+
"support": {
+
"issues": "https://github.com/nunomaduro/termwind/issues",
+
"source": "https://github.com/nunomaduro/termwind/tree/v2.3.1"
+
},
+
"funding": [
+
{
+
"url": "https://www.paypal.com/paypalme/enunomaduro",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/nunomaduro",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/xiCO2k",
+
"type": "github"
+
}
+
],
+
"time": "2025-05-08T08:14:37+00:00"
+
},
+
{
+
"name": "phpoption/phpoption",
+
"version": "1.9.4",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/schmittjoh/php-option.git",
+
"reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
+
"reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2.5 || ^8.0"
+
},
+
"require-dev": {
+
"bamarni/composer-bin-plugin": "^1.8.2",
+
"phpunit/phpunit": "^8.5.44 || ^9.6.25 || ^10.5.53 || ^11.5.34"
+
},
+
"type": "library",
+
"extra": {
+
"bamarni-bin": {
+
"bin-links": true,
+
"forward-command": false
+
},
+
"branch-alias": {
+
"dev-master": "1.9-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"PhpOption\\": "src/PhpOption/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"Apache-2.0"
+
],
+
"authors": [
+
{
+
"name": "Johannes M. Schmitt",
+
"email": "schmittjoh@gmail.com",
+
"homepage": "https://github.com/schmittjoh"
+
},
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
}
+
],
+
"description": "Option Type for PHP",
+
"keywords": [
+
"language",
+
"option",
+
"php",
+
"type"
+
],
+
"support": {
+
"issues": "https://github.com/schmittjoh/php-option/issues",
+
"source": "https://github.com/schmittjoh/php-option/tree/1.9.4"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/phpoption/phpoption",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-21T11:53:16+00:00"
+
},
+
{
+
"name": "psr/clock",
+
"version": "1.0.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/clock.git",
+
"reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+
"reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.0 || ^8.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Psr\\Clock\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "Common interface for reading the clock.",
+
"homepage": "https://github.com/php-fig/clock",
+
"keywords": [
+
"clock",
+
"now",
+
"psr",
+
"psr-20",
+
"time"
+
],
+
"support": {
+
"issues": "https://github.com/php-fig/clock/issues",
+
"source": "https://github.com/php-fig/clock/tree/1.0.0"
+
},
+
"time": "2022-11-25T14:36:26+00:00"
+
},
+
{
+
"name": "psr/container",
+
"version": "2.0.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/container.git",
+
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.4.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "2.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\Container\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "Common Container Interface (PHP FIG PSR-11)",
+
"homepage": "https://github.com/php-fig/container",
+
"keywords": [
+
"PSR-11",
+
"container",
+
"container-interface",
+
"container-interop",
+
"psr"
+
],
+
"support": {
+
"issues": "https://github.com/php-fig/container/issues",
+
"source": "https://github.com/php-fig/container/tree/2.0.2"
+
},
+
"time": "2021-11-05T16:47:00+00:00"
+
},
+
{
+
"name": "psr/event-dispatcher",
+
"version": "1.0.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/event-dispatcher.git",
+
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
+
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "1.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\EventDispatcher\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "http://www.php-fig.org/"
+
}
+
],
+
"description": "Standard interfaces for event handling.",
+
"keywords": [
+
"events",
+
"psr",
+
"psr-14"
+
],
+
"support": {
+
"issues": "https://github.com/php-fig/event-dispatcher/issues",
+
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
+
},
+
"time": "2019-01-08T18:20:26+00:00"
+
},
+
{
+
"name": "psr/http-client",
+
"version": "1.0.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/http-client.git",
+
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90",
+
"reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.0 || ^8.0",
+
"psr/http-message": "^1.0 || ^2.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "1.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\Http\\Client\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "Common interface for HTTP clients",
+
"homepage": "https://github.com/php-fig/http-client",
+
"keywords": [
+
"http",
+
"http-client",
+
"psr",
+
"psr-18"
+
],
+
"support": {
+
"source": "https://github.com/php-fig/http-client"
+
},
+
"time": "2023-09-23T14:17:50+00:00"
+
},
+
{
+
"name": "psr/http-factory",
+
"version": "1.1.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/http-factory.git",
+
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+
"reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.1",
+
"psr/http-message": "^1.0 || ^2.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "1.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\Http\\Message\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+
"keywords": [
+
"factory",
+
"http",
+
"message",
+
"psr",
+
"psr-17",
+
"psr-7",
+
"request",
+
"response"
+
],
+
"support": {
+
"source": "https://github.com/php-fig/http-factory"
+
},
+
"time": "2024-04-15T12:06:14+00:00"
+
},
+
{
+
"name": "psr/http-message",
+
"version": "2.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/http-message.git",
+
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^7.2 || ^8.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "2.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\Http\\Message\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "Common interface for HTTP messages",
+
"homepage": "https://github.com/php-fig/http-message",
+
"keywords": [
+
"http",
+
"http-message",
+
"psr",
+
"psr-7",
+
"request",
+
"response"
+
],
+
"support": {
+
"source": "https://github.com/php-fig/http-message/tree/2.0"
+
},
+
"time": "2023-04-04T09:54:51+00:00"
+
},
+
{
+
"name": "psr/log",
+
"version": "3.0.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/log.git",
+
"reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+
"reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.0.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "3.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\Log\\": "src"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "Common interface for logging libraries",
+
"homepage": "https://github.com/php-fig/log",
+
"keywords": [
+
"log",
+
"psr",
+
"psr-3"
+
],
+
"support": {
+
"source": "https://github.com/php-fig/log/tree/3.0.2"
+
},
+
"time": "2024-09-11T13:17:53+00:00"
+
},
+
{
+
"name": "psr/simple-cache",
+
"version": "3.0.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/php-fig/simple-cache.git",
+
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
+
"reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.0.0"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "3.0.x-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Psr\\SimpleCache\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "PHP-FIG",
+
"homepage": "https://www.php-fig.org/"
+
}
+
],
+
"description": "Common interfaces for simple caching",
+
"keywords": [
+
"cache",
+
"caching",
+
"psr",
+
"psr-16",
+
"simple-cache"
+
],
+
"support": {
+
"source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
+
},
+
"time": "2021-10-29T13:26:27+00:00"
+
},
+
{
+
"name": "ralouphie/getallheaders",
+
"version": "3.0.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/ralouphie/getallheaders.git",
+
"reference": "120b605dfeb996808c31b6477290a714d356e822"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
+
"reference": "120b605dfeb996808c31b6477290a714d356e822",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=5.6"
+
},
+
"require-dev": {
+
"php-coveralls/php-coveralls": "^2.1",
+
"phpunit/phpunit": "^5 || ^6.5"
+
},
+
"type": "library",
+
"autoload": {
+
"files": [
+
"src/getallheaders.php"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Ralph Khattar",
+
"email": "ralph.khattar@gmail.com"
+
}
+
],
+
"description": "A polyfill for getallheaders.",
+
"support": {
+
"issues": "https://github.com/ralouphie/getallheaders/issues",
+
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
+
},
+
"time": "2019-03-08T08:55:37+00:00"
+
},
+
{
+
"name": "ramsey/collection",
+
"version": "2.1.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/ramsey/collection.git",
+
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+
"reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
+
"shasum": ""
+
},
+
"require": {
+
"php": "^8.1"
+
},
+
"require-dev": {
+
"captainhook/plugin-composer": "^5.3",
+
"ergebnis/composer-normalize": "^2.45",
+
"fakerphp/faker": "^1.24",
+
"hamcrest/hamcrest-php": "^2.0",
+
"jangregor/phpstan-prophecy": "^2.1",
+
"mockery/mockery": "^1.6",
+
"php-parallel-lint/php-console-highlighter": "^1.0",
+
"php-parallel-lint/php-parallel-lint": "^1.4",
+
"phpspec/prophecy-phpunit": "^2.3",
+
"phpstan/extension-installer": "^1.4",
+
"phpstan/phpstan": "^2.1",
+
"phpstan/phpstan-mockery": "^2.0",
+
"phpstan/phpstan-phpunit": "^2.0",
+
"phpunit/phpunit": "^10.5",
+
"ramsey/coding-standard": "^2.3",
+
"ramsey/conventional-commits": "^1.6",
+
"roave/security-advisories": "dev-latest"
+
},
+
"type": "library",
+
"extra": {
+
"captainhook": {
+
"force-install": true
+
},
+
"ramsey/conventional-commits": {
+
"configFile": "conventional-commits.json"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Ramsey\\Collection\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Ben Ramsey",
+
"email": "ben@benramsey.com",
+
"homepage": "https://benramsey.com"
+
}
+
],
+
"description": "A PHP library for representing and manipulating collections.",
+
"keywords": [
+
"array",
+
"collection",
+
"hash",
+
"map",
+
"queue",
+
"set"
+
],
+
"support": {
+
"issues": "https://github.com/ramsey/collection/issues",
+
"source": "https://github.com/ramsey/collection/tree/2.1.1"
+
},
+
"time": "2025-03-22T05:38:12+00:00"
+
},
+
{
+
"name": "ramsey/uuid",
+
"version": "4.9.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/ramsey/uuid.git",
+
"reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/ramsey/uuid/zipball/81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+
"reference": "81f941f6f729b1e3ceea61d9d014f8b6c6800440",
+
"shasum": ""
+
},
+
"require": {
+
"brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
+
"php": "^8.0",
+
"ramsey/collection": "^1.2 || ^2.0"
+
},
+
"replace": {
+
"rhumsaa/uuid": "self.version"
+
},
+
"require-dev": {
+
"captainhook/captainhook": "^5.25",
+
"captainhook/plugin-composer": "^5.3",
+
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+
"ergebnis/composer-normalize": "^2.47",
+
"mockery/mockery": "^1.6",
+
"paragonie/random-lib": "^2",
+
"php-mock/php-mock": "^2.6",
+
"php-mock/php-mock-mockery": "^1.5",
+
"php-parallel-lint/php-parallel-lint": "^1.4.0",
+
"phpbench/phpbench": "^1.2.14",
+
"phpstan/extension-installer": "^1.4",
+
"phpstan/phpstan": "^2.1",
+
"phpstan/phpstan-mockery": "^2.0",
+
"phpstan/phpstan-phpunit": "^2.0",
+
"phpunit/phpunit": "^9.6",
+
"slevomat/coding-standard": "^8.18",
+
"squizlabs/php_codesniffer": "^3.13"
+
},
+
"suggest": {
+
"ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
+
"ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
+
"ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
+
"paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
+
"ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
+
},
+
"type": "library",
+
"extra": {
+
"captainhook": {
+
"force-install": true
+
}
+
},
+
"autoload": {
+
"files": [
+
"src/functions.php"
+
],
+
"psr-4": {
+
"Ramsey\\Uuid\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+
"keywords": [
+
"guid",
+
"identifier",
+
"uuid"
+
],
+
"support": {
+
"issues": "https://github.com/ramsey/uuid/issues",
+
"source": "https://github.com/ramsey/uuid/tree/4.9.1"
+
},
+
"time": "2025-09-04T20:59:21+00:00"
+
},
+
{
+
"name": "roots/acorn",
+
"version": "v5.0.5",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/roots/acorn.git",
+
"reference": "bc51c932b87fc35dd1c8dd6bacb3c31469fe5029"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/roots/acorn/zipball/bc51c932b87fc35dd1c8dd6bacb3c31469fe5029",
+
"reference": "bc51c932b87fc35dd1c8dd6bacb3c31469fe5029",
+
"shasum": ""
+
},
+
"require": {
+
"dragonmantank/cron-expression": "^3.4",
+
"ext-json": "*",
+
"ext-mbstring": "*",
+
"guzzlehttp/guzzle": "^7.8",
+
"illuminate/auth": "^12.0",
+
"illuminate/cache": "^12.0",
+
"illuminate/config": "^12.0",
+
"illuminate/console": "^12.0",
+
"illuminate/container": "^12.0",
+
"illuminate/contracts": "^12.0",
+
"illuminate/cookie": "^12.0",
+
"illuminate/database": "^12.0",
+
"illuminate/encryption": "^12.0",
+
"illuminate/events": "^12.0",
+
"illuminate/filesystem": "^12.0",
+
"illuminate/hashing": "^12.0",
+
"illuminate/http": "^12.0",
+
"illuminate/log": "^12.0",
+
"illuminate/queue": "^12.0",
+
"illuminate/routing": "^12.0",
+
"illuminate/support": "^12.0",
+
"illuminate/testing": "^12.0",
+
"illuminate/validation": "^12.0",
+
"illuminate/view": "^12.0",
+
"laravel/prompts": "^0.3.0",
+
"laravel/serializable-closure": "^1.3",
+
"league/flysystem": "^3.26",
+
"php": ">=8.2",
+
"ramsey/uuid": "^4.7",
+
"roots/support": "^1.0",
+
"symfony/error-handler": "^7.0",
+
"symfony/var-dumper": "^7.0",
+
"vlucas/phpdotenv": "^5.6"
+
},
+
"require-dev": {
+
"laravel/pint": "^1.15",
+
"mockery/mockery": "^1.6",
+
"pestphp/pest": "^2.34",
+
"phpcompatibility/php-compatibility": "^9.3",
+
"roave/security-advisories": "dev-master",
+
"spatie/laravel-ignition": "^2.5",
+
"spatie/pest-plugin-snapshots": "^2.1",
+
"spatie/temporary-directory": "^2.2",
+
"tmarsteel/mockery-callable-mock": "^2.1",
+
"wp-cli/wp-cli": "^2.10"
+
},
+
"suggest": {
+
"roots/acorn-prettify": "A collection of modules to apply theme-agnostic front-end modifications (^1.0).",
+
"spatie/laravel-ignition": "A beautiful error page for development (^2.0)."
+
},
+
"bin": [
+
"bin/acorn"
+
],
+
"type": "library",
+
"autoload": {
+
"files": [
+
"src/Roots/helpers.php",
+
"src/Roots/globals.php"
+
],
+
"psr-4": {
+
"Roots\\": "src/Roots/",
+
"Illuminate\\": "src/Illuminate/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "QWp6t",
+
"email": "hi@qwp6t.me"
+
},
+
{
+
"name": "Brandon Nifong",
+
"email": "brandon@tendency.me"
+
}
+
],
+
"description": "Framework for Roots WordPress projects built with Laravel components.",
+
"homepage": "https://roots.io/acorn/",
+
"keywords": [
+
"laravel",
+
"livewire",
+
"sage",
+
"wordpress"
+
],
+
"support": {
+
"forum": "https://discourse.roots.io/",
+
"issues": "https://github.com/roots/acorn/issues",
+
"source": "https://github.com/roots/acorn/tree/v5.0.5"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/roots",
+
"type": "github"
+
}
+
],
+
"time": "2025-08-05T18:57:59+00:00"
+
},
+
{
+
"name": "roots/support",
+
"version": "v1.0.1",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/roots/support.git",
+
"reference": "e1b76fb2feb806e195833b125b6d23d598a88bb3"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/roots/support/zipball/e1b76fb2feb806e195833b125b6d23d598a88bb3",
+
"reference": "e1b76fb2feb806e195833b125b6d23d598a88bb3",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=5.6"
+
},
+
"require-dev": {
+
"phpunit/phpunit": "^7.2",
+
"squizlabs/php_codesniffer": "^3.3"
+
},
+
"type": "library",
+
"autoload": {
+
"files": [
+
"helpers.php"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "QWp6t",
+
"email": "hi@qwp6t.me"
+
}
+
],
+
"homepage": "https://github.com/roots/support/",
+
"support": {
+
"forum": "https://discourse.roots.io/",
+
"issues": "https://github.com/roots/support/issues",
+
"source": "https://github.com/roots/support/tree/v1.0.1"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/roots",
+
"type": "github"
+
}
+
],
+
"time": "2024-05-08T21:05:03+00:00"
+
},
+
{
+
"name": "symfony/clock",
+
"version": "v7.3.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/clock.git",
+
"reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
+
"reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"psr/clock": "^1.0",
+
"symfony/polyfill-php83": "^1.28"
+
},
+
"provide": {
+
"psr/clock-implementation": "1.0"
+
},
+
"type": "library",
+
"autoload": {
+
"files": [
+
"Resources/now.php"
+
],
+
"psr-4": {
+
"Symfony\\Component\\Clock\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Decouples applications from the system clock",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"clock",
+
"psr20",
+
"time"
+
],
+
"support": {
+
"source": "https://github.com/symfony/clock/tree/v7.3.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-25T14:21:43+00:00"
+
},
+
{
+
"name": "symfony/console",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/console.git",
+
"reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/console/zipball/cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7",
+
"reference": "cb0102a1c5ac3807cf3fdf8bea96007df7fdbea7",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/deprecation-contracts": "^2.5|^3",
+
"symfony/polyfill-mbstring": "~1.0",
+
"symfony/service-contracts": "^2.5|^3",
+
"symfony/string": "^7.2"
+
},
+
"conflict": {
+
"symfony/dependency-injection": "<6.4",
+
"symfony/dotenv": "<6.4",
+
"symfony/event-dispatcher": "<6.4",
+
"symfony/lock": "<6.4",
+
"symfony/process": "<6.4"
+
},
+
"provide": {
+
"psr/log-implementation": "1.0|2.0|3.0"
+
},
+
"require-dev": {
+
"psr/log": "^1|^2|^3",
+
"symfony/config": "^6.4|^7.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/event-dispatcher": "^6.4|^7.0",
+
"symfony/http-foundation": "^6.4|^7.0",
+
"symfony/http-kernel": "^6.4|^7.0",
+
"symfony/lock": "^6.4|^7.0",
+
"symfony/messenger": "^6.4|^7.0",
+
"symfony/process": "^6.4|^7.0",
+
"symfony/stopwatch": "^6.4|^7.0",
+
"symfony/var-dumper": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\Console\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Eases the creation of beautiful and testable command line interfaces",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"cli",
+
"command-line",
+
"console",
+
"terminal"
+
],
+
"support": {
+
"source": "https://github.com/symfony/console/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-25T06:35:40+00:00"
+
},
+
{
+
"name": "symfony/deprecation-contracts",
+
"version": "v3.6.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/deprecation-contracts.git",
+
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
+
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.1"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/contracts",
+
"name": "symfony/contracts"
+
},
+
"branch-alias": {
+
"dev-main": "3.6-dev"
+
}
+
},
+
"autoload": {
+
"files": [
+
"function.php"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "A generic function and convention to trigger deprecation notices",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-25T14:21:43+00:00"
+
},
+
{
+
"name": "symfony/error-handler",
+
"version": "v7.3.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/error-handler.git",
+
"reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/error-handler/zipball/0b31a944fcd8759ae294da4d2808cbc53aebd0c3",
+
"reference": "0b31a944fcd8759ae294da4d2808cbc53aebd0c3",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"psr/log": "^1|^2|^3",
+
"symfony/var-dumper": "^6.4|^7.0"
+
},
+
"conflict": {
+
"symfony/deprecation-contracts": "<2.5",
+
"symfony/http-kernel": "<6.4"
+
},
+
"require-dev": {
+
"symfony/console": "^6.4|^7.0",
+
"symfony/deprecation-contracts": "^2.5|^3",
+
"symfony/http-kernel": "^6.4|^7.0",
+
"symfony/serializer": "^6.4|^7.0",
+
"symfony/webpack-encore-bundle": "^1.0|^2.0"
+
},
+
"bin": [
+
"Resources/bin/patch-type-declarations"
+
],
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\ErrorHandler\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Provides tools to manage errors and ease debugging PHP code",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/error-handler/tree/v7.3.2"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-07-07T08:17:57+00:00"
+
},
+
{
+
"name": "symfony/event-dispatcher",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/event-dispatcher.git",
+
"reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191",
+
"reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/event-dispatcher-contracts": "^2.5|^3"
+
},
+
"conflict": {
+
"symfony/dependency-injection": "<6.4",
+
"symfony/service-contracts": "<2.5"
+
},
+
"provide": {
+
"psr/event-dispatcher-implementation": "1.0",
+
"symfony/event-dispatcher-implementation": "2.0|3.0"
+
},
+
"require-dev": {
+
"psr/log": "^1|^2|^3",
+
"symfony/config": "^6.4|^7.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/error-handler": "^6.4|^7.0",
+
"symfony/expression-language": "^6.4|^7.0",
+
"symfony/http-foundation": "^6.4|^7.0",
+
"symfony/service-contracts": "^2.5|^3",
+
"symfony/stopwatch": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\EventDispatcher\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-13T11:49:31+00:00"
+
},
+
{
+
"name": "symfony/event-dispatcher-contracts",
+
"version": "v3.6.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/event-dispatcher-contracts.git",
+
"reference": "59eb412e93815df44f05f342958efa9f46b1e586"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586",
+
"reference": "59eb412e93815df44f05f342958efa9f46b1e586",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.1",
+
"psr/event-dispatcher": "^1"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/contracts",
+
"name": "symfony/contracts"
+
},
+
"branch-alias": {
+
"dev-main": "3.6-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Contracts\\EventDispatcher\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Generic abstractions related to dispatching event",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"abstractions",
+
"contracts",
+
"decoupling",
+
"interfaces",
+
"interoperability",
+
"standards"
+
],
+
"support": {
+
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-25T14:21:43+00:00"
+
},
+
{
+
"name": "symfony/finder",
+
"version": "v7.3.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/finder.git",
+
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
+
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2"
+
},
+
"require-dev": {
+
"symfony/filesystem": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\Finder\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Finds files and directories via an intuitive fluent interface",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/finder/tree/v7.3.2"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-07-15T13:41:35+00:00"
+
},
+
{
+
"name": "symfony/http-foundation",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/http-foundation.git",
+
"reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/7475561ec27020196c49bb7c4f178d33d7d3dc00",
+
"reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/deprecation-contracts": "^2.5|^3.0",
+
"symfony/polyfill-mbstring": "~1.1",
+
"symfony/polyfill-php83": "^1.27"
+
},
+
"conflict": {
+
"doctrine/dbal": "<3.6",
+
"symfony/cache": "<6.4.12|>=7.0,<7.1.5"
+
},
+
"require-dev": {
+
"doctrine/dbal": "^3.6|^4",
+
"predis/predis": "^1.1|^2.0",
+
"symfony/cache": "^6.4.12|^7.1.5",
+
"symfony/clock": "^6.4|^7.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/expression-language": "^6.4|^7.0",
+
"symfony/http-kernel": "^6.4|^7.0",
+
"symfony/mime": "^6.4|^7.0",
+
"symfony/rate-limiter": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\HttpFoundation\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Defines an object-oriented layer for the HTTP specification",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/http-foundation/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-20T08:04:18+00:00"
+
},
+
{
+
"name": "symfony/http-kernel",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/http-kernel.git",
+
"reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/72c304de37e1a1cec6d5d12b81187ebd4850a17b",
+
"reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"psr/log": "^1|^2|^3",
+
"symfony/deprecation-contracts": "^2.5|^3",
+
"symfony/error-handler": "^6.4|^7.0",
+
"symfony/event-dispatcher": "^7.3",
+
"symfony/http-foundation": "^7.3",
+
"symfony/polyfill-ctype": "^1.8"
+
},
+
"conflict": {
+
"symfony/browser-kit": "<6.4",
+
"symfony/cache": "<6.4",
+
"symfony/config": "<6.4",
+
"symfony/console": "<6.4",
+
"symfony/dependency-injection": "<6.4",
+
"symfony/doctrine-bridge": "<6.4",
+
"symfony/form": "<6.4",
+
"symfony/http-client": "<6.4",
+
"symfony/http-client-contracts": "<2.5",
+
"symfony/mailer": "<6.4",
+
"symfony/messenger": "<6.4",
+
"symfony/translation": "<6.4",
+
"symfony/translation-contracts": "<2.5",
+
"symfony/twig-bridge": "<6.4",
+
"symfony/validator": "<6.4",
+
"symfony/var-dumper": "<6.4",
+
"twig/twig": "<3.12"
+
},
+
"provide": {
+
"psr/log-implementation": "1.0|2.0|3.0"
+
},
+
"require-dev": {
+
"psr/cache": "^1.0|^2.0|^3.0",
+
"symfony/browser-kit": "^6.4|^7.0",
+
"symfony/clock": "^6.4|^7.0",
+
"symfony/config": "^6.4|^7.0",
+
"symfony/console": "^6.4|^7.0",
+
"symfony/css-selector": "^6.4|^7.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/dom-crawler": "^6.4|^7.0",
+
"symfony/expression-language": "^6.4|^7.0",
+
"symfony/finder": "^6.4|^7.0",
+
"symfony/http-client-contracts": "^2.5|^3",
+
"symfony/process": "^6.4|^7.0",
+
"symfony/property-access": "^7.1",
+
"symfony/routing": "^6.4|^7.0",
+
"symfony/serializer": "^7.1",
+
"symfony/stopwatch": "^6.4|^7.0",
+
"symfony/translation": "^6.4|^7.0",
+
"symfony/translation-contracts": "^2.5|^3",
+
"symfony/uid": "^6.4|^7.0",
+
"symfony/validator": "^6.4|^7.0",
+
"symfony/var-dumper": "^6.4|^7.0",
+
"symfony/var-exporter": "^6.4|^7.0",
+
"twig/twig": "^3.12"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\HttpKernel\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Provides a structured process for converting a Request into a Response",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/http-kernel/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-29T08:23:45+00:00"
+
},
+
{
+
"name": "symfony/mime",
+
"version": "v7.3.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/mime.git",
+
"reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1",
+
"reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/polyfill-intl-idn": "^1.10",
+
"symfony/polyfill-mbstring": "^1.0"
+
},
+
"conflict": {
+
"egulias/email-validator": "~3.0.0",
+
"phpdocumentor/reflection-docblock": "<3.2.2",
+
"phpdocumentor/type-resolver": "<1.4.0",
+
"symfony/mailer": "<6.4",
+
"symfony/serializer": "<6.4.3|>7.0,<7.0.3"
+
},
+
"require-dev": {
+
"egulias/email-validator": "^2.1.10|^3.1|^4",
+
"league/html-to-markdown": "^5.0",
+
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/process": "^6.4|^7.0",
+
"symfony/property-access": "^6.4|^7.0",
+
"symfony/property-info": "^6.4|^7.0",
+
"symfony/serializer": "^6.4.3|^7.0.3"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\Mime\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Allows manipulating MIME messages",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"mime",
+
"mime-type"
+
],
+
"support": {
+
"source": "https://github.com/symfony/mime/tree/v7.3.2"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-07-15T13:41:35+00:00"
+
},
+
{
+
"name": "symfony/polyfill-ctype",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-ctype.git",
+
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638",
+
"reference": "a3cc8b044a6ea513310cbd48ef7333b384945638",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"provide": {
+
"ext-ctype": "*"
+
},
+
"suggest": {
+
"ext-ctype": "For best performance"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Ctype\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Gert de Pagter",
+
"email": "BackEndTea@gmail.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill for ctype functions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"ctype",
+
"polyfill",
+
"portable"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-09T11:45:10+00:00"
+
},
+
{
+
"name": "symfony/polyfill-intl-grapheme",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
+
"reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70",
+
"reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"suggest": {
+
"ext-intl": "For best performance"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill for intl's grapheme_* functions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"grapheme",
+
"intl",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-06-27T09:58:17+00:00"
+
},
+
{
+
"name": "symfony/polyfill-intl-idn",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-intl-idn.git",
+
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+
"reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2",
+
"symfony/polyfill-intl-normalizer": "^1.10"
+
},
+
"suggest": {
+
"ext-intl": "For best performance"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Intl\\Idn\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Laurent Bassin",
+
"email": "laurent@bassin.info"
+
},
+
{
+
"name": "Trevor Rowbotham",
+
"email": "trevor.rowbotham@pm.me"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"idn",
+
"intl",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-10T14:38:51+00:00"
+
},
+
{
+
"name": "symfony/polyfill-intl-normalizer",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
+
"reference": "3833d7255cc303546435cb650316bff708a1c75c"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
+
"reference": "3833d7255cc303546435cb650316bff708a1c75c",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"suggest": {
+
"ext-intl": "For best performance"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Intl\\Normalizer\\": ""
+
},
+
"classmap": [
+
"Resources/stubs"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill for intl's Normalizer class and related functions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"intl",
+
"normalizer",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-09T11:45:10+00:00"
+
},
+
{
+
"name": "symfony/polyfill-mbstring",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-mbstring.git",
+
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+
"reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
+
"shasum": ""
+
},
+
"require": {
+
"ext-iconv": "*",
+
"php": ">=7.2"
+
},
+
"provide": {
+
"ext-mbstring": "*"
+
},
+
"suggest": {
+
"ext-mbstring": "For best performance"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Mbstring\\": ""
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill for the Mbstring extension",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"mbstring",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-12-23T08:48:59+00:00"
+
},
+
{
+
"name": "symfony/polyfill-php80",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-php80.git",
+
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Php80\\": ""
+
},
+
"classmap": [
+
"Resources/stubs"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Ion Bazan",
+
"email": "ion.bazan@gmail.com"
+
},
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-01-02T08:10:11+00:00"
+
},
+
{
+
"name": "symfony/polyfill-php83",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-php83.git",
+
"reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5",
+
"reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Php83\\": ""
+
},
+
"classmap": [
+
"Resources/stubs"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-07-08T02:45:35+00:00"
+
},
+
{
+
"name": "symfony/polyfill-php84",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-php84.git",
+
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191",
+
"reference": "d8ced4d875142b6a7426000426b8abc631d6b191",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Php84\\": ""
+
},
+
"classmap": [
+
"Resources/stubs"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-06-24T13:30:11+00:00"
+
},
+
{
+
"name": "symfony/polyfill-php85",
+
"version": "v1.33.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/polyfill-php85.git",
+
"reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91",
+
"reference": "d4e5fcd4ab3d998ab16c0db48e6cbb9a01993f91",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.2"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/polyfill",
+
"name": "symfony/polyfill"
+
}
+
},
+
"autoload": {
+
"files": [
+
"bootstrap.php"
+
],
+
"psr-4": {
+
"Symfony\\Polyfill\\Php85\\": ""
+
},
+
"classmap": [
+
"Resources/stubs"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"compatibility",
+
"polyfill",
+
"portable",
+
"shim"
+
],
+
"support": {
+
"source": "https://github.com/symfony/polyfill-php85/tree/v1.33.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-06-23T16:12:55+00:00"
+
},
+
{
+
"name": "symfony/process",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/process.git",
+
"reference": "32241012d521e2e8a9d713adb0812bb773b907f1"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1",
+
"reference": "32241012d521e2e8a9d713adb0812bb773b907f1",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\Process\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Executes commands in sub-processes",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/process/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-18T09:42:54+00:00"
+
},
+
{
+
"name": "symfony/routing",
+
"version": "v7.3.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/routing.git",
+
"reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/routing/zipball/7614b8ca5fa89b9cd233e21b627bfc5774f586e4",
+
"reference": "7614b8ca5fa89b9cd233e21b627bfc5774f586e4",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/deprecation-contracts": "^2.5|^3"
+
},
+
"conflict": {
+
"symfony/config": "<6.4",
+
"symfony/dependency-injection": "<6.4",
+
"symfony/yaml": "<6.4"
+
},
+
"require-dev": {
+
"psr/log": "^1|^2|^3",
+
"symfony/config": "^6.4|^7.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/expression-language": "^6.4|^7.0",
+
"symfony/http-foundation": "^6.4|^7.0",
+
"symfony/yaml": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Component\\Routing\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Maps an HTTP request to a set of configuration variables",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"router",
+
"routing",
+
"uri",
+
"url"
+
],
+
"support": {
+
"source": "https://github.com/symfony/routing/tree/v7.3.2"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-07-15T11:36:08+00:00"
+
},
+
{
+
"name": "symfony/service-contracts",
+
"version": "v3.6.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/service-contracts.git",
+
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
+
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.1",
+
"psr/container": "^1.1|^2.0",
+
"symfony/deprecation-contracts": "^2.5|^3"
+
},
+
"conflict": {
+
"ext-psr": "<1.1|>=2"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/contracts",
+
"name": "symfony/contracts"
+
},
+
"branch-alias": {
+
"dev-main": "3.6-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Contracts\\Service\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Test/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Generic abstractions related to writing services",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"abstractions",
+
"contracts",
+
"decoupling",
+
"interfaces",
+
"interoperability",
+
"standards"
+
],
+
"support": {
+
"source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-04-25T09:37:31+00:00"
+
},
+
{
+
"name": "symfony/string",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/string.git",
+
"reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
+
"reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/polyfill-ctype": "~1.8",
+
"symfony/polyfill-intl-grapheme": "~1.0",
+
"symfony/polyfill-intl-normalizer": "~1.0",
+
"symfony/polyfill-mbstring": "~1.0"
+
},
+
"conflict": {
+
"symfony/translation-contracts": "<2.5"
+
},
+
"require-dev": {
+
"symfony/emoji": "^7.1",
+
"symfony/error-handler": "^6.4|^7.0",
+
"symfony/http-client": "^6.4|^7.0",
+
"symfony/intl": "^6.4|^7.0",
+
"symfony/translation-contracts": "^2.5|^3.0",
+
"symfony/var-exporter": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"files": [
+
"Resources/functions.php"
+
],
+
"psr-4": {
+
"Symfony\\Component\\String\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"grapheme",
+
"i18n",
+
"string",
+
"unicode",
+
"utf-8",
+
"utf8"
+
],
+
"support": {
+
"source": "https://github.com/symfony/string/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-25T06:35:40+00:00"
+
},
+
{
+
"name": "symfony/translation",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/translation.git",
+
"reference": "e0837b4cbcef63c754d89a4806575cada743a38d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/translation/zipball/e0837b4cbcef63c754d89a4806575cada743a38d",
+
"reference": "e0837b4cbcef63c754d89a4806575cada743a38d",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/deprecation-contracts": "^2.5|^3",
+
"symfony/polyfill-mbstring": "~1.0",
+
"symfony/translation-contracts": "^2.5|^3.0"
+
},
+
"conflict": {
+
"nikic/php-parser": "<5.0",
+
"symfony/config": "<6.4",
+
"symfony/console": "<6.4",
+
"symfony/dependency-injection": "<6.4",
+
"symfony/http-client-contracts": "<2.5",
+
"symfony/http-kernel": "<6.4",
+
"symfony/service-contracts": "<2.5",
+
"symfony/twig-bundle": "<6.4",
+
"symfony/yaml": "<6.4"
+
},
+
"provide": {
+
"symfony/translation-implementation": "2.3|3.0"
+
},
+
"require-dev": {
+
"nikic/php-parser": "^5.0",
+
"psr/log": "^1|^2|^3",
+
"symfony/config": "^6.4|^7.0",
+
"symfony/console": "^6.4|^7.0",
+
"symfony/dependency-injection": "^6.4|^7.0",
+
"symfony/finder": "^6.4|^7.0",
+
"symfony/http-client-contracts": "^2.5|^3.0",
+
"symfony/http-kernel": "^6.4|^7.0",
+
"symfony/intl": "^6.4|^7.0",
+
"symfony/polyfill-intl-icu": "^1.21",
+
"symfony/routing": "^6.4|^7.0",
+
"symfony/service-contracts": "^2.5|^3",
+
"symfony/yaml": "^6.4|^7.0"
+
},
+
"type": "library",
+
"autoload": {
+
"files": [
+
"Resources/functions.php"
+
],
+
"psr-4": {
+
"Symfony\\Component\\Translation\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Fabien Potencier",
+
"email": "fabien@symfony.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Provides tools to internationalize your application",
+
"homepage": "https://symfony.com",
+
"support": {
+
"source": "https://github.com/symfony/translation/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-01T21:02:37+00:00"
+
},
+
{
+
"name": "symfony/translation-contracts",
+
"version": "v3.6.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/translation-contracts.git",
+
"reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d",
+
"reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.1"
+
},
+
"type": "library",
+
"extra": {
+
"thanks": {
+
"url": "https://github.com/symfony/contracts",
+
"name": "symfony/contracts"
+
},
+
"branch-alias": {
+
"dev-main": "3.6-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Symfony\\Contracts\\Translation\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Test/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Generic abstractions related to translation",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"abstractions",
+
"contracts",
+
"decoupling",
+
"interfaces",
+
"interoperability",
+
"standards"
+
],
+
"support": {
+
"source": "https://github.com/symfony/translation-contracts/tree/v3.6.0"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-09-27T08:32:26+00:00"
+
},
+
{
+
"name": "symfony/var-dumper",
+
"version": "v7.3.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/symfony/var-dumper.git",
+
"reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f",
+
"reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=8.2",
+
"symfony/deprecation-contracts": "^2.5|^3",
+
"symfony/polyfill-mbstring": "~1.0"
+
},
+
"conflict": {
+
"symfony/console": "<6.4"
+
},
+
"require-dev": {
+
"symfony/console": "^6.4|^7.0",
+
"symfony/http-kernel": "^6.4|^7.0",
+
"symfony/process": "^6.4|^7.0",
+
"symfony/uid": "^6.4|^7.0",
+
"twig/twig": "^3.12"
+
},
+
"bin": [
+
"Resources/bin/var-dump-server"
+
],
+
"type": "library",
+
"autoload": {
+
"files": [
+
"Resources/functions/dump.php"
+
],
+
"psr-4": {
+
"Symfony\\Component\\VarDumper\\": ""
+
},
+
"exclude-from-classmap": [
+
"/Tests/"
+
]
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nicolas Grekas",
+
"email": "p@tchwork.com"
+
},
+
{
+
"name": "Symfony Community",
+
"homepage": "https://symfony.com/contributors"
+
}
+
],
+
"description": "Provides mechanisms for walking through any arbitrary PHP variable",
+
"homepage": "https://symfony.com",
+
"keywords": [
+
"debug",
+
"dump"
+
],
+
"support": {
+
"source": "https://github.com/symfony/var-dumper/tree/v7.3.3"
+
},
+
"funding": [
+
{
+
"url": "https://symfony.com/sponsor",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/fabpot",
+
"type": "github"
+
},
+
{
+
"url": "https://github.com/nicolas-grekas",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-08-13T11:49:31+00:00"
+
},
+
{
+
"name": "vlucas/phpdotenv",
+
"version": "v5.6.2",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/vlucas/phpdotenv.git",
+
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
+
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af",
+
"shasum": ""
+
},
+
"require": {
+
"ext-pcre": "*",
+
"graham-campbell/result-type": "^1.1.3",
+
"php": "^7.2.5 || ^8.0",
+
"phpoption/phpoption": "^1.9.3",
+
"symfony/polyfill-ctype": "^1.24",
+
"symfony/polyfill-mbstring": "^1.24",
+
"symfony/polyfill-php80": "^1.24"
+
},
+
"require-dev": {
+
"bamarni/composer-bin-plugin": "^1.8.2",
+
"ext-filter": "*",
+
"phpunit/phpunit": "^8.5.34 || ^9.6.13 || ^10.4.2"
+
},
+
"suggest": {
+
"ext-filter": "Required to use the boolean validator."
+
},
+
"type": "library",
+
"extra": {
+
"bamarni-bin": {
+
"bin-links": true,
+
"forward-command": false
+
},
+
"branch-alias": {
+
"dev-master": "5.6-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Dotenv\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"BSD-3-Clause"
+
],
+
"authors": [
+
{
+
"name": "Graham Campbell",
+
"email": "hello@gjcampbell.co.uk",
+
"homepage": "https://github.com/GrahamCampbell"
+
},
+
{
+
"name": "Vance Lucas",
+
"email": "vance@vancelucas.com",
+
"homepage": "https://github.com/vlucas"
+
}
+
],
+
"description": "Loads environment variables from `.env` to `getenv()`, `$_ENV` and `$_SERVER` automagically.",
+
"keywords": [
+
"dotenv",
+
"env",
+
"environment"
+
],
+
"support": {
+
"issues": "https://github.com/vlucas/phpdotenv/issues",
+
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2"
+
},
+
"funding": [
+
{
+
"url": "https://github.com/GrahamCampbell",
+
"type": "github"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
+
"type": "tidelift"
+
}
+
],
+
"time": "2025-04-30T23:37:27+00:00"
+
},
+
{
+
"name": "voku/portable-ascii",
+
"version": "2.0.3",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/voku/portable-ascii.git",
+
"reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d",
+
"reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d",
+
"shasum": ""
+
},
+
"require": {
+
"php": ">=7.0.0"
+
},
+
"require-dev": {
+
"phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+
},
+
"suggest": {
+
"ext-intl": "Use Intl for transliterator_transliterate() support"
+
},
+
"type": "library",
+
"autoload": {
+
"psr-4": {
+
"voku\\": "src/voku/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Lars Moelleken",
+
"homepage": "https://www.moelleken.org/"
+
}
+
],
+
"description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
+
"homepage": "https://github.com/voku/portable-ascii",
+
"keywords": [
+
"ascii",
+
"clean",
+
"php"
+
],
+
"support": {
+
"issues": "https://github.com/voku/portable-ascii/issues",
+
"source": "https://github.com/voku/portable-ascii/tree/2.0.3"
+
},
+
"funding": [
+
{
+
"url": "https://www.paypal.me/moelleken",
+
"type": "custom"
+
},
+
{
+
"url": "https://github.com/voku",
+
"type": "github"
+
},
+
{
+
"url": "https://opencollective.com/portable-ascii",
+
"type": "open_collective"
+
},
+
{
+
"url": "https://www.patreon.com/voku",
+
"type": "patreon"
+
},
+
{
+
"url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
+
"type": "tidelift"
+
}
+
],
+
"time": "2024-11-21T01:49:47+00:00"
+
},
+
{
+
"name": "webmozart/assert",
+
"version": "1.11.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/webmozarts/assert.git",
+
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991",
+
"reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991",
+
"shasum": ""
+
},
+
"require": {
+
"ext-ctype": "*",
+
"php": "^7.2 || ^8.0"
+
},
+
"conflict": {
+
"phpstan/phpstan": "<0.12.20",
+
"vimeo/psalm": "<4.6.1 || 4.6.2"
+
},
+
"require-dev": {
+
"phpunit/phpunit": "^8.5.13"
+
},
+
"type": "library",
+
"extra": {
+
"branch-alias": {
+
"dev-master": "1.10-dev"
+
}
+
},
+
"autoload": {
+
"psr-4": {
+
"Webmozart\\Assert\\": "src/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Bernhard Schussek",
+
"email": "bschussek@gmail.com"
+
}
+
],
+
"description": "Assertions to validate method input/output with nice error messages.",
+
"keywords": [
+
"assert",
+
"check",
+
"validate"
+
],
+
"support": {
+
"issues": "https://github.com/webmozarts/assert/issues",
+
"source": "https://github.com/webmozarts/assert/tree/1.11.0"
+
},
+
"time": "2022-06-03T18:03:27+00:00"
+
}
+
],
+
"packages-dev": [
+
{
+
"name": "laravel/pint",
+
"version": "v1.24.0",
+
"source": {
+
"type": "git",
+
"url": "https://github.com/laravel/pint.git",
+
"reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a"
+
},
+
"dist": {
+
"type": "zip",
+
"url": "https://api.github.com/repos/laravel/pint/zipball/0345f3b05f136801af8c339f9d16ef29e6b4df8a",
+
"reference": "0345f3b05f136801af8c339f9d16ef29e6b4df8a",
+
"shasum": ""
+
},
+
"require": {
+
"ext-json": "*",
+
"ext-mbstring": "*",
+
"ext-tokenizer": "*",
+
"ext-xml": "*",
+
"php": "^8.2.0"
+
},
+
"require-dev": {
+
"friendsofphp/php-cs-fixer": "^3.82.2",
+
"illuminate/view": "^11.45.1",
+
"larastan/larastan": "^3.5.0",
+
"laravel-zero/framework": "^11.45.0",
+
"mockery/mockery": "^1.6.12",
+
"nunomaduro/termwind": "^2.3.1",
+
"pestphp/pest": "^2.36.0"
+
},
+
"bin": [
+
"builds/pint"
+
],
+
"type": "project",
+
"autoload": {
+
"files": [
+
"overrides/Runner/Parallel/ProcessFactory.php"
+
],
+
"psr-4": {
+
"App\\": "app/",
+
"Database\\Seeders\\": "database/seeders/",
+
"Database\\Factories\\": "database/factories/"
+
}
+
},
+
"notification-url": "https://packagist.org/downloads/",
+
"license": [
+
"MIT"
+
],
+
"authors": [
+
{
+
"name": "Nuno Maduro",
+
"email": "enunomaduro@gmail.com"
+
}
+
],
+
"description": "An opinionated code formatter for PHP.",
+
"homepage": "https://laravel.com",
+
"keywords": [
+
"format",
+
"formatter",
+
"lint",
+
"linter",
+
"php"
+
],
+
"support": {
+
"issues": "https://github.com/laravel/pint/issues",
+
"source": "https://github.com/laravel/pint"
+
},
+
"time": "2025-07-10T18:09:32+00:00"
+
}
+
],
+
"aliases": [],
+
"minimum-stability": "dev",
+
"stability-flags": {},
+
"prefer-stable": true,
+
"prefer-lowest": false,
+
"platform": {
+
"php": ">=8.2"
+
},
+
"platform-dev": {},
+
"plugin-api-version": "2.6.0"
+
}
+60
wordpress/functions.php
···
+
<?php
+
+
use Roots\Acorn\Application;
+
+
/*
+
|--------------------------------------------------------------------------
+
| Register The Auto Loader
+
|--------------------------------------------------------------------------
+
|
+
| Composer provides a convenient, automatically generated class loader for
+
| our theme. We will simply require it into the script here so that we
+
| don't have to worry about manually loading any of our classes later on.
+
|
+
*/
+
+
if (! file_exists($composer = __DIR__.'/vendor/autoload.php')) {
+
wp_die(__('Error locating autoloader. Please run <code>composer install</code>.', 'sage'));
+
}
+
+
require $composer;
+
+
/*
+
|--------------------------------------------------------------------------
+
| Register The Bootloader
+
|--------------------------------------------------------------------------
+
|
+
| The first thing we will do is schedule a new Acorn application container
+
| to boot when WordPress is finished loading the theme. The application
+
| serves as the "glue" for all the components of Laravel and is
+
| the IoC container for the system binding all of the various parts.
+
|
+
*/
+
+
Application::configure()
+
->withProviders([
+
App\Providers\ThemeServiceProvider::class,
+
])
+
->boot();
+
+
/*
+
|--------------------------------------------------------------------------
+
| Register Sage Theme Files
+
|--------------------------------------------------------------------------
+
|
+
| Out of the box, Sage ships with categorically named theme files
+
| containing common functionality and setup to be bootstrapped with your
+
| theme. Simply add (or remove) files from the array below to change what
+
| is registered alongside Sage.
+
|
+
*/
+
+
collect(['setup', 'filters'])
+
->each(function ($file) {
+
if (! locate_template($file = "app/{$file}.php", true, true)) {
+
wp_die(
+
/* translators: %s is replaced with the relative file path */
+
sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file)
+
);
+
}
+
});
+3
wordpress/index.php
···
+
<?php
+
+
echo view(app('sage.view'), app('sage.data'))->render();
+27
wordpress/package.json
···
+
{
+
"name": "Homemade Jam",
+
"private": true,
+
"engines": {
+
"node": ">=20.0.0"
+
},
+
"type": "module",
+
"scripts": {
+
"dev": "vite",
+
"build": "vite build",
+
"translate": "npm run translate:pot && npm run translate:update",
+
"translate:pot": "wp i18n make-pot . ./resources/lang/sage.pot --include=\"theme.json,patterns,app,resources\"",
+
"translate:update": "for file in ./resources/lang/*.po; do wp i18n update-po ./resources/lang/sage.pot $file; done",
+
"translate:compile": "npm run translate:mo && npm run translate:js",
+
"translate:js": "wp i18n make-json ./resources/lang --pretty-print",
+
"translate:mo": "wp i18n make-mo ./resources/lang ./resources/lang"
+
},
+
"devDependencies": {
+
"@roots/vite-plugin": "^1.0.0",
+
"@tailwindcss/vite": "^4.0.0",
+
"laravel-vite-plugin": "^2.0.0",
+
"sass-embedded": "^1.92.0"
+
},
+
"trustedDependencies": [
+
"@tailwindcss/oxide"
+
]
+
}
wordpress/public/.gitkeep

This is a binary file and will not be displayed.

+3
wordpress/resources/css/_partials/_fonts.scss
···
+
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+116
wordpress/resources/css/_partials/_game.scss
···
+
.game {
+
main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
+
h2 {
+
margin: 0;
+
+
a {
+
font-size: .9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
}
+
+
h3 {
+
margin: 0;
+
}
+
+
.blurb {
+
margin: 1em 0;
+
}
+
+
.game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
+
.jamsub {
+
font-size: .8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
}
+
+
.screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
+
.gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
+
a, button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
& > :first-child {
+
grid-area: featured;
+
}
+
}
+
}
+
+
.interaction {
+
grid-area: stuff;
+
}
+
+
.downloads {
+
padding: 20px;
+
+
ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
+
li {
+
margin-bottom: 10px;
+
}
+
}
+
+
.size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
+
.platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
+
.icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
+
.comments {
+
border-top: 1px var(--accent) solid;
+
}
+
}
+52
wordpress/resources/css/_partials/_game_list_item.scss
···
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
+
h3 {
+
margin: 0;
+
font-size: 1.25em;
+
+
a {
+
color: var(--foreground);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.thumb {
+
position: relative;
+
padding-top: 75%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
.authors {
+
font-size: .9em;
+
margin: 5px 0;
+
+
a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.blurb {
+
margin-top: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
}
+192
wordpress/resources/css/_partials/_global.scss
···
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
+
&:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
+
&.web {
+
mask: url(../images/web.svg);
+
}
+
+
&.windows {
+
mask: url(../images/windows.svg);
+
}
+
+
&.macos {
+
mask: url(../images/macos.svg);
+
}
+
+
&.linux {
+
mask: url(../images/linux.svg);
+
}
+
+
&.android {
+
mask: url(../images/android.svg);
+
}
+
+
&.random {
+
mask: url(../images/random.svg);
+
}
+
+
&.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
+
&.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
+
.active & {
+
background-color: var(--accent);
+
}
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
+
body.wide & {
+
max-width: none;
+
margin: 0;
+
}
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
+
h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
+
.hosted {
+
margin: 0;
+
}
+
+
.joined,
+
.entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
+
.count {
+
font-size: 2.25em;
+
display: block;
+
}
+
+
.caption {
+
font-size: .8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
}
+
+
nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
+
ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
+
li {
+
a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
+
&.current,
+
&:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
}
+
}
+
}
+
}
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
+
.submissions & {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
}
+
+
footer {
+
text-align: center;
+
font-size: .8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
+
a {
+
text-decoration: none;
+
}
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0,0,0,.5);
+
}
+83
wordpress/resources/css/_partials/_homepage.scss
···
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
+
.dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
+
.countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
+
.counters {
+
display: flex;
+
align-items: stretch;
+
+
& > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
+
&:last-child {
+
border-right: none;
+
}
+
}
+
+
span {
+
display: block;
+
text-align: center;
+
+
&.num {
+
font-weight: bold;
+
}
+
+
&.caption {
+
font-size: .8em;
+
font-style: italic;
+
}
+
}
+
}
+
}
+
+
.join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
+
.joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
}
+
+
.content {
+
text-align: left;
+
}
+17
wordpress/resources/css/_partials/_posts.scss
···
+
.post-list {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
text-align: left;
+
+
h3 {
+
font-weight: normal;
+
font-size: 1em;
+
+
.date {
+
margin-left: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
}
+106
wordpress/resources/css/_partials/_submissions.scss
···
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
+
#tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
+
button {
+
white-space: pre;
+
}
+
}
+
+
details {
+
margin-bottom: 10px;
+
+
ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
}
+
+
p.label,
+
details summary {
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
+
ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
+
li {
+
button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: .9em;
+
+
img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
+
&.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
}
+
}
+
}
+
+
.afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
+
&.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
}
+
+
.afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
+
.afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: .9em;
+
}
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+13
wordpress/resources/css/_partials/_variables.scss
···
+
/* display variables! skip the images if you don't want them */
+
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
+
--headingfont: 'Knewave', 'Arial Black', sans-serif;
+
--roundedCorners: 0px;
+
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+2
wordpress/resources/css/app.scss
···
+
@source "../views/";
+
@source "../../app/";
+1
wordpress/resources/css/editor.scss
···
+
@import "tailwindcss";
+39
wordpress/resources/css/screenshot.scss
···
+
.screenshots {
+
display: grid;
+
grid-template-columns: repeat(5, 1fr);
+
gap: 10px;
+
margin-top: .5em;
+
}
+
+
.screenshot {
+
width: 100%;
+
padding-top: 100%;
+
border: 1px #DDDDDD solid;
+
border-radius: 2px;
+
background-color: white;
+
position: relative;
+
display: flex;
+
justify-content: center;
+
align-items: center;
+
box-sizing: border-box;
+
+
a {
+
position: absolute;
+
top: 2px;
+
right: 2px;
+
bottom: 2px;
+
left: 2px;
+
display: flex;
+
justify-content: center;
+
align-items: center;
+
}
+
+
img {
+
position: absolute;
+
top: 2px;
+
right: 2px;
+
bottom: 2px;
+
left: 2px;
+
object-fit: cover;
+
}
+
}
wordpress/resources/fonts/.gitkeep

This is a binary file and will not be displayed.

wordpress/resources/images/.gitkeep

This is a binary file and will not be displayed.

wordpress/resources/images/android-chrome-192x192.png

This is a binary file and will not be displayed.

wordpress/resources/images/android-chrome-512x512.png

This is a binary file and will not be displayed.

+1
wordpress/resources/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>
wordpress/resources/images/apple-touch-icon.png

This is a binary file and will not be displayed.

+1
wordpress/resources/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
wordpress/resources/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
wordpress/resources/images/favicon-16x16.png

This is a binary file and will not be displayed.

wordpress/resources/images/favicon-32x32.png

This is a binary file and will not be displayed.

wordpress/resources/images/favicon.ico

This is a binary file and will not be displayed.

+1
wordpress/resources/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
wordpress/resources/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
wordpress/resources/images/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></svg>
+1
wordpress/resources/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
wordpress/resources/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
wordpress/resources/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
wordpress/resources/images/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></svg>
+1
wordpress/resources/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
wordpress/resources/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>
+1
wordpress/resources/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></svg>
+2
wordpress/resources/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};
+
//# sourceMappingURL=afs.modern.js.map
+73
wordpress/resources/js/app.js
···
+
import.meta.glob([
+
'../images/**',
+
'../fonts/**',
+
]);
+
+
const startContent = document.getElementById('startDate') ? document.getElementById('startDate').textContent : null;
+
const startDate = document.getElementById('startDate') ? document.getElementById('startDate').getAttribute('data-raw') : null;
+
const endContent = document.getElementById('endDate') ? document.getElementById('endDate').textContent : null;
+
const endDate = document.getElementById('endDate') ? document.getElementById('endDate').getAttribute('data-raw') : null;
+
+
const numEntries = 0; // fix this later to be dynamic
+
+
// Date formatting stuff. You probably only need to touch locale and time zone.
+
const locale = 'en-US';
+
const timeZone = 'America/Chicago';
+
+
// DON'T EDIT BELOW THIS LINE
+
// unless you know what you're doing.
+
+
const start = new Date(startDate);
+
const end = new Date(endDate);
+
const now = Date.now();
+
+
const dateElt = document.getElementById('dates');
+
+
const daysElt = document.getElementById('days');
+
const hoursElt = document.getElementById('hours');
+
const minutesElt = document.getElementById('minutes');
+
const secondsElt = document.getElementById('seconds');
+
+
const list = document.getElementById('list');
+
+
const dayMult = 24*60*60;
+
const hourMult = 60*60;
+
const minuteMult = 60;
+
+
const countdownTick = () => {
+
const now = Date.now();
+
let diff;
+
if (now < start.getTime()) {
+
// Jam hasn't started yet
+
diff = (start.getTime() - now) / 1000; // get total # of seconds
+
} else if (now < end.getTime()) {
+
// Jam has started but not ended
+
diff = (end.getTime() - now) / 1000;
+
} else {
+
// Jam has ended
+
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'}`
+
}
+
+
if (diff) {
+
const days = Math.floor(diff / dayMult);
+
diff = diff - (days * dayMult);
+
const hours = Math.floor(diff / hourMult);
+
diff = diff - (hours * hourMult);
+
const minutes = Math.floor(diff / minuteMult);
+
diff = diff - (minutes * minuteMult);
+
const seconds = Math.floor(diff);
+
daysElt.textContent = days;
+
hoursElt.textContent = hours;
+
minutesElt.textContent = minutes;
+
secondsElt.textContent = seconds;
+
}
+
}
+
+
if (document.querySelector('.clock')) {
+
countdownTick();
+
if (now < end.getTime()) {
+
setInterval(() => {
+
countdownTick();
+
}, 1000);
+
}
+
}
+5
wordpress/resources/js/editor.js
···
+
import domReady from '@wordpress/dom-ready';
+
+
domReady(() => {
+
//
+
});
+13
wordpress/resources/views/404.blade.php
···
+
@extends('layouts.app')
+
+
@section('content')
+
@include('partials.page-header')
+
+
@if (! have_posts())
+
<x-alert type="warning">
+
{!! __('Sorry, but the page you are trying to view does not exist.', 'sage') !!}
+
</x-alert>
+
+
{!! get_search_form(false) !!}
+
@endif
+
@endsection
wordpress/resources/views/archive.blade.php

This is a binary file and will not be displayed.

+15
wordpress/resources/views/components/alert.blade.php
···
+
@props([
+
'type' => null,
+
'message' => null,
+
])
+
+
@php($class = match ($type) {
+
'success' => 'text-green-50 bg-green-400',
+
'caution' => 'text-yellow-50 bg-yellow-400',
+
'warning' => 'text-red-50 bg-red-400',
+
default => 'text-indigo-50 bg-indigo-400',
+
})
+
+
<div {{ $attributes->merge(['class' => "px-2 py-1 {$class}"]) }}>
+
{!! $message ?? $slot !!}
+
</div>
+16
wordpress/resources/views/forms/search.blade.php
···
+
<form role="search" method="get" class="search-form" action="{{ home_url('/') }}">
+
<label>
+
<span class="sr-only">
+
{{ _x('Search for:', 'label', 'sage') }}
+
</span>
+
+
<input
+
type="search"
+
placeholder="{!! esc_attr_x('Search &hellip;', 'placeholder', 'sage') !!}"
+
value="{{ get_search_query() }}"
+
name="s"
+
>
+
</label>
+
+
<button>{{ _x('Search', 'submit button', 'sage') }}</button>
+
</form>
+23
wordpress/resources/views/index.blade.php
···
+
@extends('layouts.app')
+
+
@section('content')
+
@include('partials.page-header')
+
+
@if (! have_posts())
+
<x-alert type="warning">
+
{!! __('Sorry, no results were found.', 'sage') !!}
+
</x-alert>
+
+
{!! get_search_form(false) !!}
+
@endif
+
+
@while(have_posts()) @php(the_post())
+
@includeFirst(['partials.content-' . get_post_type(), 'partials.content'])
+
@endwhile
+
+
{!! get_the_posts_navigation() !!}
+
@endsection
+
+
@section('sidebar')
+
@include('sections.sidebar')
+
@endsection
+31
wordpress/resources/views/layouts/app.blade.php
···
+
<!doctype html>
+
<html @php(language_attributes())>
+
<head>
+
<meta charset="utf-8">
+
<meta name="viewport" content="width=device-width, initial-scale=1">
+
@php(do_action('get_header'))
+
@php(wp_head())
+
+
@vite(['resources/css/app.scss', 'resources/js/app.js'])
+
</head>
+
+
<body @php(body_class(is_archive() || get_post_type() === 'game' ? 'wide' : ''))>
+
@php(wp_body_open())
+
<a class="sr-only focus:not-sr-only" href="#main">
+
{{ __('Skip to content', 'sage') }}
+
</a>
+
+
<div id="page">
+
@include('sections.header')
+
+
<main id="main" class="main">
+
@yield('content')
+
</main>
+
+
@include('sections.footer')
+
</div>
+
+
@php(do_action('get_footer'))
+
@php(wp_footer())
+
</body>
+
</html>
+8
wordpress/resources/views/page.blade.php
···
+
@extends('layouts.app')
+
+
@section('content')
+
@while(have_posts()) @php(the_post())
+
@include('partials.page-header')
+
@includeFirst(['partials.content-page', 'partials.content'])
+
@endwhile
+
@endsection
+39
wordpress/resources/views/partials/comments.blade.php
···
+
@if (! post_password_required())
+
<section id="comments" class="comments">
+
@if ($responses())
+
<h2>
+
{!! $title !!}
+
</h2>
+
+
<ol class="comment-list">
+
{!! $responses !!}
+
</ol>
+
+
@if ($paginated())
+
<nav aria-label="Comment">
+
<ul class="pager">
+
@if ($previous())
+
<li class="previous">
+
{!! $previous !!}
+
</li>
+
@endif
+
+
@if ($next())
+
<li class="next">
+
{!! $next !!}
+
</li>
+
@endif
+
</ul>
+
</nav>
+
@endif
+
@endif
+
+
@if ($closed())
+
<x-alert type="warning">
+
{!! __('Comments are closed.', 'sage') !!}
+
</x-alert>
+
@endif
+
+
@php(comment_form())
+
</section>
+
@endif
+7
wordpress/resources/views/partials/content-page.blade.php
···
+
@php(the_content())
+
+
@if ($pagination())
+
<nav class="page-nav" aria-label="Page">
+
{!! $pagination !!}
+
</nav>
+
@endif
+15
wordpress/resources/views/partials/content-search.blade.php
···
+
<article @php(post_class())>
+
<header>
+
<h2 class="entry-title">
+
<a href="{{ get_permalink() }}">
+
{!! $title !!}
+
</a>
+
</h2>
+
+
@includeWhen(get_post_type() === 'post', 'partials.entry-meta')
+
</header>
+
+
<div class="entry-summary">
+
@php(the_excerpt())
+
</div>
+
</article>
+26
wordpress/resources/views/partials/content-single-game.blade.php
···
+
<div class="game-header">
+
<p class="jamsub">A jam submission</p>
+
<h2>{!! $title !!} <a href="" target="_blank">View game website &rarr;</a></h2>
+
<div class="blurb">
+
@php(the_excerpt())
+
</div>
+
<div class="authors">
+
Submitted by <a href="#" target="_blank">author</a> at <span class="submissiontime">date</span>
+
</div>
+
</div>
+
<div class="screenshots">
+
<div class="gallery">
+
<button popovertarget="img[index]"><img src="" alt="" /></button>
+
<img src="" alt="" popover id="img[index]" />
+
</div>
+
</div>
+
<div class="interaction">
+
<div class="downloads">
+
@php(the_content())
+
<h3>Downloads</h3>
+
<ul>
+
<li><a href="#" class="btn" download>Download</a> <b>filename</b> <span class="size">size</span> <span class="platforms"><span class="platforms-label">Platforms: </span><span class="icon [platform]" title="[platform]">[platform]</span></li>
+
</ul>
+
</div>
+
@php(comments_template())
+
</div>
+23
wordpress/resources/views/partials/content-single.blade.php
···
+
<article @php(post_class('h-entry'))>
+
<header>
+
<h1 class="p-name">
+
{!! $title !!}
+
</h1>
+
+
@include('partials.entry-meta')
+
</header>
+
+
<div class="e-content">
+
@php(the_content())
+
</div>
+
+
@if ($pagination())
+
<footer>
+
<nav class="page-nav" aria-label="Page">
+
{!! $pagination !!}
+
</nav>
+
</footer>
+
@endif
+
+
@php(comments_template())
+
</article>
+15
wordpress/resources/views/partials/content.blade.php
···
+
<article @php(post_class())>
+
<header>
+
<h2 class="entry-title">
+
<a href="{{ get_permalink() }}">
+
{!! $title !!}
+
</a>
+
</h2>
+
+
@include('partials.entry-meta')
+
</header>
+
+
<div class="entry-summary">
+
@php(the_excerpt())
+
</div>
+
</article>
+10
wordpress/resources/views/partials/entry-meta.blade.php
···
+
<time class="dt-published" datetime="{{ get_post_time('c', true) }}">
+
{{ get_the_date() }}
+
</time>
+
+
<p>
+
<span>{{ __('By', 'sage') }}</span>
+
<a href="{{ get_author_posts_url(get_the_author_meta('ID')) }}" class="p-author h-card">
+
{{ get_the_author() }}
+
</a>
+
</p>
+3
wordpress/resources/views/partials/page-header.blade.php
···
+
<div class="page-header">
+
<h1>{!! $title !!}</h1>
+
</div>
+19
wordpress/resources/views/search.blade.php
···
+
@extends('layouts.app')
+
+
@section('content')
+
@include('partials.page-header')
+
+
@if (! have_posts())
+
<x-alert type="warning">
+
{!! __('Sorry, no results were found.', 'sage') !!}
+
</x-alert>
+
+
{!! get_search_form(false) !!}
+
@endif
+
+
@while(have_posts()) @php(the_post())
+
@include('partials.content-search')
+
@endwhile
+
+
{!! get_the_posts_navigation() !!}
+
@endsection
+3
wordpress/resources/views/sections/footer.blade.php
···
+
<footer class="content-info">
+
<a href="https://veryroundbird.house" target="_blank">♥︎</a>
+
</footer>
+30
wordpress/resources/views/sections/header.blade.php
···
+
<header>
+
<h1>{!! $siteName !!}</h1>
+
<p class="hosted">Hosted by <a href="host link" target="_blank">host name</a> &bull; <a href="hashtag link" target="_blank">#</a></p>
+
@if (is_home())
+
<div class="joined">
+
<span class="count" id="joinedCount">
+
+
</span>
+
<span class="caption">Joined</span>
+
</div>
+
@else
+
@php
+
$entries = get_posts([
+
'post_type' => 'game',
+
'status' => 'published',
+
'posts_per_page' => -1
+
]);
+
$entry_count = count($entries);
+
@endphp
+
<div class="entries">
+
<span class="count" id="entryCount">{{ $entry_count }}</span>
+
<span class="caption">{{ $entry_count !== 1 ? 'Entries' : 'Entry' }}</span>
+
</div>
+
@endif
+
<nav>
+
<ul>
+
<li><a href="#" target="_blank" class="current">title</a></li>
+
</ul>
+
</nav>
+
</header>
+1
wordpress/resources/views/sections/sidebar.blade.php
···
+
@php(dynamic_sidebar('sidebar-primary'))
+7
wordpress/resources/views/single.blade.php
···
+
@extends('layouts.app')
+
+
@section('content')
+
@while(have_posts()) @php(the_post())
+
@includeFirst(['partials.content-single-' . get_post_type(), 'partials.content-single'])
+
@endwhile
+
@endsection
+12
wordpress/resources/views/template-custom.blade.php
···
+
{{--
+
Template Name: Custom Template
+
--}}
+
+
@extends('layouts.app')
+
+
@section('content')
+
@while(have_posts()) @php(the_post())
+
@include('partials.page-header')
+
@include('partials.content-page')
+
@endwhile
+
@endsection
wordpress/screenshot.png

This is a binary file and will not be displayed.

+13
wordpress/style.css
···
+
/*
+
Theme Name: Homemade Jam
+
Theme URI: https://tangled.sh/@veryroundbird.house/homemadejam
+
Description: theme for running your very own game or creative jams
+
Version: 1.0.0
+
Author: Carly Smallbird
+
Author URI: https://veryroundbird.house
+
Text Domain: sage
+
License: MIT License
+
License URI: https://opensource.org/licenses/MIT
+
Requires PHP: 8.2
+
Requires at least: 6.6
+
*/
+37
wordpress/theme.json
···
+
{
+
"__preprocessed__": "This file is used to build the theme.json file in the `public/build/assets` directory. The built artifact includes Tailwind's colors, fonts, and font sizes.",
+
"$schema": "https://schemas.wp.org/trunk/theme.json",
+
"version": 3,
+
"settings": {
+
"layout": {
+
"contentSize": "48rem"
+
},
+
"background": {
+
"backgroundImage": true
+
},
+
"color": {
+
"custom": false,
+
"customDuotone": false,
+
"customGradient": false,
+
"defaultDuotone": false,
+
"defaultGradients": false,
+
"defaultPalette": false,
+
"duotone": []
+
},
+
"custom": {
+
"spacing": {},
+
"typography": {
+
"font-size": {},
+
"line-height": {}
+
}
+
},
+
"spacing": {
+
"padding": true,
+
"units": ["px", "%", "em", "rem", "vw", "vh"]
+
},
+
"typography": {
+
"defaultFontSizes": false,
+
"customFontSize": false
+
}
+
}
+
}
+32
wordpress/vite.config.js
···
+
/* begone tailwind */
+
import { defineConfig } from 'vite'
+
import laravel from 'laravel-vite-plugin'
+
import { wordpressPlugin, wordpressThemeJson } from '@roots/vite-plugin';
+
+
export default defineConfig({
+
base: '/wp-content/themes/homemadejam/',
+
plugins: [
+
laravel({
+
input: [
+
'resources/css/app.scss',
+
'resources/js/app.js',
+
'resources/css/editor.scss',
+
'resources/js/editor.js',
+
'resources/js/afs.modern.js',
+
'resources/css/screenshot.scss'
+
],
+
refresh: true,
+
}),
+
+
wordpressPlugin(),
+
wordpressThemeJson({}),
+
],
+
resolve: {
+
alias: {
+
'@scripts': '/resources/js',
+
'@styles': '/resources/css',
+
'@fonts': '/resources/fonts',
+
'@images': '/resources/images',
+
},
+
},
+
})
+3
zola/sass/_partials/_fonts.scss
···
+
@import url('https://fonts.googleapis.com/css2?family=Knewave&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
/* if you want to use different fonts, you can use other stuff from google fonts
+
if you don't want to use google, you may want to look into hosting your own fonts locally */
+116
zola/sass/_partials/_game.scss
···
+
.game {
+
main {
+
display: grid;
+
grid-template-areas: "header header" "screenshots stuff";
+
text-align: left;
+
border-bottom: 1px var(--accent) solid;
+
padding-bottom: 0;
+
+
h2 {
+
margin: 0;
+
+
a {
+
font-size: .9rem;
+
margin-left: 10px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
}
+
+
h3 {
+
margin: 0;
+
}
+
+
.blurb {
+
margin: 1em 0;
+
}
+
+
.game-header {
+
margin: -20px -20px 0;
+
width: calc(100% + 40px);
+
border-bottom: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: left;
+
grid-area: header;
+
}
+
+
.jamsub {
+
font-size: .8em;
+
font-style: italic;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 15%);
+
margin: 0;
+
}
+
}
+
+
.screenshots {
+
border-right: 1px var(--accent) solid;
+
grid-area: screenshots;
+
padding: 20px;
+
+
.gallery {
+
display: grid;
+
gap: 10px;
+
grid-template-columns: repeat(2, 1fr);
+
grid-template-rows: auto;
+
grid-template-areas: "featured featured";
+
+
a, button {
+
position: relative;
+
padding-top: 75%;
+
width: 100%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
& > :first-child {
+
grid-area: featured;
+
}
+
}
+
}
+
+
.interaction {
+
grid-area: stuff;
+
}
+
+
.downloads {
+
padding: 20px;
+
+
ul {
+
list-style: none;
+
margin: 1em 0;
+
padding: 0;
+
+
li {
+
margin-bottom: 10px;
+
}
+
}
+
+
.size {
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
+
.platforms-label {
+
display: inline-block;
+
width: 1px;
+
overflow: hidden;
+
text-indent: -999px;
+
}
+
+
.icon {
+
width: 24px;
+
height: 24px;
+
background-color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
+
.comments {
+
border-top: 1px var(--accent) solid;
+
}
+
}
+52
zola/sass/_partials/_game_list_item.scss
···
+
.item {
+
text-align: left;
+
border: 1px red solid;
+
+
h3 {
+
margin: 0;
+
font-size: 1.25em;
+
+
a {
+
color: var(--foreground);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.thumb {
+
position: relative;
+
padding-top: 75%;
+
+
img {
+
position: absolute;
+
top: 0;
+
left: 0;
+
width: 100%;
+
height: 100%;
+
object-fit: cover;
+
}
+
}
+
+
.authors {
+
font-size: .9em;
+
margin: 5px 0;
+
+
a {
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
text-decoration: none;
+
+
&:hover {
+
text-decoration: underline;
+
}
+
}
+
}
+
+
.blurb {
+
margin-top: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), #FFFFFF 10%);
+
}
+
}
+192
zola/sass/_partials/_global.scss
···
+
* {
+
box-sizing: border-box;
+
}
+
+
body {
+
background-color: var(--background);
+
background-image: url(--pageBgImage);
+
color: var(--foreground);
+
font-family: var(--mainfont);
+
font-size: 1em;
+
}
+
+
a {
+
color: var(--accent);
+
text-decoration: underline;
+
+
&:hover {
+
color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
+
.icon {
+
width: 16px;
+
height: 16px;
+
text-indent: -999px;
+
overflow: hidden;
+
display: inline-block;
+
vertical-align: middle;
+
margin-right: 5px;
+
background-color: var(--foreground);
+
+
&.web {
+
mask: url(../images/web.svg);
+
}
+
+
&.windows {
+
mask: url(../images/windows.svg);
+
}
+
+
&.macos {
+
mask: url(../images/macos.svg);
+
}
+
+
&.linux {
+
mask: url(../images/linux.svg);
+
}
+
+
&.android {
+
mask: url(../images/android.svg);
+
}
+
+
&.random {
+
mask: url(../images/random.svg);
+
}
+
+
&.sort-asc {
+
mask: url(../images/sort-asc.svg);
+
}
+
+
&.sort-desc {
+
mask: url(../images/sort-desc.svg);
+
}
+
+
.active & {
+
background-color: var(--accent);
+
}
+
}
+
+
.btn {
+
padding: 5px 10px;
+
font-size: 1em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
color: var(--background);
+
}
+
}
+
+
#page {
+
max-width: 960px;
+
margin: 50px auto;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 50%);
+
background-image: var(--contentBgImage);
+
border-radius: var(--roundedCorners);
+
+
body.wide & {
+
max-width: none;
+
margin: 0;
+
}
+
}
+
+
header {
+
padding: 20px 20px 0;
+
position: relative;
+
background-color: color-mix(in srgb-linear, var(--background), #FFFFFF 25%);
+
+
h1 {
+
font-size: 2.5em;
+
font-weight: bold;
+
margin: 0;
+
}
+
+
.hosted {
+
margin: 0;
+
}
+
+
.joined,
+
.entries {
+
text-align: center;
+
position: absolute;
+
top: 20px;
+
right: 20px;
+
+
.count {
+
font-size: 2.25em;
+
display: block;
+
}
+
+
.caption {
+
font-size: .8em;
+
display: block;
+
color: color-mix(in srgb-linear, var(--foreground) #FFFFFF, 25%);
+
}
+
}
+
+
nav {
+
margin-top: 20px;
+
padding-bottom: 10px;
+
+
ul {
+
margin-bottom: 0;
+
display: flex;
+
gap: 10px;
+
list-style: none;
+
padding: 0;
+
+
li {
+
a {
+
text-decoration: none;
+
padding: 5px 0;
+
border-bottom: 5px transparent solid;
+
color: var(--foreground);
+
+
&.current,
+
&:hover {
+
border-bottom: 5px var(--accent) solid;
+
color: var(--foreground);
+
}
+
}
+
}
+
}
+
}
+
}
+
+
main {
+
padding: 20px;
+
text-align: center;
+
+
.submissions & {
+
display: grid;
+
grid-template-areas: "filters list";
+
grid-template-columns: 250px 1fr;
+
}
+
}
+
+
footer {
+
text-align: center;
+
font-size: .8em;
+
padding: 5px 10px;
+
margin-top: 20px;
+
+
a {
+
text-decoration: none;
+
}
+
}
+
+
[popover] {
+
position: fixed;
+
z-index: 99;
+
max-width: 90%;
+
max-height: 90%;
+
}
+
+
[popover]:-internal-popover-in-top-layer::backdrop {
+
background-color: rgba(0,0,0,.5);
+
}
+83
zola/sass/_partials/_homepage.scss
···
+
.clock {
+
border: 1px var(--accent) solid;
+
border-radius: 5px;
+
display: inline-grid;
+
grid-template-areas: "date date" "countdown join";
+
margin: 50px auto;
+
+
.dates {
+
border-bottom: 1px var(--accent) solid;
+
padding: 10px;
+
grid-area: date;
+
text-align: center;
+
}
+
+
.countdown {
+
grid-area: countdown;
+
border-right: 1px var(--accent) solid;
+
padding: 20px;
+
text-align: right;
+
display: flex;
+
align-items: center;
+
justify-content: flex-end;
+
+
.counters {
+
display: flex;
+
align-items: stretch;
+
+
& > div {
+
padding: 10px;
+
border-right: 2px var(--accent) solid;
+
display: flex;
+
flex-direction: column;
+
justify-content: center;
+
align-items: center;
+
white-space: pre;
+
+
&:last-child {
+
border-right: none;
+
}
+
}
+
+
span {
+
display: block;
+
text-align: center;
+
+
&.num {
+
font-weight: bold;
+
}
+
+
&.caption {
+
font-size: .8em;
+
font-style: italic;
+
}
+
}
+
}
+
}
+
+
.join {
+
display: flex;
+
align-items: center;
+
justify-content: flex-start;
+
padding: 20px;
+
}
+
+
.joinbtn {
+
padding: 10px 20px;
+
font-size: 1.25em;
+
font-weight: bold;
+
border-radius: 5px;
+
background-color: var(--accent);
+
color: var(--background);
+
text-decoration: none;
+
white-space: pre;
+
+
&:hover {
+
background-color: color-mix(in srgb-linear, var(--accent), #000000 50%);
+
}
+
}
+
}
+
+
.content {
+
text-align: left;
+
}
+17
zola/sass/_partials/_posts.scss
···
+
.post-list {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
text-align: left;
+
+
h3 {
+
font-weight: normal;
+
font-size: 1em;
+
+
.date {
+
margin-left: 5px;
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 20%);
+
}
+
}
+
}
+106
zola/sass/_partials/_submissions.scss
···
+
#filters {
+
grid-area: filters;
+
text-align: left;
+
+
#tags {
+
display: flex;
+
flex-wrap: wrap;
+
gap: 5px;
+
justify-content: flex-start;
+
+
button {
+
white-space: pre;
+
}
+
}
+
+
details {
+
margin-bottom: 10px;
+
+
ul {
+
list-style: none;
+
margin: 0;
+
padding: 0;
+
}
+
}
+
+
p.label,
+
details summary {
+
font-size: .8em;
+
color: color-mix(in srgb-linear, var(--foreground), var(--background) 10%);
+
padding: 5px 0;
+
margin-bottom: 0;
+
}
+
+
ul#sorts {
+
list-style: none;
+
margin: 0 0 10px;
+
padding: 0;
+
+
li {
+
button {
+
appearance: none;
+
border: none;
+
background-color: transparent;
+
color: var(--foreground);
+
border-radius: 0;
+
font-family: inherit;
+
font-size: inherit;
+
font-size: .9em;
+
+
img {
+
width: 16px;
+
height: 16px;
+
margin-right: 5px;
+
display: inline-block;
+
vertical-align: middle;
+
}
+
+
&.sort-active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
font-weight: bold;
+
}
+
}
+
}
+
}
+
+
.afs-btn-filter {
+
appearance: none;
+
padding: 3px 0;
+
border: none;
+
border-radius: 0;
+
font-family: inherit;
+
background-color: transparent;
+
+
&.active {
+
color: color-mix(in srgb-linear, var(--accent), #000000 10%);
+
background-color: transparent;
+
font-weight: bold;
+
}
+
}
+
+
.afs-filter-search {
+
width: 100%;
+
padding: 0.5rem;
+
border: 1px solid var(--accent);
+
border-radius: 0.25rem;
+
font-size: 0.875rem;
+
color: var(--foreground);
+
transition: border-color 0.2s ease;
+
margin-bottom: 10px;
+
font-family: inherit;
+
}
+
+
.afs-filter-counter {
+
text-align: center;
+
font-style: italic;
+
font-size: .9em;
+
}
+
}
+
+
#list {
+
display: grid;
+
grid-area: list;
+
grid-template-columns: repeat(4, 1fr);
+
grid-template-rows: fit-content(300px);
+
gap: 10px;
+
}
+13
zola/sass/_partials/_variables.scss
···
+
/* display variables! skip the images if you don't want them */
+
+
:root {
+
--background: #ECEBDE;
+
--foreground: #000000;
+
--accent: #A59D84;
+
--mainfont: 'Work Sans', Helvetica, Arial, sans-serif;
+
--headingfont: 'Knewave', 'Arial Black', sans-serif;
+
--roundedCorners: 0px;
+
+
--pageBgImage: url();
+
--contentBgImage: url();
+
}
+7
zola/sass/style.scss
···
+
@use '_partials/_fonts';
+
@use '_partials/_variables';
+
@use '_partials/_global';
+
@use '_partials/_homepage';
+
@use '_partials/_submissions';
+
@use '_partials/_game_list_item';
+
@use '_partials/_game';
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.

+1
zola/static/images/bluesky.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M439.8 358.7C436.5 358.3 433.1 357.9 429.8 357.4C433.2 357.8 436.5 358.3 439.8 358.7zM320 291.1C293.9 240.4 222.9 145.9 156.9 99.3C93.6 54.6 69.5 62.3 53.6 69.5C35.3 77.8 32 105.9 32 122.4C32 138.9 41.1 258 47 277.9C66.5 343.6 136.1 365.8 200.2 358.6C203.5 358.1 206.8 357.7 210.2 357.2C206.9 357.7 203.6 358.2 200.2 358.6C106.3 372.6 22.9 406.8 132.3 528.5C252.6 653.1 297.1 501.8 320 425.1C342.9 501.8 369.2 647.6 505.6 528.5C608 425.1 533.7 372.5 439.8 358.6C436.5 358.2 433.1 357.8 429.8 357.3C433.2 357.7 436.5 358.2 439.8 358.6C503.9 365.7 573.4 343.5 593 277.9C598.9 258 608 139 608 122.4C608 105.8 604.7 77.7 586.4 69.5C570.6 62.4 546.4 54.6 483.2 99.3C417.1 145.9 346.1 240.4 320 291.1z"/></svg>
+1
zola/static/images/facebook.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 440 146.7 540.8 258.2 568.5L258.2 398.2L205.4 398.2L205.4 320L258.2 320L258.2 286.3C258.2 199.2 297.6 158.8 383.2 158.8C399.4 158.8 427.4 162 438.9 165.2L438.9 236C432.9 235.4 422.4 235 409.3 235C367.3 235 351.1 250.9 351.1 292.2L351.1 320L434.7 320L420.3 398.2L351 398.2L351 574.1C477.8 558.8 576 450.9 576 320z"/></svg>
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/mastodon.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M529 243.1C529 145.9 465.3 117.4 465.3 117.4C402.8 88.7 236.7 89 174.8 117.4C174.8 117.4 111.1 145.9 111.1 243.1C111.1 358.8 104.5 502.5 216.7 532.2C257.2 542.9 292 545.2 320 543.6C370.8 540.8 399.3 525.5 399.3 525.5L397.6 488.6C397.6 488.6 361.3 500 320.5 498.7C280.1 497.3 237.5 494.3 230.9 444.7C230.3 440.1 230 435.4 230 430.8C315.6 451.7 388.7 439.9 408.7 437.5C464.8 430.8 513.7 396.2 519.9 364.6C529.7 314.8 528.9 243.1 528.9 243.1zM453.9 368.3L407.3 368.3L407.3 254.1C407.3 204.4 343.3 202.5 343.3 261L343.3 323.5L297 323.5L297 261C297 202.5 233 204.4 233 254.1L233 368.3L186.3 368.3C186.3 246.2 181.1 220.4 204.7 193.3C230.6 164.4 284.5 162.5 308.5 199.4L320.1 218.9L331.7 199.4C355.8 162.3 409.8 164.6 435.5 193.3C459.2 220.6 453.9 246.3 453.9 368.3L453.9 368.3z"/></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/twitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M523.4 215.7C523.7 220.2 523.7 224.8 523.7 229.3C523.7 368 418.1 527.9 225.1 527.9C165.6 527.9 110.4 510.7 64 480.8C72.4 481.8 80.6 482.1 89.3 482.1C138.4 482.1 183.5 465.5 219.6 437.3C173.5 436.3 134.8 406.1 121.5 364.5C128 365.5 134.5 366.1 141.3 366.1C150.7 366.1 160.1 364.8 168.9 362.5C120.8 352.8 84.8 310.5 84.8 259.5L84.8 258.2C98.8 266 115 270.9 132.2 271.5C103.9 252.7 85.4 220.5 85.4 184.1C85.4 164.6 90.6 146.7 99.7 131.1C151.4 194.8 229 236.4 316.1 240.9C314.5 233.1 313.5 225 313.5 216.9C313.5 159.1 360.3 112 418.4 112C448.6 112 475.9 124.7 495.1 145.1C518.8 140.6 541.6 131.8 561.7 119.8C553.9 144.2 537.3 164.6 515.6 177.6C536.7 175.3 557.2 169.5 576 161.4C561.7 182.2 543.8 200.7 523.4 215.7z"/></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>
+1
zola/static/images/xtwitter.svg
···
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.0.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M453.2 112L523.8 112L369.6 288.2L551 528L409 528L297.7 382.6L170.5 528L99.8 528L264.7 339.5L90.8 112L236.4 112L336.9 244.9L453.2 112zM428.4 485.8L467.5 485.8L215.1 152L173.1 152L428.4 485.8z"/></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};
+
//# sourceMappingURL=afs.modern.js.map
+68
zola/static/js/script.mjs
···
+
const startContent = document.getElementById('startDate') ? document.getElementById('startDate').textContent : null;
+
const startDate = document.getElementById('startDate') ? document.getElementById('startDate').getAttribute('data-raw') : null;
+
const endContent = document.getElementById('endDate') ? document.getElementById('endDate').textContent : null;
+
const endDate = document.getElementById('endDate') ? document.getElementById('endDate').getAttribute('data-raw') : null;
+
+
const numEntries = 0; // fix this later to be dynamic
+
+
// Date formatting stuff. You probably only need to touch locale and time zone.
+
const locale = 'en-US';
+
const timeZone = 'America/Chicago';
+
+
// DON'T EDIT BELOW THIS LINE
+
// unless you know what you're doing.
+
+
const start = new Date(startDate);
+
const end = new Date(endDate);
+
const now = Date.now();
+
+
const dateElt = document.getElementById('dates');
+
+
const daysElt = document.getElementById('days');
+
const hoursElt = document.getElementById('hours');
+
const minutesElt = document.getElementById('minutes');
+
const secondsElt = document.getElementById('seconds');
+
+
const list = document.getElementById('list');
+
+
const dayMult = 24*60*60;
+
const hourMult = 60*60;
+
const minuteMult = 60;
+
+
const countdownTick = () => {
+
const now = Date.now();
+
let diff;
+
if (now < start.getTime()) {
+
// Jam hasn't started yet
+
diff = (start.getTime() - now) / 1000; // get total # of seconds
+
} else if (now < end.getTime()) {
+
// Jam has started but not ended
+
diff = (end.getTime() - now) / 1000;
+
} else {
+
// Jam has ended
+
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'}`
+
}
+
+
if (diff) {
+
const days = Math.floor(diff / dayMult);
+
diff = diff - (days * dayMult);
+
const hours = Math.floor(diff / hourMult);
+
diff = diff - (hours * hourMult);
+
const minutes = Math.floor(diff / minuteMult);
+
diff = diff - (minutes * minuteMult);
+
const seconds = Math.floor(diff);
+
daysElt.textContent = days;
+
hoursElt.textContent = hours;
+
minutesElt.textContent = minutes;
+
secondsElt.textContent = seconds;
+
}
+
}
+
+
if (document.querySelector('.clock')) {
+
countdownTick();
+
if (now < end.getTime()) {
+
setInterval(() => {
+
countdownTick();
+
}, 1000);
+
}
+
}
+160
zola/templates/games/section.html
···
+
{% extends "index.html" %}
+
+
{% block body_classes %}wide submissions{% endblock %}
+
+
{% block main_content %}
+
{{ section.content | safe }}
+
<aside id="filters">
+
<div class="afs-filter-container">
+
<!-- Filter Controls -->
+
<div class="afs-filter-controls">
+
<!-- Basic Filters -->
+
+
<!-- Search Input -->
+
<input type="text" class="afs-filter-search" placeholder="Search by title, author, or tags" />
+
+
<p class="label">Sort entries by:</p>
+
<ul id="sorts">
+
<li><button class="custom-sort" data-sort-key="date" data-sort-direction="desc"> <span class="afs-sort-direction"><span class="icon sort-desc"></span></span> Date</button></li>
+
<li><button class="custom-sort" data-sort-key="title" data-sort-direction="asc"> <span class="afs-sort-direction"><span class="icon sort-asc"></span></span> Title</button></li>
+
<li><button class="custom-sort" data-sort-key="shuffle" data-sort-direction="desc"><span class="icon random"></span></span> Random</button></li>
+
</ul>
+
+
<details open><summary>Platform</summary>
+
<ul>
+
<li><button class="afs-btn-filter" data-filter="platforms:browser"><span class="icon web"></span> Play in browser</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:windows"><span class="icon windows"></span> Windows</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:macos"><span class="icon macos"></span> Mac OS</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:linux"><span class="icon linux"></span> Linux</button></li>
+
<li><button class="afs-btn-filter" data-filter="platforms:android"><span class="icon android"></span> Android</button></li>
+
</ul>
+
</details>
+
+
<details><summary>Tags</summary>
+
<div id="tags">
+
{% set tax = get_taxonomy(kind="games/tags") %}
+
<button class="afs-btn-filter" data-filter="*">all</button>
+
{% for tag in tax.items %}
+
<button class="afs-btn-filter" data-filter="tags:{{ tag.name }}">#{{ tag.name }}</button>
+
{% endfor %}
+
</div>
+
</details>
+
+
<details><summary>Submission Date</summary>
+
<div id="date-filter"></div>
+
</details>
+
+
<!-- Results Counter -->
+
<div class="afs-filter-counter"></div>
+
</div>
+
+
<!-- Pagination Container -->
+
<div class="afs-pagination-container"></div>
+
</div>
+
</aside>
+
<section id="list">
+
{{ post_macros::game_cards(section=section) }}
+
</section>
+
<script type="module">
+
import { AFS } from './js/afs.modern.js';
+
const afs = new AFS({
+
// Required Selectors
+
containerSelector: '#list',
+
itemSelector: '.item',
+
+
// CSS Classes
+
activeClass: 'active',
+
hiddenClass: 'hidden',
+
transitionClass: 'afs-transition',
+
searchKeys: ['title', 'authors', 'tags'],
+
debounceTime: 200, // search input delay
+
+
// Date Handling
+
dateFormat: 'YYYY-MM-DD',
+
dateFilter: {
+
enabled: true,
+
format: 'YYYY-MM-DDThh:mm:ss'
+
},
+
+
// Counter Configuration
+
counter: {
+
template: 'Showing {visible} of {total}',
+
showFiltered: true,
+
filteredTemplate: '({filtered} filtered)',
+
noResultsTemplate: 'No items found',
+
formatter: (num) => num.toLocaleString()
+
},
+
+
sort: {
+
enabled: true,
+
buttonSelector: '.afs-btn-sort'
+
},
+
+
// Animation Configuration
+
animation: {
+
type: 'fade',
+
duration: 200,
+
easing: 'ease-out',
+
inClass: 'afs-animation-enter',
+
outClass: 'afs-animation-leave'
+
},
+
+
// Lifecycle Options
+
responsive: true,
+
preserveState: false,
+
stateExpiry: 86400000, // 24 hours
+
observeDOM: false,
+
+
// Style Configuration
+
styles: {
+
colors: {
+
primary: '#000',
+
background: '#e5e7eb',
+
text: '#000',
+
textHover: '#fff'
+
}
+
}
+
});
+
+
// add date range filter
+
afs.dateFilter.addDateRange({
+
key: 'date',
+
container: document.querySelector('#date-filter'),
+
format: 'YYYY-MM-DD',
+
minDate: new Date("{{ config.extra.start_date }}".match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0]),
+
maxDate: new Date("{{ config.extra.end_date }}".match(/[0-9]{4}-[0-9]{2}-[0-9]{2}/)[0])
+
});
+
+
// fixes some behavior of the sort buttons
+
document.querySelectorAll('button.custom-sort:not([data-sort-key="shuffle"])').forEach((elt) => {
+
elt.addEventListener('click', (e) => {
+
e.preventDefault();
+
e.stopPropagation();
+
const btn = e.target.closest('button');
+
document.querySelectorAll('button.custom-sort:not([data-sort-key="'+btn.getAttribute('data-sort-key')+'"])').forEach((s) => {
+
s.classList.remove('sort-active');
+
});
+
if (btn.classList.contains('sort-active')) {
+
if (btn.getAttribute('data-sort-direction') === 'asc') {
+
btn.setAttribute('data-sort-direction', 'desc');
+
btn.querySelector('.icon').classList.remove('sort-asc');
+
btn.querySelector('.icon').classList.add('sort-desc');
+
} else {
+
btn.setAttribute('data-sort-direction', 'asc');
+
btn.querySelector('.icon').classList.remove('sort-desc');
+
btn.querySelector('.icon').classList.add('sort-asc');
+
}
+
afs.sort.sort(btn.getAttribute('data-sort-key'), btn.getAttribute('data-sort-direction'));
+
} else {
+
btn.classList.add('sort-active');
+
afs.sort.sort(btn.getAttribute('data-sort-key'), btn.getAttribute('data-sort-direction'));
+
}
+
});
+
});
+
+
// random sort button
+
document.querySelector('[data-sort-key="shuffle"]').addEventListener('click', (e) => {
+
afs.sort.shuffle();
+
});
+
</script>
+
{% endblock main_content %}
+12
zola/templates/games/tags/list.html
···
+
{% extends "index.html" %}
+
+
{% block main_content %}
+
<h2><a href="/games">games</a>: tags</h2>
+
<section id="games">
+
<ul>
+
{% for term in terms %}
+
<li><a href="{{ get_taxonomy_url(kind='games/tags', name=term.name) }}">{{ term.name }}</a></li>
+
{% endfor %}
+
</ul>
+
</section>
+
{% endblock main_content %}
+8
zola/templates/games/tags/single.html
···
+
{% extends "index.html" %}
+
+
{% block main_content %}
+
<h2><a href="/games">games</a>: {{ term.name }}</h2>
+
<section id="games">
+
{{ post_macros::plain_post_list(pages=term.pages) }}
+
</section>
+
{% endblock main_content %}
+36
zola/templates/index.html
···
+
{% import "macros/macros.html" as post_macros %}
+
+
<!DOCTYPE html>
+
<html lang="{{lang}}">
+
{% include "partials/head.html" %}
+
<body class="{% block body_classes %}{% endblock body_classes %}">
+
{% include "partials/banner.html" %}
+
<div id="page">
+
{% include "partials/header.html" %}
+
<main>
+
{% block main_content %}
+
<div class="clock">
+
<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="countdown">
+
<div class="counters">
+
<div class="verb">Starts in</div>
+
<div class="days"><span class="num" id="days">#</span><span class="caption">days</span></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>
+
</div>
+
</div>
+
<div class="join">
+
<a href="{{ config.extra.join_link }}" class="joinbtn">Join Jam</a>
+
</div>
+
</div>
+
<div class="content">
+
{% set page = get_section(path="_index.md") %}
+
{{ page.content | safe }}
+
</div>
+
{% endblock main_content %}
+
</main>
+
{% include "partials/footer.html" %}
+
</div>
+
</body>
+
</html>
+144
zola/templates/macros/macros.html
···
+
{% macro get_airtable_joined_count(offset, count=0) %}
+
{% set base_url = "https://api.airtable.com/v0/" ~ config.extra.joined_airtable_base_id ~ "/" ~ config.extra.joined_airtable_table_name %}
+
{% if offset and not offset == 'first' %}
+
{% set base_url = base_url ~ "?offset=" ~ offset %}
+
{% endif %}
+
{% set headers = "Authorization=Bearer " ~ config.extra.joined_airtable_token %}
+
{% set data = load_data(url=base_url, method="GET", headers=[headers], format="json") %}
+
{% if data %}
+
{% set record_length = data.records | length %}
+
{% if data.offset %}
+
{{ get_airtable_joined_count(offset=data.offset, count=count+record_length) }}
+
{% else %}
+
{{ count + record_length }}
+
{% endif %}
+
{% endif %}
+
{% endmacro %}
+
+
{% macro plain_post_list(pages) %}
+
<ol class="post-list">
+
{% for post in pages | reverse %}
+
<li>
+
<h3><a href={{ post.permalink }}><span class="title">{{ post.title }}</span></a> <span class="date">{{ post.date | date(format="%h %e, %Y") }}</span></h3>
+
<div class="summary">
+
{{ post.summary | safe }}
+
</div>
+
{% if section.extra.tag_tax %}
+
{% set tax = section.extra.tag_tax %}
+
<span class="tags">
+
{% for tag in post.taxonomies[tax] %}
+
<a href="{{ get_taxonomy_url(kind=tax, name=tag) }}">{{ tag }}</a>
+
{% endfor %}
+
</span>
+
{% endif %}
+
</li>
+
{% endfor %}
+
</ol>
+
{% endmacro %}
+
+
{% macro game_cards(section) %}
+
{%- for page in section.pages %}
+
{%- if page.draft %}
+
{% continue %}
+
{% endif -%}
+
{% set_global tags_data = [] %}
+
{% for tag in page.taxonomies["games/tags"] %}
+
{% set tag_full = "tags:" ~ tag %}
+
{% set_global tags_data = tags_data | concat(with=tag_full) %}
+
{% endfor %}
+
{% set_global platforms_data = [] %}
+
{% for p in page.taxonomies["games/platforms"] %}
+
{% set p_full = "platforms:" ~ p %}
+
{% set_global platforms_data = platforms_data | concat(with=p_full) %}
+
{% endfor %}
+
<article class="item" data-date="{{ page.date }}" data-categories="{{ tags_data | join(sep="") }} {{ platforms_data | join(sep=" " ) }}" data-title="{{ page.title }}" data-authors="{% if page.authors %}{{ page.authors | join(sep=", ") }}{% endif %}">
+
<div class="thumb">
+
{% set img_path = page.components | join(sep="/") %}
+
{% set img_path = img_path ~ "/" %}
+
{% set img_path = img_path ~ page.extra.thumbnail %}
+
{% set resized_image = resize_image(path=img_path, width=480, height=480, op="fit") %}
+
<a href="{{ page.permalink }}"><img src="{{ resized_image.url }}" alt="{{ page.title }} thumbnail image" class="thumb-img" /></a>
+
<div class="platform-icons">
+
{% for p in page.taxonomies["games/platforms"] %}
+
<span class="icon {{ p }}" title="{{ p }}">{{ p }}</span>
+
{% endfor %}
+
</div>
+
</div>
+
<h3><a href="{{ page.permalink }}">{{ page.title }}</a></h3>
+
<div class="authors">
+
{% if page.extra.authors %}
+
{% for author in page.extra.authors %}
+
{% if author.link != "" %}
+
<a href="{{ author.link }}" target="_blank">{{ author.name }}</a>
+
{% else %}
+
{{ author }}
+
{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}
+
{% else %}
+
Anonymous
+
{% endif %}
+
</div>
+
</article>
+
{% endfor %}
+
{% endmacro %}
+
+
{% macro content(page, extra, taxonomy=false) %}
+
<article>
+
<h2 class="title">{% if taxonomy %}{{ taxonomy.name }}{% else %}{{ page.title }}{% endif %}</h2>
+
<div class="meta">
+
{% if page.extra.author %}
+
Posted by <a href="{{ page.extra.author.social }}" target="_blank">{{ page.extra.author.name }}</a>
+
{% endif %}
+
{% if page.date %}
+
Posted on {{ page.date | date(format="%Y-%m-%d") }}
+
{% endif %}
+
+
{% if page.draft %}
+
<span class="draft-label">DRAFT</span>
+
{% endif %}
+
</div>
+
+
{% if page.extra.subnav %}
+
<ul id="subnav">
+
{% for subpage in page.extra.subnav %}
+
<li>
+
<a href="{{subpage.link}}"{% if subpage.target and subpage.target == '_blank' %} target="_blank"{% endif %}>
+
{% if subpage.img %}
+
<img src="{{subpage.img}}" alt="{{subpage.label}}" />
+
{% else %}
+
{{subpage.label}}
+
{% endif %}
+
</a>
+
</li>
+
{% endfor %}
+
</ul>
+
{% endif %}
+
+
{% if page.extra.tldr %}
+
<div class="tldr">
+
<strong>tl;dr:</strong>
+
{{ page.extra.tldr }}
+
</div>
+
{% endif %}
+
+
<div class="content">
+
{{ page.content | safe }}
+
</div>
+
+
{% if page.taxonomies and page.taxonomies.tags %}
+
<div class="post-tags">
+
<nav class="nav tags">
+
<ul class="tags">
+
{% for tag in page.taxonomies.tags %}
+
<li><a href={{ get_taxonomy_url(kind='tags', name=tag) | safe }}>{{ tag }}</a></li>
+
{% endfor %}
+
</ul>
+
</nav>
+
</div>
+
{% endif %}
+
{% if page.extra.scripts %}
+
{% for script in page.extra.scripts %}
+
<script src="{{script}}" type="text/javascript"></script>
+
{% endfor %}
+
{% endif %}
+
</article>
+
{% endmacro content %}
+64
zola/templates/page.html
···
+
{% extends "index.html" %}
+
{% block body_classes %}wide game{% endblock %}
+
{% block main_content %}
+
{% if 'games/_index.md' in page.ancestors %}
+
<div class="game-header">
+
<p class="jamsub">A jam submission</p>
+
<h2>{{ page.title }} {% if page.extra.website_link %}<a href="{{ page.extra.website_link }}" target="_blank">View game website &rarr;</a>{% endif %}</h2>
+
<div class="blurb">
+
{{ page.description }}
+
</div>
+
<div class="authors">
+
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>
+
</div>
+
</div>
+
<div class="screenshots">
+
<div class="gallery">
+
{% if page.extra.screenshots %}
+
{% for screenshot in page.extra.screenshots %}
+
<button popovertarget="img{{ loop.index }}"><img src="{{ screenshot.url }}" alt="{{ screenshot.alt }}" /></button>
+
<img src="{{ screenshot.url }}" alt="{{ screenshot.alt }}" popover id="img{{ loop.index }}" />
+
{% endfor %}
+
{% endif %}
+
</div>
+
</div>
+
<div class="interaction">
+
<div class="downloads">
+
{{ page.content | safe }}
+
{% if page.extra.downloads %}
+
<h3>Downloads</h3>
+
<ul>
+
{% for dl in page.extra.downloads %}
+
<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>
+
{% endfor %}
+
</ul>
+
{% endif %}
+
</div>
+
<!-- uncomment if you want to drop in some kind of commenting system and put in whatever script you're using -->
+
<!--<div class="comments">
+
put comment code here
+
</div>-->
+
</div>
+
{% else %}
+
<div class="content">
+
<h2>{{ page.title }}</h2>
+
{% if page.date %}
+
<p class="meta">{% if config.extra.tinylytics_script_id and config.extra.use_tinylytics_kudos %}<button class="tinylytics_kudos"></button> {% endif %}{{ page.date | date(format="%B %d, %Y at %l:%m%P") }}</p>
+
<div class="sharelinks">
+
+
</div>
+
{% endif %}
+
{{ page.content | safe }}
+
{% if page.taxonomies %}
+
<p class="tags"><b>Tags:</b>
+
{% if page.taxonomies["tags"] %}
+
{% for tag in page.taxonomies["tags"] %}
+
<a href="{{ get_taxonomy_url(kind='tags', name=tag) }}">{{ tag }}</a>
+
{% endfor %}
+
{% endif %}
+
</p>
+
{% endif %}
+
<br />
+
</div>
+
{% endif %}
+
{% endblock main_content %}
+4
zola/templates/partials/banner.html
···
+
<div id="banner">
+
<!-- uncomment the below line if banner is desired -->
+
<!-- <img src="!!YOURBANNER!!" alt="!!BANNERALT!!" /> -->
+
</div>
+11
zola/templates/partials/footer.html
···
+
<footer>
+
<a href="https://veryroundbird.house" target="_blank">♥︎</a>
+
</footer>
+
<script type="module" src="{{ config.base_url }}/js/script.mjs"></script>
+
{% if config.extra.goatcounter_id %}
+
<script data-goatcounter="https://{{ config.extra.goatcounter_id }}.goatcounter.com/count"
+
async src="//gc.zgo.at/count.js"></script>
+
{% endif %}
+
{% if config.extra.tinylytics_script_id %}
+
<script src="https://tinylytics.app/embed/{{ config.extra.tinylytics_script_id }}.js{% if config.extra.use_tinylytics_kudos %}?kudos={% if config.extra.tinylytics_kudos_emoji %}{{ config.extra.tinylytics_kudos_emoji }}{% else %}💖{% endif %}{% endif %}" defer></script>
+
{% endif %}
+86
zola/templates/partials/head.html
···
+
{% import "macros/macros.html" as post_macros %}
+
+
<head>
+
<meta charset="UTF-8">
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
+
{% if page.extra.meta %}
+
<!-- the meta data config goes here -->
+
{% for data in page.extra.meta %}
+
<meta
+
{% for key, value in data%}
+
{% if key == "property" and value == "og:title"%}
+
{% set_global page_has_og_title = true -%}
+
{% endif %}
+
{% if key == "property" and value == "og:description"%}
+
{% set_global page_has_og_description = true -%}
+
{% endif %}
+
{% if key == "name" and value == "description"%}
+
{% set_global page_has_description = true -%}
+
{% endif %}
+
{{ key }}="{{ value }}"
+
{% endfor %}
+
/>
+
{% endfor %}
+
{% endif %}
+
+
{% if current_path == "/" %}
+
<title>
+
{{ config.title }}
+
</title>
+
{% if not page_has_og_title %}
+
<meta property="og:title" content="{{ config.title }}" />
+
{% endif %}
+
{% else %}
+
<title>
+
{{ config.title }} > {% if page.title %} {{ page.title | lower }}
+
{% elif section.title %} {{ section.title | lower }}
+
{% else %} post {% endif %}
+
</title>
+
+
{% if not page_has_og_title %}
+
<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 -%}" />
+
{% endif %}
+
{% endif %}
+
+
{% if not page_has_og_description %}
+
{% if page.description %}
+
<meta property="og:description" content="{{ page.description }}" />
+
{% elif section.description %}
+
<meta property="og:description" content="{{ section.description }}" />
+
{% elif config.description %}
+
<meta property="og:description" content="{{ config.description }}" />
+
{% endif %}
+
{% endif %}
+
+
{% if not page_has_description %}
+
{% if page.description %}
+
<meta name="description" content="{{ page.description }}" />
+
{% elif section.description %}
+
<meta name="description" content="{{ section.description }}" />
+
{% elif config.description %}
+
<meta name="description" content="{{ config.description }}" />
+
{% endif %}
+
{% endif %}
+
+
{% if config.extra.favicon %}
+
<link rel="icon" type="image/png" sizes="16x16" href={{ config.extra.favicon }}>
+
{% endif %}
+
+
{% if config.extra.favicon32 %}
+
<link rel="icon" type="image/png" sizes="32x32" href={{ config.extra.favicon32 }}>
+
{% endif %}
+
+
{% if config.extra.appletouch %}
+
<link rel="apple-touch-icon" sizes="180x180" href={{ config.extra.appletouch }}>
+
{% endif %}
+
+
{% if config.extra.webmanifest %}
+
<link rel="manifest" href="{{ config.base_url }}/site.webmanifest">
+
{% endif %}
+
+
{# opengraph, twitter_cards #}
+
+
<link rel="stylesheet" type="text/css" media="screen" href="{{ config.base_url }}/style.css" />
+
</head>
+45
zola/templates/partials/header.html
···
+
<header>
+
<h1>{{ config.title | safe }}</h1>
+
<p class="hosted">Hosted by <a href="{{ config.extra.host_link }}" target="_blank">{{ config.extra.host_name }}</a> &bull; {% if config.extra.jam_hashtag != "" %}<a href="{{ config.extra.jam_hashtag_link }}" target="_blank">#{{ config.extra.jam_hashtag }}</a>{% endif %}</p>
+
{% if section and section.components | length == 0 %}
+
<div class="joined">
+
<span class="count" id="joinedCount">
+
{% if config.extra.joined_count_source == "manual" %}
+
{{ config.extra.joined_count }}
+
{% elif config.extra.joined_count_source == "airtable" %}
+
{{ post_macros::get_airtable_joined_count(offset="first", count=0) }}
+
{% elif config.extra.joined_count_source == "gsheets" %}
+
{% set gsheet_path = "https://docs.google.com/spreadsheets/d/" ~ config.extra.joined_google_sheet_id ~ "/gviz/tq?" %}
+
{% set raw_data = load_data(url=gsheet_path) | trim_start_matches(pat="/*O_o*/\ngoogle.visualization.Query.setResponse(") | trim_end_matches(pat=");") %}
+
{% set data = load_data(literal=raw_data, format="json") %}
+
{{ data.table.rows | length }}
+
{% elif config.extra.joined_count_source == "csv" %}
+
{% set data = load_data(path=config.extra.joined_csv_data_source, format="csv") %}
+
{{ data | length - 1 }}
+
{% elif config.extra.joined_count_source == "json" %}
+
{% set data = load_data(path=config.extra.joined_json_data_source, format="json") %}
+
{{ data | length }}
+
{% endif %}
+
</span>
+
<span class="caption">Joined</span>
+
</div>
+
{% else %}
+
{% set games = get_section(path="games/_index.md") %}
+
<div class="entries">
+
<span class="count" id="entryCount">{{ games.pages | length }}</span>
+
<span class="caption">Entries</span>
+
</div>
+
{% endif %}
+
<nav>
+
<ul>
+
{% for link in config.extra.navmenu %}
+
{% if link.path and link.path != "/" %}
+
{% set link_full = link.path ~ "/" %}
+
{% elif link.path %}
+
{% set link_full = "/" %}
+
{% endif %}
+
<li><a href="{% if not link.external_link %}{{ config.base_url }}{{ link.path }}{% else %}{{ link.external_url }}{% endif %}"{% if 'newwin' in link and link.newwin == true %} target="_blank"{% endif %}{% if link.path and current_path == link_full %} class="current"{% endif %}>{{ link.name }}</a></li>
+
{% endfor %}
+
</ul>
+
</nav>
+
</header>
zola/templates/posts.html

This is a binary file and will not be displayed.

+27
zola/templates/resources/section.html
···
+
{% extends "index.html" %}
+
+
{% block main_content %}
+
<h2>{{ section.title }}</h2>
+
{{ section.content | safe }}
+
<section id={{ section.title | lower | replace(from=" ", to="-") }}>
+
{% set tax = get_taxonomy(kind="resources/tags") %}
+
{% for term in tax.items %}
+
<h3>{{ term.name }}</h3>
+
<ol class="post-list">
+
{% for post in term.pages %}
+
<li>
+
<a href={{ post.permalink }}><span class="date">{{ post.date }} /</span> <span class="title">{{ post.title }}</span></a>
+
{% if section.extra.tag_tax %}
+
{% set tax = section.extra.tag_tax %}
+
<span class="tags">
+
{% for tag in post.taxonomies[tax] %}
+
<a href="{{ get_taxonomy_url(kind=tax, name=tag) }}">{{ tag }}</a>
+
{% endfor %}
+
</span>
+
{% endif %}
+
</li>
+
{% endfor %}
+
</ol>
+
{% endfor %}
+
</section>
+
{% endblock main_content %}
+9
zola/templates/section.html
···
+
{% extends "index.html" %}
+
+
{% block main_content %}
+
<h2>{{ section.title }}</h2>
+
{{ section.content | safe }}
+
<section id={{ section.title | slugify }}>
+
{{ post_macros::plain_post_list(pages=section.pages) }}
+
</section>
+
{% endblock main_content %}
+16
zola/templates/shortcodes/gallery.html
···
+
<div class="gallery">
+
{% set gallength = page.extra.gallery | length %}
+
{% for asset in page.extra.gallery -%}
+
<div id="gal-{{ loop.index }}" class="gallery-item">
+
{% if gallength > 1 %}
+
<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>
+
{% endif %}
+
<a href="{{ asset }}" target="_blank">
+
<img src="{{ config.extra.cdn_prefix }}{{ asset }}" />
+
</a>
+
{% if gallength > 1 %}
+
<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>
+
{% endif %}
+
</div>
+
{%- endfor %}
+
</div>
+9
zola/templates/shortcodes/links.html
···
+
{% if page.extra.links %}
+
<div class="links">
+
<ul>
+
{% for link in page.extra.links %}
+
<li><a href="{{ link.url }}" target="_blank">{{ link.name }}</a></li>
+
{% endfor %}
+
</ul>
+
</div>
+
{% endif %}
+12
zola/templates/taxonomy_list.html
···
+
{% extends "index.html" %}
+
+
{% block main_content %}
+
<h2>{{ taxonomy.name }}</h2>
+
<section>
+
<ul>
+
{% for term in terms %}
+
<li><a href="{{ get_taxonomy_url(kind=taxonomy.name, name=term.name) }}">{{ term.name }}</a></li>
+
{% endfor %}
+
</ul>
+
</section>
+
{% endblock main_content %}
+22
zola/templates/taxonomy_single.html
···
+
{% extends "index.html" %}
+
+
{% block main_content %}
+
<h2>#{{ term.name }}</h2>
+
<section>
+
<ol class="post-list">
+
{% for post in term.pages %}
+
<li>
+
<a href={{ post.permalink }}><span class="date">{{ post.date }} /</span> <span class="title">{{ post.title }}</span></a>
+
{% if section.extra.tag_tax %}
+
{% set tax = section.extra.tag_tax %}
+
<span class="tags">
+
{% for tag in post.taxonomies[tax] %}
+
<a href="{{ get_taxonomy_url(kind=tax, name=tag) }}">{{ tag }}</a>
+
{% endfor %}
+
</span>
+
{% endif %}
+
</li>
+
{% endfor %}
+
</ol>
+
</section>
+
{% endblock main_content %}
+80
zola/theme.toml
···
+
name = "homemade jam"
+
description = "scaffolding for game or other creative jams"
+
license = "idk"
+
homepage = "https://tangled.sh/@veryroundbird/homemadejam"
+
# The minimum version of Zola required
+
min_version = "0.20.0"
+
demo = ""
+
compile_sass = true
+
generate_feeds = true
+
+
taxonomies = [
+
{ name = "tags" },
+
{ name = "games/tags", render = false },
+
{ name = "games/platforms", render = false }
+
]
+
+
# override this in your `config.toml`
+
title = "!! YOUR GAME JAM NAME !!"
+
+
[slugify]
+
taxonomies = "off"
+
+
# override these in your `config.toml`
+
[extra]
+
# actually important stuff
+
host_name = "!! YOUR NAME !!"
+
host_link = "!! YOUR LINK !!"
+
jam_hashtag = "!! YOUR HASHTAG !!"
+
jam_hashtag_link = "#"
+
join_link = "!! JOIN LINK !!"
+
start_date = "2026-02-01T00:00:00"
+
end_date = "2026-02-28T23:59:59"
+
locale = "en-US"
+
timezone = "America/Chicago"
+
favicon = "images/android-chrome-512x512.png"
+
favicon32 = "images/favicon-32x32.png"
+
appletouch = "images/favicon-192x192.png"
+
+
# optional features
+
banner = ""
+
+
# joined count
+
joined_count_source = "manual" # options are "manual" / "airtable" / "gsheets" / "json" / "csv"
+
+
joined_count = 0
+
+
joined_airtable_base_id = ""
+
joined_airtable_table_name = ""
+
joined_airtable_token = ""
+
+
joined_google_sheet_id = ""
+
+
joined_json_data_source = ""
+
+
joined_csv_data_source = ""
+
+
# nav menu
+
navmenu = [ # uncomment announcements and/or community to use those features
+
{ name = "Overview", path = "/" },
+
# { name = "Announcements", path= "/posts" },
+
# { name = "Community", path = false, ext_url = "#", newwin = true },
+
{ name = "Submissions", path = "/games" }
+
]
+
+
# "share on [platform]" links
+
share_links = { bsky = true, mastodon = true, x = false, facebook = false }
+
+
custom_share_services = [
+
#{ name = "", icon_path = "", intent_url = "" } # fill this in if you have some other service(s) you want to share to
+
]
+
+
# analytics stuff, optional
+
tinylytics_script_id = ""
+
goatcounter_id = ""
+
use_tinylytics_kudos = true # will not be used if the tinylytics script id isn't provided
+
tinylytics_kudos_emoji = "❤️"
+
+
[author]
+
name = "Carly Smallbird"
+
homepage = "https://veryroundbird.house"