Neue Farbvariablen --c-lila/--c-lila-hover (sattes, kräftiges Violett) ersetzen das bisherige Gold/Gelb überall dort, wo es verwendet wurde: "Noch nicht öffentlich"-Badge, Verlaufsrand der Kopf-Kiste, sowie komplett das VanVan-Fenster (Rand, Avatar-Glow, Name, Eingabefeld-Fokus, Button). Gelbes Herz-Emoji im VanVan-Button ebenfalls zu einem violetten Herz gewechselt, damit nichts mehr gold/gelb übrig bleibt. Dogis Cyan-Fenster bleibt unverändert. Per Build + Browsertest verifiziert: neue Farbe korrekt angezeigt, Login-Funktion unverändert.
404 lines
16 KiB
HTML
404 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Zugang — Van's DIY & Bastelbedarf</title>
|
|
<meta name="robots" content="noindex, nofollow" />
|
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
<style>
|
|
:root {
|
|
--c-black: #0a0910;
|
|
--c-anthracite: #1b1a22;
|
|
--c-anthracite-light: #252333;
|
|
--c-text: #f4f1f7;
|
|
--c-text-muted: #b7aec4;
|
|
--c-accent: #5fd3ec;
|
|
--c-accent-hover: #3ca9c2;
|
|
--c-purple-glow: #9b7fd6;
|
|
/* 04.08.2026, auf ausdrücklichen Wunsch ("geiles spezielles lila"): ersetzt das vorherige
|
|
Gold/Gelb (VanVan-Fenster + Badge/Kopf-Kiste) durch ein kräftigeres, sattes Violett — im
|
|
Gegensatz zu --c-purple-glow (heller, für Verlaufsränder/Deko gedacht) hier bewusst
|
|
satter/dunkler gewählt, damit Text/Buttons in Vollfarbe genug Kontrast und "Wumms" haben. */
|
|
--c-lila: #a875f5;
|
|
--c-lila-hover: #7c3aed;
|
|
--radius-l: 22px;
|
|
--radius-m: 16px;
|
|
--ease: cubic-bezier(0.22, 1, 0.36, 1);
|
|
}
|
|
* { box-sizing: border-box; }
|
|
/* Für Screenreader vorhanden, visuell aber unsichtbar — ersetzt bei den Formularfeldern dieser
|
|
Seite den (allein nicht ausreichenden) Placeholder-Text durch ein echtes <label>. */
|
|
.sr-only {
|
|
position: absolute;
|
|
width: 1px; height: 1px;
|
|
padding: 0; margin: -1px;
|
|
overflow: hidden;
|
|
clip: rect(0, 0, 0, 0);
|
|
white-space: nowrap;
|
|
border: 0;
|
|
}
|
|
html, body { height: 100%; }
|
|
body {
|
|
margin: 0;
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
/* "safe center": zentriert normal, springt aber auf Start-Ausrichtung um, sobald der Inhalt
|
|
höher als der sichtbare Bereich ist — verhindert, dass bei kleineren Fenstern/Handys der
|
|
obere Teil (Badge/Überschrift) abgeschnitten wird, ohne dass man hochscrollen könnte (genau
|
|
das war der gemeldete Bug: 04.08.2026, zweite Runde). Browser ohne "safe center"-Unterstützung
|
|
nutzen einfach die Zeile darüber weiter — kein Fallback-Bruch. */
|
|
align-items: safe center;
|
|
justify-content: center;
|
|
padding: 2.5rem 1.5rem;
|
|
position: relative;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
background: var(--c-black);
|
|
background-image: radial-gradient(60% 50% at 15% 10%, color-mix(in srgb, var(--c-purple-glow) 22%, transparent), transparent 70%),
|
|
radial-gradient(50% 45% at 85% 90%, color-mix(in srgb, var(--c-accent) 16%, transparent), transparent 70%);
|
|
color: var(--c-text);
|
|
font-family: "Inter", "Manrope", system-ui, sans-serif;
|
|
line-height: 1.6;
|
|
}
|
|
/* Das echte Van's-Logo als riesiges, sehr dezentes Wasserzeichen im Hintergrund — invert()
|
|
dreht das schwarze Logo auf weißem Grund um (weiß -> schwarz, schwarz -> weiß), danach macht
|
|
mix-blend-mode:screen den (jetzt schwarzen) ehemals-weißen Kreis komplett unsichtbar und
|
|
lässt nur die (jetzt weißen) Linien leicht aufleuchten — kein Bildbearbeitungsprogramm nötig,
|
|
rein CSS. Langsame Drehung sorgt für einen dezenten "lebendigen" Glanz-Effekt.
|
|
position:fixed (04.08.2026 geändert, war vorher absolute): bleibt IMMER exakt in der Mitte
|
|
des sichtbaren Fensters, unabhängig davon, wie hoch der Inhalt gerade ist bzw. ob gescrollt
|
|
wird — vorher konnte das Logo bei einem hohen Inhalt (z.B. schmales Handy-Fenster) neben der
|
|
Bildschirmmitte statt in ihr landen, weil "top:50%" sich auf die GESAMTE Seitenhöhe bezog. */
|
|
.gate-logo-bg {
|
|
position: fixed;
|
|
top: 50%;
|
|
left: 50%;
|
|
width: min(1400px, 200vw);
|
|
height: min(1400px, 200vw);
|
|
transform: translate(-50%, -50%);
|
|
background: url("/logo.png") center / contain no-repeat;
|
|
filter: invert(1);
|
|
mix-blend-mode: screen;
|
|
opacity: 0.09;
|
|
animation: gate-logo-spin 120s linear infinite;
|
|
pointer-events: none;
|
|
}
|
|
@keyframes gate-logo-spin {
|
|
from { transform: translate(-50%, -50%) rotate(0deg); }
|
|
to { transform: translate(-50%, -50%) rotate(360deg); }
|
|
}
|
|
@media (prefers-reduced-motion: reduce) { .gate-logo-bg { animation: none; } }
|
|
|
|
/* 04.08.2026, auf ausdrücklichen Wunsch: statt EINER gemeinsamen Zugangscode-Box (in der beide
|
|
einfach irgendeinen der beiden Codes eintippen konnten) jetzt zwei eigene "Fenster" — eins für
|
|
qciga, eins für VanVan — im Stil einer anderen, bereits bestehenden Zwei-Personen-Zugangsseite,
|
|
aber komplett an Van's eigene Marke angepasst (Farben/Schrift/Wasserzeichen unverändert, siehe
|
|
Branding.md: kein Babyblau/Rot-Look von anderen Projekten, sondern die eigene Lila/Anthrazit/
|
|
Hellblau/Lila-Welt). Technisch ändert sich nichts: /gate-auth erkennt die Rolle ohnehin selbst
|
|
anhand DES CODES, nicht danach, welches Fenster benutzt wurde — die Aufteilung ist rein dafür
|
|
da, dass jede/r sofort das eigene Feld findet, statt raten zu müssen. */
|
|
.gate-wrap {
|
|
position: relative;
|
|
z-index: 1;
|
|
max-width: 700px;
|
|
width: 100%;
|
|
text-align: center;
|
|
}
|
|
/* Kopf-Kiste (04.08.2026, auf ausdrücklichen Wunsch "auch in speziellen Kisten"): dieselbe
|
|
"besondere" Formsprache wie die beiden Personen-Fenster darunter (wandernder Verlaufsrand +
|
|
Glanz-Sweep) — nur mit allen drei Markenfarben zugleich im Rand, statt der Einzelfarbe je
|
|
Person, damit sie sich sichtbar als "Dach" über beiden Fenstern liest. */
|
|
.gate-header {
|
|
position: relative;
|
|
overflow: hidden;
|
|
margin-bottom: 1.3rem;
|
|
padding: 1.7rem 2rem;
|
|
border-radius: var(--radius-l);
|
|
border: 1.5px solid transparent;
|
|
background:
|
|
linear-gradient(165deg, var(--c-anthracite-light), var(--c-anthracite)) padding-box,
|
|
linear-gradient(120deg, var(--c-accent), var(--c-purple-glow), var(--c-lila), var(--c-accent)) border-box;
|
|
background-size: 100% 100%, 300% 100%;
|
|
animation: gate-border-shift 9s ease-in-out infinite;
|
|
box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.7);
|
|
}
|
|
.gate-header::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: -60%;
|
|
width: 35%;
|
|
height: 100%;
|
|
background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.12), transparent);
|
|
transform: skewX(-18deg);
|
|
animation: gate-shine 6s ease-in-out infinite;
|
|
pointer-events: none;
|
|
border-radius: inherit;
|
|
}
|
|
.gate-header > * { position: relative; z-index: 1; }
|
|
@media (prefers-reduced-motion: reduce) { .gate-header, .gate-header::after { animation: none; } }
|
|
.gate-eyebrow {
|
|
display: inline-block;
|
|
font-size: 0.78rem;
|
|
font-weight: 700;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--c-lila);
|
|
background: color-mix(in srgb, var(--c-lila) 16%, transparent);
|
|
border: 1px solid color-mix(in srgb, var(--c-lila) 40%, transparent);
|
|
border-radius: 999px;
|
|
padding: 0.3rem 0.9rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
.gate-header h1 {
|
|
font-family: "Fraunces", "Playfair Display", Georgia, serif;
|
|
font-size: 1.7rem;
|
|
font-weight: 600;
|
|
margin: 0 0 0.6rem;
|
|
line-height: 1.2;
|
|
}
|
|
.gate-header p {
|
|
margin: 0;
|
|
color: var(--c-text-muted);
|
|
font-size: 0.96rem;
|
|
}
|
|
|
|
.gate-cards {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: center;
|
|
gap: 1.1rem;
|
|
}
|
|
.gate-card {
|
|
position: relative;
|
|
overflow: hidden;
|
|
flex: 1 1 250px;
|
|
max-width: 300px;
|
|
padding: 1.8rem 1.5rem;
|
|
border-radius: var(--radius-l);
|
|
border: 1.5px solid transparent;
|
|
background-size: 100% 100%, 300% 100%;
|
|
animation: gate-border-shift 9s ease-in-out infinite;
|
|
box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.7);
|
|
}
|
|
.gate-card-qciga {
|
|
background:
|
|
linear-gradient(165deg, var(--c-anthracite-light), var(--c-anthracite)) padding-box,
|
|
linear-gradient(120deg, var(--c-accent), var(--c-accent-hover), var(--c-purple-glow), var(--c-accent)) border-box;
|
|
}
|
|
.gate-card-vanvan {
|
|
background:
|
|
linear-gradient(165deg, var(--c-anthracite-light), var(--c-anthracite)) padding-box,
|
|
linear-gradient(120deg, var(--c-lila), var(--c-purple-glow), var(--c-accent), var(--c-lila)) border-box;
|
|
}
|
|
@keyframes gate-border-shift {
|
|
0%, 100% { background-position: 0 0, 0% 50%; }
|
|
50% { background-position: 0 0, 100% 50%; }
|
|
}
|
|
.gate-card::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: -60%;
|
|
width: 35%;
|
|
height: 100%;
|
|
background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
|
transform: skewX(-18deg);
|
|
animation: gate-shine 6s ease-in-out infinite;
|
|
pointer-events: none;
|
|
border-radius: inherit;
|
|
}
|
|
.gate-card-vanvan::after { animation-delay: 1.2s; }
|
|
@keyframes gate-shine {
|
|
0% { left: -60%; }
|
|
35%, 100% { left: 130%; }
|
|
}
|
|
.gate-card > * { position: relative; z-index: 1; }
|
|
@media (prefers-reduced-motion: reduce) { .gate-card, .gate-card::after { animation: none; } }
|
|
|
|
/* Avatar je Karte: dasselbe "Glow-Ring"-Prinzip wie beim .portrait-frame-Baustein auf der
|
|
restlichen Seite (siehe Branding.md), nur kompakt für ein kleines Zugangs-Fenster. VanVan
|
|
bekommt ihr echtes Porträtfoto, für qciga gibt es (noch) kein Foto in diesem Projekt — deshalb
|
|
ein passendes Icon in derselben Bildsprache statt eines geratenen/fremden Fotos. */
|
|
.gate-avatar {
|
|
position: relative;
|
|
width: 84px;
|
|
height: 84px;
|
|
margin: 0 auto 1rem;
|
|
}
|
|
.gate-avatar-glow {
|
|
position: absolute;
|
|
inset: -12px;
|
|
border-radius: 50%;
|
|
filter: blur(13px);
|
|
opacity: 0.6;
|
|
animation: gate-avatar-pulse 3.2s ease-in-out infinite;
|
|
}
|
|
.gate-card-qciga .gate-avatar-glow { background: radial-gradient(circle, color-mix(in srgb, var(--c-accent) 70%, transparent), transparent 72%); }
|
|
.gate-card-vanvan .gate-avatar-glow { background: radial-gradient(circle, color-mix(in srgb, var(--c-lila) 70%, transparent), transparent 72%); }
|
|
@keyframes gate-avatar-pulse {
|
|
0%, 100% { opacity: 0.45; transform: scale(1); }
|
|
50% { opacity: 0.85; transform: scale(1.12); }
|
|
}
|
|
@media (prefers-reduced-motion: reduce) { .gate-avatar-glow { animation: none; } }
|
|
.gate-avatar-photo,
|
|
.gate-avatar-icon {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 100%;
|
|
height: 100%;
|
|
border-radius: 50%;
|
|
background: linear-gradient(160deg, var(--c-anthracite-light), var(--c-anthracite));
|
|
}
|
|
.gate-avatar-photo { object-fit: cover; object-position: top center; }
|
|
.gate-card-qciga .gate-avatar-photo,
|
|
.gate-card-qciga .gate-avatar-icon { box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 50%, transparent), 0 10px 26px -10px rgba(0, 0, 0, 0.7); }
|
|
.gate-card-vanvan .gate-avatar-photo,
|
|
.gate-card-vanvan .gate-avatar-icon { box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-lila) 50%, transparent), 0 10px 26px -10px rgba(0, 0, 0, 0.7); }
|
|
.gate-avatar-icon { font-size: 2.1rem; }
|
|
|
|
.gate-card h2 {
|
|
font-family: "Fraunces", "Playfair Display", Georgia, serif;
|
|
font-size: 1.2rem;
|
|
font-weight: 600;
|
|
margin: 0 0 1.1rem;
|
|
}
|
|
.gate-card-qciga h2 { color: var(--c-accent); }
|
|
.gate-card-vanvan h2 { color: var(--c-lila); }
|
|
|
|
.gate-card input {
|
|
width: 100%;
|
|
padding: 0.85rem 0.9rem;
|
|
border-radius: 12px;
|
|
text-align: center;
|
|
letter-spacing: 0.08em;
|
|
font-size: 1rem;
|
|
margin-bottom: 0.8rem;
|
|
background: rgba(244, 241, 247, 0.05);
|
|
border: 1.5px solid rgba(244, 241, 247, 0.16);
|
|
color: var(--c-text);
|
|
font-family: inherit;
|
|
}
|
|
.gate-card-qciga input:focus { outline: none; border-color: var(--c-accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-accent) 25%, transparent); }
|
|
.gate-card-vanvan input:focus { outline: none; border-color: var(--c-lila); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-lila) 25%, transparent); }
|
|
|
|
.gate-card button {
|
|
width: 100%;
|
|
padding: 0.8rem 1rem;
|
|
border-radius: 12px;
|
|
border: none;
|
|
font-weight: 800;
|
|
font-size: 0.96rem;
|
|
cursor: pointer;
|
|
transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
|
|
}
|
|
.gate-card-qciga button { background: linear-gradient(120deg, var(--c-accent), var(--c-accent-hover)); color: var(--c-black); }
|
|
.gate-card-qciga button:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -10px color-mix(in srgb, var(--c-accent) 60%, transparent); }
|
|
.gate-card-vanvan button { background: linear-gradient(120deg, var(--c-lila), var(--c-lila-hover)); color: var(--c-black); }
|
|
.gate-card-vanvan button:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -10px color-mix(in srgb, var(--c-lila) 60%, transparent); }
|
|
|
|
.gate-fehler {
|
|
color: #ff9a9a;
|
|
font-size: 0.85rem;
|
|
margin: 0.8rem 0 0;
|
|
display: none;
|
|
}
|
|
.gate-fehler.zeige { display: block; }
|
|
|
|
.gate-logo {
|
|
font-family: "Fraunces", "Playfair Display", Georgia, serif;
|
|
font-weight: 700;
|
|
font-size: 0.95rem;
|
|
color: var(--c-text-muted);
|
|
margin: 1.6rem 0 0;
|
|
}
|
|
|
|
@media (max-width: 560px) {
|
|
.gate-card { max-width: 100%; flex-basis: 100%; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="gate-logo-bg" aria-hidden="true"></div>
|
|
<div class="gate-wrap">
|
|
<div class="gate-header">
|
|
<span class="gate-eyebrow">🔒 Noch nicht öffentlich</span>
|
|
<h1>Van's DIY & Bastelbedarf</h1>
|
|
<p>Diese Seite ist gerade im Aufbau und noch nicht für die Öffentlichkeit freigegeben.<br />Zugangscode eingeben, um weiterzukommen.</p>
|
|
</div>
|
|
|
|
<div class="gate-cards">
|
|
<div class="gate-card gate-card-vanvan">
|
|
<div class="gate-avatar" aria-hidden="true">
|
|
<span class="gate-avatar-glow"></span>
|
|
<img class="gate-avatar-photo" src="/img/gate-avatar-vanvan.webp" alt="" />
|
|
</div>
|
|
<h2>VanVan</h2>
|
|
<form class="gate-form" data-role="vanvan">
|
|
<label class="sr-only" for="gate-code-vanvan">Zugangscode für VanVan</label>
|
|
<input type="text" id="gate-code-vanvan" placeholder="Zugangscode" autocomplete="off" autocapitalize="off" spellcheck="false" />
|
|
<button type="submit">💜 Öffnen</button>
|
|
</form>
|
|
<p class="gate-fehler" data-fehler-for="vanvan" role="alert" aria-live="assertive"></p>
|
|
</div>
|
|
|
|
<div class="gate-card gate-card-qciga">
|
|
<div class="gate-avatar" aria-hidden="true">
|
|
<span class="gate-avatar-glow"></span>
|
|
<img class="gate-avatar-photo" src="/img/gate-avatar-dogi.webp" alt="" />
|
|
</div>
|
|
<h2>Dogi</h2>
|
|
<form class="gate-form" data-role="qciga">
|
|
<label class="sr-only" for="gate-code-qciga">Zugangscode für Dogi</label>
|
|
<input type="text" id="gate-code-qciga" placeholder="Zugangscode" autocomplete="off" autocapitalize="off" spellcheck="false" />
|
|
<button type="submit">🩵 Öffnen</button>
|
|
</form>
|
|
<p class="gate-fehler" data-fehler-for="qciga" role="alert" aria-live="assertive"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="gate-logo">🧶 Handgemacht mit Liebe</p>
|
|
</div>
|
|
<script>
|
|
(function () {
|
|
const params = new URLSearchParams(location.search);
|
|
const next = params.get("next") || "/";
|
|
// Ein gemeinsamer Handler für beide Fenster — /gate-auth erkennt die Rolle ohnehin selbst
|
|
// anhand des eingegebenen Codes, unabhängig davon, welches der beiden Fenster benutzt wurde.
|
|
document.querySelectorAll(".gate-form").forEach(function (form) {
|
|
const role = form.dataset.role;
|
|
const input = form.querySelector("input");
|
|
const fehlerEl = document.querySelector('[data-fehler-for="' + role + '"]');
|
|
form.addEventListener("submit", async function (e) {
|
|
e.preventDefault();
|
|
fehlerEl.classList.remove("zeige");
|
|
const code = input.value.trim();
|
|
if (!code) return;
|
|
try {
|
|
const res = await fetch("/gate-auth", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ code, next }),
|
|
});
|
|
const data = await res.json();
|
|
if (!res.ok || !data.ok) {
|
|
fehlerEl.textContent = (data && data.error) || "Falscher Zugangscode.";
|
|
fehlerEl.classList.add("zeige");
|
|
return;
|
|
}
|
|
location.href = data.next || "/";
|
|
} catch {
|
|
fehlerEl.textContent = "Verbindung fehlgeschlagen. Bitte nochmal versuchen.";
|
|
fehlerEl.classList.add("zeige");
|
|
}
|
|
});
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|