/* ===========================================================================
   Bidi.Radar — die Schale der Arbeitsflächen /app und /verwaltung
   ===========================================================================
   HERKUNFT. Diese Datei ist die Portierung der Vorlage, die die
   Marketing-Abteilung am 2026-08-19 geliefert hat
   (`bidi-marketing/website/neubau-statisch/signalbank/arbeitsflaeche/`,
   Antwort auf `docs/uebergabe_marketing_oberflaeche_2026-08-19.md`). Die Welt,
   der sie folgt, steht dort in `signalbank/DESIGN.md`: Gehäuse, Gravur,
   Rechtkant, Farbreservat.

   Anders als `verkauf.html` wird diese Datei NICHT nachgezogen: geliefert war
   eine Vorlage, kein Erzeugnis. `tools/verkaufsseite_holen.py` ist deshalb
   nicht zuständig, und es gibt hier keinen `--pruefen`-Abgleich.

   ---------------------------------------------------------------------------
   Was beim Portieren entschieden wurde
   ---------------------------------------------------------------------------
   Die Vorlage bringt die Schale (83 Bauteile). Gemessen benutzen /app und
   /verwaltung 104 Klassen; 58 davon sind Produktbauteile, die es im
   Musterbogen nicht gibt — Leitstand, Berichtsansicht, Kennzahlen, Ablage,
   Filterleiste, Fußzeile. Sie stehen unten in Abschnitt 18 ff. und sind in die
   Formsprache der Vorlage übersetzt: Radius null, keine Erhebung, Haarlinien,
   Gezähltes in Mono.

   VIER FEHLER SIND DABEI MITGEGANGEN, alle derselbe Fehlergriff — eine harte
   Farbe, die nicht mit dem Thema kippt:

     · `.knopf { color: #fff }` auf `--akzent`, das im dunklen Thema auf
       #67b3ff aufhellt: gemessen 2,22:1. Der Befund kam mit der Vorlage
       (deren Abschnitt 5) und ist hier mit `--auf-akzent` behoben.
     · `.sprung { color: #fff }` auf `--tinte` — im dunklen Thema ist `--tinte`
       HELL (#e9eeeb). Weiß auf Weiß: die Sprungmarke war dort unlesbar.
       Dieselbe Ursache, andere Stelle, von der Vorlage nicht gemeldet.
     · `.preis .band` und `.schritt.*` trugen `#fff` auf Akzent bzw. Tinte.

   `--score-farbe`, `--anteil` und `.score-kreis` sind GESTRICHEN. Sie sind der
   Rest der Punktzahl, die am 2026-08-12 aus dem Produkt genommen wurde;
   gemessen kein Verweis mehr aus JS oder HTML.

   ---------------------------------------------------------------------------
   Harte Schranken, die diese Datei einhält
   ---------------------------------------------------------------------------
   · Nichts verlässt den Server: keine Webfonts, keine CDNs, kein url() nach
     draußen. Alle Symbole sind SVG als url(data:).
   · Dunkel hängt an html[data-thema="dunkel"] (ui/thema.js), nie am System.
   · Der Ausdruck ist immer hell — @media print setzt BEIDE Selektoren.
   · Sichtbarkeit hängt nie an einer Transition. CSS bewegt, JS zeigt.
   · Ampelfarben bedeuten ein Prüfergebnis. Die Schale hat genau EINE
     Buntfarbe (--akzent).
   · Kontrast ist gegen --grund gerechnet, nicht gegen Weiß.
   ========================================================================= */


/* ===========================================================================
   1. Der Farbvertrag — hell
   ========================================================================= */
:root {
  /* `light dark` würde dem Browser erlauben, die Systemwahl auf Formularfelder
     und Scrollbalken durchzuschlagen, während die Schale hell bleibt. */
  color-scheme: light;

  /* --- Marke ------------------------------------------------------------ */
  --marke-navy:   #06265a;   /* Wortmarke                                   */
  --marke-dunkel: #0a0e1a;   /* Icon-Grund                                  */
  /* Das Marken-Amber liegt bei Farbton 35,7°, das Ampel-Gelb bei 35,5°: das
     ist dieselbe Farbe, nur heller. Es gehört ins Logo und nie in die Fläche —
     sonst liest ein Bauleiter „gelb = Befund". */
  --marke-amber:  #fa9706;

  /* --- Akzent: das einzige Bunt der Schale ------------------------------ */
  --akzent:       #0b4a9e;
  --akzent-tief:  #06265a;
  --akzent-hell:  #1d6fd6;
  --akzent-hauch: #eef4fc;
  --akzent-linie: #c3d8f2;
  /* Was auf einer Akzentfläche steht. Ohne dieses Token stand dort hart #fff,
     während --akzent im dunklen Thema aufhellt — gemessen 2,22:1. Mit ihm
     kippt die Schrift mit dem Grund: 8,44:1 hell, 8,68:1 dunkel. */
  --auf-akzent:   #ffffff;

  /* --- Die vier Wertungen: reserviert ----------------------------------- */
  /* grün = gut prüfbar · gelb = kalkulierbar mit Annahmen
     orange = Rückfrage erforderlich · rot = nicht belastbar kalkulierbar
     Die Bedeutung kommt live aus /api/konfig; hier stehen nur die Töne. */
  --gruen:  #15803d;  --gruen-hauch:  #eaf6ee;  --gruen-linie:  #c4e7d0;
  --gelb:   #a16207;  --gelb-hauch:   #fdf6e3;  --gelb-linie:   #efe0b4;
  --orange: #c2410c;  --orange-hauch: #fdf0e7;  --orange-linie: #f4d5c0;
  --rot:    #b91c1c;  --rot-hauch:    #fdecec;  --rot-linie:    #f3cfcf;

  /* --- Flächen und Text ------------------------------------------------- */
  --grund:    #f5f7fb;
  --flaeche:   #ffffff;
  --flaeche-2: #f9fafd;
  --tinte:     var(--marke-navy);
  --text:      #12203a;
  --text-2:    #46536b;
  --text-3:    #657087;
  --linie:     #e0e6f0;
  --linie-2:   #eef1f7;

  /* --- Hebung: die Signalbank ist flach --------------------------------- */
  /* Gemessen am gebauten Zustand: die ganze Welt trägt genau zwei box-shadow,
     und beide sind INSET-Haarlinien am Fokus — kein einziger Schlagschatten.
     Tiefe kommt aus Gehäusestufen und Haarlinien, nicht aus Weichzeichnung.
     Die drei Stufen bleiben als Namen stehen, weil das Markup sie anspricht;
     zwei davon sind `none`. Einen Schatten wirft nur, was wirklich ÜBER dem
     Inhalt schwebt — und das gibt es genau zweimal (Dialog, Seitenblatt). */
  --hebung-1: none;
  --hebung-2: none;
  --hebung-3: 0 24px 56px -24px rgba(6, 38, 90, .38);
  /* Der Fokus liegt INNEN, wie an den Feldern der Verkaufsseite. Ein weicher
     Außenhof wäre der einzige unscharfe Rand der ganzen Welt. */
  --ring:     inset 0 0 0 1px var(--akzent);

  /* --- Maß -------------------------------------------------------------- */
  /* NICHTS IST GERUNDET. `border-radius` kommt in der gebauten Signalbank
     null mal vor — Verkaufsseite und alle vier Rechtstexte. Ein Gerät hat
     gefräste Kanten. Die drei Stufen bleiben als Namen stehen, weil das
     Markup sie anspricht; alle drei sind 0. Wer hier eine Zahl einsetzt,
     verlässt die Welt. */
  --r-klein: 0;
  --r:       0;
  --r-gross: 0;
  --breite:  1200px;
  --hoehe:   44px;          /* Mindest-Tippfläche, nicht verhandelbar */

  /* --- Bewegung: EIN Rhythmus für alles --------------------------------- */
  --zeit-schnell: 140ms;
  --zeit:         220ms;
  --zeit-lang:    320ms;
  --kurve:      cubic-bezier(.22, .8, .32, 1);
  --kurve-rein: cubic-bezier(.4, 0, 1, 1);

  /* --- Schrift ---------------------------------------------------------- */
  /* Kein Webfont: der Systemstapel rendert sofort, kostet keine Anfrage und
     verlässt das Haus nicht. Mono trägt alles Gezählte — OZ, Beträge, IDs. */
  --sans: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system,
          "SF Pro Text", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "Cascadia Code", SFMono-Regular,
          "SF Mono", Consolas, "Liberation Mono", monospace;

  --kopf-h: 60px;

  /* Staffelung des Auftritts. Wird von ui/effekte.js je Element gesetzt und
     ist deshalb kein Gestaltungswert, sondern eine Naht zum JavaScript. */
  --verzug: 0ms;
}


/* ===========================================================================
   2. Dunkel ist eine WAHL
   ===========================================================================
   Gesetzt von ui/thema.js auf <html>, gespeichert unter `bidi-radar-thema`.
   Der Grund ist das Gehäuse der Signalbank, nicht ein aufgehelltes Schwarz:
   wer von der Verkaufsseite hereinkommt, soll dasselbe Gerät sehen.
   Die Töne sind entsättigt, keine invertierten Hellwerte.

   Dass es kein `@media (prefers-color-scheme: dark)` gibt, ist Absicht und
   testgesichert: eine zweite Quelle für dieselbe Entscheidung überstimmt die
   Wahl des Nutzers still. Wer das System berücksichtigen will, tut es in
   thema.js beim ersten Besuch. */
html[data-thema="dunkel"] {
  color-scheme: dark;

  --akzent:       #67b3ff;
  --akzent-tief:  #9ccdff;
  --akzent-hell:  #9ccdff;
  --akzent-hauch: #14242f;
  --akzent-linie: #1f4257;
  --auf-akzent:   var(--marke-dunkel);

  /* Zeichen für Zeichen die Messfarben der Signalbank. */
  --gruen:  #4ade80;  --gruen-hauch:  #10241a;  --gruen-linie:  #204431;
  --gelb:   #fcd34d;  --gelb-hauch:   #241f0e;  --gelb-linie:   #4a3d15;
  --orange: #fb923c;  --orange-hauch: #26190e;  --orange-linie: #4d3017;
  --rot:    #f87171;  --rot-hauch:    #2a1618;  --rot-linie:    #56242a;

  /* Zeichen für Zeichen die Gehäusewerte der Verkaufsseite — keine eigenen.
     Zwei Sätze für dasselbe Gehäuse wären zwei Wahrheiten. Gemessen gegen
     --grund: --text 16,27:1 · --text-2 8,59:1 · --text-3 6,26:1. */
  --grund:     #0e100f;   /* --chassis   */
  --flaeche:   #151817;   /* --chassis-2 */
  --flaeche-2: #1d211f;   /* --chassis-3 */
  --tinte:     #e9eeeb;   /* --text      */
  --text:      #e9eeeb;
  --text-2:    #a7b0ab;   /* --text-2    */
  --text-3:    #8c9691;   /* --gravur    */
  --linie:     #333a37;   /* --linie-hell — die kräftigere der beiden */
  --linie-2:   #262b29;   /* --linie      — die leisere */

  --hebung-1: none;
  --hebung-2: none;
  --hebung-3: 0 24px 56px -24px rgba(0, 0, 0, .9);
  --ring:     inset 0 0 0 1px var(--akzent);
}


/* ===========================================================================
   3. Grundlagen
   ========================================================================= */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--kopf-h) + 24px);
}

body {
  margin: 0;
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--text);
  background: var(--grund);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4 { color: var(--tinte); margin: 0; line-height: 1.18; font-weight: 650;
                 letter-spacing: -.015em; text-wrap: balance; }
h1 { font-size: clamp(1.4rem, 2.6vw, 1.85rem); }
h2 { font-size: 1.16rem; }
h3 { font-size: 1rem; }
h4 { font-size: 1rem; }
p  { margin: 0; text-wrap: pretty; }

a { color: var(--akzent); text-decoration: none; }
a:hover { text-decoration: underline; }

svg { display: block; }

:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; border-radius: var(--r-klein); }
::selection { background: color-mix(in srgb, var(--akzent) 24%, transparent); }

.huelle { width: 100%; max-width: var(--breite); margin: 0 auto; padding: 0 22px; }

/* Gravur — die Beschriftung eines Bedienteils, kein Marketing-Kicker. */
.gravur {
  font-size: 11px; font-weight: 650; letter-spacing: .19em;
  text-transform: uppercase; color: var(--text-3);
}

/* Alles Gezählte in Mono: OZ, Beträge, IDs, Uhrzeiten. Ziffern in gleicher
   Breite lassen sich untereinander vergleichen — darum geht es hier. */
.mono, .tabellenzahl, .oz, .betrag, .zahl {
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-size: .93em; letter-spacing: -.01em;
}
/* Zahlen stehen rechtsbuendig: nur so liegen die Stellen untereinander. */
.zahl, .tabellenzahl { text-align: right; }

/* Die Sprungmarke liegt auf --tinte. Hart #fff wäre im dunklen Thema weiß auf
   weiß gewesen (dort ist --tinte hell) — dieselbe Falle wie beim Hauptknopf. */
.sprung { position: absolute; left: -9999px; top: 0; z-index: 200;
          background: var(--tinte); color: var(--flaeche); padding: 12px 18px; font-weight: 620; }
.sprung:focus { left: 0; }

.nur-lesbar, .nur-leser {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.verstecken { display: none !important; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  /* Stilllegen heißt NICHT verstecken. Der Auftritt (Abschnitt 19) setzt
     Elemente auf opacity 0 und blendet sie per Beobachter ein — ohne diese
     Zeile bliebe die ganze Arbeitsfläche leer, sobald jemand weniger Bewegung
     wünscht. Gemessen und testgesichert. */
  .auftritt, html.js .auftritt { opacity: 1 !important; transform: none !important; }
}


/* ===========================================================================
   4. Gehäusekopf mit Navigation
   ========================================================================= */
.kopf {
  position: sticky; top: 0; z-index: 100; height: var(--kopf-h);
  background: var(--flaeche);
  border-bottom: 1px solid var(--linie);
}
.kopf .huelle { display: flex; align-items: center; gap: 16px; height: 100%; }
/* Beim Scrollen tritt der Kopf eine Stufe hervor. In der flachen Welt ist das
   eine kräftigere Kante, kein Schatten — --hebung-1 ist `none`. */
.kopf.geschoben { border-bottom-color: var(--text-3); }

.marke { display: flex; align-items: center; gap: 12px; margin-right: auto; }
.marke .wort, .marke .wortmarke {
  font-weight: 700; font-size: 17px; color: var(--tinte); letter-spacing: -.02em;
}
/* Der Punkt in der Wortmarke ist ein Logo, kein Prüfergebnis — unbunt. */
.marke .wortmarke i { font-style: normal; color: var(--text-3); }
.marke .wort .praefix { color: var(--akzent); font-weight: 800; }
.marke img { height: 21px; width: auto; display: block; }
.marke-klein {
  font-family: var(--mono); font-size: 11px; color: var(--text-3); letter-spacing: .08em;
  border-left: 1px solid var(--linie); padding-left: 12px;
}
.marke-klein.akzent { background: var(--akzent-hauch); color: var(--akzent-tief);
                      border-left-color: var(--akzent-linie); padding: 2px 8px; }
@media (max-width: 700px) { .marke-klein { display: none; } }

.kopf .nebenan { margin-left: auto; display: flex; align-items: center; gap: 8px; flex: none; }

.kopf nav, .kopf-nav { display: flex; gap: 4px; }
.kopf nav a:not(.knopf), .kopf-nav a {
  display: inline-flex; align-items: center; height: 36px; padding: 0 12px;
  font-size: 13.5px; color: var(--text-2); border-radius: var(--r-klein);
  border: 1px solid transparent;
}
.kopf nav a:not(.knopf):hover, .kopf-nav a:hover {
  color: var(--tinte); background: var(--flaeche-2); text-decoration: none;
}
.kopf nav a[aria-current="page"], .kopf-nav a[aria-current="page"] {
  color: var(--tinte); background: var(--akzent-hauch); border-color: var(--akzent-linie);
}

/* Der Menüknopf ist ein EIGENSTÄNDIGER Knopf, nicht `.knopf.menue-knopf` —
   so steht er in app.html. Ein Selektor mit `.knopf` davor greift hier nie und
   ließe ihn am Schreibtisch stehen; sein Symbol ist außerdem ein Strichsymbol
   ohne eigene Attribute und käme ohne `stroke` als schwarzer Klotz. */
.menue-knopf {
  position: relative;
  display: none; place-items: center; width: 40px; height: 40px; flex: none;
  padding: 0; background: var(--flaeche); border: 1px solid var(--linie);
  border-radius: var(--r-klein); cursor: pointer;
}
/* Er sieht 40 px hoch aus und lässt sich auf 44 px treffen — er ist auf dem
   Telefon der einzige Weg zur Navigation. */
.menue-knopf::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 44px;
}
.menue-knopf:hover { background: var(--flaeche-2); border-color: var(--text-3); }
.menue-knopf svg {
  width: 20px; height: 20px;
  stroke: var(--tinte); stroke-width: 2; fill: none; stroke-linecap: square;
}

/* --- Guthaben im Kopf --------------------------------------------------- */
/* Unbunt bis auf den Akzent: eine Zahl, kein Prüfergebnis. */
.guthaben-marke {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 36px; padding: 0 14px;
  border-radius: var(--r-klein);
  background: var(--akzent-hauch); color: var(--akzent-tief);
  border: 1px solid var(--akzent-linie);
  font-family: var(--mono); font-variant-numeric: tabular-nums;
  font-weight: 640; font-size: .84rem; white-space: nowrap;
}
.guthaben-marke svg { width: 15px; height: 15px; }

/* --- Themenschalter ---------------------------------------------------- */
/* Zwei Tasten statt eines Kippschalters: der Zustand ist ablesbar, ohne ihn
   zu betätigen. aria-pressed trägt die Aussage, nicht die Farbe. */
/* Der Musterbogen zeigt zwei ikonische 34-px-Tasten mit unsichtbarer
   Beschriftung. app.html hat BESCHRIFTETE Tasten (Symbol + „Hell"/„Dunkel"),
   und die bleiben — die Struktur der Ansichten wandert beim Portieren nicht.
   Eine feste Breite von 34 px hätte das Wort aus dem Knopf herauslaufen lassen:
   gemessen 42 px Text in einem 34 px breiten Knopf. Die Taste wächst deshalb
   mit ihrer Beschriftung; unter 640 px bleibt nur das Symbol. */
.thema-schalter {
  display: inline-flex; flex: none;
  border: 1px solid var(--linie); border-radius: var(--r-klein);
  background: var(--flaeche); overflow: hidden;
}
.thema-schalter button {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 34px; padding: 0 11px;
  font: inherit; font-size: .8rem; font-weight: 620;
  background: var(--flaeche); color: var(--text-2); border: 0; cursor: pointer;
  transition: background var(--zeit-schnell) var(--kurve), color var(--zeit-schnell) var(--kurve);
}
/* Die Tippfläche bleibt 44 px, auch wenn die Taste 34 px hoch aussieht. */
.thema-schalter button::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 44px;
}
.thema-schalter button + button { border-left: 1px solid var(--linie); }
.thema-schalter button:hover { background: var(--flaeche-2); color: var(--tinte); }
.thema-schalter button[aria-pressed="true"] { background: var(--akzent-hauch); color: var(--akzent-tief); }
/* Strichsymbole: sie tragen kein fill/stroke im Markup und wären sonst
   schwarze Flächen. Gemessen — beide Schaltersymbole standen so da. */
.thema-schalter svg {
  width: 15px; height: 15px; flex: none;
  stroke: currentColor; stroke-width: 1.9; fill: none;
  stroke-linecap: square; stroke-linejoin: miter;
}


/* ===========================================================================
   5. Karte
   ========================================================================= */
.karte {
  background: var(--flaeche);
  border: 1px solid var(--linie);
  border-radius: var(--r);
}
.karte-kopf {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 14px 18px; border-bottom: 1px solid var(--linie-2);
}
.karte-kopf h2, .karte-kopf h3 { margin-right: auto; }
.karte-kopf .rechts { margin-left: auto; }
.karte-rumpf { padding: 18px; }
/* Gestapelte Karten brauchen Abstand — im Raster regelt ihn `gap`, sonst
   nichts. Ohne diese Regel kleben die Karten von /app/konto aneinander. */
.karte + .karte { margin-top: 20px; }
.karten-raster > .karte + .karte,
.preis-raster > .karte + .karte,
.leitstand-raster > .karte + .karte { margin-top: 0; }
.karte > :last-child { margin-bottom: 0; }
.karte-fuss {
  padding: 13px 18px; border-top: 1px solid var(--linie-2);
  background: var(--flaeche-2);
  display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
}
.karten-raster { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }

/* Eine anfassbare Karte hebt sich nicht — sie zeigt eine kräftigere Kante.
   In der flachen Welt ist --hebung-3 der einzige echte Schatten, und der
   gehört dem, was über dem Inhalt schwebt. */
.karte.hebt { transition: border-color var(--zeit-schnell) var(--kurve); }
.karte.hebt:hover { border-color: var(--akzent); }


/* ===========================================================================
   6. Tabelle
   ===========================================================================
   Der Rahmen scrollt, die Tabelle nicht: eine Tabelle in einer klippenden
   Kiste verliert Spalten ohne ein Wort. */
.tabellen-rahmen { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: .93rem; }
th {
  text-align: left; padding: 10px 12px; white-space: nowrap;
  font-size: 11px; font-weight: 650; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-3); background: var(--flaeche-2);
  border-bottom: 1px solid var(--linie);
}
td { padding: 12px; border-bottom: 1px solid var(--linie-2); vertical-align: top; }
tbody tr:hover td { background: var(--flaeche-2); }
tbody tr:last-child td { border-bottom: 0; }
.rechts { text-align: right; }


/* ===========================================================================
   7. Formularfeld
   ========================================================================= */
.feld { margin-bottom: 16px; }
.feld > label {
  display: block; margin-bottom: 6px;
  font-size: 11px; font-weight: 650; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-3);
}
input[type=text], input[type=email], input[type=password],
input[type=number], input[type=date], input[type=search], input[type=tel],
select, textarea {
  width: 100%; min-height: var(--hoehe); padding: 10px 13px;
  font-family: inherit; font-size: 1rem; color: var(--text);
  background: var(--flaeche);
  border: 1px solid var(--linie); border-radius: var(--r-klein);
  transition: border-color var(--zeit-schnell) var(--kurve), box-shadow var(--zeit-schnell) var(--kurve);
}
textarea { min-height: 96px; resize: vertical; line-height: 1.55; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--akzent); box-shadow: var(--ring);
}
input::placeholder, textarea::placeholder { color: var(--text-3); }
input:disabled, select:disabled, textarea:disabled {
  background: var(--flaeche-2); color: var(--text-3); cursor: not-allowed;
}
/* Das fehlerhafte Feld trägt KEIN Rot — sonst hieße Rot zweierlei. Es trägt
   eine kräftigere Kante RINGSUM und den Grund darunter im Klartext.
   Ringsum und nicht links: die linke Kante ist im Meldungssatz schon vergeben
   (.meldung.gut heißt „erledigt"). Dieselbe Form zweimal mit verschiedener
   Bedeutung ist genau der Fehler, den dieses Stylesheet bei den Farben
   vermeidet. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] {
  border-color: var(--tinte); border-width: 2px; padding: 9px 12px;
}
.hinweis-text, .feld small { display: block; margin-top: 6px; font-size: .875rem; color: var(--text-3); }
.feld-fehler {
  display: flex; gap: 7px; align-items: flex-start;
  margin-top: 6px; font-size: .875rem; font-weight: 620; color: var(--tinte);
}
.feld-fehler::before {
  content: ""; width: 15px; height: 15px; flex: none; margin-top: 2px; background: currentColor;
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M10 3h4v11h-4zM10 17h4v4h-4z'/%3E%3C/svg%3E");
  -webkit-mask: var(--zeichen) center/contain no-repeat; mask: var(--zeichen) center/contain no-repeat;
}
.feld-reihe { display: grid; gap: 0 16px; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

.haken { display: flex; align-items: flex-start; gap: 11px; margin-bottom: 14px;
         font-size: .93rem; line-height: 1.55; cursor: pointer; }
.haken input { margin: 3px 0 0; flex: none; width: 18px; height: 18px; min-height: 0;
               accent-color: var(--akzent); cursor: pointer; }
.haken input:disabled { cursor: not-allowed; }
.haken input:disabled + span { color: var(--text-3); }


/* ===========================================================================
   8. Bedienteile
   ===========================================================================
   Drei Ränge, keine Farbe als Rang. Haupt trägt den Akzent, Neben trägt eine
   Kante, Gefahr trägt eine SCHRAFFUR.

   Warum Gefahr nicht rot ist: Rot bedeutet in diesem Produkt „nicht belastbar
   kalkulierbar". Ein roter Löschen-Knopf sagt dasselbe Rot ein zweites Mal und
   meint etwas anderes. Die Warnung kommt hier aus dem Muster — so, wie an einer
   Maschine eine gesicherte Taste schraffiert ist —, aus dem Wort und aus dem
   Rückfrage-Dialog davor. Das ist strenger als Farbe, nicht lockerer.
   (Bis zum 2026-08-19 stand hier `background: var(--rot)`.) */
.knopf {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: var(--hoehe); padding: 0 20px;
  font-family: inherit; font-size: .93rem; font-weight: 620; letter-spacing: .01em;
  color: var(--auf-akzent); background: var(--akzent);
  border: 1px solid var(--akzent); border-radius: var(--r-klein);
  cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background var(--zeit-schnell) var(--kurve),
              border-color var(--zeit-schnell) var(--kurve),
              transform var(--zeit-schnell) var(--kurve);
}
.knopf:hover { background: var(--akzent-tief); border-color: var(--akzent-tief);
               text-decoration: none; }
.knopf:active { transform: scale(.975); }
.knopf:disabled, .knopf[aria-disabled="true"] {
  opacity: .5; cursor: not-allowed; transform: none;
}
.knopf svg { width: 18px; height: 18px; flex: none; }

.knopf.zweit {
  color: var(--tinte); background: var(--flaeche); border-color: var(--linie);
}
.knopf.zweit:hover { background: var(--flaeche-2); border-color: var(--text-3); }

.knopf.stumm { color: var(--text-2); background: transparent; border-color: transparent; }
.knopf.stumm:hover { color: var(--tinte); background: var(--linie-2); }

.knopf.gefahr {
  color: var(--tinte); background: var(--flaeche);
  border: 1px solid var(--tinte);
  position: relative; overflow: hidden;
}
/* Das Schraffurband unten: das Muster warnt, nicht der Farbton. */
.knopf.gefahr::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 5px;
  background: repeating-linear-gradient(135deg,
              var(--tinte) 0 3px, transparent 3px 7px);
  opacity: .55;
}
.knopf.gefahr:hover { color: var(--flaeche); background: var(--tinte); }
.knopf.gefahr:hover::after { background: repeating-linear-gradient(135deg,
              var(--flaeche) 0 3px, transparent 3px 7px); opacity: .5; }

.knopf.klein { min-height: 36px; padding: 0 14px; font-size: .875rem; }
.knopf.gross { min-height: 52px; padding: 0 28px; font-size: 1.04rem; }
.knopf.breit { width: 100%; }
.knopf-reihe { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.karte-fuss .knopf-reihe .knopf { flex: 1 1 auto; }

/* Ein kleiner Knopf ist 36 px hoch — die Tippfläche bleibt trotzdem 44 px.
   Der unsichtbare Streifen ragt über die Sichtkante hinaus. */
.knopf.klein { position: relative; }
.knopf.klein::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 44px;
}


/* ===========================================================================
   9. Meldungen — vier Tonlagen OHNE Ampelfarbe
   ===========================================================================
   Das ist die Stelle, an der sonst Nacharbeit entsteht. Eine grüne
   Erfolgsmeldung und eine rote Fehlermeldung wären bequem — und sie würden
   dieselben vier Farben belegen, mit denen das Produkt ein Leistungsverzeichnis
   bewertet. Der Kunde läse eine Aussage über sein LV, die niemand gemeint hat.

   Vier Tonlagen, vier Träger. KEINER davon ist ein Farbton:

     fehler    UMKEHRUNG. Die Leiste kippt auf --tinte mit heller Schrift.
               Das ist das einzige umgekehrte Bauteil im ganzen Werkzeug —
               es kann deshalb mit nichts verwechselt werden.
     gut       KANTE. Weiße Fläche, links eine massive Akzentkante. Ein Fakt,
               abgehakt und abgelegt.
     hinweis   FLÄCHE. Akzenthauch, keine Kante. Liegt flach im Blatt, weil er
               nichts verlangt.
     schranke  SCHRAFFUR. Neutrale Fläche, links ein schraffierter Balken.
               Für Zustände, die kein Fehler sind und trotzdem den Weg
               versperren: Kontingent für heute erschöpft, Guthaben leer,
               AVV noch nicht bestätigt.

   Alle vier bleiben in Graustufen unterscheidbar, alle vier tragen zusätzlich
   ein Symbol UND ein Wort. Farbe wäre hier ohnehin nur die vierte Sicherung. */
.meldung {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 13px 15px; margin-bottom: 18px;
  border: 1px solid var(--linie); border-radius: var(--r);
  background: var(--flaeche); color: var(--text);
  font-size: .93rem;
  animation: einblenden var(--zeit-lang) var(--kurve);
}
.meldung:empty { display: none; }
.meldung::before {
  content: ""; width: 19px; height: 19px; flex: none; margin-top: 1px;
  background: currentColor;
  -webkit-mask: var(--zeichen) center/contain no-repeat;
  mask: var(--zeichen) center/contain no-repeat;
}
/* Das Wort trägt die Tonlage mit — für Graustufen, Vorlesegeräte und Papier. */
.meldung .wort {
  font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  display: block; margin-bottom: 2px; opacity: .8;
}

.meldung.fehler {
  background: var(--tinte); border-color: var(--tinte); color: var(--flaeche);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M10 3h4v11h-4zM10 17h4v4h-4z'/%3E%3C/svg%3E");
}
.meldung.fehler a { color: inherit; text-decoration: underline; }

.meldung.gut {
  border-left: 4px solid var(--akzent); padding-left: 12px;
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M3.5 12.2l2.9-2.9 3.8 3.8 7.4-7.4 2.9 2.9-10.3 10.3z'/%3E%3C/svg%3E");
}
.meldung.gut::before { color: var(--akzent); }

.meldung.hinweis {
  background: var(--akzent-hauch); border-color: var(--akzent-linie); color: var(--akzent-tief);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M10 3h4v4h-4zM10 10h4v11h-4z'/%3E%3C/svg%3E");
}

.meldung.schranke {
  position: relative; overflow: hidden; padding-left: 23px;
  background: var(--flaeche-2); color: var(--text-2);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M7 11V6h10v5h-2.5V8.5h-5V11z'/%3E%3Cpath d='M4 12h16v9H4z'/%3E%3C/svg%3E");
}
.meldung.schranke::after {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 8px;
  background: repeating-linear-gradient(135deg,
              var(--text-3) 0 3px, transparent 3px 7px);
}
.meldung.schranke::before { color: var(--text-2); }

@keyframes einblenden {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}


/* ===========================================================================
   10. Abzeichen für die vier Wertungen
   ===========================================================================
   HIER ist Farbe die Aussage — und nur hier. Trotzdem trägt jedes Abzeichen
   zusätzlich eine eigene FORM und ein Wort: rund 8 % der Männer sehen Rot und
   Grün nicht auseinander, und ein Prüfergebnis darf nicht an einem Sinn hängen.

     volle Zelle      grün    gut prüfbar
     halb gefüllt     gelb    kalkulierbar mit Annahmen
     oben offen       orange  Rückfrage erforderlich
     durchgestrichen  rot     nicht belastbar kalkulierbar
     leere Zelle      leer    ungewertet

   Ein Pegel wäre falsch gewesen: „Rückfrage" ist kein Füllstand, sondern eine
   Lücke. Und zwei Drittel gegen ein Drittel sind bei 13 px nicht zu trennen.

   Die Bedeutungstexte kommen live aus /api/konfig (`ampel_bedeutung`) und
   stehen deshalb NICHT in dieser Datei. */
.ampel {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 10px 3px 8px;
  font-size: 12px; font-weight: 650; letter-spacing: .02em; white-space: nowrap;
  border: 1px solid transparent; border-radius: var(--r-klein);
}
.ampel::before {
  content: ""; width: 13px; height: 13px; flex: none; background: currentColor;
  -webkit-mask: var(--zeichen) center/contain no-repeat;
  mask: var(--zeichen) center/contain no-repeat;
}
.ampel.gruen {
  color: var(--gruen); background: var(--gruen-hauch); border-color: var(--gruen-linie);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M4 4h16v16H4z'/%3E%3C/svg%3E");
}
.ampel.gelb {
  color: var(--gelb); background: var(--gelb-hauch); border-color: var(--gelb-linie);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath fill-rule='evenodd' d='M3 3h18v18H3zm2 2v14h14V5z'/%3E%3Cpath d='M7 7h5v10H7z'/%3E%3C/svg%3E");
}
.ampel.orange {
  color: var(--orange); background: var(--orange-hauch); border-color: var(--orange-linie);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M3 3h6v2H5v14h14V5h-4V3h6v18H3z'/%3E%3C/svg%3E");
}
.ampel.rot {
  color: var(--rot); background: var(--rot-hauch); border-color: var(--rot-linie);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath fill-rule='evenodd' d='M3 3h18v18H3zm2 2v14h14V5z'/%3E%3Cpath d='M8.4 7l8.6 8.6-1.4 1.4L7 8.4z'/%3E%3Cpath d='M15.6 7L17 8.4 8.4 17 7 15.6z'/%3E%3C/svg%3E");
}
.ampel.leer {
  color: var(--text-2); background: var(--linie-2); border-color: var(--linie);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath fill-rule='evenodd' d='M3 3h18v18H3zm2 2v14h14V5z'/%3E%3C/svg%3E");
}

/* Der Punkt ist dasselbe Zeichen ohne Text — in Listen, wo der Platz für ein
   Abzeichen fehlt. Ein QUADRAT, kein Kreis: die Welt kennt keine runde Form,
   und die Wertung soll dieselbe Gestalt haben wie im Abzeichen. */
.punkt {
  width: 11px; height: 11px; flex: none; display: inline-block;
  background: currentColor;
  -webkit-mask: var(--zeichen) center/contain no-repeat;
  mask: var(--zeichen) center/contain no-repeat;
}
.punkt.gruen  { color: var(--gruen);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M4 4h16v16H4z'/%3E%3C/svg%3E"); }
.punkt.gelb   { color: var(--gelb);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath fill-rule='evenodd' d='M3 3h18v18H3zm2 2v14h14V5z'/%3E%3Cpath d='M7 7h5v10H7z'/%3E%3C/svg%3E"); }
.punkt.orange { color: var(--orange);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M3 3h6v2H5v14h14V5h-4V3h6v18H3z'/%3E%3C/svg%3E"); }
.punkt.rot    { color: var(--rot);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath fill-rule='evenodd' d='M3 3h18v18H3zm2 2v14h14V5z'/%3E%3Cpath d='M8.4 7l8.6 8.6-1.4 1.4L7 8.4z'/%3E%3Cpath d='M15.6 7L17 8.4 8.4 17 7 15.6z'/%3E%3C/svg%3E"); }
.punkt.leer   { color: var(--text-3);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath fill-rule='evenodd' d='M3 3h18v18H3zm2 2v14h14V5z'/%3E%3C/svg%3E"); }


/* ===========================================================================
   11. Schrittanzeige 1 – 2 – 3
   ========================================================================= */
.schritte { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 24px; padding: 0; list-style: none; }
.schritt {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 14px 7px 8px; font-size: .875rem; color: var(--text-3);
  background: var(--flaeche); border: 1px solid var(--linie); border-radius: var(--r-klein);
}
.schritt b {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none;
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  /* --text-3 auf --linie-2 sind gemessen 4,40:1 und damit zu wenig für 12 px. */
  background: var(--linie-2); color: var(--text-2); border-radius: var(--r-klein);
}
.schritt.jetzt { color: var(--tinte); background: var(--akzent-hauch); border-color: var(--akzent-linie); }
.schritt.jetzt b { background: var(--akzent); color: var(--auf-akzent); }
.schritt.fertig { color: var(--text-2); }
/* Bis zum 2026-08-19 war das Häkchen grün — eine Ampelfarbe als Schmuck. */
.schritt.fertig b { background: var(--tinte); color: var(--flaeche); }


/* ===========================================================================
   12. Dialog
   ===========================================================================
   Das native <dialog> mit showModal(): Fokusfalle, Esc und inert kommen vom
   Browser und nicht aus einer nachgebauten Halterung. */
dialog {
  width: min(560px, calc(100vw - 32px)); padding: 0;
  color: var(--text); background: var(--flaeche);
  border: 1px solid var(--linie); border-radius: var(--r);
  box-shadow: var(--hebung-3);
}
dialog::backdrop { background: color-mix(in srgb, var(--marke-navy) 42%, transparent);
                   backdrop-filter: blur(2px); }
html[data-thema="dunkel"] dialog::backdrop { background: rgba(0, 0, 0, .62); }
.dialog-kopf { display: flex; align-items: center; gap: 12px; padding: 16px 18px;
               border-bottom: 1px solid var(--linie-2); }
.dialog-kopf h2 { margin-right: auto; font-size: 1.04rem; }
.dialog-rumpf { padding: 18px; max-height: min(60vh, 520px); overflow: auto; }
.dialog-fuss { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end;
               padding: 14px 18px; border-top: 1px solid var(--linie-2); background: var(--flaeche-2); }


/* ===========================================================================
   13. Seitenblatt
   ===========================================================================
   ACHTUNG, hier ist schon einmal etwas kaputtgegangen: die Sichtbarkeit hing
   an der Transition. Im Hintergrund-Tab rechnet der Browser Übergänge nicht zu
   Ende — das Blatt blieb sichtbar über dem Inhalt stehen und fing jeden Klick
   ab. Deshalb die Arbeitsteilung:

       CSS bewegt (transform).   JS zeigt und verbirgt (visibility).

   `visibility` steht als eigene Erklärung im Block und NICHT im Übergang;
   gesetzt wird sie von ergebnis.js (baueSeitenblatt). Testgesichert. */
.seitenblatt {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 120;
  width: min(460px, 100vw);
  display: flex; flex-direction: column;
  background: var(--flaeche); border-left: 1px solid var(--linie);
  box-shadow: var(--hebung-3);
  transform: translateX(100%); visibility: hidden;
  transition: transform var(--zeit-lang) var(--kurve);
}
.seitenblatt.offen { transform: none; }
.seitenblatt-kopf {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 18px; border-bottom: 1px solid var(--linie-2);
}
.seitenblatt-kopf h2, .seitenblatt-kopf h3 { margin-right: auto; font-size: 1.04rem; }
.seitenblatt-rumpf { flex: 1; overflow: auto; padding: 18px; overscroll-behavior: contain; }
@media (prefers-reduced-motion: reduce) { .seitenblatt { transition: none; } }


/* ===========================================================================
   14. Leerer Zustand
   ========================================================================= */
.leer-zustand { text-align: center; padding: clamp(32px, 6vw, 56px) 20px; color: var(--text-2); }
/* `.sinnbild` ist im Produkt ein KASTEN mit einem Symbol darin
   (`<span class="sinnbild"><svg></span>`), nicht das Symbol selbst wie im
   Musterbogen. Ohne die Größe am inneren SVG wächst dieses auf die volle
   Breite des Elternteils — gemessen 1114 px. */
.sinnbild {
  width: 44px; height: 44px; flex: none;
  display: grid; place-items: center; margin-bottom: 16px;
  background: var(--flaeche-2); color: var(--text-3);
  border: 1px solid var(--linie);
}
.sinnbild svg { width: 22px; height: 22px; }
.leer-zustand .sinnbild { margin-inline: auto; }
.leer-zustand .gross { display: block; font-size: 1.04rem; font-weight: 620; color: var(--tinte); margin-bottom: 6px; }
.leer-zustand p, .leer-zustand small { display: block; max-width: 46ch; margin: 0 auto 18px; }


/* ===========================================================================
   15. Ladezustand
   ===========================================================================
   Ein Gerüst statt eines Kreisels: es zeigt, WAS gleich dasteht. Der Schimmer
   ist abgeschaltet, sobald der Nutzer weniger Bewegung wünscht. */
.geruest { background: var(--linie-2); border-radius: var(--r-klein); overflow: hidden; position: relative; }
.geruest::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--flaeche) 70%, transparent), transparent);
  transform: translateX(-100%);
  animation: schimmer 1.35s var(--kurve) infinite;
}
.geruest.zeile { height: 13px; margin-bottom: 9px; }
.geruest.zeile.kurz { width: 42%; }
.geruest.zeile.mittel { width: 68%; }
.geruest.block { height: 96px; }
@keyframes schimmer { to { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .geruest::after { animation: none; } }

/* Kein Kreisel: ein Kreis wäre die einzige runde Form der ganzen Welt
   (Rechtkant-Regel). Stattdessen ein laufender Strich — dieselbe Bewegung, die
   der Strahl auf dem Schirm macht. Unbunt: er misst nichts. */
.laedt { display: inline-flex; align-items: center; gap: 11px; color: var(--text-2); font-size: .93rem; }
.laedt::before {
  content: ""; width: 34px; height: 3px; flex: none; align-self: center;
  background: var(--linie);
  background-image: linear-gradient(90deg, var(--text-3) 0 34%, transparent 34%);
  background-repeat: no-repeat; background-size: 34% 100%;
  animation: laeuft 1.1s var(--kurve) infinite;
}
@keyframes laeuft { from { background-position: -50% 0; } to { background-position: 150% 0; } }

/* Der Fortschrittsbalken des Uploads. Gerade Kanten, unbunt bis auf den
   Akzent — er misst eine Übertragung, kein Prüfergebnis. */
.balken { height: 4px; background: var(--linie-2); overflow: hidden; }
.balken > i {
  display: block; height: 100%; background: var(--akzent);
  animation: balken-laeuft 1.15s var(--kurve) infinite;
}
@keyframes balken-laeuft {
  from { transform: translateX(-100%); } to { transform: translateX(300%); }
}
@media (prefers-reduced-motion: reduce) {
  .laedt::before { animation: none; background-position: 33% 0; }
  .balken > i { animation: none; width: 40%; margin-left: 30%; }
}


/* ===========================================================================
   16. Raster der Ansichten
   ========================================================================= */
.zwei-spalten { display: grid; gap: 18px; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); align-items: start; }
.spalte-liste { max-height: calc(100vh - var(--kopf-h) - 64px); overflow: auto; overscroll-behavior: contain; }

/* Der Leitstand: eine Karte je REGEL, nicht je Vorkommen. */
.leitstand-raster {
  display: grid; gap: 20px; align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
}
.preis-raster { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 20px; }


/* ===========================================================================
   17. Hilfsklassen
   ===========================================================================
   Wenige und benannt. Der Grund, warum es sie überhaupt gibt: ohne sie
   entstehen im Markup style-Attribute, und die kopiert die nächste Ansicht
   mit. `style-src` trägt zwar 'unsafe-inline', aber erlaubt ist nicht
   dasselbe wie gemeint. */
.leise    { font-size: .93rem; color: var(--text-2); }
.abschnitt{ margin-bottom: 34px; }
.raum-14  { margin-bottom: 14px; }
.raum-18  { margin-bottom: 18px; }
.raum-6   { margin-bottom: 6px; }
.ohne-raum{ margin-bottom: 0; }
.schmal   { max-width: 70ch; }
.nach-rechts { margin-left: auto; }
.blatt-rumpf { padding: 26px 0 64px; }


/* ===========================================================================
   18. Produktbauteile — was der Musterbogen nicht kennt
   ===========================================================================
   Die Vorlage liefert die Schale. Was hier folgt, sind die 58 Bauteile, die
   /app und /verwaltung darüber hinaus benutzen, übersetzt in dieselbe
   Formsprache: Radius null, keine Erhebung, Haarlinien, Gezähltes in Mono.
   ========================================================================= */

/* --- Der RDG-Hinweis ---------------------------------------------------- */
/* Steht in jedem Download und auf jeder Ergebnisseite. Kante links wie bei
   `.meldung.gut` — ein Fakt, keine Warnung. */
.rdg {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--flaeche); border: 1px solid var(--linie);
  border-left: 3px solid var(--akzent);
  padding: 14px 16px; font-size: .89rem; color: var(--text-2); margin-bottom: 22px;
}
.rdg b { color: var(--tinte); }

/* --- Ablage: der Upload-Bereich ----------------------------------------- */
.ablage {
  position: relative; display: block;
  border: 2px dashed var(--linie);
  padding: clamp(28px, 5vw, 44px) 24px; text-align: center;
  background: var(--flaeche-2); cursor: pointer;
  transition: border-color var(--zeit) var(--kurve), background var(--zeit) var(--kurve);
}
.ablage:hover, .ablage.aktiv { border-color: var(--akzent); background: var(--akzent-hauch); }
.ablage.aktiv { border-style: solid; }
.ablage input[type=file] {
  position: absolute; opacity: 0; pointer-events: none; width: 1px; height: 1px; min-height: 0;
}
.ablage-symbol {
  width: 46px; height: 46px; margin: 0 auto 12px;
  display: grid; place-items: center;
  background: var(--akzent-hauch); color: var(--akzent);
  border: 1px solid var(--akzent-linie);
}
.ablage-symbol svg { width: 23px; height: 23px; }
.ablage:hover .ablage-symbol, .ablage.aktiv .ablage-symbol { transform: translateY(-2px); }
.ablage .gross {
  display: block; font-size: 1.03rem; font-weight: 620; color: var(--tinte);
  margin-bottom: 4px; overflow-wrap: anywhere;
}

/* --- Kennzahlen --------------------------------------------------------- */
.ergebnis-kopf { display: flex; flex-wrap: wrap; gap: clamp(18px, 3vw, 32px); align-items: center; }
.kennzahlen { display: flex; flex-wrap: wrap; gap: clamp(18px, 3vw, 34px); }
.kennzahl b {
  display: block; font-family: var(--mono); font-size: 1.5rem; font-weight: 700;
  line-height: 1.15; letter-spacing: -.025em; font-variant-numeric: tabular-nums;
  color: var(--tinte);
}
.kennzahl span { font-size: .82rem; color: var(--text-2); }
.kennzahl .kennzahl-zusatz { display: block; font-size: .75rem; color: var(--text-2); }
.kachelreihe {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr)); gap: 14px;
  margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--linie);
}
.kachelreihe .kennzahl { padding: 2px 0; }
a.kachel-link {
  color: inherit; text-decoration: none; padding: 6px 8px; margin: -6px -8px;
  transition: background var(--zeit-schnell) var(--kurve);
}
a.kachel-link:hover { background: var(--akzent-hauch); text-decoration: none; }
a.kachel-link:hover b, a.kachel-link:hover span { color: var(--akzent); }

/* --- Preistafel --------------------------------------------------------- */
.preis { display: flex; flex-direction: column; position: relative; }
.preis.hervor { border-color: var(--akzent); }
/* Das Band lag auf --akzent und trug hart #fff — im dunklen Thema unlesbar.
   Dieselbe Falle wie beim Hauptknopf. */
.preis .band {
  position: absolute; top: -11px; left: 50%; transform: translateX(-50%);
  background: var(--akzent); color: var(--auf-akzent);
  padding: 3px 12px; font-size: .73rem; font-weight: 650;
  letter-spacing: .04em; text-transform: uppercase;
}
.preis .betrag {
  font-family: var(--mono); font-size: 2.1rem; font-weight: 720; letter-spacing: -.03em;
  color: var(--tinte); font-variant-numeric: tabular-nums; line-height: 1.1;
}
.preis .je { color: var(--text-2); font-size: .88rem; margin-bottom: 4px; }
.preis ul { list-style: none; padding: 0; margin: 16px 0 0; font-size: .92rem; flex: 1; }
.preis li { padding-left: 26px; position: relative; margin-bottom: 9px; color: var(--text-2); }
/* Das Häkchen war grün — eine Ampelfarbe als Schmuck. Jetzt Akzent. */
.preis li::before {
  content: ""; position: absolute; left: 0; top: .32em; width: 16px; height: 16px;
  background: var(--akzent);
  --zeichen: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M3.5 12.2l2.9-2.9 3.8 3.8 7.4-7.4 2.9 2.9-10.3 10.3z'/%3E%3C/svg%3E");
  -webkit-mask: var(--zeichen) center/contain no-repeat;
  mask: var(--zeichen) center/contain no-repeat;
}

/* --- Leitstand: Regelkarte ---------------------------------------------- */
/* Eine Karte je REGEL, nicht je Vorkommen. Sie ist eine eigene Bauform und
   nicht `.karte` — ergebnis.js schreibt `article.regel-karte`. */
.regel-karte {
  background: var(--flaeche);
  border: 1px solid var(--linie); border-left: 3px solid var(--linie);
  padding: 16px 18px; margin-bottom: 16px;
}
/* Die Kante trägt die Stufe der Regel — wie beim Befund, s. dort. */
.regel-karte.hoch { border-left-color: var(--rot); }
.regel-karte p { font-size: .92rem; margin-bottom: 8px; }
.regel-karte > :last-child { margin-bottom: 0; }
.regel-kopf { display: flex; align-items: flex-start; gap: 10px; }
.regel-kopf h4 { margin: 0 0 6px; flex: 1; }
.regel-kopf .zaehler, .regel-karte .zaehler {
  flex: none; font-family: var(--mono); font-size: 12px; color: var(--text-3);
  border: 1px solid var(--linie); padding: 2px 7px;
  font-variant-numeric: tabular-nums;
}
.regel-karte .rueckfrage { color: var(--text-2); }
.regel-karte .rueckfrage b { color: var(--tinte); }

/* --- Stufe (severity) --------------------------------------------------- */
/* KEINE Ampelfarbe: die Stufe eines Befundes ist eine andere Skala als die
   vier Wertungen. Sie trägt Fläche und Kante, nicht Farbe. */
.stufe {
  display: inline-block; padding: 2px 8px;
  font-size: .71rem; font-weight: 650; letter-spacing: .05em; text-transform: uppercase;
  background: var(--linie-2); color: var(--text-2); border: 1px solid var(--linie);
}
/* `erledigt` trägt denselben gefüllten Zustand — er markiert eine bezahlte
   Bestellung. Bis zum 2026-08-19 stand dort ein grünes Ampelabzeichen, also
   die Farbe für „gut prüfbar" an einem Zahlungsstatus. */
.stufe.hoch, .stufe.kritisch, .stufe.erledigt {
  background: var(--tinte); color: var(--flaeche); border-color: var(--tinte);
}
/* Im dunklen Thema ist --tinte HELL; auf ihr steht die Gehaeusefarbe. */
html[data-thema="dunkel"] .stufe.hoch,
html[data-thema="dunkel"] .stufe.kritisch,
html[data-thema="dunkel"] .stufe.erledigt { color: var(--marke-dunkel); }

/* --- Ordnungszahlen als Knöpfe ------------------------------------------ */
.oz-chips { display: flex; flex-wrap: wrap; gap: 8px 6px; margin-top: 10px; }
.oz-chip {
  position: relative; font: inherit; font-family: var(--mono);
  font-size: .79rem; font-weight: 620; font-variant-numeric: tabular-nums;
  padding: 5px 10px; border: 1px solid var(--linie);
  background: var(--flaeche); color: var(--text-2); cursor: pointer;
}
/* Die Tippfläche bleibt 44 px hoch, auch wenn der Knopf schmaler aussieht. */
.oz-chip::after {
  content: ""; position: absolute; left: -2px; right: -2px; top: 50%;
  transform: translateY(-50%); height: 44px;
}
.oz-chip:hover { border-color: var(--akzent); color: var(--akzent); background: var(--akzent-hauch); }

.alle-positionen > summary { cursor: pointer; font-weight: 620; color: var(--tinte); padding: 10px 0; }

/* --- Filterleiste ------------------------------------------------------- */
/* Kein Weichzeichner unter der Leiste: die Welt hat keine unscharfen Ränder.
   Sie steht auf voller Fläche und trennt mit einer Haarlinie. */
.filter-leiste {
  display: flex; flex-wrap: wrap; gap: 6px; padding: 14px 16px;
  border-bottom: 1px solid var(--linie);
  position: sticky; top: 0; z-index: 2; background: var(--flaeche);
}
.filter {
  position: relative; min-height: 32px; padding: 0 12px;
  border: 1px solid var(--linie); background: var(--flaeche);
  font: inherit; font-size: .82rem; font-weight: 620; color: var(--text-2); cursor: pointer;
  transition: background var(--zeit-schnell) var(--kurve),
              color var(--zeit-schnell) var(--kurve),
              border-color var(--zeit-schnell) var(--kurve);
}
.filter::after {
  content: ""; position: absolute; left: 0; right: 0; top: 50%;
  transform: translateY(-50%); height: 44px;
}
.filter:hover { border-color: var(--text-3); color: var(--tinte); }
.filter[aria-pressed="true"] { background: var(--tinte); border-color: var(--tinte); color: var(--flaeche); }

/* --- Positionsliste ----------------------------------------------------- */
.pos-zeile {
  display: flex; gap: 11px; align-items: center; width: 100%; text-align: left;
  padding: 12px 16px; border: 0; border-bottom: 1px solid var(--linie-2);
  background: none; font: inherit; cursor: pointer;
  box-shadow: inset 3px 0 0 transparent;
  transition: background var(--zeit-schnell) var(--kurve), box-shadow var(--zeit-schnell) var(--kurve);
}
.pos-zeile:hover { background: var(--flaeche-2); }
.pos-zeile[aria-selected="true"] { background: var(--akzent-hauch); box-shadow: inset 3px 0 0 var(--akzent); }
.pos-zeile .oz {
  font-weight: 650; font-size: .85rem; flex: none; min-width: 68px; color: var(--tinte);
}
.pos-zeile .txt {
  flex: 1; min-width: 0; font-size: .88rem; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* --text-2, nicht --text-3: auf der AUSGEWÄHLTEN Zeile liegt der Grund auf
   --akzent-hauch, und dort ergibt --text-3 bei 12,5 px gemessen 4,497:1 —
   knapp unter der Schwelle. Auf Weiß wären es 4,98:1 gewesen, deshalb fällt es
   nur an der einen Zeile auf, die gerade offen ist. Dieselbe Entscheidung hat
   die Vorlage für die Schrittziffer und `.ampel.leer` getroffen; diese dritte
   Stelle steckt in einem Bauteil, das der Musterbogen nicht kennt. */
.pos-zeile .zahl { font-size: .78rem; color: var(--text-2); flex: none; }
.detail { min-height: 440px; }

/* --- Befund ------------------------------------------------------------- */
/* Die Kante links trägt die STUFE des Befundes, in den Wertungsfarben.
   Franks Entscheidung vom 2026-08-19, ausdrücklich bestätigt: die Stufe IST
   ein Prüfergebnis, und sie soll auf einen Blick ablesbar sein.

   Wer hier etwas ändern will, muss die Doppelbedeutung kennen: dieselben vier
   Farben tragen im Abzeichen (.ampel) die Wertung einer POSITION — rot heißt
   dort „nicht belastbar kalkulierbar", hier „hohe Stufe". Beide Skalen stehen
   nie am selben Element, aber auf derselben Seite. Die Stufe steht zusätzlich
   als Wort im Abzeichen daneben (.stufe), die Farbe ist also nicht ihr
   einziger Träger. */
.befund { border-left: 3px solid var(--linie); padding: 2px 0 2px 16px; margin-bottom: 22px; }
.befund.hoch, .befund.kritisch { border-left-color: var(--rot); }
.befund.mittel { border-left-color: var(--gelb); }
.befund.niedrig { border-left-color: var(--gruen); }
.befund h4 { margin-bottom: 4px; font-size: .99rem; }
/* Die Kopfzeile aus Stufe, Wertung, Regel-Kennung und Konfidenz. Sie stand
   bis zum 2026-08-19 nur im Befund unter einer Regel (`.befund .meta`) — in der
   REGELKARTE des Leitstands trägt dasselbe Markup dieselbe Klasse und lief
   deshalb ohne Abstände zusammen. Beim Portieren gemessen, nicht vermutet. */
.meta {
  font-size: .79rem; color: var(--text-3); margin-bottom: 7px;
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
}
.befund p { margin: 0 0 7px; font-size: .93rem; }

.beleg {
  background: var(--flaeche-2); border: 1px solid var(--linie);
  border-left: 3px solid var(--akzent-linie);
  padding: 10px 13px; margin: 10px 0; font-size: .87rem; color: var(--text-2);
}
.beleg b { color: var(--tinte); font-weight: 620; }

/* Der Langtext der Position — das, was die Regeln gelesen haben.
   `pre-line` erhält die Absätze der Ausschreibung; der Knoten trägt Text und
   kein Markup, fremder Inhalt wird also nicht gedeutet.
   Bis zum 2026-08-19 stand das als `style`-Attribut in ergebnis.js: die Klasse
   gab es, eine Regel dazu nicht. Erlaubt war das (`style-src` trägt
   'unsafe-inline'), gemeint nicht — und die nächste Ansicht kopiert so etwas
   mit. */
.langtext {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--linie);
  white-space: pre-line; color: var(--text-2); font-size: .93rem;
}
.langtext small {
  display: block; margin-bottom: 4px;
  font-size: 11px; font-weight: 650; letter-spacing: .19em;
  text-transform: uppercase; color: var(--text-3);
}

/* --- Berichtsansicht ---------------------------------------------------- */
/* Eine Spalte, nummerierte Abschnitte. Der Bogen ist ein Blatt Papier — auf
   dem Schirm mit Kante, im Druck ohne. */
.bericht-bogen {
  max-width: 880px; margin: 0 auto; background: var(--flaeche);
  border: 1px solid var(--linie); padding: clamp(24px, 4vw, 48px);
}
.bericht-kopf { border-bottom: 2px solid var(--tinte); padding-bottom: 16px; }
.bericht-kopf h1 { font-size: clamp(1.5rem, 1.2rem + 1vw, 1.9rem); margin-bottom: 6px; }
.bericht-kopf .datei { font-size: 1rem; color: var(--text-2); margin-bottom: 6px; }
.bericht-kopf .kontext { font-size: .87rem; color: var(--text-3); margin-bottom: 2px; }
.bericht-kacheln { grid-template-columns: repeat(3, 1fr); border-top: 0; }
.bericht-rdg {
  font-size: .84rem; color: var(--text-2); background: var(--flaeche-2);
  border: 1px solid var(--linie); padding: 12px 14px; margin-top: 18px;
}
.bericht-rdg b { color: var(--tinte); }
.bericht-abschnitt {
  font-size: 1.15rem; margin: 32px 0 4px; padding-bottom: 6px;
  border-bottom: 1px solid var(--linie);
}
.bericht-abschnitt .nr { color: var(--akzent); margin-right: 10px; }
.bericht-abschnitt small { color: var(--text-3); font-weight: 500; margin-left: 10px; font-size: .78rem; }
.bericht-eintrag { padding: 14px 0; border-bottom: 1px solid var(--linie-2); }
.bericht-eintrag:last-child { border-bottom: 0; }
.bericht-eintrag h3 { font-size: 1rem; margin-bottom: 5px; }
.bericht-eintrag h3 .nr { color: var(--text-3); margin-right: 8px; }
.bericht-eintrag h3 .zaehler {
  color: var(--text-3); font-weight: 600; margin-left: 8px; font-size: .85rem;
  border: 0; padding: 0;
}
.bericht-eintrag p { font-size: .93rem; margin-bottom: 7px; }
.bericht-eintrag .rueckfrage b { color: var(--tinte); }
.nr { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.fundstellen { font-size: .85rem; color: var(--text-2); }
.fundstellen b { color: var(--tinte); }
.fundstellen button {
  font: inherit; font-family: var(--mono); font-size: .85rem;
  font-variant-numeric: tabular-nums; background: none; border: 0; padding: 1px 2px;
  color: var(--akzent); cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.bericht-liste { font-size: .88rem; color: var(--text-2); columns: 2; column-gap: 32px; }


/* ===========================================================================
   19. Der Auftritt
   ===========================================================================
   ui/effekte.js blendet Abschnitte beim Hereinscrollen ein und setzt dafür
   `--verzug` je Element. Die Sichtbarkeit hängt NIE allein daran: ohne
   JavaScript (`html` ohne `.js`) steht alles sofort da, und der Wachhund in
   effekte.js setzt die Deckkraft direkt, falls der Beobachter nicht feuert.
   Der Block in Abschnitt 3 hebt das bei `prefers-reduced-motion` ganz auf. */
.auftritt { opacity: 1; }
html.js .auftritt {
  opacity: 0; transform: translateY(12px);
  transition: opacity var(--zeit-lang) var(--kurve), transform var(--zeit-lang) var(--kurve);
  transition-delay: var(--verzug, 0ms);
}
html.js .auftritt.da { opacity: 1; transform: none; }
html.js .auftritt.sofort { transition: none !important; opacity: 1 !important; transform: none !important; }


/* ===========================================================================
   20. Fußzeile
   ========================================================================= */
.fuss {
  border-top: 1px solid var(--linie); background: var(--flaeche);
  padding: 32px 0; margin-top: 56px; font-size: .9rem; color: var(--text-2);
}
.fuss .huelle { display: flex; flex-wrap: wrap; gap: 18px; align-items: center; }
.fuss .herkunft { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Zwei Bilddateien, weil ein <img> sich nicht umfärben lässt. Umgeschaltet
   wird über display — und die Umschaltregeln müssen den VOLLEN Präfix tragen:
   `.nur-dunkel { display: none }` allein ist unspezifischer als die Grundregel
   darüber, und dann stehen beide Wortmarken gleichzeitig da. Testgesichert. */
.fuss .herkunft img { height: 17px; width: auto; display: block; opacity: .92; }
.fuss .herkunft img.nur-dunkel { display: none; }
html[data-thema="dunkel"] .fuss .herkunft img.nur-hell { display: none; }
html[data-thema="dunkel"] .fuss .herkunft img.nur-dunkel { display: block; }
.fuss nav { margin-left: auto; display: flex; gap: 20px; flex-wrap: wrap; }
.fuss a { color: var(--text-2); }
.fuss a:hover { color: var(--akzent); }


/* ===========================================================================
   21. Schmale Schirme
   ========================================================================= */
@media (max-width: 900px) {
  .zwei-spalten { grid-template-columns: minmax(0, 1fr); }
  .spalte-liste { max-height: none; }
  .kopf-nav { display: none; }
  .menue-knopf { display: inline-grid; }

  /* Die Klappnavigation. `visibility` steht hier MIT Verzögerung im Übergang,
     damit das Zuklappen zu Ende läuft — anders als beim Seitenblatt ist das
     hier ungefährlich, weil `pointer-events: none` unabhängig davon greift und
     die Leiste im geschlossenen Zustand keinen Klick abfangen kann. */
  .kopf nav.klappt {
    position: fixed; inset: var(--kopf-h) 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 2px;
    padding: 10px 16px 16px;
    background: var(--flaeche); border-bottom: 1px solid var(--linie);
    transform: translateY(-8px); opacity: 0; visibility: hidden; pointer-events: none;
    transition: opacity var(--zeit) var(--kurve),
                transform var(--zeit) var(--kurve),
                visibility 0s linear var(--zeit);
  }
  .kopf nav.klappt.offen {
    transform: none; opacity: 1; visibility: visible; pointer-events: auto;
    transition-delay: 0s, 0s, 0s;
  }
  .kopf nav.klappt a:not(.knopf) { padding: 12px; font-size: 1rem; height: auto; }
  .kopf nav.klappt .knopf { justify-content: flex-start; }
  .kopf .nebenan { gap: 6px; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .kopf nav.klappt { transition: none; }
}
@media (max-width: 640px) {
  .huelle { padding: 0 16px; }
  .karte-rumpf, .karte-kopf, .karte-fuss { padding-left: 14px; padding-right: 14px; }
  .bericht-liste { columns: 1; }
  .bericht-kacheln { grid-template-columns: repeat(2, 1fr); }
  .fuss nav { margin-left: 0; width: 100%; }
  .leitstand-raster { gap: 14px; }
  /* Auf dem Telefon bleibt vom Themenschalter nur das Symbol. Ohne diese
     Zeile lief die Kopfzeile bei 375 px gemessen 45 px über: Schalter mit
     Beschriftung, Guthaben und Menüknopf passen dort nicht nebeneinander. */
  .thema-schalter button span { display: none; }
  .thema-schalter button { padding: 0 9px; }
}


/* ===========================================================================
   22. Druck — immer hell
   ===========================================================================
   BEIDE Selektoren, sonst schlägt die Spezifität von html[data-thema="dunkel"]
   (0,1,1) die Absicht von :root (0,1,0) und der Prüfbericht kommt schwarz aus
   dem Drucker. Der Bericht ist genau das, was weitergereicht wird. */
@media print {
  :root, html[data-thema="dunkel"] {
    color-scheme: light;
    --grund: #fff; --flaeche: #fff; --flaeche-2: #fafbfd;
    --tinte: #06265a; --text: #12203a; --text-2: #46536b; --text-3: #657087;
    --linie: #d5dce8; --linie-2: #e8edf5;
    --akzent: #0b4a9e; --akzent-tief: #06265a; --akzent-hauch: #fff; --akzent-linie: #c3d8f2;
    --auf-akzent: #fff;
    --gruen: #15803d;  --gruen-hauch: #fff;  --gruen-linie: #c4e7d0;
    --gelb: #a16207;   --gelb-hauch: #fff;   --gelb-linie: #efe0b4;
    --orange: #c2410c; --orange-hauch: #fff; --orange-linie: #f4d5c0;
    --rot: #b91c1c;    --rot-hauch: #fff;    --rot-linie: #f3cfcf;
    --hebung-1: none; --hebung-2: none; --hebung-3: none;
  }
  body { background: #fff; }
  .kopf, .fuss, .knopf, .filter-leiste, .thema-schalter, .menue-knopf,
  .seitenblatt, .nicht-drucken, .alle-positionen > summary { display: none !important; }
  .karte { border-color: var(--linie); break-inside: avoid; }
  .zwei-spalten { grid-template-columns: 1fr; }
  .spalte-liste { max-height: none; overflow: visible; }
  /* Die umgekehrte Fehlerleiste würde eine halbe Patrone kosten. Auf Papier
     trägt sie einen kräftigen Rahmen statt einer Füllung. */
  .meldung.fehler { background: #fff; color: var(--tinte); border: 2px solid var(--tinte); }
  .meldung { break-inside: avoid; animation: none; }
  .geruest::after, .laedt::before, .balken > i { animation: none; }
  .bericht-bogen { max-width: none; border: 0; padding: 0; }
  .bericht-eintrag, .regel-karte { break-inside: avoid; }
  .bericht-abschnitt { break-after: avoid; }
  .fundstellen button { color: inherit; text-decoration: none; }
  a { color: inherit; text-decoration: none; }
}
