
  html, body { margin: 0; height: 100%; background: #1c1c1c; font-family: system-ui, sans-serif; }
  #viewport { position: fixed; inset: 0; overflow: hidden; cursor: grab; touch-action: none; }
  #mapWrap { position: absolute; top: 0; left: 0; transform-origin: 0 0; }
  #mapWrap img { display: block; }
  .marker {
    position: absolute;
    width: 44px; height: 44px;
    margin-left: -22px; margin-top: -22px;
    border-radius: 50%;
    cursor: pointer;
  }
  .marker:hover { background: rgba(255,255,255,0.35); outline: 2px solid #fff; }
  .marker--disabled { cursor: not-allowed; }
  .marker--disabled:hover { background: none; outline: none; }
  /* IMU-Relativregistrierungs-Genauigkeit (siehe _build_left_markers_html/project_map.
     imu_relative_accuracy) - kleiner Kreis, nur sichtbar wenn der umgebende Marker gerade
     als .marker--current (aktive Scanposition, gross) angezeigt wird, siehe _SPLIT_CSS. */
  .marker-imu-dot {
    display: none; position: absolute; top: 50%; left: 50%;
    width: 40px; height: 40px; margin: -20px 0 0 -20px; border-radius: 50%;
    border: 2px solid #fff;
  }
  /* Anwenderwunsch (2026-08-18, vorerst nur "2026-07-30 Millennium"): Sonnenposition im
     Fotopanorama als gelber Kreis mit orangenem Rahmen, per Kurztaste 'o' ein-/ausblendbar
     (siehe renderSunMarker in _SPLIT_JS). pointer-events:none - reine Anzeige, soll die
     Panorama-Maussteuerung (Ziehen/Zoomen) nicht blockieren. */
  .sun-marker {
    position: absolute; width: 28px; height: 28px; margin-left: -14px; margin-top: -14px;
    border-radius: 50%; background: #ffd400; border: 3px solid #f39314;
    pointer-events: none; box-shadow: 0 0 6px rgba(0,0,0,0.5);
  }
  .zoom-controls {
    position: fixed; right: 16px; bottom: 16px; z-index: 10;
    display: flex; flex-direction: column; gap: 6px;
  }
  .zoom-controls button {
    width: 46px; height: 40px; border-radius: 8px; border: none;
    background: rgba(255,255,255,0.9); color: #1c1c1c; font-size: 20px;
    cursor: pointer; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  }
  /* Mehrbuchstabige Text-Buttons (3D/KML) statt der Icon-Buttons: gleiche Breite wie oben (alle
     Buttons von 3D bis KML sollen gleich breit sein), aber kleinere Schrift als die einzelnen
     Icon-Buttons, da 20px bei 3 Buchstaben nicht mehr in 46px passen wuerde. */
  .zoom-controls button.text-btn {
    font-size: 15px; font-weight: 700; letter-spacing: 0.02em;
  }
  /* "Ebenen"-Icon (Kartenhintergrund umschalten: OpenStreetMap/Satellit/weiss) statt Text -
     dasselbe Symbol, mit dem Kartenanwendungen ueblicherweise den Basiskartentyp umschalten. */
  .zoom-controls button.sat-toggle {
    display: flex; align-items: center; justify-content: center; padding: 0;
  }
  .zoom-controls button.sat-toggle svg { width: 22px; height: 22px; display: block; }
  .zoom-controls button:hover { background: #fff; }
  .zoom-controls button:disabled { opacity: 0.35; cursor: not-allowed; }
  .zoom-controls button:disabled:hover { background: rgba(255,255,255,0.9); }
  /* 3D-Button jetzt eigenstaendig oben links (gleiche Randabstaende wie #mapHeader), NICHT
     mehr Teil der .zoom-controls-Saeule - damit er exakt an derselben Bildschirmstelle sitzt
     wie der "2D"-Button auf der 3D-Seite (siehe proj.py reposition_compass_js), fuer schnelles
     Hin- und Herschalten per Mausklick. */
  .goto-3d-btn {
    position: absolute; top: 10px; left: 8px; z-index: 10;
    width: 46px; height: 44px; border-radius: 8px; border: none;
    background: rgba(255,255,255,0.9); color: #1c1c1c;
    font-family: system-ui, sans-serif; font-size: 18px; font-weight: 700;
    letter-spacing: 0.02em; cursor: pointer; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
  }
  .goto-3d-btn:hover { background: #fff; }
  /* Duenner oranger Rahmen (RIEGL-Orange) mit abgerundeten Ecken auf ALLEN Buttons dieser
     Seite (nicht der Scanpositions-Marker, die sind <a>-Elemente, keine <button>s) - bewusst
     mit !important, um bestehende, spezifischere Button-Stile (z.B. "border: none" bei
     .zoom-controls button) nicht einzeln aufsuchen/anpassen zu muessen. */
  button {
    border: 1px solid #f39314 !important;
    border-radius: 6px !important;
    /* Anwenderwunsch: langes Gedrueckthalten eines Buttons (z.B. fuer die Pfeiltasten-
       Wiederholung, siehe makeHoldRepeat) loeste auf dem iPhone bisher das native Text-
       Auswahl-/Nachschlage-Menu aus (blaue Markierung + "Kopieren/Auswahl suchen/
       Nachschlagen"), weil ein <button> mit Text-/Symbolinhalt fuer iOS wie normaler,
       auswaehlbarer Text zaehlt. -webkit-touch-callout unterdrueckt das Menu selbst,
       user-select verhindert zusaetzlich die blaue Markierung - fuer ALLE Buttons dieser
       Seite (keine Notwendigkeit, nur die betroffenen einzeln aufzusuchen). */
    -webkit-touch-callout: none;
    -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;
  }


  #splitContainer { position: fixed; inset: 0; }
  .pane { position: absolute; top: 0; bottom: 0; overflow: hidden; cursor: grab; touch-action: none; background: #1c1c1c; }
  .pane .wrap { position: absolute; top: 0; left: 0; transform-origin: 0 0; }
  .pane .wrap img { display: block; }
  .pane .zoom-controls { position: absolute; right: 16px; bottom: 16px; }
  /* mapReflectorMarkers spannt (wie mapMarkers) die gesamte Projectmap auf, damit die
     wenigen Reflektor-Kreise absolut darin positioniert werden koennen - ohne
     pointer-events:none wuerde dieser leere Container aber JEDEN Klick auf die Projectmap
     abfangen (er liegt im DOM nach mapMarkers, also optisch darueber) und so die
     Scanpositions-Marker darunter unklickbar machen. */
  #mapReflectorMarkers { pointer-events: none; }
  #mapReflectorMarkers .marker--reflector { pointer-events: auto; }
  /* Fein gescannter Reflektor (siehe proj.collect_tiepoint_images): kleiner oranger Kreis an
     der tatsaechlichen Reflektorposition, sowohl im Panorama (#panoMarkers) als auch in der
     Projectmap (#mapReflectorMarkers) - deutlich kleiner als die normalen 44px-Marker und
     nicht anklickbar (nur Hinweis, keine Navigation). */
  .marker--reflector {
    width: 16px; height: 16px; margin-left: -8px; margin-top: -8px;
    background: #ff9500; border: 2px solid #fff; cursor: default; z-index: 7;
  }
  .marker--reflector:hover { background: #ff9500; outline: none; }
  /* Beim Anklicken einer Reflektor-Feinscan-Thumbnail (#panoTiePointImages) wird der
     zugehoerige Marker hier UND in der Projectmap rot hervorgehoben (siehe Klick-Handler bei
     panoTiePointImages) - .active nach .marker--reflector im Quelltext (gleiche Spezifitaet
     wie :hover, gewinnt bei Gleichstand durch spaetere Regel). */
  .marker--reflector.active { background: #e60000; }
  .pv-reflector-selected { outline: 2px solid #e60000; outline-offset: -1px; }
  /* Scanpositions-Ueberschrift oben, Panorama-Infoleisten unten: schieben das Panorama
     selbst in den Bereich dazwischen. Direkt unter dem Panorama: Exposure/ISO (links)
     und ein Helligkeits-Histogramm (rechts); darunter: Datum/Uhrzeit/Wetter. */
  #panoScanLabel {
    position: absolute; top: 0; left: 0; right: 0; height: 64px;
    background: #111; border-bottom: 1px solid #333; color: #fff;
    display: flex; align-items: center; justify-content: space-between; padding: 0 12px;
    font-family: system-ui, sans-serif; font-size: 26px; font-weight: 600;
  }
  #panoHeaderLeft { display: flex; align-items: center; gap: 8px; flex: 0 1 auto; min-width: 0; }
  /* Zeile zwischen Ueberschrift und Panorama: links die Scanner-Schnellvorschau
     (proj.collect_scan_previews, praktisch immer vorhanden), rechts - falls fuer die aktuelle
     Scanposition vorhanden - die fein gescannten Reflektoren (ScanPosXXX.SCNPOS/
     tiepointscans/*_TP##.png), von rechts nach links aneinandergereiht (row-reverse). Beide
     Kindelemente sind gleich hoch. rightViewport.style.top wird per JS umgeschaltet (siehe
     renderPanoTiePoints) - display:none macht diese Zeile hier unsichtbar UND nimmt keinen
     Platz weg, wenn weder Vorschau noch Reflektorbilder vorhanden sind. */
  #panoTiePoints {
    position: absolute; top: 64px; left: 0; right: 0; height: 112px;
    z-index: 5; display: none; align-items: center; justify-content: space-between; gap: 12px;
    padding: 0 12px; background: #111; border-bottom: 1px solid #333; box-sizing: border-box;
  }
  #panoTiePoints.has-images { display: flex; }
  #panoScanPreview {
    flex: 0 0 auto; height: calc(112px - 16px); display: none;
    /* position:relative/overflow:hidden/border-radius/border (Anwenderwunsch: der Rahmen
       bleibt fest um die kleine Vorschau, waehrend syncPreviewToMainPano() das Bild darin per
       Transform pannt/zoomt) - waehrend des Tauschs (siehe setPanoSwapped) werden position/
       overflow ohnehin per Inline-Style auf 'fixed'/'hidden' ueberschrieben, border-radius
       bleibt unveraendert bestehen. */
    position: relative; overflow: hidden; border-radius: 4px; border: 1px solid #f39314;
    box-sizing: content-box;
    /* siehe #rightViewport - dieselbe blaue Markierung trat auch beim Scan-Vorschaubild auf. */
    -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;
  }
  #panoScanPreview.visible { display: block; cursor: pointer; }
  /* Per ID statt ueber "#panoScanPreview img" (traefe sonst auch die beiden unten definierten
     Wrap-Around-Kopien, die ausserhalb der grossen getauschten Ansicht immer verstect bleiben
     sollen). position:absolute/kein height/width mehr - Groesse/Position kommen jetzt
     ausschliesslich aus dem JS-Transform (siehe previewApply/previewFitToScreen/
     syncPreviewToMainPano), damit sich die Vorschau mit dem Fotopanorama synchronisieren
     laesst (Anwenderwunsch) - der Rahmen sitzt dafuer jetzt auf dem Container (#panoScanPreview
     oben), nicht mehr auf dem (jetzt frei transformierten) Bild selbst. */
  /* transform-origin explizit 0 0 (CSS-Default waere 50% 50%, die Bildmitte) - die gesamte
     Positionsrechnung (previewApply/syncPreviewToMainPano) geht von einem Ursprung in der
     oberen linken Ecke aus, wie es die getauschte Ansicht bereits per Inline-Style setzt
     (siehe setPanoSwapped) - hier als Grundregel ergaenzt, damit auch der kleine, nicht
     getauschte Modus (der bisher keinerlei Transform verwendete) korrekt skaliert statt um
     die Bildmitte statt die Bildecke (fuehrte zu einer stark falsch positionierten, praktisch
     leeren Vorschau bei jedem Zoom-Stand ausser dem allerersten). */
  #panoScanPreviewImg { display: block; position: absolute; top: 0; left: 0; transform-origin: 0 0; }
  /* Die beiden Wrap-Around-Kopien (siehe previewApply) - Anwenderwunsch: auch in der kleinen,
     mit dem Fotopanorama synchronisierten Ansicht sichtbar (nicht mehr nur waehrend des
     Tauschs), damit ein Ueberlauf ueber die 360-Grad-Naht hinweg (siehe syncPreviewToMainPano)
     luecklos gefuellt bleibt - genau wie es die drei Kopien beim Fotopanorama selbst schon
     tun (rightImgL/-R, siehe panoApply). OHNE eigenen Rahmen (keine Naht mitten im Bild) und
     ohne Mausinteraktion (die haengt weiterhin komplett an #panoScanPreview). */
  #panoScanPreviewImgL, #panoScanPreviewImgR {
    display: block; position: absolute; top: 0; left: 0; transform-origin: 0 0;
    pointer-events: none; border: none;
  }
  #panoTiePointImages {
    flex: 1 1 auto; min-width: 0; height: 100%; display: flex; flex-direction: row-reverse;
    align-items: center; gap: 8px; overflow-x: auto;
  }
  #panoTiePointImages img {
    height: calc(112px - 16px); width: calc(112px - 16px);
    object-fit: cover; border-radius: 4px; border: 1px solid #f39314; flex: 0 0 auto;
  }
  #rightViewport {
    position: absolute; top: 64px; left: 0; right: 0; bottom: 206px;
    overflow: hidden; cursor: grab; touch-action: none;
    /* Anwenderwunsch: das Bild faerbt sich sonst gelegentlich blau (Browser-eigene Text-/
       Bild-Markierung, ausgeloest durch Doppelklick oder durch Ziehen mit gedrueckter linker
       Maustaste - beides normale Browser-Gesten, die hier aber zum Verschieben/Zoomen
       gebraucht werden, nicht zum Markieren). user-select:none unterbindet das. */
    -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;
  }
  /* Panoramabild (nicht die Kachel-Bilder der Project Map, die ebenfalls ".wrap img" matchen
     wuerden) - oben dicker, unten duenner oranger Rahmen (Anwenderwunsch); links/rechts
     bewusst KEIN Rahmen mehr, seit das Bild fuer endloses Herumdrehen (siehe rightImgL/-R
     unten) nahtlos an sich selbst anschliesst - ein Rahmen dort waere eine stoerende Naht
     mitten in der eigentlich durchgehenden 360-Grad-Drehung. Dieselbe Regel gilt fuer die
     beiden Wrap-Around-Kopien, damit der obere/untere Streifen ueber die ganze Drehung hinweg
     durchgehend aussieht, unabhaengig davon, welche der drei Bildkopien gerade sichtbar ist. */
  /* Dicke wie #panoFrame's oberer Rahmen (16px) - dort ist es die eigentliche, per Ziehen
     verschiebbare Histogramm-Ausschluss-Grenze; hier ist es (an allen drei Bildkopien
     gleichermassen) der optische Bild-"Rahmen". Beide zusammen ergeben bei cropTopFrac==0
     (Normalfall) exakt eine einzige, ueberall gleich dicke Linie - sonst waere sie nur ueber
     der jeweils "kanonischen" Kopie (dort sitzt #panoFrame, siehe unten) dicker als ueber den
     beiden Wrap-Around-Nachbarn (vom Anwender gemeldet: "links dick, rechts nicht"). */
  #rightImg, #rightImgL, #rightImgR {
    border-top: 16px solid #f39314; border-bottom: 1px solid #f39314;
    border-left: none; border-right: none; box-sizing: border-box;
  }
  /* Zusaetzlich zu draggable="false" (siehe Markup) - verhindert in WebKit/Blink auch das
     "Geister-Bild", das beim Ziehen sonst gelegentlich statt des erwarteten Verschiebens
     erscheint (Teil desselben "wird blau/reagiert falsch beim Ziehen"-Problems). */
  #rightImg, #rightImgL, #rightImgR, #panoScanPreviewImg, #panoScanPreviewImgL, #panoScanPreviewImgR {
    -webkit-user-drag: none; user-drag: none;
  }
  /* Zwei zusaetzliche Kopien desselben Panoramas fuer nahtloses, endloses Herumdrehen (siehe
     panoApply/switchTo in der JS unten) - links/rechts der Hauptkopie positioniert,
     pointer-events:none (Maus-/Touch-Bedienung bleibt ausschliesslich am #rightViewport-
     Container haengen, unabhaengig davon, welche der drei Bildkopien gerade darunter sichtbar
     ist). */
  #rightImgL, #rightImgR { position: absolute; top: 0; pointer-events: none; }
  #panoInfo {
    position: absolute; left: 0; right: 0; bottom: 56px; height: 150px;
    background: #111; border-top: 1px solid #333; color: #fff;
    display: flex; font-family: system-ui, sans-serif;
  }
  #panoInfoExif {
    flex: 1; padding: 16px 24px; font-size: 22px; line-height: 1.8; white-space: nowrap;
  }
  #panoInfoHist { flex: 1; padding: 12px 20px; }
  #panoInfoHist canvas { width: 100%; height: 100%; display: block; background: #000; }
  /* QR-Code der AKTUELL im Browser geoeffneten Seite (window.location.href, clientseitig per
     qrcode.js gerendert - siehe unten) - rechts neben dem Histogramm, damit jemand anderes per
     Scan exakt dieselbe Seite oeffnen kann, egal wo/wie sie gerade gehostet ist. Feste Hoehe
     wie das Histogramm, quadratisch (Canvas-Breite=Hoehe wird per JS gesetzt). */
  #panoInfoQr { flex: 0 0 auto; display: flex; align-items: center; padding: 12px 24px 12px 0; }
  #panoInfoQr canvas { height: 100%; width: auto; display: block; border-radius: 4px; background: #fff; }
  /* #panoInfoQrImg spiegelt denselben QR-Code als echtes <img> (siehe updatePageQr() im JS) -
     per Default versteckt (Desktop zeigt weiterhin den Canvas), nur in der kombinierten
     Mobil-Media-Query weiter unten sichtbar (dort dann statt des Canvas) - siehe dortigen
     Kommentar fuer den Grund (natives Teilen/Foto-sichern-Menu per langem Antippen). */
  #panoInfoQr img { display: none; }
  /* Nav-/Zoom-Buttons: unten linksbuendig in derselben Zeile wie Exposure/ISO und
     Histogramm - links buendig mit dem Exposure/ISO-Text (gleicher 24px-Abstand wie
     #panoInfoExif), unten buendig mit der Unterkante des Histogramms (gleicher 12px-Abstand
     wie #panoInfoHist) - invertiert (weiss auf dunklem Grund, passt zum dunklen
     panoInfo-Hintergrund) und in derselben Groesse wie die Projectmap-Buttons (40x40px,
     siehe .zoom-controls button). Eigene Klasse statt der gemeinsamen .zoom-controls, damit
     die Projectmap-Buttons links (die weiterhin schwebend/hell bleiben) unberuehrt bleiben. */
  #panoButtonsRow {
    position: absolute; left: 24px; bottom: 12px; display: flex; align-items: center; gap: 10px;
  }
  #panoButtonsRow button {
    width: 40px; height: 40px; border-radius: 8px; border: none;
    background: rgba(255,255,255,0.12); color: #fff; font-size: 20px;
    cursor: pointer;
  }
  #panoButtonsRow button:hover { background: rgba(255,255,255,0.25); }
  #panoButtonsRow button:disabled { opacity: 0.35; cursor: not-allowed; }
  #panoButtonsRow button:disabled:hover { background: rgba(255,255,255,0.12); }
  #panoInfo2 {
    position: absolute; left: 0; right: 0; bottom: 0; height: 56px;
    background: #0a0a0a; border-top: 1px solid #333; color: #fff;
    display: flex; align-items: center; font-family: system-ui, sans-serif; font-size: 18px;
  }
  #panoInfo2 > div { flex: 1; padding: 0 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  /* Duenner oranger Rahmen um das Panorama; die obere Linie ist per Ziehen verschiebbar -
     das Histogramm bezieht sich dann nur auf den Bildteil, der noch eingerahmt ist.
     panoFrameMask (abgedunkelter, ausgeschlossener oberer Teil) ist ein Geschwister von
     panoFrame - beide liegen im selben Koordinatensystem wie das Bild (#rightWrap). */
  /* Weiss->Schwarz-Blinken reinweisser Pixel (siehe toggleWhiteBlink): invert(1) dreht die
     immer reinweiss gespeicherte Maske zu Schwarz, ohne den Alphakanal zu veraendern. Je eine
     Kopie links/rechts der Bildkopien-Kanone (siehe rightImgL/-R) - Position/Breite wird wie
     dort in panoApply() per JS gesetzt, damit das Blinken unabhaengig davon sichtbar ist,
     welche der drei Kopien man gerade sieht (vom Anwender gemeldet: ging nur bei einer). */
  #panoWhiteBlink.inverted, #panoWhiteBlinkL.inverted, #panoWhiteBlinkR.inverted { filter: invert(1); }
  /* left/width werden wie bei rightImgL/-R per JS gesetzt (siehe panoApply) - dieselben drei
     Kopien fuer den Histogramm-Ausschluss-Rahmen (Frame+Maske+Handle), damit sich die per
     Ziehen verschiebbare Grenze unabhaengig davon bedienen laesst/sichtbar bleibt, welche der
     drei Bildkopien gerade im Viewport ist (vom Anwender gemeldet: Ziehen wirkte sich nur auf
     eine der beiden sichtbaren Kopien aus). */
  #panoFrameMask, #panoFrameMaskL, #panoFrameMaskR {
    position: absolute; top: 0; height: 0;
    background: rgba(0,0,0,0.4); pointer-events: none;
  }
  #panoFrame, #panoFrameL, #panoFrameR {
    position: absolute; bottom: 0; top: 0;
    /* Nur noch oben ein Rahmen (die eigentliche, ziehbare Grenze) - links/rechts/unten
       entfernt: der optische Bild-Rahmen kommt ausschliesslich von #rightImg/-L/-R (siehe
       oben), dieser hier ist nur noch die Ziehlinie selbst. */
    border: none; border-top: 16px solid #ff9500;
    box-sizing: border-box; pointer-events: none;
  }
  /* Doppelt so dick wie zuvor (8px -> 16px) - auf einem iPad/Touchscreen ohne praezisen
     Mauszeiger liess sich der duenne obere Rahmen kaum treffen/ziehen. Der Handle bleibt um
     denselben (jetzt ebenfalls verdoppelten) Betrag zentriert um die Rahmenkante herum. */
  #panoFrameHandle, #panoFrameHandleL, #panoFrameHandleR {
    position: absolute; left: 0; right: 0; top: -14px; height: 28px;
    cursor: row-resize; pointer-events: auto;
  }
  #panoFrameIcon {
    position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
    color: #ff9500; background: rgba(0,0,0,0.7); border-radius: 4px;
    padding: 0 6px; font-size: 42px; line-height: 1.6; pointer-events: none;
    font-family: system-ui, sans-serif;
  }
  #divider {
    position: absolute; top: 0; bottom: 0; width: 16px; margin-left: -8px;
    background: #444; cursor: col-resize; z-index: 15; touch-action: none;
  }
  #divider:hover { background: #666; }
  /* Ueberschrift + RIEGL-Logo links oben in der Projectmap. */
  #mapHeader {
    position: absolute; top: 10px; right: 16px; z-index: 10; height: 44px; box-sizing: border-box;
    display: flex; align-items: center; gap: 10px;
    background: rgba(255,255,255,0.9); padding: 0 14px; border-radius: 6px;
    border: 1px solid #f39314; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
    font-family: system-ui, sans-serif; font-size: 20px; font-weight: 600; color: #1c1c1c;
  }
  #mapHeader img { height: 28px; width: auto; display: block; }
  #helpBtn {
    width: 28px; height: 28px; flex: 0 0 auto; border-radius: 6px;
    border: none; background: rgba(0,0,0,0.08); color: #1c1c1c; font-size: 15px;
    font-weight: 700; cursor: pointer;
    font-style: normal; font-family: system-ui, sans-serif;
  }
  #helpBtn:hover { background: rgba(0,0,0,0.18); }
  /* Textfenster mit GNSS-/IMU-Genauigkeit der aktuell angezeigten (rechts als Panorama
     offenen, links als grosser Kreis markierten) Scanposition - siehe updateMapScanInfo,
     aufgerufen von switchTo(). Unten links, oberhalb der (kleineren) OSM-Attribution -
     display:none, solange kein Inhalt gesetzt ist (Projekte ganz ohne GNSS/IMU-Daten haetten
     sonst eine leere Box stehen) bzw. solange nicht ueber der aktiven Scanposition gehovert
     wird (siehe mouseover/mouseout auf #mapMarkers). */
  #mapScanInfo {
    position: absolute; bottom: 34px; left: 8px; z-index: 10; display: none;
    background: rgba(255,255,255,0.9); padding: 8px 14px; border-radius: 6px;
    border: 1px solid #f39314; box-shadow: 0 1px 4px rgba(0,0,0,0.4);
    font-family: system-ui, sans-serif; font-size: 15px; line-height: 1.5; color: #1c1c1c;
    white-space: nowrap;
  }
  #mapScanInfo b { font-size: 17px; }
  /* Anwenderwunsch: "N/A relative accuracy" (siehe updateMapScanInfo) fett UND anklickbar -
     oeffnet showImuNaInfo() mit einer Erklaerung, wann/warum das passiert. cursor:pointer als
     einziger zusaetzlicher visueller Hinweis (bewusst keine Unterstreichung, sonst sieht der
     fette Text wie ein echter Link aus, obwohl er nur einen Infodialog oeffnet). */
  #mapScanInfo .imu-na-info { cursor: pointer; }
  /* Breiteres, scrollbares Modal-Panel fuer den Hilfetext (mehr Inhalt als Passwort-/
     Start-Hinweis-Dialog). */
  #appModalPanel.wide { max-width: 820px; max-height: 80vh; overflow-y: auto; }
  .help-lang-bar {
    display: flex; align-items: center; justify-content: flex-end; gap: 8px;
    font-size: 13px; color: #ddd; margin-bottom: 12px;
  }
  .help-lang-bar select {
    background: rgba(255,255,255,0.12); color: #fff; border: 1px solid #f39314 !important;
    border-radius: 6px; padding: 3px 6px; font-size: 13px; font-family: system-ui, sans-serif;
  }
  .help-lang-bar select option { color: #000; background: #fff; }
  .help-lang p { margin: 0 0 12px 0; font-size: 14px; line-height: 1.5; color: #ddd; }
  .help-lang p:last-child { margin-bottom: 0; }
  /* Fettgedruckte Passagen (Anwendervorlage Hilfe.docx) in derselben Farbe wie die
     Tasten-Buchstaben in der Klassen-Liste weiter unten (.help-list) - auf Anwenderwunsch. */
  .help-lang b { color: #ff9500; }
  .help-list {
    margin: -4px 0 12px 0; padding-left: 20px; font-size: 14px; line-height: 1.6; color: #ddd;
  }
  /* i-Button, Projektname und ScanPos-Ueberschrift sollen alle gleich hoch wirken - 44px,
     dieselbe Groesse wie im 3D-Fenster (Kompass/Open/Record/2D-Button/Ueberschrift, siehe
     proj.py reposition_compass_js), auf Anwenderwunsch (vorher 40px, dadurch leicht
     unterschiedlich zur 3D-Seite). */
  #projectTitle {
    color: #fff; background: rgba(255,255,255,0.12); padding: 0 12px; border-radius: 6px;
    height: 44px; box-sizing: border-box;
    font-size: 18px; font-weight: 400; white-space: nowrap; max-width: 40vw;
    text-overflow: ellipsis; overflow: hidden;
    /* Anwenderwunsch: derselbe oranger Rahmen wie bei allen anderen Buttons dieser Seite
       (siehe globale "button"-Regel in _VIEWER_CSS) - #projectTitle ist ein <select>, kein
       <button>, bekommt den Rahmen also nicht automatisch mit. */
    border: 1px solid #f39314; cursor: pointer; font-family: system-ui, sans-serif;
  }
  #projectTitle option { color: #000; background: #fff; font-size: 16px; }
  #projectInfoBtn {
    width: 46px; height: 44px; box-sizing: border-box; flex: 0 0 auto; border-radius: 8px;
    border: none; background: rgba(255,255,255,0.12); color: #ff9500; font-size: 17px;
    font-weight: 700; font-style: italic; font-family: Georgia, 'Times New Roman', serif;
    cursor: pointer;
  }
  #projectInfoBtn:hover { background: rgba(255,255,255,0.25); }
  #panoScanLabelText { line-height: 44px; }
  /* Notification-Tool (siehe loadInitialNotifFile/startNotifRecording/stopNotifRecording/
     openNotifFile/showNextNotifEntry): 3 gleich grosse Icon-Buttons rechts neben dem
     Projektnamen. <Projektname>.txt wird beim Erzeugen des Projekts angelegt und beim Laden
     der Seite automatisch eingelesen - Notizen erscheinen dadurch von selbst an der
     jeweiligen Scanposition (#notifAutoPanel), der Ordner-Knopf (Open) ist fuer den
     Normalfall nicht mehr noetig und dient nur noch als manueller Ausweg (z.B. um eine
     andere/aeltere Sicherungsdatei anzusehen). Record (Quadrat) schreibt (showSaveFilePicker)
     die Notizen in eine lokale Datei und faerbt sich waehrend einer aktiven Aufzeichnung rot
     (.active); Play (Dreieck) bleibt deaktiviert, solange keine Scanposition Notizen hat, und
     faerbt sich gruen (.active), waehrend man sich Scanposition fuer Scanposition mit Notizen
     durchklickt. */
  /* 44x44 (statt vormals 36x36) - dieselbe Groesse wie die Annotation-Recorder-Buttons der
     3D-Seite (siehe proj.py btnCss), auf Anwenderwunsch fuer ein einheitliches Erscheinungsbild
     der Recorder-Buttons auf beiden Seiten. */
  .notif-icon-btn {
    height: 44px; width: 44px; box-sizing: border-box; border-radius: 8px;
    background: rgba(255,255,255,0.12); color: #fff; font-size: 18px;
    display: flex; align-items: center; justify-content: center; padding: 0;
    cursor: pointer; line-height: 1;
  }
  .notif-icon-btn:hover { background: rgba(255,255,255,0.25); }
  .notif-icon-btn:disabled { opacity: 0.35; cursor: not-allowed; }
  .notif-icon-btn:disabled:hover { background: rgba(255,255,255,0.12); }
  .notif-icon-btn svg { width: 20px; height: 20px; }
  /* Als eigenes, exakt zentriertes Element (statt eines Unicode-Quadrat-Zeichens, dessen
     Position je nach Schriftart/Browser leicht verschoben wirken kann) - Hintergrundfarbe
     statt Textfarbe, damit sich die Farbe unabhaengig von Schriftglyphen-Eigenheiten aendert. */
  #notificationRecordBtn .notif-record-dot {
    width: 14px; height: 14px; background: #fff; border-radius: 1px;
  }
  #notificationRecordBtn.active .notif-record-dot { background: #ff3b30; }
  #notificationPlayBtn.active { color: #2ecc40; }
  /* Zweizeilig (Anwenderwunsch): 1. Zeile Autor, 2. Zeile Notiz - siehe startNotifInput. */
  #notifInputBox {
    position: fixed; z-index: 50; background: #fff; border: 2px solid #f39314;
    border-radius: 6px; padding: 6px; box-shadow: 0 2px 10px rgba(0,0,0,0.5);
    display: flex; flex-direction: column; gap: 4px;
  }
  #notifInputBox input {
    font-size: 14px; width: 240px; border: 1px solid #ccc; border-radius: 4px;
    padding: 4px 6px; font-family: system-ui, sans-serif;
  }
  /* Notiz-Marker an der Bildposition, an der die Notiz eingegeben wurde (siehe
     renderNotifAutoPanel/computePanoPct) - lebt wie die uebrigen Panorama-Marker in
     panoMarkersL/panoMarkers/panoMarkersR und schwenkt/zoomt dadurch korrekt mit dem
     Panorama mit. left/top werden als Bild-Prozent gesetzt (siehe JS); transform verankert
     die UNTERE Mitte der Sprechblase auf diesem Punkt (wie eine Kartennadel), statt die Notiz
     zentriert genau auf die annotierte Stelle zu legen und sie damit zu verdecken. */
  .notif-marker {
    position: absolute; transform: translate(-50%, calc(-100% - 8px));
    background: #fff8ec; border: 2px solid #f39314; border-radius: 6px; padding: 6px 10px;
    font-size: 14px; line-height: 1.4; color: #1c1c1c; box-shadow: 0 2px 10px rgba(0,0,0,0.5);
    font-family: system-ui, sans-serif; white-space: pre-wrap; max-width: 260px;
    cursor: default;
  }
  /* Auffangbecken fuer Notizen OHNE bekannte Bildposition (z.B. aus einer per Open geladenen
     aelteren Datei) - unten links im Panorama-Fenster, innerhalb von #rightPane damit die
     Position unabhaengig von der Trennlinien-Position stimmt. */
  #notifAutoPanel {
    position: absolute; z-index: 15; left: 10px; bottom: 10px; max-width: 320px;
    display: flex; flex-direction: column; gap: 4px;
  }
  .notif-auto-entry {
    background: #fff8ec; border: 2px solid #f39314; border-radius: 6px; padding: 6px 10px;
    font-size: 14px; line-height: 1.4; color: #1c1c1c; box-shadow: 0 2px 10px rgba(0,0,0,0.5);
    font-family: system-ui, sans-serif; white-space: pre-wrap;
  }
  #projectInfoOverlay {
    display: none; position: fixed; inset: 0; z-index: 40;
    background: rgba(0,0,0,0.6); align-items: center; justify-content: center;
  }
  #projectInfoOverlay.open { display: flex; }
  #projectInfoPanel {
    position: relative; background: #111; color: #fff; border: 1px solid #333;
    border-radius: 8px; padding: 28px 32px; min-width: 340px; max-width: 90vw;
    font-family: system-ui, sans-serif;
  }
  #projectInfoPanel h2 { margin: 0 0 16px 0; font-size: 20px; line-height: 24px; }
  #projectInfoHeader { margin: 0 0 16px 0; }
  #projectInfoLogo { display: block; height: 40px; width: auto; }
  /* Position/Groesse bewusst absolut statt im Flow: soll bis zur Grundlinie von "Project
     Info" (h2 direkt darunter) reichen, waehrend die Oberkante mit dem Logo auf gleicher
     Hoehe bleibt - das laesst sich nur mit position:absolute exakt treffen (ein Flow-Element
     kann bestenfalls bis zur Oberkante des naechsten Elements reichen, nie bis zu dessen
     Grundlinie). top/right decken sich mit dem Panel-Padding (28px/32px), die Hoehe ist
     rechnerisch auf die Grundlinie von h2 abgestimmt (dessen line-height ist dafuer bewusst
     explizit gesetzt, siehe #projectInfoPanel h2) - je nach Schriftart/Browser ggf. noch
     minimal nachzujustieren. */
  #projectInfoQr {
    display: none; position: absolute; top: 28px; right: 56px; width: 76px; height: 76px;
    background: #fff; padding: 4px; border-radius: 4px; box-sizing: border-box;
  }
  #projectInfoQr.visible { display: block; }
  #projectInfoClose {
    position: absolute; top: 6px; right: 10px; background: none; border: none;
    color: #fff; font-size: 26px; cursor: pointer; line-height: 1;
  }
  .project-info-row {
    display: flex; justify-content: space-between; gap: 24px;
    font-size: 16px; padding: 6px 0; border-bottom: 1px solid #262626;
  }
  .project-info-row:last-child { border-bottom: none; }
  .project-info-row span { color: #aaa; }
  .marker--current {
    width: 264px; height: 264px;
    margin-left: -132px; margin-top: -132px;
    z-index: 6;
  }
  .marker--current .marker-imu-dot { display: block; }
  /* Zoom-/KML-/Ebenen-Buttons der Project Map rechtsbuendig UNTER dem Info-Kopf (#mapHeader,
     jetzt ebenfalls rechtsbuendig/oben, siehe #mapHeader-CSS) gestapelt - beide sitzen jetzt
     auf derselben (rechten) Seite, da der "3D"-Button seinen alten Platz oben links (wo
     #mapHeader vorher stand) uebernommen hat (siehe .goto-3d-btn). 8px (Header-Rand) + 40px
     (Header-Hoehe: 28px-Logo + 6px Polsterung oben/unten) + 8px Abstand = 56px. .zoom-controls
     selbst (top:8px statt bottom:16px) nicht direkt ueberschreiben, das ist eine von
     _VIEWER_CSS gemeinsam genutzte Klasse (auch von der eigenstaendigen Panorama-Einzelseite,
     siehe build_panorama_page_html, wo die Buttons bewusst unten bleiben sollen) -
     stattdessen hier, in der nur fuer diese Split-Ansicht geltenden _SPLIT_CSS, spezifischer
     (per #leftPane) nur fuer die Project Map ueberschrieben. */
  #leftPane .zoom-controls { top: 56px; bottom: auto; }
  /* Anwenderwunsch (Mobiltelefon Querformat), zweistufig entstanden: zuerst wurde die
     Reflektor-Feinscan-Zeile (#panoTiePoints) komplett ausgeblendet, damit das Fotopanorama
     nicht durch die feste Reservierung nach unten gedraengt wird (siehe isMobileLandscapePano()
     im JS, passt rightViewport.style.top/right dazu an). Nachtrag: Foto- UND Reflectance-
     Panorama sollen stattdessen NEBENEINANDER dargestellt werden (Foto links, Reflectance
     rechts) - dann zoomen beide besser auf die Bildbreite. Diese Zeile wird dafuer statt eines
     oberen Streifens zur rechten Bildschirmhaelfte (die einzelnen Reflektor-Feinscan-
     Thumbnails selbst bleiben ausgeblendet, kein Platz dafuer - nur die praktisch immer
     vorhandene Reflectance/Scan-Vorschau #panoScanPreview wird gezeigt, per bestehendem
     syncPreviewToMainPano() ohnehin schon mit dem Fotopanorama synchron, unabhaengig vom
     Bildseitenverhaeltnis anhand der tatsaechlichen Containergroesse). Ausserdem: Datum/
     Wetter-Zeile ausblenden, Exposure/ISO-Schrift verkleinern, +/--Zoom-Buttons weglassen
     (Zwei-Finger-Geste reicht) und die Vor/Zurueck-Pfeile (die mit Abstand wichtigste
     Bedienung hier) vergroessern - alles Anwenderwunsch, um der ohnehin knappen
     Bildschirmhoehe/-breite so viel wie moeglich fuers eigentliche Panorama zu lassen. Nur
     echte Mobiltelefone im Querformat betroffen (Tablet-/Desktop-Fenster sind praktisch nie so
     niedrig). Bewusst als LETZTER Block ganz am Ende von _SPLIT_CSS (nach _VIEWER_CSS im
     fertigen Stylesheet ohnehin schon zuletzt eingebunden): fuer gleich spezifische Id-
     Selektoren (z.B. #rightViewport) entscheidet bei CSS sonst die Reihenfolge im Dokument,
     nicht ob eine Regel in einer @media-Bedingung steckt - eine fruehere Version dieses Blocks
     stand weiter oben im Stylesheet und wurde deshalb von den spaeteren, unbedingten
     Basis-Regeln (z.B. #rightViewport { bottom: PANOTOTALINFOHEIGHTpx; }) wieder ueberschrieben,
     obwohl die Media Query zutraf. */
  #panoSplitDivider { display: none; }
  /* Gemeinsamer "kompakter Mobil-Modus": alle vier Touchscreen-Ausrichtungen (Mobiltelefon
     Querformat - Foto/Reflectance nebeneinander, siehe Block weiter unten - Mobiltelefon
     Hochformat - Karte/Reflectance/Foto uebereinander, ebenfalls weiter unten - Tablet (iPad)
     Querformat, das die eigentliche Foto/Reflectance-Aufteilung des Desktops behaelt - UND
     Tablet (iPad) Hochformat, das wie beim Mobiltelefon-Hochformat gestapelt wird, siehe
     Anwenderwunsch) teilen sich dieselbe kompakte Info-/Buttonzeile unten
     (84px hoch, Datum/Wetter-Zeile ausgeblendet, +/--Zoom-Buttons weg,
     Vor/Zurueck-Pfeile so gross wie der QR-Code) - eine einzige, kombinierte Media Query statt
     vierer fast identischer Kopien. Die Tablet-Kriterien ((min-*:501px) and (max-*:1030px),
     also GROESSER als die jeweilige Telefon-Grenze, plus (pointer:coarse) - trennt
     zuverlaessig einen echten Touchscreen dieser Groesse von einem aehnlich grossen Desktop-
     Browserfenster mit Maus, das rein pixelmaessig sonst nicht unterscheidbar waere) decken
     die uebliche Hoehe/Breite von iPad-Quer-/Hochformat ab - bis 1030px, da das 12.9"/13"
     iPad Pro/Air mit 1024px (logische CSS-Pixel, nicht Geraete-Pixel) das breiteste/hoechste
     aktuelle iPad-Modell ist (kleinere Modelle wie iPad mini/iPad/iPad Air 11"/iPad Pro 11"
     liegen alle darunter, rund 744-834px). Ein zu knapper oberer Wert (fruehere Version: 900px)
     liess die Media Query auf genau diesem groessten Modell nie zutreffen - vom Anwender live
     am echten 12.9"-iPad bemerkt (Hochformat-Dreiteilung/grosse Pfeiltasten griffen nicht). Nur die
     eigentliche Aufteilung von Karte/Reflectance-Panorama/Fotopanorama (oben/unten vs.
     links/rechts vs. unveraendert wie am Desktop) unterscheidet sich zwischen den vier Faellen
     und steht deshalb in eigenen, spezifischen Bloecken danach (fuer Tablet-Querformat gibt es
     dort bewusst KEINEN eigenen Block - die Desktop-Aufteilung bleibt unveraendert bestehen;
     Tablet-Hochformat teilt sich dagegen den Block mit Mobiltelefon-Hochformat, siehe dort).
     Bewusst als LETZTE Bloecke ganz am Ende von _SPLIT_CSS (nach _VIEWER_CSS im fertigen
     Stylesheet ohnehin schon zuletzt eingebunden): fuer gleich spezifische Id-Selektoren (z.B.
     #rightViewport) entscheidet bei CSS sonst die Reihenfolge im Dokument, nicht ob eine Regel
     in einer @media-Bedingung steckt - eine fruehere Version stand weiter oben im Stylesheet
     und wurde deshalb von spaeteren, unbedingten Basis-Regeln wieder ueberschrieben, obwohl die
     Media Query zutraf. */
  @media (max-height: 500px) and (orientation: landscape), (max-width: 500px) and (orientation: portrait), (min-height: 501px) and (max-height: 1030px) and (orientation: landscape) and (pointer: coarse), (min-width: 501px) and (max-width: 1030px) and (orientation: portrait) and (pointer: coarse) {
    #panoInfo2 { display: none; }
    #panoInfo { bottom: 0; height: 84px; left: 0; right: 0; }
    /* Nav-/Zoom-Buttons als reine Positionierungshuelle ueber die gesamte Info-Zeile (statt
       einer eigenen linksbuendigen Gruppe) - so lassen sich navPrev/navNext unabhaengig
       voneinander links bzw. rechts (neben dem QR-Code) platzieren, siehe unten. */
    #panoButtonsRow {
      left: 0; right: 0; top: 0; bottom: 0; padding: 0; pointer-events: none;
    }
    #panoZoomIn, #panoZoomOut { display: none; }
    /* Vor/Zurueck: mit Abstand wichtigste Bedienung hier (Anwenderwunsch) - so gross wie der
       QR-Code (siehe #panoInfoQr weiter unten, dieselbe Hoehe/Breite: 84px
       minus 2x6px Rand = 72px), damit sie sich auf einem Touchscreen bequem treffen lassen.
       Linker Pfeil bleibt an seinem bisherigen Platz (nur groesser), rechter Pfeil wandert an
       den rechten Rand, rechts neben den QR-Code (der dafuer entsprechend Platz laesst). */
    /* #panoButtonsRow vorangestellt (Id+Id statt nur Id) - schlaegt sonst die spezifischere
       Basisregel "#panoButtonsRow button { width:40px; height:40px; ... }" weiter oben, die
       laut CSS-Kaskade trotz spaeterer Position im Stylesheet gewinnen wuerde (Spezifitaet
       zaehlt vor Reihenfolge) - derselbe Fallstrick wie zuvor schon bei #rightViewport
       (siehe Kommentar oben bei @media), nur diesmal durch hoehere statt gleiche
       Spezifitaet der Basisregel verursacht. */
    #panoButtonsRow #navPrev, #panoButtonsRow #navNext {
      position: absolute; bottom: 6px; width: 72px; height: 72px; font-size: 32px;
      pointer-events: auto;
    }
    #panoButtonsRow #navPrev { left: 12px; }
    #panoButtonsRow #navNext { right: 12px; }
    #panoButtonsRow #panoZoomReset {
      position: absolute; left: 92px; bottom: 18px; width: 36px; height: 36px; font-size: 16px;
      pointer-events: auto;
    }
    /* Exposure/ISO wandert in den bisher ungenutzten Bereich oberhalb des Histogramms
       (Anwenderwunsch) statt links davon zu stehen - dadurch bleibt links genug Platz fuer den
       jetzt viel groesseren navPrev-Button. Beide (Exif-Zeile und Histogramm) im selben
       mittleren Bereich zwischen den Buttons links und QR/navNext rechts. Dieselben festen
       Werte (140/172px) auch im schmaleren Hochformat verwendet - dort bleibt dadurch
       weniger mittlerer Platz fuer den Text (der bei Bedarf abgeschnitten wird, siehe
       white-space:nowrap/overflow:hidden), aber Button-/QR-Groessen und -Position bleiben so
       in beiden Ausrichtungen identisch. */
    #panoInfoExif {
      position: absolute; left: 140px; right: 172px; top: 2px; height: 18px;
      font-size: 11px; line-height: 18px; padding: 0 6px; white-space: nowrap; overflow: hidden;
    }
    #panoInfoHist { position: absolute; left: 140px; right: 172px; top: 22px; bottom: 4px; padding: 0; }
    #panoInfoQr {
      position: absolute; right: 92px; top: 6px; bottom: 6px; padding: 0;
    }
    #mapZoomIn, #mapZoomOut { display: none; }
    /* Anwenderwunsch: Notification-Recorder-Icons (Datei oeffnen/aufnehmen/abspielen, siehe
       #panoHeaderLeft) in beiden Mobil-Ausrichtungen ausblenden - schafft Platz in der ohnehin
       engen Kopfzeile (dort kollidierte der Scanpositions-Name zuvor mit den Icons). Die
       Funktionen bleiben auf dem Desktop unveraendert erreichbar. */
    #notificationOpenBtn, #notificationRecordBtn, #notificationPlayBtn { display: none; }
    /* Anwenderwunsch: langes Antippen des Reflectance-Bilds soll NICHT mehr das native
       Teilen/Foto-sichern-Menu des Browsers oeffnen (stattdessen soll das beim QR-Code
       erscheinen, siehe #panoInfoQr/#panoInfoQrImg weiter unten sowie den JS-
       contextmenu-Handler) - -webkit-touch-callout:none ist der iOS-Safari-Weg dafuer; fuer
       Android siehe das JS 'contextmenu'-preventDefault auf denselben Elementen. */
    #panoScanPreview img { -webkit-touch-callout: none; }
    /* Gegenstueck: der Seiten-QR-Code wird jetzt als echtes <img> (statt nur als <canvas>,
       das dieses native Menu auf den meisten mobilen Browsern gar nicht erst ausloest)
       dargestellt, damit genau dort das Teilen/Foto-sichern-Menu erscheint. */
    #panoInfoQr canvas { display: none; }
    #panoInfoQr img {
      height: 100%; width: auto; display: block; border-radius: 4px; background: #fff;
    }
  }
  @media (max-height: 500px) and (orientation: landscape) {
    #panoTiePoints.has-images {
      top: 64px; left: 50%; right: 0; bottom: 84px; height: auto;
      border-bottom: none; border-left: none; padding: 0;
    }
    #panoTiePointImages { display: none; }
    #panoScanPreview { flex: 1 1 auto; width: auto; height: 100%; }
    #rightViewport { bottom: 84px; }
    /* Dicke orangene, ziehbare Trennlinie zwischen Foto- und Reflectance-Panorama
       (Anwenderwunsch) - Position (left) wird per JS gesetzt (siehe applyPanoSplit()),
       derselbe Aufbau/dieselbe Ziehlogik wie die bestehende #divider zwischen Karte und
       Panorama, nur breiter und in RIEGL-Orange statt Grau, damit sie auf einem Touchscreen
       gut zu treffen ist. */
    #panoSplitDivider {
      /* display bleibt Sache von updatePanoSplitLayout() (JS) - nur sichtbar, wenn es
         tatsaechlich etwas zu teilen gibt (Reflectance-Vorschau vorhanden). */
      position: absolute; top: 64px; bottom: 84px;
      width: 20px; margin-left: -10px; background: #f39314; z-index: 6; cursor: col-resize;
      touch-action: none;
    }
    #panoSplitDivider:hover, #panoSplitDivider:active { background: #ff9500; }
  }
  /* Mobiltelefon UND Tablet (iPad) Hochformat (Anwenderwunsch, fuer Tablet nachtraeglich
     ergaenzt): Karte oben, Reflectance-Panorama in der Mitte, Fotopanorama unten, jede Ansicht
     ueber die volle Bildschirmbreite - im Gegensatz zum Querformat oben (nebeneinander) hier
     UEBEREINANDER gestapelt. #leftPane/#rightPane selbst (links/rechts-Aufteilung samt
     Ziehlinie #divider) werden dafuer NICHT hier per CSS umgestellt, sondern per JS in
     applySplit() (siehe isMobilePortraitPano()/isTabletPortraitPano()) - beide werden dort
     immer schon per Inline-Style positioniert (auch im Normalfall, wegen der ziehbaren
     Trennlinie), eine reine CSS-Regel wuerde von diesem spaeteren Inline-Style ueberschrieben
     und nie zum Zug kommen. Hier nur die Aufteilung INNERHALB von #rightPane (Reflectance
     oben/Foto unten, je 50% der nach #panoScanLabel verbleibenden Hoehe von #rightPane -
     ueber top+bottom statt height, damit kein calc() mit gemischten %/px noetig ist). */
  @media (max-width: 500px) and (orientation: portrait), (min-width: 501px) and (max-width: 1030px) and (orientation: portrait) and (pointer: coarse) {
    #divider { display: none; }
    #panoTiePoints.has-images {
      top: 64px; left: 0; right: 0; bottom: 50%; height: auto;
      border-bottom: none; padding: 0;
    }
    #panoTiePointImages { display: none; }
    #panoScanPreview { flex: 1 1 auto; width: 100%; height: 100%; }
    #rightViewport { top: 50%; bottom: 84px; left: 0; right: 0; }
  }

  #appModalOverlay {
    display: none; position: fixed; inset: 0; z-index: 60;
    background: rgba(0,0,0,0.6); align-items: center; justify-content: center;
  }
  #appModalOverlay.open { display: flex; }
  #appModalPanel {
    position: relative; background: #111; color: #fff; border: 1px solid #333;
    border-radius: 8px; padding: 28px 32px; min-width: 340px; max-width: 480px; width: 90vw;
    box-sizing: border-box; font-family: system-ui, sans-serif;
  }
  #appModalPanel h3 { margin: 0 0 16px 0; font-size: 18px; line-height: 24px; font-weight: 600; }
  #appModalPanel p { margin: 0 0 16px 0; font-size: 15px; line-height: 1.5; color: #ddd; }
  #appModalPanel p:last-child { margin-bottom: 0; }
  #appModalPanel ul { margin: 0; padding-left: 22px; font-size: 15px; line-height: 1.6; color: #ddd; }
  #appModalPanel ul:last-child { margin-bottom: 0; }
  #appModalInput {
    width: 100%; box-sizing: border-box; padding: 8px 10px; font-size: 15px;
    border-radius: 6px; border: 1px solid #333; background: #1c1c1c; color: #fff; margin-bottom: 6px;
  }
  #appModalError { color: #ff6b6b; font-size: 13px; margin: 0 0 12px 0; min-height: 16px; }
  #appModalButtons { display: flex; justify-content: flex-end; gap: 10px; }
  #appModalButtons button {
    padding: 8px 18px; border-radius: 6px; border: none; background: rgba(255,255,255,0.12);
    color: #fff; font-size: 14px; cursor: pointer;
  }
  #appModalButtons button:hover { background: rgba(255,255,255,0.25); }
  #appModalButtons button.primary { background: #ff9500; color: #111; font-weight: 600; }
  #appModalButtons button.primary:hover { background: #ffaa33; }
  /* Design wie #projectInfoClose (i-Seite) - dieselbe Position/Optik fuer alle Modal-
     Schliessen-Buttons (Start-Hinweis, Hilfe). */
  #appModalNoticeClose, #appModalHelpClose, #appModalImuNaClose {
    position: absolute; top: 6px; right: 10px; background: none; border: none;
    color: #fff; font-size: 26px; cursor: pointer; line-height: 1;
  }
