* { box-sizing: border-box; }
/* Klassen wie .photo-actions setzen display:flex und überstimmen sonst das
   UA-Stylesheet für [hidden] — hidden muss aber immer gewinnen. */
[hidden] { display: none !important; }
body { margin: 0; color: var(--text-strong); background: var(--surface-page); font-family: var(--font-sans); font-size: 15px; }
button, input { font: inherit; }
button { cursor: pointer; }
.app-shell { display: grid; grid-template-columns: 248px 1fr; min-height: 100vh; }
.sidebar { padding: 26px 16px 18px; background: #fff; border-right: 1px solid var(--border-subtle); display:flex; flex-direction:column; }
.brand { display:flex; align-items:center; gap:11px; height:40px; margin:0 10px 52px; }.brand img:first-child{width:30px;height:30px}.brand .wordmark{width:103px;height:auto}
.workspace-label,.eyebrow { margin:0; color:var(--text-faint); font-size:11px; font-weight:700; letter-spacing:.13em; line-height:1.2; }.workspace-label{margin:0 12px 10px}.on-dark{color:#aeb4ff}
nav { display:grid; gap:4px; }.nav-item { display:flex; gap:12px; align-items:center; padding:11px 12px; color:var(--text-muted); border-radius:10px; font-weight:600; text-decoration:none; }.nav-item span { font-size:20px; width:20px; text-align:center; font-weight:400; }.nav-item:hover,.nav-item.active { color:var(--color-brand); background:var(--color-brand-subtle); }.nav-item.active { font-weight:700; }
.sidebar-bottom{margin-top:auto}.help-card{margin:0 8px 18px;padding:16px;border-radius:12px;background:var(--tsh-blue-50);display:grid;gap:3px;color:var(--tsh-blue-800);font-size:12px}.help-card strong{font-size:13px}.profile{width:100%;border:0;background:transparent;border-top:1px solid var(--border-subtle);padding:18px 8px 0;display:flex;text-align:left;align-items:center;gap:10px;color:var(--text-body)}.profile span:nth-child(2){display:grid;gap:2px;font-size:13px}.profile small{color:var(--text-muted)}.profile i{font-style:normal;margin-left:auto}.avatar{display:grid;place-items:center;width:34px;height:34px;border-radius:50%;background:var(--tsh-purple-soft);color:var(--tsh-purple);font-size:12px;font-weight:700}
main{width:min(1240px,calc(100vw - 248px));margin:0 auto;padding:40px 48px 64px}.topbar{display:flex;align-items:end;justify-content:space-between;margin-bottom:32px}.topbar h1{font-family:var(--font-display);font-size:32px;line-height:1.1;letter-spacing:-.02em;margin:8px 0 0}.top-actions,.section-actions{display:flex;align-items:center;gap:10px}.btn{border:0;border-radius:999px;padding:0 18px;height:42px;font-weight:700;transition:all .2s var(--ease-standard)}.btn:hover:not(:disabled){transform:translateY(-1px)}.btn.primary{background:var(--color-brand);color:white}.btn.primary:not(:disabled){box-shadow:var(--shadow-brand)}.btn.primary:hover:not(:disabled){background:var(--color-brand-hover)}.btn.secondary{background:white;color:var(--text-body);border:1px solid var(--border-default)}.btn.ghost{background:transparent;color:var(--color-brand)}.btn.inverse{background:#fff;color:var(--tsh-blue-700);padding:0 19px}.btn.inverse span{margin-left:14px;font-size:18px}.icon-btn{border:1px solid var(--border-subtle);background:white;border-radius:10px;height:42px;width:42px;position:relative;color:var(--text-body);font-size:19px}.icon-btn b{position:absolute;right:-5px;top:-6px;background:var(--tsh-danger);color:white;width:16px;height:16px;display:grid;place-items:center;border-radius:20px;font-size:10px}
/* Gesperrte Knöpfe sollen gesperrt aussehen. Was nur im bedienbaren Zustand gilt
   — Hover-Lift, Brand-Schatten, Hover-Farbe —, trägt oben ein :not(:disabled) und
   greift am gesperrten Knopf gar nicht erst.
   Die frühere Fassung verließ sich stattdessen auf die Quellreihenfolge: bei
   gleicher Spezifität (0,2,0) hätte jede später angehängte .btn-Regel den Fix
   stillschweigend wieder aufgehoben, und gegen .btn.primary:hover (0,3,0) brauchte
   es ohnehin eine eigene Gegenregel.
   Gedämpft wird über opacity statt über eine graue Ersatzfarbe, damit jede Variante
   (primary, secondary, ghost, inverse) ohne eigene Regel mitkommt. Die
   Hintergrundfarbe behält der gesperrte Knopf — sie steht in .btn.primary und nicht
   in der :not(:disabled)-Regel. */
.btn:disabled{opacity:.45;cursor:not-allowed}
.hero{overflow:hidden;position:relative;border-radius:18px;background:var(--tsh-gradient-hero);padding:22px 28px;color:white;box-shadow:var(--shadow-lg);margin-bottom:20px}.hero-content{position:relative;z-index:1;width:72%}.hero-summary{font-family:var(--font-display);font-size:21px;line-height:1.25;letter-spacing:-.02em;margin:6px 0 0}.swirl{position:absolute;width:220px;right:-24px;top:-64px;opacity:.85}
/* Statusfilter. Ein abgewählter Chip bleibt stehen und wird nur blass — die Zahl
   soll lesbar bleiben und der Weg zurück sichtbar sein. Deshalb auch keine
   Farbe auf abgewählten Chips: Farbe heißt hier „wird angezeigt". */
.status-filter{display:flex;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:18px}.status-chip{display:inline-flex;align-items:center;gap:8px;border:1px solid var(--border-default);background:white;border-radius:999px;padding:5px 14px 5px 6px;font:inherit;font-size:12px;font-weight:700;color:var(--text-muted);cursor:pointer;transition:opacity .18s var(--ease-standard),border-color .18s var(--ease-standard)}.status-chip:hover{border-color:var(--border-strong)}.status-chip-count{display:grid;place-items:center;min-width:23px;height:23px;padding:0 6px;border-radius:999px;background:var(--surface-sunken);color:var(--text-faint);font-size:11px}.status-chip[aria-pressed="true"]{color:var(--text-strong)}.status-chip[aria-pressed="false"]{opacity:.45}.status-chip[aria-pressed="true"].missing .status-chip-count{background:var(--tsh-gold-soft);color:var(--tsh-warning)}.status-chip[aria-pressed="true"].expected .status-chip-count{background:var(--tsh-blue-50);color:var(--color-brand)}.status-chip[aria-pressed="true"].checked .status-chip-count{background:var(--tsh-success-soft);color:var(--tsh-success)}
.table-empty{color:var(--text-muted);font-size:13px;text-align:center;padding:26px 12px}
.panel{background:white;border:1px solid var(--border-subtle);border-radius:16px;box-shadow:var(--shadow-xs);padding:26px 28px}.section-head{display:flex;justify-content:space-between;align-items:end;margin-bottom:20px}.section-head h2{font-family:var(--font-display);font-size:22px;letter-spacing:-.02em;margin:7px 0 0}.search{height:40px;min-width:205px;display:flex;align-items:center;gap:7px;padding:0 12px;border:1px solid var(--border-default);border-radius:10px;color:var(--text-faint)}.search input{border:0;outline:0;width:100%;font-size:13px}.table-wrap{overflow-x:auto}table{border-collapse:collapse;width:100%;min-width:700px}th{text-align:left;color:var(--text-faint);font-size:11px;letter-spacing:.08em;text-transform:uppercase;padding:0 12px 11px;font-weight:700}.th-sort{display:inline-flex;align-items:center;gap:5px;background:transparent;border:0;padding:0;font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit;cursor:pointer}.th-sort:hover{color:var(--color-brand)}.th-sort::after{content:"↕";font-size:9px;opacity:.4}th[aria-sort="ascending"] .th-sort,th[aria-sort="descending"] .th-sort{color:var(--color-brand)}th[aria-sort="ascending"] .th-sort::after{content:"▲";opacity:1}th[aria-sort="descending"] .th-sort::after{content:"▼";opacity:1}td{border-top:1px solid var(--border-subtle);padding:14px 12px;color:var(--text-body);font-size:13px}.person{display:flex;align-items:center;gap:10px}.person .avatar{width:36px;height:36px;background:var(--tsh-blue-50);color:var(--color-brand);flex:none}.avatar.photo{object-fit:cover;background:var(--surface-sunken)}.person b{display:block;font-size:14px}.person small{color:var(--text-muted);font-size:12px}.visit-title{font-weight:600}.visit-sub{display:block;color:var(--text-muted);font-size:12px;margin-top:2px}.status{display:inline-flex;align-items:center;gap:6px;border-radius:999px;padding:5px 9px;font-size:11px;font-weight:700}.status::before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}.status.expected{background:var(--tsh-blue-50);color:var(--color-brand)}.status.checked{background:var(--tsh-success-soft);color:var(--tsh-success)}.status.missing{background:var(--tsh-gold-soft);color:var(--tsh-warning)}.status.done{background:var(--surface-sunken);color:var(--text-muted)}
/* Statuszelle: Pille (öffnet das Menü) und häufigste Aktion nebeneinander,
   Begründung darunter. Eine Spalte statt zwei — die alte Aktionsspalte stand
   bei ausgecheckten Besuchern leer und riss die Zeile auseinander. */
/* Ein einziges Bedienelement je Zeile: die Pille ist der Status *und* der Weg,
   ihn zu ändern. Deshalb ein dauerhafter Rahmen — ohne ihn liest sich die Pille
   als Etikett und niemand klickt darauf. */
.status-cell{position:relative}th:first-child,td.status-cell{width:212px}button.status{border:1px solid var(--border-default);cursor:pointer;font:inherit;font-size:11px;font-weight:700;padding:6px 10px;white-space:nowrap}button.status:hover{border-color:currentColor}button.status:focus-visible{outline:2px solid var(--focus-ring);outline-offset:1px}button.status i{font-style:normal;font-size:12px;line-height:0;opacity:.6;margin-left:2px}.status-detail{display:block;color:var(--text-muted);font-size:11px;line-height:1.35;margin-top:5px}
/* Das Menü liegt als Popover im Top-Layer — sonst würde .table-wrap
   (overflow-x:auto) es unten abschneiden. Position setzt app.js. */
.row-menu{position:fixed;margin:0;inset:auto;width:292px;border:1px solid var(--border-subtle);border-radius:14px;box-shadow:var(--shadow-xl);background:white;padding:7px}.row-menu:popover-open{display:grid;gap:1px}.row-menu::backdrop{background:transparent}/* Kapitälchen statt text-transform:uppercase. text-transform ändert die gerenderte Schreibweise (innerText, Vorlesesoftware): die Abschnittsmarken hießen dort „VORAUSSETZUNGEN", „STAMMDATEN" und so fort und waren in ihrer geschriebenen Form nicht mehr wiederzufinden. Kapitälchen lassen den Text der Seite den geschriebenen sein. Optisch ist das kein Nulltausch — Kapitälchen sind niedriger als Versalien —, und es betrifft alle fünf Überschriften des Zeilenmenüs. */.row-menu-head{margin:7px 9px 4px;color:var(--text-faint);font-size:10px;letter-spacing:.08em;font-variant-caps:all-small-caps;font-weight:700}.row-menu-head:first-child{margin-top:3px}.row-menu button,.row-menu-off{display:flex;align-items:center;gap:9px;width:100%;border:0;background:transparent;border-radius:9px;padding:9px 10px;font:inherit;font-size:13px;text-align:left;color:var(--text-body)}.row-menu button{cursor:pointer}.row-menu button:hover{background:var(--surface-sunken)}.row-menu button,.row-menu-off{white-space:nowrap}.row-menu-off{color:var(--text-faint)}.row-menu-off small{margin-left:auto;padding-left:14px;font-size:11px}.row-menu-off b{font-size:12px;color:var(--tsh-success)}.row-menu .dot{width:7px;height:7px;border-radius:50%;flex:none;background:var(--text-faint)}.row-menu .dot.missing{background:var(--tsh-warning)}.row-menu .dot.expected{background:var(--color-brand)}.row-menu .dot.checked{background:var(--tsh-success)}.row-menu .dot.done{background:var(--border-strong)}
.filter-reset{background:transparent;border:0;color:var(--color-brand);font-weight:700;font-size:12px;padding:0;cursor:pointer}.filter-reset:hover{text-decoration:underline}.filter-count{color:var(--text-muted);font-size:12px}
.modal{border:0;padding:0;border-radius:22px;box-shadow:var(--shadow-xl);width:min(620px,calc(100% - 32px))}.modal::backdrop{background:rgba(11,14,26,.52);backdrop-filter:blur(3px)}.modal form{padding:30px}.modal-head{display:flex;justify-content:space-between;align-items:start}.modal h2{font-family:var(--font-display);margin:6px 0 0;font-size:25px;letter-spacing:-.02em}.close{border:0;background:var(--surface-sunken);border-radius:50%;font-size:24px;line-height:1;width:32px;height:32px;color:var(--text-muted)}.modal-intro{color:var(--text-muted);font-size:14px;line-height:1.45;margin:18px 0 22px}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:15px}.form-grid label{display:grid;gap:7px;color:var(--text-body);font-size:12px;font-weight:700}.form-grid .wide{grid-column:span 2}.form-grid input{height:42px;border:1px solid var(--border-default);border-radius:10px;padding:0 12px;color:var(--text-strong);outline:0;font-size:14px}.form-grid input:focus{border-color:var(--color-brand);box-shadow:var(--shadow-focus)}.check{display:flex;gap:9px;align-items:flex-start;margin-top:20px;color:var(--text-body);font-size:13px}.check input{accent-color:var(--color-brand);margin-top:2px}.modal-actions{display:flex;justify-content:flex-end;gap:7px;margin-top:27px}.toast{position:fixed;right:24px;bottom:24px;background:var(--tsh-ink);color:white;border-radius:12px;box-shadow:var(--shadow-lg);padding:14px 17px;font-size:14px;transform:translateY(100px);opacity:0;transition:.25s var(--ease-out)}.toast.show{transform:translateY(0);opacity:1}
.form-hint{margin:18px 0 0;color:var(--text-muted);font-size:12px;line-height:1.5}/* Foto im Bearbeiten-Dialog. `:not([hidden])` statt eines pauschalen display, weil app.js den Block über das hidden-Attribut ein- und ausblendet. */.edit-photo:not([hidden]){display:flex;align-items:center;gap:14px;margin-top:18px}.edit-photo img{width:56px;height:56px;border-radius:12px;object-fit:cover;border:1px solid var(--border-subtle);background:var(--surface-sunken)}.guest-page{min-height:100vh;display:grid;place-items:center;padding:24px;background:linear-gradient(135deg,var(--tsh-blue-50),var(--surface-page) 55%)}.guest-card{width:min(560px,100%);background:white;border:1px solid var(--border-subtle);border-radius:22px;box-shadow:var(--shadow-lg);padding:32px}.guest-brand{margin:0 0 38px}.guest-content h1{font-family:var(--font-display);letter-spacing:-.025em;font-size:34px;line-height:1.08;margin:9px 0 13px}.guest-copy{color:var(--text-muted);line-height:1.55;margin:0}.visit-summary{display:grid;grid-template-columns:100px 1fr;gap:8px 12px;margin:26px 0;padding:18px;border-radius:12px;background:var(--surface-sunken);font-size:13px}.visit-summary span{color:var(--text-muted)}.instruction{border:1px solid var(--border-subtle);border-radius:12px;overflow:hidden}.instruction summary{padding:15px 16px;font-weight:700;cursor:pointer;display:flex;justify-content:space-between}.instruction div{border-top:1px solid var(--border-subtle);padding:4px 16px 10px;color:var(--text-muted);font-size:13px;line-height:1.5}.guest-check{margin-top:20px}.wide-button{width:100%;margin-top:21px}.wallet-preview{display:grid;gap:9px;margin:28px 0 12px;padding:25px;border-radius:18px;background:var(--tsh-gradient-hero);color:white;min-height:170px;box-shadow:var(--shadow-brand)}.wallet-preview b{font-family:var(--font-display);font-size:25px;margin-top:auto}.wallet-preview small{color:#cbd0ff}

/* ---- Digitaler Besucherausweis (Wallet-Karte) ---- */
.pass-card{position:relative;overflow:hidden;margin:26px 0 8px;border-radius:22px;background:var(--tsh-gradient-hero);color:#fff;box-shadow:var(--shadow-xl);padding:24px 24px 22px}
.pass-card::after{content:"";position:absolute;right:-70px;top:-90px;width:230px;height:230px;border-radius:50%;background:radial-gradient(circle at 40% 40%,rgba(147,155,255,.55),transparent 62%);pointer-events:none}
.pass-top{display:flex;align-items:center;justify-content:space-between;position:relative;z-index:1}
.pass-brand{display:flex;align-items:center;gap:9px;font-weight:700;letter-spacing:.14em;font-size:12px;color:#cfd3ff}.pass-brand img{width:22px;height:22px}
.pass-state{font-size:11px;font-weight:700;letter-spacing:.06em;padding:5px 10px;border-radius:999px;display:inline-flex;align-items:center;gap:6px}
.pass-state::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.pass-state.active{background:rgba(31,157,91,.22);color:#7ff0b4}
.pass-state.pending{background:rgba(245,179,0,.2);color:#ffd66b}
.pass-state.expired,.pass-state.revoked{background:rgba(210,49,70,.22);color:#ff9aa8}
.pass-name{font-family:var(--font-display);font-size:30px;line-height:1.05;letter-spacing:-.02em;margin:22px 0 3px;position:relative;z-index:1}
.pass-company{color:#c3c8ff;font-size:14px;position:relative;z-index:1}
.pass-fields{display:grid;grid-template-columns:1fr 1fr;gap:16px 12px;margin:24px 0 22px;position:relative;z-index:1}
.pass-fields div{display:grid;gap:3px}.pass-fields span{font-size:10px;letter-spacing:.1em;color:#9aa1e6;font-weight:700}.pass-fields b{font-size:14px;font-weight:600}
.pass-qr{position:relative;z-index:1;background:#fff;border-radius:16px;padding:16px;display:grid;place-items:center}
.pass-qr svg{width:190px;height:190px;display:block}
.pass-qr-hint{text-align:center;font-size:12px;color:#b7bcff;margin:12px 0 0;position:relative;z-index:1}
.pass-locked{position:relative;z-index:1;text-align:center;padding:24px 12px;color:#c3c8ff}
.pass-locked b{display:block;font-family:var(--font-display);font-size:18px;color:#fff;margin-bottom:6px}
.add-actions{display:grid;gap:10px;margin-top:18px}
.btn.wallet-add{background:#0b0e1a;color:#fff;display:flex;align-items:center;justify-content:center;gap:9px;height:52px}
/* Nur die abweichende Deckkraft: cursor, Lift und Schatten kommen aus
   .btn:disabled. Ein eigenes cursor:default hier hätte die globale Regel
   (0,2,0) überstimmt und den Wallet-Knopf als einzigen ohne not-allowed
   stehen lassen. */
.btn.wallet-add:disabled{opacity:.55}
.pass-refresh{background:transparent;border:0;color:var(--text-muted);font-size:12px;font-weight:600;padding:6px}

/* ---- Foto-Aufnahme-Widget ---- */
/* Das Overlay ist ein modaler <dialog> (siehe photo.js / signature.js), damit es
   auch über einem bereits offenen Dialog bedienbar bleibt — showModal() macht
   alles außerhalb des obersten Dialogs inert. Deshalb die Dialog-Vorgaben des
   Browsers zurücksetzen (Rahmen, auto-Ränder, fit-content), und display erst im
   offenen Zustand setzen, sonst überstimmt es das display:none für geschlossene
   Dialoge. */
.photo-overlay{position:fixed;inset:0;width:100%;height:100%;max-width:none;max-height:none;margin:0;border:0;z-index:100;background:rgba(11,14,26,.55);backdrop-filter:blur(3px);padding:18px}
.photo-overlay[open]{display:grid;place-items:center}
.photo-overlay::backdrop{background:transparent}
.photo-modal{width:min(440px,100%);background:#fff;border-radius:20px;box-shadow:var(--shadow-xl);padding:20px}
.photo-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.photo-head strong{font-family:var(--font-display);font-size:19px}
.photo-close{border:0;background:var(--surface-sunken);border-radius:50%;width:30px;height:30px;font-size:20px;line-height:1;color:var(--text-muted)}
.photo-stage{position:relative;aspect-ratio:1;border-radius:16px;overflow:hidden;background:var(--tsh-ink)}
/* Unterschriftfeld (signature.js). touch-action:none ist Pflicht — ohne das
   scrollt der Finger die Seite, statt zu zeichnen. Die Linie darunter zeigt,
   wo unterschrieben wird, ohne Teil des gespeicherten Bildes zu sein. */
.sign-pad{position:relative;border:1px dashed var(--border-strong);border-radius:14px;background:var(--tsh-gray-50);overflow:hidden}
.sign-canvas{display:block;width:100%;touch-action:none;cursor:crosshair}
.sign-baseline{position:absolute;left:9%;right:9%;bottom:26%;border-bottom:1px solid var(--border-default);pointer-events:none}
/* Gruppenempfang (group.js) */
.group-modal{width:min(680px,calc(100% - 32px));padding:30px}
/* Rückfrage-Dialog (mitRueckfrage in app.js). Schmaler als die Formulardialoge und mit eigenem Innenabstand, weil `.modal form` hier nichts polstert — er trägt kein Formular. */
.confirm-modal{width:min(460px,calc(100% - 32px));padding:28px}
.group-names{display:grid;gap:7px;margin-top:16px;color:var(--text-body);font-size:12px;font-weight:700}
.group-names textarea{border:1px solid var(--border-default);border-radius:10px;padding:11px 12px;font:inherit;font-size:14px;font-weight:400;color:var(--text-strong);resize:vertical;outline:0}
.group-names textarea:focus{border-color:var(--color-brand);box-shadow:var(--shadow-focus)}
.group-preview{margin-top:14px}
.group-preview-head{margin:0 0 8px;color:var(--text-muted);font-size:12px}
.group-preview ul{list-style:none;margin:0;padding:0;display:grid;gap:5px}
.group-preview li{display:flex;align-items:center;gap:8px;padding:8px 11px;border-radius:9px;background:var(--surface-sunken);font-size:13px}
.group-preview li.broken{background:var(--tsh-danger-soft);color:var(--tsh-danger)}
.group-preview li small{margin-left:auto;font-size:11px}
.group-error{margin:0 0 11px;padding:10px 12px;border-radius:9px;background:var(--tsh-danger-soft);color:var(--tsh-danger);font-size:13px}
.group-instruction{display:grid;gap:15px;max-height:46vh;overflow-y:auto;padding:18px 20px;border:1px solid var(--border-subtle);border-radius:14px;background:var(--surface-sunken)}
.group-instruction h3{margin:0 0 5px;font-size:14px;color:var(--text-strong)}
.group-instruction p{margin:0;font-size:13px;line-height:1.55;color:var(--text-body)}
.group-steps{display:grid;gap:10px;margin:20px 0}
.group-step{display:flex;align-items:center;gap:13px;width:100%;padding:15px 16px;border:1px solid var(--border-default);border-radius:13px;background:white;font:inherit;text-align:left;cursor:pointer}
.group-step:hover{border-color:var(--color-brand)}
.group-step span:nth-child(2){display:grid;gap:2px}
.group-step b{font-size:14px;color:var(--text-strong)}
.group-step small{color:var(--text-muted);font-size:12px}
.group-step-mark{display:grid;place-items:center;width:30px;height:30px;flex:none;border-radius:50%;background:var(--surface-sunken);color:var(--text-muted);font-size:13px;font-weight:700}
.group-step-mark.done{background:var(--tsh-success-soft);color:var(--tsh-success)}
.group-links{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:6px}
.group-links li{display:flex;align-items:center;gap:10px;padding:11px 13px;border-radius:10px;background:var(--surface-sunken);font-size:13px}
.group-links a,.group-links small{margin-left:auto;font-weight:700;color:var(--color-brand)}
.group-links small{color:var(--text-faint);font-weight:400}
.group-tag{display:inline-block;margin-top:3px;padding:2px 7px;border-radius:999px;background:var(--tsh-purple-soft);color:var(--tsh-purple);font-size:10px;font-weight:700}
.photo-video,.photo-preview{width:100%;height:100%;object-fit:cover;display:block}
.photo-hint{font-size:13px;color:var(--text-muted);line-height:1.5;margin:12px 0}
.photo-actions{display:flex;gap:10px}.photo-actions .btn{flex:1;height:46px}
.photo-confirm{margin-top:2px}

/* Ausweis-Ansicht im Empfang (ausweis.js): schmaler als die Formulardialoge,
   weil darin nur die Ausweiskarte steht — dieselbe wie auf dem Gerät des Gastes. */
.pass-modal{width:min(480px,calc(100% - 32px));padding:30px}
/* ---- Foto auf dem Ausweis ---- */
.pass-photo{position:absolute;top:20px;right:20px;z-index:2;width:64px;height:64px;border-radius:50%;object-fit:cover;border:2px solid rgba(255,255,255,.55);box-shadow:0 4px 14px rgba(0,0,0,.28)}
.pass-top{padding-right:76px}

/* ---- Foto beim Zutritts-Scan ---- */
.scan-photo{width:96px;height:96px;border-radius:50%;object-fit:cover;margin:0 auto 10px;display:block;border:3px solid currentColor}

/* ---- Foto-Schritt bei der Bestätigung ---- */
.photo-step{display:flex;align-items:center;gap:14px;margin-top:20px;padding:14px;border:1px solid var(--border-subtle);border-radius:12px}
.photo-thumb{width:52px;height:52px;border-radius:50%;object-fit:cover;background:var(--surface-sunken);flex-shrink:0}
.photo-thumb.empty{display:grid;place-items:center;color:var(--text-faint);font-size:22px}
.photo-step-text{flex:1;font-size:13px;color:var(--text-muted)}
.photo-step-text b{display:block;color:var(--text-body);font-size:14px;margin-bottom:2px}
.photo-step .btn{height:40px;white-space:nowrap}

/* ---- Testmodus: Bestätigungslink ---- */
.dev-link{position:fixed;left:24px;bottom:24px;z-index:50;max-width:min(440px,calc(100vw - 48px));background:#fff;border:1px solid var(--border-default);border-left:4px solid var(--tsh-gold);border-radius:12px;box-shadow:var(--shadow-lg);padding:14px 16px}
.dev-link-head{display:flex;align-items:center;justify-content:space-between;gap:12px}
.dev-link-head span{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--tsh-warning)}
.dev-link-head button{border:0;background:var(--surface-sunken);border-radius:50%;width:24px;height:24px;font-size:16px;line-height:1;color:var(--text-muted)}
.dev-link p{margin:8px 0 6px;font-size:13px;color:var(--text-body)}
.dev-link a{display:block;font-size:12px;color:var(--color-brand);word-break:break-all;text-decoration:none}
.dev-link a:hover{text-decoration:underline}

/* ---- Scanner ---- */
.scan-wrap{display:grid;gap:18px;margin-top:22px}
.scan-video{width:100%;aspect-ratio:1;background:var(--tsh-ink);border-radius:18px;object-fit:cover}
.scan-result{border-radius:16px;padding:22px;text-align:center;font-weight:700;font-size:18px;display:none}
.scan-result.granted{display:block;background:var(--tsh-success-soft);color:var(--tsh-success)}
.scan-result.denied{display:block;background:var(--tsh-danger-soft);color:var(--tsh-danger)}
.scan-result small{display:block;font-weight:500;font-size:13px;margin-top:6px;color:var(--text-muted)}
.scan-manual{display:flex;gap:8px}.scan-manual input{flex:1;height:44px;border:1px solid var(--border-default);border-radius:10px;padding:0 12px;font-size:14px;outline:0}
@media (max-width:900px){.app-shell{grid-template-columns:1fr}.sidebar{display:none}main{width:100%;padding:26px 22px}.hero-content{width:70%}.metrics{grid-template-columns:1fr}.section-head{align-items:start;gap:15px;flex-direction:column}.hero-stats{right:25px}.swirl{right:-125px}}@media(max-width:560px){.topbar{align-items:start;gap:18px;flex-direction:column}.top-actions{width:100%;justify-content:space-between}.hero{padding:28px 24px}.hero-content{width:100%}.hero h2{font-size:32px}.swirl{opacity:.25}.hero-stats{position:static;margin-top:25px}.panel{padding:22px 16px}.section-actions{width:100%}.search{flex:1}.btn.secondary{display:none}.form-grid{grid-template-columns:1fr}.form-grid .wide{grid-column:auto}}

/* ---- Sammelimport mehrerer Besucher ---- */
.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.import-modal{width:min(1080px,calc(100% - 32px));padding:30px;max-height:calc(100vh - 48px)}
.import-tabs{display:flex;gap:6px;padding:4px;background:var(--surface-sunken);border-radius:12px}
.import-tab{border:0;background:transparent;border-radius:9px;height:36px;padding:0 16px;font-size:13px;font-weight:700;color:var(--text-muted)}
.import-tab.active{background:#fff;color:var(--color-brand);box-shadow:var(--shadow-xs)}
.import-panel{margin-top:18px}
.import-panel .form-hint{margin-top:10px}
.import-panel-actions{display:flex;justify-content:flex-end;margin-top:12px}
.import-drop{display:flex;align-items:center;gap:14px;padding:16px 18px;border:1px dashed var(--border-default);border-radius:12px;cursor:pointer}
.import-drop:hover{border-color:var(--color-brand);background:var(--color-brand-subtle)}
.import-drop:focus-within{border-color:var(--color-brand);box-shadow:var(--shadow-focus)}
.import-file{position:absolute;width:1px;height:1px;opacity:0}
.import-drop-button{border:1px solid var(--border-default);background:#fff;border-radius:999px;height:38px;display:inline-flex;align-items:center;padding:0 17px;font-size:13px;font-weight:700;color:var(--text-body);white-space:nowrap}
.import-drop-name{font-size:13px;color:var(--text-muted);word-break:break-all}
.import-paste{width:100%;border:1px solid var(--border-default);border-radius:12px;padding:12px;font:inherit;font-size:13px;line-height:1.5;color:var(--text-strong);outline:0;resize:vertical}
.import-paste:focus{border-color:var(--color-brand);box-shadow:var(--shadow-focus)}
.import-shared{margin:22px 0 0;border:1px solid var(--border-subtle);border-radius:14px;padding:16px 18px 18px}
.import-shared legend{padding:0 8px;color:var(--text-faint);font-size:11px;font-weight:700;letter-spacing:.13em;text-transform:uppercase}
.import-shared .form-grid{grid-template-columns:repeat(3,1fr)}
.import-shared .form-hint{margin-top:12px}
.import-preview{margin-top:22px;border:1px solid var(--border-subtle);border-radius:14px;overflow:hidden}
.import-preview .table-wrap{max-height:46vh;overflow:auto}
.import-table{min-width:820px}
.import-table th{padding:12px;vertical-align:top;background:var(--surface-sunken);position:sticky;top:0;z-index:1}
.import-table td{padding:6px 8px}
.import-head-label{display:block;margin-bottom:6px}
.import-map{width:100%;max-width:150px;height:30px;border:1px solid var(--border-default);border-radius:8px;background:#fff;font-size:11px;color:var(--text-body);text-transform:none;letter-spacing:0;font-weight:600}
.import-table input[type="text"],.import-table input[type="email"],.import-table input[type="date"],.import-table input[type="time"],.import-table input[type="datetime-local"]{width:100%;min-width:130px;height:36px;border:1px solid var(--border-default);border-radius:8px;padding:0 9px;font-size:13px;color:var(--text-strong);outline:0}
.import-table input:focus{border-color:var(--color-brand);box-shadow:var(--shadow-focus)}
.import-table input.invalid{border-color:var(--tsh-danger);background:rgba(210,49,70,.05)}
.import-table tr.skipped{opacity:.45}
.import-tick{width:34px;text-align:center}
.import-tick input{accent-color:var(--color-brand)}
.import-remove{border:0;background:transparent;color:var(--text-faint);font-size:19px;line-height:1;width:28px;height:28px;border-radius:50%}
.import-remove:hover{background:var(--surface-sunken);color:var(--tsh-danger)}
.import-summary{margin:16px 0 0;font-size:13px;color:var(--text-muted)}
.import-summary.warning{color:var(--tsh-warning);font-weight:600}
.import-result{margin-top:8px}
.import-result h3{font-family:var(--font-display);font-size:21px;letter-spacing:-.02em;margin:14px 0 6px}
.import-result-note{color:var(--text-muted);font-size:13px;line-height:1.5;margin:0}
.import-links{list-style:none;margin:16px 0 0;padding:0;display:grid;gap:10px;max-height:40vh;overflow:auto}
.import-links li{display:grid;gap:3px;padding:11px 13px;border:1px solid var(--border-subtle);border-left:3px solid var(--tsh-gold);border-radius:10px;font-size:12px}
.import-links a{color:var(--color-brand);word-break:break-all}
.mail-warning{display:inline-block;margin-left:6px;color:var(--tsh-danger);font-size:12px;cursor:help}

/* ---- Fotos für mehrere Besucher zuordnen ---- */
.photo-assign{width:min(760px,100%);max-height:calc(100vh - 48px);overflow:auto}
.photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:14px;margin:16px 0}
.photo-tile{margin:0;display:grid;gap:7px;padding:10px;border:1px solid var(--border-subtle);border-radius:12px}
.photo-tile img{width:100%;aspect-ratio:1;object-fit:cover;border-radius:9px;background:var(--surface-sunken)}
.photo-tile figcaption{font-size:11px;color:var(--text-faint);word-break:break-all}
.photo-tile select{width:100%;height:34px;border:1px solid var(--border-default);border-radius:8px;background:#fff;font-size:12px;color:var(--text-body);padding:0 6px}
.photo-tile-status{font-size:11px;color:var(--text-muted);min-height:14px}
.photo-tile-status.ok{color:var(--tsh-success);font-weight:700}
.photo-tile-status.error{color:var(--tsh-danger);font-weight:700}
