/*
 * Design-System nach dem Fernweh-Konzept.
 *
 * Zwei Dinge, die den Charakter ausmachen:
 *  - Der Hintergrund ist warm (Sand), nicht kaltgrau. Eine Reise-App soll sich
 *    nicht anfühlen wie ein Verwaltungsformular.
 *  - Status wird NIE nur über Farbe erzählt. Jedes Abzeichen trägt Text, jede
 *    Warnung ein Zeichen — sonst ist die App für jeden Zwölften unbrauchbar.
 *
 * Handy zuerst: Tippflächen ≥ 44 px, Schrift in Eingabefeldern ≥ 16 px (sonst
 * zoomt iOS beim Antippen hinein).
 */

:root {
  /* Marke */
  --brand-900: #06343b;
  --brand-700: #0c5a66;
  --brand-600: #10707a;
  --brand-500: #1b8e96;
  --brand-100: #d6efef;
  --brand-050: #edf7f7;

  --sun-600: #d9662b;
  --sun-500: #f0864a;
  --sun-100: #fde8da;

  --berry-500: #b0407a;
  --berry-100: #fadceb;

  --ok-600: #1f7a55;
  --ok-500: #2e9e6b;
  --ok-100: #ddf2e8;
  --warn-600: #a8790a;
  --warn-500: #d9a21b;
  --warn-100: #fbf0d2;
  --err-600: #c0392b;
  --err-100: #fbe3e0;

  /* Neutral */
  --ink-900: #0d1721;
  --ink-700: #2b3a47;
  --ink-500: #5a6b7a;
  --ink-300: #93a2ae;
  --ink-200: #c9d3db;
  --ink-100: #e7edf1;
  --paper: #ffffff;
  --sand: #f7f4ef;
  --sand-2: #efeae2;

  /* Semantisch — Hell ist der Normalfall */
  --bg: var(--sand);
  --surface: var(--paper);
  --surface-2: #fbf9f6;
  --line: var(--ink-100);
  --text: var(--ink-900);
  --text-2: var(--ink-500);
  --accent: var(--brand-600);
  --accent-ink: #ffffff;
  --accent-soft: var(--brand-050);
  --danger: var(--err-600);
  --danger-soft: var(--err-100);
  --ok: var(--ok-600);
  --ok-soft: var(--ok-100);
  --warn: var(--warn-600);
  --warn-soft: var(--warn-100);

  /* Form */
  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 16px;
  --r-lg: 22px;
  --r-xl: 28px;
  --r-pill: 999px;

  --e1: 0 1px 2px rgb(13 23 33 / 0.06), 0 1px 1px rgb(13 23 33 / 0.04);
  --e2: 0 4px 14px rgb(13 23 33 / 0.08), 0 1px 3px rgb(13 23 33 / 0.05);
  --e3: 0 14px 40px rgb(13 23 33 / 0.14), 0 3px 10px rgb(13 23 33 / 0.07);

  --ease: cubic-bezier(0.22, 0.8, 0.28, 1);
  --font: "Inter", "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --pad: 20px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #101619;
    --surface: #171f23;
    --surface-2: #1d272c;
    --line: #2a363c;
    --text: #eef4f5;
    --text-2: #9aabb3;
    --accent: #4ac7d0;
    --accent-ink: #05242a;
    --accent-soft: #123036;
    --danger: #ff9b90;
    --danger-soft: #3a1f1c;
    --ok: #6fd3a0;
    --ok-soft: #102c22;
    --warn: #e8c25f;
    --warn-soft: #302713;
    --e1: 0 1px 2px rgb(0 0 0 / 0.4);
    --e2: 0 4px 14px rgb(0 0 0 / 0.45);
    --e3: 0 14px 40px rgb(0 0 0 / 0.55);
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font: 450 15px/1.45 var(--font);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
}

/* Zeiten und Beträge springen sonst beim Aktualisieren. */
.item-time,
.route-time,
.tile-value,
.mono,
time {
  font-variant-numeric: tabular-nums;
}

.app {
  max-width: 620px;
  margin: 0 auto;
  padding: max(12px, env(safe-area-inset-top)) 20px calc(110px + env(safe-area-inset-bottom));
}

h1 {
  margin: 0;
  font: 700 22px/1.2 var(--font);
  letter-spacing: -0.3px;
}

h2 {
  margin: 22px 0 10px;
  font: 650 17px/1.3 var(--font);
}

p.sub {
  margin: 4px 0 20px;
  color: var(--text-2);
}

.hint {
  margin-top: 8px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--text-2);
}

.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px;
  word-break: break-all;
}

a {
  color: var(--accent);
}

/* --- Flächen -------------------------------------------------------------- */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--e1);
  padding: var(--pad);
  margin-bottom: 14px;
}

/* --- Kopfzeile ------------------------------------------------------------ */

/*
 * Die Kopfzeile schwebt. Hintergrund mit leichter Unschärfe, damit der
 * Inhalt beim Durchscrollen nicht durch die Knöpfe hindurch zu lesen ist.
 * --kopf ist ihre Höhe — die Tagesüberschriften der Zeitleiste kleben darunter.
 */
:root {
  --kopf: calc(max(8px, env(safe-area-inset-top)) + 48px);
}

.head {
  position: sticky;
  top: 0;
  z-index: 20;
  /*
   * Nach oben in den Rand der Seite hineinziehen: .app hat oben schon
   * max(12px, Statusleiste) Abstand, und die Kopfzeile brachte ihn noch
   * einmal mit. In der iPhone-App (Statusleiste ~60 px) stand deshalb alles
   * doppelt so weit unten (Alex, 25.09.2026). Im Browser ist der Abstand 0
   * und es fiel nicht auf.
   */
  margin: calc(-1 * max(12px, env(safe-area-inset-top))) -20px 14px;
  padding: max(8px, env(safe-area-inset-top)) 20px 8px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.head-row {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) 88px;
  align-items: center;
  gap: 8px;
}

.head-links,
.head-rechts {
  display: flex;
  gap: 8px;
}

.head-rechts {
  justify-content: flex-end;
}

.head-row h1 {
  text-align: center;
  font-size: 19px;
  overflow-wrap: anywhere;
  /* Höchstens zwei Zeilen — ein Eintrag wie „부산영화체험박물관 — Busan
     Museum of Movies“ oder ein Belegname lief über vier Zeilen und schob die
     schwebende Leiste über den halben Bildschirm (Durchsicht 25.09.2026).
     Der volle Titel steht auf der Seite selbst. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
  line-height: 1.2;
}

/* iPad hochkant und kleine Laptop-Fenster: etwas mehr Breite als am Handy,
   ohne dass Textzeilen zu lang werden. */
@media (min-width: 760px) {
  .app {
    max-width: 720px;
  }
}

.icon-btn {
  width: 40px;
  height: 40px;
  min-height: 40px;
  margin: 0;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 18px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  box-shadow: var(--e1);
}

.icon-btn.ghosted {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  color: var(--text-2);
}

.head .sub {
  display: none;
}

/* --- Bedienelemente ------------------------------------------------------- */

button {
  width: 100%;
  min-height: 48px;
  margin-top: 14px;
  padding: 13px 18px;
  font: 650 15px/1.2 var(--font);
  color: var(--accent-ink);
  background: var(--accent);
  border: 0;
  border-radius: var(--r-sm);
  box-shadow: var(--e1);
  cursor: pointer;
  transition: transform 180ms var(--ease), opacity 180ms var(--ease);
}

button:active {
  transform: scale(0.985);
}

button:disabled {
  opacity: 0.5;
  cursor: default;
}

button.ghost {
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
}

button.danger {
  color: var(--danger);
  background: transparent;
  border: 1px solid var(--danger);
  box-shadow: none;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

label {
  display: block;
  margin: 14px 0 5px;
  font: 650 11px/1.3 var(--font);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-2);
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
input[type="url"],
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="number"],
textarea,
select {
  width: 100%;
  padding: 12px 13px;
  font: 450 16px/1.35 var(--font);
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  appearance: none;
}

textarea {
  min-height: 96px;
  resize: vertical;
  font-family: inherit;
}

select {
  background-image: linear-gradient(45deg, transparent 50%, var(--text-2) 50%),
    linear-gradient(135deg, var(--text-2) 50%, transparent 50%);
  background-position: calc(100% - 18px) 21px, calc(100% - 13px) 21px;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 36px;
}

label.check {
  display: flex;
  gap: 11px;
  align-items: center;
  margin: 12px 0;
  font: 450 15px/1.3 var(--font);
  letter-spacing: 0;
  text-transform: none;
  color: var(--text);
}

label.check input[type="checkbox"] {
  width: 22px;
  height: 22px;
  flex: none; /* bei zweizeiligem Text nicht schrumpfen */
  accent-color: var(--accent);
}

.people-pick {
  display: grid;
  gap: 0;
  padding-left: 2px;
}

.field {
  margin-bottom: 2px;
}

.row {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
}

.row.two {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
}

details.card > summary,
details > summary {
  font: 650 14px/1.3 var(--font);
  color: var(--text-2);
  cursor: pointer;
  list-style: none;
  margin-top: 12px;
}

details.card > summary {
  margin-top: 0;
  font-size: 15px;
  color: var(--text);
}

summary::-webkit-details-marker {
  display: none;
}

details > summary::after {
  content: " +";
  color: var(--text-2);
}

details[open] > summary::after {
  content: " –";
}

.msg {
  margin-top: 12px;
  padding: 11px 13px;
  border-radius: var(--r-sm);
  font-size: 14px;
}

.msg.error {
  color: var(--danger);
  background: var(--danger-soft);
}

.msg.ok {
  color: var(--ok);
  background: var(--ok-soft);
}

.loading {
  padding: 48px 0;
  text-align: center;
  color: var(--text-2);
}

/* --- Reisen als Cover-Karten --------------------------------------------- */

.trip-list {
  display: grid;
  gap: 14px;
  margin-bottom: 18px;
}

.trip-card {
  position: relative;
  display: grid;
  gap: 3px;
  margin: 0;
  padding: 20px;
  min-height: 128px;
  text-align: left;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-700), var(--brand-900) 70%);
  border: 0;
  border-radius: var(--r-xl);
  box-shadow: var(--e2);
  overflow: hidden;
}

.trip-card::after {
  content: "";
  position: absolute;
  right: -40px;
  top: -50px;
  width: 160px;
  height: 160px;
  border-radius: 50%;
  background: rgb(255 255 255 / 0.05);
}

.trip-card.past {
  background: linear-gradient(135deg, #3b4a52, #222c31 70%);
}

.trip-name {
  font: 700 21px/1.15 var(--font);
  letter-spacing: -0.4px;
}

.trip-stand {
  display: grid;
  margin-top: 6px;
}

.trip-meta {
  font: 500 12.5px/1.35 var(--font);
  opacity: 0.9;
}

.countdown {
  position: absolute;
  top: 16px;
  right: 16px;
  padding: 6px 12px;
  font: 650 12px/1 var(--font);
  color: #fff;
  background: var(--sun-500);
  border-radius: var(--r-pill);
  box-shadow: var(--e1);
}

.progress {
  /* block: als <span> in einer Karte war der Balken sonst 19 px hoch und weiß
     (die Höhe greift bei inline nicht) — Startseite, 25.09.2026 */
  display: block;
  height: 5px;
  margin-top: 12px;
  border-radius: var(--r-pill);
  background: rgb(255 255 255 / 0.25);
  overflow: hidden;
}

.progress > i {
  display: block;
  height: 100%;
  border-radius: var(--r-pill);
  background: #fff;
  transition: width 280ms var(--ease);
}

/* ---------------------------------------------------------------------------
   Der Balken in drei Abschnitten — bezahlt, gebucht, zu buchen.

   Zwei Fehler steckten hier: Die Abschnitte waren display:block und standen
   damit UNTEREINANDER in einem 5 px hohen Kasten — sichtbar war nur der erste.
   Und Farben hatten sie nie, alle drei erbten das Weiß von oben. Der Balken
   zeigte also faktisch nur „bezahlt", einfarbig.
   --------------------------------------------------------------------------- */
.progress.segmente {
  display: flex;
  gap: 2px;
}

.progress.segmente > i {
  border-radius: 0;
  transition: width 280ms var(--ease);
}

.progress.segmente > i:first-child {
  border-radius: var(--r-pill) 0 0 var(--r-pill);
}

.progress.segmente > i:last-child {
  border-radius: 0 var(--r-pill) var(--r-pill) 0;
}

/* Auf dem dunklen Deckblatt: erledigt grün, gebucht hell, offen orange. */
.seg-paid {
  background: var(--ok-500);
}

.seg-booked {
  background: var(--brand-100);
}

.seg-open {
  background: var(--sun-500);
}

/* --- Kennzahlen ----------------------------------------------------------- */

.tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-bottom: 16px;
}

.tile {
  padding: 13px 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--e1);
}

.tile-label {
  font: 650 10.5px/1.3 var(--font);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-2);
}

.tile-value {
  margin-top: 3px;
  font: 700 18px/1.2 var(--font);
}

/* ---------------------------------------------------------------------------
   Die Nebenwege als kompaktes Raster

   Hier standen sechs Balken über die volle Breite untereinander — rund 380 px
   gleich aussehender Knöpfe zwischen der Kopfkarte und dem eigentlichen Plan.
   Zwei Spalten mit Symbol und kurzem Wort brauchen weniger als die Hälfte, und
   sichtbar ist nur, was zur Reisephase passt (siehe trip.js).
   --------------------------------------------------------------------------- */

/* Die Kopfkarte soll als eigener Block wirken und nicht am Nächsten kleben. */
.hub-cover {
  margin-bottom: 22px;
}

/* ---------------------------------------------------------------------------
   Sicherheitsmeldung

   Steht über allem anderen und bleibt, bis man sie ausdrücklich bestätigt.
   Rot, weil sie genau eine Frage stellt: War das abgesprochen?
   --------------------------------------------------------------------------- */
.sicherheitsmeldung {
  margin-bottom: 16px;
  border: 2px solid var(--danger);
  background: var(--danger-soft);
}

.sicherheit-kopf {
  font: 700 13px/1.3 var(--font);
  letter-spacing: 0.3px;
  color: var(--danger);
}

.sicherheit-text {
  margin: 6px 0;
  font: 500 14.5px/1.45 var(--font);
  color: var(--text);
}

.sicherheitsmeldung .sekundaer {
  width: 100%;
  margin-top: 10px;
}

.aktionsbereich {
  display: grid;
  gap: 8px;
  margin-bottom: 18px;
}

.aktionen {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

/* Zugeklappt heißt wirklich weg — nicht nur durchsichtig. Sonst bliebe die
   Höhe stehen und der Plan käme keinen Millimeter näher. */
.aktionen-mehr {
  display: none;
}

.aktionen-mehr.offen {
  display: grid;
}

.aktion {
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) auto;
  align-items: center;
  gap: 9px;
  margin: 0;
  padding: 11px 12px;
  /* Antippfläche über 44 px, auch wenn der Text kurz ist. */
  min-height: 48px;
  text-align: left;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--e1);
}

.aktion:active {
  background: var(--surface-2);
}

.aktion-symbol {
  font-size: 17px;
  line-height: 1;
  text-align: center;
}

.aktion-wort {
  font: 600 13.5px/1.25 var(--font);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.aktion-mehr {
  color: var(--text-2);
  background: var(--surface-2);
  box-shadow: none;
}

/* Offene Belege sind eine Aufgabe, keine Verzierung — deshalb auffällig. */
.aktion-zahl {
  display: grid;
  place-items: center;
  min-width: 21px;
  height: 21px;
  padding: 0 6px;
  font: 700 11.5px/1 var(--font);
  color: #fff;
  background: var(--sun-600);
  border-radius: var(--r-pill);
}

@media (max-width: 360px) {
  .aktion {
    grid-template-columns: 20px minmax(0, 1fr) auto;
    gap: 7px;
    padding: 11px 10px;
  }
  .aktion-wort {
    font-size: 12.5px;
  }
}

@media print {
  .aktionsbereich {
    display: none;
  }
}

/* --- Reisende: sichtbar und als Filter ------------------------------------ */

.people-bar {
  /* Bis an den Rand scrollen lassen, damit sichtbar wird, dass es weitergeht. */
  margin: 0 -20px 14px;
  padding: 0 20px;
  position: relative;
}

.avatars {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding-bottom: 2px;
  scrollbar-width: none;
}

.avatars::-webkit-scrollbar {
  display: none;
}

.avatar {
  position: relative;
  width: auto;
  min-height: 42px;
  margin: 0;
  padding: 5px 11px 5px 5px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  font: 600 13px/1 var(--font);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  box-shadow: var(--e1);
}

.avatar.active {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.avatar-initials {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  font: 700 11px/1 var(--font);
  color: #fff;
  background: var(--person, var(--brand-600));
  border-radius: 50%;
}

.avatar-count {
  padding: 2px 7px;
  font: 700 10px/1.3 var(--font);
  color: var(--accent-ink);
  background: var(--sun-500);
  border-radius: var(--r-pill);
}

.avatar.active .avatar-count {
  color: var(--accent);
  background: #fff;
}

.filter-note {
  width: 100%;
  min-height: 40px;
  margin-top: 8px;
  padding: 9px 14px;
  font: 600 12.5px/1.3 var(--font);
  color: var(--accent);
  background: var(--accent-soft);
  border: 0;
  border-radius: var(--r-sm);
  box-shadow: none;
}

/* --- Warnungen ------------------------------------------------------------ */

.warnbox {
  margin-bottom: 14px;
  padding: 11px 14px;
  background: var(--warn-soft);
  border-radius: var(--r-md);
}

.warnbox > summary {
  margin: 0;
  font: 650 13px/1.3 var(--font);
  color: var(--warn);
  cursor: pointer;
  list-style: none;
}

.warnbox > summary::after {
  content: " ▾";
}

.warnbox[open] > summary::after {
  content: " ▴";
}

.warnline {
  margin-top: 7px;
  font: 500 12.5px/1.4 var(--font);
  color: var(--warn);
}

/* --- Zeitstrahl ----------------------------------------------------------- */

.timeline {
  display: grid;
  gap: 10px;
  margin-bottom: 16px;
}

.day {
  position: sticky;
  /* Unter der schwebenden Kopfzeile, nicht dahinter. */
  top: var(--kopf);
  z-index: 5;
  margin: 12px -20px 0;
  padding: 8px 20px;
  font: 650 11px/1.3 var(--font);
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--text-2);
  background: var(--bg);
}

.item {
  display: grid;
  /*
   * Knotenspalte, Text, Bilder — mit FESTEN Plätzen.
   *
   * Vorher lief das über den Auto-Fluss des Rasters, und die Kachel sah je
   * nachdem, ob ein Bild da war, anders aus: mal stand der Status als Pille
   * rechts neben dem Titel, mal als breiter Balken darunter. Alex hat am
   * 21.09.2026 eine Skizze geschickt und um eine klar abgegrenzte Kachel
   * gebeten — dafür muss jedes Stück seinen Platz kennen.
   *
   *   Zeile 1:  Knoten | Text (Titel, Ort, Status) | Bilderstreifen
   *   Zeile 2:  Knoten | die drei Vorschlagsknöpfe, über beide Spalten
   */
  grid-template-columns: 34px minmax(0, 1fr) auto;
  grid-template-rows: auto auto;
  gap: 10px;
  align-items: start;
  margin: 0;
  /* Kompakter als vorher (war 14px): Es passen spürbar mehr Einträge auf den
     Schirm, ohne dass der Titel gedrängt wirkt. */
  padding: 10px 12px;
  min-height: 52px;
  text-align: left;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--ink-200);
  border-radius: var(--r-md);
  box-shadow: var(--e1);
}

.item.status-to_book {
  border-left-color: var(--warn-500);
}

.item.status-booked {
  border-left-color: var(--ok-500);
}

.item.status-paid {
  border-left-color: var(--accent);
}

/*
 * Gemacht ist die Ruhefarbe: gedämpft, nicht abgehakt-grau.
 * Was war, soll den Blick nicht mehr fangen — aber auch nicht aussehen,
 * als wäre es abgesagt worden.
 */
.item.status-done {
  border-left-color: var(--text-2);
  opacity: 0.82;
}

.item-time {
  padding-top: 1px;
  font: 600 13px/1.3 var(--font);
  color: var(--text-2);
}

.item-body {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.item-title {
  font: 650 15px/1.3 var(--font);
  overflow-wrap: anywhere;
}

.item-sub {
  font: 450 13px/1.4 var(--font);
  color: var(--text-2);
  overflow-wrap: anywhere;
}

.badge {
  align-self: center;
  padding: 4px 10px;
  font: 650 11px/1.3 var(--font);
  white-space: nowrap;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.badge.to_book {
  color: var(--warn);
  background: var(--warn-soft);
  border-color: transparent;
}

.badge.booked {
  color: var(--ok);
  background: var(--ok-soft);
  border-color: transparent;
}

.badge.paid {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: transparent;
}

.badge.done {
  color: var(--text-2);
  background: var(--surface-2);
  border-color: transparent;
}

/*
 * Die Status-Pille ist ein <button> und erbt damit width:100% aus der
 * globalen Regel — sie lief als breiter Balken über die halbe Kachel.
 * Sie soll ihren Text umschließen, nicht die Zeile.
 */
.item-body > .badge-knopf {
  width: auto;
  justify-self: start;
  margin: 2px 0 0;
  min-height: 0;
  box-shadow: none;
}

/* --- Die Plätze in der Kachel --------------------------------------------- */

/*
 * MIT NAMEN statt mit Spaltennummern — und das hat einen teuer bezahlten
 * Grund.
 *
 * Der erste Anlauf am 21.09.2026 schrieb `grid-area: 1 / 2 / 2 / 3`, also
 * "Spalte 2". Das stimmt überall — nur nicht im Zeitstrahl. Dort steht der
 * Knoten AUSSERHALB der Kachel (position: absolute auf der Schiene), und
 * .timeline .item hat deshalb eine Spalte weniger. Spalte 2 war dort nicht
 * der Text, sondern die schmale Spalte ganz rechts: Der Titel klebte am
 * rechten Rand, links davon klaffte die halbe Kachel.
 *
 * Auf dem Handy fiel das nicht auf, weil dort ohnehin alles untereinander
 * steht. Alex hat es am PC gesehen: "die anzeige auf einem pc ist schlecht."
 *
 * Mit Namen kann das nicht mehr passieren: Jeder Zusammenhang legt seine
 * eigenen Felder fest, und "inhalt" heißt überall Inhalt.
 */
.item {
  grid-template-columns: 34px minmax(0, 1fr);
  grid-template-areas:
    "knoten inhalt"
    "knoten bilder"
    "knoten knoepfe";
}

.item > .knoten            { grid-area: knoten; }
.item > .item-body         { grid-area: inhalt; }
.item > .item-bilder       { grid-area: bilder; }
.item > .vorschlag-knoepfe { grid-area: knoepfe; }

/*
 * Im Zeitstrahl fehlt die Knotenspalte — der Knoten hängt außen an der
 * Schiene. Also eine Spalte weniger, sonst dasselbe.
 */
.timeline .item {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas:
    "inhalt"
    "bilder"
    "knoepfe";
}

/*
 * Breit genug? Dann die Bilder daneben statt darunter.
 *
 * Der Container sitzt am LISTENELEMENT, nicht an der Kachel selbst — eine
 * Container-Abfrage gilt immer für die Nachkommen des Containers, nie für
 * ihn selbst. Stand container-type auf .item, konnte @container für .item
 * nie greifen; gemessen am 21.09.2026: Bei 541 px Kachelbreite blieben es
 * zwei Spalten, weil die Abfrage schlicht nie zutraf.
 */
.timeline,
.station-body,
.tag-liste {
  container-type: inline-size;
}

@container (min-width: 430px) {
  .item {
    grid-template-columns: 34px minmax(0, 1fr) auto;
    grid-template-areas:
      "knoten inhalt  bilder"
      "knoten knoepfe bilder";
  }

  .timeline .item {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "inhalt  bilder"
      "knoepfe bilder";
  }
}

/*
 * Der Bilderstreifen.
 *
 * Waagrecht scrollend mit Einrastpunkten: ein Wisch, ein Bild. `touch-action:
 * pan-x` ist nicht Zierde — ohne das schluckt die Kachel, die selbst ein
 * Knopf ist, die Wischgeste und man scrollt stattdessen die Seite.
 *
 * Die Breite wächst mit dem Schirm, bleibt aber gedeckelt: Auf einem
 * 360-px-Handy darf das Bild dem Titel nicht den Platz wegnehmen.
 */
/*
 * SCHMAL: Bilder unter dem Text, über die ganze Breite.
 * BREIT:  Bilder rechts daneben, wie in Alex' Skizze.
 *
 * Warum nicht überall nebeneinander: Gemessen am 21.09.2026 auf einem
 * 390-px-Handy ist eine Eintragskachel im Aufenthalt nur 281 px breit.
 * Davon gehen 34 px Knotenspalte und 24 px Innenabstand ab. Bleiben 223 px
 * für Text UND Bild. Ein Bild von 117 px ließ dem Titel 116 px — "성산일출봉
 * (Seongsan Ilchulbong) — der Krater am Meer" brach auf FÜNF Zeilen um.
 *
 * Das Bild soll ja gerade zeigen, was der Ort ist. Auf dem Handy kann es
 * das über die volle Breite deutlich besser als als Briefmarke daneben.
 */
.item-bilder {
  display: flex;
  gap: 4px;
  width: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  touch-action: pan-x;
  scrollbar-width: none;
  border-radius: 8px;
}

@container (min-width: 430px) {
  .item-bilder { width: clamp(120px, 34cqw, 190px); }
}

.item-bilder::-webkit-scrollbar { display: none; }

.item-bild {
  position: relative;
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: center;
  display: block;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  border-radius: 8px;
  background: var(--surface-2);
}

.item-bild img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Ein geholtes Vorschaubild ist nicht das eigene — der gestrichelte Rand
   sagt das, ohne ein Wort zu brauchen. */
.item-bild.ist-vorschau {
  outline: 1px dashed var(--line);
  outline-offset: -1px;
}

.item-bild.mehr {
  display: grid;
  place-items: center;
  font: 600 13px/1 var(--font);
  color: var(--text-2);
  border: 1px solid var(--line);
}

/* Mehr als eines? Dann sagt ein Punktband, dass es sich zu wischen lohnt. */
.item-bilder:has(.item-bild + .item-bild) {
  box-shadow: inset -8px 0 8px -8px rgba(0, 0, 0, .25);
}

/* --- Die drei Knöpfe an einem Vorschlag ----------------------------------- */

/*
 * Sie sitzen IN der Zeile, die selbst ein Knopf ist. Deshalb brauchen sie
 * eine eigene, kleinere Sprache: keine Flächen, die mit der Zeile
 * konkurrieren, aber Ziele, die man mit dem Daumen trifft.
 *
 * min-height 34 px: darunter wird es auf einem Handy zur Zielübung, und
 * einer der drei löscht.
 */
.vorschlag-knoepfe {
  /* Eigene Zeile über alle drei Spalten der Eintragszeile. */
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.vk {
  /*
   * Die globale Regel setzt jeden button auf width:100% und margin-top:14px —
   * gedacht für die großen Knöpfe am Seitenende. Hier muss beides weg, sonst
   * steht jeder der drei auf einer eigenen Zeile (gemessen am 20.09.2026:
   * dreimal 170 px untereinander in einer 170 px breiten Spalte).
   */
  flex: 0 1 auto;
  width: auto;
  margin: 0;
  box-shadow: none;
  min-height: 34px;
  padding: 0 11px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text);
  font: 600 13px/1 var(--font);
  cursor: pointer;
  white-space: nowrap;
}

.vk:disabled {
  opacity: 0.5;
}

.vk-ja {
  border-color: var(--ok-500);
  color: var(--ok-600);
}

.vk-fertig {
  border-color: var(--line);
  color: var(--text-2);
}

.vk-weg {
  border-color: var(--danger);
  color: var(--danger);
}

/* --- Aufenthalt als Abschnitt --------------------------------------------- */

.station {
  border-radius: var(--r-lg);
  box-shadow: var(--e2);
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--line);
}

.station-head {
  display: grid;
  gap: 3px;
  width: 100%;
  margin: 0;
  padding: 16px 18px;
  min-height: 0;
  text-align: left;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-600), var(--brand-900));
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.station-name {
  font: 700 18px/1.2 var(--font);
  letter-spacing: -0.2px;
}

.station-span {
  font: 500 12.5px/1.35 var(--font);
  opacity: 0.88;
}

.station-head .chip {
  color: #fff;
  background: rgb(255 255 255 / 0.18);
  border-color: rgb(255 255 255 / 0.28);
}

.station-body {
  display: grid;
  gap: 8px;
  padding: 12px 12px 12px 14px;
  /* Getönter Grund + durchgehende Linie: Man sieht auf einen Blick, was zu
     diesem Aufenthalt gehört und was nicht mehr. */
  background: var(--accent-soft);
  border-left: 3px solid var(--accent);
}

.day.inner {
  position: static;
  margin: 4px 0 0;
  padding: 0 2px;
  background: transparent;
}

.item.inner {
  background: var(--surface);
  box-shadow: none;
  border-left-width: 3px;
}

.add-inline {
  /* Klarer Rahmen und eigene Fläche: Gestrichelt sah nach Platzhalter aus,
     nicht nach etwas zum Antippen. */
  margin: 2px 0 0;
  padding: 11px;
  min-height: 44px;
  font: 650 13.5px/1.2 var(--font);
  color: var(--accent);
  background: var(--surface);
  border: 1.5px solid var(--accent);
  border-radius: var(--r-sm);
  box-shadow: var(--e1);
}

.add-inline:active {
  background: var(--accent-soft);
}

/* --- Chips ---------------------------------------------------------------- */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  /*
   * width:auto ist hier kein Schönheitswunsch.
   *
   * Die globale Regel setzt JEDEN button auf width:100% — gedacht für die
   * großen Knöpfe am Seitenende. Ein .chip ist mal ein <span> (dann ist die
   * Regel egal) und mal ein <button> (im Positionseditor, im Zeitstrahl).
   * Als Knopf stand er in voller Breite da: vier Namen unter einer
   * Rechnungsposition wurden zu vier Balken untereinander.
   *
   * Dieselbe Falle hat am 20. und 21.09.2026 schon die Vorschlagsknöpfe und
   * die Status-Pille erwischt. test-css.js hält sie jetzt fest.
   */
  width: auto;
  padding: 5px 11px;
  font: 650 11px/1.3 var(--font);
  letter-spacing: 0.3px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.chips.small .chip {
  padding: 3px 9px;
  font-size: 10.5px;
}

.pill {
  padding: 5px 12px;
  font: 650 11.5px/1.3 var(--font);
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-pill);
}

/* --- Mitglieder ----------------------------------------------------------- */

.member {
  /*
   * minmax(0, 1fr) statt 1fr — der entscheidende Unterschied.
   *
   * Ein blankes 1fr hat implizit min-width:auto: Die Spalte kann NICHT kleiner
   * werden als ihr Inhalt. Bei "Denis Lucian Pop" mit langer E-Mail schob sie
   * die ganze Zeile über den Rand, und der Entfernen-Knopf landete außerhalb
   * des Bildschirms — unerreichbar.
   */
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto 44px;
  gap: 10px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.member-name {
  min-width: 0;
}

.member-name strong,
.member-name .hint {
  display: block;
  overflow-wrap: anywhere;   /* lange E-Mails brechen um, statt zu schieben */
}

/*
 * Auf schmalen Geräten zweizeilig: Name oben, Rolle und Entfernen darunter.
 * Nebeneinander bliebe für den Namen sonst kaum Platz.
 */
@media (max-width: 420px) {
  .member {
    grid-template-columns: minmax(0, 1fr) 44px;
    row-gap: 6px;
  }

  .member-name {
    grid-column: 1 / -1;
  }
}

.member select {
  width: auto;
  padding: 8px 30px 8px 10px;
  font-size: 13px;
  background-position: calc(100% - 14px) 17px, calc(100% - 9px) 17px;
}

.member .icon-btn {
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  color: var(--danger);
}

/* --- Ab/An bei Transport -------------------------------------------------- */

.route {
  display: grid;
  gap: 2px;
  margin: 16px 0 4px;
  padding: 15px;
  background: var(--surface-2);
  border-radius: var(--r-md);
}

.route-end {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  grid-template-areas:
    "label place"
    "label time"
    "label tz";
  gap: 1px 8px;
  align-items: baseline;
}

.route-label {
  grid-area: label;
  align-self: center;
  font: 700 10.5px/1.3 var(--font);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-2);
}

.route-place {
  grid-area: place;
  font: 650 14px/1.3 var(--font);
}

.route-time {
  grid-area: time;
  font: 700 17px/1.25 var(--font);
}

.route-tz {
  grid-area: tz;
  font: 450 12px/1.3 var(--font);
  color: var(--text-2);
}

.route-arrow {
  padding-left: 9px;
  color: var(--text-2);
}

.next-day {
  margin-left: 7px;
  padding: 2px 8px;
  font: 700 11px/1.3 var(--font);
  color: #fff;
  background: var(--sun-500);
  border-radius: var(--r-pill);
}

/* --- Detailansicht -------------------------------------------------------- */

.when {
  margin: 14px 0 2px;
  font: 650 15px/1.3 var(--font);
}

.details-list {
  display: grid;
  gap: 12px;
  margin-top: 16px;
}

.detail {
  display: grid;
  gap: 2px;
  overflow-wrap: anywhere;
}

.detail > span:first-child {
  font: 650 10.5px/1.3 var(--font);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-2);
}

.notes {
  margin-top: 4px;
  padding: 14px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  background: var(--surface-2);
  border-radius: var(--r-md);
  font-size: 14.5px;
}

/* --- Kosten --------------------------------------------------------------- */

.saldo {
  display: grid;
  gap: 4px;
  margin-bottom: 14px;
  padding: 20px;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-700), var(--brand-900) 70%);
  border-radius: var(--r-xl);
  box-shadow: var(--e2);
}

.saldo.minus {
  background: linear-gradient(135deg, var(--sun-600), #8f3a12 75%);
}

.saldo.plus {
  background: linear-gradient(135deg, var(--ok-500), #14513a 75%);
}

.saldo-label {
  font: 500 13px/1.3 var(--font);
  opacity: 0.9;
}

.saldo-zahl {
  font: 700 32px/1.1 var(--font);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.5px;
}

.saldo-zeile {
  margin-top: 2px;
  font: 500 13px/1.45 var(--font);
  opacity: 0.92;
}

.kategorien {
  display: grid;
  gap: 8px;
  margin-top: 14px;
}

.kat-zeile {
  display: grid;
  grid-template-columns: 108px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  font-size: 13px;
}

.kat-name {
  color: var(--text-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.kat-bar {
  height: 6px;
  background: var(--surface-2);
  border-radius: var(--r-pill);
  overflow: hidden;
}

.kat-bar > i {
  display: block;
  height: 100%;
  background: var(--accent);
  border-radius: var(--r-pill);
}

.kat-wert {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.ausgleich {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

.ausgleich strong {
  font-variant-numeric: tabular-nums;
}

.split-zeile {
  display: grid;
  /* Name, Zahlenfeld, Einheit (%, Währung, ×). */
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 10px;
  align-items: center;
}

.split-zeile label.check {
  margin: 8px 0;
}

.tile button,
button.tile {
  width: 100%;
  margin: 0;
  text-align: left;
  color: var(--text);
  box-shadow: var(--e1);
}

/* --- Knopf "+ Eintrag" ----------------------------------------------------
   Stand früher als schwebender Knopf unten rechts (position: fixed) und lag
   damit über dem Inhalt — beim Scrollen ständig über irgendeiner Karte. Jetzt
   steht er im Fluss über dem Zeitstrahl: verdeckt nichts, ist trotzdem dort,
   wo geplant wird.
   -------------------------------------------------------------------------- */

.add-btn {
  width: 100%;
  min-height: 46px;
  margin: 0 0 12px;
  padding: 0 18px;
  font: 700 14px/1 var(--font);
  color: #fff;
  background: var(--sun-500);
  border-radius: var(--r-pill);
  box-shadow: var(--e2);
}

/* Der Unterwegs-Knopf steht während der Reise gleich unter der Kopfkarte und
   braucht dort etwas Abstand nach unten zu den vier Kacheln. */
.unterwegs-jetzt {
  margin-bottom: 16px;
}

/* --- Offline-Hinweis ------------------------------------------------------ */

.offline-bar {
  /* Nicht mehr klebend: Sonst läge sie über der schwebenden Kopfzeile und
     verdeckte Zurück und Home. Sie steht oben auf der Seite, das reicht. */
  position: relative;
  z-index: 1;
  margin: -12px -20px 12px;
  padding: 9px 20px;
  font: 650 12.5px/1.3 var(--font);
  text-align: center;
  color: #fff;
  background: var(--ink-700);
}

@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* Ausgewählter Filter-Chip */
.chip-aktiv {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

/* --- Unterwegs: alles Wichtige groß, alles andere weg ---------------------- */

.jetzt {
  display: grid;
  gap: 5px;
  margin-bottom: 14px;
  padding: 22px 20px;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-600), var(--brand-900) 75%);
  border-radius: var(--r-xl);
  box-shadow: var(--e2);
}

.jetzt-label {
  font: 700 11px/1.3 var(--font);
  letter-spacing: 0.8px;
  text-transform: uppercase;
  opacity: 0.75;
}

.jetzt-titel {
  font: 700 26px/1.15 var(--font);
  letter-spacing: -0.4px;
  overflow-wrap: anywhere;
}

.jetzt-zeile {
  font: 500 15px/1.45 var(--font);
  font-variant-numeric: tabular-nums;
  opacity: 0.93;
}

.jetzt-knopfreihe {
  display: flex;
  gap: 10px;
  margin-top: 16px;
}

.jetzt-knopf {
  flex: 1;
  display: grid;
  place-items: center;
  min-height: 52px;
  padding: 14px;
  font: 700 15px/1.2 var(--font);
  color: var(--brand-900);
  text-decoration: none;
  background: #fff;
  border-radius: var(--r-sm);
}

.jetzt-buchung {
  display: grid;
  gap: 3px;
  margin-top: 14px;
  padding: 12px 14px;
  background: rgb(255 255 255 / 0.14);
  border-radius: var(--r-sm);
}

/* --- Packliste ------------------------------------------------------------ */

.pack-zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 36px;
  gap: 8px;
  align-items: center;
  padding: 7px 0;
  border-bottom: 1px solid var(--line);
}

.pack-zeile:last-child {
  border-bottom: 0;
}

.pack-zeile .icon-btn {
  width: 32px;
  height: 32px;
  min-height: 32px;
  font-size: 14px;
}

.pack-erledigt {
  color: var(--text-2);
  text-decoration: line-through;
}

.tiles.vier {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

.tiles.vier .tile {
  padding: 10px 8px;
  text-align: center;
}

.tiles.vier .tile-label {
  font-size: 9.5px;
  letter-spacing: 0.3px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.tiles.vier .tile-value {
  font-size: 17px;
  margin-top: 2px;
}

/* --- Abstimmen im Ideenpool ----------------------------------------------- */

.vote {
  align-self: center;
  display: grid;
  gap: 1px;
  place-items: center;
  width: 54px;
  min-height: 54px;
  margin: 0;
  padding: 6px;
  font-size: 18px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: none;
}

.vote-aktiv {
  color: var(--accent-ink);
  background: var(--sun-500);
  border-color: transparent;
}

.vote-zahl {
  font: 700 12px/1 var(--font);
}

/* --- Tagesansicht --------------------------------------------------------- */

.day-link {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 0;
  cursor: pointer;
  min-height: 0;
  box-shadow: none;
  text-align: left;
  color: var(--text-2);
}

.day-pfeil {
  font-size: 15px;
  opacity: 0.6;
}

.tagesleiste {
  display: flex;
  gap: 7px;
  overflow-x: auto;
  padding: 2px 0 8px;
  margin-bottom: 12px;
  scrollbar-width: none;
}

.tagesleiste::-webkit-scrollbar {
  display: none;
}

.tagchip {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  gap: 1px;
  width: 48px;
  min-height: 56px;
  margin: 0;
  padding: 8px 4px;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: none;
}

.tagchip-aktiv {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}

.tagchip-wt {
  font: 600 10px/1 var(--font);
  text-transform: uppercase;
  opacity: 0.7;
}

.tagchip-tag {
  font: 700 17px/1 var(--font);
  font-variant-numeric: tabular-nums;
}

.tag-kopf {
  display: grid;
  gap: 2px;
  margin-bottom: 14px;
  padding: 16px 18px;
  color: #fff;
  background: linear-gradient(135deg, var(--brand-600), var(--brand-900) 75%);
  border-radius: var(--r-lg);
  box-shadow: var(--e2);
}

.tag-ort {
  font: 650 14px/1.3 var(--font);
  opacity: 0.9;
}

.wetter-temp {
  font: 700 28px/1.15 var(--font);
  font-variant-numeric: tabular-nums;
}

.wetter-art {
  font: 500 12.5px/1.4 var(--font);
  opacity: 0.88;
}

.luecke {
  display: grid;
  gap: 2px;
  margin-top: 12px;
  padding: 16px 18px;
  background: var(--accent-soft);
  border: 1px dashed var(--accent);
  border-radius: var(--r-lg);
}

/* Der Status ist antippbar — das darf man ihm auch ansehen. */
.badge-knopf {
  width: auto;
  min-height: 30px;
  margin: 0;
  padding: 5px 11px;
  cursor: pointer;
  box-shadow: none;
}

.badge-knopf::after {
  content: " ›";
  opacity: 0.55;
}

.badge-knopf:active {
  transform: scale(0.94);
}

/* --- Wer hat was ausgelegt ------------------------------------------------ */

.saldo-tabelle {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto auto;
  gap: 6px 12px;
  margin-top: 12px;
  font-size: 13.5px;
  align-items: baseline;
}

.saldo-tabelle .zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.saldo-tabelle .gut {
  color: var(--ok);
  font-weight: 700;
}

.saldo-tabelle .schlecht {
  color: var(--sun-600);
  font-weight: 700;
}

/* --- Karte ---------------------------------------------------------------- */

.karte-rahmen {
  position: relative;
  margin-bottom: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--e1);
  overflow: hidden;
  background: var(--surface-2);
}

.karte-buehne {
  position: relative;
  overflow: hidden;
  touch-action: none;      /* Wischen verschiebt die Karte, nicht die Seite */
  cursor: grab;
  user-select: none;
}

.karte-buehne:active {
  cursor: grabbing;
}

.karte-kacheln {
  position: absolute;
  inset: 0;
}

.kachel {
  position: absolute;
  width: 256px;
  height: 256px;
  pointer-events: none;
}

.karte-svg {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.karte-punkt {
  cursor: pointer;
  pointer-events: auto;
}

.karte-punkt:active circle {
  opacity: 0.75;
}

.karte-zahl {
  font: 700 12px var(--font);
  fill: #fff;
}

.karte-zahl-idee {
  font: 700 12px var(--font);
  fill: #10707a;
}

/* Zweifach gezeichnet: heller Rand unten, Text darüber — sonst verschwindet
   die Beschriftung auf bunten Kartenstellen. */
.karte-name-aussen {
  font: 700 11px var(--font);
  fill: #fff;
  stroke: #fff;
  stroke-width: 3.5;
  paint-order: stroke;
}

.karte-name-innen {
  font: 700 11px var(--font);
  fill: #0d1721;
}

.karte-art {
  font-size: 15px;
}

.karte-bedienung {
  position: absolute;
  top: 10px;
  right: 10px;
  display: grid;
  gap: 6px;
}

.karte-knopf {
  width: 38px;
  height: 38px;
  min-height: 38px;
  margin: 0;
  padding: 0;
  font: 700 20px/1 var(--font);
  color: var(--ink-900);
  background: #fff;
  border: 1px solid rgb(13 23 33 / 0.15);
  border-radius: var(--r-sm);
  box-shadow: var(--e2);
}

.karte-herkunft {
  position: absolute;
  right: 0;
  bottom: 0;
  padding: 3px 7px;
  font: 500 10px/1.3 var(--font);
  background: rgb(255 255 255 / 0.82);
  border-top-left-radius: var(--r-xs);
}

.karte-herkunft a {
  color: var(--ink-700);
  text-decoration: none;
}

.karte-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0 0 14px;
  padding: 0 4px;
  font: 500 12px/1.3 var(--font);
  color: var(--text-2);
}

.strecke {
  display: grid;
  grid-template-columns: 54px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}

.strecke:last-of-type {
  border-bottom: 0;
}

.strecke-nr {
  font: 700 11px var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.strecke-km {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  white-space: nowrap;
}


/* ---------------------------------------------------------------------------
   Vorschläge mit Vorschaubild

   Das Bild kommt von unserem Server (siehe views/suggestions.js). Ohne Bild
   fällt die Kachel auf eine Spalte zurück — kein leerer Platzhalter, der
   aussieht, als würde noch etwas nachgeladen.
   --------------------------------------------------------------------------- */
/*
 * Jeder Vorschlag hat links ein Feld fester Größe: entweder das Bild oder,
 * wenn Wikipedia keines hat, ein Platzhalter mit dem Symbol der Kategorie.
 * Immer dieselbe Aufteilung — sonst springt die Liste bei jedem Eintrag ohne
 * Bild um eine Spalte.
 */
.vorschlag {
  grid-template-columns: 96px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}

.vorschlag-ohne-bild {
  display: grid;
  place-items: center;
  font-size: 30px;
  color: var(--text-2);
  background: var(--surface-2);
}

.vorschlag-bild {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 10px;
  background: var(--flaeche-2, #eee);
  display: block;
}

@media (max-width: 380px) {
  .vorschlag {
    grid-template-columns: 72px minmax(0, 1fr);
  }
  .vorschlag-bild {
    width: 72px;
    height: 72px;
  }
}


/* ---------------------------------------------------------------------------
   Zahlen unter dem Planungsbalken

   Der farbige Punkt ist eine CSS-Form, kein Schriftzeichen. Vorher stand dort
   ein ■ (U+25A0) — das fehlt in der iOS-Systemschrift und wurde als leeres
   Kästchen gezeichnet. Farbe gehört nicht in ein Zeichen.
   --------------------------------------------------------------------------- */
.legende {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin-top: 10px;
  font: 500 12px/1.4 var(--font);
  color: rgba(255, 255, 255, 0.82);
}

.legende-teil {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  white-space: nowrap;
}

.legende-teil b {
  font-weight: 700;
  color: #fff;
}

.legende-punkt {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
}


/* Die Ideen sind keine offene Aufgabe und stehen deshalb etwas abgesetzt. */
.legende-ideen {
  color: rgba(255, 255, 255, 0.6);
}

/* ---------------------------------------------------------------------------
   Vier Kacheln in EINER Zeile — auch auf 360 px

   Sie standen untereinander, weil hier
   `repeat(4, minmax(0, minmax(0, 1fr)))` stand. Verschachteltes minmax ist
   ungültig, und ein Browser verwirft eine ungültige Deklaration komplett — samt
   der ganzen Spalteneinteilung. Entstanden beim pauschalen Ersetzen von 1fr.
   --------------------------------------------------------------------------- */
@media (max-width: 400px) {
  .tiles.vier {
    gap: 6px;
  }
  .tiles.vier .tile {
    padding: 9px 5px;
  }
  .tiles.vier .tile-label {
    font-size: 9px;
    letter-spacing: 0;
  }
  .tiles.vier .tile-value {
    font-size: 15px;
  }
}

/* Lange Werte wie "1.234 €" dürfen die Kachel nicht sprengen. */
.tiles.vier .tile-value {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------------------------------------------------------------------------
   Bilder im Ideenpool

   Die Klasse wurde im JS gesetzt, hatte hier aber keine einzige Regel — das
   Bild kam damit in Originalbreite (480 px) in eine Karte, die auf dem Handy
   keine 340 px hat. Gleiche Aufteilung wie bei den Vorschlägen.
   --------------------------------------------------------------------------- */
/*
 * Ideen-Karten haben IMMER einen Stern rechts — die Spalte dafür muss
 * reserviert sein.
 *
 * Der Fehler davor: .item bringt drei Spalten mit (52px | 1fr | auto), eine
 * Idee ohne Bild rendert aber nur zwei Kinder. Der Text landete damit in der
 * 52-px-Spalte, lief über deren Rand hinaus und verschwand unter dem
 * Sternknopf, der in der mittleren Spalte saß. Auf dem Handy waren dadurch
 * mitten im Satz Wörter verdeckt.
 *
 * Jetzt legt jede Variante ihre Spalten selbst fest, passend zur Zahl ihrer
 * Kinder: Text und Stern — mit Bild eben drei.
 */
.idee {
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
}

.idee.mit-bild {
  grid-template-columns: 96px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
}

.idee-bild {
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: 10px;
  background: var(--surface-2);
  display: block;
}

@media (max-width: 380px) {
  /* Bild, Text UND Stern nebeneinander wären auf 360 px zu eng — der Stern
     rutscht deshalb unter den Text und bleibt trotzdem gut zu treffen. */
  .idee.mit-bild {
    grid-template-columns: 72px minmax(0, 1fr);
  }
  .idee.mit-bild .vote {
    grid-column: 1 / -1;
    justify-self: end;
  }
  .idee-bild {
    width: 72px;
    height: 72px;
  }
}

/* Der Vorname unter dem Kürzel — ohne Regel lief er in die nächste Zeile. */
.avatar-name {
  max-width: 84px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Online-Anzeige im Unterwegs-Modus — Punkt als Form, nicht als Zeichen. */
.netz-stand {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.netz-punkt {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  background: var(--text-3, #8a94a0);
}

.netz-punkt.netz-an {
  background: var(--ok-500);
}

/* ---------------------------------------------------------------------------
   Anhänge an einem Eintrag
   --------------------------------------------------------------------------- */
.anhang {
  grid-template-columns: 28px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
}

.anhang-symbol {
  font-size: 20px;
  line-height: 1;
  text-align: center;
}

.anhang-aktionen {
  display: flex;
  gap: 6px;
  align-items: center;
}

.anhang-hochladen {
  display: grid;
  gap: 8px;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.anhang-hochladen input[type='file'] {
  font: 400 13px/1.4 var(--font);
  color: var(--text-2);
}

/* Kleiner Knopf für Aktionen in einer Zeile — Antippfläche bleibt 40 px. */
.mini {
  width: auto;
  min-height: 40px;
  margin: 0;
  padding: 0 12px;
  font: 600 13px/1 var(--font);
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: none;
}

.mini.gefahr {
  min-width: 40px;
  padding: 0 10px;
  color: var(--err-600);
}

.sekundaer {
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--line);
  box-shadow: none;
}

@media (max-width: 380px) {
  .anhang {
    grid-template-columns: 24px minmax(0, 1fr);
    row-gap: 8px;
  }
  .anhang-aktionen {
    grid-column: 1 / -1;
    justify-content: flex-end;
  }
}

/* ---------------------------------------------------------------------------
   Galerie: Fotos und Videos
   --------------------------------------------------------------------------- */
.medien-gitter {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 6px;
  margin-top: 12px;
}

.medien-kachel {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  min-height: 0;
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: none;
}

.medien-kachel img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.medien-ersatz {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  font-size: 24px;
}

/* Marken auf der Kachel: Video und Standort. Auf dunklem Grund, damit sie auf
   jedem Bild lesbar bleiben. */
.medien-marke,
.medien-ort {
  position: absolute;
  bottom: 4px;
  font-size: 11px;
  line-height: 1;
  padding: 3px 4px;
  border-radius: 5px;
  background: rgb(0 0 0 / 0.55);
}

.medien-marke {
  left: 4px;
}

.medien-ort {
  right: 4px;
}

/* --- Bild groß ansehen ---------------------------------------------------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px;
  padding-top: calc(14px + env(safe-area-inset-top));
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
  background: rgb(6 20 26 / 0.94);
}

.lightbox-kopf,
.lightbox-fuss {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex: none;
}

.lightbox-titel {
  font: 600 14px/1.3 var(--font);
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lightbox-fuss .hint,
.lightbox-fuss a {
  color: rgb(255 255 255 / 0.75);
}

/*
 * FLEX, nicht Grid — und das ist kein Geschmack, sondern der Unterschied
 * zwischen "Bild passt in den Kasten" und "Bild ragt oben und unten hinaus".
 *
 * Alex am 15.09.2026: "Ich wollte am Laptop gerade ein Bild anzeigen lassen."
 * Es erschien nur ein Streifen aus der Bildmitte. Nachgemessen: Kasten
 * 1252 × 673, Bild 738 × 1600.
 *
 * Ursache: Als Grid richtete sich die Zeile nach ihrem Inhalt. Eine
 * Prozentangabe wie `max-height: 100%` hat dann keinen Bezugswert — der
 * Browser verwirft sie, das Bild wird in voller Höhe gezeichnet und quillt
 * über. Im Flex-Container dagegen ist die Höhe durch `flex: 1` im Kasten mit
 * fester Höhe eindeutig, und die Prozentangabe greift.
 *
 * `overflow: hidden` ist der Gürtel zum Hosenträger: Sollte je wieder etwas
 * zu groß werden, bleibt es wenigstens im Kasten.
 */
.lightbox-bild {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.lightbox-bild img,
.lightbox-bild video {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  border-radius: 8px;
}

/* --- Aufnahmen mit Standort ----------------------------------------------- */

.medien-orte {
  display: grid;
  gap: 8px;
  margin-top: 12px;
}

.medien-ort-zeile {
  display: grid;
  grid-template-columns: 56px minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  width: 100%;
  min-height: 56px;
  margin: 0;
  padding: 6px;
  text-align: left;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: none;
}

.medien-ort-zeile img {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 8px;
  display: block;
}

.medien-ort-text {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.medien-ort-text strong {
  font: 600 14px/1.3 var(--font);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Speicher wird knapp — die Karte bekommt einen warnenden Rand. */
.card.warnung {
  border-color: var(--warn-500);
}

/* Ein Knopf über die volle Breite, direkt unter den Kacheln. */
.sekundaer.breit {
  width: 100%;
  margin: 0 0 16px;
}

/* ---------------------------------------------------------------------------
   Zum Ausdrucken

   Der Notfall: Handy leer, kein Netz, und man steht mit dem Koffer vor einem
   Bahnhof in Busan. Deshalb Buchungsnummern und Telefonnummern statt Symbolen,
   und auf Papier keine Farbflächen — die kosten Tinte und bringen nichts.
   --------------------------------------------------------------------------- */
.druck-inhalt {
  padding: 4px 2px 30px;
}

.druck-inhalt h1 {
  margin: 0 0 4px;
  font-size: 22px;
}

.druck-kopf {
  margin: 0 0 18px;
  color: var(--text-2);
  font-size: 13px;
}

.druck-tag {
  margin-bottom: 18px;
  break-inside: auto;
}

.druck-tag h2 {
  margin: 0 0 8px;
  padding-bottom: 4px;
  font-size: 15px;
  border-bottom: 1px solid var(--line);
}

.druck-eintrag {
  margin-bottom: 12px;
  padding-left: 10px;
  border-left: 2px solid var(--line);
  /* Ein Eintrag soll nicht mitten in der Buchungsnummer umbrechen. */
  break-inside: avoid;
}

.druck-titel {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
}

.druck-art {
  font-size: 11px;
  color: var(--text-2);
  text-transform: uppercase;
  letter-spacing: 0.4px;
}

.druck-zeit {
  margin: 2px 0 4px;
  font-size: 13px;
}

.druck-zeile {
  display: grid;
  grid-template-columns: 78px minmax(0, 1fr);
  gap: 8px;
  font-size: 13px;
  line-height: 1.5;
}

.druck-label {
  color: var(--text-2);
}

.druck-notiz {
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-2);
}

.druck-block {
  margin-top: 20px;
}

.druck-fuss {
  margin-top: 24px;
  font-size: 11px;
  color: var(--text-2);
}

@media print {
  /* Alles weg, was nur auf dem Bildschirm Sinn ergibt. */
  .head,
  .druck-hinweis,
  .offline-bar,
  .add-btn {
    display: none !important;
  }

  body {
    background: #fff;
    color: #000;
  }

  .druck-seite,
  .druck-inhalt {
    max-width: none;
    margin: 0;
    padding: 0;
  }

  .druck-eintrag {
    border-left: 1px solid #999;
  }

  .druck-tag h2 {
    border-bottom: 1px solid #999;
  }

  .druck-art,
  .druck-label,
  .druck-notiz,
  .druck-kopf,
  .druck-fuss {
    color: #444;
  }

  @page {
    margin: 14mm;
  }
}

/* Einheit hinter dem Zahlenfeld bei der Aufteilung: %, Währung oder ×. */
.split-einheit {
  min-width: 28px;
  font: 600 13px/1 var(--font);
  color: var(--text-2);
}

/* ---------------------------------------------------------------------------
   Kommentare an einem Eintrag
   --------------------------------------------------------------------------- */
.kommentare {
  display: grid;
  gap: 10px;
  margin: 10px 0 4px;
}

.kommentar {
  padding: 10px 12px;
  background: var(--surface-2);
  border-radius: var(--r-md);
}

.kommentar-kopf {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font: 600 13px/1.3 var(--font);
}

.kommentar-kopf .hint {
  margin: 0;
  font-weight: 400;
}

/* Der Löschknopf ganz rechts, ohne die Zeile zu sprengen. */
.kommentar-kopf .mini {
  margin-left: auto;
  min-height: 32px;
  padding: 0 8px;
}

.kommentar-text {
  font: 400 14px/1.5 var(--font);
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.kommentar-neu {
  display: grid;
  gap: 8px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

/* Ein Hinweis, der wirklich stört — rot und etwas kräftiger als ein .hint.
   Wurde im JS schon gesetzt, hatte hier aber keine Regel: Der Warntext kam in
   normaler Textfarbe und sah aus wie eine Nebenbemerkung. */
.fehler {
  font: 500 13px/1.5 var(--font);
  color: var(--err-600);
}

/* ---------------------------------------------------------------------------
   Reise herunterladen

   Jede Möglichkeit ist ein normaler Link: Der Browser übernimmt Fortschritt,
   Pause und Fortsetzen selbst — das ist bei einem mehrere Gigabyte großen
   Archiv besser als alles, was wir nachbauen könnten.
   --------------------------------------------------------------------------- */
.download-karte {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 4px 12px;
  align-items: center;
  margin: 10px 0 0;
  padding: 12px 14px;
  color: var(--text);
  text-decoration: none;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.download-titel {
  font: 600 15px/1.3 var(--font);
}

.download-karte .hint {
  grid-column: 1;
  margin: 0;
}

.download-groesse {
  grid-column: 2;
  grid-row: 1 / span 2;
  font: 600 13px/1 var(--font);
  color: var(--text-2);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   Merkmale eines Vorschlags: Bekanntheit, Eintritt, Öffnungszeiten

   Nur das, was OpenStreetMap wirklich weiß. Wo nichts steht, steht auch kein
   Merkmal — geraten wird nicht.
   --------------------------------------------------------------------------- */
.merkmale {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 5px 0 2px;
}

.merkmal {
  font: 600 11px/1 var(--font);
  padding: 4px 7px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  white-space: nowrap;
}

.merkmal-gut {
  color: var(--ok-600);
  border-color: var(--ok-500);
}

/* Bekanntheit — abgestuft, nicht als erfundene Sternebewertung. */
.bekannt-hoch {
  color: var(--sun-600);
  border-color: var(--sun-500);
}

.bekannt-mittel {
  color: var(--brand-600);
  border-color: var(--brand-500);
}

.bekannt-tipp {
  color: var(--berry-500);
  border-color: var(--berry-500);
}

/* --- Ausklappbare Zusatzangaben -------------------------------------------- */

.mehr {
  margin-top: 6px;
  font: 400 13px/1.5 var(--font);
}

.mehr summary {
  cursor: pointer;
  color: var(--text-2);
  font-weight: 600;
  font-size: 12px;
  /* Genug Fläche zum Antippen, ohne die Karte aufzublähen. */
  padding: 6px 0;
}

.mehr-zeile {
  display: grid;
  grid-template-columns: 130px minmax(0, 1fr);
  gap: 8px;
  padding: 2px 0;
}

.mehr-label {
  color: var(--text-2);
}

@media (max-width: 380px) {
  .mehr-zeile {
    grid-template-columns: minmax(0, 1fr);
    gap: 0;
    padding: 4px 0;
  }
}

/* Tagebuch im Ausdruck — vor dem Programm, denn auf Papier liest man den Tag. */
.druck-tagebuch {
  margin: 0 0 10px;
  padding: 8px 10px;
  font-size: 13px;
  line-height: 1.6;
  white-space: pre-wrap;
  background: var(--surface-2);
  border-radius: var(--r-md);
}

@media print {
  .druck-tagebuch {
    background: none;
    padding: 0;
    border-left: 2px solid #999;
    padding-left: 10px;
  }
}

/* --- Filter über der Vorschlagsliste --------------------------------------- */
.filter {
  display: grid;
  gap: 8px;
  margin-bottom: 12px;
}

.zeitwahl {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 8px;
  margin-top: 10px;
}

.zeitwahl input {
  margin: 0;
}

/* Trennt "Öffnungszeiten bekannt" von "unbekannt" — unbekannt ist nicht
   geschlossen, das muss man sehen können. */
.gruppe-titel {
  display: grid;
  gap: 2px;
  margin: 18px 0 4px;
  padding-top: 14px;
  font: 600 13px/1.3 var(--font);
  color: var(--text-2);
  border-top: 1px solid var(--line);
}

.gruppe-titel .hint {
  margin: 0;
  font-weight: 400;
}

.merkmal-zu {
  color: var(--err-600);
  border-color: var(--err-600);
}


/* ---------------------------------------------------------------------------
   Der Zeitstrahl als Schiene

   ===========================================================================
    Die Geometrie — der Punkt, an dem es vorher schiefging
   ===========================================================================

   Die Linie liegt am Container (nicht an den Kacheln, sonst gäbe es in den
   Abständen keine). Die Symbole liegen dagegen IN den Kacheln — und die
   Kacheln stehen unterschiedlich tief: Transport direkt im Zeitstrahl, eine
   Unterkunft innerhalb eines Aufenthalts.

   Solange die Symbole im Textfluss der Kachel hingen, erbte jede Ebene deren
   Einzug. Gemessen am 360-px-Handy: Linie bei 29 px, Knoten bei 42 px (außen)
   und 60 px (innen). Kein einziger saß auf der Linie. Sichtbar blieb der
   farbige Ring daneben — die „Schnörkel“ am Kartenrand.

   Jetzt gilt eine einzige Achse für alle:

       │←── knoten ──→│←luft→│
       ┌──────────────┐      ┌────────────────────────────┐
       │   ( ✈️ )      │      │  Hinflug nach Seoul        │
       │    18:00     │      │  Wien 18:00 → Seoul 12:30  │
       └──────────────┘      └────────────────────────────┘
              ↑                    ↑
        Mitte = knoten/2      Kachelkante = knoten + luft
        (= die Linie)

   Der Knoten sitzt absolut und rechnet sich aus der Kachelkante auf die Linie
   zurück:  links = −(knoten + luft + kante).  Der Einzug der Umgebung fällt
   damit heraus — deshalb sitzt ein Knoten in einem Aufenthalt auf derselben
   Achse wie einer davor. Bedingung: Aufenthalte rücken ihre Kinder NICHT ein
   (.station-body ohne linke Polsterung), sonst stimmt die Rechnung wieder
   nicht.

   `--kante` ist die farbige Statuskante der Kachel; sie zählt mit, weil ein
   absolut gesetztes Kind an der Polsterkante misst, also innerhalb des Rahmens.
   --------------------------------------------------------------------------- */
.timeline {
  /* 34 statt 38: Seit jede Art ihr eigenes Zeichen hat, muss der Kreis nicht
     mehr durch Größe auffallen. Einrückung und Abzweig rechnen mit dieser
     Variablen und passen sich von selbst an. */
  --knoten: 34px;
  --luft: 5px;
  position: relative;
  padding-left: calc(var(--knoten) + var(--luft));
}

.timeline::before {
  content: '';
  position: absolute;
  left: calc(var(--knoten) / 2 - 1px);
  /* Oben und unten auslaufen lassen statt abrupt abzuschneiden. */
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(
    to bottom,
    transparent 0,
    var(--ink-200) 14px,
    var(--ink-200) calc(100% - 14px),
    transparent 100%
  );
}

/* Ein einzelner Eintrag ohne Nachbarn braucht keine Schiene. */
.timeline:has(> .item:only-child)::before,
.timeline:has(> .hint)::before {
  display: none;
}

.timeline:has(> .hint) {
  padding-left: 0;
}

.knoten {
  position: absolute;
  /*
   * Der Knoten rückt MIT der Kachel ein.
   *
   * Zuerst hatte ich die Einrückung hier herausgerechnet, damit alle Knoten
   * auf einer Achse bleiben. Das war technisch sauber und sah falsch aus: Der
   * Knoten stand weit links, die Kachel weit rechts, und dazwischen klaffte
   * nichts. Eingerückt gehört beides — dann liest es sich als Abzweig vom
   * Hauptstrang, so wie ein Tagesablauf vom Reiseverlauf abzweigt.
   *
   * Die Verbindung zur Hauptlinie zeichnet .knoten::before (siehe unten).
   */
  left: calc(-1 * (var(--knoten) + var(--luft) + var(--kante, 0px)));
  top: 6px;
  display: grid;
  justify-items: center;
  gap: 2px;
  width: var(--knoten);
  /* Nichts abschneiden: „09:30“ ist breiter als der Kreis und darf über ihn
     hinausragen — verdeckt wird dabei nichts, die Zeile steht darunter. */
  overflow: visible;
}

.knoten-symbol {
  display: grid;
  place-items: center;
  width: var(--knoten);
  height: var(--knoten);
  /*
   * Kleiner und flacher als früher (war 21 px mit Schlagschatten).
   *
   * Seit jede Art ihr eigenes Zeichen hat, trägt die Spalte Information und
   * muss nicht mehr durch Größe auffallen. Bei neun Einträgen untereinander
   * war die alte Fassung eine Perlenkette, die mit dem Text um Aufmerksamkeit
   * rang.
   *
   * Der farbige Ring BLEIBT: Er sagt, was noch offen ist, und ist bei
   * vergangenen Einträgen die einzige Auskunft — dort blendet die App das
   * Statusabzeichen aus (siehe lib/zeitstatus.js).
   */
  font-size: 18px;
  line-height: 1;
  /* Eigener Grund, damit die Linie dahinter sauber unterbrochen wirkt. */
  background: var(--surface);
  border: 2px solid var(--ink-200);
  border-radius: 50%;
}

.knoten-zeit {
  padding: 0 3px;
  font: 650 10.5px/1.2 var(--font);
  color: var(--text-2);
  white-space: nowrap;
  /* Deckt die Linie hinter der Zahl ab. Ohne das läuft der Strang mitten durch
     „18:00“ — in Variante B, wo er kräftig gefärbt ist, besonders störend.
     Der Grund der Seite passt hier immer: Die Knotenspalte liegt links neben
     den Kacheln, auch innerhalb eines Aufenthalts. */
  background: var(--bg);
  border-radius: 4px;
}

/*
 * Der Status färbt den Knotenring mit — so sieht man schon an der Symbolspalte,
 * was noch offen ist, ohne das Etikett zu lesen. Farbe ist dabei nie die
 * einzige Auskunft: Der Text im Abzeichen sagt dasselbe.
 */
.timeline .item {
  --kante: 3px;
  position: relative;
  /* Ohne Symbolspalte: Der Knoten steht außerhalb, der Text bekommt den Platz.
     Die Textspalte beginnt dadurch weiter links als vorher — trotz breiterem
     Rand. */
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  padding: 10px 12px;
  min-height: 60px;
}

.timeline .item.status-to_book .knoten-symbol {
  border-color: var(--sun-500);
}

.timeline .item.status-booked .knoten-symbol {
  border-color: var(--brand-500);
}

.timeline .item.status-paid .knoten-symbol {
  border-color: var(--ok-500);
}

.timeline .item.status-done .knoten-symbol {
  border-color: var(--text-2);
}

/* --- Aufenthalte im Strang ------------------------------------------------ */

/*
 * Ein Aufenthalt ist kein Kasten mehr, sondern ein Marker auf der Linie.
 *
 * Vorher war der Ort ein breiter dunkler Balken; drei davon zerhackten den
 * Plan in Blöcke, und der Strang lief außen daran vorbei. Jetzt trägt der Ort
 * nur seinen Knoten und seinen Namen — der Zusammenhang entsteht durch die
 * Linie selbst, nicht durch einen Rahmen drumherum.
 */
.timeline .station {
  /* Kein Zuschneiden: Die Knoten der Einträge ragen links aus dem Aufenthalt
     heraus, direkt auf die Linie. Mit overflow:hidden wären sie weg. */
  overflow: visible;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.timeline .station-head {
  --kante: 0px;
  position: relative;
  display: block;
  padding: 4px 0 2px;
  color: var(--text);
  background: none;
  border-radius: 0;
}

.timeline .station-name {
  font: 700 16px/1.2 var(--font);
  color: var(--accent);
}

.timeline .station-span {
  color: var(--text-2);
  opacity: 1;
}

.timeline .station-head .chip {
  color: var(--text-2);
  background: var(--surface-2);
  border-color: var(--line);
}

/* Der Ortsknoten ist gefüllt — er ist der stärkste Punkt auf der Linie und
   ersetzt den ganzen Balken von früher. */
.timeline .station-head .knoten-symbol {
  background: var(--accent);
  border-color: var(--accent);
}

.timeline .station-text {
  display: grid;
  gap: 3px;
}

/* KEINE linke Polsterung — sonst stünden die Knoten der Einträge darin nicht
   mehr auf derselben Achse wie die davor. */
.timeline .station-body {
  /*
   * Die Spalte MUSS hier stehen.
   *
   * Ohne sie bildet das Grid eine implizite Spalte, deren Breite sich nicht
   * am Kasten orientiert — ein `margin-left` schob die Kachel dann nur nach
   * rechts, ohne sie schmaler zu machen. Gemessen am 14.09.2026: Kachel von
   * 89 bis 400 px bei 390 px Bildschirm, also 10 px Überbreite und seitliches
   * Scrollen. Mit `minmax(0, 1fr)` ist die Spalte definiert, und der Rand
   * verkleinert die Kachel wie erwartet.
   */
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  padding: 8px 0 14px;
  background: transparent;
  border-left: 0;
}

.timeline .item.inner {
  box-shadow: var(--e1);
}

/* ---------------------------------------------------------------------------
   Was tagsüber passiert, steht eingerückt

   Ohne Einrückung stand alles auf einer Kante: Unterkunft, Tagesüberschrift
   und fünf Programmpunkte sahen gleich wichtig aus. Eingerückt liest man auf
   einen Blick, was zum Tag gehört und was den Rahmen bildet.

   Der Knoten bleibt dabei auf der Linie (siehe --einzug oben) und bekommt
   einen kurzen Strich zur Kachel — sonst schwebte er 20 px daneben und man
   sähe nicht mehr, wozu er gehört.
   --------------------------------------------------------------------------- */
/*
 * Programmpunkte UND Rundfahrten rücken ein.
 *
 * Alex am 14.09.2026: "Das Auto ist noch zu weit links." Der Mietwagen wird
 * seit der Rundfahrt-Regel im Aufenthalt gezeigt — trug aber die Klasse
 * `art-transport` und blieb deshalb auf der Hauptlinie, 30 px links von allem
 * anderen des Tages. In einen Aufenthalt kommen ohnehin nur Rundfahrten;
 * echte Verbindungen stehen als eigener Block außerhalb.
 *
 * Die Unterkunft bleibt bewusst außen vor: Sie gehört zum Aufenthalt selbst,
 * nicht zum Tagesprogramm, und sitzt deshalb auf der Hauptlinie.
 */
.timeline .station-body .art-activity,
.timeline .station-body .art-transport {
  --einzug: 30px;
  margin-left: var(--einzug);
  /*
   * Die Breite MUSS ausdrücklich stehen.
   *
   * Die Kachel ist ein <button> und dehnt sich auf die volle Spalte, ohne den
   * linken Rand abzuziehen — gemessen am 14.09.2026: Spalte 311 px, Kachel
   * 311 px, dazu 30 px Versatz, also Ende bei 400 px auf einem 390 px breiten
   * Schirm. Ergebnis war seitliches Scrollen auf jeder Seite mit Zeitstrahl.
   *
   * box-sizing ist global border-box, deshalb passt calc() hier direkt.
   */
  width: calc(100% - var(--einzug));
}

/*
 * Der Abzweig: ein Strich von der Hauptlinie zum eingerückten Knoten, und
 * einer vom Knoten zur Kachel. Ohne den ersten schwebte der Knoten neben dem
 * Strang, ohne den zweiten neben seiner Kachel.
 */
.timeline .station-body .art-activity .knoten::before,
.timeline .station-body .art-transport .knoten::before {
  content: '';
  position: absolute;
  right: 100%;
  top: calc(var(--knoten) / 2 - 1px);
  width: calc(var(--einzug) - var(--knoten) / 2);
  height: 2px;
  background: var(--ink-200);
}

.timeline .station-body .art-activity .knoten::after,
.timeline .station-body .art-transport .knoten::after {
  content: '';
  position: absolute;
  left: 100%;
  top: calc(var(--knoten) / 2 - 1px);
  width: calc(var(--luft) + var(--kante, 0px));
  height: 2px;
  background: var(--ink-200);
}

/* Ausserhalb eines Aufenthalts wird nichts eingerückt: Eine Unterkunft und
   eine Verbindung bilden den Rahmen des Tages und stehen auf der äusseren
   Kante.

   ACHTUNG: `.art-transport` steht hier nur für Transporte AUSSERHALB eines
   Aufenthalts. Rundfahrten im Aufenthalt (Mietwagen) rücken sehr wohl ein —
   die Regel weiter oben ist mit drei Klassen spezifischer und gewinnt. Wer
   hier aufräumt, prüft vorher test/test-art.js. */
.timeline .art-lodging,
.timeline .art-transport,
.timeline .art-station {
  --einzug: 0px;
}

/* ---------------------------------------------------------------------------
   Die Tagesüberschrift trägt den Tag

   Sie stand klein, grau und in Versalien auf Kachelhöhe — zwischen zwölf
   Kacheln übersieht man das. Dabei ist sie der einzige Anker im Tagesablauf:
   Wer nach "war das am Samstag oder Sonntag?" sucht, sucht genau sie.

   Jetzt größer, dunkler, mit Luft davor und einer Trennlinie darüber. Und
   weiter links als die Kacheln — sie gehört nicht in deren Spalte, sie
   ordnet sie.

   Links bleibt sie dabei knapp NEBEN der Linie stehen, nicht darauf: Ihr
   Grund ist deckend (beim Scrollen klebt sie oben), und über der Linie würde
   sie den Strang zerschneiden.
   --------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------
   Die Tagesüberschrift als Band auf der Linie
   ---------------------------------------------------------------------------
   Alex am 14.09.2026, mit rotem Stift im Screenshot: Er hat die Linie um die
   Tagesüberschriften herumgeführt und sie eingekringelt — "dass die Tage
   markanter sind".

   Vorher stand der Tag als Text NEBEN der Schiene, und die Linie lief
   ungerührt daran vorbei. Ein neuer Tag ist aber ein Einschnitt, kein
   Zwischentitel. Jetzt reicht das Band über die ganze Breite, deckt die Linie
   ab und unterbricht sie damit sichtbar — der Strang läuft hinein und kommt
   darunter wieder heraus.
   --------------------------------------------------------------------------- */
.timeline .day {
  /* Bis ganz nach links, über die Schiene hinweg: Die Kachelkante liegt bei
     (knoten + luft), so weit muss das Band zurück. */
  margin-left: calc(-1 * (var(--knoten) + var(--luft)));
  margin-right: 0;
  /* Die Breite ausdrücklich, sonst reicht das Band nicht bis zum rechten
     Rand: Die Überschrift ist ein <button> und dehnt sich auf die Spalte,
     der negative Rand verschiebt sie dann nur. Gemessen: 20..331 statt
     20..370. Dieselbe Falle wie bei den eingerückten Kacheln. */
  width: calc(100% + var(--knoten) + var(--luft));
  margin-top: 20px;
  padding: 10px 12px 10px calc(var(--knoten) + var(--luft));
  /* Deckender Grund — er ist es, der die Linie unterbricht. */
  background: var(--surface-2);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  font: 800 14px/1.3 var(--font);
  letter-spacing: 0.8px;
  color: var(--text);
  position: relative;
  /* Nicht mitverschieben: .day klebt mit top: var(--kopf) unter der
     Kopfzeile, und bei position: relative rückt DAS die Leiste um 56 px nach
     unten — über Wegzeile und nächste Kachel, mit leerem Platz darüber.
     So am 24.09.2026 auf Alex' Handy. */
  top: 0;
  z-index: 1;
}

/* Innerhalb eines Aufenthalts gilt dasselbe — gerade DORT liegen die meisten
   Tage, und genau die hat Alex markiert. Der Grund muss deckend bleiben,
   sonst läuft die Linie wieder mitten durch den Text. */
.timeline .day.inner {
  background: var(--surface-2);
}

/* Der erste Tag eines Aufenthalts braucht keine Trennlinie: Darüber steht der
   Ort, der trennt schon. */
.timeline .station-body > .day:first-child {
  margin-top: 6px;
  border-top: 0;
}

.timeline .day-pfeil {
  color: var(--ink-300);
}

@media (max-width: 360px) {
  /* Enger, aber die Kacheln bleiben über 44 px hoch und damit antippbar. */
  .timeline {
    --knoten: 31px;
    --luft: 4px;
  }
  .knoten-symbol {
    font-size: 16px;
  }
  .timeline .item {
    gap: 8px;
    padding: 10px;
  }
}

/* Auf Papier keine Schiene und keine Kreise — das kostet nur Tinte. Die
   Symbole bleiben, sie helfen beim Überfliegen. */
@media print {
  .timeline::before {
    display: none;
  }
  .knoten-symbol {
    background: none;
    border: none;
    box-shadow: none;
  }
}

/* ---------------------------------------------------------------------------
   Ausgabenliste: wer, wofür, wie viel

   Drei Spalten: Kürzel des Zahlers, Text, Betrag. Das Kürzel steht vorn, weil
   man beim Scrollen zuerst wissen will, wer ausgelegt hat.
   --------------------------------------------------------------------------- */
.ausgabe {
  grid-template-columns: 38px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
}

.ausgabe-zahler {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  font: 700 12px/1 var(--font);
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 50%;
}

.ausgabe-rechts {
  display: grid;
  justify-items: end;
  gap: 2px;
  text-align: right;
}

.ausgabe-betrag {
  font: 700 15px/1.2 var(--font);
  white-space: nowrap;
}

/* Was tatsächlich gezahlt wurde — beim Nachrechnen die wichtigere Zahl. */
.ausgabe-original {
  font: 500 11px/1.2 var(--font);
  color: var(--text-2);
  white-space: nowrap;
}

.ausgabe-beleg {
  font-size: 13px;
  line-height: 1;
}

/* Für wen geteilt wurde. Wenn NICHT alle dabei sind, fällt es auf — genau
   daran erkennt man, dass der Hinflug nur zwei betrifft. */
.geteilt {
  font: 500 12px/1.4 var(--font);
  color: var(--text-2);
  overflow-wrap: anywhere;
}

.geteilt-teil {
  font-weight: 600;
  color: var(--sun-600);
}

@media (max-width: 380px) {
  .ausgabe {
    grid-template-columns: 32px minmax(0, 1fr) auto;
    gap: 8px;
  }
  .ausgabe-zahler {
    width: 32px;
    height: 32px;
    font-size: 11px;
  }
  .ausgabe-betrag {
    font-size: 14px;
  }
}

/* ---------------------------------------------------------------------------
   Eingang: Belege, die noch nicht eingebucht sind
   --------------------------------------------------------------------------- */
.eingang-zeile {
  grid-template-columns: 30px minmax(0, 1fr) auto;
  gap: 10px;
  align-items: start;
}

.eingang-symbol {
  font-size: 19px;
  line-height: 1.2;
  text-align: center;
}

/* Verworfenes bleibt sichtbar, tritt aber zurück. */
.eingang-verworfen {
  opacity: 0.55;
}

/*
 * Die Prüfhinweise.
 *
 * Bewusst auffällig: Sie sind der Grund, warum aus einem Beleg nicht
 * automatisch ein Eintrag wird. Klein gedruckt würden sie überlesen — und
 * genau dann bucht jemand eine falsche Uhrzeit ein.
 */
.pruefen {
  display: grid;
  gap: 4px;
  margin-top: 12px;
  padding: 10px 12px;
  font: 400 13px/1.5 var(--font);
  color: var(--warn-600);
  background: var(--warn-100);
  border-radius: var(--r-md);
}

.pruefen strong {
  color: var(--warn-600);
}

.auszug {
  max-height: 300px;
  overflow: auto;
  padding: 10px;
  font: 400 11px/1.5 ui-monospace, monospace;
  white-space: pre-wrap;
  background: var(--surface-2);
  border-radius: var(--r-md);
}

/* ---------------------------------------------------------------------------
   "Dem Fahrer zeigen"

   Eine Seite, die man jemandem hinhält. Deshalb: große Schrift, hoher
   Kontrast, nichts, was ablenkt. Immer heller Grund mit dunkler Schrift —
   auch wenn das Gerät auf dunkel steht, denn im Auto liest man so besser.
   --------------------------------------------------------------------------- */
.taxi {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 24px;
  padding: 24px 20px;
  padding-top: calc(24px + env(safe-area-inset-top));
  padding-bottom: calc(24px + env(safe-area-inset-bottom));
  background: #fff;
  color: #000;
  overflow-y: auto;
}

.taxi-gross {
  text-align: center;
}

.taxi-name {
  font: 700 clamp(28px, 8vw, 46px) / 1.25 var(--font);
  overflow-wrap: anywhere;
}

.taxi-adresse {
  margin-top: 14px;
  font: 500 clamp(20px, 5.5vw, 32px) / 1.4 var(--font);
  overflow-wrap: anywhere;
}

/* Wenn die Landesschrift fehlt: sagen, statt zu erfinden. */
.taxi-hinweis {
  margin-top: 20px;
  font: 400 14px/1.5 var(--font);
  color: #8a6d1f;
  background: #fdf3d7;
  border-radius: 10px;
  padding: 10px 12px;
  text-align: left;
}

.taxi-klein {
  display: grid;
  gap: 6px;
  text-align: center;
  font: 400 15px/1.5 var(--font);
  color: #444;
}

.taxi-telefon {
  font-weight: 600;
  color: #0a58a6;
  text-decoration: none;
}

.taxi-koordinaten {
  font: 400 13px/1.4 ui-monospace, monospace;
  color: #666;
}

.taxi-zurueck {
  width: auto;
  align-self: center;
  min-height: 44px;
  margin: 0;
  padding: 0 22px;
  color: #000;
  background: #eee;
  border: 1px solid #ccc;
  box-shadow: none;
}

.taxi-fehler {
  font: 500 18px/1.5 var(--font);
  text-align: center;
}

/* ---------------------------------------------------------------------------
   Notfallblatt

   Gebaut für den Fall, dass etwas passiert ist: große Nummern, viel Kontrast,
   nichts Verspieltes. Und so, dass ein Ausdruck davon brauchbar ist — Papier
   im Gepäck braucht keinen Akku.
   --------------------------------------------------------------------------- */
/* Der Rahmen um das ganze Blatt — beim Drucken darf es die volle Breite
   nutzen, am Schirm bleibt es lesbar schmal. */
.notfall {
  padding-bottom: 24px;
}

.notfall-kopf h1 {
  margin: 0 0 4px;
  font-size: 26px;
}

.notfall-kopf p {
  margin: 0 0 16px;
  color: var(--text-2);
  font-size: 14px;
}

.notfall-block {
  margin-bottom: 20px;
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.notfall-block h2 {
  margin: 0 0 10px;
  font-size: 18px;
}

.notfall-block h3 {
  margin: 14px 0 6px;
  font-size: 16px;
}

.notfall-zeile {
  /* Flex mit Umbruch statt Raster: Ist der Wert lang (Adresse, Buchung),
     rutscht er in die nächste Zeile, statt über die Beschriftung zu laufen. */
  display: flex;
  flex-wrap: wrap;
  column-gap: 10px;
  row-gap: 2px;
  align-items: baseline;
  padding: 5px 0;
  font-size: 14px;
  border-bottom: 1px solid var(--line);
}

.notfall-zeile:last-child {
  border-bottom: none;
}

.notfall-zeile > :last-child:not(:first-child) {
  margin-left: auto;
  min-width: 0;
  text-align: right;
  overflow-wrap: anywhere;
}

/* Die Nummern sind das Wichtigste — groß und antippbar. */
.notfall-nummer {
  font: 700 17px/1.2 var(--font);
  color: var(--brand-600);
  text-decoration: none;
  white-space: nowrap;
}

.notfall-notruf .notfall-nummer {
  font-size: 22px;
}

.notfall-botschaft {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  font-size: 14px;
  line-height: 1.6;
}

/* Woher die Angaben stammen — nachvollziehbar statt behauptet. */
.notfall-quelle {
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-2);
}

.notfall-person {
  padding-bottom: 6px;
}

/* Ein leeres Feld ist ein Hinweis, keine Beruhigung. */
.notfall-fehlt {
  margin-top: 6px;
  padding: 6px 8px;
  font-size: 12px;
  color: var(--warn-600);
  background: var(--warn-100);
  border-radius: 6px;
}

@media print {
  .notfall-hinweis,
  .head {
    display: none !important;
  }

  .notfall-block {
    border: 1px solid #999;
    break-inside: avoid;
    margin-bottom: 10px;
  }

  .notfall-nummer,
  .notfall-notruf .notfall-nummer {
    color: #000;
    font-size: 15px;
  }

  .notfall-zeile {
    border-bottom: 1px solid #ddd;
  }

  @page {
    margin: 12mm;
  }
}

/* Notfalldaten je Person — eingeklappt, weil man sie einmal einträgt. */
.notfall-felder {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
}

.notfall-felder summary {
  cursor: pointer;
  padding: 6px 0;
  font: 600 13px/1.3 var(--font);
  color: var(--text-2);
}

/* ---------------------------------------------------------------------------
   Ausgabe schnell erfassen

   Gedacht für die Kasse oder den Restauranttisch: Der Betrag ist groß und
   sofort im Fokus, alles andere ist vorbelegt.
   --------------------------------------------------------------------------- */
.schnell-zeile {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 100px;
  gap: 10px;
  align-items: center;
}

.schnell-betrag {
  margin: 0;
  font: 700 30px/1.2 var(--font);
  text-align: right;
}

.schnell-waehrung {
  margin: 0;
  font-weight: 600;
}

.schnell-um-zeile {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 10px;
}

.schnell-um {
  font: 700 22px/1.2 var(--font);
  color: var(--brand-600);
}

.schnell-feld {
  display: grid;
  gap: 4px;
  margin-bottom: 12px;
}

.schnell-feld:last-child {
  margin-bottom: 0;
}

.schnell-feld .hint {
  margin: 0;
}

.schnell-feld select,
.schnell-feld input {
  margin: 0;
}

/* Wer mitzahlt — direkt sichtbar, nicht hinter einem Aufklapper. Ab dem 24.9.
   trennt sich die Gruppe, und eine falsch geteilte Rechnung merkt man erst
   bei der Abrechnung. */
.schnell-personen {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
}

.schnell-personen .check {
  margin: 4px 0;
}

@media (max-width: 380px) {
  }

/* Wiederherstellungscodes — zum Ablesen und Ausdrucken. */
.codes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: 8px;
  margin: 12px 0;
}

.codes code {
  padding: 8px 6px;
  font: 600 15px/1 ui-monospace, monospace;
  letter-spacing: 1px;
  text-align: center;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 6px;
}

@media print {
  /* Beim Drucken zählt nur der Zettel mit den Codes. */
  .codes code {
    border: 1px solid #999;
    background: none;
  }
}

/* ---------------------------------------------------------------------------
   Vom Beleg gelesen

   Steht über der Regel-Erkennung: Bei einem fotografierten koreanischen Zettel
   ist das die einzige Zeile, die einem weiterhilft.
   --------------------------------------------------------------------------- */
.scan-karte {
  border-left: 3px solid var(--accent);
}

.scan-satz {
  margin: 0 0 10px;
  font: 500 14.5px/1.45 var(--font);
  color: var(--text);
}

.item-sub.scan-satz {
  font-size: 13px;
  color: var(--text-2);
}

.scan-posten {
  margin-top: 10px;
}

.scan-posten summary {
  font: 600 13px/1.3 var(--font);
  color: var(--accent);
  cursor: pointer;
}

.scan-posten-zeile {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
  font: 450 13px/1.4 var(--font);
  border-bottom: 1px solid var(--line);
}

/* Der Satz, der die Aufteilung offen lässt — genau hier sitzt die Versuchung,
   die Zahl zu übernehmen und weiterzuklicken. */
.scan-warnung {
  margin: 12px 0 10px;
  padding: 9px 11px;
  background: var(--warn-soft);
  border-radius: var(--r-sm);
  color: var(--warn);
}

/* ---------------------------------------------------------------------------
   Foto am Zeitstrahl-Eintrag

   Klein und rechts: Der Zeitstrahl bleibt eine Liste, kein Bilderteppich.
   Nach der Reise erzählt er damit trotzdem mehr als Namen und Uhrzeiten.
   --------------------------------------------------------------------------- */
/*
 * Das Vorschaubild eines Eintrags, den es noch nicht gab.
 *
 * Gestrichelter Rand statt durchgezogenem: Es ist NICHT euer Foto, sondern
 * eines aus dem Netz, das zeigt, wie es dort aussieht. Sobald ein eigenes da
 * ist, gewinnt das eigene (siehe fotoEcke in timeline.js).
 */
.item-foto-vorschau {
  display: block;
  cursor: default;
  border-style: dashed;
  opacity: .9;
}

.item-foto {
  position: relative;
  align-self: center;
  margin: 0;
  padding: 0;
  width: 46px;
  height: 46px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--surface-2);
  box-shadow: none;
}

.item-foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Mehr als eines: die Zahl sagt, dass da noch etwas ist. */
.item-foto-zahl {
  position: absolute;
  right: 2px;
  bottom: 2px;
  padding: 0 4px;
  font: 700 10px/1.5 var(--font);
  color: #fff;
  background: rgb(13 23 33 / 0.72);
  border-radius: var(--r-xs);
}

@media print {
  .item-foto {
    display: none;
  }
}

/* Zuordnung eines Fotos zu einem Eintrag — unter der Großansicht. */
.lightbox-zuordnung {
  display: grid;
  gap: 5px;
  margin-top: 10px;
  padding: 10px 12px;
  background: rgb(255 255 255 / 0.08);
  border-radius: var(--r-sm);
}

.lightbox-zuordnung .hint {
  color: rgb(255 255 255 / 0.72);
}

/* ---------------------------------------------------------------------------
   Aus einem Beleg eine Ausgabe machen

   Abgesetzt vom Rest des Eingangs: Hier wird Geld verteilt, nicht nur ein
   Dokument einsortiert.
   --------------------------------------------------------------------------- */
.beleg-ausgabe {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

/* Die Beteiligten sind Schalter, keine Etiketten — abgewählt heißt zahlt nicht
   mit, und das muss man auf einen Blick sehen. */
.beleg-ausgabe .chip {
  min-height: 36px;
  padding: 6px 12px;
}

.beleg-ausgabe .chip:not(.chip-aktiv) {
  color: var(--text-2);
  text-decoration: line-through;
  opacity: 0.7;
}

/* ---------------------------------------------------------------------------
   Eingang: rechts steht, was zu tun ist

   Vorher stand dort nur "neu" — und nichts deutete darauf hin, dass die Zeile
   irgendwohin führt. Der wichtigste Handgriff lag damit eine Ebene tiefer und
   unsichtbar.
   --------------------------------------------------------------------------- */
.eingang-rechts {
  display: grid;
  justify-items: end;
  align-content: center;
  gap: 6px;
}

/* Nicht nur ein Pfeil: Wo ein Betrag erkannt wurde, steht der nächste Schritt
   im Klartext. */
.eingang-tun {
  font: 650 11.5px/1.2 var(--font);
  white-space: nowrap;
  color: var(--accent);
}

.eingang-pfeil {
  font: 400 18px/1 var(--font);
  color: var(--ink-300);
}

.beleg-ausgabe.ohne-linie {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* Kurs steht auf 1 bei fremder Währung — das ist fast immer ein Versehen. */
.warnung-text {
  color: var(--warn);
  font-weight: 650;
}

/* ---------------------------------------------------------------------------
   Aufteilung nach Positionen
   ---------------------------------------------------------------------------
   Am Tisch, mit einer Hand, während die Rechnung daneben liegt. Deshalb große
   Antippflächen für die Namen und ein Betragsfeld, das breit genug für fünf
   Stellen in Won ist.
   --------------------------------------------------------------------------- */
/*
 * Eigene Klasse, um die Karte gezielt ein- und auszublenden.
 *
 * Geschaltet wird ueber das hidden-Attribut, NICHT ueber style.display: Eine
 * Regel `display:none` hier wuerde mit `style.display = ''` kollidieren — das
 * faellt auf die Regel zurueck, und die Karte bliebe fuer immer unsichtbar.
 */
.posten-karte[hidden] { display: none; }
.posten-karte { border-left: 3px solid var(--accent); }

/* Der Editor selbst — er steckt mal in einer Karte (Ausgaben-Formular), mal
   direkt im Belegformular. Deshalb bringt er nur seinen eigenen Abstand mit
   und keinen Rahmen. */
.posten-bereich {
  display: block;
  margin-top: 10px;
}

.posten-liste { display: flex; flex-direction: column; gap: 10px; }

.posten-zeile {
  display: flex; flex-direction: column; gap: 7px;
  padding: 10px; border: 1px solid var(--line); border-radius: 10px;
  background: var(--surface-2);
}

/*
 * Die Bezeichnung bekommt eine EIGENE ZEILE über die volle Breite.
 *
 * Vorher teilte sie sich eine Zeile mit dem Betrag und dem ×-Knopf und war
 * damit rund 140 px breit. Auf dem Bon stehen Zeilen wie
 * "제육보리비빔밥 ×4 — Bibimbap mit Schweinefleisch" — davon sah man den
 * Anfang und musste raten, welche Zeile man gerade jemandem zuordnet.
 *
 *   Zeile 1: die Bezeichnung, volle Breite, wächst mit dem Inhalt
 *   Zeile 2: Betrag und Wegwerfen
 */
.posten-kopf {
  display: grid;
  grid-template-columns: 1fr 34px;
  grid-template-areas:
    "was was"
    "betrag weg";
  gap: 7px;
  align-items: center;
}

.posten-was {
  grid-area: was;
  min-height: 42px;
  resize: none;
  overflow: hidden;
  line-height: 1.35;
  font: 500 15px/1.35 var(--font);
}

.posten-betrag {
  grid-area: betrag;
  min-height: 42px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.posten-weg { grid-area: weg; }

.posten-weg {
  min-height: 40px; min-width: 34px; padding: 0;
  border: 1px solid var(--line); border-radius: 8px;
  background: transparent; color: var(--text-2);
  font-size: 19px; line-height: 1; cursor: pointer;
}
.posten-weg:hover { color: var(--danger); border-color: var(--danger); }

.posten-wer { display: flex; flex-wrap: wrap; gap: 6px; }
/* Antippfläche: 44 px sind das Minimum, an dem man sich nicht vertippt. */
/*
 * Eine Person an einer Rechnungsposition: Name plus, wenn nötig, − und +.
 *
 * Der Name allein schaltet an und aus — das ist der häufigste Handgriff und
 * braucht genau einen Tipp. Die Mengenknöpfe erscheinen nur, wo sie gebraucht
 * werden: + sobald jemand dabei ist, − erst ab zwei Portionen.
 *
 * Warum überhaupt: Der erste Anlauf am 21.09.2026 ließ einen Tipp hochzählen
 * (1→2→3→4→aus). Damit brauchte das Abwählen vier Tipps statt einem. Alex am
 * 22.09.: "Ich kann die Anteile nur erweitern, nicht verringern."
 */
.wer-chip {
  display: inline-flex;
  align-items: stretch;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--surface-2);
}

.wer-chip.aktiv {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.wer-chip button {
  width: auto;
  margin: 0;
  min-height: 44px;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: transparent;
  color: var(--text-2);
  font: 650 11px/1.3 var(--font);
  letter-spacing: 0.3px;
  cursor: pointer;
}

.wer-chip.aktiv button { color: var(--accent); }

.wer-name {
  padding: 0 11px;
  font-variant-numeric: tabular-nums;
}

/* Die Stufenknöpfe sind schmal, aber 44 px hoch — Daumenmaß. */
.wer-stufe {
  padding: 0;
  min-width: 34px;
  font-size: 17px !important;
  line-height: 1;
}

.wer-stufe:first-child { border-right: 1px solid var(--line); }
.wer-stufe:last-child  { border-left: 1px solid var(--line); }

.posten-knoepfe { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }

.posten-vorschau {
  display: flex; flex-direction: column; gap: 2px; margin-top: 10px;
  border-top: 1px solid var(--line); padding-top: 10px;
}
.posten-anteil {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 5px 0; font-size: 15px;
}
.posten-anteil strong { font-variant-numeric: tabular-nums; }

/* In der Ausgabenliste: so ist auf einen Blick klar, dass hier nicht
   gleichmäßig geteilt wurde. */
.ausgabe-posten { font-size: 12px; color: var(--text-2); }

/* ---------------------------------------------------------------------------
   Ausschnitt des Zeitstrahls: ab heute · vergangen · alles
   ---------------------------------------------------------------------------
   Alex am dritten Reisetag: "Ein Filter wäre cool. Dass man den heutigen Tag
   und die nächsten Tage sieht ... oder dass man alles sieht."

   Drei Knöpfe nebeneinander, jeder mit seiner Anzahl. Die Zahl ist kein
   Schmuck: Ein Knopf, der auf eine leere Ansicht führt, soll das vorher
   sagen — und ist dann gesperrt.
   --------------------------------------------------------------------------- */
.zeitfilter {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  margin: 0 0 14px;
  padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.zeitfilter-knopf {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* 44 px, damit man am Handy nicht danebentippt. */
  min-height: 44px;
  padding: 0 8px;
  border: 0;
  border-radius: calc(var(--r-md) - 4px);
  background: transparent;
  color: var(--text-2);
  font: 600 13px/1.2 var(--font);
  cursor: pointer;
}

.zeitfilter-knopf.an {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--e1);
}

.zeitfilter-knopf:disabled {
  opacity: 0.4;
  cursor: default;
}

.zeitfilter-zahl {
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--line);
  color: var(--text-2);
  font: 600 11px/1.5 var(--font);
  font-variant-numeric: tabular-nums;
}

.zeitfilter-knopf.an .zeitfilter-zahl {
  background: var(--accent-soft);
  color: var(--accent);
}

/* ---------------------------------------------------------------------------
   Ablagefläche für Bilder
   ---------------------------------------------------------------------------
   Alex am 15.09.2026: "ich hätte sie aber gerne nicht nochmal kopiert oder
   exportiert, sondern einfach nur hochgeladen aus der fotos mediathek."

   Aus Apple Fotos lassen sich Bilder direkt hierher ziehen. Die Fläche muss
   groß genug sein, dass man sie beim Ziehen trifft, und sichtbar reagieren —
   sonst weiß niemand, ob er richtig zielt.
   --------------------------------------------------------------------------- */
/*
 * Die Warteschlange vor dem Hochladen.
 *
 * Sie ist da, damit man SIEHT, was gleich hochgeht. Der Grund steht in
 * galerie.js: Zwei Züge hintereinander ergaben früher nur den zweiten, und
 * genau das fiel niemandem auf, weil nichts es zeigte.
 */
/*
 * `display: flex` schlaegt das hidden-Attribut. Ohne diese Zeile blieb die
 * Liste nach "Liste leeren" stehen, obwohl hidden gesetzt war.
 */
/* ---------------------------------------------------------------------------
   Die Kostenseite, zwei Ansichten.

   "Meine Kosten" beantwortet: Was muss ich tun? -> .tat
   "Alle Kosten"  beantwortet: Wie steht die Gruppe? -> .p

   Der Vorlaeufer stellte dieselben Zahlen dreimal untereinander in drei
   Vokabularen. Alex am 18.09.2026: "Ich finde das unverstaendlich."
   --------------------------------------------------------------------------- */

/* --- "Meine Kosten": die Handlung --- */
.tat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 16px;
  margin-bottom: 12px;
}

.tat h2 {
  margin: 0 0 4px;
  font: 800 15px/1.3 var(--font);
}

.tat-gross {
  font: 800 30px/1.1 var(--font);
  margin: 6px 0 2px;
  font-variant-numeric: tabular-nums;
}

.tat-zeile {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 0;
  border-top: 1px solid var(--line);
}

.tat-zeile:first-of-type {
  border-top: 0;
}

.tat-wer {
  flex: 1;
  font: 600 15px/1.3 var(--font);
}

.tat-betrag {
  font: 700 16px/1.2 var(--font);
  font-variant-numeric: tabular-nums;
}

/*
 * Die Herleitung. Ohne sie ist der Betrag darueber eine Zahl, die vom Himmel
 * faellt - und genau das war die Klage.
 */
.tat-rechnung {
  font: 400 13px/1.7 var(--font);
  color: var(--text-2);
  margin: 10px 0 0;
  font-variant-numeric: tabular-nums;
}

/* --- "Alle Kosten": eine Zeile je Person --- */
.p {
  border-top: 1px solid var(--line);
  padding: 13px 0;
}

.p:first-of-type {
  border-top: 0;
}

/* Die eigene Zeile hebt sich ab - man sucht sie als Erstes. */
.p-ich {
  background: var(--surface-2);
  margin: 0 -14px;
  padding-left: 14px;
  padding-right: 14px;
  border-radius: 12px;
}

.p-kopf {
  display: flex;
  align-items: baseline;
  gap: 8px;
}

.p-name {
  flex: 1;
  font: 700 16px/1.2 var(--font);
}

.p-saldo {
  font: 700 17px/1.2 var(--font);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.p-rechnung {
  margin-top: 3px;
  font: 400 13px/1.5 var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.p-tat {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 9px;
  padding: 9px 11px;
  background: var(--surface-2);
  border-radius: 10px;
}

/* In der eigenen Zeile ist der Hintergrund schon grau - dort ein Rahmen. */
.p-ich .p-tat {
  background: var(--surface);
  border: 1px solid var(--line);
}

.p-tat .txt {
  flex: 1;
  font: 600 14px/1.3 var(--font);
}

/* ---------------------------------------------------------------------------
   Die Seite zum Herzeigen — fuer Leute ohne Konto.

   Alex' eigenes Wort: "wenn teilnehmende die Bilder herzeigen wollen".
   Bewusst schlicht: keine Navigation, keine Reise-Werkzeuge. Wer hier landet,
   soll Bilder sehen und sonst nichts suchen muessen.

   NICHT ".geteilt" nennen — die Klasse gibt es schon, sie gehoert zur
   Aufteilung einer Rechnung. Der CSS-Test hat die Kollision gefangen.
   --------------------------------------------------------------------------- */
.herzeigen {
  max-width: 760px;
  margin: 0 auto;
  padding: 16px 14px 48px;
}

.herzeigen-kopf {
  margin-bottom: 16px;
}

.herzeigen-kopf h1 {
  font: 800 24px/1.2 var(--font);
  margin: 0 0 2px;
}

.herzeigen-tag {
  font: 800 14px/1.3 var(--font);
  margin: 18px 0 8px;
  color: var(--text-2);
}

.herzeigen-programm,
.herzeigen-kosten {
  display: block;
}

.herzeigen-punkt {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}

.herzeigen-zeit {
  flex: 0 0 62px;
  font: 600 13px/1.4 var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.herzeigen-betrag {
  margin-left: auto;
  font: 600 14px/1.4 var(--font);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.herzeigen-recht {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  font: 500 14px/1.3 var(--font);
}

.herzeigen-recht input {
  width: auto;
  margin: 0;
  min-height: 0;
}

.herzeigen-fuss {
  margin-top: 28px;
  text-align: center;
}

/* Ein geteilter Link in der Verwaltung. */
.freigabe {
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.freigabe:last-child {
  border-bottom: 0;
}

.freigabe-kopf {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 3px;
}

/* ---------------------------------------------------------------------------
   Antippen kopiert.

   Alex am 18.09.2026 vor einem Kartenladen in Busan: "Ich kann die Adresse
   oder den Namen so nicht rauskopieren." Er stand auf der Strasse und wollte
   eine koreanische Adresse in eine Taxi-App tippen — genau dafuer ist die App
   da, und ausgerechnet das ging nicht.

   Der Knopf sieht aus wie Text, damit die Ansicht nicht zur Schalterwand
   wird; nur der gestrichelte Unterstrich verraet, dass er etwas kann.
   --------------------------------------------------------------------------- */
.kopierbar {
  display: inline;
  width: auto;
  min-height: 0;
  margin: 0;
  padding: 1px 0;
  border: 0;
  background: none;
  box-shadow: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: copy;
  border-bottom: 1px dashed var(--line-strong, var(--line));
  border-radius: 0;
}

.kopierbar:active {
  opacity: .6;
}

.kopierbar.kopiert {
  color: var(--ok-600, var(--petrol, #0f6a63));
  border-bottom-color: currentColor;
  font-weight: 600;
}

/* Name, Adresse und Kartenlink untereinander statt in einer langen Zeile —
   auf dem Handy bricht sonst mitten in der Adresse um. */
/* Die lateinische Umschrift: zum Lesen, nicht zum Einfügen. */
.umschrift {
  font: 400 13px/1.4 var(--font);
  color: var(--text-2);
}

.karten-links {
  display: flex;
  gap: 12px;
  margin-top: 2px;
}

.ort-zeile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
}

/* Die Filterleiste der Galerie: drei Zeilen, jede nur wenn sie etwas kann. */
.medien-filter {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
}

.filter-zeile {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
}

/*
 * Ausgeblendete Kacheln: blass und durchgestrichen markiert.
 *
 * Sie sind nur zu sehen, wenn der Schalter umgelegt ist — dann aber muss man
 * sie auf einen Blick von den normalen unterscheiden koennen.
 */
.medien-kachel.medien-aus img {
  opacity: 0.35;
  filter: grayscale(0.7);
}

.medien-aus-zeichen {
  position: absolute;
  top: 4px;
  left: 4px;
  font-size: 15px;
  line-height: 1;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

/* Ausblenden links, Loeschen rechts — die zwei duerfen sich nicht verwechseln. */
.lightbox-aktionen {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 8px 12px;
  border-top: 1px solid var(--line);
}

.warteschlange[hidden] {
  display: none;
}

.warteschlange {
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface-2);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.warteschlange-kopf {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}

/* Der Knopf rechts, alles andere links. */
.warteschlange-kopf > button {
  margin-left: auto;
}

.warteschlange-zeile {
  display: flex;
  align-items: center;
  gap: 10px;
}

/*
 * Lange Dateinamen dürfen die Zeile nicht sprengen — sonst wird die Seite
 * überbreit, und genau das war schon einmal ein Fehlerbericht.
 */
.warteschlange-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 500 13px/1.3 var(--font);
}

.ablage {
  display: grid;
  justify-items: center;
  gap: 4px;
  margin: 12px 0;
  padding: 26px 16px;
  border: 2px dashed var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--text-2);
  font: 600 14px/1.4 var(--font);
  text-align: center;
  /* Ohne das landet ein Tropfen auf dem Text statt auf der Fläche. */
  pointer-events: auto;
}

.ablage-zeichen {
  font-size: 22px;
  line-height: 1;
  color: var(--accent);
}

.ablage .hint {
  margin: 0;
  font-weight: 400;
}

.ablage-an {
  border-color: var(--accent);
  border-style: solid;
  background: var(--accent-soft);
  color: var(--text);
}

/* Am Handy zieht niemand Dateien — dort nur der Dateidialog. */
@media (hover: none) {
  .ablage { display: none; }
}

/* ===========================================================================
   Abrechnung — die ganze Rechnung offen

   Vier Personenspalten plus Datum, Bezeichnung, Betrag, Zahler und Art passen
   auf kein Handy. Statt Spalten zu verstecken, scrollt die Tabelle in ihrem
   eigenen Kasten; die Seite selbst bleibt ruhig. Datum und Bezeichnung haften
   links, damit man beim Wischen weiß, welche Zeile man gerade liest.
   =========================================================================== */

.abrechnung-salden {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}

.saldo-kachel {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.saldo-name {
  font: 600 13px/1.2 var(--font);
  color: var(--text-2);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.saldo-zahl {
  font: 700 21px/1.2 var(--font);
  font-variant-numeric: tabular-nums;
}

.saldo-zahl.gut {
  color: var(--ok);
}

.saldo-zahl.schlecht {
  color: var(--danger);
}

.saldo-zeile {
  font: 400 12px/1.4 var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.ausgleich-liste {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ausgleich-liste li {
  display: flex;
  gap: 6px;
  align-items: baseline;
  padding: 10px 12px;
  background: var(--accent-soft);
  border-radius: var(--r-sm);
}

.ausgleich-liste .pfeil {
  color: var(--text-2);
}

.ausgleich-betrag {
  margin-left: auto;
  font: 700 15px/1.2 var(--font);
  font-variant-numeric: tabular-nums;
}

/*
 * Der Scroll-Kasten. `overflow-x: auto` MUSS hier stehen und nicht an der
 * Tabelle — eine Tabelle mit haftenden Zellen scrollt sonst nicht mit.
 */
.tabelle-rahmen {
  overflow-x: auto;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  -webkit-overflow-scrolling: touch;
}

table.abrechnung {
  width: max-content;
  min-width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font: 400 13px/1.4 var(--font);
}

table.abrechnung th,
table.abrechnung td {
  padding: 8px 10px;
  text-align: left;
  white-space: nowrap;
  border-bottom: 1px solid var(--line);
}

/*
 * Kein `position: sticky` am Kopf — der Kasten mit overflow-x ist ein eigener
 * Scroll-Bereich, in dem senkrecht nie gescrollt wird; der Kopf würde an
 * einer Kante kleben, die mit der Seite aus dem Bild wandert. Stattdessen
 * wiederholt ihn das JS alle 15 Zeilen.
 */
table.abrechnung .kopfzeile th {
  font: 600 12px/1.3 var(--font);
  color: var(--text-2);
  background: var(--surface-2);
  letter-spacing: 0.03em;
  border-bottom: 1px solid var(--ink-200);
}

table.abrechnung tbody .kopfzeile th {
  padding-top: 16px;
  border-top: 1px solid var(--ink-200);
}

/*
 * Haftende Spalten brauchen einen eigenen Hintergrund — sonst scheint beim
 * Wischen der Text der Zellen durch, über die sie gerade liegen.
 */
table.abrechnung .haftend {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--surface);
}

table.abrechnung .haftend.zweite {
  left: 104px;
  border-right: 1px solid var(--line);
  white-space: normal;
  min-width: 170px;
  max-width: 260px;
}

table.abrechnung .kopfzeile .haftend {
  z-index: 2;
  background: var(--surface-2);
}

table.abrechnung .zahl {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

table.abrechnung .leer {
  color: var(--ink-300);
}

table.abrechnung .z-titel {
  font-weight: 600;
}

table.abrechnung .z-fremd,
table.abrechnung .z-art {
  color: var(--text-2);
  font-size: 12px;
}

.abrechnung-zeile {
  cursor: pointer;
}

.abrechnung-zeile:hover .haftend,
.abrechnung-zeile:hover td {
  background: var(--accent-soft);
}

table.abrechnung tfoot td {
  background: var(--surface-2);
  font-weight: 600;
  border-top: 1px solid var(--line);
  border-bottom: none;
}

table.abrechnung .summenzeile td {
  background: var(--surface-2);
}

table.abrechnung .summenzeile.stark td {
  font-size: 14px;
  border-top: 2px solid var(--line);
}

table.abrechnung tfoot .gut {
  color: var(--ok);
}

table.abrechnung tfoot .schlecht {
  color: var(--danger);
}

/*
 * Die Abrechnung darf breiter sein. `.app` steht bewusst auf 620 px — das ist
 * die Breite, in der sich am Handy gut lesen lässt, und auf dem PC hält sie
 * die Zeilen kurz. Nur hier ist das falsch: Die Tabelle ist rund 990 px
 * breit, in 620 px sieht man ein Drittel davon.
 *
 * Die Ausnahme hängt an :has() — am Vorhandensein der Seite selbst. Beim
 * Weiterklicken verschwindet das Kind und der Deckel gilt wieder, ganz ohne
 * eine Klasse, die jemand zurücksetzen müsste.
 */
@media (min-width: 720px) {
  .app:has(> .breite-seite) {
    max-width: 1240px;
  }
}

/* Die Karte: Auf dem PC ist sie das Wichtigste auf der Seite und darf fast
   die ganze Fensterbreite nehmen. Die Höhe rechnet karte.js aus. */
@media (min-width: 720px) {
  .app:has(> .karten-seite) {
    max-width: min(1800px, 100%);
  }
}

/* ---------------------------------------------------------------------------
   Die Abrechnung am Handy: Karten statt Tabelle

   Gemessen auf 390 px: Die Tabelle ist 987 px breit, der Kasten 306 px. Die
   zwei haftenden Spalten (Datum und Bezeichnung) belegen davon allein 274 px
   — quer gewischt sieht man also die Namensspalten NIE. Eine Tabelle, die man
   nicht lesen kann, ist keine Tabelle.

   Deshalb wird dieselbe Tabelle hier zu Karten: eine je Ausgabe, jede Zelle
   eine Zeile mit ihrer Spaltenbeschriftung davor. Die Beschriftung steht im
   data-spalte-Attribut, das das JS mitgibt — ein Markup, zwei Darstellungen,
   keine zweite Stelle, an der Zahlen entstehen können.
   --------------------------------------------------------------------------- */
@media (max-width: 719px) {
  .tabelle-rahmen {
    overflow-x: visible;
    border: none;
    border-radius: 0;
  }

  table.abrechnung,
  table.abrechnung thead,
  table.abrechnung tbody,
  table.abrechnung tfoot,
  table.abrechnung tr,
  table.abrechnung td {
    display: block;
    width: auto;
    min-width: 0;
    max-width: none;
  }

  /* Der Kopf wird zur Beschriftung IN den Zellen — die Zeile selbst weg. */
  table.abrechnung .kopfzeile {
    display: none;
  }

  table.abrechnung tbody tr,
  table.abrechnung tfoot tr {
    margin-bottom: 10px;
    padding: 10px 12px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
  }

  table.abrechnung td {
    display: flex;
    gap: 10px;
    align-items: baseline;
    justify-content: space-between;
    padding: 3px 0;
    white-space: normal;
    border-bottom: none;
    text-align: left;
  }

  table.abrechnung td::before {
    content: attr(data-spalte);
    flex: 0 0 auto;
    font: 600 12px/1.4 var(--font);
    color: var(--text-2);
  }

  /*
   * Die Bezeichnung bekommt die ganze Breite und keine Beschriftung.
   *
   * position und border-right MÜSSEN hier zurück: In der Tabellenansicht ist
   * diese Zelle `sticky` mit `left: 104px`. Bleibt das stehen, rückt der Titel
   * in der Karte um 104 px ein und bekommt einen Strich an der rechten Seite —
   * genau das war auf dem ersten Messbild zu sehen.
   */
  /*
   * In der Tabelle haben die haftenden Zellen einen eigenen Hintergrund,
   * damit beim Querwischen nichts durchscheint. In der Karte gibt es kein
   * Querwischen — dort malt dieser Hintergrund nur ein weißes Kästchen in
   * die graue Summenkarte.
   */
  table.abrechnung td.haftend {
    background: none;
  }

  /*
   * Die Regeln der Tabellenansicht sind spezifischer als die Rücksetzer hier
   * — `table.abrechnung .haftend.zweite` schlägt `table.abrechnung td`. Ohne
   * diese beiden Zeilen behält die Bezeichnung ihre 260 px Deckel (sichtbar
   * als Kästchen mitten in der Karte) und die leere erste Zelle ihre Höhe
   * (sichtbar als Strich über jeder Summenkarte). Beides gemessen.
   */
  table.abrechnung td.haftend.zweite {
    max-width: none;
    min-width: 0;
  }

  table.abrechnung td.haftend.still {
    display: none;
  }

  table.abrechnung td.zweite {
    position: static;
    border-right: none;
    display: block;
    padding-bottom: 6px;
    font-size: 15px;
    border-bottom: 1px solid var(--line);
    margin-bottom: 6px;
  }

  table.abrechnung td.zweite::before {
    content: none;
  }

  /*
   * Das Datum steht klein darüber, wie eine Kopfzeile der Karte.
   *
   * `:not(.still)` muss mit: Die Summenzeilen haben an dieser Stelle eine
   * leere Zelle, und `display: block` würde sie aus der Versenkung holen —
   * als Strich über jeder Summenkarte. Die beiden Regeln sind gleich
   * spezifisch, die spätere gewinnt, und das ist diese hier.
   */
  table.abrechnung td.haftend:not(.zweite):not(.still) {
    position: static;
    display: block;
    font: 600 12px/1.4 var(--font);
    color: var(--text-2);
    text-transform: uppercase;
    letter-spacing: 0.03em;
  }

  table.abrechnung td.haftend:not(.zweite)::before {
    content: none;
  }

  /* Wer nicht mitgezahlt hat, braucht keine Zeile mit einem Punkt darin. */
  table.abrechnung td.leer,
  table.abrechnung td.still,
  table.abrechnung td:empty {
    display: none;
  }

  table.abrechnung tfoot tr {
    background: var(--surface-2);
  }

  table.abrechnung tfoot td.zweite {
    font: 700 15px/1.3 var(--font);
  }
}

/* ---------------------------------------------------------------------------
   Belege in der Abrechnung
   --------------------------------------------------------------------------- */

/*
 * Ein Link, der wie ein Knopf aussieht. Muss ein <a> bleiben und darf kein
 * <button> werden: Nur ein echter Link mit href lädt die Datei herunter,
 * ohne dass wir das Archiv erst in den Arbeitsspeicher holen — bei einem
 * gestreamten ZIP ist das der ganze Punkt.
 */
.knopf-link {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 16px;
  font: 600 15px/1.2 var(--font);
  color: var(--accent-ink);
  text-decoration: none;
  background: var(--accent);
  border-radius: var(--r-md);
}

.knopf-link:active {
  filter: brightness(0.94);
}

.beleg-links {
  display: inline-flex;
  gap: 4px;
}

.beleg-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  min-height: 32px;
  font-size: 15px;
  text-decoration: none;
  border-radius: var(--r-xs);
}

.beleg-link:active {
  background: var(--accent-soft);
}

.ohne-beleg {
  color: var(--ink-300);
}

table.abrechnung .z-kategorie {
  color: var(--text-2);
  font-size: 12px;
}

/* ---------------------------------------------------------------------------
   Wegzeiten zwischen zwei Einträgen

   Eine leise Zeile, keine Kachel: Sie gehört ZWISCHEN zwei Einträge und darf
   nicht wie ein dritter aussehen. Solange die Zeiten noch unterwegs sind,
   bleibt der Platzhalter unsichtbar (:empty), damit nichts springt, was dann
   doch nicht kommt.
   --------------------------------------------------------------------------- */
.weg {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  align-items: baseline;
  margin: -4px 0;
  padding: 2px 4px 2px 10px;
  font: 500 13px/1.4 var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.weg:empty {
  display: none;
}

.weg-pfeil {
  color: var(--ink-300);
}

.weg-teil {
  white-space: nowrap;
}

.weg-km {
  color: var(--ink-300);
}

.weg-oeffi {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
}

.weg.knapp {
  color: var(--warn);
}

.weg-warnung {
  flex-basis: 100%;
  font-weight: 600;
  color: var(--warn);
}

.weg-zurueck {
  margin-top: 0;
}

/* Packliste und "Zu buchen": Text über die ganze Breite, Zusätze darunter. */
.pack-text {
  align-items: flex-start;
}

.pack-text > span {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.pack-warum {
  font: 400 13px/1.4 var(--font);
  color: var(--text-2);
}

.pack-zusatz {
  font: 500 12px/1.4 var(--font);
  color: var(--ink-300);
}

.pack-mehr summary {
  font: 600 12px/1.4 var(--font);
  color: var(--accent);
  cursor: pointer;
}

.pack-notiz {
  margin-top: 4px;
  font: 400 13px/1.45 var(--font);
  color: var(--text-2);
  white-space: pre-line;
}

/* Tagesfarben unter der Karte */
.karte-tage {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 12px;
  margin-top: 8px;
  font: 500 12px/1.4 var(--font);
  color: var(--text-2);
}

.karte-tag {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  white-space: nowrap;
}

.karte-tag-farbe {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}

.karte-gruppe {
  cursor: zoom-in;
}

.karte-zahl-gruppe {
  font-size: 12px;
}

/* Ladebalken oben — erscheint erst, wenn eine Seite länger als 120 ms braucht. */
body.laedt::before {
  content: '';
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  width: 40%;
  height: 3px;
  background: var(--accent);
  animation: ladebalken 0.9s ease-in-out infinite;
}

@keyframes ladebalken {
  from { transform: translateX(-100%); }
  to { transform: translateX(250%); }
}

@media (prefers-reduced-motion: reduce) {
  body.laedt::before {
    width: 100%;
    animation: none;
    opacity: 0.7;
  }
}

/* Schwebender Knopf rechts unten: "etwas Neues anlegen". */
.fab {
  position: fixed;
  right: max(16px, env(safe-area-inset-right));
  bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 30;
  display: inline-flex;
  gap: 6px;
  align-items: center;
  width: auto;
  min-height: 52px;
  margin: 0;
  padding: 0 20px 0 16px;
  font: 700 15px/1 var(--font);
  color: #fff;
  background: var(--sun-500);
  border: none;
  border-radius: var(--r-pill);
  box-shadow: 0 6px 18px rgb(13 23 33 / 0.28), 0 2px 4px rgb(13 23 33 / 0.18);
}

.fab:active {
  transform: scale(0.96);
}

.fab-plus {
  font-size: 22px;
  line-height: 1;
}

/* Auf breiten Schirmen am Rand der App, nicht am Rand des Monitors. */
@media (min-width: 720px) {
  .fab {
    right: max(16px, calc((100vw - 620px) / 2 - 8px));
  }
}

/* Markierungen, an denen das JS Elemente wiederfindet — ohne eigenes Aussehen. */
.neuer-punkt,
.fab-hochladen {
  /* keine eigenen Regeln: .card bzw. .fab gestalten */
}

/* Über der Karte nur eine Zeile: wessen Weg, welcher Ausschnitt. */
.karte-wahl {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  align-items: center;
  margin-bottom: 12px;
}

.karte-wahl > .chips {
  margin: 0;
}

.karte-blick {
  width: auto;
  min-width: 170px;
  flex: 1 1 170px;
  max-width: 320px;
  min-height: 38px;
  margin: 0;
}

/* Platzhalter, bis die Karte nach dem Einhängen gezeichnet ist (wenige ms). */
.karte-platz {
  min-height: 380px;
}

/* Stecknadeln der großen Reiseziele und die Nummern hinter ihrem Namen. */
.karte-nadel:active path {
  opacity: 0.8;
}

.karte-name-zusatz {
  font-size: 10px;
  font-weight: 600;
}

.karte-name-innen .karte-name-zusatz {
  fill: #4a5a66;
}

/* Kein Kasten um die angetippte Marke — nur beim Bedienen mit der Tastatur. */
.karte-punkt:focus {
  outline: none;
}

.karte-punkt:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Übersicht am PC: links die Zeitleiste, rechts die Karte zum Tag.
   Unter 1100 px ist das Fenster weg und alles bleibt wie am Handy.
   --------------------------------------------------------------------------- */
.karten-fenster {
  display: none;
}

@media (min-width: 1100px) {
  .app:has(> .hub-seite) {
    max-width: min(1600px, 100%);
  }

  .hub-raster {
    display: grid;
    /* Links genau so breit wie die App am Handy: 620 px minus Rand. */
    grid-template-columns: minmax(0, 580px) minmax(0, 1fr);
    gap: 28px;
    align-items: start;
  }

  .karten-fenster {
    display: flex;
    flex-direction: column;
    gap: 8px;
    position: sticky;
    top: calc(var(--kopf) + 8px);
    height: calc(100vh - var(--kopf) - 28px);
    min-height: 360px;
  }

  .kf-kopf {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
  }

  .kf-titel {
    font: 800 14px/1.3 var(--font);
    letter-spacing: 0.4px;
    color: var(--text);
  }

  .kf-gross {
    width: auto;
    min-height: 32px;
    margin: 0;
    padding: 4px 12px;
    font-size: 13px;
  }

  .kf-flaeche {
    flex: 1;
    min-height: 0;
  }

  .kf-flaeche .karte-rahmen {
    margin: 0;
  }
}

/* Mit Karte daneben gehört das "+" an die Zeitleiste, nicht mitten auf die
   Karte: rechte Kante der linken Spalte. */
@media (min-width: 1100px) {
  .app:has(> .hub-seite) .fab {
    right: auto;
    left: calc((100vw - min(1600px, 100vw)) / 2 + 20px + 580px - 12px);
    translate: -100% 0;
  }
}

/* Die linke Spalte: min-width 0, damit breite Kacheln sie nicht aufsprengen. */
.hub-links {
  min-width: 0;
}

/* ---------------------------------------------------------------------------
   Kosten am PC: links die Ausgaben, rechts mitlaufend die Salden.
   Im DOM steht der Saldo zuerst — so bleibt am Handy alles, wie es war.
   --------------------------------------------------------------------------- */
.kosten-saldo,
.kosten-liste {
  min-width: 0;
}

@media (min-width: 1100px) {
  .app:has(> .kosten-seite) {
    max-width: min(1280px, 100%);
  }

  .kosten-raster {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(360px, 440px);
    grid-template-areas: 'liste saldo';
    gap: 28px;
    align-items: start;
  }

  .kosten-liste {
    grid-area: liste;
  }

  /* Mitlaufend; ist die Abrechnung länger als das Fenster, scrollt sie für
     sich, statt unten abgeschnitten zu werden. */
  .kosten-saldo {
    grid-area: saldo;
    position: sticky;
    top: calc(var(--kopf) + 8px);
    max-height: calc(100vh - var(--kopf) - 24px);
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 4px;
  }

  /* Das "+" an die rechte Kante der Ausgabenliste, nicht auf die Salden. */
  .app:has(> .kosten-seite) .fab {
    right: auto;
    /* rechter Rand der App − Rand 20 − Saldospalte 440 − Lücke 28 − Luft 12 */
    left: calc((100vw - min(1280px, 100vw)) / 2 + min(1280px, 100vw) - 20px - 440px - 28px - 12px);
    translate: -100% 0;
  }
}

/* Beleg wird gelesen: Balken plus echte Sekunden. */
.lese-fortschritt {
  display: grid;
  gap: 5px;
  margin: 4px 0 2px;
}

.lese-balken {
  display: block;
  height: 6px;
  border-radius: 3px;
  background: var(--surface-2);
  overflow: hidden;
}

.lese-fortschritt.gross .lese-balken {
  height: 10px;
  border-radius: 5px;
}

.lese-fuellung {
  display: block;
  width: 0;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
  transition: width 0.5s linear;
}

.lese-text {
  font-size: 13px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .lese-fuellung {
    transition: none;
  }
}

/* --- Meine GPS-Spur ------------------------------------------------------- */
.gps-titel {
  margin: 0 0 4px;
}

.gps-status.gps-an {
  border-left: 3px solid var(--ok-500);
}

.gps-schritte {
  display: grid;
  gap: 8px;
  margin: 0 0 14px;
  padding-left: 20px;
  line-height: 1.45;
}

.gps-zugang {
  display: grid;
  gap: 10px;
  margin-top: 12px;
}

.gps-wert {
  display: grid;
  grid-template-columns: 76px minmax(0, 1fr) auto;
  gap: 8px;
  align-items: center;
  margin: 6px 0;
}

.gps-wert code {
  overflow-wrap: anywhere;
  font-size: 12px;
}

.gps-kopieren {
  width: auto;
  min-height: 34px;
  margin: 0;
  padding: 4px 10px;
  font-size: 13px;
}

.gps-wer {
  display: grid;
  gap: 6px;
}

.gps-person {
  display: flex;
  gap: 10px;
  align-items: center;
  min-height: 44px;
}

.gps-person input {
  width: 22px;
  height: 22px;
  margin: 0;
}

.gps-gespeichert:empty {
  display: none;
}

.karte-spur-farbe {
  width: 16px;
  height: 4px;
  border-radius: 2px;
}

/* Die allgemeine label-Regel (Großbuchstaben, Abstand) passt hier nicht:
   Das sind Namen zum Ankreuzen, keine Feldüberschriften. */
label.gps-person {
  margin: 0;
  font: 500 16px/1.3 var(--font);
  letter-spacing: normal;
  text-transform: none;
  color: var(--text);
}

/* Markierungen ohne eigenes Aussehen — das JS und die Tests finden sie wieder. */
.gps-aus,
.gps-uebernehmen,
.karte-spur {
  /* keine eigenen Regeln */
}

/* --- iPhone-App: Warteschlange, GPS, Geräte ------------------------------- */
.warteschlange-titel {
  margin: 0 0 4px;
  font-size: 16px;
}

.warteschlange-fehler {
  color: var(--warn);
}

.gps-app-knoepfe {
  display: grid;
  gap: 8px;
}

.gps-app-hinweis {
  margin: -6px 4px 14px;
}

.geraet-zeile {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
}

.geraet-weg {
  width: auto;
  min-height: 36px;
  margin: 0;
  padding: 4px 12px;
}

.warteschlange,
.gps-app {
  /* Klassen zum Wiederfinden, das Aussehen kommt von .card */
}

.app-version:empty {
  display: none;
}

/* --- Abrechnung: Filter und Sortierung ------------------------------------ */
.tabelle-filter {
  display: grid;
  gap: 6px;
  margin: 4px 0 10px;
}

.filter-reihe {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
  align-items: end;
}

.filter-reihe select,
.filter-reihe input {
  width: 100%;
  min-height: 40px;
  margin: 0;
  font-size: 14px;
}

.filter-datum,
.filter-sort {
  display: grid;
  gap: 2px;
  margin: 0;
  text-transform: none;
  letter-spacing: normal;
  font: 500 12px/1.2 var(--font);
  color: var(--text-2);
}

.filter-stand {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  align-items: center;
  margin: 0;
}

.filter-weg {
  width: auto;
  min-height: 32px;
  margin: 0;
  padding: 4px 12px;
  font-size: 13px;
}

table.abrechnung th.sortierbar {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

table.abrechnung th.sortiert {
  color: var(--accent);
}

table.abrechnung .z-ort,
table.abrechnung .z-zahlung {
  white-space: nowrap;
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.zahlung-felder {
  margin-top: 2px;
}

/* Die Sortierung über die ganze Breite — ihre Texte sind länger als ein Filter. */
.filter-sort {
  grid-column: 1 / -1;
}

/* --- Fotos groß ansehen (lib/betrachter.js) ------------------------------- */
html.betrachter-offen,
html.betrachter-offen body {
  overflow: hidden;
  overscroll-behavior: none;
}

.betrachter {
  --b-grund: 1;
  position: fixed;
  inset: 0;
  z-index: 80;
  background: rgb(0 0 0 / var(--b-grund));
  color: #fff;
  user-select: none;
  -webkit-user-select: none;
}

.b-buehne {
  position: absolute;
  inset: 0;
  overflow: hidden;
  touch-action: none;
}

.b-folie {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  will-change: transform;
}

.b-medium {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  transform-origin: center center;
  will-change: transform;
  -webkit-user-drag: none;
}

video.b-medium {
  width: 100%;
  max-height: 80%;
  touch-action: auto;
}

.b-kopf {
  position: absolute;
  inset: 0 0 auto 0;
  display: flex;
  gap: 10px;
  align-items: center;
  padding: max(10px, env(safe-area-inset-top)) 12px 10px;
  background: linear-gradient(rgb(0 0 0 / 0.6), rgb(0 0 0 / 0));
  transition: opacity 0.2s;
}

.b-kopf-mitte {
  display: grid;
  flex: 1;
  min-width: 0;
  text-align: center;
}

.b-titel {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 600 14px/1.3 var(--font);
}

.b-zaehler {
  font: 500 12px/1.3 var(--font);
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}

.b-knopf {
  width: 44px;
  height: 44px;
  min-height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 22px;
  background: rgb(255 255 255 / 0.14);
  color: #fff;
  font-size: 20px;
  line-height: 44px;
  box-shadow: none;
}

.b-pfeil {
  position: absolute;
  top: 50%;
  width: 48px;
  height: 64px;
  min-height: 0;
  margin: -32px 0 0;
  padding: 0;
  border: 0;
  background: rgb(0 0 0 / 0.35);
  color: #fff;
  font-size: 34px;
  box-shadow: none;
  transition: opacity 0.2s;
}

.b-links { left: 0; border-radius: 0 12px 12px 0; }
.b-rechts { right: 0; border-radius: 12px 0 0 12px; }

/* Am Handy blättert man mit dem Finger — die Pfeile nur, wo es eine Maus gibt. */
@media (hover: none) {
  .b-pfeil { display: none; }
  .betrachter.ist-video .b-pfeil { display: block; }
}

.betrachter.ohne-knoepfe .b-kopf,
.betrachter.ohne-knoepfe .b-pfeil {
  opacity: 0;
  pointer-events: none;
}

.b-info {
  position: absolute;
  inset: auto 0 0 0;
  max-height: 55%;
  overflow-y: auto;
  padding: 16px 16px calc(16px + env(safe-area-inset-bottom));
  border-radius: 18px 18px 0 0;
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 -8px 30px rgb(0 0 0 / 0.4);
  user-select: text;
  -webkit-user-select: text;
}

.b-info[hidden] {
  display: none;
}

.b-info-zeile {
  margin: 0 0 8px;
}

/* --- Raster wie in der Fotos-App: quadratisch, dicht an dicht ------------- */
.medien-gitter {
  grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
  gap: 2px;
  margin: 10px -14px 0;
}

.medien-kachel {
  border: 0;
  border-radius: 0;
}

.medien-kachel img {
  transition: opacity 0.2s;
}

.medien-kachel:active img {
  opacity: 0.7;
}

@media (min-width: 720px) {
  .medien-gitter {
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    margin: 10px 0 0;
    gap: 4px;
  }
}

/* Im hellen Info-Feld der neuen Großansicht die Farben der alten, dunklen
   Lightbox zurücknehmen. */
.b-info .lightbox-zuordnung {
  background: var(--surface-2);
}

.b-info .lightbox-zuordnung .hint,
.b-info .hint {
  color: var(--text-2);
}

.b-info .lightbox-aktionen {
  margin-top: 10px;
}

.hochladen-klappe > summary {
  cursor: pointer;
  list-style: none;
}

.hochladen-klappe > summary::-webkit-details-marker {
  display: none;
}

.hochladen-titel {
  display: inline;
  margin: 0;
}

.hochladen-klappe > summary::after {
  content: ' ›';
  color: var(--text-2);
}

.hochladen-klappe[open] > summary {
  margin-bottom: 8px;
}

.b-info-inhalt {
  display: grid;
  gap: 2px;
}

/* --- Konten und Einmalpasswörter ----------------------------------------- */
.einmal-anzeige {
  display: grid;
  gap: 8px;
  margin-top: 10px;
}

.einmal-code {
  margin: 0;
  padding: 12px;
  border: 2px dashed var(--accent);
  border-radius: var(--r-md);
  font: 700 26px/1.2 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 2px;
  text-align: center;
  color: var(--text);
  user-select: all;
  -webkit-user-select: all;
}

.konten-liste {
  display: grid;
  gap: 2px;
}

.konto-zeile {
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.konto-zeile.konto-aus {
  opacity: 0.6;
}

.konto-daten {
  margin: 4px 0 6px;
}

.konto-knoepfe {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.konto-knopf {
  width: auto;
  min-height: 34px;
  margin: 0;
  padding: 4px 10px;
  font-size: 13px;
}

.grenze-feld {
  max-width: 120px;
}

.konto-kopf {
  /* Aussehen über strong/.hint */
}

.datenschutz-seite .head h1 {
  margin: 0;
  font-size: 22px;
}

.datenschutz ul {
  margin: 0;
  padding-left: 20px;
  line-height: 1.5;
}

.datenschutz li + li {
  margin-top: 6px;
}

/* Fotos auf der Karte */
.karte-foto {
  cursor: pointer;
}

.karte-foto-zahl {
  font: 700 10px var(--font);
  fill: #fff;
}

.karte-foto-schalter {
  opacity: 0.55;
}

.karte-foto-schalter.an {
  opacity: 1;
}

/* Der Rahmen, der während einer Geste nur verschoben wird (karte.js vorschau). */
.karte-inhalt {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
  will-change: transform;
}

/* Marken dürfen über den Rand hinaus gezeichnet sein — beim Verschieben
   kommen sie sonst abgeschnitten ins Bild. */
.karte-svg {
  overflow: visible;
}

/* Kacheln der vorigen Zoomstufe: liegen unter den neuen, bis diese geladen sind. */
.kachel-alt {
  z-index: -1;
}

.karte-kacheln {
  isolation: isolate;
}

/* Das "+" an den Rand der jetzt 720 px breiten App (siehe oben). */
@media (min-width: 760px) {
  .fab {
    right: max(16px, calc((100vw - 720px) / 2 - 8px));
  }
}

/* --- Flüge: ab / über / an, jede Zeile mit Datum und Uhrzeit ------------- */
.flug-plan {
  display: grid;
  gap: 2px;
  margin: 3px 0 2px;
}

.flug-zeile {
  display: grid;
  grid-template-columns: 40px auto minmax(0, 1fr);
  gap: 2px 8px;
  align-items: baseline;
  font: 500 13px/1.35 var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}

.flug-was {
  font-size: 11px;
  font-weight: 650;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  color: var(--ink-300);
}

.flug-zeit {
  color: var(--text);
  font-weight: 600;
  white-space: nowrap;
}

.flug-ort {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.flug-extra {
  grid-column: 2 / -1;
  font-size: 12px;
  color: var(--ink-300);
}

.route-stopp .route-time + .route-time {
  margin-top: 2px;
}

.stopp {
  display: grid;
  gap: 2px;
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px dashed var(--line);
  border-radius: var(--r-md);
}

.stopp-weg {
  width: auto;
  justify-self: start;
  margin-top: 6px;
}

.stopp-liste,
.card-innen {
  /* Aussehen über .stopp */
}

.route-zwei {
  display: grid;
  gap: 2px;
}

/* Lange Flugtitel mit Pfeilen ("Narita → Singapur → Wien") dürfen umbrechen,
   statt über den Kartenrand hinauszuragen. */
.item-title {
  overflow-wrap: anywhere;
}

/* --- Ausgeliehen (Mietwagen …) ------------------------------------------- */
.ausleihe {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 10px;
  align-items: center;
  margin-top: 8px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  background: var(--surface-2);
  font: 600 13px/1.35 var(--font);
  color: var(--text);
}

.ausleihe-ueberfaellig {
  background: color-mix(in srgb, var(--warn) 18%, var(--surface));
  color: var(--text);
}

.ausleihe-abgegeben {
  color: var(--text-2);
  font-weight: 500;
}

.ausleihe-text {
  flex: 1 1 180px;
}

.ausleihe-knopf {
  width: auto;
  min-height: 36px;
  margin: 0;
  padding: 4px 14px;
  font-size: 14px;
}

.ausleihe-klein {
  width: auto;
  min-height: 30px;
  margin: 0;
  padding: 2px 10px;
  font-size: 12px;
}

.ausleihe-karte {
  display: grid;
  gap: 10px;
}

/* Eingeklappt: eine Zeile "🔑 Mietwagen Okinawa ausgeliehen · zurück …" */
.ausleihe-liste { display: grid; gap: 8px; }
.ausleihe-eintrag[hidden] { display: none; }
.ausleihe-liste .ausleihe-karte { padding-block: 10px; gap: 8px; }
.ausleihe-kurz {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 40px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  text-align: left;
  font: 600 15px/1.3 var(--font);
  box-shadow: none;
}
.ausleihe-kurz-text { flex: 1; display: grid; gap: 1px; }
.ausleihe-kurz-bis { font: 500 13px/1.3 var(--font); color: var(--text-2); }
.ausleihe-pfeil { font-size: 22px; color: var(--text-2); transition: transform .2s; }
.ist-offen .ausleihe-pfeil { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) { .ausleihe-pfeil { transition: none; } }

.ausleihe-titel {
  margin: 0;
  font-size: 16px;
}

.ausleihe-eintrag {
  display: grid;
  gap: 2px;
}

.ausleihe-kommt,
.ausleihe-laeuft {
  /* Grundaussehen von .ausleihe */
}

/* Konto: Arten von Benachrichtigungen, eine je Zeile */
.meldung-arten { display: grid; gap: 2px; }

/* Unterwegs: Karte/Uber unter "Als Nächstes" — groß genug zum Antippen */
.naechst-links { gap: 20px; margin-top: 8px; font-size: 15px; }
.naechst-links a { padding: 4px 0; }

/* Eingang: wozu die Datei hochgeladen wird (Beleg / Idee / Sonstiges) */
.eingang-zweck { width: 100%; }

/* Notfallblatt: Adresse in Landesschrift groß — die zeigt man dem Taxi */
.notfall-ort {
  margin: 4px 0 8px;
  font: 600 19px/1.35 var(--font);
  white-space: pre-line;
}

.notfall-stand {
  margin: 4px 0 0;
}

/* ===========================================================================
   App-Oberfläche (html.ui-app) — ab 25.09.2026, zum Ausprobieren.
   Siehe lib/oberflaeche.js. Alles hier greift NUR mit .ui-app; ohne sie
   bleibt die Seite genau wie vorher.
   =========================================================================== */

/* Großer Titel — ohne .ui-app gar nicht da */
.gross-titel {
  display: none;
}

/* Kein Web-Verhalten beim Antippen: kein grauer Blitz, keine Textmarkierung
   und kein Kontextmenü auf Knöpfen. Inhalte (Notizen, Adressen) bleiben
   markierbar — dort will man kopieren. */
.ui-app button,
.ui-app .reiter,
.ui-app .liste-zeile,
.ui-app .item,
.ui-app .fab {
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}

.ui-app button:active,
.ui-app .liste-zeile:active {
  opacity: 0.6;
}

/* --- Kopfzeile wie in iOS ------------------------------------------------ */
.ui-app .head {
  background: transparent;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  border-bottom: 0.5px solid transparent;
  transition: background 200ms var(--ease), border-color 200ms var(--ease);
}

.ui-app.gescrollt .head {
  background: color-mix(in srgb, var(--bg) 80%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border-bottom-color: var(--line);
}

/* Der kleine Titel erscheint erst, wenn der große weggescrollt ist. */
.ui-app .head h1 {
  font-size: 17px;
  opacity: 0;
  transition: opacity 160ms var(--ease);
}

.ui-app.titel-weg .head h1 {
  opacity: 1;
}

.ui-app .gross-titel {
  display: block;
  margin: -22px 0 14px;
  font: 800 32px/1.12 var(--font);
  letter-spacing: -0.7px;
  text-wrap: balance;
  overflow-wrap: anywhere;
}

/* Kein leerer Kasten links, wo kein Zurück ist */
.ui-app .head .icon-btn.ghosted {
  visibility: hidden;
}

/* --- Leiste unten --------------------------------------------------------- */
.reiterleiste {
  display: none;
}

.ui-app .reiterleiste {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 120px));
  justify-content: center;
  padding: 6px max(8px, env(safe-area-inset-left)) calc(4px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border-top: 0.5px solid var(--line);
  /* bleibt beim Seitenwechsel stehen (View Transitions) */
  view-transition-name: reiterleiste;
}

.ui-app .reiter {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  width: auto;
  min-height: 48px;
  margin: 0;
  padding: 4px 0 2px;
  font: 600 10.5px/1.1 var(--font);
  letter-spacing: 0.1px;
  color: var(--text-2);
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.ui-app .reiter.aktiv {
  color: var(--accent);
}

.reiter-sym,
.sym,
.liste-pfeil {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.reiter-sym {
  width: 26px;
  height: 26px;
}

/* Platz für die Leiste: Inhalt und schwebender Knopf rutschen darüber */
.ui-app body.mit-reitern .app {
  padding-bottom: calc(150px + env(safe-area-inset-bottom));
}

.ui-app body.mit-reitern .fab {
  bottom: calc(76px + env(safe-area-inset-bottom));
}

/* --- Übersicht: was jetzt in den Reitern steckt, fällt weg ---------------- */
.ui-app .unterwegs-jetzt,
.ui-app .hub-links > .tiles.vier,
.ui-app .hub-links > .aktionsbereich {
  display: none;
}

/* Der Name steht schon groß darüber */
.ui-app .hub-cover .trip-name {
  display: none;
}

/* --- Liste wie in den iOS-Einstellungen (Mehr) --------------------------- */
.liste-gruppe {
  margin: 0 0 22px;
}

.liste-titel {
  margin: 0 0 6px 16px;
  font: 600 12.5px/1.3 var(--font);
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--text-2);
}

.liste {
  overflow: hidden;
  background: var(--surface);
  border-radius: var(--r-md);
  box-shadow: var(--e1);
}

.liste-zeile {
  display: flex;
  gap: 12px;
  align-items: center;
  width: 100%;
  min-height: 52px;
  margin: 0;
  padding: 10px 14px;
  text-align: left;
  color: var(--text);
  background: transparent;
  border: 0;
  border-bottom: 0.5px solid var(--line);
  border-radius: 0;
  box-shadow: none;
}

.liste-zeile:last-child {
  border-bottom: 0;
}

.liste-sym {
  display: grid;
  flex: none;
  place-items: center;
  width: 30px;
  height: 30px;
  color: #fff;
  background: var(--ink-500);
  border-radius: 8px;
}

.liste-sym .sym {
  width: 18px;
  height: 18px;
}

.sym-eingang { background: #3478f6; }
.sym-notfall { background: #e5484d; }
.sym-taxi { background: #e8a200; }
.sym-karte,
.sym-kartenLaden { background: #2e9e6b; }
.sym-ideen { background: #d9a21b; }
.sym-packen { background: var(--brand-500); }
.sym-gps { background: #8e5bd6; }
.sym-teilen { background: #3478f6; }
.sym-reisen { background: var(--sun-500); }

.liste-text {
  display: grid;
  flex: 1;
  gap: 1px;
  min-width: 0;
}

.liste-wort {
  font: 550 16px/1.25 var(--font);
}

.liste-unter {
  font: 400 13px/1.3 var(--font);
  color: var(--text-2);
}

.liste-pfeil {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--ink-300);
}

/* --- Dateiwahl: kein rohes "Choose File" --------------------------------- */
.ui-app input[type='file']::file-selector-button {
  margin-right: 10px;
  padding: 8px 14px;
  font: 600 14px/1.2 var(--font);
  color: var(--accent);
  background: var(--accent-soft);
  border: 0;
  border-radius: var(--r-pill);
}

/* --- Seitenwechsel: von rechts herein, zurück von links ------------------ */
@keyframes rein-von-rechts { from { transform: translateX(100%); } }
@keyframes raus-nach-links { to { transform: translateX(-28%); opacity: 0.4; } }
@keyframes rein-von-links { from { transform: translateX(-28%); opacity: 0.4; } }
@keyframes raus-nach-rechts { to { transform: translateX(100%); } }

.ui-app::view-transition-old(root),
.ui-app::view-transition-new(root) {
  animation-duration: 300ms;
  animation-timing-function: cubic-bezier(0.32, 0.72, 0, 1);
}

.ui-app[data-richtung='vor']::view-transition-old(root) { animation-name: raus-nach-links; }
.ui-app[data-richtung='vor']::view-transition-new(root) { animation-name: rein-von-rechts; }
.ui-app[data-richtung='zurueck']::view-transition-old(root) { animation-name: raus-nach-rechts; z-index: 2; }
.ui-app[data-richtung='zurueck']::view-transition-new(root) { animation-name: rein-von-links; }

@media (prefers-reduced-motion: reduce) {
  .ui-app::view-transition-old(root),
  .ui-app::view-transition-new(root) {
    animation: none;
  }
}

.ui-app[data-richtung='reiter']::view-transition-old(root),
.ui-app[data-richtung='reiter']::view-transition-new(root) {
  animation-duration: 140ms;
}

/* Zurück wie in iOS: nur das Zeichen, in der Akzentfarbe, ohne Kasten */
.ui-app .head .icon-btn {
  width: 44px;
  min-width: 44px;
  font-size: 34px;
  font-weight: 400;
  color: var(--accent);
  background: transparent;
  border: 0;
  box-shadow: none;
}

.reiter-wort {
  white-space: nowrap;
}

/* --- Links im Inhalt als kleine Knöpfe (NAVER, Kakao, Karte, Uber) ------- */
.sym-text {
  width: 17px;
  height: 17px;
  flex: none;
}

.ui-app .karten-links {
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 6px;
}

.ui-app .karten-links a {
  display: inline-flex;
  gap: 5px;
  align-items: center;
  min-height: 34px;
  padding: 0 12px;
  font: 600 14px/1 var(--font);
  color: var(--accent);
  text-decoration: none;
  background: var(--accent-soft);
  border-radius: var(--r-pill);
  -webkit-tap-highlight-color: transparent;
}

.ui-app .jetzt-knopf,
.ui-app .sekundaer.breit {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
}

.ui-app .jetzt-knopf .sym-text,
.ui-app .sekundaer.breit .sym-text {
  width: 20px;
  height: 20px;
}

/* Die Leiste unten bewegt sich beim Seitenwechsel nie — auch nicht, wenn
   iOS mitten im Schwung-Scrollen den Übergang startet (verrutschte Leiste
   auf Alex' Bildschirmfoto, 26.09.2026). */
.ui-app::view-transition-group(reiterleiste),
.ui-app::view-transition-old(reiterleiste),
.ui-app::view-transition-new(reiterleiste) {
  animation: none;
}
.ui-app::view-transition-old(reiterleiste) {
  display: none;
}

/* Heute: wie weit es vom eigenen Standort ist */
.entfernung {
  margin-top: 6px;
  font: 500 13.5px/1.3 var(--font);
  color: var(--text-2);
}

.entfernung:empty {
  display: none;
}

.jetzt .entfernung {
  color: rgb(255 255 255 / 0.85);
}

/* --- Zugang zur Unterkunft (Zimmer, Codes, WLAN) ------------------------- */
.zugang-zeilen {
  display: grid;
  gap: 6px;
  margin: 4px 0 6px;
}

.zugang-zeile {
  display: flex;
  flex-wrap: wrap;
  column-gap: 12px;
  align-items: baseline;
  justify-content: space-between;
}

.zugang-wort {
  font: 500 13px/1.3 var(--font);
  color: var(--text-2);
}

.zugang-wert {
  width: auto;
  min-height: 0;
  margin: 0;
  padding: 2px 0;
  font: 700 22px/1.2 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 1px;
  color: var(--text);
  text-align: right;
  background: none;
  border: 0;
  box-shadow: none;
}

.zugang-wert.kopiert {
  color: var(--ok);
}

.zugang-zeilen.klein .zugang-wert {
  font-size: 18px;
}

.zugang-verdeckt {
  font: 700 22px/1.2 ui-monospace, "SF Mono", Menlo, monospace;
  letter-spacing: 3px;
  color: var(--text-2);
}

.zugang-hinweis {
  flex-basis: 100%;
  font: 400 14px/1.4 var(--font);
}

.entsperr-knopf {
  justify-self: start;
}

.entsperr-platz:empty {
  display: none;
}

.entsperr-passwort {
  display: flex;
  gap: 8px;
  align-items: center;
}

.entsperr-passwort input {
  flex: 1;
  min-width: 0;
}

.zugang-feld {
  display: grid;
  gap: 4px;
  margin: 0 0 10px;
}

.zugang-feld > span {
  font: 500 13px/1.3 var(--font);
  color: var(--text-2);
}

.unterkunft-heute {
  display: grid;
  gap: 4px;
  width: 100%;
  text-align: left;
  color: var(--text);
  background: var(--surface);
}

.unterkunft-name {
  font: 650 16px/1.3 var(--font);
}

/* In der dunklen "Jetzt"-Karte und im Notfallblatt heller */
.jetzt .zugang-wert,
.jetzt .zugang-verdeckt {
  color: #fff;
}

.zugang-karte h2 {
  margin-bottom: 8px;
}

/* Warteschlange der App: ein gescheiterter Upload mit Knopf zum Nachreichen */
.warteschlange-fehlerzeile {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: center;
  justify-content: space-between;
  margin: 6px 0;
}

.warteschlange-fehlerzeile .warteschlange-fehler {
  flex: 1 1 200px;
  margin: 0;
}

/* Eingang: Hinweis auf einen vielleicht doppelten Beleg */
.eingang-doppelt {
  color: var(--warn);
  font-weight: 600;
}

/* Heute: Geplantes, dessen Zeit vorbei ist — bleibt sichtbar, bis erledigt */
.offen-heute { display: grid; gap: 12px; }
.offen-eintrag { display: grid; gap: 4px; padding-top: 10px; border-top: 1px solid var(--line); }
.offen-eintrag:first-of-type { border-top: 0; padding-top: 0; }
.offen-kopf { display: grid; gap: 2px; }
.offen-knoepfe { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 4px; }
.offen-knoepfe .mini { width: auto; margin: 0; }

/* Kosten: "Wofür?" — Kategorien mit Balken */
.wofuer { display: grid; gap: 4px; }
.wofuer-zeile {
  display: grid; gap: 5px; width: 100%; margin: 0; padding: 8px 0;
  background: none; border: 0; box-shadow: none; color: var(--text);
  text-align: left; font: inherit; min-height: 0;
}
.wofuer-kopf { display: flex; justify-content: space-between; gap: 12px; }
.wofuer-name { font-weight: 600; }
.wofuer-betrag { font-variant-numeric: tabular-nums; color: var(--text-2); white-space: nowrap; }
.wofuer-balken { display: block; height: 8px; border-radius: 4px; background: var(--line); overflow: hidden; }
.wofuer-balken i { display: block; height: 100%; border-radius: 4px; background: var(--accent); }
.wofuer-zeile.ist-aktiv .wofuer-name { color: var(--accent); }
.wofuer-summe { display: flex; justify-content: space-between; padding-top: 8px; border-top: 1px solid var(--line); font-variant-numeric: tabular-nums; }

/* Ausgabe: "Wo bin ich?" — Lokale in der Nähe */
.umgebung { display: grid; gap: 6px; margin: 8px 0 4px; }
.umgebung .mini { justify-self: start; width: auto; margin: 0; }
.umgebung-liste:empty { display: none; }

/* Hochladen: Fortschritt mit Balken (App, ab Build 7) */
.fortschritt-block { display: grid; gap: 4px; margin: 6px 0; }
.fortschritt-text { margin: 0; font: 600 14px/1.35 var(--font); font-variant-numeric: tabular-nums; }
.fortschritt { height: 8px; border-radius: 4px; background: var(--line); overflow: hidden; }
.fortschritt i { display: block; height: 100%; background: var(--accent); border-radius: 4px; transition: width .4s; }
@media (prefers-reduced-motion: reduce) { .fortschritt i { transition: none; } }

/* Galerie: ⭐ Beste und Grund fürs Aussortieren auf der Kachel (29.09.2026) */
.medien-beste { position: absolute; top: 4px; left: 4px; font-size: 16px; text-shadow: 0 1px 3px rgba(0,0,0,.6); }
.medien-grund {
  position: absolute; left: 4px; right: 4px; bottom: 4px; padding: 2px 6px; border-radius: 6px;
  background: rgba(0,0,0,.62); color: #fff; font: 600 11px/1.3 var(--font); text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ===========================================================================
   App-Oberfläche auf großen Bildschirmen (Mac, iPad quer, Laptop) — 30.09.2026
   Alex: "die app ansicht ist für größere bildschirme nicht passend".
   Statt Leiste unten: Seitenleiste links, Inhalt breiter.
   =========================================================================== */
@media (min-width: 1000px) {
  .ui-app .reiterleiste {
    top: 0;
    bottom: 0;
    right: auto;
    width: 220px;
    grid-template-columns: 1fr;
    align-content: start;
    gap: 2px;
    padding: 72px 12px 16px;
    border-top: 0;
    border-right: 0.5px solid var(--line);
  }
  .ui-app .reiter {
    flex-direction: row;
    justify-content: flex-start;
    gap: 12px;
    min-height: 44px;
    padding: 8px 14px;
    border-radius: 10px;
    font: 600 15px/1.2 var(--font);
    letter-spacing: 0;
  }
  .ui-app .reiter.aktiv { background: color-mix(in srgb, var(--accent) 12%, transparent); }
  .ui-app .reiter-sym { width: 22px; height: 22px; }
  .ui-app body.mit-reitern { padding-left: 220px; }
  .ui-app body.mit-reitern .app {
    max-width: 980px;
    padding-bottom: calc(60px + env(safe-area-inset-bottom));
  }
  /* Plan mit Karte daneben (30.09.2026): die 980 px oben überstimmten die
     1600 px der Übersicht — am MacBook blieb links und rechts viel leer. */
  .ui-app body.mit-reitern .app:has(> .hub-seite) {
    max-width: min(1600px, 100%);
  }
  .ui-app body.mit-reitern .fab {
    bottom: 28px;
    left: auto;
    right: max(16px, calc((100vw - 220px - 980px) / 2 + 20px));
  }
  .ui-app .medien-gitter { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }
}

/* Heute: Ort als Überschrift, Mietwagen + Hotel nebeneinander (30.09.2026) */
.ort-kopf { display: grid; gap: 2px; margin: 0 0 12px; }
.ort-kopf-name { font: 700 22px/1.2 var(--font); color: var(--text); }
.ort-kopf-zeile { font: 500 14px/1.35 var(--font); color: var(--text-2); }
.fix-raster { display: grid; gap: 10px; margin-bottom: 12px; align-items: start; }
.fix-raster > .card, .fix-raster .ausleihe-liste .card { margin: 0; }
@media (min-width: 700px) { .fix-raster { grid-template-columns: 1fr 1fr; } }
.unterkunft-heute.kompakt { display: grid; gap: 8px; padding: 12px 16px; }
.unterkunft-kopf { display: grid; gap: 2px; }
.unterkunft-heute.kompakt .unterkunft-name { font: 600 15px/1.3 var(--font); }
.unterkunft-heute.kompakt .naechst-links { margin-top: 0; }
.unterkunft-mehr summary { cursor: pointer; font: 600 13px/1.3 var(--font); color: var(--text-2); }

/*
 * Galerie "Nach Tagen" (30.09.2026): Tage außerhalb des Bildschirms nicht
 * auslegen und nicht zeichnen. Mit 4.500 Kacheln hielt jedes Umschalten das
 * iPhone sekundenlang fest. `auto 600px` merkt sich die echte Höhe, sobald ein
 * Tag einmal gezeichnet war — die Scrollleiste springt dann nicht.
 */
.medien-tag {
  content-visibility: auto;
  contain-intrinsic-size: auto 600px;
}

/* Frage nach Mitteilungen beim Start (lib/pushfrage.js, 30.09.2026) */
.push-frage {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(84px + env(safe-area-inset-bottom));
  z-index: 60;
  max-width: 520px;
  margin: 0 auto;
  padding: 14px 16px 12px;
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--e3);
  display: grid;
  gap: 6px;
}
.push-frage-titel { margin: 0; font: 700 16px/1.3 var(--font); color: var(--text); }
.push-frage-text { margin: 0; font: 400 14px/1.4 var(--font); color: var(--text-2); }
.push-frage-knoepfe { display: flex; justify-content: flex-end; gap: 8px; margin-top: 4px; }
.push-frage-knoepfe .mini { width: auto; margin: 0; }

/* Plan mit Karte: der "+ Eintrag"-Knopf nicht mitten auf die Karte */
@media (min-width: 1100px) {
  .ui-app body.mit-reitern:has(.hub-seite) .fab { right: 28px; }
}

/* 🧭 Navigation in der Plan-Übersicht (timeline.js hinKnopf, 01.10.2026) */
.hin-knopf {
  display: inline-flex;
  align-items: center;
  justify-self: start;   /* .item-body ist ein Grid — sonst über die volle Breite */
  width: fit-content;
  gap: 4px;
  margin-top: 6px;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  /* --accent-ink ist die Schrift AUF der Akzentfarbe (hell weiß) — auf dem
     zarten Grund war sie unlesbar (Alex, 02.10.2026). */
  color: var(--accent);
  font: 600 13px/1.3 var(--font);
  cursor: pointer;
}
.hin-knopf:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Plan-Kachel: Zeit dort und Anreise (timeline.js, 02.10.2026) */
.item-dauer,
.item-anreise {
  font: 400 13px/1.35 var(--font);
  color: var(--text-2);
}
.item-anreise { overflow-wrap: anywhere; }

/* 🃏 Kartenläden auf der Karte (karte.js, 02.10.2026) */
.karte-laden { cursor: pointer; }
.karte-laden-zeichen { pointer-events: none; }
.karte-laden-info {
  position: absolute;
  left: 10px;
  right: 10px;
  bottom: 34px;
  z-index: 5;
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  border-radius: var(--r-md);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--e2);
  color: var(--text);
}
.karte-laden-info[hidden] { display: none; }
.karte-laden-kopf { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.karte-laden-zu { width: auto; min-height: 28px; margin: 0; padding: 2px 8px; background: none; border: 0; color: var(--text-2); font-size: 16px; }
.karte-laden-knoepfe { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.karte-laden-knoepfe .mini { width: auto; margin: 0; }
.karte-du { pointer-events: none; }
.tcg-hinweis { border-left: 4px solid #7b4bb4; }

/* Großansicht: ❤️ und 📤 oben (galerie.js kopfKnoepfe, 02.10.2026) */
.b-kopf-knoepfe { display: flex; gap: 4px; }
.b-hinweis {
  position: absolute;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom));
  transform: translateX(-50%);
  max-width: calc(100% - 32px);
  padding: 8px 14px;
  border-radius: var(--r-pill);
  background: rgb(0 0 0 / 0.75);
  color: #fff;
  font: 600 14px/1.3 var(--font);
  z-index: 4;
}
.b-hinweis[hidden] { display: none; }

/* Galerie: Auswählen + Tag teilen (02.10.2026) */
.medien-kachel.gewaehlt { outline: 3px solid var(--accent); outline-offset: -3px; }
.medien-kachel.gewaehlt::after {
  content: '✓';
  position: absolute; top: 6px; left: 6px;
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: var(--accent-ink);
  font: 700 14px/1 var(--font);
}
.auswahl-leiste {
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(84px + env(safe-area-inset-bottom));
  z-index: 50;
  max-width: 560px; margin: 0 auto;
  display: grid; gap: 4px;
  padding: 10px 14px;
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--e3);
  color: var(--text);
}
.auswahl-zeile { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.medien-tagtext { display: grid; gap: 6px; margin: 4px 0 10px; }
.tag-text { margin: 0; white-space: pre-wrap; font: 400 14px/1.45 var(--font); color: var(--text); }
.tag-text.leer { color: var(--text-2); font-style: italic; }
.tag-knoepfe { display: flex; flex-wrap: wrap; gap: 6px; }
.tag-text-feld { width: 100%; font: 400 15px/1.4 var(--font); }

/* Galerie "Nach Tagen": jeder Tag zugeklappt, mit Kurzbeschreibung (galerie.js nachTagen, 04.10.2026) */
.medien-tag-kopf {
  display: grid;
  gap: 3px;
}
details.medien-tag > summary.medien-tag-kopf::after { content: none; }
.medien-tag-zeile {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.medien-tag-name { font: 650 16px/1.3 var(--font); color: var(--text); }
.medien-tag-zahl {
  font: 500 13px/1.3 var(--font);
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.medien-tag-zahl::after { content: "  ›"; }
details.medien-tag[open] .medien-tag-zahl::after { content: "  ⌄"; }
.medien-tag-orte {
  font: 400 13px/1.35 var(--font);
  color: var(--text-2);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
details.medien-tag[open] > .medien-tag-kopf { margin-bottom: 10px; }
/* zugeklappt: nur die Kopfzeile, keine 600px-Platzhalterhöhe */
details.medien-tag:not([open]) { contain-intrinsic-size: auto 60px; }

/* Konto → 🃏 Kartenläden einstellen (account.js, 04.10.2026) */
.tcg-filter { margin-top: 12px; }
.tcg-weite { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 10px 0 0; font: 400 14px/1.4 var(--font); text-transform: none; letter-spacing: normal; color: var(--text); }
.tcg-ketten .check { padding-top: 4px; padding-bottom: 4px; min-height: 0; }
.tcg-gruppe { display: grid; gap: 2px; margin-top: 10px; }
.tcg-ketten { display: grid; gap: 0; padding-left: 26px; }
.tcg-ketten .check { font-size: 14px; }
.tcg-aus { display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 14px; }
/* Auswahl-Leiste: Album/Leeren/Teilen nebeneinander, umbrechend (galerie.js, 05.10.2026) */
.auswahl-knoepfe { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }
/* „Wo seid ihr?“-Link (gps.js woKarte, 05.10.2026) */
.wo-neu { display: grid; gap: 6px; margin: 4px 0 12px; }
.wo-liste { display: grid; gap: 6px; }
.wo-zeile { display: flex; justify-content: space-between; align-items: center; gap: 10px; font-size: 14px; }
.wo-zeile span { flex: 1; min-width: 0; }
.wo-zeile button { flex: none; }

/* Heute: das Tagesprogramm als Liste (10.10.2026) */
.programm-heute { display: grid; gap: 2px; }
.programm-tag { font: 650 16px/1.3 var(--font); margin: 2px 0 8px; text-wrap: balance; }
.programm-punkt { display: grid; grid-template-columns: 92px 1fr; column-gap: 10px; row-gap: 4px; padding: 10px 0; border-top: 1px solid var(--line); cursor: pointer; }
.programm-punkt > .programm-info, .programm-punkt > .karten-links { grid-column: 2; margin: 0; }
.programm-zeit { font: 600 14px/1.35 var(--font); font-variant-numeric: tabular-nums; color: var(--text-2); }
.programm-titel { font: 500 15px/1.35 var(--font); overflow-wrap: anywhere; }
.programm-punkt.dran .programm-titel { font-weight: 700; }
.programm-punkt.dran .programm-zeit { color: var(--accent); }
.programm-punkt.fertig .programm-titel, .programm-punkt.vorbei .programm-titel { color: var(--text-2); }
.programm-punkt.fertig .programm-titel { text-decoration: line-through; }
.programm-marke { display: inline-block; margin-left: 8px; padding: 1px 7px; font: 700 10.5px/1.5 var(--font); letter-spacing: 0.4px; text-transform: uppercase; color: #fff; background: var(--accent); border-radius: 999px; vertical-align: 2px; }
