Files
vans-diy-bastelbedarf/public/admin/index.html
T
qciganoandClaude Sonnet 5 1b55604cba Badges kräftiger für bessere Lesbarkeit + Admin-Install-Icon endlich zuverlässig
Badges ("NEU", "HANDGEMACHT" ...) sitzen direkt auf Produktfotos mit
unterschiedlichsten Hintergründen — die alte, sehr transparente Pille
ging auf manchen Fotos optisch unter. Gleiche Farben/gleicher Stil,
aber kräftigerer (deutlich weniger transparenter) Hintergrund + eigener
Rand + dezenter Schlagschatten hinterm Text für Kontrast auf jedem
Untergrund.

Den eigentlichen Grund für das wacklige Verhalten beim Installieren des
Admin-Bereichs gefunden: Sveltia CMS liest selbst den "logo"-Eintrag in
config.yml (eigentlich nur fürs Branding IN der CMS-Oberfläche gedacht)
und fügt daraus automatisch EIGENE Icon-/Manifest-Verknüpfungen in den
<head> ein — u.a. ein live generiertes, eigenes Manifest als blob:-URL
— NACH unseren eigenen. Zwei "rel=manifest"-Links gleichzeitig sind
technisch erlaubt, aber welcher beim Installieren gewinnt, war nicht
zuverlässig vorhersagbar. Das erklärt, warum es mal geklappt hat und
mal nicht, unabhängig vom Icon-Inhalt selbst.

Fix: ein MutationObserver entfernt Sveltias eigene, automatisch
eingefügte Icon-/Manifest-Verknüpfungen sofort wieder, sobald sie
auftauchen — übrig bleiben ausschließlich unsere eigenen (Favicon =
echtes Logo, Install-Icon = lila V). Verifiziert: nach vollständigem
Laden inkl. Sveltia sind nur noch unsere 5 eigenen Verknüpfungen im
<head> vorhanden, 0 Installability-Errors.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-08-03 01:24:40 +02:00

159 lines
8.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="robots" content="noindex" />
<title>Van's DIY & Bastelbedarf Admin</title>
<link rel="icon" type="image/x-icon" href="/favicon.ico" sizes="any" />
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/admin/manifest.webmanifest" />
<meta name="theme-color" content="#0a0910" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Fraunces:opsz,[email protected],500;9..144,600;9..144,700&display=swap" rel="stylesheet" />
<style>
/* Sveltia CMS optisch an die eigentliche Website angepasst — nutzt Sveltias eigenes
CSS-Variablen-Theming-System (--sui-*, "Sveltia UI"), keine geratenen internen
Klassennamen. Das ist zwar nirgends offiziell als öffentliche Theming-API dokumentiert,
aber es sind echte, durchgängig im ganzen Sveltia-Interface verwendete Design-Tokens —
deutlich robuster als CSS gegen zufällige Klassennamen zu schreiben. Falls ein
künftiges Sveltia-Update diese Variablennamen ändert, fällt die Oberfläche einfach
wieder auf ihr Standard-Blau zurück statt kaputtzugehen.
*/
/* !important nötig: Sveltia hängt sein eigenes Stylesheet erst NACH dieser Seite ein,
gewinnt also bei gleicher Spezifität normalerweise die Kaskade. Mit !important setzt
sich unsere Optik trotzdem zuverlässig durch, unabhängig von der Ladereihenfolge. */
:root {
/* Schiebt alle neutralen Grautöne/Ränder der Oberfläche Richtung Lila — wie der
Rest der Seite (statt Sveltias Standard-Blaugrau). */
--sui-base-hue: 248 !important;
/* Mischung aus Lila und Babyblau statt einer einzelnen Akzentfarbe: der normale Zustand
(Buttons, aktive Felder, Links) ist babyblau, Hover-/Fokus-/Auswahl-Zustände (die den
"-dark"-Ton nutzen) kippen ins Lila (der gleiche Violett-Ton wie die Verlaufsränder auf
der eigentlichen Website) — dadurch entsteht überall im Interface ein echter Farbmix,
nicht nur eine Einzelfarbe. */
--sui-primary-accent-color: #8ec9f0 !important;
--sui-primary-accent-color-light: #b9e0fa !important;
--sui-primary-accent-color-dark: #9b7fd6 !important;
--sui-primary-accent-color-text: #8ec9f0 !important;
--sui-primary-accent-color-inverted: #0a0910 !important;
--sui-primary-accent-color-translucent: rgba(155, 127, 214, 0.45) !important;
--sui-primary-accent-color-translucent-light: rgba(142, 201, 240, 0.3) !important;
/* Gleiche Schriftart wie der Rest der Seite statt Sveltias Standardschrift. */
--sui-font-family-default: "Inter", system-ui, sans-serif !important;
}
/* Zahlenfelder ohne die klobigen Auf/Ab-Pfeile — dezenter, aufgeräumter. */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input[type="number"] {
-moz-appearance: textfield;
}
/* Überschriften mit derselben edlen Serifenschrift wie auf der eigentlichen Website
(dort --font-head: Fraunces) statt der Standard-Sans-Serif — Sveltia selbst bietet dafür
kein eigenes CSS-Token, deshalb hier über die stabilen, semantischen HTML-Tags gesetzt
statt über interne Klassennamen (bleibt robust, auch wenn sich Sveltias Aufbau ändert). */
h1, h2, h3 {
font-family: "Fraunces", "Playfair Display", Georgia, serif !important;
}
/* Schwebender "Installieren"-Button — nur sichtbar, wenn der Browser eine Installation
wirklich anbietet (siehe Script unten). position:fixed statt normaler Dokumentfluss,
damit er unabhängig davon funktioniert, wie Sveltia sein eigenes UI in <body> aufbaut. */
#install-btn {
display: none;
position: fixed;
bottom: 1.2rem;
right: 1.2rem;
z-index: 9999;
align-items: center;
gap: 0.5em;
padding: 0.7em 1.1em;
border-radius: 999px;
background: linear-gradient(135deg, #9b7fd6, #2e1b47);
border: 1px solid rgba(155, 127, 214, 0.6);
color: #f4f1f7;
font-family: "Inter", system-ui, sans-serif;
font-size: 0.88rem;
font-weight: 600;
cursor: pointer;
box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.55);
}
#install-btn:hover { filter: brightness(1.1); }
</style>
</head>
<body>
<!-- Sveltia CMS: quelloffen (MIT), läuft komplett im Browser, bearbeitet die Inhalte
direkt im GitHub-Repo. Kein eigener Server nötig — siehe config.yml für die
Feld-Definitionen (Produkte, Kategorien). -->
<script src="https://unpkg.com/@sveltia/cms/dist/sveltia-cms.js"></script>
<button type="button" id="install-btn" title="Admin als App installieren">⬇️ Installieren</button>
<script>
// WICHTIG gefundener Grund für das wacklige Installations-Icon bisher: Sveltia CMS liest
// selbst den "logo"-Eintrag oben in config.yml (der eigentlich nur fürs Branding IN der
// CMS-Oberfläche gedacht ist) und fügt daraus automatisch EIGENE <link rel="icon">,
// <link rel="apple-touch-icon"> und sogar ein eigenes, live generiertes
// <link rel="manifest"> (als blob:-URL) in den <head> ein — NACH unseren eigenen, fest
// im HTML stehenden Verknüpfungen. Zwei "rel=manifest"-Links gleichzeitig sind erlaubt,
// aber welcher davon beim Installieren gewinnt, ist nicht zuverlässig vorhersagbar —
// genau das erklärt, warum es mal geklappt hat und mal nicht. Fix: ein MutationObserver
// entfernt Sveltias eigene Icon-/Manifest-Verknüpfungen SOFORT wieder, sobald sie
// auftauchen, damit ausschließlich unsere eigenen (mit dem lila "V") übrig bleiben.
(function () {
var eigeneManifestUrl = location.origin + "/admin/manifest.webmanifest";
var beobachter = new MutationObserver(function (mutationen) {
mutationen.forEach(function (mutation) {
mutation.addedNodes.forEach(function (node) {
if (node.nodeName !== "LINK") return;
var rel = node.getAttribute("rel");
if (rel === "manifest" && node.href !== eigeneManifestUrl) node.remove();
if (rel === "icon" && node.href.indexOf("/logo.png") !== -1) node.remove();
if (rel === "apple-touch-icon" && node.href.indexOf("data:") === 0) node.remove();
});
});
});
beobachter.observe(document.head, { childList: true });
})();
// Gleiches Prinzip wie auf der Hauptseite: Button nur zeigen, wenn der Browser die
// Installation wirklich anbietet, und nicht mehr, sobald bereits als App installiert.
(function () {
var btn = document.getElementById("install-btn");
var laeuftBereitsAlsApp = window.matchMedia("(display-mode: standalone)").matches;
var promptEvent = null;
if (!laeuftBereitsAlsApp) {
window.addEventListener("beforeinstallprompt", function (e) {
e.preventDefault();
promptEvent = e;
btn.style.display = "flex";
});
}
btn.addEventListener("click", function () {
if (!promptEvent) return;
btn.style.display = "none";
promptEvent.prompt();
promptEvent.userChoice.then(function () { promptEvent = null; });
});
window.addEventListener("appinstalled", function () {
btn.style.display = "none";
});
if ("serviceWorker" in navigator) {
window.addEventListener("load", function () {
navigator.serviceWorker.register("/sw.js").catch(function () {});
});
}
})();
</script>
</body>
</html>