/* ==========================================================================
   Papersmith — Marketing-Website
   Design-System-Tokens und Komponenten nach Design-Handover (High-Fidelity).
   Keine Webfonts, keine Fremd-Requests, kein Tracking.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */

:root {
  color-scheme: light;

  /* Farben — Basiswerte */
  --ps-ink-900: #2A2520;    /* Tinte — Text, dunkle Flächen */
  --ps-ink-700: #55504A;
  --ps-ink-500: #70685D;   /* Sekundärtext — 4.5:1 auf allen Papiertönen */
  --ps-ink-300: #A39588;
  --ps-paper-0: #FFFDF9;    /* Karten */
  --ps-paper-50: #FAF6F0;   /* Papier — Seitengrund */
  --ps-paper-100: #F1E9DD;  /* vertiefte Flächen */
  --ps-paper-200: #E8DFD1;
  --ps-copper-800: #834D23; /* Kupfer — Link-Hover, dunkelste Stufe */
  --ps-copper-700: #955828; /* Kupfer als Text auf hellem Grund — 4.5:1 */
  --ps-copper-600: #A4612E; /* Kupferfläche, die hellen Text trägt — 4.5:1 */
  --ps-copper-500: #C97A3D; /* Kupfer — Markenton, nur Nicht-Text (Icons, Klammern) */
  --ps-copper-200: #E5C9A8; /* Falz auf hell */
  --ps-copper-100: #F3E4D2;
  --ps-linen-500: #766756;  /* Leinen — gedämpfter Zweitton, 4.5:1 auf Papier */
  --ps-linen-300: #C9BCA9;  /* Falz auf dunkel */
  --ps-success: #5C7F50;
  --ps-warning: #C99B3D;
  --ps-danger: #B1503C;

  /* Farben — semantische Aliasse */
  --ps-surface-page: var(--ps-paper-50);
  --ps-surface-card: var(--ps-paper-0);
  --ps-surface-sunken: var(--ps-paper-100);
  --ps-surface-inverse: var(--ps-ink-900);
  --ps-text-primary: var(--ps-ink-900);
  --ps-text-secondary: var(--ps-ink-500);
  --ps-text-tertiary: var(--ps-ink-300);
  --ps-text-on-accent: var(--ps-paper-50);
  --ps-text-on-inverse: var(--ps-paper-50);
  --ps-accent: var(--ps-copper-500);        /* Markenton — Nicht-Text */
  --ps-accent-solid: var(--ps-copper-600);  /* Fläche, die hellen Text trägt */
  --ps-accent-text: var(--ps-copper-700);   /* Kupfer als Text auf hellem Grund */
  --ps-accent-hover: var(--ps-copper-700);
  --ps-accent-soft: var(--ps-copper-100);
  --ps-border-subtle: #EAE1D3;
  --ps-border-strong: #D8CBB8;
  /* Doppelring: eine der beiden Kanten trägt auf jedem Untergrund über 3:1 */
  --ps-focus-ring: 0 0 0 2px var(--ps-paper-0), 0 0 0 4px var(--ps-ink-900);
  --ps-focus-ring-inset: inset 0 0 0 2px var(--ps-ink-900), inset 0 0 0 4px var(--ps-paper-0);

  /* Rahmenfarbe der Geräte-Mockups auf dunklem Grund */
  --ps-device-dark: #191511;

  /* ------------------------------------------------------------------
     Dunkle Seite

     Die Seite steht auf Tinte, nicht auf Papier. Umgelegt werden die
     Tintenstufen: `--ps-ink-900` trägt jetzt Papier. Der Name lügt damit —
     bewusst, denn er steht an 28 Stellen als Textfarbe, und die alle
     umzuhängen wäre viel Fläche für dasselbe Ergebnis. Wer die Seite je
     zurückdreht, löscht diesen Block und alles steht wieder.

     Die Papierstufen bleiben unangetastet: sie sind hier keine Oberflächen,
     sondern Abbildungen — Gerätebildschirme, Blätter, Karten. Die bleiben
     aus Papier.

     Alles, was Dunkles *meint*, steht deshalb ab hier auf festen Werten. Ein
     `var(--ps-ink-900)` in einem Alias würde sonst mit umkippen und den Hero
     ins Helle drehen.
     ------------------------------------------------------------------ */
  color-scheme: dark;

  --ps-ink-900: #FAF6F0;   /* war Tinte, trägt jetzt Papier */
  /* Gemessen: #CFC6B9 fiel über den hellsten Stellen von Grund und Kugel auf
     4.00:1. Dies ist der meistbenutzte Sekundärton der Seite (17 Stellen),
     deshalb hier und nicht an den Einzelstellen. */
  --ps-ink-700: #E3DCD2;
  --ps-ink-500: #ACA294;
  --ps-ink-300: #857B6D;
  /* Gemessen: #A99D8D trug über dem Grund der Beats nur 3.61:1. Die
     Bildunterschriften und Notizen brauchen hier mehr Papier im Ton. */
  --ps-linen-500: #C2B6A4;

  --ps-surface-page: #1C1815;
  --ps-surface-sunken: #231E1A;
  --ps-surface-inverse: #2A2520;
  --ps-surface-card: #262019;
  --ps-text-primary: #FAF6F0;
  --ps-text-secondary: #ACA294;
  --ps-text-tertiary: #857B6D;
  --ps-text-on-inverse: #FAF6F0;
  /* Kupfer als Text steht auf Tinte bei 4.58:1 — derselbe Ton, den die
     Hero-Zeile seit dem Redesign trägt. Die dunklen Stufen 700/800 wären
     hier unlesbar. */
  --ps-accent-text: var(--ps-copper-500);
  --ps-accent-hover: var(--ps-copper-200);
  --ps-accent-soft: rgba(201, 122, 61, 0.16);
  --ps-border-subtle: rgba(233, 225, 211, 0.14);
  --ps-border-strong: rgba(233, 225, 211, 0.26);
  --ps-focus-ring: 0 0 0 2px #2A2520, 0 0 0 4px #FAF6F0;
  --ps-focus-ring-inset: inset 0 0 0 2px #2A2520, inset 0 0 0 4px #FAF6F0;

  /* Erfolg und Fehler tragen hier zum ersten Mal Text — vorher gab es auf
     der Seite nichts, was hätte melden können. Die hellen Werte fielen auf
     der Karte durch: #5C7F50 auf #262019 sind 3.53:1, #B1503C sind 3.43:1.
     Beide reichen für ein Symbol, keines für einen Satz. Deshalb eine
     papierhellere Stufe derselben zwei Töne. */
  --ps-success: #9BBF8E;
  --ps-danger: #E08A72;

  /* Typografie — Apples Systemschriften, kein Font-Hosting */
  --ps-font-display: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', sans-serif;
  --ps-font-body: -apple-system, BlinkMacSystemFont, system-ui, 'Segoe UI', sans-serif;
  --ps-tracking-display: -0.025em;
  --ps-tracking-micro: 0.09em;

  /* Abstände — 4er-Raster */
  --ps-space-1: 4px;  --ps-space-2: 8px;  --ps-space-3: 12px; --ps-space-4: 16px;
  --ps-space-5: 20px; --ps-space-6: 24px; --ps-space-7: 32px; --ps-space-8: 40px;
  --ps-space-9: 48px; --ps-space-10: 64px;

  /* Radien */
  /* Eine Regel für die ganze Seite: interaktiv = pill, Fläche = md,
     große Fläche = lg. Geräterahmen (40px) sind bewusst ausgenommen —
     sie bilden ein Objekt ab, keine Oberfläche. */
  --ps-radius-sm: 8px;
  --ps-radius-md: 12px;
  --ps-radius-lg: 16px;
  --ps-radius-xl: 20px;
  --ps-radius-pill: 999px;

  /* Schatten — warm getönt, nie neutralgrau */
  --ps-shadow-card: 0 2px 8px rgba(40, 30, 20, 0.08);
  --ps-shadow-float: 0 4px 12px rgba(42, 37, 32, 0.25);
  --ps-shadow-banner: 0 8px 24px rgba(42, 37, 32, 0.18);
  --ps-shadow-device: 0 18px 36px rgba(40, 30, 20, 0.14);
  --ps-shadow-device-dark: 0 24px 48px rgba(0, 0, 0, 0.4);

  /* Layout */
  --ps-container: 1140px;
  --ps-gutter: 32px;
  --ps-nav-height: 62px;
  --ps-section: 96px;
}

/* --------------------------------------------------------------------------
   2. Reset und Grundlagen
   -------------------------------------------------------------------------- */

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

html {
  scroll-behavior: smooth;
  /* Sticky-Nav darf Ankerziele nicht verdecken */
  scroll-padding-top: calc(var(--ps-nav-height) + 16px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--ps-surface-page);
  color: var(--ps-text-primary);
  font-family: var(--ps-font-body);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

a { color: var(--ps-accent-text); }
a:hover { color: var(--ps-copper-800); }

img, svg { display: block; max-width: 100%; }
img { height: auto; }

button { font: inherit; color: inherit; }

/* Bewusst gesetzt statt Browser-Standardblau */
a, button, [role="button"] { -webkit-tap-highlight-color: rgba(42, 37, 32, 0.08); }

:focus-visible {
  outline: 2px solid transparent;
  box-shadow: var(--ps-focus-ring);
  border-radius: var(--ps-radius-sm);
}

/* Sichtbarer Sprung zum Inhalt für Tastatur- und Screenreader-Nutzung */
.ps-skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 100;
  padding: 10px 18px;
  border-radius: var(--ps-radius-pill);
  background: var(--ps-ink-900);
  color: var(--ps-paper-50);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.2s ease-out;
}
.ps-skip-link:focus {
  top: 12px;
  color: var(--ps-paper-50);
}

/* Der bewegte Grund.

   Dasselbe Rauschwerk wie die Kugel, aber ohne Kugel: ein sehr langsam
   wanderndes Feld aus Tinte, Leinen und einem Hauch Kupfer. Es ist absichtlich
   niederfrequent — ein 320×180-Puffer, über den Viewport gezogen, ist davon
   nicht zu unterscheiden und kostet praktisch nichts.

   `z-index: -1` ist hier nötig, nicht Geschmack: ein festes Element mit
   z-index 0 läge über dem Fließtext, weil positionierte Elemente nach den
   Blockhintergründen zeichnen. Minus eins legt es unter allen Inhalt und
   trotzdem über die Seitenfarbe. */
.ps-ground {
  position: fixed;
  inset: 0;
  z-index: -1;
  display: none;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.ps-ground.is-on { display: block; }

.ps-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* Jede Bahn der Seite steht über der Kugel — nicht unter ihr.

   Die Kugel reist als Hintergrundmöbel durch die Seite, liegt im Stapel aber
   im Hero: ein positioniertes Element mit `z-index: 0`. Positionierte
   Elemente zeichnen nach den Blockhintergründen *und* nach dem Fließtext.
   Eine statische Sektion, die im Markup danach kommt, verschwindet damit
   unter der Kugel, statt über ihr zu stehen.

   Auf dem Desktop fiel das nie auf: dort driftet die Kugel in den rechten
   Rand, wo neben der Textspalte nichts steht. Einspaltig auf dem Telefon
   liegt sie mitten im Satz — gemessen bei 360px Breite deckt sie die rechten
   171 von 360 Pixeln ab, und in „Außerdem" brachen die Zeilen an ihrer Kante
   schlicht ab.

   `position: relative` hebt die Bahnen in dieselbe Malstufe wie die Kugel.
   Dort entscheidet die Reihenfolge im Markup, und die steht auf ihrer Seite:
   alles nach dem Hero zeichnet über ihr. Kein Versatz, keine neue
   Bezugsfläche — jedes absolut gesetzte Kind hat bereits einen näheren
   positionierten Vorfahren.

   Der Hero selbst bleibt außen vor: dort muss die Kugel über dem Grund und
   unter der Schrift liegen, und das regelt `.ps-hero__inner`. */
main > *,
.ps-footer { position: relative; }

/* Der dunkle Grund gehört der Seite, nicht mehr dem Hero und dem Band.

   Grund: die Kugel liegt im Stapel des Hero. Alles, was im Markup nach dem
   Hero kommt, zeichnet über sie — ein eigener Tintengrund am Faktenband hätte
   sie dort abgeschnitten, und genau diese Kante sollte ja verschwinden. Als
   Hintergrund des Seitenrahmens liegt die Tinte dagegen unter der Kugel, und
   die Kugel läuft ungebrochen aus dem Dunklen ins Helle.

   Die drei Marken setzt `papersmith.js` aus der gemessenen Geometrie; die
   Vorgaben hier decken den einen Frame davor ab — den verdeckt der Preloader. */
/* `is-inked` setzt das Skript erst, wenn es die Geometrie gemessen hat — und
   nur auf Seiten mit Hero. Impressum, Datenschutz und 404 haben keinen, dort
   bleibt der Seitengrund unberührt. Bis dahin tragen Hero und Band ihre eigene
   Tinte wie zuvor, es gibt also keinen Blitzer. */
.ps-page.is-inked {
  background-image: linear-gradient(
    to bottom,
    var(--ps-surface-inverse) var(--ps-ink-start, 0px),
    var(--ps-surface-inverse) var(--ps-ink-end, 100vh),
    rgba(42, 37, 32, 0) var(--ps-ink-fade, calc(100vh + 170px)));
  background-repeat: no-repeat;
}
.is-inked .ps-hero { background: transparent; }

/* Das Band bekommt keinen Grund, sondern einen Schleier: die Kugel zieht
   dahinter durch, aber der Text steht lesbar davor. Gemessen wurde der
   schlimmste Fall — Leinenschrift über der hellsten Stelle der Kugel, dort
   sind es ohne Schleier 1.51:1. Oben und unten läuft er aus, damit die Kugel
   nicht an einer Kante abreißt; in der Mitte, wo die Buchstaben sitzen, steht
   er voll. */
.is-inked .ps-promise {
  background: linear-gradient(
    to bottom,
    rgba(42, 37, 32, 0.45) 0%,
    rgba(42, 37, 32, 0.93) 30%,
    rgba(42, 37, 32, 0.93) 70%,
    rgba(42, 37, 32, 0.45) 100%);
}
/* Die Randwischer bleiben knapp unter der Tinte des Schleiers, sonst setzen
   sie zwei dunkle Ecken auf das Band. */
.is-inked .ps-promise::before { background: linear-gradient(to right, rgba(42, 37, 32, 0.93), rgba(42, 37, 32, 0)); }
.is-inked .ps-promise::after { background: linear-gradient(to left, rgba(42, 37, 32, 0.93), rgba(42, 37, 32, 0)); }

.ps-container {
  max-width: var(--ps-container);
  margin: 0 auto;
  /* viewport-fit=cover steht im <meta> — ohne env() rutscht Inhalt
     im Querformat unter die Notch. */
  padding-left: max(var(--ps-gutter), env(safe-area-inset-left));
  padding-right: max(var(--ps-gutter), env(safe-area-inset-right));
  width: 100%;
}

.ps-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.ps-sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   3. Sprachumschaltung — beide Fassungen stehen im Markup, CSS blendet um
   -------------------------------------------------------------------------- */

.en { display: none; }
.lang-en .en { display: revert; }
.lang-en .de { display: none; }

/* --------------------------------------------------------------------------
   4. Typografische Bausteine
   -------------------------------------------------------------------------- */

.ps-eyebrow {
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: var(--ps-tracking-micro);
  text-transform: uppercase;
  color: var(--ps-accent-text);
}
.ps-eyebrow--on-dark { color: var(--ps-copper-200); }

.ps-wordmark {
  font-family: var(--ps-font-display);
  font-weight: 700;
  letter-spacing: var(--ps-tracking-display);
}

/* Zurück nach oben.

   In der Formensprache der Seite: eine Tintenfläche mit Kupferkante, die beim
   Überfahren voll in Kupfer umschlägt — dieselbe Bewegung wie der Hauptknopf,
   nur andersherum begonnen. Der Pfeil ist das gedrehte `i-arrow-left` aus dem
   Sprite; ein eigenes Symbol dafür einzuführen wäre für 90 Grad zu viel.

   Ohne Skript steht er sichtbar da und tut, was er soll — er ist ein Anker,
   kein Knopf. Mit Skript erscheint er erst, wenn es etwas zurückzugehen gibt. */
.ps-totop {
  position: fixed;
  right: clamp(16px, 2.4vw, 34px);
  bottom: clamp(16px, 2.4vw, 34px);
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  height: 46px;
  padding: 0 18px 0 15px;
  border: 1px solid rgba(201, 122, 61, 0.42);
  border-radius: var(--ps-radius-pill);
  /* Deckend, ohne Milchglas. Gemessen fiel der Kupfertext über der hellen
     Kugel auf 3.82:1 — nicht wegen der Deckkraft, sondern weil die
     Weichzeichnung die Kugel in den Knopf zieht. Der Knopf ist die eine
     Fläche, die sich ihren Untergrund nicht aussuchen kann. */
  background: var(--ps-surface-inverse);
  color: var(--ps-copper-500);
  font-family: var(--ps-font-display);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: var(--ps-tracking-micro);
  text-transform: uppercase;
  text-decoration: none;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.34);
  transition: background-color 0.2s ease-out, color 0.2s ease-out,
              border-color 0.2s ease-out, opacity 0.28s ease-out,
              transform 0.28s ease-out;
}
.ps-totop .ps-icon {
  width: 17px;
  height: 17px;
  color: currentColor;
  /* Der Pfeil zeigt nach links; ein Vierteldreh macht ihn zum Aufwärtspfeil */
  transform: rotate(90deg);
}
.ps-totop:hover {
  background: var(--ps-accent-solid);
  border-color: var(--ps-accent-solid);
  color: var(--ps-paper-50);
}
.ps-totop:focus-visible { outline: none; box-shadow: var(--ps-focus-ring); }

/* Mit Skript: erst zeigen, wenn etwas hinter einem liegt */
.js .ps-totop {
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
}
.js .ps-totop.is-visible {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

@media (max-width: 560px) {
  .ps-totop { padding: 0 14px; height: 42px; }
  .ps-totop__text { display: none; }
}

/* Das Museumsschild trägt die Kapitelnummern der Seite: 01 Hero, 02 Durchlauf,
   03 Im Kleinen, 04 Der Anspruch, 05 Der Ausbau, 06 Auf dem Gerät,
   07 Die Einladung. Der Abstand nach unten gehört hierher und nicht in die
   einzelnen Abschnitte, sonst driften sie auseinander.
   Im Beta-Rahmen steht alles mittig, dort weicht die Haarlinie: sie zeigt
   nach rechts ins Leere und würde die Mitte kippen. */
.ps-eyebrow { margin: 0 0 var(--ps-space-5); }
.ps-beta__frame .ps-eyebrow { justify-content: center; margin-bottom: var(--ps-space-4); }
.ps-beta__frame .ps-eyebrow__rule { display: none; }

/* Die zweite Zeile in Kupfer — dasselbe Mittel, mit dem Hero und
   Privatsphäre ihre Überschrift teilen: der erste Satz stellt fest, der
   zweite ist das Versprechen. Kupfer auf Tinte trägt gemessen 4.58:1. */
.ps-h2 em {
  font-style: normal;
  color: var(--ps-accent);
}

.ps-h2 {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(30px, 3.6vw, 46px);
  letter-spacing: -0.035em;
  line-height: 1.08;
  text-wrap: balance;
}

.ps-h3 {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 500;
  font-size: 26px;
  letter-spacing: -0.025em;
  line-height: 1.2;
  text-wrap: balance;
}

.ps-lead {
  margin: 0;
  font-size: 18px;
  line-height: 1.65;
  color: var(--ps-ink-700);
}
/* --------------------------------------------------------------------------
   5. Komponenten

   Radius-Regel für die ganze Seite:
   interaktiv = pill · Fläche = md (12px) · große Fläche = lg (16px).
   Geräterahmen fallen bewusst heraus (40px): sie bilden ein Objekt ab,
   keine Oberfläche.
   -------------------------------------------------------------------------- */

/* 5.1 Button */
.ps-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  border: 1px solid transparent;
  border-radius: var(--ps-radius-pill);
  font-family: var(--ps-font-display);
  font-weight: 600;
  letter-spacing: -0.01em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.18s ease-out, color 0.18s ease-out,
              border-color 0.18s ease-out, transform 0.12s ease-out;
  touch-action: manipulation;
}
.ps-btn:active { transform: translateY(1px); }

.ps-btn--primary {
  background: var(--ps-accent-solid);
  color: var(--ps-paper-50);
}
.ps-btn--primary:hover {
  background: var(--ps-copper-700);
  color: var(--ps-paper-50);
}

.ps-btn--ghost {
  background: transparent;
  color: var(--ps-accent-text);
}
.ps-btn--ghost:hover {
  background: var(--ps-copper-100);
  color: var(--ps-copper-800);
}
.ps-btn--sm {
  min-height: 40px;
  padding: 0 18px;
  font-size: 14.5px;
}
.ps-btn--lg {
  min-height: 50px;
  padding: 0 24px;
  font-size: 16px;
}

/* 5.2 Badge */
.ps-badge {
  display: inline-flex;
  align-items: center;
  border-radius: var(--ps-radius-pill);
  background: var(--ps-copper-100);
  /* Nicht `--ps-accent-text`: das Plättchen bleibt hell, auch wenn die Seite
     dunkel ist, und im dunklen Schema zeigt `--ps-accent-text` auf
     Kupfer-500 — Markenton für Nicht-Text. Auf dem hellen Plättchen misst
     das 2.66:1. Kupfer-700 ist der Ton, der genau dafür da ist: 4.55:1. */
  color: var(--ps-copper-700);
  padding: 5px 12px;
  font-family: var(--ps-font-display);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
/* 5.3 Icons — Lucide, inline als Sprite (keine Fremd-Requests) */
.ps-icon {
  flex: 0 0 auto;
  width: 21px;
  height: 21px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--ps-copper-500);
}
.ps-icon--19 { width: 19px; height: 19px; }
.ps-icon--22 { width: 22px; height: 22px; }
.ps-icon--26 { width: 26px; height: 26px; }

/* Auf den getönten Flächen trägt der Markenton nicht mehr: #C97A3D erreicht
   auf paper-100 nur 2.75:1 und auf copper-100 nur 2.66:1, verlangt sind 3:1
   für Nicht-Text. Dort greift die Textstufe (4.71:1 bzw. 4.55:1). */
.ps-why .ps-icon { color: var(--ps-accent-text); }

/* 5.4 Geräte-Mockup — nur noch der Hero trägt einen echten Rahmen */
.ps-device {
  position: relative;
  flex: 0 0 auto;
  background: var(--ps-paper-50);
  border: 10px solid var(--ps-device-dark);
  border-radius: 40px;
  box-shadow: var(--ps-shadow-device-dark);
  overflow: hidden;
}
.ps-device img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* 5.5 Scan-Linie über dem Screenshot */
.ps-scanline {
  position: absolute;
  left: 12px;
  right: 12px;
  top: 7%;
  height: 42px;
  z-index: 6;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(to bottom,
              rgba(201, 122, 61, 0) 0%,
              rgba(201, 122, 61, 0.12) 65%,
              rgba(201, 122, 61, 0.4) 100%);
  border-bottom: 2px solid var(--ps-copper-500);
  animation: ps-scan 6s ease-in-out 1.4s infinite;
}
.ps-scanline--delay-12 { animation-delay: 1.2s; }

/* --------------------------------------------------------------------------
   5.6 Preloader — das Markenzeichen rastet ein.

   Die Tintenfläche des Markenzeichens ist hier der Viewport selbst; sichtbar
   bleiben die vier Kupferklammern, das Blatt und ein Scanlauf darüber. Weil
   der Hero denselben Grund trägt, hebt das Overlay in dieselbe Farbe hinein ab.

   Drei Sicherheitsnetze: ohne `.js` wird der Block nie sichtbar, entfernt wird
   per JavaScript und nie per `animationend` (das feuert unter reduzierter
   Bewegung nie), und `lang-init.js` räumt nach 3 s auch dann auf, wenn
   `papersmith.js` gar nicht ankommt.
   -------------------------------------------------------------------------- */

.ps-preload {
  display: none;
  /* Das Tempo der Choreografie als eine Zahl: jede Dauer und jede Verzögerung
     weiter unten ist ein Vielfaches davon. 1 wäre die ursprüngliche, knappe
     Fassung; 1.9 lässt die Gesten ausspielen, statt sie abzuhaken. Wer hier
     dreht, muss MIN in `papersmith.js` mitziehen — dort steht, wie lange der
     Preloader mindestens hält. */
  --ps-pl-pace: 1.9;
}

.js .ps-preload {
  display: grid;
  place-items: center;
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--ps-surface-inverse);
  overscroll-behavior: contain;
  transition: opacity 0.42s ease-out, transform 0.42s ease-out;
}
/* Muss `display: grid` oben schlagen, sonst bleibt [hidden] wirkungslos */
.js .ps-preload[hidden] { display: none; }

.js .ps-preload.is-done {
  opacity: 0;
  transform: scale(1.04);
  pointer-events: none;
}

/* Scrollsperre, solange das Overlay steht */
html.is-preloading,
html.is-preloading body { overflow: hidden; }

.ps-preload__stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ps-space-6);
}

/* Das Zeichen trägt die Fläche, wie in der Vorlage. vmin statt vw, damit es im
   Querformat nicht über die Höhe hinauswächst. */
.ps-preload__mark {
  display: block;
  width: clamp(150px, 30vmin, 280px);
  height: auto;
}
.ps-preload__bracket {
  fill: none;
  stroke: var(--ps-copper-500);
  stroke-width: 4;
  stroke-linecap: round;
}
.ps-preload__page { fill: var(--ps-paper-50); }
.ps-preload__fold { fill: var(--ps-linen-300); }
/* Der Scanlauf ist ein Durchgang, kein Zustand: sein Ruhezustand ist fort */
.ps-preload__scan { opacity: 0; }

.ps-preload__wordmark {
  font-size: 15px;
  letter-spacing: 0.02em;
  color: var(--ps-linen-300);
}

/* Zähler statt Fortschrittsbalken — Museumsschild-Typografie wie die Sektions-
   labels. `tabular-nums` ist hier Pflicht: ohne die Ziffern gleicher Breite
   zappelt die Zeile bei jedem Zählschritt. */
.ps-preload__meter {
  display: flex;
  align-items: baseline;
  gap: var(--ps-space-4);
  font-family: var(--ps-font-display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: var(--ps-tracking-micro);
  text-transform: uppercase;
  color: var(--ps-linen-300);
}
.ps-preload__count {
  min-width: 3ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
  color: var(--ps-copper-500);
}

/* Die Choreografie. Jeder Ruhezustand ist der fertige Zustand — unter
   reduzierter Bewegung steht das Zeichen deshalb einfach da, statt zu fehlen.
   Reihenfolge (Grundwerte, vor `--ps-pl-pace`): Klammern (0.06–0.55 s), Blatt
   (0.26–0.66 s), Scanlauf (0.46–0.86 s), Knick (0.62–0.84 s), Wortmarke
   (0.44–0.80 s). Bei Pace 1.9 endet der letzte Lauf nach rund 1.63 s; die
   Mindestdauer von 1750 ms in `papersmith.js` lässt das Bild danach noch
   einen Atemzug stehen, bevor das Overlay abhebt. */
@media (prefers-reduced-motion: no-preference) {

  .ps-preload__bracket {
    opacity: 0;
    transform: translate(var(--ps-bx, 0px), var(--ps-by, 0px));
    animation: ps-snap calc(0.34s * var(--ps-pl-pace)) cubic-bezier(0.2, 0.9, 0.25, 1) both;
  }
  .ps-preload__bracket--tl { --ps-bx: -14px; --ps-by: -14px; animation-delay: calc(0.06s * var(--ps-pl-pace)); }
  .ps-preload__bracket--tr { --ps-bx:  14px; --ps-by: -14px; animation-delay: calc(0.11s * var(--ps-pl-pace)); }
  .ps-preload__bracket--bl { --ps-bx: -14px; --ps-by:  14px; animation-delay: calc(0.16s * var(--ps-pl-pace)); }
  .ps-preload__bracket--br { --ps-bx:  14px; --ps-by:  14px; animation-delay: calc(0.21s * var(--ps-pl-pace)); }

  /* Das Blatt entwickelt sich von oben: der Vorhang im clipPath fährt herunter.
     Nur eine Transform — `height` zu animieren wäre Layoutarbeit pro Frame. */
  .ps-preload__curtain {
    transform: translateY(-54px);
    animation: ps-pl-develop calc(0.40s * var(--ps-pl-pace)) cubic-bezier(0.3, 0.7, 0.25, 1) calc(0.26s * var(--ps-pl-pace)) both;
  }

  /* Der Knick klappt zuletzt auf, Scharnier unten links */
  .ps-preload__fold {
    transform-box: fill-box;
    transform-origin: 0% 100%;
    opacity: 0;
    transform: scale(0.7);
    animation: ps-pl-fold calc(0.22s * var(--ps-pl-pace)) ease-out calc(0.62s * var(--ps-pl-pace)) both;
  }

  .ps-preload__scan {
    animation: ps-pl-scan calc(0.40s * var(--ps-pl-pace)) ease-in-out calc(0.46s * var(--ps-pl-pace)) both;
  }

  /* `letter-spacing` ist die eine Ausnahme von „nur transform und opacity":
     die Sperrung lässt sich nicht kompositorfreundlich nachbauen, und sie
     kostet 360 ms Reflow eines Zehn-Zeichen-Worts auf sonst leerer Fläche. */
  .ps-preload__wordmark {
    opacity: 0;
    letter-spacing: 0.22em;
    animation: ps-pl-word calc(0.36s * var(--ps-pl-pace)) ease-out calc(0.44s * var(--ps-pl-pace)) both;
  }

  .ps-preload__meter {
    opacity: 0;
    animation: ps-pl-meter calc(0.32s * var(--ps-pl-pace)) ease-out calc(0.52s * var(--ps-pl-pace)) both;
  }
}

/* --------------------------------------------------------------------------
   6. Navigation
   -------------------------------------------------------------------------- */

.ps-nav {
  position: sticky;
  top: 0;
  z-index: 50;
  /* Die Leiste geht mit: eine cremefarbene Insel auf dunkler Seite */
  background: var(--ps-surface-page);
  border-bottom: 1px solid var(--ps-border-subtle);
}
.ps-nav__inner {
  display: flex;
  align-items: center;
  gap: 28px;
  padding-top: 11px;
  padding-bottom: 11px;
}
.ps-nav__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  text-decoration: none;
  color: var(--ps-ink-900);
  flex: 0 0 auto;
  transition: opacity 0.18s ease-out;
}
.ps-nav__brand:hover { opacity: 0.68; }
.ps-nav__brand img { border-radius: 8px; }
.ps-nav__brand .ps-wordmark { font-size: 19px; }

.ps-nav__spacer { flex: 1; }

.ps-nav__links {
  display: flex;
  align-items: center;
  gap: 22px;
}
.ps-nav__link {
  padding: 11px 4px;
  text-decoration: none;
  color: var(--ps-ink-700);
  font-size: 15px;
  transition: color 0.18s ease-out;
}
.ps-nav__link:hover { color: var(--ps-ink-900); }

/* Segmentcontrol DE / EN */
.ps-segment {
  display: flex;
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--ps-radius-pill);
  overflow: hidden;
  flex: 0 0 auto;
}
.ps-segment button {
  min-height: 38px;
  border: none;
  cursor: pointer;
  padding: 0 14px;
  font-family: var(--ps-font-body);
  font-size: 13px;
  font-weight: 600;
  background: transparent;
  color: var(--ps-ink-700);
  transition: background-color 0.18s ease-out, color 0.18s ease-out;
  touch-action: manipulation;
}
.ps-segment button:hover { color: var(--ps-ink-900); }
/* Die aktive Fläche ist ein Papierplättchen mit Tintenschrift. Vor der
   Umkehrung stand hier `--ps-ink-900` als Grund und `--ps-paper-50` als
   Schrift — seit die Tintenstufen Papier tragen, war beides derselbe Ton und
   die aktive Sprache unsichtbar. Deshalb hier feste Rollen statt Palette. */
.ps-segment button[aria-pressed="true"] {
  background: var(--ps-paper-50);
  color: var(--ps-surface-inverse);
}
.ps-segment button:focus-visible {
  box-shadow: var(--ps-focus-ring-inset);
  border-radius: 0;
}

/* Kurzfassung des CTA und Sprachschalter im Panel: erst auf schmalen Displays */
.ps-nav__cta-mini { display: none; }
.ps-nav__segment-panel { display: none; }

/* Menü-Schalter — erst unterhalb des Umbruchs sichtbar */
.ps-nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin-right: -8px;
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--ps-radius-md);
  background: transparent;
  color: var(--ps-ink-900);
  cursor: pointer;
  touch-action: manipulation;
}
.ps-nav__toggle .ps-icon { color: currentColor; width: 22px; height: 22px; }
.ps-nav__toggle .ps-nav__icon-close,
.ps-nav__toggle[aria-expanded="true"] .ps-nav__icon-open { display: none; }
.ps-nav__toggle[aria-expanded="true"] .ps-nav__icon-close { display: block; }

/* Kaffee und Kontakt in der Leiste.

   Zwei Symbolknöpfe in derselben Form, jeder in zwei Fassungen, immer nur
   eine davon sichtbar: breit ein reiner Symbolknopf in der Form des
   Menüschalters, schmal eine gewöhnliche Zeile im aufklappbaren Panel —
   derselbe Weg, den der Sprachschalter schon geht. Die Leiste ist voll;
   Dauerelemente passen neben Wortmarke, Sprache, TestFlight und
   Menüschalter nicht mehr überall hin.

   Beide Symbole bleiben Kupfer statt Tinte: die Knöpfe sind Bitten, keine
   Bedienelemente der Seite, und der Markenton macht diesen Unterschied
   sichtbar, ohne lauter zu werden.

   Der Kontaktknopf steht im Markup als mailto-Link und wird erst von
   papersmith.js zum Schalter, der den Dialog öffnet. Ohne Skript bleibt er
   ein Link, der funktioniert. */
.ps-nav__coffee,
.ps-nav__contact {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--ps-radius-md);
  background: transparent;
  text-decoration: none;
  cursor: pointer;
  transition: border-color 0.18s ease-out, background-color 0.18s ease-out;
}
.ps-nav__coffee .ps-icon,
.ps-nav__contact .ps-icon { color: var(--ps-copper-500); }
.ps-nav__coffee:hover,
.ps-nav__contact:hover {
  border-color: var(--ps-accent-solid);
  background: var(--ps-accent-soft);
}

/* Die Panel-Fassungen: erst unterhalb des Umbruchs, wie der Sprachschalter */
.ps-nav__coffee-panel,
.ps-nav__contact-panel { display: none; }

/* --------------------------------------------------------------------------
   7. Hero — editorialer Typoblock auf Tinte.

   Drei Zeilen stapeln auf Durchschuss 0.86 zu einer Masse; darüber ein
   Mikro-Label in Museumsschild-Sperrung, dahinter das einzige Farbereignis
   der Sektion: eine Kupfer-Lichtform und zwei Leinen-Ringe.
   Die vier Kupferklammern am Gerät sind dieselbe Geste wie im Preloader —
   die Kantenerkennung der App, auf Seitengröße.
   -------------------------------------------------------------------------- */

.ps-hero {
  position: relative;
  isolation: isolate;
  /* Lichtform und Ringe blenden am Sektionsrand aus, statt zu überlaufen */
  overflow: hidden;
  background: var(--ps-surface-inverse);
  color: var(--ps-text-on-inverse);
}

/* Kugel — das einzige Farbereignis der Seite.

   Nach dem Vorbild der OFF+BRAND-Sphere, übersetzt in Papersmith-Farben und auf
   dunklen Grund gedreht. Dort ist die Sphere ein WebGL-Canvas; hier reicht ein
   Mesh aus vier überlagerten Radialverläufen über einem Linearverlauf — kein
   Canvas, kein Bild, kein Request.

   Der Winkel 255deg ist aus der Vorlage übernommen: das helle Ende liegt oben
   rechts, das dunkle unten links. Das ist hier keine Kosmetik, sondern die
   Lösung des Kontrastproblems — unten links steht die Headline, und genau dort
   löst sich die Kugel in die Tinte auf. Wer den Winkel dreht, bricht das.

   Grund und Mesh sind getrennt, weil nur das Mesh sich bewegt: der
   Grundverlauf trägt die Auflösung nach unten links und steht deshalb fest.
   Die Vorlage bezahlt ihr Wabern mit einem WebGL-Canvas; hier sind es zwei
   Transforms und eine Opazität auf zwei Ebenen — Compositor-Arbeit, kein
   Repaint pro Frame, und unter reduzierter Bewegung steht alles still. */
.ps-hero__orb {
  position: absolute;
  z-index: 0;
  top: 50%;
  left: 71%;
  /* 46vw statt 58vw: die Kugel muss mitschrumpfen, sonst schiebt sie sich bei
     schmalerem Viewport unter die Kupferzeile — dort misst der Kontrast 1.06:1. */
  width: min(660px, 46vw, 78vh);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  pointer-events: none;
  /* Grundverlauf: hell oben rechts, Tinte unten links */
  background: linear-gradient(255deg,
    #F3E4D2 0%, #C97A3D 30%, #8A6E52 62%, #3A322A 86%, #2A2520 100%);
}

/* Das Mesh — dieselben vier Farbtaschen wie vorher, nur auf drei Ebenen
   verteilt, damit die beiden hellen gegeneinander wandern können. Der Kreis
   beschneidet, was dabei über den Rand läuft. Die Reihenfolge von unten nach
   oben ist die alte: Leinen, warme Mitte, Kupfer, Licht. */
.ps-hero__orb-mesh {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  overflow: hidden;
  background:
    /* Warme Mitte, damit der Linearverlauf keine Bänder zeigt */
    radial-gradient(circle at 52% 58%,
      rgba(229, 201, 168, 0.42) 0%, rgba(229, 201, 168, 0) 58%),
    /* Leinenschatten unten links — der Übergang in die Auflösung.
       Bleibt stehen: hier hängt der Kontrast der Kupferzeile. */
    radial-gradient(circle at 26% 84%,
      rgba(118, 103, 86, 0.75) 0%, rgba(118, 103, 86, 0) 55%);
}
.ps-hero__orb-mesh::before,
.ps-hero__orb-mesh::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
}

/* Die Oberfläche. Liegt still und unsichtbar da, bis `papersmith.js` einen
   WebGL-Kontext bekommt — erst dann setzt das Skript `is-gl` und übernimmt.
   Ohne JS, ohne WebGL und bei reduzierter Bewegung bleibt das Mesh oben das
   Bild, und der Canvas wird nie gezeichnet. */
.ps-hero__orb-canvas {
  position: absolute;
  inset: 0;
  display: none;
  width: 100%;
  height: 100%;
  border-radius: 50%;
}
.ps-hero__orb.is-gl .ps-hero__orb-canvas { display: block; }
/* Läuft der Shader, zeichnet er die Kugel allein: Grundverlauf und Mesh
   müssen weg, nicht nur ruhen.

   Das ist kein Aufräumen, sondern Bedingung. Der Shader nimmt über hellem
   Grund die Ränder zurück, damit über Text nichts Dunkles liegt — läge das
   Mesh darunter, käme durch genau diese Lücke die unveränderte dunkle Kugel
   wieder zum Vorschein. Beim Kontextverlust fällt `is-gl` weg und beides ist
   sofort wieder da. */
.ps-hero__orb.is-gl { background: none; }
.ps-hero__orb.is-gl .ps-hero__orb-mesh { opacity: 0; }
.ps-hero__orb.is-gl .ps-hero__orb-mesh::before,
.ps-hero__orb.is-gl .ps-hero__orb-mesh::after { animation: none; }
/* Kupfertasche links — der Markenton, wo die Vorlage Pink führt */
.ps-hero__orb-mesh::before {
  background: radial-gradient(circle at 22% 44%,
    rgba(201, 122, 61, 0.88) 0%, rgba(201, 122, 61, 0.34) 34%, rgba(201, 122, 61, 0) 62%);
}
/* Lichtpunkt oben rechts — die Stelle, an der die Kugel „leuchtet" */
.ps-hero__orb-mesh::after {
  background: radial-gradient(circle at 74% 20%,
    rgba(250, 238, 222, 0.95) 0%, rgba(243, 228, 210, 0.55) 22%, rgba(243, 228, 210, 0) 48%);
}

/* Die Reise. Sobald das Skript übernimmt (`is-travelling`), ist die Kugel
   viewportfest statt im Hero verankert: sie scrollt nicht weg, sondern wächst,
   driftet nach rechts und lässt die Abschnitte über sich hinwegziehen — die
   Geste der Vorlage. Der Hero hat `overflow: hidden`, das beschneidet eine
   `fixed`-Kugel aber nicht: ihr umschließender Block ist der Viewport.

   Alle vier Werte setzt `papersmith.js` je Bild aus der Scrollposition. Ohne
   Skript und bei reduzierter Bewegung greift die Klasse nie, dann bleibt die
   Kugel absolut im Hero stehen wie zuvor. */
.ps-hero__orb.is-travelling {
  position: fixed;
  top: var(--ps-orb-top, 50%);
  left: var(--ps-orb-left, 71%);
  transform: translate(-50%, -50%) scale(var(--ps-orb-scale, 1));
  opacity: var(--ps-orb-veil, 1);
}

/* Konzentrische Ringe — gepunktet wie in der Vorlage, dort 1.49x und 1.59x
   des Kugeldurchmessers und auf sie zentriert, nicht auf das Gerät. */
.ps-hero__orb::before,
.ps-hero__orb::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}
.ps-hero__orb::before {
  width: 110%;
  border: 1px dotted rgba(201, 188, 169, 0.30);
}
.ps-hero__orb::after {
  width: 122%;
  border: 1px dotted rgba(201, 188, 169, 0.18);
}

/* Die Kugel wabert. Zwei Farbtaschen laufen gegenläufig um den Mittelpunkt,
   schwellen dabei an und ab, die Ringe kreisen dazu. Der Leinenschatten unten
   links bewegt sich nicht: dort löst sich die Kugel in die Tinte auf, und die
   Kugel berührt an keinem Breakpoint Text — der gemessene Kontrast der
   Kupferzeile bleibt davon unberührt. Die vier Laufzeiten (18/11/14/9 s) sind
   absichtlich ungerade zueinander: das Gesamtbild wiederholt sich erst nach
   Minuten und wird nicht als Schleife lesbar. */
@media (prefers-reduced-motion: no-preference) {
  .ps-hero__orb-mesh::before {
    animation: ps-orb-copper 18s ease-in-out infinite,
               ps-orb-breathe-soft 11s ease-in-out infinite;
  }
  .ps-hero__orb-mesh::after {
    animation: ps-orb-light 14s ease-in-out infinite,
               ps-orb-breathe 9s ease-in-out infinite;
  }
  .ps-hero__orb::before { animation: ps-orb-ring 150s linear infinite; }
  .ps-hero__orb::after  { animation: ps-orb-ring 190s linear infinite reverse; }
}

.ps-hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 312px);
  gap: 56px;
  align-items: center;
  padding-top: 96px;
  padding-bottom: 104px;
}

.ps-hero__col {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}

/* 7.1 Mikro-Label — Museumsschild statt Pille. Die Haarlinie läuft nach
   rechts aus: sie markiert die Spaltenbreite, ohne sie zu schließen. */
.ps-hero__label,
.ps-eyebrow {
  display: flex;
  align-items: center;
  align-self: stretch;
  gap: var(--ps-space-4);
  margin: 0 0 var(--ps-space-8);
  font-family: var(--ps-font-display);
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: var(--ps-tracking-micro);
  text-transform: uppercase;
  color: var(--ps-linen-300);
}
/* #C97A3D auf #2A2520 — 4.58:1, trägt auch als Kleinsttext */
.ps-hero__label-index,
.ps-eyebrow__index { color: var(--ps-copper-500); }
.ps-hero__label-index::after,
.ps-eyebrow__index::after {
  content: '—';
  margin-left: 9px;
  color: var(--ps-linen-300);
}
/* Produktnamen bleiben von der Versalisierung verschont */
.ps-hero__label-keep { text-transform: none; }
.ps-hero__label-rule,
.ps-eyebrow__rule {
  flex: 1 1 auto;
  height: 1px;
  min-width: 24px;
  background: linear-gradient(to right,
              rgba(201, 188, 169, 0.30),
              rgba(201, 188, 169, 0));
}

/* 7.2 Headline — ein Block, keine drei Zeilen */
.ps-hero__title {
  margin: 0 0 var(--ps-space-7);
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(36px, 9.2vw, 80px);
  line-height: 0.86;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
/* Die Zeilen stapeln als Block. Weil §4 die Sprachen über `display` schaltet,
   wird die Umschaltung hier mit höherer Spezifität nachgebildet — sonst
   gewinnt die spätere Regel und zeigt beide Fassungen übereinander. */
.ps-hero__title .de { display: block; }
.ps-hero__title .en { display: none; }
.lang-en .ps-hero__title .de { display: none; }
.lang-en .ps-hero__title .en { display: block; }

.ps-hero__line { display: block; }
/* Versalien brauchen mehr Luft als Gemischtsatz */
.ps-hero__line--caps { text-transform: uppercase; letter-spacing: -0.022em; }
.ps-hero__title em {
  display: block;
  font-style: normal;
  letter-spacing: -0.038em;
  color: var(--ps-accent);
}

.ps-hero__subline {
  margin: 0 0 var(--ps-space-8);
  max-width: 42ch;
  font-size: 18px;
  line-height: 1.6;
  color: var(--ps-linen-300);
}

/* 7.3 Aktionen — ein Pill-CTA, daneben ein Ghost-Link statt zweitem Button.
   Ohne Fläche, aber mit 44px Trefferhöhe. */
.ps-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ps-space-3) var(--ps-space-6);
}

.ps-hero__ghost {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  min-height: 44px;
  padding: 0 2px;
  border-radius: var(--ps-radius-sm);
  font-family: var(--ps-font-display);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  color: var(--ps-paper-50);
  touch-action: manipulation;
  transition: color 0.18s ease-out;
}
.ps-hero__ghost-label { position: relative; }
.ps-hero__ghost-label::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -3px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.22s ease-out;
}
.ps-hero__ghost-arrow {
  color: var(--ps-copper-500);
  transition: transform 0.22s ease-out;
}
.ps-hero__ghost:hover { color: var(--ps-copper-200); }
.ps-hero__ghost:hover .ps-hero__ghost-label::after { transform: scaleX(1); }
.ps-hero__ghost:hover .ps-hero__ghost-arrow { transform: translateX(4px); }

/* 7.4 Gerät — Rahmen und Schatten bleiben, neu sind Ringe und Klammern */
.ps-hero__device {
  position: relative;
  justify-self: end;
  width: 100%;
  max-width: 312px;
}
.ps-hero__device .ps-device {
  position: relative;
  z-index: 2;
  width: 100%;
  aspect-ratio: 414 / 812;
}

/* Sucherklammern — die vier Ecken des Markenzeichens, auf Seitengröße */
.ps-hero__brackets {
  position: absolute;
  z-index: 3;
  inset: -14px;
  pointer-events: none;
}
.ps-hero__brackets span {
  position: absolute;
  width: 30px;
  height: 30px;
  border: 1.5px solid var(--ps-copper-500);
}
.ps-hero__brackets span:nth-child(1) {
  top: 0; left: 0;
  border-right: 0; border-bottom: 0;
  border-top-left-radius: 11px;
  --ps-bx: -12px; --ps-by: -12px;
}
.ps-hero__brackets span:nth-child(2) {
  top: 0; right: 0;
  border-left: 0; border-bottom: 0;
  border-top-right-radius: 11px;
  --ps-bx: 12px; --ps-by: -12px;
}
.ps-hero__brackets span:nth-child(3) {
  bottom: 0; left: 0;
  border-right: 0; border-top: 0;
  border-bottom-left-radius: 11px;
  --ps-bx: -12px; --ps-by: 12px;
}
.ps-hero__brackets span:nth-child(4) {
  bottom: 0; right: 0;
  border-left: 0; border-top: 0;
  border-bottom-right-radius: 11px;
  --ps-bx: 12px; --ps-by: 12px;
}

/* Die Klammern rasten erst ein, wenn der Preloader abhebt — Abheben und
   Aufbau sollen eine Bewegung sein, nicht zwei. Die Verzögerungen stehen
   im selben Selektor wie die Kurzschrift, sonst setzt die sie zurück. */
@media (prefers-reduced-motion: no-preference) {
  .js .ps-hero__brackets span {
    opacity: 0;
    transform: translate(var(--ps-bx, 0px), var(--ps-by, 0px));
  }
  .js.is-loaded .ps-hero__brackets span {
    animation: ps-snap 0.44s cubic-bezier(0.2, 0.9, 0.25, 1) both;
  }
  .js.is-loaded .ps-hero__brackets span:nth-child(1) { animation-delay: 0.30s; }
  .js.is-loaded .ps-hero__brackets span:nth-child(2) { animation-delay: 0.36s; }
  .js.is-loaded .ps-hero__brackets span:nth-child(3) { animation-delay: 0.42s; }
  .js.is-loaded .ps-hero__brackets span:nth-child(4) { animation-delay: 0.48s; }
}

/* --------------------------------------------------------------------------
   8. Faktenband — das Laufband, das den dunklen Block abschließt.

   Es läuft, weil es die Stelle ist, an der die Seite vom Dunklen ins Helle
   kippt: eine ruhige Querbewegung nimmt der Kante die Härte. Das Tempo setzt
   das Skript aus der gemessenen Breite, damit Deutsch und Englisch trotz
   verschiedener Wortlängen gleich schnell laufen.

   Ohne Skript und bei reduzierter Bewegung steht es still — dann greifen die
   Regeln weiter unten und es ist wieder die zentrierte Liste von vorher.
   -------------------------------------------------------------------------- */

.ps-promise {
  position: relative;
  overflow: hidden;
  background: var(--ps-surface-inverse);
  border-top: 1px solid rgba(233, 225, 211, 0.14);
  padding-top: 20px;
  padding-bottom: 20px;
}
/* Die Ränder wischen die Kanten weg, damit Wörter nicht abgeschnitten
   auftauchen, sondern aus der Tinte kommen und in sie zurückgehen. */
.ps-promise::before,
.ps-promise::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 72px;
  z-index: 1;
  pointer-events: none;
}
.ps-promise::before {
  left: 0;
  background: linear-gradient(to right, var(--ps-surface-inverse), rgba(42, 37, 32, 0));
}
.ps-promise::after {
  right: 0;
  background: linear-gradient(to left, var(--ps-surface-inverse), rgba(42, 37, 32, 0));
}
.ps-promise__track {
  display: flex;
  width: max-content;
}
.ps-promise__list {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  margin: 0;
  padding: 0;
  list-style: none;
}
.ps-promise__list li {
  display: flex;
  align-items: center;
  padding: 2px 0;
  font-size: 14px;
  line-height: 1.4;
  color: var(--ps-linen-300);
  white-space: nowrap;
}
/* Eine Kupferraute statt eines Haarstrichs zwischen den Stücken: dieselbe
   Trennung, aber sie bringt alle paar Wörter Farbe vorbei. Rein dekorativ,
   deshalb ein Pseudoelement — Vorlesegeräte hören nichts davon. */
.ps-promise__list li::before {
  content: '';
  flex: 0 0 auto;
  width: 4px;
  height: 4px;
  margin: 0 26px;
  background: var(--ps-copper-500);
  transform: rotate(45deg);
}
/* Die Leitaussage läuft in Kupfer mit. Nicht im Markenton: der trägt als
   14-px-Schrift auf dem Band gemessen nur 3.86:1. Die hellere Stufe
   kommt auf 8.1:1 und bleibt trotzdem eindeutig Kupfer. */
.ps-promise__list li.ps-promise__lead { color: var(--ps-copper-200); }
@media (prefers-reduced-motion: no-preference) {
  .js .ps-promise__track {
    animation: ps-marquee var(--ps-marquee, 34s) linear infinite;
  }
}

/* --------------------------------------------------------------------------
   9. Durchlauf — das Herzstück. Fünf Beats erzählen den Weg des Dokuments.

   Jeder Beat trägt seine eigene Bühne; `position: sticky` hält sie fest,
   solange der zugehörige Text vorbeiläuft. Weil alle Bühnen deckungsgleich
   sind, liest sich die Übergabe als ein Gerät, dessen Inhalt wechselt.
   Kein Duplikat im Markup, damit der lineare Fallback ohne Umbau funktioniert.
   -------------------------------------------------------------------------- */

.ps-flow {
  padding-top: var(--ps-section);
  padding-bottom: var(--ps-section);
}

.ps-flow__head {
  max-width: 26ch;
  margin-bottom: 24px;
}
.ps-flow__lead {
  max-width: 52ch;
  margin: 0 0 8px;
}

.ps-flow__beats {
  margin: 0;
  padding: 0;
  list-style: none;
}

.ps-beat {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 300px);
  gap: 72px;
  align-items: start;
}

.ps-beat__text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--ps-space-4);
  /* Die Zeile muss deutlich höher sein als die Bühne, sonst bleibt kein Weg,
     auf dem gepinnt werden kann. 105vh minus Bühnenhöhe ist der Weg. */
  min-height: 105vh;
  padding: 6vh 0 6vh 28px;
  position: relative;
}

/* Marke am Textrand statt einer Linie über die volle Zeilenhöhe */
.ps-beat__text::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  width: 2px;
  height: 72px;
  margin-top: -36px;
  border-radius: 2px;
  background: var(--ps-border-strong);
  transition: background-color 0.45s ease-out, height 0.45s ease-out, margin-top 0.45s ease-out;
}
.ps-beat.is-active .ps-beat__text::before {
  background: var(--ps-accent);
  height: 168px;
  margin-top: -84px;
}

.ps-beat__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 500;
  font-size: clamp(25px, 2.7vw, 34px);
  letter-spacing: -0.028em;
  line-height: 1.15;
  text-wrap: balance;
}

.ps-beat__body {
  margin: 0;
  max-width: 46ch;
  font-size: 17px;
  line-height: 1.65;
  color: var(--ps-ink-700);
}

.ps-beat__points {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 10px;
  max-width: 46ch;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--ps-ink-700);
}
.ps-beat__points li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: start;
}
.ps-beat__points .ps-icon { margin-top: 1px; }

.ps-beat__figure {
  position: sticky;
  top: calc(var(--ps-nav-height) + 6vh);
  margin: 0;
  justify-self: end;
  width: 100%;
  max-width: 300px;
}
.ps-beat__caption {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ps-linen-500);
}

/* 9.1 Bühne — ein Rahmen für alle fünf Beats, damit die Übergabe ruhig bleibt */
.ps-stage {
  position: relative;
  width: 100%;
  aspect-ratio: 414 / 812;
  overflow: hidden;
  background: var(--ps-paper-50);
  border: 10px solid var(--ps-device-dark);
  border-radius: 40px;
  box-shadow: var(--ps-shadow-device-dark);
}
.ps-stage img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
}
/* Kameragrund für die Sucher-Szene */
.ps-stage--dark { background: #14110E; }

/* 9.2 Widget-Bühne — die echte Kachel, freigestellt auf getöntem Grund */
.ps-stage--widget {
  display: grid;
  place-items: center;
  background: linear-gradient(168deg, var(--ps-paper-100) 0%, var(--ps-copper-100) 100%);
}
.ps-stage__tile {
  width: 62%;
  border-radius: 22px;
  overflow: hidden;
  box-shadow: var(--ps-shadow-device);
}
.ps-stage__tile img {
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: center;
}

/* 9.3 Sucher-Szene — Blatt liegt schief, die Klammern rasten auf die Kanten.
   Illustration, keine nachgebaute App-Oberfläche. */
.ps-scan {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.ps-scan__sheet {
  width: 58%;
  aspect-ratio: 210 / 297;
  border-radius: 3px;
  background: linear-gradient(150deg, var(--ps-paper-0) 0%, var(--ps-paper-100) 100%);
  box-shadow: 0 18px 34px rgba(0, 0, 0, 0.45);
  /* Ruhezustand ist der aufgelöste: ohne JavaScript steht die Szene fertig da.
     Den unaufgelösten Start setzt Abschnitt 17 hinter der `.js`-Klasse. */
  transition: transform 0.85s cubic-bezier(0.22, 1, 0.36, 1);
}

.ps-scan__brackets {
  position: absolute;
  inset: 27% 19%;
  transition: transform 0.85s cubic-bezier(0.22, 1, 0.36, 1) 0.1s;
}

.ps-scan__bracket {
  position: absolute;
  width: 30px;
  height: 30px;
  border: 0 solid var(--ps-copper-500);
}
.ps-scan__bracket--tl { top: 0; left: 0;     border-top-width: 3px; border-left-width: 3px;  border-top-left-radius: 10px; }
.ps-scan__bracket--tr { top: 0; right: 0;    border-top-width: 3px; border-right-width: 3px; border-top-right-radius: 10px; }
.ps-scan__bracket--bl { bottom: 0; left: 0;  border-bottom-width: 3px; border-left-width: 3px;  border-bottom-left-radius: 10px; }
.ps-scan__bracket--br { bottom: 0; right: 0; border-bottom-width: 3px; border-right-width: 3px; border-bottom-right-radius: 10px; }

/* 9.4 Seiten-Szene — drei Seiten, drei Filterstufen. Aufgefächert, bis der
   Beat aktiv wird; dann legen sie sich zum Stapel. */
.ps-pages {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}
.ps-pages__card {
  position: absolute;
  width: 46%;
  aspect-ratio: 210 / 297;
  border-radius: 4px;
  padding: 12% 10%;
  display: flex;
  flex-direction: column;
  gap: 7%;
  box-shadow: 0 12px 26px rgba(40, 30, 20, 0.22);
  transition: transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
}
.ps-pages__card span {
  display: block;
  height: 5px;
  border-radius: 3px;
}
.ps-pages__card span:nth-child(4) { width: 62%; }

/* Ruhezustand ist der gelegte Stapel. Das Auffächern setzt Abschnitt 17. */
/* Original: warmes Papier */
.ps-pages__card--original { background: #F6EADA; transform: translate(-46%, 7%) rotate(-7deg); }
.ps-pages__card--original span { background: #C4A882; }
/* Graustufen */
.ps-pages__card--grey { background: #E9E9E7; transform: translate(0, 0) rotate(0deg); }
.ps-pages__card--grey span { background: #9A9A97; }
/* Schwarz-Weiß */
.ps-pages__card--bw { background: #FFFFFF; transform: translate(46%, -7%) rotate(7deg); }
.ps-pages__card--bw span { background: #1B1B1E; }

/* --------------------------------------------------------------------------
   10. Außerdem — die Nebensachen. Zwei Spalten, keine Rahmen, keine Haarlinie
   unter jeder Zeile.
   -------------------------------------------------------------------------- */

.ps-extras {
  padding-bottom: var(--ps-section);
}
.ps-extras__title {
  margin: 0 0 28px;
  font-family: var(--ps-font-display);
  font-weight: 500;
  font-size: 20px;
  letter-spacing: -0.02em;
  color: var(--ps-ink-700);
}
.ps-extras__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 30px 64px;
}
.ps-extra {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 14px;
  align-items: start;
}
.ps-extra .ps-icon { margin-top: 2px; }
.ps-extra h3 {
  margin: 0 0 4px;
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: -0.012em;
}
.ps-extra p {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ps-ink-700);
}

/* --------------------------------------------------------------------------
   11. Warum — typografisches Statement auf getönter Fläche. Nach der Bewegung
   des Durchlaufs bewusst still.
   -------------------------------------------------------------------------- */

/* Durchlässig, damit die Reise der Kugel hier keine Lücke bekommt: dies war
   die einzige deckende Fläche zwischen Hero und Pro. Die beiden Haarlinien
   tragen die Abgrenzung jetzt allein. */
.ps-why {
  background: transparent;
  border-top: 1px solid var(--ps-border-subtle);
  border-bottom: 1px solid var(--ps-border-subtle);
}
.ps-why__inner {
  padding-top: var(--ps-section);
  padding-bottom: var(--ps-section);
  display: grid;
  gap: 56px;
}
.ps-why__title {
  margin: 0;
  max-width: 19ch;
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(31px, 4.2vw, 52px);
  letter-spacing: -0.036em;
  line-height: 1.06;
  text-wrap: balance;
}
.ps-why__title + .ps-why__lead { margin-top: 28px; }
.ps-why__lead {
  margin: 0;
  max-width: 58ch;
  font-size: 18px;
  line-height: 1.65;
  color: var(--ps-ink-700);
}

.ps-principles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 48px;
}
.ps-principle {
  display: grid;
  gap: 12px;
  align-content: start;
}
.ps-principle__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 500;
  font-size: 22px;
  letter-spacing: -0.022em;
  line-height: 1.25;
  text-wrap: balance;
}
.ps-principle p {
  margin: 0;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ps-ink-700);
}

/* --------------------------------------------------------------------------
   12. Pro — Kopf mit Gerät, darunter acht Punkte in zwei Spalten. Keine
   Hairline-Tabelle, keine Karten.
   -------------------------------------------------------------------------- */

.ps-pro {
  padding-top: var(--ps-section);
  padding-bottom: var(--ps-section);
  /* Das Gerät läuft über Kopf und Liste hinweg, sonst reißt neben dem
     kurzen Kopf eine Lücke von der halben Gerätehöhe auf. */
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 260px);
  gap: 40px 64px;
  align-items: start;
}
.ps-pro__top { display: contents; }
.ps-pro__head { grid-column: 1; grid-row: 1; }
.ps-pro__shot { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
.ps-pro__list { grid-column: 1; grid-row: 2; }
.ps-pro__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--ps-space-4);
}
.ps-pro__badges {
  display: flex;
  align-items: center;
  gap: 10px;
}
.ps-pro__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(28px, 3.4vw, 42px);
  letter-spacing: -0.034em;
  line-height: 1.1;
  text-wrap: balance;
}
.ps-pro__note {
  margin: 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--ps-ink-700);
}
.ps-pro__shot {
  justify-self: end;
  width: 100%;
  max-width: 260px;
}
.ps-pro__shot .ps-device {
  width: 100%;
  aspect-ratio: 414 / 812;
}

.ps-pro__list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 22px 64px;
}
.ps-pro__list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  font-size: 16px;
  line-height: 1.55;
  color: var(--ps-ink-700);
}
.ps-pro__list .ps-icon { margin-top: 2px; }

/* --------------------------------------------------------------------------
   13. Privatsphäre — Manifest, dunkel. Zweiter und letzter dunkler Block,
   Gegenstück zum Hero.
   -------------------------------------------------------------------------- */

/* Durchlässig wie die übrigen Sektionen: die eigene Tintenfläche hätte den
   bewegten Grund darunter abgedeckt. Die Schriftfarbe bleibt gesetzt, damit
   der Abschnitt auch ohne WebGL und ohne Skript hell auf dunkel bleibt. */
.ps-privacy {
  background: transparent;
  color: var(--ps-text-on-inverse);
}
.ps-privacy__inner {
  padding-top: var(--ps-section);
  padding-bottom: var(--ps-section);
  display: grid;
  gap: 40px;
}
.ps-privacy__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(34px, 4.8vw, 58px);
  letter-spacing: -0.038em;
  line-height: 1.04;
}
.ps-privacy__title em {
  font-style: normal;
  color: var(--ps-accent);
}
.ps-privacy__lead {
  margin: 0;
  max-width: 56ch;
  font-size: 18px;
  line-height: 1.65;
  color: var(--ps-linen-300);
}

.ps-facts {
  margin: 0;
  padding: 24px 0 0;
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px 40px;
  border-top: 1px solid rgba(233, 225, 211, 0.16);
}
.ps-facts li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: center;
  font-size: 16px;
  color: var(--ps-paper-50);
}
.ps-facts .ps-icon { color: var(--ps-copper-500); }

/* --------------------------------------------------------------------------
   14. Beta — Abschluss auf Kupferton
   -------------------------------------------------------------------------- */

.ps-beta {
  padding-top: var(--ps-section);
  padding-bottom: var(--ps-section);
}
.ps-beta__frame {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--ps-space-5);
  padding: 64px 40px 68px;
  border-radius: var(--ps-radius-xl);
  /* Die Kachel war eine helle Kupferfläche mit dunkler Schrift. Auf der
     dunklen Seite wäre sie eine Insel, und weil die Schrift mit dem Grund
     gekippt ist, stand sie hell auf hell. Jetzt eine gehobene Tintenfläche
     mit Kupferkante — dieselbe Rolle, andere Richtung. */
  background: var(--ps-surface-inverse);
  border: 1px solid rgba(201, 122, 61, 0.34);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}
.ps-beta__title {
  margin: 0;
  max-width: 18ch;
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(29px, 3.6vw, 44px);
  letter-spacing: -0.034em;
  line-height: 1.08;
  text-wrap: balance;
}
.ps-beta__text {
  margin: 0;
  max-width: 58ch;
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--ps-ink-700);
}
.ps-note {
  margin: 0;
  font-size: 14.5px;
  color: var(--ps-linen-500);
}

/* Der Kaffee auf der Kachel.

   Eine eigene Bitte, aber kein eigenes Kapitel: die Museumsschild-Nummern
   laufen 01–07 und erzählen die App, nicht die Kasse. Die Haarlinie trennt
   deshalb, was die Nummern nicht trennen sollen. Sie läuft auf Textbreite,
   nicht über die volle Kachel — über die ganze Breite gezogen zerschneidet
   sie die Kachel in zwei Karten, und zwei Karten wären zwei Bitten.

   Der Knopf bleibt ein Geisterknopf. Zwei gefüllte Kupferflächen über-
   einander hätten die Kachel zwei Hauptknöpfe gegeben, und der TestFlight-
   Knopf ist der, um den es hier geht. */
.ps-support {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ps-space-4);
  width: 100%;
  max-width: 62ch;
  margin-top: var(--ps-space-3);
  padding-top: var(--ps-space-6);
  border-top: 1px solid var(--ps-border-subtle);
}
.ps-support__icon { color: var(--ps-copper-500); }
.ps-support__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -0.016em;
  line-height: 1.25;
  color: var(--ps-ink-900);
  text-wrap: balance;
}
.ps-support__text {
  margin: 0;
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--ps-ink-700);
}
.ps-support__cta { margin-top: var(--ps-space-2); }
.ps-support__cta .ps-icon { color: currentColor; }


/* --------------------------------------------------------------------------
   15. Footer
   -------------------------------------------------------------------------- */

.ps-footer {
  background: transparent;
  border-top: 1px solid var(--ps-border-subtle);
  margin-top: auto;
}
/* Ohne eigenen Rastpunkt bleibt die Fußzeile unerreichbar: der letzte Halt
   liegt am Anfang der Beta-Station, und jede weitere Geste zieht dorthin
   zurück. `end` setzt den Punkt an das Seitenende, `always` sorgt dafür,
   dass die Geste dort wirklich hält. */
@media (min-width: 1000px) and (min-height: 900px) and (prefers-reduced-motion: no-preference) {
  .js .ps-footer {
    scroll-snap-align: end;
    scroll-snap-stop: always;
  }
}
.ps-footer__inner {
  padding-top: 32px;
  padding-bottom: max(32px, env(safe-area-inset-bottom));
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
.ps-footer__brand {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  text-decoration: none;
  color: var(--ps-ink-900);
  transition: opacity 0.18s ease-out;
}
.ps-footer__brand:hover { opacity: 0.68; }
.ps-footer__brand img { border-radius: 7px; }
.ps-footer__brand .ps-wordmark { font-size: 16px; letter-spacing: -0.02em; }
.ps-footer__claim {
  font-size: 14px;
  color: var(--ps-linen-500);
}
.ps-footer__links {
  display: flex;
  gap: 12px;
  font-size: 14px;
}
.ps-footer__links a {
  padding: 8px 6px;
  border-radius: var(--ps-radius-sm);
  color: var(--ps-ink-700);
  text-decoration: none;
  transition: color 0.18s ease-out;
}
.ps-footer__links a:hover { color: var(--ps-ink-900); }
.ps-footer__links a[aria-current="page"] {
  color: var(--ps-ink-900);
  font-weight: 600;
}
.ps-footer__copy {
  font-size: 13px;
  color: var(--ps-ink-500);
}

/* --------------------------------------------------------------------------
   16. Rechtliche Unterseiten
   -------------------------------------------------------------------------- */

.ps-legal {
  flex: 1;
  max-width: 760px;
  width: 100%;
  margin: 0 auto;
  padding: 72px var(--ps-gutter) 96px;
  display: flex;
  flex-direction: column;
  gap: 36px;
}
.ps-legal__head {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ps-legal__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 400;
  font-size: clamp(34px, 4.4vw, 52px);
  letter-spacing: -0.035em;
  line-height: 1.06;
  text-wrap: balance;
}
.ps-legal__stand {
  margin: 0;
  font-size: 15px;
  color: var(--ps-linen-500);
}
.ps-legal section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.ps-legal h2 {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 22px;
  letter-spacing: -0.015em;
  line-height: 1.3;
}
.ps-legal p {
  margin: 0;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--ps-ink-700);
}
.ps-legal .ps-lead + p,
.ps-legal p + p { margin-top: 4px; }

/* Definitionslisten für Berechtigungen und Empfänger */
.ps-legal dl {
  margin: 4px 0 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ps-legal dt {
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 16.5px;
  letter-spacing: -0.01em;
  color: var(--ps-ink-900);
}
.ps-legal dd {
  margin: 2px 0 0;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--ps-ink-700);
}

/* Offene Felder deutlich markieren, damit vor dem Launch keines übersehen wird.
   TODO: Klasse zusammen mit dem eingesetzten Wert entfernen. */
.ps-todo {
  background: var(--ps-copper-100);
  box-shadow: inset 0 -2px 0 var(--ps-copper-500);
  border-radius: 3px;
  padding: 0 3px;
  color: var(--ps-accent-text);
  font-weight: 600;
}

.ps-footer__copy a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color 0.18s ease-out;
}
.ps-footer__copy a:hover { color: var(--ps-ink-700); }

.ps-notfound { gap: 28px; justify-content: center; }

.ps-back {
  display: inline-flex;
  align-items: center;
  /* 2.5.8 Target Size (Minimum) — die Zeilenhöhe allein trägt nur 23px. */
  min-height: 24px;
  gap: 7px;
  text-decoration: none;
  color: var(--ps-ink-700);
  font-size: 15px;
  transition: color 0.18s ease-out;
}
.ps-back:hover { color: var(--ps-ink-900); }
.ps-back .ps-icon { width: 17px; height: 17px; color: currentColor; }
.ps-back__short { display: none; }
@media (max-width: 560px) {
  .ps-back__long { display: none; }
  .ps-back__short { display: inline; }
}

/* --------------------------------------------------------------------------
   17. Kontaktdialog — das Formular, das erst auf Klick entsteht

   Ein natives <dialog> mit showModal(). Das bringt Fokusfalle, Escape,
   inerten Hintergrund und ::backdrop mit. Alles davon nachzubauen hiesse,
   es schlechter zu bauen.

   Das Markup steht nicht im HTML, sondern setzt papersmith.js beim ersten
   Öffnen — einmal, statt vier Mal in vier Dateien, die sonst beim nächsten
   Tippfehler auseinanderlaufen. Die zweisprachigen Spans funktionieren
   trotzdem: die Sprache hängt an der Wurzelklasse, nicht an einem Skript,
   das über das Markup läuft.

   Die Knöpfe, die den Dialog öffnen, stehen dagegen im HTML, und zwar als
   mailto-Links. Ohne JavaScript bleiben sie genau das und führen zur
   Adresse aus dem Impressum. Erst das Skript macht Schalter daraus. So
   steht nirgends ein toter Knopf.
   -------------------------------------------------------------------------- */

/* Der Auslöser in der Fußzeile. Nach dem Tausch ist es ein <button>, und der
   bringt eigene Schriftgrösse und einen Rahmen mit, die hier beide weg
   müssen — daneben stehen Links, und wie ein Link soll er auch aussehen. */
.ps-footer__links button {
  font-family: inherit;
  font-size: inherit;
  padding: 8px 6px;
  border: none;
  border-radius: var(--ps-radius-sm);
  background: none;
  color: var(--ps-ink-700);
  cursor: pointer;
  transition: color 0.18s ease-out;
}
.ps-footer__links button:hover { color: var(--ps-ink-900); }

/* Die Schale.
   display wird erst im offenen Zustand auf flex gesetzt: ein <dialog> ist
   geschlossen display:none, und eine pauschale flex-Regel würde es
   aufklappen, bevor jemand darum gebeten hat. */
.ps-dialog {
  width: min(544px, calc(100vw - 2 * var(--ps-gutter)));
  max-height: 88vh;
  max-height: 88dvh;
  padding: 0;
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--ps-radius-lg);
  background: var(--ps-surface-card);
  color: var(--ps-text-primary);
  box-shadow: var(--ps-shadow-banner);
  overflow: hidden;
}
.ps-dialog[open] {
  display: flex;
  flex-direction: column;
}
.ps-dialog::backdrop { background: rgba(12, 9, 7, 0.66); }

/* Die Seite dahinter stillstellen. showModal() sperrt die Bedienung, aber
   nicht verlässlich das Rollen — dieselbe Doppelregel, die der Preloader
   schon benutzt. */
html.ps-dialog-open,
html.ps-dialog-open body { overflow: hidden; }

.ps-dialog__form {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Kopf: Titel und Schliessen. Beide bleiben stehen, wenn der Körper rollt. */
.ps-dialog__head {
  display: flex;
  align-items: flex-start;
  gap: var(--ps-space-4);
  flex: 0 0 auto;
  padding: var(--ps-space-6) var(--ps-space-6) var(--ps-space-4);
  border-bottom: 1px solid var(--ps-border-subtle);
}
.ps-dialog__title {
  flex: 1 1 auto;
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.018em;
  line-height: 1.25;
  color: var(--ps-ink-900);
  text-wrap: balance;
}
.ps-dialog__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  margin: -8px -10px -8px 0;
  border: none;
  border-radius: var(--ps-radius-sm);
  background: transparent;
  color: var(--ps-ink-500);
  cursor: pointer;
  transition: color 0.18s ease-out, background-color 0.18s ease-out;
}
.ps-dialog__close:hover {
  color: var(--ps-ink-900);
  background: var(--ps-surface-sunken);
}
.ps-dialog__close .ps-icon { width: 19px; height: 19px; color: currentColor; }

/* Körper: der einzige Teil, der rollt. */
.ps-dialog__body {
  display: flex;
  flex-direction: column;
  gap: var(--ps-space-5);
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: var(--ps-space-5) var(--ps-space-6) var(--ps-space-6);
}

/* Der Umschalter ist derselbe Pill wie der Sprachwechsel in der Leiste, nur
   über die volle Breite und mit zwei gleich breiten Hälften. */
.ps-dialog__modes { align-self: stretch; }
.ps-dialog__modes button { flex: 1 1 0; min-height: 44px; }

.ps-dialog__intro {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ps-ink-700);
}

/* Die Felder */
.ps-field {
  display: flex;
  flex-direction: column;
  gap: var(--ps-space-2);
}
.ps-field[hidden] { display: none; }
.ps-field__label {
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 14.5px;
  color: var(--ps-ink-900);
}
.ps-field__label span {
  font-weight: 400;
  color: var(--ps-text-secondary);
}
.ps-field__hint,
.ps-field__error {
  font-size: 13.5px;
  line-height: 1.5;
}
.ps-field__hint { color: var(--ps-text-secondary); }
.ps-field__error { display: none; color: var(--ps-danger); }
.ps-field.is-invalid .ps-field__error { display: block; }

/* Die Eingaben.
   16px ist kein Zufall und keine Geschmacksfrage: Safari auf dem iPhone
   zoomt beim Hineintippen in jedes Feld, das kleiner gesetzt ist, und reisst
   damit das Layout auseinander. Der Fliesstext der Seite steht auf 15.5 —
   hier ist die halbe Stufe mehr der Preis dafür, dass nichts springt. */
.ps-input,
.ps-textarea,
.ps-select select {
  width: 100%;
  min-height: 46px;
  padding: 11px 14px;
  font-family: var(--ps-font-body);
  font-size: 16px;
  line-height: 1.5;
  color: var(--ps-text-primary);
  background: var(--ps-surface-page);
  border: 1px solid var(--ps-border-strong);
  border-radius: var(--ps-radius-sm);
  transition: border-color 0.18s ease-out;
}
.ps-input::placeholder,
.ps-textarea::placeholder { color: var(--ps-text-tertiary); }
.ps-input:hover,
.ps-textarea:hover,
.ps-select select:hover { border-color: var(--ps-ink-300); }
.ps-field.is-invalid .ps-input,
.ps-field.is-invalid .ps-textarea { border-color: var(--ps-danger); }

.ps-textarea {
  min-height: 136px;
  resize: vertical;
}

/* Die Auswahl.
   Der Pfeil ist aus zwei Rahmenkanten gebaut, nicht aus einem Bild: die CSP
   erlaubt unter img-src nur die eigene Herkunft, und das schliesst auch eine
   data:-URI im Hintergrund aus. */
.ps-select {
  position: relative;
  display: block;
}
.ps-select select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 44px;
  cursor: pointer;
}
.ps-select::after {
  content: "";
  position: absolute;
  top: 50%;
  right: 18px;
  width: 8px;
  height: 8px;
  margin-top: -6px;
  border-right: 2px solid var(--ps-ink-500);
  border-bottom: 2px solid var(--ps-ink-500);
  transform: rotate(45deg);
  pointer-events: none;
}

/* Der Honigtopf.
   Steht im Markup, ist aber für Menschen unerreichbar: aus dem Bild
   geschoben, aus der Tabulatorfolge genommen und für Screenreader
   ausgeblendet. Wer ihn ausfüllt, war eine Maschine. */
.ps-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Die Meldung, wenn das Senden scheitert. */
.ps-alert {
  margin: 0;
  padding: var(--ps-space-4);
  border: 1px solid var(--ps-danger);
  border-radius: var(--ps-radius-md);
  background: rgba(224, 138, 114, 0.1);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ps-ink-700);
}
.ps-alert a { color: var(--ps-accent-text); }

/* Fuss: Rechtszeile und Absendeknopf. */
.ps-dialog__foot {
  display: flex;
  align-items: center;
  gap: var(--ps-space-4);
  flex: 0 0 auto;
  padding: var(--ps-space-4) var(--ps-space-6) var(--ps-space-6);
  border-top: 1px solid var(--ps-border-subtle);
}
.ps-dialog__legal {
  flex: 1 1 auto;
  margin: 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ps-text-secondary);
}
.ps-dialog__legal a { color: var(--ps-accent-text); }
.ps-dialog__send { flex: 0 0 auto; }
.ps-dialog__send[disabled] {
  opacity: 0.55;
  cursor: default;
}

/* Angekommen. Ersetzt Körper und Fuss, damit niemand zweimal sendet. */
.ps-done {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ps-space-4);
  padding: var(--ps-space-9) var(--ps-space-6);
  text-align: center;
}
.ps-done__icon {
  width: 38px;
  height: 38px;
  color: var(--ps-success);
}
.ps-done__title {
  margin: 0;
  font-family: var(--ps-font-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -0.016em;
  color: var(--ps-ink-900);
}
.ps-done__text {
  margin: 0;
  max-width: 44ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ps-ink-700);
}

/* Das Auftauchen. Die Keyframes stehen hier und nicht in Abschnitt 18, weil
   sie diesem einen Bauteil gehören — ps-rise und ps-scan dort teilen sich
   mehrere Sektionen. */
@media (prefers-reduced-motion: no-preference) {
  .ps-dialog[open] { animation: ps-dialog-in 0.22s ease-out; }
  .ps-dialog[open]::backdrop { animation: ps-backdrop-in 0.22s ease-out; }
}
@keyframes ps-dialog-in {
  from { opacity: 0; transform: translateY(10px) scale(0.988); }
  to   { opacity: 1; transform: none; }
}
@keyframes ps-backdrop-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Schmale Displays: weniger Rand, und der Absendeknopf über die volle
   Breite. Die Rechtszeile rutscht darüber, weil sie gelesen werden soll,
   bevor gedrückt wird. */
@media (max-width: 560px) {
  .ps-dialog {
    width: calc(100vw - 2 * var(--ps-gutter));
    max-height: 92vh;
    max-height: 92dvh;
  }
  .ps-dialog__head,
  .ps-dialog__body,
  .ps-dialog__foot {
    padding-left: var(--ps-space-5);
    padding-right: var(--ps-space-5);
  }
  .ps-dialog__foot {
    flex-direction: column;
    align-items: stretch;
    gap: var(--ps-space-3);
  }
  .ps-dialog__send { width: 100%; }
}

/* --------------------------------------------------------------------------
   18. Animationen
   -------------------------------------------------------------------------- */

@keyframes ps-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
@keyframes ps-scan {
  0%   { top: 7%;  opacity: 0; }
  6%   { opacity: 0.8; }
  42%  { top: 84%; opacity: 0.8; }
  48%  { top: 88%; opacity: 0; }
  100% { top: 88%; opacity: 0; }
}

/* --------------------------------------------------------------------------
   17.2 Einrasten — ein Scroll, eine Station

   Jede Station ist genau ein Bildschirm, eine Geste geht genau eine Station
   weiter. `scroll-snap-stop: always` ist dabei das Stück, das zählt: ohne es
   überspringt ein Schwung auf dem Trackpad mehrere Punkte, und die Zusage
   „ein Scroll, eine Sektion" wäre keine.

   Der Preis ist bekannt und gewollt: Trackpad-Schwung kämpft gegen das
   Einrasten, Tastatur-Scrollen und Seitensuche werden ruppiger. Deshalb die
   harte Bedingung — eingerastet wird nur ab 1000×900, weil erst dort jede
   Station auf einen Bildschirm passt. Passt sie nicht, wäre ihr unteres Ende
   unerreichbar: die nächste Geste springt zur nächsten Station, nicht zum
   Rest der aktuellen. Lieber gar kein Einrasten als unerreichbarer Text.
   -------------------------------------------------------------------------- */

@media (min-width: 1000px) and (min-height: 900px) and (prefers-reduced-motion: no-preference) {
  /* Nur die Startseite rastet ein. `data-preload` steht ausschließlich an
     ihrem <html> und ist damit der vorhandene Griff dafür — Impressum,
     Datenschutz und 404 scrollen normal weiter. */
  html.js[data-preload] { scroll-snap-type: y mandatory; }

  /* Die gemessene Höhe der Navigation. `--ps-nav-height` ist mit 62px die
     Schätzung für `scroll-padding`; die Leiste misst mit ihrer Haarlinie 68px,
     und hier zählt der Unterschied — sechs Pixel zu viel, und jede Station ist
     höher als der Platz, den sie hat. */
  .js .ps-hero,
  .js .ps-flow__head,
  .js .ps-beat,
  .js .ps-extras,
  .js .ps-why,
  .js .ps-pro,
  .js .ps-privacy,
  .js .ps-beta {
    scroll-snap-align: start;
    scroll-snap-stop: always;
    min-height: calc(100vh - 68px);
  }

  /* Der Kopf des Durchlaufs ist eine eigene Station, sonst rastet der Sprung
     aus der Navigation auf Beat 1 ein und die Überschrift liegt oberhalb des
     Bildes. Als Kapiteltitel auf eigener Fläche ist das ohnehin die klarere
     Lesart. Der Lead gehört dazu, deshalb umfasst die Station beides. */
  .js .ps-flow { padding-top: 0; }
  .js .ps-flow__head {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* Die Polsterung weicht der Mindesthöhe — sonst addiert sie sich auf sie
     drauf und keine Station passt mehr. */
  .js .ps-extras,
  .js .ps-pro,
  .js .ps-beta { padding-top: 0; padding-bottom: 0; }
  .js .ps-why__inner,
  .js .ps-privacy__inner { padding-top: 0; padding-bottom: 0; }

  /* Mittig statt oben. Jede Sektion behält ihre eigene Anordnung: `.ps-pro`
     und `.ps-beat` sind Raster und bekommen `align-content`, die übrigen sind
     Blöcke und werden zur Spalte. `display` zu überschreiben würde bei den
     Rastern Kopf, Bild und Liste untereinander werfen. */
  .js .ps-pro { align-content: center; }
  .js .ps-beat { align-items: center; }
  .js .ps-hero,
  .js .ps-extras,
  .js .ps-why,
  .js .ps-privacy,
  .js .ps-beta {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }

  /* Der Weg zum Pinnen entfällt: die Bühne reist nicht mehr durch den Text,
     sie steht mit ihm auf derselben Station. */
  .js .ps-beat__text { min-height: 0; padding-top: 0; padding-bottom: 0; }
  .js .ps-beat__figure { position: static; }

  /* Der Hero trägt das Faktenband mit: läge das Laufband zwischen zwei
     Rastpunkten, käme es nie zur Ruhe und wäre nur im Vorbeiflug zu sehen. */
  .js .ps-hero { min-height: calc(100vh - 68px - 65px); }
  .js .ps-hero__inner { padding-top: 4vh; padding-bottom: 4vh; }
}

/* Laufband — zwei gleiche Listen, also ist eine halbe Spurbreite genau eine
   Runde. Nur transform, damit es auf dem Compositor läuft. */
@keyframes ps-marquee {
  to { transform: translateX(-50%); }
}

/* Kugel — das Wabern der Vorlage.

   Gedreht, nicht verschoben: die Farbtaschen wandern auf einer Bahn um den
   Kugelmittelpunkt, wie ein Licht, das um einen Körper streicht. Das ist der
   Unterschied zwischen sichtbar und nicht sichtbar — ein weicher Verlauf hat
   keine Kante, an der das Auge eine Verschiebung festmachen könnte, aber eine
   umlaufende Lichtquelle liest sich sofort. Der Maßstab dazu (scale) ändert
   die Helligkeit; erst beides zusammen lebt.

   Die Bahn ist nach oben vorgespannt (mehr Plus- als Minusgrad): links unten
   liegt die Auflösung in die Tinte, und dorthin soll das Kupfer nicht kriechen.
   Ruhezustand ist überall 0° — unter reduzierter Bewegung steht also genau das
   Bild, das vorher stand. */
@keyframes ps-orb-light {
  0%, 100% { transform: rotate(0deg) scale(1); }
  26%      { transform: rotate(9deg) scale(1.13); }
  55%      { transform: rotate(2deg) scale(1.02); }
  78%      { transform: rotate(-7deg) scale(1.09); }
}
@keyframes ps-orb-copper {
  0%, 100% { transform: rotate(0deg) scale(1); }
  30%      { transform: rotate(13deg) scale(1.17); }
  60%      { transform: rotate(5deg) scale(1.03); }
  82%      { transform: rotate(-5deg) scale(1.12); }
}
/* Das An- und Abschwellen trägt die Hälfte der Bewegung: Helligkeit sieht das
   Auge auch dort, wo es keine Kante gibt. */
@keyframes ps-orb-breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.66; }
}
@keyframes ps-orb-breathe-soft {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.74; }
}
/* Die Ringe drehen um denselben Mittelpunkt, auf dem sie schon sitzen */
@keyframes ps-orb-ring {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* Einrasten — Klammern im Preloader und am Gerät, eine Geste, ein Keyframe.
   Der Startzustand steht am Element, damit vier Richtungen einen Keyframe teilen. */
@keyframes ps-snap {
  to { opacity: 1; transform: translate(0, 0); }
}

/* Preloader-Choreografie */
@keyframes ps-pl-develop { to { transform: translateY(0); } }
@keyframes ps-pl-fold    { to { opacity: 1; transform: scale(1); } }
@keyframes ps-pl-word    { to { opacity: 1; letter-spacing: 0.02em; } }
@keyframes ps-pl-meter   { to { opacity: 1; } }
@keyframes ps-pl-scan {
  0%   { opacity: 0; transform: translateY(0); }
  14%  { opacity: 1; }
  86%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(52px); }
}

/* Hero-Einstieg, gestaffelt — startet erst mit `is-loaded`, also in dem
   Moment, in dem der Preloader abhebt. Ohne JavaScript bleibt `is-loaded`
   aus, dann steht der Hero ohne Einstieg einfach da. */
.is-loaded .ps-rise   { animation: ps-rise 0.55s ease-out both; }
.is-loaded .ps-rise-1 { animation: ps-rise 0.50s ease-out 0.05s both; }
.is-loaded .ps-rise-2 { animation: ps-rise 0.55s ease-out 0.12s both; }
.is-loaded .ps-rise-3 { animation: ps-rise 0.65s ease-out 0.15s both; }

/* Scroll-Reveal — der Startzustand gilt nur mit aktivem JS,
   damit ohne JS nichts unsichtbar bleibt.
   Eine Bewegungssprache für alles: 0.55s ease-out, 18px Weg. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.55s ease-out, transform 0.55s ease-out;
  transition-delay: var(--ps-reveal-delay, 0ms);
  will-change: opacity, transform;
}
.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Gestaffelte Kinder — Verzögerung setzt das Skript als Custom Property */
.js [data-stagger] > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.5s ease-out, transform 0.5s ease-out;
  transition-delay: var(--ps-reveal-delay, 0ms);
}
.js [data-stagger].is-revealed > * {
  opacity: 1;
  transform: none;
}

/* Die Mockups blenden ein, sie schieben sich nicht.

   Zwei Gründe für die Ausnahme von den 18 Pixeln, die sonst überall gelten:
   die Bühnen des Durchlaufs sind gepinnt, und ein Versatz beim Auftritt
   arbeitet gegen das Stehenbleiben — man sieht das Bild rutschen, während es
   eigentlich hält. Und der Auftritt gehört dem Screenshot, nicht der Bewegung;
   die Szenen in Beat 2 und 3 bringen ihre eigene mit. Der Pro-Screenshot geht
   denselben Weg, damit alle Mockups dieselbe Sprache sprechen.

   0.95 s statt der 0.55 s der übrigen Seite, und eine symmetrische Kurve statt
   `ease-out`: letztere springt in den ersten Zehnteln fast auf volle Deckung,
   dann ist die Überblendung vorbei, bevor das Auge sie fasst. Eine reine
   Überblendung ohne Weg braucht beides — Zeit und einen weichen Anlauf. */
.js .ps-beat__figure[data-reveal],
.js .ps-pro__shot[data-reveal] {
  transform: none;
  transition: opacity 0.95s cubic-bezier(0.4, 0, 0.2, 1);
}
.js .ps-beat__figure[data-reveal].is-revealed,
.js .ps-pro__shot[data-reveal].is-revealed { transform: none; }

/* 17.1 Die beiden Szenen im Durchlauf.

   Ruhezustand ist der aufgelöste, siehe Abschnitt 9. Hier wird nur der
   unaufgelöste Start gesetzt, und zwar ausschließlich mit aktivem JS und
   erst ab der Breite, in der die Bühne überhaupt gepinnt wird. Ohne JS,
   auf dem Telefon und bei reduzierter Bewegung steht die Szene fertig da. */
@media (min-width: 901px) {
  .js .ps-beat:not(.is-played) .ps-scan__sheet { transform: rotate(-7deg) scale(0.94); }
  .js .ps-beat:not(.is-played) .ps-scan__brackets { transform: scale(1.42); }
  .js .ps-beat:not(.is-played) .ps-pages__card--original { transform: translate(-12%, 12%) rotate(-14deg); }
  .js .ps-beat:not(.is-played) .ps-pages__card--grey { transform: translate(0, 0) rotate(4deg); }
  .js .ps-beat:not(.is-played) .ps-pages__card--bw { transform: translate(12%, -10%) rotate(16deg); }
}

/* Lesefortschritt — feine Kupferlinie an der Unterkante der Navigation */
.ps-progress {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: 100%;
  transform: scaleX(var(--ps-progress, 0));
  transform-origin: 0 50%;
  background: var(--ps-copper-500);
  opacity: 0.9;
  pointer-events: none;
}

/* Navigation legt beim Scrollen einen leisen Schatten an */
.ps-nav {
  transition: box-shadow 0.25s ease-out, background-color 0.25s ease-out;
}
.ps-nav.is-scrolled {
  /* Milchglas in Tinte statt in Papier — die Kugel zieht darunter durch und
     soll sich abzeichnen, ohne die Leiste unlesbar zu machen. */
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
  background: rgba(28, 24, 21, 0.82);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  .js [data-reveal],
  .js [data-stagger] > * { opacity: 1; transform: none; }
  /* Die Bühne bleibt stehen, aber ihr Inhalt löst sich nicht mehr auf */
  .js .ps-beat:not(.is-played) .ps-scan__sheet,
  .js .ps-beat:not(.is-played) .ps-scan__brackets,
  .js .ps-beat:not(.is-played) .ps-pages__card--original,
  .js .ps-beat:not(.is-played) .ps-pages__card--grey,
  .js .ps-beat:not(.is-played) .ps-pages__card--bw { transform: none; }
  .js .ps-beat:not(.is-played) .ps-pages__card--original { transform: translate(-46%, 7%) rotate(-7deg); }
  .js .ps-beat:not(.is-played) .ps-pages__card--bw { transform: translate(46%, -7%) rotate(7deg); }
  /* Das Laufband steht still — dann aber als zentrierte Liste wie früher,
     nicht als angehaltene Spur mit halb sichtbarem Nachlauf. */
  .ps-promise__track { width: auto; flex-wrap: wrap; justify-content: center; }
  .ps-promise__list { flex-wrap: wrap; justify-content: center; }
  .ps-promise__list:last-child { display: none; }
  .ps-promise::before,
  .ps-promise::after { display: none; }
  .ps-scanline { display: none; }
  .ps-progress { display: none; }
  .ps-nav.is-scrolled { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* --------------------------------------------------------------------------
   19. Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 1080px) {
  :root { --ps-section: 84px; }

  /* Die Leiste rückt zusammen, bevor sie einklappt.

     Gemessen: mit beiden Symbolknöpfen lief die Zeile zwischen 901 und 930
     über — knapp, um 30px auf Deutsch und 25px auf Englisch. Genau dort ist
     der Menüschalter schon weg (ab 901) und die Links stehen wieder in der
     Reihe, es gibt also kein Panel, in das die Knöpfe ausweichen könnten.

     Sechs Elemente lassen fünf Zwischenräume. Acht Pixel weniger je Raum
     sind vierzig Pixel für die Zeile und schliessen die Lücke mit zehn
     Pixeln Luft, ohne dass ein Umbruchpunkt wandern muss. Mit 28 oben,
     20 hier und 16 unter 900 wird der Abstand zur Treppe, die mit dem
     Platz absteigt. */
  .ps-nav__inner { gap: 20px; }

  .ps-hero__inner { gap: 48px; }
  .ps-hero__device { max-width: 296px; }
  /* Unterhalb von 1080px ist zwischen Textspalte und Gerät kein Platz mehr für
     die Ringe, ohne dass sie durch die Headline laufen — gemessen 2.32:1 auf den
     Punkten, die die Kupferzeile kreuzen. Ornament weicht, Text bleibt. */
  .ps-hero__orb::before,
  .ps-hero__orb::after { display: none; }
  .ps-beat { gap: 48px; }
  .ps-beat__figure { max-width: 300px; }
  .ps-pro { gap: 36px 48px; }
  .ps-extras__list { gap: 28px 44px; }
  .ps-pro__list { gap: 20px 44px; }
}

/* Navigation klappt ein. Und der Durchlauf löst die Pinnung auf:
   ein Pfad für Telefon, fehlendes JavaScript und reduzierte Bewegung. */
@media (max-width: 900px) {
  :root { --ps-gutter: 24px; --ps-section: 72px; }

  .ps-nav__inner { gap: 16px; }
  .ps-nav__toggle { display: inline-flex; order: 3; }

  .ps-nav__links {
    display: none;
    order: 4;
    width: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    padding: 8px 0 12px;
    border-top: 1px solid var(--ps-border-subtle);
    margin-top: 6px;
  }
  .ps-nav__inner.is-open { flex-wrap: wrap; }
  .ps-nav__inner.is-open .ps-nav__links { display: flex; }
  .ps-nav__link {
    padding: 13px 4px;
    font-size: 16px;
    border-radius: var(--ps-radius-md);
  }

  .ps-hero__inner {
    grid-template-columns: minmax(0, 1fr);
    gap: 40px;
    padding-top: 64px;
    padding-bottom: 72px;
  }
  /* Einspaltig darf der Typoblock nicht mehr so hoch bauen */
  .ps-hero__label { margin-bottom: var(--ps-space-6); }
  .ps-hero__title { margin-bottom: var(--ps-space-6); font-size: clamp(38px, 11vw, 64px); }
  .ps-hero__subline { margin-bottom: var(--ps-space-7); }
  .ps-hero__device { justify-self: start; max-width: 272px; }
  /* Einspaltig ist die Lichtform zu groß für die Fläche: sie landet sonst unter
     der Kupferzeile und drückt deren Kontrast von 4.58:1 auf 3.48:1. Kleiner und
     an den rechten Rand — dort berührt sie keinen Text.

     62% war zu weit links: die Kugel lag bei 360px Breite über „Features
     ansehen" (gemessen x 104–342 gegen den Link auf x 20–174), und dort steht
     helle Schrift ohne eigene Fläche auf der hellsten Stelle der Kugel — im
     schlechtesten Anlauf der Animation 4.30:1. Der Knopf darüber trägt seine
     Kupferfläche selbst und war nie betroffen. 82%/42% schiebt die Kugel
     rechts an den Zeilenenden vorbei; ihr linkes Stück verschwindet hinter
     dem Gerät, wie im zweispaltigen Hero auch. */
  .ps-hero__orb { top: 42%; left: 82%; width: min(320px, 66vw); }

  .ps-flow__beats { display: grid; gap: 60px; }
  .ps-beat { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .ps-beat__text { min-height: 0; padding: 0 0 0 22px; }
  .ps-beat__text::before { top: 0; height: 100%; margin-top: 0; }
  .ps-beat.is-active .ps-beat__text::before { height: 100%; margin-top: 0; }
  .ps-beat__figure {
    position: static;
    justify-self: start;
    max-width: 288px;
    margin-left: 22px;
  }

  .ps-principles { grid-template-columns: minmax(0, 1fr); gap: 34px; }
  .ps-why__inner { gap: 44px; }

  .ps-pro { grid-template-columns: minmax(0, 1fr); gap: 36px; }
  .ps-pro__head, .ps-pro__shot, .ps-pro__list { grid-column: 1; grid-row: auto; }
  .ps-pro__shot { justify-self: start; max-width: 232px; }
  .ps-pro__list { grid-template-columns: minmax(0, 1fr); gap: 18px; }

  .ps-extras__list { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .ps-facts { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  :root { --ps-section: 64px; }

  /* Der CTA nimmt die ganze Zeile, der Ghost-Link rutscht darunter */
  .ps-hero__actions { width: 100%; gap: var(--ps-space-4); }
  .ps-hero__actions .ps-btn { flex: 1 1 100%; }

  .ps-promise__list li { font-size: 13.5px; }
  .ps-promise__list li::before { margin: 0 19px; }

  .ps-beta__frame { padding: 48px 26px 52px; }

  .ps-legal { padding-top: 56px; padding-bottom: 72px; gap: 30px; }
  .ps-legal__title { font-size: 34px; }

  .ps-footer__inner { gap: 16px; }
  .ps-footer__spacer { display: none; }
  .ps-footer__links { width: 100%; margin-left: -6px; }
}

/* Umbruch der beiden Symbolknöpfe: hier wandern sie ins Panel.

   720 ist gemessen, nicht geschätzt, und mit dem zweiten Knopf neu gemessen.
   Mit Kaffee und Kontakt bricht die Zeile in drei Bändern: 300–427, dann
   561–641 auf Deutsch und 561–673 auf Englisch (dort baut „Join the
   TestFlight beta“ breiter), und schliesslich 901–930. Das letzte Band ist
   oben im 1080er-Block geschlossen worden, indem die Zwischenräume der
   Leiste dort von 28 auf 20 gehen — dazu die Begründung ebendort.

   Bleibt ein Umbruch statt dreier: über 673 trägt die Zeile beide Knöpfe
   lückenlos bis 1000 und darüber hinaus. 720 lässt über dem englischen
   Bruch knapp fünfzig Pixel Luft für längere Übersetzungen und grössere
   Systemschrift. Darunter ist der Menüschalter ohnehin da (ab 900), das
   Panel also offen erreichbar.

   Zwischen 428 und 560 gingen die Knöpfe zwar auch — dort ist der CTA schon
   auf „TestFlight“ gekürzt —, aber ein Knopf, der auftaucht, verschwindet,
   wieder auftaucht und wieder verschwindet, ist keine Leiste, sondern ein
   Flackern. */
@media (max-width: 720px) {
  .ps-nav__coffee,
  .ps-nav__contact { display: none; }
  .ps-nav__coffee-panel,
  .ps-nav__contact-panel {
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .ps-nav__coffee-panel .ps-icon,
  .ps-nav__contact-panel .ps-icon { color: var(--ps-copper-500); }
}

/* Sehr schmale Geräte: Wortmarke, Sprachschalter und CTA müssen nebeneinander passen */
@media (max-width: 560px) {
  :root { --ps-gutter: 20px; }

  .ps-nav__inner { gap: 12px; }
  .ps-nav__brand .ps-wordmark { font-size: 17px; }
  .ps-nav__cta-full { display: none; }
  .ps-nav__cta-mini { display: inline; }
  .ps-nav .ps-btn--sm { padding: 0 14px; font-size: 14px; }
  .ps-nav__segment-inline { display: none; }
  .ps-nav__segment-panel { display: flex; align-self: flex-start; margin-top: 8px; }

  .ps-hero__inner { padding-top: 52px; padding-bottom: 60px; }
  .ps-hero__device { max-width: min(264px, 76vw); }
  .ps-hero__brackets { inset: -9px; }
  .ps-hero__brackets span { width: 20px; height: 20px; border-width: 1.25px; }

  /* Das Faktenband kippt von einer Zeile mit Trennstrichen auf zwei Spalten */
  .ps-promise__list li::before { margin: 0 16px; }
  .ps-promise::before,
  .ps-promise::after { width: 40px; }

  .ps-beat__text { padding-left: 18px; }
  .ps-beat__figure { margin-left: 18px; max-width: min(288px, 82vw); }

  .ps-facts { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .ps-facts li { padding-top: 12px; padding-bottom: 12px; }

  .ps-beta__frame { padding: 40px 22px 44px; }
  .ps-beta__cta { width: 100%; }
}

@media (max-width: 380px) {
  .ps-nav__brand .ps-wordmark { font-size: 16px; }
  .ps-nav .ps-btn--sm { padding: 0 12px; }
  /* Auf den Rechtsseiten stehen Brand, Sprachumschalter und Zurück-Link in
     einer Zeile; bei 320px sprengt sie sonst den Viewport um 11px. */
  .ps-nav__inner { gap: 8px; }
  .ps-segment button { padding: 0 10px; }
  .ps-promise__list li::before { margin: 0 13px; }
}

/* Querformat auf niedrigen Displays: Hero nicht überhoch werden lassen */
@media (max-height: 520px) and (orientation: landscape) {
  .ps-hero__inner { padding-top: 40px; padding-bottom: 48px; }
  .ps-hero__device { max-width: 210px; }
}


/* --------------------------------------------------------------------------
   20. Druck — vor allem für die rechtlichen Seiten
   -------------------------------------------------------------------------- */

@media print {
  .ps-nav, .ps-promise, .ps-skip-link, .ps-footer__links { display: none !important; }
  body { background: #fff; color: #000; }
  .ps-legal { padding: 0; max-width: none; }
  .ps-legal p, .ps-legal h2 { color: #000; }
  a { color: #000; text-decoration: underline; }
}

/* --------------------------------------------------------------------------
   App-Store-Badge — Apples Originalgrafik, unverändert.

   Apples Marketing-Richtlinien: das Badge nicht verändern, nicht drehen,
   nicht animieren; mindestens 40 px hoch; Freiraum rundum ein Viertel der
   Badgehöhe. Darum kein Hover-Effekt, kein Schatten, keine Einfärbung —
   nur der Fokusring, und der liegt ausserhalb der Grafik. 50 px Höhe
   entspricht dem grossen Knopf, den das Badge ersetzt; der Rand von
   13 px ist der Viertel-Freiraum.
   -------------------------------------------------------------------------- */
.ps-store {
  display: inline-flex;
  flex: none;
  margin: 13px;
  border-radius: 9px;
  line-height: 0;
}
.ps-store img {
  display: block;
  width: auto;
  height: 50px;
}
.ps-hero__actions .ps-store { margin-left: 0; }
.ps-beta__cta.ps-store { width: auto; margin-top: 0; margin-bottom: 0; }

/* --------------------------------------------------------------------------
   Launch-Hinweis — November 2026

   Ein schwebender Streifen am unteren Rand, kein Dialog: er hält nichts an
   und verlangt keinen Klick. Er kommt erst, wenn der Preloader abgehoben
   hat, und bleibt weg, sobald jemand ihn schließt oder dem Link folgt. Die
   Fläche ist dieselbe wie beim Nach-oben-Knopf — deckend, mit Kupferkante —,
   aus demselben Grund: sie liegt über allem und kann sich ihren Untergrund
   nicht aussuchen. Unter der Leiste (50), über dem Nach-oben-Knopf (40).
   -------------------------------------------------------------------------- */
.ps-launch {
  position: fixed;
  left: 50%;
  bottom: clamp(16px, 2.4vw, 34px);
  z-index: 45;
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 4px 16px;
  width: min(600px, calc(100vw - 2 * var(--ps-gutter)));
  padding: 10px 8px 10px 18px;
  border: 1px solid rgba(201, 122, 61, 0.42);
  border-radius: var(--ps-radius-lg);
  background: var(--ps-surface-inverse);
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45);
  transform: translateX(-50%);
}
.ps-launch[hidden] { display: none; }
.ps-launch__mark { width: 28px; height: 28px; }
.ps-launch__text {
  margin: 0;
  font-size: 15px;
  line-height: 1.4;
  color: var(--ps-text-primary);
}
.ps-launch__link {
  font-family: var(--ps-font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--ps-copper-500);
  text-decoration: none;
  white-space: nowrap;
  padding: 10px 4px;
}
.ps-launch__link:hover { color: var(--ps-copper-200); }
.ps-launch__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--ps-radius-pill);
  background: transparent;
  color: var(--ps-ink-500);
  cursor: pointer;
}
.ps-launch__close:hover { color: var(--ps-text-primary); background: rgba(233, 225, 211, 0.08); }
.ps-launch__close .ps-icon { width: 18px; height: 18px; }

/* Der Nach-oben-Knopf weicht nach oben aus, solange der Streifen steht. */
.has-launch .ps-totop { bottom: calc(clamp(16px, 2.4vw, 34px) + var(--ps-launch-h, 0px) + 12px); }

/* Das Konfetti — eine Leinwand über der Seite, die Klicks durchlässt und
   nach dem Schwall wieder verschwindet. */
.ps-confetti {
  position: fixed;
  inset: 0;
  z-index: 44;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .ps-launch {
    transition: opacity 0.5s ease, transform 0.6s cubic-bezier(0.2, 0.9, 0.25, 1);
  }
  .ps-launch.is-entering { opacity: 0; transform: translate(-50%, 24px); }
}

/* Schmal: der Link rückt unter den Satz, das Kreuz bleibt rechts oben. */
@media (max-width: 560px) {
  .ps-launch {
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: 0 12px;
    padding: 12px 6px 6px 14px;
  }
  .ps-launch__mark { margin-top: 2px; }
  .ps-launch__text { padding-top: 4px; }
  .ps-launch__link { grid-column: 2; grid-row: 2; justify-self: start; padding: 8px 0 10px; }
  .ps-launch__close { grid-column: 3; grid-row: 1 / span 2; margin-top: -6px; }
}
