/* Die Gestaltung der Verwaltung -- handgeschrieben, kein Werkzeug, kein Bauweg.
   Entschieden am 10.08.2026; `0031` Festlegung 1 bleibt unangetastet.

   ERHOBEN, NICHT NACHEMPFUNDEN. Jede Angabe stammt aus der v1-Kopie, Stand
   `9d1c701c` (Feature-Zweig, kein Release). Fundstelle je Abschnitt; Pfade
   relativ zu /home/coder/php-reference/html/.

   NICHT NACHMESSBAR (AGENTS.md §7): `tailwind.config.js` liegt nicht bei -- und
   sie kann es nicht, weil v1 Tailwind 4 benutzt und seine Werte in der CSS-Datei
   selbst fuehrt (`@theme` in resources/css/app.css:11-14). Die Frage nach
   "eigenen Werten statt der Vorgaben" ist damit beantwortet und nicht offen. */

/* ─── Token (Aystos Styleguide) ────────────────────────────────────────────
   Woertlich aus resources/css/app.css:17-31. Kein Wert ist hier erfunden. */

:root {
  --ui-accent: #169b96;
  --ui-accent-dark: #0f7a75;
  --ui-bg-soft: #eff3f6;
  --ui-bg-card: #ffffff;
  --ui-border: #d8e1e8;
  --ui-border-strong: #b8c8d4;
  --ui-text: #1f2d3d;
  --ui-text-soft: #5a6b7b;
  --ui-ok: #1f9d55;
  --ui-warn: #cf7d10;
  --ui-bad: #cd3f3f;
  --ui-shadow: 0 14px 30px rgba(15, 34, 58, 0.08);

  /* Abstufung statt Einzelwerte. Abgelesen an den wiederkehrenden Werten in
     app.css: 4 / 6 / 8 / 10 / 12 / 14 / 18 / 22 px. */
  --ui-s1: 4px;
  --ui-s2: 6px;
  --ui-s3: 8px;
  --ui-s4: 12px;
  --ui-s5: 14px;
  --ui-s6: 18px;
  --ui-s7: 22px;

  --ui-r-sm: 9px;
  --ui-r-md: 12px;
  --ui-r-lg: 16px;
  --ui-r-pill: 999px;

  /* Schrift: app.css:12-13. Der Bestand laedt Figtree von fonts.bunny.net;
     wir laden nichts nach -- s. Bericht, bewusste Abweichung. Der Stapel ist
     derselbe, nur ohne den externen Abruf. */
  --ui-font: "Figtree", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
    "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
  /* Woertlich aus app.css:385 und 398 -- der Bestand setzt ihn an zwei
     Stellen gleich. Nicht die Tailwind-Vorgabe: `@theme` uebergeht
     `--font-mono` nicht, aber diese zwei Regeln schreiben ihn aus. */
  --ui-font-mono: "SF Mono", "Fira Code", ui-monospace, monospace;

  --ui-sidebar: 16rem; /* w-64, dashboard.blade.php:15 */
}

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

/* ─── Flaeche ──────────────────────────────────────────────────────────────
   dashboard.blade.php:12 -- der Radialverlauf ueber der weichen Flaeche. */

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--ui-font);
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--ui-text);
  background:
    radial-gradient(ellipse 90% 40% at 50% 0%, rgba(22, 155, 150, 0.06) 0%, transparent 100%),
    var(--ui-bg-soft);
}

a {
  color: var(--ui-accent-dark);
}

code,
pre {
  font-family: var(--ui-font-mono);
  font-size: 0.85em;
}

pre.prompt {
  white-space: pre-wrap;
  word-break: break-word;
}

/* ─── Aufbau: Seitenleiste und Inhalt ──────────────────────────────────────
   dashboard.blade.php:13-15 -- flex, Leiste fest, Inhalt scrollt. */

.ui-app {
  display: flex;
  min-height: 100vh;
}

.ui-aside {
  width: var(--ui-sidebar);
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(8px);
  border-right: 1px solid var(--ui-border);
}

.ui-shell {
  flex: 1;
  max-width: 1280px;
  margin: 0 auto;
  padding: var(--ui-s7) 24px 40px;
  width: 100%;
}

/* ─── Wortmarke ────────────────────────────────────────────────────────────
   dashboard.blade.php:17-22 -- oben links, in einem abgesetzten Feld.
   `RAG` im Akzent, der Zusatz weich. app.css:70-79 traegt die Groessen. */

.ui-brand {
  display: flex;
  align-items: center;
  gap: var(--ui-s3);
  padding: var(--ui-s5);
  border-bottom: 1px solid var(--ui-border);
}

.ui-brand-mark {
  font-weight: 700;
  font-size: 1rem;
  color: var(--ui-accent);
  text-decoration: none;
}

.ui-brand-sub {
  font-weight: 400;
  font-size: 0.78rem;
  color: var(--ui-text-soft);
}

/* ─── Navigation ───────────────────────────────────────────────────────────
   app.css:80-116 (.ui-nav-link) und 118-129 (.ui-sidebar). */

.ui-nav {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--ui-s1);
  padding: var(--ui-s4);
}

.ui-nav-link {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-s3);
  width: 100%;
  justify-content: flex-start;
  min-height: 32px;
  padding: 0 var(--ui-s4);
  border-radius: 10px;
  font-weight: 600;
  font-size: 0.86rem;
  color: var(--ui-text-soft);
  text-decoration: none;
  border: 1px solid transparent;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.ui-nav-link:hover {
  background: #f8fbfd;
  border-color: var(--ui-border-strong);
  color: var(--ui-text);
}

.ui-nav-link.is-active {
  color: #fff;
  background: linear-gradient(135deg, var(--ui-accent), var(--ui-accent-dark));
  border-color: transparent;
}

.ui-nav-link svg {
  width: 1.15rem;
  height: 1.15rem;
  flex-shrink: 0;
}

.ui-nav-group {
  margin-top: var(--ui-s4);
  padding: 0 var(--ui-s4) var(--ui-s2);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 700;
  color: #667a8d;
}

/* ─── Fussbereich der Leiste ───────────────────────────────────────────────
   dashboard.blade.php:126-140 -- Fassung, dann angemeldeter Nutzer, dann
   Abmelden; je Block eine Trennlinie darueber. */

.ui-aside-foot {
  padding: var(--ui-s5);
  border-top: 1px solid var(--ui-border);
}

.ui-aside-foot dl {
  margin: 0 0 var(--ui-s4);
  padding-bottom: var(--ui-s4);
  border-bottom: 1px solid var(--ui-border);
}

.ui-aside-foot dt {
  font-size: 0.72rem;
  color: var(--ui-text-soft);
  margin-bottom: var(--ui-s1);
}

.ui-aside-foot dd {
  margin: 0 0 var(--ui-s4);
  font-size: 0.86rem;
  overflow-wrap: anywhere;
}

.ui-aside-foot dd:last-child {
  margin-bottom: 0;
}

.ui-version {
  font-family: var(--ui-font-mono);
}

/* ─── Ueberschriften ───────────────────────────────────────────────────────
   app.css:56-63 und 138-146 -- eng gesperrt, 700. */

h1,
h2,
h3 {
  letter-spacing: -0.02em;
  font-weight: 700;
}

h1 {
  font-size: 1.15rem;
  margin: 0 0 var(--ui-s6);
}

h2 {
  font-size: 1.05rem;
  margin: 0 0 var(--ui-s4);
}

h3 {
  font-size: 0.92rem;
  margin: var(--ui-s7) 0 var(--ui-s3);
}

/* Bezeichner stehen in Festbreite -- v1 setzt dafuer `font-mono`
   (query-authoring/index.blade.php:76 an `query_id`).

   OHNE STUFE DAVOR (29.08.2026). Die Regel las `h3.ui-ident`, beide Leser
   schreiben ein `h2` -- die Festbreite griff auf keiner der beiden Flaechen.
   Die Klasse sagt, WAS dort steht (ein Bezeichner), nicht in welcher
   Ueberschriftsstufe; die Stufe gehoert nicht in die Bedingung. */
.ui-ident {
  font-family: var(--ui-font-mono);
  font-weight: 600;
  letter-spacing: 0;
}

/* ─── Tafel ────────────────────────────────────────────────────────────────
   app.css:130-148 (.ui-panel). */

.ui-panel {
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  padding: var(--ui-s5);
  margin-bottom: var(--ui-s5);
}

.ui-panel > :last-child {
  margin-bottom: 0;
}

/* ─── Schaltflaechen ───────────────────────────────────────────────────────
   app.css:180-230. */

button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ui-s2);
  min-height: 34px;
  padding: 0 var(--ui-s4);
  border-radius: var(--ui-r-sm);
  border: 1px solid var(--ui-border-strong);
  background: #fff;
  color: var(--ui-text);
  font-family: inherit;
  font-weight: 600;
  font-size: 0.84rem;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}

button:hover {
  border-color: #98adb8;
  background: #f8fbfd;
}

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

button.ui-primary {
  border-color: transparent;
  color: #fff;
  background: linear-gradient(135deg, var(--ui-accent), var(--ui-accent-dark));
}

button.ui-primary:hover {
  filter: brightness(1.06);
  background: linear-gradient(135deg, var(--ui-accent), var(--ui-accent-dark));
}

td button {
  min-height: 28px;
  padding: 0 10px;
  font-size: 0.78rem;
}

.knopfreihe {
  display: flex;
  gap: var(--ui-s4);
  align-items: center;
  margin-top: var(--ui-s6);
}

/* Ein zerstoerender Vorgang bekommt einen eigenen Rahmen -- nicht eine rote
   Schaltflaeche. Die Farbe allein sagt nur *anders*; der abgesetzte Block sagt,
   dass hier etwas anderes geschieht als in der Knopfreihe darueber, und der Satz
   darin sagt was. `--ui-bad` traegt den Rand, nicht die Flaeche: Ein grosser
   roter Block liest sich als Fehler, und ein Fehler ist es nicht. */

.zerstoerend {
  margin-top: var(--ui-s6);
  padding: var(--ui-s6);
  border: 1px solid #eacbcb;
  border-left: 3px solid var(--ui-bad);
  border-radius: var(--ui-r-sm);
  background: #fdeeee;
}

.zerstoerend .hinweis {
  margin-top: 0;
}

/* ─── Marken ───────────────────────────────────────────────────────────────
   app.css:232-262 (.ui-pill). Zustaende bekommen die Farbe des Zustands. */

.ui-pill {
  display: inline-flex;
  align-items: center;
  border-radius: var(--ui-r-pill);
  padding: 2px 9px;
  font-size: 0.75rem;
  font-weight: 700;
  border: 1px solid #c9d7e2;
  color: #345066;
  background: #f3f8fb;
}

.ui-pill.ok {
  border-color: #c8ead8;
  color: #1f7d48;
  background: #eef9f2;
}

.ui-pill.off {
  border-color: #eacbcb;
  color: #a33939;
  background: #fdeeee;
}

.ui-pill.warn {
  border-color: #e8d5b8;
  color: #9a6410;
  background: #fef9f0;
}

/* ─── Felder ───────────────────────────────────────────────────────────────
   app.css:290-330 (.ui-field).

   RANG 2 -- DER FELDNAME, IN NORMALER SCHREIBUNG. Bis zum 22.08.2026 bekam
   JEDE Beschriftung Versalien, klein und gesperrt. Das Muster stammt aus v1 --
   dort traegt es aber nur kurze Systemwoerter (NAME, SLUG, STATUS), waehrend
   lange Feldnamen in gemischter Schreibung stehen ("Cross-Encoder Reranking").
   Uebernommen war das Muster, nicht seine Grenze.

   Versalien tilgen die Wortbilder, an denen schnelles Lesen haengt. Bei
   "Navigationsfragen nicht dem Classifier vorlegen" -- 45 Zeichen, eine
   Doppelnegation, mit ja/nein darunter -- wurde die Beschriftung damit zur
   Stolperstelle genau dort, wo sie die Bedeutung allein traegt.

   WAS VERSALIEN BEHAELT, IST KURZ UND SYSTEMHAFT: Tabellenkoepfe,
   Navigationsgruppen, Kartenbeschriftungen, die drei Woerter der
   Referenzzeile. */

label {
  display: block;
  margin-top: var(--ui-s5);
  font-size: 0.88rem;
  letter-spacing: 0;
  color: var(--ui-text);
  font-weight: 600;
}

/* DIE REGEL ZAEHLT AUF, WAS KEIN EINGABEFELD IST (25.08.2026). Vorher nannte
   sie die vier Typen, die es damals gab -- **eine Liste, die aufzaehlt, was
   dazugehoert, altert bei jedem neuen Feld**, und sie hat es still getan: vier
   `type="url"` und das Suchfeld der Projektliste standen ohne Rahmen, Radius
   und Innenabstand zwischen Feldern, die alle drei hatten. Die Ausschlussliste
   dagegen ist geschlossen: Knopf, Kaestchen, Punkt, verborgenes Feld, Datei,
   Schieber, Farbwaehler. Alles andere ist ein Textfeld -- auch ein `type`, den
   HTML erst noch bekommt. */
input:not([type="submit"], [type="button"], [type="reset"], [type="checkbox"],
           [type="radio"], [type="hidden"], [type="image"], [type="file"],
           [type="range"], [type="color"]),
select,
textarea {
  width: 100%;
  border: 1px solid var(--ui-border);
  border-radius: 10px;
  background: #fff;
  color: var(--ui-text);
  padding: 9px 11px;
  font-family: inherit;
  font-size: 0.9rem;
  outline: none;
  margin-top: var(--ui-s2);
  transition: border-color 0.15s, box-shadow 0.15s;
}

/* `search` traegt in WebKit eine eigene Bauform samt Loeschkreuz, die sich
   sonst gegen die Regel darueber durchsetzt. `select` bleibt ausgenommen --
   ohne seine Bauform verloere es den Auswahlpfeil. */
input[type="search"] {
  appearance: none;
}

input[type="search"]::-webkit-search-cancel-button {
  -webkit-appearance: none;
}

input:focus,
select:focus,
textarea:focus {
  border-color: var(--ui-accent);
  box-shadow: 0 0 0 3px rgba(22, 155, 150, 0.16);
}

fieldset {
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  padding: var(--ui-s4) var(--ui-s5) var(--ui-s6);
  margin: 0 0 var(--ui-s5);
}

legend {
  /* Ueber .feld-name (0.92rem/600). Vorher stand sie darunter -- die Blockgruppe
     war der kleinste ueberschriftartige Text in ihrem eigenen Block. */
  font-weight: 700;
  font-size: 1.02rem;
  padding: 0 var(--ui-s2);
}

/* Auswahlreihen: Beschriftung daneben, nicht darunter. */
/* **Die Umkehrung, berichtigt** (b, 25.08.2026): 14 px trennten zwei
   gleichrangige Optionen weiter, als 10 px Beschriftung und Steuerelement
   trennten -- also weiter, als zwei verschiedene Raenge auseinanderlagen. */
.wahl {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-s3) var(--ui-s4);
  margin-top: 0;
}

.wahl label {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-s2);
  margin: 0;
  font-size: 0.86rem;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  color: var(--ui-text);
}

.wahl input[type="radio"] {
  accent-color: var(--ui-accent);
  margin: 0;
}

/* Eine gesperrte Schaltflaechengruppe -- der Text gehoert zum Zustand, nicht
   nur der Knopf. Ohne diese Regel steht ein voll ausgezeichnetes "ja" neben
   einem ausgegrauten Punkt, und die Gruppe liest sich als halb bedienbar.
   SEIT DEM 24.08.2026 IST DAS DER REGELFALL: Jedes wirkungslose Feld ist
   gesperrt, und die Radiogruppen des Anfrageverstehens und des Antwortpfads
   sind die haeufigste Form davon.
   `:has()` statt einer Klasse aus der Vorlage: Der Zustand steht am
   Steuerelement, das der Server setzt -- eine zweite Klasse daneben waere
   dieselbe Auskunft ein zweites Mal, und sie koennte auseinanderlaufen. */
.wahl label:has(input:disabled) {
  color: var(--ui-text-soft);
  cursor: not-allowed;
}

.wahl select {
  /* Nicht `width: auto` allein: Sonst nimmt das Feld die Breite seiner
     laengsten Option und schneidet sie ab. */
  width: auto;
  min-width: 12rem;
  max-width: 100%;
  margin-top: 0;
}

/* ─── Die Feldzeile: vier Raenge, vier Mittel ──────────────────────────────
   Abgenommen vom Auftraggeber am 22.08.2026. Ein Feld beantwortet vier Fragen,
   und sie sind nicht gleich wichtig:

     1  Was gilt?          rechte Spalte, feste Position, Festbreite, Akzent
     2  Was ist es?        links, halbfett, normale Schreibung
     3  Was kann ich tun?  eigene Zeile darunter, feste Breite je Typ
     4  Warum?             darunter, begrenzte Zeilenlaenge

   DIE EINE ENTSCHEIDUNG STEHT IN RANG 1: DER GELTENDE WERT STEHT RECHTS, AUF
   EINER LINIE, IMMER. Wer wissen will, was ein Projekt tut, liest EINE SPALTE
   von oben nach unten und muss kein einziges Label lesen. Bis dahin stand
   dieselbe Auskunft als "gilt: ja (Herkunft: Default)" im KLEINSTEN Grad der
   Seite, waehrend die Beschriftung darueber in Versalien schrie -- die
   wichtigste Angabe im schwaechsten Rang, der Verwaltungszustand im
   staerksten.

   WARUM EINE FESTE POSITION UND NICHT NUR EIN GROESSERER GRAD. Bei fuenfzehn
   Feldern untereinander verschwimmt jede Abstufung, die allein auf der
   Schriftgroesse beruht. Eine Kante, an der das Auge entlanglaeuft,
   verschwimmt nicht. */

/* DREI SPALTEN, NICHT ZWEI (B-1, 25.08.2026) -- der billigste Griff der ganzen
   Durchsicht, und der Befund dahinter widerspricht dem ersten Eindruck: **Der
   Reiter *Suche* war nicht zu lang, er war zu schmal.** Steuerelement (hoechstens
   544 px), Hilfesatz (44 ch, rund 295 px) und Dreigespann stapelten
   untereinander in einer 1232 px breiten Karte; rechts lagen je Zeile rund
   600 px Nichts, und die Wertspalte stand am anderen Ende davon. Ein Feld kostete
   187 bis 215 px und benutzte 44 % seiner Breite.

   Der Hilfesatz steht jetzt **neben** dem Steuerelement statt darunter. Seine
   Zeilenlaenge begrenzt er nicht mehr selbst -- das tut die mittlere Spalte, und
   sie ist der Grund, warum `max-width` an `.feld-hilfe` faellt.

   DIE SPALTEN, UND WARUM GENAU DIESE: `34rem` ist die Breite, die
   `.feld-steuer` seit jeher fuer Text- und Auswahlfelder haelt -- die Spalte
   erfindet keine Zahl, sie liest die vorhandene. `9rem` traegt Wert und
   Herkunft; laenger wird die Zelle nur bei Lane-Listen, und die brechen um.
   Dazwischen der Rest. */
.feld {
  display: grid;
  grid-template-columns: minmax(0, 34rem) minmax(0, 1fr) 9rem;
  gap: var(--ui-s4) var(--ui-s7);
  align-items: start;
  /* ABSTAENDE, BERICHTIGT (b), 25.08.2026: Der Auftraggeber hat sie als zu eng
     beanstandet, und die Messung gab ihm recht -- mit einer Umkehrung als
     eigentlichem Fehler. `.wahl { gap: 14px }` trennte zwei **gleichrangige**
     Optionen weiter, als 10 px zwei **verschiedene Raenge** trennten. Statt
     sechs Werten gelten jetzt zwei Verhaeltnisse: innerhalb eines Feldes
     hoechstens 18 px (`--ui-s6`, hier als Zeilenabstand `--ui-s4`), zwischen
     zwei Feldern das Doppelte. */
  padding: var(--ui-s6) 0;
  border-bottom: 1px solid #edf2f6;
}

.feld:last-child {
  border-bottom: none;
}

/* Zwei Zellen liegen nebeneinander, alles Weitere ueber die volle Breite --
   als Regel und nicht je Klasse: Ein spaeter dazukommendes Kind soll nicht
   still in die Wertspalte rutschen. */
.feld > * {
  grid-column: 1 / -1;
}

/* Der Name steht ueber Steuerelement und Hilfe, der Wert rechts daneben in
   derselben Zeile -- **was heisst das Feld, und was gilt gerade.** */
.feld > .feld-name {
  grid-column: 1 / 3;
}

.feld > .feld-wert {
  grid-column: 3;
}

/* Zweite Zeile: bedient wird links, erklaert wird rechts daneben. */
.feld > .feld-steuer {
  grid-column: 1;
}

.feld > .feld-hilfe {
  grid-column: 2;
}

.feld-name {
  display: block;
  margin: 0;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ui-text);
  line-height: 1.35;
}

.feld-wert {
  font-family: var(--ui-font-mono);
  font-size: 0.9rem;
  font-weight: 500;
  color: var(--ui-accent-dark);
  text-align: right;
  /* Der Entwurf setzt hier `white-space: nowrap`. Seine Beispiele sind kurz
     ("1", "nein", "aus"); in dieser Maske stehen auch Lane-Listen und Slugs in
     der Spalte, und eine unumbrechbare Zeile schoebe die Karte auf. Die Kante,
     an der das Auge entlanglaeuft, traegt `text-align`, nicht `nowrap`. */
  overflow-wrap: anywhere;
}

/* Die Herkunft ist eine Nebenzeile des Wertes, keine zweite Angabe daneben --
   sie beantwortet "woher", nachdem der Wert "was" beantwortet hat. */
.feld-wert .quelle {
  display: block;
  margin-top: 2px;
  font-family: var(--ui-font);
  font-size: 0.74rem;
  font-weight: 400;
  color: var(--ui-text-soft);
}

.feld-steuer {
  margin-top: var(--ui-s1);
}

.feld-steuer > :first-child {
  margin-top: 0;
}

/* Rang 3: feste Breiten je Typ. Ein Zahlenfeld, das so breit ist wie ein
   Adressfeld, behauptet Platz, den es nicht braucht. Dieselbe Umkehrung wie
   oben: `number` ist der Sonderfall, alles andere bekommt die Textfeldbreite.
   Die alte Liste nannte `text` und `password` -- ein `type="url"` waere hier
   in voller Kartenbreite gelaufen. */
.feld-steuer input:not([type="number"], [type="submit"], [type="button"],
                      [type="reset"], [type="checkbox"], [type="radio"],
                      [type="hidden"], [type="image"], [type="file"],
                      [type="range"], [type="color"]),
.feld-steuer select {
  /* 22rem passt fuer Woerter und Kennungen. Adressen und Kommalisten sind
     regelmaessig laenger als der Kasten -- derselbe Einwand, mit dem die
     Wertspalte auf `nowrap` verzichtet, hier auf die Breite angewandt. */
  max-width: 34rem;
}

.feld-steuer input[type="number"] {
  max-width: 9rem;
}

/* Rang 4: ein Satz, in lesbarer Zeilenlaenge. Gemessen an den Bildschirmfotos
   liefen Hilfeabsaetze ueber die volle Kartenbreite -- bis ~190 Zeichen je
   Zeile; der Ruecksprung zum Zeilenanfang wird dabei fehleranfaellig. */
.feld-hilfe {
  margin: 0;
  font-size: 0.84rem;
  color: #5f7488;
  /* **`max-width: 44ch` ist gefallen** (B-1). Die Begrenzung war richtig,
     solange der Satz unter dem Steuerelement ueber die volle Kartenbreite lief
     -- bis zu 190 Zeichen je Zeile, und der Ruecksprung zum Zeilenanfang wird
     dabei fehleranfaellig. Jetzt steht er in der mittleren Spalte, und die
     begrenzt ihn: rund 466 px, also 62 Zeichen. Zwei Begrenzungen fuer
     dieselbe Zeilenlaenge waeren eine zweite Wahrheit, und die engere gewaenne
     -- dann bliebe die Spalte halb leer. */
}

/* ─── Die Marke am Feld ────────────────────────────────────────────────────
   EINE WARNUNG, DIE IMMER DASTEHT, IST KEINE. Auf dem Such-Reiter standen
   sieben "ohne Wirkung" untereinander; sie waren alle richtig und zusammen
   wertlos, denn wenn die Vorgabe fast ueberall gilt, ist Wirkungslosigkeit der
   Normalzustand -- und der braucht keine Warnung. Die Marke steht seit dem
   22.08.2026 nur noch am gesetzten Wert, an der Sperre und am fehlenden
   Empfaenger; WELCHE Lage das ist, entscheidet der Server.

   ZWEI FARBEN STATT DREI. Gruen hiess "wirkt gerade" und sagte dasselbe wie
   die Wertspalte daneben, nur lauter. Was bleibt, sind die zwei Faelle, in
   denen etwas nicht stimmt. */

.marke {
  display: inline-block;
  margin-left: var(--ui-s3);
  padding: 2px 9px;
  border: 1px solid;
  border-radius: var(--ui-r-pill);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  white-space: nowrap;
  vertical-align: 1px;
}

.marke.warn {
  border-color: #e8d5b8;
  color: #9a6410;
  background: #fef9f0;
}

.marke.sperr {
  border-color: #eacbcb;
  color: #a33939;
  background: #fdeeee;
}

/* ─── Die Referenzzeile Wirkt / Aktiv wenn / Aendern falls ─────────────────
   Das Dreigespann aus v1 bleibt, aber als ruhige Zeile in Spalten statt als
   drei fette Zeilen unter jedem Feld: Es ist ein Nachschlagewerk, kein
   Fliesstext. Wer es braucht, findet es; wer nicht, ueberliest es in einer
   Zeile. */

dl.trio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--ui-s1) var(--ui-s6);
  margin: var(--ui-s4) 0 0;
  padding-top: var(--ui-s3);
  border-top: 1px dashed var(--ui-border);
  font-size: 0.8rem;
  color: var(--ui-text-soft);
}

dl.trio dt {
  /* Nicht #7b8b98: gerechnet 3,51:1 gegen die weisse Karte und damit unter AA.
     #5f7488 bringt 4,84:1 bei gleicher Anmutung. Die kleinste Schrift der Seite
     ist die, bei der Kontrast am meisten zaehlt. */
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #5f7488;
  font-weight: 600;
}

dl.trio dd {
  margin: 0;
}

/* ─── Tabellen ─────────────────────────────────────────────────────────────
   app.css:332-372. Kopfzeile in Versalien auf heller Flaeche. */

/* **`overflow: hidden` ist gefallen** (25.08.2026), und es hat etwas
   abgeschnitten, das kein Feld war: **das Zeilenmenue der Projektliste.**

   Es stand hier, um die Kopfzeilenflaeche an der abgerundeten Ecke zu klippen
   -- der uebliche Griff bei `border-collapse: collapse`, wo `border-radius`
   allein auf die Zellen nicht durchschlaegt. Die Klappe am Zeilenende ist aber
   absolut positioniert; in den unteren Zeilen oeffnet sie nach unten ueber den
   Tabellenrand hinaus und wurde dort **abgeschnitten -- sichtbar blieb der
   erste Eintrag.**

   > **Nicht der offene Punkt, den wir gefuehrt haben.** Der lautete auf
   > `.tabellenrolle { overflow-x: auto }` unter 900 px. Der klippt auch, aber
   > erst dort; **dieser hier klippte auf jeder Breite**, und gemeldet hat ihn
   > der Auftraggeber an einem gewoehnlichen Fenster.

   Die Ecken rundet jetzt die jeweils aeussere Zelle. Das ist eine Regel mehr
   und eine Nebenwirkung weniger. */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
  background: var(--ui-bg-card);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  margin-bottom: var(--ui-s5);
}

thead tr:first-child th:first-child {
  border-top-left-radius: var(--ui-r-md);
}

thead tr:first-child th:last-child {
  border-top-right-radius: var(--ui-r-md);
}

th,
td {
  border-bottom: 1px solid #edf2f6;
  padding: 10px var(--ui-s4);
  text-align: left;
  vertical-align: top;
}

th {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #6d8193;
  background: #f8fbfd;
  font-weight: 600;
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr:hover {
  background: #fafcfd;
}

td form {
  display: inline;
}

/* ─── Beschreibungslisten ──────────────────────────────────────────────────
   Das Gegenstueck zur Tafel fuer Wertepaare. */

dl.fest {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--ui-s2) var(--ui-s6);
  margin: 0 0 var(--ui-s5);
  padding: var(--ui-s5);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
}

/* Dieselbe Regel wie bei `label`: Diese Liste ist die LESENDE Fassung
   derselben Felder ("Ausgeschlossene Pfade", "Stoerer-Selektoren"), und ein
   Feldname wird nicht kuerzer, weil er nicht bedienbar ist. */
dl.fest dt {
  font-size: 0.8rem;
  letter-spacing: 0;
  color: #667a8d;
  font-weight: 600;
}

dl.fest dd {
  margin: 0;
}

/* ─── Hinweise und Meldungen ───────────────────────────────────────────────
   app.css:396-410 (.ui-hint) und die Zustandsfarben aus dem Token-Block. */

p.hinweis {
  color: #5f7488;
  font-size: 0.84rem;
  margin: var(--ui-s2) 0 0;
}

p.leer {
  color: var(--ui-text-soft);
}

/* EIN BEFUND IST KEIN FEHLER DIESES ZUGRIFFS. Ein beschaedigter Namensraum
   steht in seiner Gruppe und meldet einen Zustand, den der Betreiber behebt --
   nicht das Scheitern der gerade abgeschickten Handlung (`p.fehler`, rot).
   Deshalb der Warnton und dieselbe Bauform: linke Kante, ruhige Flaeche. */
p.befund {
  border: 1px solid #ecd9b4;
  border-left: 3px solid var(--ui-warn);
  border-radius: var(--ui-r-sm);
  background: #fdf6e9;
  color: #8a5a06;
  padding: var(--ui-s3) var(--ui-s4);
  font-size: 0.86rem;
}

p.befund code {
  color: inherit;
}

p.fehler {
  border: 1px solid #eacbcb;
  border-left-width: 3px;
  border-radius: var(--ui-r-sm);
  background: #fdeeee;
  color: #a33939;
  padding: var(--ui-s3) var(--ui-s4);
  font-size: 0.86rem;
}

.herkunft {
  font-size: 0.78rem;
  color: var(--ui-text-soft);
  margin-left: var(--ui-s3);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}

.gesperrt {
  opacity: 0.75;
}

/* Ein gesperrtes Steuerelement -- sichtbar, nicht bedienbar, mit dem Grund
   daneben (vertrag-api.md 11a, Entscheidung des Auftraggebers vom 20.08.2026).
   DAS IST KEIN VERBERGEN, und der Unterschied ist mechanisch: Ein verborgenes
   Feld steht im HTML und geht mit dem Formular hinaus -- ein `disabled` Feld
   steht da und geht NICHT hinaus. Der Wert bleibt lesbar, die Handlung nicht
   ausfuehrbar. Dieselbe Form wie `button:disabled` oben. */

input:disabled,
select:disabled,
textarea:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  background: var(--ui-bg-soft, #f3f6f9);
}

/* ─── Die Antwort ──────────────────────────────────────────────────────────
   Der Haken, der sie ausloest, steht weiter unten im Abschnitt "Testsuche":
   Er ist seit dem 24.08.2026 eine Karte mit eigener Kostenmarke und kein
   Absatz mehr. */

.antwort {
  border-left: 3px solid var(--ui-border);
}

p.antworttext {
  margin: 0;
  white-space: pre-wrap;
  line-height: 1.6;
}

/* Die Ueberschrift eines Antwortblocks. `rendering.py` setzt sie als `### `
   in den Text, `ui/antwortgliederung.py` macht ein Element daraus. Sie traegt
   die Groesse von `h3` und einen kleineren Abstand: Sie steht INNERHALB der
   Tafel, deren eigene Ueberschrift ("Antwort") schon darueber steht. */
/* Ohne Stufe (29.08.2026, mit `.ui-ident` und `.ui-listenkopf`): Die Klasse
   sagt, WAS dort steht. Bleibt die Stufe in der Bedingung, faellt die Regel
   still aus, sobald ein Leser die Ueberschrift eine Stufe verschiebt. */
.antwort-ueberschrift {
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  margin: var(--ui-s5) 0 var(--ui-s2);
}

/* Beginnt die Antwort mit einer Ueberschrift, faengt sie oben an der Tafel an
   und nicht eine Zeile darunter. */
.antwort > :first-child {
  margin-top: 0;
}

/* ─── Anmeldung: eine Karte in der Mitte ───────────────────────────────────
   Der Bestand hat dafuer keine Vorlage in der Kopie (s. Bericht). Gebaut aus
   den Tokens: dieselbe Karte, dieselbe Schaltflaeche, derselbe Verlauf. */

body.ui-anmeldung {
  display: grid;
  place-items: center;
}

.ui-anmeldung .ui-shell {
  max-width: 24rem;
}

.ui-anmeldung .ui-brand {
  border: none;
  justify-content: center;
  padding-bottom: var(--ui-s6);
}

/* ─── Schmale Fenster ──────────────────────────────────────────────────────
   app.css:412-434. Die Leiste legt sich ueber die Breite statt daneben. */

/* ─── Reiter ───────────────────────────────────────────────────────────────
   Auftrag 139: ein Reiter je Seitenaufruf (`?reiter=…`), keine Aufklapp-
   Container mehr -- der Auftraggeber hat sie ausdruecklich zurueckgewiesen.
   Erhoben aus `project-edit-*.png`: eine waagerechte Zeile, aktiver Reiter
   in `--ui-accent` mit Unterstrich, die uebrigen grau. Reine Navigation --
   `<a href>`, kein Javascript, nichts verborgen: Jede Seite rendert genau
   einen Abschnitt, die anderen drei existieren auf dieser Seite gar nicht. */

.ui-tabs {
  display: flex;
  gap: var(--ui-s6);
  border-bottom: 1px solid var(--ui-border);
  margin-bottom: var(--ui-s6);
}

.ui-tab-link {
  display: inline-block;
  padding: var(--ui-s3) 0 var(--ui-s3);
  margin-bottom: -1px;
  border-bottom: 2px solid transparent;
  color: var(--ui-text-soft);
  font-size: 0.88rem;
  font-weight: 600;
  text-decoration: none;
}

.ui-tab-link:hover {
  color: var(--ui-text);
}

.ui-tab-link.is-active {
  color: var(--ui-accent-dark);
  border-bottom-color: var(--ui-accent);
}

/* ─── Zahlenkarten ─────────────────────────────────────────────────────────
   Erhoben aus `crawlstatus.png`: sechs abgesetzte Kacheln, Zahl gross und
   fett, Beschriftung darunter, kleiner und grau -- mit Abstand, nicht
   aneinandergeklebt (Auftrag 139 Nachweis 5, der auffaelligste Mangel). */

.ui-karten {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: var(--ui-s4);
  margin-bottom: var(--ui-s6);
}

.ui-karte {
  display: flex;
  flex-direction: column;
  gap: var(--ui-s2);
  padding: var(--ui-s5);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
}

.ui-karte-zahl {
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.1;
}

.ui-karte-label {
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ui-text-soft);
  font-weight: 600;
}

/* ─── Fortschrittsbalken ───────────────────────────────────────────────────
   Erhoben aus `crawlstatus.png`: Beschriftung und Prozentzahl in einer
   Kopfzeile, darunter ein Balken auf hellem Grund. */

.ui-fortschritt-kopf {
  display: flex;
  justify-content: space-between;
  font-size: 0.82rem;
  color: var(--ui-text-soft);
  margin-bottom: var(--ui-s2);
}

.ui-fortschritt {
  height: 10px;
  border-radius: var(--ui-r-pill);
  background: var(--ui-bg-soft);
  overflow: hidden;
  margin-bottom: var(--ui-s6);
}

.ui-fortschritt-balken {
  height: 100%;
  background: var(--ui-ok);
  border-radius: var(--ui-r-pill);
}

/* ─── Blaetterung ──────────────────────────────────────────────────────────
   Erhoben aus `crawlstatus.png`: nummerierte Seiten mit Pfeilen, nicht
   "Seite 1 von 3. Naechste". */

.ui-blaetterung {
  display: flex;
  align-items: center;
  gap: var(--ui-s2);
  margin-top: var(--ui-s5);
}

.ui-blaetterung a,
.ui-blaetterung span.ui-luecke {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  height: 30px;
  padding: 0 var(--ui-s2);
  border-radius: var(--ui-r-sm);
  font-size: 0.82rem;
  text-decoration: none;
  color: var(--ui-text-soft);
}

.ui-blaetterung a:hover {
  background: var(--ui-bg-soft);
}

.ui-blaetterung a.is-aktiv {
  background: var(--ui-text);
  color: #fff;
  font-weight: 700;
}

/* ============================================================================
   TELEFONBREITE -- DER EINE UMBRUCHPUNKT.
   `plan-entwurf-umsetzung.md` §7.6.

   DIESER BLOCK WAR AELTER ALS DIE MASKE, DIE ER UMBRICHT. Er stammt aus einer
   Fassung ohne Wirkungszeile, ohne Kopfzeile, ohne Reiterzaehler, ohne klebende
   Aktionsleiste, ohne sechsspaltige Projektliste, ohne Suchzeile und ohne
   aufklappbare Diagnose -- alles davon ist zwischen `0.135.0` und `0.138.0`
   dazugekommen, und keines davon war fuer ein Telefon durchdacht. Was er
   vorher konnte, steht unveraendert oben: Leiste ueber die Breite, Feldzeile
   einspaltig.

   EIN UMBRUCHPUNKT, NICHT ZWEI. Der abgenommene Prototyp schaltet seine
   Telefonfassung ueber eine Wurzelklasse `.mobil` am Wurzelelement. Sie ist
   NICHT uebernommen: Eine Klasse, die der Server setzt, und eine Breite, die
   der Browser misst, sind zwei Aussagen ueber dieselbe Sache -- und die eine
   altert, sobald die andere sich aendert. `tests/unit/test_telefonbreite.py`
   haelt die Datei bei genau einer `@media`-Regel.

   DIE ZIELHOEHE IST 44 PX, UND SIE IST NICHT HIER ERFUNDEN. `.suchfeld button`
   traegt sie seit `0.138.0`; dieser Block zieht die uebrigen Antippziele nach.
   GEHOBEN WIRD, WAS DARUNTER LAG, und das ist gemessen an `0.138.0` mit
   `font-size: 0.92rem` und `line-height: 1.5` an `body`:

     button                       34 px gesetzt
     td button                    28 px gesetzt
     .ui-nav-link                 32 px gesetzt
     .ui-blaetterung a            30 px gesetzt
     .wahl label              rund 21 px, allein aus dem Text
     .ui-tab-link             rund 39 px, Text plus 2x8 px Polster
     details > summary        rund 43 px, Text plus 2x11 px Polster
     .aktionsleiste .verwerfen     ein blanker Verweis, ohne eigene Hoehe

   `.suchfeld button` steht deshalb in keiner Regel dieses Blocks -- was schon
   hoch genug ist, wird nicht noch einmal gesetzt.

   WAS DIESER BLOCK NICHT LEISTET, und das gehoert dazugeschrieben: Er ist an
   der Datei geprueft, nicht am Auge. Die Nachweise belegen, dass eine Regel
   dasteht, nicht dass sie gut aussieht. Die Sichtpruefung am laufenden Dienst
   macht der Auftraggeber; §7.6 nennt diesen Zweig als den einen, dessen
   Abnahme nicht vollstaendig am HTML haengt.
   ========================================================================= */

@media (max-width: 900px) {
  /* ─── Aufbau: die Leiste legt sich ueber die Breite ─────────────────── */

  .ui-app {
    flex-direction: column;
  }

  .ui-aside {
    width: 100%;
    border-right: none;
    border-bottom: 1px solid var(--ui-border);
  }

  .ui-nav {
    flex-direction: row;
    flex-wrap: wrap;
  }

  .ui-nav-link {
    width: auto;
    min-height: 44px;
  }

  .ui-aside-foot {
    display: flex;
    gap: var(--ui-s6);
    align-items: baseline;
  }

  .ui-aside-foot dl {
    border-bottom: none;
    padding-bottom: 0;
    margin-bottom: 0;
  }

  .ui-shell {
    padding: var(--ui-s5) var(--ui-s4) 32px;
  }

  /* ─── Die Zielhoehe an allem, was ein Finger trifft ─────────────────── */

  button {
    min-height: 44px;
  }

  td button {
    /* Eine eigene Regel, weil `td button` spezifischer ist als `button` --
       eine Media-Query aendert an der Spezifitaet nichts. Ohne sie bliebe der
       Knopf in der Aktionsspalte der Projektliste bei 28 px, waehrend jeder
       andere Knopf der Seite auf 44 gehoben waere. */
    min-height: 44px;
  }

  .wahl label {
    min-height: 44px;
  }

  details > summary {
    min-height: 44px;
  }

  .ui-blaetterung {
    flex-wrap: wrap;
  }

  .ui-blaetterung a,
  .ui-blaetterung span.ui-luecke {
    /* `min-height` und nicht `height`: Die Grundregel setzt `height: 30px`,
       und `min-height` gewinnt gegen `height`. */
    min-width: 44px;
    min-height: 44px;
  }

  /* ─── Die Reiterleiste rollt, sie bricht nicht ──────────────────────── */

  /* Vier Reiter, zwei davon mit Zaehler, passen auf 390 px nicht in eine
     Zeile. Umbrechen hiesse: eine zweite Reiterzeile, die wie ein zweiter
     Abschnitt aussieht -- die Leiste rollt stattdessen waagerecht. */
  .ui-tabs {
    gap: var(--ui-s5);
    overflow-x: auto;
    /* `overflow-x: auto` rechnet `overflow-y` von `visible` auf `auto` mit.
       Der aktive Reiter zieht sich mit `margin-bottom: -1px` ueber die
       Trennlinie -- genau der eine Pixel, der sonst eine senkrechte Rollleiste
       erzeugt. Das Polster nimmt ihn auf, ohne den Unterstrich zu beschneiden;
       `overflow-y: hidden` haette ihn abgeschnitten. */
    padding-bottom: 1px;
  }

  .ui-tab-link {
    /* `inline-flex` statt `inline-block`, damit der Zaehler mittig sitzt --
       dabei faellt der reine Leerraum zwischen Beschriftung und Zaehler als
       Flex-Element weg, `gap` setzt ihn wieder. */
    display: inline-flex;
    align-items: center;
    gap: var(--ui-s2);
    flex: 0 0 auto;
    min-height: 44px;
    white-space: nowrap;
  }

  /* ─── Tabellen rollen in ihrem Behaelter ────────────────────────────── */

  /* NUR DER BEHAELTER ROLLT. Der Radius der Tabelle haengt an ihrem eigenen
     `overflow: hidden` und bleibt dort -- zoege der Behaelter es an sich, waere
     die Rundung weg. UND DIE TABELLE WIRD NICHT IN BLOECKE UMGEBAUT: Eine
     Zelle als `display: block` loest die Spaltenbeziehung auf, und die
     sechsspaltige Projektliste lebt genau davon.

     Kein `min-width` an der Tabelle: Das Tabellenlayout unterschreitet die
     Mindestbreite seines Inhalts ohnehin nicht, also rollt genau die Tabelle,
     die zu breit ist. Eine erzwungene Mindestbreite haette auch die
     zweispaltige Tabelle zum Rollen gebracht, die passt. */
  .tabellenrolle {
    overflow-x: auto;
  }

  /* ─── Die Feldzeile: einspaltig, und die Anatomie passt mit ─────────── */

  /* Die Wertspalte gibt ihre Kante auf, bevor sie den Feldnamen erdrueckt --
     eine Linie, an der nichts mehr Platz hat, ordnet nichts mehr. Das stand
     schon hier; was fehlte, sind die zwei Raenge, die am 22.08.2026
     dazugekommen sind: Rang 3 traegt feste Breiten je Typ, Rang 4 eine
     Zeilenlaenge -- beide in `rem` und beide breiter, als ein Telefon hat. */
  .feld {
    grid-template-columns: 1fr;
  }

  /* **Alle vier Zuweisungen zurueck in die eine Spalte.** Seit dem 25.08.2026
     verteilt das Gitter draussen Name, Steuerelement, Hilfe und Wert auf drei
     Spalten; hier gibt es nur eine, und eine `grid-column: 3` in einem
     einspaltigen Gitter erzeugt eine zweite, die niemand gesetzt hat. */
  .feld > .feld-name,
  .feld > .feld-steuer,
  .feld > .feld-hilfe {
    grid-column: 1;
  }

  .feld > .feld-wert {
    grid-column: 1;
    text-align: left;
  }

  .feld-steuer > * {
    max-width: 100%;
  }

  /* Draussen begrenzt die mittlere Spalte die Zeilenlaenge; hier gibt es sie
     nicht, und der Absatz nimmt die volle Breite -- die ist auf 390 px kurz
     genug. */
  .feld-hilfe {
    max-width: none;
  }

  /* ─── Wirkungszeile und Kopfzeile: untereinander ────────────────────── */

  /* Beide stellen zwei Angaben mit `space-between` an die Kanten. Auf 390 px
     ist zwischen den Kanten kein Zwischenraum mehr, den man verteilen koennte;
     die Angaben stehen dann untereinander. */
  .wirkung {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--ui-s2);
  }

  .kopfzeile {
    flex-direction: column;
    /* `align-items: flex-end` der Grundregel richtet die Grundlinien der
       nebeneinanderstehenden Bloecke aus. In der Spalte wuerde daraus ein
       Rechtsbuendig -- der Titel rueckte an den rechten Rand. */
    align-items: stretch;
  }

  .kopf-fakten {
    /* Vier Fakten, die mehrzeilig stehen, brauchen einen Zeilenabstand, der
       kleiner ist als der Abstand zwischen zwei Fakten derselben Zeile. */
    gap: var(--ui-s1) var(--ui-s5);
  }

  /* ─── Die Aktionsleiste: volle Breite, Knoepfe nebeneinander ────────── */

  /* SIE KLEBT WEITERHIN UNTEN, und sie verdeckt dabei nichts dauerhaft: Am
     Ende des Rollwegs steht sie an ihrer natuerlichen Stelle -- als letztes
     Element des Formulars, mit den 32 px Polster von `.ui-shell` darunter.
     Was sie unterwegs ueberdeckt, liegt ueber ihr und kommt beim
     Weiterrollen wieder frei. */
  .aktionsleiste {
    /* Bis an die Fensterkanten, damit die Knoepfe die Breite bekommen, die
       ihre Beschriftungen brauchen ("Quellkonfiguration speichern"). Die
       negativen Raender heben das waagerechte Polster von `.ui-shell` auf;
       Rahmen und Radius an den Seiten fallen mit ihnen weg. */
    margin-left: calc(var(--ui-s4) * -1);
    margin-right: calc(var(--ui-s4) * -1);
    border-left: none;
    border-right: none;
    border-radius: 0;
    gap: var(--ui-s3);
    padding: var(--ui-s3) var(--ui-s4);
  }

  .aktionsleiste button {
    /* Nebeneinander, solange beide passen, und umbrechend, sobald nicht --
       `flex-wrap: wrap` steht in der Grundregel. */
    flex: 1 1 auto;
  }

  .aktionsleiste .verwerfen {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .aktionsleiste .offen {
    /* EINE EIGENE ZEILE, NICHT WEG. Der Prototyp nimmt diesen Satz am Telefon
       heraus; er ist aber die einzige Stelle der Flaeche, die sagt, dass nichts
       von selbst gilt. `margin-left: auto` der Grundregel entfaellt -- in
       einer eigenen Zeile schiebt es ihn sonst nach rechts. */
    flex: 1 1 100%;
    margin: 0;
  }

  /* ─── Die Testsuche: Suchzeile und Kostenmarke ──────────────────────── */

  /* Eingabefeld und Knopf passen auf 390 px nicht nebeneinander: Der Knopf
     traegt 22 px Polster je Seite, dem Feld blieben rund zwei Woerter. */
  .suchfeld {
    flex-wrap: wrap;
    gap: var(--ui-s3);
  }

  .suchfeld input {
    flex: 1 1 100%;
  }

  .suchfeld button {
    width: 100%;
  }

  .option {
    /* Der Haken traegt Titel, Satz und Kostenmarke in einer Zeile. Umbruch
       erlaubt, und die Marke faellt von selbst in die zweite -- der Satz ist
       breiter als jede Telefonflaeche. */
    flex-wrap: wrap;
  }

  .kostet {
    margin-left: 0;
    align-self: flex-start;
  }

  /* Die vier Baugruppen dieses Zweigs im einen Umbruchpunkt (29.08.2026,
     Befund der Abnahmepruefung). Kein zweiter Punkt, nur dieselben Regeln
     eine Stufe weiter. */

  /* Das Suchfeld lief ueber den Rand: 18 rem fest neben einem auf 44 px
     gehobenen Knopf sind mehr als die 366 px, die auf einem 390er Geraet
     bleiben. Die Hausform macht es zwei Bildschirme weiter oben richtig
     (`.ui-listenwerkzeug input[type="search"]`). */
  .ui-suchfeld {
    flex-wrap: wrap;
  }

  .ui-suchfeld input {
    max-width: 100%;
  }

  /* Der rechte Text der Fortschrittszeile ist laenger geworden -- ohne Umbruch
     quetschen sich beide Seiten zu zwei schmalen, hohen Spalten, und das im
     klebenden Band, wo Hoehe am teuersten ist. */
  .ui-fortschritt-kopf {
    flex-wrap: wrap;
    gap: var(--ui-s2) var(--ui-s4);
  }

  /* Das klebende Band nahm mit zwei Phasen rund die Haelfte eines
     Telefonbildschirms. Was faellt, ist die Ersterklaerung -- nicht die
     Stillstandsmeldung: Die ist ein Befund, kein Beipacktext. */
  .ui-laufband {
    padding: var(--ui-s4);
  }

  .ui-laufband > p.hinweis {
    display: none;
  }
}

/* ============================================================================
   DIE WIRKUNGSZEILE -- ein Satz je Einstellungsblock, Zaehler rechts daneben.

   DER SERVER RECHNET DIE WURZELKLASSE, HIER WIRD DER SATZ GEWAEHLT.
   `api/effect_summary.py` setzt an den Block die Zustaende dieses Blocks
   (`w-l-vla w-r-ja`) und rendert ALLE Fassungen (`wv-l-vla`, `wv-r-ja`, ...);
   die Regeln darunter zeigen genau die, deren Schluessel der Block traegt.

   DASS HIER ETWAS VERBORGEN WIRD, IST AUSDRUECKLICH ENTSCHIEDEN --
   Auftraggeber, 23.08.2026 (plan-entwurf-umsetzung.md §0.3). Bis dahin verbot
   `test_gestaltung.py::test_die_stildatei_verbirgt_nichts` jede
   Anzeigeeigenschaft in dieser Datei; der Nachweis ist mit dieser Entscheidung
   entfallen. WAS ER NEBEN SICH HATTE, BLEIBT: Ein durch die Lizenz gesperrtes
   Feld wird gar nicht erst gerendert, auch nicht unsichtbar (vertrag-api.md
   11a) -- die zwei Nachweise dafuer stehen weiter in derselben Datei.

   JEDER ZUSTANDSSCHLUESSEL BRAUCHT HIER EINE ZEILE. Fehlt sie, bleibt der Satz
   unsichtbar, und der Block sagte nichts. `test_wirkungszeile.py` zaehlt alle
   Kombinationen durch und faellt an einem Schluessel ohne Regel.
   ========================================================================= */

.wirkung {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 18px;
  margin: 2px 0 10px;
  padding: 10px 12px;
  border-radius: 9px;
  background: #f4f9f9;
  border: 1px solid #dceceb;
}

.wirkung-satz {
  margin: 0;
  font-size: .86rem;
  color: #35525f;
}

.wirkung-satz b {
  font-weight: 600;
  color: var(--ui-accent-dark);
}

/* Ein Aus-Zustand ist kein Vorfall -- er steht leiser, nicht rot. Wo etwas
   nicht stimmt, steht die Marke am Feld. */
.wirkung-satz .aus {
  color: #8a99a5;
  font-weight: 500;
}

.wirkung-zahl {
  font-size: .78rem;
  font-weight: 600;
  color: var(--ui-text-soft);
  white-space: nowrap;
}

.wirkung .wv {
  display: none;
}

.wirkung.w-immer .wv-immer,
.wirkung.w-l-v .wv-l-v,
.wirkung.w-l-va .wv-l-va,
.wirkung.w-l-vl .wv-l-vl,
.wirkung.w-l-vla .wv-l-vla,
.wirkung.w-r-ja .wv-r-ja,
.wirkung.w-r-nein .wv-r-nein,
.wirkung.w-m-keins .wv-m-keins,
.wirkung.w-m-classifier .wv-m-classifier,
.wirkung.w-m-hyde .wv-m-hyde,
.wirkung.w-m-beides .wv-m-beides,
.wirkung.w-f-ja .wv-f-ja,
.wirkung.w-f-nein .wv-f-nein,
.wirkung.w-t-ja .wv-t-ja,
.wirkung.w-t-nein .wv-t-nein,
.wirkung.w-q-start .wv-q-start,
.wirkung.w-q-sitemap .wv-q-sitemap,
.wirkung.w-g-aus .wv-g-aus,
.wirkung.w-g-suche .wv-g-suche,
.wirkung.w-g-antwort .wv-g-antwort {
  display: inline;
}

/* ─── Die Projektliste, sechs Spalten ──────────────────────────────────────
   Aus dem abgenommenen Entwurf (`liste.css`, Entwurfssitzung 22.08.2026), auf
   die Klassen dieser Vorlage gebracht. Angehaengt und nicht eingewoben: die
   Datei ist chronologisch gewachsen, und ein Abschnitt am Ende ist im Diff
   lesbar.

   WAS HIER NICHT STEHT: die Breite des Balkens. Sie ist je Zeile verschieden
   und wird im Server gerechnet (`ProjectListRow.fortschritt_prozent`) -- CSS
   kann sie nicht kennen, und eine Klasse je Prozentwert waere eine Aufzaehlung
   ohne Ende. Der Farbwechsel dagegen ist eine Regel und steht hier. */

td.projekt {
  min-width: 18rem;
}

.projekt-name {
  display: inline-block;
  font-size: 0.98rem;
  font-weight: 600;
}

.sprachen {
  margin-left: var(--ui-s3);
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--ui-text-soft);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.projekt-host {
  display: block;
  margin-top: var(--ui-s1);
  font-family: var(--ui-font-mono);
  font-size: 0.78rem;
  color: var(--ui-text-soft);
}

/* Die zweite Zeile einer Zelle -- leiser als der Wert darueber, nie an seiner
   Stelle. */
.zweitzeile {
  display: block;
  margin-top: var(--ui-s1);
  font-size: 0.76rem;
  color: var(--ui-text-soft);
}

.balken {
  display: block;
  width: 90px;
  height: 5px;
  margin-top: var(--ui-s2);
  border-radius: var(--ui-r-pill);
  background: var(--ui-bg-soft);
  overflow: hidden;
}

.balken i {
  display: block;
  height: 100%;
  background: var(--ui-ok);
}

.balken.teil i {
  background: var(--ui-warn);
}

/* DIE SPEICHERSPALTE IST WEG (P-6, 24.08.2026). `.speicher`, `.paar` und
   `.abweichung` standen hier fuer zwei Zahlen, die im Normalfall gleich waren
   -- die Aussage war ihr Unterschied, und der steht jetzt im Befund des
   Urteils. Mit der Spalte fallen ihre Regeln; `.projekt-ns` ebenso, weil der
   Namensraum eine eigene Spalte bekommen hat statt einer Vorzeile. */

/* Der Zaehler nennt einen benannten Nenner (P-5). Die Zahl traegt Gewicht,
   die Einheit nicht -- `<strong>` steht im Markup, die Groesse hier. */
.ui-zaehlung {
  display: block;
  font-size: 0.82rem;
  white-space: nowrap;
}

/* Eine auffaellige Zeile wird nicht rot, sie wird **markiert**: ein Streifen
   am linken Rand. Rot faerbte fuenf von fuenf Zeilen ein, sobald mehrere
   Projekte etwas brauchen -- und dann faerbt es nichts mehr. */
tr.ist-auffaellig > td:first-child {
  box-shadow: inset 3px 0 0 var(--ui-warn);
}

/* -- Der Listenkopf: Titel links, Werkzeug rechts ------------------------- */

.ui-listenkopf {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--ui-s4);
  margin-bottom: var(--ui-s4);
}

/* DIESELBE LEHRE WIE BEI `.ui-ident` (29.08.2026): Die Klasse sagt, WAS dort
   steht, nicht in welcher Ueberschriftsstufe. Die Regel las `h2`, die
   Dokumentliste setzt einen `h3` in denselben Behaelter -- der behielt seine
   22 px Aussenabstand oben und sass gegenueber der Zaehlung verschoben. */
.ui-listenkopf > :is(h2, h3) {
  margin-bottom: var(--ui-s1);
}

.ui-listenwerkzeug {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s3);
}

.ui-listenwerkzeug input[type="search"] {
  width: 15rem;
  max-width: 100%;
}

/* Der Zaehler am Filter. Er nennt dieselbe Zahl wie der Filter zeigt --
   `ist-null` macht ihn leise, statt ihn zu verstecken: dass nichts ansteht,
   ist eine Auskunft. */
/* Die Ziffer traegt #9a6410 auf weisser Flaeche -- 4,76:1 statt 2,85:1
   (Messung 24.08.2026). `--ui-warn` (#cf7d10) ist eine Flaechenfarbe; als
   Text auf `--ui-bg-soft` fiel sie unter AA, und die Plakette selbst war auf
   der Schalterflaeche unsichtbar. Es ist dieselbe Farbe, die `.ui-pill.warn`
   seit jeher fuehrt -- keine neue (P-10).

   FLAECHE UND SCHRIFT KOMMEN AUS DERSELBEN MARKE. Die erste Berichtigung
   setzte die Flaeche auf `--ui-bg-card` -- weiss, und damit auf dem **aktiven**
   Reiter, der ebenfalls weiss ist, unsichtbar: `min-width` und `border-radius`
   taten dann nichts mehr, uebrig blieb eine freistehende Ziffer. `#fef9f0` ist
   die Flaeche von `.ui-pill.warn`, traegt in beiden Reiterzustaenden und
   haelt die Ziffer bei 4,76:1. */
.ui-zaehler {
  display: inline-block;
  min-width: 1.4rem;
  padding: 0 var(--ui-s2);
  border-radius: var(--ui-r-pill);
  background: #fef9f0;
  color: #9a6410;
  font-size: 0.74rem;
  font-weight: 700;
  text-align: center;
}

.ui-zaehler.ist-null {
  color: var(--ui-text-soft);
}

/* -- Das Zeilenmenue ------------------------------------------------------ */

/* EIN VERWEIS FUEHRT (P-7). Vier gleich laute Links je Zeile waren sechzehn
   auf der Seite; der haeufigste sah aus wie der seltenste. Die drei uebrigen
   liegen hier -- ein `<details>`, damit sie ohne `app.js` bedienbar bleiben
   (P-11). */
.ui-zeilenmenue {
  display: inline-block;
  position: relative;
}

.ui-zeilenmenue > summary {
  padding: 0 var(--ui-s2);
  border-radius: var(--ui-r-sm);
  color: var(--ui-text-soft);
  font-weight: 700;
  letter-spacing: 0.08em;
  cursor: pointer;
  list-style: none;
}

.ui-zeilenmenue > summary::-webkit-details-marker {
  display: none;
}

.ui-zeilenmenue[open] > summary,
.ui-zeilenmenue > summary:hover {
  background: var(--ui-bg-soft);
  color: var(--ui-text);
}

.ui-menueinhalt {
  display: flex;
  flex-direction: column;
  position: absolute;
  right: 0;
  z-index: 2;
  min-width: 11rem;
  padding: var(--ui-s2);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  box-shadow: var(--ui-shadow);
  text-align: left;
}

td.aktionen .ui-menueinhalt a {
  margin: 0;
  padding: var(--ui-s2) var(--ui-s3);
  border-radius: var(--ui-r-sm);
}

td.aktionen .ui-menueinhalt a:hover {
  background: var(--ui-bg-soft);
}

/* DIE ZUSTANDSMARKE FUEHRT IN IHREN REITER (F-2, 25.08.2026). Sie war eine
   Auskunft neben einem Formular, das dieselbe Angabe aenderte; das Formular ist
   in den Reiter `projekt` gewandert, und die Marke traegt den Weg dorthin.
   **Sie sieht aus wie zuvor** -- ein Verweis, der sich als solcher aufdraengt,
   waere lauter als die Auskunft, die er traegt. */
.kopf-zustand {
  color: inherit;
  text-decoration: none;
}

.kopf-zustand:hover .ui-pill {
  border-color: var(--ui-accent);
}

/* DER BEDINGUNGSSATZ (25.08.2026). Hier stand eine Klappe (*Warum ·
   Bedingung*) mit einer zweizeiligen Referenz darin; sie ist am selben Tag
   wieder gefallen, weil ihr Inhalt **ein** Satz war und weil sie an der
   Stelle zu war, an der der Leser fragt. Der Satz steht jetzt offen und
   traegt eine eigene Farbe: Er sagt etwas ueber die **Lage**, waehrend der
   Hilfesatz darueber die **Wirkung** erklaert. */
.feld-bedingung {
  color: var(--ui-warn);
}

/* DER GEERBTE WERT UNTER DER SCHALTFLAECHENGRUPPE (25.08.2026). Er stand auf
   der ersten Schaltflaeche und kollidierte dort mit der zweiten; er steht jetzt
   darunter, leise -- **eine Auskunft und keine vierte Option.** */
.ui-geerbt {
  margin: var(--ui-s2) 0 0;
  font-size: 0.78rem;
  color: var(--ui-text-soft);
}

/* DIE ABWESENHEITSNOTIZ (F-6, 25.08.2026). Sie nennt die Felder, die gerade
   nichts bewirken und deshalb nicht dastehen -- **die zweite der beiden
   Bedingungen, unter denen das Ausblenden zugelassen ist.** Sie ist leise und
   nicht unsichtbar: Wer sie nicht sucht, soll nicht darueber stolpern; wer ein
   Feld vermisst, soll sie finden. */
.ui-abwesend {
  margin-top: var(--ui-s4);
  padding-left: var(--ui-s4);
  border-left: 2px solid var(--ui-border);
}

/* -- Das Anlegeformular, einmal (P-8) ------------------------------------- */

.ui-anlegen {
  margin-top: var(--ui-s6);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
}

.ui-anlegen > summary {
  padding: var(--ui-s3) var(--ui-s4);
  font-weight: 600;
  cursor: pointer;
}

/* „freiwillig" steht neben der Beschriftung und nicht darunter: Wer das Feld
   ueberspringen darf, soll es sehen, bevor er hineinklickt. */
.ui-freiwillig {
  font-weight: 400;
  color: var(--ui-text-soft);
}

/* Kaestchen und Knoepfe einer Wahl stehen nebeneinander, solange Platz ist --
   eine Spalte aus drei Woertern liest sich als Liste und ist keine. */
.ui-wahlreihe {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-s3) var(--ui-s5);
}

.ui-wahlreihe label {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-s2);
  font-weight: 400;
}

.aktionen {
  text-align: right;
  white-space: nowrap;
}

td.aktionen a {
  margin-left: var(--ui-s4);
  font-size: 0.82rem;
  font-weight: 600;
}

/* ─── Handlungsführung: Kopfzeile, Reiterzähler, Aktionsleiste ─────────────
   Aus dem abgenommenen Entwurf (`main.css`/`style.css` der Entwurfssitzung
   22.08.2026), auf die Klassen dieser Vorlagen gebracht. Angehaengt und nicht
   eingewoben -- dieselbe Begruendung wie beim Abschnitt darueber.

   `--ui-hint` des Entwurfs gibt es hier nicht; die leise Textfarbe dieser Datei
   heisst `--ui-text-soft`, und ein zweiter Name fuer dieselbe Farbe waere ein
   Token ohne Anlass. */

.kopfzeile {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--ui-s3) var(--ui-s6);
  margin-bottom: var(--ui-s5);
}

/* Der Namensraum ist ein Bezeichner und steht deshalb in Festbreite -- wie
   `ui-ident`, nur eine Stufe leiser und ueber dem Titel statt in ihm. */
.kicker {
  display: block;
  font-family: var(--ui-font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ui-text-soft);
  margin-bottom: var(--ui-s1);
}

.kopfzeile h1 {
  margin: 0;
  font-size: 1.35rem;
}

.kopf-fakten {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ui-s2) var(--ui-s6);
  font-size: 0.8rem;
  color: var(--ui-text-soft);
}

.kopf-fakten b,
.kopf-fakten code {
  font-weight: 600;
  color: var(--ui-text);
}

/* Der leise Zaehler am Reiter. `ist-null` nimmt ihm die Farbe, statt ihn
   wegzunehmen: „nichts gesetzt" ist eine Auskunft, kein Nichts. */
.tab-zahl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--ui-r-pill);
  background: var(--ui-bg-soft);
  color: var(--ui-text-soft);
  font-size: 0.7rem;
  font-weight: 700;
}

.ui-tab-link.is-active .tab-zahl {
  background: #d7efee;
  color: var(--ui-accent-dark);
}

.tab-zahl.ist-null {
  opacity: 0.6;
}

/* Sie klebt am unteren Rand, weil ein Reiter laenger ist als das Fenster: Der
   Speicherknopf soll nicht erst nach dem Rollen auftauchen. */
.aktionsleiste {
  position: sticky;
  bottom: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s4) var(--ui-s6);
  margin-top: var(--ui-s6);
  padding: var(--ui-s4) var(--ui-s5);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  box-shadow: var(--ui-shadow);
}

.aktionsleiste .verwerfen {
  font-size: 0.84rem;
  font-weight: 600;
}

.aktionsleiste .offen {
  margin: 0 0 0 auto;
  font-size: 0.84rem;
  color: var(--ui-text-soft);
}

/* ─── Testsuche: Kostenkarten, Ergebnis ueber Diagnose ─────────────────────
   Aus dem abgenommenen Entwurf (Entwurfssitzung 22.08.2026), auf die Klassen
   dieser Vorlage gebracht. Angehaengt und nicht eingewoben -- dieselbe
   Begruendung wie bei den zwei Abschnitten darueber.

   ZWEI ANGABEN DES ENTWURFS SIND NICHT UEBERNOMMEN. Er verbirgt die
   Dreiecksmarke des `summary` zweimal: ueber `list-style: none` UND ueber
   `::-webkit-details-marker`. Das zweite ist ein Praefix fuer einen Fall, den
   `::marker` seit Jahren in jedem Zielbrowser abdeckt -- eine Zeile, die
   niemand mehr prueft, weil sie nichts mehr tut. Und seine Kostenmarke bringt
   eigene Farben mit, die auf den Wert genau denen von `.marke.warn` gleichen;
   uebernommen ist deshalb nur die Anordnung. */

/* Eingabe und Knopf auf einer Linie. Der Knopf stand zwei Zeilen tiefer in
   einer `knopfreihe` -- eine Stufe zu viel fuer das Erste, was jemand hier
   tut. `margin-top` der Eingabe faellt weg, weil die Zeile ihn setzt. */
.suchfeld {
  display: flex;
  align-items: flex-start;
  gap: var(--ui-s4);
}

.suchfeld input {
  margin-top: 0;
  padding: 11px 13px;
  font-size: 1rem;
}

.suchfeld button {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 var(--ui-s7);
}

.optionen {
  display: grid;
  gap: var(--ui-s3);
  margin-top: var(--ui-s5);
}

/* Titel, Satz und Kostenmarke -- der Haken traegt seine Folge selbst und
   braucht keinen Absatz darunter, der sie erklaert. */
.option {
  display: flex;
  align-items: flex-start;
  gap: var(--ui-s3);
  padding: var(--ui-s4);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-sm);
  cursor: pointer;
}

.option input {
  flex: 0 0 auto;
  width: auto;
  margin: 3px 0 0;
}

.option .txt {
  flex: 1;
}

.option .titel {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
}

.option .satz {
  display: block;
  max-width: 52ch;
  margin-top: var(--ui-s1);
  font-size: 0.82rem;
  color: var(--ui-text-soft);
}

.kostet {
  flex: 0 0 auto;
  align-self: center;
  margin-left: auto;
}

/* Das Bedienfeld der Testflaeche -- 0055.

   EIN RASTER STATT EINER SPALTE: `auto-fill`, weil die Zahl der Felder je
   Abschnitt verschieden ist und eine feste Spaltenzahl den kurzen Abschnitt
   luecken liesse.

   GESPERRTE FELDER BLEIBEN SICHTBAR (0040 Festlegung 1) -- gedaempft, nicht
   entfernt, und der Grund steht darunter statt in einem Titelattribut: Ein
   Grund, den man nur beim Darueberfahren sieht, erreicht niemanden, der die
   Seite ueberfliegt. */
.testlauf {
  margin-top: var(--ui-s5);
}

.testlauf-felder {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--ui-s4);
  margin-bottom: var(--ui-s5);
}

.testlauf-feld {
  display: flex;
  flex-direction: column;
  gap: var(--ui-s1);
}

.testlauf-feld .titel {
  font-size: 0.82rem;
  font-weight: 600;
}

.testlauf-feld .satz {
  max-width: 52ch;
  font-size: 0.78rem;
  color: var(--ui-text-soft);
}

.testlauf-feld.gesperrt .titel,
.testlauf-feld .gesperrt-grund {
  color: var(--ui-text-soft);
  font-style: italic;
}

/* Was diesen Lauf erzeugt hat -- nicht, was als Naechstes gilt. Sie steht
   zwischen Laufkennung und Ergebnis, also dort, wo die Frage entsteht. */
.gefahren-mit {
  margin: 0 0 var(--ui-s4);
  padding: var(--ui-s3) var(--ui-s4);
  border-left: 3px solid var(--ui-accent);
  background: var(--ui-bg-soft);
  font-size: 0.84rem;
}

.ergebnis-kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ui-s3) var(--ui-s6);
  margin: var(--ui-s7) 0 var(--ui-s4);
}

.ergebnis-kopf h3 {
  margin: 0;
}

.ergebnis-kopf .lauf {
  font-family: var(--ui-font-mono);
  font-size: 0.76rem;
  color: var(--ui-text-soft);
}

details {
  margin-bottom: var(--ui-s3);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
}

details > summary {
  display: flex;
  align-items: center;
  gap: var(--ui-s3);
  padding: 11px var(--ui-s5);
  font-size: 0.88rem;
  font-weight: 600;
  list-style: none;
  cursor: pointer;
}

details > summary::marker {
  content: "";
}

details > summary::before {
  content: "";
  flex: 0 0 auto;
  width: 7px;
  height: 7px;
  border-right: 1.6px solid var(--ui-text-soft);
  border-bottom: 1.6px solid var(--ui-text-soft);
  transform: rotate(-45deg);
}

details[open] > summary::before {
  transform: rotate(45deg);
}

.neben {
  margin-left: auto;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ui-text-soft);
}

.details-inhalt {
  padding: 0 var(--ui-s5) var(--ui-s5);
}

.details-inhalt table {
  margin-bottom: 0;
}

/* Die Zaesur zwischen Ergebnis und Diagnose. Ein kurzes Systemwort in
   Versalien -- die Grenze aus der Feldanatomie, nicht ihre Aufhebung. */
.diagnose-kopf {
  margin: var(--ui-s7) 0 var(--ui-s3);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ui-text-soft);
}

/* ─── Der Authoring-Editor: Feldblock, Artwahl, Reiterschalter ─────────────
   Aus dem abgenommenen Entwurf vom 24.08.2026 (Leinwand „Kuratierte Inhalte —
   Editor"), auf die Werte dieser Datei gebracht. **Kein neuer Token, keine
   neue Farbe, kein neuer Radius** -- der Entwurf ist absichtlich aus dem
   gebaut, was hier schon steht.

   ZWEI KLASSEN STANDEN IN DER VORLAGE UND IN KEINER REGEL. `.ui-feld` und
   `.ui-feld small` benutzt `_inhalt_felder.mako` seit dem ersten Zug; hier gab
   es sie nicht. Deshalb sassen die Hinweise mal ueber, mal unter dem Feld und
   in wechselnder Groesse.

     Eine Klasse ohne Regel faellt nicht auf -- sie sieht aus wie eine, die
     nichts tun soll.

   `tests/unit/test_stilklassen.py` haelt das ab jetzt gegeneinander. */

.ui-feld {
  display: block;
  margin-top: var(--ui-s5);
}

.ui-feld > span {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--ui-text);
}

/* Der Hinweis unter dem Feld -- **dieselben Werte wie `p.hinweis`**, damit ein
   Hinweis ueberall gleich aussieht, gleich wo er steht. */
.ui-feld small {
  display: block;
  color: #5f7488;
  font-size: 0.84rem;
  margin-top: var(--ui-s2);
}

.ui-pflicht {
  color: var(--ui-bad);
  font-weight: 700;
}

/* ─── Die Artwahl ──────────────────────────────────────────────────────────

   OHNE SKRIPT, UND OHNE `:has()`. Die Bedienoberflaeche hat keinen Zustand
   (0031 Festlegung 1); die Wahl liegt deshalb in verborgenen `input[type=radio]`,
   und die Karten sind ihre `label`. Sichtbar geschaltet wird ueber die
   **Geschwisterkombination** -- sie verlangt nur, dass die Radios **vor** allem
   stehen, was von ihnen abhaengt, und traegt seit zwanzig Jahren ueberall.

   `:has()` waere kuerzer und musste gemessen werden; auf dieser Maschine steht
   kein Browser. **Eine Form, die keine Messung braucht, ist hier die bessere.**

   WAS HIER NICHT ENTSCHIEDEN WIRD: welche Arten es gibt und welche Bindung
   gilt. Das prueft der Vorgang beim Absenden (0031 Festlegung 2) -- diese
   Regeln blenden aus, sie erlauben nicht. */

.ui-wahl {
  border: none;
  margin: 0;
  padding: 0;
}

.ui-wahl > input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}

.ui-wahlkarten {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--ui-s4);
}

.ui-wahlkarte {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0;
  padding: var(--ui-s4) var(--ui-s5);
  min-height: 34px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  font-weight: 400;
  cursor: pointer;
}

.ui-wahlkarte::before {
  content: "";
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  border: 1px solid var(--ui-border-strong);
  border-radius: var(--ui-r-pill);
  background: #fff;
}

.ui-wahlkarte b {
  display: block;
  font-weight: 600;
  margin-bottom: 2px;
}

.ui-wahlkarte small {
  color: #5f7488;
  font-size: 0.84rem;
}

/* Die Bindungsbloecke stehen beide im Markup und **einer** wird gezeigt.
   Beide zu rendern ist der Punkt: Was gilt, entscheidet der Vorgang; die
   Flaeche zeigt nur, was zur Wahl passt. */
.ui-bindung {
  display: none;
  margin-top: var(--ui-s5);
  padding-top: var(--ui-s5);
  border-top: 1px solid #eef2f5;
}

#art-zusatz:checked ~ .ui-wahlkarten label[for="art-zusatz"],
#art-artikel:checked ~ .ui-wahlkarten label[for="art-artikel"],
#art-hub:checked ~ .ui-wahlkarten label[for="art-artikel"] {
  border-color: var(--ui-accent);
  background: #f4fbfb;
  box-shadow: 0 0 0 3px rgba(22, 155, 150, 0.14);
}

#art-zusatz:checked ~ .ui-wahlkarten label[for="art-zusatz"]::before,
#art-artikel:checked ~ .ui-wahlkarten label[for="art-artikel"]::before,
#art-hub:checked ~ .ui-wahlkarten label[for="art-artikel"]::before {
  border-color: var(--ui-accent);
  box-shadow: inset 0 0 0 4px #fff, inset 0 0 0 10px var(--ui-accent);
}

/* DIE TASTATUR VERLIERT DEN FOKUS NICHT. Das Radio ist verborgen, also traegt
   die Karte seine Fokusmarke -- sonst waere die Wahl mit der Tastatur
   erreichbar und unsichtbar. */
.ui-wahl > input[type="radio"]:focus-visible ~ .ui-wahlkarten label[for="art-zusatz"],
.ui-wahl > input[type="radio"]:focus-visible ~ .ui-wahlkarten label[for="art-artikel"] {
  outline: 2px solid var(--ui-accent);
  outline-offset: 2px;
}

#art-zusatz:checked ~ .ui-bindung-zusatz,
#art-artikel:checked ~ .ui-bindung-eigen,
#art-hub:checked ~ .ui-bindung-eigen {
  display: block;
}

/* Die zweite Ebene: Artikel oder Uebersichtsseite, innerhalb des eigenen
   Blocks. Dieselben Radios, dieselbe Kombination. */
.ui-unterwahl {
  display: flex;
  gap: var(--ui-s3);
  margin-bottom: var(--ui-s4);
}

.ui-unterwahl label {
  margin: 0;
  min-height: 34px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--ui-s5);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-sm);
  background: var(--ui-bg-card);
  color: var(--ui-text-soft);
  font-size: 0.86rem;
  cursor: pointer;
}

#art-artikel:checked ~ .ui-bindung-eigen .ui-unterwahl label[for="art-artikel"],
#art-hub:checked ~ .ui-bindung-eigen .ui-unterwahl label[for="art-hub"] {
  border-color: var(--ui-accent);
  background: #eef7f7;
  color: var(--ui-accent-dark);
}

/* Der Hinweis der Uebersichtsseite erscheint nur, wenn sie gewaehlt ist --
   `p.befund` ist die Form, die der Bestand fuer *ein Zustand, den jemand
   kennen muss* fuehrt. */
.ui-bindung-eigen .nur-hub {
  display: none;
}

#art-hub:checked ~ .ui-bindung-eigen .nur-hub {
  display: block;
}

/* ─── Schreiben und Vorschau ───────────────────────────────────────────────
   Zwei Zustaende, und **einer davon braucht den Server**: Die Vorschau ist der
   gerenderte Text. Ohne `app.js` ist der Reiter deshalb ein Seitenaufruf
   (`?ansicht=vorschau`) und kein CSS-Kniff -- die einzige Stelle des Entwurfs,
   die ohne Skript einen Wechsel kostet. */

.ui-reiterschalter {
  display: flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--ui-r-sm);
  background: #eef2f5;
}

.ui-reiterschalter a {
  padding: 5px var(--ui-s5);
  border-radius: 7px;
  color: var(--ui-text-soft);
  font-weight: 600;
  font-size: 0.82rem;
  text-decoration: none;
}

.ui-reiterschalter a.ist-aktiv {
  background: var(--ui-bg-card);
  color: var(--ui-text);
  box-shadow: 0 1px 2px rgba(15, 34, 58, 0.1);
}

.ui-feldkopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-s6);
  margin-top: var(--ui-s5);
}

.ui-feldkopf > span {
  font-size: 0.88rem;
  font-weight: 600;
}

/* Der Schritt-Zaehler vor den Ueberschriften der Anlegemaske. */
.ui-schritt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  margin-right: var(--ui-s3);
  border-radius: var(--ui-r-pill);
  background: var(--ui-accent);
  color: #fff;
  font-size: 0.7rem;
  font-weight: 700;
}

.ui-gut {
  color: #1f7d48;
  font-size: 0.84rem;
  margin: var(--ui-s2) 0 0;
}

/* Das Schreibfeld -- Festbreite, weil Markdown Ausrichtung traegt (Tabellen,
   eingerueckte Bloecke). Dieselbe Familie, die der Bestand fuer Bezeichner
   fuehrt. */
.ui-schreibfeld {
  font-family: var(--ui-font-mono);
  font-size: 0.86rem;
  line-height: 1.6;
  resize: vertical;
}

/* Zwei Spalten fuer acht kurze Felder. Untereinander waeren sie eine zweite
   lange Bahn -- genau der Zustand, den der Umbau behebt. */
.ui-feldpaare {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 var(--ui-s6);
}

/* **Die Klappe selbst bekommt hier keine Regel.** `details` und
   `details > summary` stehen weiter oben vollstaendig -- Rahmen, Radius,
   Flaeche, Marke und ihre Drehung. Ein eigener `.ui-klappe`-Block waere eine
   zweite Wahrheit ueber dasselbe Element gewesen; **beim Bauen einmal
   geschrieben und wieder entfernt**, als der Zeilenwaechter zur Aussprache
   zwang.

   `.ui-klappe-flach` ist die Ausnahme, die bleibt: dieselbe Klappe **ohne**
   eigene Tafel. Sie sitzt im Textblock und braucht keinen zweiten Rahmen. */
.ui-inhaltsklappe {
  /* Die Metadatenklappe traegt nichts Eigenes -- `details` steht oben.
     Die Klasse bleibt als Griff fuer die Nachweise. */
  margin-bottom: var(--ui-s5);
}

.ui-klappe-flach {
  border: none;
  background: none;
  margin-top: var(--ui-s6);
  border-top: 1px solid #eef2f5;
  padding-top: var(--ui-s4);
}

.ui-klappe-flach > summary {
  padding: 0;
  font-weight: 600;
  font-size: 0.86rem;
}

.ui-klappe-flach .details-inhalt {
  padding: var(--ui-s4) 0 0;
}

/* ─── Die Zustandszeile: Soll → Ist ────────────────────────────────────────
   Vorher eine Tabelle mit vier Zellen -- beide Werte sichtbar, ihr
   Zusammenhang nicht. **Der Pfeil ist der Indexlauf**, und das Fenster
   dazwischen ist der Grund, warum keine Datenbankbedingung die beiden Achsen
   koppelt (0058 Festlegung 1). */

.ui-zustandszeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s4);
}

.ui-zustandszeile p.hinweis {
  margin: 0;
}

.ui-achse {
  display: inline-flex;
  align-items: center;
  gap: var(--ui-s3);
  font-size: 0.88rem;
}

.ui-achsenname {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--ui-text-soft);
}

.ui-achsenpfeil {
  color: var(--ui-border-strong);
  flex: 0 0 auto;
}

.ui-zustandsknoepfe {
  margin-left: auto;
  display: flex;
  gap: var(--ui-s3);
}

/* Eine Zeile aus Feld und Knopf -- Umhaengen und Verselbstaendigen. */
.ui-verbleiste {
  display: flex;
  gap: var(--ui-s3);
  align-items: flex-start;
  margin-bottom: var(--ui-s6);
}

.ui-verbleiste input {
  margin-top: 0;
}

/* Die Liste, ihre Filterleiste und die Adressen darin. */
.ui-filterleiste {
  display: flex;
  align-items: flex-end;
  gap: var(--ui-s4);
}

.ui-filterleiste label {
  margin-top: 0;
}

.adresse {
  color: var(--ui-text-soft);
  font-size: 0.84rem;
}

.pfad {
  margin: 0 0 var(--ui-s6);
  font-size: 0.84rem;
  color: var(--ui-text-soft);
}

/* Ein sekundaerer Knopf, der ein Verweis ist -- die Liste bietet zwei Wege
   zum Anlegen an, und beide sind Seitenaufrufe. */
.ui-button {
  display: inline-flex;
  align-items: center;
  min-height: 34px;
  padding: 0 var(--ui-s4);
  border-radius: var(--ui-r-sm);
  border: 1px solid var(--ui-border-strong);
  background: #fff;
  color: var(--ui-text);
  font-weight: 600;
  font-size: 0.86rem;
  text-decoration: none;
}

.ui-button:hover {
  border-color: #98adb8;
  background: #f8fbfd;
  text-decoration: none;
}

/* Die gerenderte Vorschau. **Der einzige Ort dieser Flaeche, an dem fremder
   Text HTML wird** -- er entsteht in `api/ui/markdown.RENDERER` mit
   `html=False`, und was der Autor schreibt, kommt escaped an
   (`tests/unit/test_vorschau_markdown.py`). Hier steht nur, wie es aussieht. */
.vorschau {
  border: 1px solid var(--ui-border);
  border-radius: 10px;
  padding: var(--ui-s5) var(--ui-s6);
  margin-top: var(--ui-s2);
  background: #fff;
  min-height: 200px;
}

.vorschau > :first-child {
  margin-top: 0;
}

.vorschau > :last-child {
  margin-bottom: 0;
}

.vorschau h1,
.vorschau h2,
.vorschau h3 {
  margin: var(--ui-s6) 0 var(--ui-s3);
}

.vorschau p,
.vorschau ul,
.vorschau ol {
  margin: 0 0 var(--ui-s4);
}

.vorschau table {
  margin-bottom: var(--ui-s4);
}

/* Die Quellenliste des Indexierung-Reiters (0061, Einheit E7). Sie steht ueber
   der Maske: erst WOHER kommen die Inhalte, dann WIE eingestellt. */
.quellenliste {
  margin-bottom: var(--ui-s4);
  width: 100%;
}

.quellenliste caption {
  color: var(--ui-text-soft);
  font-size: 0.78rem;
  text-align: left;
}

/* Eine abgeschaltete Quelle bleibt lesbar und tritt zurueck -- sie ist nicht
   fort, es kommt nur nichts Neues dazu. */
.quellenliste tr.ist-inaktiv {
  color: var(--ui-text-soft);
}

/* Die Bedienung je Zeile der Quellenliste (0061, Einheit E7b). Zwei Formulare
   nebeneinander, kein Skript -- ein Klick darf nichts tun, was ein zweiter
   nicht rueckgaengig macht. */
.quellen-aktionen {
  white-space: nowrap;
  /* DIE AKTIONSSPALTE NIMMT, WAS SIE BRAUCHT -- NICHT MEHR (29.08.2026).
     `white-space: nowrap` macht aus jedem Text in dieser Zelle eine einzige
     unumbrechbare Zeile. Seit der Warnsatz zum Kaestchen sichtbar darin steht,
     verlangte die Zelle dessen volle Laenge, und die Tabelle gab sie ihr: Die
     Bezeichnung brach auf drei Zeilen, der Zeitpunkt auf zwei. `nowrap` gilt
     jetzt den Bedienelementen, der Satz darunter bricht um. */
  width: 1%;
  text-align: right;
}

.reihenaktion {
  display: inline;
}

/* Zerstoerend, und das steht in der Farbe. Dieselbe wie `p.fehler` -- eine
   zweite Rotmarke waere eine zweite Wahrheit. Die Rueckfrage steht im
   Formular, nicht in der Farbe. */
.ui-gefahr {
  color: #a33939;
}

/* Der feste Vorsatz vor dem Wurzelpfad (0061, Einheit E9). Er steht sichtbar
   und ist nicht bedienbar: Ein Feld, das aussieht, als naehme es einen
   absoluten Pfad, ist die Falle aus 0040. */
.feld-vorsatz {
  color: var(--ui-text-soft);
  font-size: 0.78rem;
}

/* Die Maske EINER Quelle (0061, Einheit E10). Sie steht unter der Liste und
   traegt den Namen ihrer Quelle in der Legende -- ohne ihn hiesse "Quelle"
   dort *irgendeine*. */
.quellmaske legend code {
  font-weight: 600;
}

/* Das Fehlerlog einer Quelle (Einheit B). Zugeklappt, weil ein roter Absatz,
   der bei jedem Aufruf wieder dasteht, wie ein Laufergebnis aussieht und
   keines ist. */
.fehlerlog summary {
  color: var(--ui-warn);
  cursor: pointer;
}

.fehlertext {
  background: var(--ui-bg-soft);
  border-radius: var(--ui-r-sm);
  font-size: 0.78rem;
  padding: var(--ui-s3);
  white-space: pre-wrap;
}

/* Die Loeschbestaetigung in der Zeile (Einheit 0b.3). Sie steht neben dem
   Knopf, nicht darueber -- eine Zeile bleibt eine Zeile. */
.bestaetigung {
  font-size: 0.78rem;
  white-space: nowrap;
}

/* Die Bezeichnung ist ein Bezeichner und wird nicht an jedem Bindestrich
   umbrochen. Sie darf schmal werden, aber nicht dreizeilig. */
.quellenliste td:nth-child(2) {
  min-width: 12rem;
}

/* Der Zeitpunkt steht in einer Zeile -- zwei Zeilen fuer ein Datum sind ein
   Umbruch zu viel. */
.quellenliste td:nth-child(5),
.quellenliste th:nth-child(5) {
  white-space: nowrap;
}

/* Die stehende Rueckfrage vor dem Loeschen (28.08.2026). Sie ersetzt das
   Kaestchen aus 0b.3 auf dem skriptlosen Weg und ist deshalb kein Anhaengsel
   der Zeile, sondern ein eigener Block: Wer hier steht, hat eine Frage vor
   sich und keine Bedienleiste. Sie bricht die Zeile bewusst -- das `nowrap`
   von `.quellen-aktionen` gilt hier nicht. */
.rueckfrage {
  background: var(--ui-bg-soft);
  border-left: 3px solid #a33939;
  border-radius: var(--ui-r-sm);
  display: block;
  padding: var(--ui-s3);
  white-space: normal;
}

.rueckfrage-satz {
  font-size: 0.78rem;
  margin: 0 0 var(--ui-s2);
}

/* Der Ausweg neben dem zerstoerenden Knopf. Ein Verweis und kein Knopf, weil
   er nichts tut -- er laedt die Ansicht ohne die Rueckfrage. */
.ui-abbrechen {
  font-size: 0.78rem;
  margin-left: var(--ui-s3);
}

/* Die Quellenauswahl im Reiter (Einheit C-1). Ein Inhaltsverzeichnis, keine
   zweite Liste -- deshalb ohne Rahmen und ohne Zustandsspalten. */
.quellenauswahl ul {
  list-style: none;
  margin: 0 0 var(--ui-s4);
  padding: 0;
}

.quellenauswahl li {
  padding: var(--ui-s2) 0;
}

/* Der Typ neben der Bezeichnung in der Quellenauswahl -- er ordnet ein und
   soll den Namen nicht ueberstimmen. */
.leise {
  color: var(--ui-text-soft);
  font-size: 0.78rem;
}

/* Feld und Knopf nebeneinander (Einheit C-2) -- der Knopf gehoert neben das
   Feld, nicht darunter. */
.feldreihe {
  display: flex;
  gap: var(--ui-s2);
}

.feldreihe input {
  flex: 1;
}

/* Zwei Kaesten nebeneinander (Einheit C-2). Untereinander liest man den
   zweiten als Fortsetzung des ersten -- sie beantworten aber zwei Fragen. */
.kastenreihe {
  display: grid;
  gap: var(--ui-s5);
  grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}

/* Ein gesperrter Knopf in der Quellenliste (Einheit C-3). Er steht da und
   nennt seinen Grund im `title` -- ein Knopf, der ohne Erklaerung fehlt,
   sieht aus wie ein Fehler (0040). */
.gesperrt {
  color: var(--ui-text-soft);
  cursor: not-allowed;
}

/* Das Protokoll am Ende der Ansicht (Einheit F). Zugeklappt, weil es Beleg
   ist und kein Bedienelement -- wer es aufklappt, sucht etwas Bestimmtes. */
.protokolllauf {
  border-top: 1px solid var(--ui-border);
  padding: var(--ui-s3) 0;
}

.protokolllauf summary {
  cursor: pointer;
}

.protokollfehler {
  font-size: 0.78rem;
  width: 100%;
}

/* Der Fortschrittsbalken in der Quellenzeile (28.08.2026). Schmal, weil er
   neben einem Zustandswort steht und es nicht ueberstimmen soll. */
.zeilenbalken {
  height: 4px;
  margin: var(--ui-s1) 0;
  max-width: 8rem;
}

/* ─── Die Indexierungsansicht in ihrer Rangfolge (29.08.2026) ──────────────
   Kopf -> Laufband -> Zahlenreihe -> Quellen -> Dokumente -> Belege.

   ANORDNUNG AUS TOKEN, MIT ZWEI BENANNTEN AUSNAHMEN. Jeder Abstand, jeder
   Radius und jede Schriftgroesse kommt aus dem Tokenblock am Kopf dieser
   Datei. Zwei Flaechenfarben sind neu und stehen hier, weil es fuer sie keinen
   Token gibt und geben soll -- sie sind je einmal gelesen:

     #cfe3e2  die abgeschlossene Erfassungsphase (gedaempftes Akzentgruen)
     #f2fafa  die gewaehlte Filterkarte (Akzent auf 4 % Deckung)

   Beide leiten sich vom Akzent ab und nicht von einem zweiten Farbgedanken.
   Waeren sie an mehr als einer Stelle noetig, gehoerten sie in den Token. */

/* Der Kopf: die Antwort links, die eine Aktion rechts. Umbricht bei schmaler
   Flaeche, ohne dass die Aktion unter die Falz rutscht. */
.ui-kopfsatz {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--ui-s4);
  margin-bottom: var(--ui-s5);
}

/* Der gerechnete Statussatz. Groesser als der Fliesstext, weil er die Frage
   der Seite beantwortet -- und schmal gehalten, weil ein Satz ueber 1280 px
   nicht mehr als Satz gelesen wird. */
.ui-antwort {
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.45;
  max-width: 46rem;
}

.ui-kopfaktion {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--ui-s2);
}

/* Wie alt das Gezeigte ist. Ruht der Lauf, hoert `app.js` auf nachzufragen --
   dann steht hier, dass die Zahlen stehenbleiben. */
.ui-stand {
  color: var(--ui-text-soft);
  font-size: 0.78rem;
}

/* Die Brotkrume der Quellenebene. */
.ui-pfad {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s2);
  font-size: 0.84rem;
  color: var(--ui-text-soft);
  margin-bottom: var(--ui-s3);
}

.ui-pfad-teiler {
  color: var(--ui-border-strong);
}

/* Das Laufband. Es klebt beim Scrollen: Wer waehrend eines Laufs die
   Dokumenttabelle liest, soll den Fortschritt nicht verlieren.

   `top: 0` genuegt, weil die Schale keinen festen Kopf hat -- die Navigation
   steht links. Die obere Kante traegt den Akzent, damit das Band sich vom
   Kartenfeld darunter unterscheidet, ohne eine zweite Flaechenfarbe. */
.ui-laufband {
  position: sticky;
  top: 0;
  z-index: 3;
  border: 1px solid var(--ui-border);
  border-top: 3px solid var(--ui-accent);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  box-shadow: var(--ui-shadow);
  padding: var(--ui-s5) var(--ui-s6) var(--ui-s6);
  margin-bottom: var(--ui-s6);
}

.ui-laufband-kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-s4);
  margin-bottom: var(--ui-s5);
}

.ui-laufband-wer {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s3);
}

/* Die abgeschlossene Erfassung. Gedaempft, nicht gruen: Sie hat keinen
   Nenner, also misst der volle Balken keinen Anteil, sondern sagt nur
   *fertig*. Ein gruener Balken behauptete eine Rechnung, die es nicht gibt. */
.ui-fortschritt-balken.ist-erfassung {
  background: #cfe3e2;
}

/* Zwei der fuenf Karten fuehren in die Dokumentliste. Nur die zwei, die ein
   Dokumentzustand sind -- eine Karte, die aussieht wie ein Filter und keiner
   ist, waere die Falle aus 0040. */
.ui-karte.ist-filter {
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s, background 0.15s;
}

.ui-karte.ist-filter:hover {
  border-color: var(--ui-accent);
}

.ui-karte.is-gewaehlt {
  border-color: var(--ui-accent);
  background: #f2fafa;
}

.ui-karte-fuss {
  font-size: 0.72rem;
  color: var(--ui-text-soft);
}

.ui-karte.ist-filter .ui-karte-fuss {
  color: var(--ui-accent-dark);
  font-weight: 600;
}

/* Die Filterzeile ueber der Dokumentliste. Jeder Filter ist ein Verweis, die
   Suche ein Formular mit `GET` -- kein Skript entscheidet hier etwas. */
.ui-filterzeile {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s3);
  margin-bottom: var(--ui-s4);
}

.ui-filtername {
  font-size: 0.74rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #6d8193;
  font-weight: 600;
}

.ui-filterchip {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 var(--ui-s4);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-sm);
  background: #fff;
  color: var(--ui-text-soft);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
}

.ui-filterchip.is-gewaehlt {
  background: var(--ui-text);
  border-color: var(--ui-text);
  color: #fff;
  font-weight: 700;
}

/* Das Suchfeld erbt die Feldbauform der Datei und gibt nur die Blockbreite
   auf -- es steht in einer Zeile mit den Chips. */
.ui-suchfeld {
  display: flex;
  gap: var(--ui-s2);
  align-items: center;
}

.ui-suchfeld input {
  width: 18rem;
  margin-top: 0;
}

.ui-treffer {
  margin-left: auto;
  color: var(--ui-text-soft);
  font-size: 0.82rem;
}

/* Zahlen rechtsbuendig: Chunks und Zeitpunkte vergleicht man spaltenweise. */
.ui-rechts {
  text-align: right;
}

/* Die Aktionen der Quellenebene, wo es keine Liste gibt. */
.ui-quellaktionen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ui-s4);
  margin-bottom: var(--ui-s6);
}

.ui-einzeladresse {
  margin-bottom: var(--ui-s6);
}

/* Die Belege: Herkunft, Speicherzahlen, Konfiguration, Protokoll. Zugeklappt,
   weil sie Beleg sind und kein Bedienelement -- wer sie aufklappt, sucht
   etwas Bestimmtes. Sie stehen ausserhalb des gepollten Fragments; drinnen
   klappten sie alle fuenf Sekunden wieder zu. */
.ui-belege {
  margin-top: var(--ui-s7);
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-r-md);
  background: var(--ui-bg-card);
  padding: var(--ui-s4) var(--ui-s5);
}

.ui-belege summary {
  cursor: pointer;
  font-weight: 700;
}

/* Die Abweichung zwischen Meilisearch und der Registry. Warnton, kein
   Fehlerton: Waehrend eines Laufs ist sie erwartbar, und ein Befund, der immer
   wie ein Fehler aussieht, wird ueberlesen. */
.befundzeile {
  margin-top: var(--ui-s2);
  color: #8a5a06;
  font-size: 0.82rem;
}
