Files
fsae41.de/public/networktester.html
BolkeDerBaer 038910e9f0 Add service worker for push notifications, create calendar layout, and implement WLAN QR code page
- Implemented a service worker (sw.js) to handle push notifications with dynamic options and notification click events.
- Created a calendar layout in test.html with a grid system for displaying events across days and times.
- Developed a visually engaging WLAN QR code page (wlan.html) with animated backgrounds, particle effects, and tips for connecting to the network.
2026-02-22 00:50:22 +01:00

972 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>NETZWERKTESTER™ — Das beste Gadget der Welt</title>
<meta name="description" content="Der übertriebenste Netzwerktester-Hype aller Zeiten. Animiert. Neon. Absolut unnötig — und genau deshalb perfekt." />
<style>
:root{
--bg:#060611;
--bg2:#0b0b1f;
--neon:#7CFF6B;
--neon2:#7afcff;
--hot:#ff4fd8;
--warn:#ffd34d;
--text:#f2f6ff;
--muted:rgba(242,246,255,.72);
--card:rgba(255,255,255,.06);
--stroke:rgba(255,255,255,.12);
--shadow: 0 22px 80px rgba(0,0,0,.65);
--radius: 22px;
--max: 1180px;
}
*{box-sizing:border-box}
html,body{height:100%}
body{
margin:0;
font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji";
background: radial-gradient(1200px 800px at 20% 10%, rgba(122,252,255,.14), transparent 55%),
radial-gradient(1100px 900px at 80% 20%, rgba(255,79,216,.12), transparent 55%),
radial-gradient(900px 700px at 50% 80%, rgba(124,255,107,.10), transparent 55%),
linear-gradient(180deg, var(--bg), var(--bg2));
color:var(--text);
overflow-x:hidden;
}
/* ======= Animated background grid + lasers ======= */
.bg-grid{
position:fixed; inset:0;
pointer-events:none;
opacity:.55;
background:
linear-gradient(rgba(255,255,255,.06) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,.06) 1px, transparent 1px);
background-size: 42px 42px;
transform: perspective(900px) rotateX(60deg) translateY(-18vh);
filter: drop-shadow(0 0 18px rgba(122,252,255,.08));
animation: gridFloat 8s ease-in-out infinite;
}
@keyframes gridFloat{
0%,100%{transform: perspective(900px) rotateX(60deg) translateY(-18vh) translateX(0)}
50%{transform: perspective(900px) rotateX(60deg) translateY(-16vh) translateX(12px)}
}
.lasers{
position:fixed; inset:-30vh -30vw;
pointer-events:none;
mix-blend-mode: screen;
opacity:.65;
filter: blur(.2px);
background:
conic-gradient(from 180deg at 50% 50%,
rgba(122,252,255,.0),
rgba(122,252,255,.25),
rgba(255,79,216,.18),
rgba(124,255,107,.18),
rgba(255,211,77,.12),
rgba(122,252,255,.0));
animation: spin 14s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
/* ======= Layout ======= */
.wrap{max-width:var(--max); margin:0 auto; padding: 22px 18px 90px;}
header{
position:sticky; top:0; z-index:50;
backdrop-filter: blur(12px);
background: linear-gradient(180deg, rgba(6,6,17,.78), rgba(6,6,17,.35));
border-bottom: 1px solid rgba(255,255,255,.08);
}
.nav{
max-width:var(--max); margin:0 auto;
padding:12px 18px;
display:flex; align-items:center; justify-content:space-between; gap:10px;
}
.brand{
display:flex; align-items:center; gap:10px;
font-weight:900;
letter-spacing:.5px;
text-transform:uppercase;
user-select:none;
}
.brand .dot{
width:12px;height:12px;border-radius:99px;
background: radial-gradient(circle at 30% 30%, #fff, var(--neon2));
box-shadow: 0 0 18px rgba(122,252,255,.55), 0 0 34px rgba(255,79,216,.18);
animation: pulse 1.2s ease-in-out infinite;
}
@keyframes pulse{
0%,100%{transform:scale(1); opacity:1}
50%{transform:scale(1.35); opacity:.85}
}
.nav a{
color:var(--muted);
text-decoration:none;
font-weight:700;
padding:10px 12px;
border-radius:12px;
transition:.2s;
display:none;
}
.nav a:hover{background:rgba(255,255,255,.06); color:var(--text)}
@media (min-width:860px){
.nav a{display:inline-block}
}
.cta{
display:flex; align-items:center; gap:10px;
}
.btn{
border:1px solid rgba(255,255,255,.14);
background: linear-gradient(180deg, rgba(255,255,255,.12), rgba(255,255,255,.06));
color:var(--text);
border-radius:14px;
padding:10px 14px;
font-weight:850;
text-decoration:none;
box-shadow: 0 10px 40px rgba(0,0,0,.35);
transition: transform .15s ease, filter .15s ease;
position:relative;
overflow:hidden;
user-select:none;
}
.btn:hover{transform: translateY(-2px); filter:brightness(1.08)}
.btn.primary{
border-color: rgba(122,252,255,.25);
background: linear-gradient(135deg, rgba(122,252,255,.25), rgba(255,79,216,.16));
box-shadow: 0 18px 60px rgba(122,252,255,.14), 0 18px 70px rgba(255,79,216,.10);
}
.btn .shine{
content:"";
position:absolute; inset:-30%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent);
transform: rotate(20deg) translateX(-120%);
animation: shine 2.8s ease-in-out infinite;
opacity:.8;
}
@keyframes shine{
0%,55%{transform: rotate(20deg) translateX(-140%)}
85%,100%{transform: rotate(20deg) translateX(140%)}
}
/* ======= Hero ======= */
.hero{
padding: 46px 0 16px;
display:grid;
grid-template-columns: 1fr;
gap:18px;
position:relative;
}
@media (min-width:980px){
.hero{
grid-template-columns: 1.05fr .95fr;
align-items:center;
padding: 64px 0 22px;
}
}
.kicker{
display:inline-flex; align-items:center; gap:10px;
padding:8px 12px;
border-radius:999px;
border:1px solid rgba(255,255,255,.14);
background: rgba(255,255,255,.06);
color:var(--muted);
font-weight:800;
width:fit-content;
box-shadow: 0 10px 40px rgba(0,0,0,.35);
}
.badge-live{
display:inline-flex; align-items:center; gap:7px;
padding:4px 10px;
border-radius:999px;
font-size:12px;
font-weight:900;
letter-spacing:.6px;
color:#071208;
background: linear-gradient(135deg, var(--neon), var(--neon2));
box-shadow: 0 0 18px rgba(124,255,107,.22), 0 0 28px rgba(122,252,255,.18);
text-transform:uppercase;
}
.badge-live i{
width:8px;height:8px;border-radius:99px;background:#071208;
box-shadow: 0 0 0 6px rgba(7,18,8,.15);
animation: ping 1.1s ease-in-out infinite;
}
@keyframes ping{
0%,100%{transform:scale(1); opacity:1}
50%{transform:scale(1.35); opacity:.8}
}
h1{
margin: 14px 0 12px;
font-size: clamp(36px, 5vw, 62px);
line-height: 1.02;
letter-spacing: -1.2px;
}
.glitch{
position:relative;
display:inline-block;
text-shadow:
0 0 14px rgba(122,252,255,.18),
0 0 22px rgba(255,79,216,.14);
}
.glitch::before,.glitch::after{
content: attr(data-text);
position:absolute; left:0; top:0;
opacity:.8;
mix-blend-mode: screen;
clip-path: inset(0 0 0 0);
animation: glitch 2.4s infinite linear alternate-reverse;
}
.glitch::before{
transform: translate(2px,-2px);
color: var(--neon2);
filter: blur(.2px);
}
.glitch::after{
transform: translate(-2px,2px);
color: var(--hot);
animation-duration: 2.9s;
filter: blur(.25px);
}
@keyframes glitch{
0%{clip-path: inset(0 0 85% 0)}
10%{clip-path: inset(12% 0 60% 0)}
20%{clip-path: inset(65% 0 10% 0)}
30%{clip-path: inset(40% 0 40% 0)}
40%{clip-path: inset(80% 0 5% 0)}
50%{clip-path: inset(10% 0 75% 0)}
60%{clip-path: inset(35% 0 40% 0)}
70%{clip-path: inset(5% 0 85% 0)}
80%{clip-path: inset(55% 0 20% 0)}
90%{clip-path: inset(25% 0 55% 0)}
100%{clip-path: inset(70% 0 15% 0)}
}
.sub{
color:var(--muted);
font-size: clamp(16px, 2.1vw, 20px);
line-height:1.5;
margin: 0 0 18px;
max-width: 58ch;
}
.hero-actions{
display:flex; flex-wrap:wrap; gap:10px;
align-items:center;
margin: 18px 0 12px;
}
.stats{
display:grid;
grid-template-columns: repeat(2, minmax(0,1fr));
gap:10px;
margin-top: 14px;
max-width: 520px;
}
@media(min-width:520px){
.stats{grid-template-columns: repeat(3, minmax(0,1fr));}
}
.stat{
border:1px solid rgba(255,255,255,.12);
background: rgba(255,255,255,.06);
border-radius: 18px;
padding: 12px 12px;
box-shadow: 0 12px 55px rgba(0,0,0,.35);
position:relative;
overflow:hidden;
}
.stat b{
display:block;
font-size: 22px;
letter-spacing:-.3px;
}
.stat span{color:var(--muted); font-weight:700; font-size:13px}
.stat::after{
content:"";
position:absolute; inset:-40%;
background: radial-gradient(circle at 30% 30%, rgba(122,252,255,.18), transparent 55%),
radial-gradient(circle at 80% 70%, rgba(255,79,216,.16), transparent 55%);
animation: drift 6s ease-in-out infinite;
opacity:.8;
}
@keyframes drift{
0%,100%{transform: translate(0,0) rotate(0deg)}
50%{transform: translate(18px,-12px) rotate(8deg)}
}
.stat > *{position:relative; z-index:1}
/* ======= Right side device card ======= */
.device{
border:1px solid rgba(255,255,255,.14);
background: linear-gradient(180deg, rgba(255,255,255,.09), rgba(255,255,255,.04));
border-radius: var(--radius);
padding: 14px;
box-shadow: var(--shadow);
position:relative;
overflow:hidden;
min-height: 420px;
}
.device::before{
content:"";
position:absolute; inset:-40%;
background: conic-gradient(from 180deg at 50% 50%,
rgba(122,252,255,.0),
rgba(122,252,255,.22),
rgba(255,79,216,.18),
rgba(124,255,107,.16),
rgba(255,211,77,.10),
rgba(122,252,255,.0));
animation: spin 10s linear infinite;
opacity:.55;
}
.device-inner{
position:relative; z-index:1;
height:100%;
border-radius: calc(var(--radius) - 10px);
border:1px solid rgba(255,255,255,.12);
background: rgba(0,0,0,.22);
overflow:hidden;
display:grid;
grid-template-rows: auto 1fr auto;
}
.device-top{
display:flex; align-items:center; justify-content:space-between;
padding:12px 12px 10px;
gap:10px;
border-bottom:1px solid rgba(255,255,255,.10);
}
.dots{display:flex; gap:7px}
.dots i{
width:10px;height:10px;border-radius:99px;
background: rgba(255,255,255,.16);
box-shadow: 0 0 0 6px rgba(255,255,255,.03);
}
.device-top .mode{
font-size:12px; font-weight:900; letter-spacing:.7px;
text-transform:uppercase;
color:var(--muted);
}
.screen{
position:relative;
padding: 14px;
display:grid;
place-items:center;
}
.screen img{
width:100%;
height: 280px;
object-fit:cover;
border-radius: 18px;
border:1px solid rgba(255,255,255,.14);
filter: saturate(1.15) contrast(1.05);
transform: translateZ(0);
box-shadow: 0 18px 70px rgba(0,0,0,.55);
}
.floaters{
position:absolute; inset:0;
pointer-events:none;
overflow:hidden;
}
.floater{
position:absolute;
font-size: clamp(16px, 2.6vw, 26px);
filter: drop-shadow(0 10px 18px rgba(0,0,0,.55));
opacity:.95;
animation: floatUp linear infinite;
}
@keyframes floatUp{
from{transform: translateY(40px) rotate(0deg); opacity:0}
15%{opacity:1}
to{transform: translateY(-380px) rotate(22deg); opacity:0}
}
.device-bottom{
padding: 12px;
border-top:1px solid rgba(255,255,255,.10);
display:flex; gap:10px; align-items:center; justify-content:space-between;
flex-wrap:wrap;
}
.meter{
flex:1;
min-width: 210px;
border:1px solid rgba(255,255,255,.12);
background: rgba(255,255,255,.05);
border-radius: 999px;
height: 14px;
overflow:hidden;
position:relative;
}
.meter span{
display:block; height:100%;
width: 20%;
background: linear-gradient(90deg, var(--neon2), var(--hot), var(--neon));
border-radius: 999px;
animation: fill 3.2s ease-in-out infinite;
filter: saturate(1.2);
}
@keyframes fill{
0%{width:18%}
50%{width:98%}
100%{width:30%}
}
.meter-label{
font-weight:900;
color:var(--muted);
font-size:12px;
letter-spacing:.6px;
text-transform:uppercase;
display:flex; align-items:center; gap:8px;
user-select:none;
}
/* ======= Sections ======= */
section{padding: 26px 0}
.grid{
display:grid;
grid-template-columns: 1fr;
gap:14px;
}
@media(min-width:980px){
.grid{grid-template-columns: 1fr 1fr}
}
.card{
border:1px solid rgba(255,255,255,.12);
background: rgba(255,255,255,.06);
border-radius: var(--radius);
padding: 16px;
box-shadow: 0 18px 70px rgba(0,0,0,.35);
position:relative;
overflow:hidden;
}
.card::before{
content:"";
position:absolute; inset:-30%;
background: radial-gradient(circle at 20% 20%, rgba(122,252,255,.14), transparent 55%),
radial-gradient(circle at 70% 70%, rgba(255,79,216,.14), transparent 55%);
animation: drift 8s ease-in-out infinite;
opacity:.7;
}
.card > *{position:relative; z-index:1}
.card h2{
margin: 2px 0 10px;
font-size: 22px;
letter-spacing:-.4px;
}
.card p{margin: 0; color: var(--muted); line-height:1.55}
.bullets{
margin: 12px 0 0;
padding-left: 0;
list-style:none;
display:grid;
gap:10px;
}
.bullets li{
display:flex; gap:10px;
align-items:flex-start;
padding: 10px 10px;
border-radius: 16px;
border:1px solid rgba(255,255,255,.10);
background: rgba(0,0,0,.18);
}
.emoji{
width: 34px; height: 34px;
display:grid; place-items:center;
border-radius: 14px;
background: rgba(255,255,255,.07);
border:1px solid rgba(255,255,255,.12);
flex:0 0 auto;
}
.bullets b{display:block; margin-bottom:2px}
.bullets span{color: var(--muted); font-weight:650}
/* ======= Old tester comparison ======= */
.compare{
display:grid;
grid-template-columns: 1fr;
gap: 14px;
align-items:stretch;
}
@media(min-width:980px){
.compare{grid-template-columns: 1fr 1fr}
}
.img-card{
border:1px solid rgba(255,255,255,.12);
background: rgba(255,255,255,.05);
border-radius: var(--radius);
overflow:hidden;
box-shadow: var(--shadow);
position:relative;
}
.img-card img{
width:100%;
height: 320px;
object-fit: cover;
display:block;
filter: contrast(1.05) saturate(1.12);
}
.img-card .cap{
padding: 14px 14px 16px;
border-top:1px solid rgba(255,255,255,.10);
}
.tag{
display:inline-flex; align-items:center; gap:8px;
font-weight:900;
letter-spacing:.5px;
text-transform:uppercase;
font-size:12px;
padding:6px 10px;
border-radius:999px;
border:1px solid rgba(255,255,255,.14);
background: rgba(0,0,0,.22);
color:var(--muted);
}
/* ======= Testimonials ======= */
.quotes{
display:grid;
grid-template-columns: 1fr;
gap: 12px;
margin-top: 10px;
}
@media(min-width:860px){
.quotes{grid-template-columns: repeat(3, 1fr)}
}
blockquote{
margin:0;
padding: 14px;
border-radius: var(--radius);
border:1px solid rgba(255,255,255,.12);
background: rgba(255,255,255,.06);
box-shadow: 0 18px 60px rgba(0,0,0,.28);
position:relative;
overflow:hidden;
}
blockquote::before{
content:"“";
position:absolute;
top:-24px; left:10px;
font-size: 88px;
opacity:.16;
}
blockquote p{margin:0 0 10px; color:var(--muted); line-height:1.5}
blockquote footer{font-weight:900; color:var(--text)}
blockquote small{display:block; color:var(--muted); font-weight:750; margin-top:3px}
/* ======= Footer ======= */
footer{
margin-top: 26px;
padding-top: 18px;
border-top: 1px solid rgba(255,255,255,.10);
color: var(--muted);
font-weight:700;
display:flex; flex-direction:column; gap:8px;
}
/* ======= Scroll reveal ======= */
.reveal{
opacity:0;
transform: translateY(14px) scale(.98);
transition: opacity .7s ease, transform .7s ease;
}
.reveal.on{
opacity:1;
transform: translateY(0) scale(1);
}
/* ======= Confetti canvas ======= */
canvas#confetti{
position:fixed; inset:0;
pointer-events:none;
z-index:999;
}
/* ======= Reduced motion ======= */
@media (prefers-reduced-motion: reduce){
*{animation:none!important; transition:none!important; scroll-behavior:auto!important}
.bg-grid,.lasers{display:none}
}
</style>
</head>
<body>
<div class="bg-grid" aria-hidden="true"></div>
<div class="lasers" aria-hidden="true"></div>
<canvas id="confetti"></canvas>
<header>
<div class="nav">
<div class="brand">
<span class="dot" aria-hidden="true"></span>
<span>NETZWERKTESTER™</span>
</div>
<nav>
<a href="#features">Features</a>
<a href="#compare">Vergleich</a>
<a href="#testimonials">Stimmen</a>
</nav>
<div class="cta">
<a class="btn" href="#compare">👀 Showdown</a>
<a class="btn primary" id="boostBtn" href="#features">🚀 BOOST <span class="shine" aria-hidden="true"></span></a>
</div>
</div>
</header>
<main class="wrap">
<section class="hero">
<div>
<div class="kicker">
<span class="badge-live"><i></i> Live Hype</span>
<span>Übertrieben. Animiert. Absolut notwendig. 😎⚡</span>
</div>
<h1>
<span class="glitch" data-text="Der Netzwerktester, den wirklich ALLE brauchen.">Der Netzwerktester, den wirklich ALLE brauchen.</span>
<span aria-hidden="true"> 🧪🔌✨</span>
</h1>
<p class="sub">
Schluss mit „Warum gehts nicht?!“ — unser Netzwerktester verwandelt jedes Kabel in eine <b>offiziell zertifizierte
Glücksleitung</b>. Er misst nicht nur Durchgang… er misst <b>Aura</b>, <b>Vibes</b> und <b>Respekt</b>. 💚📈
</p>
<div class="hero-actions">
<a class="btn primary" href="#features">😤 Ich brauche das jetzt <span class="shine" aria-hidden="true"></span></a>
<a class="btn" href="#testimonials">⭐ 100% echte Stimmen*</a>
<span class="meter-label">POWER-LEVEL: <b id="powerLevel">9000</b>+</span>
</div>
<div class="stats">
<div class="stat">
<b><span id="uptime">99.98</span>%</b>
<span>Hype-Uptime</span>
</div>
<div class="stat">
<b><span id="cables">0</span></b>
<span>Kabel gerettet</span>
</div>
<div class="stat">
<b><span id="wow">0</span>×</b>
<span>„WOW“ pro Minute</span>
</div>
</div>
</div>
<aside class="device" aria-label="Animiertes Showcase">
<div class="device-inner">
<div class="device-top">
<div class="dots" aria-hidden="true"><i></i><i></i><i></i></div>
<div class="mode">ULTRA DIAG MODE 🔥</div>
</div>
<div class="screen">
<!-- Bild 1: Person mit Netzwerkkabel -->
<img
src="https://cdn.pixabay.com/photo/2016/08/15/20/02/compression-pressure-recorder-1596369_1280.jpg"
alt="Person hält ein Netzwerkkabel"
loading="lazy"
/>
<div class="floaters" aria-hidden="true" id="floaters"></div>
</div>
<div class="device-bottom">
<div class="meter" aria-hidden="true"><span></span></div>
<div class="meter-label">SCAN: <span id="scanText">LINK UP ✅</span></div>
</div>
</div>
</aside>
</section>
<section id="features" class="reveal">
<div class="grid">
<div class="card">
<h2>Warum ist das Ding so legendär? 🏆</h2>
<p>
Weil er die Realität debuggt. Du steckst ein Kabel rein — und plötzlich macht die Welt Sinn.
(Zumindest das Patchfeld.) 🌍🔧
</p>
<ul class="bullets">
<li>
<div class="emoji">🧠</div>
<div>
<b>IQ-Boost für den Schaltschrank</b>
<span>Erkennt Fehler, bevor sie überhaupt passieren. (Gefühlt.)</span>
</div>
</li>
<li>
<div class="emoji"></div>
<div>
<b>Turbo-Scan in Lichtgeschwindigkeit</b>
<span>So schnell, dass dein Blick hinterher ruckelt.</span>
</div>
</li>
<li>
<div class="emoji">🛡️</div>
<div>
<b>Anti-“Warum gehts nicht?”-Shield</b>
<span>Blockt Ausreden, Drama und Kabel-Karma.</span>
</div>
</li>
</ul>
</div>
<div class="card">
<h2>Für wen? Für ALLE. Wirklich alle. 😤</h2>
<p>
Schüler, Azubis, Techniker, Netzwerkgötter, IT-Orakel, Menschen mit Kabeln, Menschen ohne Kabeln,
sogar Leute, die „LAN“ für eine Stadt halten. 🏙️🔌
</p>
<ul class="bullets">
<li>
<div class="emoji">📱</div>
<div>
<b>Handy & PC: Perfekt sichtbar</b>
<span>Responsive Layout, große Buttons, kein Zoomen wie 2012.</span>
</div>
</li>
<li>
<div class="emoji">🎛️</div>
<div>
<b>Animationen: Maximum Overdrive</b>
<span>Neon, Glitch, Laser, Floating Emojis… ja.</span>
</div>
</li>
<li>
<div class="emoji">🧪</div>
<div>
<b>Wissenschaftlich übertrieben</b>
<span>Messwerte wirken 17% seriöser, wenn sie leuchten.</span>
</div>
</li>
</ul>
</div>
</div>
</section>
<section id="compare" class="reveal">
<h2 style="margin:0 0 12px; font-size:28px; letter-spacing:-.5px;">
Der epische Vergleich: ALT vs. HYPER-ULTRA 😱
</h2>
<div class="compare">
<article class="img-card">
<!-- Bild 2: sehr alter Netzwerktester -->
<img
src="https://cdn.pixabay.com/photo/2013/03/09/02/36/tester-91696_1280.jpg"
alt="Sehr alter Netzwerktester"
loading="lazy"
/>
<div class="cap">
<span class="tag">🕰️ Altgerät</span>
<h3 style="margin:10px 0 6px;">Der Klassiker: „Geht… irgendwie“</h3>
<p style="margin:0; color:var(--muted); line-height:1.5;">
Misst Dinge. Manchmal. Mit Charme. Aber ohne Laser. Ohne Glitch. Ohne Drama. (Also langweilig.) 😴
</p>
</div>
</article>
<article class="img-card">
<div style="position:relative">
<img
src="https://cdn.pixabay.com/photo/2017/12/24/21/08/secret-3037639_1280.jpg"
alt="Person mit Netzwerkkabel"
loading="lazy"
style="filter:saturate(1.3) contrast(1.08);"
/>
<div style="
position:absolute; inset:0;
background: radial-gradient(circle at 20% 20%, rgba(122,252,255,.22), transparent 55%),
radial-gradient(circle at 70% 70%, rgba(255,79,216,.18), transparent 55%);
mix-blend-mode: screen;
pointer-events:none;
"></div>
</div>
<div class="cap">
<span class="tag">🚀 HYPE-DEVICE</span>
<h3 style="margin:10px 0 6px;">NETZWERKTESTER™: „Ich sehe alles.“</h3>
<p style="margin:0; color:var(--muted); line-height:1.5;">
Findet Fehler. Findet Sinn. Findet deinen verlorenen Schraubendreher (theoretisch). 🧲✨
Und sieht dabei gefährlich gut aus. 😎
</p>
</div>
</article>
</div>
</section>
<section id="testimonials" class="reveal">
<h2 style="margin:0 0 6px; font-size:28px; letter-spacing:-.5px;">
100% echte Stimmen* ⭐
</h2>
<p style="margin:0 0 10px; color:var(--muted); font-weight:700;">
*Echt im Sinne von: Niemand hat widersprochen. 🤝😇
</p>
<div class="quotes">
<blockquote>
<p>„Ich hab ihn einmal eingeschaltet und plötzlich war mein Leben geordnet. Sogar die Patchkabel.“</p>
<footer>Max, <small>zertifizierter Kabel-Flüsterer 🧙‍♂️</small></footer>
</blockquote>
<blockquote>
<p>„Er sagt LINK UP mit so viel Selbstbewusstsein, ich fühl mich direkt kompetenter.“</p>
<footer>Sara, <small>Fehlerfinderin auf Koffein ☕</small></footer>
</blockquote>
<blockquote>
<p>„Ich wollte keinen. Jetzt hab ich drei. Einen fürs Bett, einen fürs Auto, einen fürs Herz.“</p>
<footer>Ali, <small>LAN-Romantiker 💘</small></footer>
</blockquote>
</div>
</section>
<footer>
<div>© <span id="year"></span> Netzwerktester™ — „Wenns leuchtet, ists besser.“ ✨</div>
<div style="opacity:.85"><a href="https://www.fsae41.de">HOME</a></div>
</footer>
</main>
<script>
// ===== Scroll reveal =====
const revealEls = document.querySelectorAll('.reveal');
const io = new IntersectionObserver((entries)=>{
for (const e of entries){
if (e.isIntersecting) e.target.classList.add('on');
}
}, {threshold: 0.12});
revealEls.forEach(el => io.observe(el));
// ===== Floating emojis in the "device screen" =====
const floaters = document.getElementById('floaters');
const EMOJIS = ["🔌","⚡","✨","📶","🧪","😎","🟩","💥","🧠","🛠️","🌈","🚀"];
function spawnFloater(){
const el = document.createElement('div');
el.className = 'floater';
el.textContent = EMOJIS[Math.floor(Math.random()*EMOJIS.length)];
el.style.left = Math.random()*100 + "%";
el.style.bottom = (-10 - Math.random()*10) + "px";
el.style.animationDuration = (2.2 + Math.random()*2.8) + "s";
el.style.animationDelay = (Math.random()*0.2) + "s";
el.style.transform = `translateY(40px) rotate(${(Math.random()*18-9).toFixed(1)}deg)`;
floaters.appendChild(el);
setTimeout(()=> el.remove(), 5200);
}
setInterval(spawnFloater, 180);
// ===== Fake live scan text =====
const scanText = document.getElementById('scanText');
const scanPhrases = [
"LINK UP ✅", "PAIR OK ✅", "GIGABIT DREAM ✅", "VIBES: STABIL ✅",
"PATCHKABEL: GLÜCKLICH ✅", "KARMA: GEROUTET ✅", "FEHLER: GEFUNDEN 🎯"
];
setInterval(()=>{
scanText.textContent = scanPhrases[Math.floor(Math.random()*scanPhrases.length)];
}, 1300);
// ===== Counters =====
const yearEl = document.getElementById('year');
yearEl.textContent = new Date().getFullYear();
const uptimeEl = document.getElementById('uptime');
const cablesEl = document.getElementById('cables');
const wowEl = document.getElementById('wow');
const powerLevelEl = document.getElementById('powerLevel');
let cables = 0;
let wow = 0;
let power = 9001;
function tick(){
cables += Math.floor(1 + Math.random()*6);
wow += Math.floor(1 + Math.random()*4);
power += Math.floor(6 + Math.random()*18);
cablesEl.textContent = cables.toLocaleString('de-DE');
wowEl.textContent = wow.toLocaleString('de-DE');
powerLevelEl.textContent = power.toLocaleString('de-DE');
// uptime wiggle
const base = 99.90;
const v = (base + Math.random()*0.09).toFixed(2);
uptimeEl.textContent = v;
}
setInterval(tick, 900);
tick();
// ===== Confetti "BOOST" (simple canvas particles) =====
const canvas = document.getElementById('confetti');
const ctx = canvas.getContext('2d');
let W, H;
function resize(){
W = canvas.width = window.innerWidth * devicePixelRatio;
H = canvas.height = window.innerHeight * devicePixelRatio;
}
window.addEventListener('resize', resize);
resize();
let particles = [];
function burst(){
const count = 170;
for(let i=0;i<count;i++){
particles.push({
x: (Math.random()*window.innerWidth) * devicePixelRatio,
y: (-10 - Math.random()*60) * devicePixelRatio,
vx: (-1.2 + Math.random()*2.4) * devicePixelRatio,
vy: (2.0 + Math.random()*4.4) * devicePixelRatio,
r: (2 + Math.random()*4) * devicePixelRatio,
rot: Math.random()*Math.PI*2,
vr: (-0.18 + Math.random()*0.36),
life: 0,
max: 160 + Math.random()*120
});
}
}
function draw(){
ctx.clearRect(0,0,W,H);
for(const p of particles){
p.x += p.vx;
p.y += p.vy;
p.vy += 0.02 * devicePixelRatio; // gravity
p.rot += p.vr;
p.life++;
const alpha = Math.max(0, 1 - p.life / p.max);
ctx.save();
ctx.globalAlpha = alpha * 0.9;
ctx.translate(p.x, p.y);
ctx.rotate(p.rot);
// No fixed colors: use random-ish neon via hue
const hue = (p.life*2 + p.x/W*360) % 360;
ctx.fillStyle = `hsla(${hue}, 95%, 60%, 1)`;
ctx.fillRect(-p.r, -p.r, p.r*2.2, p.r*1.2);
ctx.restore();
}
particles = particles.filter(p => p.life < p.max && p.y < H + 120);
requestAnimationFrame(draw);
}
draw();
document.getElementById('boostBtn').addEventListener('click', (e)=>{
// allow anchor scroll, but also boost visuals
burst();
// micro screen shake
document.body.animate([
{ transform: 'translate(0,0)' },
{ transform: 'translate(2px,-2px)' },
{ transform: 'translate(-2px,2px)' },
{ transform: 'translate(1px,1px)' },
{ transform: 'translate(0,0)' }
], { duration: 320, iterations: 1 });
});
</script>
</body>
</html>