* { box-sizing: border-box; }
/* iOS Dynamic Type: 1rem folgt der System-Textgröße (Einstellungen → Anzeige →
   Textgröße). Auf Nicht-Apple-Systemen ist die Deklaration ungültig und fällt
   auf die 16px-Voreinstellung zurück. Alle Größen hängen in rem/em daran. */
html { font: -apple-system-body; }
body { font-family: system-ui, sans-serif; margin: 0; background: #f5f6f8; color: var(--ink); }
/* Header: feste Höhe als Variable (Sticky-Anker für Tagesüberschriften) + eigene
   Stacking-Ebene, damit Inhalt DARUNTER verschwindet statt drüberzuscrollen.
   In rem, damit Header/Panel-Kopf/Sticky-Offsets mit der Textgröße mitwachsen. */
:root {
  --header-h: 3.75rem;  /* zweizeiliger Header; Sticky-Offsets/Panel-Kopf haengen an DIESER Variable */
  /* Grau-/Akzent-Stufen ZENTRAL (Accessibility-Audit 2026-08-30, Zielgruppe ältere
     Teilnehmer): Fließ-/Metatext ≥ 7:1 (AAA) auf JEDEM vorkommenden Hintergrund
     inkl. dunkelstem Kartentint (#F2EAEC) und Seg-Track (#e4e7ee) — nachgerechnet
     in tests/test_accessibility.py. Hex-Werte NIE lokal hart codieren.
     --ink-faint ist NUR für Dekoratives erlaubt (Chevron, Platzhalter-Rahmen). */
  --ink: #1c2330;        /* Primärtext */
  --ink-muted: #3d455e;  /* Zeitzeile, Überschriften, Untertitel, Segmente (≥7,6:1) */
  --ink-soft: #444d69;   /* Ortsname, Adresse, Datum, Labels, Footer (≥7,0:1) */
  --ink-faint: #9aa1b5;  /* dekorativ — nie für Information */
  --accent-ink: #004E86; /* Unitas-Blau, dunkel genug für TEXT auf allen Tints (≥7,3:1) */
  --action: #1e4aae;     /* gefüllte Controls (Buttons/Banner/Chips): Weiß darauf ≥7,9:1 */
}
header { display: flex; align-items: center; gap: 0.7rem; background: #1c2330; color: #fff;
  padding: 0 1rem; position: sticky; top: 0; height: var(--header-h);
  z-index: 100; flex-wrap: nowrap; }
/* Zweizeiliger Titel: Zeile 1 offizieller Name (semibold), Zeile 2 gedeckt.
   Beide Zeilen einzeilig mit Ellipsis-Fallback fuer sehr schmale Geraete.
   Weiss auf Brand-Blau = 6,05:1 (Maximum — dokumentierte Ausnahme, AA erfuellt). */
.header-title { display: flex; flex-direction: column; justify-content: center;
  flex: 1; min-width: 0; gap: 1px; }
header .brand { font-weight: 600; font-size: 0.95rem; letter-spacing: 0.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
header .subtitle { font-size: 0.78rem; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
main { max-width: 40rem; margin: 0 auto; padding: 0 1rem 3rem; }
h1 { font-size: 1.2rem; }
h2 { font-size: 0.95rem; color: var(--ink-muted); margin: 1.4rem 0 0.4rem; padding: 0.3rem 0; }
/* Nur die Tagesüberschriften der Programmliste sind sticky — direkt UNTER der
   Headerkante, deckender Grund, unter dem Header (z 100), über den Karten */
#program-list h2 { position: sticky; top: var(--header-h); z-index: 5; background: #f5f6f8;
  /* großzügige Luft oben+unten (deckend über die volle Padding-Fläche) + weicher
     unterer Schatten als Abgrenzung; gilt in BEIDEN Zuständen → kein Layout-Sprung */
  padding: 0.65rem 0 0.6rem; margin-bottom: 14px;  /* 8er-Raster-Luft: Schatten läuft frei aus, klebt nicht an der ersten Karte */
  box-shadow: 0 5px 7px -5px rgba(28, 35, 48, 0.22); }
.banner { background: var(--action); color: #fff; padding: 0.6rem 1rem; display: flex; gap: 1rem;
  align-items: center; justify-content: space-between; }
.banner.offline { background: #665012; }
.linklike { background: none; border: none; color: inherit; text-decoration: underline;
  cursor: pointer; font: inherit; padding: 0; }
/* Konto-Bereich: ausgeloggt ein einladender Ghost-Button (bewusst TEXT statt Icon —
   sanfter Anmelde-Push); eingeloggt ein kompaktes Initialen-Icon mit Dropdown.
   Der frei werdende Platz kommt dem Untertitel zugute (weniger Ellipsis). */
.ghost-btn { border: 1px solid rgba(255,255,255,0.75); background: none; color: #fff;
  font: inherit; font-size: 0.9rem; padding: 0.25rem 0.75rem; border-radius: 99px;
  cursor: pointer; white-space: nowrap; }
.account-wrap { position: relative; display: flex; align-items: center; }
.avatar { width: 2.1rem; height: 2.1rem; border-radius: 50%; border: 0;
  background: #fff; color: var(--accent-ink); font: inherit; font-size: 0.85rem;
  font-weight: 700; cursor: pointer; display: flex; align-items: center;
  justify-content: center; }
/* Dropdown wie das Google-Kontomenü: waechst mit dem Inhalt (max-content), bleibt
   rechtsbuendig am Icon und darf nach links wachsen; Deckel ist die Viewport-
   Breite minus Randabstand. Email steht in EINER Zeile, nur Extremfaelle ellipsieren. */
.account-menu { position: absolute; right: 0; top: calc(100% + 0.4rem);
  background: #fff; color: var(--ink); border: 1px solid #dfe3ea; border-radius: 10px;
  box-shadow: 0 6px 18px rgba(28,35,48,0.18); width: max-content; min-width: 12rem;
  max-width: calc(100vw - 2rem); padding: 0.35rem; z-index: 150; }
.account-id { display: flex; align-items: center; gap: 0.65rem;
  padding: 0.6rem 0.75rem; border-bottom: 1px solid #e6e9f0; margin-bottom: 0.25rem; }
/* Menue-Avatar: groesser als im Header, gefuellt (auf weissem Grund waere die
   weisse Header-Kachel unsichtbar); Weiss auf --accent-ink = 7,98:1 (AAA) */
.account-id .avatar { width: 2.6rem; height: 2.6rem; font-size: 1rem; flex: none;
  background: var(--accent-ink); color: #fff; cursor: default; }
.account-id-text { display: flex; flex-direction: column; gap: 0.1rem; min-width: 0; }
.account-id-text strong { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.account-id-text span { color: var(--ink-soft); font-size: 0.85rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.menu-item { display: block; width: 100%; text-align: left; border: 0; background: none;
  font: inherit; padding: 0.6rem 0.75rem; border-radius: 7px; cursor: pointer;
  color: var(--ink); }
.menu-item:active { background: #eef3f8; }
.toolbar { display: flex; align-items: center; gap: 0.8rem; }
.toolbar h1 { flex: 1; }
.chip { border: 1px solid var(--accent-ink); color: var(--accent-ink); background: #fff; border-radius: 99px;
  padding: 0.25rem 0.8rem; font: inherit; font-size: 0.85rem; cursor: pointer; }
.chip.active { background: var(--action); color: #fff; }
.event { background: #fff; border: 1px solid #e0e3ea; border-radius: 10px; padding: 0.7rem 0.9rem;
  margin-bottom: 0.6rem; }
.event .time { font-size: 0.85rem; color: var(--ink-muted); }
.event .title { font-weight: 600; margin: 0.15rem 0; }
.event .loc { font-size: 0.85rem; color: var(--ink-soft); }
.event .desc { font-size: 0.9rem; margin-top: 0.3rem; white-space: pre-line; }
.event.cancelled { opacity: 0.75; }
.event.cancelled .title { text-decoration: line-through; }
.badge { display: inline-block; font-size: 0.75rem; border-radius: 99px; padding: 0.1rem 0.55rem;
  margin-left: 0.4rem; vertical-align: middle; }
.badge.cancelled { background: #f7dcdc; color: #7a1d1d; }
.badge.mine { background: #d9f0dd; color: #155323; }
.badge.cat { background: #e4e9f2; color: var(--ink-muted); }
.badge.open { background: #fdf1d7; color: #664b0e; }
/* Karten-Redesign: Kategorie = getönte FLÄCHE (10 %-Ton, inline aus der Payload),
   Titelzeile pillenfrei; Statusinfos leben in der bedingten Fußzeile */
.starts-soon { color: var(--accent-ink); font-weight: 600; }
.card-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem;
  margin-top: 0.45rem; }
.card-foot .foot-status { margin-left: auto; }  /* Teilnehmer-Status rechtsbündig */
.muted { color: var(--ink-soft); font-size: 0.9rem; }
input[type=email], .plain-input { width: 100%; padding: 0.6rem; border: 1px solid #c4cad6;
  border-radius: 6px; font: inherit; margin-bottom: 0.6rem; }
button[type=submit] { width: 100%; padding: 0.6rem; border: 0; border-radius: 6px;
  background: var(--action); color: #fff; font: inherit; cursor: pointer; }
.primary-action { display: block; width: 100%; padding: 0.7rem; margin: 0.2rem 0 1rem; border: 0;
  border-radius: 8px; background: var(--action); color: #fff; font: inherit; font-weight: 600; cursor: pointer; }
#scan-video-wrap { border-radius: 10px; overflow: hidden; border: 1px solid #dfe3ea; background: #000; }
#scan-video { display: block; width: 100%; max-height: 60vh; object-fit: cover; }
.app-footer { text-align: center; color: var(--ink-soft); font-size: 0.75rem; padding: 1rem 0 1.5rem; }
/* Guard: hidden-Attribut muss IMMER gewinnen — Author-display-Regeln (flex/block auf
   .banner, .primary-action, …) überstimmen sonst die UA-Regel [hidden]{display:none}. */
[hidden] { display: none !important; }
.badge.checkedin { background: #155323; color: #fff; }
/* ---- Meldungs-System: EINE Familie, zwei Gewichte — Stufe 1 kompakt/flüchtig,
        Stufe 2 präsent/quittierbar (nahezu volle Breite wie die Programmkarten) ---- */
.notify-stack { position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(1rem + env(safe-area-inset-bottom, 0px));  /* über der Home-Indicator-Zone */
  z-index: 250; display: flex; flex-direction: column; gap: 0.5rem;
  align-items: center; width: calc(100vw - 2rem); max-width: 38rem; }
.notify { display: flex; align-items: center; gap: 0.65rem; background: #fff;
  color: var(--ink); border: 1px solid #dfe3ea; border-radius: 12px;
  padding: 0.7rem 0.9rem; box-shadow: 0 8px 24px rgba(28,35,48,0.25);
  font-size: 0.95rem; max-width: 100%; cursor: pointer;
  opacity: 0; transform: translateY(0.7rem);
  transition: opacity 0.25s ease, transform 0.25s ease; }
.notify.in { opacity: 1; transform: translateY(0);
  animation: notify-in 0.32s ease-out; }        /* Slide-up mit spürbarem Mini-Overshoot */
.notify.out { opacity: 0; transform: translateY(0.7rem); }
/* Icon im GEFÜLLTEN Kreis-Chip: weißes Symbol auf Unitas-Blau (Token, 7,98:1) */
.notify-icon { flex: none; width: 1.7rem; height: 1.7rem; border-radius: 50%;
  background: var(--accent-ink); color: #fff; font-weight: 700; font-size: 0.95rem;
  display: flex; align-items: center; justify-content: center; }
.notify-text { font-weight: 600; min-width: 0; }
.notify-info { width: max-content; }            /* Stufe 1: gleicher Stil, kompakter */
/* Stufe 2: Akzentleiste links als Kennung, kräftige Elevation, einmaliges sanftes
   Aufleuchten nach dem Erscheinen; bleibt bis zum Antippen (✕ nur als Signal —
   die ganze Karte schließt) */
.notify-important { width: 100%; border-left: 3px solid var(--accent-ink);
  box-shadow: 0 12px 32px rgba(28,35,48,0.32); padding: 0.85rem 1rem; }
.notify-important.in { animation: notify-in 0.32s ease-out,
  notify-glow 1.1s ease 0.45s 1; }
.notify-x { flex: none; margin-left: auto; color: var(--ink-soft);
  font-size: 1.05rem; padding: 0.1rem 0.2rem; }
@keyframes notify-in {
  0% { opacity: 0; transform: translateY(0.9rem); }
  70% { opacity: 1; transform: translateY(-3px); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes notify-glow {
  0%, 100% { box-shadow: 0 12px 32px rgba(28,35,48,0.32); }
  50% { box-shadow: 0 12px 36px rgba(0,101,174,0.6); }
}
/* ---- Stufe 3: Takeover — Vollbild-Moment in Brand-Blau mit animiertem ✓ ---- */
.takeover { position: fixed; inset: 0; z-index: 400; background: #0065AE; color: #fff;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.3rem; text-align: center; padding: 2rem; cursor: pointer; }
.takeover-logo { height: 4.5rem; width: auto; background: #fff; border-radius: 12px;
  padding: 0.5rem 0.7rem; }
.takeover-check svg { width: 6.5rem; height: 6.5rem; }
.takeover-check circle { fill: none; stroke: #FFDA00; stroke-width: 4;
  stroke-dasharray: 176; stroke-dashoffset: 176; }        /* 2π·28 ≈ 176 */
.takeover-check path { fill: none; stroke: #fff; stroke-width: 5;
  stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 40; stroke-dashoffset: 40; }
.takeover.in circle { animation: draw-circle 0.6s ease forwards; }      /* Kreis zeichnet sich … */
.takeover.in path { animation: draw-check 0.35s ease 0.55s forwards; }  /* … Häkchen schwingt ein */
@keyframes draw-circle { to { stroke-dashoffset: 0; } }
@keyframes draw-check { to { stroke-dashoffset: 0; } }
#takeover-msg { font-size: 1.25rem; font-weight: 600; max-width: 24rem; }
.takeover-hint { color: #d8e9f6; font-size: 0.9rem; }
#login-code { width: 100%; padding: 0.6rem; border: 1px solid #c4cad6; border-radius: 6px;
  font: inherit; font-size: 1.4rem; letter-spacing: 0.35em; text-align: center;
  margin-bottom: 0.6rem; }
#login-code.words { font-size: 1.05rem; letter-spacing: normal; text-align: left; }
#program-list .event { position: relative; cursor: pointer; padding-right: 1.7rem; }
#program-list .event::after { content: "›"; position: absolute; right: 0.8rem; top: 50%;
  transform: translateY(-50%); color: var(--ink-faint);  /* dekorativ: Karte selbst ist tappbar */ font-size: 1.25rem; }
.detail-block { background: #fff; border: 1px solid #e0e3ea; border-radius: 10px;
  padding: 0.9rem; margin-top: 1rem; }
.checkin-done { color: #155323; font-weight: 600; }
/* CheckIn-Sheet: schwebt ueber dem Inhalt, solange das Fenster offen und NICHT
   eingecheckt ist. Scroll-Container ist das Panel selbst (.detail-panel,
   overflow-y:auto) — sticky bottom:0 braucht darum keine Scroll-Rechnerei:
   solange die natuerliche Position unterhalb des Sichtfelds liegt, klebt das
   Sheet am unteren Rand; scrollt man ans Ende, sitzt es an seinem Platz.
   Randlos ueber die Panel-Body-Breite: negativer Seitenrand gegen deren
   Padding (1rem) — auf breiten Schirmen bleibt es an die 40rem-Spalte
   gebunden, konsistent zum uebrigen Panel. z-index 8: unter dem Panel-Kopf
   (z10) und den Toasts (z250). */
#detail-checkin.sheet {
  position: sticky; bottom: 0; z-index: 8;
  margin: 1rem -1rem 0;
  border-radius: 10px 10px 0 0;
  box-shadow: 0 -10px 24px rgba(28,35,48,0.18);
  padding-bottom: calc(0.9rem + env(safe-area-inset-bottom, 0px));
  transition: transform 0.2s ease;
}
#detail-checkin.sheet.dragging { transition: none; }  /* Finger führt, keine Animation */
.sheet-grip { display: block; width: 100%; border: 0; background: none;
  padding: 0.3rem 0 0.6rem; margin: -0.3rem 0 0; cursor: grab; touch-action: none; }
.sheet-grip::before { content: ""; display: block; width: 2.5rem; height: 0.25rem;
  margin: 0 auto; border-radius: 99px; background: #d3d7e0; }
.sheet-title { font-weight: 600; margin: 0; }
#detail-content .desc { white-space: pre-line; margin-top: 16px; }
#detail-content h1 { font-size: 1.35rem; margin: 16px 0 0; }  /* Ebene 1: der Held der Seite */
.doc-flag { color: var(--ink-soft); font-size: 0.78rem; margin-left: 0.45rem; }
.doc-item { margin: 0.35rem 0; }
.doc-item a { color: var(--accent-ink); text-decoration: none; }
/* Anmelde-Banner: bewusste EINLADUNG, keine Systemzeile — die Botschaft ist
   KOMPLETT lesbar (Umbruch erlaubt, KEINE Ellipsis); Gold-Akzentlinie oben +
   ›-Chevron als Tap-Signal. Weiß auf #235A41 = 8,05:1 (≥7, AAA). Der Banner
   liegt im FLUSS (kein fixed/sticky) — die Sticky-Offsets der Tages-
   überschriften hängen nur an --header-h und bleiben unberührt. */
.banner.login { background: #235a41; cursor: pointer;
  border-top: 3px solid #FFDA00; padding: 0.85rem 1rem; }
#login-banner-text { flex: 1; min-width: 0; font-weight: 600; }
#login-banner-text::after { content: " ›"; font-weight: 700; }
.banner-x { flex: none; align-self: center; border: 0; background: none; color: #fff;
  font-size: 1.15rem; line-height: 1; padding: 0.4rem 0.6rem;
  margin: -0.25rem -0.35rem -0.25rem 0; cursor: pointer; }
.install-tip { text-align: center; margin-top: 1.5rem; }
.install-guide { font-size: 1.05rem; }
.install-guide h1 { font-size: 1.35rem; }
.install-steps { line-height: 1.8; padding-left: 1.3rem; }
.install-steps li { margin: 0.4rem 0; }
.screenshot-ph { border: 2px dashed #c4cad6; border-radius: 10px; padding: 2.2rem 1rem;
  text-align: center; color: var(--ink-soft); margin: 0.8rem 0 1.4rem; }
.segments { display: flex; gap: 0.4rem; margin: 1rem 0 0.4rem; background: #e4e7ee;
  border-radius: 10px; padding: 0.25rem; }
.seg { flex: 1; border: 0; border-radius: 8px; padding: 0.45rem; font: inherit;
  background: transparent; color: var(--ink-muted); cursor: pointer; }
.seg.active { background: #fff; color: var(--ink); font-weight: 600;
  box-shadow: 0 1px 3px rgba(0,0,0,0.12); }
.info-page { background: #fff; border: 1px solid #e0e3ea; border-radius: 10px;
  padding: 0.9rem 1rem; margin-bottom: 0.8rem; }
.info-page h2 { position: static; background: none; color: var(--ink); font-size: 1.1rem;
  margin: 0 0 0.4rem; padding: 0; }
.info-page h3, .info-page h4 { margin: 0.7rem 0 0.2rem; }
.info-page ul, .info-page ol { padding-left: 1.3rem; margin: 0.3rem 0; }
.info-page p { margin: 0.4rem 0; }
:root { --live-color: #2456c4; }  /* Branding (Unitas-Gold?) färbt NUR diese Variable um */
.live-bar { height: 4px; background: #e4e7ee; border-radius: 2px; margin-top: 0.55rem;
  overflow: hidden; }
.live-fill { height: 100%; background: var(--live-color); border-radius: 2px; }
/* Bündig an der Unterkante der Programmkarte (nur Liste — Detail bleibt unter der
   Zeitzeile): absolut im Karten-Padding, kein Layout-Sprung; overflow:hidden der
   Leiste clippt den Füllstand auf die gerundeten Ecken */
#program-list .live-bar { position: absolute; left: 1px; right: 1px; bottom: 1px; margin: 0;
  border-radius: 0 0 8px 8px; }  /* um die Border-Breite eingerückt (Radius folgt) — der farbige Rahmen bleibt durchgängig sichtbar */
/* Branding-Welle 2: Unitas-Blau als Header-Grund, Logo links (weiße Kachel für Lesbarkeit) */
header { background: #0065AE; }
.header-logo { height: 1.875rem; width: auto; background: #fff; border-radius: 6px;
  padding: 2px 4px; }
header .subtitle { color: #d8e9f6; }  /* gedeckt-weiss: 4,87:1 auf Brand-Blau (Vorgabe >= 4,5) */
.view-logo { display: block; height: 4.5rem; margin: 0.6rem auto 0.2rem; }
#view-login .view-logo, #view-install .view-logo { margin-left: 0; }
/* Parallel-Gruppen: Zwischenzeile + goldene Verbindungsschiene links */
.group-time { font-weight: 600; color: var(--ink-muted); font-size: 0.9rem; margin: 0.8rem 0 0.4rem; }
.parallel-group { position: relative; padding-left: 12px; margin-bottom: 0.6rem; }
.parallel-group::before { content: ""; position: absolute; left: 0; top: 0.15rem;
  bottom: 0.15rem; width: 4px; background: #FFDA00; border-radius: 2px; }
.parallel-group .event { margin-bottom: 0.45rem; }
.parallel-link { margin: 0.3rem 0; }
.parallel-link a { color: var(--accent-ink); text-decoration: none; }
/* Location-Block: links Pin+Name/Adresse/Treffpunkt, rechts die feste Icon-/
   Button-Spalte. KEIN flex-wrap: die Text-Spalte bricht dank min-width:0 selbst um,
   das Icon bleibt immer rechts außen und vertikal zentriert */
.loc-block { display: flex; align-items: center; gap: 0.6rem;
  margin: 16px 0; padding: 0.5rem 0;
  border-top: 1px solid #e6e9f0; border-bottom: 1px solid #e6e9f0; }
.loc-info { flex: 1 1 auto; min-width: 0; }
.loc-row { display: flex; align-items: center; gap: 0.45rem; }
.loc-row .pin { width: 1.125em; height: 1.125em; flex: none; }
.loc-address { color: var(--ink-soft); font-size: 0.9rem; margin: 0.15rem 0 0 1.55rem; }
.loc-meeting { font-size: 0.92rem; margin: 0.2rem 0 0 1.55rem; }
.route-btn { flex: none; align-self: center; background: #0065AE; color: #fff;
  padding: 0.42rem 0.85rem; border-radius: 7px; font-size: 0.85rem; font-weight: 600;
  text-decoration: none; white-space: nowrap; }
/* Block-als-Link: Textfarben bleiben ruhig (Adresse grau, NICHT Link-blau) */
a.loc-block { color: inherit; text-decoration: none; }
a.loc-block:active { background: #eef3f8; }  /* Tap-Feedback */
.route-hint { display: none; width: 1.05em; height: 1.05em; flex: none; align-self: center; }
/* Mobil: kein gefüllter Button (Adresse soll nicht dominieren) — der ganze Block
   ist tappbar, rechts nur der dezente ↗-Hinweis */
@media (max-width: 640px) {
  .loc-block .route-btn { display: none; }
  .route-hint { display: block; }
}
.subline { color: var(--ink-muted); font-size: 0.92rem; margin-top: 0.1rem; }
/* Detail: Datum und Uhrzeit zweizeilig — die Uhrzeit ist die wichtigste Info */
/* Gestaltungsrichtlinie Detail-Kopf — Hierarchie: Titel > Zeit > Meta. Zeit betont
   über Gewicht/Farbe, nie über Größe. Abstände im 8er-Raster, Zugehörigkeit durch
   Nähe: Datum→Zeit 2px (EIN Block) · Zeitblock→Balken 8px · Balken/Zeit→Titel 16px ·
   Titel→Untertitel 4px · Untertitel/Titel→Meta-Pillen 8px · zu Location-Block und
   Beschreibung je 16px · Panel-Innen-
   abstand oben 16px. Genau EINE Ebene-1-Info pro Ansicht (der Eventtitel); alle
   linken Kanten auf einer Fluchtlinie, nur das Pin-Icon schert aus. */
.detail-when { margin: 0; }
.detail-date { color: var(--ink-soft); font-size: 0.95rem; }   /* Ebene 3: Meta, gedecktes Grau */
.detail-time { font-size: 1.05rem; font-weight: 600; color: var(--accent-ink);  /* Ebene 2: Gewicht+Farbe */
  margin-top: 2px; }
#detail-content .live-bar { margin-top: 8px; }         /* Balken gehört optisch zum Zeitblock */
#detail-content .subline { margin-top: 4px; }
/* Meta-Zeile im Detail: Kategorie-Pille (benennt die Kartenfarbe), abgesagt, Status */
.detail-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem;
  margin-top: 8px; }
.detail-meta .badge { margin-left: 0; }  /* Fluchtlinie: erste Pille bündig mit Titel/Datum */
.loc-label { font-size: 0.76rem; font-weight: 600; color: var(--ink-soft); letter-spacing: 0.03em;
  text-transform: uppercase; margin-bottom: 2px; }
/* Detail als Slide-Over-Panel ÜBER dem Programm — das Programm bleibt im DOM,
   seine Scroll-Position überlebt strukturell. Panel scrollt selbst. */
.detail-panel { position: fixed; inset: 0; z-index: 200; background: #f5f6f8;
  transform: translateX(100%); visibility: hidden;
  transition: transform 0.28s ease, visibility 0s linear 0.28s;
  overflow-y: auto; -webkit-overflow-scrolling: touch; touch-action: pan-y; }
.detail-panel.open { transform: translateX(0); visibility: visible;
  transition: transform 0.28s ease; }
.detail-panel.dragging { transition: none; }  /* Finger führt, keine Animation */
.detail-panel.no-anim { transition: none; }   /* nach dem Takeover: Detail steht einfach da */
/* Body-Lock, solange das Panel offen ist: fixed + top:-scrollY (setzt JS inline),
   beim Freigeben restauriert JS die Scroll-Position — overflow:hidden allein
   entkoppelt auf iOS Darstellung und Trefferflächen (Header "weg", Taps daneben).
   Der Header wird währenddessen fixed gepinnt (sticky greift ohne scrollbaren
   Body nicht); das padding-top ersetzt exakt seine Höhe im Fluss. */
body.no-scroll { position: fixed; left: 0; right: 0; width: 100%; overflow: hidden;
  padding-top: var(--header-h); }
body.no-scroll header { position: fixed; top: 0; left: 0; right: 0; }
/* Panel-Kopf in Unitas-Blau und App-Header-Hoehe: die Oberkante ist damit in
   jedem Zustand blau, der Uebergang beim Schliessen flackert nicht mehr.
   Safe-Area: das Panel liegt fullscreen, der Notch-Bereich wird mit eingefaerbt
   (env() ist 0, solange die Seite nicht unter der Statusbar liegt — unschaedlich). */
.panel-head { position: sticky; top: 0; z-index: 10; display: flex; align-items: center;
  background: #0065AE; box-sizing: border-box;
  height: calc(var(--header-h) + env(safe-area-inset-top, 0px));
  padding: env(safe-area-inset-top, 0px) 0.5rem 0 0.25rem; }
/* Pfeil + Label auf EINER Mittelachse: center statt baseline (die Baseline der
   grossen ‹-Glyphe zog das Label nach unten), line-height 1 fuer beide,
   symmetrisches Padding */
.back-arrow { border: 0; background: none; display: flex; align-items: center;
  gap: 0.4rem; font-size: 1.8rem; line-height: 1;
  padding: 0.2rem 0.75rem; color: #fff; cursor: pointer; }
.back-arrow .back-label { font-size: 1rem; font-weight: 600; line-height: 1; }
.panel-body { max-width: 40rem; margin: 0 auto; padding: 16px 1rem 3rem; }
/* ---- In-App-Dokument-Viewer: Slide-Over UEBER dem Detail-Panel ---- */
.doc-panel { z-index: 220; overflow: hidden; }
.doc-title { flex: 1; min-width: 0; color: #fff; font-size: 0.9rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.doc-share { flex: none; border: 0; background: none; color: #fff;
  padding: 0.3rem 0.7rem; cursor: pointer; }
.doc-share svg { width: 1.35rem; height: 1.35rem; display: block; }
/* Canvas-Seiten statt iframe: Touches bubblen — Swipe-Back geht ueberall */
.doc-body { position: relative; overflow-y: auto; -webkit-overflow-scrolling: touch;
  height: calc(100% - var(--header-h) - env(safe-area-inset-top, 0px));
  padding: 8px; }
.doc-page { display: block; margin: 0 auto 8px; max-width: 100%;
  background: #fff; box-shadow: 0 2px 10px rgba(28,35,48,0.25); }
.doc-status { text-align: center; padding-top: 2.5rem; }

/* ---- Passkey: Angebots-Dialog + Menue-Liste ---- */
.offer-dialog { position: fixed; inset: 0; z-index: 350; background: rgba(28,35,48,0.55);
  display: flex; align-items: center; justify-content: center; padding: 1.5rem; }
.offer-card { background: #fff; color: var(--ink); border-radius: 14px;
  padding: 1.3rem 1.2rem 0.9rem; max-width: 22rem; text-align: center;
  box-shadow: 0 16px 40px rgba(28,35,48,0.35); }
.offer-card h2 { margin: 0 0 0.4rem; color: var(--ink); font-size: 1.1rem; padding: 0; }
.offer-card p { margin: 0.3rem 0 0.9rem; }
.passkey-divider { margin: 0.9rem 0 0.5rem; }
.passkey-row { display: flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.65rem; font-size: 0.9rem; }
.passkey-row .linklike { margin-left: auto; color: #7a1d1d; }

/* ---- Start-Splash: Brand-Moment beim Oeffnen (min 2,5 s, dann weicher Fade) ---- */
.splash { position: fixed; inset: 0; z-index: 300; background: #0065AE;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 1.4rem; opacity: 1; transition: opacity 0.5s ease; }
.splash.done { opacity: 0; pointer-events: none; }
.boot-error { background: #7a1d1d; color: #fff; text-align: center;
  padding: 0.7rem 1rem; font-weight: 600; }
.splash-logo { height: 7rem; width: auto; background: #fff; border-radius: 16px;
  padding: 0.7rem 1rem; }
/* Animations-SLOT — bewusst austauschbar: hier kommt später die eigene
   150.-GV-Animation rein (Container behalten, Inhalt/Keyframes ersetzen). */
.splash-anim { display: flex; gap: 0.55rem; }
.splash-anim span { width: 0.6rem; height: 0.6rem; border-radius: 50%;
  background: #FFDA00; animation: splash-pulse 1.2s infinite ease-in-out; }
.splash-anim span:nth-child(2) { animation-delay: 0.2s; }
.splash-anim span:nth-child(3) { animation-delay: 0.4s; }
@keyframes splash-pulse {
  0%, 100% { opacity: 0.25; transform: scale(0.8); }
  40% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .detail-panel, .detail-panel.open { transition: none; }
  #detail-checkin.sheet { transition: none; }  /* kein Zurueckschnapp-Uebergang */
  .splash-anim span { animation: none; opacity: 0.85; }  /* statisch; JS kuerzt auf ~1 s */
  .takeover-check circle, .takeover-check path { animation: none; stroke-dashoffset: 0; }  /* statisches ✓ */
  .notify { transition: opacity 0.25s ease; transform: none; }
  .notify.in, .notify-important.in { animation: none; }  /* kein Overshoot/Aufleuchten */
}
