403Webshell
Server IP : 202.61.199.114  /  Your IP : 216.73.217.139
Web Server : nginx/1.22.1
System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64
User : web20 ( 1018)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : ON
Directory :  /tmp/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /tmp//ci_ab.html
<!DOCTYPE html><html lang="de"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover"><meta name="robots" content="noindex,nofollow"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><meta name="theme-color" content="#0d2c44"><link rel="manifest" href="https://seaside.pacim.de/manifest.php?t=63755ecedbb6c1c962cf0dd2"><link rel="apple-touch-icon" href="https://seaside.pacim.de/assets/webapp/icon-180.png"><meta name="apple-mobile-web-app-title" content="Seaside Parking"><title>Check-in · FB - TK 1507</title><style>@font-face{font-family:"EuroPlate";src:url("https://seaside.pacim.de/assets/fonts/EuroPlate.ttf") format("truetype");font-display:swap;}
    :root{--navy:#0d2c44;--navy2:#11436b;--blue:#1b6ca8;--green:#2fb344;--red:#d63939;--gold:#f3b53f;--ink:#16384f;--muted:#5b7488;--line:#e6eef4;}
    *{box-sizing:border-box;margin:0;padding:0;}
    html{-webkit-text-size-adjust:100%;text-size-adjust:100%;height:100%;}
    /* App-Shell: volle Viewporthöhe, kein Body-Scroll – gescrollt wird der Inhaltsbereich (Pane). */
    body{font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;background:#fff;color:var(--ink);height:100vh;height:100dvh;display:flex;flex-direction:column;align-items:center;padding:0;overflow:hidden;touch-action:manipulation;}
    /* iOS Standalone: Karte nicht unter Dynamic Island / Statusleiste (nur direkt geöffnet, nicht im Overlay). */
    /* Randlos: Safe-Area oben übernimmt der Karten-Header (.hd) selbst; seitlich nur Notch-Schutz (Querformat). */
    body.ci-sa{padding-left:env(safe-area-inset-left,0px);padding-right:env(safe-area-inset-right,0px);}
    .d-none{display:none!important;}
    .card{width:100%;max-width:460px;background:#fff;overflow:hidden;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;}
    .card>.hd{flex:0 0 auto;}
    .hd{position:relative;background:linear-gradient(135deg,var(--navy) 0%,var(--navy2) 65%,var(--blue) 130%);color:#fff;padding:20px 22px 18px;}
    /* Standalone (vom Home-Bildschirm): Navy-Header füllt randlos bis oben, Inhalt unter die Dynamic Island. */
    body.ci-sa .hd{padding-top:calc(20px + env(safe-area-inset-top,0px));}
    .hd .back{position:absolute;top:14px;right:16px;width:38px;height:38px;display:flex;align-items:center;justify-content:center;border-radius:50%;background:rgba(255,255,255,.14);color:#fff;text-decoration:none;-webkit-tap-highlight-color:transparent;transition:background .12s ease,transform .08s ease;}
    .hd .back:active{transform:scale(.92);background:rgba(255,255,255,.24);}
    .hd .back svg{width:22px;height:22px;}
    body.ci-sa .hd .back{top:calc(14px + env(safe-area-inset-top,0px));right:calc(16px + env(safe-area-inset-right,0px));}
    .hd .k{font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;opacity:.8;}
    .hd .t{font-size:22px;font-weight:800;margin-top:3px;}
    .hd .no{font-size:13px;opacity:.85;margin-top:2px;}
    .bd{padding:16px 22px 4px;}
    .plate-wrap{position:relative;margin:2px 0 14px;}
    .plate{border:2px solid #111;border-radius:8px;text-align:center;font-family:"EuroPlate",ui-monospace,monospace;font-size:30px;font-weight:700;letter-spacing:1px;padding:9px 6px;color:#111;cursor:text;-webkit-text-stroke:.6px currentColor;}
    .plate.editing{outline:2px solid var(--blue);outline-offset:1px;padding-right:64px;text-align:left;padding-left:14px;}
    .plate-save{position:absolute;right:6px;top:6px;bottom:6px;width:50px;border:0;border-radius:6px;background:var(--green);color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;}
    .plate-save svg{width:22px;height:22px;}
    /* Info-Button (Kennzeichen-Herkunft) als Badge an der Plaketten-Ecke */
    .plate-info{position:absolute;top:-10px;right:-10px;width:30px;height:30px;border-radius:50%;background:#fff;color:var(--blue);
        border:1.6px solid var(--blue);box-shadow:0 2px 7px rgba(13,44,68,.22);display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:3;-webkit-tap-highlight-color:transparent;}
    .plate-info svg{width:18px;height:18px;}
    .plate-info:active{transform:scale(.92);}
    .plate.editing ~ .plate-info{display:none;}
    /* Kennzeichen-Herkunft-Modal */
    .pl-head{display:flex;align-items:center;gap:14px;margin-bottom:14px;}
    .pl-code{flex:0 0 auto;font-family:"EuroPlate",ui-monospace,monospace;font-weight:700;font-size:26px;letter-spacing:1px;
        border:2px solid #111;border-radius:7px;padding:6px 12px;color:#111;-webkit-text-stroke:.5px currentColor;background:#fff;}
    .pl-region{font-size:18px;font-weight:800;color:var(--navy);line-height:1.2;}
    .pl-sub{font-size:13px;color:var(--muted);margin-top:2px;}
    .pl-rows{border-top:1px solid var(--line);margin-bottom:14px;}
    .pl-row{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-bottom:1px solid var(--line);font-size:14.5px;}
    .pl-row span{color:var(--muted);} .pl-row b{color:var(--ink);text-align:right;}
    .pl-alt{background:#fff8e6;border:1px solid #f3e3b0;border-radius:10px;padding:9px 12px;font-size:13px;color:#8a6400;margin-bottom:14px;}
    .pl-alt span{font-weight:800;}
    .pl-mapwrap{background:#eef3f7;border-radius:12px;padding:10px;display:flex;justify-content:center;}
    .pl-map{width:auto;max-width:100%;max-height:46vh;height:auto;display:block;}
    .pl-reg{fill:#fff;stroke:#9fb3c4;stroke-width:.8;}
    .pl-reg.active{fill:#1b6ca8;stroke:#0d2c44;stroke-width:1;}
    .pl-mark-halo{fill:rgba(214,57,57,.25);}
    .pl-pin{fill:#d63939;stroke:#fff;stroke-width:1.2;}
    .pl-pin-dot{fill:#fff;}
    .pl-empty{color:var(--muted);text-align:center;padding:24px 6px;font-size:14.5px;}
    .muted{color:var(--muted);font-weight:400;}
    .row{display:flex;justify-content:space-between;gap:12px;padding:9px 0;border-top:1px solid var(--line);font-size:14.5px;}
    .row:first-of-type{border-top:0;}
    .row .l{color:var(--muted);} .row .v{font-weight:600;text-align:right;}
    .badges{display:flex;gap:8px;margin:14px 0 2px;}
    .badge{flex:1;border-radius:12px;padding:11px;text-align:center;font-weight:700;font-size:14px;}
    .b-open{background:rgba(214,57,57,.10);color:var(--red);} .b-ok{background:rgba(47,179,68,.12);color:#1d7a33;} .b-warn{background:rgba(243,181,63,.16);color:#8a6400;}
    /* Status-Badge im Header (ganz unten rechts, flush in der Ecke) */
    .hstat{position:absolute;right:0;bottom:0;font-size:12.5px;font-weight:700;padding:6px 14px;border-radius:8px 0 0 0;white-space:nowrap;}
    .hstat.s-blue{background:#2f86d6;color:#fff;} .hstat.s-orange{background:#f59f00;color:#3a2c00;}
    .hstat.s-green{background:#2fb344;color:#fff;} .hstat.s-red{background:#d63939;color:#fff;}
    .btn.btn-out{background:#eef4f9;color:var(--navy);}
    .btn-cancel{margin-top:22px;background:#fff;color:var(--navy);border:0;border-radius:12px;padding:15px 28px;font-size:16px;font-weight:700;cursor:pointer;}
    .done-skip{margin-top:14px;font-size:12.5px;opacity:.7;}
    .sec{padding:14px 22px;border-top:1px solid var(--line);}
    .sec-h{font-weight:700;font-size:15px;color:var(--navy);margin-bottom:10px;}
    .fld-l{display:block;font-size:12px;font-weight:700;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;margin:8px 0 5px;}
    .sel{width:100%;padding:12px;border:1px solid var(--line);border-radius:10px;font-size:15px;background:#fff;color:var(--ink);}
    .amount{margin:12px 0;font-size:15px;}
    .amount strong{font-size:22px;color:var(--navy);}
    .pay-types{display:flex;gap:8px;}
    .pt{flex:1;padding:13px 6px;border:2px solid var(--line);background:#fff;border-radius:12px;font-size:14px;font-weight:700;color:var(--ink);cursor:pointer;}
    .pt.on{border-color:var(--blue);background:rgba(27,108,168,.08);color:var(--blue);}
    .btn{display:block;width:100%;border:0;border-radius:12px;padding:15px;font-size:16px;font-weight:700;text-align:center;cursor:pointer;margin-top:12px;}
    .btn-pay{background:var(--green);color:#fff;} .btn-primary{background:var(--blue);color:#fff;} .btn-light{background:#eef4f9;color:var(--navy);}
    .btn-warn{background:#f59f00;color:#fff;} .btn-checkin{background:var(--green);color:#fff;} .btn-danger{background:var(--red);color:#fff;}
    .btn[disabled]{background:#e7eef4;color:#9bacba;cursor:not-allowed;}
    .lnk{background:none;border:0;color:#1d7a33;font-weight:700;text-decoration:underline;cursor:pointer;font-size:13.5px;padding:0;margin-left:4px;}
    .modal{width:100%;max-width:420px;background:#fff;border-radius:0;overflow:hidden;box-shadow:0 20px 60px rgba(0,0,0,.35);}
    .modal-h{display:flex;align-items:center;justify-content:space-between;background:var(--navy);color:#fff;padding:15px 18px;font-size:16px;font-weight:800;}
    .modal-x{background:none;border:0;color:#cfe2f2;font-size:26px;line-height:1;cursor:pointer;padding:0 2px;}
    .modal-b{padding:16px 18px 20px;}
    .hint{font-size:12px;color:var(--muted);text-align:center;margin-top:8px;}
    .modal-err{background:rgba(214,57,57,.10);color:var(--red);border-radius:10px;padding:11px 13px;font-size:13.5px;font-weight:600;margin-top:12px;}
    .note{border-radius:10px;padding:12px 14px;font-size:14px;}
    .note.ok{background:rgba(47,179,68,.10);color:#1d7a33;} .note.warn{background:rgba(243,181,63,.16);color:#8a6400;}
    .note.info{background:rgba(27,108,168,.10);color:#155a8a;}
    .status{padding:6px 22px 16px;font-size:13.5px;font-weight:600;text-align:center;}
    .status.ok{color:#1d7a33;} .status.err{color:var(--red);}
    /* ---- Footer-Tab-Navigation + Panes (App-Shell) ---- */
    /* Slider füllt den Platz zwischen Header und Tab-Footer; jede Pane scrollt vertikal für sich. */
    .slider{position:relative;overflow:hidden;touch-action:pan-y;flex:1 1 auto;min-height:0;}
    .track{display:flex;align-items:stretch;width:100%;height:100%;transition:transform .28s cubic-bezier(.22,.61,.36,1);}
    .track.dragging{transition:none;}
    .pane{flex:0 0 100%;width:100%;min-width:0;height:100%;overflow-y:auto;-webkit-overflow-scrolling:touch;touch-action:pan-y;}
    @media (prefers-reduced-motion: reduce){ .track{transition:none;} }
    .tabbar{flex:0 0 auto;width:100%;max-width:460px;display:flex;
            background:#fff;border-top:1px solid var(--line);box-shadow:0 -2px 14px rgba(13,44,68,.10);
            padding-bottom:env(safe-area-inset-bottom,0px);}
    .tabbar .tab{flex:1;border:0;background:none;cursor:pointer;-webkit-tap-highlight-color:transparent;font:inherit;
            display:flex;flex-direction:column;align-items:center;gap:3px;padding:9px 4px 8px;position:relative;
            font-size:11px;font-weight:700;color:var(--muted);transition:color .14s ease;}
    .tabbar .tab svg{width:23px;height:23px;}
    .tabbar .tab.active{color:var(--blue);}
    .tabbar .tab.active::before{content:"";position:absolute;top:0;left:22%;right:22%;height:3px;border-radius:0 0 3px 3px;background:var(--blue);}
    .tabbar .tab:active{background:rgba(27,108,168,.06);}
    .tb-badge{position:absolute;top:5px;left:calc(50% + 7px);min-width:16px;height:16px;padding:0 4px;border-radius:9px;
            background:var(--blue);color:#fff;font-size:10px;font-weight:800;line-height:16px;text-align:center;}
    /* ---- Notizen ---- */
    .nt-hint{margin:14px 22px 0;background:#fff8e6;border:1px solid #f3e3b0;border-radius:12px;padding:12px 14px;}
    .nt-hint-h{display:flex;align-items:center;gap:7px;font-weight:800;font-size:13.5px;color:#8a6400;margin-bottom:6px;}
    .nt-hint-h svg{width:18px;height:18px;flex:0 0 auto;}
    .nt-hint-b{font-size:14px;line-height:1.45;color:var(--ink);word-break:break-word;}
    .nt-hint-reply{margin-top:10px;padding-top:10px;border-top:1px dashed #e6d28f;}
    .nt-hint-rh{font-size:12px;color:#8a6400;font-weight:700;cursor:pointer;list-style:none;display:flex;align-items:center;gap:6px;}
    .nt-hint-reply summary::-webkit-details-marker{display:none;}
    .nt-hint-rh::before{content:"\25B8";display:inline-block;transition:transform .15s ease;}
    .nt-hint-reply[open] .nt-hint-rh::before{transform:rotate(90deg);}
    .nt-hint-rh::after{content:" – anzeigen";font-weight:400;opacity:.8;}
    .nt-hint-reply[open] .nt-hint-rh::after{content:" – ausblenden";}
    .nt-hint-reply .nt-hint-b{margin-top:6px;}
    .nt-block{padding:14px 22px;}
    .nt-title{display:flex;align-items:center;gap:7px;}
    .nt-title svg{width:18px;height:18px;flex:0 0 auto;}
    .nt-add{margin:4px 0 16px;}
    .nt-add textarea{width:100%;border:1px solid var(--line);border-radius:10px;padding:11px 12px;font:inherit;font-size:14.5px;resize:vertical;background:#f6f9fc;}
    .nt-add textarea:focus{outline:2px solid var(--blue);outline-offset:1px;background:#fff;}
    .nt-add .btn{margin-top:10px;}
    .nt-list{display:flex;flex-direction:column;gap:10px;}
    .nt-item{background:#f6f9fc;border:1px solid var(--line);border-radius:12px;padding:11px 13px;}
    .nt-item-text{font-size:14.5px;line-height:1.45;color:var(--ink);word-break:break-word;}
    .nt-item-meta{font-size:11.5px;color:var(--muted);margin-top:7px;}
    .nt-item-act{display:flex;gap:16px;margin-top:9px;}
    .nt-a{border:0;background:none;cursor:pointer;font:inherit;font-size:13px;font-weight:700;color:var(--blue);padding:2px 0;}
    .nt-a.nt-del{color:var(--red);}
    .nt-eta{width:100%;border:1px solid var(--blue);border-radius:10px;padding:10px 12px;font:inherit;font-size:14.5px;resize:vertical;}
    .nt-eactions{display:flex;justify-content:flex-end;gap:18px;margin-top:8px;}
    .nt-empty{color:var(--muted);font-size:14px;text-align:center;padding:18px 0;}
    .nt-foot{color:var(--muted);font-size:12.5px;margin-top:14px;text-align:center;}
    /* Hervorheben-Option + Badge */
    .nt-hl-opt{display:flex;align-items:center;gap:8px;margin:10px 0 0;font-size:13.5px;color:var(--ink);cursor:pointer;}
    .nt-hl-opt input{width:18px;height:18px;flex:0 0 auto;}
    .nt-item.nt-hl{border-color:#f3c34f;background:#fff8e6;}
    .nt-hlbadge{display:inline-block;background:#f3b53f;color:#3a2c00;font-size:11px;font-weight:800;border-radius:6px;padding:2px 8px;margin-bottom:7px;}
    /* Endlos-Lauftext (hervorgehobene Notizen) */
    .ci-marquee{display:flex;align-items:center;gap:8px;background:linear-gradient(90deg,#f3b53f,#ffd87a);color:#3a2c00;padding:8px 12px;font-weight:700;font-size:14px;}
    .ci-marquee .ci-mq-ic{width:18px;height:18px;flex:0 0 auto;}
    .ci-mq-win{flex:1 1 auto;overflow:hidden;}
    .ci-mq-track{display:inline-flex;white-space:nowrap;will-change:transform;animation:ci-mq 18s linear infinite;}
    .ci-mq-seg{padding:0 1.6em;}
    @keyframes ci-mq{from{transform:translateX(0);}to{transform:translateX(-50%);}}
    @media (prefers-reduced-motion: reduce){ .ci-mq-track{animation:none;} }
    .foot{margin-top:16px;font-size:12px;color:var(--muted);text-align:center;}
    .overlay{position:fixed;inset:0;background:rgba(13,44,68,.92);display:flex;align-items:center;justify-content:center;z-index:50;}
    .done-box{text-align:center;color:#fff;padding:30px;}
    .check{width:92px;height:92px;border-radius:50%;background:var(--green);color:#fff;margin:0 auto 18px;display:flex;align-items:center;justify-content:center;}
    .check svg{width:50px;height:50px;}
    /* Check-out-Countdown: deutlich anders (rot/orange) als der Check-in-Countdown (navy/grün) */
    .overlay.out{background:rgba(122,28,28,.94);}
    .overlay.out .check{background:#e8590c;}
    .done-t{font-size:24px;font-weight:800;} .done-x{font-size:15px;opacity:.85;margin-top:8px;}
    .err{max-width:440px;background:#fff;border-radius:18px;padding:34px 26px;text-align:center;box-shadow:0 14px 40px rgba(13,44,68,.16);margin:60px auto;}
    .err h1{font-size:40px;color:var(--navy);} .err p{color:var(--muted);margin-top:8px;}
    /* ---- Fahrzeugfotos ---- */
    .ph-head{display:flex;align-items:center;justify-content:space-between;gap:10px;}
    .ph-title{display:flex;align-items:center;gap:7px;margin:0;} .ph-title svg{width:18px;height:18px;}
    .ph-count{background:var(--blue);color:#fff;border-radius:999px;font-size:12px;font-weight:800;padding:1px 8px;min-width:20px;text-align:center;}
    .ph-count.zero{display:none;}
    .ph-add{display:inline-flex;align-items:center;gap:5px;background:var(--blue);color:#fff;border:0;border-radius:10px;padding:9px 14px;font-size:14px;font-weight:700;cursor:pointer;}
    .ph-add svg{width:16px;height:16px;}
    .ph-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:6px;margin-top:12px;}
    .ph-thumb{position:relative;aspect-ratio:1/1;border-radius:10px;overflow:hidden;background:#e6eef4;cursor:pointer;}
    .ph-thumb img{width:100%;height:100%;object-fit:cover;display:block;}
    .ph-mbadge{position:absolute;left:5px;top:5px;display:inline-flex;align-items:center;gap:1px;background:rgba(214,57,57,.78);color:#fff;border-radius:999px;font-size:11px;font-weight:800;padding:1px 6px 1px 4px;}
    .ph-mbadge svg{width:12px;height:12px;}
    .ph-ndot{position:absolute;right:5px;bottom:5px;width:18px;height:18px;border-radius:50%;background:rgba(13,44,68,.82);display:flex;align-items:center;justify-content:center;}
    .ph-ndot svg{width:11px;height:11px;stroke:#fff;}
    .ph-empty{color:var(--muted);font-size:13.5px;margin-top:10px;}
    .ph-upmodal{max-width:460px;}
    .ph-pick{display:flex;gap:10px;}
    .ph-pickbtn{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;border:1.5px dashed var(--line);border-radius:12px;padding:18px 8px;cursor:pointer;color:var(--navy);font-weight:700;font-size:14px;}
    .ph-pickbtn svg{width:30px;height:30px;color:var(--blue);} .ph-pickbtn:active{background:#f2f7fb;}
    .ph-tiles{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px;}
    .ph-tile{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:#fff;}
    .ph-tibox{position:relative;aspect-ratio:4/3;background:#e6eef4;}
    .ph-tibox img{width:100%;height:100%;object-fit:cover;display:block;}
    .ph-rm{position:absolute;top:4px;right:4px;width:26px;height:26px;border:0;border-radius:50%;background:rgba(13,44,68,.85);color:#fff;font-size:18px;line-height:24px;cursor:pointer;}
    .ph-st{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12.5px;font-weight:700;background:rgba(13,44,68,.55);}
    .ph-bar{position:absolute;left:0;bottom:0;height:4px;background:var(--green);width:0;transition:width .15s;}
    .ph-tnote{width:100%;border:0;border-top:1px solid var(--line);padding:8px 9px;font-size:13px;background:#fff;}
    .ph-tile.done .ph-tibox{outline:2px solid var(--green);outline-offset:-2px;}
    .ph-tile.err .ph-tibox{outline:2px solid var(--red);outline-offset:-2px;}
    .lb{background:rgba(8,20,30,.96);}
    .lb-bar{position:absolute;top:0;left:0;right:0;display:flex;align-items:center;justify-content:space-between;padding:10px 12px 26px;z-index:4;color:#fff;background:linear-gradient(180deg,rgba(0,0,0,.62),rgba(0,0,0,0));}
    .lb-pos{font-size:14px;font-weight:800;text-shadow:0 1px 3px rgba(0,0,0,.7);} .lb-actions{display:flex;gap:8px;}
    .lb-btn{background:rgba(0,0,0,.62);color:#fff;border:1px solid rgba(255,255,255,.28);border-radius:10px;min-width:44px;height:44px;font-size:22px;line-height:1;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;box-shadow:0 2px 8px rgba(0,0,0,.4);}
    .lb-btn.active{background:#1b6ca8;border-color:#1b6ca8;}
    .lb-btn svg{width:20px;height:20px;}
    .lb-stage{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;overflow:hidden;touch-action:none;}
    .lb-stage img{max-width:100%;max-height:100%;user-select:none;-webkit-user-drag:none;will-change:transform;}
    .ci-lb-spin{position:absolute;top:50%;left:50%;width:46px;height:46px;margin:-23px 0 0 -23px;border-radius:50%;border:4px solid rgba(255,255,255,.25);border-top-color:#fff;pointer-events:none;z-index:4;opacity:0;transition:opacity .12s ease;}
    .ci-lb-spin.on{opacity:1;animation:ci-lb-spin .8s linear infinite;}
    @keyframes ci-lb-spin{to{transform:rotate(360deg);}}
    @media (prefers-reduced-motion: reduce){ .ci-lb-spin.on{animation:none;} }
    .lb-nav{position:absolute;top:50%;transform:translateY(-50%);background:rgba(0,0,0,.5);color:#fff;border:1px solid rgba(255,255,255,.2);width:44px;height:66px;font-size:30px;cursor:pointer;z-index:4;}
    .lb-prev{left:0;border-radius:0 12px 12px 0;} .lb-next{right:0;border-radius:12px 0 0 12px;}
    .lb-info{position:absolute;left:0;right:0;bottom:0;background:linear-gradient(transparent,rgba(0,0,0,.78));color:#fff;padding:34px 16px 16px;z-index:4;font-size:13px;}
    .lb-info .lb-note{font-size:15px;font-weight:700;margin-bottom:3px;} .lb-info .lb-meta{opacity:.85;line-height:1.5;}
    .lb-info .lb-edit{color:#9fd0ff;text-decoration:underline;background:none;border:0;cursor:pointer;font-size:13px;padding:0;margin-top:5px;}
    /* Befund-Marker (mobil) */
    .ci-mlayer{position:absolute;pointer-events:none;z-index:3;transform-origin:50% 50%;}
    .ci-mdot{position:absolute;transform:translate(-50%,-50%) scale(var(--mInv,1));width:26px;height:26px;border-radius:50%;background:rgba(214,57,57,.92);color:#fff;border:2px solid #fff;font-size:12px;font-weight:800;cursor:pointer;pointer-events:auto;box-shadow:0 2px 8px rgba(0,0,0,.55);display:flex;align-items:center;justify-content:center;}
    .ci-mprev{position:absolute;z-index:7;width:210px;background:#0a141e;border:1px solid rgba(255,255,255,.22);border-radius:10px;overflow:hidden;box-shadow:0 10px 30px rgba(0,0,0,.6);display:none;}
    .ci-mprev.on{display:block;}
    .ci-mprev-img{width:100%;height:140px;background-repeat:no-repeat;background-color:#000;border-bottom:1px solid rgba(255,255,255,.12);}
    .ci-mprev-b{padding:8px 10px;color:#fff;}
    .ci-mprev-z{font-size:11px;font-weight:700;color:#9fd0ff;}
    .ci-mprev-note{font-size:13px;font-weight:600;margin:3px 0;word-break:break-word;} .ci-mprev-empty{opacity:.55;font-style:italic;font-weight:400;}
    .ci-mprev-meta{font-size:11px;opacity:.7;}
    .ci-mprev-act{display:flex;gap:6px;margin-top:6px;}
    .ci-mprev-act button{background:rgba(255,255,255,.16);color:#fff;border:0;border-radius:6px;padding:4px 9px;font-size:12px;cursor:pointer;}
    .ci-mprev-act .ci-mprev-x{margin-left:auto;}
    /* ---- ressourcenarme Animationen: nur opacity/transform, mit Reduced-Motion-Abschaltung ---- */
    @keyframes ciFadeUp{from{opacity:0;transform:translateY(10px);}to{opacity:1;transform:none;}}
    @keyframes ciFade{from{opacity:0;}to{opacity:1;}}
    @keyframes ciSheet{from{opacity:.3;transform:translateY(18px);}to{opacity:1;transform:none;}}
    @keyframes ciPop{0%{opacity:0;transform:scale(.5);}60%{transform:scale(1.08);}100%{opacity:1;transform:none;}}
    .card{animation:ciFadeUp .3s cubic-bezier(.22,.61,.36,1) both;}
    .overlay:not(.d-none){animation:ciFade .18s ease;}
    .modal{animation:ciSheet .24s cubic-bezier(.22,.61,.36,1);}
    .check{animation:ciPop .42s cubic-bezier(.34,1.56,.64,1) both;}
    .hstat{transition:background .25s ease;}
    .btn,.pt,.plate-save,.lnk{transition:transform .08s ease, filter .12s ease;}
    .btn:active,.pt:active,.plate-save:active{transform:scale(.97);}
    @media (prefers-reduced-motion: reduce){
      .card,.overlay,.modal,.check{animation:none!important;}
      .btn:active,.pt:active,.plate-save:active{transform:none;}
    }
    </style></head><body class="ci-sa"><div class="card">
  <div class="hd">
<a class="back" id="ci-back" href="https://seaside.pacim.de/day-list.php?t=63755ecedbb6c1c962cf0dd2" title="Zurück zur Liste" aria-label="Zurück zur Liste"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg></a>
    <div class="k">Check-out</div>
    <div class="t">Fischer, Jörg</div>
    <div class="no">26-16730</div>
    <span class="hstat" id="ci-status-badge"></span>
  </div>
  <div class="slider" id="ci-slider"><div class="track" id="ci-track">

  <!-- ============================ Tab 1: Buchung ============================ -->
  <section class="pane active" id="pane-buchung" data-pane="buchung">
    <!-- Hervorgehobene Notiz(en) als Endlos-Lauftext im Datenblatt -->
  <div class="ci-marquee d-none" id="ci-marquee">
    <svg class="ci-mq-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M3 11v2a1 1 0 0 0 1 1h2l4 4V6L6 10H4a1 1 0 0 0-1 1z"/><path d="M15 9a3 3 0 0 1 0 6M17.5 6.5a6 6 0 0 1 0 11"/></svg>
    <div class="ci-mq-win"><div class="ci-mq-track" id="ci-mq-track"><span class="ci-mq-seg"></span><span class="ci-mq-seg" aria-hidden="true"></span></div></div>
  </div>
  <div class="bd">
        <div class="plate-wrap">
      <div class="plate fe" id="ci-plate" spellcheck="false">FB - TK 1507</div>
      <button type="button" class="plate-save d-none" id="ci-plate-save" title="Speichern" aria-label="Speichern"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 13l4 4L19 7"/></svg></button>
      <button type="button" class="plate-info" id="ci-plate-info" title="Kennzeichen-Herkunft" aria-label="Kennzeichen-Info"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9.5"/><path d="M12 11v5"/><circle cx="12" cy="7.7" r="0.7" fill="currentColor" stroke="none"/></svg></button>
    </div>
    <div class="row"><span class="l">Schiff</span><span class="v">AIDAluna<br><span class="muted">7 Tage</span></span></div>
    <div class="row"><span class="l">Stellplatz</span><span class="v">Außen</span></div>
    <div class="row"><span class="l">Zeitraum</span><span class="v">03.10. – 10.10.26</span></div>
        <div class="row d-none" id="ci-timerow">
      <span class="l" id="ci-timelabel">Boarding</span>
      <span class="v" id="ci-timeval"></span>
    </div>
  </div>

            <!-- Bezahlt-Status (nur sichtbar, wenn bereits gezahlt) -->
      <div class="sec d-none" id="ci-paid-sec">
        <div class="note ok"><strong>Bezahlt:</strong> <span id="ci-paid-info"></span> <button type="button" class="lnk" id="ci-edit-btn">ändern</button></div>
      </div>
        <!-- Eine Haupt-Aktion: wechselt Zahlung → Check-in → Auschecken -->
    <div class="sec">
      <button type="button" class="btn" id="ci-action-btn">Aktion</button>
    </div>
  
  <div class="status" id="ci-status"></div>
  </section>

  <!-- ============================ Tab 2: Notizen ============================ -->
  <section class="pane" id="pane-notizen" data-pane="notizen">
        
    <div class="nt-block">
      <div class="sec-h nt-title"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16v12l-4 4H4z"/><path d="M16 20v-4h4M8 9h8M8 13h5"/></svg> Interne Notizen <span class="ph-count" id="ci-nt-count"></span></div>
            <div class="nt-list" id="ci-nt-list"></div>
      <div class="nt-empty d-none" id="ci-nt-empty">Noch keine internen Notizen.</div>
      <div class="nt-foot">Dieser Zugang darf interne Notizen nur ansehen.</div>    </div>
  </section>

  <!-- ============================ Tab 3: Fotos ============================ -->
  
  </div></div><!-- /track /slider -->
</div>

<!-- Footer-Tab-Navigation (fixiert) -->
<nav class="tabbar" id="ci-tabbar">
  <button type="button" class="tab active" data-tab="buchung">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="3" width="16" height="18" rx="2"/><path d="M8 7h8M8 11h8M8 15h5"/></svg>
    <span>Buchung</span></button>
  <button type="button" class="tab" data-tab="notizen">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16v12l-4 4H4z"/><path d="M16 20v-4h4M8 9h8M8 13h5"/></svg>
    <span>Notizen</span><span class="tb-badge d-none" id="ci-tb-notes"></span></button>
  </nav>

<!-- Zahlungs-Modal -->
<div class="overlay d-none" id="ci-pay-modal">
  <div class="modal">
    <div class="modal-h"><span>Zahlung erfassen</span><button type="button" class="modal-x" id="ci-pay-close" aria-label="Schließen">&times;</button></div>
    <div class="modal-b">
      <label class="fld-l">Rabattaktion</label>
      <select id="ci-coupon" class="sel">
        <option value="0">Kein Rabatt</option>
        <option value="1">5 € Bestandskundenrabatt</option>
        <option value="2">10 % Frühbucherrabatt</option>
      </select>
      <div class="amount">Zu zahlen: <strong id="ci-amount">—</strong></div>
      <label class="fld-l">Zahlungsart</label>
      <div class="pay-types" id="ci-types">
        <button type="button" class="pt" data-type="2">EC-Karte</button>
        <button type="button" class="pt" data-type="3">Bar</button>
      </div>
      <div class="modal-err d-none" id="ci-pay-err"></div>
      <button type="button" class="btn btn-checkin" id="ci-pay-btn">Zahlung speichern</button>
    </div>
  </div>
</div>



<!-- Kennzeichen-Herkunft (lokale DB, DE/AT/CH) -->
<div class="overlay d-none" id="ci-plate-modal">
  <div class="modal pl-modal">
    <div class="modal-h"><span>Kennzeichen-Herkunft</span><button type="button" class="modal-x" id="ci-pl-close" aria-label="Schließen">&times;</button></div>
    <div class="modal-b" id="ci-pl-body"></div>
  </div>
</div>

<!-- Check-in Erfolg / Countdown -->
<div class="overlay d-none" id="ci-done">
  <div class="done-box">
    <div class="check" id="ci-done-ic"><svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 13l4 4L19 7"/></svg></div>
    <div class="done-t" id="ci-done-t">Check-in erfasst</div>
    <div class="done-x">Zurück zur Liste in <span id="ci-cd">3</span> s …</div>
    <button type="button" class="btn-cancel" id="ci-cancel">Abbrechen – hier bleiben</button>
    <div class="done-skip">irgendwo tippen, um sofort zur Liste zu wechseln</div>
  </div>
</div>

<script>
var CFG = {"b":106225,"h":"","t":"63755ecedbb6c1c962cf0dd2","embed":false,"paid":false,"arrived":false,"storno":false,"isAida":false,"isDep":true,"canAct":true,"coupon":0,"amounts":[90,85,81],"payType":0,"back":"https:\/\/seaside.pacim.de\/day-list.php?t=63755ecedbb6c1c962cf0dd2","boarding":"","ciTime":"","imgApi":"https:\/\/seaside.pacim.de\/booking-images.php","imgView":false,"imgUpload":false,"imgNote":false,"canNotes":false,"hasImg":false,"plateHasInfo":true,"notesCount":0,"noteMarquee":[],"photosCount":0,"plate":"FB - TK 1507","bookingNo":"26-16730"};
(function(){
  // Browser-Zoom unterbinden (iOS Safari ignoriert user-scalable=no)
  ['gesturestart','gesturechange','gestureend'].forEach(function(ev){ document.addEventListener(ev, function(e){ e.preventDefault(); }, {passive:false}); });
  document.addEventListener('touchmove', function(e){ if(e.touches && e.touches.length>1) e.preventDefault(); }, {passive:false});
  // Vollbild beim ersten Tippen (nur eigenständig; eingebettet übernimmt das die Tagesliste).
  if(!CFG.embed){ document.addEventListener('pointerdown', function f(){ document.removeEventListener('pointerdown',f); var e=document.documentElement,r=e.requestFullscreen||e.webkitRequestFullscreen; if(r){ try{ r.call(e); }catch(_){} } }, {passive:true}); }

  var API = location.pathname; // gleiche Datei
  var $ = function(id){ return document.getElementById(id); };
  var coupon = $('ci-coupon'), amountEl = $('ci-amount'), status = $('ci-status');
  var selType = CFG.payType || 0;  // keine Zahlungsart vorausgewählt

  // Eingebettet (Overlay der Tagesliste): Statusänderungen an die Elternseite melden.
  function ciState(){ return CFG.storno?'x':(CFG.arrived?'i':(CFG.paid?'p':'o')); }
  function parentMsg(o){ if(CFG.embed && window.parent && window.parent!==window){ o.pacimCi=1; o.b=CFG.b; try{ window.parent.postMessage(o,'*'); }catch(e){} } }
  // Anreise-/Check-in-Zeit live: angereist -> „Check-in HH:MM · Boarding HH:MM (muted)", sonst „Boarding".
  function renderTimeRow(){
    var row=$('ci-timerow'), lab=$('ci-timelabel'), val=$('ci-timeval'); if(!row||!lab||!val) return;
    if(CFG.arrived && CFG.ciTime){ lab.textContent=CFG.isDep?'Check-out':'Check-in'; val.innerHTML=CFG.ciTime+' Uhr'+(CFG.boarding?' <span class="muted">· Boarding '+CFG.boarding+'</span>':''); row.classList.remove('d-none'); }
    else if(CFG.boarding){ lab.textContent='Boarding'; val.textContent=CFG.boarding+' Uhr'; row.classList.remove('d-none'); }
    else row.classList.add('d-none');
  }

  function eur(v){ return v.toFixed(2).replace('.',',') + ' €'; }
  function setStatus(t,k){ status.textContent = t||''; status.className = 'status' + (k?(' '+k):''); }

  function refreshAmount(){ if(amountEl) amountEl.textContent = eur(CFG.amounts[coupon ? coupon.value : 0]); }
  function markType(){ var ts=document.querySelectorAll('#ci-types .pt'); for(var i=0;i<ts.length;i++) ts[i].classList.toggle('on', parseInt(ts[i].dataset.type,10)===selType); }

  function statusBadge(){
    var sb=$('ci-status-badge'); if(!sb) return;
    var cls,txt;
    if(CFG.storno){ cls='s-red'; txt='Storniert'; }
    else if(CFG.isDep){ if(CFG.arrived){ cls='s-green'; txt='Abgereist'; } else { cls='s-blue'; txt='Abreise offen'; } }
    else if(CFG.arrived){ cls='s-green'; txt='Angereist'; }
    else if(CFG.paid){ cls='s-blue'; txt='Check-in offen'; }
    else { cls='s-orange'; txt = CFG.canAct ? (eur(CFG.amounts[CFG.coupon||0])+' offen') : 'Zahlung offen'; }
    sb.className='hstat '+cls; sb.textContent=txt;
  }
  var PAYNAMES={1:'Überweisung',2:'EC-Karte',3:'Bar'};

  function renderState(){
    statusBadge();
    if(CFG.storno) return;
    var paidSec=$('ci-paid-sec'), btn=$('ci-action-btn');
    if(paidSec){
      if(CFG.paid && !CFG.isAida){
        paidSec.classList.remove('d-none');
        $('ci-paid-info').textContent = eur(CFG.amounts[CFG.coupon||0]) + ' · ' + (PAYNAMES[CFG.payType]||'');
      } else paidSec.classList.add('d-none');
    }
    if(btn){
      btn.disabled=false;
      if(CFG.isDep){
        // Abreisen: Check-out erfassen / zurücknehmen (keine Zahlungs-Logik).
        if(CFG.arrived){ btn.textContent='Check-out zurücknehmen'; btn.className='btn btn-danger'; btn.dataset.act='uncheckout'; }
        else { btn.textContent='Check-out erfassen'; btn.className='btn btn-checkin'; btn.dataset.act='checkout'; }
      }
      else if(CFG.arrived){ btn.textContent='Fahrzeug auschecken'; btn.className='btn btn-danger'; btn.dataset.act='uncheckin'; }
      else if(CFG.paid){ btn.textContent='Check-in erfassen'; btn.className='btn btn-checkin'; btn.dataset.act='checkin'; }
      else { btn.textContent='Zahlung erfassen'; btn.className='btn btn-warn'; btn.dataset.act='pay'; }
    }
  }

  if(coupon){ coupon.value = CFG.coupon || 0; coupon.addEventListener('change', refreshAmount); refreshAmount(); }
  var types=document.querySelectorAll('#ci-types .pt');
  for(var i=0;i<types.length;i++){ types[i].addEventListener('click', function(){ selType=parseInt(this.dataset.type,10); markType(); payClearErr(); }); }
  markType();

  function post(data, cb){
    var fd=new URLSearchParams(); fd.set('b',CFG.b); fd.set('h',CFG.h); if(CFG.t) fd.set('t',CFG.t);
    for(var k in data) fd.set(k,data[k]);
    fetch(API,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'},body:fd.toString()})
      .then(function(r){return r.json();}).then(cb).catch(function(){ setStatus('Serverfehler.','err'); });
  }

  // ---- Zahlungs-Modal
  var payModal=$('ci-pay-modal'), payErr=$('ci-pay-err');
  function payError(m){ if(payErr){ payErr.textContent=m||'Fehler.'; payErr.classList.remove('d-none'); } else setStatus(m,'err'); }
  function payClearErr(){ if(payErr){ payErr.textContent=''; payErr.classList.add('d-none'); } }
  function openPay(){ if(!payModal) return; selType=CFG.payType||0; if(coupon){coupon.value=CFG.coupon||0; refreshAmount();} markType(); payClearErr(); payModal.classList.remove('d-none'); }
  function closePay(){ if(payModal) payModal.classList.add('d-none'); }
  var payClose=$('ci-pay-close'); if(payClose) payClose.addEventListener('click', closePay);
  if(payModal) payModal.addEventListener('click', function(e){ if(e.target===payModal) closePay(); });

  var payBtn=$('ci-pay-btn');
  if(payBtn) payBtn.addEventListener('click', function(){
    payClearErr();
    if(!selType){ payError('Bitte Zahlungsart wählen.'); return; }
    payBtn.disabled=true;
    post({action:'pay', type:selType, coupon:(coupon?coupon.value:0)}, function(res){
      payBtn.disabled=false;
      if(!res||!res.ok){ payError((res&&res.error)||'Fehler.'); return; }   // Fehler bleibt im Modal, keine Rechnung erstellt
      CFG.paid=true; CFG.coupon=res.coupon; CFG.payType=res.type;
      closePay(); renderState(); parentMsg({state:ciState()});
      setStatus('✓ Zahlung erfasst ('+res.amount_fmt+' · '+res.type_name+')','ok');
    });
  });

  var editBtn=$('ci-edit-btn');
  if(editBtn) editBtn.addEventListener('click', function(){ openPay(); });

  var IN_ICON='<svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 13l4 4L19 7"/></svg>';
  var OUT_ICON='<svg viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M14 3h5a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-5"/><path d="M11 16l4-4-4-4"/><path d="M15 12H3"/></svg>';
  function startCountdown(mode){
    var out=(mode==='out');
    var ov=$('ci-done'); if(!ov){ if(CFG.embed) parentMsg({close:1}); else location.href=CFG.back; return; }
    ov.classList.toggle('out', out);
    var ic=$('ci-done-ic'); if(ic) ic.innerHTML = out?OUT_ICON:IN_ICON;
    var tt=$('ci-done-t'); if(tt) tt.textContent = CFG.isDep ? (out?'Check-out zurückgenommen':'Abreise erfasst') : (out?'Fahrzeug ausgecheckt':'Check-in erfasst');
    ov.classList.remove('d-none');
    var n=3, cd=$('ci-cd'), done=false; cd.textContent=n;
    var t=setInterval(function(){ n--; cd.textContent=n; if(n<=0) finish(); },1000);
    function finish(){ if(done) return; done=true; clearInterval(t); if(CFG.embed){ parentMsg({close:1}); } else { location.href=CFG.back; } }
    function stay(){ if(done) return; done=true; clearInterval(t); ov.classList.add('d-none'); }
    var cBtn=$('ci-cancel'); if(cBtn) cBtn.onclick=function(e){ e.stopPropagation(); stay(); };  // Abbrechen -> hier bleiben
    ov.onclick=function(e){ if(e.target.closest('#ci-cancel')) return; finish(); };               // woanders -> sofort weiter
  }

  var actBtn=$('ci-action-btn');
  if(actBtn) actBtn.addEventListener('click', function(){
    var act=actBtn.dataset.act;
    if(act==='pay'){ openPay(); return; }
    if(act==='uncheckin'){
      actBtn.disabled=true; setStatus('Check-in wird zurückgenommen …');
      post({action:'uncheckin'}, function(res){
        if(!res||!res.ok){ actBtn.disabled=false; setStatus((res&&res.error)||'Fehler.','err'); return; }
        CFG.arrived=false; CFG.ciTime=''; renderState(); renderTimeRow(); parentMsg({state:ciState()}); setStatus('Check-in zurückgenommen.','ok');
        startCountdown('out');
      });
      return;
    }
    if(act==='checkin'){
      actBtn.disabled=true; setStatus('Check-in …');
      post({action:'checkin'}, function(res){
        if(!res||!res.ok){ actBtn.disabled=false; setStatus((res&&res.error)||'Fehler.','err'); return; }
        CFG.arrived=true; CFG.ciTime=res.time||CFG.ciTime; renderState(); renderTimeRow(); parentMsg({state:'i'}); startCountdown('in');
      });
      return;
    }
    if(act==='checkout'){
      actBtn.disabled=true; setStatus('Check-out …');
      post({action:'checkout'}, function(res){
        if(!res||!res.ok){ actBtn.disabled=false; setStatus((res&&res.error)||'Fehler.','err'); return; }
        CFG.arrived=true; CFG.ciTime=res.time||CFG.ciTime; renderState(); renderTimeRow(); parentMsg({state:'i'}); startCountdown('in');
      });
      return;
    }
    if(act==='uncheckout'){
      actBtn.disabled=true; setStatus('Check-out wird zurückgenommen …');
      post({action:'uncheckout'}, function(res){
        if(!res||!res.ok){ actBtn.disabled=false; setStatus((res&&res.error)||'Fehler.','err'); return; }
        CFG.arrived=false; CFG.ciTime=''; renderState(); renderTimeRow(); parentMsg({state:ciState()}); setStatus('Check-out zurückgenommen.','ok');
        startCountdown('out');
      });
      return;
    }
  });

  // Kennzeichen ändern – direkt im Kennzeichen-Feld (Klick rein aktiviert, Speichern-Button rechts)
  var plate=$('ci-plate'), plSave=$('ci-plate-save'), plOrig = plate ? plate.textContent : '';
  if(plate && plSave && !plate.getAttribute('data-ro')){
    function startEdit(){
      if(plate.isContentEditable) return;
      plOrig = plate.textContent;
      plate.contentEditable='true'; plate.classList.add('editing'); plSave.classList.remove('d-none');
      plate.focus();
      try{ var rng=document.createRange(); rng.selectNodeContents(plate); rng.collapse(false); var sel=getSelection(); sel.removeAllRanges(); sel.addRange(rng); }catch(e){}
    }
    function stopEdit(){ plate.contentEditable='false'; plate.classList.remove('editing'); plSave.classList.add('d-none'); }
    plate.addEventListener('click', startEdit);
    plate.addEventListener('keydown', function(ev){
      if(ev.key==='Enter'){ ev.preventDefault(); plSave.click(); }
      else if(ev.key==='Escape'){ plate.textContent=plOrig; stopEdit(); }
    });
    // Klick außerhalb: ohne Änderung Bearbeiten beenden; mit ungespeicherter Änderung nachfragen.
    plate.addEventListener('blur', function(){
      if(!plate.isContentEditable) return;
      var cur=(plate.textContent||'').replace(/\s+/g,' ').trim();
      var org=(plOrig||'').replace(/\s+/g,' ').trim();
      if(cur===org || cur===''){ plate.textContent=plOrig; stopEdit(); return; }
      if(confirm('Kennzeichen „'+cur+'" speichern?\n\nOK = Speichern · Abbrechen = Verwerfen')){ plSave.click(); }
      else { plate.textContent=plOrig; stopEdit(); }
    });
    plSave.addEventListener('mousedown', function(ev){ ev.preventDefault(); }); // Fokus im Feld halten (kein blur beim Speichern)
    plSave.addEventListener('click', function(ev){
      ev.stopPropagation();
      var v=(plate.textContent||'').replace(/\s+/g,' ').trim();
      if(!v){ setStatus('Bitte ein Kennzeichen eingeben.','err'); return; }
      setStatus('Kennzeichen wird gespeichert …');
      post({action:'plate', plate:v}, function(res){
        if(!res||!res.ok){ setStatus((res&&res.error)||'Fehler.','err'); plate.textContent=plOrig; return; }
        plate.textContent=res.plate; plOrig=res.plate; stopEdit(); parentMsg({rows:1});
        setStatus('✓ Kennzeichen aktualisiert','ok');
      });
    });
  }

  var backLink=$('ci-back');
  if(backLink && CFG.embed) backLink.addEventListener('click', function(e){ e.preventDefault(); parentMsg({close:1}); });

  renderState();
  renderTimeRow();
})();

/* ============================================================ Fahrzeugfotos */
(function(){
  if(!CFG.imgView && !CFG.imgUpload) return;
  var $=function(id){return document.getElementById(id);};
  var grid=$('ci-ph-grid'), countEl=$('ci-ph-count'), emptyEl=$('ci-ph-empty');
  var API=CFG.imgApi, images=[];
  function esc(s){return String(s==null?'':s).replace(/[&<>"]/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];});}
  function authParams(fd){ fd.append('b',CFG.b); if(CFG.t) fd.append('t',CFG.t); if(CFG.h) fd.append('h',CFG.h); return fd; }
  function listUrl(){ var q='action=list&b='+CFG.b; if(CFG.t)q+='&t='+encodeURIComponent(CFG.t); if(CFG.h)q+='&h='+encodeURIComponent(CFG.h); return API+'?'+q; }

  // ---------- Galerie
  function loadGallery(){
    if(!CFG.imgView){ if(emptyEl) emptyEl.style.display=''; return; }
    fetch(listUrl(),{headers:{'X-Requested-With':'XMLHttpRequest'}}).then(function(r){return r.json();}).then(function(res){
      if(!res||!res.success){ return; }
      images=res.images||[]; renderGrid();
    }).catch(function(){});
  }
  var NOTE_SVG='<svg viewBox="0 0 24 24" fill="none" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>';
  function renderGrid(){
    if(countEl){ countEl.textContent=images.length; countEl.classList.toggle('zero', images.length===0); }
    var tbP=document.getElementById('ci-tb-photos'); if(tbP){ tbP.textContent=images.length; tbP.classList.toggle('d-none', images.length===0); }
    if(emptyEl) emptyEl.style.display = images.length? 'none':'';
    if(window.ciSliderResize) window.ciSliderResize();
    if(!grid) return;
    var h='';
    for(var i=0;i<images.length;i++){ var im=images[i];
      var mb=(im.marker_count>0)?'<span class="ph-mbadge"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a7 7 0 0 0-7 7c0 5.2 7 13 7 13s7-7.8 7-13a7 7 0 0 0-7-7zm0 9.5A2.5 2.5 0 1 1 12 6a2.5 2.5 0 0 1 0 5.5z"/></svg>'+im.marker_count+'</span>':'';
      h+='<div class="ph-thumb" data-i="'+i+'"><img src="'+esc(im.thumb_url)+'" loading="lazy" alt="">'+mb+((im.note&&im.note_visible!==false)?'<span class="ph-ndot">'+NOTE_SVG+'</span>':'')+'</div>';
    }
    grid.innerHTML=h;
  }
  if(grid) grid.addEventListener('click', function(e){ var t=e.target.closest('.ph-thumb'); if(t) openLb(parseInt(t.dataset.i,10)); });

  // ---------- Lightbox
  var lb=$('ci-lb'), lbImg=$('ci-lb-img'), lbInfo=$('ci-lb-info'), lbPos=$('ci-lb-pos'),
      lbDel=$('ci-lb-del'), lbDl=$('ci-lb-dl'), lbStage=$('ci-lb-stage');
  var idx=0, scale=1, tx=0, ty=0;
  // Ladespinner über der Bühne (sichtbar beim Durchsliden bis das Bild geladen ist).
  var lbSpin=document.createElement('div'); lbSpin.className='ci-lb-spin'; if(lbStage) lbStage.appendChild(lbSpin);
  function showSpin(){ if(lbSpin) lbSpin.classList.add('on'); }
  function hideSpin(){ if(lbSpin) lbSpin.classList.remove('on'); }
  function applyT(){ lbImg.style.transform='translate('+tx+'px,'+ty+'px) scale('+scale+')'; if(typeof mSync==='function') mSync(); }
  function resetT(){ scale=1; tx=0; ty=0; applyT(); }
  function showInfo(im){
    var meta=[]; meta.push(im.created_at_formatted); if(im.created_by_name) meta.push('von '+esc(im.created_by_name));
    if(CFG.plate) meta.push(esc(CFG.plate)); if(CFG.bookingNo) meta.push(esc(CFG.bookingNo));
    if(im.file_size_formatted) meta.push(im.file_size_formatted+(im.width?' · '+im.width+'×'+im.height:''));
    var note = (im.note&&im.note_visible!==false)? esc(im.note) : '';
    var html='';
    if(note) html+='<div class="lb-note">'+note+'</div>'; else html+='<div class="lb-note" style="opacity:.6;font-weight:400;font-style:italic">Keine Notiz</div>';
    html+='<div class="lb-meta">'+meta.join(' · ')+'</div>';
    if(im.can_edit) html+='<button type="button" class="lb-edit" id="ci-lb-noteedit">Notiz bearbeiten</button>';
    lbInfo.innerHTML=html;
    var ne=$('ci-lb-noteedit'); if(ne) ne.addEventListener('click', function(){ editNote(im); });
    if(lbDel) lbDel.style.display=im.can_delete?'':'none';
    if(lbDl) lbDl.style.display=(im.can_download&&im.original_url)?'':'none';
  }
  function openLb(i){ if(!lb||i<0||i>=images.length) return; idx=i; var im=images[i];
    showSpin(); lbImg.src=im.image_url; resetT(); lbPos.textContent=(i+1)+' / '+images.length; showInfo(im);
    lb.classList.remove('d-none'); document.documentElement.style.overflow='hidden';
    if(typeof mLoad==='function') mLoad();
  }
  function closeLb(){ if(lb){ lb.classList.add('d-none'); lbImg.src=''; document.documentElement.style.overflow='';
    if(typeof mHide==='function') mHide(); mMarkers=[]; if(mLayer) mLayer.innerHTML=''; } }
  function nav(d){ var n=idx+d; if(n<0||n>=images.length) return; openLb(n); }
  if($('ci-lb-x')) $('ci-lb-x').addEventListener('click', closeLb);
  if($('ci-lb-prev')) $('ci-lb-prev').addEventListener('click', function(){ nav(-1); });
  if($('ci-lb-next')) $('ci-lb-next').addEventListener('click', function(){ nav(1); });
  if($('ci-lb-zoom')) $('ci-lb-zoom').addEventListener('click', function(){ scale = scale>1?1:2.5; if(scale===1){tx=0;ty=0;} applyT(); });
  if(lbDl) lbDl.addEventListener('click', function(){ var im=images[idx]; if(im&&im.original_url) window.open(im.original_url,'_blank'); });
  if(lbDel) lbDel.addEventListener('click', function(){ delImage(images[idx]); });

  // Touch: Pinch-Zoom + Pan + Wisch-Navigation + Doppeltipp + Lange-drücken (Marker setzen).
  var pts={}, startDist=0, startScale=1, startTx=0, startTy=0, panX=0, panY=0, lastTap=0, lpTimer=null;
  function dist(a,b){ var dx=a.x-b.x, dy=a.y-b.y; return Math.sqrt(dx*dx+dy*dy); }
  function lpCancel(){ if(lpTimer){ clearTimeout(lpTimer); lpTimer=null; } }
  if(lbStage){
    lbStage.addEventListener('pointerdown', function(e){ pts[e.pointerId]={x:e.clientX,y:e.clientY}; var k=Object.keys(pts);
      if(k.length===1){ panX=e.clientX; panY=e.clientY; startTx=tx; startTy=ty;
        var now=Date.now(); if(now-lastTap<300){ scale=scale>1?1:2.5; if(scale===1){tx=0;ty=0;} applyT(); } lastTap=now;
        // Gedrückt halten -> Marker an dieser Stelle (nur mit Recht, nicht auf einem Marker)
        lpCancel(); if(CFG.imgNote && !(e.target&&e.target.closest&&e.target.closest('.ci-mdot'))){ var lx=e.clientX, ly=e.clientY; lpTimer=setTimeout(function(){ lpTimer=null; addMarkerLP(lx,ly); }, 500); }
      } else if(k.length===2){ lpCancel(); startDist=dist(pts[k[0]],pts[k[1]]); startScale=scale; }
    });
    lbStage.addEventListener('pointermove', function(e){ if(!pts[e.pointerId]) return; pts[e.pointerId]={x:e.clientX,y:e.clientY}; var k=Object.keys(pts);
      if(lpTimer && (Math.abs(e.clientX-panX)>10 || Math.abs(e.clientY-panY)>10)) lpCancel();
      if(k.length===2){ var d=dist(pts[k[0]],pts[k[1]]); if(startDist>0){ scale=Math.min(4,Math.max(1,startScale*d/startDist)); if(scale===1){tx=0;ty=0;} applyT(); } }
      else if(k.length===1 && scale>1){ tx=startTx+(e.clientX-panX); ty=startTy+(e.clientY-panY); applyT(); }
    });
    function up(e){ lpCancel(); var wasPan=(Object.keys(pts).length===1 && scale<=1);
      var sx=pts[e.pointerId]?pts[e.pointerId].x:panX; delete pts[e.pointerId];
      if(wasPan){ var dx=sx-panX; if(Math.abs(dx)>50) nav(dx<0?1:-1); }
      if(Object.keys(pts).length===0 && scale<=1){ tx=0;ty=0;applyT(); }
    }
    lbStage.addEventListener('pointerup', up); lbStage.addEventListener('pointercancel', up);
  }
  // Marker per Lange-drücken setzen: Punkt erfassen, 3× als Zoomstufe speichern, Notiz abfragen.
  function addMarkerLP(cx,cy){
    var im=images[idx]; if(!im) return; var r=lbImg.getBoundingClientRect();
    if(cx<r.left||cx>r.right||cy<r.top||cy>r.bottom) return;
    var rx=(cx-r.left)/r.width, ry=(cy-r.top)/r.height;
    if(navigator.vibrate) try{ navigator.vibrate(30); }catch(_){}
    // Zoom geräteunabhängig: 1,5× der aktuellen mobilen Anzeige (relativ zur Originalauflösung gespeichert).
    var mZoom=(lbImg.offsetWidth&&lbImg.naturalWidth)?(lbImg.offsetWidth*1.5/lbImg.naturalWidth):1.5;
    var v=prompt('Markierung setzen – Notiz (optional):',''); var note=(v===null)?'':v.trim();
    var fd=authParams(new FormData()); fd.append('id',im.id); fd.append('rx',rx.toFixed(5)); fd.append('ry',ry.toFixed(5)); fd.append('zoom',mZoom.toFixed(3)); if(note) fd.append('note',note);
    fetch(API+'?action=marker_add',{method:'POST',body:fd}).then(function(r2){return r2.json();}).then(function(res){
      if(!res||!res.success){ alert((res&&res.error)||'Marker konnte nicht gesetzt werden.'); return; }
      if(!mVisible){ mVisible=true; if(mTog) mTog.classList.add('active'); }
      mMarkers.push(res.marker); mRender();
    }).catch(function(){ alert('Fehler beim Setzen des Markers.'); });
  }

  function editNote(im){ if(!im.can_edit) return; var v=prompt('Notiz zum Bild:', im.note||''); if(v===null) return;
    var fd=authParams(new FormData()); fd.append('id',im.id); fd.append('note',v);
    fetch(API+'?action=note',{method:'POST',body:fd}).then(function(r){return r.json();}).then(function(res){
      if(res&&res.success){ im.note=res.note; showInfo(im); renderGrid(); } else alert((res&&res.error)||'Fehler.');
    }).catch(function(){ alert('Fehler.'); });
  }
  function delImage(im){ if(!im||!im.can_delete) return; if(!confirm('Dieses Foto löschen?')) return;
    var fd=authParams(new FormData()); fd.append('id',im.id);
    fetch(API+'?action=delete',{method:'POST',body:fd}).then(function(r){return r.json();}).then(function(res){
      if(res&&res.success){ closeLb(); loadGallery(); } else alert((res&&res.error)||'Fehler.');
    }).catch(function(){ alert('Fehler.'); });
  }

  // ---------- Upload
  if(CFG.imgUpload){
    var addBtn=$('ci-ph-add'), upModal=$('ci-up-modal'), tiles=$('ci-up-tiles'),
        goBtn=$('ci-up-go'), upErr=$('ci-up-err'), cam=$('ci-up-cam'), gal=$('ci-up-gal');
    var queue=[];   // {file, url, note, el, bar, st, status}
    function openUp(){ queue=[]; tiles.innerHTML=''; goBtn.disabled=true; upErr.classList.add('d-none'); upModal.classList.remove('d-none'); }
    function closeUp(){ upModal.classList.add('d-none'); queue.forEach(function(q){ if(q.url) URL.revokeObjectURL(q.url); }); queue=[]; tiles.innerHTML=''; }
    if(addBtn) addBtn.addEventListener('click', openUp);
    if($('ci-up-close')) $('ci-up-close').addEventListener('click', closeUp);
    if(upModal) upModal.addEventListener('click', function(e){ if(e.target===upModal) closeUp(); });

    function addFiles(fl){
      var MAX=10;
      for(var i=0;i<fl.length;i++){ if(queue.length>=MAX){ upErr.textContent='Maximal '+MAX+' Bilder auf einmal.'; upErr.classList.remove('d-none'); break; }
        var f=fl[i]; if(!/^image\//.test(f.type)) continue;
        addTile(f);
      }
      goBtn.disabled = queue.length===0;
    }
    function addTile(f){
      var url=URL.createObjectURL(f);
      var el=document.createElement('div'); el.className='ph-tile';
      el.innerHTML='<div class="ph-tibox"><img src="'+url+'" alt=""><button type="button" class="ph-rm">&times;</button><div class="ph-st d-none"></div><div class="ph-bar"></div></div>'+
        (CFG.imgNote?'<input type="text" class="ph-tnote" maxlength="500" placeholder="Notiz (optional)">':'');
      tiles.appendChild(el);
      var item={file:f,url:url,note:'',el:el,bar:el.querySelector('.ph-bar'),st:el.querySelector('.ph-st'),status:'wait'};
      var noteInp=el.querySelector('.ph-tnote'); if(noteInp) noteInp.addEventListener('input',function(){ item.note=this.value; });
      el.querySelector('.ph-rm').addEventListener('click',function(){ if(item.status==='up') return; var ix=queue.indexOf(item); if(ix>=0)queue.splice(ix,1); URL.revokeObjectURL(item.url); el.remove(); goBtn.disabled=queue.length===0; });
      queue.push(item);
    }
    if(cam) cam.addEventListener('change',function(){ addFiles(this.files); this.value=''; });
    if(gal) gal.addEventListener('change',function(){ addFiles(this.files); this.value=''; });

    function setSt(item,txt,show){ item.st.textContent=txt||''; item.st.classList.toggle('d-none', !show); }
    function resizeImage(file, cb){
      function finish(bw,bh,draw){ var s=Math.min(1,1920/Math.max(bw,bh)); var nw=Math.max(1,Math.round(bw*s)),nh=Math.max(1,Math.round(bh*s));
        var cv=document.createElement('canvas'); cv.width=nw; cv.height=nh; var cx=cv.getContext('2d'); cx.fillStyle='#fff'; cx.fillRect(0,0,nw,nh); draw(cx,nw,nh);
        cv.toBlob(function(b){ cb(b); }, 'image/jpeg', 0.82); }
      if(window.createImageBitmap){ createImageBitmap(file,{imageOrientation:'from-image'}).then(function(bmp){ finish(bmp.width,bmp.height,function(cx,nw,nh){cx.drawImage(bmp,0,0,nw,nh); if(bmp.close)bmp.close();}); }).catch(fb); }
      else fb();
      function fb(){ var u=URL.createObjectURL(file), im=new Image(); im.onload=function(){ finish(im.naturalWidth,im.naturalHeight,function(cx,nw,nh){cx.drawImage(im,0,0,nw,nh);}); URL.revokeObjectURL(u); }; im.onerror=function(){ URL.revokeObjectURL(u); cb(null); }; im.src=u; }
    }
    function uploadItem(item, done){
      item.status='up'; setSt(item,'Wird hochgeladen…',true); item.bar.style.width='5%';
      resizeImage(item.file, function(blob){
        if(!blob){ item.status='err'; item.el.classList.add('err'); setSt(item,'Fehler',true); return done(false); }
        var fd=authParams(new FormData()); fd.append('image',blob,'photo.jpg'); if(item.note) fd.append('note',item.note);
        var xhr=new XMLHttpRequest(); xhr.open('POST',API+'?action=upload');
        xhr.upload.onprogress=function(e){ if(e.lengthComputable){ item.bar.style.width=Math.max(5,Math.round(e.loaded/e.total*95))+'%'; } };
        xhr.onload=function(){ var res; try{res=JSON.parse(xhr.responseText);}catch(_){res=null;}
          if(res&&res.success){ item.status='done'; item.el.classList.add('done'); item.bar.style.width='100%'; setSt(item,'✓ Fertig',true); done(true); }
          else { item.status='err'; item.el.classList.add('err'); setSt(item,(res&&res.error)||'Fehler',true); done(false); } };
        xhr.onerror=function(){ item.status='err'; item.el.classList.add('err'); setSt(item,'Netzwerkfehler',true); done(false); };
        xhr.send(fd);
      });
    }
    if(goBtn) goBtn.addEventListener('click', function(){
      var pend=queue.filter(function(q){return q.status==='wait';}); if(!pend.length) return;
      goBtn.disabled=true; upErr.classList.add('d-none');
      var i=0, okCount=0;
      (function next(){ if(i>=pend.length){ // fertig
          loadGallery();
          if(okCount===pend.length){ closeUp(); }
          else { upErr.textContent='Einige Bilder konnten nicht hochgeladen werden.'; upErr.classList.remove('d-none'); goBtn.disabled=false; goBtn.textContent='Erneut versuchen'; }
          return; }
        uploadItem(pend[i], function(ok){ if(ok)okCount++; i++; next(); });
      })();
    });
  }

  // ---------- Befund-Marker (mobil: ansehen, ein-/ausblenden; Erstellen nur im CRM mit Lupe) ----------
  var mLayer=null, mMarkers=[], mPrev=null, mVisible=true, mTog=$('ci-lb-mtoggle');
  function mAuthQ(){ var q=''; if(CFG.t) q+='&t='+encodeURIComponent(CFG.t); if(CFG.h) q+='&h='+encodeURIComponent(CFG.h)+'&b='+CFG.b; return q; }
  function mEnsure(){ if(!lbStage) return;
    if(!mLayer){ mLayer=document.createElement('div'); mLayer.className='ci-mlayer'; lbStage.appendChild(mLayer);
      mLayer.addEventListener('click', function(e){ var d=e.target.closest('.ci-mdot'); if(d) mShow(parseInt(d.dataset.i,10), d); }); }
    if(!mPrev){ mPrev=document.createElement('div'); mPrev.className='ci-mprev'; lbStage.appendChild(mPrev); }
  }
  function mHide(){ if(mPrev) mPrev.classList.remove('on'); }
  function mSync(){ if(!mLayer) return; mLayer.style.transform=lbImg.style.transform||''; mLayer.style.setProperty('--mInv', scale?(1/scale):1); }
  function mLoad(){ var im=images[idx]; mMarkers=[]; if(!im||!CFG.imgView){ mRender(); return; }
    fetch(API+'?action=markers&id='+im.id+mAuthQ(),{headers:{'X-Requested-With':'XMLHttpRequest'}}).then(function(r){return r.json();}).then(function(res){ if(res&&res.success){ mMarkers=res.markers||[]; mRender(); } }).catch(function(){});
  }
  function mRender(){ mEnsure(); if(!mLayer) return; mLayer.innerHTML='';
    if(!mVisible){ mLayer.style.display='none'; return; } mLayer.style.display='';
    if(!mMarkers.length) return; var ow=lbImg.offsetWidth, oh=lbImg.offsetHeight; if(ow<2) return;
    mLayer.style.left=lbImg.offsetLeft+'px'; mLayer.style.top=lbImg.offsetTop+'px'; mLayer.style.width=ow+'px'; mLayer.style.height=oh+'px';
    for(var i=0;i<mMarkers.length;i++){ var m=mMarkers[i]; var d=document.createElement('button'); d.type='button'; d.className='ci-mdot'; d.textContent=(i+1); d.style.left=(m.rx*ow)+'px'; d.style.top=(m.ry*oh)+'px'; d.dataset.i=i; mLayer.appendChild(d); }
    mSync();
  }
  function mShow(i, dot){ var m=mMarkers[i], im=images[idx]; if(!m||!im) return; mEnsure();
    var sr=lbStage.getBoundingClientRect(), bw=210, bh=140, Z=m.zoom;
    var nw=lbImg.naturalWidth||lbImg.offsetWidth, nh=lbImg.naturalHeight||lbImg.offsetHeight, bgW=nw*Z, bgH=nh*Z;   // geräteunabhängig (Originalauflösung)
    var zcur=lbImg.offsetWidth?(bgW/lbImg.offsetWidth):Z;
    var note=(m.note&&m.note_visible!==false)?esc(m.note):'';
    var h='<div class="ci-mprev-img" style="background-image:url(\''+im.image_url+'\');background-size:'+bgW+'px '+bgH+'px;background-position:'+(bw/2-m.rx*bgW)+'px '+(bh/2-m.ry*bgH)+'px"></div>';
    h+='<div class="ci-mprev-b"><div class="ci-mprev-z">Zoom '+(Math.round(zcur*10)/10).toString().replace('.',',')+'×</div>';
    h+='<div class="ci-mprev-note">'+(note||'<span class="ci-mprev-empty">Keine Notiz</span>')+'</div>';
    h+='<div class="ci-mprev-meta">'+esc(m.created_at_formatted)+(m.created_by_name?' · '+esc(m.created_by_name):'')+'</div>';
    h+='<div class="ci-mprev-act">'+(m.can_delete?'<button type="button" class="ci-mprev-del">Löschen</button>':'')+'<button type="button" class="ci-mprev-x">&times;</button></div></div>';
    mPrev.innerHTML=h; mPrev.style.width=bw+'px';
    var dr=dot?dot.getBoundingClientRect():null; var dx=dr?(dr.left+dr.width/2-sr.left):sr.width/2, dy=dr?(dr.top+dr.height/2-sr.top):sr.height/2;
    var px=dx+18, py=dy-10; if(px+bw>sr.width) px=dx-bw-18; if(px<0)px=4; if(py+240>sr.height) py=sr.height-240; if(py<0)py=4;
    mPrev.style.left=px+'px'; mPrev.style.top=py+'px'; mPrev.classList.add('on');
    var db=mPrev.querySelector('.ci-mprev-del'); if(db) db.onclick=function(){ mDel(m); };
    mPrev.querySelector('.ci-mprev-x').onclick=mHide;
  }
  function mDel(m){ if(!m.can_delete) return; if(!confirm('Diesen Marker löschen?')) return;
    var fd=authParams(new FormData()); fd.append('mid',m.id);
    fetch(API+'?action=marker_delete',{method:'POST',body:fd}).then(function(r){return r.json();}).then(function(res){ if(res&&res.success){ var ix=mMarkers.indexOf(m); if(ix>=0)mMarkers.splice(ix,1); mHide(); mRender(); } else alert((res&&res.error)||'Fehler.'); }).catch(function(){ alert('Fehler.'); });
  }
  if(lbImg){ lbImg.addEventListener('load', mRender); lbImg.addEventListener('load', hideSpin); lbImg.addEventListener('error', hideSpin); }
  if(mTog) mTog.addEventListener('click', function(){ mVisible=!mVisible; mTog.classList.toggle('active',mVisible); if(!mVisible) mHide(); mRender(); });

  loadGallery();
})();

/* ============================================================ Footer-Tabs + interne Notizen */
(function(){
  var $=function(id){return document.getElementById(id);};
  var tabbar=$('ci-tabbar'); if(!tabbar) return;
  var panes={ buchung:$('pane-buchung'), notizen:$('pane-notizen'), fotos:$('pane-fotos') };
  function esc(s){return String(s==null?'':s).replace(/[&<>"]/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];});}

  // ---- Tab-Slider (horizontal swipen, Touch + Maus). Footer-Tabs bleiben synchron.
  var slider=$('ci-slider'), track=$('ci-track');
  var order=['buchung','notizen','fotos'].filter(function(n){return !!panes[n];});
  var idx=0, notesLoaded=false;
  function paneH(name){ return panes[name]?panes[name].offsetHeight:0; }
  function syncTabs(name){
    var tabs=tabbar.querySelectorAll('.tab'), i;
    for(i=0;i<tabs.length;i++) tabs[i].classList.toggle('active', tabs[i].getAttribute('data-tab')===name);
    for(var k in panes){ if(panes[k]) panes[k].classList.toggle('active', k===name); }
  }
  function setIndex(i, scrollTop){
    i=Math.max(0,Math.min(order.length-1,i)); idx=i; var name=order[i];
    if(track) track.style.transform='translateX(-'+(i*100)+'%)';
    syncTabs(name);
    if(scrollTop && panes[name]) panes[name].scrollTop=0;
    if(name==='notizen' && !notesLoaded){ notesLoaded=true; loadNotes(); }
  }
  function activate(name){ var i=order.indexOf(name); if(i>=0) setIndex(i,true); }
  // App-Shell: Panes scrollen selbst, keine Höhenanpassung nötig (Hook bleibt für Aufrufer ohne Effekt).
  function resizeActive(){}
  window.ciSliderResize=resizeActive;
  tabbar.addEventListener('click', function(e){ var b=e.target.closest('.tab'); if(b) activate(b.getAttribute('data-tab')); });

  // Drag/Swipe via Pointer Events (touch-action:pan-y -> vertikales Scrollen bleibt nativ).
  if(slider && track && order.length>1){
    var sx=0, sy=0, dragging=false, decided=false, didSwipe=false, pid=null;
    slider.addEventListener('pointerdown', function(e){
      if(e.pointerType==='mouse' && e.button!==0) return;
      sx=e.clientX; sy=e.clientY; dragging=true; decided=false; didSwipe=false; pid=e.pointerId;
    });
    slider.addEventListener('pointermove', function(e){
      if(!dragging) return;
      var dx=e.clientX-sx, dy=e.clientY-sy;
      if(!decided){
        if(Math.abs(dx)<7 && Math.abs(dy)<7) return;
        if(Math.abs(dx)<=Math.abs(dy)){ dragging=false; return; }  // vertikal -> nativ scrollen
        decided=true; didSwipe=true;
        track.classList.add('dragging');
        try{ slider.setPointerCapture(pid); }catch(_){}
      }
      var w=slider.offsetWidth||1, pct=dx/w*100, base=-idx*100;
      if((idx===0 && dx>0) || (idx===order.length-1 && dx<0)) pct*=0.35;  // Rand-Widerstand
      track.style.transform='translateX('+(base+pct)+'%)';
      if(e.cancelable) e.preventDefault();
    });
    function endDrag(e){
      if(!dragging) return; dragging=false;
      if(!decided){ return; }
      track.classList.remove('dragging');
      var dx=e.clientX-sx, th=(slider.offsetWidth||1)*0.18, ni=idx;
      if(dx<=-th) ni=idx+1; else if(dx>=th) ni=idx-1;
      setIndex(ni,false);
    }
    slider.addEventListener('pointerup', endDrag);
    slider.addEventListener('pointercancel', function(){ if(dragging&&decided){ track.classList.remove('dragging'); dragging=false; setIndex(idx,false); } else dragging=false; });
    // Klick direkt nach einem Swipe unterdrücken (damit ein Wisch über Button/Thumb nicht auslöst).
    slider.addEventListener('click', function(e){ if(didSwipe){ didSwipe=false; e.stopPropagation(); e.preventDefault(); } }, true);
  }

  // Initiale Badges aus CFG (vor dem ersten Öffnen)
  setNotesBadge(CFG.notesCount||0);
  var tbP=$('ci-tb-photos'); if(tbP){ tbP.textContent=CFG.photosCount||0; tbP.classList.toggle('d-none', !(CFG.photosCount>0)); }

  // ---- Notizen-API
  var API=location.pathname, curNotes=[];
  function npost(params, cb){
    params.b=CFG.b; if(CFG.t)params.t=CFG.t; if(CFG.h)params.h=CFG.h;
    var body=Object.keys(params).map(function(k){return encodeURIComponent(k)+'='+encodeURIComponent(params[k]);}).join('&');
    fetch(API,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded','X-Requested-With':'XMLHttpRequest'},body:body})
      .then(function(r){return r.json();}).then(cb).catch(function(){ cb({ok:false,error:'Netzwerkfehler'}); });
  }
  function setNotesBadge(n){ var tb=$('ci-tb-notes'); if(tb){ tb.textContent=n; tb.classList.toggle('d-none', n===0); } var c=$('ci-nt-count'); if(c){ c.textContent=n; c.classList.toggle('zero', n===0); } }
  // Hervorgehobene Notizen als Endlos-Lauftext im Datenblatt (Buchung-Tab).
  var mqEl=$('ci-marquee'), mqTrack=$('ci-mq-track');
  function setMarquee(texts){
    if(!mqEl||!mqTrack) return;
    var t=(texts||[]).join('   •••   ');
    if(!t){ mqEl.classList.add('d-none'); mqTrack.innerHTML=''; return; }
    mqEl.classList.remove('d-none');
    mqTrack.innerHTML='<span class="ci-mq-seg">'+esc(t)+'</span><span class="ci-mq-seg" aria-hidden="true">'+esc(t)+'</span>';
    mqTrack.style.animationDuration=Math.max(8, Math.round(t.length*0.28))+'s';
  }
  // Anfangs-Lauftext (server-seitig gerendert) -> Dauer passend setzen.
  if(mqEl && !mqEl.classList.contains('d-none') && mqTrack){ var seg0=mqTrack.querySelector('.ci-mq-seg'); if(seg0) setMarquee([seg0.textContent]); }
  function loadNotes(){ npost({action:'notes'}, function(res){ if(res&&res.ok){ renderNotes(res.notes||[]); setMarquee(res.marquee||[]); } }); }
  function renderNotes(notes){
    curNotes=notes; setNotesBadge(notes.length);
    var list=$('ci-nt-list'), empty=$('ci-nt-empty');
    if(empty) empty.classList.toggle('d-none', notes.length>0);
    if(!list) return;
    var h='';
    for(var i=0;i<notes.length;i++){ var n=notes[i];
      h+='<div class="nt-item'+(n.highlight?' nt-hl':'')+'" data-id="'+n.id+'">'
        +(n.highlight?'<span class="nt-hlbadge">★ Hervorgehoben</span>':'')
        +'<div class="nt-item-text">'+esc(n.text).replace(/\n/g,'<br>')+'</div>'
        +'<div class="nt-item-meta">'+esc(n.user)+' · '+esc(n.created)+(n.updated?' · bearbeitet '+esc(n.updated):'')+'</div>'
        +((n.canEdit||n.canDel)?'<div class="nt-item-act">'
            +(n.canEdit?'<button type="button" class="nt-a nt-edit">Bearbeiten</button>':'')
            +(n.canDel?'<button type="button" class="nt-a nt-del">Löschen</button>':'')
          +'</div>':'')
        +'</div>';
    }
    list.innerHTML=h;
    resizeActive();
  }

  // Neue Notiz
  var saveBtn=$('ci-nt-save'), txt=$('ci-nt-text'), err=$('ci-nt-err'), hlAdd=$('ci-nt-hl');
  function showErr(m){ if(err){ err.textContent=m; err.classList.remove('d-none'); } }
  function hideErr(){ if(err) err.classList.add('d-none'); }
  if(saveBtn){ saveBtn.addEventListener('click', function(){
    var v=(txt.value||'').trim(); hideErr();
    if(!v){ showErr('Bitte einen Text eingeben.'); return; }
    saveBtn.disabled=true;
    npost({action:'note_add', text:v, highlight:(hlAdd&&hlAdd.checked)?1:0}, function(res){ saveBtn.disabled=false;
      if(res&&res.ok){ txt.value=''; if(hlAdd) hlAdd.checked=false; loadNotes(); } else showErr((res&&res.error)||'Fehler beim Speichern.'); });
  }); }

  // Bearbeiten / Löschen (Inline)
  var list=$('ci-nt-list');
  if(list){ list.addEventListener('click', function(e){
    var item=e.target.closest('.nt-item'); if(!item) return; var id=item.getAttribute('data-id');
    if(e.target.closest('.nt-del')){ if(!confirm('Diese Notiz löschen?')) return;
      npost({action:'note_del', id:id}, function(res){ if(res&&res.ok) loadNotes(); else alert((res&&res.error)||'Fehler.'); }); return; }
    if(e.target.closest('.nt-edit')){ startEdit(item, id); return; }
    if(e.target.closest('.nt-ecancel')){ renderNotes(curNotes); return; }
    if(e.target.closest('.nt-esave')){ var ta=item.querySelector('.nt-eta'); var v=(ta.value||'').trim();
      if(!v){ alert('Bitte einen Text eingeben.'); return; }
      var eh=item.querySelector('.nt-ehl');
      npost({action:'note_edit', id:id, text:v, highlight:(eh&&eh.checked)?1:0}, function(res){ if(res&&res.ok) loadNotes(); else alert((res&&res.error)||'Fehler.'); }); return; }
  }); }
  function startEdit(item, id){
    var n=null; for(var i=0;i<curNotes.length;i++) if(String(curNotes[i].id)===String(id)) n=curNotes[i];
    if(!n) return;
    item.innerHTML='<textarea class="nt-eta" rows="3" maxlength="4000"></textarea>'
      +'<label class="nt-hl-opt"><input type="checkbox" class="nt-ehl"'+(n.highlight?' checked':'')+'> <span>Hervorheben – Lauftext im Datenblatt</span></label>'
      +'<div class="nt-eactions"><button type="button" class="nt-a nt-ecancel">Abbrechen</button><button type="button" class="nt-a nt-esave">Speichern</button></div>';
    var ta=item.querySelector('.nt-eta'); ta.value=n.text; ta.focus(); resizeActive();
  }
})();

/* ============================================================ Kennzeichen-Herkunft (Modal + lokale DB) */
(function(){
  var $=function(id){return document.getElementById(id);};
  var btn=$('ci-plate-info'), modal=$('ci-plate-modal'), body=$('ci-pl-body'), plate=$('ci-plate');
  if(!btn || !modal) return;
  function esc(s){return String(s==null?'':s).replace(/[&<>"]/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];});}
  function open(){ modal.classList.remove('d-none'); }
  function close(){ modal.classList.add('d-none'); }
  function row(l,v){ return '<div class="pl-row"><span>'+esc(l)+'</span><b>'+esc(v)+'</b></div>'; }
  function render(d){
    if(!d || !d.found){ body.innerHTML='<div class="pl-empty">Zu diesem Kennzeichen liegen keine Daten vor.</div>'; return; }
    var title = d.ort || d.region;
    var h='<div class="pl-head"><span class="pl-code">'+esc(d.code)+'</span>'
        +'<div class="pl-htxt"><div class="pl-region">'+esc(title)+'</div>'
        +'<div class="pl-sub">'+esc(d.state)+' · '+esc(d.countryName)+'</div></div></div>';
    h+='<div class="pl-rows">';
    if(d.ort && d.region.indexOf(d.ort)===0) h+=row('Stadt', d.ort);          // kreisfreie Stadt ("Wuppertal, Stadt")
    else if(d.ort)                           h+=row('Ort', d.ort)+row('Landkreis', d.region);
    else                                     h+=row(d.regionLabel, d.region);
    h+=row(d.stateLabel, d.state)+row('Land', d.countryName)+'</div>';
    if(d.alts && d.alts.length){
      h+='<div class="pl-alt"><span>auch:</span> '+d.alts.map(function(a){ return esc(a.region)+' ('+esc(a.country)+')'; }).join(', ')+'</div>';
    }
    if(d.map) h+='<div class="pl-mapwrap">'+d.map+'</div>';
    body.innerHTML=h;
  }
  btn.addEventListener('click', function(e){
    e.preventDefault(); e.stopPropagation();
    body.innerHTML='<div class="pl-empty">Lädt …</div>'; open();
    var cur=plate?plate.textContent.trim():'';
    var p='action=plateinfo&b='+CFG.b+'&plate='+encodeURIComponent(cur);
    if(CFG.t)p+='&t='+encodeURIComponent(CFG.t); if(CFG.h)p+='&h='+encodeURIComponent(CFG.h);
    fetch(location.pathname,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded','X-Requested-With':'XMLHttpRequest'},body:p})
      .then(function(r){return r.json();}).then(render).catch(function(){ body.innerHTML='<div class="pl-empty">Fehler beim Laden.</div>'; });
  });
  if($('ci-pl-close')) $('ci-pl-close').addEventListener('click', close);
  modal.addEventListener('click', function(e){ if(e.target===modal) close(); });
  document.addEventListener('keydown', function(e){ if(e.key==='Escape' && !modal.classList.contains('d-none')) close(); });
})();
</script>
<style>
#pwi-ov{position:fixed;inset:0;z-index:9000;display:none;flex-direction:column;align-items:center;justify-content:flex-start;
  background:linear-gradient(160deg,#0d2c44 0%,#11436b 60%,#1b6ca8 130%);color:#fff;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:calc(34px + env(safe-area-inset-top,0px)) 22px calc(28px + env(safe-area-inset-bottom,0px));
  font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;}
#pwi-ov.pwi-show{display:flex;}
.pwi-card{width:100%;max-width:430px;margin:auto 0;text-align:center;}
.pwi-icon{width:96px;height:96px;border-radius:22px;box-shadow:0 12px 34px rgba(0,0,0,.32);margin:0 auto 18px;display:block;background:#fff;}
.pwi-name{font-size:25px;font-weight:800;letter-spacing:.2px;}
.pwi-sub{font-size:14.5px;opacity:.82;margin-top:6px;line-height:1.5;}
.pwi-steps{margin:22px 0 6px;text-align:left;background:rgba(255,255,255,.08);border:1px solid rgba(255,255,255,.14);border-radius:16px;padding:16px 16px 6px;}
.pwi-step{display:flex;align-items:flex-start;gap:12px;padding:0 0 14px;}
.pwi-num{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:#fff;color:#0d2c44;font-weight:800;font-size:14px;display:flex;align-items:center;justify-content:center;margin-top:1px;}
.pwi-txt{font-size:14.5px;line-height:1.5;}
.pwi-txt b{font-weight:800;}
.pwi-ic{display:inline-flex;vertical-align:-5px;margin:0 1px;}
.pwi-ic svg{width:19px;height:19px;}
.pwi-install{display:none;width:100%;margin-top:18px;background:#fff;color:#0d2c44;border:0;border-radius:13px;padding:15px;font-size:16px;font-weight:800;cursor:pointer;-webkit-tap-highlight-color:transparent;}
.pwi-install:active{transform:scale(.98);}
.pwi-install.pwi-show{display:block;}
.pwi-cont{display:inline-block;margin-top:18px;color:#cfe2f2;font-size:14px;font-weight:600;text-decoration:underline;cursor:pointer;background:none;border:0;-webkit-tap-highlight-color:transparent;}
.pwi-hint{font-size:12px;opacity:.6;margin-top:14px;}
</style>
<div id="pwi-ov" role="dialog" aria-label="App installieren">
  <div class="pwi-card">
    <img class="pwi-icon" src="https://seaside.pacim.de/assets/webapp/icon-192.png" alt="" width="96" height="96">
    <div class="pwi-name">Seaside Parking</div>
    <div class="pwi-sub">Für den schnellsten Zugriff diese App zum Startbildschirm hinzufügen – sie öffnet dann im Vollbild wie eine echte App.</div>

    <div class="pwi-steps" id="pwi-ios" style="display:none">
      <div class="pwi-step"><span class="pwi-num">1</span><span class="pwi-txt">Unten in der Safari-Leiste auf das <b>Teilen-Symbol</b>
        <span class="pwi-ic"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M12 16V4M8 8l4-4 4 4"/><path d="M5 12v6a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-6"/></svg></span>
        tippen.</span></div>
      <div class="pwi-step"><span class="pwi-num">2</span><span class="pwi-txt">Im Menü <b>„Zum Home-Bildschirm"</b> wählen.</span></div>
      <div class="pwi-step"><span class="pwi-num">3</span><span class="pwi-txt">Oben rechts auf <b>„Hinzufügen"</b> tippen – fertig.</span></div>
    </div>

    <div class="pwi-steps" id="pwi-android" style="display:none">
      <div class="pwi-step"><span class="pwi-num">1</span><span class="pwi-txt">Oben rechts im Browser auf das <b>Menü</b>
        <span class="pwi-ic"><svg viewBox="0 0 24 24" fill="currentColor"><circle cx="12" cy="5" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="12" cy="19" r="2"/></svg></span>
        tippen.</span></div>
      <div class="pwi-step"><span class="pwi-num">2</span><span class="pwi-txt"><b>„App installieren"</b> bzw. <b>„Zum Startbildschirm hinzufügen"</b> wählen.</span></div>
      <div class="pwi-step"><span class="pwi-num">3</span><span class="pwi-txt">Mit <b>„Installieren"</b> bestätigen – fertig.</span></div>
    </div>

    <div class="pwi-steps" id="pwi-other" style="display:none">
      <div class="pwi-step"><span class="pwi-num">1</span><span class="pwi-txt">Im Browser-Menü <b>„Zum Startbildschirm hinzufügen"</b> bzw. <b>„App installieren"</b> wählen.</span></div>
    </div>

    <button type="button" class="pwi-install" id="pwi-install">App installieren</button>
    <br><button type="button" class="pwi-cont" id="pwi-cont">Im Browser fortfahren</button>
    <div class="pwi-hint">Diese Anleitung erscheint nur im Browser, nicht in der installierten App.</div>
  </div>
</div>
<script>(function(){
  var ov=document.getElementById('pwi-ov'); if(!ov) return;
  var KEY='pwiSkip';
  function standalone(){ return (window.matchMedia&&window.matchMedia('(display-mode: standalone)').matches) || window.navigator.standalone===true; }
  function embedded(){ try{ return window.self!==window.top; }catch(e){ return true; } }
  var skipped=false; try{ skipped=sessionStorage.getItem(KEY)==='1'; }catch(e){}
  if(standalone()||embedded()||skipped) return;

  var ua=navigator.userAgent||'';
  var isIOS=/iphone|ipad|ipod/i.test(ua) || (navigator.platform==='MacIntel' && navigator.maxTouchPoints>1);
  var isAndroid=/android/i.test(ua);
  document.getElementById( isIOS?'pwi-ios':(isAndroid?'pwi-android':'pwi-other') ).style.display='block';

  // Ein-Tipp-Installation, falls der Browser sie anbietet (Chrome/Edge mit erfüllten Kriterien).
  var deferred=null, btn=document.getElementById('pwi-install');
  window.addEventListener('beforeinstallprompt', function(e){ e.preventDefault(); deferred=e; if(btn) btn.classList.add('pwi-show'); });
  if(btn) btn.addEventListener('click', function(){ if(!deferred) return; deferred.prompt(); deferred.userChoice.then(function(c){ deferred=null; btn.classList.remove('pwi-show'); if(c&&c.outcome==='accepted') hide(); }); });
  // Wurde die App während der Sitzung installiert → Overlay weg.
  window.addEventListener('appinstalled', function(){ hide(); });

  function hide(){ ov.classList.remove('pwi-show'); }
  document.getElementById('pwi-cont').addEventListener('click', function(){ try{ sessionStorage.setItem(KEY,'1'); }catch(e){} hide(); });

  ov.classList.add('pwi-show');
})();</script>
</body></html>

Youez - 2016 - github.com/yon3zu
LinuXploit