/* main.css – einzige Wahrheit für Farben, Typografie, Seitenstruktur
   (frontend.md Sektion 3, ADR 79). Hell-only zum Launch. */

/* Figtree variable, self-hosted (OFL, s. static/fonts/OFL.txt) – Gewichte 400/600,
   800 ausschließlich in der Logo-Zeichnung. Kein externer Font-Request (DSGVO). */
@font-face {
  font-family: "Figtree";
  src: url("../fonts/Figtree-Variable.202cfb54d4e6.woff2") format("woff2-variations");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Neutrale (warm, „Stein/Sand") */
  --surface-page: #FAF8F5;
  --surface-card: #FFFFFF;
  --surface-section: #F0EBE3;
  --surface-filter: #F5F1EA;
  --text-primary: #26221E;
  --text-secondary: #5C554D;
  /* A59/ADR 313: von #8A8378 auf #6F6960 gezogen - der alte Wert riss
     4,5:1 auf JEDEM Grund (3,16-3,75) und traegt echten Text an elf
     Stellen, u. a. im geteilten Positions-Baustein und der
     Nachrichtenzeile. Neuer Wert: 4,58 (Sektion) bis 5,43 (Karte). */
  --text-muted: #6F6960;
  --border: #E4DED4;
  --border-strong: #D9D2C7;
  --border-input: #B7AFA3;
  /* Feld-Rahmen AUF getoenten Flaechen (Tableview-Kopf-Zone, ADR-123-
     Nachtrag): --border-input haelt auf --surface-filter nur 1,93:1 -
     eigener Token (Wert = Grau der text-muted-Stufe, bewusst ENTKOPPELT
     wie die state-Tokens, damit Gate/Rebranding ihn eigenstaendig
     justieren; 3,33:1 auf filter - im Kontrast-Gate) */
  --border-input-tinted: #8A8378;
  --row-alt: #FAF8F5;
  --neutral-badge-bg: #E8E4DC;
  --neutral-badge-text: #444441;
  /* Lageplan-Zustandsflaechen (A69/ADR 323, Variante B: Muster UND
     Helligkeit, nicht allein Farbe - Graustufen-/Farbfehlsichtigkeits-
     tauglich). EIN Pflegeort: Plan-Rects, Schraffur-Pattern (defs im
     Lageplan-Baustein) UND Legenden-Chips konsumieren diese Tokens.
     Vermietet-Ton seit A70 (ADR-323-Nachtrag, Prod-Sichtung: #998D7A
     dominierte bei 11 belegten Kacheln die Flaeche): der Hover-/Aktiv-Ton
     der Tarif-Kacheln (--surface-filter) - die frei/vermietet-Trennung
     tragen Rahmen + Ton, die reserviert/vermietet-Trennung traegt die
     SCHRAFFUR. Kennung auf vermietet: text-primary, 14,0:1. */
  --plan-free: #FFFFFF;
  --plan-hatch: #8A8378;
  --plan-rented: var(--surface-filter);

  /* Orange (Logo-Familie, Rebranding 24.07.) – NUR Handlung, ZWEI Stufen:
     --accent = Flächen/Markierungen OHNE Text (UI-Schwelle 3:1),
     --accent-strong = Text und text-tragende Füllungen (Schwelle 4,5:1 –
     Wert vom Kontrast-Gate justiert, Start #B24E10 riss 4,44:1 auf section) */
  /* Marken-Akzent - bleibt unveraendert (A59/ADR 313): er traegt an 14
     von 15 Stellen KEINEN Text, sondern Rahmen, Flaechen und Outlines.
     Als UI-Komponentenfarbe gilt 3:1, und das haelt er auf allen
     Gruenden (3,12-3,70). Die EINE Textverwendung ist auf
     --accent-strong umgestellt, statt die Marke global zu verschieben. */
  --accent: #D5641C;
  --accent-strong: #AC4B0F;
  --focus-ring: #26221E; /* EIN neutraler Fokus (Zustands-Standard): nie rot/grün/Orange */

  /* Mindestgrößen-Gesetz (ADR 136): DIE eine Definition der Bedienelement-
     Mindestmaße – Feld-Basis, Buttons und Varianten zitieren die Tokens
     (Wache test_control_minimum_sizes); einzige dokumentierte Ausnahme
     ist die Tableview-Filterstufe (ADR-123-Nachtrag). */
  --control-font-min: 1rem; /* 16 px – verhindert auch den iOS-Fokus-Zoom */
  --control-height-min: 2.75rem; /* 44-px-Touch-Ziel */
  --accent-badge-bg: #F9E4D4;
  --accent-badge-text: #7C360B;
  --accent-hover: #8F3E0D;

  /* Blau (Logo-Familie, Rebranding 24.07., ersetzt Seegrün) – Elde/See-
     Zweitstimme: Links, Info-Badges, Welle */
  --sea: #0C5F95;
  --sea-badge-bg: #DCE9F3;
  --sea-badge-text: #0A4A75;
  --sea-light: #7FB3D5; /* nur dekorativ (Welle) */

  /* Zustandsfarben der Formulare – UNVERÄNDERTE Werte (Rebranding-Entscheid:
     Rot/Grün bleiben stehen); vormals Aliasse auf --accent-strong/--sea,
     als eigene Tokens entkoppelt, damit das Rebranding sie nicht mitzieht */
  --state-error: #9A3412;
  --state-error-bg: #F6E3D7;
  --state-error-text: #7C2D12;
  --state-success: #0F766E;
  --state-success-bg: #D8EEE9;
  --state-success-text: #0B4F49;

  /* Amber – Hinweis-Status, Strom-Symbolik */
  --amber-badge-bg: #FAEEDA;
  --amber-badge-text: #633806;
  --amber-icon: #BA7517;

  /* Overlay-Standard (ADR 114): Bedienelemente AUF Bildern stehen IMMER auf
     eigener Kontrastflaeche - halbtransparentes Stein-Schwarz (#26221E).
     Deckkraft 0.55 statt 0.45: das Gate rechnet den Worst-Case ueber
     Reinweiss (Komposit #888583) - Weiss haelt dort 3,67:1 (0.45 risse
     2,74:1); Hover 0.7 (Komposit #676462, 5,87:1) */
  --overlay-scrim: rgba(38, 34, 30, 0.55);
  --overlay-scrim-hover: rgba(38, 34, 30, 0.7);
}

/* [data-theme="dark"] { }
   Dunkelmodus ist dokumentierte Nachrüst-Option (ADR 79): Token-Architektur
   unverändert, später eine Wertedatei an diesem Hook – kein Toggle zum Launch. */

/* Basis */
* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.5;
  color: var(--text-primary);
  background: var(--surface-page);
}

h1 { font-size: 1.75rem; font-weight: 600; }
h2 { font-size: 1.375rem; font-weight: 600; }
h3 { font-size: 1.125rem; font-weight: 600; }

a { color: var(--sea); }
@media (hover: hover) {
  /* globaler Link-Hover NIE auf Buttons UND NIE auf Filter-Chips: auf
     Anker-Buttons faerbte er die Schrift auf den Hover-Fuellton (Schrift
     unsichtbar); dasselbe traf die gewaehlten Filter-Chips der Tableview
     (Runde-2-Nachbefund "rot auf rot": a:not(.button):hover schlug
     .filter-chip:hover per Spezifitaet und setzte accent-hover-Schrift
     AUF accent-hover-Flaeche) - Komponenten mit eigener Hover-Flaeche
     behalten ihre Komponenten-Farben */
  a:not(.button):not(.filter-chip):hover { color: var(--accent-hover); }
}

/* Hover-Standard (frontend.md Abschnitt 9): NUR Interaktives hovert – dezente
   Token-Anhebung ohne Layout-Verschiebung; :focus-within zieht als
   gleichwertiges Feedback zusätzlich zum neutralen Fokusring mit */
.interactive { cursor: pointer; transition: border-color 140ms ease-out, box-shadow 140ms ease-out, background-color 140ms ease-out; }
/* Hover NUR auf echten Hover-Geräten – iOS konsumiert sonst den ersten Tap (Mobile-Standard) */
@media (hover: hover) {
  .interactive:hover { border-color: var(--border-strong); background: var(--surface-filter); box-shadow: 0 1px 4px rgb(0 0 0 / 0.08); }
  /* FAQ-Karte: Hover nur auf der Klickfläche (Füllton) + dezente Anhebung */
  .faq-group summary:hover { background: var(--surface-filter); }
  .board-message-chip:hover { background: var(--surface-filter); }
  summary.board-message-head:hover { background: var(--surface-filter); }
  .faq-group details:has(> summary:hover) { box-shadow: 0 1px 4px rgb(0 0 0 / 0.08); }
  /* Pfeil-Link-Hover (Regel-18-Ausnahme, ADR 102): Unterstreichung + Pfeil-Schub;
     der Schub NUR ohne reduced-motion (verschachtelte Query - :hover bleibt
     im (hover: hover)-Block, Mobile-Wache) */
  .arrow-link:hover { text-decoration: underline; }
  @media (prefers-reduced-motion: no-preference) {
    .arrow-link:hover svg { transform: translateX(2px); }
  }
  .site-plan a:hover g:not(.spot-selected) rect { stroke: var(--border-strong); }
  .site-plan a:hover .spot-free rect { fill: var(--surface-filter); }
}
/* Tastatur-Feedback geräteunabhängig; Touch bekommt :active statt Hover */
.interactive:focus-within { border-color: var(--border-strong); background: var(--surface-filter); box-shadow: 0 1px 4px rgb(0 0 0 / 0.08); }
.interactive:active { border-color: var(--border-strong); background: var(--surface-filter); }
.site-plan a:active g:not(.spot-selected) rect { stroke: var(--border-strong); }
a, button { -webkit-tap-highlight-color: rgb(213 100 28 / 0.12); } /* Orange --accent, dezent */
@media (prefers-reduced-motion: reduce) {
  .interactive, .site-plan rect { transition: none; }
  .arrow-link svg { transition: none; }
  .faq-group summary::after, summary.board-message-head::after { transition: none; } /* Chevron dreht ohne Bewegung */
  .village-carousel { scroll-behavior: auto; } /* Carousel springt statt gleitet (ADR 108) */
  /* Spinner-Standard (ADR 115): statisches Icon mit Puls-Opacity statt Drehung */
  .brand-spinner svg { animation: brand-pulse 1.5s ease-in-out infinite; }
}

/* Skip-Link: erstes fokussierbares Element – unsichtbar bis Fokus (frontend.md Abschnitt 9) */
.skip-link { position: absolute; left: -9999px; top: 0; z-index: 10; background: var(--surface-card); color: var(--text-primary); padding: 0.5rem 1rem; border: 1px solid var(--border-strong); border-radius: 0 0 6px 0; }
.skip-link:focus { left: 0; }

/* Fokus: sichtbar, EIN neutrales Token überall (WCAG 2.2 – Fokus nie verdeckt);
   der Ring überlagert Zustandsfarben (outline getrennt von border) */
:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}

/* Board-Tabellen: Ziffern in Tabellenläufen bündig (frontend.md Typografie) */
.tabular-nums { font-variant-numeric: tabular-nums; }

/* Header-Muster: Logo 40 px links (Stufe B 27.07.2026, vorher 32 px; davor 26 px) · Linkgruppe · "Mein Konto" rechts; mobil Burger statt Linkzeile (revidiert PR 38); Board behaelt die Linkzeile bis zur Board-Etappe */
/* Layout-Grundsatz (ADR 112): EIN zentrierter Inhalts-Container fuer Header,
   Main und Footer - die Baender bleiben vollbreit (Hintergrund + Hairline),
   ihr INHALT buendelt sich auf derselben Kante wie der Seiteninhalt. Dies ist
   die EINZIGE Breiten-/Seitenpadding-Definition (Grep-Wache T-DSN-057). */
.content-container { max-width: 60rem; margin: 0 auto; padding-left: 1.5rem; padding-right: 1.5rem; }
/* Vollbreiten-Utility (hero-full-bleed 27.07.2026, ADR-112-Nachtrag;
   wiederverwendbares Muster fuer kuenftige vollbreite Sektionen): zieht eine
   Sektion INNERHALB des content-containers auf die volle Viewport-Breite -
   die FLAECHE randlos, ihr INHALT buendelt sich per verschachteltem
   content-container auf der Inhalts-Kante. 50vw rechnet die Scrollbar mit
   (100vw-Falle, sonst Querscroll um die Scrollbar-Breite): den ueberstehenden
   halben Streifen schluckt overflow-x: clip am html - clip statt hidden
   (kein neuer Scroll-Container, Anker-Sprungziele unberuehrt). */
/* scrollbar-gutter: stable (Fix Logo-Sprung 27.07.2026): der Platz der
   vertikalen Scrollleiste ist IMMER reserviert - Seiten mit und ohne
   Scrollleiste zentrieren identisch, Logo/Inhalt springen beim Seitenwechsel
   nicht mehr (vorher 7,5 px bei klassischer Scrollbar). Evergreen-Baseline;
   ohne Support gilt der bisherige Zustand (kein Schaden). Beide Regeln
   bewusst am selben html-Element - clip schluckt den full-bleed-Ueberstand,
   stable haelt die Zentrierung scrollbar-unabhaengig. */
html { overflow-x: clip; scrollbar-gutter: stable; }
.full-bleed { margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
/* Unzertrennlich-Utility (A78): haelt zusammengehoerige Kurz-Einheiten wie
   die H1-Preisangabe "ab X Eur*" in EINER Zeile - der Umbruch rueckt vor
   die Einheit (Hurenkind-Fix der EK-Sichtung 01.09., 390px) */
.nowrap { white-space: nowrap; }
.site-header {
  display: flex;
  flex-wrap: wrap; /* Board/Fallback; die Website schaltet mobil auf Burger + Drawer */
  align-items: center;
  gap: 0.75rem 1.5rem;
  padding: 0.875rem 0; /* horizontal uebernimmt der content-container (ADR 112); vertikal Stufe B (vorher 0.75rem) */
  background: var(--surface-card);
  border-bottom: 1px solid var(--border); /* Hairline, keine Akzentlinie (ADR 79) */
  /* Kopf-Typo Stufe B: EINE Stufen-Definition fuer Nav-Links, Dropdown-Eintraege
     und "Mein Konto" (Bestand-Stufe 1.0625rem = 17 px, vorher Basis-1rem);
     die Icons folgen proportional ueber ihre em-Breiten, Buttons (Board)
     behalten ihre Komponenten-Groesse */
  font-size: 1.0625rem;
}
/* Board-Kopf entfaellt seit dem Sidebar-Layout (ADR 124) - die Website
   behaelt den site-header, das Board rendert die board-shell */
/* Innerer Header-Container: uebernimmt die Flex-Zeile des Bandes */
.site-header-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.5rem; width: 100%; }
/* Logo-Einbau Stufe B: 40 px (vorher 32 px), Breite folgt der viewBox
   (width:auto stellt das Seitenverhaeltnis sicher). EINE Groessen-Definition
   fuer Website-Header, Login-Koepfe, Board-Kopf UND die Styleguide-Demo
   (kombinierte Selektoren statt Zweit-Definition - Paritaet per Struktur) */
.site-header .logo img, .site-header .logo svg, .logo-demo svg { display: block; height: 40px; width: auto; }
.site-header nav { display: flex; flex-wrap: wrap; gap: 0.5rem 1rem; }
.site-header nav a { color: var(--text-primary); text-decoration: none; }
.site-header nav a[aria-current="page"] {
  color: var(--accent-strong);
  border-bottom: 2px solid var(--accent);
}
.site-header .header-right { margin-left: auto; }
.nav-account { color: var(--sea); display: inline-flex; align-items: center; gap: 0.375rem; text-decoration: none; font-weight: 600; }
.nav-account svg { width: 1.25em; height: 1.25em; }

/* Desktop-Dropdown "Container und Tarife" (Betreiber-Entscheid 20./21.07.;
   revidiert ADR 109): der Ausloeser ist ein ECHTER LINK auf /container/privat
   (Klick/Enter navigieren, Hover/Pfeil-runter oeffnen das Dropdown, erster
   Touch-Tap oeffnet - nav.js); ohne JS oeffnet CSS per hover/focus-within
   (html ohne js-nav) und der Klick navigiert. Die Karte ist die EINZIGE
   Schwebe-Flaeche der Website - dokumentierte Schatten-Ausnahme. */
.nav-dropdown { position: relative; display: inline-block; }
.nav-dropdown-trigger { background: none; border: 0; padding: 0; font: inherit; color: var(--text-primary); cursor: pointer; }
.nav-dropdown-trigger.nav-trigger-active { color: var(--accent-strong); border-bottom: 2px solid var(--accent); }
.nav-dropdown-menu { display: none; position: absolute; top: 100%; left: 0; margin: 0.5rem 0 0; padding: 0.25rem; list-style: none; background: var(--surface-card); border: 1px solid var(--border); border-radius: 8px; box-shadow: 0 4px 16px rgb(0 0 0 / 0.10); min-width: 13rem; z-index: 40; }
.nav-dropdown.open .nav-dropdown-menu { display: block; }
html:not(.js-nav) .nav-dropdown:focus-within .nav-dropdown-menu { display: block; }
.nav-dropdown-menu a { display: flex; align-items: center; gap: 0.5rem; padding: 0.625rem 0.75rem; border-radius: 6px; color: var(--text-primary); text-decoration: none; white-space: nowrap; }
@media (hover: hover) {
  /* No-JS-Fallback: CSS oeffnet per Hover (mit JS steuert die Insel inkl.
     Absichts-Verzoegerung; focus-within-Fallback oben ist hover-unabhaengig) */
  html:not(.js-nav) .nav-dropdown:hover .nav-dropdown-menu { display: block; }
  .nav-dropdown-menu a:hover { background: var(--surface-filter); }
}
/* lt. Draft: Toenung + Haekchen - KEINE geerbte Header-Unterstreichung */
.site-header .nav-dropdown-menu a[aria-current="page"] { background: var(--surface-filter); color: var(--accent-strong); border-bottom: 0; }
.nav-dropdown-menu a svg { width: 1em; height: 1em; }

/* Konto-Menue (O7, ADR 223): zweites Dropdown am rechten Rand - die Karte
   klappt buendig zur rechten Kante (DIESELBE dokumentierte Schwebe-Flaeche
   wie das Tarif-Dropdown, keine neue Schatten-Sprache); der Abmelden-
   Eintrag ist ein POST-Formular im Menue-Eintrags-Kleid (EINE Optik je
   Eintrag, die POST-Semantik bleibt) */
.nav-dropdown-account .nav-dropdown-menu { left: auto; right: 0; }
.nav-dropdown-account form { margin: 0; }
.nav-dropdown-menu button { display: flex; width: 100%; align-items: center; gap: 0.5rem; padding: 0.625rem 0.75rem; border-radius: 6px; border: 0; background: none; font: inherit; color: var(--text-primary); cursor: pointer; white-space: nowrap; text-align: left; }
@media (hover: hover) {
  .nav-dropdown-menu button:hover { background: var(--surface-filter); }
}

/* Burger + Drawer (unterhalb des Tablet-Breakpoints; revidiert die
   PR-38-Zwischenloesung "umbrechende Linkzeile" - ADR-Nachtrag). Der Drawer
   ist die dokumentierte AUSNAHME der "keine Modals"-Regel. */
.nav-burger { display: none; }
.footer-nav { display: none; }
@media (max-width: 767px) {
  .site-header, .site-header-inner { flex-wrap: nowrap; justify-content: space-between; }
  /* Kopfhoehe mobil nur so weit wie noetig (Stufe B): das 44-px-Burger-Touchziel
     dominiert die Zeile weiter (Logo 40 px < 44 px) - Padding bleibt 0.75rem,
     der Kopf waechst mobil NICHT mit dem Desktop-Padding mit */
  .site-header { padding: 0.75rem 0; }
  .site-header .site-nav, .site-header .header-right { display: none; }
  .nav-burger { display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; color: var(--text-primary); }
  .footer-nav { display: block; margin-bottom: 0.75rem; }
}
.nav-drawer { position: fixed; top: 0; right: 0; bottom: 0; width: 80%; max-width: 20rem; display: flex; flex-direction: column; padding: 0.75rem 1rem 1rem; background: var(--surface-card); border-left: 1px solid var(--border); z-index: 60; transform: translateX(100%); visibility: hidden; transition: transform 200ms ease-out, visibility 0s linear 200ms; }
.nav-drawer.open { transform: none; visibility: visible; transition: transform 200ms ease-out; }
.nav-drawer-scrim { position: fixed; inset: 0; background: rgb(0 0 0 / 0.4); opacity: 0; visibility: hidden; transition: opacity 200ms ease-out, visibility 0s linear 200ms; z-index: 50; }
.nav-drawer-scrim.open { opacity: 1; visibility: visible; transition: opacity 200ms ease-out; }
@media (prefers-reduced-motion: reduce) {
  .nav-drawer, .nav-drawer.open, .nav-drawer-scrim, .nav-drawer-scrim.open { transition: none; }
}
.nav-drawer-close { align-self: flex-end; display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; background: none; border: 0; cursor: pointer; color: var(--text-primary); }
.nav-drawer nav { flex: 1; overflow-y: auto; }
.drawer-link { display: flex; align-items: center; min-height: 2.75rem; padding: 0.5rem; border-bottom: 1px solid var(--border); color: var(--text-primary); text-decoration: none; }
/* Drawer-Typo-Regel: der Gruppen-Titel erbt die Groesse der Haupteintraege
   (Basis-1rem, kein Einzelwert) und markiert die Hierarchie per Gewicht -
   Titel >= Untereintraege (die bleiben in der Basisgroesse) */
.drawer-group-title { margin: 0; padding: 0.75rem 0.5rem 0.25rem; color: var(--text-primary); font-weight: 600; }
.drawer-sublink { padding-left: 1.25rem; }
.drawer-active { border-left: 3px solid var(--accent); background: var(--surface-filter); }
.drawer-account { margin-top: auto; display: flex; align-items: center; gap: 0.5rem; min-height: 2.75rem; padding: 1rem 0.5rem 0; border-top: 1px solid var(--border); color: var(--sea); font-weight: 600; text-decoration: none; }
.drawer-account svg, .nav-drawer-close svg { width: 1.25em; height: 1.25em; }
/* Burger eine Stufe groesser (Betreiber-Feinschliff 25.07.2026: 20 -> 28 px);
   Touch-Ziel bleibt 44 px (min-width/-height am .nav-burger) */
.nav-burger svg { width: 1.75rem; height: 1.75rem; }

/* Login-Anzeige der Kopfzeile (O11, ADR 234): die Zugangs-E-Mail steht
   dauerhaft klein und im Sekundaerton unter "Mein Konto", rechtsbuendig
   auf der Link-Kante; sehr lange Adressen enden mit Ellipse, gekuerzt
   wird sonst nichts. Der Kopf-Block bleibt die Stufe-B-Groesse (die
   Zeile ist bewusst KEIN Nav-Link und traegt eine eigene Stufe). */
/* Der Konto-Bereich stapelt: Link oben, E-Mail-Zeile darunter, beide auf
   der rechten Kante. Noetig, weil `.site-header nav` alle Kopf-Navs als
   Flex-ZEILE fuehrt - hier gewinnt die Komponente ueber die Spezifitaet.
   Die enge Zeilenhoehe haelt den zweizeiligen Block unter der Logo-Hoehe -
   die Kopfzeile ist damit GLEICH HOCH wie im anonymen Zustand (gemessen:
   kein Hoehen-Sprung beim An-/Abmelden) */
.site-header .nav-dropdown-account { flex-direction: column; align-items: flex-end; gap: 0; line-height: 1.25; }
.nav-account-mail { display: block; max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-secondary); font-size: 0.75rem; text-align: right; }

/* Drawer-Konto-Zeile (O11, ADR 234; seit O13 selbst das Konto-ZIEL): sie
   eroeffnet die Konto-Gruppe (Kante oben) und ist ein normaler
   Drawer-Eintrag - nur zweizeilig: Titel in der Eintrags-Sprache, darunter
   die E-Mail klein im Sekundaerton. Weil der ganze Anker das Ziel ist,
   traegt er die Bestands-Aktiv-Sprache (drawer-active) wie die drei
   folgenden Ziele. Die Tarif-Gruppe behaelt ihren .drawer-group-title
   unveraendert (Drawer-Typo-Regel). */
.drawer-account-row { flex-direction: column; align-items: flex-start; justify-content: center; gap: 0.125rem; padding-top: 0.75rem; padding-bottom: 0.75rem; border-top: 1px solid var(--border); }
.drawer-account-title { font-weight: 600; }
.drawer-user { max-width: 100%; color: var(--text-secondary); font-size: 0.8125rem; overflow: hidden; text-overflow: ellipsis; }
/* Abmelden im Drawer: Schaltflaeche ueber die volle Breite, unten
   verankert wie der Konto-Link des anonymen Zustands */
.drawer-logout { margin-top: auto; padding-top: 1rem; }
.drawer-logout .button { display: block; width: 100%; text-align: center; }

/* Portal-Tab-Leiste (O11, ADR 234; ersetzt die "Ihr Kundenbereich"-Zeile
   aus P9b/O7 ersatzlos): eigenes Band DIREKT unter der Kopfzeile - dieselbe
   Band-Mechanik wie der site-header (vollbreites Band, Inhalt buendelt sich
   auf der content-container-Kante, ADR 112) und dieselbe Aktiv-Sprache wie
   die Hauptnavigation (halbfett + Akzent-Unterstrich, accent-strong).
   Abmelden steht raeumlich getrennt am rechten Leistenende und bleibt ein
   POST-Formular. Mobil bricht die Leiste nach Bestandsmuster um (flex-wrap
   wie der Kopf) - Abmelden landet am Leistenende. */
.portal-bar { background: var(--surface-card); border-bottom: 1px solid var(--border); }
.portal-bar-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0 1.5rem; }
.portal-tabs { display: flex; flex-wrap: wrap; gap: 0 0.25rem; }
.portal-tab { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0 0.75rem; border-bottom: 3px solid transparent; color: var(--text-secondary); text-decoration: none; }
.portal-tab-active { color: var(--accent-strong); font-weight: 600; border-bottom-color: var(--accent); }
/* Abmelden mobil NICHT in der Leiste (O13, Praezisierung zu ADR 234): der
   Knopf erscheint erst ab dem Bestands-Breakpoint (Tablet, 768 px) - unterhalb
   traegt ihn der Drawer, und zwar als EINZIGER Abmelde-Weg. EIN Baustein,
   zwei Zustaende: dasselbe Partial rendert beide Faelle, ueber die Sichtbarkeit
   entscheidet die Breite - kein zweites Partial, keine Geraete-Verzweigung
   im Server. */
.portal-bar-logout { display: none; margin: 0.25rem 0; }
@media (min-width: 768px) {
  .portal-bar-logout { display: block; }
}
@media (hover: hover) {
  /* eigene Hover-Farbe (Komponenten-Regel wie .filter-chip, ADR 139a): der
     Reiter DUNKELT den Text, statt auf den globalen Link-Hover-Ton
     umzufaerben. Der globale Selektor bleibt unangetastet (eine Wache
     fuehrt ihn woertlich) - die Komponenten-Regel gewinnt ueber die
     Eltern-Klasse an Spezifitaet */
  .portal-bar .portal-tab:hover { color: var(--text-primary); }
}
@media (max-width: 767px) {
  /* Mobil (Sichtpruefung 390 px): die Leiste traegt NUR die vier Reiter
     (der Abmelden-Knopf beginnt erst oberhalb, s. o.) - sie bekommen damit
     die volle Bandbreite. Gemessen bei 390 px: drei Reiter je Zeile, der
     vierte bricht nach Bestandsmuster um (flex-wrap wie der Kopf).
     Bewusst kein waagerechtes Scrollen: dort laege der aktive Reiter je
     nach Seite ausserhalb des Sichtfelds - der Umbruch zeigt ihn immer.
     Touch-Ziele bleiben 44 px hoch und deutlich getrennt */
  .portal-tabs { width: 100%; }
  .portal-tab { padding: 0 0.5rem; }
}

/* Breite + Seitenpadding kommen aus dem content-container (ADR 112) */
main { padding-top: 1.5rem; padding-bottom: 1.5rem; }

/* Board-Layout (ADR 124, Strapi-Muster in der hellen Marken-Variante):
   feste Sidebar links (Toenung --surface-section, eigene Flaechen-Sprache),
   Arbeitsflaeche rechts - die Tableview gewinnt die volle Restbreite.
   Aktiver Eintrag = bestehende Aktiv-Sprache (Toenungs-Flaeche +
   Seitenstrich, Muster drawer-active). */
.board-shell { display: flex; align-items: stretch; min-height: 100vh; }
.board-sidebar { display: flex; flex-direction: column; gap: 1rem; width: 240px; flex-shrink: 0; padding: 1rem 0.75rem; background: var(--surface-section); border-right: 1px solid var(--border); }
/* Sidebar-/Topbar-Logo kompakt: EINE eigene Groessen-Definition der
   Board-Stufe (die Kopf-Stufe B der Website bleibt unberuehrt) */
.board-sidebar-logo svg, .board-topbar .logo svg { display: block; height: 32px; width: auto; }
.board-sidebar-nav { flex: 1; display: grid; align-content: start; gap: 0.375rem; }
/* Klappbare Sidebar-Gruppen (ADR-124-Nachtrag 29.07.): Gruppenkopf als
   getoenter Balken - dieselbe Toenungs-Logik wie der Tableview-Kopf
   ("getoent = Steuerung"); der GANZE Balken ist der native summary-Toggle
   (44-px-Ziel), Chevron rotiert im open-Zustand (reduced-motion: ohne) */
.board-nav-group { display: grid; gap: 0.125rem; }
.board-group-header { display: flex; align-items: center; gap: 0.375rem; min-height: 2.75rem; padding: 0.375rem 0.625rem; border-radius: 8px; background: var(--surface-filter); cursor: pointer; list-style: none; }
.board-group-header::-webkit-details-marker { display: none; }
.board-group-title { margin: 0; color: var(--text-secondary); font-size: 0.8125rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.board-group-count { margin-left: auto; }
.board-group-chevron { display: flex; color: var(--text-secondary); transition: transform 150ms ease; }
.board-group-chevron svg { width: 18px; height: 18px; }
.board-nav-group[open] .board-group-chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .board-group-chevron { transition: none; } }
/* Eintraege der Gruppe unter dem Balken eingerueckt */
.board-nav-group .board-nav-link { margin-left: 0.5rem; }
.board-nav-link { display: flex; align-items: center; min-height: 2.75rem; padding: 0.375rem 0.625rem; border-radius: 6px; color: var(--text-primary); text-decoration: none; }
.board-nav-link[aria-current="page"] { background: var(--surface-filter); border-left: 3px solid var(--accent); padding-left: calc(0.625rem - 3px); color: var(--accent-strong); }
/* Sidebar-Schnellfilter (ADR-160-Nachtrag): reines JS-Enhancement - ohne JS
   erscheint das Feld nicht (volle Liste, dokumentierter Degradationspfad);
   ausgefilterte Eintraege verschwinden per hidden (display:flex der Links
   muss dem hidden-Attribut weichen). Input-Paar Karte/Border wie die
   Formular-Inputs, Hinweis in --text-secondary auf --surface-section. */
.board-nav-filter { margin: 0.25rem 0 0.25rem 0.5rem; }
.board-nav-filter input { width: 100%; min-height: 2rem; padding: 0.25rem 0.5rem; border: 1px solid var(--border-input); border-radius: 6px; background: var(--surface-card); color: var(--text-primary); font: inherit; font-size: 0.875rem; }
.board-nav-filter-empty { margin: 0.375rem 0 0 0.125rem; color: var(--text-secondary); font-size: 0.875rem; }
.board-nav-link[hidden] { display: none; }
html.no-js .board-nav-filter { display: none; }
.board-sidebar-footer { margin-top: auto; display: grid; gap: 0.5rem; padding: 0.75rem 0.625rem 0; border-top: 1px solid var(--border); color: var(--text-secondary); }
.board-sidebar-user { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-logout button { width: 100%; }
.board-topbar { display: none; }
/* Board: kompakte Dichte, Arbeitsflaeche nutzt die Restbreite */
.board main { flex: 1; min-width: 0; max-width: none; padding: 1rem 1.5rem; }
@media (max-width: 767px) {
  /* Mobil: Topbar (Logo + Burger) + Drawer nach Website-Muster; MIT JS ist
     die Sidebar zu, OHNE JS bleibt sie gestapelt sichtbar (Fallback) */
  .board-topbar { display: flex; align-items: center; justify-content: space-between; padding: 0.5rem 1rem; background: var(--surface-card); border-bottom: 1px solid var(--border); }
  html.js .board-sidebar { display: none; }
  html.no-js .board-topbar .nav-burger { display: none; }
  .board-shell { display: block; min-height: 0; }
}

/* Board-Masken (Board-Etappe, ADR 123): Tabellen-/Formular-Bausteine der
   Tarif-Verwaltung - nur Bestands-Tokens, keine neuen Farbpaare */
.board-table { width: 100%; border-collapse: collapse; background: var(--surface-card); border: 1px solid var(--border); }
.board-table th { text-align: left; font-weight: 600; padding: 0.5rem 0.75rem; }
.board-table td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--border); }
.board-table tbody tr:nth-child(even) { background: var(--row-alt); }
/* Zeilen-Klick = Flaechen-Link-Muster: der Anker traegt die Bearbeitung */
/* Referenz-Bausteine (ADR 161): Kunden-/Container-/Vorgangs-Links in
   Zellen und Sektionen sprechen die Erstspalten-Link-Sprache */
.board-row-link, .board-ref { font-weight: 600; text-decoration: none; }
/* Netto/Brutto-Rechner (ADR 164): Klappbalken-Innenleben - Eingabe in
   Feldbreite, Richtungs-Knoepfe daneben, Ergebnis als Hinweis-Zeile */
.board-price-calc { margin: 1rem 0 0; }
.board-price-calc-body { display: grid; gap: 0.5rem; padding: 0.75rem 0; }
.board-price-calc-directions { display: flex; gap: 0.5rem; }
/* Gedrueckter Toggle (ADR 170): Zustands-PAAR Flaeche+Schrift - Ruhe auf
   accent-strong (Text-Schwelle, --accent traegt nie Text), Hover/Active
   unten als Varianten-Regel ALLER .button[aria-pressed="true"] */
.board-price-calc-directions .button[aria-pressed="true"] { background: var(--accent-strong); border-color: var(--accent-strong); color: #FFFFFF; }

/* Verfuegbarkeits-Sektion (ADR 164): "Heute:"-Kopfzeile + gedaempfte
   tote Vorgaenge (board-muted baut detail.py - Render-Beleg im
   Sektions-Drehbuch) */
.board-section-head { font-weight: 600; margin: 0 0 0.25rem; }
.board-muted { opacity: 0.6; }

/* Kosten-Sektion des Vorgangs (ADR 163): abgeleitete Uebersicht unter dem
   Fakten-Kopf; Zwischentitel kompakt ueber den Fakten-Listen */
.board-costs { margin: 1rem 0; }
.board-costs h3 { margin: 0.75rem 0 0.25rem; font-size: 1rem; }
/* Kosten-Tabelle der Betreiber-Sicht (A10, ADR 257): netto, USt und
   brutto nebeneinander - Kundendokumente zeigen weiterhin den einen
   massgeblichen Wert. Schmale Fenster scrollen die Tabelle in ihrem
   eigenen Kasten, die Seite bleibt ruhig (Muster tableview-scroller) */
.board-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 40rem; }
/* DAS eine Tabellendesign (A25/ADR 276): Kosten- und Container-Tabellen
   aller Orte kommen aus den zwei Komponenten (cost_table, contract_facts/
   positions) - kein Orts-Styling mehr. Ruhige Optik: weisse Zeilen, feine
   Trennlinien, Kopfzeilen-Balken, Summenzeilen fett mit Sea-Linie. */
/* Der EINE Kosten-Baustein (A19/ADR 271): Summenzeilen betont mit
   Abschluss-Linie; alle übrigen Zeilen - ausdrücklich auch "ab <Datum>" -
   in Normal-Optik (A20 Teil 2: EINE Optik an allen Orten, die Abhebung
   leistet die Position unter der Summenzeile); gilt fuer die
   Board-Spaltenwahl UND die Kunden-Tabelle darunter */
.cost-block { background: var(--surface-card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.cost-block + .cost-block { margin-top: 1.1rem; }
/* Rahmen-Entfall als PARAMETER (frameless - nur die VZF nutzt ihn; ihr
   PDF-Stylesheet definiert die Klassen selbst, diese Web-Regel haelt den
   Parameter auch webseitig ehrlich) */
.cost-block-frameless { border: none; border-radius: 0; }
.cost-block-head { padding: 0.5rem 0.875rem; font-size: 0.75rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em; color: var(--sea); background: var(--surface-filter); border-bottom: 1px solid var(--border); }
table.cost-table { width: 100%; border-collapse: collapse; }
.cost-table th, .cost-table td { padding: 0.5rem 0.875rem; text-align: left; vertical-align: top; border-bottom: 1px solid var(--border); }
.cost-table tbody tr:last-child th, .cost-table tbody tr:last-child td { border-bottom: 0; }
.cost-table td:last-child { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cost-table-three td { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.cost-table-three thead th { color: var(--text-secondary); font-weight: 400; }
/* Massgebliche Spalte je Segment (A26/ADR 277, erlaubte gewachte
   Fett-Ausnahme): Gewerbe Netto, Privat Brutto - Kopf und alle Werte */
.cost-table-three .cost-col-key { font-weight: 600; }
.cost-table-three thead th + th { text-align: right; }
/* Fett-Regel (A23/ADR 274): NUR Summenzeilen fett - expliziter th-Reset
   schliesst den Browser-Default-Weg; Sea-Linie der Summenzeile (A25) */
.cost-table tbody th { font-weight: 400; }
.cost-table .cost-row-total th, .cost-table .cost-row-total td { border-top: 2px solid var(--sea); font-weight: 600; }
/* Container-Tabelle des Portals (A19 Teil 2, analog VZF): drei schmale
   Spalten, Kennung fett, Tarifname im Akzent - bricht auch mobil nicht */
/* Mietbeginn-Zeile (A27 Teil 2): deutlicher Abstand zur Tabelle -
   gleiche Groessenordnung wie Ueberschrift->Zeile (Paritaets-Wache) */
.positions-start { margin: 0 0 1rem; }
.positions-table { width: 100%; border-collapse: collapse; background: var(--surface-card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.positions-table th { text-align: left; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 600; padding: 0.5rem 0.875rem; border-bottom: 1px solid var(--border); }
.positions-table td { padding: 0.55rem 0.875rem; border-bottom: 1px solid var(--border); }
.positions-table tbody tr:last-child td { border-bottom: 0; }
/* letzte Spalte rechtsbündig wie im VZF-Vorbild (A20 Teil 3, Mockup
   portal-vertrag-kompakt: th/td:last-child rechts) - Datumswerte mit
   Tabellenziffern (Bestandsmuster der Betrags-Spalten) */
.positions-table th:last-child, .positions-table td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
.positions-table .positions-pair { font-weight: 700; }
/* Tarifname im Positions-Baustein: --accent-strong statt --accent
   (A59/ADR 313) - hier traegt die Akzentfarbe TEXT, und zwar im
   geteilten Vertragsbaustein, der auf Angebotsseite UND im Portal
   laeuft. --accent haelt dort nur 3,12-3,70:1, --accent-strong 4,70-5,57. */
.positions-table .positions-tariff { color: var(--accent-strong); }
/* 390-px-Grundsatz (A33/ADR 281, Mobile-Ueberlauf-Wache): die Container-
   Tabelle war der einzige Seiten-Ueberlaeufer der Kundenstrecke - mobil
   kompaktere Zellen und umbrechbare Kopfzeilen statt Scrollkasten
   (Regel 25: kein horizontales Scrolling ausser Plan-Scroller) */
@media (max-width: 430px) {
  .positions-table { font-size: 0.85rem; }
  .positions-table th { font-size: 0.66rem; padding: 0.4rem 0.45rem; white-space: normal; }
  .positions-table td { padding: 0.45rem 0.45rem; }
}
.board-row-key { display: block; color: var(--text-muted); font-size: 0.8125rem; }
/* nicht klickbar = nicht klickbar-aussehend (ADR 125): Titelzelle ohne Maske */
.board-row-title { font-weight: 600; }
.board-static-facts { color: var(--text-secondary); }
.board-static-hint { display: block; color: var(--text-muted); font-size: 0.875rem; }
/* Warn-Zeile im Board-Kopf (ADR 139, Rechts-Wache Seitentexte): Amber-
   Hinweis-Paar des Token-Katalogs (Paar im Kontrast-Gate) */
.board-warn-hint { display: inline-block; margin: 0.25rem 0 0; padding: 0.375rem 0.75rem; border-radius: 6px; background: var(--amber-badge-bg); color: var(--amber-badge-text); font-size: 0.875rem; }
/* Umrahmter Gruppen-Block: EINE Deklaration fuer die M2M-Zuweisung UND
   die Konfigurations-Sektionen der Betriebseinstellungen
   (ADR-171/174-Nachtrag) - kein zweiter Rahmen-Stil, keine neuen
   Tokens; die legend traegt den Gruppen-Namen */
.board-assignment,
.board-form-group { border: 1px solid var(--border-strong); border-radius: 6px; padding: 0.75rem 1rem 1rem; margin: 1rem 0; }
.board-form-group > legend { font-weight: 600; }
.board-assignment legend { font-weight: 600; padding: 0 0.25rem; }
.board-assignment-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); gap: 0.375rem 1rem; }
.board-assignment-option { display: flex; align-items: center; gap: 0.5rem; min-height: 2.75rem; }
/* board-tariff-form ist in der einen board-create-form aufgegangen (ADR 128: Tarif-Maske = Erst-Konfiguration der Detail-View) */
/* Create-Standard (ADR 127): Listen-Kopf mit Anlegen-Button rechts,
   die eine Create-Maske in Formular-Lesebreite */
.board-page-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.board-create-button { white-space: nowrap; }
/* EINE Detail-Huelle fuer alle Modi (ADR 147): Edit-Formular UND
   Sicht-only-Detailview teilen dieselbe Definition - zwei Namen, eine
   Regel (board-create-form bleibt der JS-/Test-Anker des Formular-Modus,
   board-detail-hull traegt die Sicht ohne Input-Felder) */
.board-create-form, .board-detail-hull { max-width: 40rem; }
/* Sicht-Aktion (ADR 167): reversibler Fakt-Setzer der Sicht-View */
.board-view-actions { margin: 1rem 0 0; display: flex; gap: 0.75rem; }
/* Konflikt-Marker (ADR 169): Warnzeichen in Amber - NICHT Rot (Rot =
   Destruktiv-Ton); Erklaerung via title + sr-only, nie Icon allein */
.board-conflict { color: var(--amber-icon); margin-left: 0.25rem; cursor: help; }
/* Status-Badge (ADR 170): Titelzeile der Detail-Koepfe, visuelle Hoehe =
   Aktions-Buttons; GRUEN = positiver Status (state-success-Paar helle
   Flaeche + dunkle Schrift), alle uebrigen neutral (Rahmen/Text ohne
   Hintergrund) - Ton-Katalog: board/derivations.POSITIVE_BADGE_STATUS */
.board-title-row { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; margin: 1.17rem 0; }
/* Listen-Navigation der Detail-Kopfzeile (O9, ADR 228): Ruecksprung +
   Blaetter-Pfeile mit Position; Rand-Pfeil bleibt sichtbar-inaktiv
   (aria-disabled, Disabled-Standard-Optik) */
.board-list-nav { display: inline-flex; align-items: center; gap: 0.375rem; margin: 0.25rem 0 1rem; }
.board-list-nav-back { color: var(--sea); font-weight: 600; text-decoration: none; margin-right: 0.625rem; }
.board-list-nav-arrow { display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-card); color: var(--text-primary); text-decoration: none; font-size: 1.25rem; line-height: 1; }
.board-list-nav-arrow[aria-disabled="true"] { opacity: 0.45; }
@media (hover: hover) {
  .board-list-nav-back:hover { text-decoration: underline; }
  a.board-list-nav-arrow:hover { background: var(--surface-filter); }
}
.board-list-nav-position { color: var(--text-secondary); font-variant-numeric: tabular-nums; padding: 0 0.25rem; }
.board-title-row h1 { margin: 0; }
.status-badge { display: inline-flex; align-items: center; border-radius: 6px; padding: 0 0.875rem; min-height: var(--control-height-min); font-size: var(--control-font-min); font-weight: 600; }
.status-badge-positive { background: var(--state-success-bg); color: var(--state-success-text); }
.status-badge-neutral { background: transparent; border: 1px solid var(--text-secondary); color: var(--text-secondary); }
/* Detail-Standard (ADR 128): Read-only-Fakten-Kopf + Aktionszeile */
/* Sicht-Umschalter der Listen (ADR 160, Erst-Nutzer Tickets): aktive
   Sicht als Badge-Zustand (accent-Badge-Paar im Kontrast-Gate), andere
   Sichten als Pill-Links - 44-px-Zeilenziel */
.board-view-switch { display: flex; gap: 0.5rem; margin: 0 0 1rem; }
.board-view-current { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0.125rem 0.875rem; border-radius: 999px; background: var(--accent-badge-bg); color: var(--accent-badge-text); font-weight: 600; }
.board-view-link { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0.125rem 0.875rem; border-radius: 999px; border: 1px solid var(--border-strong); color: var(--text-primary); text-decoration: none; }

/* Kachel-Live-Vorschau der Tarif-Maske (ADR-159-Nachtrag): rendert die ECHTE
   Website-Kachel im Vorschau-Rahmen - Interaktion neutralisiert, die
   Verfuegbarkeits-Zeile entfaellt (Live-Bestand ist keine Formular-Wahrheit) */
.tariff-preview { max-width: 26rem; pointer-events: none; }
.tariff-preview .tariff-counter { display: none; }

.board-detail-facts { display: grid; grid-template-columns: max-content 1fr; gap: 0.25rem 1.5rem; margin: 0 0 1rem; max-width: 40rem; }
.board-detail-facts dt { color: var(--text-secondary); }
.board-detail-facts dd { margin: 0; overflow-wrap: anywhere; }
/* Aktions-Leiste (ADR 145): rechtsbuendig [Abbrechen][Speichern], Loeschen
   ganz links - margin-right:auto schafft die Luecke; Dialog-Zeilen (ADR 137)
   behalten ihre eigene Klasse (Bestaetigungs-Muster, destruktiv rechts) */
.board-form-actions { display: flex; align-items: center; gap: 0.75rem; margin-top: 1rem; justify-content: flex-end; }
.board-form-delete { margin-right: auto; }
.board-dialog-actions { display: flex; align-items: center; gap: 0.75rem; margin-top: 1rem; justify-content: flex-end; }
.board-delete-dialog { border: 1px solid var(--border-strong); border-radius: 8px; padding: 1.5rem; max-width: 28rem; }
.board-delete-dialog::backdrop { background: rgba(38, 34, 30, 0.55); }
/* Dialog-Regel (ADR 137): Dialoge rendern NIE open - die ?delete=...-Seite
   zeigt den geschlossenen Dialog ohne JS als Inline-Block (No-JS-Wahrheit;
   mit JS oeffnet AUSSCHLIESSLICH der Klick via showModal) */
html.no-js dialog[data-noscript-open] { display: block; position: static; margin: 1rem 0; }
/* Beziehungs-Sektionen (ADR 129) */
/* scroll-margin (ADR 147): Ruecksprung-Anker der Beziehungs-Sektionen */
.board-relation-section { margin-top: 2rem; max-width: 40rem; scroll-margin-top: 1rem; }
/* Gruppen-Spalten-Variante (ADR 149): auto-fit-Raster mit ~110px-Mindest-
   breite - schmale Viewports brechen auf 2-3 Spalten um, nie Querscroll;
   Spaltenkopf "Reihe X (Anzahl)" mit Trennlinie */
.board-relation-columns { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 0 1.25rem; }
.board-relation-column h3 { font-size: 1rem; margin: 0.5rem 0 0.25rem; padding-bottom: 0.25rem; border-bottom: 1px solid var(--border); }
/* Grid-Track darf schrumpfen (A49): der Default min-width:auto laesst
   die Spur nicht unter die min-content-Breite ihrer Zeile - bei 390 px
   schob die Nachrichten-Zeile die Liste dadurch ueber den Rand des
   Inhaltsbereichs (EK-Befund 30.08.; die Zeile selbst kappte korrekt,
   ihr Container gab die Breite nicht her). Gilt fuer ALLE
   Beziehungs-Sektionen - dieselbe Klasse, dieselbe Ursache. */
.board-relation-rows { list-style: none; margin: 0.5rem 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.25rem; }
.board-relation-rows > li { min-width: 0; }
.board-relation-rows a { color: var(--sea); }
.board-relation-empty { color: var(--text-secondary); }
/* Versand-Maske (ADR 183): Info-Kasten (Statuswechsel + Reservierungs-Ende)
   und Ablehnungs-Banner der Wiederbelebung - Rahmen aus bestehenden Tokens,
   das Amber ist der etablierte Warn-Ton (ADR 169, nie Rot = Destruktiv) */
.board-offer-info { border: 1px solid var(--border-strong); border-radius: 8px; padding: 0.75rem 1rem; margin: 0.5rem 0 1rem; }
.board-offer-info p { margin: 0; }
.board-offer-info p + p { margin-top: 0.4rem; }
.board-offer-banner { border: 1px solid var(--amber-icon); border-radius: 8px; padding: 0.75rem 1rem; margin: 0.5rem 0 1rem; }
/* Nachrichten-Historie (ADR 181; Anatomie A14/ADR 263): Karten-Accordion
   nach FAQ-Bestandsmuster - alles startet zugeklappt, mehrere duerfen
   offen sein, offene Zeile mit --sea-Akzentkante. Feste Zeilen-Anatomie:
   [Icon] Art fett · Betreff grau (einzeilig gekuerzt) | rechts Chip +
   Datum · Uhrzeit; zweite Zeile Empfaenger. Koerperlose Arten rendern
   dieselbe Anatomie ohne Aufklapper (board-message-flat). */
.board-message { background: var(--surface-card); border: 1px solid var(--border); border-left: 3px solid transparent; border-radius: 10px; margin-bottom: 0.5rem; overflow: hidden; }
details.board-message[open] { border-left-color: var(--sea); }
/* koerperlose Zeile: dieselbe Karte ohne Aufklapp-Verhalten */
.board-message-flat { border-left-color: transparent; }
.board-message-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.75rem; min-height: 2.75rem; padding: 0.5rem 1rem; }
summary.board-message-head { cursor: pointer; list-style: none; }
/* Aufklapp-Symbol (A14a): DERSELBE Chevron wie das FAQ - die drei
   FAQ-Regeln (Masken-Chevron, Dreh-Zustand offen, reduced-motion) tragen
   beide Accordions per geteiltem Selektor (eine Quelle, kein zweites
   Symbol). Position rechts aussen, Datum davor (der Meta-Block bleibt
   links vom Chevron). Koerperlose Zeilen (div statt details) haben kein
   ::after aus diesen Regeln und bleiben symbolfrei. */
/* Chevron OBEN an der ersten Zeile (A16, FAQ-Referenz): nicht ueber beide
   Zeilen zentrieren - flex-start + Ausgleich auf die Mitte der ersten
   Zeile (Zeilenhoehe 1.5rem, Symbol 18px -> 3px). */
summary.board-message-head::after { align-self: flex-start; margin-top: 0.1875rem; }
summary.board-message-head::-webkit-details-marker { display: none; }
.board-message-main { display: flex; align-items: flex-start; gap: 0.5rem; min-width: 0; }
.board-message-icon { color: var(--sea); display: inline-flex; flex-shrink: 0; margin-top: 0.15rem; }
.board-message-icon svg { width: 1.1em; height: 1.1em; }
.board-message-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.board-message-title { display: flex; gap: 0.4rem; min-width: 0; }
.board-message-title strong { white-space: nowrap; }
.board-message-subject { color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.board-message-recipient { color: var(--text-muted); font-size: 0.875rem; }
.board-message-meta { display: flex; align-items: center; gap: 0.5rem; flex-shrink: 0; color: var(--text-secondary); font-size: 0.875rem; }
.board-message-chip { display: inline-flex; align-items: center; padding: 0.1rem 0.5rem; border: 1px solid var(--border-strong); border-radius: 999px; color: var(--sea); font-weight: 600; text-decoration: none; }
.board-message-body { margin: 0 1rem 0.75rem 2.6rem; color: var(--text-secondary); white-space: pre-line; }
/* Mobile Verdichtung der Nachrichten-Zeile (A49/ADR 297, EK-Befund
   30.08.: die A14-Anatomie lief bei 390 px ueber den Rand). Mobile-first
   = der verdichtete Zustand ist der DEFAULT, ab Tablet stellt der
   Breakpoint unten die volle Anatomie wieder her. Zugeklappt bleiben nur
   Icon, Art, Chip und DATUM; Betreff, Empfaenger und Uhrzeit wandern in
   den Aufklapp-Bereich. Nur Board - das Portal hat seit A33 keine
   Nachrichten-Sektion. */
.board-message-subject { display: none; }
details.board-message .board-message-recipient { display: none; }
.board-message-time { display: none; }
/* Koerperlose Zeilen haben keinen Aufklapper (div statt details): ihr
   Hinweis bleibt mobil stehen, nur die Adresse davor entfaellt. */
.board-message-to { display: none; }
/* Der Art-Name darf mobil umbrechen (A49): nowrap + nicht
   schrumpfender Meta-Block liessen ihn sonst unter Chip und Datum
   laufen - zugeklappt hat die Zeile dank der Verdichtung Platz
   dafuer. Ab Tablet bleibt der Bestand (nowrap, eine Zeile). */
.board-message-title { flex-wrap: wrap; }
.board-message-title strong { white-space: normal; }
/* Der Hinweis selbst bleibt in JEDER Breite sichtbar - er ist bei
   koerperlosen Arten die einzige Erklaerung (kein Aufklapper). */
.board-message-hint { display: inline; }
.board-message-mobile-facts { margin: 0 1rem 0.5rem 2.6rem; color: var(--text-muted); font-size: 0.875rem; }

.board-position-card { border: 1px solid var(--border-strong); border-radius: 8px; padding: 1rem; margin: 1rem 0; }
/* Aktions-Block des Vertragsdetails (A9): jede ERLAUBTE Aktion ist ein
   nativer Aufklapper (details/summary wie „Position hinzufügen"). Das
   name-Attribut macht die Gruppe exklusiv - oeffnet man einen, schliesst
   der vorige, ohne eine Zeile JS. Die Hauptaktion des Zustands traegt den
   Akzentrahmen; die Folgen-Angabe steht rechts in der Kopfzeile. */
.board-action { border: 1px solid var(--border); border-radius: 8px; background: var(--surface-card); padding: 0.25rem 1rem; margin: 0.5rem 0; }
.board-action-primary { border-color: var(--sea); }
.board-action-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; min-height: 2.75rem; cursor: pointer; }
.board-action-label { font-weight: 600; display: inline-flex; align-items: center; gap: 0.5rem; }
/* Kopf-Icon der Aktions-Aufklapper (A12, ADR 261): dekorativ, Groesse und
   Farbe nach dem Bestandsmuster der Tarif-Kachel-Icons (.tariff-icon) */
.board-action-icon { color: var(--sea); display: inline-flex; }
.board-action-icon svg { width: 1.25em; height: 1.25em; }
.board-action-consequence { color: var(--text-muted); font-size: 0.875rem; }
.board-action-body { margin: 0.25rem 0 0.75rem; }
/* Absende-Zeile eines Aktions-Aufklappers (A10): bewusst NICHT
   .board-form-actions - die Leiste des Haupt-Formulars bleibt der eine
   Speichern-Anker (Sicht-Smoke, Tests) */
.board-action-submit { display: flex; justify-content: flex-end; margin-top: 0.75rem; }
/* Verweis-Eintrag statt Aufklapper (A10): „Weiterer Container?" oeffnet
   nichts, er fuehrt weg - Folgen-Angabe rechts wie bei den Aufklappern */
.board-action-link { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; min-height: 2.75rem; padding: 0.25rem 1rem; }
/* Cue-Zeile (A9): EIN Satz ueber den Aktionen - was ist hier gerade los
   und wodurch wird es beantwortet (abgeleitet, nicht gepflegt) */
.board-action-cue { margin: 0 0 0.75rem; }
/* Zustandszeile der Positions-Karte (A9): Laufzeit-Achse + Mietbeginn */
.board-position-state { margin: 0 0 0.5rem; color: var(--text-secondary); }
/* Konflikt im Klartext (A9): der Marker erklaerte sich bisher nur ueber
   title und sr-only - auf Beruehrung war beides stumm */
.board-conflict-note { margin: 0 0 0.75rem; color: var(--text-secondary); font-size: 0.875rem; }
/* Kunden-Karte (A9): der Vertrag zeigt den Kunden, gepflegt wird er an
   seiner eigenen Maske */
.board-customer-card-name { font-weight: 600; margin: 0 0 0.25rem; }
/* Bild-Assets (ADR 130): Listen-Thumbnail; die Masken-Vorschau lebt seit
   Runde 3 (ADR 142) in der file-Variante der Feld-Komponente
   (field-file-preview, 240-px-Kante) */
.board-thumb { display: block; width: 4.5rem; height: 2.5rem; object-fit: cover; border-radius: 4px; margin-bottom: 0.25rem; }

/* Tableview v2 (ADR 138, Betreiber-Vorlage django-filterbare-tabelle):
   DIE eine Board-Tabellen-Komponente. Panel-Muster: Filterbereich als
   getoente Steuer-Flaeche ("getoent = Steuerung, hell = Daten"), Facetten
   als Checkbox-Chips, aktive Filter als entfernbare Chips, Sortier-Koepfe;
   Tabellen-Optik (Kopf-Toenung, Zebra) = abgenommene Referenz. Die fruehere
   Kopfzeilen-Filterstufe (kompakte Inputs, Dropdown-Schwebe-Panel) ist
   ersatzlos entfallen - ALLE Eingaben stehen in Standard-Massen, die
   Tableview-Ausnahme des Mindestgroessen-Gesetzes ist GESTRICHEN. */
.tableview { margin-top: 1rem; }
/* htmx-Ladeanzeige (Vendor-Kontrakt): unsichtbar, htmx blendet sie waehrend
   eines Requests ueber .htmx-request ein - hier definiert, damit die
   Klassen-Paritaets-Wache greift und nichts vor htmx-Load aufblitzt */
.htmx-indicator { opacity: 0; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { opacity: 1; transition: opacity 200ms ease-in; }
/* ^ seit A90/ADR 339 die EINZIGE Quelle dieser Regeln: htmx injiziert seinen
   <style>-Block nicht mehr (includeIndicatorStyles=false in beiden Basen),
   weil style-src ohne 'unsafe-inline' ihn blockieren wuerde; die Transition
   ist die von htmx uebernommene */
/* Einklappbare Filter-Sektion (Polish 02.08., Muster Sidebar-Gruppen):
   getoente Kopfzeile mit Chevron + Zaehler-Badge; Zustand merkt die Insel
   je Liste (localStorage). Kompakt-Politur: halbierte Abstaende. */
.tableview-filters { margin: 0 0 0.5rem; }
.tableview-filters-head { display: flex; align-items: center; gap: 0.375rem; min-height: 2.75rem; padding: 0.375rem 0.625rem; border-radius: 8px; background: var(--surface-filter); cursor: pointer; list-style: none; }
.tableview-filters-head::-webkit-details-marker { display: none; }
.tableview-filters-title { color: var(--text-secondary); font-size: 0.8125rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.tableview-filters-chevron { margin-left: auto; display: inline-flex; }
.tableview-filters-chevron svg { width: 1rem; height: 1rem; color: var(--text-muted); transition: transform 120ms ease-out; }
.tableview-filters[open] .tableview-filters-chevron svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .tableview-filters-chevron svg { transition: none; } }
.tableview-filters-count { min-width: 1.5rem; text-align: center; }
.tableview-filterbar { margin: 0.375rem 0 0; padding: 0.5rem 1rem 0.625rem; background: var(--surface-filter); border: 1px solid var(--border); border-radius: 8px; display: grid; gap: 0.375rem; }
.tableview-searchrow { display: flex; flex-wrap: wrap; gap: 0.375rem 1rem; align-items: flex-end; }
.tableview-search { flex: 0 1 22rem; }
.tableview-searchfield { flex: 0 1 12rem; }
.tableview-search label, .tableview-searchfield label, .tableview-filterlabel { display: block; font-size: 0.875rem; color: var(--text-secondary); margin-bottom: 0.25rem; font-weight: 400; }
.tableview-filterlabel strong { color: var(--text-primary); }
/* Statischer Suchen-in-Hinweis (Runde 2): ersetzt das Dropdown bei genau
   EINEM durchsuchbaren Feld - auf Feldhoehe ausgerichtet */
.tableview-searchhint { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 0.25rem; min-height: var(--control-height-min); color: var(--text-secondary); font-size: 0.875rem; }
.tableview-searchhint strong { color: var(--text-primary); font-weight: 600; }
/* Bereichs-Filter: je Bereich eine EIGENE kompakte Zeile (Runde 2) */
.tableview-rangerow { display: block; }
.tableview-rangefield { max-width: 18rem; }
.tableview-dates { display: flex; flex-wrap: wrap; gap: 0.375rem 1.5rem; align-items: flex-end; }
.tableview-datefield { flex: 0 1 auto; }
.tableview-daterange input[type="date"] { width: 9.5rem; }
.tableview-daterange { display: flex; align-items: center; gap: 0.375rem; color: var(--text-muted); }
.tableview-daterange input[type="date"] { width: auto; }
/* Doppel-Schieberegler (Vorlagen-Muster): zwei native range-Inputs auf einer
   Spur; die Zeile haelt das 44-px-Ziel (Mindestgroessen-Gesetz - range ist
   damit ein GEDECKTER Steuerelement-Typ, Wache T-DSN-067) */
.tableview-slider { position: relative; min-height: var(--control-height-min); display: flex; align-items: center; }
.tableview-slider-track { position: absolute; left: 0; right: 0; height: 4px; border-radius: 2px; background: var(--border-strong); }
.tableview-slider-fill { position: absolute; height: 4px; border-radius: 2px; background: var(--accent); left: 0; right: 0; }
.tableview-slider input[type="range"] { position: absolute; left: 0; right: 0; width: 100%; margin: 0; appearance: none; -webkit-appearance: none; background: none; pointer-events: none; min-height: var(--control-height-min); font-size: var(--control-font-min); }
.tableview-slider input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; pointer-events: auto; width: 1.25rem; height: 1.25rem; border-radius: 50%; background: var(--surface-card); border: 2px solid var(--accent-strong); cursor: pointer; }
.tableview-slider input[type="range"]::-moz-range-thumb { pointer-events: auto; width: 1.25rem; height: 1.25rem; border-radius: 50%; background: var(--surface-card); border: 2px solid var(--accent-strong); cursor: pointer; }
.tableview-slider input[type="range"]:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
/* Facetten als Checkbox-Chips: ECHTE Checkboxen in Labels (Tastatur +
   Screenreader gratis); gewaehlt = Akzent-Badge-Paar (Kontrast im Gate) */
/* Facetten-Layout (Runde 2): JE Facette eine eigene Zeile, das Gruppen-
   Label steht als UEBERSCHRIFT ueber den Pills (kein Inline-Float mehr,
   kein "(Mehrfachauswahl)"-Zusatz - Pills kommunizieren es selbst) */
.tableview-facet { border: 0; padding: 0; margin: 0; }
.tableview-facet legend { padding: 0; margin: 0 0 0.25rem; font-weight: 400; }
.tableview-facet-options { display: flex; flex-wrap: wrap; gap: 0.375rem; }
/* Pill-Zustands-Matrix (Polish 02.08.; Runde 2 ergaenzt inaktiv):
   Checkbox bleibt technisch im Label (A11y), visuell versteckt (Vorlagen-
   Muster opacity 0) - den Zustand traegt die Pill-Faerbung allein.
   MATRIX: unausgewaehlt = Karte/border-strong · unausgewaehlt+hover =
   Flaechen-Toenung (Text primaer) · gewaehlt = Akzent-Badge-Paar ·
   gewaehlt+hover = DUNKLERE Flaeche accent-hover MIT WEISSER Schrift ·
   inaktiv (Wert ohne Vorkommen im Gesamtbestand) = sichtbar-inaktiv
   (Disabled-Standard opacity, Muster tableview-jump[disabled]; kein Hover,
   nicht klickbar, nicht fokussierbar - Gewaehltes bleibt immer abwaehlbar).
   Beide Hover-Paare stehen im Kontrast-Gate. */
.facet-chip { position: relative; display: inline-flex; align-items: center; min-height: 2rem; padding: 0.125rem 0.75rem; border: 1px solid var(--border-strong); border-radius: 999px; background: var(--surface-card); cursor: pointer; font-weight: 400; font-size: 0.8125rem; }
.facet-chip input[type="checkbox"] { position: absolute; opacity: 0; width: 100%; height: 100%; left: 0; top: 0; margin: 0; min-height: auto; cursor: pointer; }
.facet-chip:has(input:checked) { background: var(--accent-badge-bg); border-color: var(--accent); color: var(--accent-badge-text); font-weight: 600; }
.facet-chip:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.facet-chip:has(input:disabled) { opacity: 0.45; cursor: default; }
.facet-chip input[type="checkbox"]:disabled { cursor: default; }
@media (hover: hover) {
  .facet-chip:not(:has(input:disabled)):hover { background: var(--surface-filter); }
  .facet-chip:has(input:checked):hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #FFFFFF; }
}
.tableview-apply { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem 1rem; }
.tableview-pagesize { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--text-secondary); margin-left: auto; }
.tableview-pagesize select { width: auto; }
/* Trefferzahl (aria-live, A11y-Ergaenzung) + aktive Filter als Chips */
.tableview-active { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; margin: 0.75rem 0; }
.tableview-count { color: var(--text-secondary); }
.tableview-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }
/* Chip der GEWAEHLTEN Filter: Ruhe = Akzent-Badge-Paar, Hover = dunklere
   Flaeche accent-hover mit WEISSER Schrift (beide Paare im Kontrast-Gate;
   der globale Link-Hover ist per :not(.filter-chip) ausgeschlossen -
   Runde-2-Fix "rot auf rot") */
.filter-chip { display: inline-flex; align-items: center; gap: 0.5rem; min-height: var(--control-height-min); padding: 0.125rem 0.875rem; border-radius: 999px; background: var(--accent-badge-bg); color: var(--accent-badge-text); text-decoration: none; font-size: 0.875rem; }
@media (hover: hover) { .filter-chip:hover { background: var(--accent-hover); color: #FFFFFF; } }
.tableview-scroller { overflow-x: auto; -webkit-overflow-scrolling: touch; }
/* Kopf-Zone: Toenung + kraeftige Abschluss-Linie (Komponenten-Standard
   ZWEI Linien-Stufen: 1px --border Zeilen-Hairlines, 2px --border-input
   Kopf-Abschluss); Sortier-Koepfe sind Links mit aria-sort am th */
.tableview-head th { font-weight: 600; text-align: left; vertical-align: bottom; padding: 0.5rem 0.75rem; background: var(--surface-filter); border-bottom: 2px solid var(--border-input); }
/* Kopf-Ausrichtung (Runde 2): Koepfe OHNE Sortier-Symbol (z. B. Bild/Masse)
   erben die Metrik der Sortier-Links (inline-flex + 44-px-Zeile) - alle
   Ueberschriften einer Kopfzeile sitzen auf derselben Grundlinie */
.tableview-title { display: inline-flex; align-items: center; min-height: 2.75rem; }
.tableview-sortlink { display: inline-flex; align-items: center; gap: 0.25rem; min-height: 2.75rem; color: var(--text-primary); text-decoration: none; }
/* Sortier-Symbol IMMER sichtbar (Polish 02.08.): unsortiert = gedimmtes
   Doppel-Chevron (Tabler selector), aktiv = Richtungs-Chevron in Akzent */
.tableview-sortdir { display: inline-flex; }
.tableview-sortdir svg { width: 1rem; height: 1rem; color: var(--text-muted); }
.tableview-sort-active .tableview-sortdir svg { color: var(--accent-strong); }
.tableview-empty { color: var(--text-secondary); text-align: center; padding: 1.5rem 0.75rem; }
/* Steuerleiste unter der Tabelle: Bereich links, Sprung-Buttons rechts */
.tableview-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1rem; margin-top: 0.75rem; }
.tableview-reset { color: var(--sea); }
.tableview-pagination { display: flex; align-items: center; gap: 0.5rem; margin-left: auto; color: var(--text-secondary); }
.tableview-range { color: var(--text-secondary); }
.tableview-jump { display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; padding: 0.25rem; }
.tableview-jump svg { width: 1.25rem; height: 1.25rem; }
/* sichtbar-inaktiv (dokumentierte disabled-Ausnahme, Muster add_rows_button) */
.tableview-jump[disabled] { opacity: 0.45; cursor: default; }
/* CSV-Export-Menue (Runde 2): Icon-Button (Standard ADR 113) + natives
   details-Menue mit zwei Optionen; oeffnet nach OBEN (Steuerleiste ist die
   letzte Zeile der Komponente - kein Seiten-Overflow) */
.tableview-export { position: relative; }
.tableview-export summary { list-style: none; }
.tableview-export summary::-webkit-details-marker { display: none; }
.tableview-export-button { cursor: pointer; }
.tableview-export-button svg { width: 20px; height: 20px; }
@media (hover: hover) { .tableview-export-button:hover { background: var(--surface-filter); border-radius: 6px; } }
.tableview-export-button:active { background: var(--surface-filter); border-radius: 6px; }
.tableview-export-menu { position: absolute; right: 0; bottom: calc(100% + 0.25rem); min-width: 16rem; padding: 0.25rem; background: var(--surface-card); border: 1px solid var(--border-strong); border-radius: 8px; box-shadow: 0 1px 4px rgb(0 0 0 / 0.08); display: grid; z-index: 5; }
.tableview-export-menu a { display: flex; align-items: center; min-height: 2.75rem; padding: 0.25rem 0.75rem; border-radius: 6px; color: var(--text-primary); text-decoration: none; white-space: nowrap; }
@media (hover: hover) { .tableview-export-menu a:hover { background: var(--surface-filter); } }

.site-footer {
  border-top: 1px solid var(--border);
  padding: 1rem 0; /* horizontal uebernimmt der content-container (ADR 112) */
  color: var(--text-secondary);
  font-size: 0.875rem;
}
.site-footer a { color: var(--text-secondary); }

/* Formularfelder hell (ADR 79): weißer Grund, Rahmen --border-strong, Radius 6 px.
   Die Typenliste deckt JEDEN gerenderten Eingabetyp der Plattform - Wache
   test_every_input_type_is_component_styled hält CSS und Formulare deckungsgleich. */
input[type="text"], input[type="email"], input[type="password"], input[type="number"],
input[type="date"], input[type="time"], input[type="url"], select, textarea {
  background: var(--surface-card);
  border: 1px solid var(--border-strong);
  border-radius: 6px;
  padding: 0.5rem 0.625rem;
  font: inherit;
  font-size: var(--control-font-min);
  color: var(--text-primary);
  width: 100%;
  min-height: var(--control-height-min);
}
/* Datums-/Zeitwerte linksbuendig (A84): WebKit/iOS zentriert den Wert
   nativer date/time-Picker, waehrend Text-Inputs und Selects links stehen
   (EK-Sichtung 02.09. iPhone: Vor-Ort-Abschluss "Unterschrieben am",
   Vertragsdetail "Mietbeginn"). text-align am Input allein greift in WebKit
   NICHT - der Wert lebt im Shadow-Teil ::-webkit-date-and-time-value, der
   seine eigene Ausrichtung braucht (deshalb auch die A49-Zeile der
   Sperr-Variante mobil wirkungslos). EINE Stelle fuer ALLE Datums-/
   Zeitfelder (Board-Masken, Split-Felder, Tableview-Datumsbereiche,
   Styleguide); zwei Anweisungen, weil ein unbekanntes Pseudo-Element die
   ganze Selektorliste ungueltig machen wuerde. Wache
   test_date_time_values_align_left. */
input[type="date"], input[type="time"] { text-align: left; }
input[type="date"]::-webkit-date-and-time-value,
input[type="time"]::-webkit-date-and-time-value { text-align: left; }
textarea { min-height: 6rem; }
select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 2.25rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%231F2924' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6l6 -6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.625rem center;
}
/* Radio-Gruppen (Zahlungsart): touch-taugliche Optionszeilen in der Feld-Komponente */
.field label:has(input[type="radio"]) { display: flex; align-items: center; gap: 0.5rem; font-weight: 400; min-height: 2.75rem; margin-bottom: 0; }
.field input[type="radio"] { width: auto; min-height: auto; accent-color: var(--accent); }

/* Formular-Raster (Mobile-first: eine Spalte; ab Tablet mehrspaltig) */
form fieldset { border: 1px solid var(--border-strong); border-radius: 8px; padding: 0.75rem 1rem 1rem; margin: 1rem 0; }
form legend { font-weight: 600; padding: 0 0.25rem; }
.form-row { display: grid; gap: 0 1rem; }
@media (min-width: 768px) {
  /* Volle A14-Anatomie ab Tablet (A49): der Bestand vor der mobilen
     Verdichtung - Betreff, Empfaenger und Uhrzeit stehen wieder in der
     zugeklappten Zeile, der mobile Nachreich-Block entfaellt. */
  .board-message-subject { display: block; }
  details.board-message .board-message-recipient { display: block; }
  .board-message-time { display: inline; }
  .board-message-to { display: inline; }
  .board-message-title { flex-wrap: nowrap; }
  .board-message-title strong { white-space: nowrap; }
  .board-message-mobile-facts { display: none; }
}

@media (min-width: 768px) {
  .form-row-2 { grid-template-columns: 1fr 1fr; }
  .form-row-3 { grid-template-columns: 1fr 1fr 1fr; }
  .form-row-street { grid-template-columns: 2fr 1fr 1fr; } /* breit/schmal/schmal */
  .form-row-city { grid-template-columns: 1fr 2fr; } /* schmal/breit */
}

/* Checkbox-Standard (ADR 79; Haken-Optik + Zeilen-Layout 24.07.): niemals
   Browser-/Host-Default. Checkbox-Zeilen sind 44-px-Ziele und stehen IMMER
   untereinander (Desktop wie mobil - kein Breakpoint-Sonderfall, z. B. die
   drei Rückruf-Zeitfenster). */
.checkbox { display: flex; align-items: center; gap: 0.5rem; min-height: 2.75rem; }
.checkbox input[type="checkbox"] {
  appearance: none;
  width: 1.125rem;
  height: 1.125rem;
  flex-shrink: 0;
  background: var(--surface-card);
  border: 1px solid var(--border-input);
  border-radius: 4px;
  vertical-align: -0.2rem;
}
/* Angehakt: Akzent-Füllung MIT echtem weißen Haken (vendored check-Pfad als
   Daten-URI - kein Font-Trick; Gate-Paar Haken/Füllung >= 3:1) */
.checkbox input[type="checkbox"]:checked {
  background-color: var(--accent);
  border-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12l5 5l10 -10'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 0.875rem;
}

/* Button (nie disabled – Formular-Muster frontend.md Abschnitt 7).
   Der No-JS-Auswahl-Knopf der FILE-Variante (::file-selector-button, ADR 136)
   steht MIT in diesen Gruppen: eine Button-Definition, keine Kopie – die
   Pseudo-Element-Selektoren sind ab der :has()-Baseline des Bestands sicher. */
.button, .field-file input[type="file"]::file-selector-button {
  display: inline-block;
  background: var(--accent-strong);
  color: #FFFFFF;
  font-weight: 600;
  border: 0;
  border-radius: 6px;
  padding: 0.625rem 1rem;
  min-height: var(--control-height-min);
  cursor: pointer;
  font-size: var(--control-font-min);
}
/* Button-Hover (Mini-Fix 21.07.): das Hover-Signal ist ein FUELLTON-WECHSEL,
   nie eine Umrandung - der Ring bleibt das Tastatur-Signal. EINE Definition je
   Button-Art: gefuellt dunkelt die Fuellung ab, Outline erhaelt die dezente
   Flaechen-Toenung (Schrift 4,95:1, Kontur >= 3:1 auf der Toenung).
   Hover nur bei (hover: hover); Touch behaelt den Druck-Zustand. */
@media (hover: hover) {
  .button:not(:disabled):hover { background: var(--accent-hover); }
  .button-secondary:not(:disabled):hover,
  .field-file input[type="file"]::file-selector-button:hover { background: var(--surface-filter); }
}
.button:not(:disabled):active { background: var(--accent-hover); }
.button-secondary:not(:disabled):active { background: var(--surface-filter); }
.button-secondary, .field-file input[type="file"]::file-selector-button { background: transparent; color: var(--accent-strong); border: 1px solid var(--accent-strong); }
a.button { text-decoration: none; }
/* Destruktiv-Buttons (ADR 129/145): Rot-Token state-error - "Terrakotta =
   Handeln, Rot = Zerstoeren". Stehen NACH der Button-Basis (Kaskaden-Fix
   ADR 145: vorher verlor button-danger-filled gegen die spaeter definierte
   .button-Fuellung und rendete Terrakotta - latenter Alt-Befund der
   Dialog-Buttons). Gefuellt = der EINE Loeschen-Button der Aktions-Leiste
   + Dialog-Bestaetigungen; Outline = Zeilen-Trigger (Position loeschen). */
.button-danger { background: transparent; color: var(--state-error); border: 1px solid var(--state-error); }
.button-danger-filled { background: var(--state-error); border: 1px solid var(--state-error); color: #FFFFFF; }
@media (hover: hover) {
  .button-danger:not(:disabled):hover { background: var(--state-error-bg); }
  .button-danger-filled:not(:disabled):hover { background: var(--state-error-text); }
}
.button-danger:not(:disabled):active { background: var(--state-error-bg); }
.button-danger-filled:not(:disabled):active { background: var(--state-error-text); }
/* Hover-Token-PAAR gedrueckter Toggles (ADR 170, Befund Rechner-Buttons:
   der Outline-Hover hellte die Flaeche auf, die Schrift blieb weiss - axe
   prueft nur den Ruhezustand). REGEL: ein Zustands-Modifier, der die
   Flaeche fuellt, bringt sein Hover-PAAR (Flaeche+Schrift zusammen) mit -
   hier als Varianten-Regel fuer ALLE gedrueckten Buttons, kein
   Einzel-Button-CSS; Wache: Kontrast-Gate-Paare + Selektor-Abgleich. */
@media (hover: hover) {
  .button[aria-pressed="true"]:not(:disabled):hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #FFFFFF; }
}
.button[aria-pressed="true"]:not(:disabled):active { background: var(--accent-hover); border-color: var(--accent-hover); color: #FFFFFF; }
/* Zustands-Buttons sichtbar-inaktiv (dokumentierte disabled-Ausnahme, ADR 88 –
   Muster des Rufnummern-Add-Buttons) */
.button:disabled { opacity: 0.45; cursor: default; }
/* FILE-Trigger im Sperren-Zustand (O8, ADR 227): Zweit-Label des
   disabled inputs - dieselbe Disabled-Optik, keine Klick-Flaeche */
.field-file-trigger-disabled { opacity: 0.45; cursor: default; pointer-events: none; }

/* Badges */
.badge { display: inline-block; border-radius: 999px; padding: 0.125rem 0.625rem; font-size: 0.8125rem; }
.badge-neutral { background: var(--neutral-badge-bg); color: var(--neutral-badge-text); }
.badge-accent { background: var(--accent-badge-bg); color: var(--accent-badge-text); }
.badge-sea { background: var(--sea-badge-bg); color: var(--sea-badge-text); }
.badge-amber { background: var(--amber-badge-bg); color: var(--amber-badge-text); }

/* Feld-Komponente */
.field { margin: 0 0 1rem; }
.field label { display: block; font-weight: 600; margin-bottom: 0.25rem; }
/* Inset-Label (revidierter Feldkomponenten-Standard, 19.07.): echtes <label> im
   Feld, verkleinert bei Fokus/Inhalt an den Innenrand; NIE placeholder-als-Label.
   Markup-Reihenfolge Widget->Label macht es CSS-only ohne :has moeglich. */
.field-inset { position: relative; }
.field-inset > label {
  position: absolute; left: 0.8rem; top: 0.7rem; margin: 0; font-weight: 400;
  color: var(--text-secondary); pointer-events: none;
  transition: top 120ms ease-out, font-size 120ms ease-out;
}
.field-inset > input:focus ~ label,
.field-inset > input:not(:placeholder-shown) ~ label,
.field-inset > textarea:focus ~ label,
.field-inset > textarea:not(:placeholder-shown) ~ label,
.field-inset.field-static-label > label { top: 0.25rem; font-size: 0.6875rem; }
.field-inset > input, .field-inset > select, .field-inset > textarea { padding-top: 1.125rem; padding-bottom: 0.25rem; }
.field-inset > select { padding-right: 2.25rem; }
@media (prefers-reduced-motion: reduce) { .field-inset > label { transition: none; } }
/* Komponenten-Variante field-compact (ADR 88): Breite am Inhalt orientiert
   (Inset-Label + Wert + Chevron), nicht an der Sektionsbreite; mobil volle Breite */
/* Gesperrte Felder (A47/ADR 296): NICHT editierbar sieht auch so aus -
   grauer Grund aus dem Token-Bestand (--surface-filter, dieselbe Flaeche
   wie inaktive Listen-Zeilen), gedaempfte Schrift, getoenter Rahmen und
   KEIN aktiver Fokus-Rahmen. Rein visuell: readonly-Felder bleiben
   fokussierbar und vorlesbar (WCAG-Bestand) - deshalb behaelt der
   Tastatur-Fokus seinen sichtbaren Ring (:focus-visible unten), nur der
   Aktiv-Zustand der Eingabe entfaellt. Kontrast --text-secondary auf
   --surface-filter bleibt ueber AA. EINE Regel fuer Portal UND Board. */
.field-locked > input, .field-locked > select, .field-locked > textarea {
  background: var(--surface-filter);
  border-color: var(--border-input-tinted);
  color: var(--text-secondary);
  /* Ausrichtung EXPLIZIT (A49): der Wert steht linksbuendig wie in
     aktiven Feldern. Ohne diese Zeile zentrierte der Browser den Wert
     gesperrter date-Felder (EK-Befund 30.08. am Mietbeginn, mobil
     sichtbar) - der UA-Default fuer den disabled-Picker weicht von der
     Feld-Optik ab. Die Regel sitzt in DER Sperr-Gruppe (A47/ADR 296),
     nicht als zweite Regel am Ort. */
  text-align: left;
}
.field-locked > input:focus, .field-locked > select:focus,
.field-locked > textarea:focus {
  border-color: var(--border-input-tinted);
  box-shadow: none;
}
.field-locked > input:focus-visible, .field-locked > select:focus-visible,
.field-locked > textarea:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 2px;
}
.field-locked > label { color: var(--text-secondary); }

.field-compact { display: inline-block; }
.field-compact > input, .field-compact > select { width: auto; min-width: 11rem; }
@media (max-width: 767px) {
  .field-compact { display: block; }
  .field-compact > input, .field-compact > select { width: 100%; }
}
/* FILE-Variante der Feld-Komponente (ADR 136): der native input bleibt die
   Mechanik. No-JS: der input selbst rendert sichtbar in Standard-Maßen, sein
   Knopf läuft über ::file-selector-button in den Button-Gruppen oben mit
   (ehrlicher nativer Status samt Systemtext). Mit JS (html.js, ADR 104):
   input sr-only-versteckt aber fokussierbar, Knopf = Label-for in der
   Button-Sprache, Status-Text in Standard-Textgröße; der Fokus-Ring wandert
   per Geschwister-Selektor auf den Knopf (Muster phone-type-option). */
.field-file-control { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.field-file input[type="file"] { width: 100%; font-size: var(--control-font-min); color: var(--text-secondary); }
html.js .field-file input[type="file"] { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
html.no-js .field-file-trigger, html.no-js .field-file-status { display: none; }
/* Zustands-Logik (ADR 143): das Server-Markup traegt hidden je Zustand -
   hidden gewinnt hier IMMER gegen die eigenen display-Regeln (flex-Falle);
   einzige Ausnahme ist der dokumentierte No-JS-Degradationspfad darunter */
.field-file-present[hidden], .field-file-pending[hidden], .field-file-control[hidden] { display: none; }
/* No-JS-Degradationspfad (ADR 143, dokumentiert in frontend.md): ohne JS
   zeigt die Variante IMMER den nativen input (auch wenn der Zustand a ihn
   per hidden zurueckhaelt) plus die gestylte Entfernen-Checkbox; die
   JS-Aktionen Muelleimer/Hinweis+Rueckgaengig bleiben versteckt */
html.no-js .field-file-control[hidden] { display: flex; }
html.no-js .field-file-remove, html.no-js .field-file-pending { display: none; }
html.js .field-file-fallback { display: none; }
/* .field label setzt block/Abstand - der Knopf-Label bleibt Button-Optik */
.field .field-file-trigger { display: inline-block; margin-bottom: 0; }
.field-file input[type="file"]:focus-visible ~ .field-file-trigger { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.field-file-status { color: var(--text-secondary); font-size: var(--control-font-min); }
/* Bestands-Anzeige der file-Variante (Runde 3, ADR 142): Vorschau mit
   FESTER Maximalgroesse (240-px-Kante, object-fit - Hochkant-Originale
   sprengen nie wieder die Maske), Datei-Zeile, Entfernen-Toggle */
.field-file-preview-link { display: inline-block; }
.field-file-preview { display: block; max-width: 240px; max-height: 240px; width: auto; height: auto; object-fit: contain; border: 1px solid var(--border); border-radius: 6px; margin: 0.25rem 0; }
.field-file-current { display: flex; align-items: center; flex-wrap: wrap; gap: 0.25rem; margin: 0.25rem 0; color: var(--text-secondary); overflow-wrap: anywhere; }
/* Muelleimer = EINZIGE Aktion im Zustand "Datei vorhanden" (ADR 143):
   Icon-Aktions-Klasse (Basis .icon-button, 44-px-Ziel), destruktiv nach
   Loesch-Icon-Standard (Hover/Aktiv Rot-Token state-error, ADR 145) */
@media (hover: hover) {
  .field-file-remove:hover { color: var(--state-error); background: var(--surface-filter); border-radius: 6px; }
}
.field-file-remove:active { color: var(--state-error); background: var(--surface-filter); border-radius: 6px; }
/* Vormerkungs-Hinweis + Rueckgaengig-Textlink (Zustand b): der Hinweis
   spricht Destruktiv-Rot, Rueckgaengig ist ein Text-Button in Link-Optik
   (echtes button-Element - Tastatur/Screenreader, kein Navigations-<a>) */
.field-file-pending { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin: 0.25rem 0; color: var(--state-error-text); }
.field-file-restore { background: none; border: 0; padding: 0; cursor: pointer; color: var(--sea); text-decoration: underline; font-size: var(--control-font-min); min-height: var(--control-height-min); display: inline-flex; align-items: center; }
/* No-JS-Fallback: echte -clear-Checkbox als Destruktiv-Toggle (vormals
   field-file-remove, Runde 3) - mit JS unsichtbar, Zustands-Speicher bleibt */
.field-file-fallback { display: inline-flex; align-items: center; gap: 0.5rem; min-height: var(--control-height-min); cursor: pointer; }
.field-file-fallback input[type="checkbox"] { position: absolute; opacity: 0; width: 1px; height: 1px; }
.field-file-fallback-action { display: inline-flex; align-items: center; min-height: var(--control-height-min); padding: 0.25rem 0.875rem; border: 1px solid var(--state-error); border-radius: 6px; color: var(--state-error); font-size: var(--control-font-min); }
.field-file-fallback-state { display: none; color: var(--state-error-text); }
.field-file-fallback:has(input:checked) .field-file-fallback-action { background: var(--state-error-bg); }
.field-file-fallback:has(input:checked) .field-file-fallback-state { display: inline; }
.field-file-fallback:has(input:focus-visible) .field-file-fallback-action { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
@media (hover: hover) { .field-file-fallback:not(:has(input:checked)):hover .field-file-fallback-action { background: var(--state-error-bg); } }
/* Vorschau-Klappbalken der Seitentexte-Maske (ADR 144) - Balken-Muster der
   Tableview-Filter (getoenter Kopf, Chevron dreht bei [open]); der Zustand
   ist FLUECHTIG (bewusst kein localStorage, Default zu). Aktualisieren =
   Text-Button in Link-Optik NUR im aufgeklappten Zustand. No-JS: reines
   Enhancement - der Balken entfaellt komplett. Der Rahmen zeigt den
   Website-Kontext-Look: die Rechtsseiten-Styles (.legal-toc/.legal-content,
   Lesebreite 70ch) gelten unveraendert - eine Wahrheit, keine Kopien. */
.pagetext-preview { margin: 1rem 0; }
html.no-js .pagetext-preview { display: none; }
.pagetext-preview-head { display: flex; align-items: center; gap: 0.375rem; min-height: 2.75rem; padding: 0.375rem 0.625rem; border-radius: 8px; background: var(--surface-filter); cursor: pointer; list-style: none; }
.pagetext-preview-head::-webkit-details-marker { display: none; }
.pagetext-preview-title { font-weight: 600; }
.pagetext-preview-refresh { background: none; border: 0; padding: 0 0.375rem; cursor: pointer; color: var(--sea); text-decoration: underline; font-size: var(--control-font-min); min-height: var(--control-height-min); display: none; align-items: center; }
.pagetext-preview[open] .pagetext-preview-refresh { display: inline-flex; }
.pagetext-preview-chevron { margin-left: auto; display: inline-flex; }
.pagetext-preview-chevron svg { width: 1rem; height: 1rem; color: var(--text-muted); transition: transform 120ms ease-out; }
.pagetext-preview[open] .pagetext-preview-chevron svg { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .pagetext-preview-chevron svg { transition: none; } }
.pagetext-preview-frame { border: 1px solid var(--border); border-radius: 8px; padding: 1rem; margin-top: 0.5rem; background: var(--surface-card); }
.pagetext-preview-note { margin: 0 0 0.75rem; color: var(--text-secondary); }
.pagetext-preview-spinner { display: inline-flex; }
/* Split-Feld Datum+Uhrzeit (ADR 135): zwei Komponenten-Felder nebeneinander -
   die kurzen nativen Picker passen auch mobil zweispaltig (44-px-Ziele) */
.field-split { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
.field-split > .field-help, .field-split > .field-error { grid-column: 1 / -1; }
.field-help { display: block; color: var(--text-secondary); font-size: 0.875rem; }
.field-error { display: block; color: var(--state-error); font-size: 0.875rem; }
/* Zeichenzaehler (Kontakt v2, ADR 103): dezent rechts unter der Textarea;
   bewusst KEINE Fehlerfaerbung - der Zaehler informiert, das Feld traegt
   den Zustand (has-error faerbt nur den Rahmen) */
.field-counter { display: block; text-align: right; color: var(--text-secondary); font-size: 0.875rem; }
/* No-JS-Fallback-Standard (ADR 104): html startet als .no-js, der EINE
   erlaubte Inline-Zweizeiler im head tauscht VOR dem First Paint auf .js -
   .js-only-hidden-Elemente (Fallback-Submits) sind mit JS von Anfang an
   unsichtbar (kein Aufblitzen, kein Insel-Timing; die Klasse liegt am
   html-Element und ist damit swap-fest). Faellt das Skript aus, bleibt
   .no-js stehen und die Fallbacke sind voll da (Fail-open). */
html.js .js-only-hidden { display: none; }
html.no-js .js-only-hidden { display: revert; } /* explizit: ohne JS voll da */
/* Gegenstueck (Punkt 16, ADR 108): reine JS-Enhancements (Carousel-Pfeile/
   Punkte) sind OHNE JS ausgeblendet - dieselbe html-Klassen-Mechanik,
   Fail-open bleibt gewahrt (ohne JS fehlt nur Komfort, nie Funktion) */
html.no-js .no-js-hidden { display: none; }
/* Enter-Standardknopf: der ERSTE (unsichtbare, neutrale) Submit faengt die
   implizite Enter-Absendung - sonst kaperte der No-JS-Fallback-Submit
   ("Anliegen uebernehmen") sie und wuerfe Eingaben weg (ADR 104) */
.enter-default-submit { display: none; }
/* No-JS-Kategorie-Wechsel: sichtbar nur ohne JS (js-only-hidden, ADR 104) */
.category-apply { margin-bottom: 1rem; }
.field.has-error input, .field.has-error select, .field.has-error textarea { border-color: var(--state-error); }
/* Gruppen-Fehler an Checkboxen (Zeitfenster-Regel): die gezeichnete Box traegt
   den Fehlerrahmen ueber aria-invalid (Checkboxen haben keinen .field-Wrapper);
   Farbpaar state-error/surface-card steht im Kontrast-Gate */
.checkbox input[type="checkbox"][aria-invalid="true"] { border-color: var(--state-error); }

/* Fehlersammlung mit Sprunglinks */
.error-summary {
  border: 1px solid var(--state-error);
  border-radius: 6px;
  background: var(--state-error-bg);
  color: var(--state-error-text);
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
}
.error-summary a { color: var(--state-error-text); }

/* Flash: manuell schließbar, kein Auto-Verschwinden (Website/Portal) */
.flash-area { margin-bottom: 1rem; }
.flash { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface-card); padding: 0.75rem 1rem; margin-bottom: 1rem; }
.flash-success { border-color: var(--state-success); background: var(--state-success-bg); color: var(--state-success-text); }
.flash-info { border-color: var(--border-strong); }
.flash-error { border-color: var(--state-error); background: var(--state-error-bg); color: var(--state-error-text); }
.flash-close { float: right; background: none; border: 0; font-size: 1rem; cursor: pointer; color: inherit; }

/* Startseite (seiten.md 4.1, ADR 79). Vollbreit seit hero-full-bleed
   27.07.2026 (ADR-112-Nachtrag): die Flaeche laeuft per .full-bleed-Utility
   Kante zu Kante, der Inhalt liegt im verschachtelten content-container -
   die frueheren Negativ-Seiten-Margins (-1.5rem, Vor-ADR-112-Bestand: sie
   fuellten nur das Containerpadding) sind entfallen. Kein margin-Shorthand:
   die Seiten-Margins gehoeren der Utility. */
.hero {
  position: relative;
  background: var(--surface-section);
  padding: 3rem 0 5rem; /* horizontal buendelt der innere content-container */
  margin-top: -1.5rem; /* an die Header-Hairline heranziehen (main-Padding) */
  margin-bottom: 2rem;
  overflow: hidden;
}
/* Marken-Zeile ueber dem Claim (A3, ersetzt die Ortsmarke "PLAU AM SEE"):
   dieselbe Position und Groesse wie zuvor, aber ein SATZ statt eines
   Ortsnamens - deshalb OHNE Versalien-Sperrung (letter-spacing 0.1em war
   die Versal-Laufweite und ist mit den Versalien entfallen). Die Farbe
   traegt nicht mehr die Zeile, sondern die beiden Spans: Logo-Blau und
   Logo-Orange aus den BESTEHENDEN Tokens (kein dritter Farbwert). Beide
   Paare auf surface-section stehen bereits im Kontrast-Gate. */
/* Marken-Zeile (A13, EK-Entscheid nach Sichtung: Stufe b - a war zu
   klein): deutlich groesser als der Fliesstext, klar unter dem H1-Claim;
   bricht auch mobil (390px) nicht um (Sicht-Smoke misst es).
   Farben/Zwei-Ton unveraendert. */
.eyebrow { font-size: 1.25rem; font-weight: 600; margin: 0 0 0.25rem; }
.eyebrow-brand { color: var(--sea); }
.eyebrow-claim { color: var(--accent-strong); }
.hero h1 { margin: 0.25rem 0 0.75rem; font-size: 2rem; }
.hero-intro { color: var(--text-secondary); max-width: 36rem; }
.hero-actions { display: flex; align-items: center; gap: 1rem; position: relative; z-index: 1; }
.hero-counter { color: var(--text-secondary); }

/* Sternchen-Fussnote des Ab-Preises (A50, EK-Entscheid 30.08.): dezent unter dem
   Hero-Intro - kleiner, Sekundaerton, ohne die Trennlinie der
   offer-footnote (die gehoert an den Seitenfuss, nicht in den Hero). */
.hero-footnote { color: var(--text-secondary); font-size: 0.875rem; margin-top: 0.75rem; }.hero-wave { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; height: 3rem; display: block; }

.teaser-section, .steps-section { margin: 2.5rem 0; }
/* Kachel-Raster 2x2 (O2, ADR 219 - revidiert das auto-fit-3+1): EIN
   geteilter Baustein fuer "Darum Elde-Box" UND "In vier Schritten"
   (Regel 34) - ab Desktop zwei Kacheln je Zeile (groessere Kacheln),
   mobil einspaltig (Bestands-Breakpoint 767px) */
.teaser-grid, .steps-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; grid-template-columns: repeat(2, 1fr); }
@media (max-width: 767px) {
  .teaser-grid, .steps-grid { grid-template-columns: 1fr; }
}
.teaser-card, .step-card { background: var(--surface-card); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; }
/* Icon-Kacheln "Darum Elde-Box" (Marketing-Politur 21.07.): Outline-Icon oben,
   Ueberschrift, Subtitle - linksbuendig, nicht-klickbar, daher KEIN Hover;
   Icon einfarbig text-primary (zweifarbiger Aufbau ginge nur mit
   Icon-Manipulation - bewusst nicht) */
.teaser-icon { display: block; color: var(--text-primary); margin-bottom: 0.5rem; }
.teaser-icon svg { width: 30px; height: 30px; }
.teaser-card h3 { margin: 0 0 0.25rem; font-size: 1rem; }
.teaser-card p { margin: 0; color: var(--text-secondary); }
.step-card h3 { margin: 0.5rem 0 0.25rem; }
.step-card p { margin: 0; color: var(--text-secondary); }
/* Zentrierte Sektion (wiederverwendbare Utility, frontend.md): Grundlinie
   mittig, Sektions-Ueberschrift linksbuendig; die Kachel-Anatomie darunter
   ueberschreibt kartenweise (Variante B) */
.section-centered { text-align: center; }
.section-centered > h2 { text-align: left; }
/* Kachel-Anatomie Variante B (O3, ADR-219-Praezisierung - revidiert die
   zentrierte 22rem-Kachel der vierten Fassung): Kopfzeile aus Icon (Darum)
   bzw. orangem Nummern-Punkt (Schritte) + Titel NEBENEINANDER,
   linksbuendig; Fliesstext darunter linksbuendig. EIN Baustein fuer BEIDE
   Sektionen (Regel 34) - die Kopfzeile entsteht per Karten-Grid aus dem
   bestehenden Markup (span + h3 + p, kein Wrapper); die Breitkachel
   fuellt ihre Rasterspalte (die 22rem-Zentrierung stammte aus der
   Drei-Spalten-Zeit), das Kachel-Gap bleibt der etablierte 1rem-Wert. */
.section-centered .step-card, .section-centered .teaser-card {
  text-align: left;
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: 0.5rem 0.75rem;
}
.section-centered .step-card p, .section-centered .teaser-card p { grid-column: 1 / -1; }
.section-centered .step-card h3, .section-centered .teaser-card h3 { margin: 0; }
.section-centered .step-number { display: flex; margin: 0; }
.section-centered .teaser-icon { margin: 0; }
.section-centered .teaser-icon svg { display: block; }
/* Sektion "Container-Dorf" (25.07.2026, Carousel-Ausbau Punkt 16/ADR 108):
   Carousel und Text laufen auf der Hero-Inhaltsbreite (= main-Breite, EINE
   Container-Definition ohne Sonder-Wert); der Absatz folgt der
   Zeilenlaengen-Klausel (> ~90 Zeichen -> ~80ch, links buendig) */
.village-section { margin: 2.5rem 0; }
.village-section p { color: var(--text-secondary); max-width: 80ch; }
/* A80: Sektionen "Selfstorage" + "Haeufige Fragen" vor dem CTA-Band - der
   Absatz laeuft im Hausstil der Text-Sektion (identische Werte, kein neuer
   Look); die Startseiten-FAQ traegt die faq-group-Karten der FAQ-Seite */
.outro-section, .home-faq-section { margin: 2.5rem 0; }
.outro-section p { color: var(--text-secondary); max-width: 80ch; }
/* Bilder-Carousel: CSS-Scroll-Snap ohne Bibliothek, KEIN Autoplay
   (A11y-Entscheid ADR 108); Wischen (Touch/Trackpad) und Tastatur-Scroll im
   fokussierten Container sind die No-JS-Wahrheit, Pfeile/Punkte Enhancement */
/* Carousel-Bedienung v2 (ADR 114, Kino-Slider-Muster): Pfeile und Indikator
   liegen als OVERLAY auf dem Bild - die Buehne traegt die Positionierung */
.village-stage { position: relative; margin: 0 0 1rem; }
.village-carousel { display: flex; gap: 1rem; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; -webkit-overflow-scrolling: touch; margin: 0; scrollbar-width: none; }
/* Scrollbalken bewusst versteckt (Nachtrag 25.07.2026): Wischen, Pfeile,
   Punkte und Tastatur-Scroll sind vollwertige Bedienwege (frontend.md) */
.village-carousel::-webkit-scrollbar { display: none; }
.village-slide { flex: 0 0 100%; scroll-snap-align: center; }
/* Pfeile: Kreis-Layer vertikal mittig, 12 px Randabstand, 44-px-Ziele -
   weisses Chevron IMMER auf der eigenen Kontrastflaeche (Overlay-Standard,
   Paar im Kontrast-Gate), nie direkt auf dem Foto */
.carousel-arrow { position: absolute; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; background: var(--overlay-scrim); border: 0; border-radius: 50%; color: #FFFFFF; cursor: pointer; }
.carousel-arrow-prev { left: 0.75rem; }
.carousel-arrow-next { right: 0.75rem; }
.carousel-arrow svg { width: 24px; height: 24px; }
@media (hover: hover) {
  .carousel-arrow:hover { background: var(--overlay-scrim-hover); }
}
.carousel-arrow:active { background: var(--overlay-scrim-hover); }
/* Indikator unten rechts IM Bild: weiche Halbton-Pille (kein harter Kasten)
   als Kontrastgrund fuer die Punkte - lesbar auch auf hellen Motiven */
.carousel-indicator { position: absolute; right: 0.75rem; bottom: 0.75rem; display: flex; align-items: center; padding: 0.375rem 0.625rem; border-radius: 999px; background: var(--overlay-scrim); }
/* Punkt-Indikatoren: reine Anzeige (aria-hidden, von der Insel gebaut);
   aktiv = Weiss gefuellt, inaktiv = Weiss 50 % */
.carousel-dots { display: inline-flex; gap: 0.5rem; }
.carousel-dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: rgba(255, 255, 255, 0.5); }
.carousel-dot-active { background: #FFFFFF; }
/* Foto-Platzhalter im 16:9-Format (width/height-Attribute + height:auto =
   kein Layout-Sprung); gestrichelte Flaeche im selection-empty-Muster,
   Hinweistext dezent (text-secondary bleibt das Gate-geprüfte Paar auf
   surface-section); echte Fotos erben die Slide-Breite */
.village-placeholder { display: block; width: 100%; height: auto; border: 2px dashed var(--border-input); border-radius: 6px; margin: 0; }
.village-slide img { display: block; width: 100%; height: auto; border-radius: 6px; }
/* Einzelbild-Zustand (ADR 130): stehendes Bild ohne Pfeile/Indikator */
.village-single img { display: block; width: 100%; height: auto; border-radius: 6px; }
.village-placeholder-area { fill: var(--surface-section); }
.village-placeholder-note { fill: var(--text-secondary); font-size: 40px; }
.step-number {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; height: 2rem; border-radius: 50%;
  background: var(--accent-strong); color: #FFFFFF; font-weight: 600;
}
.cta-band { background: var(--surface-section); border-radius: 6px; padding: 1.5rem; margin-top: 2rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.cta-band p { margin: 0; font-weight: 600; }

/* Tarifseiten: Lageplan + Matrix (seiten.md 4.2/4.3, ADR 78/79) */
/* Plan-Scroller (Mobile-Standard): unter Tablet-Breite behält der Plan eine
   Mindestbreite mit 44-px-Spots und wird horizontal wischbar; die Legende
   steht außerhalb des Scrollers */
.plan-scroller { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.plan-scroll-hint { display: none; }
/* Anker-Chips (mobil): Sprungmarken in die eine Reihe (Token-Stil, 44-px-Ziele) */
.plan-jump { display: none; }
@media (max-width: 767px) {
  .plan-jump { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.5rem 0; }
  /* EINE durchgehende Reihe: Spots ≈ 48x84 px, Labels ≈ 15 px (ADR-84-Nachtrag revidiert) */
  .plan-scroller .site-plan { min-width: 1380px; }
  .plan-scroller { background:
    linear-gradient(to right, rgb(0 0 0 / 0.06), transparent 12px) left / 24px 100% no-repeat local,
    linear-gradient(to left, rgb(0 0 0 / 0.06), transparent 12px) right / 24px 100% no-repeat local;
  }
  .plan-scroll-hint { display: block; color: var(--text-secondary); font-size: 0.8125rem; margin: 0.25rem 0 0; }
}
.plan-chip { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0.25rem 0.875rem; border: 1px solid var(--border-strong); border-radius: 999px; background: var(--surface-card); color: var(--text-primary); text-decoration: none; font-size: 0.8125rem; }
/* Strom-Chip: ⚡ in der Plan-Stromfarbe, Text bleibt die Wahrheit */
.plan-chip svg { width: 1em; height: 1em; margin-right: 0.25em; color: var(--sea); }
.site-plan { width: 100%; height: auto; display: block; background: var(--surface-card); border: 1px solid var(--border); border-radius: 6px; }
.site-plan text { font-size: 10px; fill: var(--text-primary); }
.spot-free rect { fill: var(--plan-free); stroke: var(--border-input); }
/* Vermietet (A69/ADR 323): vollflaechig DEUTLICH dunkler, keine Schraffur;
   Kennung auf der dunklen Flaeche in text-primary (4,95:1) */
.spot-rented rect { fill: var(--plan-rented); stroke: none; }
.spot-rented text { fill: var(--text-primary); }
/* Reserviert (A69/ADR 323): helle Diagonal-Schraffur auf freiem Grund -
   das Pattern liegt EINMAL in den defs des Lageplan-Bausteins */
.spot-reserved rect { fill: url(#plan-reserved-hatch); stroke: var(--border-strong); }
.plan-hatch-ground { fill: var(--plan-free); }
.plan-hatch-line { stroke: var(--plan-hatch); stroke-width: 1.25; }
.spot-selected rect { fill: #FFFFFF; stroke: var(--accent); stroke-width: 2.5; }
.spot-dimmed { opacity: 0.35; }
/* Lageplan-Hover: SVG-Äquivalent (Rahmen-/Füllton-Anhebung); Auswahl-Orange
   bleibt dominant, der Fokus-Ring behält seinen eigenen Stil */
.site-plan rect { transition: fill 140ms ease-out, stroke 140ms ease-out; }
.site-plan a { cursor: pointer; }
.site-plan a:focus-visible .spot-free rect { fill: var(--surface-filter); }
/* Der Plan ist der zugängliche Pfad (ADR 84): sichtbarer Fokus-Stil auf den Spot-Links */
.site-plan a:focus-visible { outline: none; }
.site-plan a:focus-visible rect { stroke: var(--focus-ring); stroke-width: 2.5; stroke-dasharray: 3 2; }
/* Container-Legende (ADR 162): Kachel-Symbol + Legenden-/Listen-Zeile -
   dieselbe See-Farbe wie der fruehere Strom-Marker (Sicht unveraendert) */
.spot-legend { color: var(--sea); }
.legend-symbol svg, .board-legend-icon svg { width: 1em; height: 1em; vertical-align: -0.125em; color: var(--sea); }
.tariff-icon svg { width: 1.25em; height: 1.25em; vertical-align: -0.25em; }
.plan-access { fill: var(--text-secondary); font-size: 11px; }
.plan-legend { color: var(--text-secondary); font-size: 0.875rem; }
.plan-legend .legend-free::before, .plan-legend .legend-rented::before, .plan-legend .legend-selected::before, .plan-legend .legend-dimmed::before { content: ""; display: inline-block; width: 0.75em; height: 0.75em; margin-right: 0.35em; border-radius: 2px; }
.legend-free::before { background: var(--plan-free); border: 1px solid var(--border-input); }
/* Reserviert (A69/ADR 323): der Legenden-Chip ist ein Mini-SVG und
   konsumiert DASSELBE Schraffur-Pattern wie die Plan-Spots (ein
   Pflegeort; die frueheren eigenen Legenden-Farbwerte sind ausgebaut) */
.legend-reserved { white-space: nowrap; }
.legend-chip { width: 0.75em; height: 0.75em; margin-right: 0.35em; vertical-align: -0.05em; }
.legend-chip rect { fill: url(#plan-reserved-hatch); stroke: var(--border-strong); }
.legend-rented::before { background: var(--plan-rented); }
.legend-selected::before { background: #FFFFFF; border: 2px solid var(--accent); }
.legend-dimmed::before { background: #FFFFFF; border: 1px solid var(--border-input); opacity: 0.35; }

.tariff-grid { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); margin-bottom: 1.5rem; }
.tariff-card { background: var(--surface-card); border: 1px solid var(--border); border-radius: 6px; padding: 1rem; }
/* Ganzflächen-Link (Mobile-Standard): die Kachel selbst ist das <a> */
/* Flächen-Link-Regel (frontend.md): Karten-/Flächen-Links und ihr Inhalt sind
   NIE unterstrichen - unterstrichen sind ausschließlich Text-Links im Fließtext */
a.tariff-card, a.tariff-card * { text-decoration: none; }
a.tariff-card { display: block; color: inherit; }
.tariff-card, .site-plan a, .site-plan g[id], #tariffs, #site-plan, #kontaktformular { scroll-margin-top: 4.5rem; } /* Fragment-/Smart-Scroll-Ziele unterm Header */
.tariff-card h3 { margin: 0 0 0.25rem; color: var(--text-primary); }
.tariff-icon { color: var(--sea); }
.tariff-duration { margin: 0; color: var(--text-secondary); }
.tariff-subtitle { margin: 0.25rem 0 0; color: var(--text-secondary); }
.tariff-price { margin: 0.5rem 0 0; font-weight: 600; font-size: 1.25rem; }
/* Streichpreis-Anzeige (ADR 153): der rabattierte Preis behaelt die
   Preis-Hervorhebung der Kachel; Altpreis, Danach-Zeile und Gebuehren-Zeile
   stehen zurueckgenommen in text-secondary (Kontrast-Paar im Gate benannt) */
.tariff-price-old { color: var(--text-secondary); font-weight: 400; font-size: 0.875rem; }
/* Dokumentierte Ausnahme der Flaechen-Link-Regel (a.tariff-card * setzt
   text-decoration: none): line-through ist KEINE Unterstreichung - der
   Altpreis bleibt auch im Karten-Link sichtbar durchgestrichen */
a.tariff-card .tariff-price-old, .tariff-card .tariff-price-old { text-decoration: line-through; }
.tariff-discount-duration { margin: 0.25rem 0 0; color: var(--text-secondary); font-size: 0.875rem; }
.tariff-setup-fee { margin: 0.25rem 0 0; color: var(--text-secondary); font-size: 0.875rem; }
.tariff-counter { margin: 0.25rem 0 0; color: var(--text-secondary); font-size: 0.875rem; }
.tariff-group { border-top: 1px solid var(--border-strong); padding-top: 1rem; }

/* Matrix: gedimmt statt gesperrt – bleibt fokussierbar und klickbar (ADR 78) */
.matrix-dimmed { opacity: 0.45; }
/* Inaktive Kachel (ADR-88-Nachtrag Teil 2b): kein Link, kein Hover, cursor:default;
   der Warteliste-Textlink unter dem Kachelinhalt bleibt klar erkennbar */
.tariff-card-inactive { cursor: default; }
/* Link-Hierarchie Stufe 2 (prinzipien.md #33, ADR 102): Pfeil-Link fuer
   Seiten-Querverweise im Inhalt - blau, 600, arrow-right rechts, KEINE
   Unterstreichung im Ruhezustand; Hover: Unterstreichung + 2px-Pfeil-Schub
   (dokumentierte Regel-18-Ausnahme; reduced-motion: ohne Bewegung) */
/* display: inline statt inline-flex (A16): als Flex-Konstrukt lieferte das
   SVG (Unterkante) die Baseline und der zentrierte Text hob sich im
   Fliesstext ueber die Satz-Baseline. Echtes inline erbt Baseline UND
   Schriftgroesse des Satzes; das Icon haengt per vertical-align leicht
   unter die Baseline (optisch mittig zur Versalhoehe, Sichtabgleich). */
.arrow-link { display: inline; color: var(--sea); font-weight: 600; text-decoration: none; }
.arrow-link svg { width: 18px; height: 18px; vertical-align: -0.1875em; margin-right: 0.375rem; transition: transform 140ms ease-out; }
@media (max-width: 767px) {
  /* 44-px-Zeilenziel (Mobile-Standard): inline traegt kein min-height -
     padding-block weitet NUR die Trefferflaeche, nicht die Zeilenhoehe */
  .arrow-link { padding-block: 0.75rem; }
}
.matrix-dimmed .matrix-reason, .matrix-reason { opacity: 1; color: var(--accent-strong); font-size: 0.8125rem; }
.matrix-selected { outline: 2.5px solid var(--accent); outline-offset: 2px; border-radius: 6px; }

/* Sektion "Ihre Container" (ADR 88): Zeilen-Karte mit Trennlinien (Mülleimer
   links am Zeilenkopf, Kennung fett), darunter das Button-Paar gleicher Breite */
.selection-section { margin: 2rem 0 0; }
.selection-card { background: var(--surface-card); border: 1px solid var(--border); border-radius: 6px; padding: 0 1rem; }
.selection-row { display: flex; align-items: center; gap: 0.5rem; padding: 0.25rem 0; border-bottom: 1px solid var(--border); }
.selection-row:last-child { border-bottom: 0; }
.selection-row form { display: contents; }
/* Icon-Button-Basis (ADR 113; Destruktiv-Rot ADR 145): EINE Familie fuer
   Objekt-Aktionen - Muelleimer = Loeschen (destruktiv, Hover Rot-Token
   state-error - "Terrakotta = Handeln, Rot = Zerstoeren"), Stift = Aendern
   (navigierend, Blau --sea); 44-px-Ziel, Fokus-Ring Standard */
.selection-remove, .icon-button { display: inline-flex; align-items: center; justify-content: center; background: none; border: 0; cursor: pointer; color: var(--text-secondary); min-height: 2.75rem; min-width: 2.75rem; }
.icon-button-edit { color: var(--sea); text-decoration: none; }
@media (hover: hover) {
  .icon-button-edit:hover { background: var(--surface-filter); border-radius: 6px; }
}
.icon-button-edit:active { background: var(--surface-filter); border-radius: 6px; }
/* Abschnitts-Zeile mit Stift: Button vertikal zur Ueberschrift zentriert;
   das 44-px-Ziel traegt 12 px unsichtbaren Innenabstand um das 20-px-Icon -
   die negative Marge zieht den Stift optisch auf ~8 px an den Text heran
   (EINE Definition fuer alle drei Vorkommen, Touch-Ziel unveraendert) */
.review-heading { display: flex; align-items: center; gap: 0.25rem; }
.review-heading .icon-button-edit { margin-left: -0.5rem; }
/* Loesch-Icon-Standard (frontend.md, 25.07.2026): EINE Groessen-Definition
   fuer ALLE Muelleimer (Rufnummern-Zeilen, "Ihre Container", Schritt 1) -
   vorher zwei Streu-Regeln mit relativem 1.2em (~19,2 px), jetzt fest 20 px;
   Touch-Ziele unveraendert 44 px an den Buttons */
.selection-remove svg, .phone-remove svg, .icon-button svg { width: 20px; height: 20px; }
@media (hover: hover) {
  .selection-remove:hover { color: var(--state-error); background: var(--surface-filter); border-radius: 6px; }
}
.selection-remove:active { color: var(--state-error); background: var(--surface-filter); border-radius: 6px; }
.selection-pair { padding: 0.5rem 0; }
/* Die Zeile ist interaktiv (v2): Klick (re)aktiviert sie - Flächen-Link ohne
   Unterstreichung, 44-px-Ziel; der Mülleimer bleibt eigenes Ziel davor */
a.selection-pair { flex: 1; padding: 0.625rem 0; text-decoration: none; color: inherit; }
/* Aktive Zeile: Orange-Seitenstrich + leichte Tönung (KEIN Badge, ADR 88) */
.selection-row-active { border-left: 3px solid var(--accent); background: var(--surface-filter); margin: 0 -1rem; padding-left: calc(1rem - 3px); padding-right: 1rem; }
.selection-code { font-weight: 600; }
.selection-price { margin-left: auto; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Gesamtsumme in Schritt 1 (24.07.): nur bei mehreren Containern, per
   Hairline abgesetzt; der Preis flucht in der Preisspalte (tabular-nums) */
.selection-total { border-top: 1px solid var(--border); }
.selection-total .selection-price { font-weight: 600; }
/* Preis-Disclaimer je Segment (24.07.): Fußnote der Stern-Preise */
.price-disclaimer { color: var(--text-secondary); font-size: 0.875rem; }
/* Leerzustand: gestrichelte Fläche mit Hinweis (frontend.md „Leere Zustände") */
.selection-empty { border: 2px dashed var(--border-input); border-radius: 6px; padding: 1.5rem 1rem; color: var(--text-secondary); text-align: center; }
/* Button-Paar: zwei Spalten GLEICHER Breite, nie Umbruch; mobil gestapelt -
   EIN Standard für die Sektion "Ihre Container" UND den Flow-Stepper (Teil 4) */
.selection-actions, .flow-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem; }
.selection-actions .button, .flow-nav .button { width: 100%; white-space: nowrap; text-align: center; }
@media (max-width: 767px) {
  .selection-actions, .flow-nav { grid-template-columns: 1fr; }
}
.selection-actions .button svg, .flow-nav .button svg, .flow-add .button svg { width: 1.1em; height: 1.1em; vertical-align: -0.2em; }
.flow-nav { margin-top: 1.5rem; }

.pangv-notice { background: var(--surface-section); border-radius: 6px; padding: 0.75rem 1rem; }
.sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Angebotsseite per Token (P6, seiten.md 4.11): Meta-Zeile, Änderungs-
   Hinweiskasten (Amber-Badge-Paar wie board-warn-hint - im Kontrast-Gate),
   Unterlagen-Liste, Fußzeilen-Hinweis. Karten/Kosten nutzen die bestehenden
   Komponenten (summary-card, selection-card) - keine Seiten-Sonderoptik. */
.offer-meta { color: var(--text-secondary); margin: 0 0 1.5rem; }
.offer-change-note { background: var(--amber-badge-bg); color: var(--amber-badge-text); border-radius: 8px; padding: 0.75rem 1rem; margin: 0 0 1.5rem; }
.offer-change-note p { margin: 0; }
.offer-change-note p + p { margin-top: 0.375rem; }
.offer-documents { list-style: none; margin: 1rem 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; align-items: flex-start; }
.offer-footnote { color: var(--text-secondary); font-size: 0.875rem; margin-top: 2.5rem; border-top: 1px solid var(--border); padding-top: 1rem; }
/* Entscheidungs-Strecke (P7): Ablehnen-Satz unter dem Annahme-Button;
   "Vertrag geschlossen"-Siegel als state-success-Pille (Paar im
   Kontrast-Gate) mit vendored Haken */
.offer-decline-line { margin-top: 1.25rem; }
.offer-seal { display: inline-flex; align-items: center; gap: 0.5rem; background: var(--state-success-bg); color: var(--state-success-text); border-radius: 999px; padding: 0.5rem 1.25rem; font-weight: 600; font-size: 1.125rem; }
.offer-seal svg { width: 1.25em; height: 1.25em; }

/* Anfrage-Flow (seiten.md 4.10) */
.step-indicator { color: var(--text-secondary); font-weight: 600; margin-bottom: 0; }

/* Korrektur-Grün: nur für vormals fehlerhafte Felder; die Spezifität schlägt
   bewusst die rote has-error-Regel (der RAHMEN wird grün, nicht nur der Haken).
   Status-Icon-Automat (ADR 116): Haken und Fehlerzustand koexistieren NIE -
   das Gruen-Urteil traegt nur noch field-corrected (has-error wird entfernt),
   der Fehlerzustand traegt IMMER das rote X im selben Icon-Slot */
.field.field-corrected input, .field.field-corrected select,
.field.field-corrected textarea { border-color: var(--state-success); }
.field-corrected { position: relative; }
.field-corrected .field-error { display: none; }
.field-corrected > input, .field-corrected > select,
.field.has-error > input, .field.has-error > select { padding-right: 2.75rem; }
/* Rotes X (ADR 116): dritter Icon-Zustand im Feld-Icon-Slot (Lage identisch
   zu Haken und Spinner); Farbe = Fehlerrot (state-error auf Feld-Weiss steht
   bereits im Kontrast-Gate), aria-hidden im Partial - die Meldung bleibt die
   Text-Wahrheit daneben */
.field.has-error { position: relative; }
.field-x { position: absolute; right: 0.75rem; top: 1.375rem; transform: translateY(-50%); color: var(--state-error); pointer-events: none; }
.field-x svg { width: 20px; height: 20px; display: block; }
.field.has-error > select ~ .field-x { right: 2.25rem; }
.field-check { position: absolute; right: 0.75rem; top: 1.375rem; transform: translateY(-50%); color: var(--state-success); pointer-events: none; }
.field-check svg { width: 20px; height: 20px; display: block; }
.field-corrected > select ~ .field-check { right: 2.25rem; }
/* Spinner-Standard fuer externe Pruefungen (ADR 115): rotierende Bildmarke
   (~1s/Umdrehung) - .brand-spinner ist die Komponente (Styleguide), der
   .field-spinner-Wrapper setzt sie waehrend der Pruefung in den
   Feld-Icon-Slot (gleiche Lage wie der Korrektur-Haken); reduced-motion
   pulst stattdessen die Deckkraft (Block oben) */
.brand-spinner { display: inline-flex; }
.brand-spinner svg { width: 20px; height: 20px; display: block; animation: brand-spin 1s linear infinite; }
@keyframes brand-spin { to { transform: rotate(360deg); } }
@keyframes brand-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
.field-spinner { position: absolute; right: 0.75rem; top: 1.375rem; transform: translateY(-50%); pointer-events: none; }

/* Icon-Auswahl (ADR 151): Panel-Enhancement ueber dem nativen select -
   mit JS ersetzt der Ausloeser (aktuelles Icon + Name) das select visuell,
   das Panel ist eine role=listbox mit Icon-Zeilen; ohne JS natives select */
.icon-select { position: relative; }
.icon-select[data-icon-bound] select { display: none; }
/* Ausloeser in Feld-Geometrie (ADR-162-Nachtrag): der Select-Pfad-Ausloeser
   ersetzt sein verstecktes select in DERSELBEN field-inset-Huelle - volle
   Zellenbreite, Hoehe/Padding/Rahmen wie die Standard-Felder (T-DSN-067),
   Inset-Label sitzt wie beim Select, Chevron-Affordance wie das native
   select; der Text-Pfad-Ausloeser ("Vorhandene waehlen") bleibt bewusst
   ein Zusatz-Knopf unter seinem feldbreiten Text-Input. */
.icon-select-trigger { display: inline-flex; align-items: center; gap: 0.5rem; min-height: var(--control-height-min); font: inherit; font-size: var(--control-font-min); padding: 0.5rem 0.875rem; border: 1px solid var(--border-input); border-radius: 6px; background: #FFFFFF; cursor: pointer; }
.icon-select-trigger:not(.text-select-trigger) { display: flex; width: 100%; text-align: left; padding: 1.125rem 2.25rem 0.25rem 0.625rem; border-color: var(--border-strong); background-color: var(--surface-card); background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%231F2924' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6l6 -6'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 0.625rem center; }
.icon-select-panel { width: 100%; }
.icon-select-trigger svg, .icon-select-option svg { width: 20px; height: 20px; }
/* Panel-Breite folgt dem Ausloeser (ADR-162-Nachtrag); der Text-Pfad behaelt seine Mindestbreite */
.icon-select-panel { position: absolute; z-index: 30; margin: 0.25rem 0 0; padding: 0.25rem; list-style: none; background: var(--surface-card); border: 1px solid var(--border-strong); border-radius: 8px; box-shadow: 0 8px 24px rgba(38, 34, 30, 0.18); }
.text-select .icon-select-panel { width: auto; min-width: 16rem; }
.icon-select-option { display: flex; align-items: center; gap: 0.625rem; min-height: var(--control-height-min); padding: 0.25rem 0.625rem; border-radius: 6px; cursor: pointer; }
.icon-select-option.icon-select-active { background: var(--surface-filter); }
.icon-select-option[aria-selected="true"] { color: var(--accent-strong); font-weight: 600; }
/* Text-Panel-Variante der Auswahl-Insel (ADR 159, Gruppen-Eingabe): der
   Ausloeser steht UNTER dem Textfeld, Panel/Optionen erben die
   icon-select-Klassen (EINE Komponente, zwei Bau-Pfade) */
.text-select { position: relative; }
.text-select-trigger { margin-top: 0.375rem; }

/* Passwort-Paar (ADR 150): Auge-Toggle im Feld-Icon-Slot (44-px-Ziel aus
   der Icon-Button-Basis; Status-Icons ruecken nach links), Anforderungs-
   Checkliste ab Fokus (No-JS: immer sichtbar, Toggle entfaellt) */
.password-pair { display: block; }
.password-field { position: relative; }
.password-toggle { position: absolute; right: 0.25rem; top: 1.375rem; transform: translateY(-50%); }
html.no-js .password-toggle { display: none; }
.password-eye, .password-eye-off { display: inline-flex; }
.password-toggle .password-eye-off { display: none; }
.password-toggle[aria-pressed="true"] .password-eye { display: none; }
.password-toggle[aria-pressed="true"] .password-eye-off { display: inline-flex; }
.password-field .field-x, .password-field .field-check { right: 3.25rem; }
.password-field .field-spinner { right: 3.25rem; }
.password-field input { padding-right: 5.5rem; }
.password-requirements { list-style: none; margin: -0.5rem 0 1rem; padding: 0; color: var(--text-secondary); font-size: 0.875rem; }
html.no-js .password-requirements[hidden] { display: block; }
.password-requirements li { display: flex; align-items: center; gap: 0.375rem; padding: 0.125rem 0; }
.password-requirement-icon { display: inline-flex; color: var(--border-strong); }
.password-requirement-icon svg { width: 16px; height: 16px; }
.password-requirements li.req-met { color: var(--state-success-text); }
.password-requirements li.req-met .password-requirement-icon { color: var(--state-success); }


/* Standort & Kontakt (seiten.md 4.5) */
.hp-field { position: absolute; left: -9999px; top: auto; } /* Honeypot: unsichtbar, aber im DOM */
.contact-info, .contact-directions, .contact-form { margin: 2rem 0; }

/* Rufnummern-Zeilen v5 (ADR 86 + Nachträge, Icon-Umschalter Runde 2 24.07.):
   EIN Zeilenkopf-Wrapper (Mülleimer -> Typ-Icon-Anzeige -> Auswahlmenü) vor
   den Feldern - identisch für Zwei-Zeilen- und Einzelzeilen-Variante; mobil
   gestapelte Felder unter dem Kopf, ab Tablet eine Zeile */
.phone-rows { margin-bottom: 0.5rem; }
.phone-row { display: grid; grid-template-columns: auto 1fr; gap: 0 0.75rem; align-items: start; }
.phone-row > .field { grid-column: 2; }
.phone-row-head { display: flex; align-items: center; gap: 0.5rem; min-height: 2.75rem; margin-top: 0.25rem; }
.phone-row-icon { color: var(--text-secondary); }
.phone-row-icon svg { width: 1.25rem; height: 1.25rem; display: block; }
@media (min-width: 768px) {
  .phone-row { grid-template-columns: auto 1fr 2fr; gap: 0 1rem; }
  .phone-row > .field { grid-column: 2; }
  .phone-row > .field + .field { grid-column: 3; }
}
/* Typ-Umschalter v5: Icon-Radios (echte Radio-Semantik, Icons device-mobile/
   phone) - aktiver Typ gefüllt (Weiß auf accent-strong, Gate-Paar), freier
   Typ in Outline-Optik; 44-px-Ziele; Fokus-Ring am umschließenden Label
   (:has(input:focus-visible), neutrales Token); Hover = Füllton-Wechsel.
   Der "Typ übernehmen"-Submit ist der No-JS-Weg (JS versteckt ihn). */
.phone-type-switch { border: 0; margin: 0; padding: 0; display: inline-flex; align-items: center; }
.phone-type-option { display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; background: var(--surface-card); color: var(--accent-strong); border: 1px solid var(--accent-strong); cursor: pointer; }
.phone-type-option:first-of-type { border-radius: 6px 0 0 6px; }
.phone-type-option:last-of-type { border-radius: 0 6px 6px 0; border-left: 0; }
.phone-type-option svg { width: 1.25rem; height: 1.25rem; display: block; }
.phone-type-option:has(input:checked) { background: var(--accent-strong); color: #FFFFFF; cursor: default; }
.phone-type-option:has(input:focus-visible) { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
@media (hover: hover) {
  .phone-type-option:not(:has(input:checked)):hover { background: var(--surface-filter); }
}
.phone-switch-apply { margin-left: 0.5rem; }
/* hidden muss die .button-display-Regel schlagen (JS versteckt den No-JS-Weg) */
.phone-switch-apply[hidden] { display: none; }
.phone-add svg { width: 1.1em; height: 1.1em; vertical-align: -0.2em; }
/* sichtbar-inaktiv bei zwei Zeilen: gemeinsame .button:disabled-Regel (s. o.) */
.phone-remove { grid-row: 1; grid-column: 2; background: none; border: 0; cursor: pointer; color: var(--text-secondary); min-height: 2.75rem; min-width: 2.75rem; }
.phone-remove svg { vertical-align: middle; } /* Groesse: Loesch-Icon-Standard oben */
@media (hover: hover) {
  .phone-remove:hover { color: var(--state-error); background: var(--surface-filter); border-radius: 6px; }
}
.phone-remove:active { color: var(--state-error); background: var(--surface-filter); border-radius: 6px; }
/* Rechtsseiten-Muster (Design-Abnahme 25.07.2026, frontend.md): Fassungs-
   Pille, Lesebreite ~70ch, TOC-Sprungliste; die Zeilen-Karten und der
   Hinweis-Kasten kommen KLASSENLOS aus der Markup-Konvention der gepflegten
   Inhalte (dl = Label/Wert-Karte mit Hairline-Zeilen, aside = getönter
   Kasten) - Kontrast-Paare text-primary/-secondary auf filter/card stehen
   im Gate */
.legal-validity { display: inline-block; background: var(--surface-filter); color: var(--text-secondary); font-size: 0.875rem; padding: 0.25rem 0.75rem; border-radius: 999px; }
.legal-toc { margin: 1rem 0 2rem; }
.legal-toc ol { margin: 0; padding-left: 1.25rem; }
.legal-toc li { padding: 0.125rem 0; }
.legal-content { max-width: 70ch; }
/* AGB-TOC ohne Zaehler (legal-polish Teil 2): die Paragraf-Bezeichnungen
   tragen die Ordnung allein; Datenschutz behaelt den ol-Zaehler */
.legal-toc-plain { list-style: none; padding-left: 0.25rem; }
/* PDF-Download (Teil 3): Outline-Action-Button mit Icon nach Icon-Standard */
.legal-download { display: inline-flex; align-items: center; gap: 0.5rem; }
.legal-download svg { width: 20px; height: 20px; }
.legal-content p { line-height: 1.6; color: var(--text-primary); }
.legal-content h2 { font-weight: 600; font-size: 1.125rem; margin: 1.75rem 0 0.5rem; scroll-margin-top: 4.5rem; }
/* Zeilen-Karte: EINE CSS-Basis fuer Rechtsseiten (klassenlose dl gepflegter
   Inhalte) UND die Schritt-3-Zusammenfassung (dl.summary-card, ADR 111) -
   kombinierte Selektoren statt Kopie */
.legal-content dl, dl.summary-card { display: grid; grid-template-columns: 150px 1fr; margin: 1.5rem 0; background: var(--surface-card); border: 1px solid var(--border); border-radius: 10px; padding: 0 1rem; }
.legal-content dt, .summary-card dt { color: var(--text-secondary); }
.legal-content dt, .legal-content dd, .summary-card dt, .summary-card dd { margin: 0; padding: 0.75rem 0; border-top: 1px solid var(--border); line-height: 1.6; }
.legal-content dt:first-of-type, .legal-content dt:first-of-type + dd, .summary-card dt:first-of-type, .summary-card dt:first-of-type + dd { border-top: none; }
.legal-content dd, .summary-card dd { padding-left: 1rem; }
/* Telefon-Zeile der Zusammenfassung: Typ-Icon + Typname vor der Nummer */
.summary-phone { display: inline-flex; align-items: center; gap: 0.375rem; }
.summary-phone svg { width: 20px; height: 20px; }
.legal-content aside { background: var(--surface-filter); border-radius: 10px; padding: 1rem; margin: 1.5rem 0; line-height: 1.6; }
@media (max-width: 767px) {
  /* Label-Spalte stapelt: Label über dem Wert, Hairline nur je Zeilen-Paar */
  .legal-content dl, dl.summary-card { grid-template-columns: 1fr; }
  .legal-content dt, .summary-card dt { padding-bottom: 0.125rem; }
  .legal-content dd, .summary-card dd { border-top: none; padding: 0 0 0.75rem; }
}
/* FAQ-Karten (Design-Auftrag 25.07.2026, Mockup-Abnahme): jede Frage als
   weiße Karte am nativen details-Markup der gepflegten Inhalte (kein
   role-Umbau, Tastatur/Screenreader unangetastet). Chevron als MASKEN-
   Daten-URI (vendored Tabler-chevron-down-Pfad, Muster Checkbox-Haken) -
   die Farbe kommt damit aus den TOKENS (grau zu, --sea offen), kein
   Hex-Duplikat; als Pseudo-Element rein dekorativ (kein a11y-Knoten).
   Die geöffnete Karte spricht die Aktiv-Sprache des Systems (3-px-
   Seitenstrich, Muster selection-row-active/Drawer) in Blau; der
   transparente Ruhe-Strich verhindert Layout-Sprünge. Hover NUR auf der
   summary-Klickfläche (Füllton-Wechsel, Regel 18) + dezente Karten-
   Anhebung; bewusst ohne Border-Wechsel (kollidierte mit dem Strich). */
.faq-group { margin: 2rem 0; }
.faq-group details { background: var(--surface-card); border: 1px solid var(--border); border-left: 3px solid transparent; border-radius: 10px; margin-bottom: 0.5rem; overflow: hidden; }
.faq-group details[open] { border-left-color: var(--sea); }
.faq-group summary { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; min-height: 2.75rem; padding: 0.5rem 1rem; cursor: pointer; list-style: none; }
.faq-group summary::-webkit-details-marker { display: none; }
.faq-group summary::after, summary.board-message-head::after {
  content: ""; width: 18px; height: 18px; flex-shrink: 0;
  background-color: var(--text-secondary);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6l6 -6'/%3E%3C/svg%3E") no-repeat center / contain;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6l6 -6'/%3E%3C/svg%3E") no-repeat center / contain;
  transition: transform 150ms ease-out;
}
.faq-group details[open] summary { font-weight: 600; }
.faq-group details[open] summary::after,
details.board-message[open] summary.board-message-head::after { background-color: var(--sea); transform: rotate(180deg); }
.faq-group details p { color: var(--text-secondary); line-height: 1.55; margin: 0; padding: 0 1rem 1rem; }
/* Standort-Zeile des Direktkontakts (A6): sie kommt seit A6 aus dem
   gepflegten Seitentext contact_info und traegt daher keine eigene Klasse
   mehr - die Auszeichnung haengt an der FUEHRENDEN Zeile des Blocks
   (unveraenderte Optik: 17px gegen die 16px der Kontaktdaten darunter) */
.contact-info [data-maintained-content] > p:first-child { font-size: 1.0625rem; }

/* Styleguide-Demos (A90/ADR 339): die vier frueheren style-Attribute des
   Board-Styleguides als Klassen - style-src 'self' erlaubt kein Inline-Style.
   Die Farb-Probe ist ein SVG-Rechteck mit Praesentationsattribut fill (kein
   style-Attribut, CSP-neutral), diese Klasse gibt ihm nur den Rahmen. */
.styleguide-swatch { display: inline-block; width: 4rem; height: 1.25rem; border: 1px solid var(--border); vertical-align: middle; }
.styleguide-demo-narrow { max-width: 32rem; }
.styleguide-demo-card { max-width: 16rem; }
