/* Die Scrollleiste aus Messing, für das ganze Projekt (scrollleiste.css, 25.09.2026).
   @import muss vor jeder Regel stehen — darum hier ganz oben. */
@import url("scrollleiste.css");

/* ===========================================================================
   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;
  /* Aufgehellte Fassungen von --moss und --blood, FUER SCHRIFT auf dunklem
     Grund (die Vorratsmeldung). Die satten Toene sind Flaechenfarben und
     verschwinden als 15-px-Ziffer vor der Landschaft. */
  --moss-light: #a6e06a;
  --blood-light: #f0745a;
  --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 ------------------------------------------------------
     Seit dem 26.09.2026 gibt es NUR NOCH die gewuerfelten Zeiger (Ansage des
     Bro: „bitte nur die neuen cursor benutzen alle alten cursor wie mit feder
     etc löschen"): Speerspitze, goldene Speerspitze, Lederhandschuh offen und
     zu, Axt, Hammer. Sie stehen in /static/zeiger.css (erzeugt aus
     config/icons.json, aufbereitet mit scripts/zeiger-aus-wurf.mjs), das NACH
     dieser Datei geladen wird und die Variablen ueberschreibt.

     Was hier steht, ist nur der RUECKFALL fuer eine Seite ohne zeiger.css:
     der passende Zeiger des Systems. Die gezeichneten SVG-Pfeile (Kupfer,
     Gold, Kelle, Hammer, Feder) sind geloescht. Wer irgendwo einen Zeiger
     setzt, nimmt eine dieser Variablen und nie `pointer`, `default`,
     `grab` & Co. — ausgenommen der Textstrich (`text`) in Eingabefeldern und
     die Groessenpfeile an Fensterraendern. */
  --cursor-kupfer: default;
  --cursor-gold: pointer;
  --cursor-bauen: crosshair;
  --cursor-abriss: crosshair;
  --cursor-hand: grab;
  --cursor-hand-zu: grabbing;

  /* DIE BÜSTE EINES BAUERN — das Zeichen der Bauleute (11.09.2026).
     Ein Strohhut, ein Kopf, zwei Schultern; benutzt wird sie als MASKE
     (.bauleute-zeichen, .gp-bauleute), damit sie die Farbe ihrer Zeile
     annimmt. Hier oben wie die Zeiger, weil sie an zwei Stellen hängt und
     die Adresse lang ist. */
  --bauer-bueste: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7.1 9.4C7.1 4.8 9.3 2.5 12 2.5s4.9 2.3 4.9 6.9z'/%3E%3Cellipse cx='12' cy='9.5' rx='8.9' ry='1.8'/%3E%3Cpath d='M8.6 9.5h6.8v2.3a3.4 3.4 0 0 1-6.8 0z'/%3E%3Cpath d='M10.4 12.8h3.2v3.2h-3.2z'/%3E%3Cpath d='M12 14.9c4.4 0 7.9 2.5 8.5 6.5l.3 2H3.2l.3-2c.6-4 4.1-6.5 8.5-6.5z'/%3E%3C/svg%3E");
  /* DER OCHSENKOPF (14.10.2026) — das Zeichen der Ochsen an der Baustelle,
     eine Maske wie die Bauernbüste (.ochsen-zeichen). Wurf 3 von
     `baustelle-ochse` (config/icons.json), der dunkle Rand weggeschnitten —
     Ansage des Bro: „mach daraus ein monchromes symbol". Maske:
     assets/icons-roh/baustelle/ochse-maske-64.png. */
  --ochsen-kopf: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAHfklEQVR42u2ba2wUVRTHfzNbRFtAqFjeFNQoSkQMKiASjIpEEYwSDUYFTHyCiZroJ40PoolRMMFoQoIPPuEjGt9BJQgGg0qRqCAokYeAvEEFC23ZnfXD/m96M8x2Z3Zmdwv2JpNtd/beOefcc/7ndQc6Rseo9HB0dYxKjFQ7oKEPcArQ1B41oRzq+QbweqXMwS1wP6vLKeGz9wAzgPv1rDB0lWXnAa4Dpvu+i7pGkEa5lvldCbQAjcCDFvNuJU3CEPECsAnoHkE9HR8Tbh5mzO86A/O1+83A28BlBQRZNgE8LcLutkDTCbnrQb/rBAwAhln3HaAXsNwyue3ANKCq0hrwEOABW4GxAWps766Z00OC+wh4DrgVuAt4DVgijdoHLAAGWs8crntGCBngJXmIioHjBNlnFvgROLvAvIHAZxYTha51wgAzJgK7xLwHHAOuFvNVPqEHXZGFVEjF1gFbxPhF2tWtInK7CEzpu23A88BoEZ+1NCNrIbw9WoArNKcO6AZ8D9wIpEXfKGCp/o+yeV4cAXgi/k/gLeApETBUl3/M12/O0e6lfK40SIXTwBFgpoIhBIKbLUayMoE+wBT9/atlii0ym5TwZb3FuHlmPuGHDoL6AMushY7pwc1iYhkwR/fSEdQ/67P3jOabT7PWbRYY27/NiI7twE5p5UK57REhXHIkX14PvAf8E0D8bEVznoiKwvQBi+mMZTrmWgScCayOKOB9wDxgpNxsrFzAAf4GPgA+V+TWKBXdDHwjsOwXUdrNwF6g1gIwR2axVuHxImnABDFWyA0bVa8R87cIRHcIy2Jrgo0ddULw7/Rgrwi1zwpnFgKLJcwpQDVwKvAw8K7Adz1wKOTafm1crPWO4yVsoGEDmSNVTAGPS9JeEfG7axGUkon1kl3XApOA6+V9aiMGRYZOA4jjgDHyJk6xoOjHhK99Oxn3ysiNPqGYIxsAvP45jTKlMJo2O26iZZgfYIWtSTDvWQB4wLfm78A9wO3AXOCgvm+ynu+FFMD7QSYdVa2y2v2RVqxQaHi+hzpt1Bxq9bkf2Cj07w7cCQwCuloCi7qbdQLHxmIwwB7b5QnqQwohCpFmvV3yBtMkAP+oLoLu/spTGm0cKEYAXgTQ9ICPgQ2SfjdgsnY6qNBihDUEuDCgKOPEMN3uCup2xE2QBst1tYUBxi5fteZfC6yS/eaz22Zgd4ANezExxnxO9GtlMYg4HeitRd02dn+LEqQpCpIuBy5VZObkCWAagRVyr8slkCQrQ52iZoO2oDyp76NWotKWyu0GZgF9pXa9rTlOnjk9gEuEARuAL3Wvi74fJSCMUqd0rDjlfODDYlV/mHY1bNQX10WmlfmZSHBnjDXNvGf8ml8V0vXVqLozKELU5xYJYlmrFjFA8XxSw4vqoowAHgNukCTdIlA4qh07SrNXi+h0nPC1LX6rQtj9JNl9tkz1eqMt/RRvuAlWh+v9muAWYL5GzNeUsEGSb5yudDnJ0vi2MG7QMN8JeFE1O6+M3RrHKrB2SUAARnPTSt0LmoAH9ATuBR7wARNlMgFTMPlJmWCnGBpo5m3WenkFYABvKPCKih1eAICVwxRMPlAXk3l7rJErLRjOv5nHj3sJ5v6FrkPAJxJCNqFQ+L4gs3cD/t5nTQpyZ+uVt5dS9ZeqStQ75u6buX8BDWFT1d98rS5D2AHgHdXpDpUAG4wJLpH7G5fA+mb+zwqtj6M5SAArpQWOL99/VpWZi4XQSWKBIWov8Kli9uoEXeAPwNGgemCQFzisYoRfjaaSa2FNlnpmC6hdMaNBRdAxCQnYJG0NPi1rM0wcpOwtLReUSRj8vDygdhT4itYOsUf8Iqspu58bJvR3rAjs2xBtLC/AQzQB/0bI9o5Y/++XwLMJVpmzKrfnbQClAoTQpDS0Sq5ohTTimEpanX2NR7tfsEz+dqiFH46vG/SH0uo12vW+Vp3PLQG2zNWzAmsYhR40WqWsnSqG9lBRYoTqA12tSs4mZY2TVQjxFzodoftagWhPaVspjuqZAG6jArpdVogfSgBVUqGbpUKoJr9JqrqBXL9whu7NU6KxXPl7CrhG5TB/Ll6OnMIIYIFC+sjdIMdqWc1U8OPvzOyRuewE7lDxwmauO3ATrR2kUlWO8gFt2toAN8pRtnxNhSHkzvFcoOs8acIcBS/NvogxYzU7rgLGCxv6i8iDwFl56v5xhjmg8YueuzepfiC+xoSdrtLGMTh71GjeQNn/WAkvk4Dbs7XpMLmmSmK1BKeNg0huzJJYV+CLBMzBCLCF3NmCwaU8Z+gUWa93fIchqqxeQ5zgx8w7ADwi73UGnDjvCtSSOx1WjBZkrMBqaoyeJ5U+lPlkEQLwrDkvW0donBNNAA65vl1LBFNIW4nOrITqhxXVgHqFyYW0wK5MraW1i8yJ/t6QqxK8OSfoFQiaFtN6qtw90d87MsSfRu4onjkX5AW0yI29V7eXlyuSFsJwyyP4rwZyx2VSJxvzfjwYLSEcFeMrFSvUJv0ihdNOheCRO6E+XqnsKn1S4PT5ST3c/9sLlnZK3vFmacfoGKUZ/wFIys+yNm+Z4AAAAABJRU5ErkJggg==");
}

/* --- 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;
}
/* Die Titelmarke als Kopf (render.ts, seit 26.09.2026) — hier nur die Größe,
   das Aussehen steht in client/public/3d/titelmarke.css. */
.crest--titelmarke { --titelmarke-groesse: clamp(2rem, 5vw, 3.2rem); }
.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: text;
}

/* 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: text;
}
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);
}
/* DAS FELD BLEIBT DUNKEL, AUCH WENN DER BROWSER ES FÜLLT (26.09.2026, Ansage
   des Bro: „wenn man auf text feld drückt, dass der text feld dunkel bleibt“).
   Unser Stil ändert den Grund beim Anklicken nicht — hell macht ihn das
   AUTOFILL des Browsers (Firefox gelb, Chrome blau, Safari gelb), sobald er
   einen gespeicherten Namen oder ein Losungswort einsetzt. Die Farbe setzen
   die Browser mit !important; überdecken lässt sie sich nur mit einem
   deckenden inneren Schatten, und die Schrift mit -webkit-text-fill-color. */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
input:autofill {
  -webkit-text-fill-color: #f4e8cf;
  caret-color: #f4e8cf;
  box-shadow:
    inset 0 0 0 100px #111316,
    inset 0 2px 5px rgba(0, 0, 0, 0.55);
  filter: none;
  transition: background-color 99999s ease-out 0s;
}
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/datumstafel.ts). */
#topbar .season.datum-erklaert {
  position: relative;
  cursor: var(--cursor-gold);
}
/* 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;
}
/* DIE TAGESZEIT-ANZEIGE (30.08.2026, client/src/tageszeitAnzeige.ts) —
   Geschwister des Datums im selben .kalenderplatz. Gedaempfter als das
   Datum, sonst laesen sich zwei gleich helle Zeitangaben nebeneinander als
   ein einziger, zu langer Text statt als zwei getrennte Angaben. */
#topbar .tageszeit {
  font-size: 0.95rem;
  color: #9a8b6d;
  letter-spacing: 0.02em;
}
#topbar .tageszeit::before {
  content: "· ";
  color: var(--brass-dark, #6b5a35);
}
/* Bis zur ersten Meldung (siehe tageszeitAnzeige.ts) bleibt die Spanne leer
   — dieselbe Regel wie beim Datum, aus demselben Grund: sonst risse eine
   leere Spanne trotzdem eine Luecke in den Flex-Abstand der Reihe. */
#topbar .tageszeit:empty {
  display: none;
}
/* DAS WETTER UND DIE TEMPERATUR (30.09.2026, client/src/iso3d/klima.ts) —
   „bewölkt, frisch", gleich hinter der Tageszeit und genauso gedaempft. Der
   Tooltip sagt, wie es um das Eis steht. Nur die Burgansicht fuellt die
   Spanne; wo sie leer bleibt, reisst sie keine Luecke. */
#topbar .wetterwort {
  font-size: 0.95rem;
  color: #9a8b6d;
  letter-spacing: 0.02em;
  cursor: var(--cursor-kupfer, default);
}
#topbar .wetterwort::before {
  content: "· ";
  color: var(--brass-dark, #6b5a35);
}
#topbar .wetterwort:empty {
  display: none;
}
/* Auf schmalen Schirmen fällt erst das Wetter, dann die Tageszeit weg,
   statt dass das Band zweizeilig wird (kopfleiste.js, bandEinzeilig). Der
   Kalenderplatz schrumpft dafür nicht und bricht nie in sich um — sonst
   stellte er Datum und Tageszeit übereinander, ohne dass das Band als
   umgebrochen gälte. Nur die drei Angaben, nicht der Platz: an ihm hängt
   auch die Zeitrechnungs-Tafel, und die soll umbrechen. */
#topbar .kalenderplatz {
  flex-shrink: 0;
}
#topbar .kalenderplatz > .season,
#topbar .kalenderplatz > .tageszeit,
#topbar .kalenderplatz > .wetterwort {
  white-space: nowrap;
}
#topbar.ohne-wetter .wetterwort,
#topbar.ohne-zeit .tageszeit {
  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.

   Das Bildnis gehört seit dem 27.09.2026 NICHT mehr dazu: Es hängt unter dem
   Band (.bildnisecke) und bestimmt die Höhe der Reihe nicht. */
#topbar .links .kopfknopf,
#topbar .links .res {
  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;
}
/* DIE KACHELN ALS EIN BLOCK (19.10.2026, Ansage des Bro: „die buttons müssen
   nebeneinander richtig stehen manchmal ist der button reihen folge nach oben
   weiter links"). Wurde es eng, drückte der Browser die Knöpfe ungleich
   zusammen (das Zahnrad steckt in .einstellmenue und schrumpfte anders), und
   die Reihe begann weiter links. Jetzt schrumpft nichts: Passt die Reihe
   nicht hinter die Werte, rückt sie als Ganzes in die nächste Zeile,
   rechtsbündig — die Kacheln stehen immer im selben Raster am rechten Rand,
   und der Meldestapel darunter folgt ihnen (meldestapel.ts). */
#topbar .links {
  flex-wrap: wrap;
  justify-content: flex-end;
  row-gap: 0.4rem;
  max-width: 100%;
}
#topbar .links > * { flex-shrink: 0; }
#topbar .links .zeichenreihe {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-shrink: 0;
}
#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: auto;
}
#topbar .kopfzoom .kopfknopf.zoomknopf:disabled {
  opacity: 0.4;
  cursor: var(--cursor-kupfer);
}

#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);
}

/* --- DAS BILDNIS IN DER ECKE (27.09.2026) ------------------------------------
   Ansage des Bro: „die charakter tafel machen wir anders es gibt immer das
   protrait ist eingeblendet und angeschnitten unten links an dem portrait der
   wappen", am selben Abend umgestellt: „spiegeln auf die andere seite soll
   doch lieber obenlinks stehen. bildnis größer und mehr auf das gesicht
   reingezoomt und über dem bildniss den level balken der sich auffüllt aber
   so subtil machen." Den Balken dann doch darunter: „der geht kurz bis zum
   schild." Bis dahin stand ganz rechts in der Reihe das Wappen als
   Knopf; dort steht jetzt der Vollbildknopf.

   Es haengt UNTER dem Band in der linken Ecke, als Kind des Bandes
   (`top: 100%`) — so folgt es ihm, wenn es umbricht oder beim Laden rutscht,
   ohne dass jemand die Unterkante messen muesste. Das Wappen ragt rechts unten
   ueber den Rand: angeschnitten, nicht daneben. Alle Masse stehen seit dem
   Nachtrag „könntest du es 20 kleiner machen alles zusammen" bei vier
   Fuenfteln der ersten Fassung (Rahmen 7 → 5,6rem).

   WAS OBEN LINKS DARUNTER STEHT, RUECKT UM `--bildnis-platz` NACH UNTEN — der
   Meldestapel und die Gebaeudetafel (3d.html). Die Zahl ist die Hoehe des
   ganzen Blocks samt Balken, Abstand und ueberstehendem Schild; wer eines der
   Masse unten aendert, zieht sie nach.

   Ein Klick oeffnet die Standestafel (Taste I). Die allgemeine Knopfregel
   (button) gaebe ihm Platte, Rand und Polster — die werden hier ausdruecklich
   zurueckgenommen; die Fassung ist der Bildrahmen. */
:root {
  /* 0,55 Abstand + 5,6 Bildnis + 0,76 Schild (der Balken liegt daneben) + 0,4 Luft */
  --bildnis-platz: 7.3rem;
}
#topbar .bildnisecke {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 0.8rem;
  display: flex;
  flex-direction: column;
  gap: 0.24rem;
  width: 5.6rem;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  cursor: var(--cursor-gold);
  pointer-events: auto;
}
/* DER STUFENBALKEN — bis zum naechsten Rang. SUBTIL heisst: eine Haarlinie
   von drei Bildpunkten, gedaempftes Messing auf fast schwarzem Grund, keine
   Zahl, kein Glanz. Die Zahl steht im Zeigertext und in der Standestafel.

   UNTER dem Bildnis, von der linken Kante bis dicht an das Schild: Es ragt
   rechts unten 0,8rem ueber den Rahmen und ist 2rem breit, seine linke Kante
   liegt also 1,2rem vor der rechten des Rahmens. Auf Hoehe des Balkens ist
   das Schild schon spitz zulaufend schmaler — darum reicht der Balken bis
   genau dorthin und laeuft nicht vorher aus. */
.kopf-stufenbalken {
  order: 2;
  display: block;
  width: calc(100% - 1.2rem);
  height: 3px;
  overflow: hidden;
  background: rgba(10, 11, 13, 0.7);
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
}
.kopf-stufenbalken i {
  display: block;
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, rgba(168, 129, 61, 0.55), rgba(204, 167, 94, 0.85));
  transition: width 1.2s ease-out;
}
.kopf-bildnisrahmen {
  position: relative;
  display: block;
  width: 5.6rem;
  height: 5.6rem;
  overflow: hidden;
  background: #1b1f24;
  border: 2px solid var(--brass);
  border-radius: 3px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.6);
  transition: border-color 0.12s;
}
/* AUF DAS GESICHT VERGROESSERT — UND DER KOPF WIRD NIE ANGESCHNITTEN.
   Ansage des Bro: „bitte immer so machen beim portrait dass der kopf nicht
   angeschnitten wird". Vergroessert wird darum um die OBERKANTE des Bildes
   (`transform-origin: 50% 0`): Sie bleibt fest am Rahmen, und was ueber dem
   Kopf an grauem Grund steht, steht auch hier darueber — oben kann nichts
   hinausfallen, gleich wie hoch ein Kopf im Bild sitzt. Hinaus fallen nur die
   Schultern und die Raender links und rechts.

   Die 1,75 ist an allen 61 Bildnissen nachgesehen (Hut, Haube, Locken, der
   Prüfer): Bei jedem steht der ganze Kopf samt Kinn im Rahmen. Wer die Zahl
   hebt, sieht sie sich wieder alle an — seitlich wird es zuerst eng. */
.kopf-bildnis {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Auch ein Bild, das nicht quadratisch ist, haengt an seiner Oberkante. */
  object-position: 50% 0;
  transform: scale(1.75);
  transform-origin: 50% 0;
  transition: filter 0.12s;
}
.kopf-bildnis[hidden] {
  display: none;
}
/* DIE STUFE ALS ZAHL unten links im Bildnis (28.09.2026) — der Balken darunter
   sagt, wie weit es zur nächsten ist, die Zahl, wo man steht. Klein, dunkel
   und in Messing gerandet wie das Band, damit sie das Gesicht nicht deckt. */
.kopf-stufenzahl {
  position: absolute;
  left: 0.2rem;
  bottom: 0.2rem;
  min-width: 1.35rem;
  padding: 0.05rem 0.25rem;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  color: #f3d27a;
  background: rgba(10, 11, 13, 0.85);
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  pointer-events: none;
}
.kopf-stufenzahl[hidden] {
  display: none;
}
.kopf-schild {
  position: absolute;
  right: -0.8rem;
  /* Von OBEN gemessen, nicht von unten: Unter dem Rahmen liegt der Balken,
     und die Unterkante des Knopfes ist seine. 5,6rem Rahmen + 0,76rem
     Ueberstand - 2,36rem Schild. */
  top: 4rem;
  width: 2rem;
  height: 2.36rem;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.8));
  pointer-events: none;
}
.kopf-schild:empty {
  display: none;
}
.kopf-schild svg {
  display: block;
  width: 100%;
  height: 100%;
}
#topbar .bildnisecke:hover .kopf-bildnisrahmen {
  border-color: var(--brass-light);
}
#topbar .bildnisecke:hover .kopf-bildnis {
  filter: brightness(1.12);
}
/* Noch kein Profil geladen: nicht zu sehen und nicht zu klicken — ein leerer
   Rahmen in der Ecke saehe aus wie ein Bild, das nicht laedt. Die Taste I
   fragt dasselbe (pointer-events, kopfleiste.js). */
#topbar .bildnisecke.leer {
  visibility: hidden;
  pointer-events: none;
}
/* DIE KARTE DES GEWÄHLTEN HELDEN steht auf dem Kriegstisch oben links
   (#heldenkarte, karte3d.html, 20.10.2026) — das eigene Bildnis ist so lange
   ausgeblendet. */
body:has(#heldenkarte:not([hidden])) #topbar .bildnisecke {
  visibility: hidden;
  pointer-events: none;
}
/* Oben links steht immer das Bildnis mit Wappen, auch bei ausgefahrenen
   Siegelkarten (20.10.2026: kurz ausgeblendet, dann durch das große Wappen
   ersetzt, dann auf Ansage des Bro wieder wie vorher: „lass doch wieder das
   alte bildnis mit wappen etc oben links zurück"). */

/* DER VOLLBILDKNOPF (27.09.2026) — ganz rechts in der Reihe. Zwei Zeichen in
   einem Knopf: vier eiserne Pfeilspitzen nach aussen (hinein), nach innen (heraus). */
#topbar .links .vollbildknopf .vb-heraus,
#topbar .links .vollbildknopf.an .vb-hinein {
  display: none;
}
#topbar .links .vollbildknopf.an .vb-heraus {
  display: block;
}
/* `hidden` verliert gegen `display: inline-flex` der Reihenregel — ohne diese
   Zeile stuende er dort, wo es kein Vollbild gibt, trotzdem da. */
#topbar .links .vollbildknopf[hidden],
#vollbildtoggle[hidden] {
  display: none;
}

/* --- 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;
}

/* 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;
}

/* 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: 14rem;
  padding: 0.3rem;
  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.25rem 0.5rem;
  background: none;
  border: none;
  border-radius: 2px;
  color: var(--brass-light);
  font: inherit;
  font-size: 0.88rem;
  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; }
/* DIE EINSTELLUNGEN ALS KACHELN (16.10.2026, Entwurf C aus
   Einstellungen-Entwurf.html). Oben eine Reihe Kacheln (Zeichen über einem
   Wort), darunter Antialiasing und Auflösung — Titel klein darüber, die
   Knöpfe als EINE Leiste gleich breiter Felder mit Haarlinien —, unten durch
   eine Messinglinie getrennt der Weg zum Vorplatz. Jeder Knopf trägt eigene
   Maße: Der Hausstil gibt jedem `button` Verlauf, Schatten und
   `width: fit-content`. */
#optionsmenue {
  width: 17rem;
  padding: 0.75rem;
}
/* Der Kopf ist der gemeinsame Tafelkopf (`.tafelkopf`, unten). Die Linie
   darunter läuft bis an die Ränder der Tafel (negativer Rand = Polster). */
#optionsmenue .tafelkopf {
  margin: -0.75rem -0.75rem 0.75rem;
}
#optionsmenue .ek-kacheln {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0.5rem;
}
#optionsmenue .ek-kachel {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  width: 100%;
  height: 4rem;
  margin: 0;
  padding: 0;
  background: #121417;
  border: 1px solid var(--iron);
  border-radius: 2px;
  box-shadow: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 400;
  letter-spacing: 0;
  cursor: var(--cursor-gold);
}
#optionsmenue .ek-kachel[hidden] { display: none; }
#optionsmenue .ek-kachel svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
#optionsmenue .ek-kachel:hover {
  border-color: var(--brass-light);
  background: #121417;
  color: #f0dfb4;
}
#optionsmenue .ek-kachel.an {
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.2);
  color: #f0dfb4;
}
#optionsmenue .ek-kachel:active { transform: none; box-shadow: none; }
#optionsmenue .ek-kachel.stumm .tonwelle { display: none; }

#optionsmenue > .qualitaetswahl {
  display: grid;
  gap: 0.3rem;
  margin-top: 0.75rem;
}
#optionsmenue .qualitaetstitel {
  color: var(--text-dim);
  font-size: 0.8rem;
}
#optionsmenue .qualitaetsknoepfe {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--iron);
  border-radius: 2px;
  overflow: hidden;
}
#optionsmenue .qualitaetsknoepfe button {
  width: 100%;
  height: 1.75rem;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--iron);
  border-radius: 0;
  box-shadow: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 400;
  letter-spacing: 0;
  cursor: var(--cursor-gold);
}
#optionsmenue .qualitaetsknoepfe button:first-child { border-left: 0; }
#optionsmenue .qualitaetsknoepfe button:hover {
  background: rgba(168, 129, 61, 0.12);
  color: #f0dfb4;
}
#optionsmenue .qualitaetsknoepfe button.an {
  background: rgba(168, 129, 61, 0.3);
  color: #f0dfb4;
}
#optionsmenue .qualitaetsknoepfe button:active { transform: none; box-shadow: none; }
#optionsmenue .qualitaetshinweis {
  color: var(--text-dim);
  font-size: 0.75rem;
}
#optionsmenue .qualitaetshinweis:empty { display: none; }

/* Unten über der Messinglinie „Zum Vorplatz" als Knopf über die ganze Breite
   (16.10.2026, wie Entwurf B). Die Linie läuft bis an die Ränder der Tafel. */
#optionsmenue .ek-fuss {
  margin: 0.75rem -0.75rem 0;
  padding: 0.75rem 0.75rem 0;
  border-top: 1px solid var(--brass-dark);
}
#optionsmenue a.ek-ausgang {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 2rem;
  background: rgba(168, 129, 61, 0.1);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  color: var(--brass-light);
  font-size: 0.9rem;
  text-decoration: none;
  cursor: var(--cursor-gold);
}
#optionsmenue a.ek-ausgang:hover {
  background: rgba(168, 129, 61, 0.22);
  border-color: var(--brass);
  color: #f0dfb4;
}

/* Trennstrich (der Sprite-Editor nimmt ihn noch). */
.optionstrenner {
  height: 0;
  margin: 0.25rem 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;
  /* EINE ZEILE (14.10.2026): Wird es eng, bricht nur das offene Fach des
     Speichers um (`.speicherwaren`), nach oben — Speicher, Holzkohle, Stein
     und Holz bleiben stehen, wo sie sind. Bis dahin `wrap`: Dann rutschte
     das Holz allein in eine zweite Zeile. */
  flex-wrap: nowrap;
  justify-content: flex-end;
  align-items: flex-end;
}
#resources > .res { flex-shrink: 0; }
/* 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 {
  /* Bezugsrahmen fuer die aufsteigende Marke der Vorratsmeldung, und
     `overflow: visible`, damit sie das Feld nach oben verlassen darf —
     ein <button> klemmt sie sonst je nach Browser ab. */
  position: relative;
  overflow: visible;
  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);
  /* DICHT, NICHT DURCHSICHTIG (05.10.2026, Ansage des Bro: „im winter sieht
     man die resourcen nicht. bitte die resourcen kacheln nicht mehr so stark
     transparent machen"). Bis dahin 30 % Schwarz — auf Schnee blieb davon ein
     hellgrauer Fleck, und die helle Zahl stand auf Weiss. Die Toenung der
     Sonderfelder (Wohnraum, Lager, Waffenlager, Einfluss, Militaer) liegt seit
     demselben Tag als `background-image` DARUEBER, damit sie diesen Grund
     nicht wieder durch ihren eigenen, fast durchsichtigen ersetzt. */
  /* LEICHT DURCHSICHTIG WIE DER SPEICHER (19.10.2026, Ansage des Bro: „die
     resourcen kacheln leicht transparent machen wie von der speicher
     kachel"): derselbe Grund wie dort, dunkel mit einem Hauch Holzton. */
  background-color: rgba(14, 14, 16, 0.72);
  background-image: linear-gradient(rgba(109, 84, 38, 0.14), rgba(109, 84, 38, 0.14));
  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-image: linear-gradient(rgba(109, 84, 38, 0.22), 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-image: linear-gradient(rgba(168, 129, 61, 0.18), 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-image: linear-gradient(rgba(107, 120, 137, 0.2), 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-image: linear-gradient(rgba(143, 61, 44, 0.28), 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-image: linear-gradient(rgba(109, 84, 38, 0.22), rgba(109, 84, 38, 0.22));
}
/* VOLL IST ROT (23.10.2026, Ansage des Bro: „wenn die speicher voll sind …
   wird das speicher symbol roter hintergrund“) — dann wird nicht mehr
   produziert (tick.ts), das ist keine Normallage mehr. */
.res.lager.voll {
  border-color: var(--blood);
  background-image: linear-gradient(rgba(143, 61, 44, 0.45), rgba(143, 61, 44, 0.45));
  color: #f0c9bd;
}
.res.lager.knapp {
  border-color: var(--blood);
  background-image: linear-gradient(rgba(143, 61, 44, 0.28), rgba(143, 61, 44, 0.28));
  color: #f0c9bd;
}

/* DAS WAFFENLAGER (08.09.2026) — eigenes Fass neben dem Speicher, und darum
   auch ein eigener Ton: Eisen statt Messing. Nicht Schmuck, sondern die
   Unterscheidung, die man beim Ueberfliegen braucht — zwei gleich aussehende
   Kaestchen mit "belegt/frei" nebeneinander liest niemand auseinander.
   Voll und knapp folgen derselben Warnsprache wie Wohnraum und Lager. */
.res.waffenlager {
  border-color: var(--iron-light);
  background-image: linear-gradient(rgba(59, 65, 74, 0.34), rgba(59, 65, 74, 0.34));
}
.res.waffenlager.voll {
  border-color: var(--brass);
  color: var(--brass-light);
}
.res.waffenlager.knapp {
  border-color: var(--blood);
  background-image: linear-gradient(rgba(143, 61, 44, 0.28), rgba(143, 61, 44, 0.28));
  color: #f0c9bd;
}

/* DER SPEICHER KLAPPT AUF (14.10.2026, Ansage des Bro: „wenn man auf
   speicher klickt dann öffnen sich die restlichen resourcen aus dem
   speicher"). Seine Waren stehen in `.speicherwaren` links von ihm
   (leistenmarkup.ts), mit derselben Lücke wie die Leiste. Das Fach ist das
   EINZIGE, was schrumpfen darf (`#resources > .res` schrumpft nicht): Reicht
   die Breite nicht, bricht es nach OBEN um (`wrap-reverse`), die untere Zeile
   bleibt voll. Gegen diese Regel wirkte `hidden` allein nicht mehr — darum
   steht `[hidden]` ausdrücklich da. */
.speicherwaren {
  display: flex;
  flex-wrap: wrap-reverse;
  justify-content: flex-end;
  align-items: flex-end;
  gap: 0.18rem;
}
.speicherwaren[hidden] { display: none; }
/* DIE TRUHE GRÖSSER (14.10.2026, Ansage des Bro: „kansnt du die truhe größer
   machen als symbol"). Das Bild ist quadratisch, die Truhe darin breit und
   oben wie unten ein Drittel leer; zugeschnitten (`cover`) steht sie gut
   anderthalbmal so groß da, ohne die Kachel höher zu machen. */
.res.lager .resicon {
  width: 36px;
  height: 24px;
  margin: -1px 0;
  /* SCHARF (19.10.2026, Ansage des Bro: „warum ist der speicher icon so
     unscharf"): Das Bild ist seither selbst 36 × 24 (und 72 × 48, 108 × 72),
     aus dem 256er Rohbild zugeschnitten — vorher wurde ein 32er Quadrat per
     `cover` hochgezogen. */
}
/* Der Pfeil zeigt, wohin das Fach aufgeht: zu nach links, offen nach rechts
   zurück. Zwei Ränder eines Quadrats, gedreht — kein Schriftzeichen. */
.res.lager .speicherpfeil {
  flex: none;
  width: 0.36rem;
  height: 0.36rem;
  margin: 0 0.04rem 0 0.14rem;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  opacity: 0.8;
  transition: transform 160ms ease-out;
}
.res.lager[aria-expanded="true"] .speicherpfeil { transform: rotate(-135deg); }
@media (prefers-reduced-motion: reduce) {
  .res.lager .speicherpfeil { transition: none; }
}

/* 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). */
/* DIESELBE PLAKETTENGROESSE FUER BEIDE LEISTEN. #baumaterial zeigt im
   Baumodus drei Waren an DERSELBEN Stelle, an der #resources sie sonst
   zeigt (siehe dort) — stuende die Schriftgroesse nur hier, waere die
   Plakette beim Umschalten 27 statt 36 Punkte hoch, und die Zeile
   spraenge. */
#resources .res,
#baumaterial .res,
/* DAS KOPFBAND AUCH ALS SCHLICHTE SPANNE (03.10.2026, gemeldet: „warum sind
   im kartenmodus die zahlen oben in der leiste falsch angezeigt"). Die Größe
   1,1rem trug bis dahin nur `.res-knopf` — auf der Landkarte und beim Besuch
   einer fremden Burg stehen dort Spannen statt Knöpfe, und die Zahlen fielen
   auf die 0,77rem der Grundregel zurück, kleiner als ihr Kasten. */
.kopf-einfluss-militaer .res {
  font-size: 1.1rem;
}
/* DIESELBEN ZIFFERN UND DERSELBE ABSTAND IN BEIDEN LEISTEN (14.10.2026).
   Die Kacheln der Vorratsleiste sind Knöpfe: `button` gibt ihnen 0,03em
   Buchstabenabstand, und `.res-knopf` nimmt ihnen mit `font: inherit` die
   gleich breiten Ziffern von `.res`. Die Baustoffe im Baumodus sind Spannen
   ohne beides — mit Zahlen in Kilogramm („493.895") lagen sie darum bis zu
   vier Punkte schmaler auf ihren Kacheln. */
#resources .res,
#baumaterial .res {
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.03em;
}

/* 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: auto;
}
/* Wohnraum, Lager und Waffenlager zeigen KEIN Warenbildchen, sondern den Riss
   ihres Gebaeudes (Kate, Speicher, Waffenkammer). Fuer die muss die
   Pixelglaettung wieder aus — sie sind keine Pixelgrafik. */
.res .resicon.riss {
  image-rendering: auto;
}
/* DIE EINHEIT HINTER DER ZAHL (14.10.2026): „kg" und „Pf" kleiner und blasser
   als die Zahl und dicht an ihr — gelesen wird die Zahl. Der Rand nimmt den
   Abstand des Feldes zurück; das geschützte Leerzeichen genügt. */
.res .reseinheit {
  margin-left: -0.21rem;
  font-size: 0.8em;
  opacity: 0.7;
}
/* DAS „t“ IN DER KACHEL (15.10.2026, kilogramm.ts `reszahlHtml`): ab 1000 kg
   steht die Zahl in Tonnen. Das „t“ hängt als Merkmal an der Zahl, nicht in
   ihrem Text — die Leiste liest und rollt nur die Ziffern. Gesetzt wie die
   Einheit oben, mit geschütztem Leerzeichen. */
.res .reszahl[data-einheit]::after {
  content: "\00a0" attr(data-einheit);
  font-size: 0.8em;
  opacity: 0.7;
}

/* --- DIE VORRATSMELDUNG ----------------------------------------------------
 *
 * Ansage des Bauherrn (11.09.2026): „die meldung ,der holzfaeller hat
 * geschlagen' oder aehnliches bitte wegmachen, stattdessen eine schoene
 * animation dass mehr holz unten in der leiste ist und das bei allen
 * resourcen."
 *
 * Vier Fassungen sind gebaut und nebeneinander vorgefuehrt worden; gewaehlt
 * ist „Glut + Zahl": Das Feld zieht den Blick, die Zahl beantwortet ihn.
 * Welche laeuft, entscheidet der Regler „Vorratsmeldung / Art" — die anderen
 * drei bleiben ausdruecklich in Reichweite.
 *
 * DIE GLUT HAENGT AN `data-zugang`, NICHT AN EINER KLASSE. Die Leiste zieht
 * bei jedem Takt Klassen und Titel ihrer Felder nach (`leisteNachziehen` in
 * hud3d.ts); eine Animationsklasse waere dabei mitten im Lauf verschwunden.
 * Ein Datenattribut fasst sie nicht an.
 * ------------------------------------------------------------------------ */

/* Die aufsteigende Marke — „+3" oder „−30" ueber dem Feld. */
.reszugang {
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translateX(-50%);
  /* Fest und nicht geerbt: `#resources .res` steht auf 1.1rem, und die Marke
     soll die Zahl darunter nicht ueberragen — aber sie steht vor der
     LANDSCHAFT und nicht vor einem Feld, darum nicht zu klein. */
  font-size: 0.95rem;
  font-weight: bold;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
  /* EIN HARTER RAND, kein weicher Schein. Sie steht vor der LANDSCHAFT, nicht
     vor einem Feld — und ueber hellem Gras (gemessen an #9ab866) loest ein
     weicher Schatten das Gruen vollstaendig auf: gleiche Helligkeit, gleicher
     Farbton. Vier versetzte Kopien in Schwarz legen eine Kontur um jede Ziffer,
     der abschliessende weiche Schatten setzt sie vom Grund ab. */
  text-shadow:
    -1px -1px 0 #000,
    1px -1px 0 #000,
    -1px 1px 0 #000,
    1px 1px 0 #000,
    0 2px 5px rgba(0, 0, 0, 0.85);
}
/* ÜBEREINANDER, wenn mehrere zugleich steigen (14.10.2026): Über dem
   zugeklappten Speicher melden alle seine Waren, je eine Marke mit dem Bild
   der Ware vor der Zahl (hud3d.ts, `markeZeigen`). `--stapel` ist ihr Platz
   von unten, 0 ist der alte Sitz. */
.reszugang[data-stapel] { bottom: calc(100% + var(--stapel, 0) * 1.3rem); }
.reszugang-bild {
  width: 1rem;
  height: 1rem;
  margin-right: 0.15rem;
  vertical-align: -0.2rem;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.85));
}
/* IM KOPFBAND GIBT ES SIE NICHT MEHR (12.09.2026).
   Hier stand eine Sonderregel, die die Marke nach UNTEN fallen liess statt
   aufzusteigen — oben am Bildrand ist ueber dem Feld kein Platz, und sie legte
   sich sonst ueber den Burgnamen. Sie ist hinfaellig: Silber, Einfluss und
   Militaerstaerke bekommen gar keine Marke und kein Aufleuchten mehr, ihre
   Zahlen ROLLEN nur noch (hud3d.ts, `zahlRollen`; das Kopfband steht nicht
   mehr in MELDE_LEISTEN). Ansage des Bauherrn: „lass uns oben bei einfluss und
   geld und wehrmacht ganz simple halten, die zahl dreht sich einfach nur ohne
   aufzploppen oder so."

   DIE ZAHL BRAUCHT DAFUER KEINE ZEILE CSS. Sie wird Bild fuer Bild
   geschrieben; eine Animation darauf gaebe es gar nicht zu setzen. Was sie
   braucht, steht schon weiter oben: `font-variant-numeric: tabular-nums` —
   ohne gleich breite Ziffern huepft die Leiste beim Rollen in der Breite. */

/* DIE DAUER KOMMT AUS EINER VARIABLEN, NIE ALS ZAHL (13.09.2026).
   `--reszugang-marke` und `--reszugang-glut` setzt hud3d.ts
   (`meldungsdauernSetzen`) aus VORRATSMELDUNG — dieselbe Zahl, mit der die
   Marke auch abgeraeumt wird. Stuende hier wieder eine Millisekundenzahl,
   liefen Bewegung und Abraeumen beim ersten Dreh am Regler auseinander, und
   die Marke verschwaende mitten im Aufsteigen. `vorratsmeldung.test.ts`
   bewacht es. Die Zahl hinter dem Komma ist nur der Rueckfall fuer den
   Augenblick, bevor das Skript gelaufen ist. */
.reszugang.mehr {
  color: var(--moss-light);
  animation: res-steigt var(--reszugang-marke, 3000ms) cubic-bezier(0.22, 0.8, 0.3, 1) forwards;
}
.reszugang.weniger {
  color: var(--blood-light);
  animation: res-faellt var(--reszugang-marke, 3000ms) cubic-bezier(0.22, 0.8, 0.3, 1) forwards;
}

/* Der Zugang STEIGT auf, der Abgang SINKT ab — die Richtung sagt das Vorzeichen
   schon, bevor man die Ziffer gelesen hat.

   MIT HALTEPHASE, seit dem 13.09.2026. Vorher begann die Marke unmittelbar
   nach dem Erscheinen zu verblassen: Das Plus war nachgerechnet nur 260 ms
   VOLL zu sehen, das Minus 115 ms — ein Flackern, das man nicht liest. Der
   Bro hielt es fuer zu kurz, und er hatte recht, nur lag es weniger an der
   Dauer als an der Form. Jetzt: kurz aufploppen (die ersten 8 %), dann
   STEHEN und dabei langsam weiterziehen, erst ab 74 % ausblenden. Bei 3000 ms
   (vom Bro am Bild festgelegt) sind das rund 2 Sekunden volle Deckkraft. Das Aufploppen liegt bei 6 %
   und nicht bei 8: Prozente dehnen sich mit der Dauer, und bei drei Sekunden
   waere ein Aufploppen ueber 8 % schon ein Aufsteigen. */
@keyframes res-steigt {
  0% { opacity: 0; transform: translate(-50%, 6px) scale(0.8); }
  6% { opacity: 1; transform: translate(-50%, -3px) scale(1.12); }
  11% { opacity: 1; transform: translate(-50%, -6px) scale(1); }
  74% { opacity: 1; transform: translate(-50%, -17px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -28px) scale(1); }
}
@keyframes res-faellt {
  0% { opacity: 0; transform: translate(-50%, -16px) scale(0.9); }
  8% { opacity: 1; transform: translate(-50%, -10px) scale(1); }
  74% { opacity: 1; transform: translate(-50%, 1px) scale(1); }
  100% { opacity: 0; transform: translate(-50%, 10px) scale(1); }
}

/* Die Glut des Feldes — ebenfalls mit einem Halt am Anfang: Das Feld soll
   HELL STEHEN und dann ausklingen, nicht schon beim Aufleuchten wieder dunkler
   werden. */
.res[data-zugang="mehr"] {
  animation: res-glut var(--reszugang-glut, 2600ms) ease-out;
}
.res[data-zugang="weniger"] {
  animation: res-glut-rot var(--reszugang-glut, 2600ms) ease-out;
}
.res[data-zugang] .resicon {
  animation: res-hupf 430ms cubic-bezier(0.3, 1.5, 0.5, 1);
}
@keyframes res-glut {
  0%, 30% {
    border-color: var(--brass-light);
    background: rgba(204, 167, 94, 0.32);
    box-shadow: 0 0 14px rgba(204, 167, 94, 0.5);
  }
  100% {
    border-color: var(--iron);
    background: rgba(0, 0, 0, 0.3);
    box-shadow: 0 0 0 rgba(204, 167, 94, 0);
  }
}
@keyframes res-glut-rot {
  0%, 30% {
    border-color: var(--blood);
    background: rgba(143, 61, 44, 0.34);
    box-shadow: 0 0 14px rgba(143, 61, 44, 0.45);
  }
  100% {
    border-color: var(--iron);
    background: rgba(0, 0, 0, 0.3);
    box-shadow: 0 0 0 rgba(143, 61, 44, 0);
  }
}
@keyframes res-hupf {
  0% { transform: translateY(0); }
  40% { transform: translateY(-4px); }
  100% { transform: translateY(0); }
}

/* WER KEINE BEWEGUNG WILL, bekommt trotzdem die Auskunft: Die Marke steht
   ruhig ueber dem Feld und wird nach `dauerMs` abgeraeumt (hud3d.ts). */
@media (prefers-reduced-motion: reduce) {
  .reszugang.mehr,
  .reszugang.weniger,
  .res[data-zugang],
  .res[data-zugang] .resicon {
    animation: none;
  }
  .reszugang { opacity: 1; }
}

/* 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;
}

/* ORTHOGRAPHISCHE RISSE aus den Spielmodellen (scripts/build-building-icons.js,
   gerendert von tools/blender/vorlage-riss.py) — Parallelperspektive von vorn,
   alle auf einer Standlinie. Sie loesen die handgezeichneten 16px-Pixelbildchen
   ab (12.09.2026): Dreizehn baubare Typen hatten gar keines, und aus dem Riss
   entsteht der Satz bei jedem Lauf von selbst vollzaehlig.
   KEIN `image-rendering: pixelated` — das ist Nearest-Neighbour, und ein
   Rissbild von 96 px auf 20 px herunterzurechnen sieht damit zerfranst aus.
   Die Pixelglaettung gehoert zu den Warenbildchen, die weiter Pixelgrafik
   sind (.resicon). */
.buildicon {
  width: 16px;
  height: 16px;
  flex: none;
}
.buildbtn.locked .buildicon {
  filter: grayscale(1);
}
/* Im Zettel der Bauvorhaben steht das Bildchen LINKS NEBEN dem Text,
   nicht in der Zeile mit (12.09.2026). Bei 13 px in der Textzeile war ein Riss
   nicht mehr zu erkennen — gemessen tragen die Silhouetten ab etwa 20 px. In
   der Zeile mitlaufend haette das die Zeilenhoehe aufgeblasen und den Zettel
   genau um das wieder groesser gemacht, worum er am 11.09. verkleinert wurde;
   als Float steht es neben BEIDEN Zeilen (Satz und Balken) und kostet keine
   zusaetzliche Hoehe. `overflow: hidden` an .queueitem faengt den Float ein —
   ohne das ragte das Bildchen bei einem kurzen Satz unten heraus. */
.queueitem .buildicon {
  width: 20px;
  height: 20px;
  float: left;
  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;
  --schein: var(--iron); background-image: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%);
}
#baumenu .kategorie.kat-rohstoffe { --schein: #5d8a4f; }
#baumenu .kategorie.kat-verarbeitung { --schein: #b0793e; }
#baumenu .kategorie.kat-sozial { --schein: #4f7a9e; }
#baumenu .kategorie.kat-verteidigung { --schein: #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(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), linear-gradient(180deg, #2c3138, #22262b);
  border: 1px solid var(--iron);
  --schein: var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
  transition: border-color 0.12s, background 0.12s;
}
.baueintrag.kat-rohstoffe { --schein: #5d8a4f; }
.baueintrag.kat-verarbeitung { --schein: #b0793e; }
.baueintrag.kat-sozial { --schein: #4f7a9e; }
.baueintrag.kat-verteidigung { --schein: #8a8f96; }
.baueintrag:hover { border-color: var(--brass); }
.baueintrag.aktiv {
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), 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: auto; 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(--kampftafel-hoehe, 0rem) + var(--fuhren-hoehe, 0rem));
  bottom: auto;
  right: auto;
  left: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  max-width: 250px;
}

/* 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(--kampftafel-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(--kampftafel-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);
}
/* KLEINER SEIT DEM 11.09.2026 (Ansage: „bitte wenn ein gebäude gebaut wird
   diese ladebalken oben links kleiner gestalten"). Bei drei Baustellen
   standen dort drei Pergamentzettel in Fließtextgröße und nahmen das ganze
   linke Viertel des Bildes ein — eine Nebenauskunft in der Größe einer
   Hauptsache. Schrift, Polster, Balken und Bildchen sind alle um rund ein
   Achtel bis ein Viertel zurückgenommen; die Breite folgt von selbst, denn
   der Kasten ist schrumpfend gesetzt (`max-width` deckelt ihn nur). */
.queueitem {
  /* DUNKELGRAU MIT MESSING statt Pergament (27.09.2026, Ansage des Bro:
     „die bau tafel die noch gemacht werden im dunkel grau mit messing machen
     das ist generell bei uns der style"). Derselbe Grund wie das Kopfband
     (#topbar), derselbe Messingrand wie seine Knoepfe. */
  background: linear-gradient(180deg, rgba(34, 38, 43, 0.95), rgba(16, 18, 21, 0.95));
  color: #ddd2bb;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  padding: 0.26rem 0.5rem;
  font-size: 0.74rem;
  line-height: 1.3;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
  /* Faengt den Float des Bildchens ein, siehe .queueitem .buildicon */
  overflow: hidden;
}
/* DIE WIRKUNGSLEISTE (30.09.2026, client/src/iso3d/wirkungsleiste.ts) —
   laufende Boni und Mali als Kaestchen. Ansagen des Bro: „als so ein bildchen
   … im massstab von der bauschlange" und „oben auf der linken seite neben
   des portraits rechts von portraits". Sie haengt darum IM Kopfband wie das
   Bildnis (.bildnisecke), auf derselben Hoehe und rechts von seinem
   Wappenschild: 0,8rem Rand + 5,6rem Bildnis + 0,8rem ueberstehendes Schild
   + 0,1rem Luft (gemessen rund 16 Bildpunkte bis zum Schild). Wer die Masse
   des Bildnisses aendert, zieht `left` nach.
   Ein Kaestchen ist so hoch wie ein Eintrag der Bauvorhaben (.queueitem),
   dunkelgrau mit Messing wie alles. Ein Malus traegt einen roetlichen Rand. */
#wirkungen {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 7.3rem;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 0.3rem;
  max-width: min(24rem, calc(100vw - 8.5rem));
  pointer-events: none;
}
#wirkungen.ohne-kopfband {
  position: fixed;
  top: 3.6rem;
}
#wirkungen:empty {
  display: none;
}
#wirkungen .wirkung {
  position: relative;
  width: 36px;
  height: 36px;
  flex: none;
  display: grid;
  place-items: center;
  background: linear-gradient(180deg, rgba(34, 38, 43, 0.95), rgba(16, 18, 21, 0.95));
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
  cursor: var(--cursor-gold, pointer);
  pointer-events: auto;
}
#wirkungen .wirkung:hover {
  border-color: var(--brass-light);
}
#wirkungen .wirkung.schlecht {
  border-color: #7a3b2c;
}
#wirkungen .wirkung.schlecht:hover {
  border-color: #b4553c;
}
#wirkungen .wirkung img {
  width: 28px;
  height: 28px;
}
#wirkungen .wirkung-zahl {
  position: absolute;
  right: 1px;
  bottom: -1px;
  font-size: 0.62rem;
  line-height: 1;
  color: #f1e3c2;
  text-shadow: 1px 0 0 #000, -1px 0 0 #000, 0 1px 0 #000, 0 -1px 0 #000;
  pointer-events: none;
}
#wirkungen .wirkung.schlecht .wirkung-zahl {
  color: #f0b6a4;
}
/* Der Zeigertext der Wirkungsleiste — sofort da, kein Warten wie beim title. */
.wirkung-tipp {
  position: fixed;
  z-index: 60;
  max-width: 18rem;
  padding: 0.35rem 0.55rem;
  background: #16130f;
  border: 1px solid var(--brass-dark);
  border-radius: 4px;
  color: #e8dcc4;
  font-size: 0.85rem;
  line-height: 1.35;
  pointer-events: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
}
.wirkung-tipp[hidden] {
  display: none;
}

/* Balken und Mannschaft teilen sich EINE Zeile: Der Balken nimmt, was
   uebrig ist, die Zahl steht rechts an ihrem festen Platz. */
/* FESTE SPALTEN (16.10.2026, Ansage des Bro: „die sollen alle gleich breit
   sein. kannst du es ausrichten und die breite des balkens ist konstant und
   der wird einfach aufgefüllt" — und „dadurch haben wir kompakte gleichmässige
   kästchen das zzZ macht die nicht zu lang"). Balken, Bauleute und Ochse (ohne
   Ochsen „0/1") stehen in
   einem Raster mit festen Breiten — fehlt ein Zeichen, bleibt sein Platz
   leer, und alles darunter und darüber steht in denselben Spalten. Gleich
   breit sind die Zettel, weil der Meldestapel (#meldestapel, 3d.html) eine
   feste Breite hat und sie darin gestreckt stehen. */
.queueitem .bauzeile {
  display: grid;
  /* Die Bauleute-Spalte faengt auch „12/12" (Bergfried) ohne Umbruch; der
     Ochse steht dicht daneben (Ansage: „bewohner und ochsen näher
     zusammenrücken"). „zzZ" steht nicht hier, sondern an der Stelle des
     Bildchens (`.buildicon.schlaeft`). */
  grid-template-columns: 1fr 2.9em 2.4em;
  align-items: center;
  column-gap: 0.3rem;
  margin-top: 0.18rem;
}
.queueitem .bauzeile > .bar { grid-column: 1; margin-right: 0.6rem; }
/* Rechtsbuendig an den Ochsen geschoben (Ansage: „mach den ochsen nach links
   näher an den bauer"); „12/12" waechst nach links in den Rand vor dem Balken. */
.queueitem .bauzeile > .bauleute { grid-column: 2; justify-self: end; white-space: nowrap; }
.queueitem .bauzeile > .bauleute.ochsen { grid-column: 3; margin-left: 0; justify-self: start; }
/* „zzZ" AN DER STELLE DES BILDCHENS — dieselbe Groesse, derselbe Float. */
.queueitem .buildicon.schlaeft {
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.queueitem .buildicon.schlaeft .bauschlaf {
  margin: 0;
  font-size: 1.4em;
}
.queueitem .bar {
  height: 3px;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 2px;
  overflow: hidden;
}
.queueitem .bar > div {
  height: 100%;
  background: linear-gradient(90deg, var(--brass-dark), var(--brass));
}
/* DIE ZEIT IM BALKEN (20.10.2026, hud3d.ts `zeitBalken`): der Balken hoch
   genug für eine kleine Zeile, die Zeit mittig darüber, lesbar auf Messing
   wie auf Schwarz. */
.queueitem .bar.mit-zeit {
  position: relative;
  height: 13px;
  border-radius: 0;
  border: 1px solid #2a2a2a;
}
.queueitem .bar.mit-zeit > .bar-zeit {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.62rem;
  line-height: 1;
  white-space: nowrap;
  color: #f2ead8;
  text-shadow: 0 0 2px #000, 0 0 2px #000, 0 1px 1px #000;
  font-variant-numeric: tabular-nums;
}
.queueitem .bar.mit-zeit > .bar-zeit .ruht { color: #e8b0a0; }

/* DIE BAUSTELLENTAFEL (10.09.2026) — Fortschritt und Mannschaft beim Klick
   auf einen Bauplatz. Ansage: „wenn man drauf klickt dann wird die baustelle
   mit dem prozess angezeigt und da steht auch wie viele arbeiter gerade dran
   sind 1/3 oder 3/3 und so." */
.gp-bauzeile {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0.35rem 0 0.2rem;
  font-size: 0.85rem;
}
.gp-bauleute {
  font-variant-numeric: tabular-nums;
}
.gp-bauleute.knapp {
  color: var(--brass);
}
.gp-bauleute.ruht,
.gp-status.gp-bau-ruht {
  color: var(--blood);
}
.gp-bautempo {
  color: var(--text-dim);
  font-variant-numeric: tabular-nums;
}
.gp-baubalken {
  height: 5px;
  background: rgba(60, 48, 28, 0.35);
  border-radius: 2px;
  overflow: hidden;
}
.gp-baubalken > div {
  height: 100%;
  background: linear-gradient(90deg, var(--brass-dark), var(--brass));
}
.gp-bauhinweis {
  margin: 0.35rem 0 0;
  font-size: 0.78rem;
  color: var(--text-dim);
  line-height: 1.35;
}

/* DIE BAULEUTE an einer Baustelle (10.09.2026, server/src/bauleute.ts).
   Rechtsbuendig, damit die Zahlen mehrerer Baustellen untereinander stehen —
   sie werden verglichen, nicht gelesen. */
.queueitem .bauleute {
  flex: none;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  opacity: 0.85;
}

/* DAS ZEICHEN DER BAULEUTE: die Büste eines Bauern (11.09.2026).

   Ansage des Bauherrn: „den bauarbeiten mit helm und weste bitte wegmachen.
   stattdessen brauchen wir so eine silhouette einer büste von einem bauern."
   Dort stand 👷 — ein Bauarbeiter mit Schutzhelm und Warnweste, also zwei
   Dinge, die es 1157 nicht gibt. In einer Burg des Hochmittelalters baut
   kein Bauarbeiter, sondern der Bewohner, der gerade keine Arbeit hat.

   ES IST EINE MASKE UND KEIN BILD, und das ist der Kniff: Die Fläche kommt
   aus `currentColor`, das Zeichen nimmt also die Farbe seiner Zeile an —
   gedämpft im Normalfall, bernsteinfarben bei knapper Mannschaft, rot wenn
   die Baustelle ruht. Ein PNG müsste dafür dreimal existieren.

   Und es steht als Datenadresse hier statt als Datei daneben: Diese
   Stilvorlage wird von Seiten aus zwei verschiedenen Wurzeln geladen
   (`/ui.css` und `/app/…`), ein relativer Pfad auf eine Datei zeigte je
   nach Seite woanders hin. Verworfen wurden dabei drei Entwürfe: eine
   Gugel (der Zipfel liest sich bei 12 px als Zopf), eine Kappe (sie sieht
   aus wie ein Helm — genau das, was weg sollte) und ein barhäuptiger Kopf
   (das ist das Zeichen für „Benutzer", nicht für „Bauer"). Der Strohhut
   ist das einzige Merkmal, das bei 12 px noch trägt. */
.bauleute-zeichen {
  display: inline-block;
  width: 1.05em;
  height: 1.05em;
  vertical-align: -0.17em;
  margin-right: 0.22em;
  background-color: currentColor;
  -webkit-mask: var(--bauer-bueste) no-repeat center / contain;
  mask: var(--bauer-bueste) no-repeat center / contain;
}
/* KNAPP ist bernsteinfarben, RUHT ist rot — dieselbe Staffelung wie überall
   sonst im Spiel. Ein Bau ohne Bauleute kommt nicht voran, das ist kein
   Hinweis, sondern ein Halt. */
.queueitem .bauleute.knapp {
  color: var(--brass);
  opacity: 1;
}
.queueitem .bauleute.ruht,
.queueitem .ruht {
  color: var(--blood);
  opacity: 1;
}

/* DER OCHSE AN DER BAUSTELLE (14.10.2026, hud3d.ts `ochsenAnDerBaustelle`) —
   „1/1" neben den Bauleuten, als Kopf statt Büste. Ohne Ochsen blass: Es fehlt
   nichts, es geht nur langsamer. */
.ochsen-zeichen {
  display: inline-block;
  width: 1.05em;
  height: 1.05em;
  vertical-align: -0.17em;
  margin-right: 0.22em;
  background-color: currentColor;
  -webkit-mask: var(--ochsen-kopf) no-repeat center / contain;
  mask: var(--ochsen-kopf) no-repeat center / contain;
}
.ochsen-bild {
  width: 1.5em;
  height: 1.5em;
  vertical-align: -0.4em;
  margin-right: 0.15em;
}
.queueitem .bauleute.ochsen {
  margin-left: 0.45em;
}
.bauleute.ochsen.leer,
.gp-bauleute.ochsen.leer {
  opacity: 0.6;
}
.gp-bauleute.ochsen:not(.leer) {
  color: var(--brass);
}

/* DIE MANNSCHAFT SCHLÄFT (16.10.2026, baufortschritt.ts `schlafMarke`) —
   „zzz" neben den Bauleuten, nachts, wenn der Bau ruht (`bauruhe`). Drei z,
   jedes größer und höher, im Mondlicht-Grau; sie steigen langsam auf und
   vergehen, versetzt. */
.bauschlaf {
  display: inline-flex;
  align-items: flex-end;
  margin-left: 0.45em;
  height: 1.2em;
  font-size: 1.15em;
  letter-spacing: 0.04em;
  color: #c9d8e6;
  font-style: italic;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
}
.bauschlaf i {
  display: inline-block;
  font-style: inherit;
  animation: bauschlaf-steigen 2.4s ease-in-out infinite;
}
.bauschlaf i:nth-child(1) { font-size: 0.6em; }
.bauschlaf i:nth-child(2) { font-size: 0.8em; transform: translateY(-0.18em); animation-delay: 0.4s; }
.bauschlaf i:nth-child(3) { font-size: 1em; transform: translateY(-0.38em); animation-delay: 0.8s; }
@keyframes bauschlaf-steigen {
  0%, 100% { opacity: 0.55; translate: 0 0.06em; }
  50% { opacity: 1; translate: 0 -0.1em; }
}
@media (prefers-reduced-motion: reduce) {
  .bauschlaf i { animation: none; }
}

/* 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 Brendanburg
   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 traegt
     eine Version — ein ausgetauschtes Startbild erscheint dadurch sofort und
     nicht erst, wenn der Browser-Cache abgelaufen ist.

     GEZEIGT WIRD DIE GLATTE FASSUNG (11.09.2026). Hier stand bis dahin die
     PIXELFASSUNG (960 Punkte breit), mit der Begruendung: das Spiel dahinter
     sei Pixelkunst, das gemalte Original nicht. Beides stimmt so nicht mehr —
     die 3D-Ansicht ist seit dem 26.08.2026 keine Pixelkunst, und das
     Anmeldebild ist jetzt GEMALTE KONZEPTKUNST aus derselben Werkstatt wie die
     Ladebilder (docs/protokoll/die-ladebilder-sind-gemalte-konzeptkunst.md).
     Ein Raster darueber nimmt ihm genau das, wofuer es gewaehlt wurde: den
     Pinselstrich. Die Pixelfassung wird weiter gebaut und bleibt liegen —
     zurueck sind es zwei Zeilen (`--opener-bild-pixel` und `image-rendering`). */
  background-image: var(--opener-bild, url("/static/opener/opener.jpg"));
  background-size: 100% 100%;
  /* KEIN Filter. Das Bild bringt seine Stimmung selbst mit — jedes Abdunkeln
     nahm ihm nur Zeichnung. Lesbar bleibt die Schrift davor durch ihre eigene
     Kontur, nicht dadurch, dass das Bild gedaempft 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. */
/* UEBER dem Ladeschirm: Der `.hero__laden` liegt spaeter im Markup und deckte
   den Titel sonst zu — man saehe waehrend des Ladens nur einen Balken auf
   Schwarz. Die Ladeschirme des Spiels zeigen Titel UND Balken, und danach
   richtet sich diese Seite (Ansage vom 29.08.2026). */
.hero__kopf {
  z-index: 2;
  position: absolute;
  /* WEITER RUNTER (Ansage 29.08.2026). 6 % klebten am oberen Rand; auf einem
     flachen Fenster stand der Titel praktisch in der Kante. 13 % lassen ihn
     atmen und halten ihn zugleich ueber dem Anmeldeformular, das mittig
     sitzt. */
  top: 13%;
  left: 50%;
  translate: -50% 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* 14px wie `#laden` im Ladeschirm — der Ort holt sich davon mit seinem
     negativen Rand 6 zurueck. Nicht neu erfunden, abgeschrieben. */
  gap: 14px;
}
/* DER TITEL IST SEIT DEM 25.09.2026 DIE TITELMARKE (/app/3d/titelmarke.css,
   Markup aus server/src/titelmarke.ts) — dieselbe wie im Hub, auf der
   Charakterseite und auf dem Ladeschirm. Hier steht nur ihre GROESSE, und
   die ist die des Ladeschirms (`#laden` in client/3d.html): Anmeldung und
   Ladeschirm tragen denselben Titel in derselben Groesse. Bis dahin standen
   hier `.hero__titel` und `.hero__ort` als Abschrift von `#laden h1` und
   `#laden-ort`; sie stehen in der Historie. */
.hero__kopf { --titelmarke-groesse: clamp(1.4rem, 4.6vw, 2.8rem); }

/* ---------------------------------------------------------------------------
   DER LADEVORGANG DER KULISSE (server/public/kulisse-laden.js)

   Solange die 3D-Kulisse aufbaut, liegt hier eine dunkle Flaeche mit einem
   Balken darauf; ist sie fertig, blendet sie ein und die Flaeche geht weg.

   DAS GEMAELDE TRITT ZURUECK (`hero--kulisse`), bleibt aber im Markup: Ohne
   WebGPU oder bei einem Fehler im Aufbau holt das Skript es hervor
   (`hero--gemaelde`) — sonst staende auf der Anmeldung eine schwarze Flaeche
   mit einem Formular darauf. Zu sehen bekommt man es nur, wenn ohnehin etwas
   schiefging.
   --------------------------------------------------------------------------- */
.hero--kulisse .hero__buehne {
  opacity: 0;
  transition: opacity var(--kulisse-blende, 3s) ease;
}
.hero--kulisse.hero--gemaelde .hero__buehne {
  opacity: 1;
}
/* DIE DAUER DER BLENDE. Dieselbe Zahl steht als `BLENDE` in
   kulisse-laden.js — dort nur, um den Ladeschirm DANACH aus dem Baum zu
   nehmen. */
.hero--kulisse {
  --kulisse-blende: 3s;
  /* GANZ SCHWARZ hinter der Kulisse (Ansage 29.08.2026: „den hintergrund
     einfach komplett schwarz machen"). Der Ladeschirm darueber traegt
     dieselbe Farbe — so blendet die Kulisse aus reinem Schwarz auf und nicht
     aus einem Grauton, und waehrend der Ueberblendung liegt kein zweiter Ton
     dazwischen. */
  background: #000;
}
/* DER RAHMEN BLEIBT SICHTBAR — und das ist die Berichtigung vom 29.08.2026
   („gerade wird es so reingeploppt").

   Hier stand die Blende AM IFRAME: `opacity: 0`, dann auf 1. Das hat zwei
   Fehler, und beide erzeugen genau das Plopp:

   1. EIN UNSICHTBARER RAHMEN ZEICHNET NICHT. Browser drosseln die
      Darstellung in Rahmen, die nichts zum Bild beitragen — dieselbe
      Mechanik, an der schon `requestAnimationFrame` und die CSS-Uebergaenge
      im versteckten Fenster scheitern (CLAUDE.md, Falle 3). Der Rahmen stand
      also die ganze Blende ueber LEER da und fing erst an zu zeichnen, als
      er sichtbar wurde. Was man sah, war kein Aufblenden, sondern ein
      Erscheinen am Ende.
   2. EINE OPACITY AUF EINEM IFRAME IST TEUER. Sie zwingt den Browser, den
      Inhalt je Bild neu zu mischen, statt eine fertige Ebene zu schieben —
      und eine WebGPU-Leinwand darin ist der denkbar schlechteste Fall.

   Jetzt wird stattdessen der SCHWARZE LADESCHIRM DARUEBER weggeblendet. Der
   Rahmen ist von Anfang an sichtbar (und zeichnet damit auch von Anfang an,
   was das Vorwaermen erst wirksam macht); was verblasst, ist eine
   einfarbige Flaeche — das schiebt die Grafikkarte ohne Zutun des Hauptfadens
   und wird darum wirklich stufenlos. */
.hero--kulisse .hero__diorama {
  opacity: 1;
}
/* Springt das Gemaelde ein, bleibt der Rahmen unsichtbar — er koennte sich
   spaeter noch melden, und dann soll er sich nicht dazwischenschieben. */
.hero--kulisse.hero--gemaelde .hero__diorama {
  opacity: 0;
}

.hero__laden {
  position: absolute;
  inset: 0;
  /* GANZ SCHWARZ, nicht das #0d1013 des Spiel-Ladeschirms (Ansage
     29.08.2026). Die Kulisse blendet daraus auf; ein Grauton dazwischen liest
     sich als Schleier, der nicht ganz weggeht. */
  background: #000;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  /* Der Balken sitzt UNTEN, nicht in der Mitte: Dort steht das
     Anmeldeformular, und ein Balken dahinter waere entweder verdeckt oder im
     Weg. */
  padding-bottom: 12vh;
  /* DIE EINZIGE BLENDE, die es noch gibt: Der Ladeschirm liegt UEBER dem
     Rahmen, sein Verblassen legt die Kulisse frei (siehe .hero__diorama).

     LINEAR und nicht `ease`: Eine Abblende ist eine gleichmaessige Bewegung.
     Mit `ease` steht sie am Anfang und am Ende fast still und geht in der
     Mitte schnell — das liest sich als Ruck, gerade bei drei Sekunden. */
  transition: opacity var(--kulisse-blende, 3s) linear;
  /* EIGENE EBENE fuer die Blende. Ohne das mischt der Browser die Flaeche je
     Bild neu in die Seite — mit einer WebGPU-Leinwand darunter ist das genau
     die Arbeit, die auf dem Hauptfaden ruckelt. Mit `will-change` bekommt
     sie eine Ebene auf der Grafikkarte, und das Verblassen ist dann ein
     Schieberegler dort statt einer Rechnung hier.

     Vertretbar, obwohl `will-change` sonst sparsam gehoert: Dieses Element
     lebt genau so lange wie die Blende und wird danach aus dem Baum genommen
     (kulisse-laden.js). */
  will-change: opacity;
  pointer-events: none;
}
.hero--bereit .hero__laden,
.hero--gemaelde .hero__laden {
  opacity: 0;
}

/* MASSE VOM LADESCHIRM (`#laden-balken`) — vier Punkte hoch, messingfarben.
   Nur die Breite ist kleiner: Dort steht der Balken unter einem 620 Punkte
   breiten Bild und gehoert dazu; hier steht er allein. */
/* DER BALKEN ERLISCHT, WAEHREND ER SICH FUELLT (Ansage 29.08.2026: „dass der
   ladebalken mit fortschritt ausgeblendet wird bzw immer dunkler wird").
   `--fortschritt` setzt kulisse-laden.js bei jeder Meldung; die Deckkraft
   folgt daraus.

   NICHT BIS AUF NULL, sondern auf ein Fuenftel: Ein Balken, der schon bei
   90 % unsichtbar ist, kann nicht mehr zeigen, DASS er haengt — und genau
   dafuer steht er da (siehe den Kopf von kulisse-laden.js). Ganz weg ist er
   erst, wenn es wirklich fertig ist; das setzt das Skript dann eigens.

   Der Uebergang gehoert dazu: Die Meldungen kommen in Spruengen, und ohne
   ihn saehe man das Dunklerwerden als Stufen. Dieselbe Viertelsekunde wie
   die Breite darunter, damit beide als EINE Bewegung lesen. */
.hero__balken {
  width: min(320px, 60vw);
  height: 4px;
  background: #1a1f24;
  border: 1px solid #2c3138;
  border-radius: 2px;
  overflow: hidden;
  opacity: calc(1 - 0.8 * var(--fortschritt, 0));
  /* Kurz, nicht viertelsekundenlang: `--fortschritt` kommt seit dem Takt
     ohnehin glatt herein (alle 16 ms), der Uebergang glaettet nur noch den
     letzten Sprung auf null, den das Skript beim Fertigwerden setzt. */
  transition: opacity 0.12s linear;
}
/* KEIN Uebergang auf der Breite: Sie wird seit dem 29.08.2026 im Takt
   gestellt (kulisse-laden.js, alle 16 ms ein Stueck naeher am gemeldeten
   Stand). Ein Uebergang darueber liefe der Rechnung hinterher und machte aus
   der glatten Bewegung ein Nachziehen. Den letzten Zug auf hundert Prozent
   setzt das Skript selbst mit einem eigenen, kurzen Uebergang. */
.hero__balken > div {
  height: 100%;
  width: 0;
  background: #a8813d;
}
/* `.hero__motto` („ANNO DOMINI 1157") ist am 29.08.2026 entfallen: Der Kopf
   traegt jetzt Titel und Ort wie der Ladeschirm, und die Unterzeile heisst
   `.hero__ort` (weiter oben). Wer die alte Fassung sucht, findet sie in der
   Historie dieses Tages. */

/* 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: auto;
  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. */
/* DAS BURGDIORAMA — die 3D-Kulisse hinter der Anmeldung (client/diorama.html,
   eingehängt von opener.ts). Sie liegt ÜBER dem Gemälde und deckt es mit ihrem
   eigenen Himmel zu.

   Das Gemälde bleibt trotzdem darunter liegen, und das ist Absicht: Der iframe
   ist durchsichtig, bis sein Skript läuft. Ohne WebGPU, ohne Modelle oder mit
   abgebrochenem Client-Bau bleibt er es — und die Anmeldeseite sieht aus wie
   immer, statt schwarz zu sein. Ein Rückfall, der ohne Pflege trägt.

   `pointer-events: none` kommt schon von `.hero`, wird hier aber wiederholt:
   Ein iframe fängt Mausereignisse sonst selbst ab, und der Erbwert des Eltern-
   elements gilt für ihn nicht. Ohne die Zeile schluckt die Kulisse jeden
   Klick, der neben dem Anmeldeformular landet — und markiertes Wort für Wort
   nichts mehr. */
.hero__diorama {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  pointer-events: none;
  /* VOLL DECKEND, und das war ein gemessener Fehlgriff: Hier stand 0,92, damit
     die Kulisse als Hintergrund zurücktritt. Durch die fehlenden acht Prozent
     schien aber das GEMÄLDE durch, das absichtlich darunter liegen bleibt —
     im Bild standen Türme und ein Baukran quer über dem Abendhimmel des
     Dioramas, und das las sich als Fehler, nicht als Zurückhaltung.
     Zurückgenommen wird die Kulisse über `.hero__schleier`, der ohnehin über
     ihr liegt; er dunkelt, ohne ein zweites Bild hervorzuholen. */
  opacity: 1;
}

.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);
}

/* --- DIE TAFEL OHNE KASTEN (11.09.2026) -----------------------------------
   Ansage des Bauherrn: „schmeiss das 3d aus dem anmeldebildschirm raus und
   auch den schaukasten und fuege nur favorit.jpg ein".

   Hinter der Anmeldung steht seither ein GEMALTES Bild und keine 3D-Kulisse
   mehr. Ein Kasten davor deckt genau die Stelle zu, auf die es ankommt — die
   Felder stehen jetzt frei im Bild.

   WAS DER KASTEN GETRAGEN HAT, MUSS JETZT DIE SCHRIFT SELBST TRAGEN. Er war
   der dunkle Grund, auf dem die Beschriftung lesbar war; ohne ihn steht sie
   vor einem HELLEN Himmel. Und eine Schrift vor der Landschaft braucht eine
   KONTUR, keinen weichen Schein (CLAUDE.md, am Kopfband gemessen): Ein
   weicher Schatten loest sich vor gleich heller Flaeche auf, vier versetzte
   dunkle Kopien legen eine harte Kante um jeden Buchstaben.

   Zurueck zum Kasten ist eine Zeile: in server.ts die Klasse panel--frei
   weglassen. */
body.mit-hero .panel--frei {
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  backdrop-filter: none;
  padding: 0;
}
/* Die vier Nieten in den Ecken gehoeren zum Kasten (.panel::before). */
body.mit-hero .panel--frei::before {
  display: none;
}

body.mit-hero .panel--frei label {
  color: #f2e4c4;
  text-shadow:
    -1px -1px 0 rgba(0, 0, 0, 0.85),
    1px -1px 0 rgba(0, 0, 0, 0.85),
    -1px 1px 0 rgba(0, 0, 0, 0.85),
    1px 1px 0 rgba(0, 0, 0, 0.85),
    0 3px 12px rgba(0, 0, 0, 0.55);
}

/* Die Felder bleiben DUNKEL, und zwar mit Absicht: Ein Eingabefeld muss als
   Loch zu erkennen sein, in das man schreibt. Sie lassen das Bild nur ahnen
   (72 % Deckung) und tragen den Messingrand des Knopfes, damit Feld und Knopf
   als EIN Ding gelesen werden, das im Bild liegt. */
body.mit-hero .panel--frei input[type="text"],
body.mit-hero .panel--frei input[type="password"] {
  background: rgba(9, 11, 14, 0.86);
  border-color: rgba(120, 93, 43, 0.85);
  color: #f4e8cf;
  box-shadow:
    inset 0 2px 6px rgba(0, 0, 0, 0.6),
    0 3px 14px rgba(0, 0, 0, 0.45);
}
body.mit-hero .panel--frei input[type="text"]:focus,
body.mit-hero .panel--frei input[type="password"]:focus {
  border-color: var(--brass-light);
}

/* Der Nebenweg („Noch nicht in der Rolle?") und die Fehlermeldung stehen
   genauso frei — aber NICHT mit derselben Kontur.

   Die harte Kontur gilt fuer die Beschriftungen: Versalien, weit gesperrt,
   kraeftig genug, dass eine Kante von einem Bildpunkt sie nicht zusetzt.
   Dieser Satz hier ist kleine Antiqua mit duennen Haarstrichen — die
   verschluckt eine 1-px-Kontur ringsum, der Text wird matschig statt
   lesbar. Am 1920er Bild nachgesehen: erst dieser gestaffelte dunkle Hof
   liest sich sauber. Er widerspricht der Kopfband-Regel nicht, sondern
   grenzt sie ein: Dort ging es um GLEICH HELLE Flaechen (Gruen auf Gruen),
   hier steht fast weisse Schrift ueber mittlerem Gruen. */
body.mit-hero .panel--frei .muted,
body.mit-hero .panel--frei .error {
  color: #f1e6cd;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.95),
    0 0 5px rgba(0, 0, 0, 0.9),
    0 0 11px rgba(0, 0, 0, 0.75);
}
body.mit-hero .panel--frei .error {
  color: #f0b9a0;
}
body.mit-hero .panel--frei a {
  color: #f0d79a;
}

/* MIT GOOGLE ANMELDEN (26.09.2026, server.ts /login) — im Stil des Knopfes
   „Einlass begehren“ (body.mit-hero form button[type="submit"] weiter unten),
   Ansage des Bro: „im selben stil … wie das einlass begehren und das google
   logo ist so metalleingedrückt“, danach beide „in so dunkelgrau“. Das „G“ ist
   EINFARBIG und dunkler als das Eisen, mit einer hellen Lichtkante unten und
   einem Schatten oben — so liest es sich als ins Blech geprägt. Die Füllung
   kommt aus CSS und sticht die Farben im SVG. Wer den Knopf darunter umfärbt,
   färbt diesen mit. */
body.mit-hero .panel--frei a.google-knopf,
a.google-knopf {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  width: 100%;
  max-width: 340px;
  margin: 0 auto 0.2rem;
  padding: 0.45rem 0.8rem;
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #f2e8d4;
  text-decoration: none;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.55);
  background: linear-gradient(180deg, #33383f, #1d2024);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  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;
  cursor: var(--cursor-gold);
}
body.mit-hero .panel--frei a.google-knopf:hover,
a.google-knopf:hover {
  color: #f2e8d4;
  background: linear-gradient(180deg, #414850, #262a2f);
  border-color: var(--brass);
  box-shadow: 0 0 18px rgba(0, 0, 0, 0.45);
}
a.google-knopf:active {
  transform: translateY(1px);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.55);
}
a.google-knopf .google-g {
  width: 1.1rem;
  height: 1.1rem;
  flex: none;
  filter:
    drop-shadow(0 1px 0 rgba(220, 225, 232, 0.32))
    drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.6));
}
a.google-knopf .google-g path { fill: #121416; }
/* Noch nicht freigeschaltet (GOOGLE_ANMELDUNG_OFFEN, googleAnmeldung.ts): kein
   Link, sondern ein grauer Knopf mit „ab November“ — dieselbe Form, damit
   nichts springt, wenn er im November scharf wird. */
.google-knopf.google-knopf--grau {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  width: 100%;
  max-width: 340px;
  margin: 0 auto 0.2rem;
  padding: 0.45rem 0.8rem;
  box-sizing: border-box;
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #9a948a;
  background: linear-gradient(180deg, #2a2d31, #1b1d20);
  border: 1px solid #4a4d52;
  border-radius: 2px;
  cursor: var(--cursor-kupfer);
  user-select: none;
}
.google-knopf--grau .google-g { width: 1.1rem; height: 1.1rem; flex: none; opacity: 0.55; }
.google-knopf--grau .google-g path { fill: #0e0f11; }
.google-knopf--grau small {
  font-size: 0.72em;
  font-weight: 400;
  letter-spacing: 0.04em;
  color: #7d786f;
}
/* „oder mit Losungswort“ — eine Linie mit Wort in der Mitte. */
.anmelde-trenner {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  max-width: 340px;
  margin: 1rem auto 0.8rem;
  font-size: 0.7rem;
  color: #f1e6cd;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.95), 0 0 5px rgba(0, 0, 0, 0.9);
}
.anmelde-trenner::before,
.anmelde-trenner::after {
  content: "";
  flex: 1;
  height: 1px;
  background: rgba(241, 230, 205, 0.45);
}

/* Auf dem Startbildschirm ist der Knopf die Hauptsache: volle Breite.
   SEIT DEM 26.09.2026 DUNKELGRAU statt Messing (Ansage des Bro: „können wir die
   einlass begehren und mit google anmelden doch in so dunkelgrau machen?“) —
   das Eisen der übrigen Knöpfe, etwas dunkler, mit dem Messingrand. Der
   Google-Knopf darüber trägt dieselben Werte (a.google-knopf). */
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, #33383f, #1d2024);
  border-color: var(--brass-dark);
  color: #f2e8d4;
}
body.mit-hero form button[type="submit"]:hover {
  background: linear-gradient(180deg, #414850, #262a2f);
  border-color: var(--brass);
  box-shadow: 0 0 18px rgba(0, 0, 0, 0.45);
}

@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: var(--cursor-kupfer);
}
.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. */
/* LINKS seit dem 29.09.2026, an der Stelle der Gebaeudetafel (es ist immer
   nur eine der beiden offen): Oben rechts steht der Meldestapel, und ein
   Raeuberlager lag dort ueber dem Kreuz zum Schliessen. */
#bewohnerpanel {
  top: 3.6rem;
  left: 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: auto;
  flex: none;
}
/* DIE BUESTE (10.09.2026) — das Portrait aus den KI-Vorlagen, aus denen auch
   die 3D-Modelle entstanden sind (scripts/bewohner-portraits.mjs).

   RUND, weil die Figur im Bild auf einem runden Untersatz steht
   (figuren3d.ts): Tafel und Hof sollen dieselbe Form sprechen.

   KEIN `image-rendering: pixelated`, anders als beim Sprite darueber — das
   Portrait ist ein gerendertes Bild und wuerde davon stufig. Der Ring aussen
   ist dieselbe Farbe wie die Auswahlkontur der Gebaeude, nur gedaempft. */
.bp-portrait {
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.28),
    0 2px 6px rgba(0, 0, 0, 0.5);
}
/* DAS GEMALTE BERUFSPORTRAIT (13.09.2026) — je Beruf eines, im Stil der
   Bildnisse der Burgherren (config/asset-sets/berufsportraits.json).

   Derselbe Kreis und derselbe Ring wie die Büste darüber, aber ein anderer
   Zuschnitt, und darum ein Rahmen statt `object-fit`: Das Bild ist ein
   FREIGESTELLTES Brustbild, oben bis an den Scheitel beschnitten
   (build-charakter-sprites.js). Mit `cover` stiesse der Kopf oben an den
   Kreis, und die Schultern füllten die halbe Fläche. So steht das Gesicht in
   der Mitte, und die Schultern laufen unten hinaus — wie bei den Büsten, für
   die es hiess: „mehr auf das gesicht zoomen" (10.09.2026).

   Der Grund kommt von hier, weil das Bild keinen hat: dunkel und warm, hinter
   dem Kopf eine Spur heller, damit sich dunkles Haar und Kapuzen noch vom
   Kreis lösen. */
.bp-bildnis {
  position: relative;
  width: 64px;
  height: 64px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: radial-gradient(circle at 50% 34%, #5a5044 0%, #2e2822 52%, #171411 100%);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.28),
    0 2px 6px rgba(0, 0, 0, 0.5);
}
.bp-bildnis img {
  position: absolute;
  left: 50%;
  top: 6%;
  width: 122%;
  transform: translateX(-50%);
}
/* Die Bildnisse der Herrschaft sind seit dem 25.09.2026 HALBFIGUREN bis zum
   Gürtel, mit beiden Armen — der Kopf steht im oberen Drittel. Mit dem Zoom
   der Büsten säße ein daumennagelgroßes Gesicht im Kreis. */
.bp-bildnis.bp-halbfigur img {
  top: 4%;
  width: 210%;
}
.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;
  --schein: var(--iron);
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), 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 { --schein: #7fa663; }
.bp-stimmung.gut .bp-wort { color: #a9c795; }
.bp-stimmung.mittel { --schein: #8a7f5e; }
.bp-stimmung.schlecht { --schein: #b07a4a; }
.bp-stimmung.schlecht .bp-wort { color: #d3a273; }
.bp-stimmung.elend { --schein: #a34b3c; }
.bp-stimmung.elend .bp-wort { color: #d08a7a; }
/* DIE STIMMUNG IST EIN REITER (21.10.2026): ein Klick klappt darunter die
   Gründe heraus. Als Knopf ohne eigenes Aussehen, damit er die Zeile bleibt. */
button.bp-stimmung {
  width: 100%;
  border: 0;
  border-radius: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
button.bp-stimmung:hover { filter: brightness(1.2); }
.bp-pfeil {
  display: inline-block;
  width: 0.4rem;
  height: 0.4rem;
  margin-left: 0.5rem;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: translateY(-0.15rem) rotate(45deg);
  transition: transform 0.15s;
}
.bp-reiter[aria-expanded="true"] .bp-pfeil { transform: translateY(0.05rem) rotate(-135deg); }
.bp-gruende {
  padding: 0.3rem 0.5rem 0.35rem;
  background: rgba(0, 0, 0, 0.3);
  border-top: 1px solid var(--iron);
}
.bp-gruende[hidden] { display: none; }

/* 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,
blockquote.bp-gedanke {
  margin: 0;
  padding-left: 0.7rem;
  --schein: var(--brass-dark); background-image: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%);
  font-style: italic;
  color: var(--text);
}
blockquote.bp-gedanke { margin-top: 0.7rem; }
.bp-gedanke blockquote p,
blockquote.bp-gedanke p {
  margin: 0 0 0.4rem;
  line-height: 1.45;
}
.bp-gedanke blockquote p:last-child,
blockquote.bp-gedanke p:last-child { margin-bottom: 0; }

/* DIE SIEGELKARTE IN DER BEWOHNERTAFEL (29.09.2026) — Ritter und Herrschaft
   zeigen beim Anklicken ihre Karte (Ansage des Bro: „ritter anklickbar machen
   und es öffnet die karte des ritters"). Dieselbe Karte wie in der Standestafel
   (siegeltraeger.js); das × steht über ihr. Seit dem 18.10.2026 so groß wie
   auf dem Kriegstisch (Ansage des Bro: „die karte der ritter kleiner machen, so
   wie auf dem karten tisch“) — dieselben 13,5rem mal 0,85 wie `#heldenkarte`
   in karte3d.html. */
.bp-kartenkopf { display: flex; align-items: center; justify-content: space-between; }
.bp-kartenkopf .bp-was { margin: 0; }
.bp-karte { display: flex; justify-content: center; margin-top: 0.3rem; }
.bp-karte .sgt-platz { width: 13.5rem; zoom: 0.85; }
.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-zeile.bp-leise { padding-top: 0; font-size: 0.75rem; color: var(--text-dim); }

/* DIE STERNE EINES MENSCHEN (13.09.2026, client/src/sterne.ts) — sechs Plätze,
   auch die leeren. Der halbe Stern ist derselbe Buchstabe, zur Hälfte gefüllt:
   So bleiben alle sechs gleich breit, und kein Zeichen fehlt einer Schrift. */
.sterne { display: inline-flex; gap: 0.05rem; white-space: nowrap; line-height: 1; }
.stern { font-style: normal; color: rgba(146, 139, 125, 0.35); }
.stern.voll { color: #f3d27a; }
.stern.halb {
  background: linear-gradient(90deg, #f3d27a 50%, rgba(146, 139, 125, 0.35) 50%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
/* DER WACHSENDE STERN (21.10.2026, sterne.ts `waechst`) — der nächste Platz
   glimmt leise auf, solange der Mensch arbeitet bzw. übt. 2,4 s wie
   `STERN_WAECHST_MS`. */
.stern.leer.waechst { animation: stern-waechst-leer 2.4s ease-in-out infinite; }
.stern.halb.waechst { animation: stern-waechst-halb 2.4s ease-in-out infinite; }
@keyframes stern-waechst-leer {
  0%, 100% { color: rgba(146, 139, 125, 0.35); }
  50% { color: rgba(243, 210, 122, 0.55); }
}
@keyframes stern-waechst-halb {
  0%, 100% { filter: none; }
  50% { filter: brightness(1.45) drop-shadow(0 0 2px rgba(243, 210, 122, 0.6)); }
}
.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-kopf.tafelkopf { margin: -0.55rem -0.7rem 0.55rem; align-items: center; justify-content: flex-start; }
.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;
  --schein: var(--iron);
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(0, 0, 0, 0.3);
  border-radius: 1px;
  margin-bottom: 0.45rem;
}
.gp-status.gp-laeuft { --schein: #5d8a4f; color: #a8c79a; }
.gp-status.gp-stoerung { --schein: #9a6a3c; color: #d8ab7c; }
.gp-status.gp-bau { --schein: 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;
}

/* --- DER TURM DER AUSBAU-TAFEL (12.09.2026) -------------------------------
   Die Kachel dessen, was man bekommt — dasselbe Bild wie in der Klassenwahl
   (isometrisch aus Blender).

   Hier stand kurz ein PAAR mit Pfeil (jetzt → danach). Auf Ansage wieder
   heraus: Was jetzt dasteht, sieht der Spieler auf dem Hof — er hat gerade
   daraufgeklickt. */
.gp-tuerme {
  display: flex;
  justify-content: center;
  margin: 0.1rem 0 0.6rem;
}
.gp-turm {
  margin: 0;
  text-align: center;
}
.gp-turm img {
  display: block;
  width: 120px;
  height: auto;
  /* Der Renderer wirft keinen Schatten (durchsichtiger Grund), und ohne ihn
     steht der Turm auf nichts. */
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.55));
}
/* DIE ISOMETRIE EINES HAUSES IST QUADRATISCH, die Turmkachel hochkant
   (17.09.2026). Speicher, Waffenkammer und Palas zeigen in der Ausbau-Tafel
   ihr Menuebild aus `icons/3d/` — 256 x 256, mit Luft ringsum. Mit der Breite
   des Bergfrieds (120 px) stuende das Haus darin verloren; etwas groesser
   gefasst fuellt es dieselbe Zeile. */
.gp-turm-iso img {
  width: 132px;
}
.gp-turm figcaption {
  margin-top: 1px;
  font-size: 0.72em;
  letter-spacing: 0.1em;
  color: var(--brass-light);
}
/* 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); }
/* WAS DIE HUETTE UM SICH HERUM NOCH VORFINDET (12.09.2026).

   Ansage des Bauherrn: „gehört eigentlich nicht eine anzeige in die
   holzfäller hütte oder wald hütte wie viele diese an rohstoffe abholzen
   oder jagen/ernten kann?"

   Heller als ein Hinweis und dunkler als eine Zahl: Es ist eine AUSKUNFT,
   keine Mahnung — der Betrieb ist in Ordnung, hier steht nur, wie lange
   noch. Die Zahlen darin stehen fett, der Rest nicht; so liest man die
   Zeile im Vorbeigehen. */
.gp-waldvorrat {
  margin: 0.3rem 0 0;
  padding: 0.22rem 0.4rem;
  --schein: var(--brass-dark);
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(255, 255, 255, 0.035);
  color: var(--text);
  font-size: 0.82rem;
  line-height: 1.35;
}
.gp-waldvorrat b { color: var(--brass-light); font-weight: 600; }

/* DAS FELDJAHR DES GUTSHOFS (17.10.2026, client/src/feldjahrTafel.ts): eine
   Zeile mit dem laufenden Schritt und der erwarteten Ernte, aufgeklappt die
   vier Schritte mit Monaten, Balken und dem Strich, wo der Schritt beim
   heutigen Tempo endet. */
.gp-feldjahr {
  margin: 0.3rem 0 0;
  border: 1px solid rgba(109, 84, 38, 0.55);
  background: rgba(0, 0, 0, 0.22);
}
.gp-fj-kopf {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.28rem 0.45rem;
  cursor: var(--cursor-gold);
  list-style: none;
  font-size: 0.82rem;
}
.gp-fj-kopf::-webkit-details-marker { display: none; }
.gp-fj-kopf::before {
  content: "▸";
  color: var(--brass);
  flex: none;
}
.gp-feldjahr[open] > .gp-fj-kopf::before { content: "▾"; }
.gp-fj-kopf:hover { background: rgba(168, 129, 61, 0.12); }
.gp-fj-titel { color: var(--brass-light); flex: none; }
.gp-fj-jetzt { color: var(--text); flex: 1 1 auto; }
.gp-fj-ernte { flex: none; color: var(--text-dim); }
.gp-fj-ernte b { color: var(--brass-light); font-weight: 600; }
.gp-fj-von { color: var(--text-dim); }
/* EIN Raster für alle vier Zeilen (die Zeilen sind `display: contents`), damit
   Monate, Balken und Zahlen untereinander stehen, wie breit die Tafel auch ist. */
.gp-fj-schritte {
  border-top: 1px solid rgba(109, 84, 38, 0.4);
  padding: 0.25rem 0.45rem 0.4rem;
  display: grid;
  grid-template-columns: max-content max-content minmax(2.5rem, 1fr) max-content;
  align-items: center;
  column-gap: 0.5rem;
  row-gap: 0.2rem;
  font-size: 0.8rem;
}
.gp-fj-schritt {
  display: contents;
  color: var(--text-dim);
}
.gp-fj-schritt.jetzt { color: var(--text); }
.gp-fj-schritt.jetzt .gp-fj-name { color: var(--brass-light); }
.gp-fj-monate { font-size: 0.74rem; }
.gp-fj-wert { text-align: right; font-variant-numeric: tabular-nums; }
.gp-fj-balken {
  position: relative;
  height: 0.5rem;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(0, 0, 0, 0.5);
}
.gp-fj-balken > i {
  position: absolute;
  inset: 0 auto 0 0;
  background: linear-gradient(180deg, #b8934e, #7d5f2c);
}
/* Der Strich: wo der Schritt am Ende seiner Monate steht. */
.gp-fj-balken > b {
  position: absolute;
  top: -0.2rem;
  bottom: -0.2rem;
  width: 2px;
  margin-left: -1px;
  background: #f1e3c4;
}
.gp-fj-schritt.knapp .gp-fj-balken > b { background: #d8774f; }

.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; }
/* Ein Arbeitername bleibt einzeilig; zu lang, kürzt ihn das Skript auf den Vornamen. */
.gp-name.gp-kurzbar {
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
}
.gp-koennen {
  flex: none;
  color: var(--brass);
  letter-spacing: 0.1em;
  font-size: 0.78rem;
}
/* „abziehen" und „zuweisen" sind gleich groß und stehen in derselben Spalte. */
.gp-ab,
.gp-zuweis {
  flex: none;
  box-sizing: border-box;
  width: 5.2rem;
  background: none;
  border: 1px solid var(--iron);
  color: var(--text-dim);
  border-radius: 2px;
  padding: 0.05rem 0;
  text-align: center;
  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,
.gp-zuweis:disabled { opacity: 0.5; cursor: var(--cursor-kupfer); }
.gp-zuweis {
  background: linear-gradient(180deg, #6d5426, #43341a);
  border-color: var(--brass);
  color: #f7ecd6;
}
.gp-zuweis:hover:not(:disabled) { border-color: var(--brass-light); }

.gp-zuweisen {
  display: flex;
  justify-content: flex-end;
  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);
}
/* Das Schloss der Freischaltkette (14.10.2026) im gesperrten Ausbau-Knopf. */
.gp-btn .gp-schloss {
  width: 1.4em;
  height: 1.4em;
  vertical-align: middle;
}
.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;
}
/* Der Schlagbereich der Holzfällerhütte (21.09.2026): zwei Knöpfe
   nebeneinander, der gültige in Messing — wie die gewählte Betriebsart. */
.gp-knopfreihe {
  display: flex;
  gap: 0.35rem;
  margin-top: 0.3rem;
}
.gp-knopfreihe .gp-btn {
  flex: 1;
  padding: 0.3rem 0.5rem;
}
.gp-knopfreihe .gp-btn.aktiv {
  border-color: var(--brass);
  color: var(--brass-light);
  background: rgba(109, 84, 38, 0.26);
}
/* RADIUS ODER BEREICH (21.10.2026, Ansage des Bro: „Radius bereich wählen nicht
   als goldene buttosn bitte“): eine Wahl wie im Einstellungsfenster — EINE Leiste
   gleich breiter Felder mit Haarlinien, dunkel, die gewählte leicht erhellt. */
.gp-schlag .gp-knopfreihe {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 0;
  border: 1px solid var(--iron);
  border-radius: 2px;
  overflow: hidden;
}
.gp-schlag .gp-knopfreihe .gp-btn {
  width: 100%;
  height: 1.75rem;
  padding: 0;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--iron);
  border-radius: 0;
  box-shadow: none;
  color: var(--text-dim);
  font-size: 0.8rem;
  text-align: center;
}
.gp-schlag .gp-knopfreihe .gp-btn:first-child { border-left: 0; }
.gp-schlag .gp-knopfreihe .gp-btn:hover:not(:disabled) {
  background: rgba(168, 129, 61, 0.12);
  color: #f0dfb4;
  box-shadow: none;
}
.gp-schlag .gp-knopfreihe .gp-btn.aktiv {
  background: rgba(168, 129, 61, 0.3);
  color: #f0dfb4;
}
/* Die Axt am Gutshof (17.10.2026): rot wie `button.gefahr`, nur das Zeichen
   des Abriss-Werkzeugs, so breit wie hoch. */
.gp-knopfreihe .gp-btn.gp-axt {
  flex: none;
  display: grid;
  place-items: center;
  padding: 0.15rem 0.35rem;
  border-color: var(--blood);
  background: linear-gradient(180deg, #52302a, #331d19);
}
.gp-knopfreihe .gp-btn.gp-axt:hover:not(:disabled) {
  border-color: #d06a4e;
  background: linear-gradient(180deg, #7a4334, #4a271f);
  box-shadow: 0 0 10px rgba(208, 106, 78, 0.45);
}
.gp-btn.gp-axt img {
  width: 1.6em;
  height: 1.6em;
}
.gp-btn.gp-axt:hover:not(:disabled) img {
  filter: brightness(1.3);
}

/* ===========================================================================
   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 dieselbe Darstellung 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.

   GLATT, NICHT PIXELIG (12.09.2026). Hier stand „derselbe Pixel-Stil" und
   `image-rendering: pixelated`. Die Ladebilder sind aber seit dem 08.09.2026
   gemalte Konzeptkunst (LADEBILD_RAHMEN) — gezeigt wurden sie seither mit
   Nearest-Neighbour, also mit Treppen an jedem Pinselstrich. Aufgefallen ist
   es erst an den Ereignisbildern, als deren Striche gröber wurden. */
#ladeschirm .lade-bild,
#wechselschirm .lade-bild {
  display: block;
  /* Das dritte Glied deckelt die HOEHE: Bei 640/288 ist die Bildhoehe
     Breite/2,22, also haelt `100vh` sie unter 45 % der Fensterhoehe. Seit der
     Schirm eine Zeile mehr traegt (der Ort unter dem Titel) ist das kein
     Luxus mehr — er hat keinen Bildlauf, er ist `position: fixed; inset: 0`. */
  width: min(620px, 88vw, 100vh);
  aspect-ratio: 640 / 288;
  object-fit: cover;
  image-rendering: auto;
  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; }

/* Der Titel traegt seit dem 29.08.2026 den VOLLEN Namen ("Burgherr: A.D. 1157"),
   und darunter steht der Ort. Reihenfolge wie beim Ladeschirm der 3D-Seite:
   WAS, WO, dann das Bild, das einen dorthin setzt.

   `clamp` statt der festen 3.2rem, und das ist keine Feinheit: Der neue Titel
   ist mehr als doppelt so lang wie das alte "Burgherr", und in einer
   gebrochenen Schrift baut er breit. Auf einem schmalen Fenster braeche eine
   feste Groesse die Zeile mitten im Namen um.

   KLEINER seit dem 29.08.2026 (auf Ansage), von 1.9/7vw/4.2 herunter: Der
   erste Wurf trat gegen das Bild darunter an, statt es anzukuendigen. Ein
   Ladeschirm hat EIN Blickfang, und das ist die Vignette — der Name sagt nur,
   wessen sie ist. */
#ladeschirm .lade-titel,
#wechselschirm .lade-titel {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 4.6vw, 2.8rem);
  line-height: 1.1;
  color: var(--brass-light, #cca75e);
  letter-spacing: 0.02em;
  text-align: center;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.7);
}

/* Der Ort unter dem Namen: klein, weit gesperrt, gedaempft. Er soll den Titel
   EINORDNEN und nicht mit ihm um die Aufmerksamkeit ringen — und weit gesperrt
   liest sich eine kurze Zeile als Unterzeile statt als abgeschnittener
   zweiter Titel.

   Der negative obere Abstand holt ihn gegen das `gap: 0.9rem` von .lade-innen
   an den Titel heran: Titel und Ort gehoeren zusammen, das Bild ist das
   naechste Ding. Gleiche Abstaende ueberall machten aus drei Teilen eine
   Liste. */
#ladeschirm .lade-ort,
#wechselschirm .lade-ort {
  margin: -0.55rem 0 0.1rem;
  font-family: var(--font-body, inherit);
  font-size: clamp(0.8rem, 2.2vw, 1.05rem);
  letter-spacing: 0.42em;
  /* Die Sperrung schiebt JEDEN Buchstaben nach rechts, auch den letzten —
     ohne den Ausgleich stuende die Zeile sichtbar links von der Mitte. */
  text-indent: 0.42em;
  text-transform: uppercase;
  color: var(--text-dim, #928b7d);
  text-align: center;
}
/* --- 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, 100vh);
  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;
}
/* WAS DIE STIMMUNG BEDEUTET — die Sprosse der Stimmungsleiter, ganz oben in
   der Tafel (14.09.2026, Ansage des Bro: „kannst du auch bitte bei dem
   stimmungsfenster schreiben so atmosphärisch"). Ueberschrift in der Schrift
   des Ladeschirms, darunter ein Satz aus der Burg und der Satz zum Zuzug.
   Der Strich links traegt die Farbe des Knopfs — dieselben vier Klassen
   (stimmungsKlasse), damit Knopf und Tafel dieselbe Aussage machen. */
.moralstufe {
  margin: 0 0 0.6rem;
  padding: 0.4rem 0.6rem 0.5rem;
  --schein: var(--iron);
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(0, 0, 0, 0.2);
  font-size: 0.88rem;
  line-height: 1.4;
  color: var(--parchment);
}
.moralstufe-name {
  display: block;
  margin-bottom: 0.1rem;
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: normal;
  letter-spacing: 0.02em;
  color: var(--brass-light);
}
.moralstufe.gut      { --schein: var(--moss); }
.moralstufe.schlecht { --schein: var(--fire-light); }
.moralstufe.elend    { --schein: #f0c9bd; }
.moralstufe .moralzuzug {
  color: var(--text);
}

/* === 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: var(--cursor-gold);
  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);
}

/* Der Ablass an der Kapelle (gebaeudePanel.ts, ablassBlock): je Abzug eine
   Zeile mit Grund, Schwere und Restzeit, darunter der Knopf mit dem Preis. */
.gp-ablass {
  margin: 0.45rem 0 0.6rem;
}
.gp-ablass-grund {
  font-size: 0.85rem;
  margin-bottom: 0.25rem;
}
.gp-ablass-grund .stufe-moral {
  font-size: 0.76rem;
  font-variant-numeric: tabular-nums;
  margin-left: 0.3rem;
}
.gp-ablass-grund .stufe-moral.drueckt {
  color: var(--fire-light);
}
.gp-ablass-grund small {
  display: block;
  opacity: 0.75;
}

/* ===========================================================================
   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".
   =========================================================================== */
/* DER KALENDERPLATZ. Er umschliesst das Datum — und trug bis zum 29.08.2026
   die Tagesuhr daneben, die auf Ansage entfernt wurde.

   Er bleibt, weil an ihm die ZEITRECHNUNGS-TAFEL haengt: `position: relative`
   ist ihr Bezug, und sie muss ein GESCHWISTER des Datums sein, damit der
   Waehler `#calendar:hover ~ .datumstafel` sie findet. */
.kalenderplatz {
  position: relative; /* Bezug fuer die Zeitrechnungs-Tafel */
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  min-width: 0;
}
/* 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; }
/* Die Tafel des Anbindepfostens (16.10.2026, gebaeudePanel.ts `renderPfosten`):
   das Pferd als Zeichen vor dem Namen, so gross wie die Zeile. */
.gp-pfostentier-bild { flex: none; width: 22px; height: 22px; }
.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;
}
/* DER OCHSENKAUF AM BETRIEB (14.10.2026, Vorschlag B aus
   Ochsenkauf-Beispiel.html): ein Knopf, das Tier groß, rechts Münzen und Preis. */
.gp-tierkauf {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  margin: 0.35rem 0 0.45rem;
}
.gp-tierkauf-knopf {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  padding: 0.25rem 0.5rem 0.25rem 0.3rem;
  font: inherit;
  color: #f7ecd6;
  background: linear-gradient(180deg, #6d5426, #43341a);
  border: 1px solid var(--brass);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.gp-tierkauf-knopf:hover:not(:disabled) {
  border-color: var(--brass-light);
  box-shadow: 0 0 10px rgba(168, 129, 61, 0.35);
}
.gp-tierkauf-knopf:disabled {
  background: var(--stone-700);
  border-color: var(--iron);
  color: var(--text-dim);
  cursor: var(--cursor-kupfer);
}
.gp-tierkauf-knopf:disabled img { filter: grayscale(0.8) brightness(0.7); }
.gp-tierkauf-tier { width: 36px; height: 36px; }
.gp-tierkauf-name { flex: 1; text-align: left; font-size: 0.9rem; }
.gp-tierkauf-preis {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.gp-tierkauf-preis img { width: 24px; height: 24px; }
.gp-tierkauf-knopf.fehlt .gp-tierkauf-preis { color: #d0866f; }
/* GEKAUFT UND UNTERWEGS (14.10.2026, tierlieferung.ts): ein Balken unten im
   Kaufknopf, bis das Tier da ist; die Laenge setzt gebaeudePanel.ts. */
.gp-unterwegs { position: relative; overflow: hidden; }
.gp-unterwegs:disabled img { filter: none; }
.gp-lieferbalken {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 3px;
  background: rgba(0, 0, 0, 0.45);
  pointer-events: none;
}
.gp-lieferbalken > i {
  display: block;
  height: 100%;
  background: var(--brass-light);
  transform-origin: left center;
  animation-name: gp-liefern;
  animation-timing-function: linear;
  animation-fill-mode: both;
}
@keyframes gp-liefern {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
/* Der gekaufte Ochse: so breit wie der Kaufknopf, aber kein Knopf. */
.gp-tierkauf-steht {
  cursor: var(--cursor-kupfer, default);
  color: var(--text);
  background: rgba(0, 0, 0, 0.25);
  border-color: var(--brass-dark);
}
.gp-tierkauf-steht .gp-tier-zustand { flex: none; }
/* Abgeben und Schlachten als richtige Knöpfe (14.10.2026, Ansage des Bro:
   „schlachten und x als buttons machen") — kleine Messingkacheln. */
.gp-tierkauf-steht .gp-mini {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  font-size: 0.95rem;
  color: var(--text);
  background: linear-gradient(180deg, rgba(109, 84, 38, 0.45), rgba(67, 52, 26, 0.45));
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
}
.gp-tierkauf-steht .gp-mini:hover:not(:disabled) {
  color: #f7ecd6;
  border-color: var(--brass-light);
  box-shadow: 0 0 8px rgba(168, 129, 61, 0.35);
}
.gp-tierkauf-steht .gp-schlachten:hover:not(:disabled) {
  background: rgba(142, 51, 34, 0.35);
  border-color: #b0503a;
  box-shadow: 0 0 8px rgba(176, 80, 58, 0.35);
}

.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: auto;
  /* 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);
}
/* Vor dem Startbild steht er auf gemaltem Gras statt auf Stein (11.09.2026,
   seit der Kasten weg ist und das Bild hell). Derselbe gestaffelte dunkle Hof
   wie bei der Kleinschrift der Anmeldung — gedaempft bleibt er trotzdem: Er
   ist der Nebenweg, nicht der Eingang. */
body.mit-hero .reinschauen {
  color: #e4d6b6;
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.95),
    0 0 5px rgba(0, 0, 0, 0.9),
    0 0 11px rgba(0, 0, 0, 0.7);
}
@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%;
  }
}

/* --- Die Kammer ---------------------------------------------------- */
.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 Kammer.
   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; }
}

/* --- 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,
#tiertafel,
#tastentafel {
  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],
#tiertafel[hidden],
#tastentafel[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-kopf.tafelkopf { margin: -1.1rem -1.3rem 0.8rem; align-items: center; }
.wt-kopf.tafelkopf .wt-wert { line-height: 1; }
.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); }
/* DIE WARE SPRICHT (21.10.2026, warenspruch.ts): das Stillleben der Ware
   verdunkelt über die ganze Breite gleich unter dem Kopf, darauf der Spruch. */
.wt-spruch {
  position: relative;
  margin: -0.8rem -1.3rem 0.9rem;
  padding: 0 1.4rem 0.9rem;
  /* Das GANZE Bild (Ansage des Bro: „so skalieren dass das bild komplett drauf
     passt“): das Feld trägt das Seitenverhältnis der Stillleben (1280 × 576,
     build-stillleben.js), dann schneidet `cover` nichts ab. Die Datei hat die
     doppelte Breite der Tafel — scharf auch auf hochauflösenden Schirmen. */
  aspect-ratio: 1280 / 576;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  background-size: cover;
  background-position: center;
  border-bottom: 1px solid var(--iron);
}
.wt-spruch::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(12, 13, 15, 0.12), rgba(12, 13, 15, 0.8) 72%);
}
.wt-spruch > * { position: relative; }
.wt-spruch blockquote {
  margin: 0;
  font-style: italic;
  line-height: 1.5;
  color: var(--parchment, #f0e2c0);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}
.wt-spruch figcaption {
  margin-top: 0.4rem;
  text-align: right;
  font-size: 0.9rem;
  color: var(--brass-light);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}
/* Teller und Löffel im Kopf der Warentafel (21.10.2026): gleich links neben
   dem Kreuz und genau so groß (Ansage des Bro: „essen button neben des
   schließen buttons“, „symbol muss kleiner wie das schließ symbol“); auf dem
   Tisch wie es ist, davon genommen durchgestrichen („vllt lieber
   durchgestrichen?“). */
button.wt-tisch-knopf.wt-tisch-knopf {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  margin-left: 0.6rem;
  padding: 0;
  /* Ohne Rahmen (Wahl des Bro aus vier Fassungen: „B“) — nur der Teller. */
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  cursor: var(--cursor-gold, pointer);
}
.wt-tisch-knopf img { width: 100%; height: 100%; object-fit: contain; opacity: 0.6; transition: opacity 0.15s, filter 0.15s; }
.wt-tisch-knopf.an img { opacity: 1; }
.wt-tisch-knopf:hover img { opacity: 1; filter: brightness(1.2); }
/* DER HAKEN (22.10.2026, Ansage des Bro: „mit einem hacken für aktiv und einem
   durchgestrichen für nicht freigegeben … und bei dem tellersymbol auch"):
   unten rechts ein grüner Haken, gezeichnet aus zwei Rändern. */
.wt-tisch-knopf.an::after {
  content: "";
  position: absolute;
  right: -1px;
  bottom: 3px;
  width: 0.32rem;
  height: 0.62rem;
  border: solid #6fbf4a;
  border-width: 0 3px 3px 0;
  transform: rotate(40deg);
  filter: drop-shadow(0 0 1px #000) drop-shadow(0 0 1px #000);
  pointer-events: none;
}
.wt-tisch-knopf:not(.an)::after {
  content: "";
  position: absolute;
  left: 10%;
  right: 10%;
  top: 50%;
  height: 2px;
  margin-top: -1px;
  background: #b0402c;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.75);
  transform: rotate(-45deg);
  pointer-events: none;
}
.wt-tisch {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.2rem 0 0.4rem;
  color: var(--brass-light);
  cursor: var(--cursor-gold, pointer);
}
.wt-tisch:hover { color: var(--parchment, #f0e2c0); }
.wt-tisch input { accent-color: var(--brass-light); cursor: var(--cursor-gold, pointer); }
/* Der Waffenständer in der Warentafel der Waffen (15.10.2026) — das Fass der
   Waffenkammer, belegt und Platz. Die Leiste zeigt das Bild der Waffen. */
.wt-staender {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.2rem 0 0.4rem;
  color: var(--brass-light);
}
.wt-staender img { width: 22px; height: 22px; }
.wt-staender.voll { color: var(--blood-light); }
/* Was nicht gegessen wird, steht blass in der Leiste (13.10.2026, /api/essen). */
.res.nicht-gegessen .resicon { opacity: 0.45; filter: grayscale(1); }
.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); }
/* --- Bewohner- und Tiertafel (14.10.2026) ---------------------------------
   Aufgeräumt auf Ansage des Bro („ordentlicher aufräumen auch von stil her“):
   oben Kennzahlen als Kacheln, die Arbeit zweispaltig mit Balken, Essen und
   Futter als Raster aus Warenbildern. */
.wt-uebersicht { width: min(620px, 96vw); }
.wt-uebersicht .wt-h {
  margin: 1.1rem 0 0.5rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.8rem;
}
.wt-uebersicht .wt-proTag { text-transform: none; letter-spacing: 0; }
.wt-kacheln {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));
  gap: 0.5rem;
}
.wt-kachel {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  padding: 0.55rem 0.4rem 0.45rem;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--iron);
  border-radius: 3px;
}
.wt-kachel b {
  font-size: 1.5rem;
  font-weight: normal;
  font-variant-numeric: tabular-nums;
  color: var(--brass-light);
  line-height: 1.1;
}
.wt-kachel span { font-size: 0.8rem; color: var(--text-dim); }
.wt-kachel.achtung b { color: var(--parchment, #f0e2c0); }
.wt-kachel.warnung { border-color: var(--fire-light); }
.wt-kachel.warnung b { color: var(--fire-light); }
.wt-raster {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.35rem 1rem;
}
.wt-raster li {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  row-gap: 0.2rem;
  font-size: 0.9rem;
}
.wt-rname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wt-raster .wt-menge { min-width: 0; font-size: 0.85rem; }
.wt-balken {
  grid-column: 1 / -1;
  height: 3px;
  background: rgba(255, 255, 255, 0.07);
  border-radius: 2px;
  overflow: hidden;
}
.wt-balken i { display: block; height: 100%; background: var(--brass-dark); }
.wt-raster li.voll .wt-balken i { background: var(--moss); }
.wt-chips {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.4rem;
}
.wt-chip {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 0.5rem;
  align-items: center;
  padding: 0.35rem 0.5rem;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid var(--iron);
  border-radius: 3px;
}
.wt-chip img { grid-row: 1 / 3; width: 1.9rem; height: 1.9rem; object-fit: contain; }
.wt-chipname { font-size: 0.85rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wt-chipzahl { font-size: 0.85rem; font-variant-numeric: tabular-nums; color: var(--text-dim); }
.wt-chip.ohnebild { grid-template-columns: 1fr; }
.wt-chip.leer { border-color: var(--fire-light); }
.wt-chip.leer .wt-chipname,
.wt-chip.leer .wt-chipzahl { color: var(--fire-light); }
.wt-chip.leer img { opacity: 0.5; filter: grayscale(1); }

/* --- Die Tafel „Tastenbelegung" (kopfleiste.js, 15.09.2026) -----------------
   Dieselbe Tafel wie die Aufschlüsselungen, nur breiter und in ZWEI Spalten —
   links die Leiste, rechts die Steuerung; einspaltig reichte die Liste über
   den Schirm hinaus. Auf schmalen Schirmen rutscht die rechte Spalte unter die
   linke.

   `tasten-*` UND NICHT `tt-*`: Die Vorsilbe gehört dem Uhrwerk (tickTafel.ts),
   und dessen `.tt-liste dd { text-align: right }` griff hier mit.

   IN `em`, NICHT IN `rem`: Die Wurzelschrift steht auf 19 px, die Tafel auf
   13 px. Mit `rem` waren Tastenkappen und Mauszeilen größer als der Text
   daneben. */
.tasten-tafel { width: min(900px, 96vw); }
.tasten-inhalt {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(20em, 1fr));
  gap: 0 1.8em;
  align-items: start;
}
.tasten-spalte:empty { display: none; }
.tasten-gruppe { margin-bottom: 0.9em; }
.tasten-gruppe .wt-h { margin-top: 0.3em; }
.tasten-liste {
  display: grid;
  /* Die Tastenspalte darf wachsen, aber nicht über zwei Fünftel: Die Zeile
     „W A S D oder Pfeiltasten" bricht lieber um, als die Beschreibungen aller
     anderen Zeilen schmal zu drücken. */
  grid-template-columns: minmax(7em, 40%) 1fr;
  gap: 1px 0;
  margin: 0;
}
/* Die Leiste hat nur einzelne Tasten („K oder B" ist die breiteste) — ihre
   Spalte so schmal wie nötig, sonst stünde jeder Name weit ab von seiner Taste. */
.tasten-liste.tasten-leiste { grid-template-columns: minmax(3.2em, max-content) 1fr; }
.tasten-liste > dt,
.tasten-liste > dd {
  display: flex;
  align-items: center;
  margin: 0;
  padding: 0.24em 0.6em;
  background: rgba(0, 0, 0, 0.25);
  line-height: 1.3;
  text-align: left;
}
.tasten-liste > dt {
  flex-wrap: wrap;
  gap: 0.3em;
}
.tasten-liste > dd {
  gap: 0.6em;
  color: var(--text);
}
.tasten-liste kbd {
  min-width: 1.7em;
  font-size: 0.95em;
  text-align: center;
}
/* Die Maus ist keine Taste — als leiser Text, nicht als Kappe. */
.tasten-maus,
.tasten-oder {
  color: var(--text-dim);
  font-size: 0.95em;
}
/* Das Zeichen aus der Leiste neben dem Namen: So findet man den Knopf, dessen
   Taste man gerade liest. Leer bleibt der Platz, wo es kein Bild gibt. */
.tasten-zeichen {
  flex: none;
  width: 20px;
  height: 20px;
  object-fit: contain;
}
/* Der Buchstabe im Wort, der die Taste ist — „Diplo_m_atie". */
.tasten-merk {
  color: var(--brass-light);
  text-decoration: underline;
  text-decoration-color: var(--brass);
  text-underline-offset: 3px;
}

/* 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: auto; 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-kopf.tafelkopf { margin: -1.1rem -1.3rem 0.9rem; }
.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-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: var(--cursor-kupfer); }
.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;
}
/* Gesperrt, aber klickbar — der Klick spielt „Abgelehnt" (data-klang). */
.ht-tat button[aria-disabled="true"] {
  opacity: 0.4;
  cursor: var(--cursor-kupfer);
}
.ht-tat button[aria-disabled="true"]:hover {
  border-color: var(--brass-dark);
  background: linear-gradient(180deg, #3b424a, #262b31);
}
.ht-tat button[aria-disabled="true"]:active { transform: none; }
.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-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; }
/* Meister und Auftragszettel stehen oben, über den Fahrten und Kursen. */
.ht-oben { margin: 0.4rem 0 0.8rem; }
.ht-oben .ht-auftrag { margin-top: 0.2rem; }
/* Erlös und Kosten — am Warenknopf und auf dem Zettel. */
.ht-betrag { font-variant-numeric: tabular-nums; white-space: nowrap; }
.ht-betrag .resicon { width: 14px; height: 14px; vertical-align: -2px; margin-left: 2px; }
.ht-betrag.plus { color: #8fc27a; }
.ht-betrag.minus { color: #d98a6a; }
/* Feste Breite bis „+999,99“ (17.10.2026): Seit dem Pfennig stehen zwei
   Nachkommastellen da, und mit 4ch sprang der Knopf schon bei „+10,00“. */
.ht-tat .ht-betrag {
  font-size: 0.78rem;
  margin-left: 0.2rem;
  display: inline-block;
  min-width: 7ch;
  text-align: right;
}
/* Die Spalte der Knöpfe nimmt den freien Platz der Tafel: Ware, Lager, Kurs,
   Verkauf, Kauf und Menge rücken zusammen nach links, die Knöpfe bekommen
   Luft und schieben nichts mehr, wenn ein Betrag wächst. */
.ht-preise th, .ht-preise td { width: 1%; white-space: nowrap; padding-left: 0.4rem; padding-right: 0.4rem; }
.ht-preise td.ht-tat, .ht-preise th:last-child { width: auto; }


@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; }
}

/* DER MARKTKNOPF OBEN RECHTS (17.10.2026, Ansage des Bro: „oben rechts steht
   dann zum nächsten markt und dann ort und wenn man drauf klickt kommt dann
   diese detailierte dax graphic"): Zeichen der Kurse, Ort, Weg. Er öffnet die
   Kurstafel (kurstafel.ts) an der Stelle der Handelstafel. */
.ht-markt {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  flex: none;
  padding: 0.25rem 0.65rem 0.25rem 0.45rem;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0;
}
.ht-markt-zeichen { width: 22px; height: 22px; flex: none; }
.ht-markt-ort { color: var(--brass-light); white-space: nowrap; }
.ht-markt-zeit {
  color: var(--text-dim);
  font-weight: 400;
  font-size: 0.78rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* Das Zeichen der Kurse — im Tafelkopf und am Knopf. */
.kt-zeichen { overflow: visible; }
.kt-zeichen-grund { fill: none; stroke: var(--iron-light); stroke-width: 2; stroke-linecap: round; }
.kt-zeichen-linie { fill: none; stroke: var(--brass-light); stroke-width: 2.6; stroke-linejoin: round; stroke-linecap: round; }
.kt-zeichen-punkt { fill: var(--brass-light); }

/* DIE KURSTAFEL (17.10.2026, kurstafel.ts) — links die Waren, rechts der
   Graph der gewählten. Dieselbe Hülle und Breite wie die Handelstafel. */
.kt-tafel { display: flex; flex-direction: column; }
.kt-leib {
  display: grid;
  grid-template-columns: minmax(16rem, 19rem) 1fr;
  gap: 1rem;
  min-height: 0;
}
.kt-liste {
  display: flex;
  flex-direction: column;
  max-height: calc(88vh - 7rem);
  overflow-y: auto;
  border-right: 1px solid var(--iron);
  padding-right: 0.6rem;
}
/* Eine Zeile ist ein Knopf ohne Knopfgestalt: Bild, Name, Kurs, Änderung, Kurve. */
.kt-tafel button.kt-zeile {
  display: grid;
  grid-template-columns: 22px 1fr auto 4.4rem 64px;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  padding: 0.28rem 0.4rem;
  background: none;
  border: 1px solid transparent;
  border-radius: 2px;
  box-shadow: none;
  font-size: 0.85rem;
  font-weight: 400;
  letter-spacing: 0;
  text-align: left;
  color: var(--text);
}
.kt-tafel button.kt-zeile:hover { background: rgba(255, 255, 255, 0.04); border-color: var(--iron); }
.kt-tafel button.kt-zeile:active { transform: none; box-shadow: none; }
.kt-tafel button.kt-zeile.gewaehlt { background: rgba(168, 129, 61, 0.18); border-color: var(--brass-dark); }
.kt-zeile .resicon { width: 20px; height: 20px; }
.kt-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kt-wert { color: var(--brass-light); font-variant-numeric: tabular-nums; text-align: right; }
.kt-proz { font-size: 0.76rem; font-variant-numeric: tabular-nums; white-space: nowrap; text-align: right; }
.kt-proz.hoch { color: #8fc27a; }
.kt-proz.runter { color: #d98a6a; }
.kt-proz.gleich { color: var(--iron-light); }
.kt-klein { display: block; }
.kt-klein polyline { fill: none; stroke-width: 1.3; stroke-linejoin: round; }
.kt-klein.hoch polyline { stroke: #8fc27a; }
.kt-klein.runter polyline { stroke: #d98a6a; }
.kt-leer { color: var(--iron-light); text-align: center; }

.kt-rechts { display: flex; flex-direction: column; min-width: 0; gap: 0.6rem; }
/* Die Leiste der Zeiträume: gleich breite Felder mit Haarlinien (Entwurf C). */
.kt-spannen {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  border: 1px solid var(--iron);
}
.kt-spannen button {
  width: auto;
  padding: 0.3rem 0.4rem;
  background: rgba(0, 0, 0, 0.25);
  border: none;
  border-left: 1px solid var(--iron);
  border-radius: 0;
  box-shadow: none;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--text-dim);
}
.kt-spannen button:first-child { border-left: none; }
.kt-spannen button:hover { background: rgba(255, 255, 255, 0.05); color: var(--text); }
.kt-spannen button:active { transform: none; box-shadow: none; }
.kt-spannen button.gewaehlt { background: rgba(168, 129, 61, 0.25); color: var(--brass-light); }

.kt-kopfzeile {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.3rem 0.7rem;
  min-height: 2rem;
}
.kt-kopfzeile .resicon { width: 24px; height: 24px; align-self: center; }
.kt-ware { color: var(--text); font-size: 1rem; }
.kt-gross { color: var(--brass-light); font-size: 1.6rem; font-variant-numeric: tabular-nums; line-height: 1; }
.kt-je { color: var(--text-dim); font-size: 0.76rem; margin-left: -0.4rem; }
.kt-kopfzeile .kt-proz { font-size: 0.9rem; }
.kt-hochtief { margin-left: auto; color: var(--text-dim); font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.kt-hochtief b { color: var(--text); font-weight: 400; }

.kt-graph { position: relative; min-height: 320px; }
.kt-warten { display: grid; place-items: center; height: 320px; color: var(--iron-light); font-size: 1.4rem; }
.kt-svg { display: block; width: 100%; height: auto; overflow: visible; }
.kt-raster { stroke: rgba(255, 255, 255, 0.07); stroke-width: 1; }
.kt-achse { fill: var(--text-dim); font-size: 11px; font-variant-numeric: tabular-nums; }
.kt-anfang { stroke: var(--iron-light); stroke-width: 1; stroke-dasharray: 3 4; }
.kt-linie { fill: none; stroke-width: 1.8; stroke-linejoin: round; stroke-linecap: round; }
.kt-svg.hoch .kt-linie { stroke: #8fc27a; }
.kt-svg.runter .kt-linie { stroke: #d98a6a; }
.kt-svg.gleich .kt-linie { stroke: var(--brass-light); }
.kt-svg.hoch .kt-verlauf-oben { stop-color: #8fc27a; stop-opacity: 0.28; }
.kt-svg.runter .kt-verlauf-oben { stop-color: #d98a6a; stop-opacity: 0.28; }
.kt-svg.gleich .kt-verlauf-oben { stop-color: #cca75e; stop-opacity: 0.22; }
.kt-verlauf-unten { stop-color: #000; stop-opacity: 0; }
.kt-endmarke rect { stroke: none; }
.kt-svg.hoch .kt-endmarke rect { fill: #4f6e41; }
.kt-svg.runter .kt-endmarke rect { fill: #7a4834; }
.kt-svg.gleich .kt-endmarke rect { fill: var(--brass-dark); }
.kt-endmarke text { fill: #f2e8d4; font-size: 11px; font-variant-numeric: tabular-nums; }
.kt-zeiger-linie { stroke: var(--parchment); stroke-width: 1; stroke-dasharray: 2 3; opacity: 0.7; }
.kt-zeiger-punkt { fill: var(--parchment); stroke: #121417; stroke-width: 1.5; }
.kt-fang { fill: transparent; cursor: var(--cursor-kupfer, default); }
.kt-blase {
  position: absolute;
  top: 0;
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.2rem 0.5rem;
  background: rgba(18, 20, 23, 0.94);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  font-size: 0.78rem;
  color: var(--text-dim);
  white-space: nowrap;
  pointer-events: none;
}
.kt-blase[hidden] { display: none; }
.kt-blase b { color: var(--brass-light); font-weight: 600; font-variant-numeric: tabular-nums; }

@media (max-width: 780px) {
  .kt-leib { grid-template-columns: 1fr; }
  .kt-liste { max-height: 30vh; border-right: none; padding-right: 0; border-bottom: 1px solid var(--iron); }
  .ht-markt-zeit { display: none; }
}

/* --- 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);
  /* GEROLLT WIRD HIER, NICHT IN DER TAFEL (25.10.2026): Ein rollender Kasten
     bekommt im Browser eine eigene Ebene, und die Zeichnung multiplizierte
     dann nicht mehr mit dem Pergament, sondern mit nichts — beim
     Wanderprediger (viele Wahlen, die Tafel rollte) stand sie als weißer
     Kasten da. Die Tafel wächst, `margin: auto` hält sie mittig, ohne dass
     ihr Kopf über den Rand rutscht. */
  overflow-y: auto;
}
#ereignis[hidden] { display: none; }

/* DAS GANZE FENSTER IST EIN BLATT PERGAMENT (03.10.2026, Fassung A der Probe
   assets/tusche/fensterprobe.html; Ansage des Bro: „A ist am geilsten").
   Dasselbe Rahmenbild wie die Aufträge des Markgrafen (.qf-aufgabe weiter
   unten): Ecken und Eselsohr bleiben, die Mitte wird gezogen. Die Schrift ist
   TINTE, Messing trägt auf dem hellen Blatt nicht.

   DIE ZEICHNUNG WIRD MULTIPLIZIERT (.ereignis-bild): Sie ist Tusche auf
   reinweißem Grund (scripts/build-tuschebilder.js), das Weiß verschwindet im
   Pergament. Das geht nur, weil das Blatt und das Bild in DERSELBEN
   Stapelgruppe liegen — der filter hier macht die Tafel dazu. Wer dem Bild
   oder einem Kasten dazwischen ein transform, filter oder opacity gibt,
   isoliert es, und dann steht es wieder als weißer Kasten da. */
.ereignis-tafel {
  /* NICHT --tinte: prolog.css meldet --tinte mit @property als Prozentzahl an,
     und eine Farbe darin ist ungültig — die Schrift fiel auf helles Grau
     zurück (03.10.2026, an den Bedrohungszetteln gesehen). */
  --blatt-tinte: #3a2819;
  --blatt-rot: #6e2415;
  --blatt-blass: #6b5a45;
  width: min(34rem, 100%);
  margin: auto;
  padding: 1.6rem 2rem 1.4rem 3rem;
  border: 1px solid transparent;
  border-image: url("/app/quests/pergament.webp") 280 60 60 280 fill / 48px 10px 10px 48px stretch;
  background: none;
  color: var(--blatt-tinte);
  filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.75));
}
.ereignis-tafel h2 {
  margin: 0 0 0.6rem;
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 500;
  color: var(--blatt-rot);
  line-height: 1.1;
  text-align: center;
}

/* Der Satz aus der Welt heraus — kursiv und mittig, wie ein Vorspruch. Er ist
   das, was der Spieler wirklich liest. */
.ereignis-szene {
  margin: 0 0 1.1rem;
  font-family: var(--font-body);
  font-size: 1.08rem;
  font-style: italic;
  line-height: 1.5;
  text-align: center;
  color: var(--blatt-tinte);
}
.ereignis-szene:empty { display: none; }

.ereignis-wahlen {
  display: flex;
  flex-direction: column;
  gap: 0.45rem;
}
/* Die Wahlen sind mit Tinte umrandete Felder auf dem Blatt. Der Haus-Stil gibt
   jedem Knopf Verlauf, Schatten und Messing — hier alles zurück. */
.ereignis-wahl {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.55rem 0.8rem;
  font: inherit;
  letter-spacing: normal;
  color: var(--blatt-tinte);
  background: rgba(90, 60, 30, 0.06);
  border: 1px solid rgba(58, 40, 25, 0.45);
  border-radius: 2px;
  box-shadow: none;
  cursor: var(--cursor-gold);
}
/* Der Haus-Stil der Spielseiten setzt Knöpfe auf 13 Punkte; auf dem Blatt
   stünden die Wahlen dann winzig unter einem 20-Punkte-Vorspruch. Die Wahl ist
   der Satz, den man liest — sie bekommt die Lesegröße (wie in der Probe). */
#ereignis .ereignis-wahl { font-size: 1rem; }
#ereignis .ereignis-wahl span { font-size: 0.9em; }
.ereignis-wahl:hover:not(:disabled) {
  background: rgba(110, 36, 21, 0.1);
  border-color: var(--blatt-rot);
}
.ereignis-wahl b {
  display: block;
  color: var(--blatt-tinte);
  font-weight: 700;
  margin-bottom: 0.1rem;
}
.ereignis-wahl span {
  display: block;
  font-size: 0.9rem;
  color: var(--blatt-blass);
  line-height: 1.4;
}
.ereignis-wahl:disabled {
  opacity: 0.5;
  cursor: var(--cursor-kupfer);
}
/* Nach dem Klick: die gewaehlte Wahl bleibt voll da und rot umrandet, die
   anderen treten zurueck (ereignisTafel3d.ts, entscheide). Auch der Druck des
   Haus-Stils (button:active) bleibt hier weg. */
.ereignis-wahl:active { transform: none; box-shadow: none; }
.ereignis-wahlen.entschieden .ereignis-wahl.gewaehlt {
  opacity: 1;
  cursor: var(--cursor-gold);
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(110, 36, 21, 0.14);
  border-color: var(--blatt-rot);
  --schein: var(--blatt-rot);
}
.ereignis-wahlen.entschieden .ereignis-wahl:not(.gewaehlt) {
  opacity: 0.3;
  transition: opacity 0.25s;
}
.ereignis-wahl .unmoeglich {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.82rem;
  font-style: normal;
  color: #8a2e1c;
}

/* 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.45rem 0.85rem;
  list-style: none;
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(90, 60, 30, 0.07);
  --schein: rgba(110, 36, 21, 0.45);
  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(--blatt-blass); }
.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. */
/* Auf dem Blatt in Tinte: dunkles Grün und Rubrikenrot (wie .qf-aufgabe). */
.ereignis-bilanz-zeile.gut .eb-wert { color: #4a6a2c; }
.ereignis-bilanz-zeile.schlecht .eb-wert { color: #8a2e1c; }

.ereignis-ausgang-text {
  margin: 0 0 1.1rem;
  font-family: var(--font-body);
  font-size: 1.08rem;
  font-style: italic;
  line-height: 1.5;
  text-align: center;
  color: var(--blatt-tinte);
}
.ereignis-ausgang-weiter {
  text-align: center;
  font-weight: 700;
  color: var(--blatt-tinte);
}
/* 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.85rem;
  color: var(--blatt-blass);
  font-style: italic;
  text-align: center;
}
.ereignis-frist:empty { display: none; }

/* ===========================================================================
   Breite Server-Seiten — Überschriften der Tafeln, und die Tastenkappe.

   Hier stand bis zum 15.09.2026 das Buch der Burg (/wiki), das Tutorial und
   Nachschlagewerk. Es ist auf Ansage raus („das übernimmt jetzt bei uns
   cunrat"), und mit ihm alle .wiki-Regeln. Übrig ist, was andere Seiten
   mitbenutzten: die Überschriften in `.container.wide` (Verwaltung,
   Charakterwahl) und `kbd` (Geländeeditor, Tafel „Tastenbelegung").
   =========================================================================== */

.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);
}

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);
}

/* Bildvignette über der Ereignistafel. Breitformat.

   GLATT SKALIERT, NICHT PIXELIG (12.09.2026). Hier stand „harte Pixelkanten —
   sie ist im selben Stil gemalt wie das Spiel darunter" und dazu
   `image-rendering: pixelated`. Das stimmte, solange die Vignetten Pixelkunst
   waren. Seit sie gemalte Konzeptkunst mit groben Pinselstrichen sind, machte
   genau diese Zeile im Browser Treppenpixel aus jedem Strich — die Tafel zieht
   das Bild auf ihre Breite, und `pixelated` ist Nearest-Neighbour. Das ist die
   Stelle, an der der Spieler das Bild tatsächlich sieht. */
/* SEIT DEM 03.10.2026 EINE TUSCHEZEICHNUNG, multipliziert aufs Blatt — kein
   Rahmen, kein Beschnitt: Die Zeichnung läuft von selbst ins Papier aus.
   Volle Breite, Höhe aus dem Seitenmaß 20:9 der Datei. */
.ereignis-bild {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 20 / 9;
  object-fit: contain;
  image-rendering: auto;
  margin: 0 0 0.4rem;
  mix-blend-mode: multiply;
}
.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 FUSSLEISTE DER BAULEISTE — und sie tut es
   BLENDEND (12.09.2026, Ansage: „kannst du noch einen fade in effekt
   machen“, dazu: „fade in bei resourcen nicht beim baumenu“).

   SICHTBARKEIT UND NICHT `display`, und das ist der ganze Kniff: Aus
   `display: none` heraus laeuft KEIN Uebergang — der Browser hat keinen
   Anfangswert, von dem aus er rechnen koennte. `visibility` dagegen ist
   uebergangsfaehig, und weil sie in Stufen schaltet, laesst sie sich
   VERZOEGERN: Beim Ausblenden faellt erst die Deckkraft, danach geht die
   Sichtbarkeit; beim Einblenden umgekehrt und sofort.

   EIN UEBERGANG UND KEINE ANIMATION. Eine Animation faengt bei jedem
   Sichtbarwerden neu an — auch dann, wenn irgendwo sonst ein `display`
   umgelegt wird; gemessen blieb die Leiste dabei sekundenlang auf null.
   Ein Uebergang laeuft nur, wenn sich der Wert WIRKLICH aendert.

   NUR DIE DECKKRAFT, keine Bewegung: Die Leiste sitzt ueber die ganze
   Breite, ein Hochschieben zerrte am halben Bildrand. Und die Leiste
   wartet ohnehin, bis das Baumenue unten ist (main.ts,
   `leistenWartezeit`) — das Einblenden setzt genau dort an, wo die Fahrt
   aufhoert. Das Baumenue selbst bleibt unberuehrt: Es FAEHRT, es blendet
   nicht.
   Wer keine Bewegung will, bekommt keine (weiter unten). */
#buildbar,
#baumaterial {
  transition:
    opacity var(--hud-ein-ms, 240ms) ease-out,
    visibility 0s;
}
/* WEGGEHEN GESCHIEHT SOFORT, nur das KOMMEN blendet — und das ist
   gemessen, nicht Geschmack: Beide Leisten liegen jetzt an derselben
   Stelle (die Baustoffe genau auf den Kacheln der Vorratsleiste). Blendete
   die eine aus, waehrend die andere einblendet, saehe man die Plaketten
   einen Augenblick DOPPELT. Verlangt war ohnehin ein Fade-IN.

   `transition: none` hier, der Uebergang steht in der Regel darueber:
   Verstecken nimmt diese Regel (also ohne Uebergang), Zeigen faellt auf
   jene zurueck (also mit). */
body.baumodus #buildbar,
body:not(.baumodus) #baumaterial {
  opacity: 0;
  visibility: hidden;
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  #buildbar,
  #baumaterial { transition: none; }
}

/* Baumaterial: Ersatz für die ausgeblendete Vorratsleiste, nur die drei
   Baustoffe (ui.ts renderBaumaterial).

   SEIT DEM 14.10.2026 NUR STEIN UND HOLZ (`BAUSTOFFE`, hud3d.ts): Die
   Vorratsleiste endet jetzt auf Holzkohle, Stein, Holz, und nur deren Ende
   kann hier seine Kacheln decken — Werkzeug und Tuch liegen im Speicher
   (Ansage des Bro: „dann müssen wir es danach ausrichten", „ohne werkzeug").

   DER PLATZ HAT DREIMAL GEWANDERT: erst rechts unten neben der Bauleiste,
   dann mittig ÜBER dem Baumenü, dann mittig UNTER DER KOPFZEILE — und seit
   dem 12.09.2026 wieder in die RECHTE UNTERE ECKE (Ansage: „kannst die
   resourcen die oben in der mitte stehen also stein holz und werkzeug unten
   rechts platzieren in die ecke bitte“).

   Damit ist `--kopfband-hoehe` hier nicht mehr nötig; der Grund, aus dem
   sie einmal gebraucht wurde, steht als Warnung weiter unten bei jeder
   anderen Tafel am oberen Rand: Das Kopfband bricht auf schmalen Fenstern
   um und wird zweizeilig.

   KEIN EIGENER RAHMEN, UND AUF DER LINIE DER VORRATSLEISTE (12.09.2026,
   Ansage: „kannst du diesen rahmen da loesen und die resourcen kacheln des
   baumenues genau ueber die resourcen kacheln des standard menus legen“).

   Hier stand ein eigener Kasten — eigener Grund, eigener Rahmen, eigener
   Schlagschatten — und darin kleinere Plaketten (20-px-Embleme statt 32).
   Beim Umschalten sprang damit alles: Groesse, Grundlinie, Einfassung.

   Jetzt teilt sie mit der Vorratsleiste JEDE Zahl, die die Lage bestimmt:

     bottom / right   die Polsterung von #buildbar (0,55rem / 1rem)
     gap              der Abstand aus #resources (0,18rem)
     Plakette         gar keine eigene Regel mehr — also die von `.res`

   Gemessen im Fenster des Bauherrn: Die Vorratsleiste endet rechts bei
   1565 und steht auf 859..895. Genau dort liegen jetzt die drei Baustoffe,
   rechtsbuendig — die Werkzeug-Plakette deckt ihre eigene aus dem
   Standardmenue Punkt fuer Punkt.

   WER DIE POLSTERUNG VON #buildbar AENDERT, zieht diese beiden Zahlen
   mit. Sie stehen absichtlich als dieselben Werte da und nicht als
   gerundete Naeherung; laufen sie auseinander, sieht man es genau an dem
   Strich, den diese Ansage abgestellt hat. */
#baumaterial {
  /* IMMER GELEGT, nur unsichtbar — `display: none` waere das Ende jedes
     Uebergangs (siehe oben). Sie haengt an ihren vier Kanten und nimmt
     darum niemandem Platz weg. */
  display: flex;
  align-items: center;
  top: auto;
  bottom: 0.55rem;
  left: auto;
  right: 1rem;
  transform: none;
  gap: 0.18rem;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
}

/* IN DER ECKE TREFFEN SIE AUF SCHMALEN FENSTERN DAS BAUMENÜ.

   Das Menü steht mittig und ist rund 830 px breit; die Baustoffe belegen
   mit ihrem Rand die rechten 214 (gemessen: 1370 bis 1565 plus 1rem).
   Gerechnet berühren sich beide unterhalb von etwa 1.260 px
   Fensterbreite; die Schranke steht mit Luft darüber. Dann rücken sie
   ÜBER das Menü — die gemeinsame Linie mit der Vorratsleiste ist dort
   weniger wert als ein freier Blick — auf die Höhe,
   die es GERADE hat: `--iso3d-bauleiste-hoehe` wird gemessen und gemeldet
   (bauleiste.ts, hoeheMelden), weil die Leiste je Kategorie verschieden
   hoch ist. Eine feste Zahl sässe mal daneben und mal darauf. */
@media (max-width: 1300px) {
  body.baumodus #baumaterial { bottom: calc(var(--iso3d-bauleiste-hoehe, 0px) + 24px); }
}

#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: var(--cursor-kupfer);
  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: 6px;
}
#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);
}
/* DER FINGERZEIG IST RAUS (12.09.2026). Hier stand `sb-ziel` — der goldene,
   pulsierende Rahmen um den Knopf, den die laufende Aufgabe meinte, samt den
   Keyframes `sb-ziel-puls`, die sich 2D und 3D geteilt haben.

   Ansage des Bauherrn: „bitte das alte tutorial komplett rausnehem … gold
   unterleuchtetes das gebaeude was gebaut werden soll. das haben wir nicht
   mehr. es gibt hoechstens die missionen aber die haben nichts gold
   unterleuchtet.“ Es setzt niemand mehr die Klasse: questfenster.js meldet
   kein Ziel, main.ts reicht keines weiter, und die Bauleiste hat
   `setzeBauziel` verloren. */
#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: auto;
  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: auto;
}
#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: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(18, 20, 23, 0.94);
  border: 1px solid var(--iron);
  --schein: 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. */
  /* DIE ZAHL HAT EINE FESTE SPALTE (27.09.2026, Ansage des Bro: „die linien
     gleich ausrichten auf einer linie damit nichts verspringt"). Jede Zeile
     ist ein eigenes Raster; mit `auto` war die Zahlenspalte je Zeile so breit
     wie ihre Zahl, und der Balken davor stand in jeder Zeile woanders. */
  grid-template-columns: calc(16px * var(--tafel-skala)) minmax(0, 1fr) calc(46px * var(--tafel-skala)) calc(4.8rem * var(--tafel-skala));
  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: auto;
}
.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); }
/* Stein und Eisen haben keinen Balken — der Platz bleibt, damit nichts verspringt. */
.kv-balken.kv-ohne { visibility: hidden; }
.kv-unendlich .kv-zahl { color: var(--brass-light); }
/* AUSKLAPPBAR (27.09.2026): Der Kopf schaltet, main.ts merkt sich den Stand. */
.kv-kopf { cursor: var(--cursor-gold, pointer); }
.kv-klappe { float: right; margin-left: 0.4em; color: var(--brass); }
.kv-klappe::before { content: "▾"; }
#kartenvorrat.zu .kv-klappe::before { content: "▸"; }
#kartenvorrat.zu .kv-liste,
#kartenvorrat.zu .kv-merkmale { display: none; }
#kartenvorrat.zu .kv-kopf { margin-bottom: 0; }
.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). */
/* DIE KLAMMER AM WALD (12.09.2026).

   Ansage des Bauherrn: „waldbeeren, pilze und fleisch und felle brauchen
   wald. wenn der wald gerodet wird, dann gehen auch automatisch pilze,
   beeren, wildtier weg. es muss irgendwie klar sein."

   Die RECHNUNG tat das längst (kartenvorraete.ts: alle vier kommen aus
   `waldJetzt`) — man sah es der Tafel nur nicht an. Acht Zeilen standen als
   acht unabhängige Balken untereinander. Jetzt stehen die vier direkt unter
   dem Wald und hängen sichtbar an ihm.

   EINE LINIE UND KEIN KASTEN: Ein umrandeter Block wäre ein zweites Fenster
   in einem Fenster; die Klammer sagt dasselbe mit einem Strich. Sie sitzt
   dort, wo das Bildchen anfängt, damit die Zeilen NICHT einrücken — eine
   eingerückte Zahlenspalte liesse sich nicht mehr mit den übrigen
   vergleichen, und genau dafür ist die Tafel da. */
.kv-vomwald { position: relative; }
.kv-vomwald::before {
  content: "";
  position: absolute;
  left: calc(-0.34rem * var(--tafel-skala));
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--brass-dark);
  opacity: 0.7;
}
/* Der Fuss der Klammer bekommt einen kleinen Haken nach rechts — sonst hört
   die Linie im Nichts auf und sieht aus wie ein Rest.

   `:has(+ :not(.kv-vomwald))` und nicht `:last-of-type`: Letzteres meint die
   letzte ZEILE der Liste, und das ist der Fisch — der Haken saesse dann gar
   nicht an der Klammer. Gesucht ist die letzte Zeile DER GRUPPE, und die
   erkennt man nur an ihrem Nachbarn. */
.kv-vomwald:has(+ :not(.kv-vomwald))::after {
  content: "";
  position: absolute;
  left: calc(-0.34rem * var(--tafel-skala));
  bottom: 0;
  width: calc(0.24rem * var(--tafel-skala));
  height: 1px;
  background: var(--brass-dark);
  opacity: 0.7;
}

.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; }

/* DER JAHRESLAUF (13.09.2026, Ansage des Bro: „auch sollten pilze und beeren
   saisonal sein und fleisch kann man die ganze zeit jagen. es sollte eine
   anzeige geben sowohl in ‚was das land hergibt' als auch in der waldhütte").

   Vier Säulen, eine je Jahreszeit, die laufende hell. Gebaut in
   kartenvorratTafel.ts (jahreslaufSaeulen) und von ZWEI Stellen benutzt: der
   Vorratstafel hier und dem Regler an der Waldhütte (.gp-art-jahr). Darum
   ohne kv-/gp-Vorsilbe.

   Eine LEERE Jahreszeit ist ein roter Strich am Boden, keine fehlende Säule:
   Ein Loch liest man als „keine Angabe", einen Strich als „nichts". */
.jl-saeulen {
  display: inline-flex;
  align-items: flex-end;
  gap: 1px;
  height: calc(9px * var(--tafel-skala));
  flex: none;
}
.jl-saeulen i {
  display: block;
  width: calc(5px * var(--tafel-skala));
  height: 100%;
  background: var(--brass-dark);
}
.jl-saeulen i.jetzt { background: var(--brass-light); box-shadow: 0 0 0 1px rgba(240, 220, 168, 0.3); }
.jl-saeulen i.leer { height: 2px; background: #8a4a3c; }
.jl-saeulen i.leer.jetzt { background: #d4695a; }

/* In der Tafel sitzen Säulen und Kurzwort UNTER Balken und Zahl — in der
   zweiten Reihe, neben der Kleinschrift. Dort war schon Luft: Der Name trägt
   zwei Zeilen (Name und „je Waldkachel"), Balken und Zahl nur eine.

   Eine eigene Unterzeile über die ganze Breite war der erste Anlauf und hat
   die Tafel um fünf Zeilen verlängert — gemessen 890 Bildpunkte hoch, bei
   1920 × 1080 siebzig Bildpunkte IN der Bauleiste. So bleibt jede Zeile so
   hoch wie vorher. */
.kv-zeile.kv-mitjahr { grid-template-rows: auto auto; row-gap: 0; }
.kv-mitjahr .kv-icon { grid-column: 1; grid-row: 1 / span 2; }
.kv-mitjahr .kv-name { grid-column: 2; grid-row: 1 / span 2; }
.kv-mitjahr .kv-balken { grid-column: 3; grid-row: 1; }
.kv-mitjahr .kv-zahl { grid-column: 4; grid-row: 1; }
.kv-jahr {
  grid-column: 3 / -1;
  grid-row: 2;
  display: flex;
  align-items: center;
  gap: calc(0.25rem * var(--tafel-skala));
  font-size: calc(0.66rem * var(--tafel-skala));
  color: var(--text-dim);
  white-space: nowrap;
  min-width: 0;
}
.kv-jahr-text { overflow: hidden; text-overflow: ellipsis; }
.kv-jahreszeit { margin-left: 0.35em; color: var(--text-dim); }
.kv-jahreszeit::before { content: "· "; }

/* 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;
}
.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.5rem;
  width: 264px;
}
/* SEIT DEM 03.10.2026 EIN BLATT PERGAMENT mit Tuschezeichnung (Probe
   assets/tusche/bedrohungsprobe.html; Ansage des Bro: „mach doch wieder zurück
   volles blatt"). Dasselbe Rahmenbild wie das Ereignisfenster und die
   Aufträge; die Gefahr liest sich jetzt am roten Namen und am roten Knopf,
   nicht mehr am Blutrand. Der filter macht den Zettel zu einer Stapelgruppe,
   in der die Zeichnung aufs Blatt multipliziert wird (.bedrohung-bild). */
.bedrohung {
  --blatt-tinte: #3a2819;
  --blatt-rot: #6e2415;
  --blatt-blass: #6b5a45;
  border: 1px solid transparent;
  border-image: url("/app/quests/pergament.webp") 280 60 60 280 fill / 30px 7px 7px 30px stretch;
  background: none;
  padding: 0.55rem 0.7rem 0.6rem 1.95rem;
  font-size: 0.86rem;
  color: var(--blatt-tinte);
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.6));
}
/* Eingeklappt: nur Name und Zeichnung. Der ganze Zettel nimmt den Klick. */
.bedrohung.lager { cursor: var(--cursor-gold); }
.bedrohung-rest[hidden] { display: none; }
/* Der Kopf ist ein KNOPF, sieht aber aus wie eine Überschrift: der Name in
   roter Fraktur, rechts die Kopfzahl und der Pfeil. Der Pfeil zeigt NACH
   UNTEN, solange es dort etwas aufzuklappen gibt, und aufgeklappt nach oben
   (Wunsch des Bro, 03.10.2026: „größer … nach unten"). */
.bedrohung .kopf {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  width: 100%;
  padding: 0;
  font: inherit;
  text-align: left;
  color: var(--blatt-rot);
  background: none;
  border: 0;
  box-shadow: none;
  letter-spacing: normal;
  cursor: var(--cursor-gold);
}
.bedrohung .kopf b {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--blatt-rot);
}
.bedrohung .kopf .staerke { margin-left: auto; }
/* DER RUF DES LAGERS (24.10.2026, bedrohungsruf.ts) — ein bis drei Sterne in
   der Tinte des Namens, gewöhnliche Lager tragen keinen. */
.bedrohung .kopf .bd-ruf {
  align-self: center;
  font-size: 0.95rem;
  letter-spacing: 0.04em;
  line-height: 1;
  color: var(--blatt-rot);
  white-space: nowrap;
}
/* SEIT DEM 24.10.2026 IST NUR DER PFEIL DER KLAPPKNOPF (Ansage des Bro); ein
   Klick sonst aufs Blatt fährt die Kamera zum Lager (bedrohungen3d.ts). */
.bedrohung .bd-klappe {
  align-self: center;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.4rem;
  height: 1.4rem;
  margin: 0 -0.2rem 0 0.15rem;
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  cursor: var(--cursor-gold);
}
.bedrohung .bd-klappe::after {
  content: "";
  width: 0.55rem;
  height: 0.55rem;
  margin-top: -0.25rem;
  border-right: 2.5px solid var(--blatt-rot);
  border-bottom: 2.5px solid var(--blatt-rot);
  transform: rotate(45deg);
  transition: transform 0.15s;
}
.bedrohung .bd-klappe[aria-expanded="true"]::after {
  transform: translateY(0.3rem) rotate(-135deg);
}
.bedrohung .bd-klappe:hover::after { border-color: #a8341f; }

/* Die Zeichnung — Tusche auf Weiß (scripts/build-tuschebilder.js),
   multipliziert aufs Blatt. Kein Rahmen: Sie läuft von selbst ins Papier aus. */
.bedrohung-bild {
  display: block;
  width: 100%;
  margin: 0.15rem 0 0.1rem;
  image-rendering: auto;
  mix-blend-mode: multiply;
}
.bedrohung-szene {
  margin-bottom: 0.35rem;
  font-family: var(--font-body);
  font-style: italic;
  line-height: 1.38;
  color: var(--blatt-tinte);
}

/* 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.4rem 0 0.25rem;
  background: rgba(74, 106, 44, 0.45);
  border: 1px solid rgba(58, 40, 25, 0.7);
  border-radius: 1px;
  overflow: hidden;
}
.bedrohung .kraftbalken .feind {
  display: block;
  height: 100%;
  background: #8a2e1c;
}
/* 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: var(--blatt-tinte);
}

/* In Tinte: dunkles Grün, Ocker, Rubrikenrot. */
.bedrohung .urteil.gut { color: #4a6a2c; font-weight: 600; }
.bedrohung .urteil.knapp { color: #8a5a10; font-weight: 600; }
.bedrohung .urteil.schlecht { color: #8a2e1c; font-weight: 700; }

/* 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: var(--blatt-tinte);
  font-weight: 600;
  background: rgba(90, 60, 30, 0.1);
  border-color: rgba(58, 40, 25, 0.55);
  font-size: 0.76rem;
}
.bedrohung .entsenden button.abkauf:hover:not(:disabled) {
  background: rgba(110, 36, 21, 0.12);
}
.bedrohung .staerke {
  font-size: 0.8rem;
  color: var(--blatt-blass);
  white-space: nowrap;
}
.bedrohung .zeile {
  margin-top: 0.15rem;
}
.bedrohung .zeile.muted {
  color: var(--blatt-blass);
  font-size: 0.78rem;
}
.bedrohung .lauf {
  color: #8a5a10;
  font-weight: 600;
  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(255, 250, 235, 0.5);
  border: 1px solid rgba(58, 40, 25, 0.55);
  border-radius: 2px;
  padding: 0.15rem 0.3rem;
}
.bedrohung .entsenden button {
  flex: 1;
  cursor: var(--cursor-gold);
  font: inherit;
  font-size: 0.82rem;
  font-weight: 700;
  color: #f1e3c6;
  background: #7a2a1b;
  border: 1px solid #4a160c;
  border-radius: 2px;
  box-shadow: none;
  padding: 0.22rem 0.5rem;
}
.bedrohung .entsenden button:hover:not(:disabled) {
  background: #8e3322;
}
.bedrohung .entsenden button:disabled {
  opacity: 0.5;
  cursor: var(--cursor-kupfer);
}

/* DIE FASSUNG (13.10.2026, Ansagen des Bro: „kompakter halten, weniger text
   und ausrücken bzw bezahlen durch icons ersetzen", „kampf silber und
   aussichtslos plus die leiste mit den boni … zusammen fassen in so eine
   fassung" — gewählt aus sechs Entwürfen: B, der Tintenrahmen). Ein doppelter
   Tintenrahmen, das Urteil als rote Rubrik im oberen Rand; links Balken und
   was verloren geht, rechts die beiden Zeichenknöpfe. */
.bedrohung .bd-fassung {
  display: block;
  min-width: 0;
  /* Links so weit vom Blattrand wie rechts: Das Polster des Zettels ist links
     1,95rem breit (für die eingerollte Ecke oben), rechts 0,7rem. */
  margin: 0.1rem 0 0 -1.25rem;
  padding: 0 0.3rem 0.3rem 0.4rem;
  border: 3px double rgba(58, 40, 25, 0.75);
  border-radius: 3px;
  background: rgba(120, 80, 40, 0.06);
}
.bedrohung .bd-fassung legend {
  margin: 0 auto;
  padding: 0 0.35rem;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--blatt-tinte);
}
.bedrohung .bd-fassung legend.schlecht { color: #8a2e1c; }
.bedrohung .bd-fassung legend.knapp { color: #8a5a10; }
.bedrohung .bd-fassung legend.gut { color: #4a6a2c; }
.bedrohung .bd-fassung .kraftbalken { margin: 0.15rem 0 0.3rem; }
/* Unter dem Balken EINE Reihe Kacheln: links was verloren geht, rechts die Knöpfe. */
.bedrohung .bd-reihe { display: flex; align-items: flex-start; gap: 0.3rem; }
.bedrohung .bd-reihe .bd-werte { flex: 1; min-width: 0; }
.bedrohung .bd-werte {
  display: flex;
  flex-wrap: wrap;
  gap: 0.05rem 0.45rem;
  font-size: 0.82rem;
  color: var(--blatt-blass);
}
/* Was verloren geht, größer (Ansage des Bro: „die icons von was verloren geht
   etwas größer machen"). */
.bedrohung .bd-zeichen {
  display: inline-flex;
  align-items: center;
  gap: 0.1rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bedrohung .bd-zeichen img { width: 22px; height: 22px; }
.bedrohung .bd-zeichen.opfer { color: var(--blatt-rot); font-weight: 700; font-size: 1rem; }
/* In der Fassung ist jeder Verlust eine KACHEL wie die Knöpfe daneben —
   Zeichen oben, Zahl darunter (Ansage des Bro: „die einzelnen minuse also
   symbole auch als kacheln machen"). Nur heller und ohne Rand zum Anfassen:
   eine Kachel ist kein Knopf. */
.bedrohung .bd-werte {
  gap: 0.2rem;
}
.bedrohung .bd-werte .bd-zeichen {
  flex-direction: column;
  justify-content: center;
  gap: 0;
  width: 2.45rem;
  height: 2.75rem;
  padding: 0;
  font-size: 0.7rem;
  font-weight: 700;
  line-height: 1;
  color: var(--blatt-tinte);
  background: rgba(255, 248, 230, 0.28);
  border: 1px solid rgba(58, 40, 25, 0.3);
  border-radius: 2px;
}
.bedrohung .bd-werte .bd-zeichen img { width: 28px; height: 28px; margin: -1px 0 1px; }
.bedrohung .bd-werte .bd-zeichen.opfer img { width: 32px; height: 32px; margin: 0; }
.bedrohung .kopf .staerke.bd-zeichen { align-self: center; font-size: 0.92rem; }
.bedrohung .kopf .staerke.bd-zeichen img { width: 20px; height: 20px; }
.bedrohung .bd-knoepfe {
  display: flex;
  align-self: stretch;
  align-items: center;
  gap: 0.2rem;
  padding-left: 0.3rem;
  border-left: 1px solid rgba(58, 40, 25, 0.45);
}
.bedrohung .bd-knoepfe button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 2.45rem;
  height: 2.75rem;
  padding: 0;
  font: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  line-height: 1;
  color: var(--blatt-tinte);
  background: rgba(255, 248, 230, 0.35);
  border: 1px solid rgba(58, 40, 25, 0.7);
  border-radius: 2px;
  box-shadow: none;
  cursor: var(--cursor-gold);
}
.bedrohung .bd-knoepfe button:hover:not(:disabled) {
  background: rgba(142, 51, 34, 0.14);
  border-color: #7a2a1b;
}
.bedrohung .bd-knoepfe button:disabled {
  opacity: 0.5;
  cursor: var(--cursor-kupfer);
}
.bedrohung .bd-kampf img { width: 30px; height: 30px; }
.bedrohung .bd-silber img { width: 32px; height: 32px; margin: -4px 0 -5px; }

/* --- 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(29rem, 100%);
  max-height: 90vh;
  overflow-y: auto;
  background: var(--stone-800);
  border: 1px solid var(--brass-dark);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
}
.ausrueck-tafel .tafelkopf__titel { font-size: 1.3rem; }
.ausrueck-inhalt { padding: 0.8rem 0.9rem 0.9rem; }

/* DIE KRÄFTE (20.10.2026, Entwurf B): zwei Kästen, darunter der Balken über
   die Summe beider Kräfte — links wir, rechts das Lager. */
.ausrueck-schlacht {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}
.ar-seite {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 0.1rem;
  min-height: 4.2rem;
  padding: 0.5rem 0.6rem;
  background: #0d0e10;
  border: 1px solid var(--iron);
  overflow: hidden;
}
.ar-wer { order: 2; color: #b9ae9c; font-size: 1rem; font-variant-numeric: tabular-nums; }
.ar-kraftzahl {
  order: 1;
  font-family: var(--font-display);
  font-size: 2rem;
  line-height: 1;
  color: #efe4cf;
  font-variant-numeric: tabular-nums;
}
/* Das Tuschebild des Lagers als Grund des rechten Kastens, dunkel gelegt,
   damit die Zahl darüber steht. */
.ar-feindbild { position: absolute; inset: 0; background: #e9dfc8; }
.ar-feindbild img { width: 100%; height: 100%; object-fit: cover; mix-blend-mode: multiply; }
.ar-feindbild::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(13, 14, 16, 0.88) 0%, rgba(13, 14, 16, 0.55) 40%, rgba(13, 14, 16, 0.3) 100%); }
.ar-seite .ar-wer, .ar-seite .ar-kraftzahl { position: relative; }
.ar-wer { display: flex; align-items: center; gap: 0.3rem; }
.ar-kopfzeichen { width: 24px; height: 24px; }
.ar-waage {
  grid-column: 1 / -1;
  display: flex;
  height: 10px;
  margin-top: 0.15rem;
  background: #08090a;
  border: 1px solid var(--iron);
}
.ar-waage i { display: block; height: 100%; transition: width 0.2s ease; }
.ar-waage-unsre { background: linear-gradient(90deg, #6f9a4e, #a8c46a); }
.ar-waage-ihre { margin-left: auto; background: linear-gradient(90deg, #c46a4a, #8f3a2c); }

/* Das Urteil — ein Wort, groß und in Farbe. */
.ausrueck-urteil {
  margin: 0.35rem 0 0.5rem;
  text-align: center;
  font-family: var(--font-display);
  font-size: 1.45rem;
  line-height: 1.1;
}
.ausrueck-urteil.gut { color: #8fbf6a; }
.ausrueck-urteil.knapp { color: #e0b060; }
.ausrueck-urteil.schlecht { color: #d4695a; }

/* JE GATTUNG EINE ZEILE: Bildnis, Name, − Zahl +. Alle Spalten
   fest, damit nichts springt, wenn eine Zahl zweistellig wird. */
.ar-zeile {
  display: grid;
  grid-template-columns: 44px 1fr 26px 3.4rem 26px;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0;
  border-top: 1px solid #23252a;
}
.ar-bildnis { width: 44px; height: 44px; object-fit: contain; }
.ar-name { font-size: 1rem; color: #d7ccb8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ar-zahl { text-align: center; font-variant-numeric: tabular-nums; color: #efe4cf; }
.ar-zeile .knopf-klein { width: 26px; height: 26px; }
.ar-zahl { font-size: 1rem; }

.ar-zeile.aus { opacity: 0.4; }

/* Der Fuss: der Knopf über die ganze Breite — dunkel
   mit Messingrand wie der Ausgang der Einstellungen, KEIN gelber Knopf. */
.ausrueck-knoepfe {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.5rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--brass-dark);
}
.ausrueck-knoepfe .ar-los {
  flex: 1;
  height: 2.3rem;
  margin: 0;
  background: rgba(168, 129, 61, 0.1);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  color: var(--brass-light);
  font-family: var(--font-body);
  font-size: 1rem;
  cursor: var(--cursor-gold);
}
.ausrueck-knoepfe .ar-los:hover:not(:disabled) { background: rgba(168, 129, 61, 0.22); border-color: var(--brass); color: #f0dfb4; }
.ausrueck-knoepfe .ar-los:disabled { opacity: 0.4; cursor: default; }

/* --- 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;
  /* KEIN ABDUNKELN MEHR (21.09.2026, Ansage des Bro): Die Burg bleibt hinter
     der Tafel so hell, wie sie ist. Der Grund fängt weiter den Klick ab —
     ein Klick daneben schließt die Tafel, statt auf die Burg zu fallen. */
  background: transparent;
  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); }

/* Der Tafelkopf der Standestafel und ihrer Seiten; das Bildnis als Zeichen
   von oben her, nie am Kopf angeschnitten. */
.sp-tafel > .sp-tafelkopf { margin: -1.2rem -1.4rem 0.9rem; }
.sp-tafelkopf .sp-zu { position: static; }
.sp-tafelkopf .sp-kopfzeichen { object-fit: cover; object-position: 50% 0; border: 1px solid var(--brass-dark); }
.sp-tafelkopf .sp-anteil, .sp-tafelkopf .tb-frei { margin: 0 0.3rem 0 0; font-size: 0.85rem; }
.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;
  /* SEIT DEM 21.09.2026 DER RAHMEN DES VORPLATZES (hub.css, .portraitrahmen):
     quadratisch, Messingrand, das Wappen als Schild in der Ecke. Vorher war
     das Bildnis selbst ein Schild und das Wappen ein kleines Quadrat daneben
     — zwei Schildformen übereinander, und auf dem Vorplatz sah es anders
     aus als hier. */
  width: 6.4rem;
  height: 6.4rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  background: #15181c;
  border: 2px solid var(--brass-dark);
  border-radius: 2px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(204, 167, 94, 0.25);
  overflow: hidden;
}
/* 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: auto;
}
.sp-initiale {
  font-family: var(--font-display);
  font-size: 2.4rem;
  line-height: 1;
  color: var(--brass-light);
}
.sp-wappen {
  /* Das Wappen als Schild — dieselbe Form und Lage wie auf dem Vorplatz
     (hub.ts, wappenSchild). Das SVG schneidet das quadratische Bild aus. */
  position: absolute;
  right: -0.125rem;
  bottom: -0.125rem;
  width: 2.4rem;
  height: 2.76rem;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.7));
  pointer-events: none;
}

/* 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); }
/* Seit dem 17.10.2026 ist das Bildnis der Standestafel kein Knopf mehr
   (gewechselt wird in den Einstellungen des Vorplatzes) — es leuchtet nicht. */
div.sp-bildnis { cursor: inherit; }
div.sp-bildnis:hover { border-color: var(--brass-dark); }

/* 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: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(0, 0, 0, 0.28);
  border: 1px solid var(--iron);
  --schein: 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: auto;
}
.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 {
  /* Fünf Zahlen seit den Götterbildern (22.10.2026): so breit wie ihr Inhalt,
     verteilt über die Zeile, und nichts bricht in sich um — vorher ein Raster
     aus gleich breiten Spalten von 7 rem, in dem die fünfte allein darunter stand. */
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 0.8rem;
  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; white-space: nowrap; }
.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); }

/* DER ERFAHRUNGSBALKEN (13.09.2026). Er ersetzt die Liste der Bedingungen:
   Seit dem Umbau steht nicht mehr da, was noch fehlt, sondern wie viel
   Erfahrung — und darunter, womit man sie sammelt. Der Balken läuft von der
   Schwelle des geführten Titels bis zu der des nächsten (adel.ts, aufstieg). */
.sp-erfahrung {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 0.6rem;
  margin: 0.6rem 0 0;
}
.sp-erfahrungsbalken {
  height: 6px;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(204, 167, 94, 0.25);
  border-radius: 3px;
  overflow: hidden;
}
.sp-erfahrungsbalken i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--brass-dark), #f3d27a);
}
.sp-zahl { font-variant-numeric: tabular-nums; font-size: 0.85rem; }
/* „Was Erfahrung bringt" ist AUSKLAPPBAR (13.09.2026) — ein natives <details>,
   zu, bis man es öffnet. Der Pfeil ersetzt das Dreieck des Browsers, das in
   jedem Browser anders aussieht (Firefox: list-style, Chrome: der Marker). */
.sp-erfahrungsquellen { margin-top: 1.1rem; }
.sp-erfahrungsquellen > summary {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  list-style: none;
  font-family: var(--font-display);
  font-size: 1.05rem;
  color: var(--brass-light);
  cursor: var(--cursor-gold);
}
.sp-erfahrungsquellen > summary::-webkit-details-marker { display: none; }
.sp-erfahrungsquellen > summary::before {
  content: "▸";
  font-family: var(--font-body);
  font-size: 0.8rem;
  color: var(--text-dim);
  transition: transform 0.15s ease-out;
}
.sp-erfahrungsquellen[open] > summary::before { transform: rotate(90deg); }
.sp-erfahrungsquellen > summary:hover { color: #f3d27a; }
.sp-erfahrungstaten { margin: 0.35rem 0 0; padding: 0; list-style: none; }
.sp-erfahrungstat {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.22rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.sp-erfahrungstat .sp-zahl { color: #f3d27a; text-align: right; }
/* Die Tagesaufgaben gibt es noch nicht — sie stehen da, blass und mit Hinweis. */
.sp-erfahrungstat.kommt { opacity: 0.55; }
.sp-erfahrungstat em { font-size: 0.75rem; color: var(--text-dim); }
.sp-hinweis { margin: 0; color: var(--text-dim); }

/* --- Stufe und Titel getrennt (28.09.2026) ----------------------------------
   Die Stufe kommt aus der Erfahrung und fällt nie, der Titel hängt an der Burg
   und kann fallen (titelstand.ts). Die Bedingungen des nächsten Titels stehen
   als Liste mit Ist und Soll — erfüllte in Messing, offene gedämpft. */
.sp-stufenmarke {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0 0.4rem;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: #f3d27a;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(10, 11, 13, 0.6);
  vertical-align: middle;
}
.sp-bedingungen { margin: 0.35rem 0 0; padding: 0; list-style: none; }
.sp-bedingung {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.22rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  color: var(--text-dim);
}
.sp-bedingung .sp-was::before { content: "○"; margin-right: 0.45rem; opacity: 0.7; }
.sp-bedingung.erfuellt { color: inherit; }
.sp-bedingung.erfuellt .sp-was::before { content: "✓"; color: #f3d27a; opacity: 1; }
.sp-bedingung.erfuellt .sp-zahl { color: #f3d27a; }
.sp-leise { font-size: 0.8rem; color: var(--text-dim); margin-top: 0.4rem; }
.sp-titelwarnung { margin: 0.6rem 0 0; color: #d98a6a; font-weight: 600; }

/* --- Die Werte (28.09.2026) --------------------------------------------------
   Drei Karten nebeneinander, dunkel mit Messingrand wie jede Tafel; die Karte
   des Klassenwerts trägt einen helleren Rand. Auf schmalen Schirmen stehen sie
   untereinander. */
.sp-wertetitel { margin: 0.6rem 0 0.2rem; font-family: var(--font-display); }
.sp-wertkarten {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.7rem;
  margin: 0.8rem 0;
}
.sp-wertkarte {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  padding: 0.7rem 0.8rem;
  background: rgba(10, 11, 13, 0.55);
  border: 1px solid var(--brass-dark);
  border-radius: 4px;
}
.sp-wertkarte.klasse { border-color: var(--brass); }
.sp-wertkopf { display: flex; justify-content: space-between; align-items: baseline; gap: 0.5rem; }
.sp-wertkopf h3 { margin: 0; }
.sp-wertzahl { font-size: 1.6rem; font-weight: 700; color: #f3d27a; }
.sp-wertwirkungen { margin: 0; padding: 0; list-style: none; flex: 1; }
.sp-wertwirkung { display: flex; flex-direction: column; padding: 0.2rem 0; border-bottom: 1px solid rgba(255, 255, 255, 0.04); }
.sp-wertwirkung .sp-leise { margin-top: 0.1rem; }
.sp-wertfuss { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
/* --- Die Siegelträger (28.09.2026) -------------------------------------------
   Karten aus Rahmen (Bild, das Fenster ist durchsichtig), Bildnis DAHINTER und
   Schrift darüber (siegeltraeger.js). Die Lage von Fenster und Schild ist am
   Rahmenbild gemessen (Fenster 9,8–89,9 % breit, 6,1–64,8 % hoch). Das Siegel
   ist hell gemaltes Wachs, getönt mit `multiply` in die Farbe der Aufgabe, und
   das Wappenzeichen ist eine Maske darin — geprägt durch zwei Schatten. */
.sp-tafel.sgt-tafel { width: min(62rem, calc(100vw - 3rem)); }
.sgt-abschnitt {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 1.1rem 0 0.55rem;
  font-family: var(--font-display);
  font-size: 1.05rem;
}
.sgt-reihe { display: flex; flex-wrap: wrap; gap: 1rem 1.1rem; }
.sgt-platz { width: 13.5rem; display: flex; flex-direction: column; gap: 0.35rem; }
.sgt-karte { position: relative; width: 100%; aspect-ratio: 407 / 640; container-type: inline-size; }
.sgt-bild {
  position: absolute;
  left: 9.8%;
  top: 6.1%;
  width: 80.2%;
  height: 58.8%;
  object-fit: cover;
  object-position: 50% 12%;
  background: radial-gradient(circle at 50% 38%, #3b3229, #14110e 75%);
}
.sgt-rahmen { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.sgt-schild {
  position: absolute;
  left: 15%;
  right: 15%;
  /* Etwas tiefer ins Schild (20.10.2026, Ansage des Bro): Art, Name und Werte
     sassen am oberen Rand der Messingtafel. */
  top: 73.2%;
  bottom: 8.6%;
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0;
  text-align: center;
  line-height: 1.15;
}
.sgt-schild > * { flex: none; max-width: 100%; }
/* DIE ART UNTER DEM SCHILD (20.10.2026, Ansage des Bro: „ritter größer
   schreiben und zentral zwischen feld packen“, „R I T T E R“): mittig im
   Streifen zwischen Messingschild und Rahmen, weit gesperrt. */
.sgt-art {
  position: absolute;
  left: 12%;
  right: 12%;
  top: 93%;
  height: 5.2%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  white-space: nowrap;
  /* Ein langes Wort („Kundschafterin“) wird kleiner, bis es in den Streifen
     passt: 76 % der Kartenbreite durch die Zeichen, je Zeichen samt Sperrung
     gut 1,1 em (gemessen an den Arten der Siegelkarten). */
  font-size: min(0.78rem, calc(76cqi / (var(--artzeichen, 6) * 1.15)));
  line-height: 1;
  letter-spacing: 0.42em;
  /* Das Sperren hängt hinter den letzten Buchstaben Luft an — gleich vorn
     dazu, sonst steht das Wort links der Mitte. */
  padding-left: 0.42em;
  text-transform: uppercase;
  color: var(--brass-light, #d8b56a);
  opacity: 0.85;
}
/* SELTEN, EPISCH, LEGENDÄR (20.10.2026, Ansage des Bro: „man erkennt den status
   an der wortfarbe ritter … vllt wie bei wow"): nur das Wort der Art färbt sich,
   in den Farben von WoW, für den dunklen Grund etwas heller. */
.sgt-karte[data-seltenheit="selten"] .sgt-art { color: #4fa3ff; opacity: 1; font-weight: 600; }
.sgt-karte[data-seltenheit="episch"] .sgt-art { color: #b76df2; opacity: 1; font-weight: 600; }
.sgt-karte[data-seltenheit="legendaer"] .sgt-art { color: #ff9a2e; opacity: 1; font-weight: 600; }
.sgt-name {
  max-width: 100%;
  /* Genau EINE Zeile: Was hinter dem Vornamen umbricht, liegt darunter und
     ist abgeschnitten (nameHtml in siegeltraeger.js). */
  height: 1.15em;
  line-height: 1.15;
  overflow: hidden;
  font-family: var(--font-display);
  /* Größer (20.10.2026), und ein langer Name wird kleiner statt gekürzt
     (Ansage des Bro: „dass der name des ritters kleiner wird wenn er zu lang
     ist“): die Breite des Schildes durch die Zeichen des Namens, ein Zeichen
     dieser Schrift ist im Mittel unter 0,45 em breit (gemessen an den Namen
     der Siegelkarten). Erst unter 0,72rem greift der Vorname allein. */
  font-size: clamp(0.72rem, calc(100cqi / (var(--zeichen, 10) * 0.45)), 1.15rem);
  color: #efe3c4;
  white-space: normal;
}
/* Die Werte größer (20.10.2026, Ansage des Bro: „die klasseneigenschaften größer“). */
.sgt-werte { display: flex; gap: 0.6rem; margin-top: 0.12rem; }
.sgt-wert { display: flex; flex-direction: column; align-items: center; min-width: 2.2rem; }
.sgt-wert b { font-size: 1.4rem; line-height: 1; color: #f3d27a; }
.sgt-wert small { font-size: 0.68rem; color: var(--text-dim); }

.sgt-siegel {
  position: absolute;
  right: 3%;
  top: 55.5%;
  width: 26%;
  aspect-ratio: 1;
  transform: rotate(-9deg);
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.6));
}
.sgt-wachs {
  position: absolute;
  inset: 0;
  isolation: isolate;
  background: var(--wachs);
  -webkit-mask: var(--wachs-bild) center / contain no-repeat;
  mask: var(--wachs-bild) center / contain no-repeat;
}
.sgt-wachs::before,
.sgt-wachs::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--wachs-bild) center / contain no-repeat;
}
.sgt-wachs::before { mix-blend-mode: multiply; }
.sgt-wachs::after { mix-blend-mode: soft-light; opacity: 0.75; }
.sgt-praegung {
  position: absolute;
  inset: 29%;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, 0.28)) drop-shadow(0 -1px 0.5px rgba(0, 0, 0, 0.65));
}
.sgt-praegung i {
  display: block;
  width: 100%;
  height: 100%;
  background: color-mix(in srgb, var(--wachs) 70%, #000);
  -webkit-mask: var(--zeichen) center / contain no-repeat;
  mask: var(--zeichen) center / contain no-repeat;
}
.sgt-siegel.drueckt { animation: sgt-drueckt 0.9s cubic-bezier(0.2, 0.8, 0.2, 1) both; }
@keyframes sgt-drueckt {
  0% { transform: rotate(-9deg) scale(1.9); opacity: 0; }
  55% { transform: rotate(-9deg) scale(0.9); opacity: 1; }
  75% { transform: rotate(-9deg) scale(1.04); }
  100% { transform: rotate(-9deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .sgt-siegel.drueckt { animation: none; }
}
/* Ein gebrochenes Siegel: zwei Hälften, auseinandergerückt. */
.sgt-siegel.gebrochen .sgt-haelfte { position: absolute; inset: 0; }
.sgt-siegel.gebrochen .links {
  clip-path: polygon(0 0, 52% 0, 44% 30%, 55% 52%, 43% 78%, 50% 100%, 0 100%);
  transform: translate(-7%, 3%) rotate(-7deg);
}
.sgt-siegel.gebrochen .rechts {
  clip-path: polygon(52% 0, 100% 0, 100% 100%, 50% 100%, 43% 78%, 55% 52%, 44% 30%);
  transform: translate(7%, -2%) rotate(6deg);
}
.sgt-karte.gebrochen .sgt-bild { filter: grayscale(1) brightness(0.55); }
.sgt-status {
  padding: 0.04rem 0.45rem;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(10, 11, 13, 0.78);
  font-size: 0.66rem;
  line-height: 1.6;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #efe3c4;
}
.sgt-status.gefallen,
.sgt-status.gefasst { color: #e0a08a; }
.sgt-status.verwundet { color: #e0a08a; }
/* DAS BILDNIS DER HERRSCHAFT auf ihrer Karte (29.09.2026) ist das der
   Charakterwahl, eine freigestellte Halbfigur — oben angesetzt, damit der Kopf
   nie angeschnitten wird. */
/* Die Herrschaft als BÜSTE ohne Arme, wie die Bildnisse der Siegelträger
   (20.10.2026, Ansage des Bro): anderthalbfach von oben Mitte; der Ausschnitt
   (clip-path) wird mitvergrößert und deckt danach genau das Fenster. */
.sgt-bild.sgt-bildnis-herr {
  object-position: 50% 0;
  /* Luft über dem Kopf wie bei den Rittern: Das Bildnis ist freigestellt, im
     oberen Rand liegt der Hintergrund des Fensters (padding mit Verlauf). */
  box-sizing: border-box;
  padding-top: 7%;
  transform: scale(1.5);
  transform-origin: 50% 0;
  clip-path: inset(0 16.667% 33.333% 16.667%);
}
.sgt-fuss { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem; }
.sgt-fuss .sp-leise { margin-top: 0; }
.sgt-eigenschaft {
  padding: 0.04rem 0.4rem;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(10, 11, 13, 0.55);
  font-size: 0.72rem;
}
.sgt-eigenschaft.gut { color: #cfe0a8; }
.sgt-eigenschaft.schlecht { color: #e0a08a; }
.sgt-entlassen { margin-left: auto; }
.sgt-angebote { display: grid; gap: 0.5rem; }
.sgt-angebot {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--brass-dark);
  border-radius: 4px;
  background: rgba(10, 11, 13, 0.55);
}
.sgt-angebotsiegel {
  flex: none;
  width: 1.8rem;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--wachs);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.12), 0 1px 2px #000;
}
.sgt-angebottext { display: flex; flex: 1; flex-direction: column; }
.sgt-angebottext .sp-leise { margin-top: 0.1rem; }


/* --- Der Talentbaum (08.09.2026, als eigenes Fenster seit 13.09.2026) -------
   In der Standestafel steht nur noch die Kurzfassung mit dem Knopf; der Baum
   ist ein breites Fenster in derselben Hülle (talentbaum.js). Angesagt: „dann
   sollen die 3 talentzweige nebeneinander stehen. wir brauchen für jeden
   talent zweig einen hintergrund bild was verdunkelt wird. es soll so aussehn
   bisschen wie bei wow."

   DIE VIER ZUSTÄNDE MÜSSEN SICH UNTERSCHEIDEN, und zwar mehr als durch
   Helligkeit: `hat` hat einen goldenen Rand, `frei` einen grünen und leuchtet
   (die Einladung, wie bei WoW), `teuer` bleibt farbig, aber gedämpft und ohne
   Leuchten — „du könntest, dir fehlt ein Punkt" —, und `gesperrt` ist grau:
   „erst das davor". Die beiden letzten gleich darzustellen wäre die bequeme
   Lösung und die falsche: Sie verschwiege dem Spieler, dass ihm nur noch ein
   Aufstieg fehlt. */
.sp-talente { margin-top: 1.4rem; }
.sp-talente 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-talente .sp-talentknopf { margin-top: 0.45rem; }

/* Dieselbe Tafel, nur breiter — fenster.js schiebt `.sp-tafel`. Die Breite
   haengt am SCHIRM und nicht an 100 %: fenster.js stellt die Tafel auf
   `position: fixed`, und dann meinen 100 % die ganze Fensterbreite — das
   Fenster lief 29 px ueber den rechten Rand (gemessen bei 1024 px). */
.sp-tafel.tb-tafel { width: min(52rem, calc(100vw - 3rem)); }

/* Rechts 4 rem frei für das ×: Im Spiel trägt der Knopf den Rahmen der
   Spieloberfläche und ist 58 px breit — mit 2 rem lag „2 Punkte frei"
   darunter (gemeldet vom Bro, 13.09.2026). Die Talentprobe misst den Abstand. */
.tb-titel {
  display: flex;
  align-items: baseline;
  gap: 0.9rem;
  margin: 0 4rem 0.8rem 0;
}
.tb-titel h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.45rem;
  color: var(--brass-light);
}
.tb-zurueck {
  padding: 0;
  border: none;
  background: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.85rem;
  cursor: var(--cursor-gold);
}
.tb-zurueck:hover { color: var(--brass-light); }
.tb-frei { margin-left: auto; font-size: 0.95rem; color: var(--text-dim); }
.tb-frei.da { color: #6fd46a; font-weight: bold; }

/* SEIT DEM 21.09.2026 EIN BAUM UND DANEBEN DIE BONI: Jede Klasse wählt nur
   noch aus ihrem eigenen Baum (talente.ts, freischaltbar). */
.tb-zweige {
  display: grid;
  /* DREI BÄUME NEBENEINANDER (seit 28.09.2026 wieder alle offen), die Spalte
     der Boni darunter über die ganze Breite. Auf schmalen Schirmen stehen die
     Bäume untereinander. */
  grid-template-columns: repeat(3, minmax(16rem, 1fr));
  gap: 0.6rem;
}
.tb-zweige > .tb-boni { grid-column: 1 / -1; }
@media (max-width: 62rem) {
  .tb-zweige { grid-template-columns: 1fr; }
}

/* Die Spalte der Boni — in der Farbe der Klasse wie der Baum daneben. */
.tb-boni { --tb-farbe: #a8813d; --tb-hell: #cca75e; }
.tb-boni[data-zweig="feldherr"] { --tb-farbe: #c8402f; --tb-hell: #f08b72; }
.tb-boni[data-zweig="kaufmann"] { --tb-farbe: #3a78c8; --tb-hell: #8dbaf0; }
.tb-boni[data-zweig="verwalter"] { --tb-farbe: #cf9f2c; --tb-hell: #f1d27c; }
.tb-boni {
  padding: 0.6rem 0.75rem 0.7rem;
  border: 1px solid color-mix(in srgb, var(--tb-farbe) 45%, #000);
  border-radius: 4px;
  background: #121316;
  overflow-y: auto;
  max-height: 27rem;
}
.tb-boni h4 {
  margin: 0.2rem 0 0.1rem;
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: normal;
  color: var(--tb-hell);
}
.tb-boni-leer { margin: 0 0 0.6rem; font-size: 0.8rem; color: var(--text-dim); }
.tb-boni-liste { margin: 0 0 0.75rem; padding: 0; list-style: none; }
.tb-boni-liste li {
  padding: 0.28rem 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.tb-boni-liste li:last-child { border-bottom: none; }
.tb-boni-liste strong { display: block; font-size: 0.88rem; color: #6fe06f; }
.tb-boni-liste span { display: block; font-size: 0.74rem; line-height: 1.3; color: #d8cfbd; }

/* JE ZWEIG SEINE FARBE — rot, blau, gelb (Ansage). Sie färbt Name, Rahmen und
   den Grund hinter den Bildern; der Rest der Tafel bleibt Messing. Ein Zweig,
   der hier fehlt, steht in Messing da statt ohne Farbe. */
.tb-zweig { --tb-farbe: #a8813d; --tb-hell: #cca75e; }
.tb-zweig[data-zweig="feldherr"] { --tb-farbe: #c8402f; --tb-hell: #f08b72; }
.tb-zweig[data-zweig="kaufmann"] { --tb-farbe: #3a78c8; --tb-hell: #8dbaf0; }
.tb-zweig[data-zweig="verwalter"] { --tb-farbe: #cf9f2c; --tb-hell: #f1d27c; }

.tb-zweig {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  min-height: 27rem;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--tb-farbe) 45%, #000);
  border-radius: 4px;
  background: #0d0e10;
}
/* DAS BILD IN EINER EIGENEN SCHICHT, damit es dunkler werden kann, ohne dass
   Knöpfe und Schrift mit dunkler werden. */
.tb-zweig::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -2;
  background: var(--tb-grund) center top / cover no-repeat;
  filter: brightness(0.55) saturate(0.9);
}
/* Oben und unten dunkler, in der Mitte am hellsten: Oben steht die Schrift,
   unten liegen die Knöpfe, und dazwischen steht der Turm. */
.tb-zweig::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    180deg,
    rgba(8, 9, 11, 0.8) 0%,
    rgba(8, 9, 11, 0.12) 20%,
    rgba(8, 9, 11, 0.08) 42%,
    rgba(8, 9, 11, 0.7) 66%,
    rgba(8, 9, 11, 0.88) 100%
  );
}
.tb-zweig.eigen {
  border-color: color-mix(in srgb, var(--tb-farbe) 85%, #fff);
  box-shadow: 0 0 14px color-mix(in srgb, var(--tb-farbe) 40%, transparent);
}

.tb-kopf {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: baseline;
  padding: 0.55rem 0.7rem 0;
}
.tb-name {
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--tb-hell);
  text-shadow: 0 1px 2px #000, 0 0 10px rgba(0, 0, 0, 0.85);
}
.tb-leitsatz { font-size: 0.78rem; color: #d8cfbd; text-shadow: 0 1px 2px #000; }
.tb-summe {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  min-width: 1.8rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid color-mix(in srgb, var(--tb-farbe) 60%, #000);
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.6);
  color: var(--tb-hell);
  font-weight: bold;
  text-align: center;
}

.tb-raster {
  display: grid;
  /* VIER STRÄNGE je Baum (28.09.2026). */
  grid-template-columns: repeat(4, 1fr);
  justify-items: center;
  margin-top: auto;
  padding: 0.8rem 0.4rem 0.9rem;
}
.tb-strang { display: flex; flex-direction: column; align-items: center; }
.tb-strangname {
  margin-top: 0.55rem;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: #d8cfbd;
  text-shadow: 0 1px 2px #000;
}

.tb-talent {
  position: relative;
  width: 3.5rem;
  height: 3.5rem;
  padding: 0;
  border: 2px solid #4b4e54;
  border-radius: 6px;
  background: radial-gradient(circle at 50% 38%, color-mix(in srgb, var(--tb-farbe) 42%, #16181c) 0%, #0b0c0e 78%);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.7), 0 2px 5px rgba(0, 0, 0, 0.6);
  cursor: var(--cursor-kupfer);
}
.tb-talent:focus-visible { outline: 2px solid #fff3c8; outline-offset: 3px; }
.tb-bild { position: absolute; inset: 4px; background: center / contain no-repeat; }
/* Die Rangzahl unten rechts, wie bei WoW — ihre Farbe sagt den Zustand. */
.tb-rang {
  position: absolute;
  right: -0.5rem;
  bottom: -0.5rem;
  min-width: 1.7rem;
  padding: 0 0.2rem;
  border: 1px solid currentColor;
  border-radius: 3px;
  background: #0b0c0e;
  color: #9a9da3;
  font-size: 0.7rem;
  font-weight: bold;
  line-height: 1.15rem;
  text-align: center;
}
/* Der geschenkte Perk der Klasse — sonst hielte man ihn für einen ausgegebenen Punkt. */
.tb-geschenk {
  position: absolute;
  left: -0.5rem;
  top: -0.5rem;
  width: 1.15rem;
  height: 1.15rem;
  border: 1px solid #e0b43c;
  border-radius: 50%;
  background: #0b0c0e;
  color: #f1d27c;
  font-size: 0.7rem;
  line-height: 1.05rem;
  text-align: center;
}

.tb-talent.hat {
  border-color: #e0b43c;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.7), 0 0 9px rgba(224, 180, 60, 0.5);
}
.tb-talent.hat .tb-rang { color: #f1d27c; }
.tb-talent.frei {
  border-color: #43c247;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.7), 0 0 12px rgba(67, 194, 71, 0.65);
  cursor: var(--cursor-gold);
}
.tb-talent.frei .tb-rang { color: #6fe06f; }
.tb-talent.frei:hover { filter: brightness(1.2); }
.tb-talent.teuer .tb-bild { filter: saturate(0.6) brightness(0.8); }
/* TEILWEISE ENTFALTET (28.09.2026, Ränge): ein halber Goldrand — man sieht,
   dass hier schon Punkte liegen, aber noch nicht alle. */
.tb-talent.teil { box-shadow: inset 0 0 0 2px rgba(241, 210, 124, 0.45); }
.tb-talent.teil .tb-rang { color: #f1d27c; }
.tb-talent.gesperrt {
  border-color: #34363a;
  background: radial-gradient(circle at 50% 38%, #25272b 0%, #0b0c0e 78%);
}
.tb-talent.gesperrt .tb-bild { filter: grayscale(1) brightness(0.5); }

/* Der Pfeil vom ersten zum zweiten Talent eines Strangs — golden, sobald der
   Weg offen ist. */
.tb-pfeil {
  position: relative;
  width: 4px;
  height: 1.6rem;
  margin: 0.55rem 0 0.7rem;
  background: #4b4e54;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6);
}
.tb-pfeil::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: -0.45rem;
  transform: translateX(-50%);
  border: 0.36rem solid transparent;
  border-top: 0.45rem solid #4b4e54;
  border-bottom: 0;
}
.tb-pfeil.offen { background: #e0b43c; }
.tb-pfeil.offen::after { border-top-color: #e0b43c; }

/* Der Hinweis — am <body>, damit ihn der Rand der scrollenden Tafel nicht
   abschneidet; über #spielerpanel (880). */
.tb-hinweis {
  position: fixed;
  z-index: 950;
  max-width: 17rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid #5a5e66;
  border-radius: 4px;
  background: rgba(10, 12, 18, 0.96);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.7);
  color: var(--text);
  font-size: 0.82rem;
  pointer-events: none;
}
.tb-hinweis[hidden] { display: none; }
.tb-h-name { display: block; font-size: 0.95rem; color: #fff; }
.tb-h-rang,
.tb-h-ort { display: block; font-size: 0.72rem; color: #9a9da3; }
.tb-h-text { margin: 0.35rem 0 0; line-height: 1.3; color: #f1d27c; }
.tb-h-zahl { margin: 0.35rem 0 0; font-weight: bold; color: #6fe06f; }
.tb-h-absolut { margin: 0.1rem 0 0; font-size: 0.76rem; line-height: 1.3; color: #d8cfbd; }
.tb-h-stand { margin: 0.35rem 0 0; font-size: 0.78rem; }
.tb-h-stand.frei { color: #6fe06f; }
.tb-h-stand.hat { color: #e0b43c; }
.tb-h-stand.teuer { color: #c9c9c9; }
.tb-h-stand.gesperrt { color: #e0645a; }

.sp-talentfuss {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
}
/* Die beiden Knoepfe unter dem Baum sind echte Knoepfe und keine Textwege:
   Sie geben Einfluss aus. `sp-wechseln` daneben ist ein Link-Stil und waere
   fuer eine Ausgabe zu leise — man soll sehen, dass hier etwas kostet.
   Ein eigener vollstaendiger Stil und keine erfundene Basisklasse: `sp-knopf`
   gibt es in dieser Tafel nicht, und eine Klasse ohne Grundstil brachte die
   Browservoreinstellungen mit (Kasten, fremde Schrift). */
.sp-talentknopf {
  padding: 0.34rem 0.7rem;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(109, 84, 38, 0.24);
  color: var(--brass-light);
  font: inherit;
  font-size: 0.82rem;
  cursor: var(--cursor-gold);
}
.sp-talentknopf:hover:not([disabled]) {
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.34);
}
.sp-talentknopf.leise { border-color: var(--iron); background: rgba(0, 0, 0, 0.25); color: var(--text-dim); }
.sp-talentknopf[disabled] { opacity: 0.45; cursor: var(--cursor-kupfer); }

/* --- 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; }

/* Kopf, Linie und Kreuz sind der Tafelkopf (`.tafelkopf`). */
.ct-kopf {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  /* 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; }

/* DIE OBERE LEISTE — seit dem 17.09.2026 nur noch Zwiegespraeche und Cunrat.
   Kanaele und Runden stehen links (.ct-seite). Der Grund steht in chat.js:
   Beide Sorten in einer Zeile hiess, dass alles ab dem fuenften Reiter aus
   dem Bild rutschte, und was man heranschieben muss, klickt niemand an.

   `flex-shrink: 0` an der ganzen Leiste, damit sie beim Schrumpfen des
   Fensters nicht als Erstes zusammengedrueckt wird — sie ist nur eine Zeile
   hoch, und ohne sie sieht man nicht mehr, mit wem man redet. */
.ct-faeden {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.3rem 0.4rem;
  border-bottom: 1px solid var(--iron);
  overflow-x: auto;
  flex: 0 0 auto;
  /* Die Bildlaufleiste wuerde die Reiter um ihre Hoehe anheben. Sie darf
     bleiben (mit vielen Gespraechen braucht man sie), aber duenn. */
  scrollbar-width: thin;
}
.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);
}
/* DIE ZAHL DES UNGELESENEN an den Orten links (18.10.2026, Ansage des Bro:
   „messing zahl … die zahlen darin zentral positionieren"): ein eckiger
   Messingkasten, die Ziffer genau in der Mitte. Feste Hoehe und Mindestbreite
   samt Grid, damit „3" und „12" gleich hoch sitzen und eine Ziffer nicht am
   Rand klebt; `line-height: 1`, sonst schiebt die Zeilenhoehe der Schrift
   die Ziffer nach unten. */
.ct-punkt {
  margin-left: 0.3rem;
  display: inline-grid;
  place-items: center;
  min-width: 1.15rem;
  height: 1.05rem;
  padding: 0 0.22rem;
  box-sizing: border-box;
  font-size: 0.7rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  text-align: center;
  background: #0d0c0b;
  border: 1px solid var(--brass);
  color: var(--brass-light);
  border-radius: 0;
  flex: none;
}
/* Der Name steckt seit dem 17.09.2026 in einem eigenen Span (chat.js,
   `fadenKnopf`). Er ist das einzige Stueck eines Knopfes, das bei Platzmangel
   gekuerzt werden darf — Wappen, Bildnis und die Zahl des Ungelesenen nie:
   Eine abgeschnittene Zahl ist eine falsche Zahl. */
.ct-faden-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- ZWEI SPALTEN (17.09.2026) --------------------------------------------
   Ansage des Bro: „ich möchte dass im seitlichen feld die channels stehen und
   oben nur private fenster mit spielern und cunrat".

   `ct-mitte` traegt beides nebeneinander und ist das Stueck, das die Hoehe
   frisst; `min-height: 0` muss dabei sein, sonst waechst ein Flex-Kind
   (hier der Verlauf) ueber seinen Anteil hinaus, statt zu scrollen. Dieselbe
   Falle steht schon bei `.ct-koerper` — sie wiederholt sich bei jeder neuen
   Schachtelungsebene. */
.ct-mitte {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* DIE SEITENLEISTE — Kanaele und Runden, untereinander.

   Ihre Breite kommt als `--ct-seite` vom Skript (chat.js, `stelle`), weil sie
   ziehbar ist und im localStorage liegt. Der Rueckfall steht hier fuer den
   Fall, dass die Leiste vor dem ersten Stellen gezeichnet wird. */
.ct-seite {
  flex: 0 0 var(--ct-seite, 136px);
  width: var(--ct-seite, 136px);
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.35rem 0.3rem 0.5rem;
  overflow-y: auto;
  overflow-x: hidden;
  background: rgba(0, 0, 0, 0.22);
  border-right: 1px solid var(--iron);
  scrollbar-width: thin;
}
/* Die Ueberschriften „Kanäle" und „Runden". Klein, gesperrt und gedaempft:
   Sie sind Wegweiser und keine Knoepfe — wer sie anklickt, soll nichts
   erwarten. */
.ct-abschnitt {
  margin: 0.35rem 0 0.1rem;
  padding: 0 0.3rem;
  font-size: 0.68rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.ct-abschnitt:first-child { margin-top: 0; }
.ct-seite-leer {
  margin: 0;
  padding: 0.1rem 0.45rem 0.2rem;
  font-size: 0.76rem;
  font-style: italic;
  color: var(--text-dim);
}

/* EIN KANAL ODER EINE RUNDE ALS ZEILE.

   Er TRAEGT `.ct-faden` und holt sich Farbe und Zustaende („aktiv",
   „hat-post") von dort — hier steht nur, was an der FORM anders ist. Ein
   zweiter Satz Farben liefe beim naechsten Griff an den Reitern auseinander,
   und dann leuchtete ein Kanal links, waehrend derselbe Faden oben still ist.

   `width: 100%` ausdruecklich, weil der Haus-Stil jedem `button` ein
   `width: fit-content` gibt (ui.css oben) — ohne diese Zeile waere jede Zeile
   so breit wie ihr Name, und die Leiste saehe aus wie eine Treppe. */
.ct-faden.ct-seitig {
  display: flex;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: 0.22rem 0.45rem;
  border-color: transparent;
  background: none;
  box-shadow: none;
  font-weight: 400;
  white-space: nowrap;
  min-width: 0;
}
.ct-faden.ct-seitig .ct-faden-name { flex: 1 1 auto; min-width: 0; }
.ct-faden.ct-seitig:hover { background: rgba(255, 255, 255, 0.07); color: var(--text); }
.ct-faden.ct-seitig.aktiv {
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(109, 84, 38, 0.34);
  border-color: transparent;
  /* Der Strich links statt eines Rahmens ringsum: In einer Liste liest sich
     eine durchgehende Kante als Trennung zwischen den Zeilen, nicht als
     Auswahl der einen. */
  --schein: var(--brass);
}
/* DIE KOPFZEILE „KANÄLE ＋" (18.10.2026, Ansage des Bro: „Kanäle und
   Runden einfach das Button Runden+"). Über die ganze Breite der Leiste,
   gesperrt wie eine Überschrift, das Plus rechts; unter dem Zeiger leuchtet
   sie auf, denn sie öffnet einen Bogen. */
.ct-seite-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin: 0.25rem 0 0.05rem;
  padding: 0.22rem 0.45rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--iron);
  border-radius: 0;
  box-shadow: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 0.7rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-align: left;
  cursor: var(--cursor-gold);
}
.ct-seite-kopf:first-child { margin-top: 0; }
.ct-seite-kopf b { font-weight: normal; font-size: 0.9rem; line-height: 1; color: var(--brass); }
.ct-seite-kopf:hover { color: var(--brass-light); border-color: var(--brass-dark); }
.ct-seite-kopf:hover b { color: var(--brass-light); }
/* EIN KANAL TRÄGT IMMER EINEN LEICHTEN RAHMEN in dunklem Blau (18.10.2026,
   Ansage des Bro: „dass die sich von den spieler namen abheben und nicht so
   in der luft schweben") — auch ungewählt; gewählt bleibt er Messing. */
.ct-faden.ct-seitig.ct-kanal {
  border: 1px solid #2b3a55;
  background: rgba(32, 48, 78, 0.28);
  margin-bottom: 0.12rem;
}
.ct-faden.ct-seitig.ct-kanal:hover { border-color: #3d5278; background: rgba(40, 60, 96, 0.38); }
.ct-faden.ct-seitig.ct-kanal.aktiv {
  border-color: var(--brass-dark);
  background: linear-gradient(90deg, color-mix(in srgb, var(--brass) 22%, transparent), transparent 70%), rgba(109, 84, 38, 0.34);
}
.ct-faden.ct-seitig.ct-kanal.ct-grau:hover { border-color: #2b3a55; background: rgba(32, 48, 78, 0.28); }
/* „Global" — der Kanal über alle Server, den es erst mit mehreren gibt. */
.ct-faden.ct-seitig.ct-grau { opacity: 0.38; cursor: var(--cursor-kupfer, default); }
.ct-faden.ct-seitig.ct-grau:hover { background: none; color: var(--text-dim); }
/* PERSONEN IN DER SEITENLEISTE (18.10.2026): Cunrat und die Zwiegespräche
   mit dem Kopf aus dem Bildnis vor dem Namen. Wer nicht da ist, steht grau
   (Ansage des Bro: „bei privat ist der spieler offline ist er schwarz weiß"). */
.ct-faden.ct-seitig { gap: 0.35rem; }
.ct-faden.ct-seitig .ct-kopfbild { width: 18px; height: 18px; }
.ct-faden.ct-offline .ct-kopfbild { filter: grayscale(1); opacity: 0.7; }
.ct-faden.ct-offline .ct-faden-name { color: var(--text-dim); }
.ct-faden.ct-seitig.ct-cunrat { padding-left: 0.45rem; }

/* WER GERADE IM KANAL IST — unter dem gewählten Kanal, eingerückt: Bildnis
   und Burg; der volle Name unter dem Zeiger. Ein Klick öffnet das
   Namensmenü wie im Verlauf. */
.ct-anwesende {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  /* DIE BILDNISSE AUF DER LINIE VON CUNRAT, und eine Messinglinie links,
     die an den gewählten Kanal anschließt (18.10.2026, Ansage des Bro: „auf
     die selbe linie wie cunrat … eine messing linie die links durch geht und
     an primus anschließt"). Rand und Polster wie die Zeile darüber (1 px und
     0,45rem), die Linie in der Farbe ihres Rahmens. */
  margin: -0.22rem 0 0.12rem 0.2rem; /* oben den Abstand der Zeile und der Leiste (0,1rem) zurück */
  /* Die Linie ein Stück herein, näher an die Bildnisse (Ansage: „die linie
     ganz leicht nach rechts"); das Polster gibt es zurück, die Bildnisse
     bleiben auf der Linie von Cunrat. */
  padding: 0.2rem 0.2rem 0.25rem 0.25rem;
  border-left: 1px solid #2b3a55;
  font-size: 0.76rem;
}
/* Die Linie in der Farbe des Kanalrahmens: blau, unter dem gewählten Messing. */
.ct-anwesende.aktiv { border-left-color: var(--brass-dark); }
.ct-anwesend {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text-dim);
  padding: 0.05rem 0;
}
.ct-anwesend .ct-kopfbild { width: 18px; height: 18px; flex: none; }
/* „PRIVAT ＋": die Mitspieler als Liste im Menü, „KANÄLE ＋": Name und
   Eröffnen in einer Zeile (18.10.2026). Die Liste rollt für sich, das Menü
   bleibt im Fenster. */
.ct-nm-liste { max-height: 14rem; overflow-y: auto; scrollbar-width: thin; }
.ct-namenmenue button.ct-nm-person {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  white-space: nowrap;
}
.ct-nm-person .ct-schild { display: block; width: 15px; height: 18px; flex: none; }
.ct-nm-person > span { overflow: hidden; text-overflow: ellipsis; }
/* „Kanäle ＋": das Feld, darunter „Eröffnen" über die ganze Breite
   (Ansage des Bro: „textfeld und drunter eröffnen button"). */
.ct-nm-kanal { display: flex; flex-direction: column; gap: 0.3rem; padding: 0.15rem 0.45rem 0.35rem; }
.ct-nm-kanal .ct-rb-name { width: 100%; max-width: none; box-sizing: border-box; margin: 0; padding: 0.2rem 0.35rem; font-size: 0.8rem; }
.ct-namenmenue .ct-nm-kanal button {
  width: 100%;
  text-align: center;
  padding: 0.2rem 0.55rem;
  border: 1px solid var(--brass-dark);
  font-size: 0.8rem;
}
/* Die Plus-Menüs so breit wie ihr Knopf (die Breite setzt chat.js). */
.ct-namenmenue.ct-leistenbreit { min-width: 0; box-sizing: border-box; }
.ct-namenmenue .ct-nm-kanal button[disabled] { opacity: 0.45; cursor: var(--cursor-kupfer); }
/* Der Schild im Menü (100 : 118 wie die Schildform). */
.ct-nm-kopf .ct-schild { display: block; width: 15px; height: 18px; flex: none; }
.ct-anwesend > span:last-child { overflow: hidden; text-overflow: ellipsis; }
/* Wer im eigenen Kanal sitzt und nicht da ist: grau wie unter Privat. */
.ct-anwesend.ct-offline .ct-kopfbild { filter: grayscale(1); opacity: 0.7; }
.ct-anwesend.ct-offline > span:last-child { opacity: 0.6; }
/* Ich selbst: nicht anklickbar, der Name etwas heller. */
.ct-anwesend-ich { color: var(--text); }

/* Der Pfeil zum Auf- und Zuklappen der Liste unter einem Kanal. */
.ct-klapp {
  flex: none;
  margin-left: auto;
  padding: 0 0.15rem;
  font-size: 0.7rem;
  line-height: 1;
  color: var(--text-dim);
  cursor: var(--cursor-gold);
}
.ct-klapp:hover { color: var(--brass-light); }
.ct-faden.ct-seitig .ct-punkt + .ct-klapp { margin-left: 0.2rem; }
/* Das Kreuz an einem eigenen Kanal steht am rechten Rand der Zeile. */
.ct-faden.ct-seitig .ct-faden-zu { margin-left: 0.2rem; }

/* Der Ziehgriff ZWISCHEN Seitenleiste und Gespraech. Unsichtbar bis zum
   Ueberfahren: Ein sichtbarer Balken waere eine dritte Linie neben dem Rand
   der Leiste und dem Rahmen des Fensters. */
.ct-seitengriff {
  flex: 0 0 5px;
  margin-left: -3px;
  margin-right: -2px;
  z-index: 2;
  cursor: ew-resize;
  background: transparent;
  transition: background 0.12s;
}
.ct-seitengriff:hover { background: var(--brass-dark); }

/* Die rechte Spalte: Verlauf, Auswahlbogen, Eingabe. */
.ct-rechts {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.ct-verlauf {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.4rem 0.55rem;
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
/* EINE NACHRICHT DARF MEHRZEILIG SEIN (17.09.2026, mit dem grossen
   Eingabefeld). Zwei Dinge gehoeren dazu, und das zweite vergisst man:

   `white-space: pre-wrap` am TEXT laesst die Absaetze stehen, die jemand
   geschrieben hat — ohne das wird aus drei Zeilen eine, und wer eine Liste
   schickt, schickt einen Fliesstext.

   Den HAENGENDEN EINZUG, der die Folgezeilen unter dem Text beginnen liess,
   gibt es seit dem 17.10.2026 nicht mehr — siehe unten. */
.ct-zeile {
  margin: 0;
  /* Ueber die ganze Breite des Verlaufs: Der Haus-Stil gibt jedem `p` ein
     `max-width: 68ch` (ui.css oben) — damit hoerten Text UND das Feld eines
     privaten Wortes mitten im Fenster auf, wenn man es breiter zog
     (17.10.2026, Ansage des Bro). */
  max-width: none;
  /* Etwas kleiner als der Rest des Fensters (17.10.2026, Ansage des Bro:
     „mach die chatschrift etwas kleiner"). */
  font-size: 0.8rem;
  line-height: 1.35;
  word-break: break-word;
  /* Zeitstempel und Folgezeilen stehen buendig an derselben Kante (17.10.2026,
     Ansage des Bro: „der zeit stempel sollte bündig sein mit dem abschnitt").
     Bis dahin hing die Uhrzeit um 0.85rem links heraus. Jede Zeile traegt
     dieselbe Luft wie ein privates Feld, damit die Uhrzeiten aller Zeilen
     untereinander stehen. */
  padding: 0.1rem 0.35rem;
}
.ct-text { white-space: pre-wrap; }
.ct-zeit { color: var(--text-dim); font-size: 0.68rem; margin-right: 0.35rem; font-variant-numeric: tabular-nums; }
.ct-von { color: var(--brass-light); margin-right: 0.35rem; }
.ct-von::after { content: ":"; }
/* DER NAME ALS KNOPF (18.10.2026): Unter dem Zeiger leuchtet er auf, ein
   Klick oeffnet das Namensmenue (chat.js). Kein Unterstrich auf Dauer — was
   sich anklicken laesst, zeigt es erst unter dem Zeiger. */
.ct-von-wahl { cursor: var(--cursor-gold, pointer); border-radius: 0; }
.ct-von-wahl:hover,
.ct-von-wahl:focus-visible,
.ct-von-wahl.an {
  color: #fff0cf;
  text-shadow: 0 0 6px rgba(204, 167, 94, 0.65);
  outline: none;
}
/* Das Menue selbst: eine kleine Tafel am Namen, eckig, Messingrand. */
.ct-namenmenue {
  position: absolute;
  z-index: 5;
  min-width: 10.5rem;
  background: linear-gradient(180deg, rgba(36, 40, 46, 0.99), rgba(20, 23, 27, 0.99));
  border: 1px solid var(--brass);
  border-radius: 0;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.65);
  padding-bottom: 0.15rem;
}
.ct-namenmenue[hidden] { display: none; }
.ct-nm-kopf {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.35rem 0.55rem;
  margin-bottom: 0.15rem;
  border-bottom: 1px solid var(--brass-dark);
  color: var(--brass-light);
  font-family: var(--font-display, inherit);
  font-size: 0.86rem;
  white-space: nowrap;
}
.ct-namenmenue button {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  color: var(--text);
  font: inherit;
  font-size: 0.8rem;
  padding: 0.3rem 0.6rem;
  cursor: var(--cursor-gold, pointer);
}
.ct-namenmenue button:hover,
.ct-namenmenue button:focus-visible {
  background: rgba(204, 167, 94, 0.14);
  color: #fff0cf;
  outline: none;
}
/* 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); }
/* Das Feld eines privaten Wortes: Der Einzug bleibt der haengende von
   `.ct-zeile` PLUS die Luft des Feldes. Mit nur 0.35rem stand die Uhrzeit
   (die um 0.85rem nach links haengt) halb ausserhalb ihres Feldes. */
.ct-zeile.privat { background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(109, 84, 38, 0.12); --schein: var(--brass-dark); }
.ct-leer { color: var(--text-dim); font-style: italic; margin: auto; }

/* BEFEHLE (17.10.2026, chat.js `befehl`). Eine Handlung (/me) und ein Wurf
   sind ein Satz ueber den Absender; die Antworten auf Befehle stehen nur im
   eigenen Browser und sind darum leiser als jedes Wort eines Menschen. */
.ct-zeile.ct-me .ct-text { font-style: italic; color: var(--brass-light); }
.ct-zeile.ct-wurf .ct-text { color: var(--brass-light); }
.ct-zeile.ct-hinweis { color: var(--text-dim); font-style: italic; }
.ct-zeile.ct-hinweis .ct-text { white-space: pre-wrap; }

/* Die Liste hinter dem Fragezeichen im Kopf. */
.ct-kopf .ct-frage { margin-left: 0; }
.ct-befehlsfeld { flex: none; margin: 0.4rem 0.5rem 0.1rem; max-height: 40%; overflow-y: auto; }
.ct-befehlsfeld ul { margin: 0; padding: 0; list-style: none; display: grid; grid-template-columns: max-content 1fr; gap: 0.12rem 0.8rem; }
.ct-befehlsfeld li { display: contents; }
.ct-befehlsfeld b { color: var(--brass-light); font-weight: 400; }
/* Die Vorschlaege ueber dem Feld, solange ein Befehl getippt wird. */
.ct-vorschlag {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 4px);
  z-index: 5;
  display: flex;
  flex-direction: column;
  max-height: 14rem;
  overflow-y: auto;
  background: rgba(16, 18, 21, 0.98);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
  scrollbar-width: thin;
}
.ct-vorschlag[hidden] { display: none; }
.ct-vorschlag button {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  width: 100%;
  max-width: none;
  padding: 0.22rem 0.5rem;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  color: var(--text);
  font: inherit;
  font-size: 0.8rem;
  text-align: left;
  cursor: var(--cursor-gold);
}
.ct-vorschlag button:first-child { background: rgba(109, 84, 38, 0.28); }
.ct-vorschlag button:hover { background: rgba(255, 255, 255, 0.08); }
.ct-vorschlag b { color: var(--brass-light); font-weight: 400; white-space: nowrap; }
.ct-vorschlag span { color: var(--text-dim); font-size: 0.74rem; }


/* --- Cunrat der Schreiberling ----------------------------------------------
   Sein Reiter trägt sein Bildnis, sein Faden einen Kopf mit dem Portrait.
   Die Farbe ist Messing wie überall in der Botenstube — er ist ein Dienstmann
   der Burg, kein Fremdes im Fenster. */
.ct-faden.ct-cunrat {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  /* Links etwas schmaler, weil das Bildnis selbst schon Luft mitbringt. */
  padding-left: 0.28rem;
}
/* DER KOPF IM REITER (17.10.2026): Cunrat und jedes Zwiegespraech zeigen
   nur den Kopf aus dem Bildnis, im Ring. Der Ausschnitt steht je Bildart —
   `background-size` ist der Zoom, `background-position` legt die Kopfmitte
   in die Mitte des Rings. Die Lage stammt aus den Bildern selbst
   (cunrat.png 256 × 256, Kopf um 51 % / 28 %; die Bildnisse 164 × 192, Kopf
   um 48 % / 18 %). */
.ct-kopfbild {
  flex: none;
  display: block;
  width: 20px;
  height: 20px;
  /* Eckig wie die Bildnisse sonst im Spiel (Ansage: „kein kreis sondern eher
     quadrat"), nur die Kanten leicht gebrochen. */
  border-radius: 2px;
  border: 1px solid var(--brass-dark);
  background-color: rgba(0, 0, 0, 0.35);
  background-repeat: no-repeat;
}
.ct-kopfbild--cunrat { background-size: 280% auto; background-position: 51% 17%; }
.ct-kopfbild--bildnis { background-size: 240% auto; background-position: 46% 3%; }
.ct-faden.aktiv .ct-kopfbild { border-color: var(--brass-light); }
/* Die Reiter oben tragen Bild, Name, Zahl und Kreuz in einer Reihe. */
.ct-faeden > .ct-faden {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  flex: none;
}
.ct-faeden > .ct-faden:has(.ct-kopfbild) { padding-left: 0.25rem; }
/* Das Kreuz eines Zwiegespraechs. */
.ct-faden-zu {
  margin-left: 0.1rem;
  margin-right: -0.2rem;
  padding: 0 0.2rem;
  line-height: 1;
  font-size: 0.95rem;
  color: var(--text-dim);
  border-radius: 2px;
}
.ct-faden-zu:hover { color: var(--brass-light); background: rgba(255, 255, 255, 0.08); }

.ct-cunrat-kopf {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding-bottom: 0.35rem;
  margin-bottom: 0.1rem;
  border-bottom: 1px solid var(--iron);
  color: var(--brass-light);
  font-size: 0.85rem;
  line-height: 1.3;
}
/* Im Kopf seines Fadens Kopf und Schultern statt des ganzen Mannes. */
.ct-kopfbild--cunrat-gross {
  width: 56px;
  height: 56px;
  border-radius: 2px;
  background-size: 183% auto;
  background-position: 52% 21%;
}
.ct-cunrat-kopf em { color: var(--text-dim); font-size: 0.78rem; }

/* Der Zaehler „3/10" im Kopf des Fadens (12.09.2026).

   Rechts aussen (`margin-left: auto` im Flex-Kopf), klein und gedaempft: Er
   ist eine AUSKUNFT und keine Meldung — wer wissen will, ob er noch fragen
   darf, findet ihn; wer gerade schreibt, wird nicht von ihm angesprungen.

   `tabular-nums`, damit die Zahl beim Hochzaehlen nicht in der Breite
   springt: Ohne das wandert der Kasten bei jeder Frage um ein paar Pixel. */
.ct-cu-zaehler {
  margin-left: auto;
  align-self: flex-start;
  flex: 0 0 auto;
  padding: 0.05rem 0.3rem;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  color: var(--text-dim);
  font-size: 0.72rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Frage und Antwort stehen versetzt: Ohne das liest sich ein Gespräch mit nur
   zwei Stimmen wie ein einziger Textblock. */
.ct-zeile.ct-cu-frage { padding-left: 1.2rem; }
.ct-zeile.ct-cu-frage .ct-von { color: var(--moss); }
.ct-zeile.ct-cu-antwort {
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(109, 84, 38, 0.14);
  --schein: var(--brass-dark);
  padding: 0.15rem 0.35rem;
  /* Cunrat schreibt in Absätzen; die Zeilen dürfen umbrechen, ohne dass der
     Name mitwandert. */
  white-space: pre-wrap;
}
/* Ein BRIEF (21.10.2026, cunratBriefe.ts) — Cunrat schreibt ungefragt, wenn in
   seinen Büchern etwas schiefläuft. Dieselbe Zeile wie eine Antwort, am Rand
   ein Messingstrich: Man sieht, dass niemand danach gefragt hat. */
.ct-zeile.ct-cu-brief { border-left: 2px solid var(--brass-dark); }
/* „Taucht die Feder ein …" — dieselbe Zeile wie eine Antwort, nur blass und
   atmend. Die Bewegung liegt auf der Deckkraft und nicht auf Text, der sich
   ändert: Ein wandernder Punkt (". .. ...") müsste über einen Takt gesteuert
   werden, und der stünde still, sobald der Hauptstrang beschäftigt ist. */
.ct-zeile.ct-denkt { font-style: italic; animation: ct-feder 1.4s ease-in-out infinite; }
@keyframes ct-feder {
  0%, 100% { opacity: 0.45; }
  50% { opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) {
  .ct-zeile.ct-denkt { animation: none; opacity: 0.7; }
}



/* --- DAS EINGABEFELD IST MEHRZEILIG (17.09.2026) ---------------------------
   Ansage des Bro: „dass man längere texte schreiben kann in das chat fenster".

   `align-items: flex-end` haelt den Senden-Knopf unten, waehrend das Feld
   nach oben waechst — oben ausgerichtet staende er neben der ERSTEN Zeile und
   waere bei einem langen Text weit vom Ende des Tippens entfernt. */
.ct-eingabe {
  display: flex;
  /* `flex-direction` UND `max-width` AUSDRUECKLICH — sonst ist die Eingabe
     eine SPALTE von hoechstens 340 Pixeln.

     `form` traegt im Haus-Stil (ui.css, Zeile ~481) `display: flex;
     flex-direction: column; max-width: 340px` — gemacht fuer die
     Anmeldemaske, aber es trifft JEDES Formular im Haus. Ein `display: flex`
     allein reicht hier also NICHT: Die Richtung kommt aus derselben Regel und
     bleibt stehen.

     Das war hier schon vor dem Umbau falsch (gefunden am 17.09.2026, im
     Browser gemessen: `flex-direction: column`): Der Senden-Knopf stand unter
     dem Eingabefeld statt daneben, die ganze Zeit. Bei einem schmalen Feld
     und einem schmalen Knopf faellt das kaum auf — es sieht aus wie eine
     Gestaltung. Dieselbe Falle steht in CLAUDE.md und ist am Absendeknopf
     neben Cunrats Eingabefeld schon einmal bezahlt worden. */
  flex-direction: row;
  max-width: none;
  align-items: flex-end;
  gap: 0.3rem;
  padding: 0.4rem;
  border-top: 1px solid var(--iron);
  flex: 0 0 auto;
}
.ct-feldrahmen {
  position: relative;
  flex: 1;
  min-width: 0;
  display: flex;
}
/* EIN `textarea` BRINGT KEINE HAUS-CHROMIK MIT.

   Der Haus-Stil oben in dieser Datei gibt `input[type=text]` Farbe, Rand,
   Innenschatten und Zeiger — `textarea` steht dort NUR beim Zeiger dabei.
   Ohne diesen Block saesse mitten im messingnen Fenster ein weisses
   Browser-Feld. Die Werte sind deshalb dieselben wie bei `input[type=text]`
   (Zeile ~498) und muessen es bleiben; wer sie dort aendert, sieht hier nichts.

   `resize: none`, weil das Feld seine Hoehe selbst fuehrt (chat.js,
   `feldWachsen`): Zwei Stellen an derselben Hoehe heissen ein Feld, das nach
   jedem Tastendruck zurueckspringt. */
.ct-feld {
  flex: 1;
  min-width: 0;
  font-family: var(--font-body);
  font-size: 0.88rem;
  line-height: 1.35;
  color: var(--text);
  background: #14171a;
  border: 1px solid var(--iron);
  border-radius: 2px;
  padding: 0.3rem 0.45rem;
  box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.55);
  cursor: text;
  resize: none;
  overflow-y: hidden;
  scrollbar-width: thin;
}
/* `input:focus` im Haus-Stil trifft ein `textarea` nicht — der Rahmen muss
   hier eigens leuchten, sonst sieht man dem Feld nicht an, dass es die
   Tastatur hat. */
.ct-feld: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);
}
/* Die Zeichenzahl, die erst nahe der Grenze erscheint (chat.js,
   `zaehleZeichen`). Sie sitzt IM Feld unten rechts statt in einer eigenen
   Zeile: Eine Zeile, die auftaucht, schoebe bei jedem Erscheinen den ganzen
   Verlauf nach oben. `pointer-events: none`, damit ein Klick darauf ins Feld
   geht und nicht ins Leere. */
.ct-zaehlung {
  position: absolute;
  right: 0.35rem;
  bottom: 0.15rem;
  font-size: 0.68rem;
  font-variant-numeric: tabular-nums;
  color: var(--text-dim);
  background: rgba(20, 23, 26, 0.85);
  padding: 0 0.15rem;
  border-radius: 2px;
  pointer-events: none;
}
.ct-zaehlung[hidden] { display: none; }
.ct-zaehlung.knapp { color: #d08a7a; }
.ct-eingabe button { font-size: 0.85rem; padding: 0.3rem 0.7rem; flex: none; }
.ct-fehler {
  margin: 0;
  padding: 0 0.55rem 0.4rem;
  font-size: 0.8rem;
  color: #d08a7a;
}

/* --- GRUPPENCHATS UND WAPPEN — uebernommen aus dem Nachbarspiel (12.09.2026)
   ---------------------------------------------------------------------------
   Wortgleich uebernommen, samt der Begruendungen des Nachbarn. Eingesetzt
   HINTER der Eingabe und nicht davor, obwohl drueben die Reihenfolge anders
   ist: Vor der Eingabe stossen diese Regeln unmittelbar an Cunrats Block, und
   zwei Einfuegungen ohne eine unveraenderte Zeile dazwischen sind in einem
   Diff EIN Block. Fuer die Kaskade ist es gleich — keine dieser Regeln trifft
   eine von Cunrat oder von der Eingabe.

   HIER STAND EIN KAPUTTER KOMMENTAR, und er hat .ct-wappen GEKOSTET
   (repariert am 17.09.2026). Beim Zusammenfuehren zweier Uebernahmen blieben
   drei Kommentarschluesse stehen, zwischen denen blanker Text lag. Fuer den
   CSS-Parser war dieser Text der Anfang eines SELEKTORS, und er las weiter bis
   zur naechsten geschweiften Klammer — also bis zu der von `.ct-wappen`. Die
   ganze Regel wurde damit als Teil eines ungueltigen Selektors verworfen: Im
   Browser nachgemessen enthielt das geparste Stylesheet `.ct-wappen` gar
   nicht, und die Wappen im Verlauf standen in voller Bildgroesse da statt als
   kleines Schild.

   ZWEI LEHREN, und die zweite ist beim Reparieren selbst bezahlt worden:

   1. EIN KAPUTTER KOMMENTAR IN CSS FRISST DIE NAECHSTE REGEL. Keine
      Fehlermeldung, keine Warnung, und die verlorene Regel ist nie die, bei
      der der Text steht.

   2. IN EINEM KOMMENTAR DARF DIE ZEICHENFOLGE, DIE IHN BEENDET, NICHT
      VORKOMMEN — auch nicht in Anfuehrungszeichen, auch nicht als Beispiel.
      Der erste Anlauf dieser Reparatur nannte sie woertlich; damit endete der
      Kommentar mitten im Satz, der Rest wurde Selektor, und ab dieser Stelle
      fiel der GANZE REST DER DATEI aus — 554 Regeln statt einer. Gemessen im
      Browser: 1296 geparste Regeln statt 1850. Wer davon erzaehlen muss,
      umschreibt es.

   Das Schild ist klein, weil es NEBEN dem Namen steht und nicht statt seiner.
   Ein groesseres schoebe die Namen auseinander und machte aus dem Gespraech
   eine Kartei. `ct-wappen-leer` haelt den Platz fuer alle, die keins gewaehlt
   haben: Sonst faengt jede Zeile woanders an. */
.ct-wappen {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  margin-right: 0.3rem;
  vertical-align: -0.1em;
  object-fit: contain;
  flex: none;
}
.ct-wappen-leer { opacity: 0; }
/* HIER STANDEN `.ct-zeile.selbst .ct-von`, `.ct-zeile.privat` und `.ct-leer`
   ein ZWEITES Mal, Zeichen fuer Zeichen gleich wie weiter oben — mit der
   Uebernahme aus dem Nachbarspiel mitgekommen (entfernt am 17.09.2026). Die
   zweite Fassung gewann und sagte dasselbe, es war also nichts zu sehen. Der
   Schaden kommt beim naechsten Griff: Wer die erste aendert, sieht keine
   Wirkung und sucht den Fehler an der falschen Stelle. */
/* --- Gespraechsrunden (12.09.2026) ---------------------------------------
   Der Bogen zum Gruenden klappt UEBER der Eingabezeile auf, statt als
   eigenes Fenster daneben: Er gehoert in den Chat, und er nimmt ihm den
   Platz nur, solange er offen ist. */
.ct-rundenbau {
  border-top: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.2));
  padding: 0.3rem 0.4rem;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  max-height: 12rem;
}
/* OHNE DIESE ZEILE SCHLIESST DER BOGEN NIE (13.09.2026, gemeldet: "Runde
   gründen-Fenster, wenn man eine Runde gegründet hat, auch schließen").
   `hidden` setzt `display: none` nur im Browser-Grundstil — jede eigene
   `display`-Angabe gewinnt dagegen, und die steht eine Zeile darüber. Der
   Code schloss also korrekt (`rundenbau.hidden = true`), die Anzeige nicht:
   auch nicht beim Abbrechen und nicht beim zweiten Druck auf "Runde …".
   Das ganze Haus macht es darum so — `.chatfenster[hidden]`, `.ct-summe[hidden]`
   und ein Dutzend weitere stehen genauso da. Wer hier ein Element mit
   `display` versieht, das über `hidden` verschwinden soll, schreibt die
   Gegenzeile gleich mit. */
.ct-rundenbau[hidden] { display: none; }
.ct-rb-titel { margin: 0; color: var(--brass-light); font-size: 0.82rem; }
/* DER KANAL-BOGEN IST EINE ZEILE (18.10.2026, Ansage des Bro: „die buttons
   … genauso groß machen wie senden und auch das text feld kleiner. das
   chatfenster muss kompakt bleiben"). Das Feld nimmt den Rest, die Knöpfe
   tragen die Maße von „Senden" (`.ct-eingabe button`). */
.ct-rb-zeile { display: flex; gap: 0.3rem; align-items: center; }
.ct-rb-name {
  flex: 1 1 auto;
  min-width: 0;
  width: auto;
  max-width: none;
  margin: 0;
  padding: 0.22rem 0.4rem;
  font-size: 0.82rem;
  line-height: 1.2;
}
/* Die Namensliste scrollt fuer sich: Bei zwoelf Mitspielern waere der Bogen
   sonst hoeher als das Chatfenster, und der Gruenden-Knopf laege darunter. */
.ct-rb-leute { overflow-y: auto; display: flex; flex-direction: column; gap: 0; }
/* EINE ZEILE JE PERSON, DER HAKEN GANZ RECHTS (13.09.2026, auf Ansage).
   Vorher stand das Kaestchen UEBER dem Namen — und das war kein Zufall,
   sondern diese Zeile hier im Haus-Stil:

     label { display: flex; flex-direction: column; … text-transform: uppercase }

   Die alte Regel setzte nur `display: flex` und erbte damit die SPALTE. Wappen,
   Name, Burg und Haken standen also untereinander, und bei mehreren Leuten
   wusste man beim Ankreuzen nicht mehr, wen man erwischt — genau die gemeldete
   Beobachtung. Wer hier etwas aendert, setzt `flex-direction` also ausdruecklich:
   Ein `display: flex` allein reicht bei einem <label> in diesem Projekt NICHT.

   Der Rest haelt die Zeile beisammen: `nowrap` laesst sie gar nicht erst
   brechen, `margin-left: auto` klebt den Haken an den rechten Rand (sichtbar
   an genau EINE Zeile), und die Burg ist das einzige Stueck, das bei
   Platzmangel gekuerzt wird — sie ist der Zusatz, der Name die Auskunft. */
.ct-person {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.82rem;
  /* Namen sind Eigennamen, keine Beschriftung: Die Versalien und die weite
     Laufweite aus der label-Regel machten aus "Burg Spandow" ein Schild. */
  text-transform: none;
  letter-spacing: normal;
  color: var(--text);
  cursor: var(--cursor-gold);
  white-space: nowrap;
  padding: 0.12rem 0.2rem;
  border-radius: 2px;
}
.ct-person:hover { background: rgba(255, 255, 255, 0.07); }
/* DIE ZEILE ALS KNOPF — im Privat-Bogen (chat.js, oeffnePrivat). Sie soll
   aussehen wie die Zeile mit Haken im Runden-Bogen; der Haus-Stil fuer
   `button` (Verlauf, Messingrand, Schatten, fette Schrift) wird darum hier
   ausdruecklich zurueckgenommen, sonst stuende eine Knopfreihe da. */
button.ct-person {
  width: 100%;
  background: none;
  border: 0;
  box-shadow: none;
  font-family: inherit;
  font-weight: 400;
  text-align: left;
  transform: none;
}
.ct-p-wappen { width: 1em; height: 1em; margin-right: 0; }
.ct-p-name { flex: none; }
/* Der Burgname darf schrumpfen und verschwinden, der Haken nie. */
.ct-p-burg {
  color: var(--text-dim);
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ct-person input[type="checkbox"] { margin: 0 0 0 auto; flex: none; cursor: var(--cursor-gold); }
.ct-rb-knoepfe { display: flex; gap: 0.35rem; justify-content: flex-end; }
.ct-rb-knoepfe button,
.ct-rb-zeile button { font-size: 0.85rem; padding: 0.3rem 0.7rem; width: auto; flex: none; margin: 0; cursor: var(--cursor-gold); }
.ct-rb-knoepfe button[disabled],
.ct-rb-zeile button[disabled] { opacity: 0.45; cursor: var(--cursor-kupfer); }

.ct-fehler[hidden] { display: none; }

/* DIE KANTEN ZUM ZIEHEN (17.09.2026) — links, rechts und unten.

   Mit der Ecke allein ging es nur nach rechts und unten: Wer das Fenster
   BREITER wollte und es stand am rechten Bildrand, musste es erst nach links
   schieben, dann ziehen, dann zurueckschieben.

   Unsichtbar und nur ueber den Zeiger zu finden — dieselbe Machart wie in
   jedem Fensterverwalter. Sie enden vor der Ecke (`bottom: 14px` bzw.
   `right: 14px`), damit die Ecke ihre beiden Achsen behaelt; laegen sie
   darueber, zoege man an der Ecke nur noch in einer Richtung.

   Nur am CHATFENSTER: Chronik, Produktion, Heerschau und Auftragsfenster
   teilen sich zwar `.chatfenster` und `.ct-griffecke`, bringen aber ihr
   eigenes Ziehen mit und wuessten mit einem Griff nichts anzufangen, auf den
   niemand hoert. */
#chatfenster .ct-kante {
  position: absolute;
  z-index: 3;
}
#chatfenster .ct-kante-l {
  left: 0;
  top: 0;
  bottom: 14px;
  width: 5px;
  cursor: ew-resize;
}
#chatfenster .ct-kante-r {
  right: 0;
  top: 0;
  bottom: 14px;
  width: 5px;
  cursor: ew-resize;
}
#chatfenster .ct-kante-u {
  left: 0;
  right: 14px;
  bottom: 0;
  height: 5px;
  cursor: ns-resize;
}

/* 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;
  /* Ueber den Kanten (z-index 3): Ihre 5 Pixel wuerden sonst die aeusserste
     Reihe der Ecke verdecken, und genau dort zielt man hin. */
  z-index: 4;
  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. */
/* Seit 20.10.2026 EINE Leiste gleich breiter Felder mit Haarlinien — das
   Muster der Tafeln (Einstellungsfenster). */
.pf-spannen {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--iron, rgba(255, 255, 255, 0.18));
  margin-bottom: 0.6rem;
}
.pf-spanne {
  padding: 0.2rem 0;
  border: 0;
  border-left: 1px solid var(--iron, rgba(255, 255, 255, 0.18));
  border-radius: 0;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-body), serif;
  font-size: 0.8rem;
  text-align: center;
  letter-spacing: normal;
  text-transform: none;
  box-shadow: none;
  min-width: 0;
  width: 100%;
  cursor: var(--cursor-gold);
}
.pf-spanne:first-child { border-left: 0; }
.pf-spanne:hover { color: var(--text); }
.pf-spanne.aktiv {
  color: var(--brass-light);
  background: rgba(201, 163, 90, 0.12);
}

/* 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: 192px;
  margin-bottom: 0.5rem;
}
.pf-graphkopf {
  font-size: 0.9rem;
  margin-bottom: 0.15rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.pf-legende {
  margin-left: auto;
  font-size: 0.75rem;
  color: var(--text-dim);
  display: inline-flex;
  align-items: center;
  gap: 0.8rem;
}
.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-legende i.pf-mark-balken {
  width: 0.45rem;
  height: 0.6rem;
  border: 0;
  background: var(--fire-light);
  opacity: 0.55;
  vertical-align: -1px;
}
/* Das Bild der Ware — in der Zeile und über dem Graph. */
.pf-bild {
  width: 20px;
  height: 20px;
  vertical-align: -5px;
  margin-right: 0.4rem;
}
.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-gitter { stroke: rgba(255, 255, 255, 0.06); stroke-width: 1; }
.pf-tag { stroke: rgba(201, 163, 90, 0.28); stroke-width: 1; stroke-dasharray: 2 3; }
.pf-marke {
  fill: var(--text-dim);
  font-family: var(--font-body), serif;
  font-size: 10.5px;
}
.pf-tagtext { fill: var(--brass); opacity: 0.8; }
/* Was auf einen Schlag kam oder ging (Bauen, Handel, Abriss; Migration 0174). */
.pf-balken-aus { fill: var(--fire-light); opacity: 0.5; }
.pf-balken-ein { fill: var(--moss); opacity: 0.5; }
.pf-minus-text { fill: var(--fire-light); }
.pf-plus-text { fill: var(--moss); }

/* 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.85rem;
  width: 100%;
  border-collapse: collapse;
}
/* Die Einheit steht EINMAL unter dem Spaltenkopf, nicht in jeder Überschrift
   — das hält die Zahlenspalten schmal (20.10.2026). */
.pf-tabelle thead th {
  white-space: nowrap;
  font-weight: normal;
  font-size: 0.78rem;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text-dim);
  padding-bottom: 0;
  border-bottom: 0;
}
.pf-tabelle .pf-einheit th {
  padding-top: 0;
  font-size: 0.68rem;
  opacity: 0.8;
  border-bottom: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
}
.pf-ware { white-space: nowrap; }
/* 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: var(--cursor-gold); }
.pf-zeile:hover { background: rgba(255, 255, 255, 0.05); }
/* Die Wahl ist EIN Band über die ganze Zeile — am tr, nicht je Zelle, sonst
   bricht der Verlauf an jeder Spalte neu an (20.10.2026); links eine
   Haarlinie wie die Trennlinie unter dem Kopf. */
.pf-zeile.pf-gewaehlt {
  background: linear-gradient(90deg, rgba(201, 163, 90, 0.26), rgba(201, 163, 90, 0.06) 85%);
  box-shadow: inset 1px 0 0 var(--brass-dark, rgba(255, 255, 255, 0.25));
}
.pf-zeile:focus-visible { outline: 1px solid var(--brass); outline-offset: -1px; }
/* Was gerade ruht (13.09.2026): da, aber blass — die Zeile sagt „null",
   statt zu fehlen und damit „gibt es nicht" zu sagen. */
.pf-zeile.pf-ruht td { opacity: 0.5; }
.pf-zeile.pf-ruht:hover td,
.pf-zeile.pf-ruht.pf-gewaehlt td { opacity: 0.85; }
.pf-trenner td {
  padding-top: 0.7rem !important;
  font-size: 0.72rem;
  color: var(--text-dim);
  letter-spacing: 0.02em;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.pf-sparte { width: 76px; 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. */
/* WINZIG IN DIE ECKE GEDRÜCKT (20.10.2026, Ansage des Bro: „der version
   stempel wird winzig klein in die ecke nach unten links gedrückt") — dort
   liegt jetzt die Mappe des Siegeldecks. */
.versionsschild {
  position: fixed;
  left: 2px;
  bottom: 1px;
  z-index: 2100;
  padding: 0 0.25rem;
  border-radius: 2px;
  font-family: var(--font-body), serif;
  font-size: 9px;
  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: var(--cursor-gold);
  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: auto;
}
/* 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; }

/* Die dauerhaften Boni der Klasse (21.09.2026) — über der Mitgift, weil sie
   bleiben, wenn die Mitgift längst verbraucht ist. */
.ch-klassenbonus {
  margin: 0 0 .6rem;
  padding: .35rem .5rem;
  --schein: var(--brass, #a8813d);
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(0, 0, 0, .18);
}
.ch-klassenbonus-titel { font-size: .8em; color: var(--text-dim); }
.ch-klassenbonus ul { list-style: none; margin: .1rem 0 0; padding: 0; }
.ch-klassenbonus li { padding: 1px 0; }
.ch-klassenbonus strong { display: block; color: #6fbf5a; font-size: .95em; }
.ch-klassenbonus span { display: block; font-size: .8em; color: var(--text-dim); }

.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: var(--cursor-kupfer);
}
.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; }

/* VERGEBEN: Dieses Bildnis, dieses Wappen trägt schon ein anderes Haus
   (vergeben.ts, charakter.js). Wie beim Gesperrten bleibt die Kachel STEHEN
   und wird nur grau — rückte die Reihe bei jedem neuen Spieler, fände niemand
   sein Gesicht an der Stelle wieder, an der er es gestern sah. */
.ch-kachel.vergeben { cursor: var(--cursor-kupfer); }
.ch-kachel.vergeben img {
  filter: grayscale(1) brightness(0.55);
  opacity: 0.45;
}
.ch-kachel.vergeben .ch-symbol { opacity: 0.22; }
.ch-kachel.vergeben:hover img,
.ch-kachel.vergeben:hover .ch-symbol { border-color: var(--iron); }
/* Eine vergebene FARBE sieht aus wie eine gesperrte: Für den Spieler ist es
   dieselbe Auskunft — diese hier geht gerade nicht. Der Grund steht darunter. */
.ch-farbe.vergeben { cursor: var(--cursor-kupfer); }
.ch-farbe.vergeben .ch-farbe-tupfen {
  opacity: 0.3;
  border-style: dashed;
  border-color: var(--iron);
  position: relative;
}
.ch-farbe.vergeben .ch-farbe-tupfen::after {
  content: "";
  position: absolute;
  inset: -2px;
  background: linear-gradient(45deg, transparent 45%, var(--text-dim) 45% 55%, transparent 55%);
}
.ch-vergeben-hinweis {
  margin: 0.4rem 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
  font-style: italic;
}
.ch-vergeben-hinweis[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); }

/* --- Die drei Ausbaustufen unter der Karte ------------------------------
   Drei schmale Fernblicke nebeneinander: Palisade mit Holzturm, dann
   Feldsteinmauer, dann der steinerne Turm. Sie sagen, WOHIN der Weg fuehrt —
   das Stillleben darueber zeigt nur den Tisch.

   KLEINER UND BLASSER als das Hauptbild, und das ist der Punkt: Es ist ein
   Ausblick, keine zweite Wahl. Bei einer Kartenbreite von 220 bis 400 Pixeln
   ist ein Streifen 60 bis 130 breit — mehr als eine Andeutung kann er nicht
   sein, und mehr soll er auch nicht.

   `aria-hidden` am Halter: Fuer einen Screenreader waeren es drei leere
   Bilder, die nichts sagen, was nicht schon im Text steht. */
/* DIE DREI AUSBAUSTUFEN — seit dem 12.09.2026 die echten Turmmodelle,
   isometrisch aus Blender, mit durchsichtigem Grund.

   KEIN RAHMEN MEHR um das Bild. Er war richtig, solange dort gemalte
   Fernblicke standen: Ein Bild braucht eine Kante. Ein freigestellter Turm
   braucht sie nicht — ein Kasten um ihn herum waere ein leerer Kasten mit
   einem Turm darin.

   `align-items: end` statt einer Mitte: Die drei Kacheln sind gleich hoch
   geschnitten (gemeinsame Huelle ueber alle neun), aber ihre Tuerme stehen
   verschieden hoch darin. Ausgerichtet wird am BODEN, sonst schwebte Stufe 1
   neben Stufe 3. */
.ch-stufen {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-items: end;
  gap: 6px;
  margin-top: .7rem;
  padding-top: .6rem;
  border-top: 1px solid var(--iron);
}
.ch-stufe { margin: 0; }
.ch-stufe img {
  display: block;
  width: 100%;
  height: auto;
  /* Gedaempft, solange die Klasse nicht gewaehlt ist — dieselbe Sprache wie
     beim Stillleben darueber. Kein Graustufenfilter: Der Unterschied zwischen
     den Stufen IST der Baustoff (Holz, dann Feldstein), und der ist eine
     Farbe. */
  filter: saturate(0.6) brightness(0.68);
  transition: filter 0.25s;
}
.ch-stufe figcaption {
  margin-top: 2px;
  text-align: center;
  font-size: .7em;
  letter-spacing: .12em;
  color: var(--text-dim);
}
.ch-herkunft input:checked ~ .ch-herkunft-tafel .ch-stufe img {
  /* Voll gesaettigt UND mit Schatten: Der Renderer wirft keinen
     (durchsichtiger Grund), und ohne ihn steht der Turm auf nichts. Eine
     einzige filter-Zeile — zwei hintereinander waeren nicht additiv, die
     zweite ersetzt die erste. */
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.55));
}
.ch-herkunft input:checked ~ .ch-herkunft-tafel .ch-stufe figcaption { color: var(--brass-light); }
.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: auto;
}
.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: seit dem 25.09.2026 RAUS (Ansage des Bro: „weg von diesen
   kerzenlichtern … schwarzer hintergrund und das fenster so wie wir das immer
   machen"). Den Stil der Charakterseite trägt /static/charakter.css. */

/* 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-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; }


/* --- DIE DIPLOMATIE-TAFEL (seit 02.10.2026 ganz neu, diplomatie.js) ---------

   Ansage des Bro: „die soll komplett neu gmeacht werden. wichtig die soll
   schön groß und übersichtlich sein" — und dunkelgrau bis schwarz mit
   Messing wie jede Tafel. Oben das gewählte Haus (Wappen, Name, Werte,
   Bildnis), darunter zwei GLEICH GROSSE Listen mit GLEICH GROSSEN Schilden
   (Adelshäuser und Beziehungen), unten die Siegelträger und ihre Handlungen.
   Das Vorhaben steht in docs/vorhaben/diplomatie-tafel.md.

   Noch am selben Tag KOMPAKTER („die tafel schon etwas kompakter machen …
   das ist bisschen zu groß alles … also kleiner skalieren"): Die Burgansicht
   rechnet mit einer Wurzelschrift von rund 19 Pixeln, jedes rem ist dort ein
   Fünftel größer als gewohnt. Und keine Ecke runder als 2 Pixel („bitte
   nichts so viel abrunden").

   UND SIE SPRINGT NICHT (am Abend: „beim klicken springt die tafel bitte so
   machen dass man ohne springende tafel hin und her schalten kann"):
   fenster.js setzt ein mittiges Werkzeug neu in die Mitte, sobald sich seine
   Größe ändert. Die Tafel hat darum eine FESTE Höhe, Kopf und Siegelträger
   ihre feste Größe, die Listen nehmen den Rest — und was nicht hineinpasst,
   rollt innen.                                                              */

.diplomatietafel {
  display: flex;
  flex-direction: column;
  width: min(58rem, calc(100vw - 1.6rem));
  height: min(40rem, calc(100vh - var(--kopfband-hoehe, 42px) - 1.6rem));
  max-height: calc(100vh - var(--kopfband-hoehe, 42px) - 1.6rem);
  overflow: hidden;
  padding: 0;
  background: #15171b;
  border: 1px solid var(--brass-dark, #6d5426);
  border-radius: 2px;
  font-family: var(--font-body, Georgia, serif);
  font-size: 0.86rem;
}
/* `display: flex` oben sticht das `hidden` des Browsers — ohne diese Zeile
   ginge die Tafel nie wieder zu. */
.diplomatietafel[hidden] { display: none; }
/* Der Tafelkopf (`.tafelkopf`) mit dem Einfluss zwischen Titel und Kreuz. */
.diplomatietafel .dt-kopfleiste {
  flex: none;
  background: #0e1013;
}
.diplomatietafel .dt-einfluss { margin-right: 0.3rem; }
.diplomatietafel .dt-kopfleiste h3.tafelkopf__titel { font-family: var(--font-display); font-size: 1.2rem; margin: 0; padding: 0; border: none; }
.diplomatietafel .dt-einfluss { text-align: right; line-height: 1; }
.diplomatietafel .dt-einfluss span { display: block; font-size: 0.68rem; color: var(--text-dim, #928b7d); margin-bottom: 0.1rem; }
.diplomatietafel .dt-einfluss b {
  font-family: var(--font-display, serif);
  font-size: 1.75rem;
  font-weight: normal;
  color: #f3d27a;
  font-variant-numeric: tabular-nums;
}
.diplomatietafel .dt-kopfleiste .ort-zu { position: static; }
.diplomatietafel #diploinhalt {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  /* Erst auf einem sehr niedrigen Schirm rollt die ganze Tafel — sonst rollen
     nur die Listen und die Handlungen in sich. */
  overflow-y: auto;
  padding: 0.6rem 0.8rem 0.7rem;
}
.diplomatietafel h4 {
  margin: 0 0 0.25rem;
  font-family: var(--font-display, serif);
  font-size: 1.05rem;
  font-weight: normal;
  color: var(--brass-light, #cca75e);
}
.diplomatietafel h5 { margin: 0 0 0.2rem; font-size: 0.92rem; font-weight: normal; color: var(--parchment, #d7c7a3); }
.diplomatietafel .dt-leise { color: var(--text-dim, #928b7d); font-size: 0.88em; }
.diplomatietafel .dt-gut { color: #a6e06a; }
.diplomatietafel .dt-bos { color: #f0745a; }
.diplomatietafel .lauf { color: #e0b060; font-variant-numeric: tabular-nums; }
.diplomatietafel button {
  font: inherit;
  font-size: 0.82rem;
  color: var(--text, #d2ccbf);
  background: #22262b;
  border: 1px solid var(--brass-dark, #6d5426);
  border-radius: 2px;
  padding: 0.16rem 0.5rem;
  cursor: var(--cursor-gold, pointer);
}
.diplomatietafel button:hover:not(:disabled) { border-color: var(--brass-light, #cca75e); }
.diplomatietafel button:disabled { opacity: 0.45; cursor: var(--cursor-kupfer, default); }
.diplomatietafel button.dt-gold { color: #f3d27a; border-color: var(--brass, #a8813d); }
/* „Auf der Karte zeigen“ unter den Angaben (24.10.2026, diplomatie.js `karteKnopfHtml`). */
.diplomatietafel .dt-karteplatz { margin-top: 0.45rem; }
.diplomatietafel button.dt-karteknopf { color: var(--brass-light, #cca75e); padding: 0.22rem 0.7rem; }
.diplomatietafel input, .diplomatietafel select {
  font: inherit;
  font-size: 0.8rem;
  color: inherit;
  background: #0d0f11;
  border: 1px solid var(--iron, #3b414a);
  border-radius: 2px;
  padding: 0.05rem 0.25rem;
}

/* Das Wappen als Schild: das quadratische Bild in der Schildform, ein
   Messingrand darum — dieselbe Form wie im Kopfband (SCHILDFORM). Zwei
   Masken übereinander: die äußere ist der Rand, die innere das Bild. */
.diplomatietafel .dt-wappen {
  --schild: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 118' preserveAspectRatio='none'><path d='M3 10 Q3 2 12 2 L88 2 Q97 2 97 10 L97 52 C97 86 74 108 50 116 C26 108 3 86 3 52 Z'/></svg>");
  display: inline-block;
  flex: none;
  width: 1.6rem;
  aspect-ratio: 100 / 118;
  padding: 2px;
  background: var(--brass, #a8813d);
  -webkit-mask: var(--schild) center / 100% 100% no-repeat;
  mask: var(--schild) center / 100% 100% no-repeat;
}
.diplomatietafel .dt-wappen img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #2a2d33;
  -webkit-mask: var(--schild) center / 100% 100% no-repeat;
  mask: var(--schild) center / 100% 100% no-repeat;
}

/* --- Der Kopf: Wappen, Angaben, Bildnis ---
   FESTE Höhe für jedes Haus — er hat keine Knöpfe mehr (Bündnis, Frieden und
   Fehdebrief bringt ein Siegelträger), nur eine Zeile, die sagt, wie es
   steht. Wuchs er mit dem Haus, rutschte die Liste darunter beim Klick unter
   dem Zeiger weg, und die ganze Tafel rückte neu in die Mitte. */
.diplomatietafel .dt-haus {
  flex: none;
  display: grid;
  grid-template-columns: 6.4rem minmax(0, 1fr) 5.6rem;
  gap: 0.8rem;
  align-items: start;
  height: 7.6rem;
  overflow: hidden;
  margin-bottom: 0.6rem;
}
.diplomatietafel .dt-grossschild { position: relative; width: 6.4rem; aspect-ratio: 100 / 118; }
.diplomatietafel .dt-wappen.gross {
  position: absolute;
  inset: 0;
  width: 100%;
  padding: 3px;
  background: var(--brass-light, #cca75e);
  opacity: 0;
  transition: opacity 0.55s ease;
}
.diplomatietafel .dt-wappen.gross.sichtbar { opacity: 1; }
.diplomatietafel .dt-titel { display: flex; align-items: baseline; gap: 0.5rem; white-space: nowrap; overflow: hidden; }
.diplomatietafel .dt-titel h2 {
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: var(--font-display, serif);
  font-size: 1.5rem;
  font-weight: normal;
  line-height: 1.05;
  color: var(--brass-light, #cca75e);
}
.diplomatietafel .dt-unterzeile {
  margin: 0.1rem 0 0.35rem;
  color: var(--text-dim, #928b7d);
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Die Werte in ZWEI Spalten: Stärke | Reichtum, Verruf | Zu Euch. */
.diplomatietafel .dt-werte {
  display: grid;
  grid-template-columns: 3.9rem 5.2rem minmax(0, 1fr) 3.9rem 5.2rem minmax(0, 1fr);
  align-items: center;
  gap: 0.22rem 0.45rem;
}
.diplomatietafel .dt-wname { color: var(--text-dim, #928b7d); font-size: 0.8rem; }
.diplomatietafel .dt-wwort { font-size: 0.84rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Wie schnell sich eine Beziehung gerade bewegt (19.10.2026, pflegeHtml in diplomatie.js). */
.diplomatietafel .dt-pflege { font-variant-numeric: tabular-nums; white-space: nowrap; }
.diplomatietafel .dt-pflege.plus { color: #7fd98f; }
.diplomatietafel .dt-pflege.minus { color: #e8705f; }
.diplomatietafel .dt-stufen { display: flex; gap: 2px; }
.diplomatietafel .dt-stufen i { flex: 1; height: 0.5rem; background: #0b0c0e; border: 1px solid var(--iron, #3b414a); border-radius: 0; }
.diplomatietafel .dt-stufen.staerke i.voll { background: var(--brass, #a8813d); }
.diplomatietafel .dt-stufen.reichtum i.voll { background: #c9a14a; }
.diplomatietafel .dt-stufen.verruf i.voll { background: #8f3d2c; }
.diplomatietafel .dt-bez {
  position: relative;
  display: inline-block;
  flex: none;
  width: 5.2rem;
  height: 0.5rem;
  background: #0b0c0e;
  border: 1px solid var(--iron, #3b414a);
  border-radius: 0;
}
.diplomatietafel .dt-bez::after { content: ""; position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--iron-light, #565d67); }
.diplomatietafel .dt-bez i { position: absolute; top: 0; bottom: 0; }
.diplomatietafel .dt-bez i.rechts { left: 50%; background: var(--moss, #7a9166); }
.diplomatietafel .dt-bez i.links { right: 50%; background: #8f3d2c; }
/* Wie es steht — EINE Zeile, gleich ob leer oder voll. */
.diplomatietafel .dt-lage {
  height: 1.2rem;
  margin-top: 0.4rem;
  font-size: 0.8rem;
  line-height: 1.2rem;
  color: var(--parchment, #d7c7a3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.diplomatietafel .dt-angebot { color: #f3d27a; }
.diplomatietafel .dt-bildnis {
  width: 5.6rem;
  aspect-ratio: 4 / 5;
  border: 2px solid var(--brass, #a8813d);
  border-radius: 2px;
  overflow: hidden;
  background: #22262b;
}
.diplomatietafel .dt-bildnis img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 0; }
.diplomatietafel .dt-bildnis.leer { display: flex; align-items: center; justify-content: center; color: var(--text-dim, #928b7d); font-size: 0.72rem; }

/* --- Die zwei Listen: gleich groß, gleiche Zeilen, gleiche Schilde ---
   Sie nehmen, was Kopf und Siegelträger übrig lassen — gleich viele Häuser
   oder nicht, die Tafel bleibt so hoch, wie sie ist. */
.diplomatietafel .dt-listen {
  flex: 1 1 auto;
  min-height: 7rem;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}
.diplomatietafel .dt-liste {
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  padding: 0.4rem 0.5rem;
  background: #101215;
  border: 1px solid #2c3138;
  border-radius: 2px;
}
.diplomatietafel .dt-liste h4 { flex: none; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.diplomatietafel .dt-zeilen { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 1px; overflow-y: auto; }
.diplomatietafel .dt-zeile {
  display: flex;
  flex: none;
  align-items: center;
  gap: 0.45rem;
  width: 100%;
  min-height: 2.3rem;
  padding: 0 0.4rem;
  text-align: left;
  background: none;
  border: 1px solid transparent;
}
.diplomatietafel .dt-zeile:hover:not(.gewaehlt) { border-color: var(--brass-dark, #6d5426); background: #1a1d21; }
.diplomatietafel .dt-zeile.gewaehlt,
.diplomatietafel .dt-zeile.gewaehlt:hover { border-color: var(--brass-light, #cca75e); background: #22262b; }
.diplomatietafel .dt-zname { display: flex; flex-direction: column; flex: 1; min-width: 0; line-height: 1.15; }
.diplomatietafel .dt-zname b, .diplomatietafel .dt-zname span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.diplomatietafel .dt-zname b { font-weight: normal; font-size: 0.86rem; }
.diplomatietafel .dt-zrechts { display: flex; align-items: center; gap: 0.4rem; flex: none; }
.diplomatietafel .dt-zrechts .dt-bez { width: 4.2rem; }
.diplomatietafel .dt-zahl { width: 2.3rem; text-align: right; font-size: 0.8rem; font-variant-numeric: tabular-nums; }
/* Wie weit ein Haus weg ist — rechts in jeder Zeile der Adelshäuser. */
.diplomatietafel .dt-weite { min-width: 3.9rem; text-align: right; font-size: 0.82rem; font-variant-numeric: tabular-nums; color: var(--parchment, #d7c7a3); }
.diplomatietafel .dt-punkt { width: 0.42rem; height: 0.42rem; transform: rotate(45deg); }
.diplomatietafel .dt-punkt.gut { background: var(--moss, #7a9166); }
.diplomatietafel .dt-punkt.bos { background: #c0442f; }
/* Ein Haus, das auf Eure Antwort wartet (Bündnis- oder Friedensangebot). */
.diplomatietafel .dt-punkt.angebot { background: #f3d27a; }
/* Eine Stadt unter dem Schutz eines fremden Hauses. */
.diplomatietafel .dt-punkt.fremd { background: var(--brass, #a8813d); }

/* --- Die Städte (03.10.2026): unter den Adelshäusern in derselben Liste, mit
   ihrem Wappen (stadtwappen.ts). Im Kopf statt der Werte: wer sie schützt und
   ihre Blasonierung, höchstens zwei Zeilen — der Kopf bleibt gleich hoch. */
.diplomatietafel .dt-zwischen {
  flex: none;
  margin: 0.35rem 0 0.1rem;
  padding-top: 0.25rem;
  border-top: 1px solid #2c3138;
  font-family: var(--font-display, serif);
  font-size: 0.95rem;
  color: var(--brass-light, #cca75e);
}
.diplomatietafel .dt-stadtschutz { font-size: 0.84rem; color: var(--parchment, #d7c7a3); margin-bottom: 0.3rem; }
/* DIE GUNST EINES GÖNNERS ODER STADTRATS (03.10.2026, docs/vorhaben/questgeber.md) —
   derselbe Balken wie eine Beziehung, davor das Wort, darunter, ob er schreibt. */
.diplomatietafel .dt-gunst { display: flex; align-items: center; gap: 0.45rem; margin: 0.2rem 0 0.1rem; font-size: 0.84rem; }
.diplomatietafel .dt-gunstwort { color: var(--text-dim, #8f8a80); }
.diplomatietafel .dt-gunstsatz { font-size: 0.8rem; margin-bottom: 0.3rem; }
/* Eine Person, die ein Auftrag gerade vorstellen lässt, ist noch fremd: kursiv. */
.diplomatietafel .dt-zeile.unbekannt .dt-zname b { font-style: italic; font-weight: normal; }
.diplomatietafel .dt-stadtschutz b { font-weight: normal; color: var(--brass-light, #cca75e); }
.diplomatietafel .dt-blason {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: 0.78rem;
  font-style: italic;
  line-height: 1.25;
  color: var(--text-dim, #928b7d);
}
.diplomatietafel .dt-blason-lang { margin: 0 0 0.5rem; font-size: 0.82rem; font-style: italic; line-height: 1.3; color: var(--parchment, #d7c7a3); }

/* --- Die Siegelträger: Karten, verkleinert, und ihre Handlungen ---
   FESTE Höhe: vier Karten in einer Reihe und eine Liste von fünf Handlungen.
   Mehr Karten oder Zeilen rollen in ihrem Kasten. */
.diplomatietafel .dt-siegel {
  flex: none;
  display: flex;
  flex-direction: column;
  padding-top: 0.45rem;
  border-top: 1px solid var(--brass-dark, #6d5426);
}
.diplomatietafel .dt-siegelkopf { display: flex; align-items: baseline; gap: 1rem; min-width: 0; }
.diplomatietafel .dt-siegelkopf h4 { flex: none; }
.diplomatietafel .dt-siegelkopf h4 .dt-leise { margin-left: 0.4rem; font-family: var(--font-body, Georgia, serif); font-size: 0.74rem; }
/* Die Meldung („… bricht auf") rechts in der Kopfzeile — eine Zeile. */
.diplomatietafel .dt-meldung {
  flex: 1;
  min-width: 0;
  text-align: right;
  font-size: 0.82rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Karten links, Handlungen rechts — im selben Blick (siehe bauen() in diplomatie.js). */
.diplomatietafel .dt-siegelreihe {
  display: grid;
  grid-template-columns: 24rem minmax(0, 1fr);
  gap: 0.7rem;
  height: 12rem;
}
@media (max-width: 1150px) {
  .diplomatietafel .dt-siegelreihe { grid-template-columns: 12.2rem minmax(0, 1fr); }
}
.diplomatietafel .dt-karten {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 0.45rem;
  min-height: 0;
  overflow-y: auto;
}
.diplomatietafel .dt-karte {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.2rem;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: var(--cursor-gold, pointer);
}
.diplomatietafel .dt-karte:hover { border-color: var(--brass-dark, #6d5426); }
.diplomatietafel .dt-karte.gewaehlt { border-color: #f3d27a; background: #1d2024; }
.diplomatietafel .dt-karte.fort .dt-kartenbild { opacity: 0.6; }
/* Seit dem 20.10.2026 keine Karten mehr (sie liegen im Siegeldeck), nur Name und Art in einer Zeile. */
.diplomatietafel .dt-karten { flex-direction: column; flex-wrap: nowrap; gap: 0.2rem; }
.diplomatietafel .dt-karte { flex-direction: row; justify-content: space-between; align-items: center; gap: 0.6rem; padding: 0.25rem 0.45rem; }
.diplomatietafel .dt-kartenbild { pointer-events: none; min-width: 0; flex: 1; }
.diplomatietafel .dt-kartenbild .sgt-fuss { display: none; }
.diplomatietafel .dt-kartenersatz {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: 5.2rem;
  height: 7.4rem;
  padding: 0.3rem;
  background: #22262b;
  border: 1px solid var(--brass-dark, #6d5426);
}
.diplomatietafel .dt-kartenlage {
  height: 1.8rem;
  width: 5.8rem;
  overflow: hidden;
  font-size: 0.72rem;
  line-height: 0.9rem;
  color: var(--text-dim, #928b7d);
  text-align: center;
}
/* Zwei Zeilen, jede für sich gekürzt — wohin und wie lange noch. */
.diplomatietafel .dt-kartenlage > span { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.diplomatietafel .dt-kartenlage.bereit { color: #a6e06a; }
.diplomatietafel .dt-kartenlage.unterwegs { color: #e08a4b; }
.diplomatietafel .dt-handlungen {
  min-height: 0;
  overflow-y: auto;
  padding: 0.4rem 0.6rem;
  background: #101215;
  border: 1px solid #2c3138;
  border-radius: 2px;
  font-size: 0.86rem;
  transition: opacity 0.15s ease;
}
/* Solange die Liste für eine neue Wahl noch unterwegs ist, bleibt die alte
   blass stehen — statt für einen Augenblick einer einzigen Zeile Platz zu
   machen. */
.diplomatietafel .dt-handlungen.laedt { opacity: 0.45; }
/* Der Haus-Stil begrenzt jedes p auf 68ch (ui.css oben) — hier bricht es sonst mitten im Kasten um. */
.diplomatietafel .dt-handlungen p { margin: 0.15rem 0; max-width: none; }
.diplomatietafel .dt-keiner { color: #e0b060; }
.diplomatietafel .dt-keiner b { color: #f3d27a; font-weight: normal; }
.diplomatietafel .dt-handlung {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 3rem 3.2rem 4rem 5.8rem;
  align-items: center;
  gap: 0.45rem;
  padding: 0.12rem 0;
  line-height: 1.25;
  border-top: 1px solid #22262b;
}
.diplomatietafel .dt-handlung > span { white-space: nowrap; }
.diplomatietafel .dt-handlung button { padding: 0.08rem 0.45rem; line-height: 1.2; }
.diplomatietafel .dt-handlung.dt-hkopf { border-top: 0; padding-top: 0; color: var(--text-dim, #928b7d); font-size: 0.74rem; }
.diplomatietafel .dt-hname { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Verbessern grün, verschlechtern rot — wie der Balken (20.10.2026). */
.diplomatietafel .dt-hname.dt-plus { color: #b9d29c; }
.diplomatietafel .dt-hname.dt-minus { color: #e3a08f; }
.diplomatietafel .dt-handlung.gesperrt { color: #6b665d; }
.diplomatietafel .dt-handlung .dt-grund { font-size: 0.76rem; font-style: italic; line-height: 1.15; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.diplomatietafel .dt-chance { font-variant-numeric: tabular-nums; }
.diplomatietafel .dt-chance.gut { color: #a6e06a; }
.diplomatietafel .dt-chance.mittel { color: #e0b44b; }
.diplomatietafel .dt-chance.schlecht { color: #f0745a; }
.diplomatietafel .dt-handlung.gesperrt .dt-chance { color: inherit; }
/* Die Forderung eines Friedensangebots — unter seiner Zeile, in EINER Zeile. */
.diplomatietafel .dt-forderung {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0 0 0.2rem 0.6rem;
  font-size: 0.8rem;
  white-space: nowrap;
  overflow: hidden;
}
.diplomatietafel .dt-forderung .ff-silber { width: 4.4rem; }
.diplomatietafel .dt-forderung .ff-menge { width: 3.4rem; }
.diplomatietafel .dt-forderung select { max-width: 6.4rem; }

/* --- Der Markt in Brendanburg 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; }

/* 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: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(0, 0, 0, 0.22);
  --schein: var(--brass-dark);
  font-size: 0.86rem;
}
/* Auf dem Rückweg grünlich — er bringt etwas mit. */
.ht-fahrt.heim { --schein: #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) + var(--kampftafel-hoehe, 0rem));
  bottom: auto;
  right: auto;
  left: 0.7rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.35rem 0.5rem;
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(18, 20, 23, 0.9);
  border: 1px solid var(--iron);
  --schein: 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; }

/* WAS DIE SIEGELTRÄGER GERADE TUN (19.10.2026, siegelzettel.ts) — dieselben
   Karten wie die Bauvorhaben (#queue), das Bildchen ist der Held aus den
   Knöpfen des Kriegstisches, etwas größer, weil eine Figur sonst nur ein
   Strich ist. Gesandte, die die Beziehung heben oder senken, tragen den Ton
   ihrer Wirkung am Rand. */
#siegelzettel { display: flex; flex-direction: column; gap: 0.3rem; }
#siegelzettel[hidden] { display: none; }
/* Das Bildchen steht links über alle Zeilen, der Text rechts davon bricht nie
   darunter um. */
.queueitem.siegelkarte {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) auto;
  column-gap: 0.4rem;
  align-items: center;
}
.siegelkarte .siegelbild {
  grid-row: 1 / span 3;
  width: 34px;
  height: 34px;
  object-fit: cover;
  /* Die Bildnisse sind Kopf und Schultern im Hochformat — der Kopf sitzt im oberen Drittel. */
  object-position: 50% 22%;
  border: 1px solid var(--brass-dark);
  border-radius: 50%;
  align-self: center;
}
.siegelkarte .sz-kopf { grid-column: 2; display: flex; justify-content: space-between; gap: 0.4rem; }
.siegelkarte .sz-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.siegelkarte .sz-zeit { color: var(--text-dim); white-space: nowrap; }
.siegelkarte .sz-tun { grid-column: 2; color: var(--text-dim); font-size: 0.68rem; }
.siegelkarte .bar { grid-column: 2; margin-top: 0.18rem; }
.siegelkarte.plus { border-left: 2px solid #5f7a4a; }
/* DIE KNÖPFE DES BESUCHS unten rechts (20.10.2026, main.ts `besuchsleisteZeigen`):
   dunkelgrau mit Messingrand wie die Tafeln und das Kopfband. */
.besuchsknoepfe {
  position: fixed;
  right: max(16px, env(safe-area-inset-right, 0px));
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 20;
  display: flex;
  gap: 8px;
}
.besuchsknopf {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 16px;
  background: linear-gradient(180deg, rgba(34, 38, 43, 0.95), rgba(16, 18, 21, 0.95));
  border: 1px solid var(--brass-dark);
  border-radius: 0;
  color: #ddd2bb;
  font-family: var(--font-display);
  font-size: 0.95rem;
  text-decoration: none;
  white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
  cursor: var(--cursor-gold, pointer);
}
.besuchsknopf:hover { border-color: var(--brass-light); color: var(--brass-light); }
/* Beim Besuch zeigt die Bildnisecke den Gastgeber: ohne den eigenen Stufenbalken. */
#topbar .bildnisecke.gast .kopf-stufenbalken { display: none; }
/* DAS ZEICHEN DER TÄTIGKEIT rechts über alle Zeilen (20.10.2026, siegelzettel.ts). */
.siegelkarte .sz-zeichen {
  grid-column: 3;
  grid-row: 1 / span 3;
  position: relative;
  width: 28px;
  height: 28px;
  margin-left: 0.2rem;
}
.siegelkarte .sz-zeichen > img {
  width: 28px;
  height: 28px;
  object-fit: contain;
  /* Die Zeichen der Wirkungsleiste sind dunkel — auf dem dunklen Zettel heller. */
  filter: brightness(1.7) contrast(1.1);
}
/* Das Vorzeichen am Handschlag: verbessern grün, verschlechtern rot. */
.siegelkarte .sz-vz {
  position: absolute;
  right: -3px;
  bottom: -4px;
  font-size: 0.95rem;
  line-height: 1;
  font-weight: 700;
  text-shadow: 0 0 2px #000, 0 0 2px #000, 0 1px 1px #000;
}
.siegelkarte .sz-vz.plus { color: #7fd98f; }
.siegelkarte .sz-vz.minus { color: #e8705f; }
/* Auf dem Kriegstisch schwenkt ein Klick zum Reiter (karte3d.ts). */
#siegelzettel .siegelkarte[data-zeigen] { pointer-events: auto; cursor: var(--cursor-gold, pointer); }
#siegelzettel .siegelkarte[data-zeigen]:hover { border-color: var(--brass-light); }
.siegelkarte.minus { border-left: 2px solid #8a4a3a; }

/* --- 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; }
/* ZWEI ZEILEN JE BETRIEBSART (17.09.2026): das Bildchen links über die ganze
   Höhe, oben der Name, darunter die Rechnung. Der Wahlknopf ist weg — die
   ganze Kachel IST die Wahl, und was gewählt ist, sagt der Messingrahmen.

   Warum zwei Zeilen und nicht eine: Die Schmiede trägt drei Posten (+1,7
   Werkzeug, −3,3 Eisen, −2 Holzkohle). Neben dem Namen passen die in 19rem
   nicht, und einzeilig brächen genau die Regler um, bei denen es auf die
   Rechnung ankommt. Untereinander ist jede Zeile gleich hoch — bei zehn
   Reglern in vier Häusern ist das der ruhigere Satz.

   `minmax(0, 1fr)` statt `1fr`: Sonst schrumpft die zweite Spalte nicht unter
   ihren Inhalt, und die Rechnung läuft über den Rand der Tafel hinaus. */
.gp-art {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas:
    "bild kopf"
    "bild rechnung"
    "bild jahr";
  align-items: center;
  gap: 0.05rem 0.55rem;
  padding: 0.3rem 0.5rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--iron);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
/* Der Wahlknopf bleibt IM Baum und nur für das Auge verschwunden: An ihm
   hängt der Wechsel (data-betriebsart), und so bleibt die Tafel mit der
   Tastatur bedienbar. Wo der Fokus steht, zeigt dann der Rahmen. */
.gp-art input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  margin: 0;
  pointer-events: none;
}
.gp-art:focus-within { border-color: var(--brass-light); }
.gp-art-bild { grid-area: bild; width: 34px; height: 34px; object-fit: contain; }
.gp-art-kopf { grid-area: kopf; color: var(--text); display: inline-flex; align-items: center; gap: 0.35rem; }
.gp-art.aktiv .gp-art-kopf { color: var(--brass-light); }
.gp-art-rechnung {
  grid-area: rechnung;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  white-space: nowrap;
  font-size: 0.84rem;
}
.gp-art-ware { display: inline-flex; align-items: center; gap: 0.12rem; font-variant-numeric: tabular-nums; }
.gp-art-ware.plus { color: var(--brass-light); }
.gp-art-ware.minus { color: var(--text-dim); }
.gp-art-ware .resicon { width: 18px; height: 18px; object-fit: contain; }
/* Die Einheit steht EINMAL über der Liste statt in jeder Zeile. */
.gp-art-einheit {
  float: right;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  font-size: 0.78rem;
  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); }
/* DIE VERTEILTE SCHMIEDE (17.10.2026, gebaeudePanel.ts `verteilungBlock`):
   oben die fünf Plätze, jeder ein Knopf mit dem Bild seiner Tätigkeit; ein
   Platz ohne Mann steht blass. Die Zeilen darunter sind nur Rechnung, kein
   Knopf — sie leuchten nicht unter dem Zeiger. */
/* Die fünf Plätze teilen sich die ganze Breite der Tafel gleichmäßig. */
.gp-plaetze { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.35rem; margin: 0.15rem 0 0.4rem; }
.gp-platz {
  width: 100%;
  height: 44px;
  padding: 4px;
  display: grid;
  place-items: center;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  cursor: var(--cursor-gold);
}
.gp-platz img { width: 34px; height: 34px; object-fit: contain; }
.gp-platz:hover,
.gp-platz:focus-visible { border-color: var(--brass-light); background: rgba(109, 84, 38, 0.32); filter: brightness(1.2); }
.gp-platz.leer img { opacity: 0.35; }
.gp-art.gp-art-teil { cursor: var(--cursor-kupfer, default); }
.gp-art.gp-art-teil:hover { border-color: var(--iron); }
.gp-art.gp-art-teil.aktiv:hover { border-color: var(--brass); }
.gp-art-teil .gp-art-kopf small { color: var(--text-dim); font-variant-numeric: tabular-nums; }
/* Der Preis des Ausbaus steht im Knopf, je Ware Zahl und Bild (17.10.2026). */
.gp-ausbau-preis { display: inline-flex; align-items: center; gap: 0.15rem; margin-left: 0.45rem; font-variant-numeric: tabular-nums; }
.gp-ausbau-preis .resicon { width: 18px; height: 18px; object-fit: contain; }
/* Der Jahreslauf je Art — dieselben Säulen wie auf der Vorratstafel
   (.jl-saeulen), hier etwas größer, weil die Tafel breiter ist. */
/* Der Jahreslauf steht in der DRITTEN Zeile, in derselben Spalte wie Name und
   Rechnung. Neben die Rechnung gelegt kollidierte er bei der Jagd (drei
   Posten und vier Säulen passen nicht in 19rem), und ein Zusammenstoß sieht
   nicht nach „eng", sondern nach „kaputt" aus. */
.gp-art-jahr {
  grid-area: jahr;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.76rem;
  color: var(--text-dim);
}
.gp-art-jahr .jl-saeulen { height: 10px; }
.gp-art-jahr .jl-saeulen i { width: 6px; }
.gp-art-jahr .jl-saeulen i.leer { height: 2px; }

/* --- 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: var(--cursor-gold);
}

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 ---------------------------------------------------------

   Hier stand bis zum 13.09.2026 „dieselbe Bauform wie die Handelstafel: ein
   abgedunkelter Vorhang über der ganzen Fläche, die Tafel mittig darin".

   DER VORHANG WAR LÄNGST EIN RAHMEN. Seit dem 05.09.2026 ist die Rangliste
   ein schiebbares ECKENFENSTER (fenster.js, REGISTER) — und fenster.js setzt
   die HÜLLE auf `left`/`top` und nimmt ihr `right`/`bottom`. Aus dem Vorhang
   über dem ganzen Schirm wurde damit ein Kasten von der Größe der Tafel plus
   Polsterung: gemessen 38 × 19 Bildpunkte dunkles Halbschwarz rund um die
   Tafel. Gemeldet vom Bro: „bitte auch bei der rangliste diesen dunklen
   rahmen entfernen."

   Die Hülle ist darum jetzt DURCHSICHTIG und ohne Polster. Sie behält
   `inset: 0` und die Mitte für den Augenblick, bevor fenster.js sie setzt
   (und für eine Seite ohne fenster.js) — und lässt dabei jeden Klick
   hindurch (`pointer-events: none`); nur die Tafel selbst fängt ihn. */
#ranglistetafel {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  background: none;
  padding: 0;
  pointer-events: none;
}
#ranglistetafel .rl-tafel { pointer-events: auto; }
#ranglistetafel[hidden] { display: none; }
.rl-tafel {
  /* BREITER, ZIEHBAR, UND DIE BREITE WIRD GEMERKT (13.09.2026, Ansage des
     Bro: „die rangliste breiter machen, sodass man alle qualifikationen
     sieht" — übernommen aus dem Nachbarspiel im Ordner `Bergfried`).

     560 schnitt die Aufschlüsselung mit „…" ab, und abgeschnitten war immer
     das Ende — Silber und Dörfer. Bei 700 bleiben für die Mittelspalte rund
     390 Bildpunkte, und die längste Aufschlüsselung braucht gemessen 354.
     Wer mehr Luft will, zieht am Griff; ranglisteTafel.ts merkt sich die
     Breite (`rangliste.breite`). */
  width: min(var(--rl-breite, 700px), 94vw);
  min-width: min(430px, 94vw);
  max-width: 94vw;
  resize: horizontal;
  max-height: 86vh;
  overflow: 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;
  /* Unten etwas mehr Luft: Der Ziehgriff des Browsers sitzt in der Ecke und
     läge sonst auf der Fusszeile. */
  padding: 1rem 1.2rem 1.6rem;
}
.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-kopf.tafelkopf { margin: -1rem -1.2rem 0.9rem; }
.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 {
  /* Halbfiguren (seit 25.09.2026): auf Kopf und Schultern gezoomt, oben
     angesetzt — bei 51 Bildpunkten Breite wäre das Gesicht sonst ein Fleck. */
  width: 190%;
  height: auto;
  margin-left: -45%;
  /* Die Bildnisse sind gemalte Pixelbilder — nicht weichzeichnen. */
  image-rendering: auto;
  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: auto;
  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: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(168, 129, 61, 0.12);
  --schein: 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; }
/* Titel und Name stehen NEBENEINANDER in einer Zeile: „Markgraf Andreas" ist
   EIN Name, kein Paar aus zwei Angaben. */
.rl-zeile2 {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
  min-width: 0;
}
.rl-spieler { font-size: 0.85rem; color: var(--text-dim); }

/* DER TITEL VOR DEM NAMEN (13.09.2026, Ansage des Bro: „den titel auch
   hinzufügen" — übernommen aus dem Nachbarspiel).

   Schlichter Text: kein Rahmen, kein Grund, keine Versalien — drüben stand er
   einen Anlauf lang als Schild dahinter und las sich wie eine Etikettierung.
   Gefärbt nach STUFE, nicht nach Namen: Welcher Titel wie weit oben steht,
   entscheidet config/adelstitel.json. Der Freiherr bleibt bewusst schlicht —
   wäre schon die unterste Stufe messingfarben, wäre keine es. */
.rl-titel {
  flex: 0 0 auto;
  font-size: 0.85rem;
  color: var(--text-dim);
  opacity: 0.8;
  white-space: nowrap;
}
/* NEUN STUFEN seit dem 13.09.2026: Burggraf und Graf blass, Landgraf bis
   Pfalzgraf in Messing, Fürst, Herzog und Kurfürst hell und kräftig. */
.rl-titel[data-stufe="1"],
.rl-titel[data-stufe="2"],
.rl-titel[data-stufe="3"] { color: #b7a88f; opacity: 1; }
.rl-titel[data-stufe="4"],
.rl-titel[data-stufe="5"],
.rl-titel[data-stufe="6"] { color: var(--brass-light); opacity: 1; }
.rl-titel[data-stufe="7"],
.rl-titel[data-stufe="8"],
.rl-titel[data-stufe="9"] { color: #f0dca8; opacity: 1; font-weight: 600; }

/* Die Aufschlüsselung: klein. Sie beantwortet die Rückfrage "warum steht der
   vor mir", ohne die Liste zu einer Tabelle zu machen.

   KEIN „…" MEHR (13.09.2026). In der breiten Tafel passt die Zeile; wo sie es
   doch nicht tut (schmaler Schirm), bricht sie lieber um, als den letzten
   Posten zu verschlucken — abgeschnitten war ausgerechnet immer das Ende. */
.rl-werte {
  font-size: 0.78rem;
  color: var(--text-dim);
  opacity: 0.75;
  overflow-wrap: anywhere;
}
.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 img {
  width: 28px;
  height: 28px;
}
.rl-burgzeichen:hover img { filter: brightness(1.3); }
.rl-burgzeichen:hover,
.rl-burgzeichen:focus-visible {
  color: var(--brass-light);
  border-color: var(--brass);
  background: rgba(168, 129, 61, 0.18);
}
/* Kein eigener Späher an dieser Burg: das Burgzeichen grau, kein Klick. */
.rl-burgzeichen.aus,
.rl-burgzeichen.aus:hover { cursor: default; opacity: 0.45; color: var(--text-dim); border-color: var(--iron); background: rgba(0, 0, 0, 0.3); }
.rl-burgzeichen.aus img { filter: grayscale(1) brightness(0.7); }
.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: auto;
}
/* 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 ERSTE ZEILE EINES EINTRAGS DER BAU-UEBERSICHT (19.10.2026, hud3d.ts
   `queuezeile`, Ansage des Bro: „pfeile als buttons … immer rechts
   ausrichten, text von gebäude immer links … alle buttons standard größe"):
   der Text links, die Knöpfe rechts, alle gleich groß, eckig mit grauem
   Rahmen wie das Kreuz am Wartschild. Der gesperrte Pfeil hält den Platz. */
.queueitem .queuezeile {
  display: flex;
  /* Oben, nicht mittig: Bricht ein Text um, bleiben die Knöpfe an ihrer
     Stelle (Ansage: „die buttons müssen immer auf selbe position sein“). */
  align-items: flex-start;
  gap: 0.4rem;
  min-height: 1.3rem;
}
.queueitem .queuetext {
  flex: 1;
  min-width: 0;
  text-align: left;
}
/* Die Restzeit steht rechtsbündig neben dem Namen (19.10.2026). */
.queueitem .queuezeit {
  flex: none;
  white-space: nowrap;
  text-align: right;
}
.queueitem .queueknoepfe {
  display: inline-flex;
  gap: 4px;
  flex: none;
  margin-left: auto;
}
.queueitem.wartet .queuezeile { flex: 1; }
/* DIE BREITE DES STAPELS: Wuchse ein Eintrag mit seinem Text („ruht —
   niemand frei“ gegen „noch 3 Std“), wanderten die Knöpfe bei jedem Takt
   unter dem Zeiger weg. Was nicht passt, bricht im Text um. */
#queue > .queueitem, #queue > .wartekopf { width: 100%; box-sizing: border-box; }
/* Rechts ein ganzer Bildpunkt Polster statt 0,5rem (9,5 px): Sonst stünden
   die Knöpfe auf halben Punkten, und Rand und Kreuz verschwämmen. */
#queue > .queueitem { padding-right: 10px; }
.queueitem .queueknopf { margin: 0; }

/* DER KLEINE KNOPF — EINE REGEL FÜR ALLE (19.10.2026, Ansage des Bro: „das
   grau der knöpfe ganz dunkel machen wir brauchen regel für solche knöpfe
   damit alles einheitlich ist“). Kreuz, Pfeile und jedes andere Zeichen in
   einer Zeile: quadratisch, eckig, alle gleich groß, ganz dunkelgrauer Rand,
   kein Messing; unter dem Zeiger werden Rand und Zeichen hell. Steht er in
   einer Zeile, steht er RECHTS, der Text links (CLAUDE.md). */
.knopf-klein {
  /* GANZE BILDPUNKTE (19.10.2026, „das kreuz leicht links versetzt"): Bei
     1,3rem war der Knopf 24,69 px breit und das Zeichen lag auf Bruchteilen —
     der Browser rundete es ungleich, das Kreuz sah verrutscht aus. Knopf und
     Zeichen haben darum gerade Maße in px, die Mitte fällt auf ganze Punkte. */
  width: 24px;
  height: 24px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid #3a3a3a;
  border-radius: 0;
  box-shadow: none;
  color: #b8b0a0;
  font: inherit;
  font-size: 0.62rem;
  line-height: 1;
  opacity: 1;
  cursor: var(--cursor-gold);
}
.knopf-klein:hover {
  background: rgba(0, 0, 0, 0.25);
  border-color: #8a8a8a;
  color: #ffffff;
  opacity: 1;
}
/* Gesperrt: blass und an seinem Platz. Ein Platzhalter ohne Knopf: unsichtbar. */
.knopf-klein.aus, .knopf-klein.aus:hover { opacity: 0.3; color: #b8b0a0; border-color: #3a3a3a; pointer-events: none; }
.knopf-klein.platz { visibility: hidden; pointer-events: none; }
/* Ein gezeichnetes Zeichen im kleinen Knopf (hud3d.ts `vorrangPfeile`):
   genau in der Mitte, in der Farbe des Zeichens. */
.knopf-klein .knopf-dreieck { width: 8px; height: 8px; display: block; fill: currentColor; }
.knopf-klein .knopf-kreuz { width: 10px; height: 10px; display: block; fill: none; stroke: currentColor; stroke-width: 1.4; stroke-linecap: square; }

/* 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. Und seit dem 13.09.2026 beim Siegel des
   Markgrafen, wenn eine Tagesaufgabe angeboten ist (questfenster.js): dieselbe
   Sprache für „hier wartet etwas auf dich", keine zweite. */
.kopfknopf.hat-post,
.kopfknopf.hat-auftrag,
.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,
.kopfknopf.hat-auftrag .kopfzeichen {
  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,
  .kopfknopf.hat-auftrag,
  .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,
  .kopfknopf.hat-auftrag .kopfzeichen {
    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); }

/* VERGEBEN und GESPERRT in der Standestafel — dieselbe Auskunft wie auf der
   Charakterseite (spielerpanel.js, wappenwahlMarken): Die Kachel bleibt
   stehen, wird grau und nimmt keinen Klick. */
.sp-bildniskachel.vergeben,
.sp-wappenkachel.vergeben,
.sp-tinktur.vergeben,
.sp-tinktur.gesperrt {
  cursor: var(--cursor-kupfer);
}
.sp-bildniskachel.vergeben:hover { border-color: var(--iron); }
.sp-bildniskachel.vergeben img {
  filter: grayscale(1) brightness(0.55);
  opacity: 0.45;
}
.sp-wappenkachel.vergeben img,
.sp-wappenkachel.vergeben:hover img { filter: brightness(0) invert(1) opacity(0.18); }
.sp-tinktur.vergeben,
.sp-tinktur.gesperrt {
  opacity: 0.28;
  border-style: dashed;
  border-color: var(--iron);
}
.sp-tinktur.vergeben:hover,
.sp-tinktur.gesperrt:hover { transform: none; }
.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-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: var(--cursor-kupfer);
}
.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: row;
  align-items: center;
  gap: 0.45rem;
  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; }
/* Das Bildnis des Handelsmeisters (berufsportraits) am Knopf. */
.ht-meister-bild {
  width: 40px;
  height: 40px;
  object-fit: cover;
  object-position: 50% 0;
  border: 1px solid var(--brass-dark);
  border-radius: 2px;
  flex: none;
}
.ht-meister-text { display: flex; flex-direction: column; align-items: flex-start; }
/* DER HAKEN FUERS PFERD (11.10.2026) — am Meister, mit dem Pferdekopf des
   Kriegstisches. Ohne freies Pferd blass. */
.ht-meister-karte { display: flex; align-items: stretch; gap: 0; }
.ht-meister-karte .ht-meister { border-top-right-radius: 0; border-bottom-right-radius: 0; }
.ht-pferd {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1rem;
  padding: 0.15rem 0.35rem;
  border: 1px solid var(--brass-dark);
  border-left: none;
  border-radius: 0 2px 2px 0;
  background: rgba(0, 0, 0, 0.35);
  cursor: var(--cursor-gold);
}
.ht-pferd:hover { border-color: var(--brass); }
.ht-pferd img { width: 22px; height: 22px; }
.ht-pferd input { margin: 0; accent-color: var(--brass); cursor: inherit; }
.ht-pferd:has(input:not(:checked)) img { opacity: 0.4; }
.ht-pferd.leer { opacity: 0.45; cursor: var(--cursor-kupfer); }
.ht-pferde-frei { margin-left: 0.5rem; font-weight: 400; color: var(--text-dim); white-space: nowrap; }
.ht-pferde-frei img { width: 16px; height: 16px; vertical-align: -3px; margin-right: 0.2rem; }
.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: var(--cursor-kupfer); }

/* ===========================================================================
   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-titel { display: flex; align-items: center; gap: 0.5rem; }
.tt-kopf.tafelkopf { font-weight: 400; letter-spacing: normal; }
.tt-titel .info-frage { margin: 0; }
.tt-fenster > .info-feld { margin: 0.5rem 0.7rem 0; }
.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 KLANGTAFEL (Taste 8, klangTafel.ts, 15.10.2026) — neben dem Uhrwerk. */
.kt-fenster {
  left: 21rem;
  width: 34rem;
  max-height: calc(100vh - 8rem);
  overflow-y: auto;
}
.kt-kopf {
  margin: 0.5rem 0 0.25rem;
  color: var(--brass-light);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.kt-kopf:first-child { margin-top: 0; }
.kt-zu { margin: 0 0 0.4rem; color: #d08a6a; }
.kt-tabelle { width: 100%; border-collapse: collapse; font-size: 0.78rem; }
.kt-tabelle td { padding: 0.15rem 0.3rem; vertical-align: middle; border-bottom: 1px solid rgba(168, 129, 61, 0.15); }
.kt-vor { width: 3rem; color: var(--text-dim); opacity: 0.75; white-space: nowrap; font-variant-numeric: tabular-nums; }
.kt-ebene { width: 2.6rem; color: var(--brass-light); }
.kt-name span { display: block; color: var(--text); word-break: break-all; }
.kt-name i { color: var(--text-dim); font-style: normal; opacity: 0.8; }
.kt-name small { display: block; color: var(--text-dim); opacity: 0.7; font-size: 0.68rem; word-break: break-all; }
.kt-pegel { position: relative; width: 8.5rem; white-space: nowrap; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.kt-pegel b { position: absolute; left: 0.3rem; bottom: 0.1rem; height: 2px; background: var(--brass-dark); }
.kt-spielt td { background: rgba(201, 164, 92, 0.12); }
.kt-leer { color: var(--text-dim); }

/* ===========================================================================
   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; }

/* --- Die Heerschau -------------------------------------------------------
   Die Musterung des Aufgebots (server/public/heerschau.js). Fensterchromik
   kommt wie bei Chronik und Produktion aus .chatfenster / .ct-*; hier steht
   nur, was diesem Fenster eigen ist.

   Die Farben sind die des Spiels: --moss fuer den Vorteil, --fire-light fuer
   den Nachteil — dieselbe Sprache wie im Produktionsfenster, wo Gruen
   hereinkommt und Rot hinausgeht. Der Ring erbt sie, weil er dieselbe Frage
   stellt: Was traegt, und was kostet. */
/* --- Die Aufgaben des Markgrafen (08.09.2026) --------------------------------
   Sie ersetzen Cunrats Lehrgang, dessen Regeln bis dahin an dieser Stelle in
   der Datei standen (`.schreiber`, `.sb-*`).

   Fensterrahmen ist `.chatfenster` — dieselbe Machart wie Chat, Chronik,
   Produktion und Heerschau. Hier stehen nur die Regeln des INHALTS. */
.qf-fenster {
  min-width: 340px;
}
.qf-koerper {
  display: flex;
  flex-direction: column;
  overflow: auto;
  padding: 0.6rem 0.7rem;
  gap: 0.55rem;
}
.qf-fehler {
  margin: 0;
  font-size: 0.85rem;
  color: #d08a7a;
}
.qf-fehler[hidden] { display: none; }
.qf-warten { margin: 0; font-size: 0.85rem; }

/* DER AUFTRAGGEBER, ganz oben. Bildnis links, Name und Amt rechts — dieselbe
   Anordnung, die Cunrats Kopf hatte: Man sieht zuerst, WER etwas will. */
.qf-geber {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--iron);
}
.qf-geber strong {
  display: block;
  color: var(--brass-light);
  font-size: 0.95rem;
  letter-spacing: 0.02em;
}
.qf-geber small {
  display: block;
  color: var(--text-dim);
  font-size: 0.76rem;
}
/* Rund und randlos beschnitten: Das Bild ist ein gemaltes Breitbild, und ein
   Kreis daraus liest sich als Bildnis statt als Ausschnitt. */
.qf-bildnis {
  flex: none;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 30% 35%;
  border: 1px solid var(--brass-dark);
}

.qf-abschnitt {
  margin: 0.4rem 0 0;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.qf-fertig {
  margin: 0;
  font-size: 0.85rem;
  color: var(--moss, #7fa06a);
}
.qf-leer { margin: 0; font-size: 0.82rem; line-height: 1.45; }
/* Die laufende Uhr bis zum nächsten Auftrag (21.09.2026) — gleich breite
   Ziffern, sonst zittert die Zeile jede Sekunde. */
.qf-uhr { font-variant-numeric: tabular-nums; }
.qf-naechste {
  margin: 0.5rem 0 0;
  padding-top: 0.45rem;
  border-top: 1px solid var(--iron);
  font-size: 0.82rem;
  color: var(--text-dim);
}
.qf-naechste .qf-uhr { color: var(--brass-light); font-size: 0.95rem; margin-left: 0.2rem; }

.qf-aufgabe {
  border: 1px solid var(--iron);
  --schein: var(--brass-dark);
  border-radius: 2px;
  padding: 0.5rem 0.6rem;
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(255, 255, 255, 0.02);
}
/* Eine erfuellte Aufgabe bleibt stehen (was man geschafft hat, soll man
   sehen), tritt aber zurueck — sonst konkurriert sie mit der offenen.
   SEIT DEM 15.09.2026 NUR NOCH DIE TAGESAUFGABE, deren Lohn abgeholt ist: Ein
   erfuellter AUFTRAG traegt `.abholbar` und den goldenen Knopf, und nach dem
   Abschliessen ist er weg (weiter unten). */
.qf-aufgabe.erfuellt { opacity: 0.62; --schein: var(--moss, #7fa06a); }
.qf-titel {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
  margin: 0 0 0.35rem;
  font-size: 0.9rem;
  color: var(--brass-light);
}
.qf-erledigt {
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--moss, #7fa06a);
}
/* DIE REDE des Markgrafen — eingerueckt und schmaler als der Rest, damit sie
   als gesprochenes Wort lesbar ist und nicht als Anleitung. */
.qf-rede {
  margin: 0 0 0.5rem;
  padding-left: 0.55rem;
  border-left: 1px solid var(--brass-dark);
  font-size: 0.85rem;
  line-height: 1.5;
}
.qf-rede p { margin: 0 0 0.4rem; }
.qf-rede p:last-child { margin-bottom: 0; }

.qf-ziele { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.22rem; }
.qf-ziel {
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  font-size: 0.86rem;
}
.qf-ziel.erfuellt .qf-ziel-text { color: var(--text-dim); text-decoration: line-through; }
.qf-haken { color: var(--moss, #7fa06a); font-weight: 700; }
/* Der Zaehler steht in Ziffern und nicht als Balken: "1/2" sagt genau, was
   noch fehlt — ein Balken sagt nur "etwa die Haelfte". */
.qf-zaehler {
  flex: none;
  min-width: 2.2em;
  font-variant-numeric: tabular-nums;
  color: var(--brass-light);
}
.qf-von { color: var(--text-dim); }

/* DIE TAGESAUFGABE (13.09.2026) — dieselbe Karte wie ein Auftrag, dazu Lohn,
   Strafe und Knöpfe. Das Angebot trägt einen hellen Rand, damit es unter
   erledigten Aufträgen nicht wie einer von ihnen aussieht. */
.qf-tages.angeboten { --schein: var(--brass-light); }
.qf-tages.vorbei { opacity: 0.72; --schein: var(--iron); }
.qf-marke {
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-dim);
  white-space: nowrap;
}
.qf-zusatz { margin: 0.3rem 0 0; font-size: 0.76rem; line-height: 1.4; color: var(--text-dim); }
.qf-lohn {
  margin: 0.45rem 0 0;
  font-size: 0.86rem;
  font-variant-numeric: tabular-nums;
  color: var(--brass-light);
}
/* DIE STRAFE IN GEDÄMPFTEM ROT — Rot heißt in diesem Spiel ACHTUNG, und genau
   das ist sie. Gedämpft, weil sie eine Auskunft ist und kein Fehler. */
.qf-strafe { margin: 0.3rem 0 0; font-size: 0.78rem; line-height: 1.4; color: #c99a8a; }
.qf-knoepfe { display: flex; flex-wrap: wrap; align-items: center; gap: 0.45rem; margin-top: 0.55rem; }
.qf-knoepfe button { font-size: 0.84rem; padding: 0.32rem 0.85rem; }
.qf-knoepfe button.schlicht { padding: 0.2rem 0; font-size: 0.8rem; }
.qf-knoepfe button[disabled] { opacity: 0.55; cursor: var(--cursor-kupfer); }
.qf-annehmen { border-color: var(--brass); }

/* DIE SIEGELBRIEFE DER GÖNNER (03.10.2026, docs/vorhaben/questgeber.md) —
   dasselbe Pergament wie ein Auftrag, oben auf dem Blatt der Kopf des
   Absenders: sein Bildnis (bunt, wie Albrechts — Ansage des Bro: „die
   portraits weiterhin bunt") oder, solange es keines gibt, sein Wappen.
   Dieselbe Zeile trägt Sophies Auftrag in Albrechts Reihe. */
.qf-briefkopf {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.45rem;
}
.qf-geberbild {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 30%;
  border: 1px solid rgba(110, 36, 21, 0.45);
}
/* Ein Wappen ist ein Schild, kein Bildnis: nicht rund beschneiden, sondern in
   die Schildform der Diplomatie-Tafel (100 : 118). */
.qf-geberbild.qf-schild {
  --schild: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 118' preserveAspectRatio='none'><path d='M3 10 Q3 2 12 2 L88 2 Q97 2 97 10 L97 52 C97 86 74 108 50 116 C26 108 3 86 3 52 Z'/></svg>");
  width: 29px;
  height: 34px;
  border: none;
  border-radius: 0;
  object-fit: cover;
  -webkit-mask: var(--schild) center / 100% 100% no-repeat;
  mask: var(--schild) center / 100% 100% no-repeat;
}
.qf-briefvon b { display: block; font-size: 0.86rem; color: #6e2415; }
.qf-briefvon small { display: block; font-size: 0.72rem; color: #6b5a45; }

/* DIE AUFTRAGGEBER ALS REITER (24.10.2026, Ansage des Bro: „die portraits im
   questfenster wie reiter zwischen denen man wechseln kann"): eine Leiste
   gleich großer Felder, das offene hell umrandet, ein Punkt, wo Post wartet. */
.qf-reiter {
  display: flex;
  flex-wrap: nowrap;
  gap: 0;
  /* BÜNDIG MIT DEM FENSTER (24.10.2026, Ansage des Bro: „portraits so machen
     dass die bündig enden mit dem fenster", Fassung C aus
     Aufgabenfenster-Reiter-Entwurf.html): die Leiste hebt den Innenrand von
     `.qf-koerper` auf und sitzt direkt unter dem Kopf. */
  margin: -0.6rem -0.7rem 0.35rem;
  border-bottom: 1px solid var(--brass-dark);
}
.qf-reiterknopf {
  position: relative;
  /* Acht passen immer in EINE Reihe (24.10.2026, Ansage des Bro: „auf 8
     beschränken sodass die in einer reihe passen") — und füllen sie ganz. */
  flex: 1 1 0;
  min-width: 0;
  aspect-ratio: 1;
  margin: 0;
  padding: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #16161a;
  border: 1px solid var(--iron);
  border-top: 0;
  border-bottom: 0;
  border-radius: 0;
  cursor: var(--cursor-gold, pointer);
}
.qf-reiterknopf + .qf-reiterknopf { border-left: 0; }
.qf-reiterknopf:first-child { border-left: 0; }
.qf-reiterknopf:last-child { border-right: 0; }
.qf-reiterknopf .qf-geberbild { width: 100%; height: 100%; border-radius: 0; opacity: 0.6; border-color: var(--iron); }
.qf-reiterknopf .qf-geberbild.qf-schild { width: auto; height: 100%; aspect-ratio: 100 / 118; }
/* Unbekannt: grau und verschwommen (24.10.2026). */
.qf-reiterknopf.unbekannt .qf-geberbild { filter: grayscale(1) blur(2.5px); opacity: 0.45; }
.qf-reiterknopf.unbekannt.an .qf-geberbild { opacity: 0.6; }
.qf-reitername {
  margin: 0 0 0.5rem;
  color: var(--brass-light);
  font-family: var(--font-display, Georgia, serif);
  font-size: 1.05rem;
  letter-spacing: 0.02em;
}
.qf-reitername.unbekannt { color: var(--text-dim); font-style: italic; }
.qf-reiterknopf:hover .qf-geberbild { opacity: 0.9; }
.qf-reiterknopf.an { background: #24211a; }
.qf-reiterknopf.an .qf-geberbild { opacity: 1; border-color: var(--brass-light); }
.qf-reiterknopf.post::after {
  content: "";
  position: absolute;
  top: 4px;
  right: 4px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #d8b24a;
  box-shadow: 0 0 0 1px #000;
}
.qf-reiterwort { font-size: 0.7rem; color: var(--text-dim); }
.qf-wo { color: #6b5a45; }

/* DIE GÖNNER OBEN, wenn Albrecht fort ist: eine Reihe kleiner Bildnisse, jedes
   mit seinem Gunstbalken (0 bis +200). Wer noch nicht schreibt, steht blasser
   da; wer eng verbunden ist, trägt einen hellen Rand. */
.qf-goenner {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0 0 0.25rem;
}
.qf-goenner-ein {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
}
.qf-goenner-ein.still { opacity: 0.55; }
.qf-goenner .qf-geberbild { border-color: var(--brass-dark); }
.qf-goenner-ein.eng .qf-geberbild { border-color: var(--brass-light); }
.qf-gunst {
  display: block;
  width: 34px;
  height: 3px;
  background: var(--iron);
}
.qf-gunst > i {
  display: block;
  height: 100%;
  background: var(--brass-light);
}

/* DIE AUFGABEN STEHEN AUF PERGAMENT, UND AM ENDE WIRD GESIEGELT (28.09.2026).
   Es ersetzt den goldenen Knopf „Abschließen" (15.09.2026). Ansagen des Bro,
   der Reihe nach: „dass der nicht mehr so goldig ist sondern dass da so ein
   stempel ist den man draufdrücken soll", „der siegel ist unser klassen
   siegel", und zuletzt: „können wir ähnlich wie beim codex … hier aus so
   pergament machen auf dem die quest ausgeschrieben wird und am ende wird es
   gestempelt? bitte den siegel nicht von oben zeigen. einfach nur abschließen
   knopf hinzufügen und wenn man draufdrückt wird der wachs eingedrückt. bitte
   den wachs auch würfeln".

   DAS BLATT (quests/pergament.webp, in Nanobanana Pro 4K gewürfelt, siehe
   scripts/build-aufgabenpergament.mjs) liegt als RAHMENBILD auf jeder Karte:
   Ecken und Ränder bleiben, wie sie gemalt sind, nur die Mitte wird gezogen —
   eine Karte kann zwei Zeilen hoch sein oder zwanzig. Oben links sitzt das
   Eselsohr; es misst im Bild 280 Punkte und steht darum als eigener Eckteil
   (280 von 2000 Punkten → 36 Punkte in der Karte). Wer ein anderes Blatt
   übernimmt, misst die Ecke neu.

   DIE SCHRIFT IST TINTE: Auf dem hellen Blatt trägt kein Messing, die Farben
   stehen hier und nicht in den Regeln darüber, die für den dunklen Grund
   gelten.

   DAS WACHS IST DER KNOPF: rechts unten ein gewürfelter Klecks
   (quests/wachs.png), darunter klein „Abschließen" — Ansage am ersten Bild:
   „lass uns den button abschließen weg. den stempel 20% größer und unter dem
   stempel in klein schreiben abschließen und dann muss man auf den stempel
   klicken". Der Klick drückt das Zeichen der eigenen Klasse hinein — derselbe Klecks mit dem Relief der Bronzescheibe aus der
   Charakterwahl (quests/wachs-<klasse>.png). Kein Stempel, keine Scheibe im
   Bild: Man sieht nur, wie das Wachs nachgibt. */
.qf-aufgabe,
.qf-aufgabe.erfuellt,
.qf-aufgabe.abholbar,
.qf-tages.angeboten,
.qf-tages.vorbei {
  border: 1px solid transparent;
  border-radius: 0;
  border-image: url("/app/quests/pergament.webp") 280 60 60 280 fill / 36px 8px 8px 36px stretch;
  background: none;
  /* Links 2,5rem: Die Schrift beginnt rechts vom Eselsohr (36 Punkte), nicht
     darauf — Ansage des Bro: „text etwas nach rechts rücken damit die ecke des
     dokuments nicht beschrieben wird". */
  padding: 0.85rem 0.9rem 0.8rem 2.5rem;
  color: #3a2819;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.55));
}
/* Erledigtes tritt zurück — auf Pergament heißt das: die Tinte verblasst, das
   Blatt bleibt ein Blatt. */
.qf-aufgabe.erfuellt,
.qf-tages.vorbei {
  opacity: 1;
}
.qf-aufgabe.erfuellt .qf-siegeltext,
.qf-aufgabe.erfuellt .qf-titel,
.qf-aufgabe.erfuellt .qf-naechste,
.qf-tages.vorbei > * {
  opacity: 0.7;
}
.qf-aufgabe .qf-titel {
  color: #6e2415;
}
.qf-aufgabe .qf-erledigt {
  color: #4a6a2c;
}
.qf-aufgabe .qf-marke,
.qf-aufgabe .qf-zusatz,
.qf-aufgabe .qf-von,
.qf-aufgabe .qf-ziel.erfuellt .qf-ziel-text {
  color: #6b5a45;
}
.qf-aufgabe .qf-rede {
  border-left-color: rgba(110, 36, 21, 0.35);
}
.qf-aufgabe .qf-haken,
.qf-aufgabe .qf-fertig {
  color: #4a6a2c;
}
.qf-aufgabe .qf-zaehler,
.qf-aufgabe .qf-lohn,
.qf-aufgabe .qf-naechste .qf-uhr {
  color: #7a4a18;
}
.qf-aufgabe .qf-lohn {
  font-weight: 600;
}
.qf-aufgabe .qf-strafe,
.qf-aufgabe .qf-fehler {
  color: #8a2e1c;
}
.qf-aufgabe .qf-naechste {
  color: #6b5a45;
  border-top-color: rgba(90, 60, 30, 0.3);
}
.qf-aufgabe button.schlicht {
  color: #6b5a45;
  text-decoration-color: rgba(90, 60, 30, 0.45);
}
.qf-aufgabe button.schlicht:hover {
  color: #6e2415;
}

/* Ziele, Lohn und Knopf links, das Wachs rechts daneben — unten bündig, wie
   ein Siegel unter einer Urkunde. */
.qf-siegelzeile {
  display: flex;
  align-items: flex-end;
  gap: 0.6rem;
}
.qf-siegeltext {
  flex: 1 1 auto;
  min-width: 0;
}
/* Der Knopf ist das Wachs mit seiner Beschriftung darunter — kein Rahmen, kein
   Grund. Nach dem Abschließen steht an derselben Stelle `.qf-siegelfeld`
   (Siegel und „gesiegelt"), damit beim Umzeichnen nichts springt. */
button.qf-siegeln,
.qf-siegelfeld {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  margin: 0 -0.1rem -0.2rem 0;
}
button.qf-siegeln {
  padding: 0.1rem 0.15rem 0;
  background: none;
  border: none;
  border-radius: 4px;
  box-shadow: none;
  transition: none;
}
button.qf-siegeln:hover,
button.qf-siegeln:active {
  background: none;
  box-shadow: none;
  transform: none;
}
button.qf-siegeln:focus-visible {
  outline-color: #6e2415;
}
button.qf-siegeln[disabled] {
  cursor: var(--cursor-kupfer);
}
.qf-siegeln-text {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #6e2415;
}
.qf-siegelfeld .qf-siegeln-text {
  color: #4a6a2c;
  opacity: 0.8;
}
button.qf-siegeln:hover .qf-siegeln-text,
button.qf-siegeln:focus-visible .qf-siegeln-text {
  color: #9a2a14;
}
/* Unter dem Zeiger hebt sich der Klecks ein wenig und glänzt. */
button.qf-siegeln:hover .qf-wachs,
button.qf-siegeln:focus-visible .qf-wachs {
  transform: translateY(-2px);
  filter: drop-shadow(0 4px 3px rgba(60, 25, 10, 0.45)) brightness(1.1);
}
/* Der Klecks: 67 Punkte (20 % größer als die erste Fassung, Ansage des Bro),
   gezeichnet aus einem Bild von 112. Glatt und gesiegelt sind DERSELBE Klecks —
   übereinander, nur die Deckkraft wechselt. */
.qf-wachs {
  position: relative;
  flex: none;
  display: block;
  width: 67px;
  height: 67px;
  filter: drop-shadow(0 2px 2px rgba(60, 25, 10, 0.45));
  transition: transform 0.15s ease-out, filter 0.15s ease-out;
}
.qf-wachs img {
  position: absolute;
  inset: 0;
  width: 67px;
  height: 67px;
  pointer-events: none;
}
.qf-wachs-abdruck {
  opacity: 0;
}
.qf-wachs.gesiegelt .qf-wachs-abdruck {
  opacity: 1;
}
.qf-wachs.gesiegelt .qf-wachs-glatt {
  opacity: 0;
}

/* DAS EINDRÜCKEN — alle Stufen hängen an EINER Dauer (`--qf-stempel`, gesetzt
   aus STEMPEL_MS in questfenster.js) und an EINEM Zeitpunkt (`--qf-seit` an
   der Karte): Zeichnet das Fenster mitten darin neu, läuft jede Stufe dort
   weiter, wo sie war. Das Wachs duckt sich, gibt nach, und bei 22 % steht das
   Zeichen darin. `both` hält das Ende fest. */
.qf-aufgabe.wird-gesiegelt {
  animation: qf-rumms var(--qf-stempel, 700ms) linear var(--qf-seit, 0ms) both;
}
.wird-gesiegelt .qf-wachs {
  animation: qf-wachs-gibt-nach var(--qf-stempel, 700ms) linear var(--qf-seit, 0ms) both;
}
.wird-gesiegelt .qf-wachs-abdruck {
  animation: qf-wachs-abdruck var(--qf-stempel, 700ms) linear var(--qf-seit, 0ms) both;
}
@keyframes qf-wachs-gibt-nach {
  0% {
    transform: none;
    filter: drop-shadow(0 2px 2px rgba(60, 25, 10, 0.45));
    animation-timing-function: ease-in;
  }
  20% {
    transform: scale(0.9);
    filter: drop-shadow(0 0 1px rgba(60, 25, 10, 0.6)) brightness(0.8);
    animation-timing-function: ease-out;
  }
  34% {
    transform: scale(1.1, 1.06);
    filter: drop-shadow(0 2px 2px rgba(60, 25, 10, 0.45));
  }
  50% {
    transform: scale(0.98);
  }
  66%,
  100% {
    transform: none;
    filter: drop-shadow(0 2px 2px rgba(60, 25, 10, 0.45));
  }
}
@keyframes qf-wachs-abdruck {
  0%,
  21.9% {
    opacity: 0;
  }
  22%,
  100% {
    opacity: 1;
  }
}
/* Die Karte gibt beim Eindrücken einen Hauch nach. */
@keyframes qf-rumms {
  0%,
  17.9% {
    transform: none;
  }
  21% {
    transform: translateY(2px);
  }
  30%,
  100% {
    transform: none;
  }
}

/* EIN ABGESCHLOSSENER AUFTRAG GEHT — „dann verschwindet auch der quest".
   Erst leuchtet er kurz auf (seit dem 28.09.2026 mit dem Siegel darauf und
   ohne Gold, nur ein warmer Schein), dann verblasst er und klappt zu; questfenster.js
   zeichnet erst danach neu. Die Dauer kommt aus dem Skript (`--qf-geht`,
   GEHT_MS) — stünde hier eine eigene Zahl, risse das Neuzeichnen die Karte
   mitten im Verblassen heraus. Die Höhe setzt das Skript vorher fest: Von
   „auto" lässt sich nicht auf null klappen. Der negative Rand holt den
   Abstand der Liste mit ein. */
.qf-aufgabe.geht {
  overflow: hidden;
  animation: qf-geht var(--qf-geht, 520ms) ease-in forwards;
}
@keyframes qf-geht {
  0% {
    opacity: 1;
    box-shadow: 0 0 0 0 rgba(214, 190, 140, 0);
  }
  30% {
    opacity: 1;
    box-shadow: 0 0 14px 2px rgba(214, 190, 140, 0.35);
  }
  100% {
    opacity: 0;
    transform: translateX(28px);
    height: 0;
    padding-top: 0;
    padding-bottom: 0;
    margin-top: -0.55rem;
    border-width: 0;
    box-shadow: 0 0 0 0 rgba(214, 190, 140, 0);
  }
}

/* DIE ABGEHOLTE TAGESAUFGABE kommt als „Erfüllt" wieder, mit dem Siegel im
   Wachs, und ihre Tinte verblasst langsam wie auf jeder erledigten Karte. Bis
   zum 28.09.2026 leuchtete sie dabei golden auf; das Siegel ist jetzt der
   Moment, ein zweiter Schein danach wäre einer zu viel. */
.qf-tages.erfuellt.belohnt .qf-siegeltext,
.qf-tages.erfuellt.belohnt .qf-titel,
.qf-tages.erfuellt.belohnt .qf-naechste {
  animation: qf-belohnt 1.6s ease-out;
}
@keyframes qf-belohnt {
  0%,
  35% {
    opacity: 1;
  }
  100% {
    opacity: 0.7;
  }
}

/* „Der Markgraf zahlt: +50 Silber · +100 Erfahrung" — oben im Fenster, ein
   paar Sekunden (questfenster.js, LOHNMELDUNG_MS). Auf den Landkarten gibt es
   keine Marke im Bild und keine rollende Silberzahl; dort ist dieser Satz die
   ganze Belohnung, die man sieht. */
.qf-lohnmeldung {
  margin: 0;
  padding: 0.35rem 0.6rem;
  font-size: 0.86rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: #f3d27a;
  border: 1px solid rgba(226, 189, 98, 0.55);
  border-radius: 2px;
  background: rgba(226, 189, 98, 0.12);
  animation: qf-lohnmeldung-auf 0.35s ease-out;
}
.qf-lohnteil {
  white-space: nowrap;
}
/* Das Bildchen der Ware vor ihrer Zahl (13.10.2026) — wie in der Vorratsleiste. */
.qf-lohnicon {
  width: 1.4em;
  height: 1.4em;
  margin: -0.2em 0.25em -0.2em 0;
  vertical-align: middle;
}
@keyframes qf-lohnmeldung-auf {
  0% {
    opacity: 0;
    transform: translateY(-4px);
  }
  100% {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Kein Nachgeben, kein Wegklappen — ein Klick setzt das Zeichen sofort ins
     Wachs. */
  .qf-aufgabe.wird-gesiegelt,
  .wird-gesiegelt .qf-wachs,
  .qf-aufgabe.geht,
  .qf-tages.erfuellt.belohnt .qf-siegeltext,
  .qf-tages.erfuellt.belohnt .qf-titel,
  .qf-tages.erfuellt.belohnt .qf-naechste,
  .qf-lohnmeldung {
    animation: none;
  }
  .wird-gesiegelt .qf-wachs-abdruck {
    animation: none;
    opacity: 1;
  }
}

/* KEINE FESTE MINDESTBREITE (17.09.2026, Ansage des Bro: „responsive
   design"). Hier standen 440px, und auf einem schmalen Schirm ragte das
   Fenster damit hinaus — eine Mindestbreite im CSS kennt den Schirm nicht.
   Wie schmal es wirklich werden darf, rechnet heerschau.js aus dem Schirm
   (`MIN_BREITE`, `masse()`); das Gitter darin bricht von selbst um. */
.hs-fenster {
  min-width: 0;
}
.hs-koerper {
  display: flex;
  flex-direction: column;
  overflow: auto;
  padding: 0.6rem 0.7rem;
  gap: 0.55rem;
}
.hs-fehler,
.hs-meldung {
  margin: 0;
  font-size: 0.85rem;
  color: var(--moss, #7fa06a);
}
.hs-fehler { color: #d08a7a; }
.hs-meldung.hs-schlimm { color: #d08a7a; }
.hs-fehler[hidden],
.hs-meldung[hidden] { display: none; }

/* Die Kopfzahlen: vier Werte nebeneinander, gross die Zahl, klein das Wort.
   96px statt 120px, damit die vier auch in einem schmal gezogenen Fenster in
   EINER Reihe stehen — umgebrochen liest sich eine Zahlenreihe als Tabelle. */
.hs-zahlen {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 0.4rem;
}
.hs-zahl {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.3rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.18));
  border-radius: 2px;
  text-align: center;
}
.hs-zahl strong {
  font-size: 1.25rem;
  line-height: 1.1;
  white-space: nowrap;
}
/* Der Nenner im Bruch „3 / 73": dieselbe Zahl, nur leiser — was man hat,
   steht vorn, was hineinpasst, dahinter. */
.hs-zahl strong small {
  font-size: 0.62em;
  color: var(--text-dim);
  font-weight: 400;
}
.hs-zahl span {
  font-size: 0.72rem;
  color: var(--text-dim);
  line-height: 1.2;
}
/* DIE SYMBOLE DER KOPFZAHLEN (16.10.2026). */
.hs-zahlsymbol { width: 28px; height: 28px; object-fit: contain; }

.hs-belagerung {
  margin: 0;
  font-size: 0.82rem;
  color: var(--text-dim);
}
.hs-belagerung.hs-reif { color: var(--moss, #7fa06a); }

.hs-sperre {
  margin: 0 0 0.4rem;
  font-size: 0.78rem;
  color: #d0a87a;
}

/* Die fuenf Karten — Ritter, drei Gattungen, Soeldner. Nebeneinander, solange
   Platz ist; darunter, wenn das Fenster schmal gezogen wird.

   168px (17.09.2026): Die Vorgabebreite des Fensters ist darauf gerechnet
   (`SPALTE` in heerschau.js, fuenf Karten in EINER Reihe). Wer eine der beiden
   Zahlen dreht, dreht die andere mit — sonst steht eine Karte allein in der
   zweiten Zeile. Bei 148 brach in jeder Karte der Text um. */
/* WOHER DIE MÄNNER KOMMEN (20.10.2026, heerschau.js `quelle`): die Burg und die eigenen Dörfer,
   eine Leiste gleich breiter Felder mit Haarlinien — gewählt in Messing. */
.hs-herkunft {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  margin: 0 0 0.5rem;
  border: 1px solid var(--iron, #3b414a);
}
.hs-herkunft button {
  font: inherit;
  font-size: 0.85rem;
  padding: 0.35rem 0.4rem;
  background: #18181a;
  color: #e6dcc6;
  border: 0;
  border-radius: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: var(--cursor-gold);
}
.hs-herkunft button + button { border-left: 1px solid var(--iron, #3b414a); }
.hs-herkunft button:hover { background: #26221a; color: var(--brass-light); }
.hs-herkunft button.an { background: #2a2418; color: var(--brass-light); box-shadow: inset 0 -2px 0 var(--brass); }
.hs-herkunft button.leer { color: #8b8478; }
.hs-herkunft-zahl { font-variant-numeric: tabular-nums; color: #a99d86; margin-left: 0.25rem; }
.hs-karten {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
  gap: 0.5rem;
}
.hs-karte {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 0.5rem 0.55rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.18));
  border-radius: 2px;
}
.hs-karte-kopf {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.4rem;
}
.hs-name { font-weight: 600; }
.hs-bestand {
  font-size: 1.1rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Die Kampfsterne neben dem Bestand (17.09.2026) — sie hatten eine eigene
   Zeile je Karte und standen auch bei null Mann da. Klein und in Messing:
   Sie gehoeren zur Zahl davor, nicht neben sie. */
.hs-sternmarke {
  font-size: 0.68em;
  color: var(--brass, #b9975b);
}
/* DER RING MUSS LESBAR SEIN — loeseKampf wuerfelt nie ueber den Sieger, also
   darf niemand an einer Regel verlieren, die nirgends steht.

   EINE ZEILE, ZWEI ZEICHEN (17.09.2026): Er stand in zwei Zeilen Prosa
   („stark gegen …" / „schwach gegen …"), also zehn Zeilen ueber fuenf Karten.
   `column` bleibt der Rueckfall fuer sehr schmale Karten — dort bricht die
   Reihe um, statt die Namen abzuschneiden. */
.hs-ring {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  margin: 0;
  font-size: 0.74rem;
  line-height: 1.25;
}
.hs-stark { color: var(--moss, #7fa06a); }
.hs-schwach { color: var(--fire-light, #c98a6a); }
.hs-kosten {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.3;
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
}
/* Die Kosten als Symbol und Menge (16.10.2026). */
.hs-kostenteil { display: inline-flex; align-items: center; gap: 0.2rem; white-space: nowrap; }
.hs-kostenteil img { width: 18px; height: 18px; object-fit: contain; }
/* „· 3 Punkte" bleibt zusammen, wenn die Zeile umbricht — sonst steht das
   Wort „Punkte" allein in einer dritten Zeile und sieht aus wie eine eigene
   Auskunft. Die Kosten davor duerfen umbrechen, sie sind eine Aufzaehlung. */
.hs-punkte { white-space: nowrap; }
/* AUSBILDEN UND ANWERBEN SIND DERSELBE KNOPF (17.09.2026, Ansage des Bro:
   „bitte knoepfe ausbilden und anwerben gleich machen und kleiner machen").

   `.hs-werben` hatte NIE eine eigene Regel und fiel damit auf die Vorgabe des
   Browsers zurueck: fette Systemschrift, dicker Rahmen, graue Flaeche. In der
   Reihe daneben stand er darum als der auffaelligste Knopf des Fensters — und
   ist die Ausnahme, nicht die Regel: Vier Karten bilden aus, eine wirbt an.

   KLEINER ALS VORHER (0,74rem statt der Erbschrift, schmaleres Polster): Die
   Karte ist 168 Bildpunkte breit, und der Knopf muss nur lesbar sein, nicht
   laut. */
.hs-bilden,
.hs-werben,
.hs-belehnen {
  margin-top: auto;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
  border-radius: 2px;
  background: transparent;
  color: var(--text);
  cursor: var(--cursor-gold);
  font: inherit;
  font-size: 0.74rem;
  line-height: 1.5;
}
/* UEBER DIE GANZE BREITE DER KARTE (16.10.2026, Ansage des Bro: „den button
   ausbilden über gesamte breite der bilder") — unten angeschlagen, oben eine
   Linie, die Ecken der Karte. */
.hs-karte .hs-bilden,
.hs-karte .hs-werben,
.hs-karte .hs-belehnen {
  width: calc(100% + 1.1rem);
  margin: auto -0.55rem -0.5rem;
  padding: 0.45rem 0.5rem;
  border-width: 1px 0 0;
  border-radius: 0;
  font-size: 0.8rem;
}
.hs-bilden:hover:not(:disabled),
.hs-werben:hover:not(:disabled),
.hs-belehnen:hover:not(:disabled) { background: rgba(255, 255, 255, 0.06); }
.hs-bilden:disabled,
.hs-werben:disabled,
.hs-belehnen:disabled { opacity: 0.45; cursor: var(--cursor-kupfer); }
.hs-grund {
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.3;
}


/* Die ausklappbare Beschreibung je Gattung (01.09.2026) ist am 17.09.2026
   gefallen: Zugeklappt standen fuenfmal die Woerter „Was er taugt" im Fenster,
   die nichts sagen; aufgeklappt fuenf Absaetze uebereinander. Der Text haengt
   jetzt am Namen und am Bild der Karte (`title`). */
/* Der Knopf, der einen Mann von der Werkbank holt: gewarnt, nicht gesperrt. */
.hs-bilden.hs-warnt { border-color: var(--fire-light, #c98a6a); }
/* DIE TRUPPENLEISTE (17.09.2026) — was JEDEN Mann betrifft, in einer Zeile:
   die Ruestung und der Uebungsplatz.

   VORHER WAREN ES ZWEI BAUWEISEN AN ZWEI ORTEN: der Uebungsplatz eine Zeile
   ueber den Karten (seit 16.09.2026, davor eine Fussnote IN jeder Karte), die
   Ruestkammer ein Kasten darunter mit Kopf, Untertitel, Knopf und Grund. Zwei
   Sachen derselben Art, drei bis vier Zeilen hoch. Jetzt sind es zwei gleich
   gebaute Felder nebeneinander, und bei schmalem Fenster untereinander.

   Ein Feld ist: TITEL (was es ist) · WERT (was gerade gilt) · KNOPF (was man
   tun kann). Wer ein drittes ergaenzt — sagen wir den Sammelruf —, baut es
   genauso und muss nichts am Gitter aendern. */
.hs-truppenleiste {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0.4rem;
}
.hs-truppenblock {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}
.hs-truppenfeld {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.18));
  border-radius: 2px;
  font-size: 0.78rem;
  min-height: 1.9rem;
}
.hs-truppenfeld-titel {
  color: var(--text-dim);
  font-size: 0.72rem;
  white-space: nowrap;
}
/* Der Wert nimmt den Platz zwischen Titel und Knopf ein und schiebt den Knopf
   damit an den rechten Rand — ohne ein zweites `margin-left: auto` am Knopf,
   das bei einem fehlenden Knopf nichts tuete. */
.hs-truppenfeld-wert {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hs-sterne { margin: 0.2rem 0 0; font-size: 0.74rem; }
/* DIE AUFSTELLUNG — die Maenner nebeneinander, nicht untereinander.

   DAS SEITENVERHAELTNIS IST DER GANZE PUNKT, und deshalb steht es hier: Wer
   die Gestalt in einen festen Kasten zwaengt, bekommt einen Zwerg mit breitem
   Kopf. Jede Figur behaelt darum ihr eigenes Mass — der Bogenschuetze ist
   breiter als der Ritter, weil sein Bogen breiter ist. Gemasst wird die
   KACHEL (.hs-mann), nie die Gestalt darin; ausgeschrieben steht das
   weiter unten bei .hs-figur-platz. */
.hs-mannschaft {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}
/* SIE LIESS SICH NIE EINKLAPPEN (17.09.2026, beim Aufraeumen gemessen).
   heerschau.js setzt `hidden`, und die Vorgabe des Browsers dafuer verliert
   gegen JEDE Klassenregel mit `display` — die Liste stand also immer da,
   waehrend ihr Schalter „Mannschaftsliste zeigen" anbot. Im Fenster waren das
   104 ungewollte Bildpunkte, und der Knopf tat sichtbar nichts.

   Dieselbe Falle steht in CLAUDE.md, gefunden am 15.09.2026 am Hinweis ueber
   der Standarte. Die drei anderen `hidden`-Felder dieses Fensters (Fehler,
   Meldung, gewaehlter Mann) haben ihre Zeile; diesem fehlte sie. */
.hs-mannschaft[hidden] { display: none; }
.hs-lage {
  margin: 0;
  font-size: 0.82rem;
}
.hs-reihe {
  /* DER BEZUGSRAHMEN DER FIGURENLEINWAND (17.09.2026, siehe weiter unten):
     Sie liegt absolut darin und deckt den ganzen Behaelter. Ohne diese Zeile
     rechnete sie gegen den naechsten Vorfahren mit eigener Lage — und das ist
     das ganze Fenster. */
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  /* ZWEI ABSTAENDE, UND DER SENKRECHTE IST GROESSER (18.09.2026): Der Speer
     eines Knechts ragt rund fuenfzehn Bildpunkte ueber seine Kachel hinaus —
     seit die Figur doppelt so gross dasteht, ist das sichtbar. Ohne diese
     Zeile steht seine Spitze in den Sternen des Mannes, der in der Zeile
     darueber steht. Waagerecht bleibt es eng: Dort stehen sie Schulter an
     Schulter, und das ist eine Musterung. */
  column-gap: 0.15rem;
  row-gap: 16px;
  padding: 0.3rem 0.2rem 0;
  /* Ein Boden, auf dem sie stehen — ohne ihn schweben sie im Fenster. */
  border-bottom: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.18));
}
/* GLEICH GROSSE KACHELN, VERSCHIEDEN GROSSE FIGUREN.

   Die Kachel hat FESTE Masse, und das ist die Lehre, die aus Burgherr
   mitkommt: Ohne sie ist sie so hoch wie das, was darin steht — und ein
   Speerknecht, dessen Speer hochragt, waere dann hoeher als ein
   Schwertknecht. Die Rahmen beim Ueberfahren und die Auswahl standen damit
   auf drei verschiedenen Hoehen, und die Reihe las sich als drei verschieden
   grosse Maenner, obwohl die KOERPER gleich gross sind.

   Was IN der Kachel steht, wird darum nie in der Hoehe genormt — es steht am
   BODEN (align-items: flex-end) und darf nach oben hinausragen, so weit seine
   Waffe reicht. Wer hier je eine Hoehe an die Figur schreibt, holt genau den
   Fehler zurueck: Er rechnet den Unterschied zwischen Waffe und Koerper
   wieder heraus und staucht den Speerknecht. Gleich gross wird die KACHEL,
   nie die Gestalt. */
.hs-mann {
  box-sizing: border-box;
  /* DIE KACHEL IST 44 x 104 (18.09.2026, Ansage des Bro: „die figur ruhig
     doppelt so groß machen").

     Sie war 34 x 64, und hier stand „sie bleibt". Das ist auf Ansage
     zurueckgenommen: Der Mann stand 42 Bildpunkte hoch da und trug ueber sich
     26 leere — jetzt sind es 83 (`FIGUR_ANTEIL` 0,8 in heerfiguren.ts) und 21.
     Der Kopfraum wird dabei nicht kleiner, sondern voller: Die sechs Sterne
     stehen seither bei JEDEM Mann (grau, was er nicht hat), und genau dagegen
     ging die Ansage „sonst ist da zu viel leerer platz".

     DIE HOEHE IST DIE FIGUR PLUS DEN MARKEN: 83 Bildpunkte Mann, darueber die
     Sterne (6) und die roemische Zahl (9) samt Abstaenden. Wer sie kuerzt,
     ohne `FIGUR_ANTEIL` mitzuziehen, schiebt die Marken in den Kopf des
     Mannes — sie liegen ABSOLUT darin und werden nicht weggedrueckt.

     44 BREIT, weil der Mann jetzt seine WAFFEN traegt (Schwert an der Huefte,
     Schild auf dem Ruecken): Ohne sie war er dreizehn Bildpunkte breit, doppelt
     so gross sind es rund sechsundzwanzig, und der Schild am Ruecken kommt
     dazu. Sechs Sterne zu sechs Bildpunkten sind 36 von 44 — sie passen auch
     dann noch. Der Waechter in ruestungsbedingung.test.ts nennt die Zahlen. */
  width: 44px;
  height: 104px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  border: 1px solid transparent;
  border-radius: 2px;
  background: transparent;
  padding: 0 1px;
  cursor: var(--cursor-gold);
  line-height: 0;
  /* Fuer die Marken ueber dem Kopf (17.09.2026) — sie liegen ABSOLUT im
     Kopfraum der Kachel und nicht als Flex-Kind neben der Figur. Als Kind
     stuenden sie DANEBEN (justify-content: center auf einer Reihe) und
     schoeben die Gestalt aus der Mitte. */
  position: relative;
}
.hs-mann:hover { border-color: var(--brass-dark, rgba(255, 255, 255, 0.3)); }
/* IM FELD: blass und entfaerbt, aber DA. Wer ausgerueckt ist, verschwand
   vorher ganz aus der Reihe — und das las sich als "meine Soldaten sind weg".
   Er steht jetzt an seinem Platz und sieht aus, als sei er nicht hier. */
.hs-mann.hs-imfeld { opacity: 0.38; filter: grayscale(0.7); }
.hs-mann.hs-imfeld.hs-gewaehlt { opacity: 0.7; }
.gp-imfeld {
  margin-left: 0.4rem;
  font-size: 0.75em;
  color: var(--brass, #b9975b);
  opacity: 0.85;
  white-space: nowrap;
}
.wt-liste li.wt-blass { opacity: 0.72; }
/* Eine Nebenauskunft in der Gebaeudetafel — "noch 7 von 10 Soeldnern zu haben"
   steht neben dem Sold und soll leiser sein als er. Dieselbe Abschwaechung wie
   `wt-blass` in der Werttafel, damit beide Tafeln gleich sprechen. */
.gp-zeile.gp-blass { opacity: 0.72; }
.hs-mann.hs-gewaehlt { border-color: var(--brass, #b9975b); background: rgba(185, 151, 91, 0.12); }
/* DIE MARKEN UEBER DEM KOPF — Sterne fuer die Erfahrung, eine roemische Zahl
   fuer die Ruestung (17.09.2026, Ansage des Bro: „sternchen fuer erfahrung und
   eine roemische zahl fuer ausbaustufe der ruestung").

   SIE LIEGEN IM VORHANDENEN KOPFRAUM und machen die Kachel NICHT hoeher: Die
   Figur ist 38 Bildpunkte hoch und steht am Boden einer 64 hohen Kachel — die
   26 darueber waren leer. Eine hoehere Kachel haette die ganze Reihe
   umgeworfen, und die Kachel ist die eine Sache, die hier fest bleibt (siehe
   .hs-mann weiter oben).

   `pointer-events: none`: Der Klick gehoert dem Mann, nicht seinem Abzeichen.

   DIE ZAHL OBEN, DIE STERNE DARUNTER — also naeher am Mann: Die Sterne
   gehoeren IHM, die Ruestung ist gekauft. */
.hs-marken {
  position: absolute;
  top: 1px;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  pointer-events: none;
  line-height: 1;
}
.hs-marke-ruestung {
  font-family: var(--font-body, Georgia, serif);
  /* NEUN UND NICHT ACHT: Bei acht war „III" in einer Serifenschrift ein
     Strichbuendel, im Bild kaum von „II" zu unterscheiden. Neun passt noch
     dreifach in die 34 Bildpunkte der Kachel. */
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.5px;
  color: var(--brass, #b9975b);
  /* Ein Hauch dunkler Grund, damit die Zahl auch ueber einem hellen
     Bildpunkt der Nachbarfigur lesbar bleibt. */
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.75);
}
/* Dieselbe Zahl in der Tafel des gewaehlten Mannes, mitten im Satz — dort
   darf sie groesser sein, und sie steht neben ihrem Namen. */
.hs-marke-inline {
  font-size: 0.8rem;
  letter-spacing: 1px;
  text-shadow: none;
}
.hs-marke-sterne {
  display: flex;
  justify-content: center;
  /* KEIN Abstand: Sechs Sterne zu 6 Bildpunkten sind 36 von 42 verfuegbaren.
     Der Stern laesst durch seine Form an den Seiten Luft — sie lesen sich
     auch ohne Luecke als einzelne. */
  gap: 0;
  max-width: 42px;
}
/* DER STERN IST GESCHNITTEN, NICHT GESCHRIEBEN. Das Zeichen ★ ist bei 5
   Bildpunkten in jeder Schrift ein Fleck; ein `clip-path` bleibt eine Form mit
   Spitzen, weil er auf dem Bildpunktraster abschneidet statt zu rastern. */
/* SECHS PLAETZE STEHEN IMMER DA (18.09.2026, Ansage des Bro: „immer die
   sterne stehen, nur in grau wenn er die nicht bekommen hat und wenn er die
   bekommen hat in gold"). Der leere Platz ist DIESE Regel — grau und gedeckt,
   gerade sichtbar; Gold kommt mit `.hs-stern-voll` darueber. So liest die Reihe
   sich als Leiter: Man sieht auf einen Blick, wer wie weit ist, und nicht nur,
   wer etwas hat. */
.hs-stern {
  width: 6px;
  height: 6px;
  background: rgba(255, 255, 255, 0.2);
  clip-path: polygon(
    50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%,
    50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%
  );
}
/* ERKAEMPFT = GOLD. */
.hs-stern-voll { background: var(--brass-light, #cca75e); }
/* HALBE STERNE GIBT ES WIRKLICH (`sterneKampf` kann 2,5 sein): Bei sechs
   Bildpunkten laesst sich einer nicht halb zeichnen, also steht er als BLASSES
   Gold auf seinem Platz. Das liest sich als „einer noch nicht ganz" und ist
   ehrlicher als Aufrunden.

   NICHT `opacity`: Die wirkte auf dem alten, goldenen Grundstern; heute ist der
   Grund grau, und ein durchscheinendes Gold darauf waere schmutzig statt
   blass. */
.hs-stern-halb { background: rgba(204, 167, 94, 0.45); }
/* DIE RUESTZEILE in der Tafel des gewaehlten Mannes. */
.hs-ruestung { margin: 0.2rem 0 0; font-size: 0.78rem; }
/* DER KNOPF „RUESTEN" — wie `.hs-entlassen`, aber messing statt rot: Er GIBT
   dem Mann etwas. Gesperrt sieht er aus wie jeder gesperrte Knopf des Hauses,
   und der Grund steht als Satz darunter. */
.hs-ruesten {
  margin-top: 0.3rem;
  font-size: 0.78rem;
  padding: 0.18rem 0.5rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
  border-radius: 2px;
  background: rgba(185, 151, 91, 0.14);
  color: inherit;
  cursor: var(--cursor-gold);
}
.hs-ruesten:hover:not(:disabled) { background: rgba(185, 151, 91, 0.26); }
.hs-ruesten:disabled { opacity: 0.45; cursor: var(--cursor-kupfer); }
/* DIE FIGUR IST HEUTE EIN PLATZHALTER AUS CSS. Ansage des Bauherrn: "mach
   keine sprites einfach erst mal als platzhalter — wir machen spaeter
   richtige 3d modelle." Burgfried hat seit dem 29.08.2026 keine 2D-Ansicht,
   also auch keine gezeichneten Figuren; was hier hingehoert, sind Bilder aus
   den 3D-Modellen.

   DREI FORMEN, MEHR BRAUCHT ES NICHT: das Element ist der Rumpf, ::before der
   Kopf, ::after die Waffe. Damit liest sich die Reihe als SCHAR, und die
   Gattungen sind zu unterscheiden — genau das ist der Zweck der Aufstellung
   ("die Soldaten nicht unter eine Liste, sondern nebeneinander aufstellen wie
   eine kleine Armee").

   BUCHSTABEN WAEREN HIER DAS SCHLECHTERE gewesen, und darum steht es hier:
   "Sp", "Sc" und "Soe" fangen alle mit S an und sind im Vorbeisehen nicht zu
   trennen. Eine Gestalt erkennt man, ein Kuerzel muss man lesen.

   WER DIE BILDER LIEFERT, tauscht figurPlatzhalter() in heerschau.js gegen
   ein <img class="hs-figur"> (dann hier `image-rendering` und
   `vertical-align: bottom` setzen, KEINE Hoehe — siehe oben) und loescht die
   -platz-Regeln. Die Kachel bleibt, wie sie ist. */
/* DER PLATZ DER MUSTERUNG (16.10.2026, Ansage des Bro: „wie so ein fenster
   mit einem 3d fenster drinne", „wir nehmen die erde textur"). Ein Fenster
   mit Messingrand, darin die angetretene Truppe auf gemalter Erde
   (client/src/iso3d/heerfiguren.ts). Die Hoehe waechst mit dem Fenster, aber
   nie unter ein Mass, auf dem man einen Mann noch anklicken kann. */
.hs-wiese {
  position: relative;
  /* EIN SECHSTEL NIEDRIGER SEIT DEM 21.10.2026 (Ansage des Bro: „nur etwas
     weniger höhe"); bis dahin clamp(260px, 46vh, 520px). Die Untergrenze steht
     auch in heerschau.js (`fensterNachTruppe`). */
  height: clamp(220px, 39vh, 440px);
  margin: 6px 0 8px;
  border: 1px solid var(--brass-dark);
  border-radius: 4px;
  overflow: hidden;
  background: #1c1712;
  box-shadow: inset 0 0 28px rgba(0, 0, 0, 0.75);
}
.hs-wiese[hidden] {
  display: none;
}
.hs-wiesenleinwand {
  position: absolute;
  left: 0;
  top: 0;
  display: block;
}
/* DER RAND DUNKELT NACH — der Platz geht nicht an einer Kante zu Ende, er
   verliert sich. Ueber der Leinwand, ohne Klicks zu schlucken. */
.hs-wiese::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 60px 10px rgba(12, 9, 6, 0.85);
}
.hs-reihe[hidden] {
  display: none;
}
/* DIE ALTE FIGURENLEINWAND UEBER DER REIHE ist am 16.10.2026 gefallen — die
   Modelle stehen seither auf dem Platz (.hs-wiese). Die Reihe aus CSS ist nur
   noch der Rueckfall der gemalten Landkarte. */
.hs-figur-platz {
  position: relative;
  display: block;
  /* SIE WAECHST MIT DER KACHEL (18.09.2026). Die Kachel ist von 64 auf 104
     Bildpunkte gewachsen, weil die echte Figur doppelt so gross dasteht — der
     gemalte Rueckfall stand danach als Zwerg am Boden eines hohen Kastens, und
     zwar genau dort, wo es KEIN 3D gibt: auf der gemalten Landkarte.

     1,6 UND NICHT 2, und das ist am SPEER gerechnet: Er steht 53 Bildpunkte
     ueber dem Fuss und muss unter den Marken bleiben (83 von 104). 53 mal 1,6
     sind 85 — zweifach waeren 106 und stiessen oben aus der Kachel heraus.

     `transform` UND NICHT neue Masse: Kopf, Rumpf und die fuenf Waffenformen
     haengen mit elf Zahlen aneinander; jede einzeln zu verdoppeln waere elf
     Gelegenheiten, dass eine davon stehen bleibt. */
  transform: scale(1.6);
  transform-origin: bottom center;
  box-sizing: border-box;
  width: 16px;
  height: 38px;
  border-radius: 5px 5px 1px 1px;
  background: var(--hs-rock, #6f6552);
  border: 1px solid rgba(0, 0, 0, 0.5);
}
/* Der Kopf. */
.hs-figur-platz::before {
  content: "";
  position: absolute;
  box-sizing: border-box;
  left: 50%;
  top: -11px;
  margin-left: -6px;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--hs-kopf, #a08a68);
  border: 1px solid rgba(0, 0, 0, 0.5);
}
/* Die Waffe — je Gattung eine andere Form an derselben Stelle. Sie ragt ueber
   den Rumpf hinaus; die Kachel hat den Platz dafuer, gerechnet: der Speer
   steht 53 Pixel ueber dem Fuss, mal 1,6 also 85 — und die Figur endet bei 83
   von 104 (siehe `transform` bei .hs-figur-platz). */
.hs-figur-platz::after {
  content: "";
  position: absolute;
  box-sizing: border-box;
}
.hs-figur-platz[data-art="speerknecht"]::after {
  left: -5px;
  top: -15px;
  width: 2px;
  height: 53px;
  background: var(--brass-dark, #6d5426);
}
.hs-figur-platz[data-art="schwertknecht"]::after {
  left: -5px;
  top: 2px;
  width: 3px;
  height: 22px;
  background: var(--brass-light, #cca75e);
}
.hs-figur-platz[data-art="bogenschuetze"]::after {
  left: -9px;
  top: -4px;
  width: 11px;
  height: 30px;
  border: 2px solid var(--brass-dark, #6d5426);
  border-right: 0;
  border-radius: 16px 0 0 16px;
}
/* Der Soeldner fuehrt den Speer, wie er kommt (siehe soeldnerKarte) — aber in
   einem anderen Rock: Er ist der Fremde in der Reihe, und das soll man sehen,
   ohne den Zeiger daraufzuhalten. */
.hs-figur-platz[data-art="soeldner"] {
  --hs-rock: #5c5a5e;
}
.hs-figur-platz[data-art="soeldner"]::after {
  left: -5px;
  top: -15px;
  width: 2px;
  height: 53px;
  background: var(--brass-dark, #6d5426);
}
/* Der Ritter traegt die Farbe des Hauses und einen Schild statt einer Waffe.
   Er steht ausserhalb des Rings (er wird nicht ausgebildet und nicht
   entlassen), und genau das erzaehlt die abweichende Gestalt. */
.hs-figur-platz[data-art="ritter"] {
  --hs-rock: #8a6f42;
  --hs-kopf: #b7a487;
}
.hs-figur-platz[data-art="ritter"]::after {
  left: -7px;
  top: 4px;
  width: 11px;
  height: 15px;
  border: 1px solid var(--brass, #a8813d);
  border-radius: 2px 2px 6px 6px;
  background: rgba(168, 129, 61, 0.22);
}
/* DIE INFOLEISTE (16.10.2026) — sie faehrt beim Klick auf Soldaten unten im
   Platz hoch, eine Zeile, von rechts nach links (`row-reverse`), abgestimmt
   auf /static/heerschau-entwurf.html (Hoehe 52, Schrift 0,82rem, Symbole 18,
   Abstand 14, Deckkraft 0,88, 260 ms). Ueber der Abdunklung des Randes. */
.hs-leistenrahmen {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  overflow: hidden;
  pointer-events: none;
}
.hs-leiste {
  display: flex;
  flex-direction: row-reverse;
  align-items: center;
  gap: 14px;
  min-height: 52px;
  padding: 6px 12px;
  background: rgba(16, 13, 10, 0.88);
  border-top: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
  font-size: 0.82rem;
  white-space: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  transform: translateY(100%);
  opacity: 0;
  transition: transform 260ms cubic-bezier(0.2, 0.8, 0.2, 1), opacity 260ms;
}
.hs-leiste::-webkit-scrollbar { display: none; }
.hs-leiste.offen { transform: translateY(0); opacity: 1; pointer-events: auto; }
.hs-teil { display: inline-flex; align-items: center; gap: 5px; }
.hs-teil img { width: 22px; height: 22px; object-fit: contain; }
.hs-teil img.hs-artbild { width: 28px; height: 28px; object-fit: cover; border-radius: 50%; border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25)); }
.hs-leistenname { font-weight: 700; font-size: 1.08em; }
.hs-trenner { width: 1px; align-self: stretch; background: rgba(138, 109, 59, 0.45); }
.hs-schieber { flex: 1; }
.hs-stern-zeichen { color: var(--brass-light, #d8b46a); }
.hs-roem { display: inline-block; min-width: 1.4em; padding: 0 4px; border: 1px solid var(--brass-dark); border-radius: 2px; text-align: center; font-weight: 700; }
.hs-plus { color: var(--moss, #8fbf6a); }
.hs-leiste .hs-ruesten,
.hs-leiste .hs-entlassen {
  margin: 0;
  padding: 4px 10px;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--text);
  font: inherit;
  cursor: var(--cursor-gold, pointer);
}
.hs-leiste .hs-entlassen { color: var(--fire-light, #d9845e); }
.hs-leiste .hs-ruesten:disabled { opacity: 0.45; cursor: var(--cursor-kupfer, default); }
.hs-leiste .hs-ruesten:hover:not(:disabled),
.hs-leiste .hs-entlassen:hover { background: rgba(255, 255, 255, 0.08); }
.hs-auswahl-zu {
  margin-left: auto;
  padding: 0 0.3rem;
  border: none;
  background: transparent;
  color: var(--text-dim);
  cursor: var(--cursor-gold, pointer);
  font-size: 1rem;
  line-height: 1;
}
.hs-auswahl-zu:hover { color: var(--text); }
.hs-rueckgabe { color: var(--text); }
/* DER RAHMEN, der beim Ziehen ueber dem Platz steht (heerfiguren.ts). */
.hs-wahlrahmen {
  position: absolute;
  z-index: 1;
  border: 1px solid rgba(232, 217, 168, 0.9);
  background: rgba(232, 217, 168, 0.12);
  pointer-events: none;
}

/* DIE VIGNETTE je Gattung. Sie steht OBEN in der Karte und nicht unten: Man
   sieht zuerst den Mann und liest dann, was er kostet.

   Der KASTEN steht schon in seinen endgueltigen Massen (volle Kartenbreite,
   9:5) — was fehlt, ist sein Inhalt. Bis das Bild aus dem 3D-Modell da ist,
   steht die gezeichnete Gestalt darin, gross; ein <img> darauf gaebe heute
   nur einen 404. Wer das Bild liefert, ersetzt .hs-vignette-platz durch ein
   <img class="hs-vignette"> und ergaenzt hier `object-fit: cover` — die
   Masse bleiben dieselben, die Karte muss sich also nicht neu setzen. */
/* DIE TAFEL IST QUADRATISCH (17.09.2026, Ansage des Bro: „die tafeln der
   soldaten quadratisch machen").

   GEMEINT IST DAS BILD DARIN, und daran haengt die ganze Karte: Der gewuerfelte
   Wurf ist quadratisch (`seitenverhaeltnis: "1:1"` je Motiv), weil eine
   stehende Figur ein stehendes Feld braucht. Auf 9:5 beschnitten fehlten ihr
   die Beine — `object-position` schob den Schnitt nur nach unten, statt ihn zu
   vermeiden.

   `aspect-ratio` UND KEINE HOEHE: Die Karte ist ein Gitterfeld, dessen Breite
   der Schirm bestimmt (`minmax(168px, 1fr)` in .hs-karten). Eine feste Hoehe
   waere bei jeder anderen Breite falsch. */
.hs-vignette {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: 2px;
  margin-bottom: 0.1rem;
}
/* GESTRICHELT, mit Absicht: Ein sauber gefuellter Kasten sieht fertig aus,
   und das ist er nicht. Die Gestalt steht am BODEN und waechst nach oben
   (transform-origin) — genau wie in der Reihe darunter, sonst schnitte der
   Kasten ihr den Kopf ab. */
/* DAS GEMALTE BILD, UEBER DEM PLATZHALTER (17.09.2026). Es deckt ihn zu,
   solange es laedt; faellt es aus, steht die gezeichnete Gestalt weiter da
   (Begruendung in heerschau.js, `vignette`).

   `absolute` in einem `relative`-Halter, nicht als Ersatz des Inhalts: So
   braucht es kein `onerror` mit HTML in einem Attribut. Der gestrichelte
   Rahmen des Platzhalters faellt hier weg — das Bild IST fertig, und ein
   „hier fehlt noch etwas"-Rahmen darum waere eine Luege. */
.hs-vignette-bildhalter { position: relative; border-style: solid; }
.hs-vignette-bild {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* `cover` und keine Verschiebung: Wurf und Feld sind beide quadratisch, es
     wird also gar nichts beschnitten. `cover` bleibt trotzdem stehen — ein
     kuenftiger Wurf in einem anderen Verhaeltnis soll das Feld fuellen und
     nicht mit Balken darin stehen. */
  object-fit: cover;
  display: block;
}

.hs-vignette-platz {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 6px;
  border: 1px dashed var(--brass-dark, rgba(255, 255, 255, 0.22));
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.05), rgba(0, 0, 0, 0.2));
  overflow: hidden;
}
.hs-vignette-platz .hs-figur-platz {
  transform: scale(1.35);
  transform-origin: bottom center;
}

/* "Getreuen rufen" im Bergfried (01.09.2026). Dieselbe Machart wie der Knopf
   in der Militaertafel (.wt-btn) — er tut auch dasselbe. */
.gp-ritter {
  display: block;
  width: 100%;
  margin-top: 0.35rem;
  padding: 0.3rem 0.5rem;
  border: 1px solid var(--brass-dark, rgba(255, 255, 255, 0.25));
  border-radius: 2px;
  background: transparent;
  color: var(--text);
  cursor: var(--cursor-gold);
  text-align: center;
}
.gp-ritter small { display: block; font-size: 0.72rem; color: var(--text-dim); }
.gp-ritter:hover:not(:disabled) { background: rgba(255, 255, 255, 0.06); }
.gp-ritter:disabled { opacity: 0.45; cursor: var(--cursor-kupfer); }
/* Der Entlassen-Knopf in der Mannschaftsliste — schmal, am rechten Rand,
   dieselbe Machart wie .gp-mini in der Gebaeudetafel. */
.hs-entlassen {
  border: 1px solid rgba(208, 138, 122, 0.5);
  border-radius: 2px;
  background: transparent;
  color: #d08a7a;
  cursor: var(--cursor-gold);
  padding: 0.2rem 0.6rem;
  font-size: 0.8rem;
}
.hs-entlassen:hover { background: rgba(208, 138, 122, 0.12); }

/* HIER STAND `.hs-ruesten` EIN ZWEITES MAL — der Knopf der alten Ruestkammer,
   die ALLE Maenner auf einen Streich ausruestete (01.09. bis 17.09.2026). Der
   Name lebt weiter, die Sache nicht: Er sitzt jetzt am einzelnen Mann (weiter
   oben, bei .hs-marken). Zwei Regelsaetze fuer dieselbe Klasse sind dasselbe
   Uebel wie zwei Regler fuer einen Wert — der spaeter gebaute gewinnt, und
   hier war das der TOTE. Der Knopf am Mann stand mit fremden Farben da, und
   man haette es ihm nicht angesehen. */
/* Was dem Knopf fehlt, steht als eigene Zeile unter seinem Feld (14.09.2026,
   Bauweise seit 17.09.2026) — im Block, nicht im Feld: Im Feld waere es eine
   dritte Spalte neben Titel und Wert und zerdrueckte beide. */
.hs-truppenblock .hs-grund {
  padding: 0 0.1rem;
  color: var(--text-dim);
}

/* --- Fenster schieben (server/public/fenster.js) --------------------------
   Waehrend eines Zuges KEINE Textauswahl: Gezogen wird ueberall dort, wo kein
   Bedienelement sitzt (die meisten dieser Tafeln haben gar keine Titelzeile) —
   ohne das markiert jeder Zug den Text, ueber den er laeuft, und das Fenster
   haengt an einer blauen Auswahl statt am Zeiger. */
body.fenster-zieht {
  user-select: none;
  -webkit-user-select: none;
}

/* --- Die Wissenstafel (22.09.2026) ------------------------------------------
   Ansage des Bro: „ich möchte einen lerneffekt im spiel einbauen … dass man
   dann so wegklicken kann aber man hat so ein lerneffekt und lernt was über
   geschichte und die holzburgen", und: „das ziel ist dass bei jedem großen
   gebäude wie schmiede oder köhler oder bäcker oder so so eine tafel kommt und
   etwas über das leben auf einer burg erklärt."

   SIE LIEGT UNTER DEM DILEMMA (890 gegen 900) und das mit Absicht: Wer
   entscheiden MUSS, dessen Frage gehört obenauf; ein Lernstück kann warten.

   UND SIE IST WÄHREND DES LADENS VERBORGEN. Der erste Zustand kommt an,
   während der Ladeschirm noch steht — ohne diese Regel stünde die Tafel vor
   einem Spiel, das man noch gar nicht gesehen hat. Dasselbe Mittel wie bei den
   Eckfenstern (`body:has(#laden) .chatfenster` in client/3d.html), und aus
   demselben Grund an `#laden` und nicht an `.fertig`: Sonst stünde sie schon
   während der Ausblendung darüber. */
#wissenstafel {
  position: fixed;
  inset: 0;
  z-index: 890;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(10, 11, 13, 0.76);
}
#wissenstafel[hidden] { display: none; }
body:has(#laden) #wissenstafel { display: none; }

/* --- DIE ANKÜNDIGUNGEN IM KOPFBAND (28.09.2026) --------------------------------
   Ansage des Bro: „alle events nicht immer direkt mitten ins fenster knallen
   sondern die werden oben im header als so ein schöner knopf eingeblendet der
   pulsiert und dann muss man auf den klicken und dann wird erst das event
   eingeblendet" (client/src/iso3d/ankuendigung.ts).

   Der Platz nimmt die Mitte des Bandes zwischen Datum und Knopfreihe; ist er
   leer, nimmt er nichts. Der Knopf ist dunkel mit Messing wie jede Bedienfläche
   des Spiels, und er PULSIERT mit einem Schein, nicht mit der Größe — ein
   Knopf, der wächst, schöbe bei jedem Schlag seine Nachbarn. */
/* MITTIG UNTER DEM BAND (28.09.2026, Ansage: „nicht in den header packen
   sondern einfach zentral unter dem header"). Kind des Bandes wie das Bildnis
   (`.bildnisecke`), darum `top: 100%`: Bricht das Band um oder rutscht es beim
   Laden, gehen die Knöpfe mit. */
.ankuendigungen {
  position: absolute;
  top: calc(100% + 0.55rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  display: flex;
  justify-content: center;
  gap: 0.6rem;
  max-width: calc(100vw - 30rem);
  flex-wrap: wrap;
}
.ankuendigungen:empty { display: none; }
.ankuendigung {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  max-width: 22rem;
  min-width: 0;
  padding: 0.22rem 0.8rem 0.24rem 0.45rem;
  font: inherit;
  text-align: left;
  color: var(--brass-light);
  background: linear-gradient(180deg, #25221d, #121110);
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  cursor: var(--cursor-gold);
  animation: ankuendigung-puls 1.8s ease-in-out infinite;
}
.ankuendigung:hover,
.ankuendigung:focus-visible {
  border-color: var(--brass-light);
  background: linear-gradient(180deg, #312c24, #181613);
  outline: none;
  animation-play-state: paused;
  box-shadow: 0 0 14px rgba(243, 210, 122, 0.55);
}
@keyframes ankuendigung-puls {
  0%, 100% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.55), 0 0 0 0 rgba(243, 210, 122, 0), inset 0 0 0 rgba(243, 210, 122, 0); border-color: var(--brass-dark); }
  50% { box-shadow: 0 4px 14px rgba(0, 0, 0, 0.55), 0 0 16px 2px rgba(243, 210, 122, 0.55), inset 0 0 8px rgba(243, 210, 122, 0.18); border-color: #f3d27a; }
}
@media (prefers-reduced-motion: reduce) {
  .ankuendigung { animation: none; border-color: #f3d27a; }
}
/* Das gewürfelte Zeichen (ankuendigung.ts, ZEICHEN_DATEI), 40 Bildpunkte —
   größer als die Knopfreihe, und es ragt oben und unten etwas über den Knopf
   hinaus, damit das Kopfband dafür nicht höher wird. */
.ank-zeichen { flex: none; display: block; width: 40px; height: 40px; margin: -4px 0 -4px -3px; }
.ank-zeichen img { display: block; width: 100%; height: 100%; filter: drop-shadow(0 0 3px rgba(243, 210, 122, 0.35)); }
.ank-text { display: flex; flex-direction: column; min-width: 0; line-height: 1.1; }
.ank-art {
  font-size: 0.64rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.ank-titel {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: 1.02rem;
}


/* --- DIE AUFSTIEGSFEIER (28.09.2026) -----------------------------------------
   Ansage des Bro: „können wir beim aufstiege markgraf und level wenn man auf
   den knopf drückt, dass dann so eine richtig coole schöne animation der
   meldung zum aufstieg kommt?" (client/src/iso3d/aufstiegsfeier.ts)

   ALLES IST CSS — Strahlen, Ring, Funken, das einfallende Emblem, der Glanz
   über dem Titel. Es läuft im Compositor und bleibt flüssig, auch wenn der
   Hauptstrang gerade am Gelände rechnet. Der Ablauf in Sekunden:
     0,0  der Grund dunkelt ab, die Strahlen gehen auf und drehen langsam
     0,15 der Lichtring schießt hinaus
     0,2  das Emblem fällt aus der Tiefe ein und federt nach
     0,25 die Funken fliegen
     0,7  Kicker und Titel steigen auf, der Glanz läuft über den Titel
     1,1  der Satz, 1,4 der Zusatz, 2,2 „Klicken, um fortzufahren"
   Liegt über ALLEM, auch über dem Kopfband: Es ist der eine Augenblick, in dem
   das Spiel dem Spieler etwas feierlich sagt. */
#aufstiegsfeier { position: fixed; inset: 0; z-index: 960; }
.feier {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  cursor: var(--cursor-gold);
  --gold: #f3d27a;
  --gold-hell: #fff3c8;
  --gold-tief: #a8792a;
}
#aufstiegsfeier.geht .feier { animation: feier-geht 0.5s ease-in forwards; }
@keyframes feier-geht { to { opacity: 0; transform: scale(1.04); } }

.feier-grund {
  position: absolute;
  inset: 0;
  /* Dunkel und WEICH: Die Burg und die Tafeln dahinter sollen nur noch
     ahnbar sein, sonst liest man die Feier über einem Fenster voller Schrift. */
  background: radial-gradient(ellipse at center, rgba(34, 24, 9, 0.86) 0%, rgba(8, 7, 6, 0.95) 55%, rgba(0, 0, 0, 0.98) 100%);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  animation: feier-einblenden 0.6s ease-out both;
}
@keyframes feier-einblenden { from { opacity: 0; } }

/* DIE STRAHLEN: ein Kegelverlauf aus Licht und Lücke, radial ausgeblendet,
   drehend. Zwei Lagen gegeneinander geben das Flirren. */
.feier-strahlen,
.feier-strahlen::after {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 150vmax;
  height: 150vmax;
  margin: -75vmax 0 0 -75vmax;
  border-radius: 50%;
  background: repeating-conic-gradient(from 0deg, rgba(243, 210, 122, 0.2) 0deg 5deg, rgba(243, 210, 122, 0) 5deg 15deg);
  /* Ausgeblendet in FESTEN Längen um die Mitte — in Prozent des Kreises
     (150vmax) reichten die Strahlen bis an den Bildrand. */
  -webkit-mask: radial-gradient(circle closest-side, #000 0, rgba(0, 0, 0, 0.55) 14vmin, transparent 46vmin);
  mask: radial-gradient(circle closest-side, #000 0, rgba(0, 0, 0, 0.55) 14vmin, transparent 46vmin);
  animation: feier-strahlen-auf 1.1s cubic-bezier(0.2, 0.8, 0.2, 1) both, feier-drehen 40s linear infinite;
}
.feier-strahlen::after {
  content: "";
  left: 0;
  top: 0;
  margin: 0;
  background: repeating-conic-gradient(from 7deg, rgba(255, 243, 200, 0.12) 0deg 2deg, rgba(255, 243, 200, 0) 2deg 11deg);
  animation: feier-drehen 26s linear infinite reverse;
}
@keyframes feier-strahlen-auf { from { opacity: 0; transform: scale(0.3) rotate(-30deg); } }
@keyframes feier-drehen { to { rotate: 360deg; } }

/* DER LICHTRING — einmal, von innen nach außen. */
.feier-ring {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 40vmin;
  height: 40vmin;
  margin: -20vmin 0 0 -20vmin;
  border-radius: 50%;
  border: 3px solid var(--gold-hell);
  box-shadow: 0 0 40px 10px rgba(243, 210, 122, 0.6), inset 0 0 30px rgba(243, 210, 122, 0.5);
  opacity: 0;
  animation: feier-ring 1.3s cubic-bezier(0.1, 0.7, 0.3, 1) 0.15s both;
}
@keyframes feier-ring {
  0% { opacity: 0.95; transform: scale(0.15); }
  100% { opacity: 0; transform: scale(3.2); }
}

/* DIE FUNKEN — jeder mit eigener Richtung (--dx, --dy), Verzug und Größe
   (aufstiegsfeier.ts). Sie fliegen hinaus, sinken ein wenig und verglimmen. */
.feier-funken { position: absolute; left: 50%; top: 45%; width: 0; height: 0; }
.feier-funken i {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--groesse);
  height: var(--groesse);
  margin: calc(var(--groesse) / -2) 0 0 calc(var(--groesse) / -2);
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, var(--gold) 45%, rgba(243, 210, 122, 0) 72%);
  opacity: 0;
  animation: feier-funke 1.9s cubic-bezier(0.15, 0.7, 0.35, 1) var(--verzug) both;
}
@keyframes feier-funke {
  0% { opacity: 1; transform: translate(0, 0) scale(1.4); }
  70% { opacity: 0.9; }
  100% { opacity: 0; transform: translate(var(--dx), calc(var(--dy) + 6vmin)) scale(0.3); }
}

.feier-mitte {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: min(46rem, 90vw);
  text-align: center;
}
.feier-kicker {
  margin: 0 0 1.2rem;
  font-size: 0.95rem;
  letter-spacing: 0.5em;
  text-transform: uppercase;
  color: var(--gold);
  text-shadow: 0 0 12px rgba(243, 210, 122, 0.6);
  animation: feier-steigen 0.7s ease-out 0.7s both;
}

/* DAS EMBLEM fällt aus der Tiefe ein und federt nach. */
.feier-emblem {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: feier-einfallen 0.95s cubic-bezier(0.18, 1.35, 0.4, 1) 0.2s both;
}
@keyframes feier-einfallen {
  0% { opacity: 0; transform: scale(2.6); filter: blur(8px) brightness(2); }
  55% { opacity: 1; filter: blur(0) brightness(1.4); }
  100% { opacity: 1; transform: scale(1); filter: blur(0) brightness(1); }
}
.feier-medaille {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: clamp(8rem, 22vmin, 12rem);
  height: clamp(8rem, 22vmin, 12rem);
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #3a2c16 0%, #16110a 70%);
  border: 4px solid var(--gold-tief);
  box-shadow:
    0 0 0 3px #2a1f0e,
    0 0 0 6px var(--gold),
    0 0 40px 8px rgba(243, 210, 122, 0.55),
    inset 0 0 22px rgba(0, 0, 0, 0.8);
  animation: feier-leuchten 2.6s ease-in-out 1.2s infinite;
}
@keyframes feier-leuchten {
  50% {
    box-shadow:
      0 0 0 3px #2a1f0e,
      0 0 0 6px var(--gold-hell),
      0 0 70px 18px rgba(243, 210, 122, 0.75),
      inset 0 0 22px rgba(0, 0, 0, 0.8);
  }
}
/* Die Zahl steht als vermessener SVG-Text in der Medaille (aufstiegsfeier.ts,
   zahlText und ziffernMittig) — genau mittig, auch in der Bruchschrift. */
.feier-zahlbild { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.7)); }
.feier-zahl { font-family: var(--font-display); }
.feier-krone {
  display: block;
  width: clamp(4.5rem, 12vmin, 7rem);
  margin-bottom: 0.55rem;
  z-index: 1;
  filter: drop-shadow(0 0 10px rgba(243, 210, 122, 0.8));
  animation: feier-krone 1.1s cubic-bezier(0.2, 1.4, 0.4, 1) 0.55s both;
}
.feier-krone svg { display: block; width: 100%; height: auto; overflow: visible; fill: var(--gold); stroke: var(--gold-tief); stroke-width: 1.2; }
@keyframes feier-krone { from { opacity: 0; transform: translateY(-5rem) rotate(-8deg); } }
.feier-schild {
  display: block;
  height: clamp(9rem, 26vmin, 14rem);
  width: auto;
  aspect-ratio: 100 / 118;
  overflow: visible;
  filter: drop-shadow(0 0 24px rgba(243, 210, 122, 0.6)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.8));
}

/* DER TITEL in Gold, mit einem Glanz, der einmal darüber läuft. */
.feier-titel {
  position: relative;
  margin: 1.1rem 0 0.4rem;
  font-family: var(--font-display);
  font-size: clamp(2.8rem, 8vmin, 4.8rem);
  font-weight: normal;
  line-height: 1.05;
  /* MASSIVES GOLD mit Leuchten — ein Verlauf mit `background-clip: text` stand
     unter dem Schatten stumpf und grau da. Der Glanz ist ein einmaliges
     Aufstrahlen, danach bleibt ein ruhiges Leuchten. */
  color: var(--gold);
  text-shadow: 0 0 18px rgba(243, 210, 122, 0.5), 0 3px 4px rgba(0, 0, 0, 0.9);
  animation: feier-steigen 0.8s ease-out 0.75s both, feier-glanz 1.6s ease-out 1.2s both;
}
@keyframes feier-glanz {
  0% { color: var(--gold); }
  30% { color: #fffbe8; text-shadow: 0 0 34px rgba(255, 243, 200, 0.95), 0 0 70px rgba(243, 210, 122, 0.6), 0 3px 4px rgba(0, 0, 0, 0.9); }
  100% { color: var(--gold); }
}
@keyframes feier-steigen { from { opacity: 0; transform: translateY(1.2rem); } }
.feier-satz {
  margin: 0.2rem 0 0;
  font-size: 1.2rem;
  font-style: italic;
  color: #eadbb8;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.9);
  animation: feier-steigen 0.8s ease-out 1.1s both;
}
.feier-zusatz {
  margin: 0.8rem 0 0;
  padding: 0.35rem 1rem;
  font-size: 1rem;
  color: var(--gold-hell);
  border-top: 1px solid rgba(243, 210, 122, 0.4);
  border-bottom: 1px solid rgba(243, 210, 122, 0.4);
  animation: feier-steigen 0.8s ease-out 1.4s both;
}
.feier-weiter {
  margin: 2rem 0 0;
  font-size: 0.8rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(234, 219, 184, 0.6);
  animation: feier-einblenden 0.8s ease-out 2.2s both, feier-atmen 2.4s ease-in-out 3s infinite;
}
@keyframes feier-atmen { 50% { opacity: 0.35; } }

@media (prefers-reduced-motion: reduce) {
  .feier *,
  .feier *::after { animation-duration: 0.01s !important; animation-iteration-count: 1 !important; }
  .feier-funken, .feier-ring { display: none; }
}

/* --- DIE FEINE FEIER (28.09.2026, Fassung „fein" — die Vorgabe) ----------------
   Ansage des Bro: „der effekt bei stufen aufstieg ist schon super der erste mit
   dem aufblenden. das problem was mich stört, es sieht nicht elegant aus. es
   sieht eher aus wie von einem spiel casino … es dezenter machen vllt kleiner und
   nicht den bildschirm verdunkeln … feiner sinnlicher und schöner"
   (client/src/iso3d/aufstiegsfeier.ts, feierHtml „fein").

   WAS DAS CASINO WAR, UND WAS AN SEINE STELLE TRITT:
     der ganze Schirm dunkel      → nur ein weicher Schatten hinter der Schrift
     drehende Strahlen, Funken    → ein Goldring, der sich selbst zeichnet, und
                                    EIN Lichtschimmer, der einmal darübergleitet
     das Emblem knallt ins Bild   → es wird aus der Unschärfe scharf
     groß und laut                → klein, fein gesperrte Schrift, zwei zarte
                                    Goldlinien wie ein Zierstrich im Buch
     „Klicken, um fortzufahren"   → sie blendet von selbst aus; das Spiel läuft
                                    weiter, nur ihre Mitte nimmt einen Klick an
   Alle Zeiten sind langsam und weich (0,9–1,6 s, ausschwingende Kurven) — das
   ist der ganze Unterschied zwischen „feierlich" und „Gewinn!".

   Der Ablauf in Sekunden: 0,1 Emblem wird scharf · 0,25 der Ring zeichnet sich
   · 0,7 die Linien wachsen · 0,9 die Zahl · 1,0 „AUFSTIEG" zieht sich zusammen
   · 1,2 der Titel · 1,5 der Schimmer · 1,55 der Satz · ab 0,6 schwebt Staub ·
   nach 7 s blendet alles aus. */
#aufstiegsfeier[data-stil="fein"] { pointer-events: none; }
.feier-stil-fein {
  pointer-events: none;
  cursor: var(--cursor-kupfer, default);
  align-items: flex-start;
  padding-top: 19vh;
  overflow: visible;
}
.fein-mitte {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  align-items: center;
  max-width: min(34rem, 90vw);
  padding: 0.4rem 1rem 0.8rem;
  text-align: center;
  pointer-events: auto;
  cursor: var(--cursor-gold);
}
/* Der weiche Schatten hinter der Schrift — kein Kasten und kein Abdunkeln des
   Schirms: ein Oval, das nach außen ins Nichts ausläuft. */
.fein-halo {
  position: absolute;
  inset: -4.5rem -9rem -3.2rem;
  z-index: -1;
  background: radial-gradient(ellipse closest-side, rgba(14, 10, 6, 0.6), rgba(14, 10, 6, 0.36) 48%, rgba(14, 10, 6, 0) 100%);
  animation: fein-einblenden 1.4s ease-out both;
}
@keyframes fein-einblenden { from { opacity: 0; } }

.fein-zeile { display: flex; align-items: center; gap: 1rem; }
/* Die zwei Goldlinien wachsen von der Medaille nach außen, am inneren Ende
   eine kleine Raute. */
.fein-linie {
  position: relative;
  display: block;
  width: clamp(3.5rem, 10vw, 7.5rem);
  height: 1px;
  background: linear-gradient(90deg, rgba(243, 210, 122, 0), rgba(243, 210, 122, 0.85));
  transform-origin: right center;
  transform: scaleX(0);
  animation: fein-linie 1.4s cubic-bezier(0.3, 0.7, 0.2, 1) 0.7s forwards;
}
.fein-linie.rechts {
  background: linear-gradient(90deg, rgba(243, 210, 122, 0.85), rgba(243, 210, 122, 0));
  transform-origin: left center;
}
.fein-linie::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 5px;
  height: 5px;
  background: #f3d27a;
  transform: translateY(-50%) rotate(45deg);
}
.fein-linie.links::after { right: -3px; }
.fein-linie.rechts::after { left: -3px; }
@keyframes fein-linie { to { transform: scaleX(1); } }

/* Das Emblem wird aus der Unschärfe scharf — ein Blick, der sich einstellt. */
.fein-emblem {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  animation: fein-fokus 1.5s cubic-bezier(0.2, 0.7, 0.2, 1) 0.1s both;
}
@keyframes fein-fokus {
  0% { opacity: 0; transform: scale(0.88); filter: blur(10px); }
  60% { opacity: 1; }
  100% { opacity: 1; transform: scale(1); filter: blur(0); }
}
/* Ein warmes Licht hinter der Medaille, das einmal aufgeht und dann sacht atmet. */
.fein-glanz {
  position: absolute;
  left: 50%;
  top: 50%;
  z-index: -1;
  width: 10rem;
  height: 10rem;
  margin: -5rem 0 0 -5rem;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(243, 210, 122, 0.4), rgba(243, 210, 122, 0.12) 45%, rgba(243, 210, 122, 0) 70%);
  animation: fein-glanz-auf 1.6s ease-out 0.3s both, fein-atmen 4.5s ease-in-out 1.9s infinite alternate;
}
@keyframes fein-glanz-auf { from { opacity: 0; transform: scale(0.6); } }
@keyframes fein-atmen { to { opacity: 0.6; transform: scale(0.94); } }
.fein-medaille {
  display: block;
  width: clamp(4.8rem, 10.5vmin, 6.2rem);
  height: auto;
  overflow: visible;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.6));
}
/* Der Ring zeichnet sich selbst, von oben im Uhrzeigersinn (pathLength 1).
   RUNDE ENDEN, und das ist keine Zier: Mit geraden stießen Anfang und Ende
   oben genau aneinander, und dort blieb eine feine Naht stehen (in der
   Nahaufnahme gemessen). Rund überlappen sie sich; beim Zeichnen sieht das
   Ende aus wie eine Feder. Bis der Strich ansetzt, ist der Ring unsichtbar —
   sonst stünde oben schon ein Punkt. */
.fein-ring {
  fill: none;
  stroke-linecap: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  opacity: 0;
  transform: rotate(-90deg);
  transform-origin: 60px 60px;
  animation: fein-zeichnen 1.6s cubic-bezier(0.45, 0.05, 0.25, 1) 0.25s both;
}
.fein-ring.innen { animation-duration: 1.4s; animation-delay: 0.55s; }
@keyframes fein-zeichnen {
  0% { opacity: 0; }
  4% { opacity: 1; }
  100% { opacity: 1; stroke-dashoffset: 0; }
}
.fein-zahl {
  font-family: var(--font-display);
  opacity: 0;
  animation: fein-sichtbar 1s ease-out 0.9s forwards;
}
@keyframes fein-sichtbar { to { opacity: 1; } }
/* Der Lichtschimmer gleitet einmal über die Medaille. */
.fein-schimmer {
  transform: translateX(-60px);
  animation: fein-schimmer 1.7s ease-in-out 1.5s forwards;
}
@keyframes fein-schimmer { to { transform: translateX(200px); } }
/* Beim Titel: die Krone senkt sich sacht herab und bleibt LEICHT ÜBER dem
   Wappen stehen, mit einem schmalen Abstand (Ansage des Bro, 28.09.2026: „sie
   soll leicht über dem wappen schild stehen"). Die Lilienkrone aus krone.ts
   bringt ihr Gold selbst mit — ein `fill` hier gälte nicht, ein `stroke` zöge
   um jedes Teil eine Kontur. */
.fein-krone {
  display: block;
  width: clamp(2.8rem, 6vmin, 3.6rem);
  margin-bottom: 0.45rem;
  filter: drop-shadow(0 0 8px rgba(243, 210, 122, 0.55));
  animation: fein-krone 1.4s cubic-bezier(0.2, 0.7, 0.2, 1) 0.6s both;
}
.fein-krone svg { display: block; width: 100%; height: auto; overflow: visible; fill: #f3d27a; }
@keyframes fein-krone { from { opacity: 0; transform: translateY(-1.2rem); } }
.feier-schild.fein {
  height: clamp(5.6rem, 12vmin, 7rem);
  width: auto;
  aspect-ratio: 100 / 118;
  overflow: visible;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.6));
}

/* Die Schrift: klein, fein gesperrt, und jede Zeile taucht einzeln auf. */
.feier-stil-fein .feier-kicker {
  margin: 1rem 0 0.1rem;
  padding-left: 0.55em;
  font-size: 0.72rem;
  letter-spacing: 0.55em;
  color: #e9c46a;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  animation: fein-sperren 1.7s cubic-bezier(0.2, 0.7, 0.2, 1) 1s both;
}
@keyframes fein-sperren { from { opacity: 0; letter-spacing: 1.1em; } }
.feier-stil-fein .feier-titel {
  margin: 0.1rem 0 0.3rem;
  font-size: clamp(1.9rem, 4.4vmin, 2.5rem);
  color: #f3d27a;
  text-shadow: 0 0 16px rgba(0, 0, 0, 0.5), 0 2px 3px rgba(0, 0, 0, 0.9);
  animation: fein-auftauchen 1.3s cubic-bezier(0.2, 0.7, 0.2, 1) 1.2s both;
}
.feier-stil-fein .feier-satz {
  margin: 0;
  font-size: 1rem;
  color: #eadbb8;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.95);
  animation: fein-auftauchen 1.3s cubic-bezier(0.2, 0.7, 0.2, 1) 1.55s both;
}
.feier-stil-fein .feier-zusatz {
  margin: 0.7rem 0 0;
  padding: 0.25rem 1.1rem;
  font-size: 0.88rem;
  color: #fff3c8;
  border: none;
  background: linear-gradient(90deg, rgba(243, 210, 122, 0), rgba(243, 210, 122, 0.14), rgba(243, 210, 122, 0));
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  animation: fein-auftauchen 1.3s cubic-bezier(0.2, 0.7, 0.2, 1) 1.9s both;
}
@keyframes fein-auftauchen { from { opacity: 0; transform: translateY(0.5rem); filter: blur(4px); } }

/* Goldstaub, der langsam aufsteigt, schwankt und verglimmt — immer wieder,
   solange die Feier steht. Jedes Körnchen trägt seine Bahn (aufstiegsfeier.ts). */
.fein-staub { position: absolute; left: 50%; top: 3.2rem; z-index: 1; width: 0; height: 0; }
.fein-staub i {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--groesse);
  height: var(--groesse);
  border-radius: 50%;
  background: #fff3c8;
  box-shadow: 0 0 6px 1px rgba(243, 210, 122, 0.75);
  opacity: 0;
  animation: fein-schweben var(--dauer) ease-in-out var(--verzug) infinite;
}
@keyframes fein-schweben {
  0% { opacity: 0; transform: translate(0, 0); }
  20% { opacity: 0.85; }
  50% { transform: translate(var(--wiege), calc(var(--steig) * -0.5)); }
  80% { opacity: 0.5; }
  100% { opacity: 0; transform: translate(calc(var(--wiege) * -0.4), calc(var(--steig) * -1)); }
}

/* Das Ausblenden — sacht nach oben, leicht unscharf. */
#aufstiegsfeier.geht .feier-stil-fein { animation: fein-geht 0.9s ease-in forwards; }
@keyframes fein-geht { to { opacity: 0; transform: translateY(-0.8rem); filter: blur(4px); } }

@media (prefers-reduced-motion: reduce) {
  .feier-stil-fein *,
  .feier-stil-fein *::after { animation-duration: 0.01s !important; animation-iteration-count: 1 !important; animation-delay: 0s !important; }
  .fein-staub { display: none; }
}

/* --- DIE URKUNDE (28.09.2026, Fassung „urkunde" der Aufstiegsfeier) -----------
   Eine Pergamentrolle entrollt sich von der Mitte aus (die Stäbe fahren
   auseinander, das Blatt wird mit `clip-path` aufgedeckt), die Schrift
   erscheint wie geschrieben (links nach rechts), zum Schluss knallt ein rotes
   Wachssiegel darauf — mit einem Ruck durch die ganze Rolle und etwas Staub. */
.feier-stil-urkunde .feier-rolle {
  position: relative;
  width: min(36rem, 86vw);
  animation: feier-ruck 0.35s ease-out 2.35s both;
}
@keyframes feier-ruck {
  0% { transform: translateY(0); }
  30% { transform: translateY(5px) scale(0.995); }
  100% { transform: translateY(0); }
}
.feier-stil-urkunde .feier-pergament {
  position: relative;
  padding: 2.4rem 2.6rem 3.4rem;
  text-align: center;
  color: #3a2819;
  background:
    radial-gradient(ellipse at 50% 40%, rgba(255, 250, 235, 0.55), transparent 70%),
    radial-gradient(ellipse at 20% 80%, rgba(140, 95, 40, 0.22), transparent 55%),
    radial-gradient(ellipse at 85% 15%, rgba(140, 95, 40, 0.18), transparent 50%),
    linear-gradient(180deg, #e9d9b4, #dcc596);
  box-shadow: inset 0 0 40px rgba(110, 70, 25, 0.45), 0 18px 50px rgba(0, 0, 0, 0.7);
  clip-path: inset(50% 0 50% 0);
  animation: feier-entrollen 0.95s cubic-bezier(0.3, 0.8, 0.3, 1) 0.2s forwards;
}
@keyframes feier-entrollen { to { clip-path: inset(0 0 0 0); } }
/* Die zwei Stäbe: Holz mit Messingknäufen, sie fahren von der Mitte auseinander. */
.feier-stil-urkunde .feier-stab {
  position: absolute;
  left: -1.4rem;
  right: -1.4rem;
  z-index: 2;
  height: 1.3rem;
  border-radius: 0.65rem;
  background:
    radial-gradient(circle at 0.65rem 50%, #f3d27a 0 0.45rem, transparent 0.5rem),
    radial-gradient(circle at calc(100% - 0.65rem) 50%, #f3d27a 0 0.45rem, transparent 0.5rem),
    linear-gradient(180deg, #7a4f2a, #4a2c14 60%, #2e1a0b);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.6);
  top: calc(50% - 0.65rem);
  animation: feier-stab-oben 0.95s cubic-bezier(0.3, 0.8, 0.3, 1) 0.2s forwards;
}
.feier-stil-urkunde .feier-stab.unten { animation-name: feier-stab-unten; }
@keyframes feier-stab-oben { to { top: -0.65rem; } }
@keyframes feier-stab-unten { to { top: calc(100% - 0.65rem); } }
/* Die Schrift: in Tinte, und sie wird von links nach rechts „geschrieben". */
.feier-stil-urkunde .feier-kicker {
  color: #8a2e1c;
  text-shadow: none;
  animation: feier-schreiben 0.6s steps(18, end) 1s both;
}
.feier-stil-urkunde .feier-titel {
  margin: 0.3rem 0 0.5rem;
  color: #6e2415;
  text-shadow: 0 1px 0 rgba(255, 245, 220, 0.6);
  animation: feier-schreiben 0.9s steps(24, end) 1.25s both;
}
.feier-stil-urkunde .feier-satz { color: #3a2819; text-shadow: none; animation: feier-schreiben 0.9s steps(40, end) 1.7s both; }
.feier-stil-urkunde .feier-zusatz {
  color: #3a2819;
  border-color: rgba(110, 36, 21, 0.35);
  animation: feier-schreiben 0.8s steps(40, end) 2s both;
}
@keyframes feier-schreiben {
  from { clip-path: inset(0 100% 0 0); }
  to { clip-path: inset(0 0 0 0); }
}
.feier-urkundenkopf { display: flex; justify-content: center; margin: -0.6rem 0 0.4rem; animation: feier-einblenden 0.6s ease-out 1.05s both; }
.feier-schild.klein { height: 4.2rem; width: auto; aspect-ratio: 100 / 118; overflow: visible; filter: drop-shadow(0 2px 3px rgba(60, 30, 10, 0.5)); }
/* DAS SIEGEL knallt aus der Luft auf das Blatt. */
.feier-siegel {
  position: absolute;
  right: 2.6rem;
  bottom: -2.1rem;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 5.4rem;
  height: 5.4rem;
  border-radius: 47% 53% 50% 48% / 52% 46% 54% 48%;
  background: radial-gradient(circle at 38% 32%, #d24a3a 0%, #a11f16 45%, #6d0f0a 100%);
  box-shadow: inset 0 0 0 5px rgba(90, 10, 5, 0.55), inset 0 0 12px rgba(0, 0, 0, 0.5), 0 6px 12px rgba(0, 0, 0, 0.55);
  animation: feier-stempeln 0.42s cubic-bezier(0.5, 0, 0.75, 0) 2.2s both;
}
@keyframes feier-stempeln {
  0% { opacity: 0; transform: scale(3.2) rotate(-25deg); }
  70% { opacity: 1; }
  100% { opacity: 1; transform: scale(1) rotate(-8deg); }
}
.feier-siegelzahl {
  font-family: var(--font-display);
  font-size: 2.3rem;
  line-height: 1;
  color: #5a0c07;
  text-shadow: 0 1px 0 rgba(255, 140, 120, 0.45), 0 -1px 0 rgba(0, 0, 0, 0.4);
}
.feier-siegelkrone { display: block; width: 3rem; }
.feier-siegelkrone svg { display: block; width: 100%; fill: #5a0c07; filter: drop-shadow(0 1px 0 rgba(255, 140, 120, 0.45)); }
/* Staub, wo das Siegel aufschlägt. */
.feier-siegelstaub {
  position: absolute;
  inset: -0.8rem;
  border-radius: 50%;
  border: 2px solid rgba(235, 215, 170, 0.8);
  opacity: 0;
  animation: feier-staub 0.6s ease-out 2.58s both;
}
@keyframes feier-staub {
  0% { opacity: 0.9; transform: scale(0.6); }
  100% { opacity: 0; transform: scale(1.9); }
}
.feier-stil-urkunde .feier-weiter { margin-top: 2.8rem; }

/* --- DAS BANNER (Fassung „banner") --------------------------------------------
   Ein Wappenbanner fällt von oben herein, federt und schwingt dann sacht an
   seiner Stange; Gold rieselt wie Konfetti. */
.feier-stil-banner .feier-mitte { padding-top: 0; }
.feier-fahne {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 0.2rem 0 0.4rem;
  transform-origin: 50% 0;
  animation:
    feier-fahne-fallen 1.05s cubic-bezier(0.25, 1.5, 0.45, 1) 0.15s both,
    feier-fahne-schwingen 4.2s ease-in-out 1.2s infinite;
}
@keyframes feier-fahne-fallen { from { transform: translateY(-110vh); } }
@keyframes feier-fahne-schwingen {
  0%, 100% { transform: rotate(0deg); }
  25% { transform: rotate(1.6deg); }
  75% { transform: rotate(-1.6deg); }
}
.feier-stange {
  position: relative;
  z-index: 1;
  width: clamp(12rem, 30vmin, 17rem);
  height: 0.8rem;
  border-radius: 0.4rem;
  background:
    radial-gradient(circle at 0.4rem 50%, #fff3c8 0 0.45rem, transparent 0.5rem),
    radial-gradient(circle at calc(100% - 0.4rem) 50%, #fff3c8 0 0.45rem, transparent 0.5rem),
    linear-gradient(180deg, #f3d27a, #a8792a);
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.6);
}
.feier-tuch {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 0.4rem;
  width: clamp(9.5rem, 24vmin, 13.5rem);
  height: clamp(14rem, 36vmin, 20rem);
  margin-top: -0.2rem;
  padding-top: 1.6rem;
  background:
    linear-gradient(90deg, rgba(0, 0, 0, 0.28), transparent 18%, transparent 82%, rgba(0, 0, 0, 0.28)),
    linear-gradient(180deg, #8f1d18, #6a120e);
  box-shadow: inset 0 0 0 4px #f3d27a, inset 0 0 0 7px #6a120e, inset 0 0 0 9px rgba(243, 210, 122, 0.6), 0 16px 40px rgba(0, 0, 0, 0.7);
  /* Unten ein Schwalbenschwanz. */
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 84%, 0 100%);
}
.feier-tuchzahl {
  margin-top: 1.2rem;
  font-family: var(--font-display);
  font-size: clamp(4rem, 12vmin, 6.5rem);
  line-height: 1;
  color: #f3d27a;
  text-shadow: 0 0 16px rgba(243, 210, 122, 0.55), 0 3px 3px rgba(0, 0, 0, 0.7);
}
.feier-tuchkrone { display: block; width: 3.6rem; }
.feier-tuchkrone svg { display: block; width: 100%; height: auto; overflow: visible; fill: #f3d27a; filter: drop-shadow(0 0 6px rgba(243, 210, 122, 0.6)); }
.feier-schild.tuch { height: 60%; width: auto; aspect-ratio: 100 / 118; overflow: visible; filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.6)); }
.feier-stil-banner .feier-kicker { margin-bottom: 0.4rem; animation-delay: 0.9s; }
.feier-stil-banner .feier-titel { margin-top: 0.6rem; animation-delay: 1.05s; }
/* Das Gold rieselt von oben. */
.feier-regen { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.feier-regen i {
  position: absolute;
  top: -4vh;
  left: calc(50% + var(--x));
  width: var(--groesse);
  height: calc(var(--groesse) * 0.55);
  background: linear-gradient(90deg, #a8792a, #fff3c8, #f3d27a);
  border-radius: 1px;
  opacity: 0;
  animation: feier-rieseln var(--dauer) linear var(--verzug) both;
}
@keyframes feier-rieseln {
  0% { opacity: 0; transform: translateY(0) rotate(0deg); }
  10% { opacity: 1; }
  85% { opacity: 1; }
  100% { opacity: 0; transform: translateY(108vh) rotate(var(--dreh)); }
}
@media (prefers-reduced-motion: reduce) {
  .feier-stil-urkunde .feier-pergament { clip-path: none; }
  .feier-regen { display: none; }
}

/* --- DAS BUCH (28.09.2026) ----------------------------------------------------
   Ansage des Bro: „können wir es stattdessen als einziges objekt wie einem buch
   layouten. wir können ja eine vorlage bei nanobanana würfeln eines leerens
   buches und dann wird die zeichnung da rein dann der text".

   EIN aufgeschlagenes Buch für die Wissenstafel UND den Codex der Mark: Das
   Bild (client/public/wissen/buch.webp, übernommen mit
   scripts/build-codexbuch.js aus einem Wurf in assets/codexbuch) IST die Tafel
   — kein Kasten, kein Rahmen darum. Links steht Bild und Titel, rechts der
   Text; im Codex links das Inhaltsverzeichnis, rechts die Seiten des Kapitels.

   DIE SEITEN SIND PROZENT DES BILDES, gemessen am freigestellten Wurf „leder-2-magenta-2-pro4k-1" (Nano Banana Pro, 4K, auf 3500 Bildpunkte gebracht)
   (Gitter über das Bild gelegt, Pergament links x 10–48,5 %, rechts
   50,5–90 %, y 3–90 %). Die Satzspiegel liegen mit Rand und Abstand zum Falz
   darin. **Wer einen anderen Wurf übernimmt, misst hier neu.**

   DIE SCHRIFT WÄCHST MIT DEM BUCH (`cqw`): Das Buch nimmt so viel vom Schirm,
   wie da ist, und ein fester Schriftgrad stünde auf einem großen Schirm
   verloren und liefe auf einem kleinen über. `cqw` misst am nächsten
   Container-VORFAHREN, darum ist `.buch` der Container und die Seiten lesen es.

   TINTE AUF PERGAMENT: Die Schrift ist dunkles Braun, Überschriften und die
   Marke stehen in Rubrikenrot — so hat man im 12. Jahrhundert ausgezeichnet. */
.buch {
  position: relative;
  container-type: inline-size;
  /* Das Kopfband bleibt frei (rund 6,5rem mit Luft): Das Buch liegt über der
     Burg, nicht über der Leiste. */
  width: min(94vw, calc((100vh - 6.5rem) * 1.761), 92rem);
  aspect-ratio: 3500 / 1987;
  background: url("/bilder/wissen/buch.webp") center / 100% 100% no-repeat;
  filter: drop-shadow(0 14px 34px rgba(0, 0, 0, 0.75));
  color: #3a2819;
  --tinte: #3a2819;
  --tinte-blass: #6b5238;
  --rubrik: #8a2e1c;
}
.buch-seite {
  position: absolute;
  top: 8.5%;
  bottom: 11%;
  display: flex;
  flex-direction: column;
  min-height: 0;
  font-family: var(--font-body);
  font-size: clamp(12px, 1.2cqw, 20px);
  line-height: 1.45;
}
.buch-seite > * { flex: none; }
.buch-seite.links { left: 14%; right: 55%; }
.buch-seite.rechts { left: 54.5%; right: 14%; }

/* DAS KREUZ sitzt auf dem Einband oben rechts, nicht auf der Seite — dort ist
   es der Ausgang und nicht ein Teil des Textes. */
.buch-zu {
  position: absolute;
  top: 1.2%;
  right: 1.4%;
  z-index: 2;
  width: 2.6cqw;
  height: 2.6cqw;
  min-width: 1.9rem;
  min-height: 1.9rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font: inherit;
  font-size: max(1.3rem, 1.9cqw);
  line-height: 1;
  color: #e9dcc0;
  background: rgba(18, 13, 9, 0.72);
  border: 1px solid var(--brass-dark);
  border-radius: 50%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
  cursor: var(--cursor-gold);
}
.buch-zu:hover,
.buch-zu:focus-visible { color: var(--brass-light); border-color: var(--brass-light); outline: none; }

/* „Aus der Geschichte" — in Rubrikenrot und gesperrt, wie eine Kapitelmarke. */
.buch-marke {
  margin: 0 0 0.7em;
  font-size: 0.74em;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--rubrik);
}
/* SEIT DEM 03.10.2026 STEHT DIE ZEICHNUNG DIREKT AUF DER SEITE: Tusche auf
   Weiß (scripts/build-tuschebilder.js), multipliziert — wie mit der Feder ins
   Buch gezeichnet (Ansage des Bro: „in unserem codex buch … drüberlegen mit
   multiplizieren"). Vorher eine eingeklebte farbige Miniatur mit Tintenlinie
   und Schatten; beides ist weg, die Zeichnung läuft von selbst ins Papier aus.
   Das geht, weil .buch mit seinem filter EINE Stapelgruppe ist, in der Seite
   und Bild liegen. */
.buch-bild {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 20 / 9;
  object-fit: contain;
  margin: 0 0 0.9em;
  mix-blend-mode: multiply;
}
.buch-seite h2 {
  margin: 0 0 0.15em;
  font-family: var(--font-display);
  font-size: 2.05em;
  font-weight: normal;
  line-height: 1.1;
  color: var(--rubrik);
}
.buch-unterzeile {
  margin: 0 0 0.6em;
  font-size: 1em;
  font-style: italic;
  color: var(--tinte-blass);
}
/* Der Sachtext — einspaltig auf seiner Seite. Nur er darf im Notfall
   scrollen (ein sehr niedriges Fenster); `min-height: 0` gehört dazu. */
.buch-text {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(58, 40, 25, 0.4) transparent;
}
.buch-text p {
  margin: 0 0 0.75em;
  font-size: 1.02em;
  text-align: justify;
  hyphens: auto;
  color: var(--tinte);
}
.buch-text p:last-child { margin-bottom: 0; }
/* Die Initiale des ersten Absatzes — rot und über zwei Zeilen. */
.buch-text p:first-child::first-letter {
  float: left;
  margin: 0.06em 0.08em 0 0;
  font-family: var(--font-display);
  font-size: 3.1em;
  line-height: 0.85;
  color: var(--rubrik);
}
/* Der Fuß einer Seite: Blättern, Seitenzahl, der Hinweis auf den Codex. */
.buch-fuss {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1em;
  margin-top: auto;
  padding-top: 0.7em;
  font-size: 0.86em;
  color: var(--tinte-blass);
}
.buch-fuss .rechtsbuendig { margin-left: auto; text-align: right; }
.buch-verweis { font-style: italic; }
/* Knöpfe auf der Seite sehen aus wie geschriebene Verweise. Der Haus-Stil gibt
   jedem Knopf Rahmen, Verlauf und `width: fit-content` — hier alles zurück. */
.buch-link {
  padding: 0;
  max-width: 48%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: none;
  border: none;
  box-shadow: none;
  font: inherit;
  letter-spacing: normal;
  color: var(--tinte-blass);
  cursor: var(--cursor-gold);
}
.buch-link:hover,
.buch-link:focus-visible { color: var(--rubrik); outline: none; text-decoration: underline; }
.buch-link span { font-family: var(--font-display); font-size: 1.12em; }

/* --- Die Wissenstafel als Buch ------------------------------------------------ */
.wissen-buch .buch-seite.links { justify-content: center; }

/* --- Der Codex der Mark (24.09.2026) -----------------------------------------
   Ansage des Bro: „informationstafeln zu besonderen gebäuden und andren sachen
   möchte ich sammeln in einem art buch, ähnlich wie die achievements … neben
   talentbaum als taste einbauen und dann sauber intergrieren und schön
   layouten." (server/public/codex.js)

   IN DER STANDESTAFEL stehen Talente und Codex als zwei gleich gebaute Felder
   nebeneinander; der Knopf sitzt jeweils am Fuß, damit beide auf einer Höhe
   stehen, auch wenn ein Text eine Zeile länger ist. */
.sp-werke {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.8rem;
  margin-top: 1.4rem;
}
.sp-werke .sp-talente {
  display: flex;
  flex-direction: column;
  margin-top: 0;
  padding: 0.75rem 0.85rem 0.8rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid rgba(204, 167, 94, 0.18);
  border-radius: 3px;
}
.sp-werke .sp-talente h3 { font-size: 1.05rem; }
.sp-werke .sp-talente .sp-rangtext { flex: 1 1 auto; font-size: 0.82rem; }
.sp-werke .sp-talentknopf { align-self: flex-start; margin-top: 0.55rem; }
.sp-codexneu { color: #f3d27a; font-style: normal; font-weight: bold; white-space: nowrap; }

/* DAS BUCH selbst (seit dem 28.09.2026 ein aufgeschlagenes Buch, `.buch` oben).
   Die Hülle ist weiter eine `.sp-tafel` — fenster.js schiebt sie, und Escape
   und der Klick daneben gelten von selbst —, trägt aber keinen Kasten mehr:
   Das Buch IST die Tafel. */
.sp-tafel.cx-tafel {
  width: auto;
  max-height: none;
  overflow: visible;
  padding: 0;
  background: none;
  border: none;
  box-shadow: none;
}

/* Der Rücksprung (Standestafel, Inhalt) steht oben auf der linken Seite. */
.cx-zurueck { align-self: flex-start; margin: 0 0 0.5em; font-size: 0.9em; }
/* Im Blatt stehen Miniatur und Titel in der Mitte der linken Seite. */
.cx-blattkopf { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: center; min-height: 0; }
.cx-seitenzahl { font-style: italic; white-space: nowrap; }

/* Die LINKE SEITE im Verzeichnis: Titel, Fortschritt, die Kapitel. */
.cx-kopf { display: flex; align-items: baseline; justify-content: space-between; gap: 0.6em; }
.cx-kopf h3 {
  margin: 0;
  font-family: var(--font-display);
  font-size: 2.1em;
  font-weight: normal;
  line-height: 1.1;
  color: var(--rubrik);
}
.cx-fortschritt { display: flex; align-items: center; gap: 0.6em; margin: 0.25em 0 0.9em; }
.cx-zaehler { font-size: 0.86em; color: var(--tinte-blass); white-space: nowrap; }
.cx-zaehler b { color: var(--tinte); }
.cx-balken {
  flex: 1 1 auto;
  height: 0.35em;
  background: rgba(58, 40, 25, 0.14);
  border: 1px solid rgba(58, 40, 25, 0.3);
  border-radius: 2px;
  overflow: hidden;
}
.cx-balken i { display: block; height: 100%; background: linear-gradient(90deg, #7a2a18, #a8452a); }
.cx-laedt { margin: auto; font-style: italic; color: var(--tinte-blass); }

/* DAS INHALTSVERZEICHNIS — eine Zeile je Kapitel, wie in einer Handschrift:
   römische Ziffer, Name, eine gepunktete Leitlinie, die Zahl der Seiten. */
.cx-inhalt { display: flex; flex-direction: column; gap: 0.1em; }
.cx-reiter {
  position: relative;
  display: grid;
  /* 3,2em trägt „VIII“ in der Zierschrift (gemessen 39 px bei 26 px Spalte). */
  grid-template-columns: 3.2em auto minmax(0.8em, 1fr) auto;
  align-items: baseline;
  gap: 0.35em;
  width: 100%;
  padding: 0.28em 0.35em;
  text-align: left;
  background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), transparent;
  border: none;
  --schein: transparent;
  border-radius: 0;
  box-shadow: none;
  letter-spacing: normal;
  font: inherit;
  color: var(--tinte);
  cursor: var(--cursor-gold);
}
.cx-reiter:hover { background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(58, 40, 25, 0.07); }
.cx-reiter.aktiv { background: linear-gradient(90deg, color-mix(in srgb, var(--schein) 22%, transparent), transparent 70%), rgba(138, 46, 28, 0.1); --schein: var(--rubrik); }
.cx-reiter:focus-visible { outline: 1px dotted var(--rubrik); outline-offset: -1px; }
.cx-reiternummer { font-family: var(--font-display); font-size: 1.05em; color: var(--rubrik); text-align: right; }
.cx-reitername {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 1.08em;
}
.cx-reiter.aktiv .cx-reitername { color: var(--rubrik); }
.cx-leitlinie { border-bottom: 1px dotted rgba(58, 40, 25, 0.45); transform: translateY(-0.25em); }
.cx-reiterzahl { font-size: 0.86em; font-variant-numeric: tabular-nums; color: var(--tinte-blass); }
/* Ein ganz aufgeschlagenes Kapitel bekommt seine Zahl in Rot. */
.cx-reiter.voll .cx-reiterzahl { color: var(--rubrik); }
/* Ein Punkt am Kapitel, wenn darin eine ungelesene Seite liegt. */
.cx-reiterneu {
  position: absolute;
  top: 50%;
  left: -0.55em;
  width: 0.42em;
  height: 0.42em;
  margin-top: -0.21em;
  border-radius: 50%;
  background: #b8862a;
  box-shadow: 0 0 5px rgba(184, 134, 42, 0.9);
}

/* Die RECHTE SEITE im Verzeichnis: das Kapitel und seine Seiten. */
.cx-kapiteltitel {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.75em;
  font-weight: normal;
  line-height: 1.1;
  color: var(--rubrik);
}
.cx-leitsatz { margin: 0.1em 0 0.8em; font-style: italic; color: var(--tinte-blass); }

/* DIE SEITEN ALS KLEINE MINIATUREN — zwei nebeneinander, das größte Kapitel
   hat sechs, also drei Reihen. Offen, neu (goldene Marke) oder versiegelt
   (grau und verschwommen, Ansage 24.09.2026). */
.cx-kacheln {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75em 1em;
}
.cx-kachel {
  display: flex;
  flex-direction: column;
  min-width: 0;
  width: 100%;
  padding: 0;
  text-align: left;
  background: none;
  border: none;
  border-radius: 0;
  box-shadow: none;
  letter-spacing: normal;
  font: inherit;
  color: inherit;
  cursor: var(--cursor-gold);
}
.cx-rahmen {
  position: relative;
  display: block;
  aspect-ratio: 20 / 9;
  overflow: hidden;
  background: rgba(58, 40, 25, 0.12);
  border: 1px solid rgba(58, 40, 25, 0.6);
  box-shadow: 0 1px 4px rgba(58, 40, 25, 0.3);
  transition: transform 0.15s ease-out, box-shadow 0.15s ease-out;
}
/* KEIN transform beim Überfahren (03.10.2026): Es machte den Rahmen zu einer
   eigenen Stapelgruppe, und die multiplizierte Zeichnung darin stünde dann
   als weißer Kasten da. Der Schatten allein zeigt, dass es hier weitergeht. */
.cx-kachel.offen:hover .cx-rahmen,
.cx-kachel.offen:focus-visible .cx-rahmen {
  box-shadow: 0 4px 10px rgba(58, 40, 25, 0.45);
}
.cx-kachel:focus-visible { outline: none; }
.cx-kachel.neu .cx-rahmen { border-color: #b8862a; box-shadow: 0 0 8px rgba(184, 134, 42, 0.6); }
.cx-kachel.zu { cursor: var(--cursor-kupfer); }
.cx-kachel.zu .cx-rahmen { border-color: rgba(58, 40, 25, 0.25); box-shadow: none; }
.cx-kachelbild { display: block; width: 100%; height: 100%; object-fit: cover; mix-blend-mode: multiply; }
.cx-ohnebild { background: repeating-linear-gradient(135deg, rgba(58, 40, 25, 0.08) 0 6px, transparent 6px 12px); }
.cx-kachel.zu .cx-kachelbild { filter: grayscale(1) sepia(0.3) brightness(0.8) contrast(0.7) blur(3px); opacity: 0.55; transform: scale(1.08); }
.cx-neu {
  position: absolute;
  top: 0.3em;
  left: 0.3em;
  padding: 0.05em 0.4em 0.08em;
  background: #f3d27a;
  color: #1c1508;
  font-size: 0.64em;
  font-weight: bold;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  border-radius: 2px;
  box-shadow: 0 0 6px rgba(243, 210, 122, 0.7);
}
.cx-kacheltitel {
  margin-top: 0.3em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: 1.12em;
  line-height: 1.15;
  color: var(--tinte);
}
.cx-kachel.offen:hover .cx-kacheltitel { color: var(--rubrik); }
.cx-kachelunter {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.8em;
  font-style: italic;
  color: var(--tinte-blass);
}
.cx-kachel.zu .cx-kacheltitel,
.cx-kachel.zu .cx-kachelunter { color: rgba(58, 40, 25, 0.45); }

@media (max-width: 44rem) {
  .sp-werke { grid-template-columns: 1fr; }
}

/* Die Rechtsverweise unter Anmeldung und Registrierung (rechtstexte.ts, 25.09.2026). */
.rechtslinks { margin: 1rem 0 0; font-size: 0.8rem; color: var(--text-dim); text-align: center; }
.rechtslinks a { color: var(--text-dim); }
.rechtslinks a:hover { color: var(--brass-light); }
.rechtsseite h2 { margin: 1.4rem 0 0.4rem; font-size: 1.15rem; color: var(--brass-light); }


/* DAS FRAGEZEICHEN IM KREIS (06.10.2026, client/src/infofrage.ts) — die
   einzige Erklärung, die die Oberfläche noch trägt, und nur, wo es wirklich
   kritisch ist (CLAUDE.md, „DIE OBERFLÄCHE ERKLÄRT NICHTS"). Es klappt ein
   Feld auf, es schwebt nicht — wie das Fragezeichen der Rangliste. */
.info-frage {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.3rem;
  height: 1.3rem;
  margin-left: 0.3rem;
  padding: 0;
  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;
  vertical-align: middle;
  cursor: var(--cursor-gold);
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.info-frage:hover,
.info-frage.offen {
  color: var(--brass-light);
  border-color: var(--brass-light);
  background: rgba(198, 160, 78, 0.12);
}
.info-feld {
  margin: 0.35rem 0 0.2rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--brass-dark);
  border-radius: 3px;
  background: rgba(0, 0, 0, 0.3);
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--text-dim);
}
.info-feld[hidden] { display: none; }

/* DER TAFELKOPF (16.10.2026, Ansage des Bro: „das ist jetzt vorlage für alle
   anderen fenster und tafeln immer ein icon dann die funktion und dann kreuz
   zum schließen"). Vorbild der Kopf der Einstellungen (Entwurf C): links das
   Zeichen des Knopfes, der die Tafel öffnet (scharfe Fassung @2x, 35 px),
   daneben der Name in der Titelschrift, rechts ein ECKIGES Kreuz als Knopf,
   darunter eine Messinglinie bis an die Ränder. Wie weit der Kopf über das
   Polster seiner Tafel greift, sagt die Tafel selbst (`margin`). Was sonst
   im Kopf steht (Fragezeichen, Zähler, Einfluss), steht zwischen Titel und
   Kreuz. */
.tafelkopf {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.5rem 0.5rem 0.75rem;
  border-bottom: 1px solid var(--brass-dark);
}
.tafelkopf__zeichen {
  width: 35px;
  height: 35px;
  flex: none;
  object-fit: contain;
}
.tafelkopf__titel {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--brass-light);
  font-size: 1.2rem;
  line-height: 1;
  text-align: left;
  letter-spacing: normal;
  text-transform: none;
}

/* DIE SCHLIESSKREUZE (14.10.2026 mit Messingring, seit 16.10.2026 das Kreuz
   des Tafelkopfs: eckig, Eisenrand, unter dem Zeiger Messing). Eine Regel
   für alle; die doppelte Klasse sticht die Einzelregeln (auch
   `.ortstafel .ort-zu`, und karte.css, das nach ui.css kommt), Lage und
   Abstand bleiben deren Sache. Ein neues Kreuz kommt hier hinein. */
button:is(.bp-zu.bp-zu, .gp-zu.gp-zu, .ht-zu.ht-zu, .wt-zu.wt-zu, .sp-zu.sp-zu, .ct-klapp.ct-klapp, .rl-zu.rl-zu, .tt-zu.tt-zu, .ort-zu.ort-zu, .af-zu.af-zu, .burgtafel-zu.burgtafel-zu, .sst-zu.sst-zu, .tafelkopf__zu.tafelkopf__zu) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 1.75rem;
  height: 1.75rem;
  padding: 0;
  background: #121417;
  border: 1px solid var(--iron);
  border-radius: 0;
  box-shadow: none;
  color: var(--text-dim);
  font: inherit;
  font-size: 1.2rem;
  font-weight: 400;
  line-height: 1;
  cursor: var(--cursor-gold);
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
button:is(.bp-zu.bp-zu, .gp-zu.gp-zu, .ht-zu.ht-zu, .wt-zu.wt-zu, .sp-zu.sp-zu, .ct-klapp.ct-klapp, .rl-zu.rl-zu, .tt-zu.tt-zu, .ort-zu.ort-zu, .af-zu.af-zu, .burgtafel-zu.burgtafel-zu, .sst-zu.sst-zu, .tafelkopf__zu.tafelkopf__zu):hover {
  border-color: var(--brass-light);
  background: rgba(168, 129, 61, 0.2);
  color: #f0dfb4;
}
button:is(.bp-zu.bp-zu, .gp-zu.gp-zu, .ht-zu.ht-zu, .wt-zu.wt-zu, .sp-zu.sp-zu, .ct-klapp.ct-klapp, .rl-zu.rl-zu, .tt-zu.tt-zu, .ort-zu.ort-zu, .af-zu.af-zu, .burgtafel-zu.burgtafel-zu, .sst-zu.sst-zu, .tafelkopf__zu.tafelkopf__zu):active { transform: none; box-shadow: none; }

/* ===================================================================
   DAS SIEGELDECK (20.10.2026, client/src/iso3d/siegeldeck.ts) — die
   Ledermappe am linken Rand und die Karten der Siegelträger, in der Burg
   und auf dem Kriegstisch. Lage und Maße setzt das Skript in Bildpunkten.
   Gebaut nach der Probe /static/siegeldeck.html.
   =================================================================== */
/* Der Pfeil am Rand: zwei dünne Linien, dezent; unter dem Zeiger hell, offen zeigt er zurück. */
.sdk-pfeil { all: unset; position: fixed; z-index: 30; cursor: pointer; box-sizing: border-box; display: block;
  color: var(--brass-light, #e8c87a); opacity: .7;
  /* Ein leichter Schatten, damit man ihn auch auf dem hellen Kriegstisch erkennt (Ansage des Bro). */
  filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, .75)) drop-shadow(0 0 4px rgba(0, 0, 0, .45));
  transition: opacity .18s, transform .3s cubic-bezier(.25,.8,.25,1); }
.sdk-pfeil:hover, .sdk-pfeil:focus-visible { opacity: 1; background: none; border: 0; box-shadow: none; outline: none; }
.sdk-pfeil:focus { background: none; border: 0; box-shadow: none; outline: none; }
.sdk-pfeil svg { display: block; width: 100%; height: 100%; }
.sdk-pfeil.offen { transform: scaleX(-1); }
body.baumodus .sdk-pfeil, body.baumodus .sdk-deck { display: none; }

/* Die Karten: jede liegt fest oben links, das Skript schiebt sie mit transform. */
.sdk-deck { position: fixed; left: 0; top: 0; width: 0; height: 0; z-index: 35; }
.sdk-karte { position: fixed; left: 0; top: 0; width: var(--w); opacity: 0; pointer-events: none;
  filter: drop-shadow(0 4px 5px rgba(0,0,0,.6)); }
.sdk-karte.sichtbar { opacity: 1; }
.sdk-karte.draussen { pointer-events: auto; cursor: pointer; }
.sdk-karte .sgt-platz { width: 13.5rem; zoom: var(--zoom); }
.sdk-karte .sgt-fuss { display: none; }
/* VORSCHAU: unter dem Zeiger größer NEU gezeichnet (nicht
   hochgezogen — sonst weich); sie wächst nach allen Seiten gleich, aus
   ihrer Mitte (Ansage des Bro: „bitte zoomen immer mittig"). */
/* Seit dem 20.10.2026 das 1,3-Fache statt des 1,5-fachen (Ansage des Bro); die
   Maße in ganzen Bildpunkten setzt siegeldeck.ts (--wgross, --vrand, --vf). */
.sdk-karte.draussen.vorschau { z-index: 200 !important; --w: var(--wgross); margin-left: calc(var(--vrand) * -1); margin-top: var(--hochrand); }
.sdk-karte.draussen.vorschau .sgt-platz { zoom: calc(var(--zoom) * var(--vf)); }
/* Die gewählte Karte zeigt nur ihren Rand — angehoben stand sie schief in der Reihe und sah aus, als wäre sie nicht zurückgerückt (20.10.2026). */
/* Beim Verlassen schrumpft die Vorschau noch zurück — so lange bleibt sie über den Nachbarn. */
.sdk-karte.nachhall { z-index: 150 !important; }
/* Die gewählte Karte zeigt sich auf dem Kriegstisch im dunklen Auswahlrahmen
   um Karte und Knöpfe (.sl-auswahlrahmen, siegelleiste.ts); der warme Schein
   von unten war es nicht (20.10.2026, Ansage des Bro: „das belichten sieht
   nicht gut aus … vllt lieber ein auswahl rahmen so einen dunklen der sie
   zusammenfasst"). */
.sl-auswahlrahmen { position: fixed; z-index: 34; pointer-events: none; box-sizing: border-box;
  background: rgba(12, 10, 8, .82); border: 1px solid #3a2e1c; box-shadow: 0 4px 14px rgba(0, 0, 0, .6); }
.sl-auswahlrahmen[hidden] { display: none; }
/* Kriegstisch: unter dem Zeiger wächst die Karte nicht (`heben`, siegeldeck.ts). */
.sdk-deck.sdk-heben .sdk-karte.draussen.vorschau { --w: var(--wbasis); margin: 0; z-index: auto !important; }
.sdk-deck.sdk-heben .sdk-karte.draussen.vorschau .sgt-platz { zoom: var(--zoom); }
/* Die Karte bleibt unter dem Zeiger stehen und wird nur heller (Ansage des Bro:
   „beim drüberhovern die karte nicht bewegen"). */
.sdk-deck.sdk-heben .sdk-innen { transition: filter .18s ease-out; }
.sdk-deck.sdk-heben .sdk-karte.draussen.vorschau .sdk-innen { filter: brightness(1.14); }
.sdk-karte.blitz .sgt-karte { animation: sdk-blitz .5s; }
@keyframes sdk-blitz { 0% { filter: brightness(1.7); } 100% { filter: none; } }
.sdk-ersatz { aspect-ratio: 407 / 640; display: flex; align-items: center; justify-content: center; background: #12100e; color: #efe3c4; }

/* WENDEN: Vorder- und Rückseite, ein Klick dreht die Karte um die senkrechte Achse. */
.sdk-innen { perspective: 900px; transition: transform .16s ease-out; }
.sdk-wende { position: relative; transform-style: preserve-3d; transition: transform .55s cubic-bezier(.3,.7,.25,1); }
.sdk-karte.gewendet .sdk-wende { transform: rotateY(180deg); }
.sdk-vorn, .sdk-hinten { backface-visibility: hidden; -webkit-backface-visibility: hidden; }
.sdk-hinten { position: absolute; inset: 0; transform: rotateY(180deg); background: url("/app/siegeldeck/rueckseite.webp") center / 100% 100% no-repeat; }
/* Oben: bereit, beschäftigt oder ausgefallen. */
.sdk-lage { position: absolute; left: 50%; top: 3.6%; transform: translateX(-50%); height: 6%; padding: 0 .8em;
  display: flex; align-items: center; justify-content: center; white-space: nowrap;
  background: #12100e; border: 1px solid #3a2e1c; font-family: var(--font-body); font-size: max(10px, calc(var(--w) * .062)); line-height: 1; }
.sdk-lage.bereit { color: #cfe0a8; }
.sdk-lage.beschaeftigt { color: #f3d27a; }
.sdk-lage.ausgefallen { color: #e0a08a; }
/* Das Lederfeld der Rückseite, am Bild gemessen. */
.sdk-feld { position: absolute; left: 9.6%; right: 9.3%; top: 12.7%; bottom: 8.6%; container-type: inline-size;
  padding: 4% 5% 5%; box-sizing: border-box; display: flex; flex-direction: column; gap: 2.4%;
  font-family: var(--font-body); color: #e8dcc0; font-size: max(10px, calc(var(--w) * .058)); line-height: 1.15; }
.sdk-bild { flex: none; aspect-ratio: 16 / 10; background-color: #12100e; background-position: center; background-size: cover; background-repeat: no-repeat;
  border: 1px solid #6a5434; box-shadow: inset 0 0 0 1px rgba(0,0,0,.5); }
/* IMMER LESBAR, LIEBER ZWEI ZEILEN (20.10.2026, Ansage des Bro: „manchmal auf
   der rückseite wird der text so klein dass man den nicht lesen kann deswegen
   ruhig über zwei zeilen schreiben"): Die Schrift hat ihre Mindestgröße (10 px),
   lange Namen und Angaben brechen um, höchstens in zwei Zeilen. */
.sdk-name { font-family: var(--font-display); color: #efe3c4; text-align: center; font-size: 1.1em; line-height: 1.1;
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow-wrap: anywhere; }
.sdk-feld dl { display: grid; grid-template-columns: auto 1fr; gap: .2em .5em; margin: 0; }
.sdk-feld dt { color: var(--text-dim, #a89a80); font-size: max(10px, .85em); }
.sdk-feld dd { margin: 0; color: #f3d27a; text-align: right; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 2; line-clamp: 2; overflow-wrap: anywhere; }
.sdk-weg { height: .35em; background: #12100e; border: 1px solid #3a2e1c; }
.sdk-weg i { display: block; height: 100%; width: var(--anteil, 0%); background: linear-gradient(90deg, #a07c38, #f3d27a); }
.sdk-eig { display: flex; flex-wrap: wrap; gap: .3em; margin-top: auto; }
.sdk-eig span { font-size: max(10px, .8em); padding: .1em .35em; border: 1px solid #3a2e1c; background: #12100e; }
.sdk-eig .gut { color: #cfe0a8; } .sdk-eig .schlecht { color: #e0a08a; } .sdk-eig .klasse { color: #f3d27a; }
.sdk-sold { font-size: max(10px, .8em); color: var(--text-dim, #a89a80); text-align: center; }
/* Entlassen und die Rückfrage: dieselbe Höhe und Lage — nichts springt; unter dem Zeiger nur heller. */
.sdk-entlassen, .sdk-frage button { all: unset; }
.sdk-entlassen, .sdk-frage { height: 2em; margin-top: .2em; box-sizing: border-box; flex: none; font-size: .85em; }
.sdk-entlassen { align-self: stretch; display: flex; align-items: center; justify-content: center; cursor: pointer;
  font-family: var(--font-body); color: #e0a08a; background: #12100e; border: 1px solid #3a2e1c; }
.sdk-frage { display: flex; align-items: stretch; gap: .4em; }
.sdk-frage span { flex: 1; display: flex; align-items: center; color: #e0a08a; }
.sdk-frage button { padding: 0 .7em; display: flex; align-items: center; box-sizing: border-box; cursor: pointer;
  background: #12100e; border: 1px solid #3a2e1c; color: #e8dcc0; font-family: var(--font-body); }
.sdk-entlassen:hover, .sdk-entlassen:focus, .sdk-entlassen:active,
.sdk-frage button:hover, .sdk-frage button:focus, .sdk-frage button:active {
  background: #12100e; border-color: #3a2e1c; filter: brightness(1.35); outline: none; box-shadow: none; transform: none; }
/* Unterwegs: derselbe Knopf, blass und ohne Wirkung — nur der Hinweis im title. */
.sdk-entlassen.aus, .sdk-entlassen.aus:hover, .sdk-entlassen.aus:focus, .sdk-entlassen.aus:active { opacity: .4; filter: none; cursor: not-allowed; }
