@charset "UTF-8";
/* ============================================================================
   Serpa - Anordnung der App (Hochformat)

   Diese Datei beschreibt, WIE DIE SEITEN AUFGEBAUT sind: die Schublade, die
   untere Leiste, die Garage, der Freisteller, die Karte.

   Die gemeinsame Designsprache - Schrift, Farben, Abstaende, Radien - steht
   in design.css und wird VOR dieser Datei geladen. Wer hier eine Farbe oder
   ein Mass fest eintraegt statt eine Marke zu benutzen, baut genau die
   Doppelung ein, die die Trennung verhindern soll.

   ALLES HIER IST AUF HOCHFORMAT AUSGELEGT. Ein Handy in der Hand, ein Daumen,
   eine Spalte. Die spaetere Webseite bekommt eine eigene Datei fuer das
   Querformat und benutzt dieselbe design.css.
   ============================================================================ */

/* ---------- Startmenü & "Meine Touren" ----------
   Beide sind einfache, zentrierte Vollbild-Ansichten - der Einstieg vor
   dem eigentlichen Routenplaner (siehe .app-layout weiter unten), der
   anfangs per [hidden] versteckt ist. */
.start-screen {
  height: calc(100% - var(--nav-raum));
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  /* Konto, Passwort und "Meine Touren" haben kein eigenes Bild. Damit das
     Glas darauf ueberhaupt etwas zu brechen hat, liegt hier eine
     weichgezeichnete Fassung des Startfotos. Wichtig ist das Mass: bei zu
     starker Unschaerfe bleibt nur noch eine graue Flaeche uebrig, und dann
     hat das Glas wieder nichts, worueber es liegen koennte. Die Maschine
     muss also noch zu erahnen sein. Fertig weichgezeichnet in der Datei,
     nicht per CSS - so muss der Browser zur Laufzeit nichts rechnen. */
  background:
    linear-gradient(to bottom,
      var(--schatten-weich) 0%,
      var(--schatten-weich) 30%,
      var(--schatten-mittel) 55%,
      var(--schatten-tief) 78%,
      var(--schatten-voll) 100%),
    url('img/hintergrund-weich.jpg') center / cover no-repeat fixed;
}

.start-screen-inner {
  width: 320px;
  max-width: 100%;
  /* Die Formulare liegen jetzt auf einer Glasplatte statt frei im Raum. */
  padding: var(--s5);
  border-radius: var(--r-lg);
  background: var(--glas-hauch);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  border: 1px solid var(--glas-rand);
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    inset 0 -1px 0 var(--schatten-weich),
    0 16px 40px var(--schatten-mittel);
}
/* Auf Listenbildschirmen waere so eine Platte im Weg - dort ist die Liste
   selbst aus Glas, siehe .saved-list li. */
.listen-screen .start-screen-inner {
  background: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 0;
  box-shadow: none;
  border-radius: 0;
}
.start-screen-inner .sub { margin: 0 0 32px; }
.start-screen-inner h2 {
  margin: 0 0 var(--s4);
  font-family: var(--schrift-display);
  font-weight: 700;
  font-size: 26px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.start-screen-inner .saved-list { text-align: left; }

.back-btn { margin-bottom: var(--s5); }

/* ---------- Rechtliches ----------
   Der Fusszeilen-Link zu Impressum und Datenschutz. Dezent wie auf jeder
   Webseite, aber bewusst NICHT unlesbar: Die Angaben muessen "leicht
   erkennbar" sein (§ 5 DDG). Wer sie kleiner oder blasser macht als hier,
   erzeugt genau die Angreifbarkeit, die er vermeiden wollte. */
.rechts-fuss {
  margin: var(--s5) 0 var(--s3);
  text-align: center;
}
.rechts-fuss .linkbtn {
  font-size: 13px;
  color: var(--muted);
}
.rechts-fuss .linkbtn:hover { color: var(--text); }

/* Der Lauftext der Rechtstexte. Etwas enger gesetzt als der Rest der App,
   weil hier am Stueck gelesen wird statt auf einen Blick erfasst. */
.rechts-text { font-size: 14px; line-height: 1.6; }
.rechts-text p { margin: 0 0 var(--s3); }
.rechts-text .label { margin-top: var(--s4); }
.rechts-text a { color: var(--accent-hell); }

/* ---------- Untere Navigationsleiste ----------
   Fest am unteren Rand. Die Bildschirme darueber bekommen ihre Hoehe
   ueber calc(100% - var(--nav-raum)), damit nichts hinter der Leiste
   verschwindet - ein einfaches padding am body wuerde bei Elementen mit
   height:100% nicht helfen, die wuerden unten herausragen.

   env(safe-area-inset-bottom) ist der Streifen, den iPhones unten fuer
   die Wisch-Leiste reservieren. Ohne den Zuschlag saessen die Beschriftungen
   darunter. */
/* Elemente, die nur die Querformat-Kopfleiste braucht (Schriftzug,
   Rechtliches-Link, Konto-Knopf rechts). Im Hochformat unsichtbar.
   BEWUSST eine Klasse und nicht das hidden-Attribut: hidden gewinnt per
   !important (design.css) und liesse sich aus quer.css nicht aufheben. */
.nur-quer { display: none; }

.haupt-nav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 900;
  display: flex;
  height: calc(var(--nav-h) + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  /* Glas statt matter Flaeche: Auf dem Startbildschirm liegt das Foto
     darunter und scheint verwischt durch, auf den Kartenbildschirmen die
     Karte. Genau davon lebt der Effekt - deshalb hier eine sehr dunkle
     Fuellung statt einer hellen, sonst waere die Leiste ueber heller
     Karte nicht mehr zu lesen. */
  background: var(--schatten-tief);
  backdrop-filter: blur(28px) saturate(170%);
  -webkit-backdrop-filter: blur(28px) saturate(170%);
  border-top: 1px solid var(--glas-hell);
  /* Abgerundete Oberkante wie im Inspirationsbild: Die Leiste liest sich
     dadurch als aufgelegte Glasscheibe, nicht als abgeschnittener Rand.
     Der Schatten nach oben loest sie zusaetzlich vom Inhalt. */
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    0 -8px 24px var(--schatten-weich);
}

.nav-tab {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  padding: 0;
  font-family: var(--schrift-display);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  transition: color 0.15s ease, transform 0.15s cubic-bezier(0.2,0.8,0.2,1);
}
.nav-tab:active { transform: scale(0.92); }
.nav-tab .ic { width: 22px; height: 22px; }
.nav-tab.aktiv { color: var(--accent-hell); }
.nav-tab:hover:not(.aktiv) { color: var(--text); }

/* Solange die Leiste sichtbar ist, halten alle Bildschirme unten Platz frei. */
body.mit-nav { --nav-raum: calc(var(--nav-h) + env(safe-area-inset-bottom)); }

/* ---------- Glas ----------
   Das Grundrezept, aus dem alle Glasflaechen gebaut sind. Vier Schichten
   uebereinander, jede mit einer Aufgabe:

     1. Eine sehr helle, fast durchsichtige Fuellung. Sie faerbt nichts,
        sie hebt nur an.
     2. backdrop-filter: verwischt und saettigt, was DAHINTER liegt. Das
        ist der eigentliche Glaseffekt - ohne etwas dahinter passiert
        nichts, deshalb sitzt Glas hier immer ueber dem Bild.
     3. Zwei innere Linien: oben eine helle Lichtkante, unten eine dunkle.
        Genau das laesst eine Flaeche wie eine Scheibe mit Dicke wirken
        statt wie ein aufgemalter Kasten.
     4. Ein weicher Schlagschatten nach aussen, damit sie abhebt.

   -webkit-backdrop-filter muss mit dabeistehen, sonst bleibt der Effekt
   auf iPhones aus - und das ist die Hauptzielgruppe. */
.glas {
  background: var(--glas-hauch);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--glas-rand);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    inset 0 -1px 0 var(--schatten-weich),
    0 10px 30px var(--schatten-mittel);
}

/* Runder Glasknopf, z.B. fuer das Konto oben rechts. */
.glas-rund {
  /* position und overflow sind Voraussetzung fuer das Profilbild: .rund-bild
     liegt mit inset:0 darin und wird vom overflow rund beschnitten. */
  position: relative;
  overflow: hidden;
  width: 46px; height: 46px;
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  cursor: pointer;
  color: var(--text);
  background: var(--glas-hell);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--glas-heller);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    0 6px 18px var(--schatten-weich);
  transition: transform 0.16s cubic-bezier(0.2, 0.8, 0.2, 1), background 0.16s ease;
}
.glas-rund:hover { background: var(--glas-rand); }
.glas-rund:active { transform: scale(0.94); }

/* Die blasse Fassung fuer den zweiten Knopf einer Gruppe. Gleich gross,
   nur zurueckhaltender - so bleibt die Trefferflaeche voll erhalten und die
   Rangfolge ist trotzdem auf den ersten Blick da. */
.glas-rund.blass {
  background: var(--glas-hauch);
  border-color: var(--glas-hell);
  color: color-mix(in srgb, white 72%, transparent);
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    0 4px 12px var(--schatten-weich);
}
.glas-rund.blass:hover { background: var(--glas-hell); color: var(--text); }

/* Wenn das Neuladen laeuft, dreht sich der Pfeil - sonst tippt man und ist
   sich einen Wimpernschlag lang nicht sicher, ob etwas passiert ist. */
.glas-rund.laedt .ic { animation: knopf-drehen 0.8s linear infinite; }
@keyframes knopf-drehen {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ---------- Kopfzeile ----------
   Die beiden runden Knoepfe oben rechts (Neu laden, Konto). Sie duerfen nie
   schrumpfen - lieber bricht der Schriftzug daneben um, als dass eine
   Trefferflaeche kleiner wird. */
.kopf-knoepfe {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--s2);
}

/* ---------- Kacheln ----------
   Jede Kachel traegt ihr eigenes Bild (ueber die Marke --kachel-bild aus
   dem HTML) und liegt als Glasplatte darauf. Der Aufbau von hinten nach
   vorn: Bild, dunkler Schleier fuer die Lesbarkeit, Glanzstreifen, Inhalt.

   Bild und Schleier stecken in ::before und ::after, damit das HTML nicht
   mit reinen Gestaltungselementen zugestellt wird. */
/* Das Raster des Menues unten in der Garage. Bewusst OHNE Zeilenangabe:
   Die Garage scrollt, es gibt also keinen "Rest", den die Kacheln fuellen
   koennten. Die Hoehe kommt aus dem Inhalt, die Untergrenze aus .kachel. */
.garage-menue-raster {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s3);
}
/* Eine Kachel ueber beide Spalten - fuer eine ungerade Kachelzahl, damit
   im Raster keine Luecke bleibt. Gesetzt wird die Klasse von
   wendeShopSchalterAn() in app.js. */
.kachel--breit { grid-column: 1 / -1; }
.kachel {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 116px;
  padding: var(--s3);
  border-radius: var(--r-lg);
  border: 1px solid var(--glas-rand);
  background: var(--surface-2);
  color: var(--text);
  text-align: left;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    inset 0 -1px 0 var(--schatten-weich),
    0 12px 32px var(--schatten-mittel);
  transition: transform 0.18s cubic-bezier(0.2, 0.8, 0.2, 1),
              box-shadow 0.18s ease;
}

/* Schicht 1 und 2: das Bild, darueber der Schleier. Der Schleier ist unten
   links am dichtesten - genau dort steht der Text. */
.kachel::before {
  content: "";
  position: absolute; inset: 0;
  z-index: -2;
  background-image: var(--kachel-bild);
  background-size: cover;
  /* Der Ausschnitt ist je Kachel einstellbar. Gebraucht wird das von der
     Garage-Kachel: Sie zeigt das hochformatige Werkstattbild, und davon
     soll der Streifen mit dem Drehteller zu sehen sein, nicht die Mitte. */
  background-position: var(--kachel-lage, center);
  transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.kachel::after {
  content: "";
  position: absolute; inset: 0;
  z-index: -1;
  background:
    /* Kraeftiger Schleier von unten. Er reicht hoeher und ist unten
       dichter als vorher - in der Vorlage steht der Text auf einer klar
       abgedunkelten Flaeche, nicht auf dem blanken Foto. */
    linear-gradient(to top,
      color-mix(in srgb, black 97%, transparent) 0%,
      color-mix(in srgb, black 92%, transparent) 22%,
      color-mix(in srgb, black 72%, transparent) 45%,
      color-mix(in srgb, black 38%, transparent) 68%,
      color-mix(in srgb, black 10%, transparent) 100%),
    /* Der Glanzstreifen quer darueber bleibt, er macht das Glas aus. */
    linear-gradient(115deg, var(--glas-heller) 0%, var(--glas-hauch) 26%, transparent 52%);
}

/* Beim Antippen gibt die Kachel nach und das Bild darunter zieht leicht
   heran. Diese Verzoegerung ist das, was den Eindruck von Tiefe erzeugt:
   Glas und Bild bewegen sich nicht gleich schnell. */
.kachel:hover { transform: translateY(-2px); box-shadow: inset 0 1px 0 var(--glas-licht), inset 0 -1px 0 var(--schatten-weich), 0 18px 40px var(--schatten-mittel); }
.kachel:hover::before { transform: scale(1.06); }
.kachel:active { transform: scale(0.985); }

.kachel-inhalt {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  min-width: 0;              /* ohne das bricht langer Text nicht um, sondern
                                schiebt die Kachel breiter */
}
.kachel-symbol {
  color: var(--accent-hell);
  filter: drop-shadow(0 2px 8px var(--schatten-voll));
}
.kachel-text { display: flex; flex-direction: column; gap: 3px; }
.kachel-titel {
  font-family: var(--schrift-display);
  /* clamp() heisst: mindestens 13px, hoechstens 18px, dazwischen 4.1% der
     Bildschirmbreite. Damit passt "ROUTENPLANER" auf ein iPhone SE genauso
     in eine Zeile wie auf ein grosses Geraet - eine feste Groesse hatte hier
     um genau einen Pixel nicht gereicht und das Wort zerrissen. */
  font-size: clamp(13px, 4.1vw, 18px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0;
  line-height: 1.08;
  text-shadow: 0 1px 8px var(--schatten-voll), 0 1px 2px var(--schatten-tief);
  /* break-word statt anywhere: bricht nur, wenn ein einzelnes Wort wirklich
     nicht passt. "anywhere" hatte mitten im Wort getrennt (ROUTENPL/ANER). */
  overflow-wrap: break-word;
}
.kachel-sub {
  font-size: 13px;
  color: color-mix(in srgb, white 85%, transparent);
  line-height: 1.35;
  text-shadow: 0 1px 6px var(--schatten-voll);
  padding-right: 30px;   /* nur die Unterzeile laeuft in den Pfeil hinein */
}

.kachel-pfeil {
  position: absolute;
  right: var(--s3); bottom: var(--s3);
  color: var(--accent-hell);
  font-size: 20px;
  line-height: 1;
  transition: transform 0.18s ease;
}
.kachel:hover .kachel-pfeil { transform: translateX(4px); }

/* Bildschirme mit einer Liste statt eines Formulars: Inhalt oben statt
   senkrecht zentriert, und ueber die volle Breite. Ein Formular in der
   Mitte wirkt ruhig, eine Liste in der Mitte wirkt verloren. */
.listen-screen { align-items: stretch; justify-content: flex-start; text-align: left; overflow-y: auto; }
.listen-screen .start-screen-inner {
  width: 100%;
  padding: var(--s5) var(--s4);
  padding-top: max(var(--s5), env(safe-area-inset-top) + var(--s3));
}
.listen-screen .back-btn { flex: 0 0 auto; align-self: flex-start; }

/* ---------- Konto ----------
   Ein Knopf, der wie ein Textlink aussieht. Gebraucht für die kleinen
   Nebenwege ("Passwort vergessen", "Abmelden"), die keinen vollwertigen
   Knopf verdienen, aber trotzdem anklickbar sein müssen. Bewusst ein
   <button> und kein <a>, weil nichts verlinkt wird. */
.linkbtn {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent-hell);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}
.linkbtn:hover { color: var(--text); }

/* ---------- Profil ----------
   Das Konto sitzt hinter dem Profilsymbol oben rechts. */

/* Das Profilbild IM runden Knopf oben rechts. Es fuellt ihn ganz aus, das
   Symbol darunter tritt dafuer zurueck (konto.js schaltet um). */
.rund-bild {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
}

.profil-kopf {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s2);
  margin-bottom: var(--s5);
}
.profil-kopf h2 { margin: 0; }
.profil-kopf .sub { margin: 0; }

/* Das grosse runde Profilbild. Es ist ein KNOPF, kein Bild: Ein Druck
   darauf waehlt ein neues. Das Kamerazeichen an der Ecke sagt das ohne
   Worte - und es ist der einzige Weg, spaeter noch ein Bild nachzureichen,
   denn beim Anlegen des Kontos ist es freiwillig. */
.profil-bild {
  position: relative;
  width: 96px; height: 96px;
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  cursor: pointer;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--glas-rand);
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    0 8px 22px var(--schatten-mittel);
  transition: transform 0.16s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.profil-bild:active { transform: scale(0.96); }
.profil-bild img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  border-radius: 50%;
  object-fit: cover;
}
.profil-platzhalter { width: 44px; height: 44px; }

/* Das Kamerazeichen sitzt halb in der Kante des Bildes, so wie das
   Abzeichen am Hinweis in der Garage - dadurch gehoert es dazu, statt
   danebenzuschweben. */
.profil-bild-marke {
  position: absolute;
  right: -2px; bottom: -2px;
  width: 30px; height: 30px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--accent-ink);
  background: var(--accent);
  border: 2px solid var(--bg);
}

.profil-name-aendern { margin-bottom: var(--s4); }
#profilNameFeld { margin-top: var(--s2); text-align: left; }
#profilNameFeld input {
  width: 100%;
  padding: 12px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hell);
  color: var(--text);
  font: inherit;
  box-shadow:
    inset 0 1px 0 var(--glas-rand),
    inset 0 2px 5px var(--schatten-hauch);
}
#profilNameFeld input:focus { outline: none; border-color: var(--accent-hell); }
#profilNameFeld .btn { margin-top: var(--s2); }

.profil-liste {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
  padding-top: var(--s4);
  border-top: 1px solid var(--line);
}

/* Die Rueckmeldung unter einem Namensfeld: gruen wenn frei, rot wenn
   vergeben. Gruen ist hier ausnahmsweise erlaubt - es ist keine Deko,
   sondern die Antwort auf eine Ja-Nein-Frage. */
.namen-hinweis {
  margin: 0 0 6px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--muted);
}
.namen-hinweis.gut { color: var(--good); }
.namen-hinweis.fehler { color: var(--danger); }

.freiwillig {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  opacity: 0.7;
}

/* Der Knopf zum Bildaussuchen im Anmeldeformular: kleine runde Vorschau
   plus Beschriftung. Als Zeile und nicht als grosse Flaeche - das Bild ist
   freiwillig und soll nicht wichtiger aussehen als das Passwort. */
.bild-waehlen {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2);
  margin-bottom: 6px;
  border-radius: var(--r-md);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hell);
  color: var(--muted);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.bild-waehlen:hover { color: var(--text); }
.bild-waehlen-kreis {
  position: relative;
  width: 42px; height: 42px;
  flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--surface-2);
  overflow: hidden;
}
.bild-waehlen-kreis img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

.konto-formular {
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: left;
  margin-bottom: 14px;
}
.konto-formular label { font-size: 12px; color: var(--muted); }
.konto-formular input {
  padding: 12px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hell);
  color: var(--text);
  font: inherit;
  margin-bottom: 6px;
  box-shadow:
    inset 0 1px 0 var(--glas-rand),
    inset 0 2px 5px var(--schatten-hauch);
}
.konto-formular input:focus { outline: none; border-color: var(--accent-hell); }
.konto-formular .btn { margin-top: 6px; padding: 13px; font-size: 16px; }

/* Die Felder fuers Anlegen stecken in einem eigenen Kasten, damit sie sich
   zusammen aus- und einblenden lassen. Der Kasten braucht die Spaltenordnung
   noch einmal: Als EIN Flex-Kind des Formulars gibt er sie nicht an seine
   eigenen Kinder weiter, und Beschriftung und Feld stuenden nebeneinander. */
#kontoNeuFelder {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.konto-meldung {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.45;
  color: var(--muted);
}
.konto-meldung.fehler { color: var(--danger); }

.konto-wechsel { margin-top: 22px; font-size: 13px; color: var(--muted); }

/* --- Konto löschen --------------------------------------------------------
   Rot ist hier keine Deko, sondern die einzige Stelle in der App, an der
   die Farbe eine Warnung ist. Deshalb bekommt sie nur der eine Knopf, der
   wirklich etwas unwiderruflich macht - würde noch etwas anderes daneben
   rot leuchten, wäre die Warnung nichts mehr wert. */

.linkbtn.gefahr { color: var(--danger); }
.linkbtn.gefahr:hover { color: var(--text); }

/* Derselbe Aufbau wie .btn, nur in Rot: gleicher Verlauf von hell nach
   dunkel, gleiche Lichtkante. Der Knopf soll sich anfühlen wie die
   anderen und sich nur in der Farbe unterscheiden. */
.btn.gefahr {
  background: linear-gradient(to bottom, var(--danger-glanz), var(--danger) 55%, var(--danger-tief));
  color: var(--danger-ink);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    inset 0 -1px 0 var(--schatten-hauch),
    0 4px 14px color-mix(in srgb, var(--danger) 28%, transparent);
}
.btn.gefahr:hover { background: var(--danger-tief); color: var(--accent-ink); }

.loeschen-ueberschrift {
  margin: 18px 0 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  text-align: left;
}

/* Die Aufzählung dessen, was verschwindet. Linksbündig und mit Punkten,
   damit sie als Liste gelesen wird und nicht als Fließtext überflogen. */
.loeschen-liste {
  margin: 0 0 16px;
  padding-left: 20px;
  text-align: left;
  font-size: 13.5px;
  line-height: 1.7;
  color: var(--muted);
}
.loeschen-liste strong { color: var(--text); font-weight: 600; }

/* Kurzer Hinweis über den Auswertungszahlen einer sehr kurzen Ausfahrt.
   Gedämpft und nicht rot: Es ist kein Fehler, nur eine Einordnung. */
.kurz-hinweis {
  margin: 0 0 14px;
  padding: 10px 12px;
  border-radius: 12px;
  border: 1px solid var(--glas-hell);
  background: var(--glas-hauch);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.45;
  box-shadow: inset 0 1px 0 var(--glas-rand);
}

/* ---------- Routenplaner: zwei Spalten, Bedienfeld links, Karte rechts ---------- */
.app-layout {
  height: calc(100% - var(--nav-raum));
  display: flex;
}

.panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--line);
}
.back-to-start {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  font-size: 15px;
  cursor: pointer;
}
.back-to-start:hover { border-color: var(--muted); color: var(--text); }

/* Griff zum Aufziehen des Bedienfelds - nur auf schmalen Bildschirmen
   sichtbar (display:flex kommt erst aus der Media Query weiter unten).
   Bewusst ein eigenes Element AUSSERHALB des scrollenden Bereichs
   (.panel-scroll), nicht per position:sticky darin - diese Kombination
   (sticky + abgerundete Ecken + Scroll auf demselben Element) fuehrt in
   Safari zu doppelt gezeichneten Inhalten beim Scrollen. */
.panel-grip {
  display: none;
  width: 100%;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  padding: 10px 0;
  border: 0;
  background: transparent;
  cursor: grab;
  touch-action: none;   /* verhindert, dass iOS beim Ziehen gleichzeitig die Seite mitscrollt */
}
.panel-grip:active { cursor: grabbing; }
.panel-grip-strich {
  display: block;
  width: 44px; height: 5px;
  border-radius: var(--r-pill);
  /* Hell statt dunkel: Auf einer Glasscheibe ist der Griff eine Auflage
     aus mattem Glas, keine eingefraeste Rille. Deutlich genug, dass man
     ihn als Griff erkennt - er ist die einzige Stelle, an der man die
     Karte groesser ziehen kann, und wer ihn uebersieht, findet die
     Funktion nie. */
  background: color-mix(in srgb, white 55%, transparent);
  box-shadow: 0 1px 3px var(--schatten-mittel);
}
.panel-grip:hover .panel-grip-strich { background: var(--muted); }

/* ---------- Bedienfeld ---------- */
#panel {
  width: var(--spalte-panel);
  flex: 0 0 var(--spalte-panel);
  display: flex;
  flex-direction: column;
  /* Glas ueber der Karte. Die Fuellung ist dunkel und nicht hell: darunter
     liegt eine helle Landkarte, ein weisser Schleier waere unlesbar. */
  background: var(--schatten-tief);
  backdrop-filter: blur(26px) saturate(150%);
  -webkit-backdrop-filter: blur(26px) saturate(150%);
  border-right: 1px solid var(--glas-hell);
  box-shadow: inset 1px 0 0 var(--glas-hell);
}

/* Der eigentliche scrollende Inhalt - getrennt vom Griff, siehe oben. */
.panel-scroll {
  flex: 1;
  min-height: 0;   /* noetig, damit dieser Bereich innerhalb der Flex-Spalte ueberhaupt scrollen kann */
  overflow-y: auto;
  padding: 18px 18px 12px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* .brand-title: der Name "Serpa" mit dem Punkt in der Signalfarbe davor - wird
   sowohl im Bedienfeld-Header als auch auf dem Startbildschirm genutzt. */
.brand-title {
  margin: 0;
  font-family: var(--schrift-display);
  font-weight: 700;
  font-size: 24px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.05;
}
.brand-title::before {
  content: "";
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 8px;
  vertical-align: middle;
}
.start-screen-inner .brand-title { font-size: 32px; }
.sub { margin: 2px 0 0; color: var(--muted); font-size: 13px; }

.block h2 {
  margin: 0 0 var(--s2);
  font-family: var(--schrift-display);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
}

/* ---------- Einklappbare Abschnitte (Optionen, Sehenswertes, ...) ----------
   <details>/<summary> ist ein eingebautes HTML-Element für genau diesen
   Zweck - auf-/zuklappen - ganz ohne eigenes JavaScript. Wir entfernen nur
   das Standard-Dreieck davor und ersetzen es durch einen eigenen Pfeil,
   damit es zum Rest des Bedienfelds passt. */
/* Jeder Abschnitt ist eine eigene kleine Glasplatte, wie die Kartenreihe
   im Inspirationsbild - vorher waren es nackte Zeilen im Bedienfeld. */
.accordion {
  padding: 12px 14px;
  border-radius: var(--r-md);
  background: var(--glas-hell);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border: 1px solid var(--glas-hell);
  box-shadow:
    inset 0 1px 0 var(--glas-rand),
    inset 0 -1px 0 var(--schatten-hauch);
}
.accordion summary {
  margin: 0;
  font-family: var(--schrift-display);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--muted);
  font-weight: 600;
  cursor: pointer;
  list-style: none;             /* Chrome/Safari: eigenes Dreieck ausblenden */
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.accordion summary::-webkit-details-marker { display: none; } /* Chrome/Safari */
.accordion summary::marker { content: ""; }                    /* Firefox */
.accordion summary::after {
  content: "▸";
  color: var(--muted);
  font-size: 11px;
  transition: transform 0.15s ease;
}
.accordion[open] summary::after { transform: rotate(90deg); }
.accordion summary:hover { color: var(--text); }
.accordion-body { margin-top: 10px; }

.hint  { color: var(--muted); font-size: 12px; margin: 8px 0 0; line-height: 1.45; }
.tiny  { color: var(--muted); opacity: 0.75; font-size: 11px; line-height: 1.5; }
.tiny a, .hint a { color: var(--muted); }

/* ---------- Ortssuche ---------- */
.search-wrap { position: relative; }

/* Die drei Suchfelder: Start, Zwischenziel, Ziel. Beschriftung klein
   darueber, Felder mit Luft dazwischen. Das gesperrte Zielfeld der
   Rundtour tritt sichtbar zurueck, statt nur nicht zu reagieren. */
.such-feld { margin-bottom: var(--s3); }
.such-feld .label { display: block; margin-bottom: 6px; }
.such-feld .search-input:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
/* Als Pille, wie im Inspirationsbild - ein Suchfeld ist das rundeste
   Element jeder modernen Oberflaeche. Die Fuellung ist helles Glas statt
   dunkler Vertiefung: Das Feld liegt auf einer Glasplatte, und ein
   dunkles Loch darin saehe aus wie hineingebohrt. */
.search-input {
  width: 100%;
  padding: 12px 18px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hell);
  color: var(--text);
  font-family: var(--schrift-text);
  font-size: 15px;
  box-shadow:
    inset 0 1px 0 var(--glas-rand),
    inset 0 2px 5px var(--schatten-hauch);
}
.search-input:focus { outline: none; border-color: var(--accent-hell); }
.richtung-select { margin-top: 8px; cursor: pointer; }
.search-results {
  position: absolute;
  top: calc(100% + 4px);
  left: 0; right: 0;
  background: var(--schatten-voll);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-md);
  list-style: none;
  margin: 0;
  padding: 4px;
  max-height: 220px;
  overflow-y: auto;
  z-index: 500;
  box-shadow: inset 0 1px 0 var(--glas-heller), 0 12px 30px var(--schatten-mittel);
}
.search-results li {
  padding: 8px 10px;
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: 13px;
  line-height: 1.35;
}
.search-results li:hover { background: var(--surface-2); }
.search-results li.empty { cursor: default; color: var(--muted); }
.search-results li.empty:hover { background: transparent; }
.search-results li.standort-option {
  display: flex; align-items: center; gap: var(--s2);
  color: var(--gps);
  font-weight: 600;
  border-bottom: 1px solid var(--line);
  padding-bottom: 10px;
  margin-bottom: 4px;
}
.search-results li.standort-option:hover { background: color-mix(in srgb, var(--gps) 12%, transparent); }

/* ---------- Umschalter (Planungsart) ---------- */
/* Als PILLE: Die Rinne ist dunkles Glas, das aktive Segment eine hellere
   Glasscheibe darin,
   und die Signalfarbe steckt in Schrift und Symbol des aktiven Segments -
   nicht in einer gefuellten Flaeche. So bleibt die Farbe ein Zeichen und
   wird keine Deko. */
.segmented {
  display: flex;
  background: var(--schatten-hauch);
  border: 1px solid var(--glas-hell);
  border-radius: var(--r-pill);
  padding: 4px;
  gap: 4px;
  box-shadow: inset 0 2px 6px var(--schatten-weich);
}
.seg {
  flex: 1;
  padding: 9px 0;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--muted);
  font-family: var(--schrift-display);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  cursor: pointer;
  transition: color 0.14s ease, background 0.14s ease;
}
.seg.active {
  background: var(--glas-heller);
  border-color: var(--glas-rand);
  color: var(--accent-hell);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    0 3px 10px var(--schatten-weich);
}

/* ---------- Kurvigkeits-Regler ---------- */
/* -webkit-appearance/appearance entfernen die Browser-Standardoptik, damit
   wir Schiene und Griff selbst gestalten können - keine Raster-Markierungen,
   der Regler ist stufenlos bedienbar. */
.slider {
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
  height: 6px;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--skala-wenig), var(--skala-mittel), var(--skala-viel));
  outline: none;
  cursor: pointer;
}
.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--text);
  border: 3px solid var(--accent-hell);
  cursor: pointer;
  box-shadow: 0 1px 4px var(--schatten-mittel);
}
.slider::-moz-range-thumb {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: var(--text);
  border: 3px solid var(--accent-hell);
  cursor: pointer;
  box-shadow: 0 1px 4px var(--schatten-mittel);
}
.slider::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: transparent; /* Farbe kommt schon vom Element selbst */
}

/* ---------- Optionen (Checkboxen) ---------- */
.checkbox-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 0;
  font-size: 13px;
  cursor: pointer;
}
.checkbox-row input[type="checkbox"] {
  width: 17px; height: 17px;
  accent-color: var(--accent); /* faerbt die native Checkbox in der Signalfarbe ein */
  cursor: pointer;
}

/* ---------- Buttons ---------- */
.row { display: flex; gap: 8px; margin-top: 10px; }
.btn {
  flex: 1;
  /* inline-flex mit gap: Knoepfe mit Symbol brauchen Abstand zwischen
     Zeichen und Schrift, und beides soll mittig stehen. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  padding: 12px 14px;
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-sm);
  /* Die Woelbung: oben heller, unten dunkler, dazu Lichtkante und ein
     weicher Schein in der Knopffarbe. Zusammen liest sich das als
     gewoelbtes Glas mit Farbe DARUNTER - nicht als angemalte Flaeche.
     Die beiden Farben kommen aus der Designsprache statt fest eingetragen
     zu sein. Frueher standen hier zwei Orangetoene - beim Wechsel auf
     RAL 5005 waere der Knopf dadurch halb orange geblieben. */
  background: linear-gradient(to bottom, var(--accent-glanz), var(--accent) 55%, var(--accent-tief));
  color: var(--accent-ink);
  font-family: var(--schrift-text);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    inset 0 -1px 0 var(--schatten-hauch),
    0 6px 18px color-mix(in srgb, var(--accent) 40%, transparent);
  transition: filter 0.12s ease, transform 0.14s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.btn:hover { filter: brightness(1.12); }
.btn:active { transform: scale(0.97); }
.btn.ghost {
  background: var(--glas-hauch);
  backdrop-filter: blur(14px) saturate(150%);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  border-color: var(--glas-rand);
  color: var(--text);
  font-weight: 500;
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    0 3px 10px var(--schatten-weich);
}
.btn.ghost:hover { border-color: var(--muted); background: var(--surface-2); color: var(--text); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

.klick-modus-btn { width: 100%; margin-top: 8px; font-size: 12.5px; }
.klick-modus-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

/* ---------- Listen ---------- */
.badge {
  display: inline-block;
  min-width: 18px;
  padding: 1px 8px;
  border-radius: var(--r-pill);
  background: var(--glas-heller);
  border: 1px solid var(--glas-hell);
  color: var(--text);
  font-size: 11px;
  text-align: center;
}

.wp-list, .saved-list { list-style: none; margin: 0; padding: 0; }

.wp-list li, .saved-list li {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  border-radius: var(--r-sm);
  margin-bottom: 6px;
  font-size: 13px;
  background: var(--glas-hauch);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  border: 1px solid var(--glas-hell);
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    inset 0 -1px 0 var(--schatten-hauch);
  transition: background 0.14s ease, transform 0.14s cubic-bezier(0.2,0.8,0.2,1);
}
.saved-list li:active { transform: scale(0.985); }
.wp-list li.empty, .saved-list li.empty {
  background: transparent;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border: 0;
  box-shadow: none;
  color: var(--muted);
  font-size: 12px;
  padding: 4px 0;
}
.wp-num {
  font-family: var(--schrift-display);
  font-variant-numeric: tabular-nums;
  width: 20px; height: 20px;
  flex: 0 0 20px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  font-size: 11px;
  font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.wp-coord { color: var(--muted); font-variant-numeric: tabular-nums; }

.saved-list li { cursor: pointer; justify-content: space-between; align-items: center; gap: var(--s3); }
.saved-list li:hover { background: var(--glas-hell); }
.saved-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.saved-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.saved-marke { flex: 0 0 auto; display: flex; color: var(--accent-hell); }
.saved-meta i { font-style: normal; opacity: 0.45; margin: 0 2px; }
.saved-meta {
  color: var(--muted);
  font-family: var(--schrift-display);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
  font-variant-numeric: tabular-nums;
}
.del {
  border: 0; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 16px; line-height: 1; padding: 0 2px;
}
.del:hover { color: var(--danger); }

/* ---------- Statistik ---------- */
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.stat {
  background: linear-gradient(to bottom, var(--glas-hauch), var(--glas-hauch));
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  border: 1px solid var(--glas-hell);
  border-radius: var(--r-sm);
  padding: var(--s2) var(--s3);
  display: flex;
  flex-direction: column;
  gap: 2px;
  box-shadow:
    inset 0 1px 0 var(--glas-rand),
    inset 0 -1px 0 var(--schatten-hauch);
}
.stat .k {
  font-family: var(--schrift-display);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
.stat .v {
  font-family: var(--schrift-display);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.stat.highlight { grid-column: 1 / -1; border: 1px solid var(--accent-hell); }
.stat.highlight .v { color: var(--accent-hell); }

.curvebar {
  height: 6px;
  background: var(--surface-2);
  border-radius: 3px;
  margin-top: 8px;
  overflow: hidden;
}
.curvebar-fill {
  height: 100%;
  width: 0%;
  background: linear-gradient(90deg, var(--skala-wenig), var(--skala-mittel), var(--skala-viel));
  transition: width 0.4s ease;
}

/* ---------- Höhenprofil ---------- */
.hoehenprofil-kopf {
  font-family: var(--schrift-display);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 14px;
}
.hoehenprofil-spanne { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.hoehenprofil {
  display: block;
  width: 100%;
  height: 90px;
  margin-top: 6px;
  border-radius: var(--r-md);
  background: var(--schatten-hauch);
  border: 1px solid var(--glas-hell);
  box-shadow: inset 0 2px 6px var(--schatten-weich);
}
.hoehenprofil-fläche { opacity: 0.28; }
.hoehenprofil-linie { fill: none; stroke-width: 2.5; stroke-linejoin: round; stroke-linecap: round; }

/* ---------- Ride aufzeichnen ----------
   Eigener Vollbild-Aufbau: Karte oben, Werte-Feld unten. Bewusst mit
   grossen Zahlen - das muss man im Zweifel mit Handschuhen und einem
   kurzen Blick an der Ampel erfassen koennen. */
.ride-screen {
  height: calc(100% - var(--nav-raum));
  display: flex;
  flex-direction: column;
}

.ride-map { flex: 1; min-height: 0; background: var(--surface-2); }

.ride-panel {
  flex: 0 0 auto;
  max-height: 55dvh;
  overflow-y: auto;
  padding: var(--s4);
  padding-bottom: max(var(--s4), env(safe-area-inset-bottom));
  background: var(--schatten-voll);
  backdrop-filter: blur(26px) saturate(150%);
  -webkit-backdrop-filter: blur(26px) saturate(150%);
  border-top: 1px solid var(--glas-hell);
  box-shadow: inset 0 1px 0 var(--glas-rand);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
/* Nach dem Beenden darf das Feld mehr Platz nehmen - dann ist die
   Auswertung wichtiger als die Karte. */
.ride-panel.zusammenfassung { max-height: 88dvh; }

.ride-tempo {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
  margin-bottom: 2px;
}
.ride-tempo-wert {
  font-family: var(--schrift-display);
  font-size: 76px;
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--accent-hell);
}
.ride-tempo-einheit {
  font-family: var(--schrift-display);
  text-transform: uppercase;
  letter-spacing: 0.06em; font-size: 15px; color: var(--muted); }
.ride-status { text-align: center; margin: 0 0 12px; }
.ride-titel { margin: 0 0 12px; font-size: 18px; }

/* Laeuft die Aufzeichnung gerade nicht, soll das auf einen Blick klar sein. */
.ride-panel.pausiert .ride-tempo-wert { color: var(--muted); }

/* Vor dem Start darf das Feld ruhig etwas mehr Platz nehmen - da steht
   erklaerender Text, und die Karte ist noch nicht wichtig. */
.ride-panel.bereit { max-height: 70dvh; }

.ride-abschnitt { margin-top: 16px; margin-bottom: 6px; }
.ride-notizen { resize: vertical; min-height: 70px; font-family: inherit; line-height: 1.45; }

/* ---------- Fotos ---------- */
.foto-hinzu-btn { flex: 0 0 auto; padding: 4px 10px; font-size: 12px; }

.foto-galerie {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 6px;
  margin-top: 6px;
}
.foto-galerie:empty { display: none; }

.foto-kachel { position: relative; }
.foto-kachel img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: 12px;
  display: block;
  cursor: pointer;
  background: var(--surface-2);
  border: 1px solid var(--glas-rand);
  box-shadow: inset 0 1px 0 var(--glas-heller), 0 4px 12px var(--schatten-weich);
}
/* Kleines Kreuz zum Entfernen - nur dort, wo Fotos noch bearbeitbar sind. */
.foto-loeschen {
  position: absolute;
  top: 3px; right: 3px;
  width: 22px; height: 22px;
  border: 0;
  border-radius: 50%;
  background: var(--schatten-tief);
  color: var(--text);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.foto-loeschen:hover { background: var(--danger); }

/* Vollbild-Ansicht eines angetippten Fotos */
.foto-ansicht {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: var(--schatten-tief);
  backdrop-filter: blur(30px) saturate(140%);
  -webkit-backdrop-filter: blur(30px) saturate(140%);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}
.foto-ansicht img { max-width: 100%; max-height: 100%; border-radius: 10px; }
.foto-ansicht-zu {
  position: absolute;
  top: max(16px, env(safe-area-inset-top));
  right: 16px;
  width: 40px; height: 40px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--schatten-voll);
  color: var(--text);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

/* Marker fuer ein unterwegs aufgenommenes Foto auf der Karte */
.foto-marker {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--text);
  color: var(--accent-ink);   /* Farbe des Symbols darin */
  border: 2px solid var(--accent-ink);
  box-shadow: 0 2px 6px var(--schatten-mittel);
  display: flex; align-items: center; justify-content: center;
  font-size: 13px;
}

.aufzeichnung-notizen {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;   /* eigene Zeilenumbrueche des Nutzers erhalten */
}

/* ---------- Live-Navigation ---------- */
/* Die Navigation traegt NICHT die Signalfarbe, sondern das helle Blau des
   eigenen Standorts - und genau darum geht es hier.

   Seit die Signalfarbe selbst ein Blau ist, liegen die beiden naeher
   beieinander als frueher. Unterschieden werden sie noch durch zweierlei:
   Dieses Blau ist deutlich heller, und dieser Knopf ist nur ein Umriss,
   keine Flaeche. Sollte das eines Tages nicht mehr reichen, gehoert der
   Standortfarbe ein eigener Ton - nicht diesem Knopf eine Ausnahme. */
.nav-btn {
  background: transparent;
  border-color: var(--gps);
  color: var(--gps);
  font-weight: 600;
}
.nav-btn:hover { background: color-mix(in srgb, var(--gps) 12%, transparent); border-color: var(--gps); color: var(--gps); }

/* Während die Navigation läuft, fährt das Seitenpanel weg und die Karte
   nutzt den vollen Platz - wie bei einem eigenständigen Navi-Gerät. */
#panel { transition: flex-basis 0.3s ease, width 0.3s ease, height 0.3s ease; }
/* Waehrend am Griff gezogen wird (siehe app.js) MUSS die Animation aus sein -
   sonst hinkt das Panel dem Finger sichtbar hinterher statt ihm 1:1 zu folgen. */
#panel.panel-dragging { transition: none; }
body.nav-modus #panel {
  flex-basis: 0;
  width: 0;
  overflow: hidden;
  border-right: 0;
}

/* Die Manoevertafel liegt direkt auf der Karte (wie bei Google Maps/Waze).
   Ausgelegt fuer den Blick von der Maschine: grosser Pfeil, grosse Zahl,
   ein kurzer Satz - mehr muss in einer halben Sekunde nicht erfassbar
   sein. Die Entfernung ist das Groesste auf der Tafel, denn sie ist das,
   was sich staendig aendert und was man wirklich abliest. */
.nav-banner {
  position: absolute;
  top: max(12px, env(safe-area-inset-top));
  left: 12px; right: 12px;
  z-index: 900;
  background: var(--schatten-tief);
  backdrop-filter: blur(24px) saturate(160%);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-lg);
  padding: var(--s4);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    0 12px 34px var(--schatten-mittel);
}

.nav-manoever {
  display: flex;
  align-items: center;
  gap: var(--s4);
}
/* Der Pfeil: eigene Scheibe in der Standortfarbe, damit das Auge sofort
   dort landet. "scharf" dreht denselben Pfeil einfach 40 Grad weiter -
   ein eigenes Symbol braucht es dafuer nicht. */
.nav-pfeil {
  flex: 0 0 auto;
  width: 72px; height: 72px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--gps) 18%, transparent);
  border: 1px solid color-mix(in srgb, var(--gps) 45%, transparent);
  color: var(--gps);
  box-shadow: inset 0 1px 0 var(--glas-heller);
}
.nav-pfeil .ic {
  width: 46px; height: 46px;
  stroke-width: 2.4;
  transition: transform 0.25s ease;
}
.nav-pfeil.scharf-rechts .ic { transform: rotate(40deg); }
.nav-pfeil.scharf-links  .ic { transform: rotate(-40deg); }

.nav-texte { min-width: 0; }
.nav-distance {
  font-family: var(--schrift-display);
  font-size: 46px;
  font-weight: 700;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.nav-detail { font-size: 15px; color: var(--muted); margin-top: 4px; }

/* Das DANACH in der Fusszeile der Tafel: An der Kreuzung selbst will man
   schon wissen, wie es weitergeht - besonders wenn zwei Abzweigungen kurz
   hintereinander liegen. */
.nav-danach {
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--glas-hell);
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: 13px;
  color: var(--muted);
}
.nav-danach .ic { width: 16px; height: 16px; }

/* Die Fahrdatenleiste am unteren Rand: Tempo, Rest, Ankunft, Beenden.
   Eine Zeile, keine zweite - die Navigation MUSS ohne Scrollen auf den
   Schirm passen, das war die Vorgabe. */
.nav-fuss {
  position: absolute;
  bottom: max(12px, env(safe-area-inset-bottom));
  left: 12px; right: 12px;
  z-index: 900;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s2) var(--s4);
  background: var(--schatten-tief);
  backdrop-filter: blur(24px) saturate(160%);
  -webkit-backdrop-filter: blur(24px) saturate(160%);
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-lg);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    0 12px 34px var(--schatten-mittel);
}
.nav-wert {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  min-width: 0;
}
.nav-wert .wert {
  font-family: var(--schrift-display);
  font-size: 22px;
  font-weight: 700;
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.nav-wert .einheit {
  font-family: var(--schrift-display);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.nav-stop-btn {
  flex: 0 0 auto;
  background: color-mix(in srgb, var(--danger) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--danger) 50%, transparent);
  color: var(--danger);
  padding: 10px 16px;
  border-radius: var(--r-pill);
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.nav-stop-btn:hover { background: color-mix(in srgb, var(--danger) 26%, transparent); }

/* Waehrend der Fahrt braucht niemand die Zoom-Knoepfe - sie laegen genau
   unter der Manoevertafel und sind mit Handschuhen ohnehin nicht zu
   treffen. Die OSM-Quellenangabe bleibt sichtbar, die ist Pflicht. */
body.nav-modus .leaflet-control-zoom { display: none; }

/* Eigener Standort auf der Karte: eine Spitze, die IMMER nach oben zeigt -
   weil sich während der Navigation ja die ganze Karte mit der Fahrtrichtung
   mitdreht (siehe setzeKartenDrehung() in app.js), nicht der Marker selbst. */
.you-are-here {
  width: 22px; height: 22px;
  display: flex; align-items: center; justify-content: center;
  color: var(--gps);
  font-size: 22px;
  text-shadow: 0 0 3px var(--bg), 0 0 3px var(--bg), 0 0 3px var(--bg);
  /* Dieser eine Marker folgt der Kartendrehung weich statt zu springen -
     als einziger, siehe die Begruendung im Marker-Abschnitt weiter unten. */
  transition: transform 1s linear;
}

/* Eigener Standort beim Start: schlichter blauer Punkt, ohne Blickrichtung -
   im Unterschied zur Spitze (.you-are-here) während der Navigation. */
.standort-marker {
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--gps);
  border: 3px solid var(--bg);
  box-shadow: 0 0 0 2px var(--gps);
}

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

/* overflow:hidden ist hier kein Schönheitsmittel, sondern Pflicht: Während
   der Navigation ist die Karte absichtlich viel grösser als der Bildschirm
   (Begründung gleich darunter). Ohne diese Zeile würde sie über den ganzen
   Rest der Seite quellen. */
/* "isolation: isolate" ist die wichtigste Zeile dieses Kastens. Leaflet
   vergibt INNERHALB der Karte z-index-Werte von 200 bis 1000 (Kacheln 200,
   Marker 600, Bedienelemente 1000). Ohne einen eigenen Stapelkontext
   messen sich diese Werte mit allem anderen auf der Seite - und schlagen
   das Bedienfeld mit seiner 5 muehelos. Die Folge war sichtbar: Die
   Schublade schiebt sich um eine Eckenrundung ueber die Karte, und genau
   dieser Streifen wurde von den Kacheln uebermalt. Mit ihm verschwanden
   der Griff zum Ziehen, die gerundete Oberkante und die helle Trennlinie.
   "isolate" sperrt Leaflets Zahlen in den Kasten, danach zaehlt nach
   aussen nur noch der Kasten selbst. */
#mapWrap { flex: 1; position: relative; overflow: hidden; isolation: isolate; }

#map { position: absolute; inset: 0; background: var(--surface-2); }

/* ---------- Karte drehen während der Navigation ----------------------------
   Damit man beim Fahren nicht im Kopf umrechnen muss, zeigt die Fahrtrichtung
   immer nach oben - die Karte dreht sich also unter der eigenen Position weg.
   Diesen Winkel setzt setzeKartenDrehung() in app.js als CSS-Variable
   --karten-drehung an #mapWrap, von wo aus er hierher und bis zu jedem
   einzelnen Marker durchvererbt wird.

   Warum die Karte dabei zum QUADRAT wird: Ein gedrehtes Rechteck deckt seine
   eigene Fläche nicht mehr ab, an den Ecken gucken sonst leere Dreiecke
   heraus. Ein Quadrat mit der Bildschirmdiagonale als Seitenlänge deckt den
   Bildschirm dagegen in jeder Drehlage ab. Die genaue Seitenlänge misst
   passeKartenQuadratAn() in app.js aus und schreibt sie nach
   --karten-quadrat; die 150vmax hier sind nur der Rückfallwert, falls diese
   Messung noch nicht gelaufen ist - grosszügig gerundet, aber immer sicher.

   Die negativen Ränder ziehen das Quadrat um seine halbe Grösse zurück und
   setzen damit seine MITTE auf die Bildschirmmitte. Nur deshalb kann unten
   ein reines rotate() stehen: Die Drehung dreht dann um genau diesen Punkt,
   und das Umschalten in den Navi-Modus fängt sauber bei rotate(0deg) an,
   statt sichtbar von irgendwo hereinzurutschen.                           */
body.nav-modus #map {
  inset: auto;
  top: 50%;
  left: 50%;
  width:  var(--karten-quadrat, 150vmax);
  height: var(--karten-quadrat, 150vmax);
  margin-top:  calc(var(--karten-quadrat, 150vmax) / -2);
  margin-left: calc(var(--karten-quadrat, 150vmax) / -2);
  transform: rotate(var(--karten-drehung, 0deg));
  /* Das GPS meldet etwa einmal pro Sekunde, und genau so lange muss die
     Bewegung dauern - dann geht eine Meldung nahtlos in die naechste ueber.
     Ist sie kuerzer als der Schwenk in app.js, steht die Drehung dazwischen
     still und ruckt dann wieder los; genau das kam als "abgehackt" an.
     "linear" statt "ease-out", weil ein Fahrzeug seinen Kurs gleichmaessig
     aendert und nicht in Schueben. */
  transition: transform 1s linear;
}

/* Gegendrehung der Marker. Die Karte dreht sich als Ganzes, also drehen sich
   alle Marker mit - Wegpunkt-Zahlen stünden auf dem Kopf, die Standortspitze
   zeigte irgendwohin. Jeder Marker dreht deshalb um genau denselben Winkel
   zurück und steht dadurch wieder gerade auf dem Bildschirm.

   Das kostet keine einzige Zeile JavaScript pro Marker: Die Variable erbt von
   #mapWrap herunter, also gilt die Regel automatisch auch für Marker, die
   erst während der Fahrt dazukommen. Ausserhalb der Navigation ist der Wert
   0deg und die Regel damit wirkungslos. Dieselbe Dauer wie oben, sonst
   liefen Karte und Marker sichtbar auseinander. */
.you-are-here, .wp-marker, .poi-marker, .foto-marker, .standort-marker {
  transform: rotate(calc(-1 * var(--karten-drehung, 0deg)));
}

/* Die Uebergangsanimation bekommt im Navi-Modus NUR der eigene Standort;
   seine transition-Zeile steht oben in seinem eigenen Block. Auf einer
   Alpenroute liegen schnell zwanzig Pass-Marker im Bild, und jeder von
   ihnen waere sonst eine eigene Animation, die der Compositor im
   Sekundentakt mitrechnet. Die uebrigen Marker springen dadurch hart mit -
   was niemand sieht, weil sie waehrend der Fahrt Beiwerk sind. */
body:not(.nav-modus) .wp-marker,
body:not(.nav-modus) .poi-marker,
body:not(.nav-modus) .foto-marker,
body:not(.nav-modus) .standort-marker { transition: transform 1s linear; }

/* Sprechblasen (z.B. an einem Pass) hängen an ihrer Spitze, deshalb wird hier
   um genau diese Spitze zurückgedreht - der Text bleibt lesbar, die Blase
   bleibt am richtigen Ort. */
.leaflet-popup-content-wrapper {
  transform: rotate(calc(-1 * var(--karten-drehung, 0deg)));
  transform-origin: bottom center;
}

/* Die Zoom-Knöpfe sitzen in den ECKEN des Kartenbehälters - und der ist
   während der Fahrt viel grösser als der Bildschirm, seine Ecken liegen also
   weit ausserhalb. Statt sie aufwendig zurückzurechnen blenden wir sie aus:
   Die Karte zoomt während der Navigation ohnehin selbst auf Stufe 17 und
   folgt der eigenen Position, von Hand zoomen will da niemand. */
body.nav-modus .leaflet-control-container { display: none; }

/* Leaflet-Bedienelemente etwas dunkler einfärben */
/* Die Namensnennung von OpenStreetMap. Sie war hier abgeschaltet, weil
   die Quellen auch im Fuss des Bedienfelds stehen - nur steht der dort
   ausserhalb des Bildschirms, und auf der Aufzeichnungs-Karte und im
   Navi-Modus gibt es ihn gar nicht. Die Nutzungsbedingungen sind an
   dieser Stelle eindeutig: "Do not hide attribution beneath UI, behind
   toggles, or off-screen."

   Also sichtbar, aber dezent: klein, halbdurchsichtig, in der Ecke. */
.leaflet-control-attribution {
  background: var(--schatten-mittel);
  color: var(--muted);
  font-size: 10px;
  padding: 2px 6px;
  border-radius: var(--r-sm) 0 0 0;
}
.leaflet-control-attribution a { color: var(--muted); text-decoration: underline; }

/* Nummerierte Wegpunkt-Marker */
.wp-marker {
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  border: 2px solid var(--accent-ink);
  box-shadow: 0 2px 6px var(--schatten-mittel);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 12px;
  font-family: -apple-system, sans-serif;
}

/* Sehenswertes: Gebirgspässe */
.poi-marker {
  width: 24px; height: 24px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 14px;
  box-shadow: 0 2px 6px var(--schatten-mittel);
  border: 2px solid var(--accent-ink);
}
/* Die Marker enthalten jetzt ein SVG statt eines Emoji. Weil das Symbol
   seine Farbe ueber currentColor holt, muss hier eine dunkle Textfarbe
   stehen - sonst waere die Strichzeichnung weiss auf hellem Grund. */
.poi-marker.pass { background: var(--pass-schild); color: var(--pass-schild-ink); }

.poi-popup { font-size: 13px; line-height: 1.5; }
.poi-popup .poi-popup-titel { font-weight: 700; }

/* ---------- Overlays ---------- */
.toast {
  /* fixed statt absolute: Der Toast haengt jetzt am Bildschirm, nicht
     mehr an der Karte. Der Abstand nach oben nimmt die Notch mit. */
  position: fixed;
  top: calc(16px + env(safe-area-inset-top)); left: 50%;
  transform: translateX(-50%);
  background: var(--schatten-tief);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border: 1px solid var(--glas-rand);
  border-left: 3px solid var(--accent-hell);
  color: var(--text);
  padding: 10px 16px;
  border-radius: var(--r-md);
  font-size: 14px;
  z-index: 1000;
  max-width: 80%;
  box-shadow: inset 0 1px 0 var(--glas-heller), 0 10px 30px var(--schatten-mittel);
}

.busy {
  position: absolute;
  inset: 0;
  background: var(--schatten-stark);
  display: flex; align-items: center; justify-content: center;
  gap: var(--s3);
  z-index: 999;
  color: var(--text);
  font-family: var(--schrift-display);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.spinner {
  width: 22px; height: 22px;
  border: 3px solid var(--glas-rand);
  border-top-color: var(--accent-hell);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ---------- Schmale Bildschirme / Hochformat ----------
   Hauptzielgruppe ist eine Handy-App (siehe CLAUDE.md) - hier wird aus
   "Bedienfeld links, Karte rechts" ein senkrechter Aufbau: die Karte oben
   und dominant (per order VISUELL vor dem Bedienfeld, an der Reihenfolge
   im HTML aendert das nichts), das Bedienfeld darunter als Schublade, die
   sich am Griff STUFENLOS ziehen laesst - von "nur der Griff ist sichtbar,
   Karte hat den ganzen Bildschirm" bis fast volle Hoehe. Die eigentliche
   Hoehe setzt app.js direkt per style.height (Abschnitt 9c) - hier nur ein
   Startwert, falls JS noch nicht geladen ist. */
@media (max-width: 760px) {
  .app-layout { flex-direction: column; }

  #mapWrap { order: 1; flex: 1; }

  #panel {
    order: 2;
    width: 100%;
    flex: 0 0 auto;
    height: 45dvh;
    border-right: 0;
    border-top: 1px solid var(--glas-rand);
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    overflow: hidden;   /* rundet auch den Scroll-Inhalt sauber ab, auch beim elastischen Ueberscrollen */
    /* Die Schublade schiebt sich um eine Eckenrundung UEBER die Karte.
       Ohne das laege sie schlicht daneben, und ihr Glas haette nichts zu
       brechen - genau der Unterschied zwischen einer Glasscheibe ueber
       der Karte und einem schwarzen Kasten darunter. Der Blur an der
       Oberkante zeigt die Karte verwischt, wie beim Inspirationsbild. */
    margin-top: calc(-1 * var(--r-lg));
    position: relative;
    z-index: 5;
    box-shadow: 0 -10px 30px var(--schatten-weich);
  }

  .panel-grip { display: flex; }

  /* Waehrend der Navigation soll die Karte wie bei einem echten Navi-Geraet
     den ganzen Bildschirm bekommen - anders als am Desktop (dort schrumpft
     die BREITE auf 0, siehe body.nav-modus #panel weiter oben) schrumpft
     hier die HOEHE auf 0. !important, weil app.js beim Ziehen eine eigene
     Hoehe per Inline-Style setzt, die sonst gewinnen wuerde. */
  body.nav-modus #panel { height: 0 !important; }
}
/* ============================================================================
   Die Garage

   Aufgebaut als RAUM: hinten die Wand mit der Hakenleiste, davor der Boden,
   darauf steht die Maschine.

   DREI REGELN, die hier zusammenwirken und die man nicht einzeln kippen darf:

   1. DER RAUM HAT EINE FESTE HOEHE, die Seite darunter scrollt. Frueher
      stand hier "ohne Scrollen": Der Raum bekam den Rest, den die Platten
      uebrig liessen. Das raechte sich, sobald unten etwas dazukam - der
      Raum wurde kleiner, das Raumbild bekam einen anderen Ausschnitt, und
      die ganze Seite sah verschoben aus. Jetzt sagt
      --garage-raum-hoehe die Hoehe an, und was darunter steht, kann
      wachsen, ohne oben etwas zu verruecken.

   2. LIQUID GLASS heisst Linse, nicht Schleier. Unter allem liegt dasselbe
      weichgezeichnete Motorradfoto wie bei Konto und Touren. Wand und Boden
      sind halbdurchsichtig darueber gelegt. Wuerde man sie deckend machen,
      saehe es fast gleich aus, aber das Glas waere tot.

   3. FARBE KOMMT AUS LICHT, nicht aus Flaechen. Die Garage hat drei
      Lichtquellen: eine warme Lampe oben, einen kalten Schein von links und
      einen Strahler hinter der Maschine. Farbige Flaechen waeren Deko,
      farbiges Licht erklaert den Raum.
   ============================================================================ */

.garage-screen {
  /* WIE HOCH DER RAUM MIT DEM MOTORRAD IST - eine Ansage, kein Rest.

     Das ist die wichtigste Zeile dieses Abschnitts: Haengt die Hoehe am
     uebrigen Platz, verschiebt JEDES Element, das unten dazukommt, oben den
     Bildausschnitt des Raumbildes. Die Seite sieht dann verschoben aus.

     Die Formel liest sich von innen nach aussen: hoechstens 64 Prozent
     der Bildschirmhoehe, aber nie breiter als 132 Prozent der Breite
     (sonst wird der Raum auf einem kurzen, breiten Schirm zum Schlauch),
     und nie unter 400 Punkten, sonst passt die Maschine nicht mehr drauf.
     svh statt vh: Die kleine Fassung der Bildschirmhoehe aendert sich
     NICHT, wenn die Adresszeile des Browsers ein- und ausfaehrt - mit vh
     wuerde der Raum bei jedem Scrollen neu gerechnet. */
  --garage-raum-hoehe: calc(max(min(64svh, 132vw), 400px) + env(safe-area-inset-top));

  height: calc(100% - var(--nav-raum));
  /* Die Seite SCROLLT. Frueher galt hier "alles muss auf eine Seite
     passen"; seit die Garage der Startbildschirm ist, haengen unter dem
     Raum der Shop und das Menue, und dafuer braucht es den Weg nach
     unten. "contain" haelt das Wischen im Bildschirm, statt die Seite
     dahinter mitzuziehen. */
  overflow-y: auto;
  overscroll-behavior-y: contain;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  background:
    linear-gradient(to bottom,
      var(--schatten-weich) 0%,
      var(--schatten-stark) 40%,
      var(--schatten-tief) 70%,
      var(--schatten-voll) 100%),
    /* "scroll" statt "fixed": Ein festgenagelter Hintergrund in einem
       selbst scrollenden Kasten flackert auf iOS und verrutscht. */
    url('img/hintergrund-weich.jpg') center / cover no-repeat scroll;
}

/* ---------- Der Raum ----------
   Frueher standen hier zwei Farbverlaeufe fuer Wand und Boden und drei
   gemalte Lichtflecken. Das ist alles raus: Der Raum IST jetzt ein Bild -
   der gerenderte Werkstattraum mit dem Drehteller. Was frueher die Verlaeufe
   andeuten mussten (Kante zwischen Wand und Boden, Lichter), bringt das
   Bild selbst mit. */
.garage-raum {
  position: relative;
  /* Feste Hoehe statt Restplatz - die Begruendung steht oben bei
     --garage-raum-hoehe. position, overflow und die Flex-Spalte muessen
     bleiben: An ihnen haengt die Rechnung in setzeBuehnenPlatz(). */
  flex: 0 0 auto;
  height: var(--garage-raum-hoehe);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg);
}

/* Schicht 1: das Raumbild. Groesse und Lage rechnet zeichneBuehne() aus und
   schreibt sie in die beiden Variablen - so landet der Drehteller auf jeder
   Bildschirmgroesse an derselben Stelle relativ zur Maschine. Solange die
   Rechnung noch nicht gelaufen ist, deckt "cover" den Raum ordentlich ab. */
.buehne-platte {
  position: absolute; inset: 0;
  pointer-events: none;
  /* Nur der Rueckfall fuers allererste Zeichnen - welches der beiden
     Raumbilder wirklich gilt, setzt zeichneBuehne() in garage.js. */
  background-image: url('img/garage-werkstatt-standard.webp');
  background-repeat: no-repeat;
  background-size: var(--platte-groesse, cover);
  background-position: var(--platte-lage, center 62%);
}

/* Schicht 6: die Dunstschicht. Oben dunkel fuer Ueberschrift und
   Hakenleiste, unten laeuft das Bild in die Grundflaeche aus, damit an der
   Glasplatte darunter keine harte Fotokante steht. */
.buehne-dunst {
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom,
      color-mix(in srgb, black calc(var(--dunst-oben, 0.86) * 100%), transparent) 0%,
      color-mix(in srgb, black calc(var(--dunst-oben, 0.86) *  72%), transparent) 12%,
      color-mix(in srgb, black calc(var(--dunst-oben, 0.86) *  34%), transparent) 24%,
      transparent 38%),
    linear-gradient(to top,    var(--schatten-voll) 0%, var(--schatten-weich) 9%,  transparent 20%);
}

/* ---------- Das Lampenflackern ----------
   Ueber jeder Lampe des Raumbilds liegt ein dunkler Lichtfleck (angelegt
   von garage.js, platziert von setzeBuehnenPlatz). "multiply" rechnet ihn
   in das Bild darunter hinein: Statt einen grauen Klecks DARAUF zu legen,
   nimmt er der Lampe anteilig ihr Licht - genau so sieht Dimmen aus.

   Fast die ganze Zeit steht die Deckkraft auf null, die Flecken sind
   unsichtbar und kosten nichts. Nur an wenigen Stellen des Durchlaufs
   sacken sie fuer Sekundenbruchteile ab. Absichtlich selten und kurz -
   die Garage soll leben, nicht blinken. */
.buehne-lampen {
  position: absolute; inset: 0;
  overflow: hidden;
  pointer-events: none;
}
.buehne-lampe {
  position: absolute;
  mix-blend-mode: multiply;
  opacity: 0;
  /* Takt und Startversatz setzt garage.js je Lampe, deshalb hier nur der
     Name der Animation und ihre Gangart. "steps" gibt es nicht: Licht
     bricht weich ein, nicht in Stufen. */
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
/* Die Leuchtstoffroehre: laenglicher Fleck. Sein dunkelster Punkt liegt
   bei 30 Prozent der Hoehe, nicht in der Mitte - unter der Roehre haengt
   ihr Lichtschein an der Wand, und der soll mit abdunkeln. garage.js
   setzt den Fleck deshalb so, dass die 30-Prozent-Marke AUF der Roehre
   liegt (der "anker" in der GARAGEN-Liste). Vorher war der Fleck auf die
   Roehre zentriert und sein Schwerpunkt hing sichtbar DARUEBER. */
.lampe-roehre {
  background: radial-gradient(ellipse 50% 42% at 50% 30%,
    color-mix(in srgb, var(--raum-dunkel) 90%, transparent),
    color-mix(in srgb, var(--raum-dunkel) 35%, transparent) 55%,
    transparent 100%);
  animation-name: lampe-stottern;
}
/* Die Haengelampen: runder Schein, dichter Kern, nach aussen weich. Zwei
   Muster (a und b) mit Aussetzern an verschiedenen Stellen des Durchlaufs -
   zusammen mit den verschiedenen Takten wirken die beiden Lampen dadurch
   wirklich unabhaengig statt wie zwei Kopien derselben Stoerung. */
.lampe-schirm, .lampe-schirm2 {
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--raum-dunkel) 92%, transparent),
    color-mix(in srgb, var(--raum-dunkel) 40%, transparent) 45%,
    transparent 88%);
}
.lampe-schirm  { animation-name: lampe-durchhaengen-a; }
.lampe-schirm2 { animation-name: lampe-durchhaengen-b; }
/* Der Leuchtstoff-Stotterer, gemaechlich: einmal absacken, kurz fangen,
   tiefer absacken, langsam erholen - gut eine Sekunde. Spaeter im
   Durchlauf noch ein einzelner weicher Schlag. Bei 19 Sekunden Laufzeit
   ist ein Prozent 190 Millisekunden. */
@keyframes lampe-stottern {
  0%, 30%   { opacity: 0; }
  31.5%     { opacity: 0.85; }
  33%       { opacity: 0.3; }
  34.5%     { opacity: 0.95; }
  37%       { opacity: 0; }
  63%       { opacity: 0; }
  64.5%     { opacity: 0.6; }
  67.5%     { opacity: 0; }
  100%      { opacity: 0; }
}
/* Die Haengelampen stottern nicht, sie haengen durch wie bei einer
   Spannungsschwankung: ein wackliger Durchhaenger von gut zwei Sekunden,
   spaeter ein kurzer einzelner. Muster a und b unterscheiden sich in
   Lage und Tiefe der Aussetzer. */
@keyframes lampe-durchhaengen-a {
  0%, 40% { opacity: 0; }
  43%     { opacity: 0.8; }
  45%     { opacity: 0.45; }
  47.5%   { opacity: 0.75; }
  51%     { opacity: 0; }
  75%     { opacity: 0; }
  76.5%   { opacity: 0.5; }
  79%     { opacity: 0; }
  100%    { opacity: 0; }
}
@keyframes lampe-durchhaengen-b {
  0%, 22% { opacity: 0; }
  24%     { opacity: 0.75; }
  26%     { opacity: 0.35; }
  27.5%   { opacity: 0.7; }
  30%     { opacity: 0; }
  58%     { opacity: 0; }
  60%     { opacity: 0.55; }
  63%     { opacity: 0; }
  100%    { opacity: 0; }
}

.garage-raum > *:not(.buehne-platte):not(.buehne-lampen):not(.buehne-dunst) { position: relative; z-index: 1; }

.garage-kopf {
  flex: 0 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
  padding: calc(var(--s4) + env(safe-area-inset-top)) var(--s4) 0;
}
.garage-titel {
  margin: 0;
  font-family: var(--schrift-display);
  font-weight: 700;
  font-size: clamp(23px, 7vw, 32px);
  line-height: 1;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-shadow: 0 2px 14px var(--schatten-tief);
}
.garage-sub {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 12.5px;
  text-shadow: 0 1px 8px var(--schatten-tief);
}

/* ---------- Die Buehne mit dem Motorrad ----------

   Die Maschine steht auf dem Drehteller des Raumbilds. Damit ein
   freigestelltes Foto dort STEHT statt zu kleben, liegen fuenf Schichten
   uebereinander, von unten nach oben:

     .buehne-spiegel    die Spiegelung auf der Tellerflaeche
     .buehne-schatten   die gestauchte Silhouette als weicher Grundschatten
     .buehne-kontakt    harte, dunkle Aufsetzpunkte unter den Reifen,
                        gezeichnet aus der Bodenlinie des Freistellers
     .motorrad-bild     die Maschine selbst
     .buehne-glut       das orange Licht des LED-Rings, das von unten an
                        die Maschine schlaegt

   Von den vieren um das Bild herum ist der Schatten der wichtigste: Ein
   Motorrad ohne Schatten schwebt, und das sieht jeder sofort, ohne sagen zu
   koennen warum.

   WO und WIE GROSS der Stapel steht, setzt zeichneBuehne() in garage.js -
   left, bottom und width kommen von dort, ausgerechnet aus der Lage des
   Drehtellers im Bild. Deshalb steht hier keine Groesse. */
.garage-buehne {
  position: relative;
  flex: 1;              /* bekommt allen Platz, der uebrigbleibt */
  min-height: 0;
}

.motorrad-ansicht {
  position: absolute;   /* left/bottom/width setzt zeichneBuehne() */
  pointer-events: none;
}

/* Der Leuchtsaum: dieselbe Aufnahme noch einmal, deckungsgleich UNTER dem
   Original. Ihre drop-shadows folgen der Silhouette des Fotos - und weil
   das Original alles andere abdeckt, bleibt von dieser Kopie nur der
   schmale orange Schein rund um die Kontur uebrig.

   Warum drei Schatten: Der erste, enge, ist der eigentliche Farbstreifen.
   Die beiden weiteren lassen ihn nach aussen weich auslaufen, sonst saehe
   er aus wie ein aufgemalter Umriss. Nebenbei uebertuscht der Saum
   ausgefranste Kanten des Freistellers - dunkler Fotorand auf orangem
   Schein liest sich als Gegenlicht, nicht als Schnittfehler.

   Das langsame Atmen macht ihn lebendig, ohne aufzufallen: acht Sekunden
   je Zug, und nie ganz aus. */
.buehne-rand {
  position: absolute;
  z-index: 2;
  top: 0; left: 0;
  width: 100%;
  /* Drei Schatten, von innen nach aussen: ein haarfeiner, zum Weissen hin
     aufgehellter Kern direkt an der Kante, eine dichte orange Lage, aussen
     ein breiter, halbdurchsichtiger Schein. Der helle Kern ist der
     Unterschied zwischen "Gegenlicht" und "orange angemalt", und dass der
     Aussenschein DURCHSICHTIG ist statt einfach breit, haelt den Streifen
     schlank - vier volle Lagen uebereinander wurden beim Ausprobieren
     sofort zum Aufkleberrand.

     Beide Zusatztoene sind per color-mix aus EINER Farbe abgeleitet, es
     kommt also keine zweite ins Spiel. Die erste filter-Zeile ist der
     Rueckfall fuer Browser ohne color-mix - dann eben ohne gluehenden
     Kern, aber nie ganz ohne Saum.

     Diese Farbe ist --licht-warm und NICHT die Signalfarbe der App: Der
     Saum ist Licht des Raumes, keine Marke. Als die Signalfarbe auf
     RAL 5005 wechselte, wurde der Saum blau auf blauem Raum und die
     Maschine verschwand darin - seitdem haengt er an einer eigenen Marke. */
  filter: drop-shadow(0 0 1px var(--licht-warm))
          drop-shadow(0 0 2px var(--licht-warm))
          drop-shadow(0 0 9px var(--licht-warm));
  filter: drop-shadow(0 0 1px color-mix(in srgb, var(--licht-warm) 60%, white))
          drop-shadow(0 0 2px var(--licht-warm))
          drop-shadow(0 0 13px color-mix(in srgb, var(--licht-warm) 40%, transparent));
  animation: rand-atmen 8s ease-in-out infinite;
}
@keyframes rand-atmen {
  0%, 100% { opacity: 0.6; }
  50%      { opacity: 0.85; }
}

/* Die weisse Kantenlinie: eine duenne, STAENDIG sichtbare Linie direkt an
   der Kontur - sie atmet nicht mit, das ist Absicht: Das Orange dahinter
   lebt, die Linie steht. Drei gleiche drop-shadows uebereinander
   verdichten die Linie zu voller Staerke, ohne sie zu verbreitern; mit
   zweien blieb sie an hellen Bildstellen zu blass. Das Weiss ist das
   Textweiss der Designsprache, kein reines Weiss.

   Der vierte Schatten ist der HELLE SCHEIN: ein breites, halbdurchsichtiges
   Aufhellen rund um die Linie, ebenfalls staendig da. Er liegt auf
   derselben Schicht wie die Linie, damit beide zusammen stehen - Kante,
   heller Saum, und erst dahinter das atmende Orange. Halbdurchsichtig per
   color-mix, sonst wuerde der Schein zur dicken weissen Wolke; die erste
   filter-Zeile ist der Rueckfall fuer Browser ohne color-mix. */
.buehne-kante-linie {
  position: absolute;
  z-index: 2;
  top: 0; left: 0;
  width: 100%;
  filter: drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 1px var(--text));
  filter: drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 7px color-mix(in srgb, var(--text) 55%, transparent));
}

/* ---------- Das Lauflicht ----------
   Ein kleiner weisser Streifen, der pausenlos im Uhrzeigersinn an der
   Aussenlinie der Maschine entlangwandert.

   Wie das ohne Wegberechnung geht: Das Bild in der Huelle traegt weisse
   drop-shadows, also einen Leuchtrand um die ganze Silhouette. Die HUELLE
   traegt eine Maske in Form eines Tortenstuecks - nur ein schmales
   Winkelfenster mit weichem Schweif ist durchlaessig - und dreht sich.
   Das Bild darin dreht exakt gegenlaeufig (gleiche Dauer, gleiche
   Gangart) und steht deshalb still. Es wandert also nur das Fenster im
   Kreis, und sichtbar ist immer genau das Stueck Leuchtrand, das gerade
   darin liegt: ein Lichtpunkt, der der Kontur folgt.

   Die Huelle ist um den Schattenweg groesser als das Bild (inset -24px
   gegen die Buehne, das Bild sitzt 24px eingerueckt), denn die Maske
   schneidet an der Huellenkante ab - saesse sie knapp, waere der
   Leuchtrand oben und unten gekappt. */
.buehne-lauf {
  position: absolute;
  z-index: 2;
  inset: -24px;
  pointer-events: none;
  animation: lauf-drehen 8.4s linear infinite;
  -webkit-mask-image: conic-gradient(from 0deg,
    transparent 0deg 295deg,
    color-mix(in srgb, black 25%, transparent) 322deg,
    color-mix(in srgb, black 70%, transparent) 344deg,
    black 353deg,
    black 358deg,
    transparent 360deg);
          mask-image: conic-gradient(from 0deg,
    transparent 0deg 295deg,
    color-mix(in srgb, black 25%, transparent) 322deg,
    color-mix(in srgb, black 70%, transparent) 344deg,
    black 353deg,
    black 358deg,
    transparent 360deg);
}
.buehne-lauf > img {
  position: absolute;
  top: 24px; left: 24px;
  width: calc(100% - 48px);
  animation: lauf-gegendrehen 8.4s linear infinite;
  /* Der Leuchtrand des Laeufers: genauso SCHMAL wie die stehende
     Kantenlinie, nur dichter. Er soll exakt AUF der Linie entlanglaufen,
     nicht als Wolke darum herum - deshalb kein breiter Schein hier. Wo
     der Laeufer vorbeikommt, verdoppelt sich die Dichte der Linie, und
     genau das ist der sichtbare Lichtpunkt. */
  filter: drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 1px var(--text))
          drop-shadow(0 0 2px var(--text));
}
@keyframes lauf-drehen       { to { transform: rotate(360deg); } }
@keyframes lauf-gegendrehen  { to { transform: rotate(-360deg); } }

.motorrad-bild {
  position: relative;
  z-index: 3;
  display: block;
  width: 100%;
  -webkit-user-drag: none;
  /* Leicht abgedunkelt und entsaettigt: Das Foto entstand bei Tageslicht,
     der Raum ist eine dunkle Werkstatt. Ohne den Angleich wirkt die
     Maschine wie ein Aufkleber - zu hell fuer ihre Umgebung. Der Wert
     kommt je Garage aus der GARAGEN-Liste. */
  filter: brightness(var(--buehne-helligkeit, 0.9)) saturate(0.95) contrast(1.04);
}

/* Die Spiegelung: dasselbe Bild kopfueber unter dem Aufsetzpunkt, nach
   unten schnell auslaufend und leicht verwaschen - eine polierte
   Metallflaeche spiegelt weich, nicht wie ein Badezimmerspiegel.

   Das ersetzt das fruehere -webkit-box-reflect: Das spiegelte die ganze
   Schicht mitsamt Schatten und fehlte in Firefox. Der alte Einwand gegen
   ein zweites <img> (verschiedene Massstaebe durch contain/cover) gilt
   nicht mehr, seit beide Bilder dieselbe ausgerechnete Breite haben.

   Der clip-path begrenzt die Spiegelung auf die Ellipse der Tellerflaeche,
   sonst laeuft sie ueber den Podestrand auf den Betonboden - Werte von
   zeichneBuehne(). */
.buehne-spiegel {
  position: absolute;
  z-index: 1;
  top: var(--spiegel-oben, 100%);
  left: 0;
  width: 100%;
  transform: scaleY(-1);
  opacity: 0.30;
  filter: blur(2px) brightness(0.75) saturate(0.8);
  -webkit-mask-image: linear-gradient(to bottom, color-mix(in srgb, black 90%, transparent) 0%, color-mix(in srgb, black 25%, transparent) 22%, transparent 46%);
          mask-image: linear-gradient(to bottom, color-mix(in srgb, black 90%, transparent) 0%, color-mix(in srgb, black 25%, transparent) 22%, transparent 46%);
  clip-path: ellipse(var(--teller-rx, 60%) var(--teller-ry, 26px) at 50% 0);
}

/* Der Grundschatten: die Silhouette der Maschine, am Boden auf ein Sechstel
   gestaucht, geschwaerzt und verwaschen. Weil er aus dem Bild selbst
   entsteht, folgt er jeder Maschine von allein - laenger unter einem
   Tourer, kuerzer unter einer Supermoto. */
.buehne-schatten {
  position: absolute;
  z-index: 2;
  bottom: var(--schatten-unten, 0px);
  left: 0;
  width: 100%;
  transform: scaleY(0.16);
  transform-origin: bottom;
  filter: brightness(0) blur(10px);
  opacity: var(--schatten-staerke, 0.62);
}

/* Die Aufsetzpunkte: dort, wo die Bodenlinie am tiefsten ist - unter den
   Reifen - wird der Schatten hart und fast schwarz. zeichneBuehne() malt
   sie in diese Leinwand. Ohne Bodenlinie (Standardbild, alte Eintraege)
   bleibt die Leinwand leer und der Grundschatten allein. */
.buehne-kontakt {
  position: absolute;
  z-index: 2;
  /* bottom, left und width setzt setzeBuehnenPlatz() - der Kontaktschatten
     gehoert unter die RAEDER, nicht unter die Bildkante. */
  height: 5%;
  filter: blur(3px);
}

/* Die Glut: das orange Licht des LED-Rings von unten. Eine eingefaerbte
   Kopie der Maschine, auf das untere Viertel maskiert und aufhellend
   daruebergelegt. Bewusst schwach - uebertrieben saehe es aus wie ein
   Aufkleber mit Leuchtrand. */
.buehne-glut {
  position: absolute;
  z-index: 4;
  top: 0;
  left: 0;
  width: 100%;
  opacity: var(--glut-staerke, 0.4);
  filter: sepia(1) saturate(5) hue-rotate(-18deg) brightness(1.35) blur(1px);
  mix-blend-mode: screen;
  /* Der Verlauf beginnt an der BODENLINIE der Maschine, nicht an der
     Bildkante - sonst leuchtet der leere Rand statt der Reifen. */
  -webkit-mask-image: linear-gradient(to top, transparent var(--glut-kante, 0%), color-mix(in srgb, black 95%, transparent) var(--glut-kante, 0%), color-mix(in srgb, black 30%, transparent) calc(var(--glut-kante, 0%) + 14%), transparent calc(var(--glut-kante, 0%) + 30%));
          mask-image: linear-gradient(to top, transparent var(--glut-kante, 0%), color-mix(in srgb, black 95%, transparent) var(--glut-kante, 0%), color-mix(in srgb, black 30%, transparent) calc(var(--glut-kante, 0%) + 14%), transparent calc(var(--glut-kante, 0%) + 30%));
}

/* ---------- Der Hinweis "Dein Bike einfuegen" ----------
   Er erscheint nur, solange kein eigenes Foto da ist. Dann steht im Raum
   eine Beispielmaschine, die zum Bild gehoert - der Hinweis sagt, dass das
   nicht die eigene ist und wie man das aendert.

   Gestaltet als Tafel an der Werkstattwand, nicht als Bedienelement der
   App: Sucherwinkel statt Rahmen, Glas statt Flaeche. Lage und Groesse
   rechnet setzeBuehnenPlatz() aus, damit die Tafel ueber dem Drehteller
   sitzt und der Pfeil auf die Maschine zeigt. */
.buehne-hinweis {
  position: absolute;       /* left, bottom und width setzt garage.js */
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  animation: hinweis-auftauchen 0.5s ease-out both;
}

@keyframes hinweis-auftauchen {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: none; }
}

.hinweis-tafel {
  position: relative;
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  /* Unten mehr Luft als oben: Dort haengt das Abzeichen halb in der Kante,
     und ohne diesen Abstand draengt es sich an die Schrift. */
  padding: 26px 30px 34px;
  border-radius: var(--r-lg);
  /* Glas ueber dem Raumbild: Die Werkstatt bleibt dahinter erkennbar, der
     Text wird trotzdem lesbar. Genau der Fall, fuer den die Designsprache
     Glas vorsieht - eine Linse ueber etwas Echtem.

     DUNKEL getoent, nicht hell: Dahinter liegt eine helle Werkstatt mit
     einer Werkzeugwand voller Kleinteile. Auf hellem Glas haette weisse
     Schrift dort keine Chance. */
  background: linear-gradient(var(--schatten-mittel), var(--schatten-weich));
  -webkit-backdrop-filter: blur(16px) saturate(1.05);
          backdrop-filter: blur(16px) saturate(1.05);
  box-shadow:
    inset 0 1px 0 var(--glas-licht),
    inset 0 -1px 0 var(--schatten-hauch),
    0 12px 34px var(--schatten-weich);
  /* Fuer das Nachgeben beim Antippen weiter unten
     (.buehne-hinweis:active .hinweis-tafel). */
  transition: transform 0.12s ease-out;
}

/* Die vier Sucherwinkel in den Ecken. Sie sagen "hier kommt ein Bild hin",
   ohne dass ein Wort dafuer noetig waere. preserveAspectRatio="none" laesst
   sie mit der Tafel mitwachsen; die Ecken bleiben trotzdem rechtwinklig,
   weil sie kurz sind. */
.hinweis-winkel {
  position: absolute;
  inset: 7px;
  width: calc(100% - 14px);
  height: calc(100% - 14px);
  fill: none;
  stroke: color-mix(in srgb, white 85%, transparent);
  stroke-width: 2.2;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

.hinweis-kamera {
  width: 34px; height: 34px;
  stroke-width: 1.3;
  color: color-mix(in srgb, white 92%, transparent);
}

.hinweis-text {
  font-family: var(--schrift-display);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: color-mix(in srgb, white 95%, transparent);
  text-shadow: 0 1px 10px var(--schatten-mittel);
}

/* Der Zeiger nach unten.

   HIER STAND VORHER ein geschwungener, gestrichelter Pfeil in Weiss. Er war
   auf dem hellen, unruhigen Werkstattbild kaum zu sehen und wirkte wie ein
   Fremdkoerper - ein duenner Strich, der neben der Tafel schwebte.

   Der Ersatz macht drei Dinge anders:

     Er HAENGT an der Tafel, halb in ihre Unterkante eingesenkt, statt
     daneben zu schweben. Dadurch liest er sich als Teil davon.

     Er traegt die SIGNALFARBE, und zwar deren hellen Ton. Weiss geht auf
     diesem Bild unter, weil es selbst voller Weiss ist - und RAL 5005 in
     seiner vollen Tiefe geht auf der grau-blauen Werkstattwand ebenso
     unter. Der helle Ton ist derselbe Farbton, nur so weit aufgehellt,
     dass er sich von der Wand loest.

     Er ist eine FLAECHE mit Schatten, kein Strich. Eine Scheibe von 36
     Punkten setzt sich gegen jeden Untergrund durch, ein 2,6 Punkte breiter
     Strich nicht. */
.hinweis-marke {
  position: absolute;
  left: 50%;
  bottom: -18px;
  width: 36px; height: 36px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent-hell);
  box-shadow:
    0 6px 16px var(--schatten-mittel),
    0 0 0 4px var(--schatten-weich);
  animation: marke-nicken 1.9s ease-in-out infinite;
}
.hinweis-marke svg {
  width: 22px; height: 22px;
  fill: none;
  stroke: var(--accent-ink);
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Das Nicken ist der zweite Grund, warum der Zeiger auffaellt: Bewegung
   sieht das Auge noch am Rand des Blickfelds, Farbe erst beim Hinsehen.
   Bewusst langsam und klein - ein huepfendes Element waere Reklame. */
@keyframes marke-nicken {
  0%, 62%, 100% { transform: translateX(-50%) translateY(0); }
  78%           { transform: translateX(-50%) translateY(5px); }
}

/* Beim Antippen gibt die Tafel spuerbar nach - dieselbe Sprache wie bei den
   uebrigen Glasflaechen der App. Die dazugehoerige Uebergangsdauer steht
   oben im Block von .hinweis-tafel. */
.buehne-hinweis:active .hinweis-tafel { transform: scale(0.97); }

@media (prefers-reduced-motion: reduce) {
  .buehne-hinweis, .hinweis-marke { animation: none; }
  /* Der Leuchtsaum bleibt stehen, nur sein Atmen entfaellt; das
     Lampenflackern entfaellt ganz. */
  .buehne-rand  { animation: none; opacity: 0.75; }
  .buehne-lampe { animation: none; opacity: 0; }
  /* Ohne Drehung staende vom Lauflicht nur ein einzelnes Segment fest im
     Bild - das saehe kaputt aus, also faellt es ganz weg. Kantenlinie
     und heller Schein stehen ohnehin. */
  .buehne-lauf  { display: none; }
}

/* Die Ausgaben neben den Justier-Reglern brauchen etwas mehr Platz als die
   im Freisteller, sonst bricht "100 %" auf zwei Zeilen um. */
#buehneJustierung output { min-width: 46px; white-space: nowrap; }

/* Die Justier-Knoepfe unter den drei Reglern. */
.justierung-knoepfe {
  display: flex;
  gap: var(--s3);
  margin-top: var(--s2);
}
.justierung-knoepfe .btn.klein { padding: 10px 14px; font-size: 14px; }

/* ---------- Das Datenblatt unter dem Raum ---------- */
.garage-inhalt {
  flex: 0 0 auto;
  position: relative;
  z-index: 2;
  margin-top: -20px;    /* schiebt sich unter den Raum, weicher Uebergang */
  padding: 0 var(--s4) var(--s4);
  /* Eine Spalte mit Luft dazwischen. Ohne den Abstand stossen Datenblatt
     und Shop-Leiste aneinander und ihre beiden grossen Radien verschmelzen
     zu einer liegenden Acht. */
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.garage-platte {
  padding: var(--s4);
  border-radius: var(--r-lg);
  background: var(--glas-hauch);
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  border: 1px solid var(--glas-hell);
  box-shadow:
    inset 0 1px 0 var(--glas-heller),
    inset 0 -1px 0 var(--schatten-hauch),
    0 12px 34px var(--schatten-mittel);
}

.garage-leer { display: flex; flex-direction: column; gap: var(--s3); }
.garage-leer .hint { margin: 0; }

.motorrad-umschalter { margin-bottom: var(--s3); }

.motorrad-kopf {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: var(--s3);
}
.motorrad-kopf-text { min-width: 0; }
.motorrad-kopf h3 {
  margin: 0;
  font-family: var(--schrift-display);
  font-weight: 700;
  font-size: clamp(19px, 5.6vw, 25px);
  line-height: 1.1;
  text-transform: uppercase;
}
.motorrad-kopf .sub { margin-top: 2px; }

/* Kleinere Fassung des runden Glasknopfs, fuer Stift und Schliessen. */
.glas-rund.klein { width: 36px; height: 36px; font-size: 20px; line-height: 1; }

/* Drei Werte nebeneinander: Hubraum, Leistung, Baujahr. Untereinander
   braeuchten sie die doppelte Hoehe, und die fehlt auf einer Seite ohne
   Scrollen. */
#garageDatenblatt .stats { grid-template-columns: repeat(3, 1fr); gap: var(--s2); }
#garageDatenblatt .stat { padding: 6px var(--s2); }
#garageDatenblatt .stat .v { font-size: clamp(16px, 4.8vw, 20px); }
#garageDatenblatt .linkbtn { margin-top: var(--s3); }

/* ---------- Das Fenster zum Anlegen und Aendern ----------
   Es liegt ueber allem, auch ueber der unteren Leiste (z-index hoeher als
   deren 900), sonst haette man beim Tippen im Formular die Navigation unter
   den Fingern. */
.garage-dialog {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  background: var(--schatten-stark);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.garage-dialog-blatt {
  width: 100%;
  max-width: 520px;
  max-height: 92dvh;
  display: flex;
  flex-direction: column;
  border-radius: 24px 24px 0 0;
  padding-bottom: env(safe-area-inset-bottom);
}
@media (min-width: 560px) {
  .garage-dialog { align-items: center; }
  .garage-dialog-blatt { border-radius: 24px; max-height: 86dvh; }
}

.garage-dialog-kopf {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s4) var(--s4) var(--s3);
  border-bottom: 1px solid var(--glas-hell);
}
.garage-dialog-kopf h3 {
  margin: 0;
  font-family: var(--schrift-display);
  font-weight: 700;
  font-size: 21px;
  text-transform: uppercase;
}

.garage-dialog-inhalt {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: var(--s4);
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: left;
}
.garage-dialog-inhalt label {
  margin-top: var(--s3);
  font-size: 12px;
  color: var(--muted);
}
.garage-dialog-inhalt input,
.garage-dialog-inhalt select,
.garage-dialog-inhalt textarea {
  /* Ein <input> bringt eine eigene Wunschbreite von etwa 20 Zeichen mit. In
     einem Raster aus 1fr-Spalten gewinnt diese Wunschbreite und schiebt das
     Feld ueber den Rand hinaus - width und min-width nehmen ihr das. */
  width: 100%;
  min-width: 0;
  padding: 12px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hell);
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  box-shadow:
    inset 0 1px 0 var(--glas-rand),
    inset 0 2px 5px var(--schatten-hauch);
}
.garage-dialog-inhalt textarea { resize: vertical; line-height: 1.45; }
.garage-dialog-inhalt input:focus,
.garage-dialog-inhalt select:focus,
.garage-dialog-inhalt textarea:focus { outline: none; border-color: var(--accent-hell); }

/* Waehrend die technischen Daten geholt werden, pulsiert das Feld leicht.
   Ohne das saehe es aus, als passiere nichts. */
.garage-dialog-inhalt input.wird-geholt {
  border-color: var(--accent-hell);
  animation: holen 1s ease-in-out infinite;
}
@keyframes holen { 50% { opacity: 0.55; } }

.dialog-paar { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.dialog-paar > div { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.dialog-paar label { margin-top: var(--s3); }

.btn.klein { flex: 0 0 auto; padding: 7px 11px; font-size: 12.5px; }

/* ---------- Die Anleitung vor der Fotoauswahl ----------
   Liegt ueber dem Garage-Dialog (dessen z-index ist 1200), denn sie wird
   aus ihm heraus geoeffnet. Mittig statt am unteren Rand: Es ist kein
   Formular, das man ausfuellt, sondern etwas zum Lesen. */
.foto-tipp {
  position: fixed;
  inset: 0;
  z-index: 1300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s4);
  background: var(--schatten-stark);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.foto-tipp-blatt {
  width: 340px;
  max-width: 100%;
  padding: var(--s5);
  border-radius: var(--r-lg);
  text-align: center;
}
.foto-tipp-symbol { color: var(--accent-hell); margin-bottom: var(--s2); }
.foto-tipp-blatt h3 {
  margin: 0 0 var(--s4);
  font-family: var(--schrift-display);
  font-weight: 700;
  font-size: 20px;
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

/* Die Punkte linksbuendig, obwohl die Tafel mittig ist: Eine Aufzaehlung
   mittig zu setzen macht sie schwerer lesbar, weil jede Zeile woanders
   anfaengt. Der Punkt davor ist gezeichnet statt vom Browser, damit er in
   der Signalfarbe steht. */
.foto-tipp-liste {
  list-style: none;
  margin: 0 0 var(--s5);
  padding: 0;
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}
.foto-tipp-liste li {
  position: relative;
  padding-left: 20px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--muted);
}
.foto-tipp-liste li::before {
  content: "";
  position: absolute;
  left: 2px; top: 8px;
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent-hell);
}
.foto-tipp-liste strong { color: var(--text); font-weight: 600; }

.foto-tipp-knoepfe { display: flex; gap: var(--s2); }

/* ---------- Das eigene Foto im Dialog ---------- */
.foto-feld {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  margin-top: var(--s4);
  padding: var(--s3);
  border-radius: var(--r-md);
  border: 1px solid var(--glas-hell);
  background: var(--glas-hauch);
}
.foto-feld-kopf {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
}
.foto-feld .label { margin: 0; }
.foto-feld .hint { margin: 0; }
.foto-vorschau:empty { display: none; }
.foto-vorschau { display: flex; flex-direction: column; gap: var(--s2); }
.foto-bild {
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--glas-hell);
  /* Schachbrett, damit man sieht, wo das Bild durchsichtig ist. Ohne das
     koennte man nach dem Freistellen nicht beurteilen, ob es geklappt hat. */
  background-color: var(--surface);
  background-image:
    linear-gradient(45deg, var(--glas-hauch) 25%, transparent 25%, transparent 75%, var(--glas-hauch) 75%),
    linear-gradient(45deg, var(--glas-hauch) 25%, transparent 25%, transparent 75%, var(--glas-hauch) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
}
.foto-bild img { width: 100%; height: 150px; object-fit: contain; display: block; }
.foto-knöpfe { display: flex; gap: var(--s2); flex-wrap: wrap; }

.garage-dialog-fuss {
  flex: 0 0 auto;
  display: flex;
  gap: var(--s2);
  padding: var(--s3) var(--s4) var(--s4);
  border-top: 1px solid var(--glas-hell);
}
.garage-dialog-fuss .btn.ghost { flex: 0 0 auto; color: var(--danger); }

/* ---------- Der Motorrad-Finder im Dialog ----------
   Marke als Knopfreihe, weil die Fahrzeugdatenbank 1684 Marken kennt und
   die allermeisten davon amerikanische Kleinstserien sind. Zwoelf Knoepfe
   decken ab, was in Deutschland tatsaechlich faehrt; fuer alles andere gibt
   es darunter die Suche. */
.finder {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  padding: var(--s3);
  margin-bottom: var(--s3);
  border-radius: var(--r-md);
  border: 1px solid var(--glas-hell);
  background: var(--glas-hauch);
}
.finder .label { margin: 0; }
.finder .hint { margin: 0; }
.finder .dialog-paar label:first-child,
.finder > label { margin-top: var(--s2); }

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

.marken-chip,
.modell-chip {
  flex: 0 0 auto;
  padding: 6px 10px;
  border-radius: var(--r-sm);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hauch);
  color: var(--muted);
  font-family: var(--schrift-text);
  font-size: 12.5px;
  cursor: pointer;
  transition: color 0.14s ease, border-color 0.14s ease, background 0.14s ease;
}
.marken-chip:hover,
.modell-chip:hover { color: var(--text); border-color: var(--glas-licht); }
.marken-chip.active,
.modell-chip.active {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
  font-weight: 600;
}

/* Die Modelltreffer koennen je nach Marke und Jahr siebzig Eintraege sein.
   Ohne Hoehenbegrenzung waere der halbe Dialog eine Knopfwueste, deshalb
   scrollt der Kasten in sich. */
.finder-modelle {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  max-height: 132px;
  overflow-y: auto;
  padding: 2px;
}
.finder-modelle .tiny { margin: 0; width: 100%; }

/* Die Trefferliste der Markensuche liegt direkt unter dem Eingabefeld und
   soll den Dialog nicht laenger machen, sondern in sich scrollen. */
.garage-dialog-inhalt .search-results {
  position: static;
  max-height: 180px;
  margin: 0;
}

/* ============================================================================
   Der Freisteller

   Ein Vollbildfenster ueber allem. Aufbau von oben nach unten: Kopfzeile,
   Buehne mit dem Foto, Regler, Werkzeugleiste. Die Buehne nimmt sich den
   Rest - genau wie in der Garage selbst, damit es sich vertraut anfuehlt.

   Das SCHACHBRETT unter dem Foto ist keine Zierde: Ohne es koennte man gar
   nicht sehen, wo das Bild durchsichtig geworden ist, und damit das Ergebnis
   nicht beurteilen.
   ============================================================================ */

.frei-fenster {
  position: fixed;
  inset: 0;
  z-index: 1400;          /* ueber dem Garagen-Dialog (1200) */
  display: flex;
  flex-direction: column;
  background: var(--bg);
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}

.frei-kopf {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--glas-hell);
}
.frei-kopf h3 {
  margin: 0;
  flex: 1;
  min-width: 0;
  text-align: center;
  font-family: var(--schrift-display);
  font-weight: 700;
  /* Auf 320 Pixeln brach die Zeile sonst um und die Kopfzeile wurde doppelt
     so hoch - Platz, der der Buehne fehlt. */
  font-size: clamp(14px, 4.4vw, 17px);
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.frei-kopf .btn.klein { padding: 8px 16px; font-size: 14px; }

/* Der Fortschrittsbalken beim Laden und Rechnen.

   Zwei Zustaende, und der Unterschied ist Absicht:

     mit Klasse "unbestimmt"   ein Streifen laeuft durch, KEINE Zahl. Fuer
                               Schritte, deren Dauer sich nicht messen laesst.
     ohne                      die Fuellung waechst auf einen echten Anteil,
                               daneben steht, wieviel von wieviel geladen ist.

   Ein erfundener Prozentwert waere schlimmer als gar keiner: Er weckt eine
   Erwartung, die das Programm nicht einloesen kann. */
.frei-fortschritt {
  flex: 0 0 auto;
  padding: var(--s3) var(--s4) 0;
}

.frei-fortschritt-zeile {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s2);
  margin-bottom: 6px;
  font-size: 13px;
  color: var(--muted);
}
.frei-fortschritt-zeile span:last-child {
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

.frei-balken {
  height: 4px;
  border-radius: 2px;
  background: var(--glas-hell);
  overflow: hidden;
}
.frei-balken-füllung {
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: var(--accent);
  transition: width 0.18s linear;
}

/* Der laufende Streifen. Er ist bewusst schmal und wandert von links nach
   rechts wieder heraus - so ist auf einen Blick klar, dass hier nichts
   gezaehlt wird, sondern nur etwas arbeitet. */
.frei-fortschritt.unbestimmt .frei-balken-füllung {
  width: 34%;
  transition: none;
  animation: balken-wandern 1.15s ease-in-out infinite;
}
@keyframes balken-wandern {
  0%   { transform: translateX(-110%); }
  100% { transform: translateX(330%); }
}
/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt statt der
   Wanderung einen ruhig pulsierenden Balken ueber die volle Breite. */
@media (prefers-reduced-motion: reduce) {
  .frei-fortschritt.unbestimmt .frei-balken-füllung {
    width: 100%;
    animation: balken-pulsen 1.6s ease-in-out infinite;
  }
  @keyframes balken-pulsen {
    0%, 100% { opacity: 0.30; }
    50%      { opacity: 1; }
  }
}

.frei-buehne {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s3);
  overflow: hidden;
  /* Verhindert, dass ein Wisch ueber die Leinwand die Seite dahinter
     mitzieht - auf dem Handy sonst ein sicherer Weg, den Strich zu verlieren. */
  overscroll-behavior: contain;
}

.frei-leinwand {
  max-width: 100%;
  max-height: 100%;
  border-radius: var(--r-md);
  /* OHNE touch-action: none nimmt der Browser das Wischen als Scrollen und
     der Pinsel bekommt die Bewegung nie zu sehen. */
  touch-action: none;
  -webkit-user-select: none; user-select: none;
  background-color: var(--surface);
  background-image:
    linear-gradient(45deg, var(--glas-hauch) 25%, transparent 25%, transparent 75%, var(--glas-hauch) 75%),
    linear-gradient(45deg, var(--glas-hauch) 25%, transparent 25%, transparent 75%, var(--glas-hauch) 75%);
  background-size: 18px 18px;
  background-position: 0 0, 9px 9px;
  box-shadow: 0 10px 40px var(--schatten-stark);
}

.frei-regler { flex: 0 0 auto; padding: 0 var(--s4); }
.frei-zeile {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s2) 0;
}
.frei-zeile label {
  flex: 0 0 auto;
  width: 108px;
  font-family: var(--schrift-display);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.frei-zeile .slider {
  flex: 1;
  margin: 0;
  background: var(--glas-rand);
}
.frei-zeile output {
  flex: 0 0 auto;
  width: 30px;
  text-align: right;
  font-family: var(--schrift-display);
  font-variant-numeric: tabular-nums;
  font-size: 15px;
}

.frei-werkzeuge {
  flex: 0 0 auto;
  display: flex;
  gap: 4px;
  padding: var(--s2) var(--s3) var(--s3);
}
.frei-werkzeug {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 9px 2px;
  border-radius: 14px;
  border: 1px solid var(--glas-hell);
  background: var(--glas-hauch);
  color: var(--muted);
  cursor: pointer;
  font-family: var(--schrift-display);
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  transition: color 0.14s ease, background 0.14s ease, border-color 0.14s ease;
}
.frei-werkzeug span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.frei-werkzeug:hover:not(:disabled) { color: var(--text); background: var(--glas-hell); }
.frei-werkzeug.active {
  color: var(--accent-ink);
  background: var(--accent);
  border-color: var(--accent);
}
.frei-werkzeug:disabled { opacity: 0.35; cursor: not-allowed; }

/* =========================================================================
   SHOP

   Der Preisvergleich fuer Ausruestung. Fast alles hier benutzt Bausteine,
   die es schon gibt (.saved-list, .stats, .marken-chip, .accordion) -
   dieser Abschnitt ergaenzt nur, was dem Shop allein gehoert.
   ========================================================================= */

/* Der Demo-Balken. Er sagt auf beiden Shop-Bildschirmen unuebersehbar,
   dass alle Preise Beispieldaten sind. Warmes Orange statt Markenblau,
   weil es eine Warnung ist und keine Schmuckfarbe - dieselbe Logik wie
   bei der Kurvigkeits-Skala, die auch nicht im Markenton faerbt. */
.shop-demo-balken {
  margin: 0 0 var(--s3);
  padding: 8px 14px;
  border: 1px solid color-mix(in srgb, var(--licht-warm) 55%, transparent);
  border-radius: var(--r-sm);
  background: var(--glas-dunkel);
  color: var(--licht-warm);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
}

/* Die Bildergalerie der Produktseite: ein wischbares Band, jedes Bild
   eine volle Breite, scroll-snap laesst es beim Loslassen einschnappen.
   Hier stehen spaeter die echten Produktfotos aus dem Haendlerkatalog;
   bis die Bildlizenz gesichert ist, malt die App das Kategorie-Symbol
   mit einer ehrlichen Beschriftung. */
.galerie { margin-bottom: var(--s3); }
.galerie-band {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;            /* das Band selbst zeigt, wo man ist */
  border-radius: var(--r-md);
  gap: var(--s2);
}
.galerie-band::-webkit-scrollbar { display: none; }
.galerie-bild {
  flex: 0 0 100%;
  scroll-snap-align: center;
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--s2);
  height: 230px;
  margin: 0;
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-md);
  background: var(--glas-hell);
}
.galerie-bild .ic { width: 84px; height: 84px; color: var(--accent-hell); }
.galerie-bild img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: var(--r-md);
}
.galerie-bild figcaption { color: var(--muted); font-size: 12px; }
.galerie-punkte {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: var(--s2);
}
.galerie-punkte span {
  width: 6px;
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--glas-licht);
  transition: background 0.2s ease, transform 0.2s ease;
}
.galerie-punkte span.aktiv {
  background: var(--accent-hell);
  transform: scale(1.3);
}

/* Die Bildkachel in den Listen: gross genug, dass ein echtes Foto etwas
   zeigt, bis dahin das Kategorie-Symbol auf Glas. */
.produkt-mini-bild {
  flex: 0 0 auto;
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-sm);
  background: var(--glas-hell);
}
.produkt-mini-bild .ic { width: 30px; height: 30px; color: var(--accent-hell); }
.produkt-mini-bild img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: var(--r-sm);
}

.produkt-titel { margin: 0; }
.produkt-kategorie { margin: 2px 0 var(--s3); }

/* Die Groessen als stumme Chips - reine Information, keine Auswahl.
   Gewaehlt wird die Groesse spaeter im Shop, nicht hier. */
.groessen-reihe { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--s3); }
.shop-groesse {
  padding: 3px 10px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glas-rand);
  background: var(--glas-hell);
  color: var(--muted);
  font-size: 12px;
}

.produkt-daten { margin-bottom: var(--s3); }
.meinung-text { margin: 0; font-size: 14px; line-height: 1.55; }

/* Eine Angebotszeile traegt mehr Zeilen als eine Tour in "Meine Touren",
   deshalb bekommt der Text etwas Luft nach innen. Das Abzeichen "Anzeige"
   steht in derselben Groesse wie der Platzname - eine Kennzeichnung, die
   kleiner gedruckt ist als das, was sie kennzeichnet, kennzeichnet nichts. */
.angebots-liste .saved-text { gap: 2px; }
.angebot-kopf { display: flex; align-items: center; gap: 8px; }
.angebot-kopf .badge.anzeige { font-size: 13px; color: var(--muted); }

/* Der Gesamtpreis ist DIE Zahl des Vergleichs und steht deshalb im
   Instrumenten-Stil, wie die Messwerte im Rest der App. */
.angebot-gesamt {
  font-family: var(--schrift-display);
  font-size: 18px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/* "Fuer dich": der Grund eines Vorschlags in der Akzentfarbe - er ist
   das Besondere an dieser Liste. Der leere Zustand (noch kein Motorrad
   in der Garage) ist eine Glaskarte mit Abkuerzung dorthin. */
.vorschlag-block { margin-bottom: var(--s3); }
.vorschlag-grund { color: var(--accent-hell); }
.vorschlag-leer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s3);
  border-radius: var(--r-md);
  margin-bottom: var(--s3);
}
.vorschlag-leer .hint { margin: 0; }
.vorschlag-leer .btn { flex: 0 0 auto; }

/* Der Merken-Knopf nimmt die volle Breite unter dem Preisvergleich ein -
   er ist die einzige Handlung auf der Seite, die nichts kostet. */
.merken-knopf { width: 100%; margin-top: var(--s3); }

/* "Direkt zu den Shops": dieselben Chips wie bei den Kategorien, nur
   dass sie nach draussen fuehren. */
.shop-links { display: flex; flex-wrap: wrap; gap: 6px; }

/* Die Shop-Leiste in der Garage: eine schmale, wischbare Reihe aus
   Karten. Sie bleibt bewusst klein - die Buehne mit der Maschine ist der
   Star der Seite, der Shop ist das, was man beim Weiterscrollen findet. */
/* Derselbe Innenabstand wie bei den anderen Platten - sonst steht die
   Ueberschrift der Leiste vier Punkte weiter links als der Motorradname
   darueber, und das faellt genau dann auf, wenn beides untereinander steht. */
.garage-shop { padding: var(--s4); }
.garage-shop-kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: var(--s2);
}
.garage-shop-kopf h3 {
  margin: 0;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.garage-shop-band {
  display: flex;
  gap: var(--s2);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Etwas Luft, damit der Fokusrand der Karten nicht abgeschnitten wird. */
  padding: 2px;
}
.garage-shop-band::-webkit-scrollbar { display: none; }
.garage-shop-karte {
  flex: 0 0 108px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  padding: 0;
  border: none;
  background: none;
  color: var(--text);
  text-align: left;
  font-family: var(--schrift-text);
  cursor: pointer;
}
.garage-shop-karte .produkt-mini-bild { width: 100%; height: 58px; }
.garage-shop-name {
  font-size: 12px;
  line-height: 1.25;
  display: -webkit-box;
  -webkit-line-clamp: 2;      /* lange Namen enden nach zwei Zeilen */
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.garage-shop-meta { font-size: 11px; color: var(--accent-hell); }

/* Der kleine Demo-Vermerk neben der Ueberschrift der Garage-Leiste. Er
   ist Pflicht, nicht Schmuck: Die Leiste zeigt Preise ausserhalb der
   Shop-Bildschirme, deren grosser DEMO-Balken hier nicht zu sehen ist. */
.garage-shop-demo {
  margin-left: 6px;
  padding: 1px 8px;
  border-radius: var(--r-pill);
  border: 1px solid color-mix(in srgb, var(--licht-warm) 55%, transparent);
  color: var(--licht-warm);
  font-size: 10px;
  letter-spacing: 0.04em;
}

/* ---------- Das Menue unten in der Garage ----------
   Seit die Garage der Startbildschirm ist, stehen hier die Wege in die
   uebrigen Bereiche. Die Ueberschrift traegt denselben leisen Ton wie die
   der Shop-Leiste darueber - beides sind Abschnitte, nicht Titel. */
.garage-menue { margin-top: var(--s2); }
.garage-menue-kopf {
  margin: 0 0 var(--s2);
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Waehrend "Punkt auf der Karte setzen" an ist, wird der Zeiger zum
   Fadenkreuz. Auf dem Handy sieht man das zwar nicht, aber die Meldung
   dort sagt es - und am Rechner ist es der schnellste Hinweis darauf,
   dass der naechste Klick etwas anderes tut als sonst. */
body.kartenklick #map { cursor: crosshair; }

/* ---------- Navigation: Glas kostet hier zu viel ----------
   Die beiden Navi-Platten liegen ueber einer Karte, die sich in jedem
   Bild dreht und verschiebt. Ein backdrop-filter muss deshalb in JEDEM
   Bild den Untergrund zurueckholen, herunterrechnen, weichzeichnen und
   neu zusammensetzen - zweimal, ueber die volle Bildschirmbreite. Genau
   das kostet auf dem iPhone die Bildrate.

   Waehrend der Fahrt wiegt Lesbarkeit ohnehin schwerer als Glas: Sonne
   auf dem Display, Handschuhe, ein Blick von einer Sekunde. Deshalb hier
   eine ruhige, fast deckende Flaeche statt einer Linse. */
body.nav-modus .nav-banner,
body.nav-modus .nav-fuss {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--schatten-voll);
}

/* ---------- Bedienung waehrend der Fahrt ----------
   Drei runde Knoepfe am rechten Rand, zwischen Manoevertafel und
   Fahrdatenleiste. Gross genug fuer Handschuhe (48 Punkte), und wie die
   beiden Platten ohne backdrop-filter - hier zaehlt jede Bildrate. */
.nav-knoepfe {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 900;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}
.nav-rund {
  width: 48px; height: 48px;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  border: 1px solid var(--glas-rand);
  background: var(--schatten-voll);
  color: var(--text);
  font-family: var(--schrift-display);
  font-size: 26px;
  line-height: 1;
  cursor: pointer;
}
.nav-rund:active { background: var(--glas-heller); }
/* Der Zentrieren-Knopf traegt die Akzentfarbe: Er erscheint nur, wenn die
   Karte gerade NICHT der Position folgt, und ist dann das Wichtigste auf
   dem Bildschirm. */
#btnNavZentrieren { color: var(--accent-hell); border-color: var(--accent-hell); }
.nav-rund .ic { width: 24px; height: 24px; }

/* Der Schraeglage-Block auf dem Aufzeichnen-Bildschirm. Er steht vor dem
   Start-Knopf, weil der Nullpunkt im Stand gesetzt werden muss. */
.neigung-block {
  margin: var(--s3) 0;
  padding: var(--s3);
  border: 1px solid var(--glas-rand);
  border-radius: var(--r-md);
  background: var(--glas-hell);
}
.neigung-block .hint { margin: 0 0 var(--s2); }
.neigung-block .hint:last-child { margin: var(--s2) 0 0; }

/* Die Namensnennung waehrend der Navigation. Klein und dezent, aber
   sichtbar - sie ist Pflicht und darf deshalb nicht hinter etwas
   verschwinden. Sitzt ueber der Fahrdatenleiste am linken Rand. */
.nav-quelle {
  position: absolute;
  left: 12px;
  bottom: calc(max(12px, env(safe-area-inset-bottom)) + 72px);
  margin: 0;
  z-index: 900;
  padding: 2px 6px;
  border-radius: var(--r-sm);
  background: var(--schatten-mittel);
  color: var(--muted);
  font-size: 10px;
}
.nav-quelle a { color: var(--muted); }

/* Der Suchknopf in den Ortsfeldern. Gesucht wird auf Absenden, nicht
   beim Tippen - der Grund steht in app.js bei der Ortssuche. */
.such-knopf {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 34px; height: 34px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-pill);
  background: var(--glas-heller);
  color: var(--text);
  cursor: pointer;
}
.such-knopf:active { background: var(--glas-licht); }
.such-feld .search-input { padding-right: 48px; }

/* Der Knopf, der die Route wirklich berechnet. */
.route-knopf { width: 100%; margin-top: var(--s3); }
.route-knopf:disabled { opacity: 0.45; cursor: not-allowed; }
#routeKnopfHinweis { margin-top: 6px; text-align: center; }
