/* Operian OS — Mobile-Shell-Layer (additiv, NEBEN dem eingefrorenen Bundle).
 *
 * Der Bundle (assets/index-r1.js) bleibt unangetastet — Bundle-Freeze-Doktrin (CLAUDE.md).
 *
 * AKTIVIERUNG (nur die Bedingung hat sich geändert, keine Regel):
 * Diese Datei trägt die TELEFON-Präsentation und gilt ausschliesslich für die
 * Präsentationsklasse `compact`. Das Gate war früher `max-width: 767px` — eine reine
 * Breitenabfrage, durch die ein iPad mini im Hochformat (744px breit, aber 1133px hoch)
 * die Telefon-Oberfläche erbte. Massgeblich ist jetzt die KURZE SEITE der Arbeitsfläche:
 *
 *   Hochformat   @media (max-width: 600px)
 *   Querformat   (max-height: 500px) and (max-width: 932px)   — bereits vorher hier
 *
 * 600 liegt über jeder Telefon-Kurzseite (grösste ~440px) und unter jeder Tablet-Kurzseite
 * (kleinste 744px). Dieselbe Schwelle leitet kernel.js aus viloWorkspaceClass() ab und
 * spiegelt sie als html[data-vilo-class="compact"] — dort steht die Begründung ausführlich.
 * Tablet (`medium`) und Desktop (`wide`) dürfen durch diese Datei nie verändert werden.
 */

/* M1.1 — authentifizierte OS-Menüleiste auf Smartphones erreichbar halten.
 *
 * Die Leiste ist React-gerendert (Bundle, eingefroren) ohne IDs/data-Attribute; die
 * Tailwind-Utility-Klassen sind Build-Output des GENAU EINMAL gepatchten Bundles und
 * ändern sich nicht zur Laufzeit — daher sind Struktur-Selektoren (Kindposition) unter
 * dem stabilen z-[9999]-Leisten-Root hier verlässlich. Der Abmelden-Button hat zusätzlich
 * ein stabiles title="Abmelden" (deutsches UI-Label, semantisch, kein Utility-Artefakt).
 *
 * Leisten-Struktur (siehe DOM-Audit):
 *   div[class*="z-[9999]"]                  Leisten-Root (h-9, volle Breite)
 *   ├─ div (links)                          erstes Kind
 *   │  ├─ div > button "vilo"               primärer VILO-Menütrigger — bleibt erhalten
 *   │  ├─ span (nur bei fokussiertem Fenster!)   App-Name (z.B. "Dienstplan") — zusätzliches
 *   │  │                                    Kind, das NUR erscheint wenn ein Fenster offen/
 *   │  │                                    fokussiert ist (per Audit mit offenem Fenster
 *   │  │                                    nachträglich entdeckt, M1.3). Verschiebt bei
 *   │  │                                    einer rein positionsbasierten Auswahl (nth-
 *   │  │                                    child) den folgenden Menü-Wrapper von Position
 *   │  │                                    2 auf 3 — siehe Klassen-Selektor unten, der
 *   │  │                                    davon absichtlich unabhängig ist.
 *   │  └─ div.ml-1                          Desktop-Menü (Ablage/Bearbeiten/…/Hilfe) —
 *   │                                       Position unter den Geschwistern variiert (2
 *   │                                       ohne, 3 mit fokussiertem Fenster), daher hier
 *   │                                       per Klassenkombination statt nth-child anvisiert
 *   └─ div (rechts, letztes Kind)
 *      ├─ div (Status-Icons: Lautstärke/WLAN/Akku)
 *      ├─ div (Name-Span, .vilo-clock, Datum, Uhrzeit)
 *      └─ button[title="Abmelden"]          Logout — auf Mobil per M1.4 ausgeblendet
 *                                           (Funktion bleibt über den VILO-Menü-
 *                                           Trigger links erreichbar: dort abmelden)
 */
@media (max-width: 600px) {
  /* Positionierungskontext für die absolute Namens-Zentrierung weiter unten (M1.4) —
     das Bundle verankert die Leiste selbst zwar bereits per Inline-Style (fixed), aber
     diese Regel ist ein harmloses Sicherheitsnetz, falls sich das je ändert: ohne einen
     positionierten Vorfahren würde sich "position:absolute" auf dem Namen gegen das
     nächste positionierte Element weiter oben im Baum zentrieren statt gegen die Leiste. */
  /* M1.9 — Notch/Dynamic-Island-Reserve für die Topleiste selbst. Bisher reservierte NUR
     der untere Dock/Fensterrand env(safe-area-inset-bottom); oben fehlte das Gegenstück
     komplett — die Leiste (h-9, 36px, Tailwind-Klasse, KEIN Inline-Style) begann exakt bei
     y=0 und würde auf einem echten Gerät mit Notch/Dynamic Island (safe-area-inset-top > 0,
     nur bei viewport-fit=cover + edge-to-edge Rendering wirksam, z. B. als installierte PWA
     gemäß manifest.webmanifest display:"fullscreen" — hier per Audit bestätigt) teilweise
     darunter verschwinden. Fix spiegelt exakt das Dock-Muster (M1.3): Gesamthöhe wächst um
     die Inset-Reserve (height statt padding-only, da *,*::before,*::after per Tailwind-
     Preflight bereits box-sizing:border-box sind — sonst würde ein reines padding-top den
     36px-Inhalt stauchen statt die Box zu vergrößern), padding-top schiebt den Flex-Inhalt
     exakt um dieselbe Reserve nach unten. Bei env()=0 (hier verifiziertes Environment)
     bleibt height exakt 36px — keine sichtbare Änderung im getesteten Browser. Jede Stelle,
     die die Leistenhöhe als literales 36px annimmt (window-shadow top/height, M2/M3 unten),
     muss um denselben Term ergänzt werden — sonst klafft eine Lücke bzw. schiebt sich das
     Fenster unter die vergrößerte Leiste. KEIN !important nötig: `.h-9{height:2.25rem}`
     (Tailwind, Build-Output) hat Klassen-Spezifität (0,1,0), der Attribut+Typ-Selektor
     hier (0,1,1) schlägt sie bereits ohne — zusätzlich lädt mobile-shell.css nach dem
     Bundle-CSS (index.html), Kaskaden-Reihenfolge wäre ohnehin auf unserer Seite. */
  div[class*="z-[9999]"] {
    position: relative;
    height: calc(36px + env(safe-area-inset-top));
    padding-top: env(safe-area-inset-top);
    box-sizing: border-box;
  }

  /* Desktop-Menülabels (Ablage…Hilfe) verbergen — der primäre VILO-Trigger (erstes Kind
     der linken Gruppe) bleibt unangetastet. Das ist der eine Cluster, der bei knapper
     Breite den Account-/Logout-Bereich rechts aus dem Viewport schiebt. Anvisiert über die
     vollständige, stabile Klassenkombination (nicht nth-child) — sonst würde die Regel bei
     fokussiertem Fenster (zusätzlicher App-Name-Span verschiebt die Kindposition) ins Leere
     laufen und der volle Desktop-Menü den Abmelden-Button aus dem Viewport drängen. */
  div[class*="z-[9999]"] > div:first-child > div.flex.items-center.gap-0.ml-1 {
    display: none;
  }

  /* Zeiterfassungs-Widget-Uhr (.vilo-clock, siehe unten in dieser Datei rechts bereits
     verborgen) taucht bei FOKUSSIERTEM Zeiterfassungs-Fenster zusätzlich links neben dem
     App-Namen auf (kernel.js hängt sie dort als Menüleisten-Erweiterung der aktiven App
     ein — per Audit entdeckt: eigene id="vilo-clock-zeiterfassung", ca. 90px breit). Ohne
     dieses Verstecken schiebt sie bei "Zeiterfassung" fokussiert bereits bei 375px den
     Abmelden-Button aus dem Viewport (388px Rechtskante bei 375px Breite gemessen). Bleibt
     wie ihr rechtes Gegenstück auf Mobil ausgeblendet — dieselbe Vorgabe wie in M1.1. */
  div[class*="z-[9999]"] > div:first-child > span.vilo-clock {
    display: none;
  }

  /* M1.7 — App-Name-Span (M1.1-Audit: "Dienstplan"/"Zeiterfassung"/…, nur bei fokussiertem
     Fenster) auf Mobil ausgeblendet statt nur schmaler gestellt (vorher M1.3b). Zwei Gründe:
     1) Redundant — im Single-Active-App-Modus (M3) trägt das EINE sichtbare Fenster ohnehin
        seine eigene Titelleiste mit demselben Namen (M1.2-Audit, "zentrierter Titel-Text").
     2) Kollisionsquelle — der Span sitzt links im Fluss (endet gemessen bei 139.7px/375px),
        der Name rechts ist per M1.4 absolut mittig auf der GANZEN Leiste zentriert; bei einem
        längeren Namen ("Stephan Wenneker") begann er bereits bei 122.2px → 17.5px Überlappung
        ("Mein Profil" und Name rendern übereinander, gemeldeter Fehler). M1.3b löste das nur
        unterhalb 340px per Kürzung — der Kern der Kollision (zwei unabhängig positionierte
        Texte ohne Kenntnis voneinander) blieb bei 341–767px bestehen. Hier komplett verbergen
        entfernt die Quelle für alle Breiten; die M1.4-Zentrierung wurde zusätzlich auf feste
        Abstände zu vilo-Trigger/Uhr umgestellt (siehe dort) statt sich (auch) hierauf zu
        verlassen. */
  div[class*="z-[9999]"] > div:first-child > span.text-white\/80.text-xs.font-semibold.px-2 {
    display: none;
  }

  /* Status-Icons (Lautstärke/WLAN/Akku) sind auf dem Smartphone redundant (das Betriebs-
     system des Geräts zeigt sie bereits) und nicht Teil der geforderten Mobil-Funktionen
     (Account/Logout/VILO-Menü) — verbergen schafft den nötigen Platz, ohne Uhr oder
     Nutzernamen anzutasten. */
  div[class*="z-[9999]"] > div:last-child > div:first-child {
    display: none;
  }

  /* M1.4 — Uhr komplett entfernt (das Smartphone hat bereits eine eigene Statusleiste
     mit Uhrzeit, siehe Vorgabe), Abmelden-Button entfernt (Funktion bleibt über den
     VILO-Menü-Trigger links erreichbar) → der Nutzer-Cluster besteht auf Mobil nur
     noch aus dem Namen. Nach Nutzer-Feedback (Screenshot-Annotation) soll der Name
     ECHT MITTIG in der GESAMTEN Leiste stehen — nicht nur mittig im verbleibenden
     rechten Rest neben "vilo" (das war die vorige, zu subtile Lösung: flex:1 auf dem
     rechten Container zentriert nur relativ zu dessen eigener Breite, die durch
     "vilo" links bereits verschoben ist). Der rechte Bereich soll außerdem bewusst
     leer/reserviert bleiben, weil dort später ein Zeiterfassungs-Widget andocken
     soll (Start bei Schichtbeginn, 00:00) — daher hier NICHT flex:1 auf den rechten
     Container legen (das würde den künftigen Widget-Platz mit dem Namen belegen).
     Lösung: der Name wird aus dem Flex-Fluss genommen und absolut relativ zum
     Leisten-Root (positioniert, da Bundle die Leiste per Inline-Style fixed/relativ
     verankert) mittig platziert — funktioniert unabhängig von der Breite der
     Geschwister links (vilo) und rechts (künftiges Widget).

     M1.7-KORREKTUR (Kollision behoben): `left:50%; transform:translate(-50%,-50%);
     max-width:55vw` zentrierte auf der GESAMTEN Leistenbreite, ohne die tatsächliche
     Breite der Geschwister zu kennen. Gemessen bei 375px mit fokussiertem Fenster:
     der App-Name-Span (links, M1.1-Audit) reichte bis 139.7px, der so zentrierte
     Name begann bei einem längeren Namen ("Stephan Wenneker") bereits bei 122.2px —
     17.5px Überlappung. Bei maximal langem Namen (55vw-Obergrenze = 206px) reicht die
     rechte Kante zudem bis 290.5px in die Uhr-Kachel hinein (Kachel beginnt bei
     gemessenen 272.1px) — zweite, seltenere Kollision. Der App-Name-Span wird unten
     auf Mobil ohnehin ausgeblendet (redundant zur Fenster-eigenen Titelleiste im
     Single-Active-App-Modus, M3) und entfällt damit als Kollisionsquelle links; die
     Uhr-Kachel bleibt aber sichtbar. Statt "zentriert auf der vollen Breite, dann
     hoffentlich schmal genug" wird der Name jetzt in eine feste Restzone ZWISCHEN
     dem vilo-Trigger (endet bei 60.6px) und der Uhr-Kachel (beginnt bei 272.1px)
     gesetzt — beide Maße sind Inhaltsbreiten fester Elemente (Icon/Zeit-Format),
     bleiben also über 320–430px konstant, nur die Leiste selbst wird breiter/
     schmaler. Mit Puffer (inkl. Messungenauigkeit durch Padding/Border der Leiste,
     live nachgemessen): left:72px, right:118px. Der Name kann dadurch NIE mehr mit
     einer der beiden Seiten kollidieren — bei zu wenig Platz greift die bestehende
     Ellipse statt einer Überlappung. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span:first-child {
    position: absolute;
    left: 50%;
    /* M1.9-KORREKTUR: `top:50%` zentrierte auf der GESAMTEN (jetzt um env(safe-area-inset-top)
       gewachsenen) Leistenbox — Prozent-Offsets bei position:absolute beziehen sich auf die
       PADDING-Box des positionierten Vorfahrens, ignorieren also nicht den reservierten
       Notch-Bereich oben. Die Uhr-Kachel (.vilo-clock, normaler Fluss) wird dagegen vom
       padding-top nach unten in die untere 36px-Inhaltszone verschoben und dort zentriert —
       bei einem Inset > 0 klaffte dadurch ein Versatz zwischen Name und Uhr (gemessen bei
       44px Test-Inset: 22px, exakt die Hälfte des Insets). Fix: statt 50% des GESAMTEN Bar-
       Rechtecks wird auf einen festen Abstand vom oberen Rand umgestellt (Inset + halbe
       Inhaltszone, 36px/2=18px) — das trifft exakt die Mitte derselben unteren 36px-Zone,
       in der auch die Uhr sitzt. Bei env()=0 identisch zu vorher (0+18px = 50% von 36px). */
    top: calc(env(safe-area-inset-top) + 18px);
    /* .vilo-namebtn trägt eine BASIS-Regel aus kernel.js (margin:-2px -6px, dort für den
       eingerückten Desktop-Fluss gedacht, wo eine negative Margin den erweiterten
       Touch-Bereich einbezieht, ohne Nachbarn zu verschieben). Hier ist der Name per
       "position:absolute" bereits aus dem Fluss genommen — die Margin hat also keinen
       Layout-Zweck mehr, verschiebt aber (da nur "left", nicht "right" gesetzt ist) die
       zentrierte Box um ihren margin-left-Wert und zerstört die exakte Mitte (gemessen:
       6px Versatz). Auf 0 zurückgesetzt, rein für diese Positionierung. */
    margin: 0;
    transform: translate(-50%, -50%);
    /* Echte Mitte der GESAMTEN Leiste (nicht der Restzone zwischen den Nachbarn) —
       links (vilo-Trigger, endet bei ~60.6px) und rechts (Uhr-Kachel-Zone, beginnt
       bei ~272.1px, Sicherheitsabstand insgesamt ~118px) sind Inhaltsbreiten fester
       Elemente und bleiben über 320–430px konstant. Der größere der beiden gemessenen
       Sicherheitsabstände (118px) wird auf BEIDE Seiten der Mitte angewendet (statt je
       eine feste Kante links/rechts), damit der Name mathematisch mittig bleibt und
       trotzdem nie mit der schmaleren linken Zone kollidiert (72px < 118px, also
       reichlich Puffer übrig). */
    /* M1.8-KORREKTUR: text-align:center + overflow:hidden + white-space:nowrap kappte
       lange Namen SYMMETRISCH an beiden Enden (kein sichtbares "…" links), z.B.
       "Stephan Wenneker" -> "ephan Wennek". text-overflow:ellipsis wirkt nur auf das
       Ende der Textrichtung (rechts), nie auf den Anfang. Fix: Box bleibt zentriert
       positioniert (left/transform oben unverändert), der Text darin wird aber
       linksbündig gesetzt, damit bei zu wenig Platz nur das Ende beschnitten wird
       (mit sichtbarem "…") und der Anfang des Namens immer erhalten bleibt. */
    max-width: calc(100% - 236px);
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    pointer-events: none;
  }

  /* M1.6 — Namensmenü auch auf Mobil: der Name öffnet dieselben vier Mein-Profil-Panes
   * wie auf dem Desktop (Mein Dienstplan · Meine Arbeitszeit · Meine Verfügbarkeit ·
   * Urlaub). Der Kernel dekoriert den Namen ohnehin in BEIDEN Breiten zum Trigger
   * (injectNameMenu, kein Media-Query in JS) — folgenlos blieb er allein wegen des
   * `pointer-events: none` der M1.4-Regel oben, das ihn aus der Interaktion nimmt.
   * Diese Regel nimmt genau das zurück, und zwar NUR für den dekorierten Namen: ein
   * undekorierter Span (ausgeloggt, oder bevor refreshDock() gelaufen ist) hat nichts
   * zu tun und bleibt tot, damit ein Tap auf die zentrierte Beschriftung nicht ins
   * Leere greift. !important, weil die M1.4-Regel im selben Block steht und laut
   * Kernel-Doku (assets/kernel.js, injectNameMenu) genau so zurückzunehmen ist.
   *
   * TOUCH-ZIEL: dieselbe Ausgangslage wie bei der Kachel in M1.5 — die Leiste ist
   * 36px hoch (h-9, Bundle-Fixmaß), der Name selbst nur textzeilenhoch. Die ::after-
   * Lösung der Kachel scheidet hier aus: der Name trägt `overflow: hidden` (M1.4, für
   * die Ellipse bei 55vw) und würde jede vergrößerte Trefferfläche wieder wegschneiden.
   * Stattdessen wächst die Box selbst auf 44px und zentriert ihren Text per Flex. Weil
   * der Name vertikal per top:50%/translateY(-50%) sitzt (M1.4/M1.7), verteilen sich
   * die 8px Überstand symmetrisch: 4px über die Leistenoberkante (dort ist Viewport-
   * Rand, kein Bedienelement) und 4px darunter auf den leeren Desktop-Hintergrund —
   * dieselbe Abwägung wie bei der Kachel, es wird kein fremder Tap gestohlen. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span:first-child.vilo-namebtn {
    pointer-events: auto !important;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    height: 44px;
  }

  /* Die Panel-Einträge sind für die Maus bemessen (py-1.5 ≈ 26px, Bundle-Klassenstring,
     verbatim und daher nicht anzufassen). Auf Touch bekommen sie hier das 44px-Mindest-
     maß — das Panel hängt am <body>, liegt also außerhalb der Leisten-Selektoren, wird
     aber von derselben Breiten-Query erfasst. */
  .vilo-namemenu button[role="menuitem"] {
    min-height: 44px;
  }

  /* Trennstrich, Datum UND Uhrzeit ausblenden (Vorgabe: komplett weg, nicht nur
     kompaktiert) — das Smartphone hat dafür seine eigene Statusleiste.
     SICHTBAR BLEIBEN: der Name (:first-child, oben absolut zentriert) und die
     Zeiterfassungs-Widget-Kachel (.vilo-clock) — das ist der in M1.4 reservierte
     rechte Slot, der jetzt bezogen wird (siehe unten).

     WARUM :not() STATT nth-child: die vorige Fassung zählte Positionen (3/4/last) und
     setzte damit voraus, dass injectWidgets() die Kachel bereits hinter den Namen
     gehängt hat — ohne sie rutschen Trennstrich/Datum eine Position nach vorn und der
     Trennstrich (dann nth-child(2)) blieb sichtbar. Diese Fassung ist unabhängig davon,
     ob und wann die Kachel injiziert wird (sie kommt per MutationObserver → refreshDock
     asynchron), und überlebt damit auch den Moment vor der Injektion. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span:not(:first-child):not(.vilo-clock):not(.vilo-search):not(.vilo-bell) {
    display: none;
  }

  /* M1.8 — Lupe der globalen Suche (#606) auf Mobil: sichtbar UND treffbar.
   *
   * Die Regel darüber blendet alles aus, was nicht Name oder Uhr-Kachel ist. Ohne die
   * :not(.vilo-search)-Ausnahme wäre die Lupe auf dem Smartphone still verschwunden —
   * eine Affordanz, die auf einer Breite lautlos wegfällt, ist genau das Muster, das die
   * Sidebar-Regel in _pattern.css verboten bekommen hat. ⌘K gibt es auf dem Telefon nicht,
   * die Kachel ist dort also der EINZIGE Einstieg.
   *
   * TOUCH-ZIEL: identisch zur Uhr-Kachel (M1.5) — die Leiste ist mit 36px (h-9, Bundle-
   * Fixmaß) zu flach für ein echtes 44px-Ziel, deshalb optisch 36px hoch mit einer
   * unsichtbaren, nach unten überstehenden 44px-Trefferfläche per ::after. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-search {
    position: relative;
    min-width: 44px;
    height: 36px;
    padding: 2px 10px;
  }

  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-search::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* M1.10 — Mitteilungs-Glocke (#612) auf Mobil: sichtbar UND treffbar (#274).
   *
   * Dieselbe Lücke wie bei der Lupe, nur später entstanden — eine reine Chronologie-Panne:
   * die Ausblend-Regel oben lässt vom rechten Cluster genau das durch, was sie NAMENTLICH
   * kennt. Als sie zuletzt angefasst wurde (M1.8, Suche #606), gab es die Glocke noch nicht;
   * sie kam danach und hat ihre Ausnahme nie bekommen. Ergebnis war exakt das Muster, das
   * zwei Regeln weiter oben schon verboten steht: eine Affordanz, die auf einer Breite
   * lautlos wegfällt. Bei der Glocke wiegt das schwerer als bei jeder anderen Kachel, weil
   * ihr Zweck PASSIV ist — sie meldet sich von selbst (Zahl bzw. Warnpunkt bei ungedeckter
   * Aussage). Der Takt lief unterhalb 600px weiter (kernel.js, notifStart), nur sah ihn
   * niemand; ein Ersatzweg existiert nicht, denn das Mitteilungsfenster hat kein Dock-Icon.
   *
   * TOUCH-ZIEL: identisch zu Lupe (M1.8) und Uhr-Kachel (M1.5) — die Leiste ist mit 36px
   * (h-9, Bundle-Fixmaß) zu flach für ein echtes 44px-Ziel, deshalb optisch 36px hoch mit
   * einer unsichtbaren, nach unten überstehenden 44px-Trefferfläche per ::after. Die 4px
   * unterhalb der Leistenkante liegen auf dem leeren Desktop-Hintergrund (Dock sitzt unten,
   * Fenster beginnen unterhalb der Leiste) — es wird kein fremder Tap gestohlen. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-bell {
    position: relative;
    min-width: 44px;
    height: 36px;
    padding: 2px 10px;
  }

  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-bell::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* Badge und Warnpunkt (.vilo-bell__n / .vilo-bell__q, gebaut in kernel.js/notifBadge)
     hängen absolut am KACHEL-Rechteck, nicht am Glocken-Glyph. Auf dem Desktop sind beide
     fast deckungsgleich (14px Icon + padding 2px/8px = 18×30px), dort trifft `top:-1px;
     right:0` die obere rechte Ecke der Glocke. Die Kachel oben wächst auf 44×36px — mit
     unveränderten Offsets landete die Zahl 9px zu hoch und 7px zu weit rechts: ein rotes
     Plättchen an der Leistenoberkante (auf Geräten mit Notch teils dahinter), sichtbar
     losgelöst von der Glocke. Das ist keine Kosmetik: die Zahl IST die passive Aussage,
     um derentwillen die Glocke hier überhaupt wieder sichtbar wird. Der Glyph sitzt in der
     44×36px-Kachel zentriert (x 15–29, y 11–25); die Offsets stellen sein Verhältnis zur
     Ecke exakt so wieder her wie auf dem Desktop (Zahl 3px darüber und 8px daneben, Punkt
     1px darüber und 5px daneben). Angefasst wird NUR die Position — Größe, Farbe und Form
     bleiben beim Kernel, der sie besitzt. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-bell .vilo-bell__n {
    top: 8px;
    right: 7px;
  }

  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-bell .vilo-bell__q {
    top: 10px;
    right: 10px;
  }

  /* M1.5 — Zeiterfassungs-Kachel auf Mobil: der einzige Stempelweg.
   *
   * Das Dock-Icon entfällt (kernel.js, applyPersonalGroup) — die Zeiterfassung läuft
   * ausschließlich über dieses Popover. Auf Mobil ist die Kachel damit nicht länger
   * optionaler Komfort, sondern die einzige Einstiegsstelle: sie MUSS sichtbar und
   * sicher treffbar sein.
   *
   * TOUCH-ZIEL: die Leiste ist nur 36px hoch (h-9, Bundle-Fixmaß) — ein 44px-Ziel passt
   * dort nicht hinein, ohne die Leiste aufzublasen (das verschöbe den gesamten Desktop
   * darunter, der sich am Leisten-Fixmaß orientiert). Stattdessen bleibt die Kachel
   * optisch 36px hoch und bekommt per ::after eine unsichtbare, nach unten über die
   * Leistenkante hinausreichende 44px-Trefferfläche. Die 4px, die unter der Leiste
   * liegen, überdecken nur den leeren Desktop-Hintergrund direkt an der Oberkante —
   * dort liegt kein Bedienelement (Dock sitzt unten, Fenster beginnen unterhalb der
   * Leiste), es wird also kein Tap gestohlen. */
  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-clock {
    position: relative;
    min-width: 44px;
    height: 36px;
    justify-content: center;
    padding: 2px 10px;
  }

  div[class*="z-[9999]"] > div:last-child > div:nth-child(2) > span.vilo-clock::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    height: 44px;
    transform: translateY(-50%);
  }

  /* Abmelden-Button komplett ausblenden (Vorgabe: Funktion nur noch über den
     VILO-Menü-Trigger ganz links, dort "Abmelden" anbieten). */
  div[class*="z-[9999]"] > div:last-child > button[title="Abmelden"] {
    display: none !important;
  }
}

/* M1.3b — ENTFERNT (2026-08, mobile-shell-Fix): der App-Name-Span wird jetzt per M1.7
 * (oben, im 767px-Block) auf JEDER Mobil-Breite komplett ausgeblendet statt hier nur
 * unterhalb 340px gekürzt — diese schmalere Zusatz-Query griff ins Leere, sobald ihr
 * Ziel bereits `display:none` ist. Verlauf: M1.3b sollte ursprünglich verhindern, dass
 * der Span den Abmelden-Button bei 320px aus dem Viewport drängt; M1.7 blendet ihn nun
 * aus einem zweiten, wichtigeren Grund auch bei 375–767px aus (Kollision mit dem
 * absolut zentrierten Namen, siehe M1.4-Kommentar) — der 320px-Fall ist damit als
 * Teilmenge mit erledigt.
 */

/* M1.2 — OS-Fenster auf Smartphones erreichbar machen (App-Iframe bekommt Mobil-Breite).
 *
 * Fenster-DOM (siehe DOM-Audit, React-gerendert/eingefroren, keine IDs/data-Attribute):
 *   .window-shadow                             Fenster-Root — EIGENE, semantische Klasse
 *                                               (kein Tailwind-Utility-Artefakt, daher als
 *                                               Selektor stabil). Inline: position:absolute;
 *                                               top/width/height (900×600 Desktop-Fixmaß) +
 *                                               transform (Kaskaden-Offset + Öffnen/Schließen-
 *                                               Animation). z-index pro Fenster aufsteigend
 *                                               (oberstes/fokussiertes Fenster = höchster Wert
 *                                               — bereits vorhandene, verlässliche Stapel-
 *                                               reihenfolge; kein JS/kernel.js nötig, da auf
 *                                               Mobil ohnehin nur EIN Fenster deckungsgleich
 *                                               den ganzen Screen füllt und das oberste per
 *                                               nativer z-index-Stapelung allein sichtbar/
 *                                               bedienbar ist — dahinterliegende Fenster sind
 *                                               vollständig verdeckt, kein CSS-Trick nötig, um
 *                                               "das aktive Fenster" gesondert zu selektieren).
 *   ├─ div.rounded-2xl.overflow-hidden…w-full.h-full   Clip-Wrapper
 *   │  ├─ div.cursor-grab…bg-neutral-800        Titelleiste (44px, draggable) — bleibt erhalten
 *   │  │  ├─ div.flex.items-center.gap-0        Ampel: button.window-btn (rot/gelb/grün =
 *   │  │  │                                     Schließen/Minimieren/Maximieren) — eigene,
 *   │  │  │                                     semantische Klasse, bleibt unangetastet
 *   │  │  ├─ div (zentrierter Titel-Text)
 *   │  │  └─ div.w-16 (Aktualisieren-Button)
 *   │  └─ div.flex-1.overflow-auto.bg-neutral-900   Content-Pane
 *   │     └─ div.w-full.h-full > iframe.w-full.h-full   App-Iframe — erbt Breite/Höhe vom
 *   │                                               Fenster-Root, braucht kein eigenes Ziel
 *   └─ 8× div.absolute.cursor-{ns,ew,nwse,nesw}-resize   Resize-Handles, direkte Kinder von
 *      .window-shadow (Geschwister des Clip-Wrappers) — auf Mobil überflüssig/fehleranfällig
 *      (versehentliches Ändern der Fenstergröße per Touch), da das Fenster ohnehin fix
 *      bildschirmfüllend ist.
 *
 * Kein Ahnen-Element von .window-shadow setzt transform/filter/perspective (per Audit
 * geprüft) — position:fixed verankert daher zuverlässig am echten Viewport, nicht an einem
 * versehentlich neuen Containing Block. Topleiste (z-[9999], M1.1) und Dock (z-9990, vom
 * Bundle bereits unabhängig positioniert/gestapelt) bleiben unangetastet und liegen dank
 * ihrer höheren z-index-Werte weiterhin sichtbar über dem Fenster. Der Dock (per DOM-Audit:
 * .absolute.bottom-4…, feste Pillenhöhe 92px, Bodenabstand ursprünglich 16px) würde bei
 * einem exakt bildschirmfüllenden Fenster dessen unteren Bereich optisch verdecken —
 * App-Inhalte dort blieben zwar über den Dock sichtbar, aber nicht mehr tappbar (Dock hat
 * höheren z-index). Die Fensterhöhe reserviert daher unten Platz nach DERSELBEN Formel wie
 * der in M1.3 safe-area-bewusst positionierte Dock-Bodenabstand (siehe dort) + 4px Puffer,
 * damit beide bei einem Home-Indicator (env(safe-area-inset-bottom) > 0) synchron bleiben
 * — der Dock selbst wird dabei nicht angefasst (non-goal: keine Dock-Änderungen in M1.2).
 * Bei env()=0 (Desktop-Browser ohne Notch, hier verifiziert) ergibt die Formel exakt die
 * bisherigen 112px (92px Pille + 16px Bodenabstand + 4px Puffer) — keine sichtbare Änderung
 * im getesteten Environment.
 */
@media (max-width: 600px) {
  /* GEOMETRIE ZOG UM → assets/app-shell-geometry.css.
     position/top/left/width/height/transform/max-* dieses Fensters lagen bis hierher
     an dieser Stelle und galten nur unterhalb 768px. Sie sind unverändert in die
     geteilte App-Shell-Geometrie gewandert, die jetzt Mobil UND Tablet trägt —
     dort steht dieselbe Formel (Topleiste + Notch-Inset oben, Dock-/Safe-Area-
     Reserve unten). Hier bleibt ausschliesslich Telefon-PRÄSENTATION.
     Wer die Fenstergrösse ändern will, ändert sie DORT, nicht hier: zwei Regeln
     für dieselbe Eigenschaft wären genau der zweite Eigentümer, den die geteilte
     Schicht abgeschafft hat. */
  .window-shadow {
    border-radius: 0 !important;
  }

  /* Innerer Clip-Wrapper füllt bereits per w-full/h-full das (jetzt bildschirmfüllende)
     Fenster-Root; nur die abgerundeten Ecken werden für den bildschirmfüllenden Look auf 0
     gesetzt (rein visuell, keine Layout-/Verhaltensänderung). */
  .window-shadow > .rounded-2xl {
    border-radius: 0 !important;
  }

  /* Resize-Handles (direkte Geschwister-Divs des Clip-Wrappers) ausblenden und deaktivieren
     — das Fenster ist auf Mobil fix bildschirmfüllend, Touch-Resize ist weder möglich noch
     gewünscht (Vorgabe: Resize-Handles auf Mobil unterdrücken). */
  .window-shadow > div[class*="cursor-ns-resize"],
  .window-shadow > div[class*="cursor-ew-resize"],
  .window-shadow > div[class*="cursor-nwse-resize"],
  .window-shadow > div[class*="cursor-nesw-resize"] {
    display: none !important;
    pointer-events: none !important;
  }

  /* M1.8 — Ampel (.window-btn, 12×12px, Bundle-Fixmaß) ist für Touch zu klein und hat auf
     Mobil nur eine sinnvolle Aktion: „Maximieren" ist durch das erzwungene Vollbild oben
     bereits wirkungslos, „Minimieren" räumt im Single-Active-App-Modus (M3) das Fenster
     genauso vollständig vom Schirm wie „Schließen". Gelb/Grün daher nur visuell verborgen,
     der bestehende rote Schließen-Button bekommt per ::after eine 44×44px-Trefferfläche
     (Technik wie M1.5/M1.6) — derselbe Button, derselbe Klick-Handler, nur größer tappbar.
     Desktop (>767px) unverändert. */
  .window-shadow .window-btn.bg-yellow-500\/80,
  .window-shadow .window-btn.bg-green-500\/80 {
    display: none !important;
  }
  .window-shadow .window-btn.bg-red-500\/80 {
    position: relative;
  }
  .window-shadow .window-btn.bg-red-500\/80::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 44px;
    height: 44px;
    transform: translate(-50%, -50%);
  }
}

/* M1.3 — OS-Dock auf Smartphones erreichbar halten (alle erlaubten Apps ohne Clipping).
 *
 * Dock-DOM (siehe DOM-Audit, React-gerendert/eingefroren, keine IDs/data-Attribute):
 *   div[class*="bottom-4"][class*="justify-center"]   Dock-Root — absolute, volle Breite,
 *                                               z-index:9990 (inline, unangetastet), zentriert
 *                                               sein Kind per justify-center. Einziges Element
 *                                               mit dieser Klassenkombination (per Audit
 *                                               geprüft) — als Selektor stabil.
 *   └─ div (Animations-Wrapper, opacity/transform inline)
 *      └─ div.glass-dock.rounded-3xl.px-4.py-3.flex.items-center.gap-2   Die sichtbare
 *         Dock-Pille. „.glass-dock" allein ist NICHT eindeutig (auch die Topleiste aus M1.1
 *         trägt diese Klasse) — „.rounded-3xl" kommt nur bei der Pille vor und disambiguiert
 *         zuverlässig. Breite ist inhaltsgetrieben (kein fixes CSS-Maß): 6 erlaubte Icons
 *         à 56×66px (w-14 h-14 + Label-Zeile) + gap-2 (8px) + px-4/py-3-Padding ergeben
 *         gemessen ≈410px Pillenbreite bei diesem Manifest-Stand (Bestellungen, Reservier-
 *         ungen, Raumplan, Reports, Personal-Gruppe, Franchise — verifiziert per DOM-Audit,
 *         inkl. zweier unsichtbarer 0×0-Gruppenmitglieder "Team"/"Zeiterfassung", die im
 *         Personal-Fächer aufgehen und keinen eigenen Platz in der Pille beanspruchen).
 *         ≈410px > jede Zielbreite (320/375/390px) → ohne Eingriff werden die äußersten
 *         Icons (erstes/letztes) beidseitig über den Viewport-Rand hinaus abgeschnitten.
 *
 * Gewählte Lösung: interner horizontaler Scroll auf der Pille selbst (kleinste additive
 * Änderung aus der Vorgabe), statt Icons zu verkleinern oder zu verstecken — Icon-Größe,
 * Touch-Zielgröße (56×66px) und Fächer-Verhalten bleiben exakt wie im Desktop-Fall
 * unangetastet, es wird nur zusätzlich wischbar, wenn nicht alles auf einmal passt. Die
 * eigentliche Positionierung (bottom-4 → 16px) wird zusätzlich safe-area-bewusst gemacht,
 * damit der Dock auf Geräten mit Home-Indicator nicht im Indicator-Bereich landet — bei
 * env(safe-area-inset-bottom)=0 (hier verifiziertes Environment) bleibt der Wert exakt bei
 * 16px, keine sichtbare Änderung im getesteten Browser.
 */
@media (max-width: 600px) {
  div[class*="bottom-4"][class*="justify-center"] {
    bottom: max(16px, calc(env(safe-area-inset-bottom) + 8px)) !important;
    /* M1.6 — Seitliche Einrückung: der Dock-Root spannt die volle Viewport-Breite,
       die Pille darunter darf per max-width:100% also bis exakt an beide Ränder
       laufen (Nutzer-Feedback per Screenshot: Pille klebt am Rand). Statt die Pille
       zu bemaßen, bekommt der Root ein Innenpolster — die max-width:100% der Pille
       rechnet gegen dessen Content-Box und respektiert die Einrückung automatisch,
       auch wenn sich die Icon-Anzahl (und damit die Pillenbreite) ändert. Der
       vertikale Wert (16px) wird als Seitenmaß gespiegelt, damit der Dock in allen
       vier Richtungen gleich weit vom Rand steht; safe-area-inset-left/right decken
       zusätzlich das Querformat auf Geräten mit Notch ab (Hochformat = 0 → exakt
       16px, keine Änderung im getesteten Environment). */
    padding-left: max(16px, env(safe-area-inset-left));
    padding-right: max(16px, env(safe-area-inset-right));
    box-sizing: border-box;
  }

  /* Zwischen Dock-Root und Pille sitzt ein klassenloser Animations-Wrapper-Div (nur
     inline opacity/transform), der als Flex-Kind des Dock-Roots per Default auf die
     Inhaltsbreite der Pille besteht (implizite Flex-Mindestbreite). Ohne diese Regel
     bleibt die weiter unten gesetzte max-width:100% auf der Pille wirkungslos, da sie
     sich gegen genau diesen (dann noch unbegrenzten) Wrapper berechnet. */
  div[class*="bottom-4"][class*="justify-center"] > div {
    max-width: 100%;
    min-width: 0;
  }

  /* Pille darf nicht breiter als der Viewport werden; erlaubt aber weiterhin volle
     Icon-Größe — Überschuss wird intern gescrollt statt am Viewport-Rand abgeschnitten.
     overflow-x:auto hebt zugleich die implizite Flex-Mindestbreite auf (min-width:auto),
     ohne die überschrieben würde max-width bei einem Flex-Kind wirkungslos bleiben und die
     Pille trotzdem auf ihre Inhaltsbreite (~410px) bestehen. */
  .glass-dock.rounded-3xl {
    max-width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .glass-dock.rounded-3xl::-webkit-scrollbar {
    display: none;
  }

  /* Icons dürfen beim Scrollen nicht schrumpfen (Touch-Ziel bleibt 56×66px) — ohne dies
     würde derselbe Flex-Shrink-Mechanismus, der die Pille selbst schrumpfen lässt, auch die
     einzelnen dock-item-Buttons stauchen. */
  .glass-dock.rounded-3xl > button.dock-item {
    flex-shrink: 0;
  }

  /* M1.5 — Abstand Icon→Pillenrand oben/unten angleichen (Nutzer-Feedback per
     Screenshot: unterer Abstand wirkt größer als oberer). Ursache per DOM-Audit: die
     Pille selbst hat symmetrisches Padding (py-3, 12px oben/unten), aber JEDES
     dock-item reserviert unterhalb des 56px-Icons zusätzlich 10px (4px Abstand +
     6px Höhe) für den Fokus-Punkt, der beim aktiven/offenen Fenster erscheint —
     dieser Platz bleibt auch reserviert, wenn der Punkt unsichtbar ist. Dadurch ist
     der reale Abstand Icon→Pillenboden (10px Punkt-Reserve + 12px Padding = 22px)
     fast doppelt so groß wie Icon→Pillendach (12px). Kompensiert durch symmetrisch
     verkleinertes Bodenpadding der Pille um genau diese 10px — die Punkt-Reserve
     selbst bleibt unangetastet (Fokus-Punkt-Funktion nicht antasten), nur das
     zusätzliche Pillenpolster darunter weicht ihr, bis beide Abstände gleich sind. */
  .glass-dock.rounded-3xl {
    padding-bottom: 2px;
  }
}

/* ============================================================================
 * M2 — Sperrbildschirm (Konto-Auswahl „Gastro System" + 4-stelliger PIN) auf
 *      Smartphones (Hoch- UND Querformat) erreichbar, flüssig scrollbar &
 *      kollisionsfrei halten. Reines Shell-Overlay gegen die vom eingefrorenen
 *      Bundle (assets/index-r1.js, React/Framer-Motion) gerenderte Lock-Screen-
 *      DOM — KEIN Bundle-/kompiliertes-CSS-Eingriff (Freeze-Doktrin).
 *
 * Anker (per Quell-Audit gegen das deployte, byte-identische Bundle verifiziert):
 *   .desktop-bg.justify-center  Lock-Root. ACHTUNG: .desktop-bg trägt AUCH der
 *       OS-Desktop nach dem Login (dort „desktop-bg relative", OHNE justify-center).
 *       Einziges Element mit BEIDEN Klassen ist der Lock-Root → nie bare .desktop-bg.
 *   .flex.gap-8                 Konto-Liste. „gap-8" kommt im GESAMTEN Bundle genau
 *       EINMAL vor → global eindeutig (Dots=gap-4, Keypad=gap-3). Direkte Kinder =
 *       Konto-<button>s (Reihenfolge/onClick unangetastet).
 *   #vilo-switch-betrieb        „Betrieb wechseln" — von index.html body-fixed
 *       injiziert; display wird per JS getoggelt → hier NIE display anfassen, nur
 *       die Position (per !important, da index.html sie inline setzt).
 *   PIN-Ansicht (per Struktur-Audit bestätigt, Kindreihenfolge in EINEM
 *       .flex.flex-col.items-center-Wrapper): Avatar (.w-24.h-24.rounded-full,
 *       global eindeutig) → Name-<p> (.text-lg) → Rollen-<p> (.text-sm.mb-8) →
 *       Dots (.flex.gap-4.mb-8, global eindeutig) → BEDINGT gerenderter Fehler-<p>
 *       ("Falscher PIN", nur bei falscher Eingabe) → Keypad (.grid.grid-cols-3.gap-3
 *       + .numpad-btn-Buttons) → bedingter Demo-PIN-<p>. WICHTIG: „grid grid-cols-3
 *       gap-3" ist NICHT global eindeutig (kollidiert mit „Tische"/„Stunden"-Stats-
 *       Grids in anderen OS-Apps) — deshalb IMMER unter .desktop-bg.justify-center
 *       scopen, nie bare .grid.grid-cols-3.gap-3. Die bedingte Fehlermeldung sitzt
 *       ZWISCHEN Dots und Keypad → jede nth-child-basierte Mehrspalten-Anordnung
 *       (z. B. Identität links / Keypad rechts) würde bei „Falscher PIN" den Keypad
 *       falsch einsortieren — deshalb bleibt die PIN-Ansicht ein einspaltiger
 *       Flex-Fluss, nur kompaktiert (Größen/Abstände), nie umstrukturiert.
 *
 * SCROLL-MODELL (behebt „springt beim Scrollen zurück nach oben"):
 * Das eingefrorene #root ist height:100%;overflow:hidden. Der Lock-Root wird selbst
 * zum Scroll-Container (overflow-y:auto) und behält die geerbte height:100% (KEIN
 * 100dvh — das kann auf iOS beim Ein-/Ausfahren der Browser-Leiste größer als #root
 * werden und wieder clippen). Die Zentrierung liegt auf dem INNEREN Wrapper
 * (min-height:100% + justify-content:center) statt als margin:auto auf dem Scroll-
 * Container selbst: margin:auto/align-center auf dem Scroller schneidet bei Überlauf
 * den OBEREN Rand ab bzw. lässt den Scroll „nach oben springen". Mit min-height:100%
 * ist der Inhalt zentriert solange er passt und wächst/scrollt-von-oben wenn nicht.
 * overscroll-behavior:contain verhindert das Weiterreichen an #root (Rubber-Band).
 *
 * LAYOUT je Orientierung (nach Nutzer-Feedback getauscht — v1 hatte es andersherum):
 *   Hochkant  = Konten HORIZONTAL in einer eigenen wischbaren Reihe (exakt dasselbe
 *               bewährte Muster wie der Dock in M1.3: overflow-x:auto + verstecktem
 *               Scrollbalken) — eine einzelne, kurze Reihe braucht keinen Platz nahe
 *               dem unteren Rand, „Betrieb wechseln" bleibt dadurch automatisch frei.
 *   Querformat (niedriges Smartphone, oft BREITER als 767px!) = Konten als VERTIKALE
 *               Liste, erreichbar über den ohnehin vorhandenen vertikalen Scroll des
 *               Lock-Roots (kein zusätzlicher Scroll-Container nötig).
 * „Betrieb wechseln" bekommt EINE einzige, orientierungsunabhängige Position (Boden-
 * mitte) im Kern-Block: die vorherige Sonderposition (untere rechte Ecke) im Quer-
 * format verursachte genau die beobachtete Überlappung, wenn die (damals horizontale)
 * Konto-Reihe bis ans rechte Ende gescrollt wurde — die Boden-Reservierung wirkt
 * dagegen unabhängig von der Scroll-Position, weil sie den sichtbaren Container
 * tatsächlich verkürzt statt nur den Button zu verschieben.
 *
 * PIN-KOMPAKTIERUNG: dieselbe PIN-Ansicht wird auf sehr niedrigen Querformat-Geräten
 * enger (kleinerer Avatar/Abstände/Tasten) als im Hochformat, damit Avatar+Name+
 * Rolle+Dots+3-reihiges Tastenfeld ohne Scroll passen — Tasten bleiben in beiden
 * Fällen komfortabel über der 44px-Mindestgröße (60px Hochkant / 48px Querformat).
 *
 * Alle Regeln nur für Smartphone-Viewports (schmal ODER niedrig-und-nicht-breiter-
 * als-ein-Landscape-Phone) → Desktop (>=768px breit & >500px hoch) sieht nichts davon.
 * ============================================================================ */

/* --- Kern: safe-area-bewusster Scroll-Container + EINE Betrieb-wechseln-Position
       für Smartphones in BEIDEN Orientierungen (schmal ODER niedrig). --- */
@media (max-width: 600px), (max-height: 500px) and (max-width: 932px) {
  .desktop-bg.justify-center {
    box-sizing: border-box;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
    align-items: flex-start;
    padding-top: max(16px, env(safe-area-inset-top));
    padding-left: max(20px, env(safe-area-inset-left));
    padding-right: max(20px, env(safe-area-inset-right));
    /* Reserviert Platz unter dem fixen „Betrieb wechseln", damit das letzte Konto /
       die unterste Keypad-Reihe frei darüber scrollt. */
    padding-bottom: max(88px, calc(env(safe-area-inset-bottom) + 80px));
  }
  /* Zentrierung auf dem INNEREN Wrapper (nicht als margin:auto auf dem Scroller):
     min-height:100% zentriert den Inhalt wenn er passt und wächst/scrollt-von-oben
     wenn nicht → kein Cutoff/Sprung. justify-content wirkt auf die vertikale Achse
     (Wrapper ist flex-col). margin:0 neutralisiert etwaige auto-Margins. */
  .desktop-bg.justify-center > div {
    width: 100%;
    min-height: 100%;
    justify-content: center;
    margin: 0;
  }
  /* „Betrieb wechseln": EINE Position für beide Orientierungen (Bodenmitte,
     safe-area-bewusst, Baseline 34px via max()) — reserviert bereits oben im
     Scroll-Container, dadurch keine Kollision unabhängig von der Scroll-Position. */
  #vilo-switch-betrieb {
    bottom: max(34px, calc(env(safe-area-inset-bottom) + 16px)) !important;
  }
}

/* --- Hochkant: Konten horizontal in einer eigenen wischbaren Reihe (dasselbe Muster
       wie der Dock, M1.3) statt untereinander — behebt sowohl das Scroll-Verhalten
       (eine kurze Reihe statt einer langen vertikalen Liste) als auch die Nähe zu
       „Betrieb wechseln". PIN-Ansicht: leichte Kompaktierung, passt i. d. R. ohne
       Scroll unter den mobilen Browser-Chrome. --- */
@media (max-width: 600px) and (orientation: portrait) {
  .desktop-bg.justify-center .flex.gap-8 {
    flex-direction: row;
    flex-wrap: nowrap;
    gap: 1rem;
    width: 100%;
    max-width: 100%;
    justify-content: flex-start;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 6px;
  }
  .desktop-bg.justify-center .flex.gap-8::-webkit-scrollbar {
    display: none;
  }
  .desktop-bg.justify-center .flex.gap-8 > button {
    flex: 0 0 auto;
    width: auto;
  }

  /* PIN-Kompaktierung (Hochkant, leicht — siehe Dimensionierungsplan): Avatar
     96px→80px, Dots-Bodenabstand 32px→24px, Tasten-Lücke 12px→8px, Tasten
     64px→60px. Budget ≈398px vs. ~520px verfügbar (inkl. Fehlertext) → reichlich
     Puffer, Tasten bleiben deutlich über der 44px-Mindestgröße. */
  .desktop-bg.justify-center .w-24.h-24.rounded-full {
    width: 80px;
    height: 80px;
  }
  .desktop-bg.justify-center .flex.gap-4.mb-8 {
    margin-bottom: 24px;
  }
  .desktop-bg.justify-center .grid.grid-cols-3.gap-3 {
    gap: 8px;
  }
  .desktop-bg.justify-center .numpad-btn {
    width: 60px;
    height: 60px;
  }
}

/* --- Querformat (niedriges Smartphone): Konten als vertikale Liste, erreichbar über
       den vertikalen Scroll des Lock-Roots (kein horizontales Wischen nötig, wenn
       ohnehin schon wenig Höhe da ist). PIN-Ansicht: stärkere Kompaktierung, damit
       Avatar+Name+Rolle+Dots+Tastenfeld auf ~360px Höhe ohne Scroll passen. --- */
@media (orientation: landscape) and (max-height: 500px) and (max-width: 932px) {
  .desktop-bg.justify-center .flex.gap-8 {
    flex-direction: column;
    gap: 0.5rem;
    width: 100%;
    max-width: 320px;
  }
  .desktop-bg.justify-center .flex.gap-8 > button {
    width: 100%;
  }

  /* PIN-Kompaktierung (Querformat, stärker — siehe Dimensionierungsplan): Avatar
     96px→56px, Name-/Rollen-Bodenabstand reduziert, Dots-Bodenabstand 32px→8px,
     Tasten-Lücke 12px→8px, Tasten 64px→48px (weiterhin >44px). Budget ≈310px vs.
     ~360px verfügbar (inkl. Fehlertext ≈334px) → knapper, aber positiver Puffer;
     der äußere Scroll-Container (Kern-Block) bleibt zusätzlich als Fallback aktiv. */
  .desktop-bg.justify-center .w-24.h-24.rounded-full {
    width: 56px;
    height: 56px;
  }
  .desktop-bg.justify-center p.text-lg {
    margin-bottom: 2px;
  }
  .desktop-bg.justify-center p.text-sm.mb-8 {
    margin-bottom: 8px;
  }
  .desktop-bg.justify-center .flex.gap-4.mb-8 {
    margin-bottom: 8px;
  }
  .desktop-bg.justify-center .grid.grid-cols-3.gap-3 {
    gap: 8px;
  }
  .desktop-bg.justify-center .numpad-btn {
    width: 48px;
    height: 48px;
  }
}

/* ============================================================================
 * M3 — Mobiler Single-Active-App-Modus (additiv, NUR mobil, Desktop unberührt)
 *
 * Ziel: auf Mobil zeigt NUR der neutrale Startbildschirm (Launcher) den Dock. Sobald
 * eine App/das Profil-Fenster offen ist, nutzt sie die volle verfügbare Viewport-Höhe
 * — ohne den in M1.2 reservierten 96px-Dock-Korridor. Der Kernel setzt dafür weiterhin
 * EINEN Zustandsanker an <html> (kernel.js, syncMobileMode() — kanonischer State, hier
 * nur ausgewertet, nicht dupliziert):
 *
 *   html[data-vilo-mobile="launcher"]  kein sichtbares App-Fenster → Dock sichtbar
 *   html[data-vilo-mobile="app"]       ein App-Fenster im Vordergrund → Dock aus,
 *                                      Fenster ganzflächig (nur Safe-Area reserviert)
 *   (Attribut FEHLT ≥768px)            Desktop: keine Regel greift, unverändert
 *
 * Rückkehr zum Launcher (App schließen) setzt den Zustand automatisch zurück auf
 * "launcher" und damit den Dock wieder sichtbar — kein separater Restore-Pfad nötig.
 * ==========================================================================*/
@media (max-width: 600px) {
  /* (1) GEOMETRIE ZOG UM → assets/app-shell-geometry.css.
         Hier stand die App-Modus-Höhe (Fenster bis zum Viewport-Boden, 96px-Dock-
         Korridor entfällt). Dieselbe Aussage lebt jetzt dort als untere Reserve:
         `html[data-vilo-appshell="app"]` setzt sie unterhalb 768px auf die blosse
         Safe-Area — null Dock-Korridor, weil (2) den Dock ausblendet.

         SAFE-AREA — EIN EINZIGER EIGENTÜMER: das bleibt gültig, nur ist der eine
         Eigentümer jetzt die geteilte Schicht (Shell-Dokument, trägt
         viewport-fit=cover) — die App-Dokumente selbst tragen bewusst KEIN
         viewport-fit=cover (sonst doppelte Reservierung im iframe).

         Das Ausblenden des Docks (2) bleibt hier: es ist Telefon-VERHALTEN,
         keine Geometrie. */

  /* (2) App-Modus: den globalen Dock ausblenden. Der Dock ist ein position:absolute-
         Overlay (kein eigener Korridor) — hier genügt Wegblenden. !important schlägt
         den Framer-Motion-Inline-Transform des Bundles. */
  html[data-vilo-mobile="app"] div[class*="bottom-4"][class*="justify-center"] {
    opacity: 0 !important;
    transform: translateY(140%) !important;
    pointer-events: none !important;
    transition: transform .24s ease, opacity .24s ease;
  }
}

