Zugangsseite: zwei eigene Fenster für qciga und VanVan statt einer gemeinsamen Box
Auf ausdrücklichen Wunsch im Stil einer bereits bestehenden Zwei-Personen-Zugangsseite umgebaut, aber komplett an Van's eigene Marke angepasst (Farben/Schrift/Wasserzeichen unverändert: Lila/ Anthrazit/Hellblau/Gold statt fremder Projektfarben). Jede Person bekommt ihr eigenes Fenster mit Avatar (VanVan: ihr echtes Porträtfoto; qciga: passendes Icon, da noch kein Foto in diesem Projekt hinterlegt ist), eigenem Codefeld und eigenem "Öffnen"-Button in unterschiedlicher Akzentfarbe (Cyan/Violett für qciga, Gold/Violett für VanVan). Technisch unverändert: /gate-auth erkennt die Rolle weiterhin selbst anhand des eingegebenen Codes, unabhängig vom benutzten Fenster. Dabei gefundener und behobener Bug: /img/vanvan-portrait.png wurde von der Zugangs-Schranke selbst blockiert (302) — das für den Avatar gebrauchte Foto zeigte deshalb nur einen leeren Kreis. Gezielt nur diese eine Datei freigegeben (kein Shop-/Kundendatum, ohnehin VanVans öffentliches Porträtfoto). Per echtem Browsertest verifiziert: beide Fenster funktional getrennt (falscher Code im einen Fenster zeigt den Fehler nur dort, richtiger Code im anderen Fenster loggt korrekt ein), Layout auf Desktop nebeneinander und auf schmalen Bildschirmen sauber gestapelt.
This commit is contained in:
+204
-80
@@ -16,6 +16,8 @@
|
||||
--c-accent: #5fd3ec;
|
||||
--c-accent-hover: #3ca9c2;
|
||||
--c-purple-glow: #9b7fd6;
|
||||
--c-gold: #e3b23c;
|
||||
--c-gold-hover: #c99527;
|
||||
--radius-l: 22px;
|
||||
--radius-m: 16px;
|
||||
--ease: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
@@ -73,26 +75,82 @@
|
||||
to { transform: translate(-50%, -50%) rotate(360deg); }
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) { .gate-logo-bg { animation: none; } }
|
||||
.gate-box {
|
||||
|
||||
/* 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/Gold-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;
|
||||
max-width: 430px;
|
||||
z-index: 1;
|
||||
max-width: 700px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 2.4rem 2rem;
|
||||
}
|
||||
.gate-header { margin-bottom: 1.6rem; }
|
||||
.gate-eyebrow {
|
||||
display: inline-block;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--c-gold);
|
||||
background: color-mix(in srgb, var(--c-gold) 16%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--c-gold) 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:
|
||||
linear-gradient(165deg, var(--c-anthracite-light), var(--c-anthracite)) padding-box,
|
||||
linear-gradient(120deg, #9b7fd6, var(--c-accent), #e3b23c, #9b7fd6) 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-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-gold), var(--c-purple-glow), var(--c-accent), var(--c-gold)) border-box;
|
||||
}
|
||||
@keyframes gate-border-shift {
|
||||
0%, 100% { background-position: 0 0, 0% 50%; }
|
||||
50% { background-position: 0 0, 100% 50%; }
|
||||
}
|
||||
.gate-box::after {
|
||||
.gate-card::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -105,75 +163,105 @@
|
||||
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-box > * { position: relative; z-index: 1; }
|
||||
@media (prefers-reduced-motion: reduce) { .gate-box, .gate-box::after { animation: none; } }
|
||||
.gate-eyebrow {
|
||||
display: inline-block;
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
color: #e3b23c;
|
||||
background: color-mix(in srgb, #e3b23c 16%, transparent);
|
||||
border: 1px solid color-mix(in srgb, #e3b23c 40%, transparent);
|
||||
border-radius: 999px;
|
||||
padding: 0.3rem 0.9rem;
|
||||
margin-bottom: 1rem;
|
||||
.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-box 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-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-box p {
|
||||
margin: 0 0 1.4rem;
|
||||
color: var(--c-text-muted);
|
||||
font-size: 0.96rem;
|
||||
.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-gold) 70%, transparent), transparent 72%); }
|
||||
@keyframes gate-avatar-pulse {
|
||||
0%, 100% { opacity: 0.45; transform: scale(1); }
|
||||
50% { opacity: 0.85; transform: scale(1.12); }
|
||||
}
|
||||
.gate-box input {
|
||||
@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%;
|
||||
padding: 0.9rem 1rem;
|
||||
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-gold) 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-gold); }
|
||||
|
||||
.gate-card input {
|
||||
width: 100%;
|
||||
padding: 0.85rem 0.9rem;
|
||||
border-radius: 12px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: 1.05rem;
|
||||
margin-bottom: 0.9rem;
|
||||
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-box 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-box button {
|
||||
.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-gold); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-gold) 25%, transparent); }
|
||||
|
||||
.gate-card button {
|
||||
width: 100%;
|
||||
padding: 0.85rem 1rem;
|
||||
padding: 0.8rem 1rem;
|
||||
border-radius: 12px;
|
||||
border: none;
|
||||
background: linear-gradient(120deg, var(--c-accent), var(--c-accent-hover));
|
||||
color: var(--c-black);
|
||||
font-weight: 800;
|
||||
font-size: 1rem;
|
||||
font-size: 0.96rem;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
|
||||
}
|
||||
.gate-box button:hover { transform: translateY(-2px); box-shadow: 0 10px 24px -10px color-mix(in srgb, var(--c-accent) 60%, transparent); }
|
||||
.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-gold), var(--c-gold-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-gold) 60%, transparent); }
|
||||
|
||||
.gate-fehler {
|
||||
color: #ff9a9a;
|
||||
font-size: 0.88rem;
|
||||
margin: 0.9rem 0 0;
|
||||
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;
|
||||
@@ -181,50 +269,86 @@
|
||||
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-box">
|
||||
<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>
|
||||
<form id="gate-form">
|
||||
<label class="sr-only" for="gate-code">Zugangscode</label>
|
||||
<input type="text" id="gate-code" placeholder="Zugangscode" autocomplete="off" autocapitalize="off" spellcheck="false" autofocus />
|
||||
<button type="submit">Weiter</button>
|
||||
</form>
|
||||
<p class="gate-fehler" id="gate-fehler" role="alert" aria-live="assertive"></p>
|
||||
<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-qciga">
|
||||
<div class="gate-avatar" aria-hidden="true">
|
||||
<span class="gate-avatar-glow"></span>
|
||||
<span class="gate-avatar-icon">🧑💻</span>
|
||||
</div>
|
||||
<h2>qciga</h2>
|
||||
<form class="gate-form" data-role="qciga">
|
||||
<label class="sr-only" for="gate-code-qciga">Zugangscode für qciga</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 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/vanvan-portrait.png" 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>
|
||||
|
||||
<p class="gate-logo">🧶 Handgemacht mit Liebe</p>
|
||||
</div>
|
||||
<script>
|
||||
(function () {
|
||||
const params = new URLSearchParams(location.search);
|
||||
const next = params.get("next") || "/";
|
||||
const form = document.getElementById("gate-form");
|
||||
const fehlerEl = document.getElementById("gate-fehler");
|
||||
form.addEventListener("submit", async function (e) {
|
||||
e.preventDefault();
|
||||
fehlerEl.classList.remove("zeige");
|
||||
const code = document.getElementById("gate-code").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.";
|
||||
// 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");
|
||||
return;
|
||||
}
|
||||
location.href = data.next || "/";
|
||||
} catch {
|
||||
fehlerEl.textContent = "Verbindung fehlgeschlagen. Bitte nochmal versuchen.";
|
||||
fehlerEl.classList.add("zeige");
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user