/* ============================================================
   Familienarchiv – Styles
   Primär: Bordeaux #8E244D | Sekundär: Rosé #F8BBD0
   Hintergrund: Beige #FFF8E1 | Text: Dunkelbraun #4E342E
   Akzent: Gold #C9A227
   Beide hier genutzten Schriften (Nunito fürs Fliesstext, Neuton fürs
   Logo-Wortbild) liegen selbst gehostet in fonts/ - kein Aufruf mehr bei
   Google, siehe Datenschutz Abschnitt 6.
   ============================================================ */
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('fonts/nunito-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 600;
  font-display: swap; src: url('fonts/nunito-600.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 700;
  font-display: swap; src: url('fonts/nunito-700.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 800;
  font-display: swap; src: url('fonts/nunito-800.woff2') format('woff2');
}
/* Neuton bleibt fuer Ueberschriften (--font-display). Das Logo-Wortbild
   "Farefisi.com" laeuft seit dieser Runde bewusst in Nunito - siehe .logo. */
@font-face {
  font-family: 'Neuton'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('fonts/neuton-400.woff2') format('woff2');
}

:root {
  --focus: #8E244D;
  --focus-dark: #6f1c3c;
  --focus-light: #f5e2ea;
  --gold: #C9A227;
  --gold-dark: #a4841f;
  --pink: #F8BBD0;
  --red: #b3261e;
  --blue: #3b82f6;
  --ink: #4E342E;
  --muted: #8d7468;
  --line: #cabba9;
  --card-border: #ecdfc4;
  --app-bg: #FFF8E1;
  --panel-w: 400px;
  --radius: 16px;
  --radius-sm: 10px;
  /* Zwei abgestufte Schatten statt eines einzelnen: ein enger, dunklerer
     direkt an der Kante ("liegt auf") und ein weiter, sehr weicher darunter
     ("wirft Schatten"). Genau das laesst Flaechen heute plastisch wirken -
     ein einzelner Schatten sieht dagegen schnell nach grauem Rand aus.
     Seit der Hintergrund farbig ist, brauchen weisse Flaechen das, um sich
     ueberhaupt abzuheben. */
  --shadow-sm: 0 1px 2px rgba(78,52,46,.07), 0 3px 8px rgba(78,52,46,.06);
  --shadow-md: 0 2px 4px rgba(78,52,46,.07), 0 10px 24px rgba(78,52,46,.09);
  --card-border-soft: #f0e6d2;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  height: 100%;
  font-family: 'Nunito', system-ui, -apple-system, sans-serif;
  color: var(--ink);
  overflow: hidden;
}

.hidden { display: none !important; }
.hidden-input { display: none; }

.photo-crop-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.55); z-index: 210;
  display: flex; align-items: center; justify-content: center; padding: 16px;
}
.photo-crop-box {
  background: #fff; border-radius: 16px; padding: 20px;
  width: 100%; max-width: 340px;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  box-shadow: 0 12px 40px rgba(0,0,0,.25);
}
.photo-crop-box h3 { font-size: 16px; color: var(--ink); margin: 0; }
/* Leinwand skaliert mit der Fensterbreite (die Zeichen-Koordinaten werden
   in app.js entsprechend umgerechnet) - vorher lief sie auf schmalen
   Handys seitlich aus dem Fenster heraus. */
#photoCropCanvas {
  border-radius: 8px; touch-action: none; cursor: grab; background: #eee;
  width: 100%; max-width: 300px; height: auto; aspect-ratio: 1 / 1;
}
#photoCropCanvas:active { cursor: grabbing; }
#photoCropZoom { width: 100%; max-width: 300px; height: 32px; }
.photo-crop-actions { display: flex; gap: 10px; width: 100%; }
.photo-crop-actions button { flex: 1; min-height: 46px; }

/* ---------- Topbar ---------- */
.topbar {
  /* touch-action: eine Wischgeste auf der Leiste ist nie ein Zoom -
     zusammen mit syncFixedBarsToZoom() in app.js bleiben Kopfzeile und
     Fussleiste dadurch in fester Grösse. */
  touch-action: manipulation;
  position: fixed; top: 0; left: 0; right: 0;
  height: calc(60px + env(safe-area-inset-top, 0px));
  padding-top: env(safe-area-inset-top, 0px);
  background: #fff; border-bottom: 1px solid #f0e6c8;
  display: flex; align-items: center; gap: 12px;
  padding-left: 16px; padding-right: 12px; z-index: 40;
}
.logo {
  display: flex; align-items: center; gap: 9px; flex-shrink: 0;
  background: var(--focus); border: none; border-radius: var(--radius-sm);
  padding: 6px 15px; color: #fff;
  /* Identisch zum Logo auf der Landingpage (.lp-logo in landing.css):
     gleiche Schrift, Stärke, Grösse und Abstände. Seit dieser Runde
     Nunito statt Neuton - in Nunito traegt das Wortbild schon bei
     kleineren Graden, deshalb etwas kleiner und mit engerem Sperrsatz
     als die Serifen-Fassung davor. */
  font-family: 'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-weight: 800; letter-spacing: .2px; font-size: 19px; line-height: 1.25; cursor: pointer;
}
.logo:hover { filter: brightness(1.08); }
.logo:active { transform: scale(.97); }

/* ---------- Infozeile: Familienarchiv + Fokusperson ----------
   Jetzt ein Bedienelement: ein Klick springt zum eigenen Profil bzw. zur
   Standard-Fokusperson des Archivs (siehe #treeInfo-Handler in app.js). */
.tree-info {
  display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 auto;
  font-style: italic; font-size: 13.5px; color: var(--muted);
  user-select: none;
}
.tree-info.hidden { display: none !important; }
.tree-info-chip {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0; max-width: 100%;
  background: #faf7ef; border: 1px solid var(--card-border);
  border-radius: 999px; padding: 5px 12px; overflow: hidden;
  cursor: pointer; border-color: transparent; transition: background .15s, border-color .15s;
  font: inherit; color: inherit; text-align: left; -webkit-tap-highlight-color: transparent;
}
.tree-info-chip:hover, .tree-info-chip:focus-visible {
  background: #f3ede0; border-color: var(--card-border); outline: none;
}
/* Schmale Geräte: dieselbe einzeilige Kapsel wie auf breiten Geräten, nur
   kompakter gepolstert - so bleibt sie genauso hoch wie das Logo daneben,
   statt durch zwei gestapelte Zeilen höher zu wirken. */
@media (max-width: 620px) {
  .topbar { gap: 8px; padding-left: 10px; padding-right: 8px; }
  .tree-info-chip { gap: 6px; padding: 8px 11px; }
  .tree-info-name { font-size: 11px; }
  .tree-info-focus { font-size: 12.5px; }
}
.tree-info-icon { display: inline-flex; flex-shrink: 0; line-height: 0; }
.tree-info-icon.is-private { color: #7c705c; }
.tree-info-icon.is-public { color: #2e6b45; }
.tree-info-icon.is-shared { color: var(--focus-dark); }
/* Trennzeichen und Fokusperson sitzen in DERSELBEN Kapsel wie der Baumname:
   "[Symbol] Familienarchiv – [Person] Fokusperson". */
.tree-info-dash { flex-shrink: 0; color: var(--line); font-style: normal; }
.tree-info-dash.hidden, .tree-info-focus.hidden { display: none !important; }
/* Immer einzeilig (bleibt so hoch wie das Logo daneben, auch mobil). Der
   Archivname gibt bei wenig Platz komplett nach und wird gekürzt - die
   Fokusperson ist die wichtigere Information: flex-shrink 0 heisst, das
   Layout schrumpft sie NIE zugunsten des Archivnamens. Nur falls sie ganz
   allein (Archivname bereits auf Minimum) immer noch nicht in die Kapsel
   passt - ein sehr seltener Extremfall bei aussergewöhnlich langen Namen -
   greift als letzte Sicherung ihr eigenes max-width/ellipsis. */
.tree-info-lines {
  display: flex; align-items: baseline; gap: 6px; min-width: 0;
}
/* padding-right statt eines Leerzeichens im Text: der kursive letzte
   Buchstabe ragt mit seiner Schräge minimal über die vom Browser
   berechnete (nicht-kursive) Textbreite hinaus - ohne diesen Puffer
   schneidet overflow:hidden genau dieses Stück ab. Ein Leerzeichen im
   Textinhalt half hier nicht zuverlässig (wurde am Zeilenende teils selbst
   mitabgeschnitten); ein echter CSS-Rand tut es. */
.tree-info-name {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  padding-right: 3px;
}
.tree-info-focus {
  flex: 0 0 auto; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--focus-dark); font-weight: 600;
  padding-right: 3px;
}
.tree-info-dot { color: var(--line); }

/* Suche + Menü hängen IMMER am rechten Rand - auch wenn links gar keine
   Infozeile steht (kein Familienarchiv gewählt). */
.topbar-right {
  display: flex; align-items: center; gap: 8px;
  margin-left: auto; flex-shrink: 0;
}

/* ---------- Suchfeld in der Kopfzeile ---------- */
.topbar-search {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
  width: min(300px, 34vw); padding: 9px 14px;
  background: #f3f1ec; border: 1px solid transparent; border-radius: 999px;
  color: var(--muted); transition: background .15s, border-color .15s;
}
.topbar-search:focus-within { background: #fff; border-color: var(--card-border); }
.topbar-search input {
  flex: 1; min-width: 0; border: none; background: none; outline: none;
  font-family: inherit; font-size: 14.5px; color: var(--ink);
}
.topbar-search input::placeholder { color: #9d968c; }

/* Menü-Knopf oben rechts */
.topbar-menu-btn {
  flex-shrink: 0; width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 1px solid transparent; color: var(--ink); cursor: pointer;
}
.topbar-menu-btn:hover { background: #f3ede0; }
.topbar-menu-btn:active { transform: scale(.95); }
.topbar-menu-btn.active-panel { background: var(--focus-light); color: var(--focus); }
/* ---------- Konto-Icon: schwarz-weiß als Gast, farbig wenn angemeldet ---------- */
.account-btn {
  display: flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; margin-left: 22px; flex-shrink: 0;
  border-radius: 50%; border: 1.5px solid #cfc6b0; background: #f3ede0;
  color: #9a9182; cursor: pointer; transition: transform .12s, box-shadow .15s;
}
.account-btn:hover { transform: scale(1.05); }
.account-btn.signed-in {
  background: var(--focus); border-color: var(--focus); color: #fff;
  box-shadow: 0 3px 10px rgba(142,36,77,.35);
}
.account-btn.active-panel { box-shadow: 0 0 0 3px var(--focus-light); }
.btn-link {
  background: none; border: none; color: var(--focus);
  font-family: inherit; font-weight: 700; font-size: inherit;
  cursor: pointer; text-decoration: underline; padding: 0;
}

.guest-banner {
  position: absolute; left: 50%; top: 14px; transform: translateX(-50%);
  background: #fff4e5; border: 1px solid #f3c98a; color: #7a4a00;
  padding: 8px 16px; border-radius: 999px; font-size: 13.5px;
  font-weight: 600; z-index: 20; display: flex; gap: 10px; align-items: center;
  box-shadow: 0 2px 8px rgba(0,0,0,.06);
}

/* ---------- Canvas ---------- */
:root {
  --header-h: calc(60px + env(safe-area-inset-top, 0px));
  --nav-h: calc(64px + env(safe-area-inset-bottom, 0px));
  /* Höhe des Hinweisbalkens (Einladung / geteilte Ansicht). 0, solange kein
     Balken sichtbar ist - JS setzt die tatsächliche Höhe. */
  --bar-h: 0px;
}
.view-page { position: fixed; inset: calc(var(--header-h) + var(--bar-h)) 0 var(--nav-h) 0; overflow-y: auto; }

/* ---------- Hinweisbalken unter der Kopfzeile ----------
   Sitzt fest unter der Topbar und bleibt deshalb in JEDER Ansicht
   (Übersicht, Baum, Kalender, Medien) oben stehen. */
.invite-bar {
  position: fixed; left: 0; right: 0; top: var(--header-h); z-index: 39;
  display: flex; align-items: center; gap: 10px 14px; flex-wrap: wrap;
  padding: 9px 16px; border: none; border-bottom: 1px solid #f3c98a;
  background: #fff4e5; color: #7a4a00;
  font-family: inherit; font-size: 13.5px; font-weight: 600; text-align: left;
  cursor: pointer;
}
.invite-bar.hidden { display: none !important; }
.invite-bar:hover { background: #fff0d8; }
.invite-bar:disabled { cursor: default; }
.invite-bar-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.invite-bar-note { font-weight: 600; font-size: 12.5px; color: #8a6a2a; }
.invite-bar-note.hidden { display: none !important; }
/* Der gewaehlte Hintergrund liegt auf dem Wurzelelement (siehe
   applyTreeBackgroundVar in app.js) - dadurch liegt er hinter JEDER
   Ansicht: Uebersicht, Baum, Kalender und Medien sehen automatisch gleich
   aus, statt dass nur die Baum-Flaeche gestaltet ist. `fixed` haelt den
   Verlauf beim Scrollen ruhig stehen, statt ihn mitlaufen zu lassen. */
html { background: var(--app-bg); }
body { background: transparent; }
/* Der Verlauf liegt auf einer eigenen, fest im Bildschirm stehenden Ebene
   HINTER allem. Bewusst nicht ueber `background-attachment: fixed` am
   Wurzelelement: das ist auf iOS unzuverlaessig (wird dort teils ignoriert
   oder ruckelt beim Scrollen). Eine fixierte Ebene mit z-index -1 zeigt
   ueberall dasselbe Verhalten und bleibt beim Scrollen ruhig stehen. */
body::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background: var(--tree-bg, var(--app-bg));
}
#canvasWrap {
  /* Durchsichtig: der Hintergrund kommt vom Wurzelelement (siehe oben). */
  background: transparent;
  overflow: hidden;
  cursor: grab;
}
/* Dashboard, Kalender & Medien: NICHT fixed positioniert, damit tatsächlich
   das Browserfenster scrollt statt eines inneren Containers - Safaris
   automatisches Einklappen der Adressleiste reagiert nur auf echtes
   Fenster-Scrollen. Header/Navigation bleiben trotzdem fixiert oben/unten
   sichtbar, weil sie selbst position:fixed sind. #mediaView gehörte
   inhaltlich immer schon hierher (siehe isNativeScrollView in app.js),
   nutzte bisher aber noch die allgemeine .view-page-Regel (fixed, mit
   eigenem Innen-Scroll) - dadurch reservierte die Medien-Seite immer exakt
   die volle Bildschirmhöhe für ihren Innen-Container, unabhängig davon,
   wie viele Fotos tatsächlich drin waren. Jetzt einheitlich wie die
   anderen beiden: Höhe richtet sich nach dem tatsächlichen Inhalt. */
#dashboardView, #calendarView, #mediaView {
  position: static;
  min-height: 100%;
  padding-top: calc(var(--header-h) + var(--bar-h));
  padding-bottom: var(--nav-h);
  overflow: visible;
}
html.native-scroll { overflow-y: auto; height: auto; }
html.native-scroll body { overflow: visible; height: auto; }
#canvasWrap.dragging { cursor: grabbing; }
#treeSvg { width: 100%; height: 100%; display: block; user-select: none; -webkit-user-select: none; }

.install-step {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 0; border-bottom: 1px solid var(--card-border);
  font-size: 14.5px; color: var(--ink);
}
.install-step:last-child { border-bottom: none; }
.install-step-icon { flex-shrink: 0; color: var(--focus); }

/* ---------- Empty State ---------- */
.empty-state {
  position: absolute; top: 40%; left: 50%; transform: translate(-50%, -50%);
  text-align: center;
}
.empty-state h2 { margin-bottom: 8px; }
.empty-state p { color: var(--muted); margin-bottom: 16px; }

/* ---------- Buttons ---------- */
.btn {
  border: none; border-radius: var(--radius-sm); padding: 12px 20px;
  min-height: 46px; font-family: inherit; font-weight: 700; font-size: 15px;
  cursor: pointer; transition: filter .15s, transform .1s;
  display: inline-flex; align-items: center; justify-content: center;
}
.btn:hover { filter: brightness(1.05); }
.btn:active { transform: scale(.97); }
.btn.gold { background: var(--gold); color: #fff; }
.btn.gold.dark { background: var(--gold-dark); }
.btn.blue { background: var(--focus); color: #fff; border-radius: 999px; padding: 10px 28px; }
.btn.outline {
  background: #fff; color: var(--ink); border: 1px solid #d8d8e6;
  border-radius: 999px; padding: 10px 24px;
}

.tree-float-btn {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  background: #fff; border: 1px solid var(--card-border); color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; box-shadow: 0 3px 10px rgba(0,0,0,.08);
  transition: filter .15s, transform .1s;
}
.tree-float-btn:hover { filter: brightness(.97); }
.tree-float-btn:active { transform: scale(.95); }

/* ---------- Untere Navigation (4 Icons) ---------- */
.bottom-nav {
  touch-action: manipulation;
  position: fixed; left: 0; right: 0; bottom: 0; height: var(--nav-h);
  background: #fff; border-top: 1px solid #f0e6c8;
  display: flex; z-index: 40;
  padding-bottom: env(safe-area-inset-bottom, 0);
  /* Ohne Anmeldung komplett ausgeblendet (siehe updateAuthUI in app.js) -
     erst nach dem Anmelden fährt die Leiste sanft von unten hoch, statt
     einfach zu erscheinen. */
  transform: translateY(100%);
  opacity: 0;
  pointer-events: none;
  transition: transform .45s cubic-bezier(.16, 1, .3, 1), opacity .3s ease;
}
.bottom-nav.nav-visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}
/* Nur noch Symbole - die Beschriftungen sind entfallen, dadurch sind die
   Ziele größer und die Leiste ruhiger. */
.nav-item {
  flex: 1; border: none; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--muted); font-family: inherit;
  transition: color .15s;
}
.nav-item svg { width: 26px; height: 26px; }
.nav-item:hover { color: var(--ink); }
.nav-item.active, .nav-item.active-panel { color: var(--focus); }
.nav-item.signed-in svg circle:first-child { fill: var(--focus-light); }

/* ---------- Profil-Menü: Unter-Seiten (Einstellungen / Herunterladen) ---------- */
.profile-subpage {
  display: flex; flex-direction: column; gap: 4px; min-width: 0;
}
/* Beschriftung links, Schalter rechts - und die GANZE Zeile ist antippbar
   (mindestens 48px hoch), nicht nur der kleine Schalter. */
.toggle-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  font-weight: 600; font-size: 15px; min-height: 48px; padding: 6px 6px;
  margin: 0 -6px; border-radius: 10px; cursor: pointer;
}
.toggle-row:hover { background: #faf6ea; }
.toggle-row > span:first-child { min-width: 0; }
.switch { position: relative; display: inline-block; width: 40px; height: 22px; flex-shrink: 0; }
.switch input { opacity: 0; width: 0; height: 0; position: absolute; }
.switch i {
  position: absolute; inset: 0; background: #e0d3ba; border-radius: 999px;
  transition: background .15s;
}
.switch i::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; background: #fff; border-radius: 50%;
  transition: left .15s; box-shadow: 0 1px 3px rgba(0,0,0,.2);
}
.switch input:checked + i { background: var(--gold); }
.switch input:checked + i::after { left: 20px; }
/* Grössere Variante für Touch (Apple-Grösse ~51x31) */
.switch.switch-lg { width: 50px; height: 30px; }
.switch.switch-lg i::after { width: 26px; height: 26px; top: 2px; left: 2px; }
.switch.switch-lg input:checked + i::after { left: 22px; }
.switch input:focus-visible + i { outline: 2px solid var(--focus); outline-offset: 2px; }

.tools-item {
  display: flex; align-items: center; gap: 10px;
  background: none; border: none; text-align: left; text-decoration: none;
  font-family: inherit; font-size: 15px; font-weight: 600;
  min-height: 48px; padding: 10px 6px; margin: 0 -6px;
  cursor: pointer; color: var(--ink); border-radius: 10px;
}
.tools-item:hover { background: #f6efd9; }
.tools-item:disabled { color: var(--muted, #9a8f7a); cursor: default; opacity: .55; }
.tools-item:disabled:hover { background: none; }

/* ---------- Hintergrund-Varianten (5 feste, dezente Optionen) ---------- */
.bg-swatch-row { display: flex; gap: 10px; padding: 4px 6px 14px; }
.bg-swatch-row.hidden { display: none; }
.bg-swatch {
  width: 34px; height: 34px; border-radius: 50%; cursor: pointer;
  border: 2px solid var(--card-border); padding: 0; position: relative;
}
.bg-swatch.is-active { border-color: var(--pink); box-shadow: 0 0 0 2px rgba(142,36,77,.18); }
.bg-swatch.is-active::after {
  content: "✓"; position: absolute; inset: 0; display: flex;
  align-items: center; justify-content: center; font-size: 13px;
  font-weight: 800; color: var(--pink);
}

/* ---------- Suche ---------- */
.search-panel {
  /* Auf derselben Höhe wie der Such-Button im Header (der sitzt zentriert
     in einer 60px-Zeile, beginnend nach der Notch-Aussparung oben) - vorher
     stand das Suchfeld unterhalb des GESAMTEN Headers, das sah nach zwei
     getrennten Elementen statt einer Einheit aus. */
  position: fixed; top: calc(env(safe-area-inset-top, 0px) + 10px); right: 22px;
  z-index: 45; width: 260px; max-width: calc(100vw - 32px);
  /* Bewusst kein display:none (wie die generische .hidden-Klasse) - das
     würde jede CSS-Transition verhindern. Stattdessen unsichtbar +
     nicht klickbar + leicht nach rechts verschoben, bis .open dazukommt. */
  opacity: 0; pointer-events: none; transform: translateX(18px);
  transition: opacity .18s ease, transform .18s ease;
}
.search-panel.open { opacity: 1; pointer-events: all; transform: translateX(0); }
/* Auf breiten Fenstern hängt die Trefferliste unter dem Suchfeld der
   Kopfzeile; das eigene Feld im Panel wird dort nicht gebraucht. */
@media (min-width: 861px) {
  .search-panel { right: 74px; top: calc(env(safe-area-inset-top, 0px) + 58px); width: 300px; }
  .search-panel .search-pill { display: none; }
  #searchResults { margin-top: 0; }
}
@media (max-width: 860px) {
  .topbar-search { display: none; }
}
@media (min-width: 861px) {
  #btnSearch { display: none; }
}
.search-pill {
  display: flex; align-items: center; gap: 8px;
  background: #f3ede0; border: 1px solid #e8dcc0; border-radius: 999px;
  padding: 10px 16px; box-shadow: 0 10px 26px rgba(0,0,0,.10);
}
.search-pill-icon { color: var(--muted); flex-shrink: 0; }
.search-pill input {
  flex: 1; min-width: 0; border: none; background: none; outline: none;
  font-family: inherit; font-size: 15px; color: var(--ink);
}
.search-pill input::placeholder { color: var(--muted); }
#searchResults:empty { display: none; }
#searchResults {
  max-height: 260px; overflow: auto; margin-top: 8px;
  background: #fff; border: 1px solid #f0e6c8; border-radius: 14px;
  box-shadow: 0 10px 30px rgba(0,0,0,.12); padding: 6px;
}
.search-result {
  padding: 12px 12px; min-height: 46px; display: flex; align-items: center;
  border-radius: 8px; cursor: pointer; font-weight: 600;
}
.search-result:hover { background: #fdf0ec; color: var(--focus-dark); }

/* ---------- Add-Menü (pink) ---------- */
.add-menu {
  position: absolute; z-index: 35;
  display: flex; flex-direction: column; gap: 6px;
}
.add-menu-divider { border-top: 1px solid rgba(0,0,0,.12); margin: 2px 4px; }
.pink-btn {
  background: var(--pink); color: var(--focus-dark); border: none;
  border-radius: 8px; padding: 11px 18px; min-height: 42px; font-family: inherit;
  font-weight: 700; font-size: 14px; cursor: pointer; white-space: nowrap;
  box-shadow: 0 2px 6px rgba(0,0,0,.15);
}
.pink-btn:hover { filter: brightness(1.05); }
.pink-btn:active { transform: scale(.96); }

/* ---------- SVG-Karten ---------- */
.person-card { cursor: pointer; }
.person-card .hover-zone { pointer-events: all; }
.person-card .card-rect {
  fill: #fff; stroke: var(--card-border); stroke-width: 1;
}
/* Der Schatten ist ein einmal vorberechnetes Bild hinter der Karte (siehe
   getCardShadowUrl in app.js) - bewusst kein Filter, weil ein Filter beim
   Zoomen fuer JEDE Karte neu gerechnet werden muesste. Es faengt keine
   Klicks ab; dafuer gibt es die eigene Trefferflaeche der Karte. */
.person-card .card-shadow { pointer-events: none; }
.person-card.editing .card-rect { fill: url(#cardGradFocusPerson); stroke: var(--focus-dark); }
.person-card .card-name {
  font-family: 'Nunito', sans-serif; font-weight: 700; font-size: 15px;
  fill: var(--ink); text-anchor: middle;
}
.person-card.editing .card-name { fill: #fff; }
.person-card .avatar-circle { fill: #e8ddc7; }
.person-card .avatar-sil { fill: #c3c7cf; }
/* Grüner Haken neben dem Profilbild: diese Person hat ein eigenes Konto.
   Abschaltbar über "Verbergen" neben "Registrierte Nutzer" im Teilen-Fenster. */
.card-verified-ring { fill: #fff; }
.card-verified-badge { fill: #22a06b; }
.card-verified-check { fill: none; stroke: #fff; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

/* Platzhalter-Box für einen noch nicht erfassten Elternteil - etwas
   transparent, damit sie sich sichtbar von echten Personen abhebt. */
.placeholder-card { cursor: default; opacity: .62; }
.placeholder-card.clickable { cursor: pointer; }
.placeholder-rect {
  fill: url(#cardGradPlaceholder); stroke: #cfc6ad; stroke-width: 1.5; stroke-dasharray: 6 5;
}
/* Eine noch nicht erfasste Person bleibt bewusst flach und hebt sich
   dadurch klar von echten Karten ab. Dafuer braucht es hier keine Regel:
   die Platzhalter-Karte wird von drawPlaceholderCard() gebaut und bekommt
   das Schattenbild gar nicht erst mit. */
.placeholder-card.clickable:hover .placeholder-rect { fill: #f5f0e4; stroke: var(--gold); }
.placeholder-plus-circle { fill: none; stroke: #cfc6ad; stroke-width: 1.5; }
.placeholder-card.clickable:hover .placeholder-plus-circle { stroke: var(--gold); }
.placeholder-plus { stroke: #b8ac8a; }
.placeholder-card.clickable:hover .placeholder-plus { stroke: var(--gold); }
.placeholder-label { fill: #948a6e; font-weight: 600; font-style: italic; }

.hover-btn { cursor: pointer; }
.hover-btn rect { rx: 4; }
.hover-btn text {
  font-weight: 800; fill: var(--ink); text-anchor: middle; font-size: 14px;
}
.person-card .hover-btn { opacity: 0; transition: opacity .12s; pointer-events: none; }
@media (hover: hover) {
  .person-card:hover .hover-btn { opacity: 1; pointer-events: all; }
}

/* Familienarchiv-Symbol oben links: zeigt an, dass in dieser Richtung noch
   mehr Familie existiert, die gerade nicht angezeigt wird. Anders als
   der Drei-Punkte-Button IMMER leicht sichtbar (nicht erst bei Hover
   über die Karte) - sonst würde man ja gar nicht bemerken, dass dort
   mehr ist. Der goldene Kreis dahinter erscheint erst, wenn man mit der
   Maus GENAU über das Symbol fährt (nicht über die ganze Karte).*/
.hidden-tree-btn { cursor: pointer; }
.hidden-tree-circle { opacity: 0; transition: opacity .12s; }
.hidden-tree-line {
  fill: none; stroke: var(--muted); stroke-width: 1.4; stroke-linecap: round;
  opacity: .55; transition: stroke .12s, opacity .12s;
}
.hidden-tree-btn:hover .hidden-tree-circle { opacity: 1; }
.hidden-tree-btn:hover .hidden-tree-line { stroke: #fff; opacity: 1; }

/* Crosshair-Symbol (oben rechts) und Drei-Punkte-Menü (unten rechts):
   beide nutzen .hover-btn für die Sichtbarkeit (nur bei Kartenhover, wie
   bisher), zusätzlich wird - wie beim Symbol oben links - der goldene
   Kreis erst sichtbar, wenn die Maus GENAU über dieses Symbol fährt. */
.corner-icon-btn { cursor: pointer; }
.corner-icon-circle { opacity: 0; transition: opacity .12s; }
.corner-icon-dot { fill: var(--muted); transition: fill .12s; }
.corner-icon-line {
  fill: none; stroke: var(--muted); stroke-width: 1.4; stroke-linecap: round;
  transition: stroke .12s;
}
.corner-icon-btn:hover .corner-icon-circle { opacity: 1; }
.corner-icon-btn:hover .corner-icon-dot { fill: #fff; }
.corner-icon-btn:hover .corner-icon-line { stroke: #fff; }
/* Symbol der AKTUELLEN Fokusperson: dauerhaft sichtbar statt nur bei
   Kartenhover (siehe drawCard) - der goldene Kreis bleibt trotzdem bis
   zum direkten Hover über das Symbol ausgeblendet. */
.corner-icon-always { opacity: 1; pointer-events: all; cursor: pointer; }
/* Reine Markierung "hier ist der Fokus": kräftiger gezeichnet, aber nicht
   anklickbar - man ist ja schon auf dieser Person. */
.focus-person-btn.is-focus-mark { cursor: default; pointer-events: none; }
.focus-person-btn.is-focus-mark .corner-icon-line { stroke: var(--focus); opacity: 1; stroke-width: 1.8; }
.focus-person-btn .corner-icon-line {
  fill: none; stroke: var(--muted); stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round; transition: stroke .12s;
}
.focus-person-btn:hover .corner-icon-line { stroke: #fff; }

.tree-line { stroke: var(--line); fill: none; stroke-linecap: round; }
.tree-line.direct { stroke-width: 2.1; }
.tree-line.sideline { stroke-width: 1.6; }

/* ============================================================
   Fenster-Gerüst ("Sheet"): eine fixierte Kopfzeile (Titel, Zurück,
   Schliessen) + ein scrollender Inhaltsbereich. Der Inhaltsbereich reicht
   bis an den Rand der Karte, damit die Bildlaufleiste GANZ aussen sitzt
   (vorher lag sie ein Stück innerhalb, siehe Screenshot des Nutzers).
   ============================================================ */
.modal-card.sheet-card { padding: 0; display: flex; flex-direction: column; overflow: hidden; }
/* Menü und Bearbeiten-Fenster sind IMMER gleich hoch, egal wie viel darin
   steht - vorher sprang die Höhe je nach Inhalt und Ansicht. Was nicht
   hineinpasst, wird im .sheet-body gescrollt. NUR ab Desktop-Breite: auf
   dem Handy soll dasselbe Menü randlos das GANZE Bildschirm füllen (siehe
   die 100dvh-Regel weiter unten für @media max-width 640px) - ohne dieses
   min-width hier hätte die ID-Selektor-Regel (#profileMenu ...) durch ihre
   höhere Spezifität sonst IMMER gewonnen, egal wie schmal der Bildschirm
   ist. Das liess auf dem Handy eine Lücke unterhalb der (auf 720px
   gedeckelten) Karte offen, durch die man die untere Navigation
   dahinter sehen konnte, obwohl das Menü eigentlich Vollbild sein soll.
   */
@media (min-width: 641px) {
  #profileMenu .modal-card.sheet-card,
  .modal-card.edit-modal-card { height: min(88vh, 720px); }
}
.sheet-head {
  display: flex; align-items: center; gap: 12px; flex-shrink: 0;
  padding: 12px 12px 12px 18px; border-bottom: 1px solid var(--card-border);
  background: #fff; border-radius: 16px 16px 0 0;
}
/* Etwas Abstand nach der Kopfzeile, damit die erste Menüzeile nicht direkt
   unter dem Schliessen-Kreuz klebt. */
.profile-menu-list { padding-top: 4px; }
.sheet-title {
  flex: 1; min-width: 0; margin: 0 !important; font-size: 18px; font-weight: 800;
  color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sheet-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
  -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
  /* Bearbeiten-Fenster: der Kopf (Foto+Name) schrumpft beim Scrollen (siehe
     updateEditHeaderCollapse in app.js), wodurch sich die Höhe DIESES
     Scroll-Bereichs mitverändert. Ist man ganz unten, versucht der Browser
     von sich aus, die Scroll-Position an der jetzt veränderten Höhe
     "festzuhalten" (Scroll-Anchoring) - das kollidierte mit der eigenen,
     auf scrollTop basierenden Neuberechnung und erzeugte ein Zittern.
     overflow-anchor:none schaltet dieses automatische Nachjustieren ab. */
  overflow-anchor: none;
  padding: 16px 20px calc(20px + env(safe-area-inset-bottom, 0px));
}

/* Schliessen/Zurück: 44x44 Tippfläche (Apple/Google-Richtwert), sichtbarer
   Kreis statt eines fast unsichtbaren kleinen Kreuzes. */
.close-btn, .sheet-back {
  flex-shrink: 0; width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: #f3ede0; border: 1px solid var(--card-border); color: var(--ink);
  cursor: pointer; font-size: 20px; line-height: 1; padding: 0;
  transition: background .15s, transform .1s;
}
.close-btn:hover, .sheet-back:hover { background: #e9dfc9; }
.close-btn:active, .sheet-back:active { transform: scale(.94); }
.sheet-back { background: none; border-color: transparent; }
.sheet-back:hover { background: #f3ede0; }
/* Karten OHNE Sheet-Kopfzeile (kleine Dialoge): Kreuz weiterhin oben rechts
   schwebend, aber in derselben Grösse/Sichtbarkeit. */
.modal-card > .close-btn { position: absolute; top: 10px; right: 10px; z-index: 2; }

.modal-card.edit-modal-card { width: 480px; }
.avatar-wrap { position: relative; width: 46px; height: 46px; flex-shrink: 0; }
.avatar-img, .avatar-placeholder {
  width: 46px; height: 46px; border-radius: 50%;
  background: #e8ddc7; object-fit: cover; display: block;
  overflow: hidden;
}
/* Standard-Profilbild (weiblich/männlich) wird per JS als <img> eingesetzt,
   siehe setAvatarPlaceholder() in app.js - dasselbe Bild wie auf den
   Baum-Karten, nur ausserhalb des Baums (Bearbeiten-Fenster, Aktivität,
   Mein Konto). */
.avatar-sil-img { width: 100%; height: 100%; display: block; object-fit: cover; }
.photo-btn, .photo-remove-btn {
  position: absolute; width: 24px; height: 24px; border-radius: 50%;
  border: 1px solid var(--card-border); background: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink); box-shadow: 0 2px 6px rgba(0,0,0,.2); padding: 0;
}
.photo-btn { right: -5px; bottom: -3px; }
.photo-remove-btn { right: -5px; top: -3px; color: var(--red); }

/* ============================================================
   Bearbeiten-Fenster einer Person: eigene, mittig ausgerichtete
   Kopfzeile (Lese-/Bearbeiten-Umschalter). Löst sich bewusst von der
   generischen .sheet-head-Zeile (Zurück|Titel|Kreuz), die weiterhin
   unverändert für Menü/Konto/Beitreten gilt.
   ============================================================ */
.edit-sheet-head {
  flex-direction: column; align-items: stretch; gap: 6px;
  padding: 10px 18px 18px;
}
.edit-head-bar { display: flex; align-items: center; justify-content: space-between; }
/* Lese-Modus (Zurück links, Stift rechts) und Bearbeiten-Modus (X links,
   Haken rechts) blenden sich per .hidden gegenseitig aus - siehe
   setEditPanelMode() in app.js. */
.edit-sheet-head .sheet-back, .edit-sheet-head .close-btn { position: static; }
.edit-pencil-btn, .edit-save-btn {
  flex-shrink: 0; width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  border: none; cursor: pointer; padding: 0;
  transition: background .15s, color .15s, transform .1s;
}
.edit-pencil-btn:active, .edit-save-btn:active { transform: scale(.94); }
/* Bewusst NICHT farbig (kein Bordeaux-Fülleffekt) - dezenter, neutraler
   Kreis wie Zurück-Pfeil/Kreuz, damit der Stift nicht wie ein Haupt-Knopf
   wirkt. */
.edit-pencil-btn { background: #f3ede0; border: 1px solid var(--card-border); color: var(--ink); }
.edit-pencil-btn:hover { background: #e9dfc9; }
/* Haken: gedämpft/inaktiv wirkend UND nicht bedienbar, solange noch nichts
   geändert wurde - wird erst farbig UND klickbar (.dirty), sobald wirklich
   eine Änderung ansteht (siehe markEditDirty/setEditPanelMode). */
.edit-save-btn { background: #efe6d2; color: #b9ab8e; }
.edit-save-btn:disabled { cursor: not-allowed; }
.edit-save-btn.dirty { background: var(--focus); color: #fff; }
.edit-save-btn.dirty:hover { filter: brightness(1.08); }

/* 40% größer als der ursprüngliche 96px-Kreis (siehe GO-LIVE, Abschnitt 19).
   Breite/Höhe werden zusätzlich beim Scrollen im Panel-Inhalt per JS laufend
   verkleinert (siehe updateEditHeaderCollapse) - deshalb hier bewusst OHNE
   CSS-Transition, damit die Grösse 1:1 mit der Scrollposition mitläuft,
   statt hinterherzufedern. Kind-Elemente folgen über width/height:100%. */
.avatar-wrap-lg { width: 134px; height: 134px; margin: 6px auto 2px; }
.avatar-wrap-lg .avatar-img, .avatar-wrap-lg .avatar-placeholder { width: 100%; height: 100%; }

/* ============================================================
   Kompakter Kopf beim Scrollen
   ------------------------------------------------------------
   Sobald im Inhalt nach unten gescrollt wird (siehe updateEditHeadCompact
   in app.js), rutscht das grosse Foto zur Seite und der Name daneben - aus
   dem hohen Block wird eine flache Zeile, und unten wird spuerbar mehr
   Platz fuer die Felder frei.

   Ohne zweites Markup: der Kopf wird von Spalte auf Zeile umgestellt, und
   die Knopfleiste gibt ueber display:contents ihre Kinder direkt an diese
   Zeile weiter. Dadurch stehen Zurueck/X, Foto, Name und Stift/Haken in
   EINER Reihe, ohne dass irgendetwas doppelt im HTML stehen muss.
   ============================================================ */
.edit-sheet-head { transition: padding .18s ease; }
.avatar-wrap-lg { transition: width .18s ease, height .18s ease, margin .18s ease; }
.edit-sheet-title { transition: font-size .18s ease; }
/* Waehrend der Messung der Hoehen-Ersparnis (measureEditHeadGain) wird kurz
   umgeschaltet - das darf man nicht sehen. */
.edit-sheet-head.no-anim, .edit-sheet-head.no-anim * { transition: none !important; }

.edit-sheet-head.is-compact {
  flex-direction: row; align-items: center; gap: 10px; padding: 8px 14px;
}
.edit-sheet-head.is-compact .edit-head-bar { display: contents; }
.edit-sheet-head.is-compact .sheet-back,
.edit-sheet-head.is-compact .close-btn { order: 1; }
.edit-sheet-head.is-compact .avatar-wrap-lg { order: 2; width: 38px; height: 38px; margin: 0; }
/* Das Foto-Plus waere auf 38px zu klein zum Treffen - im kompakten Kopf
   geht es weg und kommt beim Hochscrollen wieder. */
.edit-sheet-head.is-compact .photo-menu-btn { display: none; }
.edit-sheet-head.is-compact .edit-sheet-title-row {
  order: 3; flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 6px;
}
.edit-sheet-head.is-compact .edit-sheet-title {
  text-align: left; font-size: 17px; margin-top: 0 !important;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.edit-sheet-head.is-compact .edit-verified-badge { margin-top: 0; }
.edit-sheet-head.is-compact .edit-pencil-btn,
.edit-sheet-head.is-compact .edit-save-btn { order: 4; }
/* Foto verwalten: neutrales Plus oben rechts am Foto (nur im Bearbeiten-
   Modus, siehe refreshPhotoControls). Bewusst NICHT rot - es ist der
   Zugang zu allen Foto-Aktionen, nicht nur zum Loeschen. Ersetzt das
   fruehere rote Minus UND den Textknopf unter dem Foto. */
.avatar-wrap-lg .photo-menu-btn {
  position: absolute; right: -2px; top: -2px;
  width: 28px; height: 28px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer;
  background: var(--focus); border: 2px solid #fff; color: #fff;
  box-shadow: 0 2px 6px rgba(78,52,46,.22);
  transition: filter .15s, transform .1s;
}
.avatar-wrap-lg .photo-menu-btn:hover { filter: brightness(1.1); }
.avatar-wrap-lg .photo-menu-btn:active { transform: scale(.92); }
/* Kleines Menue darunter: "Foto aendern" / "Foto entfernen". */
.photo-menu {
  position: absolute; top: calc(100% + 6px); left: 50%; transform: translateX(-50%);
  z-index: 5; min-width: 168px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 12px;
  box-shadow: 0 10px 28px rgba(78,52,46,.18);
  padding: 5px; display: flex; flex-direction: column;
}
.photo-menu.hidden { display: none; }
.photo-menu button {
  font-family: inherit; font-size: 14px; font-weight: 600; text-align: left;
  color: var(--ink); background: none; border: none; border-radius: 8px;
  padding: 9px 12px; cursor: pointer; white-space: nowrap;
}
.photo-menu button:hover { background: #f6f0e4; }
.photo-menu button.danger { color: var(--red); }
/* Drei Spalten statt Flexbox: die äusseren beiden sind gleich breit (1fr),
   dadurch bleibt der Name in der mittleren Spalte immer exakt mittig,
   unabhängig davon, ob rechts daneben noch der grüne Haken Platz braucht -
   vorher schob der Haken (nur rechts vorhanden) den Namen sichtbar nach
   links. */
.edit-sheet-title-row {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 6px;
}
.edit-sheet-title {
  grid-column: 2; flex: none;
  text-align: center; font-size: 19px; margin-top: 4px !important;
  white-space: normal; overflow: visible; text-overflow: clip;
}
/* Grüner Haken statt des Texts "(registriert)" - dieselben Farben wie
   .card-verified-* auf den Baum-Karten. */
.edit-verified-badge { grid-column: 3; justify-self: start; flex-shrink: 0; display: flex; margin-top: 4px; }
.edit-verified-badge .ev-ring { fill: #fff; }
.edit-verified-badge .ev-badge { fill: #22a06b; }
.edit-verified-badge .ev-check { fill: none; stroke: #fff; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

.edit-tabs {
  display: flex; flex-shrink: 0; border-bottom: 1px solid var(--card-border);
  padding: 0 12px; background: #fff;
}
.edit-tab {
  flex: 1; background: none; border: none; font-family: inherit; cursor: pointer;
  font-size: 15px; font-weight: 700; color: var(--muted);
  padding: 13px 8px; border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.edit-tab.active { color: var(--focus); border-bottom-color: var(--focus); }

.edit-modal-body { padding-top: 4px; }
.edit-tab-page.hidden { display: none; }

.edit-modal-footer {
  flex-shrink: 0; border-top: 1px solid var(--card-border);
  padding: 12px 20px calc(12px + env(safe-area-inset-bottom, 0px));
  background: #fff;
}

/* ============================================================
   Formularzeilen im Person-Tab
   Aufbau wie im Referenzbild: Beschriftung links (gedämpft), Wert rechts
   daneben LINKSbündig, feine Trennlinie, und die gerade bearbeitete Zeile
   wird als Ganzes hervorgehoben. Volle Kartenbreite - nichts ragt seitlich
   heraus, deshalb entsteht auch kein waagerechtes Scrollen mehr.
   ============================================================ */
#editPagePerson .field-row {
  display: grid; grid-template-columns: 116px minmax(0, 1fr);
  align-items: center; gap: 10px;
  min-height: 52px; padding: 8px 10px; margin: 0 -10px;
  border-bottom: 1px solid var(--card-border); border-radius: 12px;
  transition: background .15s, box-shadow .15s;
}
#editPagePerson .field-row:last-child { border-bottom: none; }
/* Aktive Zeile hervorheben (wie im Referenzbild) */
#editPagePerson .field-row:focus-within {
  background: #fdf7f9; border-bottom-color: transparent;
  box-shadow: inset 0 0 0 2px var(--focus);
}
.field-label {
  font-weight: 600; font-size: 14px; color: var(--muted);
  margin: 0 !important; display: block; min-width: 0;
  overflow-wrap: anywhere; cursor: pointer;
}
#editPagePerson .field-row:focus-within .field-label { color: var(--focus); }
#editPagePerson .field-input {
  display: block; width: 100%; min-width: 0; margin: 0; padding: 6px 0;
  border: none; background: none; outline: none; text-align: left;
  font-family: inherit; font-size: 16px; font-weight: 600; color: var(--ink);
}
.field-input::placeholder { color: #b6a597; font-weight: 400; }

/* Lesemodus Geschlecht: reiner Text statt der drei Auswahl-Knöpfe. */
.field-value-text { font-size: 16px; font-weight: 600; color: var(--ink); }

/* Geschlecht: EIN Segment-Schalter (vorher drei einzelne Radio-Knöpfe, die
   auf dem Handy umbrachen). Nur noch Männlich/Weiblich (siehe Abschnitt 20,
   "Divers" ist aus dem Bearbeiten-Formular entfernt) - deshalb zwei statt
   drei Spalten, sonst bliebe sichtbar leerer Platz für die dritte,
   nicht mehr vorhandene Option stehen. */
.segmented {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 3px; background: #f3ede0; border-radius: 999px; padding: 3px;
  min-width: 0;
}
.segmented .seg { margin: 0 !important; min-width: 0; }
.segmented .seg input { position: absolute; opacity: 0; pointer-events: none; }
.segmented .seg span {
  display: flex; align-items: center; justify-content: center;
  min-height: 36px; padding: 0 4px; border-radius: 999px;
  font-size: 13px; font-weight: 700; color: var(--muted);
  cursor: pointer; text-align: center; line-height: 1.1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: background .15s, color .15s;
}
.segmented .seg input:checked + span {
  background: var(--focus); color: #fff; box-shadow: 0 1px 4px rgba(142,36,77,.3);
}
.segmented .seg input:focus-visible + span { outline: 2px solid var(--focus); outline-offset: 1px; }

/* Status-Zeile: nur noch "Lebend" + Schalter. Wird er ausgeschaltet,
   blendet sich die Zeile "Sterbedatum" automatisch ein (siehe app.js). */
#editPagePerson .field-row-switch .switch { justify-self: end; }
#editPagePerson .field-row-switch .field-label { font-weight: 700; color: var(--ink); }

/* ---------- Datumseingabe ----------
   Standard: der native Datums-Wähler des Geräts (Kalender-Rad, keine
   Tastatur, kein Tippen von Punkten nötig). Für Vorfahren, bei denen nur
   das Jahr oder Monat+Jahr bekannt ist, lässt sich pro Feld auf die
   Teil-Eingabe TT/MM/JJJJ umschalten (reine Zahlenfelder, springen von
   selbst weiter). */
.date-field { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; min-width: 0; width: 100%; }
.date-native {
  width: 100%; min-width: 0; border: none; background: none; outline: none;
  font-family: inherit; font-size: 16px; font-weight: 600; color: var(--ink);
  padding: 6px 0; min-height: 32px;
}
.date-native::-webkit-date-and-time-value { text-align: left; }
.date-native::-webkit-calendar-picker-indicator { opacity: .55; cursor: pointer; }
.date-parts { display: flex; align-items: center; gap: 2px; padding: 2px 0; min-width: 0; }
.date-parts.hidden { display: none !important; }
.date-part {
  width: 2.6em; min-width: 0; text-align: center; border: 1px solid #e0d3ba;
  border-radius: 8px; padding: 7px 2px; font-family: inherit; font-size: 16px;
  font-weight: 600; color: var(--ink); background: #fff;
}
.date-part-year { width: 4.2em; }
.date-part:focus { outline: none; border-color: var(--focus); }
.date-sep { color: var(--muted); font-weight: 700; }
/* Dezent halten: der Umschalter ist ein Sonderfall, nicht die Hauptaktion. */
.date-mode-btn {
  background: none; border: none; padding: 4px 0; cursor: pointer;
  font-family: inherit; font-size: 12px; font-weight: 700; color: var(--muted);
  text-decoration: underline; text-underline-offset: 2px; text-align: left;
  white-space: nowrap;
}
.date-mode-btn:hover { color: var(--focus); }
/* Lesemodus: reiner Text statt Wähler/Kästchen/Umschalt-Link (siehe
   updateDateViewText in app.js) - zeigt genau so viel vom Datum, wie
   bekannt ist ("1991" statt "TT . MM . 1991" mit leeren Kästchen). */
.date-view-text { display: none; }
.date-field.locked .date-native,
.date-field.locked .date-parts,
.date-field.locked .date-mode-btn { display: none !important; }
.date-field.locked .date-view-text { display: block; padding: 6px 0; }

/* ---------- Beziehungen (Eltern/Partner/Kinder direkt bearbeiten) ---------- */
.rel-group { margin-bottom: 18px; }
.rel-group-title {
  font-size: 12.5px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); margin-bottom: 8px; font-weight: 700;
}
.rel-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; min-width: 0; }
.rel-row {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 10px;
  padding: 6px 8px 6px 12px; min-height: 48px;
}
/* Name + Jahre. Der Name darf abgeschnitten werden, die Jahre nicht -
   sonst verschwindet als Erstes genau die Angabe, die zwei gleichnamige
   Verwandte auseinanderhält. */
.rel-row-name { flex: 1; min-width: 0; font-weight: 700; font-size: 14.5px; color: var(--ink);
  display: flex; align-items: baseline; gap: 0; overflow: hidden; white-space: nowrap; }
.rel-row-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.rel-row-years { flex-shrink: 0; font-weight: 600; font-size: 13px; color: var(--muted); }
/* Art der Partnerschaft: Auswahlliste im Pillen-Stil des früheren
   Umschalters - vier Möglichkeiten passen nicht mehr auf einen Knopf. */
.rel-kind-select {
  flex-shrink: 0; border: 1px solid #e0d3ba; background: #fff; border-radius: 999px;
  font-family: inherit; font-size: 12.5px; font-weight: 700; color: var(--muted);
  padding: 8px 10px; min-height: 36px; cursor: pointer;
  max-width: 132px;
}
.rel-kind-select.is-ex { color: var(--focus-dark); border-color: var(--pink); background: #fdf0f4; }
.rel-kind-select:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* "Seit"-Zeile direkt unter dem Partnernamen */
.rel-since-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 8px 2px 2px; margin-top: 2px;
}
.rel-since-label {
  font-size: 12.5px; font-weight: 800; color: var(--muted);
  text-transform: uppercase; letter-spacing: .4px; flex-shrink: 0;
}
.rel-since-row .date-field-inline { flex: 1; min-width: 150px; }
/* Im Lesemodus steht dort nur der fertige Satz. */
.rel-since-text {
  font-size: 13px; font-weight: 700; color: var(--muted);
  padding: 6px 2px 2px;
}

.rel-type-toggle {
  flex-shrink: 0; border: 1px solid #e0d3ba; background: #fff; border-radius: 999px;
  font-family: inherit; font-size: 12px; font-weight: 700; color: var(--muted);
  padding: 8px 12px; min-height: 36px; cursor: pointer;
}
.rel-type-toggle.is-ex { color: var(--focus-dark); border-color: var(--pink); background: #fdf0f4; }
/* 36px Tippfläche statt eines winzigen Kreuzes */
.rel-row-remove {
  flex-shrink: 0; border: none; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; font-size: 18px; line-height: 1;
  color: var(--muted); padding: 0; border-radius: 8px;
}
.rel-row-remove:hover { color: #b3261e; background: #fdecec; }
.rel-empty { font-size: 13px; color: var(--muted); margin-bottom: 8px; }

.check-list { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.check-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  text-align: left; font-family: inherit; cursor: pointer; min-width: 0;
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 10px;
  padding: 12px; min-height: 52px; flex-wrap: wrap;
}
.check-row:hover { background: #fdf0ec; border-color: var(--pink); }
.check-row-name { font-weight: 700; font-size: 14.5px; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.check-row-reason { font-size: 12.5px; color: var(--focus-dark); }

/* ---------- Änderungshistorie ---------- */
.change-log-list { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.change-log-day {
  font-size: 11.5px; font-weight: 800; letter-spacing: .5px; color: var(--muted);
  margin: 14px 2px 2px;
}
.change-log-day:first-child { margin-top: 4px; }
.change-log-row {
  display: flex; align-items: flex-start; gap: 10px; min-width: 0; text-align: left;
  font-family: inherit; background: #faf7ef;
  border: 1px solid var(--card-border); border-radius: 10px; padding: 12px;
}
.change-log-icon {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%;
  background: #e4ecff; color: #3b5bdb; display: flex; align-items: center;
  justify-content: center; font-size: 13px;
}
.change-log-body { min-width: 0; flex: 1; }
.change-log-field { font-weight: 800; font-size: 14px; color: var(--ink); }
.change-log-person { font-size: 12.5px; color: var(--muted); margin-top: 1px; }
.change-log-editor { font-size: 11.5px; color: var(--muted); margin-top: 4px; }
/* Eigener Rückgängig-Knopf rechts in der Zeile (siehe renderChangeLog) -
   macht auf einen Blick klar, welche Aktion ein Antippen auslöst, statt
   die ganze Zeile unklar klickbar zu machen. */
.change-log-undo {
  flex-shrink: 0; align-self: center; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--card-border); background: #fff; color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-family: inherit; margin-left: auto;
}
.change-log-undo:hover { border-color: var(--focus); color: var(--focus); background: #fdf0ec; }
/* Kein Rückgängig-Knopf möglich (siehe renderChangeLog) - rein informativ,
   etwas gedämpfter, damit klar ist, dass hier nichts zu tun ist. */
.change-log-row.not-restorable { opacity: .65; }

/* ---------- Aktivitäten (Timeline) ---------- */
/* touch-action: pan-y nimmt dem Browser die Pinch-Geste ueber diesem
   Bereich - hoch- und runterscrollen geht weiter, herauszoomen nicht mehr.
   Statistik und Karte verhielten sich schon so (die Karte faengt die Geste
   selbst ab), die Aktivitaet liess sich als Einzige noch verkleinern. */
#dashActivityPage { touch-action: pan-y; }
.activity-list { display: flex; flex-direction: column; gap: 8px; }

/* Tages-Boxen oberhalb der Timeline (Geburtstag/Jahrestag/Foto-Rückblick) -
   ersetzen die frühere Filterleiste. Waagrecht scrollbar, damit auch mehrere
   Boxen an einem Tag (z. B. zwei Geburtstage) nicht umbrechen müssen.
   Jede Box hat eine FEST VERDRAHTETE Breite UND Höhe plus overflow:hidden
   direkt auf der Karte selbst - so kann ein grosses/querformatiges Foto sie
   niemals aufweiten, ganz gleich wie das Bild selbst zugeschnitten ist. */
.activity-highlights {
  display: flex; gap: 10px; overflow-x: auto; padding: 2px 2px 12px;
  margin-bottom: 4px; -webkit-overflow-scrolling: touch;
  /* Ausnahme zum pan-y der Seite darueber: DIESE Reihe scrollt waagrecht. */
  touch-action: pan-x;
}
.activity-highlights.hidden { display: none; }
/* Kleiner als zuvor, und das Bild füllt die GESAMTE Box (kein separater
   30%-Textstreifen mehr) - nur noch ein schmaler, dunkler Farbverlauf ganz
   unten, gerade genug, damit der kurze weisse Text über jedem Foto lesbar
   bleibt, egal wie hell das Foto selbst ist. */
.activity-highlight-card {
  flex: 0 0 auto; width: 120px; height: 150px; position: relative;
  border-radius: 14px; overflow: hidden; cursor: pointer;
  background: var(--ahc-tint, #faf7ef); border: 1px solid var(--card-border-soft);
  box-shadow: var(--shadow-sm);
  transition: transform .16s ease, box-shadow .16s ease;
}
.activity-highlight-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.activity-highlight-card.ahc-birthday { --ahc-tint: #f6dfc4; }
.activity-highlight-card.ahc-anniversary { --ahc-tint: #d9d6ce; }
.activity-highlight-card.ahc-photo { --ahc-tint: #e7ddc9; }
/* Vollbild-Foto (Erinnerung) bzw. Profilbild/Silhouette (Geburtstag/
   Jahrestag) - füllt die komplette Karte, exakt zugeschnitten über
   object-fit statt die Karte an das Bildformat anzupassen. */
.ahc-image {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}
/* Namens-Karte statt Standard-Silhouette: Geburtstag/Jahrestag OHNE
   eigenes Foto der Person - ein farbiger Verlauf (siehe nameCardGradient
   in app.js, stabil pro Person) mit dem Vornamen direkt im Text
   ("Maria wird heute 25!"). Löst die frühere Verwechslungsgefahr zweier
   namensgleicher, foto-loser Karten am selben Tag. */
.ahc-namecard-bg { position: absolute; inset: 0; }
.activity-highlight-card.ahc-namecard .ahc-gradient { display: none; }
/* Grossformatiges, sehr dezentes Symbol unten rechts - füllt die zuvor
   leere Fläche der Farbkarte, ohne mit dem Kreis/Text zu konkurrieren. */
.ahc-namecard-watermark {
  position: absolute; right: -10px; bottom: -14px; font-size: 76px;
  opacity: .16; line-height: 1; transform: rotate(-8deg);
  filter: grayscale(1) brightness(1.6); pointer-events: none;
}
/* Initialen-Kreis - sitzt oberhalb des Namens, wie bei einer Kontakt-Kachel. */
.ahc-namecard-avatar {
  position: absolute; top: 18px; left: 50%; transform: translateX(-50%);
  width: 40px; height: 40px; border-radius: 50%;
  background: rgba(255,255,255,.22); border: 1.5px solid rgba(255,255,255,.55);
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 15px; font-weight: 800; letter-spacing: .3px;
  text-shadow: 0 1px 2px rgba(0,0,0,.25);
}
.activity-highlight-card.ahc-namecard .ahc-text {
  position: absolute; left: 10px; right: 10px; bottom: 14px; top: auto;
  text-align: center; font-size: 13.5px; line-height: 1.3; font-weight: 700;
}
/* Schmaler, dunkler Farbverlauf ganz unten - nur für die Lesbarkeit des
   Textes, deckt bewusst nicht mehr die halbe Karte ab wie zuvor. */
.ahc-gradient {
  position: absolute; left: 0; right: 0; bottom: 0; height: 48%;
  background: linear-gradient(to bottom, transparent 0%, rgba(30,20,10,.72) 100%);
}
.ahc-text {
  position: absolute; left: 8px; right: 8px; bottom: 7px;
  font-size: 12px; font-weight: 700; color: #fff; line-height: 1.25;
  text-shadow: 0 1px 3px rgba(0,0,0,.45);
}

.activity-row {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  background: #fff; border: 1px solid var(--card-border-soft); border-radius: 14px;
  padding: 11px 13px; box-shadow: var(--shadow-sm);
}
.activity-avatar-wrap { position: relative; flex-shrink: 0; }
.activity-avatar.avatar-img, .activity-avatar.avatar-placeholder { width: 40px; height: 40px; }
.activity-icon-badge {
  position: absolute; right: -4px; bottom: -4px; width: 19px; height: 19px;
  border-radius: 50%; background: #fff; border: 1px solid var(--card-border);
  display: flex; align-items: center; justify-content: center; font-size: 11px;
  line-height: 1;
}
.activity-body { min-width: 0; flex: 1; }
.activity-text { font-weight: 700; font-size: 14px; color: var(--ink); }
.activity-time { font-size: 12px; color: var(--muted); margin-top: 2px; }
.activity-photo-thumb {
  flex-shrink: 0; width: 44px; height: 44px; border-radius: 10px;
  object-fit: cover; border: 1px solid var(--card-border);
}

.rel-add-row { position: relative; min-width: 0; }
.rel-search-input {
  width: 100%; min-width: 0; padding: 11px 12px; border: 1px solid #e0d3ba;
  border-radius: 10px; font-family: inherit; font-size: 16px; background: #fff;
}
.rel-search-input:focus { outline: none; border-color: var(--focus); }
.rel-search-results {
  position: absolute; left: 0; right: 0; top: calc(100% + 4px); z-index: 20;
  background: #fff; border: 1px solid #f0e6c8; border-radius: 10px;
  box-shadow: 0 8px 20px rgba(0,0,0,.12); max-height: 200px; overflow-y: auto;
}
.rel-search-result {
  padding: 12px; min-height: 46px; display: flex; align-items: center;
  font-size: 14.5px; font-weight: 600; cursor: pointer;
}
.rel-search-result:hover { background: #fdf0ec; color: var(--focus-dark); }
.rel-search-empty { padding: 8px 12px; font-size: 13px; color: var(--muted); }
.rel-search-create { color: var(--focus); font-weight: 700; }
.rel-search-create:hover { background: #fdf0ec; }
#editPanel.read-only .rel-add-row, #editPanel.read-only .rel-row-remove, #editPanel.read-only .rel-type-toggle { display: none; }

/* Partner-Karte (Familie-Tab): umschließt die Partnerschaft selbst UND
   die mit ihr gemeinsamen Kinder in einer Box - an das mitgeschickte
   Referenzbild angelehnt. */
.rel-partner-card {
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 10px;
  padding: 10px; margin-bottom: 10px;
}
.rel-partner-top { background: none; border: none; padding: 0 0 8px; }
.rel-shared-kids-title {
  font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); font-weight: 700; margin: 6px 0 6px; padding-top: 8px;
  border-top: 1px solid var(--card-border);
}
.rel-shared-kids-list .rel-row, .rel-partner-card .rel-search-input { background: #fff; }

/* ---------- Toast ---------- */
.toast {
  position: fixed; bottom: calc(var(--nav-h) + 16px); left: 50%; transform: translateX(-50%);
  background: var(--ink); color: #fff; padding: 10px 22px;
  border-radius: 999px; font-weight: 700; z-index: 100;
  animation: toastIn .2s ease;
}
@keyframes toastIn { from { opacity: 0; transform: translate(-50%, 8px); } }

/* Dezenter, anklickbarer Rückgängig-Hinweis - erscheint kurz nach
   Löschaktionen und verschwindet von selbst wieder, statt wie zuvor als
   dauerhafter Button in der unteren Leiste zu stehen. Bewusst gedämpfter
   als der normale Toast (heller Hintergrund, dünner Rand statt Vollton),
   damit er nicht mit den aktiven Gold-Buttons konkurriert. Dauerhafter
   Zugriff auf Rückgängig bleibt zusätzlich im Werkzeuge-Menü erhalten.
   Etwas höher positioniert als .toast, damit sich beide nicht überlappen,
   falls eine Löschaktion zusätzlich eine normale Erfolgsmeldung auslöst. */
.undo-toast {
  position: fixed; bottom: calc(var(--nav-h) + 60px); left: 50%; transform: translateX(-50%);
  background: var(--paper, #fff); color: var(--ink);
  border: 1px solid rgba(0,0,0,.14);
  padding: 8px 18px; border-radius: 999px; font-weight: 600; font-size: 13px;
  box-shadow: 0 2px 10px rgba(0,0,0,.1);
  z-index: 100; cursor: pointer;
  animation: toastIn .2s ease, undoFadeOut .25s ease 2.55s forwards;
}
.undo-toast:hover { border-color: rgba(0,0,0,.28); }
@keyframes undoFadeOut { to { opacity: 0; transform: translate(-50%, 6px); } }

/* ---------- Mobil ---------- */
@media (max-width: 640px) {
  :root {
    --panel-w: 100vw;
    --header-h: calc(52px + env(safe-area-inset-top, 0px));
    --nav-h: calc(60px + env(safe-area-inset-bottom, 0px));
  }

  /* Topbar kompakt: Logo klein, Modus-Umschalter und Sign-in passen in eine Zeile */
  .topbar {
    height: var(--header-h); padding-left: 10px; padding-right: 10px; gap: 8px;
    flex-wrap: nowrap;
  }
  .logo { padding: 6px 9px; font-size: 12px; letter-spacing: .5px; flex-shrink: 0; }
  .logo-text { display: none; }
  .logo-icon { display: block; }
  /* Infozeile bekommt den ganzen verbleibenden Platz und kürzt statt zu drängeln.
     Die Polsterung der Kapsel selbst kommt bewusst NUR aus dem
     @media(max-width:620px)-Block oben (gleiche Höhe wie das Logo) - hier
     keine zweite, abweichende padding-Regel mehr definieren. */
  .tree-info { font-size: 12px; gap: 5px; }
  .topbar-right { gap: 2px; }
  .invite-bar { padding: 7px 12px; font-size: 12.5px; gap: 6px 10px; }
  .invite-bar-note { font-size: 11.5px; }
  .topnav {
    display: flex; align-items: center; gap: 8px;
    margin-left: auto; min-width: 0;
  }

  /* Gast-Banner: unterhalb der Topbar, volle Breite, nicht mehr überlappend */
  .guest-banner {
    left: 8px; right: 8px; top: 8px; transform: none;
    border-radius: 12px; padding: 8px 12px; font-size: 12px;
    flex-direction: column; gap: 4px; text-align: center;
  }
  .guest-banner .btn-link { font-size: 12px; }

  /* Bewusst KEIN eigenes Andocken am unteren Rand mehr für die Suche: bei
     geöffneter Bildschirmtastatur landete das Eingabefeld dadurch hinter
     der Tastatur (nicht mehr erreichbar). Die Suche bleibt stattdessen
     immer oben verankert (siehe .search-panel oben, direkt neben der
     Lupe) und schiebt sich von dort seitlich heraus - das funktioniert
     auf jeder Bildschirmgrösse gleich und bleibt auch mit offener
     Tastatur immer sichtbar. */
}

/* iOS: kein automatisches Text-Vergrößern im Querformat, keine Tap-Highlights */
html {
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}
/* Verhindert, dass Safari beim Ziehen die ganze Seite mitbewegt */
#canvasWrap { touch-action: none; overscroll-behavior: none; }
body { overscroll-behavior: none; }
/* Solange ein Fenster offen ist, darf der Hintergrund nicht mitscrollen
   (sonst "rutscht" in der Übersicht/Kalender-Ansicht die Seite unter dem
   Fenster weg). Wird in app.js automatisch gesetzt. */
html.modal-open, html.modal-open body { overflow: hidden !important; }

/* ---------- Modal-Overlays (Login/Signup, Teilen) ---------- */
.modal-overlay {
  position: fixed; inset: 0; background: rgba(15,20,35,.45);
  display: flex; align-items: center; justify-content: center; z-index: 60;
  padding: 16px;
}
.modal-card {
  background: #fff; border-radius: 16px; padding: 28px 26px;
  width: 380px; max-width: 100%; max-height: 88vh;
  overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain;
  position: relative; box-shadow: 0 20px 60px rgba(0,0,0,.25);
}
/* Nichts in einem Fenster darf breiter werden als das Fenster selbst -
   das war die Ursache für das seitliche Wischen/Scrollen auf dem Handy. */
.modal-card, .modal-card *:not(svg):not(svg *) { max-width: 100%; }
/* Bestätigungsdialoge (Ja/Abbrechen) können AUS anderen Overlays heraus
   ausgelöst werden (z. B. aus dem Profilmenü beim Wiederherstellen einer
   Änderung) - müssen deshalb IMMER über allen anderen Overlays liegen,
   nicht nur mit derselben z-index wie diese (sonst gewinnt je nach
   DOM-Reihenfolge das andere Overlay und der Dialog bleibt unsichtbar
   dahinter verborgen). */
#confirmDialog { z-index: 90; }
#iosInstallModal { z-index: 80; }
/* Das Beitritts-/„Wer bist du?"-Fenster kann AUS dem Profilmenü heraus
   geöffnet werden und muss deshalb darüber liegen. */
#joinPanel { z-index: 85; }
.modal-card.profile-card { width: 420px; max-height: 88vh; }

.modal-card.confirm-modal-card { width: 340px; padding: 26px 24px; text-align: center; }
.confirm-modal-card p { font-size: 15.5px; font-weight: 700; color: var(--ink); margin-bottom: 20px; }
.confirm-dialog-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.confirm-dialog-actions .btn { flex: 1 1 120px; min-height: 46px; }

#guestMergeModal { z-index: 95; }
.modal-card.guest-merge-card { width: 400px; padding: 30px 24px 26px; text-align: center; }
.guest-merge-icon {
  width: 72px; height: 72px; border-radius: 50%; background: #f5e9db;
  color: var(--ink); display: flex; align-items: center; justify-content: center;
  margin: 0 auto 16px;
}
.guest-merge-title {
  font-size: 21px; font-weight: 800; color: var(--ink); line-height: 1.25;
  margin-bottom: 10px;
}
.guest-merge-intro { font-size: 15px; color: var(--muted); margin-bottom: 20px; }
.guest-merge-options { display: flex; flex-direction: column; gap: 12px; text-align: left; }
.guest-merge-option {
  display: flex; align-items: center; gap: 14px; width: 100%;
  padding: 14px 16px; border-radius: 16px;
  border: 1px solid var(--card-border); background: #fff; cursor: pointer;
  /* Buttons erben in Browsern standardmässig NICHT die Schrift vom body -
     ohne diese Zeile wird der Button-Text in der System-Schrift dargestellt
     statt in 'Nunito' wie der Dialog-Titel. */
  font-family: inherit;
}
.guest-merge-option:hover { border-color: var(--focus); background: #fdf0ec; }
.guest-merge-option-icon {
  flex-shrink: 0; width: 46px; height: 46px; border-radius: 50%;
  background: #f5e9db; color: var(--ink);
  display: flex; align-items: center; justify-content: center;
}
.guest-merge-option-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.guest-merge-option-label { font-size: 15px; font-weight: 800; color: var(--ink); }
.guest-merge-option-desc { font-size: 12.5px; color: var(--muted); line-height: 1.35; }
.guest-merge-option-chevron { flex-shrink: 0; color: var(--ink); opacity: .55; }
.guest-merge-upsell.hidden { display: none; }
.guest-merge-divider { display: flex; align-items: center; gap: 10px; margin: 20px 0 14px; }
.guest-merge-divider::before, .guest-merge-divider::after {
  content: ''; flex: 1; height: 1px; background: var(--card-border);
}
.guest-merge-divider-dot {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%;
  background: #f5e9db; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
}
.guest-merge-upsell-row { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 16px; text-align: left; }
.guest-merge-upsell-icon {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%;
  background: #f5e9db; color: var(--focus);
  display: flex; align-items: center; justify-content: center; margin-top: 1px;
}
.guest-merge-upsell-row p { font-size: 14px; color: var(--ink); line-height: 1.4; }
.guest-merge-upsell-row strong { font-weight: 800; }
.guest-merge-cta {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; padding: 15px 20px; border-radius: 999px; border: none;
  background: var(--focus); color: #fff; font-size: 15.5px; font-weight: 800;
  cursor: pointer;
  font-family: inherit;
}
.guest-merge-cta:hover { filter: brightness(1.05); }
.guest-merge-cta-icon {
  flex-shrink: 0; width: 22px; height: 22px; border-radius: 50%; background: #fff;
  display: flex; align-items: center; justify-content: center;
}
.profile-menu-list { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.profile-menu-row {
  display: flex; align-items: center; gap: 14px;
  background: none; border: none; text-align: left; min-width: 0;
  min-height: 52px; padding: 12px 6px; margin: 0 -6px;
  font-family: inherit; font-size: 15.5px; font-weight: 700;
  color: var(--ink); cursor: pointer; border-radius: 10px;
}
.profile-menu-row > span { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.profile-menu-row svg { flex-shrink: 0; }
.profile-menu-row:hover { background: #f6efd9; }
.profile-menu-row:active { background: #f0e7cd; }
.profile-menu-row.danger { color: var(--red); }
.profile-menu-row > span:first-of-type { margin-right: auto; }
.pm-chevron { margin-left: 0; color: var(--muted); font-size: 20px; font-weight: 400; flex-shrink: 0; }

/* ---------- Dashboard ---------- */
.dash-wrap { max-width: 720px; margin: 0 auto; padding: 28px 20px 40px; }
.dash-title { font-size: 24px; font-weight: 800; margin-bottom: 22px; }

.stat-section-label {
  font-size: 12.5px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); margin: 30px 0 12px;
}
.stat-section-label:first-of-type { margin-top: 0; }

/* Drei Kästchen statt zwei: auf schmalen Geräten umbrechen lassen, sonst
   quetschen sich die Zahlen und die Beschriftungen brechen mitten im Wort. */
.stat-numbers-row { display: flex; gap: 14px; flex-wrap: wrap; }
.stat-number-box {
  flex: 1 1 150px; min-width: 0; background: #f6f3ec; border-radius: 14px; padding: 16px 18px;
}
.stat-number-value { font-size: 26px; font-weight: 800; color: var(--ink); }
.stat-number-label { font-size: 14px; color: var(--ink); font-weight: 600; margin-top: 2px; }
.stat-number-sublabel { font-size: 12px; color: var(--muted); margin-top: 1px; }

.stat-two-col { display: flex; gap: 28px; margin-top: 8px; flex-wrap: wrap; }
.stat-block { flex: 1 1 240px; min-width: min(240px, 100%); }
.stat-block-title { font-size: 14.5px; font-weight: 800; color: var(--ink); margin-bottom: 10px; }

.stat-bar-track {
  display: flex; width: 100%; height: 9px; border-radius: 999px;
  overflow: hidden; background: #f0ece0;
}
.stat-bar-segment { height: 100%; }
.stat-legend { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 10px; }
.stat-legend-item { display: flex; align-items: center; gap: 6px; font-size: 13px; }
.stat-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.stat-legend-label { color: var(--ink); font-weight: 700; }
.stat-legend-value { color: var(--muted); }

.age-row { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
.age-label { width: 70px; flex-shrink: 0; font-size: 13.5px; color: var(--ink); font-weight: 600; }
.age-bar-track { flex: 1; height: 8px; border-radius: 999px; background: #f0ece0; overflow: hidden; }
.age-bar-fill { height: 100%; background: var(--focus); border-radius: 999px; }
.age-count { width: 24px; text-align: right; flex-shrink: 0; font-size: 13px; color: var(--muted); font-weight: 700; }

.completeness-text { font-size: 13.5px; color: var(--ink); margin-bottom: 8px; }
.completeness-bar-track { width: 100%; height: 9px; border-radius: 999px; background: #f0ece0; overflow: hidden; }
.completeness-bar-fill { height: 100%; background: var(--gold); border-radius: 999px; }

/* ---------- Übersicht: Unter-Tabs (Zahlen / Karte) ---------- */
/* Die Reiterleiste steht jetzt auf farbigem Grund - als eigene weisse
   Flaeche mit Schatten wirkt sie dort wie eine Karte statt wie ein
   abgeschnittener Streifen. */
.dash-tabs { margin-bottom: 22px; border-radius: 14px; overflow: hidden; box-shadow: var(--shadow-sm); }
.dash-tabs .edit-tabs { border-bottom: none; }
.dash-tab-page.hidden { display: none; }

/* ---------- Weltkarte ----------
 * Farben folgen dem Kategorie-Schema (fest zugeordnet, nie zyklisch):
 * Geburtsorte Blau, Wohnorte Orange, Sterbeorte Aqua/Grün - dieselben drei
 * Kapseln dienen zugleich als Legende (Punkt + Beschriftung), Farbe steht
 * also nie allein für die Bedeutung.
 */
.map-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.map-filter-group { display: flex; gap: 8px; flex-wrap: wrap; }
.map-chip {
  position: relative; display: inline-flex; align-items: center; gap: 7px; min-height: 40px;
  padding: 8px 13px; border-radius: 999px; cursor: pointer;
  background: #fff; border: 1px solid var(--card-border);
  font-size: 13.5px; font-weight: 700; color: var(--muted);
}
.map-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.map-chip-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; background: #ccc; }
.map-chip-birth .map-chip-dot { background: #2a78d6; }
.map-chip-residence .map-chip-dot { background: #eb6834; }
.map-chip-death .map-chip-dot { background: #1baf7a; }
.map-chip.is-on { background: #faf7ef; border-color: var(--card-border); color: var(--ink); }
.map-chip.is-off { opacity: .55; }
.map-chip.is-off .map-chip-dot { background: #d8d3c4 !important; }
.map-chip-count { color: var(--muted); font-weight: 700; font-variant-numeric: tabular-nums; }
.map-heat-toggle {
  display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0;
  font-size: 13.5px; font-weight: 700; color: var(--ink); cursor: pointer;
}

.map-people-picker { margin-bottom: 14px; }
.map-people-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 8px; font-size: 13px; font-weight: 700; color: var(--muted);
}
.map-people-chosen { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.map-person-chip {
  display: inline-flex; align-items: center; gap: 6px; min-height: 38px;
  padding: 5px 6px 5px 13px; border-radius: 999px;
  background: var(--focus-light); border: 1px solid var(--pink);
  font-size: 13.5px; font-weight: 700; color: var(--focus-dark);
}
.map-person-chip button {
  flex-shrink: 0; border: none; background: none; cursor: pointer;
  width: 26px; height: 26px; border-radius: 50%; color: inherit;
  display: flex; align-items: center; justify-content: center; padding: 0;
}
.map-person-chip button:hover { background: rgba(0,0,0,.08); }

.map-container {
  width: 100%; height: min(60vh, 520px); min-height: 320px;
  border-radius: 16px; overflow: hidden; border: 1px solid var(--card-border);
  background: #eef1ea;
  /* Leaflet vergibt seinen Ebenen/Steuerelementen intern z-index-Werte bis
     1000. Ohne eigenen Stapelkontext "leaken" die in den Wurzel-Kontext und
     landen dort über fixierten Elementen wie der Topbar (z-index: 40) oder
     den Suchergebnissen - genau der gemeldete Fehler "Karte erscheint über
     allem beim Scrollen/Suchen". isolation:isolate kapselt die Karte in
     ihren eigenen Stapelkontext, ihre internen z-index-Werte wirken dann
     nur noch untereinander, nie mehr gegen den Rest der Seite. */
  position: relative;
  isolation: isolate;
  z-index: 0;
}
/* Schrift und Ecken der Kartenbedienelemente an den Rest der App angleichen */
.map-container .leaflet-popup-content-wrapper,
.map-container .leaflet-popup-tip { font-family: inherit; border-radius: 10px; }
.map-container .leaflet-popup-content { font-size: 13.5px; margin: 10px 12px; }
.map-container .leaflet-control-zoom a { border-radius: 8px !important; }
.map-container .leaflet-div-icon { background: transparent; border: none; }
.map-popup-title { font-weight: 800; color: var(--ink); margin-bottom: 2px; }
.map-popup-sub { font-size: 12px; color: var(--muted); margin-bottom: 6px; }
.map-popup-person { padding: 2px 0; color: var(--ink); }
.map-popup-more { color: var(--muted); font-style: italic; }
.map-pin {
  width: 20px; height: 20px; border-radius: 50%;
  background: var(--pin-color, #2a78d6); border: 2px solid #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.35);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 800; color: #fff; font-family: inherit;
}
.map-arrow-icon {
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; line-height: 1; color: var(--focus-dark);
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.35));
}
.map-empty-hint { margin-top: 12px; text-align: center; }
.map-attribution { margin: 8px 2px 0; font-size: 11px; color: var(--muted); text-align: right; }
.map-attribution a { color: inherit; }

@media (max-width: 640px) {
  .map-toolbar { flex-direction: column; align-items: stretch; }
  .map-heat-toggle { justify-content: space-between; }
  .map-container { height: min(50vh, 420px); }
}

/* ---------- Ortsfelder (Geburts-, Wohn-, Sterbeort) ----------
 * Autovervollständigung, die nur echte Treffer zulässt: getippter Text, der
 * nie ausgewählt wurde, springt beim Verlassen des Feldes zurück - dafür
 * dieser kleine "Schüttel"-Hinweis. */
.place-input-wrap { position: relative; min-width: 0; }
/* Mit "#editPagePerson" davor, damit das hier gewinnt statt der
   allgemeinen "#editPagePerson .field-input { padding: 6px 0 }" (gleiche
   ID + eine Klasse schlägt sonst zwei blosse Klassen, unabhängig von der
   Reihenfolge im Stylesheet) - sonst hatte das Feld gar keinen reservierten
   Platz mehr für den Standort-Knopf, und ein langer Ortsname lief optisch
   direkt hinter das Knopf-Symbol statt daneben aufzuhören. Zusätzlich mit
   "…" abgeschnitten statt einfach nur beschnitten - die volle Adresse
   erscheint per Hover (title, siehe app.js). */
#editPagePerson .place-input-wrap .field-input {
  padding-right: 42px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.place-suggest { font-size: 14px; }
.place-suggest .rel-search-result { flex-direction: column; align-items: flex-start; gap: 1px; }
.place-suggest .rel-search-result-sub { font-size: 12px; color: var(--muted); font-weight: 500; }
@keyframes place-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-4px); }
  40% { transform: translateX(4px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}
.field-input.place-input-shake { animation: place-shake .35s ease; border-color: #e0776f; }

/* Standort-Button im Ortsfeld selbst - öffnet den Standort-Wähler
   (Karten-Klick oder aktueller GPS-Standort). */
.place-locate-btn {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  width: 30px; height: 30px; border-radius: 8px; border: none;
  background: transparent; color: var(--muted); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.place-locate-btn:hover { background: #f0e9d6; color: var(--focus-dark); }
.place-locate-btn.hidden { display: none; }

/* ---------- Standort wählen (Modal mit Mini-Karte) ---------- */
.place-picker-card { width: min(520px, 92vw); display: flex; flex-direction: column; gap: 10px; }
.place-picker-title { margin: 0; font-size: 18px; font-weight: 800; color: var(--ink); }
.place-picker-hint { margin: -4px 0 2px; font-size: 13px; color: var(--muted); }
.place-picker-gps-btn { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; }
.place-picker-map {
  width: 100%; height: min(42vh, 320px); min-height: 220px;
  border-radius: 12px; overflow: hidden; border: 1px solid var(--card-border);
  background: #eef1ea; position: relative; isolation: isolate; z-index: 0;
}
.place-picker-result { min-height: 18px; font-size: 13.5px; font-weight: 600; color: var(--ink); margin: 0; }

/* ---------- Abo Plus ----------
   Eigene Unter-Seite, eine Ebene unter "Mein Konto". */
.pm-plan-badge {
  padding: 3px 10px; border-radius: 999px;
  font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  background: #efe6d5; color: var(--muted);
}
.pm-plan-badge.is-plus {
  background: linear-gradient(135deg, var(--gold), var(--gold-dark)); color: #fff;
}


.plan-tree-hint {
  margin-bottom: 14px; padding: 11px 14px; border-radius: 12px;
  font-size: 13.5px; line-height: 1.5;
}
.plan-tree-hint.is-plus { background: #fbf3de; color: #6f5300; border: 1px solid #eddfba; }
.plan-tree-hint.is-free { background: var(--focus-light); color: var(--focus-dark); border: 1px solid #eccfda; }

.plan-usage-group { margin-bottom: 14px; }
.plan-usage-list { display: flex; flex-direction: column; gap: 13px; }
.plan-usage-row { display: flex; flex-direction: column; gap: 6px; }
.plan-usage-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 10px;
  font-size: 14px; font-weight: 600; color: var(--ink);
}
.plan-usage-value { font-size: 13px; font-weight: 800; color: var(--muted); white-space: nowrap; }
.plan-usage-track { height: 8px; border-radius: 999px; background: #eee3cd; overflow: hidden; }
.plan-usage-track > i {
  display: block; height: 100%; background: #1fae63; border-radius: 999px;
  transition: width .25s ease;
}
.plan-usage-track > i.is-warn { background: var(--gold); }
.plan-usage-track > i.is-full { background: var(--red); }

/* Vergleichstabelle: ausklappbar, damit der Abschnitt kurz bleibt. */
.plan-compare {
  border: 1px solid var(--card-border); border-radius: 12px;
  background: #fffdf6; margin-bottom: 16px;
}
.plan-compare > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 14px; cursor: pointer; list-style: none;
  font-size: 13.5px; font-weight: 800; color: var(--ink);
  border-radius: 12px;
}
.plan-compare > summary::-webkit-details-marker { display: none; }
.plan-compare > summary:hover { background: #faf7ef; }
.plan-compare-chevron { flex-shrink: 0; color: var(--muted); transition: transform .22s cubic-bezier(.22,.7,.3,1); }
.plan-compare[open] .plan-compare-chevron { transform: rotate(180deg); }
.plan-compare-body { padding: 0 14px 12px; }
.plan-compare[open] .plan-compare-body { animation: planCompareOpen .24s cubic-bezier(.22,.7,.3,1); }
@keyframes planCompareOpen {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.plan-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.plan-table th, .plan-table td { padding: 9px 6px; text-align: center; }
.plan-table thead th {
  font-size: 11px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); font-weight: 800; border-bottom: 1px solid var(--card-border);
}
.plan-table tbody th {
  text-align: left; font-weight: 600; color: var(--ink);
  border-bottom: 1px solid var(--card-border);
}
.plan-table tbody td {
  font-weight: 700; color: var(--muted); border-bottom: 1px solid var(--card-border);
}
.plan-table tbody td.is-plus-col { color: var(--gold-dark); }

.plan-upgrade-btn { width: 100%; margin-bottom: 8px; }
.plan-upgrade-btn:disabled { opacity: .65; cursor: default; }
.plan-thanks { color: #2e6b45; font-weight: 700; }

/* Statuskarte ganz oben auf "Abo Plus": aktueller Tarif und, sobald Plus
   läuft, das Datum der nächsten Zahlung. */
.plan-status {
  background: #fffbf1; border: 1px solid #eddfba; border-radius: 14px;
  padding: 16px 18px; margin-bottom: 16px;
}
.plan-status-name {
  font-family: var(--font-display); font-size: 22px; font-weight: 400;
  letter-spacing: -.2px; color: var(--ink); margin-bottom: 3px;
}
.plan-status-name.is-plus { color: var(--gold-dark); }
.plan-status-sub { font-size: 13.5px; color: var(--muted); line-height: 1.5; }

/* ---------- Anmelde-Hinweis (Übersicht / Kalender / Medien ohne Konto) ---------- */
.signin-gate {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 10px; max-width: 400px; margin: 0 auto; padding: 11vh 24px 40px;
}
.signin-gate-icon {
  width: 100px; height: 100px; border-radius: 50%; margin-bottom: 4px;
  display: flex; align-items: center; justify-content: center;
  background: var(--focus-light); color: var(--focus);
}
.signin-gate h2 { font-size: 22px; }
.signin-gate p { color: var(--muted); font-size: 15px; line-height: 1.6; }
.signin-gate-btn { margin-top: 8px; min-width: 200px; }
.signin-gate-link { font-size: 14px; }
.signin-gate-note { margin-top: 6px; font-size: 12.5px; }

@media (max-width: 560px) {
  .signin-gate { padding-top: 7vh; }
  .signin-gate-icon { width: 84px; height: 84px; }
}

/* ---------- Medien-Ansicht (Galerie) ---------- */
.media-wrap { max-width: 1000px; margin: 0 auto; padding: 24px 20px 48px; }

.media-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-bottom: 14px;
}
.media-head .dash-title { margin: 0; }
.media-upload-btn { display: inline-flex; align-items: center; gap: 8px; }

/* Eigene Zeile UNTER der Überschrift - die Personenauswahl soll nicht
   neben dem Hochladen-Knopf stehen. */
.media-filter-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-bottom: 14px; margin-bottom: 16px;
  border-bottom: 1px solid var(--card-border);
}
.media-filter-label {
  font-size: 12.5px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); font-weight: 700;
}
.media-filter-select { max-width: 240px; }
/* Mehrere Personen gleichzeitig filterbar (z.B. "Max und Sabine") - eigene
   Zeilen-Variante ohne den unteren Rand von .media-people-list, die sonst
   für die Personenliste AM Foto selbst gedacht ist. */
.media-filter-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.media-count { margin-left: auto; font-size: 13.5px; color: var(--muted); font-weight: 700; }

.media-progress { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; }
.media-progress-track {
  flex: 1; height: 8px; border-radius: 999px; background: #eee3cd; overflow: hidden;
}
.media-progress-track > i { display: block; height: 100%; width: 0;
  background: var(--gold); transition: width .2s ease; }
.media-progress-text { font-size: 13px; color: var(--muted); font-weight: 700; white-space: nowrap; }

/* Leerer Zustand - gleiche Anmutung wie das noch leere Familienarchiv */
.media-empty-state {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 10px; padding: 12vh 20px 40px; max-width: 380px; margin: 0 auto;
}
.media-empty-icon {
  width: 96px; height: 96px; border-radius: 50%; margin-bottom: 6px;
  display: flex; align-items: center; justify-content: center;
  background: var(--focus-light); color: var(--focus);
}
.media-empty-state h2 { font-size: 21px; }
.media-empty-state p { color: var(--muted); font-size: 15px; line-height: 1.55; margin-bottom: 8px; }

.media-grid {
  display: grid; gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.media-tile {
  position: relative; padding: 0; border: 1px solid var(--card-border-soft);
  background: #f3ece0; border-radius: 14px; overflow: hidden; cursor: pointer;
  aspect-ratio: 1 / 1; display: block;
  box-shadow: var(--shadow-sm);
  transition: transform .16s ease, box-shadow .16s ease;
}
.media-tile:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.media-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-tile:hover img { filter: brightness(1.04); }
.media-tile-caption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 16px 8px 6px;
  font-size: 11.5px; font-weight: 700; color: #fff; text-align: left;
  background: linear-gradient(to top, rgba(0,0,0,.6), rgba(0,0,0,0));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------- Bildbetrachter ---------- */
.media-viewer-card {
  width: min(1040px, 96vw); max-width: none;
  max-height: 92vh;
  /* dvh statt vh, wo unterstützt: auf dem Handy verändert sich die Höhe
     der sichtbaren Fläche, wenn die Adressleiste beim Scrollen ein-/
     ausklappt - mit vh (immer bezogen auf die GRÖSSTMÖGLICHE Fläche)
     konnte die Karte dadurch kurz zu hoch wirken und Bild/Text
     verrutschten sichtbar ineinander; dvh folgt der tatsächlich
     sichtbaren Höhe. Browser ohne dvh ignorieren die Zeile und bleiben
     bei 92vh.
  */
  max-height: 92dvh;
  display: flex; flex-direction: column;
  /* Überschreibt NICHT nur max-height von .modal-card, sondern auch dessen
     overflow-y:auto - sonst sind zwei Bereiche gleichzeitig scrollbar
     (diese Karte UND .media-viewer-body weiter unten). Bei zu hohem Inhalt
     übernahm dann mal die äussere Karte das Scrollen: sie wanderte beim
     Scrollen als Ganzes nach oben, wodurch das Bild über den Text der
     Seitenleiste rutschte, statt dass nur ein einziger, innerer Bereich für
     sich scrollt. Scrollen bleibt jetzt ausschliesslich bei .media-viewer-body
     (Runde 55: vorher war stattdessen .media-viewer-side für sich allein der
     Scroll-Container, siehe dortiger Kommentar für den Grund der Umstellung). */
  overflow: hidden;
}
.media-viewer-body { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
.media-viewer-stage {
  position: relative;
  /* War ein dunkles Fast-Schwarz - bei Fotos, die nicht genau ins Format
     passen (object-fit: contain), blieb das als Rand sichtbar. Weiss
     passt besser zum hellen Erscheinungsbild der App. */
  background: #ffffff; display: flex; align-items: center; justify-content: center;
  flex-shrink: 0; overflow: hidden;
  /* Mindesthöhe, damit der Rahmen nicht auf 0 zusammenfällt, solange das
     Bild noch lädt oder ein Link einmal nicht auflösbar ist. */
  min-height: 200px;
}
.media-viewer-stage img {
  max-width: 100%; max-height: 40vh; display: block; object-fit: contain;
}
/* Pfeile zum vorigen/nächsten Foto - mittig links/rechts über dem Bild,
   nur sichtbar, wenn es in der aktuell geöffneten Liste tatsächlich ein
   Nachbar-Foto gibt (siehe openMediaViewer in app.js). */
.media-viewer-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px; border-radius: 50%; border: none;
  background: rgba(0, 0, 0, .38); color: #fff; cursor: pointer;
  display: flex; align-items: center; justify-content: center; padding: 0;
  transition: background .15s, transform .1s;
}
.media-viewer-nav:hover { background: rgba(0, 0, 0, .55); }
.media-viewer-nav:active { transform: translateY(-50%) scale(.92); }
.media-viewer-nav.hidden { display: none !important; }
.media-viewer-nav-prev { left: 10px; }
.media-viewer-nav-next { right: 10px; }
/* overflow-x explizit hidden: sonst macht der Browser aus "overflow-y:auto"
   automatisch AUCH "overflow-x:auto" (CSS-Spezifikation) - dadurch liess
   sich der Text bisher unbeabsichtigt nach links/rechts wegwischen, sobald
   irgendein Kind (z. B. ein Eingabefeld) auch nur 1px breiter war als die
   Spalte. overscroll-behavior: contain verhindert zusätzlich, dass ein
   Scrollen bis zum Rand dieser Box auf die Seite dahinter "durchschlägt" -
   auf dem Handy sonst eine mögliche Ursache für den gemeldeten Eindruck,
   Text und Bild würden sich beim Scrollen kurz überlappen. */
.media-viewer-side {
  padding: 18px 20px 22px; overflow-y: auto; overflow-x: hidden; min-height: 0;
  overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
  /* Füllt IMMER die restliche Höhe der Karte, auch wenn der Inhalt (z. B.
     ein Foto ohne verknüpfte Personen, kaum Angaben) kürzer ist als der
     verfügbare Platz - sonst blieb darunter die schwarze Bühnenfarbe der
     Karte sichtbar (gemeldet als "schwarzer Balken unten"). Ist der Inhalt
     stattdessen LÄNGER, sorgt overflow-y:auto weiterhin fürs Scrollen. */
  flex: 1 1 auto;
}
.media-viewer-side .rel-group + .rel-group { margin-top: 20px; }
/* Der Griff-Balken ergibt nur im schmalen (gestapelten) Fenster Sinn - im
   breiten Fenster stehen Bild und Angaben ohnehin nebeneinander (siehe
   @media (max-width: 899px) weiter unten für die sichtbare Version). */
.media-viewer-handle { display: none; }
.media-field-pair { display: flex; gap: 10px; }
.media-field-pair .field-row { flex: 1; min-width: 0; }
.media-notes-input { resize: vertical; min-height: 84px; font-family: inherit; line-height: 1.5; }
.media-viewer-meta { margin-top: 4px; }
.media-viewer-actions {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--card-border);
}

.media-people-list { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.media-person-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 999px;
  padding: 6px 6px 6px 12px; font-size: 13.5px; font-weight: 700; color: var(--ink);
}
.media-person-x {
  border: none; background: #efe6d5; color: var(--muted); cursor: pointer;
  width: 22px; height: 22px; border-radius: 50%; font-size: 15px; line-height: 1;
  font-family: inherit;
}
.media-person-x:hover { background: var(--pink); color: var(--focus-dark); }

/* Breites Fenster: Bild links, Angaben rechts nebeneinander. */
@media (min-width: 900px) {
  .media-viewer-body { flex-direction: row; }
  .media-viewer-stage { flex: 1 1 auto; min-width: 0; min-height: 320px; border-bottom-left-radius: var(--radius); }
  .media-viewer-stage img { max-height: 76vh; }
  .media-viewer-side { flex: 0 0 380px; border-left: 1px solid var(--card-border); }
}

/* ---------- Schmales Fenster: Foto als Vollbild, Angaben als Sheet ----------
   Vorher steckte das Bild in einer normalen weissen Karte mit sichtbarem
   Rand ringsum, darunter ein einfaches Formular - im Vergleich zur Foto-App
   des Handys (randloses Bild, Angaben als von unten hochziehendes,
   abgerundetes Blatt) wirkte das schmucklos. Ab hier: dieselbe Kopfzeile/
   Angaben-Struktur wie zuvor, nur neu angeordnet und eingefärbt - keine
   neue Logik, der bestehende Schrumpf-Effekt beim Scrollen (siehe
   applyMediaStageShrink in app.js) bleibt unverändert bestehen und wirkt
   auf die jetzt grössere Bühne genauso. */
@media (max-width: 899px) {
  /* Ohne dies bliebe rund um die randlose Karte weiterhin der übliche
     16px-Rahmen des Overlays stehen (siehe .modal-overlay oben) - #mediaViewer
     als sicherer Rückfall für Browser ohne :has(). */
  .modal-overlay:has(> .media-viewer-card), #mediaViewer {
    padding: 0; align-items: stretch; justify-content: stretch;
  }
  /* Zwei Klassen wie .modal-card.media-viewer-card, damit dies auch die
     spätere, ebenfalls zweiklassige Vollbild-Regel unter 640px
     (".modal-card { padding: 20px 16px ... }" weiter unten in dieser
     Datei) zuverlässig überstimmt - sonst bliebe dort ein 16-20px breiter
     weisser Rand um Bild und Blatt stehen. */
  .modal-card.media-viewer-card {
    padding: 0; background: #000;
    /* Randlos über die komplette Fläche - bisher galt das erst unter 640px
       (die allgemeine Vollbild-Regel für Fenster), zwischen 640-899px blieb
       die Karte trotz gestapeltem Bild+Angaben-Layout noch als schwebendes,
       abgerundetes Kärtchen stehen. Jetzt durchgängig bis zur selben
       Schwelle (900px), ab der auch der Schrumpf-Effekt greift (siehe
       isMediaViewerStacked in app.js) - ein Bruch im Erscheinungsbild
       zwischen 640 und 899px wäre sonst die Folge. */
    width: 100%; max-width: 100%; height: 100dvh; max-height: none;
    border-radius: 0; box-shadow: none;
  }
  /* Kopfzeile schwebt transparent ÜBER dem Bild statt eine eigene weisse
     Zeile zu belegen - dadurch gewinnt die Bühne den Platz zurück, den die
     Kopfzeile vorher fest beanspruchte. Der Titel ("Foto") entfällt hier
     bewusst (selbsterklärend, sobald der Bildschirm nur noch aus dem Foto
     besteht) - pointer-events:none auf der Zeile, damit ein Fingertipp auf
     das Bild darunter (z. B. zum Wegwischen der Pfeile) nicht am
     unsichtbaren Kopfzeilen-Streifen hängen bleibt; nur das Kreuz selbst
     bleibt antippbar. */
  .media-viewer-card .sheet-head {
    position: absolute; top: 0; left: 0; right: 0; z-index: 5;
    background: linear-gradient(to bottom, rgba(0,0,0,.5), rgba(0,0,0,0));
    border: none; border-radius: 0; box-shadow: none;
    padding: calc(12px + env(safe-area-inset-top, 0px)) 12px 36px;
    pointer-events: none;
  }
  .media-viewer-card .sheet-title { display: none; }
  .media-viewer-card .close-btn {
    pointer-events: auto;
    background: rgba(30, 28, 24, .45); border-color: rgba(255,255,255,.4); color: #fff;
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  }
  .media-viewer-card .close-btn:hover { background: rgba(30, 28, 24, .6); }
  /* ---------- Runde 55: EIN Scroll-Container statt zwei ----------
     Vorher scrollte .media-viewer-side unabhängig für sich, während das
     Skript GLEICHZEITIG die Bühnenhöhe anhand von dessen scrollTop
     berechnete - zwei Systeme, die sich gegenseitig ausbremsten: wuchs die
     Bühne kleiner, wuchs .media-viewer-side (flex:1) automatisch, wodurch
     der Browser die schon gescrollte Position von .media-viewer-side
     eigenmächtig zurechtstutzte (max. scrollTop = scrollHeight-clientHeight
     sinkt, sobald der Container selbst wächst) - das Bild liess sich dadurch
     nicht mehr zuverlässig zurückziehen, und das Blatt kam ungewollt zu
     früh. Jetzt ist .media-viewer-body der EINZIGE Scroll-Container: die
     Bühne ist darin "position: sticky" (bleibt oben stehen, schrumpft aber
     wirklich), das Blatt folgt einfach im normalen Textfluss direkt danach -
     kein zweites, gegenläufiges Scroll-System mehr. */
  .media-viewer-body {
    display: block; min-height: 0; flex: 1 1 auto;
    overflow-y: auto; overflow-x: hidden;
    overscroll-behavior-y: contain; -webkit-overflow-scrolling: touch;
    /* Derselbe Fall wie bei .sheet-body (Bearbeiten-Fenster, siehe dortiger
       Kommentar): die Bühne schrumpft WÄHREND man scrollt, wodurch sich die
       Höhe des Inhalts über der aktuellen Scroll-Position laufend ändert.
       Ohne dies versuchte der Browser von sich aus (Scroll-Anchoring), die
       Scroll-Position an diese sich ändernde Höhe "festzuhalten" - und
       sprang dabei selbst auf 0 zurück, sobald die Bühne stärker schrumpfte
       als die bisherige Scroll-Position hoch war. Das war die eigentliche
       Ursache dafür, dass sich das Bild beim Hochziehen unvorhersehbar
       verhielt (mal zu früh zurückschnappend, siehe Rückmeldung Runde 55) -
       overflow-anchor:none schaltet dieses automatische Nachjustieren ab
       und überlässt die Scroll-Position vollständig unserer eigenen Logik. */
    overflow-anchor: none;
  }
  .media-viewer-stage {
    background: #000; padding-top: env(safe-area-inset-top, 0px);
    position: sticky; top: 0; z-index: 1;
    /* Die Höhe der Bühne wird ab hier vom Skript gesetzt (siehe
       resetMediaStageShrink/applyMediaStageShrink in app.js) - dieser Wert
       gilt nur als kurzer Rückfall, bis das Skript beim Öffnen des Fotos
       greift. */
    height: 94vh; height: 94dvh;
    /* Runde 56: erlaubt dem Browser NUR senkrechtes Wischen als eigene,
       native Geste (das Hochziehen der Angaben bleibt dadurch butterweich) -
       waagrechtes Wischen und Zwei-Finger-Zoom übernehmen wir stattdessen
       selbst per JS (siehe Touch-Ereignisse in app.js). Ohne dies hätte der
       Browser bei einem Zwei-Finger-Zoom die GANZE (fixierte) Karte inkl.
       Kopfzeile und Angaben-Blatt mitvergrössert, statt nur das Foto -
       genau das war die Rückmeldung "es soll nur das Bild gezoomt werden". */
    touch-action: pan-y;
    /* Hinweis an den Browser, Höhenänderungen effizienter vorzubereiten -
       zusammen mit dem rAF-Sammel-Schritt in app.js (Runde 56) gegen das
       gemeldete leichte Zittern beim Hoch-/Runterziehen. */
    will-change: height;
  }
  .media-viewer-side { will-change: transform; }
  /* Füllt IMMER genau die (vom Skript gesetzte) Höhe der Bühne aus - anstatt
     wie zuvor unabhängig davon per fester vh-Angabe zu skalieren. Vorher
     wurde die Bühne per echter Höhe UND das Bild zusätzlich per
     CSS-Transform (scale) verkleinert - bei einem grossen Foto, das die
     Bühne tatsächlich ausfüllt (anders als ein kleines Testbild), liefen
     beide Werte auseinander: das Bild "verschwand" sichtbar nach oben,
     darunter blieb ein schwarzer Leerraum stehen, bis das Blatt kam (genau
     das gemeldete Bild). Eine einzige, echte Höhenquelle vermeidet dieses
     Auseinanderlaufen von Grund auf. */
  .media-viewer-stage img { max-height: 100%; touch-action: pan-y; }
  .media-viewer-nav { border: 1px solid rgba(255,255,255,.4); }
  /* Das abgerundete "Blatt" mit den Angaben: im Ruhezustand ist davon nur
     der Griff-Balken sichtbar (die Bühne nimmt praktisch den ganzen
     Bildschirm ein, siehe MEDIA_STAGE_PEEK in app.js) - erst beim
     Hochziehen/Scrollen wächst der sichtbare Teil des Blattes, weil die
     (sticky) Bühne über ihm schrumpft. Kein negativer Rand mehr nötig (der
     frühere "Peek" per Überlappung zeigte ungewollt schon einen ganzen
     Absatz der Angaben an, siehe Rückmeldung "nicht so schön"). min-height
     statt flex:1 (Runde 55, siehe Kommentar bei .media-viewer-body): sorgt
     dafür, dass auch ein Foto mit sehr wenig Angaben genug Fläche mitbringt,
     um bis zum unteren Kartenrand zu reichen (kein schwarzer Balken) UND
     damit sich der Schrumpfweg der Bühne immer gleich anfühlt, unabhängig
     von der tatsächlichen Länge der Angaben. */
  .media-viewer-side {
    background: #fff; border-radius: 20px 20px 0 0;
    position: relative; z-index: 2;
    box-shadow: 0 -10px 26px rgba(0,0,0,.22);
    /* Runde 58: deutlich mehr Platz unter dem "Foto löschen"-Knopf als nur
       env(safe-area-inset-bottom) allein liefert. Grund: iPhones mit der
       schwebenden, kompakten Safari-Adressleiste am unteren Rand (statt
       einer klassischen Werkzeugleiste) ändern dafür weder 100dvh noch
       env(safe-area-inset-bottom) - die Leiste liegt einfach lose ÜBER der
       Seite. Ohne diesen zusätzlichen Puffer liess sich der Knopf ganz
       unten dadurch nicht mehr über den Rand der Leiste hinaus nach oben
       wegscrollen (siehe Rückmeldung "Löschen ist noch hinter der URL").
       Der zusätzliche Leerraum kostet nur etwas mehr Wischweg, verhindert
       aber zuverlässig, dass irgendein Bedienelement dauerhaft dahinter
       verschwindet. */
    padding: 0 18px calc(72px + env(safe-area-inset-bottom, 0px));
    overflow-y: visible; overflow-x: visible;
    overscroll-behavior: auto; -webkit-overflow-scrolling: auto;
    min-height: 60vh; min-height: 60dvh;
  }
  /* Griff-Balken: eigenes, antippbares Element (siehe #mediaViewerHandle in
     app.html) statt eines reinen CSS-Symbols - kein sticky mehr nötig
     (Runde 55): er steht im normalen Textfluss direkt nach der Bühne und
     rutscht dadurch von ganz allein an deren Unterkante, während diese
     schrumpft. Ein Fingertipp klappt die Angaben auch ohne Wischen ein-/
     aus (siehe Klick-Handler in app.js). Grössere unsichtbare Tippfläche als
     der sichtbare Balken selbst (Apple/Google-Richtwert ~44px), damit ein
     kurzer, dünner Balken trotzdem leicht zu treffen ist. */
  .media-viewer-handle {
    display: flex; align-items: center; justify-content: center;
    width: 100%; height: 32px; margin: 0 0 4px;
    border: none; background: none; padding: 0; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .media-viewer-handle-bar {
    display: block; width: 38px; height: 4px; border-radius: 999px;
    background: #ddd3ba; transition: background .15s;
  }
  .media-viewer-handle:hover .media-viewer-handle-bar,
  .media-viewer-handle:active .media-viewer-handle-bar { background: #c9bb9c; }
  /* Die beiden Abschnitte ("Wer ist auf dem Bild?" / "Angaben zum Bild")
     als eigene, leicht abgesetzte Karten statt einer durchgehenden Liste -
     näher an der gruppierten "Details"-Karte der Foto-App. */
  .media-viewer-side .rel-group {
    background: #faf7ef; border: 1px solid var(--card-border-soft);
    border-radius: 14px; padding: 14px 14px 16px;
  }
  .media-viewer-side .rel-group + .rel-group { margin-top: 12px; }
}

/* Formularfelder ausserhalb von #editPagePerson brauchen eigene Regeln -
   das dortige Raster-Layout gilt bewusst nur für das Personen-Formular. */
.media-viewer-side .field-row,
.mem-note-form .field-row { display: block; margin-bottom: 14px; }
.media-viewer-side .field-label,
.mem-note-form .field-label {
  display: block; margin-bottom: 5px !important;
  font-size: 12px; font-weight: 700; letter-spacing: .4px;
  text-transform: uppercase; color: var(--muted);
}
.media-viewer-side .field-input,
.mem-note-form .field-input,
.media-filter-select {
  width: 100%; min-height: 44px; padding: 10px 12px;
  border: 1px solid var(--card-border); border-radius: 10px; background: #fff;
  font-family: inherit; font-size: 15px; font-weight: 600; color: var(--ink);
  outline: none; transition: border-color .15s, box-shadow .15s;
}
/* Runde 58: ein natives input[type=date] (hier "Genaues Datum" neben
   "Jahr") behält auf dem iPhone seine eigene, inhaltsbedingte Mindestbreite
   bei, auch wenn width:100% eigentlich ein Einpassen in die schmälere
   Spalte der Zwei-Felder-Reihe vorsieht - dieselbe Lösung wie bereits bei
   .date-native weiter oben in dieser Datei: min-width:0 erlaubt dem
   Eingabefeld tatsächlich, sich auf die zugewiesene Breite zu verkleinern.
   Ohne dies ragte das Feld sichtbar über den rechten Kartenrand hinaus, da
   .media-viewer-side im schmalen Fenster bewusst overflow-x:visible nutzt
   (siehe dortiger Kommentar - overflow-x:hidden würde dort das für Runde 55
   nötige overflow-y:visible ungewollt mit aushebeln).
   Runde 59: min-width:0 allein reichte auf echten iPhones nicht - anders
   als in unseren (Chromium-basierten) Tests erzwingt WebKits natives
   Datums-Steuerelement offenbar eine eigene kleine Mindest-Renderbreite,
   die es unabhängig von jeder CSS-Breitenvorgabe trotzdem malt (ein reines
   Darstellungs-Verhalten der Plattform, das sich über CSS-Grössen nicht
   wegverhandeln lässt). Da .media-viewer-side selbst overflow-x:visible
   braucht (siehe oben), schneidet stattdessen overflow:hidden NUR auf der
   einzelnen Feld-Zeile diesen Rest zuverlässig ab - eine lokale Klammer,
   die den Rest der Architektur unberührt lässt. */
.media-viewer-side input[type="date"].field-input { min-width: 0; }
.media-field-pair .field-row { overflow: hidden; border-radius: 10px; }
.media-viewer-side .field-input:focus,
.mem-note-form .field-input:focus,
.media-filter-select:focus {
  border-color: var(--focus); box-shadow: 0 0 0 3px rgba(142, 36, 77, .12);
}
/* Reines Anschauen (nicht bearbeitbar): kein grauer, nach Formular
   aussehender Kasten mehr - reiner Anzeigetext, wie beim Lesemodus des
   Profils selbst (siehe #editPanel.read-only in style.css). Ein leeres
   Feld wird dabei ohnehin ganz ausgeblendet (siehe openMediaViewer), hier
   geht es nur um Felder, die tatsächlich einen Wert zeigen. */
.media-viewer-side .field-input:disabled,
.mem-note-form .field-input:disabled {
  background: none; border-color: transparent; color: var(--ink);
  cursor: default; padding-left: 0; padding-right: 0; resize: none;
}

/* ---------- Erinnerungen (Tab im Bearbeiten-Fenster) ---------- */
.mem-add-link { float: right; text-transform: none; letter-spacing: 0; font-size: 13px; }
.mem-photo-grid {
  display: grid; gap: 8px; grid-template-columns: repeat(auto-fill, minmax(92px, 1fr));
  margin-bottom: 8px;
}
.mem-note-form { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.mem-note-input { resize: vertical; min-height: 72px; font-family: inherit; line-height: 1.5; }
.mem-note-form-row { display: flex; gap: 8px; align-items: center; }
.mem-note-date { flex: 1; min-width: 0; }
.mem-note-list { display: flex; flex-direction: column; gap: 8px; }
.mem-note {
  position: relative; background: #faf7ef; border: 1px solid var(--card-border);
  border-radius: 12px; padding: 12px 38px 10px 14px;
}
.mem-note-body { font-size: 14.5px; line-height: 1.55; color: var(--ink); white-space: pre-wrap; }
.mem-note-meta { margin-top: 6px; font-size: 12px; color: var(--muted); font-weight: 700; }
.mem-note-del {
  position: absolute; top: 8px; right: 8px; border: none; background: none;
  color: var(--muted); cursor: pointer; font-size: 19px; line-height: 1;
  width: 26px; height: 26px; border-radius: 50%; font-family: inherit;
}
.mem-note-del:hover { background: #f6e5e4; color: var(--red); }

@media (max-width: 560px) {
  .media-grid { grid-template-columns: repeat(auto-fill, minmax(108px, 1fr)); }
  .media-count { margin-left: 0; width: 100%; }
  .media-field-pair { flex-direction: column; gap: 0; }
  .media-empty-state { padding-top: 8vh; }
}

/* ---------- Kalender ---------- */
.cal-wrap { max-width: 640px; margin: 0 auto; padding: 28px 20px 40px; }
.cal-header { margin-bottom: 20px; }
/* Die Kalender-Reiter nutzen jetzt den Stil der Übersicht (.dash-tabs).
   .cal-tabs/.cal-tab bleiben für die Filter-Kapseln der Aktivitäten. Kein
   margin-top mehr, seit die Titelzeile "Kalender" darüber entfernt wurde -
   die Reiter sitzen jetzt direkt oben, wie in der Übersicht. */
.cal-header .dash-tabs { margin-bottom: 0; }
.cal-tabs { display: flex; gap: 8px; margin-top: 14px; flex-wrap: wrap; }
.cal-tab {
  background: #fff; border: 1px solid var(--card-border); border-radius: 999px;
  padding: 10px 18px; min-height: 42px; font-family: inherit; font-weight: 700;
  font-size: 14px; color: var(--muted); cursor: pointer;
}
.cal-tab.active { background: var(--focus); border-color: var(--focus); color: #fff; }
/* ---------- Werkzeugzeile des Zeitstrahls ----------
   Links Filter-Chips, rechts die Sortierung - beides im selben Chip-Stil
   wie die übrigen Filter der App (vgl. .map-chip). Die frühere Zeile aus
   nacktem Text plus rundem Pfeil-Knopf fiel dagegen aus dem Bild. */
.cal-tools {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 14px 0 2px;
}
.cal-filter-chips { display: flex; gap: 8px; flex-wrap: wrap; flex: 1; min-width: 0; }
.cal-chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: inherit; font-size: 12.5px; font-weight: 700;
  padding: 8px 13px; min-height: 38px; border-radius: 999px;
  border: 1px solid var(--card-border); background: #fffdf6; color: var(--muted);
  cursor: pointer; transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.cal-chip:hover { background: #f6efd9; }
.cal-chip-dot {
  width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
  background: #d7cdba; transition: background .15s ease;
}
/* Eingeschaltet = kräftig, ausgeschaltet = blass. Die Farbe je Art ist
   dieselbe wie in der Statistik, damit "grün = lebt / rot = Tod" nicht
   von Ansicht zu Ansicht wechselt. */
.cal-chip.is-on { background: #f3ede0; border-color: var(--gold); color: var(--ink); }
.cal-chip[data-tl="born"].is-on .cal-chip-dot { background: #1fae63; }
.cal-chip[data-tl="died"].is-on .cal-chip-dot { background: #8d7468; }
.cal-chip[data-tl="union"].is-on .cal-chip-dot { background: var(--focus); }
.cal-chip:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

.cal-sort-btn {
  display: inline-flex; align-items: center; gap: 7px; flex-shrink: 0;
  font-family: inherit; font-size: 12.5px; font-weight: 700;
  padding: 8px 13px; min-height: 38px; border-radius: 999px;
  background: #fbf6e6; border: 1px solid var(--gold); color: var(--gold-dark);
  cursor: pointer;
}
.cal-sort-btn:hover { background: #f7eed6; }
.cal-sort-btn:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.cal-sort-btn svg { transition: transform .2s ease; }
.cal-sort-btn.desc svg { transform: rotate(180deg); }
#calSortLabel { white-space: nowrap; }

@media (max-width: 460px) {
  .cal-tools { gap: 8px; }
  .cal-sort-btn { width: 100%; justify-content: center; }
}
.cal-month-title {
  font-size: 15px; font-weight: 800; color: var(--muted);
  margin: 22px 0 8px; text-transform: uppercase; letter-spacing: .4px;
}
.cal-month-title:first-child { margin-top: 0; }
.cal-row {
  display: flex; align-items: center; gap: 12px; min-width: 0;
  background: #fff; border: 1px solid var(--card-border-soft); border-radius: 12px;
  padding: 13px 14px; min-height: 52px; margin-bottom: 8px; cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform .14s ease, box-shadow .14s ease, background .14s ease;
}
.cal-row:hover { background: #fffdf7; transform: translateY(-1px); box-shadow: var(--shadow-md); }
.cal-day { font-weight: 800; color: var(--focus); width: 30px; flex-shrink: 0; }
.cal-day-wide { width: 92px; }
.cal-name { font-weight: 700; flex: 1; min-width: 0; overflow-wrap: anywhere; }
.cal-age { color: var(--muted); font-size: 13.5px; font-weight: 600; }
.cal-empty { color: var(--muted); padding: 20px 4px; }

.modal-card h2 { margin-bottom: 18px; font-size: 22px; }
.modal-card h3 { font-size: 15px; margin-bottom: 10px; }
.modal-card .close-btn { position: absolute; top: 14px; right: 14px; left: auto; }
/* In einer Sheet-Kopfzeile gehört das Kreuz in den normalen Fluss - sonst
   wächst die Kopfzeile nicht mit und die Trennlinie läuft mitten durch den
   Knopf hindurch (genau das war im Screenshot zu sehen). */
.sheet-head .close-btn, .sheet-head .sheet-back { position: static; top: auto; right: auto; }
.modal-card label {
  display: block; font-weight: 700; font-size: 14px; margin-bottom: 12px;
}
.modal-card label input {
  display: block; width: 100%; min-width: 0; margin-top: 6px;
  padding: 12px; border: 1px solid #e0d3ba; border-radius: 10px;
  font-family: inherit; font-size: 16px;
}
.modal-card label input:focus { outline: none; border-color: var(--focus); }

/* Die generische Regel ".modal-card label" (Element+Klasse) ist spezifischer
   als eine einzelne Klasse und würde sonst die neuen Bedienelemente
   überschreiben - deshalb hier gezielt wieder geradegerückt. */
.modal-card label.toggle-row, .modal-card label.field-label,
.modal-card label.seg, .modal-card label.switch { margin-bottom: 0; }
.modal-card .toggle-row { display: flex; font-size: 15px; font-weight: 600; }
.modal-card .field-label { display: block; font-size: 14px; font-weight: 600; }
.modal-card .field-row-switch .field-label { font-weight: 700; }
.modal-card .switch { display: inline-block; }
.modal-card .segmented .seg { display: block; font-size: inherit; font-weight: inherit; }
.name-row { display: flex; gap: 10px; }
.name-row label { flex: 1; }
.full-width { width: 100%; margin-top: 4px; }
.auth-error {
  background: #fdecec; color: #b42318; border-radius: 8px;
  padding: 8px 10px; font-size: 13.5px; font-weight: 600; margin-bottom: 12px;
}
.auth-switch { margin-top: 16px; font-size: 14px; text-align: center; }

/* Hinweis unter Passwort-Feldern (Mindestanforderungen) */
.password-hint {
  display: block; font-size: 12.5px; color: var(--muted);
  margin: -6px 0 10px;
}

/* "Mit Google fortfahren" - Trennlinie + Knopf im Anmeldefenster */
.auth-divider {
  display: flex; align-items: center; gap: 10px;
  margin: 16px 0; font-size: 12.5px; color: var(--muted, #8a8a99);
  text-transform: uppercase; letter-spacing: .03em;
}
.auth-divider::before, .auth-divider::after {
  content: ''; flex: 1; height: 1px; background: #e3e3ee;
}
.btn-google {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  background: #fff; color: #3c4043; border: 1px solid #dadce0;
  border-radius: 999px; padding: 10px 20px; min-height: 46px;
  font-family: inherit; font-weight: 700; font-size: 15px;
  cursor: pointer; transition: filter .15s, transform .1s, box-shadow .15s;
}
.btn-google:hover { box-shadow: 0 1px 4px rgba(60,64,67,.2); }
.btn-google:active { transform: scale(.98); }
.btn-google:disabled { opacity: .6; cursor: default; }

/* Teilen: Link-Zeile und Einladungs-Formular brechen auf schmalen Displays
   um, statt seitlich aus dem Fenster herauszulaufen. */
.ts-link-wrap { display: flex; gap: 8px; margin: 10px 0 6px; flex-wrap: wrap; }
.ts-link-wrap input {
  flex: 1 1 180px; min-width: 0; padding: 11px 12px; border: 1px solid #e0d3ba;
  border-radius: 10px; font-family: inherit; font-size: 14px; background: #faf7ef;
}
.ts-link-wrap .btn { min-height: 44px; flex-shrink: 0; }
.ts-divider { border: none; border-top: 1px solid #f0e6c8; margin: 18px 0; }
.ts-invite-form { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.ts-invite-form input {
  width: 100%; min-width: 0; padding: 11px 12px; border: 1px solid #e0d3ba;
  border-radius: 10px; font-family: inherit; font-size: 16px;
}
.ts-invite-row { display: flex; gap: 8px; min-width: 0; }
.ts-invite-form select {
  flex: 1; min-width: 0; padding: 11px 10px; border: 1px solid #e0d3ba;
  border-radius: 10px; font-family: inherit; font-size: 15px; background: #fff;
}
.ts-invite-form .btn { flex-shrink: 0; min-height: 46px; }
.ts-share-list { display: flex; flex-direction: column; gap: 8px; }
.ts-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 10px 12px; background: #fbf3de; border-radius: 10px;
  font-size: 14px; min-width: 0; flex-wrap: wrap;
}
.ts-row > span:first-child { min-width: 0; overflow-wrap: anywhere; }
.ts-row .btn-link { min-height: 32px; }
.ts-perm { color: var(--muted); font-weight: 700; font-size: 12px; text-transform: uppercase; }

/* ---------- Freigabe-Filter ---------- */
/* Aufklapp-Knopf für die erweiterten Filter */
.ts-filter-btn {
  display: flex; align-items: center; gap: 10px; width: 100%;
  margin: 14px 0 4px; padding: 12px 14px; min-height: 48px;
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 12px;
  font-family: inherit; font-size: 15px; font-weight: 700; color: var(--ink);
  cursor: pointer; text-align: left;
}
.ts-filter-btn:hover { background: #f6efd9; }
.ts-filter-btn svg { flex-shrink: 0; color: var(--focus); }
.ts-filter-chevron {
  margin-left: auto; font-size: 20px; font-style: normal; color: var(--muted);
  transition: transform .18s ease;
}
.ts-filter-btn.is-open { background: #f6efd9; border-color: var(--pink); }
.ts-filter-btn.is-open .ts-filter-chevron { transform: rotate(90deg); }

.ts-filter-panel {
  border-left: 2px solid var(--pink); padding-left: 12px; margin: 4px 0 8px;
}
.ts-filter-panel .settings-subhead:first-child { margin-top: 6px; }

.ts-field { margin: 10px 0 4px; }
.ts-field-label {
  display: block; font-size: 11.5px; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 6px;
}
.ts-field .account-hint { margin: 8px 0 4px; }
.ts-field select {
  width: 100%; min-width: 0; padding: 11px 12px; min-height: 46px;
  border: 1px solid #e0d3ba; border-radius: 10px; background: #fff;
  font-family: inherit; font-size: 15px; color: var(--ink);
}

/* ---------- Überschrift "Registrierte Nutzer" + Schalter "Verbergen" ---------- */
.members-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap; margin-top: 4px;
}
.members-head h3 { margin: 0; }
.modal-card .members-hide-toggle {
  display: inline-flex; align-items: center; gap: 8px; min-width: 0;
  margin: 0; font-size: 13.5px; font-weight: 600; color: var(--muted); cursor: pointer;
}

/* ---------- Öffentliche Kopfzeile: klickbar zum Beitreten ---------- */
.public-banner {
  font-family: inherit; cursor: pointer; text-align: left;
  flex-direction: column; align-items: flex-start; gap: 4px;
  max-width: min(520px, calc(100vw - 32px));
}
.public-banner:hover { background: #fff0d8; }
.public-banner:disabled { cursor: default; }
.public-banner-cta { font-weight: 800; color: var(--focus); }

/* ---------- Familie beitreten ---------- */
.join-step { display: flex; flex-direction: column; gap: 4px; }
.join-lead { font-size: 15px; line-height: 1.5; color: var(--ink); margin-bottom: 12px; }
.join-results { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.join-result {
  display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; min-height: 56px; padding: 10px 14px; text-align: left;
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 10px;
  font-family: inherit; cursor: pointer;
}
.join-result:hover { background: #fdf0ec; border-color: var(--pink); }
.join-result.is-claimed { opacity: .55; cursor: default; }
.join-result-name { font-weight: 800; font-size: 15px; color: var(--ink); }
.join-result-meta { font-size: 12.5px; color: var(--muted); }
.join-notfound { margin-top: 16px; align-self: flex-start; min-height: 44px; }
.join-person-card {
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 12px;
  padding: 16px; margin-bottom: 16px;
}
.join-person-name { font-size: 19px; font-weight: 800; color: var(--ink); }
.join-person-meta { font-size: 13.5px; color: var(--muted); margin-top: 4px; }
.join-actions { display: flex; flex-direction: column; gap: 10px; }
.join-actions .btn { width: 100%; }
.join-done-icon {
  width: 62px; height: 62px; border-radius: 50%; margin: 8px auto 18px;
  display: flex; align-items: center; justify-content: center;
  background: var(--focus-light); color: var(--focus);
}

/* ---------- Einladung verschicken ---------- */
.invite-actions {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 8px; margin: 12px 0 4px;
}
.invite-btn {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 10px 12px; border-radius: 12px;
  background: #faf7ef; border: 1px solid var(--card-border);
  font-family: inherit; font-size: 14.5px; font-weight: 700; color: var(--ink);
  cursor: pointer; min-width: 0;
}
.invite-btn:hover { background: #f6efd9; border-color: var(--pink); }
.invite-btn:active { transform: scale(.98); }
.invite-btn svg { flex-shrink: 0; color: var(--focus); }
.invite-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.qr-box {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  margin: 12px 0 4px; padding: 16px;
  background: #fffdf6; border: 1px solid var(--card-border); border-radius: 14px;
}
.qr-image { line-height: 0; }
.qr-image svg { width: min(240px, 60vw); height: auto; border-radius: 6px; }
.qr-box .account-hint { margin: 0; text-align: center; }

/* Einladungs-Fenster */
.join-invite-icon {
  width: 62px; height: 62px; border-radius: 50%; margin: 8px auto 18px;
  display: flex; align-items: center; justify-content: center;
  background: var(--focus-light); color: var(--focus);
}

/* ---------- Persönliche Einladungen ---------- */
.pinvite-form { display: flex; flex-direction: column; gap: 8px; margin: 10px 0 4px; }
.pinvite-chosen {
  display: flex; align-items: center; gap: 8px; min-height: 46px;
  padding: 6px 8px 6px 14px; border-radius: 10px;
  background: var(--focus-light); border: 1px solid var(--pink);
}
.pinvite-chosen-name { flex: 1; min-width: 0; font-weight: 800; font-size: 14.5px; color: var(--focus-dark);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pinvite-row { display: flex; gap: 8px; min-width: 0; }
.pinvite-row select {
  flex: 1; min-width: 0; padding: 11px 10px; min-height: 46px;
  border: 1px solid #e0d3ba; border-radius: 10px; background: #fff;
  font-family: inherit; font-size: 15px; font-weight: 700; color: var(--ink);
}
.pinvite-row .btn { flex-shrink: 0; }

.pinvite-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.pinvite-row-wrap { min-width: 0; }
.pinvite-list .pinvite-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  background: #fffdf6; border: 1px solid var(--card-border);
  border-radius: 12px; padding: 10px 12px;
}
.pinvite-info { flex: 1 1 130px; min-width: 0; }
.pinvite-name { font-weight: 800; font-size: 14.5px; color: var(--ink); overflow-wrap: anywhere; }
.pinvite-meta { font-size: 12px; color: var(--muted); margin-top: 2px; }
.pinvite-actions { display: flex; gap: 4px; flex-shrink: 0; }
.pinvite-btn {
  width: 38px; height: 38px; border-radius: 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: #faf7ef; border: 1px solid var(--card-border);
  color: var(--focus); cursor: pointer; padding: 0;
}
.pinvite-btn:hover { background: #f6efd9; }
.pinvite-btn.is-danger { color: var(--red); }
.pinvite-qr { flex-basis: 100%; display: flex; justify-content: center; padding-top: 8px; }
.pinvite-qr svg { width: min(200px, 60vw); height: auto; }

/* ---------- Registrierte Mitglieder ---------- */
.members-list { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.member-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; min-width: 0;
  background: #fffdf6; border: 1px solid var(--card-border);
  border-radius: 12px; padding: 12px;
}
.member-row.is-owner { background: var(--focus-light); border-color: var(--pink); }
.member-row.is-pending { background: #faf7ef; border-style: dashed; }
.member-info { min-width: 0; flex: 1 1 160px; }
.member-name { font-weight: 800; font-size: 14.5px; color: var(--ink); overflow-wrap: anywhere; }
.member-sub { font-size: 12.5px; color: var(--muted); margin-top: 2px; overflow-wrap: anywhere; }
.member-controls { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.member-role-select {
  padding: 9px 10px; min-height: 42px; border: 1px solid #e0d3ba; border-radius: 10px;
  background: #fff; font-family: inherit; font-size: 14px; font-weight: 700; color: var(--ink);
}
.member-role-static { font-size: 12.5px; font-weight: 800; color: var(--focus-dark); text-transform: uppercase; }
.member-remove { min-height: 42px; }

/* Vorschau: wie viele Personen der Besucher am Ende sieht */
.ts-preview {
  margin-top: 10px; padding: 10px 12px; border-radius: 10px;
  background: #f6f3ec; color: var(--muted);
  font-size: 13px; font-weight: 700;
}
.ts-preview.is-reduced { background: #fbf3de; color: var(--gold-dark); }

/* Gesperrte Ansicht in der unteren Leiste: sichtbar, aber erkennbar aus */
.bottom-nav .nav-item { position: relative; }
.nav-item.locked { opacity: .42; }
.nav-item.locked::after {
  /* Sitzt an der oberen rechten Ecke des Symbols - die Leiste hat keine
     Beschriftungen mehr, deshalb relativ zur Mitte gerechnet. */
  content: ""; position: absolute; top: calc(50% - 15px); left: 50%; margin-left: 8px;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--muted); box-shadow: 0 0 0 2px #fff;
}
.ts-empty { color: var(--muted); font-size: 14px; }

/* ---------- Read-only Edit-Panel ---------- */
/* Kein grauer Kasten mehr hinter den Feldern im Lesemodus - wirkt sonst wie
   ein (nicht bedienbares) Eingabefeld statt reinem Anzeigetext. */
#editPanel.read-only .edit-modal-body input { background: none; color: var(--ink); }
/* Safari/iOS stellt ein deaktiviertes <input disabled> unabhängig von
   "color" IMMER zusätzlich gedämpft/ausgegraut dar (eigene, systemweite
   Feldfarbe über -webkit-text-fill-color) - das erklärt, warum Vorname/
   Nachname/Geburtsname/Rufname (echte, nur deaktivierte Eingabefelder) im
   Lesemodus heller wirkten als Geschlecht/Geburtsdatum (die dort als
   reiner Text ohne <input> gerendert werden, siehe .field-value-text -
   deshalb nie von diesem Effekt betroffen). -webkit-text-fill-color
   erzwingt dieselbe Farbe wie überall sonst, opacity:1 hebt die von
   manchen Browsern zusätzlich angewandte Deckkraft-Reduktion auf. */
#editPanel.read-only .edit-modal-body input:disabled,
.media-viewer-side .field-input:disabled,
.mem-note-form .field-input:disabled,
.acc-tree-name:disabled {
  -webkit-text-fill-color: var(--ink); opacity: 1;
}

/* ---------- Editorrechte: einzelne, schon befüllte Felder gesperrt ---------- */
.edit-modal-body input.field-locked,
.edit-modal-body .date-mode-btn.field-locked {
  background: #f7f7f8; color: #888; cursor: not-allowed;
  background-image: linear-gradient(135deg, transparent 0%, transparent 92%, #e3d8b8 92%, #e3d8b8 100%);
}

/* ---------- Geschlechts-Farben (Eltern/Vorfahren sofort erkennbar) ---------- */
/* Verlauf statt einer flachen Farbe: oben etwas heller, unten etwas
   tiefer. Zusammen mit dem Schatten (siehe .card-rect oben) bekommt die
   Karte dadurch Koerper, statt wie ein aufgeklebtes Rechteck zu wirken. */
.person-card.gender-male .card-rect { fill: url(#cardGradMale); stroke: #c3d4e6; }
.person-card.gender-female .card-rect { fill: url(#cardGradFemale); stroke: #f0c2d5; }
.person-card.gender-other .card-rect { fill: url(#cardGradOther); stroke: #ddccaa; }
.person-card.editing .card-rect { fill: url(#cardGradFocusPerson); stroke: var(--focus-dark); }

/* ---------- Generationstiefe (Tools-Menü) ---------- */
.tools-divider { border-top: 1px solid #f0e6c8; margin: 8px 0; }
.gen-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 6px 4px; font-size: 15px; font-weight: 600;
  min-width: 0; flex-wrap: wrap;
}
.gen-row select {
  font-family: inherit; font-weight: 700; font-size: 15px;
  padding: 10px 12px; min-height: 44px; border-radius: 10px;
  border: 1px solid #e0d3ba; background: #fff;
}

/* ---------- Delete-Bereich im Edit-Panel ---------- */
.danger-zone {
  padding: 14px 18px 20px; text-align: center;
}
.btn-link.danger {
  color: #c0392b; text-decoration: none; font-size: 15px;
  display: inline-flex; align-items: center; min-height: 44px;
}
.btn-link.danger:hover { text-decoration: underline; }
.delete-confirm {
  margin-top: 10px; background: #fdecec; border-radius: 10px;
  padding: 12px 14px; font-size: 13.5px; color: #7a1a1a;
}
.delete-confirm-warning { margin: 0 0 12px; font-weight: 700; line-height: 1.5; }
/* Konto löschen: die E-Mail-Bestätigung sitzt in derselben roten Warn-
   Box wie der Text - eigene, kleinere Beschriftung statt der grossen
   ".modal-card label"-Regel, damit sie sich unterordnet. */
.delete-confirm-email-label {
  display: block; font-size: 12.5px; font-weight: 700; color: #7a1a1a;
  margin-bottom: 4px; text-align: left;
}
.delete-confirm-email-label input {
  display: block; width: 100%; min-width: 0; margin-top: 6px;
  padding: 11px 12px; border: 1px solid #eab4ab; border-radius: 10px;
  font-family: inherit; font-size: 15px; background: #fff; color: var(--ink);
}
.delete-confirm-email-label input:focus { outline: none; border-color: #c0392b; }
.delete-confirm-btns { display: flex; gap: 10px; justify-content: center; margin-top: 12px; flex-wrap: wrap; }
.btn.red-solid {
  background: #c0392b; color: #fff; border: none; border-radius: 999px;
  padding: 12px 22px; min-height: 46px; font-weight: 700; cursor: pointer;
  font-family: inherit;
}
/* Gesperrt, bis die eigene E-Mail-Adresse exakt eingetippt wurde. */
.btn.red-solid:disabled { background: #e3b3ac; cursor: not-allowed; }

/* ---------- Fokusperson: dezenter pulsierender Rahmen (kein Punkt mehr -
   der saß bei zweizeiligen Namen unschön weit unten) - die Karte bleibt in
   ihrer Geschlechtsfarbe, damit sie sich nicht mehr von den übrigen
   abhebt. ---------- */
.person-card.focus .card-rect { stroke: var(--gold); stroke-width: 2; animation: focusPulse 3.2s ease-in-out infinite; }
@keyframes focusPulse {
  0%, 100% { stroke-opacity: 1; }
  50% { stroke-opacity: .45; }
}
@media (prefers-reduced-motion: reduce) {
  .person-card.focus .card-rect { animation: none; }
}

/* ---------- Angeklickte Karte: nur ein dezenter, statischer Rahmen (keine
   Animation - die ist der Fokusperson vorbehalten, sonst wäre nicht mehr
   eindeutig, welche Hervorhebung was bedeutet). ---------- */
.person-card.selected:not(.focus) .card-rect { stroke: var(--focus); stroke-width: 2px; }

/* ---------- Sanftes Einblenden statt abruptem "Aufpoppen" ----------
   Karten gleiten in .55s zur neuen Position (siehe drawCard). Die Linien
   blenden über dieselbe Dauer/Kurve ein, leicht verzögert - so wirken
   Karten und Linien wie EINE gemeinsame Bewegung statt nacheinander. */
.card-inner {
  transform-box: fill-box;
  transform-origin: center;
}
.card-inner.card-grow {
  animation: cardIn 0.55s cubic-bezier(0.4, 0, 0.2, 1) both;
}
@keyframes cardIn {
  from { opacity: 0; transform: scale(0.25); }
  60%  { opacity: 1; }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .card-inner, .card-grow, .person-card { animation: none !important; transition: none !important; }
}

/* ---------- Verstorben: entsättigt + dunklerer Rahmen statt Transparenz -
   Transparenz auf .card-inner hätte auch das undeckende Kartenrechteck
   erfasst, wodurch die Verbindungslinien im Hintergrund durchscheinen
   (sie liegen im SVG hinter den Karten). Nur saturate() dämpft die Farben,
   ohne die Karte selbst durchsichtig zu machen. ---------- */
.person-card.deceased .card-inner { filter: saturate(0.55); }
.person-card.deceased .card-rect { stroke: var(--muted); stroke-width: 1.5; }
/* Der frühere gedämpfte Look (Name, Avatar, Jahreszahl etc.) kommt über
   opacity zurück - aber gezielt nur auf die Kind-Elemente AUSSER dem
   Kartenrechteck, damit das Rechteck weiterhin blickdicht bleibt und die
   Linien im Hintergrund nicht mehr durchscheinen (siehe oben). */
.person-card.deceased .card-inner > *:not(.card-rect):not(.hover-btn):not(.card-relation) { opacity: 0.88; }
.card-years {
  font-family: 'Nunito', sans-serif; font-size: 11.5px; font-weight: 700;
  fill: var(--muted); text-anchor: middle;
}
.person-card.editing .card-years { fill: rgba(255,255,255,.85); }
.card-relation {
  font-family: 'Nunito', sans-serif; font-size: 11px; font-weight: 700;
  fill: var(--muted); text-anchor: middle;
  opacity: 0; transition: opacity .12s; pointer-events: none;
}
.person-card.selected .card-relation { opacity: 1; }

/* Auf Touch gibt es kein Hover - die Buttons erscheinen stattdessen erst,
   wenn die Karte angetippt wurde (.selected), nicht mehr dauerhaft. */
@media (max-width: 640px) {
  .person-card.selected .hover-btn { opacity: 1; pointer-events: all; }
}
@media (hover: none) {
  .person-card.selected .hover-btn { opacity: 1; pointer-events: all; }
}

/* ---------- Konto-Panel: Inhalt (lebt jetzt in der Profil-Unter-Seite) ---------- */
/* Oben ausgerichtet, weil unter dem Namen jetzt zwei weitere Zeilen
   stehen (Tarif und geöffnetes Archiv) - mittig zentriert liesse das
   Bild sonst neben dem Namen nach unten rutschen. */
.account-head { display: flex; align-items: flex-start; gap: 12px; margin: 4px 0 18px; }
.account-avatar {
  width: 46px; height: 46px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--focus); color: #fff;
  /* overflow, damit die Silhouette im Kreis bleibt statt eckig zu stehen */
  overflow: hidden;
}
.account-email { font-weight: 800; font-size: 15px; word-break: break-all; }
.account-sub { font-size: 12.5px; color: var(--muted); }
/* Rolle im gerade geöffneten Archiv, unter der E-Mail-Adresse. */
.acc-role-line {
  display: flex; align-items: center; gap: 5px; margin-top: 4px;
  font-size: 12px; font-weight: 700; color: var(--focus-dark);
}
.acc-role-icon { display: inline-flex; flex-shrink: 0; }
.account-section { margin-bottom: 20px; }
.account-section h3 {
  font-size: 12.5px; text-transform: uppercase; letter-spacing: .5px;
  color: var(--muted); margin-bottom: 10px;
}
.account-section label {
  display: block; font-size: 13px; font-weight: 700; color: var(--ink); margin-bottom: 12px;
}
.account-hint { font-size: 12px; color: var(--muted); margin: -4px 0 8px; }
.account-inline-form { display: flex; gap: 8px; margin-top: 5px; flex-wrap: wrap; }
.account-inline-form input, .account-inline-form select {
  flex: 1 1 160px; min-width: 0; border: 1px solid #d8cdb0; border-radius: var(--radius-sm);
  padding: 11px 12px; font-family: inherit; font-size: 16px; background: #fff;
}
.account-inline-form .btn { padding: 10px 16px; font-size: 14px; min-height: 44px; flex-shrink: 0; }

.acc-trees-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.acc-trees-head h3 { margin-bottom: 0; }
.acc-trees-head #accAddTree { font-size: 12.5px; font-weight: 800; color: var(--focus); background: none; border: none; cursor: pointer; font-family: inherit; padding: 0; }

.acc-tree-list { display: flex; flex-direction: column; gap: 10px; }
.acc-tree-row {
  border: 1px solid var(--card-border); border-radius: var(--radius-sm);
  padding: 10px 12px; background: #fffdf6;
}
.acc-tree-row.shared-with-me { background: #f7f4ec; }
.acc-tree-top { display: flex; align-items: center; gap: 8px; }
.acc-tree-name {
  flex: 1; min-width: 0; border: none; background: none; font-weight: 800;
  font-size: 16px; color: var(--ink); font-family: inherit;
  padding: 8px 6px; border-radius: 8px;
}
.acc-tree-name:hover, .acc-tree-name:focus { background: #f0e9d4; outline: none; }
.acc-tree-name:disabled { color: var(--ink); cursor: default; }
.acc-tree-date { font-size: 11.5px; color: var(--muted); margin: 3px 0 6px 4px; }
/* Zustands-Abzeichen: antippbar, führt direkt zur passenden Stelle */
.acc-tree-badge {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: inherit; font-size: 12px; font-weight: 800;
  padding: 8px 12px; min-height: 36px; border-radius: 999px;
  margin: 2px 4px 8px; border: 1px solid transparent; cursor: pointer;
}
.acc-tree-badge svg { flex-shrink: 0; }
.acc-tree-badge.is-private { background: #f1ece0; color: #7c705c; }
.acc-tree-badge.is-public { background: #e4f1e8; color: #2e6b45; border-color: #bcdcc7; }
.acc-tree-badge.is-shared { background: var(--focus-light); color: var(--focus-dark); border-color: var(--pink); }
.acc-tree-badge:hover { filter: brightness(.97); }
.acc-tree-badge:active { transform: scale(.97); }

/* Roter Punkt an "Prüfen" */
.pm-badge {
  width: 9px; height: 9px; border-radius: 50%; background: var(--red);
  flex-shrink: 0; box-shadow: 0 0 0 2px #fff;
}

/* ---------- Mein Konto: Kopfbereich ----------
   Bild und Name sind bewusst grösser als früher: sie sind das Erste,
   was man hier sieht, und beantworten "wer bin ich gerade". */
.account-avatar-img {
  width: 100%; height: 100%; border-radius: 50%; object-fit: cover; display: block;
  background: #e8ddc7;
}
.account-avatar-click .account-avatar { width: 100%; height: 100%; }

/* Ein Klick aufs Bild führt ins Bearbeiten-Fenster der eigenen Person -
   dort wird auch das Foto gewechselt. Die früheren kleinen Symbole zum
   Ändern/Entfernen daneben sind entfallen; stattdessen legt sich beim
   Zeigen ein Hinweis über das Bild. */
.account-avatar-click {
  position: relative; display: block; padding: 0; border: none; background: none;
  cursor: pointer; border-radius: 50%; width: 74px; height: 74px;
  overflow: hidden; flex-shrink: 0;
}
.account-avatar-click:active { transform: scale(.97); }
.account-avatar-click:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.account-avatar-hover {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(40,26,20,.55); color: #fff;
  font-size: 12px; font-weight: 800; letter-spacing: .02em;
  opacity: 0; transition: opacity .15s ease;
}
.account-avatar-click:hover .account-avatar-hover,
.account-avatar-click:focus-visible .account-avatar-hover { opacity: 1; }
/* Auf Geräten ohne Mauszeiger gibt es kein "Zeigen" - dort wäre der
   Hinweis entweder nie oder dauerhaft zu sehen. Also gar nicht. */
@media (hover: none) {
  .account-avatar-hover { display: none; }
}

.account-head-text { min-width: 0; flex: 1; }
.acc-name-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.acc-name {
  font-weight: 800; font-size: 18.5px; color: var(--ink); line-height: 1.25;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* Verknüpfung mit dem Archiv, direkt neben dem Namen: grüner Haken, wenn
   man einer Person zugeordnet ist, sonst ein grauer Kreis gleicher Grösse
   mit Ketten-Symbol. Beides gleich gross, damit die Zeile beim Wechsel
   nicht springt. */
.acc-link-wrap { position: relative; flex-shrink: 0; }
.acc-link-dot {
  display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 50%; border: none; cursor: pointer; flex-shrink: 0;
  background: #e6e0d5; color: #8d7468;
  transition: background .15s ease, color .15s ease;
}
.acc-link-dot:hover { background: #dcd4c6; color: var(--ink); }
.acc-link-dot:active { transform: scale(.92); }
.acc-link-dot:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.acc-link-dot .acc-link-icon-on { display: none; }
.acc-link-dot.is-linked { background: #1f9d5c; color: #fff; }
.acc-link-dot.is-linked:hover { background: #1b874f; color: #fff; }
.acc-link-dot.is-linked .acc-link-icon-off { display: none; }
.acc-link-dot.is-linked .acc-link-icon-on { display: block; }

/* Nur wenn verknüpft: kleines Menü mit "Profil bearbeiten" und "Lösen". */
.acc-link-menu {
  position: absolute; top: calc(100% + 6px); left: 0; right: auto; z-index: 30;
  min-width: 210px; max-width: calc(100vw - 40px); padding: 5px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 12px;
  box-shadow: 0 10px 28px rgba(78,52,46,.16);
  display: flex; flex-direction: column;
}
.acc-link-menu button {
  text-align: left; font-family: inherit; font-size: 14px; font-weight: 600;
  color: var(--ink); background: none; border: none; cursor: pointer;
  padding: 11px 12px; border-radius: 8px; min-height: 44px;
}
.acc-link-menu button:hover { background: #f6efd9; }
.acc-link-menu button.is-danger { color: var(--red); }

/* ---------- Das geöffnete Familienarchiv ---------- */
.acc-archive-box {
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 14px;
  padding: 12px 14px 13px; margin-bottom: 20px;
}
.acc-archive-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 6px; }
.acc-plan-line {
  display: inline-block;
  font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  padding: 3px 10px; border-radius: 999px;
  background: #efe6d5; color: var(--muted);
}
.acc-plan-line.is-plus {
  background: linear-gradient(135deg, var(--gold), var(--gold-dark)); color: #fff;
  text-transform: none; letter-spacing: .01em; font-size: 11.5px;
}
/* Wer das Plus bezahlt, steht daneben - bewusst gedämpft, es ist eine
   Fussnote zum Abzeichen, keine zweite Überschrift. */
.acc-shared-by { font-size: 12.5px; color: var(--muted); min-width: 0; }

.acc-archive-pick-wrap { position: relative; }
.acc-archive-pick {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: none; border: none; cursor: pointer; font-family: inherit;
  padding: 4px 0; text-align: left; color: var(--ink); border-radius: 8px;
}
.acc-archive-pick:hover .acc-archive-name { color: var(--focus); }
.acc-archive-pick:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.acc-archive-name {
  flex: 1; min-width: 0; font-size: 16.5px; font-weight: 800; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.acc-archive-chev { flex-shrink: 0; color: var(--muted); }
.acc-archive-stats { margin-top: 2px; font-size: 12.5px; color: var(--muted); line-height: 1.45; }

/* Auswahlliste aller Archive */
.acc-archive-menu {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  max-height: 260px; overflow-y: auto; padding: 5px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 12px;
  box-shadow: 0 10px 28px rgba(78,52,46,.16);
}
.acc-archive-loading { padding: 12px; font-size: 13.5px; color: var(--muted); }
.acc-archive-option {
  display: flex; align-items: center; gap: 8px; width: 100%;
  text-align: left; font-family: inherit; font-size: 14.5px; font-weight: 700;
  color: var(--ink); background: none; border: none; cursor: pointer;
  padding: 11px 12px; border-radius: 8px; min-height: 44px;
}
.acc-archive-option:hover { background: #f6efd9; }
.acc-archive-option.is-current { background: #f3ede0; }
.acc-archive-option-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acc-archive-option-tag {
  flex-shrink: 0; font-size: 11px; font-weight: 800; color: var(--muted);
  background: #efe6d5; border-radius: 999px; padding: 2px 8px;
}
.acc-archive-option-check { flex-shrink: 0; color: #1f9d5c; font-weight: 800; }

/* Die zwei Unter-Seiten von "Mein Konto" */
/* Spalte, damit die Zeilen auf volle Breite gehen - sonst schrumpfen die
   Knöpfe auf ihre Textbreite und der Pfeil rechts klebt am Text. */
.acc-submenu {
  display: flex; flex-direction: column;
  margin: 0 0 20px; padding: 4px 0;
  border-top: 1px solid var(--card-border); border-bottom: 1px solid var(--card-border);
}

/* Hilfe & Support: dieselben Zeilen wie früher unter "Rechtliches",
   nur ohne die Emoji davor - die passten nicht zum übrigen Bild. Statt
   der Symbole trennen jetzt feine Linien, damit es als Liste lesbar
   bleibt und die Einträge nicht frei im Raum stehen. */
.help-section { margin-top: 4px; display: flex; flex-direction: column; }
.help-section .tools-item {
  border-bottom: 1px solid var(--card-border); border-radius: 0;
  margin: 0; padding: 14px 6px;
}
.help-section .tools-item:last-child { border-bottom: none; }
.acc-current-email {
  display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline;
  background: #faf7ef; border: 1px solid var(--card-border); border-radius: 10px;
  padding: 10px 12px; margin-bottom: 14px;
}
.acc-current-email-label {
  font-size: 11px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted);
}
.acc-current-email-value { font-size: 14.5px; font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.acc-tree-shared-list { font-size: 12px; color: var(--muted); margin: 0 4px 8px; line-height: 1.6; }
.acc-tree-focus { margin: 8px 4px 2px; }
.acc-tree-focus-label { font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; margin-bottom: 4px; display: block; }
.acc-tree-focus .account-inline-form { margin-top: 4px; }
.acc-tree-actions { display: flex; gap: 18px; margin: 4px 4px 0; flex-wrap: wrap; }
.acc-tree-actions button {
  background: none; border: none; font-family: inherit; font-weight: 700;
  font-size: 13.5px; cursor: pointer; padding: 8px 0; min-height: 40px;
  color: var(--focus);
}
.acc-tree-actions button.danger { color: #b3261e; }
.acc-tree-empty { font-size: 13px; color: var(--muted); }

/* ---------- Eingeklappte Familienarchiv-Zeile ---------- */
.acc-tree-row-collapsed {
  display: flex; align-items: center; gap: 10px; width: 100%;
  font-family: inherit; text-align: left; cursor: pointer;
}
/* Der Pfeil sitzt immer am rechten Rand: eingeklappt zeigt er nach unten
   ("hier geht etwas auf"), aufgeklappt nach oben ("hier geht es wieder zu"). */
.acc-tree-chevron {
  flex-shrink: 0; width: 30px; height: 30px; margin-left: auto;
  border-radius: 8px; border: none; background: none; color: var(--muted);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
}
.acc-tree-chevron svg { transition: transform .22s cubic-bezier(.22,.7,.3,1); }
.acc-tree-chevron-collapse svg { transform: rotate(180deg); }
.acc-tree-chevron:hover { background: #f0e9d4; color: var(--ink); }
/* Die Zeilen klappen mit einer Höhen-Animation auf und zu (siehe app.js) -
   dafür darf während der Bewegung nichts herausragen. */
.acc-tree-row { overflow: hidden; }
.acc-tree-badge-icon {
  flex-shrink: 0; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.acc-tree-badge-icon.is-private { background: #f1ece0; color: #7c705c; }
.acc-tree-badge-icon.is-public { background: #e4f1e8; color: #2e6b45; }
.acc-tree-badge-icon.is-shared { background: var(--focus-light); color: var(--focus-dark); }
.acc-tree-collapsed-text { min-width: 0; flex: 1; }
.acc-tree-collapsed-name { font-weight: 800; font-size: 15px; color: var(--ink); }
.acc-tree-collapsed-status { font-size: 11.5px; color: var(--muted); margin-top: 1px; }

.account-danger-zone { border-top: 1px solid var(--card-border); padding-top: 14px; text-align: center; }
/* ============================================================
   Ergänzungen: Lade-Overlay, Onboarding-Hinweis, Passwort-Reset,
   Einstellungen-Überschriften (vor Launch hinzugefügt)
   ============================================================ */

/* ---------- Lade-Overlay beim Start ---------- */
.boot-loader {
  position: fixed; inset: 0; z-index: 200;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 16px; background: var(--app-bg, #FFF8E1);
  transition: opacity .25s ease;
}
.boot-loader.hidden { opacity: 0; pointer-events: none; visibility: hidden; }
#bootLoaderSpinner { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.boot-spinner {
  width: 42px; height: 42px; border-radius: 50%;
  border: 4px solid var(--pink, #F8BBD0);
  border-top-color: var(--focus, #8E244D);
  animation: bootspin .8s linear infinite;
}
.boot-loader-text { color: var(--muted, #8d7468); font-weight: 700; font-size: 14px; }
@keyframes bootspin { to { transform: rotate(360deg); } }
.boot-loader-timeout {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  max-width: 300px; text-align: center;
}
.boot-loader-timeout p { color: var(--ink, #4E342E); font-weight: 600; font-size: 14.5px; line-height: 1.5; }
/* Der hängende Schritt steht über der allgemeinen Meldung und etwas
   kräftiger - er ist die eigentliche Auskunft. */
.boot-loader-stage {
  font-weight: 800 !important; color: var(--focus-dark, #6f1c3c) !important;
  margin-bottom: -4px;
}
.boot-loader-stage:empty { display: none; }

/* ---------- "Bitte warten" fuer laengere Vorgaenge ----------
   Erbt die Optik des Startbildschirms (.boot-loader), liegt aber ueber
   allem anderen und laesst den Hintergrund durchscheinen: man soll sehen,
   dass die App noch da ist und nur gerade arbeitet. */
.busy-overlay {
  z-index: 260;
  background: rgba(255, 248, 225, .82);
  -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
}
.busy-box {
  display: flex; flex-direction: column; align-items: center; gap: 14px;
  background: #fff; border: 1px solid var(--card-border); border-radius: 18px;
  padding: 26px 30px; box-shadow: 0 18px 46px rgba(78,52,46,.18);
  max-width: min(320px, calc(100vw - 40px)); text-align: center;
}
.busy-box .boot-loader-timeout { gap: 12px; margin-top: 2px; }

/* ---------- Onboarding-Hinweis (Coachmark) ---------- */
.coach-hint {
  position: absolute; left: 50%; bottom: calc(var(--nav-h) + 18px);
  transform: translateX(-50%);
  max-width: min(420px, 90vw);
  background: var(--focus, #8E244D); color: #fff;
  padding: 12px 16px; border-radius: 14px;
  font-size: 14px; font-weight: 600; line-height: 1.4;
  display: flex; align-items: center; gap: 12px;
  box-shadow: 0 8px 24px rgba(142,36,77,.32); z-index: 25;
}
.coach-hint.hidden { display: none; }
.coach-hint-close {
  flex-shrink: 0; background: rgba(255,255,255,.18); color: #fff;
  border: none; border-radius: 999px; padding: 6px 14px;
  font-family: inherit; font-weight: 700; font-size: 13px; cursor: pointer;
}
.coach-hint-close:hover { background: rgba(255,255,255,.3); }

/* ---------- Passwort vergessen / erneut senden ---------- */
.auth-forgot-row { margin: -4px 0 12px; text-align: right; }
.auth-forgot-row .btn-link { font-size: 13px; }
.auth-resend-row { margin: -4px 0 12px; text-align: center; }
.auth-resend-row .btn-link { font-size: 13.5px; }

/* ---------- Einstellungen: Zwischenüberschriften ---------- */
.settings-subhead {
  font-size: 11.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted, #8d7468); margin: 18px 6px 6px;
}
.settings-subhead:first-of-type { margin-top: 8px; }

@media (prefers-reduced-motion: reduce) {
  .boot-spinner { animation-duration: 1.6s; }
}

/* ============================================================
   Mobil: Fenster als Vollbild-"Sheet"
   Auf dem Handy füllen die Fenster den Bildschirm - fixe Kopfzeile mit
   grossem Schliessen-Kreuz, darunter der scrollende Inhalt. Dadurch gibt
   es keine abgeschnittenen Ränder, kein seitliches Wischen und die
   Bedienelemente sitzen dort, wo der Daumen sie erreicht.
   ============================================================ */
@media (max-width: 640px) {
  .modal-overlay { padding: 0; align-items: stretch; justify-content: stretch; }
  .modal-card {
    width: 100%; max-width: 100%;
    max-height: none; height: 100%; height: 100dvh;
    border-radius: 0; padding: 20px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    padding-top: calc(20px + env(safe-area-inset-top, 0px));
    box-shadow: none;
  }
  .modal-card.sheet-card { padding: 0; }
  .sheet-head {
    border-radius: 0; padding: 8px 8px 8px 14px;
    padding-top: calc(8px + env(safe-area-inset-top, 0px));
    position: sticky; top: 0; z-index: 3;
  }
  .sheet-body { padding: 14px 16px calc(24px + env(safe-area-inset-bottom, 0px)); }
  .modal-card > .close-btn { top: calc(10px + env(safe-area-inset-top, 0px)); }

  /* Kleine Bestätigungs-Dialoge bleiben mittig als Kärtchen - ein
     Vollbild-Sheet wäre für eine Ja/Nein-Frage übertrieben. */
  .modal-overlay:has(> .confirm-modal-card) { padding: 16px; align-items: center; justify-content: center; }
  /* :has() als Ergänzung, #confirmDialog als sicherer Rückfall für ältere Browser */
  #confirmDialog { padding: 16px; align-items: center; justify-content: center; }
  .modal-card.confirm-modal-card {
    width: 100%; max-width: 360px; height: auto; border-radius: 16px;
    padding: 24px 20px; box-shadow: 0 20px 60px rgba(0,0,0,.25);
  }

  /* Das Upgrade-Fenster bleibt ebenfalls ein Kärtchen in der Mitte: es
     stellt eine einzelne Frage, ein Vollbild-Sheet wäre dafür zu viel. */
  #upgradeModal { padding: 16px; align-items: center; justify-content: center; }
  .modal-card.upgrade-card {
    width: 100%; max-width: 400px; height: auto; max-height: 88dvh;
    border-radius: 16px; box-shadow: 0 20px 60px rgba(0,0,0,.25);
    padding: 24px 20px 20px;
  }

  /* Zwei-Klassen-Regeln weiter oben (z. B. .modal-card.edit-modal-card)
     würden die Höhen-Angabe sonst überstimmen - deshalb hier ebenfalls
     mit zwei Klassen. */
  .modal-card.edit-modal-card, .modal-card.profile-card, .modal-card.auth-card,
  .modal-card.sheet-card {
    width: 100%; max-height: none; height: 100dvh;
  }
  .name-row { flex-direction: column; gap: 0; }

  /* Beschriftung über dem Wert, sobald es sonst zu eng wird */
  #editPagePerson .field-row { grid-template-columns: 112px minmax(0, 1fr); gap: 8px; }
  .modal-card .field-label { font-size: 13.5px; }
  .segmented .seg span { font-size: 12.5px; }
}

@media (max-width: 380px) {
  #editPagePerson .field-row {
    grid-template-columns: minmax(0, 1fr); gap: 2px; padding-top: 10px; padding-bottom: 10px;
  }
  #editPagePerson .field-row-switch { grid-template-columns: minmax(0, 1fr) auto; align-items: center; }
}

/* iOS zoomt Formularfelder automatisch hinein, wenn die Schrift < 16px ist
   - deshalb ALLE Eingabefelder und Auswahllisten auf mindestens 16px. */
@media (max-width: 640px) {
  input, select, textarea { font-size: 16px !important; }
  .date-part { font-size: 16px !important; }
}

/* ============================================================
   Demo-Baukasten der Landingpage (/app?demo=1)
   ------------------------------------------------------------
   Die Demo laeuft als ganz normale App in einem Rahmen auf der
   Landingpage. Dort gehoeren Kopfzeile, untere Leiste und der
   Konto-Hinweis nicht hin - die Landingpage rahmt den Baukasten selbst
   ein und stellt den Weg zum Konto daneben. Statt Positionen zu
   ueberschreiben werden einfach die Hoehen-Variablen auf 0 gesetzt, aus
   denen die App ihre Flaechen ohnehin berechnet - dadurch fuellt der Baum
   den Rahmen exakt aus, ohne dass irgendeine Ansicht Sonderregeln braucht.
   ============================================================ */
.demo-embed { --header-h: 0px; --nav-h: 0px; }
.demo-embed .topbar,
.demo-embed .bottom-nav,
.demo-embed #guestBanner { display: none !important; }

/* ---------- Wechsel auf Farefisi Plus (Upgrade-Fenster) ----------
   Ein Fenster für zwei Wege: den Knopf unter "Abo Plus" und jede
   erreichte Free-Grenze. */
/* Über allen anderen Fenstern: das Upgrade-Fenster meldet sich auch aus
   einem offenen Bearbeiten-Fenster oder aus "Abo Plus" heraus - dort läge
   es sonst hinter dem Fenster, aus dem es aufgerufen wurde. */
#upgradeModal { z-index: 90; }
.modal-card.upgrade-card {
  width: 400px; padding: 28px 24px 22px; position: relative; text-align: left;
}
.upgrade-close { top: 10px; right: 10px; }
/* padding-right hält den Titel vom Schliessen-Kreuz frei - auf schmalen
   Geräten lief er sonst darunter durch. */
.upgrade-head {
  display: flex; align-items: flex-start; gap: 10px;
  margin-bottom: 10px; padding-right: 34px;
}
.upgrade-crown {
  display: grid; place-items: center; color: var(--gold-dark);
  flex-shrink: 0; margin-top: 2px;
}
.upgrade-title {
  font-family: var(--font-display); font-weight: 400; font-size: 21px;
  letter-spacing: -.2px; color: var(--ink); margin: 0;
}
.upgrade-lead {
  font-size: 14px; line-height: 1.55; color: var(--muted); margin: 0 0 18px;
}
.upgrade-box {
  border: 1px solid #eddfba; background: #fffbf1; border-radius: 14px;
  padding: 16px 16px 14px;
}
.upgrade-price-row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; flex-wrap: wrap; margin-bottom: 14px;
}
.upgrade-plan-name { font-size: 16px; font-weight: 800; color: var(--ink); }
.upgrade-price {
  font-size: 21px; font-weight: 800; color: var(--gold-dark); white-space: nowrap;
}
.upgrade-price-per { font-size: 14px; font-weight: 700; }
.upgrade-perks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.upgrade-perks li {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: 14px; line-height: 1.45; color: var(--ink);
}
.upgrade-perks svg { color: #2e6b45; flex-shrink: 0; margin-top: 2px; }
.upgrade-note {
  margin: 14px 0 0; padding-top: 12px; border-top: 1px solid #eddfba;
  font-size: 12px; line-height: 1.5; color: var(--muted);
}
.upgrade-actions {
  display: flex; align-items: center; gap: 12px; margin-top: 18px;
}
.upgrade-later {
  font-size: 14.5px; font-weight: 700; color: var(--muted);
  padding: 12px 6px; min-height: 44px; flex-shrink: 0;
  text-decoration: none;
}
.upgrade-later:hover { color: var(--ink); text-decoration: none; }
.upgrade-go {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px;
}
.upgrade-go:disabled { opacity: .65; cursor: default; }
.upgrade-secure {
  margin: 10px 0 0; text-align: center; font-size: 11.5px; color: var(--muted);
}

/* Wer bereits Plus hat und trotzdem an eine Grenze stösst (z. B. das 6.
   Familienarchiv): kein Upgrade-Angebot mehr, nur der erklärende Satz und
   ein "Verstanden"-Knopf statt Preis/Vorteilsliste/Bezahl-Hinweis. Siehe
   openUpgradeModal() in app.js. */
#upgradeModal.is-at-max .upgrade-box,
#upgradeModal.is-at-max .upgrade-secure,
#upgradeModal.is-at-max #upgradeGoBtn { display: none; }
#upgradeModal.is-at-max .upgrade-actions { justify-content: center; }
#upgradeModal.is-at-max .upgrade-later {
  flex: 1; text-align: center; padding: 12px; border-radius: 10px;
  background: var(--card-border, #ecdfc4);
}

@media (max-width: 340px) {
  .modal-card.upgrade-card { padding: 22px 16px 16px; }
  .upgrade-actions { flex-direction: column-reverse; gap: 6px; }
  .upgrade-go { width: 100%; }
  .upgrade-later { width: 100%; }
}
