diff --git a/.github/workflows/wails.yml b/.github/workflows/wails.yml
new file mode 100644
index 0000000..aafcf68
--- /dev/null
+++ b/.github/workflows/wails.yml
@@ -0,0 +1,98 @@
+name: Release YellowJacket
+run-name: Release ${{ github.ref_name }}
+
+permissions:
+ contents: write
+
+on:
+ push:
+ tags:
+ # Match any new tag
+ - '*'
+
+env:
+ # Necessary for most environments as build failure can occur due to OOM issues
+ NODE_OPTIONS: "--max-old-space-size=4096"
+
+jobs:
+ build:
+ strategy:
+ # Failure in one platform build won't impact the others
+ fail-fast: false
+ matrix:
+ build:
+ - name: 'yellowjacket'
+ platform: 'linux/amd64'
+ os: 'ubuntu-latest'
+ bin-name: 'yellowjacket'
+ artifact-name: 'yellowjacket'
+ - name: 'yellowjacket'
+ platform: 'windows/amd64'
+ os: 'windows-latest'
+ bin-name: 'yellowjacket'
+ artifact-name: 'yellowjacket.exe'
+ - name: 'yellowjacket'
+ platform: 'darwin/universal'
+ os: 'macos-latest'
+ bin-name: 'yellowjacket.app'
+ artifact-name: 'yellowjacket.app'
+
+ runs-on: ${{ matrix.build.os }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: recursive
+
+ - name: Dependencies
+ uses: ConorMacBride/install-package@v1
+ with:
+ apt: libasound2-dev
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+ with:
+ version: 10
+
+ - name: Build wails
+ uses: dAppServer/wails-build-action@main
+ id: build
+ with:
+ build-name: ${{ matrix.build.name }}
+ build-platform: ${{ matrix.build.platform }}
+ go-version: '1.24'
+ package: false
+ app-working-directory: ${{ github.workspace }}
+
+ - name: Upload Binaries
+ uses: actions/upload-artifact@v4
+ with:
+ name: ${{ matrix.build.artifact-name }}
+ path: ${{ github.workspace }}/build/bin/${{ matrix.build.bin-name }}
+
+ release:
+ runs-on: ubuntu-latest
+ needs: build
+ steps:
+ - name: Download Artifacts
+ uses: actions/download-artifact@v4
+ with:
+ merge-multiple: true
+ path: ${{ github.workspace }}/bin
+ - name: Release
+ uses: softprops/action-gh-release@v2
+ if: github.ref_type == 'tag'
+ with:
+ body: |
+ # YellowJacket Release ${{ github.ref_name }}
+
+ This is an early preview of YellowJacket. Please report any bugs to [our issues] page.
+
+ Thanks for trying out our app!
+
+ ## Which do I click?
+
+ - Linux: `yellowjacket`
+ - Windows: `yellowjacket.exe`
+ - MacOS: `yellowjacket.app`
+ files: ${{ github.workspace }}/bin/*
diff --git a/.gitignore b/.gitignore
index d9e6a2e..3a5fbab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-build/bin
-node_modules
frontend/dist
+node_modules
+build
test_data
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b2e59c4
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+dev:
+ WEBKIT_DISABLE_DMABUF_RENDERER=1 wails dev -tags webkit2_41
+
+build-dev:
+ wails build -tags webkit2_41 -debug -clean
+
+build-prod:
+ wails build -tags webkit2_41 -clean -obfuscated -upx
+
+generate:
+ go generate ./...
diff --git a/README.md b/README.md
index 397b08b..bd76822 100644
--- a/README.md
+++ b/README.md
@@ -1,19 +1,36 @@
-# README
+# YellowJacket
-## About
+A MusicBee inspired music player and library manager.
-This is the official Wails Vanilla template.
+## Install
-You can configure the project by editing `wails.json`. More information about the project settings can be found
-here: https://wails.io/docs/reference/project-config
+TODO: put release links here
-## Live Development
+## Features
-To run in live development mode, run `wails dev` in the project directory. This will run a Vite development
-server that will provide very fast hot reload of your frontend changes. If you want to develop in a browser
-and have access to your Go methods, there is also a dev server that runs on http://localhost:34115. Connect
-to this in your browser, and you can call your Go code from devtools.
+TODO: add feature list and screenshots here
-## Building
+## Development
-To build a redistributable, production mode package, use `wails build`.
+YellowJacket relies on [Wails](https://wails.io/docs/introduction) for development.
+Wails allows us to build a frontend with HTML/CSS/JS and backend with Golang.
+
+### Prerequisites
+
+1. First, you will need Go installed.
+
+2. Then, you will need the `wails` cli tool.
+
+ Install it with
+
+ ```shell
+ go install github.com/wailsapp/wails/v2/cmd/wails@latest
+ ```
+
+3. After installing the Wails CLI you may need some build dependencies.
+ View the missing Wails dependencies by running `wails doctor`.
+ Using your system's package manager, install the missing dependencies.
+
+### Dev Server
+
+To run the Wails hot-reloading dev server, run `make dev` in the root of the project.
diff --git a/app.go b/app.go
deleted file mode 100644
index 0850c62..0000000
--- a/app.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package main
-
-import (
- "context"
- "fmt"
- "yellowjacket/backend"
-)
-
-// App struct
-type App struct {
- ctx context.Context
- config *backend.Config
-}
-
-// NewApp creates a new App application struct
-func NewApp() *App {
- return &App{}
-}
-
-// startup is called when the app starts. The context is saved
-// so we can call the runtime methods
-func (a *App) startup(ctx context.Context) {
- a.ctx = ctx
-
- conf, err := backend.GetConfig()
- if err != nil {
- panic(fmt.Errorf("could not get config: %w", err))
- }
- a.config = conf
-}
-
-// Greet returns a greeting for the given name
-func (a *App) Greet(name string) string {
- return fmt.Sprintf("Hello %s, here's your song!", name)
-}
-
-//trying to make a function
-//func (a *App) dirPicker(ctx context.Context, dialogOptions OpenDialogOptions)(string, error){}
diff --git a/backend/config.go b/backend/config.go
deleted file mode 100644
index 7d34cd1..0000000
--- a/backend/config.go
+++ /dev/null
@@ -1,77 +0,0 @@
-package backend
-
-import (
- "fmt"
- "os"
- "path"
-
- "github.com/BurntSushi/toml"
-)
-
-type Config struct {
- LibraryDirPath string
- MyConfigValue string
-}
-
-var defaultConfig *Config = &Config{
- LibraryDirPath: "",
- MyConfigValue: "testtesttest",
-}
-
-func GetConfig() (*Config, error) {
-
- configDir, err := GetUserConfigDirPath()
- if err != nil {
- return nil, fmt.Errorf("could not get user config directory path: %w", err)
- }
- configFilePath := path.Join(configDir, "config.toml")
- // create the config file and load defaults if it doesn't exist
- _, err = os.Stat(configFilePath)
- if os.IsNotExist(err) {
- defaultConfig.WriteConfig(configFilePath)
- }
- conf, err := LoadConfig(configFilePath)
- if err != nil {
- return nil, fmt.Errorf("could not load config file %s: %w", configFilePath, err)
- }
- return conf, nil
-}
-
-func LoadConfig(configFilePath string) (*Config, error) {
- // read in the file
- confFileData, err := os.ReadFile(configFilePath)
- if err != nil {
- return nil, fmt.Errorf("problem reading config file %s: %w", configFilePath, err)
- }
-
- // parse it into the config struct
- var conf Config
- _, err = toml.Decode(string(confFileData), &conf)
- if err != nil {
- return nil, fmt.Errorf("problem parsing config file %s: %w", configFilePath, err)
- }
-
- // validate the config
- if err = conf.validate(); err != nil {
- return nil, fmt.Errorf("invalid config file at %s: %w", configFilePath, err)
- }
-
- return &conf, nil
-}
-
-func (c *Config) WriteConfig(configFileWritePath string) error {
- confFileData, err := toml.Marshal(c)
- if err != nil {
- return fmt.Errorf("could not marshal config struct: %w", err)
- }
- err = os.WriteFile(configFileWritePath, confFileData, os.FileMode(int(0666)))
- if err != nil {
- return fmt.Errorf("could not write config file: %w", err)
- }
- return nil
-}
-
-// return errors if there is a *breaking* issue with the config
-func (c *Config) validate() error {
- return nil
-}
diff --git a/backend/config/config.go b/backend/config/config.go
new file mode 100644
index 0000000..bcb950f
--- /dev/null
+++ b/backend/config/config.go
@@ -0,0 +1,145 @@
+package config
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "path"
+ "yellowjacket/backend/library"
+
+ "github.com/BurntSushi/toml"
+)
+
+type Config struct {
+ filePath string // required
+ *configData
+}
+
+func newConfig(filePath string, data *configData) (*Config, error) {
+ conf := &Config{
+ filePath: filePath,
+ configData: data,
+ }
+ // TODO make sure required fields have SOMETHING in them
+ // TODO Merge existing config with read in config
+ if data == nil {
+ return nil, errors.New("nil config")
+ }
+ if err := data.validate(); err != nil {
+ return nil, fmt.Errorf("invalid config: %w", err)
+ }
+ return conf, nil
+}
+
+type configData struct {
+ Library *library.Config
+}
+
+// return errors if there is a *breaking* issue with the config
+func (d *configData) validate() error {
+ if d.Library == nil {
+ return errors.New("nil library config")
+ }
+ if err := d.Library.Validate(); err != nil {
+ return fmt.Errorf("invalid library config: %#v: %w", d.Library, err)
+ }
+ return nil
+}
+
+var defaultConfigData *configData = &configData{
+ Library: library.DefaultConfig,
+}
+
+// GetCurrentConfig will load and return the config
+// reading the config file in the user's config directory
+func GetCurrentConfig() (*Config, error) {
+ // get the config file location
+ configDir, err := GetUserConfigDirPath()
+ if err != nil {
+ return nil, fmt.Errorf("could not get user config directory path: %w", err)
+ }
+ configFilePath := path.Join(configDir, "config.toml")
+
+ // create the config obj with the filepath we got, initializing with default data
+ config, err := newConfig(configFilePath, defaultConfigData)
+ if err != nil {
+ return nil, fmt.Errorf("could not create new config: %w", err)
+ }
+ config.filePath = configFilePath
+
+ // does the config file alaeady exist?
+ // if not, create it
+ _, err = os.Stat(configFilePath)
+ if os.IsNotExist(err) {
+ if err := config.WriteConfig(); err != nil {
+ return nil, fmt.Errorf("could not write config: %w", err)
+ }
+ }
+
+ // now that we have our config file, load it in
+ config, err = config.loadConfig()
+ if err != nil {
+ return nil, fmt.Errorf("could not load config file %s: %w", configFilePath, err)
+ }
+
+ // before we return the config, lets make sure sub configs can invoke saving when they need
+ err = config.updateSubConfigSaveFuncReferences()
+ if err != nil {
+ return nil, fmt.Errorf("could not update sub config save func references: %w", err)
+ }
+ return config, nil
+}
+
+func (c *Config) loadConfig() (*Config, error) {
+ // read in the file
+ confFileData, err := os.ReadFile(c.filePath)
+ if err != nil {
+ return nil, fmt.Errorf("problem reading config file %s: %w", c.filePath, err)
+ }
+
+ // parse it into the config struct
+ var confData configData
+ _, err = toml.Decode(string(confFileData), &confData)
+ if err != nil {
+ return nil, fmt.Errorf("problem parsing config file %s: %w", c.filePath, err)
+ }
+
+ // validate the config
+ if err = confData.validate(); err != nil {
+ return nil, fmt.Errorf("invalid config file at %s: %w", c.filePath, err)
+ }
+
+ config, err := newConfig(c.filePath, &confData)
+ if err != nil {
+ return nil, fmt.Errorf("could not create config from config file data at %s: %w", c.filePath, err)
+ }
+
+ // before we return the config, lets make sure sub configs can invoke saving when they need
+ err = config.updateSubConfigSaveFuncReferences()
+ if err != nil {
+ return nil, fmt.Errorf("could not update sub config save func references: %w", err)
+ }
+
+ return config, nil
+}
+
+func (c *Config) WriteConfig() error {
+ if err := c.validate(); err != nil {
+ return fmt.Errorf("invalid config: %w", err)
+ }
+ confFileData, err := toml.Marshal(c)
+ if err != nil {
+ return fmt.Errorf("could not marshal config struct: %w", err)
+ }
+
+ err = os.WriteFile(c.filePath, confFileData, os.FileMode(int(0666)))
+ if err != nil {
+ return fmt.Errorf("could not write config file: %w", err)
+ }
+ return nil
+}
+
+func (c *Config) updateSubConfigSaveFuncReferences() error {
+ c.Library.SaveFunc = c.WriteConfig
+ return nil
+}
diff --git a/backend/userdata.go b/backend/config/userdata.go
similarity index 92%
rename from backend/userdata.go
rename to backend/config/userdata.go
index 320634f..58e8918 100644
--- a/backend/userdata.go
+++ b/backend/config/userdata.go
@@ -1,4 +1,4 @@
-package backend
+package config
import (
"fmt"
@@ -18,7 +18,7 @@ func GetUserConfigDirPath() (string, error) {
}
switch currentOS := runtime.GOOS; currentOS {
case "darwin":
- fallthrough
+ path = fmt.Sprintf("/Users/%s/.config/yellowjacket", currentUser.Username)
case "linux":
path = fmt.Sprintf("/home/%s/.config/yellowjacket", currentUser.Username)
case "windows":
@@ -55,7 +55,7 @@ func getUserDataDirPath() (string, error) {
}
switch currentOS := runtime.GOOS; currentOS {
case "darwin":
- fallthrough
+ path = fmt.Sprintf("/Users/%s/.local/share/yellowjacket", currentUser.Username)
case "linux":
path = fmt.Sprintf("/home/%s/.local/share/yellowjacket", currentUser.Username)
case "windows":
diff --git a/backend/database/database.go b/backend/database/database.go
new file mode 100644
index 0000000..02c43f3
--- /dev/null
+++ b/backend/database/database.go
@@ -0,0 +1,7 @@
+package database
+
+type DB struct{}
+
+func NewDB() (*DB, error) {
+ return &DB{}, nil
+}
diff --git a/backend/database/sql/queries/todo.txt b/backend/database/sql/queries/todo.txt
new file mode 100644
index 0000000..e69de29
diff --git a/backend/database/sql/schemas/todo.txt b/backend/database/sql/schemas/todo.txt
new file mode 100644
index 0000000..e69de29
diff --git a/backend/database/sqlc.yaml b/backend/database/sqlc.yaml
new file mode 100644
index 0000000..bb168b2
--- /dev/null
+++ b/backend/database/sqlc.yaml
@@ -0,0 +1,10 @@
+version: "2"
+sql:
+ - name: "yellowjacket"
+ engine: "sqlite"
+ queries: "./sql/queries"
+ schema: "./sql/schemas"
+ gen:
+ go:
+ package: "sql"
+ out: "sql"
diff --git a/backend/frontendbindings/frontendbindings.go b/backend/frontendbindings/frontendbindings.go
new file mode 100644
index 0000000..b152358
--- /dev/null
+++ b/backend/frontendbindings/frontendbindings.go
@@ -0,0 +1,38 @@
+package frontendbindings
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+)
+
+// FrontendBindings contain any Go functions that are specific to the frontend only and need to be bound
+type FrontendBindings struct {
+ ctx context.Context
+}
+
+func NewFrontendBindings() (*FrontendBindings, error) {
+ return &FrontendBindings{}, nil
+}
+
+func (fe *FrontendBindings) Init(ctx context.Context) error {
+ fe.ctx = ctx
+ return nil
+}
+
+// Open a directory picker
+func (fe *FrontendBindings) DirectoryPicker() (string, error) {
+ runtime.LogInfo(fe.ctx, "selecting a directory")
+ dir, err := runtime.OpenDirectoryDialog(
+ fe.ctx,
+ runtime.OpenDialogOptions{})
+ if err != nil {
+ return "", fmt.Errorf("could not open directory dialog\n%w", err)
+ }
+ if dir == "" {
+ return "No Library Directory Selected", nil
+ }
+
+ return dir, nil
+}
diff --git a/backend/library/library.go b/backend/library/library.go
new file mode 100644
index 0000000..e147906
--- /dev/null
+++ b/backend/library/library.go
@@ -0,0 +1,63 @@
+package library
+
+import (
+ "context"
+ "fmt"
+ "os"
+)
+
+type Config struct {
+ DirectoryPath string
+ SaveFunc func() error `toml:"-"`
+}
+
+func (c *Config) Validate() error {
+ return nil
+}
+
+var DefaultConfig *Config = &Config{
+ DirectoryPath: "",
+}
+
+type Library struct {
+ ctx context.Context
+ conf *Config
+}
+
+func NewLibrary(conf *Config) (*Library, error) {
+ if conf == nil {
+ return nil, fmt.Errorf("nil config for library")
+ }
+ if err := conf.Validate(); err != nil {
+ return nil, fmt.Errorf("invalid library config %#v: %w", conf, err)
+ }
+ return &Library{
+ conf: conf,
+ }, nil
+}
+
+func (l *Library) Init(ctx context.Context) error {
+ l.ctx = ctx
+ return nil
+}
+
+func (l *Library) GetDir() (string, error) {
+ return l.conf.DirectoryPath, nil
+}
+
+func (l *Library) SetDir(dirPath string) error {
+ fileInfo, err := os.Stat(dirPath)
+ if err != nil {
+ return fmt.Errorf("could not stat %s: %w", dirPath, err)
+ }
+ if !fileInfo.IsDir() {
+ return fmt.Errorf("dirPath is not a directory: %s", dirPath)
+ }
+
+ l.conf.DirectoryPath = dirPath
+ err = l.conf.SaveFunc()
+ if err != nil {
+ return fmt.Errorf("could not save library dir config: %w", err)
+ }
+ return nil
+}
diff --git a/backend/logging/logging.go b/backend/logging/logging.go
new file mode 100644
index 0000000..23cb975
--- /dev/null
+++ b/backend/logging/logging.go
@@ -0,0 +1,11 @@
+package logging
+
+import (
+ "encoding/json"
+)
+
+// TODO check that error
+func PrettyJSON(obj interface{}) string {
+ bytes, _ := json.MarshalIndent(obj, "\t", "\t")
+ return string(bytes)
+}
diff --git a/backend/player/player.go b/backend/player/player.go
new file mode 100644
index 0000000..1be6729
--- /dev/null
+++ b/backend/player/player.go
@@ -0,0 +1,194 @@
+package player
+
+import (
+ "context"
+ "fmt"
+ "math"
+ "os"
+ "time"
+
+ "github.com/gopxl/beep"
+ "github.com/gopxl/beep/effects"
+ "github.com/gopxl/beep/generators"
+ "github.com/gopxl/beep/mp3"
+ "github.com/gopxl/beep/speaker"
+)
+
+type Player struct {
+ ctx context.Context
+ state PlayerState
+ currentFile *os.File
+ format beep.Format
+ baseStreamer beep.Streamer
+ seeker beep.StreamSeeker
+ resampled beep.Streamer
+ control *beep.Ctrl
+ volume *effects.Volume
+ speakerStreamer beep.Streamer
+}
+
+type PlayerState int
+
+const (
+ Playing PlayerState = iota
+ Paused
+ Stopped
+)
+
+var speakerSampleRate = beep.SampleRate(44100)
+
+func NewPlayer() (*Player, error) {
+ return &Player{
+ state: Stopped,
+ baseStreamer: generators.Silence(-1),
+ format: beep.Format{
+ SampleRate: speakerSampleRate,
+ },
+ }, nil
+}
+
+func (p *Player) Init(ctx context.Context) error {
+ p.ctx = ctx
+
+ // Initialize speaker
+ // TODO: allow user to change buffer size and speaker sample rate
+ err := speaker.Init(p.format.SampleRate, p.format.SampleRate.N(time.Second/10))
+ if err != nil {
+ return fmt.Errorf("failed to initialize speaker %w", err)
+ }
+
+ return nil
+}
+
+func (p *Player) updateStreamers(newBaseStreamer beep.StreamSeeker, sr beep.SampleRate) error {
+ // set base streamer
+ p.baseStreamer = newBaseStreamer
+ p.seeker = newBaseStreamer
+
+ // resample file stream to match speaker
+ // TODO: variable resample quality
+ p.resampled = beep.Resample(4, sr, speakerSampleRate, p.baseStreamer)
+
+ // wrap in ctrl streamer to allow play/pause
+ p.control = &beep.Ctrl{Streamer: p.resampled}
+
+ // wrap in volume streamer
+ p.volume = &effects.Volume{
+ Streamer: p.control,
+ Base: 2,
+ Volume: 0,
+ Silent: false,
+ }
+
+ // set "final" streamer
+ p.speakerStreamer = p.volume
+
+ return nil
+}
+
+// TODO: proper state management extracted to function
+func (p *Player) changeState(desiredState PlayerState) error {
+ return nil
+}
+
+// reads a file and creates a streamer, also wraps necessary streamers
+func (p *Player) LoadFile(filePath string) error {
+ // opening file
+ f, err := os.Open(filePath)
+ if err != nil {
+ return fmt.Errorf("failed to open file %w", err)
+ }
+
+ // attempt to decode mp3 file and create streamer and format data
+ streamer, format, err := mp3.Decode(f)
+ if err != nil {
+ return fmt.Errorf("failed to decode mp3 %w", err)
+ }
+
+ p.currentFile = f
+
+ p.updateStreamers(streamer, format.SampleRate)
+
+ return nil
+}
+
+func (p *Player) Play() error {
+ p.state = Playing
+ // hangs until song finishes playing
+ done := make(chan bool)
+ speaker.Play(beep.Seq(p.speakerStreamer, beep.Callback(func() {
+ p.state = Paused //called when streamer finishes
+ done <- true
+ })))
+
+ <-done
+ return nil
+}
+
+// TODO: reduce dupilcation in pause/resume functions
+func (p *Player) Pause() error {
+ speaker.Lock()
+ p.control.Paused = true
+ speaker.Unlock()
+ return nil
+}
+
+// TODO: reduce dupilcation in pause/resume functions
+func (p *Player) Resume() error {
+ speaker.Lock()
+ p.control.Paused = false
+ speaker.Unlock()
+ return nil
+}
+
+//Paraprasing info from the beep docs here:
+/*
+To INCREASE volume by 1 means to multiply the signal by Base.
+Volume = 0 means unchanged volume.
+Positive Volume value means increasing volume
+Negative Volume value means decreasing volume
+*/
+func (p *Player) SetVolume(desiredVolume UserVolume) error {
+ speaker.Lock()
+ // clamp value between 1 and 100
+ volume := clampVolume(desiredVolume)
+
+ // Apply the volume settings
+ p.volume.Volume = float64(volume.ToPlayerVolume())
+ p.volume.Silent = volume == MinUserVol
+ speaker.Unlock()
+
+ return nil
+}
+func (p *Player) ChangeVolume(deltaVolume int) error {
+ return p.SetVolume(p.getUserVolume() + UserVolume(deltaVolume))
+}
+
+func (p *Player) getUserVolume() UserVolume {
+ return PlayerVolume(p.volume.Volume).ToUserVolume()
+}
+
+func (p *Player) MuteToggle() error {
+ p.volume.Silent = !p.volume.Silent
+ return nil
+}
+
+// return the current position as an int between 0 and 100 to work with progress bar easily.
+func (p *Player) CurrentPosition() (int, error) {
+ pos := math.Round(100.0 * float64(p.seeker.Position()) / float64(p.seeker.Len()))
+ return int(pos), nil
+}
+
+// TODO: double check best type for percentage parameter
+// percentage comes from the progress bar as a value between 0 and 100
+func (p *Player) Seek(percentage int) error {
+ //take percentage value (0-100), make 0-1, multiply by total number of samples in stream
+ samples := int(math.Round((float64(percentage) / 100.0) * float64(p.seeker.Len())))
+ p.seeker.Seek(samples)
+ return nil
+}
+
+func (p *Player) TrackLengthInSeconds() (int, error) {
+ len := p.seeker.Len() / int(p.format.SampleRate)
+ return len, nil
+}
diff --git a/backend/player/player_test.go b/backend/player/player_test.go
new file mode 100644
index 0000000..488929a
--- /dev/null
+++ b/backend/player/player_test.go
@@ -0,0 +1,42 @@
+package player
+
+import (
+ "context"
+ "testing"
+)
+
+var testQueue = []string{
+ "../../test_data/music_library_test/other_music/03 PONPONPON.mp3",
+ "../../test_data/music_library_test/01 Some Chords.mp3",
+ "../../test_data/music_library_test/03 anything.mp3",
+}
+
+func TestPlayer(t *testing.T) {
+ t.Logf("Starting test")
+ p, err := NewPlayer()
+ if err != nil {
+ t.Errorf("could not create player\n%s", err.Error())
+ t.Failed()
+ }
+ t.Logf("initializing player")
+ err = p.Init(context.Background())
+ if err != nil {
+ t.Errorf("could not initialize player\n%s", err.Error())
+ t.Failed()
+ }
+
+ for _, track := range testQueue {
+ t.Logf("loading file: %s", track)
+ err = p.LoadFile(track)
+ if err != nil {
+ t.Errorf("could not load file\n%s\n%s", track, err.Error())
+ t.Failed()
+ }
+ err = p.Play()
+ if err != nil {
+ t.Errorf("could not play file\n%s\n%s", track, err.Error())
+ t.Failed()
+ }
+ }
+
+}
diff --git a/backend/player/volume.go b/backend/player/volume.go
new file mode 100644
index 0000000..1320e15
--- /dev/null
+++ b/backend/player/volume.go
@@ -0,0 +1,40 @@
+package player
+
+type UserVolume int
+type PlayerVolume float64
+
+const MinUserVol UserVolume = 0
+const MaxUserVol UserVolume = 100
+
+const MinPlayerVol PlayerVolume = -10
+const MaxPlayerVol PlayerVolume = 10
+
+func (oldVol UserVolume) ToPlayerVolume() PlayerVolume {
+ var newVol PlayerVolume
+
+ if oldVol >= MinUserVol && oldVol <= MaxUserVol {
+ ratio := PlayerVolume(oldVol-MinUserVol) / PlayerVolume(MaxUserVol-MinUserVol)
+ newVol = ratio*(MaxPlayerVol-MinPlayerVol) + MinPlayerVol
+ }
+ return newVol
+}
+
+func (oldVolFloat PlayerVolume) ToUserVolume() UserVolume {
+ var newVol UserVolume
+
+ if oldVolFloat >= MinPlayerVol && oldVolFloat <= MaxPlayerVol {
+ ratio := (oldVolFloat - MinPlayerVol) / (MaxPlayerVol - MinPlayerVol)
+ newVol = UserVolume(ratio*PlayerVolume(MaxUserVol-MinUserVol)) + MinUserVol
+ }
+ return newVol
+}
+
+func clampVolume(v UserVolume) UserVolume {
+ if v > MaxUserVol {
+ return MaxUserVol
+ }
+ if v < MinUserVol {
+ return MinUserVol
+ }
+ return v
+}
diff --git a/build/README.md b/build/README.md
deleted file mode 100644
index 1ae2f67..0000000
--- a/build/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Build Directory
-
-The build directory is used to house all the build files and assets for your application.
-
-The structure is:
-
-* bin - Output directory
-* darwin - macOS specific files
-* windows - Windows specific files
-
-## Mac
-
-The `darwin` directory holds files specific to Mac builds.
-These may be customised and used as part of the build. To return these files to the default state, simply delete them
-and
-build with `wails build`.
-
-The directory contains the following files:
-
-- `Info.plist` - the main plist file used for Mac builds. It is used when building using `wails build`.
-- `Info.dev.plist` - same as the main plist file but used when building using `wails dev`.
-
-## Windows
-
-The `windows` directory contains the manifest and rc files used when building with `wails build`.
-These may be customised for your application. To return these files to the default state, simply delete them and
-build with `wails build`.
-
-- `icon.ico` - The icon used for the application. This is used when building using `wails build`. If you wish to
- use a different icon, simply replace this file with your own. If it is missing, a new `icon.ico` file
- will be created using the `appicon.png` file in the build directory.
-- `installer/*` - The files used to create the Windows installer. These are used when building using `wails build`.
-- `info.json` - Application details used for Windows builds. The data here will be used by the Windows installer,
- as well as the application itself (right click the exe -> properties -> details)
-- `wails.exe.manifest` - The main application manifest file.
\ No newline at end of file
diff --git a/build/appicon.png b/build/appicon.png
deleted file mode 100644
index 63617fe..0000000
Binary files a/build/appicon.png and /dev/null differ
diff --git a/build/darwin/Info.dev.plist b/build/darwin/Info.dev.plist
deleted file mode 100644
index 14121ef..0000000
--- a/build/darwin/Info.dev.plist
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
- CFBundlePackageType
- APPL
- CFBundleName
- {{.Info.ProductName}}
- CFBundleExecutable
- {{.OutputFilename}}
- CFBundleIdentifier
- com.wails.{{.Name}}
- CFBundleVersion
- {{.Info.ProductVersion}}
- CFBundleGetInfoString
- {{.Info.Comments}}
- CFBundleShortVersionString
- {{.Info.ProductVersion}}
- CFBundleIconFile
- iconfile
- LSMinimumSystemVersion
- 10.13.0
- NSHighResolutionCapable
- true
- NSHumanReadableCopyright
- {{.Info.Copyright}}
- {{if .Info.FileAssociations}}
- CFBundleDocumentTypes
-
- {{range .Info.FileAssociations}}
-
- CFBundleTypeExtensions
-
- {{.Ext}}
-
- CFBundleTypeName
- {{.Name}}
- CFBundleTypeRole
- {{.Role}}
- CFBundleTypeIconFile
- {{.IconName}}
-
- {{end}}
-
- {{end}}
- {{if .Info.Protocols}}
- CFBundleURLTypes
-
- {{range .Info.Protocols}}
-
- CFBundleURLName
- com.wails.{{.Scheme}}
- CFBundleURLSchemes
-
- {{.Scheme}}
-
- CFBundleTypeRole
- {{.Role}}
-
- {{end}}
-
- {{end}}
- NSAppTransportSecurity
-
- NSAllowsLocalNetworking
-
-
-
-
diff --git a/build/darwin/Info.plist b/build/darwin/Info.plist
deleted file mode 100644
index d17a747..0000000
--- a/build/darwin/Info.plist
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
- CFBundlePackageType
- APPL
- CFBundleName
- {{.Info.ProductName}}
- CFBundleExecutable
- {{.OutputFilename}}
- CFBundleIdentifier
- com.wails.{{.Name}}
- CFBundleVersion
- {{.Info.ProductVersion}}
- CFBundleGetInfoString
- {{.Info.Comments}}
- CFBundleShortVersionString
- {{.Info.ProductVersion}}
- CFBundleIconFile
- iconfile
- LSMinimumSystemVersion
- 10.13.0
- NSHighResolutionCapable
- true
- NSHumanReadableCopyright
- {{.Info.Copyright}}
- {{if .Info.FileAssociations}}
- CFBundleDocumentTypes
-
- {{range .Info.FileAssociations}}
-
- CFBundleTypeExtensions
-
- {{.Ext}}
-
- CFBundleTypeName
- {{.Name}}
- CFBundleTypeRole
- {{.Role}}
- CFBundleTypeIconFile
- {{.IconName}}
-
- {{end}}
-
- {{end}}
- {{if .Info.Protocols}}
- CFBundleURLTypes
-
- {{range .Info.Protocols}}
-
- CFBundleURLName
- com.wails.{{.Scheme}}
- CFBundleURLSchemes
-
- {{.Scheme}}
-
- CFBundleTypeRole
- {{.Role}}
-
- {{end}}
-
- {{end}}
-
-
diff --git a/build/windows/icon.ico b/build/windows/icon.ico
deleted file mode 100644
index f334798..0000000
Binary files a/build/windows/icon.ico and /dev/null differ
diff --git a/build/windows/info.json b/build/windows/info.json
deleted file mode 100644
index 9727946..0000000
--- a/build/windows/info.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "fixed": {
- "file_version": "{{.Info.ProductVersion}}"
- },
- "info": {
- "0000": {
- "ProductVersion": "{{.Info.ProductVersion}}",
- "CompanyName": "{{.Info.CompanyName}}",
- "FileDescription": "{{.Info.ProductName}}",
- "LegalCopyright": "{{.Info.Copyright}}",
- "ProductName": "{{.Info.ProductName}}",
- "Comments": "{{.Info.Comments}}"
- }
- }
-}
\ No newline at end of file
diff --git a/build/windows/installer/project.nsi b/build/windows/installer/project.nsi
deleted file mode 100644
index 654ae2e..0000000
--- a/build/windows/installer/project.nsi
+++ /dev/null
@@ -1,114 +0,0 @@
-Unicode true
-
-####
-## Please note: Template replacements don't work in this file. They are provided with default defines like
-## mentioned underneath.
-## If the keyword is not defined, "wails_tools.nsh" will populate them with the values from ProjectInfo.
-## If they are defined here, "wails_tools.nsh" will not touch them. This allows to use this project.nsi manually
-## from outside of Wails for debugging and development of the installer.
-##
-## For development first make a wails nsis build to populate the "wails_tools.nsh":
-## > wails build --target windows/amd64 --nsis
-## Then you can call makensis on this file with specifying the path to your binary:
-## For a AMD64 only installer:
-## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe
-## For a ARM64 only installer:
-## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe
-## For a installer with both architectures:
-## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe
-####
-## The following information is taken from the ProjectInfo file, but they can be overwritten here.
-####
-## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}"
-## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}"
-## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}"
-## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.Info.ProductVersion}}"
-## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}"
-###
-## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe"
-## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
-####
-## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html
-####
-## Include the wails tools
-####
-!include "wails_tools.nsh"
-
-# The version information for this two must consist of 4 parts
-VIProductVersion "${INFO_PRODUCTVERSION}.0"
-VIFileVersion "${INFO_PRODUCTVERSION}.0"
-
-VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}"
-VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer"
-VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}"
-VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}"
-VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}"
-VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}"
-
-# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware
-ManifestDPIAware true
-
-!include "MUI.nsh"
-
-!define MUI_ICON "..\icon.ico"
-!define MUI_UNICON "..\icon.ico"
-# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314
-!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps
-!define MUI_ABORTWARNING # This will warn the user if they exit from the installer.
-
-!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page.
-# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer
-!insertmacro MUI_PAGE_DIRECTORY # In which folder install page.
-!insertmacro MUI_PAGE_INSTFILES # Installing page.
-!insertmacro MUI_PAGE_FINISH # Finished installation page.
-
-!insertmacro MUI_UNPAGE_INSTFILES # Uinstalling page
-
-!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer
-
-## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1
-#!uninstfinalize 'signtool --file "%1"'
-#!finalize 'signtool --file "%1"'
-
-Name "${INFO_PRODUCTNAME}"
-OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file.
-InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder).
-ShowInstDetails show # This will always show the installation details.
-
-Function .onInit
- !insertmacro wails.checkArchitecture
-FunctionEnd
-
-Section
- !insertmacro wails.setShellContext
-
- !insertmacro wails.webview2runtime
-
- SetOutPath $INSTDIR
-
- !insertmacro wails.files
-
- CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
- CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
-
- !insertmacro wails.associateFiles
- !insertmacro wails.associateCustomProtocols
-
- !insertmacro wails.writeUninstaller
-SectionEnd
-
-Section "uninstall"
- !insertmacro wails.setShellContext
-
- RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath
-
- RMDir /r $INSTDIR
-
- Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
- Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
-
- !insertmacro wails.unassociateFiles
- !insertmacro wails.unassociateCustomProtocols
-
- !insertmacro wails.deleteUninstaller
-SectionEnd
diff --git a/build/windows/installer/wails_tools.nsh b/build/windows/installer/wails_tools.nsh
deleted file mode 100644
index f9c0f88..0000000
--- a/build/windows/installer/wails_tools.nsh
+++ /dev/null
@@ -1,249 +0,0 @@
-# DO NOT EDIT - Generated automatically by `wails build`
-
-!include "x64.nsh"
-!include "WinVer.nsh"
-!include "FileFunc.nsh"
-
-!ifndef INFO_PROJECTNAME
- !define INFO_PROJECTNAME "{{.Name}}"
-!endif
-!ifndef INFO_COMPANYNAME
- !define INFO_COMPANYNAME "{{.Info.CompanyName}}"
-!endif
-!ifndef INFO_PRODUCTNAME
- !define INFO_PRODUCTNAME "{{.Info.ProductName}}"
-!endif
-!ifndef INFO_PRODUCTVERSION
- !define INFO_PRODUCTVERSION "{{.Info.ProductVersion}}"
-!endif
-!ifndef INFO_COPYRIGHT
- !define INFO_COPYRIGHT "{{.Info.Copyright}}"
-!endif
-!ifndef PRODUCT_EXECUTABLE
- !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe"
-!endif
-!ifndef UNINST_KEY_NAME
- !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}"
-!endif
-!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}"
-
-!ifndef REQUEST_EXECUTION_LEVEL
- !define REQUEST_EXECUTION_LEVEL "admin"
-!endif
-
-RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
-
-!ifdef ARG_WAILS_AMD64_BINARY
- !define SUPPORTS_AMD64
-!endif
-
-!ifdef ARG_WAILS_ARM64_BINARY
- !define SUPPORTS_ARM64
-!endif
-
-!ifdef SUPPORTS_AMD64
- !ifdef SUPPORTS_ARM64
- !define ARCH "amd64_arm64"
- !else
- !define ARCH "amd64"
- !endif
-!else
- !ifdef SUPPORTS_ARM64
- !define ARCH "arm64"
- !else
- !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY"
- !endif
-!endif
-
-!macro wails.checkArchitecture
- !ifndef WAILS_WIN10_REQUIRED
- !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later."
- !endif
-
- !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED
- !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}"
- !endif
-
- ${If} ${AtLeastWin10}
- !ifdef SUPPORTS_AMD64
- ${if} ${IsNativeAMD64}
- Goto ok
- ${EndIf}
- !endif
-
- !ifdef SUPPORTS_ARM64
- ${if} ${IsNativeARM64}
- Goto ok
- ${EndIf}
- !endif
-
- IfSilent silentArch notSilentArch
- silentArch:
- SetErrorLevel 65
- Abort
- notSilentArch:
- MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}"
- Quit
- ${else}
- IfSilent silentWin notSilentWin
- silentWin:
- SetErrorLevel 64
- Abort
- notSilentWin:
- MessageBox MB_OK "${WAILS_WIN10_REQUIRED}"
- Quit
- ${EndIf}
-
- ok:
-!macroend
-
-!macro wails.files
- !ifdef SUPPORTS_AMD64
- ${if} ${IsNativeAMD64}
- File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}"
- ${EndIf}
- !endif
-
- !ifdef SUPPORTS_ARM64
- ${if} ${IsNativeARM64}
- File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}"
- ${EndIf}
- !endif
-!macroend
-
-!macro wails.writeUninstaller
- WriteUninstaller "$INSTDIR\uninstall.exe"
-
- SetRegView 64
- WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}"
- WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}"
- WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
- WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
-
- ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
- IntFmt $0 "0x%08X" $0
- WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0"
-!macroend
-
-!macro wails.deleteUninstaller
- Delete "$INSTDIR\uninstall.exe"
-
- SetRegView 64
- DeleteRegKey HKLM "${UNINST_KEY}"
-!macroend
-
-!macro wails.setShellContext
- ${If} ${REQUEST_EXECUTION_LEVEL} == "admin"
- SetShellVarContext all
- ${else}
- SetShellVarContext current
- ${EndIf}
-!macroend
-
-# Install webview2 by launching the bootstrapper
-# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment
-!macro wails.webview2runtime
- !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT
- !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime"
- !endif
-
- SetRegView 64
- # If the admin key exists and is not empty then webview2 is already installed
- ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- ${If} $0 != ""
- Goto ok
- ${EndIf}
-
- ${If} ${REQUEST_EXECUTION_LEVEL} == "user"
- # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed
- ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv"
- ${If} $0 != ""
- Goto ok
- ${EndIf}
- ${EndIf}
-
- SetDetailsPrint both
- DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}"
- SetDetailsPrint listonly
-
- InitPluginsDir
- CreateDirectory "$pluginsdir\webview2bootstrapper"
- SetOutPath "$pluginsdir\webview2bootstrapper"
- File "tmp\MicrosoftEdgeWebview2Setup.exe"
- ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install'
-
- SetDetailsPrint both
- ok:
-!macroend
-
-# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b
-!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
- ; Backup the previously associated file class
- ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
- WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
-
- WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
-
- WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
- WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
- WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
- WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
- WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
-!macroend
-
-!macro APP_UNASSOCIATE EXT FILECLASS
- ; Backup the previously associated file class
- ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
- WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
-
- DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
-!macroend
-
-!macro wails.associateFiles
- ; Create file associations
- {{range .Info.FileAssociations}}
- !insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
-
- File "..\{{.IconName}}.ico"
- {{end}}
-!macroend
-
-!macro wails.unassociateFiles
- ; Delete app associations
- {{range .Info.FileAssociations}}
- !insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}"
-
- Delete "$INSTDIR\{{.IconName}}.ico"
- {{end}}
-!macroend
-
-!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND
- DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
- WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}"
- WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" ""
- WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}"
- WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" ""
- WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" ""
- WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}"
-!macroend
-
-!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL
- DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}"
-!macroend
-
-!macro wails.associateCustomProtocols
- ; Create custom protocols associations
- {{range .Info.Protocols}}
- !insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
-
- {{end}}
-!macroend
-
-!macro wails.unassociateCustomProtocols
- ; Delete app custom protocol associations
- {{range .Info.Protocols}}
- !insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}"
- {{end}}
-!macroend
diff --git a/build/windows/wails.exe.manifest b/build/windows/wails.exe.manifest
deleted file mode 100644
index 17e1a23..0000000
--- a/build/windows/wails.exe.manifest
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- true/pm
- permonitorv2,permonitor
-
-
-
\ No newline at end of file
diff --git a/docs/dev/resources.md b/docs/dev/resources.md
new file mode 100644
index 0000000..6ddd676
--- /dev/null
+++ b/docs/dev/resources.md
@@ -0,0 +1,8 @@
+# Cool Links
+
+## Frontend
+
+### Lit
+
+- https://lit.dev/docs/
+- https://github.com/web-padawan/awesome-lit
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000..d255e21
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,59 @@
+# YellowJacket Frontend
+
+This directory contains the frontend for YellowJacket.
+
+## Dependencies
+
+There are a couple of tools that are required to build and use the frontend.
+
+- [`vite`](https://vite.dev/) for
+ - transpiling typescript
+ - bundling the final "package" that is useb by the webview
+ - running a dev server with hot-reloading
+ - configured with the [`vite.config.ts`](./vite.config.ts) file in this directory
+- [`pnpm`](https://pnpm.io/) for managing frontend dependency packages
+
+There are a handful of dependency packages that we use directly in the frontend.
+
+- [`picocss`](https://picocss.com) for basic CSS while developing
+- [`lit`](https://lit.dev) for a simple but powerful wrapper around [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components)
+
+Lastly, there are some dependencies that only benefit development
+
+- `tsserver` comes bundled with vscode and can be used as an LSP with other editors using [`typescript-language-server`](https://github.com/typescript-language-server/typescript-language-server)
+ - Used for autocomplete, syntax highlighting, etc.
+ - This can be configured with the `tsconfig.json` file in the root of the project
+ - NOTE: your configuration should align with the `vite` config so you get in-editor feedback that aligns with how the build will be done.
+
+## Development
+
+Ideally, you would use the frontend in the wails app as the frontend depends on the Go bindings generated by Wails.
+You can do this by running `wails dev` in the root of the YellowJacket repo.
+
+If you want to run the frontend standalone, make sure the Wails go bindings have been generated with `wails generate modules`.
+Then, you can run `pnpm dev` to run the vite dev server.
+For more information on what commands are available, refer to `package.json`.
+
+## Code
+
+### Web Components
+
+Our frontend is based off of Web Components, a standard that provides native browser encapsulation of components that can include HTML, CSS and Javascript all together.
+Instead of writing these components manually in Javascript, we utilize `lit` as a wrapper library.
+
+### Typescript
+
+To better integrate with our tooling and to provide a better developer experience with strong typing, we have written all functional frontend code in Typescript.
+Vite serves as our Typescript transpiler.
+
+### Important Files and Directories
+
+NOTE: most of these directories have aliases defined in `tsconfig.json` and `vite.config.ts` so that we may refer to them by shorthand when importing.
+
+- `index.html` and `index.js` is the entrypoint for the frontend. The first page that loads.
+- `wailsjs/go` Go code bindings generated by wails reside here
+- `wailsjs/runtime` the Wails runtime code needed to use Wails features
+- `src` all app code resides here
+- `src/assets` static assets like fonts, images and icons
+- `src/components` lit components that are used to compose the application
+- `src/pages` pages that serve as other entrypoints for the application that can be navigated to
diff --git a/frontend/index.css b/frontend/index.css
new file mode 100644
index 0000000..1bee9c0
--- /dev/null
+++ b/frontend/index.css
@@ -0,0 +1,4 @@
+body {
+ background-color: black;
+ color: white;
+}
diff --git a/frontend/index.html b/frontend/index.html
index 944889a..9fffb7b 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,12 +1,49 @@
+
-
-
+
+
+
yellowjacket
+
+
-
-
+
+
+
+
+
+
+
+
diff --git a/frontend/index.ts b/frontend/index.ts
new file mode 100644
index 0000000..84bf224
--- /dev/null
+++ b/frontend/index.ts
@@ -0,0 +1,5 @@
+import '@components/audio-player/audio-player.ts';
+import '@node_modules/@shoelace-style/shoelace/dist/themes/light.css';
+import { setBasePath } from '@node_modules/@shoelace-style/shoelace/dist/utilities/base-path';
+
+setBasePath("dist/shoelace")
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
deleted file mode 100644
index a70af4f..0000000
--- a/frontend/package-lock.json
+++ /dev/null
@@ -1,653 +0,0 @@
-{
- "name": "frontend",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "frontend",
- "version": "0.0.0",
- "devDependencies": {
- "vite": "^3.0.7"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
- "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
- "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
- "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/android-arm": "0.15.18",
- "@esbuild/linux-loong64": "0.15.18",
- "esbuild-android-64": "0.15.18",
- "esbuild-android-arm64": "0.15.18",
- "esbuild-darwin-64": "0.15.18",
- "esbuild-darwin-arm64": "0.15.18",
- "esbuild-freebsd-64": "0.15.18",
- "esbuild-freebsd-arm64": "0.15.18",
- "esbuild-linux-32": "0.15.18",
- "esbuild-linux-64": "0.15.18",
- "esbuild-linux-arm": "0.15.18",
- "esbuild-linux-arm64": "0.15.18",
- "esbuild-linux-mips64le": "0.15.18",
- "esbuild-linux-ppc64le": "0.15.18",
- "esbuild-linux-riscv64": "0.15.18",
- "esbuild-linux-s390x": "0.15.18",
- "esbuild-netbsd-64": "0.15.18",
- "esbuild-openbsd-64": "0.15.18",
- "esbuild-sunos-64": "0.15.18",
- "esbuild-windows-32": "0.15.18",
- "esbuild-windows-64": "0.15.18",
- "esbuild-windows-arm64": "0.15.18"
- }
- },
- "node_modules/esbuild-android-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
- "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-android-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
- "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-darwin-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
- "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-darwin-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
- "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-freebsd-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
- "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-freebsd-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
- "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-32": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
- "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
- "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-arm": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
- "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
- "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-mips64le": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
- "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-ppc64le": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
- "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-riscv64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
- "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-linux-s390x": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
- "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-netbsd-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
- "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-openbsd-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
- "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-sunos-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
- "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-32": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
- "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
- "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/esbuild-windows-arm64": {
- "version": "0.15.18",
- "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
- "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/postcss": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
- "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.8",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.10",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
- "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-core-module": "^2.16.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/rollup": {
- "version": "2.79.2",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
- "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=10.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/vite": {
- "version": "3.2.11",
- "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.11.tgz",
- "integrity": "sha512-K/jGKL/PgbIgKCiJo5QbASQhFiV02X9Jh+Qq0AKCRCRKZtOTVi4t6wh75FDpGf2N9rYOnzH87OEFQNaFy6pdxQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "esbuild": "^0.15.9",
- "postcss": "^8.4.18",
- "resolve": "^1.22.1",
- "rollup": "^2.79.1"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- },
- "peerDependencies": {
- "@types/node": ">= 14",
- "less": "*",
- "sass": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- }
- }
-}
diff --git a/frontend/package.json b/frontend/package.json
index a1b6f8e..62eb2bb 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,13 +1,19 @@
{
- "name": "frontend",
- "private": true,
- "version": "0.0.0",
- "scripts": {
- "dev": "vite",
- "build": "vite build",
- "preview": "vite preview"
- },
- "devDependencies": {
- "vite": "^3.0.7"
- }
-}
\ No newline at end of file
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@lit-labs/signals": "^0.1.2",
+ "@shoelace-style/shoelace": "^2.20.1",
+ "lit": "^3.2.1"
+ },
+ "devDependencies": {
+ "ts-lit-plugin": "^2.0.2",
+ "typescript-lit-html-plugin": "^0.9.0",
+ "vite": "^6.2.3",
+ "vite-plugin-static-copy": "^2.3.1",
+ "vite-tsconfig-paths": "^5.1.4"
+ }
+}
diff --git a/frontend/package.json.md5 b/frontend/package.json.md5
index d4671a1..eeb7c11 100755
--- a/frontend/package.json.md5
+++ b/frontend/package.json.md5
@@ -1 +1 @@
-5fbf12469d224a93954efecb5886e8a6
\ No newline at end of file
+1f0c68f2bbba06f2a24fb43e1238cb42
\ No newline at end of file
diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml
new file mode 100644
index 0000000..49a5e94
--- /dev/null
+++ b/frontend/pnpm-lock.yaml
@@ -0,0 +1,1389 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@lit-labs/signals':
+ specifier: ^0.1.2
+ version: 0.1.2
+ '@shoelace-style/shoelace':
+ specifier: ^2.20.1
+ version: 2.20.1(@floating-ui/utils@0.2.9)(@types/react@19.1.0)
+ lit:
+ specifier: ^3.2.1
+ version: 3.2.1
+ devDependencies:
+ ts-lit-plugin:
+ specifier: ^2.0.2
+ version: 2.0.2
+ typescript-lit-html-plugin:
+ specifier: ^0.9.0
+ version: 0.9.0
+ vite:
+ specifier: ^6.2.3
+ version: 6.2.3
+ vite-plugin-static-copy:
+ specifier: ^2.3.1
+ version: 2.3.1(vite@6.2.3)
+ vite-tsconfig-paths:
+ specifier: ^5.1.4
+ version: 5.1.4(typescript@5.2.2)(vite@6.2.3)
+
+packages:
+
+ '@babel/runtime@7.27.0':
+ resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==}
+ engines: {node: '>=6.9.0'}
+
+ '@ctrl/tinycolor@4.1.0':
+ resolution: {integrity: sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==}
+ engines: {node: '>=14'}
+
+ '@emmetio/extract-abbreviation@0.1.6':
+ resolution: {integrity: sha512-Ce3xE2JvTSEbASFbRbA1gAIcMcZWdS2yUYRaQbeM0nbOzaZrUYfa3ePtcriYRZOZmr+CkKA+zbjhvTpIOAYVcw==}
+
+ '@esbuild/aix-ppc64@0.25.1':
+ resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.25.1':
+ resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.25.1':
+ resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.25.1':
+ resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.25.1':
+ resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.25.1':
+ resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.25.1':
+ resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.25.1':
+ resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.25.1':
+ resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.25.1':
+ resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.25.1':
+ resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.25.1':
+ resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.25.1':
+ resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.25.1':
+ resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.25.1':
+ resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.25.1':
+ resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.25.1':
+ resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.25.1':
+ resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.25.1':
+ resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.25.1':
+ resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.25.1':
+ resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/sunos-x64@0.25.1':
+ resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.25.1':
+ resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.25.1':
+ resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.25.1':
+ resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@floating-ui/core@1.6.9':
+ resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==}
+
+ '@floating-ui/dom@1.6.13':
+ resolution: {integrity: sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==}
+
+ '@floating-ui/utils@0.2.9':
+ resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==}
+
+ '@lit-labs/signals@0.1.2':
+ resolution: {integrity: sha512-hkOL0ua4ILeHlaJ8IqFKS+Y+dpYznWaDhdikzwt3zJ1/LPz3Etft4OPIMoltzbBJS5pyXPRseD/uWRlET3ImEA==}
+
+ '@lit-labs/ssr-dom-shim@1.3.0':
+ resolution: {integrity: sha512-nQIWonJ6eFAvUUrSlwyHDm/aE8PBDu5kRpL0vHMg6K8fK3Diq1xdPjTnsJSwxABhaZ+5eBi1btQB5ShUTKo4nQ==}
+
+ '@lit/react@1.0.7':
+ resolution: {integrity: sha512-cencnwwLXQKiKxjfFzSgZRngcWJzUDZi/04E0fSaF86wZgchMdvTyu+lE36DrUfvuus3bH8+xLPrhM1cTjwpzw==}
+ peerDependencies:
+ '@types/react': 17 || 18 || 19
+
+ '@lit/reactive-element@2.0.4':
+ resolution: {integrity: sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==}
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@rollup/rollup-android-arm-eabi@4.37.0':
+ resolution: {integrity: sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.37.0':
+ resolution: {integrity: sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.37.0':
+ resolution: {integrity: sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.37.0':
+ resolution: {integrity: sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.37.0':
+ resolution: {integrity: sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.37.0':
+ resolution: {integrity: sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.37.0':
+ resolution: {integrity: sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.37.0':
+ resolution: {integrity: sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.37.0':
+ resolution: {integrity: sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.37.0':
+ resolution: {integrity: sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.37.0':
+ resolution: {integrity: sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.37.0':
+ resolution: {integrity: sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.37.0':
+ resolution: {integrity: sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.37.0':
+ resolution: {integrity: sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.37.0':
+ resolution: {integrity: sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.37.0':
+ resolution: {integrity: sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.37.0':
+ resolution: {integrity: sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-win32-arm64-msvc@4.37.0':
+ resolution: {integrity: sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.37.0':
+ resolution: {integrity: sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.37.0':
+ resolution: {integrity: sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==}
+ cpu: [x64]
+ os: [win32]
+
+ '@shoelace-style/animations@1.2.0':
+ resolution: {integrity: sha512-avvo1xxkLbv2dgtabdewBbqcJfV0e0zCwFqkPMnHFGbJbBHorRFfMAHh1NG9ymmXn0jW95ibUVH03E1NYXD6Gw==}
+
+ '@shoelace-style/localize@3.2.1':
+ resolution: {integrity: sha512-r4C9C/5kSfMBIr0D9imvpRdCNXtUNgyYThc4YlS6K5Hchv1UyxNQ9mxwj+BTRH2i1Neits260sR3OjKMnplsFA==}
+
+ '@shoelace-style/shoelace@2.20.1':
+ resolution: {integrity: sha512-FSghU95jZPGbwr/mybVvk66qRZYpx5FkXL+vLNpy1Vp8UsdwSxXjIHE3fsvMbKWTKi9UFfewHTkc5e7jAqRYoQ==}
+ engines: {node: '>=14.17.0'}
+
+ '@types/estree@1.0.6':
+ resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==}
+
+ '@types/react@19.1.0':
+ resolution: {integrity: sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==}
+
+ '@types/trusted-types@2.0.7':
+ resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
+
+ '@vscode/web-custom-data@0.4.13':
+ resolution: {integrity: sha512-2ZUIRfhofZ/npLlf872EBnPmn27Kt4M2UssmQIfnJvgGgMYZJ5fvtHEDnttBBf2hnVtBgNCqZMVHJA+wsFVqTA==}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
+ color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ composed-offset-position@0.0.6:
+ resolution: {integrity: sha512-Q7dLompI6lUwd7LWyIcP66r4WcS9u7AL2h8HaeipiRfCRPLMWqRx8fYsjb4OHi6UQFifO7XtNC2IlEJ1ozIFxw==}
+ peerDependencies:
+ '@floating-ui/utils': ^0.2.5
+
+ csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+
+ debug@4.4.0:
+ resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ didyoumean2@4.1.0:
+ resolution: {integrity: sha512-qTBmfQoXvhKO75D/05C8m+fteQmn4U46FWYiLhXtZQInzitXLWY0EQ/2oKnpAz9g2lQWW8jYcLcT+hPJGT+kig==}
+ engines: {node: '>=10.13'}
+
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
+ esbuild@0.25.1:
+ resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fastq@1.19.1:
+ resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ fs-extra@11.3.0:
+ resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
+ engines: {node: '>=14.14'}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ globrex@0.1.2:
+ resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ jsonc-parser@1.0.3:
+ resolution: {integrity: sha512-hk/69oAeaIzchq/v3lS50PXuzn5O2ynldopMC+SWBql7J2WtdptfB9dy8Y7+Og5rPkTCpn83zTiO8FMcqlXJ/g==}
+
+ jsonfile@6.1.0:
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+
+ leven@3.1.0:
+ resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==}
+ engines: {node: '>=6'}
+
+ lit-analyzer@2.0.3:
+ resolution: {integrity: sha512-XiAjnwVipNrKav7r3CSEZpWt+mwYxrhPRVC7h8knDmn/HWTzzWJvPe+mwBcL2brn4xhItAMzZhFC8tzzqHKmiQ==}
+ hasBin: true
+
+ lit-element@4.1.1:
+ resolution: {integrity: sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==}
+
+ lit-html@3.2.1:
+ resolution: {integrity: sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==}
+
+ lit@3.2.1:
+ resolution: {integrity: sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==}
+
+ lodash.deburr@4.1.0:
+ resolution: {integrity: sha512-m/M1U1f3ddMCs6Hq2tAsYThTBDaAKFDX3dwDo97GEYzamXi9SqUpjWi/Rrj/gf3X2n8ktwgZrlP1z6E3v/IExQ==}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ p-map@7.0.3:
+ resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==}
+ engines: {node: '>=18'}
+
+ parse5@5.1.0:
+ resolution: {integrity: sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ postcss@8.5.3:
+ resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ qr-creator@1.0.0:
+ resolution: {integrity: sha512-C0cqfbS1P5hfqN4NhsYsUXePlk9BO+a45bAQ3xLYjBL3bOIFzoVEjs79Fado9u9BPBD3buHi3+vY+C8tHh4qMQ==}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
+ regenerator-runtime@0.14.1:
+ resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
+
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rollup@4.37.0:
+ resolution: {integrity: sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ signal-polyfill@0.2.2:
+ resolution: {integrity: sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
+ supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ ts-lit-plugin@2.0.2:
+ resolution: {integrity: sha512-DPXlVxhjWHxg8AyBLcfSYt2JXgpANV1ssxxwjY98o26gD8MzeiM68HFW9c2VeDd1CjoR3w7B/6/uKxwBQe+ioA==}
+
+ ts-simple-type@2.0.0-next.0:
+ resolution: {integrity: sha512-A+hLX83gS+yH6DtzNAhzZbPfU+D9D8lHlTSd7GeoMRBjOt3GRylDqLTYbdmjA4biWvq2xSfpqfIDj2l0OA/BVg==}
+
+ tsconfck@3.1.5:
+ resolution: {integrity: sha512-CLDfGgUp7XPswWnezWwsCRxNmgQjhYq3VXHM0/XIRxhVrKw0M1if9agzryh1QS3nxjCROvV+xWxoJO1YctzzWg==}
+ engines: {node: ^18 || >=20}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ typescript-lit-html-plugin@0.9.0:
+ resolution: {integrity: sha512-Ux2I1sPpt2akNbRZiBAND9oA8XNE2BuVmDwsb7rZshJ9T8/Na2rICE5Tnuj9dPHdFUATdOGjVEagn1/v8T4gCQ==}
+
+ typescript-styled-plugin@0.13.0:
+ resolution: {integrity: sha512-GGMzv/JAd4S8mvWgHZslvW2G1HHrdurrp93oSR4h85SM8e5at7+KCqHsZICiTaL+iN25YGkJqoaZe4XklA76rg==}
+ deprecated: Deprecated in favor of https://github.com/styled-components/typescript-styled-plugin
+
+ typescript-template-language-service-decorator@2.3.2:
+ resolution: {integrity: sha512-hN0zNkr5luPCeXTlXKxsfBPlkAzx86ZRM1vPdL7DbEqqWoeXSxplACy98NpKpLmXsdq7iePUzAXloCAoPKBV6A==}
+
+ typescript@5.2.2:
+ resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+
+ vite-plugin-static-copy@2.3.1:
+ resolution: {integrity: sha512-EfsPcBm3ewg3UMG8RJaC0ADq6/qnUZnokXx4By4+2cAcipjT9i0Y0owIJGqmZI7d6nxk4qB1q5aXOwNuSyPdyA==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ vite: ^5.0.0 || ^6.0.0
+
+ vite-tsconfig-paths@5.1.4:
+ resolution: {integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==}
+ peerDependencies:
+ vite: '*'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
+ vite@6.2.3:
+ resolution: {integrity: sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ jiti: '>=1.21.0'
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ sass-embedded: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vscode-css-languageservice@3.0.13:
+ resolution: {integrity: sha512-RWkO/c/A7iXhHEy3OuEqkCqavDjpD4NF2Ca8vjai+ZtEYNeHrm1ybTnBYLP4Ft1uXvvaaVtYA9HrDjD6+CUONg==}
+
+ vscode-css-languageservice@4.3.0:
+ resolution: {integrity: sha512-BkQAMz4oVHjr0oOAz5PdeE72txlLQK7NIwzmclfr+b6fj6I8POwB+VoXvrZLTbWt9hWRgfvgiQRkh5JwrjPJ5A==}
+
+ vscode-emmet-helper@1.2.11:
+ resolution: {integrity: sha512-ms6/Z9TfNbjXS8r/KgbGxrNrFlu4RcIfVJxTZ2yFi0K4gn+Ka9X1+8cXvb5+5IOBGUrOsPjR0BuefdDkG+CKbQ==}
+ deprecated: This package has been renamed to @vscode/emmet-helper, please update to the new name
+
+ vscode-html-languageservice@2.1.12:
+ resolution: {integrity: sha512-mIb5VMXM5jI97HzCk2eadI1K//rCEZXte0wBqA7PGXsyJH4KTyJUaYk9MR+mbfpUl2vMi3HZw9GUOLGYLc6l5w==}
+
+ vscode-html-languageservice@3.1.0:
+ resolution: {integrity: sha512-QAyRHI98bbEIBCqTzZVA0VblGU40na0txggongw5ZgTj9UVsVk5XbLT16O9OTcbqBGSqn0oWmFDNjK/XGIDcqg==}
+
+ vscode-languageserver-textdocument@1.0.12:
+ resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==}
+
+ vscode-languageserver-types@3.16.0-next.2:
+ resolution: {integrity: sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q==}
+
+ vscode-languageserver-types@3.17.5:
+ resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
+
+ vscode-nls@4.1.2:
+ resolution: {integrity: sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw==}
+
+ vscode-uri@1.0.8:
+ resolution: {integrity: sha512-obtSWTlbJ+a+TFRYGaUumtVwb+InIUVI0Lu0VBUAPmj2cU5JutEXg3xUE0c2J5Tcy7h2DEKVJBFi+Y9ZSFzzPQ==}
+
+ vscode-uri@2.1.2:
+ resolution: {integrity: sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A==}
+
+ web-component-analyzer@2.0.0:
+ resolution: {integrity: sha512-UEvwfpD+XQw99sLKiH5B1T4QwpwNyWJxp59cnlRwFfhUW6JsQpw5jMeMwi7580sNou8YL3kYoS7BWLm+yJ/jVQ==}
+ hasBin: true
+
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+
+snapshots:
+
+ '@babel/runtime@7.27.0':
+ dependencies:
+ regenerator-runtime: 0.14.1
+
+ '@ctrl/tinycolor@4.1.0': {}
+
+ '@emmetio/extract-abbreviation@0.1.6': {}
+
+ '@esbuild/aix-ppc64@0.25.1':
+ optional: true
+
+ '@esbuild/android-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/android-arm@0.25.1':
+ optional: true
+
+ '@esbuild/android-x64@0.25.1':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/darwin-x64@0.25.1':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.25.1':
+ optional: true
+
+ '@esbuild/linux-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/linux-arm@0.25.1':
+ optional: true
+
+ '@esbuild/linux-ia32@0.25.1':
+ optional: true
+
+ '@esbuild/linux-loong64@0.25.1':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.25.1':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.25.1':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.25.1':
+ optional: true
+
+ '@esbuild/linux-s390x@0.25.1':
+ optional: true
+
+ '@esbuild/linux-x64@0.25.1':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.25.1':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.25.1':
+ optional: true
+
+ '@esbuild/sunos-x64@0.25.1':
+ optional: true
+
+ '@esbuild/win32-arm64@0.25.1':
+ optional: true
+
+ '@esbuild/win32-ia32@0.25.1':
+ optional: true
+
+ '@esbuild/win32-x64@0.25.1':
+ optional: true
+
+ '@floating-ui/core@1.6.9':
+ dependencies:
+ '@floating-ui/utils': 0.2.9
+
+ '@floating-ui/dom@1.6.13':
+ dependencies:
+ '@floating-ui/core': 1.6.9
+ '@floating-ui/utils': 0.2.9
+
+ '@floating-ui/utils@0.2.9': {}
+
+ '@lit-labs/signals@0.1.2':
+ dependencies:
+ lit: 3.2.1
+ signal-polyfill: 0.2.2
+
+ '@lit-labs/ssr-dom-shim@1.3.0': {}
+
+ '@lit/react@1.0.7(@types/react@19.1.0)':
+ dependencies:
+ '@types/react': 19.1.0
+
+ '@lit/reactive-element@2.0.4':
+ dependencies:
+ '@lit-labs/ssr-dom-shim': 1.3.0
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.19.1
+
+ '@rollup/rollup-android-arm-eabi@4.37.0':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.37.0':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.37.0':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.37.0':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.37.0':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-loongarch64-gnu@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-powerpc64le-gnu@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.37.0':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.37.0':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.37.0':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.37.0':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.37.0':
+ optional: true
+
+ '@shoelace-style/animations@1.2.0': {}
+
+ '@shoelace-style/localize@3.2.1': {}
+
+ '@shoelace-style/shoelace@2.20.1(@floating-ui/utils@0.2.9)(@types/react@19.1.0)':
+ dependencies:
+ '@ctrl/tinycolor': 4.1.0
+ '@floating-ui/dom': 1.6.13
+ '@lit/react': 1.0.7(@types/react@19.1.0)
+ '@shoelace-style/animations': 1.2.0
+ '@shoelace-style/localize': 3.2.1
+ composed-offset-position: 0.0.6(@floating-ui/utils@0.2.9)
+ lit: 3.2.1
+ qr-creator: 1.0.0
+ transitivePeerDependencies:
+ - '@floating-ui/utils'
+ - '@types/react'
+
+ '@types/estree@1.0.6': {}
+
+ '@types/react@19.1.0':
+ dependencies:
+ csstype: 3.1.3
+
+ '@types/trusted-types@2.0.7': {}
+
+ '@vscode/web-custom-data@0.4.13': {}
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@3.2.1:
+ dependencies:
+ color-convert: 1.9.3
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ binary-extensions@2.3.0: {}
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ chalk@2.4.2:
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+
+ chokidar@3.6.0:
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.3
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ color-convert@1.9.3:
+ dependencies:
+ color-name: 1.1.3
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.3: {}
+
+ color-name@1.1.4: {}
+
+ composed-offset-position@0.0.6(@floating-ui/utils@0.2.9):
+ dependencies:
+ '@floating-ui/utils': 0.2.9
+
+ csstype@3.1.3: {}
+
+ debug@4.4.0:
+ dependencies:
+ ms: 2.1.3
+
+ didyoumean2@4.1.0:
+ dependencies:
+ '@babel/runtime': 7.27.0
+ leven: 3.1.0
+ lodash.deburr: 4.1.0
+
+ emoji-regex@8.0.0: {}
+
+ esbuild@0.25.1:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.25.1
+ '@esbuild/android-arm': 0.25.1
+ '@esbuild/android-arm64': 0.25.1
+ '@esbuild/android-x64': 0.25.1
+ '@esbuild/darwin-arm64': 0.25.1
+ '@esbuild/darwin-x64': 0.25.1
+ '@esbuild/freebsd-arm64': 0.25.1
+ '@esbuild/freebsd-x64': 0.25.1
+ '@esbuild/linux-arm': 0.25.1
+ '@esbuild/linux-arm64': 0.25.1
+ '@esbuild/linux-ia32': 0.25.1
+ '@esbuild/linux-loong64': 0.25.1
+ '@esbuild/linux-mips64el': 0.25.1
+ '@esbuild/linux-ppc64': 0.25.1
+ '@esbuild/linux-riscv64': 0.25.1
+ '@esbuild/linux-s390x': 0.25.1
+ '@esbuild/linux-x64': 0.25.1
+ '@esbuild/netbsd-arm64': 0.25.1
+ '@esbuild/netbsd-x64': 0.25.1
+ '@esbuild/openbsd-arm64': 0.25.1
+ '@esbuild/openbsd-x64': 0.25.1
+ '@esbuild/sunos-x64': 0.25.1
+ '@esbuild/win32-arm64': 0.25.1
+ '@esbuild/win32-ia32': 0.25.1
+ '@esbuild/win32-x64': 0.25.1
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@1.0.5: {}
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fastq@1.19.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ fs-extra@11.3.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+
+ fsevents@2.3.3:
+ optional: true
+
+ get-caller-file@2.0.5: {}
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ globrex@0.1.2: {}
+
+ graceful-fs@4.2.11: {}
+
+ has-flag@3.0.0: {}
+
+ is-binary-path@2.1.0:
+ dependencies:
+ binary-extensions: 2.3.0
+
+ is-extglob@2.1.1: {}
+
+ is-fullwidth-code-point@3.0.0: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-number@7.0.0: {}
+
+ jsonc-parser@1.0.3: {}
+
+ jsonfile@6.1.0:
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ leven@3.1.0: {}
+
+ lit-analyzer@2.0.3:
+ dependencies:
+ '@vscode/web-custom-data': 0.4.13
+ chalk: 2.4.2
+ didyoumean2: 4.1.0
+ fast-glob: 3.3.3
+ parse5: 5.1.0
+ ts-simple-type: 2.0.0-next.0
+ vscode-css-languageservice: 4.3.0
+ vscode-html-languageservice: 3.1.0
+ web-component-analyzer: 2.0.0
+
+ lit-element@4.1.1:
+ dependencies:
+ '@lit-labs/ssr-dom-shim': 1.3.0
+ '@lit/reactive-element': 2.0.4
+ lit-html: 3.2.1
+
+ lit-html@3.2.1:
+ dependencies:
+ '@types/trusted-types': 2.0.7
+
+ lit@3.2.1:
+ dependencies:
+ '@lit/reactive-element': 2.0.4
+ lit-element: 4.1.1
+ lit-html: 3.2.1
+
+ lodash.deburr@4.1.0: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ ms@2.1.3: {}
+
+ nanoid@3.3.11: {}
+
+ normalize-path@3.0.0: {}
+
+ p-map@7.0.3: {}
+
+ parse5@5.1.0: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ postcss@8.5.3:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ qr-creator@1.0.0: {}
+
+ queue-microtask@1.2.3: {}
+
+ readdirp@3.6.0:
+ dependencies:
+ picomatch: 2.3.1
+
+ regenerator-runtime@0.14.1: {}
+
+ require-directory@2.1.1: {}
+
+ reusify@1.1.0: {}
+
+ rollup@4.37.0:
+ dependencies:
+ '@types/estree': 1.0.6
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.37.0
+ '@rollup/rollup-android-arm64': 4.37.0
+ '@rollup/rollup-darwin-arm64': 4.37.0
+ '@rollup/rollup-darwin-x64': 4.37.0
+ '@rollup/rollup-freebsd-arm64': 4.37.0
+ '@rollup/rollup-freebsd-x64': 4.37.0
+ '@rollup/rollup-linux-arm-gnueabihf': 4.37.0
+ '@rollup/rollup-linux-arm-musleabihf': 4.37.0
+ '@rollup/rollup-linux-arm64-gnu': 4.37.0
+ '@rollup/rollup-linux-arm64-musl': 4.37.0
+ '@rollup/rollup-linux-loongarch64-gnu': 4.37.0
+ '@rollup/rollup-linux-powerpc64le-gnu': 4.37.0
+ '@rollup/rollup-linux-riscv64-gnu': 4.37.0
+ '@rollup/rollup-linux-riscv64-musl': 4.37.0
+ '@rollup/rollup-linux-s390x-gnu': 4.37.0
+ '@rollup/rollup-linux-x64-gnu': 4.37.0
+ '@rollup/rollup-linux-x64-musl': 4.37.0
+ '@rollup/rollup-win32-arm64-msvc': 4.37.0
+ '@rollup/rollup-win32-ia32-msvc': 4.37.0
+ '@rollup/rollup-win32-x64-msvc': 4.37.0
+ fsevents: 2.3.3
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ signal-polyfill@0.2.2: {}
+
+ source-map-js@1.2.1: {}
+
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
+ supports-color@5.5.0:
+ dependencies:
+ has-flag: 3.0.0
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ ts-lit-plugin@2.0.2:
+ dependencies:
+ lit-analyzer: 2.0.3
+ web-component-analyzer: 2.0.0
+
+ ts-simple-type@2.0.0-next.0: {}
+
+ tsconfck@3.1.5(typescript@5.2.2):
+ optionalDependencies:
+ typescript: 5.2.2
+
+ typescript-lit-html-plugin@0.9.0:
+ dependencies:
+ typescript-styled-plugin: 0.13.0
+ typescript-template-language-service-decorator: 2.3.2
+ vscode-html-languageservice: 2.1.12
+ vscode-languageserver-types: 3.17.5
+
+ typescript-styled-plugin@0.13.0:
+ dependencies:
+ typescript-template-language-service-decorator: 2.3.2
+ vscode-css-languageservice: 3.0.13
+ vscode-emmet-helper: 1.2.11
+ vscode-languageserver-types: 3.17.5
+
+ typescript-template-language-service-decorator@2.3.2: {}
+
+ typescript@5.2.2: {}
+
+ universalify@2.0.1: {}
+
+ vite-plugin-static-copy@2.3.1(vite@6.2.3):
+ dependencies:
+ chokidar: 3.6.0
+ fast-glob: 3.3.3
+ fs-extra: 11.3.0
+ p-map: 7.0.3
+ picocolors: 1.1.1
+ vite: 6.2.3
+
+ vite-tsconfig-paths@5.1.4(typescript@5.2.2)(vite@6.2.3):
+ dependencies:
+ debug: 4.4.0
+ globrex: 0.1.2
+ tsconfck: 3.1.5(typescript@5.2.2)
+ optionalDependencies:
+ vite: 6.2.3
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ vite@6.2.3:
+ dependencies:
+ esbuild: 0.25.1
+ postcss: 8.5.3
+ rollup: 4.37.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ vscode-css-languageservice@3.0.13:
+ dependencies:
+ vscode-languageserver-types: 3.17.5
+ vscode-nls: 4.1.2
+
+ vscode-css-languageservice@4.3.0:
+ dependencies:
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.16.0-next.2
+ vscode-nls: 4.1.2
+ vscode-uri: 2.1.2
+
+ vscode-emmet-helper@1.2.11:
+ dependencies:
+ '@emmetio/extract-abbreviation': 0.1.6
+ jsonc-parser: 1.0.3
+ vscode-languageserver-types: 3.17.5
+
+ vscode-html-languageservice@2.1.12:
+ dependencies:
+ vscode-languageserver-types: 3.17.5
+ vscode-nls: 4.1.2
+ vscode-uri: 1.0.8
+
+ vscode-html-languageservice@3.1.0:
+ dependencies:
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.16.0-next.2
+ vscode-nls: 4.1.2
+ vscode-uri: 2.1.2
+
+ vscode-languageserver-textdocument@1.0.12: {}
+
+ vscode-languageserver-types@3.16.0-next.2: {}
+
+ vscode-languageserver-types@3.17.5: {}
+
+ vscode-nls@4.1.2: {}
+
+ vscode-uri@1.0.8: {}
+
+ vscode-uri@2.1.2: {}
+
+ web-component-analyzer@2.0.0:
+ dependencies:
+ fast-glob: 3.3.3
+ ts-simple-type: 2.0.0-next.0
+ typescript: 5.2.2
+ yargs: 17.7.2
+
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ y18n@5.0.8: {}
+
+ yargs-parser@21.1.1: {}
+
+ yargs@17.7.2:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
diff --git a/frontend/src/assets/fonts/OFL.txt b/frontend/src/assets/fonts/OFL.txt
deleted file mode 100644
index 9cac04c..0000000
--- a/frontend/src/assets/fonts/OFL.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-Copyright 2016 The Nunito Project Authors (contact@sansoxygen.com),
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/frontend/src/assets/images/icons/music/album-carousel.svg b/frontend/src/assets/images/icons/music/album-carousel.svg
new file mode 100644
index 0000000..bf5e7f7
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/album-carousel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/album-list.svg b/frontend/src/assets/images/icons/music/album-list.svg
new file mode 100644
index 0000000..e0e2f5d
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/album-list.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/album-open.svg b/frontend/src/assets/images/icons/music/album-open.svg
new file mode 100644
index 0000000..f37ff1b
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/album-open.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/album.svg b/frontend/src/assets/images/icons/music/album.svg
new file mode 100644
index 0000000..962472e
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/album.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/backward15-seconds.svg b/frontend/src/assets/images/icons/music/backward15-seconds.svg
new file mode 100644
index 0000000..bf21201
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/backward15-seconds.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/compact-disc.svg b/frontend/src/assets/images/icons/music/compact-disc.svg
new file mode 100644
index 0000000..c3ddaea
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/compact-disc.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/forward-solid.svg b/frontend/src/assets/images/icons/music/forward-solid.svg
new file mode 100644
index 0000000..cb2040a
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/forward-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/forward.svg b/frontend/src/assets/images/icons/music/forward.svg
new file mode 100644
index 0000000..07337c3
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/forward.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/forward15-seconds.svg b/frontend/src/assets/images/icons/music/forward15-seconds.svg
new file mode 100644
index 0000000..a4ec938
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/forward15-seconds.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/headset-solid.svg b/frontend/src/assets/images/icons/music/headset-solid.svg
new file mode 100644
index 0000000..5e59462
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/headset-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/headset.svg b/frontend/src/assets/images/icons/music/headset.svg
new file mode 100644
index 0000000..5a7261a
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/headset.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/music-double-note-plus.svg b/frontend/src/assets/images/icons/music/music-double-note-plus.svg
new file mode 100644
index 0000000..a8c2fb1
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/music-double-note-plus.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/music-double-note.svg b/frontend/src/assets/images/icons/music/music-double-note.svg
new file mode 100644
index 0000000..ada270e
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/music-double-note.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/pause-solid.svg b/frontend/src/assets/images/icons/music/pause-solid.svg
new file mode 100644
index 0000000..3e7bc34
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/pause-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/pause.svg b/frontend/src/assets/images/icons/music/pause.svg
new file mode 100644
index 0000000..afadaa4
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/pause.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/play-solid.svg b/frontend/src/assets/images/icons/music/play-solid.svg
new file mode 100644
index 0000000..32bcdde
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/play-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/play.svg b/frontend/src/assets/images/icons/music/play.svg
new file mode 100644
index 0000000..d40e7d6
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/play.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/playlist-play.svg b/frontend/src/assets/images/icons/music/playlist-play.svg
new file mode 100644
index 0000000..2095009
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/playlist-play.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/playlist-plus.svg b/frontend/src/assets/images/icons/music/playlist-plus.svg
new file mode 100644
index 0000000..7a04158
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/playlist-plus.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/playlist.svg b/frontend/src/assets/images/icons/music/playlist.svg
new file mode 100644
index 0000000..b9fdcc0
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/playlist.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/repeat-once.svg b/frontend/src/assets/images/icons/music/repeat-once.svg
new file mode 100644
index 0000000..148bdc2
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/repeat-once.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/repeat.svg b/frontend/src/assets/images/icons/music/repeat.svg
new file mode 100644
index 0000000..a6ebc76
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/repeat.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/rewind-solid.svg b/frontend/src/assets/images/icons/music/rewind-solid.svg
new file mode 100644
index 0000000..faa8c2b
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/rewind-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/rewind.svg b/frontend/src/assets/images/icons/music/rewind.svg
new file mode 100644
index 0000000..6f37fd6
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/rewind.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/shuffle.svg b/frontend/src/assets/images/icons/music/shuffle.svg
new file mode 100644
index 0000000..ab9ddf2
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/shuffle.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/skip-next-solid.svg b/frontend/src/assets/images/icons/music/skip-next-solid.svg
new file mode 100644
index 0000000..3bd53dc
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/skip-next-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/skip-next.svg b/frontend/src/assets/images/icons/music/skip-next.svg
new file mode 100644
index 0000000..c640fb1
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/skip-next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/skip-prev-solid.svg b/frontend/src/assets/images/icons/music/skip-prev-solid.svg
new file mode 100644
index 0000000..5541327
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/skip-prev-solid.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/music/skip-prev.svg b/frontend/src/assets/images/icons/music/skip-prev.svg
new file mode 100644
index 0000000..a798ae4
--- /dev/null
+++ b/frontend/src/assets/images/icons/music/skip-prev.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/ui/menu.svg b/frontend/src/assets/images/icons/ui/menu.svg
new file mode 100644
index 0000000..36c2b71
--- /dev/null
+++ b/frontend/src/assets/images/icons/ui/menu.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/icons/ui/settings.svg b/frontend/src/assets/images/icons/ui/settings.svg
new file mode 100644
index 0000000..2b26a53
--- /dev/null
+++ b/frontend/src/assets/images/icons/ui/settings.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/src/assets/images/logo-universal.png b/frontend/src/assets/images/logo-universal.png
deleted file mode 100644
index d63303b..0000000
Binary files a/frontend/src/assets/images/logo-universal.png and /dev/null differ
diff --git a/frontend/src/components/audio-player/audio-player.ts b/frontend/src/components/audio-player/audio-player.ts
new file mode 100644
index 0000000..4ae6ade
--- /dev/null
+++ b/frontend/src/components/audio-player/audio-player.ts
@@ -0,0 +1,25 @@
+import { LitElement, html } from 'lit';
+import { customElement } from 'lit/decorators.js';
+import './controls/player-controls';
+import './seekbar/seek-bar';
+import '@go/player/Player';
+import '@shoelace-style/shoelace/dist/components/icon/icon.js';
+
+
+const audioPlayer = () => html`
+
+`;
+
+@customElement('audio-player')
+export class AudioPlayer extends LitElement {
+
+ override render() {
+ return audioPlayer();
+ }
+
+}
diff --git a/frontend/src/components/audio-player/controls/player-controls.ts b/frontend/src/components/audio-player/controls/player-controls.ts
new file mode 100644
index 0000000..4231463
--- /dev/null
+++ b/frontend/src/components/audio-player/controls/player-controls.ts
@@ -0,0 +1,57 @@
+import { LitElement, html } from 'lit';
+import { customElement, property } from 'lit/decorators.js';
+import { Play, Pause } from '@go/player/Player';
+
+// assets
+import pauseSVG from "@assets/images/icons/music/pause-solid.svg"
+import playSVG from "@assets/images/icons/music/play-solid.svg"
+import shuffleSVG from "@assets/images/icons/music/shuffle.svg"
+import skipPrevSVG from "@assets/images/icons/music/skip-prev-solid.svg"
+import skipNextSVG from "@assets/images/icons/music/skip-next-solid.svg"
+import repeatSVG from "@assets/images/icons/music/repeat.svg"
+
+@customElement('player-controls')
+export class PlayerControls extends LitElement {
+
+ @property({ type: Boolean })
+ isPlaying = false
+
+ override render() {
+ var imagePath = this.isPlaying ? pauseSVG : playSVG
+ return html`
+
+
+
+
+
+
+
+ `;
+ }
+
+ onPlayPauseClick() {
+ if (this.isPlaying) {
+ Play().then(() => {
+ }).catch((err) => {
+ console.error("there is an error with playing " + err);
+ });
+ } else {
+ Pause().then(() => {
+ }).catch((err) => {
+ console.error("there is an error with pausing " + err);
+ });
+
+ }
+ this.isPlaying = !this.isPlaying
+ }
+}
diff --git a/frontend/src/components/audio-player/seekbar/seek-bar.ts b/frontend/src/components/audio-player/seekbar/seek-bar.ts
new file mode 100644
index 0000000..56ea427
--- /dev/null
+++ b/frontend/src/components/audio-player/seekbar/seek-bar.ts
@@ -0,0 +1,84 @@
+import { LitElement, html, css, type PropertyValues } from 'lit';
+import { customElement, property} from 'lit/decorators.js';
+import {SignalWatcher, watch, signal} from '@lit-labs/signals';
+import { ref, createRef } from 'lit/directives/ref.js';
+import { SlRange } from '@node_modules/@shoelace-style/shoelace/dist/shoelace';
+
+const progress = signal(20);
+
+@customElement('seek-bar')
+export class SeekBar extends SignalWatcher(LitElement) {
+ @property()
+ progressIntervalMillis: number = 1000;
+
+ @property()
+ isProgressing: boolean = false;
+
+ timerID: number = -1;
+ private rangeRef = createRef();
+
+ constructor(){
+ super();
+ this.stopProgress();
+ }
+ static override styles = css`
+ sl-range::part(base) {
+ --track-color-active: red;
+ --track-color-inactive: white;
+ --track-height: 6px;
+ }
+ sl-range::part(form-control-input) {
+ --sl-color-primary-600: yellow;
+ }
+ `;
+ override render() {
+ return html`
+ {
+ this.setProgressValue((event.target as SlRange).value);
+ if(this.isProgressing) this.startProgress();
+ else this.stopProgress();
+ }}"
+ @sl-input="${() => {
+ var progressing = this.isProgressing;
+ this.stopProgress();
+ this.isProgressing = progressing;
+ }}">
+ `;
+ }
+
+ init(interval: number, playing: boolean){
+ this.progressIntervalMillis = interval;
+ if(playing)this.startProgress
+ }
+
+ stopProgress(){
+ this.isProgressing = false;
+ clearInterval(this.timerID);
+ }
+
+ startProgress(){
+ this.isProgressing = true;
+ this.timerID = setInterval(this.incrementProgressValue, this.progressIntervalMillis);
+ }
+
+ setProgressValue(val: number){
+ if(val < 0) val = 0;
+ if(val > 100) val = 100;
+ progress.set(val);
+ }
+
+ setProgressInterval(intervalMillis: number){
+ if(intervalMillis < 10) intervalMillis = 10;
+
+ }
+ async incrementProgressValue(){
+ if(progress.get() <100)
+ {
+ progress.set(progress.get() + 1);
+ }
+ }
+}
+
diff --git a/frontend/src/components/config/options/library-picker.ts b/frontend/src/components/config/options/library-picker.ts
new file mode 100644
index 0000000..0a4b18e
--- /dev/null
+++ b/frontend/src/components/config/options/library-picker.ts
@@ -0,0 +1,49 @@
+import { LitElement, html } from 'lit';
+import { customElement, property } from 'lit/decorators.js';
+import { GetDir, SetDir } from '@go/library/Library.js';
+import { DirectoryPicker } from '@go/frontendbindings/FrontendBindings.js';
+
+@customElement('library-picker')
+export class LibraryPicker extends LitElement {
+
+ @property({ type: String })
+ currentLibraryDirectoryText: string = "No Library Directory selected";
+
+ override render() {
+ return html`
+
+
+
+
+ `;
+ }
+
+ constructor() {
+ super();
+ GetDir().
+ then((result) => {
+ if (result.length === 0) { return; }
+ this.currentLibraryDirectoryText = result;
+ }).catch((err) => { console.error("error with getting current library directory: " + err) })
+ }
+
+ onSelectLibraryClick() {
+ try {
+ DirectoryPicker()
+ .then((result: string) => {
+ SetDir(result).then(() => {
+ this.currentLibraryDirectoryText = result;
+ }).catch((err: string) => {
+ console.error("error with saving selected directory: " + err);
+ });
+ })
+ .catch((err) => {
+ console.error("error with directory picker: " + err);
+ });
+ }
+ catch (err) {
+ console.error(err);
+ }
+ }
+
+}
diff --git a/frontend/src/main.js b/frontend/src/main.js
deleted file mode 100644
index d51ef8c..0000000
--- a/frontend/src/main.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import './pico.css';
-import {Greet} from '../wailsjs/go/main/App';
-
-document.querySelector('#app').innerHTML = `
- Please enter your name below 👇
-
-
-`;
-
-
-let nameElement = document.getElementById("name");
-nameElement.focus();
-let resultElement = document.getElementById("result");
-
-document.getElementById("directory-picker").addEventListener(
- "change",
- (event) => {
- let output = document.getElementById("listing");
- for (const file of event.target.files) {
- let item = document.createElement("li");
- item.textContent = file.webkitRelativePath;
- output.appendChild(item);
- }
- },
- false,
- );
-
-
-// Setup the greet function
-window.greet = function () {
- // Get name
- let name = nameElement.value;
-
- // Check if the input is empty
- if (name === "") return;
-
- // Call App.Greet(name)
- try {
- Greet(name)
- .then((result) => {
- // Update result with data back from App.Greet()
- resultElement.innerText = result;
- })
- .catch((err) => {
- console.error(err);
- });
- } catch (err) {
- console.error(err);
- }
-};
diff --git a/frontend/src/pages/config/config.css b/frontend/src/pages/config/config.css
new file mode 100644
index 0000000..1bee9c0
--- /dev/null
+++ b/frontend/src/pages/config/config.css
@@ -0,0 +1,4 @@
+body {
+ background-color: black;
+ color: white;
+}
diff --git a/frontend/src/pages/config/config.html b/frontend/src/pages/config/config.html
new file mode 100644
index 0000000..afcbc3f
--- /dev/null
+++ b/frontend/src/pages/config/config.html
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ yellowjacket - config
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/pages/config/config.ts b/frontend/src/pages/config/config.ts
new file mode 100644
index 0000000..d8b8bd8
--- /dev/null
+++ b/frontend/src/pages/config/config.ts
@@ -0,0 +1 @@
+import '@components/config/options/library-picker.ts';
diff --git a/frontend/src/pico.css b/frontend/src/pico.css
deleted file mode 100644
index 567927e..0000000
--- a/frontend/src/pico.css
+++ /dev/null
@@ -1,2835 +0,0 @@
-@charset "UTF-8";
-/*!
- * Pico CSS ✨ v2.1.1 (https://picocss.com)
- * Copyright 2019-2025 - Licensed under MIT
- */
-/**
- * Styles
- */
-:root,
-:host {
- --pico-font-family-emoji: "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- --pico-font-family-sans-serif: system-ui, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, Helvetica, Arial, "Helvetica Neue", sans-serif, var(--pico-font-family-emoji);
- --pico-font-family-monospace: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace, var(--pico-font-family-emoji);
- --pico-font-family: var(--pico-font-family-sans-serif);
- --pico-line-height: 1.5;
- --pico-font-weight: 400;
- --pico-font-size: 100%;
- --pico-text-underline-offset: 0.1rem;
- --pico-border-radius: 0.25rem;
- --pico-border-width: 0.0625rem;
- --pico-outline-width: 0.125rem;
- --pico-transition: 0.2s ease-in-out;
- --pico-spacing: 1rem;
- --pico-typography-spacing-vertical: 1rem;
- --pico-block-spacing-vertical: var(--pico-spacing);
- --pico-block-spacing-horizontal: var(--pico-spacing);
- --pico-grid-column-gap: var(--pico-spacing);
- --pico-grid-row-gap: var(--pico-spacing);
- --pico-form-element-spacing-vertical: 0.75rem;
- --pico-form-element-spacing-horizontal: 1rem;
- --pico-group-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
- --pico-group-box-shadow-focus-with-input: 0 0 0 0.0625rem var(--pico-form-element-border-color);
- --pico-modal-overlay-backdrop-filter: blur(0.375rem);
- --pico-nav-element-spacing-vertical: 1rem;
- --pico-nav-element-spacing-horizontal: 0.5rem;
- --pico-nav-link-spacing-vertical: 0.5rem;
- --pico-nav-link-spacing-horizontal: 0.5rem;
- --pico-nav-breadcrumb-divider: ">";
- --pico-icon-checkbox: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
- --pico-icon-minus: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='5' y1='12' x2='19' y2='12'%3E%3C/line%3E%3C/svg%3E");
- --pico-icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
- --pico-icon-date: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
- --pico-icon-time: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
- --pico-icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
- --pico-icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(136, 145, 164)' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
- --pico-icon-loading: url("data:image/svg+xml,%3Csvg fill='none' height='24' width='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' %3E%3Cstyle%3E g %7B animation: rotate 2s linear infinite; transform-origin: center center; %7D circle %7B stroke-dasharray: 75,100; stroke-dashoffset: -5; animation: dash 1.5s ease-in-out infinite; stroke-linecap: round; %7D @keyframes rotate %7B 0%25 %7B transform: rotate(0deg); %7D 100%25 %7B transform: rotate(360deg); %7D %7D @keyframes dash %7B 0%25 %7B stroke-dasharray: 1,100; stroke-dashoffset: 0; %7D 50%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -17.5; %7D 100%25 %7B stroke-dasharray: 44.5,100; stroke-dashoffset: -62; %7D %7D %3C/style%3E%3Cg%3E%3Ccircle cx='12' cy='12' r='10' fill='none' stroke='rgb(136, 145, 164)' stroke-width='4' /%3E%3C/g%3E%3C/svg%3E");
-}
-@media (min-width: 576px) {
- :root,
- :host {
- --pico-font-size: 106.25%;
- }
-}
-@media (min-width: 768px) {
- :root,
- :host {
- --pico-font-size: 112.5%;
- }
-}
-@media (min-width: 1024px) {
- :root,
- :host {
- --pico-font-size: 118.75%;
- }
-}
-@media (min-width: 1280px) {
- :root,
- :host {
- --pico-font-size: 125%;
- }
-}
-@media (min-width: 1536px) {
- :root,
- :host {
- --pico-font-size: 131.25%;
- }
-}
-
-a {
- --pico-text-decoration: underline;
-}
-a.secondary, a.contrast {
- --pico-text-decoration: underline;
-}
-
-small {
- --pico-font-size: 0.875em;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- --pico-font-weight: 700;
-}
-
-h1 {
- --pico-font-size: 2rem;
- --pico-line-height: 1.125;
- --pico-typography-spacing-top: 3rem;
-}
-
-h2 {
- --pico-font-size: 1.75rem;
- --pico-line-height: 1.15;
- --pico-typography-spacing-top: 2.625rem;
-}
-
-h3 {
- --pico-font-size: 1.5rem;
- --pico-line-height: 1.175;
- --pico-typography-spacing-top: 2.25rem;
-}
-
-h4 {
- --pico-font-size: 1.25rem;
- --pico-line-height: 1.2;
- --pico-typography-spacing-top: 1.874rem;
-}
-
-h5 {
- --pico-font-size: 1.125rem;
- --pico-line-height: 1.225;
- --pico-typography-spacing-top: 1.6875rem;
-}
-
-h6 {
- --pico-font-size: 1rem;
- --pico-line-height: 1.25;
- --pico-typography-spacing-top: 1.5rem;
-}
-
-thead th,
-thead td,
-tfoot th,
-tfoot td {
- --pico-font-weight: 600;
- --pico-border-width: 0.1875rem;
-}
-
-pre,
-code,
-kbd,
-samp {
- --pico-font-family: var(--pico-font-family-monospace);
-}
-
-kbd {
- --pico-font-weight: bolder;
-}
-
-input:not([type=submit],
-[type=button],
-[type=reset],
-[type=checkbox],
-[type=radio],
-[type=file]),
-:where(select, textarea) {
- --pico-outline-width: 0.0625rem;
-}
-
-[type=search] {
- --pico-border-radius: 5rem;
-}
-
-[type=checkbox],
-[type=radio] {
- --pico-border-width: 0.125rem;
-}
-
-[type=checkbox][role=switch] {
- --pico-border-width: 0.1875rem;
-}
-
-details.dropdown summary:not([role=button]) {
- --pico-outline-width: 0.0625rem;
-}
-
-nav details.dropdown summary:focus-visible {
- --pico-outline-width: 0.125rem;
-}
-
-[role=search] {
- --pico-border-radius: 5rem;
-}
-
-[role=search]:has(button.secondary:focus,
-[type=submit].secondary:focus,
-[type=button].secondary:focus,
-[role=button].secondary:focus),
-[role=group]:has(button.secondary:focus,
-[type=submit].secondary:focus,
-[type=button].secondary:focus,
-[role=button].secondary:focus) {
- --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus);
-}
-[role=search]:has(button.contrast:focus,
-[type=submit].contrast:focus,
-[type=button].contrast:focus,
-[role=button].contrast:focus),
-[role=group]:has(button.contrast:focus,
-[type=submit].contrast:focus,
-[type=button].contrast:focus,
-[role=button].contrast:focus) {
- --pico-group-box-shadow-focus-with-button: 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus);
-}
-[role=search] button,
-[role=search] [type=submit],
-[role=search] [type=button],
-[role=search] [role=button],
-[role=group] button,
-[role=group] [type=submit],
-[role=group] [type=button],
-[role=group] [role=button] {
- --pico-form-element-spacing-horizontal: 2rem;
-}
-
-details summary[role=button]:not(.outline)::after {
- filter: brightness(0) invert(1);
-}
-
-[aria-busy=true]:not(input, select, textarea):is(button, [type=submit], [type=button], [type=reset], [role=button]):not(.outline)::before {
- filter: brightness(0) invert(1);
-}
-
-/**
- * Color schemes
- */
-[data-theme=light],
-:root:not([data-theme=dark]),
-:host(:not([data-theme=dark])) {
- color-scheme: light;
- --pico-background-color: #fff;
- --pico-color: #373c44;
- --pico-text-selection-color: rgba(2, 154, 232, 0.25);
- --pico-muted-color: #646b79;
- --pico-muted-border-color: rgb(231, 234, 239.5);
- --pico-primary: #0172ad;
- --pico-primary-background: #0172ad;
- --pico-primary-border: var(--pico-primary-background);
- --pico-primary-underline: rgba(1, 114, 173, 0.5);
- --pico-primary-hover: #015887;
- --pico-primary-hover-background: #02659a;
- --pico-primary-hover-border: var(--pico-primary-hover-background);
- --pico-primary-hover-underline: var(--pico-primary-hover);
- --pico-primary-focus: rgba(2, 154, 232, 0.5);
- --pico-primary-inverse: #fff;
- --pico-secondary: #5d6b89;
- --pico-secondary-background: #525f7a;
- --pico-secondary-border: var(--pico-secondary-background);
- --pico-secondary-underline: rgba(93, 107, 137, 0.5);
- --pico-secondary-hover: #48536b;
- --pico-secondary-hover-background: #48536b;
- --pico-secondary-hover-border: var(--pico-secondary-hover-background);
- --pico-secondary-hover-underline: var(--pico-secondary-hover);
- --pico-secondary-focus: rgba(93, 107, 137, 0.25);
- --pico-secondary-inverse: #fff;
- --pico-contrast: #181c25;
- --pico-contrast-background: #181c25;
- --pico-contrast-border: var(--pico-contrast-background);
- --pico-contrast-underline: rgba(24, 28, 37, 0.5);
- --pico-contrast-hover: #000;
- --pico-contrast-hover-background: #000;
- --pico-contrast-hover-border: var(--pico-contrast-hover-background);
- --pico-contrast-hover-underline: var(--pico-secondary-hover);
- --pico-contrast-focus: rgba(93, 107, 137, 0.25);
- --pico-contrast-inverse: #fff;
- --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(129, 145, 181, 0.01698), 0.0335rem 0.067rem 0.402rem rgba(129, 145, 181, 0.024), 0.0625rem 0.125rem 0.75rem rgba(129, 145, 181, 0.03), 0.1125rem 0.225rem 1.35rem rgba(129, 145, 181, 0.036), 0.2085rem 0.417rem 2.502rem rgba(129, 145, 181, 0.04302), 0.5rem 1rem 6rem rgba(129, 145, 181, 0.06), 0 0 0 0.0625rem rgba(129, 145, 181, 0.015);
- --pico-h1-color: #2d3138;
- --pico-h2-color: #373c44;
- --pico-h3-color: #424751;
- --pico-h4-color: #4d535e;
- --pico-h5-color: #5c6370;
- --pico-h6-color: #646b79;
- --pico-mark-background-color: rgb(252.5, 230.5, 191.5);
- --pico-mark-color: #0f1114;
- --pico-ins-color: rgb(28.5, 105.5, 84);
- --pico-del-color: rgb(136, 56.5, 53);
- --pico-blockquote-border-color: var(--pico-muted-border-color);
- --pico-blockquote-footer-color: var(--pico-muted-color);
- --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-table-border-color: var(--pico-muted-border-color);
- --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375);
- --pico-code-background-color: rgb(243, 244.5, 246.75);
- --pico-code-color: #646b79;
- --pico-code-kbd-background-color: var(--pico-color);
- --pico-code-kbd-color: var(--pico-background-color);
- --pico-form-element-background-color: rgb(251, 251.5, 252.25);
- --pico-form-element-selected-background-color: #dfe3eb;
- --pico-form-element-border-color: #cfd5e2;
- --pico-form-element-color: #23262c;
- --pico-form-element-placeholder-color: var(--pico-muted-color);
- --pico-form-element-active-background-color: #fff;
- --pico-form-element-active-border-color: var(--pico-primary-border);
- --pico-form-element-focus-color: var(--pico-primary-border);
- --pico-form-element-disabled-opacity: 0.5;
- --pico-form-element-invalid-border-color: rgb(183.5, 105.5, 106.5);
- --pico-form-element-invalid-active-border-color: rgb(200.25, 79.25, 72.25);
- --pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);
- --pico-form-element-valid-border-color: rgb(76, 154.5, 137.5);
- --pico-form-element-valid-active-border-color: rgb(39, 152.75, 118.75);
- --pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);
- --pico-switch-background-color: #bfc7d9;
- --pico-switch-checked-background-color: var(--pico-primary-background);
- --pico-switch-color: #fff;
- --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-range-border-color: #dfe3eb;
- --pico-range-active-border-color: #bfc7d9;
- --pico-range-thumb-border-color: var(--pico-background-color);
- --pico-range-thumb-color: var(--pico-secondary-background);
- --pico-range-thumb-active-color: var(--pico-primary-background);
- --pico-accordion-border-color: var(--pico-muted-border-color);
- --pico-accordion-active-summary-color: var(--pico-primary-hover);
- --pico-accordion-close-summary-color: var(--pico-color);
- --pico-accordion-open-summary-color: var(--pico-muted-color);
- --pico-card-background-color: var(--pico-background-color);
- --pico-card-border-color: var(--pico-muted-border-color);
- --pico-card-box-shadow: var(--pico-box-shadow);
- --pico-card-sectioning-background-color: rgb(251, 251.5, 252.25);
- --pico-dropdown-background-color: #fff;
- --pico-dropdown-border-color: #eff1f4;
- --pico-dropdown-box-shadow: var(--pico-box-shadow);
- --pico-dropdown-color: var(--pico-color);
- --pico-dropdown-hover-background-color: #eff1f4;
- --pico-loading-spinner-opacity: 0.5;
- --pico-modal-overlay-background-color: rgba(232, 234, 237, 0.75);
- --pico-progress-background-color: #dfe3eb;
- --pico-progress-color: var(--pico-primary-background);
- --pico-tooltip-background-color: var(--pico-contrast-background);
- --pico-tooltip-color: var(--pico-contrast-inverse);
- --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(76, 154.5, 137.5)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
- --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(200.25, 79.25, 72.25)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
-}
-[data-theme=light] input:is([type=submit],
-[type=button],
-[type=reset],
-[type=checkbox],
-[type=radio],
-[type=file]),
-:root:not([data-theme=dark]) input:is([type=submit],
-[type=button],
-[type=reset],
-[type=checkbox],
-[type=radio],
-[type=file]),
-:host(:not([data-theme=dark])) input:is([type=submit],
-[type=button],
-[type=reset],
-[type=checkbox],
-[type=radio],
-[type=file]) {
- --pico-form-element-focus-color: var(--pico-primary-focus);
-}
-
-@media only screen and (prefers-color-scheme: dark) {
- :root:not([data-theme]),
- :host(:not([data-theme])) {
- color-scheme: dark;
- --pico-background-color: rgb(19, 22.5, 30.5);
- --pico-color: #c2c7d0;
- --pico-text-selection-color: rgba(1, 170, 255, 0.1875);
- --pico-muted-color: #7b8495;
- --pico-muted-border-color: #202632;
- --pico-primary: #01aaff;
- --pico-primary-background: #0172ad;
- --pico-primary-border: var(--pico-primary-background);
- --pico-primary-underline: rgba(1, 170, 255, 0.5);
- --pico-primary-hover: #79c0ff;
- --pico-primary-hover-background: #017fc0;
- --pico-primary-hover-border: var(--pico-primary-hover-background);
- --pico-primary-hover-underline: var(--pico-primary-hover);
- --pico-primary-focus: rgba(1, 170, 255, 0.375);
- --pico-primary-inverse: #fff;
- --pico-secondary: #969eaf;
- --pico-secondary-background: #525f7a;
- --pico-secondary-border: var(--pico-secondary-background);
- --pico-secondary-underline: rgba(150, 158, 175, 0.5);
- --pico-secondary-hover: #b3b9c5;
- --pico-secondary-hover-background: #5d6b89;
- --pico-secondary-hover-border: var(--pico-secondary-hover-background);
- --pico-secondary-hover-underline: var(--pico-secondary-hover);
- --pico-secondary-focus: rgba(144, 158, 190, 0.25);
- --pico-secondary-inverse: #fff;
- --pico-contrast: #dfe3eb;
- --pico-contrast-background: #eff1f4;
- --pico-contrast-border: var(--pico-contrast-background);
- --pico-contrast-underline: rgba(223, 227, 235, 0.5);
- --pico-contrast-hover: #fff;
- --pico-contrast-hover-background: #fff;
- --pico-contrast-hover-border: var(--pico-contrast-hover-background);
- --pico-contrast-hover-underline: var(--pico-contrast-hover);
- --pico-contrast-focus: rgba(207, 213, 226, 0.25);
- --pico-contrast-inverse: #000;
- --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(7, 8.5, 12, 0.01698), 0.0335rem 0.067rem 0.402rem rgba(7, 8.5, 12, 0.024), 0.0625rem 0.125rem 0.75rem rgba(7, 8.5, 12, 0.03), 0.1125rem 0.225rem 1.35rem rgba(7, 8.5, 12, 0.036), 0.2085rem 0.417rem 2.502rem rgba(7, 8.5, 12, 0.04302), 0.5rem 1rem 6rem rgba(7, 8.5, 12, 0.06), 0 0 0 0.0625rem rgba(7, 8.5, 12, 0.015);
- --pico-h1-color: #f0f1f3;
- --pico-h2-color: #e0e3e7;
- --pico-h3-color: #c2c7d0;
- --pico-h4-color: #b3b9c5;
- --pico-h5-color: #a4acba;
- --pico-h6-color: #8891a4;
- --pico-mark-background-color: #014063;
- --pico-mark-color: #fff;
- --pico-ins-color: #62af9a;
- --pico-del-color: rgb(205.5, 126, 123);
- --pico-blockquote-border-color: var(--pico-muted-border-color);
- --pico-blockquote-footer-color: var(--pico-muted-color);
- --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-table-border-color: var(--pico-muted-border-color);
- --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375);
- --pico-code-background-color: rgb(26, 30.5, 40.25);
- --pico-code-color: #8891a4;
- --pico-code-kbd-background-color: var(--pico-color);
- --pico-code-kbd-color: var(--pico-background-color);
- --pico-form-element-background-color: rgb(28, 33, 43.5);
- --pico-form-element-selected-background-color: #2a3140;
- --pico-form-element-border-color: #2a3140;
- --pico-form-element-color: #e0e3e7;
- --pico-form-element-placeholder-color: #8891a4;
- --pico-form-element-active-background-color: rgb(26, 30.5, 40.25);
- --pico-form-element-active-border-color: var(--pico-primary-border);
- --pico-form-element-focus-color: var(--pico-primary-border);
- --pico-form-element-disabled-opacity: 0.5;
- --pico-form-element-invalid-border-color: rgb(149.5, 74, 80);
- --pico-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59);
- --pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);
- --pico-form-element-valid-border-color: #2a7b6f;
- --pico-form-element-valid-active-border-color: rgb(22, 137, 105.5);
- --pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);
- --pico-switch-background-color: #333c4e;
- --pico-switch-checked-background-color: var(--pico-primary-background);
- --pico-switch-color: #fff;
- --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-range-border-color: #202632;
- --pico-range-active-border-color: #2a3140;
- --pico-range-thumb-border-color: var(--pico-background-color);
- --pico-range-thumb-color: var(--pico-secondary-background);
- --pico-range-thumb-active-color: var(--pico-primary-background);
- --pico-accordion-border-color: var(--pico-muted-border-color);
- --pico-accordion-active-summary-color: var(--pico-primary-hover);
- --pico-accordion-close-summary-color: var(--pico-color);
- --pico-accordion-open-summary-color: var(--pico-muted-color);
- --pico-card-background-color: #181c25;
- --pico-card-border-color: var(--pico-card-background-color);
- --pico-card-box-shadow: var(--pico-box-shadow);
- --pico-card-sectioning-background-color: rgb(26, 30.5, 40.25);
- --pico-dropdown-background-color: #181c25;
- --pico-dropdown-border-color: #202632;
- --pico-dropdown-box-shadow: var(--pico-box-shadow);
- --pico-dropdown-color: var(--pico-color);
- --pico-dropdown-hover-background-color: #202632;
- --pico-loading-spinner-opacity: 0.5;
- --pico-modal-overlay-background-color: rgba(7.5, 8.5, 10, 0.75);
- --pico-progress-background-color: #202632;
- --pico-progress-color: var(--pico-primary-background);
- --pico-tooltip-background-color: var(--pico-contrast-background);
- --pico-tooltip-color: var(--pico-contrast-inverse);
- --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
- --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
- }
- :root:not([data-theme]) input:is([type=submit],
- [type=button],
- [type=reset],
- [type=checkbox],
- [type=radio],
- [type=file]),
- :host(:not([data-theme])) input:is([type=submit],
- [type=button],
- [type=reset],
- [type=checkbox],
- [type=radio],
- [type=file]) {
- --pico-form-element-focus-color: var(--pico-primary-focus);
- }
- :root:not([data-theme]) details summary[role=button].contrast:not(.outline)::after,
- :host(:not([data-theme])) details summary[role=button].contrast:not(.outline)::after {
- filter: brightness(0);
- }
- :root:not([data-theme]) [aria-busy=true]:not(input, select, textarea).contrast:is(button,
- [type=submit],
- [type=button],
- [type=reset],
- [role=button]):not(.outline)::before,
- :host(:not([data-theme])) [aria-busy=true]:not(input, select, textarea).contrast:is(button,
- [type=submit],
- [type=button],
- [type=reset],
- [role=button]):not(.outline)::before {
- filter: brightness(0);
- }
-}
-[data-theme=dark] {
- color-scheme: dark;
- --pico-background-color: rgb(19, 22.5, 30.5);
- --pico-color: #c2c7d0;
- --pico-text-selection-color: rgba(1, 170, 255, 0.1875);
- --pico-muted-color: #7b8495;
- --pico-muted-border-color: #202632;
- --pico-primary: #01aaff;
- --pico-primary-background: #0172ad;
- --pico-primary-border: var(--pico-primary-background);
- --pico-primary-underline: rgba(1, 170, 255, 0.5);
- --pico-primary-hover: #79c0ff;
- --pico-primary-hover-background: #017fc0;
- --pico-primary-hover-border: var(--pico-primary-hover-background);
- --pico-primary-hover-underline: var(--pico-primary-hover);
- --pico-primary-focus: rgba(1, 170, 255, 0.375);
- --pico-primary-inverse: #fff;
- --pico-secondary: #969eaf;
- --pico-secondary-background: #525f7a;
- --pico-secondary-border: var(--pico-secondary-background);
- --pico-secondary-underline: rgba(150, 158, 175, 0.5);
- --pico-secondary-hover: #b3b9c5;
- --pico-secondary-hover-background: #5d6b89;
- --pico-secondary-hover-border: var(--pico-secondary-hover-background);
- --pico-secondary-hover-underline: var(--pico-secondary-hover);
- --pico-secondary-focus: rgba(144, 158, 190, 0.25);
- --pico-secondary-inverse: #fff;
- --pico-contrast: #dfe3eb;
- --pico-contrast-background: #eff1f4;
- --pico-contrast-border: var(--pico-contrast-background);
- --pico-contrast-underline: rgba(223, 227, 235, 0.5);
- --pico-contrast-hover: #fff;
- --pico-contrast-hover-background: #fff;
- --pico-contrast-hover-border: var(--pico-contrast-hover-background);
- --pico-contrast-hover-underline: var(--pico-contrast-hover);
- --pico-contrast-focus: rgba(207, 213, 226, 0.25);
- --pico-contrast-inverse: #000;
- --pico-box-shadow: 0.0145rem 0.029rem 0.174rem rgba(7, 8.5, 12, 0.01698), 0.0335rem 0.067rem 0.402rem rgba(7, 8.5, 12, 0.024), 0.0625rem 0.125rem 0.75rem rgba(7, 8.5, 12, 0.03), 0.1125rem 0.225rem 1.35rem rgba(7, 8.5, 12, 0.036), 0.2085rem 0.417rem 2.502rem rgba(7, 8.5, 12, 0.04302), 0.5rem 1rem 6rem rgba(7, 8.5, 12, 0.06), 0 0 0 0.0625rem rgba(7, 8.5, 12, 0.015);
- --pico-h1-color: #f0f1f3;
- --pico-h2-color: #e0e3e7;
- --pico-h3-color: #c2c7d0;
- --pico-h4-color: #b3b9c5;
- --pico-h5-color: #a4acba;
- --pico-h6-color: #8891a4;
- --pico-mark-background-color: #014063;
- --pico-mark-color: #fff;
- --pico-ins-color: #62af9a;
- --pico-del-color: rgb(205.5, 126, 123);
- --pico-blockquote-border-color: var(--pico-muted-border-color);
- --pico-blockquote-footer-color: var(--pico-muted-color);
- --pico-button-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-button-hover-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-table-border-color: var(--pico-muted-border-color);
- --pico-table-row-stripped-background-color: rgba(111, 120, 135, 0.0375);
- --pico-code-background-color: rgb(26, 30.5, 40.25);
- --pico-code-color: #8891a4;
- --pico-code-kbd-background-color: var(--pico-color);
- --pico-code-kbd-color: var(--pico-background-color);
- --pico-form-element-background-color: rgb(28, 33, 43.5);
- --pico-form-element-selected-background-color: #2a3140;
- --pico-form-element-border-color: #2a3140;
- --pico-form-element-color: #e0e3e7;
- --pico-form-element-placeholder-color: #8891a4;
- --pico-form-element-active-background-color: rgb(26, 30.5, 40.25);
- --pico-form-element-active-border-color: var(--pico-primary-border);
- --pico-form-element-focus-color: var(--pico-primary-border);
- --pico-form-element-disabled-opacity: 0.5;
- --pico-form-element-invalid-border-color: rgb(149.5, 74, 80);
- --pico-form-element-invalid-active-border-color: rgb(183.25, 63.5, 59);
- --pico-form-element-invalid-focus-color: var(--pico-form-element-invalid-active-border-color);
- --pico-form-element-valid-border-color: #2a7b6f;
- --pico-form-element-valid-active-border-color: rgb(22, 137, 105.5);
- --pico-form-element-valid-focus-color: var(--pico-form-element-valid-active-border-color);
- --pico-switch-background-color: #333c4e;
- --pico-switch-checked-background-color: var(--pico-primary-background);
- --pico-switch-color: #fff;
- --pico-switch-thumb-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
- --pico-range-border-color: #202632;
- --pico-range-active-border-color: #2a3140;
- --pico-range-thumb-border-color: var(--pico-background-color);
- --pico-range-thumb-color: var(--pico-secondary-background);
- --pico-range-thumb-active-color: var(--pico-primary-background);
- --pico-accordion-border-color: var(--pico-muted-border-color);
- --pico-accordion-active-summary-color: var(--pico-primary-hover);
- --pico-accordion-close-summary-color: var(--pico-color);
- --pico-accordion-open-summary-color: var(--pico-muted-color);
- --pico-card-background-color: #181c25;
- --pico-card-border-color: var(--pico-card-background-color);
- --pico-card-box-shadow: var(--pico-box-shadow);
- --pico-card-sectioning-background-color: rgb(26, 30.5, 40.25);
- --pico-dropdown-background-color: #181c25;
- --pico-dropdown-border-color: #202632;
- --pico-dropdown-box-shadow: var(--pico-box-shadow);
- --pico-dropdown-color: var(--pico-color);
- --pico-dropdown-hover-background-color: #202632;
- --pico-loading-spinner-opacity: 0.5;
- --pico-modal-overlay-background-color: rgba(7.5, 8.5, 10, 0.75);
- --pico-progress-background-color: #202632;
- --pico-progress-color: var(--pico-primary-background);
- --pico-tooltip-background-color: var(--pico-contrast-background);
- --pico-tooltip-color: var(--pico-contrast-inverse);
- --pico-icon-valid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(42, 123, 111)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
- --pico-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(149.5, 74, 80)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cline x1='12' y1='8' x2='12' y2='12'%3E%3C/line%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'%3E%3C/line%3E%3C/svg%3E");
-}
-[data-theme=dark] input:is([type=submit],
-[type=button],
-[type=reset],
-[type=checkbox],
-[type=radio],
-[type=file]) {
- --pico-form-element-focus-color: var(--pico-primary-focus);
-}
-[data-theme=dark] details summary[role=button].contrast:not(.outline)::after {
- filter: brightness(0);
-}
-[data-theme=dark] [aria-busy=true]:not(input, select, textarea).contrast:is(button,
-[type=submit],
-[type=button],
-[type=reset],
-[role=button]):not(.outline)::before {
- filter: brightness(0);
-}
-
-progress,
-[type=checkbox],
-[type=radio],
-[type=range] {
- accent-color: var(--pico-primary);
-}
-
-/**
- * Document
- * Content-box & Responsive typography
- */
-*,
-*::before,
-*::after {
- box-sizing: border-box;
- background-repeat: no-repeat;
-}
-
-::before,
-::after {
- text-decoration: inherit;
- vertical-align: inherit;
-}
-
-:where(:root),
-:where(:host) {
- -webkit-tap-highlight-color: transparent;
- -webkit-text-size-adjust: 100%;
- -moz-text-size-adjust: 100%;
- text-size-adjust: 100%;
- background-color: var(--pico-background-color);
- color: var(--pico-color);
- font-weight: var(--pico-font-weight);
- font-size: var(--pico-font-size);
- line-height: var(--pico-line-height);
- font-family: var(--pico-font-family);
- text-underline-offset: var(--pico-text-underline-offset);
- text-rendering: optimizeLegibility;
- overflow-wrap: break-word;
- -moz-tab-size: 4;
- -o-tab-size: 4;
- tab-size: 4;
-}
-
-/**
- * Landmarks
- */
-body {
- width: 100%;
- margin: 0;
-}
-
-main {
- display: block;
-}
-
-body > header,
-body > main,
-body > footer {
- padding-block: var(--pico-block-spacing-vertical);
-}
-
-/**
- * Section
- */
-section {
- margin-bottom: var(--pico-block-spacing-vertical);
-}
-
-/**
- * Container
- */
-.container,
-.container-fluid {
- width: 100%;
- margin-right: auto;
- margin-left: auto;
- padding-right: var(--pico-spacing);
- padding-left: var(--pico-spacing);
-}
-
-@media (min-width: 576px) {
- .container {
- max-width: 510px;
- padding-right: 0;
- padding-left: 0;
- }
-}
-@media (min-width: 768px) {
- .container {
- max-width: 700px;
- }
-}
-@media (min-width: 1024px) {
- .container {
- max-width: 950px;
- }
-}
-@media (min-width: 1280px) {
- .container {
- max-width: 1200px;
- }
-}
-@media (min-width: 1536px) {
- .container {
- max-width: 1450px;
- }
-}
-
-/**
- * Grid
- * Minimal grid system with auto-layout columns
- */
-.grid {
- grid-column-gap: var(--pico-grid-column-gap);
- grid-row-gap: var(--pico-grid-row-gap);
- display: grid;
- grid-template-columns: 1fr;
-}
-@media (min-width: 768px) {
- .grid {
- grid-template-columns: repeat(auto-fit, minmax(0%, 1fr));
- }
-}
-.grid > * {
- min-width: 0;
-}
-
-/**
- * Overflow auto
- */
-.overflow-auto {
- overflow: auto;
-}
-
-/**
- * Typography
- */
-b,
-strong {
- font-weight: bolder;
-}
-
-sub,
-sup {
- position: relative;
- font-size: 0.75em;
- line-height: 0;
- vertical-align: baseline;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-sup {
- top: -0.5em;
-}
-
-address,
-blockquote,
-dl,
-ol,
-p,
-pre,
-table,
-ul {
- margin-top: 0;
- margin-bottom: var(--pico-typography-spacing-vertical);
- color: var(--pico-color);
- font-style: normal;
- font-weight: var(--pico-font-weight);
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- margin-top: 0;
- margin-bottom: var(--pico-typography-spacing-vertical);
- color: var(--pico-color);
- font-weight: var(--pico-font-weight);
- font-size: var(--pico-font-size);
- line-height: var(--pico-line-height);
- font-family: var(--pico-font-family);
-}
-
-h1 {
- --pico-color: var(--pico-h1-color);
-}
-
-h2 {
- --pico-color: var(--pico-h2-color);
-}
-
-h3 {
- --pico-color: var(--pico-h3-color);
-}
-
-h4 {
- --pico-color: var(--pico-h4-color);
-}
-
-h5 {
- --pico-color: var(--pico-h5-color);
-}
-
-h6 {
- --pico-color: var(--pico-h6-color);
-}
-
-:where(article, address, blockquote, dl, figure, form, ol, p, pre, table, ul) ~ :is(h1, h2, h3, h4, h5, h6) {
- margin-top: var(--pico-typography-spacing-top);
-}
-
-p {
- margin-bottom: var(--pico-typography-spacing-vertical);
-}
-
-hgroup {
- margin-bottom: var(--pico-typography-spacing-vertical);
-}
-hgroup > * {
- margin-top: 0;
- margin-bottom: 0;
-}
-hgroup > *:not(:first-child):last-child {
- --pico-color: var(--pico-muted-color);
- --pico-font-weight: unset;
- font-size: 1rem;
-}
-
-:where(ol, ul) li {
- margin-bottom: calc(var(--pico-typography-spacing-vertical) * 0.25);
-}
-
-:where(dl, ol, ul) :where(dl, ol, ul) {
- margin: 0;
- margin-top: calc(var(--pico-typography-spacing-vertical) * 0.25);
-}
-
-ul li {
- list-style: square;
-}
-
-mark {
- padding: 0.125rem 0.25rem;
- background-color: var(--pico-mark-background-color);
- color: var(--pico-mark-color);
- vertical-align: baseline;
-}
-
-blockquote {
- display: block;
- margin: var(--pico-typography-spacing-vertical) 0;
- padding: var(--pico-spacing);
- border-right: none;
- border-left: 0.25rem solid var(--pico-blockquote-border-color);
- border-inline-start: 0.25rem solid var(--pico-blockquote-border-color);
- border-inline-end: none;
-}
-blockquote footer {
- margin-top: calc(var(--pico-typography-spacing-vertical) * 0.5);
- color: var(--pico-blockquote-footer-color);
-}
-
-abbr[title] {
- border-bottom: 1px dotted;
- text-decoration: none;
- cursor: help;
-}
-
-ins {
- color: var(--pico-ins-color);
- text-decoration: none;
-}
-
-del {
- color: var(--pico-del-color);
-}
-
-::-moz-selection {
- background-color: var(--pico-text-selection-color);
-}
-
-::selection {
- background-color: var(--pico-text-selection-color);
-}
-
-/**
- * Link
- */
-:where(a:not([role=button])),
-[role=link] {
- --pico-color: var(--pico-primary);
- --pico-background-color: transparent;
- --pico-underline: var(--pico-primary-underline);
- outline: none;
- background-color: var(--pico-background-color);
- color: var(--pico-color);
- -webkit-text-decoration: var(--pico-text-decoration);
- text-decoration: var(--pico-text-decoration);
- text-decoration-color: var(--pico-underline);
- text-underline-offset: 0.125em;
- transition: background-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition), -webkit-text-decoration var(--pico-transition);
- transition: background-color var(--pico-transition), color var(--pico-transition), text-decoration var(--pico-transition), box-shadow var(--pico-transition);
- transition: background-color var(--pico-transition), color var(--pico-transition), text-decoration var(--pico-transition), box-shadow var(--pico-transition), -webkit-text-decoration var(--pico-transition);
-}
-:where(a:not([role=button])):is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[role=link]:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-color: var(--pico-primary-hover);
- --pico-underline: var(--pico-primary-hover-underline);
- --pico-text-decoration: underline;
-}
-:where(a:not([role=button])):focus-visible,
-[role=link]:focus-visible {
- box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
-}
-:where(a:not([role=button])).secondary,
-[role=link].secondary {
- --pico-color: var(--pico-secondary);
- --pico-underline: var(--pico-secondary-underline);
-}
-:where(a:not([role=button])).secondary:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[role=link].secondary:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-color: var(--pico-secondary-hover);
- --pico-underline: var(--pico-secondary-hover-underline);
-}
-:where(a:not([role=button])).contrast,
-[role=link].contrast {
- --pico-color: var(--pico-contrast);
- --pico-underline: var(--pico-contrast-underline);
-}
-:where(a:not([role=button])).contrast:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[role=link].contrast:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-color: var(--pico-contrast-hover);
- --pico-underline: var(--pico-contrast-hover-underline);
-}
-
-a[role=button] {
- display: inline-block;
-}
-
-/**
- * Button
- */
-button {
- margin: 0;
- overflow: visible;
- font-family: inherit;
- text-transform: none;
-}
-
-button,
-[type=submit],
-[type=reset],
-[type=button] {
- -webkit-appearance: button;
-}
-
-button,
-[type=submit],
-[type=reset],
-[type=button],
-[type=file]::file-selector-button,
-[role=button] {
- --pico-background-color: var(--pico-primary-background);
- --pico-border-color: var(--pico-primary-border);
- --pico-color: var(--pico-primary-inverse);
- --pico-box-shadow: var(--pico-button-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
- padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
- border: var(--pico-border-width) solid var(--pico-border-color);
- border-radius: var(--pico-border-radius);
- outline: none;
- background-color: var(--pico-background-color);
- box-shadow: var(--pico-box-shadow);
- color: var(--pico-color);
- font-weight: var(--pico-font-weight);
- font-size: 1rem;
- line-height: var(--pico-line-height);
- text-align: center;
- text-decoration: none;
- cursor: pointer;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- transition: background-color var(--pico-transition), border-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition);
-}
-button:is([aria-current]:not([aria-current=false])), button:is(:hover, :active, :focus),
-[type=submit]:is([aria-current]:not([aria-current=false])),
-[type=submit]:is(:hover, :active, :focus),
-[type=reset]:is([aria-current]:not([aria-current=false])),
-[type=reset]:is(:hover, :active, :focus),
-[type=button]:is([aria-current]:not([aria-current=false])),
-[type=button]:is(:hover, :active, :focus),
-[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])),
-[type=file]::file-selector-button:is(:hover, :active, :focus),
-[role=button]:is([aria-current]:not([aria-current=false])),
-[role=button]:is(:hover, :active, :focus) {
- --pico-background-color: var(--pico-primary-hover-background);
- --pico-border-color: var(--pico-primary-hover-border);
- --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
- --pico-color: var(--pico-primary-inverse);
-}
-button:focus, button:is([aria-current]:not([aria-current=false])):focus,
-[type=submit]:focus,
-[type=submit]:is([aria-current]:not([aria-current=false])):focus,
-[type=reset]:focus,
-[type=reset]:is([aria-current]:not([aria-current=false])):focus,
-[type=button]:focus,
-[type=button]:is([aria-current]:not([aria-current=false])):focus,
-[type=file]::file-selector-button:focus,
-[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus,
-[role=button]:focus,
-[role=button]:is([aria-current]:not([aria-current=false])):focus {
- --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
-}
-
-[type=submit],
-[type=reset],
-[type=button] {
- margin-bottom: var(--pico-spacing);
-}
-
-:is(button, [type=submit], [type=button], [role=button]).secondary,
-[type=reset],
-[type=file]::file-selector-button {
- --pico-background-color: var(--pico-secondary-background);
- --pico-border-color: var(--pico-secondary-border);
- --pico-color: var(--pico-secondary-inverse);
- cursor: pointer;
-}
-:is(button, [type=submit], [type=button], [role=button]).secondary:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[type=reset]:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[type=file]::file-selector-button:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-background-color: var(--pico-secondary-hover-background);
- --pico-border-color: var(--pico-secondary-hover-border);
- --pico-color: var(--pico-secondary-inverse);
-}
-:is(button, [type=submit], [type=button], [role=button]).secondary:focus, :is(button, [type=submit], [type=button], [role=button]).secondary:is([aria-current]:not([aria-current=false])):focus,
-[type=reset]:focus,
-[type=reset]:is([aria-current]:not([aria-current=false])):focus,
-[type=file]::file-selector-button:focus,
-[type=file]::file-selector-button:is([aria-current]:not([aria-current=false])):focus {
- --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus);
-}
-
-:is(button, [type=submit], [type=button], [role=button]).contrast {
- --pico-background-color: var(--pico-contrast-background);
- --pico-border-color: var(--pico-contrast-border);
- --pico-color: var(--pico-contrast-inverse);
-}
-:is(button, [type=submit], [type=button], [role=button]).contrast:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-background-color: var(--pico-contrast-hover-background);
- --pico-border-color: var(--pico-contrast-hover-border);
- --pico-color: var(--pico-contrast-inverse);
-}
-:is(button, [type=submit], [type=button], [role=button]).contrast:focus, :is(button, [type=submit], [type=button], [role=button]).contrast:is([aria-current]:not([aria-current=false])):focus {
- --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-contrast-focus);
-}
-
-:is(button, [type=submit], [type=button], [role=button]).outline,
-[type=reset].outline {
- --pico-background-color: transparent;
- --pico-color: var(--pico-primary);
- --pico-border-color: var(--pico-primary);
-}
-:is(button, [type=submit], [type=button], [role=button]).outline:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[type=reset].outline:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-background-color: transparent;
- --pico-color: var(--pico-primary-hover);
- --pico-border-color: var(--pico-primary-hover);
-}
-
-:is(button, [type=submit], [type=button], [role=button]).outline.secondary,
-[type=reset].outline {
- --pico-color: var(--pico-secondary);
- --pico-border-color: var(--pico-secondary);
-}
-:is(button, [type=submit], [type=button], [role=button]).outline.secondary:is([aria-current]:not([aria-current=false]), :hover, :active, :focus),
-[type=reset].outline:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-color: var(--pico-secondary-hover);
- --pico-border-color: var(--pico-secondary-hover);
-}
-
-:is(button, [type=submit], [type=button], [role=button]).outline.contrast {
- --pico-color: var(--pico-contrast);
- --pico-border-color: var(--pico-contrast);
-}
-:is(button, [type=submit], [type=button], [role=button]).outline.contrast:is([aria-current]:not([aria-current=false]), :hover, :active, :focus) {
- --pico-color: var(--pico-contrast-hover);
- --pico-border-color: var(--pico-contrast-hover);
-}
-
-:where(button, [type=submit], [type=reset], [type=button], [role=button])[disabled],
-:where(fieldset[disabled]) :is(button, [type=submit], [type=button], [type=reset], [role=button]) {
- opacity: 0.5;
- pointer-events: none;
-}
-
-/**
- * Table
- */
-:where(table) {
- width: 100%;
- border-collapse: collapse;
- border-spacing: 0;
- text-indent: 0;
-}
-
-th,
-td {
- padding: calc(var(--pico-spacing) / 2) var(--pico-spacing);
- border-bottom: var(--pico-border-width) solid var(--pico-table-border-color);
- background-color: var(--pico-background-color);
- color: var(--pico-color);
- font-weight: var(--pico-font-weight);
- text-align: left;
- text-align: start;
-}
-
-tfoot th,
-tfoot td {
- border-top: var(--pico-border-width) solid var(--pico-table-border-color);
- border-bottom: 0;
-}
-
-table.striped tbody tr:nth-child(odd) th,
-table.striped tbody tr:nth-child(odd) td {
- background-color: var(--pico-table-row-stripped-background-color);
-}
-
-/**
- * Embedded content
- */
-:where(audio, canvas, iframe, img, svg, video) {
- vertical-align: middle;
-}
-
-audio,
-video {
- display: inline-block;
-}
-
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-
-:where(iframe) {
- border-style: none;
-}
-
-img {
- max-width: 100%;
- height: auto;
- border-style: none;
-}
-
-:where(svg:not([fill])) {
- fill: currentColor;
-}
-
-svg:not(:root),
-svg:not(:host) {
- overflow: hidden;
-}
-
-/**
- * Code
- */
-pre,
-code,
-kbd,
-samp {
- font-size: 0.875em;
- font-family: var(--pico-font-family);
-}
-
-pre code,
-pre samp {
- font-size: inherit;
- font-family: inherit;
-}
-
-pre {
- -ms-overflow-style: scrollbar;
- overflow: auto;
-}
-
-pre,
-code,
-kbd,
-samp {
- border-radius: var(--pico-border-radius);
- background: var(--pico-code-background-color);
- color: var(--pico-code-color);
- font-weight: var(--pico-font-weight);
- line-height: initial;
-}
-
-code,
-kbd,
-samp {
- display: inline-block;
- padding: 0.375rem;
-}
-
-pre {
- display: block;
- margin-bottom: var(--pico-spacing);
- overflow-x: auto;
-}
-pre > code,
-pre > samp {
- display: block;
- padding: var(--pico-spacing);
- background: none;
- line-height: var(--pico-line-height);
-}
-
-kbd {
- background-color: var(--pico-code-kbd-background-color);
- color: var(--pico-code-kbd-color);
- vertical-align: baseline;
-}
-
-/**
- * Figure
- */
-figure {
- display: block;
- margin: 0;
- padding: 0;
-}
-figure figcaption {
- padding: calc(var(--pico-spacing) * 0.5) 0;
- color: var(--pico-muted-color);
-}
-
-/**
- * Misc
- */
-hr {
- height: 0;
- margin: var(--pico-typography-spacing-vertical) 0;
- border: 0;
- border-top: 1px solid var(--pico-muted-border-color);
- color: inherit;
-}
-
-[hidden],
-template {
- display: none !important;
-}
-
-canvas {
- display: inline-block;
-}
-
-/**
- * Basics form elements
- */
-input,
-optgroup,
-select,
-textarea {
- margin: 0;
- font-size: 1rem;
- line-height: var(--pico-line-height);
- font-family: inherit;
- letter-spacing: inherit;
-}
-
-input {
- overflow: visible;
-}
-
-select {
- text-transform: none;
-}
-
-legend {
- max-width: 100%;
- padding: 0;
- color: inherit;
- white-space: normal;
-}
-
-textarea {
- overflow: auto;
-}
-
-[type=checkbox],
-[type=radio] {
- padding: 0;
-}
-
-::-webkit-inner-spin-button,
-::-webkit-outer-spin-button {
- height: auto;
-}
-
-[type=search] {
- -webkit-appearance: textfield;
- outline-offset: -2px;
-}
-
-[type=search]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-::-webkit-file-upload-button {
- -webkit-appearance: button;
- font: inherit;
-}
-
-::-moz-focus-inner {
- padding: 0;
- border-style: none;
-}
-
-:-moz-focusring {
- outline: none;
-}
-
-:-moz-ui-invalid {
- box-shadow: none;
-}
-
-::-ms-expand {
- display: none;
-}
-
-[type=file],
-[type=range] {
- padding: 0;
- border-width: 0;
-}
-
-input:not([type=checkbox], [type=radio], [type=range]) {
- height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);
-}
-
-fieldset {
- width: 100%;
- margin: 0;
- margin-bottom: var(--pico-spacing);
- padding: 0;
- border: 0;
-}
-
-label,
-fieldset legend {
- display: block;
- margin-bottom: calc(var(--pico-spacing) * 0.375);
- color: var(--pico-color);
- font-weight: var(--pico-form-label-font-weight, var(--pico-font-weight));
-}
-
-fieldset legend {
- margin-bottom: calc(var(--pico-spacing) * 0.5);
-}
-
-input:not([type=checkbox], [type=radio]),
-button[type=submit],
-select,
-textarea {
- width: 100%;
-}
-
-input:not([type=checkbox], [type=radio], [type=range], [type=file]),
-select,
-textarea {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
-}
-
-input,
-select,
-textarea {
- --pico-background-color: var(--pico-form-element-background-color);
- --pico-border-color: var(--pico-form-element-border-color);
- --pico-color: var(--pico-form-element-color);
- --pico-box-shadow: none;
- border: var(--pico-border-width) solid var(--pico-border-color);
- border-radius: var(--pico-border-radius);
- outline: none;
- background-color: var(--pico-background-color);
- box-shadow: var(--pico-box-shadow);
- color: var(--pico-color);
- font-weight: var(--pico-font-weight);
- transition: background-color var(--pico-transition), border-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition);
-}
-
-input:not([type=submit],
-[type=button],
-[type=reset],
-[type=checkbox],
-[type=radio],
-[readonly]):is(:active, :focus),
-:where(select, textarea):not([readonly]):is(:active, :focus) {
- --pico-background-color: var(--pico-form-element-active-background-color);
-}
-
-input:not([type=submit], [type=button], [type=reset], [role=switch], [readonly]):is(:active, :focus),
-:where(select, textarea):not([readonly]):is(:active, :focus) {
- --pico-border-color: var(--pico-form-element-active-border-color);
-}
-
-input:not([type=submit],
-[type=button],
-[type=reset],
-[type=range],
-[type=file],
-[readonly]):focus,
-:where(select, textarea):not([readonly]):focus {
- --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color);
-}
-
-input:not([type=submit], [type=button], [type=reset])[disabled],
-select[disabled],
-textarea[disabled],
-label[aria-disabled=true],
-:where(fieldset[disabled]) :is(input:not([type=submit], [type=button], [type=reset]), select, textarea) {
- opacity: var(--pico-form-element-disabled-opacity);
- pointer-events: none;
-}
-
-label[aria-disabled=true] input[disabled] {
- opacity: 1;
-}
-
-:where(input, select, textarea):not([type=checkbox],
-[type=radio],
-[type=date],
-[type=datetime-local],
-[type=month],
-[type=time],
-[type=week],
-[type=range])[aria-invalid] {
- padding-right: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem) !important;
- padding-left: var(--pico-form-element-spacing-horizontal);
- padding-inline-start: var(--pico-form-element-spacing-horizontal) !important;
- padding-inline-end: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem) !important;
- background-position: center right 0.75rem;
- background-size: 1rem auto;
- background-repeat: no-repeat;
-}
-:where(input, select, textarea):not([type=checkbox],
-[type=radio],
-[type=date],
-[type=datetime-local],
-[type=month],
-[type=time],
-[type=week],
-[type=range])[aria-invalid=false]:not(select) {
- background-image: var(--pico-icon-valid);
-}
-:where(input, select, textarea):not([type=checkbox],
-[type=radio],
-[type=date],
-[type=datetime-local],
-[type=month],
-[type=time],
-[type=week],
-[type=range])[aria-invalid=true]:not(select) {
- background-image: var(--pico-icon-invalid);
-}
-:where(input, select, textarea)[aria-invalid=false] {
- --pico-border-color: var(--pico-form-element-valid-border-color);
-}
-:where(input, select, textarea)[aria-invalid=false]:is(:active, :focus) {
- --pico-border-color: var(--pico-form-element-valid-active-border-color) !important;
-}
-:where(input, select, textarea)[aria-invalid=false]:is(:active, :focus):not([type=checkbox], [type=radio]) {
- --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-valid-focus-color) !important;
-}
-:where(input, select, textarea)[aria-invalid=true] {
- --pico-border-color: var(--pico-form-element-invalid-border-color);
-}
-:where(input, select, textarea)[aria-invalid=true]:is(:active, :focus) {
- --pico-border-color: var(--pico-form-element-invalid-active-border-color) !important;
-}
-:where(input, select, textarea)[aria-invalid=true]:is(:active, :focus):not([type=checkbox], [type=radio]) {
- --pico-box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-invalid-focus-color) !important;
-}
-
-[dir=rtl] :where(input, select, textarea):not([type=checkbox], [type=radio]):is([aria-invalid], [aria-invalid=true], [aria-invalid=false]) {
- background-position: center left 0.75rem;
-}
-
-input::placeholder,
-input::-webkit-input-placeholder,
-textarea::placeholder,
-textarea::-webkit-input-placeholder,
-select:invalid {
- color: var(--pico-form-element-placeholder-color);
- opacity: 1;
-}
-
-input:not([type=checkbox], [type=radio]),
-select,
-textarea {
- margin-bottom: var(--pico-spacing);
-}
-
-select::-ms-expand {
- border: 0;
- background-color: transparent;
-}
-select:not([multiple], [size]) {
- padding-right: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);
- padding-left: var(--pico-form-element-spacing-horizontal);
- padding-inline-start: var(--pico-form-element-spacing-horizontal);
- padding-inline-end: calc(var(--pico-form-element-spacing-horizontal) + 1.5rem);
- background-image: var(--pico-icon-chevron);
- background-position: center right 0.75rem;
- background-size: 1rem auto;
- background-repeat: no-repeat;
-}
-select[multiple] option:checked {
- background: var(--pico-form-element-selected-background-color);
- color: var(--pico-form-element-color);
-}
-
-[dir=rtl] select:not([multiple], [size]) {
- background-position: center left 0.75rem;
-}
-
-textarea {
- display: block;
- resize: vertical;
-}
-textarea[aria-invalid] {
- --pico-icon-height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);
- background-position: top right 0.75rem !important;
- background-size: 1rem var(--pico-icon-height) !important;
-}
-
-:where(input, select, textarea, fieldset, .grid) + small {
- display: block;
- width: 100%;
- margin-top: calc(var(--pico-spacing) * -0.75);
- margin-bottom: var(--pico-spacing);
- color: var(--pico-muted-color);
-}
-:where(input, select, textarea, fieldset, .grid)[aria-invalid=false] + small {
- color: var(--pico-ins-color);
-}
-:where(input, select, textarea, fieldset, .grid)[aria-invalid=true] + small {
- color: var(--pico-del-color);
-}
-
-label > :where(input, select, textarea) {
- margin-top: calc(var(--pico-spacing) * 0.25);
-}
-
-/**
- * Checkboxes, Radios and Switches
- */
-label:has([type=checkbox], [type=radio]) {
- width: -moz-fit-content;
- width: fit-content;
- cursor: pointer;
-}
-
-[type=checkbox],
-[type=radio] {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- width: 1.25em;
- height: 1.25em;
- margin-top: -0.125em;
- margin-inline-end: 0.5em;
- border-width: var(--pico-border-width);
- vertical-align: middle;
- cursor: pointer;
-}
-[type=checkbox]::-ms-check,
-[type=radio]::-ms-check {
- display: none;
-}
-[type=checkbox]:checked, [type=checkbox]:checked:active, [type=checkbox]:checked:focus,
-[type=radio]:checked,
-[type=radio]:checked:active,
-[type=radio]:checked:focus {
- --pico-background-color: var(--pico-primary-background);
- --pico-border-color: var(--pico-primary-border);
- background-image: var(--pico-icon-checkbox);
- background-position: center;
- background-size: 0.75em auto;
- background-repeat: no-repeat;
-}
-[type=checkbox] ~ label,
-[type=radio] ~ label {
- display: inline-block;
- margin-bottom: 0;
- cursor: pointer;
-}
-[type=checkbox] ~ label:not(:last-of-type),
-[type=radio] ~ label:not(:last-of-type) {
- margin-inline-end: 1em;
-}
-
-[type=checkbox]:indeterminate {
- --pico-background-color: var(--pico-primary-background);
- --pico-border-color: var(--pico-primary-border);
- background-image: var(--pico-icon-minus);
- background-position: center;
- background-size: 0.75em auto;
- background-repeat: no-repeat;
-}
-
-[type=radio] {
- border-radius: 50%;
-}
-[type=radio]:checked, [type=radio]:checked:active, [type=radio]:checked:focus {
- --pico-background-color: var(--pico-primary-inverse);
- border-width: 0.35em;
- background-image: none;
-}
-
-[type=checkbox][role=switch] {
- --pico-background-color: var(--pico-switch-background-color);
- --pico-color: var(--pico-switch-color);
- width: 2.25em;
- height: 1.25em;
- border: var(--pico-border-width) solid var(--pico-border-color);
- border-radius: 1.25em;
- background-color: var(--pico-background-color);
- line-height: 1.25em;
-}
-[type=checkbox][role=switch]:not([aria-invalid]) {
- --pico-border-color: var(--pico-switch-background-color);
-}
-[type=checkbox][role=switch]:before {
- display: block;
- aspect-ratio: 1;
- height: 100%;
- border-radius: 50%;
- background-color: var(--pico-color);
- box-shadow: var(--pico-switch-thumb-box-shadow);
- content: "";
- transition: margin 0.1s ease-in-out;
-}
-[type=checkbox][role=switch]:focus {
- --pico-background-color: var(--pico-switch-background-color);
- --pico-border-color: var(--pico-switch-background-color);
-}
-[type=checkbox][role=switch]:checked {
- --pico-background-color: var(--pico-switch-checked-background-color);
- --pico-border-color: var(--pico-switch-checked-background-color);
- background-image: none;
-}
-[type=checkbox][role=switch]:checked::before {
- margin-inline-start: calc(2.25em - 1.25em);
-}
-[type=checkbox][role=switch][disabled] {
- --pico-background-color: var(--pico-border-color);
-}
-
-[type=checkbox][aria-invalid=false]:checked, [type=checkbox][aria-invalid=false]:checked:active, [type=checkbox][aria-invalid=false]:checked:focus,
-[type=checkbox][role=switch][aria-invalid=false]:checked,
-[type=checkbox][role=switch][aria-invalid=false]:checked:active,
-[type=checkbox][role=switch][aria-invalid=false]:checked:focus {
- --pico-background-color: var(--pico-form-element-valid-border-color);
-}
-[type=checkbox]:checked[aria-invalid=true], [type=checkbox]:checked:active[aria-invalid=true], [type=checkbox]:checked:focus[aria-invalid=true],
-[type=checkbox][role=switch]:checked[aria-invalid=true],
-[type=checkbox][role=switch]:checked:active[aria-invalid=true],
-[type=checkbox][role=switch]:checked:focus[aria-invalid=true] {
- --pico-background-color: var(--pico-form-element-invalid-border-color);
-}
-
-[type=checkbox][aria-invalid=false]:checked, [type=checkbox][aria-invalid=false]:checked:active, [type=checkbox][aria-invalid=false]:checked:focus,
-[type=radio][aria-invalid=false]:checked,
-[type=radio][aria-invalid=false]:checked:active,
-[type=radio][aria-invalid=false]:checked:focus,
-[type=checkbox][role=switch][aria-invalid=false]:checked,
-[type=checkbox][role=switch][aria-invalid=false]:checked:active,
-[type=checkbox][role=switch][aria-invalid=false]:checked:focus {
- --pico-border-color: var(--pico-form-element-valid-border-color);
-}
-[type=checkbox]:checked[aria-invalid=true], [type=checkbox]:checked:active[aria-invalid=true], [type=checkbox]:checked:focus[aria-invalid=true],
-[type=radio]:checked[aria-invalid=true],
-[type=radio]:checked:active[aria-invalid=true],
-[type=radio]:checked:focus[aria-invalid=true],
-[type=checkbox][role=switch]:checked[aria-invalid=true],
-[type=checkbox][role=switch]:checked:active[aria-invalid=true],
-[type=checkbox][role=switch]:checked:focus[aria-invalid=true] {
- --pico-border-color: var(--pico-form-element-invalid-border-color);
-}
-
-/**
- * Input type color
- */
-[type=color]::-webkit-color-swatch-wrapper {
- padding: 0;
-}
-[type=color]::-moz-focus-inner {
- padding: 0;
-}
-[type=color]::-webkit-color-swatch {
- border: 0;
- border-radius: calc(var(--pico-border-radius) * 0.5);
-}
-[type=color]::-moz-color-swatch {
- border: 0;
- border-radius: calc(var(--pico-border-radius) * 0.5);
-}
-
-/**
- * Input type datetime
- */
-input:not([type=checkbox], [type=radio], [type=range], [type=file]):is([type=date], [type=datetime-local], [type=month], [type=time], [type=week]) {
- --pico-icon-position: 0.75rem;
- --pico-icon-width: 1rem;
- padding-right: calc(var(--pico-icon-width) + var(--pico-icon-position));
- background-image: var(--pico-icon-date);
- background-position: center right var(--pico-icon-position);
- background-size: var(--pico-icon-width) auto;
- background-repeat: no-repeat;
-}
-input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=time] {
- background-image: var(--pico-icon-time);
-}
-
-[type=date]::-webkit-calendar-picker-indicator,
-[type=datetime-local]::-webkit-calendar-picker-indicator,
-[type=month]::-webkit-calendar-picker-indicator,
-[type=time]::-webkit-calendar-picker-indicator,
-[type=week]::-webkit-calendar-picker-indicator {
- width: var(--pico-icon-width);
- margin-right: calc(var(--pico-icon-width) * -1);
- margin-left: var(--pico-icon-position);
- opacity: 0;
-}
-
-@-moz-document url-prefix() {
- [type=date],
- [type=datetime-local],
- [type=month],
- [type=time],
- [type=week] {
- padding-right: var(--pico-form-element-spacing-horizontal) !important;
- background-image: none !important;
- }
-}
-[dir=rtl] :is([type=date], [type=datetime-local], [type=month], [type=time], [type=week]) {
- text-align: right;
-}
-
-/**
- * Input type file
- */
-[type=file] {
- --pico-color: var(--pico-muted-color);
- margin-left: calc(var(--pico-outline-width) * -1);
- padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) 0;
- padding-left: var(--pico-outline-width);
- border: 0;
- border-radius: 0;
- background: none;
-}
-[type=file]::file-selector-button {
- margin-right: calc(var(--pico-spacing) / 2);
- padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) var(--pico-form-element-spacing-horizontal);
-}
-[type=file]:is(:hover, :active, :focus)::file-selector-button {
- --pico-background-color: var(--pico-secondary-hover-background);
- --pico-border-color: var(--pico-secondary-hover-border);
-}
-[type=file]:focus::file-selector-button {
- --pico-box-shadow: var(--pico-button-hover-box-shadow, 0 0 0 rgba(0, 0, 0, 0)), 0 0 0 var(--pico-outline-width) var(--pico-secondary-focus);
-}
-
-/**
- * Input type range
- */
-[type=range] {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- width: 100%;
- height: 1.25rem;
- background: none;
-}
-[type=range]::-webkit-slider-runnable-track {
- width: 100%;
- height: 0.375rem;
- border-radius: var(--pico-border-radius);
- background-color: var(--pico-range-border-color);
- -webkit-transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
- transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
-}
-[type=range]::-moz-range-track {
- width: 100%;
- height: 0.375rem;
- border-radius: var(--pico-border-radius);
- background-color: var(--pico-range-border-color);
- -moz-transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
- transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
-}
-[type=range]::-ms-track {
- width: 100%;
- height: 0.375rem;
- border-radius: var(--pico-border-radius);
- background-color: var(--pico-range-border-color);
- -ms-transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
- transition: background-color var(--pico-transition), box-shadow var(--pico-transition);
-}
-[type=range]::-webkit-slider-thumb {
- -webkit-appearance: none;
- width: 1.25rem;
- height: 1.25rem;
- margin-top: -0.4375rem;
- border: 2px solid var(--pico-range-thumb-border-color);
- border-radius: 50%;
- background-color: var(--pico-range-thumb-color);
- cursor: pointer;
- -webkit-transition: background-color var(--pico-transition), transform var(--pico-transition);
- transition: background-color var(--pico-transition), transform var(--pico-transition);
-}
-[type=range]::-moz-range-thumb {
- -webkit-appearance: none;
- width: 1.25rem;
- height: 1.25rem;
- margin-top: -0.4375rem;
- border: 2px solid var(--pico-range-thumb-border-color);
- border-radius: 50%;
- background-color: var(--pico-range-thumb-color);
- cursor: pointer;
- -moz-transition: background-color var(--pico-transition), transform var(--pico-transition);
- transition: background-color var(--pico-transition), transform var(--pico-transition);
-}
-[type=range]::-ms-thumb {
- -webkit-appearance: none;
- width: 1.25rem;
- height: 1.25rem;
- margin-top: -0.4375rem;
- border: 2px solid var(--pico-range-thumb-border-color);
- border-radius: 50%;
- background-color: var(--pico-range-thumb-color);
- cursor: pointer;
- -ms-transition: background-color var(--pico-transition), transform var(--pico-transition);
- transition: background-color var(--pico-transition), transform var(--pico-transition);
-}
-[type=range]:active, [type=range]:focus-within {
- --pico-range-border-color: var(--pico-range-active-border-color);
- --pico-range-thumb-color: var(--pico-range-thumb-active-color);
-}
-[type=range]:active::-webkit-slider-thumb {
- transform: scale(1.25);
-}
-[type=range]:active::-moz-range-thumb {
- transform: scale(1.25);
-}
-[type=range]:active::-ms-thumb {
- transform: scale(1.25);
-}
-
-/**
- * Input type search
- */
-input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search] {
- padding-inline-start: calc(var(--pico-form-element-spacing-horizontal) + 1.75rem);
- background-image: var(--pico-icon-search);
- background-position: center left calc(var(--pico-form-element-spacing-horizontal) + 0.125rem);
- background-size: 1rem auto;
- background-repeat: no-repeat;
-}
-input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid] {
- padding-inline-start: calc(var(--pico-form-element-spacing-horizontal) + 1.75rem) !important;
- background-position: center left 1.125rem, center right 0.75rem;
-}
-input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid=false] {
- background-image: var(--pico-icon-search), var(--pico-icon-valid);
-}
-input:not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid=true] {
- background-image: var(--pico-icon-search), var(--pico-icon-invalid);
-}
-
-[dir=rtl] :where(input):not([type=checkbox], [type=radio], [type=range], [type=file])[type=search] {
- background-position: center right 1.125rem;
-}
-[dir=rtl] :where(input):not([type=checkbox], [type=radio], [type=range], [type=file])[type=search][aria-invalid] {
- background-position: center right 1.125rem, center left 0.75rem;
-}
-
-/**
- * Accordion ()
- */
-details {
- display: block;
- margin-bottom: var(--pico-spacing);
-}
-details summary {
- line-height: 1rem;
- list-style-type: none;
- cursor: pointer;
- transition: color var(--pico-transition);
-}
-details summary:not([role]) {
- color: var(--pico-accordion-close-summary-color);
-}
-details summary::-webkit-details-marker {
- display: none;
-}
-details summary::marker {
- display: none;
-}
-details summary::-moz-list-bullet {
- list-style-type: none;
-}
-details summary::after {
- display: block;
- width: 1rem;
- height: 1rem;
- margin-inline-start: calc(var(--pico-spacing, 1rem) * 0.5);
- float: right;
- transform: rotate(-90deg);
- background-image: var(--pico-icon-chevron);
- background-position: right center;
- background-size: 1rem auto;
- background-repeat: no-repeat;
- content: "";
- transition: transform var(--pico-transition);
-}
-details summary:focus {
- outline: none;
-}
-details summary:focus:not([role]) {
- color: var(--pico-accordion-active-summary-color);
-}
-details summary:focus-visible:not([role]) {
- outline: var(--pico-outline-width) solid var(--pico-primary-focus);
- outline-offset: calc(var(--pico-spacing, 1rem) * 0.5);
- color: var(--pico-primary);
-}
-details summary[role=button] {
- width: 100%;
- text-align: left;
-}
-details summary[role=button]::after {
- height: calc(1rem * var(--pico-line-height, 1.5));
-}
-details[open] > summary {
- margin-bottom: var(--pico-spacing);
-}
-details[open] > summary:not([role]):not(:focus) {
- color: var(--pico-accordion-open-summary-color);
-}
-details[open] > summary::after {
- transform: rotate(0);
-}
-
-[dir=rtl] details summary {
- text-align: right;
-}
-[dir=rtl] details summary::after {
- float: left;
- background-position: left center;
-}
-
-/**
- * Card ()
- */
-article {
- margin-bottom: var(--pico-block-spacing-vertical);
- padding: var(--pico-block-spacing-vertical) var(--pico-block-spacing-horizontal);
- border-radius: var(--pico-border-radius);
- background: var(--pico-card-background-color);
- box-shadow: var(--pico-card-box-shadow);
-}
-article > header,
-article > footer {
- margin-right: calc(var(--pico-block-spacing-horizontal) * -1);
- margin-left: calc(var(--pico-block-spacing-horizontal) * -1);
- padding: calc(var(--pico-block-spacing-vertical) * 0.66) var(--pico-block-spacing-horizontal);
- background-color: var(--pico-card-sectioning-background-color);
-}
-article > header {
- margin-top: calc(var(--pico-block-spacing-vertical) * -1);
- margin-bottom: var(--pico-block-spacing-vertical);
- border-bottom: var(--pico-border-width) solid var(--pico-card-border-color);
- border-top-right-radius: var(--pico-border-radius);
- border-top-left-radius: var(--pico-border-radius);
-}
-article > footer {
- margin-top: var(--pico-block-spacing-vertical);
- margin-bottom: calc(var(--pico-block-spacing-vertical) * -1);
- border-top: var(--pico-border-width) solid var(--pico-card-border-color);
- border-bottom-right-radius: var(--pico-border-radius);
- border-bottom-left-radius: var(--pico-border-radius);
-}
-
-/**
- * Dropdown (details.dropdown)
- */
-details.dropdown {
- position: relative;
- border-bottom: none;
-}
-details.dropdown > summary::after,
-details.dropdown > button::after,
-details.dropdown > a::after {
- display: block;
- width: 1rem;
- height: calc(1rem * var(--pico-line-height, 1.5));
- margin-inline-start: 0.25rem;
- float: right;
- transform: rotate(0deg) translateX(0.2rem);
- background-image: var(--pico-icon-chevron);
- background-position: right center;
- background-size: 1rem auto;
- background-repeat: no-repeat;
- content: "";
-}
-
-nav details.dropdown {
- margin-bottom: 0;
-}
-
-details.dropdown > summary:not([role]) {
- height: calc(1rem * var(--pico-line-height) + var(--pico-form-element-spacing-vertical) * 2 + var(--pico-border-width) * 2);
- padding: var(--pico-form-element-spacing-vertical) var(--pico-form-element-spacing-horizontal);
- border: var(--pico-border-width) solid var(--pico-form-element-border-color);
- border-radius: var(--pico-border-radius);
- background-color: var(--pico-form-element-background-color);
- color: var(--pico-form-element-placeholder-color);
- line-height: inherit;
- cursor: pointer;
- -webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
- transition: background-color var(--pico-transition), border-color var(--pico-transition), color var(--pico-transition), box-shadow var(--pico-transition);
-}
-details.dropdown > summary:not([role]):active, details.dropdown > summary:not([role]):focus {
- border-color: var(--pico-form-element-active-border-color);
- background-color: var(--pico-form-element-active-background-color);
-}
-details.dropdown > summary:not([role]):focus {
- box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-form-element-focus-color);
-}
-details.dropdown > summary:not([role]):focus-visible {
- outline: none;
-}
-details.dropdown > summary:not([role])[aria-invalid=false] {
- --pico-form-element-border-color: var(--pico-form-element-valid-border-color);
- --pico-form-element-active-border-color: var(--pico-form-element-valid-focus-color);
- --pico-form-element-focus-color: var(--pico-form-element-valid-focus-color);
-}
-details.dropdown > summary:not([role])[aria-invalid=true] {
- --pico-form-element-border-color: var(--pico-form-element-invalid-border-color);
- --pico-form-element-active-border-color: var(--pico-form-element-invalid-focus-color);
- --pico-form-element-focus-color: var(--pico-form-element-invalid-focus-color);
-}
-
-nav details.dropdown {
- display: inline;
- margin: calc(var(--pico-nav-element-spacing-vertical) * -1) 0;
-}
-nav details.dropdown > summary::after {
- transform: rotate(0deg) translateX(0rem);
-}
-nav details.dropdown > summary:not([role]) {
- height: calc(1rem * var(--pico-line-height) + var(--pico-nav-link-spacing-vertical) * 2);
- padding: calc(var(--pico-nav-link-spacing-vertical) - var(--pico-border-width) * 2) var(--pico-nav-link-spacing-horizontal);
-}
-nav details.dropdown > summary:not([role]):focus-visible {
- box-shadow: 0 0 0 var(--pico-outline-width) var(--pico-primary-focus);
-}
-
-details.dropdown > summary + ul {
- display: flex;
- z-index: 99;
- position: absolute;
- left: 0;
- flex-direction: column;
- width: 100%;
- min-width: -moz-fit-content;
- min-width: fit-content;
- margin: 0;
- margin-top: var(--pico-outline-width);
- padding: 0;
- border: var(--pico-border-width) solid var(--pico-dropdown-border-color);
- border-radius: var(--pico-border-radius);
- background-color: var(--pico-dropdown-background-color);
- box-shadow: var(--pico-dropdown-box-shadow);
- color: var(--pico-dropdown-color);
- white-space: nowrap;
- opacity: 0;
- transition: opacity var(--pico-transition), transform 0s ease-in-out 1s;
-}
-details.dropdown > summary + ul[dir=rtl] {
- right: 0;
- left: auto;
-}
-details.dropdown > summary + ul li {
- width: 100%;
- margin-bottom: 0;
- padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) var(--pico-form-element-spacing-horizontal);
- list-style: none;
-}
-details.dropdown > summary + ul li:first-of-type {
- margin-top: calc(var(--pico-form-element-spacing-vertical) * 0.5);
-}
-details.dropdown > summary + ul li:last-of-type {
- margin-bottom: calc(var(--pico-form-element-spacing-vertical) * 0.5);
-}
-details.dropdown > summary + ul li a {
- display: block;
- margin: calc(var(--pico-form-element-spacing-vertical) * -0.5) calc(var(--pico-form-element-spacing-horizontal) * -1);
- padding: calc(var(--pico-form-element-spacing-vertical) * 0.5) var(--pico-form-element-spacing-horizontal);
- overflow: hidden;
- border-radius: 0;
- color: var(--pico-dropdown-color);
- text-decoration: none;
- text-overflow: ellipsis;
-}
-details.dropdown > summary + ul li a:hover, details.dropdown > summary + ul li a:focus, details.dropdown > summary + ul li a:active, details.dropdown > summary + ul li a:focus-visible, details.dropdown > summary + ul li a[aria-current]:not([aria-current=false]) {
- background-color: var(--pico-dropdown-hover-background-color);
-}
-details.dropdown > summary + ul li label {
- width: 100%;
-}
-details.dropdown > summary + ul li:has(label):hover {
- background-color: var(--pico-dropdown-hover-background-color);
-}
-
-details.dropdown[open] > summary {
- margin-bottom: 0;
-}
-
-details.dropdown[open] > summary + ul {
- transform: scaleY(1);
- opacity: 1;
- transition: opacity var(--pico-transition), transform 0s ease-in-out 0s;
-}
-
-details.dropdown[open] > summary::before {
- display: block;
- z-index: 1;
- position: fixed;
- width: 100vw;
- height: 100vh;
- inset: 0;
- background: none;
- content: "";
- cursor: default;
-}
-
-label > details.dropdown {
- margin-top: calc(var(--pico-spacing) * 0.25);
-}
-
-/**
- * Group ([role="group"], [role="search"])
- */
-[role=search],
-[role=group] {
- display: inline-flex;
- position: relative;
- width: 100%;
- margin-bottom: var(--pico-spacing);
- border-radius: var(--pico-border-radius);
- box-shadow: var(--pico-group-box-shadow, 0 0 0 rgba(0, 0, 0, 0));
- vertical-align: middle;
- transition: box-shadow var(--pico-transition);
-}
-[role=search] > *,
-[role=search] input:not([type=checkbox], [type=radio]),
-[role=search] select,
-[role=group] > *,
-[role=group] input:not([type=checkbox], [type=radio]),
-[role=group] select {
- position: relative;
- flex: 1 1 auto;
- margin-bottom: 0;
-}
-[role=search] > *:not(:first-child),
-[role=search] input:not([type=checkbox], [type=radio]):not(:first-child),
-[role=search] select:not(:first-child),
-[role=group] > *:not(:first-child),
-[role=group] input:not([type=checkbox], [type=radio]):not(:first-child),
-[role=group] select:not(:first-child) {
- margin-left: 0;
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
-}
-[role=search] > *:not(:last-child),
-[role=search] input:not([type=checkbox], [type=radio]):not(:last-child),
-[role=search] select:not(:last-child),
-[role=group] > *:not(:last-child),
-[role=group] input:not([type=checkbox], [type=radio]):not(:last-child),
-[role=group] select:not(:last-child) {
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
-}
-[role=search] > *:focus,
-[role=search] input:not([type=checkbox], [type=radio]):focus,
-[role=search] select:focus,
-[role=group] > *:focus,
-[role=group] input:not([type=checkbox], [type=radio]):focus,
-[role=group] select:focus {
- z-index: 2;
-}
-[role=search] button:not(:first-child),
-[role=search] [type=submit]:not(:first-child),
-[role=search] [type=reset]:not(:first-child),
-[role=search] [type=button]:not(:first-child),
-[role=search] [role=button]:not(:first-child),
-[role=search] input:not([type=checkbox], [type=radio]):not(:first-child),
-[role=search] select:not(:first-child),
-[role=group] button:not(:first-child),
-[role=group] [type=submit]:not(:first-child),
-[role=group] [type=reset]:not(:first-child),
-[role=group] [type=button]:not(:first-child),
-[role=group] [role=button]:not(:first-child),
-[role=group] input:not([type=checkbox], [type=radio]):not(:first-child),
-[role=group] select:not(:first-child) {
- margin-left: calc(var(--pico-border-width) * -1);
-}
-[role=search] button,
-[role=search] [type=submit],
-[role=search] [type=reset],
-[role=search] [type=button],
-[role=search] [role=button],
-[role=group] button,
-[role=group] [type=submit],
-[role=group] [type=reset],
-[role=group] [type=button],
-[role=group] [role=button] {
- width: auto;
-}
-@supports selector(:has(*)) {
- [role=search]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus),
- [role=group]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) {
- --pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-button);
- }
- [role=search]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) input:not([type=checkbox], [type=radio]),
- [role=search]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) select,
- [role=group]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) input:not([type=checkbox], [type=radio]),
- [role=group]:has(button:focus, [type=submit]:focus, [type=button]:focus, [role=button]:focus) select {
- border-color: transparent;
- }
- [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus),
- [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) {
- --pico-group-box-shadow: var(--pico-group-box-shadow-focus-with-input);
- }
- [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) button,
- [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=submit],
- [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=button],
- [role=search]:has(input:not([type=submit], [type=button]):focus, select:focus) [role=button],
- [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) button,
- [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=submit],
- [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) [type=button],
- [role=group]:has(input:not([type=submit], [type=button]):focus, select:focus) [role=button] {
- --pico-button-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-border);
- --pico-button-hover-box-shadow: 0 0 0 var(--pico-border-width) var(--pico-primary-hover-border);
- }
- [role=search] button:focus,
- [role=search] [type=submit]:focus,
- [role=search] [type=reset]:focus,
- [role=search] [type=button]:focus,
- [role=search] [role=button]:focus,
- [role=group] button:focus,
- [role=group] [type=submit]:focus,
- [role=group] [type=reset]:focus,
- [role=group] [type=button]:focus,
- [role=group] [role=button]:focus {
- box-shadow: none;
- }
-}
-
-[role=search] > *:first-child {
- border-top-left-radius: 5rem;
- border-bottom-left-radius: 5rem;
-}
-[role=search] > *:last-child {
- border-top-right-radius: 5rem;
- border-bottom-right-radius: 5rem;
-}
-
-/**
- * Loading ([aria-busy=true])
- */
-[aria-busy=true]:not(input, select, textarea, html, form) {
- white-space: nowrap;
-}
-[aria-busy=true]:not(input, select, textarea, html, form)::before {
- display: inline-block;
- width: 1em;
- height: 1em;
- background-image: var(--pico-icon-loading);
- background-size: 1em auto;
- background-repeat: no-repeat;
- content: "";
- vertical-align: -0.125em;
-}
-[aria-busy=true]:not(input, select, textarea, html, form):not(:empty)::before {
- margin-inline-end: calc(var(--pico-spacing) * 0.5);
-}
-[aria-busy=true]:not(input, select, textarea, html, form):empty {
- text-align: center;
-}
-
-button[aria-busy=true],
-[type=submit][aria-busy=true],
-[type=button][aria-busy=true],
-[type=reset][aria-busy=true],
-[role=button][aria-busy=true],
-a[aria-busy=true] {
- pointer-events: none;
-}
-
-/**
- * Modal (