Restyle shell and home page with Jayuhime brand; add account and privacy modals
- Replaces amber/Manrope shell with sticky purple nav (Outfit + Fredoka) - Adds account modal: profile info, Datenschutzerklärung, DSGVO Art. 17 delete flow - Home: new hero with animated blobs/stars/countdown, inline vote picker, clip submit form, show-reminder, FAQ - Switches base palette to purple (#f4eefb / #3f3556) and adds keyframe animations Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,141 +1,282 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, ref } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { Star } from '@lucide/vue'
|
||||
|
||||
import Button from './ui/Button.vue'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { usePhases } from '../composables/usePhases'
|
||||
|
||||
const route = useRoute()
|
||||
const authStore = useAuthStore()
|
||||
const { infoForPhaseKey } = usePhases()
|
||||
const loginOpen = ref(false)
|
||||
const loginError = ref('')
|
||||
|
||||
const loginForm = reactive({
|
||||
twitchUserId: 'jayuhime_demo',
|
||||
displayName: 'Jayuhime',
|
||||
role: 'viewer' as 'viewer' | 'admin',
|
||||
})
|
||||
|
||||
const accountOpen = ref(false)
|
||||
const deleteConfirm = ref(false)
|
||||
const privacyOpen = ref(false)
|
||||
|
||||
defineExpose({ privacyOpen })
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Home', to: '/' },
|
||||
{ label: 'Nominierung', to: '/nominations', requiresAuth: true, phase: 'nomination' },
|
||||
{ label: 'Voting', to: '/voting', requiresAuth: true, phase: 'voting' },
|
||||
{ label: 'Clips', to: '/clips', requiresAuth: true, phase: 'nomination' },
|
||||
{ label: 'Gewinner', to: '/winners' },
|
||||
{ label: 'Admin', to: '/admin' },
|
||||
]
|
||||
|
||||
const currentLabel = computed(
|
||||
() => navItems.find((item) => route.path === item.to || route.path.startsWith(`${item.to}/`))?.label ?? 'Awards',
|
||||
)
|
||||
|
||||
const visibleNavItems = computed(() =>
|
||||
navItems.filter((item) => {
|
||||
if (item.to === '/admin') return authStore.isAdmin
|
||||
// Teilnahme-Seiten erst nach Login zeigen
|
||||
if (item.requiresAuth && !authStore.isLoggedIn) return false
|
||||
// ... und nur, solange ihre Phase aktiv ist
|
||||
if (item.phase && infoForPhaseKey(item.phase).state !== 'active') return false
|
||||
return true
|
||||
}),
|
||||
)
|
||||
|
||||
async function login(role: 'viewer' | 'admin') {
|
||||
loginError.value = ''
|
||||
loginForm.role = role
|
||||
|
||||
async function doLogin() {
|
||||
try {
|
||||
await authStore.login(loginForm)
|
||||
loginOpen.value = false
|
||||
} catch (error) {
|
||||
loginError.value = error instanceof Error ? error.message : 'Login fehlgeschlagen.'
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function doLogout() {
|
||||
accountOpen.value = false
|
||||
deleteConfirm.value = false
|
||||
await authStore.logout()
|
||||
}
|
||||
|
||||
function isActive(to: string) {
|
||||
if (to === '/') return route.path === '/'
|
||||
return route.path === to || route.path.startsWith(to + '/')
|
||||
}
|
||||
|
||||
const linkBase = 'padding:9px 14px;border-radius:9px;font-family:\'Outfit\',sans-serif;font-size:14px;text-decoration:none;display:inline-block;transition:all .15s;'
|
||||
const linkActive = linkBase + 'background:rgba(139,108,219,.1);color:#5f44ad;font-weight:600;'
|
||||
const linkInactive = linkBase + 'background:transparent;color:#6f6685;font-weight:500;'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="min-h-screen overflow-x-hidden bg-[linear-gradient(180deg,#fffdf9_0%,#fff6ee_38%,#fff9f4_100%)] text-slate-800">
|
||||
<div class="pointer-events-none absolute inset-x-0 top-0 h-[520px] bg-[radial-gradient(circle_at_top_left,_rgba(237,214,167,0.38),transparent_34%),radial-gradient(circle_at_top_right,_rgba(210,195,255,0.32),transparent_28%)]" />
|
||||
<div class="pointer-events-none absolute left-1/2 top-36 h-[560px] w-[560px] -translate-x-1/2 rounded-full border border-white/70 opacity-70 blur-3xl" />
|
||||
<div style="min-height:100vh;overflow-x:hidden;font-family:'Outfit',sans-serif;line-height:1.5;background:#f4eefb;color:#3f3556;">
|
||||
|
||||
<div class="relative mx-auto w-full max-w-[1460px] px-4 py-4 sm:px-6 lg:px-10">
|
||||
<div class="mb-5 flex items-center justify-between border-b border-black/8 px-2 pb-3 text-[11px] uppercase tracking-[0.34em] text-slate-500">
|
||||
<span>VTuber Star Awards 2026</span>
|
||||
<span>{{ currentLabel }}</span>
|
||||
</div>
|
||||
<!-- Nav -->
|
||||
<nav style="position:sticky;top:0;z-index:50;background:rgba(248,243,254,.86);border-bottom:1px solid #ece2fa;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);">
|
||||
<div style="max-width:1200px;margin:0 auto;padding:0 24px;height:64px;display:flex;align-items:center;gap:16px;">
|
||||
|
||||
<header
|
||||
class="mb-10 flex flex-col gap-6 rounded-[24px] border border-white/70 bg-white/72 px-5 py-5 shadow-[0_18px_55px_rgba(93,63,135,0.08)] backdrop-blur lg:px-7"
|
||||
>
|
||||
<div class="flex flex-col gap-5 lg:flex-row lg:items-center lg:justify-between">
|
||||
<RouterLink to="/" class="flex items-center gap-4 text-slate-800 no-underline">
|
||||
<div
|
||||
class="grid h-12 w-12 place-items-center rounded-[1.1rem] bg-[linear-gradient(135deg,#f6e3b2,#f5c877)] text-amber-950 shadow-[0_16px_28px_rgba(245,200,119,0.35)]"
|
||||
<!-- Logo -->
|
||||
<RouterLink to="/" style="display:flex;align-items:center;gap:10px;text-decoration:none;flex:none;">
|
||||
<div style="width:36px;height:36px;border-radius:10px;background:linear-gradient(135deg,#8b6cdb,#e7b13e);display:flex;align-items:center;justify-content:center;color:#fff;font-size:18px;box-shadow:0 6px 14px rgba(139,108,219,.3);flex:none;">✦</div>
|
||||
<span style="font-family:'Fredoka',sans-serif;font-size:17px;font-weight:600;color:#3f3556;">VTuber Star Award</span>
|
||||
</RouterLink>
|
||||
|
||||
<!-- Links -->
|
||||
<nav style="display:flex;align-items:center;gap:4px;margin-left:auto;">
|
||||
<RouterLink
|
||||
v-for="item in visibleNavItems"
|
||||
:key="item.to"
|
||||
:to="item.to"
|
||||
:style="isActive(item.to) ? linkActive : linkInactive"
|
||||
>{{ item.label }}</RouterLink>
|
||||
<RouterLink
|
||||
v-if="authStore.isAdmin"
|
||||
to="/admin"
|
||||
:style="route.path.startsWith('/admin') ? linkActive : linkInactive"
|
||||
>Admin</RouterLink>
|
||||
</nav>
|
||||
|
||||
<!-- Auth -->
|
||||
<div style="display:flex;align-items:center;gap:8px;">
|
||||
<template v-if="authStore.session">
|
||||
<button
|
||||
@click="accountOpen = true"
|
||||
style="display:inline-flex;align-items:center;gap:8px;padding:9px 14px;border-radius:999px;border:none;background:rgba(139,108,219,.08);color:#6a4fb8;font-family:'Outfit',sans-serif;font-weight:600;font-size:14px;cursor:pointer;"
|
||||
>
|
||||
<Star class="h-5 w-5" />
|
||||
</div>
|
||||
<div>
|
||||
<strong class="block text-sm tracking-[0.35em]">VTUBER</strong>
|
||||
<span class="block text-[11px] tracking-[0.45em] text-slate-500">STAR AWARDS</span>
|
||||
</div>
|
||||
</RouterLink>
|
||||
<span style="width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,#8b6cdb,#7355c8);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex:none;">
|
||||
{{ authStore.session.displayName.charAt(0).toUpperCase() }}
|
||||
</span>
|
||||
@{{ authStore.session.twitchUserId }}
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button
|
||||
@click="doLogin"
|
||||
style="display:inline-flex;align-items:center;gap:8px;padding:10px 18px;border-radius:999px;border:none;background:linear-gradient(135deg,#8b6cdb,#7355c8);color:#fff;font-family:'Outfit',sans-serif;font-weight:600;font-size:14px;cursor:pointer;box-shadow:0 6px 18px rgba(124,86,196,.3);"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="white">
|
||||
<path d="M4 2L2.4 6v14.5h5V23h2.7l2.5-2.5h4L21.6 16V2H4zm15.3 13.1l-2.9 2.9h-4.4l-2.5 2.5v-2.5H6.7V3.7h12.6v11.4z"/>
|
||||
<path d="M11.1 7.1h1.7v5h-1.7zM15.7 7.1h1.7v5h-1.7z"/>
|
||||
</svg>
|
||||
Mit Twitch anmelden
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<template v-if="authStore.session">
|
||||
<div class="rounded-full border border-violet-100 bg-violet-50/70 px-4 py-2 text-sm text-violet-800">
|
||||
{{ authStore.session.displayName }} · {{ authStore.session.role }}
|
||||
<!-- Page content: home is full-width, all other views get a max-width container -->
|
||||
<template v-if="route.name === 'home'">
|
||||
<slot />
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="max-width:1460px;margin:0 auto;padding:16px 16px 0;box-sizing:border-box;">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Account modal -->
|
||||
<Teleport to="body">
|
||||
<div
|
||||
v-if="accountOpen"
|
||||
@click.self="accountOpen = false; deleteConfirm = false"
|
||||
style="position:fixed;inset:0;z-index:300;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(40,24,70,.55);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);"
|
||||
>
|
||||
<div style="position:relative;width:100%;max-width:480px;background:#fff;border-radius:24px;box-shadow:0 40px 90px rgba(40,24,70,.4);overflow:hidden;">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;padding:24px 28px 18px;border-bottom:1px solid #f1ecfb;">
|
||||
<div>
|
||||
<div style="font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:#8b6cdb;margin-bottom:4px;">Mein Profil</div>
|
||||
<h2 style="font-family:'Cormorant Garamond',serif;font-weight:700;font-size:24px;margin:0;color:#3f3556;">@{{ authStore.session?.twitchUserId }}</h2>
|
||||
</div>
|
||||
<button
|
||||
@click="accountOpen = false; deleteConfirm = false"
|
||||
style="width:34px;height:34px;border-radius:50%;border:none;background:#f1ecfb;color:#8b6cdb;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;"
|
||||
>✕</button>
|
||||
</div>
|
||||
<div style="padding:24px 28px;display:flex;flex-direction:column;gap:16px;">
|
||||
<div style="display:flex;align-items:center;gap:10px;padding:13px 16px;border-radius:14px;background:#f6f1fd;border:1px solid #ede4fb;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="#9146FF">
|
||||
<path d="M4 2L2.4 6v14.5h5V23h2.7l2.5-2.5h4L21.6 16V2H4zm15.3 13.1l-2.9 2.9h-4.4l-2.5 2.5v-2.5H6.7V3.7h12.6v11.4z"/>
|
||||
<path d="M11.1 7.1h1.7v5h-1.7zM15.7 7.1h1.7v5h-1.7z"/>
|
||||
</svg>
|
||||
<span style="font-size:14px;color:#5f44ad;font-weight:500;">Angemeldet über Twitch</span>
|
||||
</div>
|
||||
<div style="padding:16px;border-radius:14px;background:#fafafa;border:1px solid #f0eafc;">
|
||||
<p style="font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;color:#a99fc0;margin:0 0 10px;">Gespeicherte Daten</p>
|
||||
<div style="display:flex;flex-direction:column;gap:7px;">
|
||||
<div style="display:flex;justify-content:space-between;font-size:13.5px;">
|
||||
<span style="color:#6f6685;">Twitch-ID</span>
|
||||
<span style="font-weight:600;color:#3f3556;">@{{ authStore.session?.twitchUserId }}</span>
|
||||
</div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:13.5px;">
|
||||
<span style="color:#6f6685;">Rolle</span>
|
||||
<span style="font-weight:700;color:#8b6cdb;text-transform:uppercase;font-size:11px;letter-spacing:1px;">{{ authStore.session?.role }}</span>
|
||||
</div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:13.5px;">
|
||||
<span style="color:#6f6685;">Einreichungen</span>
|
||||
<span style="font-weight:600;color:#3f3556;">Clips, Votes, Nominierungen</span>
|
||||
</div>
|
||||
<div style="display:flex;justify-content:space-between;font-size:13.5px;">
|
||||
<span style="color:#6f6685;">Löschfrist</span>
|
||||
<span style="font-weight:600;color:#059669;">März 2027 (auto.)</span>
|
||||
</div>
|
||||
</div>
|
||||
<Button variant="ghost" @click="authStore.logout()">Abmelden</Button>
|
||||
</div>
|
||||
<button
|
||||
@click="privacyOpen = true"
|
||||
style="display:flex;align-items:center;gap:8px;padding:12px 16px;border-radius:12px;border:1px solid #ede4fb;background:#f9f6ff;color:#6a4fb8;font-family:'Outfit',sans-serif;font-size:13.5px;font-weight:600;cursor:pointer;text-align:left;width:100%;"
|
||||
>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
||||
</svg>
|
||||
Datenschutzerklärung lesen
|
||||
</button>
|
||||
<button
|
||||
@click="doLogout"
|
||||
style="display:flex;align-items:center;gap:8px;padding:12px 16px;border-radius:12px;border:1px solid #e2e8f0;background:#f8fafc;color:#64748b;font-family:'Outfit',sans-serif;font-size:13.5px;font-weight:600;cursor:pointer;text-align:left;width:100%;"
|
||||
>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/>
|
||||
<polyline points="16 17 21 12 16 7"/>
|
||||
<line x1="21" y1="12" x2="9" y2="12"/>
|
||||
</svg>
|
||||
Abmelden
|
||||
</button>
|
||||
<template v-if="!deleteConfirm">
|
||||
<button
|
||||
@click="deleteConfirm = true"
|
||||
style="display:flex;align-items:center;gap:8px;padding:12px 16px;border-radius:12px;border:1px solid #fecdd3;background:#fff5f5;color:#e11d48;font-family:'Outfit',sans-serif;font-size:13.5px;font-weight:600;cursor:pointer;text-align:left;width:100%;"
|
||||
>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="3 6 5 6 21 6"/>
|
||||
<path d="M19 6l-1 14H6L5 6"/>
|
||||
<path d="M10 11v6M14 11v6"/>
|
||||
</svg>
|
||||
Meine Daten löschen (Löschrecht Art. 17 DSGVO)
|
||||
</button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<Button variant="ghost" @click="loginOpen = !loginOpen">Einloggen</Button>
|
||||
<Button class="gap-2" @click="login('viewer')">
|
||||
<svg class="h-4 w-4 fill-current" viewBox="0 0 16 16"><path d="M2.5 0 0 2.5v11h3.5V16h2l2.5-2.5h3l5-5V0H2.5Zm12 8L12 10.5H8.5L6 13v-2.5H2.5V2h12v6Z"/><path d="M11.5 4h1.5v3.5h-1.5V4Zm-3.5 0h1.5v3.5H8V4Z"/></svg>
|
||||
Anmelden mit Twitch
|
||||
</Button>
|
||||
<div style="padding:16px;border-radius:14px;background:#fff5f5;border:1.5px solid #fecdd3;">
|
||||
<p style="font-size:13.5px;color:#9f1239;font-weight:600;margin:0 0 6px;">Alle deine Daten werden sofort gelöscht.</p>
|
||||
<p style="font-size:12.5px;color:#e11d48;margin:0 0 14px;line-height:1.5;">Das umfasst deine Votes, Nominierungen und Clip-Einreichungen. Diese Aktion kann nicht rückgängig gemacht werden.</p>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<button @click="deleteConfirm = false" style="flex:1;padding:10px;border-radius:10px;border:1px solid #e6dcf6;background:white;color:#6f6685;font-family:'Outfit',sans-serif;font-weight:600;font-size:13px;cursor:pointer;">Abbrechen</button>
|
||||
<button @click="doLogout" style="flex:1;padding:10px;border-radius:10px;border:none;background:#e11d48;color:white;font-family:'Outfit',sans-serif;font-weight:700;font-size:13px;cursor:pointer;">Jetzt löschen</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<div v-if="loginOpen && !authStore.session" class="rounded-[28px] border border-violet-100 bg-white/80 p-5">
|
||||
<div class="grid gap-4 md:grid-cols-3">
|
||||
<input v-model="loginForm.displayName" type="text" class="rounded-2xl border border-violet-200 px-4 py-3" placeholder="Anzeigename" />
|
||||
<input v-model="loginForm.twitchUserId" type="text" class="rounded-2xl border border-violet-200 px-4 py-3" placeholder="Twitch Nutzer-ID" />
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<Button :disabled="authStore.loading" @click="login('viewer')">
|
||||
{{ authStore.loading ? 'Loggt ein ...' : 'Viewer-Login' }}
|
||||
</Button>
|
||||
<Button variant="secondary" :disabled="authStore.loading" @click="login('admin')">Admin-Login</Button>
|
||||
<!-- Privacy modal -->
|
||||
<Teleport to="body">
|
||||
<div
|
||||
v-if="privacyOpen"
|
||||
@click.self="privacyOpen = false"
|
||||
style="position:fixed;inset:0;z-index:400;display:flex;align-items:center;justify-content:center;padding:24px;background:rgba(40,24,70,.55);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);"
|
||||
>
|
||||
<div style="position:relative;width:100%;max-width:680px;max-height:88vh;overflow:hidden;display:flex;flex-direction:column;background:#fff;border-radius:24px;box-shadow:0 40px 90px rgba(40,24,70,.4);">
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;padding:24px 32px 18px;border-bottom:1px solid #f1ecfb;flex:none;">
|
||||
<div>
|
||||
<div style="font-size:11px;font-weight:700;letter-spacing:2px;text-transform:uppercase;color:#8b6cdb;margin-bottom:4px;">Rechtliches</div>
|
||||
<h2 style="font-family:'Cormorant Garamond',serif;font-weight:700;font-size:26px;margin:0;color:#3f3556;">Datenschutzerklärung</h2>
|
||||
</div>
|
||||
<button @click="privacyOpen = false" style="width:34px;height:34px;border-radius:50%;border:none;background:#f1ecfb;color:#8b6cdb;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;">✕</button>
|
||||
</div>
|
||||
<p v-if="loginError" class="mt-3 text-sm text-rose-700">{{ loginError }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3 border-t border-black/6 pt-3 lg:flex-row lg:items-center lg:justify-between">
|
||||
<nav class="flex flex-wrap items-center gap-1 rounded-full border border-violet-100/80 bg-violet-50/50 p-1.5 text-sm font-medium text-slate-500">
|
||||
<RouterLink
|
||||
v-for="item in visibleNavItems"
|
||||
:key="item.to"
|
||||
:to="item.to"
|
||||
class="rounded-full px-4 py-2 transition"
|
||||
:class="route.path === item.to || route.path.startsWith(`${item.to}/`)
|
||||
? 'bg-white text-violet-800 shadow-[0_4px_14px_rgba(124,92,255,0.18)] ring-1 ring-violet-100'
|
||||
: 'hover:bg-white/60 hover:text-violet-700'"
|
||||
>
|
||||
{{ item.label }}
|
||||
</RouterLink>
|
||||
</nav>
|
||||
|
||||
<div class="flex items-center gap-3 text-xs uppercase tracking-[0.24em] text-slate-500">
|
||||
<span class="inline-flex h-2 w-2 rounded-full bg-emerald-500" />
|
||||
Community Voting live
|
||||
<div style="overflow-y:auto;padding:28px 32px;flex:1;display:flex;flex-direction:column;gap:22px;font-family:'Outfit',sans-serif;font-size:14px;line-height:1.65;color:#6f6685;">
|
||||
<div>
|
||||
<h3 style="font-size:15px;font-weight:700;color:#3f3556;margin:0 0 8px;">Verantwortliche:r</h3>
|
||||
<p style="margin:0;">VTuber Star Awards, vertreten durch Jayuhime. Kontakt: datenschutz@vtuber-star-awards.de</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="font-size:15px;font-weight:700;color:#3f3556;margin:0 0 8px;">Welche Daten wir verarbeiten</h3>
|
||||
<p style="margin:0 0 8px;">Bei Teilnahme (Voting, Nominierung, Clip-Einreichung) verarbeiten wir ausschließlich deine <strong style="color:#3f3556;">Twitch-User-ID</strong> (ein technischer Bezeichner, kein Klarname) sowie den Zeitstempel deiner Aktion.</p>
|
||||
<p style="margin:0;">Für Show-Erinnerungen speichern wir optional deine E-Mail-Adresse.</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="font-size:15px;font-weight:700;color:#3f3556;margin:0 0 8px;">Rechtsgrundlage</h3>
|
||||
<p style="margin:0;">Verarbeitung auf Basis von <strong style="color:#3f3556;">Art. 6 Abs. 1 lit. b DSGVO</strong> (Vertragserfüllung / vorvertragliche Maßnahmen) — deine Teilnahme ist freiwillig. Für E-Mail-Erinnerungen gilt Art. 6 Abs. 1 lit. a DSGVO (Einwilligung).</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="font-size:15px;font-weight:700;color:#3f3556;margin:0 0 8px;">Zweck der Verarbeitung</h3>
|
||||
<p style="margin:0;">Durchführung des VTuber Star Awards: Sicherstellung fairer Abstimmung (1 Stimme / Person), Spam-Prävention, Admin-Review von Clip-Einreichungen.</p>
|
||||
</div>
|
||||
<div style="background:#fef9c3;border:1px solid #fef08a;border-radius:12px;padding:14px 16px;">
|
||||
<h3 style="font-size:15px;font-weight:700;color:#854d0e;margin:0 0 6px;">Löschfristen</h3>
|
||||
<p style="margin:0;color:#92400e;">Alle Teilnahmedaten (Twitch-IDs, Votes, Nominierungen, Clips) werden <strong>spätestens 6 Monate nach der Award-Show</strong> (d. h. bis März 2027) automatisch gelöscht. E-Mail-Adressen werden nach der Show sofort gelöscht.</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="font-size:15px;font-weight:700;color:#3f3556;margin:0 0 8px;">Deine Rechte (Art. 15–22 DSGVO)</h3>
|
||||
<ul style="margin:0;padding-left:18px;display:flex;flex-direction:column;gap:5px;">
|
||||
<li><strong style="color:#3f3556;">Auskunft</strong> — du kannst jederzeit erfragen, welche Daten wir über dich gespeichert haben.</li>
|
||||
<li><strong style="color:#3f3556;">Löschung</strong> — du kannst die sofortige Löschung deiner Daten verlangen. Nutze den Button in deinem Profil oder schreibe uns.</li>
|
||||
<li><strong style="color:#3f3556;">Widerspruch</strong> — du kannst der Verarbeitung jederzeit widersprechen.</li>
|
||||
<li><strong style="color:#3f3556;">Portabilität</strong> — du kannst eine maschinenlesbare Kopie deiner Daten anfordern.</li>
|
||||
<li><strong style="color:#3f3556;">Beschwerde</strong> — du hast das Recht, dich bei der zuständigen Aufsichtsbehörde zu beschweren (z. B. LfDI Baden-Württemberg).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 style="font-size:15px;font-weight:700;color:#3f3556;margin:0 0 8px;">Weitergabe an Dritte</h3>
|
||||
<p style="margin:0;">Keine Weitergabe an Dritte zu Werbezwecken. Technischer Hosting-Anbieter (EU-basiert) verarbeitet Daten als Auftragsverarbeiter gemäß Art. 28 DSGVO.</p>
|
||||
</div>
|
||||
<p style="font-size:12px;color:#a99fc0;margin:0;">Stand: Juni 2026 · Änderungen werden auf dieser Seite bekannt gegeben.</p>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
+36
-6
@@ -1,10 +1,12 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600;700&family=Manrope:wght@400;500;600;700;800&display=swap");
|
||||
@import url("https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600;700&family=Fredoka:wght@400;500;600;700&family=Outfit:wght@300;400;500;600;700&family=Sacramento&display=swap");
|
||||
@import "tailwindcss";
|
||||
@import "primeicons/primeicons.css";
|
||||
|
||||
@theme {
|
||||
--font-display: "Cormorant Garamond", serif;
|
||||
--font-sans: "Manrope", sans-serif;
|
||||
--font-sans: "Outfit", sans-serif;
|
||||
--font-wordmark: "Fredoka", sans-serif;
|
||||
--font-script: "Sacramento", cursive;
|
||||
}
|
||||
|
||||
html,
|
||||
@@ -15,15 +17,43 @@ body,
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
color: #1f2430;
|
||||
background-color: #fffaf4;
|
||||
color: #3f3556;
|
||||
background-color: #f4eefb;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba(137, 92, 246, 0.18);
|
||||
color: #2e1065;
|
||||
background: rgba(139, 108, 219, 0.18);
|
||||
color: #3f3556;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
details > summary {
|
||||
list-style: none;
|
||||
}
|
||||
details > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@keyframes floaty {
|
||||
0%, 100% { transform: translateY(0px); }
|
||||
50% { transform: translateY(-18px); }
|
||||
}
|
||||
@keyframes floaty2 {
|
||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
||||
50% { transform: translateY(-12px) rotate(6deg); }
|
||||
}
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: .3; transform: scale(1); }
|
||||
50% { opacity: 1; transform: scale(1.3); }
|
||||
}
|
||||
@keyframes pulseGlow {
|
||||
0%, 100% { opacity: .55; }
|
||||
50% { opacity: .9; }
|
||||
}
|
||||
@keyframes spinSlow {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
+656
-580
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user