/* ==========================================================================
   Wardspire — Website
   Grundsatz: Die Seite ist vollstaendig ohne JavaScript benutzbar.
   Menue, Turmauswahl und Bild-Vollansicht laufen ueber reines CSS.
   ========================================================================== */

:root {
  /* Flaechen */
  --bg:            #0a0e16;
  --bg-alt:        #0e1420;
  --panel:         #141b28;
  --panel-hi:      #1b2434;

  /* Linien */
  --border:        rgba(224, 179, 86, .18);
  --border-soft:   rgba(255, 255, 255, .07);

  /* Schrift */
  --text:          #dfe5f0;
  --text-dim:      #97a3b8;
  --text-faint:    #6b7789;

  /* Akzente */
  --gold:          #e0b356;
  --gold-hi:       #f4d089;
  --frost:         #6fb7d8;
  --ember:         #d9603a;
  --moss:          #7fae6b;
  --violet:        #9a7cc4;

  /* Masse */
  --wrap:          1180px;
  --radius:        14px;
  --radius-sm:     8px;

  --font-head:     "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --font-body:     ui-sans-serif, system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --shadow:        0 18px 48px rgba(0, 0, 0, .45);
  --ease:          cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------- Basis -- */

*, *::before, *::after { box-sizing: border-box; }

/* Abstand, den eine Sprungmarke unter der fest stehenden Kopfzeile freihaelt.
   Die Kopfzeile ist rund 67 px hoch, der Rest ist Luft. */
html { scroll-padding-top: 90px; }

/* Sanftes Scrollen NUR innerhalb einer Seite.
   Kommt man von einer anderen Seite (downloads.html -> index.html#gallery),
   hat beim Laden noch nichts den Eingabefokus — `:focus-within` trifft also
   nicht zu, und der Browser springt hart und damit zuverlaessig ans Ziel.
   Vorher scrollte er weich von oben los, waehrend die Bilder noch luden; die
   Bewegung brach ab und die Seite blieb ganz oben stehen (gemessen 2026-07-28).
   Klickt man dagegen auf der Seite selbst einen Verweis an, hat dieser den
   Fokus — dann bleibt es weich wie bisher. */
@media (prefers-reduced-motion: no-preference) {
  html:focus-within { scroll-behavior: smooth; }
}

/* Seitliches Ueberlaufen abfangen — bewusst HIER und nicht am <body>.
   Am <body> macht `overflow-x: hidden` diesen zu einem eigenen Scroll-Behaelter,
   der aber nie scrollt (gescrollt wird das Dokument darueber). Alle scroll-
   gesteuerten Animationen haengen sich dann an diesen toten Behaelter und
   laufen nie: Einblenden beim Scrollen, das Fuellen der Kopfzeile und das
   Hochzaehlen der Zahlen waren davon betroffen (gemessen 2026-07-28). */
html { overflow-x: hidden; }

/* Platz für den Bildlaufbalken IMMER freihalten, auch wenn die Seite kurz ist und
   gar nicht scrollt. Sonst wird das Fenster beim Wechsel von einer langen auf eine
   kurze Seite (Impressum -> Fehlerseite) um die Balkenbreite breiter, und der
   zentrierte Inhalt rutscht sichtbar zur Seite — gemessen 7 px bei 1280 px Breite,
   am deutlichsten an der Fusszeile, wo Text an beiden Raendern steht.
   Browser mit ueberlagerten Bildlaufbalken (Firefox mit Windows-Standardeinstellung)
   nehmen ohnehin keine Breite weg; dort aendert die Zeile nichts. */
html { scrollbar-gutter: stable; }

/* Der Koerper ist mindestens so hoch wie das Fenster und stapelt seine Teile
   untereinander; <main> dehnt sich auf den Rest. Damit steht die Fusszeile bei
   kurzen Seiten (Fehlerseite 404) unten am Fensterrand statt direkt unter dem
   Knopf. Lange Seiten aendern sich nicht — dort ist der Inhalt ohnehin hoeher.
   svh statt vh: auf Handys zaehlt vh die eingeblendete Browserleiste mit, die
   Seite bekaeme sonst einen Streifen Leerraum und liesse sich scrollen.
   Kopfzeile (fixed) und Sprungmarke (absolute) stehen ausserhalb des Flusses
   und sind von der Stapelung nicht betroffen. */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

/* 0 als Schrumpfwert: <main> darf nie kleiner werden als sein Inhalt. */
main { flex: 1 0 auto; }

img, svg, canvas { display: block; max-width: 100%; }
img { height: auto; }

a { color: var(--gold); text-decoration: none; transition: color .2s var(--ease); }
a:hover { color: var(--gold-hi); }

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 600; line-height: 1.15;
  margin: 0 0 .5em; letter-spacing: .01em;
}
h2 { font-size: clamp(1.9rem, 3.6vw, 2.9rem); }
h3 { font-size: 1.25rem; }
p  { margin: 0 0 1em; }

ul, ol { margin: 0; padding: 0; list-style: none; }

:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; border-radius: 4px; }

.wrap {
  width: 100%; max-width: var(--wrap); margin-inline: auto;
  padding-inline: clamp(18px, 4vw, 32px);
}

.skip-link {
  position: absolute; top: -60px; left: 16px; z-index: 200;
  background: var(--gold); color: #17120a;
  padding: 10px 18px; border-radius: 0 0 8px 8px; font-weight: 700;
  transition: top .2s var(--ease);
}
.skip-link:focus { top: 0; }

/* ==========================================================================
   EINBLENDUNG — zwei Wege, beide ohne JavaScript
   1) Grundfall: normale Lade-Animation. Laeuft in JEDEM Browser. Endzustand
      ist immer sichtbar, es kann also nichts dauerhaft unsichtbar bleiben.
   2) Moderne Browser: dieselbe Animation, aber am Scrollstand aufgehaengt.
   ========================================================================== */

@keyframes revealUp {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

.reveal {
  animation: revealUp .7s var(--ease) both;
}
/* Leichter Versatz, damit Karten einer Reihe nacheinander erscheinen */
.reveal:nth-child(1) { animation-delay: .04s; }
.reveal:nth-child(2) { animation-delay: .12s; }
.reveal:nth-child(3) { animation-delay: .20s; }
.reveal:nth-child(4) { animation-delay: .28s; }
.reveal:nth-child(5) { animation-delay: .36s; }
.reveal:nth-child(6) { animation-delay: .44s; }
.reveal:nth-child(7) { animation-delay: .52s; }
.reveal:nth-child(8) { animation-delay: .60s; }
.reveal:nth-child(n+9) { animation-delay: .66s; }

@supports (animation-timeline: view()) {
  .reveal {
    animation: revealUp linear both;
    animation-timeline: view();
    animation-range: entry 10% entry 90%;
    animation-delay: 0s;
  }
}

/* Wer weniger Bewegung wuenscht, bekommt gar keine */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { animation: none; opacity: 1; transform: none; }
  .hero-wind, .hero-storm { display: none; }
  /* Feuerstellen behalten ihren (dann stillen) Schein — nur die Bewegung faellt weg */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* Markierung auf Platzhalter-Flaechen */
.placeholder-tag {
  position: absolute; right: 10px; bottom: 10px; z-index: 2;
  font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-faint);
  background: rgba(10, 14, 22, .72);
  border: 1px solid var(--border-soft);
  padding: 3px 8px; border-radius: 999px; pointer-events: none;
}

/* ------------------------------------------------------------- Buttons -- */

.btn {
  --btn-bg: transparent;
  display: inline-flex; align-items: center; justify-content: center; gap: .6em;
  padding: .78em 1.5em;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--btn-bg); color: var(--text);
  font: inherit; font-weight: 600; letter-spacing: .02em;
  cursor: pointer; position: relative;
  transition: transform .18s var(--ease), box-shadow .25s var(--ease),
              border-color .25s var(--ease), background-color .25s var(--ease), color .2s;
}
.btn svg { width: 1.15em; height: 1.15em; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn-primary {
  --btn-bg: linear-gradient(180deg, var(--gold-hi), var(--gold));
  color: #1a1305; border-color: rgba(255, 232, 180, .6);
  box-shadow: 0 6px 20px rgba(224, 179, 86, .22);
}
.btn-primary:hover { color: #1a1305; box-shadow: 0 10px 30px rgba(224, 179, 86, .34); }

.btn-ghost { background: rgba(255, 255, 255, .035); }
.btn-ghost:hover { border-color: rgba(224, 179, 86, .5); background: rgba(224, 179, 86, .1); }

.btn-lg { padding: .95em 1.9em; font-size: 1.02rem; }

/* -------------------------------------------------------------- Header -- */

.site-header {
  position: fixed; inset: 0 0 auto; z-index: 100;
  padding: 12px 0;
  background: rgba(10, 14, 22, .82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border-soft);
}
/* ENTFERNT 2026-08-06 (Nutzer-Entscheidung): Hier stand ein Effekt, der die
   Kopfzeile oben durchsichtig liess und sie beim Scrollen einblendete
   (animation-timeline: scroll()). Chrome kann das, Firefox nicht — die Seite
   sah in beiden Browsern verschieden aus: in Chrome fehlte ganz oben die
   Trennlinie unter der Navigation, in Firefox war sie immer da.
   ★ REGEL: Nur einbauen, was in JEDEM Browser gleich aussieht. Ein Effekt,
   den nur ein Teil der Besucher sieht, ist kein Gewinn, sondern eine zweite
   Fassung der Seite, die niemand prueft. Die Kopfzeile ist jetzt immer
   gefuellt und traegt immer ihre Linie — siehe .site-header oben. */

/* Drei Spalten: links (Logo oder leer) — Navigation mittig — rechts Sprache */
.header-inner {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 16px;
  /* Feste Mindesthoehe, sonst SPRINGT der Kopf beim Seitenwechsel (Nutzer-Fund
     2026-08-05, gemessen): Auf der Startseite fehlt das kleine Kopf-Logo, dort
     bestimmt allein die Navigation die Hoehe (35,66 px) — auf Unterseiten das
     Logo (37,27 px bei 104 px Breite). Die 1,6 px Unterschied waren beim Klick
     aufs Logo als Ruckeln sichtbar. 38 px liegt knapp ueber beiden Werten und
     haelt die Hoehe auch dann stabil, wenn sich das Seitenverhaeltnis des Logos
     wieder aendert. */
  min-height: 38px;
}
.header-left { justify-self: start; min-width: 0; }
.header-right { justify-self: end; display: flex; align-items: center; gap: 10px; }

/* flex, NICHT inline-flex: Als inline-Element sitzt das Logo in einer Textzeile,
   und der Browser haelt darunter Platz fuer Unterlaengen frei. Gemessen waren
   das 7px — der linke Kopfbereich war 41,9px hoch, obwohl das Logo nur 34,9px
   misst. Dadurch war die Kopfzeile der Unterseiten hoeher als die der
   Startseite und sprang beim Seitenwechsel. */
.brand { display: flex; align-items: center; color: var(--text); }
.brand picture { display: block; line-height: 0; }
/* FESTE, kleine Breite. Vorher wuchs das Logo mit der Fensterbreite mit
   (clamp bis 168px) — dadurch war die Kopfzeile der Unterseiten hoeher als die
   der Startseite, und beim Seitenwechsel sprang das Layout. */
.brand-logo { width: 104px; height: auto; }

.nav { display: flex; align-items: center; justify-content: center; gap: clamp(10px, 1.5vw, 24px); }
.nav > a {
  color: var(--text-dim); font-size: .92rem; font-weight: 600;
  letter-spacing: .03em; position: relative; padding: 4px 0;
}
.nav > a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 1px;
  background: var(--gold); transition: right .3s var(--ease);
}
.nav > a:hover { color: var(--text); }
.nav > a:hover::after { right: 0; }
/* ACHTUNG: muss mindestens so spezifisch sein wie `.nav > a` — sonst gewinnt
   dessen `padding: 4px 0` und der Rahmen klebt an den Buchstaben. */
.nav > a.nav-cta {
  padding: .75em 1.9em; margin-left: .5em; color: var(--text);
  white-space: nowrap; line-height: 1.2;
  border-color: rgba(224, 179, 86, .45);
  background: rgba(224, 179, 86, .1);
}
.nav > a.nav-cta:hover { background: rgba(224, 179, 86, .2); border-color: var(--gold); color: var(--text); }
.nav > a.nav-cta::after { display: none; }

/* Menue-Schalter (Checkbox statt JavaScript) */
.nav-switch { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.nav-toggle { display: none; flex-direction: column; gap: 5px; cursor: pointer; padding: 8px; }
.nav-toggle span { width: 24px; height: 2px; background: var(--text); border-radius: 2px; transition: transform .3s var(--ease), opacity .2s; }

/* ------------------------------------------------------- Sprachauswahl --
   Natives <details>-Aufklappmenue: funktioniert in jedem Browser ohne
   JavaScript und ist per Tastatur bedienbar. */

.lang-switch { position: relative; }
.lang-switch summary {
  display: flex; align-items: center; gap: 7px;
  padding: 6px 10px; cursor: pointer; list-style: none;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, .04);
  font-size: .82rem; font-weight: 700; letter-spacing: .08em;
  color: var(--text-dim);
  transition: border-color .25s, color .25s, background-color .25s;
}
.lang-switch summary::-webkit-details-marker { display: none; }
.lang-switch summary::marker { content: ""; }
.lang-switch summary:hover { color: var(--text); border-color: var(--border); background: rgba(224, 179, 86, .1); }
.lang-switch summary img { width: 20px; height: 14px; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.4); }

.lang-arrow {
  width: 0; height: 0; margin-left: 1px;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
  border-top: 5px solid currentColor;
  transition: transform .25s var(--ease);
}
.lang-switch[open] .lang-arrow { transform: rotate(180deg); }
.lang-switch[open] summary { border-color: var(--border); color: var(--text); }

.lang-list {
  position: absolute; right: 0; top: calc(100% + 8px); z-index: 60;
  min-width: 190px; padding: 6px;
  background: rgba(12, 17, 26, .98);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.lang-list a {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 6px;
  color: var(--text-dim); font-size: .9rem;
}
.lang-list a:hover { background: rgba(224, 179, 86, .12); color: var(--text); }
.lang-list a[aria-current="true"] { color: var(--gold); background: rgba(224, 179, 86, .08); }
.lang-list img { width: 20px; height: 14px; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.4); }
.lang-list .lang-name { flex: 1; }
.lang-list .lang-code { font-size: .72rem; letter-spacing: .1em; color: var(--text-faint); }

/* ---------------------------------------------------------------- Hero -- */

.hero {
  position: relative; isolation: isolate;
  min-height: min(100svh, 900px);
  display: flex; align-items: center;
  padding: 150px 0 110px; overflow: hidden;
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(22, 32, 48, .35) 0%, transparent 60%),
    linear-gradient(180deg, #080b12 0%, #0a0e16 70%, var(--bg) 100%);
}

/* Kulisse hinter dem Startbild — halbdurchsichtig, endet genau an der
   Unterkante des Startbereichs (dort beginnt die Zahlenleiste). */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -4;
  background-image: url("../assets/placeholder/background.jpg");
  background-size: cover;
  /* An der UNTERKANTE verankert: Fjord und Ufer bleiben in jeder Auflösung
     sichtbar, beschnitten wird oben der leere Himmel. */
  background-position: center bottom;
  opacity: .5;
}

/* ================================== Leben im Hintergrundbild ====
   Feuerschein flackert ueber den Feuerstellen des Bilds — rein per CSS.
   Kernidee: .hero-scene ist ein Rahmen, der IMMER das Seitenverhaeltnis des
   Bilds hat und den Hero wie background-size:cover fuellt (unten verankert,
   identischer Beschnitt wie .hero::before). Alles darin ist in Prozent DES
   BILDES platziert und klebt deshalb bei jeder Fenstergroesse an seiner
   Stelle.
   Rueckfall: Kann ein Browser kein aspect-ratio, bleibt .hero-scene versteckt
   und .hero::before zeigt das Bild statisch — exakt der bisherige Zustand.
   (Bewegte Baeume und Wasser-Glitzern: 2026-07-31 in zwei Anlaeufen probiert
   und rueckgaengig gemacht — die maskierte Bild-Kopie verzerrte die
   Umgebung, der freigestellte Baum wirkte trotz Umfaerbung kuenstlich.
   Material fuer einen neuen Anlauf liegt in assets/quellen.) */

.hero-scene {
  display: none;
  position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  aspect-ratio: 1672 / 941;              /* Pixelmasse des Bilds */
  min-width: 100%; min-height: 100%;     /* zusammen mit aspect-ratio = cover */
  z-index: -4; opacity: .5; pointer-events: none;
}
.hero-scene::before {
  content: ""; position: absolute; inset: 0;
  background: url("../assets/placeholder/background.jpg") center / 100% 100% no-repeat;
}
/* MUSS nach der .hero-scene-Grundregel stehen: gleiche Spezifitaet,
   die spaetere Regel gewinnt. */
@supports (aspect-ratio: 1 / 1) {
  .hero::before { display: none; }
  .hero-scene { display: block; }
}

/* Feuerschein: weicher warmer Lichtfleck ueber jeder Feuerstelle, pulsiert
   unregelmaessig in Helligkeit und Groesse — jedes Feuer im eigenen Takt. */
.hero-scene .fire {
  position: absolute; left: var(--x); top: var(--y);
  width: calc(9% * var(--s)); aspect-ratio: 1 / 1;
  transform: translate(-50%, -50%);
  background:
    radial-gradient(closest-side, rgba(255, 232, 180, .5), rgba(255, 232, 180, 0) 16%),
    radial-gradient(closest-side, rgba(255, 196, 110, .4), rgba(255, 142, 52, .17) 45%, rgba(255, 110, 30, 0) 70%);
  mix-blend-mode: screen;
  animation: fireflick var(--dur) linear var(--del) infinite;
}
/* Ferne Uferlichter atmen nur leise, statt zu flackern */
.hero-scene .fire-faint { animation-name: firebreathe; }

@keyframes fireflick {
  0%   { opacity: .58; transform: translate(-50%, -50%) scale(.93); }
  17%  { opacity: .95; transform: translate(-50%, -50%) scale(1.05); }
  29%  { opacity: .70; transform: translate(-50%, -50%) scale(.97); }
  43%  { opacity: 1;   transform: translate(-50%, -50%) scale(1.08); }
  58%  { opacity: .64; transform: translate(-50%, -50%) scale(.95); }
  71%  { opacity: .92; transform: translate(-50%, -50%) scale(1.03); }
  86%  { opacity: .74; transform: translate(-50%, -50%) scale(.98); }
  100% { opacity: .58; transform: translate(-50%, -50%) scale(.93); }
}
@keyframes firebreathe {
  0%, 100% { opacity: .22; }
  50%      { opacity: .4; }
}

/* ------------------------------------------------------ Wind & Wetter -- */

/* Beides ist reine Stimmung: nur Verschieben und Deckkraft, nichts, was den
   Text stoert oder das Bild neu berechnen laesst. Wer weniger Bewegung
   eingestellt hat, bekommt beides gar nicht (siehe ganz unten). */

.hero-wind {
  position: absolute; inset: 0 0 auto; height: 56%; z-index: -1;
  overflow: hidden; pointer-events: none;
  /* Die Schwaden starten mit negativem Versatz, stehen beim Laden also mitten
     in ihrer Bahn — ohne das hier taucht Nebel aus dem Nichts auf. Die ganze
     Ebene blendet deshalb einmal sanft ein. */
  animation: nebelKommt 3s ease-out both;
}
@keyframes nebelKommt {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.hero-wind span {
  position: absolute; left: -80%; top: var(--t);
  width: var(--w); height: var(--h);
  border-radius: 50%;
  background: radial-gradient(58% 50% at 50% 50%, rgba(202, 222, 242, .3), transparent 70%);
  filter: blur(16px);
  /* Zwei Bewegungen gleichzeitig: der Zug durchs Bild und das kurze Aufhellen,
     wenn im Himmel ein Blitz zuckt. --fdur/--fdel sind auf je einen der Blitze
     abgestimmt, damit Wolke und Blitz denselben Moment teilen. */
  animation: windDrift var(--dur) linear var(--del) infinite,
             cloudFlash var(--fdur) linear var(--fdel) infinite;
}
/* Nur Helligkeit — die Weichzeichnung muss mitgeschrieben werden, sonst
   loescht die Bewegung sie fuer ihre Laufzeit aus. */
@keyframes cloudFlash {
  0%, 90%, 100% { filter: blur(16px) brightness(1); }
  90.7%         { filter: blur(16px) brightness(3.2); }
  91.4%         { filter: blur(16px) brightness(1.4); }
  92.1%         { filter: blur(16px) brightness(2.5); }
  94%           { filter: blur(16px) brightness(1); }
}
@keyframes windDrift {
  0%   { transform: translate3d(0, 0, 0);       opacity: 0; }
  22%  { opacity: 1; }
  78%  { opacity: 1; }
  100% { transform: translate3d(320%, -18%, 0); opacity: 0; }
}

.hero-storm {
  position: absolute; inset: 0 0 auto; height: 56%; z-index: -1;
  overflow: hidden; pointer-events: none;
}
.hero-storm span {
  position: absolute; top: var(--y); left: var(--x);
  width: var(--w); height: 26%;
  background: radial-gradient(54% 58% at 50% 40%,
              rgba(178, 212, 245, .55), rgba(126, 166, 218, .18) 48%, transparent 76%);
  filter: blur(12px);
  opacity: 0;
  animation: stormFlash var(--dur) linear var(--del) infinite;
}
/* Das Zucken belegt nur ein knappes Zwanzigstel des Durchlaufs — den Rest der
   Zeit ist es dunkel. Zwei Schlaege kurz hintereinander wirken echter als einer. */
@keyframes stormFlash {
  0%, 90%, 100% { opacity: 0; }
  90.7% { opacity: .85; }
  91.4% { opacity: .12; }
  92.1% { opacity: .55; }
  94%   { opacity: 0; }
}

.hero-aurora {
  position: absolute; inset: -20% -10% auto; height: 70%; z-index: -3;
  background:
    radial-gradient(50% 60% at 25% 40%, rgba(111, 183, 216, .18), transparent 70%),
    radial-gradient(45% 55% at 72% 30%, rgba(154, 124, 196, .16), transparent 70%),
    radial-gradient(40% 50% at 50% 55%, rgba(224, 179, 86, .12), transparent 70%);
  filter: blur(30px);
  animation: aurora 22s ease-in-out infinite alternate;
}
@keyframes aurora {
  0%   { transform: translate3d(-3%, 0, 0) scale(1); }
  100% { transform: translate3d(4%, 3%, 0) scale(1.12); }
}

/* Abdunkelung: haelt die Schrift lesbar, laesst unten aber genug Fjord
   stehen. Der Verlauf setzt erst spaet ein, damit das Ufer sichtbar bleibt. */
.hero-vignette {
  position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(85% 60% at 50% 42%, transparent 45%, rgba(6, 9, 14, .5) 100%),
    linear-gradient(180deg, rgba(8, 11, 18, .35) 0%, transparent 28%, transparent 72%, var(--bg) 100%);
}

.hero-inner { position: relative; text-align: center; }

.eyebrow {
  font-size: .8rem; letter-spacing: .26em; text-transform: uppercase;
  color: var(--gold); margin-bottom: 1.1em;
}

.hero-title { margin-bottom: .35em; }
/* Grosses Logo im Startbild — skaliert mit der Fensterbreite */
.hero-title picture { display: block; }
.hero-logo {
  width: min(860px, 92vw);
  height: auto;
  margin: 0 auto;
  /* Schein hinter dem Schriftzug. Der erste, ganz kurze Schatten legt einen
     hauchduennen warmen Saum direkt an die Kante — das kaschiert die harten
     Treppchen der Freistellung. Die beiden weiten Scheine heben das Logo vom
     Fjord ab, der schwarze bleibt als Tiefe darunter. drop-shadow folgt der
     Silhouette (nicht dem Bildrahmen), deshalb kein Kasten-Schatten. */
  filter:
    drop-shadow(0 0 2px rgba(244, 208, 137, .55))
    drop-shadow(0 0 22px rgba(224, 179, 86, .30))
    drop-shadow(0 14px 40px rgba(0, 0, 0, .6));
}
.hero-title-sub {
  display: block; margin-top: .55em;
  font-family: var(--font-body); font-size: clamp(.85rem, 2vw, 1.05rem);
  font-weight: 600; letter-spacing: .42em; text-transform: uppercase;
  color: var(--text-dim);
}

/* Der Textblock bekommt Platz fuer drei Zeilen fest reserviert. Damit
   rutschen die Knoepfe darunter beim Sprachwechsel nicht mehr, selbst wenn
   eine Uebersetzung etwas laenger ausfaellt. `balance` verteilt die Woerter
   in neueren Browsern gleichmaessig auf die Zeilen; aeltere ignorieren es. */
.hero-lead {
  max-width: 62ch; margin-inline: auto;
  font-size: clamp(1rem, 1.6vw, 1.15rem);
  color: var(--text-dim);
  min-height: calc(3 * 1.65em);
  text-wrap: balance;
}

.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; margin: 2.2em 0 2.6em; }

.hero-badges {
  display: flex; flex-wrap: wrap; gap: 10px 28px; justify-content: center;
  font-size: .85rem; color: var(--text-faint);
}
.hero-badges li { display: flex; align-items: baseline; gap: .45em; position: relative; }
.hero-badges strong { color: var(--text); font-weight: 700; letter-spacing: .04em; }
.hero-badges li + li::before {
  content: ""; position: absolute; left: -15px; top: 50%;
  width: 3px; height: 3px; border-radius: 50%; background: var(--gold);
  transform: translateY(-50%); opacity: .6;
}

/* Lesbarkeit ueber der Kulisse: weicher dunkler Hauch hinter der Schrift.
   Nur im Startbereich — auf den ruhigen Flaechen weiter unten waere er
   unnoetig. Zwei Ebenen: eine breite fuer den Kontrast zum Bild, eine enge
   fuer die Kantenschaerfe. */
.hero .eyebrow,
.hero-title-sub,
.hero-lead,
.hero-badges {
  text-shadow: 0 2px 12px rgba(4, 6, 11, .9), 0 1px 3px rgba(4, 6, 11, .75);
}
/* Die kleine Zeile unter den Knoepfen war fast verschwunden */
.hero-badges { color: #8e9bb0; }
.hero-lead { color: #b6c0d0; }

.hero-scroll {
  position: absolute; bottom: 26px; left: 50%; transform: translateX(-50%);
  width: 22px; height: 34px; border: 1px solid var(--border); border-radius: 12px;
}
.hero-scroll span {
  position: absolute; left: 50%; top: 7px; width: 3px; height: 7px;
  margin-left: -1.5px; border-radius: 2px; background: var(--gold);
  animation: scrollDot 1.9s var(--ease) infinite;
}
@keyframes scrollDot {
  0%, 100% { transform: translateY(0); opacity: 1; }
  60%      { transform: translateY(11px); opacity: 0; }
}

/* -------------------------------------------------------------- Zahlen -- */

.stats {
  border-block: 1px solid var(--border-soft);
  background: linear-gradient(180deg, rgba(224, 179, 86, .045), transparent);
  padding: 40px 0;
}
.stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; text-align: center; }
.stat { position: relative; }
.stat + .stat::before {
  content: ""; position: absolute; left: -12px; top: 12%; bottom: 12%; width: 1px;
  background: linear-gradient(180deg, transparent, var(--border), transparent);
}
.stat-num {
  display: block; position: relative;
  font-family: var(--font-head); font-size: clamp(2.1rem, 4.5vw, 3.2rem);
  color: var(--gold); line-height: 1;
}

/* ================================================= Zahlen hochzaehlen ====
   Reine CSS-Loesung ueber eine angemeldete Rechenvariable (@property).
   Die richtige Zahl steht als normaler Text im HTML und wird von der
   mitzaehlenden Fassung ueberdeckt. Der Zaehler endet IMMER exakt auf dem
   Zielwert (fill-mode both), es kann also nie eine falsche Zahl stehen
   bleiben.
   ======================================================================== */

@property --n {
  syntax: "<integer>";
  initial-value: 0;
  inherits: false;
}

/* Die Zahlen zaehlen BEIM LADEN der Seite von 0 auf ihren Wert. Kein Bezug
   zum Scrollen — die Kopplung war einmal drin und hing den Zaehlstand an die
   Scrollposition; wer oben stand, sah dauerhaft krumme Zwischenwerte.

   BEWUSST OHNE @supports-Abfrage: Vorher stand der Block hinter
   "at-rule(@property)" bzw. "animation-timeline: view()". Firefox besteht
   KEINE der beiden Abfragen und uebersprang deshalb den ganzen Block — die
   Zahl stand starr da, obwohl Firefox die noetige Technik (@property) laengst
   beherrscht. Die Absicherung schuetzte also vor nichts und verhinderte die
   Wirkung. Ein Browser ohne @property zeigt hier eine 0, die nach einer
   Sekunde auf den Endwert springt — unschoen, aber nie falsch. */

.stat-num { color: transparent; }
.stat-num::before {
  content: counter(n);
  counter-reset: n var(--n);
  position: absolute; inset: 0;
  color: var(--gold);
  animation-duration: 1.6s;
  animation-timing-function: var(--ease);
  animation-fill-mode: both;
  animation-delay: .4s;
}
.stat:nth-child(1) .stat-num::before { animation-name: count8;  }
.stat:nth-child(2) .stat-num::before { animation-name: count17; }
.stat:nth-child(3) .stat-num::before { animation-name: count9;  }
.stat:nth-child(4) .stat-num::before { animation-name: count20; }

@keyframes count8  { from { --n: 0; } to { --n: 8;  } }
@keyframes count17 { from { --n: 0; } to { --n: 17; } }
@keyframes count9  { from { --n: 0; } to { --n: 9;  } }
@keyframes count20 { from { --n: 0; } to { --n: 20; } }
.stat-label { display: block; margin-top: .45em; font-size: .84rem; color: var(--text-faint); letter-spacing: .04em; }

/* ------------------------------------------------------------ Sektionen -- */

.section { padding: clamp(70px, 9vw, 120px) 0; position: relative; }
.section-alt { background: var(--bg-alt); border-block: 1px solid var(--border-soft); }

.section-head { max-width: 66ch; margin: 0 auto clamp(40px, 6vw, 64px); text-align: center; }
.section-lead { color: var(--text-dim); font-size: 1.04rem; margin: 0; }

.rune-divider { display: flex; align-items: center; justify-content: center; gap: 18px; padding: 0 clamp(18px, 6vw, 60px); }
.rune-divider span { flex: 1; height: 1px; max-width: 340px; background: linear-gradient(90deg, transparent, var(--border), transparent); }
.rune-divider svg {
  width: 17px; height: 23px; fill: var(--gold); opacity: .5;
}
/* Die mittlere Rune ist ein Verweis nach ganz oben. Tiwaz ist ein Pfeil nach
   oben — das Zeichen erklaert sich damit selbst. Die Flaeche zum Klicken ist
   bewusst groesser als das Zeichen (44 px), damit sie auch auf dem Handy
   sicher zu treffen ist. */
.rune-divider .rune-top {
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  transition: background .3s var(--ease), transform .3s var(--ease);
}
.rune-divider .rune-top svg { opacity: .8; }
.rune-divider .rune-top:hover { background: rgba(224, 179, 86, .1); transform: translateY(-3px); }
.rune-divider .rune-top:hover svg { opacity: 1; fill: var(--gold-hi); }
.rune-divider .rune-top:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

.card {
  position: relative;
  background: linear-gradient(160deg, var(--panel), var(--bg-alt) 85%);
  border: 1px solid var(--border-soft); border-radius: var(--radius);
  transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.card::before, .card::after {
  content: ""; position: absolute; width: 14px; height: 14px;
  border: 1px solid var(--gold); opacity: 0; transition: opacity .3s var(--ease); pointer-events: none;
}
.card::before { top: 8px; left: 8px; border-right: 0; border-bottom: 0; border-top-left-radius: 6px; }
.card::after  { bottom: 8px; right: 8px; border-left: 0; border-top: 0; border-bottom-right-radius: 6px; }
.card:hover::before, .card:hover::after { opacity: .75; }
.card:hover { border-color: var(--border); box-shadow: var(--shadow); }

/* ------------------------------------------------------------- Features -- */

.feature-grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); }
.feature { padding: 30px 28px; }
.feature:hover { transform: translateY(-5px); }
.feature p { color: var(--text-dim); font-size: .96rem; margin: 0; }
.feature em { color: var(--gold); font-style: normal; }

.feature-icon {
  display: grid; place-items: center; width: 50px; height: 50px; margin-bottom: 20px;
  border-radius: 12px;
  background: radial-gradient(circle at 35% 25%, rgba(224, 179, 86, .22), rgba(224, 179, 86, .05));
  border: 1px solid var(--border);
}
.feature-icon svg { width: 25px; height: 25px; fill: none; stroke: var(--gold); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }

/* ==========================================================================
   TUERME — Auswahl per Radio-Knopf, komplett ohne JavaScript.
   Pfeiltasten funktionieren dabei automatisch (Browser-Standard).
   ========================================================================== */

.tower-explorer {
  position: relative;
  display: grid; gap: 22px;
  grid-template-columns: minmax(230px, 300px) 1fr;
  align-items: start;
}

.tower-radio { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; }

.tower-list { display: flex; flex-direction: column; gap: 7px; }
.tower-tab {
  width: 100%; display: grid; align-items: center; gap: 2px 14px;
  grid-template-columns: 40px 1fr;
  padding: 11px 14px;
  background: rgba(255, 255, 255, .02);
  border: 1px solid transparent; border-left: 2px solid transparent;
  border-radius: var(--radius-sm);
  color: var(--text-dim); text-align: left; cursor: pointer;
  transition: background-color .22s var(--ease), color .22s var(--ease), border-color .22s var(--ease);
}
.tower-tab:hover { background: rgba(255, 255, 255, .05); color: var(--text); }
.tower-name { grid-column: 2; font-weight: 600; }
.tower-hint { grid-column: 2; grid-row: 2; font-size: .76rem; color: var(--text-faint); letter-spacing: .1em; text-transform: uppercase; }
.tower-glyph {
  grid-row: 1 / 3; width: 40px; height: 40px; border-radius: 10px;
  background: rgba(255, 255, 255, .04); border: 1px solid var(--border-soft); position: relative;
}
.tower-glyph::after {
  content: ""; position: absolute; inset: 9px; background: currentColor; opacity: .85;
}

/* Aktiver Reiter + zugehoerige Karte */
#t-arrow:checked    ~ .tower-list label[for="t-arrow"],
#t-cannon:checked   ~ .tower-list label[for="t-cannon"],
#t-magic:checked    ~ .tower-list label[for="t-magic"],
#t-piercing:checked ~ .tower-list label[for="t-piercing"],
#t-slower:checked   ~ .tower-list label[for="t-slower"],
#t-storm:checked    ~ .tower-list label[for="t-storm"],
#t-blight:checked   ~ .tower-list label[for="t-blight"],
#t-support:checked  ~ .tower-list label[for="t-support"] {
  background: linear-gradient(90deg, rgba(224, 179, 86, .16), rgba(224, 179, 86, .02));
  border-left-color: var(--gold);
  color: var(--text);
}
#t-arrow:focus-visible    ~ .tower-list label[for="t-arrow"],
#t-cannon:focus-visible   ~ .tower-list label[for="t-cannon"],
#t-magic:focus-visible    ~ .tower-list label[for="t-magic"],
#t-piercing:focus-visible ~ .tower-list label[for="t-piercing"],
#t-slower:focus-visible   ~ .tower-list label[for="t-slower"],
#t-storm:focus-visible    ~ .tower-list label[for="t-storm"],
#t-blight:focus-visible   ~ .tower-list label[for="t-blight"],
#t-support:focus-visible  ~ .tower-list label[for="t-support"] {
  outline: 2px solid var(--gold); outline-offset: 2px;
}

.tower-panels { position: relative; }
.tower-panel { display: none; grid-template-columns: 240px 1fr; gap: 30px; padding: 30px; }

/* Sicherheitsnetz: Die erste Karte ist von Haus aus sichtbar. Sie wird nur
   ausgeblendet, wenn ein anderer Turm gewaehlt ist — kann die Auswahl-Technik
   ein Browser also nicht, bleibt trotzdem eine vollstaendige Karte stehen. */
#p-arrow { display: grid; }
#t-arrow:not(:checked) ~ .tower-panels #p-arrow { display: none; }

#t-arrow:checked    ~ .tower-panels #p-arrow,
#t-cannon:checked   ~ .tower-panels #p-cannon,
#t-magic:checked    ~ .tower-panels #p-magic,
#t-piercing:checked ~ .tower-panels #p-piercing,
#t-slower:checked   ~ .tower-panels #p-slower,
#t-storm:checked    ~ .tower-panels #p-storm,
#t-blight:checked   ~ .tower-panels #p-blight,
#t-support:checked  ~ .tower-panels #p-support {
  display: grid;
  animation: panelIn .3s var(--ease) both;
}
@keyframes panelIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* Glyphen-Farben je Turm */
.tower-glyph[data-glyph="arrow"]    { color: var(--gold);   }
.tower-glyph[data-glyph="cannon"]   { color: var(--ember);  }
.tower-glyph[data-glyph="magic"]    { color: var(--violet); }
.tower-glyph[data-glyph="piercing"] { color: #c9d3e2;       }
.tower-glyph[data-glyph="slower"]   { color: var(--frost);  }
.tower-glyph[data-glyph="storm"]    { color: #e8d36a;       }
.tower-glyph[data-glyph="blight"]   { color: var(--moss);   }
.tower-glyph[data-glyph="support"]  { color: var(--gold-hi);}

.tower-glyph[data-glyph="arrow"]::after    { clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%); }
.tower-glyph[data-glyph="cannon"]::after   { clip-path: circle(42% at 50% 55%); }
.tower-glyph[data-glyph="magic"]::after    { clip-path: polygon(50% 0, 100% 35%, 82% 100%, 18% 100%, 0 35%); }
.tower-glyph[data-glyph="piercing"]::after { clip-path: polygon(50% 0, 62% 72%, 50% 100%, 38% 72%); }
.tower-glyph[data-glyph="slower"]::after   { clip-path: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%); }
.tower-glyph[data-glyph="storm"]::after    { clip-path: polygon(58% 0, 20% 55%, 46% 55%, 38% 100%, 80% 42%, 52% 42%); }
.tower-glyph[data-glyph="blight"]::after   { clip-path: polygon(50% 0, 90% 60%, 50% 100%, 10% 60%); }
.tower-glyph[data-glyph="support"]::after  { clip-path: polygon(0 30%, 100% 0, 100% 100%, 0 70%); }

.tower-art {
  position: relative; display: grid; place-items: center;
  border-radius: var(--radius-sm);
  background:
    radial-gradient(circle at 50% 35%, rgba(224, 179, 86, .1), transparent 65%),
    var(--panel-hi);
  border: 1px dashed var(--border-soft);
  padding: 12px; min-height: 240px;
}
/* Die Turmbilder kommen aus dem Spiel und sind unterschiedlich hoch. Die feste
   Deckelung sorgt dafuer, dass alle acht gleich gross wirken und der Kasten
   beim Umschalten der Reiter nicht springt. */
.tower-art picture { display: block; line-height: 0; }
.tower-art img { max-height: 230px; width: auto; }

.tower-role { color: var(--gold); font-size: .78rem; letter-spacing: .2em; text-transform: uppercase; margin-bottom: .5em; }
.tower-body > h3 { font-size: 1.8rem; margin-bottom: .4em; }
.tower-body > p { color: var(--text-dim); }

.tower-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 14px; margin: 24px 0; padding: 16px 0; border-block: 1px solid var(--border-soft);
}
.tower-stats dt { font-size: .72rem; letter-spacing: .14em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 3px; }
.tower-stats dd { margin: 0; font-weight: 600; font-size: .97rem; }

.tower-specs-head { font-size: .74rem; letter-spacing: .16em; text-transform: uppercase; color: var(--text-faint); margin-bottom: .7em; }
.tower-specs li { position: relative; padding-left: 20px; margin-bottom: .45em; color: var(--text-dim); font-size: .95rem; }
.tower-specs li::before {
  content: ""; position: absolute; left: 0; top: .62em;
  width: 8px; height: 8px; transform: rotate(45deg); border: 1px solid var(--gold);
}
.tower-specs strong { color: var(--text); }

/* ---------------------------------------------------------------- Runen -- */

/* Hinweis unter den Turmkarten, der zum Runenteil darunter ueberleitet. */
.tower-note {
  margin: 26px auto 0; max-width: 62ch; text-align: center;
  color: var(--text-faint); font-size: .92rem;
}

/* Luft um die Trennlinie (Nutzer 2026-07-31): VOR und NACH der Linie gleich
   viel Abstand, angelehnt an die grossen Abschnitts-Abstaende — vorher sassen
   Linie und Ueberschrift gequetscht aufeinander (30px). */
.rune-block { margin-top: clamp(48px, 6vw, 72px); padding: clamp(48px, 6vw, 72px) 26px 26px; border-top: 1px solid var(--border-soft); }
.rune-head { text-align: center; max-width: 68ch; margin: 0 auto 26px; }
.rune-head h3 { font-size: 1.7rem; margin: .1em 0 .35em; }
.rune-head p:last-child { color: var(--text-dim); margin: 0; }

/* Fuenf je Zeile — dadurch steht in der ersten Zeile genau das, was heute im
   Spiel ist, darunter das Geplante. Angebrochene Zeilen sitzen mittig statt
   links angeschlagen. (Wer lieber drei gleiche Zeilen zu vier moechte: 25 %
   statt 20 % und Mindestbreite 200 px.) */
.rune-grid {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 16px; list-style: none; margin: 0; padding: 0;
}
.rune {
  flex: 0 1 calc(20% - 13px); min-width: 190px;
  position: relative; overflow: hidden; padding: 20px 18px; text-align: center;
}
.rune:hover { transform: translateY(-4px); }

/* Noch nicht im Spiel: rotes Eckband oben links, 45 Grad gekippt. */
.is-planned { position: relative; overflow: hidden; }
.is-planned::before { display: none; }          /* Eckzier weicht dem Band */
.rune-tag {
  position: absolute; top: 15px; left: -36px; width: 130px; z-index: 2;
  transform: rotate(-45deg);
  padding: 2px 0; text-align: center;
  background: rgba(217, 96, 58, .18);
  border-top: 1px solid rgba(217, 96, 58, .45);
  border-bottom: 1px solid rgba(217, 96, 58, .45);
  color: var(--ember); font-size: .6rem; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
}
.is-planned .rune-mark { opacity: .6; }
.is-planned h4 { color: var(--text-dim); }
.rune h4 { font-size: 1.05rem; margin: 0 0 .35em; }
.rune p { margin: 0; color: var(--text-dim); font-size: .88rem; }

/* Das Runenzeichen ist gezeichnet, kein Bild — skaliert beliebig, laedt nichts nach. */
.rune-mark {
  display: grid; place-items: center; width: 46px; height: 46px; margin: 0 auto 14px;
  border: 1px solid var(--border); border-radius: 50%;
  background: radial-gradient(circle, rgba(224, 179, 86, .12), transparent 70%);
}
.rune-mark svg { width: 20px; height: 26px; fill: var(--gold); }
.rune:hover .rune-mark svg { fill: var(--gold-hi); }

.rune-foot {
  margin: 22px auto 0; max-width: 70ch; text-align: center;
  color: var(--text-faint); font-size: .88rem;
}
/* Folgesaetze stehen als eigene Zeile darunter, nicht als neuer Absatz. */
.rune-foot + .rune-foot { margin-top: .35em; }

/* -------------------------------------------------------- Goetter-Gunst -- */

/* Vier Karten in einer Reihe; angebrochene Zeilen sitzen mittig (wie .rune-grid). */
.god-grid {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 16px; list-style: none; margin: 0; padding: 0;
}
.god {
  flex: 0 1 calc(25% - 12px); min-width: 220px;
  position: relative; overflow: hidden; padding: 22px 20px; text-align: center;
}
.god:hover { transform: translateY(-4px); }
.god h4 { font-size: 1.15rem; margin: 0 0 .1em; }
.god > p { margin: 0; color: var(--text-dim); font-size: .9rem; }

/* Der Name der Faehigkeit steht als goldene Kapitaelchen-Zeile unter dem Gott. */
.god .god-power {
  color: var(--gold); font-size: .78rem; letter-spacing: .12em;
  text-transform: uppercase; margin: 0 0 .6em;
}

/* Groesseres Emblem als bei den Runen — Platzhalter, bis es Goetterbilder gibt. */
.god-mark {
  display: grid; place-items: center; width: 64px; height: 64px; margin: 0 auto 14px;
  border: 1px solid var(--border); border-radius: 50%;
  background: radial-gradient(circle, rgba(224, 179, 86, .14), transparent 70%);
}
.god-mark svg { width: 26px; height: 34px; fill: var(--gold); }
.god:hover .god-mark svg { fill: var(--gold-hi); }
.is-planned .god-mark { opacity: .65; }

/* ---------------------------------------------------------------- Bosse -- */

/* Bewusst KEINE Bossbilder: Wer am Ende einer Welt steht, soll man im Spiel
   herausfinden. Das Archiv im Spiel haelt es genauso. */
/* Fuenf oben, vier darunter — und die letzte Zeile sitzt mittig. Ein festes
   Raster laesst die Reste links kleben; mit umbrechenden Zeilen zentriert sich
   jede angebrochene Zeile von selbst, auch auf schmalen Bildschirmen. */
.boss-grid {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 14px; list-style: none; margin: 0; padding: 0;
}
.boss { flex: 0 1 calc(20% - 12px); min-width: 150px; padding: 16px 12px; text-align: center; }
.boss:hover { transform: translateY(-4px); }
.boss h4 { font-size: .98rem; margin: 0 0 .2em; }
.boss p { margin: 0; color: var(--text-faint); font-size: .85rem; letter-spacing: .06em; }
.boss-mark {
  display: grid; place-items: center; margin: 0 auto 12px;
  width: 100%; aspect-ratio: 4 / 3; border-radius: var(--radius-sm);
  border: 1px dashed var(--border-soft);
  background: radial-gradient(circle at 50% 45%, rgba(224, 179, 86, .08), transparent 68%), var(--panel-hi);
  font-family: var(--font-head); font-size: 2.4rem; color: var(--gold);
  opacity: .85;
}
.boss:hover .boss-mark { opacity: 1; }

/* Enthuellte Bosse: Bild statt Fragezeichen im selben Rahmen — durchgezogener
   Rand markiert "bekannt", die gestrichelten Kacheln bleiben das Geheimnis. */
.boss-face { border-style: solid; position: relative; }
/* Bild ABSOLUT in die Kachel gelegt: nimmt an der Hoehenberechnung nicht teil,
   die 4:3-Kachel bleibt exakt so hoch wie die "?"-Nachbarn (sonst gemessen
   198 vs. 131 px). */
.boss-face picture { position: absolute; inset: 8px; }
.boss-face img { width: 100%; height: 100%; object-fit: contain; object-position: center bottom; display: block; }
/* Zusatzklasse fuer SCHLANKE, hohe Figuren (Elf Lord): das Bild bekommt mehr
   Hoehe als die Kachel (top -16px) und wird unten verankert — sonst wirkte die
   Figur verloren klein. overflow:hidden schneidet den Ueberstand (Lanzenspitze)
   am oberen Kachelrand ab (Nutzer 2026-07-30: nicht herausragen lassen).
   Breite Figuren (Jarl) bleiben ohne diese Klasse in der Kachel. */
.boss-face-tall { overflow: hidden; }
.boss-face-tall picture { inset: -16px 8px 6px 8px; }

/* ------------------------------------------------- Schwierigkeitsgrade -- */

.diff-grid {
  display: grid; gap: 16px; list-style: none; margin: 0; padding: 0;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.diff { position: relative; overflow: hidden; padding: 22px 20px; }
.diff:hover { transform: translateY(-4px); }
.diff h4 { font-size: 1.15rem; margin: 0 0 .35em; }
.diff p { margin: 0; color: var(--text-dim); font-size: .9rem; }
.diff-step {
  display: block; margin-bottom: .5em;
  font-family: var(--font-head); font-size: 1.5rem; color: var(--gold);
  letter-spacing: .08em;
}

/* --------------------------------------------------------------- Welten -- */

.world-path { position: relative; }
.world-path::before {
  content: ""; position: absolute; left: 27px; top: 20px; bottom: 20px; width: 2px;
  background: linear-gradient(180deg, transparent, var(--border) 8%, var(--border) 92%, transparent);
}

.world { position: relative; padding-left: 76px; margin-bottom: 18px; }

.world-node {
  position: absolute; left: 0; top: 22px;
  width: 56px; height: 56px; display: grid; place-items: center; border-radius: 50%;
  background: var(--bg-alt); border: 1px solid var(--border);
  font-family: var(--font-head); color: var(--gold); font-size: .95rem; letter-spacing: .04em;
  transition: box-shadow .3s var(--ease), transform .3s var(--ease); z-index: 1;
}
.world:hover .world-node {
  box-shadow: 0 0 0 5px rgba(224, 179, 86, .08), 0 0 26px rgba(224, 179, 86, .25);
  transform: scale(1.06);
}
.world.is-final .world-node { background: linear-gradient(160deg, var(--gold), #9a6f24); color: #161004; border-color: var(--gold-hi); }

.world-card { display: grid; grid-template-columns: 230px 1fr; gap: 24px; padding: 18px; }
.world:hover .world-card { transform: translateX(4px); }

.world-thumb { position: relative; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--border-soft); }
.world-thumb picture { display: block; height: 100%; }
.world-thumb img { width: 100%; height: 100%; object-fit: cover; }

.world-info h3 { margin-bottom: .18em; }
.world-biome { font-size: .78rem; letter-spacing: .14em; text-transform: uppercase; color: var(--gold); margin-bottom: .7em; }
.world-info > p:not(.world-biome):not(.world-boss) { color: var(--text-dim); font-size: .95rem; margin-bottom: .8em; }
.world-boss { margin: 0; font-size: .92rem; font-weight: 600; }
.world-boss span {
  display: inline-block; margin-right: .6em; padding: 2px 9px;
  font-size: .68rem; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--ember); border: 1px solid rgba(217, 96, 58, .4);
  border-radius: 999px; background: rgba(217, 96, 58, .1);
}

/* ----------------------------------------------------------- Bestiarium -- */

.beast-grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.beast { padding: 16px; }
.beast:hover { transform: translateY(-4px); }
.beast h3 { font-size: 1.1rem; margin: 14px 0 .3em; }
.beast p { color: var(--text-dim); font-size: .89rem; margin: 0; }
.beast-art {
  position: relative; border-radius: var(--radius-sm); overflow: hidden;
  border: 1px dashed var(--border-soft);
  background: radial-gradient(circle at 50% 60%, rgba(255, 255, 255, .05), transparent 65%), var(--panel-hi);
  display: grid; place-items: center; padding: 6px;
  /* FESTE Hoehe, damit alle Namen auf einer Linie stehen: die Bilder kommen aus
     dem Spiel und sind unterschiedlich hoch (Rabe 135 px, Eistroll 180 px).
     Ohne feste Hoehe richtet sich die Flaeche nach dem Bild und die Karte des
     Raben rutscht nach oben. Bild bleibt mittig, nichts wird beschnitten. */
  height: 188px;
}
.beast-art picture { display: block; line-height: 0; }
.beast-art img { max-height: 170px; width: auto; }

.rank-row { margin-top: 34px; padding: 22px 26px; border: 1px solid var(--border-soft); border-radius: var(--radius); background: rgba(255, 255, 255, .02); }
.rank-intro { color: var(--text-dim); font-size: .95rem; margin-bottom: .9em; }
.ranks { display: flex; flex-wrap: wrap; gap: 10px 26px; align-items: center; font-size: .9rem; }
.rank { display: inline-flex; align-items: center; gap: .55em; color: var(--text-dim); }
.rank-dot { width: 10px; height: 10px; border-radius: 50%; box-shadow: 0 0 12px currentColor; }
.rank-1 .rank-dot { background: var(--violet); color: var(--violet); }
.rank-2 .rank-dot { background: var(--gold);   color: var(--gold);   }
.rank-3 .rank-dot { background: var(--ember);  color: var(--ember);  }
.rank-mod .rank-dot { background: var(--text-faint); box-shadow: none; }
.rank-mod { color: var(--text-faint); font-size: .86rem; }

/* -------------------------------------------------------------- Galerie -- */

.video-frame { position: relative; overflow: hidden; margin: 0 0 20px; padding: 0; }
/* display:block gegen den Spalt darunter: ein <video> ist wie ein Bild ein
   Zeilen-Element, der Browser haelt darunter Platz fuer Unterlaengen frei.
   Die Hoehe kommt aus dem Seitenverhaeltnis, damit beim Laden nichts springt. */
.video-frame video { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: #000; }
.video-frame figcaption { padding: 12px 18px; font-size: .85rem; color: var(--text-faint); border-top: 1px solid var(--border-soft); }

/* Sechs Bilder = zwei Zeilen zu drei. Ein selbstfuellendes Raster machte
   daraus 4 + 2 mit angebrochener zweiter Zeile; umbrechende Zeilen halten
   drei je Zeile und ruecken einen Rest mittig. */
.shot-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 14px; }
.shot { flex: 0 1 calc(33.333% - 10px); min-width: 260px; }
.shot {
  position: relative; display: block; overflow: hidden;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm); background: var(--panel);
  transition: transform .3s var(--ease), border-color .3s;
}
.shot img { width: 100%; transition: transform .5s var(--ease), opacity .3s; opacity: .82; }
.shot:hover { border-color: var(--border); transform: translateY(-3px); }
.shot:hover img { transform: scale(1.05); opacity: 1; }
.shot-label {
  position: absolute; inset: auto 0 0; padding: 26px 14px 12px;
  font-size: .8rem; letter-spacing: .1em; color: var(--gold);
  background: linear-gradient(0deg, rgba(8, 11, 18, .92), transparent);
}

/* Vollansicht per :target — kein JavaScript */
.lightbox {
  position: fixed; inset: 0; z-index: 300;
  display: none; place-items: center;
  background: rgba(4, 6, 11, .94);
  backdrop-filter: blur(8px);
  padding: 40px 70px;
}
.lightbox { display: none; }
/* Die Vollansicht haengt an einem Auswahlknopf, NICHT an einer Sprungmarke.
   Grund: Eine Sprungmarke aendert die Adresse, und der Browser scrollt dann
   zwangslaeufig irgendwohin — beim Schliessen sprang die Seite deshalb immer
   ein Stueck. Auswahlknoepfe fassen die Adresse nicht an, es bleibt alles
   stehen, wo es steht. */
/* ★ DIESE LISTE WAECHST MIT DER GALERIE MIT. Wer ein Bild ergaenzt und die Zeile hier
   vergisst, bekommt eine Kachel, die sich beim Klick einfach nicht oeffnet -- ohne
   Fehlermeldung, denn HTML und Bild sind ja da. Genau das ist am 09.08.2026 beim
   Sprung von 6 auf 9 Bildern passiert. Anzahl muss zu src/templates/index.html passen
   (Kacheln, Vollansichten, Zaehler "N/9") und zu SHOTS in tools/make_shots.py. */
#lb-1:checked ~ .lightbox.lb-1,
#lb-2:checked ~ .lightbox.lb-2,
#lb-3:checked ~ .lightbox.lb-3,
#lb-4:checked ~ .lightbox.lb-4,
#lb-5:checked ~ .lightbox.lb-5,
#lb-6:checked ~ .lightbox.lb-6,
#lb-7:checked ~ .lightbox.lb-7,
#lb-8:checked ~ .lightbox.lb-8,
#lb-9:checked ~ .lightbox.lb-9 { display: grid; animation: fadeIn .25s var(--ease) both; }

/* Die Knoepfe selbst sieht niemand */
.lb-switch { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* Beschriftungen verhalten sich wie Schaltflaechen */
.shot, .lightbox-close, .lightbox-nav, .lightbox-backdrop { cursor: pointer; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.lightbox-backdrop { position: absolute; inset: 0; }
.lightbox img {
  position: relative; max-width: 100%; max-height: 78vh;
  border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow);
}
.lightbox-caption { position: absolute; bottom: 26px; left: 0; right: 0; text-align: center; color: var(--text-faint); font-size: .88rem; margin: 0; }
.lightbox-close, .lightbox-nav {
  position: absolute; background: rgba(255, 255, 255, .05);
  border: 1px solid var(--border-soft); color: var(--text);
  border-radius: 50%; display: grid; place-items: center; text-decoration: none;
  transition: background-color .2s, border-color .2s, transform .2s var(--ease);
}
.lightbox-close { top: 22px; right: 22px; width: 44px; height: 44px; font-size: 1.7rem; line-height: 1; }
/* padding-bottom hebt das Zeichen optisch in die Mitte: ‹ und › sitzen in ihrer Zeilenbox
   hoeher als deren Mitte, place-items:center richtet aber die BOX aus, nicht das sichtbare
   Zeichen -- ohne Ausgleich klebt der Pfeil zu tief (Nutzer-Fund 2026-08-09). */
.lightbox-nav { top: 50%; transform: translateY(-50%); width: 48px; height: 48px; font-size: 2rem; line-height: 1; padding-bottom: 6px; }
.lightbox-prev { left: 16px; }
.lightbox-next { right: 16px; }
.lightbox-close:hover, .lightbox-nav:hover { background: rgba(224, 179, 86, .18); border-color: var(--gold); color: var(--gold-hi); }
.lightbox-nav:hover { transform: translateY(-50%) scale(1.08); }

/* ----------------------------------------------------------- Entwicklung -- */

.devlog-layout { display: grid; grid-template-columns: 1.3fr .7fr; gap: 34px; align-items: start; }

.timeline { position: relative; padding-left: 34px; }
.timeline::before {
  content: ""; position: absolute; left: 7px; top: 8px; bottom: 8px; width: 2px;
  background: linear-gradient(180deg, var(--gold), rgba(224, 179, 86, .35) 40%, var(--border-soft));
}
.tl-item { position: relative; padding: 0 0 34px 8px; }
.tl-marker { position: absolute; left: -34px; top: 5px; width: 16px; height: 16px; border-radius: 50%; background: var(--bg); border: 2px solid var(--border); }
.tl-item.is-done .tl-marker { background: var(--gold); border-color: var(--gold); }
.tl-item.is-current .tl-marker {
  background: var(--gold); border-color: var(--gold-hi);
  box-shadow: 0 0 0 5px rgba(224, 179, 86, .16);
  animation: nowPulse 2.4s ease-in-out infinite;
}
@keyframes nowPulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(224, 179, 86, .14); }
  50%      { box-shadow: 0 0 0 9px rgba(224, 179, 86, .05); }
}
.tl-when { font-size: .74rem; letter-spacing: .18em; text-transform: uppercase; color: var(--gold); margin-bottom: .35em; }
.tl-item h3 { margin-bottom: .3em; }
.tl-item > p:last-child { color: var(--text-dim); font-size: .96rem; margin: 0; }

.dev-note { padding: 26px; text-align: center; }
.dev-portrait {
  width: 130px; height: 130px; margin: 0 auto 18px;
  border-radius: 50%; overflow: hidden;
  border: 1px solid var(--border); background: var(--panel-hi);
}
.dev-portrait img { width: 100%; height: 100%; object-fit: cover; }
.dev-note p { color: var(--text-dim); font-size: .94rem; }
.dev-note-tag { color: var(--text-faint) !important; font-size: .8rem !important; font-style: italic; margin: 0; }


/* Zwei Bereiche mit demselben Hintergrund direkt untereinander (Entwicklung +
   Roadmap) sollen als EIN Band lesen. Ohne diese Regel laeuft mittendurch eine
   Linie — .section-alt setzt oben UND unten einen Rand, hier stossen also zwei
   aufeinander — und der Abstand waere doppelt so gross wie ueberall sonst.
   Getrennt wird erst darunter, dort steht der Runen-Trenner.
   :has() kennt jeder heutige Browser; kennt es einer nicht, bleibt an der
   Stelle eine haarfeine Linie stehen, sonst nichts. */
.section-alt + .section-alt { border-top: 0; padding-top: 0; }
.section-alt:has(+ .section-alt) { border-bottom: 0; }

/* -------------------------------------------------------------- Roadmap -- */

/* Drei Karten nebeneinander, auf schmalen Schirmen untereinander. Der Punkt
   vor der Phasen-Zeile ist derselbe Marker wie in der Zeitleiste darueber
   (nowPulse) — dieselbe Formensprache, ein Bauteil weniger. */
.road-grid {
  display: grid; gap: 18px; list-style: none; margin: 0; padding: 0;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  align-items: start;
}
.road { padding: 26px 24px 24px; }
.road:hover { transform: translateY(-4px); }
.road h3 { font-size: 1.25rem; margin: 0 0 .35em; }

.road-when {
  display: flex; align-items: center; gap: .7em; margin-bottom: .5em;
  font-size: .74rem; letter-spacing: .18em; text-transform: uppercase; color: var(--gold);
}
.road-when::before {
  content: ""; flex: none; width: 11px; height: 11px; border-radius: 50%;
  background: var(--bg); border: 2px solid var(--border);
}
.road.is-now .road-when::before {
  background: var(--gold); border-color: var(--gold-hi);
  animation: nowPulse 2.4s ease-in-out infinite;
}
.road-lead { color: var(--text-dim); font-size: .94rem; margin: 0 0 1.1em; }

.road-items { list-style: none; margin: 0; padding: 0; }
.road-items li { position: relative; padding-left: 20px; margin-bottom: .5em; color: var(--text-dim); font-size: .92rem; }
.road-items li:last-child { margin-bottom: 0; }
.road-items li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 8px; height: 8px; transform: rotate(45deg); border: 1px solid var(--gold);
}

/* ------------------------------------------------------------- Download -- */

.download { padding-block: clamp(50px, 7vw, 90px); }
.download-box {
  display: grid; grid-template-columns: 1.15fr .85fr; gap: 40px; align-items: center;
  padding: clamp(28px, 4vw, 52px);
  border: 1px solid var(--border); border-radius: var(--radius);
  background:
    radial-gradient(90% 140% at 100% 0%, rgba(224, 179, 86, .1), transparent 55%),
    linear-gradient(150deg, var(--panel), var(--bg-alt));
  box-shadow: var(--shadow); position: relative; overflow: hidden;
}
.download-box::before {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(115deg, rgba(255,255,255,.02) 0 2px, transparent 2px 9px);
  pointer-events: none;
}
.download-text h2 { margin-bottom: .35em; }
.download-text p { color: var(--text-dim); margin-bottom: .8em; }
.download-note { font-size: .88rem; color: var(--text-faint); }
/* align-items:center statt der Vorgabe stretch: Sonst zieht die Flex-Spalte den
   Knopf auf ihre volle Breite (gemessen 413 px fuer 20 Zeichen Text) und er
   wirkt leer. min-width haelt ihn trotzdem stattlich und in allen vier
   Sprachen gleich breit — die laengste Fassung gibt sonst den Ton an. */
.download-actions { display: flex; flex-direction: column; align-items: center; gap: 12px; position: relative; }
.download-actions .btn { min-width: 300px; }
.download-meta { margin: 6px 0 0; font-size: .82rem; color: var(--text-faint); text-align: center; line-height: 1.5; }
.download-meta a { color: var(--gold); opacity: .8; }

/* --------------------------------------------------------------- System -- */

.req-grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.req { padding: 30px 28px; }
.req h3 { color: var(--gold); font-size: 1.2rem; letter-spacing: .06em; }
.req.is-recommended { border-color: var(--border); }
.req-badge {
  position: absolute; top: -11px; left: 26px;
  font-size: .66rem; letter-spacing: .18em; text-transform: uppercase; font-weight: 700;
  color: #17120a; background: var(--gold); padding: 3px 12px; border-radius: 999px;
}
.req dl { margin: 0; }
.req dl > div { display: grid; grid-template-columns: 140px 1fr; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--border-soft); }
.req dl > div:last-child { border-bottom: 0; }
.req dt { color: var(--text-faint); font-size: .85rem; }
.req dd { margin: 0; font-size: .93rem; }
.req-note { max-width: 68ch; margin: 28px auto 0; text-align: center; color: var(--text-faint); font-size: .9rem; }
.req-note em { color: var(--gold); opacity: .8; }

/* --------------------------------------------------------------- Footer -- */

.site-footer { background: #06090f; border-top: 1px solid var(--border-soft); padding-top: 60px; }
.footer-grid { display: grid; gap: 36px; grid-template-columns: 1.6fr .8fr .9fr 1.4fr; padding-bottom: 46px; }
.footer-brand p { color: var(--text-faint); font-size: .92rem; margin-top: 1em; max-width: 40ch; }
.footer-links { display: flex; flex-direction: column; gap: 9px; }
.footer-links h4, .footer-cta h4 {
  font-family: var(--font-body); font-size: .74rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: .5em;
}
.footer-links a { color: var(--text-dim); font-size: .93rem; }
.footer-links a:hover { color: var(--gold); }
.footer-cta p { color: var(--text-faint); font-size: .9rem; }

/* Kanal-Knoepfe im Fuss. Bewusst NICHT die Klasse .btn: deren Regel setzt
   `fill: none; stroke: currentColor` — richtig fuer die gezeichneten Symbole
   der Seite, falsch fuer die beiden Markenzeichen, die aus Flaechen bestehen
   und mit einer Kontur nur als Umriss erschienen. */
/* "Folgen" steht auf gleicher Hoehe wie der dritte Verweis der Nachbarspalte
   (Pressemappe). Der Wert ist gemessen, nicht geschaetzt: vom unteren Rand des
   Wunschzettel-Knopfes bis zur Mitte jener Zeile sind es 44px. Er gilt in allen
   vier Sprachen, weil der Knopf ueberall einzeilig bleibt (nachgemessen: 57px
   hoch in de/en/fr/es, Abstand zur Zeile ueberall 39px). Sollte der Knopftext
   je umbrechen, verrutscht die Ausrichtung — dann hier neu messen.
   Der Selektor nennt beide Klassen, weil die Regel weiter oben
   (".footer-links h4, .footer-cta h4") sonst staerker waere und den groesseren
   Abstand nach unten ueberschriebe. */
.footer-cta .social-head { margin-top: 44px; margin-bottom: 14px; }
.social { display: flex; gap: 10px; }
.social-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px;   /* 44px = die uebliche Mindestgroesse fuer Finger */
  border: 1px solid var(--border); border-radius: 50%;
  background: rgba(255, 255, 255, .035); color: var(--text-dim);
  transition: transform .18s var(--ease), border-color .25s var(--ease),
              background-color .25s var(--ease), color .2s;
}
.social-btn svg { width: 19px; height: 19px; fill: currentColor; stroke: none; }
.social-btn:hover {
  transform: translateY(-2px); color: var(--gold);
  border-color: rgba(224, 179, 86, .5); background: rgba(224, 179, 86, .1);
}

.footer-bottom {
  display: flex; flex-wrap: wrap; gap: 8px 24px; justify-content: space-between;
  padding-block: 20px; border-top: 1px solid var(--border-soft);
  font-size: .82rem; color: var(--text-faint);
}
.footer-bottom p { margin: 0; }

/* ==================================================== Unterseiten (Text) == */

.page-head { padding: 150px 0 40px; border-bottom: 1px solid var(--border-soft); background: linear-gradient(180deg, #080b12, var(--bg)); }
/* Der Abschnitt direkt unter einem Seitenkopf braucht oben weniger Polster:
   Sonst addieren sich die 40px von .page-head und die 70-120px von .section zu
   einer riesigen Luecke. Gilt NUR fuer die Unterseiten (Demo, Impressum,
   Datenschutz, Pressemappe) — die Startseite hat keinen .page-head und behaelt
   ihren Abschnitts-Rhythmus. */
.page-head + .section { padding-top: clamp(34px, 4vw, 55px); }
.page-head h1 { font-size: clamp(2rem, 5vw, 3rem); letter-spacing: .04em; }
/* 92ch statt 60ch: Gemessen brauchte die laengste Einleitung (deutsches
   Impressum) 821px fuer eine Zeile, gesetzt waren 550px — sie brach also um.
   92ch sind ~843px und decken alle vier Sprachen; die Textspalte darunter
   (.prose-wide, 100ch) bleibt breiter. */
.page-head p { color: var(--text-dim); max-width: 92ch; margin: 0; }
/* Zweiter Einleitungsabsatz (Demo-Seite): .page-head p hat margin:0, sonst
   klebten die beiden Zeilen aneinander. Trifft die Einleitung, nicht die
   eyebrow — dahinter steht die Ueberschrift, kein p. */
.page-head p + p { margin-top: .35em; }

.prose { max-width: 72ch; margin-inline: auto; }
/* Alle Unterseiten (Demo, Impressum, Datenschutz, Pressemappe): breiter als die
   72ch der Lesespalte (~870px statt ~640px), aber BEWUSST nicht bis an den Rand
   — bei voller Breite (~1116px) stehen ueber 120 Zeichen in einer Zeile und das
   Auge findet den naechsten Zeilenanfang schlecht.
   margin-inline:0 hebt das Zentrieren von .prose auf: Der Text beginnt damit an
   derselben linken Kante wie die Ueberschrift darueber (beide sitzen im .wrap
   mit gleichem Innenabstand), statt mittig zu schwimmen.
   Einziger Regler fuer die Breite: dieser eine Wert. */
.prose-wide { max-width: 100ch; margin-inline: 0; }
.prose h2 { font-size: 1.5rem; margin-top: 2em; }
.prose h3 { font-size: 1.12rem; margin-top: 1.6em; }
.prose p, .prose li { color: var(--text-dim); }
.prose ul { list-style: disc; padding-left: 1.3em; margin-bottom: 1em; }
.prose li { margin-bottom: .4em; }
.prose strong { color: var(--text); }
.prose table { width: 100%; border-collapse: collapse; margin: 1.2em 0; font-size: .93rem; }
.prose th, .prose td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border-soft); }
.prose th { color: var(--gold); font-weight: 600; font-size: .8rem; letter-spacing: .1em; text-transform: uppercase; }

.note-box {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: rgba(224, 179, 86, .06); padding: 18px 22px; margin: 24px 0;
}
.note-box p { margin: 0; color: var(--text-dim); font-size: .93rem; }
.note-box p + p { margin-top: .7em; }
.note-box strong { color: var(--gold); }
/* Nur auf der Demo-Seite: Die Frage steht auf einer eigenen Zeile, die Antwort
   direkt darunter — als Block statt inline im selben Absatz. */
.note-box-narrow strong { display: block; }

.dl-grid { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); margin-bottom: 30px; }
.dl-card { padding: 26px; text-align: center; }
.dl-card h3 { color: var(--gold); }
.dl-card p { color: var(--text-dim); font-size: .92rem; }
.dl-card .btn { width: 100%; margin-top: 8px; }

/* Demo-Seite: Hinweisbox und die einzelne Steam-Karte bekommen GENAU Breite und
   linke Kante des Textblocks darunter (.prose-wide) — sonst hat die Seite drei
   verschiedene Kanten: Ueberschrift, Boxen, Fliesstext. */
.note-box-narrow,
.dl-grid-single { max-width: 100ch; margin-left: 0; margin-right: 0; }

/* MUSS hinter .dl-card .btn stehen: gleiche Gewichtung, also gewinnt die
   spaetere Regel. Ohne width:auto zoege der Knopf ueber die ganze Karte;
   zentriert wird er vom text-align:center der Karte (.btn ist inline-flex). */
.dl-grid-single .btn { width: auto; min-width: 260px; }

/* ------------------------------------------------------------- Responsiv -- */

@media (max-width: 980px) {
  .tower-explorer { grid-template-columns: 1fr; }
  .tower-list { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; padding-bottom: 8px; }
  .tower-tab { min-width: 190px; }
  .devlog-layout { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-brand, .footer-cta { grid-column: 1 / -1; }
  /* Ab hier steht die Spalte allein unter den anderen — es gibt keine Zeile
     mehr, auf die "Folgen" sich ausrichten koennte. Also nur noch normaler
     Abstand statt der 44px von oben. */
  .footer-cta .social-head { margin-top: 1.6em; }
}

@media (max-width: 1000px) {
  /* Menue klappt per Checkbox auf — ohne JavaScript */
  .nav {
    position: fixed; inset: 0 0 auto; top: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    padding: 84px 26px 30px;
    background: rgba(8, 11, 18, .98);
    border-bottom: 1px solid var(--border-soft);
    transform: translateY(-102%);
    transition: transform .4s var(--ease);
    max-height: 100svh; overflow-y: auto;
  }
  .nav-switch:checked ~ .nav { transform: translateY(0); }
  .nav-switch:checked ~ .header-right .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-switch:checked ~ .header-right .nav-toggle span:nth-child(2) { opacity: 0; }
  .nav-switch:checked ~ .header-right .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .nav-switch:focus-visible ~ .header-right .nav-toggle { outline: 2px solid var(--gold); outline-offset: 3px; }
  .nav > a { padding: 14px 0; border-bottom: 1px solid var(--border-soft); font-size: 1.05rem; }
  .nav > a::after { display: none; }
  .nav > a.nav-cta { margin: 18px 0 0; border-bottom: 0; text-align: center; }
  .nav-toggle { display: flex; z-index: 2; }

  .stats-grid { grid-template-columns: repeat(2, 1fr); gap: 30px 12px; }
  .stat + .stat::before { display: none; }

  .tower-panel { grid-template-columns: 1fr; }
  .tower-art { min-height: 180px; }

  .world { padding-left: 0; }
  .world-path::before { display: none; }
  .world-node { position: static; margin: 0 0 -28px 18px; width: 44px; height: 44px; font-size: .85rem; }
  .world-card { grid-template-columns: 1fr; padding-top: 34px; }

  .download-box { grid-template-columns: 1fr; gap: 26px; }
  .lightbox { padding: 20px; }
  .lightbox-nav { width: 40px; height: 40px; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .hero { padding-top: 130px; }
  .hero-actions { flex-direction: column; align-items: stretch; }
  .req dl > div { grid-template-columns: 1fr; gap: 2px; }
  .footer-grid { grid-template-columns: 1fr; }
  .beast-grid { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .beast-art img { max-height: 120px; }
}

/* -------------------------------------------- Nachtrag: weniger Bewegung --
   MUSS am Dateiende stehen: die Zaehler-Regeln weiter oben haben dieselbe
   Staerke, und bei Gleichstand gewinnt in CSS die spaetere Regel. */

@media (prefers-reduced-motion: reduce) {
  .stat-num { color: var(--gold); }
  .stat-num::before { content: none; }
}

/* ----------------------------------------------------------------- Druck -- */

@media print {
  body { background: #fff; color: #000; }
  .site-header, .hero-aurora, .hero-wind, .hero-storm,
  .lightbox, .nav-toggle, .hero-scroll { display: none !important; }
  .reveal { animation: none; opacity: 1; transform: none; }
  .tower-panel { display: grid !important; page-break-inside: avoid; }
}


/* ======================================= Ruhe beim Sprachwechsel ====
   Spanische und franzoesische Texte sind stellenweise laenger als die
   deutschen. Ohne Gegenmassnahme wachsen einzelne Kacheln dadurch und das
   Layout springt beim Umschalten.

   Zwei Mittel, beide folgenlos, wenn ein Browser sie nicht kennt:
   - Mindesthoehen, wo Kacheln nebeneinander stehen: die Kachel behaelt ihre
     Hoehe, egal wie lang der Text ist.
   - `text-wrap`: neuere Browser verteilen die Woerter gleichmaessiger auf die
     Zeilen und lassen keine einzelnen Woerter auf der letzten Zeile stehen.

   ★ WELCHER WERT WOFUER (berichtigt 2026-08-07, Nutzer-Fund):

   `balance` verteilt die Zeilen GLEICH BREIT. `pretty` tut das NICHT — es
   sorgt nur dafuer, dass die letzte Zeile nicht aus einem einzelnen Wort
   besteht, und nimmt dafuer sogar sehr ungleiche Zeilen in Kauf.

   Bei den kurzen Texten dieser Seite (Einleitungen, Kacheln, Fussnoten —
   fast alle 2 bis 4 Zeilen) sieht das schlecht aus: gemessen am Vorspann von
   „Goetter-Gunst" standen 564 px in der ersten und 365 px in der zweiten
   Zeile — 199 px Unterschied, der Satz wirkte zerrissen. Mit `balance`:
   463 zu 466 px. Ueber die ganze Startseite betraf das 23 Textbloecke.

   Deshalb gilt hier: **`balance` als Regel**, `pretty` nur fuer echten
   Fliesstext ueber viele Zeilen (Impressum, Datenschutz). Grund fuer die
   Grenze: Browser rechnen `balance` nur bis etwa sechs Zeilen aus — bei
   langen Absaetzen wirkt es ohnehin nicht, und dort ist `pretty` richtig.
   ==================================================================== */

/* ★ ALS GRUNDREGEL, nicht als Liste einzelner Klassen. Eine Aufzaehlung
   bleibt zwangslaeufig lueckenhaft — beim Umstellen am 2026-08-07 blieben
   trotz 15 Selektoren zwei Absaetze ohne Klasse zerrissen zurueck. Absaetze
   ueber mehr als etwa sechs Zeilen laesst der Browser ohnehin unberuehrt,
   ein Schaden kann hier also nicht entstehen. */
h1, h2, h3, h4, p, figcaption, blockquote { text-wrap: balance; }

/* Einzige Ausnahme: echter Fliesstext ueber viele Zeilen (Impressum,
   Datenschutz, Pressemappe). Browser rechnen `balance` nur bis etwa sechs
   Zeilen aus — bei laengeren Absaetzen bleibt es wirkungslos, waehrend
   `pretty` wenigstens verhindert, dass die letzte Zeile aus einem einzelnen
   Wort besteht.

   ★ Die Klasse heisst .prose, NICHT .legal. Hier stand zuerst `.legal` —
   ein Selektor, den es auf keiner Seite gibt (07.08.2026). Die Ausnahme war
   dadurch wirkungslos, und ein Absatz im Datenschutz wurde messbar
   schlechter statt besser. Beim naechsten Mal: erst im erzeugten HTML
   nachsehen, welche Klasse tatsaechlich dransteht. */
.prose p, .prose li { text-wrap: pretty; }

/* ★ EIN SATZ, EINE ZEILE (Turmbeschreibungen).
   Dort stehen zwei bis drei kurze Saetze in einer schmalen Spalte. Ohne das
   hier zerreisst sie der Browser quer: jeder Satz beginnt und endet mitten in
   einer Zeile. `balance` kann das nicht loesen — es macht die Zeilen gleich
   BREIT und kennt keine Satzgrenzen. build.py legt deshalb jeden Satz in ein
   eigenes <span class="satz">, das hier zum Block wird.
   Der Vorteil gegenueber einem <br>: Ein Satz, der nicht in eine Zeile passt,
   bricht INNERHALB seines Blocks weiter um — auf dem Handy bleibt also alles
   lesbar, nur eben nie mit dem naechsten Satz vermischt.

   ★ INNERHALB des Satzes gilt `pretty`, NICHT `balance` (gemessen 07.08.2026).
   `balance` wuerde den Satz auf seine Zeilen gleichmaessig verteilen und dabei
   genau das zerreissen, worum es hier geht:
       balance:  „…das effizienteste Geraet im" / „Arsenal — trifft aber nur…"
       pretty:   „…das effizienteste Geraet im Arsenal —" / „trifft aber nur…"
   `pretty` fuellt die erste Zeile aus und laesst den Gedankenstrich am Ende
   stehen — zusammen mit dem geschuetzten Leerzeichen davor (build.py,
   strich_festhalten) bleibt „Arsenal —" dadurch beisammen. */
.satz { display: block; text-wrap: pretty; }

/* Mindesthoehen fuer die Kachelraster (in Zeilen gerechnet, damit sie mit der
   Schriftgroesse mitwachsen) */
.beast p        { min-height: calc(3 * 1.55em); }
.rune p         { min-height: calc(3 * 1.55em); }
.diff p         { min-height: calc(3 * 1.55em); }
.world-info > p:not(.world-biome):not(.world-boss) { min-height: calc(2 * 1.55em); }
.feature p      { min-height: calc(4 * 1.55em); }

@media (max-width: 700px) {
  /* Auf dem Handy stehen die Kacheln untereinander — dort sind reservierte
     Hoehen nur Leerraum. */
  .beast p, .rune p, .diff p, .feature p,
  .world-info > p:not(.world-biome):not(.world-boss) { min-height: 0; }
}


/* ============================================ Bilder erschweren ====
   WAS DAS IST UND WAS NICHT: Ein echter Kopierschutz ist im Web nicht
   moeglich. Jedes Bild, das ein Besucher SIEHT, hat sein Browser bereits
   heruntergeladen — es steht in der Adresszeile, im Zwischenspeicher und in
   den Entwicklerwerkzeugen. Was hier steht, ist eine HUERDE gegen das
   beilaeufige Mitnehmen, kein Schutz gegen jemanden, der es darauf anlegt.

   Bewusst OHNE JavaScript geloest, weil die Seite ohne auskommt. Ein Sperren
   der rechten Maustaste ginge nur mit JavaScript — und waere die schwaechste
   Huerde von allen, dafuer die aergerlichste fuer normale Besucher.

   Der wirksamste Schutz bleibt ein Wasserzeichen im Bild selbst.
   ================================================================== */

/* Bilder lassen sich nicht ziehen und nicht direkt anfassen. Der Rechtsklick
   trifft dadurch die Seite statt des Bildes — im Menue fehlen "Bild speichern
   unter" und "Bild in neuem Tab oeffnen". Klicks gehen an das umgebende
   Element weiter, die Galerie-Vollansicht funktioniert also weiter. */
img, picture {
  -webkit-user-drag: none;
  user-select: none;
  -webkit-touch-callout: none;
  pointer-events: none;
}

/* Ausnahme: Flaggen im Sprachmenue muessen anklickbar bleiben */
.lang-list img { pointer-events: auto; }

/* Kein versehentliches Markieren von Ueberschriften und Bildunterschriften */
h1, h2, h3, h4, .eyebrow, .shot-label, .stat-num, .rune-mark, .boss-mark {
  user-select: none;
}

/* GEGENAUSNAHME: In den Rechtstexten muss man Text markieren und kopieren
   koennen — Anschrift, Steuernummer, E-Mail. Das ist kein Diebstahl, das ist
   der Zweck der Seite. */
.prose, .prose * { user-select: text; }

/* --------------------------------------------------- Zurueck-Verweis -- */
/* Auf den Unterseiten oben links. Das Logo fuehrt zwar auch zur Startseite,
   aber das erkennt man nicht — ein beschrifteter Verweis schon. */
.back-link {
  display: inline-flex; align-items: center; gap: .5em;
  margin-bottom: 1.1em;
  color: var(--text-dim); font-size: .92rem; letter-spacing: .02em;
  transition: color .25s var(--ease), transform .25s var(--ease);
}
.back-link svg {
  width: 16px; height: 16px; fill: none; stroke: currentColor;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}
.back-link:hover { color: var(--gold); transform: translateX(-3px); }
.back-link:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; }
