/**
 * LAL App-Hülle – Shell (Schritt 4)
 *
 * Titelzeile oben, Tab-Leiste unten. Bewusst schlank – die Inhalte
 * (Eventliste, Filter, Detailseiten) kommen unverändert aus EventHub.
 */

/* Beide Leisten rechnen ihren 1-px-Rahmen in die Höhe ein. Ohne das ist die
   Tab-Leiste real 65 statt 64 px hoch (content-box), während `body.is-app`
   unten nur 64 px reserviert – die unterste Pixelzeile des Inhalts liegt dann
   darunter. Auf der Kartenseite traf das ausgerechnet die Google-Attribution,
   die laut Maps-Nutzungsbedingungen sichtbar bleiben muss. */
.lal-appbar,
.lal-tabbar {
	box-sizing: border-box;
}

:root {
	--lal-navy: #0a1f44;
	/* Markenpink wie im Theme-Override (styles-eventhub.css definiert
	   --lev-pink auf :root und lädt über wp_head vor dieser Datei). Der
	   Literalwert dahinter ist nur die Rückfalllinie, falls das Override auf
	   einer Seite einmal nicht geladen ist. Aktuell hängen der Indikator des
	   aktiven Tabs und das Merklisten-Abzeichen daran. */
	--lal-accent: var( --lev-pink, #cb0950 );
	--lal-ink: #1b2430;
	--lal-muted: #6b7686;
	--lal-line: rgba( 10, 31, 68, 0.10 );
	--lal-bg: #ffffff;
	--lal-appbar-h: 52px;
	--lal-tabbar-h: 64px;
	--lal-safe-top: env( safe-area-inset-top, 0px );
	--lal-safe-bottom: env( safe-area-inset-bottom, 0px );
}

/* Keine sichtbare Scrollleiste in der App-Hülle.
   Das Eltern-Theme unicon erzwingt in style.css `html { overflow-y: scroll }`,
   also eine dauerhafte Leiste. Auf einem Telefon gibt es so etwas nicht, und
   die App-Hülle soll sich wie eine App anfühlen – daher ausgeblendet.
   Gescrollt wird weiterhin ganz normal (Rad, Wischen, Tastatur).
   Damit das greift, wird app.css NACH wp_head() geladen (app/header.php),
   sonst gewinnt unicon bei gleicher Spezifität. */
html {
	scrollbar-width: none; /* Firefox, Chrome 121+ */
	/* Chrome faerbt die untere Android-Systemleiste im Standalone-Modus nach
	   dem <html>-Hintergrund. Ohne das bleibt sie grau statt weiss. */
	background: #ffffff;
}

html::-webkit-scrollbar {
	display: none; /* Chrome, Safari, Edge */
}

/* Platz, den die Titelzeile oben wegnimmt. Auf den Wurzeln der Tab-Leiste
   (Archiv, Karte, Merkliste) wird sie gar nicht erst ausgegeben – dort also
   null. Die Klasse setzt app/header.php. */
body.is-app {
	--lal-appbar-space: 0px;
}

body.is-app.has-appbar {
	--lal-appbar-space: var( --lal-appbar-h );
}

body.is-app {
	background: var( --lal-bg );
	/* Kein horizontales Scrollen: fängt kurzzeitiges Überbreiten beim Laden
	   ab (z. B. Slider-Track vor JS-Init). */
	overflow-x: hidden;
	overflow-x: clip;
	padding-top: calc( var( --lal-appbar-space ) + var( --lal-safe-top ) );
	padding-bottom: calc( var( --lal-tabbar-h ) + var( --lal-safe-bottom ) );
	/* unicon/style.css erzwingt `html, body { height: 100% }`. Dadurch sitzt
	   das padding-bottom an der nominalen Viewport-Höhe statt hinter dem
	   echten Seiteninhalt: bei langen Listen verschwindet der letzte Button
	   unter der Tab-Leiste, bei kurzen Seiten (leere Merkliste) entsteht
	   sinnloser Leerraum-Scroll. Höhe zurück auf den tatsächlichen Inhalt. */
	height: auto;
}

/* Ziel für den "Suche"-Tab: unter der festen Titelzeile parken, nicht am
   oberen Bildschirmrand (wo die App-Bar es verdeckt). */
#eventhub-search,
.eventhub-filter__group--search {
	scroll-margin-top: calc( var( --lal-appbar-space ) + var( --lal-safe-top ) + 12px );
}

/* Website-Chrome ausblenden, falls es doch per Hook ausgegeben wird. */
body.is-app #header,
body.is-app #footer,
body.is-app #copyright,
body.is-app #back-to-top,
body.is-app .sticky__event_btn,
body.is-app .titlebar {
	display: none !important;
}

/* View-Switcher (Übersicht | Karte | Merkliste) aus EventHub: in der App
   überflüssig, weil die Tab-Leiste unten dieselben drei Ziele führt – und
   zwei konkurrierende Navigationen für dieselbe Sache sind schlechter als
   eine. Bewusst per CSS statt per Template-Override: die Hülle blendet
   Website-Chrome aus, das Plugin bleibt unangetastet.
   Achtung: Damit verschwindet auch die Favoriten-Zählung, die im Switcher
   hängt (#eventhub-view-switcher-fav-count). Gehört perspektivisch als
   Abzeichen an den Merkliste-Tab. */
body.is-app .eventhub-view-switcher {
	display: none !important;
}

/* ---------------------------------------------------------------------
 *  Kartenansicht
 *
 *  EventHubs Kartenseite ist für die Website gebaut: Sie zieht vom Viewport
 *  die Höhe des Website-Kopfs ab und hängt unten einen "Zur Übersicht"-Link
 *  in den normalen Fluss. In der App gibt es keinen Website-Kopf, dafür die
 *  Tab-Leiste – dadurch wurde die Seite höher als der Bildschirm und der
 *  schwebende Umschalt-Knopf verschwand hinter der Tab-Leiste.
 * ------------------------------------------------------------------ */

/* "Zur Übersicht" dupliziert den Entdecken-Tab – und ist das einzige Element
   unterhalb der Karte, das die Seite scrollen ließ. */
body.is-app .eventhub-back-navigation {
	display: none !important;
}

/* Suchleiste ganz nach oben. styles-eventhub.css setzt unter 767 px
   `body .eventhub-wrapper { padding: 1rem !important }` – die 16 px oben
   schieben die Filterleiste vom Rand weg und addieren sich zugleich auf die
   Höhenrechnung unten, womit die Seite doch wieder um genau diesen Betrag
   scrollte. !important ist nötig, weil die Ausgangsregel es ebenfalls nutzt.

   Links und rechts stehen die 16 px weiterhin: die Karte bricht per
   negativem Margin daraus aus (styles-eventhub.css, Block "Kartenansicht
   randlos"). Das gilt dort für Website und App gemeinsam und gehört deshalb
   nicht hierher. Oben geht das nicht denselben Weg – auf der Website steht
   über der Karte der Website-Kopf, dort ist der Abstand richtig. */
body.is-app.eventhub-page-map .eventhub-wrapper {
	padding-top: 0 !important;
}

/* Exakt eine Bildschirmhöhe: body.is-app reserviert unten bereits die
   Tab-Leiste per padding-bottom, oben auf der Karte (Tab-Wurzel) nur die
   Safe-Area. Zieht die Karte genau den Rest ab, geht die Rechnung auf 100dvh
   auf und es bleibt nichts zu scrollen. */
body.is-app .eventhub-map-view {
	height: calc(
		100dvh - var( --lal-safe-top ) - var( --lal-tabbar-h ) - var( --lal-safe-bottom )
	);
}

/* Der Umschalt-Knopf ist bereits eine schwebende Pille unten mittig – er muss
   nur über die Tab-Leiste steigen. Behalten statt entfernen: er wechselt
   innerhalb der Karte zur Trefferliste und trägt deren Anzahl im Text
   ("Liste anzeigen (23)"). Der Entdecken-Tab führt dagegen aufs allgemeine
   Archiv und verwirft den Filterzustand der Karte.

   Wichtig: derselbe Abstand wie im Original (--eventhub-spacing-lg), nur
   zusätzlich um die Tab-Leiste angehoben. Die Plugin-Geometrie ist so
   abgestimmt, dass Knopf-Oberkante und Slider-Unterkante zusammenfallen
   (1.5rem + Knopfhöhe = 4.25rem). Ein eigener Wert reißt genau dort eine
   Lücke auf, in der der weiße Verlauf des Sliders abrupt endet. */
body.is-app .eventhub-map-toggle {
	bottom: calc( var( --eventhub-spacing-lg, 1.5rem ) + var( --lal-tabbar-h ) + var( --lal-safe-bottom ) );
}

/* Der Karten-Slider sitzt oberhalb des Knopfs – dieselbe Verschiebung, damit
   der Abstand zwischen beiden erhalten bleibt. */
body.is-app .eventhub-map-slider {
	bottom: calc( 4.25rem + var( --lal-tabbar-h ) + var( --lal-safe-bottom ) );

	/* Weißschleier abschalten. Der Verlauf des Plugins blendet nach oben
	   sauber aus, endet unten aber bei 85 % Weiß mit harter Kante:
	   linear-gradient( 0deg, rgba(255,255,255,.85) 0%, … rgba(255,255,255,0) 100% )
	   Auf der Website fällt das kaum auf, über der Tab-Leiste steht die Kante
	   mitten im Bild. Nach unten weiterziehen ginge auch, würde dann aber die
	   Google-Attribution überlagern – die muss laut Maps-Nutzungsbedingungen
	   unverdeckt bleiben. Die Karten tragen ohnehin eigenen Hintergrund und
	   Schatten und schweben so über der Karte wie bei Google Maps selbst. */
	background: none;

	/* Das Plugin setzt 2rem oben und unten – Raum, den dort der weiße Verlauf
	   füllt. Ohne ihn ist der Abstand nur noch Luft zwischen Card und
	   Tab-Leiste. 1.2rem reicht; der Slider ist unten verankert, die Cards
	   rücken damit näher an den Umschalt-Knopf. */
	padding: 1.2rem 0;
}

/* ---------------------------------------------------------------------
 *  Titelzeile
 * ------------------------------------------------------------------ */

.lal-appbar {
	position: fixed;
	inset: 0 0 auto 0;
	z-index: 1000;
	display: flex;
	align-items: center;
	height: calc( var( --lal-appbar-h ) + var( --lal-safe-top ) );
	padding-top: var( --lal-safe-top );
	/* Oben deckend weiß, nach unten in die milchige Fassung überblenden.
	   Die System-Statusleiste darüber ist weiß (theme_color). Wäre die Leiste
	   durchgehend rgba(…,0.88), färbte der durchscheinende Inhalt sie beim
	   Scrollen leicht ein – und genau dann würde die Kante zur Systemleiste
	   sichtbar. Der deckende Streifen oben verhindert das.
	   Echtes Edge-to-Edge (Inhalt unter der Statusleiste) ist für eine WebAPK
	   nicht erreichbar, siehe Messung im Manifest-Kommentar in lal-app.php. */
	background: linear-gradient(
		to bottom,
		#ffffff 0%,
		#ffffff 10%,
		rgba( 255, 255, 255, 0.86 ) 100%
	);
	backdrop-filter: saturate( 180% ) blur( 12px );
	-webkit-backdrop-filter: saturate( 180% ) blur( 12px );
	border-bottom: 1px solid var( --lal-line );
}

.lal-appbar__back,
.lal-appbar__spacer {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
}

.lal-appbar__back {
	display: flex;
	align-items: center;
	justify-content: center;
	color: var( --lal-navy );
	text-decoration: none;
}

.lal-appbar__back:active {
	opacity: 0.5;
}

.lal-appbar__title {
	flex: 1 1 auto;
	min-width: 0;
	padding: 0 4px;
	font-size: 17px;
	font-weight: 600;
	color: var( --lal-ink );
	text-align: center;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* ---------------------------------------------------------------------
 *  Tab-Leiste
 * ------------------------------------------------------------------ */

.lal-tabbar {
	position: fixed;
	inset: auto 0 0 0;
	z-index: 1000;
	display: flex;
	height: calc( var( --lal-tabbar-h ) + var( --lal-safe-bottom ) );
	padding-bottom: var( --lal-safe-bottom );
	/* Spiegelbildlich zur Titelzeile: unten deckend weiß, nach oben milchig.
	   Die Android-Gestenleiste darunter lässt sich aus einer PWA nicht
	   einfärben (das ginge nur als TWA), der deckende Streifen nimmt dem
	   Übergang aber die Härte. */
	background: linear-gradient(
		to top,
		#ffffff 0%,
		#ffffff 10%,
		rgba( 255, 255, 255, 0.90 ) 100%
	);
	backdrop-filter: saturate( 180% ) blur( 12px );
	-webkit-backdrop-filter: saturate( 180% ) blur( 12px );
	border-top: 1px solid var( --lal-line );
}

.lal-tabbar__item {
	position: relative;
	flex: 1 1 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	min-height: 44px;
	padding: 6px 0;
	font-size: 11px;
	font-weight: 500;
	line-height: 1;
	color: var( --lal-muted );
	text-decoration: none;
	-webkit-tap-highlight-color: transparent;
}

.lal-tabbar__item svg {
	display: block;
	width: 24px;
	height: 24px;
}

.lal-tabbar__item:active {
	background: rgba( 10, 31, 68, 0.04 );
}

.lal-tabbar__item.is-active {
	color: var( --lal-navy );
}

.lal-tabbar__item.is-active::before {
	content: "";
	position: absolute;
	top: 0;
	width: 28px;
	height: 3px;
	border-radius: 0 0 3px 3px;
	background: var( --lal-accent );
}

.lal-tabbar__item.is-disabled {
	opacity: 0.38;
	pointer-events: none;
}

/* Zähler der Merkliste. Sitzt als Abzeichen an der oberen rechten Ecke des
   Symbols; gefüllt wird er von eventhub-favorites.js über die Klasse
   .eventhub-favorites-count.

   Bewusst über :not([hidden]): das Skript blendet den Zähler bei leerer
   Merkliste per hidden-Attribut aus, und ein display-Wert hier würde das
   sonst aushebeln. */
.lal-tabbar__badge:not( [hidden] ) {
	position: absolute;
	top: 2px;
	left: calc( 50% + 4px );
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 16px;
	height: 16px;
	padding: 0 4px;
	border-radius: 8px;
	background: var( --lal-accent );
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 1;
	/* Der Rahmen in Leistenfarbe trennt das Abzeichen vom Symbol darunter. */
	box-shadow: 0 0 0 2px var( --lal-bg );
}

/* ---------------------------------------------------------------------
 *  Weiche Seitenwechsel (Cross-Document View Transitions)
 *
 *  Muss im CSS beider Seiten stehen – app.css lädt auf jeder App-Seite,
 *  also erfüllt. Die benannten Elemente werden beim Wechsel als dieselben
 *  erkannt und bleiben stehen, statt mit überzublenden.
 * ------------------------------------------------------------------ */

@view-transition {
	navigation: auto;
}

.lal-appbar {
	view-transition-name: lal-appbar;
}

.lal-tabbar {
	view-transition-name: lal-tabbar;
}

/* Richtungsabhängiger Wechsel: die neue Seite kommt von rechts herein, die
   alte zieht nach links ab – zurück spiegelverkehrt. Die Richtung setzt das
   Skript in app/footer.php per data-lal-nav auf <html>. Ohne Skript-Unter-
   stützung bleibt es beim Vorwärts-Verhalten. */

@keyframes lal-in-from-right {
	from { opacity: 0; transform: translateX( 30px ); }
}

@keyframes lal-out-to-left {
	to { opacity: 0; transform: translateX( -18px ); }
}

@keyframes lal-in-from-left {
	from { opacity: 0; transform: translateX( -30px ); }
}

@keyframes lal-out-to-right {
	to { opacity: 0; transform: translateX( 18px ); }
}

::view-transition-old( root ) {
	animation: lal-out-to-left 150ms cubic-bezier( 0.4, 0, 1, 1 ) both;
}

::view-transition-new( root ) {
	animation: lal-in-from-right 260ms cubic-bezier( 0, 0, 0.2, 1 ) both;
}

:root[data-lal-nav="back"]::view-transition-old( root ) {
	animation: lal-out-to-right 150ms cubic-bezier( 0.4, 0, 1, 1 ) both;
}

:root[data-lal-nav="back"]::view-transition-new( root ) {
	animation: lal-in-from-left 260ms cubic-bezier( 0, 0, 0.2, 1 ) both;
}

@media ( prefers-reduced-motion: reduce ) {
	::view-transition-group( * ),
	::view-transition-old( * ),
	::view-transition-new( * ) {
		animation: none !important;
	}
}
