/* ===================================================================
   JONAS ENGEL — Homepage, Version 2 ("Glitch")
   -------------------------------------------------------------------
   Mehrseitige Struktur: index.html (Startseite, nur Bild + Name,
   mit durchgehendem Glitch-Effekt) + about/projects/calendar/media/
   contact.html (jeweils: Bild auf einer Seite, Inhalt auf der
   anderen, Hintergrund führt die Bildfarbe als Verlauf fort).

   Farben/Schriften unten als Variablen — hier anpassen, wirkt sich
   auf die ganze Seite aus.
   =================================================================== */

:root {
  --bg: #08090b;
  --fg: #f2eee4;
  --fg-dim: #8d8f94;
  --accent: #2fe0e8;
  --accent-2: #ff2626;
  --line: rgba(242, 238, 228, 0.14);
  --chaos-amp: 1; /* wird live von script.js über den Chaos-Slider gesetzt */

  /* Farbe aus dem rechten Bildrand von portrait-double.jpg —
     wird als Verlaufsfarbe auf den Unterseiten benutzt, damit der
     Hintergrund das Bild optisch fortsetzt. Neues Bild, andere
     Farbe: Wert hier anpassen. */
  --image-edge: #2e3f50;

  --font-display: "Space Grotesk", Arial, sans-serif;
  --font-sans: "Space Grotesk", Arial, sans-serif;
  --font-serif: "Fraunces", Georgia, serif;
  --font-hand: "Caveat", cursive;

  --edge: clamp(1.25rem, 5vw, 4rem);
  --nav-h: 64px;
}

* {
  box-sizing: border-box;
}

/* ===================================================================
   SEITEN-ÜBERGANG — Chaos-reaktiver Glitch beim Seitenwechsel
   -------------------------------------------------------------------
   Läuft auf jeder Seite automatisch beim Laden weg (ptRevealAuto,
   ohne JS-Abhängigkeit — falls JS mal nicht lädt, verschwindet der
   Übergang trotzdem zuverlässig). Beim Klick auf einen internen Link
   fügt script.js kurz die Klasse "pt-exit" hinzu, bevor navigiert
   wird — Stärke/Dauer skalieren mit --chaos-amp, genau wie der
   Hero-Glitch und die Artefakte.
   =================================================================== */
.page-transition-overlay {
  position: fixed;
  inset: 0;
  z-index: 3000;
  pointer-events: none;
  overflow: hidden;
  background: var(--bg);
  animation: ptRevealAuto 0.6s ease-out 0.05s forwards;
}
.pt-band {
  position: absolute;
  inset: 0;
}
.pt-band.pt-base {
  background: var(--bg);
}
.pt-band.pt-b1 {
  background: var(--accent-2);
  mix-blend-mode: screen;
  opacity: 0;
}
.pt-band.pt-b2 {
  background: var(--accent);
  mix-blend-mode: screen;
  opacity: 0;
}
.pt-band.pt-b3 {
  background: #7cff5a;
  mix-blend-mode: screen;
  opacity: 0;
}
.pt-scanlines {
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.05) 0px,
    rgba(255, 255, 255, 0.05) 1px,
    transparent 1px,
    transparent 3px
  );
  mix-blend-mode: overlay;
}

@keyframes ptRevealAuto {
  0%   { opacity: 1; clip-path: inset(0 0 0 0); }
  18%  { opacity: 1; clip-path: inset(0 0 62% 0); }
  34%  { opacity: 1; clip-path: inset(0 0 22% 0); }
  50%  { opacity: 1; clip-path: inset(0 0 0 0); }
  100% { opacity: 0; }
}

/* Wird von script.js kurz vor dem Navigieren hinzugefügt — jetzt mit
   mehr Zwischen-Sprüngen und drei Bildteilen, die zeitlich gestaffelt
   nacheinander auflösen statt alle gleichzeitig. */
.page-transition-overlay.pt-exit {
  animation: ptExitMain 0.5s steps(9) forwards;
}
.page-transition-overlay.pt-exit .pt-b1 {
  animation: ptExitB1 0.5s steps(9) forwards;
}
.page-transition-overlay.pt-exit .pt-b2 {
  animation: ptExitB2 0.5s steps(9) forwards;
  animation-delay: 0.04s;
}
.page-transition-overlay.pt-exit .pt-b3 {
  animation: ptExitB3 0.5s steps(9) forwards;
  animation-delay: 0.09s;
}
@keyframes ptExitMain {
  0%   { opacity: 0; transform: translate(0, 0); clip-path: inset(0 0 70% 0); }
  12%  { opacity: 0.7; transform: translate(calc(var(--chaos-amp) * -12px), calc(var(--chaos-amp) * 3px)); clip-path: inset(0 0 70% 0); }
  24%  { opacity: 0.3; transform: translate(calc(var(--chaos-amp) * 9px), 0); clip-path: inset(40% 0 10% 0); }
  38%  { opacity: 0.85; transform: translate(calc(var(--chaos-amp) * -7px), calc(var(--chaos-amp) * -4px)); clip-path: inset(0 0 45% 0); }
  52%  { opacity: 0.4; transform: translate(calc(var(--chaos-amp) * 11px), 0); clip-path: inset(20% 0 0 0); }
  68%  { opacity: 0.95; transform: translate(calc(var(--chaos-amp) * -5px), 0); clip-path: inset(0 0 0 0); }
  100% { opacity: 1; transform: translate(0, 0); clip-path: inset(0 0 0 0); }
}
@keyframes ptExitB1 {
  0%   { opacity: 0; transform: translateX(0); }
  20%  { opacity: 0.55; transform: translateX(calc(var(--chaos-amp) * 16px)); }
  45%  { opacity: 0.2; transform: translateX(calc(var(--chaos-amp) * -11px)); }
  65%  { opacity: 0.5; transform: translateX(calc(var(--chaos-amp) * 8px)); }
  100% { opacity: 0.4; transform: translateX(0); }
}
@keyframes ptExitB2 {
  0%   { opacity: 0; transform: translateX(0); }
  20%  { opacity: 0.55; transform: translateX(calc(var(--chaos-amp) * -16px)); }
  45%  { opacity: 0.2; transform: translateX(calc(var(--chaos-amp) * 11px)); }
  65%  { opacity: 0.5; transform: translateX(calc(var(--chaos-amp) * -8px)); }
  100% { opacity: 0.4; transform: translateX(0); }
}
@keyframes ptExitB3 {
  0%   { opacity: 0; transform: translate(0, 0); }
  25%  { opacity: 0.4; transform: translate(calc(var(--chaos-amp) * 10px), calc(var(--chaos-amp) * -6px)); }
  55%  { opacity: 0.15; transform: translate(calc(var(--chaos-amp) * -8px), calc(var(--chaos-amp) * 4px)); }
  100% { opacity: 0.3; transform: translate(0, 0); }
}

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  .glitch-stage *,
  .g-band {
    animation: none !important;
    transition: none !important;
  }
  .page-transition-overlay,
  .page-transition-overlay * {
    animation-duration: 0.001ms !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-weight: 300;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  display: block;
}

a {
  color: inherit;
}

p {
  margin: 0 0 1em;
  color: var(--fg-dim);
  max-width: 46ch;
}

h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 500;
  margin: 0;
  letter-spacing: -0.01em;
}

.accent-line {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  color: var(--fg);
}

.container {
  max-width: 1320px;
  margin: 0 auto;
  padding: 0 var(--edge);
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--fg);
  color: var(--bg);
  padding: 0.75em 1.25em;
  z-index: 1000;
}
.skip-link:focus {
  left: 1rem;
  top: 1rem;
}

a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ---------- Nav (alle Seiten) ---------- */
.site-nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--edge);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
  background: rgba(8, 9, 11, 0.72);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.site-nav .brand {
  text-decoration: none;
  font-weight: 500;
  font-size: 1.05rem;
}

.site-nav ul {
  list-style: none;
  display: flex;
  gap: 2rem;
  margin: 0;
  padding: 0;
}

.site-nav a {
  text-decoration: none;
}

.site-nav a:not(.brand) {
  border-bottom: 1px solid transparent;
  padding-bottom: 2px;
  color: var(--fg-dim);
  transition: color 0.2s ease, border-color 0.2s ease;
}
.site-nav a:not(.brand):hover,
.site-nav a.current {
  color: var(--fg);
  border-color: var(--accent);
}

.nav-toggle {
  display: none;
}

@media (max-width: 720px) {
  .site-nav ul {
    display: none;
  }
  .nav-toggle {
    display: block;
    background: none;
    border: none;
    color: var(--fg);
    font: inherit;
    cursor: pointer;
  }
  .site-nav.open ul {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%;
    right: var(--edge);
    background: var(--bg);
    color: var(--fg);
    padding: 1.25rem 1.5rem;
    gap: 1rem;
    border: 1px solid var(--line);
  }
}

main {
  padding-top: var(--nav-h);
}
.hero {
  margin-top: calc(var(--nav-h) * -1);
}

/* ===================================================================
   HOME-HERO — EXTREMER, KONTINUIERLICHER GLITCH
   -------------------------------------------------------------------
   Nutzt ausschließlich images/portrait-mirror.jpg. Statt zwischen
   mehreren Bildern zu wechseln, zerlegt sich EIN Bild ständig in
   Streifen/Blöcke (.g-band), die unabhängig voneinander springen,
   sich verfärben (Rot/Cyan-Versatz) und wieder einrasten — daher
   "kontinuierlich". Dazu in Abständen ein kurzer, harter Vollbild-
   Blitz (.mega-glitch, wird von script.js zufällig ausgelöst).
   =================================================================== */
.hero {
  position: relative;
  height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
}

.glitch-hero-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 45%, rgba(136, 120, 124, 0.35) 0%, var(--bg) 68%);
}

.glitch-hero-stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--bg);
}

/* Fullscreen (object-fit: cover), aber die Bild-Position wandert
   langsam auf und ab, damit dein Gesicht nie dauerhaft am oberen
   oder unteren Rand abgeschnitten steht. Der Bereich (22%–46%) ist
   bewusst so gewählt, dass das Gesicht in jeder Phase im Bild
   bleibt — Werte in heroBob/heroBobBg anpassen, falls nötig. */
.g-base {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  animation: baseHum 5s ease-in-out infinite, heroBob 17s ease-in-out infinite;
}
@keyframes baseHum {
  0%, 100% { transform: scale(1.001); }
  50%      { transform: scale(1.012) translate(0.4px, -0.3px); }
}
@keyframes heroBob {
  0%, 100% { object-position: 50% 34%; }
  25%      { object-position: 50% 22%; }
  50%      { object-position: 50% 34%; }
  75%      { object-position: 50% 46%; }
}

.g-band {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  background-image: var(--hero-img, url("images/start.jpg"));
  background-repeat: no-repeat;
  background-size: cover;
  animation: heroBobBg 17s ease-in-out infinite;
  will-change: transform, clip-path, opacity, background-position;
}
@keyframes heroBobBg {
  0%, 100% { background-position: 50% 34%; }
  25%      { background-position: 50% 22%; }
  50%      { background-position: 50% 34%; }
  75%      { background-position: 50% 46%; }
}

/* Vom Chaos-Slider gesteuerte Pausen: script.js setzt/entfernt diese
   Klasse in unregelmäßigen Abständen, damit der Glitch nicht 100%
   pausenlos läuft. */
.glitch-hero-stage.glitch-paused .g-band {
  animation-play-state: paused;
}

/* Strukturelle Streifen — verschieben sich, keine Farbverfremdung */
.g-band.b1 { animation: gb1 1.6s steps(7) infinite; }
.g-band.b2 { animation: gb2 2.3s steps(9) infinite; animation-delay: -0.6s; }
.g-band.b3 { animation: gb3 1.1s steps(5) infinite; animation-delay: -0.3s; }

/* Farbversatz-Streifen — Rot/Cyan, mix-blend-mode screen */
.g-band.c1 {
  mix-blend-mode: screen;
  filter: sepia(1) hue-rotate(-58deg) saturate(9) brightness(1.25);
  animation: gc1 1.4s steps(6) infinite;
}
.g-band.c2 {
  mix-blend-mode: screen;
  filter: hue-rotate(180deg) saturate(9) brightness(1.25);
  animation: gc2 1.9s steps(8) infinite;
  animation-delay: -0.9s;
}

/* Die Distanz-Werte nutzen calc(var(--chaos-amp)) — der Chaos-Slider
   multipliziert sie live, ohne dass die Keyframes selbst neu
   geschrieben werden müssen. --chaos-amp 1 = Standard/"medium". */
@keyframes gb1 {
  0%   { clip-path: inset(8% 0 84% 0);  transform: translateX(0); opacity: 0; }
  8%   { clip-path: inset(8% 0 84% 0);  transform: translateX(calc(var(--chaos-amp) * -28px)); opacity: 1; }
  16%  { clip-path: inset(8% 0 84% 0);  transform: translateX(calc(var(--chaos-amp) * 16px)); opacity: 1; }
  24%  { opacity: 0; }
  55%  { clip-path: inset(46% 0 30% 0); transform: translateX(0); opacity: 0; }
  63%  { clip-path: inset(46% 0 30% 0); transform: translateX(calc(var(--chaos-amp) * 22px)); opacity: 1; }
  70%  { clip-path: inset(46% 0 30% 0); transform: translateX(calc(var(--chaos-amp) * -19px)); opacity: 1; }
  78%  { opacity: 0; }
  100% { clip-path: inset(8% 0 84% 0); opacity: 0; }
}
@keyframes gb2 {
  0%   { clip-path: inset(62% 0 12% 0); transform: translateX(0); opacity: 0; }
  12%  { opacity: 0; }
  18%  { clip-path: inset(62% 0 12% 0); transform: translateX(calc(var(--chaos-amp) * 32px)); opacity: 1; }
  27%  { clip-path: inset(62% 0 12% 0); transform: translateX(calc(var(--chaos-amp) * -22px)); opacity: 1; }
  34%  { opacity: 0; }
  60%  { clip-path: inset(20% 0 60% 0); opacity: 0; }
  67%  { clip-path: inset(20% 0 60% 0); transform: translateX(calc(var(--chaos-amp) * -30px)); opacity: 1; }
  75%  { clip-path: inset(20% 0 60% 0); transform: translateX(calc(var(--chaos-amp) * 13px)); opacity: 1; }
  83%  { opacity: 0; }
  100% { opacity: 0; }
}
@keyframes gb3 {
  0%, 100% { opacity: 0; }
  10% { clip-path: inset(30% 55% 40% 8%); transform: translate(0,0); opacity: 0; }
  16% { clip-path: inset(30% 55% 40% 8%); transform: translate(calc(var(--chaos-amp) * 14px), calc(var(--chaos-amp) * -6px)); opacity: 1; }
  24% { opacity: 0; }
  58% { clip-path: inset(70% 10% 5% 60%); opacity: 0; }
  64% { clip-path: inset(70% 10% 5% 60%); transform: translate(calc(var(--chaos-amp) * -10px), calc(var(--chaos-amp) * 4px)); opacity: 1; }
  71% { opacity: 0; }
}
@keyframes gc1 {
  0%, 100% { opacity: 0; transform: translateX(0); }
  10% { clip-path: inset(15% 0 70% 0); opacity: 0; }
  15% { clip-path: inset(15% 0 70% 0); opacity: 0.75; transform: translateX(calc(var(--chaos-amp) * 19px)); }
  22% { opacity: 0; }
  50% { clip-path: inset(50% 0 20% 0); opacity: 0; }
  56% { clip-path: inset(50% 0 20% 0); opacity: 0.7; transform: translateX(calc(var(--chaos-amp) * -16px)); }
  63% { opacity: 0; }
}
@keyframes gc2 {
  0%, 100% { opacity: 0; transform: translateX(0); }
  20% { clip-path: inset(38% 0 40% 0); opacity: 0; }
  26% { clip-path: inset(38% 0 40% 0); opacity: 0.7; transform: translateX(calc(var(--chaos-amp) * -18px)); }
  33% { opacity: 0; }
  70% { clip-path: inset(4% 0 88% 0); opacity: 0; }
  76% { clip-path: inset(4% 0 88% 0); opacity: 0.75; transform: translateX(calc(var(--chaos-amp) * 15px)); }
  83% { opacity: 0; }
}

/* Vollbild-Blitz — wird von script.js in unregelmäßigen Abständen
   kurz auf .glitch-hero-stage gesetzt (Klasse "mega"). */
.glitch-hero-stage.mega .g-base {
  animation: megaBase 0.3s steps(3) 1;
}
.glitch-hero-stage.mega .g-band {
  animation-duration: 0.3s !important;
}
@keyframes megaBase {
  0%   { transform: translate(0,0); filter: none; }
  33%  { transform: translate(calc(var(--chaos-amp) * -12px), calc(var(--chaos-amp) * 6px)); filter: invert(1) hue-rotate(180deg); }
  66%  { transform: translate(calc(var(--chaos-amp) * 9px), calc(var(--chaos-amp) * -4px)); filter: hue-rotate(90deg) saturate(4); }
  100% { transform: translate(0,0); filter: none; }
}

.glitch-scanlines {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.25) 0px,
    rgba(0, 0, 0, 0.25) 1px,
    transparent 1px,
    transparent 3px
  );
  opacity: 0.4;
  mix-blend-mode: overlay;
}

.glitch-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(8, 9, 11, 0.05) 0%,
    rgba(8, 9, 11, 0.45) 60%,
    rgba(8, 9, 11, 0.9) 100%
  );
}

.hero-content {
  position: relative;
  z-index: 2;
  padding: var(--edge);
  padding-bottom: clamp(2rem, 7vh, 4rem);
}

.hero-content h1 {
  font-size: clamp(2.8rem, 9vw, 6.4rem);
  animation: textGlitch 6s linear 1.4s infinite;
}
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(0.5em); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes textGlitch {
  0%, 93%, 100% { text-shadow: none; transform: translate(0, 0); }
  93.6% { text-shadow: 3px 0 var(--accent), -3px 0 var(--accent-2); transform: translate(2px, 0); }
  94.6% { text-shadow: -3px 0 var(--accent), 3px 0 var(--accent-2); transform: translate(-2px, 0); }
  95.6% { text-shadow: 2px 0 var(--accent), -2px 0 var(--accent-2); transform: translate(1px, 0); }
  96.6% { text-shadow: none; transform: translate(0, 0); }
}

.hero-content .tagline {
  margin-top: 0.9rem;
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: clamp(1rem, 2vw, 1.25rem);
  color: var(--fg-dim);
  max-width: 36ch;
  opacity: 0;
  animation: fadeUp 1.1s ease-out 0.5s forwards;
}
.hero-content .tagline strong {
  color: var(--fg);
  font-weight: 500;
}

.hero-socials {
  display: flex;
  gap: 1.5rem;
  margin-top: 1.5rem;
  opacity: 0;
  animation: fadeUp 1.1s ease-out 0.7s forwards;
}
.hero-socials a {
  font-size: 0.85rem;
  text-decoration: none;
  color: var(--fg-dim);
  border-bottom: 1px solid var(--line);
  padding-bottom: 2px;
}
.hero-socials a:hover {
  color: var(--fg);
  border-color: var(--accent);
}

.hero-copyright {
  margin-top: 1.75rem;
  font-size: 0.72rem;
  color: var(--fg-dim);
  opacity: 0;
  animation: fadeUp 1.1s ease-out 0.85s forwards;
}

/* ===================================================================
   CHAOS-WIDGET — Regler + drei Icon-Buttons, separat neben dem Namen
   in der Navigation (auf jeder Seite identisch). Der Regler steuert
   visuelles Chaos (--chaos-amp: Bild-/Buchstaben-Glitch, Chromatic-
   Split, Artefakte). Der Wert bleibt stehen und wird in localStorage
   gespeichert — gilt seitenübergreifend. Sound läuft nur, wenn der
   Lautsprecher-Button aktiv ist (siehe script.js).
   =================================================================== */
.nav-left {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

/* Frei fliegende Artefakte bei hohem Chaos-Level — werden von
   script.js dynamisch erzeugt und wieder entfernt. */
.chaos-artifact {
  position: fixed;
  z-index: 40;
  pointer-events: none;
  mix-blend-mode: screen;
}

.chaos-widget {
  display: flex;
  align-items: center;
  gap: 0;
}
/* Reihenfolge im Markup ist bereits die AUFGEKLAPPTE Reihenfolge:
   Slider, Boost, Explosion, Lautsprecher. Im eingeklappten Zustand
   sind Slider/Boost/Explosion auf Breite 0 zusammengefaltet — dadurch
   rutscht der Lautsprecher-Button automatisch direkt neben den Namen.
   Beim Aufklappen wachsen sie nach rechts heraus, der Lautsprecher
   "wandert" dabei ganz natürlich an die rechte Position, ohne dass
   die Positionen einzeln animiert werden müssen. */
.chaos-widget-slider,
#boostBtn,
#explodeBtn {
  overflow: hidden;
  max-width: 0;
  opacity: 0;
  margin-left: 0;
  pointer-events: none;
  transition: max-width 0.45s cubic-bezier(0.5, 0, 0.15, 1), opacity 0.3s ease, margin-left 0.45s cubic-bezier(0.5, 0, 0.15, 1);
}
.chaos-widget-slider {
  height: 34px;
  padding-top: 2px;
}
.chaos-widget.expanded .chaos-widget-slider {
  max-width: 140px;
  opacity: 1;
  margin-left: 0.7rem;
  pointer-events: auto;
}
.chaos-widget.expanded #boostBtn,
.chaos-widget.expanded #explodeBtn {
  max-width: 34px;
  opacity: 1;
  margin-left: 0.6rem;
  pointer-events: auto;
}
#soundToggle {
  flex-shrink: 0;
  margin-left: 0.3rem;
}
/* "SPICE"-Hinweis links vom Lautsprecher — nur sichtbar, wenn ALLES
   eingeklappt ist (also genau umgekehrt zu Slider/Boost/Explosion).
   Klappt sich weg, sobald der Lautsprecher aktiviert wird. */
.spice-hint {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  overflow: hidden;
  max-width: 90px;
  opacity: 1;
  margin-left: 0;
  color: var(--accent-2);
  font-family: var(--font-sans);
  font-style: italic;
  font-weight: 600;
  letter-spacing: 0.02em;
  font-size: 0.85rem;
  white-space: nowrap;
  pointer-events: none;
  transition: max-width 0.4s cubic-bezier(0.5, 0, 0.15, 1), opacity 0.25s ease, margin-left 0.4s cubic-bezier(0.5, 0, 0.15, 1);
}
.spice-hint svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}
.chaos-widget.expanded .spice-hint {
  max-width: 0;
  opacity: 0;
  margin-left: 0;
}
.chaos-widget-slider {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.chaos-widget-slider label {
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent-2);
  white-space: nowrap;
}
.chaos-widget-slider input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 110px;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-2) 100%);
  cursor: pointer;
}
.chaos-widget-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--fg);
  border: 2px solid var(--accent-2);
  box-shadow: 0 0 8px 1px rgba(255, 38, 38, 0.6);
  cursor: pointer;
}
.chaos-widget-slider input[type="range"]::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--fg);
  border: 2px solid var(--accent-2);
  box-shadow: 0 0 8px 1px rgba(255, 38, 38, 0.6);
  cursor: pointer;
}
@media (max-width: 720px) {
  .chaos-widget-slider input[type="range"] { width: 72px; }
  .chaos-widget.expanded .chaos-widget-slider { max-width: 100px; }
}

.chaos-btn {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 1.5px solid var(--line);
  background: rgba(242, 238, 228, 0.04);
  color: var(--fg-dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  flex-shrink: 0;
  transition: border-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}
.chaos-btn:hover,
.chaos-btn.active {
  border-color: var(--accent);
  color: var(--accent);
  box-shadow: 0 0 10px 1px rgba(47, 224, 232, 0.35);
}
.chaos-btn svg {
  width: 15px;
  height: 15px;
}
#soundToggle.active {
  border-color: var(--accent-2);
  color: var(--accent-2);
  box-shadow: 0 0 10px 1px rgba(255, 38, 38, 0.4);
}
#soundToggle .icon-off { display: block; }
#soundToggle .icon-on { display: none; }
#soundToggle.active .icon-off { display: none; }
#soundToggle.active .icon-on { display: block; }

/* Glüh-Overlay im Hero, wird beim Ziehen des Sliders stärker
   (Opacity wird von script.js live gesetzt; nur auf der Startseite
   vorhanden). */
.hero-glow {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(circle at 50% 45%, rgba(255, 130, 90, 0.6) 0%, rgba(255, 38, 38, 0.3) 38%, transparent 72%);
  mix-blend-mode: screen;
  opacity: 0;
}

/* ===================================================================
   "VOLLE KONTROLLE"-MELDUNG — erscheint ab ~96% Chaos, auf jeder
   Seite. Bewusst ohne Hintergrund, damit die Artefakte weiter
   durchscheinen — der Bildschirm soll wirklich voller Chaos wirken,
   die Meldung schwebt nur flackernd darüber.
   =================================================================== */
#fullControlMsg {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  text-align: center;
  pointer-events: none;
  padding: 2rem;
}
#fullControlMsg .fc-line1 {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 5vw, 3.2rem);
  color: var(--fg);
  text-shadow: 0 0 18px rgba(0, 0, 0, 0.8);
  animation: fcFlicker1 1.6s steps(2) infinite;
}
/* Derselbe hektische Tanz-Effekt wie zuvor bei "ERROR 404" — jetzt
   direkt auf der Nachricht selbst statt einem separaten Text. */
#fullControlMsg .fc-line1.fc-dance {
  animation: fc404Glitch 0.25s steps(2) infinite;
}
#fullControlMsg .fc-line2 {
  font-family: var(--font-hand);
  font-size: clamp(1rem, 2.4vw, 1.4rem);
  color: var(--accent-2);
  text-shadow: 0 0 14px rgba(0, 0, 0, 0.8);
  animation: fcFlicker2 2.1s steps(3) infinite;
}
@keyframes fcFlicker1 {
  0%, 92%, 100% { opacity: 1; text-shadow: 0 0 18px rgba(0,0,0,0.8); }
  94% { opacity: 0.4; text-shadow: 2px 0 var(--accent), -2px 0 var(--accent-2); }
  96% { opacity: 1; }
}
@keyframes fcFlicker2 {
  0%, 88%, 100% { opacity: 0.9; }
  90% { opacity: 0.2; }
  93% { opacity: 0.9; }
}
@keyframes fc404Glitch {
  0%   { text-shadow: 1px 1px rgba(246,0,153,0.8), -1px -1px rgba(15,210,255,0.8), -1px 0 rgba(255,210,0,1); transform: translate(0,0); }
  25%  { text-shadow: -3px 1px rgba(246,0,153,0.8), 3px -1px rgba(15,210,255,0.8), 1px 0 rgba(255,210,0,1); transform: translate(-2px, 1px); }
  50%  { text-shadow: 3px -2px rgba(246,0,153,0.8), -3px 2px rgba(15,210,255,0.8), -1px 0 rgba(255,210,0,1); transform: translate(2px, -1px); }
  75%  { text-shadow: -1px 2px rgba(246,0,153,0.8), 1px -2px rgba(15,210,255,0.8), 2px 0 rgba(255,210,0,1); transform: translate(1px, 1px); }
  100% { text-shadow: 1px 1px rgba(246,0,153,0.8), -1px -1px rgba(15,210,255,0.8), -1px 0 rgba(255,210,0,1); transform: translate(0,0); }
}

/* ===================================================================
   VOLLBILD-SEITEN (Calendar, Contact) — dasselbe Hero-Bild mit
   demselben Glitch-Effekt (Streifen, Bob-Bewegung, RGB-Split), aber
   fixiert über den GANZEN Bildschirm statt nur einer Spalte. Der
   Text bleibt auf einer Seite (rechts) begrenzt, mit einem
   zusätzlichen seitlichen Verlauf für Lesbarkeit.
   .full-bg-stage ist eine Zusatzklasse zu .glitch-hero-stage — sie
   ändert nur position:absolute zu position:fixed, alle Glitch-
   Keyframes (gb1/gb2/gb3/gc1/gc2/heroBob/mega) werden 1:1
   wiederverwendet.
   =================================================================== */
.full-bg-page {
  position: relative;
  min-height: 100vh;
}
.full-bg-stage.glitch-hero-stage,
.full-bg-stage.chroma-stage {
  position: fixed;
  z-index: 0;
}
/* Spiegelt NUR das Bild horizontal (für Seiten, bei denen der
   scharfe Teil eines "halb scharf, halb künstlich verlängert"-
   Bildes auf der anderen Seite liegen soll, z. B. Media: Text
   links, scharfes Bild soll rechts liegen). Die Verlaufs-/
   Scanline-Ebenen bekommen eine Gegen-Spiegelung, damit ihre
   eigene Ausrichtung (welche Seite dunkler ist) normal bleibt.
*/
.full-bg-stage.flip-h {
  transform: scaleX(-1);
}
.full-bg-stage.flip-h .glitch-scrim,
.full-bg-stage.flip-h .full-bg-side-scrim,
.full-bg-stage.flip-h .glitch-scanlines {
  transform: scaleX(-1);
}
.full-bg-side-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    rgba(8, 9, 11, 0.1) 0%,
    rgba(8, 9, 11, 0.55) 45%,
    rgba(8, 9, 11, 0.92) 100%
  );
}
.full-bg-content {
  position: relative;
  z-index: 1;
  max-width: 640px;
  margin-left: auto;
  padding: clamp(6rem, 14vh, 8rem) var(--edge) 5rem;
}
/* Linksbündige Variante (Media, Projects) — Text/Verlauf gespiegelt. */
.full-bg-content.align-left {
  margin-left: 0;
  margin-right: auto;
}
.full-bg-side-scrim.align-left {
  background: linear-gradient(
    270deg,
    rgba(8, 9, 11, 0.1) 0%,
    rgba(8, 9, 11, 0.55) 45%,
    rgba(8, 9, 11, 0.92) 100%
  );
}
@media (max-width: 800px) {
  .full-bg-content,
  .full-bg-content.align-left {
    max-width: none;
    margin-left: 0;
    margin-right: 0;
  }
  .full-bg-side-scrim,
  .full-bg-side-scrim.align-left {
    background: linear-gradient(
      180deg,
      rgba(8, 9, 11, 0.15) 0%,
      rgba(8, 9, 11, 0.75) 35%,
      rgba(8, 9, 11, 0.95) 100%
    );
  }
}

/* ===================================================================
   IMPLOSION — Explosions-Button zieht das aktuelle Hintergrund-Bild
   kurz wie ein schwarzes Loch in sich zusammen und glitcht dann
   zurück. script.js setzt/entfernt die Klasse "imploding" auf dem
   jeweiligen ".js-implode-target" der aktuellen Seite.
   =================================================================== */
@keyframes stageImplode {
  0%   { transform: scale(1) rotate(0deg); filter: none; }
  34%  { transform: scale(0.035) rotate(12deg); filter: brightness(0.15) saturate(3); }
  42%  { transform: scale(0.03) rotate(-6deg); filter: invert(1) hue-rotate(180deg) brightness(2); }
  56%  { transform: scale(0.03) rotate(-10deg); filter: invert(1) hue-rotate(200deg) brightness(2.2); }
  76%  { transform: scale(1.18) rotate(3deg); filter: hue-rotate(70deg) saturate(2.2); }
  100% { transform: scale(1) rotate(0deg); filter: none; }
}
.js-implode-target.imploding {
  animation: stageImplode 1.1s cubic-bezier(0.6, 0, 0.35, 1) 1;
}

/* Der Text verschwindet zeitgleich kurz — löst sich in grobe
   "Pixel" auf (simuliert über eine gestufte Unschärfe + Kontrast-
   Sprünge, da echtes Pixel-Rendering CSS nicht möglich ist) und
   kommt dann wieder zurück, synchron zur Bild-Implosion. */
@keyframes textImplode {
  0%   { opacity: 1; filter: none; transform: scale(1); }
  30%  { opacity: 0.5; filter: blur(1px) contrast(2.4) saturate(0); transform: scale(0.98); }
  42%  { opacity: 0.05; filter: blur(6px) contrast(4) saturate(0); transform: scale(0.92); }
  50%  { opacity: 0; filter: blur(9px); transform: scale(0.88); }
  58%  { opacity: 0; filter: blur(9px); transform: scale(0.88); }
  66%  { opacity: 0.05; filter: blur(6px) contrast(4) saturate(0); transform: scale(0.92); }
  80%  { opacity: 0.6; filter: blur(2px) contrast(1.8); transform: scale(1.03); }
  100% { opacity: 1; filter: none; transform: scale(1); }
}
.js-text-implode-target.imploding {
  animation: textImplode 1.1s cubic-bezier(0.6, 0, 0.35, 1) 1;
}

/* Comic-Stern-Lichtblitz beim Explosions-Button — vier lange,
   schmale Zacken, kurz und hell aufblitzend genau im Moment, in dem
   Bild/Text/Artefakte am stärksten zusammengezogen sind. */
.explosion-star {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 140px;
  height: 140px;
  margin: -70px 0 0 -70px;
  pointer-events: none;
  z-index: 2500;
  opacity: 0;
  transform: scale(0) rotate(0deg);
  filter: drop-shadow(0 0 24px #fff) drop-shadow(0 0 50px var(--accent));
}
.explosion-star svg { width: 100%; height: 100%; }
.explosion-star.flash {
  animation: starFlash 1.1s cubic-bezier(0.6, 0, 0.35, 1) 1;
}
@keyframes starFlash {
  0%   { opacity: 0; transform: scale(0) rotate(0deg); }
  38%  { opacity: 0; transform: scale(0) rotate(0deg); }
  46%  { opacity: 1; transform: scale(1.5) rotate(12deg); }
  55%  { opacity: 1; transform: scale(2.4) rotate(22deg); }
  70%  { opacity: 0; transform: scale(3.2) rotate(30deg); }
  100% { opacity: 0; transform: scale(0) rotate(30deg); }
}

/* ===================================================================
   UNTERSEITEN — Bild auf einer Seite, Inhalt auf der anderen
   Hintergrund führt die Bildfarbe (--image-edge) als Verlauf fort.
   =================================================================== */
.split-page {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 42vw 1fr;
}
.split-page.image-right {
  grid-template-columns: 1fr 42vw;
}
.split-page.image-right .split-media { order: 2; }
.split-page.image-right .split-content { order: 1; }

.split-media {
  position: relative;
  height: 100%;
}
.split-media .media-sticky {
  position: sticky;
  top: var(--nav-h);
  height: calc(100vh - var(--nav-h));
  overflow: hidden;
}
.split-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 25%;
  filter: saturate(1.05) contrast(1.03);
}

/* ---------- Chromatic-Split-Glitch auf dem Unterseiten-Bild ----------
   Drei übereinanderliegende Kopien desselben Bildes (Basis + rot- /
   cyanverschobene Kopie) spalten sich in einem langsamen, dauerhaften
   Zyklus leicht auseinander und setzen sich wieder zusammen. Die
   Weite nutzt --chaos-amp — reagiert also live auf den Chaos-Slider,
   genau wie der Hero-Glitch und das Buchstaben-Chaos. */
.chroma-stage {
  position: absolute;
  inset: 0;
}
.chroma-layer {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 25%;
}
.chroma-layer.base {
  filter: saturate(1.05) contrast(1.03);
  animation: chromaBase 6.5s ease-in-out infinite;
}
.chroma-layer.r {
  mix-blend-mode: screen;
  filter: sepia(1) hue-rotate(-58deg) saturate(8) brightness(1.2);
  opacity: 0;
  animation: chromaR 6.5s ease-in-out infinite;
}
.chroma-layer.b {
  mix-blend-mode: screen;
  filter: hue-rotate(180deg) saturate(8) brightness(1.2);
  opacity: 0;
  animation: chromaB 6.5s ease-in-out infinite;
}
@keyframes chromaBase {
  0%, 34%, 68%, 100% { transform: scale(1); filter: saturate(1.05) contrast(1.03); }
  48% { transform: scale(calc(1 + var(--chaos-amp) * 0.012)); filter: saturate(1.2) contrast(1.08); }
}
@keyframes chromaR {
  0%, 32%, 70%, 100% { opacity: 0; transform: translateX(0); }
  44% { opacity: calc(var(--chaos-amp) * 0.32); transform: translateX(calc(var(--chaos-amp) * 15px)); }
  56% { opacity: calc(var(--chaos-amp) * 0.24); transform: translateX(calc(var(--chaos-amp) * -9px)); }
}
@keyframes chromaB {
  0%, 32%, 70%, 100% { opacity: 0; transform: translateX(0); }
  44% { opacity: calc(var(--chaos-amp) * 0.32); transform: translateX(calc(var(--chaos-amp) * -15px)); }
  56% { opacity: calc(var(--chaos-amp) * 0.24); transform: translateX(calc(var(--chaos-amp) * 9px)); }
}
.media-sticky.glitching .chroma-layer.r,
.media-sticky.glitching .chroma-layer.b {
  animation-duration: 1.1s;
}

.split-content {
  position: relative;
  z-index: 0;
  background: var(--bg);
  padding: clamp(6rem, 14vh, 8rem) var(--edge) 5rem;
}
/* Verwischter Farb-"Wulst", der das Bild optisch fortsetzt, statt
   eines einfachen Verlaufs. Bild austauschen: siehe --blur-bg unten
   und LIESMICH.md.
   Technik: position:sticky + height:100vh + margin-bottom:-100vh
   hält den Hintergrund exakt auf Bildschirmgröße fixiert, auch wenn
   der Text darunter viel länger ist und gescrollt wird. */
.split-content::before {
  content: "";
  display: block;
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  height: 100vh;
  margin-bottom: -100vh;
  z-index: -1;
  background-image:
    linear-gradient(90deg, rgba(8, 9, 11, 0.05) 0%, var(--bg) 58%),
    var(--blur-bg, url("images/portrait-double-blur.jpg"));
  background-size: 100% 100%, cover;
  background-position: 0 0, left center;
  background-repeat: no-repeat, no-repeat;
  filter: blur(6px) saturate(1.1);
  opacity: 0.85;
}
.split-page.image-right .split-content::before {
  background-image:
    linear-gradient(270deg, rgba(8, 9, 11, 0.05) 0%, var(--bg) 58%),
    var(--blur-bg, url("images/portrait-double-blur.jpg"));
  background-position: 0 0, right center;
}

.page-eyebrow {
  display: block;
  font-size: 0.8rem;
  color: var(--accent);
  margin-bottom: 1.25rem;
  letter-spacing: 0.02em;
}

.page-title {
  font-size: clamp(2.2rem, 5vw, 3.4rem);
  margin-bottom: 2rem;
  max-width: 16ch;
}
/* Typewriter-Aufbau beim Ankommen: blinkender Cursor während des
   Tippens, kurzer Regenbogen-Textschatten-Blitz beim Fertigwerden.
   Gilt generisch für Titel UND Fließtext-Absätze (.tw-active/.tw-done
   werden von script.js auf beide gesetzt) — der Titel bekommt einen
   kräftigeren Ausschlag, Fließtext einen dezenteren. */
.tw-active::after {
  content: '';
  display: inline-block;
  width: 0.06em;
  height: 0.9em;
  margin-left: 0.08em;
  background: var(--accent);
  vertical-align: -0.05em;
  animation: twCursorBlink 0.8s steps(1) infinite;
}
@keyframes twCursorBlink {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: 0; }
}
.tw-done {
  animation: twRainbowFlashSmall 1s ease-out 1;
}
.page-title.tw-done {
  animation: twRainbowFlash 1.3s ease-out 1;
}
@keyframes twRainbowFlashSmall {
  0% {
    text-shadow: 1px 1px rgba(246,0,153,0.7), -1px -1px rgba(15,210,255,0.7), -1px 0 rgba(255,210,0,0.9);
  }
  20% {
    text-shadow: 3px 1px rgba(246,0,153,0.6), -4px -1px rgba(15,210,255,0.6), -1px 0 rgba(255,210,0,0.7);
  }
  50% {
    text-shadow: 1px -1px rgba(246,0,153,0.4), -1px 1px rgba(15,210,255,0.4), 1px 0 rgba(255,210,0,0.5);
  }
  100% {
    text-shadow: none;
  }
}
@keyframes twRainbowFlash {
  0% {
    text-shadow: 1px 1px rgba(246,0,153,0.8), -1px -1px rgba(15,210,255,0.8), -1px 0 rgba(255,210,0,1);
  }
  15% {
    text-shadow: 14px 6px rgba(246,0,153,0.8), -18px -3px rgba(15,210,255,0.8), -2px -2px rgba(255,210,0,1);
  }
  30% {
    text-shadow: -10px 4px rgba(246,0,153,0.7), 12px -5px rgba(15,210,255,0.7), 2px 2px rgba(255,210,0,0.9);
  }
  55% {
    text-shadow: 4px -2px rgba(246,0,153,0.5), -4px 2px rgba(15,210,255,0.5), 1px 0 rgba(255,210,0,0.7);
  }
  100% {
    text-shadow: none;
  }
}

.split-content .lede {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(1.2rem, 2.4vw, 1.6rem);
  color: var(--fg);
  max-width: 30ch;
  margin-bottom: 2rem;
}

@media (max-width: 900px) {
  .split-page,
  .split-page.image-right {
    grid-template-columns: 1fr;
  }
  .split-page.image-right .split-media,
  .split-page.image-right .split-content {
    order: initial;
  }
  .split-media .media-sticky {
    position: relative;
    height: 60vh;
    top: 0;
  }
  .split-content {
    padding-top: 3rem;
  }
}

/* ---------- Glitch-Buchstaben in Fließtext ---------- */
.gw {
  display: inline-block;
  position: relative;
}

/* ---------- Vita (About) ---------- */
.vita-block {
  margin-bottom: 2.25rem;
}
.vita-block h3 {
  font-size: 0.95rem;
  color: var(--fg-dim);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 0.75rem;
  font-weight: 500;
}
.vita-list {
  list-style: none;
  margin: 0;
  padding: 0;
  color: var(--fg-dim);
  font-size: 0.95rem;
  line-height: 1.75;
}

/* ---------- Projects ---------- */
.project-list {
  list-style: none;
  margin: 0 0 3rem;
  padding: 0;
}
.project-list li {
  border-top: 1px solid var(--line);
  padding: 1.5rem 0;
}
.project-list li:last-child { border-bottom: 1px solid var(--line); }

/* Projekte mit Video: Text links, Video rechts auf Höhe des
   Bandnamens (statt darunter). */
.project-list li.has-video {
  display: flex;
  align-items: flex-start;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.project-list li.has-video .project-text {
  flex: 1 1 220px;
  min-width: 0;
}
.project-list li.has-video .project-video {
  flex: 0 0 auto;
  width: 240px;
  max-width: 100%;
}
.project-list li.has-video .video-embed {
  max-width: none;
  margin-top: 0;
}
/* Instagram-Embeds (ZEVRA, ENGELTHOMSEN) — Instagrams eigenes Skript
   bestimmt die genaue Höhe, wir sorgen nur für die passende Breite. */
.project-list li.has-video .instagram-media {
  width: 100% !important;
  max-width: 300px !important;
}
.project-list h3 {
  font-size: clamp(1.2rem, 2.2vw, 1.5rem);
  margin-bottom: 0.35rem;
}
.project-list .role {
  display: block;
  font-size: 0.82rem;
  color: var(--fg-dim);
  margin-bottom: 0.5rem;
}
.project-list a.ext {
  color: var(--accent);
  text-decoration: none;
  font-size: 0.8rem;
  border-bottom: 1px solid currentColor;
  margin-right: 1rem;
}
.lineup-line {
  color: var(--fg-dim);
  font-size: 0.9rem;
  line-height: 1.6;
  margin: 0 0 1rem;
  max-width: none;
}
.embed-row {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

/* Platz für Video/Bandcamp pro Projekt. Bandcamp läuft im schmalen
   "slim"-Embed-Design (42px hoch, size=small) — einfach ein
   <iframe> in .project-embed packen (Beispiele siehe HTML). Noch
   kein Embed: die gestrichelte .project-embed-placeholder-Box zeigt,
   wo später eins hinkommt. Alle klickbaren Embeds sind bis zum
   Hover dezent ausgegraut — beim Drüberfahren werden sie farbig. */
.project-embed {
  margin-top: 0.5rem;
  max-width: 380px;
  background: var(--fg);
  border-radius: 8px;
  border: 1.5px solid var(--line);
  overflow: hidden;
  filter: grayscale(1) brightness(0.85);
  opacity: 0.75;
  transition: filter 0.35s ease, opacity 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}
.project-embed:hover {
  filter: grayscale(0) brightness(1);
  opacity: 1;
  border-color: var(--accent);
  box-shadow: 0 0 18px rgba(47, 224, 232, 0.28);
}
.project-embed iframe {
  width: 100%;
  height: 42px;
  border: none;
  display: block;
}
.project-embed-placeholder {
  margin-top: 0.5rem;
  max-width: 380px;
  height: 42px;
  border: 1.5px dashed var(--line);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.7rem;
  color: var(--fg-dim);
  text-align: center;
  padding: 0.5rem;
}

.curation-block {
  border-top: 1px solid var(--line);
  padding-top: 2.5rem;
}
.curation-block .badge-row {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 1.25rem;
}
.curation-block .badge-row > span {
  font-size: 0.75rem;
  color: var(--fg-dim);
  border: 1px solid var(--line);
  padding: 0.3em 0.75em;
  border-radius: 999px;
}
.curation-block .badge-row > span .gw {
  border: none;
  padding: 0;
}
.curation-block .links {
  margin-top: 1.5rem;
  display: flex;
  gap: 1.5rem;
  flex-wrap: wrap;
}
.curation-block .links a {
  font-size: 0.85rem;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
}

/* ---------- Press / Media ---------- */
.press-quote {
  max-width: 44ch;
  margin-bottom: 2rem;
}
.press-quote p.accent-line {
  font-size: 1.15rem;
}
.press-quote cite {
  display: block;
  font-style: normal;
  font-size: 0.8rem;
  color: var(--fg-dim);
  margin-top: 0.5rem;
}

/* ---------- EPK-Seiten (Electronic Press Kit) ---------- */
.epk-label {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-2);
  margin: 2.5rem 0 0.75rem;
}
.epk-lineup {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 0;
}
.epk-lineup li {
  padding: 0.3rem 0;
  border-bottom: 1px solid var(--line);
}
.epk-lineup li:first-child { border-top: 1px solid var(--line); }
.epk-samply-note {
  font-size: 0.8rem;
  color: var(--fg-dim);
  font-style: italic;
  border: 1px dashed var(--line);
  border-radius: 8px;
  padding: 1rem;
}

.media-block {
  margin-top: 3rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--line);
}
.discography-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 1.5rem;
}
.bandcamp-embed {
  background: var(--fg);
  border-radius: 8px;
  border: 1.5px solid var(--line);
  overflow: hidden;
  max-width: 380px;
  filter: grayscale(1) brightness(0.85);
  opacity: 0.75;
  transition: filter 0.35s ease, opacity 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}
.bandcamp-embed:hover {
  filter: grayscale(0) brightness(1);
  opacity: 1;
  border-color: var(--accent);
  box-shadow: 0 0 18px rgba(47, 224, 232, 0.28);
}
.bandcamp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 350px));
  gap: 1.5rem;
}
.bandcamp-grid .bandcamp-embed {
  max-width: none;
  width: 100%;
}
.media-block iframe { width: 100%; height: 42px; border: none; }
.media-secondary { display: flex; flex-direction: column; gap: 1.25rem; margin-top: 1.5rem; }

/* ---------- Video-Galerie (Media-Seite & Projekte) ---------- */
.video-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 1.25rem;
}
.video-embed {
  max-width: 300px;
  position: relative;
  width: 100%;
  padding-top: 56.25%; /* 16:9 */
  background: #000;
  border-radius: 10px;
  border: 1.5px solid var(--line);
  overflow: hidden;
  filter: grayscale(1) brightness(0.85);
  opacity: 0.75;
  transition: filter 0.35s ease, opacity 0.35s ease, border-color 0.35s ease, box-shadow 0.35s ease;
}
.video-embed:hover {
  filter: grayscale(0) brightness(1);
  opacity: 1;
  border-color: var(--accent);
  box-shadow: 0 0 18px rgba(47, 224, 232, 0.28);
}
.video-embed iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
}
/* Periodischer RGB-Split-Glitch über dem Video, wie ein kurzer
   Empfangsfehler — script.js vergibt jedem Video eine zufällige
   Verzögerung (--vg-delay), damit nicht alle synchron glitchen. */
.video-embed::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    rgba(255, 38, 38, 0.3) 0%,
    transparent 25%,
    transparent 75%,
    rgba(47, 224, 232, 0.3) 100%
  );
  mix-blend-mode: screen;
  opacity: 0;
  animation: videoGlitchFlicker 6.5s steps(1) infinite;
  animation-delay: var(--vg-delay, 0s);
}
@keyframes videoGlitchFlicker {
  0%, 91%, 100% { opacity: 0; transform: translateX(0); clip-path: inset(0 0 0 0); }
  92% { opacity: 0.85; transform: translateX(-4px); clip-path: inset(15% 0 60% 0); }
  93% { opacity: 0.5; transform: translateX(3px); clip-path: inset(55% 0 10% 0); }
  94.5% { opacity: 0.9; transform: translateX(-3px); clip-path: inset(5% 0 75% 0); }
  96% { opacity: 0; transform: translateX(0); clip-path: inset(0 0 0 0); }
}

/* ---------- Calendar ---------- */
.cal-group-title {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--fg-dim);
  margin: 2.5rem 0 1rem;
}
.cal-group-title:first-child { margin-top: 0; }
.cal-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.92rem;
}
.cal-list li {
  display: grid;
  grid-template-columns: 7.5em 1fr;
  gap: 0.5rem 1.25rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--line);
}
.cal-date {
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.cal-details .venue { color: var(--fg); }
.cal-details .place,
.cal-details .who {
  color: var(--fg-dim);
  font-size: 0.85rem;
}
.cal-list.past .cal-date { color: var(--fg-dim); opacity: 0.7; }
.cal-list.past .cal-details .venue { color: var(--fg-dim); opacity: 0.7; }
.cal-list.past li { opacity: 0.6; }

/* ---------- Contact ---------- */
.contact-links {
  list-style: none;
  margin: 0 0 2.5rem;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  font-size: 1rem;
}
.contact-links a {
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 2px;
}
.contact-links a:hover { border-color: var(--fg); }

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 1.1rem;
  max-width: 42ch;
}
.contact-form label {
  font-size: 0.8rem;
  color: var(--fg-dim);
  display: block;
  margin-bottom: 0.4rem;
}
.contact-form input,
.contact-form textarea {
  width: 100%;
  background: rgba(242, 238, 228, 0.05);
  border: 1px solid var(--line);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 0.95rem;
  padding: 0.7em 0.9em;
  border-radius: 2px;
}
.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.contact-form button {
  align-self: flex-start;
  background: var(--accent);
  color: #08090b;
  border: none;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 0.9rem;
  padding: 0.75em 1.6em;
  border-radius: 2px;
  cursor: pointer;
  transition: opacity 0.2s ease;
}
.contact-form button:hover { opacity: 0.85; }
.form-status {
  font-size: 0.85rem;
  color: var(--fg-dim);
  min-height: 1.2em;
}
.form-status.ok { color: var(--accent); }
.form-status.err { color: var(--accent-2); }

footer.site-footer {
  font-size: 0.75rem;
  color: var(--fg-dim);
  padding-top: 3.5rem;
  margin-top: 3.5rem;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.75rem;
}
