/* BelegHero – zusammengefuehrtes Stylesheet.
   Teil 1: Basis-Theme. Teil 2: Corporate-Ueberschreibungen (frueher
   corporate.css, immer nach dem Theme geladen – Reihenfolge bleibt erhalten).
   Tote Theme-Deklarationen, die vom Corporate-Teil ohnehin ueberschrieben
   wurden, sind beim Zusammenfuehren entfallen. */
/* Die Hausschrift steht hier und nicht nur in bp2.css, weil 20 Seiten dieses
   Stylesheet laden, aber nur ein Teil davon bp2.css. Ohne diese Deklaration
   fordern die uebrigen Seiten ueber --bp-font-sans eine Schrift an, die sie
   nicht laden koennen, und fallen still auf die Systemschrift zurueck - zwei
   verschiedene Schriftbilder auf derselben Website. Die Datei wird selbst
   ausgeliefert, es geht kein Abruf an Google Fonts. */
@font-face {
  font-family: "Jakarta";
  src: url("/static/fonts/PlusJakartaSans.woff2") format("woff2");
  font-weight: 200 800;
  font-style: normal;
  font-display: swap;
}

/* ============================ TEIL 1: BASIS-THEME ======================== */
:root {
  --bp-ink-2: #23402c;
  --bp-soft-2: var(--bp-accent-soft);
  --bp-white: #ffffff;
  --bp-warm: #cfe1d3;
  --bp-sky: #e1ebf0;
  --bp-peach: #edf1f3;
  --bp-sage: #e4eee7;
  --bp-ash: #eef2f3;
  --bp-danger: #a8432e;
  --bp-radius-sm: 20px;
  --bp-radius-md: 20px;
  --bp-radius-lg: 20px;
  --bp-radius-xl: 30px;
  --bp-shadow-soft: none;
  --bp-shadow-lift: none;
  --bp-shadow-button: none;
  /* Plus Jakarta Sans führt, Systemschriften bleiben als Rückfall dahinter.
     Nur diese zwei Zeilen, weil theme.css die Schrift an 31 Stellen über genau
     diese beiden Tokens erzwingt - alles andere hätte 31 Einzeleingriffe
     bedeutet. Die Datei liegt unter /static/fonts/ und wird selbst
     ausgeliefert; es geht kein Abruf an Google Fonts, was für einen deutschen
     Dienst mit Kanzleien als Kundschaft der Punkt ist. */
  --bp-font-sans: "Jakarta", -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
  --bp-font-display: "Jakarta", -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
  --card: var(--bp-white);
  --accent-light: #3f7a4f;
  --gold: var(--bp-accent);
  --warn: var(--bp-danger);
}
html {
  scroll-behavior: smooth;
  background: var(--bp-white);
}
body {
  background: var(--bp-white) !important;
  color: var(--bp-ink) !important;
  font-family: var(--bp-font-sans) !important;
  letter-spacing: -0.008em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body::before {
  background:
    radial-gradient(44rem 26rem at 92% -12%, rgba(63, 122, 79, 0.14), transparent 65%),
    radial-gradient(36rem 24rem at -10% 18%, rgba(46, 79, 53, 0.07), transparent 68%) !important;
}
::selection {
  color: var(--bp-white);
  background: var(--bp-accent);
}
a {
  color: var(--bp-ink);
  text-underline-offset: 0.2em;
}
:where(a, button, input, select, textarea):focus-visible {
  outline: 3px solid rgba(46, 79, 53, 0.25);
  outline-offset: 3px;
}
[stroke="#2e4f35"] {
  stroke: var(--bp-accent);
}
[fill="#2e4f35"] {
  fill: var(--bp-accent);
}
[fill="#c9a227"] {
  fill: var(--bp-accent);
}
.logo-word,
.login-logo-word,
.brand,
.logo {
  font-family: var(--bp-font-display);
  font-weight: 600 !important;
  letter-spacing: -0.03em;
}
.brand-hero {
  color: var(--bp-ink) !important;
}
.brand-beleg,
.logo-word .p,
.logo .p {
  color: var(--bp-accent) !important;
}
/* Shared controls */
button,
.btn,
.primary,
.secondary,
.primary-btn,
.ghost-btn,
.cta-btn,
.plan-pick,
.google-btn,
.google-link-btn,
.row-action-btn,
.paywall-btn {
  min-height: var(--bp-tap);
  font-family: var(--bp-font-sans) !important;
  font-weight: 600 !important;
  letter-spacing: -0.01em;
  transition: transform 180ms ease, box-shadow 180ms ease, opacity 180ms ease,
    background-color 180ms ease, color 180ms ease;
}
:where(button, .btn, .primary, .secondary, .primary-btn, .ghost-btn, .cta-btn, .plan-pick, .google-btn, .google-link-btn):not(:disabled):hover {
  transform: translateY(-2px);
}
.btn-primary,
button.primary,
.primary,
.primary-btn,
.cta-btn,
button:not([class]),
.bp-bottom-nav .btn {
  border-color: transparent !important;
  background: var(--bp-accent) !important;
  color: var(--bp-white) !important;
  box-shadow: var(--bp-shadow-button) !important;
}
.btn-ghost,
button.secondary,
.secondary,
.ghost-btn,
.google-btn,
.google-link-btn,
.plan-pick {
  border: 0 !important;
  background: var(--bp-white) !important;
  color: var(--bp-ink) !important;
  box-shadow: var(--bp-shadow-soft) !important;
}
input,
select,
textarea {
  border: 1px solid var(--bp-line) !important;
  border-radius: var(--bp-radius-sm) !important;
  background: var(--bp-white) !important;
  color: var(--bp-ink) !important;
  font-family: var(--bp-font-sans) !important;
  box-shadow: inset 0 1px 1px rgba(5, 26, 36, 0.025);
  transition: border-color 160ms ease, box-shadow 160ms ease;
}
input:focus,
select:focus,
textarea:focus {
  border-color: rgba(46, 79, 53, 0.5) !important;
  box-shadow: 0 0 0 4px rgba(46, 79, 53, 0.1) !important;
  outline: 0;
}
label {
  color: var(--bp-ink);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.sub,
.muted,
.hint,
.panel-hint,
.hero-sub,
.fine-print {
  color: var(--bp-muted) !important;
}
.panel,
.card,
.login-card,
.billing-box,
.stat-tile,
.choice-card,
.requirements-box,
.detect-candidate-card,
.scan-summary-panel,
.task-accordion,
.modal-panel,
.table-wrap,
.dropzone,
.mini-dropzone,
.mock-window,
.cost-cap-banner {
  border: 0 !important;
  border-radius: var(--bp-radius-lg) !important;
  background: var(--bp-white) !important;
  box-shadow: var(--bp-shadow-soft) !important;
}
.panel,
.card,
.login-card,
.billing-box,
.modal-panel {
  padding: clamp(1.4rem, 3vw, 2.2rem) !important;
}
.choice-card:hover,
.panel:hover,
.tier:hover,
.plan-card:hover,
.project-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--bp-shadow-lift) !important;
}
/* AUSSERHALB DES ARBEITSBEREICHS - dieselbe Einschraenkung wie bei `table td`
   direkt darunter, und aus demselben Grund.

   Diese vier Zeilen machten aus jeder Spaltenkopfzeile eine kleine graue
   Versalienzeile: 0.72rem, --bp-muted, 0.07em Sperrung. Gemessen an sevdesk
   ist der Kopf GENAUSO GROSS wie der Inhalt und AUFFAELLIGER, nicht leiser.
   Meine neue Regel in app-neu.css ist spezifischer und steht im spaeter
   geladenen Blatt - gegen vier `!important` half beides nicht, und der Kopf
   blieb bei 11,664px in Grau 101.

   FUENFTER FALL DIESER BAUART AN EINEM TAG. Der Umbau besteht inzwischen zu
   einem guten Teil daraus, altes `!important` aus dem Weg zu raeumen, bevor
   ein Baustein ueberhaupt wirken kann - genau die Reihenfolge, die in
   docs/SCHICHTGERUEST-ABLAUF.md steht.

   Die oeffentlichen Seiten sind nicht betroffen: theme.css wird dort gar
   nicht geladen (gemessen an /datenschutzerklaerung und /avv). */
body:not(.bp-app) table th {
  color: var(--bp-muted) !important;
  font-size: 0.72rem !important;
  font-weight: 650 !important;
  letter-spacing: 0.07em !important;
}
/* AUSSERHALB DES ARBEITSBEREICHS. Hier stand `table td` ohne Einschraenkung,
   und das `!important` hat am 07.08.2026 die neue Listenzeile ueberstimmt:
   `body.bp-app table.invoice-table td` ist spezifischer UND steht im spaeter
   geladenen Blatt - gegen ein `!important` aus einem frueheren Blatt hilft
   beides nicht. Genau der Fall, den SideChats Schichtmessung als Fall 4
   beschrieben hat.

   Die Zeile wird NICHT ersatzlos entfernt: theme.css traegt auch die zwoelf
   oeffentlichen Seiten, und die sollen sich nicht bewegen. `:not(.bp-app)`
   laesst sie dort woertlich so wirken wie bisher - dieselbe Deklaration,
   dieselbe Wirkung, nur hoehere Spezifitaet, also derselbe Gewinner - und
   gibt den Arbeitsbereich frei. */
body:not(.bp-app) table td {
  border-color: var(--bp-line) !important;
}


/* Auth, purchase and standalone pricing */
.bp-auth {
  min-height: 100vh;
  background:
    radial-gradient(34rem 22rem at 12% 8%, rgba(216, 169, 79, 0.08), transparent 72%),
    radial-gradient(42rem 28rem at 90% 0%, rgba(63, 122, 79, 0.14), transparent 72%),
    var(--bp-white) !important;
}
.bp-auth > .card,
.bp-auth .login-card {
  border-radius: var(--bp-radius-xl) !important;
  box-shadow: var(--bp-shadow-lift) !important;
}
.bp-auth h1,
.bp-auth .intro h1 {
  color: var(--bp-ink-2);
  font-family: var(--bp-font-display);
  font-weight: 500;
  letter-spacing: -0.045em;
  line-height: 1;
}
.bp-auth .step-indicator,
.bp-auth .success-badge,
.bp-auth .form-section-title {
  width: fit-content;
  border-radius: 999px;
  background: var(--bp-soft-2);
  color: var(--bp-ink);
  padding: 0.38rem 0.68rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.68rem;
}


/* Product app */
.bp-app .hero-title,
.bp-app .header h1,
/* Der Kopf im abgemeldeten Zustand wiederholte auf drei Seiten die sichtbare
   Ueberschrift WORTGLEICH als zweites h1. Fuers Auge folgenlos - beide sind
   nie gleichzeitig zu sehen -, fuer Suchmaschinen und Screenreader nicht:
   im Markup standen zwei Dokumentueberschriften. Jetzt traegt der Kopf ein
   `p.header-titel` und sieht genauso aus wie vorher. */
.bp-app .modal-overlay,
.bp-auth #success-overlay,
.bp-app #purchased-modal {
  background: rgba(5, 26, 36, 0.62) !important;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}


@media (max-width: 600px) {


.bp-auth > .card,
.bp-auth .login-card,
.bp-pricing .plan-card,
.bp-pricing .compare,
.bp-pricing #code-box {
    border-radius: var(--bp-radius-lg) !important;
  }
}
/* ==========================================================================
   Professional refinement
   Restrained surfaces, clear information hierarchy and consistent density.
   ========================================================================== */
:root {
  --bp-surface-subtle: #eef2f0;
}


.bp-public .section-label,
.bp-project .bp-section-label {
  display: block;
  margin-bottom: 0.9rem;
  color: var(--bp-accent);
  font-size: 0.72rem;
  font-weight: 750;
  letter-spacing: 0.13em;
  line-height: 1.2;
  text-transform: uppercase;
}


.bp-public section.alt :where(.step, .feat-item, .trust-item, .src),
.bp-public .tier,
.bp-public .compare .col {
  border: 1px solid var(--bp-line) !important;
  border-radius: var(--r, 20px) !important;
  background: var(--bp-surface) !important;
  color: var(--bp-ink) !important;
  box-shadow: none !important;
}


.bp-marketing :where(.ic, .sg-ic) {
  color: var(--bp-accent) !important;
}


/* ==========================================================================
   Corporate accounting pass
   Neutral work surfaces, restrained brand accents and glass navigation.
   ========================================================================== */
:root {
  --bp-ink-2: #263441;
  --bp-corporate-2: #263441;
  --bp-surface-subtle: #eef1f3;
  --bp-warm: #eef1f3;
  --bp-sky: #f1f3f5;
  --bp-peach: #f1f3f5;
  --bp-sage: #f1f3f5;
  --bp-ash: #eef1f3;
  --card: var(--bp-surface);
  --accent-light: #557566;
}


/* Accounting product shell. */


/* AUF `body:not(.bp-app)` EINGEGRENZT, 08.08.2026. `width: auto !important`
   von hier hat jeden Versuch verhindert, dem schwebenden Hilfe-Knopf im
   Arbeitsbereich eine Groesse zu geben - Emil hat gemeldet, dass er am Handy
   Karten und Handlungen verdeckt. Siebter Eintrag derselben Reparatur: ein
   `!important` in einem frueher geladenen Blatt schlaegt jede gewoehnliche
   Regel in app-neu.css, egal wie spezifisch. */
body:not(.bp-app) #chat-toggle {
  width: auto !important;
  min-width: 3.7778rem;
  padding-inline: 1rem !important;
  font-size: 0.78rem !important;
  font-weight: 750;
  letter-spacing: 0.02em;
}
#chat-attach-btn {
  width: auto !important;
  min-width: 2.5556rem;
  padding-inline: 0.55rem !important;
  font-size: 0.72rem !important;
  font-weight: 700;
}
/* Logged-in workspace redesign
   Uses the same white, editorial typography and deep green surfaces as the
   marketing site while preserving every existing form, id and interaction. */
.app-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin-bottom: 0.65rem;
  color: var(--bp-accent);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.app-eyebrow::before {
  content: "";
  width: 1.1111rem;
  height: 1px;
  background: currentColor;
}
/* Account overview */
/* Project workspace */
.bp-project :where(input, select, textarea) {
  min-height: 2.7778rem;
  padding: 0.78rem 0.9rem !important;
  border-radius: var(--r, 20px) !important;
}
/* Account-level tools such as invoices and invoice settings */
.bp-shell :where(input, select, textarea) {
  min-height: var(--bp-tap-m);
  padding: 0.72rem 0.82rem !important;
  border-radius: var(--r, 20px) !important;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
    scroll-behavior: auto;
    animation-duration: 0.01ms;
    animation-iteration-count: 1;
    transition-duration: 0.01ms;
  }

}
/* ==========================================================================
   BelegHero editorial system
   Inspired by the supplied pastoral magazine reference: bone canvas, forest
   structure, one lime signal and quilted pastel surfaces. This final layer is
   intentionally centralized so every existing route keeps its functionality.
   ========================================================================== */
html,
body,
body.bp-app,
body.bp-auth {
  /* DER SEITENGRUND IST NEUTRAL.

     Hier stand `var(--bp-bone)` = #f3f5f3 = rgb(243,245,243) - Gruenstich,
     und das ist die GROESSTE Flaeche der Anwendung. SideChat hat ihn am
     08.08.2026 gefunden, NACHDEM ich alle Farbtokens neutralisiert hatte:
     der Grund kam gar nicht aus einem Token, sondern aus dieser Regel.

     Die Lehre: `html` malt die LEINWAND. Der body darueber war schon neutral
     (253,253,253) - sichtbar ist aber die Leinwand, ueberall dort, wo der
     body sie nicht bedeckt. Ich hatte nur `body` gemessen und deshalb
     "neutral" gemeldet, waehrend der Bildschirm gruenlich blieb.

     theme.css wird auf den oeffentlichen Seiten nicht geladen (gemessen an
     /datenschutzerklaerung und /avv). Marketing bleibt unberuehrt.

     WARUM HIER EIN LITERAL UND KEIN TOKEN STEHT: `--flur` ist auf
     `body.bp-app` definiert. `html` liegt DARUEBER und sieht es nicht -
     `var(--flur)` ist dort ungueltig, die Eigenschaft faellt weg, und die
     Leinwand wird durchsichtig. Das Ergebnis SAH richtig aus, weil dann der
     Grund des body durchschlaegt - ein Zufall, kein Mechanismus. Gefunden
     beim Nachmessen: die Leinwand meldete rgba(0,0,0,0).

     Und der zweite Anlauf hat prompt den Kommentar zu frueh geschlossen -
     `test_kein_kommentar_wird_zu_frueh_geschlossen` hat es sofort gemeldet.
     Zwei Fehler in einer Aenderung, beide von Pruefungen gefangen.

     NACHTRAG 08.08.2026: von 99,4 % auf 100 % - die Leinwand muss dasselbe
     reine Weiss tragen wie `--flur` und `--karte`, sonst schiene sie unter
     dem body durch. Begruendung und Messung stehen bei den beiden Tokens in
     app-neu.css. Und derselbe Test hat auch DIESEN Nachtrag beim ersten
     Anlauf gefangen - ich hatte den Kommentar erneut zu frueh geschlossen,
     drei Zeilen unter dem Satz, der genau davor warnt. */
  background: oklch(100% 0 155) !important;
}
button,
.btn,
.primary,
.secondary,
.primary-btn,
.ghost-btn,
.cta-btn,
.plan-pick,
.google-btn,
.google-link-btn,
.row-action-btn,
.paywall-btn {
  box-shadow: none !important;
  font-size: 0.88rem;
  font-weight: 600 !important;
  letter-spacing: 0.015em;
}
:where(button, .btn, .primary, .secondary, .primary-btn, .ghost-btn, .cta-btn, .plan-pick, .google-btn, .google-link-btn):not(:disabled):hover {
  box-shadow: none !important;
  transform: translateY(-1px);
}
input,
select,
textarea,
.bp-project :where(input, select, textarea),
.bp-shell :where(input, select, textarea) {
  border: 1px solid var(--bp-line) !important;
  border-radius: var(--r-lg, 34px) !important;
  box-shadow: none !important;
}
textarea,
.bp-project textarea {
  border-radius: var(--r-card, 26px) !important;
}
input:focus,
select:focus,
textarea:focus {
  border-color: var(--bp-accent) !important;
  box-shadow: 0 0 0 3px rgba(7, 80, 63, 0.12) !important;
}
.panel,
.card,
.login-card,
.billing-box,
.stat-tile,
.choice-card,
.requirements-box,
.detect-candidate-card,
.scan-summary-panel,
.task-accordion,
.modal-panel,
.table-wrap,
.dropzone,
.mini-dropzone,
.mock-window,
.cost-cap-banner {
  border-radius: var(--r-card, 26px) !important;
  box-shadow: none !important;
}
.choice-card:hover,
.panel:hover,
.tier:hover,
.plan-card:hover,
.project-card:hover {
  box-shadow: none !important;
}


.bp-public .hero h1,
.bp-public .hero-title,
.bp-public .problem-h,
.bp-public .sec-head h2,
.bp-public .cta-band h2,
.bp-public main > h1,
.bp-legal h1,
.bp-app .hero-title,
.bp-app .section-title,
.bp-app section > h2,
.bp-app .panel > h2 {
  font-family: var(--bp-font-display) !important;
  font-weight: 650 !important;
  letter-spacing: -0.045em !important;
}

.bp-public .eyebrow,
.bp-public .tag,
.app-eyebrow {
  font-family: var(--bp-font-sans) !important;
}


.bp-public section.alt :where(.step, .feat-item, .trust-item, .src) {
  color: var(--bp-ink) !important;
}
.bp-public section.alt :where(.step, .feat-item, .trust-item, .src) h3 {
  color: var(--bp-ink) !important;
}
.bp-public section.alt :where(.step, .feat-item, .trust-item, .src) p {
  color: #425149 !important;
}


.bp-public .cta-band :where(h1, h2),
.bp-public .cta-box :where(h1, h2) {
  color: var(--bp-white) !important;
}


.bp-pricing .plan-card,
.bp-pricing .compare,
.bp-pricing #code-box,
.bp-auth > .card,
.bp-auth .login-card {
  border: 0 !important;
  border-radius: var(--r-card, 26px) !important;
  box-shadow: none !important;
}


.notice,
.pilot-note,
.prep-notice {
  border: 1px solid var(--bp-line) !important;
  border-radius: var(--r-card, 26px) !important;
  background: var(--bp-sage) !important;
  color: var(--bp-ink) !important;
}
.review-card {
  border: 1px solid var(--bp-line) !important;
  border-radius: var(--r-card, 26px) !important;
  background: var(--bp-sky) !important;
}
.badge.needs_review {
  background: var(--bp-sky) !important;
  color: var(--bp-accent-strong) !important;
}
/* Logged-in product: same materials, tuned for dense functional work. */
.bp-auth > .card,
.bp-auth .login-card {
  background: var(--bp-white) !important;
}


.bp-public section.alt :where(.step, .feat-item, .trust-item, .src),
.bp-public .compare .col,
.bp-public .tier,
.bp-public .tier.pop {
  border: 1px solid var(--bp-line) !important;
  border-radius: var(--r, 20px) !important;
  background: var(--bp-surface) !important;
  color: var(--bp-ink) !important;
  box-shadow: none !important;
}
.bp-public section.alt :where(.step, .feat-item, .trust-item, .src) h3,
.bp-public section.alt :where(.step, .feat-item, .trust-item, .src) p {
  color: inherit !important;
}


/* ======================= TEIL 2: CORPORATE-EBENE ========================= */
:root {
  --bp-ink: #171a18;
  --bp-corporate: #171a18;
  --bp-accent: #2e4f35;
  --bp-accent-strong: #24402a;
  --bp-accent-soft: #e8efe9;
  --bp-muted: #666c68;
  --bp-line: #d7dbd7;
  --bp-line-strong: #bfc6c0;
  --bp-soft: #f3f5f3;
  --bp-bone: #f3f5f3;
  --bp-canvas: #edf0ed;
  --bp-surface: #ffffff;
  --bp-green-soft: #edf3ee;
  --ink: var(--bp-ink);
  --paper: var(--bp-bone);
  --line: var(--bp-line);
  --accent: var(--bp-accent);
  --accent-soft: var(--bp-accent-soft);
  --accent-tint: var(--bp-soft);
  --muted: var(--bp-muted);
}
body::before {
  display: none !important;
}
.bp-public :where(h1, h2, h3, h4),
.bp-app :where(h1, h2, h3, h4),
.bp-auth :where(h1, h2, h3, h4) {
  color: var(--bp-ink) !important;
}
button,
.btn,
.primary,
.secondary,
.primary-btn,
.ghost-btn,
.cta-btn,
.plan-pick,
.google-btn,
.google-link-btn,
.row-action-btn,
.paywall-btn {
  /* Ohne `!important` seit 07.08.2026 - dritter Fall desselben Musters an
     einem Tag. Es stand auf JEDEM Knopf und hat die neue Filterreihe auf 20px
     Ecken gezwungen, obwohl `body.bp-app .bp-filter` spezifischer ist UND im
     spaeter geladenen Blatt steht. Nur diese eine Stelle - die sechs anderen
     Vorkommen betreffen Kacheln und Tarifspalten, nicht Knoepfe.
     Ohne `!important` gewinnt weiterhin dasselbe wie vorher, ueberall wo
     app-neu.css keinen eigenen Radius setzt. Die oeffentlichen Seiten sind
     nicht betroffen: theme.css wird dort gar nicht geladen (gemessen an
     /datenschutzerklaerung und /avv). */
  border-radius: var(--r, 20px);
}
.btn-primary,
button.primary,
.primary,
.primary-btn,
.cta-btn,
.plan-pick,
.paywall-btn {
  border-color: var(--bp-accent) !important;
  background: var(--bp-accent) !important;
  color: #fff !important;
  box-shadow: var(--sh-tile, 0 5px 14px rgba(46, 79, 53, 0.18)) !important;
}
.btn-primary:hover,
button.primary:hover,
.primary:hover,
.primary-btn:hover,
.cta-btn:hover,
.plan-pick:hover,
.paywall-btn:hover {
  border-color: var(--bp-accent-strong) !important;
  background: var(--bp-accent-strong) !important;
}
.btn-ghost,
.secondary,
.ghost-btn {
  border-color: var(--bp-line-strong) !important;
  background: #fff !important;
  color: var(--bp-ink) !important;
  box-shadow: none !important;
}


.bp-public section.alt :where(.step, .feat-item, .trust-item, .src),
.bp-public .compare .col,
.bp-public .tier,
.bp-public .tier.pop,
.bp-public .hide-list {
  border-color: var(--bp-line) !important;
  border-radius: var(--r, 20px) !important;
  background: #fff !important;
}


/* Accounting application: neutral navigation and dense document surfaces.

   AUF `body:not(.bp-app)` EINGEGRENZT, 08.08.2026. Diese Regel faerbt jede
   Marke mit dem Akzent-Waschton - gemessen oklch(0.955 0.018 152), also der
   sichtbar bunteste Fleck auf Schritt 4 des Arbeitsbereichs. Betroffen war
   unter anderem "Keine ausstehenden Belege - alles bereits hochgeladen":
   eine Zustandsmeldung, die dadurch aussah wie eine Handlung.

   Sie traegt `!important` und steht in einem FRUEHER geladenen Blatt; damit
   schlaegt sie jede gewoehnliche Regel in app-neu.css, egal wie spezifisch.
   Das ist der Fall, den wir in dieser Nacht sechsmal hatten. Statt in
   app-neu.css ein lauteres `!important` daraufzusetzen, wird sie hier
   eingegrenzt - sechster Eintrag derselben Reparatur. */
body:not(.bp-app) .bp-project .primary-feature-badge,
body:not(.bp-app) .bp-project .key-action-badge,
body:not(.bp-app) .badge,
body:not(.bp-app) .pending-pill,
body:not(.bp-app) .method-running-badge {
  border-color: #cad3ce !important;
  background: var(--bp-accent-soft) !important;
  color: var(--bp-accent-strong) !important;
}
/* Ebenfalls eingegrenzt - im Arbeitsbereich bestimmen `--e-pille` und die
   Ruhigstell-Regel in app-neu.css, wie der Knopf aussieht. */
body:not(.bp-app) #chat-toggle {
  border-radius: var(--r, 20px) !important;
  background: var(--bp-accent) !important;
  color: #fff !important;
}
.bp-auth .google-btn svg,
.bp-start .google-btn svg {
  filter: grayscale(1) contrast(1.1);
}
:where(.bp-public, .bp-app, .bp-auth) svg [fill="#c9a227"] {
  fill: var(--bp-accent);
}
body.bp-auth:not(.bp-app) {
  background: var(--bp-canvas) !important;
  color: var(--bp-ink) !important;
}
.bp-auth:not(.bp-app) .card {
  border-color: var(--bp-line) !important;
  background: #fff !important;
  box-shadow: var(--sh-tile, 0 14px 38px rgba(23, 26, 24, 0.08)) !important;
}
.bp-auth:not(.bp-app) .notice,
.bp-auth:not(.bp-app) .provider-detect-hint,
.bp-auth:not(.bp-app) .imap-guide {
  border-color: #b8c6bb !important;
  background: var(--bp-accent-soft) !important;
  color: #39413b !important;
}


/* Software composition pass
   The application now uses one strong navigation plane and quiet working
   surfaces. Borders are reserved for controls that actually need an edge. */
:root {
  --bp-app-nav: #171a18;
  --bp-app-nav-soft: #242925;
  --bp-app-page: #f1f3f1;
  --bp-app-surface: #ffffff;
  --bp-app-tonal: #f6f7f5;
  --bp-app-tonal-strong: #ecefec;
  --bp-app-shadow: 0 12px 34px rgba(23, 26, 24, 0.07);
}
/* Ueber die GANZE Rasterzeile, nicht in eine Zelle.
   Diese Zeile ist selbst ein Dreispaltenraster (Text | Eingabe | Knopf) und
   braucht mindestens 180+240+Knopf, also gut 470px. Als gewoehnliches
   Rasterfeld bekam sie aber nur eine Spalte des Projektrasters - rund 320px.
   Der Inhalt lief heraus, und die Projektkarten der Spalten 2 und 3 zeichneten
   darueber: vom Eingabefeld war "z.B" zu sehen, vom Knopf "An".
   Emil, 05.08.2026: "wenn man ein neues projekt oeffnet ist der name auch
   immernoch hinter den bestehenden projekten."
   Man tippte also in ein Feld, das man nicht lesen konnte. */
/* Project workspace */
/* Monat und Betrag sind je EIN Wert, kein Fliesstext. Die automatische
   Tabellenbreite teilte trotzdem so zu, dass beide umbrachen: gemessen bei
   1400px Tabellenbreite bekam MONAT 74px und brauchte 100 ("2026-" / "07"),
   BETRAG bekam 90 und brauchte 109 ("59.49" / "EUR") - waehrend STATUS 45px
   und BEGRUENDUNG 64px uebrig hatten. Das passierte in JEDER Zeile und bei
   jeder Breite; es machte die Belegliste doppelt so hoch wie noetig.
   Auf schmalen Geraeten scrollt die Tabelle ohnehin waagerecht
   (siehe die @media-Regel weiter unten), ein Datum bricht dort also nicht
   um, sondern wandert aus dem Bild - das ist das kleinere Uebel. */
/* Marketing labels are typographic markers, not floating white pills. */
.bp-public :is(.eyebrow, .tag, .section-label) {
  display: inline-flex !important;
  align-items: center;
  gap: 0.65rem !important;
  width: auto !important;
  max-width: none;
  margin-right: auto !important;
  padding: 0 !important;
  border: 0 !important;
  border-radius: 0 !important;
  background: transparent !important;
  color: #59615b !important;
  box-shadow: none !important;
  font-size: 0.68rem !important;
  font-weight: 760 !important;
  letter-spacing: 0.11em !important;
  line-height: 1.25 !important;
  text-transform: uppercase !important;
}
.bp-public :is(.eyebrow, .tag, .section-label)::before {
  display: block !important;
  flex: 0 0 1.1111rem !important;
  width: 1.1111rem !important;
  height: 1px !important;
  background: var(--bp-accent) !important;
  content: "";
}


/* Software breathing-room pass: fewer nested panels, clearer work stages. */


/* ==========================================================================
   ENTERPRISE-PORTAL-SHELL
   Eine gemeinsame Shell fuer alle eingeloggten Seiten (Projekt-Workspace,
   Projekte, Rechnungen, Stammdaten, Bankverbindung). Bewusst zurueckhaltend:
   helle Flaechen, Haarlinien statt Schatten, Markengruen nur als Akzent -
   der Ton einer Buchhaltungsanwendung, nicht eines Consumer-Dashboards.
   Farben, Schrift und Abstaende stammen aus der Marketing-Palette.
   ========================================================================== */

/* ------------------------------------------------------------------ Sidebar */
/* HENRY, 06.08.2026: "oben links das beleghero logo stimmt nicht ganz. das
   hero soll auch den dunkelgruen ton haben, sodass alles ueberall einheitlich
   ist."

   Die Marketingseite setzt die Wortmarke seit jeher zweifarbig:
   `Beleg<span class="p">Hero</span>` mit .p in --green (siehe .nav-logo .p in
   bp2.css). Die Anwendung hatte dagegen EINE Span ohne Teilung - also
   durchgehend Tinte, kein Gruen. Zwei Wortmarken fuer eine Marke.

   Das Markup der fuenf Anwendungsseiten ist jetzt dasselbe wie im Marketing;
   diese Regel gibt dem Hero-Teil dieselbe Farbe. Eine dritte Variante gab es
   uebrigens auch noch: `.brand-beleg { color: #3f7a4f }` stand hart in
   index.html, start.html und post_purchase.html - ein Gruen, das in keinem
   Token vorkommt. Auch das ist weg. */
/* Nur die oberste Beschriftung braucht keinen Abstand nach oben - sie steht
   ohnehin direkt unter der Marke.

   Das war :first-of-type und meinte damit den ersten <span> unter seinen
   Geschwistern, nicht das erste Element. Seit die Projektschritte als <div>
   davorstehen, blieb "Projekt" der erste <span> und bekam weiter 0 - die
   Beschriftung klebte gemessen mit 0px an Schritt 4, waehrend alle anderen
   Gruppen 21px Luft hatten. :first-child fragt nach der Stellung, und darum
   geht es hier. */

/* --------------------------------------------------------------- Inhalt */

/* Die Kopfleiste ist davon ausgenommen, und zwar weil sie eine FLAECHE ist,
   kein Textblock. Der Deckel oben soll Zeilen kurz halten; bei der Leiste
   deckelt er stattdessen ihren Hintergrund - das graue Band hoert dann mitten
   auf der Seite auf, und rechts daneben steht Weiss.

   Ausgeklappt faellt das nicht auf: da ist der Inhaltsbereich schmaler als
   1180px und der Deckel bindet nie. EINGEKLAPPT wird er breiter, der Deckel
   greift, und das Band bricht ab. Emil, 05.08.2026: "diese graue bar ist im
   eingeklappten modus noch komisch."

   Der Inhalt der Leiste (Titel links, Aktionen rechts) darf die Breite
   nutzen - er steht ohnehin an den beiden Raendern, nicht als Fliesstext. */

/* ------------------------------------------------------- Mobile Ansicht ---
   Die Seitenleiste wuerde umgebrochen die halbe erste Bildschirmhoehe belegen.
   Auf schmalen Geraeten wird sie deshalb zu einem Menue, das ueber den Inhalt
   faehrt; darueber liegt eine schlanke Kopfzeile mit Marke und Schalter.
   Kopfzeile und Abdunklung erzeugt app-shell.js. */
.app-sr-only {
  position: absolute;
  width: 1px !important; height: 1px !important;
  margin: -1px !important; padding: 0 !important;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0 !important;
}

@media (max-width: 900px) {

  /* Flaeche mind. 44x44 px - auf dem Touchscreen sicher zu treffen. */
  body.app-nav-open .app-burger { background: transparent !important; }
  body.app-nav-open .app-burger::before { transform: translateY(5.5px) rotate(45deg) !important; }
  body.app-nav-open .app-burger::after  { transform: translateY(-5.5px) rotate(-45deg) !important; }
  body.app-nav-open .sidebar { transform: translateX(0) !important; }
  body.app-nav-open { overflow: hidden; }
}


/* Auf breiten Ansichten darf kein Menuezustand haengenbleiben. */

/* Navigationsbausteine, die zuvor in jeder Seite einzeln definiert waren. */

/* ------------------------------------------------------- Prozessleiste ---
   Die vier Schritte lagen auf `white-space: nowrap` mit `overflow: hidden`.
   Sobald eine Spalte schmaler wurde als die Beschriftung - auf dem Handy im
   2x2-Raster, aber auch auf mittleren Fenstern - wurde der Text hart
   abgeschnitten ("Zuordnungen pruefe"). Beschriftungen duerfen deshalb
   umbrechen; der Fortschritt bleibt so bei jeder Breite lesbar. */


/* Sehr schmale Geraete: vier Schritte untereinander bleiben lesbarer als ein
   gequetschtes Raster. */

/* ---------------------------------------------------- Tippflaechen mobil ---
   Fuss- und Navigationslinks waren nur 18-20 px hoch. Auf dem Touchscreen ist
   das zu wenig; WCAG 2.2 (2.5.8) nennt 24 px als Untergrenze, komfortabel
   sind 44 px. Die Hoehe kommt ueber Innenabstand, damit sich am Schriftbild
   und an der Zeilenfuehrung nichts aendert. */
@media (max-width: 900px) {


  /* Freistehende Textlinks in Fliesstext bleiben unberuehrt - dort wuerde ein
     Block die Zeile zerreissen. Nur eigenstaendige Aktionen werden groesser. */
  body.bp-app .main-content a.btn,
  body.bp-app .main-content button,
  body.bp-public .btn {
    min-height: var(--bp-tap) !important;
  }
}

/* ------------------------------------------ Rechnungspositionen (mobil) ---
   Die Kopfzeile der Positionstabelle stand auf `min-width: 640px` und lag
   ausserhalb des scrollenden Rahmens - sie schob deshalb die ganze Seite
   seitlich weg (Dokumentbreite 678 px bei 375 px Fenster). Auf schmalen
   Geraeten liegen die Felder untereinander; eine Spaltenueberschrift ergibt
   dort ohnehin keinen Sinn und weicht der Beschriftung am Feld selbst. */

/* Die Bedingung fragt seit dem 03.08.2026 die Formularspalte statt das
   Fenster (@container rechnungsspalte, gesetzt in invoices.html).
   Gemessen am 1280px-Bildschirm: die Spalte war 352px breit, die Zeile
   braucht 640px - sie scrollte seitlich. Weil das Fenster aber 1280px hat,
   griff `@media (max-width:680px)` nie, und dieser ganze Block - die
   Untereinander-Ansicht, die genau dafuer gebaut wurde - lag brach.
   Am Handy aendert sich nichts: die Spalte ist dort ebenfalls schmal. */
@container rechnungsspalte (max-width: 660px) {
  /* Feld und Beschriftung gehoeren sichtbar zusammen. */
}

/* ------------------------------------------------ Stammdaten: Logo (mobil) ---
   Die Schaltflaechenzeile lief ueber den Rand, weil ein Dateifeld seine
   natuerliche Breite behaelt und nicht schrumpft. */

/* Kopfzeile und Positionen scrollen gemeinsam in einem Rahmen. */

/* ------------------------------------------------------------ Grundmass ---
   Jede Seite ausser /datenschutz brachte diese Regel in ihrem eigenen
   Style-Block mit. Dort fehlte sie - dadurch addierte sich das Innenpolster
   auf die Breite (375 px Fenster, 407 px Inhalt) und die Seite liess sich
   seitlich schieben. Zentral gesetzt kann sie keine Seite mehr auslassen. */
*,
*::before,
*::after { box-sizing: border-box; }

/* Ab hier wird die einzeilige Prozessleiste zu eng fuer die Beschriftungen -
   das 2x2-Raster bleibt laenger lesbar als vier gequetschte Spalten. */

/* Der schwebende Hilfe-Knopf lag auf dem Inhalt. Am Seitenende bleibt jetzt
   Platz, damit die letzte Zeile einer Tabelle nicht darunter verschwindet. */

/* Eingabe-plus-Knopf-Zeilen auf sehr schmalen Geraeten.
   Flex-Kinder schrumpfen nicht unter ihre Inhaltsbreite (`min-width: auto`),
   deshalb schob die Zeile "Zugangscode + Freischalten" die Seite bei 320 px
   um 22 px zur Seite. Umbrechen statt schieben. */

/* Grundsatz fuer alle Eingabefelder in Flex-Zeilen: sie duerfen schrumpfen.
   Ohne das reisst ein einzelnes langes Feld die ganze Seite auf. */

/* ------------------------------------------------------ Abo & Zahlung ---
   Der Abschnitt trug eine kleine graue Ueberschrift, darueber stand die Zeile
   "Angemeldet als ..." frei im Raum - das wirkte wie ein Ueberbleibsel statt
   wie ein Abschnitt. Er folgt jetzt demselben Aufbau wie die Projektliste:
   Ueberschrift, erklaerende Zeile, rechts eine Randangabe. */

/* Der Abschnitt stand direkt unter der Projektliste ohne erkennbare Grenze. */


/* Der Abo-Abschnitt war als weisse Flaeche gesetzt, die Projektliste
   darueber nicht - dadurch begann ab der Ueberschrift ein Kasten, der die
   Seite in zwei Gestaltungen teilte. Beide Abschnitte liegen jetzt auf dem
   Seitenhintergrund; weiss ist nur die Box mit den Tarifen. */

/* Die Tarifkarten werden per JS mit Inline-Stilen erzeugt und haben keine
   eigene Klasse. Ihre Beschreibungen sind unterschiedlich lang, wodurch die
   Schaltflaechen auf verschiedenen Hoehen standen. Der Abstand oberhalb der
   letzten Zeile waechst jetzt mit, dann liegen sie auf einer Linie. */

/* Inline-Symbole statt Emojis. Farbige Emojis wirken in einem Buchhaltungs-
   werkzeug wie Fremdkoerper - besonders auf den Rechts- und Datenschutzseiten,
   wo sie den ernsten Ton untergraben. Die SVGs erben die Textfarbe und sitzen
   auf der Schriftlinie. */
.inline-warn {
  flex: none;
  margin-right: 0.4em;
  vertical-align: -0.18em;
}


/* ==========================================================================
   ZUSTANDSFARBEN
   Buchungen haben vier Zustaende, die auf einen Blick unterscheidbar sein
   muessen. Bisher lagen die Farben als feste Hexwerte in den einzelnen
   Seiten - und "wartet auf dich" trug dieselbe Warnfarbe wie "Beleg fehlt",
   obwohl das eine eine Aufgabe und das andere eine Luecke ist.
   Kontrast durchgehend mindestens 4.5:1 fuer kleinen Text.
   ========================================================================== */
:root {
  --bp-state-done-bg: #e6f0e8;      --bp-state-done-fg: #1e5c2d;
  --bp-state-review-bg: #fbeed4;    --bp-state-review-fg: #7d5409;
  --bp-state-open-bg: #fae2dc;      --bp-state-open-fg: #96371f;
  --bp-state-progress-bg: #e7edf5;  --bp-state-progress-fg: #2b5280;
  --bp-state-neutral-bg: #ecefe9;   --bp-state-neutral-fg: #5b625b;
}

/* Im Protokoll stand "wartet auf dich" in derselben Farbe wie "Beleg fehlt".
   Das eine ist eine offene Aufgabe, das andere eine Luecke - sie duerfen
   nicht gleich aussehen. */


/* ------------------------------------------------ Erster Besuch: leer ---
   Bewusst kein Kasten mit Rahmen: der Abschnitt steht fuer sich, die Schritte
   tragen die Struktur. */

/* Das hidden-Attribut wirkt nur ueber die Standardformatvorlage des Browsers
   und wird von jeder eigenen display-Angabe ueberstimmt - `.project-grid`
   traegt `display: grid` und blieb deshalb trotz hidden sichtbar. Diese Regel
   stellt das erwartete Verhalten wieder her. */
/* Doppelt notiert, damit die Regel auch Selektoren wie
   `.bp-account .project-grid { display: grid !important }` uebertrifft. */
[hidden][hidden] { display: none !important; }


/* ========================= TEIL 3: LESBARKEIT DER APP =====================
   Ergaenzt 02.08.2026 nach einer Messung in der laufenden Oberflaeche
   (Schriftgroessen und Kontrastwerte je Element ausgelesen, nicht geschaetzt).
   Betrifft ausschliesslich den eingeloggten Bereich; die Marketingseiten
   bleiben unveraendert.

   Zwei Regeln als Untergrenze, die hier vorher vielfach unterschritten wurden:
   - alles Bedienbare und alle Fliesstexte:            mindestens 13px
   - kurze Etiketten, Abzeichen und Tabellenkoepfe:    mindestens 12px
   Die Groessenverhaeltnisse bleiben erhalten - die Hierarchie wird nur nach
   oben verschoben, nicht eingeebnet.
   ------------------------------------------------------------------------ */

/* 1. FEHLER: Terminal-Fenster war unlesbar.
      Teil 1 dieses Stylesheets zieht .mock-window zusammen mit .cost-cap-banner
      auf weissen Grund. Fuer das Banner ist das richtig, fuer das Terminal
      nicht: dessen Textfarbe (#e8e8e8) stammt aus dem Seiten-Stylesheet und ist
      fuer dunklen Grund gedacht. Ergebnis war ein Kontrast von 1,23:1 - der
      Befehl, den der Nutzer zum Starten der Suche kopieren muss, war praktisch
      unsichtbar. Terminal bleibt dunkel, zur Marke hin getoent statt neutralgrau. */
.mock-window {
  background: #22302a !important;
}
.mock-window .titlebar {
  background: #2c3d34 !important;
}
.mock-window .body {
  color: #eaf0ea !important;
  font-size: 0.8125rem !important;
  line-height: 1.55 !important;
}

/* 2. FEHLER: Kicker ueber der Projektueberschrift lag bei 4,01:1 (Soll 4,5:1)
      und zusaetzlich bei 10,6px. Dunkler und groesser. */

/* 3. Etiketten und Abzeichen: Untergrenze 12px.
      Vorher 9,3px (Fortschritts-Abzeichen) bis 11,8px. */

/* 4. Tabellenkoepfe: 28 Vorkommen bei 10,9px, im Buchungsverzeichnis die
      Orientierung ueber die gesamte Tabelle. */

/* 5. Bedienelemente und Fliesstext: Untergrenze 13px.
      Betrifft Knoepfe, Formularbeschriftungen und die Beschreibungstexte der
      Auswahlkarten - alles, was gelesen oder geklickt wird. */

/* 6. Abstaende auf eine 4er-Skala bringen.
      Gemessen waren 1, 8, 9, 10, 16, 19px nebeneinander - die krummen Werte
      stammen aus rem-Angaben wie 0.6rem und 1.2rem. Nur die Ausreisser werden
      eingefangen, die Rhythmik bleibt. */

/* 7. Nachtrag: Regeln, die die Untergrenze aus Punkt 3-5 noch unterlaufen haben.
      Teil 1 und 2 dieses Stylesheets setzen an 29 Stellen font-size unter 12px
      mit !important. Bei gleichem !important entscheidet die Spezifitaet,
      deshalb hier gezielt hoeher angesetzt. Die Marketingseiten
      (.bp-public/.bp-landing/.bp-marketing/.bp-kanzlei) bleiben bewusst
      unberuehrt - dort ist die kleine Auszeichnungsschrift gewollt. */

/* Kontoseite: Projektkacheln und Kopfzeile */

/* Projekt-Workspace: Schrittnummer und Karten-Auszeichnung */

/* Einziger ID-Selektor unter der Grenze - braucht deshalb ebenfalls eine ID. */

/* 8. FEHLER: zu helle Textfarben auf der Kontoseite.
      Gemessen am 02.08.2026 - fuenf Stellen unter 4,5:1, darunter der
      Einleitungstext bei 3,78:1 und der Projektmenue-Knopf bei 3,26:1.
      Ursache sind handverlesene Grautoene (#6e756f, #737a74, #8a908b), die
      HELLER sind als der eigene Token --bp-muted (#666c68). Der Token selbst
      besteht die Pruefung: 5,37:1 auf Weiss, 4,68:1 auf dem getoenten Grund
      der Kopfzeile. Es wird also keine neue Farbe erfunden, sondern die
      vorhandene durchgesetzt. */

/* Restliche Groessen-Ausreisser, die noch unter 12px lagen. */

/* 9. Nachzuegler aus dem zweiten Messdurchgang: Selektoren, die gegen
      spezifischere Regeln aus Teil 1/2 verloren hatten. */

/* 10. Rechnungs-Layoutwaehler: die Namen unter den Vorschaubildchen sind das
       einzige Unterscheidungsmerkmal der fuenf Vorlagen und lagen bei 11,8px. */
/* Letzte zwei Etiketten unter der Grenze, der Vollstaendigkeit halber. */

/* ========================== TEIL 4: FINOM-SCHICHT =========================
   Der Arbeitsbereich uebernimmt die Farbwelt und die Groessen des neuen
   Designs, ohne dass am Markup etwas veraendert wird.

   Warum das hier steht und nicht im Markup: theme.css benutzt seine
   --bp-*-Familie an 719 Stellen. Diese Familie einmal auf die Tokens aus
   bp2.css umzulegen verschiebt die ganze Anwendung auf einen Schlag und
   zusammenhaengend - waehrend jedes einzelne Umschreiben von Regeln 719
   Gelegenheiten waere, etwas zu uebersehen. Kein Selektor, keine ID und keine
   Klasse aendert sich dadurch.

   Voraussetzung: bp2.css wird VOR dieser Datei geladen. Das gilt inzwischen
   auf allen elf Seiten, die theme.css einbinden. Die Rueckfallwerte hinter
   jedem var() sind trotzdem gesetzt, damit eine vergessene Einbindung nicht
   zu farblosen Flaechen fuehrt, sondern zum bisherigen Aussehen. */

:root {
  /* --- Flaechen ---------------------------------------------------------
     Vorher warmes Grau (#f1f3f1, #f6f7f5), jetzt leicht ins Gruen getoente
     Neutraltoene. Derselbe Helligkeitsaufbau, nur zur Hausfarbe passend. */
  /* ACHTUNG, Ringbezug vermeiden: Teil 1 dieser Datei setzt --ink, --paper und
     --line auf die --bp-*-Familie. Wuerde hier umgekehrt var(--ink) stehen,
     zeigten beide Definitionen aufeinander. CSS wertet solche Zirkel als
     ungueltig aus - bei Farben heisst das durchsichtig, nicht "Rueckfallwert".
     Der Rueckfall hinter dem Komma greift naemlich nur, wenn eine Variable gar
     nicht definiert ist, nicht wenn sie ungueltig ist. Genau daran waren die
     drei Balken des Menuesymbols unsichtbar geworden.

     Fuer die drei Namen, die bp2.css und theme.css gemeinsam haben, stehen
     deshalb die Werte hier direkt. Alle uebrigen bp2-Tokens sind eindeutig und
     werden per var() bezogen. */
  --bp-white: oklch(99.4% 0.003 150);
  --bp-app-surface: oklch(99.4% 0.003 150);
  --bp-surface: oklch(99.4% 0.003 150);
  --bp-app-page: var(--surface, #f1f3f1);
  --bp-bone: var(--surface, #f3f5f3);
  --bp-canvas: var(--surface, #edf0ed);
  --bp-app-tonal: var(--surface, #f6f7f5);
  --bp-soft: var(--surface, #f3f5f3);
  --bp-app-tonal-strong: var(--surface-2, #ecefec);
  --bp-surface-subtle: var(--surface-2, #eef1f3);
  --bp-ash: var(--surface-2, #eef1f3);
  --bp-warm: var(--surface-2, #eef1f3);
  --bp-peach: var(--surface-2, #f1f3f5);
  --bp-sage: var(--surface-2, #f1f3f5);
  --bp-sky: var(--surface-2, #f1f3f5);

  /* --- Schrift ----------------------------------------------------------
     --bp-ink-2 war #263441, ein Blaugrau. Das war der einzige Ton in der
     Anwendung, der nicht zur gruenen Hausfarbe gehoerte. */
  --bp-ink: oklch(18% 0.014 152);
  --bp-corporate: oklch(18% 0.014 152);
  --bp-ink-2: var(--ink-2, #263441);
  --bp-corporate-2: var(--ink-2, #263441);
  --bp-muted: var(--ink-3, #666c68);

  /* --- Linien ------------------------------------------------------------ */
  --bp-line: oklch(90% 0.010 150);
  --bp-line-strong: var(--line-soft, #bfc6c0);

  /* --- Hausfarbe ---------------------------------------------------------
     --bp-accent war schon #2e4f35 und bleibt exakt gleich; bp2.css fuehrt
     denselben Wert als --green. Hier steht also keine Farbaenderung, sondern
     nur eine gemeinsame Quelle fuer beide Teile der Website. */
  --bp-accent: var(--green, #2e4f35);
  --bp-accent-strong: var(--green-deep, #24402a);
  --bp-accent-soft: var(--green-wash, #e8efe9);
  --bp-green-soft: var(--green-wash, #edf3ee);
  --bp-app-nav: var(--forest, #171a18);
  --bp-app-nav-soft: var(--green-deep, #242925);

  /* --- Form --------------------------------------------------------------
     Vorher lagen alle vier Radien bei 20px bzw. 30px - eine Schaltflaeche war
     so rund wie eine Karte. Jetzt gestaffelt, damit Groesse wieder etwas
     bedeutet. */
  --bp-radius-sm: var(--r-sm, 14px);
  --bp-radius-md: var(--r, 20px);
  --bp-radius-lg: var(--r-card, 26px);
  --bp-radius-xl: var(--r-lg, 34px);

  /* --- Tiefe -------------------------------------------------------------
     Standen auf none. Ohne jede Abstufung liegt alles in einer Ebene und die
     Augen finden keinen Einstieg. */
  --bp-shadow-soft: var(--sh-tile, none);
  --bp-shadow-lift: var(--sh-float, none);
  --bp-shadow-button: none; /* Schaltflaechen bleiben flach, das war Absicht */
  --bp-app-shadow: var(--sh-nav, 0 12px 34px rgba(23, 26, 24, 0.07));
}

/* --- Groessen ------------------------------------------------------------
   Der Ausloeser fuer den ganzen Umbau: "Texte zu klein und viel zu hell".
   Die Grundschrift lag bei 17px, der Entwurf sieht 19px vor.

   Gesetzt wird an der WURZEL und nicht am body, weil praktisch jede Groesse in
   dieser Anwendung in rem angegeben ist und rem sich auf <html> bezieht. Eine
   Regel am body haette nur die wenigen Stellen ohne eigene Schriftgroesse
   erreicht.

   112,5% sind 18px an der Wurzel. Der body traegt 1,0625rem und landet damit
   bei 19,1px - genau dem Zielwert. Zwischenschritt bewusst: 118,75% haetten
   den body auf 20,2px gehoben und zugleich alle Abstaende, Radien und Breiten
   um ein Fuenftel aufgeblaeht, weil die auch in rem stehen. Getestet, war zu
   viel.

   05.08.2026 - der Zeiger schlaegt zurueck. Henry: bei 75% Browserzoom sieht
   die Software gut aus, bei 100% ist sie zu gross. Deshalb der Faktor unten.

   Er steht bewusst als `calc(112,5% * 0,75)` und nicht ausgerechnet als
   84,375% da: so bleibt beides lesbar - der Grundwert von oben UND wie weit
   herausgezoomt wurde. Wer das zurueckdrehen will, aendert genau eine Zahl.

   Was das kostet, damit es niemand uebersieht: der body faellt von 19,1px auf
   14,3px. Das ist WENIGER als die 17px, die weiter oben als "zu klein"
   beanstandet wurden und den ganzen Umbau ausgeloest haben. Die beiden
   Rueckmeldungen widersprechen sich; hier gilt die neuere.

   Der Faktor allein reicht nicht. Er skaliert nur, was in rem steht - die
   Inhaltsspalten hingen an festen Pixeln (max-width: 1120px und Verwandte)
   und waeren stehen geblieben, waehrend die Schrift schrumpft. Die Zeile im
   Rechnungsbereich waere dadurch von rund 115 auf 154 Zeichen gewachsen, also
   SCHLECHTER lesbar statt besser. Deshalb sind diese 25 Deckel auf rem
   umgestellt (63,3333rem statt 1140px usw.) - bei 18px Wurzel rechnerisch
   derselbe Wert, aber sie skalieren jetzt mit. Siehe test_softwarezoom.py.

   Nicht mitskaliert - und das ist Absicht: die 44px Mindesthoehe der
   Bedienelemente direkt unter dieser Regel. 44px ist ein Fingermass nach
   WCAG 2.5.5, kein Schriftmass. Bei echtem Browserzoom waeren daraus 33px
   geworden; das waere unter die Schwelle gefallen. */
html {
  /* <<< HIER DREHEN. Das ist die einzige Zahl. >>>
     1,00 = wie bisher (18px)   0,90 = 16,2px   0,85 = 15,3px   0,75 = 13,5px

     Steht auf 0,90 und nicht auf Henrys 0,75. Begruendung, nachgemessen am
     1440x900-Fenster mit der Projektansicht:

       0,75 -> Grundschrift 14,3px, Fliesstext 12,2px, Gruppentitel der
               Seitenleiste 9,7px. Der weisse Inhaltsblock schrumpft, das
               gruene Seitengrau tritt ringsum hervor, die Orientierung
               ("wo bin ich?") geht verloren. Emil, 05.08.2026: "alles ist
               kaputt gefuehlt".
       0,90 -> Grundschrift 17,2px, spuerbar kompakter als vorher, alles
               lesbar, das Gruen bleibt Beiwerk.

     Der Unterschied zwischen beiden Urteilen ist kein Geschmack, sondern der
     Bildschirm: 75% BROWSERZOOM auf einem grossen oder hochaufloesenden
     Monitor ergibt etwas anderes als derselbe Faktor fest im Stylesheet, der
     jedes normale Notebook mittrifft. Deshalb ist die Zahl hier eine
     Stellschraube und keine Uebersetzung von Henrys Zoomstufe. */
  font-size: calc(112.5% * 0.9);
}


/* --- Der Mindestboden fuer Bedienelemente --------------------------------
   44px ist die begehbare Mindestgroesse nach WCAG 2.5.5, 56px tragen die
   Hauptschaltflaechen wie im Entwurf. Bewusst nicht pauschal 56px fuer jeden
   Knopf - in einer dichten Tabelle mit Zeilenaktionen zerreisst das die
   Zeilenhoehe.

   05.08.2026, beim Herauszoomen: der Boden stand absolut in px und ist beim
   Verkleinern als einziges stehen geblieben. Gemessen an einer Zeile der
   Seitenleiste: Schrift 15,9 -> 11,9px (richtig), Zeilenhoehe 49 -> 44px
   statt 37px. Das Verhaeltnis Hoehe zu Schrift kippte von 3,1 auf 3,64 -
   Emil sah es sofort ("die Seitenleiste sieht komisch aus"). Er hat recht:
   ein Text, der in einer zu hohen Zeile schwimmt, sieht falsch aus, und
   zwar ueberall in der Anwendung, nicht nur in der Leiste.

   Die Loesung ist nicht, die Barrierefreiheit fallenzulassen. 44px ist ein
   FINGERMASS - es gilt fuer Beruehrung, nicht fuer eine Maus. Also fragt der
   Boden jetzt nach dem Zeigegeraet:

     Maus/Trackpad -> mitskalierend (2,4444rem = 44px bei 18px Wurzel,
                      33px bei 13,5px). Damit bindet er meist gar nicht mehr,
                      und die Zeile findet ihre natuerliche Hoehe von 36,1px.
                      Immer noch ueber den 24px, die WCAG 2.5.8 (AA) fordert.
     Beruehrung     -> unveraendert 44px bzw. 56px absolut, volle 2.5.5.

   Ein Notebook mit Bildschirmberuehrung bekommt den grossen Boden - richtig,
   dort wird auch getippt. */
:root {
  --bp-tap: 2.4444rem;   /* 44px bei 18px Wurzel */
  --bp-tap-m: 2.6667rem; /* 48px */
  --bp-tap-l: 3.1111rem; /* 56px */
}
@media (pointer: coarse) {
  :root {
    --bp-tap: 44px;
    --bp-tap-m: 48px;
    --bp-tap-l: 56px;
  }
}

/* --- Navigationssymbole ---------------------------------------------------
   Von app-shell.js eingesetzt. Sie tragen die eingeklappte Leiste; im
   ausgeklappten Zustand stehen sie ruhig vor der Beschriftung. */
body.bp-app .sidebar .nav-item,
body.bp-app .sidebar .nav-subitem,
body .sidebar .nav-item,
body .sidebar .nav-subitem {
  display: flex !important;
  align-items: center;
  gap: 0.7rem;
}
.sidebar .nav-symbol {
  flex: none;
  width: 1.1111rem;
  height: 1.1111rem;
  opacity: 0.62;
}
.sidebar .nav-item.active .nav-symbol,
.sidebar .nav-subitem.active .nav-symbol {
  opacity: 1;
  color: var(--bp-accent);
}
.sidebar .nav-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- Leiste einklappen ----------------------------------------------------
   Unter 901px uebernimmt die Menueschublade aus buildMobileChrome(); dort darf
   der Knopf gar nicht erst auftauchen, sonst gaebe es zwei Bedienwege fuer
   dieselbe Leiste. */
.sidebar-collapse {
  display: none;
}
@media (min-width: 901px) {
  .sidebar-collapse {
    display: inline-grid;
    place-items: center;
    margin-left: auto;
    flex: none;
    width: var(--bp-tap);
    height: var(--bp-tap);
    min-height: var(--bp-tap);
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--bp-muted);
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease, transform 0.35s var(--ease, ease);
  }
  .sidebar-collapse:hover {
    background: var(--bp-app-tonal-strong);
    color: var(--bp-ink);
  }
  .sidebar-collapse:focus-visible {
    outline: 2px solid var(--bp-accent);
    outline-offset: 2px;
  }

  /* ---------------------------------------------------------------- schmal
     Eingeklappte Leiste.

     Das AUSSEHEN kommt aus app-neu.css unter `.app.narrow` - das ist der
     Entwurf, und er ist dort vollstaendig ausgestaltet. Diese Klasse wurde
     nur nie gesetzt (nachgetragen in app-shell.js:leisteAufbauen), weshalb
     die Leiste bis zum 03.08.2026 auf halb fertige Ersatzregeln zurueckfiel:
     Spalte 88px breit bei scrollWidth 112px, Wortmarke bis 102px
     hinausragend, Einklapp-Knopf bei left 70 mit 42px Breite komplett
     ausserhalb, Beschriftungen zu "ARB" und "KON" abgeschnitten.

     Hier bleibt nur, was der Entwurf nicht kennen kann.
     ------------------------------------------------------------------- */
  body.bp-leiste-schmal .sidebar {
    width: 4.9rem !important;
    min-width: 4.9rem !important;
    /* Eine Symbolspalte hat nichts waagerecht zu rollen. Ohne diese Zeile
       zeigte der Browser den Ueberlauf als Rollbalken quer durch die Leiste. */
    overflow-x: hidden;
    /* Der Entwurf gibt .side gar keinen waagerechten Innenabstand - dort
       polstern .side-head und .side-scroll selbst. Hier standen zusaetzlich
       2x15,3px an der Leiste. Gemessen blieben dem Kopf dadurch 24,2px
       Innenbreite fuer ein 26px breites Logo, und das SVG wurde als
       schrumpfbares Flex-Kind auf 4,4px gequetscht - sichtbar als
       abgeschnittener Rest der Marke. */
    padding-inline: 0 !important;
  }
  /* Und damit es auch dann nicht schrumpft, wenn der Platz einmal knapp
     wird: eine Bildmarke wird lieber abgeschnitten als verzerrt - hier
     gar nicht erst zusammendruecken lassen. */
  body.bp-leiste-schmal .sidebar .sidebar-brand .radar-logo {
    flex: none !important;
    width: 1.4444rem !important;
    height: 1.4444rem !important;
  }
  /* Den Hinweis auf den neuen Tab gibt es im Entwurf nicht - er kam mit dem
     Datenschutz-Punkt dazu. Ohne Beschriftung ergibt er keinen Sinn. */
  body.bp-leiste-schmal .sidebar .nav-extern { display: none !important; }

  .sidebar {
    transition: width 0.35s var(--ease, ease);
  }
}


/* Kopfzeile der Leiste: Marke links, Einklapp-Knopf rechts. Ohne diese Zeile
   waere der Knopf ein weiteres Kind der Flex-Spalte und wuerde die volle
   Breite belegen. */
.sidebar .sidebar-head {
  display: flex !important;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
}
.sidebar .sidebar-head .sidebar-brand {
  min-width: 0;
  flex: 1 1 auto;
}

/* Die Symbole muessen sich gegen die Bildregel aus bp2.css durchsetzen
   (img, video, svg { max-width:100% }) - ohne feste Groesse skaliert das SVG
   auf die volle Spaltenbreite. */
.sidebar .nav-symbol {
  width: 1.1111rem !important;
  height: 1.1111rem !important;
  min-width: 1.1111rem;
  flex: 0 0 1.1111rem !important;
}

/* ======================= TEIL 5: MOBIL, NEUES DESIGN ======================
   Gemessen bei 375, 390, 414 und 768 px. Jede Regel hier behebt einen Befund,
   der vorher nachweisbar war - nicht vorsorglich.

   Grenze 900px, passend zur vorhandenen Menueschublade in app-shell.js: ab da
   uebernimmt die Leiste wieder ihren Platz links. */

@media (max-width: 900px) {
  /* 1. Abschnittskopf: war ein Flex mit space-between. Auf 375px passen Titel
        und Zaehler nicht nebeneinander, der Titel wurde dadurch nach rechts
        gedrueckt und sah aus wie rechtsbuendig gesetzt. */

  /* 2. Projektkarten: lagen als vierspaltiges Raster (132px 71px 0 34px) auf
        einer 339px breiten Karte. Der Name bekam 132px und wurde mit
        Auslassungspunkten abgeschnitten - "Reisekosten S...". Untereinander
        hat er die volle Breite. */
  /* :nth-child(n) steht hier nur, um die Spezifitaet von
     ".bp-account .project-card:nth-child(n)" weiter oben zu erreichen - die
     Regel setzt das vierspaltige Raster mit !important. Ohne den Zusatz
     verliert diese Regel und die Karte bliebe vierspaltig. */
  /* Der Öffnen-Verweis stand neben dem abgeschnittenen Namen. Als eigene Zeile
     ist er zugleich ein ordentlich grosses Ziel. */

  /* 3. Ueberschriften: der Entwurf setzt sie sehr gross. Bei 375px verbraucht
        eine 3rem-Zeile den halben ersten Bildschirm, bevor Inhalt kommt. */

  /* 4. Tabellen duerfen die Seite nicht breiter machen; sie scrollen in sich.
        Ohne das schiebt eine einzige breite Zeile das ganze Layout auf. */

  /* 5. Nichts darf ueber den rechten Rand hinausragen. Lange Kontonummern,
        Dateinamen und Adressen ohne Leerzeichen sind die haeufigste Ursache. */
  /* Kontonummern, Token und Dateipfade haben keine Umbruchstellen. Hier ist
     Trennen an beliebiger Stelle richtig, sonst sprengen sie das Layout. */

  /* 6. Der Mobil-Kopfbalken traegt die einzige Navigation. Er muss ueber allem
        liegen und beim Scrollen erreichbar bleiben. */
}

/* Sehr schmale Geraete: ab hier wird jede zweite Spalte zur Zeile. */


.sidebar .konto-zusatz {
  font-size: 0.78rem;
  /* --bp-ink-3 gibt es nicht; --bp-muted (#666c68) ist derselbe Ton
     und steht in dieser Datei. */
  color: var(--bp-muted);
  line-height: 1.3;
}
/* Leer heisst weg, nicht "leere Zeile mit Hoehe" - sonst sitzt der Eintrag
   schief, solange /account/me noch laeuft. */
.sidebar .konto-zusatz:empty { display: none; }

/* In der eingeklappten Leiste zeigt jeder Eintrag nur sein Symbol. Der
   Zustandstext wuerde dort als abgeschnittener Rest stehenbleiben. */

/* --- Kante an der rollenden Leiste ------------------------------------------
   Sichtbares Zeichen, dass unter dem Ausschnitt noch Eintraege liegen. Auf der
   Projektseite sind das bei 800px Fensterhoehe 560px - der ganze
   Konto-Abschnitt samt "Vertrag kuendigen". Auf einem Mac blendet sich die
   ueberlagernde Bildlaufleiste aus, sobald man nicht rollt; dann gibt es ohne
   diese Kante gar kein Zeichen mehr.

   UMGESETZT ALS MASKE, NICHT ALS SCHICHT DARUEBER
   Der erste Anlauf war ein klebendes Pseudo-Element mit Verlauf. Es lud, der
   Selektor traf, die Deckkraft stand auf 1 - und im Bild war nichts zu sehen.
   Eine Maske blendet stattdessen den INHALT an der Kante aus:

     - sie kann keine Klicks schlucken, weil sie kein Element ist. Genau das
       war die groesste Sorge: der unterste sichtbare Eintrag ist auf der
       Projektseite "Vertrag kuendigen", und eine unsichtbare Schicht darueber
       waere die schlechteste denkbare Nebenwirkung (§ 312k verlangt leichte
       Zugaenglichkeit).
     - sie haengt am Kasten, nicht am gerollten Inhalt, rollt also nicht weg.
     - sie braucht keine Farbe, die zum Hintergrund passen muss.

   Die drei Regeln haengen an den Klassen, die app-shell.js aus drei gemessenen
   Zahlen setzt. Ohne Klasse KEINE Maske - eine Kante bei vollstaendig
   sichtbarem Inhalt wuerde dauerhaft etwas Falsches behaupten, und wer bis ans
   Ende gerollt hat, sieht alles. */

/* Eingeklappt ist die Spalte 4,6rem schmal. Die Kante bleibt richtig - sie
   haengt an gemessenen Zahlen, nicht an der Breite - nur flacher, damit sie
   dort nicht den halben Ausschnitt einnimmt. */
