feat(theme): runtime custom theme ecosystem (graphics-only)

Runtime-loaded visual re-skin system (no client rebuild, real themes never
hit git). A theme = a folder on the server (theme.base.url) with a manifest +
CSS "pieces"; each piece is toggled from Settings > Themes (checkboxes). A
broken/404 piece auto-falls back to the default (per piece). Hotel-wide default
via ui-config theme.default (+ theme.default.pieces), per-user override in
localStorage (same pattern as the catalog style toggle).

- api/theme/ThemeManager: fetch index/manifest + inject/remove <link> + fallback
- hooks/theme/useThemes: state + persist + default-from-config + live apply
- components/theme/ThemeApplier: applies on boot (mounted in MainView)
- UserSettings: General/Themes tabs with theme selector + per-piece checkboxes
- custom-themes/: reference template (demo theme "Neon Viola" + README)
- .gitignore: public/custom-themes/ (real themes are never committed)
This commit is contained in:
medievalshell
2026-05-31 14:39:59 +02:00
parent cbd63220bd
commit 8097344561
18 changed files with 400 additions and 1 deletions
+24
View File
@@ -0,0 +1,24 @@
/* Tema Neon Viola — pezzo "cards" (finestre / NitroCard).
Ricolora header + cornice delle finestre. Caricato DOPO il CSS base, quindi
usa !important per vincere. Tocca solo la cornice/header (non lo sfondo del
contenuto) per non rovinare la leggibilita' del testo. */
.nitro-card-shell:not(.nitro-wired) {
border-color: #7c3aed !important;
box-shadow: 0 0 14px rgba(124, 58, 237, .55), 0 8px 22px rgba(0, 0, 0, .4) !important;
}
.nitro-card-shell:not(.nitro-wired) .nitro-card-header-shell {
background: linear-gradient(180deg, #9333ea 0%, #6d28d9 100%) !important;
border-color: #a855f7 !important;
border-bottom-color: #2a0a4a !important;
}
.nitro-card-shell:not(.nitro-wired) .nitro-card-title {
color: #fff !important;
text-shadow: 0 0 6px #c084fc, 0 1px 0 #3b0764 !important;
}
.nitro-card-shell:not(.nitro-wired) .nitro-card-tabs-shell .nitro-card-tab-item-active {
box-shadow: inset 0 -2px 0 #a855f7 !important;
}
+10
View File
@@ -0,0 +1,10 @@
/* Tema Neon Viola — pezzo "catalog" (catalogo Hippiehotel, .nitro-catalog). */
.nitro-catalog .nitro-card-header-shell {
background: linear-gradient(180deg, #9333ea 0%, #6d28d9 100%) !important;
}
.nitro-catalog .group\/rail {
background: #1a1030 !important;
border-right-color: #7c3aed !important;
}
+12
View File
@@ -0,0 +1,12 @@
/* Tema Neon Viola — pezzo "chat".
Accento viola sulla bubble di default (bubble-0) e sull'input chat.
(Le bubble custom hanno la loro grafica; qui tocchiamo solo l'accento base.) */
.chat-bubble.bubble-0 {
filter: drop-shadow(0 0 5px rgba(168, 85, 247, .8));
}
.nitro-chat-input-container,
.chat-input-container {
box-shadow: inset 0 0 0 1px #7c3aed !important;
}
+10
View File
@@ -0,0 +1,10 @@
{
"name": "Neon Viola",
"author": "infinityhotel",
"pieces": [
{ "id": "cards", "name": "Finestre / Card", "file": "cards.css" },
{ "id": "chat", "name": "Chat", "file": "chat.css" },
{ "id": "toolbar", "name": "Toolbar", "file": "toolbar.css" },
{ "id": "catalog", "name": "Catalogo", "file": "catalog.css" }
]
}
+9
View File
@@ -0,0 +1,9 @@
/* Tema Neon Viola — pezzo "toolbar".
Best-effort: ricolora la barra strumenti in basso. Se i selettori non
matchano nella tua build, il pezzo non ha effetto (fallback sicuro). */
.nitro-toolbar,
[class*="toolbar-container"] {
background: linear-gradient(180deg, #2a0a4a 0%, #1a0730 100%) !important;
box-shadow: 0 -2px 10px rgba(124, 58, 237, .4) !important;
}