/*
 * plupp.app — Startseite.
 *
 * Der Plupp ist hier NICHT neu erfunden, sondern nachgebaut: alle Zahlen
 * stammen aus components/plupp-pin.tsx und components/splash-mark.tsx, damit
 * Web und App dasselbe Atom zeigen. Wer dort tunt, tunt hier mit — die Quellen
 * sind bei jeder Zahl vermerkt.
 *
 * Keine externen Requests: Fonts liegen lokal, kein CDN, kein Analytics.
 * Die Seite lädt aus genau einer Domain — der eigenen.
 */

/* ---------------------------------------------------------------- Fonts --
   Mona Sans, subgesetzt auf Latin (aus @expo-google-fonts/mona-sans, SIL OFL —
   Lizenz liegt in fonts/). Bewusst kein Google-Fonts-CDN: das überträgt die IP
   jedes Besuchers an Google. */

@font-face {
  font-family: 'Mona Sans';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/fonts/MonaSans-300Light.woff2') format('woff2');
}

@font-face {
  font-family: 'Mona Sans';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url('/fonts/MonaSans-300Light_Italic.woff2') format('woff2');
}

@font-face {
  font-family: 'Mona Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/MonaSans-400Regular.woff2') format('woff2');
}

/* --------------------------------------------------------------- Token --
   Nocturne. Die App ist fix auf dark gesperrt (THEME_LOCK in
   constants/theme.ts), die Seite hält sich daran — ein helles Web neben einer
   dunklen App wären zwei Marken. */

:root {
  --bg: #0E0E12;
  --text: #F4F2EE;
  --text2: #8A8A92;
  /* Aktionsfarbe (Palette.akzent, constants/theme.ts): Rosa = dein Zug / meint dich. */
  --akzent: #DD90BE;

  /* Grundmass der Marke: die gesamte Wellen-Geometrie hängt daran. */
  --pin: clamp(54px, 8vw, 74px);
  /* Der Dot — halbes Grundmass, also bewusst KLEINER als das App-Verhältnis
     (dort füllt er die Wellen-Box zu 18/32). Auf einer leeren Seite trägt der
     weite Ring das Bild; ein grosser Punkt darin wird zum Klecks. Ein kleiner
     Tropfen, weite Wellen. Wer den Punkt ändern will, ändert nur diese Zeile —
     die Ringe bleiben, wo sie sind. */
  --dot: calc(var(--pin) * 0.5);
  /* Wellen-Box: WAVE/DOT = 32/18 aus plupp-pin.tsx, gerechnet auf das
     Grundmass — damit die Ringe unabhängig vom Dot dieselbe Bahn laufen. */
  --wave: calc(var(--pin) * 1.7778);
  /* perspective 320 bei einer 74.7er Box (Splash) = Faktor 4.286. Proportional
     mitgeführt, sonst kippen die Ringe bei grossem Dot flacher als in der App. */
  --persp: calc(var(--wave) * 4.286);
}

/* ---------------------------------------------------------------- Bühne -- */

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Mona Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100svh;
  overflow: hidden;
}

.defs {
  position: absolute;
  width: 0;
  height: 0;
}

.stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 0 24px;
}

/* ---------------------------------------------------------------- Plupp --
   Der Dot sitzt in der Mitte, die Ringe liegen konzentrisch darum und ragen
   über ihn hinaus. Die Box bekommt die Grösse der äussersten Welle, damit der
   Text darunter Luft behält (BOX 120 bei DOT 42 im Splash ≈ Faktor 2.86). */

.plupp {
  position: relative;
  width: calc(var(--pin) * 2.86);
  height: calc(var(--pin) * 2.86);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fade-in 900ms ease-out backwards;
}

/* Jedes SVG füllt seine Box exakt. OHNE das nimmt ein <svg> ohne width/height
   die Ersatz-Grösse 300×150 und passt den Kreis nach Seitenverhältnis ein —
   der Dot sitzt dann falsch und wirkt eiförmig. */
.plupp svg {
  display: block;
  width: 100%;
  height: 100%;
}

.dot {
  /* Nicht schrumpfen, nicht strecken: der Dot ist rund, und zwar exakt. */
  flex: 0 0 auto;
  width: var(--dot);
  height: var(--dot);
  aspect-ratio: 1;
  /* OPEN_FILL 0.7 — durchscheinend, wie auf der Karte, wo die Stadt
     hindurchschimmert. Auf leerer Fläche bleibt es dieselbe Dichte. */
  opacity: 0.7;
  /* Bewusst OHNE den Atem, den der Splash trägt (scale 1 → 1.1, 1100ms):
     in der App dauert der Splash Sekunden, hier steht das Bild dauerhaft — ein
     endlos pochender Punkt wird zum Zappeln. Die Wellen sagen ohnehin schon,
     dass der Plupp lebt; der Tropfen selbst darf ruhig liegen. */
}

.dot circle { fill: url(#pinGrad); }

.ring {
  position: absolute;
  width: var(--wave);
  height: var(--wave);
  opacity: 0;
  will-change: transform, opacity;
}

.ring circle {
  fill: none;
  /* Verlauf steht als Attribut am Kreis (eigene <defs> je Ring, s. index.html). */
  /* SplashMark führt waveStroke 3; im Browser skaliert der Ring bis 2.88×
     und die Linie mit — auf dem Desktop wurde sie breit (Geräte-Befund
     26.09.). Darum 1.5 mit vector-effect: die Linie bleibt in Pixeln fein,
     egal wie gross die Welle gerade ist. */
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

/* Drei Wellen, gestaffelt und mit KRUMMEN Dauern: die Ringe driften
   gegeneinander, das Muster wirkt organisch statt getaktet. Zahlen aus
   RIPPLES (plupp-pin.tsx), mal waveSlow 2 wie im Splash — ein Startbild atmet
   langsamer als eine lebende Karte.
   Die erste Welle läuft flach in der Ebene, die zweite kippt um X, die dritte
   um Y: so kreuzen sie sich räumlich. */

/* Drei verschiedene Endradien (Entscheid 26.09.): nicht jede Welle läuft
   gleich weit — die flache gross, die gekippten kleiner. So gibt es nahe und
   ferne Ringe, wie Tropfen verschiedener Grösse. */
.ring-1 {
  --end: 5.2;
  animation: ripple-flat 8400ms cubic-bezier(0, 0, 0.58, 1) infinite;
}

.ring-2 {
  --end: 3.1;
  animation: ripple-x 7400ms cubic-bezier(0, 0, 0.58, 1) 5200ms infinite;
}

.ring-3 {
  --end: 1.9;
  animation: ripple-y 9600ms cubic-bezier(0, 0, 0.58, 1) 2600ms infinite;
}

/* Endradius pro Ring über --end (der Splash endet einheitlich bei 2.88 =
   1.8 Peak × 1.6 waveScale; die Seite ist Bühne und darf weiter).
   opacity-Spitze 0.52 = COMMIT_PEAK, früh im Lauf — die Welle schält sich vom
   Dot ab, wird kurz präsent und verklingt nach aussen. */

@keyframes ripple-flat {
  0%   { opacity: 0;    transform: scale(0); }
  8%   { opacity: 0.62; }
  100% { opacity: 0;    transform: scale(var(--end)); }
}

@keyframes ripple-x {
  0%   { opacity: 0;    transform: perspective(var(--persp)) rotateX(80deg) scale(0); }
  8%   { opacity: 0.62; }
  100% { opacity: 0;    transform: perspective(var(--persp)) rotateX(0deg) scale(var(--end)); }
}

@keyframes ripple-y {
  0%   { opacity: 0;    transform: perspective(var(--persp)) rotateY(80deg) scale(0); }
  8%   { opacity: 0.62; }
  100% { opacity: 0;    transform: perspective(var(--persp)) rotateY(0deg) scale(var(--end)); }
}

/* ----------------------------------------------------------------- Wort --
   Stagger 0 / 280 / 560 ms wie der Splash (app/index.tsx): erst das Zeichen,
   dann der Name, dann der Satz. */

.wordmark {
  font-size: clamp(38px, 6vw, 50px);
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1;
  margin: 4px 0 0;
  animation: fade-in 900ms ease-out 280ms backwards;
}

.tagline {
  font-style: italic;
  font-size: clamp(13px, 1.8vw, 15px);
  line-height: 1.7;
  color: var(--text2);
  max-width: 32ch;
  margin: 18px 0 0;
  animation: fade-in 900ms ease-out 560ms backwards;
}

.studio {
  position: absolute;
  bottom: 26px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  letter-spacing: -0.01em;
  color: var(--text2);
  opacity: 0.55;
  animation: fade-in 900ms ease-out 900ms backwards;
}

/* Die Pflicht-Seiten hängen unten am Rand — erreichbar, aber ohne Anspruch auf
   den Blick. Die Seite gehört dem Plupp. */
.legal {
  display: flex;
  gap: 18px;
}

.studio a {
  color: inherit;
  text-decoration: none;
}

.studio a:hover { text-decoration: underline; }

@keyframes fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ------------------------------------------------------------ Bewegung --
   Wer Bewegung abgestellt hat, bekommt den stillen Plupp — genau die Variante,
   die Onboarding Seite 1 zeigt (`static`): der Dot ohne Wellen. Nicht weniger
   Marke, nur ruhiger. */

@media (prefers-reduced-motion: reduce) {
  .ring { display: none; }

  .plupp,
  .wordmark,
  .tagline,
  .studio {
    animation: none;
  }
}

/* ------------------------------------------------------------ Welt zwei --
   Die Startseite scrollt: oben die Bühne (ein Bildschirm), darunter der Kern
   aus «die Idee», unten das Studio. body.welt hebt das overflow:hidden der
   alten Ein-Bildschirm-Bühne auf. */

body.welt {
  height: auto;
  overflow: visible;
  justify-content: flex-start;
}
html:has(body.welt) { height: auto; }

body.welt .stage {
  min-height: 100svh;
  justify-content: center;
  position: relative;
}

body.welt .studio {
  position: static;
  padding: 40px 0 34px;
}

/* Abzweig als Action-Link mit Pfeil (Welt-zwei-Muster: «erstmal ohne →»);
   Rosa, weil anfassbar. Sitzt am unteren Rand der Bühne. */
.abzweig {
  position: absolute;
  bottom: 30px;
  color: var(--akzent);
  text-decoration: none;
  opacity: 0.6;
  line-height: 0;
  animation: fade-in 900ms ease-out 1200ms backwards;
}
.abzweig:hover { opacity: 1; }
.abzweig svg { display: block; }

.tagline .leer { display: inline-block; height: 0.4em; }

.idee {
  max-width: 34ch;
  padding: 24px 24px 8px;
  text-align: center;
  font-size: clamp(14px, 1.9vw, 16px);
  line-height: 1.7;
  color: var(--text2);
  font-weight: 400;
}
.idee p { margin: 0 0 14px; }
.idee p.luft { margin-top: 34px; }
.idee .gruss {
  margin-top: 40px;
  font-style: italic;
}
.idee .schluss {
  margin-top: 34px;
  font-style: italic;
  color: var(--akzent);
}

/* Sternenstaub: jedes Korn driftet vom Kern nach aussen und verglimmt —
   Deckkraft 0 → 0.8 (bei 12 % des Wegs) → 0, wie interpolate() in der App. */
/* Der Himmel: fixe Ebene, Ursprung = Plupp-Mitte (Script), unter allem. */
.himmel {
  position: fixed;
  width: 0;
  height: 0;
  left: 50%;
  top: 40%;
  z-index: 0;
  pointer-events: none;
}
body.welt .stage, body.welt .idee, body.welt .studio { position: relative; z-index: 1; }

/* Der Anker: ein Korn, das bleibt. */
.anker {
  position: absolute;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--akzent);
  opacity: 0.55;
}

.himmel i {
  position: absolute;
  left: calc(var(--s) / -2);
  top: calc(var(--s) / -2);
  width: var(--s);
  height: var(--s);
  border-radius: 50%;
  opacity: 0;
  animation: korn var(--d) cubic-bezier(0, 0, 0.58, 1) var(--v) infinite;
  will-change: transform, opacity;
}
.himmel i.rosa  { background: var(--akzent); }
.himmel i.weiss { background: var(--text); }

/* Die weite Welle: ein Zyklus von 24 s, davon läuft sie 14 s; leise Spitze,
   damit sie den Text nicht überfährt. --weit setzt das Script aus dem
   Bildschirm-Mass. */
.ring-weit {
  animation: ripple-weit 24000ms cubic-bezier(0, 0, 0.58, 1) 6000ms infinite;
}
@keyframes ripple-weit {
  0%   { opacity: 0;    transform: scale(0); }
  4%   { opacity: 0.3; }
  42%  { opacity: 0.16; }
  58%  { opacity: 0;    transform: scale(var(--weit, 14)); }
  100% { opacity: 0;    transform: scale(var(--weit, 14)); }
}

/* Nichts, was über den Rand wandert, darf die Seite breiter machen. */
html:has(body.welt), body.welt { overflow-x: hidden; }

@keyframes korn {
  0%   { opacity: 0;   transform: translate(0, 0); }
  10%  { opacity: 0.75; }
  100% { opacity: 0;   transform: translate(var(--x), var(--y)); }
}

@media (prefers-reduced-motion: reduce) {
  .himmel, .abzweig { animation: none; }
}

/* ================================================================ Seiten ==
   Alles ab hier gilt den Text-Seiten (Impressum, Datenschutz, Kontakt) und der
   Invite-Landung. Die Startseite ist eine Bühne, diese hier sind zum Lesen
   gemacht: linksbündig, ruhige Zeilenlänge, scrollbar. */

body.doc {
  display: block;
  overflow: auto;
  text-align: left;
}

.doc-inner {
  max-width: 62ch;
  margin: 0 auto;
  padding: 56px 24px 96px;
  animation: fade-in 700ms ease-out backwards;
}

/* Rücklink: der Plupp in klein, still (keine Wellen) — dasselbe Atom, nur als
   Wegweiser. Kein Pfeil-Zurück, kein Menü: die Seite hat einen Ausgang, und der
   ist die Marke selbst. */
.home-link {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
  margin-bottom: 44px;
}

.home-link .mini {
  width: 15px;
  height: 15px;
  opacity: 0.7;
}

.home-link .mini svg { display: block; width: 100%; height: 100%; }
/* Das Mini-Zeichen trägt seinen Verlauf im eigenen SVG (Safari-Falle, 27.09.)
   und ist seit 28.09. der Ring ohne Punkt, wie das Icon. */

.home-link span {
  font-size: 19px;
  font-weight: 300;
  letter-spacing: -0.02em;
}

.doc h1 {
  font-size: clamp(26px, 4vw, 32px);
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0 0 10px;
}

.doc h2 {
  font-size: 17px;
  font-weight: 400;
  letter-spacing: -0.01em;
  margin: 44px 0 12px;
}

.doc p,
.doc li {
  font-size: 15px;
  font-weight: 400;
  line-height: 1.75;
  color: var(--text);
}

.doc ul { padding-left: 20px; }
.doc li { margin-bottom: 8px; }

.doc a { color: var(--text); text-decoration-color: var(--text2); }
.doc a:hover { text-decoration-color: var(--text); }

/* Der leise Vorspann unter der Überschrift — Pfirsich wie die Helper-Zeile der
   Sheets in der App (helperAccent). Der Kopf sagt, was die Seite ist, der
   farbige Satz spricht dich an. */
.lede {
  color: #FF9E80;
  font-style: italic;
  margin: 0 0 8px;
}

.meta {
  color: var(--text2);
  font-size: 13px;
  margin-top: 56px;
}

.table {
  width: 100%;
  border-collapse: collapse;
  margin: 16px 0;
  font-size: 14.5px;
}

.table th,
.table td {
  text-align: left;
  padding: 10px 12px 10px 0;
  border-bottom: 1px solid rgba(244, 242, 238, 0.09);
  vertical-align: top;
  line-height: 1.6;
}

.table th {
  font-weight: 400;
  color: var(--text2);
  font-size: 13px;
}

/* Offene Stelle: was vor dem Hochladen ausgefüllt sein MUSS. Sichtbar
   markiert, damit ein halbfertiger Rechtstext nicht unbemerkt live geht. */
.todo {
  display: inline-block;
  padding: 1px 7px;
  border: 1px dashed rgba(255, 158, 128, 0.55);
  border-radius: 4px;
  color: #FF9E80;
  font-size: 13px;
  font-style: normal;
}

/* -------------------------------------------------------------- Invite --
   Die Landung für /i/<token> ohne App: mittig wie die Startseite, aber mit
   einem Weg nach vorn. */

.invite-actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 30px;
}

/* Outline-Pille — dieselbe Familie wie die Knöpfe in der App
   (components/outline-pill-button.tsx): Hairline-Rahmen, kein Flächen-Füllen. */
.pill {
  display: inline-block;
  padding: 13px 30px;
  border: 1px solid rgba(244, 242, 238, 0.3);
  border-radius: 999px;
  color: var(--text);
  text-decoration: none;
  font-size: 14px;
  letter-spacing: 0.01em;
  transition: border-color 200ms ease;
}

.pill:hover { border-color: rgba(244, 242, 238, 0.6); }

.hint {
  color: var(--text2);
  font-size: 13.5px;
  line-height: 1.7;
  max-width: 34ch;
  margin: 0;
}

.hidden { display: none; }
