/* =====================================================================
DOGFATHER UNIVERSE — main.css
Gemeinsames Design-System für alle drei Welten (Dogfather / HasiDog /
Manager Dogfather). Farben kommen aus den theme-*.css Dateien über
CSS-Variablen — dieses File ist bewusst themen-neutral.
===================================================================== */
/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* overflow-x:hidden gehört auf BEIDE Elemente: ist im Standards-Modus
das tatsächliche Scroll-Element des Dokuments, nicht
— nur auf body
gesetzt, ließ sich die Seite auf schmalen Bildschirmen (Handy-Breiten wie
320-414px) trotzdem ca. 50px horizontal wegwischen und zeigte Leerraum
hinter den absichtlich überbreiten Deko-Elementen (Nebel/Aurora-Hintergrund).
Tagescheck-Fund vom 02.08.2026, siehe DogFather Website.md. */
html { overflow-x: hidden; }
html, body { margin: 0; padding: 0; }
img, svg { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }
ul { list-style: none; margin: 0; padding: 0; }
/* ---------- Fallback-Theme (Dogfather) — wird von theme-*.css überschrieben ---------- */
:root {
--bg: #0b0d10;
--bg-alt: #12151a;
--card-bg: #171b21;
--text: #f3f5f7;
--text-muted: #9aa4b2;
--border: #262c35;
--accent: #8fd9ea; /* Babyblau */
--accent-2: #8b5cf6; /* Lila */
--accent-contrast: #0b0d10;
--radius: 14px;
--font-head: "Poppins", "Segoe UI", system-ui, sans-serif;
--font-body: "Inter", "Segoe UI", system-ui, sans-serif;
--shadow: 0 10px 30px rgba(0,0,0,.35);
}
body {
background: var(--bg);
color: var(--text);
font-family: var(--font-body);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
min-height: 100vh;
position: relative;
overflow-x: hidden;
}
h1, h2, h3, h4 {
font-family: var(--font-head);
line-height: 1.2;
margin: 0 0 .5em;
font-weight: 700;
}
h1 { font-size: clamp(2.2rem, 5.4vw, 3.5rem); }
h2 { font-size: clamp(1.95rem, 4.3vw, 2.95rem); }
h3 { font-size: 1.62rem; }
p { margin: 0 0 1em; color: var(--text-muted); font-size: 1.32rem; line-height: 1.85; }
.lead { font-size: 1.5rem; color: var(--text); }
.quote { font-size: 1.4rem; }
.container {
width: min(1180px, 92vw);
margin: 0 auto;
}
section { padding: clamp(3rem, 6vw, 5.5rem) 0; }
.section-tight { padding: clamp(1.5rem, 3vw, 2.5rem) 0; }
.eyebrow {
display: inline-block;
font-size: .78rem;
letter-spacing: .14em;
text-transform: uppercase;
color: var(--accent);
font-weight: 700;
margin-bottom: .8em;
}
/* ---------- Nebel/Partikel Hintergrund ---------- */
.fog-layer {
position: fixed;
inset: 0;
pointer-events: none;
z-index: 0;
overflow: hidden;
}
.fog-layer span {
position: absolute;
border-radius: 50%;
background: radial-gradient(circle, var(--accent) 0%, transparent 70%);
opacity: .08;
filter: blur(4px);
animation: drift 26s linear infinite;
}
@keyframes drift {
0% { transform: translateY(0) translateX(0); }
50% { transform: translateY(-40px) translateX(20px); }
100% { transform: translateY(0) translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
.fog-layer span { animation: none; }
}
/* ---------- Header / Navigation ---------- */
header.site-header {
position: sticky;
top: 0;
z-index: 50;
/* Kräftig deckend statt Weichzeichnen durch das Bild dahinter — die
Kombination aus backdrop-filter + fest positionierter Kopfzeile führte
bei Chromium-Rendern zu Darstellungsfehlern (Logo/Menü teils unsichtbar).
Deckende Farbe braucht keinen Weichzeichner und ist zusätzlich schneller. */
background: var(--bg);
border-bottom: 1px solid var(--border);
}
.nav-bar {
/* Eigene, etwas breitere Kappung als .container (1180px) — die Nav
braucht durch größere Schrift + mehr Abstand + Polarlicht-Padding
spürbar mehr Platz, ohne dass der restliche Seiteninhalt breiter
werden soll.
Bugfix 04.08.2026: 1400px -> 1440px angehoben (siehe damalige Analyse).
Bugfix 20.08.2026: reichte seither wieder nicht mehr — die Nav braucht
inzwischen (Nav-Punkt "DogiCrew" + "BALD"-Badge dazugekommen) real ca.
1491px, der Deckel blieb bei 1440px. 1440px -> 1560px, zusammen mit der
auf 1650px angehobenen Hamburger-Schwelle weiter unten (siehe Kommentar
dort) — diesmal mit echtem Sicherheitsabstand statt wieder nur knapp
genug für den aktuellen Stand. */
width: min(1560px, 94vw);
margin: 0 auto;
display: flex;
align-items: center;
/* Bewusst NICHT space-between: sonst landet der ganze freie Platz auf
großen Bildschirmen als große Lücke zwischen Logo und "Start", und
das Menü wirkt an die rechte Kante gepresst. Stattdessen rückt das
Menü mit festem Abstand direkt ans Logo heran, der übrige Platz
bleibt rechts nach dem Bewerben-Knopf. */
justify-content: flex-start;
gap: 2rem;
padding: .9rem 0;
flex-wrap: nowrap;
}
/* Logo und Menü-Knopf dürfen NIE zusammengequetscht werden — auch nicht,
wenn .nav-links (das ausgeklappte Menü) aus irgendeinem Grund kurzzeitig
noch normal mitgerechnet wird, bevor die Klappt-Logik greift. */
.brand, .nav-toggle { flex-shrink: 0; }
.brand {
display: flex;
align-items: center;
gap: .65rem;
font-family: var(--font-head);
font-weight: 800;
font-size: 1.32rem;
letter-spacing: .02em;
}
.brand .heart { color: var(--accent); }
.brand-logo {
width: 42px;
height: 42px;
border-radius: 9px;
object-fit: cover;
flex-shrink: 0;
}
.brand small {
display: block;
font-size: .7rem;
font-weight: 500;
letter-spacing: .1em;
color: var(--text-muted);
text-transform: uppercase;
}
.nav-links {
display: flex;
align-items: center;
/* Seit die Kategorien eigene farbige Pillen (Polarlicht-Hintergrund)
haben, trennt schon die Farbfläche selbst optisch — ein kleinerer
Lücken-Abstand wirkt dadurch aufgeräumter/professioneller als der
vorherige große Abstand. */
gap: .7rem;
}
.nav-group { position: relative; }
.nav-group > button {
position: relative;
isolation: isolate;
overflow: hidden;
background: none;
border: none;
border-radius: 999px;
color: var(--text);
font-weight: 600;
font-size: 1.14rem;
cursor: pointer;
display: flex;
align-items: center;
gap: .3rem;
padding: .5rem .55rem;
transition: color .2s ease;
}
.nav-group > button:hover, .nav-group.open > button { color: var(--accent); }
.nav-flat {
position: relative;
isolation: isolate;
overflow: hidden;
border-radius: 999px;
font-weight: 600;
font-size: 1.14rem;
padding: .5rem .55rem;
transition: color .2s ease;
}
.nav-flat:hover, .nav-flat.active { color: var(--accent); }
/* Kein Button-/Pillen-Look im Ruhezustand mehr (0% Deckkraft) — die
Kategorien sehen bei Dogi so aus wie normale Textlinks. Der Farbschein
in den echten Farben der jeweiligen Welt (siehe theme-dogfather/
-hasidog/-spicymedia.css) taucht NUR bei Hover/offenem Dropdown ganz
dezent auf, als kleiner Hinweis statt als ständige Box. */
.nav-group > button::before, .nav-flat::before {
content: "";
position: absolute;
inset: -70% -35%;
z-index: -1;
background:
radial-gradient(circle at 28% 30%, var(--brand-1, transparent), transparent 62%),
radial-gradient(circle at 74% 72%, var(--brand-2, transparent), transparent 62%);
filter: blur(9px) saturate(1.25);
opacity: 0;
animation: nav-cta-aurora 11s ease-in-out infinite alternate;
pointer-events: none;
transition: opacity .3s ease;
}
.nav-group:hover > button::before,
.nav-group.open > button::before,
.nav-flat:hover::before,
.nav-flat.active::before {
opacity: .32;
}
@media (prefers-reduced-motion: reduce) {
.nav-group > button::before, .nav-flat::before { animation: none; }
}
.nav-item-dogfather { --brand-1: rgba(143, 217, 234, .9); --brand-2: rgba(139, 92, 246, .85); }
.nav-item-hasidog { --brand-1: rgba(143, 217, 234, .9); --brand-2: rgba(199, 204, 209, .8); }
.nav-item-manager { --brand-1: rgba(217, 74, 92, .85); --brand-2: rgba(232, 147, 58, .8); }
.nav-item-medien { --brand-1: rgba(143, 217, 234, .7); --brand-2: rgba(217, 74, 92, .6); }
.nav-item-start { --brand-1: rgba(143, 217, 234, .85); --brand-2: rgba(139, 92, 246, .5); }
.nav-item-links { --brand-1: rgba(143, 217, 234, .85); --brand-2: rgba(212, 175, 55, .7); }
/* Aufgeklapptes Kategorie-Menü: gleiche "gläserne, dunkle Karte mit
farbigem Schein"-Machart wie beim Sprachschalter-Dropdown, aber im
Farbton DIESER Kategorie (--brand-1/--brand-2, vom umschließenden
.nav-group geerbt) statt neutral silbern — sorgt für einen klaren,
ruhigen Look statt der vorherigen schlichten grauen Box. */
.nav-dropdown {
position: absolute;
/* WICHTIG: KEIN margin-top/Lücke zum Knopf — sonst verliert die Maus
beim Runterfahren zur Box kurz den Hover auf .nav-group, und das
Menü klappt zu, bevor man einen Punkt anklicken kann (Bug gefunden
03.08.2026, durch den Caret-Abstand selbst verursacht). Box sitzt
deshalb bewusst bündig an top:100%, der Verbindungs-Pfeil unten
pokt einfach in die Knopf-Kante hinein statt in eine echte Lücke. */
top: 100%;
left: 50%;
transform: translateX(-50%);
min-width: 230px;
background: rgba(4, 5, 8, .96);
border: 1px solid rgba(255, 255, 255, .14);
border-radius: 14px;
padding: .45rem;
box-shadow:
0 14px 34px rgba(0, 0, 0, .6),
0 0 16px var(--brand-1, rgba(220, 226, 235, .3)),
0 0 32px var(--brand-2, rgba(190, 200, 215, .15));
display: none;
flex-direction: column;
/* EIGENE Animation statt der geteilten sprach-dropdown-in: eine
@keyframes-Regel setzt "transform" als GANZES pro Frame, würde also
das zentrierende translateX(-50%) oben komplett überschreiben und
die Box nach dem Aufklappen sichtbar nach rechts verschieben (Bug
gefunden 03.08.2026 — Box wirkte "nicht mittig", war es auch nicht:
transform sprang nach der Animation auf reines translateY/scale).
Der Sprachschalter unten ist rechtsbündig (kein translateX nötig)
und behält deshalb bewusst die alte, geteilte Animation. */
animation: nav-dropdown-in .18s ease both;
}
/* Kleiner Verbindungs-Pfeil (Caret), mittig unter dem Kategorie-Knopf —
macht auch dann unmissverständlich klar, zu welcher Kategorie das
Menü gehört, wenn die Box (wegen mehr Einträgen) breiter ist als der
Knopf selbst und dadurch optisch in Nachbar-Kategorien hineinragt. */
.nav-dropdown::before {
content: "";
position: absolute;
top: -7px;
left: 50%;
transform: translateX(-50%) rotate(45deg);
width: 14px;
height: 14px;
background: rgba(4, 5, 8, .96);
border-left: 1px solid rgba(255, 255, 255, .14);
border-top: 1px solid rgba(255, 255, 255, .14);
border-radius: 3px 0 0 0;
pointer-events: none;
}
.nav-group.open .nav-dropdown { display: flex; }
/* Auf echten Maus-Geräten (nicht Touch) öffnet sich das Menü schon beim
Drüberfahren, ohne extra Klick — auf Touch/Tablet bleibt es bewusst
beim Klick (dort gibt es kein echtes "Hover"). */
@media (hover: hover) and (pointer: fine) {
.nav-group:hover .nav-dropdown { display: flex; }
}
/* Bewusst KEIN Button-Look (kein gefüllter Hintergrund, keine Pille) —
nur schlichte Menü-Zeilen, die beim Hover die Farbe wechseln. Die
Kategorie-Knöpfe selbst (DogFather/HasiDog/Manager/...) behalten
weiterhin ihren Pillen-Stil, nur das aufgeklappte Untermenü nicht. */
.nav-dropdown a {
padding: .55rem .75rem;
font-size: 1.06rem;
color: var(--text-muted);
transition: color .2s ease;
}
/* translateX(-50%) MUSS in jedem Frame mit drinstehen, sonst hebt die
Animation die Zentrierung von .nav-dropdown auf (siehe Kommentar oben). */
@keyframes nav-dropdown-in {
from { opacity: 0; transform: translateX(-50%) translateY(-6px) scale(.96); }
to { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
}
.nav-dropdown a:hover, .nav-dropdown a.active {
color: var(--brand-1, var(--accent));
}
/* ===================================================================
Sprachumschalter — eigenes kleines "Schmuckstück" in der Nav-Bar statt
eines schlichten Menüpunkts: eine gläserne Pille mit Polarlicht-Schein
in der jeweiligen Sprachfarbe (--sprach-glut, von main.js gesetzt),
eine glänzende, sich sacht drehende "Mini-Planet"-Kugel und ein
Dropdown im selben Look, das beim Öffnen sanft einschwebt. */
.sprach-schalter { --sprach-glut: var(--accent); }
.sprach-schalter > button {
position: relative;
isolation: isolate;
overflow: hidden;
font-size: 1.08rem;
font-weight: 700;
align-items: center;
gap: .5rem;
padding: .45rem 1.1rem .45rem .6rem;
border-radius: 999px;
/* Rand bewusst neutral silbern (wie beim Dropdown-Kasten) statt in der
Sprachfarbe — nur die Kugel + das Glühen dahinter sind bunt, der
Rahmen selbst bleibt für alle Sprachen gleich. */
border: 1px solid rgba(210, 216, 224, .55);
background: rgba(4, 5, 8, .94);
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, .05),
0 3px 10px rgba(0, 0, 0, .5),
0 0 10px color-mix(in srgb, var(--sprach-glut) 55%, transparent),
0 0 22px color-mix(in srgb, var(--sprach-glut) 35%, transparent);
transition: transform .2s ease, box-shadow .3s ease, border-color .3s ease;
}
.sprach-schalter > button:hover,
.sprach-schalter.open > button {
transform: translateY(-1px);
border-color: rgba(235, 239, 244, .9);
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, .08),
0 6px 16px rgba(0, 0, 0, .4),
0 0 24px color-mix(in srgb, var(--sprach-glut) 60%, transparent);
}
/* Ebene: die "Landesflagge" als weiche, wandernde Aurora-Wolke im
Hintergrund des Knopfs — mehrere Farbflecken statt nur eines Farbtons,
dieselbe Machart wie beim Bewerben-Knopf, nur mit den 2-3 echten
Farben DIESER Sprache (siehe SPRACHEN.farbstopps in main.js). */
.sprach-schalter > button::before {
content: "";
position: absolute;
inset: -65%;
z-index: -2;
background: var(--sprach-aurora);
filter: blur(8px) saturate(1.3);
/* Bewusst nur ein dezenter Farbschein statt einer vollflächig bunten
Fläche — der Knopf selbst soll "leuchtend schwarz" wirken (Glow am
Rand + hinter der Kugel), nicht komplett eingefärbt. */
opacity: .32;
animation: sprach-aurora-drift 7s ease-in-out infinite alternate;
pointer-events: none;
}
.sprach-schalter > button:hover::before,
.sprach-schalter.open > button::before {
opacity: .48;
}
@keyframes sprach-aurora-drift {
from { transform: translate(-3%, -2%) rotate(0deg) scale(1); }
to { transform: translate(3%, 3%) rotate(8deg) scale(1.12); }
}
/* Ebene: ein schmales Lichtband, das einmal quer durch den Knopf läuft —
dieselbe Machart wie beim Bewerben-Knopf, nur in der Sprachfarbe. */
.sprach-schalter > button::after {
content: "";
position: absolute;
inset: 0;
z-index: -1;
background: linear-gradient(115deg, transparent 35%, color-mix(in srgb, var(--sprach-glut) 55%, white 25%) 49%, transparent 63%);
background-size: 240% 100%;
mix-blend-mode: overlay;
opacity: .8;
animation: sprach-schimmer 5s linear infinite;
pointer-events: none;
}
@keyframes sprach-schimmer {
0% { background-position: 160% 0; }
100% { background-position: -60% 0; }
}
.sprach-schalter .nav-dropdown {
min-width: 190px;
left: auto;
right: 0;
transform: none;
padding: .4rem;
border-radius: 14px;
border: 1px solid rgba(210, 216, 224, .55);
background: rgba(4, 5, 8, .96);
box-shadow:
0 14px 34px rgba(0, 0, 0, .6),
0 0 16px rgba(220, 226, 235, .35),
0 0 34px rgba(190, 200, 215, .18);
transform-origin: top right;
animation: sprach-dropdown-in .18s ease both, sprach-silber-puls 3.6s ease-in-out infinite;
}
@keyframes sprach-dropdown-in {
from { opacity: 0; transform: translateY(-6px) scale(.96); }
to { opacity: 1; transform: translateY(0) scale(1); }
}
/* Silberner Polarlicht-Schein um den Dropdown-Rand — bewusst neutral
silber statt farbig, damit sich der schwarze Kasten von der bunten
Kugel/Schrift jeder Sprache klar abhebt statt zu verschwimmen. */
@keyframes sprach-silber-puls {
0%, 100% {
border-color: rgba(210, 216, 224, .5);
box-shadow: 0 14px 34px rgba(0, 0, 0, .6), 0 0 14px rgba(220, 226, 235, .3), 0 0 30px rgba(190, 200, 215, .15);
}
50% {
border-color: rgba(235, 239, 244, .9);
box-shadow: 0 14px 34px rgba(0, 0, 0, .6), 0 0 22px rgba(230, 235, 242, .55), 0 0 46px rgba(200, 210, 224, .3);
}
}
.sprach-schalter .nav-dropdown a {
display: flex;
align-items: center;
gap: .65rem;
padding: .6rem .7rem;
border-radius: 10px;
border-left: 3px solid transparent;
transition: background .2s ease, border-color .2s ease, transform .15s ease;
}
.sprach-schalter .nav-dropdown a:hover,
.sprach-schalter .nav-dropdown a.active {
background: rgba(255, 255, 255, .09);
border-left-color: var(--sprach-glut);
transform: translateX(2px);
}
/* Kleine "Mini-Planet"-Kugel statt eines Flaggen-Emojis — Windows stellt
Flaggen-Emojis grundsätzlich nicht als Bild dar (siehe SPRACHEN oben in
main.js). Ein außermittiges Glanzlicht + langsame Drehung lassen sie
wie eine echte, beleuchtete Kugel wirken statt einer flachen Fläche. */
/* Kugel-Grundfarbe: conic-gradient aus den 2-3 echten Landesfarben
dieser Sprache (--sprach-stopps, siehe SPRACHEN.farbstopps in
main.js) — wirkt wie eine kleine, marmoriert eingefärbte Kugel statt
nur einem Farbton, plus Eigendrehung, damit die Farbmischung sichtbar
"lebt". Glanzlicht kommt separat über ::before oben drauf. */
.sprach-kugel {
position: relative;
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
vertical-align: -4px;
overflow: hidden;
background: conic-gradient(from 0deg, var(--sprach-stopps));
box-shadow:
inset -3px -3px 5px rgba(0, 0, 0, .5),
0 0 8px 2px color-mix(in srgb, var(--sprach-glut) 75%, transparent),
0 0 20px 4px color-mix(in srgb, var(--sprach-glut) 45%, transparent);
flex-shrink: 0;
animation: sprach-glut-puls 3.2s ease-in-out infinite, sprach-kugel-dreh 7s linear infinite;
}
.sprach-kugel::before {
content: "";
position: absolute;
inset: 0;
border-radius: 50%;
background: radial-gradient(circle at 32% 26%, rgba(255, 255, 255, .95) 0%, rgba(255, 255, 255, .35) 16%, transparent 55%);
mix-blend-mode: overlay;
}
.sprach-schalter .nav-dropdown a .sprach-kugel { width: 16px; height: 16px; }
/* Die Sprachfarbe zieht sich auch über die Schrift — kräftiger,
leuchtender Text statt neutralem Weiß, plus ein sanft pulsierender
Schein (dieselbe "Polarlicht"-Idee wie beim Bewerben-Knopf/den
Foto-Rahmen, nur in der jeweiligen Sprachfarbe). */
.sprach-schalter > button,
.sprach-schalter .nav-dropdown a {
color: var(--sprach-glut, var(--text));
text-shadow:
0 0 6px color-mix(in srgb, var(--sprach-glut, transparent) 70%, transparent),
0 0 14px color-mix(in srgb, var(--sprach-glut, transparent) 45%, transparent);
}
.sprach-kurz { animation: sprach-glut-puls 3.2s ease-in-out infinite; display: inline-block; }
@keyframes sprach-glut-puls {
0%, 100% { filter: brightness(1) saturate(1); }
50% { filter: brightness(1.3) saturate(1.35); }
}
@keyframes sprach-kugel-dreh {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
.sprach-kugel, .sprach-kurz, .sprach-schalter > button::before, .sprach-schalter > button::after, .sprach-schalter .nav-dropdown { animation: none; }
}
/* "Bewerben" ist der Treffpunkt beider Welten (Team Dogi + Spicy Media) —
deshalb bewusst FEST babyblau + rot, unabhängig vom Theme der gerade
offenen Seite. Statt einer einfachen 50/50-Teilung ein echtes
Polarlicht: mehrere weiche, wandernde Farbwolken (blau/lila/rot) plus
ein durchlaufender Lichtschimmer — soll wirken wie Licht und Nebel,
nicht wie zwei flache Farbflächen. */
.nav-cta {
position: relative;
isolation: isolate;
overflow: hidden;
display: inline-flex;
align-items: center;
white-space: nowrap;
padding: .6rem 1.35rem;
border-radius: 999px;
color: #fff;
font-weight: 700;
font-size: .95rem;
background: #0b0e14;
border: 1px solid rgba(255, 255, 255, .16);
transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
box-shadow: 0 6px 18px rgba(0, 0, 0, .35);
}
.nav-cta span {
position: relative;
z-index: 2;
text-shadow: 0 1px 3px rgba(0, 0, 0, .6), 0 0 14px rgba(0, 0, 0, .35);
}
/* Ebene 1: die wandernden Polarlicht-Wolken selbst */
.nav-cta::before {
content: "";
position: absolute;
inset: -60%;
z-index: 0;
background:
radial-gradient(circle at 18% 30%, rgba(143, 217, 234, .95), transparent 55%),
radial-gradient(circle at 45% 75%, rgba(139, 92, 246, .85), transparent 58%),
radial-gradient(circle at 82% 32%, rgba(217, 74, 92, .95), transparent 55%),
radial-gradient(circle at 62% 82%, rgba(232, 147, 58, .55), transparent 55%);
filter: blur(9px) saturate(1.35);
animation: nav-cta-aurora 9s ease-in-out infinite alternate;
}
/* Ebene 2: ein feiner Lichtschimmer, der einmal quer durchläuft */
.nav-cta::after {
content: "";
position: absolute;
inset: 0;
z-index: 1;
background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, .4) 49%, transparent 63%);
background-size: 240% 100%;
mix-blend-mode: overlay;
animation: nav-cta-shimmer 4.5s linear infinite;
pointer-events: none;
}
@keyframes nav-cta-aurora {
from { transform: translate(-3%, -2%) rotate(0deg) scale(1); }
to { transform: translate(3%, 3%) rotate(6deg) scale(1.08); }
}
@keyframes nav-cta-shimmer {
from { background-position: 130% 0; }
to { background-position: -30% 0; }
}
.nav-cta:hover {
transform: translateY(-1px);
border-color: rgba(255, 255, 255, .32);
box-shadow: 0 10px 26px rgba(0, 0, 0, .45),
0 0 22px rgba(143, 217, 234, .3),
0 0 22px rgba(217, 74, 92, .28);
}
/* Abo-Button (Supporter-Abo) — gleicher Polarlicht-Mechanismus wie
.nav-cta, aber in Babyblau/Lila (VIP-Anmutung) statt der allgemeinen
Regenbogen-Aurora.
Bugfix 04.08.2026: war Gold/Lila (rgba(212,175,55,...)) — dieser Knopf
erscheint in der Navigationsleiste auf JEDER Seite (auch auf
verwaltung.html, siehe Screenshot-Beschwerde), wurde von der 4. Runde
"überall wo gelb ist, Babyblau benutzen" aber NICHT erfasst, weil er in
main.css/main.js liegt statt in verwaltung.html selbst. Jetzt
nachgezogen: Gold -> Babyblau (rgba(143,217,234,...), derselbe Farbwert
wie beim allgemeinen .nav-cta-Polarlicht oben), Lila unverändert. Der
separate, deutlich größere Gold-VIP-Look von abonnieren.html/
supporter.html/gate.html/links.html/rabattcodes.html ist davon NICHT
betroffen — das ist eine eigenständige, bislang nie angesprochene
Design-Entscheidung für den öffentlichen Supporter-Bereich. */
.nav-cta-abo::before {
background:
radial-gradient(circle at 20% 30%, rgba(143, 217, 234, .95), transparent 55%),
radial-gradient(circle at 78% 70%, rgba(139, 92, 246, .85), transparent 58%);
}
.nav-cta-abo:hover {
box-shadow: 0 10px 26px rgba(0, 0, 0, .45),
0 0 22px rgba(143, 217, 234, .35),
0 0 22px rgba(139, 92, 246, .3);
}
/* "Bald"-Badge auf dem Abo-Knopf, solange die Registrierung auf
abonnieren.html gesperrt ist (20.08.2026, siehe .btn-gold-locked weiter
unten + main.js renderAboButton/soonBadge). Sitzt als zweites Kind IN
der Pille (nicht als eigenes Nav-Element), bleibt dadurch Teil desselben
Klicks — der Knopf führt bewusst weiterhin ganz normal zu abonnieren.html,
nur die Registrierung selbst dort ist gesperrt. Bewusst neutral-silbern
(Wiederverwendung von .btn-silver-text/-spark, nur kleiner skaliert)
statt Gold, damit es nicht mit der babyblau/lila-Aurora dieser Pille
konkurriert — reine Status-Markierung, kein zweiter Marken-Akzent. */
.nav-cta-soon {
position: relative;
z-index: 2;
display: inline-flex;
align-items: center;
gap: .22rem;
margin-left: .5rem;
padding: .15rem .5rem;
border-radius: 999px;
font-size: .64rem;
font-weight: 800;
letter-spacing: .04em;
text-transform: uppercase;
background: rgba(255, 255, 255, .07);
border: 1px solid rgba(255, 255, 255, .3);
box-shadow: 0 0 10px rgba(230, 235, 242, .3);
flex-shrink: 0;
}
.nav-cta-soon .btn-silver-spark { font-size: .85em; }
@media (prefers-reduced-motion: reduce) {
.nav-cta::before, .nav-cta::after { animation: none; }
}
/* TikTok-Button "Glitch/Duotone" — eigener, klar erkennbarer Stil (nicht
mehr nur eine eingefärbte Kopie von .nav-cta): schwarze Pille mit einem
fließenden Cyan/Pink-Rahmen (klassischer Zwei-Layer-Background-Trick,
NICHT ein rotierender Masken-Ring — der verzerrt sich auf einer
länglichen Pillenform zu einer krummen Schlaufe statt einer sauberen
Kontur), einem dezenten Innenschimmer (KEIN nach außen strahlender
Blur-Wolken-Glow mehr — der hat vorher Text/Bilder drumherum überstrahlt,
Feedback vom 03.08.2026: "geht über den Text und das Bild"), einer
rotierenden Notenkopf-Spielmarke und einem Text mit TikToks
charakteristischem Chromatic-Aberration-/Glitch-Versatz (die Cyan/Rot-
Schattenkopien, die auch im echten TikTok-Logo stecken), der alle paar
Sekunden kurz "springt". Alle Effekte bleiben INNERHALB der Pille bzw.
direkt an ihrer Kante — die Auffälligkeit kommt vom Button selbst, nicht
von seiner Ausstrahlung. Bewusst NUR für echte TikTok-Links — die
Markenfarben (Cyan #25F4EE + Pink/Rot #FE2C55) bleiben exakt gleich. */
.btn-tiktok {
position: relative;
isolation: isolate;
overflow: hidden;
display: inline-flex;
align-items: center;
gap: .6rem;
padding: .85rem 2.2rem;
border-radius: 999px;
color: #fff;
font-weight: 800;
font-size: 1.1rem;
letter-spacing: .01em;
border: 2px solid transparent;
background:
linear-gradient(160deg, #12151b, #05070a 55%, #14171d) padding-box,
linear-gradient(90deg, #25F4EE, #FE2C55, #25F4EE) border-box;
background-size: 100% 100%, 260% 100%;
text-decoration: none;
transition: transform .25s ease, box-shadow .25s ease;
box-shadow: 0 4px 12px rgba(0, 0, 0, .4),
inset 0 0 10px rgba(37, 244, 238, .12),
inset 0 0 10px rgba(254, 44, 85, .1);
animation: btn-tiktok-border-flow 5s linear infinite;
}
.btn-tiktok-note {
position: relative;
z-index: 3;
display: inline-block;
font-size: 1.05em;
filter: drop-shadow(0 0 3px rgba(37, 244, 238, .8));
animation: btn-tiktok-spin 3.6s linear infinite;
}
.btn-tiktok-text {
/* Ruhezustand ist bewusst KLAR LESBAR (nur normaler Schlagschatten) —
der Cyan/Rot-Chromatic-Versatz von TikToks Logo erscheint nur ganz
kurz als Flicker (siehe @keyframes btn-tiktok-glitch), nicht dauerhaft,
sonst verschwimmt der Text (Feedback vom 03.08.2026: "kriegt man
TikTok nichtmal richtig gelesen"). */
position: relative;
z-index: 3;
text-shadow: 0 2px 6px rgba(0, 0, 0, .6);
animation: btn-tiktok-glitch 6s ease-in-out infinite;
}
.btn-tiktok::before {
/* Sehr dezentes Farbschimmern INNEN in der Pille — sorgt für Tiefe,
bleibt aber innerhalb der Ränder (kein overflow, kein Blur-Bleed). */
content: "";
position: absolute;
inset: 0;
z-index: 0;
border-radius: inherit;
background:
radial-gradient(circle at 18% 20%, rgba(37, 244, 238, .3), transparent 60%),
radial-gradient(circle at 85% 80%, rgba(254, 44, 85, .28), transparent 62%);
animation: nav-cta-aurora 9s ease-in-out infinite alternate;
pointer-events: none;
}
.btn-tiktok::after {
/* Diagonaler Lichtschimmer, wandert einmal quer über die Pille */
content: "";
position: absolute;
inset: 0;
z-index: 1;
border-radius: inherit;
background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, .4) 49%, transparent 63%);
background-size: 240% 100%;
mix-blend-mode: overlay;
animation: nav-cta-shimmer 4.5s linear infinite;
pointer-events: none;
}
.btn-tiktok:hover {
transform: translateY(-1px) scale(1.02);
box-shadow: 0 6px 16px rgba(0, 0, 0, .45),
inset 0 0 14px rgba(37, 244, 238, .2),
inset 0 0 14px rgba(254, 44, 85, .16);
}
@keyframes btn-tiktok-border-flow {
to { background-position: 0 0, -260% 0; }
}
@keyframes btn-tiktok-spin {
to { transform: rotate(360deg); }
}
@keyframes btn-tiktok-glitch {
/* 97% der Zeit klar lesbarer Text — der Chromatic-Versatz blitzt nur für
einen Wimpernschlag (~150ms von 6s) auf, statt dauerhaft zu "verwaschen". */
0%, 96%, 100% {
text-shadow: 0 2px 6px rgba(0, 0, 0, .6);
transform: translateX(0);
}
97% {
text-shadow: -3px 0 rgba(37, 244, 238, .95), 3px 0 rgba(254, 44, 85, .95), 0 2px 6px rgba(0, 0, 0, .6);
transform: translateX(-1px);
}
97.5% {
text-shadow: 3px 0 rgba(37, 244, 238, .95), -3px 0 rgba(254, 44, 85, .95), 0 2px 6px rgba(0, 0, 0, .6);
transform: translateX(1px);
}
98% {
text-shadow: 0 2px 6px rgba(0, 0, 0, .6);
transform: translateX(0);
}
}
@media (prefers-reduced-motion: reduce) {
.btn-tiktok, .btn-tiktok::before, .btn-tiktok::after, .btn-tiktok-note, .btn-tiktok-text { animation: none; }
}
/* Silberner "Coming soon"-Button: eigener, deutlich edlerer Look als
.btn-tiktok — echtes Chrome-Metallic-Textglitzern, rotierender
Metallrand-Schimmer, zwei funkelnde Sparkle-Akzente und ein sanft
pulsierender Halo-Glow. Für Dinge, die noch nicht live sind
(z.B. VanVans zweiter Kanal), aber trotzdem besonders auffallen sollen. */
.btn-silver {
position: relative;
isolation: isolate;
overflow: visible;
display: inline-flex;
align-items: center;
gap: .55rem;
padding: .95rem 2.4rem;
border-radius: 999px;
color: #fff;
font-weight: 800;
font-size: 1.1rem;
letter-spacing: .02em;
background: linear-gradient(160deg, #14161c, #0b0e14 55%, #1a1d24);
border: 1px solid rgba(255, 255, 255, .22);
text-decoration: none;
transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
box-shadow: 0 6px 18px rgba(0, 0, 0, .4),
0 0 0 1px rgba(255, 255, 255, .03) inset;
animation: btn-silver-halo 3.2s ease-in-out infinite;
}
.btn-silver-text {
position: relative;
z-index: 2;
background: linear-gradient(100deg, #9aa4b2 0%, #ffffff 28%, #e6ebf2 42%, #c7ccd1 58%, #ffffff 76%, #9aa4b2 100%);
background-size: 260% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .6));
animation: btn-silver-text-shine 3.6s linear infinite;
}
.btn-silver-spark {
position: relative;
z-index: 2;
display: inline-block;
font-size: .9em;
filter: drop-shadow(0 0 4px rgba(255, 255, 255, .8));
animation: btn-silver-twinkle 1.8s ease-in-out infinite;
}
.btn-silver-spark:last-child { animation-delay: .9s; }
.btn-silver::before {
content: "";
position: absolute;
inset: -1px;
z-index: 0;
border-radius: inherit;
padding: 1.5px;
background: conic-gradient(from 0deg, #eef1f5, #9aa4b2, #ffffff, #c7ccd1, #7d8794, #eef1f5);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: btn-silver-shine-rotate 5s linear infinite;
}
.btn-silver::after {
content: "";
position: absolute;
inset: 0;
z-index: 1;
border-radius: inherit;
background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, .5) 49%, transparent 63%);
background-size: 240% 100%;
mix-blend-mode: overlay;
animation: nav-cta-shimmer 4.5s linear infinite;
pointer-events: none;
}
.btn-silver:hover {
transform: translateY(-1px) scale(1.02);
border-color: rgba(255, 255, 255, .4);
box-shadow: 0 10px 30px rgba(0, 0, 0, .5),
0 0 26px rgba(230, 235, 242, .45),
0 0 26px rgba(190, 200, 215, .35);
}
@keyframes btn-silver-shine-rotate {
to { transform: rotate(360deg); }
}
@keyframes btn-silver-text-shine {
0% { background-position: 0% 50%; }
100% { background-position: 260% 50%; }
}
@keyframes btn-silver-twinkle {
0%, 100% { opacity: .45; transform: scale(.85) rotate(0deg); }
50% { opacity: 1; transform: scale(1.15) rotate(15deg); }
}
@keyframes btn-silver-halo {
0%, 100% { box-shadow: 0 6px 18px rgba(0, 0, 0, .4), 0 0 14px rgba(200, 208, 220, .18); }
50% { box-shadow: 0 6px 18px rgba(0, 0, 0, .4), 0 0 26px rgba(230, 235, 242, .4); }
}
@media (prefers-reduced-motion: reduce) {
.btn-silver, .btn-silver::before, .btn-silver::after, .btn-silver-text, .btn-silver-spark {
animation: none;
}
}
/* "Legendärer" Button (z.B. Casperlino-Link auf streamer.html): babyblau
+ Silber, gleiche edle Machart wie .btn-silver (Chrome-Textglanz,
rotierender Rand, Sparkles, pulsierender Halo), aber größer, kräftiger
und in der Marken-Akzentfarbe --accent (Babyblau) statt neutralem Grau —
soll bewusst wie ein besonderes, "episches" Highlight wirken. */
.btn-legendary {
position: relative;
isolation: isolate;
overflow: visible;
display: inline-flex;
align-items: center;
gap: .6rem;
padding: 1.05rem 2.7rem;
border-radius: 999px;
color: #fff;
font-weight: 800;
font-size: 1.18rem;
letter-spacing: .02em;
background: linear-gradient(160deg, #101b20, #0b0e14 55%, #16232a);
border: 1px solid rgba(143, 217, 234, .35);
text-decoration: none;
transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
box-shadow: 0 8px 22px rgba(0, 0, 0, .45),
0 0 0 1px rgba(143, 217, 234, .06) inset;
animation: btn-legendary-halo 3s ease-in-out infinite;
}
.btn-legendary-text {
position: relative;
z-index: 2;
background: linear-gradient(100deg, #8fd9ea 0%, #ffffff 26%, #c7ccd1 42%, #8fd9ea 58%, #ffffff 76%, #c7ccd1 100%);
background-size: 260% 100%;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .6));
animation: btn-legendary-text-shine 3.4s linear infinite;
}
.btn-legendary-spark {
position: relative;
z-index: 2;
display: inline-block;
font-size: .95em;
filter: drop-shadow(0 0 5px rgba(143, 217, 234, .9));
animation: btn-legendary-twinkle 1.7s ease-in-out infinite;
}
.btn-legendary-spark:last-child { animation-delay: .85s; }
.btn-legendary::before {
content: "";
position: absolute;
inset: -1.5px;
z-index: 0;
border-radius: inherit;
padding: 2px;
background: conic-gradient(from 0deg, #8fd9ea, #eef1f5, #c7ccd1, #ffffff, #8fd9ea, #7d8794, #8fd9ea);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: btn-legendary-shine-rotate 4.5s linear infinite;
}
.btn-legendary::after {
content: "";
position: absolute;
inset: 0;
z-index: 1;
border-radius: inherit;
background: linear-gradient(115deg, transparent 32%, rgba(143, 217, 234, .55) 49%, transparent 66%);
background-size: 240% 100%;
mix-blend-mode: overlay;
animation: nav-cta-shimmer 4s linear infinite;
pointer-events: none;
}
.btn-legendary:hover {
transform: translateY(-2px) scale(1.03);
border-color: rgba(143, 217, 234, .55);
box-shadow: 0 14px 34px rgba(0, 0, 0, .5),
0 0 30px rgba(143, 217, 234, .5),
0 0 30px rgba(199, 204, 209, .35);
}
@keyframes btn-legendary-shine-rotate {
to { transform: rotate(360deg); }
}
@keyframes btn-legendary-text-shine {
0% { background-position: 0% 50%; }
100% { background-position: 260% 50%; }
}
@keyframes btn-legendary-twinkle {
0%, 100% { opacity: .5; transform: scale(.85) rotate(0deg); }
50% { opacity: 1; transform: scale(1.2) rotate(15deg); }
}
@keyframes btn-legendary-halo {
0%, 100% { box-shadow: 0 8px 22px rgba(0, 0, 0, .45), 0 0 16px rgba(143, 217, 234, .22); }
50% { box-shadow: 0 8px 22px rgba(0, 0, 0, .45), 0 0 32px rgba(143, 217, 234, .5); }
}
@media (prefers-reduced-motion: reduce) {
.btn-legendary, .btn-legendary::before, .btn-legendary::after, .btn-legendary-text, .btn-legendary-spark {
animation: none;
}
}
/* =====================================================================
"Gesperrter Tresor"-Knopf für den DogiCrew-Registrieren-Knopf
(abonnieren.html, 20.08.2026, Nutzer-Wunsch: "richtig krank übertrieben
geiles... weil es wird ja das geilste Bonus und überhaupt so von mir").
Bewusst KEINE Wiederverwendung von .btn-silver — der ist neutral-grau und
auf DIESER Seite bereits für die Teddy-Kollektion (Nebensache) vergeben.
Chrome-Text-Clip-Schimmer + Schimmer-Sweep + Halo-Puls wie .btn-silver/
.btn-legendary, aber in den ECHTEN Gold-Tönen dieser Seite
(#ffe9a8/#d4af37, siehe .abo-panel .btn) und mit einem pulsierenden
Schloss statt Sternen, damit die Haupt-CTA sichtbar "das Besondere,
noch verschlossene" bleibt statt nur "irgendwann verfügbar".
WICHTIG: Für den Rand bewusst NICHT die rotierende Conic-Gradient-Maske
von .btn-silver/.btn-legendary kopiert — dieser Knopf läuft über
`width:100%` auf voller Kartenbreite (~440px) bei nur ~62px Höhe, also
ein sehr langgestrecktes Rechteck. Genau für diesen Fall ist die
dokumentierte Lektion in Projektregeln.md Punkt 14 gedacht (03.08.2026,
"TikTok-Button-Bug"): ein rotierendes maskiertes Pseudo-Element verzieht
sich auf länglichen Formen zu einer krummen Schlaufe, weil ein Rechteck
beim Rotieren nicht rotationssymmetrisch ist — live mit Playwright-
Screenshots über mehrere Frames nachgewiesen (die Schlaufe ist der
rotierende Rand bei verschiedenen Winkeln). Stattdessen derselbe sichere
Zwei-Layer-Background-Trick wie bei .abo-google-frame weiter oben in
dieser Datei (Füllung padding-box + Verlauf border-box, Bewegung nur
über background-position) — bleibt geometrisch exakt an der Kontur,
unabhängig vom Seitenverhältnis. Reine Deko/Statusanzeige — echte
Deaktivierung läuft über das native disabled-Attribut am