/**
 * app.css · Familien Wunschliste 2.0 — das komplette Design-System
 *
 * **Diese Datei wird von Hand gepflegt und direkt ausgeliefert.** Kein Build, kein
 * Node, kein npm: Ändern, in die beiden `style/`-Ordner kopieren, per WinSCP hochladen.
 *
 * Sie ist die einzige Quelle für das Aussehen von Homepage, Web-App und App-Hülle.
 * Grundlage ist das Marketing Kit (Stand August 2026, `docs/`).
 *
 * Aufbau:
 *   1. Schriften (selbst gehostet — kein Google-CDN, DSGVO)
 *   2. Token als CSS-Variablen, Weihnachts-Layer
 *   3. Grundlagen
 *   4. Kleine Helfer (die wenigen Klassen, die Vorlagen direkt benutzen)
 *   5. Rahmen der App: Kopfzeile, Screen, Tab-Leiste
 *   6. Bausteine: Karten, Wünsche, Einkaufsliste, Schaltflächen, Abzeichen, Felder
 *   7. Homepage: Kopf, Fuß, Hero-Kosmos, Abschnitte, Blog, Fließtext
 *   8. Eigenbewegung des Kosmos
 *
 * Konventionen:
 *   - Farben **nur** über die Variablen aus Abschnitt 2, nie als Hex-Wert im Regelwerk.
 *   - Eine Komponente = eine Klasse mit sprechendem Namen. Keine Utility-Ketten im HTML;
 *     die Ausnahmen stehen gesammelt in Abschnitt 4.
 *   - Mobil zuerst; Abweichungen für größere Bildschirme stehen in `@media (min-width: 640px)`.
 *   - Tippflächen mindestens 3rem (48 px) — die Zielgruppe reicht bis zu den Großeltern.
 */

/* ==================================================================== */
/* 1. Schriften                                                         */
/* ==================================================================== */
/* Die Dateien liegen neben dieser Datei in `fonts/`. `font-display: swap`
   zeigt sofort die Fallback-Schrift — auf einer langsamen Mobilverbindung
   steht der Text da, bevor die Schrift ankommt. */

@font-face {
  font-family: 'Fredoka';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/fredoka-latin-500-normal.woff2') format('woff2'),
       url('fonts/fredoka-latin-500-normal.woff') format('woff');
}
@font-face {
  font-family: 'Fredoka';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/fredoka-latin-600-normal.woff2') format('woff2'),
       url('fonts/fredoka-latin-600-normal.woff') format('woff');
}
@font-face {
  font-family: 'Fredoka';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/fredoka-latin-700-normal.woff2') format('woff2'),
       url('fonts/fredoka-latin-700-normal.woff') format('woff');
}
@font-face {
  font-family: 'Quicksand';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/quicksand-latin-400-normal.woff2') format('woff2'),
       url('fonts/quicksand-latin-400-normal.woff') format('woff');
}
@font-face {
  font-family: 'Quicksand';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/quicksand-latin-500-normal.woff2') format('woff2'),
       url('fonts/quicksand-latin-500-normal.woff') format('woff');
}
@font-face {
  font-family: 'Quicksand';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/quicksand-latin-600-normal.woff2') format('woff2'),
       url('fonts/quicksand-latin-600-normal.woff') format('woff');
}

/* ==================================================================== */
/* 2. Token                                                             */
/* ==================================================================== */
/* RGB-Kanäle statt fertiger Farben, damit überall `rgb(var(--c-x) / 0.4)`
   möglich ist — eine Farbe, beliebige Deckkraft. */

:root {
  /* Kosmos-Palette (Marketing Kit 02) */
  --c-night:  43 11 63;    /* #2B0B3F  Grund, Flächen */
  --c-violet: 122 47 160;  /* #7A2FA0  Karten, Übergänge */
  --c-pink:   245 53 158;  /* #F5359E  CTA, Akzent */
  --c-orange: 247 144 33;  /* #F79021  Illustration */
  --c-gold:   252 196 78;  /* #FCC44E  Sterne, Highlights */
  --c-aqua:   99 211 222;  /* #63D3DE  Frische, Icons */
  --c-light:  247 243 234; /* #F7F3EA  heller Grund */

  /* Weihnachts-Layer */
  --c-xmas-red:   200 16 46;  /* #C8102E */
  --c-xmas-green: 31 111 74;  /* #1F6F4A */

  /* Semantische Token — nur diese benutzen die Regeln unten */
  --c-bg:      var(--c-night);
  --c-surface: var(--c-violet);
  --c-cta:     var(--c-pink);
  --c-ink:     43 11 63;      /* Text auf hellem Grund */
  --c-ink-inv: 255 255 255;   /* Text auf dunklem Grund */
  --c-muted:   208 195 220;   /* Nebentext auf dunklem Grund */
  --c-line:    255 255 255;   /* Linien; immer mit Deckkraft benutzen */
  --c-decor-a: var(--c-aqua);
  --c-decor-b: var(--c-orange);

  /* Maße */
  --radius-card: 1.25rem;
  --radius-pill: 999px;
  --touch: 3rem;            /* kleinste Tippfläche */
  --kopfband: 8.5rem;       /* Höhe des Kosmos-Bands über der Kopfzeile */
  --breite-text: 38rem;     /* höchstens 70 Zeichen je Zeile (Marketing Kit) */
  --breite-screen: 46rem;

  --schatten-card: 0 10px 30px -12px rgb(0 0 0 / 0.45);
  --schatten-lift: 0 16px 40px -14px rgb(0 0 0 / 0.55);

  --schrift-kopf: 'Fredoka', 'Trebuchet MS', Verdana, sans-serif;
  --schrift-text: 'Quicksand', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
}

/* Ab Oktober setzt render_theme() `data-theme="xmas"` auf <html>.
   Der Layer ergänzt, er ersetzt nicht: Grund bleibt Nachtviolett,
   CTA bleibt Pink — getauscht wird nur die Dekoration. */
[data-theme='xmas'] {
  --c-decor-a: var(--c-xmas-green);
  --c-decor-b: var(--c-xmas-red);
}

/* ==================================================================== */
/* 3. Grundlagen                                                        */
/* ==================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;   /* kein Vergrößern beim Drehen des Geräts */
}

body {
  margin: 0;
  min-height: 100vh;
  font-family: var(--schrift-text);
  /* Grundgröße 18 px statt 16 px: Die Zielgruppe reicht bis zu den Großeltern. */
  font-size: 1.125rem;
  line-height: 1.6;
  color: rgb(var(--c-ink-inv));
  background-color: rgb(var(--c-bg));
  /* Der Kosmos als Grund: ein warmer Schimmer oben, sonst Nachtviolett.
     Kein Bild — das ist sofort da. */
  background-image:
    radial-gradient(60rem 30rem at 50% -10rem, rgb(var(--c-violet) / 0.55), transparent 70%),
    radial-gradient(30rem 20rem at 110% 10%, rgb(var(--c-decor-b) / 0.12), transparent 70%);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--schrift-kopf);
  font-weight: 600;
  line-height: 1.15;
}

h1 { font-size: 1.875rem; }
h2 { font-size: 1.5rem; }
h3 { font-size: 1.25rem; }

p { margin: 0; }

a {
  color: rgb(var(--c-decor-a));
  text-underline-offset: 2px;
}
a:hover { text-decoration: underline; }

img { max-width: 100%; }

button { font: inherit; }

/* Sichtbarer Fokus für alles, was per Tastatur erreichbar ist — für manche
   Nutzer ist die Tastatur der einzige Weg. */
:focus-visible {
  outline: none;
  border-radius: 0.5rem;
  box-shadow: 0 0 0 2px rgb(var(--c-bg)), 0 0 0 6px rgb(var(--c-gold) / 0.7);
}

/* Wer im Betriebssystem weniger Bewegung eingestellt hat, bekommt keine. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

@media (min-width: 640px) {
  h1 { font-size: 2.25rem; }
  h2 { font-size: 1.875rem; }
}

/* ==================================================================== */
/* 4. Kleine Helfer                                                     */
/* ==================================================================== */
/* Die einzigen Klassen, die Vorlagen direkt setzen dürfen. Bewusst kurz
   gehalten — alles Wiederkehrende gehört als Komponente hierher, nicht als
   Kette von Helfern ins HTML. */

.hidden { display: none; }

.mt-2 { margin-top: 0.5rem; }
.mt-4 { margin-top: 1rem; }
.mt-6 { margin-top: 1.5rem; }
.mt-8 { margin-top: 2rem; }

.mx-auto { margin-left: auto; margin-right: auto; }
.text-center { text-align: center; }
.flex { display: flex; }
.flex-wrap { flex-wrap: wrap; }
.gap-2 { gap: 0.5rem; }
.max-w-prose { max-width: var(--breite-text); }

/* Nur für Screenreader: sichtbar für die Vorlesesoftware, nicht auf dem Schirm. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ==================================================================== */
/* 5. Rahmen der App                                                    */
/* ==================================================================== */

.app {
  /* Platz für Tab-Leiste und die Home-Anzeige auf dem iPhone. */
  padding-bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px));
}

/* --- Kopfband ---------------------------------------------------------- */
/* Die Anspielung auf die Homepage: ein Ausschnitt des Kosmos mit dem Logo in der
   Mitte. Es scrollt mit — die Kopfzeile darunter bleibt kleben. Genau so war es in
   der App 1.2: oben das Weltall, darunter der Inhalt.

   Die Ebenen darin sind dieselben wie auf der Homepage (`.hero-layer`,
   `.cloudband`); bewegt werden sie hier ohne JavaScript, nur über die
   Animationen aus Abschnitt 8. */

.app-hero {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  height: var(--kopfband);
  padding-top: env(safe-area-inset-top, 0px);
  overflow: hidden;
  background: radial-gradient(120% 130% at 50% 0%,
                              rgb(var(--c-violet) / 0.45),
                              rgb(var(--c-night)) 70%);
}

/* Das violette Wolkenband am oberen Rand — dieselbe Welle wie auf der Homepage.
   Bewusst **ohne** `z-index`: `.cloudband` (Abschnitt 12) bringt `z-index: 10` mit und
   steht weiter unten in dieser Datei — bei gleicher Spezifität gewinnt die spätere
   Regel. Eine kleinere Zahl an dieser Stelle bliebe wirkungslos und läse sich wie eine
   Zusage, die das Band nicht hält. Es liegt damit über Planet, Mond und Sternen; genau
   so ist das Bild gemeint. Über dem Band steht allein das Logo. */
.app-hero-band { top: -0.5rem; opacity: 0.85; }

/* Der große Planet schaut von links herein, angeschnitten. */
.app-hero-planet {
  left: -3.25rem;
  top: 1.25rem;
  width: 8rem;
  z-index: 3;
  opacity: 0.9;
}

.app-hero-mond {
  right: 1rem;
  top: 1rem;
  width: 2.75rem;
  z-index: 3;
  opacity: 0.75;
}

.app-hero-stern { z-index: 4; }

/* Das Logo mittig, mit den runden Ecken aus der alten App.
   Die Ebene liegt über dem Wolkenband (10) — mit der 5 von vorher verschwand die obere
   Hälfte des Logos unter dem Band (gemeldet 2026-08-24). Unter der klebenden Kopfzeile
   bleibt es: `.topbar` steht auf 30. */
.app-hero-logo {
  position: relative;
  z-index: 20;
  display: block;
  width: 4.5rem;
  height: 4.5rem;
  border-radius: 1.25rem;
  box-shadow: var(--schatten-card);
}

/* Auf einem sehr flachen Bildschirm (Handy quer) frisst das Band zu viel Platz. */
@media (max-height: 34rem) {
  :root { --kopfband: 5.5rem; }
  .app-hero-logo { width: 3rem; height: 3rem; }
  .app-hero-planet { width: 5.5rem; top: 0.75rem; }
}

.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1rem;
  padding-top: calc(0.75rem + env(safe-area-inset-top, 0px));
  background: linear-gradient(to bottom, rgb(var(--c-night)), rgb(var(--c-night) / 0.86));
  backdrop-filter: blur(8px);
  border-bottom: 1px solid rgb(var(--c-line) / 0.1);
}

.topbar-back {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: var(--touch);
  height: var(--touch);
  border-radius: var(--radius-pill);
  font-size: 1.875rem;
  line-height: 1;
  color: rgb(var(--c-ink-inv));
  background: rgb(var(--c-line) / 0.1);
}
/* `a:hover` weiter oben unterstreicht jeden Link — und ist mit seiner Pseudoklasse
   spezifischer als `.topbar-back`. Auf dem Handy bleibt dieser Zustand nach dem
   Antippen kleben, und unter dem Pfeil stand ein Strich (gemeldet 2026-08-23).
   Deshalb hier ausdrücklich für alle drei Zustände. */
.topbar-back,
.topbar-back:hover,
.topbar-back:focus,
.topbar-back:active { text-decoration: none; }
.topbar-back:hover { background: rgb(var(--c-line) / 0.18); }

.topbar-back-icon { width: 26px; height: 26px; }

.topbar-title {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--schrift-kopf);
  font-size: 1.25rem;
  font-weight: 600;
}

.screen {
  width: 100%;
  max-width: var(--breite-screen);
  margin: 0 auto;
  padding: 1.25rem 1rem;
}

.screen-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 1.5rem;
}

/* Der eine Knopf, um den es auf der Wunschliste geht: mittig, mit Luft, allein
   (Festlegung 2026-08-23). Links in einer Reihe sah er aus, als fehlte daneben etwas. */
.wish-add {
  margin: 0.5rem 0 1.5rem;
  text-align: center;
}
.wish-add .btn { width: 100%; max-width: 22rem; }
.wish-add-hint { margin-top: 0.5rem; font-size: 0.875rem; color: rgb(var(--c-muted)); }

/* Ein Satz über einem Formular — sagt vor dem Tippen, was danach passiert. */
.form-intro {
  margin-bottom: 1.5rem;
  padding: 0.875rem 1.125rem;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
  font-size: 0.9375rem;
}

/* --- Seiten vor der Anmeldung ---------------------------------------- */
/* Anmelden, Passwort vergessen, Konto bestätigen: kein Familienwechsel, keine
   Tab-Leiste. Der Inhalt steht mittig und schmal — es gibt genau eine Sache
   zu tun. */

/* Kein zusätzlicher Fuß: Kopfband plus Screen füllen den Bildschirm schon genau aus
   (siehe .screen--plain), und 3rem obendrauf hießen 3rem Scrollweg ohne Inhalt. */
.app--plain { padding-bottom: 0; }

/* Der Rest des Bildschirms unter dem Kopfband. Das Logo steht dort und nicht mehr
   hier — sonst stünde es zweimal übereinander. */
.screen--plain {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: calc(100vh - var(--kopfband));
  min-height: calc(100svh - var(--kopfband));
  padding: 1.5rem 1rem 2rem;
}

.plain-card {
  width: 100%;
  max-width: 26rem;
  padding: 2rem 1.5rem;
  border: 1px solid rgb(var(--c-line) / 0.12);
  border-radius: var(--radius-card);
  background: linear-gradient(160deg, rgb(var(--c-surface) / 0.85), rgb(var(--c-surface) / 0.45));
  box-shadow: var(--schatten-card);
}

.plain-title { font-family: var(--schrift-kopf); font-size: 1.5rem; font-weight: 600; text-align: center; }
.plain-text { margin-top: 0.75rem; text-align: center; color: rgb(var(--c-muted)); }
.plain-card .form { margin-top: 1.5rem; }
.plain-card .btn { width: 100%; }

.plain-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.5rem;
  margin-top: 1.5rem;
  font-size: 0.875rem;
}

/* Zwei Karten untereinander gibt es genau einmal: freischalten und „keine E-Mail
   bekommen?" auf `confirm_code`. Ohne diesen Abstand klebten sie aneinander. */
.plain-card + .plain-card { margin-top: 1.5rem; }

/* Der Freischaltcode. Sechs Ziffern, die man aus einer E-Mail abtippt — groß,
   mittig und weit gesperrt, damit beim Vergleichen keine Ziffer verrutscht. */
.field-input--code {
  text-align: center;
  font-size: 1.75rem;
  letter-spacing: 0.4em;
  text-indent: 0.4em;   /* gleicht die Sperrung hinter der letzten Ziffer aus */
}

/* --- Tab-Leiste ------------------------------------------------------ */
/* Vier große Flächen, immer sichtbar. Symbol oben, Wort klein darunter — so
   kannte man es aus der App 1.2 (dort 11px unter dem Symbol). Beides zusammen:
   Ein Symbol ohne Wort ist für die Großeltern ein Rätsel, ein Wort ohne Symbol
   lässt sich im Vorbeigehen nicht erfassen. Die Tippfläche bleibt die ganze
   Kachel, nicht nur das Symbol. */

.tabbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.25rem;
  padding: 0.5rem 0.5rem calc(0.5rem + env(safe-area-inset-bottom, 0px));
  background: rgb(var(--c-night) / 0.96);
  border-top: 1px solid rgb(var(--c-line) / 0.12);
}

.tabbar-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.1875rem;
  min-height: var(--touch);
  padding: 0.375rem 0.125rem;
  border-radius: var(--radius-card);
  font-size: 0.6875rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  color: rgb(var(--c-muted));
}

/* Nimmt die Farbe des Eintrags an (`currentColor` im SVG) — deshalb steht hier
   keine Farbe. */
.tabbar-icon {
  display: block;
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
}
.tabbar-item:hover { color: rgb(var(--c-ink-inv)); text-decoration: none; }

.tabbar-item.is-active {
  color: rgb(var(--c-ink-inv));
  background: rgb(var(--c-cta) / 0.22);
  box-shadow: inset 0 0 0 1px rgb(var(--c-cta) / 0.5);
}

/* Der lange Name darf die Kachel nicht sprengen; `Einkaufsliste` ist der
   Grenzfall auf einem schmalen Telefon. */
.tabbar-label {
  max-width: 100%;
  overflow: hidden;
  line-height: 1.2;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ==================================================================== */
/* 6. Bausteine                                                         */
/* ==================================================================== */

/* Die Kachel bringt ihren Innenabstand selbst mit (2026-08-23). Vorher war sie ein
   reiner Rahmen, und jede Variante musste an ihr Padding denken — im Shop und im
   Backoffice steht der Text aber oft direkt in einer blanken `.card`, und der klebte
   dann am Rand. Umgekehrt ist es die sichere Voreinstellung: Wer randlos sein will,
   sagt es (die drei Karten mit eigenem Link darunter). */
.card {
  overflow: hidden;
  padding: 1.5rem;
  border-radius: var(--radius-card);
  border: 1px solid rgb(var(--c-line) / 0.12);
  background: linear-gradient(160deg, rgb(var(--c-surface) / 0.85), rgb(var(--c-surface) / 0.45));
  box-shadow: var(--schatten-card);
}

/* Diese drei sind ganzflächig anklickbar: Der Abstand sitzt im Link beziehungsweise
   in den Teilen darin, damit die Tippfläche bis an den Rand geht. */
.wish-card,
.shopping-card,
.family-card { padding: 0; }

.list { display: grid; gap: 1rem; }
.list-shopping { gap: 0.75rem; }
.list-count { margin-bottom: 1rem; font-size: 0.875rem; color: rgb(var(--c-muted)); }

@media (min-width: 640px) {
  .list-wishes { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- Wunschkarte ------------------------------------------------------ */

.wish-card:hover { box-shadow: var(--schatten-lift); }
/* „Schon übernommen": zurückgenommen, aber nicht unlesbar. */
.wish-card.is-taken { opacity: 0.7; }

.wish-card-link {
  display: flex;
  gap: 1rem;
  padding: 0.75rem;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
}
.wish-card-link:hover { text-decoration: none; }

.wish-card-image {
  flex: none;
  width: 6rem;
  height: 6rem;
  object-fit: cover;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

.wish-card-body { flex: 1 1 auto; min-width: 0; }

.wish-card-title {
  font-family: var(--schrift-kopf);
  font-size: 1.125rem;
  font-weight: 600;
  line-height: 1.3;
}

.wish-card-text {
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: rgb(var(--c-muted));
  /* Zwei Zeilen, dann Auslassungspunkte. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

.wish-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
}

.wish-card-price { font-weight: 600; color: rgb(var(--c-gold)); }

@media (min-width: 640px) {
  .wish-card-link { flex-direction: column; padding: 0; }
  .wish-card-image { width: 100%; height: 11rem; border-radius: 0; }
  .wish-card-body { padding: 1rem; }
}


/* --- Anklickbare Flächen ---------------------------------------------- */
/* Eine Kachel, die weiterführt, braucht kein Symbol am Ende und keinen Knopf
   daneben (Festlegung 2026-08-23) — wer eine App bedient, tippt auf das Ding
   selbst. Was sie braucht, ist die Antwort auf die Berührung: Sie geht unter dem
   Finger kurz ein Stück ein. Das ist die Rückmeldung, die auf dem Handy zählt —
   `:hover` gibt es dort nicht. */

.family-card,
.member-link,
.wish-card,
.shopping-card { transition: transform 0.12s ease-out, box-shadow 0.2s; }

.family-card:active,
a.member-link:active,
.wish-card:active,
.shopping-card:active { transform: scale(0.985); }

@media (prefers-reduced-motion: reduce) {
  .family-card:active,
  a.member-link:active,
  .wish-card:active,
  .shopping-card:active { transform: none; }
}

/* --- Ladeschirm beim Seitenwechsel ------------------------------------- */
/* Kommt verzögert (app.js, 350 ms) und ist deshalb im Normalfall nie zu sehen.
   Wenn er kommt, dann ganzflächig und ruhig: ein Geschenk, das leicht atmet, und
   ein Satz. Kein Kreisel — das Symbol ist dasselbe, das die Wunschliste führt. */

.ladeschirm {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgb(var(--c-bg) / 0.94);
  opacity: 0;
  /* Solange er nicht zu sehen ist, faengt er auch keine Beruehrung ab. */
  pointer-events: none;
  transition: opacity 0.15s ease-out;
}

/* **Diese Zeile ist die wichtige** (2026-08-23): Ein eigenes `display` schlaegt das
   Attribut `hidden` aus dem Browser-Stylesheet. Ohne sie liegt der Schirm unsichtbar
   ueber der ganzen Seite und schluckt jeden Klick — im Browser war nichts mehr
   anklickbar, waehrend die App-Huelle lief, weil es dort kein `#ladeschirm` gibt. */
.ladeschirm[hidden] { display: none; }

.ladeschirm.is-visible { opacity: 1; pointer-events: auto; }

.ladeschirm-inhalt { display: grid; justify-items: center; gap: 1rem; }

.ladeschirm-icon {
  width: 4.5rem;
  height: 4.5rem;
  color: rgb(var(--c-cta));
  animation: geschenk-atmen 1.4s ease-in-out infinite;
}

.ladeschirm-text { color: rgb(var(--c-muted)); }

@keyframes geschenk-atmen {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.12); }
}

/* Wer Bewegung abgestellt hat, bekommt das Symbol ruhig — sichtbar bleibt es. */
@media (prefers-reduced-motion: reduce) {
  .ladeschirm-icon { animation: none; }
  .ladeschirm { transition: none; }
}

/* --- Wunsch-Detail ---------------------------------------------------- */

.wish-detail { display: grid; gap: 1rem; }

.wish-detail-image {
  width: 100%;
  max-height: 26rem;
  object-fit: cover;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

.wish-detail-title { font-family: var(--schrift-kopf); font-size: 1.5rem; font-weight: 600; }
.wish-detail-owner { font-size: 0.875rem; color: rgb(var(--c-muted)); }
.wish-detail-price { font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; color: rgb(var(--c-gold)); }

.wish-detail-text {
  max-width: var(--breite-text);
  white-space: pre-line;
  line-height: 1.7;
}

.wish-detail-link { display: inline-block; overflow-wrap: break-word; color: rgb(var(--c-decor-a)); }

.wish-detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-top: 0.5rem;
}

/* --- Einkaufsliste ---------------------------------------------------- */
/* Der Screen setzt zusätzlich `is-status-0|1|2` (0 = noch nicht gekauft,
   1 = gekauft, 2 = verpackt; core/purchases.php). Ein farbiger Streifen links
   zeigt den Stand, ohne dass man den Text lesen muss. */

/* Der Streifen links zeigt die Stufe: übernommen, gekauft, verpackt. */
.shopping-card { border-left: 4px solid rgb(var(--c-line) / 0.18); }
.shopping-card.is-status-0 { border-left-color: rgb(var(--c-line) / 0.18); }
.shopping-card.is-status-1 { border-left-color: rgb(var(--c-gold)); }
.shopping-card.is-status-2 { border-left-color: rgb(var(--c-decor-a)); }

.shopping-card-link {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
}
.shopping-card-link:hover { text-decoration: none; }

.shopping-card-image {
  flex: none;
  width: 4rem;
  height: 4rem;
  object-fit: cover;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

.shopping-card-body { flex: 1 1 auto; min-width: 0; }
.shopping-card-title { font-family: var(--schrift-kopf); font-size: 1.125rem; font-weight: 600; line-height: 1.3; }
.shopping-card-meta { margin-top: 0.25rem; font-size: 0.875rem; color: rgb(var(--c-muted)); }
.shopping-card-status { flex: none; font-size: 0.875rem; font-weight: 600; color: rgb(var(--c-gold)); }

/* Die drei Stufen zum Antippen — statt eines Auswahlfelds, das auf dem Handy einen
   Systemdialog öffnet (Festlegung 2026-08-23, so war es in der App 1.2).
   Alle drei sind immer sichtbar: Man sieht auf einen Blick, wo man steht und wie weit
   es noch ist. */
.status-wahl {
  display: flex;
  gap: 0.5rem;
  padding: 0 0.75rem 0.75rem;
}

.status-knopf {
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  min-height: var(--touch);
  padding: 0.5rem 0.25rem;
  border: 0;
  border-radius: var(--radius-card);
  color: rgb(var(--c-muted));
  background: rgb(var(--c-line) / 0.07);
  font-family: var(--schrift-text);
  cursor: pointer;
}
.status-knopf:hover { background: rgb(var(--c-line) / 0.14); }

.status-knopf.is-active {
  color: rgb(var(--c-night));
  background: rgb(var(--c-gold));
}

.status-icon  { width: 26px; height: 26px; }
.status-label { font-size: 0.75rem; font-weight: 600; }

/* --- Familien --------------------------------------------------------- */

.family-card:hover { box-shadow: var(--schatten-lift); }
/* Die gerade geöffnete Familie ist die, deren Wünsche man sieht — das muss man
   auf einen Blick erkennen. */
.family-card.is-current { box-shadow: inset 0 0 0 2px rgb(var(--c-cta) / 0.6), var(--schatten-card); }

.family-card-link {
  display: block;
  padding: 1.25rem;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
}
.family-card-link:hover { text-decoration: none; }

/* Der Innenabstand sitzt sonst im Link, der die ganze Kachel ausfüllt (Familienliste).
   Steht die Kachel ohne Link da — im Shop unter `konto.php` —, muss ihn der Rumpf selbst
   mitbringen, sonst klebt der Text am Rand (2026-08-23). */
.family-card-body { min-width: 0; padding: 1.25rem; }
.family-card-link .family-card-body { padding: 0; }
.family-card-title { font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.family-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  font-size: 0.875rem;
  color: rgb(var(--c-muted));
}
/* Knopfreihe am Fuß einer Kachel. In der Familienliste gibt es sie nicht mehr — dort
   ist die Kachel selbst der Weg —, im Shop (`konto.php`) steht sie weiter. */
.family-card-actions { padding: 0 1.25rem 1.25rem; }

/* Abschnitt mit Formular oder Einstellungen — auf allen drei Screens gleich. */
.family-form { margin-top: 1.5rem; padding: 1.5rem; }

/* Beitreten und Gründen sind keine Familie in der Liste, sondern die zwei Wege, an
   eine zu kommen — deshalb heben sie sich ab (Festlegung 2026-08-23). Ein leichter
   Verlauf ins Aqua, dieselbe Palette wie überall, nur eine andere Rolle. */
.family-form-neu {
  border-color: rgb(var(--c-decor-a) / 0.35);
  background:
    linear-gradient(150deg, rgb(var(--c-decor-a) / 0.22), rgb(var(--c-surface) / 0.55) 65%);
}
.family-form-title { font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.family-form .form { margin-top: 1.25rem; }
.family-form .hint { margin-top: 0.5rem; }

/* Löschen und Verlassen: sichtbar abgesetzt, damit niemand versehentlich hier landet. */
.family-danger { border-color: rgb(var(--c-xmas-red) / 0.5); }

.family-head { padding: 1.5rem; }
.family-head-title { font-family: var(--schrift-kopf); font-size: 1.5rem; font-weight: 600; }
.family-head-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  color: rgb(var(--c-muted));
}
.family-head .btn { margin-top: 1rem; }

.family-head-links { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1rem; }

/* „Besonderes Avatar wählen" auf der Familienseite — ein Link mit dem eigenen Bild
   davor, genau wie in der App 1.2 (2026-08-24). Als <button> statt <a>, weil er die
   Auswahl darunter auf- und zuklappt statt zu einer eigenen Seite zu führen. */
.family-avatar-link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.5rem;
  padding: 0;
  border: none;
  background: none;
  font-family: inherit;
  font-size: 1rem;
  color: rgb(var(--c-decor-a));
  cursor: pointer;
}
.family-avatar-link:hover { text-decoration: underline; }
.family-avatar-link img { width: 1.75rem; height: 1.75rem; border-radius: 999px; object-fit: cover; }

/* Wichtel-Hinweis: das Bild hängt oben in die Kachel hinein, genau wie in der
   App 1.2 (2026-08-24). Deshalb `overflow: visible` statt der `.card`-Vorgabe. */
.family-santa {
  position: relative;
  overflow: visible;
  margin-top: 1.5rem;
  padding: 1.25rem 1.25rem 1.25rem 5.5rem;
}
.family-santa-img { position: absolute; left: 1rem; top: -1.5rem; width: 4.5rem; height: auto; }

/* --- Wichteln ----------------------------------------------------------- */
/* Das Wichtelziel ist das Einzige, wofür die meisten diesen Screen öffnen —
   entsprechend groß und ohne Beiwerk. */

.santa-ziele { display: grid; gap: 0.75rem; margin-top: 1rem; }

.santa-ziel {
  display: block;
  padding: 1.25rem;
  border-radius: var(--radius-card);
  text-decoration: none;
  color: rgb(var(--c-ink-inv));
  background: linear-gradient(135deg, rgb(var(--c-cta) / 0.28), rgb(var(--c-cta) / 0.12));
  box-shadow: inset 0 0 0 1px rgb(var(--c-cta) / 0.45);
}
.santa-ziel:hover { text-decoration: none; background: linear-gradient(135deg, rgb(var(--c-cta) / 0.38), rgb(var(--c-cta) / 0.18)); }

.santa-ziel-name {
  display: block;
  font-family: var(--schrift-kopf);
  font-size: 1.5rem;
  font-weight: 600;
}
.santa-ziel .hint { display: block; margin-top: 0.25rem; }

.family-code { margin-top: 1.5rem; padding: 1.5rem; text-align: center; }
.family-code-value {
  margin: 1rem 0;
  font-family: var(--schrift-kopf);
  font-size: 2.25rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  color: rgb(var(--c-gold));
  user-select: all;          /* ein Fingertipp markiert den ganzen Code */
}

.family-members { margin-top: 2rem; }
.family-members .list { margin-top: 1rem; }
.family-pending { margin-top: 1.5rem; padding: 1.5rem; }
.family-pending .list { margin-top: 1rem; }

/* Ein Mitglied in der Liste */
.member {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  border: 1px solid rgb(var(--c-line) / 0.12);
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.06);
}

/* Die ganze Zeile führt zur Wunschliste (Festlegung 2026-08-23) — vorher stand
   dafür ein Knopf „Wünsche ansehen" daneben. Der Abstand sitzt deshalb hier und
   nicht an der Zeile: So geht die Tippfläche bis an den Rand. Das Zahnrad des
   Verwalters bleibt daneben stehen, es ist eine andere Sache. */
.member-link {
  display: flex;
  flex: 1 1 12rem;
  align-items: center;
  gap: 1rem;
  min-width: 0;
  padding: 0.75rem;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
}
.member-link:hover { text-decoration: none; }
a.member-link:hover { background: rgb(var(--c-line) / 0.1); border-radius: var(--radius-card); }

.member-avatar {
  flex: none;
  width: 3.5rem;
  height: 3.5rem;
  /* contain statt cover: Nicht jede Avatar-Sammlung ist quadratisch (Beach Buddies
     sind hochkant). cover schnitte dem Delfin den Kopf ab; alle Avatare haben einen
     durchsichtigen Grund, also passt contain immer. */
  object-fit: contain;
  border-radius: var(--radius-pill);
  background: rgb(var(--c-line) / 0.12);
}

.member-body { flex: 1 1 8rem; min-width: 0; }
.member-name { font-weight: 600; }
.member-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.25rem;
  font-size: 0.875rem;
  color: rgb(var(--c-muted));
}
.member-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding-right: 0.75rem; }

/* --- Das Zahnrad am Mitglied ------------------------------------------- */
/* Was ein Verwalter mit einem einzelnen Mitglied tun kann, steckt dahinter
   (Festlegung 2026-08-23). Vorher stand es als Knopfreihe neben jedem Namen
   und machte die Liste unruhig — dabei braucht man es selten.
   Ein <details>, also ohne eine Zeile JavaScript: Das klappt auch dann auf,
   wenn in der App-Hülle gerade etwas nachlädt. */

.member-menu { position: relative; flex: none; }

.member-menu-knopf {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--touch);
  height: var(--touch);
  border-radius: var(--radius-pill);
  background: rgb(var(--c-line) / 0.12);
  color: rgb(var(--c-ink-inv));
  cursor: pointer;
  list-style: none;          /* Firefox: kein Dreieck */
}
.member-menu-knopf::-webkit-details-marker { display: none; }
.member-menu-knopf:hover { background: rgb(var(--c-line) / 0.2); }
.member-menu[open] .member-menu-knopf { background: rgb(var(--c-cta) / 0.3); }

.member-menu-icon { width: 22px; height: 22px; }

.member-menu-inhalt {
  position: absolute;
  right: 0;
  z-index: 20;
  display: grid;
  gap: 0.5rem;
  min-width: 15rem;
  margin-top: 0.5rem;
  padding: 0.75rem;
  border-radius: var(--radius-card);
  background: rgb(var(--c-bg));
  box-shadow: inset 0 0 0 1px rgb(var(--c-line) / 0.2), var(--schatten-lift);
}
/* Auf schmalen Geräten hat rechts nichts mehr Platz — dann untereinander. */
@media (max-width: 30rem) {
  .member-menu { position: static; }
  .member-menu-inhalt { position: static; min-width: 0; box-shadow: none; padding: 0.5rem 0; }
}

/* --- Wunschformular ---------------------------------------------------- */

.wish-form { margin-top: 1.5rem; max-width: var(--breite-text); }
.wish-form textarea { resize: vertical; line-height: 1.5; }
/* Dateiauswahl: Der native Knopf lässt sich kaum gestalten — deshalb bekommt das
   Feld nur eine ruhige Fläche und genug Platz für den Daumen. */
.wish-form input[type='file'] { padding: 0.75rem; line-height: 1.4; }

.bild-aktuell {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.bild-vorschau {
  width: 6rem;
  height: 6rem;
  object-fit: cover;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

/* --- Produktsuche ------------------------------------------------------- */

.suche-zeile { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem; }
.suche-zeile .field-input { flex: 1 1 12rem; }

.suche-ergebnis { margin-top: 1rem; }

.suche-treffer {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 0.75rem;
}

.suche-treffer-knopf {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem;
  border: 0;
  border-radius: var(--radius-card);
  font-family: var(--schrift-text);
  text-align: left;
  color: rgb(var(--c-ink-inv));
  background: rgb(var(--c-line) / 0.08);
  cursor: pointer;
}
.suche-treffer-knopf:hover { background: rgb(var(--c-line) / 0.16); }
.suche-treffer-knopf img {
  width: 100%;
  height: 7rem;
  object-fit: contain;
  border-radius: 0.5rem;
  background: rgb(var(--c-light));
}
.suche-treffer-titel {
  font-size: 0.875rem;
  line-height: 1.3;
  /* Drei Zeilen — Amazon-Titel sind oft ganze Absätze. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.suche-treffer-preis { font-weight: 600; color: rgb(var(--c-gold)); }

/* Wenn die Produktsuche nicht antwortet, muss man das sehen (gemeldet 2026-08-23).
   Vorher stand der Satz als grauer `.hint` unter dem Feld und ging unter — dabei sagt
   er, dass Weitersuchen nichts bringt und der Wunsch von Hand einzutragen ist. */
.suche-stoerung {
  margin-top: 0.75rem;
  padding: 0.875rem 1rem;
  border-radius: var(--radius-card);
  border-left: 4px solid rgb(var(--c-gold));
  background: rgb(var(--c-gold) / 0.14);
  color: rgb(var(--c-ink-inv));
  font-weight: 600;
}

/* --- Kopf einer Liste --------------------------------------------------- */

.listen-kopf { margin-bottom: 1.25rem; }
.listen-titel { font-family: var(--schrift-kopf); font-size: 1.5rem; font-weight: 600; }
.listen-kopf .list-count { margin-top: 0.25rem; margin-bottom: 0; }

/* Die Seite einer einzelnen Person: Bild groß und mittig über dem Namen
   (Festlegung 2026-08-23). Es ist die einzige Liste, die jemandem gehört — und der
   PRO-Avatar ist gekauft, der darf man sehen. `contain` wie überall, weil nicht
   jede Sammlung quadratisch ist. */
.person-kopf {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  text-align: center;
  margin-bottom: 1.5rem;
}

.person-avatar {
  width: 7rem;
  height: 7rem;
  object-fit: contain;
  border-radius: var(--radius-pill);
  background: rgb(var(--c-line) / 0.12);
  box-shadow: var(--schatten-lift);
}

@media (min-width: 640px) {
  .person-avatar { width: 8.5rem; height: 8.5rem; }
}

/* Die E-Mail-Benachrichtigung auf der Seite einer Person (2026-08-24). In App 1.2 war
   das ein blankes Briefsymbol, dessen Farbe den Zustand trug — hier steht der Zustand
   daneben. Ausgeschaltet ist es ein ruhiger Umriss, eingeschaltet trägt es die
   Frische-Farbe des Marketing Kits; Wunsch-Pink bleibt den echten Aktionen vorbehalten.
   Höhe 3rem = die kleinste Tippfläche des Projekts. */
.person-follow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--touch);
  padding: 0.5rem 1.1rem;
  border: 0;
  border-radius: var(--radius-pill);
  background: rgb(var(--c-line) / 0.12);
  box-shadow: inset 0 0 0 1px rgb(var(--c-line) / 0.28);
  color: rgb(var(--c-ink-inv));
  font-family: var(--schrift-text);
  font-size: 0.9375rem;
  font-weight: 600;
  cursor: pointer;
}

.person-follow.is-on {
  background: rgb(var(--c-aqua) / 0.22);
  box-shadow: inset 0 0 0 2px rgb(var(--c-aqua));
}

.person-follow-icon { width: 1.25rem; height: 1.25rem; flex: none; }

/* --- Konto: kompakte Liste mit Modal (2026-08-24) ----------------------- */
/* Vorher stand jedes Formular offen auf der Seite — dadurch war nichts zu lesen,
   ohne an Formularen vorbeizuscrollen (wie in der App 1.2: `konto.tpl.html`, nur
   dort als aufklappende Liste statt als echtes Dialogfenster). Jetzt steht erst
   der Wert da, „ändern" öffnet das dazugehörige Formular als Modal. */
.konto-liste { display: grid; gap: 0.25rem; margin-top: 1rem; }
.konto-zeile {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.875rem 0;
  border-bottom: 1px solid rgb(var(--c-line) / 0.12);
}
.konto-zeile:last-child { border-bottom: none; }
.konto-zeile-label { display: block; font-size: 0.875rem; color: rgb(var(--c-muted)); }
.konto-zeile-wert { display: block; font-family: var(--schrift-kopf); font-size: 1.0625rem; font-weight: 600; }

/* Natives <dialog>: Fokus-Falle, Esc-Taste und das Abschneiden vom Rest der
   Seite bringt der Browser von allein mit — app.js ergänzt nur das Öffnen per
   Knopf (`data-modal`) und das Schließen per Rand-Klick oder „Abbrechen". */
dialog.modal {
  width: min(26rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  overflow-y: auto;
  margin: auto;
  padding: 1.5rem;
  border: none;
  border-radius: var(--radius-card);
  color: rgb(var(--c-ink-inv));
  background: linear-gradient(160deg, rgb(var(--c-surface) / 0.98), rgb(var(--c-night) / 0.98));
  box-shadow: var(--schatten-lift);
}
dialog.modal::backdrop { background: rgb(var(--c-night) / 0.7); }
.modal-title { margin-bottom: 1rem; }
.modal .hint { margin-bottom: 1.25rem; }
.modal-actions { display: flex; justify-content: flex-end; gap: 0.75rem; }

/* --- Avatarauswahl ----------------------------------------------------- */

.avatar-aktuell { display: flex; align-items: center; gap: 1rem; margin-top: 1rem; }

/* Die Auswahl ist zugeklappt (Festlegung 2026-08-23): 40 PRO-Bilder plus 15 Vögel
   schoben sonst Name, E-Mail und Passwort weit nach unten. */
.avatar-schalter { margin-top: 1rem; }
.avatar-gruppe {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 2rem;
  font-family: var(--schrift-kopf);
  font-size: 1.125rem;
  font-weight: 600;
}

.avatar-wahl {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));
  gap: 0.5rem;
  margin-top: 1rem;
}

/* --- Die Auswahl der Sammlung ------------------------------------------ */
/* Gezeigt, nicht aufgezählt (Festlegung 2026-08-23): „Winterfreunde" und
   „Beach Buddies" sagen niemandem, wie die Avatare aussehen. Jede Sammlung
   steht deshalb als Karte mit sechs Beispielbildern da und wird angetippt —
   ein Auswahlfeld mit Namen wäre hier die falsche Bedienung. */

.sammlung-wahl { display: grid; gap: 1rem; margin-top: 1rem; }

.sammlung {
  display: block;
  width: 100%;
  padding: 1rem;
  border: 0;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
  color: rgb(var(--c-ink-inv));
  font-family: var(--schrift-text);
  text-align: left;
  cursor: pointer;
}
.sammlung:hover { background: rgb(var(--c-line) / 0.14); }
.sammlung.is-active { box-shadow: inset 0 0 0 2px rgb(var(--c-cta)); }

.sammlung-kopf {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}
.sammlung-name { font-family: var(--schrift-kopf); font-size: 1.125rem; font-weight: 600; }
.sammlung-zahl { font-size: 0.875rem; color: rgb(var(--c-muted)); }

.sammlung-bilder {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.4rem;
  margin-top: 0.75rem;
}
.sammlung-bilder img {
  display: block;
  width: 100%;
  height: 3.5rem;
  object-fit: contain;
  border-radius: 0.6rem;
  background: rgb(var(--c-line) / 0.08);
}

.avatar-knopf {
  padding: 0.25rem;
  border: 0;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
  cursor: pointer;
}
/* Feste Zellenhöhe, damit hochkant und quadratisch nebeneinander eine Reihe
   ergeben — die Sammlungen sind nicht auf ein Seitenverhältnis festgelegt. */
.avatar-knopf img { display: block; width: 100%; height: 4rem; object-fit: contain; }
.avatar-knopf:hover { background: rgb(var(--c-line) / 0.16); }
.avatar-knopf.is-active { box-shadow: inset 0 0 0 2px rgb(var(--c-cta)); }

/* --- Schaltflächen ---------------------------------------------------- */
/* Marketing Kit: Weiß auf Pink erst ab 20 px — deshalb steht .btn auf 1.25rem.
   Das passt zugleich zur Bedienung mit dem Daumen. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: var(--touch);
  padding: 0 1.5rem;
  border: 0;
  border-radius: var(--radius-pill);
  font-family: var(--schrift-text);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.1s;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: scale(0.98); }
.btn[disabled], .btn.is-busy { pointer-events: none; opacity: 0.6; }

.btn-primary {
  color: rgb(var(--c-ink-inv));
  background: linear-gradient(135deg, rgb(var(--c-cta)), rgb(var(--c-cta) / 0.82));
  box-shadow: 0 10px 24px -10px rgb(var(--c-cta) / 0.9);
}

.btn-secondary {
  color: rgb(var(--c-ink-inv));
  background: rgb(var(--c-line) / 0.12);
  box-shadow: inset 0 0 0 1px rgb(var(--c-line) / 0.28);
}

/* Löschen, Verlassen, Zurücksetzen — sichtbar anders, aber nicht schreiend. */
.btn-danger {
  color: rgb(var(--c-ink-inv));
  background: rgb(var(--c-xmas-red) / 0.85);
  box-shadow: inset 0 0 0 1px rgb(var(--c-xmas-red));
}

.btn-small {
  min-height: 0;
  padding: 0.5rem 1rem;
  font-size: 1.125rem;
}

/* --- Abzeichen -------------------------------------------------------- */

.badge {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.75rem;
  border-radius: var(--radius-pill);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1;
}

/* Auf Gold nur dunkler Text (Marketing Kit, Kontrastregel). */
.badge-mine  { color: rgb(var(--c-ink)); background: rgb(var(--c-gold)); }
.badge-taken { color: rgb(var(--c-muted)); background: rgb(var(--c-line) / 0.14); }
.badge-idea  { color: rgb(var(--c-ink)); background: rgb(var(--c-decor-a) / 0.9); }

/* --- Familienwechsel und Auswahlfelder -------------------------------- */

/* Auswahlfeld in einem Formular. Ein `data-submit` daran heißt: Auswählen genügt,
   das Formular geht von allein ab (app.js) — so die Statusauswahl auf der
   Einkaufsliste. */
.field-select {
  width: 100%;
  max-width: 100%;
  min-height: var(--touch);
  padding: 0 2.25rem 0 1rem;
  border: 0;
  border-radius: var(--radius-pill);
  font-family: var(--schrift-text);
  font-size: 1.125rem;
  color: rgb(var(--c-ink-inv));
  background-color: rgb(var(--c-line) / 0.12);
  /* Pfeil als Inline-SVG: ein Bild weniger, das laden muss. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%23ffffff'%3E%3Cpath d='M5.5 7.5 10 12l4.5-4.5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 1.25rem;
  appearance: none;
  -webkit-appearance: none;
}
.field-select option { color: rgb(var(--c-ink-inv)); background: rgb(var(--c-night)); }

/* --- Formularfelder --------------------------------------------------- */

.form {
  display: grid;
  gap: 1.25rem;
  max-width: var(--breite-text);
  margin: 0 auto;
}

.field { display: grid; gap: 0.5rem; }
.field-label { font-weight: 600; }

.field-input {
  width: 100%;
  min-height: var(--touch);
  padding: 0.75rem 1rem;
  border: 0;
  border-radius: var(--radius-card);
  font-family: var(--schrift-text);
  font-size: 1.125rem;
  color: rgb(var(--c-ink-inv));
  background: rgb(var(--c-line) / 0.1);
  box-shadow: inset 0 0 0 1px rgb(var(--c-line) / 0.2);
}
.field-input::placeholder { color: rgb(var(--c-muted) / 0.7); }
.field-input:focus { box-shadow: inset 0 0 0 2px rgb(var(--c-cta)); }
.field-input.is-invalid { box-shadow: inset 0 0 0 2px rgb(var(--c-xmas-red)); }

.field-hint { font-size: 0.875rem; color: rgb(var(--c-muted)); }

.field-check { display: flex; align-items: flex-start; gap: 0.75rem; }
.field-check input {
  flex: none;
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.25rem;
  accent-color: rgb(var(--c-cta));
}

/* --- Leerer Zustand, Hinweise, Meldungen ------------------------------ */

.empty-state {
  max-width: var(--breite-text);
  margin: 0 auto;
  padding: 2.5rem 1.5rem;
  text-align: center;
  border: 1px dashed rgb(var(--c-line) / 0.2);
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.06);
}
.empty-state-title { font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.empty-state-text { margin-top: 0.5rem; color: rgb(var(--c-muted)); }
.empty-state .btn { margin-top: 1.5rem; }
/* Zwei Wege nebeneinander (Code eingeben / zur Anmeldung) — ohne den Abstand
   klebten die Knöpfe aneinander. */
.empty-state .btn + .btn { margin-left: 0.75rem; }

/* Abgeschlossener Schritt statt „nichts da" — etwa nach der Registrierung.
   Nutzt dieselbe Weihnachtsfarbe wie `.notice.is-error` das Rot: ganzjährig
   als Erfolgsfarbe, unabhängig vom Weihnachts-Layer. */
.empty-state.is-success {
  border-style: solid;
  border-color: rgb(var(--c-xmas-green) / 0.5);
  background: rgb(var(--c-xmas-green) / 0.16);
}

.hint { font-size: 0.875rem; color: rgb(var(--c-muted)); }

/* Tipp oder Kommentar zu einem Wunsch */
.tip {
  padding: 1rem;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

/* Derselbe Kasten, aber anklickbar — etwa „2 Personen möchten beitreten". */
.tip-link {
  display: block;
  margin-top: 1rem;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
  border-left: 4px solid rgb(var(--c-gold));
}
.tip-link:hover { background: rgb(var(--c-line) / 0.14); text-decoration: none; }

/* Geschenk-Tipp: ein Banner, das ganz verlinkt ist (Partial promo_summitlines).
   Zwei Bildfassungen wählt <picture> selbst aus; hier steht nur der Rahmen.
   line-height: 0 verhindert den Streifen, den ein Bild in einem Link sonst
   unter sich lässt. */
.promo {
  display: block;
  margin-top: 2rem;
  line-height: 0;
  border-radius: var(--radius-card);
  overflow: hidden;
}
/* Das Verhältnis steht hier statt als Attribut am Bild: Die schmale Fassung ist
   1200×424, die breite 1456×311 — ein Attribut könnte nur eines von beiden nennen
   und stauchte die jeweils andere. */
.promo img { display: block; width: 100%; height: auto; aspect-ratio: 1200 / 424; }
.promo:focus-visible { outline: 2px solid rgb(var(--c-gold)); outline-offset: 2px; }

/* Derselbe Rahmen für den PRO-Banner der Familienseite (Partial promo_pro), nur mit
   den Maßen jener beiden Bilder: 1000×531 fürs Handy, 1200×279 ab 640 px. Er steht
   direkt unter der Kopfkarte und braucht deshalb weniger Luft nach oben als der
   Geschenk-Tipp, der einen Screen abschließt. */
.promo-pro { margin-top: 1rem; }
.promo-pro img { aspect-ratio: 1000 / 531; }

@media (min-width: 640px) {
  /* Ab hier lädt <picture> die flache Fassung — dasselbe Verhältnis wie dort. */
  .promo img { aspect-ratio: 1456 / 311; }
  .promo-pro img { aspect-ratio: 1200 / 279; }
}

/* Erscheint nur, wenn app.js ihm `is-visible` gibt — sonst ist er auch für
   die Vorlesesoftware nicht vorhanden. */
.toast {
  position: fixed;
  left: 1rem;
  right: 1rem;
  bottom: calc(6rem + env(safe-area-inset-bottom, 0px));
  z-index: 50;
  max-width: var(--breite-text);
  margin: 0 auto;
  padding: 1rem 1.25rem;
  border-radius: var(--radius-card);
  font-weight: 600;
  text-align: center;
  background: rgb(var(--c-night));
  box-shadow: inset 0 0 0 1px rgb(var(--c-line) / 0.2), var(--schatten-lift);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.2s;
}
.toast.is-visible { opacity: 1; visibility: visible; }
.toast.is-error { box-shadow: inset 0 0 0 1px rgb(var(--c-xmas-red)), var(--schatten-lift); }

/* Die Meldung, die der Server schon mitgeliefert hat — Shop und Backoffice
   arbeiten ohne JavaScript, dort gibt es niemanden, der einen Toast
   einblendet. Sie steht im Textfluss, nicht darüber. */
.notice {
  padding: 0.875rem 1.25rem;
  border-radius: var(--radius-card);
  border-left: 4px solid rgb(var(--c-aqua));
  background: rgb(var(--c-aqua) / 0.12);
  font-weight: 600;
}
.notice.is-error {
  border-left-color: rgb(var(--c-xmas-red));
  background: rgb(var(--c-xmas-red) / 0.12);
}

/* ==================================================================== */
/* 7. Homepage                                                          */
/* ==================================================================== */

.site { min-height: 100vh; }

/* Sprungmarke für die Tastaturbedienung: unsichtbar, bis sie den Fokus bekommt. */
.skip-link {
  position: absolute;
  top: -4rem;
  left: 1rem;
  z-index: 50;
  padding: 0.5rem 1rem;
  border-radius: var(--radius-card);
  font-weight: 600;
  color: rgb(var(--c-ink));
  text-decoration: none;
  background: rgb(var(--c-gold));
  transition: top 0.15s;
}
.skip-link:focus { top: 1rem; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  padding: 0.75rem 1.25rem;
  background: rgb(var(--c-night) / 0.82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgb(var(--c-line) / 0.1);
}

.site-logo {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
}
.site-logo img { width: 2.75rem; height: 2.75rem; border-radius: var(--radius-card); }
.site-logo-text { font-family: var(--schrift-kopf); font-size: 1.125rem; font-weight: 600; }

.site-menu-button { margin-left: auto; }

.site-nav {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  width: 100%;
}
.site-nav.hidden { display: none; }

.site-nav-link {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-pill);
  font-weight: 500;
  color: rgb(var(--c-muted));
  text-decoration: none;
}
.site-nav-link:hover { color: rgb(var(--c-ink-inv)); text-decoration: none; background: rgb(var(--c-line) / 0.1); }
.site-nav-link.is-active { color: rgb(var(--c-ink-inv)); background: rgb(var(--c-line) / 0.14); }

.site-nav-login { margin-top: 0.5rem; }

@media (min-width: 640px) {
  .site-logo-text { font-size: 1.25rem; }
  .site-menu-button { display: none; }
  .site-nav,
  .site-nav.hidden {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    width: auto;
    margin-left: auto;
  }
  .site-nav-link { padding: 0.5rem 1rem; }
  .site-nav-login { margin-top: 0; margin-left: 0.5rem; }
}

.site-footer {
  margin-top: 4rem;
  padding: 3rem 1.5rem;
  background: rgb(var(--c-night) / 0.75);
  border-top: 1px solid rgb(var(--c-line) / 0.1);
}
.site-footer-inner {
  display: grid;
  gap: 2rem;
  width: 100%;
  max-width: var(--breite-screen);
  margin: 0 auto;
}
.site-footer-claim { font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.site-footer-nav { display: flex; flex-direction: column; gap: 0.5rem; }
.site-footer-nav a { color: rgb(var(--c-muted)); text-decoration: none; }
.site-footer-nav a:hover { color: rgb(var(--c-ink-inv)); text-decoration: underline; }
.site-footer .store-row { margin-top: 0; justify-content: flex-start; }
.site-footer .store-row img { height: 2.75rem; }

@media (min-width: 640px) {
  .site-footer-inner { grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: start; }
}

/* --- Hero: die Kosmos-Bühne ------------------------------------------- */
/* Rakete, Komet, Planeten, Sterne und Wolkenbänder liegen als Ebenen
   übereinander; bewegt werden sie von `home.js` (data-parallax). Ohne
   JavaScript steht dasselbe Bild still da — es fehlt nichts. */

.hero {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 100vh;
  /* svh: auf dem Handy zählt die sichtbare Höhe ohne Adressleiste, sonst
     springt die Bühne beim Scrollen. */
  min-height: 100svh;
  overflow: hidden;
}

/* Unterseiten: derselbe Kosmos, aber flacher — der Inhalt soll ohne Scrollen
   beginnen, nicht erst nach einem bildschirmfüllenden Kopf. */
.hero--klein { min-height: 60vh; min-height: 60svh; }

/* Eine Ebene. Sie fängt keine Klicks ab — der Knopf darunter bleibt bedienbar. */
.hero-layer {
  position: absolute;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
}
.hero-layer img { display: block; width: 100%; height: auto; }

/* Ankerpunkte wie im bisherigen Auftritt (uk-position-*). */
.hero-layer--cover      { inset: 0; }
.hero-layer--top        { top: 0; left: 0; right: 0; }
.hero-layer--bottom     { bottom: 0; left: 0; right: 0; }
.hero-layer--left       { left: 0; top: 50%; transform: translateY(-50%); }
.hero-layer--right      { right: 0; top: 50%; transform: translateY(-50%); }
.hero-layer--top-right  { top: 0; right: 0; }
.hero-layer--top-center { top: 0; left: 50%; transform: translateX(-50%); }
.hero-layer--center     { top: 50%; left: 50%; }

.hero-content {
  position: relative;
  z-index: 20;
  width: 100%;
  max-width: var(--breite-screen);
  margin: 0 auto;
  padding: 0 1.5rem;
  text-align: center;
}

.hero-title {
  font-family: var(--schrift-kopf);
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1.1;
  text-shadow: 0 2px 24px rgb(var(--c-night) / 0.75);
}

.hero-claim {
  display: block;
  margin-top: 0.5rem;
  font-family: var(--schrift-kopf);
  font-size: 1.5rem;
  font-weight: 600;
  color: rgb(var(--c-cta));
  text-shadow: 0 2px 24px rgb(var(--c-night) / 0.75);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem;
  margin-top: 2rem;
}

@media (min-width: 640px) {
  .hero-title { font-size: 3.75rem; }
  .hero-claim { font-size: 2.25rem; }
}

/* Wolkenband. Der Ankerpunkt ist das Entscheidende: Wächst ein Band um seine
   Mitte, wird es nur größer. Unten verankert baut es sich vor dem Betrachter
   auf — zusammen mit kräftiger Skalierung und Verschiebung nach unten entsteht
   der Eindruck, hindurchzufliegen. Genau das macht der bestehende Auftritt.
   Die Bänder sind breiter als der Bildschirm, damit beim Wachsen seitlich
   keine Kante auftaucht. */
.cloudband {
  position: absolute;
  left: -10%;
  width: 120%;
  z-index: 10;
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  transform-origin: 50% 100%;
}
.cloudband img { display: block; width: 100%; }
.cloudband--bottom { bottom: 0; }
.cloudband--top { top: 0; transform-origin: 50% 0%; }

/* --- Abschnitte -------------------------------------------------------- */

.section {
  position: relative;
  overflow: hidden;
  padding: 4rem 1.5rem;
}
.section-inner { width: 100%; max-width: var(--breite-screen); margin: 0 auto; }
.section-title { font-family: var(--schrift-kopf); font-size: 1.875rem; font-weight: 700; }
.section-lead { margin-top: 1rem; max-width: var(--breite-text); font-size: 1.25rem; line-height: 1.55; }

@media (min-width: 640px) {
  .section { padding: 6rem 1.5rem; }
  .section-title { font-size: 2.25rem; }
}

/* Die drei Argumente-Karten (Kostenfrei · Kinderleicht · Privatsphäre) */
.feature-grid { display: grid; gap: 1.5rem; margin-top: 2.5rem; }

.feature {
  padding: 1.5rem;
  text-align: center;
  border: 1px solid rgb(var(--c-line) / 0.12);
  border-radius: var(--radius-card);
  background: linear-gradient(160deg, rgb(var(--c-surface) / 0.8), rgb(var(--c-surface) / 0.4));
}

.feature-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 6rem;
  height: 6rem;
  margin: 0 auto 1rem;
  border-radius: var(--radius-pill);
  background: rgb(var(--c-light));
}
.feature-icon img { width: 4rem; height: 4rem; object-fit: contain; }

.feature-title { font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.feature-text { margin-top: 0.5rem; color: rgb(var(--c-muted)); }

@media (min-width: 640px) {
  .feature-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Nummerierte Schritte („So funktioniert die Wunschliste") */
.steps { display: grid; gap: 1rem; margin: 2.5rem 0 0; padding: 0; list-style: none; }

.step {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 1.25rem;
  border: 1px solid rgb(var(--c-line) / 0.12);
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.07);
}

.step-number {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-pill);
  font-family: var(--schrift-kopf);
  font-size: 1.25rem;
  font-weight: 700;
  color: rgb(var(--c-ink));
  background: rgb(var(--c-gold));
}

.step-title { font-family: var(--schrift-kopf); font-size: 1.125rem; font-weight: 600; }
.step-text { margin-top: 0.25rem; color: rgb(var(--c-muted)); }

/* Store-Buttons */
.store-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 2rem;
}
.store-row img { height: 3.5rem; width: auto; }

/* Avatar-Beispiele auf der PRO-Seite */
.avatar-row { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; margin-top: 1.5rem; }
.avatar-sample {
  width: 5rem;
  height: 5rem;
  object-fit: contain;
  border-radius: var(--radius-pill);
  background: rgb(var(--c-line) / 0.12);
}

@media (min-width: 640px) {
  .avatar-sample { width: 6rem; height: 6rem; }
}

/* --- Blog -------------------------------------------------------------- */

/* Die Spaltenzahl richtet sich nach dem **vorhandenen Platz**, nicht nach der
   Fensterbreite. Das war der Fehler bis 2026-08-24: Ab 1024 px Fenster standen
   drei Karten nebeneinander — aber der Inhaltsbereich ist auf `--breite-screen`
   (46rem) gedeckelt, also blieben je Karte rund 14rem. Zu schmal für Bild,
   Überschrift und Anrisstext.

   `auto-fill` mit einer Mindestbreite legt die Zahl selbst fest: bei 46rem sind
   das zwei Karten zu je gut 22rem, auf dem Telefon eine. Wird der Container
   später breiter, kommt eine dritte von allein dazu — ohne dass jemand einen
   Breakpoint nachziehen muss.

   `min(17rem, 100%)` fängt sehr schmale Geräte ab: Ohne das ragte eine 17rem
   breite Spalte aus einem 15rem schmalen Container heraus. */
.post-grid {
  display: grid;
  gap: 1.5rem;
  margin-top: 2.5rem;
  grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
}

.post-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid rgb(var(--c-line) / 0.12);
  border-radius: var(--radius-card);
  background: linear-gradient(160deg, rgb(var(--c-surface) / 0.8), rgb(var(--c-surface) / 0.4));
}

.post-card-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: rgb(var(--c-line) / 0.08);
}

.post-card-body { display: flex; flex: 1 1 auto; flex-direction: column; padding: 1.25rem; }
.post-card-tag { font-size: 0.875rem; font-weight: 600; color: rgb(var(--c-gold)); }
.post-card-title { margin-top: 0.25rem; font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.post-card-title a { color: rgb(var(--c-ink-inv)); text-decoration: none; }
.post-card-title a:hover { text-decoration: underline; }
.post-card-teaser { flex: 1 1 auto; margin-top: 0.5rem; color: rgb(var(--c-muted)); }
.post-card-date { margin-top: 1rem; font-size: 0.875rem; color: rgb(var(--c-muted)); }

.post-hero-image {
  width: 100%;
  max-height: 26rem;
  margin-bottom: 2rem;
  object-fit: cover;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

/* Rubriken über der Artikelliste */
.tag-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.tag {
  padding: 0.5rem 1rem;
  border-radius: var(--radius-pill);
  font-weight: 600;
  color: rgb(var(--c-ink-inv));
  text-decoration: none;
  background: rgb(var(--c-line) / 0.12);
}
.tag:hover { text-decoration: none; background: rgb(var(--c-cta) / 0.3); }

/* Hier standen die beiden Breakpoints für zwei und drei Spalten. Sie sind
   entfallen — `.post-grid` regelt das jetzt über die Mindestbreite selbst. */

/* --- Fließtext --------------------------------------------------------- */
/* Artikel und Rechtstexte kommen aus der Datenbank beziehungsweise aus dem
   Altbestand — sie bringen keine Klassen mit, deshalb werden hier die
   Grundelemente gestaltet. */

.prose { max-width: var(--breite-text); line-height: 1.7; }
.prose > * + * { margin-top: 1rem; }
.prose h2 { margin-top: 2.5rem; font-family: var(--schrift-kopf); font-size: 1.5rem; font-weight: 600; }
.prose h3 { margin-top: 2rem; font-family: var(--schrift-kopf); font-size: 1.25rem; font-weight: 600; }
.prose ul { padding-left: 1.5rem; list-style: disc; }
.prose ol { padding-left: 1.5rem; list-style: decimal; }
.prose li + li { margin-top: 0.5rem; }
.prose a { color: rgb(var(--c-decor-a)); text-decoration: underline; }
.prose img { margin: 1.5rem 0; height: auto; max-width: 100%; border-radius: var(--radius-card); }
.prose strong { font-weight: 600; color: rgb(var(--c-ink-inv)); }
/* Trennlinie aus dem Editor (seit 2026-08-24 im erlaubten Tag-Satz). */
.prose hr { margin: 2rem 0; border: 0; border-top: 1px solid rgb(var(--c-line) / 0.25); }
.prose table { width: 100%; border-collapse: collapse; }
.prose th, .prose td {
  padding: 0.5rem 0.75rem;
  text-align: left;
  border-bottom: 1px solid rgb(var(--c-line) / 0.15);
}
.prose blockquote {
  margin: 0;
  padding: 1rem 1.25rem;
  border-radius: var(--radius-card);
  background: rgb(var(--c-line) / 0.08);
}

/* --- Hilfe (KnowledgeBase, Etappe 8j) --------------------------------- */
/* Der öffentliche Teil von `/hilfe`. Bewusst schlicht: Wer hier landet,
   sucht eine Antwort und keine Gestaltung. Große Trefferflächen, weil auch
   das hier Oma und Opa benutzen. */

.hilfe-suche {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  justify-content: center;
  max-width: 30rem;
  margin-inline: auto;
}
.hilfe-suche .field-input { flex: 1 1 14rem; width: auto; }

.hilfe-liste {
  display: grid;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hilfe-eintrag { margin: 0; }

/* Der ganze Eintrag ist der Link, nicht nur die Überschrift — eine kleine
   Trefferfläche ist auf dem Telefon eine Fehlerquelle. */
.hilfe-link,
.hilfe-thema {
  display: block;
  padding: 1rem 1.25rem;
  border-radius: var(--radius-card);
  border: 1px solid rgb(var(--c-line) / 0.18);
  background: rgb(var(--c-line) / 0.06);
  color: inherit;
  text-decoration: none;
}
.hilfe-link:hover,
.hilfe-link:focus-visible,
.hilfe-thema:hover,
.hilfe-thema:focus-visible {
  border-color: rgb(var(--c-decor-a) / 0.5);
  background: rgb(var(--c-line) / 0.12);
  text-decoration: none;
}

.hilfe-titel {
  display: block;
  font-family: var(--schrift-kopf);
  font-weight: 600;
  font-size: 1.125rem;
}

.hilfe-teaser {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.9375rem;
  color: rgb(var(--c-ink-inv) / 0.75);
}

.hilfe-anzahl {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.8125rem;
  color: rgb(var(--c-ink-inv) / 0.55);
}

.hilfe-themen { display: grid; gap: 0.75rem; }

@media (min-width: 640px) {
  .hilfe-themen { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ==================================================================== */
/* 8. Eigenbewegung des Kosmos                                          */
/* ==================================================================== */
/* Der Bestand bewegt sich nur beim Scrollen — wer oben stehen bleibt, sieht
   ein Standbild. Diese drei Animationen geben dem Kosmos auch im Stillstand
   Leben. Sie laufen auf dem inneren <img>, während die Ebene darüber vom
   Parallax verschoben wird; so kommen sich die beiden Transformationen nicht
   ins Gehege. Bei „weniger Bewegung" im Betriebssystem stehen sie still
   (Regel in Abschnitt 3). */

@keyframes fw-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-14px) rotate(-1.5deg); }
}

@keyframes fw-drift {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(-12px, 10px, 0); }
}

@keyframes fw-twinkle {
  0%, 100% { opacity: 0.35; transform: scale(0.9); }
  50%      { opacity: 1;    transform: scale(1.08); }
}

.fw-float   { animation: fw-float 7s ease-in-out infinite; }
.fw-drift   { animation: fw-drift 16s ease-in-out infinite; }
.fw-twinkle { animation: fw-twinkle 4s ease-in-out infinite; }

/* Versetzter Start, damit die Sterne nicht im Gleichtakt blinken. */
.fw-delay-1 { animation-delay: -1.3s; }
.fw-delay-2 { animation-delay: -2.6s; }
.fw-delay-3 { animation-delay: -3.9s; }


/* ==================================================================== */
/* 9. Shop (order.familien-wunschliste.de)                              */
/* ==================================================================== */
/* Der Bestellvorgang bekommt einen bewusst schmalen Rahmen: Logo oben,
   Inhalt in einer Spalte, Rechtstexte unten. Keine Menüs, keine
   Nebenwege — wer hier ist, will bezahlen, und jedes zusätzliche Element
   ist eine Gelegenheit abzuspringen. Aufgebaut aus denselben Variablen
   wie der Rest, damit ein Redesign den Shop von allein mitnimmt. */

.shop-body {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: rgb(var(--c-bg));
  color: rgb(var(--c-ink-inv));
}

.shop-header {
  padding: 1.5rem;
  display: flex;
  justify-content: center;
  border-bottom: 1px solid rgb(var(--c-line) / 0.1);
}

.shop-logo { display: inline-block; }
.shop-logo img { height: 2.5rem; width: auto; }

.shop-main {
  flex: 1 1 auto;
  width: 100%;
  max-width: var(--breite-screen);
  margin: 0 auto;
  padding: 2rem 1.5rem 4rem;
}

.shop-title {
  font-family: var(--schrift-kopf);
  font-size: 1.75rem;
  font-weight: 700;
  margin-bottom: 1.5rem;
}

.shop-footer {
  padding: 2rem 1.5rem;
  border-top: 1px solid rgb(var(--c-line) / 0.1);
}

.shop-footer-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem 1.5rem;
  font-size: 0.875rem;
}
.shop-footer-links a { color: rgb(var(--c-ink-inv) / 0.75); text-decoration: none; }
.shop-footer-links a:hover,
.shop-footer-links a:focus-visible { color: rgb(var(--c-ink-inv)); text-decoration: underline; }

@media (min-width: 640px) {
  .shop-title { font-size: 2rem; }
  .shop-main  { padding: 3rem 1.5rem 5rem; }
}
