/**
 * Default-Theme (Akzent: Orange). Per-Gemeinde-Override unter
 * /assets/communities/{slug}/main.css.
 *
 * Enthaelt:
 *  - Tailwind-Config-Ueberschreibungen (Farben, Fonts)
 *  - Globale Styles die bisher inline in jeder .html-Datei standen
 *  - Utility-Classes (hide-scroll, nav-fixed)
 *
 * Gemeinde-spezifische Akzentfarben/Fonts/Sub-Element-Styles werden im
 * /assets/communities/{slug}/main.css ueberschrieben — die Layout-API
 * haengt den Pfad automatisch an assets.css an. Statusbar-Farbe
 * (PWA + <meta name="theme-color">) kommt zusaetzlich aus
 * community.theme_color, siehe app/manifest.php + app/index.php.
 */

/* Tailwind runtime-config wird per <script> im <head> gesetzt (siehe index.php).
   Hier nur statische Styles die kein Tailwind-Preset brauchen. */

/* ============================================================================
   Inter — self-hosted (DSGVO-konform, kein Google-Fonts-Roundtrip)
   ----------------------------------------------------------------------------
   Begruendung: Einbindung ueber fonts.googleapis.com sendet die IP-Adresse
   des Besuchers an Google. Das LG Muenchen hat das 2022 (Az. 3 O 17493/20)
   ohne Einwilligung als DSGVO-Verstoss gewertet — Schadenersatzpflicht.
   Selbst-Hosting der OFL-lizenzierten Inter-WOFF2-Files schaltet das aus.
   Quelle der Files: fonts.gstatic.com (Variable-Font, 1 Datei pro Subset
   enthaelt alle Gewichte 300-700). Lizenz: SIL Open Font License 1.1
   (siehe app/assets/fonts/inter/LICENSE.txt).

   font-display: optional — kein Layout-Shift waehrend des Lesens (siehe
   PR #821). Bei kaltem Cache rendert der Erst-Besucher mit System-Font,
   ab dem zweiten Pageview ist Inter aus dem Browser-Cache da.
   ============================================================================ */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 700;     /* Variable-Font: ein File deckt 300-700 ab */
  font-display: optional;
  src: url('/assets/fonts/inter/inter-latin.woff2') format('woff2');
  unicode-range:
    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 300 700;
  font-display: optional;
  src: url('/assets/fonts/inter/inter-latin-ext.woff2') format('woff2');
  unicode-range:
    U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF,
    U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* ============================================================================
   Design-Tokens (CSS-Variablen)
   ----------------------------------------------------------------------------
   Per-Gemeinde-Overrides liegen unter app/assets/communities/{slug}/main.css
   und werden NACH dieser Datei geladen (siehe erp/Classes/API/ApiLayout.php
   -> buildAssets). Eine Gemeinde stellt damit ihren Look mit wenigen Zeilen
   um, ohne dass Templates angefasst werden muessen.

   Defaults entsprechen 1:1 dem aktuellen Tailwind-basierten Design — Phase 1
   fuehrt die Variablen nur ein, sie werden noch nicht in Templates angewendet
   (das passiert in spaeteren Phasen, schrittweise pro Block-Typ).
   ============================================================================ */
:root {
  /* ---- Akzent-Farbe ---- */
  --accent:         #f97316;   /* tailwind orange-500 — primary */
  --accent-strong:  #ea580c;   /* tailwind orange-600 — hover/active */
  --accent-soft:    #fed7aa;   /* tailwind orange-200 — backgrounds */
  --accent-mute:    #fdba74;   /* tailwind orange-300 — disabled/indeterminate */
  --accent-on:      #ffffff;   /* Textfarbe AUF Akzent-Hintergrund */

  /* Fuellfarbe hinter der Handy-Statusleiste im nativen App-Shell
     (mitanand-Markenblau). Per-Gemeinde ueberschreibbar. Nur relevant
     wenn env(safe-area-inset-top) > 0, also App/Standalone-PWA. */
  --status-bar-bg:  #008ecf;   /* mitanand-Blau */

  /* ---- Status-Farben ---- */
  --status-open:    #16a34a;   /* green-600 */
  --status-closed:  #ef4444;   /* red-500 */
  --status-info:    #2563eb;   /* blue-600 */
  --status-warning: #d97706;   /* amber-600 */
  --status-error:   #dc2626;   /* red-600 */
  --status-muted:   #6b7280;   /* gray-500 — z.B. abgelehnte Mängel-Meldung */

  /* ---- Neutrale Text- und Flaechenfarben ---- */
  --text-strong:    #111827;   /* gray-900 — Headings, primaerer Text */
  --text-default:   #1f2937;   /* gray-800 — Fliesstext */
  --text-muted:     #6b7280;   /* gray-500 — sekundaerer Text */
  --text-faint:     #9ca3af;   /* gray-400 — Labels, Meta */
  --border-default: #e5e7eb;   /* gray-200 — Trenner, Card-Border */
  --surface-soft:   #f3f4f6;   /* gray-100 — Card-Background */
  --surface-toggle-off: #d1d5db; /* gray-300 — inaktiver Toggle-Track */

  /* ---- Section-Rhythmus ----
     Der section-divider (h-2 grau) ist heute fester Block-Trenner.
     --block-py/px sind vorbereitet, werden aber in Phase 1 noch nicht
     erzwungen — Templates regeln padding/margin weiterhin via Tailwind. */
  --block-py:        0;            /* spaeter z.B. 1.5rem */
  --block-px:        0;            /* spaeter z.B. 1rem (px-5 = 1.25rem heute) */
  --divider-height:  0.5rem;       /* h-2 (8px) — section-divider */
  --divider-color:   var(--border-default);

  /* ---- Radius ----
     Design-Kern: kantig. Bewusst auf 0 — bei Bedarf pro Gemeinde anhebbar. */
  --radius:          0;
  --radius-pill:     9999px;       /* Toggle-Knob, Avatare (full-round bleibt) */

  /* ---- Typografie: Basis ---- */
  --font-family:     'Inter', system-ui, sans-serif;
  --font-size-base:  1rem;         /* 16px */
  --line-height-base: 1.5;
  --font-smoothing:  antialiased;

  /* ---- H1 — Page-Titel (text-2xl font-bold tracking-tight) ----
     Verwendet in: page-header, event-hero, news/detail, tenants/profile-header */
  --h1-size:         1.5rem;       /* text-2xl */
  --h1-weight:       700;          /* font-bold */
  --h1-line:         1.25;         /* leading-tight */
  --h1-tracking:     -0.025em;     /* tracking-tight */
  --h1-color:        var(--text-strong);

  /* ---- H2 (Block-Title) — Block-Headline mit Akzent-Underline (text-lg font-bold) ----
     Verwendet in: home/vereine, news/list-horizontal, list, resource-* */
  --h2-size:         1.125rem;     /* text-lg */
  --h2-weight:       700;
  --h2-line:         1.5;
  --h2-color:        var(--text-strong);

  /* ---- H2-Label — Kapitel-Label ueber Block (text-xs uppercase tracking-wide gray-400) ----
     Bei weitem haeufigste Variante (~35 Templates) */
  --label-size:      0.75rem;      /* text-xs */
  --label-weight:    500;          /* font-medium */
  --label-color:     var(--text-faint);
  --label-tracking:  0.025em;      /* tracking-wide */
  --label-transform: uppercase;

  /* ---- H3 — Item-Titel in Listen (text-[15px] / text-lg semibold) ---- */
  --h3-size:         1.125rem;     /* text-lg (text-card-Titel) */
  --h3-weight:       600;          /* font-semibold */
  --h3-line:         1.5;
  --h3-color:        var(--text-strong);

  /* ---- Wichtig-Box (Banner) ----
     --waste-color steuert das Pastell-Schema. Default = Akzent;
     pro waste_type ueber .wichtig-box[style="--waste-color: #xxx"] (Template). */
  --waste-color:     var(--accent-strong);
}

body {
  /* font-size + line-height bewusst nicht hier setzen — sie werden via
     Tailwind-Preflight von <html> geerbt (line-height: 1.5). Ein expliziter
     line-height auf body sorgte beim Font-Swap (Inter laedt async) fuer
     einen sichtbaren Layout-Shift, weil der Browser den Wert dann mit den
     neuen Inter-Metriken neu berechnet. Variablen --font-size-base /
     --line-height-base bleiben deklariert fuer spaetere h1/h2-Regeln. */
  font-family: var(--font-family);
  padding-bottom: 2.5rem;
  -webkit-font-smoothing: antialiased;
}

/* ============================================================================
   Tailwind-Bridge — Akzent-Klassen ans Token-System anbinden
   ----------------------------------------------------------------------------
   tailwind.css wird mit festen Hex-Werten aus tailwind.config.js gebaut
   (accent-500: #f97316 etc.). Ohne diesen Block wuerde ein Tenant-Override
   wie '.tenant-pfarrkirchen { --accent: #ea580c }' an den sichtbarsten
   Stellen verpuffen: H2-Block-Title-Underline (border-accent-500),
   Akzent-Buttons (bg-accent-500), Bottom-Nav-Active, Form-Focus-Rings.
   Diese Regeln ueberschreiben die kompilierten Hex mit var(--accent...),
   damit der Token-Override wirklich global durchschlaegt.

   Lade-Reihenfolge: tailwind.css (frueher) -> main.css (jetzt). Bei gleicher
   Spezifitaet (0,1,0) gewinnt die spaeter deklarierte Regel — also unsere.

   Stufung-Mapping (Tailwind-Step -> Token):
     50, 100         -> color-mix mit --accent (sehr helle Pastell-BGs)
     200, 300, 400   -> --accent-mute (mittel-helle Backgrounds)
     500             -> --accent (Default-Akzent)
     600, 700        -> --accent-strong (Hover-/Active-State)

   Wenn eine Gemeinde nur --accent + --accent-strong setzt, ziehen ALLE
   Stufen automatisch mit (color-mix berechnet die hellen Varianten).
   ============================================================================ */

/* Background — bg-accent-* */
.bg-accent-50          { background-color: color-mix(in srgb, var(--accent) 8%,  white); }
.bg-accent-100         { background-color: color-mix(in srgb, var(--accent) 18%, white); }
.bg-accent-500         { background-color: var(--accent); }
.bg-accent-600         { background-color: var(--accent-strong); }
.bg-accent-700         { background-color: color-mix(in srgb, var(--accent-strong) 88%, black); }

/* Text — text-accent-* */
.text-accent-500       { color: var(--accent); }
.text-accent-600       { color: var(--accent-strong); }
.text-accent-700       { color: var(--accent-strong); }
.text-accent-800       { color: color-mix(in srgb, var(--accent-strong) 80%, black); }

/* Border — border-accent-* */
.border-accent-200     { border-color: var(--accent-mute); }
.border-accent-300     { border-color: var(--accent-mute); }
.border-accent-500     { border-color: var(--accent); }
.border-accent-600     { border-color: var(--accent-strong); }

/* Hover-Varianten — gleiche Stufung, aber mit :hover */
.hover\:bg-accent-50:hover       { background-color: color-mix(in srgb, var(--accent) 8%,  white); }
.hover\:bg-accent-600:hover      { background-color: var(--accent-strong); }
.hover\:bg-accent-700:hover      { background-color: color-mix(in srgb, var(--accent-strong) 88%, black); }
.hover\:text-accent-500:hover    { color: var(--accent); }
.hover\:text-accent-600:hover    { color: var(--accent-strong); }
.hover\:text-accent-700:hover    { color: var(--accent-strong); }
.hover\:border-accent-200:hover  { border-color: var(--accent-mute); }
.hover\:border-accent-300:hover  { border-color: var(--accent-mute); }

/* Focus-Ring + Focus-Border — Form-Inputs (Tailwind nutzt --tw-ring-color
   als CSS-Variable, daher direkt setzen). */
.focus\:ring-accent-500:focus    { --tw-ring-color: var(--accent); }
.focus\:border-accent-500:focus  { border-color: var(--accent); }

/* App-Header: Sticky oben, faellt im nativen App-Shell (Android 15/16,
   edge-to-edge) hinter die transparente Statusleiste. padding-top haelt
   Wappen/Name unter der Statusleiste frei — mindestens 0.5rem (klassisch,
   iOS/Android ohne Notch melden env()=0), mehr wenn das Geraet eine
   Statusleisten-Inset meldet. Der weisse Header-Hintergrund fuellt so
   nahtlos bis zur Bildschirmoberkante. */
.app-header {
  padding-top: max(0.5rem, env(safe-area-inset-top));
}

/* ---------------------------------------------------------------------------
   Nativer App-Shell (Capacitor) — html.native-app wird von native-bridge.js
   gesetzt. Im Browser greift NICHTS davon.
   --------------------------------------------------------------------------- */

/* Statusleisten-Bereich in Markenblau fuellen — greift auf iOS (dort umfasst
   die Safe-Area die Systemleisten). ANDROID: env(safe-area-inset-*) meldet
   NUR den Display-Cutout, nicht Status-/Navigationsleiste — dieser Streifen
   bleibt dort 0 hoch. Die Leisten faerbt auf Android die native Seite
   (windowBackground/setStatusBarColor + adjustMarginsForEdgeToEdge=force,
   siehe mobile/android MainActivity + styles.xml). Im Emulator (API 30 + 36)
   nachgewiesen. Liegt UEBER allem (auch Fullscreen-Overlays, z-index 90);
   pointer-events:none — faengt keine Taps ab. */
html.native-app body::before {
  content: '';
  position: fixed;
  top: 0; left: 0; right: 0;
  height: env(safe-area-inset-top);
  background: var(--status-bar-bg);
  z-index: 200;
  pointer-events: none;
}

/* Overscroll-Stretch abschalten (Android 12+): beim Scroll-Anschlag dehnt
   die WebView sonst den GESAMTEN Viewport — inklusive der fixierten
   Bottom-Nav und des sticky Headers, die dabei sichtbar aus dem Bild
   wandern. `none` unterbindet den Effekt und die Pull-to-Refresh-Gestik;
   in der App will beides niemand (Inhalte laedt die App selbst nach).
   Nur nativ — im Browser bleibt Pull-to-Refresh erhalten. */
html.native-app,
html.native-app body {
  overscroll-behavior: none;
}

/* Fullscreen-Overlays (Suche, Menue, Login) liegen bei edge-to-edge unter
   den Systemleisten — ihr sticky Header bzw. Scroll-Ende braucht dieselbe
   Kompensation wie Seiten-Header und Bottom-Nav. */
html.native-app .overlay-header {
  padding-top: calc(0.75rem + env(safe-area-inset-top));
}
html.native-app .overlay-body {
  padding-bottom: env(safe-area-inset-bottom);
}

.nav-fixed {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 50;
  /* Horizontaler Abstand zu abgerundeten Bildschirmkanten (iOS + Android).
     Mindestens 17px (auch auf iPhone Portrait wo safe-area-inset = 0 meldet),
     mehr wenn das Geraet eine groessere Safe-Area meldet. */
  padding-left: max(17px, env(safe-area-inset-left));
  padding-right: max(17px, env(safe-area-inset-right));
  /* Volle Safe-Area-Bottom: im nativen App-Shell (Android edge-to-edge)
     die Hoehe der Gestenleiste — der farbige Nav-Hintergrund fuellt
     dahinter, die Tab-Icons bleiben darueber bedienbar. iPhone: Polster
     ueber dem Home-Indicator. Ohne Inset (Desktop/Browser) meldet env() 0. */
  padding-bottom: env(safe-area-inset-bottom);
}

.hide-scroll::-webkit-scrollbar { display: none; }
.hide-scroll { -ms-overflow-style: none; scrollbar-width: none; }

/* Gemeindename im Header-Prefix hervorheben. JSON liefert z.B.
   "Stadt <b>Pfarrkirchen</b>" — das <b> wird hier schwarz dargestellt,
   waehrend der Rest der Zeile grau bleibt. */
header p b { color: #000; font-weight: 600; }

/* User-Agent [hidden] wird von Tailwinds .flex / .grid / .block-Utilities
   ueberschrieben — deshalb hier explizit mit !important erzwingen.
   Filter-JS setzt element.hidden = true auf versteckten Items. */
[hidden] { display: none !important; }

/* ---- Fullscreen-Overlays (Suche / Inbox) ---- */
.overlay-panel {
  position: fixed; inset: 0; z-index: 90;
  background: white;
  display: flex; flex-direction: column;
  transform: translateY(12px);
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.overlay-panel.open { transform: translateY(0); opacity: 1; }

/* Inbox-Variante: nicht fullscreen, sondern 80% Breite rechts angedockt
   wie ein klassisches Notification-Panel. Schatten zur visuellen Abgrenzung. */
#overlay-inbox.overlay-panel {
  left: auto;
  right: 0;
  width: 80vw;
  max-width: 480px;
  box-shadow: -8px 0 24px rgba(0, 0, 0, 0.15);
}

/* Overlay-Variante, die ueber der Bottom-Nav endet, damit die Nav
   sichtbar und bedienbar bleibt (z.B. Menue per "Mehr"-Tab schliessen).
   z-index unter .nav-fixed (50), damit die Nav-Buttons obenauf liegen.
   bottom = Nav-Content-Hoehe (3.5rem) + volles Safe-Area-Inset (vgl. .nav-fixed). */
.overlay-panel.above-nav {
  bottom: calc(3.5rem + env(safe-area-inset-bottom));
  z-index: 40;
}
.overlay-header {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.75rem 1rem;
  border-bottom: 1px solid #e5e7eb;
  position: sticky; top: 0;
  background: white; z-index: 1;
}
.overlay-body { flex: 1; overflow-y: auto; }

/* ---- Toggle-Switch (.gem-toggle) ----
   Eigene CSS-Implementierung statt Tailwind peer-checked:-Variants — der
   Tailwind-Build im Repo enthaelt diese Variants nicht (peer-checked: kommt
   beim Conditional-Rebuild offenbar nicht durch), deshalb fielen Subscriptions-
   Toggles visuell stumm aus. Markup:
     <label class="gem-toggle [is-locked]">
       <input type="checkbox" class="gem-toggle__input" [checked] [disabled]>
       <span class="gem-toggle__track"></span>
       <span class="gem-toggle__knob"></span>
     </label>
   Drei sichtbare Zustaende ueber den input:
     :checked         -> orange Track + Knob nach rechts
     :indeterminate   -> mattes Orange + Knob in der Mitte (Master-Mixed)
     is-locked        -> ausgegraut, Track in mattem Orange, Knob rechts
*/
.gem-toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  cursor: pointer;
  user-select: none;
}
.gem-toggle__input {
  position: absolute;
  width: 1px; height: 1px;
  margin: 0; padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.gem-toggle__track {
  display: inline-block;
  width: 2.5rem; height: 1.25rem;
  background: var(--surface-toggle-off);
  border-radius: var(--radius-pill);
  transition: background-color 0.15s;
}
.gem-toggle__knob {
  position: absolute;
  left: 0.125rem; top: 0.125rem;
  width: 1rem; height: 1rem;
  background: #fff;
  border-radius: var(--radius-pill);
  pointer-events: none;
  transition: transform 0.15s;
}
.gem-toggle__input:checked ~ .gem-toggle__track   { background: var(--accent); }
.gem-toggle__input:checked ~ .gem-toggle__knob    { transform: translateX(1.25rem); }
.gem-toggle__input:indeterminate ~ .gem-toggle__track { background: var(--accent-mute); }
.gem-toggle__input:indeterminate ~ .gem-toggle__knob  { transform: translateX(0.625rem); }
.gem-toggle.is-locked { cursor: not-allowed; opacity: 0.65; }
.gem-toggle.is-locked .gem-toggle__track { background: var(--accent-mute); }
.gem-toggle.is-locked .gem-toggle__knob  { transform: translateX(1.25rem); }
.gem-toggle__input:focus-visible ~ .gem-toggle__track {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---- Status-Farben fuer Oeffnungszeiten / Verfuegbarkeit / etc. ----
   Werden von Templates via class="status-{state}" bzw. "status-dot-{state}"
   angewendet. Pro Gemeinde in assets/communities/<gemeinde>/main.css
   ueberschreibbar. */
.status-open      { color: var(--status-open); }
.status-closed    { color: var(--status-closed); }
.status-always    { color: var(--status-open); }
.status-info      { color: var(--status-info); }
.status-warning   { color: var(--status-warning); }
.status-muted     { color: var(--status-muted); }

.status-dot-open      { background-color: var(--status-open); }
.status-dot-closed    { background-color: var(--status-closed); }
.status-dot-always    { background-color: var(--status-open); }
.status-dot-info      { background-color: var(--status-info); }
.status-dot-warning   { background-color: var(--status-warning); }
.status-dot-muted     { background-color: var(--status-muted); }

/* ---- Wichtig-Box Farbschema (aus --waste-color abgeleitet) ----
   Home-Banner faerbt sich aus der CSS-Variable --waste-color, die das
   Template per inline-style setzt (Hex aus DB). Pastell-Varianten
   (Banner-BG, Border, Icon-BG, Label-Color, Arrow) entstehen per
   color-mix(). Fehlt die Variable, wird Orange als Default verwendet. */

.wichtig-box {
  /* Default = Akzent. Templates koennen pro Banner ueber inline-style
     "--waste-color: #xxx" einen anderen Hex setzen (waste-type-Farbe). */
  --waste-color: var(--accent-strong);
  background-color: color-mix(in srgb, var(--waste-color) 10%, white);
  border: 1px solid color-mix(in srgb, var(--waste-color) 22%, white);
}
.wichtig-box .wichtig-icon  {
  background-color: color-mix(in srgb, var(--waste-color) 28%, white);
  color: color-mix(in srgb, var(--waste-color) 85%, black);
}
.wichtig-box .wichtig-label { color: color-mix(in srgb, var(--waste-color) 80%, black); }
.wichtig-box .wichtig-arrow { color: color-mix(in srgb, var(--waste-color) 55%, white); }

/* ---- Umfrage-Balken Fade-In von links ---- */
@keyframes poll-bar-grow {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
.poll-bar {
  transform-origin: left center;
  animation: poll-bar-grow 700ms cubic-bezier(.22,.61,.36,1);
}
.poll-bar.poll-bar--no-anim { animation: none; }

/* ---- Polyline-Endpunkte auf Leaflet-Karten ----
   WICHTIG: Map-Pins werden vom Backend pro Track gesteuert (items[*].color
   im tracks.json — Redaktion setzt die Farbe pro Wanderweg/Route). Wenn
   das JSON eine Farbe liefert, uebersteuert map.js diese Default-CSS-Regel
   inline. Diese Regel hier greift NUR als Fallback wenn die JSON-color
   fehlt. Daher absichtlich NICHT an --accent gekoppelt — sonst wuerde
   ein Gemeinde-Theme-Override die fachlich zugeordnete Track-Farbe
   verfaelschen. Wenn du die Default-Pin-Farbe global aendern willst,
   hier den Hex anpassen, NICHT die Theme-Tokens. */
.gem-map-endpoint {
  width: 26px; height: 26px;
  background: #ea580c;
  color: #ffffff;
  border-radius: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Inter', system-ui, sans-serif;
  font-weight: 700; font-size: 13px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
}

/* ---- Lightbox (Galerie-Viewer) ---- */
.gem-lightbox {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0,0,0,0.92);
  display: none;
  align-items: center; justify-content: center;
  user-select: none;
}
.gem-lightbox.open { display: flex; }
.gem-lightbox-stage {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.gem-lightbox-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  transition: transform 0.15s ease-out;
  transform-origin: center center;
  touch-action: none;
  cursor: zoom-in;
}
.gem-lightbox-close,
.gem-lightbox-prev,
.gem-lightbox-next {
  position: absolute;
  background: rgba(255,255,255,0.12);
  color: white; border: 0;
  width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  font-size: 24px;
  cursor: pointer;
  z-index: 101;
}
.gem-lightbox-close { top: 12px; right: 12px; }
.gem-lightbox-prev  { left: 8px; top: 50%; transform: translateY(-50%); }
.gem-lightbox-next  { right: 8px; top: 50%; transform: translateY(-50%); }
.gem-lightbox-counter {
  position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%);
  color: white; font-size: 13px; font-family: Inter, system-ui, sans-serif;
  background: rgba(255,255,255,0.12);
  padding: 4px 10px;
}

/* ---- Hero-Overlay: Boxen im Bild mit 20% Transparenz ----
   Nur der Hintergrund wird durchscheinend (Bild schimmert durch),
   Text/Icons bleiben voll deckend. Aeusseres color-mix mischt die
   fertige Pastellfarbe mit 20% transparent. */
.hero-overlay .wichtig-box {
  background-color: color-mix(in srgb,
    color-mix(in srgb, var(--waste-color) 10%, white) 80%, transparent);
}
.hero-overlay .wichtig-box.alert-important {
  background-color: rgba(254, 242, 242, 0.8);
}

/* ---- Wichtige News/Alerts ---- */
.wichtig-box.alert-important          { background-color: #fef2f2; border-color: #fecaca; }
.wichtig-box.alert-important .wichtig-icon  { background-color: #fecaca; color: #991b1b; }
.wichtig-box.alert-important .wichtig-label { color: #dc2626; }
.wichtig-box.alert-important .wichtig-arrow { color: #fca5a5; }

/* ---- POI: Karten-Marker + Listen-Item Highlight ----
   .poi-marker = Leaflet divIcon-Wrapper aus map.js (poiIcon()).
   .is-active wird vom Marker-Click-Handler bzw. Listen-Item-Klick gesetzt:
   Skaliert den Pin etwas, legt einen Akzent-Ring darum und einen
   weicheren Drop-Shadow drunter. Auf der Liste markiert .is-active die
   zuletzt angeklickte/fokussierte Row mit Akzent-Border + leichtem Bg.
   Beides nutzt CSS-Transition damit der Zustandswechsel sanft kommt. */
.poi-marker > span {
  transition: transform .15s ease, box-shadow .15s ease;
}
.poi-marker.is-active > span {
  transform: scale(1.15);
  box-shadow: 0 0 0 3px #f97316, 0 4px 10px rgba(0,0,0,.25);
  z-index: 600;
}
.poi-list-item.is-active {
  background-color: #fff7ed;       /* orange-50 */
  border-color: #fdba74;           /* orange-300 */
}

/* DSGVO-Datenexport: beim Drucken / "als PDF speichern" nur die Daten-Ansicht
   ausgeben, nicht die ganze Konto-Seite (Header/Nav/Formular). JS
   (personal-data-export.js) setzt body.printing-data-export vor window.print()
   und entfernt die Klasse via afterprint wieder. Technik: alles unsichtbar,
   nur die gerenderte Export-Ansicht sichtbar + nach oben links gezogen. */
@media print {
  body.printing-data-export * {
    visibility: hidden !important;
  }
  body.printing-data-export [data-export-result],
  body.printing-data-export [data-export-result] * {
    visibility: visible !important;
  }
  body.printing-data-export [data-export-result] {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    padding: 1rem;
  }
}

/* Cookie-/Speicher-Hinweis (TDDDG §25). index.php bindet das Banner nur ein,
   solange der gem_consent-Cookie fehlt; cookie-banner.php setzt ihn beim
   "Verstanden"-Klick. Eigenstaendiges CSS (kein Tailwind-Rebuild noetig).
   Sitzt fix unten ueber der Bottom-Nav, mobile-first, kantig. */
.cookie-banner {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 9999;
  background: #ffffff;
  border-top: 2px solid #e5e7eb;          /* gray-200 */
  box-shadow: 0 -4px 12px rgba(0, 0, 0, .08);
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
}
.cookie-banner__inner {
  max-width: 640px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cookie-banner__text {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: #374151;                         /* gray-700 */
}
.cookie-banner__link { color: #ea580c; text-decoration: underline; }
.cookie-banner__btn {
  align-self: flex-end;
  background: #ea580c;                     /* accent-600 */
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  padding: 8px 22px;
  border: 0;
  border-radius: 0;
  cursor: pointer;
}
.cookie-banner__btn:hover { background: #c2410c; }   /* accent-700 */
@media (min-width: 480px) {
  .cookie-banner__inner { flex-direction: row; align-items: center; }
  .cookie-banner__text { flex: 1; }
  .cookie-banner__btn { align-self: auto; white-space: nowrap; }
}

/* ============================================================
   Einfaerbbares Graustufen-Hintergrundmotiv (Content-Bloecke)
   ------------------------------------------------------------
   Der Block-Container (.cp-has-bg-motif) bekommt einen Bild-Layer
   HINTER dem Inhalt. Das Graustufen-Motiv wird per SVG-Filter
   (#gem-bg-tint, siehe helpers/backgrounds.php) in die Gemeinde-
   farbe eingefaerbt: dunkel = Farbe, weiss = transparent.

   Position (unten), Groesse (contain) und Deckkraft sind hier FIX
   vorgegeben — es gibt bewusst KEINE per-Block-Regler.

   Bewusst <img> statt background-image: SVG filter:url() auf einem
   <img>-Element ist auf iOS-Safari robuster als auf einem
   Hintergrundbild.
   ============================================================ */
.cp-has-bg-motif {
  position: relative;
  overflow: hidden;
}
.cp-bg-motif {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
  object-position: bottom;
  opacity: 0.38;                 /* fixe Deckkraft-Vorgabe */
  filter: url(#gem-bg-tint);
  pointer-events: none;
  z-index: 0;
}
.cp-bg-content {
  position: relative;
  z-index: 1;
}

/* ============================================================================
   Boxed-Layout ab Tablet-Breite (> 800px)
   ----------------------------------------------------------------------------
   Mobile-first bleibt unangetastet: bis 800px aendert sich NICHTS. Ab 801px
   wird die App als zentrierter "Geraete"-Kasten mit max. 800px Breite
   dargestellt, die Flaeche aussenrum grau. Der Body traegt den Inhalt als
   Box; der sticky Header liegt im normalen Fluss und wird dadurch automatisch
   mitbegrenzt. Die viewport-fixierten Chrome-Elemente (Bottom-Nav, Overlays,
   Lightbox, Cookie-Banner) spannten sonst ueber den ganzen Desktop — sie
   werden per --app-inset an dieselbe Box gekoppelt (left/right statt
   transform, damit die Overlay-Open/Close-Animation frei bleibt).
   ============================================================================ */
@media (min-width: 801px) {
  :root {
    --app-max: 800px;
    /* Abstand Viewport-Rand -> zentrierte Box (nie negativ) */
    --app-inset: max(0px, calc(50% - (var(--app-max) / 2)));
  }

  html { background: #dfe1e5; }              /* Flaeche ausserhalb der Box */

  body {
    max-width: var(--app-max);
    margin-inline: auto;
    min-height: 100vh;                       /* Box fuellt die Hoehe */
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.05),
                0 8px 40px rgba(0, 0, 0, 0.12);
  }

  /* Viewport-fixierte Chrome-Elemente an die Box-Kanten koppeln. */
  .nav-fixed,
  .cookie-banner,
  .gem-lightbox,
  .overlay-panel {
    left: var(--app-inset);
    right: var(--app-inset);
  }

  /* Inbox dockt rechts an die Box-Kante (nicht an den Viewport-Rand). */
  #overlay-inbox.overlay-panel {
    left: auto;
    right: var(--app-inset);
  }
}

/* ---------------------------------------------------------------------------
   Anbieterkennzeichnung (templates/ui/anbieterkennzeichnung.php)

   <details>/<summary> statt Overlay: nativ zugaenglich und ohne JavaScript.
   Der Default-Marker der Browser wird ausgeblendet — Tailwinds list-none
   deckt WebKit nicht ab, deshalb hier explizit.
--------------------------------------------------------------------------- */
.imprint-toggle::-webkit-details-marker { display: none; }
.imprint-toggle { list-style: none; }

/* Chevron dreht sich beim Aufklappen. Bewusst hier statt als
   group-open:-Variante — die steht im vorgebauten Tailwind nicht drin. */
details[open] > .imprint-toggle .imprint-chevron { transform: rotate(180deg); }
.imprint-chevron { transition: transform .15s ease; }

/* ============================================================================
   App-Install-Banner (app-install-banner.js) — Hinweis "gibt's auch als App"
   auf Mobilgeraeten im Browser. Erscheint nur wenn eine Store-URL hinterlegt
   ist (Api::ANDROID_STORE_URL/IOS_STORE_URL, leer = aus) und nie im nativen
   Shell. Liegt UEBER der Bottom-Nav (z-index 60 > 50), kantig wie der Rest.
   ============================================================================ */
.gem-app-banner {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 60;
  display: flex; align-items: center; gap: 12px;
  background: #ffffff;
  border-top: 2px solid var(--status-bar-bg, #008ecf);
  box-shadow: 0 -4px 12px rgba(0, 0, 0, .12);
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
}
.gem-app-banner__icon { width: 40px; height: 40px; flex: 0 0 auto; }
.gem-app-banner__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.gem-app-banner__text strong { font-size: 14px; color: #111827; }
.gem-app-banner__text span   { font-size: 12px; color: #6b7280; }
.gem-app-banner__cta {
  flex: 0 0 auto;
  background: var(--status-bar-bg, #008ecf);
  color: #ffffff; text-decoration: none;
  font-size: 14px; font-weight: 600;
  padding: 10px 16px;
}
.gem-app-banner__close {
  flex: 0 0 auto;
  background: none; border: 0; cursor: pointer;
  font-size: 22px; line-height: 1; color: #9ca3af;
  padding: 4px 6px;
}

/* ---------------------------------------------------------------------------
   Karten-Klick-zum-Laden (assets/js/map.js)

   Liegt im Kartencontainer, bis der Nutzer die Karte ausdruecklich laedt.
   Erst dann geht ein Request an OpenStreetMap — vorher verlaesst keine
   IP-Adresse die eigene Domain. Das ist der Grund, warum die App ohne
   Einwilligungsdialog auskommt.
--------------------------------------------------------------------------- */
.map-gate,
.embed-gate {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
  text-align: center;
  background: #f9fafb;                     /* gray-50 */
}
.map-gate__text,
.embed-gate__text {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: #4b5563;                          /* gray-600, 7,6:1 auf gray-50 */
  max-width: 34ch;
}
.map-gate__btn,
.embed-gate__btn {
  background: #ea580c;                     /* accent-600 */
  color: #fff;
  border: 0;
  font-size: 14px;
  font-weight: 600;
  padding: 10px 20px;
  cursor: pointer;
}
.map-gate__btn:hover,
.embed-gate__btn:hover { background: #c2410c; }
.map-gate__btn:focus-visible,
.embed-gate__btn:focus-visible { outline: 2px solid #1f2937; outline-offset: 2px; }

/* Platzhalter fuer eingebettete Videos — gleiche Optik wie der Karten-Gate,
   damit "hier wird etwas von Dritten nachgeladen" in der App immer gleich
   aussieht. Das Icon ersetzt das frueher von Google geladene Vorschaubild. */
.embed-gate { background: #f3f4f6; }        /* gray-100, etwas dunkler als die Karte */
.embed-gate__icon { width: 40px; height: 40px; color: #6b7280; }

/* Eigenes Vorschaubild (BlockYoutube data.poster_image_id). Ersetzt nur die
   graue Flaeche — Icon, Hinweistext und Button bleiben darueber stehen,
   sonst waere die Zwei-Klick-Loesung nicht mehr erkennbar. Das Bild kommt
   same-origin von /images/..., nie von YouTube.

   Der Scrim (::after, 65 % #111827) ist der Preis fuer Lesbarkeit: selbst auf
   einem komplett weissen Bild kommt weisser Text damit noch auf 5,5:1 und
   liegt ueber der WCAG-AA-Schwelle von 4,5:1 (gemessen, nicht geschaetzt).
   Wer den Scrim aufhellt, muss den Kontrast neu rechnen. */
.embed-gate--poster { position: relative; background: #111827; }
.embed-gate__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
.embed-gate--poster::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(17, 24, 39, .65);
  z-index: 1;
}
/* Inhalt ueber Bild + Scrim heben. Ohne das eigene Stacking waeren Text und
   Button vom ::after verdeckt. */
.embed-gate--poster > .embed-gate__icon,
.embed-gate--poster > .embed-gate__text,
.embed-gate--poster > .embed-gate__btn { position: relative; z-index: 2; }
.embed-gate--poster .embed-gate__icon { color: #ffffff; }
.embed-gate--poster .embed-gate__text {
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
}

/* SPA-Navigation (assets/js/spa-nav.js): duenner Ladebalken am oberen
   Rand waehrend ein Content-Fragment geholt wird. Farbe = Accent; per
   Gemeinde-Theme-CSS ueberschreibbar (.spa-progress { background: ... }). */
.spa-progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 2px;
  width: 0;
  background: #f97316;                     /* accent-500 */
  z-index: 9999;
  opacity: 0;
  pointer-events: none;
  transition: width .3s ease, opacity .2s ease;
}
.spa-progress.active { opacity: 1; }
