html, body { height: 100%; margin: 0; background-color: #000; }
        #root { height: 100%; background-color: #000; }

        /* ── Scroll-Anchoring deaktivieren ────────────────────────────────
           Bei Impressum/Datenschutz verschiebt der Browser die Scroll-
           Position automatisch nach oben-gesetztem scrollTo(0,0), sobald
           nachträglich Inhalte (Bilder/Fonts/Framer-Animationen) oberhalb
           die Layouthöhe verändern ("Scroll Anchoring"). Das lässt die
           Seite beim 2./3. Aufruf mittig/unten landen. Global deaktivieren. */
        html, body, #root {
          overflow-anchor: none !important;
        }

        /* ── Scroll-Ruckler: GPU-Compositing-Hints ───────────────────── */
        /* Promote fixed elements to own GPU layer → smoother scrolling  */
        nav, #back-to-top {
          will-change: transform;
          -webkit-transform: translateZ(0);
          transform: translateZ(0);
        }

        /* ── Logo-Button: Fade beim Scrollen auf Unterseiten ────────────
           Auf Projekt-, Impressum- und Datenschutzseiten blendet das
           Desktop-Logo beim Runterscrollen sanft aus und beim Zurück-
           an-den-Anfang-Scrollen wieder ein.                           */
        body.is-detail-page button.absolute[aria-label="Zur Startseite"],
        body.is-legal-page  button.absolute[aria-label="Zur Startseite"] {
          transition: opacity 0.35s ease, pointer-events 0s 0.35s;
        }
        body.is-detail-page.logo-scrolled button.absolute[aria-label="Zur Startseite"],
        body.is-legal-page.logo-scrolled  button.absolute[aria-label="Zur Startseite"] {
          opacity: 0 !important;
          pointer-events: none !important;
          transition: opacity 0.35s ease;
        }

        /* ── Viewer Fullscreen: alles außer dem Viewer ausblenden ─────── */
        body.is-viewer-fullscreen > *:not(script):not(style) {
          visibility: hidden !important;
          pointer-events: none !important;
        }
        body.is-viewer-fullscreen iframe.lm-viewer-fs-active {
          visibility: visible !important;
          pointer-events: auto !important;
        }
        /* Reset transform/will-change im Fullscreen — verhindert Stacking-Context-Konflikte */
        body.is-viewer-fullscreen nav,
        body.is-viewer-fullscreen #back-to-top {
          will-change: auto !important;
          transform: none !important;
          -webkit-transform: none !important;
          display: none !important;
        }
        /* Smooth momentum scrolling on iOS (older devices) */
        html, body {
          -webkit-overflow-scrolling: touch;
          overscroll-behavior-y: none;
          overscroll-behavior-x: none;
        }
        /* GPU compositing hints — kein content-visibility (verursacht Flash beim Scrollen) */
        img, video {
          backface-visibility: hidden;
          -webkit-backface-visibility: hidden;
        }

        /* ── Mobile navigation through iPad mini landscape ──────────────
           The app's md breakpoint starts the desktop tabs at 768px. Keep
           the compact header and burger menu through 1024px so smartphones
           in landscape and iPad mini landscape do not switch to desktop. */
        @media (min-width: 768px) and (max-width: 1024px) {
          nav > div.md\:hidden {
            display: flex !important;
          }
          nav > div.hidden.md\:block {
            display: none !important;
          }
          nav + div[class*="top-14"][class*="z-40"] {
            display: block !important;
            overflow: hidden !important;
            transition: max-height 0.2s ease-out !important;
            background-color: #000 !important;
            -webkit-backdrop-filter: blur(4px) !important;
            backdrop-filter: blur(4px) !important;
            transform: translateZ(0) !important;
            -webkit-transform: translateZ(0) !important;
            isolation: isolate;
            /* Keep the menu labels aligned with the logo. The list already
               has 1rem horizontal padding, so the outer panel gets the
               matching 1rem on tablet widths. Notch insets are corrected
               below only where the navigation itself uses them. */
            padding-left: 1rem !important;
            padding-right: 1rem !important;
            box-sizing: border-box;
          }
          nav + div[class*="top-14"][class*="z-40"] ul {
            width: 100%;
            min-width: 0;
            box-sizing: border-box;
          }
          nav + div[class*="top-14"][class*="z-40"] button {
            display: block;
            width: 100%;
            min-width: max-content;
            white-space: nowrap;
            text-align: left;
          }
        }

        /* In smartphone landscape the nav itself moves inward for a
           camera/notch safe area. Subtract the list's existing 1rem so the
           first label remains exactly flush with the logo. */
        @media (orientation: landscape) and (max-width: 1024px) {
          nav + div[class*="top-14"][class*="z-40"] {
            padding-left: max(0px, calc(env(safe-area-inset-left, 0px) - 1rem)) !important;
            padding-right: max(0px, calc(env(safe-area-inset-right, 0px) - 1rem)) !important;
          }
        }

        /* ── Mobile Performance: Startseite ────────────────────────── */
        /* Floating particles: doppelter drop-shadow ist GPU-intensiv   */
        /* SVG-Hintergrund: infinite stroke-Animationen paused stellen  */
        @media (max-width: 767px) {
          /* Drop-shadow-Filter der animierten Partikel entfernen       */
          .absolute[style*="drop-shadow"] {
            filter: none !important;
          }
          /* Infinite CSS-Animationen auf SVG-Elementen pausieren       */
          svg line, svg circle, svg path, svg polyline, svg rect {
            animation-play-state: paused !important;
            animation-duration: 0.001ms !important;
          }
          /* Ausnahme: Lade-Logo im Transition-Overlay soll auch mobil animieren */
          #lm-transition .lm-t-pw,
          #lm-transition .lm-t-po,
          #lm-transition .lm-t-pw2 {
            animation-play-state: running !important;
            animation-duration: 2.4s !important;
          }
          /* GPU-Kompositing-Layer-Hints reduzieren                     */
          .absolute[style*="transform"] {
            will-change: auto !important;
          }

          /* Firefox Android kann fixe Elemente, die per translateZ(0)
             künstlich in eine eigene Compositor-Ebene gezwungen werden,
             beim Wechsel der Browser-UI kurz relativ zum Visual Viewport
             versetzen. Das sieht beim langsamen Wischen wie ein Springen
             der darunterliegenden Bilder aus. Für fixe UI-Elemente die
             künstliche Ebene deshalb auf Mobilgeräten nicht erzwingen. */
          nav,
          #back-to-top {
            will-change: auto !important;
            transform: none !important;
            -webkit-transform: none !important;
          }
        }

        /* ── Ältere Desktop-/Laptop-Geräte: ruhiger Erst-Render ──────────
           Nur dekorative Kompositor-Effekte werden entlastet. Portfolio-
           Bilder, Projektmedien, Auflösung und sichtbare Layouts bleiben
           unverändert. Nach 1,8 s laufen die Animationen wieder normal. */
        html.lm-low-power-boot [aria-hidden="true"].pointer-events-none {
          filter: none !important;
          -webkit-filter: none !important;
          will-change: auto !important;
        }
        html.lm-low-power-boot nav {
          backdrop-filter: none !important;
          -webkit-backdrop-filter: none !important;
        }
        html.lm-low-power-boot .fixed.top-0.left-0.pointer-events-none.z-\[9998\],
        html.lm-low-power-boot .fixed.top-0.left-0.pointer-events-none.z-\[9999\] {
          will-change: auto !important;
        }
        html.lm-low-power-boot [aria-hidden="true"].pointer-events-none *,
        html.lm-low-power-boot [aria-hidden="true"].pointer-events-none {
          animation-play-state: paused !important;
        }
        html.lm-low-power-boot .fixed.top-0.left-0.pointer-events-none.z-\[9998\],
        html.lm-low-power-boot .fixed.top-0.left-0.pointer-events-none.z-\[9999\] {
          visibility: hidden !important;
        }

        /* ── Über mich: Profilbild etwas heller ─────────────────────── */
        /* Inline-Style: grayscale(20%) contrast(1.08) brightness(0.85)  */
        img[style*="center 10%"] {
          filter: grayscale(8%) contrast(1.06) brightness(0.97) !important;
        }

        /* ── Portfolio Cover: heller auf Desktop ─────────────────────── */
        /* Default idle-State ist brightness(0.7) grayscale(30%) — auf   */
        /* Desktop (≥768px) etwas aufhellen ohne den Stil zu brechen.    */
        @media (min-width: 768px) {
          img.group-hover\:scale-105 {
            filter: brightness(0.88) contrast(1.05) grayscale(12%) !important;
          }
        }

        /* ── Querformat-Notch/Kamera: Safe-Area-Insets ───────────────── */
        /* Push root content away from notch in landscape mode           */
        @media (orientation: landscape) and (max-width: 932px) {
          #root {
            padding-left: env(safe-area-inset-left, 0px);
            padding-right: env(safe-area-inset-right, 0px);
          }
          /* Fixed nav also needs horizontal safe-area padding */
          nav {
            padding-left: max(1rem, env(safe-area-inset-left)) !important;
            padding-right: max(1rem, env(safe-area-inset-right)) !important;
          }
          /* Fixed bottom elements (cookie banner etc.) */
          .fixed.bottom-0 {
            padding-left: max(1rem, env(safe-area-inset-left)) !important;
            padding-right: max(1rem, env(safe-area-inset-right)) !important;
          }
        }

        /* Back-to-top button — mobile only */
        #back-to-top {
          display: none;
          position: fixed;
          bottom: calc(24px + env(safe-area-inset-bottom, 0px));
          right: 20px;
          z-index: 999;
          width: 40px;
          height: 40px;
          background: transparent;
          border: 1px solid rgba(255,255,255,0.25);
          color: rgba(255,255,255,0.6);
          font-size: 18px;
          cursor: pointer;
          align-items: center;
          justify-content: center;
          transition: border-color 0.15s, color 0.15s;
        }
        #back-to-top:hover {
          border-color: #ff6d00;
          color: #ff6d00;
        }
        @media (min-width: 768px) {
          #back-to-top { display: none !important; }
        }

        /* Hide back-to-top when lightbox/gallery is open */
        body.is-lightbox-open #back-to-top {
          display: none !important;
        }

        /* Close button for the fullscreen 3D viewer (desktop + mobile) */
        #viewer-close-btn {
          position: fixed;
          top: calc(env(safe-area-inset-top, 0px) + 12px);
          right: calc(env(safe-area-inset-right, 0px) + 12px);
          z-index: 100000;
          width: 40px;
          height: 40px;
          border-radius: 50%;
          border: none;
          background: rgba(0,0,0,0.55);
          color: rgba(255,255,255,0.9);
          display: none;
          align-items: center;
          justify-content: center;
          font-size: 22px;
          line-height: 1;
          cursor: pointer;
          -webkit-tap-highlight-color: transparent;
          backdrop-filter: blur(4px);
          -webkit-backdrop-filter: blur(4px);
          transition: background .15s;
        }
        #viewer-close-btn:hover { background: rgba(0,0,0,0.75); }
        body.is-viewer-fullscreen #viewer-close-btn {
          display: flex;
        }

        /* Extra close (X) button for the fullscreen image-gallery lightbox,
           mobile only. The lightbox already closes on Escape/tap-outside,
           but on touch this button gives a clear, always-visible way out. */
        #gallery-close-btn {
          position: fixed;
          top: calc(env(safe-area-inset-top, 0px) + 12px);
          right: calc(env(safe-area-inset-right, 0px) + 12px);
          z-index: 100000;
          width: 40px;
          height: 40px;
          border-radius: 50%;
          border: none;
          background: rgba(0,0,0,0.55);
          color: rgba(255,255,255,0.9);
          display: none;
          align-items: center;
          justify-content: center;
          font-size: 22px;
          line-height: 1;
          cursor: pointer;
          -webkit-tap-highlight-color: transparent;
        }
        body.is-lightbox-open #gallery-close-btn {
          display: none;
        }
        @media (max-width: 767px) {
          body.is-lightbox-open #gallery-close-btn {
            display: flex;
          }
        }

        @media (max-width: 767px) {
          /* Portfolio-Karten: Software-Tags auf Mobil ausblenden */
          .lm-sw-tags { display: none !important; }

          /* Beschreibungstext auf Mobil komplett ausblenden */
          .lm-desc-wrap { display: none !important; }

          /* Titelzeile → Kategorie-Label: Abstand reduzieren wie STANDORT/Bad Dürkheim */
          .flex.items-start.justify-between.gap-4.mb-3 { margin-bottom: 0.1rem !important; }

          /* Karte gedrückt: sofort orange Titel + helles Bild + Pfeil sichtbar */
          a.group:active h3 { color: #ff6d00 !important; transition: none !important; }
          a.group:active img.object-cover {
            filter: brightness(1.0) contrast(1.1) !important;
            transition: none !important;
          }
          a.group:active span.absolute.bottom-4.right-4 {
            opacity: 1 !important;
            transform: translate(0,0) !important;
            transition: none !important;
          }

          /* Mobile performance: hide shapes on all pages EXCEPT home page */
          body:not(.is-home-page) [aria-hidden="true"].pointer-events-none {
            display: none !important;
          }

          /* On home page: show only first 4 shapes (children 2–5) + SVG lines (child 1).
             Hide the rest (children 6+) to limit CPU load to ~4 animations. */
          body.is-home-page [aria-hidden="true"].pointer-events-none > *:nth-child(n+6) {
            display: none !important;
          }

          /* Also hide custom cursor tracker (not needed on touch devices) */
          .fixed.z-\[9998\],
          .fixed.z-\[9999\] {
            display: none !important;
          }

          /* ── Weißer Streifen bei Burger-Nav-Klick unterdrücken ─────────────
             Framer animiert Seiten-Wrapper mit initial:{y:20}→animate:{y:0}.
             Auf Mobil sweept das 20px-Offset des großen LUCAS/MUSIL-Texts
             als heller Streifen durchs Bild. CSS !important überschreibt
             Framers Inline-Style jeden Frame → Y bleibt bei 0, Opacity
             läuft weiter. Die Nav wird zusätzlich bei Y=0 fixiert damit
             kein "Slide-down"-Effekt des Nav-Balkens sichtbar wird.         */
          /* Nur Nicht-Bild-Elemente: translateY unterdrücken (verhindert weißen Streifen).
             Bilder NICHT einschließen — Framer Motions Slide-up soll bei Bildern erhalten bleiben. */
          #root [style*="translateY"]:not(img):not(figure):not(picture) {
            transform: translateZ(0) !important;
          }
          nav {
            transform: translateZ(0) !important;
          }

          /* ── Mobile: Bilder auf GPU-Layer vorlagern → kein Compositor-Flicker ──
             Deckt Cover-Bilder im Portfolio und Bilder auf Detailseiten ab.       */
          a[href*="/projekt/"] img,
          .bg-zinc-900 img,
          div[class*="overflow-hidden"] img {
            transform: translateZ(0);
            backface-visibility: hidden;
            -webkit-backface-visibility: hidden;
          }

          /* ── Weißes Flackern beim Portfolio-Einrollen verhindern ───────────
             Framer Motion animiert Portfolio-Karten und Bilder mit
             initial:{opacity:0} beim Einrollen in den Viewport. In dieser
             Phase ist der Container transparent → Browser zeigt kurz den
             Standard-Hintergrund (weiß/hell) dahinter.
             Fix: Alle Bild-Container, Portfolio-Karten und Section explizit
             auf schwarz setzen — egal ob opacity:0 oder 1, kein Weiß sichtbar. */
          #arbeit,
          #arbeit .grid,
          #arbeit .grid > a,
          #arbeit .grid > a > div {
            background-color: #000 !important;
          }

          a[href*="/projekt/"] div[class*="overflow-hidden"],
          div[class*="overflow-hidden"]:has(img) {
            background-color: #000 !important;
          }

          /* Bild-Elemente selbst: verhindert weißen Img-Placeholder */
          a[href*="/projekt/"] img,
          #arbeit img {
            background-color: #000 !important;
          }

          /* ── Burger-Overlay: dekorative Linien-Animation unterdrücken ──────
             Das Nav-Overlay (z-[99999]) enthält 6 animierte horizontale
             Scan-Lines und Ecken-Klammern als Deko-SVGs (Framer-Motion-
             gesteuert — animation-play-state greift hier nicht).
             Auf Mobil wirken sie komisch/störend; nur das LM-Logo-SVG
             (viewBox "0 0 344.34 258.18") bleibt sichtbar.               */
          .z-\[99999\] svg:not([viewBox="0 0 344.34 258.18"]) {
            display: none !important;
          }

          /* ── Burger-Dropdown: weißen Streifen beim Aufklappen entfernen ────
             Der Mobile-Menü-Container animiert max-height 0→240px mit
             transition-all (erbt dadurch auch eine backdrop-filter/background
             -Überblendung). Das gemeinsame Animieren von max-height + blur
             erzeugt auf vielen Mobil-Browsern einen hellen Renderer-Seam am
             wachsenden Rand. Fix: nur max-height animieren, Hintergrund/Blur
             sofort fix setzen + eigene Compositing-Layer erzwingen.          */
          nav + div[class*="top-14"][class*="z-40"] {
            transition: max-height 0.2s ease-out !important;
            background-color: #000 !important;
            -webkit-backdrop-filter: blur(4px) !important;
            backdrop-filter: blur(4px) !important;
            transform: translateZ(0) !important;
            -webkit-transform: translateZ(0) !important;
            isolation: isolate;
          }

          /* ── Animated logo: visibility controlled via JS (see syncLogoVisibility) ── */

           /* Animated background layer: clamp to viewport height so the SVG logo
              never scales below the first section divider, regardless of page length.
              100svh statt 100vh: svh ist die kleinste stabile Viewport-Höhe (mit
              sichtbarer Browser-UI) — ändert sich NICHT wenn die URL-Bar ein-/
              ausblendet → verhindert Layout-Sprünge beim Hochswipen. */
          .pointer-events-none.absolute.inset-0[aria-hidden="true"] {
            height: 100svh !important;
            overflow: hidden !important;
          }

          /* Reduce spacing between media blocks on mobile detail pages */
          body.is-detail-page .mb-12 {
            margin-bottom: 1.5rem !important;
          }
          body.is-detail-page .mb-16 {
            margin-bottom: 2rem !important;
          }

          /* Safe area: push fixed bottom elements above browser UI chrome */
          .fixed.bottom-0 {
            padding-bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px)) !important;
          }

          /* Stable viewport height for full-height sections on mobile.
             Do not use 100dvh here: Firefox Android (and some Chromium
             browsers) changes dvh while the URL bar animates during a swipe.
             That resizes the hero and shifts every image below it. svh keeps
             the document layout stable while the browser chrome changes. */
          .min-h-screen {
            min-height: 100svh;
          }

          /* ── Alle Abschnitte: gleicher Abstand oben wie #ueber (py-12 = 3rem) ─── */
          #arbeit, #skills, #kontakt {
            padding-top: 3rem !important;
          }
        }

        /* ── Seitenweites Hintergrundraster stabilisieren ────────────────
           Das Bundle zeichnet ein 28px-Raster mit halbtransparentem Weiß.
           Sehr niedrige Alpha-Werte werden je nach Display-Gamma und
           Browser-Skalierung sichtbar unterschiedlich gerastert. Eine feste
           RGB-Farbe, feste Kachelgröße und feste Ausgangsposition halten
           Kontrast und Ausrichtung über Desktop-Varianten hinweg stabil. */
        #root > div.relative.overflow-x-hidden {
          background-color: #000 !important;
          background-image:
            linear-gradient(#0e0e0e 1px, transparent 1px),
            linear-gradient(90deg, #0e0e0e 1px, transparent 1px) !important;
          background-size: 28px 28px !important;
          background-position: 0 0 !important;
        }

        /* ── Intro-Video: ab 1280px (~13" Laptop/Desktop-Viewport) ─────────── */
        .lm-intro-video { display: none !important; }
        @media (min-width: 1280px) {
          .lm-intro-video {
            display: block !important;
            right: calc(2rem + 12px) !important;
            opacity: 0 !important;
            transition: opacity 0.45s ease !important;
          }
          .lm-intro-video.lm-intro-ready {
            opacity: 1 !important;
          }
          .lm-intro-video > div.relative {
            background: #000 !important;
          }
          .lm-intro-video video {
            opacity: 0.95 !important;
            background: #000 !important;
          }
        }

        /* ── Animiertes Logo links im Hero: ab 1280px (~13" Viewport) ──────── */
        #lm-hero-logo { display: none !important; }
        @media (min-width: 1280px) {
          #lm-hero-logo { display: block !important; width: clamp(180px, 45vw, 720px) !important; }
        }
        /* 23,8–24" (~1920–2199px): näher an der kompakten 23,6"-Größe,
           ohne den abrupten Sprung auf mindestens 1000px. */
        @media (min-width: 1920px) and (max-width: 2199px) {
          #lm-hero-logo {
            left: clamp(2rem, 2vw, 3rem) !important;
            top: 50% !important;
            width: clamp(760px, 45vw, 900px) !important;
          }
        }
        /* Ab 25"+ (~2200px+): SVG proportional weiter vergrößern und
           horizontal/vertikal an der Referenzposition halten. */
        @media (min-width: 2200px) {
          #lm-hero-logo {
            left: clamp(2rem, 2vw, 3rem) !important;
            top: 50% !important;
            width: clamp(1120px, 48vw, 1450px) !important;
          }
        }
        /* 2560×1440 / 25"+: die ursprüngliche große Darstellung
           ausdrücklich wiederherstellen. Diese Stufe steht nach der
           kompakten 23,8–24"-Regel und gewinnt bei breiten Monitoren. */
        @media (min-width: 2400px) {
          #lm-hero-logo {
            width: clamp(1120px, 50vw, 1450px) !important;
          }
        }
        /* 2560px-Display mit Betriebssystem-Skalierung: die CSS-Viewport-
           breite kann unter 2400px liegen, soll aber trotzdem groß bleiben. */
        @media (min-width: 1280px) and (max-width: 2399px) {
          html.lm-wide-monitor #lm-hero-logo {
            left: clamp(2rem, 2vw, 3rem) !important;
            top: 50% !important;
            width: clamp(1120px, 50vw, 1450px) !important;
          }
        }

        /* ── Hero-Titel: auf Desktop/Laptop kompakter halten ───────────────
           Die JS-Inlinegröße war mit 14vw/14rem auf 15", 17" und 24"
           unnötig dominant. Mobil bleibt die bestehende Größe unverändert. */
        @media (min-width: 768px) {
          body.is-home-page section.min-h-screen > div.transition-all.duration-700 > h1 {
            font-size: clamp(4rem, 9vw, 10rem) !important;
          }
        }
        /* ── 24"+: Hero-Titel moderat vergrößern ───────────────────────── */
        @media (min-width: 1920px) and (max-width: 2199px) {
          body.is-home-page section.min-h-screen > div.transition-all.duration-700 > h1 {
            font-size: clamp(12rem, 10vw, 18rem) !important;
          }
        }
        /* ── Sehr breite Desktops: Hero-Titel deutlich vergrößern ─────────
           Ab etwa 25" wächst der Titel passend zum größeren SVG weiter,
           ohne die kleineren Desktop- und Laptop-Stufen zu verändern. */
        @media (min-width: 2200px) {
          body.is-home-page section.min-h-screen > div.transition-all.duration-700 > h1 {
            font-size: clamp(16rem, 16vw, 26rem) !important;
          }
        }
        /* ── 25"-BenQ bei 2560×1440: Titel nochmals kompakter ──────────────
           Die sehr breite Desktop-Stufe bleibt erhalten, wirkt auf diesem
           Monitor aber mit etwas weniger Fläche ausgewogener. */
        @media (min-width: 2400px) {
          body.is-home-page section.min-h-screen > div.transition-all.duration-700 > h1 {
            font-size: clamp(12rem, 11.8vw, 18.8rem) !important;
          }
        }

        /* ── Größere Hochformat-Handys: Hero-Titel etwas präsenter ────────
           Größere Viewports lassen bei der nach unten ausgerichteten Hero-
           Fläche sonst deutlich mehr Leerraum oberhalb des Titels entstehen.
           Diese zusätzliche Regel greift erst oberhalb des iPhone-15-
           Viewports, damit dessen bewährte Aufteilung unverändert bleibt. */
        @media (max-width: 767px) and (min-width: 400px) and (min-height: 860px) {
          body.is-home-page section.min-h-screen h1 {
            font-size: clamp(3.2rem, 16vw, 4.5rem) !important;
          }
        }

        /* ── Hero Info-Zeile: bei 768–1150px auf Column-Stack umschalten ───
           In diesem Bereich würden Beruf/Standort/Status den zentrierten
           Scroll-Indikator überlagern. Lösung: dasselbe vertikale Layout
           wie Mobile Portrait — kein Overlap mehr möglich.                  */
        @media (min-width: 768px) and (max-width: 1280px) {
          /* Stack: Beruf → Standort → Status untereinander */
          body.is-home-page section.min-h-screen > div.mt-12 {
            flex-direction: column !important;
            align-items: flex-start !important;
            gap: 0.5rem !important;
          }
          /* md:text-right zurücksetzen — links ausrichten wie Mobile */
          body.is-home-page section.min-h-screen > div.mt-12 > div:nth-child(2),
          body.is-home-page section.min-h-screen > div.mt-12 > div:nth-child(3) {
            text-align: left !important;
          }
          /* Status-Indikator (Flex-Row mit Punkt): links ausrichten */
          body.is-home-page section.min-h-screen > div.mt-12 > div:nth-child(3) p {
            justify-content: flex-start !important;
          }
        }

        /* ── Über mich: zwischen 768–1023px auf 1-Spalte erzwingen ──────── */
        /* Verhindert dass Bild + Text bei iPad Hochformat zu schmal werden  */
        @media (min-width: 768px) and (max-width: 1023px) {
          #ueber .grid {
            grid-template-columns: 1fr !important;
          }
          /* Text darf breiter werden, max-w-sm aufheben */
          #ueber .max-w-sm {
            max-width: 100% !important;
          }
        }

        /* ── Tablet + kleiner Laptop (768–1279 px): 2-Spalten-Portfolio-Layout
           Mobile <768 px = 1 Spalte.
           Tablet + Laptop bis 1279 px = 2 Spalten (saubere Zwischenstufe).
           Desktop ≥ 1280 px = 3 Spalten — genug Platz für alle Inhalte.   */
        @media (min-width: 768px) and (max-width: 1279px) {

          /* 1. Portfolio-Grid: 2 Spalten statt 3 */
          #arbeit .grid {
            grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
          }

          /* 2. Trennlinien für 2-Spalten-Raster korrekt setzen
                JS berechnet Borders für 3 Spalten — hier für 2 überschreiben */
          #arbeit .grid > a {
            border-right: 1px solid rgba(255,255,255,0.1) !important;
            border-bottom: 1px solid rgba(255,255,255,0.1) !important;
          }
          #arbeit .grid > a:nth-child(2n) {
            border-right: none !important;
          }
          #arbeit .grid > a:nth-last-child(-n+2) {
            border-bottom: none !important;
          }

          /* 3. Software-Tags ausblenden wie auf Mobil */
          .lm-sw-tags { display: none !important; }

          /* 4. Beschreibungs-Bereich verstecken (vermeidet Leerraum durch
                min-height: 64px im inaktiven Hover-Zustand)                */
          #arbeit a.group div.relative.mb-3 {
            display: none !important;
          }

          /* 5. Kategorie-Untertitel: unter den Titel statt daneben
                sm:inline (neben Titel) ausblenden → sm:hidden (unter Titel) zeigen */
          #arbeit span.whitespace-nowrap.sm\:inline {
            display: none !important;
          }
          #arbeit .sm\:hidden.mb-2 {
            display: block !important;
          }

          /* 6. Kategorie-Text: Zeilenumbruch erlauben, nicht abschneiden */
          #arbeit .p-5 .text-xs.text-white\/30 {
            white-space: normal !important;
          }

          /* 7. Titelzeile: Abstand zum Kategorie-Label reduzieren wie Mobil */
          #arbeit .flex.items-start.justify-between.gap-4.mb-3 {
            margin-bottom: 0.1rem !important;
          }

          /* 8. Titel: immer 2-Zeilen Höhe reservieren — verhindert dass die
                Kategorie darunter "springt" wenn ein Titel umbricht          */
          #arbeit a.group h3 {
            min-height: calc(0.875rem * 1.25 * 2); /* text-sm × leading-tight × 2 */
            display: flex;
            align-items: flex-start;
          }
        }

        /* ── Desktop ≥ 1280 px: Kategorie-Text neben Titel — kein Abschneiden ──
           Sicherstellen dass der lange Kategorie-Text (z.B. "3D-Visualisierung /
           Fotogrammetrie") auf dem Desktop-Layout sauber umbricht statt clippt.
           Auch hier: 2-Zeilen-Mindesthöhe für h3 damit Kategorie-Label stabil
           bleibt wenn Titel auf schmalem 3-Spalten-Desktop umbricht.         */
        @media (min-width: 1280px) {
          #arbeit .p-5 span.whitespace-nowrap.sm\:inline {
            white-space: normal !important;
            text-align: right;
          }
          #arbeit a.group h3 {
            min-height: calc(0.875rem * 1.25 * 2); /* text-sm × leading-tight × 2 */
          }
        }

        /* ── Background shapes & grid: lift brightness slightly ──────────── */
         /* brightness(1.4) gives the strengthened SVG contours a little more
            presence without affecting foreground content. */
        /* Only affects aria-hidden decorative layer — no foreground impact  */
        [aria-hidden="true"].pointer-events-none {
           filter: brightness(1.4);
          /* Promote to own compositor layer so the filter is resolved on the
             GPU as a pre-composited texture. Without this the browser must
             re-apply the filter on the main compositor pass every animation
             frame (60×/s from the SVG stroke animations), stealing bandwidth
             that the cursor compositor layer also needs → cursor stutter.   */
          will-change: transform;
          contain: paint;
        }

        /* ── Hintergrund-Grid: sichtbar, aber zurückhaltend ───────────────
           Das Grid wird im Bundle als Inline-Background gesetzt. Die geringere
           Deckkraft verhindert unterschiedlich dominant wirkende Rasterlinien
           auf Displays mit abweichender Pixel-Dichte. */
        #root > div.relative.overflow-x-hidden {
          background-image:
            linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px) !important;
          background-size: 28px 28px !important;
          background-position: 0 0 !important;
        }
        /* Tagsüber gegen direkte Lichteinstrahlung besser sichtbar.
           Nachts bleibt das bisherige zurückhaltende Raster unverändert. */
        html.lm-grid-day #root > div.relative.overflow-x-hidden {
          background-image:
            linear-gradient(rgba(255,255,255,0.06) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255,255,255,0.06) 1px, transparent 1px) !important;
        }

        /* ── Desktop-Cursor: weich ausblenden ─────────────────────────
           Framer setzt die Cursor-Opazität inline. Die Transition muss
           deshalb hier separat definiert werden, damit der Punkt beim
           Verlassen des Browserfensters/der Seite nicht abrupt verschwindet.
           Die beiden zusätzlichen Klassen werden am Dokumentrand gesetzt;
           der Selektor ist bewusst auf die Cursor-Struktur begrenzt und
           betrifft nicht den z-[9999]-Seitenloader.                         */
        @media (pointer: fine) {
          .fixed.top-0.left-0.pointer-events-none.z-\[9998\],
          .fixed.top-0.left-0.pointer-events-none.z-\[9999\] {
            transition: opacity 0.35s ease !important;
          }
          html.lm-pointer-out
          .fixed.top-0.left-0.pointer-events-none.z-\[9998\],
          html.lm-pointer-out
          .fixed.top-0.left-0.pointer-events-none.z-\[9999\] {
            opacity: 0 !important;
          }
        }

        /* Respect system-level "reduce motion" preference on all devices */
        @media (prefers-reduced-motion: reduce) {
          [aria-hidden="true"].pointer-events-none {
            display: none !important;
          }
          *, *::before, *::after {
            animation-duration: 0.01ms !important;
            transition-duration: 0.01ms !important;
          }
        }

        /* ── Page Transition / Nav-Loader ────────────────────────────── */
        #lm-transition {
          position: fixed;
          inset: 0;
          z-index: 10000; /* above cursors (9998/9999), below viewer (99999) */
          background: #000;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          opacity: 0;
          pointer-events: none;
          /* Nur beim Ausblenden sanft (fade-out). Das Einblenden muss SOFORT
             passieren (kein transition), sonst blitzt während der 0.2s
             Übergangszeit kurz die darunterliegende Seite durch, bevor die
             Ladefläche deckend ist ("Aufblitzen"-Bug).                      */
          transition: opacity 0.2s ease;
          font-family: 'IBM Plex Mono', monospace;
        }
        #lm-transition.lm-t-active {
          opacity: 1;
          pointer-events: auto;
          touch-action: none;
          transition: none;
        }
        /* Initial-load blocker: invisible but blocks all touch/scroll */
        #lm-transition.lm-t-init {
          opacity: 0;
          pointer-events: auto;
          touch-action: none;
          transition: none;
        }
        /* Initialer Asset-Loader: bereits während React mountet sichtbar.
           Nach Abschluss wird lm-t-boot entfernt; lm-t-init bleibt bis zur
           normalen App-Initialisierung als unsichtbare Scroll-Sperre bestehen. */
        #lm-transition.lm-t-boot {
          opacity: 1;
          pointer-events: auto;
          touch-action: none;
          transition: none;
        }
        body.lm-loading,
        html.lm-loading {
          overflow: hidden !important;
          touch-action: none !important;
        }
        /* Custom cursor (desktop): nur beim ersten Seitenaufruf ausblenden,
           danach sanft einblenden — bei Nav-Übergängen bleibt er sichtbar */
        body.lm-cursor-init .fixed.z-\[9998\],
        body.lm-cursor-init .fixed.z-\[9999\] {
          opacity: 0 !important;
          pointer-events: none !important;
          transition: opacity 0.5s ease !important;
        }
        body:not(.lm-cursor-init) .fixed.z-\[9998\],
        body:not(.lm-cursor-init) .fixed.z-\[9999\] {
          transition: opacity 0.5s ease;
        }
        /* Inline LM-logo inside the nav-transition overlay */
        .lm-t-logo   { width: 86px; height: auto; margin-bottom: 2rem; display: block; overflow: visible; }
        @keyframes lmNavDraw {
          0%   { stroke-dashoffset: var(--l); opacity: 0; }
          14%  { opacity: 1; }
          50%  { stroke-dashoffset: 0; opacity: 1; }
          86%  { stroke-dashoffset: 0; opacity: 1; }
          100% { stroke-dashoffset: var(--l); opacity: 0; }
        }
        .lm-t-pw  { --l:1200; stroke-dasharray:1200; stroke-dashoffset:1200;
                    animation: lmNavDraw 2.4s ease-in-out 0s   infinite; }
        .lm-t-po  { --l:1100; stroke-dasharray:1100; stroke-dashoffset:1100;
                    animation: lmNavDraw 2.4s ease-in-out 0.38s infinite; }
        .lm-t-pw2 { --l:420;  stroke-dasharray:420;  stroke-dashoffset:420;
                    animation: lmNavDraw 2.4s ease-in-out 0.76s infinite; }
        /* Only the first page visit uses the solid white app-loader logo. */
        #lm-transition.lm-t-boot .lm-t-logo {
          width: auto;
          height: 80px;
          margin-bottom: 3rem;
          fill: #fff;
          animation: lmInitialPulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
        }
        #lm-transition.lm-t-boot .lm-t-logo path {
          fill: #fff;
          stroke: none;
          animation: none;
        }
        @keyframes lmInitialPulse {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.5; }
        }
        /* These dimensions mirror the second-visit React loader exactly. */
        .lm-t-pct    { color: rgba(255,255,255,0.6); font-size: 0.75rem; letter-spacing: 0.1em; margin-bottom: 0.75rem; min-width: 3ch; text-align: center; }
        .lm-t-row    { display: flex; align-items: center; width: 16rem; }
        .lm-t-brack  { color: rgba(255,255,255,0.2); font-size: 0.75rem; }
        .lm-t-track  { width: 16rem; height: 1px; background: rgba(255,255,255,0.1); position: relative; overflow: hidden; }
        .lm-t-fill   { position: absolute; left: 0; top: 0; height: 100%; width: 0%; background: #ff6d00; transition: width 0.1s ease-out; box-shadow: 0 0 12px rgba(255,109,0,0.6); }
        .lm-t-brackets { display: flex; justify-content: space-between; width: 16rem; margin-top: 0.5rem; }
        .lm-t-label  { margin-top: 2rem; color: rgba(255,255,255,0.3); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; }
        @media (min-width: 768px) {
          .lm-t-row, .lm-t-track, .lm-t-brackets { width: 24rem; }
        }
        /* Mobile: Beim direkten Aufruf soll die Seite ohne sichtbaren
           Start-Ladebalken erscheinen. Der Navigations-Loader bleibt jedoch
           aktiv, damit interne Wechsel (Projekte, Impressum, Datenschutz)
           auch auf kleinen Viewports den gleichen Übergang wie Desktop zeigen. */
        @media (max-width: 767px) {
          /* Der unsichtbare Initial-Blocker darf den direkten Seitenaufruf
             nicht blockieren. lm-t-active wird bei interner Navigation
             weiterhin sichtbar und blockierend. */
          #lm-transition.lm-t-init,
          #lm-transition.lm-t-boot {
            display: none !important;
          }
          #root > div.fixed.inset-0.bg-black {
            display: none !important;
          }
          body.lm-loading,
          html.lm-loading {
            overflow: auto !important;
            touch-action: auto !important;
          }
        }
        @media (prefers-reduced-motion: reduce) {
          #lm-transition { display: none !important; }
        }

        /* ── Ältere Desktop-/Laptop-Geräte: Kompromissmodus ────────────────
           Hintergrund und Cursor bleiben sichtbar. Nur ein Teil der
           dekorativen Formen läuft weiter; teure Filter werden vermieden.
           Portfolio-Bilder, Projektmedien und ihre Qualität bleiben gleich. */
        html.lm-low-power-boot [aria-hidden="true"].pointer-events-none {
          filter: none !important;
          -webkit-filter: none !important;
          will-change: auto !important;
          contain: paint;
        }
        html.lm-low-power-boot .fixed.top-0.left-0.pointer-events-none.z-\[9998\],
        html.lm-low-power-boot .fixed.top-0.left-0.pointer-events-none.z-\[9999\] {
          will-change: auto !important;
          transition: none !important;
        }
        html.lm-low-power-boot .lm-intro-video video {
          filter: none !important;
          -webkit-filter: none !important;
        }
        html.lm-low-power-boot nav {
          backdrop-filter: none !important;
          -webkit-backdrop-filter: none !important;
        }

        /* ── Haupt-Trennlinien wie die animierte Hero-Logo-Linie ─────── */
        #arbeit > div:first-child,
        #ueber > div:first-child,
        #skills > div:first-child,
        #kontakt > div:first-child {
          border-bottom-width: 0.7px !important;
          border-bottom-color: rgba(255, 255, 255, 0.18) !important;
        }

        /* Feiner Mittelwert für die skalierte SVG-Linie auf Desktop. */
        @media (min-width: 1280px) {
          #arbeit > div:first-child,
          #ueber > div:first-child,
          #skills > div:first-child,
          #kontakt > div:first-child {
            border-bottom-width: 1px !important;
          }
        }
        @media (min-width: 1920px) and (max-width: 2199px) {
          #arbeit > div:first-child,
          #ueber > div:first-child,
          #skills > div:first-child,
          #kontakt > div:first-child {
            border-bottom-width: 1.5px !important;
          }
        }
        @media (min-width: 2200px) {
          #arbeit > div:first-child,
          #ueber > div:first-child,
          #skills > div:first-child,
          #kontakt > div:first-child {
            border-bottom-width: 1.75px !important;
          }
        }

        /* Hero-Abschlusslinie unter den Berufsdaten ebenfalls anpassen. */
        body.is-home-page section.min-h-screen > div.absolute.bottom-0.left-0.right-0.h-px {
          height: 0.7px !important;
          background: rgba(255, 255, 255, 0.18) !important;
        }
        @media (min-width: 1280px) {
          body.is-home-page section.min-h-screen > div.absolute.bottom-0.left-0.right-0.h-px {
            height: 1px !important;
          }
        }
        @media (min-width: 1920px) and (max-width: 2199px) {
          body.is-home-page section.min-h-screen > div.absolute.bottom-0.left-0.right-0.h-px {
            height: 1.5px !important;
          }
        }
        @media (min-width: 2200px) {
          body.is-home-page section.min-h-screen > div.absolute.bottom-0.left-0.right-0.h-px {
            height: 1.75px !important;
          }
        }

        /* Portfolio-Pagination: Seitenbreite Karten-Transition ──────────────
           overflow-x:clip beschneidet die ausgleitenden Karten ohne einen
           Scroll-Container zu erzeugen (fixed Pfeile bleiben korrekt). */
        #arbeit { overflow-x: clip; }

        /* ── Vorher/Nachher-Vergleichs-Slider (Bonus-Feature Projekte) ────────── */
        .ba-wrap { position: relative; }
        .ba-slider {
          position: relative;
          overflow: hidden;
          background: #18181b;
          aspect-ratio: 16 / 9;
          user-select: none;
          -webkit-user-select: none;
          touch-action: pan-y;
          cursor: ew-resize;
        }
        .ba-slider img {
          position: absolute;
          inset: 0;
          width: 100%;
          height: 100%;
          object-fit: cover;
          display: block;
          pointer-events: none;
          opacity: 0;
          transition: opacity 0.35s ease;
        }
        .ba-slider img.ba-loaded {
          opacity: 1;
        }
        /* shimmer shown while images are loading */
        @keyframes ba-shimmer {
          0%   { background-position: -200% 0; }
          100% { background-position:  200% 0; }
        }
        .ba-slider.ba-loading {
          background: linear-gradient(90deg,
            #1c1c1f 25%, #2a2a2e 50%, #1c1c1f 75%);
          background-size: 200% 100%;
          animation: ba-shimmer 1.4s infinite linear;
        }
        .ba-slider .ba-after {
          clip-path: inset(0 0 0 50%);
        }
        .ba-slider .ba-handle {
          position: absolute;
          top: 0;
          bottom: 0;
          left: 50%;
          width: 0;
          transform: translateX(-50%);
          pointer-events: none;
        }
        .ba-slider .ba-handle::before {
          content: '';
          position: absolute;
          top: 0;
          bottom: 0;
          left: 0;
          width: 1px;
          background: rgba(255,255,255,0.7);
        }
        .ba-slider .ba-handle-dot {
          position: absolute;
          top: 50%;
          left: 0;
          width: 40px;
          height: 40px;
          margin-left: -20px;
          margin-top: -20px;
          border-radius: 50%;
          background: #ff6d00;
          display: flex;
          align-items: center;
          justify-content: center;
          box-shadow: 0 2px 10px rgba(0,0,0,0.4);
        }
        .ba-slider .ba-handle-dot svg { width: 18px; height: 18px; fill: none; stroke: #0a0a0a; stroke-width: 2; }
        .ba-slider .ba-label {
          position: absolute;
          top: 0.75rem;
          font-size: 0.65rem;
          letter-spacing: 0.12em;
          text-transform: uppercase;
          color: rgba(255,255,255,0.8);
          background: rgba(0,0,0,0.55);
          border: 1px solid rgba(255,255,255,0.15);
          padding: 0.25rem 0.6rem;
          pointer-events: none;
        }
        @media (max-width: 767px) {
          .ba-slider { touch-action: none; }
        }
        /* Gleiches Rahmen-/Layout wie die Bildergalerie der Projektseite */
        .ba-gallery-item { position: relative; }
        .ba-gallery-item .ba-frame {
          position: absolute;
          inset: 0;
          translate: 12px 12px;
          border: 1px solid rgba(255,109,0,0.4);
          pointer-events: none;
          z-index: 0;
        }
        @media (max-width: 767px) {
          .ba-gallery-item .ba-frame { display: none; }
        }
        .ba-gallery-item .ba-slider {
          position: relative;
          z-index: 1;
          aspect-ratio: 16 / 9;
        }
        /* ── Zurück-Button: nur auf Desktop verbessert ───────────────────
           Mobil bleibt der originale Look (gedimmt, kein Rahmen).
           Ab 768 px (md) wird der Button heller + bekommt einen Rahmen. */
        @media (min-width: 768px) {
          .back-btn {
            color: rgba(255,255,255,0.8) !important;
            border: 1px solid rgba(255,255,255,0.2);
            padding: 0.25rem 0.75rem;
            border-radius: 2px;
            transition: border-color 150ms, color 150ms;
          }
          .back-btn:hover {
            border-color: #ff6d00 !important;
            color: #ff6d00 !important;
          }
           /* Impressum/Datenschutz verwenden einen zentrierten max-w-4xl-
              Container. Der Zurück-Button soll dort auf Desktop an derselben
              linken Position wie auf den Projekt-Detailseiten stehen. */
           .max-w-4xl > .back-btn {
             position: relative;
             left: min(0px, calc((60rem - 100vw) / 2));
           }
        }
        /* ── Portfolio card: GPU-Hints + mobile slide-in von unten ────────
           GPU-Hints (transform/backface) wurden aus dem inline-style
           entfernt und hier zentralisiert, damit @keyframes den transform
           ohne Konflikte überschreiben kann (inline styles > @keyframes
           in älteren WebKit-Engines).
           Auf Desktop: keine Animation, nur GPU-Promotion.
           Mobil (< 768 px): slide-in von unten bei jedem Card-Mount
           (key wechselt bei ↑/↓ → React remount → Animation feuert). */
        .project-card-anim {
          transform: translateZ(0);
          -webkit-transform: translateZ(0);
          backface-visibility: hidden;
          -webkit-backface-visibility: hidden;
        }
        @keyframes cardSlideUp {
          from { opacity: 0; }
          to   { opacity: 1; }
        }
        @media (max-width: 767px) {
          .project-card-anim {
            animation: cardSlideUp 0.4s ease both;
          }
        }

/* ── Portfolio: Slide-Up Animation für neue Karten ── */
        @keyframes lm-pop-in {
          0%   { opacity: 0; transform: translateY(40px); }
          100% { opacity: 1; transform: translateY(0); }
        }
        .lm-card-hidden  { display: none !important; }
        .lm-card-popping { animation: lm-pop-in 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94) both; }

          /* ── Mobile: stabile Bilder statt Pop-in ────────────────────────────────
             Bilder dürfen beim Scrollen nicht gleichzeitig opacity und transform
             animieren. Das erzeugt auf Firefox/Android sichtbares Flackern, wenn
             mehrere Bilder die Viewport-Grenze nacheinander passieren. */
        @keyframes lm-img-pop {
            from { opacity: 1; transform: translateZ(0); }
            to   { opacity: 1; transform: translateZ(0); }
        }
        @media (max-width: 767px) {
            /* Falls ein alter DOM-Zustand die Klasse noch trägt, darf sie
               keine sichtbare Ein-/Ausblendung oder Bewegung auslösen. */
          img.lm-img-pop {
              animation: none !important;
              opacity: 1 !important;
              transform: translateZ(0) !important;
              transition: none !important;
          }

          /* ── Bilder nach abgeschlossener Animation: stabil eingefroren ──── */
          img.lm-anim-done {
            opacity: 1 !important;
            transform: translateZ(0) !important;
            transition: none !important;
          }

          /* Bild IN einer laufenden Karten-Animation (lm-card-popping):
             Nur wenn das Bild KEINE eigene Slide-Animation hat → sofort zeigen.
             Mit lm-slide-in darf die Animation laufen (Karte UND Bild animieren).
             Nur wenn bereits geladen (lm-img-ready) — sonst bleibt das Bundle
             in der Steuerung (opacity 0→1 via onLoad) und verhindert den
             Leerbildflash bei leerem Cache.                                   */
          .lm-card-popping img.lm-img-ready:not(.lm-slide-in):not(.lm-anim-done) {
            opacity: 1 !important;
            transform: translateZ(0) !important;
            animation: none !important;
            transition: none !important;
          }

           /* ── Detail-Seiten Bilder (object-contain): stabil wenn keine Animation ──
              Beim erneuten Passieren der Viewport-Grenze nicht neu animieren.
              Gilt nur nach dem Laden (lm-img-ready) — gleiche Begründung wie oben. */
          img.object-contain.lm-img-ready:not(.lm-slide-in):not(.lm-anim-done) {
            transition: none !important;
            transform: translateZ(0) !important;
            opacity: 1 !important;
          }

          /* ── Cover-Bilder: Flicker-Fix für Bilder ohne eigene Animation ────
             Das kompilierte Bundle setzt opacity:0 + transition:0.7s (inline
             via React) auf das <img>. Gleichzeitig animiert Framer Motion die
             übergeordnete Karte (opacity 0→1). Beide Systeme kämpfen →
             Aufblitzen beim ZWEITEN Besuch (Warm-Cache, Bild schon geladen).

             Fix A (Warm-Cache): lm-img-ready wird per JS sofort gesetzt,
             sobald img.complete → opacity:1 + transition:none überschreiben
             Reacts Inline-Style → nur noch die Framer-Karte animiert. ✓

             Fix B (Cold-Cache, erstes Laden): lm-img-ready fehlt noch →
             Regel greift nicht → React steuert Bild (opacity 0→1 via onLoad),
             Framer steuert Karte (opacity 0→1) — zeitlich kein Konflikt, da
             das Bild erst nach der Karten-Animation fertig lädt. ✓

             :not(.lm-slide-in) ausklammern damit die Slide-Animation
             ungestört opacity und transform selbst steuern kann.              */
          a[href*="/projekt/"] img.lm-img-ready:not(.lm-slide-in):not(.lm-anim-done) {
            opacity: 1 !important;
            transition: none !important;
            transform: translateZ(0) !important;
          }
          /* Noch nicht geladene Cover-Bilder: Bundle-Transition kürzen damit
             kein langes 0.7s-Fade gegen die Framer-Karte konkurriert.        */
          a[href*="/projekt/"] img:not(.lm-img-ready):not(.lm-slide-in):not(.lm-anim-done) {
            transition: opacity 0.25s ease !important;
            transform: translateZ(0) !important;
          }

          /* ── Slide-Up Animation für Cover- und Detail-Bilder ──────────────
             Gleicher Effekt wie "Mehr laden"-Karten: von unten nach oben.
             CSS-Animationen rangieren über normalen Autor-Styles (inkl. Inline),
             aber UNTER !important — deshalb oben überall :not() ergänzt.
             animation-fill-mode: both = Bild startet bei from-Werten (opacity:0,
             translateY:35px) und bleibt nach Ende bei to-Werten eingefroren.
             transition:none verhindert dass das Bundle seine opacity-Transition
             (0.7s) gleichzeitig läuft und gegen unsere Animation kämpft.   */
          @keyframes lm-img-reveal {
            from { opacity: 0; }
            to   { opacity: 1; }
          }
          img.lm-slide-in {
            animation: lm-img-reveal 0.45s ease both !important;
            transition: none !important;
            transform: translateZ(0) !important;
            will-change: opacity !important;
          }
        }

#lm-mehr-btn {
          display: none;
          margin: 2.5rem auto 0;
          background: none;
          border: 1px solid rgba(255,255,255,0.18);
          border-radius: 2px;
          color: rgba(255,255,255,0.6);
          font-family: 'IBM Plex Mono', monospace;
          font-size: 0.68rem;
          letter-spacing: 0.18em;
          text-transform: uppercase;
          padding: 0.6rem 1.6rem;
          cursor: pointer;
          transition: color 0.2s, border-color 0.2s;
          align-items: center;
          justify-content: center;
          gap: 0.5rem;
          flex-direction: row;
        }
        #lm-mehr-btn:hover {
          color: #ff6d00;
          border-color: rgba(255,109,0,0.5);
        }
        #lm-mehr-wrap {
          text-align: center;
        }

/* ── Portfolio Filter-Leiste (Mobile + Desktop) ── */
        /* Karte beim Filtern ausblenden — alle Breakpoints */
        .lm-filter-out {
          display: none !important;
        }
        #lm-filter-bar {
          display: inline-flex;
          align-items: center;
          gap: 3px;
          margin-bottom: 1.5rem;
          font-family: 'IBM Plex Mono', monospace;
          background: rgba(255,255,255,0.06);
          border-radius: 999px;
          padding: 3px;
        }
        .lm-filter-btn {
          background: none;
          border: none;
          border-radius: 999px;
          cursor: pointer;
          padding: 0.38rem 1.1rem;
          font-size: 0.68rem;
          letter-spacing: 0.14em;
          text-transform: uppercase;
          color: rgba(255,255,255,0.45);
          transition: color 0.22s, background 0.22s;
          font-family: inherit;
          line-height: 1;
        }
        .lm-filter-btn:hover { color: rgba(255,255,255,0.8); }
        .lm-filter-btn.lm-filter-active {
          background: #ff6d00;
          color: #fff;
        }
        @media (min-width: 768px) {
          #lm-filter-bar {
            margin-bottom: 2.5rem;
          }
          .lm-filter-btn {
            padding: 0.45rem 1.4rem;
            font-size: 0.72rem;
            letter-spacing: 0.16em;
          }
        }
