kilabor/layouts/_default/single.html
2026-06-19 00:33:12 +02:00

640 lines
27 KiB
HTML
Raw Permalink 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.

{{ define "main" }}
<!-- SCANLINES + DECLASSIFIED OVERLAY -->
<div id="declassified-overlay">
<div class="scanlines"></div>
<div id="declassified-stamp">ZUGANG<br>GEWÄHRT</div>
</div>
<div class="person-page-wrapper visible" style="padding-bottom: 100px; opacity: 1 !important;">
{{ partial "person_nav.html" . }}
<!-- HERO BANNER -->
<div class="person-hero">
{{ if .Params.comic_img }}
<div class="person-hero-img" style="background-image: url('{{ .Params.comic_img }}')"></div>
{{ end }}
<div class="person-hero-content">
<div class="person-hero-badges">
<span class="hero-badge">ZENTRAL-ARCHIV</span>
<span class="hero-badge red">EINHEIT IDENTIFIZIERT</span>
</div>
<p class="person-pre-label" style="margin:12px 0 4px;">// ZENTRAL-ARCHIV · EINHEIT IDENTIFIZIERT //</p>
<div class="person-title-wrap">
<span class="person-title-deco">⟪</span>
<h1 class="person-glitch-title" data-text="{{ .Title | upper }}">{{ .Title | upper }}</h1>
<span class="person-title-deco">⟫</span>
</div>
<p class="person-sub-label">STATUS: <span class="person-status-blink">{{ .Params.status | default "AKTIV" | upper }}</span></p>
<!-- STAT BARS -->
<div class="stat-bars">
<div class="stat-row">
<span class="stat-label">GEFAHR</span>
<div class="stat-track"><div class="stat-bar danger" data-val="{{ .Params.stat_gefahr | default 50 }}"></div></div>
<span class="stat-val">{{ .Params.stat_gefahr | default 50 }}%</span>
</div>
<div class="stat-row">
<span class="stat-label">STABILITÄT</span>
<div class="stat-track"><div class="stat-bar stable" data-val="{{ .Params.stat_stabilitaet | default 50 }}"></div></div>
<span class="stat-val">{{ .Params.stat_stabilitaet | default 50 }}%</span>
</div>
<div class="stat-row">
<span class="stat-label">CHAOS</span>
<div class="stat-track"><div class="stat-bar chaos" data-val="{{ .Params.stat_chaos | default 50 }}"></div></div>
<span class="stat-val">{{ .Params.stat_chaos | default 50 }}%</span>
</div>
<div class="stat-row">
<span class="stat-label">KOMPETENZ</span>
<div class="stat-track"><div class="stat-bar kompetenz" data-val="{{ .Params.stat_kompetenz | default 50 }}"></div></div>
<span class="stat-val">{{ .Params.stat_kompetenz | default 50 }}%</span>
</div>
</div>
</div>
</div>
<!-- ALIAS TICKER -->
{{ if .Params.alias }}
<div class="alias-ticker-outer">
<div class="alias-ticker-inner">
<span>{{ .Params.alias }} &nbsp;·&nbsp; {{ .Params.alias }} &nbsp;·&nbsp; {{ .Params.alias }}</span>
</div>
</div>
{{ end }}
<div class="container" style="max-width: 900px; margin: 0 auto; padding: 0 20px;">
<header style="margin-bottom: 20px; display:none;"></header>
<!-- DIE SCHÖNE STEAMPUNK TIMELINE -->
<div class="timeline-track">
{{ range $index, $element := .Params.events }}
{{ $side := "right" }}{{ if (mod $index 2) }}{{ $side = "left" }}{{ end }}
<div class="time-node {{ $side }} {{ if .omega }}omega{{ end }}">
<div class="time-content {{ if .omega }}omega-node{{ end }}">
<div class="tc-header">
<span class="tc-year">[ {{ .year }} ]</span>
{{ if .tag }}<span class="tc-tag">{{ .tag }}</span>{{ end }}
</div>
<p>{{ .text }}</p>
</div>
</div>
{{ end }}
</div>
<!-- AKTE BUTTON -->
<div style="text-align: center; margin-top: 60px;">
<button class="akte-label-btn"
onclick="document.getElementById('person-akte-modal').style.display='flex'; document.body.style.overflow='hidden';">
<div class="akte-label-top">
<span class="akte-label-nr">DOKUMENT-NR. {{ .Params.geburtsjahr | default "UNBEKANNT" }}</span>
<span class="akte-label-stamp">VERTRAULICH</span>
</div>
<div class="akte-label-divider"></div>
<div class="akte-label-title">AKTE: {{ .Title | upper }}</div>
<div class="akte-label-divider"></div>
<div class="akte-label-bottom">
<span>STATUS: {{ .Params.status | default "KLASSIFIZIERT" }}</span>
<span>▶ AKTE ÖFFNEN</span>
</div>
</button>
</div>
<style>
.akte-label-btn {
background: linear-gradient(180deg, #1c1208 0%, #0e0a04 100%);
border: 1px solid #5d3d1e;
border-left: 4px solid #b87333;
color: #d4af37;
font-family: 'Courier New', monospace;
cursor: pointer;
padding: 18px 28px;
width: 320px;
text-align: left;
transition: all 0.2s;
box-shadow: 2px 2px 12px rgba(0,0,0,0.6);
position: relative;
}
.akte-label-btn::before {
content: '';
position: absolute;
top: 6px; left: 6px; right: 6px; bottom: 6px;
border: 1px dashed rgba(184,115,51,0.2);
pointer-events: none;
}
.akte-label-btn:hover {
border-left-color: #ff4500;
box-shadow: 3px 3px 20px rgba(184,115,51,0.2);
background: linear-gradient(180deg, #221508 0%, #0e0a04 100%);
}
.akte-label-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.akte-label-nr {
font-size: 0.6rem;
color: rgba(212,175,55,0.4);
letter-spacing: 1px;
}
.akte-label-stamp {
font-size: 0.55rem;
letter-spacing: 2px;
color: #b71c1c;
border: 1px solid #b71c1c;
padding: 1px 6px;
opacity: 0.8;
}
.akte-label-divider {
border-top: 1px solid rgba(184,115,51,0.25);
margin: 8px 0;
}
.akte-label-title {
font-size: 1rem;
font-weight: bold;
letter-spacing: 4px;
color: #d4af37;
margin: 4px 0;
}
.akte-label-bottom {
display: flex;
justify-content: space-between;
font-size: 0.6rem;
color: rgba(212,175,55,0.45);
letter-spacing: 1px;
margin-top: 4px;
}
.akte-label-btn:hover .akte-label-bottom span:last-child {
color: #ff4500;
}
</style>
</div>
</div>
<!-- DAS ECHTE ABGEWETZTE PAPIER AKTE MODAL -->
<div id="person-akte-modal" style="position: fixed; inset: 0; z-index: 1000000; background: rgba(0,0,0,0.85); display: none; align-items: center; justify-content: center; padding: 10px; overflow: hidden; perspective: 1000px;">
<div style="display: flex; flex-direction: column; align-items: center; max-width: 585px; width: 95%;">
<div class="akte-inner" style="width: 100%; background: #d9c5a0; background-image: radial-gradient(circle at 50% 50%, rgba(255,255,255,0.1) 0%, transparent 100%), url('https://www.transparenttextures.com/patterns/old-paper.png'); border: 1px solid #8b7355; padding: 25px; position: relative; font-family: 'Courier New', monospace; box-shadow: 10px 20px 50px rgba(0,0,0,0.8), inset 0 0 100px rgba(139,115,85,0.3); transform: rotate(-2deg); animation: throw-sign 0.5s ease-out forwards; color: #2a1b0a;">
<style>
@keyframes throw-sign {
0% { transform: rotate(-10deg) scale(0.7) translateY(500px); opacity: 0; }
100% { transform: rotate(-2deg) scale(1) translateY(0); opacity: 1; }
}
.akte-inner h1 { color: #2a1b0a !important; font-size: 1.8rem !important; margin: 10px 0 2px !important; text-shadow: none !important; border-bottom: 2px solid rgba(42,27,10,0.2); }
.akte-inner div, .akte-inner p { font-size: 0.75rem !important; }
.akte-inner .data-row { border-bottom: 1px solid rgba(42,27,10,0.1) !important; padding: 6px 0 !important; }
.akte-inner .label { color: #5d4037 !important; font-weight: bold; }
.akte-inner .red-stamp { border: 2px solid #b71c1c; color: #b71c1c; padding: 3px 10px; font-weight: bold; transform: rotate(10deg); opacity: 0.8; font-size: 0.8rem !important; display: inline-block; }
</style>
<!-- Top Header Bar -->
<div style="display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 12px;">
<div class="red-stamp">TOP SECRET</div>
<button onclick="document.getElementById('person-akte-modal').style.display='none'; document.body.style.overflow='auto';"
style="background: rgba(0,0,0,0.1); border: 1px solid #2a1b0a; color: #2a1b0a; cursor: pointer; padding: 3px 10px; font-size: 0.7rem !important;">[X] SCHLIESSEN</button>
</div>
{{ if .Params.akte_fotos }}
<!-- FOTO SWITCHER -->
<div style="display: flex; gap: 8px; margin-bottom: 16px; border-bottom: 1px dashed rgba(42,27,10,0.2); padding-bottom: 12px;">
{{ range $i, $foto := .Params.akte_fotos }}
<button onclick="switchAkteFoto('{{ $foto }}')"
class="akte-foto-btn {{ if eq $i 0 }}akte-foto-active{{ end }}"
data-foto="{{ $foto }}"
style="background: {{ if eq $i 0 }}rgba(183,28,28,0.15){{ else }}rgba(0,0,0,0.1){{ end }}; border: 1px solid {{ if eq $i 0 }}#b71c1c{{ else }}rgba(42,27,10,0.3){{ end }}; color: #2a1b0a; cursor: pointer; padding: 3px 12px; font-family: 'Courier New', monospace; font-size: 0.65rem !important; letter-spacing: 1px;">
FOTO {{ add $i 1 }}
</button>
{{ end }}
</div>
{{ end }}
<div style="display: flex; gap: 20px; align-items: flex-start;">
<!-- Left: Photo -->
<div style="position: relative; border: 1px solid #2a1b0a; padding: 3px; background: #fff; box-shadow: 2px 2px 5px rgba(0,0,0,0.2);">
{{ $photo := .Params.img | default "/img/hero.png" }}
<img src="{{ $photo }}" class="akte-foto" style="width: 200px; height: 250px; object-fit: cover; filter: none; cursor: zoom-in; display: block;"
onclick="document.getElementById('akte-foto-zoom').style.display='flex';">
<div style="position: absolute; bottom: 5px; right: -10px; background: #b71c1c; color: #fff; padding: 2px 5px; font-weight: bold; font-size: 0.6rem !important; transform: rotate(-5deg);">GESPERRT</div>
</div>
<!-- ZOOM OVERLAY -->
<div id="akte-foto-zoom" onclick="this.style.display='none';"
style="display:none; position:fixed; inset:0; z-index:9999999; background:rgba(0,0,0,0.92); align-items:center; justify-content:center; cursor:zoom-out;">
<img src="{{ $photo }}" style="max-width:90vw; max-height:90vh; object-fit:contain; box-shadow: 0 0 60px rgba(0,0,0,0.9); border: 2px solid #2a1b0a;">
</div>
<!-- Right: Main Info -->
<div style="flex: 1;">
<div style="font-size: 0.5rem !important; color: #5d4037; letter-spacing: 2px; margin-bottom: 2px;">PROTOKOLL NR. 1974-Ø</div>
<h1 style="font-weight: bold;">{{ .Title | upper }}</h1>
<p style="color: #5d4037; font-size: 0.7rem !important; margin: 5px 0 10px;">ALIAS: {{ .Params.alias | upper }}</p>
<div style="display: flex; gap: 10px;">
<div style="border: 1px solid #b71c1c; padding: 2px 8px; color: #b71c1c; font-size: 0.6rem !important; font-weight: bold;">STATUS: {{ .Params.status | upper }}</div>
<div style="color: #2a1b0a; font-size: 0.6rem !important; font-weight: bold;">GEFAHR: <span style="letter-spacing: 1px;">{{ .Params.gefahr }}</span><br><img src="/img/akte/hp_totenkopf_1.png" style="width: 70px; height: 70px; object-fit: contain; margin-top: 4px;"></div>
</div>
</div>
</div>
<!-- Data Table -->
<div style="margin-top: 20px; border-top: 2px solid rgba(42,27,10,0.2);">
{{ $data := slice
(dict "l" "DESIGNATION" "v" .Title)
(dict "l" "GEBURTSDATUM" "v" $.Params.geburtsjahr "c" true)
(dict "l" "BESCHÄFTIGUNG" "v" $.Params.occupation)
(dict "l" "SPEZIALFÄHIGK." "v" $.Params.spezialfaehigkeit)
(dict "l" "BEKANNTE KOMPL." "v" $.Params.komplizen "c" true)
(dict "l" "LETZTE AKTIVITÄT" "v" "GERADE JETZT")
(dict "l" "STABILITÄT" "v" $.Params.stabilitaet)
(dict "l" "STANDORT" "v" $.Params.standort)
}}
{{ range $data }}
<div class="data-row" style="display: flex; align-items: center;">
<div class="label" style="width: 160px; letter-spacing: 1px;">{{ .l }}:</div>
<div style="flex: 1; font-weight: normal;">
{{ .v }}
{{ if .c }}<span style="background: rgba(0,0,0,0.8); color: rgba(0,0,0,0); margin-left: 5px; padding: 0 10px;">XXXXX</span>{{ end }}
</div>
</div>
{{ end }}
</div>
<!-- Footer Elements -->
<div style="margin-top: 20px; display: flex; justify-content: space-between; align-items: flex-end;">
<div style="display: flex; align-items: center; gap: 10px; opacity: 0.7;">
<div style="width: 35px; height: 35px;">
<svg viewBox="0 0 100 100" stroke="#2a1b0a" fill="none"><circle cx="50" cy="50" r="40"/><path d="M30 50 Q50 10 70 50 T30 50 Z"/></svg>
</div>
<div style="font-size: 0.6rem !important; color: #2a1b0a; line-height: 1.2;">ID-SCAN: 94.7%<br>VERIFIZIERT</div>
</div>
<div style="font-family: 'Courier New', monospace; font-size: 0.75rem !important; letter-spacing: 2px; color: #5d4037; border: 1px dashed #2a1b0a; padding: 2px 10px;">ARCHIV_PERMANENT</div>
</div>
</div>
</div>
</div>
<style>
.akte-foto { transition: transform 0.2s, box-shadow 0.2s; }
.akte-foto:hover { transform: scale(1.04); box-shadow: 0 0 15px rgba(184,115,51,0.7); }
.akte-foto-btn { transition: all 0.2s; }
.akte-foto-btn:hover { background: rgba(183,28,28,0.1) !important; border-color: #b71c1c !important; }
.akte-foto-active { background: rgba(183,28,28,0.15) !important; border-color: #b71c1c !important; }
/* OMEGA PULSE ANIMATION (VIBRATING & BLINKING) */
.time-node.omega .time-content {
border: 2px solid rgba(255, 69, 0, 0.6) !important;
box-shadow: inset 0 0 12px rgba(255, 69, 0, 0.15), 0 0 10px rgba(255, 0, 0, 0.2);
animation: omega-pulse 3s infinite alternate;
background: linear-gradient(135deg, rgba(80, 20, 10, 0.95), rgba(30, 0, 0, 0.95)) !important;
}
.time-node.omega .node-dot {
border-color: #ff4500 !important;
background: radial-gradient(circle, #ff0000 0%, #330000 100%) !important;
box-shadow: 0 0 8px rgba(255, 69, 0, 0.4);
animation: omega-dot-pulse 3s infinite alternate ease-in-out;
}
.node-dot {
box-shadow: 0 0 8px rgba(212, 175, 55, 0.4);
transition: all 0.3s ease;
}
.time-node.omega .tc-year {
color: #ff4500 !important;
text-shadow: 0 0 10px #ff4500;
font-weight: 900 !important;
}
@keyframes omega-dot-pulse {
0% { box-shadow: 0 0 5px rgba(255, 69, 0, 0.3); }
100% { box-shadow: 0 0 12px rgba(255, 69, 0, 0.6); }
}
@keyframes omega-pulse {
0% { box-shadow: inset 0 0 8px rgba(255, 69, 0, 0.1), 0 0 6px rgba(255, 0, 0, 0.15); border-color: rgba(255, 69, 0, 0.4); }
100% { box-shadow: inset 0 0 18px rgba(255, 69, 0, 0.25), 0 0 14px rgba(255, 0, 0, 0.3); border-color: rgba(255, 69, 0, 0.8); }
}
@keyframes omega-dot-blink {
50% { opacity: 0; transform: scale(1.5); }
}
</style>
<style>
/* ── DECLASSIFIED OVERLAY ─────────────────── */
#declassified-overlay {
position: fixed; inset: 0; z-index: 99999;
pointer-events: none;
background: rgba(0,0,0,0.92);
display: flex; align-items: center; justify-content: center;
transition: opacity 0.8s ease;
}
#declassified-overlay.gone { opacity: 0; pointer-events: none; }
.scanlines {
position: absolute; inset: 0;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0,255,0,0.015) 2px,
rgba(0,255,0,0.015) 4px
);
pointer-events: none;
}
#declassified-stamp {
font-family: 'Courier New', monospace;
font-size: 3.5rem;
font-weight: 900;
color: #b71c1c;
border: 6px solid #b71c1c;
padding: 20px 40px;
letter-spacing: 8px;
text-align: center;
line-height: 1.2;
transform: rotate(-12deg) scale(0);
opacity: 0;
text-shadow: 0 0 30px rgba(183,28,28,0.5);
box-shadow: 0 0 40px rgba(183,28,28,0.3), inset 0 0 40px rgba(183,28,28,0.1);
animation: stamp-in 0.4s 0.3s cubic-bezier(0.175,0.885,0.32,1.275) forwards;
}
@keyframes stamp-in {
to { transform: rotate(-12deg) scale(1); opacity: 0.85; }
}
/* ── HERO BANNER ──────────────────────────── */
.person-hero {
position: relative;
width: 100%;
min-height: 300px;
background: linear-gradient(135deg, #0a0600 0%, #120e06 60%, #0a0600 100%);
border-bottom: 1px solid rgba(184,115,51,0.3);
overflow: hidden;
display: flex;
align-items: center;
margin-bottom: 0;
}
.person-hero::before {
content: '';
position: absolute; inset: 0;
background: repeating-linear-gradient(
0deg, transparent, transparent 3px,
rgba(184,115,51,0.03) 3px, rgba(184,115,51,0.03) 4px
);
pointer-events: none;
}
.person-hero-img {
position: absolute;
right: 0; top: 0; bottom: 0;
width: 45%;
background-size: contain;
background-repeat: no-repeat;
background-position: right bottom;
opacity: 0.25;
filter: sepia(0.4) hue-rotate(10deg);
mask-image: linear-gradient(to left, rgba(0,0,0,0.8) 0%, transparent 100%);
-webkit-mask-image: linear-gradient(to left, rgba(0,0,0,0.8) 0%, transparent 100%);
}
.person-hero-content {
position: relative;
z-index: 2;
padding: 30px 40px;
max-width: 620px;
}
.person-hero-badges {
display: flex; gap: 10px; margin-bottom: 10px; flex-wrap: wrap;
}
.hero-badge {
font-family: 'Courier New', monospace;
font-size: 0.55rem;
letter-spacing: 3px;
padding: 3px 10px;
border: 1px solid rgba(184,115,51,0.4);
color: rgba(184,115,51,0.7);
}
.hero-badge.red {
border-color: rgba(183,28,28,0.5);
color: rgba(183,28,28,0.8);
}
/* ── STAT BARS ────────────────────────────── */
.stat-bars { margin-top: 20px; width: 100%; max-width: 400px; }
.stat-row {
display: flex; align-items: center; gap: 10px; margin-bottom: 8px;
}
.stat-label {
font-family: 'Courier New', monospace;
font-size: 0.6rem; letter-spacing: 2px;
color: rgba(212,175,55,0.5);
width: 80px; flex-shrink: 0;
}
.stat-track {
flex: 1; height: 6px;
background: rgba(255,255,255,0.05);
border: 1px solid rgba(184,115,51,0.2);
overflow: hidden;
}
.stat-bar {
height: 100%; width: 0%;
transition: width 1.2s cubic-bezier(0.4,0,0.2,1);
}
.stat-bar.danger { background: linear-gradient(90deg, #8b0000, #ff4500); box-shadow: 0 0 8px rgba(255,69,0,0.5); }
.stat-bar.stable { background: linear-gradient(90deg, #1a4a1a, #4caf50); box-shadow: 0 0 8px rgba(76,175,80,0.5); }
.stat-bar.chaos { background: linear-gradient(90deg, #4a0080, #c800ff); box-shadow: 0 0 8px rgba(200,0,255,0.4); }
.stat-bar.kompetenz { background: linear-gradient(90deg, #1a3a5c, #2196f3); box-shadow: 0 0 8px rgba(33,150,243,0.5); }
.stat-val {
font-family: 'Courier New', monospace;
font-size: 0.6rem; color: rgba(212,175,55,0.4);
width: 32px; text-align: right; flex-shrink: 0;
}
/* ── ALIAS TICKER ─────────────────────────── */
.alias-ticker-outer {
overflow: hidden;
background: rgba(0,0,0,0.6);
border-top: 1px solid rgba(184,115,51,0.15);
border-bottom: 1px solid rgba(184,115,51,0.15);
padding: 7px 0;
white-space: nowrap;
}
.alias-ticker-inner {
display: inline-block;
animation: ticker-scroll 18s linear infinite;
font-family: 'Courier New', monospace;
font-size: 0.65rem;
letter-spacing: 4px;
color: rgba(184,115,51,0.5);
padding-left: 100%;
}
@keyframes ticker-scroll {
from { transform: translateX(0); }
to { transform: translateX(-50%); }
}
/* ── GLITCH + TITLE (gleich wie vorher) ───── */
.person-pre-label {
color: rgba(184,115,51,0.5);
font-family: 'Courier New', monospace;
font-size: 0.6rem; letter-spacing: 4px; margin-bottom: 6px;
}
.person-title-wrap {
display: flex; align-items: center; gap: 14px; margin: 4px 0;
}
.person-title-deco {
color: #b87333; font-size: 1.8rem; opacity: 0.6;
animation: deco-pulse 2s ease-in-out infinite alternate;
}
@keyframes deco-pulse {
from { opacity: 0.3; transform: scaleY(0.85); }
to { opacity: 0.8; transform: scaleY(1.1); }
}
.person-glitch-title {
color: #ff4500; font-family: 'Courier New', monospace;
font-size: 2rem; letter-spacing: 10px;
text-shadow: 0 0 20px rgba(255,69,0,0.5);
margin: 0; position: relative;
animation: glitch-flicker 6s infinite;
}
.person-glitch-title::before,
.person-glitch-title::after {
content: attr(data-text); position: absolute;
left: 0; top: 0; width: 100%; overflow: hidden; opacity: 0;
}
.person-glitch-title::before {
color: #0ff; animation: glitch-top 6s infinite;
clip-path: polygon(0 0,100% 0,100% 40%,0 40%);
}
.person-glitch-title::after {
color: #f0f; animation: glitch-bot 6s infinite;
clip-path: polygon(0 60%,100% 60%,100% 100%,0 100%);
}
@keyframes glitch-flicker {
0%,90%,100% { text-shadow: 0 0 20px rgba(255,69,0,0.5); }
92% { text-shadow: 2px 0 #0ff,-2px 0 #f0f,0 0 20px rgba(255,69,0,0.5); }
94% { text-shadow: -2px 0 #0ff,2px 0 #f0f,0 0 20px rgba(255,69,0,0.5); }
96% { text-shadow: 0 0 20px rgba(255,69,0,0.5); }
98% { text-shadow: 1px 0 #0ff,-1px 0 #f0f; }
}
@keyframes glitch-top {
0%,90%,100% { opacity:0; transform:none; }
92% { opacity:0.7; transform:translate(-3px,-2px); }
94% { opacity:0; }
96% { opacity:0.5; transform:translate(3px,-1px); }
98% { opacity:0; }
}
@keyframes glitch-bot {
0%,90%,100% { opacity:0; transform:none; }
93% { opacity:0.6; transform:translate(3px,2px); }
95% { opacity:0; }
97% { opacity:0.4; transform:translate(-3px,1px); }
99% { opacity:0; }
}
.person-sub-label {
color: rgba(212,175,55,0.45); font-family: 'Courier New', monospace;
font-size: 0.65rem; letter-spacing: 3px; margin-top: 6px;
}
.person-status-blink { color: #0f0; animation: blink-status 1.4s step-end infinite; }
@keyframes blink-status { 50% { opacity: 0; } }
</style>
<script>
// ── DECLASSIFIED EFFECT ──────────────────────
(function() {
const key = 'decl_{{ .Title | urlize }}';
const overlay = document.getElementById('declassified-overlay');
if (!overlay) return;
if (sessionStorage.getItem(key)) {
overlay.style.display = 'none';
return;
}
setTimeout(() => {
overlay.classList.add('gone');
setTimeout(() => {
overlay.style.display = 'none';
sessionStorage.setItem(key, '1');
}, 900);
}, 1800);
})();
// ── STAT BARS ANIMIEREN ──────────────────────
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
document.querySelectorAll('.stat-bar').forEach(bar => {
bar.style.width = bar.dataset.val + '%';
});
}, 400);
});
</script>
<script>
// CYBER SPINNE
(function() {
const SPIDER = '🕷';
let active = [];
function spawn() {
const el = document.createElement('div');
el.textContent = SPIDER;
el.style.cssText = [
'position:fixed',
'font-size:1.6rem',
'z-index:999999',
'pointer-events:none',
'transition:none',
'filter:drop-shadow(0 0 4px #0f0) hue-rotate(100deg) brightness(0.7)',
'will-change:transform',
'line-height:1',
].join(';');
document.body.appendChild(el);
const W = window.innerWidth, H = window.innerHeight;
// Startpunkt: zufälliger Bildschirmrand
const edge = Math.floor(Math.random() * 4);
let x = edge === 1 ? W + 20 : edge === 3 ? -20 : Math.random() * W;
let y = edge === 0 ? -20 : edge === 2 ? H + 20 : Math.random() * H;
el.style.left = x + 'px';
el.style.top = y + 'px';
// 4–7 zufällige Wegpunkte quer über den Bildschirm
const steps = 4 + Math.floor(Math.random() * 4);
let i = 0;
function step() {
if (i >= steps || !document.body.contains(el)) { el.remove(); return; }
const tx = Math.random() * W;
const ty = Math.random() * H;
const dist = Math.hypot(tx - x, ty - y);
const dur = dist * 4; // ms — je weiter, desto länger
const ang = Math.atan2(ty - y, tx - x) * 180 / Math.PI + 90;
el.style.transition = `left ${dur}ms linear, top ${dur}ms linear`;
el.style.transform = `rotate(${ang}deg)`;
el.style.left = tx + 'px';
el.style.top = ty + 'px';
x = tx; y = ty; i++;
setTimeout(step, dur);
}
step();
}
// sofort eine + dann alle 4 Sekunden
spawn();
setInterval(spawn, 4000);
})();
function switchAkteFoto(src) {
document.querySelector('.akte-foto').src = src;
document.getElementById('akte-foto-zoom').querySelector('img').src = src;
document.querySelectorAll('.akte-foto-btn').forEach(btn => {
const active = btn.dataset.foto === src;
btn.classList.toggle('akte-foto-active', active);
btn.style.background = active ? 'rgba(183,28,28,0.15)' : 'rgba(0,0,0,0.1)';
btn.style.borderColor = active ? '#b71c1c' : 'rgba(42,27,10,0.3)';
});
}
</script>
{{ end }}