detached b1ebd30

New structure and embedding ok

commit
b1ebd301f7ef87cd55f96ca7add691d1a074d3f7
author
bnema · · 2023-09-12 17:30 UTC
parent
69d1ee6
signature
unsigned
54 files · +2128 -991

this diff is incomplete: 2 files are too large to show. the totals above count everything; clone the repository to read the rest.

M .gitignore +1 -0
@@ -7,3 +7,4 @@ logs/error.log
77 logs/http.log
88 logs/docker.log
99 gordon.yml
10+bun.lockb
@@ -7,3 +7,4 @@ logs/error.log
7 logs/http.log7 logs/http.log
8 logs/docker.log8 logs/docker.log
9 gordon.yml9 gordon.yml
10+bun.lockb
A cmd/main.go +10 -0
@@ -0,0 +1,10 @@
1+package main
2+
3+import (
4+ "github.com/bnema/gordon/internal/app"
5+)
6+
7+func main() {
8+ a := app.NewApp()
9+ a.Start()
10+}
@@ -0,0 +1,10 @@
1+package main
2+
3+import (
4+ "github.com/bnema/gordon/internal/app"
5+)
6+
7+func main() {
8+ a := app.NewApp()
9+ a.Start()
10+}
A go.mod +21 -0
@@ -0,0 +1,21 @@
1+module github.com/bnema/gordon
2+
3+go 1.21.1
4+
5+require (
6+ github.com/PuerkitoBio/goquery v1.8.1
7+ github.com/labstack/echo/v4 v4.11.1
8+)
9+
10+require (
11+ github.com/andybalholm/cascadia v1.3.1 // indirect
12+ github.com/labstack/gommon v0.4.0 // indirect
13+ github.com/mattn/go-colorable v0.1.13 // indirect
14+ github.com/mattn/go-isatty v0.0.19 // indirect
15+ github.com/valyala/bytebufferpool v1.0.0 // indirect
16+ github.com/valyala/fasttemplate v1.2.2 // indirect
17+ golang.org/x/crypto v0.11.0 // indirect
18+ golang.org/x/net v0.12.0 // indirect
19+ golang.org/x/sys v0.10.0 // indirect
20+ golang.org/x/text v0.11.0 // indirect
21+)
@@ -0,0 +1,21 @@
1+module github.com/bnema/gordon
2+
3+go 1.21.1
4+
5+require (
6+ github.com/PuerkitoBio/goquery v1.8.1
7+ github.com/labstack/echo/v4 v4.11.1
8+)
9+
10+require (
11+ github.com/andybalholm/cascadia v1.3.1 // indirect
12+ github.com/labstack/gommon v0.4.0 // indirect
13+ github.com/mattn/go-colorable v0.1.13 // indirect
14+ github.com/mattn/go-isatty v0.0.19 // indirect
15+ github.com/valyala/bytebufferpool v1.0.0 // indirect
16+ github.com/valyala/fasttemplate v1.2.2 // indirect
17+ golang.org/x/crypto v0.11.0 // indirect
18+ golang.org/x/net v0.12.0 // indirect
19+ golang.org/x/sys v0.10.0 // indirect
20+ golang.org/x/text v0.11.0 // indirect
21+)
A go.sum +77 -0 generated file: collapsed
A internal/app/app.go +61 -0
@@ -0,0 +1,61 @@
1+package app
2+
3+import (
4+ "fmt"
5+ "io/fs"
6+
7+ "github.com/bnema/gordon/internal/gotemplate"
8+ "github.com/bnema/gordon/internal/webui"
9+)
10+
11+const (
12+ BuildVersion = "0.0.2"
13+ BuildDir = "tmp"
14+)
15+
16+type App struct {
17+ TemplateFS fs.FS
18+ PublicFS fs.FS
19+ BuildVersion string
20+ BuildDir string
21+}
22+
23+func (*App) GetTemplateFS() fs.FS {
24+ return gotemplate.TemplateFS
25+}
26+
27+func (*App) GetPublicFS() fs.FS {
28+ return webui.PublicFS
29+}
30+
31+func (*App) GetBuildVersion() string {
32+ return BuildVersion
33+}
34+
35+func (*App) GetBuildDir() string {
36+ return BuildDir
37+}
38+
39+func NewApp() *App {
40+ return &App{
41+ TemplateFS: gotemplate.TemplateFS,
42+ PublicFS: webui.PublicFS,
43+ BuildVersion: BuildVersion,
44+ BuildDir: BuildDir,
45+ }
46+}
47+
48+func (a *App) Start() {
49+ fmt.Println("Starting app")
50+
51+ // LS in the template directory
52+ entries, err := fs.ReadDir(a.TemplateFS, ".") // List the root directory
53+ if err != nil {
54+ fmt.Println("Error reading directory:", err)
55+ return
56+ }
57+
58+ for _, entry := range entries {
59+ fmt.Println(entry.Name())
60+ }
61+}
@@ -0,0 +1,61 @@
1+package app
2+
3+import (
4+ "fmt"
5+ "io/fs"
6+
7+ "github.com/bnema/gordon/internal/gotemplate"
8+ "github.com/bnema/gordon/internal/webui"
9+)
10+
11+const (
12+ BuildVersion = "0.0.2"
13+ BuildDir = "tmp"
14+)
15+
16+type App struct {
17+ TemplateFS fs.FS
18+ PublicFS fs.FS
19+ BuildVersion string
20+ BuildDir string
21+}
22+
23+func (*App) GetTemplateFS() fs.FS {
24+ return gotemplate.TemplateFS
25+}
26+
27+func (*App) GetPublicFS() fs.FS {
28+ return webui.PublicFS
29+}
30+
31+func (*App) GetBuildVersion() string {
32+ return BuildVersion
33+}
34+
35+func (*App) GetBuildDir() string {
36+ return BuildDir
37+}
38+
39+func NewApp() *App {
40+ return &App{
41+ TemplateFS: gotemplate.TemplateFS,
42+ PublicFS: webui.PublicFS,
43+ BuildVersion: BuildVersion,
44+ BuildDir: BuildDir,
45+ }
46+}
47+
48+func (a *App) Start() {
49+ fmt.Println("Starting app")
50+
51+ // LS in the template directory
52+ entries, err := fs.ReadDir(a.TemplateFS, ".") // List the root directory
53+ if err != nil {
54+ fmt.Println("Error reading directory:", err)
55+ return
56+ }
57+
58+ for _, entry := range entries {
59+ fmt.Println(entry.Name())
60+ }
61+}
A internal/gotemplate/embed.go +13 -0
@@ -0,0 +1,13 @@
1+package gotemplate
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding templates directories
10+
11+//go:embed models/*
12+var template embed.FS
13+var TemplateFS = echo.MustSubFS(template, "models")
@@ -0,0 +1,13 @@
1+package gotemplate
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding templates directories
10+
11+//go:embed models/*
12+var template embed.FS
13+var TemplateFS = echo.MustSubFS(template, "models")
A internal/gotemplate/models/html/admin/dashboard.gohtml +9 -0
@@ -0,0 +1,9 @@
1+<div id="dashboard">
2+ <h1
3+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
4+ >
5+ Hello World from dashboard.html
6+ </h1>
7+ <!-- We load Chart.js here to avoid loading it in every page end when all the rest is loaded -->
8+ <script src="libs/chart.js"></script>
9+</div>
@@ -0,0 +1,9 @@
1+<div id="dashboard">
2+ <h1
3+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
4+ >
5+ Hello World from dashboard.html
6+ </h1>
7+ <!-- We load Chart.js here to avoid loading it in every page end when all the rest is loaded -->
8+ <script src="libs/chart.js"></script>
9+</div>
A internal/gotemplate/models/html/admin/index.gohtml +124 -0
@@ -0,0 +1,124 @@
1+<!-- @format -->
2+
3+<!DOCTYPE html>
4+<html lang="en">
5+ <head>
6+ <meta charset="UTF-8" />
7+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+ <title>{{ .header.meta.title }}</title>
9+ <meta name="description" content="{{ .Header.Meta.Description }}" />
10+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
11+ <!-- Custom CSS + Tailwind -->
12+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
13+ <!-- Iconoir -->
14+ <link rel="stylesheet" href="/libs/iconoir.css" />
15+ <!-- Alpine -->
16+ <script src="/libs/alpine.min.js"></script>
17+ <!-- HTMX min js -->
18+ <script src="/libs/htmx.min.js"></script>
19+ <!-- HTMX SSE -->
20+ <script src="/libs/htmx-sse.js"></script>
21+ <!-- Custom JS from assets/js -->
22+ <script src="assets/js/custom.js"></script>
23+ </head>
24+ <body class="IBMPlexSans bg-zinc-200 md:p-8 flex">
25+ <!-- Left Menu -->
26+ <div class="w-1/5 flex flex-col space-evenly">
27+ <!-- Logo -->
28+ <div id="logo-mascot-leftnav" class="flex justify-center p-4">
29+ <div class="circle-shadow flex justify-center w-100">
30+ <img
31+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
32+ alt="logo"
33+ class="sm:h-24 h-32 xl:h-48"
34+ />
35+ </div>
36+ </div>
37+ <!-- Site Name + Version -->
38+ <div
39+ class="p-4 flex flex-col bg-gordonmascot-lblue rounded-lg shadow space-y-4"
40+ >
41+ <div class="w-full flex justify-center">
42+ <h1
43+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
44+ >
45+ Gordon
46+ </h1>
47+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm"
48+ >v0.0.1</span
49+ >
50+ </div>
51+ <!--(Navigation) -->
52+ <div id="menu-leftnav" class="w-full">
53+ <ul
54+ class="flex flex-col md:space-y-6 md:py-8 font-semibold text-gray-100 text-lg md:text-2xl md:pl-4"
55+ >
56+ <li class="flex items-center">
57+ <i class="iconoir-dashboard-speed mr-2 md:text-3xl"></i>
58+ <a href="index.html">Dashboard</a>
59+ </li>
60+ <li class="flex items-center">
61+ <i class="iconoir-server mr-2 md:text-3xl"></i>
62+ <a href="#manager">Manager</a>
63+ </li>
64+ <li class="flex items-center">
65+ <i class="iconoir-community mr-2 md:text-3xl"></i>
66+ <a href="#users">Users</a>
67+ </li>
68+ <li class="flex items-center">
69+ <i class="iconoir-database-settings mr-2 md:text-3xl"></i>
70+ <a href="#gordon-settings">Settings</a>
71+ </li>
72+ </ul>
73+ </div>
74+
75+ <div class="w-full h-24 bg-gordonmascot-mblue rounded-lg"></div>
76+ <!-- Mock menu item -->
77+ </div>
78+ </div>
79+
80+ <!-- Main Content including the navbar -->
81+ <div class="flex-1 flex flex-col md:pt-10 space-y-4 ml-4">
82+ <!-- Search Nav within the main content -->
83+ <div class="mb-4 flex justify-end">
84+ <div class="w-72 h-10 bg-gray-300 rounded-lg">
85+ <!-- Search input with iconir search -->
86+ <div class="flex justify-between items-center h-full px-2">
87+ <input
88+ type="text"
89+ class="w-full h-full bg-transparent outline-none"
90+ placeholder="Search"
91+ />
92+ <i class="iconoir-search"></i>
93+ </div>
94+ </div>
95+ <!-- Mock search or other element -->
96+ </div>
97+
98+ <!-- Cards section -->
99+ <div class="flex space-x-4 flex-grow">
100+ <!-- Main Card on the Left -->
101+ <div class="w-4/6 bg-white p-4 rounded-md shadow mb-4">
102+ <div class="w-full rounded-sm bg-gray-300"></div>
103+ <!-- Mock main card -->
104+ </div>
105+
106+ <!-- Two Cards on the Right -->
107+ <div class="w-2/6 flex flex-col flex-justify-start">
108+ <div class="bg-white p-4 rounded-md shadow mb-4">
109+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
110+ <!-- Mock card -->
111+ </div>
112+ <div class="bg-white p-4 rounded-md shadow mb-4">
113+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
114+ <!-- Mock card -->
115+ </div>
116+ <div class="bg-white p-4 rounded-md shadow mb-4">
117+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
118+ <!-- Mock card -->
119+ </div>
120+ </div>
121+ </div>
122+ </div>
123+ </body>
124+</html>
@@ -0,0 +1,124 @@
1+<!-- @format -->
2+
3+<!DOCTYPE html>
4+<html lang="en">
5+ <head>
6+ <meta charset="UTF-8" />
7+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+ <title>{{ .header.meta.title }}</title>
9+ <meta name="description" content="{{ .Header.Meta.Description }}" />
10+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
11+ <!-- Custom CSS + Tailwind -->
12+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
13+ <!-- Iconoir -->
14+ <link rel="stylesheet" href="/libs/iconoir.css" />
15+ <!-- Alpine -->
16+ <script src="/libs/alpine.min.js"></script>
17+ <!-- HTMX min js -->
18+ <script src="/libs/htmx.min.js"></script>
19+ <!-- HTMX SSE -->
20+ <script src="/libs/htmx-sse.js"></script>
21+ <!-- Custom JS from assets/js -->
22+ <script src="assets/js/custom.js"></script>
23+ </head>
24+ <body class="IBMPlexSans bg-zinc-200 md:p-8 flex">
25+ <!-- Left Menu -->
26+ <div class="w-1/5 flex flex-col space-evenly">
27+ <!-- Logo -->
28+ <div id="logo-mascot-leftnav" class="flex justify-center p-4">
29+ <div class="circle-shadow flex justify-center w-100">
30+ <img
31+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
32+ alt="logo"
33+ class="sm:h-24 h-32 xl:h-48"
34+ />
35+ </div>
36+ </div>
37+ <!-- Site Name + Version -->
38+ <div
39+ class="p-4 flex flex-col bg-gordonmascot-lblue rounded-lg shadow space-y-4"
40+ >
41+ <div class="w-full flex justify-center">
42+ <h1
43+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
44+ >
45+ Gordon
46+ </h1>
47+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm"
48+ >v0.0.1</span
49+ >
50+ </div>
51+ <!--(Navigation) -->
52+ <div id="menu-leftnav" class="w-full">
53+ <ul
54+ class="flex flex-col md:space-y-6 md:py-8 font-semibold text-gray-100 text-lg md:text-2xl md:pl-4"
55+ >
56+ <li class="flex items-center">
57+ <i class="iconoir-dashboard-speed mr-2 md:text-3xl"></i>
58+ <a href="index.html">Dashboard</a>
59+ </li>
60+ <li class="flex items-center">
61+ <i class="iconoir-server mr-2 md:text-3xl"></i>
62+ <a href="#manager">Manager</a>
63+ </li>
64+ <li class="flex items-center">
65+ <i class="iconoir-community mr-2 md:text-3xl"></i>
66+ <a href="#users">Users</a>
67+ </li>
68+ <li class="flex items-center">
69+ <i class="iconoir-database-settings mr-2 md:text-3xl"></i>
70+ <a href="#gordon-settings">Settings</a>
71+ </li>
72+ </ul>
73+ </div>
74+
75+ <div class="w-full h-24 bg-gordonmascot-mblue rounded-lg"></div>
76+ <!-- Mock menu item -->
77+ </div>
78+ </div>
79+
80+ <!-- Main Content including the navbar -->
81+ <div class="flex-1 flex flex-col md:pt-10 space-y-4 ml-4">
82+ <!-- Search Nav within the main content -->
83+ <div class="mb-4 flex justify-end">
84+ <div class="w-72 h-10 bg-gray-300 rounded-lg">
85+ <!-- Search input with iconir search -->
86+ <div class="flex justify-between items-center h-full px-2">
87+ <input
88+ type="text"
89+ class="w-full h-full bg-transparent outline-none"
90+ placeholder="Search"
91+ />
92+ <i class="iconoir-search"></i>
93+ </div>
94+ </div>
95+ <!-- Mock search or other element -->
96+ </div>
97+
98+ <!-- Cards section -->
99+ <div class="flex space-x-4 flex-grow">
100+ <!-- Main Card on the Left -->
101+ <div class="w-4/6 bg-white p-4 rounded-md shadow mb-4">
102+ <div class="w-full rounded-sm bg-gray-300"></div>
103+ <!-- Mock main card -->
104+ </div>
105+
106+ <!-- Two Cards on the Right -->
107+ <div class="w-2/6 flex flex-col flex-justify-start">
108+ <div class="bg-white p-4 rounded-md shadow mb-4">
109+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
110+ <!-- Mock card -->
111+ </div>
112+ <div class="bg-white p-4 rounded-md shadow mb-4">
113+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
114+ <!-- Mock card -->
115+ </div>
116+ <div class="bg-white p-4 rounded-md shadow mb-4">
117+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
118+ <!-- Mock card -->
119+ </div>
120+ </div>
121+ </div>
122+ </div>
123+ </body>
124+</html>
A internal/gotemplate/models/html/admin/install.gohtml +137 -0
@@ -0,0 +1,137 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>{{ .header.meta.title }}</title>
7+ <meta name="description" content="{{ .Header.Meta.Description }}" />
8+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
9+ <!-- Custom CSS + Tailwind -->
10+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
11+ <!-- Iconoir -->
12+ <link rel="stylesheet" href="/libs/iconoir.css" />
13+ <!-- Alpine -->
14+ <script src="/libs/alpine.min.js"></script>
15+ <!-- HTMX min js -->
16+ <script src="/libs/htmx.min.js"></script>
17+ <!-- HTMX SSE -->
18+ <script src="/libs/htmx-sse.js"></script>
19+ <!-- Custom JS from assets/js -->
20+ <script src="/assets/js/custom.js"></script>
21+ </head>
22+
23+ <body
24+ class="IBMPlexSans bg-zinc-200 md:p-8 flex flex-col items-center"
25+ hx-boost="true"
26+ >
27+ <!-- Logo and Title -->
28+ <div
29+ id="logo-mascot"
30+ class="flex flex-col justify-center items-center p-4 mb-4"
31+ >
32+ <div class="circle-shadow flex justify-center w-100">
33+ <img
34+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
35+ alt="logo"
36+ class="sm:h-24 h-32 xl:h-48"
37+ />
38+ </div>
39+ <div class="flex justify-center mt-4">
40+ <h1
41+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
42+ >
43+ Gordon
44+ </h1>
45+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm ml-2"
46+ >v0.0.1</span
47+ >
48+ </div>
49+ </div>
50+
51+ <!-- Main Content -->
52+ <div class="bg-white p-4 rounded-md shadow mb-4 w-2/3">
53+ <!-- Install Traefik -->
54+ <div id="install-traefik">
55+ <div class="flex flex-col items-center">
56+ <h2 class="text-2xl font-semibold text-gray-800">
57+ 1 - Install Traefik
58+ </h2>
59+ <!-- Dual view left : install procedure / right : SSE log installation -->
60+ <div class="flex flex-col md:flex-row justify-items-center w-full">
61+ <!-- Left -->
62+ <div class="w-full md:w-1/2 p-4">
63+ <form
64+ id="install-traefik-form"
65+ action="/admin/install/traefik"
66+ method="POST"
67+ hx-post="/admin/install/traefik"
68+ hx-swap="outerHTML"
69+ >
70+ <h2 class="">1.1 - Set your top domain name</h2>
71+ <input
72+ type="text"
73+ name="topdomain"
74+ id="topdomain"
75+ class="w-full py-2 px-4 my-2 border border-gray-300 rounded-md"
76+ placeholder="example.com"
77+ />
78+ <h2>1.2 - Set your admin email (a reachable one)</h2>
79+ <input
80+ type="text"
81+ name="adminemail"
82+ id="adminemail"
83+ class="w-full p-2 border border-gray-300 rounded-md"
84+ placeholder="admin@example.com"
85+ />
86+ <button
87+ type="submit"
88+ class="w-full p-2 bg-gordonmascot-hblue text-slate-100 rounded-md mt-4"
89+ >
90+ Save & Install Traefik
91+ </button>
92+ </form>
93+ </div>
94+ <!-- Right -->
95+ <div class="w-full md:w-1/2 p-4 text-slate-100">
96+ <div
97+ class="flex flex-col items-center bg-gordonmascot-hblue rounded-md"
98+ >
99+ <div class="w-full h-64 overflow-y-scroll-auto p-4">
100+ <div
101+ class="flex flex-col space-y-2"
102+ hx-ext="sse"
103+ sse-connect="/admin/install/traefik/sse"
104+ >
105+ <!-- One item -->
106+ <div class="flex flex-row items-center">
107+ <span class="">[INFO]</span>
108+ <span class="">Traefik installed</span>
109+ </div>
110+ <!-- One item -->
111+ <div class="flex flex-row items-center">
112+ <span class="">[INFO]</span>
113+ <span class="ml-2">Traefik started</span>
114+ </div>
115+ <!-- One item -->
116+ <div class="flex flex-row items-center">
117+ <span class="">[INFO]</span>
118+ <span class="ml-2"
119+ >Traefik configuration file created</span
120+ >
121+ </div>
122+ <!-- One item -->
123+ <div class="flex flex-row items-center">
124+ <span class="">[INFO]</span>
125+ <span class="">Traefik configuration file updated</span>
126+ </div>
127+ </div>
128+ </div>
129+ </div>
130+ </div>
131+ </div>
132+ </div>
133+ </div>
134+ <!-- End Install Traefik -->
135+ </div>
136+ </body>
137+</html>
@@ -0,0 +1,137 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>{{ .header.meta.title }}</title>
7+ <meta name="description" content="{{ .Header.Meta.Description }}" />
8+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
9+ <!-- Custom CSS + Tailwind -->
10+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
11+ <!-- Iconoir -->
12+ <link rel="stylesheet" href="/libs/iconoir.css" />
13+ <!-- Alpine -->
14+ <script src="/libs/alpine.min.js"></script>
15+ <!-- HTMX min js -->
16+ <script src="/libs/htmx.min.js"></script>
17+ <!-- HTMX SSE -->
18+ <script src="/libs/htmx-sse.js"></script>
19+ <!-- Custom JS from assets/js -->
20+ <script src="/assets/js/custom.js"></script>
21+ </head>
22+
23+ <body
24+ class="IBMPlexSans bg-zinc-200 md:p-8 flex flex-col items-center"
25+ hx-boost="true"
26+ >
27+ <!-- Logo and Title -->
28+ <div
29+ id="logo-mascot"
30+ class="flex flex-col justify-center items-center p-4 mb-4"
31+ >
32+ <div class="circle-shadow flex justify-center w-100">
33+ <img
34+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
35+ alt="logo"
36+ class="sm:h-24 h-32 xl:h-48"
37+ />
38+ </div>
39+ <div class="flex justify-center mt-4">
40+ <h1
41+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
42+ >
43+ Gordon
44+ </h1>
45+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm ml-2"
46+ >v0.0.1</span
47+ >
48+ </div>
49+ </div>
50+
51+ <!-- Main Content -->
52+ <div class="bg-white p-4 rounded-md shadow mb-4 w-2/3">
53+ <!-- Install Traefik -->
54+ <div id="install-traefik">
55+ <div class="flex flex-col items-center">
56+ <h2 class="text-2xl font-semibold text-gray-800">
57+ 1 - Install Traefik
58+ </h2>
59+ <!-- Dual view left : install procedure / right : SSE log installation -->
60+ <div class="flex flex-col md:flex-row justify-items-center w-full">
61+ <!-- Left -->
62+ <div class="w-full md:w-1/2 p-4">
63+ <form
64+ id="install-traefik-form"
65+ action="/admin/install/traefik"
66+ method="POST"
67+ hx-post="/admin/install/traefik"
68+ hx-swap="outerHTML"
69+ >
70+ <h2 class="">1.1 - Set your top domain name</h2>
71+ <input
72+ type="text"
73+ name="topdomain"
74+ id="topdomain"
75+ class="w-full py-2 px-4 my-2 border border-gray-300 rounded-md"
76+ placeholder="example.com"
77+ />
78+ <h2>1.2 - Set your admin email (a reachable one)</h2>
79+ <input
80+ type="text"
81+ name="adminemail"
82+ id="adminemail"
83+ class="w-full p-2 border border-gray-300 rounded-md"
84+ placeholder="admin@example.com"
85+ />
86+ <button
87+ type="submit"
88+ class="w-full p-2 bg-gordonmascot-hblue text-slate-100 rounded-md mt-4"
89+ >
90+ Save & Install Traefik
91+ </button>
92+ </form>
93+ </div>
94+ <!-- Right -->
95+ <div class="w-full md:w-1/2 p-4 text-slate-100">
96+ <div
97+ class="flex flex-col items-center bg-gordonmascot-hblue rounded-md"
98+ >
99+ <div class="w-full h-64 overflow-y-scroll-auto p-4">
100+ <div
101+ class="flex flex-col space-y-2"
102+ hx-ext="sse"
103+ sse-connect="/admin/install/traefik/sse"
104+ >
105+ <!-- One item -->
106+ <div class="flex flex-row items-center">
107+ <span class="">[INFO]</span>
108+ <span class="">Traefik installed</span>
109+ </div>
110+ <!-- One item -->
111+ <div class="flex flex-row items-center">
112+ <span class="">[INFO]</span>
113+ <span class="ml-2">Traefik started</span>
114+ </div>
115+ <!-- One item -->
116+ <div class="flex flex-row items-center">
117+ <span class="">[INFO]</span>
118+ <span class="ml-2"
119+ >Traefik configuration file created</span
120+ >
121+ </div>
122+ <!-- One item -->
123+ <div class="flex flex-row items-center">
124+ <span class="">[INFO]</span>
125+ <span class="">Traefik configuration file updated</span>
126+ </div>
127+ </div>
128+ </div>
129+ </div>
130+ </div>
131+ </div>
132+ </div>
133+ </div>
134+ <!-- End Install Traefik -->
135+ </div>
136+ </body>
137+</html>
A internal/gotemplate/models/html/admin/manager.gohtml +0 -0

no textual change.

A internal/gotemplate/models/html/admin/user.gohtml +0 -0

no textual change.

A internal/gotemplate/models/html/fragments/components.gohtml +33 -0
@@ -0,0 +1,33 @@
1+<!-- @format -->
2+
3+<div id="header">
4+ <h1
5+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
6+ >
7+ {{ .body.header.helloworld }}
8+ </h1>
9+</div>
10+
11+<div id="hello">
12+ <h1
13+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
14+ >
15+ {{ .body.div.hello }}
16+ </h1>
17+</div>
18+<div
19+ id="header"
20+ hx-get="/htmx"
21+ hx-headers='{"HX-Fragment": "header"}'
22+ hx-trigger="load"
23+ hx-swap="outerHTML"
24+></div>
25+
26+<!-- App Fragment -->
27+<div
28+ id="app"
29+ hx-get="/htmx"
30+ hx-headers='{"HX-Fragment": "hello"}'
31+ hx-trigger="load"
32+ hx-swap="outerHTML"
33+></div>
@@ -0,0 +1,33 @@
1+<!-- @format -->
2+
3+<div id="header">
4+ <h1
5+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
6+ >
7+ {{ .body.header.helloworld }}
8+ </h1>
9+</div>
10+
11+<div id="hello">
12+ <h1
13+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
14+ >
15+ {{ .body.div.hello }}
16+ </h1>
17+</div>
18+<div
19+ id="header"
20+ hx-get="/htmx"
21+ hx-headers='{"HX-Fragment": "header"}'
22+ hx-trigger="load"
23+ hx-swap="outerHTML"
24+></div>
25+
26+<!-- App Fragment -->
27+<div
28+ id="app"
29+ hx-get="/htmx"
30+ hx-headers='{"HX-Fragment": "hello"}'
31+ hx-trigger="load"
32+ hx-swap="outerHTML"
33+></div>
A internal/gotemplate/models/html/strings.yml +23 -0
@@ -0,0 +1,23 @@
1+en:
2+ header:
3+ meta:
4+ title: Gordon - Admin Dashboard
5+ description: Admin dashboard for Gordon
6+ keywords: gordon, admin, dashboard
7+ body:
8+ header:
9+ helloworld: Hello World!
10+ div:
11+ hello: Hello component loaded from a template!
12+
13+fr:
14+ header:
15+ meta:
16+ title: Gordon - Tableau de bord administrateur
17+ description: Tableau de bord administrateur pour Gordon
18+ keywords: gordon, admin, dashboard
19+ body:
20+ header:
21+ helloworld: Bonjour le monde!
22+ div:
23+ hello: Composant de salut chargé à partir d'un modèle!
@@ -0,0 +1,23 @@
1+en:
2+ header:
3+ meta:
4+ title: Gordon - Admin Dashboard
5+ description: Admin dashboard for Gordon
6+ keywords: gordon, admin, dashboard
7+ body:
8+ header:
9+ helloworld: Hello World!
10+ div:
11+ hello: Hello component loaded from a template!
12+
13+fr:
14+ header:
15+ meta:
16+ title: Gordon - Tableau de bord administrateur
17+ description: Tableau de bord administrateur pour Gordon
18+ keywords: gordon, admin, dashboard
19+ body:
20+ header:
21+ helloworld: Bonjour le monde!
22+ div:
23+ hello: Composant de salut chargé à partir d'un modèle!
A internal/gotemplate/models/txt/test.txt +0 -0

no textual change.

A internal/httpserve/handler/adminroutes.go +5 -0
@@ -0,0 +1,5 @@
1+package handlers
2+
3+import ()
4+
5+
@@ -0,0 +1,5 @@
1+package handlers
2+
3+import ()
4+
5+
A internal/httpserve/handler/htmx.go +0 -0

no textual change.

A internal/httpserve/handler/static.go +0 -0

no textual change.

A internal/httpserve/middleware/detectcolorscheme.go +0 -0

no textual change.

A internal/httpserve/middleware/detectlang.go +0 -0

no textual change.

A internal/httpserve/middleware/secure.go +0 -0

no textual change.

A internal/httpserve/middleware/tmp/build-errors.log +1 -0
@@ -0,0 +1,1 @@
1+exit status 1⏎̸
@@ -0,0 +1,1 @@
1+exit status 1⏎̸
A internal/httpserve/router.go +0 -0

no textual change.

A internal/webui/embed.go +14 -0
@@ -0,0 +1,14 @@
1+package webui
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding the public directory
10+//
11+//go:embed public/*
12+var public embed.FS
13+
14+var PublicFS = echo.MustSubFS(public, "internal/webui/public")
@@ -0,0 +1,14 @@
1+package webui
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding the public directory
10+//
11+//go:embed public/*
12+var public embed.FS
13+
14+var PublicFS = echo.MustSubFS(public, "internal/webui/public")
A internal/webui/public/404.gohtml +12 -0
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 404</title>
7+ </head>
8+ <body>
9+ <h1>Error 404</h1>
10+ <p>Page not found</p>
11+ </body>
12+</html>
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 404</title>
7+ </head>
8+ <body>
9+ <h1>Error 404</h1>
10+ <p>Page not found</p>
11+ </body>
12+</html>
A internal/webui/public/500.gohtml +12 -0
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 500</title>
7+ </head>
8+ <body>
9+ <h1>500 Internal Server Error</h1>
10+ <p>Something went really wrong o/</p>
11+ </body>
12+</html>
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 500</title>
7+ </head>
8+ <body>
9+ <h1>500 Internal Server Error</h1>
10+ <p>Something went really wrong o/</p>
11+ </body>
12+</html>
A internal/webui/public/android-chrome-192x192.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/android-chrome-512x512.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/apple-touch-icon.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/css/custom.css +116 -0
@@ -0,0 +1,116 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+@tailwind base;
10+@tailwind components;
11+@tailwind utilities;
12+
13+/* Import IBM Plex Fonts */
14+@font-face {
15+ font-family: "IBMPlexSans-Bold";
16+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
17+ font-weight: bold;
18+ font-style: normal;
19+}
20+
21+@font-face {
22+ font-family: "IBMPlexSans-Regular";
23+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
24+ font-weight: normal;
25+ font-style: normal;
26+}
27+
28+/* Import Jetbrains Mono Nerd Font */
29+@font-face {
30+ font-family: "JetBrainsMono-Nerd-Font-Regular";
31+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
32+ format("woff2");
33+ font-weight: normal;
34+ font-style: normal;
35+}
36+
37+@font-face {
38+ font-family: "LilitaOne-Regular";
39+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
40+ font-weight: normal;
41+ font-style: normal;
42+}
43+
44+.fade-me-out.htmx-swapping {
45+ opacity: 0;
46+ transition: opacity 1s ease-out;
47+}
48+
49+/* View transition */
50+@keyframes fade-in {
51+ from {
52+ opacity: 0;
53+ }
54+}
55+
56+@keyframes fade-out {
57+ to {
58+ opacity: 0;
59+ }
60+}
61+
62+@keyframes slide-from-right {
63+ from {
64+ transform: translateX(90px);
65+ }
66+}
67+
68+@keyframes slide-to-left {
69+ to {
70+ transform: translateX(-90px);
71+ }
72+}
73+
74+.slide-it {
75+ view-transition-name: slide-it;
76+}
77+
78+::view-transition-old(slide-it) {
79+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
80+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
81+}
82+::view-transition-new(slide-it) {
83+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
84+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
85+}
86+
87+.gordon-title {
88+ font-family: "LilitaOne-Regular", sans-serif;
89+
90+}
91+
92+.IBMPlexSans {
93+ font-family: "IBMPlexSans-Regular", sans-serif;
94+}
95+
96+.circle-shadow {
97+ width: 100%;
98+ position: relative;
99+}
100+
101+.circle-shadow::after {
102+ position: absolute;
103+ width: 50%;
104+ height: 0.4rem;
105+ margin: auto;
106+ background: rgba(0, 0, 0, 0.1);
107+ border-radius: 50%;
108+ z-index: -1;
109+ bottom: 2%;
110+ content: "";
111+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
112+}
113+
114+.iconoir {
115+ margin-right: 8px;
116+}
@@ -0,0 +1,116 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+@tailwind base;
10+@tailwind components;
11+@tailwind utilities;
12+
13+/* Import IBM Plex Fonts */
14+@font-face {
15+ font-family: "IBMPlexSans-Bold";
16+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
17+ font-weight: bold;
18+ font-style: normal;
19+}
20+
21+@font-face {
22+ font-family: "IBMPlexSans-Regular";
23+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
24+ font-weight: normal;
25+ font-style: normal;
26+}
27+
28+/* Import Jetbrains Mono Nerd Font */
29+@font-face {
30+ font-family: "JetBrainsMono-Nerd-Font-Regular";
31+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
32+ format("woff2");
33+ font-weight: normal;
34+ font-style: normal;
35+}
36+
37+@font-face {
38+ font-family: "LilitaOne-Regular";
39+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
40+ font-weight: normal;
41+ font-style: normal;
42+}
43+
44+.fade-me-out.htmx-swapping {
45+ opacity: 0;
46+ transition: opacity 1s ease-out;
47+}
48+
49+/* View transition */
50+@keyframes fade-in {
51+ from {
52+ opacity: 0;
53+ }
54+}
55+
56+@keyframes fade-out {
57+ to {
58+ opacity: 0;
59+ }
60+}
61+
62+@keyframes slide-from-right {
63+ from {
64+ transform: translateX(90px);
65+ }
66+}
67+
68+@keyframes slide-to-left {
69+ to {
70+ transform: translateX(-90px);
71+ }
72+}
73+
74+.slide-it {
75+ view-transition-name: slide-it;
76+}
77+
78+::view-transition-old(slide-it) {
79+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
80+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
81+}
82+::view-transition-new(slide-it) {
83+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
84+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
85+}
86+
87+.gordon-title {
88+ font-family: "LilitaOne-Regular", sans-serif;
89+
90+}
91+
92+.IBMPlexSans {
93+ font-family: "IBMPlexSans-Regular", sans-serif;
94+}
95+
96+.circle-shadow {
97+ width: 100%;
98+ position: relative;
99+}
100+
101+.circle-shadow::after {
102+ position: absolute;
103+ width: 50%;
104+ height: 0.4rem;
105+ margin: auto;
106+ background: rgba(0, 0, 0, 0.1);
107+ border-radius: 50%;
108+ z-index: -1;
109+ bottom: 2%;
110+ content: "";
111+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
112+}
113+
114+.iconoir {
115+ margin-right: 8px;
116+}
A internal/webui/public/assets/css/tailwind.css +1046 -0
@@ -0,0 +1,1046 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
10+ */
11+
12+/*
13+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
14+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
15+*/
16+
17+*,
18+::before,
19+::after {
20+ box-sizing: border-box;
21+ /* 1 */
22+ border-width: 0;
23+ /* 2 */
24+ border-style: solid;
25+ /* 2 */
26+ border-color: #e5e7eb;
27+ /* 2 */
28+}
29+
30+::before,
31+::after {
32+ --tw-content: '';
33+}
34+
35+/*
36+1. Use a consistent sensible line-height in all browsers.
37+2. Prevent adjustments of font size after orientation changes in iOS.
38+3. Use a more readable tab size.
39+4. Use the user's configured `sans` font-family by default.
40+5. Use the user's configured `sans` font-feature-settings by default.
41+6. Use the user's configured `sans` font-variation-settings by default.
42+*/
43+
44+html {
45+ line-height: 1.5;
46+ /* 1 */
47+ -webkit-text-size-adjust: 100%;
48+ /* 2 */
49+ -moz-tab-size: 4;
50+ /* 3 */
51+ -o-tab-size: 4;
52+ tab-size: 4;
53+ /* 3 */
54+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
55+ /* 4 */
56+ font-feature-settings: normal;
57+ /* 5 */
58+ font-variation-settings: normal;
59+ /* 6 */
60+}
61+
62+/*
63+1. Remove the margin in all browsers.
64+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
65+*/
66+
67+body {
68+ margin: 0;
69+ /* 1 */
70+ line-height: inherit;
71+ /* 2 */
72+}
73+
74+/*
75+1. Add the correct height in Firefox.
76+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
77+3. Ensure horizontal rules are visible by default.
78+*/
79+
80+hr {
81+ height: 0;
82+ /* 1 */
83+ color: inherit;
84+ /* 2 */
85+ border-top-width: 1px;
86+ /* 3 */
87+}
88+
89+/*
90+Add the correct text decoration in Chrome, Edge, and Safari.
91+*/
92+
93+abbr:where([title]) {
94+ -webkit-text-decoration: underline dotted;
95+ text-decoration: underline dotted;
96+}
97+
98+/*
99+Remove the default font size and weight for headings.
100+*/
101+
102+h1,
103+h2,
104+h3,
105+h4,
106+h5,
107+h6 {
108+ font-size: inherit;
109+ font-weight: inherit;
110+}
111+
112+/*
113+Reset links to optimize for opt-in styling instead of opt-out.
114+*/
115+
116+a {
117+ color: inherit;
118+ text-decoration: inherit;
119+}
120+
121+/*
122+Add the correct font weight in Edge and Safari.
123+*/
124+
125+b,
126+strong {
127+ font-weight: bolder;
128+}
129+
130+/*
131+1. Use the user's configured `mono` font family by default.
132+2. Correct the odd `em` font sizing in all browsers.
133+*/
134+
135+code,
136+kbd,
137+samp,
138+pre {
139+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
140+ /* 1 */
141+ font-size: 1em;
142+ /* 2 */
143+}
144+
145+/*
146+Add the correct font size in all browsers.
147+*/
148+
149+small {
150+ font-size: 80%;
151+}
152+
153+/*
154+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
155+*/
156+
157+sub,
158+sup {
159+ font-size: 75%;
160+ line-height: 0;
161+ position: relative;
162+ vertical-align: baseline;
163+}
164+
165+sub {
166+ bottom: -0.25em;
167+}
168+
169+sup {
170+ top: -0.5em;
171+}
172+
173+/*
174+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
175+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
176+3. Remove gaps between table borders by default.
177+*/
178+
179+table {
180+ text-indent: 0;
181+ /* 1 */
182+ border-color: inherit;
183+ /* 2 */
184+ border-collapse: collapse;
185+ /* 3 */
186+}
187+
188+/*
189+1. Change the font styles in all browsers.
190+2. Remove the margin in Firefox and Safari.
191+3. Remove default padding in all browsers.
192+*/
193+
194+button,
195+input,
196+optgroup,
197+select,
198+textarea {
199+ font-family: inherit;
200+ /* 1 */
201+ font-feature-settings: inherit;
202+ /* 1 */
203+ font-variation-settings: inherit;
204+ /* 1 */
205+ font-size: 100%;
206+ /* 1 */
207+ font-weight: inherit;
208+ /* 1 */
209+ line-height: inherit;
210+ /* 1 */
211+ color: inherit;
212+ /* 1 */
213+ margin: 0;
214+ /* 2 */
215+ padding: 0;
216+ /* 3 */
217+}
218+
219+/*
220+Remove the inheritance of text transform in Edge and Firefox.
221+*/
222+
223+button,
224+select {
225+ text-transform: none;
226+}
227+
228+/*
229+1. Correct the inability to style clickable types in iOS and Safari.
230+2. Remove default button styles.
231+*/
232+
233+button,
234+[type='button'],
235+[type='reset'],
236+[type='submit'] {
237+ -webkit-appearance: button;
238+ /* 1 */
239+ background-color: transparent;
240+ /* 2 */
241+ background-image: none;
242+ /* 2 */
243+}
244+
245+/*
246+Use the modern Firefox focus style for all focusable elements.
247+*/
248+
249+:-moz-focusring {
250+ outline: auto;
251+}
252+
253+/*
254+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
255+*/
256+
257+:-moz-ui-invalid {
258+ box-shadow: none;
259+}
260+
261+/*
262+Add the correct vertical alignment in Chrome and Firefox.
263+*/
264+
265+progress {
266+ vertical-align: baseline;
267+}
268+
269+/*
270+Correct the cursor style of increment and decrement buttons in Safari.
271+*/
272+
273+::-webkit-inner-spin-button,
274+::-webkit-outer-spin-button {
275+ height: auto;
276+}
277+
278+/*
279+1. Correct the odd appearance in Chrome and Safari.
280+2. Correct the outline style in Safari.
281+*/
282+
283+[type='search'] {
284+ -webkit-appearance: textfield;
285+ /* 1 */
286+ outline-offset: -2px;
287+ /* 2 */
288+}
289+
290+/*
291+Remove the inner padding in Chrome and Safari on macOS.
292+*/
293+
294+::-webkit-search-decoration {
295+ -webkit-appearance: none;
296+}
297+
298+/*
299+1. Correct the inability to style clickable types in iOS and Safari.
300+2. Change font properties to `inherit` in Safari.
301+*/
302+
303+::-webkit-file-upload-button {
304+ -webkit-appearance: button;
305+ /* 1 */
306+ font: inherit;
307+ /* 2 */
308+}
309+
310+/*
311+Add the correct display in Chrome and Safari.
312+*/
313+
314+summary {
315+ display: list-item;
316+}
317+
318+/*
319+Removes the default spacing and border for appropriate elements.
320+*/
321+
322+blockquote,
323+dl,
324+dd,
325+h1,
326+h2,
327+h3,
328+h4,
329+h5,
330+h6,
331+hr,
332+figure,
333+p,
334+pre {
335+ margin: 0;
336+}
337+
338+fieldset {
339+ margin: 0;
340+ padding: 0;
341+}
342+
343+legend {
344+ padding: 0;
345+}
346+
347+ol,
348+ul,
349+menu {
350+ list-style: none;
351+ margin: 0;
352+ padding: 0;
353+}
354+
355+/*
356+Reset default styling for dialogs.
357+*/
358+
359+dialog {
360+ padding: 0;
361+}
362+
363+/*
364+Prevent resizing textareas horizontally by default.
365+*/
366+
367+textarea {
368+ resize: vertical;
369+}
370+
371+/*
372+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
373+2. Set the default placeholder color to the user's configured gray 400 color.
374+*/
375+
376+input::-moz-placeholder, textarea::-moz-placeholder {
377+ opacity: 1;
378+ /* 1 */
379+ color: #9ca3af;
380+ /* 2 */
381+}
382+
383+input::placeholder,
384+textarea::placeholder {
385+ opacity: 1;
386+ /* 1 */
387+ color: #9ca3af;
388+ /* 2 */
389+}
390+
391+/*
392+Set the default cursor for buttons.
393+*/
394+
395+button,
396+[role="button"] {
397+ cursor: pointer;
398+}
399+
400+/*
401+Make sure disabled buttons don't get the pointer cursor.
402+*/
403+
404+:disabled {
405+ cursor: default;
406+}
407+
408+/*
409+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
410+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
411+ This can trigger a poorly considered lint error in some tools but is included by design.
412+*/
413+
414+img,
415+svg,
416+video,
417+canvas,
418+audio,
419+iframe,
420+embed,
421+object {
422+ display: block;
423+ /* 1 */
424+ vertical-align: middle;
425+ /* 2 */
426+}
427+
428+/*
429+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
430+*/
431+
432+img,
433+video {
434+ max-width: 100%;
435+ height: auto;
436+}
437+
438+/* Make elements with the HTML hidden attribute stay hidden by default */
439+
440+[hidden] {
441+ display: none;
442+}
443+
444+*, ::before, ::after {
445+ --tw-border-spacing-x: 0;
446+ --tw-border-spacing-y: 0;
447+ --tw-translate-x: 0;
448+ --tw-translate-y: 0;
449+ --tw-rotate: 0;
450+ --tw-skew-x: 0;
451+ --tw-skew-y: 0;
452+ --tw-scale-x: 1;
453+ --tw-scale-y: 1;
454+ --tw-pan-x: ;
455+ --tw-pan-y: ;
456+ --tw-pinch-zoom: ;
457+ --tw-scroll-snap-strictness: proximity;
458+ --tw-gradient-from-position: ;
459+ --tw-gradient-via-position: ;
460+ --tw-gradient-to-position: ;
461+ --tw-ordinal: ;
462+ --tw-slashed-zero: ;
463+ --tw-numeric-figure: ;
464+ --tw-numeric-spacing: ;
465+ --tw-numeric-fraction: ;
466+ --tw-ring-inset: ;
467+ --tw-ring-offset-width: 0px;
468+ --tw-ring-offset-color: #fff;
469+ --tw-ring-color: rgb(59 130 246 / 0.5);
470+ --tw-ring-offset-shadow: 0 0 #0000;
471+ --tw-ring-shadow: 0 0 #0000;
472+ --tw-shadow: 0 0 #0000;
473+ --tw-shadow-colored: 0 0 #0000;
474+ --tw-blur: ;
475+ --tw-brightness: ;
476+ --tw-contrast: ;
477+ --tw-grayscale: ;
478+ --tw-hue-rotate: ;
479+ --tw-invert: ;
480+ --tw-saturate: ;
481+ --tw-sepia: ;
482+ --tw-drop-shadow: ;
483+ --tw-backdrop-blur: ;
484+ --tw-backdrop-brightness: ;
485+ --tw-backdrop-contrast: ;
486+ --tw-backdrop-grayscale: ;
487+ --tw-backdrop-hue-rotate: ;
488+ --tw-backdrop-invert: ;
489+ --tw-backdrop-opacity: ;
490+ --tw-backdrop-saturate: ;
491+ --tw-backdrop-sepia: ;
492+}
493+
494+::backdrop {
495+ --tw-border-spacing-x: 0;
496+ --tw-border-spacing-y: 0;
497+ --tw-translate-x: 0;
498+ --tw-translate-y: 0;
499+ --tw-rotate: 0;
500+ --tw-skew-x: 0;
501+ --tw-skew-y: 0;
502+ --tw-scale-x: 1;
503+ --tw-scale-y: 1;
504+ --tw-pan-x: ;
505+ --tw-pan-y: ;
506+ --tw-pinch-zoom: ;
507+ --tw-scroll-snap-strictness: proximity;
508+ --tw-gradient-from-position: ;
509+ --tw-gradient-via-position: ;
510+ --tw-gradient-to-position: ;
511+ --tw-ordinal: ;
512+ --tw-slashed-zero: ;
513+ --tw-numeric-figure: ;
514+ --tw-numeric-spacing: ;
515+ --tw-numeric-fraction: ;
516+ --tw-ring-inset: ;
517+ --tw-ring-offset-width: 0px;
518+ --tw-ring-offset-color: #fff;
519+ --tw-ring-color: rgb(59 130 246 / 0.5);
520+ --tw-ring-offset-shadow: 0 0 #0000;
521+ --tw-ring-shadow: 0 0 #0000;
522+ --tw-shadow: 0 0 #0000;
523+ --tw-shadow-colored: 0 0 #0000;
524+ --tw-blur: ;
525+ --tw-brightness: ;
526+ --tw-contrast: ;
527+ --tw-grayscale: ;
528+ --tw-hue-rotate: ;
529+ --tw-invert: ;
530+ --tw-saturate: ;
531+ --tw-sepia: ;
532+ --tw-drop-shadow: ;
533+ --tw-backdrop-blur: ;
534+ --tw-backdrop-brightness: ;
535+ --tw-backdrop-contrast: ;
536+ --tw-backdrop-grayscale: ;
537+ --tw-backdrop-hue-rotate: ;
538+ --tw-backdrop-invert: ;
539+ --tw-backdrop-opacity: ;
540+ --tw-backdrop-saturate: ;
541+ --tw-backdrop-sepia: ;
542+}
543+
544+.my-2 {
545+ margin-top: 0.5rem;
546+ margin-bottom: 0.5rem;
547+}
548+
549+.mb-4 {
550+ margin-bottom: 1rem;
551+}
552+
553+.ml-2 {
554+ margin-left: 0.5rem;
555+}
556+
557+.ml-4 {
558+ margin-left: 1rem;
559+}
560+
561+.mr-2 {
562+ margin-right: 0.5rem;
563+}
564+
565+.mt-4 {
566+ margin-top: 1rem;
567+}
568+
569+.flex {
570+ display: flex;
571+}
572+
573+.h-10 {
574+ height: 2.5rem;
575+}
576+
577+.h-24 {
578+ height: 6rem;
579+}
580+
581+.h-32 {
582+ height: 8rem;
583+}
584+
585+.h-44 {
586+ height: 11rem;
587+}
588+
589+.h-64 {
590+ height: 16rem;
591+}
592+
593+.h-full {
594+ height: 100%;
595+}
596+
597+.w-1\/5 {
598+ width: 20%;
599+}
600+
601+.w-2\/6 {
602+ width: 33.333333%;
603+}
604+
605+.w-4\/6 {
606+ width: 66.666667%;
607+}
608+
609+.w-72 {
610+ width: 18rem;
611+}
612+
613+.w-full {
614+ width: 100%;
615+}
616+
617+.w-2\/3 {
618+ width: 66.666667%;
619+}
620+
621+.w-screen {
622+ width: 100vw;
623+}
624+
625+.w-96 {
626+ width: 24rem;
627+}
628+
629+.flex-1 {
630+ flex: 1 1 0%;
631+}
632+
633+.flex-grow {
634+ flex-grow: 1;
635+}
636+
637+.flex-row {
638+ flex-direction: row;
639+}
640+
641+.flex-col {
642+ flex-direction: column;
643+}
644+
645+.items-center {
646+ align-items: center;
647+}
648+
649+.justify-end {
650+ justify-content: flex-end;
651+}
652+
653+.justify-center {
654+ justify-content: center;
655+}
656+
657+.justify-between {
658+ justify-content: space-between;
659+}
660+
661+.justify-items-center {
662+ justify-items: center;
663+}
664+
665+.space-x-4 > :not([hidden]) ~ :not([hidden]) {
666+ --tw-space-x-reverse: 0;
667+ margin-right: calc(1rem * var(--tw-space-x-reverse));
668+ margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
669+}
670+
671+.space-y-2 > :not([hidden]) ~ :not([hidden]) {
672+ --tw-space-y-reverse: 0;
673+ margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
674+ margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
675+}
676+
677+.space-y-4 > :not([hidden]) ~ :not([hidden]) {
678+ --tw-space-y-reverse: 0;
679+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
680+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
681+}
682+
683+.space-x-3 > :not([hidden]) ~ :not([hidden]) {
684+ --tw-space-x-reverse: 0;
685+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
686+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
687+}
688+
689+.space-y-3 > :not([hidden]) ~ :not([hidden]) {
690+ --tw-space-y-reverse: 0;
691+ margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
692+ margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
693+}
694+
695+.overflow-y-scroll {
696+ overflow-y: scroll;
697+}
698+
699+.rounded-lg {
700+ border-radius: 0.5rem;
701+}
702+
703+.rounded-md {
704+ border-radius: 0.375rem;
705+}
706+
707+.rounded-sm {
708+ border-radius: 0.125rem;
709+}
710+
711+.border {
712+ border-width: 1px;
713+}
714+
715+.border-gray-300 {
716+ --tw-border-opacity: 1;
717+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
718+}
719+
720+.bg-gordonmascot-lblue {
721+ --tw-bg-opacity: 1;
722+ background-color: rgb(0 123 192 / var(--tw-bg-opacity));
723+}
724+
725+.bg-gordonmascot-mblue {
726+ --tw-bg-opacity: 1;
727+ background-color: rgb(0 82 147 / var(--tw-bg-opacity));
728+}
729+
730+.bg-gray-300 {
731+ --tw-bg-opacity: 1;
732+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
733+}
734+
735+.bg-transparent {
736+ background-color: transparent;
737+}
738+
739+.bg-white {
740+ --tw-bg-opacity: 1;
741+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
742+}
743+
744+.bg-zinc-200 {
745+ --tw-bg-opacity: 1;
746+ background-color: rgb(228 228 231 / var(--tw-bg-opacity));
747+}
748+
749+.bg-gordonmascot-hblue {
750+ --tw-bg-opacity: 1;
751+ background-color: rgb(1 30 92 / var(--tw-bg-opacity));
752+}
753+
754+.bg-zinc-400 {
755+ --tw-bg-opacity: 1;
756+ background-color: rgb(161 161 170 / var(--tw-bg-opacity));
757+}
758+
759+.p-4 {
760+ padding: 1rem;
761+}
762+
763+.p-2 {
764+ padding: 0.5rem;
765+}
766+
767+.px-2 {
768+ padding-left: 0.5rem;
769+ padding-right: 0.5rem;
770+}
771+
772+.px-6 {
773+ padding-left: 1.5rem;
774+ padding-right: 1.5rem;
775+}
776+
777+.py-2 {
778+ padding-top: 0.5rem;
779+ padding-bottom: 0.5rem;
780+}
781+
782+.px-4 {
783+ padding-left: 1rem;
784+ padding-right: 1rem;
785+}
786+
787+.text-2xl {
788+ font-size: 1.5rem;
789+ line-height: 2rem;
790+}
791+
792+.text-5xl {
793+ font-size: 3rem;
794+ line-height: 1;
795+}
796+
797+.text-lg {
798+ font-size: 1.125rem;
799+ line-height: 1.75rem;
800+}
801+
802+.text-sm {
803+ font-size: 0.875rem;
804+ line-height: 1.25rem;
805+}
806+
807+.text-xl {
808+ font-size: 1.25rem;
809+ line-height: 1.75rem;
810+}
811+
812+.font-semibold {
813+ font-weight: 600;
814+}
815+
816+.tracking-tighter {
817+ letter-spacing: -0.05em;
818+}
819+
820+.text-gordonmascot-hblue {
821+ --tw-text-opacity: 1;
822+ color: rgb(1 30 92 / var(--tw-text-opacity));
823+}
824+
825+.text-gordonmascot-mblue {
826+ --tw-text-opacity: 1;
827+ color: rgb(0 82 147 / var(--tw-text-opacity));
828+}
829+
830+.text-gray-100 {
831+ --tw-text-opacity: 1;
832+ color: rgb(243 244 246 / var(--tw-text-opacity));
833+}
834+
835+.text-gray-800 {
836+ --tw-text-opacity: 1;
837+ color: rgb(31 41 55 / var(--tw-text-opacity));
838+}
839+
840+.text-slate-400 {
841+ --tw-text-opacity: 1;
842+ color: rgb(148 163 184 / var(--tw-text-opacity));
843+}
844+
845+.text-slate-100 {
846+ --tw-text-opacity: 1;
847+ color: rgb(241 245 249 / var(--tw-text-opacity));
848+}
849+
850+.shadow {
851+ --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
852+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
853+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
854+}
855+
856+.outline-none {
857+ outline: 2px solid transparent;
858+ outline-offset: 2px;
859+}
860+
861+/* Import IBM Plex Fonts */
862+
863+@font-face {
864+ font-family: "IBMPlexSans-Bold";
865+
866+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
867+
868+ font-weight: bold;
869+
870+ font-style: normal;
871+}
872+
873+@font-face {
874+ font-family: "IBMPlexSans-Regular";
875+
876+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
877+
878+ font-weight: normal;
879+
880+ font-style: normal;
881+}
882+
883+/* Import Jetbrains Mono Nerd Font */
884+
885+@font-face {
886+ font-family: "JetBrainsMono-Nerd-Font-Regular";
887+
888+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
889+ format("woff2");
890+
891+ font-weight: normal;
892+
893+ font-style: normal;
894+}
895+
896+@font-face {
897+ font-family: "LilitaOne-Regular";
898+
899+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
900+
901+ font-weight: normal;
902+
903+ font-style: normal;
904+}
905+
906+.fade-me-out.htmx-swapping {
907+ opacity: 0;
908+ transition: opacity 1s ease-out;
909+}
910+
911+/* View transition */
912+
913+@keyframes fade-in {
914+ from {
915+ opacity: 0;
916+ }
917+}
918+
919+@keyframes fade-out {
920+ to {
921+ opacity: 0;
922+ }
923+}
924+
925+@keyframes slide-from-right {
926+ from {
927+ transform: translateX(90px);
928+ }
929+}
930+
931+@keyframes slide-to-left {
932+ to {
933+ transform: translateX(-90px);
934+ }
935+}
936+
937+.slide-it {
938+ view-transition-name: slide-it;
939+}
940+
941+::view-transition-old(slide-it) {
942+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
943+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
944+}
945+
946+::view-transition-new(slide-it) {
947+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
948+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
949+}
950+
951+.gordon-title {
952+ font-family: "LilitaOne-Regular", sans-serif;
953+}
954+
955+.IBMPlexSans {
956+ font-family: "IBMPlexSans-Regular", sans-serif;
957+}
958+
959+.circle-shadow {
960+ width: 100%;
961+ position: relative;
962+}
963+
964+.circle-shadow::after {
965+ position: absolute;
966+ width: 50%;
967+ height: 0.4rem;
968+ margin: auto;
969+ background: rgba(0, 0, 0, 0.1);
970+ border-radius: 50%;
971+ z-index: -1;
972+ bottom: 2%;
973+ content: "";
974+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
975+}
976+
977+.iconoir {
978+ margin-right: 8px;
979+}
980+
981+@media (min-width: 640px) {
982+ .sm\:h-24 {
983+ height: 6rem;
984+ }
985+}
986+
987+@media (min-width: 768px) {
988+ .md\:w-1\/2 {
989+ width: 50%;
990+ }
991+
992+ .md\:flex-row {
993+ flex-direction: row;
994+ }
995+
996+ .md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
997+ --tw-space-y-reverse: 0;
998+ margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
999+ margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
1000+ }
1001+
1002+ .md\:p-8 {
1003+ padding: 2rem;
1004+ }
1005+
1006+ .md\:py-8 {
1007+ padding-top: 2rem;
1008+ padding-bottom: 2rem;
1009+ }
1010+
1011+ .md\:pl-4 {
1012+ padding-left: 1rem;
1013+ }
1014+
1015+ .md\:pt-10 {
1016+ padding-top: 2.5rem;
1017+ }
1018+
1019+ .md\:text-2xl {
1020+ font-size: 1.5rem;
1021+ line-height: 2rem;
1022+ }
1023+
1024+ .md\:text-3xl {
1025+ font-size: 1.875rem;
1026+ line-height: 2.25rem;
1027+ }
1028+}
1029+
1030+@media (min-width: 1024px) {
1031+ .lg\:text-4xl {
1032+ font-size: 2.25rem;
1033+ line-height: 2.5rem;
1034+ }
1035+}
1036+
1037+@media (min-width: 1280px) {
1038+ .xl\:h-48 {
1039+ height: 12rem;
1040+ }
1041+
1042+ .xl\:text-5xl {
1043+ font-size: 3rem;
1044+ line-height: 1;
1045+ }
1046+}
@@ -0,0 +1,1046 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
10+ */
11+
12+/*
13+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
14+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
15+*/
16+
17+*,
18+::before,
19+::after {
20+ box-sizing: border-box;
21+ /* 1 */
22+ border-width: 0;
23+ /* 2 */
24+ border-style: solid;
25+ /* 2 */
26+ border-color: #e5e7eb;
27+ /* 2 */
28+}
29+
30+::before,
31+::after {
32+ --tw-content: '';
33+}
34+
35+/*
36+1. Use a consistent sensible line-height in all browsers.
37+2. Prevent adjustments of font size after orientation changes in iOS.
38+3. Use a more readable tab size.
39+4. Use the user's configured `sans` font-family by default.
40+5. Use the user's configured `sans` font-feature-settings by default.
41+6. Use the user's configured `sans` font-variation-settings by default.
42+*/
43+
44+html {
45+ line-height: 1.5;
46+ /* 1 */
47+ -webkit-text-size-adjust: 100%;
48+ /* 2 */
49+ -moz-tab-size: 4;
50+ /* 3 */
51+ -o-tab-size: 4;
52+ tab-size: 4;
53+ /* 3 */
54+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
55+ /* 4 */
56+ font-feature-settings: normal;
57+ /* 5 */
58+ font-variation-settings: normal;
59+ /* 6 */
60+}
61+
62+/*
63+1. Remove the margin in all browsers.
64+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
65+*/
66+
67+body {
68+ margin: 0;
69+ /* 1 */
70+ line-height: inherit;
71+ /* 2 */
72+}
73+
74+/*
75+1. Add the correct height in Firefox.
76+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
77+3. Ensure horizontal rules are visible by default.
78+*/
79+
80+hr {
81+ height: 0;
82+ /* 1 */
83+ color: inherit;
84+ /* 2 */
85+ border-top-width: 1px;
86+ /* 3 */
87+}
88+
89+/*
90+Add the correct text decoration in Chrome, Edge, and Safari.
91+*/
92+
93+abbr:where([title]) {
94+ -webkit-text-decoration: underline dotted;
95+ text-decoration: underline dotted;
96+}
97+
98+/*
99+Remove the default font size and weight for headings.
100+*/
101+
102+h1,
103+h2,
104+h3,
105+h4,
106+h5,
107+h6 {
108+ font-size: inherit;
109+ font-weight: inherit;
110+}
111+
112+/*
113+Reset links to optimize for opt-in styling instead of opt-out.
114+*/
115+
116+a {
117+ color: inherit;
118+ text-decoration: inherit;
119+}
120+
121+/*
122+Add the correct font weight in Edge and Safari.
123+*/
124+
125+b,
126+strong {
127+ font-weight: bolder;
128+}
129+
130+/*
131+1. Use the user's configured `mono` font family by default.
132+2. Correct the odd `em` font sizing in all browsers.
133+*/
134+
135+code,
136+kbd,
137+samp,
138+pre {
139+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
140+ /* 1 */
141+ font-size: 1em;
142+ /* 2 */
143+}
144+
145+/*
146+Add the correct font size in all browsers.
147+*/
148+
149+small {
150+ font-size: 80%;
151+}
152+
153+/*
154+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
155+*/
156+
157+sub,
158+sup {
159+ font-size: 75%;
160+ line-height: 0;
161+ position: relative;
162+ vertical-align: baseline;
163+}
164+
165+sub {
166+ bottom: -0.25em;
167+}
168+
169+sup {
170+ top: -0.5em;
171+}
172+
173+/*
174+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
175+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
176+3. Remove gaps between table borders by default.
177+*/
178+
179+table {
180+ text-indent: 0;
181+ /* 1 */
182+ border-color: inherit;
183+ /* 2 */
184+ border-collapse: collapse;
185+ /* 3 */
186+}
187+
188+/*
189+1. Change the font styles in all browsers.
190+2. Remove the margin in Firefox and Safari.
191+3. Remove default padding in all browsers.
192+*/
193+
194+button,
195+input,
196+optgroup,
197+select,
198+textarea {
199+ font-family: inherit;
200+ /* 1 */
201+ font-feature-settings: inherit;
202+ /* 1 */
203+ font-variation-settings: inherit;
204+ /* 1 */
205+ font-size: 100%;
206+ /* 1 */
207+ font-weight: inherit;
208+ /* 1 */
209+ line-height: inherit;
210+ /* 1 */
211+ color: inherit;
212+ /* 1 */
213+ margin: 0;
214+ /* 2 */
215+ padding: 0;
216+ /* 3 */
217+}
218+
219+/*
220+Remove the inheritance of text transform in Edge and Firefox.
221+*/
222+
223+button,
224+select {
225+ text-transform: none;
226+}
227+
228+/*
229+1. Correct the inability to style clickable types in iOS and Safari.
230+2. Remove default button styles.
231+*/
232+
233+button,
234+[type='button'],
235+[type='reset'],
236+[type='submit'] {
237+ -webkit-appearance: button;
238+ /* 1 */
239+ background-color: transparent;
240+ /* 2 */
241+ background-image: none;
242+ /* 2 */
243+}
244+
245+/*
246+Use the modern Firefox focus style for all focusable elements.
247+*/
248+
249+:-moz-focusring {
250+ outline: auto;
251+}
252+
253+/*
254+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
255+*/
256+
257+:-moz-ui-invalid {
258+ box-shadow: none;
259+}
260+
261+/*
262+Add the correct vertical alignment in Chrome and Firefox.
263+*/
264+
265+progress {
266+ vertical-align: baseline;
267+}
268+
269+/*
270+Correct the cursor style of increment and decrement buttons in Safari.
271+*/
272+
273+::-webkit-inner-spin-button,
274+::-webkit-outer-spin-button {
275+ height: auto;
276+}
277+
278+/*
279+1. Correct the odd appearance in Chrome and Safari.
280+2. Correct the outline style in Safari.
281+*/
282+
283+[type='search'] {
284+ -webkit-appearance: textfield;
285+ /* 1 */
286+ outline-offset: -2px;
287+ /* 2 */
288+}
289+
290+/*
291+Remove the inner padding in Chrome and Safari on macOS.
292+*/
293+
294+::-webkit-search-decoration {
295+ -webkit-appearance: none;
296+}
297+
298+/*
299+1. Correct the inability to style clickable types in iOS and Safari.
300+2. Change font properties to `inherit` in Safari.
301+*/
302+
303+::-webkit-file-upload-button {
304+ -webkit-appearance: button;
305+ /* 1 */
306+ font: inherit;
307+ /* 2 */
308+}
309+
310+/*
311+Add the correct display in Chrome and Safari.
312+*/
313+
314+summary {
315+ display: list-item;
316+}
317+
318+/*
319+Removes the default spacing and border for appropriate elements.
320+*/
321+
322+blockquote,
323+dl,
324+dd,
325+h1,
326+h2,
327+h3,
328+h4,
329+h5,
330+h6,
331+hr,
332+figure,
333+p,
334+pre {
335+ margin: 0;
336+}
337+
338+fieldset {
339+ margin: 0;
340+ padding: 0;
341+}
342+
343+legend {
344+ padding: 0;
345+}
346+
347+ol,
348+ul,
349+menu {
350+ list-style: none;
351+ margin: 0;
352+ padding: 0;
353+}
354+
355+/*
356+Reset default styling for dialogs.
357+*/
358+
359+dialog {
360+ padding: 0;
361+}
362+
363+/*
364+Prevent resizing textareas horizontally by default.
365+*/
366+
367+textarea {
368+ resize: vertical;
369+}
370+
371+/*
372+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
373+2. Set the default placeholder color to the user's configured gray 400 color.
374+*/
375+
376+input::-moz-placeholder, textarea::-moz-placeholder {
377+ opacity: 1;
378+ /* 1 */
379+ color: #9ca3af;
380+ /* 2 */
381+}
382+
383+input::placeholder,
384+textarea::placeholder {
385+ opacity: 1;
386+ /* 1 */
387+ color: #9ca3af;
388+ /* 2 */
389+}
390+
391+/*
392+Set the default cursor for buttons.
393+*/
394+
395+button,
396+[role="button"] {
397+ cursor: pointer;
398+}
399+
400+/*
401+Make sure disabled buttons don't get the pointer cursor.
402+*/
403+
404+:disabled {
405+ cursor: default;
406+}
407+
408+/*
409+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
410+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
411+ This can trigger a poorly considered lint error in some tools but is included by design.
412+*/
413+
414+img,
415+svg,
416+video,
417+canvas,
418+audio,
419+iframe,
420+embed,
421+object {
422+ display: block;
423+ /* 1 */
424+ vertical-align: middle;
425+ /* 2 */
426+}
427+
428+/*
429+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
430+*/
431+
432+img,
433+video {
434+ max-width: 100%;
435+ height: auto;
436+}
437+
438+/* Make elements with the HTML hidden attribute stay hidden by default */
439+
440+[hidden] {
441+ display: none;
442+}
443+
444+*, ::before, ::after {
445+ --tw-border-spacing-x: 0;
446+ --tw-border-spacing-y: 0;
447+ --tw-translate-x: 0;
448+ --tw-translate-y: 0;
449+ --tw-rotate: 0;
450+ --tw-skew-x: 0;
451+ --tw-skew-y: 0;
452+ --tw-scale-x: 1;
453+ --tw-scale-y: 1;
454+ --tw-pan-x: ;
455+ --tw-pan-y: ;
456+ --tw-pinch-zoom: ;
457+ --tw-scroll-snap-strictness: proximity;
458+ --tw-gradient-from-position: ;
459+ --tw-gradient-via-position: ;
460+ --tw-gradient-to-position: ;
461+ --tw-ordinal: ;
462+ --tw-slashed-zero: ;
463+ --tw-numeric-figure: ;
464+ --tw-numeric-spacing: ;
465+ --tw-numeric-fraction: ;
466+ --tw-ring-inset: ;
467+ --tw-ring-offset-width: 0px;
468+ --tw-ring-offset-color: #fff;
469+ --tw-ring-color: rgb(59 130 246 / 0.5);
470+ --tw-ring-offset-shadow: 0 0 #0000;
471+ --tw-ring-shadow: 0 0 #0000;
472+ --tw-shadow: 0 0 #0000;
473+ --tw-shadow-colored: 0 0 #0000;
474+ --tw-blur: ;
475+ --tw-brightness: ;
476+ --tw-contrast: ;
477+ --tw-grayscale: ;
478+ --tw-hue-rotate: ;
479+ --tw-invert: ;
480+ --tw-saturate: ;
481+ --tw-sepia: ;
482+ --tw-drop-shadow: ;
483+ --tw-backdrop-blur: ;
484+ --tw-backdrop-brightness: ;
485+ --tw-backdrop-contrast: ;
486+ --tw-backdrop-grayscale: ;
487+ --tw-backdrop-hue-rotate: ;
488+ --tw-backdrop-invert: ;
489+ --tw-backdrop-opacity: ;
490+ --tw-backdrop-saturate: ;
491+ --tw-backdrop-sepia: ;
492+}
493+
494+::backdrop {
495+ --tw-border-spacing-x: 0;
496+ --tw-border-spacing-y: 0;
497+ --tw-translate-x: 0;
498+ --tw-translate-y: 0;
499+ --tw-rotate: 0;
500+ --tw-skew-x: 0;
501+ --tw-skew-y: 0;
502+ --tw-scale-x: 1;
503+ --tw-scale-y: 1;
504+ --tw-pan-x: ;
505+ --tw-pan-y: ;
506+ --tw-pinch-zoom: ;
507+ --tw-scroll-snap-strictness: proximity;
508+ --tw-gradient-from-position: ;
509+ --tw-gradient-via-position: ;
510+ --tw-gradient-to-position: ;
511+ --tw-ordinal: ;
512+ --tw-slashed-zero: ;
513+ --tw-numeric-figure: ;
514+ --tw-numeric-spacing: ;
515+ --tw-numeric-fraction: ;
516+ --tw-ring-inset: ;
517+ --tw-ring-offset-width: 0px;
518+ --tw-ring-offset-color: #fff;
519+ --tw-ring-color: rgb(59 130 246 / 0.5);
520+ --tw-ring-offset-shadow: 0 0 #0000;
521+ --tw-ring-shadow: 0 0 #0000;
522+ --tw-shadow: 0 0 #0000;
523+ --tw-shadow-colored: 0 0 #0000;
524+ --tw-blur: ;
525+ --tw-brightness: ;
526+ --tw-contrast: ;
527+ --tw-grayscale: ;
528+ --tw-hue-rotate: ;
529+ --tw-invert: ;
530+ --tw-saturate: ;
531+ --tw-sepia: ;
532+ --tw-drop-shadow: ;
533+ --tw-backdrop-blur: ;
534+ --tw-backdrop-brightness: ;
535+ --tw-backdrop-contrast: ;
536+ --tw-backdrop-grayscale: ;
537+ --tw-backdrop-hue-rotate: ;
538+ --tw-backdrop-invert: ;
539+ --tw-backdrop-opacity: ;
540+ --tw-backdrop-saturate: ;
541+ --tw-backdrop-sepia: ;
542+}
543+
544+.my-2 {
545+ margin-top: 0.5rem;
546+ margin-bottom: 0.5rem;
547+}
548+
549+.mb-4 {
550+ margin-bottom: 1rem;
551+}
552+
553+.ml-2 {
554+ margin-left: 0.5rem;
555+}
556+
557+.ml-4 {
558+ margin-left: 1rem;
559+}
560+
561+.mr-2 {
562+ margin-right: 0.5rem;
563+}
564+
565+.mt-4 {
566+ margin-top: 1rem;
567+}
568+
569+.flex {
570+ display: flex;
571+}
572+
573+.h-10 {
574+ height: 2.5rem;
575+}
576+
577+.h-24 {
578+ height: 6rem;
579+}
580+
581+.h-32 {
582+ height: 8rem;
583+}
584+
585+.h-44 {
586+ height: 11rem;
587+}
588+
589+.h-64 {
590+ height: 16rem;
591+}
592+
593+.h-full {
594+ height: 100%;
595+}
596+
597+.w-1\/5 {
598+ width: 20%;
599+}
600+
601+.w-2\/6 {
602+ width: 33.333333%;
603+}
604+
605+.w-4\/6 {
606+ width: 66.666667%;
607+}
608+
609+.w-72 {
610+ width: 18rem;
611+}
612+
613+.w-full {
614+ width: 100%;
615+}
616+
617+.w-2\/3 {
618+ width: 66.666667%;
619+}
620+
621+.w-screen {
622+ width: 100vw;
623+}
624+
625+.w-96 {
626+ width: 24rem;
627+}
628+
629+.flex-1 {
630+ flex: 1 1 0%;
631+}
632+
633+.flex-grow {
634+ flex-grow: 1;
635+}
636+
637+.flex-row {
638+ flex-direction: row;
639+}
640+
641+.flex-col {
642+ flex-direction: column;
643+}
644+
645+.items-center {
646+ align-items: center;
647+}
648+
649+.justify-end {
650+ justify-content: flex-end;
651+}
652+
653+.justify-center {
654+ justify-content: center;
655+}
656+
657+.justify-between {
658+ justify-content: space-between;
659+}
660+
661+.justify-items-center {
662+ justify-items: center;
663+}
664+
665+.space-x-4 > :not([hidden]) ~ :not([hidden]) {
666+ --tw-space-x-reverse: 0;
667+ margin-right: calc(1rem * var(--tw-space-x-reverse));
668+ margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
669+}
670+
671+.space-y-2 > :not([hidden]) ~ :not([hidden]) {
672+ --tw-space-y-reverse: 0;
673+ margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
674+ margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
675+}
676+
677+.space-y-4 > :not([hidden]) ~ :not([hidden]) {
678+ --tw-space-y-reverse: 0;
679+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
680+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
681+}
682+
683+.space-x-3 > :not([hidden]) ~ :not([hidden]) {
684+ --tw-space-x-reverse: 0;
685+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
686+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
687+}
688+
689+.space-y-3 > :not([hidden]) ~ :not([hidden]) {
690+ --tw-space-y-reverse: 0;
691+ margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
692+ margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
693+}
694+
695+.overflow-y-scroll {
696+ overflow-y: scroll;
697+}
698+
699+.rounded-lg {
700+ border-radius: 0.5rem;
701+}
702+
703+.rounded-md {
704+ border-radius: 0.375rem;
705+}
706+
707+.rounded-sm {
708+ border-radius: 0.125rem;
709+}
710+
711+.border {
712+ border-width: 1px;
713+}
714+
715+.border-gray-300 {
716+ --tw-border-opacity: 1;
717+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
718+}
719+
720+.bg-gordonmascot-lblue {
721+ --tw-bg-opacity: 1;
722+ background-color: rgb(0 123 192 / var(--tw-bg-opacity));
723+}
724+
725+.bg-gordonmascot-mblue {
726+ --tw-bg-opacity: 1;
727+ background-color: rgb(0 82 147 / var(--tw-bg-opacity));
728+}
729+
730+.bg-gray-300 {
731+ --tw-bg-opacity: 1;
732+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
733+}
734+
735+.bg-transparent {
736+ background-color: transparent;
737+}
738+
739+.bg-white {
740+ --tw-bg-opacity: 1;
741+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
742+}
743+
744+.bg-zinc-200 {
745+ --tw-bg-opacity: 1;
746+ background-color: rgb(228 228 231 / var(--tw-bg-opacity));
747+}
748+
749+.bg-gordonmascot-hblue {
750+ --tw-bg-opacity: 1;
751+ background-color: rgb(1 30 92 / var(--tw-bg-opacity));
752+}
753+
754+.bg-zinc-400 {
755+ --tw-bg-opacity: 1;
756+ background-color: rgb(161 161 170 / var(--tw-bg-opacity));
757+}
758+
759+.p-4 {
760+ padding: 1rem;
761+}
762+
763+.p-2 {
764+ padding: 0.5rem;
765+}
766+
767+.px-2 {
768+ padding-left: 0.5rem;
769+ padding-right: 0.5rem;
770+}
771+
772+.px-6 {
773+ padding-left: 1.5rem;
774+ padding-right: 1.5rem;
775+}
776+
777+.py-2 {
778+ padding-top: 0.5rem;
779+ padding-bottom: 0.5rem;
780+}
781+
782+.px-4 {
783+ padding-left: 1rem;
784+ padding-right: 1rem;
785+}
786+
787+.text-2xl {
788+ font-size: 1.5rem;
789+ line-height: 2rem;
790+}
791+
792+.text-5xl {
793+ font-size: 3rem;
794+ line-height: 1;
795+}
796+
797+.text-lg {
798+ font-size: 1.125rem;
799+ line-height: 1.75rem;
800+}
801+
802+.text-sm {
803+ font-size: 0.875rem;
804+ line-height: 1.25rem;
805+}
806+
807+.text-xl {
808+ font-size: 1.25rem;
809+ line-height: 1.75rem;
810+}
811+
812+.font-semibold {
813+ font-weight: 600;
814+}
815+
816+.tracking-tighter {
817+ letter-spacing: -0.05em;
818+}
819+
820+.text-gordonmascot-hblue {
821+ --tw-text-opacity: 1;
822+ color: rgb(1 30 92 / var(--tw-text-opacity));
823+}
824+
825+.text-gordonmascot-mblue {
826+ --tw-text-opacity: 1;
827+ color: rgb(0 82 147 / var(--tw-text-opacity));
828+}
829+
830+.text-gray-100 {
831+ --tw-text-opacity: 1;
832+ color: rgb(243 244 246 / var(--tw-text-opacity));
833+}
834+
835+.text-gray-800 {
836+ --tw-text-opacity: 1;
837+ color: rgb(31 41 55 / var(--tw-text-opacity));
838+}
839+
840+.text-slate-400 {
841+ --tw-text-opacity: 1;
842+ color: rgb(148 163 184 / var(--tw-text-opacity));
843+}
844+
845+.text-slate-100 {
846+ --tw-text-opacity: 1;
847+ color: rgb(241 245 249 / var(--tw-text-opacity));
848+}
849+
850+.shadow {
851+ --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
852+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
853+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
854+}
855+
856+.outline-none {
857+ outline: 2px solid transparent;
858+ outline-offset: 2px;
859+}
860+
861+/* Import IBM Plex Fonts */
862+
863+@font-face {
864+ font-family: "IBMPlexSans-Bold";
865+
866+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
867+
868+ font-weight: bold;
869+
870+ font-style: normal;
871+}
872+
873+@font-face {
874+ font-family: "IBMPlexSans-Regular";
875+
876+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
877+
878+ font-weight: normal;
879+
880+ font-style: normal;
881+}
882+
883+/* Import Jetbrains Mono Nerd Font */
884+
885+@font-face {
886+ font-family: "JetBrainsMono-Nerd-Font-Regular";
887+
888+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
889+ format("woff2");
890+
891+ font-weight: normal;
892+
893+ font-style: normal;
894+}
895+
896+@font-face {
897+ font-family: "LilitaOne-Regular";
898+
899+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
900+
901+ font-weight: normal;
902+
903+ font-style: normal;
904+}
905+
906+.fade-me-out.htmx-swapping {
907+ opacity: 0;
908+ transition: opacity 1s ease-out;
909+}
910+
911+/* View transition */
912+
913+@keyframes fade-in {
914+ from {
915+ opacity: 0;
916+ }
917+}
918+
919+@keyframes fade-out {
920+ to {
921+ opacity: 0;
922+ }
923+}
924+
925+@keyframes slide-from-right {
926+ from {
927+ transform: translateX(90px);
928+ }
929+}
930+
931+@keyframes slide-to-left {
932+ to {
933+ transform: translateX(-90px);
934+ }
935+}
936+
937+.slide-it {
938+ view-transition-name: slide-it;
939+}
940+
941+::view-transition-old(slide-it) {
942+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
943+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
944+}
945+
946+::view-transition-new(slide-it) {
947+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
948+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
949+}
950+
951+.gordon-title {
952+ font-family: "LilitaOne-Regular", sans-serif;
953+}
954+
955+.IBMPlexSans {
956+ font-family: "IBMPlexSans-Regular", sans-serif;
957+}
958+
959+.circle-shadow {
960+ width: 100%;
961+ position: relative;
962+}
963+
964+.circle-shadow::after {
965+ position: absolute;
966+ width: 50%;
967+ height: 0.4rem;
968+ margin: auto;
969+ background: rgba(0, 0, 0, 0.1);
970+ border-radius: 50%;
971+ z-index: -1;
972+ bottom: 2%;
973+ content: "";
974+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
975+}
976+
977+.iconoir {
978+ margin-right: 8px;
979+}
980+
981+@media (min-width: 640px) {
982+ .sm\:h-24 {
983+ height: 6rem;
984+ }
985+}
986+
987+@media (min-width: 768px) {
988+ .md\:w-1\/2 {
989+ width: 50%;
990+ }
991+
992+ .md\:flex-row {
993+ flex-direction: row;
994+ }
995+
996+ .md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
997+ --tw-space-y-reverse: 0;
998+ margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
999+ margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
1000+ }
1001+
1002+ .md\:p-8 {
1003+ padding: 2rem;
1004+ }
1005+
1006+ .md\:py-8 {
1007+ padding-top: 2rem;
1008+ padding-bottom: 2rem;
1009+ }
1010+
1011+ .md\:pl-4 {
1012+ padding-left: 1rem;
1013+ }
1014+
1015+ .md\:pt-10 {
1016+ padding-top: 2.5rem;
1017+ }
1018+
1019+ .md\:text-2xl {
1020+ font-size: 1.5rem;
1021+ line-height: 2rem;
1022+ }
1023+
1024+ .md\:text-3xl {
1025+ font-size: 1.875rem;
1026+ line-height: 2.25rem;
1027+ }
1028+}
1029+
1030+@media (min-width: 1024px) {
1031+ .lg\:text-4xl {
1032+ font-size: 2.25rem;
1033+ line-height: 2.5rem;
1034+ }
1035+}
1036+
1037+@media (min-width: 1280px) {
1038+ .xl\:h-48 {
1039+ height: 12rem;
1040+ }
1041+
1042+ .xl\:text-5xl {
1043+ font-size: 3rem;
1044+ line-height: 1;
1045+ }
1046+}
A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Light.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Medium.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Thin.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFont-Bold.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFont-Regular.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.ttf +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/LilitaOne/LilitaOne-Regular.ttf +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/LilitaOne/LilitaOne-Regular.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/imgs/gordon-mascot-hq-trsp.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/imgs/gordon-mascot-mq-trsp.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/imgs/gordon-mascot.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/favicon-16x16.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/favicon-32x32.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/favicon.ico +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/libs/alpine.min.js +5 -0
@@ -0,0 +1,5 @@
1+(()=>{var Ze=!1,Qe=!1,V=[],et=-1;function Kt(e){bn(e)}function bn(e){V.includes(e)||V.push(e),wn()}function we(e){let t=V.indexOf(e);t!==-1&&t>et&&V.splice(t,1)}function wn(){!Qe&&!Ze&&(Ze=!0,queueMicrotask(En))}function En(){Ze=!1,Qe=!0;for(let e=0;e<V.length;e++)V[e](),et=e;V.length=0,et=-1,Qe=!1}var T,D,L,rt,tt=!0;function zt(e){tt=!1,e(),tt=!0}function Ht(e){T=e.reactive,L=e.release,D=t=>e.effect(t,{scheduler:r=>{tt?Kt(r):r()}}),rt=e.raw}function nt(e){D=e}function Vt(e){let t=()=>{};return[n=>{let i=D(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),L(i))},i},()=>{t()}]}function q(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function O(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>O(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)O(n,t,!1),n=n.nextElementSibling}function S(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var qt=!1;function Ut(){qt&&S("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),qt=!0,document.body||S("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),q(document,"alpine:init"),q(document,"alpine:initializing"),ce(),Qt(t=>v(t,O)),Q(t=>ae(t)),Se((t,r)=>{le(t,r).forEach(n=>n())});let e=t=>!U(t.parentElement,!0);Array.from(document.querySelectorAll(Jt())).filter(e).forEach(t=>{v(t)}),q(document,"alpine:initialized")}var it=[],Wt=[];function Gt(){return it.map(e=>e())}function Jt(){return it.concat(Wt).map(e=>e())}function Ee(e){it.push(e)}function ve(e){Wt.push(e)}function U(e,t=!1){return Z(e,r=>{if((t?Jt():Gt()).some(i=>r.matches(i)))return!0})}function Z(e,t){if(e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return Z(e.parentElement,t)}}function Yt(e){return Gt().some(t=>e.matches(t))}var Xt=[];function Zt(e){Xt.push(e)}function v(e,t=O,r=()=>{}){tr(()=>{t(e,(n,i)=>{r(n,i),Xt.forEach(o=>o(n,i)),le(n,n.attributes).forEach(o=>o()),n._x_ignore&&i()})})}function ae(e){O(e,t=>{ot(t),er(t)})}var rr=[],nr=[],ir=[];function Qt(e){ir.push(e)}function Q(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,nr.push(t))}function Se(e){rr.push(e)}function Oe(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function ot(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}function er(e){if(e._x_cleanups)for(;e._x_cleanups.length;)e._x_cleanups.pop()()}var at=new MutationObserver(ft),ct=!1;function ce(){at.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ct=!0}function lt(){vn(),at.disconnect(),ct=!1}var ue=[],st=!1;function vn(){ue=ue.concat(at.takeRecords()),ue.length&&!st&&(st=!0,queueMicrotask(()=>{Sn(),st=!1}))}function Sn(){ft(ue),ue.length=0}function h(e){if(!ct)return e();lt();let t=e();return ce(),t}var ut=!1,Ae=[];function or(){ut=!0}function sr(){ut=!1,ft(Ae),Ae=[]}function ft(e){if(ut){Ae=Ae.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{ot(s,o)}),n.forEach((o,s)=>{rr.forEach(a=>a(s,o))});for(let o of r)t.includes(o)||(nr.forEach(s=>s(o)),ae(o));t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.includes(o)||o.isConnected&&(delete o._x_ignoreSelf,delete o._x_ignore,ir.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function Ce(e){return F($(e))}function N(e,t,r){return e._x_dataStack=[t,...$(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function $(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?$(e.host):e.parentNode?$(e.parentNode):[]}function F(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function Te(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Re(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>An(n,i),s=>dt(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function An(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function dt(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),dt(e[t[0]],t.slice(1),r)}}var ar={};function y(e,t){ar[e]=t}function fe(e,t){return Object.entries(ar).forEach(([r,n])=>{let i=null;function o(){if(i)return i;{let[s,a]=pt(t);return i={interceptor:Re,...s},Q(t,a),i}}Object.defineProperty(e,`$${r}`,{get(){return n(t,o())},enumerable:!1})}),e}function cr(e,t,r,...n){try{return r(...n)}catch(i){ee(i,e,t)}}function ee(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message}
2+
3+${r?'Expression: "'+r+`"
4+
5+`:""}`,t),setTimeout(()=>{throw e},0)}var Me=!0;function Pe(e){let t=Me;Me=!1;let r=e();return Me=t,r}function R(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return lr(...e)}var lr=ht;function ur(e){lr=e}function ht(e,t){let r={};fe(r,e);let n=[r,...$(e)],i=typeof t=="function"?On(n,t):Tn(n,t,e);return cr.bind(null,e,t,i)}function On(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(F([n,...e]),i);Ne(r,o)}}var mt={};function Cn(e,t){if(mt[e])return mt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e.trim())||/^(let|const)\s/.test(e.trim())?`(async()=>{ ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return ee(s,t,e),Promise.resolve()}})();return mt[e]=o,o}function Tn(e,t,r){let n=Cn(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=F([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>ee(l,r,t));n.finished?(Ne(i,n.result,a,s,r),n.result=void 0):c.then(l=>{Ne(i,l,a,s,r)}).catch(l=>ee(l,r,t)).finally(()=>n.result=void 0)}}}function Ne(e,t,r,n,i){if(Me&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Ne(e,s,r,n)).catch(s=>ee(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var yt="x-";function C(e=""){return yt+e}function fr(e){yt=e}var _t={};function p(e,t){return _t[e]=t,{before(r){if(!_t[r]){console.warn("Cannot find directive `${directive}`. `${name}` will use the default order of execution");return}let n=W.indexOf(r);W.splice(n>=0?n:W.indexOf("DEFAULT"),0,e)}}}function le(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=bt(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(pr((o,s)=>n[o]=s)).filter(hr).map(Mn(n,r)).sort(Nn).map(o=>Rn(e,o))}function bt(e){return Array.from(e).map(pr()).filter(t=>!hr(t))}var gt=!1,de=new Map,dr=Symbol();function tr(e){gt=!0;let t=Symbol();dr=t,de.set(t,[]);let r=()=>{for(;de.get(t).length;)de.get(t).shift()();de.delete(t)},n=()=>{gt=!1,r()};e(r),n()}function pt(e){let t=[],r=a=>t.push(a),[n,i]=Vt(e);return t.push(i),[{Alpine:j,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:R.bind(R,e)},()=>t.forEach(a=>a())]}function Rn(e,t){let r=()=>{},n=_t[t.type]||r,[i,o]=pt(e);Oe(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),gt?de.get(dr).push(n):n())};return s.runCleanups=o,s}var De=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Ie=e=>e;function pr(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=mr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var mr=[];function te(e){mr.push(e)}function hr({name:e}){return _r().test(e)}var _r=()=>new RegExp(`^${yt}([^:^.]+)\\b`);function Mn(e,t){return({name:r,value:n})=>{let i=r.match(_r()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var xt="DEFAULT",W=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",xt,"teleport"];function Nn(e,t){let r=W.indexOf(e.type)===-1?xt:e.type,n=W.indexOf(t.type)===-1?xt:t.type;return W.indexOf(r)-W.indexOf(n)}var wt=[],Et=!1;function re(e=()=>{}){return queueMicrotask(()=>{Et||setTimeout(()=>{ke()})}),new Promise(t=>{wt.push(()=>{e(),t()})})}function ke(){for(Et=!1;wt.length;)wt.shift()()}function gr(){Et=!0}function pe(e,t){return Array.isArray(t)?xr(e,t.join(" ")):typeof t=="object"&&t!==null?Pn(e,t):typeof t=="function"?pe(e,t()):xr(e,t)}function xr(e,t){let r=o=>o.split(" ").filter(Boolean),n=o=>o.split(" ").filter(s=>!e.classList.contains(s)).filter(Boolean),i=o=>(e.classList.add(...o),()=>{e.classList.remove(...o)});return t=t===!0?t="":t||"",i(n(t))}function Pn(e,t){let r=a=>a.split(" ").filter(Boolean),n=Object.entries(t).flatMap(([a,c])=>c?r(a):!1).filter(Boolean),i=Object.entries(t).flatMap(([a,c])=>c?!1:r(a)).filter(Boolean),o=[],s=[];return i.forEach(a=>{e.classList.contains(a)&&(e.classList.remove(a),s.push(a))}),n.forEach(a=>{e.classList.contains(a)||(e.classList.add(a),o.push(a))}),()=>{s.forEach(a=>e.classList.add(a)),o.forEach(a=>e.classList.remove(a))}}function G(e,t){return typeof t=="object"&&t!==null?Dn(e,t):In(e,t)}function Dn(e,t){let r={};return Object.entries(t).forEach(([n,i])=>{r[n]=e.style[n],n.startsWith("--")||(n=kn(n)),e.style.setProperty(n,i)}),setTimeout(()=>{e.style.length===0&&e.removeAttribute("style")}),()=>{G(e,r)}}function In(e,t){let r=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",r||"")}}function kn(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function me(e,t=()=>{}){let r=!1;return function(){r?t.apply(this,arguments):(r=!0,e.apply(this,arguments))}}p("transition",(e,{value:t,modifiers:r,expression:n},{evaluate:i})=>{typeof n=="function"&&(n=i(n)),n!==!1&&(!n||typeof n=="boolean"?$n(e,r,t):Ln(e,n,t))});function Ln(e,t,r){yr(e,pe,""),{enter:i=>{e._x_transition.enter.during=i},"enter-start":i=>{e._x_transition.enter.start=i},"enter-end":i=>{e._x_transition.enter.end=i},leave:i=>{e._x_transition.leave.during=i},"leave-start":i=>{e._x_transition.leave.start=i},"leave-end":i=>{e._x_transition.leave.end=i}}[r](t)}function $n(e,t,r){yr(e,G);let n=!t.includes("in")&&!t.includes("out")&&!r,i=n||t.includes("in")||["enter"].includes(r),o=n||t.includes("out")||["leave"].includes(r);t.includes("in")&&!n&&(t=t.filter((g,b)=>b<t.indexOf("out"))),t.includes("out")&&!n&&(t=t.filter((g,b)=>b>t.indexOf("out")));let s=!t.includes("opacity")&&!t.includes("scale"),a=s||t.includes("opacity"),c=s||t.includes("scale"),l=a?0:1,u=c?he(t,"scale",95)/100:1,d=he(t,"delay",0)/1e3,m=he(t,"origin","center"),w="opacity, transform",k=he(t,"duration",150)/1e3,be=he(t,"duration",75)/1e3,f="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:m,transitionDelay:`${d}s`,transitionProperty:w,transitionDuration:`${k}s`,transitionTimingFunction:f},e._x_transition.enter.start={opacity:l,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"}),o&&(e._x_transition.leave.during={transformOrigin:m,transitionDelay:`${d}s`,transitionProperty:w,transitionDuration:`${be}s`,transitionTimingFunction:f},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:l,transform:`scale(${u})`})}function yr(e,t,r={}){e._x_transition||(e._x_transition={enter:{during:r,start:r,end:r},leave:{during:r,start:r,end:r},in(n=()=>{},i=()=>{}){Le(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,i)},out(n=()=>{},i=()=>{}){Le(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,i)}})}window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,r,n){let i=document.visibilityState==="visible"?requestAnimationFrame:setTimeout,o=()=>i(r);if(t){e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(r):o():e._x_transition?e._x_transition.in(r):o();return}e._x_hidePromise=e._x_transition?new Promise((s,a)=>{e._x_transition.out(()=>{},()=>s(n)),e._x_transitioning.beforeCancel(()=>a({isFromCancelledTransition:!0}))}):Promise.resolve(n),queueMicrotask(()=>{let s=br(e);s?(s._x_hideChildren||(s._x_hideChildren=[]),s._x_hideChildren.push(e)):i(()=>{let a=c=>{let l=Promise.all([c._x_hidePromise,...(c._x_hideChildren||[]).map(a)]).then(([u])=>u());return delete c._x_hidePromise,delete c._x_hideChildren,l};a(e).catch(c=>{if(!c.isFromCancelledTransition)throw c})})})};function br(e){let t=e.parentNode;if(t)return t._x_hidePromise?t:br(t)}function Le(e,t,{during:r,start:n,end:i}={},o=()=>{},s=()=>{}){if(e._x_transitioning&&e._x_transitioning.cancel(),Object.keys(r).length===0&&Object.keys(n).length===0&&Object.keys(i).length===0){o(),s();return}let a,c,l;Fn(e,{start(){a=t(e,n)},during(){c=t(e,r)},before:o,end(){a(),l=t(e,i)},after:s,cleanup(){c(),l()}})}function Fn(e,t){let r,n,i,o=me(()=>{h(()=>{r=!0,n||t.before(),i||(t.end(),ke()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning})});e._x_transitioning={beforeCancels:[],beforeCancel(s){this.beforeCancels.push(s)},cancel:me(function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()}),finish:o},h(()=>{t.start(),t.during()}),gr(),requestAnimationFrame(()=>{if(r)return;let s=Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""))*1e3,a=Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""))*1e3;s===0&&(s=Number(getComputedStyle(e).animationDuration.replace("s",""))*1e3),h(()=>{t.before()}),n=!0,requestAnimationFrame(()=>{r||(h(()=>{t.end()}),ke(),setTimeout(e._x_transitioning.finish,s+a),i=!0)})})}function he(e,t,r){if(e.indexOf(t)===-1)return r;let n=e[e.indexOf(t)+1];if(!n||t==="scale"&&isNaN(n))return r;if(t==="duration"||t==="delay"){let i=n.match(/([0-9]+)ms/);if(i)return i[1]}return t==="origin"&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[n,e[e.indexOf(t)+2]].join(" "):n}var I=!1;function B(e,t=()=>{}){return(...r)=>I?t(...r):e(...r)}function wr(e){return(...t)=>I&&e(...t)}function Er(e,t){e._x_dataStack&&(t._x_dataStack=e._x_dataStack,t.setAttribute("data-has-alpine-state",!0)),I=!0,Sr(()=>{v(t,(r,n)=>{n(r,()=>{})})}),I=!1}var vt=!1;function vr(e,t){t._x_dataStack||(t._x_dataStack=e._x_dataStack),I=!0,vt=!0,Sr(()=>{jn(t)}),I=!1,vt=!1}function jn(e){let t=!1;v(e,(n,i)=>{O(n,(o,s)=>{if(t&&Yt(o))return s();t=!0,i(o,s)})})}function Sr(e){let t=D;nt((r,n)=>{let i=t(r);return L(i),()=>{}}),e(),nt(t)}function Ar(e){return I?vt?!0:e.hasAttribute("data-has-alpine-state"):!1}function _e(e,t,r,n=[]){switch(e._x_bindings||(e._x_bindings=T({})),e._x_bindings[t]=r,t=n.includes("camel")?Wn(t):t,t){case"value":Bn(e,r);break;case"style":zn(e,r);break;case"class":Kn(e,r);break;case"selected":case"checked":Hn(e,t,r);break;default:Cr(e,t,r);break}}function Bn(e,t){if(e.type==="radio")e.attributes.value===void 0&&(e.value=t),window.fromModel&&(e.checked=Or(e.value,t));else if(e.type==="checkbox")Number.isInteger(t)?e.value=t:!Array.isArray(t)&&typeof t!="boolean"&&![null,void 0].includes(t)?e.value=String(t):Array.isArray(t)?e.checked=t.some(r=>Or(r,e.value)):e.checked=!!t;else if(e.tagName==="SELECT")Un(e,t);else{if(e.value===t)return;e.value=t===void 0?"":t}}function Kn(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses(),e._x_undoAddedClasses=pe(e,t)}function zn(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles(),e._x_undoAddedStyles=G(e,t)}function Hn(e,t,r){Cr(e,t,r),qn(e,t,r)}function Cr(e,t,r){[null,void 0,!1].includes(r)&&Gn(t)?e.removeAttribute(t):(Tr(t)&&(r=t),Vn(e,t,r))}function Vn(e,t,r){e.getAttribute(t)!=r&&e.setAttribute(t,r)}function qn(e,t,r){e[t]!==r&&(e[t]=r)}function Un(e,t){let r=[].concat(t).map(n=>n+"");Array.from(e.options).forEach(n=>{n.selected=r.includes(n.value)})}function Wn(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Or(e,t){return e==t}function Tr(e){return["disabled","checked","required","readonly","hidden","open","selected","autofocus","itemscope","multiple","novalidate","allowfullscreen","allowpaymentrequest","formnovalidate","autoplay","controls","loop","muted","playsinline","default","ismap","reversed","async","defer","nomodule"].includes(e)}function Gn(e){return!["aria-pressed","aria-checked","aria-expanded","aria-selected"].includes(e)}function Rr(e,t,r){return e._x_bindings&&e._x_bindings[t]!==void 0?e._x_bindings[t]:Nr(e,t,r)}function Mr(e,t,r,n=!0){if(e._x_bindings&&e._x_bindings[t]!==void 0)return e._x_bindings[t];if(e._x_inlineBindings&&e._x_inlineBindings[t]!==void 0){let i=e._x_inlineBindings[t];return i.extract=n,Pe(()=>R(e,i.expression))}return Nr(e,t,r)}function Nr(e,t,r){let n=e.getAttribute(t);return n===null?typeof r=="function"?r():r:n===""?!0:Tr(t)?!![t,"true"].includes(n):n}function $e(e,t){var r;return function(){var n=this,i=arguments,o=function(){r=null,e.apply(n,i)};clearTimeout(r),r=setTimeout(o,t)}}function Fe(e,t){let r;return function(){let n=this,i=arguments;r||(e.apply(n,i),r=!0,setTimeout(()=>r=!1,t))}}function je({get:e,set:t},{get:r,set:n}){let i=!0,o,s,a,c,l=D(()=>{let u,d;i?(u=e(),n(JSON.parse(JSON.stringify(u))),d=r(),i=!1):(u=e(),d=r(),a=JSON.stringify(u),c=JSON.stringify(d),a!==o?(d=r(),n(u),d=u):(t(JSON.parse(c??null)),u=d)),o=JSON.stringify(u),s=JSON.stringify(d)});return()=>{L(l)}}function Pr(e){(Array.isArray(e)?e:[e]).forEach(r=>r(j))}var J={},Dr=!1;function Ir(e,t){if(Dr||(J=T(J),Dr=!0),t===void 0)return J[e];J[e]=t,typeof t=="object"&&t!==null&&t.hasOwnProperty("init")&&typeof t.init=="function"&&J[e].init(),Te(J[e])}function kr(){return J}var Lr={};function $r(e,t){let r=typeof t!="function"?()=>t:t;return e instanceof Element?St(e,r()):(Lr[e]=r,()=>{})}function Fr(e){return Object.entries(Lr).forEach(([t,r])=>{Object.defineProperty(e,t,{get(){return(...n)=>r(...n)}})}),e}function St(e,t,r){let n=[];for(;n.length;)n.pop()();let i=Object.entries(t).map(([s,a])=>({name:s,value:a})),o=bt(i);return i=i.map(s=>o.find(a=>a.name===s.name)?{name:`x-bind:${s.name}`,value:`"${s.value}"`}:s),le(e,i,r).map(s=>{n.push(s.runCleanups),s()}),()=>{for(;n.length;)n.pop()()}}var jr={};function Br(e,t){jr[e]=t}function Kr(e,t){return Object.entries(jr).forEach(([r,n])=>{Object.defineProperty(e,r,{get(){return(...i)=>n.bind(t)(...i)},enumerable:!1})}),e}var Jn={get reactive(){return T},get release(){return L},get effect(){return D},get raw(){return rt},version:"3.13.0",flushAndStopDeferringMutations:sr,dontAutoEvaluateFunctions:Pe,disableEffectScheduling:zt,startObservingMutations:ce,stopObservingMutations:lt,setReactivityEngine:Ht,onAttributeRemoved:Oe,onAttributesAdded:Se,closestDataStack:$,skipDuringClone:B,onlyDuringClone:wr,addRootSelector:Ee,addInitSelector:ve,addScopeToNode:N,deferMutations:or,mapAttributes:te,evaluateLater:x,interceptInit:Zt,setEvaluator:ur,mergeProxies:F,extractProp:Mr,findClosest:Z,onElRemoved:Q,closestRoot:U,destroyTree:ae,interceptor:Re,transition:Le,setStyles:G,mutateDom:h,directive:p,entangle:je,throttle:Fe,debounce:$e,evaluate:R,initTree:v,nextTick:re,prefixed:C,prefix:fr,plugin:Pr,magic:y,store:Ir,start:Ut,clone:vr,cloneNode:Er,bound:Rr,$data:Ce,walk:O,data:Br,bind:$r},j=Jn;function At(e,t){let r=Object.create(null),n=e.split(",");for(let i=0;i<n.length;i++)r[n[i]]=!0;return t?i=>!!r[i.toLowerCase()]:i=>!!r[i]}var Yn="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly";var As=At(Yn+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected");var zr=Object.freeze({}),Os=Object.freeze([]);var Xn=Object.prototype.hasOwnProperty,ge=(e,t)=>Xn.call(e,t),K=Array.isArray,ne=e=>Hr(e)==="[object Map]";var Zn=e=>typeof e=="string",Be=e=>typeof e=="symbol",xe=e=>e!==null&&typeof e=="object";var Qn=Object.prototype.toString,Hr=e=>Qn.call(e),Ot=e=>Hr(e).slice(8,-1);var Ke=e=>Zn(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e;var ze=e=>{let t=Object.create(null);return r=>t[r]||(t[r]=e(r))},ei=/-(\w)/g,Cs=ze(e=>e.replace(ei,(t,r)=>r?r.toUpperCase():"")),ti=/\B([A-Z])/g,Ts=ze(e=>e.replace(ti,"-$1").toLowerCase()),Ct=ze(e=>e.charAt(0).toUpperCase()+e.slice(1)),Rs=ze(e=>e?`on${Ct(e)}`:""),Tt=(e,t)=>e!==t&&(e===e||t===t);var Rt=new WeakMap,ye=[],P,Y=Symbol("iterate"),Mt=Symbol("Map key iterate");function ri(e){return e&&e._isEffect===!0}function Jr(e,t=zr){ri(e)&&(e=e.raw);let r=ii(e,t);return t.lazy||r(),r}function Yr(e){e.active&&(Xr(e),e.options.onStop&&e.options.onStop(),e.active=!1)}var ni=0;function ii(e,t){let r=function(){if(!r.active)return e();if(!ye.includes(r)){Xr(r);try{return si(),ye.push(r),P=r,e()}finally{ye.pop(),Zr(),P=ye[ye.length-1]}}};return r.id=ni++,r.allowRecurse=!!t.allowRecurse,r._isEffect=!0,r.active=!0,r.raw=e,r.deps=[],r.options=t,r}function Xr(e){let{deps:t}=e;if(t.length){for(let r=0;r<t.length;r++)t[r].delete(e);t.length=0}}var ie=!0,Pt=[];function oi(){Pt.push(ie),ie=!1}function si(){Pt.push(ie),ie=!0}function Zr(){let e=Pt.pop();ie=e===void 0?!0:e}function M(e,t,r){if(!ie||P===void 0)return;let n=Rt.get(e);n||Rt.set(e,n=new Map);let i=n.get(r);i||n.set(r,i=new Set),i.has(P)||(i.add(P),P.deps.push(i),P.options.onTrack&&P.options.onTrack({effect:P,target:e,type:t,key:r}))}function H(e,t,r,n,i,o){let s=Rt.get(e);if(!s)return;let a=new Set,c=u=>{u&&u.forEach(d=>{(d!==P||d.allowRecurse)&&a.add(d)})};if(t==="clear")s.forEach(c);else if(r==="length"&&K(e))s.forEach((u,d)=>{(d==="length"||d>=n)&&c(u)});else switch(r!==void 0&&c(s.get(r)),t){case"add":K(e)?Ke(r)&&c(s.get("length")):(c(s.get(Y)),ne(e)&&c(s.get(Mt)));break;case"delete":K(e)||(c(s.get(Y)),ne(e)&&c(s.get(Mt)));break;case"set":ne(e)&&c(s.get(Y));break}let l=u=>{u.options.onTrigger&&u.options.onTrigger({effect:u,target:e,key:r,type:t,newValue:n,oldValue:i,oldTarget:o}),u.options.scheduler?u.options.scheduler(u):u()};a.forEach(l)}var ai=At("__proto__,__v_isRef,__isVue"),Qr=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Be)),ci=en();var li=en(!0);var Vr=ui();function ui(){let e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...r){let n=_(this);for(let o=0,s=this.length;o<s;o++)M(n,"get",o+"");let i=n[t](...r);return i===-1||i===!1?n[t](...r.map(_)):i}}),["push","pop","shift","unshift","splice"].forEach(t=>{e[t]=function(...r){oi();let n=_(this)[t].apply(this,r);return Zr(),n}}),e}function en(e=!1,t=!1){return function(n,i,o){if(i==="__v_isReactive")return!e;if(i==="__v_isReadonly")return e;if(i==="__v_raw"&&o===(e?t?Oi:on:t?Ai:nn).get(n))return n;let s=K(n);if(!e&&s&&ge(Vr,i))return Reflect.get(Vr,i,o);let a=Reflect.get(n,i,o);return(Be(i)?Qr.has(i):ai(i))||(e||M(n,"get",i),t)?a:Nt(a)?!s||!Ke(i)?a.value:a:xe(a)?e?sn(a):Je(a):a}}var fi=di();function di(e=!1){return function(r,n,i,o){let s=r[n];if(!e&&(i=_(i),s=_(s),!K(r)&&Nt(s)&&!Nt(i)))return s.value=i,!0;let a=K(r)&&Ke(n)?Number(n)<r.length:ge(r,n),c=Reflect.set(r,n,i,o);return r===_(o)&&(a?Tt(i,s)&&H(r,"set",n,i,s):H(r,"add",n,i)),c}}function pi(e,t){let r=ge(e,t),n=e[t],i=Reflect.deleteProperty(e,t);return i&&r&&H(e,"delete",t,void 0,n),i}function mi(e,t){let r=Reflect.has(e,t);return(!Be(t)||!Qr.has(t))&&M(e,"has",t),r}function hi(e){return M(e,"iterate",K(e)?"length":Y),Reflect.ownKeys(e)}var _i={get:ci,set:fi,deleteProperty:pi,has:mi,ownKeys:hi},gi={get:li,set(e,t){return console.warn(`Set operation on key "${String(t)}" failed: target is readonly.`,e),!0},deleteProperty(e,t){return console.warn(`Delete operation on key "${String(t)}" failed: target is readonly.`,e),!0}};var Dt=e=>xe(e)?Je(e):e,It=e=>xe(e)?sn(e):e,kt=e=>e,Ge=e=>Reflect.getPrototypeOf(e);function He(e,t,r=!1,n=!1){e=e.__v_raw;let i=_(e),o=_(t);t!==o&&!r&&M(i,"get",t),!r&&M(i,"get",o);let{has:s}=Ge(i),a=n?kt:r?It:Dt;if(s.call(i,t))return a(e.get(t));if(s.call(i,o))return a(e.get(o));e!==i&&e.get(t)}function Ve(e,t=!1){let r=this.__v_raw,n=_(r),i=_(e);return e!==i&&!t&&M(n,"has",e),!t&&M(n,"has",i),e===i?r.has(e):r.has(e)||r.has(i)}function qe(e,t=!1){return e=e.__v_raw,!t&&M(_(e),"iterate",Y),Reflect.get(e,"size",e)}function qr(e){e=_(e);let t=_(this);return Ge(t).has.call(t,e)||(t.add(e),H(t,"add",e,e)),this}function Ur(e,t){t=_(t);let r=_(this),{has:n,get:i}=Ge(r),o=n.call(r,e);o?rn(r,n,e):(e=_(e),o=n.call(r,e));let s=i.call(r,e);return r.set(e,t),o?Tt(t,s)&&H(r,"set",e,t,s):H(r,"add",e,t),this}function Wr(e){let t=_(this),{has:r,get:n}=Ge(t),i=r.call(t,e);i?rn(t,r,e):(e=_(e),i=r.call(t,e));let o=n?n.call(t,e):void 0,s=t.delete(e);return i&&H(t,"delete",e,void 0,o),s}function Gr(){let e=_(this),t=e.size!==0,r=ne(e)?new Map(e):new Set(e),n=e.clear();return t&&H(e,"clear",void 0,void 0,r),n}function Ue(e,t){return function(n,i){let o=this,s=o.__v_raw,a=_(s),c=t?kt:e?It:Dt;return!e&&M(a,"iterate",Y),s.forEach((l,u)=>n.call(i,c(l),c(u),o))}}function We(e,t,r){return function(...n){let i=this.__v_raw,o=_(i),s=ne(o),a=e==="entries"||e===Symbol.iterator&&s,c=e==="keys"&&s,l=i[e](...n),u=r?kt:t?It:Dt;return!t&&M(o,"iterate",c?Mt:Y),{next(){let{value:d,done:m}=l.next();return m?{value:d,done:m}:{value:a?[u(d[0]),u(d[1])]:u(d),done:m}},[Symbol.iterator](){return this}}}}function z(e){return function(...t){{let r=t[0]?`on key "${t[0]}" `:"";console.warn(`${Ct(e)} operation ${r}failed: target is readonly.`,_(this))}return e==="delete"?!1:this}}function xi(){let e={get(o){return He(this,o)},get size(){return qe(this)},has:Ve,add:qr,set:Ur,delete:Wr,clear:Gr,forEach:Ue(!1,!1)},t={get(o){return He(this,o,!1,!0)},get size(){return qe(this)},has:Ve,add:qr,set:Ur,delete:Wr,clear:Gr,forEach:Ue(!1,!0)},r={get(o){return He(this,o,!0)},get size(){return qe(this,!0)},has(o){return Ve.call(this,o,!0)},add:z("add"),set:z("set"),delete:z("delete"),clear:z("clear"),forEach:Ue(!0,!1)},n={get(o){return He(this,o,!0,!0)},get size(){return qe(this,!0)},has(o){return Ve.call(this,o,!0)},add:z("add"),set:z("set"),delete:z("delete"),clear:z("clear"),forEach:Ue(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(o=>{e[o]=We(o,!1,!1),r[o]=We(o,!0,!1),t[o]=We(o,!1,!0),n[o]=We(o,!0,!0)}),[e,r,t,n]}var[yi,bi,wi,Ei]=xi();function tn(e,t){let r=t?e?Ei:wi:e?bi:yi;return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(ge(r,i)&&i in n?r:n,i,o)}var vi={get:tn(!1,!1)};var Si={get:tn(!0,!1)};function rn(e,t,r){let n=_(r);if(n!==r&&t.call(e,n)){let i=Ot(e);console.warn(`Reactive ${i} contains both the raw and reactive versions of the same object${i==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var nn=new WeakMap,Ai=new WeakMap,on=new WeakMap,Oi=new WeakMap;function Ci(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Ti(e){return e.__v_skip||!Object.isExtensible(e)?0:Ci(Ot(e))}function Je(e){return e&&e.__v_isReadonly?e:an(e,!1,_i,vi,nn)}function sn(e){return an(e,!0,gi,Si,on)}function an(e,t,r,n,i){if(!xe(e))return console.warn(`value cannot be made reactive: ${String(e)}`),e;if(e.__v_raw&&!(t&&e.__v_isReactive))return e;let o=i.get(e);if(o)return o;let s=Ti(e);if(s===0)return e;let a=new Proxy(e,s===2?n:r);return i.set(e,a),a}function _(e){return e&&_(e.__v_raw)||e}function Nt(e){return Boolean(e&&e.__v_isRef===!0)}y("nextTick",()=>re);y("dispatch",e=>q.bind(q,e));y("watch",(e,{evaluateLater:t,effect:r})=>(n,i)=>{let o=t(n),s=!0,a,c=r(()=>o(l=>{JSON.stringify(l),s?a=l:queueMicrotask(()=>{i(l,a),a=l}),s=!1}));e._x_effects.delete(c)});y("store",kr);y("data",e=>Ce(e));y("root",e=>U(e));y("refs",e=>(e._x_refs_proxy||(e._x_refs_proxy=F(Ri(e))),e._x_refs_proxy));function Ri(e){let t=[],r=e;for(;r;)r._x_refs&&t.push(r._x_refs),r=r.parentNode;return t}var Lt={};function $t(e){return Lt[e]||(Lt[e]=0),++Lt[e]}function cn(e,t){return Z(e,r=>{if(r._x_ids&&r._x_ids[t])return!0})}function ln(e,t){e._x_ids||(e._x_ids={}),e._x_ids[t]||(e._x_ids[t]=$t(t))}y("id",e=>(t,r=null)=>{let n=cn(e,t),i=n?n._x_ids[t]:$t(t);return r?`${t}-${i}-${r}`:`${t}-${i}`});y("el",e=>e);un("Focus","focus","focus");un("Persist","persist","persist");function un(e,t,r){y(t,n=>S(`You can't use [$${directiveName}] without first installing the "${e}" plugin here: https://alpinejs.dev/plugins/${r}`,n))}p("modelable",(e,{expression:t},{effect:r,evaluateLater:n,cleanup:i})=>{let o=n(t),s=()=>{let u;return o(d=>u=d),u},a=n(`${t} = __placeholder`),c=u=>a(()=>{},{scope:{__placeholder:u}}),l=s();c(l),queueMicrotask(()=>{if(!e._x_model)return;e._x_removeModelListeners.default();let u=e._x_model.get,d=e._x_model.set,m=je({get(){return u()},set(w){d(w)}},{get(){return s()},set(w){c(w)}});i(m)})});var Mi=document.createElement("div");p("teleport",(e,{modifiers:t,expression:r},{cleanup:n})=>{e.tagName.toLowerCase()!=="template"&&S("x-teleport can only be used on a <template> tag",e);let i=B(()=>document.querySelector(r),()=>Mi)();i||S(`Cannot find x-teleport element for selector: "${r}"`);let o=e.content.cloneNode(!0).firstElementChild;e._x_teleport=o,o._x_teleportBack=e,e._x_forwardEvents&&e._x_forwardEvents.forEach(s=>{o.addEventListener(s,a=>{a.stopPropagation(),e.dispatchEvent(new a.constructor(a.type,a))})}),N(o,{},e),h(()=>{t.includes("prepend")?i.parentNode.insertBefore(o,i):t.includes("append")?i.parentNode.insertBefore(o,i.nextSibling):i.appendChild(o),v(o),o._x_ignore=!0}),n(()=>o.remove())});var fn=()=>{};fn.inline=(e,{modifiers:t},{cleanup:r})=>{t.includes("self")?e._x_ignoreSelf=!0:e._x_ignore=!0,r(()=>{t.includes("self")?delete e._x_ignoreSelf:delete e._x_ignore})};p("ignore",fn);p("effect",(e,{expression:t},{effect:r})=>r(x(e,t)));function oe(e,t,r,n){let i=e,o=c=>n(c),s={},a=(c,l)=>u=>l(c,u);if(r.includes("dot")&&(t=Ni(t)),r.includes("camel")&&(t=Pi(t)),r.includes("passive")&&(s.passive=!0),r.includes("capture")&&(s.capture=!0),r.includes("window")&&(i=window),r.includes("document")&&(i=document),r.includes("debounce")){let c=r[r.indexOf("debounce")+1]||"invalid-wait",l=Ye(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=$e(o,l)}if(r.includes("throttle")){let c=r[r.indexOf("throttle")+1]||"invalid-wait",l=Ye(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Fe(o,l)}return r.includes("prevent")&&(o=a(o,(c,l)=>{l.preventDefault(),c(l)})),r.includes("stop")&&(o=a(o,(c,l)=>{l.stopPropagation(),c(l)})),r.includes("self")&&(o=a(o,(c,l)=>{l.target===e&&c(l)})),(r.includes("away")||r.includes("outside"))&&(i=document,o=a(o,(c,l)=>{e.contains(l.target)||l.target.isConnected!==!1&&(e.offsetWidth<1&&e.offsetHeight<1||e._x_isShown!==!1&&c(l))})),r.includes("once")&&(o=a(o,(c,l)=>{c(l),i.removeEventListener(t,o,s)})),o=a(o,(c,l)=>{Ii(t)&&ki(l,r)||c(l)}),i.addEventListener(t,o,s),()=>{i.removeEventListener(t,o,s)}}function Ni(e){return e.replace(/-/g,".")}function Pi(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Ye(e){return!Array.isArray(e)&&!isNaN(e)}function Di(e){return[" ","_"].includes(e)?e:e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}function Ii(e){return["keydown","keyup"].includes(e)}function ki(e,t){let r=t.filter(o=>!["window","document","prevent","stop","once","capture"].includes(o));if(r.includes("debounce")){let o=r.indexOf("debounce");r.splice(o,Ye((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.includes("throttle")){let o=r.indexOf("throttle");r.splice(o,Ye((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.length===0||r.length===1&&dn(e.key).includes(r[0]))return!1;let i=["ctrl","shift","alt","meta","cmd","super"].filter(o=>r.includes(o));return r=r.filter(o=>!i.includes(o)),!(i.length>0&&i.filter(s=>((s==="cmd"||s==="super")&&(s="meta"),e[`${s}Key`])).length===i.length&&dn(e.key).includes(r[0]))}function dn(e){if(!e)return[];e=Di(e);let t={ctrl:"control",slash:"/",space:" ",spacebar:" ",cmd:"meta",esc:"escape",up:"arrow-up",down:"arrow-down",left:"arrow-left",right:"arrow-right",period:".",equal:"=",minus:"-",underscore:"_"};return t[e]=e,Object.keys(t).map(r=>{if(t[r]===e)return r}).filter(r=>r)}p("model",(e,{modifiers:t,expression:r},{effect:n,cleanup:i})=>{let o=e;t.includes("parent")&&(o=e.parentNode);let s=x(o,r),a;typeof r=="string"?a=x(o,`${r} = __placeholder`):typeof r=="function"&&typeof r()=="string"?a=x(o,`${r()} = __placeholder`):a=()=>{};let c=()=>{let m;return s(w=>m=w),pn(m)?m.get():m},l=m=>{let w;s(k=>w=k),pn(w)?w.set(m):a(()=>{},{scope:{__placeholder:m}})};typeof r=="string"&&e.type==="radio"&&h(()=>{e.hasAttribute("name")||e.setAttribute("name",r)});var u=e.tagName.toLowerCase()==="select"||["checkbox","radio"].includes(e.type)||t.includes("lazy")?"change":"input";let d=I?()=>{}:oe(e,u,t,m=>{l(Li(e,t,m,c()))});if(t.includes("fill")&&([null,""].includes(c())||e.type==="checkbox"&&Array.isArray(c()))&&e.dispatchEvent(new Event(u,{})),e._x_removeModelListeners||(e._x_removeModelListeners={}),e._x_removeModelListeners.default=d,i(()=>e._x_removeModelListeners.default()),e.form){let m=oe(e.form,"reset",[],w=>{re(()=>e._x_model&&e._x_model.set(e.value))});i(()=>m())}e._x_model={get(){return c()},set(m){l(m)}},e._x_forceModelUpdate=m=>{m===void 0&&typeof r=="string"&&r.match(/\./)&&(m=""),window.fromModel=!0,h(()=>_e(e,"value",m)),delete window.fromModel},n(()=>{let m=c();t.includes("unintrusive")&&document.activeElement.isSameNode(e)||e._x_forceModelUpdate(m)})});function Li(e,t,r,n){return h(()=>{if(r instanceof CustomEvent&&r.detail!==void 0)return r.detail??r.target.value;if(e.type==="checkbox")if(Array.isArray(n)){let i=t.includes("number")?Ft(r.target.value):r.target.value;return r.target.checked?n.concat([i]):n.filter(o=>!$i(o,i))}else return r.target.checked;else{if(e.tagName.toLowerCase()==="select"&&e.multiple)return t.includes("number")?Array.from(r.target.selectedOptions).map(i=>{let o=i.value||i.text;return Ft(o)}):Array.from(r.target.selectedOptions).map(i=>i.value||i.text);{let i=r.target.value;return t.includes("number")?Ft(i):t.includes("trim")?i.trim():i}}})}function Ft(e){let t=e?parseFloat(e):null;return Fi(t)?t:e}function $i(e,t){return e==t}function Fi(e){return!Array.isArray(e)&&!isNaN(e)}function pn(e){return e!==null&&typeof e=="object"&&typeof e.get=="function"&&typeof e.set=="function"}p("cloak",e=>queueMicrotask(()=>h(()=>e.removeAttribute(C("cloak")))));ve(()=>`[${C("init")}]`);p("init",B((e,{expression:t},{evaluate:r})=>typeof t=="string"?!!t.trim()&&r(t,{},!1):r(t,{},!1)));p("text",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{h(()=>{e.textContent=o})})})});p("html",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{h(()=>{e.innerHTML=o,e._x_ignoreSelf=!0,v(e),delete e._x_ignoreSelf})})})});te(De(":",Ie(C("bind:"))));var mn=(e,{value:t,modifiers:r,expression:n,original:i},{effect:o})=>{if(!t){let a={};Fr(a),x(e,n)(l=>{St(e,l,i)},{scope:a});return}if(t==="key")return ji(e,n);if(e._x_inlineBindings&&e._x_inlineBindings[t]&&e._x_inlineBindings[t].extract)return;let s=x(e,n);o(()=>s(a=>{a===void 0&&typeof n=="string"&&n.match(/\./)&&(a=""),h(()=>_e(e,t,a,r))}))};mn.inline=(e,{value:t,modifiers:r,expression:n})=>{t&&(e._x_inlineBindings||(e._x_inlineBindings={}),e._x_inlineBindings[t]={expression:n,extract:!1})};p("bind",mn);function ji(e,t){e._x_keyExpression=t}Ee(()=>`[${C("data")}]`);p("data",(e,{expression:t},{cleanup:r})=>{if(Ar(e))return;t=t===""?"{}":t;let n={};fe(n,e);let i={};Kr(i,n);let o=R(e,t,{scope:i});(o===void 0||o===!0)&&(o={}),fe(o,e);let s=T(o);Te(s);let a=N(e,s);s.init&&R(e,s.init),r(()=>{s.destroy&&R(e,s.destroy),a()})});p("show",(e,{modifiers:t,expression:r},{effect:n})=>{let i=x(e,r);e._x_doHide||(e._x_doHide=()=>{h(()=>{e.style.setProperty("display","none",t.includes("important")?"important":void 0)})}),e._x_doShow||(e._x_doShow=()=>{h(()=>{e.style.length===1&&e.style.display==="none"?e.removeAttribute("style"):e.style.removeProperty("display")})});let o=()=>{e._x_doHide(),e._x_isShown=!1},s=()=>{e._x_doShow(),e._x_isShown=!0},a=()=>setTimeout(s),c=me(d=>d?s():o(),d=>{typeof e._x_toggleAndCascadeWithTransitions=="function"?e._x_toggleAndCascadeWithTransitions(e,d,s,o):d?a():o()}),l,u=!0;n(()=>i(d=>{!u&&d===l||(t.includes("immediate")&&(d?a():o()),c(d),l=d,u=!1)}))});p("for",(e,{expression:t},{effect:r,cleanup:n})=>{let i=Ki(t),o=x(e,i.items),s=x(e,e._x_keyExpression||"index");e._x_prevKeys=[],e._x_lookup={},r(()=>Bi(e,i,o,s)),n(()=>{Object.values(e._x_lookup).forEach(a=>a.remove()),delete e._x_prevKeys,delete e._x_lookup})});function Bi(e,t,r,n){let i=s=>typeof s=="object"&&!Array.isArray(s),o=e;r(s=>{zi(s)&&s>=0&&(s=Array.from(Array(s).keys(),f=>f+1)),s===void 0&&(s=[]);let a=e._x_lookup,c=e._x_prevKeys,l=[],u=[];if(i(s))s=Object.entries(s).map(([f,g])=>{let b=hn(t,g,f,s);n(E=>u.push(E),{scope:{index:f,...b}}),l.push(b)});else for(let f=0;f<s.length;f++){let g=hn(t,s[f],f,s);n(b=>u.push(b),{scope:{index:f,...g}}),l.push(g)}let d=[],m=[],w=[],k=[];for(let f=0;f<c.length;f++){let g=c[f];u.indexOf(g)===-1&&w.push(g)}c=c.filter(f=>!w.includes(f));let be="template";for(let f=0;f<u.length;f++){let g=u[f],b=c.indexOf(g);if(b===-1)c.splice(f,0,g),d.push([be,f]);else if(b!==f){let E=c.splice(f,1)[0],A=c.splice(b-1,1)[0];c.splice(f,0,A),c.splice(b,0,E),m.push([E,A])}else k.push(g);be=g}for(let f=0;f<w.length;f++){let g=w[f];a[g]._x_effects&&a[g]._x_effects.forEach(we),a[g].remove(),a[g]=null,delete a[g]}for(let f=0;f<m.length;f++){let[g,b]=m[f],E=a[g],A=a[b],X=document.createElement("div");h(()=>{A||S('x-for ":key" is undefined or invalid',o),A.after(X),E.after(A),A._x_currentIfEl&&A.after(A._x_currentIfEl),X.before(E),E._x_currentIfEl&&E.after(E._x_currentIfEl),X.remove()}),A._x_refreshXForScope(l[u.indexOf(b)])}for(let f=0;f<d.length;f++){let[g,b]=d[f],E=g==="template"?o:a[g];E._x_currentIfEl&&(E=E._x_currentIfEl);let A=l[b],X=u[b],se=document.importNode(o.content,!0).firstElementChild,Bt=T(A);N(se,Bt,o),se._x_refreshXForScope=gn=>{Object.entries(gn).forEach(([xn,yn])=>{Bt[xn]=yn})},h(()=>{E.after(se),v(se)}),typeof X=="object"&&S("x-for key cannot be an object, it must be a string or an integer",o),a[X]=se}for(let f=0;f<k.length;f++)a[k[f]]._x_refreshXForScope(l[u.indexOf(k[f])]);o._x_prevKeys=u})}function Ki(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=/^\s*\(|\)\s*$/g,n=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,i=e.match(n);if(!i)return;let o={};o.items=i[2].trim();let s=i[1].replace(r,"").trim(),a=s.match(t);return a?(o.item=s.replace(t,"").trim(),o.index=a[1].trim(),a[2]&&(o.collection=a[2].trim())):o.item=s,o}function hn(e,t,r,n){let i={};return/^\[.*\]$/.test(e.item)&&Array.isArray(t)?e.item.replace("[","").replace("]","").split(",").map(s=>s.trim()).forEach((s,a)=>{i[s]=t[a]}):/^\{.*\}$/.test(e.item)&&!Array.isArray(t)&&typeof t=="object"?e.item.replace("{","").replace("}","").split(",").map(s=>s.trim()).forEach(s=>{i[s]=t[s]}):i[e.item]=t,e.index&&(i[e.index]=r),e.collection&&(i[e.collection]=n),i}function zi(e){return!Array.isArray(e)&&!isNaN(e)}function _n(){}_n.inline=(e,{expression:t},{cleanup:r})=>{let n=U(e);n._x_refs||(n._x_refs={}),n._x_refs[t]=e,r(()=>delete n._x_refs[t])};p("ref",_n);p("if",(e,{expression:t},{effect:r,cleanup:n})=>{let i=x(e,t),o=()=>{if(e._x_currentIfEl)return e._x_currentIfEl;let a=e.content.cloneNode(!0).firstElementChild;return N(a,{},e),h(()=>{e.after(a),v(a)}),e._x_currentIfEl=a,e._x_undoIf=()=>{O(a,c=>{c._x_effects&&c._x_effects.forEach(we)}),a.remove(),delete e._x_currentIfEl},a},s=()=>{e._x_undoIf&&(e._x_undoIf(),delete e._x_undoIf)};r(()=>i(a=>{a?o():s()})),n(()=>e._x_undoIf&&e._x_undoIf())});p("id",(e,{expression:t},{evaluate:r})=>{r(t).forEach(i=>ln(e,i))});te(De("@",Ie(C("on:"))));p("on",B((e,{value:t,modifiers:r,expression:n},{cleanup:i})=>{let o=n?x(e,n):()=>{};e.tagName.toLowerCase()==="template"&&(e._x_forwardEvents||(e._x_forwardEvents=[]),e._x_forwardEvents.includes(t)||e._x_forwardEvents.push(t));let s=oe(e,t,r,a=>{o(()=>{},{scope:{$event:a},params:[a]})});i(()=>s())}));Xe("Collapse","collapse","collapse");Xe("Intersect","intersect","intersect");Xe("Focus","trap","focus");Xe("Mask","mask","mask");function Xe(e,t,r){p(t,n=>S(`You can't use [x-${t}] without first installing the "${e}" plugin here: https://alpinejs.dev/plugins/${r}`,n))}j.setEvaluator(ht);j.setReactivityEngine({reactive:Je,effect:Jr,release:Yr,raw:_});var jt=j;window.Alpine=jt;queueMicrotask(()=>{jt.start()});})();
@@ -0,0 +1,5 @@
1+(()=>{var Ze=!1,Qe=!1,V=[],et=-1;function Kt(e){bn(e)}function bn(e){V.includes(e)||V.push(e),wn()}function we(e){let t=V.indexOf(e);t!==-1&&t>et&&V.splice(t,1)}function wn(){!Qe&&!Ze&&(Ze=!0,queueMicrotask(En))}function En(){Ze=!1,Qe=!0;for(let e=0;e<V.length;e++)V[e](),et=e;V.length=0,et=-1,Qe=!1}var T,D,L,rt,tt=!0;function zt(e){tt=!1,e(),tt=!0}function Ht(e){T=e.reactive,L=e.release,D=t=>e.effect(t,{scheduler:r=>{tt?Kt(r):r()}}),rt=e.raw}function nt(e){D=e}function Vt(e){let t=()=>{};return[n=>{let i=D(n);return e._x_effects||(e._x_effects=new Set,e._x_runEffects=()=>{e._x_effects.forEach(o=>o())}),e._x_effects.add(i),t=()=>{i!==void 0&&(e._x_effects.delete(i),L(i))},i},()=>{t()}]}function q(e,t,r={}){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:!0,composed:!0,cancelable:!0}))}function O(e,t){if(typeof ShadowRoot=="function"&&e instanceof ShadowRoot){Array.from(e.children).forEach(i=>O(i,t));return}let r=!1;if(t(e,()=>r=!0),r)return;let n=e.firstElementChild;for(;n;)O(n,t,!1),n=n.nextElementSibling}function S(e,...t){console.warn(`Alpine Warning: ${e}`,...t)}var qt=!1;function Ut(){qt&&S("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),qt=!0,document.body||S("Unable to initialize. Trying to load Alpine before `<body>` is available. Did you forget to add `defer` in Alpine's `<script>` tag?"),q(document,"alpine:init"),q(document,"alpine:initializing"),ce(),Qt(t=>v(t,O)),Q(t=>ae(t)),Se((t,r)=>{le(t,r).forEach(n=>n())});let e=t=>!U(t.parentElement,!0);Array.from(document.querySelectorAll(Jt())).filter(e).forEach(t=>{v(t)}),q(document,"alpine:initialized")}var it=[],Wt=[];function Gt(){return it.map(e=>e())}function Jt(){return it.concat(Wt).map(e=>e())}function Ee(e){it.push(e)}function ve(e){Wt.push(e)}function U(e,t=!1){return Z(e,r=>{if((t?Jt():Gt()).some(i=>r.matches(i)))return!0})}function Z(e,t){if(e){if(t(e))return e;if(e._x_teleportBack&&(e=e._x_teleportBack),!!e.parentElement)return Z(e.parentElement,t)}}function Yt(e){return Gt().some(t=>e.matches(t))}var Xt=[];function Zt(e){Xt.push(e)}function v(e,t=O,r=()=>{}){tr(()=>{t(e,(n,i)=>{r(n,i),Xt.forEach(o=>o(n,i)),le(n,n.attributes).forEach(o=>o()),n._x_ignore&&i()})})}function ae(e){O(e,t=>{ot(t),er(t)})}var rr=[],nr=[],ir=[];function Qt(e){ir.push(e)}function Q(e,t){typeof t=="function"?(e._x_cleanups||(e._x_cleanups=[]),e._x_cleanups.push(t)):(t=e,nr.push(t))}function Se(e){rr.push(e)}function Oe(e,t,r){e._x_attributeCleanups||(e._x_attributeCleanups={}),e._x_attributeCleanups[t]||(e._x_attributeCleanups[t]=[]),e._x_attributeCleanups[t].push(r)}function ot(e,t){e._x_attributeCleanups&&Object.entries(e._x_attributeCleanups).forEach(([r,n])=>{(t===void 0||t.includes(r))&&(n.forEach(i=>i()),delete e._x_attributeCleanups[r])})}function er(e){if(e._x_cleanups)for(;e._x_cleanups.length;)e._x_cleanups.pop()()}var at=new MutationObserver(ft),ct=!1;function ce(){at.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),ct=!0}function lt(){vn(),at.disconnect(),ct=!1}var ue=[],st=!1;function vn(){ue=ue.concat(at.takeRecords()),ue.length&&!st&&(st=!0,queueMicrotask(()=>{Sn(),st=!1}))}function Sn(){ft(ue),ue.length=0}function h(e){if(!ct)return e();lt();let t=e();return ce(),t}var ut=!1,Ae=[];function or(){ut=!0}function sr(){ut=!1,ft(Ae),Ae=[]}function ft(e){if(ut){Ae=Ae.concat(e);return}let t=[],r=[],n=new Map,i=new Map;for(let o=0;o<e.length;o++)if(!e[o].target._x_ignoreMutationObserver&&(e[o].type==="childList"&&(e[o].addedNodes.forEach(s=>s.nodeType===1&&t.push(s)),e[o].removedNodes.forEach(s=>s.nodeType===1&&r.push(s))),e[o].type==="attributes")){let s=e[o].target,a=e[o].attributeName,c=e[o].oldValue,l=()=>{n.has(s)||n.set(s,[]),n.get(s).push({name:a,value:s.getAttribute(a)})},u=()=>{i.has(s)||i.set(s,[]),i.get(s).push(a)};s.hasAttribute(a)&&c===null?l():s.hasAttribute(a)?(u(),l()):u()}i.forEach((o,s)=>{ot(s,o)}),n.forEach((o,s)=>{rr.forEach(a=>a(s,o))});for(let o of r)t.includes(o)||(nr.forEach(s=>s(o)),ae(o));t.forEach(o=>{o._x_ignoreSelf=!0,o._x_ignore=!0});for(let o of t)r.includes(o)||o.isConnected&&(delete o._x_ignoreSelf,delete o._x_ignore,ir.forEach(s=>s(o)),o._x_ignore=!0,o._x_ignoreSelf=!0);t.forEach(o=>{delete o._x_ignoreSelf,delete o._x_ignore}),t=null,r=null,n=null,i=null}function Ce(e){return F($(e))}function N(e,t,r){return e._x_dataStack=[t,...$(r||e)],()=>{e._x_dataStack=e._x_dataStack.filter(n=>n!==t)}}function $(e){return e._x_dataStack?e._x_dataStack:typeof ShadowRoot=="function"&&e instanceof ShadowRoot?$(e.host):e.parentNode?$(e.parentNode):[]}function F(e){let t=new Proxy({},{ownKeys:()=>Array.from(new Set(e.flatMap(r=>Object.keys(r)))),has:(r,n)=>e.some(i=>i.hasOwnProperty(n)),get:(r,n)=>(e.find(i=>{if(i.hasOwnProperty(n)){let o=Object.getOwnPropertyDescriptor(i,n);if(o.get&&o.get._x_alreadyBound||o.set&&o.set._x_alreadyBound)return!0;if((o.get||o.set)&&o.enumerable){let s=o.get,a=o.set,c=o;s=s&&s.bind(t),a=a&&a.bind(t),s&&(s._x_alreadyBound=!0),a&&(a._x_alreadyBound=!0),Object.defineProperty(i,n,{...c,get:s,set:a})}return!0}return!1})||{})[n],set:(r,n,i)=>{let o=e.find(s=>s.hasOwnProperty(n));return o?o[n]=i:e[e.length-1][n]=i,!0}});return t}function Te(e){let t=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,r=(n,i="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([o,{value:s,enumerable:a}])=>{if(a===!1||s===void 0)return;let c=i===""?o:`${i}.${o}`;typeof s=="object"&&s!==null&&s._x_interceptor?n[o]=s.initialize(e,c,o):t(s)&&s!==n&&!(s instanceof Element)&&r(s,c)})};return r(e)}function Re(e,t=()=>{}){let r={initialValue:void 0,_x_interceptor:!0,initialize(n,i,o){return e(this.initialValue,()=>An(n,i),s=>dt(n,i,s),i,o)}};return t(r),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let i=r.initialize.bind(r);r.initialize=(o,s,a)=>{let c=n.initialize(o,s,a);return r.initialValue=c,i(o,s,a)}}else r.initialValue=n;return r}}function An(e,t){return t.split(".").reduce((r,n)=>r[n],e)}function dt(e,t,r){if(typeof t=="string"&&(t=t.split(".")),t.length===1)e[t[0]]=r;else{if(t.length===0)throw error;return e[t[0]]||(e[t[0]]={}),dt(e[t[0]],t.slice(1),r)}}var ar={};function y(e,t){ar[e]=t}function fe(e,t){return Object.entries(ar).forEach(([r,n])=>{let i=null;function o(){if(i)return i;{let[s,a]=pt(t);return i={interceptor:Re,...s},Q(t,a),i}}Object.defineProperty(e,`$${r}`,{get(){return n(t,o())},enumerable:!1})}),e}function cr(e,t,r,...n){try{return r(...n)}catch(i){ee(i,e,t)}}function ee(e,t,r=void 0){Object.assign(e,{el:t,expression:r}),console.warn(`Alpine Expression Error: ${e.message}
2+
3+${r?'Expression: "'+r+`"
4+
5+`:""}`,t),setTimeout(()=>{throw e},0)}var Me=!0;function Pe(e){let t=Me;Me=!1;let r=e();return Me=t,r}function R(e,t,r={}){let n;return x(e,t)(i=>n=i,r),n}function x(...e){return lr(...e)}var lr=ht;function ur(e){lr=e}function ht(e,t){let r={};fe(r,e);let n=[r,...$(e)],i=typeof t=="function"?On(n,t):Tn(n,t,e);return cr.bind(null,e,t,i)}function On(e,t){return(r=()=>{},{scope:n={},params:i=[]}={})=>{let o=t.apply(F([n,...e]),i);Ne(r,o)}}var mt={};function Cn(e,t){if(mt[e])return mt[e];let r=Object.getPrototypeOf(async function(){}).constructor,n=/^[\n\s]*if.*\(.*\)/.test(e.trim())||/^(let|const)\s/.test(e.trim())?`(async()=>{ ${e} })()`:e,o=(()=>{try{return new r(["__self","scope"],`with (scope) { __self.result = ${n} }; __self.finished = true; return __self.result;`)}catch(s){return ee(s,t,e),Promise.resolve()}})();return mt[e]=o,o}function Tn(e,t,r){let n=Cn(t,r);return(i=()=>{},{scope:o={},params:s=[]}={})=>{n.result=void 0,n.finished=!1;let a=F([o,...e]);if(typeof n=="function"){let c=n(n,a).catch(l=>ee(l,r,t));n.finished?(Ne(i,n.result,a,s,r),n.result=void 0):c.then(l=>{Ne(i,l,a,s,r)}).catch(l=>ee(l,r,t)).finally(()=>n.result=void 0)}}}function Ne(e,t,r,n,i){if(Me&&typeof t=="function"){let o=t.apply(r,n);o instanceof Promise?o.then(s=>Ne(e,s,r,n)).catch(s=>ee(s,i,t)):e(o)}else typeof t=="object"&&t instanceof Promise?t.then(o=>e(o)):e(t)}var yt="x-";function C(e=""){return yt+e}function fr(e){yt=e}var _t={};function p(e,t){return _t[e]=t,{before(r){if(!_t[r]){console.warn("Cannot find directive `${directive}`. `${name}` will use the default order of execution");return}let n=W.indexOf(r);W.splice(n>=0?n:W.indexOf("DEFAULT"),0,e)}}}function le(e,t,r){if(t=Array.from(t),e._x_virtualDirectives){let o=Object.entries(e._x_virtualDirectives).map(([a,c])=>({name:a,value:c})),s=bt(o);o=o.map(a=>s.find(c=>c.name===a.name)?{name:`x-bind:${a.name}`,value:`"${a.value}"`}:a),t=t.concat(o)}let n={};return t.map(pr((o,s)=>n[o]=s)).filter(hr).map(Mn(n,r)).sort(Nn).map(o=>Rn(e,o))}function bt(e){return Array.from(e).map(pr()).filter(t=>!hr(t))}var gt=!1,de=new Map,dr=Symbol();function tr(e){gt=!0;let t=Symbol();dr=t,de.set(t,[]);let r=()=>{for(;de.get(t).length;)de.get(t).shift()();de.delete(t)},n=()=>{gt=!1,r()};e(r),n()}function pt(e){let t=[],r=a=>t.push(a),[n,i]=Vt(e);return t.push(i),[{Alpine:j,effect:n,cleanup:r,evaluateLater:x.bind(x,e),evaluate:R.bind(R,e)},()=>t.forEach(a=>a())]}function Rn(e,t){let r=()=>{},n=_t[t.type]||r,[i,o]=pt(e);Oe(e,t.original,o);let s=()=>{e._x_ignore||e._x_ignoreSelf||(n.inline&&n.inline(e,t,i),n=n.bind(n,e,t,i),gt?de.get(dr).push(n):n())};return s.runCleanups=o,s}var De=(e,t)=>({name:r,value:n})=>(r.startsWith(e)&&(r=r.replace(e,t)),{name:r,value:n}),Ie=e=>e;function pr(e=()=>{}){return({name:t,value:r})=>{let{name:n,value:i}=mr.reduce((o,s)=>s(o),{name:t,value:r});return n!==t&&e(n,t),{name:n,value:i}}}var mr=[];function te(e){mr.push(e)}function hr({name:e}){return _r().test(e)}var _r=()=>new RegExp(`^${yt}([^:^.]+)\\b`);function Mn(e,t){return({name:r,value:n})=>{let i=r.match(_r()),o=r.match(/:([a-zA-Z0-9\-:]+)/),s=r.match(/\.[^.\]]+(?=[^\]]*$)/g)||[],a=t||e[r]||r;return{type:i?i[1]:null,value:o?o[1]:null,modifiers:s.map(c=>c.replace(".","")),expression:n,original:a}}}var xt="DEFAULT",W=["ignore","ref","data","id","bind","init","for","model","modelable","transition","show","if",xt,"teleport"];function Nn(e,t){let r=W.indexOf(e.type)===-1?xt:e.type,n=W.indexOf(t.type)===-1?xt:t.type;return W.indexOf(r)-W.indexOf(n)}var wt=[],Et=!1;function re(e=()=>{}){return queueMicrotask(()=>{Et||setTimeout(()=>{ke()})}),new Promise(t=>{wt.push(()=>{e(),t()})})}function ke(){for(Et=!1;wt.length;)wt.shift()()}function gr(){Et=!0}function pe(e,t){return Array.isArray(t)?xr(e,t.join(" ")):typeof t=="object"&&t!==null?Pn(e,t):typeof t=="function"?pe(e,t()):xr(e,t)}function xr(e,t){let r=o=>o.split(" ").filter(Boolean),n=o=>o.split(" ").filter(s=>!e.classList.contains(s)).filter(Boolean),i=o=>(e.classList.add(...o),()=>{e.classList.remove(...o)});return t=t===!0?t="":t||"",i(n(t))}function Pn(e,t){let r=a=>a.split(" ").filter(Boolean),n=Object.entries(t).flatMap(([a,c])=>c?r(a):!1).filter(Boolean),i=Object.entries(t).flatMap(([a,c])=>c?!1:r(a)).filter(Boolean),o=[],s=[];return i.forEach(a=>{e.classList.contains(a)&&(e.classList.remove(a),s.push(a))}),n.forEach(a=>{e.classList.contains(a)||(e.classList.add(a),o.push(a))}),()=>{s.forEach(a=>e.classList.add(a)),o.forEach(a=>e.classList.remove(a))}}function G(e,t){return typeof t=="object"&&t!==null?Dn(e,t):In(e,t)}function Dn(e,t){let r={};return Object.entries(t).forEach(([n,i])=>{r[n]=e.style[n],n.startsWith("--")||(n=kn(n)),e.style.setProperty(n,i)}),setTimeout(()=>{e.style.length===0&&e.removeAttribute("style")}),()=>{G(e,r)}}function In(e,t){let r=e.getAttribute("style",t);return e.setAttribute("style",t),()=>{e.setAttribute("style",r||"")}}function kn(e){return e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase()}function me(e,t=()=>{}){let r=!1;return function(){r?t.apply(this,arguments):(r=!0,e.apply(this,arguments))}}p("transition",(e,{value:t,modifiers:r,expression:n},{evaluate:i})=>{typeof n=="function"&&(n=i(n)),n!==!1&&(!n||typeof n=="boolean"?$n(e,r,t):Ln(e,n,t))});function Ln(e,t,r){yr(e,pe,""),{enter:i=>{e._x_transition.enter.during=i},"enter-start":i=>{e._x_transition.enter.start=i},"enter-end":i=>{e._x_transition.enter.end=i},leave:i=>{e._x_transition.leave.during=i},"leave-start":i=>{e._x_transition.leave.start=i},"leave-end":i=>{e._x_transition.leave.end=i}}[r](t)}function $n(e,t,r){yr(e,G);let n=!t.includes("in")&&!t.includes("out")&&!r,i=n||t.includes("in")||["enter"].includes(r),o=n||t.includes("out")||["leave"].includes(r);t.includes("in")&&!n&&(t=t.filter((g,b)=>b<t.indexOf("out"))),t.includes("out")&&!n&&(t=t.filter((g,b)=>b>t.indexOf("out")));let s=!t.includes("opacity")&&!t.includes("scale"),a=s||t.includes("opacity"),c=s||t.includes("scale"),l=a?0:1,u=c?he(t,"scale",95)/100:1,d=he(t,"delay",0)/1e3,m=he(t,"origin","center"),w="opacity, transform",k=he(t,"duration",150)/1e3,be=he(t,"duration",75)/1e3,f="cubic-bezier(0.4, 0.0, 0.2, 1)";i&&(e._x_transition.enter.during={transformOrigin:m,transitionDelay:`${d}s`,transitionProperty:w,transitionDuration:`${k}s`,transitionTimingFunction:f},e._x_transition.enter.start={opacity:l,transform:`scale(${u})`},e._x_transition.enter.end={opacity:1,transform:"scale(1)"}),o&&(e._x_transition.leave.during={transformOrigin:m,transitionDelay:`${d}s`,transitionProperty:w,transitionDuration:`${be}s`,transitionTimingFunction:f},e._x_transition.leave.start={opacity:1,transform:"scale(1)"},e._x_transition.leave.end={opacity:l,transform:`scale(${u})`})}function yr(e,t,r={}){e._x_transition||(e._x_transition={enter:{during:r,start:r,end:r},leave:{during:r,start:r,end:r},in(n=()=>{},i=()=>{}){Le(e,t,{during:this.enter.during,start:this.enter.start,end:this.enter.end},n,i)},out(n=()=>{},i=()=>{}){Le(e,t,{during:this.leave.during,start:this.leave.start,end:this.leave.end},n,i)}})}window.Element.prototype._x_toggleAndCascadeWithTransitions=function(e,t,r,n){let i=document.visibilityState==="visible"?requestAnimationFrame:setTimeout,o=()=>i(r);if(t){e._x_transition&&(e._x_transition.enter||e._x_transition.leave)?e._x_transition.enter&&(Object.entries(e._x_transition.enter.during).length||Object.entries(e._x_transition.enter.start).length||Object.entries(e._x_transition.enter.end).length)?e._x_transition.in(r):o():e._x_transition?e._x_transition.in(r):o();return}e._x_hidePromise=e._x_transition?new Promise((s,a)=>{e._x_transition.out(()=>{},()=>s(n)),e._x_transitioning.beforeCancel(()=>a({isFromCancelledTransition:!0}))}):Promise.resolve(n),queueMicrotask(()=>{let s=br(e);s?(s._x_hideChildren||(s._x_hideChildren=[]),s._x_hideChildren.push(e)):i(()=>{let a=c=>{let l=Promise.all([c._x_hidePromise,...(c._x_hideChildren||[]).map(a)]).then(([u])=>u());return delete c._x_hidePromise,delete c._x_hideChildren,l};a(e).catch(c=>{if(!c.isFromCancelledTransition)throw c})})})};function br(e){let t=e.parentNode;if(t)return t._x_hidePromise?t:br(t)}function Le(e,t,{during:r,start:n,end:i}={},o=()=>{},s=()=>{}){if(e._x_transitioning&&e._x_transitioning.cancel(),Object.keys(r).length===0&&Object.keys(n).length===0&&Object.keys(i).length===0){o(),s();return}let a,c,l;Fn(e,{start(){a=t(e,n)},during(){c=t(e,r)},before:o,end(){a(),l=t(e,i)},after:s,cleanup(){c(),l()}})}function Fn(e,t){let r,n,i,o=me(()=>{h(()=>{r=!0,n||t.before(),i||(t.end(),ke()),t.after(),e.isConnected&&t.cleanup(),delete e._x_transitioning})});e._x_transitioning={beforeCancels:[],beforeCancel(s){this.beforeCancels.push(s)},cancel:me(function(){for(;this.beforeCancels.length;)this.beforeCancels.shift()();o()}),finish:o},h(()=>{t.start(),t.during()}),gr(),requestAnimationFrame(()=>{if(r)return;let s=Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""))*1e3,a=Number(getComputedStyle(e).transitionDelay.replace(/,.*/,"").replace("s",""))*1e3;s===0&&(s=Number(getComputedStyle(e).animationDuration.replace("s",""))*1e3),h(()=>{t.before()}),n=!0,requestAnimationFrame(()=>{r||(h(()=>{t.end()}),ke(),setTimeout(e._x_transitioning.finish,s+a),i=!0)})})}function he(e,t,r){if(e.indexOf(t)===-1)return r;let n=e[e.indexOf(t)+1];if(!n||t==="scale"&&isNaN(n))return r;if(t==="duration"||t==="delay"){let i=n.match(/([0-9]+)ms/);if(i)return i[1]}return t==="origin"&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[n,e[e.indexOf(t)+2]].join(" "):n}var I=!1;function B(e,t=()=>{}){return(...r)=>I?t(...r):e(...r)}function wr(e){return(...t)=>I&&e(...t)}function Er(e,t){e._x_dataStack&&(t._x_dataStack=e._x_dataStack,t.setAttribute("data-has-alpine-state",!0)),I=!0,Sr(()=>{v(t,(r,n)=>{n(r,()=>{})})}),I=!1}var vt=!1;function vr(e,t){t._x_dataStack||(t._x_dataStack=e._x_dataStack),I=!0,vt=!0,Sr(()=>{jn(t)}),I=!1,vt=!1}function jn(e){let t=!1;v(e,(n,i)=>{O(n,(o,s)=>{if(t&&Yt(o))return s();t=!0,i(o,s)})})}function Sr(e){let t=D;nt((r,n)=>{let i=t(r);return L(i),()=>{}}),e(),nt(t)}function Ar(e){return I?vt?!0:e.hasAttribute("data-has-alpine-state"):!1}function _e(e,t,r,n=[]){switch(e._x_bindings||(e._x_bindings=T({})),e._x_bindings[t]=r,t=n.includes("camel")?Wn(t):t,t){case"value":Bn(e,r);break;case"style":zn(e,r);break;case"class":Kn(e,r);break;case"selected":case"checked":Hn(e,t,r);break;default:Cr(e,t,r);break}}function Bn(e,t){if(e.type==="radio")e.attributes.value===void 0&&(e.value=t),window.fromModel&&(e.checked=Or(e.value,t));else if(e.type==="checkbox")Number.isInteger(t)?e.value=t:!Array.isArray(t)&&typeof t!="boolean"&&![null,void 0].includes(t)?e.value=String(t):Array.isArray(t)?e.checked=t.some(r=>Or(r,e.value)):e.checked=!!t;else if(e.tagName==="SELECT")Un(e,t);else{if(e.value===t)return;e.value=t===void 0?"":t}}function Kn(e,t){e._x_undoAddedClasses&&e._x_undoAddedClasses(),e._x_undoAddedClasses=pe(e,t)}function zn(e,t){e._x_undoAddedStyles&&e._x_undoAddedStyles(),e._x_undoAddedStyles=G(e,t)}function Hn(e,t,r){Cr(e,t,r),qn(e,t,r)}function Cr(e,t,r){[null,void 0,!1].includes(r)&&Gn(t)?e.removeAttribute(t):(Tr(t)&&(r=t),Vn(e,t,r))}function Vn(e,t,r){e.getAttribute(t)!=r&&e.setAttribute(t,r)}function qn(e,t,r){e[t]!==r&&(e[t]=r)}function Un(e,t){let r=[].concat(t).map(n=>n+"");Array.from(e.options).forEach(n=>{n.selected=r.includes(n.value)})}function Wn(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Or(e,t){return e==t}function Tr(e){return["disabled","checked","required","readonly","hidden","open","selected","autofocus","itemscope","multiple","novalidate","allowfullscreen","allowpaymentrequest","formnovalidate","autoplay","controls","loop","muted","playsinline","default","ismap","reversed","async","defer","nomodule"].includes(e)}function Gn(e){return!["aria-pressed","aria-checked","aria-expanded","aria-selected"].includes(e)}function Rr(e,t,r){return e._x_bindings&&e._x_bindings[t]!==void 0?e._x_bindings[t]:Nr(e,t,r)}function Mr(e,t,r,n=!0){if(e._x_bindings&&e._x_bindings[t]!==void 0)return e._x_bindings[t];if(e._x_inlineBindings&&e._x_inlineBindings[t]!==void 0){let i=e._x_inlineBindings[t];return i.extract=n,Pe(()=>R(e,i.expression))}return Nr(e,t,r)}function Nr(e,t,r){let n=e.getAttribute(t);return n===null?typeof r=="function"?r():r:n===""?!0:Tr(t)?!![t,"true"].includes(n):n}function $e(e,t){var r;return function(){var n=this,i=arguments,o=function(){r=null,e.apply(n,i)};clearTimeout(r),r=setTimeout(o,t)}}function Fe(e,t){let r;return function(){let n=this,i=arguments;r||(e.apply(n,i),r=!0,setTimeout(()=>r=!1,t))}}function je({get:e,set:t},{get:r,set:n}){let i=!0,o,s,a,c,l=D(()=>{let u,d;i?(u=e(),n(JSON.parse(JSON.stringify(u))),d=r(),i=!1):(u=e(),d=r(),a=JSON.stringify(u),c=JSON.stringify(d),a!==o?(d=r(),n(u),d=u):(t(JSON.parse(c??null)),u=d)),o=JSON.stringify(u),s=JSON.stringify(d)});return()=>{L(l)}}function Pr(e){(Array.isArray(e)?e:[e]).forEach(r=>r(j))}var J={},Dr=!1;function Ir(e,t){if(Dr||(J=T(J),Dr=!0),t===void 0)return J[e];J[e]=t,typeof t=="object"&&t!==null&&t.hasOwnProperty("init")&&typeof t.init=="function"&&J[e].init(),Te(J[e])}function kr(){return J}var Lr={};function $r(e,t){let r=typeof t!="function"?()=>t:t;return e instanceof Element?St(e,r()):(Lr[e]=r,()=>{})}function Fr(e){return Object.entries(Lr).forEach(([t,r])=>{Object.defineProperty(e,t,{get(){return(...n)=>r(...n)}})}),e}function St(e,t,r){let n=[];for(;n.length;)n.pop()();let i=Object.entries(t).map(([s,a])=>({name:s,value:a})),o=bt(i);return i=i.map(s=>o.find(a=>a.name===s.name)?{name:`x-bind:${s.name}`,value:`"${s.value}"`}:s),le(e,i,r).map(s=>{n.push(s.runCleanups),s()}),()=>{for(;n.length;)n.pop()()}}var jr={};function Br(e,t){jr[e]=t}function Kr(e,t){return Object.entries(jr).forEach(([r,n])=>{Object.defineProperty(e,r,{get(){return(...i)=>n.bind(t)(...i)},enumerable:!1})}),e}var Jn={get reactive(){return T},get release(){return L},get effect(){return D},get raw(){return rt},version:"3.13.0",flushAndStopDeferringMutations:sr,dontAutoEvaluateFunctions:Pe,disableEffectScheduling:zt,startObservingMutations:ce,stopObservingMutations:lt,setReactivityEngine:Ht,onAttributeRemoved:Oe,onAttributesAdded:Se,closestDataStack:$,skipDuringClone:B,onlyDuringClone:wr,addRootSelector:Ee,addInitSelector:ve,addScopeToNode:N,deferMutations:or,mapAttributes:te,evaluateLater:x,interceptInit:Zt,setEvaluator:ur,mergeProxies:F,extractProp:Mr,findClosest:Z,onElRemoved:Q,closestRoot:U,destroyTree:ae,interceptor:Re,transition:Le,setStyles:G,mutateDom:h,directive:p,entangle:je,throttle:Fe,debounce:$e,evaluate:R,initTree:v,nextTick:re,prefixed:C,prefix:fr,plugin:Pr,magic:y,store:Ir,start:Ut,clone:vr,cloneNode:Er,bound:Rr,$data:Ce,walk:O,data:Br,bind:$r},j=Jn;function At(e,t){let r=Object.create(null),n=e.split(",");for(let i=0;i<n.length;i++)r[n[i]]=!0;return t?i=>!!r[i.toLowerCase()]:i=>!!r[i]}var Yn="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly";var As=At(Yn+",async,autofocus,autoplay,controls,default,defer,disabled,hidden,loop,open,required,reversed,scoped,seamless,checked,muted,multiple,selected");var zr=Object.freeze({}),Os=Object.freeze([]);var Xn=Object.prototype.hasOwnProperty,ge=(e,t)=>Xn.call(e,t),K=Array.isArray,ne=e=>Hr(e)==="[object Map]";var Zn=e=>typeof e=="string",Be=e=>typeof e=="symbol",xe=e=>e!==null&&typeof e=="object";var Qn=Object.prototype.toString,Hr=e=>Qn.call(e),Ot=e=>Hr(e).slice(8,-1);var Ke=e=>Zn(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e;var ze=e=>{let t=Object.create(null);return r=>t[r]||(t[r]=e(r))},ei=/-(\w)/g,Cs=ze(e=>e.replace(ei,(t,r)=>r?r.toUpperCase():"")),ti=/\B([A-Z])/g,Ts=ze(e=>e.replace(ti,"-$1").toLowerCase()),Ct=ze(e=>e.charAt(0).toUpperCase()+e.slice(1)),Rs=ze(e=>e?`on${Ct(e)}`:""),Tt=(e,t)=>e!==t&&(e===e||t===t);var Rt=new WeakMap,ye=[],P,Y=Symbol("iterate"),Mt=Symbol("Map key iterate");function ri(e){return e&&e._isEffect===!0}function Jr(e,t=zr){ri(e)&&(e=e.raw);let r=ii(e,t);return t.lazy||r(),r}function Yr(e){e.active&&(Xr(e),e.options.onStop&&e.options.onStop(),e.active=!1)}var ni=0;function ii(e,t){let r=function(){if(!r.active)return e();if(!ye.includes(r)){Xr(r);try{return si(),ye.push(r),P=r,e()}finally{ye.pop(),Zr(),P=ye[ye.length-1]}}};return r.id=ni++,r.allowRecurse=!!t.allowRecurse,r._isEffect=!0,r.active=!0,r.raw=e,r.deps=[],r.options=t,r}function Xr(e){let{deps:t}=e;if(t.length){for(let r=0;r<t.length;r++)t[r].delete(e);t.length=0}}var ie=!0,Pt=[];function oi(){Pt.push(ie),ie=!1}function si(){Pt.push(ie),ie=!0}function Zr(){let e=Pt.pop();ie=e===void 0?!0:e}function M(e,t,r){if(!ie||P===void 0)return;let n=Rt.get(e);n||Rt.set(e,n=new Map);let i=n.get(r);i||n.set(r,i=new Set),i.has(P)||(i.add(P),P.deps.push(i),P.options.onTrack&&P.options.onTrack({effect:P,target:e,type:t,key:r}))}function H(e,t,r,n,i,o){let s=Rt.get(e);if(!s)return;let a=new Set,c=u=>{u&&u.forEach(d=>{(d!==P||d.allowRecurse)&&a.add(d)})};if(t==="clear")s.forEach(c);else if(r==="length"&&K(e))s.forEach((u,d)=>{(d==="length"||d>=n)&&c(u)});else switch(r!==void 0&&c(s.get(r)),t){case"add":K(e)?Ke(r)&&c(s.get("length")):(c(s.get(Y)),ne(e)&&c(s.get(Mt)));break;case"delete":K(e)||(c(s.get(Y)),ne(e)&&c(s.get(Mt)));break;case"set":ne(e)&&c(s.get(Y));break}let l=u=>{u.options.onTrigger&&u.options.onTrigger({effect:u,target:e,key:r,type:t,newValue:n,oldValue:i,oldTarget:o}),u.options.scheduler?u.options.scheduler(u):u()};a.forEach(l)}var ai=At("__proto__,__v_isRef,__isVue"),Qr=new Set(Object.getOwnPropertyNames(Symbol).map(e=>Symbol[e]).filter(Be)),ci=en();var li=en(!0);var Vr=ui();function ui(){let e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...r){let n=_(this);for(let o=0,s=this.length;o<s;o++)M(n,"get",o+"");let i=n[t](...r);return i===-1||i===!1?n[t](...r.map(_)):i}}),["push","pop","shift","unshift","splice"].forEach(t=>{e[t]=function(...r){oi();let n=_(this)[t].apply(this,r);return Zr(),n}}),e}function en(e=!1,t=!1){return function(n,i,o){if(i==="__v_isReactive")return!e;if(i==="__v_isReadonly")return e;if(i==="__v_raw"&&o===(e?t?Oi:on:t?Ai:nn).get(n))return n;let s=K(n);if(!e&&s&&ge(Vr,i))return Reflect.get(Vr,i,o);let a=Reflect.get(n,i,o);return(Be(i)?Qr.has(i):ai(i))||(e||M(n,"get",i),t)?a:Nt(a)?!s||!Ke(i)?a.value:a:xe(a)?e?sn(a):Je(a):a}}var fi=di();function di(e=!1){return function(r,n,i,o){let s=r[n];if(!e&&(i=_(i),s=_(s),!K(r)&&Nt(s)&&!Nt(i)))return s.value=i,!0;let a=K(r)&&Ke(n)?Number(n)<r.length:ge(r,n),c=Reflect.set(r,n,i,o);return r===_(o)&&(a?Tt(i,s)&&H(r,"set",n,i,s):H(r,"add",n,i)),c}}function pi(e,t){let r=ge(e,t),n=e[t],i=Reflect.deleteProperty(e,t);return i&&r&&H(e,"delete",t,void 0,n),i}function mi(e,t){let r=Reflect.has(e,t);return(!Be(t)||!Qr.has(t))&&M(e,"has",t),r}function hi(e){return M(e,"iterate",K(e)?"length":Y),Reflect.ownKeys(e)}var _i={get:ci,set:fi,deleteProperty:pi,has:mi,ownKeys:hi},gi={get:li,set(e,t){return console.warn(`Set operation on key "${String(t)}" failed: target is readonly.`,e),!0},deleteProperty(e,t){return console.warn(`Delete operation on key "${String(t)}" failed: target is readonly.`,e),!0}};var Dt=e=>xe(e)?Je(e):e,It=e=>xe(e)?sn(e):e,kt=e=>e,Ge=e=>Reflect.getPrototypeOf(e);function He(e,t,r=!1,n=!1){e=e.__v_raw;let i=_(e),o=_(t);t!==o&&!r&&M(i,"get",t),!r&&M(i,"get",o);let{has:s}=Ge(i),a=n?kt:r?It:Dt;if(s.call(i,t))return a(e.get(t));if(s.call(i,o))return a(e.get(o));e!==i&&e.get(t)}function Ve(e,t=!1){let r=this.__v_raw,n=_(r),i=_(e);return e!==i&&!t&&M(n,"has",e),!t&&M(n,"has",i),e===i?r.has(e):r.has(e)||r.has(i)}function qe(e,t=!1){return e=e.__v_raw,!t&&M(_(e),"iterate",Y),Reflect.get(e,"size",e)}function qr(e){e=_(e);let t=_(this);return Ge(t).has.call(t,e)||(t.add(e),H(t,"add",e,e)),this}function Ur(e,t){t=_(t);let r=_(this),{has:n,get:i}=Ge(r),o=n.call(r,e);o?rn(r,n,e):(e=_(e),o=n.call(r,e));let s=i.call(r,e);return r.set(e,t),o?Tt(t,s)&&H(r,"set",e,t,s):H(r,"add",e,t),this}function Wr(e){let t=_(this),{has:r,get:n}=Ge(t),i=r.call(t,e);i?rn(t,r,e):(e=_(e),i=r.call(t,e));let o=n?n.call(t,e):void 0,s=t.delete(e);return i&&H(t,"delete",e,void 0,o),s}function Gr(){let e=_(this),t=e.size!==0,r=ne(e)?new Map(e):new Set(e),n=e.clear();return t&&H(e,"clear",void 0,void 0,r),n}function Ue(e,t){return function(n,i){let o=this,s=o.__v_raw,a=_(s),c=t?kt:e?It:Dt;return!e&&M(a,"iterate",Y),s.forEach((l,u)=>n.call(i,c(l),c(u),o))}}function We(e,t,r){return function(...n){let i=this.__v_raw,o=_(i),s=ne(o),a=e==="entries"||e===Symbol.iterator&&s,c=e==="keys"&&s,l=i[e](...n),u=r?kt:t?It:Dt;return!t&&M(o,"iterate",c?Mt:Y),{next(){let{value:d,done:m}=l.next();return m?{value:d,done:m}:{value:a?[u(d[0]),u(d[1])]:u(d),done:m}},[Symbol.iterator](){return this}}}}function z(e){return function(...t){{let r=t[0]?`on key "${t[0]}" `:"";console.warn(`${Ct(e)} operation ${r}failed: target is readonly.`,_(this))}return e==="delete"?!1:this}}function xi(){let e={get(o){return He(this,o)},get size(){return qe(this)},has:Ve,add:qr,set:Ur,delete:Wr,clear:Gr,forEach:Ue(!1,!1)},t={get(o){return He(this,o,!1,!0)},get size(){return qe(this)},has:Ve,add:qr,set:Ur,delete:Wr,clear:Gr,forEach:Ue(!1,!0)},r={get(o){return He(this,o,!0)},get size(){return qe(this,!0)},has(o){return Ve.call(this,o,!0)},add:z("add"),set:z("set"),delete:z("delete"),clear:z("clear"),forEach:Ue(!0,!1)},n={get(o){return He(this,o,!0,!0)},get size(){return qe(this,!0)},has(o){return Ve.call(this,o,!0)},add:z("add"),set:z("set"),delete:z("delete"),clear:z("clear"),forEach:Ue(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(o=>{e[o]=We(o,!1,!1),r[o]=We(o,!0,!1),t[o]=We(o,!1,!0),n[o]=We(o,!0,!0)}),[e,r,t,n]}var[yi,bi,wi,Ei]=xi();function tn(e,t){let r=t?e?Ei:wi:e?bi:yi;return(n,i,o)=>i==="__v_isReactive"?!e:i==="__v_isReadonly"?e:i==="__v_raw"?n:Reflect.get(ge(r,i)&&i in n?r:n,i,o)}var vi={get:tn(!1,!1)};var Si={get:tn(!0,!1)};function rn(e,t,r){let n=_(r);if(n!==r&&t.call(e,n)){let i=Ot(e);console.warn(`Reactive ${i} contains both the raw and reactive versions of the same object${i==="Map"?" as keys":""}, which can lead to inconsistencies. Avoid differentiating between the raw and reactive versions of an object and only use the reactive version if possible.`)}}var nn=new WeakMap,Ai=new WeakMap,on=new WeakMap,Oi=new WeakMap;function Ci(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function Ti(e){return e.__v_skip||!Object.isExtensible(e)?0:Ci(Ot(e))}function Je(e){return e&&e.__v_isReadonly?e:an(e,!1,_i,vi,nn)}function sn(e){return an(e,!0,gi,Si,on)}function an(e,t,r,n,i){if(!xe(e))return console.warn(`value cannot be made reactive: ${String(e)}`),e;if(e.__v_raw&&!(t&&e.__v_isReactive))return e;let o=i.get(e);if(o)return o;let s=Ti(e);if(s===0)return e;let a=new Proxy(e,s===2?n:r);return i.set(e,a),a}function _(e){return e&&_(e.__v_raw)||e}function Nt(e){return Boolean(e&&e.__v_isRef===!0)}y("nextTick",()=>re);y("dispatch",e=>q.bind(q,e));y("watch",(e,{evaluateLater:t,effect:r})=>(n,i)=>{let o=t(n),s=!0,a,c=r(()=>o(l=>{JSON.stringify(l),s?a=l:queueMicrotask(()=>{i(l,a),a=l}),s=!1}));e._x_effects.delete(c)});y("store",kr);y("data",e=>Ce(e));y("root",e=>U(e));y("refs",e=>(e._x_refs_proxy||(e._x_refs_proxy=F(Ri(e))),e._x_refs_proxy));function Ri(e){let t=[],r=e;for(;r;)r._x_refs&&t.push(r._x_refs),r=r.parentNode;return t}var Lt={};function $t(e){return Lt[e]||(Lt[e]=0),++Lt[e]}function cn(e,t){return Z(e,r=>{if(r._x_ids&&r._x_ids[t])return!0})}function ln(e,t){e._x_ids||(e._x_ids={}),e._x_ids[t]||(e._x_ids[t]=$t(t))}y("id",e=>(t,r=null)=>{let n=cn(e,t),i=n?n._x_ids[t]:$t(t);return r?`${t}-${i}-${r}`:`${t}-${i}`});y("el",e=>e);un("Focus","focus","focus");un("Persist","persist","persist");function un(e,t,r){y(t,n=>S(`You can't use [$${directiveName}] without first installing the "${e}" plugin here: https://alpinejs.dev/plugins/${r}`,n))}p("modelable",(e,{expression:t},{effect:r,evaluateLater:n,cleanup:i})=>{let o=n(t),s=()=>{let u;return o(d=>u=d),u},a=n(`${t} = __placeholder`),c=u=>a(()=>{},{scope:{__placeholder:u}}),l=s();c(l),queueMicrotask(()=>{if(!e._x_model)return;e._x_removeModelListeners.default();let u=e._x_model.get,d=e._x_model.set,m=je({get(){return u()},set(w){d(w)}},{get(){return s()},set(w){c(w)}});i(m)})});var Mi=document.createElement("div");p("teleport",(e,{modifiers:t,expression:r},{cleanup:n})=>{e.tagName.toLowerCase()!=="template"&&S("x-teleport can only be used on a <template> tag",e);let i=B(()=>document.querySelector(r),()=>Mi)();i||S(`Cannot find x-teleport element for selector: "${r}"`);let o=e.content.cloneNode(!0).firstElementChild;e._x_teleport=o,o._x_teleportBack=e,e._x_forwardEvents&&e._x_forwardEvents.forEach(s=>{o.addEventListener(s,a=>{a.stopPropagation(),e.dispatchEvent(new a.constructor(a.type,a))})}),N(o,{},e),h(()=>{t.includes("prepend")?i.parentNode.insertBefore(o,i):t.includes("append")?i.parentNode.insertBefore(o,i.nextSibling):i.appendChild(o),v(o),o._x_ignore=!0}),n(()=>o.remove())});var fn=()=>{};fn.inline=(e,{modifiers:t},{cleanup:r})=>{t.includes("self")?e._x_ignoreSelf=!0:e._x_ignore=!0,r(()=>{t.includes("self")?delete e._x_ignoreSelf:delete e._x_ignore})};p("ignore",fn);p("effect",(e,{expression:t},{effect:r})=>r(x(e,t)));function oe(e,t,r,n){let i=e,o=c=>n(c),s={},a=(c,l)=>u=>l(c,u);if(r.includes("dot")&&(t=Ni(t)),r.includes("camel")&&(t=Pi(t)),r.includes("passive")&&(s.passive=!0),r.includes("capture")&&(s.capture=!0),r.includes("window")&&(i=window),r.includes("document")&&(i=document),r.includes("debounce")){let c=r[r.indexOf("debounce")+1]||"invalid-wait",l=Ye(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=$e(o,l)}if(r.includes("throttle")){let c=r[r.indexOf("throttle")+1]||"invalid-wait",l=Ye(c.split("ms")[0])?Number(c.split("ms")[0]):250;o=Fe(o,l)}return r.includes("prevent")&&(o=a(o,(c,l)=>{l.preventDefault(),c(l)})),r.includes("stop")&&(o=a(o,(c,l)=>{l.stopPropagation(),c(l)})),r.includes("self")&&(o=a(o,(c,l)=>{l.target===e&&c(l)})),(r.includes("away")||r.includes("outside"))&&(i=document,o=a(o,(c,l)=>{e.contains(l.target)||l.target.isConnected!==!1&&(e.offsetWidth<1&&e.offsetHeight<1||e._x_isShown!==!1&&c(l))})),r.includes("once")&&(o=a(o,(c,l)=>{c(l),i.removeEventListener(t,o,s)})),o=a(o,(c,l)=>{Ii(t)&&ki(l,r)||c(l)}),i.addEventListener(t,o,s),()=>{i.removeEventListener(t,o,s)}}function Ni(e){return e.replace(/-/g,".")}function Pi(e){return e.toLowerCase().replace(/-(\w)/g,(t,r)=>r.toUpperCase())}function Ye(e){return!Array.isArray(e)&&!isNaN(e)}function Di(e){return[" ","_"].includes(e)?e:e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}function Ii(e){return["keydown","keyup"].includes(e)}function ki(e,t){let r=t.filter(o=>!["window","document","prevent","stop","once","capture"].includes(o));if(r.includes("debounce")){let o=r.indexOf("debounce");r.splice(o,Ye((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.includes("throttle")){let o=r.indexOf("throttle");r.splice(o,Ye((r[o+1]||"invalid-wait").split("ms")[0])?2:1)}if(r.length===0||r.length===1&&dn(e.key).includes(r[0]))return!1;let i=["ctrl","shift","alt","meta","cmd","super"].filter(o=>r.includes(o));return r=r.filter(o=>!i.includes(o)),!(i.length>0&&i.filter(s=>((s==="cmd"||s==="super")&&(s="meta"),e[`${s}Key`])).length===i.length&&dn(e.key).includes(r[0]))}function dn(e){if(!e)return[];e=Di(e);let t={ctrl:"control",slash:"/",space:" ",spacebar:" ",cmd:"meta",esc:"escape",up:"arrow-up",down:"arrow-down",left:"arrow-left",right:"arrow-right",period:".",equal:"=",minus:"-",underscore:"_"};return t[e]=e,Object.keys(t).map(r=>{if(t[r]===e)return r}).filter(r=>r)}p("model",(e,{modifiers:t,expression:r},{effect:n,cleanup:i})=>{let o=e;t.includes("parent")&&(o=e.parentNode);let s=x(o,r),a;typeof r=="string"?a=x(o,`${r} = __placeholder`):typeof r=="function"&&typeof r()=="string"?a=x(o,`${r()} = __placeholder`):a=()=>{};let c=()=>{let m;return s(w=>m=w),pn(m)?m.get():m},l=m=>{let w;s(k=>w=k),pn(w)?w.set(m):a(()=>{},{scope:{__placeholder:m}})};typeof r=="string"&&e.type==="radio"&&h(()=>{e.hasAttribute("name")||e.setAttribute("name",r)});var u=e.tagName.toLowerCase()==="select"||["checkbox","radio"].includes(e.type)||t.includes("lazy")?"change":"input";let d=I?()=>{}:oe(e,u,t,m=>{l(Li(e,t,m,c()))});if(t.includes("fill")&&([null,""].includes(c())||e.type==="checkbox"&&Array.isArray(c()))&&e.dispatchEvent(new Event(u,{})),e._x_removeModelListeners||(e._x_removeModelListeners={}),e._x_removeModelListeners.default=d,i(()=>e._x_removeModelListeners.default()),e.form){let m=oe(e.form,"reset",[],w=>{re(()=>e._x_model&&e._x_model.set(e.value))});i(()=>m())}e._x_model={get(){return c()},set(m){l(m)}},e._x_forceModelUpdate=m=>{m===void 0&&typeof r=="string"&&r.match(/\./)&&(m=""),window.fromModel=!0,h(()=>_e(e,"value",m)),delete window.fromModel},n(()=>{let m=c();t.includes("unintrusive")&&document.activeElement.isSameNode(e)||e._x_forceModelUpdate(m)})});function Li(e,t,r,n){return h(()=>{if(r instanceof CustomEvent&&r.detail!==void 0)return r.detail??r.target.value;if(e.type==="checkbox")if(Array.isArray(n)){let i=t.includes("number")?Ft(r.target.value):r.target.value;return r.target.checked?n.concat([i]):n.filter(o=>!$i(o,i))}else return r.target.checked;else{if(e.tagName.toLowerCase()==="select"&&e.multiple)return t.includes("number")?Array.from(r.target.selectedOptions).map(i=>{let o=i.value||i.text;return Ft(o)}):Array.from(r.target.selectedOptions).map(i=>i.value||i.text);{let i=r.target.value;return t.includes("number")?Ft(i):t.includes("trim")?i.trim():i}}})}function Ft(e){let t=e?parseFloat(e):null;return Fi(t)?t:e}function $i(e,t){return e==t}function Fi(e){return!Array.isArray(e)&&!isNaN(e)}function pn(e){return e!==null&&typeof e=="object"&&typeof e.get=="function"&&typeof e.set=="function"}p("cloak",e=>queueMicrotask(()=>h(()=>e.removeAttribute(C("cloak")))));ve(()=>`[${C("init")}]`);p("init",B((e,{expression:t},{evaluate:r})=>typeof t=="string"?!!t.trim()&&r(t,{},!1):r(t,{},!1)));p("text",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{h(()=>{e.textContent=o})})})});p("html",(e,{expression:t},{effect:r,evaluateLater:n})=>{let i=n(t);r(()=>{i(o=>{h(()=>{e.innerHTML=o,e._x_ignoreSelf=!0,v(e),delete e._x_ignoreSelf})})})});te(De(":",Ie(C("bind:"))));var mn=(e,{value:t,modifiers:r,expression:n,original:i},{effect:o})=>{if(!t){let a={};Fr(a),x(e,n)(l=>{St(e,l,i)},{scope:a});return}if(t==="key")return ji(e,n);if(e._x_inlineBindings&&e._x_inlineBindings[t]&&e._x_inlineBindings[t].extract)return;let s=x(e,n);o(()=>s(a=>{a===void 0&&typeof n=="string"&&n.match(/\./)&&(a=""),h(()=>_e(e,t,a,r))}))};mn.inline=(e,{value:t,modifiers:r,expression:n})=>{t&&(e._x_inlineBindings||(e._x_inlineBindings={}),e._x_inlineBindings[t]={expression:n,extract:!1})};p("bind",mn);function ji(e,t){e._x_keyExpression=t}Ee(()=>`[${C("data")}]`);p("data",(e,{expression:t},{cleanup:r})=>{if(Ar(e))return;t=t===""?"{}":t;let n={};fe(n,e);let i={};Kr(i,n);let o=R(e,t,{scope:i});(o===void 0||o===!0)&&(o={}),fe(o,e);let s=T(o);Te(s);let a=N(e,s);s.init&&R(e,s.init),r(()=>{s.destroy&&R(e,s.destroy),a()})});p("show",(e,{modifiers:t,expression:r},{effect:n})=>{let i=x(e,r);e._x_doHide||(e._x_doHide=()=>{h(()=>{e.style.setProperty("display","none",t.includes("important")?"important":void 0)})}),e._x_doShow||(e._x_doShow=()=>{h(()=>{e.style.length===1&&e.style.display==="none"?e.removeAttribute("style"):e.style.removeProperty("display")})});let o=()=>{e._x_doHide(),e._x_isShown=!1},s=()=>{e._x_doShow(),e._x_isShown=!0},a=()=>setTimeout(s),c=me(d=>d?s():o(),d=>{typeof e._x_toggleAndCascadeWithTransitions=="function"?e._x_toggleAndCascadeWithTransitions(e,d,s,o):d?a():o()}),l,u=!0;n(()=>i(d=>{!u&&d===l||(t.includes("immediate")&&(d?a():o()),c(d),l=d,u=!1)}))});p("for",(e,{expression:t},{effect:r,cleanup:n})=>{let i=Ki(t),o=x(e,i.items),s=x(e,e._x_keyExpression||"index");e._x_prevKeys=[],e._x_lookup={},r(()=>Bi(e,i,o,s)),n(()=>{Object.values(e._x_lookup).forEach(a=>a.remove()),delete e._x_prevKeys,delete e._x_lookup})});function Bi(e,t,r,n){let i=s=>typeof s=="object"&&!Array.isArray(s),o=e;r(s=>{zi(s)&&s>=0&&(s=Array.from(Array(s).keys(),f=>f+1)),s===void 0&&(s=[]);let a=e._x_lookup,c=e._x_prevKeys,l=[],u=[];if(i(s))s=Object.entries(s).map(([f,g])=>{let b=hn(t,g,f,s);n(E=>u.push(E),{scope:{index:f,...b}}),l.push(b)});else for(let f=0;f<s.length;f++){let g=hn(t,s[f],f,s);n(b=>u.push(b),{scope:{index:f,...g}}),l.push(g)}let d=[],m=[],w=[],k=[];for(let f=0;f<c.length;f++){let g=c[f];u.indexOf(g)===-1&&w.push(g)}c=c.filter(f=>!w.includes(f));let be="template";for(let f=0;f<u.length;f++){let g=u[f],b=c.indexOf(g);if(b===-1)c.splice(f,0,g),d.push([be,f]);else if(b!==f){let E=c.splice(f,1)[0],A=c.splice(b-1,1)[0];c.splice(f,0,A),c.splice(b,0,E),m.push([E,A])}else k.push(g);be=g}for(let f=0;f<w.length;f++){let g=w[f];a[g]._x_effects&&a[g]._x_effects.forEach(we),a[g].remove(),a[g]=null,delete a[g]}for(let f=0;f<m.length;f++){let[g,b]=m[f],E=a[g],A=a[b],X=document.createElement("div");h(()=>{A||S('x-for ":key" is undefined or invalid',o),A.after(X),E.after(A),A._x_currentIfEl&&A.after(A._x_currentIfEl),X.before(E),E._x_currentIfEl&&E.after(E._x_currentIfEl),X.remove()}),A._x_refreshXForScope(l[u.indexOf(b)])}for(let f=0;f<d.length;f++){let[g,b]=d[f],E=g==="template"?o:a[g];E._x_currentIfEl&&(E=E._x_currentIfEl);let A=l[b],X=u[b],se=document.importNode(o.content,!0).firstElementChild,Bt=T(A);N(se,Bt,o),se._x_refreshXForScope=gn=>{Object.entries(gn).forEach(([xn,yn])=>{Bt[xn]=yn})},h(()=>{E.after(se),v(se)}),typeof X=="object"&&S("x-for key cannot be an object, it must be a string or an integer",o),a[X]=se}for(let f=0;f<k.length;f++)a[k[f]]._x_refreshXForScope(l[u.indexOf(k[f])]);o._x_prevKeys=u})}function Ki(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=/^\s*\(|\)\s*$/g,n=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,i=e.match(n);if(!i)return;let o={};o.items=i[2].trim();let s=i[1].replace(r,"").trim(),a=s.match(t);return a?(o.item=s.replace(t,"").trim(),o.index=a[1].trim(),a[2]&&(o.collection=a[2].trim())):o.item=s,o}function hn(e,t,r,n){let i={};return/^\[.*\]$/.test(e.item)&&Array.isArray(t)?e.item.replace("[","").replace("]","").split(",").map(s=>s.trim()).forEach((s,a)=>{i[s]=t[a]}):/^\{.*\}$/.test(e.item)&&!Array.isArray(t)&&typeof t=="object"?e.item.replace("{","").replace("}","").split(",").map(s=>s.trim()).forEach(s=>{i[s]=t[s]}):i[e.item]=t,e.index&&(i[e.index]=r),e.collection&&(i[e.collection]=n),i}function zi(e){return!Array.isArray(e)&&!isNaN(e)}function _n(){}_n.inline=(e,{expression:t},{cleanup:r})=>{let n=U(e);n._x_refs||(n._x_refs={}),n._x_refs[t]=e,r(()=>delete n._x_refs[t])};p("ref",_n);p("if",(e,{expression:t},{effect:r,cleanup:n})=>{let i=x(e,t),o=()=>{if(e._x_currentIfEl)return e._x_currentIfEl;let a=e.content.cloneNode(!0).firstElementChild;return N(a,{},e),h(()=>{e.after(a),v(a)}),e._x_currentIfEl=a,e._x_undoIf=()=>{O(a,c=>{c._x_effects&&c._x_effects.forEach(we)}),a.remove(),delete e._x_currentIfEl},a},s=()=>{e._x_undoIf&&(e._x_undoIf(),delete e._x_undoIf)};r(()=>i(a=>{a?o():s()})),n(()=>e._x_undoIf&&e._x_undoIf())});p("id",(e,{expression:t},{evaluate:r})=>{r(t).forEach(i=>ln(e,i))});te(De("@",Ie(C("on:"))));p("on",B((e,{value:t,modifiers:r,expression:n},{cleanup:i})=>{let o=n?x(e,n):()=>{};e.tagName.toLowerCase()==="template"&&(e._x_forwardEvents||(e._x_forwardEvents=[]),e._x_forwardEvents.includes(t)||e._x_forwardEvents.push(t));let s=oe(e,t,r,a=>{o(()=>{},{scope:{$event:a},params:[a]})});i(()=>s())}));Xe("Collapse","collapse","collapse");Xe("Intersect","intersect","intersect");Xe("Focus","trap","focus");Xe("Mask","mask","mask");function Xe(e,t,r){p(t,n=>S(`You can't use [x-${t}] without first installing the "${e}" plugin here: https://alpinejs.dev/plugins/${r}`,n))}j.setEvaluator(ht);j.setReactivityEngine({reactive:Je,effect:Jr,release:Yr,raw:_});var jt=j;window.Alpine=jt;queueMicrotask(()=>{jt.start()});})();
A internal/webui/public/libs/chart.js +20 -0 too large to show in the browser

too large to show in the browser view raw

A internal/webui/public/libs/htmx-sse.js +322 -0
@@ -0,0 +1,322 @@
1+/*
2+Server Sent Events Extension
3+============================
4+This extension adds support for Server Sent Events to htmx. See /www/extensions/sse.md for usage instructions.
5+
6+*/
7+
8+(function(){
9+
10+ /** @type {import("../htmx").HtmxInternalApi} */
11+ var api;
12+
13+ htmx.defineExtension("sse", {
14+
15+ /**
16+ * Init saves the provided reference to the internal HTMX API.
17+ *
18+ * @param {import("../htmx").HtmxInternalApi} api
19+ * @returns void
20+ */
21+ init: function(apiRef) {
22+ // store a reference to the internal API.
23+ api = apiRef;
24+
25+ // set a function in the public API for creating new EventSource objects
26+ if (htmx.createEventSource == undefined) {
27+ htmx.createEventSource = createEventSource;
28+ }
29+ },
30+
31+ /**
32+ * onEvent handles all events passed to this extension.
33+ *
34+ * @param {string} name
35+ * @param {Event} evt
36+ * @returns void
37+ */
38+ onEvent: function(name, evt) {
39+
40+ switch (name) {
41+
42+ // Try to remove remove an EventSource when elements are removed
43+ case "htmx:beforeCleanupElement":
44+ var internalData = api.getInternalData(evt.target)
45+ if (internalData.sseEventSource) {
46+ internalData.sseEventSource.close();
47+ }
48+ return;
49+
50+ // Try to create EventSources when elements are processed
51+ case "htmx:afterProcessNode":
52+ createEventSourceOnElement(evt.target);
53+ }
54+ }
55+ });
56+
57+ ///////////////////////////////////////////////
58+ // HELPER FUNCTIONS
59+ ///////////////////////////////////////////////
60+
61+
62+ /**
63+ * createEventSource is the default method for creating new EventSource objects.
64+ * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed.
65+ *
66+ * @param {string} url
67+ * @returns EventSource
68+ */
69+ function createEventSource(url) {
70+ return new EventSource(url, {withCredentials:true});
71+ }
72+
73+ function splitOnWhitespace(trigger) {
74+ return trigger.trim().split(/\s+/);
75+ }
76+
77+ function getLegacySSEURL(elt) {
78+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
79+ if (legacySSEValue) {
80+ var values = splitOnWhitespace(legacySSEValue);
81+ for (var i = 0; i < values.length; i++) {
82+ var value = values[i].split(/:(.+)/);
83+ if (value[0] === "connect") {
84+ return value[1];
85+ }
86+ }
87+ }
88+ }
89+
90+ function getLegacySSESwaps(elt) {
91+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
92+ var returnArr = [];
93+ if (legacySSEValue) {
94+ var values = splitOnWhitespace(legacySSEValue);
95+ for (var i = 0; i < values.length; i++) {
96+ var value = values[i].split(/:(.+)/);
97+ if (value[0] === "swap") {
98+ returnArr.push(value[1]);
99+ }
100+ }
101+ }
102+ return returnArr;
103+ }
104+
105+ /**
106+ * createEventSourceOnElement creates a new EventSource connection on the provided element.
107+ * If a usable EventSource already exists, then it is returned. If not, then a new EventSource
108+ * is created and stored in the element's internalData.
109+ * @param {HTMLElement} elt
110+ * @param {number} retryCount
111+ * @returns {EventSource | null}
112+ */
113+ function createEventSourceOnElement(elt, retryCount) {
114+
115+ if (elt == null) {
116+ return null;
117+ }
118+
119+ var internalData = api.getInternalData(elt);
120+
121+ // get URL from element's attribute
122+ var sseURL = api.getAttributeValue(elt, "sse-connect");
123+
124+
125+ if (sseURL == undefined) {
126+ var legacyURL = getLegacySSEURL(elt)
127+ if (legacyURL) {
128+ sseURL = legacyURL;
129+ } else {
130+ return null;
131+ }
132+ }
133+
134+ // Connect to the EventSource
135+ var source = htmx.createEventSource(sseURL);
136+ internalData.sseEventSource = source;
137+
138+ // Create event handlers
139+ source.onerror = function (err) {
140+
141+ // Log an error event
142+ api.triggerErrorEvent(elt, "htmx:sseError", {error:err, source:source});
143+
144+ // If parent no longer exists in the document, then clean up this EventSource
145+ if (maybeCloseSSESource(elt)) {
146+ return;
147+ }
148+
149+ // Otherwise, try to reconnect the EventSource
150+ if (source.readyState === EventSource.CLOSED) {
151+ retryCount = retryCount || 0;
152+ var timeout = Math.random() * (2 ^ retryCount) * 500;
153+ window.setTimeout(function() {
154+ createEventSourceOnElement(elt, Math.min(7, retryCount+1));
155+ }, timeout);
156+ }
157+ };
158+
159+ source.onopen = function (evt) {
160+ api.triggerEvent(elt, "htmx:sseOpen", {source: source});
161+ }
162+
163+ // Add message handlers for every `sse-swap` attribute
164+ queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function(child) {
165+
166+ var sseSwapAttr = api.getAttributeValue(child, "sse-swap");
167+ if (sseSwapAttr) {
168+ var sseEventNames = sseSwapAttr.split(",");
169+ } else {
170+ var sseEventNames = getLegacySSESwaps(child);
171+ }
172+
173+ for (var i = 0 ; i < sseEventNames.length ; i++) {
174+ var sseEventName = sseEventNames[i].trim();
175+ var listener = function(event) {
176+
177+ // If the parent is missing then close SSE and remove listener
178+ if (maybeCloseSSESource(elt)) {
179+ source.removeEventListener(sseEventName, listener);
180+ return;
181+ }
182+
183+ // swap the response into the DOM and trigger a notification
184+ swap(child, event.data);
185+ api.triggerEvent(elt, "htmx:sseMessage", event);
186+ };
187+
188+ // Register the new listener
189+ api.getInternalData(elt).sseEventListener = listener;
190+ source.addEventListener(sseEventName, listener);
191+ }
192+ });
193+
194+ // Add message handlers for every `hx-trigger="sse:*"` attribute
195+ queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function(child) {
196+
197+ var sseEventName = api.getAttributeValue(child, "hx-trigger");
198+ if (sseEventName == null) {
199+ return;
200+ }
201+
202+ // Only process hx-triggers for events with the "sse:" prefix
203+ if (sseEventName.slice(0, 4) != "sse:") {
204+ return;
205+ }
206+
207+ var listener = function(event) {
208+
209+ // If parent is missing, then close SSE and remove listener
210+ if (maybeCloseSSESource(elt)) {
211+ source.removeEventListener(sseEventName, listener);
212+ return;
213+ }
214+
215+ // Trigger events to be handled by the rest of htmx
216+ htmx.trigger(child, sseEventName, event);
217+ htmx.trigger(child, "htmx:sseMessage", event);
218+ }
219+
220+ // Register the new listener
221+ api.getInternalData(elt).sseEventListener = listener;
222+ source.addEventListener(sseEventName.slice(4), listener);
223+ });
224+ }
225+
226+ /**
227+ * maybeCloseSSESource confirms that the parent element still exists.
228+ * If not, then any associated SSE source is closed and the function returns true.
229+ *
230+ * @param {HTMLElement} elt
231+ * @returns boolean
232+ */
233+ function maybeCloseSSESource(elt) {
234+ if (!api.bodyContains(elt)) {
235+ var source = api.getInternalData(elt).sseEventSource;
236+ if (source != undefined) {
237+ source.close();
238+ // source = null
239+ return true;
240+ }
241+ }
242+ return false;
243+ }
244+
245+ /**
246+ * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
247+ *
248+ * @param {HTMLElement} elt
249+ * @param {string} attributeName
250+ */
251+ function queryAttributeOnThisOrChildren(elt, attributeName) {
252+
253+ var result = [];
254+
255+ // If the parent element also contains the requested attribute, then add it to the results too.
256+ if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-sse")) {
257+ result.push(elt);
258+ }
259+
260+ // Search all child nodes that match the requested attribute
261+ elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [hx-sse], [data-hx-sse]").forEach(function(node) {
262+ result.push(node);
263+ });
264+
265+ return result;
266+ }
267+
268+ /**
269+ * @param {HTMLElement} elt
270+ * @param {string} content
271+ */
272+ function swap(elt, content) {
273+
274+ api.withExtensions(elt, function(extension) {
275+ content = extension.transformResponse(content, null, elt);
276+ });
277+
278+ var swapSpec = api.getSwapSpecification(elt);
279+ var target = api.getTarget(elt);
280+ var settleInfo = api.makeSettleInfo(elt);
281+
282+ api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo);
283+
284+ settleInfo.elts.forEach(function (elt) {
285+ if (elt.classList) {
286+ elt.classList.add(htmx.config.settlingClass);
287+ }
288+ api.triggerEvent(elt, 'htmx:beforeSettle');
289+ });
290+
291+ // Handle settle tasks (with delay if requested)
292+ if (swapSpec.settleDelay > 0) {
293+ setTimeout(doSettle(settleInfo), swapSpec.settleDelay);
294+ } else {
295+ doSettle(settleInfo)();
296+ }
297+ }
298+
299+ /**
300+ * doSettle mirrors much of the functionality in htmx that
301+ * settles elements after their content has been swapped.
302+ * TODO: this should be published by htmx, and not duplicated here
303+ * @param {import("../htmx").HtmxSettleInfo} settleInfo
304+ * @returns () => void
305+ */
306+ function doSettle(settleInfo) {
307+
308+ return function() {
309+ settleInfo.tasks.forEach(function (task) {
310+ task.call();
311+ });
312+
313+ settleInfo.elts.forEach(function (elt) {
314+ if (elt.classList) {
315+ elt.classList.remove(htmx.config.settlingClass);
316+ }
317+ api.triggerEvent(elt, 'htmx:afterSettle');
318+ });
319+ }
320+ }
321+
322+})();⏎̸
@@ -0,0 +1,322 @@
1+/*
2+Server Sent Events Extension
3+============================
4+This extension adds support for Server Sent Events to htmx. See /www/extensions/sse.md for usage instructions.
5+
6+*/
7+
8+(function(){
9+
10+ /** @type {import("../htmx").HtmxInternalApi} */
11+ var api;
12+
13+ htmx.defineExtension("sse", {
14+
15+ /**
16+ * Init saves the provided reference to the internal HTMX API.
17+ *
18+ * @param {import("../htmx").HtmxInternalApi} api
19+ * @returns void
20+ */
21+ init: function(apiRef) {
22+ // store a reference to the internal API.
23+ api = apiRef;
24+
25+ // set a function in the public API for creating new EventSource objects
26+ if (htmx.createEventSource == undefined) {
27+ htmx.createEventSource = createEventSource;
28+ }
29+ },
30+
31+ /**
32+ * onEvent handles all events passed to this extension.
33+ *
34+ * @param {string} name
35+ * @param {Event} evt
36+ * @returns void
37+ */
38+ onEvent: function(name, evt) {
39+
40+ switch (name) {
41+
42+ // Try to remove remove an EventSource when elements are removed
43+ case "htmx:beforeCleanupElement":
44+ var internalData = api.getInternalData(evt.target)
45+ if (internalData.sseEventSource) {
46+ internalData.sseEventSource.close();
47+ }
48+ return;
49+
50+ // Try to create EventSources when elements are processed
51+ case "htmx:afterProcessNode":
52+ createEventSourceOnElement(evt.target);
53+ }
54+ }
55+ });
56+
57+ ///////////////////////////////////////////////
58+ // HELPER FUNCTIONS
59+ ///////////////////////////////////////////////
60+
61+
62+ /**
63+ * createEventSource is the default method for creating new EventSource objects.
64+ * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed.
65+ *
66+ * @param {string} url
67+ * @returns EventSource
68+ */
69+ function createEventSource(url) {
70+ return new EventSource(url, {withCredentials:true});
71+ }
72+
73+ function splitOnWhitespace(trigger) {
74+ return trigger.trim().split(/\s+/);
75+ }
76+
77+ function getLegacySSEURL(elt) {
78+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
79+ if (legacySSEValue) {
80+ var values = splitOnWhitespace(legacySSEValue);
81+ for (var i = 0; i < values.length; i++) {
82+ var value = values[i].split(/:(.+)/);
83+ if (value[0] === "connect") {
84+ return value[1];
85+ }
86+ }
87+ }
88+ }
89+
90+ function getLegacySSESwaps(elt) {
91+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
92+ var returnArr = [];
93+ if (legacySSEValue) {
94+ var values = splitOnWhitespace(legacySSEValue);
95+ for (var i = 0; i < values.length; i++) {
96+ var value = values[i].split(/:(.+)/);
97+ if (value[0] === "swap") {
98+ returnArr.push(value[1]);
99+ }
100+ }
101+ }
102+ return returnArr;
103+ }
104+
105+ /**
106+ * createEventSourceOnElement creates a new EventSource connection on the provided element.
107+ * If a usable EventSource already exists, then it is returned. If not, then a new EventSource
108+ * is created and stored in the element's internalData.
109+ * @param {HTMLElement} elt
110+ * @param {number} retryCount
111+ * @returns {EventSource | null}
112+ */
113+ function createEventSourceOnElement(elt, retryCount) {
114+
115+ if (elt == null) {
116+ return null;
117+ }
118+
119+ var internalData = api.getInternalData(elt);
120+
121+ // get URL from element's attribute
122+ var sseURL = api.getAttributeValue(elt, "sse-connect");
123+
124+
125+ if (sseURL == undefined) {
126+ var legacyURL = getLegacySSEURL(elt)
127+ if (legacyURL) {
128+ sseURL = legacyURL;
129+ } else {
130+ return null;
131+ }
132+ }
133+
134+ // Connect to the EventSource
135+ var source = htmx.createEventSource(sseURL);
136+ internalData.sseEventSource = source;
137+
138+ // Create event handlers
139+ source.onerror = function (err) {
140+
141+ // Log an error event
142+ api.triggerErrorEvent(elt, "htmx:sseError", {error:err, source:source});
143+
144+ // If parent no longer exists in the document, then clean up this EventSource
145+ if (maybeCloseSSESource(elt)) {
146+ return;
147+ }
148+
149+ // Otherwise, try to reconnect the EventSource
150+ if (source.readyState === EventSource.CLOSED) {
151+ retryCount = retryCount || 0;
152+ var timeout = Math.random() * (2 ^ retryCount) * 500;
153+ window.setTimeout(function() {
154+ createEventSourceOnElement(elt, Math.min(7, retryCount+1));
155+ }, timeout);
156+ }
157+ };
158+
159+ source.onopen = function (evt) {
160+ api.triggerEvent(elt, "htmx:sseOpen", {source: source});
161+ }
162+
163+ // Add message handlers for every `sse-swap` attribute
164+ queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function(child) {
165+
166+ var sseSwapAttr = api.getAttributeValue(child, "sse-swap");
167+ if (sseSwapAttr) {
168+ var sseEventNames = sseSwapAttr.split(",");
169+ } else {
170+ var sseEventNames = getLegacySSESwaps(child);
171+ }
172+
173+ for (var i = 0 ; i < sseEventNames.length ; i++) {
174+ var sseEventName = sseEventNames[i].trim();
175+ var listener = function(event) {
176+
177+ // If the parent is missing then close SSE and remove listener
178+ if (maybeCloseSSESource(elt)) {
179+ source.removeEventListener(sseEventName, listener);
180+ return;
181+ }
182+
183+ // swap the response into the DOM and trigger a notification
184+ swap(child, event.data);
185+ api.triggerEvent(elt, "htmx:sseMessage", event);
186+ };
187+
188+ // Register the new listener
189+ api.getInternalData(elt).sseEventListener = listener;
190+ source.addEventListener(sseEventName, listener);
191+ }
192+ });
193+
194+ // Add message handlers for every `hx-trigger="sse:*"` attribute
195+ queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function(child) {
196+
197+ var sseEventName = api.getAttributeValue(child, "hx-trigger");
198+ if (sseEventName == null) {
199+ return;
200+ }
201+
202+ // Only process hx-triggers for events with the "sse:" prefix
203+ if (sseEventName.slice(0, 4) != "sse:") {
204+ return;
205+ }
206+
207+ var listener = function(event) {
208+
209+ // If parent is missing, then close SSE and remove listener
210+ if (maybeCloseSSESource(elt)) {
211+ source.removeEventListener(sseEventName, listener);
212+ return;
213+ }
214+
215+ // Trigger events to be handled by the rest of htmx
216+ htmx.trigger(child, sseEventName, event);
217+ htmx.trigger(child, "htmx:sseMessage", event);
218+ }
219+
220+ // Register the new listener
221+ api.getInternalData(elt).sseEventListener = listener;
222+ source.addEventListener(sseEventName.slice(4), listener);
223+ });
224+ }
225+
226+ /**
227+ * maybeCloseSSESource confirms that the parent element still exists.
228+ * If not, then any associated SSE source is closed and the function returns true.
229+ *
230+ * @param {HTMLElement} elt
231+ * @returns boolean
232+ */
233+ function maybeCloseSSESource(elt) {
234+ if (!api.bodyContains(elt)) {
235+ var source = api.getInternalData(elt).sseEventSource;
236+ if (source != undefined) {
237+ source.close();
238+ // source = null
239+ return true;
240+ }
241+ }
242+ return false;
243+ }
244+
245+ /**
246+ * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
247+ *
248+ * @param {HTMLElement} elt
249+ * @param {string} attributeName
250+ */
251+ function queryAttributeOnThisOrChildren(elt, attributeName) {
252+
253+ var result = [];
254+
255+ // If the parent element also contains the requested attribute, then add it to the results too.
256+ if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-sse")) {
257+ result.push(elt);
258+ }
259+
260+ // Search all child nodes that match the requested attribute
261+ elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [hx-sse], [data-hx-sse]").forEach(function(node) {
262+ result.push(node);
263+ });
264+
265+ return result;
266+ }
267+
268+ /**
269+ * @param {HTMLElement} elt
270+ * @param {string} content
271+ */
272+ function swap(elt, content) {
273+
274+ api.withExtensions(elt, function(extension) {
275+ content = extension.transformResponse(content, null, elt);
276+ });
277+
278+ var swapSpec = api.getSwapSpecification(elt);
279+ var target = api.getTarget(elt);
280+ var settleInfo = api.makeSettleInfo(elt);
281+
282+ api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo);
283+
284+ settleInfo.elts.forEach(function (elt) {
285+ if (elt.classList) {
286+ elt.classList.add(htmx.config.settlingClass);
287+ }
288+ api.triggerEvent(elt, 'htmx:beforeSettle');
289+ });
290+
291+ // Handle settle tasks (with delay if requested)
292+ if (swapSpec.settleDelay > 0) {
293+ setTimeout(doSettle(settleInfo), swapSpec.settleDelay);
294+ } else {
295+ doSettle(settleInfo)();
296+ }
297+ }
298+
299+ /**
300+ * doSettle mirrors much of the functionality in htmx that
301+ * settles elements after their content has been swapped.
302+ * TODO: this should be published by htmx, and not duplicated here
303+ * @param {import("../htmx").HtmxSettleInfo} settleInfo
304+ * @returns () => void
305+ */
306+ function doSettle(settleInfo) {
307+
308+ return function() {
309+ settleInfo.tasks.forEach(function (task) {
310+ task.call();
311+ });
312+
313+ settleInfo.elts.forEach(function (elt) {
314+ if (elt.classList) {
315+ elt.classList.remove(htmx.config.settlingClass);
316+ }
317+ api.triggerEvent(elt, 'htmx:afterSettle');
318+ });
319+ }
320+ }
321+
322+})();⏎̸
A internal/webui/public/libs/htmx.min.js +1 -0 generated file: collapsed
A internal/webui/public/libs/iconoir.css +22 -0 too large to show in the browser

too large to show in the browser view raw

A internal/webui/public/site.webmanifest +1 -0
@@ -0,0 +1,1 @@
1+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}⏎̸
@@ -0,0 +1,1 @@
1+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}⏎̸
D package-lock.json +0 -991 generated file: collapsed
A pkg/utils/htmx/htmlfragments.go +42 -0
@@ -0,0 +1,42 @@
1+package htmx
2+
3+import (
4+ "bytes"
5+
6+ "github.com/PuerkitoBio/goquery"
7+
8+)
9+
10+// GetHTMLFragmentByID returns the HTML fragment with the specified id
11+func GetHTMLFragmentByID(id string, data interface{}, a *app.App, ac *app.Config) (string, error) {
12+ // 1. Render the template
13+ renderer, err := templating.GetHTMLRenderer("components.gohtml", ac.GetTemplateFS(), a)
14+ if err != nil {
15+ return "", err
16+ }
17+
18+ renderedHTML, err := renderer.Render(data, a)
19+ if err != nil {
20+ return "", err
21+ }
22+
23+ // 2. Parse the rendered HTML with goquery
24+ doc, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(renderedHTML)))
25+ if err != nil {
26+ return "", err
27+ }
28+
29+ // 3. Find the div with the specified id
30+ fragmentContent, err := doc.Find("#" + id).Html()
31+ if err != nil {
32+ return "", err
33+ }
34+
35+ if fragmentcontent == "" {
36+ return "", err
37+ }
38+
39+ return fragmentContent, nil
40+}
41+
42+
@@ -0,0 +1,42 @@
1+package htmx
2+
3+import (
4+ "bytes"
5+
6+ "github.com/PuerkitoBio/goquery"
7+
8+)
9+
10+// GetHTMLFragmentByID returns the HTML fragment with the specified id
11+func GetHTMLFragmentByID(id string, data interface{}, a *app.App, ac *app.Config) (string, error) {
12+ // 1. Render the template
13+ renderer, err := templating.GetHTMLRenderer("components.gohtml", ac.GetTemplateFS(), a)
14+ if err != nil {
15+ return "", err
16+ }
17+
18+ renderedHTML, err := renderer.Render(data, a)
19+ if err != nil {
20+ return "", err
21+ }
22+
23+ // 2. Parse the rendered HTML with goquery
24+ doc, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(renderedHTML)))
25+ if err != nil {
26+ return "", err
27+ }
28+
29+ // 3. Find the div with the specified id
30+ fragmentContent, err := doc.Find("#" + id).Html()
31+ if err != nil {
32+ return "", err
33+ }
34+
35+ if fragmentcontent == "" {
36+ return "", err
37+ }
38+
39+ return fragmentContent, nil
40+}
41+
42+

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close