diff --git a/Makefile b/Makefile
index 48734a3..812d3d4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,10 @@
.PHONY: tw-build tw-watch flags-copy assets server test db-reset fmt
tw-build:
- npm run tw:build
+ npm --prefix tailwind run tw:build
tw-watch:
- npm run tw:watch
+ npm --prefix tailwind run tw:watch
flags-copy:
mkdir -p web/static/vendor/flags && cp assets/flags/*.svg web/static/vendor/flags/
diff --git a/README.md b/README.md
index 0611d5c..e251b98 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# GoFiber MVC Boilerplate
-Boilerplate GoFiber MVC + HTMX + Flowbite + GORM, con auth server-rendered, area private/admin e mail sink in sviluppo.
+Boilerplate GoFiber MVC + HTMX + Tailwind + GORM, con auth server-rendered, area private/admin e mail sink in sviluppo.
## Setup Assets + Server
@@ -27,7 +27,6 @@ Private SPA (Quasar):
- build frontend private: `cd quasar/private_section && npm i && npm run build`
`make assets` esegue:
-- copia di `node_modules/flowbite/dist/flowbite.min.js` in `web/static/vendor/flowbite.js`
- build Tailwind in `web/static/css/app.css`
Dark mode globale:
diff --git a/codex-prompt/add-flowbite.txt b/codex-prompt/add-flowbite.txt
deleted file mode 100644
index 5a37817..0000000
--- a/codex-prompt/add-flowbite.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-TASK: Integra Flowbite (UI + JS behavior) e aggiungi Makefile per Tailwind CLI (build/watch). Uso più terminali: non aggiungere tool per runner multi-process.
-
-1) Dipendenze Node
-- Se non esiste package.json in root, crearlo.
-- Installare:
- - npm install -D @tailwindcss/cli tailwindcss
- - npm install flowbite
-
-2) Tailwind config
-- Creare tailwind.config.js con:
- content: [
- "./web/templates/**/*.{html,gohtml}",
- "./web/static/**/*.js",
- "./node_modules/flowbite/**/*.js"
- ],
- theme: { extend: {} },
- plugins: [ require("flowbite/plugin") ]
-
-3) CSS input
-- Creare ./assets/tailwind/input.css con:
- @import "tailwindcss";
-
-4) Scripts npm
-- In package.json aggiungere:
- "scripts": {
- "tw:build": "npx @tailwindcss/cli -i ./assets/tailwind/input.css -o ./web/static/css/app.css --minify",
- "tw:watch": "npx @tailwindcss/cli -i ./assets/tailwind/input.css -o ./web/static/css/app.css --watch"
- }
-
-5) Copia Flowbite JS
-- Creare directory web/static/vendor se manca
-- Copiare:
- node_modules/flowbite/dist/flowbite.min.js -> web/static/vendor/flowbite.js
-
-6) Layout
-- Aggiornare /web/templates/layout.html per includere:
-
-
-
-- Rimuovere dal layout riferimenti attivi al vecchio UI kit Svelte (ma non cancellare /ui-kit dal repo)
-
-7) Makefile
-- Creare/aggiornare Makefile con target:
- - tw-build: npm run tw:build
- - tw-watch: npm run tw:watch
- - flowbite-copy: mkdir -p web/static/vendor && cp node_modules/flowbite/dist/flowbite.min.js web/static/vendor/flowbite.js
- - assets: flowbite-copy tw-build
- - server: go run ./cmd/server
-- Non creare target che avvia più processi insieme.
-
-8) Partials Flowbite
-- Creare /web/templates/components:
- - navbar.html
- - modal.html
- - dropdown.html
- - tabs.html
- - collapse.html
-Con markup Flowbite + data-attributes standard, senza JS custom.
-
-9) Licenze
-- Creare /licenses/FLOWBITE-MIT.txt e THIRD_PARTY_NOTICES.md (Flowbite MIT, Tailwind MIT).
-
-10) README
-- Aggiornare README con istruzioni:
- Terminale 1: npm i && make assets && make tw-watch
- Terminale 2: make server
-
-Criteri:
-- make assets genera CSS e copia flowbite.js
-- modals/dropdowns Flowbite funzionano
-- progetto compilabile e avviabile.
diff --git a/codex-prompt/dark-mode.txt b/codex-prompt/dark-mode.txt
index a1fe956..d0500c2 100644
--- a/codex-prompt/dark-mode.txt
+++ b/codex-prompt/dark-mode.txt
@@ -1,4 +1,4 @@
-TASK: Aggiungere Dark Mode globale con toggle nel footer (Flowbite + Tailwind).
+TASK: Aggiungere Dark Mode globale con toggle nel footer (Tailwind).
Vincoli:
- Usare Tailwind dark mode con strategia "class" (non media)
@@ -6,13 +6,13 @@ Vincoli:
- Stato persistente con localStorage
- Default: se non c’è preferenza salvata, usare prefers-color-scheme
- Nessun framework JS aggiuntivo
-- Non rompere HTMX e Flowbite
+- Non rompere HTMX
- Accessibile (aria-label, stato, focus)
1) Tailwind config
- Aggiornare tailwind.config.js:
- impostare `darkMode: 'class'`
- - assicurarsi che content includa templates e node_modules/flowbite come già configurato
+ - assicurarsi che content includa templates e script statici come già configurato
2) JS globale
- Creare file /web/static/vendor/theme.js (o /web/static/js/theme.js se preferisci) con:
@@ -37,10 +37,10 @@ Vincoli:
- min-h-screen flex flex-col
- contenuto in main con flex-1
-4) Footer + toggle button (Flowbite style)
+4) Footer + toggle button (Tailwind style)
- Nel footer del layout aggiungere un bottone:
- posizionato a destra (o center se preferisci) con icona (testo va bene senza icone)
- - classi Flowbite/Tailwind:
+ - classi Tailwind:
- px-3 py-2 text-sm font-medium rounded-lg
- bg-gray-100 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700
- attributi accessibilità:
@@ -70,7 +70,7 @@ Non serve perfezione totale, ma assicurare leggibilità.
- Il tema persiste al reload
- Default segue prefers-color-scheme se non impostato manualmente
- Nessun flash di tema sbagliato (FOUC minimizzato)
-- Non rompe Flowbite JS, modals, dropdown e HTMX
+- Non rompe modals, dropdown e HTMX
- Accessibile: bottone focusable e aria-pressed aggiornato
Esegui:
diff --git a/codex-prompt/flowbite-convert.txt b/codex-prompt/flowbite-convert.txt
deleted file mode 100644
index 9d43bf6..0000000
--- a/codex-prompt/flowbite-convert.txt
+++ /dev/null
@@ -1,141 +0,0 @@
-TASK: Convertire tutti i template HTML esistenti per usare componenti Flowbite (markup + behavior JS) mantenendo logica MVC e HTMX.
-
-Non modificare controller, services, repo.
-Modificare solo template e layout.
-
--------------------------------------
-1) LAYOUT GLOBALE
--------------------------------------
-
-Aggiornare /web/templates/layout.html:
-
-- Layout container moderno Tailwind
-- Navbar Flowbite responsive con:
- - Logo/AppName a sinistra
- - Link:
- - Public: Login / Signup
- - Private: Dashboard / Users
- - Admin: Admin (solo se role=admin)
- - Dropdown utente con logout
-- Include:
-
-
-
-
-Struttura:
-- Navbar top
-- Container max-w-7xl mx-auto p-6
-- Footer minimale
-
--------------------------------------
-2) PUBLIC TEMPLATES
--------------------------------------
-
-Convertire:
-
-/web/templates/public/login.html
-/web/templates/public/signup.html
-/web/templates/public/forgot_password.html
-/web/templates/public/reset_password.html
-
-Usare:
-- Card Flowbite per form
-- Input Flowbite style
-- Button primary
-- Alert Flowbite per flash messages
-- Layout centrato verticalmente (flex items-center justify-center min-h-screen)
-
--------------------------------------
-3) PRIVATE USERS
--------------------------------------
-
-/web/templates/private/users/index.html
-
-- Header sezione con:
- - Titolo
- - Pulsante "Nuovo Utente" (modal Flowbite)
-- Search input Flowbite
-- Table Flowbite styled (striped, hover)
-- Pagination button Flowbite
-- Modal Flowbite per dettaglio utente
-
-Assicurarsi che:
-- fetch/get
-- target DOM update
-- swap HTML manuale
-rimangano funzionanti
-
--------------------------------------
-4) ADMIN
--------------------------------------
-
-/web/templates/admin/dashboard.html
-/web/templates/admin/users.html
-/web/templates/admin/audit_logs.html
-
-Usare:
-- Card summary (stats)
-- Table Flowbite
-- Badge per ruoli (admin = red, user = blue)
-- Tabs Flowbite se presenti più sezioni
-
--------------------------------------
-5) FLASH MESSAGES
--------------------------------------
-
-Creare partial:
-- /web/templates/components/flash.html
-
-Usare Flowbite alert component:
-- success -> green
-- error -> red
-- warning -> yellow
-
-Includere in layout sopra {{embed}}
-
--------------------------------------
-6) MODAL STANDARD
--------------------------------------
-
-Creare partial riusabile:
-/web/templates/components/modal.html
-
-Markup Flowbite standard con:
-- id dinamico
-- header con titolo
-- body slot
-- footer slot opzionale
-- data-modal-toggle attributes
-
-Usare nelle pagine private.
-
--------------------------------------
-7) ACCESSIBILITÀ
--------------------------------------
-
-- Usare aria attributes corretti come in documentazione Flowbite
-- Non rompere keyboard interaction
-- Mantenere form method e csrf se presente
-
--------------------------------------
-8) RESPONSIVE DESIGN
--------------------------------------
-
-- Navbar collapse mobile
-- Table scrollable mobile
-- Forms full width mobile
-
--------------------------------------
-9) CRITERI DI ACCETTAZIONE
--------------------------------------
-
-- Tutte le pagine hanno layout moderno Flowbite
-- Modals funzionano
-- Dropdown funzionano
-- Navbar responsive
-- HTMX partial update continua a funzionare
-- Nessuna modifica backend richiesta
-- Nessun errore JS in console
-
-Scrivere codice pulito, leggibile, con commenti minimi.
-Non eliminare logica Go template esistente.
diff --git a/licenses/FLOWBITE-MIT.txt b/licenses/FLOWBITE-MIT.txt
deleted file mode 100644
index d7bc06a..0000000
--- a/licenses/FLOWBITE-MIT.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2020 Themesberg
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/package.json b/package.json
deleted file mode 100644
index e799cbf..0000000
--- a/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "name": "trustcontact-flowbite",
- "private": true,
- "version": "1.0.0",
- "scripts": {
- "tw:build": "npx @tailwindcss/cli -i ./assets/tailwind/input.css -o ./web/static/css/app.css --minify",
- "tw:watch": "npx @tailwindcss/cli -i ./assets/tailwind/input.css -o ./web/static/css/app.css --watch"
- },
- "devDependencies": {
- "@tailwindcss/cli": "^4.1.13",
- "tailwindcss": "^4.1.13"
- }
-}
diff --git a/assets/tailwind/input.css b/tailwind/input.css
similarity index 100%
rename from assets/tailwind/input.css
rename to tailwind/input.css
diff --git a/package-lock.json b/tailwind/package-lock.json
similarity index 99%
rename from package-lock.json
rename to tailwind/package-lock.json
index 516a22d..5c76620 100644
--- a/package-lock.json
+++ b/tailwind/package-lock.json
@@ -1,11 +1,11 @@
{
- "name": "trustcontact-flowbite",
+ "name": "trustcontact",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "trustcontact-flowbite",
+ "name": "trustcontact",
"version": "1.0.0",
"devDependencies": {
"@tailwindcss/cli": "^4.1.13",
diff --git a/tailwind/package.json b/tailwind/package.json
new file mode 100644
index 0000000..c45aefe
--- /dev/null
+++ b/tailwind/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "trustcontact",
+ "private": true,
+ "version": "1.0.0",
+ "scripts": {
+ "tw:build": "npx @tailwindcss/cli -i ./input.css -o ../web/static/css/app.css -c ./tailwind.config.js --minify",
+ "tw:watch": "npx @tailwindcss/cli -i ./input.css -o ../web/static/css/app.css -c ./tailwind.config.js --watch"
+ },
+ "devDependencies": {
+ "@tailwindcss/cli": "^4.1.13",
+ "tailwindcss": "^4.1.13"
+ }
+}
diff --git a/tailwind/pnpm-lock.yaml b/tailwind/pnpm-lock.yaml
new file mode 100644
index 0000000..7ec1012
--- /dev/null
+++ b/tailwind/pnpm-lock.yaml
@@ -0,0 +1,562 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ '@tailwindcss/cli':
+ specifier: ^4.1.13
+ version: 4.2.1
+ tailwindcss:
+ specifier: ^4.1.13
+ version: 4.2.1
+
+packages:
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@parcel/watcher-android-arm64@2.5.6':
+ resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ '@parcel/watcher-darwin-arm64@2.5.6':
+ resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@parcel/watcher-darwin-x64@2.5.6':
+ resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@parcel/watcher-freebsd-x64@2.5.6':
+ resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@parcel/watcher-linux-arm-glibc@2.5.6':
+ resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm-musl@2.5.6':
+ resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm64-glibc@2.5.6':
+ resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@parcel/watcher-linux-arm64-musl@2.5.6':
+ resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@parcel/watcher-linux-x64-glibc@2.5.6':
+ resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@parcel/watcher-linux-x64-musl@2.5.6':
+ resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@parcel/watcher-win32-arm64@2.5.6':
+ resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@parcel/watcher-win32-ia32@2.5.6':
+ resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@parcel/watcher-win32-x64@2.5.6':
+ resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==}
+ engines: {node: '>= 10.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@parcel/watcher@2.5.6':
+ resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==}
+ engines: {node: '>= 10.0.0'}
+
+ '@tailwindcss/cli@4.2.1':
+ resolution: {integrity: sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==}
+ hasBin: true
+
+ '@tailwindcss/node@4.2.1':
+ resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==}
+
+ '@tailwindcss/oxide-android-arm64@4.2.1':
+ resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [android]
+
+ '@tailwindcss/oxide-darwin-arm64@4.2.1':
+ resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-darwin-x64@4.2.1':
+ resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@tailwindcss/oxide-freebsd-x64@4.2.1':
+ resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1':
+ resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==}
+ engines: {node: '>= 20'}
+ cpu: [arm]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.2.1':
+ resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.2.1':
+ resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.2.1':
+ resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-linux-x64-musl@4.2.1':
+ resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+
+ '@tailwindcss/oxide-wasm32-wasi@4.2.1':
+ resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.2.1':
+ resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.2.1':
+ resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [win32]
+
+ '@tailwindcss/oxide@4.2.1':
+ resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==}
+ engines: {node: '>= 20'}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ enhanced-resolve@5.20.0:
+ resolution: {integrity: sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==}
+ engines: {node: '>=10.13.0'}
+
+ graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ jiti@2.6.1:
+ resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
+ hasBin: true
+
+ lightningcss-android-arm64@1.31.1:
+ resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
+ lightningcss-darwin-arm64@1.31.1:
+ resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ lightningcss-darwin-x64@1.31.1:
+ resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ lightningcss-freebsd-x64@1.31.1:
+ resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ lightningcss-linux-arm-gnueabihf@1.31.1:
+ resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
+ lightningcss-linux-arm64-gnu@1.31.1:
+ resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-arm64-musl@1.31.1:
+ resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ lightningcss-linux-x64-gnu@1.31.1:
+ resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-linux-x64-musl@1.31.1:
+ resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.31.1:
+ resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-x64-msvc@1.31.1:
+ resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
+ lightningcss@1.31.1:
+ resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
+ engines: {node: '>= 12.0.0'}
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ mri@1.2.0:
+ resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
+ engines: {node: '>=4'}
+
+ node-addon-api@7.1.1:
+ resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ tailwindcss@4.2.1:
+ resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==}
+
+ tapable@2.3.0:
+ resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
+ engines: {node: '>=6'}
+
+snapshots:
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ '@parcel/watcher-android-arm64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-darwin-arm64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-darwin-x64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-freebsd-x64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm-glibc@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm-musl@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm64-glibc@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-arm64-musl@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-x64-glibc@2.5.6':
+ optional: true
+
+ '@parcel/watcher-linux-x64-musl@2.5.6':
+ optional: true
+
+ '@parcel/watcher-win32-arm64@2.5.6':
+ optional: true
+
+ '@parcel/watcher-win32-ia32@2.5.6':
+ optional: true
+
+ '@parcel/watcher-win32-x64@2.5.6':
+ optional: true
+
+ '@parcel/watcher@2.5.6':
+ dependencies:
+ detect-libc: 2.1.2
+ is-glob: 4.0.3
+ node-addon-api: 7.1.1
+ picomatch: 4.0.3
+ optionalDependencies:
+ '@parcel/watcher-android-arm64': 2.5.6
+ '@parcel/watcher-darwin-arm64': 2.5.6
+ '@parcel/watcher-darwin-x64': 2.5.6
+ '@parcel/watcher-freebsd-x64': 2.5.6
+ '@parcel/watcher-linux-arm-glibc': 2.5.6
+ '@parcel/watcher-linux-arm-musl': 2.5.6
+ '@parcel/watcher-linux-arm64-glibc': 2.5.6
+ '@parcel/watcher-linux-arm64-musl': 2.5.6
+ '@parcel/watcher-linux-x64-glibc': 2.5.6
+ '@parcel/watcher-linux-x64-musl': 2.5.6
+ '@parcel/watcher-win32-arm64': 2.5.6
+ '@parcel/watcher-win32-ia32': 2.5.6
+ '@parcel/watcher-win32-x64': 2.5.6
+
+ '@tailwindcss/cli@4.2.1':
+ dependencies:
+ '@parcel/watcher': 2.5.6
+ '@tailwindcss/node': 4.2.1
+ '@tailwindcss/oxide': 4.2.1
+ enhanced-resolve: 5.20.0
+ mri: 1.2.0
+ picocolors: 1.1.1
+ tailwindcss: 4.2.1
+
+ '@tailwindcss/node@4.2.1':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.20.0
+ jiti: 2.6.1
+ lightningcss: 1.31.1
+ magic-string: 0.30.21
+ source-map-js: 1.2.1
+ tailwindcss: 4.2.1
+
+ '@tailwindcss/oxide-android-arm64@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-arm64@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-darwin-x64@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-freebsd-x64@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-gnu@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-linux-arm64-musl@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-gnu@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-linux-x64-musl@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-wasm32-wasi@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-win32-arm64-msvc@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide-win32-x64-msvc@4.2.1':
+ optional: true
+
+ '@tailwindcss/oxide@4.2.1':
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.2.1
+ '@tailwindcss/oxide-darwin-arm64': 4.2.1
+ '@tailwindcss/oxide-darwin-x64': 4.2.1
+ '@tailwindcss/oxide-freebsd-x64': 4.2.1
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1
+ '@tailwindcss/oxide-linux-arm64-musl': 4.2.1
+ '@tailwindcss/oxide-linux-x64-gnu': 4.2.1
+ '@tailwindcss/oxide-linux-x64-musl': 4.2.1
+ '@tailwindcss/oxide-wasm32-wasi': 4.2.1
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1
+ '@tailwindcss/oxide-win32-x64-msvc': 4.2.1
+
+ detect-libc@2.1.2: {}
+
+ enhanced-resolve@5.20.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ tapable: 2.3.0
+
+ graceful-fs@4.2.11: {}
+
+ is-extglob@2.1.1: {}
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ jiti@2.6.1: {}
+
+ lightningcss-android-arm64@1.31.1:
+ optional: true
+
+ lightningcss-darwin-arm64@1.31.1:
+ optional: true
+
+ lightningcss-darwin-x64@1.31.1:
+ optional: true
+
+ lightningcss-freebsd-x64@1.31.1:
+ optional: true
+
+ lightningcss-linux-arm-gnueabihf@1.31.1:
+ optional: true
+
+ lightningcss-linux-arm64-gnu@1.31.1:
+ optional: true
+
+ lightningcss-linux-arm64-musl@1.31.1:
+ optional: true
+
+ lightningcss-linux-x64-gnu@1.31.1:
+ optional: true
+
+ lightningcss-linux-x64-musl@1.31.1:
+ optional: true
+
+ lightningcss-win32-arm64-msvc@1.31.1:
+ optional: true
+
+ lightningcss-win32-x64-msvc@1.31.1:
+ optional: true
+
+ lightningcss@1.31.1:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.31.1
+ lightningcss-darwin-arm64: 1.31.1
+ lightningcss-darwin-x64: 1.31.1
+ lightningcss-freebsd-x64: 1.31.1
+ lightningcss-linux-arm-gnueabihf: 1.31.1
+ lightningcss-linux-arm64-gnu: 1.31.1
+ lightningcss-linux-arm64-musl: 1.31.1
+ lightningcss-linux-x64-gnu: 1.31.1
+ lightningcss-linux-x64-musl: 1.31.1
+ lightningcss-win32-arm64-msvc: 1.31.1
+ lightningcss-win32-x64-msvc: 1.31.1
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ mri@1.2.0: {}
+
+ node-addon-api@7.1.1: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@4.0.3: {}
+
+ source-map-js@1.2.1: {}
+
+ tailwindcss@4.2.1: {}
+
+ tapable@2.3.0: {}
diff --git a/tailwind.config.js b/tailwind/tailwind.config.js
similarity index 100%
rename from tailwind.config.js
rename to tailwind/tailwind.config.js
diff --git a/web/static/css/app.css b/web/static/css/app.css
index 4b85749..7e00053 100644
--- a/web/static/css/app.css
+++ b/web/static/css/app.css
@@ -1,1186 +1,2 @@
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
-@layer properties;
-@layer theme, base, components, utilities;
-@layer theme {
- :root, :host {
- --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
- "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
- "Courier New", monospace;
- --color-red-50: oklch(97.1% 0.013 17.38);
- --color-red-200: oklch(88.5% 0.062 18.334);
- --color-red-300: oklch(80.8% 0.114 19.571);
- --color-red-500: oklch(63.7% 0.237 25.331);
- --color-red-700: oklch(50.5% 0.213 27.518);
- --color-red-800: oklch(44.4% 0.177 26.899);
- --color-red-900: oklch(39.6% 0.141 25.723);
- --color-yellow-50: oklch(98.7% 0.026 102.212);
- --color-yellow-200: oklch(94.5% 0.129 101.54);
- --color-yellow-300: oklch(90.5% 0.182 98.111);
- --color-yellow-700: oklch(55.4% 0.135 66.442);
- --color-yellow-800: oklch(47.6% 0.114 61.907);
- --color-yellow-900: oklch(42.1% 0.095 57.708);
- --color-green-50: oklch(98.2% 0.018 155.826);
- --color-green-200: oklch(92.5% 0.084 155.995);
- --color-green-300: oklch(87.1% 0.15 154.449);
- --color-green-800: oklch(44.8% 0.119 151.328);
- --color-green-900: oklch(39.3% 0.095 152.535);
- --color-blue-50: oklch(97% 0.014 254.604);
- --color-blue-100: oklch(93.2% 0.032 255.585);
- --color-blue-200: oklch(88.2% 0.059 254.128);
- --color-blue-300: oklch(80.9% 0.105 251.813);
- --color-blue-400: oklch(70.7% 0.165 254.624);
- --color-blue-500: oklch(62.3% 0.214 259.815);
- --color-blue-700: oklch(48.8% 0.243 264.376);
- --color-blue-800: oklch(42.4% 0.199 265.638);
- --color-blue-900: oklch(37.9% 0.146 265.522);
- --color-gray-50: oklch(98.5% 0.002 247.839);
- --color-gray-100: oklch(96.7% 0.003 264.542);
- --color-gray-200: oklch(92.8% 0.006 264.531);
- --color-gray-300: oklch(87.2% 0.01 258.338);
- --color-gray-400: oklch(70.7% 0.022 261.325);
- --color-gray-500: oklch(55.1% 0.027 264.364);
- --color-gray-600: oklch(44.6% 0.03 256.802);
- --color-gray-700: oklch(37.3% 0.034 259.733);
- --color-gray-800: oklch(27.8% 0.033 256.848);
- --color-gray-900: oklch(21% 0.034 264.665);
- --color-white: #fff;
- --spacing: 0.25rem;
- --container-md: 28rem;
- --container-2xl: 42rem;
- --container-7xl: 80rem;
- --text-sm: 0.875rem;
- --text-sm--line-height: calc(1.25 / 0.875);
- --text-base: 1rem;
- --text-base--line-height: calc(1.5 / 1);
- --text-xl: 1.25rem;
- --text-xl--line-height: calc(1.75 / 1.25);
- --text-2xl: 1.5rem;
- --text-2xl--line-height: calc(2 / 1.5);
- --text-3xl: 1.875rem;
- --text-3xl--line-height: calc(2.25 / 1.875);
- --font-weight-medium: 500;
- --font-weight-semibold: 600;
- --font-weight-bold: 700;
- --radius-lg: 0.5rem;
- --default-transition-duration: 150ms;
- --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
- --default-font-family: var(--font-sans);
- --default-mono-font-family: var(--font-mono);
- }
-}
-@layer base {
- *, ::after, ::before, ::backdrop, ::file-selector-button {
- box-sizing: border-box;
- margin: 0;
- padding: 0;
- border: 0 solid;
- }
- html, :host {
- line-height: 1.5;
- -webkit-text-size-adjust: 100%;
- tab-size: 4;
- font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");
- font-feature-settings: var(--default-font-feature-settings, normal);
- font-variation-settings: var(--default-font-variation-settings, normal);
- -webkit-tap-highlight-color: transparent;
- }
- hr {
- height: 0;
- color: inherit;
- border-top-width: 1px;
- }
- abbr:where([title]) {
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
- }
- h1, h2, h3, h4, h5, h6 {
- font-size: inherit;
- font-weight: inherit;
- }
- a {
- color: inherit;
- -webkit-text-decoration: inherit;
- text-decoration: inherit;
- }
- b, strong {
- font-weight: bolder;
- }
- code, kbd, samp, pre {
- font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
- font-feature-settings: var(--default-mono-font-feature-settings, normal);
- font-variation-settings: var(--default-mono-font-variation-settings, normal);
- font-size: 1em;
- }
- small {
- font-size: 80%;
- }
- sub, sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
- }
- sub {
- bottom: -0.25em;
- }
- sup {
- top: -0.5em;
- }
- table {
- text-indent: 0;
- border-color: inherit;
- border-collapse: collapse;
- }
- :-moz-focusring {
- outline: auto;
- }
- progress {
- vertical-align: baseline;
- }
- summary {
- display: list-item;
- }
- ol, ul, menu {
- list-style: none;
- }
- img, svg, video, canvas, audio, iframe, embed, object {
- display: block;
- vertical-align: middle;
- }
- img, video {
- max-width: 100%;
- height: auto;
- }
- button, input, select, optgroup, textarea, ::file-selector-button {
- font: inherit;
- font-feature-settings: inherit;
- font-variation-settings: inherit;
- letter-spacing: inherit;
- color: inherit;
- border-radius: 0;
- background-color: transparent;
- opacity: 1;
- }
- :where(select:is([multiple], [size])) optgroup {
- font-weight: bolder;
- }
- :where(select:is([multiple], [size])) optgroup option {
- padding-inline-start: 20px;
- }
- ::file-selector-button {
- margin-inline-end: 4px;
- }
- ::placeholder {
- opacity: 1;
- }
- @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {
- ::placeholder {
- color: currentcolor;
- @supports (color: color-mix(in lab, red, red)) {
- color: color-mix(in oklab, currentcolor 50%, transparent);
- }
- }
- }
- textarea {
- resize: vertical;
- }
- ::-webkit-search-decoration {
- -webkit-appearance: none;
- }
- ::-webkit-date-and-time-value {
- min-height: 1lh;
- text-align: inherit;
- }
- ::-webkit-datetime-edit {
- display: inline-flex;
- }
- ::-webkit-datetime-edit-fields-wrapper {
- padding: 0;
- }
- ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
- padding-block: 0;
- }
- ::-webkit-calendar-picker-indicator {
- line-height: 1;
- }
- :-moz-ui-invalid {
- box-shadow: none;
- }
- button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
- appearance: button;
- }
- ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
- height: auto;
- }
- [hidden]:where(:not([hidden="until-found"])) {
- display: none !important;
- }
-}
-@layer utilities {
- .collapse {
- visibility: collapse;
- }
- .sr-only {
- position: absolute;
- width: 1px;
- height: 1px;
- padding: 0;
- margin: -1px;
- overflow: hidden;
- clip-path: inset(50%);
- white-space: nowrap;
- border-width: 0;
- }
- .absolute {
- position: absolute;
- }
- .relative {
- position: relative;
- }
- .start {
- inset-inline-start: var(--spacing);
- }
- .end {
- inset-inline-end: var(--spacing);
- }
- .z-50 {
- z-index: 50;
- }
- .container {
- width: 100%;
- @media (width >= 40rem) {
- max-width: 40rem;
- }
- @media (width >= 48rem) {
- max-width: 48rem;
- }
- @media (width >= 64rem) {
- max-width: 64rem;
- }
- @media (width >= 80rem) {
- max-width: 80rem;
- }
- @media (width >= 96rem) {
- max-width: 96rem;
- }
- }
- .mx-auto {
- margin-inline: auto;
- }
- .my-4 {
- margin-block: calc(var(--spacing) * 4);
- }
- .me-3 {
- margin-inline-end: calc(var(--spacing) * 3);
- }
- .mt-2 {
- margin-top: calc(var(--spacing) * 2);
- }
- .mt-4 {
- margin-top: calc(var(--spacing) * 4);
- }
- .mb-1 {
- margin-bottom: calc(var(--spacing) * 1);
- }
- .mb-2 {
- margin-bottom: calc(var(--spacing) * 2);
- }
- .mb-3 {
- margin-bottom: calc(var(--spacing) * 3);
- }
- .mb-4 {
- margin-bottom: calc(var(--spacing) * 4);
- }
- .mb-6 {
- margin-bottom: calc(var(--spacing) * 6);
- }
- .block {
- display: block;
- }
- .contents {
- display: contents;
- }
- .flex {
- display: flex;
- }
- .hidden {
- display: none;
- }
- .inline {
- display: inline;
- }
- .inline-flex {
- display: inline-flex;
- }
- .table {
- display: table;
- }
- .h-4 {
- height: calc(var(--spacing) * 4);
- }
- .h-5 {
- height: calc(var(--spacing) * 5);
- }
- .h-8 {
- height: calc(var(--spacing) * 8);
- }
- .h-10 {
- height: calc(var(--spacing) * 10);
- }
- .min-h-screen {
- min-height: 100vh;
- }
- .w-4 {
- width: calc(var(--spacing) * 4);
- }
- .w-5 {
- width: calc(var(--spacing) * 5);
- }
- .w-10 {
- width: calc(var(--spacing) * 10);
- }
- .w-56 {
- width: calc(var(--spacing) * 56);
- }
- .w-full {
- width: 100%;
- }
- .max-w-2xl {
- max-width: var(--container-2xl);
- }
- .max-w-7xl {
- max-width: var(--container-7xl);
- }
- .max-w-md {
- max-width: var(--container-md);
- }
- .min-w-\[95px\] {
- min-width: 95px;
- }
- .flex-1 {
- flex: 1;
- }
- .shrink-0 {
- flex-shrink: 0;
- }
- .grow {
- flex-grow: 1;
- }
- .transform {
- transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
- }
- .resize {
- resize: both;
- }
- .list-none {
- list-style-type: none;
- }
- .flex-col {
- flex-direction: column;
- }
- .flex-wrap {
- flex-wrap: wrap;
- }
- .items-center {
- align-items: center;
- }
- .items-start {
- align-items: flex-start;
- }
- .justify-between {
- justify-content: space-between;
- }
- .justify-center {
- justify-content: center;
- }
- .justify-evenly {
- justify-content: space-evenly;
- }
- .gap-2 {
- gap: calc(var(--spacing) * 2);
- }
- .gap-3 {
- gap: calc(var(--spacing) * 3);
- }
- .space-y-5 {
- :where(& > :not(:last-child)) {
- --tw-space-y-reverse: 0;
- margin-block-start: calc(calc(var(--spacing) * 5) * var(--tw-space-y-reverse));
- margin-block-end: calc(calc(var(--spacing) * 5) * calc(1 - var(--tw-space-y-reverse)));
- }
- }
- .space-x-3 {
- :where(& > :not(:last-child)) {
- --tw-space-x-reverse: 0;
- margin-inline-start: calc(calc(var(--spacing) * 3) * var(--tw-space-x-reverse));
- margin-inline-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-x-reverse)));
- }
- }
- .divide-y {
- :where(& > :not(:last-child)) {
- --tw-divide-y-reverse: 0;
- border-bottom-style: var(--tw-border-style);
- border-top-style: var(--tw-border-style);
- border-top-width: calc(1px * var(--tw-divide-y-reverse));
- border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
- }
- }
- .divide-gray-100 {
- :where(& > :not(:last-child)) {
- border-color: var(--color-gray-100);
- }
- }
- .divide-gray-700 {
- :where(& > :not(:last-child)) {
- border-color: var(--color-gray-700);
- }
- }
- .self-center {
- align-self: center;
- }
- .truncate {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .rounded {
- border-radius: 0.25rem;
- }
- .rounded-lg {
- border-radius: var(--radius-lg);
- }
- .border {
- border-style: var(--tw-border-style);
- border-width: 1px;
- }
- .border-t {
- border-top-style: var(--tw-border-style);
- border-top-width: 1px;
- }
- .border-b {
- border-bottom-style: var(--tw-border-style);
- border-bottom-width: 1px;
- }
- .border-blue-200 {
- border-color: var(--color-blue-200);
- }
- .border-gray-100 {
- border-color: var(--color-gray-100);
- }
- .border-gray-200 {
- border-color: var(--color-gray-200);
- }
- .border-gray-300 {
- border-color: var(--color-gray-300);
- }
- .border-green-200 {
- border-color: var(--color-green-200);
- }
- .border-red-200 {
- border-color: var(--color-red-200);
- }
- .border-yellow-200 {
- border-color: var(--color-yellow-200);
- }
- .bg-blue-50 {
- background-color: var(--color-blue-50);
- }
- .bg-blue-100 {
- background-color: var(--color-blue-100);
- }
- .bg-blue-700 {
- background-color: var(--color-blue-700);
- }
- .bg-gray-50 {
- background-color: var(--color-gray-50);
- }
- .bg-gray-100 {
- background-color: var(--color-gray-100);
- }
- .bg-green-50 {
- background-color: var(--color-green-50);
- }
- .bg-red-50 {
- background-color: var(--color-red-50);
- }
- .bg-white {
- background-color: var(--color-white);
- }
- .bg-yellow-50 {
- background-color: var(--color-yellow-50);
- }
- .object-cover {
- object-fit: cover;
- }
- .p-2 {
- padding: calc(var(--spacing) * 2);
- }
- .p-2\.5 {
- padding: calc(var(--spacing) * 2.5);
- }
- .p-4 {
- padding: calc(var(--spacing) * 4);
- }
- .p-6 {
- padding: calc(var(--spacing) * 6);
- }
- .p-8 {
- padding: calc(var(--spacing) * 8);
- }
- .px-2 {
- padding-inline: calc(var(--spacing) * 2);
- }
- .px-3 {
- padding-inline: calc(var(--spacing) * 3);
- }
- .px-4 {
- padding-inline: calc(var(--spacing) * 4);
- }
- .px-5 {
- padding-inline: calc(var(--spacing) * 5);
- }
- .px-6 {
- padding-inline: calc(var(--spacing) * 6);
- }
- .py-1 {
- padding-block: calc(var(--spacing) * 1);
- }
- .py-2 {
- padding-block: calc(var(--spacing) * 2);
- }
- .py-2\.5 {
- padding-block: calc(var(--spacing) * 2.5);
- }
- .py-3 {
- padding-block: calc(var(--spacing) * 3);
- }
- .py-4 {
- padding-block: calc(var(--spacing) * 4);
- }
- .text-center {
- text-align: center;
- }
- .text-left {
- text-align: left;
- }
- .text-2xl {
- font-size: var(--text-2xl);
- line-height: var(--tw-leading, var(--text-2xl--line-height));
- }
- .text-3xl {
- font-size: var(--text-3xl);
- line-height: var(--tw-leading, var(--text-3xl--line-height));
- }
- .text-base {
- font-size: var(--text-base);
- line-height: var(--tw-leading, var(--text-base--line-height));
- }
- .text-sm {
- font-size: var(--text-sm);
- line-height: var(--tw-leading, var(--text-sm--line-height));
- }
- .text-xl {
- font-size: var(--text-xl);
- line-height: var(--tw-leading, var(--text-xl--line-height));
- }
- .font-bold {
- --tw-font-weight: var(--font-weight-bold);
- font-weight: var(--font-weight-bold);
- }
- .font-medium {
- --tw-font-weight: var(--font-weight-medium);
- font-weight: var(--font-weight-medium);
- }
- .font-semibold {
- --tw-font-weight: var(--font-weight-semibold);
- font-weight: var(--font-weight-semibold);
- }
- .whitespace-nowrap {
- white-space: nowrap;
- }
- .text-blue-700 {
- color: var(--color-blue-700);
- }
- .text-blue-800 {
- color: var(--color-blue-800);
- }
- .text-blue-900 {
- color: var(--color-blue-900);
- }
- .text-gray-500 {
- color: var(--color-gray-500);
- }
- .text-gray-600 {
- color: var(--color-gray-600);
- }
- .text-gray-700 {
- color: var(--color-gray-700);
- }
- .text-gray-900 {
- color: var(--color-gray-900);
- }
- .text-green-800 {
- color: var(--color-green-800);
- }
- .text-red-700 {
- color: var(--color-red-700);
- }
- .text-red-800 {
- color: var(--color-red-800);
- }
- .text-white {
- color: var(--color-white);
- }
- .text-yellow-800 {
- color: var(--color-yellow-800);
- }
- .antialiased {
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- }
- .shadow {
- --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- }
- .shadow-sm {
- --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- }
- .outline {
- outline-style: var(--tw-outline-style);
- outline-width: 1px;
- }
- .outline-red-500 {
- outline-color: var(--color-red-500);
- }
- .\[rows\:\%v\] {
- rows: %v;
- }
- .hover\:bg-blue-800 {
- &:hover {
- @media (hover: hover) {
- background-color: var(--color-blue-800);
- }
- }
- }
- .hover\:bg-gray-100 {
- &:hover {
- @media (hover: hover) {
- background-color: var(--color-gray-100);
- }
- }
- }
- .hover\:bg-gray-200 {
- &:hover {
- @media (hover: hover) {
- background-color: var(--color-gray-200);
- }
- }
- }
- .hover\:bg-red-50 {
- &:hover {
- @media (hover: hover) {
- background-color: var(--color-red-50);
- }
- }
- }
- .hover\:underline {
- &:hover {
- @media (hover: hover) {
- text-decoration-line: underline;
- }
- }
- }
- .focus\:border-blue-500 {
- &:focus {
- border-color: var(--color-blue-500);
- }
- }
- .focus\:ring-2 {
- &:focus {
- --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- }
- }
- .focus\:ring-4 {
- &:focus {
- --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
- box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
- }
- }
- .focus\:ring-blue-300 {
- &:focus {
- --tw-ring-color: var(--color-blue-300);
- }
- }
- .focus\:ring-blue-500 {
- &:focus {
- --tw-ring-color: var(--color-blue-500);
- }
- }
- .focus\:ring-gray-200 {
- &:focus {
- --tw-ring-color: var(--color-gray-200);
- }
- }
- .focus\:outline-none {
- &:focus {
- --tw-outline-style: none;
- outline-style: none;
- }
- }
- .md\:order-1 {
- @media (width >= 48rem) {
- order: 1;
- }
- }
- .md\:ms-4 {
- @media (width >= 48rem) {
- margin-inline-start: calc(var(--spacing) * 4);
- }
- }
- .md\:mt-0 {
- @media (width >= 48rem) {
- margin-top: calc(var(--spacing) * 0);
- }
- }
- .md\:flex {
- @media (width >= 48rem) {
- display: flex;
- }
- }
- .md\:hidden {
- @media (width >= 48rem) {
- display: none;
- }
- }
- .md\:w-auto {
- @media (width >= 48rem) {
- width: auto;
- }
- }
- .md\:flex-row {
- @media (width >= 48rem) {
- flex-direction: row;
- }
- }
- .md\:items-center {
- @media (width >= 48rem) {
- align-items: center;
- }
- }
- .md\:gap-1 {
- @media (width >= 48rem) {
- gap: calc(var(--spacing) * 1);
- }
- }
- .md\:border-0 {
- @media (width >= 48rem) {
- border-style: var(--tw-border-style);
- border-width: 0px;
- }
- }
- .md\:bg-transparent {
- @media (width >= 48rem) {
- background-color: transparent;
- }
- }
- .md\:p-0 {
- @media (width >= 48rem) {
- padding: calc(var(--spacing) * 0);
- }
- }
- .md\:p-8 {
- @media (width >= 48rem) {
- padding: calc(var(--spacing) * 8);
- }
- }
- .rtl\:space-x-reverse {
- &:where(:dir(rtl), [dir="rtl"], [dir="rtl"] *) {
- :where(& > :not(:last-child)) {
- --tw-space-x-reverse: 1;
- }
- }
- }
- .dark\:divide-gray-700 {
- &:where(.dark, .dark *) {
- :where(& > :not(:last-child)) {
- border-color: var(--color-gray-700);
- }
- }
- }
- .dark\:border-1 {
- &:where(.dark, .dark *) {
- border-style: var(--tw-border-style);
- border-width: 1px;
- }
- }
- .dark\:border-2 {
- &:where(.dark, .dark *) {
- border-style: var(--tw-border-style);
- border-width: 2px;
- }
- }
- .dark\:border-4 {
- &:where(.dark, .dark *) {
- border-style: var(--tw-border-style);
- border-width: 4px;
- }
- }
- .dark\:border-blue-800 {
- &:where(.dark, .dark *) {
- border-color: var(--color-blue-800);
- }
- }
- .dark\:border-gray-600 {
- &:where(.dark, .dark *) {
- border-color: var(--color-gray-600);
- }
- }
- .dark\:border-gray-700 {
- &:where(.dark, .dark *) {
- border-color: var(--color-gray-700);
- }
- }
- .dark\:border-green-800 {
- &:where(.dark, .dark *) {
- border-color: var(--color-green-800);
- }
- }
- .dark\:border-red-800 {
- &:where(.dark, .dark *) {
- border-color: var(--color-red-800);
- }
- }
- .dark\:border-yellow-700 {
- &:where(.dark, .dark *) {
- border-color: var(--color-yellow-700);
- }
- }
- .dark\:bg-blue-900 {
- &:where(.dark, .dark *) {
- background-color: var(--color-blue-900);
- }
- }
- .dark\:bg-blue-900\/30 {
- &:where(.dark, .dark *) {
- background-color: color-mix(in srgb, oklch(37.9% 0.146 265.522) 30%, transparent);
- @supports (color: color-mix(in lab, red, red)) {
- background-color: color-mix(in oklab, var(--color-blue-900) 30%, transparent);
- }
- }
- }
- .dark\:bg-gray-700 {
- &:where(.dark, .dark *) {
- background-color: var(--color-gray-700);
- }
- }
- .dark\:bg-gray-800 {
- &:where(.dark, .dark *) {
- background-color: var(--color-gray-800);
- }
- }
- .dark\:bg-gray-900 {
- &:where(.dark, .dark *) {
- background-color: var(--color-gray-900);
- }
- }
- .dark\:bg-green-900\/40 {
- &:where(.dark, .dark *) {
- background-color: color-mix(in srgb, oklch(39.3% 0.095 152.535) 40%, transparent);
- @supports (color: color-mix(in lab, red, red)) {
- background-color: color-mix(in oklab, var(--color-green-900) 40%, transparent);
- }
- }
- }
- .dark\:bg-red-900\/40 {
- &:where(.dark, .dark *) {
- background-color: color-mix(in srgb, oklch(39.6% 0.141 25.723) 40%, transparent);
- @supports (color: color-mix(in lab, red, red)) {
- background-color: color-mix(in oklab, var(--color-red-900) 40%, transparent);
- }
- }
- }
- .dark\:bg-yellow-900\/30 {
- &:where(.dark, .dark *) {
- background-color: color-mix(in srgb, oklch(42.1% 0.095 57.708) 30%, transparent);
- @supports (color: color-mix(in lab, red, red)) {
- background-color: color-mix(in oklab, var(--color-yellow-900) 30%, transparent);
- }
- }
- }
- .dark\:text-blue-100 {
- &:where(.dark, .dark *) {
- color: var(--color-blue-100);
- }
- }
- .dark\:text-blue-200 {
- &:where(.dark, .dark *) {
- color: var(--color-blue-200);
- }
- }
- .dark\:text-blue-300 {
- &:where(.dark, .dark *) {
- color: var(--color-blue-300);
- }
- }
- .dark\:text-blue-400 {
- &:where(.dark, .dark *) {
- color: var(--color-blue-400);
- }
- }
- .dark\:text-gray-100 {
- &:where(.dark, .dark *) {
- color: var(--color-gray-100);
- }
- }
- .dark\:text-gray-200 {
- &:where(.dark, .dark *) {
- color: var(--color-gray-200);
- }
- }
- .dark\:text-gray-300 {
- &:where(.dark, .dark *) {
- color: var(--color-gray-300);
- }
- }
- .dark\:text-gray-400 {
- &:where(.dark, .dark *) {
- color: var(--color-gray-400);
- }
- }
- .dark\:text-green-300 {
- &:where(.dark, .dark *) {
- color: var(--color-green-300);
- }
- }
- .dark\:text-red-300 {
- &:where(.dark, .dark *) {
- color: var(--color-red-300);
- }
- }
- .dark\:text-white {
- &:where(.dark, .dark *) {
- color: var(--color-white);
- }
- }
- .dark\:text-yellow-300 {
- &:where(.dark, .dark *) {
- color: var(--color-yellow-300);
- }
- }
- .dark\:placeholder-gray-400 {
- &:where(.dark, .dark *) {
- &::placeholder {
- color: var(--color-gray-400);
- }
- }
- }
- .dark\:outline {
- &:where(.dark, .dark *) {
- outline-style: var(--tw-outline-style);
- outline-width: 1px;
- }
- }
- .dark\:outline-gray-100 {
- &:where(.dark, .dark *) {
- outline-color: var(--color-gray-100);
- }
- }
- .dark\:outline-gray-500 {
- &:where(.dark, .dark *) {
- outline-color: var(--color-gray-500);
- }
- }
- .dark\:hover\:bg-gray-700 {
- &:where(.dark, .dark *) {
- &:hover {
- @media (hover: hover) {
- background-color: var(--color-gray-700);
- }
- }
- }
- }
- .dark\:hover\:bg-red-900\/40 {
- &:where(.dark, .dark *) {
- &:hover {
- @media (hover: hover) {
- background-color: color-mix(in srgb, oklch(39.6% 0.141 25.723) 40%, transparent);
- @supports (color: color-mix(in lab, red, red)) {
- background-color: color-mix(in oklab, var(--color-red-900) 40%, transparent);
- }
- }
- }
- }
- }
- .dark\:focus\:ring-gray-700 {
- &:where(.dark, .dark *) {
- &:focus {
- --tw-ring-color: var(--color-gray-700);
- }
- }
- }
- .md\:dark\:bg-transparent {
- @media (width >= 48rem) {
- &:where(.dark, .dark *) {
- background-color: transparent;
- }
- }
- }
-}
-@layer utilities {
- .flag-lang {
- width: 32px;
- height: 22px;
- }
- .flag-lang-ch {
- width: 22px;
- height: 22px;
- }
-}
-@property --tw-rotate-x {
- syntax: "*";
- inherits: false;
-}
-@property --tw-rotate-y {
- syntax: "*";
- inherits: false;
-}
-@property --tw-rotate-z {
- syntax: "*";
- inherits: false;
-}
-@property --tw-skew-x {
- syntax: "*";
- inherits: false;
-}
-@property --tw-skew-y {
- syntax: "*";
- inherits: false;
-}
-@property --tw-space-y-reverse {
- syntax: "*";
- inherits: false;
- initial-value: 0;
-}
-@property --tw-space-x-reverse {
- syntax: "*";
- inherits: false;
- initial-value: 0;
-}
-@property --tw-divide-y-reverse {
- syntax: "*";
- inherits: false;
- initial-value: 0;
-}
-@property --tw-border-style {
- syntax: "*";
- inherits: false;
- initial-value: solid;
-}
-@property --tw-font-weight {
- syntax: "*";
- inherits: false;
-}
-@property --tw-shadow {
- syntax: "*";
- inherits: false;
- initial-value: 0 0 #0000;
-}
-@property --tw-shadow-color {
- syntax: "*";
- inherits: false;
-}
-@property --tw-shadow-alpha {
- syntax: "";
- inherits: false;
- initial-value: 100%;
-}
-@property --tw-inset-shadow {
- syntax: "*";
- inherits: false;
- initial-value: 0 0 #0000;
-}
-@property --tw-inset-shadow-color {
- syntax: "*";
- inherits: false;
-}
-@property --tw-inset-shadow-alpha {
- syntax: "";
- inherits: false;
- initial-value: 100%;
-}
-@property --tw-ring-color {
- syntax: "*";
- inherits: false;
-}
-@property --tw-ring-shadow {
- syntax: "*";
- inherits: false;
- initial-value: 0 0 #0000;
-}
-@property --tw-inset-ring-color {
- syntax: "*";
- inherits: false;
-}
-@property --tw-inset-ring-shadow {
- syntax: "*";
- inherits: false;
- initial-value: 0 0 #0000;
-}
-@property --tw-ring-inset {
- syntax: "*";
- inherits: false;
-}
-@property --tw-ring-offset-width {
- syntax: "";
- inherits: false;
- initial-value: 0px;
-}
-@property --tw-ring-offset-color {
- syntax: "*";
- inherits: false;
- initial-value: #fff;
-}
-@property --tw-ring-offset-shadow {
- syntax: "*";
- inherits: false;
- initial-value: 0 0 #0000;
-}
-@property --tw-outline-style {
- syntax: "*";
- inherits: false;
- initial-value: solid;
-}
-@layer properties {
- @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
- *, ::before, ::after, ::backdrop {
- --tw-rotate-x: initial;
- --tw-rotate-y: initial;
- --tw-rotate-z: initial;
- --tw-skew-x: initial;
- --tw-skew-y: initial;
- --tw-space-y-reverse: 0;
- --tw-space-x-reverse: 0;
- --tw-divide-y-reverse: 0;
- --tw-border-style: solid;
- --tw-font-weight: initial;
- --tw-shadow: 0 0 #0000;
- --tw-shadow-color: initial;
- --tw-shadow-alpha: 100%;
- --tw-inset-shadow: 0 0 #0000;
- --tw-inset-shadow-color: initial;
- --tw-inset-shadow-alpha: 100%;
- --tw-ring-color: initial;
- --tw-ring-shadow: 0 0 #0000;
- --tw-inset-ring-color: initial;
- --tw-inset-ring-shadow: 0 0 #0000;
- --tw-ring-inset: initial;
- --tw-ring-offset-width: 0px;
- --tw-ring-offset-color: #fff;
- --tw-ring-offset-shadow: 0 0 #0000;
- --tw-outline-style: solid;
- }
- }
-}
+@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.flag-lang{width:32px;height:22px}.flag-lang-ch{width:22px;height:22px}}
\ No newline at end of file
diff --git a/web/templates/layout.html b/web/templates/layout.html
index 1869a60..00c32c2 100644
--- a/web/templates/layout.html
+++ b/web/templates/layout.html
@@ -49,7 +49,7 @@
'private.title': 'Dashboard', 'private.back_prefix': 'Bentornato', 'private.generic': 'Benvenuto.', 'private.quick_links': 'Link rapidi',
'admin.dashboard.title': 'Admin Dashboard', 'admin.dashboard.area': 'Area amministrazione.', 'admin.users_count': 'Utenti', 'admin.current_role': 'Ruolo corrente', 'admin.navigation': 'Navigazione', 'admin.manage_users': 'Gestione utenti',
'users.title': 'Users', 'users.subtitle': 'Ricerca, ordinamento e paging server-side.', 'users.new_user': 'Nuovo Utente', 'users.search': 'Search', 'users.search_placeholder': 'Cerca nome o email', 'users.page_size': 'Page size', 'users.search_button': 'Cerca', 'users.user_detail': 'Dettaglio utente', 'users.actions': 'Azioni', 'users.open': 'Apri', 'users.none': 'Nessun utente trovato.', 'users.total': 'Totale', 'users.users_label': 'utenti', 'users.page': 'Pagina', 'users.prev': 'Prev', 'users.next': 'Next', 'users.close': 'Chiudi',
- 'users.new_user_modal_title': 'Nuovo utente', 'users.new_user_modal_placeholder': 'Placeholder UI Flowbite. La creazione utente può essere collegata a una route backend quando disponibile.',
+ 'users.new_user_modal_title': 'Nuovo utente', 'users.new_user_modal_placeholder': 'Placeholder UI. La creazione utente può essere collegata a una route backend quando disponibile.',
'table.id': 'ID', 'table.name': 'Name', 'table.email': 'Email', 'table.role': 'Role', 'user.role_admin': 'admin', 'user.role_user': 'user', 'user.verified': 'Verificato', 'user.created': 'Creato', 'user.yes': 'sì', 'user.no': 'no',
'audit.title': 'Audit Logs', 'audit.activity': 'Attività', 'audit.security': 'Sicurezza', 'audit.timestamp': 'Timestamp', 'audit.actor': 'Attore', 'audit.action': 'Azione', 'audit.placeholder': 'Placeholder log di sicurezza.'
},
@@ -64,7 +64,7 @@
'private.title': 'Dashboard', 'private.back_prefix': 'Signed in as', 'private.generic': 'Signed in.', 'private.quick_links': 'Quick links',
'admin.dashboard.title': 'Admin Dashboard', 'admin.dashboard.area': 'Administration area.', 'admin.users_count': 'Users', 'admin.current_role': 'Current role', 'admin.navigation': 'Navigation', 'admin.manage_users': 'Manage users',
'users.title': 'Users', 'users.subtitle': 'Search, sorting and server-side paging.', 'users.new_user': 'New user', 'users.search': 'Search', 'users.search_placeholder': 'Search by name or email', 'users.page_size': 'Page size', 'users.search_button': 'Search', 'users.user_detail': 'User details', 'users.actions': 'Actions', 'users.open': 'Open', 'users.none': 'No users found.', 'users.total': 'Total', 'users.users_label': 'users', 'users.page': 'Page', 'users.prev': 'Prev', 'users.next': 'Next', 'users.close': 'Close',
- 'users.new_user_modal_title': 'New user', 'users.new_user_modal_placeholder': 'Flowbite placeholder UI. Connect creation to backend route when available.',
+ 'users.new_user_modal_title': 'New user', 'users.new_user_modal_placeholder': 'UI placeholder. Connect creation to backend route when available.',
'table.id': 'ID', 'table.name': 'Name', 'table.email': 'Email', 'table.role': 'Role', 'user.role_admin': 'admin', 'user.role_user': 'user', 'user.verified': 'Verified', 'user.created': 'Created', 'user.yes': 'yes', 'user.no': 'no',
'audit.title': 'Audit Logs', 'audit.activity': 'Activity', 'audit.security': 'Security', 'audit.timestamp': 'Timestamp', 'audit.actor': 'Actor', 'audit.action': 'Action', 'audit.placeholder': 'Security logs placeholder.'
},
@@ -79,7 +79,7 @@
'private.title': 'Dashboard', 'private.back_prefix': 'Willkommen zurück', 'private.generic': 'Willkommen.', 'private.quick_links': 'Schnelllinks',
'admin.dashboard.title': 'Admin-Dashboard', 'admin.dashboard.area': 'Administrationsbereich.', 'admin.users_count': 'Benutzer', 'admin.current_role': 'Aktuelle Rolle', 'admin.navigation': 'Navigation', 'admin.manage_users': 'Benutzer verwalten',
'users.title': 'Benutzer', 'users.subtitle': 'Suche, Sortierung und serverseitiges Paging.', 'users.new_user': 'Neuer Benutzer', 'users.search': 'Suche', 'users.search_placeholder': 'Nach Name oder E-Mail suchen', 'users.page_size': 'Seitengröße', 'users.search_button': 'Suchen', 'users.user_detail': 'Benutzerdetails', 'users.actions': 'Aktionen', 'users.open': 'Öffnen', 'users.none': 'Keine Benutzer gefunden.', 'users.total': 'Gesamt', 'users.users_label': 'Benutzer', 'users.page': 'Seite', 'users.prev': 'Zurück', 'users.next': 'Weiter', 'users.close': 'Schließen',
- 'users.new_user_modal_title': 'Neuer Benutzer', 'users.new_user_modal_placeholder': 'Flowbite-Placeholder-UI. Bei Bedarf mit Backend-Route verbinden.',
+ 'users.new_user_modal_title': 'Neuer Benutzer', 'users.new_user_modal_placeholder': 'Placeholder-UI. Bei Bedarf mit Backend-Route verbinden.',
'table.id': 'ID', 'table.name': 'Name', 'table.email': 'E-Mail', 'table.role': 'Rolle', 'user.role_admin': 'admin', 'user.role_user': 'user', 'user.verified': 'Verifiziert', 'user.created': 'Erstellt', 'user.yes': 'ja', 'user.no': 'nein',
'audit.title': 'Audit-Logs', 'audit.activity': 'Aktivität', 'audit.security': 'Sicherheit', 'audit.timestamp': 'Zeitstempel', 'audit.actor': 'Akteur', 'audit.action': 'Aktion', 'audit.placeholder': 'Platzhalter für Sicherheitsprotokolle.'
},
@@ -93,7 +93,7 @@
'private.title': 'Tableau de bord', 'private.back_prefix': 'Bon retour', 'private.generic': 'Bienvenue.', 'private.quick_links': 'Liens rapides',
'admin.dashboard.title': 'Tableau de bord admin', 'admin.dashboard.area': 'Zone d’administration.', 'admin.users_count': 'Utilisateurs', 'admin.current_role': 'Rôle actuel', 'admin.navigation': 'Navigation', 'admin.manage_users': 'Gérer les utilisateurs',
'users.title': 'Utilisateurs', 'users.subtitle': 'Recherche, tri et pagination côté serveur.', 'users.new_user': 'Nouvel utilisateur', 'users.search': 'Recherche', 'users.search_placeholder': 'Rechercher par nom ou email', 'users.page_size': 'Taille de page', 'users.search_button': 'Rechercher', 'users.user_detail': 'Détails utilisateur', 'users.actions': 'Actions', 'users.open': 'Ouvrir', 'users.none': 'Aucun utilisateur trouvé.', 'users.total': 'Total', 'users.users_label': 'utilisateurs', 'users.page': 'Page', 'users.prev': 'Préc.', 'users.next': 'Suiv.', 'users.close': 'Fermer',
- 'users.new_user_modal_title': 'Nouvel utilisateur', 'users.new_user_modal_placeholder': 'UI Flowbite placeholder. Connecter à une route backend si nécessaire.',
+ 'users.new_user_modal_title': 'Nouvel utilisateur', 'users.new_user_modal_placeholder': 'UI placeholder. Connecter à une route backend si nécessaire.',
'table.id': 'ID', 'table.name': 'Nom', 'table.email': 'Email', 'table.role': 'Rôle', 'user.role_admin': 'admin', 'user.role_user': 'user', 'user.verified': 'Vérifié', 'user.created': 'Créé', 'user.yes': 'oui', 'user.no': 'non',
'audit.title': 'Journaux d’audit', 'audit.activity': 'Activité', 'audit.security': 'Sécurité', 'audit.timestamp': 'Horodatage', 'audit.actor': 'Acteur', 'audit.action': 'Action', 'audit.placeholder': 'Espace réservé des journaux de sécurité.'
}