/* ===========================================================================
   Bergfried — gemeinsames Interface für Server-Seiten und Spiel-HUD.
   Wird unter /static/ui.css ausgeliefert.

   Schriften liegen selbst im Projekt (OFL-lizenziert), kein CDN: das Spiel
   soll auch auf einem VPS ohne Fremdabhängigkeiten laufen und bei allen
   Mitspielern gleich aussehen.
   =========================================================================== */

@font-face {
  font-family: "Unifraktur";
  src: url("/static/fonts/unifraktur-latin.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Garamond Bergfried";
  src: url("/static/fonts/ebgaramond-latin.woff2") format("woff2");
  font-weight: 400 700;
  font-display: swap;
}

:root {
  /* Stein und Eisen — die Grundmasse der Oberfläche */
  --stone-900: #121417;
  --stone-800: #181b1f;
  --stone-700: #22262b;
  --stone-600: #2c3138;
  --iron: #3b414a;
  --iron-light: #565d67;

  /* Messing — der einzige Zierton, sparsam */
  --brass: #a8813d;
  --brass-light: #cca75e;
  --brass-dark: #6d5426;

  /* Pergament für Urkunden und Chronik */
  --parchment: #d7c7a3;
  --parchment-dark: #bfad86;
  --ink: #2b2419;
  --ink-soft: #5b4e3b;

  /* Schrift auf dunklem Grund: warmes Grau, nie kaltes Weiß */
  --text: #d2ccbf;
  --text-dim: #928b7d;

  --moss: #7a9166;
  --fire: #c2662e;
  --fire-light: #e08a4b;
  --blood: #8f3d2c;

  --font-display: "Unifraktur", "Old English Text MT", "UnifrakturMaguntia", serif;
  --font-body: "Garamond Bergfried", "Palatino Linotype", Palatino, Georgia, serif;

  /* --- Die Mauszeiger ------------------------------------------------------
     EIN Zeiger, überall: ein kupferner Metallpfeil. Er wechselt nur die
     Legierung — golden, sobald unter ihm etwas geschehen kann — und bekommt
     in den Werkzeug-Zuständen ein kleines Gerät an die Seite gestellt.

     Ein Mauszeiger ist ein STEHENDES Bild; der Browser animiert ihn nicht.
     "Schimmern" ist deshalb Malerei und keine Bewegung: hellere Legierung,
     Glanzkante an der linken Schneide, ein Lichtfunke auf der Fläche.

     Der Griff — der Punkt, der wirklich klickt — liegt bei allen fünf auf
     derselben Pfeilspitze (3 2). Das Werkzeug daneben verschiebt ihn nicht,
     sonst zielte man im Abriss anders als beim Bauen.

     Die Icon-Werkstatt (/dev/icons) kann jede dieser Variablen zusätzlich auf
     ein gewürfeltes PNG umbiegen; dann gilt jenes statt der Zeichnung. */

  /* Kupfer — der Normalfall. Gilt überall, wo nichts weiter ist. */
  --cursor-kupfer: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E %3Cdefs%3E%3ClinearGradient id='m' x1='0' y1='0' x2='0.75' y2='1'%3E %3Cstop offset='0' stop-color='%23e9a877'/%3E %3Cstop offset='.45' stop-color='%23b87333'/%3E %3Cstop offset='1' stop-color='%236f3f1c'/%3E %3C/linearGradient%3E%3C/defs%3E %3Cpath d='M2.6 1.6 L2.6 21.8 L7.7 17.1 L11.1 24.9 L14.6 23.3 L11.2 15.7 L17.9 15.1 Z' fill='url(%23m)' stroke='%2312151a' stroke-width='1.5' stroke-linejoin='round'/%3E %3Cpath d='M4.3 4.2 L4.3 19.0' stroke='%23f6d3b0' stroke-width='1.1' opacity='.8' stroke-linecap='round'/%3E %3Cpath d='M5.2 4.6 L15.0 13.4' stroke='%2312151a' stroke-width='.9' opacity='.26'/%3E %3Ccircle cx='6.4' cy='12.4' r='.7' fill='%2312151a' opacity='.16'/%3E %3Ccircle cx='8.6' cy='16.6' r='.6' fill='%2312151a' opacity='.14'/%3E %3Ccircle cx='5.6' cy='7.6' r='.55' fill='%23f6d3b0' opacity='.5'/%3E %3C/svg%3E")
    3 2, auto;

  /* Gold — über allem, was auf einen Klick antwortet: Knöpfe,
     Verweise, Gebäude, Dörfer. */
  --cursor-gold: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E %3Cdefs%3E%3ClinearGradient id='m' x1='0' y1='0' x2='0.75' y2='1'%3E %3Cstop offset='0' stop-color='%23fbeaa8'/%3E %3Cstop offset='.45' stop-color='%23cca75e'/%3E %3Cstop offset='1' stop-color='%237d5f22'/%3E %3C/linearGradient%3E%3C/defs%3E %3Cpath d='M2.6 1.6 L2.6 21.8 L7.7 17.1 L11.1 24.9 L14.6 23.3 L11.2 15.7 L17.9 15.1 Z' fill='url(%23m)' stroke='%2312151a' stroke-width='1.5' stroke-linejoin='round'/%3E %3Cpath d='M4.3 4.2 L4.3 19.0' stroke='%23fff6d0' stroke-width='1.1' opacity='.8' stroke-linecap='round'/%3E %3Cpath d='M5.2 4.6 L15.0 13.4' stroke='%2312151a' stroke-width='.9' opacity='.26'/%3E %3Ccircle cx='6.4' cy='12.4' r='.7' fill='%2312151a' opacity='.16'/%3E %3Ccircle cx='8.6' cy='16.6' r='.6' fill='%2312151a' opacity='.14'/%3E %3Ccircle cx='5.6' cy='7.6' r='.55' fill='%23fff6d0' opacity='.5'/%3E %3Cpath d='M7.5 6.2 L8.2 8.3 L10.3 9 L8.2 9.7 L7.5 11.8 L6.8 9.7 L4.7 9 L6.8 8.3 Z' fill='%23fff8dc' opacity='.92'/%3E%3C/svg%3E")
    3 2, pointer;

  /* Kupfer mit Maurerkelle — im Baumodus. */
  --cursor-bauen: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E %3Cdefs%3E%3ClinearGradient id='m' x1='0' y1='0' x2='0.75' y2='1'%3E %3Cstop offset='0' stop-color='%23e9a877'/%3E %3Cstop offset='.45' stop-color='%23b87333'/%3E %3Cstop offset='1' stop-color='%236f3f1c'/%3E %3C/linearGradient%3E%3C/defs%3E %3Cpath d='M2.6 1.6 L2.6 21.8 L7.7 17.1 L11.1 24.9 L14.6 23.3 L11.2 15.7 L17.9 15.1 Z' fill='url(%23m)' stroke='%2312151a' stroke-width='1.5' stroke-linejoin='round'/%3E %3Cpath d='M4.3 4.2 L4.3 19.0' stroke='%23f6d3b0' stroke-width='1.1' opacity='.8' stroke-linecap='round'/%3E %3Cpath d='M5.2 4.6 L15.0 13.4' stroke='%2312151a' stroke-width='.9' opacity='.26'/%3E %3Ccircle cx='6.4' cy='12.4' r='.7' fill='%2312151a' opacity='.16'/%3E %3Ccircle cx='8.6' cy='16.6' r='.6' fill='%2312151a' opacity='.14'/%3E %3Ccircle cx='5.6' cy='7.6' r='.55' fill='%23f6d3b0' opacity='.5'/%3E %3Cpath d='M27.6 20.6 L30.4 17.9' stroke='%2312151a' stroke-width='4.6' stroke-linecap='round'/%3E %3Cpath d='M27.9 20.4 L30.1 18.2' stroke='%236e5537' stroke-width='2.4' stroke-linecap='round'/%3E %3Cpath d='M18.2 30.2 L24.2 17.6 L30.8 24.0 Z' fill='%239aa1a9' stroke='%2312151a' stroke-width='1.15' stroke-linejoin='round'/%3E %3Cpath d='M20.6 28.2 L24.6 19.8' stroke='%23d3d8de' stroke-width='1.1' opacity='.75'/%3E%3C/svg%3E")
    3 2, crosshair;

  /* Kupfer mit Hammer — beim Abreißen. */
  --cursor-abriss: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E %3Cdefs%3E%3ClinearGradient id='m' x1='0' y1='0' x2='0.75' y2='1'%3E %3Cstop offset='0' stop-color='%23e9a877'/%3E %3Cstop offset='.45' stop-color='%23b87333'/%3E %3Cstop offset='1' stop-color='%236f3f1c'/%3E %3C/linearGradient%3E%3C/defs%3E %3Cpath d='M2.6 1.6 L2.6 21.8 L7.7 17.1 L11.1 24.9 L14.6 23.3 L11.2 15.7 L17.9 15.1 Z' fill='url(%23m)' stroke='%2312151a' stroke-width='1.5' stroke-linejoin='round'/%3E %3Cpath d='M4.3 4.2 L4.3 19.0' stroke='%23f6d3b0' stroke-width='1.1' opacity='.8' stroke-linecap='round'/%3E %3Cpath d='M5.2 4.6 L15.0 13.4' stroke='%2312151a' stroke-width='.9' opacity='.26'/%3E %3Ccircle cx='6.4' cy='12.4' r='.7' fill='%2312151a' opacity='.16'/%3E %3Ccircle cx='8.6' cy='16.6' r='.6' fill='%2312151a' opacity='.14'/%3E %3Ccircle cx='5.6' cy='7.6' r='.55' fill='%23f6d3b0' opacity='.5'/%3E %3Cg transform='rotate(-15 24 24)'%3E %3Crect x='18.6' y='17.6' width='11.2' height='5.2' rx='1' fill='%236e747c' stroke='%2312151a' stroke-width='1.3'/%3E %3Crect x='19.7' y='18.5' width='9' height='1.5' rx='.7' fill='%239aa1a9' opacity='.85'/%3E %3Crect x='22.8' y='22.4' width='2.9' height='8.2' rx='.8' fill='%236e5537' stroke='%2312151a' stroke-width='1.15'/%3E %3Cpath d='M24.3 23.6 L24.3 29.6' stroke='%238a6d47' stroke-width='.9' opacity='.8'/%3E %3C/g%3E%3C/svg%3E")
    3 2, crosshair;

  /* Kupfer mit Federkiel — in Eingabefeldern. */
  --cursor-schreiben: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E %3Cdefs%3E%3ClinearGradient id='m' x1='0' y1='0' x2='0.75' y2='1'%3E %3Cstop offset='0' stop-color='%23e9a877'/%3E %3Cstop offset='.45' stop-color='%23b87333'/%3E %3Cstop offset='1' stop-color='%236f3f1c'/%3E %3C/linearGradient%3E%3C/defs%3E %3Cpath d='M2.6 1.6 L2.6 21.8 L7.7 17.1 L11.1 24.9 L14.6 23.3 L11.2 15.7 L17.9 15.1 Z' fill='url(%23m)' stroke='%2312151a' stroke-width='1.5' stroke-linejoin='round'/%3E %3Cpath d='M4.3 4.2 L4.3 19.0' stroke='%23f6d3b0' stroke-width='1.1' opacity='.8' stroke-linecap='round'/%3E %3Cpath d='M5.2 4.6 L15.0 13.4' stroke='%2312151a' stroke-width='.9' opacity='.26'/%3E %3Ccircle cx='6.4' cy='12.4' r='.7' fill='%2312151a' opacity='.16'/%3E %3Ccircle cx='8.6' cy='16.6' r='.6' fill='%2312151a' opacity='.14'/%3E %3Ccircle cx='5.6' cy='7.6' r='.55' fill='%23f6d3b0' opacity='.5'/%3E %3Cpath d='M17.9 31.5 L21.0 29.0 L20.1 31.0 Z' fill='%2312151a'/%3E %3Cpath d='M19.4 30.2 L30.2 18.4 Q29.4 28.2 19.4 30.2 Z' fill='%23e2dccb' stroke='%2312151a' stroke-width='1.15' stroke-linejoin='round'/%3E %3Cpath d='M20.2 29.6 L29.6 19.4' stroke='%23a99f88' stroke-width='.9'/%3E %3Cpath d='M23.4 26.6 L25.4 28.4 M26.6 23.0 L28.2 24.4' stroke='%23a99f88' stroke-width='.8' opacity='.7'/%3E%3C/svg%3E")
    3 2, text;

  /* Die greifende Hand fürs Schieben von Karte und Bildausschnitt.
     ABSICHTLICH der Systemzeiger: "grab" und "grabbing" sind die einzigen
     Zeiger, die jedes Betriebssystem im eigenen Stil zeigt, und ein
     gezeichneter Ersatz wäre hier schlechter als das Original. Ein
     Panzerhandschuh, wie er hier einmal stand, kommt ohnehin nicht mehr
     in Frage. */
  --cursor-hand: grab;
  --cursor-hand-zu: grabbing;
}

/* --- Grundgerüst ---------------------------------------------------------- */

* {
  box-sizing: border-box;
}

html {
  /* Grundmaß der ganzen Oberfläche. Von 17 auf 19 angehoben: Bei 17 px waren
     die kleinen Beschriftungen (0,7 rem = 12 px) auf einem großen Bildschirm
     kaum zu entziffern. Alles in rem wächst mit — deshalb steht die Änderung
     hier und nicht an hundert Einzelstellen. */
  font-size: 19px;
}

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--font-body);
  color: var(--text);
  background-color: var(--stone-900);
  /* rauer Steingrund: zwei weiche Lichtquellen, dazu ein Korn-Overlay */
  background-image:
    radial-gradient(1200px 600px at 20% -10%, rgba(122, 145, 102, 0.06), transparent 60%),
    radial-gradient(900px 500px at 100% 100%, rgba(168, 129, 61, 0.05), transparent 60%);
  background-attachment: fixed;
  cursor: var(--cursor-kupfer);
}

/* Feines Korn über allem — nimmt den digitalen Flachheitseindruck */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.32;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
}

/* --- Typografie ----------------------------------------------------------- */

h1,
h2,
h3 {
  font-family: inherit;
  font-weight: 400;
  color: var(--brass-light);
  letter-spacing: 0.01em;
  text-wrap: balance;
  margin: 0 0 0.6rem;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.6);
}

h1 {
  font-size: 2.5rem;
  line-height: 1.15;
}
h2 {
  font-size: 1.6rem;
  margin-top: 2rem;
  color: var(--brass);
}
h3 {
  font-size: 1.2rem;
}

p {
  line-height: 1.65;
  margin: 0 0 0.9rem;
  max-width: 68ch;
}

a {
  color: var(--brass-light);
  text-decoration: none;
  border-bottom: 1px solid rgba(168, 129, 61, 0.35);
  cursor: var(--cursor-gold);
}
a:hover {
  color: #e3c88a;
  border-bottom-color: var(--brass-light);
}

code {
  font-family: ui-monospace, Consolas, monospace;
  font-size: 0.88em;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.1em 0.35em;
  color: var(--parchment-dark);
  word-break: break-all;
}

.muted {
  color: var(--text-dim);
  font-size: 0.92rem;
}

.error {
  color: var(--fire-light);
}

.eyebrow {
  font-family: var(--font-body);
  font-size: 0.78rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* Zierleiste mit Raute in der Mitte */
.rule {
  border: 0;
  height: 1px;
  margin: 1.6rem 0;
  background: linear-gradient(90deg, transparent, var(--iron) 15%, var(--iron) 85%, transparent);
  position: relative;
  overflow: visible;
}
.rule::after {
  content: "";
  position: absolute;
  left: 50%;
  top: -3px;
  width: 7px;
  height: 7px;
  margin-left: -3.5px;
  background: var(--brass-dark);
  border: 1px solid var(--brass);
  transform: rotate(45deg);
}

/* --- Rahmen und Tafeln ---------------------------------------------------- */

.container {
  position: relative;
  z-index: 2;
  max-width: 780px;
  margin: 0 auto;
  padding: 3rem 1.25rem 4rem;
}
.container.wide {
  max-width: 1140px;
}

.panel {
  position: relative;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.035), transparent 140px), var(--stone-700);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 1.9rem 2.1rem;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.07),
    inset 0 0 60px rgba(0, 0, 0, 0.35),
    0 14px 40px rgba(0, 0, 0, 0.55);
}

/* vier Nieten in den Ecken der Tafel */
.panel::before {
  content: "";
  position: absolute;
  inset: 6px;
  pointer-events: none;
  background-image: radial-gradient(circle, var(--iron-light) 0 1.4px, rgba(0, 0, 0, 0.5) 1.9px, transparent 2.4px);
  background-size: 7px 7px;
  background-repeat: no-repeat;
  background-position:
    0 0,
    100% 0,
    0 100%,
    100% 100%;
}

/* --- Die Urkundentafel --------------------------------------------------------
   Aufnahme in die Lehnsrolle: die erste Seite, die ein neuer Spieler
   ausfüllt. Sie war zuletzt ein nacktes Formular in einem grauen Kasten und
   sah damit aus wie die Einstellungen eines Programms, nicht wie der Eintritt
   in ein Lehen. Hier bekommt sie einen Kopf, etwas Luft und einen wärmeren
   Grund — dieselben Mittel, die Panel und Zierleiste ohnehin schon kennen,
   nur zusammengestellt. */
.panel.urkunde {
  max-width: 30rem;
  margin: 0 auto;
  padding: 2.2rem 2.4rem 2rem;
  /* Ein Hauch Kerzenschein von oben, wie auf der Charakterseite. */
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(224, 168, 82, 0.075), transparent 62%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.035), transparent 140px),
    var(--stone-700);
}
.panel.urkunde .eyebrow {
  text-align: center;
}
.urkunde-titel {
  font-family: var(--font-display);
  font-size: 2.1rem;
  text-align: center;
  margin: 0.35rem 0 0;
  color: var(--brass-light);
}
.urkunde-vorspann {
  text-align: center;
  margin: 0.7rem auto 0;
  max-width: 26rem;
}
/* Alles auf die Mittelachse. Das Grundformular ist links ausgerichtet und auf
   340 px gedeckelt (siehe `form` weiter oben) — in einer Tafel, deren Kopf,
   Titel und Vorspann mittig stehen, saß der Eingabeblock damit sichtbar
   daneben. Hier bekommt er dieselbe Achse wie alles darüber. */
.panel.urkunde form {
  margin: 0.2rem auto 0;
  width: 100%;
  max-width: 22rem;
}
/* NUR den Text mittig, NICHT die Kinder ausrichten: `label` ist eine
   Flex-Spalte, und `align-items: center` ließe das Eingabefeld darin auf
   seine Inhaltsbreite schrumpfen. Genau das war der Fehler — die Felder
   standen 238 px breit unter einem 418 px breiten Knopf, und dieser
   Treppenrand ist es, der einen sonst mittigen Block unaufgeräumt aussehen
   lässt. Ohne die Zeile gilt wieder `stretch`, und alles hat dieselbe
   Kante. */
.panel.urkunde label {
  text-align: center;
}
/* Auch der eingegebene Text steht mittig: Ein linksbündiger Schlüssel in
   einem sonst durchweg mittig gesetzten Blatt fällt sofort als Bruch auf. */
.panel.urkunde input[type="text"],
.panel.urkunde input[type="password"] {
  text-align: center;
}
.panel.urkunde button[type="submit"] {
  width: 100%;
  margin-top: 0.5rem;
  padding: 0.62rem 1rem;
  font-size: 1rem;
}
.panel.urkunde .txt-klein {
  text-align: center;
}
/* Der Zugangsschlüssel ist eine KENNUNG, kein Wort: gesperrt und in
   Versalien gesetzt, damit man Verwechslungen (O/0, I/l) beim Abtippen
   bemerkt. Die Umsetzung in Großbuchstaben ist rein optisch — der Server
   normalisiert ohnehin selbst (normalisiereAccessKey). */
input.schluesselfeld {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 1.02rem;
}
/* Nebenbedingungen gehören nicht in die Feldbeschriftung: "Losungswort
   (mind. 8 Zeichen)" liest sich als Name des Feldes, obwohl die Klammer nur
   eine Auflage ist. Klein und gedämpft daneben bleibt beides lesbar. */
.feldhinweis {
  text-transform: none;
  letter-spacing: 0.04em;
  font-size: 0.72rem;
  color: var(--text-dim);
}

/* Pergament-Einleger für Urkunden, Chronik, Listen */
.parchment {
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255, 255, 255, 0.28), transparent 70%),
    linear-gradient(180deg, var(--parchment), var(--parchment-dark));
  color: var(--ink);
  border: 1px solid #8d7d5c;
  border-radius: 2px;
  padding: 1.1rem 1.3rem;
  box-shadow:
    inset 0 0 30px rgba(120, 96, 55, 0.35),
    0 2px 6px rgba(0, 0, 0, 0.4);
}
.parchment .muted {
  color: var(--ink-soft);
}
.parchment a {
  color: #6a4c1e;
  border-bottom-color: rgba(106, 76, 30, 0.4);
}

/* --- Kopfzeile der Seiten ------------------------------------------------- */

.crest {
  text-align: center;
  margin-bottom: 2.1rem;
}
.crest .sigil {
  display: block;
  margin: 0 auto 0.4rem;
}
/* Der Schriftzug in der GEBROCHENEN Schrift des Spiels (--font-display,
   Unifraktur) statt in der Brotschrift. Er ist das erste, was ein neuer
   Spieler sieht, und stand bis dahin in derselben Antiqua wie jeder
   Fließtext — der Name trug das Mittelalter also als einziges Element nicht
   mit. Der Wahlspruch darunter bleibt bewusst in der Antiqua: Zwei gebrochene
   Zeilen übereinander liest niemand mehr, und die gesperrten Versalien sind
   genau der ruhige Gegenpart, der den Schriftzug wirken lässt. */
.crest h1 {
  font-family: var(--font-display);
  /* 3,6rem statt der früheren 3,1rem — aber nicht mehr: Eine gebrochene
     Schrift trägt bei gleicher Punktgröße spürbar breiter und schwerer als
     die Antiqua davor, und denselben Kopf tragen auch Werkzeugseiten
     (Sprite-Editor, Startbild). Dort soll der Schriftzug nicht die halbe
     Seite einnehmen. */
  font-size: 3.6rem;
  line-height: 1;
  margin: 0;
  /* Gebrochene Schriften stehen von Haus aus eng; ein Hauch Sperrung nimmt
     ihnen das Gedrängte, ohne sie auseinanderfallen zu lassen. */
  letter-spacing: 0.02em;
  color: var(--brass-light);
  /* Der warme Schein dahinter: Der Titel soll aussehen, als läge Kerzenlicht
     darauf — dieselbe Handschrift wie der Saal der Charaktererstellung. */
  text-shadow:
    0 1px 0 rgba(0, 0, 0, 0.75),
    0 0 24px rgba(224, 168, 82, 0.22),
    0 0 60px rgba(224, 168, 82, 0.1);
}
.crest .motto {
  font-size: 0.85rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--text-dim);
  /* Die automatischen Seitenränder sind das Entscheidende: Absätze tragen
     global `max-width: 68ch` (siehe `p` weiter oben), und dieser Kasten war
     damit schmaler als der Kopf, aber linksbündig darin. Der Text stand also
     mittig in einem Kasten, der selbst aus der Mitte gerückt war — sichtbar
     als Jahreszeile und Zierstrich, die beide gut hundert Pixel zu weit
     links saßen. `text-align: center` allein konnte das nie beheben. */
  margin: 0.55rem auto 0;
}
/* Eine schmale Zierleiste unter dem Wahlspruch — zwei Striche, die in der
   Mitte auf eine Raute zulaufen. Reines CSS, kein Bild: Sie schließt den Kopf
   ab, damit er nicht ohne Übergang in die Tafel fällt. */
.crest .motto::after {
  content: "";
  display: block;
  width: 190px;
  height: 7px;
  margin: 0.9rem auto 0;
  background:
    linear-gradient(90deg, transparent, var(--brass-dark) 22%, var(--brass-dark) 78%, transparent) center / 100% 1px no-repeat,
    linear-gradient(45deg, transparent 46%, var(--brass) 46% 54%, transparent 54%) center / 7px 7px no-repeat;
  opacity: 0.85;
}

nav.wegweiser {
  display: flex;
  align-items: center;
  gap: 1.2rem;
  margin-bottom: 1.4rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--iron);
  font-size: 0.9rem;
}
nav.wegweiser a {
  border-bottom: none;
}
nav.wegweiser form {
  display: inline;
  margin-left: auto;
}

/* --- Bedienelemente ------------------------------------------------------- */

form {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  max-width: 340px;
}

label {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}

input[type="text"],
input[type="password"] {
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--text);
  background: #14171a;
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.55rem 0.7rem;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.55);
  cursor: var(--cursor-schreiben);
}

/* Formularfelder bringen ihren Zeiger aus dem Browser mit, und der schlägt
   das geerbte Kupfer vom <body>. Ohne diesen Block stünde über Kästchen,
   Reglern und Auswahllisten wieder der blanke Systempfeil — mitten in einer
   Oberfläche, die sonst durchweg kupfern ist. Genauere Regeln weiter unten
   (etwa der Musikregler im Kopfband) gelten weiterhin. */
input[type="number"],
input[type="search"],
input[type="email"],
textarea {
  cursor: var(--cursor-schreiben);
}
label,
option,
select,
summary,
input[type="checkbox"],
input[type="radio"],
input[type="range"],
input[type="color"],
input[type="file"],
input[type="submit"],
input[type="button"] {
  cursor: var(--cursor-gold);
}

input:focus {
  outline: none;
  border-color: var(--brass);
  box-shadow:
    inset 0 2px 5px rgba(0, 0, 0, 0.55),
    0 0 0 2px rgba(168, 129, 61, 0.22);
}
input::placeholder {
  color: #6e685d;
}

button,
.btn {
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: #f2e8d4;
  background: linear-gradient(180deg, #3b424a, #262b31);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  padding: 0.5rem 1.15rem;
  width: fit-content;
  cursor: var(--cursor-gold);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -2px 6px rgba(0, 0, 0, 0.4),
    0 2px 3px rgba(0, 0, 0, 0.4);
  transition: border-color 0.12s, background 0.12s, transform 0.06s;
}
button:hover,
.btn:hover {
  border-color: var(--brass);
  background: linear-gradient(180deg, #464e58, #2c3239);
}
button:active,
.btn:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.55);
}
button:focus-visible,
a:focus-visible,
input:focus-visible {
  outline: 2px solid var(--brass-light);
  outline-offset: 2px;
}

button.gefahr {
  border-color: var(--blood);
  background: linear-gradient(180deg, #52302a, #331d19);
  color: #f0d5c8;
}
button.gefahr:hover {
  border-color: #b8543c;
  background: linear-gradient(180deg, #63392f, #3d211b);
}

button.schlicht {
  background: none;
  border: none;
  box-shadow: none;
  color: var(--text-dim);
  padding: 0;
  font-weight: 400;
  font-size: 0.9rem;
  text-decoration: underline;
  text-decoration-color: rgba(146, 139, 125, 0.4);
}
button.schlicht:hover {
  color: var(--brass-light);
  background: none;
}

/* --- Tabellen als Register ------------------------------------------------ */

table {
  border-collapse: collapse;
  width: 100%;
  margin-top: 0.8rem;
  font-size: 0.95rem;
}
th {
  text-align: left;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--brass-dark);
  white-space: nowrap;
}
td {
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid rgba(59, 65, 74, 0.7);
  vertical-align: top;
  font-variant-numeric: tabular-nums;
}
tbody tr:last-child td {
  border-bottom: none;
}
tbody tr:hover td {
  background: rgba(168, 129, 61, 0.06);
}

.parchment th {
  color: #6a4c1e;
  border-bottom-color: rgba(106, 76, 30, 0.45);
}
.parchment td {
  border-bottom-color: rgba(106, 76, 30, 0.2);
}
.parchment tbody tr:hover td {
  background: rgba(106, 76, 30, 0.07);
}

.tabelle-scroll {
  overflow-x: auto;
}

/* Verstorbene Bewohner in der Liste */
tr.tot td {
  opacity: 0.5;
  text-decoration: line-through;
}

/* ===========================================================================
   Spiel-HUD (PixiJS-Ansicht)
   =========================================================================== */

body.spiel {
  overflow: hidden;
  height: 100vh;
  /* Soll sich wie ein Spiel anfassen, nicht wie eine Webseite: kein
     Markieren beim Ziehen über die Karte, keine Lupe/Auswahl auf dem HUD,
     kein Bild-Wegziehen. Eingabefelder bleiben ausgenommen (weiter unten). */
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}
body.spiel img {
  -webkit-user-drag: none;
  user-select: none;
}
/* Wo doch getippt wird, muss Markieren weiter gehen */
body.spiel input,
body.spiel textarea {
  user-select: text;
  -webkit-user-select: text;
}
body.spiel::before {
  opacity: 0.18;
}

#game {
  position: absolute;
  inset: 0;
  cursor: var(--cursor-kupfer);
  /* Der Browser darf Wischen und Aufziehen nicht selbst auswerten — beides
     gehört der Burgansicht (schieben und zoomen, siehe main.ts). Sonst
     scrollt am Handy die Seite, statt dass sich die Karte bewegt. */
  touch-action: none;
}
/* Zeiger steht über einem Gebäude (main.ts setzt die Klasse aus demselben
   Treffertest, den auch der Klick benutzt). Steht VOR bauen/abreissen: dort
   soll das Werkzeug in der Hand bleiben, auch über einem Haus. */
#game.zeigen {
  cursor: var(--cursor-gold);
}
#game.bauen {
  cursor: var(--cursor-bauen);
}
#game.abreissen {
  cursor: var(--cursor-abriss);
}
#game canvas {
  display: block;
}

.hud {
  position: absolute;
  z-index: 10;
  pointer-events: none;
}
.hud > * {
  pointer-events: auto;
}

/* Kopfband: Eisenleiste mit Messingkante */
#topbar {
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  /* GETRENNTE Abstände, und das ist der eigentliche Hebel gegen ein zu hohes
     Kopfband: `gap` gilt für BEIDE Richtungen, also auch zwischen den Zeilen,
     sobald die Leiste umbricht (flex-wrap unten). Gemessen waren das 28 px
     Luft zwischen Titelzeile und Knopfreihe — mehr als die Polsterung oben und
     unten zusammen, und für nichts: Waagerecht brauchen Name, Datum und
     Wegweiser diesen Abstand, senkrecht stehen sie ohnehin schon in eigenen
     Zeilen.

     Umbrochen wird vor allem in der WERKSTATT: Dort verlängert das
     Entwicklermodus-Abzeichen den Titel um gut 200 px (siehe .title unten).
     Auf MAIN steht das Band einzeilig, dort ändert der Zeilenabstand nichts —
     die schmalere Polsterung darunter wirkt aber auf beiden Ständen. */
  column-gap: 1.5rem;
  row-gap: 0.3rem;
  flex-wrap: wrap;
  /* Wieder so schmal wie ganz am Anfang (0.45rem/1rem, Commit 8a5f5ed) — und
     seit 08/2026 noch etwas schmaler (0.3rem). Zwischendurch stand hier
     0.65rem/1.1rem — mit der Begründung, das Kopfband trage die doppelt großen
     Vorratsembleme und die brauchten Luft. Die Embleme sind längst nach unten
     gezogen (Vorratsleiste), der Grund ist also weggefallen; die Polsterung
     war nur geblieben. Das Kopfband hält jetzt nur noch Name, Datum und
     Wegweiser — dafür genügt eine dünne Leiste, und die Burg bekommt die
     Bildhöhe zurück. */
  padding: 0.3rem 1rem;
  background: linear-gradient(180deg, rgba(34, 38, 43, 0.96), rgba(18, 20, 23, 0.96));
  border-bottom: 1px solid var(--brass-dark);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
}
#topbar .title {
  font-family: var(--font-display);
  /* Der Burgname ist das höchste Ding seiner Zeile und bestimmt damit die
     Bandhöhe mit — eine dünnere Leiste bekommt man nicht über die Polsterung
     allein. Stand ursprünglich auf 1.5rem; 1.32rem nimmt gut vier Pixel und
     bleibt in der Bruchschrift noch klar der Titel gegenüber allem daneben
     (Datum 0.95rem, Knöpfe geerbt). */
  font-size: 1.32rem;
  color: var(--brass-light);
  line-height: 1.1;
  /* Kein Kürzen mit Auslassungspunkten, obwohl es naheliegt: Bei
     `flex-wrap: wrap` (siehe #topbar) bricht Flexbox die Zeile UM, statt ein
     Kind unter seinen Inhalt zu schrumpfen — `min-width: 0` und
     `text-overflow` blieben also wirkungslos und schnitten obendrein das
     Entwicklermodus-Abzeichen ab, das mit im Titel sitzt.

     Gemessen: Im Spiel steht das Band einzeilig (53 px). Zweizeilig wird es
     allein in der WERKSTATT, wo das Abzeichen den Titel um gut 200 px
     verlängert — dort ist die zweite Zeile hinnehmbar, und die Tafeln hängen
     sich ohnehin an die gemessene Höhe (--kopfband-hoehe). */
}
#topbar .season {
  font-size: 0.95rem;
  /* Messing statt Moosgruen (22.08.2026). Das Datum steht neben der Uhr, und
     die ist messingfarben — zwei Zeitangaben nebeneinander in zwei Farben
     lasen sich als zwei verschiedene Dinge. */
  color: var(--brass-light, #cca75e);
  letter-spacing: 0.04em;
}

/* Das Datum traegt die Zeitrechnungs-Tafel (client/src/tagesuhr.ts). */
#topbar .season.datum-erklaert {
  position: relative;
  cursor: help;
}
/* In der Burgansicht bleibt der Platz meist leer (ui.ts schreibt nur noch
   das Festhalten-Abzeichen hinein, und das nur im Entwicklermodus) — ohne
   diese Regel risse die leere Spanne trotzdem eine Lücke neben den Burgnamen,
   weil #topbar sie über den flex-gap mitzählt. Auf der Karte bleibt die
   Spanne stets gefüllt (Jahr, Datum) und die Regel greift dort nie. */
#topbar .season:empty {
  display: none;
}
#topbar .links {
  margin-left: auto;
  display: flex;
  gap: 0.5rem;
  align-items: center;
  font-size: 0.9rem;
  /* EINE Zahl für die ganze Reihe — Bauen, Landkarte, Einstellungen, Tickuhr
     UND die Chips für Einfluss, Militär und Stimmung.

     Vorher hatte jedes Stück seine eigene Polsterung, und die Höhen fielen
     entsprechend auseinander: Knöpfe 38 px, Tickuhr 37 px, Chips 32 px — drei
     Maße in einer Reihe, die nebeneinander stehen und gleich aussehen sollen.
     Das war nicht falsch gerechnet, sondern gar nicht gerechnet: Die 32 der
     Chips entstehen aus Emblemhöhe plus Polster plus Rahmen, die 38 der Knöpfe
     aus Zeilenhöhe plus Polster plus Rahmen. Zwei Rechenwege treffen sich nie
     von allein, und jede spätere Änderung an Schrift oder Emblem verschiebt
     sie neu gegeneinander.

     Mit einer gemeinsamen Höhe ist das strukturell erledigt: Was hier steht,
     gilt für alle. Möglich, weil ganz oben `* { box-sizing: border-box }`
     steht — Polster und Rahmen zählen also INNERHALB dieser Höhe, und keiner
     der Beteiligten sprengt sie durch sein eigenes Polster. */
  --kopfreihe-hoehe: 1.7rem;
}
/* Alle Bedienstücke der Reihe auf dieselbe Höhe. Die Polsterungen bleiben
   stehen — sie machen weiter den waagerechten Abstand und zentrieren den
   Inhalt; nur die HÖHE bestimmen sie nicht mehr.

   Der AVATAR gehört ausdrücklich dazu, obwohl er kein Knopf im engeren Sinn
   ist: Er stand als einziges Stück auf 40 px und bestimmte damit allein die
   Höhe der ganzen Zeile — die übrigen sechs auf 32 zu bringen hätte die Reihe
   also weder gleichmäßig noch niedriger gemacht. Sein Wappen schrumpft dafür
   mit (siehe .kopf-wappen-rahmen). */
#topbar .links .kopfknopf,
#topbar .links .res,
#topbar .links .spielername {
  height: var(--kopfreihe-hoehe);
}
/* --- Die Knöpfe des Kopfbands -----------------------------------------------
   Landkarte, Chronik und Einstellungen tun dasselbe: eine andere Ansicht
   öffnen. Sie tragen deshalb EINE gemeinsame Form statt drei ähnlicher —
   vorher waren zwei davon Links mit Wegzeichen und einer ein Knopf ohne, und
   sie standen nur zufällig ungefähr gleich da.

   Die Wegzeichen sind weg, weil sie bei 12 Pixeln nichts beitrugen: Karte,
   Buch und Rad waren kaum auseinanderzuhalten, und das ausgeschriebene Wort
   daneben sagte ohnehin alles.

   Ein <a> und ein <button> sehen von Haus aus verschieden aus (Schrift,
   Polsterung, Zeilenhöhe). Deshalb wird hier ALLES gesetzt, was sie
   unterscheidet — sonst fällt die Gleichheit beim nächsten Browser wieder
   auseinander.

   Alle vier sind TASTEN: eine gefasste Platte mit Messingrand, nicht
   unterstrichener Text. Vorher waren es vier flache Wörter mit einem Strich
   darunter — und weil die allgemeine Knopfregel (button, .btn) ihren
   box-shadow vererbt, dieser Block ihn aber nie abglich, trugen ausgerechnet
   die beiden <button> (Botenstube, Einstellungen) einen zarten Plattenschein,
   die beiden <a> (Landkarte, Chronik) nicht. Genau daran sah man, dass zwei
   davon Knöpfe sein wollten und zwei nicht. Jetzt tragen alle vier dieselbe
   Fassung, ausdrücklich gesetzt statt geerbt. */
#topbar .links .kopfknopf {
  display: inline-flex;
  align-items: center;
  margin: 0;
  /* Senkrecht auf die Höhe von Einfluss/Militär/Stimmung daneben gebracht
     (deren 32-Pixel-Embleme, siehe .kopf-einfluss-militaer/.moralfeld) — nur
     das senkrechte Polster ist gewachsen, die Schrift bleibt, wie sie war. */
  padding: 0.33rem 0.45rem;
  background: linear-gradient(180deg, rgba(59, 66, 74, 0.85), rgba(38, 43, 49, 0.85));
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  color: var(--brass-light);
  font: inherit;
  line-height: 1.35;
  text-decoration: none;
  white-space: nowrap;
  cursor: var(--cursor-gold);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -2px 6px rgba(0, 0, 0, 0.4),
    0 2px 3px rgba(0, 0, 0, 0.4);
  /* Auch das Aufleuchten muss gleich sein: Der <button> erbte 0,12 s von der
     allgemeinen Knopfregel, die beiden <a> schalteten hart um. Nebeneinander
     fällt das auf. */
  transition: border-color 0.12s, background 0.12s, color 0.12s;
}
/* --- DIE ZEICHENREIHE -------------------------------------------------------

   Acht gleich gebaute Bildknoepfe (24.08.2026): Rangliste, Botenstube, Bauen,
   Landkarte, Produktion, Diplomatie, Chronik, Einstellungen. Sie tragen
   dieselbe .kopfknopf-Form wie vorher die Wortknoepfe — nur ihr Inhalt ist ein
   Zeichen statt eines Wortes, und das Polster wird darum quadratisch.

   28 PIXEL, und die Zahl ist der ganze Punkt. An dieser Stelle standen bis
   08/2026 schon einmal Piktogramme, und sie wurden abgeschafft; im Code stand
   der Grund: "Bei 12 Pixeln waren Karte, Buch und Rad kaum auseinanderzuhalten."
   Das stimmte. Auf 28 Pixeln ist ein Zahnrad ein Zahnrad. Wer die Zahl wieder
   senkt, holt sich das alte Problem zurueck — sie steht deshalb als Variable
   hier und nicht verstreut in acht Regeln. */
#topbar .links {
  --kopfzeichen: 28px;
}
#topbar .links .zeichenknopf {
  /* Quadratisch statt breit: Ein Wortknopf braucht seitlich Luft fuer die
     Schrift, ein Zeichen sitzt mittig. */
  padding: 0.28rem;
  justify-content: center;
}
.kopfzeichen {
  width: var(--kopfzeichen);
  height: var(--kopfzeichen);
  display: block;
  flex: none;
  /* Voll deckend in Messing — gedimmt wirkten die Strichzeichnungen grau
     statt golden. Dieselbe Entscheidung wie bei .navicon. */
  color: var(--brass-light);
}
/* Die Strichzeichnungen. Die Sprites bringen ihre Farbe selbst mit; diese
   Regeln greifen nur bei den Zeichen, die noch als SVG in kopfleiste.js
   stehen, bis ihr Sprite gewuerfelt ist. */
svg.kopfzeichen path,
svg.kopfzeichen circle {
  fill: none;
  stroke: currentColor;
  /* 28px Anzeige aus 24er-Zeichenflaeche = Faktor 1,167. 1,5 x 1,167 = 1,75
     Geraetepixel — knapp ueber der Kante, damit der Strich nicht ausduennt.
     (Bei .navicon liegt die Rechnung genau auf 1; dort ist die Flaeche
     kleiner und ein halber Pixel faellt auf.) */
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#topbar .links .zeichenknopf:hover .kopfzeichen {
  color: #e3c88a;
}
/* Der offene Einstellknopf haelt sein Zeichen hell, solange das Menue steht —
   sonst sieht man dem Kopfband nicht an, welcher Knopf gerade aufgeklappt
   ist, wenn der Zeiger schon im Menue steht. */
#topbar .links .zeichenknopf[aria-expanded="true"] .kopfzeichen {
  color: #e3c88a;
}

/* DIE ZOOMSTUFEN im Kopfband (`data-zoom="1"`, siehe kopfleiste.js).

   MITTIG, und darum absolut gesetzt: Das Kopfband ist ein Flexkasten aus
   Titel, Datum und der Knopfreihe rechts — in dessen Fluss laege "die Mitte"
   dort, wo der Titel gerade endet, also bei jedem Burgnamen woanders. Sie
   haengt sich stattdessen an die Mitte des BANDES, wie es die alte,
   freistehende Leiste tat (frueher `#kopf` in 3d.html).

   `pointer-events` muss ausdruecklich zurueck: `.hud` schaltet sie ab und
   gibt sie nur den direkten Kindern zurueck — ein absolut gesetztes Kind ist
   zwar eines, aber die Regel `.hud > *` greift vor der eigenen. */
#topbar .kopfzoom {
  position: absolute;
  left: 50%;
  top: 0;
  transform: translateX(-50%);
  height: 100%;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  pointer-events: auto;
  user-select: none;
}
#topbar .kopfzoom .stufe {
  min-width: 3.2em;
  text-align: center;
  color: var(--brass-light);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
#topbar .kopfzoom .kopfknopf.zoomknopf {
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 0.2rem 0.3rem;
  background: linear-gradient(180deg, rgba(59, 66, 74, 0.85), rgba(38, 43, 49, 0.85));
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  color: var(--brass-light);
  font: inherit;
  cursor: var(--cursor-gold);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.14),
    inset 0 -2px 6px rgba(0, 0, 0, 0.4),
    0 2px 3px rgba(0, 0, 0, 0.4);
  transition: border-color 0.12s, background 0.12s;
}
#topbar .kopfzoom .kopfknopf.zoomknopf:hover:not(:disabled) {
  border-color: var(--brass);
  background: linear-gradient(180deg, rgba(70, 78, 88, 0.9), rgba(44, 50, 57, 0.9));
}
#topbar .kopfzoom .kopfknopf.zoomknopf img {
  display: block;
  width: 16px;
  height: 16px;
  image-rendering: pixelated;
}
#topbar .kopfzoom .kopfknopf.zoomknopf:disabled {
  opacity: 0.4;
  cursor: default;
}

#topbar .links .kopfknopf:hover,
#topbar .links .kopfknopf.offen {
  border-color: var(--brass);
  background: linear-gradient(180deg, rgba(70, 78, 88, 0.9), rgba(44, 50, 57, 0.9));
  color: #e8d5a8;
}
/* Der <button> senkt sich beim Drücken (allgemeine Knopfregel). Damit sich die
   beiden <a> genauso anfühlen, steht es hier für alle vier. */
#topbar .links .kopfknopf:active {
  transform: translateY(1px);
}
/* EINGESCHALTET — bisher nur für "Bauen" gebraucht, den einzigen Umschalter
   in dieser Reihe: Die übrigen Knöpfe öffnen etwas und sind danach fertig,
   der Baumodus dagegen bleibt an, bis man ihn wieder verlässt. Ohne dieses
   Merkmal sähe der Knopf im Baumodus genauso aus wie davor, und man hätte
   keinen Anhalt, wie man wieder herauskommt.

   Kräftiger als :hover, damit "an" und "Zeiger darüber" nicht zu verwechseln
   sind — deshalb der Messingrahmen samt Schein statt nur einer helleren
   Fläche. */
#topbar .links .kopfknopf.aktiv {
  border-color: var(--brass);
  background: linear-gradient(180deg, rgba(112, 88, 40, 0.95), rgba(74, 58, 26, 0.95));
  color: #f2e2b8;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    inset 0 -2px 6px rgba(0, 0, 0, 0.45),
    0 0 6px rgba(168, 129, 61, 0.5);
}

/* Der Wappenknopf ist seit 24.08.2026 ein ZEICHENKNOPF wie die anderen acht:
   Form, Rahmen, Polster und Maße kommen aus `#topbar .links .kopfknopf` und
   `.zeichenknopf`. Was hier übrig bleibt, ist nur, was ihn von ihnen
   unterscheidet — der Anker für die weggeschnittene Namensspanne.

   Was hier stand und weg musste: `background: none`, `border: none`,
   `padding`, `font-size`. Alles Aufhebungen der Knopfform, aus der Zeit, als
   der Knopf den Namen in Fraktur trug und keinen Rahmen hatte. Sie blieben
   ohne Wirkung (die Reihenregel ist spezifischer), aber eine Regel, die still
   verliert, ist eine Falle für den Nächsten: Er ändert sie und sieht nichts
   passieren. */
.spielername {
  /* Anker für die weggeschnittene Namensspanne (.nur-vorleser, position:absolute). */
  position: relative;
}
/* Das Wappen im Kopfband. Höhe an die Schrift gekoppelt statt fest in Pixeln:
   So bleibt es auf jeder Zoomstufe des Browsers auf einer Linie mit dem Namen.
   Harte Kanten, wie überall im Spiel — ein weich skaliertes Wappen sähe
   zwischen den Pixelbildern nach Fremdkörper aus.

   server/src/wappen.ts liefert ein einfaches QUADRAT in der Schildfarbe —
   und genau als Quadrat steht es auch hier, kein Schild-Umriss mehr (der lief
   früher über clip-path, s. Karten-Marker: dort ist das Wappen ebenfalls das
   schlichte Quadrat, ohne Zuschnitt). Die äußere Spanne liefert die
   Messingfläche, das Bild sitzt darin auf einem schmalen Innenabstand —
   das IST der Rahmen, kein eigenes Rahmenbild nötig. */
/* --- Die Wertegruppe --------------------------------------------------------
   Geld, Einfluss, Militaer und Stimmung sind EIN Posten mit vier Zahlen, nicht
   vier Posten. Standen sie im gleichmaessigen Zeilenabstand zwischen den
   Zeichenknoepfen, las sich die Reihe als dreizehn gleichrangige Stuecke — und
   dabei sind die vier links etwas anderes als die neun rechts: Zahlen, die man
   liest, gegen Knoepfe, die man drueckt.

   Innen derselbe Abstand wie ueberall in der Reihe, aussen das Doppelte. Der
   Bruch ist die ganze Aussage; darum steht er als eigene Zahl und nicht als
   Vielfaches, das jemand versehentlich mit der Reihe mitzieht. */
#topbar .links .kopfwerte {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* Zusaetzlich zum Zeilenabstand von 0,5rem — zusammen also 1,25rem. */
  margin-right: 0.75rem;
}

/* --- Das Wappen: derselbe Knopf, aber randvoll ------------------------------
   DIE FASSUNG IST DIE DER ANDEREN, DER INHALT FUELLT SIE GANZ. Rahmen,
   Haarlinie, Eckradius, Aussenmasse, Aufleuchten und Absenken beim Druecken
   kommen unveraendert aus `#topbar .links .kopfknopf` und `.zeichenknopf` —
   angefasst wird hier nur das POLSTER: Es faellt weg, damit der Schildgrund
   bis an die Linie heranlaeuft statt als 28-px-Kaertchen in der Mitte zu
   sitzen. Ein Wappen ist eine Flaeche, kein Piktogramm.

   DIE BREITE MUSS DESHALB GESETZT WERDEN. Bei den uebrigen entsteht sie aus
   Zeichen plus Polster plus Rahmen; ohne Polster faellt der Knopf auf die
   Breite seines Inhalts zusammen und stuende schmaler in der Reihe. Die
   Rechnung unten ist dieselbe, die die anderen von selbst ergeben — nicht die
   gemessene Zahl abgeschrieben, sonst laufen sie beim naechsten Griff an
   `--kopfzeichen` auseinander.

   `overflow: hidden` wegen der 2-px-Ecken: Ohne ihn stiessen die Bildecken
   ueber die abgerundete Platte hinaus.

   EIN IRRWEG, DEN NIEMAND ZWEIMAL GEHEN MUSS: Zwischendurch stand hier gar
   kein Rahmen, und die Meldung darauf lautete, der Rand sei zu dick. Er war
   messtechnisch derselbe wie nebenan (1px, dieselbe Farbe) — nur sah er
   dicker aus, weil eine dunkle Haarlinie an einem hellen Wappen hervortritt,
   waehrend sie auf der dunklen Platte der Nachbarn fast verschwindet. Wer an
   dieser Stelle je wieder "der Rand ist zu dick" hoert, MISST ihn zuerst: Die
   Antwort liegt fast sicher im Kontrast und nicht in der Breite. */
#topbar .links .spielername {
  padding: 0;
  width: calc(var(--kopfzeichen) + 0.56rem + 2px);
  overflow: hidden;
}
/* DASSELBE AUFLEUCHTEN, AUF DEM EINZIGEN WEG, DER HIER OFFEN IST.
   Die Reihenregel (#topbar .links .kopfknopf:hover) hellt Rand UND Platte auf.
   Der Rand kommt hier an, die Platte nicht: Sie liegt vollstaendig unter dem
   Wappen. Ein Knopf, bei dem sich nur eine Haarlinie faerbt, waehrend die acht
   daneben aufleuchten, fuehlt sich matter an als sie. Darum hellt sich hier
   das BILD auf — kein zweites Ausdrucksmittel, sondern dasselbe an der
   Stelle, an der es zu sehen ist. */
#topbar .links .spielername:hover .kopf-wappen {
  filter: brightness(1.14);
}
.kopf-wappen-rahmen {
  display: inline-flex;
  flex: 0 0 auto;
  /* GENAU SO GROSS WIE JEDES ANDERE ZEICHEN DER REIHE (24.08.2026, auf
     Ansage). Das Wappen ist der neunte Knopf im Kopfband, und ein Knopf, der
     aus der Reihe fällt, liest sich als Fehler — auch wenn er der wichtigste
     ist.

     Darum `--kopfzeichen` statt einer eigenen Zahl: Wer die Reihe später von
     28 auf 24 stellt, stellt das Wappen mit. Der Rückfall (28px) steht dabei
     nicht als Sicherheitsnetz da, sondern weil `.kopf-wappen-rahmen` auch
     außerhalb von `#topbar .links` stehen könnte, wo die Variable nicht gilt.

     Vorher waren es 1.15em, gekoppelt an die Schriftgröße des Knopfs — das
     ergab 26,7 px, und die Messingfassung ringsum machte daraus optisch ein
     größeres Stück als die 28-px-Sprites daneben. Die Fassung ist weg: Die
     anderen acht Zeichen haben auch keine, und der Knopfrahmen ist der
     gemeinsame Rahmen. */
  /* Fuellt den Knopf INNERHALB seines Rahmens ganz aus — die Breite gibt
     `#topbar .links .spielername` vor, die Hoehe `--kopfreihe-hoehe`. Kein
     aspect-ratio: Der Knopf ist breiter als hoch, ein Quadrat darin liesse
     links und rechts einen Streifen Platte stehen. Das Wappenbild ist
     quadratisch und wird per `object-fit: cover` beschnitten statt verzerrt
     (siehe .kopf-wappen). */
  height: 100%;
  width: 100%;
  padding: 0;
}
/* Bevor das Profil geladen ist (Bild noch [hidden]) bliebe sonst eine leere
   Messingscherbe im Knopf stehen. */
.kopf-wappen-rahmen:has(.kopf-wappen[hidden]) {
  display: none;
}
.kopf-wappen {
  display: block;
  height: 100%;
  width: 100%;
  object-fit: cover;
  image-rendering: pixelated;
}
.kopf-wappen[hidden] {
  display: none;
}
/* Das Aufleuchten kommt aus der Reihenregel (#topbar .links .kopfknopf:hover) —
   ein eigenes Unterstreichen wäre der einzige Knopf mit zwei Rückmeldungen. */
/* NUR FÜR VORLESEPROGRAMME — im Dokument, aber nicht auf dem Schirm.
   Gebraucht für den Spielernamen im Kopfband: sichtbar ist dort seit 08/2026
   allein das Wappen, doch der Knopf braucht eine Beschriftung (sonst ist er
   für ein Vorleseprogramm ein stummer Knopf), und zwei Stellen schreiben in
   das Feld hinein (kopfleiste.js, client/src/ui.ts).

   NICHT display:none und nicht visibility:hidden — beide nehmen den Text
   auch den Vorleseprogrammen weg, und genau der soll bleiben. Das Muster
   unten (1 Pixel, weggeschnitten, aus dem Fluss genommen) ist der übliche
   Weg; position:absolute sorgt zugleich dafür, dass die Spanne im Flex-Knopf
   keine Lücke neben dem Wappen hinterlässt. */
.nur-vorleser {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Noch kein Profil geladen: sichtbar, aber ohne Versprechen. */
.spielername.leer {
  color: var(--text-dim);
  cursor: var(--cursor-kupfer);
  pointer-events: none;
}

/* Einfluss und Militärstärke im Kopfband (kopfleiste.js) — dieselben .res-
   Embleme wie in der Vorratsleiste, hier nur zu zweit und ohne deren
   flex-wrap/justify-Regeln, die für die lange Warenliste unten gedacht sind.
   Bleiben in ihrer vollen Größe (32-Pixel-Embleme, 1,1rem) — die Knöpfe
   daneben (Bauen/Landkarte/Einstellungen/Avatar) sind stattdessen auf DIESE
   Höhe gewachsen, siehe .kopfknopf/.spielername weiter oben. */
.kopf-einfluss-militaer {
  display: inline-flex;
  align-items: center;
  /* Dasselbe Maß wie der Abstand zwischen allen übrigen Knöpfen der Reihe
     (#topbar .links, gap: 0.5rem) — sonst rückt das Paar enger zusammen als
     der Rest und die Reihe wirkt ungleichmäßig. */
  gap: 0.5rem;
}

/* --- Das Einstellungsmenü UND das Avatar-Menü -------------------------------
   Vorher ein Speichenrad als Symbol. Es war weder als Knopf noch als
   Einstellungen zu erkennen — ein Bild, das man erklären muss, erklärt nichts.
   Jetzt das Wort, in derselben Form wie Landkarte und Chronik daneben.

   Dasselbe Muster trägt seit dem Kopfleisten-Umbau auch das Avatar-Menü
   (Chronik/Diplomatie/Botenstube/Dein Stand, kopfleiste.js) — deshalb stehen
   #optionsmenue und #avatarmenue hier durchweg nebeneinander statt als zweite,
   fast gleichlautende Regelgruppe. */
.einstellmenue { position: relative; display: flex; align-items: center; }
/* Die eigene Form des Einstellknopfs ist entfallen — er trägt jetzt
   .kopfknopf wie Landkarte und Chronik. Übrig bleibt nur, was NUR ihn
   betrifft: dass er ein aufklappbares Menü hat. */

#optionsmenue,
#avatarmenue {
  position: absolute;
  top: calc(100% + 0.55rem);
  right: 0;
  z-index: 60;
  width: 15rem;
  padding: 0.4rem;
  background: linear-gradient(180deg, rgba(28, 31, 36, 0.985), rgba(18, 20, 23, 0.985));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.7);
}
#optionsmenue[hidden],
#avatarmenue[hidden] {
  display: none;
}

/* JEDE Zeile hat denselben Aufbau: Symbolspalte, Beschriftung, Rest. Vorher
   waren es drei verschiedene Formen — ein Link, ein Knopf und eine zentrierte
   Überschrift über einem freischwebenden Regler —, und deshalb stand nichts
   untereinander. Ein Raster mit fester erster Spalte richtet alle Symbole auf
   dieselbe Kante aus, egal wie breit die Beschriftung ist. */
/* Über die ID adressiert, nicht über die Klasse: "#topbar .linkbtn" weiter
   unten ist ein ID-Selektor und schlug jede Klassenregel — der Tonknopf behielt
   dadurch Polsterung und Unterstrich aus dem Kopfband und stand acht Pixel
   weiter links als die übrigen Zeilen. */
#optionsmenue > a,
#optionsmenue > button.linkbtn,
#optionsmenue > label.optionszeile,
#avatarmenue > a,
#avatarmenue > button.linkbtn {
  display: grid;
  grid-template-columns: 1.15rem 1fr;
  align-items: center;
  gap: 0 0.55rem;
  width: 100%;
  margin: 0;
  padding: 0.4rem 0.5rem;
  background: none;
  border: none;
  border-radius: 2px;
  color: var(--brass-light);
  font: inherit;
  font-size: 0.92rem;
  text-align: left;
  text-decoration: none;
  white-space: nowrap;
  cursor: var(--cursor-gold);
}
/* Das Avatar-Menü hat keine Symbolspalte — seine vier Einträge sind reiner
   Text, wie die Knöpfe, aus denen sie hervorgegangen sind. Ohne diese
   Überschreibung bliebe die erste Rasterspalte leer und der Text säße
   grundlos eingerückt. */
#avatarmenue > a,
#avatarmenue > button.linkbtn {
  grid-template-columns: 1fr;
}
#optionsmenue > a:hover,
#optionsmenue > button.linkbtn:hover,
#avatarmenue > a:hover,
#avatarmenue > button.linkbtn:hover {
  background: rgba(168, 129, 61, 0.16);
  color: #e8d5a8;
}
/* Die Symbole haben im Kopfband eine eigene Größe — hier wird sie noch einmal
   festgesetzt, damit die Spalte wirklich überall gleich breit ist. */
#optionsmenue .navicon {
  width: 15px;
  height: 15px;
  flex: none;
}

/* Die Musikzeile. Der Regler bekommt eine eigene Zeile UNTER der Beschriftung,
   aber in derselben Spalte — so bleibt die Symbolkante gewahrt und der Regler
   hat die volle Breite, die er zum Treffen braucht. */
#optionsmenue > label.optionszeile {
  color: var(--text-dim);
  cursor: var(--cursor-kupfer);
}
#optionsmenue > label.optionszeile:hover { background: none; }
#optionsmenue input.musikregler {
  /* Im Kopfband ist der Regler 4rem breit; hier hat er eine eigene Zeile und
     soll sie ausfüllen — sonst ist er kaum zu treffen. */
  width: 100%;
}
#optionsmenue > label.optionszeile input {
  grid-column: 2;
  width: 100%;
  margin-top: 0.3rem;
  cursor: var(--cursor-gold);
}

/* Trennstrich vor dem Abmelden: Was die Sitzung beendet, gehört nicht in eine
   Reihe mit dem Lautstärkeregler. */
.optionstrenner {
  height: 0;
  margin: 0.35rem 0.5rem;
  border: none;
  border-top: 1px solid var(--iron);
}

#topbar .linkbtn {
  background: none;
  border: none;
  border-bottom: 1px solid rgba(168, 129, 61, 0.35);
  color: var(--brass-light);
  font: inherit;
  font-size: 0.9rem;
  padding: 0;
  cursor: var(--cursor-gold);
}
#topbar .linkbtn:hover,
#topbar .linkbtn.stumm,
#topbar .linkbtn.aus {
  color: #e3c88a;
  border-bottom-color: var(--brass-light);
}
#topbar .linkbtn.stumm,
#topbar .linkbtn.aus {
  opacity: 0.55;
}
/* Musikregler: der Browser-Standard bringt ein blaugraues Bedienelement mit,
   das im Messing-Kopfband wie ein Fremdkörper wirkt — deshalb Schiene und
   Griff komplett selbst gezeichnet. Die ::-webkit-/::-moz-Paare sind nötig,
   weil sich beide Engines hier nicht auf eine Schreibweise geeinigt haben. */
#topbar .musikregler {
  width: 4rem;
  height: 10px;
  -webkit-appearance: none;
  appearance: none;
  background: none;
  cursor: var(--cursor-gold);
}
#topbar .musikregler::-webkit-slider-runnable-track {
  height: 2px;
  border-radius: 1px;
  background: var(--brass-dark);
}
#topbar .musikregler::-moz-range-track {
  height: 2px;
  border-radius: 1px;
  background: var(--brass-dark);
}
#topbar .musikregler::-moz-range-progress {
  height: 2px;
  border-radius: 1px;
  background: var(--brass-light);
}
#topbar .musikregler::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 8px;
  height: 8px;
  margin-top: -3px;
  border-radius: 50%;
  border: none;
  background: var(--brass-light);
}
#topbar .musikregler::-moz-range-thumb {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: none;
  background: var(--brass-light);
}
#topbar .musikregler:hover::-webkit-slider-thumb {
  background: #e3c88a;
}
#topbar .musikregler:hover::-moz-range-thumb {
  background: #e3c88a;
}

/* Die Vorratsleiste sitzt unten rechts, ÜBER der Bauleiste.
   Rechtsbündig und von unten nach oben umbrechend: Die Reihe wächst damit
   nach oben in den leeren Himmel statt in die Bauleiste hinein, und die
   Stimmung bleibt am selben Fleck, egal wie viele Waren man führt. */
#vorratsleiste {
  /* Rechter Teil der Fußleiste — kein eigenes schwebendes Feld mehr. Dort ist
     der Platz, den die Bauwerkzeuge nicht brauchen, und Vorrat und Baukosten
     stehen endlich nebeneinander statt übereinander. */
  margin-left: auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: center;
  gap: 0.3rem;
  flex: 0 1 auto;
}
#resources {
  display: flex;
  gap: 0.18rem;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: flex-end;
}
/* Um 30% verkleinert (Wunsch: die Leiste soll weniger Raum in der Burgansicht
   einnehmen) — alle Maße mit demselben Faktor 0,7, damit Emblem, Zahl und
   Einfassung im selben Verhältnis zueinander bleiben wie vorher. */
.res {
  display: inline-flex;
  align-items: center;
  gap: 0.21rem;
  /* Die Zahl wächst mit dem Emblem mit — ein Emblem neben einer viel
     kleineren Ziffer sähe aus, als hinge die Zahl daran statt dazuzugehören. */
  font-size: 0.77rem;
  font-variant-numeric: tabular-nums;
  color: var(--text);
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.07rem 0.25rem;
}
/* Wohnraum ist keine Ware: eigene Einfassung, damit er sich vom Lager
   abhebt. Voll = messing, überbelegt = Warnfarbe (jemand schläft draußen). */
.res.wohnraum {
  border-color: var(--brass-dark);
  background: rgba(109, 84, 38, 0.22);
}
/* Einfluss ist ebenfalls keine Ware — er liegt in keinem Speicher und wird
   nicht gehandelt. Messing statt Eisen, und eine Lücke davor, damit er sich
   vom Lagerbestand absetzt statt als weiterer Sack Getreide gelesen zu werden. */
.res.res-einfluss {
  /* HIER STAND EIN margin-left: 0.39rem — die Lücke zum Lagerbestand, als der
     Einfluss noch in der Vorratsleiste zwischen den Waren stand. Er steht dort
     seit dem Kopfleisten-Umbau nicht mehr (ui.ts filtert ihn aus #resources),
     und oben in der Wertegruppe machte das Extra-Polster genau einen Abstand
     ungleich: 17 Pixel zwischen Geld und Einfluss, 10 überall sonst.

     Eine Rücknahme dafür gab es: `.kopf-einfluss-militaer .res-einfluss
     { margin-left: 0 }`. Sie hat NIE gewirkt — gleiche Spezifität wie diese
     Regel hier, aber weiter oben in der Datei, also verliert sie. Das ist die
     zweite Regel dieser Art an einem Tag (die erste stand in .spielername),
     und beide Male war die Antwort dieselbe: nicht noch eine Überschreibung
     obendrauf, sondern die Ursache weg. */
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.18);
  color: var(--brass-light);
}
/* Militärstärke — wie der Einfluss keine Ware, aber ein anderer Stoff:
   Abschreckung statt Ansehen. Deshalb Eisenton statt Messing, ohne zusätzliche
   Lücke: Einfluss und Militär bilden am Ende der Leiste ein Paar, das sich
   gemeinsam vom Lagerbestand absetzt. */
.res.res-militaer {
  border-color: #6b7889;
  background: rgba(107, 120, 137, 0.2);
  color: #b9c0c8;
}
.res.wohnraum.voll {
  border-color: var(--brass);
  color: var(--brass-light);
}
.res.wohnraum.knapp {
  border-color: var(--blood);
  background: rgba(143, 61, 44, 0.28);
  color: #f0c9bd;
}
/* Lagerzustand — wie Wohnraum eine Summe, keine einzelne Ware: eigene
   Einfassung. Voll = messing (der Topf ist an seiner Grenze, noch normal),
   knapp = Warnfarbe (er läuft über — was zu viel ist, verdirbt statt zu
   wachsen). */
.res.lager {
  border-color: var(--brass-dark);
  background: rgba(109, 84, 38, 0.22);
}
.res.lager.voll {
  border-color: var(--brass);
  color: var(--brass-light);
}
.res.lager.knapp {
  border-color: var(--blood);
  background: rgba(143, 61, 44, 0.28);
  color: #f0c9bd;
}

/* ALLE Kästchen der Vorratsleiste gleich hoch — und das geht über die
   SCHRIFTGRÖSSE, nicht über eine Höhenangabe.
 *
 * Der Grund, warum das Lager herausfiel: Jede Ware ist ein <button>
 * (.res-knopf) und öffnet ihre Tafel — nur Lagerzustand und, beim Besuch einer
 * fremden Burg, alle übrigen sind ein schlichtes <span>. .res-knopf hat sich
 * irgendwann seine eigene Schriftgröße gegeben (1.1rem), das schlichte .res
 * blieb bei 0.77rem stehen. Die kleinere Schrift ergibt eine kleinere
 * Zeilenhöhe, und die ist es, die das Kästchen bestimmt: 26,7 px statt 31,7 px
 * bei sonst gleicher Polsterung und gleichem Emblem.
 *
 * Eine feste Höhe hier wäre der falsche Weg: Sie hätte das Kästchen passend
 * gemacht und die Schrift trotzdem kleiner gelassen als bei allen Nachbarn —
 * kleine Ziffern in einem Kasten für große. Mit der gemeinsamen Schriftgröße
 * stimmt beides auf einmal.
 *
 * Auf #resources beschränkt: .res tragen auch die Baumaterial-Leiste und die
 * Kostenzeile im Baumenü, und beide haben ihre eigene, bewusst kleinere Größe
 * (.baueintrag .fuss .res). */
#resources .res {
  font-size: 1.1rem;
}

/* Die Vorratsembleme, um 30% verkleinert (siehe .res oben) — 22 statt 32 px.
   Die Icon-Dateien selbst liegen bei 32×32, 32px war also die native, nie
   skalierte Größe; 22px ist damit ein Herunterrechnen, kein Hochrechnen, und
   verzeiht eine krumme Zahl deutlich eher als das Hochskalieren kleiner
   Pixelraster (dafür gilt die Regel: nur ganzzahlige Teiler bleiben scharf).
   Bei diesem kleinen, beiläufig gelesenen HUD-Element fällt das nicht auf. */
.res .resicon {
  width: 22px;
  height: 22px;
  flex: none;
  image-rendering: pixelated;
}

/* Der untere Rand — KEIN Balken mehr.
   Hier lag ein durchgehender Eisenbalken über die volle Breite. Er trug
   einmal eine Reihe Bauwerkzeuge; geblieben sind links ein einziger Knopf
   ("Bauen" — der Abriss wohnt jetzt im Baumenü) und rechts Vorräte und
   Stimmung. Ein Balken über die ganze Breite für zwei Häufchen an den Enden
   ist verschenkte Bildfläche: Er nahm der Burg unten einen Streifen weg und
   erzählte dabei nichts.
   Was bleibt, ist nur noch die ANORDNUNG — links/rechts, unten. Jedes Stück
   bringt seine eigene Fassung mit (.buildbtn, .res, .moralknopf haben alle
   Grund und Rahmen), steht also auch ohne Balken lesbar über der Burg.
   Kein overflow-x auf der Leiste: Sonst würden die Vorräte rechts
   mitscrollen, sobald die Werkzeuge breiter werden als der Schirm. Das
   Rollen übernimmt der Werkzeugkasten für sich. */
#buildbar {
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: flex-end;
  gap: 1rem;
  padding: 0.55rem 1rem;
}
/* Links die Bauwerkzeuge. Sie dürfen wachsen und notfalls rollen — die
   Vorräte daneben bleiben stehen. */
#bauwerkzeuge {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
  overflow-x: auto;
}
.buildbtn {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.25;
  text-align: left;
  /* Dieselbe Höhe wie ein Vorratskästchen am anderen Ende der Fußleiste:
     32 Pixel Emblem plus Polsterung und Rahmen. Die Erklärungen, die früher
     als zweite Zeile im Knopf standen, hängen jetzt am Zeiger (title in
     ui.ts) — in einer Fußleiste zählt Ruhe, und wer die Taste sucht, hält
     ohnehin kurz an. */
  min-height: calc(32px + 0.2rem + 2px);
  padding: 0.1rem 0.7rem;
  color: var(--text);
  background: linear-gradient(180deg, #333941, #22262b);
  border: 1px solid var(--iron);
  border-radius: 2px;
  white-space: nowrap;
  cursor: var(--cursor-gold);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08);
  transition: border-color 0.12s, background 0.12s;
}

/* Handgezeichnete 16px-Pixel-Icons (scripts/build-building-icons.js) —
   Werkzeug oder Erzeugnis statt winzigem Gebäude, das ist bei dieser Größe
   deutlich schneller lesbar. */
.buildicon {
  width: 16px;
  height: 16px;
  flex: none;
  image-rendering: pixelated;
}
.buildbtn.locked .buildicon {
  filter: grayscale(1);
}
/* Im Pergamentzettel der Bauvorhaben läuft das Icon in der Textzeile mit */
.queueitem .buildicon {
  vertical-align: -3px;
  margin-right: 0.35rem;
}

/* Kopfzeilen-Wege: gezeichnete Strichsymbole statt Pixelart — das hier ist
   Bedienoberfläche, kein Gegenstand aus der Spielwelt (wie das Turmsignet).
   Alle vier Symbole teilen sich eine Strichstärke und einen Zeichenstil; die
   Linien liegen im Entwurf auf halben Koordinaten (2.5, 5.5 …), damit sie bei
   dieser Größe auf ganze Gerätepixel fallen statt zu verwischen. */
.navicon {
  /* 12 statt 10 Pixel: Das Kopfband ist insgesamt gewachsen, und bei 10 Pixeln
     sahen die Wegzeichen daneben aus wie Streichhölzer. Weiterhin ein glatter
     Teiler der 16er-Zeichenfläche (0,75), damit die Striche nicht verwischen —
     siehe die Strichstärke unten. */
  width: 12px;
  height: 12px;
  vertical-align: -1px;
  margin-right: 0.32rem;
  flex: none;
  /* Voll deckend in Messing — gedimmt wirkten sie grau statt golden. */
  color: var(--brass-light);
}
.navicon path {
  fill: none;
  stroke: currentColor;
  /* 12px Anzeige aus 16er-Zeichenfläche = Faktor 0.75; 1.34 × 0.75 = genau
     1 Gerätepixel. Sub-Pixel-Striche waren der Grund für den Grauschleier. */
  stroke-width: 1.34;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#topbar .links a:hover .navicon,
#topbar .linkbtn:hover .navicon {
  color: #e3c88a;
}

/* Der Ton-Knopf tauscht beim Umschalten nur seine Beschriftung aus (siehe
   ui.ts), das Symbol bleibt stehen. Bei "Ton aus" verschwindet die Schallwelle
   — der Zustand ist damit auch ohne Lesen der Beschriftung erkennbar. */
#soundtoggle {
  display: inline-flex;
  align-items: center;
}
#soundtoggle.stumm .tonwelle {
  display: none;
}
/* Ausgewähltes Werkzeug: Icon leicht anheben, damit die Wahl auch ohne
   Farbunterschied im Augenwinkel erkennbar bleibt */
.buildbtn.selected .buildicon {
  filter: brightness(1.15) drop-shadow(0 0 4px rgba(204, 167, 94, 0.6));
}
.buildbtn:hover {
  border-color: var(--brass);
}
.buildbtn.selected {
  background: linear-gradient(180deg, #6d5426, #4a3819);
  border-color: var(--brass-light);
  color: #f7ecd6;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.18),
    0 0 10px rgba(168, 129, 61, 0.35);
}
.buildbtn.locked {
  opacity: 0.4;
  cursor: var(--cursor-kupfer);
}

/* ===========================================================================
   Baumodus: seitliches Gebäudemenü (Baumodus-Dokument, Teil 2)
   =========================================================================== */

#baumenu {
  top: 3.6rem;
  bottom: 4.2rem;
  left: 0.7rem;
  width: 21rem;
  overflow-y: auto;
  padding: 0.6rem;
  background: linear-gradient(180deg, rgba(28, 31, 36, 0.97), rgba(18, 20, 23, 0.97));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.65);
}
#baumenu .kopfzeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.4rem;
}
#baumenu .titel {
  font-family: inherit;
  font-size: 1.3rem;
  color: var(--brass-light);
}
#baumenu .fertig {
  font-family: var(--font-body);
  font-size: 0.85rem;
  padding: 0.25rem 0.8rem;
  color: #f7ecd6;
  background: linear-gradient(180deg, #6d5426, #4a3819);
  border: 1px solid var(--brass-light);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
#baumenu .kategorie {
  font-size: 0.75rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 0.7rem 0 0.25rem;
  padding-left: 0.85rem;
  border-left: 3px solid var(--iron);
}
#baumenu .kategorie.kat-rohstoffe { border-left-color: #5d8a4f; }
#baumenu .kategorie.kat-verarbeitung { border-left-color: #b0793e; }
#baumenu .kategorie.kat-sozial { border-left-color: #4f7a9e; }
#baumenu .kategorie.kat-verteidigung { border-left-color: #8a8f96; }

.baueintrag {
  display: flex;
  gap: 0.55rem;
  align-items: flex-start;
  width: 100%;
  text-align: left;
  margin-bottom: 0.3rem;
  padding: 0.4rem 0.5rem;
  font-family: var(--font-body);
  color: var(--text);
  background: linear-gradient(180deg, #2c3138, #22262b);
  border: 1px solid var(--iron);
  border-left-width: 3px;
  border-radius: 2px;
  cursor: var(--cursor-gold);
  transition: border-color 0.12s, background 0.12s;
}
.baueintrag.kat-rohstoffe { border-left-color: #5d8a4f; }
.baueintrag.kat-verarbeitung { border-left-color: #b0793e; }
.baueintrag.kat-sozial { border-left-color: #4f7a9e; }
.baueintrag.kat-verteidigung { border-left-color: #8a8f96; }
.baueintrag:hover { border-color: var(--brass); }
.baueintrag.aktiv {
  background: linear-gradient(180deg, #6d5426, #4a3819);
  border-color: var(--brass-light);
  color: #f7ecd6;
}
.baueintrag.locked { opacity: 0.4; cursor: var(--cursor-kupfer); }
.baueintrag .buildicon { width: 28px; height: 28px; flex: none; image-rendering: pixelated; margin-top: 2px; }
.baueintrag .text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.baueintrag .name { font-size: 0.98rem; }
.baueintrag .flavor { font-size: 0.8rem; font-style: italic; color: var(--text-dim); }
.baueintrag.aktiv .flavor { color: #e2cfa8; }
.baueintrag .mechanik { font-size: 0.78rem; color: var(--text-dim); }
.baueintrag.aktiv .mechanik { color: #e2cfa8; }
.baueintrag .fuss { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; margin-top: 0.15rem; }
/* Auch in den Baukosten die doppelte Größe — dieselbe Überlegung wie im
   Kopfband: Woraus etwas gebaut wird, ist die wichtigste Zeile des Eintrags.
   32 Pixel statt 12, weil zwischen 16 und 32 kein Maß liegt, das die
   16er-Pixelraster scharf hält (24 fiele auf halbe Bildpunkte). */
.baueintrag .fuss .res { font-size: 0.92rem; padding: 0 0.35rem; }
.baueintrag .fuss .resicon { width: 32px; height: 32px; }
.baueintrag .bauzeit { font-size: 0.75rem; color: var(--text-dim); margin-left: auto; }

/* Besuch einer fremden Burg: statt Werkzeugen steht dort, wo man ist */
/* Eigener Grund und eigener Rahmen, seit die Fußleiste kein Balken mehr ist
   (siehe #buildbar): Vorher lehnte dieser Text auf dem Eisenbalken und
   brauchte nichts Eigenes — freistehend über der Burg wäre er auf hellem
   Boden oder vor einer Mauer nicht mehr zu lesen. */
.besuchsleiste {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.05rem;
  padding: 0.25rem 0.7rem;
  margin-right: 0.6rem;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
.besuchsleiste .ort {
  font-family: inherit;
  font-size: 1.15rem;
  color: var(--brass-light);
  line-height: 1.2;
}
.besuchsleiste .wer {
  font-size: 0.86rem;
  color: var(--text);
}
.besuchsleiste .hinweis {
  font-size: 0.76rem;
  font-style: italic;
  color: var(--text-dim);
}

/* "Bauen"-Einstieg unten in der Leiste — durchgehend aus Messing, nicht nur
   der Rahmen. Der Hauptweg ins Spiel soll wie das kostbarste Metall wirken,
   das die Burg kennt, nicht wie ein Knopf unter vielen, der erst beim Klick
   golden wird.
   ALTES Messing, kein poliertes: gedeckt statt glänzend-golden, mit einem
   schmalen Lichtstreif oben und dunklerer Patina zum unteren Rand hin, wie
   von vielen Händen abgegriffen. Textfarbe dunkel, wie eingeprägt. */
.bauenbtn {
  color: #17130a;
  font-weight: 600;
  background: linear-gradient(180deg, var(--brass) 0%, var(--brass-dark) 60%, #241c0e 100%);
  border: 1px solid var(--brass-dark);
  box-shadow:
    inset 0 1px 0 rgba(230, 200, 140, 0.22),
    inset 0 -2px 3px rgba(0, 0, 0, 0.4),
    0 2px 4px rgba(0, 0, 0, 0.4);
}
.bauenbtn:hover {
  background: linear-gradient(180deg, #b9924a 0%, var(--brass) 60%, #2e2410 100%);
  border-color: var(--brass);
}
/* Aktiver Baumodus: das Messing wirkt eingedrückt statt erhaben — derselbe
   Knopf, nur sichtbar "gedrückt" gehalten, solange man im Modus steckt. */
.bauenbtn.selected {
  background: linear-gradient(180deg, #1c150a, #4a3819);
  border-color: var(--brass);
  color: var(--brass-light);
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.7),
    0 0 8px rgba(109, 84, 38, 0.4);
}

/* Hier stand .abrissbtn — die blutrote Fassung des Abriss-Knopfs in der
   Fußleiste. Der Knopf ist weg (ui.ts, renderBuildbar): Abgerissen wird nur
   noch im Baumenü. Die Regeln sind mitgegangen, weil sie ausschließlich ihn
   trafen. */
.buildbtn small {
  display: block;
  font-size: 0.82rem;
  color: var(--text-dim);
  letter-spacing: 0.02em;
}
.buildbtn.selected small {
  color: #e2cfa8;
}

/* Bauvorhaben — dritter Zettel im Meldungsstapel OBEN LINKS
   (siehe #bedrohungen für den ganzen Stapel und seine Reihenfolge). */
#queue {
  top: calc(var(--meldungen-oben) + var(--bedrohungen-hoehe, 0rem) + var(--fuhren-hoehe, 0rem));
  bottom: auto;
  right: auto;
  left: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  max-width: 260px;
}

/* Ausbau-Tafel: steht ÜBER den Bauvorhaben, damit die Stufe des Bergfrieds
   nicht zwischen den Baustellen untergeht — dieselbe Vorrangstellung wie eh
   und je, nur zählt sie jetzt von oben statt von unten. */
#ausbau {
  top: calc(var(--meldungen-oben) + var(--bedrohungen-hoehe, 0rem) + var(--fuhren-hoehe, 0rem));
  bottom: auto;
  right: auto;
  left: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  max-width: 260px;
}
/* Steht die Ausbau-Tafel, rücken die Bauvorhaben unter sie. Die 7,5rem sind
   ihre gemessene Normalhöhe und stammen unverändert aus der Zeit, als der
   Stapel noch von unten wuchs — eine echte Messung wie bei --bedrohungen-hoehe
   wäre sauberer, aber die Tafel zeigt immer genau EINE Zeile, und für die
   stimmt der Wert. */
#ausbau:not([style*="none"]) ~ #queue {
  bottom: auto;
  top: calc(var(--meldungen-oben) + 7.5rem + var(--bedrohungen-hoehe, 0rem) + var(--fuhren-hoehe, 0rem));
}
.ausbauitem {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  background: rgba(18, 20, 23, 0.94);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  padding: 0.5rem 0.6rem;
}
.ausbauitem .kopf {
  font-size: 0.86rem;
  color: var(--brass-light);
}
.ausbauitem button {
  margin-top: 0.15rem;
  background: linear-gradient(180deg, #6d5426, #43341a);
  border: 1px solid var(--brass);
  color: #f7ecd6;
  border-radius: 2px;
  padding: 0.3rem 0.5rem;
  font-family: var(--font-body);
  font-size: 0.88rem;
  cursor: var(--cursor-gold);
}
.ausbauitem button:hover:not(:disabled) {
  border-color: var(--brass-light);
  box-shadow: 0 0 10px rgba(168, 129, 61, 0.35);
}
.ausbauitem button:disabled {
  background: var(--stone-700);
  border-color: var(--iron);
  color: var(--text-dim);
  cursor: var(--cursor-kupfer);
}
.queueitem {
  background: linear-gradient(180deg, var(--parchment), var(--parchment-dark));
  color: var(--ink);
  border: 1px solid #8d7d5c;
  border-radius: 2px;
  padding: 0.4rem 0.7rem;
  font-size: 0.85rem;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.45);
}
.queueitem .bar {
  height: 4px;
  background: rgba(60, 48, 28, 0.35);
  border-radius: 2px;
  margin-top: 0.3rem;
  overflow: hidden;
}
.queueitem .bar > div {
  height: 100%;
  background: linear-gradient(90deg, var(--brass-dark), var(--brass));
}

/* FEHLER SIND ROT. Der Rand trug bis 13.08.2026 --fire (#c2662e) — die
   Flammenfarbe des Spiels, die neben dem bernsteinfarbenen Hinweis darunter
   zu wenig anders aussah: Beides las sich als "Kupfer", und eine Ablehnung
   war von einer Erinnerung nicht zu unterscheiden. Jetzt ein eigenes,
   deutliches Rot — dunkel genug für die Palette, hell genug, um zu stoppen.
   --fire selbst bleibt unangetastet, es gehört Feuer und Bedrohung. */
#toast {
  /* ÜBER ALLEM, was eine Meldung auslösen kann.
     Der Kasten lag auf z-index 10 und damit UNTER jeder Tafel (Handel,
     Gebäude, Stand: 60 und darüber). Wer in der Handelstafel etwas
     Unmögliches versuchte, bekam die Absage des Servers hinter die Tafel
     gemalt und sah gar nichts — der Knopf schien schlicht nicht zu
     reagieren. Gemeldet am 22.08.2026 als "man klickt darauf und es kommt
     keine Meldung"; die Meldung kam die ganze Zeit, nur eben unsichtbar.
     2500 liegt über allen Tafeln und unter dem Drehhinweis am Handy. */
  z-index: 2500;
  top: 3.6rem;
  left: 50%;
  transform: translateX(-50%);
  background: linear-gradient(180deg, #4d1f1a, #2c1210);
  border: 1px solid #c0392b;
  color: #f6cdc6;
  padding: 0.5rem 1rem;
  border-radius: 2px;
  font-size: 0.92rem;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);
  opacity: 0;
  transition: opacity 0.25s;
}
#toast.show {
  opacity: 1;
}
/* Erinnerung statt Ablehnung: bernsteinfarben aus der Messing-Palette des
   Spiels, nicht das rote Feuer der Fehlermeldung — "hier fehlt noch ein
   Schritt" ist keine Zurückweisung. */
#toast.hinweis {
  background: linear-gradient(180deg, #4a3a12, #2e2408);
  border-color: var(--brass);
  color: #f5dfa0;
}
/* GELUNGEN IST GRUEN (22.08.2026, Ansage des Bauherrn: "nur Fehlermeldungen in
   rot, normale Meldungen wenn alles passt in gruen").

   Vorher war der Kasten immer rot — auch fuer "Ein Haendler bricht nach Aachen
   auf" oder "Die Mauer steht". Rot heisst "es ging nicht"; wer dieselbe Farbe
   fuer Erfolg benutzt, nimmt ihr genau die Bedeutung, wegen der sie rot ist.

   Das Gruen ist aus derselben Familie wie .ht-verkauf (#a9c795), nur satter —
   die Palette kennt es also schon, es ist keine neue Farbe im Spiel. */
#toast.gut {
  background: linear-gradient(180deg, #2c3f22, #18240f);
  border-color: #6f8f52;
  color: #cfe3b4;
}

#hint {
  bottom: 4rem;
  left: 50%;
  transform: translateX(-50%);
  color: var(--text-dim);
  font-size: 0.85rem;
  background: rgba(18, 20, 23, 0.8);
  border: 1px solid var(--iron);
  padding: 0.25rem 0.8rem;
  border-radius: 2px;
}
/* Im Baumodus steht die Bauleiste unten in der Mitte — genau dort, wo der
   Hinweisbalken saß. Er legte sich damit über die Ikonenreihe: Wer auf eine
   verdeckte Ikone klickte, traf zwar durch (pointer-events: none), schaltete
   aber sein eigenes Werkzeug wieder ab — als hätte man den Hinweis
   weggeklickt. Also über die Leiste damit. Die Höhe misst ui.ts und schreibt
   sie in --baumenu-hoehe, weil die Leiste mit der Infokarte wächst. */
body.baumodus #hint {
  bottom: calc(var(--baumenu-hoehe, 12rem) + 1.4rem);
}

/* Entwickler-Panel — bewusst grell abgesetzt (Feuer statt Messing), damit
   nie unklar ist, dass Testwerkzeuge und nicht echte Spielmechanik am Werk sind */
#devpanel {
  top: 3.6rem;
  left: 0.7rem;
  transition: left 0.18s;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  background: rgba(18, 20, 23, 0.94);
  border: 1px solid var(--fire);
  border-radius: 2px;
  padding: 0.6rem 0.7rem;
  min-width: 190px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
  /* Gedeckelt und scrollbar. Die Werkstatt wächst mit jedem neuen Werkzeug;
     zuletzt war sie 1266 px hoch und damit höher als das Fenster — sie deckte
     die halbe Karte ab, und da ihre Zeilen Klicks annehmen, ging jeder Klick
     darauf ins Leere statt aufs Spielfeld. Ein Testpanel darf das Spiel nie
     unbedienbar machen. */
  max-height: calc(100vh - 5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}
#devpanel .kopf {
  font-size: 0.80rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fire-light);
  font-weight: 600;
}
/* Abstand vor jeder Gruppe außer der ersten */
#devpanel .kopf ~ .kopf {
  margin-top: 0.5rem;
  border-top: 1px solid rgba(194, 102, 46, 0.3);
  padding-top: 0.5rem;
}
/* Jeder Abschnitt ein <details> statt eines flachen .kopf-Blocks — elf
   Abschnitte offen untereinander waren nicht mehr zu überblicken. Dieselbe
   Randlinie wie oben, jetzt an <details> statt an .kopf gebunden, weil .kopf
   jetzt IN der Summary steckt statt als eigenes Geschwister davorzustehen. */
#devpanel details {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
#devpanel details ~ details {
  margin-top: 0.5rem;
  border-top: 1px solid rgba(194, 102, 46, 0.3);
  padding-top: 0.5rem;
}
#devpanel details > summary.kopf {
  cursor: var(--cursor-gold);
  list-style: revert;
}
#devpanel details > summary.kopf::marker {
  color: var(--fire);
  font-size: 0.75em;
}
#devpanel details:not([open]) > summary.kopf {
  margin-bottom: 0;
}
/* Nachrichtlich, nicht bedienbar — etwa das eingestellte Zeittempo, das in
   config/world.json steht und hier nur erklärt, warum die Welt so rennt. */
#devpanel .hinweis {
  margin: 0;
  font-size: 0.80rem;
  font-style: italic;
  line-height: 1.35;
  color: var(--text-dim);
}
#devpanel .reihe {
  display: flex;
  gap: 0.3rem;
}
#devpanel .reihe button {
  flex: 1;
}
#devpanel button.klein {
  font-size: 0.82rem;
  padding: 0.22rem 0.4rem;
}
/* Zoomgrenzen-Regler: Beschriftung mit Wert links, Schieber rechts daneben */
#devpanel .zoomzeile {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  color: var(--text-dim);
  white-space: nowrap;
}
#devpanel .zoomzeile strong {
  color: var(--brass-light);
  font-weight: 600;
  min-width: 1.7rem;
}
#devpanel .zoomzeile input[type="range"] {
  flex: 1 1 auto;
  min-width: 0;
  accent-color: var(--brass);
}
/* Aktuell eingestellte Tages-/Jahreszeit hervorheben */
#devpanel button.aktiv {
  border-color: var(--fire-light);
  background: linear-gradient(180deg, #6b4527, #4a2f1b);
  color: #ffd9b0;
}
#devpanel button {
  font-size: 0.8rem;
  padding: 0.3rem 0.55rem;
  border-color: var(--fire);
  background: linear-gradient(180deg, #3d2c22, #2a1d16);
}
#devpanel button:hover {
  border-color: var(--fire-light);
}
/* Sprite-Editor-Link: wie ein .klein-Knopf, aber ein <a> statt <button> */
#devpanel a.klein {
  display: block;
  text-align: center;
  font-size: 0.82rem;
  padding: 0.22rem 0.4rem;
  border: 1px solid var(--fire);
  border-radius: 2px;
  color: var(--text);
  background: linear-gradient(180deg, #3d2c22, #2a1d16);
  cursor: var(--cursor-gold);
}
#devpanel a.klein:hover {
  border-color: var(--fire-light);
}
/* Im Baumodus belegt das Gebäudemenü die linke Spalte (21rem breit ab 0.7rem) */
/* KEIN Ausweichen mehr im Baumodus.
   Diese Regel stammt aus der Zeit, als das Baumenü eine linke Spalte war —
   die Werkstatt rückte daneben. Seit das Menü als Leiste unten sitzt, schob
   der Versatz die Werkstatt mitten ins Bild (x≈380), und weil ihre Zeilen
   Klicks annehmen, verschluckte ein unsichtbarer 400-px-Streifen jeden Klick
   auf die Karte: Man konnte kein Gebäude mehr setzen. Sie bleibt jetzt links
   stehen, wo sie hingehört. */
body.baumodus #devpanel {
  left: 0.7rem;
}

.dev-abzeichen {
  /* nüchternes Werkstatt-Schild: bewusst Grundschrift, keine Fraktur —
     das Badge erbt sonst die gotische Titelschrift der Topbar.
     Zugleich Schalter für das Werkstatt-Panel (siehe ui.ts). */
  font-family: "Garamond Bergfried", Georgia, serif;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fire-light);
  background: rgba(194, 102, 46, 0.12);
  border: 1px solid var(--fire);
  border-radius: 2px;
  padding: 0.1rem 0.4rem;
  vertical-align: 0.22em;
  cursor: var(--cursor-gold);
  transition: opacity 0.12s, background 0.12s, border-color 0.12s;
}
.dev-abzeichen:hover {
  background: rgba(194, 102, 46, 0.28);
  border-color: var(--fire-light);
}
/* Werkstatt ausgeblendet: Schild tritt zurück, bleibt aber anklickbar */
.dev-abzeichen.zu {
  color: var(--text-dim);
  background: transparent;
  border-color: var(--iron);
  opacity: 0.65;
}
.dev-abzeichen.zu:hover {
  color: var(--fire-light);
  border-color: var(--fire);
  opacity: 1;
}

/* ===========================================================================
   Startbildschirm — die Burg als lebendiger Hintergrund

   Alle Bewegung steckt in CSS: das Bild driftet langsam (Ken-Burns), am Tor
   flackert Feuerschein, Nebel zieht in zwei Ebenen unterschiedlich schnell
   und gelegentlich kreuzen Krähen das Bild. Nachgeladen wird nur opener.jpg;
   die Bewegung schaltet sich über die reduced-motion-Regel weiter unten
   vollständig ab.
   =========================================================================== */

body.mit-hero {
  background-color: #08090b;
}

.hero {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Die Bühne: hält das Seitenverhältnis des Bildes und legt sich wie
   `object-fit: cover` über den Viewport — MINDESTENS so groß wie das Fenster,
   der Viewport ist also immer vollständig gefüllt. Je nach Fensterform ragt
   die Bühne oben/unten oder links/rechts über den Rand hinaus; `.hero` (siehe
   dort, overflow:hidden) schneidet das sauber ab. Das ist der Preis dafür,
   dass nie ein dunkler Rand am Bildschirmrand bleibt.

   Bild, Lichter und Rauch liegen GEMEINSAM darin, und nur deshalb sitzt ein
   Licht auch bei jeder Fensterform auf seinem Fenster. Läge das Bild als
   background-size und die Lichter daneben im Viewport, liefen beide bei
   jedem Seitenverhältnis auseinander. */
.hero__buehne {
  --ar: calc(var(--opener-b, 2560) / var(--opener-h, 1396));
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100%, calc(100vh * var(--ar)));
  height: max(100%, calc(100vw / var(--ar)));
  /* Zentrierung über die EIGENSTÄNDIGE translate-Eigenschaft. Historisch war
     das nötig, weil hier eine Drift-Animation transform belegte; sie ist
     entfallen, aber die Trennung bleibt richtig — wer hier je wieder etwas
     animiert, tritt der Zentrierung nicht auf die Füße. */
  translate: -50% -50%;
  /* KEINE Bewegung mehr. Früher schwenkte hier eine Ken-Burns-Drift über das
     Bild; die setzt aber zwingend voraus, dass man in einen größeren
     Ausschnitt hineinfahren kann — und genau diesen Spielraum gibt es nicht
     mehr, seit das Bild vollständig sichtbar sein soll. Das Leben kommt
     stattdessen von Lichtern, Rauch, Nebel und Krähen. */
}

.hero__bild {
  position: absolute;
  inset: 0;
  /* Die URL kommt als Variable von der Seite (server/src/opener.ts) und trägt
     eine Version — ein ausgetauschtes Startbild erscheint dadurch sofort und
     nicht erst, wenn der Browser-Cache abgelaufen ist.

     GEZEIGT WIRD DIE PIXELFASSUNG (scripts/build-opener.js, 960 Punkte breit,
     volle Farben). Das Spiel dahinter ist Pixelkunst, das gemalte Original war
     es nicht — die Anmeldung sah dadurch aus wie das Titelbild eines anderen
     Spiels. Zurück zur glatten Fassung ist genau eine Zeile: hier
     `--opener-bild` statt `--opener-bild-pixel` einsetzen. */
  background-image: var(--opener-bild-pixel, url("/static/opener/opener-pixel.webp"));
  background-size: 100% 100%;
  /* Ohne das glättete der Browser die 560 Punkte beim Hochziehen wieder weg
     und die ganze Rechnerei wäre umsonst. `pixelated` heißt: nächster
     Nachbar, harte Kanten. */
  image-rendering: pixelated;
  /* KEIN Filter. Das Bild ist eine gemalte Winternacht und bringt seine
     Stimmung selbst mit — jedes Abdunkeln nahm ihm nur Zeichnung. Lesbar
     bleibt die Anmeldetafel durch ihren eigenen Grund, nicht dadurch, dass
     die Burg dahinter gedämpft wird. */
}

/* Die frühere Sonderregel für schmale Fenster ist ERSATZLOS weg: Sie lud dort
   die kleine Fassung, weil ein 2560er Bild auf einem Telefon verschenkte
   Ladezeit ist. Die Pixelfassung wiegt 112 kB statt 325 — der Grund für die
   Unterscheidung ist damit entfallen, und eine Regel weniger ist eine Regel
   weniger, die auseinanderlaufen kann. */

/* --- Lichter: von Hand gesetzte Anker (/admin/startbild) ------------------
   Jedes Licht ist ein weicher Fleck im Mischmodus „screen": Es legt Helligkeit
   auf das Bild, statt es zu übermalen — so bleibt das gemalte Fenster darunter
   sichtbar und bekommt nur seinen Schein dazu. */
.hero__lichter {
  position: absolute;
  inset: 0;
  mix-blend-mode: screen;
}
.hero__licht {
  position: absolute;
  display: block;
  /* Maß am Bild, nicht am Viewport: Ein Licht muss beim Zoomen mit seinem
     Fenster mitwachsen, sonst rutscht der Schein von der Öffnung. Die Maße
     sind bewusst klein — ein Lichtpunkt soll ein FENSTER andeuten, keinen
     Scheinwerfer; das Leben kommt aus dem Flackern, nicht aus der Fläche. */
  width: calc(var(--kraft, 1) * 2.3%);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  animation: hero-glimmen var(--takt, 5s) ease-in-out infinite;
}
/* Fenster: Talglicht hinter Butzenscheiben. Zittert leicht — eine Kerze
   steht nie still, aber sie tanzt auch nicht wie eine Fackel. */
.hero__licht--fenster {
  background: radial-gradient(circle, rgba(232, 190, 106, 0.58), rgba(196, 146, 68, 0.18) 40%, transparent 68%);
}
/* Fackel: unruhiger und oranger, das lebendigste der Lichter */
.hero__licht--fackel {
  width: calc(var(--kraft, 1) * 3.3%);
  background: radial-gradient(circle, rgba(238, 152, 74, 0.64), rgba(200, 104, 44, 0.22) 40%, transparent 70%);
  animation-name: hero-flackern-punkt;
}
/* Esse: das größte, tiefste Glühen — Schmiedefeuer, fast rot */
.hero__licht--esse {
  width: calc(var(--kraft, 1) * 5.5%);
  background: radial-gradient(circle, rgba(240, 130, 58, 0.68), rgba(186, 74, 30, 0.26) 38%, transparent 70%);
  animation-name: hero-flackern-punkt;
}

/* Viele ungleich verteilte Stufen statt einer Sinuswelle: Ein regelmäßiges
   Auf und Ab liest sich als Pulsieren, erst der unregelmäßige Takt wirkt wie
   eine Flamme. Die Prozentwerte sind bewusst keine runden Zahlen. */
@keyframes hero-glimmen {
  0%,
  100% {
    opacity: 0.62;
  }
  17% {
    opacity: 1;
  }
  31% {
    opacity: 0.74;
  }
  44% {
    opacity: 0.95;
  }
  58% {
    opacity: 0.58;
  }
  69% {
    opacity: 0.9;
  }
  83% {
    opacity: 0.7;
  }
}
/* Fackel und Esse: dasselbe Prinzip, nur heftiger — mit Größensprüngen, als
   würde die Flamme im Zug stehen. */
@keyframes hero-flackern-punkt {
  0%,
  100% {
    opacity: 0.45;
    transform: translate(-50%, -50%) scale(0.9);
  }
  13% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1.16);
  }
  26% {
    opacity: 0.62;
    transform: translate(-50%, -50%) scale(0.97);
  }
  39% {
    opacity: 0.95;
    transform: translate(-50%, -50%) scale(1.1);
  }
  51% {
    opacity: 0.4;
    transform: translate(-50%, -50%) scale(0.88);
  }
  64% {
    opacity: 0.88;
    transform: translate(-50%, -50%) scale(1.07);
  }
  78% {
    opacity: 0.55;
    transform: translate(-50%, -50%) scale(0.94);
  }
  91% {
    opacity: 0.8;
    transform: translate(-50%, -50%) scale(1.03);
  }
}

/* Kopf: Das Startbild trägt keinen eigenen gemalten Schriftzug mehr, darum
   stehen Titel und Wahlspruch hier als echter Text — still, ohne Animation.
   Beide in einer flex-Spalte statt einzeln mit geschätzten top-Prozenten:
   so bleiben sie bei jeder Fensterform bündig übereinander, unabhängig von
   der tatsächlichen Zeilenhöhe des großen Titels. Sitzt in der Bühne statt
   im Textfluss, damit der Kopf bei jeder Fensterform an derselben
   Bildstelle bleibt. */
.hero__kopf {
  position: absolute;
  top: 6%;
  left: 50%;
  translate: -50% 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15em;
}
.hero__titel {
  margin: 0;
  white-space: nowrap;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2.4rem, 6.2vw, 5.2rem);
  color: #cbb794;
  text-shadow:
    0 3px 6px rgba(0, 0, 0, 0.95),
    0 0 34px rgba(0, 0, 0, 0.75);
}
.hero__motto {
  margin: 0;
  white-space: nowrap;
  font-size: clamp(1rem, 2.1vw, 1.9rem);
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: #cbb794;
  /* Die halbe Sperrung wieder aufaddieren: Sie hängt als Leerraum HINTER dem
     letzten Buchstaben, wodurch die Zeile im flex-Kasten links säße statt
     mittig unter dem Titel. */
  translate: 0.15em 0;
  text-shadow:
    0 2px 4px rgba(0, 0, 0, 0.95),
    0 0 26px rgba(0, 0, 0, 0.7);
}

/* Rauch-Leinwand: rechnet grob und wird hier hochskaliert — „pixelated" ist
   der ganze Trick, ohne die Regel wäre der Rauch weichgezeichneter Brei. */
.hero__rauch {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  image-rendering: pixelated;
  opacity: 0.85;
}

/* Das frühere .hero__glut — ein einzelner, fest einprogrammierter Feuerschein
   am Tor — ist entfallen: Seine Lage war auf das alte Bild eingemessen und
   passte nach dem Bildwechsel nirgends mehr hin. An seine Stelle treten die
   frei gesetzten Lichtanker oben (/admin/startbild). */

/* Nebelbänke und Krähen sind entfallen. Beide lagen ÜBER dem Bild und im
   Viewport statt in der Bühne — seit das Bild vollständig und unbewegt
   gezeigt wird, zogen sie als einzige Fremdkörper darüber hinweg, auch über
   den dunklen Saum. Was das Bild belebt, sitzt jetzt ausschließlich IM Bild:
   die gesetzten Lichter und die Rauchfahnen. */

/* Schleier: nur noch ein Hauch an den äußersten Rändern, damit das Bild nicht
   hart gegen den Fensterrand stößt. Früher lag hier ein kräftiger Verlauf,
   der die halbe Burg schluckte — die Anmeldetafel trägt ihre Lesbarkeit
   selbst, dafür muss das Bild nicht büßen. */
.hero__schleier {
  position: absolute;
  inset: 0;
  background: radial-gradient(135% 100% at 50% 45%, transparent 62%, rgba(8, 9, 11, 0.34) 100%);
}

/* --- Inhalt über der Burgansicht ----------------------------------------- */

/* Die Anmeldetafel bleibt bewusst klein: Sie ist nur ein Namensschild am Tor,
   die Burg dahinter ist die Hauptsache. Rund die halbe Fläche der früheren
   Tafel — schmaler UND knapper gepolstert, denn nur beides zusammen macht
   wirklich Platz frei. */
body.mit-hero .container {
  min-height: 100vh;
  max-width: 360px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: 2.5rem;
}
/* Nicht jede Seite vor dem Burgbild ist ein Anmeldeformular: Die Werkstatt-
   Einfahrt (/start) stellt zwei Wege nebeneinander und erstickt in 360 px.
   Die Regel muss hier stehen, damit sie die Zeile darüber schlägt — sonst
   gewönne die spezifischere Hero-Regel gegen .container.wide. */
body.mit-hero .container.wide {
  max-width: 700px;
}

body.mit-hero .panel {
  padding: 1.1rem 1.2rem;
}
body.mit-hero label {
  font-size: 0.78rem;
  gap: 0.2rem;
}
body.mit-hero input[type="text"],
body.mit-hero input[type="password"] {
  font-size: 0.88rem;
  padding: 0.36rem 0.5rem;
}
body.mit-hero form {
  gap: 0.7rem;
}
body.mit-hero .crest .sigil {
  width: 68px;
  height: 68px;
  filter: drop-shadow(0 0 14px rgba(168, 129, 61, 0.55));
}
body.mit-hero .crest h1 {
  font-size: clamp(3.4rem, 12vw, 5.4rem);
  color: #e6cd94;
  text-shadow:
    0 2px 0 rgba(0, 0, 0, 0.8),
    0 0 38px rgba(168, 129, 61, 0.5);
  animation: hero-titelglut 9s ease-in-out infinite;
}
body.mit-hero .crest .motto {
  color: #a2977f;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}

@keyframes hero-titelglut {
  0%,
  100% {
    text-shadow:
      0 2px 0 rgba(0, 0, 0, 0.8),
      0 0 30px rgba(168, 129, 61, 0.38);
  }
  50% {
    text-shadow:
      0 2px 0 rgba(0, 0, 0, 0.8),
      0 0 48px rgba(204, 167, 94, 0.6);
  }
}

/* Tafel wird durchscheinend — die Burg soll dahinter sichtbar bleiben */
body.mit-hero .panel {
  background: linear-gradient(180deg, rgba(48, 54, 62, 0.88), rgba(16, 18, 21, 0.92));
  backdrop-filter: blur(4px);
  border-color: rgba(109, 84, 38, 0.75);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.09),
    inset 0 0 70px rgba(0, 0, 0, 0.45),
    0 20px 60px rgba(0, 0, 0, 0.7);
}

/* Auf dem Startbildschirm ist der Knopf die Hauptsache: volle Breite,
   Messing statt Eisen, damit klar ist, wo es hineingeht. */
body.mit-hero form {
  max-width: none;
}
body.mit-hero form button[type="submit"] {
  width: 100%;
  padding: 0.45rem 0.8rem;
  font-size: 0.88rem;
  letter-spacing: 0.06em;
  background: linear-gradient(180deg, #6d5426, #43341a);
  border-color: var(--brass);
  color: #f7ecd6;
}
body.mit-hero form button[type="submit"]:hover {
  background: linear-gradient(180deg, #866633, #55411f);
  border-color: var(--brass-light);
  box-shadow: 0 0 18px rgba(168, 129, 61, 0.4);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

@media (max-width: 640px) {
  html {
    font-size: 16px;
  }
  .container {
    padding: 1.8rem 0.9rem 3rem;
  }
  .panel {
    padding: 1.3rem 1.1rem;
  }
  .crest h1 {
    font-size: 2.3rem;
  }
  #topbar {
    gap: 0.7rem;
    font-size: 0.9rem;
  }
  #topbar .title {
    font-size: 1.2rem;
  }
  /* Auf dem Handy zurück auf die einfache Größe. Elf doppelt große Embleme
     nebeneinander sind auf 400 Pixeln Breite vier Zeilen Kopfband — dann sieht
     man von der Burg nichts mehr. Wieder GENAU 16 Pixel, nicht irgendetwas
     dazwischen: Nur ganze Vielfache halten das Pixelraster scharf. */
  .res .resicon {
    width: 16px;
    height: 16px;
  }
  .res {
    font-size: 0.92rem;
    gap: 0.3rem;
  }
  .baueintrag .fuss .resicon {
    width: 16px;
    height: 16px;
  }
}

/* ===========================================================================
   Dev-Sprite-Editor (server/src/spriteEditor.ts, server/public/sprite-editor.js)
   =========================================================================== */

.txt-klein {
  font-size: 0.8rem;
}
/* minmax(0, 1fr) statt 1fr: Eine Grid-Spalte ist von sich aus mindestens so
   breit wie ihr Inhalt — und der Inhalt ist hier die Zeichenfläche, die beim
   Hineinzoomen mehrere tausend Pixel breit wird. Mit dem blanken 1fr wuchs
   deshalb die SPALTE mit, statt dass .se-canvaswrap gescrollt hätte: Die
   ganze Seite bekam eine waagerechte Bildlaufleiste, die Werkzeugspalte
   rutschte aus dem Bild, und das Schieben im Rahmen konnte gar nicht
   greifen, weil es nichts zu scrollen gab. Die 0 als Minimum erlaubt der
   Spalte zu schrumpfen — erst dadurch wird overflow:auto im Rahmen wirksam. */
.se-layout {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: 1.2rem;
  align-items: start;
}
.se-seite label {
  display: block;
  font-size: 0.85rem;
  color: var(--text-dim);
  margin-bottom: 1rem;
}
.se-seite select {
  width: 100%;
  margin-top: 0.3rem;
  background: var(--stone-800);
  color: var(--text);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.4rem;
  font-family: var(--font-body);
}
.se-gruppe {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin-bottom: 0.8rem;
}
.se-gruppe button {
  text-align: left;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text);
  padding: 0.4rem 0.6rem;
  border-radius: 2px;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
  font-size: 0.9rem;
}
.se-gruppe button:hover:not(:disabled) {
  border-color: var(--brass);
}
.se-gruppe button.aktiv {
  background: linear-gradient(180deg, #6d5426, #43341a);
  border-color: var(--brass-light);
  color: #f7ecd6;
}
.se-gruppe button:disabled {
  opacity: 0.35;
  cursor: not-allowed;
}
.se-pinsel {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.se-pinsel select {
  width: auto;
}
.se-anker-liste {
  border-top: 1px solid var(--iron);
  padding-top: 0.8rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.se-ankerzeile {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  color: var(--text-dim);
}
.se-ankerzeile button {
  margin-left: auto;
  background: none;
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  padding: 0 0.4rem;
}
.se-ankerzeile button:hover {
  border-color: var(--blood);
  color: var(--fire-light);
}
.se-punkt {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid #14171a;
  flex: none;
}
.se-zoom {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
  flex-wrap: wrap;
}
.se-zoom button {
  height: 2rem;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  font-size: 1.1rem;
}
/* Quadratisch NUR die beiden Zoomtasten. Vorher galt die feste Breite von
   2rem für jeden Knopf dieser Leiste — auch für "↶ Rückgängig", dessen
   Beschriftung damit aus ihrem eigenen Kasten herauslief und über den
   Nachbarn lag. */
.se-zoom button[data-zoom] {
  width: 2rem;
}
.se-zoom .se-zoom-weit {
  padding: 0 0.7rem;
  font-size: 0.85rem;
}
.se-zoom #se-undo {
  padding: 0 0.7rem;
  font-size: 0.85rem;
  margin-right: auto;
}
/* Die Tastenzeile in der Werkzeugspalte: dicht gesetzt, damit sie als
   Nachschlagezeile liest und nicht als Fließtext. */
.se-tasten {
  line-height: 1.65;
}
.se-tasten b {
  color: var(--text);
  background: var(--stone-800);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0 0.28rem;
  font-weight: 600;
  white-space: nowrap;
}
/* Zeichenfläche: soll wirklich zum Arbeiten taugen. Die Höhe richtet sich
   nach dem Fenster, nicht nach einem festen Wert — beim Schattenmalen will
   man das ganze Sprite samt Randzone sehen. */
.se-canvaswrap {
  overflow: auto;
  border: 1px solid var(--iron);
  background: #1a1c20;
  height: calc(100vh - 22rem);
  min-height: 460px;
  max-width: 100%;
}
/* margin:auto statt Flex-Zentrierung: bei einer Zeichenfläche, die größer
   ist als das Fenster, wäre mit align-items:center die obere linke Ecke
   nicht mehr scrollbar. Die Bühne trägt das margin, nicht mehr das Canvas —
   sie ist der gemeinsame Bezugsrahmen für Bild, Rauch und Lichter. */
.se-buehne {
  position: relative;
  width: max-content;
  margin: auto;
}
.se-canvaswrap canvas {
  display: block;
  image-rendering: pixelated;
  cursor: crosshair;
  touch-action: none;
}
/* Rauch und Lichter liegen ÜBER dem Bild, fangen aber keine Klicks ab —
   sonst ließe sich unter einer Fackel kein Pixel mehr radieren. */
.se-buehne .se-rauch,
.se-buehne .se-lichter {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.se-buehne .se-rauch {
  image-rendering: pixelated;
}
/* Mit der mittleren Maustaste wird der Ausschnitt geschoben (sprite-editor.js).
   Während des Ziehens die geschlossene Hand zeigen — und das Fadenkreuz des
   Canvas darunter überstimmen, sonst wechselte der Zeiger je nachdem, ob man
   gerade über dem Bild oder daneben ist. */
.se-canvaswrap.schiebt,
.se-canvaswrap.schiebt canvas {
  cursor: var(--cursor-hand-zu, grabbing);
}
.se-aktionen {
  display: flex;
  gap: 0.6rem;
  margin-top: 0.9rem;
  flex-wrap: wrap;
}
#se-status.se-ok,
#se-gruppe-status.se-ok {
  color: #6fdc5a;
  font-weight: 700;
}
#se-status.se-fehler,
#se-gruppe-status.se-fehler {
  color: var(--fire-light);
}

@media (max-width: 800px) {
  /* Auch hier minmax(0, …) — aus demselben Grund wie oben: ein blankes 1fr
     wäre mindestens so breit wie die hineingezoomte Zeichenfläche. */
  .se-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --- Editor-Übersicht: Karten aller Sprites ------------------------------- */

.se-uebersicht-kopf {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  margin-bottom: 0.8rem;
}
.se-hilfe {
  border: 1px solid var(--iron);
  border-radius: 2px;
  background: var(--stone-800);
  padding: 0.5rem 0.8rem;
  margin-bottom: 1.1rem;
}
.se-hilfe summary {
  cursor: var(--cursor-gold);
  color: var(--brass-light);
  font-size: 0.9rem;
}
.se-hilfe dl {
  margin: 0.7rem 0 0.4rem;
}
.se-hilfe dt {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--text);
  font-weight: 600;
  margin-top: 0.55rem;
}
.se-hilfe dd {
  margin: 0.15rem 0 0;
  color: var(--text-dim);
  font-size: 0.86rem;
  line-height: 1.5;
  max-width: 70ch;
}
.se-karten {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 0.7rem;
}
.se-karte {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  padding: 0.7rem 0.6rem 0.6rem;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
  color: var(--text);
  text-align: center;
}
.se-karte:hover {
  border-color: var(--brass);
}
.se-karte.se-stand-fertig {
  border-color: rgba(122, 145, 102, 0.6);
}
.se-karte.se-stand-platzhalter {
  border-color: var(--fire);
  border-style: dashed;
}
.se-filterleiste {
  margin-left: auto;
  display: flex;
  gap: 0.7rem;
  align-items: center;
}
.se-filterleiste label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
  color: var(--text-dim);
  margin: 0;
}
.se-filterleiste select {
  background: var(--stone-800);
  color: var(--text);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.25rem 0.4rem;
  font-family: var(--font-body);
  font-size: 0.85rem;
}
/* Zerstörende Aktionen abgesetzt und in Warnfarbe */
.se-gefahr {
  border-top: 1px solid var(--iron);
  padding-top: 0.7rem;
  margin-top: 0.7rem;
}
.se-gefahr button {
  border-color: var(--blood);
  color: #e9b9ac;
}
.se-gefahr button:hover {
  background: linear-gradient(180deg, #5a241a, #3a150f);
  border-color: var(--fire-light);
}
.se-status-badge {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  padding: 0.06rem 0.35rem;
  border-radius: 2px;
  border: 1px solid var(--brass-dark);
  color: var(--brass-light);
  background: rgba(0, 0, 0, 0.35);
}
.se-karte.se-fertig .se-status-badge {
  border-color: rgba(122, 145, 102, 0.7);
  color: #a9c795;
}
.se-karte-bild {
  height: 92px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.se-karte-bild img {
  max-height: 92px;
  max-width: 130px;
  image-rendering: pixelated;
}
.se-karte-name {
  font-size: 0.92rem;
}
.se-karte-badges {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem;
}
.se-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.78rem;
  color: var(--text-dim);
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.02rem 0.3rem;
}
.se-badge-leer {
  border-style: dashed;
  opacity: 0.75;
}

/* Wehrbau: Was einem Modul zum Würfeln fehlt. Die Abzeichen für Stilvorlage
   und Vererbung standen bis 08/2026 daneben; seit der Wurf eine reine
   Bildbearbeitung ist, gibt es keine Vererbung mehr (siehe wbTeilHtml). */
.wb-badge-fehlt {
  border-color: #8a4a2a;
  color: #d99a72;
}
.se-abschnitt {
  margin: 1.4rem 0 0.6rem;
}

/* Woher die Licht-/Rauchpunkte kommen: eigene oder vom Grundtyp geerbte */
.se-ankerherkunft {
  margin: 0 0 0.5rem;
  padding: 0.35rem 0.5rem;
  border-left: 2px solid var(--brass-dark);
  background: rgba(168, 129, 61, 0.07);
}
.se-ankerherkunft button {
  background: none;
  border: none;
  border-bottom: 1px solid var(--brass-dark);
  color: var(--brass-light);
  padding: 0;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
}
.se-ankerherkunft button:hover {
  color: #e3c88a;
}

/* --- Bildprompt: der Text, mit dem Nano Banana das Sprite erzeugt ---------- */
.se-prompt {
  margin: 0.8rem 0 0.4rem;
  border: 1px solid var(--iron);
  border-radius: 2px;
  background: var(--stone-800);
  padding: 0.5rem 0.7rem;
}
.se-prompt > summary {
  cursor: var(--cursor-gold);
  color: var(--brass-light);
  font-size: 0.9rem;
}
.se-prompt[open] > summary {
  margin-bottom: 0.5rem;
}
.se-prompt textarea {
  width: 100%;
  resize: vertical;
  background: var(--stone-900);
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--text);
  padding: 0.5rem 0.6rem;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.78rem;
  line-height: 1.5;
}
.se-prompt textarea:disabled {
  opacity: 0.5;
}
.se-prompt-fuss {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-top: 0.4rem;
}
.se-prompt-fuss button {
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.22rem 0.5rem;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
}
.se-prompt-fuss button:hover {
  border-color: var(--brass);
  color: var(--text);
}
/* Abweichung vom Standard sichtbar machen — sonst würfelt man versehentlich
   mit einem Text, den man vor zwanzig Minuten angefasst hat. */
.se-prompt-abweichung {
  color: var(--fire-light);
}
/* Dauerhaft übernommen: messing statt Feuerfarbe — das ist kein Warnzustand,
   sondern ein erledigter. */
.se-prompt-eigen {
  color: var(--brass-light);
}
.se-prompt.se-prompt-leer textarea,
.se-prompt.se-prompt-leer .se-prompt-fuss {
  display: none;
}

/* --- Gebäudefamilie: Zeile je Sicht-Variante, Spalte je Ausbaustufe -------- */
.se-matrix {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.8rem;
}
.se-matrix-zeile {
  display: grid;
  /* Beschriftungsspalte, dann eine gleich breite Spalte je Stufe. Feste
     Spaltenbreite statt 1fr: sonst zöge eine breite Seite die Zellen auf
     halbe Bildschirmbreite auseinander, für ein 56px-Sprite. */
  grid-template-columns: 8.5rem repeat(var(--stufen, 2), minmax(0, 15rem));
  justify-content: start;
  gap: 0.5rem;
  align-items: stretch;
}
.se-matrix-rand,
.se-matrix-kopf {
  display: flex;
  align-items: center;
  font-size: 0.85rem;
  color: var(--text-dim);
  letter-spacing: 0.03em;
}
.se-matrix-kopf {
  justify-content: center;
  color: var(--brass-light);
  border-bottom: 1px solid var(--iron);
  padding-bottom: 0.3rem;
}
.se-matrix-kopf small {
  color: var(--text-dim);
  margin-left: 0.35rem;
}
.se-zelle {
  position: relative;
  /* Buttons dehnen sich als Grid-Element nicht von selbst auf die Spalte */
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  gap: 0.25rem;
  padding: 1.4rem 0.5rem 0.5rem;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
  color: var(--text);
  text-align: center;
}
.se-zelle:hover {
  border-color: var(--brass);
}
.se-zelle.se-stand-fertig {
  border-color: rgba(122, 145, 102, 0.6);
}
.se-zelle.se-stand-platzhalter {
  border-color: var(--fire);
  border-style: dashed;
}
/* Kein Sprite an dieser Stelle — als Lücke sichtbar, aber nicht anklickbar */
.se-zelle-leer {
  border-style: dashed;
  opacity: 0.4;
  cursor: var(--cursor-kupfer);
  min-height: 7rem;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
}
.se-zelle-bild {
  height: 110px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.se-zelle-bild img {
  max-height: 110px;
  max-width: 100%;
  image-rendering: pixelated;
}
.se-zelle-name {
  font-size: 0.82rem;
}

/* --- Bearbeiten-Kopfzeile -------------------------------------------------- */

.se-editor-kopf {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.9rem;
  flex-wrap: wrap;
}
.se-editor-kopf button {
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text);
  border-radius: 2px;
  padding: 0.3rem 0.6rem;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
}
.se-editor-kopf button:hover {
  border-color: var(--brass);
}
/* Der "+"-Knopf ist eine ANLEGENDE Handlung (kostet Guthaben, dauert), kein
   Navigations- oder Status-Knopf wie seine Nachbarn — deshalb eigens
   abgesetzt: rechtsbündig und mit demselben Grünton wie die übrigen
   "gut"-Markierungen im Spiel. */
#se-neue-variante {
  margin-left: auto;
  border-color: #7fa663;
  color: #cfe0bf;
}
#se-neue-variante:hover {
  border-color: #a9c795;
}
#se-neue-variante:disabled {
  opacity: 0.5;
  cursor: var(--cursor-kupfer);
}
.se-fertig-schalter {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.88rem;
  color: var(--text-dim);
  cursor: var(--cursor-gold);
}
.se-gruppe button .se-punkt {
  margin-right: 0.15rem;
}

/* Schatten-Werkzeuge im Sprite-Editor */
.se-schattenleiste {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0.6rem 0 0.8rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--iron);
}
.se-schattenleiste label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.82rem;
  margin: 0;
  cursor: var(--cursor-gold);
}
.se-schattenleiste button {
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.25rem 0.4rem;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
}
.se-schattenleiste button:hover {
  border-color: var(--brass);
  color: var(--text);
}
/* Regler für Richtung und Länge des Schlagschattens */
.se-schattenleiste .se-regler {
  gap: 0.5rem;
  color: var(--text-dim);
}
.se-schattenleiste .se-regler input[type="range"] {
  flex: 1;
  min-width: 0;
  accent-color: var(--brass);
}
.se-schattenleiste .se-regler output {
  min-width: 3.2rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.se-schattenleiste p {
  margin: 0.1rem 0 0.2rem;
}
.se-schatten-versatz-anzeige output {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* Umschalter zwischen den Sammlungen (Gebäude / Burgen) */
.se-sammlungen {
  display: flex;
  gap: 0.4rem;
  margin-bottom: 0.9rem;
}
.se-sammlungen button {
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.4rem 0.9rem;
  cursor: var(--cursor-gold);
  font-family: var(--font-body);
  font-size: 0.92rem;
}
.se-sammlungen button:hover {
  border-color: var(--brass);
}
.se-sammlungen button.aktiv {
  background: linear-gradient(180deg, #6d5426, #43341a);
  border-color: var(--brass-light);
  color: #f7ecd6;
}

/* ===========================================================================
   Gebäudetafel — öffnet sich beim Anklicken eines Gebäudes in der Burgansicht.
   Sitzt links unter dem Kopfband, wo im Baumodus das Baumenü steht: beides
   ist nie gleichzeitig sichtbar, und der Blick sucht Gebäudeauskünfte an
   derselben Stelle wie Bauauskünfte.
   =========================================================================== */
/* --- Die Bewohnertafel ------------------------------------------------------
   Rechts, nicht links: Die Gebäudetafel sitzt links, und beide gleichzeitig
   offen zu haben wäre zwar möglich, aber verwirrend — deshalb schließt in
   main.ts die eine, wenn die andere aufgeht. Die Seite trennt sie trotzdem
   sichtbar, damit man beim Klicken merkt, dass es zwei verschiedene Dinge sind:
   links das Haus, rechts der Mensch. */
#bewohnerpanel {
  top: 3.6rem;
  right: 0.7rem;
  width: 18.5rem;
  max-height: calc(100vh - 8.5rem);
  overflow-y: auto;
  pointer-events: auto;
  padding: 0.55rem 0.7rem 0.7rem;
  background: linear-gradient(180deg, rgba(28, 31, 36, 0.97), rgba(18, 20, 23, 0.97));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.65);
  font-size: 0.86rem;
}
.bp-kopf {
  display: flex;
  align-items: center;
  gap: 0.55rem;
}
/* Dieselbe Figur wie auf dem Hof, nur größer — hier soll man das Gesicht
   wiedererkennen, das man eben angeklickt hat. Nearest-Neighbor, sonst
   verwaschen die Pixel zu Brei. */
.bp-figur {
  width: 34px;
  image-rendering: pixelated;
  flex: none;
}
.bp-titel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.bp-titel strong {
  font-family: inherit;
  font-size: 1.15rem;
  color: var(--brass-light);
  line-height: 1.2;
}
.bp-unter {
  font-size: 0.75rem;
  color: var(--text-dim);
}
.bp-zu {
  flex: none;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.2rem;
  line-height: 1;
  cursor: var(--cursor-gold);
  padding: 0 0.2rem;
}
.bp-zu:hover { color: var(--brass-light); }

.bp-stimmung {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: 0.55rem 0 0;
  padding: 0.3rem 0.5rem;
  border-left: 3px solid var(--iron);
  background: rgba(0, 0, 0, 0.3);
}
.bp-wort { font-family: inherit; font-size: 1rem; }
.bp-wert { font-variant-numeric: tabular-nums; font-size: 0.85rem; color: var(--text-dim); }
.bp-stimmung.gut { border-left-color: #7fa663; }
.bp-stimmung.gut .bp-wort { color: #a9c795; }
.bp-stimmung.mittel { border-left-color: #8a7f5e; }
.bp-stimmung.schlecht { border-left-color: #b07a4a; }
.bp-stimmung.schlecht .bp-wort { color: #d3a273; }
.bp-stimmung.elend { border-left-color: #a34b3c; }
.bp-stimmung.elend .bp-wort { color: #d08a7a; }

/* Der Gedanke. Kursiv und eingerückt: Es ist wörtliche Rede, keine Auskunft
   der Oberfläche — das muss man auf einen Blick auseinanderhalten können. */
.bp-gedanke { margin: 0.7rem 0 0; }
.bp-was {
  margin: 0 0 0.3rem;
  font-size: 0.75rem;
  color: var(--text-dim);
}
.bp-gedanke blockquote {
  margin: 0;
  padding-left: 0.7rem;
  border-left: 2px solid var(--brass-dark);
  font-style: italic;
  color: var(--text);
}
.bp-gedanke blockquote p {
  margin: 0 0 0.4rem;
  line-height: 1.45;
}
.bp-gedanke blockquote p:last-child { margin-bottom: 0; }

.bp-abschnitt {
  margin-top: 0.8rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--iron);
}
.bp-abschnitt h4 {
  margin: 0 0 0.35rem;
  font-size: 0.78rem;
  font-weight: normal;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.bp-zeile,
.bp-posten {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.12rem 0;
}
.bp-zeile > span:first-child,
.bp-posten > span:first-child { color: var(--text-dim); }
.bp-posten > span:last-child { font-variant-numeric: tabular-nums; }
.bp-posten .gut { color: #a9c795; }
.bp-posten .schlecht,
.bp-zeile .schlecht { color: #d08a7a; }
.bp-hinweis { margin: 0; font-size: 0.8rem; color: var(--text-dim); }
.bp-abziehen {
  width: 100%;
  margin-top: 0.7rem;
}

#gebaeudepanel {
  top: 3.6rem;
  left: 0.7rem;
  width: 19rem;
  max-height: calc(100vh - 8.5rem);
  overflow-y: auto;
  pointer-events: auto;
  padding: 0.55rem 0.7rem 0.7rem;
  background: linear-gradient(180deg, rgba(28, 31, 36, 0.97), rgba(18, 20, 23, 0.97));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.65);
  font-size: 0.86rem;
}
/* IM BAUPLAN steht die Gebäudetafel RECHTS, nicht links.
   Links sitzt dort die Vorratstafel (#kartenvorrat) — auf derselben Höhe und
   an derselben Kante. Beide übereinander hieße: eine von beiden ist nicht zu
   lesen, und welche, entschiede die Reihenfolge im HTML.

   Rechts ist frei, und zwar genau dann, wenn die Tafel offen ist: Dort sitzt
   die Bauinfotafel (#bauinfo), die nur bei gewähltem WERKZEUG erscheint — und
   Werkzeug und Auswahl schließen sich aus (main.ts, der Werkzeug-Rückruf
   schließt die Tafel). Die beiden können sich also gar nicht begegnen.

   Die Höhe endet über der Bauleiste, mit derselben Rechnung wie #bauinfo:
   --baumenu-hoehe wird gemessen, weil die Leiste mit ihrer Infokarte wächst. */
body.baumodus #gebaeudepanel {
  left: auto;
  right: 0.7rem;
  max-height: calc(100vh - 4.2rem - var(--baumenu-hoehe, 12rem) - 1.5rem);
}
.gp-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}
.gp-titel {
  font-family: inherit;
  font-size: 1.25rem;
  color: var(--brass-light);
  line-height: 1.2;
}
.gp-titel small {
  font-family: var(--font-body);
  font-size: 0.80rem;
  color: var(--text-dim);
}
.gp-zu {
  flex: none;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.2rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: var(--cursor-gold);
}
.gp-zu:hover { color: var(--brass-light); }
.gp-flavor {
  margin: 0.15rem 0 0.5rem;
  color: var(--text-dim);
  font-style: italic;
  font-size: 0.82rem;
  line-height: 1.35;
}

/* Statuszeile: die eine Aussage, für die man die Tafel aufmacht. */
.gp-status {
  padding: 0.28rem 0.5rem;
  border-left: 3px solid var(--iron);
  background: rgba(0, 0, 0, 0.3);
  border-radius: 1px;
  margin-bottom: 0.45rem;
}
.gp-status.gp-laeuft { border-left-color: #5d8a4f; color: #a8c79a; }
.gp-status.gp-stoerung { border-left-color: #9a6a3c; color: #d8ab7c; }
.gp-status.gp-bau { border-left-color: var(--brass); color: var(--brass-light); }

/* Mängel: hart = Stillstand, weich = bremst nur. Der Unterschied wird über
   die Farbe getragen, nicht über Ausrufezeichen. */
.gp-maengel {
  list-style: none;
  margin: 0 0 0.55rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.22rem;
}
.gp-maengel li {
  position: relative;
  padding-left: 0.85rem;
  line-height: 1.35;
  font-size: 0.82rem;
}
.gp-maengel li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
}
.gp-maengel li.hart { color: #d8ab7c; }
.gp-maengel li.hart::before { background: #9a6a3c; }
.gp-maengel li.weich { color: var(--text-dim); }
.gp-maengel li.weich::before { background: var(--iron-light); }

.gp-abschnitt {
  border-top: 1px solid rgba(109, 84, 38, 0.4);
  padding-top: 0.42rem;
  margin-top: 0.42rem;
}
.gp-abschnitt h4 {
  margin: 0 0 0.3rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brass);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.gp-zaehler {
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-dim);
  font-weight: 400;
}
/* Bewohner-/Garnisonsliste (gebaeudePanel.ts, wohnraumBlock/garnisonBlock):
   lange Listen — Kaserne, Bergfried, eine volle Kate — sollen nicht das ganze
   Fenster füllen. Die Kopfzeile mit der Zahl bleibt immer da, nur die Namen
   klappen weg. Dieselbe Bauart wie #devpanel details oben, hier an die
   .gp-abschnitt-Überschrift statt an .kopf gebunden. */
.gp-abschnitt details.gp-liste > summary {
  cursor: var(--cursor-gold);
  list-style: revert;
}
.gp-abschnitt details.gp-liste > summary::marker {
  color: var(--brass);
  font-size: 0.75em;
}
.gp-abschnitt details.gp-liste > summary h4 {
  display: inline-flex;
}
/* ZUKLAPPBARE ABSCHNITTE der Gebäudetafel (gebaeudePanel.ts, klappe()).
   Angesagt am 24.08.2026: "die Tafel etwas aufräumen, dass der Inhalt
   ausklappbar ist und nicht alles auf einmal angezeigt wird". Die Kopfzeile
   trägt die Antwort (Auslastung, Arbeiterzahl, Zufluss), der Inhalt die
   Begründung. Knöpfe wie "Handel treiben" und der Ausbau stehen bewusst
   AUSSERHALB einer Klappe — nach ihnen sucht man nicht, sie sollen dastehen. */
details.gp-klapp > summary {
  cursor: var(--cursor-gold);
  list-style: revert;
}
details.gp-klapp > summary::marker {
  color: var(--brass);
  font-size: 0.75em;
}
details.gp-klapp > summary h4 { display: inline-flex; width: calc(100% - 1.1rem); }
details.gp-klapp[open] > summary h4 { margin-bottom: 0.28rem; }

/* Die Auslastung: ein Balken, darunter nur das, was wirklich abweicht. Der
   Balken ist die Antwort auf einen Blick — Prozentzahlen liest man erst,
   wenn man schon weiß, dass etwas nicht stimmt. */
.gp-auslastung { margin-top: 0.45rem; }
.gp-balken {
  height: 0.42rem;
  border-radius: 0.21rem;
  background: rgba(0, 0, 0, 0.32);
  border: 1px solid rgba(109, 84, 38, 0.5);
  overflow: hidden;
  margin-bottom: 0.32rem;
}
.gp-balken-fuellung { height: 100%; transition: width 0.35s ease; }
.gp-balken-fuellung.voll { background: linear-gradient(90deg, #8fae82, #b6d0a4); }
.gp-balken-fuellung.gut { background: linear-gradient(90deg, #9a8a4c, #c3ad63); }
.gp-balken-fuellung.mager { background: linear-gradient(90deg, #8a5f34, #c08a4e); }
.gp-auslastung-kopf { font-weight: 700; color: var(--brass); }
.gp-auslastung .gp-zeile small {
  display: block;
  color: var(--text-dim);
  font-weight: 400;
  font-size: 0.76rem;
  line-height: 1.25;
}

.gp-zeile {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.08rem 0;
}
.gp-zeile.gp-plus span:last-child { color: #a8c79a; }
.gp-zeile.gp-minus span:last-child { color: #d8ab7c; }
.gp-zeile.gp-nichts { color: var(--text-dim); }
.gp-hinweis {
  margin: 0.25rem 0 0;
  color: var(--text-dim);
  font-size: 0.79rem;
  line-height: 1.35;
}

.gp-leute {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
}
.gp-leute li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
.gp-name { flex: 1 1 auto; }
.gp-koennen {
  flex: none;
  color: var(--brass);
  letter-spacing: 0.1em;
  font-size: 0.78rem;
}
.gp-ab {
  flex: none;
  background: none;
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.05rem 0.35rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
  cursor: var(--cursor-gold);
}
.gp-ab:hover:not(:disabled) { border-color: #9a6a3c; color: #d8ab7c; }
.gp-ab:disabled { opacity: 0.5; cursor: var(--cursor-kupfer); }

.gp-zuweisen {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.4rem;
}
.gp-auswahl {
  flex: 1 1 auto;
  min-width: 0;
  background: var(--stone-700);
  border: 1px solid var(--iron);
  color: var(--text);
  border-radius: 2px;
  padding: 0.22rem 0.3rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
}
.gp-btn {
  flex: none;
  background: linear-gradient(180deg, #6d5426, #43341a);
  border: 1px solid var(--brass);
  color: #f7ecd6;
  border-radius: 2px;
  padding: 0.22rem 0.6rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
  cursor: var(--cursor-gold);
}
.gp-btn:hover:not(:disabled) {
  border-color: var(--brass-light);
  box-shadow: 0 0 10px rgba(168, 129, 61, 0.35);
}
.gp-btn:disabled {
  background: var(--stone-700);
  border-color: var(--iron);
  color: var(--text-dim);
  cursor: var(--cursor-kupfer);
}
.gp-aktionen {
  border-top: 1px solid rgba(109, 84, 38, 0.4);
  padding-top: 0.45rem;
  margin-top: 0.45rem;
}

/* Der Sprite-Editor braucht mehr Fläche als die übrigen Seiten. */
body:has(.spriteeditor) .container.wide {
  max-width: min(1800px, 96vw);
}
/* Ausbau-Knopf in der Gebäudetafel: über die volle Breite, damit er als
   Abschluss des Abschnitts liest und nicht als Beiwerk. */
.gp-btn.gp-breit {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.32rem 0.6rem;
}

/* ===========================================================================
   Die Blende (server/public/blende.js)

   Burg, Landkarte und Chronik sind drei eigene Seiten. Der Wechsel war deshalb
   ein harter Schnitt mit einem Blitzen des Browsers dazwischen; der Baumodus
   schaltete ebenso unvermittelt von der Schrägsicht auf das Planbrett um.
   Dieses Tuch liegt über allem und macht aus dem Schnitt eine Blende.

   Die Farbe ist die des Ladeschirms — was zwischen den Ansichten liegt, soll
   überall dasselbe Dunkel sein. Ohne Korn: Bei 220 Millisekunden sieht man es
   nicht, und ein Bild zu laden, das niemand sieht, kostet nur Zeit.
   =========================================================================== */

.blende {
  position: fixed;
  inset: 0;
  /* Über allem, auch über Ereignistafel (1300) und Ladeschirm (200). Ein
     Übergang, den ein Fenster durchbricht, ist keiner. */
  z-index: 2000;
  background: #14171a;
  opacity: 0;
  /* Im Ruhezustand für Klicks durchlässig — sonst läge ein unsichtbares Tuch
     über dem Spielfeld und schluckte jeden Mausklick. */
  pointer-events: none;
  /* Der Übergang steht HIER und nicht nur in `.zu`. Beim Aufblenden wird die
     Klasse ja entfernt — und maßgeblich ist immer der Zustand NACH der
     Änderung. Stünde er nur in `.zu`, gäbe es kein Aufblenden, sondern einen
     harten Sprung zurück. Diese Regel gilt also für den Weg ins Bild hinein,
     die in `.zu` für den Weg hinaus. */
  transition: opacity 0.28s ease-out;
  /* Das AUFblenden läuft ohne JavaScript. Käme es aus dem Skript, bliebe die
     Seite bei jedem Ladefehler für immer schwarz. */
  animation: blende-auf 0.34s ease-out;
}
/* Bewusst OHNE animation-fill-mode: Eine nachwirkende Animation schlägt jede
   spätere Deklaration und machte `.zu` wirkungslos. Der Endwert der Animation
   ist ohnehin derselbe wie der Ruhewert darüber. */
@keyframes blende-auf {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* Die Notleine. In einem Fenster, das sich als verborgen meldet — ein Tab im
   Hintergrund —, laufen Animationen nicht an: Das Tuch stünde dort auf voller
   Deckung still. blende.js setzt diese Klasse kurz nach dem Laden; ohne
   Animation fällt die Deckung auf den Ruhewert 0 zurück. In einem sichtbaren
   Fenster ist die Blende zu diesem Zeitpunkt längst durchgelaufen, dort ändert
   die Klasse nichts. */
.blende.auf { animation: none; }

.blende.zu {
  opacity: 1;
  /* Beim Abblenden Klicks abfangen: Ein zweiter Klick auf denselben Weg würde
     sonst einen zweiten Wechsel auslösen. */
  pointer-events: auto;
  transition: opacity 0.22s ease-in;
}

/* Wer Bewegung abbestellt hat, bekommt keine. blende.js überspringt das Tuch
   dann ganz — ein ohne Übergang schwarz werdendes Bild wäre genau das
   Blitzen, das hier verhindert werden soll. */
@media (prefers-reduced-motion: reduce) {
  .blende { animation: none; }
  .blende.zu { transition: none; }
}

/* ===========================================================================
   Ladeschirm der Burgansicht (client/index.html + client/src/ladeschirm.ts)

   Warum es ihn gibt: Der Boden des Burglands wird als EIN Pixelbild mit
   6144×3072 gebacken — 18,9 Millionen Pixel, jedes durch Rauschen, Uferprüfung
   und Relief. Das dauert spürbar, und ohne Rückmeldung sieht man in dieser
   Zeit ein schwarzes Fenster.

   Alles hier ist Pixelwerk: harte Kanten, keine Verläufe, keine runden Ecken.
   Der Schirm soll aussehen wie das Spiel dahinter, nicht wie ein Webformular.
   =========================================================================== */

#ladeschirm,
#wechselschirm {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #14171a;
  /* dasselbe Korn wie der Rest der Oberfläche — der Schirm gehört dazu */
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.35'/%3E%3C/svg%3E");
  opacity: 1;
  transition: opacity 0.45s ease-out;
}
#ladeschirm.fertig,
#wechselschirm.fertig {
  opacity: 0;
  pointer-events: none;
}

#ladeschirm .lade-innen,
#wechselschirm .lade-innen {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.9rem;
}

/* Eines von 20 Motiven aus dem Burgleben (config/ladebilder.json) — dieselbe
   Größe und derselbe Pixel-Stil wie eine Ereignis-Vignette (.ereignis-bild),
   nur größer: hier ist sie das Hauptbild des Schirms, nicht ein Begleiter
   über einem Text. [hidden] bis das Inline-Skript in index.html ein Motiv
   gewählt hat. */
#ladeschirm .lade-bild,
#wechselschirm .lade-bild {
  display: block;
  width: min(620px, 88vw);
  aspect-ratio: 640 / 288;
  object-fit: cover;
  image-rendering: pixelated;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
  filter: saturate(0.92);
}
#ladeschirm .lade-bild[hidden] { display: none; }

#ladeschirm .lade-titel,
#wechselschirm .lade-titel {
  margin: 0 0 0.3rem;
  font-family: var(--font-display);
  font-size: 3.2rem;
  color: var(--brass-light, #cca75e);
  letter-spacing: 0.03em;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.7);
}
/* --- Fortschrittsbalken: ein gemauerter Kasten, der sich füllt.
   Kein Verlauf, keine runde Kappe — harte Kanten wie alles andere.
   Genauso breit wie das Ladebild darüber (.lade-bild) — beide sollen als EIN
   Block wirken, nicht als Bild mit einem angeklebten schmalen Streifen. */
#ladeschirm .lade-balken,
#wechselschirm .lade-balken {
  position: relative;
  width: min(620px, 88vw);
  height: 10px;
  padding: 2px;
  background: #0e1013;
  border: 2px solid #4a4d54;
  box-shadow: inset 0 0 0 1px #23262b;
}
/* KEIN echter Fortschritt — eine Uhr. Der Balken hing früher an realen
   Meilensteinen (Bündel da, Daten da, Boden fertig) ab und lief deshalb
   unterschiedlich schnell, je nachdem wie lange die jeweilige Rechnung
   wirklich brauchte: mal ein Sprung, mal zähes Warten. Jetzt läuft er als
   feste, immer gleich lange CSS-Animation durch — kontinuierlich und gleich
   schnell von Anfang bis Ende, ohne jede Rücksicht darauf, wie weit das echte
   Laden im Hintergrund (main.ts) gerade ist.

   2 Sekunden — und das ist zugleich die MINDESTDAUER des ganzen Schirms:
   ladeschirm.ts (MINDESTDAUER_MS) wartet mit dem Ausblenden, bis die Uhr
   abgelaufen ist, selbst wenn die Burg längst steht. Beide Zahlen müssen
   deshalb gleich bleiben — ändert sich die eine, muss die andere mit. Braucht
   die Burg LÄNGER als die Uhr (großer Boden, langsame Leitung), gilt weiter
   nur die echte Ladezeit: ladeFertig() zeigt sie ohnehin erst, wenn sie
   wirklich steht, die Uhr steht dann längst bei 100 % und wartet mit. */
#ladeschirm .lade-balken span,
#wechselschirm .lade-balken span {
  display: block;
  height: 100%;
  /* Volle Breite, gestaucht per scaleX statt über width animiert — läuft auf
     dem Compositor, nicht im Hauptthread, der nebenbei das Bodenbild rechnet. */
  width: 100%;
  transform-origin: left center;
  transform: scaleX(0.02);
  background: var(--brass, #a8813d);
  /* Dem Browser vorab sagen, dass hier transformiert wird — sonst entscheidet
     er womöglich erst mitten in der Rechnung, eine eigene Ebene anzulegen,
     und genau dann ist er dafür zu beschäftigt. */
  will-change: transform;
  animation: ladeUhr 2s linear forwards;
}
@keyframes ladeUhr {
  from { transform: scaleX(0.02); }
  to   { transform: scaleX(1); }
}
/* Die Fugen liegen ÜBER der Füllung und gehören zum Kasten, nicht zum
   Balken: Am gestauchten Balken würde das Muster mitgestaucht und wäre bei
   6 % Füllung nur noch Rauschen. So bleiben sie überall gleich breit, und
   die Füllung wandert dahinter durch. */
#ladeschirm .lade-balken::after,
#wechselschirm .lade-balken::after {
  content: "";
  position: absolute;
  inset: 2px;
  pointer-events: none;
  background-image: repeating-linear-gradient(90deg, transparent 0 8px, #0e1013 8px 10px);
}

/* ===========================================================================
   Startbild-Editor (/admin/startbild)

   Lichter und Rauchfahnen über das Burgbild setzen. Die Vorschau benutzt
   bewusst DIESELBEN Klassen wie der echte Startbildschirm (.hero__licht,
   .hero__rauch) — nur so kann sie nicht lügen. Dazu kommen die Marken:
   greifbare Punkte, die es nur hier gibt, damit man auch ein schwaches
   Licht mit der Maus fassen kann.
   =========================================================================== */

.startbild-editor .sb-leiste {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.8rem;
}
.startbild-editor .sb-werkzeuge {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.startbild-editor .sb-werkzeuge button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.startbild-editor .sb-werkzeuge button.aktiv {
  border-color: var(--brass);
  background: linear-gradient(180deg, #4a3a1c, #2a2113);
  color: #f2e3c4;
}
.startbild-editor .sb-regler {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.86rem;
  color: var(--text-dim);
}
.startbild-editor .sb-regler input {
  width: 130px;
}
.startbild-editor .sb-knoepfe {
  display: flex;
  gap: 0.4rem;
  margin-left: auto;
}
.startbild-editor .sb-haupt {
  border-color: var(--brass);
  background: linear-gradient(180deg, #6d5426, #43341a);
  color: #f7ecd6;
}
.startbild-editor .sb-meldung {
  flex-basis: 100%;
  margin: 0;
  min-height: 1.2em;
  font-size: 0.85rem;
  color: var(--text-dim);
}
.startbild-editor .sb-meldung.fehler {
  color: var(--fire-light);
}

/* Die Bühne hält das Seitenverhältnis des Bildes — dadurch stimmen die
   Anteilskoordinaten hier und auf dem Startbildschirm überein. */
.startbild-editor .sb-buehne {
  position: relative;
  width: 100%;
  overflow: hidden;
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: crosshair;
  touch-action: none;
  user-select: none;
}
.startbild-editor .sb-bild {
  position: absolute;
  inset: 0;
  background-image: var(--opener-bild, url("/static/opener/opener.jpg"));
  background-size: 100% 100%;
  /* Ungefiltert wie der Startbildschirm — sonst setzt man die Lichter gegen
     einen Bildeindruck, den es später gar nicht gibt. */
}

.startbild-editor .sb-marken {
  position: absolute;
  inset: 0;
}
.startbild-editor .sb-marke {
  position: absolute;
  width: 13px;
  height: 13px;
  margin: -7px 0 0 -7px;
  border: 2px solid #e8be6a;
  border-radius: 50%;
  background: rgba(10, 12, 15, 0.45);
  cursor: var(--cursor-hand, grab);
}
.startbild-editor .sb-marke.gewaehlt {
  background: rgba(232, 190, 106, 0.5);
  box-shadow: 0 0 0 2px rgba(10, 12, 15, 0.7);
}

/* --- Sprite-Editor: Größe anpassen ---------------------------------------
   Die Maße eines Sprites sind seine Größe im Spiel (buildingSprites.ts rechnet
   textur.width × skala) — deshalb steht dieses Feld gleichberechtigt neben den
   Werkzeugen und nicht in einem Untermenü. */
.se-groesse {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  margin: 0.6rem 0 0.8rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--iron);
}
.se-groesse .se-kopf {
  font-size: 0.80rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass);
}
.se-groesse-knoepfe {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
}
.se-groesse-knoepfe button {
  background: var(--stone-800);
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.25rem 0.5rem;
  font-family: var(--font-body);
  font-size: 0.8rem;
  cursor: var(--cursor-gold);
}
.se-groesse-knoepfe button:hover {
  border-color: var(--brass);
  color: var(--text);
}
#se-groesse-anwenden {
  border-color: var(--brass);
  color: var(--parchment);
}
.se-groesse-feld {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  font-size: 0.82rem;
  margin: 0;
}
.se-groesse-feld input[type="number"] {
  width: 5.5rem;
  background: var(--stone-900, #14171b);
  border: 1px solid var(--iron);
  color: var(--text);
  border-radius: 2px;
  padding: 0.2rem 0.35rem;
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
}
.se-groesse-feld.se-seitenverhaeltnis {
  justify-content: flex-start;
  cursor: var(--cursor-gold);
}
/* Abweichung von der gespeicherten Größe deutlich machen — sonst klickt man
   sich durch und wundert sich später, warum im Hof etwas anderes steht. */
#se-groesse-stand.se-warn {
  color: var(--brass-light, #cca75e);
}

/* --- Stimmung der Bewohner --------------------------------------------------
   War einmal ein eigener, länglicher Knopf mit einem -100/+100-Balken und
   einem 3×3-Pixelgesicht davor — deutlich breiter als jedes Vorratskästchen
   daneben. Jetzt derselbe Zuschnitt wie .res-militaer/.res-einfluss: EIN
   Emblem (die gewürfelten Theatermasken, /dev/icons: "Stimmung"), dahinter
   nur die Zahl. Die Farbe der Zahl trägt die Nachricht — Grün im Plus, Rot
   im Minus —, die Aufschlüsselung bleibt einen Klick entfernt in #moraltafel. */
.moralknopf {
  border-color: #6b7889;
  background: rgba(107, 120, 137, 0.2);
}
.moralknopf[hidden] { display: none; }

.moralwert {
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
}
.moralknopf.gut .moralwert      { color: var(--moss); }
.moralknopf.schlecht .moralwert { color: var(--fire-light); }
.moralknopf.elend .moralwert    { color: #f0c9bd; }

/* --- Die Aufschlüsselung ---------------------------------------------------
   Was hier steht, muss sich zur Zahl im Balken addieren. Der Spieler soll
   nachrechnen können, warum seine Leute murren — sonst ist die Anzeige eine
   Behauptung. */
/* Klappt nach UNTEN auf — seit dem Kopfleisten-Umbau sitzt der Knopf oben,
   und dort ist unterhalb reichlich Platz (wie beim Einstellungs- und
   Avatar-Menü direkt daneben). Vorher, als der Knopf noch in der Fußleiste
   stand, öffnete die Tafel nach OBEN in den Bildschirm hinein — nach dem
   Umzug hätte dieselbe Richtung sie über den oberen Bildrand hinausklappen
   lassen. */
#moraltafel {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 6px;
  min-width: 300px;
  max-width: 360px;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
  padding: 0.7rem 0.85rem;
  z-index: 40;
}
#moraltafel[hidden] { display: none; }
#moraltafel h4 {
  margin: 0 0 0.5rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: normal;
  color: var(--brass-light);
  letter-spacing: 0.04em;
}
ul.moralposten {
  list-style: none;
  margin: 0 0 0.6rem;
  padding: 0;
}
ul.moralposten li {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 0.5rem;
  align-items: baseline;
  padding: 0.2rem 0;
  border-bottom: 1px solid rgba(59, 65, 74, 0.45);
  font-size: 0.88rem;
}
ul.moralposten li:last-child { border-bottom: 0; }
ul.moralposten .wen {
  font-size: 0.78rem;
  color: var(--text-dim);
}
ul.moralposten b {
  font-variant-numeric: tabular-nums;
  min-width: 2.6em;
  text-align: right;
  font-weight: normal;
}
ul.moralposten li.drueckt b { color: var(--fire-light); }
ul.moralposten li.hebt b    { color: var(--moss); }
ul.moralposten li.leer      { color: var(--text-dim); }

.moralsumme {
  margin: 0 0 0.5rem;
  padding-top: 0.4rem;
  border-top: 1px solid var(--iron);
  font-size: 0.86rem;
  color: var(--text-dim);
}
.moralsumme b {
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.moralzuzug {
  margin: 0 0 0.4rem;
  font-size: 0.86rem;
  color: var(--text-dim);
}
.moralhinweis {
  margin: 0;
  font-size: 0.86rem;
  font-style: italic;
  color: var(--parchment-dark);
}

/* === Wehrbau: Mauern, Tore, Türme im Sprite-Editor ========================
   Zwei Spalten: links der Prüfstand (Nachbarschaft schalten, Kachel ansehen),
   rechts die Teileliste zum Austauschen gegen eigene Bilder. */
.wb-raum {
  display: grid;
  grid-template-columns: minmax(20rem, 26rem) 1fr;
  gap: 1rem;
  align-items: start;
}
@media (max-width: 1100px) {
  .wb-raum { grid-template-columns: 1fr; }
}

.wb-pruefstand {
  position: sticky;
  top: 1rem;
  padding: 0.9rem 1rem;
}
.wb-oben {
  display: flex;
  gap: 1rem;
  align-items: center;
}

/* Nachbarschaftskarte: 3x3, die Mitte ist die eigene Kachel. Die Anordnung
   folgt der BILDSCHIRMlage der Nachbarn, nicht der Gitterlogik — man klickt
   dorthin, wo der Nachbar im Spiel zu sehen ist. */
.wb-rasterzeile {
  display: flex;
  gap: 3px;
  margin-bottom: 3px;
}
.wb-zelle {
  width: 2.6rem;
  height: 2rem;
  display: grid;
  place-items: center;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  border: 1px solid var(--iron, #4a4f57);
  background: #1a1c20;
  color: #7c848f;
  border-radius: 2px;
  cursor: var(--cursor-gold), pointer;
}
.wb-zelle.an {
  background: var(--brass-dark, #6b5424);
  border-color: var(--brass-light, #cca75e);
  color: #f0e2c0;
}
.wb-zelle.wb-mitte {
  border-style: dashed;
  color: var(--brass-light, #cca75e);
  cursor: var(--cursor-kupfer);
}

.wb-buehne {
  flex: 1;
  display: grid;
  place-items: center;
  min-height: 12rem;
  padding: 0.4rem;
  border: 1px solid var(--iron, #4a4f57);
  background: #23262b;
  /* Schachbrett, damit Transparenz am Rand sichtbar bleibt */
  background-image:
    linear-gradient(45deg, #1c1f23 25%, transparent 25%, transparent 75%, #1c1f23 75%),
    linear-gradient(45deg, #1c1f23 25%, transparent 25%, transparent 75%, #1c1f23 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
  overflow: auto;
}
.wb-buehne canvas {
  image-rendering: pixelated;
  display: block;
}
.wb-befund {
  margin: 0.6rem 0 0.4rem;
  color: var(--parchment, #d7c7a3);
}

.wb-regler {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  align-items: center;
  margin-top: 0.5rem;
}
.wb-regler label {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.78rem;
  color: #9aa4ae;
}
.wb-vorlagen {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}
.wb-vorlagen button {
  font-size: 0.80rem;
  padding: 0.2rem 0.5rem;
}
/* Der aktive Stoff im Prüfstand — die Lagen-Knöpfe daneben markieren sich
   nicht, weil dort schon das Bild zeigt, welche Lage gewählt ist. Beim Stoff
   sieht man das nicht: Fehlt der zweite Satz noch, sind beide Ansichten leer. */
.wb-vorlagen button.aktiv {
  border-color: var(--brass, #cca75e);
  color: var(--brass-light, #e0c48a);
}
.wb-stofftrenner {
  color: var(--iron, #4a4f57);
  padding: 0 0.2rem;
}

.wb-gruppenkopf {
  margin: 1.1rem 0 0.5rem;
  color: var(--brass-light, #cca75e);
  font-size: 0.9rem;
}
.wb-gruppenkopf:first-child { margin-top: 0; }
.wb-teile {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 0.6rem;
}
.wb-teil {
  display: flex;
  gap: 0.6rem;
  padding: 0.5rem;
  border: 1px solid var(--iron, #4a4f57);
  border-radius: 3px;
  background: #1e2126;
}
/* Ersetzte Teile heben sich ab — man sieht auf einen Blick, was schon
   eigenes Werk ist und was noch das gezeichnete Original. */
.wb-teil.eigen {
  border-color: rgba(204, 167, 94, 0.5);
  background: #23231d;
}
.wb-teil-bild {
  flex: 0 0 auto;
  width: 4.5rem;
  display: grid;
  place-items: center;
  background: #16181b;
  border-radius: 2px;
  overflow: hidden;
}
.wb-teil-bild img,
.wb-teil-bild canvas {
  image-rendering: pixelated;
  max-width: 100%;
  height: auto;
  display: block;
}
/* Die MASKE ist nur die Vorlage, kein Spielbild — gedämpft, damit man auf
   einen Blick sieht, welche Module schon gewürfelt sind und welche nicht. */
.wb-teil-bild img.wb-maske {
  opacity: 0.5;
  filter: grayscale(0.4);
}

/* --- Ausrichten: Bild gegen die Kachelraute halten ------------------------ */
.wb-ausricht-huelle {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(10, 11, 13, 0.82);
  display: grid;
  place-items: center;
  padding: 1rem;
  overflow: auto;
}
.wb-ausricht {
  max-width: min(92vw, 34rem);
  padding: 1rem;
}
.wb-ausricht canvas {
  image-rendering: pixelated;
  display: block;
  margin: 0 auto;
  max-width: 100%;
  height: auto;
  /* Karo dahinter: Ohne ihn ist bei einem freigestellten Bild nicht zu
     erkennen, wo das Bild aufhört und der Hintergrund anfängt. */
  background:
    repeating-conic-gradient(#1c1e22 0% 25%, #16181b 0% 50%) 50% / 12px 12px;
  border: 1px solid rgba(204, 167, 94, 0.25);
}
.wb-ar-regler {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  margin-top: 0.6rem;
}
.wb-ar-regler label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex: 1;
  font-size: 0.82rem;
  color: var(--muted, #8b8b80);
}
.wb-ar-regler input[type="range"] { flex: 1; }
/* Feste Breite, damit die Regler beim Ziehen nicht springen — der Wert ändert
   sich ständig, und ein wanderndes Bedienfeld trifft man nicht. */
.wb-ar-regler output {
  min-width: 3.6rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--parchment, #d7c7a3);
}
.wb-ar-regler .wb-ar-kette {
  flex: 0 0 auto;
  gap: 0.25rem;
}

/* --- Prompt je Modul ------------------------------------------------------ */
.wb-prompt {
  margin: 0.4rem 0 0.5rem;
  border-top: 1px solid rgba(204, 167, 94, 0.18);
  padding-top: 0.4rem;
}
.wb-prompt > summary {
  cursor: pointer;
  font-size: 0.78rem;
  color: var(--brass-light, #cca75e);
  list-style: revert;
}
.wb-prompt textarea {
  width: 100%;
  box-sizing: border-box;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.72rem;
  line-height: 1.45;
  background: #16181b;
  color: var(--parchment, #d7c7a3);
  border: 1px solid rgba(204, 167, 94, 0.25);
  border-radius: 2px;
  padding: 0.4rem;
  resize: vertical;
}
.wb-prompt-fuss {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-top: 0.3rem;
}
.wb-teil-text { min-width: 0; }
.wb-teil-text strong {
  display: block;
  font-size: 0.82rem;
  color: var(--parchment, #d7c7a3);
}
.wb-teil-text p { margin: 0.3rem 0 0.45rem; }
.wb-teil-knoepfe {
  display: flex;
  gap: 0.4rem;
  align-items: center;
}
.wb-hochladen {
  font-size: 0.80rem;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--iron, #4a4f57);
  border-radius: 2px;
  color: var(--parchment, #d7c7a3);
  cursor: var(--cursor-gold), pointer;
}
.wb-hochladen:hover { background: var(--stone-600, #2c3138); }

/* Rahmen für Knopf + Tafel: die Tafel klappt unter dem Knopf auf, nicht am
   linken Rand des Kopfbalkens. */
.moralfeld {
  position: relative;
  display: inline-flex;
}

/* Der Notausgang des Wehrbau-Reiters: verwirft alle eigenen Bilder. Warnfarbe,
   weil er wirklich etwas wegwirft — aber nichts Unwiederbringliches, die
   gezeichneten Fassungen stehen im Code. */
.wb-notausgang {
  margin-left: auto;
  font-size: 0.82rem;
  padding: 0.25rem 0.6rem;
  color: #d8b48a;
  border: 1px solid rgba(190, 120, 70, 0.55);
  background: rgba(70, 40, 26, 0.5);
}
.wb-notausgang:hover {
  background: rgba(102, 55, 32, 0.7);
  color: #f2d9bd;
}

/* Der Würfel-Knopf am Wehrbau-Teil: hebt sich messingfarben ab, weil er als
   einziger Geld kostet (Nanobanana-Aufruf). */
.wb-wuerfeln {
  font-size: 0.80rem;
  padding: 0.2rem 0.5rem;
  color: var(--brass-light, #cca75e);
  border: 1px solid rgba(204, 167, 94, 0.45);
  background: rgba(60, 48, 22, 0.5);
}
.wb-wuerfeln:hover:not(:disabled) {
  background: rgba(92, 73, 33, 0.7);
  color: #f0e2c0;
}
.wb-wuerfeln:disabled {
  opacity: 0.6;
  cursor: var(--cursor-kupfer);
}
.wb-teil-knoepfe {
  flex-wrap: wrap;
  row-gap: 0.3rem;
}

/* --- Abgaben: die Steuerwahl in der Moraltafel -----------------------------
   Sie steht dort, weil sie in dieselbe Rechnung gehört: der Satz taucht oben
   als Moralposten auf, und darunter stellt man ihn um. Jede Stufe zeigt
   Ertrag UND Preis — ein Regler, der nur die Einnahme nennt, wäre eine Falle. */
.steuerwahl {
  margin-top: 0.7rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--iron);
}
.steuerwahl h4 {
  margin: 0 0 0.2rem;
}
.steuerstufen {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.4rem;
  margin-top: 0.5rem;
}
.steuerstufe {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem 0.5rem;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--text-dim);
  font-family: var(--font-body);
  text-align: left;
  cursor: var(--cursor-gold);
}
.steuerstufe:hover:not(:disabled) {
  border-color: var(--brass);
}
.steuerstufe.aktiv {
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.18);
}
.steuerstufe:disabled {
  opacity: 0.5;
}
.steuerstufe .stufe-name {
  color: var(--text);
  font-size: 0.9rem;
}
.steuerstufe.aktiv .stufe-name {
  color: var(--brass-light);
}
.steuerstufe .stufe-ertrag,
.steuerstufe .stufe-moral {
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
}
.steuerstufe .stufe-moral.hebt {
  color: var(--moos-hell, #a9c795);
}
.steuerstufe .stufe-moral.drueckt {
  color: var(--fire-light);
}

/* ===========================================================================
   Die TAGESUHR im Kopfband — eine Sanduhr neben dem Datum. Beim Schweben
   nennt sie die Uhrzeit der Spielwelt, sonst steht sie still da.

   Drei Anlaeufe stehen hinter dieser Schlichtheit, und alle drei sind
   verworfen worden:

     ein WORT ("Morgengrauen")   stellte die Zeile zu und sagte nichts
                                 darueber, wie weit der Abschnitt ist
     eine DREHENDE SCHEIBE       mechanisch richtig, bei 26 Pixeln unlesbar
     ZWOELF GEMALTE HIMMEL       schoen, aber der Blick blieb daran haengen

   Uebrig ist das Kleinste, das die Frage beantwortet: ein ruhiges Zeichen,
   die Zahl erst auf Nachfrage.

   Die Sanduhr stand hier frueher schon einmal, damals als COUNTDOWN bis zum
   naechsten Serverschritt (mit Zahl daneben und drehendem Glas). Das Bild ist
   geblieben, seine Bedeutung nicht — sie zeigt auf nichts mehr, sie steht
   fuer "Zeit".
   =========================================================================== */
/* Datum und Uhr als EIN Posten des Kopfbands. Der column-gap von #topbar
   (1,5rem) liegt damit LINKS von beiden, nicht dazwischen — die Uhr rueckt an
   das Jahr heran und wandert mit ihm, auch wenn das Band umbricht.

   Hier stand kurz ein negativer Rand an der Uhr, der den gap aufheben sollte.
   Das hielt nur, solange beide in derselben Zeile standen: Bricht das Band um
   (in der Werkstatt regelmaessig, weil das Entwickler-Abzeichen den Titel
   verlaengert), steht die Uhr allein in einer Zeile — und der negative Rand
   schob sie ueber die linke Kante hinaus. */
.kalenderplatz {
  position: relative; /* Bezug fuer die Zeitrechnungs-Tafel */
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-width: 0;
}
.tagesuhr {
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: none;
  vertical-align: middle;
  cursor: help;
}
/* DIE ZEIGERUHR. Das Zifferblatt ist ein Bild, die Zeiger sind SVG und liegen
   deckungsgleich darueber — siehe client/src/tagesuhr.ts, warum gemischt.

   22px statt der 18 der alten Sanduhr: Ein Zeiger braucht Weg, um eine
   Richtung zu zeigen. Darunter sind Stunden- und Minutenzeiger nicht mehr
   auseinanderzuhalten, und die Uhr wird zum Fleck. */
.tagesuhr {
  /* Um die Haelfte groesser als beim ersten Bau (22px). Eine Uhr, die man
     ablesen soll, darf nicht das kleinste Zeichen der Leiste sein. */
  width: 33px;
  height: 33px;
}
.tagesuhr-blatt {
  display: block;
  width: 100%;
  height: 100%;
  /* Gewuerfeltes Pixel-Icon — hier darf NICHT geglaettet werden, sonst
     verwaschen die Kanten (dieselbe Regel wie bei den Vorrats-Emblemen). */
  image-rendering: pixelated;
  opacity: 0.85;
  transition: opacity 0.15s ease-out;
}

/* Die Zeiger liegen UEBER dem Blatt und decken es genau. `inset: 0` statt
   fester Masse: So folgen sie jeder Aenderung an .tagesuhr von selbst, und die
   Groesse steht nur an EINER Stelle. */
.tagesuhr-zeiger {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  opacity: 0.9;
  transition: opacity 0.15s ease-out;
}
/* Die Zeiger sind PFEILE — eine Flaeche mit Kontur, nicht zwei Striche
   uebereinander. Ein Strich mit runder Kappe hat kein Vorn: Man sieht seine
   Richtung, aber nicht, welches Ende zaehlt, und der Zeiger steht hinten
   absichtlich ueber die Mitte hinaus.

   `miter` und nicht `round`: Die Widerhaken der Spitze sind der ganze Zweck
   der Form. Rund verschliffen waeren sie wieder ein Knubbel. */
.tagesuhr-arm {
  fill: var(--brass-light, #cca75e);
  stroke: #14100b;
  stroke-width: 1.5;
  stroke-linejoin: miter;
  stroke-miterlimit: 6;
}
.tagesuhr-nagel {
  fill: var(--brass-light, #cca75e);
  stroke: #14100b;
  stroke-width: 1.6;
}

.tagesuhr:hover .tagesuhr-blatt,
.tagesuhr:focus-visible .tagesuhr-blatt,
.tagesuhr:hover .tagesuhr-zeiger,
.tagesuhr:focus-visible .tagesuhr-zeiger {
  opacity: 1;
}

/* DIE ZEITRECHNUNGS-TAFEL, aufklappbar am Datum.

   Hier stand die Sprechblase der UHR, die beim Schweben die Uhrzeit als Zahl
   nannte. Sie ist weg (22.08.2026): Seit die Zeiger gehen, liest man die Zeit
   am Blatt ab, und eine Blase, die das Abgelesene wiederholt, steht nur im
   Weg. Die Form lebt hier weiter, fuer die Frage, die das Blatt NICHT
   beantwortet — wie schnell die Zeit ueberhaupt vergeht.

   Kein title-Attribut, aus demselben Grund wie damals: Der native Tooltip
   verzoegert etwa eine Sekunde, bricht bei der kleinsten Mausbewegung ab, und
   neben einer eigenen Blase erschienen ZWEI Tooltips uebereinander. */
.datumstafel {
  position: absolute;
  top: calc(100% + 0.5rem);
  /* Am linken Rand des Datums ausgerichtet und NICHT mittig: Das Datum steht
     ganz links im Kopfband, eine mittige Tafel liefe links aus dem Bild. */
  left: 0;
  z-index: 70;
  width: max-content;
  max-width: 22rem;
  padding: 0.5rem 0.6rem;
  background: linear-gradient(180deg, rgba(28, 31, 36, 0.985), rgba(18, 20, 23, 0.985));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.7);
  color: var(--brass-light);
  font-size: 0.85rem;
  line-height: 1.35;
  letter-spacing: normal;
  text-align: left;
  white-space: normal;
  pointer-events: none;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.1s ease-out;
}
.datumstafel b {
  display: block;
  margin-bottom: 0.35rem;
  color: #e8dcc0;
}
/* Zwei Spalten, damit die Dauern untereinander stehen und vergleichbar sind —
   als Fliesstext waere die Tafel eine Wand. */
.datumstafel-gitter {
  display: grid;
  grid-template-columns: auto auto;
  gap: 0.1rem 0.9rem;
  font-variant-numeric: tabular-nums;
}
.datumstafel-gitter > span:nth-child(even) {
  text-align: right;
  color: #e8dcc0;
}
.datumstafel-fuss {
  display: block;
  margin-top: 0.4rem;
  padding-top: 0.35rem;
  border-top: 1px solid rgba(140, 110, 60, 0.35);
  color: #9a8b6d;
  font-size: 0.8rem;
}
/* `~` und nicht ` `: Die Tafel ist ein GESCHWISTER des Datums, kein Kind —
   ui.ts ueberschreibt den Inhalt von #calendar bei jedem Serverabruf und
   raeumte sie als Kind jedes Mal wieder weg. */
#topbar .season.datum-erklaert:hover ~ .datumstafel,
#topbar .season.datum-erklaert:focus-visible ~ .datumstafel {
  opacity: 1;
  transform: translateY(0);
}




/* --- Wer hier wohnt: Bewohner mit Gesicht ----------------------------------
   Dieselbe Figur wie auf dem Hof (client/src/figurWahl.ts), damit man die
   Person draußen wiedererkennt. Pixelgenau skaliert — die Sprites sind mit
   doppelter Weltgröße gebacken und würden sonst weichgezeichnet. */
/* DIE STALLLISTE (Migration 0048). Dieselbe Kachelform wie die Bewohner-
   liste darunter — ein Tier ist zwar kein Bewohner, steht in der Tafel aber
   an derselben Stelle und soll sich nicht wie ein Fremdkörper lesen.

   Der Unterschied ist die AUSWAHL statt eines Berufs: Ein Bewohner arbeitet,
   wo er zugewiesen ist, ein Tier tut nur etwas, wenn man es einteilt. Genau
   diese Entscheidung ist der Grund, warum es die Tafel gibt — sie bekommt
   deshalb die ganze verbleibende Breite. */
.gp-tierliste {
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.gp-tier {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.22rem 0.35rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
/* Ein Farbtupfen statt eines Bildchens: Der Stall steht in der Tafel, nicht
   auf dem Hof, und ein 16-Pixel-Pferd wäre bei dieser Größe nur ein Fleck.
   Braun für den Ochsen (Zugtier, Erde), heller Fuchs für das Pferd. */
.gp-tier-art {
  flex: none;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.5);
}
.gp-tier-ochse { background: #7a5c3a; }
.gp-tier-pferd { background: #b5813f; }
.gp-tier .gp-name {
  flex: none;
  min-width: 3.4rem;
  color: var(--text);
}
/* Die Auswahl nimmt den Rest — dort steht der eigentliche Inhalt der Zeile. */
/* Der ZUSTAND statt einer Auswahl — für Tiere, die nichts zu entscheiden
   haben (25.08.2026). Beim Schaf stand dort ein Klappfeld mit genau einem
   Eintrag; es sah aus wie eine Entscheidung und war keine. Jetzt steht da,
   was man an einem Schaf wirklich wissen will: ob es zu fressen hat.
   Die Breite ist dieselbe wie beim Klappfeld daneben, damit die Zeilen einer
   gemischten Liste (Stall mit Ochse und Schaf) nicht gegeneinander springen. */
.gp-tier-zustand {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 0.82rem;
  color: var(--text-dim);
  align-self: center;
}
.gp-tier-zustand.hungrig {
  color: #d8ab7c;
  font-weight: 600;
}

.gp-tier-wahl {
  flex: 1 1 auto;
  min-width: 0;
  font-family: inherit;
  font-size: 0.78rem;
  color: var(--text);
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  padding: 0.1rem 0.2rem;
  cursor: var(--cursor-gold, pointer);
}
.gp-tier-wahl:disabled { opacity: 0.5; }
/* Die beiden Kaufknöpfe nebeneinander, gleich breit: Ochse oder Pferd ist
   EINE Entscheidung mit zwei Antworten, keine Liste. */
.gp-tier-kauf {
  display: flex;
  gap: 0.35rem;
}
.gp-tier-kauf .gp-btn {
  flex: 1 1 0;
  min-width: 0;
}

.gp-bewohnerliste {
  list-style: none;
  margin: 0 0 0.5rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.gp-bewohner {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.22rem 0.35rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
/* Der Entlassen-Knopf in der Garnisonsliste. Winzig und unauffällig, aber
   vorhanden: Einen Söldner zu entlassen ist eine gewöhnliche Verwaltungssache,
   kein Drama — und ein eigener Abschnitt dafür wäre mehr Apparat als Nutzen. */
.gp-mini {
  flex: none;
  padding: 0 0.3rem;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 0.95rem;
  line-height: 1;
  cursor: var(--cursor-gold);
}
.gp-mini:hover { color: #d08a7a; }
.gp-mini:disabled { opacity: 0.4; cursor: var(--cursor-kupfer); }
.gp-hinweis.warnung { color: #d3a273; }
.gp-figur {
  flex: none;
  width: 16px;
  height: auto;
  image-rendering: pixelated;
  /* Auf den Boden stellen statt mittig schweben lassen */
  align-self: flex-end;
}
.gp-bewohner .gp-name {
  flex: 1 1 auto;
  font-size: 0.88rem;
}
.gp-bewohner .gp-beruf {
  flex: none;
  font-size: 0.76rem;
  color: var(--text-dim);
}
.gp-bewohner .gp-stimmung {
  flex: none;
  min-width: 2.2rem;
  text-align: right;
  font-size: 0.78rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
}
.gp-bewohner .gp-stimmung.gut {
  color: var(--moos-hell, #a9c795);
}
.gp-bewohner .gp-stimmung.schlecht {
  color: var(--fire-light);
}

/* --- Bildmodell: die Kostenstufe für neue Assets ---------------------------
   Steht ÜBER den Erzeugen-Knöpfen, nicht in einer Einstellungsseite: Wer
   gleich würfeln will, soll im selben Blick sehen, was der Wurf kostet. Die
   Reihenfolge ist teuer → günstig, die Pfeile machen sie lesbar. */
.se-modellwahl {
  margin: 0.9rem 0 0.4rem;
  padding: 0.55rem 0.7rem;
  background: var(--stone-800);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
.se-modell-kopf {
  display: block;
  margin-bottom: 0.45rem;
  font-size: 0.85rem;
  color: var(--brass-light);
}
.se-modellstufen {
  display: flex;
  align-items: stretch;
  gap: 0.35rem;
  flex-wrap: wrap;
}
.se-modellpfeil {
  align-self: center;
  color: var(--text-dim);
  opacity: 0.6;
}
.se-modellstufe {
  flex: 1 1 0;
  min-width: 8rem;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.35rem 0.5rem;
  background: var(--stone-900);
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--text-dim);
  font-family: var(--font-body);
  text-align: left;
  cursor: var(--cursor-gold);
}
.se-modellstufe:hover:not(:disabled) {
  border-color: var(--brass);
}
.se-modellstufe.aktiv {
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.18);
}
.se-modellstufe:disabled {
  opacity: 0.5;
}
.se-modellstufe .stufe-name {
  color: var(--text);
  font-size: 0.88rem;
}
.se-modellstufe.aktiv .stufe-name {
  color: var(--brass-light);
}
.se-modellstufe .stufe-kosten {
  font-size: 0.82rem;
}
/* Die teuerste Stufe soll man sehen, bevor man sie wählt */
.se-modellstufe:first-child .stufe-kosten {
  color: var(--fire-light);
}

/* --- Startseite: die Wahl zwischen Spielen und Verwalten -------------------
   Zwei gleichwertige Wege nebeneinander statt eines Hauptknopfs mit einem
   Kleingedruckten daneben. Wer testet, wechselt ständig zwischen beidem. */
/* Die Werkstatt-Einfahrt hält sich knapp: Sie steht vor dem Burgbild, und wer
   sie zum dritten Mal sieht, will nicht wieder sieben Absätze lesen. Die
   Begründungen sind deshalb in Merkzettel gewandert, die beim Überfahren
   rechts neben der Tafel aufgehen — der Text bleibt vollständig erhalten,
   er drängt sich nur nicht mehr auf. */
.start-wege {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.7rem;
  margin-top: 0.9rem;
}

/* Die Tafel im Schaufenster (client/src/main.ts, zeigeSchaufensterTafel).
   Unten LINKS, damit sie dem Versionsschild unten rechts nicht ins Gehege
   kommt, und schmal genug, dass die Burg daneben zu sehen bleibt. */
.schaufenster-tafel {
  position: fixed;
  z-index: 40;
  left: 1rem;
  bottom: 1rem;
  max-width: 22rem;
  padding: 0.9rem 2.2rem 0.9rem 1rem;
  background: color-mix(in srgb, var(--stone-800) 92%, transparent);
  border: 1px solid var(--iron);
  border-left: 3px solid var(--brass);
  color: var(--text);
  font-size: 0.88rem;
  line-height: 1.5;
  box-shadow: 0 6px 22px rgb(0 0 0 / 45%);
}
.schaufenster-tafel p {
  margin: 0 0 0.5rem;
}
.schaufenster-tafel p:last-child {
  margin-bottom: 0;
}
.schaufenster-kopf {
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--brass-light);
  letter-spacing: 0.04em;
}
.schaufenster-leise {
  color: var(--text-dim);
  font-size: 0.82rem;
}
.schaufenster-zu {
  position: absolute;
  top: 0.35rem;
  right: 0.45rem;
  background: none;
  border: 0;
  color: var(--text-dim);
  font-size: 1.15rem;
  line-height: 1;
  padding: 0.2rem 0.35rem;
  cursor: var(--cursor-gold);
}
.schaufenster-zu:hover,
.schaufenster-zu:focus-visible {
  color: var(--brass-light);
}
@media (max-width: 40rem) {
  .schaufenster-tafel {
    left: 0.6rem;
    right: 0.6rem;
    bottom: 0.6rem;
    max-width: none;
  }
}

/* Das Schaufenster: unten rechts, klein und ohne Rahmen — es ist ein
   Nebenweg, kein dritter Hauptknopf. Wer ein Losungswort hat, geht durchs
   Tor; wer nur zusehen will, findet hier hinein, ohne dass die Anmeldung
   dadurch an Gewicht verliert. */
.reinschauen {
  /* fixed statt absolute: Der Link steht als Geschwister der Tafel, und ohne
     einen eigens positionierten Elternteil bezöge sich absolute auf das
     Fenster — nur eben unzuverlässig, sobald die Seite scrollt. */
  position: fixed;
  z-index: 5;
  right: 1.4rem;
  bottom: 1.1rem;
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  color: var(--text-dim);
  text-decoration: none;
  border-bottom: 1px dotted currentColor;
  padding-bottom: 1px;
  transition: color 0.15s;
}
.reinschauen::before {
  content: "› ";
  opacity: 0.7;
}
.reinschauen:hover,
.reinschauen:focus-visible {
  color: var(--brass-light);
}
@media (max-width: 40rem) {
  /* Auf schmalem Schirm nicht überlagern, sondern anhängen. */
  .reinschauen {
    position: static;
    display: block;
    margin: 0.8rem 0 0;
    text-align: right;
  }
}
.start-weg {
  padding: 0.7rem 0.8rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
.start-weg h3 {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.35rem;
  font-size: 1.15rem;
  color: var(--brass-light);
}
.start-weg form {
  margin-top: 0.45rem;
}
.start-weg p {
  margin: 0.2rem 0;
  font-size: 0.85rem;
}

/* Das Fragezeichen ist der einzige Hinweis, dass es mehr zu lesen gibt —
   ein Merkzettel, den niemand findet, ist keiner. */
.start-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.05rem;
  height: 1.05rem;
  border: 1px solid var(--brass-dark);
  border-radius: 50%;
  font-family: var(--font-body);
  font-size: 0.78rem;
  color: var(--brass);
  cursor: var(--cursor-gold);
}
.start-weg:hover .start-info {
  border-color: var(--brass);
  color: var(--brass-light);
}

/* Beide Merkzettel hängen am Kasten der WEGE, nicht am einzelnen Weg: So
   gehen sie immer rechts NEBEN der Tafel auf statt über dem Nachbarweg, und
   beide sitzen an derselben Stelle — es ist ohnehin nie mehr als einer zu
   sehen. */
.start-tip {
  position: absolute;
  left: calc(100% + 0.8rem);
  top: 0;
  width: 15rem;
  padding: 0.7rem 0.8rem;
  background: linear-gradient(180deg, #2c3138, #1e2227);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.7);
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--text-dim);
  opacity: 0;
  /* Kein visibility:hidden — der Text soll für Vorleseprogramme lesbar
     bleiben, auch wenn er gerade nicht zu sehen ist. */
  pointer-events: none;
  transition: opacity 0.12s ease-out;
  z-index: 6;
}
.start-tip p {
  margin: 0 0 0.5rem;
  font-size: inherit;
}
.start-tip p:last-child {
  margin-bottom: 0;
}
.start-weg:hover .start-tip,
.start-weg:focus-within .start-tip {
  opacity: 1;
}

/* Zu schmal für einen Merkzettel daneben: dann klappt er unter dem Weg auf.
   Die Schwelle ist gerechnet, nicht geraten: Die Tafel ist 700 px breit und
   mittig, rechts daneben braucht der Zettel 255 px plus Abstand — unter rund
   1156 px Fensterbreite ragt er sonst aus dem Bild. 1200 lässt Luft. */
@media (max-width: 1200px) {
  .start-tip {
    left: 0;
    top: calc(100% + 0.4rem);
    width: 100%;
  }
}

/* --- Verwaltungsbereich ---------------------------------------------------- */
.adm-zahlen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 0.6rem;
  margin-bottom: 1.2rem;
}
.adm-zahl {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.6rem 0.75rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
.adm-zahl .wert {
  font-size: 1.5rem;
  line-height: 1.1;
  color: var(--brass-light);
  font-variant-numeric: tabular-nums;
}
.adm-zahl .text {
  font-size: 0.78rem;
  color: var(--text-dim);
}

/* Befunde: die Farbe sagt, ob man hinsehen muss */
.adm-liste {
  list-style: none;
  margin: 0.4rem 0 1.2rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.adm-liste li {
  padding: 0.45rem 0.7rem;
  border-left: 3px solid var(--iron);
  background: rgba(0, 0, 0, 0.18);
  font-size: 0.9rem;
  line-height: 1.45;
}
.adm-liste li.gut {
  border-left-color: rgba(122, 145, 102, 0.8);
}
.adm-liste li.warnung {
  border-left-color: var(--fire);
}
.adm-liste strong {
  color: var(--text);
}

.adm-knoepfe {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-top: 0.6rem;
}
.adm-knoepfe form {
  margin: 0;
}

/* Rückmeldung nach einer Verwaltungshandlung. Grün und über der Überschrift,
   also dort, wo der Blick nach dem Seitenwechsel ohnehin landet — eine
   Meldung weiter unten hätte dasselbe Problem wie gar keine. */
.adm-meldung {
  margin: 0 0 1rem;
  padding: 0.7rem 1rem;
  background: rgba(60, 90, 45, 0.28);
  border: 1px solid #4d7a3c;
  border-left: 4px solid #6ac46a;
  border-radius: 2px;
  color: #cbe6b8;
  line-height: 1.5;
}

/* Zurücksetzen einer einzelnen Burg (Tabelle "Burgplätze").
   Zurückhaltend gehalten — der Knopf steht in siebzig Zeilen untereinander
   und darf nicht wie ein Aufruf wirken. Rot wird er erst beim Berühren:
   dann ist die Hand schon dort, und die Warnung kommt zur rechten Zeit. */
.burg-zurueck {
  font: inherit;
  font-size: 0.78rem;
  padding: 0.2rem 0.6rem;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  white-space: nowrap;
}
.burg-zurueck:hover {
  color: #d4695a;
  border-color: #8a4a3c;
  background: rgba(90, 45, 40, 0.25);
}

/* Die Testburg — der große Eingang ganz oben in der Verwaltung.
   Bewusst breiter und lauter als alles andere auf der Seite: Sie ist das
   Werkzeug, das man am häufigsten braucht, und stand vorher als kleine Tafel
   im dritten Abschnitt, wo man sie kennen musste, um sie zu finden. */
.testburg {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem;
  margin-bottom: 1.1rem;
  padding: 1.2rem 1.4rem;
  background: linear-gradient(180deg, rgba(46, 38, 22, 0.85), rgba(22, 24, 27, 0.92));
  border: 1px solid var(--brass-dark);
  border-left: 4px solid var(--brass);
  border-radius: 3px;
}
.testburg .tb-text { flex: 1 1 22rem; }
.testburg h2 {
  margin: 0 0 0.35rem;
  font-size: 1.5rem;
  color: var(--brass-light);
  letter-spacing: 0.01em;
}
.testburg p { margin: 0 0 0.4rem; line-height: 1.5; max-width: 46rem; }
.testburg .tb-stand { margin: 0; color: var(--text-dim); font-size: 0.86rem; }
.testburg .tb-tat {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0.5rem;
}
/* Der Knopf selbst: groß genug, dass man ihn nicht sucht. */
.tb-knopf {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.95rem 2.1rem;
  font-size: 1.15rem;
  font-weight: 600;
  color: #14171a;
  background: linear-gradient(180deg, var(--brass-light), var(--brass));
  border: 1px solid var(--brass-light);
  border-radius: 3px;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.45);
}
.tb-knopf:hover {
  background: linear-gradient(180deg, #f0d79a, var(--brass-light));
  color: #14171a;
}
/* Turm mit Zinnen, rein aus Rahmen gezeichnet — passt zum Wappen im Spiel. */
.tb-wappen {
  width: 14px;
  height: 16px;
  background:
    linear-gradient(#14171a, #14171a) 0 0 / 4px 5px no-repeat,
    linear-gradient(#14171a, #14171a) 10px 0 / 4px 5px no-repeat,
    linear-gradient(#14171a, #14171a) 0 5px / 14px 11px no-repeat;
  opacity: 0.85;
}
.tb-neu {
  font: inherit;
  font-size: 0.82rem;
  padding: 0.3rem 0.7rem;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.tb-neu:hover { color: #d4695a; border-color: #8a4a3c; }

/* Werkzeugkacheln — jede sagt, wozu sie gut ist. Ein Raster aus nackten
   Links wäre schneller gebaut und beim zehnten Werkzeug unbrauchbar. */
.adm-werkzeuge {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 0.7rem;
}
.adm-werkzeug {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.8rem 0.9rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--iron);
  border-radius: 2px;
  border-bottom: 1px solid var(--iron);
  text-decoration: none;
}
.adm-werkzeug:hover {
  border-color: var(--brass);
}
.adm-werkzeug strong {
  color: var(--brass-light);
}
.adm-werkzeug .muted {
  font-size: 0.82rem;
  line-height: 1.4;
}

/* Zahlenspalten rechtsbündig — sonst liest sich keine Tabelle */
.panel table td.zahl,
.panel table th.zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.panel table .gut {
  color: #a9c795;
}

/* --- Klangwerkstatt ---------------------------------------------------------
   Eine Liste, kein Mischpult. Jede Zeile ist EIN Klang: Name links, Datei und
   Lautstärke in der Mitte, Anschlagen rechts. Die Spaltenbreiten sind fest,
   damit die Regler untereinander stehen und man Lautstärken über die ganze
   Liste hinweg vergleichen kann — genau darum geht es beim Abstimmen. */
.kw-kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.kw-kopfknoepfe {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
#kw-speichern.geaendert {
  border-color: var(--brass);
  color: var(--brass-light);
}
.kw-meldung {
  font-size: 0.85rem;
  color: var(--muted);
}
.kw-meldung.ok { color: #a9c795; }
.kw-meldung.fehler { color: #d08a7a; }

.kw-zaehler {
  font-size: 0.78rem;
  font-weight: normal;
  margin-left: 0.6rem;
}

.kw-liste {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--iron);
  border: 1px solid var(--iron);
}
.kw-zeile {
  display: grid;
  grid-template-columns: minmax(12rem, 1fr) 12rem 11rem auto;
  align-items: center;
  gap: 0.9rem;
  padding: 0.45rem 0.7rem;
  background: rgba(0, 0, 0, 0.25);
}
/* Belegte Stellen leicht hervorheben — leere sind Lücken, keine Fehler, und
   sollen als solche lesbar bleiben statt zu alarmieren. */
.kw-zeile.stumm { opacity: 0.62; }
.kw-name {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-width: 0;
}
.kw-name strong { color: var(--brass-light); }
.kw-wann {
  font-size: 0.80rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.kw-hinweis {
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--muted);
}
.kw-zeile select { width: 100%; }
.kw-regler {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.kw-regler input[type="range"] { flex: 1; min-width: 0; }
.kw-regler output {
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
  color: var(--muted);
  min-width: 3.1rem;
  text-align: right;
}
.kw-hoeren { white-space: nowrap; }

/* Der Stopp-Knopf ist im Ruhezustand grau und unscheinbar — er soll erst
   auffallen, wenn wirklich etwas läuft und abzubrechen ist. */
#kw-stopp.aktiv {
  border-color: var(--brass);
  color: var(--brass-light);
}
#kw-stopp:disabled { opacity: 0.45; }

/* „alle anhören" gehört zur Überschrift der Gruppe, nicht in die Liste:
   Es hört die Gruppe als Ganzes ab, nicht eine ihrer Zeilen. */
.kw-durchhoeren {
  float: right;
  font-size: 0.78rem;
  padding: 0.2rem 0.7rem;
}

/* Ablage für neue Klänge. Gestrichelter Rand als Einladung zum Ziehen — dass
   auch ein Knopf danebensteht, ist Absicht: Ziehen und Ablegen ist nicht auf
   jedem Gerät bequem. */
.kw-ablage {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 1rem;
  border: 1px dashed var(--iron);
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.18);
}
.kw-ablage.bereit {
  border-color: var(--brass);
  background: rgba(138, 122, 85, 0.12);
}
#kw-upload-stand { margin: 0.6rem 0 0; }

@media (max-width: 780px) {
  .kw-zeile {
    grid-template-columns: 1fr auto;
    row-gap: 0.5rem;
  }
  .kw-name { grid-column: 1 / -1; }
}

/* --- Cunrat, der Schreiber ---------------------------------------------------
   Der Lehrgang der ersten Stunde. Sitzt oben rechts UNTER dem Kopfband: dort
   ist Platz, man sucht Rat oben, und unten liegt die Bauleiste, auf die er
   zeigt. Bewusst schmal — er soll begleiten, nicht die Burg verdecken. */
.schreiber {
  position: fixed;
  top: 7.2rem;
  right: 1rem;
  width: min(22rem, 34vw);
  z-index: 40;
  /* Pergament: heller als das übrige HUD, damit er als BLATT gelesen wird und
     nicht als weitere Tafel des Spiels. */
  background: linear-gradient(180deg, #e8dfc8, #d9cfb4);
  color: #2c2418;
  border: 1px solid #8a7a55;
  border-radius: 2px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.55);
  padding: 0.7rem 0.85rem 0.8rem;
  font-size: 0.9rem;
}
/* Eingeklappt bleibt nur das Siegel stehen. */
.schreiber.zu {
  width: auto;
  background: none;
  border: none;
  box-shadow: none;
  padding: 0;
}
.sb-siegel {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 50%;
  border: 2px solid #8a7a55;
  background: radial-gradient(circle at 35% 30%, #b1503f, #7d3325);
  color: #f0e2c8;
  /* Ein Fragezeichen statt der Schreibfeder. Die Feder war hübsch, sagte aber
     "hier wird geschrieben" — geklickt wird sie jedoch, wenn man etwas WISSEN
     will. Größer und fetter als die Feder, weil ein einzelnes Satzzeichen auf
     einem Siegel sonst untergeht. */
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: bold;
  line-height: 1;
  cursor: var(--cursor-gold);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
  /* Bildnis statt Fragezeichen: das Siegel bleibt der Rahmen (Rand, Schatten,
     roter Grund als Rückfalllösung, falls das Bild einmal fehlt), das Gesicht
     füllt ihn kreisrund aus. */
  padding: 0;
  overflow: hidden;
}
/* Der Rückgabe-Anteil am Abriss-Werkzeug — klein und grün unter dem Namen,
   damit man vor dem Klick weiß, was zurückkommt. Grün wie die aufsteigende
   Zahl beim Abriss selbst, damit beides als dieselbe Aussage gelesen wird. */
.bau-ikone__rueckgabe {
  display: block;
  font-size: 0.62rem;
  line-height: 1;
  margin-top: 0.1rem;
  color: #9fc47a;
}

/* Die Rückgabe eines Abrisses: steigt über der Abbruchstelle auf und
   verblasst. Liegt über der Burg (z-index), reagiert aber auf nichts —
   pointer-events:none, sonst schluckte sie den nächsten Klick, und man
   stünde mit dem Abrisswerkzeug vor einer Stelle, die sich nicht mehr
   treffen lässt. translate(-50%) zentriert sie über dem Punkt. */
.rueckgabe-flug {
  position: fixed;
  z-index: 60;
  pointer-events: none;
  display: flex;
  gap: 0.5rem;
  transform: translate(-50%, -50%);
  font-size: 0.95rem;
  font-weight: 600;
  color: #cfe8b0;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.95), 0 0 6px rgba(0, 0, 0, 0.8);
  animation: rueckgabe-auf 1.9s ease-out forwards;
}
.rueckgabe-flug span {
  display: flex;
  align-items: center;
  gap: 0.2rem;
  white-space: nowrap;
}
.rueckgabe-flug img {
  width: 1.1rem;
  height: 1.1rem;
  image-rendering: pixelated;
}
@keyframes rueckgabe-auf {
  0%   { opacity: 0; transform: translate(-50%, -30%) scale(0.9); }
  15%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  70%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -190%) scale(1); }
}

.sb-siegel:hover { border-color: var(--brass-light); }
.sb-siegel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 15%;
  display: block;
}

.sb-kopf {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  border-bottom: 1px solid rgba(90, 74, 44, 0.35);
  padding-bottom: 0.35rem;
  margin-bottom: 0.5rem;
}
.sb-bildnis {
  width: 3.6rem;
  height: 3.6rem;
  border-radius: 50%;
  border: 2px solid #8a7a55;
  object-fit: cover;
  object-position: center 15%;
  align-self: center;
  flex-shrink: 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.sb-wer {
  font-family: inherit;
  font-size: 1.15rem;
  color: #5a4526;
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}
.sb-wer small {
  font-family: inherit;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #7b6a4a;
}
.sb-zaehler {
  margin-left: auto;
  font-size: 0.80rem;
  color: #7b6a4a;
  font-variant-numeric: tabular-nums;
}
.sb-zu {
  background: none;
  border: none;
  color: #7b6a4a;
  font-size: 1.2rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: var(--cursor-gold);
}
.sb-zu:hover { color: #2c2418; }

.sb-titel {
  margin: 0 0 0.35rem;
  font-family: inherit;
  font-size: 1.05rem;
  color: #4a3a1e;
}
/* pre-line, damit eine Botschaft Absätze setzen kann: Der Text geht durch
   esc() in ein einziges <p>, und ohne diese Zeile fielen zwei Absätze zu
   einer Textwand zusammen. Lehrgangsschritte enthalten keine Umbrüche und
   sehen unverändert aus. */
.sb-text { margin: 0 0 0.5rem; line-height: 1.45; white-space: pre-line; }
/* Der Handgriff, den man wirklich tun soll — abgesetzt vom Fließtext, weil
   man in der Eile nur diese eine Zeile sucht. */
.sb-hinweis {
  margin: 0 0 0.6rem;
  padding: 0.35rem 0.5rem;
  background: rgba(90, 74, 44, 0.14);
  border-left: 2px solid #8a7a55;
  font-size: 0.82rem;
  color: #4a3a1e;
}
.sb-warten {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  font-size: 0.8rem;
  font-style: italic;
  color: #6b5a3a;
}
/* Der pulsende Punkt sagt: Es liegt jetzt an dir, nicht an mir. */
.sb-punkt {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: #8a5a2b;
  animation: sb-puls 1.8s ease-in-out infinite;
}
@keyframes sb-puls {
  0%, 100% { opacity: 0.35; }
  50% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .sb-punkt { animation: none; opacity: 0.8; }
}

.sb-weiter {
  width: 100%;
  background: linear-gradient(180deg, #6d5426, #4a3819);
  border: 1px solid #8a7a55;
  color: #f7ecd6;
  font: inherit;
  padding: 0.35rem 0.7rem;
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.sb-weiter:hover { border-color: var(--brass-light); }
/* Für Schritte, die auf den Spielzustand warten: kein Knopf treibt voran,
   aber wer nicht weiterkommt (oder nicht mehr will), soll nicht feststecken. */
.sb-ueberspringen {
  display: block;
  width: 100%;
  margin-top: 0.4rem;
  background: none;
  border: 1px dashed #8a7a55;
  color: #6b5a3a;
  font: inherit;
  font-size: 0.8rem;
  padding: 0.3rem 0.6rem;
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.sb-ueberspringen:hover { border-color: var(--brass-light); color: #2c2418; }
.sb-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  margin-top: 0.5rem;
}
.sb-zurueck {
  background: none;
  border: none;
  color: #7b6a4a;
  font-size: 0.80rem;
  text-decoration: underline;
  padding: 0;
  cursor: var(--cursor-gold);
}
.sb-zurueck:hover { color: #2c2418; }
.sb-abbruch {
  display: block;
  margin: 0 0 0 auto;
  background: none;
  border: none;
  color: #7b6a4a;
  font-size: 0.80rem;
  text-decoration: underline;
  padding: 0;
  cursor: var(--cursor-gold);
}
.sb-abbruch:hover { color: #2c2418; }

@media (max-width: 780px) {
  .schreiber {
    top: auto;
    bottom: 6.5rem;
    right: 0.5rem;
    left: 0.5rem;
    width: auto;
  }
}

/* --- Werttafeln: Einfluss und Militärstärke ----------------------------------
   Beide Zahlen sind keine Waren, sondern Rechenergebnisse aus vielen Quellen.
   Die Tafeln zeigen die Rechnung — sonst bleibt die Zahl eine Behauptung. */
.res-knopf {
  font: inherit;
  font-size: 1.1rem;
  cursor: var(--cursor-gold);
}
.res-knopf:hover { border-color: var(--brass-light); }

#einflusstafel,
#militaertafel,
#bewohnertafel {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  background: rgba(8, 10, 13, 0.72);
  padding: 2rem 1rem;
}
#einflusstafel[hidden],
#militaertafel[hidden],
#bewohnertafel[hidden] { display: none; }
.wt-tafel {
  width: min(680px, 96vw);
  max-height: 88vh;
  overflow-y: auto;
  background: linear-gradient(180deg, rgba(38, 42, 48, 0.99), rgba(22, 25, 29, 0.99));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
  padding: 1.1rem 1.3rem 1.4rem;
}
.wt-kopf {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  border-bottom: 1px solid var(--iron);
  padding-bottom: 0.6rem;
  margin-bottom: 0.8rem;
}
.wt-titel { font-size: 1.4rem; color: var(--brass-light); }
.wt-wert {
  margin-left: auto;
  font-size: 1.6rem;
  font-variant-numeric: tabular-nums;
  color: var(--brass-light);
}
.wt-zu {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.4rem;
  line-height: 1;
  padding: 0 0.3rem;
  cursor: var(--cursor-gold);
}
.wt-zu:hover { color: var(--brass-light); }
.wt-text { margin: 0 0 0.9rem; line-height: 1.5; }
.wt-h {
  margin: 1rem 0 0.4rem;
  font-size: 0.95rem;
  color: var(--brass);
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
}
.wt-proTag {
  margin-left: auto;
  font-size: 0.8rem;
  font-weight: normal;
  color: var(--text-dim);
}
.wt-liste {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.wt-liste li {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.4rem 0.6rem;
  background: rgba(0, 0, 0, 0.25);
}
.wt-sache {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  min-width: 0;
  flex: 1;
}
.wt-sache small { color: var(--text-dim); font-size: 0.8rem; line-height: 1.3; }
.wt-menge,
.wt-punkte {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.wt-menge { color: var(--text-dim); min-width: 2.5rem; text-align: right; }
.wt-punkte { color: var(--moss); min-width: 3.5rem; text-align: right; }
.wt-summe {
  display: flex;
  justify-content: space-between;
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--iron);
  color: var(--brass-light);
}
.wt-fuss { margin: 0.8rem 0 0; font-size: 0.85rem; color: var(--text-dim); }
.wt-schlicht li { background: none; padding-left: 0; }
/* Zuwachs grün, Verlust rot — dieselbe Farbsprache wie die Moralposten und
   die Produktionszeile der Chronik. Muss NACH `.wt-punkte` stehen, sonst
   überschriebe dessen pauschales Grün den roten Fall. */
.wt-plus { color: var(--moss); }
.wt-minus { color: var(--fire-light); }

/* Die Rüstkammer: EINE Rüstung für die ganze Mannschaft, nicht je Mann. */
.wt-ruestkammer {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.6rem 0.7rem;
  background: rgba(109, 84, 38, 0.16);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
}
.wt-ruestkammer > div { display: flex; flex-direction: column; gap: 0.1rem; }
.wt-ruestkammer small { color: var(--text-dim); font-size: 0.82rem; }
.wt-btn {
  margin-left: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  font: inherit;
  font-size: 0.88rem;
  padding: 0.3rem 0.8rem;
  white-space: nowrap;
}
.wt-btn small { font-size: 0.78rem; opacity: 0.8; }
.wt-fertig { margin-left: auto; color: var(--text-dim); font-size: 0.85rem; }

.wt-maenner li { gap: 0.6rem; }
.wt-figur { image-rendering: pixelated; flex: none; }
.wt-ruestung {
  font-size: 0.85rem;
  color: var(--text-dim);
  white-space: nowrap;
}
.wt-ruestung.hat { color: #b9c0c8; }

@media (max-width: 780px) {
  .wt-liste li { flex-wrap: wrap; }
  .wt-btn { margin-left: 0; }
}

/* --- Handelstafel des Markts ------------------------------------------------
   Liegt über der Burg wie die Ereignistafel: Beim Handeln vergleicht man
   Preise und rechnet, dafür ist die HUD-Ecke zu eng. Die Tafel nimmt Klicks
   an, damit man nicht versehentlich daneben baut. */
#handelstafel {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  background: rgba(8, 10, 13, 0.72);
  padding: 2rem 1rem;
}
#handelstafel[hidden] { display: none; }
.ht-tafel {
  width: min(1080px, 96vw);
  max-height: 88vh;
  overflow-y: auto;
  background: linear-gradient(180deg, rgba(38, 42, 48, 0.99), rgba(22, 25, 29, 0.99));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
  padding: 1.1rem 1.3rem 1.4rem;
}
.ht-kopf {
  display: flex;
  align-items: center;
  gap: 1rem;
  border-bottom: 1px solid var(--iron);
  padding-bottom: 0.6rem;
  margin-bottom: 0.9rem;
}
.ht-titel {
  font-family: inherit;
  font-size: 1.6rem;
  color: var(--brass-light);
}
.ht-silber {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 1.1rem;
  color: var(--brass-light);
}
.ht-zu {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.4rem;
  line-height: 1;
  padding: 0 0.3rem;
  cursor: var(--cursor-gold);
}
.ht-zu:hover { color: var(--brass-light); }

.ht-ort { margin: 0 0 0.7rem; font-size: 0.92rem; }

.ht-preise {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92rem;
}
.ht-preise th {
  text-align: left;
  font-size: 0.80rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  font-weight: normal;
  padding: 0 0.5rem 0.35rem;
}
.ht-preise td {
  padding: 0.3rem 0.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  vertical-align: middle;
}
/* Das Erzeugnis des Ortes: der ganze Grund, diesen Partner zu wählen.
   KEIN display:flex auf der Zelle selbst — derselbe Grund wie bei .ht-tat:
   das nimmt die Zelle aus dem Tabellenlayout und lässt Trennlinien zwischen
   den Zeilen verspringen. vertical-align auf dem Bild reicht für dieselbe
   Optik (Symbol neben Text, mittig ausgerichtet). */
.ht-ware {
  white-space: nowrap;
}
.ht-ware img.resicon {
  vertical-align: middle;
  margin-right: 0.45rem;
}
.ht-zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.ht-verkauf { color: #a9c795; }
.ht-kauf { color: #d8a67e; }
/* DER MENGENWÄHLER — gestellt, nicht getippt.

   Hier stand ein <input type="number"> mit `max`. Das hält niemanden auf: Wer
   100 hineinschrieb, während der Karren 60 fasst, bekam eine Absage vom
   Server — und die lag hinter der Tafel, weil #toast auf z-index 10 stand und
   die Tafel auf 60. Auf dem Schirm tat der Knopf scheinbar nichts.

   KEIN display:flex auf dem <td> — das hebt die Zelle aus dem Tabellenlayout,
   und die Trennlinien der Zeile springen dann gegen die Nachbarspalten. Die
   Knöpfe stehen darum inline, die Zelle bleibt eine gewöhnliche Zelle. */
.ht-mengenwahl {
  white-space: nowrap;
  text-align: right;
}
.ht-mengenwahl button {
  width: 1.4rem;
  padding: 0.1rem 0;
  background: var(--stone-900);
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--brass-light);
  font: inherit;
  font-size: 0.9rem;
  line-height: 1.2;
  cursor: var(--cursor-gold);
}
.ht-mengenwahl button:hover:not(:disabled) { border-color: var(--brass); }
.ht-mengenwahl button:disabled { opacity: 0.35; cursor: default; }
.ht-mengenzahl {
  display: inline-block;
  min-width: 2.4rem;
  color: var(--brass-light);
  font-variant-numeric: tabular-nums;
  text-align: center;
}
/* Hier stand einmal eine rote Zahl, sobald die Ladung den Lagerbestand
   uebertraf. Das war zweimal falsch: Beim EINFUEHREN ist "mehr als im Lager"
   gerade der Sinn der Sache — Werkzeug zu bestellen sah damit aus wie ein
   Fehler. Und selbst beim Verkaufen ist eine eingefaerbte Zahl eine Warnung
   ohne Worte. Seit dem 22.08.2026 sagt es stattdessen der Meldungskasten, in
   klarem Satz und in Rot: "So viel liegt nicht im Lager." Der ist seit
   demselben Tag ueber den Tafeln sichtbar (#toast, z-index) — vorher lag er
   dahinter, und DAS war der eigentliche Grund, warum es hier je eine Farbe
   brauchte. */
/* KEIN display:flex hier — das war der Grund für die verspringenden
   Trennlinien: `display:flex` auf einem <td> hebt es aus dem Tabellenlayout,
   die Zeile richtet sich dann nicht mehr an den Nachbarzellen aus. text-align
   plus Abstand zwischen den Knöpfen erreicht dieselbe rechtsbündige Reihe,
   ohne die Zelle aus der Tabelle zu nehmen. */
.ht-tat {
  text-align: right;
  white-space: nowrap;
}
.ht-tat button + button {
  margin-left: 0.3rem;
}
.ht-tat button {
  font-size: 0.78rem;
  padding: 0.2rem 0.6rem;
}
.ht-fuss { font-size: 0.8rem; margin: 0.7rem 0 0; }

/* Ein GEWAEHLTER Warenknopf. Die Knoepfe schicken seit 21.08.2026 nicht mehr
   sofort los, sondern legen den Auftrag auf den Zettel darunter — man muss
   also sehen koennen, was schon draufliegt. */
.ht-tat button.gewaehlt {
  border-color: var(--brass-light);
  background: rgba(168, 129, 61, 0.25);
  color: var(--brass-light);
}

/* DER AUFTRAGSZETTEL — was der Haendler mitnimmt, was er holt, und der eine
   Knopf, der ihn losschickt. Abgesetzt vom Tabellenfuss, weil er kein
   Erklaertext ist, sondern das Bedienelement: Hier endet die Ueberlegung und
   beginnt die Reise. */
.ht-auftrag {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-top: 0.8rem;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(109, 84, 38, 0.16);
}
/* Noch nichts gewaehlt: zurueckhaltend, damit der Zettel nicht auffordert,
   bevor es etwas zu schicken gibt. */
.ht-auftrag.leer {
  border-color: var(--iron);
  background: rgba(0, 0, 0, 0.2);
}
.ht-auftrag-text { font-size: 0.85rem; color: var(--text-dim); }
.ht-auftrag.leer .ht-auftrag-text { font-style: italic; }
.ht-auftrag-teil { color: var(--text); }
.ht-auftrag-teil + .ht-auftrag-teil { margin-left: 1rem; }
.ht-auftrag-teil b { color: var(--brass-light); font-weight: 400; }
.ht-auftrag button { flex: none; }


@media (max-width: 780px) {
  .ht-preise { font-size: 0.82rem; }
  .ht-preise th:nth-child(2), .ht-preise td:nth-child(2) { display: none; }
  .ht-tat { flex-direction: column; }
}

/* --- Icon-Werkstatt ---------------------------------------------------------
   Wie die Klangwerkstatt eine Liste, keine Galerie: Jede Zeile ist EIN Zeichen
   mit seinem Stand im Spiel, dem letzten Wurf daneben und den Knöpfen rechts.
   Die Bilder stehen in ECHTER Größe — ein Icon lässt sich nur beurteilen, wenn
   es so groß ist wie später in der Leiste. */
.iw-anleitung {
  margin-bottom: 1.2rem;
  font-size: 0.9rem;
}
.iw-anleitung summary {
  cursor: var(--cursor-gold);
  color: var(--brass-light);
}
.iw-anleitung summary strong { color: inherit; }
.iw-anleitung ol,
.iw-anleitung p {
  margin: 0.7rem 0 0;
  line-height: 1.5;
}
.iw-anleitung ol { padding-left: 1.3rem; }
.iw-anleitung li + li { margin-top: 0.35rem; }
.iw-anleitung code {
  font-family: ui-monospace, monospace;
  font-size: 0.88em;
  color: var(--parchment, #d7c7a3);
}

.iw-kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.iw-kopfknoepfe {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}
.iw-meldung {
  font-size: 0.85rem;
  color: var(--muted);
}
.iw-meldung.ok { color: #a9c795; }
.iw-meldung.fehler { color: #d08a7a; }
.iw-zaehler {
  font-size: 0.78rem;
  font-weight: normal;
  margin-left: 0.6rem;
}

.iw-liste {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--iron);
  border: 1px solid var(--iron);
}
.iw-zeile {
  display: grid;
  /* Name/Knöpfe oben, das (jetzt breitere) Bilderfeld darunter über die
     ganze Zeile — bei einer 6- bis 10-fachen Vergrößerung passt es nicht
     mehr in eine schmale feste Spalte wie früher. */
  grid-template-columns: minmax(11rem, 1fr) auto;
  align-items: center;
  gap: 0.5rem 0.9rem;
  padding: 0.5rem 0.7rem;
  background: rgba(0, 0, 0, 0.25);
}
.iw-zeile.eigen { background: rgba(138, 122, 85, 0.1); }
.iw-name {
  display: flex;
  flex-direction: column;
  gap: 0.12rem;
  min-width: 0;
}
.iw-name strong { color: var(--brass-light); }
.iw-ziel {
  font-size: 0.80rem;
  color: var(--muted);
  font-family: ui-monospace, monospace;
}
.iw-marke {
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brass);
}

.iw-bilder {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.9rem;
}
.iw-bilder figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.2rem;
}
/* Die vergrößerte Fassung sticht optisch hervor — sie ist der Grund, warum
   dieses Feld überhaupt eine eigene Zeile bekommen hat (siehe .iw-zeile):
   ein 32-Pixel-Zeiger 6-fach vergrößert ist knapp 200px breit. */
.iw-gross { order: 1; }
.iw-wurf { order: 2; }
/* Karo-Grund: Bei freigestellten Zeichen ist sonst nicht zu sehen, wo das Bild
   aufhört und wo ein dunkler Fleck im Motiv sitzt. */
.iw-bild,
.iw-leer {
  display: block;
  min-width: 18px;
  min-height: 18px;
  image-rendering: pixelated;
  background-color: #23272c;
  background-image: linear-gradient(45deg, #2c3138 25%, transparent 25%, transparent 75%, #2c3138 75%),
    linear-gradient(45deg, #2c3138 25%, transparent 25%, transparent 75%, #2c3138 75%);
  background-size: 8px 8px;
  background-position: 0 0, 4px 4px;
  border: 1px solid var(--iron);
}
.iw-bild.fehlt { visibility: hidden; }
.iw-bilder figcaption {
  font-size: 0.78rem;
  color: var(--muted);
}
.iw-leer {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  color: var(--muted);
}

.iw-knoepfe {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  justify-content: flex-end;
}
.iw-knoepfe button {
  font-size: 0.78rem;
  padding: 0.25rem 0.7rem;
}
.iw-promptfeld {
  grid-column: 1 / -1;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
.iw-promptfeld textarea {
  width: 100%;
  font-size: 0.8rem;
}
.iw-promptknoepfe {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-size: 0.78rem;
}

/* --- Der Pixel-Editor -------------------------------------------------------
   Liegt über der ganzen Werkstatt (fixed), damit die Zeile darunter beim
   Bearbeiten nicht wegspringt. Kein natives <dialog> — die Werkstatt kennt
   dieses Muster schon vom Dilemma und vom Sprite-Editor, ein weiteres wäre
   nur Inkonsistenz. */
.iw-editor {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: grid;
  place-items: center;
  background: rgba(10, 11, 13, 0.82);
  padding: 1rem;
}
.iw-editor-tafel {
  background: var(--stone-700, #1c1f24);
  border: 1px solid var(--iron);
  border-radius: 3px;
  padding: 1rem 1.2rem 1.2rem;
  max-width: min(92vw, 44rem);
  max-height: 92vh;
  overflow: auto;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
}
.iw-editor-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.7rem;
}
.iw-editor-kopf strong { color: var(--brass-light); }
.iw-editor-schliessen {
  background: none;
  border: none;
  color: var(--muted);
  font-size: 1.3rem;
  line-height: 1;
  cursor: var(--cursor-gold);
  padding: 0.1rem 0.4rem;
}
.iw-editor-schliessen:hover { color: var(--parchment, #d7c7a3); }
.iw-editor-werkzeuge {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.8rem;
}
.iw-editor-farbe {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
}
.iw-editor-farbe input[type="color"] {
  width: 2rem;
  height: 1.6rem;
  padding: 0;
  border: 1px solid var(--iron);
  background: none;
  cursor: var(--cursor-gold);
}
.iw-editor-werkzeuge button[aria-pressed="true"] {
  background: var(--brass, #a8813d);
  color: #1a1a1a;
}
.iw-editor-leinwand-rahmen {
  display: flex;
  justify-content: center;
  padding: 0.6rem;
  background-color: #23272c;
  background-image: linear-gradient(45deg, #2c3138 25%, transparent 25%, transparent 75%, #2c3138 75%),
    linear-gradient(45deg, #2c3138 25%, transparent 25%, transparent 75%, #2c3138 75%);
  background-size: 8px 8px;
  background-position: 0 0, 4px 4px;
  border: 1px solid var(--iron);
}
#iw-editor-leinwand {
  image-rendering: pixelated;
  cursor: crosshair;
  touch-action: none;
}
.iw-editor-hinweis {
  font-size: 0.8rem;
  margin: 0.6rem 0 0;
}
.iw-editor-knoepfe {
  display: flex;
  justify-content: flex-end;
  gap: 0.6rem;
  margin-top: 0.8rem;
}

@media (max-width: 780px) {
  .iw-zeile {
    grid-template-columns: 1fr auto;
    row-gap: 0.5rem;
  }
  .iw-name { grid-column: 1 / -1; }
  .iw-knoepfe { justify-content: flex-start; }
}

/* --- Das offene Dilemma -----------------------------------------------------
   Liegt über der ganzen Burg und nimmt Klicks an. Kein Schließknopf: Ein
   Dilemma, das man wegklicken kann, ist keins — man würde es wegklicken und
   nie wieder ansehen. Wer nicht entscheiden will, lässt die Frist verstreichen. */
#ereignis {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 11, 13, 0.72);
}
#ereignis[hidden] { display: none; }

.ereignis-tafel {
  width: min(30rem, 100%);
  max-height: 90vh;
  overflow-y: auto;
  padding: 1.4rem 1.5rem 1.2rem;
  background: var(--stone-800);
  border: 1px solid var(--brass-dark);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
}
.ereignis-tafel h2 {
  margin: 0 0 0.7rem;
  font-family: inherit;
  font-size: 1.5rem;
  font-weight: normal;
  color: var(--brass-light);
  line-height: 1.15;
}

/* Der Satz aus der Welt heraus — auf Pergament, damit er sich vom Apparat
   drumherum absetzt. Er ist das, was der Spieler wirklich liest. */
.ereignis-szene {
  margin: 0 0 1.1rem;
  padding: 0.7rem 0.85rem;
  background: rgba(215, 199, 163, 0.08);
  border-left: 2px solid var(--brass-dark);
  font-family: var(--font-body);
  font-size: 1.02rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--parchment);
}

.ereignis-wahlen {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.ereignis-wahl {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.6rem 0.75rem;
  font: inherit;
  color: var(--text);
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.ereignis-wahl:hover:not(:disabled) {
  background: rgba(109, 84, 38, 0.22);
  border-color: var(--brass);
}
.ereignis-wahl b {
  display: block;
  color: var(--kopf, #e8e4d6);
  font-weight: 600;
  margin-bottom: 0.15rem;
}
.ereignis-wahl span {
  display: block;
  font-size: 0.88rem;
  color: var(--text-dim);
  line-height: 1.4;
}
.ereignis-wahl:disabled {
  opacity: 0.45;
  cursor: var(--cursor-kupfer);
}
.ereignis-wahl .unmoeglich {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.8rem;
  font-style: normal;
  color: var(--blood);
}

/* Die Auflösung einer getroffenen Wahl: was WIRKLICH geschah, nicht der
   Vorschautext von vorher. Ersetzt kurz die Fragestellung, bis "Weiter"
   geklickt wird (ui.ts, zeichneAusgang). */
/* ===========================================================================
   DIE AUSGANGSBILANZ — was eine Entscheidung wirklich gekostet hat.

   Vorher stand unter der Wahl nur ihr Erzaehltext, und den hatte man vor dem
   Klick schon gelesen. Was gebucht wurde, musste man sich aus dem Kopfband
   zusammensuchen. Jetzt steht es als Liste da, in Zahlen.

   ZWEI SPALTEN, rechtsbuendige Zahl: Man liest solche Listen an der Zahl
   entlang, nicht am Namen. Tabellenziffern, damit die Stellen untereinander
   stehen — sonst tanzt die Spalte.
   =========================================================================== */
.ereignis-bilanz {
  margin: 0 0 1.1rem;
  padding: 0.55rem 0.85rem;
  list-style: none;
  background: rgba(0, 0, 0, 0.22);
  border-left: 2px solid var(--brass-dark);
  border-radius: 0 2px 2px 0;
}
.ereignis-bilanz-zeile {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.12rem 0;
  font-size: 0.95rem;
}
.eb-was { color: var(--text-dim); }
.eb-wert {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}
/* Dieselbe Sprache wie die Meldungen oben rechts: Gewinn gruen, Verlust rot.
   Wer beides gelernt hat, muss es nicht zweimal lernen. */
.ereignis-bilanz-zeile.gut .eb-wert { color: #a9c795; }
.ereignis-bilanz-zeile.schlecht .eb-wert { color: #d98b7f; }

.ereignis-ausgang-text {
  margin: 0 0 1.1rem;
  padding: 0.7rem 0.85rem;
  background: rgba(215, 199, 163, 0.08);
  border-left: 2px solid var(--brass-dark);
  font-family: var(--font-body);
  font-size: 1.02rem;
  font-style: italic;
  line-height: 1.5;
  color: var(--parchment);
}
.ereignis-ausgang-weiter {
  text-align: center;
  font-weight: 600;
  color: var(--kopf, #e8e4d6);
}
/* Deutlich als Rückmeldung statt als Frage erkennbar. */
.ereignis-ausgang-tafel {
  border-color: var(--brass);
}

/* Die Frist. Zurückhaltend gesetzt — sie soll drohen, nicht schreien. */
.ereignis-frist {
  margin: 0.9rem 0 0;
  font-size: 0.82rem;
  color: var(--text-dim);
  font-style: italic;
}

/* ===========================================================================
   Das Buch der Burg (/wiki) — Tutorial und Nachschlagewerk.
   Aufgebaut aus denselben Tafeln wie die übrigen Server-Seiten; eigen ist nur
   der Bildkopf und die Gebäudegalerie.
   =========================================================================== */

/* Bildkopf: das Startbild als Bühne, der Titel darauf. Die Verläufe holen
   den Text aus dem Bild heraus, ohne es zuzukleistern. */
.wiki-kopf {
  position: relative;
  margin-bottom: 1.6rem;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  overflow: hidden;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.55);
}
.wiki-kopf__bild {
  display: block;
  width: 100%;
  height: 230px;
  object-fit: cover;
  object-position: center 62%;
  filter: saturate(0.85) brightness(0.72);
}
.wiki-kopf__text {
  position: absolute;
  inset: auto 0 0 0;
  padding: 1.4rem 1.6rem 1.2rem;
  background: linear-gradient(180deg, transparent, rgba(10, 12, 15, 0.82) 55%);
}
.wiki-kopf__text h1 {
  margin: 0.1rem 0 0.3rem;
  font-family: var(--font-display);
  font-size: 2.3rem;
  line-height: 1;
  color: var(--brass-light);
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.8);
}
.wiki-kopf__text .wiki-lead {
  margin: 0;
  max-width: 46rem;
}

.wiki-lead {
  color: var(--text-dim);
  font-style: italic;
  line-height: 1.5;
}

/* Inhaltsverzeichnis: zweispaltig, kompakt — es soll überflogen werden. */
.wiki-inhalt {
  padding: 1.1rem 1.4rem;
  margin-bottom: 1.6rem;
}
.wiki-inhalt ol {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: kapitel;
  columns: 2;
  column-gap: 2rem;
}
.wiki-inhalt li {
  counter-increment: kapitel;
  break-inside: avoid;
  padding: 0.16rem 0;
}
.wiki-inhalt li::before {
  content: counter(kapitel) ".";
  color: var(--brass);
  margin-right: 0.45rem;
  font-variant-numeric: tabular-nums;
}

.container.wide > section.panel {
  margin-bottom: 1.4rem;
}
.container.wide > section.panel h2 {
  margin-top: 0;
  font-family: inherit;
  font-size: 1.65rem;
  color: var(--brass-light);
}
.container.wide > section.panel h3 {
  margin: 1.6rem 0 0.3rem;
  font-size: 1.05rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brass);
}

/* Erste Schritte: nummerierte Marschtafel */
.wiki-schritte {
  counter-reset: schritt;
  list-style: none;
  padding: 0;
  margin: 0.6rem 0 0;
}
.wiki-schritte li {
  counter-increment: schritt;
  position: relative;
  padding: 0.4rem 0 0.4rem 2.6rem;
  border-top: 1px solid rgba(109, 84, 38, 0.25);
  line-height: 1.5;
}
.wiki-schritte li:first-child { border-top: none; }
.wiki-schritte li::before {
  content: counter(schritt);
  position: absolute;
  left: 0;
  top: 0.42rem;
  width: 1.7rem;
  height: 1.7rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--brass-dark);
  border-radius: 50%;
  color: var(--brass-light);
  font-size: 0.85rem;
  background: rgba(0, 0, 0, 0.3);
}

/* Gebäudegalerie: Bild links, Daten rechts. */
.wiki-galerie {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 0.8rem;
  margin-top: 0.7rem;
}
.wiki-bau {
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  padding: 0.8rem 0.9rem;
  background: rgba(0, 0, 0, 0.24);
  border: 1px solid var(--iron);
  border-left: 3px solid var(--brass-dark);
  border-radius: 2px;
}
.wiki-bau__bild {
  flex: none;
  width: 76px;
  min-height: 68px;
  display: grid;
  place-items: end center;
}
/* Die Sprites sind Pixelbilder — nur so bleiben sie beim Skalieren scharf. */
.wiki-sprite {
  image-rendering: pixelated;
  max-width: 76px;
  max-height: 84px;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.6));
}
.wiki-sprite--icon {
  max-width: 46px;
  max-height: 46px;
}
.wiki-sprite--fehlt {
  display: block;
  width: 46px;
  height: 46px;
  border: 1px dashed var(--iron-light);
  border-radius: 2px;
}
.wiki-bau__text { min-width: 0; }
.wiki-bau h4 {
  margin: 0;
  font-size: 1rem;
  color: var(--brass-light);
}
.wiki-flavor {
  margin: 0.15rem 0 0.4rem;
  font-size: 0.82rem;
  font-style: italic;
  color: var(--text-dim);
  line-height: 1.35;
}
.wiki-bau dl {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.1rem 0.6rem;
  margin: 0;
  font-size: 0.83rem;
}
.wiki-bau dt {
  color: var(--text-dim);
  white-space: nowrap;
}
.wiki-bau dd { margin: 0; }

.wiki-plus { color: #a8c79a; }
.wiki-minus { color: #d8ab7c; }

.wiki-tabelle {
  width: 100%;
  border-collapse: collapse;
  margin: 0.7rem 0;
  font-size: 0.88rem;
}
.wiki-tabelle th {
  text-align: left;
  font-size: 0.80rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brass);
  border-bottom: 1px solid var(--brass-dark);
  padding: 0.3rem 0.6rem 0.3rem 0;
}
.wiki-tabelle td {
  padding: 0.28rem 0.6rem 0.28rem 0;
  border-bottom: 1px solid rgba(109, 84, 38, 0.18);
  vertical-align: top;
}

kbd {
  display: inline-block;
  padding: 0.05rem 0.35rem;
  border: 1px solid var(--iron-light);
  border-bottom-width: 2px;
  border-radius: 3px;
  background: var(--stone-800);
  font-family: var(--font-body);
  font-size: 0.82rem;
  color: var(--brass-light);
}

.wiki-zurueck {
  text-align: center;
  margin-top: 2rem;
}

@media (max-width: 640px) {
  .wiki-inhalt ol { columns: 1; }
  .wiki-kopf__bild { height: 160px; }
  .wiki-kopf__text h1 { font-size: 1.7rem; }
}

/* Bildvignette über der Ereignistafel. Breitformat, harte Pixelkanten —
   sie ist im selben Stil gemalt wie das Spiel darunter. */
.ereignis-bild {
  display: block;
  width: 100%;
  height: 150px;
  object-fit: cover;
  image-rendering: pixelated;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  margin-bottom: 0.9rem;
  filter: saturate(0.92);
}
.ereignis-bild[hidden] { display: none; }

/* Auswahlfeld der Werkstatt (Ereignisliste) */
#devpanel .dev-auswahl {
  width: 100%;
  background: var(--stone-700);
  border: 1px solid var(--iron);
  color: var(--text);
  border-radius: 2px;
  padding: 0.24rem 0.3rem;
  font-family: var(--font-body);
  font-size: 0.8rem;
}

/* ===========================================================================
   Bauleiste (Baumodus) — Neufassung: Gebäudebilder unten, Reiter darüber,
   Infokarte nur fürs gewählte Werkzeug. Überschreibt die alte Seitenspalte.
   =========================================================================== */
#baumenu {
  top: auto;
  bottom: 0.75rem;
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  width: auto;
  /* 66rem war auf die alten, schmalen Hochkant-Kacheln gemünzt. Seit Bild und
     Text nebeneinander stehen, sind die Kacheln rund doppelt so breit; bei
     66rem hätte schon der Reiter "Rohstoffe" seitwärts gescrollt. 96vw deckelt
     das auf kleinen Fenstern ohnehin — die Zahl wirkt nur auf großen. */
  max-width: min(96vw, 88rem);
  overflow: visible;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
}
/* Im Baumodus weicht die ganze Fußleiste der Bauleiste — sie kostet auf
   einem Notebook zu viel Höhe. Statt der vollen Vorratsleiste zeigt
   #baumaterial oben zentral nur die drei Baustoffe (Holz, Stein, Werkzeug). */
body.baumodus #buildbar { display: none; }

/* Baumaterial: Ersatz für die ausgeblendete Vorratsleiste, nur die drei
   Baustoffe (ui.ts renderBaumaterial).

   Der Platz hat gewandert: erst rechts unten neben der Bauleiste, dann
   mittig ÜBER dem Baumenü — und jetzt mittig UNTER DER KOPFZEILE, auf
   ausdrücklichen Wunsch.

   Der Anker ist `--kopfband-hoehe`, und die wird GEMESSEN, nicht geraten
   (ui.ts, meldeKopfbandHoehe; kopfleiste.js tut dasselbe auf den Server-
   Seiten). Das ist hier nicht Feinschliff: Das Kopfband bricht auf schmalen
   Fenstern um und wird dann zweizeilig — mit einer fest notierten Höhe
   schöbe sich das Feld genau dort unter das Band, wo es am wenigsten Platz
   gibt.

   Kleiner gehalten als die Vorratsleiste der Burgansicht: Drei Zahlen im
   Augenwinkel brauchen keine 32-px-Embleme. */
#baumaterial {
  display: none;
  top: calc(var(--kopfband-hoehe, 42px) + 0.5rem);
  bottom: auto;
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  gap: 0.35rem;
  padding: 0.25rem 0.5rem;
  background: rgba(18, 20, 23, 0.88);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.5);
}
#baumaterial .res {
  padding: 0.1rem 0.35rem;
  gap: 0.25rem;
  font-size: 0.95rem;
}
#baumaterial .resicon {
  width: 20px;
  height: 20px;
}
body.baumodus #baumaterial { display: flex; align-items: center; }

#baumenu .bau-kopf {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.3rem 0.6rem;
  background: linear-gradient(180deg, rgba(28, 31, 36, 0.97), rgba(18, 20, 23, 0.97));
  border: 1px solid var(--brass-dark);
  border-bottom: none;
  border-radius: 3px 3px 0 0;
}
#baumenu .bau-titel {
  font-family: inherit;
  font-size: 1.15rem;
  color: var(--brass-light);
  padding: 0 0.2rem;
}
#baumenu .bau-tabs { display: flex; gap: 0.25rem; flex: 1 1 auto; }
#baumenu .bau-tab {
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--iron);
  border-bottom-width: 3px;
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.22rem 0.6rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
  cursor: var(--cursor-gold);
}
#baumenu .bau-tab.kat-rohstoffe { border-bottom-color: #5d8a4f; }
#baumenu .bau-tab.kat-verarbeitung { border-bottom-color: #b0793e; }
#baumenu .bau-tab.kat-sozial { border-bottom-color: #4f7a9e; }
#baumenu .bau-tab.kat-verteidigung { border-bottom-color: #8a8f96; }
#baumenu .bau-tab.aktiv {
  background: linear-gradient(180deg, #3a3f47, #2c3138);
  color: var(--brass-light);
  border-color: var(--brass-dark);
}
#baumenu .planhinweis-kurz {
  font-size: 0.80rem;
  color: var(--text-dim);
  font-style: italic;
  white-space: nowrap;
  cursor: var(--cursor-gold);
}
#baumenu .planhinweis-kurz.wartend { color: #d8ab7c; font-style: normal; }

/* DER MAUERPLAN — der gezeichnete Ring, der noch nicht steht.
   Eigene Gruppe im Kopf der Bauleiste, weil er anders funktioniert als alles
   daneben: nicht Stück für Stück gebaut, sondern in einem Zug, und nur wenn
   der Ring geschlossen ist. Solange er das nicht ist, trägt der Knopf den
   Grund als Beschriftung statt eines Namens — ein gesperrter Knopf ohne
   Begründung ist die ärgerlichste Art, jemandem etwas zu verweigern. */
#baumenu .mauerplan {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: auto;
  padding: 0.15rem 0.35rem;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  background: rgba(40, 31, 16, 0.55);
  white-space: nowrap;
}
#baumenu .mauerplan.bereit {
  border-color: var(--brass);
  background: rgba(70, 54, 24, 0.7);
}
#baumenu .mauerplan__zahl {
  font-size: 0.78rem;
  color: #d8ab7c;
  white-space: nowrap;
}
#baumenu .mauerplan__bauen,
#baumenu .mauerplan__weg {
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  padding: 0.18rem 0.55rem;
  font-family: var(--font-body);
  font-size: 0.78rem;
  color: #f7ecd6;
  background: linear-gradient(180deg, #4a3a1c, #2e2412);
  cursor: var(--cursor-gold);
}
#baumenu .mauerplan.bereit .mauerplan__bauen {
  border-color: var(--brass);
  background: linear-gradient(180deg, #6d5426, #43341a);
}
/* Gesperrt: derselbe Knopf, aber sichtbar zu. Der GRUND steht nicht mehr
   darauf — er würde die Kopfzeile sprengen — sondern ploppt als rote Meldung
   auf und hängt als Kurzinfo am Knopf. Der rote Saum sagt hier nur "geht
   nicht"; das Warum sagt die Meldung. */
#baumenu .mauerplan__bauen:disabled {
  cursor: default;
  color: #b08b7a;
  border-color: #7a3b2c;
  background: rgba(28, 18, 15, 0.9);
}
#baumenu .fertig {
  background: linear-gradient(180deg, #6d5426, #43341a);
  border: 1px solid var(--brass);
  color: #f7ecd6;
  border-radius: 2px;
  padding: 0.22rem 0.7rem;
  font-family: var(--font-body);
  font-size: 0.82rem;
  cursor: var(--cursor-gold);
}

/* Die Leiste selbst: Bild oben, Name darunter — man erkennt das Haus. */
#baumenu .bau-leiste {
  display: flex;
  gap: 0.3rem;
  padding: 0.5rem 0.6rem 0.45rem;
  background: linear-gradient(180deg, rgba(18, 20, 23, 0.97), rgba(12, 14, 17, 0.97));
  border: 1px solid var(--brass-dark);
  border-radius: 0 0 3px 3px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.6);
  overflow-x: auto;
  /* Firefox: dünn statt Systembreite, in Messingtönen — kein eigener
     Rahmen/Verlauf möglich, das kann nur der WebKit-Zweig unten. */
  scrollbar-width: thin;
  scrollbar-color: var(--brass-dark) rgba(0, 0, 0, 0.35);
}
/* Sichtbarer Messing-Scrollbalken statt der unauffälligen Systemleiste — ohne
   das sah man im Reiter "Verteidigung" (zwölf Einträge) nicht auf den ersten
   Blick, dass da noch mehr steht, man musste es per Zufall entdecken. */
#baumenu .bau-leiste::-webkit-scrollbar {
  height: 10px;
}
#baumenu .bau-leiste::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.35);
  border-radius: 2px;
}
#baumenu .bau-leiste::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, var(--brass-light), var(--brass-dark));
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
}
#baumenu .bau-leiste::-webkit-scrollbar-thumb:hover {
  background: var(--brass);
}
/* FLACH statt hoch. Bild links, Name und Kosten rechts daneben — vorher stand
   alles übereinander (Bild, Name, Kostenzeile), und bei drei Rohstoffen brach
   die Kostenzeile zusätzlich um. Die Kachel wurde damit rund 90 px hoch; auf
   einem 13-Zoll-Notebook verdeckte die Leiste mitsamt Kopfzeile das halbe
   Spielfeld. Nebeneinander sind es noch rund 56 px.

   Bezahlt wird das mit BREITE: Die Kacheln sind gut anderthalbmal so breit,
   und im Reiter "Verteidigung" (zwölf Einträge) scrollt die Leiste seitwärts.
   Das ist der bewusste Tausch — Höhe verdeckt das Bild, Breite nicht. */
#baumenu .bau-ikone {
  position: relative;
  flex: none;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.35rem;
  padding: 0.3rem 0.45rem 0.3rem 0.3rem;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  transition: transform 0.08s ease-out, border-color 0.08s;
}
/* Die rechte Spalte: Name oben, Kosten darunter. Feste Breite, damit die
   Kacheln einer Reihe gleich breit bleiben — sonst tanzten sie mit der Länge
   des Namens, und die Leiste läse sich als Flickenteppich. */
#baumenu .bau-ikone__text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  width: 4.5rem;
}
#baumenu .bau-ikone:hover:not(.locked) {
  transform: translateY(-3px);
  border-color: var(--brass);
}
#baumenu .bau-ikone.aktiv {
  border-color: var(--brass-light);
  background: linear-gradient(180deg, rgba(168, 129, 61, 0.22), rgba(168, 129, 61, 0.08));
  box-shadow: 0 0 12px rgba(168, 129, 61, 0.35);
}
/* Cunrats Fingerzeig: der Knopf, den der aktuelle Lehrgangsschritt meint
   (schreiber.ts → ui.ts setzeBauziel). Pulsiert, statt nur stillzustehen —
   ein feststehender Rahmen geht in einer Leiste mit zwanzig Knöpfen unter. */
#baumenu .bau-ikone.sb-ziel {
  border-color: var(--brass-light);
  animation: sb-ziel-puls 1.6s ease-in-out infinite;
}
@keyframes sb-ziel-puls {
  0%, 100% { box-shadow: 0 0 6px 1px rgba(204, 167, 94, 0.45); }
  50% { box-shadow: 0 0 16px 4px rgba(204, 167, 94, 0.9); }
}
@media (prefers-reduced-motion: reduce) {
  #baumenu .bau-ikone.sb-ziel { animation: none; box-shadow: 0 0 12px 3px rgba(204, 167, 94, 0.7); }
}
#baumenu .bau-ikone__bild {
  flex: none;
  width: 44px;
  height: 42px;
  display: grid;
  place-items: center;
}
#baumenu .bau-ikone__bild img {
  max-width: 44px;
  max-height: 42px;
  image-rendering: pixelated;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.6));
}
#baumenu .bau-ikone__name {
  font-size: 0.76rem;
  line-height: 1.1;
  color: var(--text-dim);
  text-align: left;
  max-width: 100%;
  /* Zwei Zeilen statt einer mit "…" am Ende — seit Palisaden-Torhaus (17
     Zeichen) und Steinmauer-Torhaus (18) gibt es die beiden längsten Namen
     im Spiel, und "Palisaden-…" sagt nicht mehr, was da eigentlich steht.
     -webkit-line-clamp ist trotz des Präfixes Standard in allen Engines, die
     dieses Projekt bedient (Chromium, Firefox, Safari). */
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
}
#baumenu .bau-ikone.aktiv .bau-ikone__name { color: var(--brass-light); }
/* Die Kostenzeile: stand früher nur in der Infokarte hinter dem "?", jetzt
   direkt am Knopf — wer die Leiste überfliegt, sieht sofort, was er braucht,
   ohne jede Kachel einzeln anzuklicken. Sie sitzt RECHTS vom Gebäudebild,
   unter dem Namen, statt wie früher unter beidem: Das war die Zeile, die die
   Kachel hoch machte, weil sie bei drei Rohstoffen umbrach. */
#baumenu .bau-ikone__kosten {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 0.1rem 0.28rem;
}
#baumenu .bau-ikone__kosten .res {
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  font-size: 0.62rem;
  line-height: 1;
  color: var(--text-dim);
  white-space: nowrap;
}
#baumenu .bau-ikone__kosten .res.fehlt { color: #d4695a; }
#baumenu .bau-ikone__kosten .resicon {
  width: 12px;
  height: 12px;
  image-rendering: pixelated;
}
#baumenu .bau-ikone.locked {
  opacity: 0.45;
  filter: grayscale(0.7);
  cursor: var(--cursor-kupfer);
}
/* DIE BEIDEN BAUTAFELN — Vorratstafel links, Bauinfotafel rechts.
   Sie sind ein PAAR und tragen darum EINE gemeinsame Stellschraube: Was der
   Ort hergibt und was das Werkzeug kann, gehört in gleicher Größe an die
   beiden Ränder. Wer nur eine von beiden vergrößerte, machte aus dem Paar
   zwei Zufälle.

   `--tafel-skala` streckt beide zugleich — Breite, Ränder, Schriftgrade und
   Zeichen gehen alle durch dasselbe calc(). 1 ist der Ursprungszustand
   (232 px breit), 1.5 wären anderthalbfache Tafeln. Eine Zahl ändern genügt;
   einzelne Werte von Hand nachzuziehen liefe unweigerlich auseinander.

   STEHT BEWUSST AUF 1. Anderthalbfach war einmal eingestellt und wieder
   verworfen: Die Tafeln selbst waren in ihrer ursprünglichen Größe richtig,
   nur das Bild darin war zu klein. Das Bild ist deshalb einzeln gewachsen
   (.bi-bild weiter unten), nicht die Tafel — die Schraube bleibt hier
   stehen, damit man sie nicht ein zweites Mal erfinden muss. */
:root {
  --tafel-skala: 1;
  --tafel-breite: calc(232px * var(--tafel-skala));
}
/* Vorratstafel des Bauplans, oben links. Zeigt, wovon diese Burgstätte lebt:
   Wald und Fisch wachsen nach, Fels und Erz nicht. Der Unterschied ist die
   wichtigste Information darauf — deshalb das Nachwuchszeichen. */
#kartenvorrat {
  top: 3.6rem;
  left: 0.7rem;
  width: var(--tafel-breite);
  padding: calc(0.55rem * var(--tafel-skala)) calc(0.7rem * var(--tafel-skala)) calc(0.5rem * var(--tafel-skala));
  background: rgba(18, 20, 23, 0.94);
  border: 1px solid var(--iron);
  border-left: 2px solid var(--brass-dark);
  border-radius: 2px;
}
.kv-kopf { display: flex; flex-direction: column; gap: 0.1rem; margin-bottom: calc(0.45rem * var(--tafel-skala)); }
.kv-titel { font-size: calc(0.8rem * var(--tafel-skala)); color: var(--brass-light); letter-spacing: 0.02em; }
.kv-merkmale { font-size: calc(0.80rem * var(--tafel-skala)); color: var(--text-dim); font-style: italic; }
.kv-liste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: calc(0.28rem * var(--tafel-skala)); }
.kv-zeile {
  display: grid;
  /* Erste und dritte Spalte tragen feste Pixelmaße (Zeichen und Balken) und
     müssen deshalb mitwachsen — sonst säße ein 16-px-Zeichen neben 1,1-rem-Text. */
  grid-template-columns: calc(16px * var(--tafel-skala)) 1fr calc(46px * var(--tafel-skala)) auto;
  align-items: center;
  gap: calc(0.35rem * var(--tafel-skala));
  font-size: calc(0.75rem * var(--tafel-skala));
  color: var(--text);
}
.kv-icon {
  width: calc(16px * var(--tafel-skala));
  height: calc(16px * var(--tafel-skala));
  image-rendering: pixelated;
}
.kv-name { white-space: nowrap; }
.kv-nachwuchs { font-style: normal; color: #6ac46a; margin-left: 0.15rem; font-size: 0.8em; }
/* Wie viel EINE Kachel dieser Art trägt (kartenvorraete.ts, ERTRAG_JE_*) —
   eigene Zeile unter dem Namen, damit .kv-name trotzdem nowrap bleiben darf. */
.kv-je-kachel { display: block; font-size: calc(0.66rem * var(--tafel-skala)); color: var(--text-dim); font-weight: normal; }
.kv-balken {
  height: calc(5px * var(--tafel-skala));
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--iron);
  border-radius: 1px;
  overflow: hidden;
}
.kv-balken i { display: block; height: 100%; background: var(--brass); }
.kv-zahl { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.kv-zahl b { font-weight: 400; color: var(--text-dim); }
/* Knapp: der Vorrat geht zur Neige. Leer: hier gibt es davon nichts (mehr). */
.kv-zeile.knapp .kv-balken i { background: #d0913a; }
.kv-zeile.knapp .kv-zahl { color: #d8ab7c; }
.kv-zeile.leer { opacity: 0.55; }
.kv-zeile.leer .kv-balken i { background: #8a4a3c; }
.kv-zeile.leer .kv-zahl { color: #d4695a; }
.kv-fuss { margin: calc(0.45rem * var(--tafel-skala)) 0 0; font-size: calc(0.78rem * var(--tafel-skala)); color: var(--text-dim); line-height: 1.3; }

/* Rückfrage nach einem gezogenen Zug — UND ihr Gegenstück vorm Abriss
   (#abrissfrage, main.ts frageAbriss). Beide sitzen über der Bauleiste,
   mittig, dort, wo der Blick nach dem Loslassen ohnehin hängt, und nehmen
   Klicks an (anders als die übrigen HUD-Schichten), sonst ginge der Knopf
   ins Leere.

   Beim Abriss ist "Ja" mit .gefahr eingefärbt statt mit .zug-ja: Dort wird
   nicht bestätigt, sondern zerstört, und Grün für "reiß es ab" wäre die
   falsche Ampel. .gefahr kommt schon global mit (button.gefahr, siehe oben
   im Dokument) und braucht hier keine eigene Regel. */
#zugfrage,
#abrissfrage {
  bottom: calc(var(--baumenu-hoehe, 12rem) + 3.6rem);
  left: 50%;
  transform: translateX(-50%);
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 0.7rem 1rem;
  background: rgba(18, 20, 23, 0.96);
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 4px 18px rgba(0, 0, 0, 0.55);
}
#zugfrage[hidden],
#abrissfrage[hidden] { display: none; }
.zugfrage-text {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text);
  text-align: center;
}
.zugfrage-knoepfe { display: flex; gap: 0.5rem; }
#zugfrage button,
#abrissfrage button {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.35rem 0.9rem;
  border-radius: 2px;
  cursor: var(--cursor-gold);
  background: rgba(30, 34, 38, 0.9);
  color: var(--text);
  border: 1px solid var(--iron);
}
#zugfrage .zug-ja,
#abrissfrage .zug-ja {
  color: #9ae86a;
  border-color: #4d7a3c;
}
#zugfrage .zug-ja:hover,
#abrissfrage .zug-ja:hover { background: rgba(60, 90, 45, 0.5); }
#zugfrage .zug-nein,
#abrissfrage .zug-nein { color: #d4695a; }
#zugfrage .zug-nein:hover,
#abrissfrage .zug-nein:hover { background: rgba(90, 45, 40, 0.5); }
/* .gefahr ist global (button.gefahr, weiter oben im Dokument) — hier nur
   ausdrücklich wiederholt, weil die ID-Regel "#abrissfrage button" sonst
   dieselben Eigenschaften (background, color, border) mit höherer
   Spezifität überschriebe und "Ja, abreißen" wieder wie ein normaler,
   ungefährlicher Knopf aussähe. */
#abrissfrage button.gefahr {
  border-color: var(--blood);
  background: linear-gradient(180deg, #52302a, #331d19);
  color: #f0d5c8;
}
#abrissfrage button.gefahr:hover {
  border-color: #b8543c;
  background: linear-gradient(180deg, #63392f, #3d211b);
}

/* Der Weg steht in jedem Reiter — abgesetzt durch einen Trenner und
   einen leichten Messingschimmer, damit er nicht wie ein Gebäude des gerade
   offenen Reiters gelesen wird. */
#baumenu .bau-ikone.dauerhaft {
  border-color: var(--brass-dark);
  background: rgba(168, 129, 61, 0.08);
}
/* Weg und Abriss stehen IMMER da, unabhängig vom Reiter — schmaler als die
   wechselnden Gebäudekacheln daneben, damit sie sich als eigene, kleinere
   Werkzeuggruppe lesen und nicht wie ein drittes Gebäude in der Reihe. "Weg"
   und "Abriss" samt Kosten-/Rückgabezeile passen auch schmaler noch
   einzeilig. */
#baumenu .bau-ikone.dauerhaft .bau-ikone__text {
  width: 3rem;
}
#baumenu .bau-trenner {
  flex: 0 0 auto;
  align-self: stretch;
  width: 1px;
  margin: 0.15rem 0.3rem;
  background: var(--iron);
}
/* Rohstoffe reichen (noch) nicht: Bild ergraut, wählbar bleibt die Ikone —
   geplant wird kostenlos, bezahlt erst beim Bestätigen. Nur das BILD wird
   entsättigt, nicht der ganze Knopf: der Name muss lesbar bleiben. */
#baumenu .bau-ikone.zu-teuer .bau-ikone__bild {
  filter: grayscale(0.85) brightness(0.72);
}
#baumenu .bau-ikone.zu-teuer .bau-ikone__name {
  color: var(--text-dim);
}
/* Schloss als gezeichnetes Symbol statt Emoji — bleibt im Pixelstil */
#baumenu .bau-ikone__schloss {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 10px;
  height: 8px;
  background: var(--iron-light);
  border-radius: 1px;
}
#baumenu .bau-ikone__schloss::before {
  content: "";
  position: absolute;
  top: -5px;
  left: 2px;
  width: 6px;
  height: 5px;
  border: 1.6px solid var(--iron-light);
  border-bottom: none;
  border-radius: 3px 3px 0 0;
}

/* DIE BAUINFOTAFEL — oben rechts, das Gegenstück zu #kartenvorrat oben links.
   Gleiche Breite, gleicher Rahmen, gleiche Höhe unter dem Kopfband: Links
   steht, was der ORT hergibt, rechts, was das gewählte WERKZEUG kann. Zwei
   Seiten derselben Entscheidung, darum als Paar gebaut — wer eine von beiden
   verstellt, verstellt die andere mit.

   Vorher war das eine Karte ÜBER der Bauleiste, die sich nur über ein "?" an
   jeder Kachel öffnete. Sie machte die Leiste höher, und auf einem kleinen
   Notebook war genau diese Höhe das Problem. Das "?" ist mitsamt seiner
   Karte ersatzlos fort: Die Tafel geht von selbst auf, sobald etwas gewählt
   ist, und sie steht am Rand, wo sie nichts verdeckt.

   Der Rand ist SPIEGELBILDLICH gesetzt (border-right statt border-left),
   damit die Messingkante bei beiden Tafeln nach außen zeigt. */
#bauinfo {
  top: 3.6rem;
  right: 0.7rem;
  left: auto;
  /* Breite, Ränder und Schriftgrade hängen an --tafel-skala, derselben
     Stellschraube wie die Vorratstafel gegenüber (dort steht sie erklärt).
     Die beiden sind ein Paar und müssen zusammen wachsen. */
  width: var(--tafel-breite);
  /* Sie darf nicht bis in die Bauleiste hinunterwachsen: Auf einem kurzen
     Bildschirm ist eine lange Beschreibung sonst genau das, was hier gerade
     abgeschafft wurde. pointer-events wieder an, sonst ließe sich in einer
     abgeschnittenen Tafel nicht rollen (.hud setzt es für die Schicht ab). */
  max-height: calc(100vh - 4.2rem - var(--baumenu-hoehe, 12rem) - 1.5rem);
  overflow-y: auto;
  pointer-events: auto;
  padding: calc(0.55rem * var(--tafel-skala)) calc(0.7rem * var(--tafel-skala)) calc(0.5rem * var(--tafel-skala));
  background: rgba(18, 20, 23, 0.94);
  border: 1px solid var(--iron);
  border-right: 2px solid var(--brass-dark);
  border-radius: 2px;
}
/* Cunrat sitzt sonst genau hier (`.schreiber`, top: 7.2rem rechts) und läge
   quer über der Tafel. Im Baumodus rückt er unter sie — die Höhe misst ui.ts
   bei jedem Aufbau (renderBauinfo), weil sie mit der Länge der Beschreibung
   schwankt. Ohne gewählte Bautafel ist die Variable 0 und er steht, wo er
   immer stand. */
body.baumodus .schreiber {
  top: max(7.2rem, calc(3.6rem + var(--bauinfo-hoehe, 0px) + 0.7rem));
}
.bi-kopf {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: calc(0.5rem * var(--tafel-skala));
  margin-bottom: calc(0.4rem * var(--tafel-skala));
}
.bi-titel { font-size: calc(0.9rem * var(--tafel-skala)); color: var(--brass-light); letter-spacing: 0.02em; }
.bi-bauzeit { font-size: calc(0.72rem * var(--tafel-skala)); color: var(--text-dim); white-space: nowrap; }
/* Das Bildchen des Bauwerks (client/public/gebaeudebilder, 464 breit im
   Verhältnis 21:9 — dasselbe Breitformat wie die Ladebilder, in deren Machart
   sie gemalt sind). Es behält sein Verhältnis, wird also nicht beschnitten:
   Die Szene ist eigens für diesen Platz gemalt und hat nichts Überflüssiges am
   Rand, das man wegschneiden müsste.

   RANDLOS bis an die Tafelkanten. Es ist das einzige Stück der Tafel, das
   über den Innenabstand hinausgreift — die negativen Ränder heben genau die
   Polsterung von #bauinfo wieder auf, und weil oben zusätzlich der Kopf sitzt,
   sitzt es nicht in der Ecke, sondern unter der Überschrift.

   Warum nur DAS Bild und nicht die ganze Tafel: Ein Versuch, beide Bautafeln
   anderthalbfach zu strecken (--tafel-skala: 1.5), machte sie in der Sache
   nicht besser — der Text war schon vorher gut lesbar, die Tafeln nahmen bloß
   Burg weg. Zu klein war allein die Szene darin. Also wächst allein sie, und
   in einer 232 Pixel breiten Tafel ist randlos dafür die Obergrenze: Mehr
   ginge nur, indem die Tafel selbst breiter wird. */
.bi-bild {
  display: block;
  width: calc(100% + 2 * 0.7rem * var(--tafel-skala));
  margin-left: calc(-0.7rem * var(--tafel-skala));
  margin-right: calc(-0.7rem * var(--tafel-skala));
  aspect-ratio: 21 / 9;
  object-fit: cover;
  border-top: 1px solid var(--iron);
  border-bottom: 1px solid var(--iron);
  margin-bottom: calc(0.5rem * var(--tafel-skala));
}
.bi-flavor {
  margin: 0;
  font-size: calc(0.78rem * var(--tafel-skala));
  font-style: italic;
  line-height: 1.3;
  color: var(--text-dim);
}
.bi-mechanik {
  margin: calc(0.35rem * var(--tafel-skala)) 0 0;
  font-size: calc(0.78rem * var(--tafel-skala));
  line-height: 1.3;
  color: var(--text);
}

/* --- DER MELDUNGSSTAPEL OBEN LINKS ------------------------------------------

   Vier Zettel, einer unter dem anderen, von oben nach unten in der
   Reihenfolge ihrer Dringlichkeit:

     #bedrohungen    Wolfsrudel und Räuberlager — Gefahr mit Frist
     #handelsfuhren  ein Karren unterwegs
     #ausbau         die Stufe des Bergfrieds
     #queue          laufende Bauvorhaben

   Jeder misst seine Höhe selbst und schiebt die darunter weg
   (--bedrohungen-hoehe, --fuhren-hoehe; gesetzt in ui.ts nach dem Messen).

   WARUM OBEN LINKS. Der Stapel stand bis 08/2026 unten links, und dort lag
   er über der Fußleiste: Bauwerkzeuge und Vorratsanzeige teilen sich denselben
   Balken (#buildbar, bottom 0), die Zettel begannen 1,6rem darüber und
   verdeckten ihn, sobald mehr als eine Meldung anstand. Genau das hat der
   Bauherr gemeldet.

   Oben rechts geht nicht: Dort klappen Charaktermenü und Kopfband-Popups auf.
   Bleibt oben links. Dort sitzen zwar auch Gebäudepanel und die Vorratstafel
   des Bauplans — aber die sind beide FLÜCHTIG (ein Klick öffnet sie, ein Klick
   schließt sie wieder) und stehen in index.html NACH diesen Zetteln, decken
   sie also von selbst zu, solange sie offen sind. Ein verdeckter Zettel, der
   beim Schließen wieder da ist, wiegt leichter als eine dauerhaft verdeckte
   Vorratsanzeige.

   Das Werkstatt/MAIN-Schild musste dafür weichen — es sitzt jetzt oben RECHTS
   (siehe .versionsschild weiter unten). */
:root {
  /* Oberkante des Stapels: unter dem Kopfband, mit etwas Luft. Die Bandhöhe
     wird gemessen, nicht geraten (ui.ts, meldeKopfbandHoehe) — das Band bricht
     bei schmalem Fenster um. Der Rückfallwert greift nur für den Wimpernschlag,
     bevor das Bündel geladen ist. */
  --meldungen-oben: calc(var(--kopfband-hoehe, 42px) + 0.7rem);
}

/* Blutrand statt Messing: Das hier ist keine Verwaltung, das ist Gefahr — sie
   muss sich von jedem anderen Zettel des Stapels unterscheiden, ohne dass man
   liest. Ganz oben, weil zuerst gelesen gehört, was eine Frist hat. */
#bedrohungen {
  top: var(--meldungen-oben);
  bottom: auto;
  right: auto;
  left: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: 264px;
}
.bedrohung {
  background: rgba(24, 16, 16, 0.92);
  border: 1px solid #6e2a22;
  border-left: 3px solid #8f3a2c;
  border-radius: 2px;
  padding: 0.45rem 0.6rem;
  font-size: 0.85rem;
}
/* Der Kopf ist jetzt ein KNOPF: Ein Klick klappt Vignette und Beschreibung
   aus. Er muss trotzdem aussehen wie eine Überschrift und nicht wie ein
   Bedienelement — die Zeile war vorher eine, und der Zettel soll nicht
   plötzlich nach Formular aussehen. Der Zeiger verrät, dass da etwas geht. */
.bedrohung .kopf {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  width: 100%;
  padding: 0;
  font: inherit;
  text-align: left;
  color: #d8a08a;
  background: none;
  border: 0;
  cursor: var(--cursor-gold);
}
.bedrohung .kopf::after {
  content: "▸";
  font-size: 0.7rem;
  color: #8a6a5a;
  transition: transform 0.12s;
}
.bedrohung .kopf[aria-expanded="true"]::after {
  transform: rotate(90deg);
}

/* Die ausgeklappte Vignette. Volle Zettelbreite, damit sie wirkt — dasselbe
   Bild und dieselbe Machart wie die Ereignisbilder (build-ereignisbilder.js),
   nur kleiner gezeigt. */
.bedrohung-bild {
  display: block;
  width: 100%;
  margin: 0.4rem 0 0.3rem;
  border: 1px solid #5a3a30;
  image-rendering: pixelated;
}
.bedrohung-bild[hidden] { display: none; }
.bedrohung-szene {
  margin-bottom: 0.35rem;
  font-family: var(--font-body);
  font-style: italic;
  line-height: 1.4;
  color: var(--parchment);
}
.bedrohung-szene[hidden] { display: none; }

/* Der Kräftebalken. Die ganze Breite ist die Summe beider Kampfkräfte; der
   dunkelrote Teil gehört dem Lager. Steht er über der Hälfte, ist der Ausfall
   aussichtslos — DAS ist die Zahl, die der Spieler früher selbst ausrechnen
   musste, und die Mitte ist genau die Kippstelle (bei Gleichstand siegt der
   Verteidiger, also das Lager). */
.bedrohung .kraftbalken {
  position: relative;
  height: 6px;
  margin: 0.35rem 0 0.25rem;
  background: #3a5040;
  border: 1px solid #2a1c18;
  border-radius: 1px;
  overflow: hidden;
}
.bedrohung .kraftbalken .feind {
  display: block;
  height: 100%;
  background: #8f3a2c;
}
/* Die Marke in der Mitte: hier kippt es. Ohne sie wäre der Balken hübsch,
   aber ohne Schwelle — und ein Verhältnis ohne Schwelle liest niemand. */
.bedrohung .kraftbalken::after {
  content: "";
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: 50%;
  width: 1px;
  background: #e8d9b0;
  opacity: 0.75;
}

.bedrohung .urteil.gut { color: #86a86e; }
.bedrohung .urteil.knapp { color: #e0b060; }
.bedrohung .urteil.schlecht { color: #d4695a; font-weight: 600; }

/* Der Abkauf steht neben dem Ausrücken, aber leiser: Er ist der teurere Weg
   und soll nicht der erste Griff sein. Messing statt Blut — es ist ein
   Handel, kein Gefecht. */
.bedrohung .entsenden button.abkauf {
  color: #d9c9a4;
  background: #33291c;
  border-color: #6d5426;
  font-size: 0.76rem;
}
.bedrohung .entsenden button.abkauf:hover:not(:disabled) {
  background: #42341f;
}
.bedrohung .staerke {
  font-size: 0.8rem;
  color: #b98;
  white-space: nowrap;
}
.bedrohung .zeile {
  margin-top: 0.15rem;
}
.bedrohung .zeile.muted {
  color: #9a8f83;
  font-size: 0.78rem;
}
.bedrohung .lauf {
  color: #e0b060;
  font-variant-numeric: tabular-nums;
}
.bedrohung .entsenden {
  display: flex;
  gap: 0.4rem;
  margin-top: 0.35rem;
}
.bedrohung .entsenden input {
  width: 3.2rem;
  font: inherit;
  color: inherit;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid #5a4a3a;
  border-radius: 2px;
  padding: 0.15rem 0.3rem;
}
.bedrohung .entsenden button {
  flex: 1;
  cursor: var(--cursor-gold);
  font: inherit;
  font-size: 0.82rem;
  color: #e8c9a0;
  background: #4a2620;
  border: 1px solid #8f3a2c;
  border-radius: 2px;
  padding: 0.2rem 0.5rem;
}
.bedrohung .entsenden button:hover:not(:disabled) {
  background: #5d2f26;
}
.bedrohung .entsenden button:disabled {
  opacity: 0.5;
  cursor: var(--cursor-kupfer);
}

/* --- Der Ausrück-Dialog ------------------------------------------------------
   Zwei Scharen, die einander gegenüberstehen. Der Ausfall war vorher ein
   Zahlenfeld neben einem Knopf; das genügte mechanisch, war aber keine
   Entscheidung, sondern eine Eingabe. Hier sieht man, WEN man wegschickt und
   WEN man dort vorfindet — mit denselben Figuren, die auch im Hof stehen.

   Machart wie die Ereignistafel (dunkler Vorhang, Messingrahmen): Es ist
   dieselbe Sorte Augenblick, nur eine, die man auch abbrechen darf. */
#ausrueckung {
  position: fixed;
  inset: 0;
  z-index: 905;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 11, 13, 0.72);
}
#ausrueckung[hidden] { display: none; }

.ausrueck-tafel {
  width: min(34rem, 100%);
  max-height: 90vh;
  overflow-y: auto;
  padding: 1.3rem 1.4rem 1.1rem;
  background: var(--stone-800);
  border: 1px solid var(--brass-dark);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
}
.ausrueck-tafel h2 {
  margin: 0 0 0.9rem;
  font-size: 1.35rem;
  font-weight: normal;
  color: var(--brass-light);
}

/* Die Aufstellung. Drei Spalten, das "gegen" in der Mitte — man liest von
   links nach rechts und weiß danach, worauf man sich einlässt. */
.ausrueck-schlacht {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  gap: 0.6rem;
  align-items: start;
}
.ar-gegen {
  align-self: center;
  padding-top: 1.2rem;
  font-family: var(--font-body);
  font-style: italic;
  color: var(--text-dim);
}
.ar-kopf {
  margin-bottom: 0.3rem;
  font-size: 0.85rem;
  color: var(--brass-light);
}
.ar-ihre .ar-kopf { color: #d8a08a; }

/* Die Reihe der Figuren. Sie umbricht, statt zu überlaufen: Eine Schar von
   zwölf Mann soll zweizeilig dastehen, nicht aus dem Zettel laufen.
   align-items: flex-end, weil die Sprites verschieden hoch sind (ein Wolf ist
   niedriger als ein Söldner) und alle auf DERSELBEN Standlinie stehen müssen —
   sonst schweben die Tiere. */
.ar-reihe {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 1px;
  min-height: 58px;
  padding: 0.3rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--iron);
  border-radius: 2px;
}
.ar-figur {
  height: 52px;
  width: auto;
  image-rendering: pixelated;
}
/* Die Gegenseite in derselben fahlen Tönung wie im Hof (feindLager.ts,
   FEIND_TON): fremde Leute, die seit Tagen im Feld liegen. Ein Filter statt
   eines zweiten Bildersatzes — dieselbe Absicht, ein Bruchteil des Aufwands. */
.ar-ihre .ar-figur {
  filter: brightness(0.82) saturate(0.55);
}
.ar-mehr {
  align-self: flex-end;
  padding-left: 0.3rem;
  font-size: 0.8rem;
  color: var(--text-dim);
}
.ar-kraft {
  margin-top: 0.3rem;
  font-size: 0.8rem;
  color: var(--text-dim);
}

.ausrueck-regler { margin-top: 1rem; }
.ar-label {
  display: block;
  font-size: 0.9rem;
  color: var(--text);
}
.ar-label input[type="range"] {
  display: block;
  width: 100%;
  margin-top: 0.3rem;
  accent-color: var(--brass);
  cursor: var(--cursor-gold);
}
.ar-marsch,
.ar-leer {
  margin-top: 0.4rem;
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* Das Urteil. Groß und in Farbe, weil es die eine Zeile ist, die zählt —
   "aussichtslos" soll niemand überlesen und hinterher fragen, warum sieben
   Mann nicht wiederkamen. */
.ausrueck-urteil {
  margin: 0.7rem 0 0.9rem;
  font-size: 1.1rem;
}
.ausrueck-urteil.gut { color: #86a86e; }
.ausrueck-urteil.knapp { color: #e0b060; }
.ausrueck-urteil.schlecht { color: #d4695a; font-weight: 600; }

.ausrueck-knoepfe {
  display: flex;
  gap: 0.5rem;
}
.ausrueck-knoepfe button { flex: 1; text-align: center; }

/* --- Die Standestafel --------------------------------------------------------
   Wer der Spieler ist, was er getan hat und was ihm zum nächsten Rang fehlt.
   Liegt über der Burg wie die Ereignistafel und nicht in der Ecke: Man liest
   sie einmal, fasst einen Vorsatz und geht zurück ans Werk. */
#spielerpanel {
  position: fixed;
  inset: 0;
  z-index: 880;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 11, 13, 0.72);
  pointer-events: auto;
}
#spielerpanel[hidden] { display: none; }
.sp-tafel {
  position: relative;
  width: min(34rem, 100%);
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
  padding: 1.2rem 1.4rem 1.4rem;
  background: linear-gradient(180deg, rgba(30, 33, 38, 0.99), rgba(18, 20, 23, 0.99));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.75);
}
.sp-zu {
  position: absolute;
  top: 0.5rem;
  right: 0.7rem;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.4rem;
  line-height: 1;
  cursor: var(--cursor-gold);
}
.sp-zu:hover { color: var(--brass-light); }

.sp-kopf { display: flex; gap: 1rem; align-items: flex-start; }
/* Bildnis und Wappen. Beide werden bei der Charaktererstellung gewählt; ohne
   gewähltes Bildnis steht wie früher die Initiale auf dem Schild — leer wäre
   schlimmer als vorläufig. Das Wappen sitzt als kleines Zeichen in der Ecke,
   so wie ein Siegel an einer Urkunde: es gehört zum Bild, drängt sich aber
   nicht davor. */
/* Das Bildnis ist seit 08/2026 ein KNOPF: Ein Klick darauf klappt die Auswahl
   auf, statt auf /charakter zu führen (spielerpanel.js). Die Schildform, die
   Maße und alles Sichtbare bleiben unverändert — die drei Zeilen darunter
   nehmen nur die Knopf-Voreinstellungen des Browsers zurück, damit aus dem
   Wappenschild kein grauer Kasten wird. */
.sp-bildnis {
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: var(--cursor-gold, pointer);
  position: relative;
  flex: none;
  width: 5.5rem;
  height: 6.4rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  background: linear-gradient(180deg, rgba(74, 63, 82, 0.5), rgba(40, 34, 46, 0.6));
  border: 1px solid var(--brass-dark);
  /* Schildform: oben gerade, unten in eine Spitze zulaufend. */
  clip-path: polygon(0 0, 100% 0, 100% 62%, 50% 100%, 0 62%);
}
/* Das Porträt füllt das Schild ganz aus; die Schildform beschneidet es
   ohnehin. object-fit hält das Gesicht im oberen Teil, wo die Spitze noch
   nichts wegnimmt. */
.sp-portrait {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
  image-rendering: pixelated;
}
.sp-initiale {
  font-family: var(--font-display);
  font-size: 2.4rem;
  line-height: 1;
  color: var(--brass-light);
}
.sp-wappen {
  position: absolute;
  right: -0.15rem;
  bottom: 1.35rem;
  width: 1.9rem;
  height: 1.9rem;
  image-rendering: pixelated;
  border: 1px solid var(--brass-dark);
  /* Dieselbe Schildform wie das große Bildnis, nur klein. */
  clip-path: polygon(0 0, 100% 0, 100% 62%, 50% 100%, 0 62%);
}

/* Die Marke "ändern" liegt in der Schildspitze und ist normalerweise fast
   unsichtbar — sie soll sagen, DASS hier etwas geht, ohne das Bildnis zu
   überschreiben. Beim Überfahren tritt sie hervor. */
.sp-bildnis-marke {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.15rem;
  text-align: center;
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brass-light, #cca75e);
  opacity: 0.45;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9);
  transition: opacity 0.15s;
  pointer-events: none;
}
.sp-bildnis:hover .sp-bildnis-marke,
.sp-bildnis:focus-visible .sp-bildnis-marke { opacity: 1; }
.sp-bildnis:hover { border-color: var(--brass-light, #cca75e); }

/* DIE BILDNISWAHL. Ein Gitter aus 66 Köpfen — es braucht die ganze Breite der
   Tafel und deshalb eine eigene Zeile unter der Kopfzeile, nicht den Platz
   neben dem Namen. Gedeckelte Höhe mit eigenem Rollbalken: Sonst schöbe die
   Auswahl Rangleiter und Bedingungen aus dem Bild, also genau das, wofür man
   die Tafel sonst aufmacht. */
.sp-bildniswahl {
  margin: 0.7rem 0 0.2rem;
  padding: 0.55rem 0.6rem 0.6rem;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--iron);
  border-left: 2px solid var(--brass-dark);
  border-radius: 2px;
}
.sp-bildniswahl.laeuft { opacity: 0.5; pointer-events: none; }
.sp-bildniswahl-kopf {
  margin: 0 0 0.45rem;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim, #928b7d);
}
.sp-bildnisgitter {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(3rem, 1fr));
  gap: 0.35rem;
  max-height: 14rem;
  overflow-y: auto;
}
.sp-bildniskachel {
  padding: 0;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold, pointer);
  aspect-ratio: 87 / 96;
  overflow: hidden;
}
.sp-bildniskachel img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
  image-rendering: pixelated;
}
.sp-bildniskachel:hover { border-color: var(--brass-light, #cca75e); }
/* Das eigene Bildnis bleibt erkennbar, auch beim Rollen durch die Reihe. */
.sp-bildniskachel.gewaehlt {
  border-color: var(--brass-light, #cca75e);
  box-shadow: 0 0 0 1px var(--brass-light, #cca75e) inset;
}

.sp-namen { min-width: 0; flex: 1; }
.sp-titel {
  display: block;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
}
.sp-name {
  display: block;
  font-family: var(--font-display);
  font-size: 1.9rem;
  line-height: 1.15;
  color: var(--brass-light);
}
.sp-rangtext { margin: 0.35rem 0 0; font-size: 0.85rem; line-height: 1.45; color: var(--text-dim); }
/* Der Weg zur Charakterwahl. Bewusst zurückhaltend: Er steht neben dem
   Bildnis, weil er dorthin gehört, soll aber nicht mit dem Rang um
   Aufmerksamkeit streiten. */
.sp-wechseln {
  display: inline-block;
  margin-top: 0.5rem;
  font-size: 0.8rem;
  color: var(--brass);
  border-bottom: 1px solid transparent;
}
.sp-wechseln:hover {
  color: var(--brass-light);
  border-bottom-color: var(--brass);
}
/* "Bildnis ändern" ist ein BUTTON, seine Nachbarn sind Links. Ohne diese
   Zeilen brächte er die Voreinstellungen des Browsers mit — Kasten, Rahmen,
   eigene Schrift — und stünde als Fremdkörper zwischen zwei Textwegen.
   Er ist trotzdem ein Knopf und kein Link: Er führt nirgendwohin, er klappt
   die Auswahl darunter auf. */
button.sp-wechseln {
  background: none;
  border: none;
  border-bottom: 1px solid transparent;
  padding: 0;
  font: inherit;
  font-size: 0.8rem;
  cursor: var(--cursor-gold);
}
/* Die beiden stehen nebeneinander in einer Zeile — ohne Abstand kleben
   "Bildnis ändern" und "Wappen ändern" aneinander. */
.sp-bildnistext { margin-right: 0.9rem; }
/* "Von vorn beginnen" — dieselbe zurückhaltende Form wie .sp-wechseln, aber
   in Blutrot statt Messing: Wer hier klickt, verliert die ganze Burg, nicht
   nur ihr Aussehen. Die Farbe soll das schon vor der Rückfrageseite sagen. */
.sp-zuruecksetzen {
  display: block;
  margin-top: 0.3rem;
  color: var(--blood);
}
.sp-zuruecksetzen:hover {
  color: #d97a5c;
  border-bottom-color: var(--blood);
}

.sp-taten {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: 0.5rem;
  margin-top: 1rem;
  padding: 0.6rem 0;
  border-top: 1px solid var(--iron);
  border-bottom: 1px solid var(--iron);
}
.sp-taten > div { display: flex; flex-direction: column; gap: 0.1rem; }
.sp-wert { font-size: 1rem; color: var(--text); }
.sp-marke { font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-dim); }

/* Die Leiter als Kette. Erreichtes in Messing, der aktuelle Rang gefüllt,
   das Künftige blass — auf einen Blick, wo man steht und wie weit es ist. */
.sp-leiter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
}
.sp-stufe {
  padding: 0.2rem 0.5rem;
  font-size: 0.78rem;
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--text-dim);
}
.sp-stufe.erreicht { border-color: var(--brass-dark); color: var(--brass); }
.sp-stufe.jetzt {
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.22);
  color: #e8d5a8;
  font-weight: bold;
}

.sp-aufstieg { margin-top: 1.1rem; }
.sp-aufstieg h3 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  margin: 0 0 0.3rem;
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--brass-light);
}
.sp-anteil { font-family: var(--font-body); font-size: 0.85rem; color: var(--text-dim); }

.sp-bedingungen { margin: 0.7rem 0 0; padding: 0; list-style: none; }
.sp-bedingung {
  display: grid;
  grid-template-columns: 1.2rem 1fr auto;
  align-items: center;
  gap: 0.4rem 0.5rem;
  padding: 0.28rem 0;
}
.sp-haken { color: var(--text-dim); text-align: center; }
.sp-bedingung.erfuellt .sp-haken { color: #a9c795; }
.sp-bedingung.erfuellt .sp-was,
.sp-bedingung.erfuellt .sp-zahl { color: var(--text-dim); }
.sp-zahl { font-variant-numeric: tabular-nums; font-size: 0.85rem; }
/* Der Balken läuft über die volle Breite unter der Zeile — so vergleicht man
   auf einen Blick, welche Aufgabe am weitesten und welche am wenigsten weit
   ist, ohne die Zahlen im Kopf ins Verhältnis setzen zu müssen. */
.sp-balken {
  grid-column: 2 / -1;
  height: 3px;
  background: rgba(0, 0, 0, 0.4);
  border-radius: 2px;
  overflow: hidden;
}
.sp-balken i { display: block; height: 100%; background: var(--brass); }
.sp-bedingung.erfuellt .sp-balken i { background: #7fa663; }
.sp-bereit { margin: 0.7rem 0 0; color: #a9c795; }
.sp-hinweis { margin: 0; color: var(--text-dim); }

/* --- Die Botenstube ----------------------------------------------------------
   Ein Fenster, das Burgansicht und Landkarte teilen (server/public/chat.js).
   Frei verschiebbar und in der Größe zu ziehen — deshalb bekommt es hier nur
   Aussehen und Innenaufbau; wo es steht und wie groß es ist, schreibt das
   Skript als Inline-Stil, weil es aus localStorage kommt und den Seitenwechsel
   überleben muss. */
.chatfenster {
  position: fixed;
  z-index: 55;
  display: flex;
  flex-direction: column;
  background: linear-gradient(180deg, rgba(36, 40, 46, 0.97), rgba(20, 23, 27, 0.97));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.6);
  font-size: 0.9rem;
  overflow: hidden;
}
.chatfenster[hidden] { display: none; }

.ct-kopf {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.6rem;
  background: rgba(0, 0, 0, 0.35);
  border-bottom: 1px solid var(--iron);
  /* Die Titelleiste IST der Griff — deshalb der Greifzeiger und kein
     Textmarkieren beim Ziehen. */
  cursor: var(--cursor-hand, grab);
  user-select: none;
}
.ct-titel { color: var(--brass-light); }
.ct-summe {
  margin-left: auto;
  min-width: 1.3rem;
  padding: 0 0.3rem;
  text-align: center;
  font-size: 0.78rem;
  background: var(--blood);
  color: #f0c9bd;
  border-radius: 999px;
}
.ct-summe[hidden] { display: none; }
.ct-klapp {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.1rem;
  line-height: 1;
  padding: 0 0.25rem;
  cursor: var(--cursor-gold);
}
.ct-summe:not([hidden]) + .ct-klapp { margin-left: 0.4rem; }
.ct-klapp:hover { color: var(--brass-light); }

.ct-koerper {
  display: flex;
  flex-direction: column;
  /* Füllt, was die Titelleiste übrig lässt. Die Höhe steht am Fenster —
     hier stünde sie in einem Flex-Item und würde weggeschrumpft. */
  flex: 1;
  min-height: 0;
  /* Eingeklappt fährt der Körper auf null — das Fenster schrumpft dann auf
     seine Titelleiste, bleibt aber an derselben Stelle stehen. */
  transition: height 0.15s ease;
}
.chatfenster.zu .ct-koerper { display: none; }

.ct-faeden {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.4rem;
  border-bottom: 1px solid var(--iron);
  overflow-x: auto;
}
.ct-faden {
  position: relative;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--iron);
  border-radius: 2px;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.82rem;
  padding: 0.15rem 0.5rem;
  white-space: nowrap;
  cursor: var(--cursor-gold);
}
.ct-faden.aktiv {
  border-color: var(--brass);
  background: rgba(109, 84, 38, 0.28);
  color: var(--text);
}
.ct-punkt {
  margin-left: 0.3rem;
  padding: 0 0.25rem;
  font-size: 0.72rem;
  background: var(--blood);
  color: #f0c9bd;
  border-radius: 999px;
}
.ct-neu {
  font: inherit;
  font-size: 0.8rem;
  background: rgba(0, 0, 0, 0.3);
  color: var(--text-dim);
  border: 1px solid var(--iron);
  max-width: 8rem;
}

.ct-verlauf {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.4rem 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.ct-zeile {
  margin: 0;
  line-height: 1.35;
  word-break: break-word;
}
.ct-zeit { color: var(--text-dim); font-size: 0.78rem; margin-right: 0.35rem; }
.ct-von { color: var(--brass-light); margin-right: 0.35rem; }
.ct-von::after { content: ":"; }
/* Eigene Worte etwas zurückgenommen — man erkennt die eigene Stimme ohnehin,
   und die der anderen sind das, was man sucht. */
.ct-zeile.selbst .ct-von { color: var(--moss); }
.ct-zeile.privat { background: rgba(109, 84, 38, 0.12); border-left: 2px solid var(--brass-dark); padding-left: 0.35rem; }
.ct-leer { color: var(--text-dim); font-style: italic; margin: auto; }

.ct-eingabe {
  display: flex;
  gap: 0.3rem;
  padding: 0.4rem;
  border-top: 1px solid var(--iron);
}
.ct-eingabe input {
  flex: 1;
  min-width: 0;
  font: inherit;
  font-size: 0.88rem;
  padding: 0.25rem 0.45rem;
}
.ct-eingabe button { font-size: 0.85rem; padding: 0.25rem 0.7rem; }
.ct-fehler {
  margin: 0;
  padding: 0 0.55rem 0.4rem;
  font-size: 0.8rem;
  color: #d08a7a;
}
.ct-fehler[hidden] { display: none; }

/* Die Ecke zum Ziehen. Kein eigenes Bild — zwei Striche genügen, und sie
   liegen dort, wo man sie erwartet. */
.ct-griffecke {
  position: absolute;
  right: 0;
  bottom: 0;
  width: 14px;
  height: 14px;
  cursor: nwse-resize;
  background:
    linear-gradient(135deg, transparent 50%, var(--iron-light, #6a6864) 50%, var(--iron-light, #6a6864) 60%, transparent 60%),
    linear-gradient(135deg, transparent 70%, var(--iron-light, #6a6864) 70%, var(--iron-light, #6a6864) 80%, transparent 80%);
}
.chatfenster.zu .ct-griffecke { display: none; }

/* --- Das Chronik-Fenster ----------------------------------------------------
   Trägt dieselbe Rahmen-Chromik wie die Botenstube (.chatfenster, .ct-*),
   nur der Körper füllt sich anders: Geschehnisprotokoll und Bewohner statt
   Gesprächsfäden. Hier steht nur, was daran EIGEN ist. */
.kf-fenster {
  min-width: 340px;
}
.kf-koerper {
  overflow-y: auto;
  padding: 0.6rem 0.7rem 0.8rem;
  gap: 0;
}
.kf-kopfzeile {
  margin: 0 0 0.5rem;
  color: var(--text-dim);
  font-size: 0.85rem;
}
.kf-fehler {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  color: #d08a7a;
}
.kf-fehler[hidden] { display: none; }
.kf-abschnitt {
  margin-top: 0.9rem;
}
.kf-abschnitt:first-of-type {
  margin-top: 0;
}
.kf-abschnitt h4 {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass);
}
/* Kleinere Schrift als die normale table-Regel aus ui.css, damit auf 440px
   Breite nicht jede Zeile umbricht. */
.kf-abschnitt table {
  font-size: 0.82rem;
}

/* --- Das Produktions-Fenster ------------------------------------------------
   Dieselbe Rahmen-Chromik wie Botenstube und Chronik (.chatfenster, .ct-*);
   hier steht nur, was daran EIGEN ist: die Tabelle mit den Flusszahlen und
   die beiden Graphen (Sparklinie je Zeile, grosser Verlauf oben).

   Die Farben sind die des Spiels und nicht neu erfunden: --moss fuer alles,
   was hereinkommt, --fire-light fuer alles, was hinausgeht. Dieselbe Farbsprache
   trug bis zum 24.08.2026 auch eine Produktionszeile in der Chronik
   (.kf-plus / .kf-minus); sie ist entfallen, weil sie neben diesem Fenster
   dasselbe sagte — nur als Momentaufnahme statt als Verlauf. */
.pf-fenster {
  min-width: 420px;
}
.pf-koerper {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 0.6rem 0.7rem 0.6rem;
  gap: 0;
}
.pf-fehler {
  margin: 0 0 0.5rem;
  font-size: 0.85rem;
  color: #d08a7a;
}
.pf-fehler[hidden] { display: none; }

/* Die Spannenwahl — Reiter in derselben Machart wie .kf-reiter. */
.pf-spannen {
  display: flex;
  gap: 0.3rem;
  margin-bottom: 0.5rem;
  flex-wrap: wrap;
}
.pf-spanne {
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
  border-radius: 2px;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-ui, system-ui), sans-serif;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  cursor: pointer;
}
.pf-spanne:hover { color: var(--text); }
.pf-spanne.aktiv {
  color: var(--brass);
  border-color: var(--brass);
}

/* Der grosse Verlauf. Feste Hoehe, damit die Tabelle darunter nicht springt,
   sobald eine andere Ware gewaehlt wird. */
.pf-graph {
  flex: 0 0 auto;
  min-height: 136px;
  margin-bottom: 0.5rem;
}
.pf-graphkopf {
  font-size: 0.8rem;
  margin-bottom: 0.15rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.pf-legende {
  margin-left: auto;
  font-size: 0.72rem;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.pf-legende i {
  display: inline-block;
  width: 0.7rem;
  height: 0;
  border-top: 2px solid currentColor;
  margin-right: 0.15rem;
}
.pf-mark-ein { color: var(--moss); }
.pf-mark-aus { color: var(--fire-light); }
.pf-hinweis {
  font-size: 0.82rem;
  margin: 0.6rem 0;
}
.pf-svg { display: block; overflow: visible; }
.pf-svg polyline { fill: none; stroke-width: 1.6; stroke-linejoin: round; stroke-linecap: round; }
.pf-linie-ein { stroke: var(--moss); }
.pf-linie-aus { stroke: var(--fire-light); }
.pf-achse { stroke: var(--brass-dark, rgba(255, 255, 255, 0.25)); stroke-width: 1; }
.pf-marke {
  fill: var(--text-dim);
  font-family: var(--font-ui, system-ui), sans-serif;
  font-size: 9px;
}

/* Die Tabelle nimmt den Rest und scrollt fuer sich — der Graph soll beim
   Blaettern stehen bleiben. */
.pf-tabelle {
  flex: 1 1 auto;
  overflow-y: auto;
  min-height: 4rem;
}
.pf-tabelle table {
  font-size: 0.82rem;
  width: 100%;
}
/* Enger als die allgemeine Tabellenregel: Sechzehn Waren sind moeglich, und
   je hoeher eine Zeile, desto frueher scrollt eine Liste, die man am Stueck
   ueberblicken will. */
.pf-tabelle td,
.pf-tabelle th {
  padding: 0.18rem 0.45rem;
}
.pf-r { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.pf-plus { color: var(--moss); }
.pf-minus { color: var(--fire-light); }
.pf-zeile { cursor: pointer; }
.pf-zeile:hover td { background: rgba(255, 255, 255, 0.05); }
.pf-zeile.pf-gewaehlt td {
  background: rgba(255, 255, 255, 0.08);
  box-shadow: inset 2px 0 0 var(--brass);
}
.pf-zeile:focus-visible { outline: 1px solid var(--brass); outline-offset: -1px; }
.pf-sparte { width: 90px; padding-right: 0 !important; }
.pf-spark { display: block; }
.pf-spark polyline { fill: none; stroke: var(--brass); stroke-width: 1.2; stroke-linejoin: round; }
.pf-spark .pf-null { stroke: var(--brass-dark, rgba(255, 255, 255, 0.25)); stroke-width: 0.8; }
.pf-leer { color: var(--text-dim); }
.pf-fuss {
  margin: 0.4rem 0 0;
  font-size: 0.72rem;
}

/* Am Handy ist es — wie die Chronik — ein formatfuellendes Blatt, kein
   Fenster: Ziehen und Groesseziehen sind dort abgeschaltet (das Skript prueft
   body.handy), und ein 620 Pixel breites Fenster passt ohnehin nicht. */
body.handy #produktionsfenster {
  left: 0 !important;
  top: 0 !important;
  bottom: 0 !important;
  width: 100% !important;
  height: 100% !important;
  max-width: none;
  border-radius: 0;
}
body.handy .pf-sparte { display: none; }

/* --- Versionsschild -----------------------------------------------------------
   Klein unten links, auf jeder Seite, die versionsschild.js einbindet. Es sagt
   nur eines: welcher Stand hier läuft. Gebaut nach zwei Runden Fehlersuche, in
   denen der Browser-Zwischenspeicher einen längst behobenen Fehler vorgetäuscht
   hat — ändert sich der Stempel nach dem Neuladen nicht, war es der Cache.

   Bewusst zurückhaltend: halbdurchsichtig, klein, und es fängt keine Klicks ab
   (pointer-events: none) — es liegt über der Karte, soll aber nie im Weg sein.
   Beim Darüberfahren wird es lesbar, dann steht der volle Stand im Tooltip. */
.versionsschild {
  position: fixed;
  left: 0.5rem;
  bottom: 0.35rem;
  z-index: 2100;
  padding: 0.1rem 0.4rem;
  border-radius: 2px;
  font-family: var(--font-ui, system-ui), sans-serif;
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  line-height: 1.5;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0.35;
  transition: opacity 0.15s;
}
.versionsschild:hover { opacity: 1; }
/* MAIN tritt zurück — man liest es nur, wenn man es sucht. */
.versionsschild.main {
  background: rgba(0, 0, 0, 0.5);
  border: 1px solid var(--brass-dark, #7a6538);
  color: var(--brass-light, #cca75e);
}
/* Die WERKSTATT meldet sich deutlicher: Wer lokal spielt und es für die
   öffentliche Fassung hält, wundert sich sonst über Werkzeuge, die dort gar
   nicht existieren — oder testet stundenlang am falschen Stand. */
.versionsschild.werkstatt {
  background: rgba(122, 62, 24, 0.65);
  border: 1px solid #c87a3c;
  color: #f2d3a8;
  opacity: 0.55;
}

/* In der BURGANSICHT hängt das Schild oben RECHTS unter dem Kopfband statt
   unten in der Ecke. Zwei Gründe, einer nach dem anderen entstanden:

   Unten ging es nicht mehr, seit die Fußleiste weg ist — dort steht kein
   Balken mehr, auf dem es sitzen könnte, und es schwebte allein über der Burg
   wie ein Teil des Spiels statt wie ein Stempel.

   Oben LINKS ging es seit 08/2026 nicht mehr: Dorthin ist der Meldungsstapel
   gezogen (siehe #bedrohungen), weil er unten die Vorratsanzeige verdeckte.
   Zwei Dinge an derselben Stelle sind eines zu viel — und von beiden ist der
   Stempel das, was man nur sucht, wenn man etwas wissen will.

   Die anderen Seiten (Landkarte, Chronik, Werkzeuge) behalten unten links:
   Sie haben ihren eigenen Rahmen (server/src/render.ts) und oben rechts ihre
   eigenen Knöpfe.

   --kopfband-hoehe wird gemessen, nicht geraten (ui.ts, meldeKopfbandHoehe) —
   das Kopfband bricht bei schmalem Fenster um. Der Rückfallwert greift nur
   für den Wimpernschlag, bevor das Bündel geladen ist. */
body.spiel .versionsschild {
  top: calc(var(--kopfband-hoehe, 42px) + 0.35rem);
  bottom: auto;
  right: 0.5rem;
  left: auto;
  /* UNTER dem Kopfband statt darüber. Sonst legte sich der Stempel über das
     Charaktermenü, das genau hier aufklappt — und ein halbdurchsichtiges
     Schild quer über den Menüeinträgen liest sich wie ein Darstellungsfehler.
     Die 9 ist bewusst kleiner als .hud (10): Alles, was zur Bedienoberfläche
     gehört, deckt den Stempel zu. Nur in der Burgansicht; die anderen Seiten
     behalten ihre 2100, dort steht nichts, was ihn verdecken könnte. */
  z-index: 9;
}

/* --- Wehrbau-Probebühne (/dev/wehrbau-probe) ----------------------------- */

.wp-leiste {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  align-items: center;
  margin-bottom: 10px;
}
.wp-gruppe {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.wp-gruppe label {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 0.9rem;
  color: #c9c0ad;
}
#wp-werkzeuge button {
  padding: 5px 12px;
}
/* Das gewählte Werkzeug trägt dieselbe Messingfarbe wie die aktiven
   Schaltflächen im Sprite-Editor — man soll auf einen Blick sehen, was ein
   Klick auf die Bühne gerade täte. */
#wp-werkzeuge button.wp-aktiv {
  background: #7a5a24;
  border-color: #c8a45c;
  color: #f6e6c4;
}
.wp-buehne {
  overflow: auto;
  border: 1px solid #3a3f47;
  border-radius: 4px;
  background: #20242a;
  /* Der Mauszeiger zeigt auf die Kachel, nicht auf ein Bild darin. */
  line-height: 0;
}
.wp-buehne canvas {
  image-rendering: pixelated;
  cursor: crosshair;
}
.wp-warnung {
  color: #e8a13c;
}
/* Feste Höhe, damit die Bühne nicht springt, sobald ein Hinweis zwei Zeilen
   braucht — sonst rutscht die Kachel unter dem Mauszeiger beim Klicken weg. */
#wp-stand {
  min-height: 2.6em;
  margin: 6px 0 8px;
}

/* --------------------------------------------------------------------------
   Charaktererstellung (/charakter, server/src/charakter.ts)
   --------------------------------------------------------------------------
   Der eine Schritt zwischen Registrierung und Burgwahl: Bildnis, Herkunft,
   Wappen. Drei Tafeln untereinander, jede mit einer Auswahl darin.

   Durchgehendes Muster: Der Radiobutton selbst ist unsichtbar, sichtbar ist
   das, was er auswählt (Bild, Karte, Farbtupfen). Deshalb steckt jedes
   <input> in seinem <label> und wird per :checked am Nachbarn abgelesen. */

/*
 * DAS WAR DER GRUND FÜR DAS ENDLOSE SCROLLEN.
 *
 * Weiter oben steht `form { max-width: 340px }` — sinnvoll für Anmelde- und
 * Einzelfeld-Formulare, für die es gedacht war. Die Charaktererstellung ist
 * aber kein solches Formular, sondern eine Auslage: 60 Bildnisse, 3 Herkünfte,
 * Wappenfarben und -symbole. Auf 340 Pixeln gepresst standen die Bildnisse zu
 * ZWEIT nebeneinander — dreißig Reihen, in einem Container, der 1056 Pixel
 * breit ist. Gemessen, nicht geschätzt.
 *
 * Mit der vollen Breite passen zwölf in eine Reihe: aus dreißig Reihen werden
 * fünf. Das ist der ganze Unterschied zwischen "man scrollt ewig" und "man
 * sieht seine Auswahl".
 */
.ch-form {
  max-width: none;
}
.ch-form section.panel { margin-bottom: 1rem; }
.ch-form h2 { margin: 0 0 .6rem; }

/* --- Ton an/aus auf der Charakterseite -------------------------------------
 *
 * Oben rechts, schwebend. Die Seite hat bewusst keine Kopfleiste (sie ist ein
 * Weg ohne Rückkehr), deshalb steht der Schalter für sich — dezent, bis man
 * ihn sucht. Er ist die Gegenleistung dafür, dass die Musik hier von selbst
 * anläuft: Wer sie nicht will, muss sie mit EINEM Griff abstellen können, ohne
 * erst eine Einstellungsseite zu finden.
 *
 * `hidden` bis JavaScript ihn freischaltet (musik-charakter.js): Ohne Skript
 * gibt es weder Musik noch etwas abzuschalten — ein toter Knopf wäre schlimmer
 * als keiner.
 */
.ch-ton {
  position: fixed;
  top: 14px;
  right: 16px;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .3rem .7rem;
  font-family: var(--font-body);
  font-size: .82rem;
  color: var(--brass-light, #cca75e);
  background: rgba(20, 23, 26, 0.72);
  border: 1px solid var(--brass-dark, #6b5426);
  border-radius: 3px;
  cursor: pointer;
  opacity: 0.75;
  transition: opacity .15s, border-color .15s, color .15s;
}
.ch-ton:hover { opacity: 1; border-color: var(--brass, #a8813d); }
.ch-ton .ch-ton-zeichen { font-size: 1rem; line-height: 1; }
/* Abgestellt: matter, und das Notenzeichen bekommt einen Querstrich. */
.ch-ton.aus { color: #8b8f95; border-color: #4a4d54; }
.ch-ton.aus .ch-ton-zeichen { position: relative; }
.ch-ton.aus .ch-ton-zeichen::after {
  content: "";
  position: absolute;
  left: -2px;
  right: -2px;
  top: 50%;
  border-top: 1px solid currentColor;
  transform: rotate(-20deg);
}
@media (max-width: 640px) {
  .ch-ton .ch-ton-text { display: none; }
  .ch-ton { padding: .35rem .5rem; }
}

.ch-raster {
  display: grid;
  gap: 8px;
  margin-top: .6rem;
}
.ch-raster-avatare { grid-template-columns: repeat(auto-fill, minmax(84px, 1fr)); }
.ch-raster-symbole { grid-template-columns: repeat(auto-fill, minmax(56px, 1fr)); }

.ch-kachel { display: block; cursor: var(--cursor-gold); }
.ch-kachel input { position: absolute; opacity: 0; pointer-events: none; }

.ch-kachel img,
.ch-kachel .ch-symbol {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  border: 2px solid var(--iron);
  /* Pixelbilder dürfen beim Vergrößern nicht weichgezeichnet werden. */
  image-rendering: pixelated;
}
/* Nur die Bildnis-Kacheln bekommen den dunklen Steingrund. Für .ch-symbol
   NICHT hier mitsetzen: `.ch-kachel .ch-symbol` (zwei Klassen) schlägt sonst
   IMMER die eigene Regel unten (`.ch-symbol { background-color: ... }`,
   nur eine Klasse) — ganz gleich, welche Reihenfolge im Stylesheet steht.
   Die Maskenfarbe landete dadurch auf demselben Dunkel wie der Kachelgrund
   selbst: eine so gut wie unsichtbare Silhouette, schwarz auf schwarz. */
.ch-kachel img { background: var(--stone-800); }
/*
 * OHNE DIESE ZEILE WERDEN DIE BILDNISSE VERZERRT.
 *
 * Die Kachel oben erzwingt ein Quadrat (aspect-ratio: 1), die Büsten sind
 * aber alle 96 Pixel HOCH und verschieden BREIT — gemessen von 75 bis 113.
 * Ein <img> ohne object-fit füllt seine Box, indem es das Bild dehnt: Jedes
 * Gesicht wurde also um einen anderen Betrag gestaucht oder gezogen, und nur
 * die drei zufällig quadratischen sahen richtig aus.
 *
 * `contain` statt `cover`: Ein Bildnis ist ein Porträt, da darf nichts
 * abgeschnitten werden — lieber links und rechts etwas Stein sehen als ein
 * angeschnittenes Kinn. Der Kachelgrund trägt die Ränder.
 */
.ch-kachel img { object-fit: contain; }
.ch-kachel:hover img,
.ch-kachel:hover .ch-symbol { border-color: var(--iron-light); }
.ch-kachel input:checked ~ img,
.ch-kachel input:checked ~ .ch-symbol {
  border-color: var(--brass-light);
  box-shadow: 0 0 0 1px var(--brass-dark);
}

/* Das Wappenzeichen ist eine Silhouette. Als MASKE gesetzt trägt die
   Hintergrundfarbe die Darstellung — so lässt sich dasselbe Bild in jeder
   Tinktur zeigen, ohne für jede Farbe eine eigene Datei zu backen. */
.ch-symbol {
  background-color: var(--parchment);
  -webkit-mask-image: var(--symbol);
  mask-image: var(--symbol);
  /*
   * `contain` STATT einer festen Prozentgröße — hier stand 76% 76%, und das
   * zwang jede Silhouette auf 76 % BEIDER Kanten der quadratischen Kachel.
   * Die Zeichen sind aber alle 64 Pixel hoch und zwischen 12 und 247 breit:
   * Ein schmales Schwert wurde auf Kachelbreite aufgeblasen, ein breites
   * Band plattgedrückt, und nur die zufällig quadratischen stimmten —
   * dieselbe Sorte Fehler wie das fehlende object-fit bei den Bildnissen.
   *
   * Die Luft um das Zeichen kommt jetzt aus dem INNENABSTAND: Die Maske wird
   * auf den Inhaltskasten begrenzt (mask-clip/-origin content-box) und darin
   * unverzerrt eingepasst. Der Server macht es beim fertigen Wappenbild
   * genauso (wappen.ts, fit "inside") — Vorschau und Ergebnis zeigen damit
   * dieselben Proportionen.
   */
  padding: 12%;
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-origin: content-box;
  mask-origin: content-box;
  -webkit-mask-clip: content-box;
  mask-clip: content-box;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

/* --- Herkunft: drei Karten nebeneinander -------------------------------- */

.ch-herkuenfte {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
  margin-top: .6rem;
}
.ch-herkunft { display: block; cursor: var(--cursor-gold); }
.ch-herkunft input { position: absolute; opacity: 0; pointer-events: none; }
.ch-herkunft-tafel {
  height: 100%;
  padding: .8rem .9rem 1rem;
  border: 2px solid var(--iron);
  background: var(--stone-800);
}
.ch-herkunft:hover .ch-herkunft-tafel { border-color: var(--iron-light); }
.ch-herkunft input:checked ~ .ch-herkunft-tafel {
  border-color: var(--brass-light);
  background: var(--stone-700);
}
.ch-herkunft-tafel h3 { margin: .1rem 0 .4rem; }
.ch-herkunft-tafel p { margin: 0 0 .6rem; }

.ch-vorrat { list-style: none; margin: 0; padding: 0; }
.ch-vorrat li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 1px 0;
  font-size: .92em;
  color: var(--text-dim);
}
.ch-vorrat b { color: var(--text); font-variant-numeric: tabular-nums; }

/* --- Wappen: Vorschau links, Farbwahl rechts ---------------------------- */

.ch-wappenbau {
  display: flex;
  gap: 1.2rem;
  align-items: flex-start;
  flex-wrap: wrap;
  margin-top: .6rem;
}

/* Der Schild. Unten spitz zulaufend über clip-path — ein Rechteck sähe aus
   wie ein Farbfeld, nicht wie ein Wappen. */
.ch-wappen-vorschau {
  flex: 0 0 auto;
  width: 96px;
  height: 112px;
  background: var(--stone-700);
  border: 2px solid var(--brass-dark);
  clip-path: polygon(0 0, 100% 0, 100% 62%, 50% 100%, 0 62%);
  position: relative;
}
.ch-wappen-vorschau::after {
  content: "";
  position: absolute;
  /*
   * Der Kasten selbst IST jetzt der Platz des Zeichens (statt inset: 0 plus
   * mask-size 58% 58% — die feste Prozentgröße verzerrte jede nicht-
   * quadratische Silhouette, siehe .ch-symbol). Die Zahlen ergeben dieselbe
   * Lage wie vorher: 58 % Breite mittig (21 % je Seite), 58 % Höhe um die
   * 38-%-Linie (9 % oben, 33 % unten) — im oberen Schildteil, weil der
   * untere spitz zuläuft. Darin unverzerrt eingepasst.
   */
  inset: 9% 21% 33% 21%;
  background-color: var(--symbolfarbe, var(--parchment));
  -webkit-mask-image: var(--symbol, none);
  mask-image: var(--symbol, none);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.ch-wappen-regler { flex: 1 1 260px; }
.ch-feld { border: 0; margin: 0 0 .8rem; padding: 0; }
.ch-feld legend { padding: 0; margin-bottom: .3rem; color: var(--text-dim); font-size: .92em; }
.ch-farben { display: flex; flex-wrap: wrap; gap: 6px; }

.ch-farbe { cursor: var(--cursor-gold); }
.ch-farbe input { position: absolute; opacity: 0; pointer-events: none; }
.ch-farbe-tupfen {
  display: block;
  width: 30px;
  height: 30px;
  border: 2px solid var(--iron);
}
.ch-farbe:hover .ch-farbe-tupfen { border-color: var(--iron-light); }
.ch-farbe input:checked ~ .ch-farbe-tupfen { border-color: var(--brass-light); }
/* GESPERRT: Die Farbe trägt bereits der Schild — auf sich selbst wäre das
   Zeichen unsichtbar (charakter.js, haltFarbenAuseinander). Der Tupfen bleibt
   STEHEN und wird nur durchgestrichen, statt zu verschwinden: Eine Reihe, aus
   der Felder springen, sobald man nebenan etwas anfasst, ist nicht zu
   bedienen — und dass gerade DIESE Farbe belegt ist, ist ja die Auskunft. */
.ch-farbe.gesperrt {
  cursor: not-allowed;
}
.ch-farbe.gesperrt .ch-farbe-tupfen {
  opacity: 0.3;
  border-style: dashed;
  border-color: var(--iron);
  position: relative;
}
.ch-farbe.gesperrt .ch-farbe-tupfen::after {
  content: "";
  position: absolute;
  inset: -2px;
  background: linear-gradient(45deg, transparent 45%, var(--text-dim) 45% 55%, transparent 55%);
}
.ch-farbe.gesperrt:hover .ch-farbe-tupfen { border-color: var(--iron); }
.ch-farbregel {
  margin: 0.5rem 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
  font-style: italic;
}
.ch-farbregel[hidden] { display: none; }
/* Der Farbname trägt die Bedeutung für Vorleseprogramme, sichtbar reicht der
   Tupfen — die Namen nebeneinander sprengten sonst die Zeile. */
.ch-farbe-name {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* --- Das Stillleben der Herkunftskarte ----------------------------------
   Randlos bis an die Tafelkante (die negativen Ränder heben die Polsterung
   der Tafel wieder auf) — ein Bild mit Passepartout sähe nach Fotoalbum aus,
   nicht nach Karte. Ungewählte Karten stehen leicht gedimmt: Die Wahl soll
   man am BILD ablesen können, nicht nur am Rahmen. */
.ch-herkunft-bild {
  display: block;
  width: calc(100% + 1.8rem);
  /* Quadratisch wie die Quelle (448×448) — `height: auto` hebt die im HTML
     gesetzten Maße wieder auf und lässt das Bild unverzerrt mitwachsen. Ohne
     das würden die Attribute width/height eine feste Größe erzwingen. */
  height: auto;
  margin: -0.8rem -0.9rem 0.7rem;
  border-bottom: 1px solid var(--iron);
  filter: saturate(0.8) brightness(0.82);
  transition: filter 0.25s;
}
.ch-herkunft:hover .ch-herkunft-bild { filter: saturate(0.95) brightness(0.95); }
.ch-herkunft input:checked ~ .ch-herkunft-tafel .ch-herkunft-bild { filter: none; }

/* === Die drei Stationen ======================================================
   Bildnis → Herkunft → Wappen. Alles hier hängt an `ch-js` (setzt
   charakter.js): Ohne Skript gibt es keine Leiste und keine verborgenen
   Abschnitte — die Seite ist dann eine gewöhnliche Rolle von oben nach
   unten, und das Formular schickt wie eh und je. */

.ch-form:not(.ch-js) .ch-stationen { display: none; }

.ch-stationen {
  display: flex;
  justify-content: center;
  gap: 0;
  list-style: none;
  margin: 0.2rem 0 1.1rem;
  padding: 0;
}
.ch-stationen li { display: flex; align-items: center; }
/* Der Faden zwischen den Stationen — Teil der VORDEREN Station, damit er
   sich mit ihr färbt, wenn sie hinter einem liegt. */
.ch-stationen li + li::before {
  content: "";
  width: clamp(24px, 6vw, 72px);
  height: 1px;
  background: var(--iron);
  margin: 0 0.4rem;
}
.ch-station {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  background: none;
  border: none;
  padding: 0.25rem 0.35rem;
  font: inherit;
  color: var(--text-dim);
  cursor: var(--cursor-gold);
}
/* Die Münze mit der römischen Zahl. */
.ch-station i {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border: 1px solid var(--iron);
  border-radius: 50%;
  background: var(--stone-800);
  /* BUCHSCHRIFT, nicht Schmuckschrift: Das Fraktur-I der Zierschrift liest
     sich als 3 — aus I·II·III wurde auf den Münzen "3·33·333". Römische
     Zahlen brauchen die nüchterne Serifenschrift. */
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  transition: border-color 0.2s, color 0.2s, box-shadow 0.2s;
}
.ch-station span {
  font-size: 0.95rem;
  letter-spacing: 0.03em;
}
.ch-station:hover i { border-color: var(--iron-light); }
.ch-station.aktiv { color: var(--brass-light); }
.ch-station.aktiv i {
  border-color: var(--brass-light);
  color: var(--brass-light);
  box-shadow: 0 0 10px rgba(204, 167, 94, 0.25);
}
.ch-station.besucht { color: var(--text); }
.ch-station.besucht i { border-color: var(--brass-dark); color: var(--brass); }

/* Die Abschnitte: mit Skript sieht man genau einen. Der Auftritt ist ein
   aufgelegtes Pergament — kurz, tief, ohne Springerei. */
.ch-js .ch-schritt { display: none; }
.ch-js .ch-schritt.aktiv {
  display: block;
  animation: ch-pergament 0.35s ease;
}
@keyframes ch-pergament {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: none; }
}

/* --- Die Geleitzeile ---------------------------------------------------------
   Unten angeheftet: links der Rückweg, in der Mitte die bisherige Wahl,
   rechts Weiter bzw. das Siegel. Sie schwebt über dem Inhalt (sticky), damit
   der Weg nach vorn nie hinter einem langen Raster verschwindet. */
.ch-geleit {
  position: sticky;
  bottom: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 1rem 0 0;
  padding: 0.55rem 0.8rem;
  background: linear-gradient(180deg, rgba(24, 26, 30, 0.88), rgba(16, 18, 21, 0.94));
  border-top: 1px solid var(--brass-dark);
  backdrop-filter: blur(3px);
}
.ch-geleit-wahl {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-right: auto;
  min-height: 40px;
}
.ch-geleit-wahl img {
  height: 40px;
  border: 1px solid var(--iron);
  background: var(--stone-800);
  image-rendering: pixelated;
}
.ch-geleit-wahl span {
  font-family: var(--font-display);
  font-size: 1.02rem;
  color: var(--parchment);
}
.ch-geleit-schild {
  position: relative;
  width: 26px;
  height: 30px;
  background: var(--stone-700);
  clip-path: polygon(0 0, 100% 0, 100% 62%, 50% 100%, 0 62%);
}
.ch-geleit-schild::after {
  content: "";
  position: absolute;
  inset: 10% 18% 32% 18%;
  background-color: var(--symbolfarbe, var(--parchment));
  -webkit-mask-image: var(--symbol, none);
  mask-image: var(--symbol, none);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}

.ch-zurueck,
.ch-weiter {
  font: inherit;
  padding: 0.5rem 1.1rem;
  color: var(--text);
  background: linear-gradient(180deg, #333941, #22262b);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.ch-weiter {
  border-color: var(--brass-dark);
  color: var(--brass-light);
}
.ch-zurueck:hover { border-color: var(--iron-light); }
.ch-weiter:hover { border-color: var(--brass); }

/* --- Der Abschlussknopf -------------------------------------------------------
   Ein rechteckiger Knopf, ohne Zeichen — dasselbe Gewand wie "Weiter"
   daneben, nur in Messing statt Eisen: Was den Weg beendet, darf sich vom
   Weiterblättern abheben, ohne aus der Reihe zu tanzen.

   Hier stand ein rundes Wachssiegel mit eingeprägtem Turm. Es sah gut aus,
   passte aber nicht in eine Zeile mit zwei kantigen Knöpfen — und ein Zeichen,
   das man erklären muss, erklärt nichts. Der Druck-Effekt beim Absenden bleibt
   (jetzt als kurzes Einsinken des Knopfes, siehe charakter.js).

   Auf den ersten Stationen ausgeblendet (nur MIT Skript): "So sei es" kann man
   erst meinen, wenn man alles gesehen hat. */
.ch-js .ch-siegel:not(.bereit) { display: none; }
.ch-siegel {
  font: inherit;
  font-family: var(--font-display);
  font-size: 1.02rem;
  letter-spacing: 0.04em;
  padding: 0.55rem 1.6rem;
  color: var(--brass-light);
  background: linear-gradient(180deg, #3b3126, #241e17);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  transition: border-color 0.15s, background 0.15s, transform 0.12s, box-shadow 0.15s;
}
.ch-siegel:hover {
  border-color: var(--brass);
  background: linear-gradient(180deg, #46392b, #2b241b);
}
/* Bereit heißt: letzte Station. Ein leises Glimmen am Rand, kein Blinken. */
.ch-siegel.bereit { animation: ch-siegel-glimmen 2.6s ease-in-out infinite; }
@keyframes ch-siegel-glimmen {
  0%, 100% { box-shadow: 0 0 0 rgba(204, 167, 94, 0); }
  50% { box-shadow: 0 0 14px rgba(204, 167, 94, 0.28); }
}
/* Beim Absenden kurz einsinken — der Rest des Siegel-Gedankens. */
.ch-siegel.drueckt { animation: ch-siegel-druck 0.6s ease forwards; }
@keyframes ch-siegel-druck {
  0% { transform: scale(1); }
  40% { transform: scale(0.96); box-shadow: inset 0 3px 10px rgba(0, 0, 0, 0.5); }
  100% { transform: scale(0.98); box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.45); }
}

/* --- Kerzenlicht --------------------------------------------------------------
   Warmer Schein aus den Ecken, der leise atmet — die Seite spielt in dem Saal,
   in dem gleich gesiegelt wird.

   VERSTÄRKT: Der Schein lag zuvor unter einem Zehntel Deckkraft und war damit
   auf den meisten Bildschirmen schlicht nicht zu sehen — die Absicht "sehr
   zurückhaltend" war so weit getrieben, dass gar nichts mehr ankam. Jetzt
   vier Lichtquellen statt zwei, kräftiger und mit einem zweiten, langsameren
   Takt darüber.

   ZWEI Ebenen, weil eine Kerze nicht gleichmäßig flackert: `::before` trägt
   die beiden großen Scheine, `::after` zwei kleinere mit anderer Laufzeit.
   Weil sich die Takte (7,3 s und 4,1 s) nicht glatt teilen, wiederholt sich
   das Muster erst nach Minuten statt im Sekundentakt — das ist der ganze
   Unterschied zwischen "atmet" und "blinkt".

   Beide liegen über allem, fangen aber keine Klicks (pointer-events). */
.ch-form::before,
.ch-form::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  /* Addiert sich auf den Grund, statt ihn zu überdecken: Licht macht heller,
     es legt keinen Schleier darüber. Ohne das wirkte der stärkere Schein wie
     Nebel im Saal. */
  mix-blend-mode: screen;
}
.ch-form::before {
  background:
    radial-gradient(1000px 700px at 10% 2%, rgba(255, 186, 92, 0.3), transparent 60%),
    radial-gradient(780px 560px at 96% 92%, rgba(255, 176, 84, 0.2), transparent 58%);
  animation: ch-kerzen 7.3s ease-in-out infinite;
}
.ch-form::after {
  background:
    radial-gradient(520px 420px at 88% 6%, rgba(255, 198, 110, 0.16), transparent 62%),
    radial-gradient(460px 380px at 4% 78%, rgba(255, 168, 76, 0.13), transparent 62%);
  animation: ch-kerzen-zweit 4.1s ease-in-out infinite;
}
@keyframes ch-kerzen {
  0%, 100% { opacity: 0.72; }
  38% { opacity: 1; }
  62% { opacity: 0.84; }
}
@keyframes ch-kerzen-zweit {
  0%, 100% { opacity: 0.55; }
  30% { opacity: 0.95; }
  70% { opacity: 0.68; }
}

/* Wer Bewegung abbestellt hat, bekommt keine — weder Flackern noch Auftritt
   noch Siegeldruck (den Aufschub davor überspringt charakter.js selbst). */
@media (prefers-reduced-motion: reduce) {
  .ch-form::before,
  .ch-form::after { animation: none; }
  .ch-js .ch-schritt.aktiv { animation: none; }
  .ch-siegel.bereit { animation: none; }
}

/* === Tafeln, die BEIDE Ansichten tragen =====================================
   Ortstafel und Diplomatie-Tafel standen bis zum gemeinsamen Kopfband allein
   in karte.css. Das ging, solange es die Diplomatie nur auf der Landkarte gab
   — seit sie auch in der Burgansicht sitzt, nicht mehr: Die Burgansicht lädt
   karte.css nicht (und soll es auch nicht, dort stehen Kartenraster, Wolken
   und Zoomstufen drin). Also stehen die geteilten Tafeln hier, wo jede Seite
   sie ohnehin bekommt (render.ts und client/index.html laden ui.css beide).
   Die Karte verliert nichts: ui.css liegt dort VOR karte.css.
   ========================================================================== */
/* --- Ortstafel der Landschau -------------------------------------------------
   Erst anwählen, dann handeln. Sie sitzt an derselben Stelle und in derselben
   Formsprache wie die Tafel der Burgwahl — wer einmal einen Sitz gewählt hat,
   findet sich hier ohne Umlernen zurecht. Der Landbalken und die Landliste
   teilen sich sogar die Klassen mit ihr (.landbalken, .landliste). */
.ortstafel {
  /* Fest statt absolut: In der Burgansicht hängt die Tafel unmittelbar am
     Fenster (dort gibt es keinen Kartenrahmen, gegen den sie sich stellen
     könnte), auf der Karte sieht es genauso aus, weil die Karte ohnehin das
     ganze Fenster füllt. */
  position: fixed;
  /* UNTER dem Kopfband, nicht darunter verschwindend. Die Höhe wird gemessen
     und nicht geraten (kopfleiste.js setzt --kopfband-hoehe auf beiden
     Seiten) — der Ausweichwert greift nur, solange nichts gemessen ist. */
  top: calc(var(--kopfband-hoehe, 42px) + 0.6rem);
  right: 0.8rem;
  z-index: 30;
  width: 18.5rem;
  max-width: calc(100vw - 1.6rem);
  max-height: calc(100vh - var(--kopfband-hoehe, 42px) - 1.6rem);
  overflow-y: auto;
  padding: 0.75rem 0.9rem 0.85rem;
  background: rgba(14, 14, 11, 0.94);
  border: 1px solid var(--iron, #3b414a);
  border-radius: 3px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.65);
}
.ortstafel[hidden] { display: none; }

.ortstafel .ort-zu {
  position: absolute;
  top: 0.3rem;
  right: 0.4rem;
  width: 1.5rem;
  height: 1.5rem;
  line-height: 1;
  font-size: 1.1rem;
  color: var(--text-dim, #928b7d);
  background: none;
  border: 0;
  cursor: var(--cursor-gold, pointer);
}
.ortstafel .ort-zu:hover { color: var(--parchment, #d7c7a3); }

.ortstafel h3 {
  margin: 0 1.4rem 0.15rem 0;
  font-family: var(--font-body, Georgia, serif);
  font-size: 1.15rem;
  font-weight: normal;
  color: var(--brass-light, #cca75e);
  line-height: 1.2;
}
.ortstafel .lage {
  margin: 0 0 0.5rem;
  font-size: 0.82rem;
}
.ortstafel .besitz {
  margin: 0 0 0.5rem;
  font-size: 0.88rem;
  color: var(--text, #d2ccbf);
}

/* --- "Einzelheiten" und "Das Land": zugeklappt bis man sie will -----------
   Native <details>/<summary> statt eines eigenen Auf/Zu-Knopfes mit JS
   davor — braucht keine Skriptzeile, tastaturbedienbar von Haus aus, und der
   Zustand bleibt beim Umschalten zwischen Fensterbreiten erhalten. Dieselbe
   Bauart wie im Dev-Panel (#devpanel details), nur in Messing statt Glut,
   damit sie sich in die Ortstafel einfügt. */
.ortstafel .ort-mehr {
  margin: 0.55rem 0 0;
}
.ortstafel .ort-mehr + .ort-mehr {
  margin-top: 0.35rem;
  padding-top: 0.35rem;
  border-top: 1px solid rgba(59, 65, 74, 0.4);
}
.ortstafel .ort-mehr summary {
  margin: 0;
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim, #928b7d);
  cursor: var(--cursor-gold, pointer);
  list-style: revert;
}
.ortstafel .ort-mehr summary::marker {
  color: var(--brass, #a8813d);
  font-size: 0.75em;
}
.ortstafel .ort-mehr summary:hover {
  color: var(--brass-light, #cca75e);
}
.ortstafel .ort-mehr[open] summary {
  margin-bottom: 0.4rem;
}
/* Ein leeres "Das Land" (Dörfer haben keins) blendet ortstafel.js über
   [hidden] auf dem <details> selbst aus — dieselbe Eigenschaft, die vorher
   auf dem umschließenden <div> saß. */

/* Werteliste einer Spielerburg: Beschriftung links, Zahl rechts. */
.ortstafel .ortwerte {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
}
.ortstafel .ortwerte[hidden] { display: none; }
.ortstafel .ortwerte li {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.16rem 0;
  border-bottom: 1px solid rgba(59, 65, 74, 0.4);
  font-size: 0.82rem;
  color: var(--text-dim, #928b7d);
}
.ortstafel .ortwerte li:last-child { border-bottom: 0; }
.ortstafel .ortwerte b {
  font-weight: normal;
  color: var(--text, #d2ccbf);
  font-variant-numeric: tabular-nums;
}

/* Die Tat, die dieser Ort zulässt — Burg ansehen oder Dorf schützen. Es ist
   immer genau eine, deshalb steht sie breit und allein am Fuß der Tafel. */
/* War 0.9rem, als die Tat noch am Fuß der Tafel stand, hinter Bildchen,
   Land und Werten. Jetzt folgt sie direkt auf die Lage — die knappe Zeile
   darüber gibt schon genug Abstand. */
.ortstafel .ort-taten { margin-top: 0.5rem; }
.ortstafel .ort-tat {
  display: block;
  width: 100%;
  padding: 0.45rem 0.5rem;
  font: inherit;
  font-size: 0.92rem;
  text-align: center;
  text-decoration: none;
  color: #e6d9b8;
  background: #4a3a29;
  border: 1px solid var(--brass-dark, #6d5426);
  border-radius: 2px;
  cursor: var(--cursor-gold, pointer);
}
.ortstafel .ort-tat:hover {
  background: #5b4832;
  border-color: var(--brass, #a8813d);
}
.ortstafel .ort-tat:disabled {
  opacity: 0.5;
  cursor: var(--cursor-kupfer);
}
.ortstafel .ort-fussnote {
  margin: 0.3rem 0 0;
  font-size: 0.78rem;
  text-align: center;
  color: var(--moss, #7a9166);
}
.ortstafel .ort-meldung {
  margin: 0.6rem 0 0;
  font-size: 0.84rem;
  color: var(--moss, #7a9166);
}
.ortstafel .ort-meldung[hidden] { display: none; }
.ortstafel .ort-meldung.fehler { color: #d98b74; }


/* --- Diplomatie (Phase 7) --------------------------------------------------- */
.brietzaehler {
  display: inline-block;
  min-width: 1.1em;
  margin-left: 0.3em;
  padding: 0 0.3em;
  font-size: 0.75em;
  text-align: center;
  color: #f0d9c0;
  background: #8f3a2c;
  border-radius: 999px;
}
.diplomatietafel { width: 340px; max-height: 82vh; overflow-y: auto; }
.diplomatietafel .kopf { display: block; margin: 0.7rem 0 0.3rem; }
.diplomatietafel .reihe { display: flex; flex-wrap: wrap; gap: 0.35rem; align-items: center; margin: 0.25rem 0; }
.diplomatietafel button {
  cursor: var(--cursor-gold);
  font: inherit;
  font-size: 0.8rem;
  color: #d9c9a8;
  background: #2c2f36;
  border: 1px solid #5a4a3a;
  border-radius: 2px;
  padding: 0.2rem 0.5rem;
}
.diplomatietafel button:hover { border-color: #a8813d; }
.diplomatietafel button.brand { color: #e8c4b0; background: #4a2620; border-color: #8f3a2c; }
.diplomatietafel .dspieler-liste, .diplomatietafel .feldzuege { list-style: none; margin: 0; padding: 0; }
.diplomatietafel .dspieler, .diplomatietafel .feldzug {
  padding: 0.4rem 0.45rem;
  margin-bottom: 0.35rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid #3a3d44;
  border-radius: 2px;
  font-size: 0.85rem;
}
.diplomatietafel .feldzug.her { border-left: 3px solid #8f3a2c; }
.diplomatietafel .feldzug.hin { border-left: 3px solid #a8813d; }
.diplomatietafel .kopfzeile { display: flex; justify-content: space-between; gap: 0.5rem; align-items: baseline; }
.diplomatietafel .gut { color: #8fae7a; }
.diplomatietafel .warnung { color: #d8a08a; }
.diplomatietafel .lauf { color: #e0b060; font-variant-numeric: tabular-nums; }
.diplomatietafel .angriff input {
  width: 3.2rem;
  font: inherit;
  color: inherit;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid #5a4a3a;
  border-radius: 2px;
  padding: 0.15rem 0.3rem;
}
/* Der Ladeschein eines Trosses: eine Zeile je Ware, Menge in der Mitte, der
   Speicherstand daneben — man soll beim Ausfüllen nie nachschlagen müssen. */
.diplomatietafel .ladeliste { margin: 0.4rem 0; }
.diplomatietafel .ladeposten {
  display: grid;
  grid-template-columns: 1fr 4.2rem auto;
  gap: 0.4rem;
  align-items: center;
  padding: 0.15rem 0;
  font-size: 0.85rem;
}
.diplomatietafel .ladeposten input {
  font: inherit;
  font-size: 0.85rem;
  color: inherit;
  text-align: right;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid #5a4a3a;
  border-radius: 2px;
  padding: 0.15rem 0.3rem;
}
.diplomatietafel .lastzeile { margin: 0.3rem 0; font-size: 0.85rem; font-variant-numeric: tabular-nums; }
.diplomatietafel .lastzeile .last.warnung { color: #d8a08a; }

/* --- Was ein Bündnis bewirkt --------------------------------------------

   Der offene Speicher des Verbündeten. Fließtext aus Wortpaaren statt einer
   Tabelle: Es sind selten mehr als eine Handvoll Posten, und eine Tabelle mit
   drei Zeilen sieht aus, als fehlte etwas. */
.diplomatietafel .verblager {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.7rem;
  margin: 0.2rem 0 0.1rem;
  font-size: 0.8rem;
  color: #b9a887;
}
.diplomatietafel .verblager .lagerposten b {
  color: #e0d3b4;
  font-variant-numeric: tabular-nums;
}

/* Eine offene Bitte. Sie steht in der Zeile des Verbündeten und nicht in einer
   eigenen Liste: Eine Bitte ist etwas ZWISCHEN zwei Häusern, und wer sie
   beantworten will, sieht dort auch gleich, was der andere im Speicher hat. */
.diplomatietafel .bitte {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35rem;
  margin: 0.25rem 0 0.1rem;
  padding: 0.25rem 0.4rem;
  border-left: 2px solid #8a6a3a;
  background: rgba(138, 106, 58, 0.12);
  font-size: 0.85rem;
}

.diplomatietafel .briefe { max-height: 40vh; overflow-y: auto; margin: 0.4rem 0; }
.diplomatietafel .brief {
  margin: 0.3rem 0;
  padding: 0.3rem 0.45rem;
  background: rgba(0, 0, 0, 0.25);
  border-left: 2px solid #5a4a3a;
  font-size: 0.85rem;
}
.diplomatietafel .brief.von-mir { border-left-color: #a8813d; background: rgba(60, 48, 28, 0.3); }
.diplomatietafel .schreiben textarea {
  flex: 1;
  font: inherit;
  font-size: 0.85rem;
  color: inherit;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid #5a4a3a;
  border-radius: 2px;
  padding: 0.3rem;
  resize: vertical;
}

/* --- Der Aachener Markt in der Handelstafel --------------------------------

   Zeile über allem: was den Handel überhaupt möglich macht. Ohne zugewiesenen
   Bewohner fährt kein Karren — das MUSS oben stehen, sonst sucht der Spieler
   den Fehler bei den Knöpfen.                                              */

.ht-lage {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.4rem;
  align-items: baseline;
  padding: 0.45rem 0.7rem;
  margin-bottom: 0.8rem;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--iron);
  border-radius: 2px;
  font-size: 0.85rem;
  color: var(--text-dim);
}
.ht-lage strong { color: var(--text); }
.ht-lage.warnung { border-color: #7a4a32; }
.ht-warnwort { color: #d8a67e; }

/* Die Karren, die gerade unterwegs sind. */
.ht-fahrten { display: flex; flex-direction: column; gap: 0.3rem; margin-bottom: 0.9rem; }
.ht-fahrt {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.32rem 0.6rem;
  background: rgba(0, 0, 0, 0.22);
  border-left: 2px solid var(--brass-dark);
  font-size: 0.86rem;
}
/* Auf dem Rückweg grünlich — er bringt etwas mit. */
.ht-fahrt.heim { border-left-color: #5f7a4a; }
.ht-fahrt-text { flex: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 0.15rem 0.5rem; }
/* Wer faehrt — vor der Ladung, damit ein Karren einen Mann hat und nicht nur
   einen Inhalt. */
.ht-fahrt-wer {
  color: var(--brass-light);
  font-weight: 600;
  white-space: nowrap;
}
.ht-fahrt-wer::after { content: " ·"; color: var(--text-dim); font-weight: 400; }
/* Zwei Ladungen auf EINEM Karren stehen nebeneinander, nicht untereinander:
   Untereinander sieht wieder nach zwei Fuhren aus — genau der Eindruck, den
   diese Umstellung beseitigt. */
.ht-ladung { display: inline-flex; align-items: center; gap: 0.3rem; }
.ht-restzeit { color: var(--text-dim); white-space: nowrap; font-size: 0.8rem; }

.ht-kurs { color: var(--brass-light); }
.ht-trend { font-size: 0.78rem; white-space: nowrap; }
.ht-trend.hoch { color: #7fa05a; }
.ht-trend.runter { color: #b0563c; }
.ht-trend.gleich { color: var(--iron-light); }

/* --- Händler unterwegs (zweiter Zettel im Stapel, siehe #bedrohungen) ------

   Schmal und still: Ein Karren ist keine Gefahr, er hat nur eine Frist. Die
   Tafel steht unter den Bedrohungen und schiebt die Bauvorhaben kaum weg —
   dafür ist sie klein genug.                                               */

#handelsfuhren {
  top: calc(var(--meldungen-oben) + var(--bedrohungen-hoehe, 0rem));
  bottom: auto;
  right: auto;
  left: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.35rem 0.5rem;
  background: rgba(18, 20, 23, 0.9);
  border: 1px solid var(--iron);
  border-left: 2px solid var(--brass-dark);
  border-radius: 2px;
  font-size: 0.82rem;
}
#handelsfuhren[hidden] { display: none; }
.hf-kopf { color: var(--text-dim); font-size: 0.76rem; margin-bottom: 0.1rem; }
.hf-zeile { display: flex; align-items: center; gap: 0.35rem; }
.hf-was { color: var(--text); min-width: 1.6rem; text-align: right; }
/* Der Pfeil sagt die Richtung: hin zum Markt oder heim mit der Beute. */
.hf-pfeil { color: var(--brass-dark); }
.hf-zeile.heim .hf-pfeil { color: #5f7a4a; }
.hf-rest { color: var(--text-dim); margin-left: auto; white-space: nowrap; }

/* --- Der Regler an der Esse ------------------------------------------------

   Beide Rechnungen stehen nebeneinander, auch die der nicht gewählten
   Betriebsart. Das ist Absicht: Die Wahl soll eine Rechnung sein und kein
   Ratespiel — wer wissen will, ob sich das Umlegen lohnt, darf dafür nicht
   die Tafel schließen müssen.                                              */

.gp-betriebsart { display: flex; flex-direction: column; gap: 0.25rem; }
.gp-art {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "wahl kopf"
    ".    rechnung";
  gap: 0.1rem 0.45rem;
  align-items: baseline;
  padding: 0.3rem 0.5rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
/* Blau ist der Browser-Standard für Radios — im Spiel ist alles Messing/Kupfer,
   also hier dieselbe Farbe wie die Zoom-Regler im Devpanel (accent-color). */
.gp-art input { grid-area: wahl; margin: 0; align-self: center; accent-color: var(--brass); }
.gp-art-kopf { grid-area: kopf; color: var(--text); display: inline-flex; align-items: center; gap: 0.35rem; }
.gp-art-rechnung { grid-area: rechnung; font-size: 0.86rem; }
.gp-art-rechnung strong { color: var(--brass-light); }
.gp-art-aus { color: var(--text-dim); }
.gp-art.aktiv { border-color: var(--brass); background: rgba(109, 84, 38, 0.26); }
.gp-art:hover { border-color: var(--brass-dark); }
.gp-art-leer { margin: 0.2rem 0 0; font-size: 0.8rem; color: #d8a67e; }

/* Das Fragezeichen ersetzt den fest sichtbaren Erklärtext (gp-art-text) —
   dieselbe Idee wie .start-info: knapp halten, die Erläuterung nur bei
   Bedarf. title= reicht hier als Tooltip, der Text ist kurz und einmalig. */
.gp-info {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 0.9rem;
  height: 0.9rem;
  border: 1px solid var(--brass-dark);
  border-radius: 50%;
  font-size: 0.66rem;
  line-height: 1;
  color: var(--brass);
  cursor: help;
  flex: none;
}
.gp-art:hover .gp-info,
.gp-art.aktiv .gp-info {
  border-color: var(--brass);
  color: var(--brass-light);
}

/* --- Der Wechselschirm ------------------------------------------------------
 *
 * Derselbe Schirm wie beim Start (dieselbe faule Uhr, derselbe Balken), aber
 * für den Wechsel zwischen Baumodus und Burgansicht — und nur dann, wenn das
 * Bodenbild wirklich neu gebacken wird (client/src/bodenMaler.ts,
 * muessteBodenBacken). Er teilt sich Fläche, Korn, Ausblende, Titel,
 * Bildrahmen, Balken UND Uhr-Dauer mit #ladeschirm (siehe die gemeinsamen
 * Selektoren oben — dieselben 2 Sekunden, dieselbe Animation `ladeUhr`,
 * keine eigene Regel dafür nötig); hier steht nur, was ihn unterscheidet —
 * eine kürzere Ausblendzeit und der Z-INDEX unten.
 */
#wechselschirm {
  /* Kürzer als beim Start: Dort blendet man in ein Spiel hinein, das man noch
     nicht kennt; hier kehrt man in ein Bild zurück, das man gerade verlassen
     hat. Ein langes Aufblenden fühlte sich an, als hätte man etwas verpasst. */
  transition: opacity 0.3s ease-out;
  /* MUSS über der Blende (.blende, z-index 2000) liegen: main.ts blendet für
     den Wechsel selbst per wechselAnsicht() über dieselbe Blende ab, die auch
     Seitenwechsel benutzt — und die deckt bewusst ALLES ab, auch den
     Ladeschirm (siehe Kommentar dort). Der geerbte Wert 200 lag also unter
     der Blende: Zu sehen war nur ihr eigenes flaches Dunkel, der Wechselschirm
     blieb komplett verdeckt darunter — genau das sah wie ein bloßer grauer
     Bildschirm aus. Da beide dieselbe Farbe tragen, kostet das Anheben
     nichts an Nahtlosigkeit; der Wechselschirm deckt von der ersten
     Sekunde an vollständig ab, noch bevor die Blende ihr eigenes Abblenden
     überhaupt fertig hat. */
  z-index: 2001;
}

/* ===========================================================================
   DIE HANDY-ANSICHT
   ---------------------------------------------------------------------------
   Am Handy und am Tablet wird nicht gespielt, sondern zugesehen: die eigene
   Burg ansehen, die Chronik lesen, abmelden. Mehr nicht — Mauern ziehen und
   Bauplätze setzen braucht Maus und Bildschirm (server/src/server.ts,
   handySchranke sperrt dort dieselbe Regel serverseitig).

   Die Klasse `handy` setzt client/index.html ganz vorn und synchron, noch vor
   dem Ladeschirm. Alles hier hängt daran; am Rechner greift keine dieser
   Regeln.

   Warum abschalten statt umbauen: Kopfband, Bauleiste, Vorratsleiste und die
   Tafeln sind für Zeigergenauigkeit und Bildschirmbreite gebaut. Sie am Daumen
   nachzubilden hieße, eine zweite Oberfläche zu pflegen, die niemand ernsthaft
   benutzen will. Die Burg selbst dagegen ist ein Bild — und ein Bild trägt
   jeden Bildschirm.
   =========================================================================== */

/* Alles, was zum Bedienen da ist, bleibt weg. Über die Sammelklasse .hud statt
   über eine Namensliste: Was in Zukunft als HUD dazukommt, ist damit von
   selbst mit abgeschaltet — eine vergessene ID wäre sonst ein Bedienelement,
   das am Handy ins Leere führt. */
body.handy .hud,
body.handy #kopfleiste-halter,
body.handy #buildbar,
body.handy #chatfenster,
body.handy #diplomatietafel,
body.handy .versionsschild {
  display: none !important;
}

/* Die Leinwand nimmt die Gesten selbst an (main.ts: ein Finger schiebt, zwei
   zoomen). Ohne touch-action legte der Browser sein eigenes Scrollen und
   Doppeltipp-Zoomen darüber, und die Burg ruckelte unter der Geste weg. */
body.handy canvas {
  touch-action: none;
}

/* Kein Auswählen, kein Lupen-Popup, kein blauer Blitz beim Tippen — hier gibt
   es keinen Text zu markieren, nur ein Bild zum Ansehen. */
body.handy {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
  overscroll-behavior: none;
}

/* --- Die zwei Knöpfe ------------------------------------------------------
 *
 * Oben rechts, klein, mit Abstand zur Systemleiste (env(safe-area-inset-*) —
 * quer gehaltene iPhones legen ihre Kerbe an eine der beiden Seiten, und ein
 * Knopf darunter ist nicht zu treffen).
 *
 * z-index bewusst UNTER dem Ladeschirm (200): Solange die Burg noch backt,
 * sollen die Knöpfe nicht schon über dem Ladebalken schweben.
 */
.handyleiste {
  display: none;
}

body.handy .handyleiste {
  display: flex;
  position: fixed;
  z-index: 150;
  top: calc(0.5rem + env(safe-area-inset-top, 0px));
  right: calc(0.6rem + env(safe-area-inset-right, 0px));
  gap: 0.45rem;
  align-items: center;
}

body.handy .handy-abmelden {
  margin: 0;
  display: contents; /* das <form> ist bloß Träger der POST-Aktion, kein Kasten */
}

body.handy .handyknopf {
  font-family: var(--font-body);
  font-size: 0.9rem;
  line-height: 1;
  /* 2.2rem hoch: die übliche Mindestgröße für einen Daumen. Kleiner sähe
     zierlicher aus und ginge im Fahren daneben. */
  padding: 0 0.85rem;
  height: 2.2rem;
  color: var(--text);
  background: linear-gradient(180deg, var(--stone-700), var(--stone-900));
  border: 1px solid var(--iron);
  border-radius: 3px;
  box-shadow: 0 1px 4px rgb(0 0 0 / 55%);
  cursor: pointer;
}

body.handy .handyknopf:active {
  background: linear-gradient(180deg, var(--stone-900), var(--stone-800));
  border-color: var(--brass-dark);
  color: var(--brass-light);
}

/* --- Der Drehhinweis -------------------------------------------------------
 *
 * Nur am Handy und nur hochkant. Über ALLEM (auch über Blende 2000 und
 * Wechselschirm 2001): Solange das Gerät falsch herum liegt, gibt es nichts
 * anderes zu sehen.
 */
.drehhinweis {
  display: none;
}

@media (orientation: portrait) {
  body.handy .drehhinweis {
    display: grid;
    place-items: center;
    position: fixed;
    inset: 0;
    z-index: 3000;
    background: var(--stone-900);
    text-align: center;
    padding: 2rem;
  }
}

.dreh-icon {
  width: 4.5rem;
  height: 4.5rem;
  fill: none;
  stroke: var(--brass);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* Ein langsames Kippen — es zeigt, was zu tun ist, ohne es zu erklären. */
  animation: drehWink 2.6s ease-in-out infinite;
}

@keyframes drehWink {
  0%, 55%, 100% { transform: rotate(0deg); }
  75%, 95% { transform: rotate(-90deg); }
}

@media (prefers-reduced-motion: reduce) {
  .dreh-icon { animation: none; }
}

.dreh-titel {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--brass-light);
  margin: 1.1rem 0 0.4rem;
}

.dreh-text {
  font-family: var(--font-body);
  color: var(--text-dim);
  margin: 0;
  max-width: 22rem;
}

/* --- Die Chronik als Blatt -------------------------------------------------
 *
 * Am Rechner ist die Chronik ein Fenster, das man zieht und in der Größe
 * ändert (chronikfenster.js). Am Daumen ist beides Gefummel — hier legt sie
 * sich formatfüllend über die Burg, und das × oben schließt sie wieder.
 *
 * !important, weil chronikfenster.js Lage und Größe als Inline-Stil setzt;
 * seine Rechnung läuft am Handy ins Leere, aber sie läuft (siehe dort).
 */
body.handy #chronikfenster {
  inset: 0 !important;
  left: 0 !important;
  top: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  width: auto !important;
  height: auto !important;
  max-width: none !important;
  border-radius: 0 !important;
  border-width: 0 !important;
  z-index: 1500 !important;
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  padding-left: env(safe-area-inset-left, 0px);
  padding-right: env(safe-area-inset-right, 0px);
}

/* Die Griffecke zum Größenziehen hat auf einem formatfüllenden Blatt keine
   Bedeutung mehr — und wäre unten rechts genau da, wo man scrollt. */
body.handy #chronikfenster .ct-griffecke {
  display: none;
}

/* Das Schließen-× größer: 2.2rem ist die Fläche, die ein Daumen sicher
   trifft — der zierliche Fensterknopf vom Rechner geht hier daneben. */
body.handy #chronikfenster .ct-klapp {
  width: 2.2rem;
  height: 2.2rem;
  font-size: 1.4rem;
}

/* --- DIE RANGLISTE ---------------------------------------------------------

   Dieselbe Bauform wie die Handelstafel: ein abgedunkelter Vorhang über der
   ganzen Fläche, die Tafel mittig darin. Sie ist aber SCHMALER — eine Liste
   liest sich in einer Spalte, nicht über die volle Breite eines Marktes.

   Der Vorhang ist bewusst kein eigenes Fenster: Wer die Rangliste offen hat,
   spielt gerade nicht, und ein halbdurchsichtiger Kasten mitten im Bild würde
   Zahlen vor Gebäude legen, die man dahinter noch zu lesen versucht. */
#ranglistetafel {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  background: rgba(8, 10, 13, 0.72);
  padding: 2rem 1rem;
}
#ranglistetafel[hidden] { display: none; }
.rl-tafel {
  width: min(560px, 94vw);
  max-height: 86vh;
  overflow-y: auto;
  background: linear-gradient(180deg, rgba(38, 42, 48, 0.99), rgba(22, 25, 29, 0.99));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  padding: 1rem 1.2rem 1.2rem;
}
.rl-kopf {
  display: flex;
  align-items: center;
  /* Kein space-between mehr: Den Abstand macht der auto-Rand am
     Fragezeichen, und der gap gilt dann nur noch zwischen ? und ×. */
  gap: 0.35rem;
}
.rl-kopf h3 { margin: 0; }
.rl-zu {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1.4rem;
  line-height: 1;
  padding: 0 0.2rem;
  cursor: var(--cursor-gold);
}
.rl-zu:hover { color: var(--brass-light); }
/* Das Fragezeichen sitzt RECHTS, unmittelbar links vom Schließkreuz.
   Beide sind Bedienelemente der Tafel und gehören zusammen an ihre Ecke; die
   Überschrift bleibt für sich.

   Es stand kurzzeitig links bei der Überschrift, aus Sorge, ein Knopf neben
   dem Schließen werde versehentlich getroffen. Die Sorge trägt nicht: Das
   Fragezeichen KLAPPT NUR AUF, ein Fehlgriff kostet also einen zweiten Klick
   und nichts weiter.

   Nach rechts geschoben wird das PAAR — margin-left:auto steht deshalb am
   Fragezeichen und nicht mehr am Kreuz. Der schmale gap trennt die beiden
   voneinander; zur Überschrift hält sie der auto-Rand auf Abstand. */
.rl-frage {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
  border-radius: 50%;
  border: 1px solid var(--brass-dark);
  background: none;
  color: var(--text-dim);
  font-size: 0.8rem;
  font-weight: 700;
  line-height: 1;
  padding: 0;
  cursor: var(--cursor-gold);
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.rl-frage:hover,
.rl-frage.offen {
  color: var(--brass-light);
  border-color: var(--brass-light);
  background: rgba(198, 160, 78, 0.12);
}
.rl-kopf .rl-frage { margin-left: auto; }

.rl-erklaertafel {
  margin: 0 0 0.9rem;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.25);
  font-size: 0.85rem;
  color: var(--text-dim);
}
.rl-erklaertafel .rl-formel {
  margin: 0 0 0.6rem;
  color: var(--brass-light);
  letter-spacing: 0.02em;
}
.rl-erklaertafel ul {
  margin: 0;
  padding-left: 1.1rem;
  display: grid;
  gap: 0.4rem;
}
.rl-erklaertafel li b { color: var(--text); }

.rl-liste {
  list-style: none;
  margin: 0;
  padding: 0;
}
.rl-zeile {
  display: grid;
  /* Rang | Bildnis | Wappen | Namen | Punkte.
     Die vier äußeren Spalten haben FESTE Breiten, auch wenn ein Bild fehlt —
     nur so stehen die Namen aller Zeilen untereinander. Die Mittelspalte nimmt
     den Rest: Sie trägt den längsten und den unwichtigsten Text zugleich. */
  grid-template-columns: 2.1rem 51px 39px 1fr auto auto;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.35rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
/* Das Bildnis: rechteckig wie ein gerahmtes Porträt, nicht rund. Ein Kreis
   wäre die Form der Benutzerbilder heutiger Netzdienste und schnitte ausgerechnet
   das ab, was die Bildnisse tragen — Hut, Haube, Schulterpartie. */
.rl-bildnis {
  width: 51px;
  height: 63px;
  border: 1px solid var(--brass-dark);
  background: rgba(0, 0, 0, 0.35);
  overflow: hidden;
  display: block;
}
.rl-bildnis img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Die Bildnisse sind gemalte Pixelbilder — nicht weichzeichnen. */
  image-rendering: pixelated;
  display: block;
}
/* Das Wappen daneben, ohne Rahmen: Es HAT schon eine Form, und ein Kasten um
   einen Schild herum ergäbe zwei Umrisse, die um Aufmerksamkeit streiten. */
.rl-wappen {
  width: 39px;
  height: 45px;
  display: block;
}
.rl-wappen img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
  display: block;
}
.rl-zeile:last-child { border-bottom: none; }
/* Die eigene Burg hebt sich ab — sonst sucht man sich in einer Liste aus
   fremden Namen jedes Mal selbst.

   Der Messingstrich am Rand ist ein INNENSCHATTEN und kein border-left, und
   das Padding bleibt das der anderen Zeilen. Vorher war es umgekehrt: 2 px
   Rand plus ein von 0,35 auf 0,5 rem erhoehtes Padding-links. Beides zusammen
   schob den ganzen Inhalt dieser einen Zeile um 4,86 px nach rechts — Rang,
   Bildnis, Wappen und Name standen gegen alle anderen versetzt, und weil die
   eigene Burg meist oben steht, sah es aus, als sitze ausgerechnet Platz 1
   schief. Ein Rand ist Layout, eine Hervorhebung soll keines sein.

   Dieselbe Loesung wie in der Rangliste ueber den Wolken (karte.css,
   .rangliste li.meins) — dort stand sie von Anfang an richtig. */
.rl-zeile.meins {
  background: rgba(168, 129, 61, 0.12);
  box-shadow: inset 2px 0 0 var(--brass);
}
.rl-rang {
  text-align: center;
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.rl-rang.oben { color: var(--brass-light); font-weight: 600; }
.rl-namen { display: flex; flex-direction: column; gap: 0.05rem; min-width: 0; }
.rl-burg { font-weight: 600; }
.rl-spieler { font-size: 0.85rem; color: var(--text-dim); }
/* Die Aufschlüsselung: klein und einzeilig. Sie beantwortet die Rückfrage
   "warum steht der vor mir", ohne die Liste zu einer Tabelle zu machen. */
.rl-werte {
  font-size: 0.78rem;
  color: var(--text-dim);
  opacity: 0.75;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rl-punkte {
  font-variant-numeric: tabular-nums;
  font-size: 1.05rem;
  color: var(--brass-light);
}
/* Das Burgzeichen ganz rechts: der Weg zur Burg dieses Spielers.
   Zurueckhaltend, solange man es nicht sucht — es steht in JEDER Zeile, und
   zwoelf leuchtende Tuerme neben zwoelf Namen waeren ein Zaun statt einer
   Liste. Erst beim Ueberfahren nimmt es Messingfarbe an. */
.rl-burgzeichen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--iron);
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.3);
  color: var(--text-dim);
  cursor: var(--cursor-gold);
  transition: color 0.1s, border-color 0.1s, background 0.1s;
}
.rl-burgzeichen svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.rl-burgzeichen:hover,
.rl-burgzeichen:focus-visible {
  color: var(--brass-light);
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.18);
}
.rl-fuss { margin: 0.9rem 0 0; font-size: 0.88rem; }

/* --- DIE BAUWARTELISTE -----------------------------------------------------

   Sitzt im selben Kasten wie die laufenden Baustellen (#queue), darunter und
   durch eine Überschrift abgesetzt: Oben, was schon gebaut wird; darunter,
   was noch auf Vorräte wartet. Beides beantwortet dieselbe Frage, deshalb
   steht es beieinander. */
.wartekopf {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  margin-top: 0.35rem;
  padding-top: 0.45rem;
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--text-dim);
  font-size: 0.82rem;
  letter-spacing: 0.02em;
}
.wartekopf-glas {
  width: 15px;
  height: 15px;
  flex: none;
  image-rendering: pixelated;
}
/* Wartende Einträge sind blasser als laufende Baustellen — sie tun gerade
   nichts, und der Blick soll zuerst auf dem hängenbleiben, was läuft. */
.queueitem.wartet {
  opacity: 0.82;
  display: flex;
  align-items: center;
  gap: 0.35rem;
}
.queueitem.wartet .wartegrund {
  color: var(--text-dim);
  font-size: 0.78rem;
  opacity: 0.85;
  margin-left: 0.15rem;
}
/* Das Kreuz zum Herausnehmen: ganz rechts, unauffällig bis man hinzeigt.
   Eine Warteliste, aus der man nicht wieder herauskommt, wäre eine Falle. */
.warte-weg {
  margin-left: auto;
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: 1rem;
  line-height: 1;
  padding: 0 0.15rem;
  opacity: 0.5;
  cursor: var(--cursor-gold);
}
.warte-weg:hover { opacity: 1; color: var(--brass-light); }

/* Die Lücke in der Leibgarde — Zustand links, Handlung rechts, wie in der
   Rüstkammer darüber. Dieselbe Form für dieselbe Sorte Entscheidung. */
.wt-gardeluecke {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  padding: 0.55rem 0.6rem;
  background: rgba(192, 80, 58, 0.08);
  border: 1px solid rgba(192, 80, 58, 0.35);
  border-radius: 3px;
}
.wt-gardeluecke strong { display: block; }
.wt-gardeluecke small {
  display: block;
  color: var(--text-dim);
  font-size: 0.8rem;
  margin-top: 0.15rem;
}
/* ===========================================================================
   UNGELESENE POST — eine ruhig pulsierende Messingaura.

   EINE Definition fuer zwei Orte: das Briefzeichen im Kopfband
   (#botenstubeknopf, gesetzt von chat.js → meldeAmKopfband) und die Reiter
   der Faeden im Botenstuben-Fenster (.ct-faden, gesetzt beim Zeichnen).
   Beide beantworten dieselbe Frage — "hier liegt etwas" —, und zwei
   verschieden pulsierende Goldtoene fuer dieselbe Antwort waeren Unruhe.

   LANGSAM UND SCHWACH, das ist der Punkt: 2,4 Sekunden je Atemzug und ein
   Schein, der nicht ganz verschwindet. Ein schnelles, kraeftiges Blinken
   liest sich als Alarm; hier ist nur ein Brief angekommen. Wer gerade baut,
   soll es aus dem Augenwinkel bemerken und nicht erschrecken.
   =========================================================================== */
@keyframes post-aura {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(204, 167, 94, 0);
    border-color: var(--brass-dark);
  }
  50% {
    box-shadow: 0 0 7px 1px rgba(204, 167, 94, 0.45);
    border-color: var(--brass-light);
  }
}
/* Das Zeichen selbst atmet mit — ohne das leuchtet nur der Rahmen, und der
   Brief bliebe stumpf in einem hellen Kasten. */
@keyframes post-schein {
  0%,
  100% {
    filter: none;
  }
  50% {
    filter: drop-shadow(0 0 3px rgba(204, 167, 94, 0.75)) brightness(1.15);
  }
}

/* Der RAHMEN atmet — bei beiden. */
.kopfknopf.hat-post,
.ct-faden.hat-post {
  animation: post-aura 2.4s ease-in-out infinite;
}
/* Das ZEICHEN atmet mit — nur der Brief hat eines. Der Reiter traegt bloss
   Text, bei ihm genuegt die Aura. Beide Atemzuege sind gleich lang und
   starten zusammen, sonst flackerte es gegeneinander. */
.kopfknopf.hat-post .brieficon {
  animation: post-schein 2.4s ease-in-out infinite;
}

/* Wer den offenen Faden ansieht, hat ihn gelesen — er soll nicht mitleuchten.
   Die Klasse kommt hier gar nicht erst dran (chat.js setzt sie nur bei
   ungelesen > 0), diese Regel ist die Sicherung fuer den Moment ZWISCHEN
   Klick und naechstem Zeichnen. */
.ct-faden.aktiv.hat-post {
  animation: none;
  border-color: var(--brass);
}

@media (prefers-reduced-motion: reduce) {
  /* Kein Pulsieren, aber die Auskunft bleibt: ein stehender Schein. */
  .kopfknopf.hat-post,
  .ct-faden.hat-post {
    animation: none;
    border-color: var(--brass-light);
    box-shadow: 0 0 6px 1px rgba(204, 167, 94, 0.4);
  }
  .kopfknopf.hat-post .brieficon {
    animation: none;
    filter: drop-shadow(0 0 3px rgba(204, 167, 94, 0.7)) brightness(1.12);
  }
}
/* ===========================================================================
   DER WAPPENWAEHLER in der Standestafel.

   Anders als beim Bildnis waehlt man hier keine fertige Sache aus einer Wand,
   sondern STELLT ZUSAMMEN: Schildfarbe, Zeichen, Zeichenfarbe — ueber 3800
   Kombinationen. Deshalb oben die Vorschau mit den beiden Farbreihen daneben
   und darunter das Gitter der Zeichen: Man sieht beim Suchen, was entsteht.

   Die Vorschau kommt vom Server (/wappen/vorschau.png), nicht aus dem
   Browser — sonst gaebe es zwei Zeichnungen desselben Wappens.
   =========================================================================== */
.sp-wappenbau {
  display: flex;
  align-items: center;
  gap: 1.1rem;
  margin-bottom: 0.8rem;
}
.sp-wappenvorschau {
  flex: none;
  width: 84px;
  height: 84px;
  image-rendering: auto;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.6));
}
.sp-wappenteile {
  display: grid;
  gap: 0.5rem;
  font-size: 0.82rem;
  color: var(--text-dim);
}
.sp-wappenteile label {
  display: grid;
  gap: 0.25rem;
}
.sp-tinkturen {
  display: flex;
  gap: 0.3rem;
}
/* Eine Farbe ist ein Farbfleck, kein Wort: Sieben Namen nebeneinander liest
   niemand, sieben Flecken erfasst man in einem Blick. Der Name steht im
   title fuer alle, die ihn brauchen. */
.sp-tinktur {
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 50%;
  background: var(--tinktur, #888);
  cursor: var(--cursor-gold);
  transition: border-color 0.12s, transform 0.12s;
}
.sp-tinktur:hover { transform: scale(1.12); }
.sp-tinktur.gewaehlt {
  border-color: var(--brass-light);
  transform: scale(1.12);
}

/* Das Zeichengitter ist hoeher als die Bildniswand: 78 Zeichen, und man
   sucht darin. Eine feste Hoehe mit eigenem Bildlauf haelt Vorschau und
   Speichern-Knopf sichtbar, statt sie aus der Tafel zu schieben. */
.sp-wappengitter {
  max-height: 15rem;
  overflow-y: auto;
}
.sp-wappenkachel {
  padding: 0.2rem;
  border: 1px solid transparent;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.25);
  cursor: var(--cursor-gold);
}
.sp-wappenkachel img {
  display: block;
  width: 28px;
  height: 28px;
  /* Die Zeichen liegen als helle Silhouetten vor; hier stehen sie auf dunklem
     Grund und wuerden sonst verschwinden. */
  filter: brightness(0) invert(1) opacity(0.75);
}
.sp-wappenkachel:hover img { filter: brightness(0) invert(1) opacity(1); }
.sp-wappenkachel.gewaehlt {
  border-color: var(--brass-light);
  background: rgba(168, 129, 61, 0.28);
}
.sp-wappenkachel.gewaehlt img { filter: brightness(0) invert(1) opacity(1); }

.sp-wappenfuss {
  display: flex;
  justify-content: flex-end;
  margin-top: 0.7rem;
}

/* ===========================================================================
   VON VORN BEGINNEN — die Rueckfrage an Ort und Stelle.

   Bestaetigt wird durch ABTIPPEN DES BURGNAMENS. Ein "Ja, wirklich" klickt
   man weg, ohne es gelesen zu haben; einen Namen tippt man nur ab, wenn man
   hingesehen hat — und man sieht dabei genau das, was gleich verschwindet.
   =========================================================================== */
.sp-neuanfang {
  border-color: var(--blood, #8f2f28);
}
.sp-neuanfang .sp-warnung {
  color: var(--blood, #8f2f28);
  font-weight: 600;
}
.sp-neuanfang-text {
  margin: 0.3rem 0 0.7rem;
  font-size: 0.85rem;
  color: var(--text-dim);
}
.sp-neuanfang-text strong { color: var(--text); }
.sp-neuanfang-zeile {
  display: flex;
  gap: 0.5rem;
  align-items: center;
}
.sp-neuanfang-feld {
  flex: 1 1 auto;
  min-width: 0;
}
.sp-neuanfang-tat {
  flex: none;
  border-color: var(--blood, #8f2f28);
  color: var(--blood, #8f2f28);
}
.sp-neuanfang-tat:disabled {
  opacity: 0.45;
  cursor: default;
}
.sp-neuanfang-tat:not(:disabled):hover {
  background: rgba(143, 47, 40, 0.2);
}

/* --- DIE HANDELSMEISTER ----------------------------------------------------

   Vier Gestalten statt einer Zahl. "3 von 4 Karren frei" beantwortet nicht,
   WEN man schickt — und genau das ist seit dem Umbau die Entscheidung. */
/* KLEINER als beim ersten Wurf (22.08.2026, Ansage des Bauherrn): Vier
   Kacheln zu je 140 px nahmen mehr Platz ein als die Kurstafel darunter,
   obwohl sie nur einen Namen und ein Wort tragen. Jetzt reihen sie sich, statt
   ein Raster zu fuellen — sie werden so breit, wie der Name es braucht, und
   umbrechen erst, wenn die Zeile voll ist. */
.ht-meisterreihe {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 0.6rem;
}
.ht-meister {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  padding: 0.25rem 0.5rem;
  line-height: 1.25;
  text-align: left;
  background: linear-gradient(180deg, rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.4));
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  color: var(--text-dim);
  cursor: var(--cursor-gold);
}
.ht-meister:hover:not(:disabled) { border-color: var(--brass); }
.ht-meister-name { color: var(--text); font-weight: 600; font-size: 0.88rem; }
.ht-meister small { font-size: 0.7rem; opacity: 0.85; }
/* Der Gewählte: Messingkante und heller Grund — dieselbe Sprache wie beim
   ausgewählten Gebäude im Bauplan. */
.ht-meister.gewaehlt {
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.16);
}
.ht-meister.gewaehlt .ht-meister-name { color: var(--brass-light); }
/* Unterwegs: sichtbar, aber nicht wählbar. Ihn auszublenden wäre bequemer und
   falsch — dass Meinhard erst morgen kann, ist die gesuchte Auskunft. */
.ht-meister.fort { opacity: 0.5; cursor: default; }

/* ===========================================================================
   DAS UHRWERK — das Tick-Fenster auf Taste T (client/src/tickTafel.ts).

   Klein, unten links, ueber allem. Es ist ein NACHSCHLAGE-Fenster: Wer es
   nicht ruft, sieht es nie. Genau darum steht der Takt nicht mehr im
   Kopfband — dort hat er die Spieler nur irritiert.
   =========================================================================== */
.tt-fenster {
  position: fixed;
  left: 1rem;
  bottom: 3.5rem;
  z-index: 60;
  width: 19rem;
  max-width: calc(100vw - 2rem);
  background: linear-gradient(180deg, rgba(24, 20, 16, 0.97), rgba(16, 13, 10, 0.97));
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.6);
  color: var(--text-dim);
  font-size: 0.85rem;
}
.tt-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.4rem 0.5rem 0.4rem 0.7rem;
  border-bottom: 1px solid var(--brass-dark);
  color: var(--brass-light);
  font-weight: 600;
  letter-spacing: 0.04em;
}
.tt-zu {
  padding: 0 0.35rem;
  border: none;
  background: none;
  color: var(--text-dim);
  font-size: 1.1rem;
  line-height: 1;
  cursor: var(--cursor-gold);
}
.tt-zu:hover { color: var(--text); }
.tt-leib { padding: 0.6rem 0.7rem 0.7rem; }
/* Zwei Spalten, damit die Zahlen untereinander stehen und sich vergleichen
   lassen — eine Liste aus Saetzen laese man nicht. */
.tt-liste {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem 0.7rem;
  margin: 0;
}
.tt-liste dt { color: var(--text-dim); opacity: 0.8; }
.tt-liste dd { margin: 0; color: var(--text); text-align: right; }
.tt-wort {
  margin: 0.7rem 0 0;
  padding-top: 0.6rem;
  border-top: 1px solid rgba(168, 129, 61, 0.25);
  font-size: 0.78rem;
  line-height: 1.45;
}
.tt-wort strong { color: var(--text); }

/* ===========================================================================
   DIE REITER DER CHRONIK (23.08.2026).

   Vorher stand alles untereinander, und weil die Liste gedeckelt war,
   verdraengten Fuhren und Zuzuege alles andere — man scrollte an dreissig
   "Ein Fremder hat um Aufnahme gebeten" vorbei, um zu sehen, was gebaut wurde.
   =========================================================================== */
.kf-reiter {
  display: flex;
  flex-wrap: wrap;
  gap: 0.2rem;
  margin: 0.2rem 0 0.6rem;
  border-bottom: 1px solid var(--brass-dark);
}
.kf-reiterknopf {
  padding: 0.28rem 0.7rem;
  background: none;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: 3px 3px 0 0;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.88rem;
  cursor: var(--cursor-gold);
  /* Der gewaehlte Reiter sitzt AUF der Linie: 1px nach unten, damit seine
     Unterkante die Trennlinie ueberdeckt. Ohne das schwebt er darueber. */
  margin-bottom: -1px;
}
.kf-reiterknopf:hover { color: var(--text); }
.kf-reiterknopf.offen {
  border-color: var(--brass-dark);
  border-bottom-color: var(--stone-900, #14110d);
  background: rgba(168, 129, 61, 0.12);
  color: var(--brass-light);
}

/* Ein entschiedenes Ereignis: Titel, getroffene Wahl, Folge, Zahlen. */
.kf-ereignis-titel { color: var(--brass-light); font-weight: 600; }
.kf-ereignis-wahl { color: var(--text-dim); font-size: 0.86rem; font-style: italic; }
.kf-ereignis-text { margin-top: 0.2rem; }
.kf-folgen { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-top: 0.35rem; }
/* Dieselbe Farbsprache wie das Auflösungsfenster und die Meldungen:
   Gewinn gruen, Verlust rot. Wer sie einmal gelernt hat, liest sie ueberall. */
.kf-folge {
  padding: 0.05rem 0.4rem;
  border-radius: 2px;
  background: rgba(0, 0, 0, 0.3);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
.kf-folge.gut { color: #a9c795; }
/* HERGELEITET, nicht gemessen: alles, was vor Migration 0057 entschieden
   wurde, hat seine echten Zahlen nicht mitgeschrieben. Die Vorlage sagt,
   was vorgesehen WAR — gekappt wurde dort nichts, und anteilige Wirkungen
   fehlen ganz. Blasser und mit Wort dahinter, damit niemand sie fuer
   Tatsachen haelt. */
.kf-folgen.erwartet .kf-folge { opacity: 0.62; }
.kf-folge-hinweis {
  align-self: center;
  color: var(--text-dim);
  font-size: 0.74rem;
  font-style: italic;
}
.kf-folge.schlecht { color: #d98b7f; }
