diff --git a/development/config/import.mjs b/development/config/import.mjs
index da425fd2db8c6daa89207471d98fe9d04363eb5a..b7202242f58c0a00aac7a1667ab67374d937c814 100644
--- a/development/config/import.mjs
+++ b/development/config/import.mjs
@@ -1,8 +1,8 @@
 export const projectRoot = "/home/vs/workspaces/oss/monster/monster";
 export const sourcePath = "/home/vs/workspaces/oss/monster/monster/source";
 export const developmentPath = "/home/vs/workspaces/oss/monster/monster/development";
-export const pnpxBin = "/nix/store/rbdrkcs5kkwpalxcd7c6bnm33lk2955n-nodejs-20.19.0/bin/npx";
-export const nodeBin = "/nix/store/qsbvdw53nbhnzad466fvgczrw9kxc1vh-nodejs-23.11.0/bin/node";
+export const pnpxBin = "/nix/store/c8jxsih8yy2rnncdmx2hyraizf689nvp-nodejs-22.14.0/bin/npx";
+export const nodeBin = "/nix/store/wnayblhh0555nwfccnzcqkzph52y4yby-nodejs-24.1.0/bin/node";
 export const license = "/**" + "\n" +
     " * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved." + "\n" +
     " * Node module: @schukai/monster" + "\n" +
diff --git a/development/issues/closed/312.html b/development/issues/closed/312.html
index f4a2f24218ca4f4156b6435fe33b64e2484e76fc..b18ace65f4f66017ad5f1baf97bd1f211acc0e13 100644
--- a/development/issues/closed/312.html
+++ b/development/issues/closed/312.html
@@ -27,6 +27,13 @@
         <main>
 
             <!-- data-monster-option-features-lazyload="false" -->
+            <monster-tabs style="width: 100%"
+                          data-monster-option-features-opendelay="500">
+                <div data-monster-button-label="Leer" data-monster-state="active" class="active">
+                    EMPTY, zum testen von intersection observer
+                </div>
+                <div data-monster-button-label="Select">
+
 
             <monster-select
                     data-monster-option-features-lazyload="true"
@@ -43,6 +50,10 @@
                     data-monster-option-url="/issue-312?q={filter}"
                     data-monster-option-filter-defaultoptionsurl="/issue-312?q=1002">
             </monster-select>
+                </div>
+
+            </monster-tabs>
+
         </main>
     </body>
 </html>
diff --git a/development/issues/closed/312.mjs b/development/issues/closed/312.mjs
index 31c551a96a25c0044e82eaf93433b1d706178d9d..030cf9d33abfbcbcfed6f915a6ec5f72e1f106a1 100644
--- a/development/issues/closed/312.mjs
+++ b/development/issues/closed/312.mjs
@@ -12,4 +12,5 @@ import "../../../source/components/style/theme.pcss";
 import "../../../source/components/style/normalize.pcss";
 import "../../../source/components/style/typography.pcss";
 import "../../../source/components/form/select.mjs";
+import "../../../source/components/layout/tabs.mjs";
 
diff --git a/source/components/datatable/columnbar.mjs b/source/components/datatable/columnbar.mjs
index ed5637906907be257613f7bff9698de068b26af2..e6a57b156eb8420312d1152fc62c3e2b3f4234c1 100644
--- a/source/components/datatable/columnbar.mjs
+++ b/source/components/datatable/columnbar.mjs
@@ -23,6 +23,9 @@ import { clone } from "../../util/clone.mjs";
 import { ColumnBarStyleSheet } from "./stylesheet/column-bar.mjs";
 import { createPopper } from "@popperjs/core";
 import { getLocaleOfDocument } from "../../dom/locale.mjs";
+import {hasObjectLink} from "../../dom/attributes.mjs";
+import {customElementUpdaterLinkSymbol} from "../../dom/constants.mjs";
+import {getGlobalObject} from "../../types/global.mjs";
 
 export { ColumnBar };
 
@@ -56,6 +59,12 @@ const dotsContainerElementSymbol = Symbol("dotsContainerElement");
  */
 const popperInstanceSymbol = Symbol("popperInstance");
 
+/**
+ * @private
+ * @type {symbol}
+ */
+const closeEventHandlerSymbol = Symbol("closeEventHandler");
+
 /**
  * A column bar for a datatable
  *
@@ -72,7 +81,18 @@ class ColumnBar extends CustomElement {
 	 * @return {symbol}
 	 */
 	static get [instanceSymbol]() {
-		return Symbol.for("@schukai/monster/components/column-bar");
+		return Symbol.for("@schukai/monster/components/column-bar@@instance");
+	}
+
+	/**
+	 * This method is called to customize the component.
+	 * @returns {Map<unknown, unknown>}
+	 */
+	get customization() {
+		return new Map([
+			...super.customization,
+			["templateFormatter.i18n", true],
+		]);
 	}
 
 	/**
@@ -83,24 +103,61 @@ class ColumnBar extends CustomElement {
 	 *
 	 * @property {Object} templates Template definitions
 	 * @property {string} templates.main Main template
-	 * @property {object} datasource The datasource
-	 * @property {boolean} autoLoad If true, the datasource is called immediately after the control is created.
+	 * @property {object} labels Locale definitions
+	 * @property {string} locale.settings The text for the settings button
 	 */
 	get defaults() {
-		const obj = Object.assign({}, super.defaults, {
+		return Object.assign({}, super.defaults, {
 			templates: {
 				main: getTemplate(),
 			},
-			locale: getTranslations(),
+			labels: getTranslations(),
 
 			columns: [],
 		});
+	}
+
+	/**
+	 * Called every time the element is added to the DOM. Useful for running initialization code.
+	 * @return {void}
+	 * @since 4.14.0
+	 */
+	connectedCallback() {
+		super.connectedCallback();
+
+		this[closeEventHandlerSymbol] = (event) => {
+			const path = event.composedPath();
+			const isOutsideElement = !path.includes(this);
+			const isOutsideShadow = !path.includes(this.shadowRoot);
+
+			if (isOutsideElement && isOutsideShadow && this[settingsLayerElementSymbol]) {
+				this[settingsLayerElementSymbol].classList.remove("visible");
+			}
+		}
+
+		getGlobalObject("document").addEventListener("click" , this[closeEventHandlerSymbol]);
+		getGlobalObject("document").addEventListener("touch" , this[closeEventHandlerSymbol]);
 
-		return obj;
 	}
 
 	/**
+	 * Called every time the element is removed from the DOM. Useful for running clean up code.
 	 *
+	 * @return {void}
+	 * @since 4.14.0
+	 */
+	disconnectedCallback() {
+		super.disconnectedCallback();
+
+		if(this[closeEventHandlerSymbol]) {
+			getGlobalObject("document").removeEventListener("click", this[closeEventHandlerSymbol]);
+			getGlobalObject("document").removeEventListener("touch", this[closeEventHandlerSymbol]);
+			this[closeEventHandlerSymbol] = null;
+		}
+
+	}
+
+	/**
 	 * @return {string}
 	 */
 	static getTag() {
@@ -133,43 +190,47 @@ class ColumnBar extends CustomElement {
 function getTranslations() {
 	const locale = getLocaleOfDocument();
 	switch (locale.language) {
-		case "de":
-			return {
-				settings: "Einstellungen",
-			};
-		case "fr":
-			return {
-				settings: "Paramètres",
-			};
-		case "sp":
-			return {
-				settings: "Configuración",
-			};
-		case "it":
-			return {
-				settings: "Impostazioni",
-			};
-		case "pl":
-			return {
-				settings: "Ustawienia",
-			};
-		case "no":
-			return {
-				settings: "Innstillinger",
-			};
-		case "dk":
-			return {
-				settings: "Indstillinger",
-			};
-		case "sw":
-			return {
-				settings: "Inställningar",
-			};
-		default:
+		case "de": // German
+			return { settings: "Einstellungen" };
+		case "fr": // French
+			return { settings: "Paramètres" };
+		case "es": // Spanish
+			return { settings: "Configuración" };
+		case "zh": // Mandarin (Chinese)
+			return { settings: "设置" };
+		case "hi": // Hindi
+			return { settings: "सेटिंग्स" };
+		case "bn": // Bengali
+			return { settings: "সেটিংস" };
+		case "pt": // Portuguese
+			return { settings: "Configurações" };
+		case "ru": // Russian
+			return { settings: "Настройки" };
+		case "ja": // Japanese
+			return { settings: "設定" };
+		case "pa": // Western Punjabi
+			return { settings: "ਸੈਟਿੰਗਾਂ" };
+		case "mr": // Marathi
+			return { settings: "सेटिंग्ज" };
+		case "it": // Italian
+			return { settings: "Impostazioni" };
+		case "nl": // Dutch
+			return { settings: "Instellingen" };
+		case "sv": // Swedish
+			return { settings: "Inställningar" };
+		case "pl": // Polish
+			return { settings: "Ustawienia" };
+		case "da": // Danish
+			return { settings: "Indstillinger" };
+		case "fi": // Finnish
+			return { settings: "Asetukset" };
+		case "no": // Norwegian
+			return { settings: "Innstillinger" };
+		case "cs": // Czech
+			return { settings: "Nastavení" };
+		default: // English fallback
 		case "en":
-			return {
-				settings: "Settings",
-			};
+			return { settings: "Settings" };
 	}
 }
 
@@ -325,7 +386,7 @@ function getTemplate() {
         <div data-monster-role="control" part="control" data-monster-select-this="true" data-monster-attributes="class path:columns | has-entries | ?::hidden">
             <ul data-monster-insert="dots path:columns" 
                 data-monster-role="dots"></ul>
-            <a href="#" data-monster-role="settings-button" data-monster-replace="path:locale.settings">Settings</a>
+            <a href="#" data-monster-role="settings-button">i18n{settings}</a>
             <div data-monster-role="settings-layer">
                 <div data-monster-insert="column path:columns" data-monster-role="settings-popup-list">
                 </div>
diff --git a/source/components/form/select.mjs b/source/components/form/select.mjs
index f8060a565f8b64172fcca87225d47f65b17830df..f5c110e1adb0fe80d9e937e661d66ffb94914733 100644
--- a/source/components/form/select.mjs
+++ b/source/components/form/select.mjs
@@ -390,6 +390,7 @@ class Select extends CustomControl {
 	 * @property {"radio"|"checkbox"} type Selection mode: "radio" for single, "checkbox" for multiple.
 	 * @property {string} name Name of the hidden form field for form submission.
 	 * @property {string|null} url URL to dynamically fetch options via HTTP when opening or filtering.
+	 * @property {Object} lookup Configuration for lookup requests.
 	 * @property {string} lookup.url URL template with ${filter} placeholder to fetch only selected entries on init when `url` is set and either `features.lazyLoad` or `filter.mode==="remote"`.
 	 * @property {boolean} lookup.grouping Group lookup requests: true to fetch all selected values in one request, false to fetch each individually.
 	 * @property {string} fetch.redirect Fetch redirect mode (e.g. "error").
@@ -1354,51 +1355,64 @@ function getTranslations() {
 function lookupSelection() {
 	const self = this;
 
-	setTimeout(() => {
-		const selection = self.getOption("selection");
-		if (selection.length === 0) {
-			return;
-		}
+	const observer = new IntersectionObserver((entries, obs) => {
+		for (const entry of entries) {
+			if (entry.isIntersecting) {
+				console.log("IntersectionObserver: entry.target is visible");
+				obs.disconnect(); // Only observe once
 
-		if (self[isLoadingSymbol] === true) {
-			return;
-		}
+				setTimeout(() => {
+					const selection = self.getOption("selection");
+					if (selection.length === 0) {
+						return;
+					}
 
-		if (self[lazyLoadDoneSymbol] === true) {
-			return;
-		}
+					if (self[isLoadingSymbol] === true) {
+						return;
+					}
 
-		let url = self.getOption("url");
-		const lookupUrl = self.getOption("lookup.url");
-		if (lookupUrl !== null) {
-			url = lookupUrl;
-		}
+					if (self[lazyLoadDoneSymbol] === true) {
+						return;
+					}
 
-		this[cleanupOptionsListSymbol] = false;
+					let url = self.getOption("url");
+					const lookupUrl = self.getOption("lookup.url");
+					if (lookupUrl !== null) {
+						url = lookupUrl;
+					}
 
-		if (this.getOption("lookup.grouping") === true) {
-			filterFromRemoteByValue
-				.call(
-					self,
-					url,
-					selection.map((s) => s?.["value"]),
-				)
-				.catch((e) => {
-					addErrorAttribute(self, e);
-				});
-			return;
-		}
+					self[cleanupOptionsListSymbol] = false;
+
+					if (self.getOption("lookup.grouping") === true) {
+						filterFromRemoteByValue
+							.call(
+								self,
+								url,
+								selection.map((s) => s?.["value"]),
+							)
+							.catch((e) => {
+								addErrorAttribute(self, e);
+							});
+						return;
+					}
 
-		for (const s of selection) {
-			if (s?.["value"]) {
-				filterFromRemoteByValue.call(self, url, s?.["value"]).catch((e) => {
-					addErrorAttribute(self, e);
-				});
+					for (const s of selection) {
+						if (s?.["value"]) {
+							filterFromRemoteByValue.call(self, url, s["value"]).catch((e) => {
+								addErrorAttribute(self, e);
+							});
+						}
+					}
+				}, 100);
 			}
 		}
-	}, 100);
+	}, { threshold: 0.1 });
+
+	// Beobachte das Element selbst (dieses Element muss im DOM sein)
+	observer.observe(self);
 }
 
+
 /**
  *
  * @param url