/*!
 * cipher — Darstellung
 *
 * Sechs Themes ueber das Attribut data-theme am <html>: dark (Blaupause),
 * light (Weisspause), contrast (Schwarz auf Weiss, maximaler Kontrast),
 * writer (Papier: warmes, liniertes Schreibpapier), space (Weltall:
 * Neon auf Sternenhimmel) und forge (Schmiede: Holz und Messing, angelehnt
 * an die Farben des Spiels).
 * Alle Farben laufen ueber Custom Properties, damit ein Theme nur die
 * Variablen neu belegen muss.
 */

/* ---------------------------------------------------------------- Themes */

:root {
  /* Blaupause (dunkel) */
  --bg: #1f4a7a;
  --panel: rgba(22, 57, 89, .82);
  --field: #163959;
  --ink: #f2f6fb;
  --dim: #b9cce3;
  --grid: rgba(242, 246, 251, .22);
  --grid-fine: rgba(242, 246, 251, .07);
  --frame: #f2f6fb;
  --btn: #f2f6fb;
  --btn-ink: #163959;
  --on-accent: #163959;
  --gold: #f0c24f;
  --silver: #cfd8e1;
  --bronze: #e59a66;
  --iron: #9fb0c2;
  --own: #ff8f7e;
  --ok: #7fe0ad;
  --warn: #ffd36e;
  --field-border: var(--grid);
  /* Form: runde Ecken und ein weicher Schatten. Jedes Theme stimmt den
     Schatten auf seinen Hintergrund ab; der Kontrastmodus kommt ohne aus. */
  --r: 8px;
  --r-sm: 5px;
  --shadow: inset 0 1px 0 rgba(242, 246, 251, .08), 0 8px 22px rgba(8, 26, 48, .35);
  --shadow-sm: 0 2px 6px rgba(8, 26, 48, .3);

  box-sizing: border-box;
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  color-scheme: dark;
}

:root[data-theme="light"] {
  /* Weisspause (hell) */
  --bg: #eef3f9;
  --panel: #ffffff;
  --field: #f3f7fc;
  --ink: #133356;
  --dim: #4f6a88;
  --grid: rgba(31, 74, 122, .14);
  --grid-fine: rgba(31, 74, 122, .05);
  --frame: #1f4a7a;
  --btn: #1f4a7a;
  --btn-ink: #ffffff;
  --on-accent: #ffffff;
  --gold: #b98512;
  --silver: #74818f;
  --bronze: #b0602f;
  --iron: #4f5f71;
  --own: #c9423a;
  --ok: #1f8a55;
  --warn: #a86a00;
  --field-border: rgba(31, 74, 122, .3);
  --shadow: 0 1px 2px rgba(19, 51, 86, .06), 0 8px 20px rgba(19, 51, 86, .08);
  --shadow-sm: 0 1px 3px rgba(19, 51, 86, .15);
  color-scheme: light;
}

:root[data-theme="contrast"] {
  --bg: #fff;
  --panel: #fff;
  --field: #fff;
  --ink: #000;
  --dim: #000;
  --grid: transparent;
  --grid-fine: transparent;
  --frame: #000;
  --btn: #000;
  --btn-ink: #fff;
  --on-accent: #fff;
  --gold: #000;
  --silver: #000;
  --bronze: #000;
  --iron: #000;
  --own: #000;
  --ok: #000;
  --warn: #000;
  --field-border: #000;
  --r: 4px;
  --r-sm: 3px;
  --shadow: none;
  --shadow-sm: none;
  color-scheme: light;
}

:root[data-theme="writer"] {
  /* Papier (hell, warm) */
  --bg: #f4ecd8;
  --panel: #fbf6e9;
  --field: #f8f1e0;
  --ink: #3b2f22;
  --dim: #6b5943;
  --grid: rgba(110, 84, 50, .13);
  --grid-fine: transparent;
  --frame: #5a4632;
  --btn: #5a4632;
  --btn-ink: #fbf6e9;
  --on-accent: #fbf6e9;
  --gold: #8f6300;
  --silver: #6b665e;
  --bronze: #9a4a1e;
  --iron: #4e4a44;
  --own: #a8322a;
  --ok: #3d6b37;
  --warn: #875600;
  --field-border: rgba(90, 70, 50, .35);
  --shadow: 0 1px 2px rgba(90, 60, 30, .08), 0 8px 20px rgba(90, 60, 30, .10);
  --shadow-sm: 0 1px 3px rgba(90, 60, 30, .18);
  color-scheme: light;
}

:root[data-theme="space"] {
  /* Weltall (dunkel, Neon) */
  --bg: #07061a;
  --panel: rgba(16, 12, 44, .82);
  --field: #110d33;
  --ink: #eef2ff;
  --dim: #a3acd9;
  --grid: rgba(0, 229, 255, .10);
  --grid-fine: transparent;
  --frame: #00e5ff;
  --btn: #00e5ff;
  --btn-ink: #07061a;
  --on-accent: #07061a;
  --gold: #ffe45c;
  --silver: #c9d4ff;
  --bronze: #ff9d5c;
  --iron: #8e97d0;
  --own: #ff4df0;
  --ok: #39ff9f;
  --warn: #ffb63d;
  --field-border: rgba(0, 229, 255, .35);
  --shadow: 0 0 18px rgba(0, 229, 255, .18), inset 0 0 24px rgba(160, 60, 255, .08);
  --shadow-sm: 0 0 10px rgba(0, 229, 255, .3);
  color-scheme: dark;
}

:root[data-theme="forge"] {
  /* Schmiede (dunkel, Holz). Die Werte sind aus der Oberflaeche des Spiels
     abgenommen: dunkles Holz der Leisten, Orangeholz der Knoepfe, das
     Hellgold der Pfeile und das Hellgruen der Prozentanzeige. Gezeichnet
     ist alles in CSS — keine Grafik aus dem Spiel. */
  --bg: #183c30;
  --panel: #3e2410;
  --field: #2e1a08;
  --ink: #fff4e4;
  --dim: #dcbf94;
  --grid: rgba(168, 204, 60, .10);
  --grid-fine: transparent;
  --frame: #c27f2e;
  --btn: linear-gradient(#e0a24c, #bd782a);
  --btn-ink: #1e0f02;
  --on-accent: #1e0f02;
  --gold: #f5b95e;
  --silver: #dcd6ca;
  --bronze: #ec945a;
  --iron: #b3a590;
  --own: #ff8466;
  --ok: #a8cc3c;
  --warn: #ffc94a;
  --field-border: #6c3c18;
  --shadow: inset 0 1px 0 rgba(255, 200, 120, .25), 0 4px 0 #1e0f02, 0 8px 18px rgba(0, 0, 0, .35);
  --shadow-sm: 0 2px 0 #1e0f02;
  color-scheme: dark;
}

/* ------------------------------------------------------------- Grundlage */

*, *::before, *::after { box-sizing: inherit }

/* Fuer Beschriftungen, die Screenreader brauchen, das Auge aber nicht. */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

html { background: var(--bg) }

body {
  margin: 0;
  color: var(--ink);
  background-color: var(--bg);
  background-image:
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px),
    linear-gradient(var(--grid-fine) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-fine) 1px, transparent 1px);
  background-size: 96px 96px, 96px 96px, 16px 16px, 16px 16px;
  font-family: "Barlow Semi Condensed", "Arial Narrow", system-ui, sans-serif;
  font-size: 17px;
  line-height: 1.4;
  font-variant-numeric: tabular-nums;
}

/* Papier: nur waagrechte Linien wie auf einem Schreibblock. */
:root[data-theme="writer"] body {
  background-image: linear-gradient(transparent 31px, var(--grid) 31px);
  background-size: 100% 32px;
}

/* Weltall: zwei Nebel, drei versetzte Sternenraster und ein zartes Neon-
   gitter. Die Sternkacheln haben unterschiedliche Groessen, damit sich
   kein sichtbares Muster wiederholt. */
:root[data-theme="space"] body {
  background-image:
    radial-gradient(ellipse at 10% 0%, rgba(160, 60, 255, .28), transparent 55%),
    radial-gradient(ellipse at 95% 70%, rgba(0, 229, 255, .16), transparent 50%),
    radial-gradient(circle at 20% 30%, rgba(255, 255, 255, .85) 0 1px, transparent 1.5px),
    radial-gradient(circle at 70% 65%, rgba(0, 229, 255, .8) 0 1px, transparent 1.5px),
    radial-gradient(circle at 40% 85%, rgba(255, 77, 240, .7) 0 1px, transparent 1.5px),
    linear-gradient(var(--grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid) 1px, transparent 1px);
  background-size: 100% 100vh, 100% 100vh, 170px 170px, 230px 230px, 310px 310px, 96px 96px, 96px 96px;
  background-repeat: no-repeat, no-repeat, repeat, repeat, repeat, repeat, repeat;
}
:root[data-theme="space"] h1 {
  text-shadow: 0 0 10px rgba(0, 229, 255, .6), 0 0 28px rgba(255, 77, 240, .4);
}

/* Schmiede: Wasser und Wiese wie auf der Stadtkarte, darauf Holzleisten
   mit runden Ecken, heller Oberkante und kraeftigem Schlagschatten. */
:root[data-theme="forge"] body {
  background-image:
    radial-gradient(ellipse at 80% 0%, rgba(108, 114, 40, .45), transparent 60%),
    radial-gradient(ellipse at 0% 100%, rgba(48, 84, 60, .6), transparent 55%);
  background-size: 100% 100vh, 100% 100vh;
  background-repeat: no-repeat;
}
:root[data-theme="forge"] h1 { color: var(--gold); text-shadow: 0 2px 0 #1e0f02, 0 0 14px rgba(0, 0, 0, .4) }
:root[data-theme="forge"] .panel {
  border-width: 2px;
  background-image: linear-gradient(rgba(255, 200, 120, .06), transparent 40%);
}

main { max-width: 560px; margin: 0 auto; padding: 16px 14px 24px }

a { color: inherit }

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

header {
  display: flex;
  flex-direction: column-reverse;
  gap: 10px;
  margin: 6px 0 22px;
}

h1 {
  font-size: clamp(2.1rem, 9vw, 2.7rem);
  line-height: 1;
  margin: 0 0 4px;
  font-weight: 700;
  letter-spacing: -.02em;
  white-space: nowrap;
}

/* Die Wortmarke ist anklickbar (Easter Egg), soll aber nicht wie ein Button
   aussehen — nur der Fokusring verraet, dass sie bedienbar ist. */
.wordmark {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: inline-block;
}

.sub { color: var(--dim); margin: 0; max-width: 42ch; font-size: .98rem }

.modes { display: flex; border: 1.5px solid var(--frame); align-self: flex-end }
.modes button {
  width: 36px; height: 34px;
  display: grid; place-items: center;
  background: transparent; color: var(--ink);
  border: 0; cursor: pointer;
}
.modes button + button { border-left: 1.5px solid var(--frame) }
.modes button[aria-pressed="true"] { background: var(--btn); color: var(--btn-ink) }
.modes svg { width: 18px; height: 18px }

/* ---------------------------------------------------------------- Panels */

.panel {
  border: 1.5px solid var(--frame);
  background: var(--panel);
  padding: 14px;
  margin-bottom: 14px;
}
:root[data-theme="contrast"] .panel { border-width: 2px }
.panel h2 { font-size: 1.15rem; margin: 0 0 10px; font-weight: 600 }

/* ------------------------------------------------------ Formularelemente */

.l { display: block; font-size: .9rem; color: var(--dim); margin: 0 0 4px }

select, input, .pick {
  font: inherit;
  color: var(--ink);
  background: var(--field);
  border: 1.5px solid var(--field-border);
  padding: 9px 10px;
  width: 100%;
  border-radius: 0;
}
:root[data-theme="contrast"] select,
:root[data-theme="contrast"] input,
:root[data-theme="contrast"] .pick { border-width: 2px }

select, .pick {
  appearance: none;
  font-weight: 600;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink) 50%),
    linear-gradient(135deg, var(--ink) 50%, transparent 50%);
  background-position: calc(100% - 18px) 55%, calc(100% - 12px) 55%;
  background-size: 6px 6px;
  background-repeat: no-repeat;
  padding-right: 32px;
}

/* Unter rund 390px Geraetebreite blieben fuer die Stufenzahl nur noch
   wenige Pixel zwischen den Steppertasten. Darum bricht die Reihe dort um,
   statt beide Felder starr nebeneinander zu quetschen. */
.row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px }
.row > div { flex: 1 1 150px; min-width: 0 }
/* Das zweite Feld einer Spalte braucht Abstand zum ersten; ohne ihn klebt
   die Beschriftung am Feld darueber. */
.lbl-short { margin-top: 10px }

/* Beschriftung links, Schalter "Kuerzel" rechts auf derselben Linie — er
   sitzt beim Bauwerk, weil er dessen Namen betrifft, und kostet so keine
   eigene Zeile. */
.sel-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px }
.abbr-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: .9rem; color: var(--dim); cursor: pointer;
  margin: 0 0 4px; white-space: nowrap;
}
.abbr-toggle input { width: 16px; height: 16px; margin: 0; padding: 0; accent-color: var(--gold); cursor: pointer }
.abbr-toggle:has(input:checked) { color: var(--ink) }
/* Am Foerderchat steht der Schalter rechts neben der Ueberschrift. */
.chat-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px }
.chat-head .abbr-toggle { margin: 0 0 10px }

/* Dieselbe Zahl heisst fuer die einen "steht auf 80", fuer die anderen
   "wird auf 81 gezogen". Umschalter und erklaerende Zeile stehen zusammen
   unter dem Feld: neben der Beschriftung waere fuer beides kein Platz, und
   die Spalte mit dem Namen daneben liefe dann versetzt. */
.lvl-foot {
  display: flex; flex-wrap: wrap;
  align-items: center; gap: 4px 8px; margin-top: 6px;
}

/* Gebaut wie der Themenwechsler im Kopf: ein Rahmen, eine Trennlinie. */
.seg { display: flex; border: 1.5px solid var(--field-border) }
:root[data-theme="contrast"] .seg { border-width: 2px }
.seg button {
  font: inherit; font-size: .78rem; font-weight: 600;
  background: transparent; color: var(--dim);
  border: 0; padding: 1px 8px; cursor: pointer;
}
.seg button + button { border-left: 1.5px solid var(--field-border) }
:root[data-theme="contrast"] .seg button + button { border-left-width: 2px }
/* Nicht gold: das Gold gehoert den Werten (Faktor, P1, aktiver Favorit).
   Der Umschalter stellt eine Lesart ein, keinen Wert. */
.seg button[aria-pressed="true"] { background: var(--btn); color: var(--btn-ink) }

/* Nennt jeweils die Zahl, die nicht im Feld steht. */
.lvl-hint { color: var(--dim); font-size: .82rem; margin: 0 }

/* Frueher war jeder Knopf eine volle Flaeche in --btn. Auf einem Bildschirm
   mit Stufe, Faktor und fuenf Plaetzen sind das vierzehn helle Bloecke, die
   lauter sind als die Zahlen, um die es geht. Jetzt ist der Stepper ein Feld
   mit zwei ruhigen Zeichen an den Enden, getrennt durch dieselbe Linie wie
   der Rahmen. Die Flaeche zum Tippen bleibt gleich gross. */
.step {
  display: flex;
  background: var(--field);
  border: 1.5px solid var(--field-border);
}
:root[data-theme="contrast"] .step { border-width: 2px }

.step input { text-align: center; font-weight: 700; font-size: 1.2rem; min-width: 0 }
/* Den Rahmen traegt der Stepper, nicht das Feld darin. */
.step input,
:root[data-theme="contrast"] .step input { background: transparent; border: 0 }
/* Der Fokusring sitzt sonst genau auf dem Rahmen des Steppers. */
.step input:focus-visible { outline-offset: -3px }

.step button {
  flex: 0 0 44px;
  font: inherit; font-size: 1.3rem; font-weight: 600; line-height: 1;
  background: transparent; color: var(--dim);
  border: 0; cursor: pointer;
}
.step button:first-child { border-right: 1.5px solid var(--field-border) }
.step button:last-child { border-left: 1.5px solid var(--field-border) }
:root[data-theme="contrast"] .step button:first-child { border-right-width: 2px }
:root[data-theme="contrast"] .step button:last-child { border-left-width: 2px }
.step button:hover:not(:disabled) { color: var(--ink) }
/* An der Grenze war bisher nichts zu sehen, der Knopf reagierte nur nicht.
   Gedaempft wird die Schriftfarbe, nicht der Knopf: opacity haette seine
   Trennlinie mit abblassen lassen. */
.step button:disabled { color: var(--field-border); cursor: default }
/* Im Kontrastmodus ist --field-border schwarz, ein blasses Zeichen gibt es
   dort also nicht. Statt den Kontrast zu senken verschwindet das Zeichen. */
:root[data-theme="contrast"] .step button:disabled { color: transparent }

/* Der Faktor lief frueher ueber einen Schieberegler. Auf dem Telefon sprang
   sein Wert schon beim Aufsetzen des Fingers dorthin, wo man ihn hinsetzte —
   beim Scrollen also staendig unbemerkt. Keine touch-action-Einstellung
   hilft dagegen, der Wert wird vor der Gestenerkennung gesetzt. Ein Stepper
   hat keine Schiene, die man versehentlich trifft: Knoepfe loesen erst beim
   Loslassen aus, und eine Wischgeste bricht den Klick ab. */
.fac input { color: var(--gold) }

/* Was der Regler konnte und der Stepper nicht: die Lage im Bereich zeigen.
   Darum ein schmaler Balken darunter — reine Anzeige, nichts zum Anfassen. */
.fac-gauge {
  height: 4px; margin-top: 6px;
  background: var(--field);
  border: 1.5px solid var(--field-border);
  pointer-events: none;
}
:root[data-theme="contrast"] .fac-gauge { border-width: 2px }
.fac-gauge i {
  display: block; height: 100%;
  background: var(--gold);
  transition: width .2s cubic-bezier(.2, .8, .2, 1);
}
:root[data-theme="contrast"] .fac-gauge i { background: #000 }
@media (prefers-reduced-motion: reduce) { .fac-gauge i { transition: none } }

.factor-block { margin-top: 12px }

.chips { display: flex; gap: 6px; margin-top: 6px }
.chips button {
  flex: 1;
  font: inherit; font-weight: 600;
  background: transparent; color: var(--ink);
  border: 1.5px solid var(--field-border);
  padding: 5px 0; cursor: pointer;
}
:root[data-theme="contrast"] .chips button { border-width: 2px }
.chips button.on { background: var(--gold); color: var(--on-accent); border-color: var(--gold) }

/* ------------------------------------------------------- Faktor je Platz */

/* Der Arche-Bonus gehoert dem Foerderer, nicht dem Bauwerk — wer P3 nimmt,
   kann eine andere Arche haben als wer P1 nimmt. Die meisten brauchen das
   nie, darum liegt der Block hinter einem Aufklapper und kostet zu keine
   Hoehe. */
.slots { margin-top: 10px; border-top: 1.5px solid var(--field-border); padding-top: 8px }
:root[data-theme="contrast"] .slots { border-top-width: 2px }

.slots summary {
  display: flex; align-items: center; gap: 8px;
  font-size: .9rem; font-weight: 600; color: var(--dim);
  cursor: pointer; list-style: none;
}
.slots summary::-webkit-details-marker { display: none }
/* Eigener Pfeil, damit er in allen Browsern gleich sitzt und mitdreht. */
.slots summary::before {
  content: ""; flex: 0 0 auto;
  width: 0; height: 0;
  border: 5px solid transparent;
  border-left-color: currentColor;
  transition: transform .15s ease;
}
.slots[open] summary::before { transform: rotate(90deg) translateX(-2px) }
@media (prefers-reduced-motion: reduce) { .slots summary::before { transition: none } }

/* Zeigt die Spanne, sobald ein Platz einen eigenen Wert hat. So steht auch
   bei zugeklapptem Block da, dass sich etwas unterscheidet. */
.slots-badge {
  font-weight: 700; color: var(--gold);
  border: 1.5px solid var(--gold);
  padding: 0 6px; font-size: .82rem;
}
:root[data-theme="contrast"] .slots-badge { color: #000; border-color: #000; border-width: 2px }

/* Der Kopf der Absicherungsspalte ist ein Schalter zwischen zwei Lesarten.
   Er sieht aus wie die anderen Koepfe — ein Knopf, der sich als Knopf
   auffuehrt, waere lauter als die Zahlen, um die es geht. Das Zeichen
   daneben ist die ganze Handhabe. */
/* Die Zelle behaelt das Polster der uebrigen Koepfe; der Knopf bringt keins
   mit. Andersherum (Polster an den Knopf, Zelle auf 0) sass die Beschriftung
   drei Pixel tiefer als "Platz", "Belohnung" und "Einzahlen" daneben. */
.th-pre button {
  display: block; width: 100%;
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: inherit; text-align: inherit;
}
/* Im Textfluss, nicht daneben: als Flex-Glied landete das Zeichen beim
   Umbruch hinter "Vorher" statt hinter "sichern". */
.th-caret { margin-left: 4px; font-size: .7em; opacity: .7 }
:root[data-theme="contrast"] .th-caret { opacity: 1 }

.slots-note { color: var(--dim); font-size: .82rem; margin: 8px 0 0 }
.slots-unit { margin-top: 8px; width: max-content }
.slots-unit button { padding: 4px 12px; font-size: .82rem }

.slot-list { list-style: none; margin: 8px 0 0; padding: 0 }
.slot-list li { margin-top: 6px }
.slot-row { display: flex; align-items: center; gap: 8px }
.slot-list .tag { font-size: .95rem; flex: 0 0 34px }

/* Kleiner als der grosse Stepper daruber: fuenf davon in voller Groesse
   waeren ueber 230px hoch. */
.step.mini { flex: 0 1 148px; min-width: 0 }
.step.mini button { flex: 0 0 34px; font-size: 1.1rem }
/* min-width, damit das Feld schrumpft statt die Zeile zu sprengen: ein
   Textfeld haelt sonst seine Eigenbreite und schiebt bei 320 Pixeln das
   Kreuz aus dem Bild. */
.step.mini input { font-size: 1rem; padding: 4px 6px; min-width: 0 }

/* Der Stepper misst Faktorstufen. Ein abgelesener Betrag hat keine, also
   faellt er dort weg und das Feld bekommt die Breite. */
.slot-list li.fp .step.mini button { display: none }
.slot-list li.fp .step.mini input { text-align: left; padding-left: 10px }

/* Die andere Einheit steht unter der Zeile, nicht daneben: auf 320 Pixeln
   waere daneben kein Platz mehr. Sie liegt ausserhalb der Flex-Zeile, denn
   darin wuerde sie umbrechen — und ein Umbruch greift vor dem Schrumpfen. */
.slot-hint {
  display: block; margin: -1px 0 0 42px;
  color: var(--dim); font-size: .78rem; font-variant-numeric: tabular-nums;
}
/* Ein Platz mit eigenem Wert faellt auf — sonst sieht man nicht, welcher
   dem Wert oben noch folgt. */
.slot-list li.own .step.mini { border-color: var(--gold) }
.slot-list li.own .step.mini input { color: var(--gold) }
:root[data-theme="contrast"] .slot-list li.own .step.mini { border-width: 3px }

/* Das Wort traegt den Zustand, die Farbe verstaerkt ihn nur. */
.slot-state { color: var(--dim); font-size: .8rem; flex: 0 0 auto }
.slot-list li.own .slot-state { color: var(--gold); font-weight: 600 }
:root[data-theme="contrast"] .slot-list li.own .slot-state { color: #000; text-decoration: underline }

.slot-reset {
  font: inherit; font-size: 1rem; line-height: 1;
  background: transparent; color: var(--dim);
  border: 1.5px solid var(--field-border);
  padding: 3px 7px; cursor: pointer;
}
:root[data-theme="contrast"] .slot-reset { border-width: 2px }
.slot-reset:hover { color: var(--own) }

#slotsReset { margin-top: 10px; font-size: .85rem; color: var(--dim) }

/* --------------------------------------------------------- Bauwerksfilter */

.filter { display: flex; margin-top: 6px }
.filter input { flex: 1 1 auto; min-width: 0; font-size: .95rem; padding: 7px 10px }
.filter input::-webkit-search-cancel-button { display: none }

.filter button {
  flex: 0 0 38px;
  font: inherit; font-size: 1.2rem; line-height: 1;
  background: transparent; color: var(--dim);
  border: 1.5px solid var(--field-border); border-left: 0;
  cursor: pointer;
}
:root[data-theme="contrast"] .filter button { border-width: 2px; border-left: 0; color: #000 }
.filter button:hover { color: var(--ink) }
.filter button[hidden] { display: none }

.filter-count { margin: 4px 0 0; font-size: .82rem; color: var(--dim); min-height: 1.2em }
.filter-count:empty { display: none }

/* Die Treffer stehen als eigene Liste unter dem Feld, statt das Auswahlfeld
   umzubauen. So zeigt das Auswahlfeld immer alle Bauwerke und immer das
   wirklich gewaehlte — und die Trefferzahl stimmt mit dem ueberein, was
   man sieht. Auf dem Telefon spart es ausserdem den Weg durch die native
   Liste mit 49 Eintraegen. */
.filter-results {
  list-style: none;
  display: flex; flex-direction: column; gap: 4px;
  margin: 6px 0 0; padding: 0;
  max-height: calc(4 * 2.4rem);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.filter-results:empty { display: none }

.filter-hit {
  width: 100%;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  font: inherit; font-size: .95rem; text-align: left;
  background: var(--field); color: var(--ink);
  border: 1.5px solid var(--field-border);
  padding: 7px 10px; cursor: pointer;
}
:root[data-theme="contrast"] .filter-hit { border-width: 2px }
.filter-hit:hover, .filter-hit:focus-visible { border-color: var(--gold) }
.filter-hit b { font-weight: 600 }
.filter-hit span { font-size: .82rem; color: var(--dim); white-space: nowrap }
.filter-hit[aria-current="true"] b::after { content: " ·"; color: var(--gold) }

/* Die getroffene Stelle hervorheben, damit man sieht, warum ein Eintrag in
   der Liste steht — ob der Name gepasst hat oder nur das Zeitalter. Die
   Vorgabe des Browsers (gelber Kasten, schwarze Schrift) passt hier nicht. */
.filter-hit mark { background: none; color: var(--gold); font-weight: 700 }
:root[data-theme="contrast"] .filter-hit mark { color: #000; text-decoration: underline; text-underline-offset: 2px }

/* ------------------------------------------------------ Bauwerksauswahl */

/* Der Knopf, der die Auswahl oeffnet. Er sieht aus wie das Auswahlfeld
   davor (Rahmen, Pfeil), zeigt rechts aber zusaetzlich das Zeitalter. */
.pick {
  display: flex; align-items: baseline; gap: 10px;
  text-align: left; cursor: pointer;
  min-height: 44px;
}
.pick-name {
  flex: 1 1 auto; min-width: 0;
  font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pick-era { flex: 0 1 auto; font-size: .82rem; color: var(--dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis }

/* Solange die Auswahl offen ist, bleibt die Seite dahinter stehen. Der
   Platz der Bildlaufleiste bleibt reserviert, sonst ruckt die Seite zur
   Seite. */
html.picker-open { overflow: hidden; scrollbar-gutter: stable }

/* Das <dialog> selbst ist nur der Rahmen; es fuellt das Blatt ganz aus,
   damit ein Klick auf das <dialog> nur vom Hintergrund kommen kann.
   Telefon: Blatt von unten, ueber der Bildschirmtastatur (--kb setzt
   app.js aus dem visualViewport). */
.picker {
  position: fixed;
  inset: auto 0 var(--kb, 0px) 0;
  margin: 0; padding: 0; border: 0;
  width: 100%; max-width: none;
  height: calc(var(--vvh, 100dvh) * .88);
  max-height: calc(var(--vvh, 100dvh) - 16px);
  background: transparent; color: var(--ink);
  overflow: visible;
}
.picker[open] { display: flex }
.picker::backdrop { background: rgba(4, 12, 24, .55) }
:root[data-theme="contrast"] .picker::backdrop { background: rgba(0, 0, 0, .6) }

.picker-sheet {
  display: flex; flex-direction: column;
  width: 100%; min-height: 0;
  /* --panel ist in den dunklen Themes durchscheinend; ueber --bg gelegt
     ergibt es dieselbe Flaeche wie die Panels, nur deckend. */
  background: linear-gradient(var(--panel), var(--panel)), var(--bg);
  border: 1.5px solid var(--frame); border-bottom: 0;
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -10px 30px rgba(0, 0, 0, .3);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  transition: transform .2s ease-out;
}
:root[data-theme="contrast"] .picker-sheet { border-width: 2px; border-bottom: 0; box-shadow: none }
.picker-sheet.dragging { transition: none }

.picker-head {
  position: relative;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 18px 10px 8px 16px;
  /* Hier greift das Wischen nach unten; der Browser soll dabei nicht
     selbst scrollen oder zoomen. */
  touch-action: none;
  user-select: none; -webkit-user-select: none;
}
.picker-grip {
  position: absolute; top: 7px; left: 50%;
  width: 40px; height: 4px; border-radius: 2px;
  background: var(--field-border);
  transform: translateX(-50%);
}
:root[data-theme="contrast"] .picker-grip { background: #000 }
.picker-head h2 { margin: 0; font-size: 1.15rem; font-weight: 600 }

.picker-close {
  flex: 0 0 44px; width: 44px; height: 44px;
  display: grid; place-items: center;
  background: transparent; color: var(--dim);
  border: 0; border-radius: var(--r-sm); cursor: pointer;
}
.picker-close:hover { color: var(--ink) }
.picker-close svg { width: 20px; height: 20px }

.picker-search { margin: 0 14px }
/* Unter 16px zoomt Safari auf dem iPhone beim Antippen ins Feld. */
.picker-search input { font-size: max(16px, 1rem); padding: 10px 12px }
.picker-count { margin: 6px 16px 0 }

.picker-list {
  list-style: none;
  flex: 1 1 auto; min-height: 0;
  margin: 8px 0 0; padding: 0 8px 12px;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.picker-list:focus-visible { outline-offset: -3px }
.picker-group { list-style: none; margin: 0; padding: 0 }

/* Die Zeitalter laufen beim Scrollen oben mit, bis das naechste sie
   wegschiebt — man weiss immer, wo in der Liste man steht. */
.picker-era {
  position: sticky; top: 0; z-index: 1;
  padding: 12px 10px 4px;
  font-size: .78rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--dim);
  background: linear-gradient(var(--panel), var(--panel)), var(--bg);
}

.picker-opt {
  position: relative;
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  min-height: 48px;
  padding: 12px 12px 12px 36px;
  border: 1.5px solid transparent;
  border-radius: var(--r-sm);
  cursor: pointer;
  /* Platz fuer die mitlaufende Zeitalter-Ueberschrift, wenn die Tastatur
     eine Option in den sichtbaren Bereich holt. */
  scroll-margin: 40px 0 8px;
  -webkit-tap-highlight-color: transparent;
}
.picker-opt b { font-weight: 600; min-width: 0; overflow-wrap: anywhere }
.picker-opt span { font-size: .82rem; color: var(--dim); white-space: nowrap }
.picker-opt:hover, .picker-opt:active { background: var(--field) }
/* Wo die Tastatur steht: Enter nimmt dieses Bauwerk. */
.picker-opt.active { background: var(--field); border-color: var(--field-border) }
:root[data-theme="contrast"] .picker-opt.active { border: 2px solid #000 }

.picker-opt[aria-selected="true"] b { color: var(--gold) }
.picker-opt[aria-selected="true"]::before {
  content: "✓";
  content: "✓" / "";
  position: absolute; left: 12px;
  color: var(--gold); font-weight: 700;
}
.picker-opt mark { background: none; color: var(--gold); font-weight: 700 }
:root[data-theme="contrast"] .picker-opt mark { color: #000; text-decoration: underline; text-underline-offset: 2px }

/* Blatt faehrt von unten herein und wieder hinaus. */
@keyframes picker-up { from { transform: translateY(100%) } }
@keyframes picker-down { to { transform: translateY(100%) } }
@keyframes picker-fade-in { from { opacity: 0 } }
@keyframes picker-fade-out { to { opacity: 0 } }
.picker[open] .picker-sheet { animation: picker-up .26s cubic-bezier(.2, .8, .25, 1) }
.picker.closing .picker-sheet { animation: picker-down .18s ease-in forwards }
.picker[open]::backdrop { animation: picker-fade-in .2s ease-out }
.picker.closing::backdrop { animation: picker-fade-out .18s ease-in forwards }

/* Breite Bildschirme und Telefone quer: ein Fenster in der Mitte statt
   eines Blatts, das ueber die ganze Breite liefe. */
@media (min-width: 641px) {
  .picker {
    inset: 0; margin: auto;
    width: min(460px, calc(100% - 32px));
    height: min(640px, calc(var(--vvh, 100dvh) - 32px));
    max-height: none;
  }
  .picker-sheet {
    border-bottom: 1.5px solid var(--frame);
    border-radius: var(--r);
    box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
    padding-bottom: 0;
  }
  :root[data-theme="contrast"] .picker-sheet { border-bottom: 2px solid #000 }
  .picker-grip { display: none }
  .picker-head { padding-top: 12px; touch-action: auto }
  @keyframes picker-pop { from { opacity: 0; transform: translateY(8px) scale(.98) } }
  @keyframes picker-pop-out { to { opacity: 0; transform: translateY(8px) scale(.98) } }
  .picker[open] .picker-sheet { animation: picker-pop .2s cubic-bezier(.2, .8, .25, 1) }
  .picker.closing .picker-sheet { animation: picker-pop-out .15s ease-in forwards }
}

@media (prefers-reduced-motion: reduce) {
  .picker-sheet, .picker[open] .picker-sheet, .picker.closing .picker-sheet,
  .picker[open]::backdrop, .picker.closing::backdrop { animation: none; transition: none }
}

/* ------------------------------------------------------------ Favoriten */

/* Der Streifen stand frueher ganz unten im Panel, hinter Suche, Stufe, Name
   und Faktor — auf dem Telefon also ausserhalb des ersten Bildschirms. Wer
   wiederkommt, will aber meistens genau dorthin zurueck, darum steht er
   jetzt vor allem anderen. Leer wird er ausgeblendet (siehe app.js). */
.favs { margin: 0 0 12px }
.favs[hidden] { display: none }
.favs .l { margin: 0 0 6px }

/* Der Knopf traegt jetzt den Namen dessen, was er merkt, und braucht darum
   die ganze Breite. Er bleibt umrandet statt gefuellt: der aktive Faktor-Chip
   ist eine Einstellung und darf leuchten, dieser Knopf ist nur eine Aktion. */
.fav-save {
  font: inherit; font-weight: 600; font-size: .92rem;
  display: flex; align-items: center; justify-content: center; gap: 7px;
  width: 100%; margin-top: 10px;
  background: transparent; color: var(--ink);
  border: 1.5px solid var(--field-border);
  padding: 8px 10px; cursor: pointer;
}
:root[data-theme="contrast"] .fav-save { border-width: 2px }
.fav-save svg { width: 15px; height: 15px; flex: 0 0 auto }
/* Den Zustand zeigt der gefuellte Stern, ohne mit dem Chip zu konkurrieren. */
.fav-save[aria-pressed="true"] { color: var(--gold); border-color: var(--gold) }
.fav-save[aria-pressed="true"] svg { fill: currentColor }
:root[data-theme="contrast"] .fav-save[aria-pressed="true"] { color: #000; border-color: #000 }

/* Bei voller Liste wuchs das Panel um rund 400px und schob den Foerderplan
   aus dem Bild. Drei Reihen bleiben sichtbar, der Rest ist scrollbar — die
   Hoehe ist damit unabhaengig von der Anzahl. */
.fav-list {
  list-style: none;
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 0; padding: 0;
  max-height: calc(3 * var(--fav-row) + 2 * 6px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* Gemessene Hoehe eines Chips. Eine glatte Zahl zu raten reichte nicht:
     mit 2rem wurde die dritte Reihe im Kontrastmodus angeschnitten, weil
     die Rahmen dort dicker sind. */
  --fav-row: 30.6px;
}
:root[data-theme="contrast"] .fav-list { --fav-row: 32.6px }
/* Platz fuer den Rollbalken, damit er die Chips nicht ueberdeckt. */
.fav-list { scrollbar-width: thin; padding-right: 2px }

/* Gefuellt statt durchsichtig: die Faktor-Chips daneben sind Einstellungen,
   diese hier sind Sprungmarken. Gleiche Optik hiesse gleiche Bedeutung. */
.fav-list li { display: flex; border: 1.5px solid var(--field-border); background: var(--field) }
:root[data-theme="contrast"] .fav-list li { border-width: 2px }
.fav-list li[aria-current="true"] { border-color: var(--gold) }

.fav-go, .fav-del {
  font: inherit;
  background: transparent; color: var(--ink);
  border: 0; cursor: pointer;
}
.fav-go { font-weight: 600; font-size: .92rem; padding: 4px 8px; max-width: 22ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap }
/* Mit Kuerzeln schrumpft ein Chip auf "KI 12" und die Reihe springt beim
   Umschalten. Der Name behaelt darum mindestens fuenf Zeichen Platz;
   lange Namen kuerzt er selbst, weil eine Ellipse am Knopf nicht in ein
   inline-block hineinreicht. */
.fav-n {
  display: inline-block; vertical-align: bottom;
  min-width: 5ch; max-width: 17ch; text-align: center;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fav-go b { color: var(--gold); font-weight: 700 }
.fav-list li[aria-current="true"] .fav-go { background: var(--gold); color: var(--on-accent) }
.fav-list li[aria-current="true"] .fav-go b { color: inherit }
.fav-del { padding: 4px 7px; color: var(--dim); border-left: 1.5px solid var(--field-border); line-height: 1 }
.fav-del:hover { color: var(--own) }

/* --------------------------------------------------------- Verteilbalken */

.bar {
  display: flex; height: 12px;
  margin: 2px 0 6px;
  border: 1.5px solid var(--frame);
}
.bar[hidden] { display: none }
.bar i { display: block; height: 100%; transition: width .4s cubic-bezier(.2, .8, .2, 1) }

.legend { display: flex; gap: 14px; flex-wrap: wrap; font-size: .85rem; color: var(--dim); margin-bottom: 10px }
/* Ohne diese Regel schlaegt das display:flex oben das display:none, das der
   Browser fuer [hidden] vorsieht — die Legende blieb im Leerzustand stehen. */
.legend[hidden] { display: none }
/* Bei 320px fehlten der Legende genau drei Pixel und "P4-P5" rutschte allein
   auf eine zweite Zeile. Eine engere Luecke reicht, die Schriftgroesse bleibt. */
@media (max-width: 380px) { .legend { gap: 6px 10px } }
.legend i { display: inline-block; width: 10px; height: 10px; margin-right: 5px; vertical-align: 0; background: var(--c) }
/* Im Kontrastmodus sind alle Farben schwarz — die Legende bekommt darum
   dieselbe Schraffur wie der Balken, damit sie unterscheidbar bleibt. */
:root[data-theme="contrast"] .legend i { border: 1px solid #000; background: repeating-linear-gradient(45deg, #000 0 2px, #fff 2px 6px) }
:root[data-theme="contrast"] .legend span:first-child i { background: #000 }

.b-own { background: var(--own) }
.b-1 { background: var(--gold) }
.b-2 { background: var(--silver) }
.b-3 { background: var(--bronze) }
.b-4, .b-5 { background: var(--iron) }
:root[data-theme="contrast"] .b-own { background: #000 }
:root[data-theme="contrast"] .bar i:not(.b-own) { background: repeating-linear-gradient(45deg, #000 0 2px, #fff 2px 6px) }

/* --------------------------------------------------------------- Tabelle */

table { width: 100%; border-collapse: collapse }
th { font-weight: 500; color: var(--dim); font-size: .85rem; text-align: right; padding: 0 4px 6px }
th:first-child { text-align: left }
td { padding: 9px 4px; border-top: 1px solid var(--grid); text-align: right }
:root[data-theme="light"] td { border-top-color: rgba(31, 74, 122, .15) }
:root[data-theme="writer"] td { border-top-color: rgba(110, 84, 50, .18) }
:root[data-theme="contrast"] td { border-top: 1px solid #000 }
td:first-child { text-align: left; white-space: nowrap }
td.pay { font-weight: 700; font-size: 1.15rem }
/* Die Zahl schaltet die Lesart mit um — wer sie antippt, meint sie. */
td.pre { font-weight: 600; color: var(--warn); cursor: pointer }
td.empty { padding: 14px 0; color: var(--dim); white-space: normal; text-align: left; border-top: 0 }
table.none thead { display: none }

tr.off td:not(:first-child) { opacity: .35 }
tr.off td.pay { text-decoration: line-through }
/* Vergeben: bezahlt, nur nicht mehr ausgeschrieben. Leiser als ein
   angebotener Platz, aber ohne Streichung — das Geld ist ja da. */
tr.taken td:not(:first-child):not(.pre) { opacity: .6 }
.given { color: var(--dim); font-weight: 600; font-size: .85rem }

.safe {
  display: inline-block;
  background: var(--ok); color: var(--on-accent);
  font-weight: 700; font-size: .85rem;
  padding: 2px 8px;
  animation: pop .3s ease-out;
}

.pl { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-weight: 700 }
.pl input { width: 20px; height: 20px; accent-color: var(--gold); margin: 0 }

/* Die Farbe je Platz kommt aus einer Klasse, nicht aus einem style-Attribut:
   so braucht der CSP kein 'unsafe-inline' fuer Stile. */
.slot-own { --c: var(--own) }
.slot-1 { --c: var(--gold) }
.slot-2 { --c: var(--silver) }
.slot-3 { --c: var(--bronze) }
.slot-4, .slot-5 { --c: var(--iron) }

.tag {
  display: inline-block;
  padding-left: 8px;
  border-left: 4px solid var(--c);
  color: var(--c);
  font-weight: 700; font-size: 1.05rem;
}
:root[data-theme="contrast"] .tag { color: #000; border-left-color: #000 }

/* ------------------------------------------------------------ Kennzahlen */

.sum {
  display: grid; grid-template-columns: 1fr 1fr 1.3fr; gap: 8px;
  margin-top: 14px; padding-top: 12px;
  border-top: 1.5px solid var(--frame);
}
.sum div { color: var(--dim); font-size: .9rem }
.sum b { display: block; font-size: 1.45rem; line-height: 1.1; color: var(--ink) }
.sum .ext b { color: var(--ok) }
.sum .own b { color: var(--own) }

/* ----------------------------------------------------------- Vorab-Block */

.lump {
  display: flex; gap: 14px; align-items: center;
  margin-top: 12px; padding: 12px;
  border: 1.5px solid var(--ok);
  background: rgba(127, 224, 173, .08);
}
:root[data-theme="light"] .lump { background: rgba(31, 138, 85, .06) }
:root[data-theme="writer"] .lump { background: rgba(61, 107, 55, .07) }
:root[data-theme="space"] .lump { background: rgba(57, 255, 159, .07); box-shadow: 0 0 14px rgba(57, 255, 159, .2) }
:root[data-theme="forge"] .lump { background: rgba(168, 204, 60, .08) }
:root[data-theme="contrast"] .lump { border-width: 2px; border-color: #000; background: none }
.lump[hidden] { display: none }
.lump-n { flex-shrink: 0; text-align: center; min-width: 6.5ch }
.lump-n b { display: block; font-size: 1.7rem; line-height: 1.05; color: var(--ok) }
.lump-n span { font-size: .8rem; color: var(--dim) }
.lump p { margin: 0; font-size: .95rem }

/* ----------------------------------------------------------- Ohne Skript */

/* Wird nur im <noscript> ausgeliefert, braucht also keinen eigenen Umschalter. */
.noscript { border-color: var(--warn) }
.noscript h2 { color: var(--warn) }
.noscript p { margin: 0 0 10px }
.noscript p:last-child { margin-bottom: 0 }
.noscript a { color: var(--warn) }

/* ------------------------------------------------------------- Hinweise */

.note {
  margin-top: 10px; padding: 10px;
  border: 1.5px dashed var(--warn);
  color: var(--warn);
  font-size: .95rem;
}
.note.man { border-color: var(--ok); color: var(--ok) }

/* Ein Wert, der nur gegengelesen werden will, ist keine Warnung: gleiche
   Form, aber die ruhige Schrift des Plans statt des Warngelbs. */
.note.chk { border-color: var(--frame); color: var(--ink) }
.note.chk .go { background: var(--btn); color: var(--btn-ink) }

/* Und ein hochgerechnetes P1 ist nicht einmal das: die Kurve des
   Zeitalters trifft, der Plan steht. Bleibt ueberhaupt etwas zu sagen,
   dann als Zeile unter dem Plan — ohne Rahmen, ohne Feld. Das Feld holt
   der Textknopf hervor, wenn jemand die Zahl wirklich gegenlesen will. */
.note.quiet { border: 0; padding: 0; color: var(--dim); font-size: .88rem }
.note.quiet .link { color: var(--ink) }
.note.quiet .go { background: var(--btn); color: var(--btn-ink) }
.note.quiet .in[hidden] { display: none }
.note .in { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px }
.note .in div { flex: 1 1 40% }
.note .in .go { flex: 1 1 100% }
.note .in label { display: block; font-size: .8rem; margin-bottom: 2px }
.note .go { font: inherit; font-weight: 600; cursor: pointer; background: var(--warn); color: var(--on-accent); border: 0; padding: 10px 14px }

.link { font: inherit; font-weight: 600; cursor: pointer; background: none; border: 0; color: inherit; text-decoration: underline; padding: 0 }
.warnline { color: var(--own); font-size: .95rem; margin-top: 8px }

/* ------------------------------------------------------------ Kopiertext */

.copy + .copy { margin-top: 14px }
.copy .t {
  font-size: .95rem;
  background: var(--field);
  border: 1px solid var(--grid);
  padding: 8px 10px;
  word-break: break-word;
  min-height: 2.6em;
}
:root[data-theme="contrast"] .copy .t { border: 2px solid #000 }
.copy button, .coll-copy {
  font: inherit; font-weight: 600; cursor: pointer;
  background: var(--btn); color: var(--btn-ink);
  border: 0; padding: 11px;
}
.copy button { width: 100%; margin-top: 6px }
.copy button.done, .coll-copy.done { background: var(--ok); color: var(--on-accent) }
.copy button:disabled { opacity: .45; cursor: default }

/* ------------------------------------------------------------- Sammlung */

/* Der dritte Kasten unter den beiden Kopierkaesten. Eine gestrichelte Linie
   trennt ihn ab: er gehoert zum Foerderchat, ist aber nicht noch eine
   Zeile, sondern das, was sich aus ihnen angesammelt hat. */
.coll { margin-top: 18px; border-top: 1.5px dashed var(--field-border); padding-top: 12px }
.coll[hidden] { display: none }

.coll-head { display: flex; align-items: baseline; gap: 8px }
.coll-head .l { margin: 0 }
.coll-badge {
  font-weight: 700; color: var(--gold);
  border: 1.5px solid var(--gold);
  padding: 0 6px; font-size: .82rem;
}

.coll-list { list-style: none; margin: 8px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px }
.coll-list li { display: flex; background: var(--field); border: 1px solid var(--grid) }
:root[data-theme="contrast"] .coll-list li { border: 2px solid #000 }

.coll-t { flex: 1; font-size: .95rem; padding: 8px 10px; word-break: break-word }
.coll-del {
  font: inherit; line-height: 1;
  background: transparent; color: var(--dim);
  border: 0; border-left: 1px solid var(--grid);
  padding: 4px 10px; cursor: pointer;
}
:root[data-theme="contrast"] .coll-del { color: #000; border-left: 2px solid #000 }
.coll-del:hover { color: var(--own) }

.coll-note { color: var(--dim); font-size: .82rem; margin: 8px 0 0 }
.coll-actions { display: flex; align-items: center; gap: 12px; margin-top: 8px }
.coll-copy { flex: 1 }

/* ----------------------------------------------------------------- Fuss */

.foot { color: var(--dim); font-size: .85rem; margin-top: 20px }
.foot p { margin: 0 0 10px }
.foot a { color: inherit }

.site-foot {
  max-width: 560px; margin: 0 auto; padding: 0 14px 40px;
  color: var(--dim); font-size: .82rem;
}
/* Auf den Rechtsseiten ist der Textblock breiter — der Fuss zieht mit. */
.site-foot.wide { max-width: 720px }
.site-foot hr { border: 0; border-top: 1.5px dashed var(--field-border); margin: 0 0 14px }
.site-foot p { margin: 0 0 10px }
.foot-links { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 14px }
.foot-links a { color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--field-border) }
.foot-links a:hover { border-bottom-color: var(--gold); color: var(--gold) }

/* ------------------------------------------------ Erklaerung und Fragen */

/* Zum Nachlesen unter dem Rechner. Die Kaesten sind .panel, stehen aber in
   einem eigenen Abschnitt: main > .panel meint nur die drei Rechnerteile. */
.info { margin-top: 26px }

/* Trennlinie mit Beschriftung: ab hier Lesestoff, nicht mehr Rechner. */
.info-sep {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 14px;
  color: var(--dim); font-size: .85rem; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
}
.info-sep::before, .info-sep::after {
  content: ""; flex: 1 1 0;
  border-top: 1.5px dashed var(--field-border);
}
.info .panel { line-height: 1.45 }
.info p { margin: 0 0 10px }
.info-steps { margin: 0; padding-left: 1.4em }
.info-steps li + li { margin-top: 6px }

/* Fragen als Aufklapper, Pfeil wie bei "Faktor oder FP je Platz". */
.faq details { border-top: 1.5px solid var(--field-border) }
.faq details:last-child { border-bottom: 1.5px solid var(--field-border) }
:root[data-theme="contrast"] .faq details { border-width: 2px 0 0 }
:root[data-theme="contrast"] .faq details:last-child { border-bottom-width: 2px }
.faq summary {
  display: flex; align-items: baseline; gap: 9px;
  padding: 9px 0; font-weight: 600;
  cursor: pointer; list-style: none;
}
.faq summary::-webkit-details-marker { display: none }
.faq summary::before {
  content: ""; flex: 0 0 auto;
  width: 0; height: 0;
  border: 5px solid transparent;
  border-left-color: var(--gold);
  transform: translateY(-1px);
  transition: transform .15s ease;
}
.faq details[open] summary::before { transform: rotate(90deg) translateX(-2px) }
.faq summary:focus-visible { outline: 3px solid var(--warn); outline-offset: 2px }
.faq details p { margin: 0 0 12px 19px; color: var(--dim) }
:root[data-theme="contrast"] .faq details p { color: var(--ink) }
@media (prefers-reduced-motion: reduce) { .faq summary::before { transition: none } }

/* ----------------------------------------------------- Rechtliche Seiten */

.legal { max-width: 720px }
.legal h1 { white-space: normal; font-size: clamp(1.8rem, 7vw, 2.4rem); margin-bottom: 8px }
.legal .lead { color: var(--dim); margin: 0 0 28px; font-size: .95rem }
.legal h2 { font-size: 1.1rem; font-weight: 600; margin: 28px 0 8px }
.legal p { margin: 0 0 10px }
.legal ul { margin: 0 0 10px; padding-left: 20px }
.legal li { margin-bottom: 4px }
.legal .muted { color: var(--dim) }
.legal a { color: var(--gold) }
:root[data-theme="contrast"] .legal a { color: #000 }

.card { border: 1.5px solid var(--field-border); background: var(--field); padding: 14px 16px; margin: 0 0 12px }
:root[data-theme="contrast"] .card { border-width: 2px }
.card p { margin: 0 0 2px }

.highlight { border: 1.5px solid var(--ok); border-left-width: 4px; background: rgba(127, 224, 173, .08); padding: 14px 16px; margin: 0 0 24px }
:root[data-theme="light"] .highlight { background: rgba(31, 138, 85, .06) }
:root[data-theme="writer"] .highlight { background: rgba(61, 107, 55, .07) }
:root[data-theme="contrast"] .highlight { border-width: 2px; border-left-width: 5px; border-color: #000; background: none }
.highlight p { margin: 0 }

.back { display: inline-block; margin-bottom: 18px; color: var(--ink); text-decoration: none; border-bottom: 1px solid var(--field-border) }
.back:hover { color: var(--gold); border-bottom-color: var(--gold) }

/* ------------------------------------------------------------ Easter Eggs */

/* 1) Freigabe-Stempel: erscheint, wenn ein Plan ohne Vorleistung aufgeht. */
.stamp {
  position: fixed;
  right: clamp(10px, 4vw, 40px);
  bottom: clamp(10px, 4vw, 40px);
  z-index: 3;
  pointer-events: none;
  display: grid; place-items: center;
  width: 118px; height: 118px;
  border: 3px double var(--ok);
  border-radius: 50%;
  color: var(--ok);
  font-weight: 700; font-size: .82rem; letter-spacing: .14em;
  text-transform: uppercase; text-align: center;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  transform: rotate(-14deg);
  animation: stamp-in 2.8s cubic-bezier(.2, 1.4, .3, 1) forwards;
}
.stamp span { display: block; font-size: .62rem; letter-spacing: .1em; color: var(--dim); margin-top: 3px }

@keyframes stamp-in {
  0%   { opacity: 0; transform: rotate(-30deg) scale(2.6) }
  14%  { opacity: 1; transform: rotate(-14deg) scale(1) }
  18%  { transform: rotate(-14deg) scale(1.07) }
  24%  { transform: rotate(-14deg) scale(1) }
  80%  { opacity: 1 }
  100% { opacity: 0; transform: rotate(-14deg) scale(1) }
}

/* 2) Blaupausen-Scan: ein Lichtstrahl laeuft einmal ueber die Seite. */
.scan {
  position: fixed; inset: 0;
  z-index: 4;
  pointer-events: none;
  background: linear-gradient(
    100deg,
    transparent 0%, transparent 42%,
    color-mix(in srgb, var(--gold) 55%, transparent) 50%,
    transparent 58%, transparent 100%
  );
  background-size: 260% 100%;
  animation: scan-sweep 1.5s cubic-bezier(.4, 0, .3, 1) forwards;
  mix-blend-mode: screen;
}
:root[data-theme="light"] .scan, :root[data-theme="contrast"] .scan,
:root[data-theme="writer"] .scan { mix-blend-mode: multiply }

@keyframes scan-sweep {
  from { background-position: 160% 0 }
  to   { background-position: -60% 0 }
}

/* 3) Plotter: die Wortmarke wird Buchstabe fuer Buchstabe neu "gezeichnet". */
.wordmark.plotting > span {
  display: inline-block;
  animation: plot-in .5s cubic-bezier(.2, .9, .3, 1.2) backwards;
  animation-delay: calc(var(--i) * 70ms);
}
@keyframes plot-in {
  from { opacity: 0; transform: translateY(-.22em) scaleY(.4); filter: blur(2px) }
  to   { opacity: 1; transform: none; filter: none }
}

/* Kurze Rueckmeldung am unteren Rand, wenn ein Easter Egg ausgeloest wurde. */
.toast {
  position: fixed;
  left: 50%; bottom: 18px;
  z-index: 5;
  transform: translateX(-50%);
  background: var(--btn); color: var(--btn-ink);
  font-weight: 600; font-size: .9rem; letter-spacing: .04em;
  padding: 8px 16px;
  border: 1.5px solid var(--frame);
  animation: toast-in .25s ease-out, toast-out .4s ease-in 2.1s forwards;
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 12px) } }
@keyframes toast-out { to { opacity: 0; transform: translate(-50%, 12px) } }

/* ------------------------------------------------- Telefon im Querformat */

/*
 * Quer ist Hoehe das knappe Gut und Breite im Ueberfluss da. Ohne diese
 * Regeln blieb main bei 560px stehen, links und rechts lag Platz brach,
 * und die Seite war knapp fuenf Bildschirme hoch.
 *
 * Die drei Bedingungen zusammen treffen Telefone im Querformat und sonst
 * nichts:
 *   orientation      selbsterklaerend, allein aber nutzlos — ein
 *                    Desktop-Fenster ist auch "landscape"
 *   max-height 520   Telefone quer sind 330-430px hoch, Tablets und
 *                    Desktops deutlich mehr; die haben Platz genug
 *   min-width 540    schliesst ein hochkant gehaltenes Telefon aus, dessen
 *                    Ansicht durch eine eingeblendete Tastatur flacher als
 *                    breit wuerde
 *
 * Alles hier drin kann im Hochformat nicht greifen. Das ist keine Frage der
 * Sorgfalt, sondern der Logik — und test/e2e/landscape.spec.js haelt es fest.
 */
@media (orientation: landscape) and (max-height: 520px) and (min-width: 540px) {

  main {
    max-width: 1000px;
    padding: 10px 16px 18px;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 0 16px;
    align-items: start;
  }

  /* Kopf und Fusstext laufen ueber beide Spalten. */
  main > header,
  main > noscript,
  main > .foot { grid-column: 1 / -1 }

  /* Links einstellen, rechts ablesen — ohne zu scrollen. */
  main > .panel:nth-of-type(1) { grid-column: 1; grid-row: 2 }   /* Bauwerk */
  main > .panel:nth-of-type(2) { grid-column: 2; grid-row: 2 / span 2 } /* Foerderplan */
  main > .panel:nth-of-type(3) { grid-column: 1; grid-row: 3 }   /* Foerderchat */

  /* Der Kopf stand hochkant untereinander; quer passt er in eine Zeile. */
  header {
    flex-direction: row;
    justify-content: space-between;
    align-items: flex-start;
    margin: 0 0 12px;
  }
  h1 { font-size: 1.9rem }
  /* Die Zeilenbreite von 42 Zeichen ist fuer schmale Geraete gedacht; quer
     steht daneben ohnehin nur der Themenwechsler. */
  .sub { font-size: .9rem; max-width: none }

  .panel { padding: 12px; margin-bottom: 12px }
  .panel h2 { margin-bottom: 8px }

  /* Stufe und Name passen quer wieder nebeneinander. */
  .row > div { flex: 1 1 130px }

  /* Quer ist die Hoehe das Knappe, nicht die Breite: der Streifen bekommt
     zwei Reihen statt drei und gibt gut 36px an den Rest zurueck. */
  .fav-list { max-height: calc(2 * var(--fav-row) + 6px) }

  .foot { margin-top: 8px }
  .site-foot { max-width: 1000px }

  /* Erklaerung und Fragen fallen quer weg: Hoehe ist hier das knappe Gut,
     und landscape.spec.js haelt die Seite unter festen Bildschirmzahlen.
     Hochkant und am Rechner stehen sie wie gewohnt da. */
  .info { display: none }
}

/* ------------------------------------------------------------ Feinschliff */

/* Runde Ecken und ein leiser Schatten fuer alles, was man anfasst oder
   liest. Die Werte kommen aus den Theme-Variablen --r, --r-sm, --shadow
   und --shadow-sm; hier steht nur, wer sie bekommt. */
.panel, .card { border-radius: var(--r); box-shadow: var(--shadow) }

select, input, .pick, .seg, .step, .modes,
.chips button, .fav-save, .fav-list li, .filter-hit, .slot-reset,
.copy .t, .copy button, .coll-copy, .coll-list li,
.lump, .note, .note .go, .highlight, .bar, .fac-gauge,
.safe, .coll-badge, .slots-badge { border-radius: var(--r-sm) }

/* Zusammengesetzte Felder: die inneren Flaechen (aktiver Knopf, gewaehlter
   Favorit, Balkenstuecke) sollen die runde Ecke nicht ueberragen. */
.seg, .modes, .fav-list li, .bar, .fac-gauge, .coll-list li { overflow: hidden }
.step input { border-radius: 0 }

/* Suchfeld und Loeschknopf bilden eine Einheit, sobald der Knopf da ist. */
.filter:has(button:not([hidden])) input { border-top-right-radius: 0; border-bottom-right-radius: 0 }
.filter button { border-radius: 0 var(--r-sm) var(--r-sm) 0 }

/* Gefuellte Flaechen heben sich ein wenig ab. */
.modes, .chips button.on, .copy button, .coll-copy, .note .go,
.fav-list li[aria-current="true"] { box-shadow: var(--shadow-sm) }

/* Weiche Uebergaenge und ein kleines Nachgeben beim Druecken. Die Stepper-
   Knoepfe bleiben aussen vor: an der Grenze soll ihr Zeichen sofort
   verblassen, nicht erst nach einer Blende. */
.modes button, .seg button, .chips button, .fav-save, .fav-go, .filter-hit,
.copy button, .coll-copy, .note .go, .slot-reset, select, input, .pick {
  transition: background-color .15s, border-color .15s, color .15s, box-shadow .15s, transform .1s;
}
.chips button:active, .fav-save:active, .copy button:active:not(:disabled),
.coll-copy:active, .note .go:active, .modes button:active { transform: translateY(1px) }
.chips button:hover:not(.on), .fav-save:hover { border-color: var(--frame) }
.copy button:hover:not(:disabled), .coll-copy:hover, .note .go:hover { filter: brightness(1.07) }
select:hover, input:hover:not(:focus), .pick:hover { border-color: var(--frame) }
.step input:hover { border-color: transparent }

/* ------------------------------------------------------- Themenwechsel */

/* Der Vorhang beim Umschalten (siehe revealTheme in app.js): die alte Seite
   bleibt stehen, die neue senkt sich mit weicher Kante von oben darueber.
   Die Maske ist 2,5-mal so hoch wie die Seite, oben deckend, unten
   durchsichtig; sie wandert von unten nach oben und gibt die neue Seite
   dabei von oben nach unten frei. Das Ueberblenden des Browsers ist
   abgeschaltet, sonst schienen beide Bilder halb durch. */
::view-transition-old(root) { animation: none; mix-blend-mode: normal }
::view-transition-new(root) {
  mix-blend-mode: normal;
  -webkit-mask-image: linear-gradient(to bottom, #000 40%, transparent 60%);
  mask-image: linear-gradient(to bottom, #000 40%, transparent 60%);
  -webkit-mask-size: 100% 250%;
  mask-size: 100% 250%;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  animation: theme-curtain .8s cubic-bezier(.65, 0, .35, 1) both;
}
@keyframes theme-curtain {
  from { -webkit-mask-position: 0 100%; mask-position: 0 100% }
  to   { -webkit-mask-position: 0 0; mask-position: 0 0 }
}

/* ------------------------------------------------------------- Animation */

@keyframes pop { from { transform: scale(.6); opacity: 0 } }
@keyframes flash { from { background: rgba(255, 211, 110, .28) } to { background: transparent } }
td.chg { animation: flash .7s ease-out }
:root[data-theme="contrast"] td.chg { animation: none }

/* Frisch gesammelt: sonst sieht man dem Kopierknopf nicht an, dass die
   Zeile zusaetzlich in der Sammlung gelandet ist. */
@keyframes coll-in { from { background: rgba(255, 211, 110, .28) } }
.coll-list li.fresh { animation: coll-in .7s ease-out }
:root[data-theme="contrast"] .coll-list li.fresh { animation: none }

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

@media (prefers-reduced-motion: reduce) {
  .bar i { transition: none }
  .safe, td.chg, .stamp, .scan, .wordmark.plotting > span, .toast { animation: none }
  .coll-list li.fresh { animation: none }
  .modes button, .seg button, .chips button, .fav-save, .fav-go, .filter-hit,
  .copy button, .coll-copy, .note .go, .slot-reset, select, input, .pick { transition: none }
  .chips button:active, .fav-save:active, .copy button:active,
  .coll-copy:active, .note .go:active, .modes button:active { transform: none }
  /* Der Stempel wuerde sonst dauerhaft stehen bleiben — er wird in diesem
     Modus gar nicht erst eingeblendet (siehe app.js). */
}
