/* ═══════════════════════════════════════════════════════════════════════════
   NestAnalysisSuite — globale Utility-Klassen
   ═══════════════════════════════════════════════════════════════════════════

   Ergänzt shared/tokens.css (reine Custom Properties, keine Selektoren) um
   eine zweite, ebenfalls geteilte Schicht: fertige, einzeln buchbare Klassen
   für die immer wiederkehrenden Signalfarben (positiv/negativ/warnend,
   immer-dunkle Fläche, Gelb-Highlight). Zweck ist eine Stelle, von der aus
   Farbe/Zustand auf allen Seiten und in allen vier Apps gleichzeitig
   steuerbar ist (Wunsch Martin, 03.08.2026, im Zuge des Hardcoding-Audits).

   BEWUSST NUR ADDITIV, keine Komponenten-Regeln: dieselbe Grenze wie in
   shared/tokens.css dokumentiert (".canvas-frame-Bug", 26.07.2026) -- eine
   frühere gemeinsame Komponenten-Datei hat unbemerkt alle drei Apps
   gleichzeitig zerschossen, weil Selektoren wie .canvas-frame in jeder App
   leicht unterschiedlich beansprucht wurden. Diese Datei stellt deshalb NUR
   eigene, sonst nirgends vergebene Klassennamen bereit (Präfix txt-/bg-) --
   sie überschreibt oder ergänzt keine bestehende Komponenten-Klasse
   (.master-frame, .canvas-frame, .primary-btn, …). Jede App bleibt frei,
   diese Klassen zu benutzen oder zu ignorieren.

   EINBINDEN (direkt nach shared/tokens.css, vor allem App-Eigenen):
     <link rel="stylesheet" href="../shared/tokens.css" />
     <link rel="stylesheet" href="../shared/global.css" />
     <link rel="stylesheet" href="../shared/ui-icons.css" />
     …

   Stand: 03.08.2026
   ═══════════════════════════════════════════════════════════════════════════ */

/* ─── Text ────────────────────────────────────────────────────────────── */
.txt-good        { color: var(--good); }
.txt-bad         { color: var(--bad); }
.txt-warn        { color: var(--warn); }
.txt-muted       { color: var(--muted); }
.txt-ink         { color: var(--ink); }
.txt-accent      { color: var(--accent); }
.txt-warn        { color: var(--warn); }
.txt-schuld      { color: var(--schuld); }

/* Text AUF --flaeche-invers bzw. auf dem Gelb-Highlight -- beide Flächen
   bleiben palettenunabhängig fest, ihr Text deshalb ebenso. */
.txt-invers       { color: var(--flaeche-invers-text); }
.txt-invers-muted { color: var(--flaeche-invers-text-muted); }
.txt-auf-gelb     { color: var(--flaeche-invers); }

/* ─── Fläche ──────────────────────────────────────────────────────────── */
.bg-good          { background:var(--good); }
.bg-bad           { background:var(--bad); }
.bg-warn          { background:var(--warn); }
.bg-schuld        { background:var(--schuld); }
.bg-ink           { background:var(--ink); }
.bg-invers        { background:var(--flaeche-invers); }
.bg-highlight-gelb{ background:var(--highlight-gelb); }
.bg-soft          { background:var(--soft); }
.bg-paper         { background:var(--paper); }

/* ─── Kombiniert (Fläche + passender Text in einer Klasse) ──────────────── */
.badge-invers  { background:var(--flaeche-invers); color: var(--flaeche-invers-text); }
.badge-gelb    { background:var(--highlight-gelb); color: var(--flaeche-invers); border-color:var(--highlight-gelb-rand); }


/* ═══════════════════════════════════════════════════════════════════════════
   Scrollbalken — eine Optik für die ganze Suite
   ═══════════════════════════════════════════════════════════════════════════

   Diese Regel stand bis 23.08.2026 nur in shared/seitenmenu.css und galt nur
   für .side-menu. Ergebnis: das Menü hatte einen schlanken Balken, jede
   scrollbare Karte daneben den groben Browser-Standard — zwei Optiken auf
   einem Bildschirm, und die auffälligere gehörte dem unwichtigeren Element.

   Jetzt gilt sie für alles. Die Sonderregel im Menü ist entfallen, statt
   sie danebenstehen zu lassen: zwei identische Regeln an zwei Orten sind
   der Anfang von zwei verschiedenen.

   Die Pfeile (Scrollbar-Buttons) sind AUSGEBLENDET statt verkleinert —
   WebKit kennt dafür keine schlanke Variante, nur volle Breite oder gar
   keine. Ein 6px schmaler Balken mit Pfeilklötzen in Originalgröße wäre
   kein Gewinn. Firefox bekommt dieselbe Optik über scrollbar-width und
   -color; dort gibt es ohnehin keine Pfeile serienmäßig.

   Farbe an --line/--muted, nicht am Akzent: der Balken soll sich einordnen,
   nicht auffallen. */
html { scrollbar-width: thin; scrollbar-color: var(--scrollbar-daumen) transparent; }
*::-webkit-scrollbar { width: 6px; height: 6px; }
*::-webkit-scrollbar-track { background:transparent; }
*::-webkit-scrollbar-thumb { background:var(--scrollbar-daumen); border-radius: var(--r-pill); }
*::-webkit-scrollbar-thumb:hover { background:var(--scrollbar-daumen-aktiv); }
*::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
*::-webkit-scrollbar-corner { background:transparent; }

/* ═══════════════════════════════════════════════════════════════════════════
   Schloss — gehört zu shared/schloss.js
   ═══════════════════════════════════════════════════════════════════════════
   Der Knopf sitzt im <summary> einer Karte, also in einer Zeile, die schon
   einen Klapp-Klick hat. `margin-left:auto` schiebt ihn nach rechts, weg
   vom Text — damit man nicht aus Versehen aufschließt, wenn man aufklappen
   wollte.

   Gesperrte Felder werden NICHT ausgegraut. Grau heißt in dieser Oberfläche
   "gerechnet, nicht eingebbar" (siehe .bg-soft) — und das ist etwas anderes
   als "geschützt". Ein gesperrtes Feld sieht normal aus und wehrt sich erst,
   wenn man hineinschreibt. */

.schloss-knopf {
  margin-left: auto;
  flex: 0 0 auto;
  border:1px solid var(--karten-linie);
  background:transparent;
  border-radius: var(--r-kreis);
  width: 30px; height: 30px;
  line-height: var(--lh-zahl);
  font-size: var(--fs-body);
  cursor: pointer;
  opacity: .55;
  transition: opacity .15s ease, border-color .15s ease;
}
.schloss-knopf:hover,
.schloss-knopf:focus-visible { opacity: 1; border-color:var(--accent); }
/* Das Schloss traegt seit dem 27.08.2026 ein SVG statt der Emojis 🔒/🔓
   (shared/ui-icons.js). Groesse und Farbe kommen damit aus dem CSS und nicht
   mehr vom Betriebssystem -- ein Emoji wird auf Windows, macOS und Android
   verschieden gezeichnet, mit eigener Strichstaerke und eigener Farbe. */
.schloss-knopf svg { width: 15px; height: 15px; display: block; }

/* Der Cursor ist die einzige Rückmeldung vor dem ersten Tastendruck —
   deshalb hier und nicht nur beim Schreibversuch. */
input.ist-gesperrt, textarea.ist-gesperrt { cursor: default; }
input.ist-gesperrt:focus, textarea.ist-gesperrt:focus {
  outline-color: var(--muted);
}

/* Damit das Schloss im <summary> überhaupt nach rechts kann. */
/* 17.09.2026: .canvas-frame dazu. Auf estate/project.html sind die fuenf
   Abschnitte seit Etappe 2 details.canvas-frame -- ihr summary ist der
   Abschnittskopf. Ohne diese Zeile faellt es auf display:list-item
   zurueck und das Schloss kann nicht nach rechts. */
details.card > summary,
details.canvas-frame > summary { display: flex; align-items: center; gap: var(--sp-2); }

/* ═══════════════════════════════════════════════════════════════════════════
   WIE ETWAS AUF DEN ZEIGER ANTWORTET — die eine Stelle
   ═══════════════════════════════════════════════════════════════════════════
   Angelegt am 25.08.2026 (Wunsch MWM: "eine Stelle, wo drinsteht, so stark
   soll das reagieren").

   VORHER: fünfzehn Regeln in fünf Dateien, jede mit eigenen Werten.
     .module-card    translateY(-4px) scale(1.035)  + 28px Glow
     .project-card   translateY(-4px) scale(1.035)  + 28px Glow
     .steuer-teaser  translateY(-3px) scale(1.012)  + 16px Glow
     .master-frame   translateY(-3px) scale(1.008)  + drei Lagen
     .teaser         translateY(-2px)               + 20px Glow
     .hero-value     scale(1.012)                   + 30px Glow
   Sechs Stärken für dieselbe Aussage. Auf den Unterseiten sprang es also
   anders als auf dem Hub, und niemand konnte sagen warum — weil die Antwort
   in fünf Dateien verteilt lag.

   JETZT: zwei Gesten, beide hier.

     FLÄCHEN (Karten, Rahmen, Kacheln)
       heben sich um --hebung, bekommen --shadow-hover und eine Linie.
       Kein scale: eine Karte, die ihre Größe ändert, verschiebt ihre
       Nachbarn im Blick mit. Bei .hero-value kommt dazu, dass sie der
       Ansatzpunkt der Herkunftsbänder ist — wächst sie, zittert die Grafik.

     ZEICHEN (Pfeile, Zurück-Links, Quellverweise)
       rücken um --zeichen-weg in ihre Richtung. Kein Schatten, keine Linie.

   NEUE KARTE ANLEGEN: den Selektor unten in die Liste eintragen, sonst
   nichts. Wer stattdessen eine eigene :hover-Regel mit rohen Werten
   schreibt, wird von check-tokens Punkt 17 abgewiesen.

   Der Farbton der Linie kommt aus --modulfarbe, falls das Element eine hat
   (Modulkarten setzen sie über data-farbe), sonst aus --hover-linie. Ein
   farbiger SCHATTEN ist bewusst nicht vorgesehen: er hing vorher an
   --accent, der Seitenfarbe, und ergab auf türkisen oder blauen Karten
   einen orangefarbenen Hof.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Flächen ──────────────────────────────────────────────────────────────── */
/* ═══ DER KLICKPFEIL — FORM UND GESTE AN EINEM ORT (09.09.2026, #131) ═══════
   Die BEWEGUNG des Pfeils stand seit jeher hier, seine FORM zweimal
   woanders: in css/styles.css und in estate/css/styles.css, Wort fuer Wort
   gleich. Beide Dateien tragen daneben einen Kommentar, der die Trennung
   erklaert — "die Geste zur Suite, die Form zur Seite". Nur stimmte sie
   nicht: die "Form zur Seite" war in beiden Seiten dieselbe.

   Auffallen konnte es nicht, weil die zwei Kopien NIE auf derselben Seite
   liegen: jedes Modul laedt sein eigenes css/styles.css. Zwei Kopien, die
   sich nie begegnen, laufen genau deshalb auseinander — es gibt keinen
   Moment, in dem der Unterschied sichtbar wuerde.

   Jetzt hier, neben den neun Regeln, die den Pfeil ohnehin bewegen. */
.oeffnen-pfeil {
  position: absolute; top: 14px; right: 16px;
  font-size: var(--fs-body); line-height: var(--lh-zahl); font-weight: var(--fw-normal);
  color: var(--muted); transition: transform .18s, color .18s;
  pointer-events: none;
}

.module-card,
.project-card,
.steuer-teaser,
.teaser,
.hero-value.reagiert,
/* KORREKTUR 25.08.2026: der Selektor lautete zuerst :has(.oeffnen-pfeil) --
   ohne Kind-Zeichen. :has() prueft ALLE NACHFAHREN, nicht nur die direkten
   Kinder. Auf dem Hub tragen die Wegweiser- und Modulkarten INNEN einen
   Pfeil, also traf die Regel auch dort: der ganze Gesamtvermoegens-Block hob
   sich beim Ueberfahren an -- genau das, was er nicht soll.
   Jetzt der volle Pfad. Der Pfeil muss in der KOPFZEILE dieses Frames sitzen,
   nicht irgendwo darin. Ein Pfeil auf einer Karte gehoert der Karte. */
.master-frame:has(> .section-heading > .oeffnen-pfeil) {
  transition: transform var(--hover-dauer) var(--hover-kurve),
              box-shadow var(--hover-dauer) var(--hover-kurve),
              border-color var(--hover-dauer) var(--hover-kurve);
}

.module-card:hover,       .module-card:focus-visible,
.project-card:hover,      .project-card:focus-within,
.steuer-teaser:hover,     .steuer-teaser:focus-visible,
.teaser:hover,            .teaser:focus-visible,
.master-frame:has(> .section-heading > .oeffnen-pfeil):hover,
.master-frame:has(> .section-heading > .oeffnen-pfeil):focus-within,
/* .hero-value hört auf die Klasse .haelt statt auf :hover — sie wird von
   js/baender.js gesetzt und wieder genommen. Grund: :hover endet an der
   Elementkante, die Bänder liegen aber weiter, während der Zeiger ihnen nach
   unten folgt. Zwei Dinge, die zusammengehören, brauchen einen Auslöser. */
.hero-value.reagiert.haelt,
.hero-value.reagiert:focus-visible,
/* Solange die Bänder liegen, zeigen ihre Zielkarten dieselbe Antwort — nicht
   weil der Zeiger auf ihnen steht, sondern weil sie gemeint sind. */
[data-baender="an"] .module-card {
  transform: translateY(var(--hebung));
  box-shadow: var(--shadow-hover);
  border-color:var(--modulfarbe, var(--hover-linie));
}.module-card:hover   .oeffnen-pfeil,
.teaser:hover        .oeffnen-pfeil,
.project-card:hover  .oeffnen-pfeil,
.master-frame:hover  .oeffnen-pfeil,
.steuer-teaser:hover .oeffnen-pfeil {
  transform: translate(var(--zeichen-weg), calc(var(--zeichen-weg) * -1));
}
.steuer-teaser:hover .go { transform: translateX(var(--zeichen-weg)); }
/* Auswahlfelder (Sortierung, Bereichsschalter) -- hierher umgezogen aus
   shared/ui-icons.css am 05.09.2026, weil der Fokusring ein Token wurde und
   check-tokens Zeigerantworten ausserhalb dieses Abschnitts meldet. */
select.secondary-btn:hover,
.sort-select:hover { border-color: var(--accent); color: var(--accent); }
select.secondary-btn:focus-visible,
.sort-select:focus-visible { outline: none; border-color: var(--accent); box-shadow: var(--fokus-ring); }
.eci-quelle:hover, .eci-quelle:focus-visible {
  transform: translate(var(--zeichen-weg), calc(var(--zeichen-weg) * -1));
}/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt die
   Rückmeldung über Schatten und Linie — die Verschiebung entfällt. Eine
   Antwort bleibt, nur ohne Weg. */
@media (prefers-reduced-motion: reduce) {
  :root { --hebung: 0px; --zeichen-weg: 0px; }
}

/* ─── Zahlenfelder ohne Rauf-/Runter-Pfeile ──────────────────────────────────
   25.08.2026, Wunsch MWM: "die will ich nicht sehen".

   Die Pfeile sind eine Zugabe des Browsers, kein Element unseres Entwurfs.
   Sie erscheinen nur beim Überfahren, verschieben dabei den Text nach links
   und sehen in jedem Browser anders aus — drei Gründe, aus denen sie in einer
   Oberfläche mit festen Feldbreiten mehr stören als helfen.

   Was sie konnten, kann die Tastatur weiterhin: Pfeil hoch und runter zählen
   im Feld hoch und runter, unabhängig von dieser Regel.

   Zwei Schreibweisen, weil die Browser sich hier nie geeinigt haben:
   WebKit/Blink kennen die Pseudoelemente, Firefox nur appearance. */
input[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
}


/* ═══ LAGE-UTILITIES (05.09.2026, Hardcoding-Audit #2) ═══════════════════════
   188 style="…"-Attribute im Markup, 122 davon auf drei Seiten. Die
   haeufigsten: margin-top:24px (21x), font-weight:600 (17x),
   text-align:right (9x). Inline schlaegt jede Kaskade -- Dunkelmodus und
   Schriftrollen kamen dort nicht hin, und kein Waechter liest style="".

   Sieben Klassen fuer die sieben haeufigsten Faelle. Bewusst wenige: eine
   Utility je Zahl auf der Skala waere ein zweites Inline. Wer etwas anderes
   braucht, schreibt eine Bauform-Regel, keine achte Utility. */
/* .hidden stand in vier Dateien identisch, .version-tag in vieren mit zwei
   Deckkraften (Hub .5, Module .65) und mit oder ohne Laufweite. Seit
   09.09.2026 hier, Modulfassung -- der Hub war der Ausreisser. */
.hidden { display: none !important; }

/* ═══ DAS ATTRIBUT hidden MUSS AUCH VERSTECKEN  (17.09.2026) ════════════════
   MWM: "wenn ich Liste einstelle, verschwinden die Kacheln nicht."

   DER GRUND ist eine Eigenheit von HTML, die man einmal im Leben trifft und
   danach nie wieder vergisst: `hidden` setzt display:none nur im
   Browser-Standardstylesheet. Jede eigene Regel mit einer display-Angabe
   schlaegt es, schon bei gleicher Spezifitaet -- und `.project-grid` traegt
   display:grid. Das Element bleibt sichtbar, obwohl im DOM hidden steht.
   Der Fehler sieht dabei nicht nach Fehler aus: die Eigenschaft ist gesetzt,
   der Knopf hat reagiert, nur das Bild folgt nicht.

   WARUM !important, WO WIR SIE SONST ABBAUEN: die Aussage "dieses Element ist
   nicht da" ist keine Gestaltungsfrage, die eine andere Regel ueberstimmen
   duerfte. Genau dafuer ist !important gedacht, und genau so wird es eine
   Zeile darueber fuer .hidden schon benutzt -- dieselbe Entscheidung, nur
   bisher nicht fuer das Attribut mitgetroffen.

   ES ERSETZT DREI EINZELREGELN: shared/seitenmenu.css (.sm-klappraum[hidden])
   und css/farben.css (#fcDiff[hidden]) hatten je eine eigene Fassung
   desselben Gedankens. Die dritte waere gerade fuer .project-grid dazu-
   gekommen. Eine Regel statt vier. */
[hidden] { display: none !important; }
.version-tag {
  position: fixed; left: 16px; bottom: 12px;
  font-size: var(--fs-mini); color: var(--ink); letter-spacing: var(--ls-versal-eng);
  opacity: .65; pointer-events: none; z-index: var(--z-schweben);
}
.oben-2 { margin-top: var(--sp-2); }
.oben-4 { margin-top: var(--sp-4); }
.oben-5 { margin-top: var(--sp-5); }
.oben-6 { margin-top: var(--sp-6); }
.unten-2 { margin-bottom: var(--sp-2); }
.rechts { text-align: right; }
.mitte  { text-align: center; }
.halbfett { font-weight: var(--fw-halbfett); }


/* ═══ EINGABEFELDER — DIE GRUNDFLAECHE (05.09.2026, Gegenprobe) ══════════════
   Gefunden beim Nachsehen im Dunkelmodus: auf inout/index.html trugen 51
   Felder --paper (#363B45, dunkel) und 43 daneben reines Weiss. Auf DERSELBEN
   Seite, in derselben Tabelle.

   Der Grund war kein Fehler, sondern eine Luecke: fuer die 43 gab es
   ueberhaupt KEINE Regel. Sie zeigten den Browser-Standard, und der kennt
   keine Palette. Gemessen mit einer Abfrage aller Stylesheets: null Treffer
   fuer background auf diesen Elementen.

   Deshalb hier, auf Elementebene und damit mit der niedrigsten Spezifitaet,
   die es gibt -- jede bestehende Klassenregel gewinnt weiterhin. Es ist ein
   Boden, keine Vorschrift.

   Checkbox und Radio bleiben aussen vor: sie zeichnen sich selbst, und ein
   Hintergrund darauf macht sie in manchen Browsern unsichtbar. */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select,
textarea {
  background-color: var(--paper);
  color: var(--ink);
  border: 1px solid var(--karten-linie);
  border-radius: var(--r-bedien);
  font-family: inherit;
}


/* ═══ KLAPPKASTEN — eine Bauform fuer die ganze Suite (17.09.2026) ═════════
   Stand bis heute in estate/css/calculator.css, also in einer Datei, die NUR
   die vier Estate-Seiten laden. Auf farben.html habe ich sie trotzdem
   benutzt -- die Klasse stand im Markup, das CSS dazu gab es dort nicht, und
   der Kasten sass nackt im Frame: keine Flaeche, kein Rand, ein
   Browser-Standardpfeil. Mein Fehler, und einer der unsichtbaren Sorte: das
   Markup war richtig, die Klasse hiess richtig, nur galt sie nicht.

   Deshalb hier in shared/global.css, das jede Seite laedt. Eine Klappe ist
   keine Estate-Eigenheit -- sie ist dieselbe Handlung auf jeder Seite.
   Die estate-eigenen Varianten (.rent-growth-vorschau und die Hausgeld-
   Klappen) bleiben in calculator.css, sie tragen dort Zusatzregeln. */
.klapp-feld {
  background: rgba(var(--ink-rgb), var(--wash-hauch));
  border: 1px solid rgba(var(--ink-rgb), var(--wash-leicht));
  border-radius: var(--r-bedien);
  box-shadow: none;
}
.klapp-feld > summary {
  cursor: pointer;
  list-style: none;
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  font-weight: var(--fw-mittel);
  color: var(--ink);
}
.klapp-feld > summary::-webkit-details-marker { display: none; }
/* Derselbe Chevron wie bei .card und .canvas-frame -- shared/ui-icons.css
   traegt ihn dort. Hier steht er nochmal, weil .klapp-feld kein .card ist
   und die dortige Regel nicht greift. Gleiche Zeichen, gleiche Drehung,
   gleiche Dauer: wer beides sieht, soll keinen Unterschied bemerken. */
.klapp-feld > summary::before {
  content: "▸"; display: inline-block;
  transition: transform .15s ease;
  color: var(--muted);
}
.klapp-feld[open] > summary::before { transform: rotate(90deg); }
.klapp-feld > summary:hover::before { color: var(--ink); }
