├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── assets ├── assets.go ├── css │ ├── source.css │ └── style.css ├── index.html ├── main.js ├── package.json └── webpack.config.js ├── cmd └── pngsource.go ├── go.mod ├── go.sum ├── lib └── pnghandler.go ├── package.json ├── packaging ├── macos │ └── pngsource.app │ │ └── Contents │ │ ├── Info.plist.tmpl │ │ └── Resources │ │ └── pngsource.icns └── windows │ ├── WebView2Loader.dll │ ├── app-windows-4.0-amd64.exe │ ├── pngsource.bmp │ ├── pngsource.ico │ ├── pngsource.nsi.tmpl │ └── webview.dll ├── pngsource └── gui.go ├── postcss.config.js ├── project.json ├── rsrc_windows_386.syso ├── rsrc_windows_amd64.syso ├── screenshot.png ├── tailwind.config.js ├── web ├── guihandler.go ├── guiwails.go └── guiwebview.go └── winres ├── icon.png ├── icon16.png └── winres.json /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | package-lock.json 4 | tags 5 | *.log 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2021 Chris F Ravenscroft 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO ?= 1.17.2 2 | BRANCH ?= main 3 | VERSION ?= 1.0.1 4 | TARGET ?= webview 5 | 6 | help: 7 | @echo "cli|dev|css|platforms|release" 8 | 9 | devcli: 10 | @go run cmd/pngsource.go 11 | 12 | linuxcli: 13 | @go build -ldflags "-s -w -X 'main.Version=$(VERSION)'" -o dist/linux/cli/pngsource cmd/pngsource.go 14 | 15 | windowscli: 16 | @xgo --branch=$(BRANCH) --go=$(GO) --dest dist/windows/cli --ldflags="-X 'main.Version=$(VERSION)'" --pkg cmd --targets=windows/amd64 github.com/fusion/pngsource \ 17 | && sudo chown -R $$(id -u) dist \ 18 | && mv dist/windows/cli/cmd-windows-4.0-amd64.exe dist/windows/cli/pngsource.exe 19 | 20 | macoscli: 21 | @xgo --branch=$(BRANCH) --go=$(GO) --dest dist/macos/cli --pkg cmd --targets=darwin/arm64 github.com/fusion/pngsource \ 22 | && sudo chown -R $$(id -u) dist \ 23 | && mv dist/macos/cli/cmd-darwin-10.??-arm64 dist/macos/cli/pngsource 24 | 25 | cli: linuxcli windowscli macoscli 26 | 27 | devweb: 28 | @go run pngsource/gui.go 29 | 30 | css: 31 | @yarn css 32 | 33 | # Assuming Linux... yup. 34 | buildlinuxapp: 35 | @go build --tags $(TARGET) --ldflags "-s -w" -o dist/linux/pngsourceapp pngsource/gui.go 36 | 37 | linuxapp: buildlinuxapp 38 | 39 | buildwindowsapp: 40 | @xgo --tags="$(TARGET)" --branch=$(BRANCH) --go=$(GO) --dest dist/windows --ldflags="-H windowsgui" --pkg pngsource --targets=windows/amd64 github.com/fusion/pngsource 41 | 42 | packagewindowsapp: 43 | @sudo chown -R $$(id -u) dist \ 44 | && cp -r packaging/windows/* dist/windows/ \ 45 | && cd dist/windows \ 46 | && cat pngsource.nsi.tmpl | sed "s/{{VERSION}}/$(VERSION)/g" > pngsource.nsi \ 47 | && makensis pngsource.nsi 48 | 49 | windowsapp: buildwindowsapp packagewindowsapp 50 | 51 | buildmacosapp: 52 | @xgo --tags="$(TARGET)" --branch=$(BRANCH) --go=$(GO) --dest dist/macos --ldflags="-s -w" --pkg pngsource --targets=darwin/arm64 github.com/fusion/pngsource 53 | 54 | packagemacosapp: 55 | @sudo chown -R $$(id -u) dist \ 56 | && rm -rf dist/macos/pngsource.app \ 57 | && cp -r packaging/macos/* dist/macos/ \ 58 | && cat dist/macos/pngsource.app/Contents/Info.plist.tmpl | sed "s/{{VERSION}}/$(VERSION)/g" \ 59 | > dist/macos/pngsource.app/Contents/Info.plist \ 60 | && mkdir -p dist/macos/pngsource.app/Contents/MacOS \ 61 | && cp dist/macos/pngsource-darwin-10.??-arm64 dist/macos/pngsource.app/Contents/MacOS/pngsource-darwin-arm64 \ 62 | && dd if=/dev/zero of=dist/macos/PNGSource.dmg bs=1M count=6 status=progress \ 63 | && mkfs.hfsplus -v PNGSource dist/macos/PNGSource.dmg \ 64 | && sudo mkdir -pv /mnt/dmgwork \ 65 | && sudo mount -o loop dist/macos/PNGSource.dmg /mnt/dmgwork \ 66 | && sudo cp -arv dist/macos/pngsource.app /mnt/dmgwork/ \ 67 | && sudo umount /mnt/dmgwork 68 | 69 | macosapp: buildmacosapp packagemacosapp 70 | 71 | app: linuxapp windowsapp macosapp 72 | 73 | clean: 74 | @rm -rf dist/* 75 | 76 | collect: 77 | @mkdir -p dist/release \ 78 | && zip dist/release/pngsource-cli-linux.zip dist/linux/cli/pngsource \ 79 | && zip dist/release/pngsource-cli-windows.zip dist/windows/cli/pngsource.exe \ 80 | && zip dist/release/pngsource-cli-macos.zip dist/macos/cli/pngsource \ 81 | && cp dist/linux/pngsourceapp dist/release/ \ 82 | && cp dist/windows/pngsource_installer.exe dist/release/ \ 83 | && cp dist/macos/PNGSource.dmg dist/release/ 84 | 85 | releasewebview: cli css app collect 86 | 87 | release: releasewebview 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PNGSource 2 | 3 | A tool that makes it easy to embed source code in a PNG file. It can also read source code previously embedded, of course! 4 | 5 | ![Screenshot](screenshot.png) 6 | 7 | ## Benefits 8 | 9 | I detest losing source code, and I like creating diagrams using a descriptive language (be it YAML, UML, Python...) -- Diagrams.com (formerly Draw.io) lets users save their code alongside the generated PNG files. So, that's our prior art! (I tried to remain compatible with their encoding) 10 | 11 | ## What it does 12 | 13 | If you provide PNGSource with the path to an existing PNG file (or drag/drop) it will display that file's decoded `text` chunk, if it exists. 14 | 15 | You can also provide a PNG file and a text file (or enter text manually) and embed the text in the file, in a `text` chunk. 16 | 17 | ## What it does not do 18 | 19 | There is no stenography involved here. Although I am planning on performing a few tests to see if this would let me embed a reasonable amount of code in any image format. 20 | 21 | # Using 22 | 23 | Simply download a CLI tool for your platform, or the GUI application (installer on Windows, disk image on MacOs, standalone on Linux) 24 | 25 | Run the cli command with `--help` to see what you can do. The GUI app should be self explanatory (I hope!) 26 | 27 | If you are running the application on MacOS and are getting an error message, please check the FAQ section. 28 | 29 | # Building 30 | 31 | Only if you plan on contributing or need a different platform: 32 | 33 | `make platforms VERSION=` 34 | 35 | or 36 | 37 | `make platforms BRANCH= VERSION=` 38 | 39 | or 40 | 41 | `make platforms GO= BRANCH= VERSION=` 42 | 43 | Full-on release: 44 | 45 | `make release` instead of `make platforms` 46 | 47 | ## Build dependencies 48 | 49 | - hfsplus (OS package) 50 | - hfsplus support in your kernel... you may have to rebuild a new kernel with `CONFIG_HFS_FS=y` 51 | - pkg-config (OS package) 52 | - libgtk-3-dev (OS package) 53 | - libwebkit2gtk-4.0-dev (OS package) 54 | - zip (OS package) 55 | - nsis nsis-doc nsis-pluginapi (OS packages, Windows packager) 56 | - yarn: `yarn install` 57 | 58 | # FAQ 59 | 60 | **Is this an Electron app?** 61 | 62 | No. It is significantly smaller and less greedy than an Electron-based application. It does, however, rely on a combination of go, webview, tailwindcss and native dialogs. 63 | 64 | **Why isn't it working for me?** 65 | 66 | Please create an issue. If possible, include the files you were working with (image and code) so that I can reproduce the issue. 67 | 68 | **Why am I getting an error message on MacOS?** 69 | 70 | You may be getting a message about the application being damaged. It is not, but the gatekeeper is blocking it. You can work around this from the shell: 71 | 72 | ``` 73 | sudo xattr -cr /Applications/pngsource.app 74 | ``` 75 | -------------------------------------------------------------------------------- /assets/assets.go: -------------------------------------------------------------------------------- 1 | package assets 2 | 3 | import "embed" 4 | 5 | //go:embed *.html css/* 6 | var Content embed.FS 7 | -------------------------------------------------------------------------------- /assets/css/source.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /assets/css/style.css: -------------------------------------------------------------------------------- 1 | /*! tailwindcss v3.0.15 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;-webkit-box-sizing:border-box;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#9ca3af;opacity:1}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#9ca3af;opacity:1}input::-ms-input-placeholder,textarea::-ms-input-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}:root{background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));color:hsla(var(--bc)/var(--tw-text-opacity,1))}html{-webkit-tap-highlight-color:transparent}:root{--p:259 94.4% 51.2%;--pf:259 94.3% 41%;--pc:0 0% 100%;--s:314 100% 47.1%;--sf:314 100% 37.1%;--sc:0 0% 100%;--a:174 60% 51%;--af:174 59.8% 41%;--ac:0 0% 100%;--n:219 14.1% 27.8%;--nf:222 13.4% 19%;--nc:0 0% 100%;--b1:0 0% 100%;--b2:210 20% 98%;--b3:216 12.2% 83.9%;--bc:215 27.9% 16.9%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}@media (prefers-color-scheme:dark){:root{--p:259 94% 61%;--pf:259 94.4% 51.2%;--pc:0 0% 100%;--s:314 100% 47.1%;--sf:314 100% 37.1%;--sc:0 0% 100%;--a:174 60% 51%;--af:174 59.8% 41%;--ac:0 0% 100%;--n:222 13.4% 19%;--nf:223 13.7% 10%;--nc:0 0% 100%;--b1:219 14.1% 27.8%;--b2:222 13.4% 19%;--b3:223 13.7% 10%;--bc:228 14.3% 93.1%;--in:202 100% 70%;--su:89 61.6% 52%;--wa:54 68.8% 63.5%;--er:0 100% 71.8%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}}[data-theme=light]{--p:259 94.4% 51.2%;--pf:259 94.3% 41%;--pc:0 0% 100%;--s:314 100% 47.1%;--sf:314 100% 37.1%;--sc:0 0% 100%;--a:174 60% 51%;--af:174 59.8% 41%;--ac:0 0% 100%;--n:219 14.1% 27.8%;--nf:222 13.4% 19%;--nc:0 0% 100%;--b1:0 0% 100%;--b2:210 20% 98%;--b3:216 12.2% 83.9%;--bc:215 27.9% 16.9%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=dark]{--p:259 94% 61%;--pf:259 94.4% 51.2%;--pc:0 0% 100%;--s:314 100% 47.1%;--sf:314 100% 37.1%;--sc:0 0% 100%;--a:174 60% 51%;--af:174 59.8% 41%;--ac:0 0% 100%;--n:222 13.4% 19%;--nf:223 13.7% 10%;--nc:0 0% 100%;--b1:219 14.1% 27.8%;--b2:222 13.4% 19%;--b3:223 13.7% 10%;--bc:228 14.3% 93.1%;--in:202 100% 70%;--su:89 61.6% 52%;--wa:54 68.8% 63.5%;--er:0 100% 71.8%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=cupcake]{--p:183 47.4% 59%;--pf:183 47.2% 49%;--pc:0 0% 100%;--s:338 71.4% 78%;--sf:338 71.8% 68%;--sc:0 0% 100%;--a:39 84.1% 58%;--af:39 83.7% 48%;--ac:0 0% 100%;--n:280 46.5% 13.9%;--nf:279 46.4% 11%;--nc:0 0% 100%;--b1:24 33.3% 97.1%;--b2:27 22% 92%;--b3:22 14.3% 89%;--bc:280 46.5% 13.9%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:1.9rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:2px;--tab-radius:.5rem}[data-theme=bumblebee]{--p:50 94.4% 58%;--pf:50 94.3% 47.8%;--pc:240 33.3% 14.1%;--s:41 74.2% 52.9%;--sf:41 73.6% 43.1%;--sc:0 0% 100%;--a:240 33.3% 14.1%;--af:240 33.3% 10%;--ac:0 0% 100%;--n:240 33.3% 14.1%;--nf:240 33.3% 10%;--nc:0 0% 100%;--b1:0 0% 100%;--b2:0 0% 96.1%;--b3:0 0% 89%;--bc:0 0% 0%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=emerald]{--p:141 50% 60%;--pf:141 49.8% 50%;--pc:210 20% 98%;--s:219 96.1% 60%;--sf:219 96.1% 50%;--sc:210 20% 98%;--a:10 81.2% 56.1%;--af:10 81.2% 45.9%;--ac:210 20% 98%;--n:219 20.3% 25.1%;--nf:220 19.5% 15.1%;--nc:210 20% 98%;--b1:0 0% 100%;--b2:210 20% 98%;--b3:0 0% 94.9%;--bc:219 20.3% 25.1%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0;--animation-input:0;--btn-text-case:uppercase;--btn-focus-scale:1;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=corporate]{--p:229 95.7% 63.9%;--pf:229 95.7% 53.9%;--pc:233 27.3% 12.9%;--s:215 26.3% 59%;--sf:214 26.1% 48.8%;--sc:233 27.3% 12.9%;--a:154 49% 60%;--af:154 49% 50%;--ac:233 27.3% 12.9%;--n:233 27.3% 12.9%;--nf:240 25% 3.1%;--nc:210 38.5% 94.9%;--b1:0 0% 100%;--b2:210 60% 98%;--b3:210 38.5% 94.9%;--bc:233 27.3% 12.9%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0;--animation-input:0;--btn-text-case:uppercase;--btn-focus-scale:1;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=synthwave]{--p:321 69.6% 69%;--pf:321 70.3% 59%;--pc:257 63.2% 17.1%;--sf:197 87.4% 75.1%;--s:197 86.6% 64.9%;--sc:257 63.2% 17.1%;--af:48 89.3% 67.1%;--a:48 89% 57.1%;--ac:257 63.2% 17.1%;--n:253 60.8% 19%;--nf:257 64.3% 11%;--nc:260 60% 98%;--b1:254 59.1% 25.9%;--b2:253 60.8% 19%;--b3:257 64.3% 11%;--bc:260 60% 98%;--in:199 87% 63.9%;--su:168 74.2% 68%;--wa:48 89% 57.1%;--er:352 73.6% 56.9%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=retro]{--p:3 73.8% 76.1%;--pf:3 73.6% 65.9%;--pc:345 5.3% 14.9%;--s:145 27.3% 72%;--sf:145 26.8% 62%;--sc:345 5.3% 14.9%;--a:49 67.2% 76.1%;--af:49 66.7% 65.9%;--ac:345 5.3% 14.9%;--n:42 16.8% 42%;--nf:41 13.1% 23.9%;--nc:45 47.1% 80%;--b1:45 47.1% 80%;--b2:45 37.1% 72%;--b3:42 36% 65.1%;--bc:345 5.3% 14.9%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:0.4rem;--rounded-btn:0.4rem;--rounded-badge:0.4rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem;font-family:uisecondaryerif,Georgia,Cambria,Times New Roman,Times,serif}[data-theme=cyberpunk]{--p:345 100% 72.9%;--pf:344 100% 67.1%;--pc:0 0% 0%;--s:195 80.4% 70%;--sf:194 65.8% 61%;--sc:0 0% 0%;--a:276 74.3% 71%;--af:276 75.7% 62.9%;--ac:0 0% 0%;--n:57 100% 12.9%;--nf:60 80% 2%;--nc:56 100% 50%;--b1:56 100% 50%;--b2:56 100% 42.9%;--b3:56 100% 36.1%;--bc:0 0% 0%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:0;--rounded-btn:0;--rounded-badge:0;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}[data-theme=valentine]{--p:353 73.8% 67.1%;--pf:353 73.6% 56.9%;--pc:0 0% 100%;--s:254 86.4% 76.9%;--sf:254 86.9% 67.1%;--sc:0 0% 100%;--a:181 55.6% 70%;--af:181 54.9% 60%;--ac:0 0% 100%;--n:336 42.9% 48%;--nf:340 40.2% 38%;--nc:318 46.4% 89%;--b1:318 46.4% 89%;--b2:315 58.9% 79%;--b3:316 62.3% 72.9%;--bc:344 38.5% 28%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:1.9rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=halloween]{--p:32 89.3% 52.2%;--pf:32 88.8% 42%;--pc:180 7.3% 8%;--s:271 45.8% 42%;--sf:271 46% 32%;--sc:0 0% 100%;--a:91 100% 32.9%;--af:91 100% 22.9%;--ac:0 0% 100%;--n:180 3.6% 11%;--nf:180 7.3% 8%;--nc:0 0% 100%;--b1:0 0% 12.9%;--b2:180 3.6% 11%;--b3:180 7.3% 8%;--bc:0 0% 100%;--in:202 100% 70%;--su:89 61.6% 52%;--wa:54 68.8% 63.5%;--er:0 100% 71.8%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=garden]{--p:139 16% 42.9%;--pf:137 14.8% 33.1%;--pc:0 0% 100%;--s:97 37.1% 93.1%;--sf:98 36.3% 82.2%;--sc:96 32.5% 15.1%;--a:0 67.7% 93.9%;--af:0 71.1% 85.1%;--ac:0 22% 16.1%;--n:0 3.9% 35.1%;--nf:0 3.7% 15.9%;--nc:0 4.3% 91%;--b1:0 4.3% 91%;--b2:0 5.2% 81%;--b3:0 5.4% 71%;--bc:0 3.2% 6.1%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=forest]{--p:141 72% 42%;--pf:141 71.8% 32%;--pc:0 0% 100%;--s:141 74.7% 48%;--sf:141 75.3% 38%;--sc:0 0% 100%;--a:35 69% 52%;--af:35 69.2% 42%;--ac:0 0% 100%;--n:0 9.7% 6.1%;--nf:0 20% 2%;--nc:0 0% 100%;--b1:0 12.2% 8%;--b2:0 9.7% 6.1%;--b3:0 20% 2%;--bc:0 0% 100%;--rounded-btn:0.5rem;--in:202 100% 70%;--su:89 61.6% 52%;--wa:54 68.8% 63.5%;--er:0 100% 71.8%;--border-color:var(--b3);--rounded-box:1rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=aqua]{--p:189 100% 62.9%;--pf:189 100% 52.9%;--pc:0 0% 0%;--s:274 30.9% 56.9%;--sf:274 30.8% 47.1%;--sc:0 0% 100%;--a:47 100% 80%;--af:47 100% 70%;--ac:0 0% 100%;--n:231 77.4% 32.9%;--nf:231 67.6% 29%;--nc:0 0% 100%;--b1:231 88.7% 38%;--b2:231 77.4% 32.9%;--b3:231 67.6% 29%;--bc:0 0% 100%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=lofi]{--p:0 0% 50.2%;--pf:0 0% 45.1%;--pc:240 4% 95.1%;--s:0 0% 30.2%;--sf:0 0% 25.1%;--sc:240 4% 95.1%;--a:0 0% 10.2%;--af:0 0% 5.1%;--ac:240 4% 95.1%;--n:240 4% 95.1%;--nf:240 5.9% 90%;--nc:0 0% 30.2%;--b1:0 0% 100%;--b2:0 0% 100%;--b3:0 0% 100%;--bc:0 0% 49%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:#e6e6e6;--rounded-box:0;--rounded-btn:0;--rounded-badge:0;--animation-btn:0;--animation-input:0;--btn-text-case:uppercase;--btn-focus-scale:1;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0}[data-theme=lofi] :where(.btn){--tw-border-opacity:1!important;--tw-text-opacity:1!important;--tw-shadow:0 0 0 1px var(--border-color)!important;border-color:var(--border-color)!important}[data-theme=lofi] :where(.badge){--tw-border-opacity:1!important;--tw-text-opacity:1!important;--tw-shadow:0 0 0 1px var(--border-color)!important;border-color:var(--border-color)!important}[data-theme=lofi] :where(.card){--tw-border-opacity:1!important;--tw-text-opacity:1!important;--tw-shadow:0 0 0 1px var(--border-color)!important;border-color:var(--border-color)!important}[data-theme=pastel]{--p:284 21.6% 80%;--pf:282 21.6% 70%;--pc:0 0% 0%;--s:352 70.5% 88%;--sf:352 69.6% 78%;--sc:0 0% 100%;--a:158 54.6% 81%;--af:158 55.4% 71%;--ac:0 0% 100%;--n:199 43.7% 61%;--nf:199 44% 51%;--nc:0 0% 100%;--b1:0 0% 100%;--b2:210 20% 98%;--b3:216 12.2% 83.9%;--bc:206 3.1% 55.1%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--rounded-box:1rem;--rounded-btn:1.9rem;--rounded-badge:1.9rem;--border-color:var(--b3);--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=fantasy]{--p:296 82.8% 25.1%;--pf:296 81.8% 15.1%;--pc:0 0% 100%;--s:200 100% 37.1%;--sf:200 100% 27.1%;--sc:0 0% 100%;--a:31 94.4% 51.2%;--af:31 94.3% 41%;--ac:0 0% 100%;--n:215 27.9% 16.9%;--nf:221 39.3% 11%;--nc:0 0% 100%;--b1:0 0% 100%;--b2:210 20% 98%;--b3:216 12.2% 83.9%;--bc:215 27.9% 16.9%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=wireframe]{--p:0 0% 72.2%;--pf:0 0% 72.2%;--pc:0 0% 0%;--s:0 0% 72.2%;--sf:0 0% 72.2%;--sc:0 0% 0%;--a:0 0% 72.2%;--af:0 0% 72.2%;--ac:0 0% 0%;--b1:0 0% 100%;--b2:0 0% 100%;--b3:0 0% 100%;--bc:0 0% 0%;--n:0 0% 92.2%;--nf:0 0% 92.2%;--nc:0 0% 0%;--in:240 100% 50%;--su:120 100% 25.1%;--wa:60 30.2% 50%;--er:0 100% 50%;--border-color:#000;--rounded-box:0.2rem;--rounded-btn:0.2rem;--rounded-badge:0.2rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.2rem;font-family:Chalkboard,comic sans ms,sanssecondaryerif}[data-theme=wireframe] *{--tw-border-opacity:1!important;--tw-text-opacity:1!important;--tw-shadow:0 0 0 1px var(--border-color)!important;border-color:var(--border-color)!important}[data-theme=black]{--p:0 0% 100%;--pf:0 0% 100%;--pc:0 0% 0%;--s:0 0% 100%;--sf:0 0% 100%;--sc:0 0% 0%;--a:0 0% 100%;--af:0 0% 100%;--ac:0 0% 0%;--b1:0 0% 0%;--b2:0 0% 20%;--b3:0 0% 30.2%;--bc:0 0% 100%;--n:0 0% 20%;--nf:0 0% 30.2%;--nc:0 0% 100%;--in:240 100% 50%;--su:120 100% 25.1%;--wa:60 100% 50%;--er:0 100% 50%;--border-color:var(--b3);--rounded-box:0;--rounded-btn:0;--rounded-badge:0;--animation-btn:0;--animation-input:0;--btn-text-case:lowercase;--btn-focus-scale:1;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0}[data-theme=luxury]{--p:0 0% 100%;--pf:0 0% 90.2%;--pc:0 0% 0%;--s:218 54.3% 18%;--sf:219 56.1% 8%;--sc:0 0% 100%;--a:319 21.8% 26.1%;--af:320 22% 16.1%;--ac:0 0% 100%;--n:270 4.3% 9%;--nf:270 2.2% 18%;--nc:37 67.3% 58%;--b1:240 10% 3.9%;--b2:270 4.3% 9%;--b3:270 2.2% 18%;--bc:37 67.3% 58%;--in:202 100% 70%;--su:89 61.6% 52%;--wa:54 68.8% 63.5%;--er:0 100% 71.8%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=dracula]{--p:330 100% 85.1%;--pf:330 100% 75.1%;--pc:233 12.1% 12.9%;--s:115 100% 85.1%;--sf:115 100% 75.1%;--sc:233 12.1% 12.9%;--a:60 100% 85.1%;--af:60 100% 75.1%;--ac:233 12.1% 12.9%;--n:245 14.3% 15.1%;--nf:233 12.1% 12.9%;--nc:251 100% 90%;--b1:244 13% 21.2%;--b2:245 14.3% 15.1%;--b3:233 12.1% 12.9%;--bc:251 100% 90%;--in:207 89.8% 53.9%;--su:174 100% 29%;--wa:36 100% 50%;--er:14 100% 57.1%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}[data-theme=cmyk]{--p:203 83.3% 60.2%;--pf:203 65.1% 53.9%;--pc:0 0% 0%;--s:335 77.7% 59.6%;--sf:335 59.2% 52.9%;--sc:0 0% 0%;--a:56 100% 59.8%;--af:56 72.2% 52%;--ac:0 0% 0%;--n:0 0% 10.2%;--nf:0 0% 0%;--nc:0 0% 100%;--b1:0 0% 100%;--b2:0 0% 96.1%;--b3:0 0% 92.2%;--bc:0 0% 0%;--in:192 48.4% 52.2%;--su:291 48.5% 38%;--wa:25 84.6% 56.7%;--er:4 80.5% 55.7%;--border-color:var(--b3);--rounded-box:1rem;--rounded-btn:0.5rem;--rounded-badge:1.9rem;--animation-btn:0.25s;--animation-input:.2s;--btn-text-case:uppercase;--btn-focus-scale:0.95;--navbar-padding:.5rem;--border-btn:1px;--tab-border:1px;--tab-radius:0.5rem}*,:after,:before{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}.\!container{width:100%!important}@media (min-width:640px){.container{max-width:640px}.\!container{max-width:640px!important}}@media (min-width:768px){.container{max-width:768px}.\!container{max-width:768px!important}}@media (min-width:1024px){.container{max-width:1024px}.\!container{max-width:1024px!important}}@media (min-width:1280px){.container{max-width:1280px}.\!container{max-width:1280px!important}}@media (min-width:1536px){.container{max-width:1536px}.\!container{max-width:1536px!important}}.alert>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(.5rem*var(--tw-space-y-reverse));margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)))}.alert{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-align:center;-ms-flex-align:center;-webkit-box-pack:justify;-ms-flex-pack:justify;--tw-bg-opacity:1;align-items:center;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1));border-radius:var(--rounded-box,1rem);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;justify-content:space-between;padding:1rem}@media (min-width:768px){.alert>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(0px*var(--tw-space-y-reverse));margin-top:calc(0px*(1 - var(--tw-space-y-reverse)))}.alert{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}}.alert>*,.avatar.placeholder>div{display:-webkit-box;display:-ms-flexbox;display:flex}.avatar.placeholder>div{-webkit-box-align:center;-ms-flex-align:center;-webkit-box-pack:center;-ms-flex-pack:center;align-items:center;justify-content:center}.\!avatar.\!placeholder>div{-webkit-box-align:center!important;-ms-flex-align:center!important;-webkit-box-pack:center!important;-ms-flex-pack:center!important;align-items:center!important;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;justify-content:center!important}.badge{border-color:hsla(var(--n)/var(--tw-border-opacity,1));border-radius:var(--rounded-badge,1.9rem);border-width:1px;height:1.25rem;padding-left:.563rem;padding-right:.563rem;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.badge,.btn{-webkit-box-align:center;-ms-flex-align:center;-webkit-box-pack:center;-ms-flex-pack:center;--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;align-items:center;background-color:hsla(var(--n)/var(--tw-bg-opacity,1));color:hsla(var(--nc)/var(--tw-text-opacity,1));display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:.875rem;justify-content:center;line-height:1.25rem;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1)}.btn{-ms-flex-negative:0;-webkit-animation:button-pop var(--animation-btn,.25s) ease-out;animation:button-pop var(--animation-btn,.25s) ease-out;border-color:transparent;border-color:hsla(var(--n)/var(--tw-border-opacity,1));border-radius:var(--rounded-btn,.5rem);border-width:var(--border-btn,1px);cursor:pointer;flex-shrink:0;-ms-flex-wrap:wrap;flex-wrap:wrap;font-weight:600;height:3rem;line-height:1em;min-height:3rem;padding-left:1rem;padding-right:1rem;text-align:center;text-transform:uppercase;text-transform:var(--btn-text-case,uppercase);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus{outline:2px solid transparent;outline-offset:2px}.btn-disabled,.btn[disabled]{--tw-bg-opacity:0.2;--tw-border-opacity:0;--tw-text-opacity:0.2;background-color:hsla(var(--n)/var(--tw-bg-opacity,1));color:hsla(var(--bc)/var(--tw-text-opacity,1));pointer-events:none}.btn.loading,.btn.loading:hover{pointer-events:none}.btn.loading:before{-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;border-color:transparent currentColor currentColor transparent;border-radius:9999px;border-width:2px;content:"";height:1rem;margin-right:.5rem;width:1rem}@media (prefers-reduced-motion:reduce){.btn.loading:before{-webkit-animation:spin 10s linear infinite;animation:spin 10s linear infinite}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.btn-group>input[type=radio].btn{-webkit-appearance:none;-moz-appearance:none;appearance:none}.btn-group>input[type=radio].btn:before{content:attr(data-title)}.card{-webkit-box-orient:vertical;-webkit-box-direction:normal;border-radius:var(--rounded-box,1rem);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;overflow:hidden;position:relative}.card:focus{outline:2px solid transparent;outline-offset:2px}.card figure,.card figure>*{width:100%}.card.image-full{display:grid}.card.image-full:before{--tw-bg-opacity:1;background-color:hsla(var(--n)/var(--tw-bg-opacity,1));border-radius:var(--rounded-box,1rem);content:"";opacity:.75;position:relative;z-index:10}.card.image-full:before,.card.image-full>*{grid-column-start:1;grid-row-start:1}.card.image-full>figure img{height:100%;-o-object-fit:cover;object-fit:cover}.card.image-full>.card-body{--tw-text-opacity:1;color:hsla(var(--nc)/var(--tw-text-opacity,1));position:relative;z-index:20}.checkbox:focus,.collapse{outline:2px solid transparent;outline-offset:2px}.collapse{display:grid;overflow:hidden;position:relative}.collapse-content,.collapse-title,.collapse>input[type=checkbox]{grid-column-start:1;grid-row-start:1}.collapse>input[type=checkbox]{-webkit-appearance:none;-moz-appearance:none;appearance:none;opacity:0}.collapse-open .collapse-content,.collapse:focus:not(.collapse-close) .collapse-content,.collapse:not(.collapse-close) input[type=checkbox]:checked~.collapse-content{--tw-bg-opacity:0.1;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1));max-height:9000px;opacity:1;padding-bottom:1rem;-webkit-transition:padding .2s ease-in-out,background-color .2s ease-in-out;transition:padding .2s ease-in-out,background-color .2s ease-in-out}.divider{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:1rem;margin-bottom:1rem;margin-top:1rem}.divider:after,.divider:before{-webkit-box-flex:1;-ms-flex-positive:1;--tw-bg-opacity:1;--tw-bg-opacity:var(--tw-border-opacity,0.1);background-color:hsla(var(--bc)/var(--tw-bg-opacity,1));content:"";flex-grow:1;height:.125rem}.dropdown{display:inline-block;position:relative}.dropdown>:focus{outline:2px solid transparent;outline-offset:2px}.dropdown .dropdown-content{--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:.95;--tw-scale-y:.95;opacity:0;position:absolute;-webkit-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));-webkit-transform-origin:top;transform-origin:top;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);visibility:hidden;z-index:50}.dropdown.dropdown-hover:hover .dropdown-content,.dropdown.dropdown-open .dropdown-content,.dropdown:not(.dropdown-hover):focus-within .dropdown-content,.dropdown:not(.dropdown-hover):focus .dropdown-content{opacity:1;visibility:visible}.footer{-moz-column-gap:1rem;-webkit-column-gap:1rem;column-gap:1rem;font-size:.875rem;grid-auto-flow:row;line-height:1.25rem;row-gap:2.5rem;width:100%}.footer,.footer>*{display:grid;place-items:start}.footer>*{gap:.5rem}@media (min-width:48rem){.footer{grid-auto-flow:column}.footer-center{grid-auto-flow:row dense}}.form-control{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.form-control,.label{display:-webkit-box;display:-ms-flexbox;display:flex}.label{-webkit-box-align:center;-ms-flex-align:center;-webkit-box-pack:justify;-ms-flex-pack:justify;align-items:center;justify-content:space-between;padding:.5rem .25rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.\!label{-webkit-box-align:center!important;-ms-flex-align:center!important;-webkit-box-pack:justify!important;-ms-flex-pack:justify!important;align-items:center!important;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;justify-content:space-between!important;padding:.5rem .25rem!important;-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.indicator{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.indicator .indicator-item{--tw-translate-x:0;--tw-translate-x:50%;--tw-translate-y:0;--tw-translate-y:-50%;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;bottom:auto;left:auto;position:absolute;right:0;top:0;-webkit-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));z-index:1}.indicator .indicator-item.indicator-start{--tw-translate-x:-50%;left:0;right:auto}.indicator .indicator-item.indicator-center{--tw-translate-x:-50%;left:50%;right:50%}.indicator .indicator-item.indicator-end{--tw-translate-x:50%;left:auto;right:0}.indicator .indicator-item.indicator-bottom{--tw-translate-y:50%;bottom:0;top:auto}.indicator .indicator-item.indicator-middle{--tw-translate-y:-50%;bottom:50%;top:50%}.indicator .indicator-item.indicator-top{--tw-translate-y:-50%;bottom:auto;top:0}.input{-ms-flex-negative:1;--tw-bg-opacity:1;--tw-border-opacity:0;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:.875rem;height:3rem;line-height:1.25rem;line-height:2;padding-left:1rem;padding-right:1rem;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1)}.\!input{-ms-flex-negative:1!important;--tw-bg-opacity:1!important;--tw-border-opacity:0!important;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1))!important;border-color:hsla(var(--bc)/var(--tw-border-opacity,1))!important;border-radius:var(--rounded-btn,.5rem)!important;border-width:1px!important;flex-shrink:1!important;font-size:.875rem!important;height:3rem!important;line-height:1.25rem!important;line-height:2!important;padding-left:1rem!important;padding-right:1rem!important;-webkit-transition-duration:.2s!important;transition-duration:.2s!important;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform!important;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform!important;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform!important;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important}.input:focus{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2);box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2);outline:2px solid transparent;outline-offset:2px}.\!input:focus{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2)!important;box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2)!important;outline:2px solid transparent!important;outline-offset:2px!important}.input-group>*,.input-group>.input{border-radius:0}.\!input-group>*,.\!input-group>.\!input{border-radius:0!important}.link{cursor:pointer;text-decoration:underline}.mask{-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain}.\!mask{-webkit-mask-position:center!important;mask-position:center!important;-webkit-mask-repeat:no-repeat!important;mask-repeat:no-repeat!important;-webkit-mask-size:contain!important;mask-size:contain!important}.menu{-webkit-box-orient:vertical;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;overflow:hidden}.menu,.menu.horizontal{-webkit-box-direction:normal}.menu.horizontal{-webkit-box-orient:horizontal;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-ms-flex-direction:row;flex-direction:row}.menu.horizontal :where(li){-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.menu :where(li){-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column}.menu :where(li)>a,.menu :where(li)>span{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1)}.menu :where(li)>a{cursor:pointer}.menu :where(li)>a:focus{outline:2px solid transparent;outline-offset:2px}.menu :where(li).disabled>a,.menu :where(li).disabled>span{cursor:auto}.\!menu :where(li).\!disabled>a,.\!menu :where(li).\!disabled>span{cursor:auto!important}.modal{-webkit-box-align:end;-ms-flex-align:end;-webkit-box-pack:center;-ms-flex-pack:center;--tw-bg-opacity:0.4;align-items:flex-end;background-color:hsla(var(--nf)/var(--tw-bg-opacity,1));bottom:0;display:-webkit-box;display:-ms-flexbox;display:flex;justify-content:center;left:0;opacity:0;pointer-events:none;position:fixed;right:0;top:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);visibility:hidden;z-index:999}@media (min-width:640px){.modal{-webkit-box-align:center;-ms-flex-align:center;align-items:center}}.modal-open,.modal-toggle:checked+.modal,.modal:target{opacity:1;pointer-events:auto;visibility:visible}.progress{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:var(--rounded-box,1rem);height:.5rem;overflow:hidden;position:relative;width:100%}.radio:focus{outline:2px solid transparent;outline-offset:2px}.range{--range-shdw:var(--bc);-webkit-appearance:none;background-color:transparent;cursor:pointer;height:1.25rem;width:100%}.\!range{--range-shdw:var(--bc)!important;-webkit-appearance:none!important;background-color:transparent!important;cursor:pointer!important;height:1.25rem!important;width:100%!important}.range:focus{outline:none}.\!range:focus{outline:none!important}.select{-ms-flex-negative:0;--tw-bg-opacity:1;--tw-border-opacity:0;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));background-image:linear-gradient(45deg,transparent 50%,currentColor 0),linear-gradient(135deg,currentColor 50%,transparent 0);background-position:calc(100% - 20px) calc(1px + 50%),calc(100% - 16px) calc(1px + 50%);background-repeat:no-repeat;background-size:4px 4px,4px 4px;border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-radius:var(--rounded-btn,.5rem);border-width:1px;cursor:pointer;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;flex-shrink:0;font-size:.875rem;font-weight:600;height:3rem;line-height:1.25rem;line-height:2;min-height:3rem;padding-left:1rem;padding-right:2.5rem;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.select:focus{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2);box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2);outline:2px solid transparent;outline-offset:2px}.select-disabled,.select[disabled]{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:0.2;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1));border-color:hsla(var(--b2)/var(--tw-border-opacity,1));cursor:not-allowed;pointer-events:none}.stack{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;display:inline-grid;place-items:center}.\!stack{-webkit-box-align:end!important;-ms-flex-align:end!important;align-items:flex-end!important;display:inline-grid!important;place-items:center!important}.stack>*{grid-column-start:1;grid-row-start:1;opacity:.6;-webkit-transform:translateY(1rem)scale(.9);transform:translateY(1rem)scale(.9);width:100%;z-index:1}.\!stack>*{grid-column-start:1!important;grid-row-start:1!important;opacity:.6!important;-webkit-transform:translateY(1rem)scale(.9)!important;transform:translateY(1rem)scale(.9)!important;width:100%!important;z-index:1!important}.stack>:nth-child(2){opacity:.8;-webkit-transform:translateY(.5rem)scale(.95);transform:translateY(.5rem)scale(.95);z-index:2}.\!stack>:nth-child(2){opacity:.8!important;-webkit-transform:translateY(.5rem)scale(.95)!important;transform:translateY(.5rem)scale(.95)!important;z-index:2!important}.stack>:first-child{opacity:1;-webkit-transform:translateY(0)scale(1);transform:translateY(0)scale(1);z-index:3}.\!stack>:first-child{opacity:1!important;-webkit-transform:translateY(0)scale(1)!important;transform:translateY(0)scale(1)!important;z-index:3!important}.stats{border-radius:var(--rounded-box,1rem);display:inline-grid;grid-auto-flow:column;overflow:hidden;overflow-x:auto}.\!stats{border-radius:var(--rounded-box,1rem)!important;display:inline-grid!important;grid-auto-flow:column!important;overflow:hidden!important;overflow-x:auto!important}.stat{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));color:hsla(var(--bc)/var(--tw-text-opacity,1));display:inline-grid;grid-template-columns:1fr auto;padding:1rem 1.5rem;width:100%}.\!stat{--tw-bg-opacity:1!important;--tw-text-opacity:1!important;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1))!important;color:hsla(var(--bc)/var(--tw-text-opacity,1))!important;display:inline-grid!important;grid-template-columns:1fr auto!important;padding:1rem 1.5rem!important;width:100%!important}.stats.grid-flow-row{grid-auto-rows:minmax(0,1fr)}.\!stats.\!grid-flow-row{grid-auto-rows:minmax(0,1fr)!important}.steps{counter-reset:step;display:inline-grid;grid-auto-columns:1fr;grid-auto-flow:column;overflow:hidden;overflow-x:auto}.steps .step{display:grid;grid-template-columns:repeat(1,minmax(0,1fr));grid-template-rows:repeat(2,minmax(0,1fr));grid-template-rows:40px 1fr;min-width:4rem;place-items:center;text-align:center}.\!steps .\!step{display:grid!important;grid-template-columns:repeat(1,minmax(0,1fr))!important;grid-template-rows:repeat(2,minmax(0,1fr))!important;grid-template-rows:40px 1fr!important;min-width:4rem!important;place-items:center!important;text-align:center!important}.steps-vertical .step{display:grid;gap:.5rem;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-columns:40px 1fr;grid-template-rows:repeat(1,minmax(0,1fr));grid-template-rows:auto;justify-items:start;min-height:4rem}.\!steps-vertical .\!step{display:grid!important;gap:.5rem!important;grid-template-columns:repeat(2,minmax(0,1fr))!important;grid-template-columns:40px 1fr!important;grid-template-rows:repeat(1,minmax(0,1fr))!important;grid-template-rows:auto!important;justify-items:start!important;min-height:4rem!important}.tabs{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;display:-webkit-box;display:-ms-flexbox;display:flex}.tab,.tabs{-ms-flex-wrap:wrap;flex-wrap:wrap}.tab{-webkit-box-align:center;-ms-flex-align:center;-webkit-box-pack:center;-ms-flex-pack:center;--tab-padding:1rem;--tw-text-opacity:0.5;align-items:center;color:hsla(var(--bc)/var(--tw-text-opacity,1));cursor:pointer;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:.875rem;height:2rem;justify-content:center;line-height:1.25rem;line-height:2;padding-left:var(--tab-padding,1rem);padding-right:var(--tab-padding,1rem);text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tab,.table{position:relative}.table{text-align:left}.\!table{position:relative!important;text-align:left!important}.table th:first-child{left:0;position:sticky;position:-webkit-sticky;z-index:10}.\!table th:first-child{left:0!important;position:sticky!important;position:-webkit-sticky!important;z-index:10!important}.textarea{-ms-flex-negative:1;--tw-bg-opacity:1;--tw-border-opacity:0;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-radius:var(--rounded-btn,.5rem);border-width:1px;flex-shrink:1;font-size:.875rem;line-height:1.25rem;line-height:2;min-height:3rem;padding:.5rem 1rem;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,-webkit-box-shadow,-webkit-transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform;transition-property:background-color,border-color,color,fill,stroke,opacity,box-shadow,transform,-webkit-box-shadow,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1)}.textarea:focus{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2);box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsla(var(--bc)/.2)}.textarea:focus,.toggle:focus{outline:2px solid transparent;outline-offset:2px}.btn .badge{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));border-color:transparent;color:hsla(var(--bc)/var(--tw-text-opacity,1))}.btn .badge-outline{--tw-border-opacity:1;--tw-text-opacity:1;background-color:transparent;border-color:hsla(var(--b2)/var(--tw-border-opacity,1));color:hsla(var(--b2)/var(--tw-text-opacity,1))}.btn-outline .badge{--tw-border-opacity:1;--tw-text-opacity:1;border-color:hsla(var(--nf)/var(--tw-border-opacity,1));color:hsla(var(--nc)/var(--tw-text-opacity,1))}.btn-outline.btn-primary .badge{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--p)/var(--tw-bg-opacity,1));border-color:hsla(var(--p)/var(--tw-border-opacity,1));color:hsla(var(--pc)/var(--tw-text-opacity,1))}.btn-outline.btn-secondary .badge{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--s)/var(--tw-bg-opacity,1));border-color:hsla(var(--s)/var(--tw-border-opacity,1));color:hsla(var(--sc)/var(--tw-text-opacity,1))}.btn-outline.btn-accent .badge{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--a)/var(--tw-bg-opacity,1));border-color:hsla(var(--a)/var(--tw-border-opacity,1));color:hsla(var(--ac)/var(--tw-text-opacity,1))}.btn-outline .badge.outline{--tw-border-opacity:1;background-color:transparent;border-color:hsla(var(--nf)/var(--tw-border-opacity,1))}.btn-outline:hover .badge{--tw-bg-opacity:1;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1));color:hsla(var(--bc)/var(--tw-text-opacity,1))}.btn-outline:hover .badge,.btn-outline:hover .badge.outline{--tw-border-opacity:1;--tw-text-opacity:1;border-color:hsla(var(--b2)/var(--tw-border-opacity,1))}.btn-outline:hover .badge.outline{color:hsla(var(--nc)/var(--tw-text-opacity,1))}.btn-outline.btn-primary:hover .badge{background-color:hsla(var(--pc)/var(--tw-bg-opacity,1));color:hsla(var(--p)/var(--tw-text-opacity,1))}.btn-outline.btn-primary:hover .badge,.btn-outline.btn-primary:hover .badge.outline{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;border-color:hsla(var(--pc)/var(--tw-border-opacity,1))}.btn-outline.btn-primary:hover .badge.outline{background-color:hsla(var(--pf)/var(--tw-bg-opacity,1));color:hsla(var(--pc)/var(--tw-text-opacity,1))}.btn-outline.btn-secondary:hover .badge{background-color:hsla(var(--sc)/var(--tw-bg-opacity,1));color:hsla(var(--s)/var(--tw-text-opacity,1))}.btn-outline.btn-secondary:hover .badge,.btn-outline.btn-secondary:hover .badge.outline{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;border-color:hsla(var(--sc)/var(--tw-border-opacity,1))}.btn-outline.btn-secondary:hover .badge.outline{background-color:hsla(var(--sf)/var(--tw-bg-opacity,1));color:hsla(var(--sc)/var(--tw-text-opacity,1))}.btn-outline.btn-accent:hover .badge{background-color:hsla(var(--ac)/var(--tw-bg-opacity,1));color:hsla(var(--a)/var(--tw-text-opacity,1))}.btn-outline.btn-accent:hover .badge,.btn-outline.btn-accent:hover .badge.outline{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;border-color:hsla(var(--ac)/var(--tw-border-opacity,1))}.btn-outline.btn-accent:hover .badge.outline{background-color:hsla(var(--af)/var(--tw-bg-opacity,1));color:hsla(var(--ac)/var(--tw-text-opacity,1))}.btn:active:focus,.btn:active:hover{-webkit-animation:none;animation:none;-webkit-transform:scale(var(--btn-focus-scale,.95));transform:scale(var(--btn-focus-scale,.95))}.btn-active,.btn:hover{--tw-bg-opacity:1;--tw-border-opacity:1;background-color:hsla(var(--nf)/var(--tw-bg-opacity,1));border-color:hsla(var(--nf)/var(--tw-border-opacity,1))}.btn:focus-visible{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--nf));box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--nf))}.btn.glass.btn-active,.btn.glass:hover{--glass-opacity:25%;--glass-border-opacity:15%}.btn.glass:focus-visible{-webkit-box-shadow:0 0 0 2px currentColor;box-shadow:0 0 0 2px currentColor}.btn.loading.btn-circle:before,.btn.loading.btn-square:before{margin-right:0}.btn.loading.btn-lg:before,.btn.loading.btn-xl:before{height:1.25rem;width:1.25rem}.btn.loading.btn-sm:before,.btn.loading.btn-xs:before{height:.75rem;width:.75rem}.btn-group>.btn-active,.btn-group>input[type=radio]:checked.btn{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--p)/var(--tw-bg-opacity,1));border-color:hsla(var(--p)/var(--tw-border-opacity,1));color:hsla(var(--pc)/var(--tw-text-opacity,1))}.btn-group>.btn-active:focus-visible,.btn-group>input[type=radio]:checked.btn:focus-visible{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--p));box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--p))}.btn-group>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.btn-group>.btn:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}@-webkit-keyframes button-pop{0%{-webkit-transform:scale(var(--btn-focus-scale,.95));transform:scale(var(--btn-focus-scale,.95))}40%{-webkit-transform:scale(1.02);transform:scale(1.02)}to{-webkit-transform:scale(1);transform:scale(1)}}@keyframes button-pop{0%{-webkit-transform:scale(var(--btn-focus-scale,.95));transform:scale(var(--btn-focus-scale,.95))}40%{-webkit-transform:scale(1.02);transform:scale(1.02)}to{-webkit-transform:scale(1);transform:scale(1)}}.card:focus-visible{-webkit-box-shadow:0 0 0 2px currentColor;box-shadow:0 0 0 2px currentColor}.card.bordered{--tw-border-opacity:1;border-color:hsla(var(--b2)/var(--tw-border-opacity,1));border-width:1px}.card.compact .card-body{font-size:.875rem;line-height:1.25rem;padding:1rem}.\!card.\!compact .\!card-body{font-size:.875rem!important;line-height:1.25rem!important;padding:1rem!important}.card.compact .card-title{margin-bottom:.25rem}.\!card.\!compact .\!card-title{margin-bottom:.25rem!important}.checkbox{--chkbg:var(--bc);--chkfg:var(--b1);--tw-border-opacity:0.2;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-radius:var(--rounded-btn,.5rem);border-width:1px;cursor:pointer;height:1.5rem;width:1.5rem}.checkbox:focus-visible{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--bc));box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--bc))}.checkbox:checked{-webkit-animation:checkmark var(--animation-input,.2s) ease-in-out;animation:checkmark var(--animation-input,.2s) ease-in-out;background-image:linear-gradient(-45deg,transparent 65%,hsl(var(--chkbg)) 0),linear-gradient(45deg,transparent 75%,hsl(var(--chkbg)) 0),linear-gradient(-45deg,hsl(var(--chkbg)) 40%,transparent 0),linear-gradient(45deg,hsl(var(--chkbg)) 30%,hsl(var(--chkfg)) 0,hsl(var(--chkfg)) 40%,transparent 0),linear-gradient(-45deg,hsl(var(--chkfg)) 50%,hsl(var(--chkbg)) 0);background-repeat:no-repeat}.checkbox:checked,.checkbox:disabled{--tw-bg-opacity:1;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1))}.checkbox:disabled{border-color:transparent;cursor:not-allowed;opacity:.2}@-webkit-keyframes checkmark{0%{background-position-y:5px}50%{background-position-y:-2px}to{background-position-y:0}}@keyframes checkmark{0%{background-position-y:5px}50%{background-position-y:-2px}to{background-position-y:0}}.collapse:not(.collapse-open):not(.collapse-close) .collapse-title,.collapse:not(.collapse-open):not(.collapse-close) input[type=checkbox]{cursor:pointer}.collapse:focus:not(.collapse-open):not(.collapse-close) .collapse-title{cursor:unset}.collapse-title,.collapse>input[type=checkbox]{min-height:3.75rem;padding:1rem 3rem 1rem 1rem;-webkit-transition:background-color .2s ease-in-out;transition:background-color .2s ease-in-out;width:100%}.collapse:not(.collapse-close) input[type=checkbox]:focus~.collapse-title{--tw-bg-opacity:0.1;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1))}.collapse-open .collapse-title,.collapse:focus:not(.collapse-close) .collapse-title,.collapse:not(.collapse-close) input[type=checkbox]:checked~.collapse-title{--tw-bg-opacity:0.1;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1));outline:2px solid transparent;outline-offset:2px}.divider:not(:empty):before{margin-right:1rem}.divider:not(:empty):after{margin-left:1rem}.drawer-toggle:focus-visible~.drawer-content .drawer-button.glass{-webkit-box-shadow:0 0 0 2px currentColor;box-shadow:0 0 0 2px currentColor}.dropdown.dropdown-hover:hover .dropdown-content,.dropdown.dropdown-open .dropdown-content,.dropdown:focus-within .dropdown-content,.dropdown:focus .dropdown-content{--tw-scale-x:1;--tw-scale-y:1}.label-text{font-size:.875rem;line-height:1.25rem}.label-text,.label a:hover{--tw-text-opacity:1;color:hsla(var(--bc)/var(--tw-text-opacity,1))}.\!label a:hover{--tw-text-opacity:1!important;color:hsla(var(--bc)/var(--tw-text-opacity,1))!important}.input-disabled,.input[disabled]{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:0.2;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1));border-color:hsla(var(--b2)/var(--tw-border-opacity,1));cursor:not-allowed}.\!input-disabled,.\!input[disabled]{--tw-bg-opacity:1!important;--tw-border-opacity:1!important;--tw-text-opacity:0.2!important;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1))!important;border-color:hsla(var(--b2)/var(--tw-border-opacity,1))!important;cursor:not-allowed!important}.input-disabled::-webkit-input-placeholder,.input[disabled]::-webkit-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.input-disabled::-moz-placeholder,.input[disabled]::-moz-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.input-disabled:-ms-input-placeholder,.input[disabled]:-ms-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.input-disabled::-ms-input-placeholder,.input[disabled]::-ms-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.input-disabled::placeholder,.input[disabled]::placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.\!input-disabled::-webkit-input-placeholder,.\!input[disabled]::-webkit-input-placeholder{--tw-placeholder-opacity:0.2!important;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))!important}.\!input-disabled::-moz-placeholder,.\!input[disabled]::-moz-placeholder{--tw-placeholder-opacity:0.2!important;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))!important}.\!input-disabled:-ms-input-placeholder,.\!input[disabled]:-ms-input-placeholder{--tw-placeholder-opacity:0.2!important;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))!important}.\!input-disabled::-ms-input-placeholder,.\!input[disabled]::-ms-input-placeholder{--tw-placeholder-opacity:0.2!important;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))!important}.\!input-disabled::placeholder,.\!input[disabled]::placeholder{--tw-placeholder-opacity:0.2!important;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))!important}.link:focus{outline:2px solid transparent;outline-offset:2px}.link:focus-visible{-webkit-box-shadow:0 0 0 2px currentColor;box-shadow:0 0 0 2px currentColor}.menu.horizontal li.bordered>a,.menu.horizontal li.bordered>span{--tw-border-opacity:1;border-bottom-width:4px;border-color:hsla(var(--p)/var(--tw-border-opacity,1));border-left-width:0}.menu[class*=p-] li a{border-radius:var(--rounded-btn,.5rem)}.menu li>a,.menu li>span{color:currentColor;padding:.75rem 1.25rem}.menu li>a:focus,.menu li>a:hover{--tw-bg-opacity:0.1;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1))}.menu li>a.active{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--p)/var(--tw-bg-opacity,1));color:hsla(var(--pc)/var(--tw-text-opacity,1))}.\!menu li>a.\!active{--tw-bg-opacity:1!important;--tw-text-opacity:1!important;background-color:hsla(var(--p)/var(--tw-bg-opacity,1))!important;color:hsla(var(--pc)/var(--tw-text-opacity,1))!important}.menu li>a:active{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--pf)/var(--tw-bg-opacity,1));color:hsla(var(--pc)/var(--tw-text-opacity,1))}.menu li.disabled>a:hover,.menu li.disabled>span:hover{background-color:transparent}.\!menu li.\!disabled>a:hover,.\!menu li.\!disabled>span:hover{background-color:transparent!important}.menu li.disabled>a,.menu li.disabled>span{--tw-text-opacity:0.2;color:hsla(var(--bc)/var(--tw-text-opacity,1))}.\!menu li.\!disabled>a,.\!menu li.\!disabled>span{--tw-text-opacity:0.2!important;color:hsla(var(--bc)/var(--tw-text-opacity,1))!important}.menu li.bordered a,.menu li.bordered span{--tw-border-opacity:1;border-color:hsla(var(--p)/var(--tw-border-opacity,1));border-left-width:4px}.menu li.hover-bordered a{border-color:transparent;border-left-width:4px}.menu li.hover-bordered a:hover{--tw-border-opacity:1;border-color:hsla(var(--p)/var(--tw-border-opacity,1))}.menu ul{padding-left:1.5rem}.menu.compact li>a,.menu.compact li>span{font-size:.875rem;line-height:1.25rem;padding-bottom:.5rem;padding-top:.5rem}.\!menu.\!compact li>a,.\!menu.\!compact li>span{font-size:.875rem!important;line-height:1.25rem!important;padding-bottom:.5rem!important;padding-top:.5rem!important}.menu .menu-title>a,.menu .menu-title>span{--tw-text-opacity:0.4;color:hsla(var(--bc)/var(--tw-text-opacity,1));font-size:.75rem;font-weight:700;line-height:1rem;padding-bottom:.25rem;padding-top:.25rem}.mockup-phone .display{border-radius:40px;margin-top:-25px;overflow:hidden}.modal-open .modal-box,.modal-toggle:checked+.modal .modal-box,.modal:target .modal-box{--tw-scale-x:1;--tw-scale-y:1;--tw-translate-y:0px}.progress::-moz-progress-bar{--tw-bg-opacity:1;background-color:hsla(var(--n)/var(--tw-bg-opacity,1))}.progress::-webkit-progress-bar{--tw-bg-opacity:0.2;background-color:hsla(var(--n)/var(--tw-bg-opacity,1));border-radius:var(--rounded-box,1rem)}.progress::-webkit-progress-value{--tw-bg-opacity:1;background-color:hsla(var(--nf)/var(--tw-bg-opacity,1));border-radius:var(--rounded-box,1rem)}.radio{--chkbg:var(--bc);--focus-shadow:0 0 0;--tw-border-opacity:0.2;-webkit-appearance:none;-moz-appearance:none;appearance:none;border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-radius:9999px;border-width:1px;cursor:pointer;height:1.5rem;-webkit-transition:background,-webkit-box-shadow var(--animation-input,.2s) ease-in-out;transition:background,-webkit-box-shadow var(--animation-input,.2s) ease-in-out;transition:background,box-shadow var(--animation-input,.2s) ease-in-out;transition:background,box-shadow var(--animation-input,.2s) ease-in-out,-webkit-box-shadow var(--animation-input,.2s) ease-in-out;width:1.5rem}.radio:focus-visible{--focus-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--bc))}.radio:checked{--tw-bg-opacity:1;-webkit-animation:radiomark var(--animation-input,.2s) ease-in-out;animation:radiomark var(--animation-input,.2s) ease-in-out;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1));-webkit-box-shadow:0 0 0 4px hsl(var(--b1)) inset,0 0 0 4px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 4px hsl(var(--b1)) inset,0 0 0 4px hsl(var(--b1)) inset,var(--focus-shadow)}.radio:disabled{cursor:not-allowed;opacity:.2}@-webkit-keyframes radiomark{0%{-webkit-box-shadow:0 0 0 12px hsl(var(--b1)) inset,0 0 0 12px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 12px hsl(var(--b1)) inset,0 0 0 12px hsl(var(--b1)) inset,var(--focus-shadow)}50%{-webkit-box-shadow:0 0 0 3px hsl(var(--b1)) inset,0 0 0 3px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 3px hsl(var(--b1)) inset,0 0 0 3px hsl(var(--b1)) inset,var(--focus-shadow)}to{-webkit-box-shadow:0 0 0 4px hsl(var(--b1)) inset,0 0 0 4px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 4px hsl(var(--b1)) inset,0 0 0 4px hsl(var(--b1)) inset,var(--focus-shadow)}}@keyframes radiomark{0%{-webkit-box-shadow:0 0 0 12px hsl(var(--b1)) inset,0 0 0 12px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 12px hsl(var(--b1)) inset,0 0 0 12px hsl(var(--b1)) inset,var(--focus-shadow)}50%{-webkit-box-shadow:0 0 0 3px hsl(var(--b1)) inset,0 0 0 3px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 3px hsl(var(--b1)) inset,0 0 0 3px hsl(var(--b1)) inset,var(--focus-shadow)}to{-webkit-box-shadow:0 0 0 4px hsl(var(--b1)) inset,0 0 0 4px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:0 0 0 4px hsl(var(--b1)) inset,0 0 0 4px hsl(var(--b1)) inset,var(--focus-shadow)}}.range:focus-visible::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--range-shdw));box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--range-shdw))}.\!range:focus-visible::-webkit-slider-thumb{-webkit-box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--range-shdw))!important;box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--range-shdw))!important}.range:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--range-shdw))}.\!range:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--range-shdw))!important}.range::-webkit-slider-runnable-track{background-color:hsla(var(--bc)/.1);border-radius:var(--rounded-box,1rem);height:.5rem;width:100%}.\!range::-webkit-slider-runnable-track{background-color:hsla(var(--bc)/.1)!important;border-radius:var(--rounded-box,1rem)!important;height:.5rem!important;width:100%!important}.range::-moz-range-track{background-color:hsla(var(--bc)/.1);border-radius:var(--rounded-box,1rem);height:.5rem;width:100%}.\!range::-moz-range-track{background-color:hsla(var(--bc)/.1)!important;border-radius:var(--rounded-box,1rem)!important;height:.5rem!important;width:100%!important}.range::-webkit-slider-thumb{-webkit-appearance:none;background-color:hsl(var(--range-shdw));border-radius:var(--rounded-box,1rem);border-style:none;height:1.25rem;position:relative;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:all;transition-property:all;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);width:1.25rem}.\!range::-webkit-slider-thumb{-webkit-appearance:none!important;background-color:hsl(var(--range-shdw))!important;border-radius:var(--rounded-box,1rem)!important;border-style:none!important;height:1.25rem!important;position:relative!important;top:50%!important;-webkit-transform:translateY(-50%)!important;transform:translateY(-50%)!important;-webkit-transition-duration:.3s!important;transition-duration:.3s!important;-webkit-transition-property:all!important;transition-property:all!important;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1)!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;width:1.25rem!important}.range::-moz-range-thumb{background-color:hsl(var(--range-shdw));border-radius:var(--rounded-box,1rem);border-style:none;height:1.25rem;position:relative;top:50%;transition-duration:.3s;-moz-transition-property:all;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);width:1.25rem}.\!range::-moz-range-thumb{background-color:hsl(var(--range-shdw))!important;border-radius:var(--rounded-box,1rem)!important;border-style:none!important;height:1.25rem!important;position:relative!important;top:50%!important;transition-duration:.3s!important;-moz-transition-property:all!important;transition-property:all!important;transition-timing-function:cubic-bezier(.4,0,.2,1)!important;width:1.25rem!important}.select-disabled::-webkit-input-placeholder,.select[disabled]::-webkit-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.select-disabled::-moz-placeholder,.select[disabled]::-moz-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.select-disabled:-ms-input-placeholder,.select[disabled]:-ms-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.select-disabled::-ms-input-placeholder,.select[disabled]::-ms-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.select-disabled::placeholder,.select[disabled]::placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.stat+.stat{--tw-border-opacity:0.1;border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-left-width:1px}.\!stat+.\!stat{--tw-border-opacity:0.1!important;border-color:hsla(var(--bc)/var(--tw-border-opacity,1))!important;border-left-width:1px!important}.stats.grid-flow-row .stat+.stat{border-left-width:0;border-top-width:1px}.\!stats.\!grid-flow-row .\!stat+.\!stat{border-left-width:0!important;border-top-width:1px!important}.steps .step:before{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1));color:hsla(var(--bc)/var(--tw-text-opacity,1));content:"";grid-column-start:1;grid-row-start:1;height:.5rem;margin-left:-100%;top:0;width:100%}.\!steps .\!step:before{--tw-bg-opacity:1!important;--tw-text-opacity:1!important;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1))!important;color:hsla(var(--bc)/var(--tw-text-opacity,1))!important;content:""!important;grid-column-start:1!important;grid-row-start:1!important;height:.5rem!important;margin-left:-100%!important;top:0!important;width:100%!important}.steps .step:after{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1));border-radius:9999px;color:hsla(var(--bc)/var(--tw-text-opacity,1));content:counter(step);counter-increment:step;display:block;display:grid;grid-column-start:1;grid-row-start:1;height:2rem;place-items:center;place-self:center;position:relative;width:2rem;z-index:1}.\!steps .\!step:after{--tw-bg-opacity:1!important;--tw-text-opacity:1!important;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1))!important;border-radius:9999px!important;color:hsla(var(--bc)/var(--tw-text-opacity,1))!important;content:counter(step)!important;counter-increment:step!important;display:block!important;display:grid!important;grid-column-start:1!important;grid-row-start:1!important;height:2rem!important;place-items:center!important;place-self:center!important;position:relative!important;width:2rem!important;z-index:1!important}.steps .step:first-child:before{content:none}.\!steps .\!step:first-child:before{content:none!important}.steps .step[data-content]:after{content:attr(data-content)}.\!steps .\!step[data-content]:after{content:attr(data-content)!important}.steps .step-neutral+.step-neutral:before,.steps .step-neutral:after{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--n)/var(--tw-bg-opacity,1));color:hsla(var(--nc)/var(--tw-text-opacity,1))}.steps .step-primary+.step-primary:before,.steps .step-primary:after{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--p)/var(--tw-bg-opacity,1));color:hsla(var(--pc)/var(--tw-text-opacity,1))}.steps .step-secondary+.step-secondary:before,.steps .step-secondary:after{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--s)/var(--tw-bg-opacity,1));color:hsla(var(--sc)/var(--tw-text-opacity,1))}.steps .step-accent+.step-accent:before,.steps .step-accent:after{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--a)/var(--tw-bg-opacity,1));color:hsla(var(--ac)/var(--tw-text-opacity,1))}.steps .step-info+.step-info:before,.steps .step-info:after{--tw-bg-opacity:1;background-color:hsla(var(--in)/var(--tw-bg-opacity,1))}.steps .step-info:after{--tw-text-opacity:1;color:hsla(var(--b1)/var(--tw-text-opacity,1))}.steps .step-success+.step-success:before,.steps .step-success:after{--tw-bg-opacity:1;background-color:hsla(var(--su)/var(--tw-bg-opacity,1))}.steps .step-success:after{--tw-text-opacity:1;color:hsla(var(--b1)/var(--tw-text-opacity,1))}.steps .step-warning+.step-warning:before,.steps .step-warning:after{--tw-bg-opacity:1;background-color:hsla(var(--wa)/var(--tw-bg-opacity,1))}.steps .step-warning:after{--tw-text-opacity:1;color:hsla(var(--b1)/var(--tw-text-opacity,1))}.steps .step-error+.step-error:before,.steps .step-error:after{--tw-bg-opacity:1;background-color:hsla(var(--er)/var(--tw-bg-opacity,1))}.steps .step-error:after{--tw-text-opacity:1;color:hsla(var(--b1)/var(--tw-text-opacity,1))}.steps-vertical .step:before{--tw-translate-x:0;--tw-translate-x:-50%;--tw-translate-y:0;--tw-translate-y:-50%;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;height:100%;margin-left:50%;top:0;-webkit-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));width:.5rem}.\!steps-vertical .\!step:before{--tw-translate-x:0!important;--tw-translate-x:-50%!important;--tw-translate-y:0!important;--tw-translate-y:-50%!important;--tw-rotate:0!important;--tw-skew-x:0!important;--tw-skew-y:0!important;--tw-scale-x:1!important;--tw-scale-y:1!important;height:100%!important;margin-left:50%!important;top:0!important;-webkit-transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important;transform:translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important;width:.5rem!important}.tab:hover{--tw-text-opacity:1}.tab.tab-active{--tw-border-opacity:1;--tw-text-opacity:1;border-color:hsla(var(--bc)/var(--tw-border-opacity,1));color:hsla(var(--bc)/var(--tw-text-opacity,1))}.tab:focus{outline:2px solid transparent;outline-offset:2px}.tab:focus-visible{-webkit-box-shadow:inset 0 0 0 2px currentColor;box-shadow:inset 0 0 0 2px currentColor}.tab-lifted{border:0 solid transparent;border-bottom:var(--tab-border,1px) solid hsla(var(--border-color,var(--b3))/var(--tw-border-opacity,1));border-top-left-radius:var(--tab-radius,.5rem);border-top-right-radius:var(--tab-radius,.5rem);padding-left:var(--tab-padding,1rem);padding-right:var(--tab-padding,1rem);padding-top:var(--tab-border,1px)}.tab-lifted.tab-active{--tw-bg-opacity:1;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1));border-bottom-width:0;border-left-color:hsla(var(--border-color,var(--b3))/var(--tw-border-opacity,1));border-left-width:var(--tab-border,1px);border-right-color:hsla(var(--border-color,var(--b3))/var(--tw-border-opacity,1));border-right-width:var(--tab-border,1px);border-top-color:hsla(var(--border-color,var(--b3))/var(--tw-border-opacity,1));border-top-width:var(--tab-border,1px);padding-bottom:var(--tab-border,1px);padding-left:calc(var(--tab-padding, 1rem) - var(--tab-border, 1px));padding-right:calc(var(--tab-padding, 1rem) - var(--tab-border, 1px));padding-top:0}.tab-lifted.tab-active:after,.tab-lifted.tab-active:before{--tab-grad:calc(68% - var(--tab-border, 1px));--tab-corner-bg:radial-gradient(circle at var(--circle-pos),transparent var(--tab-grad),hsla(var(--border-color,var(--b3))/var(--tw-border-opacity,1)) calc(var(--tab-grad) + 0.3px),hsla(var(--border-color,var(--b3))/var(--tw-border-opacity,1)) calc(var(--tab-grad) + var(--tab-border, 1px)),hsla(var(--b1)/var(--tw-border-opacity,1)) calc(var(--tab-grad) + var(--tab-border, 1px) + 0.3px));bottom:0;content:"";display:block;height:var(--tab-radius,.5rem);position:absolute;width:var(--tab-radius,.5rem);z-index:1}.tab-lifted.tab-active:before{--circle-pos:top left;background-image:var(--tab-corner-bg);left:calc(var(--tab-radius, .5rem)*-1)}[dir=rtl] .tab-lifted.tab-active:before{--circle-pos:top right}.tab-lifted.tab-active:after{--circle-pos:top right;background-image:var(--tab-corner-bg);right:calc(var(--tab-radius, .5rem)*-1)}[dir=rtl] .tab-lifted.tab-active:after{--circle-pos:top left}.tab-lifted.tab-active+.tab-lifted.tab-active:before,.tab-lifted.tab-active:first-child:before,.tab-lifted.tab-active:last-child:after{background:none}.tabs-boxed .tab-active{--tw-bg-opacity:1;background-color:hsla(var(--p)/var(--tw-bg-opacity,1));border-radius:var(--rounded-btn,.5rem)}.tabs-boxed .tab-active,.tabs-boxed .tab-active:hover{--tw-text-opacity:1;color:hsla(var(--pc)/var(--tw-text-opacity,1))}.table td,.table th{padding:1rem;vertical-align:middle;white-space:nowrap}.\!table td,.\!table th{padding:1rem!important;vertical-align:middle!important;white-space:nowrap!important}.table tr.active:nth-child(2n) td,.table tr.active:nth-child(2n) th,.table tr.active td,.table tr.active th{--tw-bg-opacity:1;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1))}.\!table tr.\!active:nth-child(2n) td,.\!table tr.\!active:nth-child(2n) th,.\!table tr.\!active td,.\!table tr.\!active th{--tw-bg-opacity:1!important;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1))!important}.table tr.hover:hover td,.table tr.hover:hover th,.table tr.hover:nth-child(2n):hover td,.table tr.hover:nth-child(2n):hover th{--tw-bg-opacity:1;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1))}.\!table tr.\!hover:hover td,.\!table tr.\!hover:hover th,.\!table tr.\!hover:nth-child(2n):hover td,.\!table tr.\!hover:nth-child(2n):hover th{--tw-bg-opacity:1!important;background-color:hsla(var(--b3)/var(--tw-bg-opacity,1))!important}.table:not(.table-zebra) tbody tr:not(:last-child) td,.table:not(.table-zebra) tbody tr:not(:last-child) th,.table:not(.table-zebra) tfoot tr:not(:last-child) td,.table:not(.table-zebra) tfoot tr:not(:last-child) th,.table:not(.table-zebra) thead tr:not(:last-child) td,.table:not(.table-zebra) thead tr:not(:last-child) th{--tw-border-opacity:1;border-bottom-width:1px;border-color:hsla(var(--b2)/var(--tw-border-opacity,1))}.\!table:not(.\!table-zebra) tbody tr:not(:last-child) td,.\!table:not(.\!table-zebra) tbody tr:not(:last-child) th,.\!table:not(.\!table-zebra) tfoot tr:not(:last-child) td,.\!table:not(.\!table-zebra) tfoot tr:not(:last-child) th,.\!table:not(.\!table-zebra) thead tr:not(:last-child) td,.\!table:not(.\!table-zebra) thead tr:not(:last-child) th{--tw-border-opacity:1!important;border-bottom-width:1px!important;border-color:hsla(var(--b2)/var(--tw-border-opacity,1))!important}.table tfoot td,.table tfoot th,.table thead td,.table thead th{--tw-bg-opacity:1;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1));font-size:.75rem;font-weight:700;line-height:1rem;text-transform:uppercase}.\!table tfoot td,.\!table tfoot th,.\!table thead td,.\!table thead th{--tw-bg-opacity:1!important;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1))!important;font-size:.75rem!important;font-weight:700!important;line-height:1rem!important;text-transform:uppercase!important}.table tfoot td:first-child,.table tfoot th:first-child,.table thead td:first-child,.table thead th:first-child{border-bottom-left-radius:.5rem;border-top-left-radius:.5rem}.\!table tfoot td:first-child,.\!table tfoot th:first-child,.\!table thead td:first-child,.\!table thead th:first-child{border-bottom-left-radius:.5rem!important;border-top-left-radius:.5rem!important}.table tfoot td:last-child,.table tfoot th:last-child,.table thead td:last-child,.table thead th:last-child{border-bottom-right-radius:.5rem;border-top-right-radius:.5rem}.\!table tfoot td:last-child,.\!table tfoot th:last-child,.\!table thead td:last-child,.\!table thead th:last-child{border-bottom-right-radius:.5rem!important;border-top-right-radius:.5rem!important}.table tbody td,.table tbody th{--tw-bg-opacity:1;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1))}.\!table tbody td,.\!table tbody th{--tw-bg-opacity:1!important;background-color:hsla(var(--b1)/var(--tw-bg-opacity,1))!important}.textarea-bordered{--tw-border-opacity:0.2}.textarea-disabled,.textarea[disabled]{--tw-bg-opacity:1;--tw-border-opacity:1;--tw-text-opacity:0.2;background-color:hsla(var(--b2)/var(--tw-bg-opacity,1));border-color:hsla(var(--b2)/var(--tw-border-opacity,1));cursor:not-allowed}.textarea-disabled::-webkit-input-placeholder,.textarea[disabled]::-webkit-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.textarea-disabled::-moz-placeholder,.textarea[disabled]::-moz-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.textarea-disabled:-ms-input-placeholder,.textarea[disabled]:-ms-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.textarea-disabled::-ms-input-placeholder,.textarea[disabled]::-ms-input-placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.textarea-disabled::placeholder,.textarea[disabled]::placeholder{--tw-placeholder-opacity:0.2;color:hsla(var(--bc)/var(--tw-placeholder-opacity,1))}.toggle{--chkbg:hsla(var(--bc)/.2);--focus-shadow:0 0 0;--handleoffset:1.5rem;--tw-bg-opacity:0.2;--tw-border-opacity:0.2;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1));border-color:hsla(var(--bc)/var(--tw-border-opacity,1));border-radius:var(--rounded-badge,1.9rem);border-width:1px;-webkit-box-shadow:calc(var(--handleoffset)*-1) 0 0 2px hsl(var(--b1)) inset,0 0 0 2px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:calc(var(--handleoffset)*-1) 0 0 2px hsl(var(--b1)) inset,0 0 0 2px hsl(var(--b1)) inset,var(--focus-shadow);cursor:pointer;height:1.5rem;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1);-webkit-transition:background,-webkit-box-shadow var(--animation-input,.2s) ease-in-out;transition:background,-webkit-box-shadow var(--animation-input,.2s) ease-in-out;transition:background,box-shadow var(--animation-input,.2s) ease-in-out;transition:background,box-shadow var(--animation-input,.2s) ease-in-out,-webkit-box-shadow var(--animation-input,.2s) ease-in-out;width:3rem}.toggle:focus-visible{--focus-shadow:0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--bc))}.toggle:checked{--chkbg:hsl(var(--bc));--tw-bg-opacity:1;--tw-border-opacity:1;-webkit-box-shadow:var(--handleoffset) 0 0 2px hsl(var(--b1)) inset,0 0 0 2px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:var(--handleoffset) 0 0 2px hsl(var(--b1)) inset,0 0 0 2px hsl(var(--b1)) inset,var(--focus-shadow)}[dir=rtl] .toggle:checked{-webkit-box-shadow:calc(var(--handleoffset)*1) 0 0 2px hsl(var(--b1)) inset,0 0 0 2px hsl(var(--b1)) inset,var(--focus-shadow);box-shadow:calc(var(--handleoffset)*1) 0 0 2px hsl(var(--b1)) inset,0 0 0 2px hsl(var(--b1)) inset,var(--focus-shadow)}.toggle:disabled{--tw-bg-opacity:0.2;background-color:hsla(var(--bc)/var(--tw-bg-opacity,1));border-color:transparent;cursor:not-allowed}.prose .lead,.prose .lead:hover,.prose a,.prose a:hover,.prose a code,.prose a code:hover,.prose blockquote,.prose blockquote:hover,.prose figure figcaption,.prose figure figcaption:hover,.prose h1,.prose h1:hover,.prose h2,.prose h2:hover,.prose h3,.prose h3:hover,.prose h4,.prose h4:hover,.prose strong,.prose strong:hover,.prose thead,.prose thead:hover{color:inherit}.glass,.glass.btn-active,.glass:hover{-webkit-backdrop-filter:blur(var(--glass-blur,40px));backdrop-filter:blur(var(--glass-blur,40px));background-color:transparent;background-image:linear-gradient(135deg,rgb(255 255 255/var(--glass-opacity,30%)),transparent),linear-gradient(var(--glass-reflex-degree,100deg),rgb(255 255 255/var(--glass-reflex-opacity,10%)) 25%,transparent 0);border:none;-webkit-box-shadow:0 0 0 1px rgb(255 255 255/var(--glass-border-opacity,10%)) inset,0 0 0 2px rgba(0,0,0,.05);box-shadow:0 0 0 1px rgb(255 255 255/var(--glass-border-opacity,10%)) inset,0 0 0 2px rgba(0,0,0,.05);text-shadow:0 1px rgb(0 0 0/var(--glass-text-shadow-opacity,5%))}.tab-border-none{--tab-border:0px}.artboard.phone{width:320px}.artboard.phone-1.horizontal{height:320px;width:568px}.artboard.phone-2.horizontal{height:375px;width:667px}.artboard.phone-3.horizontal{height:414px;width:736px}.artboard.phone-4.horizontal{height:375px;width:812px}.artboard.phone-5.horizontal{height:414px;width:896px}.artboard.phone-6.horizontal{height:320px;width:1024px}.tab-lg{--tab-padding:1.25rem;font-size:1.125rem;height:3rem;line-height:1.75rem;line-height:2}.avatar.online:before{background-color:hsla(var(--su)/var(--tw-bg-opacity,1));border-radius:9999px;-webkit-box-shadow:0 0 0 2px hsl(var(--b1));box-shadow:0 0 0 2px hsl(var(--b1));content:"";display:block;height:15%;position:absolute;right:7%;top:7%;width:15%;z-index:10}.avatar.online:before,.badge-accent{--tw-bg-opacity:1}.badge-accent{--tw-border-opacity:1;--tw-text-opacity:1;background-color:hsla(var(--a)/var(--tw-bg-opacity,1));border-color:hsla(var(--a)/var(--tw-border-opacity,1));color:hsla(var(--ac)/var(--tw-text-opacity,1))}.badge-outline.badge-accent{--tw-text-opacity:1;color:hsla(var(--a)/var(--tw-text-opacity,1))}.visible{visibility:visible}.\!visible{visibility:visible!important}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.\!relative{position:relative!important}.sticky{position:sticky}.col-span-12{grid-column:span 12/span 12}.row-span-3{grid-row:span 3/span 3}.m-1{margin:.25rem}.mx-auto{margin-left:auto;margin-right:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.mt-0{margin-top:0}.mb-0{margin-bottom:0}.mr-0{margin-right:0}.ml-0{margin-left:0}.mt-12{margin-top:3rem}.mb-12{margin-bottom:3rem}.mt-4{margin-top:1rem}.mr-6{margin-right:1.5rem}.mt-8{margin-top:2rem}.mb-6{margin-bottom:1.5rem}.block{display:block}.\!block{display:block!important}.inline-block{display:inline-block}.inline{display:inline}.flex{display:-webkit-box;display:-ms-flexbox;display:flex}.table{display:table}.\!table{display:table!important}.table-row{display:table-row}.grid{display:grid}.contents{display:contents}.\!contents{display:contents!important}.hidden{display:none}.\!hidden{display:none!important}.h-64{height:16rem}.h-48{height:12rem}.h-6{height:1.5rem}.h-1{height:.25rem}.h-2{height:.5rem}.max-h-screen{max-height:100vh}.w-full{width:100%}.w-6{width:1.5rem}.max-w-screen-sm{max-width:640px}.max-w-screen-xl{max-width:1280px}.flex-1{-webkit-box-flex:1;-ms-flex:1 1 0%;flex:1 1 0%}.flex-shrink-0{-ms-flex-negative:0;flex-shrink:0}.flex-shrink,.shrink{-ms-flex-negative:1;flex-shrink:1}.flex-grow-0{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.flex-grow,.grow{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.border-collapse{border-collapse:collapse}.transform{-webkit-transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-flow-row{grid-auto-flow:row}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.flex-col{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.flex-wrap{-ms-flex-wrap:wrap;flex-wrap:wrap}.items-center{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.justify-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.gap-4{gap:1rem}.gap-3{gap:.75rem}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(.5rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(.5rem*var(--tw-space-x-reverse))}.space-x-4>:not([hidden])~:not([hidden]){--tw-space-x-reverse:0;margin-left:calc(1rem*(1 - var(--tw-space-x-reverse)));margin-right:calc(1rem*var(--tw-space-x-reverse))}.overflow-y-hidden{overflow-y:hidden}.overflow-x-scroll{overflow-x:scroll}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded-xl{border-radius:.75rem}.rounded{border-radius:.25rem}.rounded-tl-none{border-top-left-radius:0}.border-2{border-width:2px}.border{border-width:1px}.border-dashed{border-style:dashed}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.bg-base-100{--tw-bg-opacity:1;background-color:hsla(var(--b1)/var(--tw-bg-opacity))}.p-6{padding:1.5rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-8{padding:2rem}.p-14{padding:3.5rem}.p-16{padding:4rem}.px-10{padding-left:2.5rem;padding-right:2.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-1{padding-top:.25rem}.pb-10{padding-bottom:2.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.font-extrabold{font-weight:800}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.text-base-content{--tw-text-opacity:1;color:hsla(var(--bc)/var(--tw-text-opacity))}.text-opacity-60{--tw-text-opacity:0.6}.text-opacity-40{--tw-text-opacity:0.4}.underline{-webkit-text-decoration-line:underline;text-decoration-line:underline}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color)}.shadow,.shadow-xl{-webkit-box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.outline{outline-style:solid}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);-webkit-box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.blur{--tw-blur:blur(8px)}.blur,.grayscale{-webkit-filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.grayscale{--tw-grayscale:grayscale(100%)}.invert{--tw-invert:invert(100%)}.filter,.invert{-webkit-filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.\!filter{-webkit-filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important;filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)!important}.transition{-webkit-transition-duration:.15s;transition-duration:.15s;-webkit-transition-property:color,background-color,border-color,fill,stroke,opacity,-webkit-text-decoration-color,-webkit-box-shadow,-webkit-transform,-webkit-filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,fill,stroke,opacity,-webkit-text-decoration-color,-webkit-box-shadow,-webkit-transform,-webkit-filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-text-decoration-color,-webkit-box-shadow,-webkit-transform,-webkit-filter,-webkit-backdrop-filter;-webkit-transition-timing-function:cubic-bezier(.4,0,.2,1);transition-timing-function:cubic-bezier(.4,0,.2,1)}.\[http\:\/\/zlib\.net\/manual\.html\#Advanced\]{http://zlib.net/manual.html#Advanced}@media (min-width:1280px){.xl\:rounded-box{border-radius:var(--rounded-box,1rem)}.xl\:grid{display:grid}.xl\:overflow-x-auto{overflow-x:auto}.xl\:overflow-x-hidden{overflow-x:hidden}.xl\:px-4{padding-left:1rem;padding-right:1rem}} -------------------------------------------------------------------------------- /assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 24 |
25 |
26 |
27 |
28 |
29 |
30 |
Drop a png file here
31 |
Embedded source code will be displayed.
32 |
33 |
34 |
35 |
36 |
Embedded Code
37 |
38 | 40 |
41 |
42 | 138 |
139 |
140 |
141 |
142 |
143 | 407 | 408 | 409 | -------------------------------------------------------------------------------- /assets/main.js: -------------------------------------------------------------------------------- 1 | import 'core-js/stable'; 2 | const runtime = require('@wailsapp/runtime'); 3 | 4 | // Main entry point 5 | function start() { 6 | 7 | }; 8 | 9 | // We provide our entrypoint as a callback for runtime.Init 10 | runtime.Init(start); 11 | -------------------------------------------------------------------------------- /assets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vanilla", 3 | "author": "Lea", 4 | "private": true, 5 | "scripts": { 6 | "serve": "webpack-dev-server", 7 | "build": "npx webpack" 8 | }, 9 | "dependencies": { 10 | "core-js": "^3.6.4", 11 | "regenerator-runtime": "^0.13.3", 12 | "@wailsapp/runtime": "^1.0.10" 13 | }, 14 | "devDependencies": { 15 | "babel-eslint": "^10.1.0", 16 | "copy-webpack-plugin": "^6.0.2", 17 | "eslint": "^6.8.0", 18 | "eventsource-polyfill": "^0.9.6", 19 | "webpack": "^4.43.0", 20 | "webpack-cli": "^3.3.11", 21 | "webpack-dev-server": "^3.11.0", 22 | "webpack-hot-middleware": "^2.25.0" 23 | }, 24 | "eslintConfig": { 25 | "root": true, 26 | "env": { 27 | "node": true 28 | }, 29 | "extends": [ 30 | "eslint:recommended" 31 | ], 32 | "rules": {}, 33 | "parserOptions": { 34 | "parser": "babel-eslint" 35 | } 36 | }, 37 | "browserslist": [ 38 | "> 1%", 39 | "last 2 versions", 40 | "not ie <= 8" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /assets/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 3 | 4 | let imageSizeLimit = 9007199254740991; // Number.MAX_SAFE_INTEGER 5 | let sourceDir = path.resolve(__dirname); 6 | let buildDir = path.resolve(__dirname, 'build'); 7 | 8 | module.exports = { 9 | entry: { 10 | index: path.resolve(sourceDir, 'main.js') 11 | }, 12 | output: { 13 | path: buildDir, 14 | filename: 'main.js' 15 | }, 16 | optimization: { 17 | splitChunks: false 18 | }, 19 | devServer: { 20 | disableHostCheck: true, 21 | contentBase: path.join(__dirname), 22 | compress: true, 23 | open: true, 24 | port: 8090 25 | }, 26 | mode: 'production', 27 | module: { 28 | rules: [ 29 | { 30 | test: /\.(png|gif|jpg|woff2?|eot|ttf|otf|svg)(\?.*)?$/i, 31 | use: [ 32 | { 33 | loader: 'url-loader', 34 | options: { 35 | limit: imageSizeLimit 36 | } 37 | } 38 | ], 39 | } 40 | ] 41 | }, 42 | plugins: [ 43 | new CopyWebpackPlugin({ 44 | patterns: [ 45 | { 46 | from: path.resolve(sourceDir, 'css/style.css'), 47 | to: path.resolve(buildDir, 'css/style.css') 48 | }, 49 | { 50 | from: path.resolve(sourceDir, 'index.html'), 51 | to: path.resolve(buildDir, 'index.html') 52 | }, 53 | ] 54 | }) 55 | ] 56 | }; 57 | -------------------------------------------------------------------------------- /cmd/pngsource.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/fusion/pngsource/lib" 11 | ) 12 | 13 | var Version = "unspecified" 14 | 15 | func setConfig(l *log.Logger) (*lib.Config, error) { 16 | config := &lib.Config{Display: true} 17 | fs := flag.NewFlagSet(filepath.Base(os.Args[0]), flag.ExitOnError) 18 | fs.BoolVar(&config.Verbose, "verbose", false, "Verbose display") 19 | fs.BoolVar(&config.Verbose, "v", false, "Verbose display") 20 | fs.BoolVar(&config.ReWriteCRC, "crc", false, "Write newly computed CRC values") 21 | fs.BoolVar(&config.ReWriteCRC, "c", false, "Write newly computed CRC values") 22 | fs.BoolVar(&config.Lenient, "lenient", false, "Do not reject incorrect CRC values") 23 | fs.BoolVar(&config.Lenient, "l", false, "Do not reject incorrect CRC values") 24 | fs.BoolVar(&config.Overwrite, "overwrite", false, "Allow overwriting previous embed if present") 25 | fs.BoolVar(&config.Overwrite, "o", false, "Allow overwriting previous embed if present") 26 | fs.BoolVar(&config.InPlace, "inplace", false, "When embedding, embed in current image (no 'to' file)") 27 | fs.BoolVar(&config.InPlace, "i", false, "When embedding, embed in current image (no 'to' file)") 28 | fs.StringVar(&config.ActionRead, "read", "", "Read image's embedded code (use '-' for stdin)") 29 | fs.StringVar(&config.ActionRead, "r", "", "Read image's embedded code (use '-' for stdin)") 30 | fs.StringVar(&config.ActionEmbed, "embed", "", "Embed code in image") 31 | fs.StringVar(&config.ActionEmbed, "e", "", "Embed code in image") 32 | fs.StringVar(&config.SourceFile, "source", "", "File containing code to embed") 33 | fs.StringVar(&config.SourceFile, "s", "", "File containing code to embed") 34 | fs.StringVar(&config.DestFile, "to", "", "New file to be created with embedded code (use '-' for stdout)") 35 | fs.Usage = func() { 36 | w := flag.CommandLine.Output() 37 | fmt.Fprintf(w, "\n%s version %s\n", filepath.Base(os.Args[0]), Version) 38 | fmt.Fprintf(w, "Usage:\n\n") 39 | fs.PrintDefaults() 40 | fmt.Fprintln(w, "\nExamples:\n") 41 | fmt.Fprintf(w, "> %s --embed --source --to \n", os.Args[0]) 42 | fmt.Fprintf(w, "> cat | %s --embed - --source --to \n", os.Args[0]) 43 | fmt.Fprintf(w, "> %s --read --verbose\n", os.Args[0]) 44 | } 45 | 46 | err := fs.Parse(os.Args[1:]) 47 | if err != nil { 48 | return nil, err 49 | } 50 | if config.ActionRead != "" && config.ActionEmbed != "" { 51 | l.Fatal("You cannot provide both and read and an embed action.") 52 | } 53 | if config.ActionRead == "" && config.ActionEmbed == "" { 54 | l.Fatal("Please specify a '--read' or '--embed' action (or --help)") 55 | } 56 | if config.ActionEmbed != "" && config.SourceFile == "" { 57 | l.Fatal("You must specify a '--source' file to perform a '--embed' action.") 58 | } 59 | if config.ActionEmbed != "" && config.DestFile == "" && !config.InPlace { 60 | l.Fatal("You must specify a '--to' file or '--inplace' when embedding.") 61 | } 62 | if config.DestFile != "" && config.InPlace { 63 | l.Fatal("You cannot specify '--inplace' and a '--to' file together.") 64 | } 65 | return config, nil 66 | } 67 | 68 | func main() { 69 | l := log.New(os.Stderr, "", 0) 70 | config, err := setConfig(l) 71 | if err != nil { 72 | println(err) 73 | return 74 | } 75 | if config.ActionRead != "" { 76 | lib.Read_content(l, config) 77 | } 78 | if config.ActionEmbed != "" { 79 | lib.Write_content(l, config) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/fusion/pngsource 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/ncruces/zenity v0.7.12 7 | github.com/rakyll/globalconf v0.0.0-20180912185831-87f8127c421f 8 | github.com/wailsapp/wails v1.16.9 9 | github.com/webview/webview v0.0.0-20210330151455-f540d88dde4e 10 | ) 11 | 12 | require ( 13 | github.com/Masterminds/semver v1.4.2 // indirect 14 | github.com/abadojack/whatlanggo v1.0.1 // indirect 15 | github.com/akavel/rsrc v0.10.2 // indirect 16 | github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 // indirect 17 | github.com/fatih/color v1.7.0 // indirect 18 | github.com/glacjay/goini v0.0.0-20161120062552-fd3024d87ee2 // indirect 19 | github.com/go-playground/colors v1.2.0 // indirect 20 | github.com/gorilla/websocket v1.4.1 // indirect 21 | github.com/jackmordaunt/icns v1.0.0 // indirect 22 | github.com/josephspurrier/goversioninfo v1.3.0 // indirect 23 | github.com/kennygrant/sanitize v1.2.4 // indirect 24 | github.com/leaanthony/slicer v1.4.0 // indirect 25 | github.com/leaanthony/spinner v0.5.3 // indirect 26 | github.com/leaanthony/synx v0.1.0 // indirect 27 | github.com/leaanthony/wincursor v0.1.0 // indirect 28 | github.com/mattn/go-colorable v0.1.1 // indirect 29 | github.com/mattn/go-isatty v0.0.7 // indirect 30 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect 31 | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 // indirect 32 | github.com/pkg/errors v0.8.1 // indirect 33 | github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844 // indirect 34 | github.com/sirupsen/logrus v1.8.1 // indirect 35 | github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba // indirect 36 | golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect 37 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect 38 | golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect 39 | golang.org/x/text v0.3.6 // indirect 40 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect 41 | ) 42 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= 2 | github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= 3 | github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= 4 | github.com/abadojack/whatlanggo v1.0.1 h1:19N6YogDnf71CTHm3Mp2qhYfkRdyvbgwWdd2EPxJRG4= 5 | github.com/abadojack/whatlanggo v1.0.1/go.mod h1:66WiQbSbJBIlOZMsvbKe5m6pzQovxCH9B/K8tQB2uoc= 6 | github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw= 7 | github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947 h1:Fm10/KNuoAyBm2P5P5H91Xy21hGcZnBdjR+cMdytv1M= 12 | github.com/dchest/jsmin v0.0.0-20160823214000-faeced883947/go.mod h1:Dv9D0NUlAsaQcGQZa5kc5mqR9ua72SmA8VXi4cd+cBw= 13 | github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= 14 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 15 | github.com/glacjay/goini v0.0.0-20161120062552-fd3024d87ee2 h1:+SEORW3KptcFnlhTbn7N0drG3AFnrcmBDWDyQ3Bt06o= 16 | github.com/glacjay/goini v0.0.0-20161120062552-fd3024d87ee2/go.mod h1:1vW2LGZb8uLSqmYBOdxvhiwATuLtmyUTMezM3cHrIHQ= 17 | github.com/go-playground/colors v1.2.0 h1:0EdjTXKrr2g1L/LQTYtIqabeHpZuGZz1U4osS1T8+5M= 18 | github.com/go-playground/colors v1.2.0/go.mod h1:miw1R2JIE19cclPxsXqNdzLZsk4DP4iF+m88bRc7kfM= 19 | github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= 20 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 21 | github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= 22 | github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ= 23 | github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo= 24 | github.com/josephspurrier/goversioninfo v1.3.0 h1:pmgDhWnG8I59p5kCR09J73s/gy9JqRPAtiaUK8jixtE= 25 | github.com/josephspurrier/goversioninfo v1.3.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY= 26 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= 27 | github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= 28 | github.com/kennygrant/sanitize v1.2.4/go.mod h1:LGsjYYtgxbetdg5owWB2mpgUL6e2nfw2eObZ0u0qvak= 29 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 30 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 31 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 32 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 33 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 34 | github.com/leaanthony/slicer v1.4.0 h1:Q9u4w+UBU4WHjXnEDdz+eRLMKF/rnyosRBiqULnc1J8= 35 | github.com/leaanthony/slicer v1.4.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= 36 | github.com/leaanthony/spinner v0.5.3 h1:IMTvgdQCec5QA4qRy0wil4XsRP+QcG1OwLWVK/LPZ5Y= 37 | github.com/leaanthony/spinner v0.5.3/go.mod h1:oHlrvWicr++CVV7ALWYi+qHk/XNA91D9IJ48IqmpVUo= 38 | github.com/leaanthony/synx v0.1.0 h1:R0lmg2w6VMb8XcotOwAe5DLyzwjLrskNkwU7LLWsyL8= 39 | github.com/leaanthony/synx v0.1.0/go.mod h1:Iz7eybeeG8bdq640iR+CwYb8p+9EOsgMWghkSRyZcqs= 40 | github.com/leaanthony/wincursor v0.1.0 h1:Dsyp68QcF5cCs65AMBmxoYNEm0n8K7mMchG6a8fYxf8= 41 | github.com/leaanthony/wincursor v0.1.0/go.mod h1:7TVwwrzSH/2Y9gLOGH+VhA+bZhoWXBRgbGNTMk+yimE= 42 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 43 | github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= 44 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= 45 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 46 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 47 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 48 | github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= 49 | github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 50 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= 51 | github.com/ncruces/zenity v0.7.12 h1:NITUYXHby0Wlb+4lWsBs53U4n8hGqDPrnyxuHT1geHs= 52 | github.com/ncruces/zenity v0.7.12/go.mod h1:218cld52IfyQ5Mkdt/koDUBSz93sM81DZ3OQNkj8o+c= 53 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= 54 | github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= 55 | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 h1:49lOXmGaUpV9Fz3gd7TFZY106KVlPVa5jcYD1gaQf98= 56 | github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= 57 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 58 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 59 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 60 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 61 | github.com/rakyll/globalconf v0.0.0-20180912185831-87f8127c421f h1:mVzXRrAR2ipnx3pWDsbWz9Y7+EC+I96EBellUayAyBU= 62 | github.com/rakyll/globalconf v0.0.0-20180912185831-87f8127c421f/go.mod h1:lvWGGAzNhA3ux6f0tkwQ94lLT69Nj/wTRg9781V7M3M= 63 | github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844 h1:GranzK4hv1/pqTIhMTXt2X8MmMOuH3hMeUR0o9SP5yc= 64 | github.com/randall77/makefat v0.0.0-20210315173500-7ddd0e42c844/go.mod h1:T1TLSfyWVBRXVGzWd0o9BI4kfoO9InEgfQe4NV3mLz8= 65 | github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= 66 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 67 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 68 | github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 69 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 70 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 71 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 72 | github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 73 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 74 | github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0= 75 | github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk= 76 | github.com/wailsapp/wails v1.16.9 h1:H0jWILvWU1I3y2MgqwIPjMfD95/nQP9qAuqAsadYaOs= 77 | github.com/wailsapp/wails v1.16.9/go.mod h1:R4AAEWp6K4c0nIMHj5jmr+WQ4yXTfzLXbQoXbg2vEHM= 78 | github.com/webview/webview v0.0.0-20210330151455-f540d88dde4e h1:z780M7mCrdt6KiICeW9SGirvQjxDlrVU+n99FO93nbI= 79 | github.com/webview/webview v0.0.0-20210330151455-f540d88dde4e/go.mod h1:rpXAuuHgyEJb6kXcXldlkOjU6y4x+YcASKKXJNUhh0Y= 80 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 81 | go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= 82 | go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 83 | golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 84 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 85 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 86 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 87 | golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 88 | golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= 89 | golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= 90 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 91 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 92 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 93 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 94 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 95 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 96 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 97 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 98 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= 99 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 100 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 101 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 102 | golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 103 | golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 104 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 105 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 106 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 107 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 108 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 109 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 110 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 111 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 112 | golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 113 | golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik= 114 | golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 115 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 116 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 117 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 118 | golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= 119 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 120 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 121 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 122 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 123 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 124 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 125 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 126 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 127 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 128 | gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= 129 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 130 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 131 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 132 | gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 133 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= 134 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 135 | -------------------------------------------------------------------------------- /lib/pnghandler.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "bytes" 5 | "compress/flate" 6 | "encoding/base64" 7 | "encoding/binary" 8 | "fmt" 9 | "hash/crc32" 10 | "io" 11 | "io/ioutil" 12 | "log" 13 | "net/url" 14 | "os" 15 | "strings" 16 | "time" 17 | ) 18 | 19 | var PNGHEADERSTR = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A" 20 | 21 | type Config struct { 22 | Verbose bool 23 | ReWriteCRC bool 24 | Lenient bool 25 | Overwrite bool 26 | InPlace bool 27 | Display bool 28 | 29 | ActionRead string 30 | ActionEmbed string 31 | SourceFile string 32 | DestFile string 33 | } 34 | 35 | type XmlChunk struct { 36 | Diagram string `xml:"diagram"` 37 | } 38 | 39 | type Chunk struct { 40 | ChunkLen uint32 41 | ChunkType string 42 | ChunkData []byte 43 | ChunkCRC uint32 44 | } 45 | 46 | func Read_content(l *log.Logger, config *Config) string { 47 | imgFile, err := open_png_file(l, config.ActionRead) 48 | if err != nil { 49 | l.Fatal(err) 50 | } 51 | defer imgFile.Close() 52 | 53 | var content string 54 | 55 | for { 56 | chunk, err := read_chunk(config, imgFile) 57 | if err != nil { 58 | break 59 | } 60 | 61 | if config.Verbose { 62 | l.Println("Found chunk type: ", chunk.ChunkType) 63 | } 64 | if strings.ToLower(chunk.ChunkType) == "text" { 65 | content, err = decode_chunk(l, config, chunk) 66 | if err != nil { 67 | l.Fatal(err) 68 | } 69 | } 70 | } 71 | 72 | if config.Display { 73 | print(content) 74 | } 75 | return content 76 | } 77 | 78 | func Write_content_from_data(l *log.Logger, action string, content []byte) string { 79 | config := new(Config) 80 | config.Display = false 81 | 82 | workFile, err := ioutil.TempFile("", "*") 83 | if err != nil { 84 | l.Fatal("unable to open temporary file") 85 | } 86 | _, err = workFile.Write(content) 87 | config.ActionRead = workFile.Name() 88 | workFile.Close() 89 | 90 | if action == "read" { 91 | return Read_content(l, config) 92 | } else { 93 | return workFile.Name() 94 | } 95 | } 96 | 97 | func Write_content_dynamic_config( 98 | l *log.Logger, 99 | writePath string, 100 | sourcePath string, 101 | destPath string) { 102 | 103 | config := new(Config) 104 | config.Display = false 105 | config.ActionEmbed = writePath 106 | config.SourceFile = sourcePath 107 | config.DestFile = destPath 108 | config.Lenient = true 109 | config.Overwrite = true 110 | config.InPlace = false 111 | config.ReWriteCRC = false 112 | config.Verbose = false 113 | 114 | Write_content(l, config) 115 | } 116 | 117 | func Write_content(l *log.Logger, config *Config) { 118 | finalizeInPlace := false 119 | 120 | imgFile, err := open_png_file(l, config.ActionEmbed) 121 | if err != nil { 122 | l.Fatal(err) 123 | } 124 | 125 | var destFile *os.File 126 | 127 | finalizeDest := func() { 128 | if finalizeInPlace { 129 | if err = os.Remove(imgFile.Name()); err != nil { 130 | l.Fatal(err) 131 | } 132 | if err = os.Rename(destFile.Name(), imgFile.Name()); err != nil { 133 | l.Fatal(err) 134 | } 135 | } 136 | } 137 | 138 | if config.InPlace { 139 | destFile, err = ioutil.TempFile("", "*") 140 | if err != nil { 141 | l.Fatal("unable to open temporary file") 142 | } 143 | defer finalizeDest() 144 | } else { 145 | if config.DestFile == "-" { 146 | destFile = os.Stdout 147 | } else { 148 | destFile, err = os.Create(config.DestFile) 149 | if err != nil { 150 | l.Fatal("unable to open destination file") 151 | } 152 | } 153 | defer destFile.Close() 154 | } 155 | 156 | // Declare this defer call further down the stack to ensure 157 | // proper finalization work. 158 | defer imgFile.Close() 159 | 160 | sourceCode, err := os.ReadFile(config.SourceFile) 161 | if err != nil { 162 | l.Fatal(err) 163 | } 164 | 165 | destFile.Write([]byte(PNGHEADERSTR)) 166 | 167 | sourceWritten := false 168 | 169 | for { 170 | chunk, err := read_chunk(config, imgFile) 171 | if err != nil { 172 | break 173 | } 174 | 175 | normalizedType := strings.ToLower(chunk.ChunkType) 176 | if config.Verbose { 177 | l.Println("Chunk type", normalizedType) 178 | } 179 | if normalizedType == "text" { 180 | if !config.Overwrite { 181 | l.Println("! Not overwriting existing text chunk.") 182 | } else { 183 | if config.Verbose { 184 | l.Println("-> Replacing existing text chunk") 185 | } 186 | write_sourcecode(config, destFile, sourceCode) 187 | sourceWritten = true 188 | continue 189 | } 190 | } else { 191 | if normalizedType == "iend" { 192 | if !sourceWritten { 193 | if config.Verbose { 194 | l.Println("-> Including new text chunk") 195 | } 196 | write_sourcecode(config, destFile, sourceCode) 197 | } 198 | } 199 | } 200 | 201 | write_chunk(config, destFile, chunk) 202 | } 203 | 204 | if config.InPlace { 205 | finalizeInPlace = true 206 | } 207 | } 208 | 209 | func write_sourcecode(config *Config, destFile *os.File, sourceCode []byte) { 210 | var buf bytes.Buffer 211 | writer, _ := flate.NewWriter(&buf, -1) 212 | writer.Write(sourceCode) 213 | writer.Close() 214 | deflatedSC := buf.Bytes() 215 | b64SC := base64.StdEncoding.EncodeToString(deflatedSC) 216 | data := "mxfile" + 217 | url.QueryEscape( 218 | ``) + 221 | string(b64SC) + 222 | url.QueryEscape("") 223 | 224 | chunk := new(Chunk) 225 | chunk.ChunkType = "tExt" 226 | chunk.ChunkLen = uint32(len(data)) 227 | chunk.ChunkData = []byte(data) 228 | chunk.ChunkCRC = chunk_CRC([]byte(chunk.ChunkType), chunk.ChunkData) 229 | write_chunk(config, destFile, chunk) 230 | } 231 | 232 | func open_png_file(l *log.Logger, filepath string) (*os.File, error) { 233 | var err error 234 | var imgFile *os.File 235 | 236 | if filepath == "-" { 237 | imgFile = os.Stdin 238 | } else { 239 | imgFile, err = os.Open(filepath) 240 | if err != nil { 241 | return nil, err 242 | } 243 | } 244 | 245 | ihdrStr := make([]byte, 8) 246 | _, err = io.ReadFull(imgFile, ihdrStr) 247 | if err != nil { 248 | return nil, err 249 | } 250 | 251 | if PNGHEADERSTR != string(ihdrStr) { 252 | return nil, fmt.Errorf("This is not a PNG file.") 253 | } 254 | 255 | return imgFile, nil 256 | } 257 | 258 | func read_chunk(config *Config, imgFile *os.File) (*Chunk, error) { 259 | chunk := new(Chunk) 260 | var err error 261 | 262 | rawChunkLen := make([]byte, 4) 263 | _, err = io.ReadFull(imgFile, rawChunkLen) 264 | if err != nil { 265 | return nil, fmt.Errorf("error reading length: %v", err) 266 | } 267 | chunk.ChunkLen = uint32(binary.BigEndian.Uint32(rawChunkLen)) 268 | 269 | rawChunkType := make([]byte, 4) 270 | _, err = io.ReadFull(imgFile, rawChunkType) 271 | if err != nil { 272 | return nil, fmt.Errorf("error reading type") 273 | } 274 | chunk.ChunkType = string(rawChunkType) 275 | 276 | chunk.ChunkData = make([]byte, chunk.ChunkLen) 277 | _, err = io.ReadFull(imgFile, chunk.ChunkData) 278 | if err != nil { 279 | return nil, fmt.Errorf("error reading data") 280 | } 281 | 282 | rawChunkCRC := make([]byte, 4) 283 | _, err = io.ReadFull(imgFile, rawChunkCRC) 284 | if err != nil { 285 | return nil, fmt.Errorf("error reading CRC") 286 | } 287 | chunk.ChunkCRC = uint32(binary.BigEndian.Uint32(rawChunkCRC)) 288 | 289 | if !config.Lenient { 290 | if chunk.ChunkCRC != chunk_CRC(rawChunkType, chunk.ChunkData) { 291 | return nil, fmt.Errorf("error incorrect CRC") 292 | } 293 | } 294 | 295 | return chunk, nil 296 | } 297 | 298 | func write_chunk(config *Config, destFile *os.File, chunk *Chunk) error { 299 | var rawChunkLen bytes.Buffer 300 | var rawChunkCRC bytes.Buffer 301 | if binary.Write(&rawChunkLen, binary.BigEndian, chunk.ChunkLen) != nil { 302 | return fmt.Errorf("Unable to write chunk length") 303 | } 304 | destFile.Write(rawChunkLen.Bytes()) 305 | 306 | destFile.Write([]byte(chunk.ChunkType)) 307 | 308 | destFile.Write(chunk.ChunkData) 309 | 310 | if config.ReWriteCRC { 311 | if binary.Write( 312 | &rawChunkCRC, 313 | binary.BigEndian, 314 | chunk_CRC([]byte(chunk.ChunkType), chunk.ChunkData)) != nil { 315 | return fmt.Errorf("Unable to convert computed CRC size") 316 | } 317 | } else { 318 | if binary.Write(&rawChunkCRC, binary.BigEndian, chunk.ChunkCRC) != nil { 319 | return fmt.Errorf("Unable to write computed CRC size") 320 | } 321 | } 322 | destFile.Write(rawChunkCRC.Bytes()) 323 | 324 | return nil 325 | } 326 | 327 | func decode_chunk(l *log.Logger, config *Config, chunk *Chunk) (string, error) { 328 | if config.Verbose { 329 | l.Println("Chunk size: ", chunk.ChunkLen) 330 | } 331 | // Brutal removal of header and footer 332 | if chunk.ChunkLen < 22+31 { 333 | return "", fmt.Errorf("error chunk size too small") 334 | } 335 | start := strings.Index(string(chunk.ChunkData), "name%3D%22Page-1%22%3E") 336 | if start == -1 { 337 | return "", fmt.Errorf("error no preamble in chunk") 338 | } 339 | data := string(chunk.ChunkData[start+22 : chunk.ChunkLen-31]) 340 | debased, err := base64.StdEncoding.DecodeString(data) 341 | if err != nil { 342 | // Is this a draw.io urlencoded file? 343 | uddata, _ := url.QueryUnescape(data) 344 | debased, err = base64.StdEncoding.DecodeString(uddata) 345 | if err != nil { 346 | return "", fmt.Errorf("error not base64 encoded") 347 | } 348 | } 349 | deflated, err := ioutil.ReadAll(flate.NewReader(bytes.NewReader(debased))) 350 | if err != nil { 351 | return "", fmt.Errorf("error not deflate mode") 352 | } 353 | return string(deflated), nil 354 | } 355 | 356 | func chunk_CRC(chunkType []byte, chunkData []byte) uint32 { 357 | c32 := crc32.NewIEEE() 358 | c32.Write(chunkType) 359 | c32.Write(chunkData) 360 | return c32.Sum32() 361 | } 362 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mysite", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "css": "postcss assets/css/source.css -o assets/css/style.css" 7 | }, 8 | "dependencies": { 9 | "daisyui": "^1.16.6" 10 | }, 11 | "devDependencies": { 12 | "autoprefixer": "^10.4.2", 13 | "cssnano": "^5.0.15", 14 | "postcss": "^8.4.5", 15 | "postcss-cli": "^9.1.0", 16 | "postcss-resemble-image": "^2.1.1", 17 | "stylelint": "^14.1.0", 18 | "tailwindcss": "^3.0.15" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packaging/macos/pngsource.app/Contents/Info.plist.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | PNGSource 9 | CFBundleExecutable 10 | pngsource-darwin-arm64 11 | CFBundleIconFile 12 | pngsource.icns 13 | CFBundleIdentifier 14 | com.voilaweb.pngsource 15 | CFBundleInfoDictionaryVersion 16 | 1.0 17 | CFBundleName 18 | PNGSource 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | {{VERSION}} 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleURLName 27 | Custom App 28 | CFBundleURLSchemes 29 | 30 | pngsource 31 | 32 | 33 | 34 | CFBundleVersion 35 | 20211201.205724 36 | CSResourcesFileMapped 37 | 38 | LSApplicationCategoryType 39 | public.app-category.developer-tools 40 | LSRequiresCarbon 41 | 42 | NSHighResolutionCapable 43 | 44 | NSHumanReadableCopyright 45 | © 2021, CFR 46 | 47 | 48 | -------------------------------------------------------------------------------- /packaging/macos/pngsource.app/Contents/Resources/pngsource.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/packaging/macos/pngsource.app/Contents/Resources/pngsource.icns -------------------------------------------------------------------------------- /packaging/windows/WebView2Loader.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/packaging/windows/WebView2Loader.dll -------------------------------------------------------------------------------- /packaging/windows/app-windows-4.0-amd64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/packaging/windows/app-windows-4.0-amd64.exe -------------------------------------------------------------------------------- /packaging/windows/pngsource.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/packaging/windows/pngsource.bmp -------------------------------------------------------------------------------- /packaging/windows/pngsource.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/packaging/windows/pngsource.ico -------------------------------------------------------------------------------- /packaging/windows/pngsource.nsi.tmpl: -------------------------------------------------------------------------------- 1 | # modern ui 2 | !include MUI2.nsh 3 | !include "FileFunc.nsh" 4 | 5 | !define MUI_ICON pngsource.ico 6 | 7 | !define MUI_HEADERIMAGE 8 | !define MUI_HEADERIMAGE_BITMAP "pngsource.bmp" 9 | !define MUI_HEADERIMAGE_UNBITMAP "pngsource.bmp" 10 | 11 | !define MUI_PAGE_HEADER_TEXT "PNGSource" 12 | !define MUI_PAGE_HEADER_SUBTEXT "Embed source code in png files" 13 | !define MUI_WELCOMEPAGE_TITLE "Embed source code in png files" 14 | !define MUI_WELCOMEPAGE_TEXT "You are about to install PNGSource." 15 | 16 | !define MUI_FINISHPAGE_NOAUTOCLOSE 17 | 18 | !define MUI_FINISHPAGE_TITLE "PNGSource successfully installed." 19 | !define MUI_FINISHPAGE_LINK "Click here to visit the project's page" 20 | !define MUI_FINISHPAGE_LINK_LOCATION "https://github.com/fusion/pngsource" 21 | 22 | !define MUI_PAGE_CUSTOMFUNCTION_LEAVE "OnPageWelcomeLeave" 23 | !insertmacro MUI_PAGE_WELCOME 24 | 25 | !define MUI_PAGE_CUSTOMFUNCTION_LEAVE "OnPageDirectoryLeave" 26 | !insertmacro MUI_PAGE_DIRECTORY 27 | !insertmacro MUI_PAGE_INSTFILES 28 | !insertmacro MUI_PAGE_FINISH 29 | 30 | !define MUI_WELCOMEPAGE_TEXT "You are about to uninstall PNGSource." 31 | !define MUI_FINISHPAGE_TEXT "PNGSource was uninstalled.$\r$\nI hope it worked well for you." 32 | !define MUI_FINISHPAGE_LINK "Click here to visit the project's page" 33 | !define MUI_FINISHPAGE_LINK_LOCATION "https://github.com/fusion/pngsource" 34 | !insertmacro MUI_UNPAGE_WELCOME 35 | !insertmacro MUI_UNPAGE_CONFIRM 36 | !insertmacro MUI_UNPAGE_INSTFILES 37 | !insertmacro MUI_UNPAGE_FINISH 38 | 39 | VIProductVersion "{{VERSION}}.0" 40 | VIFileVersion "{{VERSION}}.0" 41 | 42 | Name "PNGSouce Installer" 43 | OutFile "pngsource_installer.exe" 44 | InstallDir "$LOCALAPPDATA\PNGSource" 45 | 46 | # For removing Start Menu shortcut in Windows 7 plus writing registry entries 47 | RequestExecutionLevel admin 48 | 49 | 50 | Section 51 | SetOutPath $INSTDIR 52 | 53 | File pngsource-windows-4.0-amd64.exe 54 | File webview.dll 55 | File WebView2Loader.dll 56 | 57 | WriteUninstaller "$INSTDIR\uninstall.exe" 58 | CreateShortcut "$SMPROGRAMS\PNGSource Uninstaller.lnk" "$INSTDIR\uninstall.exe" 59 | CreateShortcut "$SMPROGRAMS\PNGSource.lnk" "$INSTDIR\pngsource-windows-4.0-amd64.exe" 60 | 61 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\PNGSource" \ 62 | "DisplayName" "PNGSource -- Embed source code in png files" 63 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\PNGSource" \ 64 | "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" 65 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\PNGSource" \ 66 | "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" 67 | ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 68 | IntFmt $0 "0x%08X" $0 69 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\PNGSource" \ 70 | "EstimatedSize" "$0" 71 | SectionEnd 72 | 73 | Section "uninstall" 74 | SetOutPath $INSTDIR 75 | 76 | Delete "$INSTDIR\uninstall.exe" 77 | Delete "$INSTDIR\pngsource-windows-4.0-amd64.exe" 78 | Delete "$INSTDIR\webview.exe" 79 | Delete "$INSTDIR\WebView2Loader.dll" 80 | Delete "$SMPROGRAMS\PNGSource Uninstaller.lnk" 81 | Delete "$SMPROGRAMS\PNGSource.lnk" 82 | 83 | RMDir $INSTDIR 84 | SectionEnd 85 | 86 | Function "OnPageWelcomeLeave" 87 | Return 88 | FunctionEnd 89 | 90 | Function "OnPageDirectoryLeave" 91 | Return 92 | FunctionEnd 93 | -------------------------------------------------------------------------------- /packaging/windows/webview.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/packaging/windows/webview.dll -------------------------------------------------------------------------------- /pngsource/gui.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/base64" 5 | "flag" 6 | "log" 7 | "os" 8 | "strings" 9 | 10 | "github.com/fusion/pngsource/lib" 11 | "github.com/fusion/pngsource/web" 12 | "github.com/rakyll/globalconf" 13 | //"github.com/davecgh/go-spew/spew" 14 | ) 15 | 16 | var l *log.Logger 17 | var preferences *globalconf.GlobalConf 18 | 19 | type StringValue struct { 20 | value string 21 | } 22 | 23 | func (s StringValue) String() string { 24 | return s.value 25 | } 26 | 27 | func (s StringValue) Set(newValue string) error { 28 | s.value = newValue 29 | return nil 30 | } 31 | 32 | func getActualBytes(sourceString string) []byte { 33 | comma := strings.Index(sourceString, ",") 34 | if comma == -1 { 35 | return []byte(sourceString) 36 | } 37 | subcontent := sourceString[comma+1:] 38 | debased, err := base64.StdEncoding.DecodeString(subcontent) 39 | if err != nil { 40 | l.Println("BASE64 Oopsy.") 41 | return []byte("*err*") 42 | } 43 | return debased 44 | } 45 | 46 | // "Localize" type so that we can use it as a receiver 47 | type AppHandler web.AppHandler 48 | 49 | func (h *AppHandler) Wlog(msg string) { 50 | l.Println(msg) 51 | } 52 | 53 | func (h *AppHandler) Wupdatedestfolderpref(value string) { 54 | preferences.Set("webview", &flag.Flag{Name: "dest", Value: StringValue{value}}) 55 | } 56 | 57 | func (h *AppHandler) Wrawimage(action string, content string) string { 58 | return lib.Write_content_from_data(l, action, getActualBytes(content)) 59 | } 60 | 61 | func (h *AppHandler) Wsourcecode(action string, content string) string { 62 | return lib.Write_content_from_data(l, action, getActualBytes(content)) 63 | } 64 | 65 | func (h *AppHandler) Wembedcode( 66 | writeFileName string, 67 | writepath string, 68 | sourcetype string, 69 | sourcepathorcode string, 70 | destfolder string) bool { 71 | 72 | // destFolder is not relevant at this time as we are using 73 | // a file dialog instead. 74 | selectedPath := web.SelectSavePath(writeFileName) 75 | if selectedPath == "" { 76 | return false 77 | } 78 | if sourcetype == "string" { 79 | sourcepath := lib.Write_content_from_data(l, "put", []byte(sourcepathorcode)) 80 | lib.Write_content_dynamic_config(l, writepath, sourcepath, selectedPath) 81 | } else { 82 | lib.Write_content_dynamic_config(l, writepath, sourcepathorcode, selectedPath) 83 | } 84 | 85 | return true 86 | } 87 | 88 | func main() { 89 | debug := true 90 | l = log.New(os.Stderr, "", 0) 91 | 92 | f := flag.NewFlagSet("gui", flag.ContinueOnError) 93 | flagDestPath := f.String("dest", "", "destination path") 94 | 95 | globalconf.Register("gui", f) 96 | preferences, _ := globalconf.New("pngsource") 97 | preferences.ParseAll() 98 | 99 | web.Instantiate( 100 | debug, 101 | flagDestPath, 102 | &AppHandler{States: make(map[string]string)}) 103 | } 104 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | cssnano: {preset: 'default',}, 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pngsource", 3 | "description": "Embed source code in png files", 4 | "author": { 5 | "name": "", 6 | "email": "" 7 | }, 8 | "version": "1.0.0", 9 | "binaryname": "pngsource", 10 | "frontend": { 11 | "dir": "assets", 12 | "install": "npm install", 13 | "build": "npm run build", 14 | "bridge": ".", 15 | "serve": "npm run serve" 16 | }, 17 | "tags": "", 18 | "WailsVersion": "", 19 | "CrossCompile": false, 20 | "Platform": "", 21 | "Architecture": "", 22 | "LdFlags": "", 23 | "GoPath": "", 24 | "UseFirebug": false 25 | } 26 | -------------------------------------------------------------------------------- /rsrc_windows_386.syso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/rsrc_windows_386.syso -------------------------------------------------------------------------------- /rsrc_windows_amd64.syso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/rsrc_windows_amd64.syso -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/screenshot.png -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: ["./assets/**/*.{html,js}"], 3 | theme: { 4 | extend: {}, 5 | }, 6 | plugins: [ 7 | require('daisyui'), 8 | ], 9 | daisyui: { 10 | styled: true, 11 | themes: true, 12 | base: true, 13 | utils: true, 14 | logs: true, 15 | rtl: false, 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /web/guihandler.go: -------------------------------------------------------------------------------- 1 | package web 2 | 3 | type GUIHandler interface { 4 | Wlog(string) 5 | Wupdatedestfolderpref(string) 6 | Wrawimage(string, string) string 7 | Wsourcecode(string, string) string 8 | Wembedcode(string, string, string, string, string) bool 9 | } 10 | 11 | type AppHandler struct { 12 | States map[string]string 13 | } 14 | -------------------------------------------------------------------------------- /web/guiwails.go: -------------------------------------------------------------------------------- 1 | //go:build !webview 2 | // +build !webview 3 | 4 | package web 5 | 6 | import ( 7 | _ "embed" 8 | "strings" 9 | 10 | "github.com/fusion/pngsource/assets" 11 | "github.com/ncruces/zenity" 12 | "github.com/wailsapp/wails" 13 | ) 14 | 15 | func SelectSavePath(writeFileName string) string { 16 | selectedPath, err := zenity.SelectFileSave( 17 | zenity.Title("Save File with Embed"), 18 | zenity.Filename(writeFileName), 19 | zenity.FileFilters{{ 20 | Name: "PNG files", 21 | Patterns: []string{"*.png"}}}, 22 | zenity.ConfirmOverwrite(), 23 | ) 24 | if err != nil { // e.g. dialog canceled 25 | return "" 26 | } 27 | return selectedPath 28 | } 29 | 30 | func Instantiate( 31 | debug bool, 32 | destPath *string, 33 | h GUIHandler) { 34 | 35 | rawhtml, _ := assets.Content.ReadFile("index.html") 36 | html := strings.Replace(string(rawhtml), "{{STYLE}}", "", -1) 37 | css, _ := assets.Content.ReadFile("css/style.css") 38 | app := wails.CreateApp(&wails.AppConfig{ 39 | Width: 1024, 40 | Height: 768, 41 | Title: "pngsource", 42 | HTML: html, 43 | CSS: string(css), 44 | Colour: "#131313", 45 | }) 46 | app.Bind(h) 47 | app.Run() 48 | } 49 | -------------------------------------------------------------------------------- /web/guiwebview.go: -------------------------------------------------------------------------------- 1 | //go:build webview 2 | // +build webview 3 | 4 | package web 5 | 6 | import ( 7 | "strings" 8 | 9 | "github.com/fusion/pngsource/assets" 10 | "github.com/ncruces/zenity" 11 | "github.com/webview/webview" 12 | ) 13 | 14 | func SelectSavePath(writeFileName string) string { 15 | selectedPath, err := zenity.SelectFileSave( 16 | zenity.Title("Save File with Embed"), 17 | zenity.Filename(writeFileName), 18 | zenity.FileFilters{{ 19 | Name: "PNG files", 20 | Patterns: []string{"*.png"}}}, 21 | zenity.ConfirmOverwrite(), 22 | ) 23 | if err != nil { // e.g. dialog canceled 24 | return "" 25 | } 26 | return selectedPath 27 | } 28 | 29 | var w webview.WebView 30 | 31 | func Instantiate( 32 | debug bool, 33 | destPath *string, 34 | h GUIHandler) { 35 | css, _ := assets.Content.ReadFile("css/style.css") 36 | rawpage, _ := assets.Content.ReadFile("index.html") 37 | almostpage := strings.Replace( 38 | strings.Replace( 39 | string(rawpage), "{{STYLE}}", string(css), -1), 40 | "{{DESTPATH}}", *destPath, -1) 41 | page := strings.Replace(almostpage, "%", "%25", -1) 42 | 43 | w = webview.New(debug) 44 | defer w.Destroy() 45 | 46 | w.Bind("wlog", h.Wlog) 47 | w.Bind("wupdatedestfolderpref", h.Wupdatedestfolderpref) 48 | w.Bind("wrawimage", h.Wrawimage) 49 | w.Bind("wsourcecode", h.Wsourcecode) 50 | w.Bind("wembedcode", h.Wembedcode) 51 | 52 | w.SetTitle("PngSource Thingamagig") 53 | w.SetSize(800, 720, webview.HintNone) 54 | 55 | w.Navigate("data:text/html," + string(page)) 56 | w.Run() 57 | } 58 | -------------------------------------------------------------------------------- /winres/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/winres/icon.png -------------------------------------------------------------------------------- /winres/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Fusion/pngsource/13d83c985072592d9696375ceb985e7fcd5ebf52/winres/icon16.png -------------------------------------------------------------------------------- /winres/winres.json: -------------------------------------------------------------------------------- 1 | { 2 | "RT_GROUP_ICON": { 3 | "APP": { 4 | "0000": [ 5 | "icon.png", 6 | "icon16.png" 7 | ] 8 | } 9 | }, 10 | "RT_MANIFEST": { 11 | "#1": { 12 | "0409": { 13 | "identity": { 14 | "name": "", 15 | "version": "" 16 | }, 17 | "description": "", 18 | "minimum-os": "win7", 19 | "execution-level": "as invoker", 20 | "ui-access": false, 21 | "auto-elevate": false, 22 | "dpi-awareness": "system", 23 | "disable-theming": false, 24 | "disable-window-filtering": false, 25 | "high-resolution-scrolling-aware": false, 26 | "ultra-high-resolution-scrolling-aware": false, 27 | "long-path-aware": false, 28 | "printer-driver-isolation": false, 29 | "gdi-scaling": false, 30 | "segment-heap": false, 31 | "use-common-controls-v6": false 32 | } 33 | } 34 | }, 35 | "RT_VERSION": { 36 | "#1": { 37 | "0000": { 38 | "fixed": { 39 | "file_version": "0.0.0.0", 40 | "product_version": "0.0.0.0" 41 | }, 42 | "info": { 43 | "0409": { 44 | "Comments": "", 45 | "CompanyName": "", 46 | "FileDescription": "", 47 | "FileVersion": "", 48 | "InternalName": "", 49 | "LegalCopyright": "", 50 | "LegalTrademarks": "", 51 | "OriginalFilename": "", 52 | "PrivateBuild": "", 53 | "ProductName": "", 54 | "ProductVersion": "", 55 | "SpecialBuild": "" 56 | } 57 | } 58 | } 59 | } 60 | } 61 | } --------------------------------------------------------------------------------