
  /* ── 1) Kein horizontaler Overflow — app-weit gegen „abgeschnittene" Seiten ──
     Greift ab iPhone-Breite. viewport-fit=cover ist im <meta> gesetzt. */
  /* ── Sticky Footer (Phil, 27.08.2026): auf kurzen Seiten rutschte die
     Fusszeile direkt unter die Tabelle hoch. Body als Flex-Spalte ueber die
     volle Viewport-Hoehe, <main> nimmt den Restraum -- damit klebt .pm-footer
     am unteren Rand oder wird bei langen Seiten normal weggescrollt.
     position:fixed-Elemente (Sidebar, Modals, Toasts) bleiben unberuehrt.
     Erste Fassung sass versehentlich IN der 480px-Media-Query darunter --
     Messprobe fing es (Footer bei 522px von 900px Viewport). */
  body {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh; /* mobile Adressleisten korrekt eingerechnet */
  }
  main.pm-main { flex: 1 0 auto; }
  .pm-footer { margin-top: auto; flex-shrink: 0; }

  /* ══ Handy-Scrollarchitektur — 1:1 nach PMS (11.09.2026) ═══════════════════
     Phil, woertlich und zum zweiten Mal: "du sollst die aktuelle version von
     Projekt PMS anschauen und das main menu unten sowie das menu oben und die
     fucking randgrenzen und scrollverhalten 1:1 genau so bauen!! DAS IST
     PFLICHT." Vorbild: pms/sonos-bridge/templates/index.html (nur gelesen),
     Abschnitt D/E der gemessenen Spezifikation:
       html,body{height:app-height}  body{display:flex;column;overflow:hidden}
       darin GENAU EIN overflow-y:auto-Container (#content).

     ── WARUM (GEMESSEN 11.09.2026, nicht vermutet) ──────────────────────────
     Der Tab-Kopf der News-Seite ging beim Scrollen kaputt. Ursache war NICHT
     eine overflow-Falle, sondern die Offset-Rechnung zweier Sticky-Leisten im
     SELBEN Scroller:
       .pm-navbar.d-lg-none  position:sticky top:0   z-index 1040
       .news-kopf            position:sticky top:54px z-index 30
     Die 54px stammen aus der Zeit vor --pm-safe-top. Am iPhone reicht die
     Kopfleiste aber bis 113px (Kinder 69..113px, siehe Hoehen-Riegel in der
     .pm-navbar.d-lg-none-Regel weiter unten). Messprotokoll:
       scrollY   0 -> Ueberlappung  0px
       scrollY 200 -> Ueberlappung 14.6px
       scrollY>=320 -> Ueberlappung 26px, konstant
       elementFromPoint(60, 82.8) == SPAN.fw-bold.text-white  (der PortfoLeo-
       Schriftzug der Kopfleiste) -> die Tabs waren ueberdruckt UND unklickbar.

     PMS hat dieses Problem baulich nicht: die Kopfleiste liegt AUSSERHALB des
     Scrollers, darum klebt der einzige echte Unter-Kopf dort (.fav-filter-bar)
     schlicht bei top:0 — es gibt keinen Offset, den man falsch rechnen kann.
     Genau diese Bauform uebernehmen wir; .news-kopf/.pos-kopf stehen danach
     auf top:0 (news.html / style.css), die 54px entfallen ERSATZLOS.

     ── Zuschnitt ────────────────────────────────────────────────────────────
     Nur < 992px. Ab 992px ist die Navigation die Seitenspalte, oben steht
     nichts (--pm-navbar-h:0px) — dort scrollt weiterhin das Fenster, der
     Desktop bleibt Byte-fuer-Byte unangetastet. Embed-Modus (Positions-Modal
     im Iframe) ebenfalls aussen vor: der hat weder Kopfleiste noch Tab-Leiste.
     GEMESSEN hat die Body-Flex-Spalte am Handy genau ZWEI Kinder im Fluss
     (nav.pm-navbar + main.pm-main); alles andere (Schublade, Overlays,
     Tab-Leiste, Onboarding, Toasts, Matrix-Hintergrund) ist position:fixed
     und beruehrt den Fluss nicht. Darum ist der Umbau klein und risikoarm. */
  @media (max-width: 991.98px) {
    html:not(.embed-mode),
    html:not(.embed-mode) body {
      height: var(--pm-app-height, 100dvh);
      min-height: var(--pm-app-height, 100dvh);
      /* PMS: kein Gummiband ueber die Raender hinaus (Spec D). */
      overscroll-behavior: none;
    }
    /* BODY SCROLLT NICHT. */
    html:not(.embed-mode) body { overflow: hidden; padding-bottom: 0; }
    /* Kopfleiste: Flow-Geschwister, schrumpft nie, verschwindet nie. */
    html:not(.embed-mode) body > .pm-navbar { flex: 0 0 auto; }
    /* DER EINZIGE Scroller der Seite. */
    html:not(.embed-mode) body > main.pm-main {
      flex: 1 1 auto;
      min-height: 0;
      overflow-y: auto;
      overflow-x: hidden;
      -webkit-overflow-scrolling: touch;
      overscroll-behavior: none;
      /* PMS Spec D: KEIN padding-bottom am Scroller gegen die fixe Leiste —
         die Hoehe reserviert ein FLOW-Element per margin-bottom (dort
         #np-bar{margin-bottom:var(--bottomnav)}). Hier ist der Scroller selbst
         das Flow-Element der Body-Spalte: sein margin-bottom haelt die 74px
         frei, ohne dass die Innenpolsterung mitwaechst (padding-bottom haette
         den Scrollweg verlaengert statt die Leiste freizuhalten). */
      margin-bottom: var(--pm-bottomnav);
    }
    /* Horizontaler Seitenrand app-weit 16px (PMS Spec C: #content{padding:16px},
       Kopfleiste 16px). Links/rechts im HOCHFORMAT ohne Safe-Area — --pm-safe-left
       ist dort 0, im Querformat 59px, darum max() statt fester Zahl.

       OBEN/UNTEN bewusst 0 und stattdessen als Aussenabstand am ersten/letzten
       Kind: GEMESSEN 11.09.2026 klebt ein sticky top:0-Kopf an der POLSTERKANTE
       des Scrollers. Mit padding-top:16px blieb ueber dem Tab-Kopf ein 16px
       hoher Streifen offen, durch den der Inhalt sichtbar durchwanderte
       (Screenshot tabkopf-nachher-500.png: Kartenrand als Strich ueber der
       Tab-Leiste, .news-kopf.top stand bei 140 statt 124). Als Aussenabstand
       scrollt die Luft mit weg und der Kopf sitzt buendig unter der
       Kopfleiste. */
    html:not(.embed-mode) body > main.pm-main {
      padding: 0;
      padding-left: max(16px, var(--pm-safe-left));
      padding-right: max(16px, var(--pm-safe-right));
    }
    html:not(.embed-mode) body > main.pm-main > *:first-child { margin-top: 16px; }
    html:not(.embed-mode) body > main.pm-main > *:last-child  { margin-bottom: 16px; }
    /* Onboarding-Leiste (.pm-onboarding, volle Breite, --pm-onb-leiste hoch)
       dockt buendig ueber der Tab-Leiste an (style.css) — solange sie sichtbar
       ist (onboarding.js setzt body.pm-onb-leiste), waechst die Reserve um ihre
       Hoehe. Dieselbe EINE Stelle wie die Grundreserve, statt eines zweiten
       padding-bottom am <body>, das die Flex-Spalte gekuerzt haette. */
    html:not(.embed-mode) body.pm-onb-leiste > main.pm-main {
      margin-bottom: calc(var(--pm-bottomnav) + var(--pm-onb-leiste));
    }
  }
  @media (max-width: 480px) {
    /* NUR body, nicht html (E2E-Messung 08.09.2026): overflow-x:hidden auf
       BEIDEN machte auch body zum Scroll-Container (implizit overflow-y:auto),
       obwohl nur html scrollt — position:sticky (.news-kopf/.pos-kopf) haengte
       sich an body, das nie scrollt, und trieb mit dem Inhalt davon. Gemessen:
       kopfBottom 27 -> -241 -> -4796 beim Weiterscrollen; mit html:visible
       bleibt der Kopf bei 54 px stehen. */
    body {
      max-width: 100vw;
      overflow-x: hidden;
    }
    /* Safe-Area links/rechts für den Hauptinhalt (Notch im Landscape). */
    .pm-main {
      padding-left: max(0.6rem, var(--pm-safe-left));
      padding-right: max(0.6rem, var(--pm-safe-right));
      padding-top: 0.6rem;
    }

    /* ── Breite Tabellen: defensiv scrollbar machen statt clippen ──
       Wir wrappen NICHT das <table> selbst in display:block (das würde
       thead/tbody-Layout mancher Seiten zerlegen). Stattdessen bekommen die
       bekannten Bootstrap-/App-Tabellen-Container horizontales Scrollen. */
    .table-responsive,
    .pm-table-wrap,
    .card .table,
    .pm-card .table {
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
    }
    /* Fallback: jede „nackte" .table ohne scrollbaren Wrapper darf trotzdem
       nicht die Seite sprengen — sie scrollt in sich selbst. Nur Mobile. */
    table.table {
      display: block;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
      max-width: 100%;
      width: max-content;
    }
    /* Häufige Overflow-Verursacher zähmen: sehr breite <pre>, lange Codes/URLs. */
    pre, code {
      max-width: 100%;
      overflow-x: auto;
      white-space: pre-wrap;
      word-break: break-word;
    }
    img, svg, canvas, video, iframe { max-width: 100%; }
    /* Bootstrap-Row-Gutter erzeugt sonst horizontalen Overflow am Viewport-Rand. */
    .container-fluid, .container { padding-left: 12px; padding-right: 12px; }
  }
  /* Querformat-Labor 09.09.2026: echtes iPhone quer misst 852px Breite --
     ausserhalb der 480px-Deckelung oben, darum eigener Block, sonst bleibt
     .pm-main links/rechts ungepolstert und der Inhalt startet unter der
     Insel/dem rechten Rand (gemessen: 55 Kollisionen auf /news). */
  @media (orientation: landscape) and (max-height: 500px) {
    .pm-main {
      padding-left: max(0.6rem, var(--pm-safe-left));
      padding-right: max(0.6rem, var(--pm-safe-right));
    }
  }

  /* ── 2) Kompaktere globale Paddings/Font — mehr passt auf den iPhone-Schirm ──
     Bewusst dezent; NUR ≤ 480px, damit Tablet/Desktop unangetastet bleiben. */
  @media (max-width: 480px) {
    .pm-card, .card { padding: 0.7rem 0.8rem; }
    .card-body { padding: 0.7rem 0.8rem; }
    h1 { font-size: 1.5rem; }
    h2 { font-size: 1.3rem; }
    h3 { font-size: 1.15rem; }
    h4 { font-size: 1.02rem; }
    h5 { font-size: 0.95rem; }
    /* Modals randlos-freundlich: nutzen fast die volle Breite, kein Clipping. */
    .modal-dialog { margin: 0.5rem; max-width: calc(100vw - 1rem); }
    .modal-body { padding: 0.9rem; }
    /* Bootstrap-Buttons/Inputs bequem antippbar (Touch-Target). */
    .btn { touch-action: manipulation; }
  }

  /* ── 3) Mobile Top-Bar (< lg): darf nie clippen ──
     Icons/Buttons rechts (Refresh, Hilfe-Glühbirne, Alert-Bell) sollen
     umbrechen/scrollen statt abgeschnitten zu werden. Gilt für die
     d-lg-none Top-Bar. */
  @media (max-width: 991.98px) {
    /* iPhone-Huelle-Welle (08.09.2026): Masse/Optik 1:1 von PMS' #topbar
       uebernommen (pms/sonos-bridge/templates/index.html:525-533, NUR
       gelesen) — Padding 10px 16px + Safe-Area oben, blur+saettigender
       Hintergrund, 1px Trennlinie unten. Farbe kommt aus Leo-Tokens
       (--pm-panel-rgb/--pm-border), NICHT aus PMS' Hexwerten (#0d0d0d). Der
       Hintergrund ist scoped auf ".d-lg-none" (NUR die mobile Leiste) — die
       Desktop-Kopfzeile behaelt ihren eigenen Verlauf (portfo-leo-skin.css). */
    .pm-navbar.d-lg-none {
      flex-wrap: wrap;
      row-gap: 4px;
      /* Hoehen-Riegel (11.09.2026, GEMESSEN): style.css:661 setzt global
         ".pm-navbar { height: 54px }" — ein Rest der alten waagrechten
         Desktop-Leiste, die es seit dem Menue-Umbau (19.08.2026) gar nicht
         mehr gibt (--pm-navbar-h ist ab 992px 0px). Am Handy traf diese 54px
         auf padding-top:69px (10 + --pm-safe-top 59) bei box-sizing:border-box:
         die Box klemmte auf 80px (79px Polster + 1px Linie, Inhaltshoehe 0),
         waehrend die Kinder 69..113px hoch stehen. Messung:
           box {top:0, bottom:80}   clientHeight 79   scrollHeight 113
           Kind A (Logo/Marke)  top 69  bottom 113
           Kind B (Glocke)      top 69  bottom 113
         Folge: Logo und Glocke haengen 33px UNTER dem eigenen Hintergrund und
         liegen ueber dem Seiteninhalt — auf /positions ueberdeckte der
         Schriftzug schon bei scrollY=0 die erste Karte. PMS setzt hier gar
         keine Hoehe (Spec B: "HOEHE NICHT GESETZT — inhaltsgetrieben"), also
         hier zurueck auf auto. Zwei Klassen schlagen die eine in style.css,
         unabhaengig von der Ladereihenfolge. */
      height: auto;
      flex-shrink: 0;
      padding: 10px 16px;
      padding-top: calc(10px + var(--pm-safe-top));
      /* Querformat-Labor 09.09.2026: --pm-safe-left/right statt env() direkt,
         damit auch der simulierte Wert im Preview greift (env() liefert
         headless nie etwas, siehe --pm-safe-top/bottom oben). */
      padding-left: max(16px, var(--pm-safe-left));
      padding-right: max(16px, var(--pm-safe-right));
      background: rgba(var(--pm-panel-rgb), .92) !important;
      -webkit-backdrop-filter: saturate(180%) blur(20px);
      backdrop-filter: saturate(180%) blur(20px);
      border-bottom: 1px solid var(--pm-border);
    }
    /* Falls die rechte Icon-Gruppe doch mal breiter wird: horizontal scrollen
       statt clippen. */
    .pm-navbar.d-lg-none .ms-auto {
      flex-shrink: 0;
      max-width: 100%;
      overflow-x: auto;
      -webkit-overflow-scrolling: touch;
    }
    /* Touch-Targets ≥ 44px für die Icon-Buttons in der Mobile-Top-Bar. */
    .pm-navbar.d-lg-none .btn,
    .pm-navbar.d-lg-none [onclick] {
      min-height: 44px;
      min-width: 44px;
      display: inline-flex;
      align-items: center;
      justify-content: center;
    }
  }

  /* ── 4) Mobile-Menü + Bottom-Tabs: Touch-Targets & Safe-Area ──
     mob-menu-link ist bereits ≥ 52px (style.css). Hier die Bottom-Tab-Bar
     und die Menü-Kopfzeile gegen Notch/Home-Indicator absichern. */
  @media (max-width: 991.98px) {
    /* Menü-Kopf unter der Notch, Menü-Fuss über dem Home-Indicator. */
    /* Bottom-Tab-Buttons: sicheres 44px-Touch-Target. */
    .mob-tab { min-height: 44px; }
    /* Menü-Link-Text darf nie überlaufen. */
    .mob-menu-link {
      min-height: 48px;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
