/* KUKANILEA Webtools — Rechnungs- & Angebotsgenerator. Eigenständige Subdomain, eigenes
   Mini-Design-System (Brand-Werte aus sites/kukanilea-www/styles.css :root übernommen, nicht
   importiert — volle Unabhängigkeit der Subdomain; identische Tokens wie kukanilea-brief). */

:root {
  --cream: #ffffff;
  --ink: #0f172a;
  --ink-2: #1e293b;
  --ink-3: #475569;
  --ink-4: #5a6678;
  --line: #e6ebf1;
  --line-2: #cbd5e1;
  --white: #ffffff;
  --paper: #f4f6f9;
  --blue: #1B4965;
  --blue-2: #123449;
  --blue-soft: #d7e3ea;
  --blue-tint: #eef3f6;
  --green: #18553a;
  --green-soft: #e4f1e9;
  --green-border: #bfe0cd;
  --warn-ink: #97491a;
  --warn-soft: #fde9d4;
  --red-ink: #8a1f2b;
  --red-soft: #fbe0e2;

  --radius: 14px;
  --radius-lg: 20px;
  --radius-sm: 8px;
  --shadow-sm: 0 1px 0 rgba(15,23,42,.04), 0 1px 2px rgba(15,23,42,.05);
  --shadow: 0 1px 0 rgba(15,23,42,.04), 0 12px 28px -16px rgba(15,23,42,.16);

  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: "SFMono-Regular", "SF Mono", "IBM Plex Mono", monospace;
  --maxw: 880px;
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
html body [hidden] { display: none; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.container { max-width: var(--maxw); margin: 0 auto; padding: 0 20px; }
.wide { max-width: 1080px; }

a { color: var(--blue); }

.skip-link {
  position: absolute; left: -999px; top: 0;
  background: var(--blue); color: var(--white); padding: 10px 16px; z-index: 100;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ── Header ── */
.site-header {
  background: var(--white);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: 40;
}
.header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 14px 20px;
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; color: var(--ink); }
.brand-mark { display: block; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-weight: 700; font-size: 15px; letter-spacing: .01em; }
.brand-sub { font-size: 11px; color: var(--ink-4); font-weight: 600; text-transform: uppercase; letter-spacing: .06em; }
.brand-sub.tool-suite { color: var(--blue); }

.site-nav { display: flex; flex-wrap: wrap; gap: 4px 18px; }
.site-nav a { color: var(--ink-3); font-size: 14px; font-weight: 600; text-decoration: none; }
.site-nav a:hover, .site-nav a[aria-current] { color: var(--blue); }

.header-actions a.text-link { font-size: 14px; font-weight: 600; text-decoration: none; }

@media (max-width: 720px) {
  .header-row { flex-wrap: wrap; }
  .site-nav { order: 3; width: 100%; padding-top: 8px; border-top: 1px solid var(--line); }
}

/* ── Hero / intro ── */
.tool-hero { padding: 44px 0 8px; }

/* ── Verdichteter Einstieg (UI-Pilot A, 2026-09-15) ────────────────────────
   Nur der Rechnungsgenerator traegt diese Klasse. Messwerte und Begruendung
   stehen im Kommentar an der Fundstelle in rechnungsgenerator.html.

   Kein Inhalt verschwindet -- nur Abstaende und Schriftgroessen werden auf
   schmalen Geraeten kleiner. Wer die Seite zum ARBEITEN oeffnet, soll im
   ersten Bildschirm auch etwas zu bearbeiten finden. */
@media (max-width: 720px) {
  .tool-hero-kompakt { padding: 20px 0 4px; }
  .tool-hero-kompakt h1 { font-size: clamp(22px, 6vw, 28px); margin: 0 0 8px; }
  .tool-hero-kompakt p.lede { font-size: 15px; line-height: 1.45; }
  .tool-hero-kompakt .tool-kicker { font-size: 11px; margin-bottom: 6px; }
  /* Der Datenschutzhinweis bleibt -- er ist eine Produktaussage, keine
     Dekoration -- steht aber kompakter und ohne grosse eigene Flaeche. */
  .tool-hero-kompakt .privacy-note { margin-top: 10px; padding: 8px 10px; font-size: 13px; }

  /* Wiederkehrer: die Lede erklaert, was dieses Werkzeug tut. Wer hier seine
     Firmendaten hinterlegt hat, hat die Antwort. Die Klasse setzt
     rechnungsgenerator.js, nicht das Markup -- ein Crawler sieht immer die
     vollstaendige Seite. Titel und Datenschutzzusage bleiben stehen. */
  .tool-hero-wiederkehrer p.lede { display: none; }
}
.tool-kicker {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--blue); margin-bottom: 10px;
}
.tool-hero h1 { font-size: clamp(28px, 4vw, 38px); line-height: 1.15; margin: 0 0 12px; letter-spacing: -0.01em; }
.tool-hero p.lede { font-size: 17px; color: var(--ink-3); max-width: 60ch; margin: 0 0 0; }

.privacy-note {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 22px 0 0;
  padding: 14px 16px;
  background: var(--blue-tint);
  border: 1px solid var(--blue-soft);
  border-radius: var(--radius);
  font-size: 14px; color: var(--blue-2);
}
.privacy-note svg { flex: none; margin-top: 2px; }

/* ── Tool card / workspace ── */
.tool-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 28px;
  margin: 28px 0 40px;
}
.tool-card-title { margin: 0 0 4px; font-size: 17px; }
.tool-card-hint { margin: 0 0 14px; font-size: 14px; color: var(--ink-3); }

/* ── Entwurf-Verlauf: mehrere Zwischenstände + eingefrorene Exporte einsehbar ── */
.history-bar { margin: 0 0 6px; }
.history-panel {
  margin: 0 0 20px; padding: 16px; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--radius);
}
.history-intro { margin: 0 0 12px; font-size: 12.5px; color: var(--ink-4); }
.history-empty { margin: 0; font-size: 13.5px; color: var(--ink-4); }
.history-row {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 14px; padding: 10px 0; border-top: 1px solid var(--line);
}
.history-row:first-child { border-top: 0; padding-top: 0; }
.history-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; min-width: 0; }
.history-badge {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  padding: 3px 9px; border-radius: 999px; background: var(--blue-tint); color: var(--blue-2);
}
.history-badge.is-locked { background: var(--line-2); color: var(--ink-3); }
.history-label { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.history-ts { font-size: 12px; color: var(--ink-4); }
.history-actions { display: flex; align-items: center; gap: 8px; flex: none; }
.history-locked-hint { font-size: 12px; color: var(--ink-4); font-style: italic; }

.tool-actions { display: flex; align-items: center; gap: 14px; margin-top: 20px; flex-wrap: wrap; }

/* Kartentitel und Nebenaktion auf einer Zeile -- der Verlauf belegt keine
   eigene Zeile mehr vor dem ersten Eingabefeld (UI-Pilot A). */
.karten-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.karten-kopf .tool-card-title { margin-bottom: 0; }

/* Absender-Zusammenfassung: vier Zeilen statt neun offener Felder.
   Bewusst KEINE Karte in der Karte -- eine weitere Box machte alles wieder
   gleich wichtig. Eine ruhige Flaeche mit Akzentkante genuegt. */
.absender-zusammenfassung {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 18px;
  padding: 12px 14px;
  border-left: 3px solid var(--blue);
  background: var(--blue-tint);
  border-radius: var(--radius-sm);
}
.absender-zusammenfassung .az-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.absender-zusammenfassung strong { font-size: 15px; color: var(--ink); }
.absender-zusammenfassung span { font-size: 13.5px; color: var(--ink-3); }
.absender-zusammenfassung .az-meta { color: var(--ink-4); font-size: 12.5px; }
.absender-zusammenfassung .btn { flex: none; min-height: 44px; }

/* ── Persistente Hauptaktion (UI-Pilot A, 2026-09-15) ──────────────────────
   Nur der Rechnungsgenerator traegt diese Klasse. Begruendung und Messwerte
   stehen im Kommentar an der Fundstelle in rechnungsgenerator.html.

   `position: sticky` mit `bottom: 0` haelt die Zeile im Blick, ohne sie aus
   dem Dokumentfluss zu nehmen: die Leiste bleibt an ihrem Platz im DOM, also
   auch in der Lesereihenfolge und in der Tabulatorfolge. Ein `position:
   fixed`-Balken waere ein Element, das am Ende vorgelesen wird und trotzdem
   oben klebt. */
.tool-actions-haftend {
  position: sticky;
  bottom: 0;
  z-index: 20;
  margin-top: 28px;
  padding: 12px 16px;
  /* Die sichere Zone moderner Telefone -- ohne sie liegt die Hauptaktion auf
     dem Homebalken. */
  padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--line);
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: color-mix(in srgb, var(--white) 92%, transparent);
  backdrop-filter: blur(8px);
  box-shadow: 0 -2px 12px rgb(0 0 0 / 6%);
}
/* Browser ohne color-mix bekommen eine deckende Flaeche statt einer
   durchscheinenden -- lesbar bleibt sie in beiden Faellen. */
@supports not (background: color-mix(in srgb, white 50%, transparent)) {
  .tool-actions-haftend { background: var(--white); }
}
/* WCAG 2.2 SC 2.4.11 Focus Not Obscured: ein klebender Balken darf das
   fokussierte Feld nicht verdecken. Die Bildlaufpolsterung sorgt dafuer, dass
   der Browser ein per Tabulator angesprungenes Feld oberhalb der Leiste
   anhaelt statt darunter. */
html:has(.tool-actions-haftend) { scroll-padding-bottom: 96px; }
/* "Entwurf verwerfen" vernichtet Arbeit und darf nicht neben der Hauptaktion
   liegen -- es rutscht ans andere Ende der Zeile. */
/* Die Verwerfen-Zeile steht unter der klebenden Leiste im normalen Fluss --
   erreichbar, aber nicht unter dem Daumen. */
.tool-actions-abseits { margin-top: 12px; justify-content: flex-end; }

/* Die Kurzform der Nebenaktion erscheint nur, wo der lange Text die Leiste
   in eine zweite Zeile zwingen wuerde. Der zugaengliche Name kommt aus dem
   aria-label und bleibt in beiden Faellen vollstaendig. */
.tool-actions-haftend .ta-kurz { display: none; }
@media (max-width: 560px) {
  .tool-actions-haftend { flex-wrap: nowrap; gap: 8px; padding: 10px 12px; }
  .tool-actions-haftend .ta-lang { display: none; }
  .tool-actions-haftend .ta-kurz { display: inline; }
  /* Die Hauptaktion nimmt den Platz, die Nebenaktion nur so viel wie noetig. */
  .tool-actions-haftend #processBtn { flex: 1 1 auto; }
  .tool-actions-haftend #xmlBtn { flex: 0 0 auto; }
  /* Komfortziel fuer zentrale Touch-Aktionen -- WCAG verlangt 24, hier ist
     mehr richtig, weil es die Hauptaktion des Werkzeugs ist. */
  .tool-actions-haftend .btn { min-height: 44px; }
  /* Der Status braucht in der schmalen Leiste keine eigene Spalte; er steht
     ohnehin zusaetzlich in der Ergebnisanzeige. */
  .tool-actions-haftend #status { flex-basis: 100%; font-size: 12.5px; }
  .tool-actions-haftend #status:empty { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .tool-actions-haftend { backdrop-filter: none; background: var(--white); }
}

.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 11px 20px;
  border-radius: 999px;
  font-size: 14px; font-weight: 700;
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
}
.btn-primary { background: var(--blue); color: var(--white); }
.btn-primary:hover:not(:disabled) { background: var(--blue-2); }
.btn-primary:disabled { background: var(--line-2); color: var(--ink-4); cursor: not-allowed; }
.btn-ghost { background: var(--white); color: var(--ink-2); border-color: var(--line-2); }
.btn-ghost:hover { border-color: var(--blue); color: var(--blue); }
.btn-ghost:disabled { opacity: .45; cursor: not-allowed; border-color: var(--line-2); color: var(--ink-2); }
.btn-sm { padding: 6px 12px; font-size: 12.5px; }

/* Die Aktionsmeldung darf die Leiste, in der sie steht, nicht wachsen lassen.
   Gemessen am 2026-09-15: sobald Text erschien, brach die Flexzeile um, die
   haftende Leiste wuchs um 36px, und die Hauptaktion sprang mit nach oben --
   ein Fingertipp darauf ging verloren, weil der Knopf zwischen Druck und
   Loslassen weggerutscht war. Im echten Klicktest erhielt der Knopf null
   Klickereignisse.

   Eine Zeile, notfalls gekuerzt. Fuer Vorlesesoftware bleibt der Text
   vollstaendig: `role="status"` liest den textContent, nicht das, was sichtbar
   ist -- und die ausfuehrliche Fassung steht ohnehin in der Fehleruebersicht. */
.tool-status {
  flex: 1 1 0; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-size: 14px; color: var(--ink-3);
}
/* Die Meldung nimmt den Rest, die Knoepfe geben nichts ab.
   Live auf 390px gemessen, nachdem die Meldung eine Zeile bekam: sie belegte
   177 von 390px, "PDF erstellen" wurde auf 100px gequetscht und brach auf zwei
   Zeilen um -- die Leiste wuchs auf 77px. Die Hauptaktion ist das Letzte, was
   hier schrumpfen darf. */
.tool-actions-haftend > .btn { flex: 0 0 auto; white-space: nowrap; }
/* Der Speicherstand im Kartenkopf: ruhig, klein, ohne eigene Flaeche. */
.speicher-status { margin-left: auto; font-size: 12.5px; color: var(--ink-4); }
.speicher-status[data-state="error"] { color: var(--warn-ink); font-weight: 600; }
.tool-status[data-state="error"] { color: var(--warn-ink); }
.tool-status[data-state="done"] { color: var(--green); font-weight: 600; }

.result-panel {
  margin-top: 20px;
  padding: 18px;
  background: var(--green-soft);
  border: 1px solid var(--green-border);
  border-radius: var(--radius);
  display: none;
}
.result-panel.is-visible { display: block; }
.result-panel h3 { margin: 0 0 6px; font-size: 15px; color: var(--green); }

/* ── Landing: tool grid ── */
.tool-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  margin: 28px 0 48px;
}
.tool-tile {
  display: block;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 22px;
  text-decoration: none;
  color: var(--ink);
  box-shadow: var(--shadow-sm);
  transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease;
}
.tool-tile:hover { transform: translateY(-2px); box-shadow: var(--shadow); border-color: var(--blue-soft); }
.tool-tile .tt-icon { color: var(--blue); margin-bottom: 12px; }
.tool-tile h2 { font-size: 16px; margin: 0 0 6px; }
.tool-tile p { font-size: 13.5px; color: var(--ink-3); margin: 0; }

/* ── Footer ── */
.site-footer {
  border-top: 1px solid var(--line);
  padding: 32px 0 40px;
  margin-top: 40px;
}
.ft-row {
  display: flex; flex-wrap: wrap; gap: 10px 24px;
  align-items: center; justify-content: space-between;
  font-size: 13px; color: var(--ink-4);
}
.ft-links { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.ft-links a { color: var(--ink-4); text-decoration: none; }
.ft-links a:hover { color: var(--blue); }

/* ── Formular (Rechnungs-/Angebotsgenerator) ── */
.job-form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 20px;
  margin-top: 20px;
}
.job-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.job-field.full { grid-column: 1 / -1; }
.job-field label { font-size: 13px; font-weight: 700; color: var(--ink-2); }
.job-field input[type="text"],
.job-field input[type="number"],
.job-field input[type="date"],
.job-field input[type="email"],
.job-field input[type="tel"],
.job-field textarea,
.job-field select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--white);
}
.job-field textarea { resize: vertical; min-height: 70px; line-height: 1.5; }
.job-field input:focus, .job-field textarea:focus, .job-field select:focus {
  outline: 2px solid var(--blue-soft); border-color: var(--blue);
}
.job-field .field-hint { font-size: 12px; color: var(--ink-4); }
.job-field .field-hint-warn { color: var(--warn-ink); font-weight: 600; }
.job-field input.field-mismatch { border-color: var(--warn-ink); background: var(--warn-soft); }

.preset-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.preset-chip {
  font: inherit; font-size: 12.5px; padding: 5px 12px; border-radius: 999px;
  border: 1px solid var(--line-2); background: var(--white); color: var(--ink-3); cursor: pointer;
}
.preset-chip:hover { border-color: var(--blue); color: var(--blue); background: var(--blue-tint); }

@media (max-width: 640px) {
  .job-form { grid-template-columns: 1fr; }
}

.form-section-title {
  margin: 32px 0 4px; font-size: 13px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-4);
}
.form-section-title:first-child { margin-top: 0; }

/* Progressive Disclosure: erweiterte Rechnungs-Sektionen (E-Rechnung, Individualisierung)
   defaultmäßig eingeklappt, siehe Compliance-Review Phase 6 (WEBTOOLS.md 2026-07-24). */
.form-section-collapsible { margin: 32px 0 4px; }
/* Die Ueberschrift sitzt seit dem 2026-09-15 IM summary, damit die Bereiche in
   der Ueberschriftengliederung erscheinen -- die Formatierung folgt ihr nach. */
.form-section-collapsible summary.form-section-summary {
  margin: 0; cursor: pointer; list-style: none; display: flex; align-items: center; gap: 6px;
}
.form-section-collapsible summary.form-section-summary > .form-section-title { margin: 0; }
.form-section-collapsible summary.form-section-summary::-webkit-details-marker { display: none; }
.form-section-collapsible summary.form-section-summary::before {
  content: "▸"; display: inline-block; font-size: 11px; color: var(--blue); transition: transform .15s ease;
}
.form-section-collapsible[open] summary.form-section-summary::before { transform: rotate(90deg); }
.form-section-collapsible .job-form { margin-top: 14px; }

.toggle-row { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.toggle-row input[type="checkbox"] { width: 18px; height: 18px; accent-color: var(--blue); cursor: pointer; }
.toggle-row label { font-size: 14px; color: var(--ink-2); cursor: pointer; }
.toggle-hint { font-size: 12.5px; color: var(--ink-4); margin: 4px 0 0 28px; }

.calc-inputs { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px 20px; margin: 12px 0 0 28px; }
.calc-field { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--ink-3); }
.calc-field input { width: 70px; padding: 6px 8px; }
.calc-preview { flex-basis: 100%; font-weight: 600; color: var(--ink-2); margin-top: 4px; }

.ref-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin: 0 0 16px; padding: 10px 14px; border-radius: var(--radius-sm);
  background: var(--warn-soft); border: 1px solid var(--warn-ink);
  font-size: 13px; color: var(--warn-ink); font-weight: 600;
}
.ref-banner .btn-sm { flex-shrink: 0; }

/* ── Positionstabelle ── */
/* `position: relative` macht den Scrollrahmen zum Bezugspunkt fuer alles, was in ihm absolut
   positioniert ist. Ohne das bezieht sich die `.sr-only`-Beschriftung der letzten Spalte auf
   den Viewport: sie ist zwar weggeclippt, zaehlt aber zum Scrollbereich des Dokuments, und
   `documentElement.scrollWidth` meldete 662 statt 375, obwohl die Seite gar nicht mehr
   waagerecht scrollte. Eine Messgroesse, die luegt, laesst sich nicht mehr als Gate benutzen. */
.item-table-wrap {
  overflow-x: auto; margin-top: 18px; position: relative;
  /* Ein waagerechter Wischer im Rahmen darf nicht die Zurueck-Geste des Browsers ausloesen. */
  overscroll-behavior-x: contain;
}
/* Sobald der Rahmen wirklich scrollt, muss man das auch sehen. Rollbalken sind auf Telefonen
   und auf macOS unsichtbar, bis jemand zufaellig wischt -- eine abgeschnittene Spalte sieht
   dann aus wie eine fehlende, und der Nutzer sucht das Preisfeld, das er fuer verschwunden
   haelt. Die beiden Schattenkanten sind der bekannte reine CSS-Hinweis: die weissen
   Deckflaechen haengen an der Scrollposition (`local`), die Schatten stehen fest (`scroll`) --
   wo es weitergeht, schiebt sich der Schatten unter der Deckflaeche hervor. Kein JavaScript,
   kein zusaetzliches Markup (der Angebotsgenerator teilt sich diese Regel und liegt nicht im
   Schreibbereich dieses Werkzeugs). */
.item-table-wrap {
  background:
    linear-gradient(to right, var(--white) 40%, rgba(255, 255, 255, 0)) 0 0 / 28px 100% no-repeat local,
    linear-gradient(to left, var(--white) 40%, rgba(255, 255, 255, 0)) 100% 0 / 28px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, rgba(15, 23, 42, .22), rgba(15, 23, 42, 0)) 0 0 / 16px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, rgba(15, 23, 42, .22), rgba(15, 23, 42, 0)) 100% 0 / 16px 100% no-repeat scroll;
}
/* Der Hinweis ist Dekoration; auf Papier hat er nichts zu suchen (dort scrollt nichts). */
@media print { .item-table-wrap { background: none; } }
table.item-table { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 640px; }
table.item-table th {
  text-align: left; padding: 6px 8px; color: var(--ink-4); font-size: 11.5px;
  text-transform: uppercase; letter-spacing: .03em; border-bottom: 1px solid var(--line-2);
}
table.item-table td { padding: 5px 8px; vertical-align: top; }
table.item-table input[type="text"], table.item-table input[type="number"], table.item-table select {
  width: 100%; padding: 7px 9px; border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  font-size: 13.5px; font-family: var(--font-sans); color: var(--ink); background: var(--white);
}
table.item-table td.col-desc { min-width: 220px; }
table.item-table td.col-qty, table.item-table td.col-price, table.item-table td.col-tax { width: 90px; }
table.item-table td.col-sum { width: 100px; text-align: right; font-variant-numeric: tabular-nums; padding-top: 10px; color: var(--ink-2); font-weight: 600; }
table.item-table td.col-del { width: 36px; text-align: center; }
.item-del-btn {
  border: 0; background: none; color: var(--ink-4); cursor: pointer; font-size: 18px; line-height: 1;
  padding: 6px; border-radius: 6px;
}
.item-del-btn:hover { color: var(--warn-ink); background: var(--warn-soft); }
/* Am Desktop bleibt das Kreuz; das Wort gehoert zur Karte. */
.item-del-wort { display: none; }

/* ── Bearbeiten | Vorschau auf schmalen Geraeten (UI-Pilot A, Schritt 12) ────
   Am Desktop gibt es die Umschaltung nicht: dort steht die Vorschau daneben,
   und ein Schalter waere eine Entscheidung ueber etwas, das es nicht zu
   entscheiden gibt. */
.ansichtsumschalter { display: none; }

@media (max-width: 720px) {
  /* Er klebt oben, und das ist kein Schmuck.
     Der erste Entwurf setzte ihn an den Kartenanfang -- erreichbar nur, wenn
     man vorher 2400px nach oben scrollt. Im Test fiel das auf, weil der
     Treiber den Schalter ins Bild rollen musste, bevor er ihn treffen konnte;
     ein Mensch muss dasselbe tun. Ein Blick aufs Blatt darf nicht teurer sein
     als er wert ist. */
  .ansichtsumschalter {
    display: inline-flex;
    position: sticky;
    top: 8px;
    z-index: 19;
    margin: 0 0 16px;
    border: 1px solid var(--line-2);
    border-radius: 999px;
    padding: 3px;
    background: var(--white);
    box-shadow: 0 1px 6px rgba(15, 23, 42, .10);
  }
  /* Der klebende Schalter darf ein angesprungenes Feld nicht verdecken --
     dieselbe Regel wie fuer die Aktionsleiste unten (WCAG 2.2 SC 2.4.11). */
  html:has(.ansichtsumschalter) { scroll-padding-top: 64px; }
  .au-knopf {
    border: 0; background: none; cursor: pointer;
    /* WCAG 2.2 SC 2.5.8 nennt 24x24 als Untergrenze; fuer eine Umschaltung,
       die man mit dem Daumen trifft, sind 44px die brauchbare Groesse. */
    min-height: 40px; padding: 0 18px;
    border-radius: 999px;
    font: inherit; font-size: 14px; font-weight: 600; color: var(--ink-3);
  }
  /* Der gewaehlte Zustand haengt NICHT nur an der Farbe.
     In erzwungenen Farben ersetzt der Browser Hintergruende und entfernt
     Schatten; bliebe der Zustand allein farbig, waere er dort unsichtbar.
     Deshalb zusaetzlich eine Kontur, die auch dann erhalten bleibt. */
  .au-knopf[aria-pressed="true"] {
    background: var(--white); color: var(--ink);
    outline: 2px solid var(--blue); outline-offset: -2px;
  }
  @media (forced-colors: active) {
    .au-knopf[aria-pressed="true"] {
      outline: 3px solid Highlight;
      color: Highlight;
    }
  }

  /* Vorschaumodus: die Eingabe wird ausgeblendet, nicht entleert. Die Karte
     schrumpft dadurch auf Kopf und Aktionsleiste, und die Vorschau -- die im
     Raster ohnehin darunter liegt -- rueckt von selbst nach oben. Kein
     Verschieben im DOM, kein zweiter Zustand. */
  .tool-layout[data-ansicht="vorschau"] > .tool-card > *:not(.karten-kopf):not(.ansichtsumschalter):not(.tool-actions-haftend):not(#resultPanel) {
    display: none;
  }
  .tool-layout[data-ansicht="bearbeiten"] .invoice-preview { display: none; }

  /* Im Vorschaumodus schwebt der Schalter, statt zu kleben.
     `position: sticky` haelt nur, solange der eigene Elternblock im Bild ist --
     und der ist hier die Karte, die im Vorschaumodus auf wenige hundert Pixel
     schrumpft. Wer im A4-Blatt nach unten scrollt, verliert den Weg zurueck
     nach etwa einem halben Bildschirm. Gemessen in echtem Chrome auf 390px:
     der Schalter stand bei 318px und wanderte beim Scrollen mit heraus. */
  .tool-layout[data-ansicht="vorschau"] .ansichtsumschalter {
    position: fixed;
    /* UNTER der Kopfzeile. Die ist ebenfalls klebend und traegt `z-index: 40`;
       der erste Entwurf setzte den Schalter auf `top: 10px` und legte ihn damit
       darunter -- unsichtbar und nicht anklickbar. Aufgefallen ist es, weil
       `elementFromPoint` an seiner Mitte den Markennamen zurueckgab.
       Die Hoehe ist nicht konstant (die Navigation bricht je nach Breite um)
       und wird deshalb gemessen, nicht geschaetzt. */
    top: calc(var(--kopfhoehe, 64px) + 10px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 30;
    box-shadow: 0 2px 10px rgba(15, 23, 42, .18);
  }
  /* Der schwebende Schalter verdeckt sonst den Anfang des Blattes. */
  .tool-layout[data-ansicht="vorschau"] .invoice-preview { padding-top: 56px; }

}

/* ── Fehleruebersicht (UI-Pilot A, Schritt 9) ────────────────────────────────
   Der Rahmen ist kraeftig, weil er einen Abbruch meldet und nicht einen
   Hinweis. Die Farbe traegt die Aussage aber nicht allein: die Ueberschrift
   nennt die Zahl im Klartext, und jeder Eintrag ist ein Link -- auch wer
   Farben nicht unterscheidet, sieht eine Liste anklickbarer Saetze. */
.fehler-uebersicht {
  margin: 0 0 18px;
  padding: 14px 16px;
  border: 2px solid var(--warn-ink, #b91c1c);
  border-radius: var(--radius-md, 10px);
  background: var(--warn-soft, #fef2f2);
}
.fehler-uebersicht:focus-visible { outline: 3px solid var(--accent, #0f172a); outline-offset: 2px; }
.fehler-uebersicht .fu-titel { margin: 0 0 8px; font-size: 16px; color: var(--warn-ink, #b91c1c); }
.fehler-uebersicht .fu-liste { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.fehler-uebersicht .fu-liste a {
  color: var(--warn-ink, #b91c1c); font-weight: 600;
  /* Der Zielbereich muss auch mit dem Finger treffbar sein (WCAG 2.2 SC 2.5.8). */
  display: inline-block; padding: 4px 0; min-height: 24px;
}

/* Dieselbe Meldung noch einmal am Feld. Die Uebersicht sagt, WAS fehlt; hier
   steht sie dort, wo der Nutzer nach dem Sprung hinsieht. */
.feld-fehler {
  margin: 4px 0 0;
  font-size: 13px; font-weight: 600;
  color: var(--warn-ink, #b91c1c);
}
:where(input, select, textarea)[aria-invalid="true"] {
  border-color: var(--warn-ink, #b91c1c);
}

/* ── Positionen als Karten, wenn die SPALTE zu schmal wird (UI-Pilot A, 8) ───
   Die Tabelle traegt `min-width: 640px`. Auf 390px bedeutet das: waagerecht
   wischen, um den Preis zu sehen, den man gerade eingibt -- bei sechs Spalten
   und Feldern, die Geld tragen. Die Schattenkanten oben machen das Rollen
   sichtbar, aber sie machen es nicht gut.

   Massgeblich ist die Breite der SPALTE, nicht die des Fensters. Der erste
   Anlauf haengte die Umschaltung an eine Medienabfrage bei 720px -- und liess
   damit genau die Luecke offen, in der das Problem am unerwartetsten auftritt:
   auf 1024x768 gemessen, also einem gewoehnlichen Laptop, belegte der Editor
   559px und die Tabelle lief um 139px ueber. Waagerechtes Wischen auf einem
   Desktop, weil daneben eine Vorschau steht.

   Die Komponente lebt in wechselnden Spaltenbreiten (einspaltig mobil,
   zweispaltig am Desktop, kuenftig womoeglich in einem Panel) -- dafuer ist
   die Containerabfrage da.

   Container ist die KARTE, nicht der Tabellenrahmen: eine Containerabfrage
   gilt fuer die Nachkommen des Containers, nie fuer ihn selbst. Der Rahmen
   muss aber mit umschalten (der Scrollschatten verschwindet), also darf er
   nicht der Container sein.

   Die Schwelle liegt bei 680px. Eine Containerabfrage misst die INHALTSBOX,
   nicht die Randbox -- die Polsterung der Karte ist also schon abgezogen, und
   die Tabelle braucht 640px davon. Der erste Wert (720) war entsprechend zu
   hoch: bei 1280px Fenster hat die Karte 755px aussen und 715px innen, die
   Tabelle haette gepasst, und trotzdem standen dort Karten.

   Browser ohne `@container` behalten den Scrollrahmen. Der funktioniert und
   ist der Zustand von gestern -- eine stille Verschlechterung ist es nicht. */
.tool-card:has(.item-table-wrap) { container-type: inline-size; container-name: beleg; }

/* Aufgeloest wird nur die DARSTELLUNG. Dieselben Zellen, dieselben Klassen,
   derselbe Zustand -- `getItems()` liest weiterhin `.i-desc`/`.i-qty`/
   `.i-price`/`.i-tax` aus denselben Knoten. Eine zweite mobile Datenstruktur
   waere eine zweite fachliche Wahrheit ueber denselben Betrag.

   Die Tabellensemantik geht dabei verloren -- `display: block` nimmt einer
   Tabelle ihre Rolle im Accessibility-Baum. Das ist hier vertretbar und sogar
   besser: jedes Eingabefeld traegt ein eigenes `aria-label`, war also nie auf
   die Kopfzeile angewiesen. Die EINE Zelle ohne eigenes Label -- die Summe --
   bekommt ihren Namen sichtbar aus `data-spalte`.

   Die Nummer kommt aus einem CSS-Zaehler, nicht aus dem Markup. Beim Entfernen
   einer Zeile wird nicht neu nummeriert; eine mitgeschriebene Nummer waere
   nach dem ersten Loeschen falsch, eine gezaehlte ist es nie. */
@container beleg (max-width: 680px) {
  .item-table-wrap { overflow-x: visible; background: none; }
  table.item-table { min-width: 0; display: block; }
  table.item-table thead { display: none; }
  table.item-table tbody { display: block; counter-reset: position; }

  table.item-table tbody tr {
    display: grid;
    /* Zwei Spalten als Grundform. Drei nur, wo sie wirklich passen -- die
       Regel dafuer steht weiter unten in einer eigenen Containerabfrage. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 10px;
    counter-increment: position;
    border: 1px solid var(--line-2);
    border-radius: var(--radius-md, 10px);
    padding: 12px;
    margin-bottom: 12px;
    background: var(--white);
  }
  /* Die Kopfzeile der Karte traegt Nummer UND Summe -- das Ergebnis gehoert
     dorthin, wo man hinsieht, wenn man eine Position sucht. */
  table.item-table tbody tr::before {
    content: "Position " counter(position);
    grid-column: 1 / -1;
    align-self: center;
    font-size: 11.5px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--ink-4);
  }

  /* `min-width: 0` an JEDER Zelle, nicht nur an der Bezeichnung: ein
     Rasterkind traegt sonst `min-width: auto` und wird nie schmaler als sein
     Inhalt. Bei drei Spalten auf 320px lief die Karte dadurch um 29px ueber. */
  table.item-table td { display: block; padding: 0; width: auto; min-width: 0; }
  table.item-table td > input, table.item-table td > select { min-width: 0; }
  table.item-table td::before {
    content: attr(data-spalte);
    display: block; margin-bottom: 4px;
    font-size: 12px; font-weight: 700; color: var(--ink-2);
  }
  /* Die Karte ist hoeher als eine Tabellenzeile -- das ist der Preis dafuer,
     dass nichts mehr waagerecht weggeschoben wird. Sie soll aber nicht hoeher
     sein als noetig: gepaart wird, was zusammen gelesen wird.

       Bezeichnung        (ganze Breite)
       Menge | Einzelpreis   -- die Rechnung steht in einer Blickachse
       USt   | Summe         -- Satz und Ergebnis nebeneinander
       Entfernen             (am Ende, nicht neben dem Preis)

     Gemessen: eine Zeile weniger je Position. */
  table.item-table td.col-desc { grid-column: 1 / -1; min-width: 0; }
  /* Die Summe steht in der Kopfzeile rechts, nicht in einer eigenen Zeile. */
  /* Die Desktopregel setzt hier feste 100px. Als Rasterkind sprengte das die
     Spalte: gemessen 100px Inhalt in einer 57px breiten Spalte, 43px
     Ueberlauf. Eine Zahl aus dem Tabellenlayout hat im Kartenlayout nichts zu
     suchen. */
  table.item-table td.col-sum { width: auto; }
  table.item-table td.col-sum::before { display: none; }
  table.item-table td.col-del { grid-column: 1 / -1; }
  table.item-table td.col-qty,
  table.item-table td.col-price,
  table.item-table td.col-tax { width: auto; }

  table.item-table td.col-sum {
    font-size: 15px; font-weight: 700; color: var(--ink);
    align-self: center;
  }
  /* Die Eingabeflaechen bekommen Komfortgroesse. WCAG 2.2 SC 2.5.8 verlangt
     mindestens 24x24; fuer Felder, in die jemand Betraege tippt, sind 44px die
     Groesse, bei der man nicht danebengreift. */
  table.item-table input[type="text"],
  table.item-table input[type="number"],
  table.item-table select { min-height: 44px; font-size: 16px; }

  /* Entfernen wird eine benannte Aktion statt eines 18px grossen Kreuzes --
     und sie steht am Ende der Karte, nicht neben dem Preisfeld. */
  table.item-table td.col-del { text-align: left; }
  .item-del-btn {
    display: inline-flex; align-items: center; gap: 6px;
    min-height: 44px; padding: 8px 12px; font-size: 14px;
    color: var(--ink-3, var(--ink-4));
  }
  .item-del-wort { display: inline; }
}

/* Drei Spalten, sobald die Karte sie traegt (UI-Pilot A, Schritt 14).
   Gemessen mit zehn Positionen: zweispaltig 347px je Karte und 3578px fuer den
   ganzen Block, dreispaltig 270px und 2812px -- drei Viertel eines
   Bildschirms weniger. Unterhalb dieser Breite waeren die Spalten 57px breit;
   ein Betrag passt da nicht hinein, und die Karte wurde dadurch sogar
   HOEHER als zweispaltig. Deshalb eine Schwelle und kein `auto-fit`: die
   Aufteilung der Kopfzeile haengt an der Spaltenzahl und laesst sich nicht
   automatisch mitdrehen. */
@container beleg (min-width: 420px) and (max-width: 680px) {
  table.item-table tbody tr { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  /* Die Kopfzeile teilt sich jetzt mit der Summe: das Ergebnis steht dort,
     wo man hinsieht, wenn man eine Position sucht. */
  table.item-table tbody tr::before { grid-column: 1 / 3; }
  table.item-table td.col-sum {
    grid-column: 3; grid-row: 1;
    text-align: right; align-self: center;
    font-size: 15px; font-weight: 700; color: var(--ink);
  }
  table.item-table td.col-sum::before { display: none; }
}

.summary-box {
  margin: 18px 0 0; margin-left: auto; max-width: 340px;
  display: flex; flex-direction: column; gap: 6px;
}
.summary-row { display: flex; justify-content: space-between; font-size: 14px; color: var(--ink-2); }
.summary-row.total { font-size: 16px; font-weight: 700; color: var(--ink); border-top: 1px solid var(--line-2); padding-top: 8px; margin-top: 4px; }
.summary-note { font-size: 12px; color: var(--ink-4); margin-top: 2px; }

@media (max-width: 520px) {
  .tool-card { padding: 20px; }
  .summary-box { max-width: 100%; }
}

/* ── Formular + Live-Vorschau nebeneinander ──
   Container nutzt auf breiten Desktops mehr vom verfügbaren Platz (statt der pauschalen
   1080px aus .wide); vw-basiert, damit Fenstergröße/Auflösung/Browser-Zoom automatisch
   berücksichtigt werden (vw ist immer relativ zum aktuellen Viewport). Untergrenze 0 statt
   fixem px-Wert, damit auf schmalen/mobilen Viewports nichts erzwungen wird (max-width kappt
   nur nach oben, der Block schrumpft normal weiter). */
.tool-section { max-width: clamp(0px, 94vw, 1360px); }

.tool-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(340px, 30vw, 480px);
  gap: 24px;
  align-items: start;
  margin: 28px 0 40px;
}
.tool-layout .tool-card { margin: 0; }
/* Ein Grid-Kind traegt per Vorgabe `min-width: auto` und wird damit nie schmaler als sein
   min-content. Genau daran scheiterte die Positionstabelle: `.item-table-wrap` hat
   `overflow-x: auto`, aber ein Scrollrahmen, der selbst mitwaechst, scrollt nie -- die
   `min-width: 640px` der Tabelle wanderte durch `.tool-card` bis in die Spalte hinauf und die
   ganze Seite lief waagerecht ueber (gemessen 2026-09-03: documentElement.scrollWidth 713 bei
   375 px Viewport, 717 bei 500 px, auf Rechnungs- und Angebotsgenerator). Dieselbe Ursache
   trug auch die Rechnerseiten: `.form-grid` und `.slider-row` schoben ihr min-content nach
   oben durch (495 bzw. 415 px bei 375 px Viewport). Die Kinder duerfen schrumpfen; wer
   Ueberlauf hat, bekommt ihn dort, wo er hingehoert -- im eigenen Scrollrahmen. */
.tool-layout > * { min-width: 0; }
.invoice-preview { position: sticky; top: 84px; }
.preview-label-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 0 8px 2px; }
.preview-label {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-4);
}
.invoice-sheet {
  background: var(--line-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  aspect-ratio: 210 / 297;
  overflow: hidden;
}
.pdf-preview-embed { width: 100%; height: 100%; border: 0; display: block; }

.invoice-preview.is-zoomed {
  position: fixed; inset: 0; z-index: 80; margin: 0; max-width: none; width: 100vw; height: 100vh;
  background: rgba(15, 23, 42, .6);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  padding: 32px; overflow-y: auto;
}
.invoice-preview.is-zoomed .preview-label-row { width: min(92vw, 760px); }
.invoice-preview.is-zoomed .preview-label { color: var(--white); }
/* `flex: 0 0 auto` haelt das Seitenverhaeltnis: die vergroesserte Vorschau ist
   eine Flex-Spalte in einem bildschirmhohen Kasten, und ein Flex-Element gibt
   dort ohne diese Angabe nach -- gemessen 760 x 791 statt 760 x 1074, also ein
   Blatt, das kein A4 mehr ist. Gescrollt wird stattdessen (overflow-y oben). */
.invoice-preview.is-zoomed .invoice-sheet {
  width: min(92vw, 760px); aspect-ratio: 210 / 297; flex: 0 0 auto;
}
.invoice-preview.is-zoomed .ip-style-controls { width: min(92vw, 760px); }

.ip-style-controls { margin-top: 18px; display: flex; flex-direction: column; gap: 14px; }
.style-control-group { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; }
.style-control-label {
  font-size: 11px; font-weight: 700; color: var(--ink-4); text-transform: uppercase;
  letter-spacing: .04em;
}
.style-control-hint { font-size: 12px; color: var(--ink-4); margin: -4px 0 0; }
.color-swatches { display: flex; flex-wrap: wrap; gap: 10px; }
.color-swatch {
  width: 32px; height: 32px; padding: 0; border-radius: 50%; cursor: pointer;
  border: 2px solid var(--white); background: var(--sw); box-shadow: 0 0 0 1px var(--line-2);
}
.color-swatch.active { box-shadow: 0 0 0 1px var(--sw), 0 0 0 3px var(--white), 0 0 0 4px var(--ink-3); }
.segmented { display: inline-flex; flex-wrap: wrap; gap: 2px; padding: 2px; border: 1px solid var(--line-2); border-radius: 999px; }
.segmented-btn {
  border: 0; background: none; padding: 6px 14px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; color: var(--ink-3); cursor: pointer;
}
.segmented-btn.active { background: var(--blue); color: var(--white); }

/* ── Auswahl in erzwungenen Farben (UI-Pilot A, Schritt 13) ──────────────────
   In diesem Modus ersetzt der Browser Autorenfarben und entfernt `box-shadow`
   vollstaendig. Damit verschwand hier die gesamte Zustandsinformation: die
   gewaehlte Akzentfarbe zeigte sich NUR ueber einen Schattenring, der
   gewaehlte Schriftschnitt NUR ueber Hintergrund- und Textfarbe. Acht
   Farbknoepfe sahen danach gleich aus, und kein Knopf sagte, welcher gilt.

   Die Farbauswahl selbst laesst sich in diesem Modus nicht darstellen -- der
   Browser ueberschreibt ja gerade die Farbe, die zur Wahl steht. Was bleiben
   muss, ist die Aussage WELCHE gewaehlt ist: dafuer eine Kontur (die
   ueberlebt) und ein Haken (der keine Farbe braucht).

   `forced-color-adjust` wird bewusst NICHT gesetzt: die Nutzerpraeferenz
   bleibt gueltig, hier kommt nur hinzu, was sonst verlorenginge. */
@media (forced-colors: active) {
  .color-swatch { border: 1px solid CanvasText; }
  .color-swatch.active {
    outline: 3px solid Highlight;
    outline-offset: 2px;
  }
  .color-swatch.active::after {
    content: "✓";
    display: block; line-height: 28px; text-align: center;
    font-size: 16px; font-weight: 700; color: CanvasText;
  }
  .segmented-btn.active {
    outline: 2px solid Highlight;
    outline-offset: -2px;
    color: Highlight;
  }
}

@media (max-width: 900px) {
  /* `1fr` ist `minmax(auto, 1fr)`: die Spur waere nie schmaler als das min-content ihres
     Inhalts und wuechse ueber den Viewport hinaus, auch wenn das Kind selbst schrumpfen darf.
     `minmax(0, 1fr)` ist dieselbe Spalte ohne diese Untergrenze. */
  .tool-layout { grid-template-columns: minmax(0, 1fr); }
  .invoice-preview { position: static; max-width: 420px; }
  .av-preview-aside, .qrbill-aside { position: static; max-width: 640px; }
  .qb-title { font-size: 13px; }
  .qb-label { font-size: 9px; }
  .qb-value { font-size: 11px; }
}

/* Unterschrift-Zeichenfeld — Kanon aus kukanilea-mahnung/styles.css (byte-gleiche Regeln) */
.sig-field { margin-top: 18px; }
.sig-field-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
/* <span> statt <label>: ein <canvas> ist kein beschriftbares Formularelement,
   `for="sigCanvas"` war deshalb ein Fehler (Chrome: "Incorrect use of
   <label for=FORM_ELEMENT>"). Die Zuordnung laeuft jetzt ueber
   aria-labelledby am Canvas. */
.sig-field-head label,
.sig-field-head .sig-label { font-size: 14px; font-weight: 700; color: var(--ink-2, var(--ink)); }
.sig-field-hint { margin: 4px 0 8px; font-size: 12.5px; color: var(--ink-3, var(--muted)); }
.sig-canvas {
  display: block;
  width: 100%;
  height: 140px;
  border: 1.5px dashed var(--line-2, #cbd5e1);
  border-radius: 10px;
  background: #fff;
  cursor: crosshair;
  touch-action: none;
}

/* ── BusinessProfile / Kunden-Branding (Regel 19/20) — Klassen-Kanon aus
   kukanilea-servicebericht/styles.css (Pilot 1), Werte/Token identisch übernommen. ── */
.biz-logo-row { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.biz-logo-preview {
  width: 64px; height: 64px;
  border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  background: var(--paper);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.biz-logo-preview img { max-width: 100%; max-height: 100%; object-fit: contain; }
.biz-logo-preview[data-empty="true"]::after { content: "Logo"; font-size: 11px; color: var(--ink-4); }
.biz-profile-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.biz-profile-status { font-size: 12px; color: var(--ink-4); margin: 8px 0 0; }

/* ── MwSt-Rechner (migriert aus kukanilea-taschenrechner, 2026-07-17) ──
   Klassen mit mwst- Präfix skopiert, da .calc-field bereits mit anderer
   Bedeutung in rechnungsgenerator.html/angebotsgenerator.html existiert. */
.mwst-form { display: flex; flex-direction: column; gap: 16px; }
.mwst-form-row { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 14px 20px; }
.mwst-field { display: flex; flex-direction: column; gap: 6px; min-width: 140px; flex: 1 1 160px; }
.mwst-field label { font-size: 13px; font-weight: 600; color: var(--ink-2); }
.mwst-field input[type="number"], .mwst-field input[type="text"], .mwst-field select {
  padding: 10px 12px; border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  font-size: 15px; font-family: var(--font-sans); color: var(--ink); background: var(--white);
}
.mwst-toggle-group { display: flex; gap: 8px; flex-wrap: wrap; }
.mwst-toggle {
  padding: 8px 16px; border-radius: 999px; border: 1px solid var(--line-2);
  background: var(--white); color: var(--ink-3); font-size: 13px; font-weight: 600; cursor: pointer;
}
.mwst-toggle.is-active { background: var(--blue); color: var(--white); border-color: var(--blue); }
.mwst-hint { font-size: 13px; color: var(--ink-4); background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px 12px; }
.mwst-hint.is-warn { color: var(--warn-ink); background: var(--warn-soft); border-color: #f3cfa0; }

.mwst-output {
  margin-top: 4px; padding: 18px 20px; background: var(--blue-tint); border: 1px solid var(--blue-soft);
  border-radius: var(--radius); display: flex; flex-direction: column; gap: 4px;
}
.mwst-output .co-label { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--blue); }
.mwst-output .co-value { font-size: clamp(22px, 4vw, 30px); font-weight: 700; color: var(--blue-2); font-variant-numeric: tabular-nums; }
.mwst-output .co-sub { font-size: 13px; color: var(--ink-3); }

.legal-source { font-size: 12px; color: var(--ink-4); margin: 14px 0 0; }

/* ── Rechnungswerkstatt: Workspace-Schale (RECHNUNG-R1) ──
   Eigener ws- Präfix, damit die Schale die bestehenden Generator-Klassen
   nicht berührt. Nutzt ausschließlich die Tokens aus :root. */
.ws-layout {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0 24px;
  align-items: start;
}
.ws-bereich { margin-top: 14px; }
.ws-laedt { margin: 0; font-size: 14px; color: var(--ink-4); }

.ws-note {
  border: 1px solid var(--line);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  background: var(--paper);
  padding: 14px 16px;
  margin: 28px 0 0;
}
.ws-note strong { display: block; font-size: 15px; margin-bottom: 4px; }
.ws-note p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ink-3); }
.ws-note a { color: var(--blue); }

.ws-note-ausbau { border-color: var(--blue-soft); border-left-color: var(--blue); background: var(--blue-tint); }
.ws-note-ausbau strong { color: var(--blue-2); }

/* Eingeklappte Funktionsbeschreibung (s. Kommentar in werkstatt.html).
   Die Zusammenfassung traegt das Gewicht, das vorher das <strong> hatte --
   sie ist jetzt zusaetzlich ein Bedienelement und braucht deshalb eine
   Zielgroesse, die auch mit dem Finger zu treffen ist. */
details.ws-note-ausbau > summary {
  font-size: 15px;
  color: var(--blue-2);
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 10px;
}
/* Eigene Aufklapp-Markierung, weil `display: flex` den Standardmarker
   entfernt: Chrome zeichnet das ::marker eines <summary> nur, solange dessen
   display `list-item` ist. Ohne sie sah die Zusammenfassung im ersten Entwurf
   aus wie eine Ueberschrift -- niemand haette vermutet, dass sich dahinter
   noch Text befindet, und die Offenlegung waere zur Loeschung geworden. */
details.ws-note-ausbau > summary::marker,
details.ws-note-ausbau > summary::-webkit-details-marker { display: none; content: ""; }
details.ws-note-ausbau > summary::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  margin-left: 2px;
  transition: transform .15s ease;
}
details.ws-note-ausbau[open] > summary::before { transform: rotate(45deg); }
@media (prefers-reduced-motion: reduce) {
  details.ws-note-ausbau > summary::before { transition: none; }
}
details.ws-note-ausbau[open] > summary { margin-bottom: 10px; }
.ws-note-leer { margin: 0; border-left-color: var(--line-2); }
.ws-note-warn { margin: 0 0 14px; border-color: #f3cfa0; border-left-color: var(--warn-ink); background: var(--warn-soft); }
.ws-note-warn strong, .ws-note-warn p { color: var(--warn-ink); }
.ws-note-fehler { margin: 0; border-color: #f3cfa0; border-left-color: var(--warn-ink); background: var(--warn-soft); }
.ws-note-fehler p { color: var(--warn-ink); }

.ws-projektliste { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.ws-projekt {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px;
  border: 1px solid var(--line); border-radius: var(--radius-sm);
  background: var(--white); padding: 12px 14px;
}
.ws-projekt-name { font-weight: 600; font-size: 15px; }
.ws-projekt-zeit { font-size: 13px; color: var(--ink-4); }

.ws-speicher-zahlen { margin: 0 0 10px; font-size: 14px; line-height: 1.55; color: var(--ink-2); }
.ws-speicher-hinweis { margin: 0; font-size: 13px; line-height: 1.6; color: var(--ink-4); }

/* ── Rechnungswerkstatt: Projekte und Projektansicht (RECHNUNG-R1.2) ── */
.ws-projekt-leiste { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; margin: 0 0 14px; }

.ws-btn {
  appearance: none; cursor: pointer;
  font: inherit; font-size: 14px; font-weight: 600; line-height: 1.2;
  padding: 9px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-2); background: var(--white); color: var(--ink-2);
}
.ws-btn:hover { border-color: var(--blue-soft); background: var(--blue-tint); color: var(--blue-2); }
.ws-btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ws-btn-primaer { border-color: var(--blue); background: var(--blue); color: var(--white); }
.ws-btn-primaer:hover { border-color: var(--blue-2); background: var(--blue-2); color: var(--white); }
.ws-btn-still { font-weight: 500; color: var(--ink-3); }

.ws-projekt { flex-direction: column; align-items: stretch; gap: 8px; }
.ws-projekt-kopfzeile { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px; }
/* Bereichsnavigation der Werkstatt (s. Kommentar in werkstatt.html).
   Waagerecht scrollbar statt umbrechend: sechs Bereiche passen auf 320px
   nicht nebeneinander, und ein Umbruch in drei Zeilen kostet genau die
   Bildschirmhoehe, die diese Umstellung gewinnen soll. Das Scrollen bleibt
   INNERHALB der Leiste -- die Seite selbst scrollt nicht waagerecht. */
.ws-bereichsnav {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  scrollbar-width: thin;
  margin: 0 0 18px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--line);
}
.ws-navknopf {
  flex: 0 0 auto;
  min-height: 44px;
  padding: 0 14px;
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  font: inherit;
  font-weight: 600;
  font-size: 14px;
  color: var(--ink-3);
  cursor: pointer;
  white-space: nowrap;
}
.ws-navknopf:hover { color: var(--ink); }
.ws-navknopf[aria-current="page"] { color: var(--blue-2); border-bottom-color: var(--blue); }

.ws-projekt-aktionen { display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-start; }

/* Sekundaere Projektaktionen hinter einer Offenlegung (s. Kommentar in
   shell.js: renderProjekte). Natives <details>, damit Tastaturbedienung und
   Zustand vom Browser kommen statt aus eigenem ARIA-Code. */
.ws-mehr { position: relative; }
.ws-mehr > summary { list-style: none; cursor: pointer; user-select: none; min-width: 44px; text-align: center; }
.ws-mehr > summary::-webkit-details-marker { display: none; }
.ws-mehr > summary::marker { content: ""; }
.ws-mehr-fach {
  position: absolute;
  right: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  padding: 8px;
  min-width: 170px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--white);
  box-shadow: var(--shadow);
}
.ws-mehr-fach .ws-btn { width: 100%; text-align: left; }
/* Loeschen ist die einzige Aktion im Fach, die Arbeit vernichtet. Sie
   bekommt eine Trennlinie, damit sie nicht direkt neben "Umbenennen" liegt
   und versehentlich getroffen wird.

   Bewusst NUR im Fach: `.ws-btn-gefahr` gibt es schon (s. weiter unten, mit
   Warnfarbe und Rahmen) und traegt auch "Alle lokalen Daten loeschen" im
   Speicherbereich. Eine globale Regel unter demselben Namen haette jener
   Schaltflaeche stillschweigend einen Rahmen und Abstaende verpasst. */
.ws-mehr-fach .ws-btn-gefahr { margin-top: 4px; border-top: 1px solid var(--line); padding-top: 10px; }

/* Auf schmalen Geraeten ist ein absolut positioniertes Fach riskant -- es
   kann aus dem Bild ragen. Dort klappt es einfach im Fluss auf. */
@media (max-width: 480px) {
  .ws-mehr { width: 100%; }
  .ws-mehr-fach { position: static; min-width: 0; }
}

/* ── Rechnungswerkstatt: zuletzt bearbeitet und Duplikate (RECHNUNG-R1.3) ── */
.ws-projekt-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 12px; }
.ws-projekt-summe { font-size: 13px; color: var(--ink-4); font-variant-numeric: tabular-nums; }

/* ── Offene Posten in der Projektliste ────────────────────────────────────
   Der Status wurde seit R2.2-C berechnet, aber nie gezeigt. Farbe traegt hier
   keine Information allein: „Überfällig" steht als Wort in der Marke, die
   Faerbung verstaerkt es nur (WCAG 1.4.1). */
.ws-projekt-offen { font-size: 13px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.ws-projekt-offen.ist-ueberfaellig { color: var(--warn-ink); font-weight: 600; }
.ws-offene-posten {
  margin: 0 0 12px; font-size: 14px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.ws-offene-posten.ist-ueberfaellig { color: var(--warn-ink); }
.ws-badge-status { color: var(--ink-3); background: var(--paper); border-color: var(--line-2); }
.ws-badge-status[data-status="ueberfaellig"] { color: var(--warn-ink); background: var(--warn-soft); border-color: currentColor; }
.ws-badge-status[data-status="bezahlt"],
.ws-badge-status[data-status="ueberbezahlt"] { color: var(--green); border-color: currentColor; }
.ws-projekt-leiste .ws-speicher-hinweis { flex: 1 1 100%; }

.ws-projekt-kopf { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; margin: 0 0 4px; }
.ws-projekt-titel { margin: 0; font-size: 19px; line-height: 1.3; }
.ws-badge {
  font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--blue-2); background: var(--blue-tint); border: 1px solid var(--blue-soft);
  border-radius: 999px; padding: 3px 10px;
}
.ws-zurueck { flex: 0 0 auto; }

.ws-status { margin: 0; font-size: 14px; color: var(--ink-4); }
.ws-status[data-zustand="gespeichert"] { color: var(--green); }
.ws-status[data-zustand="fehler"] { color: var(--warn-ink); }

.ws-abschnitt { margin: 22px 0 10px; font-size: 15px; letter-spacing: .01em; }
.ws-gruppe:first-child .ws-abschnitt { margin-top: 14px; }
.ws-raster { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px 16px; }
.ws-feld { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.ws-feld label { font-size: 13px; font-weight: 600; color: var(--ink-3); }
.ws-feld input, .ws-feld select {
  font: inherit; font-size: 15px; width: 100%; min-width: 0;
  padding: 8px 10px; border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  background: var(--white); color: var(--ink);
}
.ws-feld input:focus-visible, .ws-feld select:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

.ws-leer { margin: 0 0 12px; font-size: 14px; color: var(--ink-4); }
.ws-tabelle { width: 100%; border-collapse: collapse; margin: 0 0 12px; }
.ws-tabelle th {
  text-align: left; font-size: 12px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-4); padding: 0 8px 6px 0; white-space: nowrap;
}
.ws-tabelle td { padding: 5px 8px 5px 0; vertical-align: top; }
.ws-tabelle tr > *:last-child { padding-right: 0; }
.ws-zahl { font-variant-numeric: tabular-nums; white-space: nowrap; padding-top: 14px; }

.ws-summenliste {
  display: grid; grid-template-columns: 1fr auto; gap: 4px 20px;
  margin: 14px 0 0; padding: 14px 0 0; border-top: 1px solid var(--line);
  font-size: 15px;
}
.ws-summenliste dt { color: var(--ink-3); }
.ws-summenliste dd { margin: 0; text-align: right; font-variant-numeric: tabular-nums; }
.ws-summenliste .ws-summe-gesamt { font-weight: 700; color: var(--ink); }

.ws-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ── Rechnungswerkstatt: Sicherung und Wiederherstellung (RECHNUNG-R1.4) ── */

/* Die Sicherung braucht die volle Breite: Dateiname, Zahlen und die
   Ersetzen-Erklärung stehen sonst in einer 300-px-Spalte übereinander. */
.ws-karte-breit { grid-column: 1 / -1; }

.ws-sicherung-block { margin: 0 0 18px; padding: 0 0 18px; border-bottom: 1px solid var(--line); }
.ws-sicherung-block:last-of-type { margin-bottom: 10px; }
.ws-sicherung-block > .ws-speicher-hinweis { margin-top: 8px; }

.ws-datei { max-width: 520px; }
.ws-datei input[type="file"] {
  font: inherit; font-size: 14px; width: 100%; min-width: 0;
  padding: 8px 10px; border: 1px dashed var(--line-2); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink-2);
}
.ws-datei input[type="file"]:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }

.ws-pruefung:empty { display: none; }
.ws-pruefung { margin: 14px 0 0; }
.ws-pruefung-inhalt {
  border: 1px solid var(--green-border); border-radius: var(--radius-sm);
  background: var(--green-soft); padding: 14px 16px;
}
.ws-pruefung-inhalt:focus-visible, .ws-note-fehler:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.ws-pruefung-inhalt .ws-abschnitt { margin-top: 0; }
/* Ein Dateiname kann beliebig lang sein und enthält keine Leerzeichen --
   ohne Umbruch im Wort schiebt er die Karte über den Viewport hinaus. */
.ws-pruefung-datei {
  margin: 0 0 10px; font-size: 13px; color: var(--ink-3);
  overflow-wrap: anywhere; word-break: break-word;
}
.ws-pruefung-fussnote { margin: 6px 0 0; font-size: 13px; }

.ws-kennzahlen {
  display: grid; grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  gap: 4px 16px; margin: 0 0 14px; font-size: 14px;
}
.ws-kennzahlen dt { color: var(--ink-3); }
.ws-kennzahlen dd { margin: 0; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

.ws-pruefung-wege { display: flex; flex-wrap: wrap; gap: 10px; }

.ws-ersetzen {
  margin: 16px 0 0; padding: 14px 0 0; border-top: 1px solid var(--green-border);
}
.ws-ersetzen-text { margin: 0 0 10px; font-size: 13px; line-height: 1.6; color: var(--warn-ink); }
.ws-ersetzen-bestaetigung { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 12px; }
.ws-ersetzen-bestaetigung input { margin: 3px 0 0; flex: 0 0 auto; }
.ws-ersetzen-bestaetigung label { font-size: 14px; line-height: 1.5; color: var(--ink-2); }

.ws-btn-gefahr { border-color: var(--warn-ink); color: var(--warn-ink); }
.ws-btn-gefahr:hover:not(:disabled) { border-color: var(--warn-ink); background: var(--warn-soft); color: var(--warn-ink); }
/* Abgeschaltet heißt sichtbar abgeschaltet, nicht bloß blass: der Rahmen
   bleibt, damit erkennbar ist, dass der Knopf existiert und wartet. */
.ws-btn:disabled { cursor: not-allowed; opacity: .55; background: var(--paper); }

.ws-status[data-art="gut"] { color: var(--green); }
.ws-status[data-art="fehler"] { color: var(--warn-ink); }
#ws-sicherung .ws-status { margin: 4px 0 0; overflow-wrap: anywhere; }

/* ── Rechnungswerkstatt: XRechnung öffnen (RECHNUNG-R2.3-B) ── */

.ws-liste { margin: 0 0 12px; padding-left: 20px; font-size: 14px; line-height: 1.6; }
.ws-liste li { margin: 0 0 4px; }

.ws-original-xml { margin: 16px 0 0; }
.ws-original-xml summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--ink-2); }
.ws-original-xml-inhalt {
  margin: 10px 0; padding: 10px 12px; max-height: 320px; overflow: auto;
  font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
  background: var(--paper); border: 1px solid var(--line-2); border-radius: var(--radius-sm);
}

/* ── Rechnungswerkstatt: Stammdaten, Vorlagen, PDF (RECHNUNG-R1.5) ── */

/* Reiterleiste. Gleichrangige Bereiche, immer genau einer sichtbar --
   kein Dialog, keine Akkordeons, kein zweiter Scrollbereich. */
.ws-reiterleiste {
  display: flex; flex-wrap: wrap; gap: 4px;
  margin: 0 0 16px; border-bottom: 1px solid var(--line);
}
.ws-reiter-knopf {
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  padding: 9px 14px; min-height: 40px;
  border: 1px solid transparent; border-bottom: none;
  border-radius: var(--radius-sm) var(--radius-sm) 0 0;
  background: none; color: var(--ink-3);
}
.ws-reiter-knopf:hover { color: var(--ink); background: var(--paper); }
.ws-reiter-knopf:focus-visible { outline: 2px solid var(--blue); outline-offset: -2px; }
/* Nicht nur die Farbe: der aktive Reiter trägt Rahmen und Grundlinie, damit er
   auch ohne Farbwahrnehmung als ausgewählt erkennbar ist. */
.ws-reiter-aktiv {
  color: var(--ink); background: var(--white);
  border-color: var(--line); margin-bottom: -1px;
  border-bottom: 1px solid var(--white);
}
.ws-reiterflaeche[hidden] { display: none; }

.ws-bereich-hinweis {
  margin: 0 0 14px; font-size: 13px; line-height: 1.6; color: var(--ink-3);
  max-width: 68ch;
}

/* Stammdatenlisten: Name links, Aktionen rechts, auf schmalen Geräten
   untereinander. Lange Namen brechen, statt die Karte zu verbreitern. */
.ws-stammliste, .ws-vorlagenliste { list-style: none; margin: 0 0 16px; padding: 0; }
.ws-stammzeile, .ws-vorlage {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  padding: 10px 0; border-bottom: 1px solid var(--line);
}
.ws-stamm-kopf { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; flex: 1 1 220px; }
.ws-stamm-name { font-weight: 600; overflow-wrap: anywhere; }
.ws-stamm-zusatz { font-size: 13px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.ws-vorlage { flex-direction: column; align-items: stretch; }
.ws-badge-still { background: var(--paper); color: var(--ink-3); border-color: var(--line-2); }

.ws-stammformular { margin-top: 8px; }
.ws-feld-breit { grid-column: 1 / -1; }
.ws-feld textarea {
  font: inherit; font-size: 15px; width: 100%; min-width: 0; resize: vertical;
  padding: 9px 11px; border: 1px solid var(--line-2); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink);
}
.ws-feld textarea:focus-visible { outline: 2px solid var(--blue); outline-offset: 1px; }
.ws-feld-kaestchen { display: flex; align-items: flex-start; gap: 8px; grid-column: 1 / -1; }
.ws-feld-kaestchen input { margin: 3px 0 0; flex: 0 0 auto; }
.ws-feld-kaestchen label { font-size: 14px; line-height: 1.5; color: var(--ink-2); }

/* Logo: die Vorschau bleibt klein und verschiebt nichts, egal wie groß das
   gewählte Bild ist. */
.ws-logo-vorschau { margin: 0 0 12px; }
.ws-logo-bild {
  display: block; max-width: 220px; max-height: 90px; width: auto; height: auto;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--paper);
  padding: 6px;
}
.ws-logo-groesse { margin: 6px 0 0; font-size: 13px; color: var(--ink-3); }

/* Nummernkreise: eine Tabelle, deren Felder sich mitverkleinern. */
.ws-nummerntabelle .ws-feld { margin: 0; }
.ws-nummerntabelle td { vertical-align: middle; }
.ws-nummern-art { font-weight: 600; white-space: nowrap; }

/* ── Projektansicht: bearbeiten links, Blatt rechts ──
   Dieselbe Aufteilung wie im Rechnungsgenerator (.tool-layout /
   .invoice-preview) und bewusst dieselben Klassen für Blatt, Zoom und
   Gestaltungsknöpfe — zwei Vorschauflächen, die verschieden aussehen, wären
   zwei Antworten auf dieselbe Frage. Neu ist nur die Schale drumherum, weil
   die Werkstatt in einer .tool-card statt in .tool-layout steckt. */
.ws-dok-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(300px, 30vw, 430px);
  gap: 24px;
  align-items: start;
  margin-top: 8px;
}
.ws-dok-editor { min-width: 0; }
.ws-dok-vorschau { min-width: 0; }
.ws-dok-vorschau .invoice-sheet { background: var(--white); }
/* Steht im Blatt, bis der erste Lauf fertig ist. Das <embed> kommt erst dann
   in den Baum — ohne `src` würde der Browser die leere Adresse laden, was die
   Content-Security-Policy dieses Shards (`object-src blob:`) verbietet. */
.ws-blatt-platzhalter {
  margin: 0; height: 100%; display: flex; align-items: center; justify-content: center;
  padding: 24px; text-align: center; font-size: 13px; color: var(--ink-4);
}
.ws-vorschau-stand {
  margin: 0; flex: 1 1 auto; font-size: 12.5px; color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}
.ws-vorschau-stand[data-art="fehler"] { color: var(--warn-ink); }
.ws-vorschau-hinweis { margin: 10px 0 0; }
.ws-vorschau-gross { flex: 0 0 auto; }
/* Die Kopfleiste der vergroesserten Ansicht startet unter der klebenden
   Seitenkopfzeile (z-index 40, die Ueberlagerung liegt mit 80 darueber, ist
   aber durchscheinend) -- sonst steht „Live-Vorschau" auf der Navigation. */
.ws-dok-vorschau.is-zoomed { padding-top: 84px; }
.ws-dok-vorschau.is-zoomed .ws-vorschau-stand { color: var(--white); }
.ws-dok-vorschau.is-zoomed .ws-vorschau-hinweis,
.ws-dok-vorschau.is-zoomed .ws-darstellung { display: none; }
.ws-darstellung .style-control-label:first-child { font-size: 12px; }

/* Auf Papier ist die Vorschauspalte ein leerer Rahmen: den eingebetteten
   PDF-Betrachter druckt die umgebende Seite nicht mit. Das gedruckte Dokument
   ist die gespeicherte Datei, nicht dieser Bildschirm — hier bleibt deshalb
   das Formular übrig, über die volle Breite. */
@media print {
  .ws-dok-layout { display: block; }
  .ws-dok-vorschau, .ws-ansicht-umschalter { display: none; }
}

/* Der Umschalter ist nur da, wo die Spalten untereinanderstehen. */
.ws-ansicht-umschalter { display: none; gap: 8px; margin: 12px 0 0; }
.ws-ansicht-knopf.ist-aktiv { background: var(--blue); border-color: var(--blue); color: var(--white); }

@media (max-width: 900px) {
  .ws-dok-layout { grid-template-columns: 1fr; }
  .ws-ansicht-umschalter { display: flex; }
  /* Entweder tippen oder schauen: ein A4-Blatt neben einem Formular auf 375
     Pixeln wäre für beides zu schmal. Das Blatt bekommt dann die volle
     Breite, `view=FitH` füllt sie aus. */
  .ws-dok-layout[data-ansicht="vorschau"] .ws-dok-editor { display: none; }
  .ws-dok-layout[data-ansicht="bearbeiten"] .ws-dok-vorschau { display: none; }
  .ws-dok-vorschau { position: static; max-width: none; }
}

/* Werkzeuge im Projekt: Übernahmen und Ausgabe, deutlich vom Formular
   abgesetzt, weil sie Daten von außen hereinholen. */
.ws-werkzeuge { background: var(--paper); border-radius: var(--radius-sm); padding: 14px 16px; }
.ws-uebernahme { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; }
.ws-uebernahme .ws-feld { flex: 1 1 200px; margin: 0; }
.ws-werkzeugknoepfe { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; grid-column: 1 / -1; }
.ws-werkzeugstatus { margin: 10px 0 0; grid-column: 1 / -1; overflow-wrap: anywhere; }

.ws-loeschbereich { margin-top: 18px; }
#ws-stammdaten .ws-status, #ws-vorlagen .ws-status { margin: 0 0 10px; overflow-wrap: anywhere; }

/* ── Rechnungswerkstatt: Dokumentarten und Kette (RECHNUNG-R2.1) ───────── */

/* Dokumentnummer in der Liste: neben dem Namen, in Ziffernbreite, damit
   untereinander stehende Nummern auch untereinander lesbar sind. */
.ws-projekt-nummer {
  font-size: 13px; color: var(--ink-3); font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.ws-projekt-herkunft { font-size: 13px; color: var(--ink-4); overflow-wrap: anywhere; }

/* Der Status steht in Wort und Form, nicht nur in Farbe: ein Entwurf traegt
   einen gestrichelten Rand, ein ausgestelltes Dokument einen durchgezogenen.
   Wer Farben nicht unterscheidet, sieht denselben Unterschied. */
.ws-status-marke {
  font-size: 12px; font-weight: 600; border-radius: 999px; padding: 2px 10px;
  border: 1px dashed var(--line-2); color: var(--ink-3); background: var(--paper);
}
.ws-status-marke[data-status="ausgestellt"] {
  border-style: solid; border-color: var(--ink-4); color: var(--ink-2);
}
/* Korrigiert und storniert kommen mit R2.2-A dazu -- wieder je eine eigene
   Form, nicht nur eine eigene Farbe. Korrigiert: doppelt so breiter Rand wie
   ausgestellt. Storniert: durchgestrichen, wie ein aufgehobener Beleg. */
.ws-status-marke[data-status="korrigiert"] {
  border-style: solid; border-width: 2px; border-color: var(--ink-4); color: var(--ink-2);
}
.ws-status-marke[data-status="storniert"] {
  border-style: solid; border-color: var(--ink-4); color: var(--ink-2);
  text-decoration: line-through;
}
/* Teilbezahlt, bezahlt und ueberbezahlt kommen mit R2.2-B dazu -- das Wort in
   der Marke traegt die Unterscheidung, Rand und Farbe sind nur Verstaerkung. */
.ws-status-marke[data-status="teilbezahlt"] {
  border-style: dotted; border-width: 2px; border-color: var(--ink-4); color: var(--ink-2);
}
.ws-status-marke[data-status="bezahlt"] {
  border-style: solid; border-color: var(--green-border); color: var(--green); background: var(--green-soft);
}
.ws-status-marke[data-status="ueberbezahlt"] {
  border-style: solid; border-width: 2px; border-color: var(--warn-ink); color: var(--warn-ink);
  background: var(--warn-soft);
}
/* Ueberfaellig kommt mit R2.2-C dazu -- dieselbe Warnfarbe wie ueberbezahlt
   (beides braucht Aufmerksamkeit), aber gestrichelt statt durchgezogen, damit
   beide Marken auch ohne Farbe auseinanderzuhalten sind. */
.ws-status-marke[data-status="ueberfaellig"] {
  border-style: dashed; border-width: 2px; border-color: var(--warn-ink); color: var(--warn-ink);
  background: var(--warn-soft);
}

/* ── Zahlungen (R2.2-B) ── */
.ws-zahlungsuebersicht .ws-ueberbezahlt { color: var(--warn-ink); }
.ws-zahlungsformular { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.ws-zahlungstabelle { margin-top: 10px; }

/* Auswahl der Dokumentart beim Anlegen -- neben dem Knopf, nicht darueber. */
.ws-neuwahl { margin: 0; flex: 0 1 240px; }
.ws-neuwahl label { font-size: 13px; }

/* Filter und Suche der Projektliste. */
.ws-projektfilter {
  display: flex; flex-wrap: wrap; gap: 8px 14px; align-items: flex-end;
  margin: 0 0 12px; padding: 0 0 12px; border-bottom: 1px solid var(--line);
}
.ws-projektfilter .ws-feld { margin: 0; flex: 1 1 200px; }
.ws-trefferzahl { margin: 0 0 10px; }

/* Herkunft und Folgedokumente. Bewusst eine schlichte Liste: die Kette ist
   eine Herkunft, kein Ablaufdiagramm. */
.ws-kette:empty { display: none; }
.ws-kette-herkunft { margin: 0 0 8px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.ws-kettenliste { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.ws-kettenpunkt { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.ws-kettenname { font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

/* Auswahl des Folgedokuments -- eine Auswahl und ein Knopf, keine neun. */
.ws-folgeblock { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 8px; grid-column: 1 / -1; }
.ws-folgeblock .ws-feld { flex: 1 1 200px; margin: 0; }

/* Auf schmalen Geräten steht die Positionstabelle als Kartenstapel --
   fünf Spalten mit Eingabefeldern passen nicht in 320 px. */
@media (max-width: 640px) {
  .ws-tabelle, .ws-tabelle tbody, .ws-tabelle tr, .ws-tabelle td { display: block; width: 100%; }
  /* Sichtbar gemacht braucht eine vorher nur vorgelesene Beschriftung auch
     die Erlaubnis umzubrechen: .ws-sr traegt white-space: nowrap, und
     „Nächste Nummer, Auftragsbestätigung" passt in einer Zeile in kein
     320-px-Gerät. */
  .ws-nummerntabelle .ws-feld label.ws-sr {
    position: static; width: auto; height: auto; margin: 0 0 4px; clip: auto;
    white-space: normal; overflow-wrap: anywhere;
  }
  .ws-nummern-art { white-space: normal; padding-top: 10px; }
  .ws-tabelle thead { display: none; }
  .ws-tabelle tr { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px 12px; margin: 0 0 10px; }
  .ws-tabelle td { padding: 4px 0; }
  .ws-tabelle .ws-sr {
    position: static; width: auto; height: auto; margin: 0; clip: auto; white-space: normal;
  }
  .ws-feld label.ws-sr {
    position: static; width: auto; height: auto; margin: 0; clip: auto; white-space: normal;
  }
  .ws-zahl { padding-top: 6px; text-align: right; }
}

/* ── Geteilte Rechner-Bausteine (Rechnungswerkstatt-Deeproutes) ──
   1:1 aus den Alt-Hosts (break-even/skonto/rabatt/...) uebernommen -- ein
   Baustein, von jeder Deeproute wiederverwendet statt je Seite dupliziert. */
/* `min-width: 0`, weil ein Feld fast immer als Raster-Kind steht (`.pp-form`, `.form-grid`)
   und dort per Vorgabe nie schmaler wird als sein Inhalt: gemessen 2026-09-03 stand auf
   „Mahnung erstellen" bei 320 px ein 280 px breites Eingabefeld in einer 219 px breiten
   Spalte. Die Spalte gibt die Breite vor, nicht das Feld. */
.form-field { display: flex; flex-direction: column; gap: 6px; margin: 0 0 20px; min-width: 0; }
.form-field label { font-size: 13px; font-weight: 600; color: var(--ink-2); }
.form-field input[type="text"], .form-field input[type="number"], .form-field input[type="date"], .form-field select {
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  font-size: 16px;
  font-family: var(--font-sans);
  color: var(--ink);
  background: var(--white);
  max-width: 280px;
  /* Ein Eingabefeld bringt eine eigene Wunschbreite mit (`size`-Vorgabe, hier gemessen
     201 px) und gibt sie ohne diese Zeile auch dann nicht auf, wenn daneben kein Platz mehr
     ist. In einer zweispaltigen `.form-grid` ergab das ein min-content von 422 px und damit
     einen waagerechten Ueberlauf auf jedem 375-px-Geraet. Die Felder sind ohnehin auf
     280 px gedeckelt und fuellen ihre Spalte -- eine Untergrenze brauchen sie nicht. */
  min-width: 0;
}
.form-field select { appearance: auto; cursor: pointer; }
.form-field input:focus, .form-field select:focus {
  outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-tint);
}
.form-field input:disabled { background: var(--paper); color: var(--ink-4); cursor: not-allowed; }

/* Mahnung erstellen: Empfaenger-Adresse (Mehrzeiler) + Logo-Upload -- 1:1 aus
   kukanilea-mahnung/styles.css uebernommen, hier ergaenzt statt dupliziert. */
.form-field textarea {
  border: 1px solid var(--line-2); border-radius: var(--radius-sm); padding: 10px 12px;
  font-size: 16px; font-family: var(--font-sans); color: var(--ink); background: var(--white);
  max-width: 280px; resize: vertical; min-height: 74px; line-height: 1.45;
}
.form-field textarea:focus { outline: none; border-color: var(--blue); box-shadow: 0 0 0 3px var(--blue-tint); }
.form-field input[type="file"] {
  font-size: 13px; color: var(--ink-3);
  border: 1px dashed var(--line-2); border-radius: var(--radius-sm);
  padding: 9px 12px; background: var(--white); cursor: pointer;
}
.vz-radio-group { display: flex; gap: 18px; margin-top: 4px; flex-wrap: wrap; }
.vz-radio-group label { display: flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 500; color: var(--ink-2); cursor: pointer; }

/* ── BusinessProfile erweiterte Felder / Rechtstext-Bausteine (Mahnung erstellen) ── */
.biz-advanced-fields { margin-top: 14px; }
.biz-advanced-fields summary { cursor: pointer; font-size: 13px; font-weight: 600; color: var(--blue); margin: 4px 0 10px; }
.legal-block-picker { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.legal-block-option { border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 10px 12px; }
.legal-block-option label { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; font-weight: 600; cursor: pointer; }
.legal-block-option input { margin-top: 3px; }
.legal-block-option p { margin: 4px 0 0 24px; font-size: 12.5px; color: var(--ink-3); }

.input-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px 20px;
  margin: 0 0 4px;
}

.warn-banner {
  margin: 18px 0 0;
  padding: 14px 16px;
  background: var(--red-soft);
  border: 1px solid #f0b9bf;
  border-radius: var(--radius);
  font-size: 14px; color: var(--red-ink);
}
.warn-banner strong { display: inline; }

.result-block { margin-top: 22px; }
.result-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
}
.stat {
  background: var(--blue-tint);
  border: 1px solid var(--blue-soft);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
}
.stat.is-primary { background: var(--blue); border-color: var(--blue-2); }
.stat.is-primary .stat-label { color: rgba(255,255,255,.75); }
.stat.is-primary .stat-value { color: var(--white); }
.stat-label { font-size: 12px; color: var(--ink-4); text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
.stat-value { font-size: 22px; font-weight: 700; color: var(--blue-2); margin-top: 4px; }
.stat-sub { font-size: 12.5px; color: var(--ink-4); margin-top: 2px; }

.safety-block { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--line); }
.safety-block .stat.is-positive { background: var(--green-soft); border-color: var(--green-border); }
.safety-block .stat.is-positive .stat-value { color: var(--green); }
.safety-block .stat.is-negative { background: var(--red-soft); border-color: #f0b9bf; }
.safety-block .stat.is-negative .stat-value { color: var(--red-ink); }
.safety-note { margin: 12px 0 0; font-size: 13.5px; color: var(--ink-3); }

.chart-wrap { margin-top: 22px; }
.chart-caption { margin: 0 0 8px; font-size: 12.5px; color: var(--ink-4); }
#beChart {
  display: block; width: 100%; height: auto;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.chart-legend { display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 10px; font-size: 12.5px; color: var(--ink-3); }
.legend-item { display: inline-flex; align-items: center; gap: 7px; }
.legend-swatch { width: 16px; height: 3px; display: inline-block; border-radius: 2px; }
.legend-swatch.is-kosten { background: var(--red-ink); }
.legend-swatch.is-erloes { background: var(--blue); }
.legend-swatch.is-be { width: 10px; height: 10px; border-radius: 50%; background: var(--green); }

.faq-list { display: flex; flex-direction: column; gap: 2px; }
.faq-item {
  border-top: 1px solid var(--line);
  padding: 4px 0;
}
.faq-item:first-child { border-top: none; }
.faq-item summary {
  cursor: pointer; font-weight: 700; font-size: 15px; padding: 12px 4px;
  list-style: none; display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; font-size: 20px; color: var(--blue); flex: none; }
.faq-item[open] summary::after { content: "–"; }
.faq-item p { margin: 0 4px 16px; font-size: 14.5px; color: var(--ink-3); }

.source-note { font-size: 12.5px; color: var(--ink-4); margin-top: 16px; }
.source-note a { color: var(--ink-4); text-decoration: underline; }

.brand-note {
  max-width: var(--maxw);
  margin: 18px auto 0;
  padding: 0 20px;
  font-size: 12px; color: var(--ink-4);
}
.brand-note a { color: var(--ink-4); text-decoration: underline; }

@media (max-width: 520px) {
  .tool-card { padding: 20px; }
}

/* ── Druckansicht (A4) -- fuer Rechner-Deeproutes ohne PDF-Export ──
   Das Blattformat stand bis zum 2026-09-03 nirgends: fuenf @media-print-Bloecke, aber weder
   `@page` noch eine einzige Umbruchregel (docs/webtools/document-output-standard.md,
   Abschnitt „Browserdruck"). Was der Browser druckte, hing damit an seiner Voreinstellung --
   in den USA Letter statt A4 --, und ein Ergebniskasten oder eine Tabellenzeile konnte
   mitten im Seitenwechsel auseinanderfallen.

   Betroffen sind die fuenf Seiten mit „Drucken"-Knopf (window.print(): Skonto, Rabatt,
   Break-even, Zahlungsziel, XRechnung-Ansicht) und jede Seite, die jemand von Hand druckt.
   Rechnung, Angebot und Mahnung leben davon nicht: dort ist das Dokument die erzeugte
   PDF-Datei, „Oeffnen & drucken" oeffnet sie in einem eigenen Tab, und dieses Stylesheet
   gilt dort gar nicht. */
@page {
  size: A4 portrait;
  margin: 18mm 16mm;
}
.print-footer-note { display: none; }

@media print {
  .site-header, .site-footer, .tool-actions, .privacy-note, .tool-kicker { display: none; }
  .faq-list { display: none; }
  .source-note { display: none; }
  .print-footer-note {
    display: block;
    margin-top: 18px;
    padding-top: 10px;
    border-top: 1px solid var(--line-2);
    font-size: 11px; color: var(--ink-4);
  }
  .brand-mark { opacity: 0.035; }

  /* Zusammenhaengendes bleibt zusammen. Eine Positionszeile, ein Summenblock oder ein
     Ergebniskasten, den der Seitenwechsel in der Mitte durchschneidet, ist auf Papier nicht
     mehr lesbar -- und beim Beleg, den jemand seiner Buchhaltung reicht, auch nicht mehr
     glaubwuerdig. `break-*` statt `page-break-*`: die alten Eigenschaften sind seit CSS
     Fragmentation Level 3 nur noch Legacy-Aliase. */
  table.item-table tr,
  .breakdown li,
  .chain-row,
  .pp-stat,
  .compare-col,
  .summary-box,
  .result-box,
  .sig-field { break-inside: avoid; }
  /* Eine Ueberschrift allein am Fussende traegt nichts. */
  h2, h3, .form-section-title, .preview-label { break-after: avoid; }
  /* Der Tabellenkopf wiederholt sich auf jeder Folgeseite, statt nur auf der ersten zu
     stehen -- sonst sind die Spalten ab Seite 2 unbeschriftet. */
  table.item-table thead { display: table-header-group; }
  table.item-table tfoot { display: table-footer-group; }
  /* Auf Papier gibt es kein Scrollen: der Rahmen darf nichts abschneiden, und die Tabelle
     braucht ihre 640-px-Untergrenze nicht mehr -- sie richtet sich nach dem Satzspiegel. */
  .item-table-wrap { overflow: visible; }
  table.item-table { min-width: 0; }
  /* Die Werte im Ergebniskasten sind farbig kodiert; ohne diese Zeile druckt der Browser sie
     nach eigenem Ermessen weiss. */
  .result-box, .pp-stat, .stat { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

/* ── Weitere geteilte Rechner-Bausteine (Wave A: break-even/rabatt/zahlungsziel) ── */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.custom-rate-row { display: flex; align-items: center; gap: 10px; max-width: 320px; }
.custom-rate-row input[type="number"] { max-width: 110px; }

.checkbox-field {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 0 0 20px;
  font-size: 14.5px; color: var(--ink-2);
}
.checkbox-field input[type="checkbox"] { margin-top: 3px; width: 17px; height: 17px; accent-color: var(--blue); cursor: pointer; }
.checkbox-field label { font-weight: 600; cursor: pointer; }
.checkbox-field .field-hint { display: block; font-weight: 400; margin-top: 2px; }

.chain-list { display: flex; flex-direction: column; gap: 10px; margin: 0 0 14px; }
.chain-row {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: 8px 10px;
}
.chain-row-index { font-size: 12.5px; font-weight: 700; color: var(--ink-4); min-width: 20px; }
.chain-row input[type="number"] { max-width: 120px; margin: 0; }
.chain-row-remove {
  margin-left: auto;
  border: none; background: transparent; color: var(--ink-4);
  font-size: 18px; line-height: 1; cursor: pointer; padding: 4px 8px; border-radius: var(--radius-sm);
}
.chain-row-remove:hover { color: var(--red-ink); background: var(--red-soft); }
.chain-row-remove:disabled { opacity: .3; cursor: not-allowed; }

.chain-steps-table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-sm); margin-top: 16px; }
.chain-steps-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.chain-steps-table caption { text-align: left; padding: 10px 12px; font-size: 12px; color: var(--ink-4); }
.chain-steps-table th, .chain-steps-table td { text-align: right; padding: 8px 12px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.chain-steps-table th:first-child, .chain-steps-table td:first-child { text-align: left; }
.chain-steps-table thead th { color: var(--ink-4); font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: .03em; background: var(--paper); }
.chain-steps-table tbody tr:last-child td { font-weight: 700; }
.chain-steps-table tbody tr:nth-child(even) { background: var(--paper); }

.compare-note {
  margin-top: 16px;
  padding: 12px 16px;
  background: var(--warn-soft);
  border: 1px solid #f3d3ab;
  border-radius: var(--radius-sm);
  font-size: 13.5px; color: var(--warn-ink);
}
.compare-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px;
  margin-top: 18px;
}
.compare-col {
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  padding: 16px 18px;
}
.compare-col h3 { margin: 0 0 4px; font-size: 15px; }
.compare-col p.compare-col-hint { margin: 0 0 14px; font-size: 12.5px; color: var(--ink-4); }
.compare-col .stat { margin-top: 12px; }
.compare-col .field-hint.equiv { margin-top: 6px; }

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px 20px;
}
/* Zwei Spalten mit je einem Eingabefeld brauchen zusammen mehr als ein Telefon breit ist.
   Dieselbe Grenze und dieselbe Loesung wie bei `.pp-form` (siehe unten) -- nur dass diese
   Tabelle sie bis zum 2026-09-03 nicht hatte und die Seite deshalb ueberlief. */
@media (max-width: 640px) {
  .form-grid { grid-template-columns: 1fr; }
}
.span-2 { grid-column: 1 / -1; }

.result-box {
  margin-top: 22px;
  padding: 20px;
  border: 1px solid var(--blue-soft);
  border-radius: var(--radius);
  background: var(--blue-tint);
}
/* Deutsche Komposita sind laenger als ein Telefon breit ist: „Kleinunternehmerregelung" misst
   bei 26 px 336 px und stand damit bei 375 px Viewport 107 px ueber seinem Ergebniskasten
   hinaus (gemessen 2026-09-03). Trennung zuerst -- `hyphens: auto` greift, weil die Seiten
   `lang="de"` tragen --, Umbruch im Wort nur als Rueckfallebene. */
.result-date {
  font-size: 26px; font-weight: 800; color: var(--blue-2); margin: 0 0 4px;
  hyphens: auto; overflow-wrap: break-word;
}
.result-weekday { font-size: 14px; color: var(--ink-3); margin: 0 0 14px; }

.breakdown { margin: 14px 0 0; padding: 0; list-style: none; }
.breakdown li {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 8px 0; border-top: 1px solid var(--line);
  font-size: 13.5px; color: var(--ink-2);
}
.breakdown li:first-child { border-top: none; }
.breakdown li b { color: var(--ink); }

.vz-result-summary {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
}
.vz-stat {
  background: var(--blue-tint);
  border: 1px solid var(--blue-soft);
  border-radius: var(--radius-sm);
  padding: 14px 16px;
}
.vz-stat-label { font-size: 12px; color: var(--ink-4); text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
.vz-stat-value { font-size: 22px; font-weight: 700; color: var(--blue-2); margin-top: 4px; }

.law-note {
  margin: 14px 0 0;
  padding: 12px 14px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 13px;
  color: var(--ink-3);
}

.print-only-footnote { display: none; }
@media print {
  body:has(#printArea) .site-header,
  body:has(#printArea) .tool-hero,
  body:has(#printArea) .site-footer,
  body:has(#printArea) .skip-link,
  body:has(#printArea) .tool-actions { display: none; }
  body:has(#printArea) main .tool-card { border: 0; box-shadow: none; }
  body:has(#printArea) main section:not(:has(#printArea)) { display: none; }
  body:has(#printArea) { background: #fff; }
  .print-only-footnote { display: block; margin-top: 16px; font-size: 11px; color: var(--ink-4); opacity: 0.035; text-align: right; }
}

/* ── Wave B (Skonto/Stundensatz/Kleinunternehmer): weitere 1:1 aus den Alt-Hosts
   uebernommene Rechner-Bausteine, die in Wave A noch nicht gebraucht wurden. ── */
.preset-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; margin: 0 0 18px; }
.preset-label { font-size: 12px; font-weight: 700; color: var(--ink-4); text-transform: uppercase; letter-spacing: .04em; }

.slider-row { display: flex; align-items: center; gap: 8px; }
/* Regler und Zahlenfeld brachten beide ihre eigene Wunschbreite mit (gemessen 133 px und
   201 px) und keines gab sie ab: das min-content der Zeile lag bei 342 px und drueckte jede
   Spalte auseinander, in der sie steht -- auf 375 px bis ueber den Bildschirmrand, auf dem
   Desktop 3,5 px in die Rasterluecke. Der Regler nimmt jetzt den verbleibenden Platz, das
   Zahlenfeld eine feste Breite, die auch fuenfstellige Betraege traegt. */
.slider-row input[type="range"] { flex: 1 1 0; min-width: 0; }
.slider-row input[type="number"] { flex: 0 0 110px; width: 110px; min-width: 0; }

.pp-form { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px 20px; margin-top: 20px; }
.pp-form .form-field { margin: 0; }
.form-field-wide { grid-column: 1 / -1; }
@media (max-width: 620px) { .pp-form { grid-template-columns: 1fr; } }

.pp-result { margin-top: 24px; }
.pp-result-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; margin-bottom: 20px; }
.pp-stat { background: var(--blue-tint); border: 1px solid var(--blue-soft); border-radius: var(--radius-sm); padding: 14px 16px; }
.pp-stat-label { font-size: 12px; color: var(--ink-4); text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
.pp-stat-value { font-size: 22px; font-weight: 700; color: var(--blue-2); margin-top: 4px; }
.pp-formula { font-size: 14px; color: var(--ink-2); margin: 0 0 8px; }
.pp-compare-text { font-size: 14px; color: var(--ink-2); font-weight: 600; margin: 0 0 16px; }
.pp-note { margin-top: 16px; font-size: 13px; color: var(--ink-3); }

.skonto-table { width: 100%; border-collapse: collapse; margin: 0 0 16px; font-size: 13.5px; }
.skonto-table th, .skonto-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left; }
.skonto-table th { color: var(--ink-3); font-weight: 600; border-bottom: 2px solid var(--line-2); }
.skonto-table tbody tr:last-child td { border-bottom: none; }

.result-shifted {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600; color: var(--warn-ink);
  background: var(--warn-soft); border-radius: 999px; padding: 4px 12px;
  margin-bottom: 14px;
}

.radio-option { display: flex; align-items: flex-start; gap: 8px; font-size: 14px; }
.radio-option input { margin-top: 3px; }
.radio-option span.hint { display: block; font-size: 12.5px; color: var(--ink-4); }
.form-field.is-disabled { opacity: .55; }

.disclosure-box summary { cursor: pointer; font-size: 14px; font-weight: 700; color: var(--blue-2); padding: 4px 0; }
.disclosure-box[open] summary { margin-bottom: 10px; }
.pp-note-list { margin: 0; padding-left: 20px; font-size: 13.5px; color: var(--ink-3); }
.pp-note-list li { margin: 0 0 8px; }
.pp-note-list li:last-child { margin-bottom: 0; }

/* Live-Vorschau-Aside-Varianten (eigener Klassenname je Alt-Host, gleiches Verhalten
   wie .invoice-preview oben) -- Skonto, Stundensatz, Kleinunternehmer, Mahnung. */
.pp-preview-aside, .stz-preview-aside, .ku-preview-aside, .mahn-preview-aside { position: sticky; top: 84px; }
.pp-sheet, .stz-sheet, .ku-sheet, .mahn-sheet {
  background: var(--line-2); border: 1px solid var(--line); border-radius: var(--radius-sm);
  box-shadow: var(--shadow); aspect-ratio: 210 / 297; overflow: hidden;
}
.pp-preview-aside.is-zoomed, .stz-preview-aside.is-zoomed, .ku-preview-aside.is-zoomed, .mahn-preview-aside.is-zoomed {
  position: fixed; inset: 0; z-index: 80; margin: 0; max-width: none; width: 100vw; height: 100vh;
  background: rgba(15, 23, 42, .6); display: flex; flex-direction: column; align-items: center;
  justify-content: flex-start; padding: 32px; overflow-y: auto;
}
.pp-preview-aside.is-zoomed .preview-label-row, .stz-preview-aside.is-zoomed .preview-label-row, .ku-preview-aside.is-zoomed .preview-label-row, .mahn-preview-aside.is-zoomed .preview-label-row { width: min(92vw, 700px); }
.pp-preview-aside.is-zoomed .preview-label, .stz-preview-aside.is-zoomed .preview-label, .ku-preview-aside.is-zoomed .preview-label, .mahn-preview-aside.is-zoomed .preview-label { color: var(--white); }
.pp-preview-aside.is-zoomed .pp-sheet { width: min(92vw, 700px); aspect-ratio: 210 / 297; }
.stz-preview-aside.is-zoomed .stz-sheet { width: min(92vw, 700px); aspect-ratio: 210 / 297; }
.ku-preview-aside.is-zoomed .ku-sheet { width: min(92vw, 700px); aspect-ratio: 210 / 297; }
.mahn-preview-aside.is-zoomed .mahn-sheet { width: min(92vw, 700px); aspect-ratio: 210 / 297; }
.pp-preview-aside.is-zoomed .ip-style-controls, .stz-preview-aside.is-zoomed .ip-style-controls, .ku-preview-aside.is-zoomed .ip-style-controls, .mahn-preview-aside.is-zoomed .ip-style-controls { width: min(92vw, 700px); }

@media (max-width: 900px) {
  .pp-preview-aside, .stz-preview-aside, .ku-preview-aside, .mahn-preview-aside { position: static; max-width: 420px; }
}

@media print {
  body:has(#printArea) .history-bar,
  body:has(#printArea) .history-panel,
  body:has(#printArea) .preset-bar,
  body:has(#printArea) .pp-preview-aside,
  body:has(#printArea) .stz-preview-aside,
  body:has(#printArea) .ku-preview-aside,
  body:has(#printArea) .mahn-preview-aside { display: none; }
  body:has(#printArea) .tool-card-stack .tool-card:not(#printArea) { display: none; }
}

/* ── Zahlungs-QR (EPC-QR/SEPA + Schweizer QR-Rechnung) — Kanon aus
   kukanilea-qr-rechnung/styles.css, Token-Namen an dieses Blatt angeglichen
   (--err-ink hier --red-ink). .tool-layout/.tool-section/.preview-label(-row)/
   .faq-list/.faq-item/.span-2/.radio-option sind oben bereits definiert. ── */
.tool-card-stack { display: flex; flex-direction: column; }
.tool-layout .tool-card-stack .tool-card { margin: 0 0 20px; }
.tool-layout .tool-card-stack .tool-card:last-child { margin-bottom: 0; }
.av-preview-aside { position: sticky; top: 84px; }

.field-hint { font-size: 13px; color: var(--ink-4); margin: 0; }
.field-status { font-size: 12.5px; margin: 2px 0 0; min-height: 1.2em; }
.field-status[data-state="ok"] { color: var(--green); }
.field-status[data-state="warn"] { color: var(--warn-ink); }
.field-status[data-state="error"] { color: var(--red-ink); }
.radio-row { display: flex; gap: 18px; flex-wrap: wrap; }

/* Die Schweizer QR-Rechnung ist Querformat (210 x 105mm, 2:1) -- braucht mehr
   Breite als eine A4-Hochformat-Vorschau, deshalb eigene, breitere Aside-Spalte. */
.qrbill-layout { grid-template-columns: minmax(0, 1fr) clamp(420px, 42vw, 620px); }
.qrbill-aside { position: sticky; top: 84px; }

.qrbill-sheet {
  display: flex; width: 100%; aspect-ratio: 210 / 105;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-sm);
  box-shadow: var(--shadow); overflow: hidden; font-family: var(--font-sans);
}
.qb-receipt { flex: 0 0 29.6%; padding: 3.2% 3.5%; display: flex; flex-direction: column; gap: 2.5%; min-width: 0; }
.qb-perforation {
  flex: 0 0 1px; background-image: linear-gradient(var(--line-2) 60%, transparent 0%);
  background-size: 1px 6px; background-repeat: repeat-y; position: relative;
}
.qb-payment { flex: 1 1 auto; padding: 3.2% 3.5%; min-width: 0; display: flex; flex-direction: column; }
.qb-title { font-weight: 700; font-size: clamp(9px, 1.6vw, 15px); margin: 0 0 6%; letter-spacing: .01em; }
.qb-label { font-size: clamp(5.5px, .95vw, 9px); font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-4); margin: 0; }
.qb-value { font-size: clamp(7px, 1.25vw, 11.5px); color: var(--ink); margin: 0 0 3%; word-break: break-word; }
.qb-mono { font-family: var(--font-mono); letter-spacing: .01em; }
.qb-amount-row { display: flex; gap: 8%; margin-top: auto; }
.qb-amount-row-payment { margin-top: 8%; }
.qb-annahme-label { margin-top: auto; }
.qb-annahme-box { border: 1px solid var(--line-2); border-radius: 4px; height: 14%; margin-top: 4%; }
.qb-payment-body { display: flex; gap: 5%; flex: 1; min-height: 0; }
.qb-qr-col { flex: 0 0 40%; display: flex; flex-direction: column; }
.qb-qr-canvas { width: 100%; height: auto; aspect-ratio: 1/1; image-rendering: pixelated; }
.qb-fields-col { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }

/* ── Hub-Tabs: EPC-QR (SEPA, neutral) / Schweizer QR-Rechnung ── */
.hub-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 18px 0 0; border-bottom: 1px solid var(--line); }
.hub-tab-btn {
  border: 0; background: none; padding: 10px 16px; margin-bottom: -1px;
  font-size: 14px; font-weight: 600; color: var(--ink-3); cursor: pointer; border-bottom: 2px solid transparent;
}
.hub-tab-btn:hover { color: var(--blue); }
.hub-tab-btn.active { color: var(--blue-2); border-bottom-color: var(--blue); }
.hub-panel { margin-top: 8px; }

/* ── EPC-QR-Vorschaukarte (schlichte Label/Wert-Liste statt Empfangsschein-Layout) ── */
.epc-preview-card { text-align: center; }
.epc-preview-card canvas { width: 100%; height: auto; max-width: 240px; margin: 0 auto 16px; display: block; }
.epc-pv-list { text-align: left; margin: 0; }
.epc-pv-list dt { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--ink-4); margin: 10px 0 2px; }
.epc-pv-list dt:first-child { margin-top: 0; }
.epc-pv-list dd { font-size: 13px; color: var(--ink); margin: 0; word-break: break-word; }

/* ── XRechnung oeffnen: Abgrenzung Viewer-vs-Validator (keine Konformitaets-Suggestion) ── */
.scope-note {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 14px 0 0; padding: 14px 16px;
  background: var(--warn-soft); border: 1px solid #f3d3ab; border-radius: var(--radius);
  font-size: 14px; color: var(--warn-ink);
}
.scope-note svg { flex: none; margin-top: 2px; }
.scope-note a { color: var(--warn-ink); font-weight: 700; }

/* ── Upload / Dropzone ── */
.dropzone {
  border: 2px dashed var(--line-2); border-radius: var(--radius);
  padding: 32px 20px; text-align: center; cursor: pointer; background: var(--paper);
}
.dropzone:hover, .dropzone.is-dragover { border-color: var(--blue); background: var(--blue-tint); }
.dropzone:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
.dropzone-icon { color: var(--blue); margin: 0 0 10px; }
.dropzone-text { font-size: 14.5px; color: var(--ink-2); font-weight: 600; margin: 0 0 4px; }
.dropzone-hint { font-size: 12.5px; color: var(--ink-4); margin: 0; }
.dropzone input[type="file"] { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }

.file-meta-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 16px; padding: 10px 14px;
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--paper);
  font-size: 13.5px; color: var(--ink-2);
}
.file-meta-name { font-weight: 700; word-break: break-all; }
.file-meta-size { color: var(--ink-4); font-size: 12.5px; }

/* ── XRechnung oeffnen: Ergebnis-Darstellung ── */
.invoice-summary { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px 24px; margin: 0 0 20px; }
.invoice-summary-block h3 { margin: 0 0 6px; font-size: 12px; color: var(--ink-4); text-transform: uppercase; letter-spacing: .04em; font-weight: 700; }
.invoice-summary-block p { margin: 0 0 2px; font-size: 14px; color: var(--ink-2); }
.invoice-summary-block .party-name { font-weight: 700; color: var(--ink); }

.invoice-meta-list { list-style: none; margin: 0; padding: 0; }
.invoice-meta-list li { display: flex; justify-content: space-between; gap: 12px; padding: 6px 0; border-top: 1px solid var(--line); font-size: 14px; }
.invoice-meta-list li:first-child { border-top: none; }
.invoice-meta-list li b { color: var(--ink); font-weight: 700; }

.invoice-table-wrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-sm); margin: 0 0 20px; }
.invoice-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.invoice-table th, .invoice-table td { text-align: right; padding: 9px 12px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.invoice-table th:first-child, .invoice-table td:first-child { text-align: left; white-space: normal; }
.invoice-table thead th { color: var(--ink-4); font-weight: 600; font-size: 11.5px; text-transform: uppercase; letter-spacing: .03em; background: var(--paper); }
.invoice-table tbody tr:nth-child(even) { background: var(--paper); }

.invoice-totals { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; margin: 0 0 4px; }
.invoice-totals-row { display: flex; justify-content: space-between; gap: 24px; width: 100%; max-width: 320px; font-size: 14px; color: var(--ink-2); }
.invoice-totals-row.is-grand { font-size: 17px; font-weight: 800; color: var(--blue-2); border-top: 1px solid var(--line-2); padding-top: 6px; margin-top: 2px; }

.pdf-preview-wrap {
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--white);
  padding: 12px; text-align: center; overflow: auto; max-height: 720px;
}
.pdf-preview-wrap canvas { max-width: 100%; height: auto; box-shadow: var(--shadow-sm); }
.pdf-preview-nav { display: flex; align-items: center; justify-content: center; gap: 12px; margin-top: 10px; font-size: 13.5px; color: var(--ink-3); }

.attachment-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 700; color: var(--green);
  background: var(--green-soft); border-radius: 999px; padding: 4px 12px; margin: 0 0 14px;
}
.attachment-badge.is-missing { color: var(--warn-ink); background: var(--warn-soft); }

.tech-details { margin: 20px 0 0; border-top: 1px solid var(--line); padding-top: 14px; }
.tech-details summary { cursor: pointer; font-weight: 700; font-size: 14px; color: var(--ink-2); }
.tech-list { list-style: none; margin: 12px 0 0; padding: 0; }
.tech-list li { display: flex; justify-content: space-between; gap: 12px; padding: 5px 0; border-top: 1px solid var(--line); font-size: 13px; }
.tech-list li:first-child { border-top: none; }
.tech-list li b { color: var(--ink); font-weight: 600; text-align: right; }
.raw-xml-box {
  margin: 14px 0 0; padding: 12px; max-height: 320px; overflow: auto;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: 12px; white-space: pre-wrap; word-break: break-all;
}

@media print {
  .dropzone, .pdf-preview-nav, .tech-details { display: none; }
  .invoice-table-wrap { border: none; overflow: visible; }
  .invoice-table { font-size: 11px; }
  .invoice-table th, .invoice-table td { padding: 4px 6px; }
  .pdf-preview-wrap { border: none; max-height: none; overflow: visible; }
}

/* KUK-VORLAGEN:ANFANG -- ERZEUGT, NICHT VON HAND AENDERN.
   Quelle: scripts/ops/sync_webtool_common.py */
.chip-group { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  border: 1px solid var(--line-2); background: var(--white); color: var(--ink-2);
  padding: 9px 16px; border-radius: 999px; font-size: 14px; font-weight: 600;
  cursor: pointer;
}
.chip:hover { border-color: var(--blue); color: var(--blue); }
.chip.active { background: var(--blue); border-color: var(--blue); color: var(--white); }
/* Fokus sichtbar halten: die Chips sind ein Tastaturweg, kein Mausweg. */
.chip:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
@media (prefers-contrast: more) {
  .chip.active { outline: 2px solid currentColor; outline-offset: -4px; }
}

/* Der Schritt nach dem Ergebnis. Bewusst ruhig gehalten: er steht neben einer
   Zahl, um die es dem Menschen geht, und darf sie nicht ueberstrahlen. */
.kk-next {
  margin-top: 18px; padding: 14px 16px;
  border: 1px solid var(--line-2); border-left: 3px solid var(--blue);
  border-radius: var(--radius-sm); background: var(--blue-tint);
}
.kk-next-title { margin: 0 0 6px; font-weight: 700; font-size: 14.5px; color: var(--ink-1); }
.kk-next-text { margin: 0 0 10px; font-size: 14.5px; line-height: 1.5; color: var(--ink-2); }
.kk-next-aktion { margin: 0 0 4px; font-size: 14px; }
.kk-next-aktion a { color: var(--blue); font-weight: 600; }
.kk-next-hinweis { color: var(--ink-3); font-weight: 400; }
.kk-next-quelle { margin: 10px 0 0; font-size: 12.5px; color: var(--ink-4); }
@media print { .kk-next { display: none; } }
/* KUK-VORLAGEN:ENDE */

/* KUK-ZIELGROESSEN:ANFANG -- ERZEUGT, NICHT VON HAND AENDERN.
   Quelle: scripts/ops/sync_webtool_common.py
   Zielgroessen fuer Pointer und Touch: WCAG 2.2 SC 2.5.8 verlangt 24x24,
   das Produktziel sind rund 44 Pixel fuer haeufig benutzte Schaltflaechen. */
.btn-sm,
.chip {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.vz-radio-group label,
.chip-group > label {
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* Die Vorlagenleiste auf schmalen Bildschirmen.
   Gemessen am 2026-09-16 auf `prozent` bei 390 Pixeln: die Leiste bricht auf
   vier Zeilen um und wird 200 Pixel hoch -- ein Viertel des Bildschirms, VOR
   dem ersten Eingabefeld. Das erste Feld begann dadurch erst nach 1,12
   Bildschirmhoehen; der Mensch musste scrollen, bevor er die Aufgabe
   ueberhaupt sah. Die Hoehe kommt nicht von der Schrift, sondern von der
   44-Pixel-Zielgroesse oben: sie multipliziert sich mit jeder Umbruchzeile.

   Zwei Varianten gemessen, bevor eine gebaut wurde:

       Ausgang           200 px    erstes Feld bei 1,12x
       eine Zeile         44 px    erstes Feld bei 0,93x
       Leiste ausgeblendet 0 px    erstes Feld bei 0,86x

   Das Ausblenden bringt 0,07 Bildschirme mehr und kostet die Vorlagen ganz.
   Eine Zeile bringt das Feld in den ersten Viewport und laesst sie stehen --
   fuer wiederkehrende Nutzer sind sie echte Beschleuniger, kein Beiwerk.

   Der Tastaturweg traegt ohne Zutun: die Knoepfe sind fokussierbar, und der
   Browser scrollt sie beim Tabben in den Blick (gemessen: 480 Pixel). Anders
   als bei den breiten Tabellen, deren Inhalt NICHT fokussierbar ist und die
   deshalb einen eigenen Tabstopp brauchten, waere hier ein Handler Ueberbau.

   Nur bis 600 Pixel. Wo Platz ist, bleiben die Vorlagen vollstaendig
   sichtbar -- dieselbe Funktion, andere Darstellung. */
@media (max-width: 600px) {
  .preset-bar { flex-wrap: nowrap; overflow-x: auto; }
  .preset-bar > * { flex: none; }
}

/* Die Fusszeilen-Navigation.
   Am 2026-09-16 ueber vier Archetypen gemessen: "Impressum", "Datenschutz"
   und "KUKANILEA Buerosoftware" sind 20 Pixel hoch bei `padding: 0`, und sie
   stehen untereinander so dicht, dass der 24-Pixel-Kreis des Erfolgs-
   kriteriums den Nachbarn beruehrt.
   Damit greift KEINE der beiden Ausnahmen von SC 2.5.8: Spacing nicht, weil
   die Kreise sich schneiden -- und Inline nicht, weil `nav.ft-links` eine
   Navigation ist und kein Satz. Der Kommentar oben nimmt Inline-Links im
   Fliesstext bewusst aus; diese hier sind keine.
   Drei Werkzeuge von vieren trugen den Befund, das vierte nur deshalb nicht,
   weil seine Fusszeile weiter auseinanderstand. Ein gemeinsamer Owner, ein
   Fix: vier Pixel Innenabstand machen aus 20 genau 24, ohne dass sich die
   Schrift oder das Bild der Seite aendert. */
.ft-links a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/* Waagerechtes Scrollen im Hauptweg.
   Ein Grid-Kind traegt von sich aus `min-width: auto` und kann deshalb nicht
   unter die Mindestbreite seines Inhalts schrumpfen. Eine einzige lange
   Auswahloption genuegt, um die ganze Spalte breiter zu machen als den
   Bildschirm -- gemessen am 2026-09-12 auf fristen.kukanilea.de: 421 Pixel
   Scrollbreite bei 390 Pixeln Viewport, verursacht von einem <select>, dessen
   breiteste Option 409 Pixel misst. `min-width: 0` gibt dem Kind das
   Schrumpfen zurueck; die Option bricht dann in der Liste um, statt die Seite
   zu verschieben. */
.tool-layout > *,
.tool-card-stack > *,
.form-grid > *,
.vz-form > *,
.pp-form > *,
/* Und das Kind selbst, statt jeden Container einzeln aufzuzaehlen.
   Am 2026-09-12 gemessen: acht Werkzeuge scrollten bei 390 Pixeln waagerecht,
   und jedes hatte seinen EIGENEN Grid-Container -- eg-form, es-form, gh-grid,
   kz-form, ab-grid. Das nicht schrumpfende Kind hiess aber ueberall gleich.
   Wer die Container aufzaehlt, vergisst den naechsten; wer das Kind nimmt,
   erwischt auch den, den es noch nicht gibt. */
.form-field,
/* Und dieselbe Lehre ein zweites Mal, an einem anderen Kind.
   Am 2026-09-16 scrollte fahrtenbuch.kukanilea.de bei 320 Pixeln waagerecht:
   drei `.tool-card` waren 363 Pixel breit und trugen `min-width: auto`. Die
   Regel darueber zaehlt Container auf -- `.tool-layout`, `.tool-card-stack`,
   `.form-grid` --, und der Grid-Container dieser Karten war keiner davon.
   Genau der Fall, den der Kommentar daneben vorhergesagt hat: wer die
   Container aufzaehlt, vergisst den naechsten. `.tool-card` ist die
   durchgehende Klasse in allen Werkzeugen. */
.tool-card {
  min-width: 0;
}

/* Ein Schieberegler in einer Flex-Zeile hat dasselbe Problem aus derselben
   Ursache. Auf kfz-steuer.kukanilea.de steht neben ihm ein Zahlenfeld, das
   auf schmalen Schirmen ABSICHTLICH breiter wird, damit es die 44 Pixel
   Zielmass erreicht -- der Regler daneben konnte aber nicht nachgeben und
   schob die Seite auf 400 Pixel. Beide Anforderungen vertragen sich, sobald
   der Regler schrumpfen darf. */
.slider-row input[type="range"] {
  min-width: 0;
}

/* Deutsche Komposita in Ueberschriften.
   "Weihnachtsgeld-/Urlaubsgeld-Rechner" bietet dem Browser keine
   Umbruchstelle: nach einem Bindestrich, auf den ein Schraegstrich folgt,
   wird nicht getrennt. Das Wort war 398 Pixel breit in einer 350 Pixel
   breiten Ueberschrift. Diese Regel greift nur, wenn ein Wort sonst gar
   nicht passt -- an vier Kontrollwerkzeugen gemessen blieb die Hoehe der
   Ueberschrift auf das Pixel gleich, und auch beim Anlassfall kam keine
   Zeile hinzu. */
h1, h2, h3 {
  overflow-wrap: break-word;
}

/* Kontrollkaestchen und Radiofelder.
   Gemessen am 2026-09-12 ueber 242 Werkzeuge bei 390 Pixeln Breite: 73 trugen
   Ziele unter 24 CSS-Pixeln, und 103 davon waren Kontrollkaestchen oder
   Radiofelder. Gezaehlt wurde bereits das GROESSTE Ziel -- Element,
   umschliessendes Label oder label[for] -- diese blieben trotzdem darunter.
   Ein Browser zeichnet sie von sich aus mit ungefaehr dreizehn Pixeln; auf
   dem Telefon ist das mit dem Daumen nicht sicher zu treffen. WCAG 2.2
   SC 2.5.8 nennt 24 x 24 als Untergrenze. */
input[type="checkbox"],
input[type="radio"] {
  min-width: 24px;
  min-height: 24px;
}

/* Und die uebrigen Bedienelemente auf dieselbe Untergrenze. In den meisten
   Werkzeugen sind sie ohnehin um die 39 Pixel hoch -- das hebt nur die
   Ausreisser, etwa die 21 Pixel hohen Felder des SEPA-Formulars. */
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="number"],
input[type="date"],
input[type="file"],
input[type="range"],
select,
textarea {
  min-height: 24px;
}

/* Das Dateifeld schiebt die Seite waagerecht, und zwar aus einem Grund, den
   man ihm nicht ansieht: ein `input[type="file"]` traegt `white-space: pre`.
   Seine Mindestbreite ist damit der Text "Datei auswaehlen | Keine
   ausgewaehlt", der nicht umbrechen darf -- rund 320 Pixel, unabhaengig davon,
   wieviel Platz da ist.
   Am 2026-09-16 auf fahrtenbuch.kukanilea.de gemessen: das Sicherungsfeld war
   321 Pixel breit in einem 320 Pixel breiten Fenster und schob das ganze
   Dokument auf 383 Pixel. Derselbe Fehler hatte kurz zuvor die PDF-Werkstatt
   getroffen; 95 index.html tragen Dateifelder.
   `min-width: 0` allein genuegt nicht -- die Mindestbreite kommt aus dem
   Inhalt, nicht aus der Eigenschaft. */
input[type="file"] {
  max-width: 100%;
  min-width: 0;
}

/* Aufklapper sind Bedienelemente, keine Ueberschriften.
   Am 2026-09-16 auf elterngeld.kukanilea.de bei 390 und 430 Pixeln gemessen:
   die FAQ-Zeilen waren 23 Pixel hoch -- einen Pixel unter der Grenze des
   WCAG 2.2 SC 2.5.8. Bei 320 und 360 Pixeln fiel es nicht auf, weil der Text
   dort umbricht und die Zeile dadurch hoeher wird; genau deshalb ist so ein
   Fehler ohne Messung an mehreren Breiten unsichtbar.
   Die Inline-Ausnahme des Erfolgskriteriums greift hier NICHT: ein <summary>
   ist ein eigenes Bedienelement, kein Verweis in einem Satz.
   Nur `min-height`, bewusst ohne `display: flex`: sobald `display` gesetzt
   wird, verschwindet die Aufklappmarkierung des Browsers -- und die zeichnen
   nicht alle Werkzeuge selbst nach. Fuer das Zielmass genuegt die Hoehe. */
summary {
  min-height: 24px;
}
/* KUK-ZIELGROESSEN:ENDE */

/* KUK-SHELL:CSS:ANFANG -- ERZEUGT, NICHT VON HAND AENDERN.
   Owner: scripts/ops/sync_webtool_shell.py

   `.tool-weiter` ist die kontextuelle Produktnavigation, die beim Umbau
   aus dem Footer geloest wurde. Sie sieht dem Footer bewusst aehnlich --
   sie steht an derselben Stelle der Seite --, ist aber ein eigener
   Bereich mit eigenem zugaenglichen Namen.

   Sie faellt weg, wenn sie leer ist: ein Werkzeug ohne verwandte
   Werkzeuge bekommt keine leere Leiste. */
/* EIN AUSWAHLFELD IST SO BREIT WIE SEINE LAENGSTE OPTION.
   Das ist Browservorgabe und kein Fehler des Werkzeugs: die
   intrinsische Mindestbreite eines `<select>` kommt aus dem laengsten
   Eintrag, und `min-width: auto` laesst es nicht darunter.

   Am 2026-09-22 ueber 186 Werkzeuge bei 320 CSS px gemessen. Es war
   die haeufigste Einzelursache fuer waagerechtes Seitenscrollen:
   "Windows-1252 / ANSI (ältere Excel-Exporte)" macht ein Feld 331 px
   breit, wo 238 zur Verfuegung stehen -- und die ganze Seite wird
   breiter als das Fenster. WCAG 1.4.10 verlangt 320 CSS px ohne
   zweidimensionales Scrollen; 320 px sind ausdruecklich auch der
   Zoomfall 400 % an einem 1280-px-Bildschirm, also kein Sonderfall
   fuer kleine Telefone.

   Dieselbe Falle steht in `.claude/rules/autonomer-maximum-modus.md`
   schon einmal beschrieben -- damals mit 409 px in einem 390 px
   breiten Bildschirm.

   `max-inline-size` statt `width`: die Felder behalten ihre gesetzte
   Breite, wo Platz ist, und geben nur nach, wenn es eng wird. Die
   Vorfahren brauchen `min-inline-size: 0`, weil ein Flex- oder
   Grid-Element sonst nicht unter seinen Inhalt schrumpft -- ohne das
   verschiebt die Regel den Ueberlauf nur eine Ebene nach oben. */
:where(select, input, textarea) {
  max-inline-size: 100%;
  min-inline-size: 0;
}
:where(.form-field, .option-field, .option-row, .field, .tool-card) {
  min-inline-size: 0;
}

/* UND EIN UNTEILBARES WORT HAELT EINE GANZE SEITE AUSEINANDER.
   `Einzelunternehmen/Personengesellschaft` hat keine Umbruchstelle --
   ein Schraegstrich ohne Leerzeichen ist keine. Der Chip wurde damit
   312 px breit in einer 219 px breiten Gruppe, obwohl sie laengst
   `flex-wrap: wrap` traegt: umbrechen kann nur, was sich teilen
   laesst. Gemessen an `gewerbesteuer`, dieselbe Bauform steht in 235
   Werkzeugen.

   `anywhere` und nicht `break-word`: nur `anywhere` senkt auch die
   INTRINSISCHE Mindestbreite, und genau die verhindert hier das
   Schrumpfen. `break-word` bricht erst beim Zeichnen und aendert an
   der Ueberlaufrechnung nichts.

   Beschraenkt auf Beschriftungen von Bedienelementen: im Fliesstext
   waere ein Umbruch mitten im Wort eine Verschlechterung, hier ist er
   die Alternative zu abgeschnittenem Text. */
:where(.chip, .check-tile, .sn-template-btn) {
  max-inline-size: 100%;
  overflow-wrap: anywhere;
}

/* EINE FLEXZEILE BRICHT NICHT VON ALLEIN UM.
   `display: flex` ohne `flex-wrap` ist `nowrap` -- die Vorgabe des
   Browsers, und in einer Zeile mit drei Auswahlknoepfen ist sie bei
   320 CSS px falsch. `.vz-radio-group` steht in 235 Werkzeugen und
   trug sie ueberall; aufgefallen ist es an `kuendigungsschreiben`
   (+40 px), `mahnung` (+3) und `impressum` (+33).

   Umgebrochen wird nur, wo es sonst nicht passt: solange Platz ist,
   aendert `wrap` nichts an der Darstellung. */
:where(.vz-radio-group, .checkbox-label, .chip-group, .seg-group,
       .diff-mode-group, .json-toolbar, .tool-actions) {
  flex-wrap: wrap;
}
/* Eine Beschriftung, die ein Bedienelement umschliesst, ist selbst ein
   Kasten und muss genauso nachgeben koennen. Bei `camt053-viewer` war
   sie 287 px breit in einem 238 px breiten Feld -- das Dateifeld darin
   bringt seine eigene Mindestbreite mit. */
label { max-inline-size: 100%; min-inline-size: 0; }

/* UND EIN LANGES WORT IM FLIESSTEXT RAGT EINFACH HERAUS.
   "(monatlich/vierteljährlich/befreit)" hat keine Umbruchstelle; der
   Listeneintrag blieb 179 px breit und sein Text lief 63 px darueber
   hinaus. Gemessen an `ust-voranmeldung`, `kuendigungsfrist-schweiz`
   und `buchfuehrungspflicht`.

   `break-word` und nicht `anywhere`: hier ist die Kastenbreite
   richtig, nur der Text passt nicht. `break-word` greift genau dann
   -- und laesst die Mindestbreitenrechnung in Ruhe, damit sich an
   Rastern und Flexzeilen nichts still verschiebt. */
body { overflow-wrap: break-word; }

.tool-weiter {
  border-top: 1px solid var(--line);
  padding: 20px 0 0;
  margin-top: 40px;
}
.tool-weiter + .site-footer { margin-top: 20px; }
.tool-weiter:empty { display: none; }
.weiter-row {
  display: flex; flex-wrap: wrap; gap: 10px 24px;
  align-items: baseline;
  font-size: 13px; color: var(--ink-4);
}

/* ── Volle Fensterbreite fuer Kopf und Fuss ──────────────────────────
   `.container` zentriert auf `--maxw` und setzt 20 px Rand. Fuer den
   Seiteninhalt ist das richtig -- eine Textspalte ueber 1600 px waere
   unlesbar. Fuer die Shell ist es falsch: eine App-Bar, die in der Mitte
   schwebt, sieht aus wie ein Seitenkopf, nicht wie die Leiste einer
   Anwendung. Auf 1440 px begann die Marke erst bei rund 300 px.

   Kopf und Fuss laufen deshalb ueber die volle Breite, und ihr Rand
   waechst stufenlos mit dem Fenster statt in Sprüngen: `clamp` geht von
   14 px auf schmalen Geraeten bis 48 px auf sehr breiten. Der Inhalt
   darunter behaelt seine zentrierte Spalte. */
.site-header > .container,
.site-header .header-lokal > .container,
.site-footer > .container,
.tool-weiter > .container {
  max-width: none;
  width: 100%;
  padding-inline: clamp(14px, 2.4vw, 48px);
}

/* ── App-Bar ─────────────────────────────────────────────────────────
   Eine Zeile, und sie bleibt eine Zeile. Der Werkzeugname darf kuerzen,
   die Marke nicht verschwinden, und der Knopf nicht umbrechen. */
.header-row { flex-wrap: nowrap; min-height: 56px; }
.brand { flex: 0 0 auto; }
/* DIE KOPFZEILE PASSTE BEI 320 PX NICHT INS FENSTER.
   Gemessen am 2026-09-22 an `rechnung` und `stundennachweis`:

     Marke 130 + Trenner 1 + Werkzeugname 64 + Knopf 106 = 301
     plus Abstaende -> rechte Kante bei 383, Fenster 320

   Die Seite scrollte also waagerecht -- und zwar die ganze Seite, nicht
   ein einzelnes Element (WCAG 1.4.10 verlangt 320 CSS px ohne
   zweidimensionales Scrollen). Nachgeben konnte niemand: die Marke steht
   auf `0 0 auto`, der Werkzeugname lag schon auf seiner Mindestbreite
   von 6ch, und der Knopf ist die einzige Bedienung im Kopf.

   Unterhalb von 400 px traegt die Bildmarke allein. Der Schriftzug ist
   dort die einzige Angabe, auf die verzichtet werden kann, ohne dass
   jemand etwas verliert: wo man ist, sagt der Werkzeugname daneben, und
   die Marke bleibt sichtbar. Das spart rund 98 px -- gemessen genug. */
@media (max-width: 400px) {
  .brand-text {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
}
.kuk-trenner {
  flex: 0 0 auto; width: 1px; height: 22px;
  background: currentColor; opacity: .25; margin: 0 4px;
}
/* Der Werkzeugname darf kuerzen, aber erst spaet: er ist die Antwort auf
   "wo bin ich". Deshalb `flex: 1 1 auto` erst NACH einer Mindestbreite --
   und keine Navigation mehr daneben, die ihn verdraengen koennte. */
.kuk-kontext {
  flex: 1 1 auto; min-width: 6ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  text-decoration: none; color: inherit; font-weight: 600;
}
.kuk-kontext:hover { text-decoration: underline; }
.header-actions { flex: 0 0 auto; }

/* Die lokale Ebene einer Werkstatt: eigene Zeile unter der App-Bar,
   nicht darin. Sie existiert nur, wo es sie gibt -- ein Rechner bekommt
   sie nicht. */
.header-lokal {
  border-top: 1px solid var(--line);
  background: var(--white, #fff);
}
.header-lokal .site-nav {
  display: flex; flex-wrap: wrap; gap: 4px 18px;
  padding: 8px 0; font-size: 14px;
}
.kuk-tools {
  font: inherit; font-size: 14px; font-weight: 600;
  color: inherit; background: transparent;
  border: 1px solid currentColor; border-radius: 8px;
  padding: 7px 14px; min-height: 40px; cursor: pointer;
}
.kuk-tools:hover { border-color: var(--blue); color: var(--blue); }
@media (pointer: coarse) { .kuk-tools { min-height: 44px; } }

/* Unterhalb des gemessenen Umbruchpunkts verlaesst die
   Werkstattnavigation den Kopf. Sie wird nicht versteckt -- `kuk-shell.js`
   verschiebt den echten Knoten in den Launcher. Diese Regel ist nur die
   Ruecklage fuer den Fall, dass kein JavaScript laeuft: dann bleibt sie
   sichtbar und bricht um. Ein umgebrochener Kopf ist haesslich; eine
   verschwundene Navigation waere ein Verlust. */
@media (max-width: 840px) {
  .header-lokal { display: none; }
}
.kuk-launcher .site-nav {
  display: flex; flex-direction: column; gap: 2px;
}

/* ── Launcher ────────────────────────────────────────────────────────
   Auf schmalen Breiten ein Blatt am unteren Rand -- dort ist der Daumen.
   Auf breiten ein Popover unter dem Knopf. Dieselbe Information, andere
   Komposition. */
.kuk-launcher {
  position: fixed; inset: 0; z-index: 60;
  background: rgba(16, 24, 32, .38);
  display: flex; align-items: flex-end; justify-content: center;
}
.kuk-launcher[hidden] { display: none; }
.kuk-launcher-blatt {
  width: 100%; max-height: 86vh; overflow-y: auto;
  background: var(--white, #fff);
  border-radius: 16px 16px 0 0;
  padding: 8px 18px 24px;
  box-shadow: 0 -8px 32px rgba(16, 24, 32, .18);
}
.kuk-launcher-kopf {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 0 4px;
}
.kuk-launcher-titel { font-weight: 700; }
.kuk-launcher-zu {
  font: inherit; font-size: 24px; line-height: 1;
  background: transparent; border: 0; cursor: pointer;
  min-width: 44px; min-height: 44px; color: inherit;
}
.kuk-launcher-bereich { padding: 8px 0; }
.kuk-launcher-bereich[hidden] { display: none; }
.kuk-launcher-label {
  margin: 0 0 6px; font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-4);
}
.kuk-launcher-ziel, .kuk-launcher .site-nav a {
  display: flex; align-items: center; gap: 11px;
  padding: 7px 0; min-height: 44px;
  text-decoration: none; color: inherit;
}
.kuk-launcher-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.kuk-launcher-ziel:hover, .kuk-launcher .site-nav a:hover {
  color: var(--blue);
}
.kuk-launcher-hinweis { font-size: 12px; color: var(--ink-4); }
/* DASSELBE GESICHT WIE IM STORE.
   Die Zeichnung und die beiden Kachelfarben kommen aus dem Suchindex
   von /webtools -- keine zweite Iconliste, kein zweiter Farbschluessel.
   Ein Werkzeug sieht hier aus wie dort. */
.kuk-kachel {
  display: grid; place-items: center; flex: none;
  width: 34px; height: 34px; border-radius: 28%; corner-shape: squircle;
  border: 1px solid rgba(255,255,255,.24); color: #fff;
  background: linear-gradient(145deg, var(--tile-light), var(--tile-dark));
  box-shadow: inset 0 1px 1px rgba(255,255,255,.35), 0 3px 8px rgba(20,50,60,.16);
}
.kuk-kachel svg { display: block; width: 74%; height: 74%; overflow: visible; }
/* Die kuratierten Marken tragen `stroke="currentColor"`, die
   semantischen Glyphen nicht -- ohne diese Zeile blieben sie
   unsichtbar auf der farbigen Kachel. Derselbe Fall wie im Store. */
.kuk-kachel svg:not([stroke]) { stroke: currentColor; fill: none; stroke-width: 1.7; }
.kuk-kachel .duo { fill: rgba(255,255,255,.22); stroke: none; }
.kuk-launcher-offen { overflow: hidden; }

@media (min-width: 841px) {
  /* Das Popover steht buendig unter dem Knopf -- also am selben
     fliessenden Rand wie die App-Bar darueber. */
  .kuk-launcher {
    background: transparent; inset: 0 0 auto auto;
    padding: 8px clamp(14px, 2.4vw, 48px) 0; justify-content: flex-end;
  }
  .kuk-launcher-blatt {
    width: min(360px, calc(100vw - 36px));
    border-radius: 12px; margin-top: 56px;
    border: 1px solid var(--line);
    box-shadow: 0 12px 32px rgba(16, 24, 32, .16);
  }
}

/* ── Der Kopf tritt beim Lesen zurueck ───────────────────────────────
   Nur auf schmalen Breiten: dort kostet ein dauerhaft klebender Kopf
   68 von 844 Pixeln, also acht Prozent der Hoehe, waehrend jemand
   arbeitet. Verschoben wird mit `transform` -- der Kopf bleibt im
   Fluss, und der Inhalt darunter springt nicht.

   `kuk-kopf-weg` setzt `kuk-shell.js`; ohne JavaScript bleibt der Kopf
   stehen, wie er es immer getan hat. */
@media (max-width: 840px) {
  .site-header { transition: transform .22s ease; will-change: transform; }
  .kuk-kopf-weg .site-header { transform: translateY(-100%); }
}
/* Wer Bewegung reduziert haben will, bekommt den Wechsel ohne Fahrt --
   aber er bekommt ihn: der Platzgewinn ist kein Effekt, sondern der
   Zweck. */
@media (prefers-reduced-motion: reduce) {
  .site-header { transition: none; }
}

/* Ein klebender Kopf verdeckt jedes Sprungziel.
   Der Skip-Link fuehrt zu `#main`, Inhaltsverzeichnisse fuehren zu
   Abschnitten -- landet das Ziel unter der App-Bar, ist der Fokus zwar
   gesetzt, aber nicht zu sehen. W3C nennt Scroll-Padding ausdruecklich
   als Technik dagegen. Der Wert deckt App-Bar und lokale Ebene ab. */
html { scroll-padding-top: 112px; }
@media (max-width: 840px) {
  html { scroll-padding-top: 76px; }
}

/* Der Skip-Link ist im Ruhezustand nicht zu sehen und im Tastaturfokus
   deutlich -- W3C G1. Er darf dabei nicht unter der App-Bar liegen. */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 70;
  background: var(--white, #fff); color: inherit;
  border: 2px solid currentColor; border-radius: 8px;
  padding: 10px 16px; text-decoration: none;
  transition: top .12s ease-out;
}
.skip-link:focus { top: 8px; }
@media (prefers-reduced-motion: reduce) {
  .skip-link { transition: none; }
}
/* Die Zielgroesse gilt, wo grob gezeigt wird -- hier stehen Links eng
   beieinander, und ein Fehlgriff fuehrt auf ein fremdes Werkzeug. */
@media (pointer: coarse) {
  .weiter-row .ft-links a,
  .site-footer .ft-links a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
}
/* KUK-SHELL:CSS:ENDE */

/* ── Rechnung erstellen (2026-09-26): Steuermodus, Exportleiste, lokale Daten ── */
.steuermodus { border: 0; margin: 0 0 16px; padding: 0; min-width: 0; }
.steuermodus-titel { font-size: 13px; font-weight: 700; color: var(--ink-3); margin-bottom: 6px; padding: 0; }
.steuermodus-wahl { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); gap: 8px; }
.steuermodus-wahl input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.steuermodus-wahl label {
  display: flex; flex-direction: column; gap: 2px; min-height: 52px; padding: 10px 14px; cursor: pointer;
  border: 1.5px solid var(--line-2); border-radius: var(--radius-sm); background: var(--white);
}
.steuermodus-wahl .sm-name { font-weight: 700; color: var(--ink); }
.steuermodus-wahl .sm-sub { font-size: 12.5px; color: var(--ink-3); }
.steuermodus-wahl input:checked + label { border-color: var(--blue); background: var(--blue-tint); box-shadow: inset 0 0 0 1px var(--blue); }
.steuermodus-wahl input:focus-visible + label { outline: 3px solid var(--blue-2); outline-offset: 2px; }
/* Kleinunternehmer: die USt-Spalte hat nichts zu sagen und tritt ab. */
.ku-aktiv .item-table th:nth-child(4), .ku-aktiv .item-table td:nth-child(4) { display: none; }

.export-mehr { position: relative; }
.export-mehr > summary { list-style: none; cursor: pointer; }
.export-mehr > summary::-webkit-details-marker { display: none; }
.export-mehr > summary::after { content: " ▾"; }
.export-mehr[open] > summary::after { content: " ▴"; }
.export-mehr-liste {
  position: absolute; bottom: calc(100% + 8px); left: 0; z-index: 30; min-width: 250px;
  display: flex; flex-direction: column; gap: 4px; padding: 8px;
  background: var(--white); border: 1px solid var(--line-2); border-radius: var(--radius-sm); box-shadow: var(--shadow);
}
.export-mehr-knopf { justify-content: flex-start; min-height: 44px; width: 100%; text-align: left; }
.export-mehr-knopf small { color: var(--ink-3); font-weight: 400; margin-left: 6px; }
.zf-status { margin: 8px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-3); }
.zf-status[data-stand="bereit"] { color: var(--green); }
.zf-status[data-stand="fehlt"] { color: var(--warn-ink); }

.lokal-hinweis { margin-top: 28px; padding: 16px 18px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--paper); }
.lokal-titel { margin: 0 0 6px; font-size: 15px; }
.lokal-text { margin: 0 0 10px; font-size: 13.5px; line-height: 1.55; color: var(--ink-3); }
.lokal-aktionen { display: flex; flex-wrap: wrap; gap: 8px; }
.lokal-aktionen .btn { min-height: 44px; }
.lokal-status { min-height: 1.2em; margin: 8px 0 0; font-size: 13px; }

/* Abschluss nach dem Export (rechnung-abschied.js) -- aus der Brief-Werkstatt. */
.kuk-abschied {
  width: min(520px, calc(100vw - 24px)); max-height: calc(100dvh - 24px);
  padding: 0; border: 1px solid var(--line-2); border-radius: 18px;
  background: var(--white); color: var(--ink); box-shadow: 0 25px 50px -12px rgba(15, 23, 42, .35);
}
.kuk-abschied::backdrop { background: rgba(15, 23, 42, .55); }
.kuk-abschied-innen { position: relative; padding: 30px 24px 24px; }
.kuk-abschied-zu {
  position: absolute; top: 8px; right: 8px; width: 44px; height: 44px; border: 0; border-radius: 50%;
  background: transparent; color: var(--ink-3); font-size: 26px; line-height: 1; cursor: pointer;
}
.kuk-abschied-zu:hover { background: var(--paper); color: var(--ink); }
.kuk-abschied-kopf { text-align: center; margin-bottom: 18px; }
.kuk-abschied-symbol {
  display: inline-flex; align-items: center; justify-content: center; width: 56px; height: 56px;
  border-radius: 50%; margin-bottom: 12px; background: var(--green-soft); color: var(--green);
}
.kuk-abschied-kopf h2 { margin: 0 0 6px; font-size: 21px; font-weight: 800; }
.kuk-abschied-kopf p { margin: 0; font-size: 14px; line-height: 1.55; color: var(--ink-3); }
.kuk-abschied-vorschau { display: inline-flex; align-items: center; min-height: 44px; margin-top: 6px; font-weight: 700; color: var(--blue-2); }
.kuk-teilen { background: var(--paper); border: 1px solid var(--line); border-radius: 14px; padding: 14px; margin-bottom: 18px; }
.kuk-teilen-titel { margin: 0 0 10px; font-size: 14px; font-weight: 700; color: var(--ink-2); }
.kuk-teilen-raster { display: grid; gap: 8px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 112px), 1fr)); }
.kuk-teilen-knopf {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px; min-height: 44px; padding: 8px 10px;
  border: 0; border-radius: 10px; font: inherit; font-size: 14px; font-weight: 700; color: #fff;
  text-decoration: none; cursor: pointer;
}
.kuk-teilen-knopf svg { flex: none; }
.kuk-teilen-whatsapp { background: #075e54; }
.kuk-teilen-linkedin { background: #0a66c2; }
.kuk-teilen-mail { background: #334155; }
.kuk-teilen-link { background: var(--blue); }
.kuk-teilen-knopf:hover { filter: brightness(1.12); }
.kuk-teilen-status { min-height: 1.3em; margin: 10px 0 0; font-size: 13px; color: var(--green); }
.kuk-teilen-status:empty { min-height: 0; margin: 0; }
.kuk-abschied-aktionen { display: flex; flex-direction: column; gap: 10px; }
.kuk-abschied-aktionen .btn { width: 100%; min-height: 48px; justify-content: center; text-align: center; }
.kuk-abschied-zweit { background: var(--white); color: var(--ink-2); border: 1px solid var(--line-2); }
.kuk-abschied-zu:focus-visible, .kuk-teilen-knopf:focus-visible, .kuk-abschied .btn:focus-visible,
.kuk-abschied-vorschau:focus-visible { outline: 3px solid var(--blue-2); outline-offset: 2px; }
.kv-sr { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media print { .kuk-abschied { display: none !important; } }
@media (max-width: 560px) {
  .tool-actions-haftend #docxBtn, .tool-actions-haftend .export-mehr { flex: 0 0 auto; }
  .export-mehr-liste { left: auto; right: 0; min-width: min(250px, calc(100vw - 24px)); }
}
