/* =========================================================================
   SUPACE — Startseite v4 „Porcelain"
   -------------------------------------------------------------------------
   Eigenständig: diese Datei ist das GANZE Stylesheet der Seite. v4 lädt
   weder styles.css noch v2.css noch v3.css — sonst wäre es kein neues
   Design, sondern ein Aufsatz auf dem alten.

   Die Idee in einem Satz: die Seite ist kein Papier, sondern eine belichtete
   Fläche. Es gibt kein Grau — jeder Neutralton ist entweder zum Cyan hin
   gekühlt oder zum Bernstein hin gewärmt, weil es in einem beleuchteten
   Raum kein Grau gibt, sondern Licht und dessen Abwesenheit.

   Drei Regeln, die überall gelten:
   1. Hell. Dunkel sind nur die Produktaufnahmen selbst und der Fuß.
   2. Keine Trennlinien zwischen Dingen. Gegliedert wird über Weißraum und
      über Licht. Ein Rahmen UM eine ganze Karte ist erlaubt (Umriss ist
      keine Trennlinie).
   3. Keine 01/02/03-Nummerierung.
   ========================================================================= */

/* ---------- Marken und Licht ---------------------------------------------
   Die Blautöne kommen aus dem Logo und aus der App selbst (der Akzent in
   den Aufnahmen ist #2563EB). Bernstein und Gold sind reines Licht — sie
   werden nie als Flächenfarbe eingesetzt, nur als Schein.
   ------------------------------------------------------------------------ */
:root {
  --paper:      #F5F6FA;
  --paper-warm: #FBFAF8;
  --surface:    #FFFFFF;

  --ink:    #0D1220;
  --ink-2:  #39415A;
  --ink-3:  #656D80;   /* 5,18:1 auf Weiss, 4,83:1 auf --paper — AA auch bei 12 px */
  --ink-4:  #97A0B4;   /* 2,6:1 — NUR dekorativ (Sterne, inaktive Punkte).
                          Niemals fuer Text, den jemand lesen muss. */

  /* Umrisse — nur um ganze Karten, nie zwischen Zeilen */
  --edge:        rgba(13, 18, 32, 0.075);
  --edge-strong: rgba(13, 18, 32, 0.13);

  --blue:      #2456E8;
  --blue-deep: #16295E;
  --blue-soft: #6E97FF;
  --cyan:      #2FBBDD;
  --cyan-soft: #7FE0F2;
  --amber:     #F0AE62;
  --gold:      #B8933F;

  --dark:   #0B1020;      /* Fuss — die Marke, leicht blaustichig */
  --dark-2: #131A2E;
  /* Der Grund UNTER einer Produktaufnahme — abgetastet aus tour-poster.jpg
     (x=1500, y=700), nicht geschätzt. Nicht das Blau des Fusses: sonst
     blitzt beim Laden ein anderes Schwarz auf als im Video danach. */
  --screen: #080B12;
  /* Die App trägt an ihrer Oberkante eine Haarlinie, die nach rechts ins
     Cyan aufhellt — nachgemessen in tour-poster.jpg, Zeilen 4 bis 8:
     #194D62 · #2E8FA5 · #4BE0F4. Jede Fassung auf dieser Seite zitiert sie,
     damit gebaute Elemente und echte Aufnahmen dieselbe Sorte Objekt sind. */
  --app-edge: linear-gradient(90deg, #194D62 0%, #2E8FA5 42%, #4BE0F4 100%);
  /* Das Blau der App selbst — abgetastet vom „Ask"-Knopf in tour-poster.jpg
     (#1D4DDF/#1E49CB/#1F4DD7). Gilt nur auf dunklen Produktflächen; auf dem
     Papier bleibt --blue. */
  --app-accent: #2A5AE8;

  /* 20.08.2026: EINE Fassung fuer jede dunkle Flaeche. Vorher trugen .ts und
     .code buchstaeblich keinen Schatten und benutzten --dark statt --screen —
     sie lasen als eingeklebte Rechtecke, waehrend die Hero-Platte eine
     gefraeste Blende hat. Der erste Ring IST die Blende: Spread ohne
     Weichzeichnung zeichnet eine massive weisse Fassung, deren Eckenradius
     automatisch mitwaechst. */
  --win-dark:
    0 0 0 4px #FFFFFF,
    0 0 0 5px rgba(22, 41, 94, 0.10),
    inset 0 0 0 1px rgba(255, 255, 255, 0.07),
    0 10px 20px -14px rgba(8, 11, 18, 0.45),
    0 30px 56px -34px rgba(8, 11, 18, 0.42),
    0 60px 100px -70px rgba(36, 86, 232, 0.40);

  /* Figur und Grund: auf Weiss-auf-Fastweiss kann definitionsgemaess nichts
     schweben. Beide Enden sind gefaerbt (kuehl oben, warm unten) — kein Grau. */
  --card-cool:
    radial-gradient(130% 90% at 14% -12%, rgba(255,255,255,.95) 0%, rgba(255,255,255,0) 58%),
    linear-gradient(168deg, #FFFFFF 0%, #F7F9FD 46%, #EDF1F9 100%);
  --lift-card:
    0 1px 0 rgba(255,255,255,.95) inset, 0 0 0 1px rgba(22,41,94,.07),
    0 1px 2px rgba(22,41,94,.05), 0 14px 26px -18px rgba(22,41,94,.22),
    0 44px 76px -44px rgba(36,86,232,.20);
  --lift-card-hi:
    0 1px 0 rgba(255,255,255,.95) inset, 0 0 0 1px rgba(22,41,94,.07),
    0 2px 4px rgba(22,41,94,.06), 0 22px 38px -22px rgba(22,41,94,.26),
    0 66px 110px -60px rgba(36,86,232,.28);

  /* Maße */
  --wrap: 1240px;
  --wrap-narrow: 940px;
  --pad: clamp(1.15rem, 4vw, 2.5rem);

  --r-xs: 8px;
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 26px;
  --r-xl: 34px;
  /* Breite der hellen Fassung um eine Produktaufnahme. Uejs wollte sie
     dünner — war 9px. Innenradius und Glanzstreifen hängen mit dran. */
  --bez: 5px;

  /* Schatten sind gefärbt, nicht grau: kühl von oben, blau am Boden. */
  --lift-1:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 0 0 1px var(--edge),
    0 1px 2px rgba(13, 18, 32, 0.04),
    0 10px 24px -14px rgba(13, 18, 32, 0.18);
  --lift-2:
    0 1px 0 rgba(255, 255, 255, 0.95) inset,
    0 0 0 1px var(--edge),
    0 2px 4px rgba(13, 18, 32, 0.045),
    0 20px 44px -22px rgba(13, 18, 32, 0.22),
    0 44px 90px -50px rgba(36, 86, 232, 0.3);
  --lift-3:
    0 1px 0 rgba(255, 255, 255, 0.95) inset,
    0 0 0 1px var(--edge),
    0 3px 6px rgba(13, 18, 32, 0.05),
    0 30px 60px -28px rgba(13, 18, 32, 0.26),
    0 80px 150px -70px rgba(36, 86, 232, 0.38);

  --font:  "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --serif: "Instrument Serif", "Iowan Old Style", Georgia, serif;
  --mono:  "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --accent-grad: linear-gradient(100deg, var(--blue-deep) 8%, var(--blue) 52%, var(--cyan) 96%);

  --ease:   cubic-bezier(0.22, 1, 0.36, 1);
  --spring: cubic-bezier(0.16, 1, 0.3, 1);
  --smooth: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---------- Reset --------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 92px;
}

body {
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink-2);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "cv11", "ss01";
  overflow-x: clip;
}

img, svg, video { display: block; max-width: 100%; }
/* `hidden` muss gewinnen — .btn und .dl a setzen sonst display neu. */
[hidden] { display: none !important; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
input { font: inherit; }

::selection { background: color-mix(in srgb, var(--blue) 22%, transparent); color: var(--ink); }

:focus-visible {
  outline: 2.5px solid var(--blue);
  outline-offset: 3px;
  border-radius: 6px;
}

.skip {
  position: fixed;
  left: 1rem;
  top: -80px;
  z-index: 999;
  background: var(--ink);
  color: #fff;
  padding: 0.8rem 1.3rem;
  border-radius: var(--r-sm);
  transition: top 0.25s var(--ease);
}
.skip:focus { top: 1rem; }

/* ---------- Layout -------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
}

main > section {
  position: relative;
  padding-block: clamp(5rem, 11vw, 9.5rem);
}

/* ---------- Schrift ------------------------------------------------------- */
/* Der kursive Akzent ist eine ANDERE Schrift, nicht dieselbe schräggestellt.
   Das ist der Unterschied zwischen teuer und Vorlage. */
.display {
  font-family: var(--font);
  font-weight: 540;
  color: var(--ink);
  letter-spacing: -0.04em;
  line-height: 0.96;
  text-wrap: balance;
}
.display em {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.015em;
  /* optischer Ausgleich: die Serif sitzt bei gleicher Punktgröße kleiner */
  font-size: 1.06em;
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

h1.display { font-size: clamp(2.85rem, 8.4vw, 7rem); }
h2.display { font-size: clamp(2.1rem, 5.4vw, 4.3rem); }

h3 {
  font-size: clamp(1.1rem, 1.5vw, 1.32rem);
  font-weight: 580;
  letter-spacing: -0.02em;
  line-height: 1.25;
  color: var(--ink);
}
.ftr-col h3 {
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
}

.kicker {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--blue);
}

.lede {
  font-size: clamp(1.08rem, 1.9vw, 1.42rem);
  line-height: 1.45;
  letter-spacing: -0.018em;
  color: var(--ink-2);
  text-wrap: pretty;
}
.lede b { color: var(--ink); font-weight: 560; }

/* ALLE Abschnittskoepfe stehen mittig (19.08.2026). Vorher standen acht links
   und einer (FAQ) mittig, dazu mittig: Auftakt, Schluss, der Maker-Absatz und
   das Siegelband — das las sich als Zufall, nicht als System. Uejs: „manchmal
   ist die ueberschrift links, manchmal mittig … mach alles einheitlich".
   Mittig traegt hier, weil die Vorspaenne kurz sind (ein bis zwei Zeilen);
   bei langen Absaetzen waere es die schlechtere Wahl, weil das Auge den
   Zeilenanfang jedes Mal neu suchen muss. Der INHALT unter dem Kopf bleibt
   linksbuendig, wo er aus Karten oder Listen besteht — eine mittige
   Ueberschrift ueber linksbuendigem Inhalt ist die uebliche und ruhige
   Kombination, mittiger Fliesstext in Karten waere es nicht. */
.sec-head {
  /* 900px, NICHT 62ch: `ch` misst in der Schriftgroesse des Elements, und die
     ist hier 16 px — 62ch ergaben 609 px, also 52 % der Papierbreite. Die H2
     ist aber 68,8 px gross; sieben von neun brachen dadurch zweizeilig und
     standen mittig als schmale Rinne. Der Vorspann bekommt sein eigenes,
     engeres Mass, weil fuer LESBAREN Fliesstext die Zeichenzahl zaehlt und
     nicht die Pixelbreite. */
  max-width: 900px;
  margin-inline: auto;
  margin-bottom: clamp(2.5rem, 5vw, 4.5rem);
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 1.05rem;
}
.sec-lede {
  max-width: 56ch;
  margin-inline: auto;
  font-size: clamp(1rem, 1.35vw, 1.16rem);
  line-height: 1.55;
  color: var(--ink-3);
  text-wrap: pretty;
}
.sec-lede a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

.micro {
  font-family: var(--mono);
  font-size: 0.735rem;
  letter-spacing: 0.055em;
  color: var(--ink-3);
}

.cap {
  margin-top: 1.15rem;
  font-size: 0.85rem;
  color: var(--ink-3);
  text-align: center;
}
.cap b { color: var(--ink-2); font-weight: 560; }

b, strong { font-weight: 560; color: var(--ink); }

/* ---------- Symbole ------------------------------------------------------- */
.ic {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Die großen Marken stehen auf einer eigenen Scheibe. Ohne sie schwimmt ein
   1,5 px starkes Strichsymbol auf einer weißen Karte und wird zur Fußnote;
   mit ihr ist es ein Zeichen, das die Karte anführt. */
.ic-lg {
  width: 26px;
  height: 26px;
  padding: 10px;
  box-sizing: content-box;
  border-radius: 15px;
  stroke-width: 1.5;
  color: var(--blue);
  background:
    linear-gradient(158deg,
      color-mix(in srgb, var(--blue) 13%, #fff),
      color-mix(in srgb, var(--cyan) 11%, #fff));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent);
}
.card-off .ic-lg {
  color: var(--cyan);
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--cyan) 18%, #fff),
    color-mix(in srgb, var(--cyan) 8%, #fff));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    inset 0 0 0 1px color-mix(in srgb, var(--cyan) 26%, transparent);
}

/* ---------- Knöpfe -------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.72rem 1.3rem;
  border-radius: 999px;
  font-size: 0.94rem;
  font-weight: 540;
  letter-spacing: -0.012em;
  white-space: nowrap;
  transition: transform 0.45s var(--spring), box-shadow 0.3s var(--ease),
              background-color 0.3s var(--ease), color 0.3s var(--ease);
  translate: var(--mx, 0) var(--my, 0);
}
.btn-lg { padding: 0.95rem 1.75rem; font-size: 1rem; }
.btn-block { display: flex; width: 100%; }

.btn-fill,
.btn-primary {
  position: relative;
  color: #fff;
  background: linear-gradient(180deg, #3563EE, var(--blue) 55%, #1C46CE);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.28) inset,
    0 1px 2px rgba(13, 18, 32, 0.12),
    0 10px 22px -10px rgba(36, 86, 232, 0.55),
    0 22px 44px -26px rgba(36, 86, 232, 0.7);
}
.btn-fill:hover,
.btn-primary:hover {
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.34) inset,
    0 2px 4px rgba(13, 18, 32, 0.14),
    0 16px 32px -12px rgba(36, 86, 232, 0.6),
    0 34px 60px -30px rgba(36, 86, 232, 0.75);
}
.btn-fill:active,
.btn-primary:active { transform: translateY(1px); }

.btn-ghost {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 0 0 1px var(--edge-strong),
    0 8px 20px -14px rgba(13, 18, 32, 0.3);
}
.btn-ghost:hover { background: #fff; }

/* ══════════════════════════════════════════════════════════════════════════
   KOPFZEILE — schwebt frei, wird beim Scrollen zu einer Glasleiste.
   ══════════════════════════════════════════════════════════════════════════ */
.hdr {
  position: fixed;
  inset: 0 0 auto;
  z-index: 100;
  padding-block: 0.85rem;
  transition: padding 0.4s var(--ease), background-color 0.4s var(--ease),
              box-shadow 0.4s var(--ease), backdrop-filter 0.4s var(--ease);
}
.hdr.is-scrolled {
  padding-block: 0.55rem;
  background: rgba(246, 247, 250, 0.72);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  box-shadow: 0 1px 24px -12px rgba(13, 18, 32, 0.25);
}

.hdr-in {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--pad);
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 1.18rem;
  font-weight: 600;
  letter-spacing: -0.035em;
  color: var(--ink);
}
.brand img { width: 32px; height: 32px; border-radius: 8px; }

.hdr-nav {
  display: flex;
  align-items: center;
  gap: 0.15rem;
  margin-inline: auto;
}
.hdr-nav a {
  position: relative;
  padding: 0.45rem 0.72rem;
  border-radius: 999px;
  font-size: 0.885rem;
  font-weight: 480;
  color: var(--ink-3);
  transition: color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.hdr-nav a:hover { color: var(--ink); background: rgba(13, 18, 32, 0.045); }
.hdr-nav a.is-here { color: var(--ink); }
.hdr-nav a.is-here::after {
  content: "";
  position: absolute;
  left: 0.72rem;
  right: 0.72rem;
  bottom: 0.16rem;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--blue), var(--cyan));
}

/* Solange die Kopfzeile über dem Himmelsband schwebt, steht sie auf Cyan
   statt auf Papier — das gedämpfte Grau käme dort auf 3:1 und wäre zu
   schwach. Erst wenn sie zu Glas wird, darf sie sich zurücknehmen. */
.hdr:not(.is-scrolled) .hdr-nav a,
.hdr:not(.is-scrolled) .lnk { color: #223349; }
.hdr:not(.is-scrolled) .hdr-nav a:hover { color: var(--ink); background: rgba(255, 255, 255, 0.42); }

.hdr-act { display: flex; align-items: center; gap: 0.7rem; }
.lnk {
  font-size: 0.885rem;
  font-weight: 480;
  color: var(--ink-3);
  padding: 0.45rem 0.35rem;
  transition: color 0.25s var(--ease);
}
.lnk:hover { color: var(--ink); }

.burger {
  display: none;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  position: relative;
  background: rgba(255, 255, 255, 0.7);
  box-shadow: 0 0 0 1px var(--edge-strong);
}
.burger span {
  position: absolute;
  left: 12px;
  right: 12px;
  height: 1.6px;
  border-radius: 2px;
  background: var(--ink);
  transition: transform 0.35s var(--spring), opacity 0.2s;
}
.burger span:nth-child(1) { top: 17px; }
.burger span:nth-child(2) { top: 23px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(3px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { transform: translateY(-3px) rotate(-45deg); }

.mnav {
  display: none;
  margin: 0.7rem var(--pad) 0;
  padding: 1rem;
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, 0.9);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  backdrop-filter: blur(24px) saturate(180%);
  box-shadow: var(--lift-2);
}
.mnav.is-open { display: block; }
/* Auf einem kurzen Telefon (oder quer) ist das Menü höher als der Bildschirm.
   Ohne diese zwei Zeilen sind die untersten Einträge — Log in und der
   Knopf — schlicht unerreichbar, weil `body` beim Öffnen auf
   `overflow: hidden` steht und das Menü selbst nicht scrollt. */
.mnav {
  max-height: calc(100svh - 5.5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}
.mnav ul { display: grid; gap: 0.15rem; margin-bottom: 0.85rem; }
.mnav a {
  display: block;
  padding: 0.72rem 0.85rem;
  border-radius: var(--r-sm);
  font-size: 1rem;
  font-weight: 500;
  color: var(--ink);
}
.mnav a:hover { background: rgba(13, 18, 32, 0.045); }

/* ══════════════════════════════════════════════════════════════════════════
   LICHT — die Seite hat drei große farbige Lichtquellen statt grauer
   Flächen. Sie liegen hinter allem, fangen keine Zeiger ab und kosten
   nichts: reine Verläufe, kein Filter über der ganzen Seite.
   ══════════════════════════════════════════════════════════════════════════ */
/* Kein `filter: blur()` — Verläufe sind schon weich, und ein Weichzeichner
   über einer bildschirmgroßen Fläche kostet jeden Bildaufbau. */
.hero-light,
.close-light {
  position: absolute;
  inset: -22% -12% auto;
  height: 155%;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(48% 40% at 10% 0%,   color-mix(in srgb, var(--cyan) 22%, transparent) 0%, transparent 68%),
    radial-gradient(46% 38% at 90% -4%,  color-mix(in srgb, var(--blue) 18%, transparent) 0%, transparent 66%),
    radial-gradient(82% 50% at 50% 58%,  color-mix(in srgb, var(--amber) 22%, transparent) 0%, transparent 72%);
}
/* Im Auftakt trägt das Himmelsband die Farbe — das Lichtfeld bleibt dort
   nur noch ein leiser Zusammenhalt, sonst wäscht es das Bild aus.
   Im Schlussband, wo kein Bild liegt, darf es voll aufdrehen. */
.hero-light { opacity: 0.55; }
/* Der Saum: das Licht läuft nach unten ins Papier aus, statt an einer Kante
   zu enden. Deshalb braucht die Seite keine einzige Trennlinie. */
.hero-light { mask-image: linear-gradient(180deg, #000 0%, #000 46%, transparent 82%); }
.close-light { inset: auto -10% -20%; mask-image: linear-gradient(0deg, #000 0%, #000 46%, transparent 82%); }

/* Abschnittslicht: drei Stellen im Mittelteil bekommen einen sehr leisen
   farbigen Schein, damit die Seite zwischen Auftakt und Schluss nicht
   gleichmäßig flach wird. Absichtlich nur drei — jede weitere Lichtquelle
   nimmt den vorhandenen ihre Wirkung. */
.how::before,
.data::before,
.pricing::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}
.how::before     { background: radial-gradient(50% 40% at 88% 10%, color-mix(in srgb, var(--cyan) 17%, transparent), transparent 70%); }
.data::before    { background: radial-gradient(48% 42% at 6% 24%,  color-mix(in srgb, var(--blue) 15%, transparent), transparent 72%); }
.pricing::before { background: radial-gradient(56% 46% at 84% 76%, color-mix(in srgb, var(--amber) 20%, transparent), transparent 74%); }

/* ══════════════════════════════════════════════════════════════════════════
   AUFTAKT
   ══════════════════════════════════════════════════════════════════════════ */
.hero {
  padding-top: clamp(7.5rem, 15vh, 11rem);
  padding-bottom: clamp(3rem, 7vw, 6rem);
  overflow: clip;
}

/* Das Himmelsband aus v3 — und diesmal ganz zu sehen, nicht als Textur.
   Die Fläche bekommt das Seitenverhältnis des Bildes (2400 × 1561), also
   zeigt `cover` das komplette Motiv: Himmel, Sonne, Bergkette, nichts
   abgeschnitten. Auf einem 1440er Fenster ist das Band 937 px hoch.
   Nach unten läuft es aus, statt an einer Kante zu enden — sonst stünde
   mitten auf der Seite ein waagerechter Strich, und Trennlinien gibt es
   hier nicht. Der Saum beginnt erst bei 70 %, damit die Gipfel stehen
   bleiben und nur der Vordergrund ins Papier übergeht.
   `::before` malt vor .hero-light und liegt damit darunter; der Inhalt
   liegt mit z-index 1 über beidem. */
.hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  width: 100%;
  aspect-ratio: 2400 / 1561;
  max-height: 1120px;
  z-index: 0;
  pointer-events: none;
  background: url("../assets/img/hero-sky.webp") center top / cover no-repeat;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, #000 70%, rgba(0,0,0,.35) 88%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 0%, #000 70%, rgba(0,0,0,.35) 88%, transparent 100%);
}
.hero-in {
  position: relative;
  z-index: 1;
  text-align: center;
  display: grid;
  justify-items: center;
  gap: 1.35rem;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.4rem 0.9rem 0.4rem 0.72rem;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 0 0 1px var(--edge-strong), 0 6px 18px -12px rgba(13, 18, 32, 0.4);
}
.eyebrow i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 18%, transparent);
}

.hero h1 { max-width: 15ch; }
.hero .lede { max-width: 46ch; }
/* Auf dem warmen Teil des Himmels ist --ink-4 nicht mehr zu lesen. Die
   Zeile trägt echte Angaben (keine Karte, Credits verfallen nicht) — die
   darf nicht dekorativ verblassen. */
.hero .micro { color: #4E5A70; }

.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  justify-content: center;
  margin-top: 0.4rem;
}

/* ---------- Die Bühne ----------------------------------------------------- */
.hero-stage {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 1140px;
  margin: clamp(3rem, 6vw, 5rem) auto 0;
  padding-inline: var(--pad);
  perspective: 1600px;
}
/* Der Rückwurf: die Aufnahme ist dunkel und leuchtet, also wirft sie Licht
   auf das Papier — statt nur einen Schatten darauf. Das ist der Unterschied
   zwischen „Bild auf einer Seite" und „Gerät in einem Raum".
   Aus Verläufen gebaut, nicht aus `filter: blur()`: bei einer so weichen
   Quelle sieht man keinen Unterschied, aber der Weichzeichner kostet bei
   jedem Bildaufbau. Gilt für alle drei Fassungen der Seite. */
.hero-stage::before,
.veil-fig::before,
.reel-media::before {
  content: "";
  position: absolute;
  inset: 12% -5% -14%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(58% 42% at 50% 10%,  color-mix(in srgb, var(--blue) 32%, transparent), transparent 70%),
    radial-gradient(64% 36% at 46% 62%,  color-mix(in srgb, var(--cyan) 24%, transparent), transparent 72%),
    radial-gradient(72% 38% at 50% 100%, color-mix(in srgb, var(--blue) 20%, transparent), transparent 68%);
  /* Ohne diese Maske endet der Schein an der Kante seines eigenen Kastens —
     ein hartes Rechteck aus blauem Licht mitten auf dem Papier. Gesehen,
     nicht vermutet. */
  -webkit-mask-image: radial-gradient(72% 64% at 50% 48%, #000 26%, transparent 78%);
  mask-image: radial-gradient(72% 64% at 50% 48%, #000 26%, transparent 78%);
}
.veil-fig, .reel-media { position: relative; }

/* ---------- Die Überschrift setzt sich Wort für Wort ---------------------
   Jedes Wort steigt aus einer eigenen unsichtbaren Zeile auf. Der kursive
   Teil bleibt EIN Stück, damit sein Farbverlauf nicht zerfällt. Ohne JS
   oder bei reduzierter Bewegung steht die Zeile sofort da. */
.h1-split .w { display: inline-block; overflow: hidden; vertical-align: bottom; }
.h1-split .w > i {
  display: inline-block;
  font-style: inherit;
  animation: word-up 0.95s var(--spring) both;
}
/* Der Verlauf muss auf das INNERE Element: `overflow: hidden` auf der
   Wortmaske schneidet den mit `background-clip: text` beschnittenen
   Hintergrund des Elternteils weg — der kursive Teil wäre dann unsichtbar.
   (Genau das ist beim ersten Bauen passiert.) */
.h1-split em { background: none; }
.h1-split em .w {
  /* Platz für die Unterlänge des kursiven „f" — sonst schneidet die Maske sie ab */
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.h1-split em .w > i {
  background: var(--accent-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
@keyframes word-up {
  from { transform: translateY(104%); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* Die Platte: eine helle gefräste Fassung um eine dunkle Aufnahme. Der
   Bodenschatten ist blau, nicht grau — die Aufnahme leuchtet ja. */
.plate {
  position: relative;
  padding: var(--bez);
  border-radius: var(--r-xl);
  background: linear-gradient(165deg, #FFFFFF 0%, #F0F2F7 55%, #E8EBF3 100%);
  box-shadow: var(--lift-3);
  transform-style: preserve-3d;
  transition: transform 0.6s var(--spring);
}
.plate-glass {
  position: relative;
  border-radius: calc(var(--r-xl) - var(--bez));
  overflow: hidden;
  background: var(--screen);
  box-shadow: 0 0 0 1px rgba(13, 18, 32, 0.55) inset;
}
/* Die Haarlinie der App, auf die Fassung zitiert. */
.plate-glass::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1.5px;
  z-index: 5;
  pointer-events: none;
  background: var(--app-edge);
  opacity: 0.9;
}
/* Innenkante: die gefräste Blende um das Bild. Ein Umriss, keine Trennlinie. */
.plate-glass::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  border-radius: inherit;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.07),
    inset 0 -26px 44px -30px rgba(31, 89, 233, 0.4);
}
.plate-glass video,
.plate-glass img { width: 100%; height: auto; }

/* Glanzkante: ein einmaliger Lichtstreifen, wenn die Platte sich setzt. */
.plate::after {
  content: "";
  position: absolute;
  inset: var(--bez);
  border-radius: calc(var(--r-xl) - var(--bez));
  pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, 0.5) 48%, transparent 58%);
  opacity: 0;
}
.plate.is-settled::after { animation: sheen 1.5s var(--ease) 0.15s 1 both; }
@keyframes sheen {
  0%   { opacity: 0; transform: translateX(-42%); }
  22%  { opacity: 0.85; }
  100% { opacity: 0; transform: translateX(42%); }
}

/* Schwebende Bruchstücke der Oberfläche — in HTML gebaut, nicht als Bild:
   gestochen scharf und wörtlich das, was im Video darunter passiert. */
.chips {
  position: absolute;
  inset: 0;
  pointer-events: none;
}
/* Die Bruchstücke liegen über einer DUNKLEN Aufnahme. Deshalb sind sie
   nahezu deckend statt durchscheinend: ein Milchglas über Schwarz wird
   grau und unlesbar. Der Schatten ist schwarz statt blau — er fällt hier
   auf das Gerät, nicht auf das Papier. */
.chip {
  position: absolute;
  border-radius: var(--r-md);
  background: #fff;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 1) inset,
    0 0 0 1px rgba(13, 18, 32, 0.09),
    0 6px 14px -6px rgba(0, 0, 0, 0.3),
    0 30px 60px -24px rgba(0, 0, 0, 0.55);
  padding: 0.85rem 1rem;
  animation: bob 9s var(--smooth) infinite;
}
.chip-k {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.615rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 0.45rem;
}
/* Seiten wie im Produkt: die Antworten stehen in der App LINKS, das
   Transkript RECHTS (tour.mp4, „Answers" / „Transcript"). Vorher war es
   vertauscht, also erzählte die Seite etwas anderes als die Aufnahme
   darunter.
   Und diagonal statt beide in der Bildmitte: eins oben links, eins unten
   rechts. So rahmen sie das Gerät ein, statt seinen Inhalt zu verdecken. */
.chip-pill {
  left: 4%;
  bottom: -3%;
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  padding: 0.5rem 0.85rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 540;
  color: var(--ink);
  animation-delay: -7.1s;
}
/* Die Marke zeigt zwei Bildschirme, keinen Haken — sie behauptet nichts,
   sie zeigt den Sachverhalt. Deshalb Tinte statt Signalgrün. */
.chip-pill .ic { width: 1.35em; height: 1.35em; color: var(--blue); }

.pulse {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #E5484D;
  animation: pulse 2s var(--smooth) infinite;
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 72, 77, 0.45); }
  50%      { box-shadow: 0 0 0 5px rgba(229, 72, 77, 0); }
}

.caret {
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin-left: 2px;
  vertical-align: -0.14em;
  background: var(--blue);
  animation: blink 1.15s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

@keyframes bob {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50%      { transform: translateY(-9px) rotate(-0.35deg); }
}

@media (max-width: 1180px) { .chips { display: none; } }

/* ══════════════════════════════════════════════════════════════════════════
   BEWEIS
   ══════════════════════════════════════════════════════════════════════════ */
/* Drei Zahlen, die frei auf dem Papier stehen, sehen nach nichts aus. Sie
   stehen jetzt auf EINEM breiten Objekt mit eigenem Licht — getrennt nur
   durch Weißraum, wie überall auf dieser Seite. */
.figures {
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  text-align: center;
  max-width: 780px;
  margin-inline: auto;
  margin-bottom: clamp(3.5rem, 7vw, 6rem);
  padding: clamp(1.4rem, 2.4vw, 2rem) clamp(1rem, 2.4vw, 2rem);
  border-radius: var(--r-xl);
  background: linear-gradient(168deg, #FFFFFF 0%, #FBFCFE 58%, #F6F8FD 100%);
  box-shadow: var(--lift-2);
  overflow: hidden;
}
/* Licht hinter den Zahlen, damit das Band nicht als leere Fläche liest */
.figures::before {
  content: "";
  position: absolute;
  inset: -60% -10% auto;
  height: 190%;
  pointer-events: none;
  background:
    radial-gradient(34% 40% at 18% 62%, color-mix(in srgb, var(--cyan) 15%, transparent), transparent 70%),
    radial-gradient(34% 40% at 82% 60%, color-mix(in srgb, var(--blue) 13%, transparent), transparent 70%),
    radial-gradient(40% 38% at 50% 64%, color-mix(in srgb, var(--amber) 13%, transparent), transparent 72%);
}
.figures li {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 0.35rem;
  align-content: start;
}
.fig {
  font-size: clamp(2rem, 3.8vw, 2.9rem);
  font-weight: 600;
  letter-spacing: -0.05em;
  line-height: 0.95;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(158deg, var(--ink) 8%, var(--blue-deep) 62%, var(--blue) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.fig-l {
  font-family: var(--mono);
  font-size: 0.615rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.stars { display: flex; gap: 2px; margin-top: 0.15rem; color: var(--gold); }
.stars svg { width: 12px; height: 12px; fill: currentColor; stroke: none; }
.stars .star-part path { fill: url(#st49); }

.proof-k {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--ink-3);
  /* #proof hat kein `.sec-head` — die neue Zentrierung aller Abschnittskoepfe
     greift hier also nicht, und die Kennzeichnung stand als einzige links unter
     einem mittigen Zahlenband. */
  text-align: center;
  margin-bottom: 2.4rem;
}

/* Sechs Kästen, drei Spalten: zwei volle Reihen statt einer ausgefransten.
   Ein Umriss UM den ganzen Kasten ist erlaubt — das ist keine Trennlinie
   zwischen zwei Dingen, sondern die Kante eines Dings. */
.checks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: clamp(0.9rem, 1.8vw, 1.35rem);
}
.checks li {
  display: grid;
  gap: 0.35rem;
  align-content: start;
  padding: clamp(1.25rem, 2.2vw, 1.7rem);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--lift-1);
  transition: transform 0.5s var(--spring), box-shadow 0.4s var(--ease);
}
.checks li:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.checks .k {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}
/* Ein kleiner Haken vor jeder Angabe — die Überschrift darüber heißt
   „What you can check yourself", der Haken macht daraus eine Prüfliste. */
.checks .k::before {
  content: "";
  width: 15px;
  height: 15px;
  flex: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--blue) 12%, transparent)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232456E8' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 6.5'/%3E%3C/svg%3E") center / 9px 9px no-repeat;
}
.checks b { font-size: 1.02rem; font-weight: 560; letter-spacing: -0.018em; }
.checks span:last-child { font-size: 0.9rem; line-height: 1.5; color: var(--ink-3); }

/* ══════════════════════════════════════════════════════════════════════════
   DER SCHNITT — die eine Bewegung, die die Seite trägt.
   Zwei Aufnahmen desselben Takes liegen übereinander. Beim Scrollen wandert
   die Naht: links bleibt, was beim Interviewer ankommt, rechts erscheint
   dieselbe Sekunde auf dem eigenen Bildschirm.
   Ohne JS (und bei „Bewegung reduzieren") steht --wipe auf 50 % — dann ist
   es ein ruhiger Vorher/Nachher-Vergleich, vollständig und lesbar.
   ══════════════════════════════════════════════════════════════════════════ */
.veil { overflow: clip; }
/* Dasselbe für den Momente-Abschnitt: `.reel-media::before` ist derselbe
   Rückwurf und steht mit `inset: 12% -5% -14%` links und rechts 5 % über
   seinen Kasten hinaus — bei 460 px Spaltenbreite sind das 23 px je Seite.
   `.hero` und `.veil` klippen das seit jeher, `.moments` war als einziger
   Abschnitt mit Rückwurf ohne eigene Regel und schob die Seite bei schmalem
   Fenster um 3 px seitlich auf (bei 500 px gemessen, Ursache eingegrenzt,
   indem jeder Abschnitt einzeln stillgelegt wurde). */
.moments { overflow: clip; }
/* KEIN klebender Abschnitt mehr (war erst 270vh, dann 190vh).
   Beides fühlte sich falsch an: man scrollte, und die Seite blieb stehen —
   der Abschnitt kostete doppelt so viel Weg wie er groß war. Jetzt ist es
   eine ganz normale Abbildung im Fluss. Der Wisch läuft, während sie durchs
   Bild wandert, und danach gehört der Regler dem Leser (Skript 7).
   Die beiden Hüllen bleiben als Klassen bestehen, damit Skript und
   Beobachter ihre Anker behalten. */
.veil-stage { height: auto; }
.veil-sticky {
  position: static;
  height: auto;
  display: grid;
  place-items: center;
  padding-inline: var(--pad);
}
.veil-fig { width: 100%; max-width: 1080px; }

.veil .plate-flat { --wipe: 50%; }
.plate-flat .plate-glass { aspect-ratio: 1600 / 944; }
.plate-flat .plate-glass video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ══ REGISTRIERUNG DER BEIDEN AUFNAHMEN — nachgemessen, nicht geraten ══
   `hide-you` liegt exakt 17 px tiefer als `hide-them` (dx=0, dy=+17; zwei
   unverdeckte Fenster, Kreuzkorrelation 0.999). Ohne Korrektur springt an
   der Naht das Bücherregal und die Schulter.

   Die erste Fassung hob `you` an und skalierte um 1,8 % nach, um die unten
   frei werdenden 17 px zu füllen — das war FALSCH: `scale` wirkt auf beide
   Achsen. Alles abseits der Mitte wanderte dadurch waagerecht mit, am Rand
   um bis zu 9 px. Genau das war zu sehen, wenn man den Regler zog: der
   „Leave"-Knopf unten sprang.

   Richtig ist ohne jede Verzerrung: beide Videos werden 17 px höher gemacht
   als ihr Ausschnitt und `you` um genau diese 17 px angehoben. Gezeigt wird
   dann von `them` Zeile 0…926 und von `you` Zeile 17…943 — inhaltlich
   derselbe Ausschnitt, kein Streckfaktor, keine Seitwärtsbewegung.
     Ausschnitt  1600 × (944−17) = 1600 × 927
     Videohöhe   944/927 = 101,8339 %
     Versatz     17/927 = 1,8339 %                                        */
/* 19.08.2026: Registrierung entfaellt. Beide Aufnahmen stammen jetzt aus
   ihren ECHTEN Quellen und decken sich ohne Korrektur — `hide-you` ist der
   Bildschirmmitschnitt auf die Anrufflaeche beschnitten (2940x1752 ab y=64),
   `hide-them` dieselbe Sekunde direkt aus `call-clip-final-1440p.mp4`.
   Nachgemessen in panelfreien Bereichen: Abweichung 0,87-3,35 (vorher waren
   17 px Versatz auszugleichen). Der alte Kunstgriff mit 101,8339 % Hoehe und
   -1,8339 % Versatz ist damit ersatzlos weg. */
.veil .plate-glass { aspect-ratio: 2048 / 1220; }
.veil .plate-glass video {
  inset: auto;
  top: 0;
  left: 0;
  height: 100%;
}
/* Der Selektor muss mindestens so stark sein wie der darüber — sonst
   gewinnt dessen `top: 0` und die ganze Registrierung passiert schlicht
   nicht. Genau das war der Fall: der Namensschild sprang weiter, obwohl
   die Rechnung stimmte. */
/* 19.08.2026: Richtung gedreht. Vorher lief die Naht von rechts nach links
   (`apply(1 - fortschritt)`), „you" wurde also von rechts aufgedeckt. Jetzt
   laeuft sie von links nach rechts und „you" liegt LINKS — deshalb der Einzug
   von rechts statt von links. Die Schilder im HTML sind mitgetauscht. */
.veil .plate-glass video.veil-you {
  top: 0;
  clip-path: inset(0 calc(100% - var(--wipe)) 0 0);
}

/* Die Naht ist kein Strich zwischen zwei Dingen, sondern eine Lichtkante
   innerhalb EINES Bildes — sie trennt nicht, sie zeigt, wo geschnitten wird. */
.veil-seam {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--wipe);
  width: 3px;
  transform: translateX(-1.5px);
  background: linear-gradient(180deg,
    rgba(127, 224, 242, 0.45), #fff 22%, #fff 78%, rgba(127, 224, 242, 0.45));
  box-shadow:
    0 0 3px 0 rgba(255, 255, 255, 0.95),
    0 0 22px 4px rgba(127, 224, 242, 0.75),
    0 0 60px 14px rgba(47, 187, 221, 0.35);
  pointer-events: none;
}
/* Am Anfang und am Ende steht die Naht am Rand und wäre nur noch ein
   Strich — dann blendet das Skript sie aus (siehe Block 7). */

/* Der Griff sitzt in der Naht. Die Pfeile sind Inline-SVG-Polygone: der
   Rahmen-Dreieck-Trick scheitert an `box-sizing: border-box`, und
   CSS-Chevrons werden bei dieser Größe zu dünn. */
.veil-grip {
  position: absolute;
  top: 50%;
  left: 50%;
  translate: -50% -50%;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.96);
  box-shadow:
    0 0 0 1px rgba(13, 18, 32, 0.08),
    0 4px 10px -3px rgba(0, 0, 0, 0.45),
    0 0 30px 6px rgba(127, 224, 242, 0.5);
  transition: scale 0.35s var(--spring);
}
.veil-grip svg { width: 26px; height: 26px; fill: var(--ink); }
.veil-fig:hover .veil-grip { scale: 1.08; }

/* Echter Regler, unsichtbar darüber: trägt Tastaturbedienung und den
   Fokusring. Gezogen wird per Zeiger direkt auf dem Bild (Skript 7). */
.veil-range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  opacity: 0;
  cursor: ew-resize;
  z-index: 4;
  -webkit-appearance: none;
  appearance: none;
  background: none;
}
.veil-range:focus-visible { outline: none; }
.plate:has(.veil-range:focus-visible) { box-shadow: var(--lift-3), 0 0 0 3px var(--blue); }

.veil-tag {
  position: absolute;
  top: 1rem;
  font-family: var(--mono);
  font-size: 0.63rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  padding: 0.34rem 0.7rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  color: var(--ink);
  box-shadow: 0 2px 12px -4px rgba(13, 18, 32, 0.4);
  transition: opacity 0.4s var(--ease);
}
.veil-tag-l { left: 1.2rem; }
.veil-tag-r { right: 1.2rem; }

/* Karte: Umriss um das GANZE Ding — erlaubt. Keine Linie darin. */
.card {
  padding: clamp(1.5rem, 2.6vw, 2.1rem);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--lift-1);
  display: grid;
  gap: 0.7rem;
  align-content: start;
  transition: transform 0.5s var(--spring), box-shadow 0.4s var(--ease);
}
.card:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.card p { font-size: 0.94rem; line-height: 1.55; color: var(--ink-3); }
.card .k {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}

/* Drei kleine Kästen, durch Pfeile verkettet. Der Pfeil ist keine
   Trennlinie: eine Trennlinie steht QUER zur Leserichtung und trennt, der
   Pfeil zeigt IN die Leserichtung und verbindet.
   Gleiche Höhe für alle drei, damit die Reihe ruhig liegt; der Pfeil sitzt
   auf halber Höhe dazwischen. */
.steps {
  display: grid;
  grid-template-columns: 1fr auto 1fr auto 1fr;
  gap: clamp(0.8rem, 1.8vw, 1.5rem);
  align-items: stretch;
}
.step {
  display: grid;
  grid-template-rows: auto auto 1fr;
  gap: 0.4rem;
  padding: clamp(1.2rem, 2vw, 1.6rem);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--lift-1);
  transition: transform 0.5s var(--spring), box-shadow 0.4s var(--ease);
}
.step:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.step .ic-lg {
  display: block;
  width: 18px;
  height: 18px;
  padding: 9px;
  border-radius: 12px;
  margin: 0 0 0.5rem;
}
.step .k {
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue);
  background: none;
  -webkit-background-clip: border-box;
  background-clip: border-box;
}
.step h3 {
  font-size: clamp(1.06rem, 1.35vw, 1.22rem);
  font-weight: 580;
  letter-spacing: -0.02em;
  line-height: 1.25;
}
.step p {
  margin-top: 0.15rem;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--ink-3);
}
.flow-arrow {
  display: grid;
  place-items: center;
  align-self: center;
  color: var(--ink-4);
}
.flow-arrow .ic { width: 22px; height: 22px; stroke-width: 1.5; }

@media (max-width: 900px) {
  .steps { grid-template-columns: 1fr; gap: 0.7rem; }
  /* Gestapelt zeigt der Pfeil nach unten — der Ablauf bleibt lesbar. */
  .flow-arrow { justify-self: center; rotate: 90deg; }
}

/* ══════════════════════════════════════════════════════════════════════════
   VIER MOMENTE
   ══════════════════════════════════════════════════════════════════════════ */
.reel {
  display: grid;
  grid-template-columns: minmax(0, 1.42fr) minmax(300px, 0.85fr);
  gap: clamp(1.8rem, 4vw, 3.5rem);
  align-items: center;
}
.reel-media { position: relative; }
.reel .plate-glass { aspect-ratio: 1600 / 1044; }
.clip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transform: scale(1.015);
  transition: opacity 0.7s var(--ease), transform 0.9s var(--ease);
}
.clip.is-on { opacity: 1; transform: none; }

.reel-steps { display: grid; gap: 0.4rem; }
.rstep {
  position: relative;
  display: grid;
  gap: 0.25rem;
  width: 100%;
  text-align: left;
  padding: 1rem 1.15rem 1.25rem;
  border-radius: var(--r-md);
  transition: background-color 0.4s var(--ease);
}
.rstep:hover { background: rgba(255, 255, 255, 0.6); }
.rstep.is-on { background: var(--surface); box-shadow: var(--lift-1); }
.rstep .k {
  font-family: var(--mono);
  font-size: 0.61rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
  transition: color 0.35s var(--ease);
}
.rstep.is-on .k { color: var(--blue); }
.rstep .h {
  font-size: 1.02rem;
  font-weight: 560;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.rstep .p {
  font-size: 0.885rem;
  line-height: 1.5;
  color: var(--ink-3);
  max-height: 8rem;
  opacity: 1;
  overflow: hidden;
  transition: max-height 0.5s var(--ease), opacity 0.35s var(--ease), margin 0.5s var(--ease);
}
/* Eingeklappt wird ebenfalls nur mit JavaScript — sonst wären ohne Skript
   drei der vier Beschreibungen dauerhaft verborgen. */
.js .rstep .p { max-height: 0; opacity: 0; }
.rstep.is-on .p { max-height: 8rem; opacity: 1; margin-top: 0.2rem; }

/* Die Zeitleiste zeigt nur der aktive Schritt — sonst wäre es eine Reihe
   von Trennlinien. */
.bar {
  display: block;
  height: 2px;
  margin-top: 0.75rem;
  border-radius: 2px;
  background: rgba(13, 18, 32, 0.08);
  opacity: 0;
  transition: opacity 0.3s var(--ease);
}
.rstep.is-on .bar { opacity: 1; }
.bar i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--blue), var(--cyan));
}
.rstep.is-on .bar i { animation: run var(--reel-dur, 6s) linear both; }
@keyframes run { to { width: 100%; } }

@media (max-width: 900px) {
  .reel { grid-template-columns: 1fr; }
  .rstep .p { max-height: 8rem; opacity: 1; margin-top: 0.2rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   BENTO
   ══════════════════════════════════════════════════════════════════════════ */
.bento {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(0.9rem, 1.6vw, 1.35rem);
}
/* Flex-Spalte statt Raster: die gebaute Oberflächen-Miniatur wird mit
   `margin-top: auto` an den unteren Rand gedrückt. Sonst sitzt sie bei
   kurzem Text mitten in der Kachel und darunter klafft Leere. */
.tile {
  position: relative;
  grid-column: span 3;
  padding: clamp(1.5rem, 2.4vw, 2rem);
  border-radius: var(--r-lg);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  transition: box-shadow 0.4s var(--ease);
}
/* Chips rutschen nach unten; die dunklen Fenster WACHSEN stattdessen mit.
   Im Bento sind alle Kacheln einer Reihe gleich hoch — läge das Fenster nur
   unten an, klaffte in der kürzeren Kachel ein Loch in der Mitte. So füllt
   es den Rest und sieht aus, als sei es so gemeint. */
.tile > .flow { margin-top: auto; padding-top: 1.1rem; }
.tile > .ts,
.tile > .code {
  margin-top: 1rem;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 118px;
}
.tile > .ts { justify-content: flex-start; }
.tile > .code > pre { flex: 1; }
/* Zeigerlicht: ein weicher Schein folgt der Maus über der Kachel. */
.tile::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
  background: radial-gradient(340px circle at var(--gx, 50%) var(--gy, 0%),
    color-mix(in srgb, var(--blue) 10%, transparent), transparent 68%);
}
.tile:hover::before { opacity: 1; }
.tile:hover { box-shadow: var(--lift-card-hi); }
.tile .k {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}
.tile .t { font-size: 0.94rem; line-height: 1.55; color: var(--ink-3); }
.tile .ic-lg { margin-bottom: 0.35rem; }

.tile-hero { grid-column: span 6; }
/* ---------- Antwortmodi zum Anfassen -------------------------------------- */
.dials {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.1rem;
  margin-top: 0.9rem;
}
.dial { display: grid; gap: 0.5rem; align-content: start; }
.dial-t {
  font-size: 0.78rem;
  font-weight: 560;
  color: var(--ink);
  letter-spacing: -0.01em;
}
.seg {
  display: inline-flex;
  padding: 3px;
  border-radius: 999px;
  background: rgba(13, 18, 32, 0.05);
  width: fit-content;
  max-width: 100%;
  flex-wrap: wrap;
}
.seg button {
  padding: 0.42rem 0.85rem;
  border-radius: 999px;
  font-size: 0.83rem;
  font-weight: 500;
  color: var(--ink-3);
  transition: color 0.25s var(--ease), background-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.seg button.is-on {
  color: var(--ink);
  background: #fff;
  box-shadow: 0 1px 2px rgba(13, 18, 32, 0.1), 0 0 0 1px var(--edge);
}
/* Alle drei Beschreibungen stehen sichtbar untereinander, hervorgehoben ist
   die gewaehlte. Vorher wurde EIN Hinweistext ausgetauscht — dann sieht man
   den Unterschied zwischen den Modi erst, wenn man alle drei durchklickt, und
   genau darum ging es (Uejs: „man soll richtig den unterschied zwischen denen
   erkennen").
   Ruhende Zeilen stehen auf --ink-3 (4,83:1), NICHT auf --ink-4: das ist mit
   2,6:1 rein dekorativ und traegt keinen Text. Der Unterschied kommt deshalb
   aus dem getoenten Grund der aktiven Zeile, nicht aus blasserer Schrift. */
.dial-legend { display: grid; gap: 0.2rem; margin-top: 0.55rem; }
.dial-legend li {
  padding: 0.38rem 0.55rem;
  border-radius: var(--r-sm);
  font-size: 0.775rem;
  line-height: 1.45;
  color: var(--ink-3);
  background: transparent;
  transition: color 0.3s var(--ease), background-color 0.3s var(--ease);
}
.dial-legend li b {
  margin-right: 0.34rem;
  font-weight: 560;
  letter-spacing: -0.01em;
  color: var(--ink-2);
}
.dial-legend li.is-on {
  color: var(--ink-2);
  background: color-mix(in srgb, var(--cyan) 10%, transparent);
}
.dial-legend li.is-on b { color: var(--ink); }


/* Die Antwortvorschau ist eine PRODUKTFLÄCHE, kein Seitentext — also dunkel
   wie die App, mit deren Haarlinie an der Oberkante, deren Beschriftungen
   und deren blauen Aufzählungspunkten. Erlaubt nach der Hell-Regel: eine
   kleine dunkle Einlage zählt als Produktfenster. */
.answer {
  position: relative;
  margin-top: 1rem;
  padding: 1.25rem 1.4rem 1.35rem;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--screen);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.06),
    0 18px 40px -24px rgba(13, 18, 32, 0.55);
}
.answer::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1.5px;
  background: var(--app-edge);
  opacity: 0.85;
}
.answer-q {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.55rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: #C6D0E4;
  margin-bottom: 0.9rem;
}
.answer-q span,
.answer-l {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: #6E7C99;
  flex: none;
}
.answer-l { margin-bottom: 0.35rem; }
.answer-open {
  font-size: 0.95rem;
  line-height: 1.55;
  color: #EDF1F9;
  letter-spacing: -0.012em;
  margin-bottom: 0.7rem;
}
.answer-points { display: grid; gap: 0.5rem; }
.answer-points li {
  position: relative;
  padding-left: 1.05rem;
  font-size: 0.885rem;
  line-height: 1.55;
  color: #C9D3E6;
}
.answer-points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--app-accent);
}
/* Schlüsselwörter: nur Gewicht und volle Helligkeit, keine zweite Farbe —
   so macht es die App auch (AnswerContent.tsx: „weight only, plain white"). */
.answer b { color: #FFFFFF; font-weight: 600; }
@keyframes mode-in {
  from { opacity: 0; transform: translateY(5px); }
  to   { opacity: 1; transform: none; }
}

/* Der Hinweis unter der Vorschau. Er steht da, weil die Vorschau eine
   ERFUNDENE Frage beantwortet — im Gespraech schreibt das Werkzeug aus
   Lebenslauf, Notizen und der tatsaechlich gestellten Frage. Ohne den Satz
   liest sich der Kasten wie ein Versprechen ueber die Antwortqualitaet, das
   eine Startseite nicht halten kann. */
.answer-note {
  /* BLAU, nicht grau (Uejs: „schreib das in dieser blauen schrift, damit die
     leute das auch gut sehen und verstehen, dass es nur ein preview ist").
     Der Hinweis muss auffallen, sonst liest sich der dunkle Kasten darueber
     als Versprechen ueber die Antwortqualitaet — und das kann eine Startseite
     nicht halten: die Vorschau beantwortet eine ERFUNDENE Frage, im Gespraech
     entsteht die Antwort aus Lebenslauf, Notizen und der echten Frage.
     `--blue` auf dem hellsten Kartenende (#FFFFFF) hat 6,26:1, auf dem
     dunkelsten (#EDF1F9) 5,58:1 — beides ueber der Schwelle. Der getoente
     Grund macht ihn zur Notiz statt zu einem weiteren Absatz. */
  margin-top: 1.1rem;
  padding: 0.8rem 0.95rem;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--blue) 6%, transparent);
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--ink);
  text-wrap: pretty;
}
/* Die Anrede steht in eigener Zeile und ist groesser — sonst geht sie neben dem
   fetten Fliesstext unter, und genau sie soll man zuerst sehen.
   `1.24rem`: gross genug, um vor dem fetten Satz zuerst gelesen zu werden,
   aber unter der H3 der Kachel (1,32 rem) — die Notiz darf keine dritte
   Ueberschrift werden. War kurz 1,62 rem, das war zu laut. */
.note-lead {
  display: block;
  margin-bottom: 0.12rem;
  font-size: 1.24rem;
  line-height: 1.25;
}
/* Fett und schwarz (Uejs). Das Blau steckt in der Anrede darueber, der
   erklaerende Satz traegt das Gewicht. */
.answer-note b { font-weight: 600; color: var(--ink); }

.kw {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.85rem;
  font-size: 0.86rem;
  color: var(--ink-3);
  cursor: pointer;
}
.kw input { position: absolute; opacity: 0; pointer-events: none; }
.kw-box {
  width: 20px;
  height: 20px;
  flex: none;
  border-radius: 6px;
  display: grid;
  place-items: center;
  background: #fff;
  box-shadow: 0 0 0 1px var(--edge-strong);
  transition: background-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.kw-box .ic { width: 13px; height: 13px; stroke-width: 2.8; color: #fff; opacity: 0; transition: opacity 0.2s; }
.kw input:checked + .kw-box { background: var(--blue); box-shadow: 0 0 0 1px var(--blue); }
.kw input:checked + .kw-box .ic { opacity: 1; }
.kw input:focus-visible + .kw-box { outline: 2.5px solid var(--blue); outline-offset: 3px; }

/* ---------- Gebaute Oberflächen-Miniaturen -------------------------------- */
.flow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.7rem;
}
.doc, .flow-out b {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.36rem 0.68rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--ink-2);
  background: rgba(13, 18, 32, 0.04);
}

/* ── Blaetterfaecher (Grounding) ──────────────────────────────────────────
   Vier flache Pillen sagten "CV, Job posting, Notes" — jetzt SIND es Blaetter.
   Gefaechert ueber negative Raender und eine feste Drehung je Blatt (--i).
   Der Inhalt bleibt abstrakt: Balken, kein erfundener Lebenslauf. */
.fan {
  position: relative;
  margin-top: auto;
  padding-top: 1.1rem;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  padding-left: 6px;
}
.sheet {
  --rot: calc((var(--i) - 1.5) * 5.2deg);
  position: relative;
  /* Spaetere Blaetter liegen OBEN. Andersherum verdeckt jedes Blatt die
     Beschriftung des naechsten ("OB POSTING", "OTES") — die sitzt links,
     also muss links sichtbar bleiben. */
  z-index: var(--i);
  display: block;
  flex: none;
  width: 108px;
  height: 140px;
  margin-left: -26px;
  padding: 0.6rem 0.62rem;
  border-radius: 10px;
  background: var(--surface);
  transform: rotate(var(--rot));
  transform-origin: bottom center;
  box-shadow:
    0 0 0 1px var(--edge),
    0 2px 4px -2px rgba(22, 41, 94, 0.12),
    0 16px 30px -18px rgba(22, 41, 94, 0.34);
  transition: transform 0.45s var(--spring);
}
.sheet:first-child { margin-left: 0; }
.sheet .ic { width: 15px; height: 15px; color: var(--blue); stroke-width: 1.6; }
.sheet b {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--mono);
  font-size: 0.53rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* Die Textzeilen des Dokuments — abstrakt, damit nichts erfunden wird. */
.sheet s {
  display: grid;
  gap: 5px;
  margin-top: 0.5rem;
  text-decoration: none;
}
.sheet s i {
  display: block;
  width: var(--w);
  height: 4px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--ink) 9%, transparent);
}
/* Das ausgelassene Blatt. `opacity` ist auf dieser Seite dem Verstecken
   vorbehalten — hier heisst es genau das: bleibt draussen. */
.sheet-out { opacity: 0.4; }
.sheet-out .ic { color: var(--amber); }
/* Der Faecher oeffnet sich beim Ueberfahren der Kachel etwas weiter. */
.tile:hover .sheet { transform: rotate(calc(var(--rot) * 1.35)) translateY(-3px); }
.fan-out {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.9rem;
  flex-basis: 100%;
}
.fan-out .ic { width: 16px; height: 16px; color: var(--blue); }
.fan-out b {
  display: inline-flex;
  align-items: center;
  padding: 0.36rem 0.68rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 500;
  color: #fff;
  background: var(--blue);
}
/* Die Blaetter haben feste Breite — bei 350 px Spalte lief der Faecher 107 px
   ueber. Unter 560 px werden sie kleiner statt umzubrechen: umgebrochen waere
   es kein Faecher mehr, sondern eine Reihe. Nachgemessen, nicht geschaetzt. */
@media (max-width: 560px) {
  .sheet { width: 82px; height: 108px; margin-left: -19px; padding: 0.45rem 0.46rem; }
  .sheet .ic { width: 12px; height: 12px; }
  .sheet b { font-size: 0.46rem; letter-spacing: 0.08em; margin-top: 0.22rem; }
  .sheet s { gap: 4px; margin-top: 0.38rem; }
  .sheet s i { height: 3px; }
}
.doc .ic { width: 13px; height: 13px; color: var(--ink-3); }
.flow-out { display: inline-flex; align-items: center; gap: 0.4rem; }
.flow-out .ic { width: 16px; height: 16px; color: var(--blue); }
.flow-out b {
  color: #fff;
  background: linear-gradient(180deg, #3563EE, var(--blue));
  box-shadow: 0 6px 16px -8px rgba(36, 86, 232, 0.7);
}

.ts {
  position: relative;
  overflow: hidden;
  margin-top: 0.7rem;
  padding: 0.9rem 1rem;
  border-radius: var(--r-sm);
  background: var(--screen);
  box-shadow: var(--win-dark);
  color: #E8EDF7;
}
/* Dieselbe Haarlinie, die .plate-glass und .answer schon tragen — abgetastet
   aus tour-poster.jpg. Damit sind alle dunklen Flaechen dieselbe Sorte Objekt. */
.ts::before, .code::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1.5px;
  z-index: 2;
  background: var(--app-edge);
  opacity: 0.8;
}
/* ── Aufnahmezustand im Transkriptfenster ───────────────────────────────── */
.ts-clock {
  font-family: var(--mono);
  font-size: 2.15rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
  text-align: center;
  color: rgba(232, 237, 247, 0.72);
}
.ts-rec {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.42rem;
  margin-top: 0.4rem;
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #7FE0F2;
}
.ts-rec { opacity: 0.42; transition: opacity 0.5s var(--ease); }
.ts.is-live .ts-rec { opacity: 1; }
.ts-rec i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cyan);
}
.ts.is-live .ts-rec i { animation: ts-puls 1.8s var(--ease) infinite; }
@keyframes ts-puls { 0%, 100% { opacity: 1; } 50% { opacity: 0.28; } }
/* Die Pegellinie. Jeder Balken bekommt ueber --n eine eigene Verzoegerung,
   damit die Welle laeuft statt zu blinken. Bei "Bewegung reduzieren" setzt der
   globale Block die Dauer auf 0,001 ms — der Endzustand ist eine ruhige,
   gleichmaessige Linie, also bleibt es dann ein stilles Bild. */
.ts-wave {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 3px;
  height: 22px;
  margin-top: 0.85rem;
  /* Luft nach unten, sonst klebt die Transkriptzeile an der Pegellinie.
     Weissraum statt Trennlinie — Regel 2. */
  margin-bottom: 1.15rem;
}
/* Ruhezustand: eine flache Linie. Der Pegel schlaegt ERST aus, wenn der Kasten
   im Bild ist — vorher ist nichts zu hoeren, also darf auch nichts ausschlagen.
   Deshalb wird die Animation nicht pausiert, sondern gar nicht erst gesetzt:
   pausiert stuende sie auf dem 0-%-Bild (22 %) und saehe nicht nach Stille aus. */
.ts-wave i {
  width: 3px;
  height: 12%;
  border-radius: 2px;
  background: color-mix(in srgb, var(--cyan) 30%, transparent);
  transition: height 0.5s var(--ease), background-color 0.5s var(--ease);
}
.ts.is-live .ts-wave i {
  background: color-mix(in srgb, var(--cyan) 52%, transparent);
  animation: ts-pegel 1.5s var(--ease) infinite;
  animation-delay: calc(var(--n) * -0.11s);
}
@keyframes ts-pegel {
  0%, 100% { height: 22%; }
  50%      { height: 88%; }
}
.ts-m {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: #7E8CA8;
  margin-bottom: 0.35rem;
}
.ts-t { font-size: 0.84rem; line-height: 1.45; }
/* Ohne Skript steht der Satz vollständig da — `is-typed` setzt das Skript
   erst, nachdem es die Zeichen eingesetzt hat.
   `font-style: normal` ist Pflicht: die Zeichen stecken in <i>, und das ist
   von Haus aus kursiv. */
.ts-t .tc { font-style: normal; }
.ts-t.is-typed .tc { opacity: 0; }
.ts-t.is-typed .tc.on { opacity: 1; }
/* Der Schreibbalken: 2 px breit, aber durch den negativen rechten Rand
   rechnerisch null — sonst würde er den Zeilenumbruch verschieben, während
   er durch den Satz wandert. */
.ts-t .tc.cur::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin: 0 -3px 0 1px;
  vertical-align: -0.14em;
  background: var(--cyan-soft);
  animation: blink 1.15s steps(1) infinite;
}

.code {
  position: relative;
  margin-top: 0.7rem;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: var(--screen);
  box-shadow: var(--win-dark);
}
.code-bar {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 0.55rem 0.8rem;
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #6E7C99;
}
.code-bar span { width: 7px; height: 7px; border-radius: 50%; background: #2A3550; }
.code-bar b { margin-left: 0.4rem; font-weight: 400; color: #6E7C99; }
.code pre {
  margin: 0;
  padding: 0 0.9rem 0.9rem;
  font-family: var(--mono);
  font-size: 0.73rem;
  line-height: 1.65;
  color: #9EB6E8;
  overflow-x: auto;
  padding-bottom: 5.4rem;
}
/* Die Kette dauert 8 s: Kürzel blitzt (6–12 %), der Blick fährt durch
   (12–34 %), dann steht der Satz da (38–88 %) und geht wieder. */
.scan {
  position: absolute;
  left: 0;
  right: 0;
  height: 34%;
  top: -34%;
  pointer-events: none;
  background: linear-gradient(180deg, transparent, rgba(127, 224, 242, 0.22), transparent);
  animation: scan 8s var(--smooth) infinite;
}
@keyframes scan {
  0%, 12%   { top: -34%; }
  34%       { top: 100%; }
  100%      { top: 100%; }
}
.code-key {
  position: absolute;
  right: 0.7rem;
  top: 0.55rem;
  padding: 0.18rem 0.5rem;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.92);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.08em;
  opacity: 0;
  animation: code-key 8s var(--smooth) infinite;
}
@keyframes code-key {
  0%, 4%    { opacity: 0; transform: scale(0.9); }
  7%        { opacity: 1; transform: scale(1); }
  14%, 100% { opacity: 0; transform: scale(1); }
}
/* Der Satz redet ÜBER den Code — er löst ihn nicht. Genau das ist der
   Unterschied, den der Absatz behauptet. */
.code-say {
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 0.75rem;
  display: grid;
  gap: 0.45rem;
  padding: 0.6rem 0.7rem;
  border-radius: var(--r-xs);
  background: rgba(8, 11, 18, 0.94);
  box-shadow: inset 0 0 0 1px rgba(127, 224, 242, 0.22);
  color: #D5DEEE;
  font-size: 0.74rem;
  line-height: 1.45;
  opacity: 0;
  animation: code-say 8s var(--smooth) infinite;
}
.code-say em { font-size: 0.56rem; }
.code-say em::before { width: 5px; height: 5px; }
.code-say span { display: flex; gap: 0.5rem; }
.code-say i {
  width: 5px;
  height: 5px;
  margin-top: 0.5em;
  flex: none;
  border-radius: 50%;
  background: var(--app-accent);
}
@keyframes code-say {
  0%, 34%   { opacity: 0; transform: translateY(6px); }
  42%, 86%  { opacity: 1; transform: none; }
  94%, 100% { opacity: 0; transform: translateY(6px); }
}

/* ---------- Steuerung zum Zusehen ----------------------------------------
   Ein Takt von 9 s, drei Zustände. Alles hängt an EINER Zeitachse, damit
   Panel, Zeiger und die Beschriftung darunter garantiert synchron laufen:
     0–33 %   dimmen        Panel geht auf 34 % Deckkraft
     33–66 %  durchklicken  Zeiger fährt über das Panel, der Druckpunkt
                            erscheint auf dem Fenster DARUNTER
     66–100 % verstecken    Panel verschwindet ganz
   ------------------------------------------------------------------------ */
.ctrl { margin-top: auto; padding-top: 1.1rem; display: grid; gap: 0.7rem; }
/* Die frühere .ctrl-scene-Regel (aspect-ratio 16/7) stand hier und war TOT —
   die gültige Definition folgt weiter unten und überschrieb sie vollständig.
   Entfernt am 20.08.2026: wer hier editiert, editiert ins Leere. */


/* ── Das gebaute Beispiel ────────────────────────────────────────────────
   Ein kleines Anruffenster mit dem Supace-Panel darüber. Eine Zeitachse von
   9 s, drei Zustände, alles hängt an denselben Prozentwerten:
     0–30 %   dimmen        Panel geht auf 32 % Deckkraft, man liest hindurch
     30–65 %  durchklicken  Zeiger fährt über das Panel, der Druckpunkt
                            erscheint auf dem Fenster DARUNTER
     65–100 % verstecken    Kürzel blitzt, Panel weg, dann zurück
   Animiert werden nur opacity und transform. */
.ctrl-scene {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: var(--r-sm);
  overflow: hidden;
  background: linear-gradient(168deg, #10182B 0%, var(--screen) 68%);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07);
  /* Deckel bewusst bei 14 px: eine Vergroesserung auf 18 px bei voller
     Kachelbreite war am 20.08.2026 gebaut und von Uejs verworfen — ihm gefiel
     die kompaktere Fassung besser. Nicht erneut vorschlagen. */
  font-size: clamp(10px, 2.7cqw, 14px);
  container-type: inline-size;
}

/* Titelleiste des Anrufs */
.ctrl-bar {
  position: absolute;
  inset: 0 0 auto;
  height: 13%;
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding-inline: 4%;
  color: #8C9AB8;
  font-family: var(--mono);
  font-size: 0.62em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.ctrl-bar i { width: 0.5em; height: 0.5em; border-radius: 50%; background: #E5484D; flex: none; }
.ctrl-bar em { font-style: normal; }
.ctrl-bar b { margin-left: auto; font-weight: 400; color: #6E7C99; }

/* Zwei Teilnehmer — weiche Porträtverläufe statt grauer Kästen */
.ctrl-call { position: absolute; inset: 13% 4% 17%; display: flex; gap: 3%; }
/* 20.08.2026: echte Gesichter statt angedeuteter Koepfe. Die beiden Portraits
   sind aus `call-clip-final-1440p.mp4` geschnitten — eigenes Material, im
   Seitenverhaeltnis der Kachel (225/199 = 1,13). Der dunkle Verlauf darueber
   ist kein Effekt, sondern noetig: das Panel wird beim Dimmen auf 0,34
   durchsichtig und muss auch ueber einem hellen Gesicht lesbar bleiben. */
.ctrl-tile {
  position: relative;
  flex: 1;
  border-radius: 5px;
  overflow: hidden;
  background:
    linear-gradient(168deg, rgba(10, 14, 24, 0.34) 0%, rgba(10, 14, 24, 0.62) 100%),
    url("../assets/img/product/ctrl-face-a.webp") center / cover no-repeat;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}
.ctrl-tile:last-child {
  background:
    linear-gradient(168deg, rgba(10, 14, 24, 0.34) 0%, rgba(10, 14, 24, 0.62) 100%),
    url("../assets/img/product/ctrl-face-b.webp") center / cover no-repeat;
}
/* Die angedeuteten Koepfe sind seit den echten Portraits ueberfluessig.
   Die Regel bleibt stehen, weil check-v4.py zu jeder Klasse eine Regel
   verlangt — das <u> ist im HTML entfallen. */
.ctrl-tile u {
  display: none;
  position: absolute;
  left: 50%;
  top: 24%;
  width: 26%;
  aspect-ratio: 1;
  translate: -50%;
  border-radius: 50%;
  background: linear-gradient(170deg, rgba(255, 255, 255, 0.34), rgba(255, 255, 255, 0.12));
}
.ctrl-tile u::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 118%;
  width: 190%;
  height: 108%;
  translate: -50%;
  border-radius: 50% 50% 0 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.03));
}
.ctrl-tile s {
  position: absolute;
  left: 5%;
  bottom: 5%;
  padding: 0.18em 0.5em;
  border-radius: 3px;
  background: rgba(8, 11, 18, 0.72);
  color: #C6D0E4;
  font-size: 0.62em;
  text-decoration: none;
}

/* Werkzeugleiste unten */
.ctrl-dock {
  position: absolute;
  inset: auto 0 0;
  height: 17%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
}
.ctrl-dock i { width: 1.5em; height: 1.5em; border-radius: 5px; background: rgba(255, 255, 255, 0.08); }
.ctrl-dock b {
  padding: 0.3em 0.7em;
  border-radius: 5px;
  background: #C8443F;
  color: #fff;
  font-size: 0.66em;
  font-weight: 500;
}

/* Der Druckpunkt liegt UNTER dem Panel — das ist der Kern von
   „click-through": der Klick kommt beim Fenster darunter an. */
.ctrl-hit {
  position: absolute;
  left: 52%;
  top: 46%;
  width: 2.6em;
  height: 2.6em;
  margin: -1.3em 0 0 -1.3em;
  border-radius: 50%;
  border: 1.5px solid rgba(127, 224, 242, 0.9);
  opacity: 0;
  animation: ctrl-hit 12s var(--smooth) infinite;
}

/* Das Panel */
.ctrl-panel {
  position: absolute;
  left: 24%;
  right: 7%;
  top: 20%;
  display: grid;
  gap: 0.42em;
  padding: 0.85em 1em;
  border-radius: 7px;
  background: rgba(8, 11, 18, 0.92);
  animation: ctrl-panel 12s var(--smooth) infinite;
}
/* Der Schriftzug auf dem Panel: ohne ihn ist nicht zu erkennen, dass das
   schwebende Fenster das Produkt IST und nicht Teil des Anrufs. */
.ctrl-panel em, .code-say em {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-family: var(--mono);
  font-style: normal;
  font-size: 0.62em;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #7FE0F2;
}
.ctrl-panel em::before, .code-say em::before {
  content: "";
  width: 0.42em;
  height: 0.42em;
  border-radius: 50%;
  background: var(--cyan);
}
.ctrl-panel::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1.5px;
  border-radius: 7px 7px 0 0;
  background: var(--app-edge);
}
.ctrl-p-q {
  color: #B9C7E0;
  font-family: var(--mono);
  font-size: 0.62em;
  letter-spacing: 0.03em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.ctrl-p-b {
  position: relative;
  padding-left: 0.9em;
  color: #F2F6FF;
  font-size: 0.72em;
  line-height: 1.35;
  /* Nur ein Hauch Saum: die Schrift soll in beiden Zuständen gleich
     aussehen, nicht im gedimmten plötzlich umrandet. */
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
.ctrl-p-b::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 0.32em;
  height: 0.32em;
  border-radius: 50%;
  background: var(--app-accent);
}

.ctrl-cursor {
  position: absolute;
  width: 0.9em;
  height: 0.9em;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 1.5px rgba(8, 11, 18, 0.6), 0 2px 5px rgba(0, 0, 0, 0.6);
  opacity: 0;
  animation: ctrl-cursor 12s var(--smooth) infinite;
}

/* Das Kürzel blitzt genau in dem Bild auf, in dem das Panel verschwindet */
.ctrl-key {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  padding: 0.32em 0.75em;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.94);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.68em;
  letter-spacing: 0.08em;
  opacity: 0;
  animation: ctrl-key 12s var(--smooth) infinite;
}

/* Zwölf Sekunden, vier Phasen — so viele, wie der Absatz daneben behauptet:
     8–22 %   dimmen        Panel auf 32 %, man liest hindurch
     26–48 %  durchklicken  Zeiger über dem Panel, Druckpunkt DARUNTER
     52–70 %  verschieben   Pfeiltasten leuchten, das Panel rückt weg
     72–92 %  verstecken    „hide" blitzt, Panel weg
   Zurück springt es unsichtbar, damit man den Rücksprung nicht sieht. */
/* WICHTIG: gedimmt wird der HINTERGRUND, nicht das ganze Panel.
   Genau so macht es das Werkzeug — die Fläche wird durchsichtig, damit man
   den Anruf dahinter sieht, aber die Antwort bleibt lesbar. Würde man
   stattdessen `opacity` auf dem Panel fahren, verschwände der Text mit, und
   die Kachel würde etwas zeigen, was das Produkt nicht tut.
   `opacity` bleibt deshalb dem Verstecken vorbehalten. */
@keyframes ctrl-panel {
  0%, 8%    { opacity: 1; background-color: rgba(8, 11, 18, 0.92); translate: 0 0; }
  22%, 50%  { opacity: 1; background-color: rgba(8, 11, 18, 0.34); translate: 0 0; }
  60%, 70%  { opacity: 1; background-color: rgba(8, 11, 18, 0.34); translate: 7% -9%; }
  78%, 92%  { opacity: 0; background-color: rgba(8, 11, 18, 0.34); translate: 7% -9%; }
  93%       { opacity: 0; background-color: rgba(8, 11, 18, 0.92); translate: 0 0; }
  100%      { opacity: 1; background-color: rgba(8, 11, 18, 0.92); translate: 0 0; }
}
@keyframes ctrl-cursor {
  0%, 26%   { opacity: 0; left: 30%; top: 66%; }
  32%       { opacity: 1; }
  42%       { opacity: 1; left: 52%; top: 46%; }
  48%, 100% { opacity: 0; left: 52%; top: 46%; }
}
@keyframes ctrl-hit {
  0%, 40%   { opacity: 0; transform: scale(0.3); }
  44%       { opacity: 1; transform: scale(0.6); }
  52%, 100% { opacity: 0; transform: scale(1); }
}
@keyframes ctrl-key {
  0%, 70%   { opacity: 0; transform: scale(0.9); }
  74%       { opacity: 1; transform: scale(1); }
  80%, 100% { opacity: 0; transform: scale(1); }
}

.ctrl-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.ctrl-steps li { display: inline-flex; align-items: center; gap: 0.38rem; }
.ctrl-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(13, 18, 32, 0.16);
}
/* Die drei Fenster decken sich genau mit den Phasen des Panels:
   dimmen 10–34 %, durchklicken 34–64 %, verstecken 64–92 %.
   Drei eigene Keyframes statt eines mit negativen Verzoegerungen — mit
   einem gemeinsamen leuchtete im Standbild der falsche Punkt. */
.ctrl-steps li:nth-child(1) .ctrl-dot { animation: ctrl-d1 12s linear infinite; }
.ctrl-steps li:nth-child(2) .ctrl-dot { animation: ctrl-d2 12s linear infinite; }
.ctrl-steps li:nth-child(3) .ctrl-dot { animation: ctrl-d3 12s linear infinite; }
.ctrl-steps li:nth-child(4) .ctrl-dot { animation: ctrl-d4 12s linear infinite; }
@keyframes ctrl-d1 { 0%, 7%, 25%, 100% { background: rgba(13,18,32,.16); box-shadow: none; } 8%, 24% { background: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); } }
@keyframes ctrl-d2 { 0%, 25%, 51%, 100% { background: rgba(13,18,32,.16); box-shadow: none; } 26%, 50% { background: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); } }
@keyframes ctrl-d3 { 0%, 51%, 71%, 100% { background: rgba(13,18,32,.16); box-shadow: none; } 52%, 70% { background: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); } }
@keyframes ctrl-d4 { 0%, 71%, 93%, 100% { background: rgba(13,18,32,.16); box-shadow: none; } 72%, 92% { background: var(--blue); box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 16%, transparent); } }

@media (prefers-reduced-motion: reduce) {
  .ctrl-panel, .ctrl-cursor, .ctrl-hit, .ctrl-key, .ctrl-dot,
  .key-arrow, .key-hide { animation: none; }
  /* Steht still im gedimmten Zustand — dann zeigt das Bild genau das,
     wovon der Absatz daneben spricht. */
  .ctrl-panel { background-color: rgba(8, 11, 18, 0.34); }
  .ctrl-steps li:first-child .ctrl-dot { background: var(--blue); }
}

/* Teil der Vorführung, nicht Dekoration: die Pfeile leuchten genau dann,
   wenn das Panel rückt, „hide" genau dann, wenn es verschwindet. */
.keys { display: flex; align-items: center; gap: 0.35rem; margin-top: 0.85rem; flex-wrap: wrap; }
.key-arrow { animation: key-lit 12s linear infinite; }
.key-hide  { animation: key-lit 12s linear infinite; animation-delay: -6.4s; }
@keyframes key-lit {
  0%, 51%, 71%, 100% { color: var(--ink-2); background: linear-gradient(180deg, #fff, #F1F3F8); box-shadow: 0 1px 0 rgba(255,255,255,.9) inset, 0 0 0 1px var(--edge-strong), 0 2px 3px rgba(13,18,32,.07); }
  54%, 68% { color: #fff; background: linear-gradient(180deg, #3563EE, var(--blue)); box-shadow: 0 0 0 1px var(--blue), 0 6px 14px -6px rgba(36,86,232,.65); }
}
.key {
  min-width: 30px;
  height: 30px;
  padding-inline: 0.5rem;
  display: grid;
  place-items: center;
  border-radius: 8px;
  font-size: 0.78rem;
  font-weight: 500;
  color: var(--ink-2);
  background: linear-gradient(180deg, #fff, #F1F3F8);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 0 0 1px var(--edge-strong), 0 2px 3px rgba(13, 18, 32, 0.07);
}
.key-word { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.06em; }

.strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: clamp(0.7rem, 1.4vw, 1.1rem);
  margin-top: clamp(2rem, 4vw, 3rem);
}
/* Kaestchen statt freistehender Textpaare (19.08.2026, Uejs). Dieselbe
   Kartensprache wie die Kacheln darueber, nur kleiner und mit dem leichteren
   Schatten — die Reihe liest sich damit als Nachtrag zum Bento und nicht als
   loser Text unter ihm. `align-content: start` haelt den Text oben, damit die
   Kaestchen bei unterschiedlich langen Zeilen nicht auseinanderlaufen. */
.strip li {
  display: grid;
  align-content: start;
  gap: 0.18rem;
  padding: clamp(0.85rem, 1.5vw, 1.15rem);
  border-radius: var(--r-md);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
  font-size: 0.845rem;
  line-height: 1.45;
  color: var(--ink-3);
}
.strip b { font-size: 0.95rem; letter-spacing: -0.015em; color: var(--ink); }

@media (max-width: 980px) { .tile { grid-column: span 6; } }

/* ══════════════════════════════════════════════════════════════════════════
   KOMPATIBILITÄT
   ══════════════════════════════════════════════════════════════════════════ */
/* Umbenannt von .chip-k: der Name gehoerte schon dem Label der schwebenden
   Hero-Kaertchen, und die spaetere Regel hat dessen Schriftgroesse, Farbe
   und Abstand still ueberschrieben. */

/* Der Abschnitt ist eine mittige Spalte — dann muss der Kopf mit, sonst steht
   die Ueberschrift links und alles darunter zentriert. Gleiche Behandlung wie
   die FAQ, die aus demselben Grund mittig steht. */
/* Zwei KARTEN in einer Zeile: links der Ring, rechts die Namen.
   Vorher standen Kopf, Ring, Nachsatz und Namensband untereinander — 1252 px,
   und der drehende Ring hatte nichts neben sich. Uejs: „kann man nicht alles in
   einer reihe bekommen, den kreis vielleicht in so einer box und die weiteren
   apps nebenan in der box".
   Karten sind erlaubt: die Regel verbietet TRENNLINIEN zwischen Dingen, nicht
   Rahmen um ein ganzes Ding.
   `align-items: stretch` (Vorgabe) — die Namenkarte nimmt die Hoehe der
   Ringkarte an, sonst haetten die beiden verschieden hohe Boeden. */
.compat-duo {
  display: grid;
  grid-template-columns: clamp(280px, 34vw, 470px) minmax(0, 1fr);
  /* Die Zeilenhoehe kommt vom RING, nicht vom Inhalt. Ohne sie zieht die Spur
     die Zeile auf ihre eigene Laenge (gemessen: 889 statt 470 px) — eine
     Zeilenhoehe `auto` richtet sich nach dem Hoechsten, und die Spur waechst
     mit jedem Eintrag. Der Wert ist dieselbe Formel wie die Ringspalte: die
     Ringkarte ist quadratisch (Ring `aspect-ratio: 1` + Innenabstand). */
  grid-auto-rows: clamp(280px, 34vw, 470px);
  gap: clamp(1.1rem, 2.2vw, 1.8rem);
}
.duo {
  padding: clamp(1.3rem, 2.2vw, 1.9rem);
  border-radius: var(--r-lg);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
}
.duo-ring { display: grid; place-items: center; }
/* Der Ring fuellt die Karte. Sein `width: min(100%, 430px)` bezieht sich jetzt
   auf die Karte statt auf die Textspalte — die feste Spaltenbreite oben
   verhindert den Zirkelschluss, in den die erste Fassung gelaufen ist. */
.duo-ring .ringbox { margin: 0; width: 100%; }

/* Die Namenkarte: Kennzeichnung, laufende Spur, fester Fuss.
   Die Spur laeuft SENKRECHT — andere Achse als das Sprachband in #languages
   direkt darunter, deshalb liest es sich nicht als dieselbe Bewegung zweimal. */
.duo-list { display: grid; grid-template-rows: minmax(0, 1fr) auto; text-align: center; }
/* Mittig, nicht linksbuendig: die Karte ist breiter als die Namen lang sind
   (661 gegen ~150 px), links angeschlagen bliebe rechts eine leere Haelfte. */
.duo-track { justify-items: center; }
.duo-scroll {
  position: relative;
  overflow: hidden;
  min-height: 8rem;
  /* Oben und unten ausblenden statt abschneiden — eine harte Kante mitten in
     einer Zeile liest sich als Fehler, und Trennlinien gibt es hier nicht. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 13%, #000 87%, transparent 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 13%, #000 87%, transparent 100%);
}
.duo-track {
  display: grid;
  gap: 0.62rem;
  /* Die Spur steht zweimal im HTML; -50 % ist damit genau eine Runde. */
  animation: drift-y 30s linear infinite;
}
.duo-track li {
  font-family: var(--mono);
  font-size: clamp(0.9rem, 1.15vw, 1.02rem);
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--ink-3);
}
/* In der Mitte der Spur kippen die Eintraege von Marken zu Dingen ohne Marke.
   Das ist das Argument des Abschnitts, deshalb Seitenschrift, groesser und
   dunkler — man sieht die Liste aufgeben, bevor der Fuss sie beendet. */
.duo-track .duo-any {
  font-family: var(--font);
  font-size: clamp(1.06rem, 1.45vw, 1.24rem);
  letter-spacing: -0.01em;
  color: var(--ink-2);
}
/* Der Fuss beendet den Satz, den die Spur anfaengt. Traegt zusaetzlich
   `.display` und benutzt damit fuer das <em> die bestehende Regel
   `.display em` — das Rezept fuer Serif-Kursiv + Blauverlauf steht so
   weiterhin genau EINMAL im Stylesheet. */
.duo-end {
  margin-top: clamp(0.7rem, 1.4vw, 1.1rem);
  font-size: clamp(1.45rem, 2.5vw, 2rem);
  line-height: 1.15;
}
@keyframes drift-y { to { transform: translateY(-50%); } }

/* Unter 860 px reicht die Breite fuer zwei Karten nicht (Ring 280 + Namen 280
   + Fuge 18 + Innenabstaende 84 = 662, plus Wrap-Polster). Dort gestapelt. */
@media (max-width: 860px) {
  .compat-duo { grid-template-columns: minmax(0, 1fr); grid-auto-rows: auto; }
  .duo-ring .ringbox { width: min(100%, 430px); margin-inline: auto; }
  .duo-scroll { min-height: 12rem; }
}

/* Plattform-Ring, nach dem „Works on Any Platform“-Kreis von Final Round.
   Scheiben statt Namensblasen: eine Scheibe braucht ~58 px Bogen, „Microsoft
   Teams“ als Blase brauchte 117 px — deshalb passen hier zehn bequem. Und
   Kreise auf einem Kreis behalten ihre Abstaende beim Drehen, Blasen nicht.
   Alle Masse in cqw, sonst laeuft der Ring aus der Spalte, sobald sie schmaler
   wird als der Kasten (zwischen 900 und 1400 px Viewport ist sie das). */
.ringbox {
  container-type: inline-size;
  position: relative;
  width: min(100%, 430px);
  aspect-ratio: 1;
  margin: clamp(2.4rem, 5vw, 3.6rem) auto 0;
  /* `.ring` ist im Layout ein Quadrat und dreht sich. Seine ACHSENPARALLELE
     Huellbox waechst dabei auf das Wurzel-2-fache — gemessen 430 → bis 608 px.
     Ohne Klipp schob das die ganze Seite seitlich auf, sobald das Fenster
     schmal wurde (bei 500 px: 26 px Ueberlauf, flackernd im Takt der Drehung).
     Klippen ist gefahrlos: alles Sichtbare liegt auf einem KREIS, dessen
     Ausdehnung sich beim Drehen nicht aendert — die weiteste Scheibe endet
     176 px von der Mitte, also 39 px INNERHALB der halben Kastenbreite (215).
     Nur die leeren Ecken des Quadrats werden abgeschnitten.
     `clip` statt `hidden`: `hidden` macht daraus einen Scrollcontainer.
     Die 10 px Zugabe decken die Schlagschatten der Scheiben ab und bleiben
     unter dem Innenabstand des Wraps (>= 15,6 px), laufen also nirgends an. */
  overflow: clip;
  overflow-clip-margin: 10px;
}
.ring-orbit {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 68cqw;
  height: 68cqw;
  translate: -50% -50%;
  border-radius: 50%;
  border: 1.5px dashed color-mix(in srgb, var(--cyan) 30%, transparent);
}
.ring-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 20cqw;
  height: 20cqw;
  translate: -50% -50%;
  border-radius: 50%;
  background:
    linear-gradient(160deg, #FFFFFF, color-mix(in srgb, var(--cyan) 10%, #fff)) padding-box,
    var(--app-edge) border-box;
  border: 1.5px solid transparent;
  box-shadow: 0 16px 38px -22px rgba(36, 86, 232, 0.6);
  display: grid;
  place-items: center;
}
.ring-core img { width: 52%; height: auto; }
.ring {
  --ring-r: 34cqw;
  --step: 36deg;
  position: absolute;
  inset: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  animation: ring-turn 96s linear infinite;
}
.ring li {
  position: absolute;
  left: 50%;
  top: 50%;
  /* Erst zentrieren, dann auf den Kreis drehen, dann die feste Eigendrehung
     zuruecknehmen — sonst kippt jede Scheibe um ihren eigenen Winkel. */
  transform:
    translate(-50%, -50%)
    rotate(calc(var(--i) * var(--step)))
    translateY(calc(var(--ring-r) * -1))
    rotate(calc(var(--i) * var(--step) * -1));
}
/* Gegendrehung, damit das Zeichen aufrecht bleibt statt mitzurollen. */
.disc {
  display: grid;
  place-items: center;
  width: 14cqw;
  height: 14cqw;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--edge), 0 8px 20px -12px rgba(13, 18, 32, 0.55);
  animation: ring-turn 96s linear infinite reverse;
  color: var(--brand, var(--ink-3));
}
.disc .logo { width: 46%; height: auto; }
/* Mercor liegt als PNG vor, nicht als Sprite-Zeichen. Ohne eigene Regel
   rendert es in Naturgroesse und sprengt die Scheibe — genau das ist beim
   CSS-Neuschrieb einmal passiert. */
.disc img { width: 62%; height: auto; object-fit: contain; }
@keyframes ring-turn { to { rotate: 360deg; } }
/* Die Zeichen aus dem Sprite sind Flaechen, keine Striche — .ic setzt genau
   andersherum (fill:none, stroke:currentColor) und wuerde sie unsichtbar machen. */
.logo {
  display: block;
  flex: none;
  fill: currentColor;
  stroke: none;
}
.compat-say {
  margin: clamp(2rem, 4vw, 3rem) auto 0;
  max-width: 54ch;
  text-align: center;
  font-size: clamp(0.95rem, 1.3vw, 1.08rem);
  line-height: 1.65;
  color: var(--ink-3);
  text-wrap: pretty;
}
.compat-say b { color: var(--ink-2); font-weight: 560; }


/* Fuer Vorlesesoftware: das Band ist aria-hidden (Kette doppelt), die Namen
   bleiben als Liste lesbar. */
.vis-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ══════════════════════════════════════════════════════════════════════════
   SPRACHEN — zwei gegenläufige Reihen. Die Kette ist verdoppelt, damit die
   Schleife nahtlos ist; die Maske schneidet die Ränder weich ab.
   ══════════════════════════════════════════════════════════════════════════ */
.marquee {
  display: grid;
  gap: 0.7rem;
  mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12%, #000 88%, transparent);
}
.mrow { overflow: hidden; }
.mtrack {
  display: flex;
  gap: 0.6rem;
  width: max-content;
  animation: drift 68s linear infinite;
}
.mrow-back .mtrack { animation-direction: reverse; animation-duration: 82s; }
.mtrack span {
  padding: 0.6rem 1.15rem;
  border-radius: 999px;
  font-size: 0.92rem;
  color: var(--ink-2);
  white-space: nowrap;
  background: var(--surface);
  box-shadow: 0 0 0 1px var(--edge), 0 4px 12px -10px rgba(13, 18, 32, 0.5);
}
@keyframes drift { to { transform: translateX(-50%); } }

/* ══════════════════════════════════════════════════════════════════════════
   DATEN
   ══════════════════════════════════════════════════════════════════════════ */
.trio {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(272px, 1fr));
  gap: clamp(1.2rem, 2.5vw, 2rem);
}
.card-off {
  background: linear-gradient(160deg, #FFFFFF, color-mix(in srgb, var(--cyan) 7%, #fff));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--cyan) 26%, transparent), 0 20px 44px -26px rgba(47, 187, 221, 0.5);
}
.card-off .ic-lg { color: var(--cyan); }
.data-foot {
  /* Mittig wie `.compat-say` an derselben Stelle: eine linksbuendige Fussnote
     unter mittigem Inhalt las sich als vergessen. */
  margin: clamp(2rem, 4vw, 3rem) auto 0;
  text-align: center;
  max-width: 72ch;
  font-size: 0.93rem;
  line-height: 1.62;
  color: var(--ink-3);
}
.data-foot a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }

/* Sicherheitsband. Die Konkurrenz stellt hier eine Reihe Zertifikatsplaketten
   hin (SOC 2, CCPA, GDPR) und schreibt „In progress“ darunter — also hat sie
   keine. Supace hat auch keine, deshalb tragen die Siegel hier ausschliesslich
   Zusagen, die im Code oder in der Datenschutzerklaerung eingeloest werden.
   Hell gehalten: ein dunkler Abschnitt ist abgelehnt, das Schloss traegt die
   Ernsthaftigkeit stattdessen ueber Groesse. */
.safe {
  position: relative;
  overflow: hidden;
  margin-top: clamp(1.8rem, 3.6vw, 3rem);
  padding: clamp(2.4rem, 5.2vw, 4.2rem) clamp(1.4rem, 4vw, 3.4rem);
  border-radius: var(--r-lg);
  text-align: center;
  background:
    radial-gradient(76% 118% at 50% 0%, color-mix(in srgb, var(--cyan) 12%, transparent), transparent 70%),
    linear-gradient(178deg, #FFFFFF, color-mix(in srgb, var(--cyan) 5%, #fff));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--cyan) 22%, transparent),
              0 34px 76px -44px rgba(36, 86, 232, 0.42);
}
/* Kein negativer z-index: der hat beim Auftakt schon einmal eine eigene
   Compositor-Ebene unter den Papiergrund geschoben. Stattdessen steht der
   Inhalt per position/z-index davor. */
/* Gefuellte Silhouette, kein Umriss: als Linie schnitt das Schloss quer durch
   Ueberschrift und Siegel und machte den Block unruhig. Gefuellt liegt es
   darunter wie ein Wasserzeichen — so macht es die Vorlage auch. */
.safe-mark {
  position: absolute;
  left: 50%;
  top: 46%;
  translate: -50% -50%;
  width: min(88%, 660px);
  height: auto;
  fill: color-mix(in srgb, var(--cyan) 9%, transparent);
  stroke: none;
  mask-image: linear-gradient(#000 52%, transparent 97%);
  pointer-events: none;
}
/* Der Buegel ist ein offener Pfad — er traegt die Fuellfarbe als dicke Linie,
   damit Buegel und Koerper eine einzige Flaeche ergeben. */
.safe-mark path {
  fill: none;
  stroke: color-mix(in srgb, var(--cyan) 9%, transparent);
  stroke-width: 19;
  stroke-linecap: round;
}
.safe-in { position: relative; z-index: 1; }
h3.display { font-size: clamp(1.8rem, 4vw, 3.05rem); }
.safe-lede {
  margin: clamp(0.9rem, 1.8vw, 1.3rem) auto 0;
  max-width: 58ch;
  font-size: clamp(1rem, 1.28vw, 1.12rem);
  line-height: 1.58;
  color: var(--ink-2);
}
.seals {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
  gap: clamp(1.5rem, 3vw, 2.4rem);
  max-width: 960px;
  margin: clamp(2rem, 4vw, 3.2rem) auto 0;
  padding: 0;
  list-style: none;
}
.seals li {
  display: grid;
  justify-items: center;
  align-content: start;
  gap: 0.5rem;
}
.ic-seal {
  width: 1.65rem;
  height: 1.65rem;
  color: var(--cyan);
  stroke-width: 1.5;
}
.seals b {
  font-weight: 600;
  font-size: 0.98rem;
  letter-spacing: -0.015em;
  color: var(--ink);
}
.seals span {
  max-width: 26ch;
  font-size: 0.87rem;
  line-height: 1.5;
  color: var(--ink-3);
}

/* ══════════════════════════════════════════════════════════════════════════
   PREISE
   ══════════════════════════════════════════════════════════════════════════ */
.price-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: clamp(1rem, 2vw, 1.4rem);
}
.cell {
  display: grid;
  gap: 0.28rem;
  align-content: start;
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--lift-1);
}
.cell .k {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}
.cell .v {
  font-size: clamp(1.9rem, 3vw, 2.5rem);
  font-weight: 560;
  letter-spacing: -0.045em;
  line-height: 1.05;
  color: var(--ink);
}
.cell .v small { font-size: 0.42em; font-weight: 500; letter-spacing: -0.01em; color: var(--ink-3); }
.cell .v-word { font-size: clamp(1.25rem, 1.8vw, 1.5rem); letter-spacing: -0.03em; line-height: 1.2; }
.cell .n { font-size: 0.85rem; color: var(--ink-3); }
.price-foot {
  /* Gleiche Behandlung wie `.data-foot` und `.compat-say`; vorher als einziges
     dieser Familie ein fester 2rem-Abstand statt des gemeinsamen Masses. */
  margin: clamp(2rem, 4vw, 3rem) auto 0;
  max-width: 62ch;
  text-align: center;
  font-size: 1rem;
  color: var(--ink-2);
}
.pricing .btn { margin-top: 1.1rem; }

/* ══════════════════════════════════════════════════════════════════════════
   FRAGEN — keine Linien zwischen den Einträgen. Getrennt wird über Abstand
   und darüber, dass der offene Eintrag zu einer Karte wird.
   ══════════════════════════════════════════════════════════════════════════ */
/* Mittig: der Abschnitt steht als Block in der Seitenmitte. Die Fragen und
   Antworten selbst bleiben linksbündig — zentrierter Fließtext über mehrere
   Zeilen liest sich schlecht, und eine Antwort ist hier oft ein Absatz. */
/* Die FAQ ist die einzige Stelle, an der laengerer Fliesstext steht — deshalb
   eine eigene, schmalere Spalte als der uebrige Abschnittsinhalt. Antworten
   linksbuendig: mittiger Fliesstext ueber mehrere Zeilen zwingt das Auge, den
   Zeilenanfang jedes Mal neu zu suchen. Nur der KOPF steht mittig, wie ueberall. */
.faq { text-align: left; }
.faq .sec-head { text-align: center; }
.faq-list { display: grid; gap: 0.35rem; max-width: 900px; margin-inline: auto; }
.faq-item {
  border-radius: var(--r-md);
  padding: 0.35rem 1.2rem;
  transition: background-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.faq-item[open] { background: var(--surface); box-shadow: var(--lift-1); padding-bottom: 1.2rem; }
.faq-item summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-block: 1rem;
  font-size: 1.03rem;
  font-weight: 540;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-ic {
  position: relative;
  width: 15px;
  height: 15px;
  flex: none;
  margin-left: auto;
}
.faq-ic::before, .faq-ic::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto;
  height: 1.7px;
  border-radius: 2px;
  background: var(--ink-3);
  transform: translateY(-50%);
  transition: transform 0.35s var(--spring), opacity 0.25s;
}
.faq-ic::after { transform: translateY(-50%) rotate(90deg); }
.faq-item[open] .faq-ic::after { transform: translateY(-50%) rotate(0deg); opacity: 0; }
.faq-item p {
  font-size: 0.955rem;
  line-height: 1.65;
  color: var(--ink-3);
  max-width: 72ch;
}
.faq-item p + p { margin-top: 0.8rem; }
.faq-item a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }

/* ══════════════════════════════════════════════════════════════════════════
   WER DAHINTERSTECKT
   ══════════════════════════════════════════════════════════════════════════ */
/* Der Schluss-Absatz steht mittig: es ist eine kurze persönliche Aussage,
   kein Fließtext — die trägt zentriert. */
.maker-in {
  max-width: 780px;
  margin-inline: auto;
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 1.1rem;
  padding: clamp(2rem, 4vw, 3.2rem);
  border-radius: var(--r-xl);
  background: linear-gradient(150deg, #fff, color-mix(in srgb, var(--blue) 4%, #fff));
  box-shadow: var(--lift-2);
}
.maker-lede {
  font-size: clamp(1.02rem, 1.5vw, 1.22rem);
  line-height: 1.55;
  letter-spacing: -0.015em;
  color: var(--ink-2);
}
.maker-sign { display: grid; gap: 0.3rem; justify-items: center; }
.maker-sign a {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  font-size: 1.05rem;
  font-weight: 560;
  color: var(--blue);
}
.maker-sign a .ic { color: var(--blue); }
.maker-sign a:hover { text-decoration: underline; text-underline-offset: 4px; }
.maker-sign span { font-size: 0.9rem; color: var(--ink-3); }

/* ══════════════════════════════════════════════════════════════════════════
   SCHLUSS
   ══════════════════════════════════════════════════════════════════════════ */
.close {
  overflow: clip;
  text-align: center;
  padding-block: clamp(6rem, 13vw, 11rem) clamp(6rem, 13vw, 11rem);
}
.close .wrap { position: relative; z-index: 1; display: grid; justify-items: center; gap: 1.1rem; }
.close h2 { max-width: 18ch; }

/* Der Auftakt öffnet mit dem Himmelsband — der Schluss legt es unter den
   ganzen Block und schliesst damit die Klammer.

   DER TEXT SOLL IN DEN BERGEN UND IN DER SONNE STEHEN, nicht darueber im
   leeren Himmel (Uejs). Zwei Fassungen davor sind daran gescheitert:
   - `close-sky.webp` mit den OBEREN 68,5 % — der Ausschnitt ist fast nur
     Farbverlauf, der Text schwebte im Nichts.
   - das ganze Bild bei gewachsenem Abschnitt (`padding-bottom: 29vw`) — dann
     ist das Bild 65 % der Fensterbreite hoch, der Text sitzt zwangsläufig in
     seinem oberen Drittel, und der Abschnitt wurde 869 px hoch.
   Uejs: „du musst das bild jetzt nicht extra groesser ziehen, kannst es etwas
   schneiden". Der Abschnitt ist deshalb wieder kompakt, und der Ausschnitt
   liegt dort, wo etwas zu sehen ist.

   AUSSCHNITT: Bildzeilen 25 %..75 % (2558x832, 3,07:1, 55 KB).
   Enthaelt Gipfel, Gratlinie (58 %) und die ganze Sonne (58,7..66,9 %),
   aber keinen leeren Himmel darueber und nicht die dunkle Vordergrundmasse
   darunter.

   QUALITAET: geschnitten aus dem PNG-ORIGINAL (2558x1664, verlustfrei) in
   VOLLER Quellaufloesung, nicht aus dem schon komprimierten hero-sky.webp und
   ohne Verkleinern. Die erste Fassung war 1900x519 und wurde bei DPR 2 auf
   4531x1238 Geraetepixel hochgezogen — 2,38-fach, plus eine zweite
   Verlustkodierung obendrauf. Jetzt 1,49-fach aus verlustfreier Quelle.
   Weiter laesst es sich nicht treiben: mehr Aufloesung hat das Original nicht.

   WARUM GENAU BIS 72 % UND NICHT WEITER (WCAG gegen --ink #0D1220,
   gemessen ueber die tatsaechliche Textbreite):
     Bildzeile 56 %: Ueberschrift 13,75:1 · Zeile 7,98:1
     Bildzeile 65 %: Ueberschrift  5,78:1 · Zeile 7,11:1
     Bildzeile 68 %: Ueberschrift  5,04:1 · Zeile 3,98:1  <- Zeile faellt durch
     Bildzeile 71 %: Ueberschrift  4,16:1               <- beide durch
   Alles unter 68 % traegt keine dunkle Schrift mehr. Der Ausschnitt endet
   deshalb bei 72 % — die letzten Prozente liegen im unteren Innenabstand,
   wo kein Text steht.

   `cover` + Ausschnitt mit 3,07:1: solange der Abschnitt SCHMALER als 3,07:1
   ist (Fenster bis ~1900 px), skaliert `cover` ueber die HOEHE. Dann ist die
   Zuordnung Abschnittszeile -> Bildzeile bei jeder Fensterbreite dieselbe,
   und der Text landet ueberall an derselben Stelle im Bild. Genau das ging
   vorher schief: bei `100% auto` haengt die Bildhoehe an der Fensterbreite,
   und derselbe Text sass bei 1920 px 6 Prozentpunkte tiefer im Bild als bei
   1470 px — auf einem breiten Schirm mitten in den dunklen Bergen.
   Oberhalb von ~1900 px skaliert `cover` ueber die Breite; durchgerechnet
   bleibt die Zeile darunter auch dann im sicheren Band:
     1920 px -> Bildzeile 58,2..60,2 %   2560 px -> 59,3..60,4 %
     3440 px -> 63,4..64,3 %             5120 px -> 67,2..67,9 % (Grenze)
   Der Ausschnitt ist bewusst 3,07:1 und nicht flacher: flacher waere schaerfer
   (weniger Hochskalierung), kippte aber frueher in die Breitenskalierung und
   damit die Schrift in die dunklen Berge. */
.close::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url("../assets/img/close-sky.webp") center bottom / cover no-repeat;
  /* Oben ins Papier ausblenden, sonst steht quer ueber der Seite eine harte
     Kante — also eine Trennlinie, und die gibt es hier nicht. Die Ueberschrift
     beginnt bei ~32 % der Abschnittshoehe, die Blende ist bei 20 % durch. */
  -webkit-mask-image: linear-gradient(180deg, transparent 0%, #000 20%, #000 100%);
  mask-image: linear-gradient(180deg, transparent 0%, #000 20%, #000 100%);
}
/* Das Lichtfeld war voll aufgedreht, WEIL im Schluss kein Bild lag. Jetzt
   liegt eines darunter — bei voller Staerke wuerde es den Himmel auswaschen.
   Gleiche Begruendung und gleicher Wert wie im Auftakt. */
.close-light { opacity: 0.55; }

/* ══════════════════════════════════════════════════════════════════════════
   FUSS — der einzige dunkle Grund der Seite außer den Aufnahmen selbst.
   ══════════════════════════════════════════════════════════════════════════ */
.ftr {
  background: var(--dark);
  color: #A9B4CC;
  padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem;
  font-size: 0.9rem;
}
.ftr-grid {
  display: grid;
  grid-template-columns: 1.6fr repeat(3, 1fr);
  gap: clamp(1.8rem, 4vw, 3.5rem);
}
.brand-light { color: #fff; }
.ftr-claim { color: #EAEEF8; font-weight: 540; margin-top: 1rem; }
.ftr-brand p { max-width: 34ch; }
.ftr-mail {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1rem;
  color: var(--cyan-soft);
}
.ftr-mail:hover { text-decoration: underline; text-underline-offset: 3px; }
.ftr-col h3 { color: #fff; margin-bottom: 0.9rem; font-size: 0.78rem; letter-spacing: 0.09em; text-transform: uppercase; }
.ftr-col ul { display: grid; gap: 0.5rem; }
.ftr-col a:hover { color: #fff; }
.dl { display: grid; gap: 0.5rem; }
.dl a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.65rem 0.85rem;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.05);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.07);
  transition: background-color 0.3s var(--ease);
}
.dl a:hover { background: rgba(255, 255, 255, 0.09); }
.dl .ic { width: 19px; height: 19px; color: #fff; }
.dl span { display: grid; color: #fff; font-weight: 500; line-height: 1.25; }
.dl small { font-size: 0.72rem; font-weight: 400; color: #8794AF; }
.ftr-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem 1.5rem;
  justify-content: space-between;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  font-size: 0.79rem;
  color: #7B879F;
}

/* ══════════════════════════════════════════════════════════════════════════
   AUFTRITT — alles tritt einmal ein, dann nie wieder. Ohne JS und bei
   „Bewegung reduzieren" steht alles sofort richtig da.
   ══════════════════════════════════════════════════════════════════════════ */
/* NUR wenn JavaScript läuft, darf überhaupt etwas versteckt werden — die
   Klasse `js` setzt ein Einzeiler im <head>. Ohne ihn steht die Seite
   vollständig da. */
.js .rise { opacity: 0; transform: translateY(26px); }
.rise.is-in {
  opacity: 1;
  transform: none;
  transition: opacity 0.8s var(--ease) var(--d, 0s), transform 0.9s var(--spring) var(--d, 0s);
}

/* ══════════════════════════════════════════════════════════════════════════
   SCHMALE FENSTER
   ══════════════════════════════════════════════════════════════════════════ */
@media (max-width: 1040px) {
  .hdr-nav { display: none; }
  .burger { display: block; }
  .lnk { display: none; }
}
@media (max-width: 760px) {
  html { scroll-padding-top: 78px; }
  .figures { grid-template-columns: 1fr; gap: 2rem; }
  .ftr-grid { grid-template-columns: 1fr 1fr; }
  .hdr-act .btn { padding: 0.6rem 1rem; font-size: 0.88rem; }

  /* Auf dem Telefon ist die Aufnahme das Knappste, was es gibt: sie geht
     randlos über die ganze Breite, die Fassung fällt weg. */
  .veil-sticky { padding-inline: 0; }
  .veil-fig { max-width: none; }
  .veil .plate { padding: 0; border-radius: 0; background: none; box-shadow: none; }
  .veil .plate-glass { border-radius: 0; }
  .veil-tag { font-size: 0.56rem; top: 0.7rem; }
  .veil-tag-l { left: 0.7rem; }
  .veil-tag-r { right: 0.7rem; }
  .veil .cap { padding-inline: var(--pad); }
}
@media (max-width: 560px) {
  .ftr-grid { grid-template-columns: 1fr; }
  .btn-lg { width: 100%; }
  .hero-cta { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .rise { opacity: 1; transform: none; }
  .mtrack { animation: none; }
  .ring, .disc, .duo-track { animation: none; }
  .clip { opacity: 0; }
  .clip.is-on { opacity: 1; }
  /* Ohne Selbstlauf muss alles lesbar dastehen: die vier Beschreibungen
     sind offen, der Fortschrittsbalken ist bedeutungslos und verschwindet. */
  .rstep .p { max-height: 8rem; opacity: 1; margin-top: 0.2rem; }
  .bar { display: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   DOWNLOAD-SEITE — „Der erste Lauf"
   --------------------------------------------------------------------------
   Anhang an v4.css, ans ENDE der Datei, VOR den Block „prefers-reduced-motion".
   KEINE eigene Datei: v4.css ist das ganze Stylesheet, ein zweites daneben
   waere der erste Schritt zurueck zum alten Aufsatzbau.
   Nach dem Einfuegen `css/v4.css?v=74` in BEIDEN Seiten hochzaehlen.

   Jeder neue Klassenname wurde gegen v4.css geprueft (Skript ueber alle
   `.name`-Vorkommen, 0 Treffer):
     dlhero · getcard · getname · getmeta · getbtns · btn-os · is-soon · spec ·
     spec-k · spec-v · osnote · runway · rundown · stn · stn-say · stn-view ·
     stn-full · dmg-body · dmg-app · dmg-dir ·
     perms · perm · perm-h · perm-why · perm-tag · perm-opt ·
     gauge · gauge-k · gauge-n · gauge-bar · gauge-f
   Nachtrag 20.08.2026 (die Abbildungen, Block am Dateiende) — ebenfalls
   gegen v4.css und beide Porcelain-Seiten geprueft, 0 Treffer:
     pane · pane-bar · pane-dot · pane-name · dmg-hint · dmg-fly · dmg-hand ·
     askset · ask-name · is-run · is-turn · perm-lit1/2 (nur Keyframes)
   ENTFALLEN: dmg-go (der pendelnde Cyan-Pfeil, den es im echten Abbild
   nicht gibt), askghost und perm-lit3 (mit den Geisterfenstern bzw. der
   Accessibility-Karte), dlstage/dlpill (mit der Hero-Buehne), und am
   21.08.2026 der ganze term-*-Satz mit den Pruefbefehlen.
   Ohne eine Zeile neues CSS wiederverwendet: .hero .hero-light .hero-in
   .eyebrow .lede .micro .hero-cta .display .kicker .sec-head .sec-lede .btn
   .btn-fill .btn-ghost .btn-lg .how .data .card .code .code-bar .ic .ic-lg .k
   .safe .safe-mark .safe-in .safe-lede .seals .ic-seal .data-foot .faq
   .faq-list .faq-item .faq-ic .close .close-light .ftr* .dl .rise .is-here.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---------- Auftakt -------------------------------------------------------
   Das Himmelsband bleibt UNANGETASTET: `.hero::before` behaelt Seitenverhaeltnis,
   Ausschnitt und Blende der Startseite, damit Gipfel und Sonne genauso
   dastehen wie dort. Die einzige Gefahr dabei ist die harte Kante — das Band
   ist `min(100% * 1561/2400, 1120px)` hoch, und wenn der Abschnitt kuerzer
   ausfaellt als das Band, wird die Blende mittendrin abgeschnitten und steht
   als waagerechter Strich quer ueber der Seite. Genau das kostet auf dieser
   Seite Hoehe, weil hier kein Produktvideo im Auftakt haengt.
   Die Loesung ist eine Zeile Arithmetik statt eines neuen Ausschnitts:
     Bandhoehe  = min(Abschnittsbreite x 0,650417 ; 1120px)
     min-height = min(65,05vw ; 1120px)
   `vw` ist nie kleiner als die Abschnittsbreite (es zaehlt die Bildlaufleiste
   mit), der Abschnitt ist damit bei JEDER Fensterbreite mindestens so hoch
   wie das Band — die Blende laeuft immer vollstaendig aus.
   `align-content: center` haengt daran: auf sehr breiten Schirmen ist die
   Mindesthoehe groesser als der Inhalt, und der soll dann in der Mitte des
   Bandes stehen statt oben zu kleben. `.hero-light` ist absolut positioniert
   und damit kein Rasterelement — es bleibt unberuehrt. */
.dlhero {
  display: grid;
  align-content: center;
  min-height: min(65.05vw, 1120px);
}

/* ---------- Das Release-Kaertchen -----------------------------------------
   Auf einer Downloadseite IST der Download das Objekt — also bekommt er die
   staerkste Fassung der Seite (`--lift-3`, sonst nur der Hero-Platte
   vorbehalten) statt eines Produktbildes ueber der Falz.
   Der Kopf darueber steht mittig wie ueberall; der Karteninhalt linksbuendig,
   weil er aus einer Liste besteht. */
.getcard {
  width: min(100%, 720px);
  margin-top: 0.6rem;
  padding: clamp(1.4rem, 3vw, 2.2rem);
  border-radius: var(--r-xl);
  text-align: left;
  background: var(--card-cool);
  box-shadow: var(--lift-3);
}

.getname {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 0.85rem;
  row-gap: 0.15rem;
}
/* Das App-Zeichen liegt als 400x400 vor — bei 52 px also auch auf einem
   Schirm mit doppelter Pixeldichte noch aus der Quelle, nicht hochgerechnet. */
.getname img {
  grid-row: span 2;
  width: 52px;
  height: 52px;
  border-radius: 13px;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 0 0 1px var(--edge),
    0 10px 22px -14px rgba(22, 41, 94, 0.45);
}
.getname b {
  align-self: end;
  font-size: 1.12rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--ink);
}
.getmeta {
  align-self: start;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem 0.55rem;
  font-family: var(--mono);
  font-size: 0.665rem;
  letter-spacing: 0.05em;
  /* --ink-3 auf dem dunkelsten Kartenende (#EDF1F9) = 4,578:1, knapp ueber der
     Schwelle. NICHT dunkler ziehen wollen — dann stattdessen auf --ink-2
     heben. --ink-4 waere 2,6:1 und traegt keinen Text. */
  color: var(--ink-3);
}
/* Ein Mittelpunkt als Trenner, kein Strich. Das Datum ist im Ruhezustand
   `hidden` — der Punkt davor faellt mit ihm weg (display:none nimmt auch das
   Pseudo-Element mit), der Punkt vor dem Link bleibt. Deshalb tragen beide
   Folgeelemente ihren eigenen. */
.getmeta > span + span::before,
.getmeta > a::before { content: "· "; color: var(--ink-4); }
.getmeta a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }

.getbtns {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-top: clamp(1.2rem, 2.4vw, 1.6rem);
}
/* Zwei Zeilen im Knopf: Beschriftung und Dateiangabe gehoeren AN den Klick,
   nicht in einen Abschnitt weiter unten. */
.btn-os { flex: 1 1 240px; }
.btn-os span { display: grid; justify-items: start; min-width: 0; line-height: 1.2; }
.btn-os small {
  margin-top: 0.1rem;
  font-size: 0.735rem;
  font-weight: 400;
  letter-spacing: 0;
  /* `.btn` steht auf `white-space: nowrap`, und das vererbt sich hierher.
     Ohne diese Zeile ist die MINDESTBREITE des Knopfes die Breite seiner
     Unterzeile — bei 390 px waere das mehr als der Knopf und damit
     seitlicher Ueberlauf der ganzen Seite. */
  white-space: normal;
  /* Kein zweiter Farbwert: derselbe Knopf ist mal gefuellt (weisse Schrift),
     mal hell (Tinte). 88 % von currentColor traegt in beiden Faellen —
     Weiss/88 % auf --blue sind 4,83:1, --ink/88 % auf Weiss deutlich mehr.
     Die Hierarchie kommt aus der Groesse, nicht aus blasserer Farbe. */
  color: color-mix(in srgb, currentColor 88%, transparent);
}
.btn-os .ic { width: 20px; height: 20px; }

/* „Noch nicht da" ueber FARBE und GRUND, nicht ueber Deckkraft: `opacity` ist
   auf dieser Website ausschliesslich dem Verstecken vorbehalten, und die alte
   Regel `.dl-os.is-soon { opacity: .72 }` aus styles.css verstiess dagegen —
   sie machte ausgerechnet den Text schlechter lesbar, der gelesen werden soll.
   Bernstein statt Cyan: Bernstein ist auf dieser Seite die Farbe fuer „noch
   nicht" und steht nur hier und in der Betriebssystem-Notiz.
   Zwei Klassen (`.btn.is-soon`), damit der Zustand auch dann gewinnt, wenn das
   Skript `btn-fill` setzt — Spezifitaet schlaegt Reihenfolge. */
/* `:not(.btn-fill)` seit dem 21.08.2026: der Knopf des ERKANNTEN Geraets ist
   jetzt immer der gefuellte, auch wenn seine Datei noch fehlt (Uejs' Wunsch).
   Bernstein bleibt damit dem Fall vorbehalten, in dem der Windows-Knopf
   NICHT der eigene ist — dort ist „noch nicht da" die ganze Aussage. */
.btn.is-soon:not(.btn-fill),
.btn.is-soon:not(.btn-fill):hover {
  cursor: default;
  color: var(--ink-2);
  background: linear-gradient(180deg, #FFFDF9, color-mix(in srgb, var(--amber) 13%, #fff));
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 0 0 1px color-mix(in srgb, var(--amber) 45%, transparent),
    0 10px 24px -16px rgba(184, 147, 63, 0.55);
  transform: none;
}
/* Muss NACH `.btn-os small` stehen: gleiche Spezifitaet, die spaetere Regel
   gewinnt — sonst stuende auf dem hellen Bernsteinknopf weisse Schrift. */
.btn.is-soon:not(.btn-fill) .btn-os small,
.btn-os.is-soon:not(.btn-fill) small { color: var(--ink-3); }
/* Der gefuellte, aber noch leere Knopf: blau wie gewuenscht, nur ohne
   Klickerwartung. Cursor `default`, nicht `not-allowed` — es ist nichts
   verboten, es ist nur noch nicht da. */
.btn.is-soon.btn-fill { cursor: default; }
.btn.is-soon.btn-fill:active { transform: none; }
/* Der Untertitel folgt sonst ueber `currentColor` der Knopffarbe. Bei einem
   Knopf, der erst NACHTRAEGLICH gefuellt wird (die Betonung haengt am
   erkannten Geraet, das steht erst im Skript fest), blieb in Chrome der
   Wert des ersten Bildaufbaus stehen: dunkle Schrift auf blauem Grund.
   Im Bild gesehen, nicht vermutet — deshalb hier ausgeschrieben statt
   gemischt. Weiss/88 % auf --blue misst 4,83:1. */
.btn-os.btn-fill small { color: rgba(255, 255, 255, 0.88); }

/* Das Datenblatt: die vier Angaben, die vor einem Klick zaehlen. Keine der
   verglichenen Downloadseiten nennt Version UND Groesse UND Voraussetzung. */
.spec {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.9rem 1.6rem;
  margin-top: clamp(1.3rem, 2.6vw, 1.7rem);
}
.spec li { display: grid; gap: 0.18rem; align-content: start; }
.spec-k {
  font-family: var(--mono);
  font-size: 0.615rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.spec-v {
  font-size: 0.94rem;
  font-weight: 540;
  letter-spacing: -0.012em;
  color: var(--ink);
}

/* Die Windows-Wahrheit. Steht UNTER den Knoepfen und getoent statt umrandet —
   eine Auskunft, keine Warnung. Bernstein, nicht Rot: nichts ist kaputt. */
.osnote {
  margin-top: clamp(1.2rem, 2.4vw, 1.6rem);
  padding: 0.85rem 1rem;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--amber) 14%, transparent);
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-2);
  text-wrap: pretty;
}

/* ---------- Der Lauf ------------------------------------------------------
   Vier Stationen, durch Pfeile verkettet. `rotate` statt `transform`, weil es
   die Layoutbox nicht anfasst: der Kasten bleibt 22x22, es kann nichts
   seitlich ueberlaufen. */
.runway { display: grid; gap: clamp(0.6rem, 1.4vw, 1rem); }
.rundown {
  display: grid;
  place-items: center;
  justify-self: center;
  /* Traegt keinen Text, sondern zeigt eine Richtung — hier ist --ink-4 (2,6:1)
     zulaessig und richtig: der Pfeil soll verbinden, nicht mitreden. */
  color: var(--ink-4);
  rotate: 90deg;
}
.rundown .ic { width: 22px; height: 22px; stroke-width: 1.5; }

/* Getoenter Grund, beide Enden gefaerbt (#FFFFFF -> #F7F9FD -> #EDF1F9):
   auf Weiss-auf-Fastweiss kann definitionsgemaess nichts schweben. Dieselben
   Tokens wie `.tile` auf der Startseite. */
.stn {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(1.2rem, 3vw, 2.4rem);
  align-items: center;
  padding: clamp(1.35rem, 2.6vw, 2.2rem);
  border-radius: var(--r-lg);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
  transition: transform 0.5s var(--spring), box-shadow 0.4s var(--ease);
}
.stn:hover { transform: translateY(-3px); box-shadow: var(--lift-card-hi); }
.stn-say { display: grid; align-content: center; }
/* Ein ZEITPUNKT statt einer Ziffer — 01/02/03 ist verboten, und die Startseite
   markiert ihre vier Momente ebenso ueber die Zeit („The night before"). */
.stn .k {
  margin-bottom: 0.4rem;
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue);
}
.stn h3 { font-size: clamp(1.15rem, 1.6vw, 1.42rem); }
.stn p {
  margin-top: 0.55rem;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink-3);
}
.stn-view { min-width: 0; }
/* `.code` bringt aus dem Bento `margin-top: .7rem` mit — in einer mittig
   ausgerichteten Spalte waere das eine 11-px-Schieflage. */
.stn-view .code { margin-top: 0; }

/* Die Freigaben-Station steht einspaltig: ihr Inhalt IST der Abschnitt, und
   vier gleich gebaute Reihen hintereinander lesen sich als Raster, nicht als
   Bewegung. */
.stn-full { grid-template-columns: minmax(0, 1fr); }
.stn-full .stn-say { max-width: 64ch; }

/* ---------- Szene 1 ------------------------------------------------------
   Die Masse stehen jetzt am Abbildfenster-Block ganz unten in dieser Datei
   (Abschnitt „INSTALLATIONSSEITE — DIE ABBILDUNGEN"). Hier stand bis zum
   20.08.2026 eine freie Anordnung mit 56-px-Symbolen und einem Cyan-Pfeil in
   Dauerschleife (`dmg-go`) — beides ist entfallen: der Pfeil pendelte, ohne
   dass etwas ankam, und im echten Abbild gibt es ihn gar nicht. */

/* ---------- Szene 2 ------------------------------------------------------
   Hier standen bis zum 21.08.2026 die Regeln der Terminal-Fenster
   (`.code.term`, `.term-p/-ok/-copy`). Sie sind mit den Pruefbefehlen
   entfallen — Uejs: „zu viel Proof kann auch Misstrauen schaffen". An ihrer
   Stelle steht jetzt eine ruhige Angabe aus `.pane` + `.setup-body`, also
   ohne eigene Regeln. Wer den Befehl zurueckholt, findet ihn in git. */

/* ---------- Szene 3: die drei Freigaben -----------------------------------
   Keine Karten in der Karte: die drei Spalten sind ueber Weissraum gegliedert,
   nicht ueber Kaesten oder Linien. */
.perms {
  display: grid;
  /* Obergrenze 430 px, seit es nur noch ZWEI Freigaben sind (20.08.2026):
     mit `1fr` teilten sich die beiden die volle Kartenbreite und standen
     530 px breit da — fuer 0,9-rem-Text rund 85 Zeichen je Zeile, das liest
     sich nicht mehr. 430 px sind rund 68 Zeichen. Bei drei Karten aendert
     die Grenze nichts, dort war die Spalte ohnehin schmaler. */
  grid-template-columns: repeat(auto-fit, minmax(240px, 430px));
  gap: clamp(1.1rem, 2.4vw, 1.9rem);
  margin-top: clamp(1.3rem, 2.6vw, 2rem);
}
.perm { display: grid; align-content: start; gap: 0.45rem; }
/* Die beiden Karten stehen an den RAENDERN, nicht links zusammengedraengt
   (Uejs, 21.08.2026: „beweg mal so links und rechts, also richtig
   einruecken"). Zwei Dinge muessen dafuer zusammenkommen: die Spalten
   nehmen die volle Breite (`1fr`), der TEXT bleibt aber auf 430 px begrenzt
   — sonst waeren es rund 85 Zeichen je Zeile, das liest sich nicht. Und die
   letzte Karte rueckt in ihrer Spalte nach rechts.
   Erst ab 760 px: darunter steht ohnehin eine Karte je Zeile, und dort
   wuerde `justify-self: end` sie an den rechten Rand druecken. */
@media (min-width: 760px) {
  .perms { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
}
.perm .ic-lg { width: 18px; height: 18px; padding: 9px; border-radius: 12px; margin-bottom: 0.35rem; }
.perm-h { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; }
.perm-h b { font-size: 1.02rem; font-weight: 560; letter-spacing: -0.018em; }
.perm-why { font-size: 0.95rem; line-height: 1.6; color: var(--ink-3); }
/* „required" / „optional" gehoert AN die Ueberschrift, nicht in den Absatz —
   sonst muss man lesen, um zu wissen, ob man es freigeben muss.
   --blue traegt auf Weiss 6,26:1; die Farbe darf hier also den Text tragen. */
.perm-tag {
  padding: 0.16rem 0.5rem;
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue);
  background: color-mix(in srgb, var(--blue) 10%, transparent);
}
/* Warmer Ton fuer „optional" — kein Grau, wie ueberall auf dieser Seite.
   Nachgerechnet: #8A5A18 auf Bernstein 24 % ueber dem dunkelsten Kartenende
   (#EEE1D5) = 4,9:1, ueber Weiss 5,1:1 — beides ueber AA. */
.perm-opt {
  color: #8A5A18;
  background: color-mix(in srgb, var(--amber) 24%, transparent);
}

/* ---------- Szene 4: das Freiguthaben -------------------------------------
   Kein erfundener Antworttext und keine erfundene Frage — das waeren erfundene
   Produktausgaben in einer Produktdarstellung. Was hier steht, ist die eine
   Zahl, die belegt ist. Dunkel, weil es eine Produktflaeche ist, mit derselben
   Fassung und derselben App-Haarlinie wie jede andere Einlage der Seite. */
.gauge {
  position: relative;
  overflow: hidden;
  padding: clamp(1.3rem, 3.4vw, 1.9rem) clamp(1.2rem, 3vw, 1.7rem) clamp(1.4rem, 3.4vw, 1.9rem);
  border-radius: var(--r-sm);
  background: var(--screen);
  box-shadow: var(--win-dark);
}
.gauge::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 1.5px;
  background: var(--app-edge);
  opacity: 0.8;
}
/* ZWEI Klassen, nicht eine — im Bild gesehen (20.08.2026, zweiter Blick):
   `.gauge` steht INNERHALB einer `.stn`, und dort gilt
   `.stn p { font-size: .95rem; color: var(--ink-3); margin-top: .55rem }`
   mit der Spezifitaet (0,1,1). Jede einklassige `.gauge-*`-Regel (0,1,0) an
   einem <p> verlor dagegen lautlos: die 20 stand in 15,2 px --ink-3 statt in
   38 px Weiss, die Kennzeichnung war nicht cyan, und der Balken hatte 0,55
   statt 1 rem Abstand. In der halben Spalte fiel das nicht auf; unter dem
   Fenster in voller Breite sofort. Betrifft nur Regeln an einem <p>. */
.gauge .gauge-k {
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #7FE0F2;
}
.gauge .gauge-n {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  margin-top: 0.35rem;
  font-family: var(--mono);
  font-size: 2.4rem;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
  line-height: 1;
  color: #FFFFFF;
}
.gauge-n small {
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #8C9AB8;
}
/* Der Balken ist voll, weil das Guthaben unangetastet ist. Ein halb gefuellter
   Balken waere ein erfundener Kontostand. */
.gauge .gauge-bar {
  height: 6px;
  margin-top: 1rem;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(158, 182, 232, 0.16);
}
.gauge-bar i { display: block; width: 100%; height: 100%; background: var(--app-edge); }
.gauge .gauge-f {
  margin-top: 0.8rem;
  font-size: 0.8rem;
  line-height: 1.5;
  color: #8C9AB8;
}

/* ---------- Schmale Fenster ----------------------------------------------
   Unter 900 px steht jede Station einspaltig (dieselbe Schwelle, an der auch
   `.steps` und `.reel` umbrechen).
   Unter 560 px steht das Datenblatt einspaltig: zweispaltig blieben bei
   390 px Fensterbreite 141 px je Zelle, und „Apple Silicon & Intel — one file"
   braeche dort in drei Zeilen. Ein Datenblatt, das umbricht, liest sich wie
   ein Fehler. Einspaltig sind es 308 px.
   `.btn-lg { width: 100% }` steht schon in v4 — die Knoepfe brauchen hier nur
   noch die volle Zeile, damit sie nicht nebeneinander gequetscht werden. */
@media (max-width: 900px) {
  .stn { grid-template-columns: minmax(0, 1fr); gap: clamp(1.1rem, 3vw, 1.6rem); }
}
@media (max-width: 560px) {
  .spec { grid-template-columns: minmax(0, 1fr); }
  .btn-os { flex: 1 1 100%; }
  .gauge .gauge-n { font-size: 2rem; }
  /* Bei 390 px bricht die Kopfzeile des Kaertchens auf drei Zeilen, und die
     Mittelpunkte standen dann als Aufzaehlungszeichen am Zeilenanfang — das
     las sich als Liste, nicht als eine Zeile. Untereinander braucht es sie
     nicht: der Umbruch trennt schon. */
  .getmeta { display: grid; justify-items: start; gap: 0.1rem; }
  .getmeta > span + span::before,
  .getmeta > a::before { content: none; }
}

/* ── Installationsseite, Nachtrag 19.08.2026 ──────────────────────────────
   Uejs wollte die Abbildungen so, wie der Wettbewerb sie macht: Final Round
   baut in jedem Installationsschritt eine ATTRAPPE eines macOS-Fensters mit
   Platzhalterinhalt. Zwei Stationen hatten hier noch keine bzw. eine zu
   abstrakte Abbildung. */

/* Die Systemabfrage. NACHGEBAUT, nicht fotografiert: ein Foto von Apples
   Fenster waere fremdes Material und saehe bei jeder macOS-Fassung anders aus.
   Hell gehalten — eine Systemabfrage ist keine Produktflaeche, und Regel 1
   erlaubt Dunkel nur fuer die Aufnahmen selbst. */
.stn-view-ask { display: grid; place-items: center; }
.ask {
  width: min(300px, 100%);
  padding: 1.35rem 1.2rem 1.1rem;
  border-radius: var(--r-md);
  text-align: center;
  background: var(--surface);
  /* Die Blende ist ein Ring ohne Weichzeichnung: dieselbe Sprache wie die
     Fassung um die Produktaufnahmen, damit es als „Fenster" liest. */
  box-shadow: 0 0 0 1px rgba(22, 41, 94, .1), 0 26px 50px -28px rgba(22, 41, 94, .45);
}
.ask-ic { display: block; margin: 0 auto .7rem; width: 40px; height: 40px; }
.ask-ic img { width: 100%; height: auto; border-radius: 9px; }
.ask-t { font-size: .93rem; line-height: 1.4; color: var(--ink-2); }
.ask-t b { color: var(--ink); font-weight: 600; }
.ask-s {
  margin-top: .45rem;
  font-size: .75rem;
  line-height: 1.45;
  color: var(--ink-3);
}
.ask-btns { display: grid; grid-template-columns: 1fr 1fr; gap: .45rem; margin-top: .95rem; }
.ask-btns span {
  padding: .42rem .5rem;
  border-radius: 8px;
  font-size: .78rem;
  font-weight: 500;
}
.ask-no  { color: var(--ink-2); background: rgba(13, 18, 32, .055); }
.ask-yes { color: #fff; background: var(--blue); }

/* Die echte Aufnahme in der letzten Station. Dieselbe Fassung wie auf der
   Startseite (weisser Ring als Blende), damit sie als Produktflaeche liest und
   nicht als eingeklebtes Bild. Nur ein Standbild: ein zweites Video vor einem
   219-MB-Download waere schlechter Stil. */
.runshot {
  margin: 0 0 1rem;
  padding: 5px;
  border-radius: var(--r-lg);
  background: linear-gradient(165deg, #FFFFFF 0%, #F0F2F7 55%, #E8EBF3 100%);
  box-shadow: var(--lift-card);
}
.runshot img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--r-lg) - 5px);
}


/* ══════════════════════════════════════════════════════════════════════════
   INSTALLATIONSSEITE — DIE ABBILDUNGEN (20.08.2026)
   Anlass: Uejs wollte die Seite auf das Niveau von Final Rounds
   „Installation Overview" heben — „aber noch besser".
   Der Unterschied zu deren Fassung: die bauen drei ATTRAPPEN. Station 1 hier
   ist ein massstabsgetreues ZITAT des Abbilds, das der Leser dreissig
   Sekunden spaeter wirklich oeffnet — alle Masse aus electron-builder.yml
   des App-Repos, nicht entworfen. Details am jeweiligen Block.
   ══════════════════════════════════════════════════════════════════════════ */

/* Die eine helle Fensterfassung. Wiedererkennung entsteht aus GEOMETRIE —
   drei Punkte links, Titel mittig, Fläche darunter —, nicht aus Insignien.
   Die Punkte sind neutral-KÜHL und bewusst nicht Apples Rot/Gelb/Grün;
   `.code-bar span` liefert seit dem Livegang dieselbe Lösung dunkel aus.
   Der Farbsprung in `.pane-bar` ist eine Stufe, keine Trennlinie. */
.pane {
  max-width: 540px;
  margin-inline: auto;
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 0 0 1px rgba(22, 41, 94, .1), 0 26px 50px -28px rgba(22, 41, 94, .45);
}
.pane-bar {
  position: relative;
  display: flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 10px;
  background: linear-gradient(180deg, #FBFCFE, #EDF1F9);
}
.pane-dot { width: 9px; height: 9px; border-radius: 50%; background: #C9D3E4; }
.pane-name {
  position: absolute;
  left: 0; right: 0;
  font-family: var(--mono);
  font-size: .58rem;
  font-weight: 400;
  letter-spacing: .1em;
  text-align: center;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* NACHGEMESSEN, nicht entworfen. Quelle: electron-builder.yml (dmg.window
   540x380, contents x130/x410 y220, iconSize 80 aus dmg.js:217) und das
   mitgelieferte node_modules/dmg-builder/templates/background.tiff — dessen
   gestrichelter Blockpfeil hat die Hüllbox x243…292 / y193…253.
   ÄNDERT SICH dmg.window, contents ODER legt jemand resources/background.png
   an, ist dieses Bild eine Falschaussage. Dann hier nachziehen.
   Der Grund des echten Fensters ist #EDECEC — reines Grau und damit auf
   dieser Seite verboten; hier zum Blau gekühlt (#E7EBF2, B>G>R). */
.dmg-body {
  position: relative;
  container-type: inline-size;
  width: 100%;
  aspect-ratio: 540 / 380;
  background: #E7EBF2;
}
/* 130/540 = 24,074 % · 410/540 = 75,926 % · 220/380 = 57,895 %
   80/540 = 14,815cqw · 12/540 = 2,222cqw */
.dmg-app,
.dmg-dir {
  position: absolute;
  top: 57.895%;
  translate: -50% -50%;
  width: 14.815cqw;
  height: 14.815cqw;
  margin: 0;
}
.dmg-app { left: 24.074%; }
.dmg-dir { left: 75.926%; }
.dmg-app img {
  width: 100%; height: 100%;
  border-radius: 22.5%;
  box-shadow: 0 8px 18px -10px rgba(22, 41, 94, .55);
}
/* Ein gefülltes generisches Ordnersymbol aus unserem eigenen 24er-Raster.
   Apples blaues Applications-Zeichen 1:1 nachzuzeichnen — was Final Round
   tut — wäre das Markenzeichen; der Name daneben trägt die Information
   vollständig (§ 23 Nr. 3 MarkenG, EuGH Gillette C-228/03), dieselbe
   Argumentation wie beim „everywhere else"-Block der Startseite. */
.dmg-dir .ic {
  width: 100%; height: 100%;
  color: var(--blue);
  fill: color-mix(in srgb, var(--blue-soft) 20%, transparent);
  stroke-width: 1.1;
}
/* Systemschrift in gemischter Schreibung wie das echte Finder-Etikett.
   Mono-Versalien wären eine Website-Konvention IM Fenster gewesen. */
.dmg-body figcaption {
  position: absolute;
  top: 100%; left: 50%;
  translate: -50% 0;
  margin-top: 0.6cqw;
  white-space: nowrap;
  font-size: max(9px, 2.222cqw);
  line-height: 1.3;
  color: var(--ink-2);
}
/* Der gestrichelte Blockpfeil des Abbilds. #5E5D5D auf #EDECEC misst 5,51:1;
   #545D6E auf #E7EBF2 misst 5,34:1 — derselbe Kontrast, zum Blau gekühlt. */
.dmg-hint {
  position: absolute;
  left: 49.537%;            /* 267,5/540 */
  top: 58.684%;             /* 223/380   */
  translate: -50% -50%;
  width: 9.259cqw;          /* 50/540    */
  aspect-ratio: 50 / 61;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-dasharray: 4 2.6;
  stroke-linejoin: round;
  color: #545D6E;
}
/* Die mitwandernde Kopie. Ruhezustand ist `opacity: 0`, NICHT
   `animation-play-state: paused` — pausiert säße sie auf dem 0-%-Keyframe
   und läge als zweites Symbol über dem Original. Das ruhende Bild ist damit
   vollständig und wahr: Symbol links, gestrichelter Pfeil, Ordner rechts. */
.dmg-fly {
  position: absolute;
  top: 57.895%;
  left: 24.074%;
  translate: -50% -50%;
  width: 14.815cqw;
  height: 14.815cqw;
  opacity: 0;
  pointer-events: none;
}
.dmg-fly img {
  width: 100%; height: 100%;
  border-radius: 22.5%;
  box-shadow: 0 14px 26px -12px rgba(22, 41, 94, .7);
}
/* Der Griffpunkt, kein nachgezeichneter Apple-Zeiger: die Startseite hat für
   dieselbe Geste bereits diese Form (`.ctrl-cursor`, v4.css:2182). Der äußere
   Schatten ist gegen den hellen Grund von .6 auf .45 zurückgenommen. */
.dmg-hand {
  position: absolute;
  right: -6%; bottom: -6%;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 0 1.5px rgba(8, 11, 18, .6), 0 2px 5px rgba(0, 0, 0, .45);
}

/* Der Zug ins Programmverzeichnis. EINMAL, `forwards`, Endzustand = das
   ruhige vollständige Bild. Die Strecke läuft über prozentuale `left`-Werte
   am absolut positionierten Element — dieselbe Bezugsgröße wie die
   Symbolpositionen, also keine Laufzeitmessung und keine cqw in transform.
   Der Bogen läuft über `translate` in Prozent der EIGENEN Kantenlänge. */
/* Der Zeiger blieb unterwegs zweimal stehen — im Bild gesehen (Uejs,
   20.08.2026). Ursache: `animation-timing-function` gilt PRO
   Keyframe-Intervall, und `var(--ease)` bremst damit an JEDEM Zwischenpunkt
   auf null ab. Die Strecke laeuft jetzt `linear` durch; geeast wird nur beim
   Aufnehmen und beim Ablegen. Die vier Zwischenpunkte stehen waagerecht
   gleichmaessig (24,074 -> 37 -> 50 -> 63 -> 75,926 %) und tragen nur den
   Bogen, damit er rund bleibt statt zu knicken. */
@keyframes dmg-drag {
  0%        { left: 24.074%; translate: -50% -50%; scale: 1;    opacity: 0; animation-timing-function: ease-out; }
  8%        { left: 24.074%; translate: -50% -54%; scale: 1.06; opacity: 1; animation-timing-function: linear; }
  21%       { left: 37%;     translate: -50% -62%; scale: 1.06; opacity: 1; animation-timing-function: linear; }
  34%       { left: 50%;     translate: -50% -65%; scale: 1.06; opacity: 1; animation-timing-function: linear; }
  47%       { left: 63%;     translate: -50% -62%; scale: 1.06; opacity: 1; animation-timing-function: linear; }
  60%       { left: 75.926%; translate: -50% -54%; scale: 1.06; opacity: 1; animation-timing-function: ease-in; }
  72%       { left: 75.926%; translate: -50% -50%; scale: .55;  opacity: 1; }
  82%, 100% { left: 75.926%; translate: -50% -50%; scale: .38;  opacity: 0; }
}
/* Der Pfeil leuchtet, während etwas seinen Weg nimmt — Farbe, nicht Bewegung. */
@keyframes dmg-lit {
  0%, 8%    { color: #545D6E; }
  20%, 60%  { color: var(--blue); }
  85%, 100% { color: #545D6E; }
}
/* Der Ordner quittiert die Ankunft. Literale rgba statt color-mix, weil in
   Keyframes interpoliert wird: 110,151,255 IST --blue-soft (#6E97FF). */
@keyframes dmg-catch {
  0%, 66%   { fill: rgba(110, 151, 255, .20); }
  74%, 88%  { fill: rgba(110, 151, 255, .55); }
  100%      { fill: rgba(110, 151, 255, .20); }
}
.stn.is-run .dmg-fly     { animation: dmg-drag  2.9s var(--ease) 1 forwards; }
.stn.is-run .dmg-hint    { animation: dmg-lit   2.9s var(--ease) 1 forwards; }
.stn.is-run .dmg-dir .ic { animation: dmg-catch 2.9s var(--ease) 1 forwards; }

/* Der Text sagt „three permissions, ONE AT A TIME", die Abbildung zeigte
   eine. Zwei angeschnittene Fensteroberkanten dahinter lösen das in einem
   STEHENDEN Bild — und sie tragen keinen einzigen Buchstaben: es gibt also
   nichts zu erfinden, Apples Wortlaut bleibt unangetastet.
   Keine negativen Ränder: das Polster oben fängt beide Versätze ab. */
/* Die zwei angeschnittenen Fensteroberkanten dahinter sind am 20.08.2026
   entfallen (Uejs: „das bild dort soll nur einmal zeigen … im Hintergrund
   sind mehrere screens"). Sie sollten „one at a time" zeigen, lasen sich
   aber als Stapel mehrerer Bildschirme. Der Namenswechsel im einen Fenster
   sagt dasselbe, ohne das Bild zu verstellen. */
.askset {
  position: relative;
  width: min(300px, 100%);
  margin-inline: auto;
}
.askset .ask { position: relative; width: 100%; }

/* Der fette Name wechselt: Screen Recording → Microphone → Accessibility.
   Die Namen werden nicht ins Skript kopiert, sondern aus `.perm-h b`
   darunter GELESEN — keine dritte Fassung derselben Strings, und der
   Prüfer sieht das Wort weiter genau dort, wo die benannte Ausnahme greift.
   Kein min-height nötig: das <br> hält `.ask-t` immer zweizeilig, und alle
   drei Namen passen bei 300 px in eine Zeile (~120 px in 262 px). */
.ask-name { color: var(--ink); font-weight: 600; }
.ask-t { transition: opacity .26s var(--spring), transform .26s var(--spring); }
.ask.is-turn .ask-t {
  opacity: 0;
  transform: translateY(-5px);
  transition-duration: .17s;
  transition-timing-function: var(--ease);
}


/* ---------- Die Abbildung zeigt in den Text --------------------------------
   Die textlastigste Stelle der Seite bekommt eine Abbildung, die auf sie
   zeigt: waehrend der Dialog Name N fragt, leuchtet Scheibe N.
   Geleuchtet wird NUR auf der Symbolscheibe — die Kartenflaeche bleibt
   unangetastet, und `opacity` wird nirgends zum Dimmen benutzt.
   DREI eigene Keyframes statt eines mit animation-delay: der globale
   reduce-Block setzt animation-duration, aber NICHT animation-delay — mit
   Verzoegerungen blitzte die dritte Scheibe dort 4,4 s spaeter auf.
   Zeitachse 6,6 s, passend zum Namenswechsel im Skript (2,2 s / 4,4 s).
   Der 100-%-Keyframe IST der Ruhewert aus `.ic-lg` (v4.css:326) — der dritte,
   voellig durchsichtige Ring steht nur da, damit ueberhaupt interpoliert
   werden kann. --blue ist #2456E8 = rgb(36,86,232). */
@keyframes perm-lit1 {
  0%, 4%   { box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent), 0 0 0 0   rgba(36,86,232,0); }
  11%, 40% { box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent), 0 0 0 5px rgba(36,86,232,.14); }
  47%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent), 0 0 0 0   rgba(36,86,232,0); }
}
@keyframes perm-lit2 {
  0%, 51%   { box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent), 0 0 0 0   rgba(36,86,232,0); }
  58%, 90% { box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent), 0 0 0 5px rgba(36,86,232,.14); }
  97%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,.9), inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent), 0 0 0 0   rgba(36,86,232,0); }
}
/* Zwei Freigaben, also 4,4 s statt 6,6 — der Namenswechsel im Dialog liegt
   bei 2,2 s, und die zweite Scheibe geht kurz danach an (58 % von 4,4 s =
   2,55 s). `perm-lit3` ist mit der Mikrofon-Karte entfallen. */
.stn-full.is-run .perm:nth-child(1) .ic-lg { animation: perm-lit1 4.4s var(--ease) 1 forwards; }
.stn-full.is-run .perm:nth-child(2) .ic-lg { animation: perm-lit2 4.4s var(--ease) 1 forwards; }


/* ---------- Der Umschalter Mac / Windows ----------------------------------
   Zwei Betriebssysteme, zwei echte Ablaeufe. Keine Trennlinie: die Auswahl
   traegt einen gefuellten Grund, die andere Seite bleibt einfach Papier —
   Gliederung ueber Flaeche, nicht ueber einen Strich.
   `.osswap` steht mittig unter dem Abschnittskopf, in derselben Kartensprache
   wie alles andere auf dieser Seite. */
.osswap {
  display: flex;
  gap: .3rem;
  width: max-content;
  max-width: 100%;
  margin: 0 auto clamp(1.1rem, 2.4vw, 1.8rem);
  padding: .3rem;
  border-radius: 999px;
  background: var(--card-cool);
  box-shadow: var(--lift-card);
}
.osswap button {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.05rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: .92rem;
  font-weight: 500;
  color: var(--ink-3);
  cursor: pointer;
  transition: color .25s var(--ease), background .25s var(--ease);
}
.osswap button .ic { width: 16px; height: 16px; }
.osswap button:hover { color: var(--ink); }
/* Die Auswahl: gefuellt wie der Hauptknopf, damit sie als Zustand liest und
   nicht als zweiter Aufruf. Weiss auf --blue misst 8,6:1. */
.osswap .is-pick {
  background: var(--blue);
  color: #fff;
  box-shadow: 0 6px 14px -8px rgba(36, 86, 232, .8);
}
.osswap .is-pick:hover { color: #fff; }

/* Ohne JavaScript stehen beide Bloecke untereinander — vollstaendig und wahr.
   Erst `.js` versteckt den nicht gewaehlten (das `hidden`-Attribut am
   Windows-Block greift dann). Das ist dieselbe Absicherung wie bei `.rise`. */
.osblock { display: grid; gap: clamp(0.6rem, 1.4vw, 1rem); }
.js .osblock[hidden] { display: none; }
/* Die Zusage „ohne JavaScript stehen BEIDE Ablaeufe untereinander" war
   GEBROCHEN: [hidden] { display:none !important } (Zeile 161) versteckt den
   Windows-Block auch dann, wenn kein Skript laeuft. Nur ein !important
   schlaegt ein !important — eng auf den Nicht-JS-Fall gescoped, mit JS gilt
   weiter die Zeile darueber. (Befund aus dem verworfenen Neubau 20.08.,
   per sandbox-iframe ohne Skripte nachgewiesen.) */
html:not(.js) .osblock[hidden] { display: grid !important; }

/* ---------- Szene: der Windows-Installer ----------------------------------
   Dieselbe Fensterfassung `.pane` wie das Abbildfenster der Mac-Fassung, und
   BEWUSST dasselbe Seitenverhaeltnis 540/380: beim Umschalten darf die Zeile
   nicht in der Hoehe springen, sonst wandert der Text unter dem Zeiger weg.
   Der echte NSIS-Assistent ist hell — hier zum Blau gekuehlt wie ueberall. */
.setup-body {
  display: grid;
  align-content: center;
  gap: .5rem;
  aspect-ratio: 540 / 380;
  padding: clamp(1rem, 4cqw, 2rem);
  background: #E7EBF2;
}
.setup-k {
  font-family: var(--mono);
  font-size: .58rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
/* Der Zielpfad steht im Monospace-Satz: er IST ein Pfad, keine Prosa. */
.setup-path {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .6rem .75rem;
  border-radius: var(--r-sm);
  background: var(--surface);
  box-shadow: inset 0 0 0 1px rgba(22, 41, 94, .1);
}
.setup-path .ic { width: 18px; height: 18px; flex: none; color: var(--blue); }
.setup-path span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: .72rem;
  color: var(--ink-2);
}
.setup-note { font-size: .78rem; color: var(--ink-3); }
/* Der Knopf ist eine ABBILDUNG, kein Bedienelement — deshalb ein <span> im
   Absatz und kein <button>: nichts, was den Tabstopp einsammelt oder eine
   Klickerwartung weckt, die die Seite nicht einloesen kann. */
.setup-go { margin-top: .35rem; }
.setup-go span {
  display: inline-block;
  padding: .5rem 1.4rem;
  border-radius: var(--r-sm);
  background: var(--blue);
  font-size: .84rem;
  font-weight: 560;
  color: #fff;
  box-shadow: 0 8px 16px -10px rgba(36, 86, 232, .9);
}


/* ══════════════════════════════════════════════════════════════════════════
   DOWNLOAD-HERO IN DER SPRACHE DER STARTSEITE (20.08.2026)
   Uejs: „genau wie die homepage … komplett neue version … next level".
   Der Weg dahin ist WIEDERVERWENDUNG, nicht Neuerfindung: die Buehne unter
   dem Kaertchen benutzt woertlich .hero-stage/.plate/.plate-glass/.is-settled
   der Startseite — derselbe Rueckwurf, dieselbe Glanzkante, dieselbe Neigung
   zum Zeiger. Nur mit einem STANDBILD statt Video: vor einem 219-MB-Download
   kein zweites Video (Entscheidung STAND §5c). Neu sind hier nur die Masse
   der Buehne, der Pill darauf, das Zeigerlicht der Stationen, der Glanz auf
   dem Hauptknopf und der gleitende Daumen des Umschalters.
   ══════════════════════════════════════════════════════════════════════════ */

/* Die Buehne unter dem Kaertchen (`.dlstage` mit `hide-you.jpg` und dem
   Pill) ist am 20.08.2026 ENTFALLEN — Uejs: „die Abbildung darunter ist immer
   dieselbe wie auf der Homepage, entweder mal andere nehmen oder gleich weg
   machen, das hat eh keinen Nutzen". Auf einer Downloadseite IST der Download
   das Objekt; ein zweites Mal dasselbe Standbild trug nichts bei. Die
   Aufnahme steht jetzt weiter unten in Station 4 — dort in einer anderen
   Szene und auf einem Schreibtisch. Mit der Buehne sind auch die
   Plattenneigung und der `is-settled`-Glanz aus dem Skript gefallen. */

/* Das Release-Kaertchen traegt die App-Haarlinie an der Oberkante — dieselbe
   Kennung, die jede dunkle Produktflaeche zitiert: DIESES Objekt ist die App.
   ::after (ueber den Kindern) fuer die Linie, ::before (unter ihnen) fuer das
   Zeigerlicht. Augmentiert die bestehende .getcard-Regel, ersetzt sie nicht. */
.getcard { position: relative; overflow: hidden; }
.getcard::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 2px;
  pointer-events: none;
  background: var(--app-edge);
  opacity: 0.85;
}

/* Zeigerlicht auf Stationen und Kaertchen — dasselbe Rezept wie .tile::before
   auf der Startseite: nur eine Custom Property wird geschrieben, kein Layout. */
.stn { position: relative; overflow: hidden; }
.stn::before,
.getcard::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
  background: radial-gradient(440px circle at var(--gx, 50%) var(--gy, 0%),
    color-mix(in srgb, var(--blue) 9%, transparent), transparent 70%);
}
.stn:hover::before,
.getcard:hover::before { opacity: 1; }

/* Ein einmaliger Glanz ueber dem Hauptknopf, wenn die Seite steht — dieselbe
   Geste wie `sheen` auf der Platte, nur kleiner. EINMAL, dann Ruhe. */
.btn-os { position: relative; overflow: hidden; }
.btn-os::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  translate: -70% 0;
  background: linear-gradient(105deg, transparent 40%, rgba(255, 255, 255, 0.55) 50%, transparent 60%);
}
.btn-os.is-shine::after { animation: btn-shine 1.4s var(--ease) 1 both; }

/* Der Knopf des ERKANNTEN Geraets pulst — die Seite zeigt damit, dass sie
   hingeschaut hat. Ueber `outline`, NICHT ueber `box-shadow`: der Knopf
   traegt seinen eigenen mehrstufigen Schatten, den muesste jeder Keyframe
   sonst vollstaendig wiederholen (dieselbe Falle wie bei `perm-lit`).
   Und nicht ueber ein `::before`: `.btn-os` ist `overflow: hidden` fuer den
   Glanz, ein Ring darin waere abgeschnitten — `outline` liegt ausserhalb und
   wird davon nicht beruehrt.
   VIER Durchgaenge, dann Ruhe. Ein Dauerblinken waere auf dieser Seite ein
   Fremdkoerper und laut WCAG 2.2.2 ohnehin nur bis fuenf Sekunden zulaessig.
   Bei „Bewegung reduzieren" setzt der globale Block die Dauer auf 0,001 ms:
   der Ring blitzt einmal unsichtbar durch und endet im Ruhezustand. */
@keyframes btn-ping {
  0%        { outline-color: rgba(36, 86, 232, 0.75); outline-offset: 0;
              filter: brightness(1.14); }
  55%       { outline-color: rgba(36, 86, 232, 0.08); outline-offset: 11px;
              filter: brightness(1); }
  70%, 100% { outline-color: rgba(36, 86, 232, 0);    outline-offset: 13px;
              filter: brightness(1); }
}
.btn-os.is-detected {
  outline: 4px solid rgba(36, 86, 232, 0);
  animation: btn-ping 1.4s var(--ease) 4;
}
@keyframes btn-shine {
  0%   { opacity: 0;   translate: -70% 0; }
  18%  { opacity: 0.9; }
  100% { opacity: 0;   translate: 70% 0; }
}

/* Der Umschalter bekommt einen GLEITENDEN Daumen: ein Zustand, der von einer
   Seite zur anderen faehrt, liest sich als dieselbe Sache an neuer Stelle —
   zwei getrennt aufleuchtende Knoepfe lesen sich als zwei Dinge.
   Nur unter .js: ohne JavaScript schaltet der Umschalter nichts, dann traegt
   der gewaehlte Knopf seine Fuellung selbst (Basisregel .osswap .is-pick).
   --tx/--tw setzt das Skript aus der echten Knopfgeometrie — keine geratenen
   Haelften: die Woerter „macOS" und „Windows" sind verschieden breit. */
.js .osswap { position: relative; }
.js .osswap::before {
  content: "";
  position: absolute;
  top: 0.3rem;
  bottom: 0.3rem;
  left: 0;
  width: var(--tw, 0px);
  translate: var(--tx, 0px) 0;
  border-radius: 999px;
  background: var(--blue);
  box-shadow: 0 6px 14px -8px rgba(36, 86, 232, 0.8);
  transition: translate 0.5s var(--spring), width 0.5s var(--spring);
}
.js .osswap button { position: relative; z-index: 1; }
.js .osswap .is-pick { background: transparent; box-shadow: none; }




/* ══════════════════════════════════════════════════════════════════════════
   INSTALLATIONSSEITE — DER SCHREIBTISCH (20.08.2026)
   Uejs: „das bild also screenshot kann auch weg … du kannst ja auch das tool
   zeigen und als hintergrund mac os machen".
   Station 4 zeigte ein Standbild in einer halben Spalte. Jetzt läuft dort die
   echte Aufnahme, und zwar da, wo sie hingehört: auf einem Rechner. Der
   Schreibtisch ist Wandbild + Menüleiste + Fenster — mehr braucht das
   Wiedererkennen nicht, und mehr wäre Nachbau fremder Oberfläche.

   Zwei Dinge sind bewusst NICHT nachgebaut: Apples Apfel in der Leiste (das
   Zeichen ist geschützt; der eigene Name trägt die Information vollständig,
   dieselbe Argumentation wie beim „everywhere else"-Block der Startseite) und
   eine Systemuhr (das wäre eine erfundene Anzeige — dieselbe Linie wie beim
   Verzicht auf Apples Wortlaut in der Freigabe-Attrappe).

   Die Höhe ist NICHT gerechnet: `.desk` bekommt Polster und richtet sich nach
   dem Fenster darin. Eine feste `aspect-ratio` müsste bei jeder Änderung am
   Fenster nachgezogen werden und bricht sonst still — hier kann nichts
   auseinanderlaufen.
   ══════════════════════════════════════════════════════════════════════════ */
.deskfig { margin: 0; }

.desk {
  position: relative;
  container-type: inline-size;
  overflow: hidden;
  /* Polster oben trägt die Menüleiste plus Luft; unten/seitlich bleibt so
     viel Wandbild stehen, dass das Fenster als Objekt IM Raum liest. */
  /* Unten mehr als oben: dort steht das Dock, und darunter bleibt noch
     Wandbild stehen. Nachgerechnet bei 1090 px Schreibtisch — Dock 48 px
     hoch, 14 px ueber der Unterkante, Fensterunterkante 22 px darueber. */
  padding: clamp(2.4rem, 7cqw, 4.2rem) clamp(0.9rem, 6cqw, 3.4rem) clamp(3.4rem, 9cqw, 5.4rem);
  /* ECKIG seit dem 21.08.2026 (Uejs): mit `--r-lg` (26 px) schnitten die
     runden Ecken oben in die Menueleiste, und die endete dann sichtbar vor
     dem Rand statt ihn auszufuellen — genau wie es ein Bildschirm eben nicht
     tut. Ein Schreibtisch ist rechteckig; die Kartensprache der Seite gilt
     fuer die Karte DRUMHERUM, nicht fuer das Bild darin. */
  border-radius: 0;
  /* Unser eigenes Bild aus dem Auftakt — kein fremdes Wallpaper. Der
     Ausschnitt bei 42 % zeigt Gipfel und Licht, nicht den leeren Himmel. */
  background: url("../assets/img/hero-sky.webp") center 42% / cover no-repeat;
  box-shadow: var(--lift-2);
}

/* Die Menüleiste. Helles Glas mit Tinte darauf — auf dem hellen Wandbild ist
   das der einzige sichere Kontrast; heller Text auf Glas wäre je nach
   Bildzeile mal lesbar und mal nicht. Ohne Linie darunter: der Blur trennt
   schon, und Trennlinien gibt es hier nicht. */
.desk-bar {
  position: absolute;
  inset: 0 0 auto;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.55em;
  height: clamp(22px, 3.2cqw, 30px);
  padding-inline: clamp(0.55rem, 2cqw, 1.1rem);
  background: rgba(255, 255, 255, 0.62);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
}
.desk-bar img {
  width: clamp(13px, 1.9cqw, 17px);
  height: auto;
  border-radius: 4px;
}
.desk-bar b {
  font-size: clamp(9px, 1.25cqw, 12px);
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
/* Rechts in der Leiste stehen zwei Statuszeichen — wie im Vorbild, das dort
   WLAN und das Kontrollzentrum zeigt. Beides Gattungszeichen aus unserem
   eigenen Raster. KEINE Uhr: eine Uhrzeit waere eine erfundene Anzeige,
   dieselbe Linie wie beim Verzicht auf Apples Wortlaut in der Freigabe-
   Attrappe. */
.desk-sys { margin-left: auto; display: flex; align-items: center; gap: 0.75em; }
.desk-sys .ic {
  width: clamp(11px, 1.5cqw, 15px);
  height: clamp(11px, 1.5cqw, 15px);
  color: rgba(13, 18, 32, 0.62);
  stroke-width: 1.8;
}

/* Das Fenster ist die `.pane`-Fassung dieser Seite (helle Titelzeile, drei
   Punkte) — dieselbe, die Station 1 und die Windows-Stationen tragen. Bis zum
   20.08.2026 war es eine randlose `.plate` und las sich als eingeklebtes Bild
   statt als Fenster; Uejs wollte „die Mac-Oberfläche etwas besser zeigen".
   `.pane` bringt `max-width: 540px` mit — das muss hier weg, sonst steht ein
   540er Fenster in einem 1090er Schreibtisch.
   Der Schatten faellt auf ein Wandbild, nicht auf Papier: dunkel und tief,
   kein blaues Leuchten (das wirkt nur auf hellem Grund). */
.desk-win {
  max-width: none;
  /* 920 statt 820 px. Der Grund von damals (ein enger geschnittener Clip)
     ist entfallen, die 100 px bleiben trotzdem: sie kosten nichts, lassen
     85 px Wandbild je Seite stehen und heben den Massstab der Aufnahme von
     40 auf 45 %. Das macht sie nicht lesbar — dafuer braucht es eine neue
     Aufnahme —, aber ein bisschen ruhiger. */
  width: min(100%, 920px);
  margin-inline: auto;
  box-shadow:
    0 2px 6px rgba(8, 11, 18, 0.2),
    0 26px 50px -26px rgba(8, 11, 18, 0.55),
    0 60px 110px -60px rgba(8, 11, 18, 0.6);
}
.desk-win video { display: block; width: 100%; height: auto; }

/* Das Dock. Eine Glasleiste mit dem eigenen Zeichen und vier angedeuteten
   Kacheln — keine fremden App-Symbole (das waeren fremde Marken), und leere
   Kacheln behaupten nichts. Sie sind zum Blau gekuehlt bzw. zum Bernstein
   gewaermt, wie jeder Neutralton auf dieser Seite. */
.desk-dock {
  position: absolute;
  left: 50%;
  bottom: clamp(6px, 1.3cqw, 14px);
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: clamp(4px, 0.85cqw, 9px);
  padding: clamp(4px, 0.8cqw, 8px);
  border-radius: clamp(9px, 1.7cqw, 17px);
  background: rgba(255, 255, 255, 0.44);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  backdrop-filter: blur(16px) saturate(150%);
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.5),
    0 8px 20px -12px rgba(8, 11, 18, 0.45);
}
/* Die Kacheln. Seit dem 21.08.2026 sind es AUSSCHNITTE aus dem
   Bildschirmfoto, das Uejs geliefert hat (`~/Desktop/Record 2/Mac.png`),
   nicht mehr Zeichnungen — seine Entscheidung.
   Wie sie entstanden sind (Skript im Scratchpad, `icons.py`):
     · Am Dock-Grund gemessen, nicht geschaetzt: 12 Zeichen zu 66 px, erste
       Mitte x=962, Schrittweite 81,5, Mitte y=1613.
     · Freigestellt mit einer SUPERELLIPSE `|x|^5 + |y|^5 = 1` — dieselbe
       Form, die die Zeichnungen vorher trugen; vierfach ueberabgetastet,
       sonst franst die Kante bei 38 px aus.
     · 4 px Einzug: der Rand des Ausschnitts traegt einen weich ausgelaufenen
       Saum des DOCK-Grunds, und der reisst auf unserem blauen Wandbild
       sofort auf. Auf blauem Grund gegengeprueft, nicht auf weissem.
     · Der Papierkorb ist DURCHSCHEINEND — durch ihn hindurch sah man das
       gruene Gras des Vorbilds. Seine Farbachse ist neutralisiert.
     · Supace ist im selben Verfahren erzeugt (heller Verlauf + eigenes
       Zeichen, gleiche Maske), damit es dieselbe Silhouette und dieselbe
       Kantenweichheit hat wie seine Nachbarn.
   Zusammen 31 KB fuer zwoelf Kacheln; dafuer sind rund 200 Zeilen
   SVG-Zeichnung aus der Seite gefallen. */
.desk-dock i {
  position: relative;
  display: grid;
  place-items: center;
  width: clamp(18px, 3.5cqw, 38px);
  aspect-ratio: 1;
  /* KEIN border-radius: die Bilder bringen ihre Superellipse als Alphakanal
     mit, ein Kreisbogen darueber wuerde sie an den Ecken beschneiden. Der
     Schatten faellt deshalb ueber `drop-shadow`, das der ECHTEN Silhouette
     folgt statt dem Rechteck. */
  filter: drop-shadow(0 1.5px 1.5px rgba(8, 11, 18, 0.35));
}
.desk-dock i img { display: block; width: 100%; height: 100%; }

/* Der Punkt unter Supace: es laeuft, deshalb steht sein Fenster im Bild.
   Er sitzt im unteren Polster des Docks, nicht in der Kachel. */
.desk-app::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: clamp(-6px, -0.55cqw, -4px);
  translate: -50% 0;
  width: clamp(2.5px, 0.35cqw, 4px);
  aspect-ratio: 1;
  border-radius: 50%;
  background: rgba(13, 18, 32, 0.5);
}

/* Der Papierkorb wirft keinen Schatten — er ist ein durchscheinender
   Behaelter, kein Programmsymbol. */
.desk-trash { filter: none; }

/* Der Trennstrich vor dem Papierkorb. Er ist KEINE Gliederung der Seite,
   sondern Teil des abgebildeten Gegenstands — dieselbe Ueberlegung wie bei
   den drei Punkten der Fensterleiste, die auch nicht als Schmuck dastehen,
   sondern das Objekt kenntlich machen. */
.desk-sep {
  width: 1px;
  height: clamp(14px, 2.4cqw, 26px);
  margin-inline: clamp(1px, 0.35cqw, 4px);
  background: rgba(13, 18, 32, 0.16);
}

/* ---------- Das Guthaben quer ---------------------------------------------
   Unter einem Fenster in voller Breite säße das hochkante Kästchen wie ein
   Rest. Ab 760 px wird daraus ein Band: Zahl links, Balken in der Mitte
   (er läuft dann über die ganze Breite und liest sich als Vorrat), Satz
   rechts. Darunter gilt weiter die gestapelte Grundfassung — deshalb steht
   die ganze Variante IN der Abfrage und muss nichts zurücksetzen. */
@media (min-width: 760px) {
  .gauge-wide {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "k   bar note"
      "num bar note";
    column-gap: clamp(1.2rem, 3.5vw, 2.8rem);
    align-items: center;
  }
  .gauge-wide .gauge-k { grid-area: k; align-self: end; }
  .gauge-wide .gauge-n { grid-area: num; align-self: start; margin-top: 0.2rem; }
  .gauge-wide .gauge-bar { grid-area: bar; margin-top: 0; }
  .gauge-wide .gauge-f { grid-area: note; margin-top: 0; max-width: 26ch; text-align: right; }
}


/* ---------- Was es eigentlich tut (Downloadseite, 21.08.2026) -------------
   Die Seite ist auf „Download … for Mac and Windows" optimiert; wer ueber die
   Suche hier landet, hat die Startseite nie gesehen und bekam bis dahin eine
   Installationsanleitung fuer ein Produkt, das ihm niemand erklaert hat.
   Drei Zeilen unter dem Kaertchen, bewusst KEINE Karten: sie stehen im
   Auftakt auf dem Himmelsband, und dort ist jede weitere Flaeche eine zu
   viel. Gegliedert wird ueber den fetten Anfang jeder Zeile. */
.dlwhat {
  display: grid;
  gap: 0.55rem;
  width: min(100%, 720px);
  margin-top: clamp(1.6rem, 3.5vw, 2.6rem);
  text-align: left;
}
/* Der Inhalt steckt in einem <span>, und das ist PFLICHT: in einem Grid wird
   JEDER Textknoten ein eigenes Item — `<b>` und der Satz dahinter waeren zwei
   Kaesten, der eine in Spalte 2, der andere in der Zeile darunter. Genau so
   zuerst gebaut und im Bild gesehen: die fetten Anfaenge standen einzeln und
   mittig, der Rest linksbuendig darunter. */
.dlwhat li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.55rem;
  text-align: left;
  font-size: 0.97rem;
  line-height: 1.55;
  /* Auf dem warmen Teil des Himmels traegt --ink-3 nicht mehr sicher —
     dieselbe Ueberlegung wie bei `.hero .micro`. */
  color: #46526B;
}
/* Der Punkt davor ist ein Zeichen, kein Aufzaehlungspunkt: er sitzt auf der
   Grundlinie der ersten Zeile und faerbt sich wie die Marke. */
.dlwhat li::before {
  content: "";
  width: 6px;
  height: 6px;
  margin-top: 0.62em;
  border-radius: 50%;
  background: var(--blue);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 15%, transparent);
}
.dlwhat b { color: var(--ink); font-weight: 600; }

.dlwhat-f {
  width: min(100%, 720px);
  margin-top: 0.9rem;
  text-align: left;
  font-size: 0.9rem;
  color: #4E5A70;
}
.dlwhat-f a {
  color: var(--blue);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 560px) {
  .dlwhat li { font-size: 0.92rem; }
}


/* Der Hinweis unter den Knoepfen leuchtet einmal auf, wenn jemand den noch
   leeren Windows-Knopf drueckt — ein gefuellter Knopf, bei dem ein Klick
   nichts tut, liest sich sonst als kaputt. Ueber `box-shadow`, nicht ueber
   `opacity`: die ist auf dieser Seite dem Verstecken vorbehalten. */
@keyframes osnote-flash {
  0%       { box-shadow: 0 0 0 0 color-mix(in srgb, var(--amber) 55%, transparent); }
  55%      { box-shadow: 0 0 0 7px color-mix(in srgb, var(--amber) 0%, transparent); }
  100%     { box-shadow: 0 0 0 0 color-mix(in srgb, var(--amber) 0%, transparent); }
}
.osnote.is-flash { animation: osnote-flash 1.1s var(--ease) 2; }

/* ══════════════════════════════════════════════════════════════════════════
   PREISSEITE — „Der Laden" (21./22.08.2026)
   --------------------------------------------------------------------------
   Dritte Porcelain-Seite. Fassung vom 22.08.2026 (Uejs): ZWEI TABS —
   Abos zuerst, dann Guthaben —, und die Vorteile stehen auf den Karten
   selbst, „wie bei Final Round". Der Erklaersatz im Auftakt ist dafuer
   entfallen; er lebt jetzt als „Everything in Free, plus:" dort, wo er
   gebraucht wird. Ebenfalls entfallen: die Abschnitte #promise und
   #included — beide sagten, was die Karten jetzt selbst sagen.
   Der Umschalter ist woertlich `.osswap` der Installationsseite (kein neuer
   Baustein); nur `.planswap` und `.planview` kommen hinzu.
   Jeder neue Klassenname wurde gegen v4.css geprueft (0 Treffer):
     guide · planswap · planview · plan-grid · plan · plan-name · plan-price ·
     plan-per · plan-meta · plan-plus · plan-feat · plan-tag · plan-reco ·
     is-fit · plans-note · calcard · calc-l · calc-r · calc-k · calc-num ·
     calc-way · calc-per · calc-foot · fc · fc-note · manif · manif-line ·
     manif-sub
   (`is-pick` kommt aus `.osswap` und wird mitbenutzt.)
   Ohne neue Regel wiederverwendet: .hero .dlhero .hero-light .hero-in
   .eyebrow .display .lede .hero-cta .micro .how .pricing .data .sec-head
   .kicker .sec-lede .osswap .faq* .close* .ftr* .btn* .rise.
   Zeigerlicht liegt auf ::before (Rezept von `.stn`), die App-Haarlinie
   deshalb auf ::after — `.plan-reco` braucht beide gleichzeitig.
   ══════════════════════════════════════════════════════════════════════════ */

/* Der Ein-Satz-Wegweiser: sagt, WELCHER Tab gemeint ist, bevor der Blick in
   die Karten faellt. */
.guide {
  max-width: 62ch;
  margin: 0 auto clamp(1.6rem, 3vw, 2.4rem);
  text-align: center;
  font-size: clamp(0.98rem, 1.25vw, 1.08rem);
  line-height: 1.55;
  color: var(--ink-2);
  text-wrap: pretty;
}

/* ---------- Die zwei Tabs ------------------------------------------------
   `.osswap` bringt Form, Farbe und den gefuellten Auswahlzustand mit;
   hier steht nur das Mass. */
.planswap { margin-bottom: clamp(0.9rem, 1.8vw, 1.3rem); }

/* Ohne JavaScript stehen BEIDE Ansichten untereinander — vollstaendig und
   wahr. `[hidden] { display:none !important }` (Zeile 161) wuerde die zweite
   sonst auch ohne Skript verschlucken; nur ein !important schlaegt ein
   !important, eng auf den Nicht-JS-Fall gescoped. Dieselbe Absicherung wie
   bei `.osblock` auf der Installationsseite. */
.planview { display: block; }
.planview + .planview { margin-top: clamp(1rem, 2vw, 1.5rem); }
.js .planview[hidden] { display: none; }
html:not(.js) .planview[hidden] { display: block !important; }

/* ---------- Die Karten ---------------------------------------------------
   Feste vier Spalten statt auto-fit: auto-fit erzeugt beim Verengen eine
   3+1-Waisenreihe, und eine einzelne Karte am Ende einer Reihe liest sich
   als Fehler. Zwei Spalten ab 1040 px, eine ab 560 px — immer volle Reihen. */
.plan-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(0.8rem, 1.5vw, 1.15rem);
}
.plan {
  position: relative;
  overflow: clip;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: clamp(1.3rem, 2.2vw, 1.7rem);
  border-radius: var(--r-lg);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
  transition: transform 0.5s var(--spring), box-shadow 0.4s var(--ease);
}
.plan:hover { transform: translateY(-3px); box-shadow: var(--lift-card-hi); }
/* Zeigerlicht — dasselbe Rezept wie .stn/.getcard, eine Custom Property. */
.plan::before,
.calcard::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
  background: radial-gradient(440px circle at var(--gx, 50%) var(--gy, 0%),
    color-mix(in srgb, var(--blue) 9%, transparent), transparent 70%);
}
.plan:hover::before,
.calcard:hover::before { opacity: 1; }

.plan-name {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue);
}
.plan-price {
  font-size: clamp(2.2rem, 2.9vw, 2.75rem);
  font-weight: 600;
  letter-spacing: -0.05em;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.plan-per {
  font-size: 0.34em;
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--ink-3);
}
/* Bei den Guthabenkarten traegt diese Zeile die Minutenpreis-Treppe
   ($0.10 → $0.073 → $0.061) — die einzige Preisstaffel der Seite, reine
   Arithmetik, kein Rabatt-Etikett. */
.plan-meta {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.03em;
  color: var(--ink-2);
}
/* Der Knopf sitzt VOR der Merkmalsliste, wie beim Wettbewerb: wer schon
   entschieden hat, muss nicht erst an einer Liste vorbei. */
.plan .btn { margin-top: 0.85rem; }
.plan-plus {
  margin-top: 0.9rem;
  font-family: var(--mono);
  font-size: 0.585rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.plan-feat { display: grid; gap: 0.42rem; margin-top: 0.15rem; }
.plan-feat li {
  display: grid;
  grid-template-columns: 15px minmax(0, 1fr);
  gap: 0.5rem;
  align-items: start;
  font-size: 0.875rem;
  line-height: 1.45;
  color: var(--ink-2);
}
/* Derselbe Haken wie im Beweisband der Startseite (.checks .k::before) —
   eine Pruefliste sieht auf allen drei Seiten gleich aus. */
.plan-feat li::before {
  content: "";
  width: 15px;
  height: 15px;
  margin-top: 0.2rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--blue) 12%, transparent)
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232456E8' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 6.5'/%3E%3C/svg%3E") center / 9px 9px no-repeat;
}

/* Die Empfehlung: hoeherer Schatten, App-Haarlinie als Oberkante (dieselbe
   Produkt-Signatur wie das Release-Kaertchen der Downloadseite), Chip. */
.plan-reco { box-shadow: var(--lift-card-hi); }
.plan-reco::after,
.calcard::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  pointer-events: none;
  background: var(--app-edge);
}
.plan-tag {
  position: absolute;
  top: 1.05rem;
  right: 1.05rem;
  font-family: var(--mono);
  font-size: 0.545rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #fff;
  padding: 0.28rem 0.56rem;
  border-radius: 999px;
  background: linear-gradient(180deg, #3563EE, var(--blue) 70%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset, 0 6px 14px -8px rgba(36, 86, 232, 0.6);
}

/* Der Rechner zeigt auf die passende Karte — ein Cyan-Ring, erst nachdem
   der Leser selbst gerechnet hat (Skript 10 setzt die Klasse). */
.plan.is-fit {
  box-shadow:
    0 0 0 2px color-mix(in srgb, var(--cyan) 65%, transparent),
    var(--lift-card-hi);
}

.plans-note {
  margin-top: clamp(1.6rem, 3vw, 2.2rem);
  text-align: center;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--ink-3);
}

/* ---------- Der Rechner ---------------------------------------------------
   Eine grosse erhobene Karte (dieselbe Fassung wie das Release-Kaertchen:
   --card-cool + --lift-3 + Haarlinie). Links die zwei Regler, rechts das
   Ergebnisfeld in der Zahlenband-Typografie. */
.calcard {
  position: relative;
  overflow: clip;
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(1.6rem, 3.6vw, 3rem);
  width: min(100%, 980px);
  margin-inline: auto;
  padding: clamp(1.6rem, 3.2vw, 2.6rem);
  border-radius: var(--r-xl);
  background: var(--card-cool);
  box-shadow: var(--lift-3);
}
.calc-l { display: grid; gap: 1.5rem; align-content: center; }
.fc { display: grid; gap: 0.6rem; }
.fc label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}
.fc output {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.fc-note { font-size: 0.85rem; line-height: 1.5; color: var(--ink-3); }

/* Die Regler: gefuellte Spur ueber --fill (Skript), Griff als weisse Scheibe
   mit blauem Kern. Firefox bekommt die Fuellung ueber ::-moz-range-progress
   und braucht --fill nicht. */
.fc input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 26px;
  background: transparent;
  cursor: pointer;
}
.fc input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 999px;
  background: linear-gradient(90deg,
    var(--blue) var(--fill, 50%),
    color-mix(in srgb, var(--blue) 13%, #fff) var(--fill, 50%));
  box-shadow: inset 0 0 0 1px var(--edge);
}
.fc input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 22px;
  height: 22px;
  margin-top: -8px;
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 0 0 1px var(--edge-strong),
    0 2px 6px rgba(13, 18, 32, 0.22),
    inset 0 0 0 6.5px var(--blue);
}
.fc input[type="range"]::-moz-range-track {
  height: 6px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--blue) 13%, #fff);
  box-shadow: inset 0 0 0 1px var(--edge);
}
.fc input[type="range"]::-moz-range-progress {
  height: 6px;
  border-radius: 999px;
  background: var(--blue);
}
.fc input[type="range"]::-moz-range-thumb {
  width: 22px;
  height: 22px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow:
    0 0 0 1px var(--edge-strong),
    0 2px 6px rgba(13, 18, 32, 0.22),
    inset 0 0 0 6.5px var(--blue);
}

.calc-r { display: grid; gap: 0.55rem; align-content: center; justify-items: start; }
.calc-k {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}
.calc-num {
  font-size: clamp(2.6rem, 4vw, 3.4rem);
  font-weight: 600;
  letter-spacing: -0.05em;
  line-height: 0.95;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(158deg, var(--ink) 8%, var(--blue-deep) 62%, var(--blue) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.calc-way { font-size: 1.04rem; line-height: 1.5; color: var(--ink-2); }
.calc-per {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.03em;
  color: var(--ink-3);
}
.calc-r .btn { margin-top: 0.55rem; }
.calc-foot { font-size: 0.8rem; color: var(--ink-3); }

/* ---------- Das Kleingedruckte, gross gedruckt ----------------------------
   Reine Typografie, keine Karten: vier Display-Zeilen mit dem Serif-Kursiv-
   Blauverlauf, darunter je eine leise Erlaeuterung. Die Geste „nichts zu
   verstecken" ist das teuerste Premium-Signal der Seite. */
.manif {
  display: grid;
  gap: clamp(2.2rem, 4.5vw, 3.4rem);
  max-width: 880px;
  margin-inline: auto;
}
.manif li { display: grid; gap: 0.55rem; justify-items: center; text-align: center; }
.manif-line { font-size: clamp(1.7rem, 3.6vw, 2.85rem); }
.manif-sub { font-size: 0.95rem; line-height: 1.55; color: var(--ink-3); max-width: 52ch; }

/* ---------- Die Mikrozeile im Auftakt --------------------------------------
   Sie traegt echte Angaben (zwanzig Freiminuten, keine Karte, Credits
   verfallen nicht) — die darf nicht im Bild verschwinden. Uejs, 22.08.:
   „das kann man im Hintergrund nicht lesen".
   NACHGEMESSEN aus hero-sky.webp: bei 1470 px sitzt die Zeile auf Bildzeile
   76,7 %; nach der Blende von `.hero::before` (0,758 dort) ist der effektive
   Grund rgb(185,206,222), und #4E5A70 misst darauf nur **4,30:1** — fuer
   11,8-px-Text zu wenig.
   Eine reine Farbaenderung traegt nicht: das Band ist `min(65,05vw, 1120px)`
   hoch, der Hero-Inhalt aber immer gleich, also WANDERT die Zeile mit der
   Fensterbreite durchs Bild — bei 1000 px steht dieselbe Zeile auf Bildzeile
   89 %, mitten in den dunklen Bergen.
   Deshalb ein eigener heller Grund in derselben Glassprache wie `.eyebrow`:
   damit ist die Zeile von jedem Bildinhalt unabhaengig. --ink-2 darauf misst
   ueber 8:1. Nur auf dieser Seite — `.hero .micro` gehoert den drei Seiten
   gemeinsam, und auf der Installationsseite sitzt die Zeile ganz woanders.
   DIESELBE Pille traegt die Zeile im Schlussband: dort misst --ink-3 auf
   close-sky bei Abschnittszeile 75,7 % (Grund rgb(252,222,203), die Sonne)
   nur **4,07:1**, mit Pille 9,46:1. Zwei Pillen an derselben Stelle des
   Auftakts und des Schlusses lesen sich als EINE wiederkehrende Geste —
   und es bleibt bei einer Loesung statt zweier Sonderfaelle. */
.hero .micro-pill,
.close .micro-pill {
  padding: 0.42rem 0.95rem;
  border-radius: 999px;
  color: var(--ink-2);
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 0 0 1px var(--edge-strong), 0 6px 18px -12px rgba(13, 18, 32, 0.4);
}

/* Der einmalige Glanz des Hauptknopfs — dieselbe Geste wie .btn-os auf der
   Downloadseite, hier fuer den Hero-Knopf der Preisseite. */
.hero-cta .btn-fill { position: relative; overflow: hidden; }
.hero-cta .btn-fill::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  translate: -70% 0;
  background: linear-gradient(105deg, transparent 40%, rgba(255, 255, 255, 0.55) 50%, transparent 60%);
}
.hero-cta .btn-fill.is-shine::after { animation: btn-shine 1.4s var(--ease) 1 both; }

/* ---------- Schmale Fenster ---------------------------------------------- */
@media (max-width: 1040px) {
  .plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .calcard { grid-template-columns: 1fr; }
  .calc-r { justify-items: stretch; text-align: left; }
}
@media (max-width: 560px) {
  .plan-grid { grid-template-columns: 1fr; }
}

/* ══════════════════════════════════════════════════════════════════════════
   ANMELDUNG — login.html und signup.html (23.08.2026)
   --------------------------------------------------------------------------
   Die zwei Seiten im Kaufweg: von „Get 400 minutes" auf der Preisseite geht
   es direkt hierher. Bis heute liefen sie auf `styles.css` + `auth.css` und
   sahen damit aus wie ein anderes Produkt — genau im Moment der Entscheidung.
   Jetzt Porcelain, und `auth.css` wird von ihnen NICHT mehr geladen: das
   ganze Formularvokabular steht hier.

   ZWEISPALTIG: links das Formular auf Papier, rechts das Himmelsband mit dem
   Vorher/Nachher-Vergleich. Ab 980 px gestapelt — dann steht das Formular
   OBEN, weil es der Zweck der Seite ist; die Schauspalte darunter.

   Klassennamen gegen v4.css geprueft (0 Treffer): auth · authbody ·
   auth-side · auth-card · auth-brand · auth-title · auth-sub · auth-alert ·
   auth-or · auth-form · auth-foot · auth-foot-alt · auth-show · auth-show-in ·
   field · field-error · input-shell · pw-toggle · check-row · btn-google ·
   show-claim · show-facts · demo · demo-box · demo-under · demo-over ·
   demo-clip · demo-logo · demo-tag(-l/-r) · demo-glow · demo-line ·
   demo-handle · demo-cap.  (Die cmp-*-Fassung mit dem interaktiven Regler
   und den hide-*-Fotos ist am 23.08. der App-Szene gewichen — s. u.)
   Ohne neue Regel wiederverwendet: .skip .display .kicker .btn .btn-fill
   .btn-ghost .btn-block .btn-lg .is-shown.

   PFLICHT-HAKEN aus `js/ui.js` — nicht umbenennen:
     `#authAlert` + `.auth-alert` (className wird komplett neu gesetzt:
       „auth-alert is-shown error|success|info"),
     `.field-error` an `#<feldId>-error` (bekommt `is-shown` getoggelt),
     `.pw-toggle` (innerHTML wird durch ein Auge-SVG ersetzt),
     `aria-invalid` an den Eingaben.
   Und: `setBusy()` tauscht `button.textContent` — ein Knopf darf deshalb
   KEIN Inline-SVG enthalten, sonst ist es nach dem ersten Fehlversuch weg.
   Deshalb traegt `.btn-google` sein Zeichen als Hintergrund.
   ══════════════════════════════════════════════════════════════════════════ */

.authbody { background: var(--paper); }

.auth {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100svh;
}
/* DER GRUND — einer fuer die GANZE Seite, nicht je Spalte (23.08., Uejs:
   „mir fehlt da irgendwie so ein Hintergrund"). Vorher war links eine
   getoente Flaeche und rechts leeres Papier — das las sich als zwei Haelften,
   und die rechte wirkte unfertig. Jetzt liegt EIN Lichtfeld ueber beiden
   Spalten (dasselbe Dreifarben-Rezept wie .hero-light: Cyan links, Blau
   rechts, Bernstein unten — hier voll aufgedreht, weil kein Bild darunter
   liegt), und das Punktraster laeuft durch. Die Spaltenkante verschwindet:
   eine Buehne mit zwei Objekten, Szene links, Karte rechts. */
.auth::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(54% 46% at 6% -8%,   color-mix(in srgb, var(--cyan) 30%, transparent) 0%, transparent 68%),
    radial-gradient(50% 42% at 96% -10%, color-mix(in srgb, var(--blue) 22%, transparent) 0%, transparent 66%),
    radial-gradient(64% 40% at 74% 112%, color-mix(in srgb, var(--amber) 26%, transparent) 0%, transparent 72%),
    radial-gradient(56% 38% at 12% 116%, color-mix(in srgb, var(--cyan) 14%, transparent) 0%, transparent 70%);
}
/* Das feine PUNKTraster — Punkte, keine Linien (ein Linienraster waere ein
   Feld aus Trennlinien). Ueber die ganze Buehne, in der Mitte ausgespart,
   damit es HINTER den beiden Objekten liegt statt in ihnen. */
.auth::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(circle,
    color-mix(in srgb, var(--blue-deep) 17%, transparent) 1px, transparent 1.35px);
  background-size: 23px 23px;
  -webkit-mask-image: radial-gradient(72% 68% at 50% 46%, transparent 30%, #000 82%);
  mask-image: radial-gradient(72% 68% at 50% 46%, transparent 30%, #000 82%);
}
/* Beide Spalten liegen UEBER dem gemeinsamen Grund. */
.auth-side, .auth-show { position: relative; z-index: 1; }
/* Das Formular steht RECHTS (Uejs, 23.08.). Ueber `order`, nicht ueber die
   DOM-Reihenfolge: im Quelltext bleibt es das erste Element, damit die
   Tab-Taste dort landet und nicht erst durch die Schauspalte laeuft. */
.auth-side { order: 2; }
.auth-show { order: 1; }

/* ---------- Links: die Formularspalte ------------------------------------ */
.auth-side {
  display: grid;
  align-content: center;
  justify-items: center;
  padding: clamp(1.5rem, 4vw, 3.5rem) var(--pad);
}
/* Die Karte wirft Licht auf den Grund — derselbe Gedanke wie der Rueckwurf
   unter den Produktaufnahmen: ein Objekt im Raum, kein Bild auf der Seite.
   EIN Radial mit transparentem Ende braucht keine Maske (die harte-Kante-
   Falle betrifft nur mehrlagige Rueckwuerfe mit ueberstehendem inset). */
.auth-side::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: min(150%, 820px);
  aspect-ratio: 1.15;
  pointer-events: none;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--blue) 13%, transparent), transparent 72%);
}
.auth-card {
  width: min(100%, 460px);
  position: relative;
  overflow: clip;
  padding: clamp(1.6rem, 3.4vw, 2.6rem);
  border-radius: var(--r-xl);
  background: var(--card-cool);
  box-shadow: var(--lift-3);
}
/* Die App-Haarlinie als Oberkante — dieselbe Produkt-Signatur wie das
   Release-Kaertchen der Downloadseite und die empfohlene Preiskarte. */
.auth-card::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  pointer-events: none;
  background: var(--app-edge);
}

.auth-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: clamp(1.2rem, 2.6vw, 1.9rem);
  font-size: 1.12rem;
  font-weight: 620;
  letter-spacing: -0.035em;
  color: var(--ink);
}
.auth-brand img { border-radius: 9px; }

/* Kein `.display` und KEIN Serif-Kursiv-Akzent mehr (Uejs, 23.08.: „Welcome
   back sieht sehr schlecht aus"): der Blauverlauf-Akzent ist fuer die
   grossen Auftakte gebaut — bei Formulargroesse kippt er von edel zu schief.
   Eine Anmeldemaske ist kein Auftakt; die Ueberschrift benennt nur, wo man
   ist, das Formular darunter ist die Hauptsache. */
.auth-title {
  font-size: clamp(1.35rem, 2vw, 1.6rem);
  font-weight: 620;
  letter-spacing: -0.03em;
  line-height: 1.15;
  color: var(--ink);
}
.auth-sub {
  margin-top: 0.6rem;
  font-size: 0.985rem;
  line-height: 1.5;
  color: var(--ink-3);
  text-wrap: pretty;
}

/* ---------- Meldungen ----------------------------------------------------
   `ui.js` setzt `className = "auth-alert is-shown <kind>"`. Im Ruhezustand
   ist der Kasten NICHT nur durchsichtig, sondern nimmt keinen Platz ein —
   sonst klafft ueber dem Google-Knopf eine Luecke, solange nichts los ist. */
.auth-alert { display: none; }
.auth-alert.is-shown {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  align-items: start;
  gap: 0.6rem;
  margin-top: 1.2rem;
  padding: 0.8rem 0.95rem;
  border-radius: var(--r-sm);
  font-size: 0.9rem;
  line-height: 1.5;
  text-wrap: pretty;
}
.auth-alert svg { width: 18px; height: 18px; margin-top: 0.1rem; fill: none; stroke: currentColor; }
/* Rot ist die EINZIGE Stelle der Website, an der es rot gibt — ein Fehler in
   einem Formular ist der eine Fall, in dem eine Warnfarbe traegt. */
.auth-alert.error {
  color: #8A1F1F;
  background: #FDF2F2;
  box-shadow: inset 0 0 0 1px rgba(138, 31, 31, 0.18);
}
.auth-alert.success {
  color: #14563C;
  background: #F0FBF5;
  box-shadow: inset 0 0 0 1px rgba(20, 86, 60, 0.16);
}
.auth-alert.info {
  color: var(--blue-deep);
  background: color-mix(in srgb, var(--blue) 7%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 20%, transparent);
}

/* ---------- Der Google-Knopf ---------------------------------------------
   Das Zeichen liegt als Hintergrund, nicht als <svg> im Knopf: `setBusy()`
   schreibt `textContent` und wuerde ein Inline-SVG loeschen. Vier Farben in
   einer data-URI, also ein Bild ohne zweiten Abruf. */
.btn-google {
  margin-top: 1.3rem;
  padding-left: 3rem;
  justify-content: center;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%234285F4' d='M23.5 12.3c0-.9-.1-1.6-.2-2.3H12v4.1h6.6c-.1 1.1-.9 2.8-2.5 3.9l3.6 2.8c2.1-2 3.8-5 3.8-8.5Z'/%3E%3Cpath fill='%2334A853' d='M12 24c3.2 0 6-1.1 7.9-2.9l-3.6-2.8c-1 .7-2.3 1.2-4.3 1.2-3.1 0-5.8-2.1-6.7-5H1.6v2.9C3.5 21.3 7.4 24 12 24Z'/%3E%3Cpath fill='%23FBBC05' d='M5.3 14.5c-.2-.7-.4-1.4-.4-2.5s.1-1.8.4-2.5V6.6H1.6C.9 8.1.5 9.9.5 12s.4 3.9 1.1 5.4l3.7-2.9Z'/%3E%3Cpath fill='%23EA4335' d='M12 4.8c1.8 0 3.3.7 4.5 1.8l3.2-3.2C17.9 1.4 15.2.3 12 .3 7.4.3 3.5 3 1.6 6.6l3.7 2.9C6.2 6.6 8.9 4.8 12 4.8Z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 1.15rem center;
  background-size: 18px 18px;
}
/* `.btn-ghost:hover` setzt `background: #fff` — als Kurzform wuerde das das
   Zeichen mit weghauen. Nur die FARBE tauschen. */
.btn-google:hover { background-color: #fff; }
.btn-google:disabled { cursor: default; }

/* ---------- „or" ohne Trennlinie -----------------------------------------
   Zwei Striche links und rechts waeren zwei Trennlinien. Stattdessen steht
   das Wort allein im Weissraum — dieselbe Gliederungsregel wie ueberall. */
.auth-or {
  margin: 1.15rem 0 0.15rem;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---------- Felder -------------------------------------------------------- */
.auth-form { display: grid; gap: 1rem; margin-top: 1.15rem; }
.field { display: grid; gap: 0.42rem; }
.field > label {
  font-size: 0.82rem;
  font-weight: 560;
  letter-spacing: -0.01em;
  color: var(--ink-2);
}
.input-shell { position: relative; display: grid; }
.input-shell input {
  width: 100%;
  padding: 0.82rem 1rem;
  border: 0;
  border-radius: var(--r-sm);
  font-size: 0.985rem;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 1px var(--edge-strong), inset 0 1px 2px rgba(13, 18, 32, 0.04);
  transition: box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.input-shell input::placeholder { color: var(--ink-4); }
.input-shell input:hover { background: #fff; }
/* Der Fokusring des Feldes ersetzt den globalen `:focus-visible`-Umriss —
   an einer abgerundeten Eingabe sieht ein zweiter Rahmen daneben aus. */
.input-shell input:focus {
  outline: none;
  background: #fff;
  box-shadow:
    inset 0 0 0 1.5px var(--blue),
    0 0 0 4px color-mix(in srgb, var(--blue) 15%, transparent);
}
.input-shell input[aria-invalid="true"] {
  box-shadow: inset 0 0 0 1.5px #C0392B, 0 0 0 4px rgba(192, 57, 43, 0.12);
}
/* Platz fuer das Auge, damit lange Passwoerter nicht darunter laufen. */
.field:has(.pw-toggle) .input-shell input { padding-right: 3rem; }

.pw-toggle {
  position: absolute;
  top: 50%;
  right: 0.55rem;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  color: var(--ink-3);
  transition: color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.pw-toggle:hover { color: var(--ink); background: color-mix(in srgb, var(--blue) 8%, transparent); }
.pw-toggle svg { width: 18px; height: 18px; fill: none; stroke: currentColor; }

/* `ui.js` toggelt `is-shown`; ohne Meldung nimmt die Zeile keinen Platz. */
.field-error { display: none; font-size: 0.82rem; line-height: 1.45; color: #C0392B; }
.field-error.is-shown { display: block; }

/* ---------- Das Haekchen --------------------------------------------------
   Eigene Zeichnung statt `accent-color`: die Systemfassung ist quadratisch
   und hart, und ihr Blau ist nicht unseres. */
.check-row { display: grid; grid-template-columns: 20px minmax(0, 1fr); gap: 0.65rem; align-items: start; }
.check-row input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 20px;
  height: 20px;
  margin: 0.1rem 0 0;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.check-row input[type="checkbox"]:checked {
  background: var(--blue) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 12.5 4.5 4.5L19 6.5'/%3E%3C/svg%3E") center / 12px 12px no-repeat;
  box-shadow: inset 0 0 0 1px var(--blue);
}
.check-row label { font-size: 0.875rem; line-height: 1.5; color: var(--ink-3); }
.check-row a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Fusszeilen der Karte ------------------------------------------ */
.auth-foot {
  margin-top: 1.15rem;
  text-align: center;
  font-size: 0.895rem;
  color: var(--ink-3);
}
.auth-foot-alt { margin-top: 0.65rem; }
.auth-foot a { color: var(--blue); font-weight: 540; text-decoration: underline; text-underline-offset: 3px; }

/* ══════════════════════════════════════════════════════════════════════════
   Rechts: die Schauspalte auf dem Himmelsband
   ══════════════════════════════════════════════════════════════════════════ */
/* Die Schauspalte traegt das HIMMELSBAND (zurueck am 23.08., Uejs: „links
   fehlt so ein cooles Hintergrundbild wie du davor gemacht hast mit dem
   Berg"). `cover` mit Ausschnitt bei 62 %: Gipfel und Sonne im Bild, nicht
   der leere Himmel. Die Spalte liegt mit z-index 1 UEBER dem gemeinsamen
   Grund von `.auth` — das Foto deckt Lichtfeld und Punktraster links ab,
   rechts bleibt beides stehen: links Bild, rechts Licht — zwei Flaechen,
   EINE Buehne. */
.auth-show {
  display: grid;
  align-content: center;
  padding: clamp(2rem, 4vw, 4rem) clamp(1.5rem, 3.5vw, 3.5rem);
  overflow: clip;
  background: url("../assets/img/hero-sky.webp") center 62% / cover no-repeat;
}

.auth-show-in {
  position: relative;
  z-index: 1;
  width: min(100%, 620px);
  margin-inline: auto;
  display: grid;
  justify-items: center;
  text-align: center;
  gap: 1.1rem;
}
.show-claim { font-size: clamp(1.55rem, 2.5vw, 2.15rem); max-width: 16ch; }

/* ---------- Die Szene: der Anmeldebildschirm der App ----------------------
   WOERTLICH die Abbildung aus dem Login des Tools (ComparisonSlider.tsx +
   compare-with/-without.svg, hier als auth-scene-*.svg): zwei gebaute
   SVG-Ebenen desselben Bildschirms, die obere an der Naht beschnitten.
   Website und App zeigen beim Anmelden DASSELBE Bild — Wiedererkennung
   statt Tapete; und die vierte Verwendung von hide-them/hide-you entfaellt.
   Alles haengt an EINER Variable `--pos` auf `.demo-box` (Schnitt, Naht,
   Glut, Griff) — das Skript schreibt nur sie. KEINE Bedienung, mit
   Absicht: die App begruendet es als „showcase, not a control" — nichts
   hier soll greifbar aussehen. Der kleine Griff ist reine Deko der Naht
   (aria-hidden), wie in der App.
   3:2 wie in der App; die SVGs bringen ihren dunklen Grund selbst mit —
   eine gebaute dunkle Produkteinlage, wie .ts/.code auf der Startseite,
   in derselben --win-dark-Fassung. */
.demo { position: relative; width: 100%; margin: 0.4rem 0 0; }
/* Die Szene ist dunkel und leuchtet — sie wirft blaues Licht auf den Grund,
   wie die Hero-Platte der Startseite (abgeschwaechtes Rezept von
   `.hero-stage::before`). MIT Maske: mehrere Radialverlaeufe mit
   ueberstehendem inset enden sonst als hartes Rechteck — im Bild gesehene
   Falle der Startseite, nicht neu hineinlaufen. */
.demo::before {
  content: "";
  position: absolute;
  inset: 10% -6% -4%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(60% 46% at 50% 16%,  color-mix(in srgb, var(--blue) 24%, transparent), transparent 70%),
    radial-gradient(66% 40% at 46% 66%,  color-mix(in srgb, var(--cyan) 18%, transparent), transparent 72%),
    radial-gradient(72% 40% at 50% 100%, color-mix(in srgb, var(--blue) 15%, transparent), transparent 68%);
  -webkit-mask-image: radial-gradient(74% 66% at 50% 48%, #000 28%, transparent 80%);
  mask-image: radial-gradient(74% 66% at 50% 48%, #000 28%, transparent 80%);
}
.demo-box {
  position: relative;
  aspect-ratio: 3 / 2;
  border-radius: var(--r-md);
  overflow: hidden;
  background: #0D1526; /* der Grund der SVGs selbst — kein Aufblitzen beim Laden */
  box-shadow: var(--win-dark);
}
.demo-box img { user-select: none; -webkit-user-drag: none; }
.demo-under,
.demo-over {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.demo-over { clip-path: inset(0 calc(100% - var(--pos, 90%)) 0 0); }
/* Das echte Markenzeichen, im Gleichschnitt mit dem Panel — Masse sind
   LOGO_BOX aus der App (Position in der echten Toolbar, bewusst klein:
   die echte Stelle zaehlt mehr als maximale Lesbarkeit). */
.demo-clip {
  position: absolute;
  inset: 0;
  pointer-events: none;
  clip-path: inset(0 calc(100% - var(--pos, 90%)) 0 0);
}
.demo-logo {
  position: absolute;
  left: 76.33%;
  top: 14%;
  width: 3%;
  aspect-ratio: 1;
  object-fit: contain;
}
/* Ecken-Beschriftung im App-Stil: Text + Punkt, KEIN Chip — nichts liegt
   auf der Aufnahme; ein Schlagschatten haelt sie auf jedem Inhalt lesbar. */
.demo-tag {
  position: absolute;
  top: 0.75rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  filter: drop-shadow(0 1px 3px rgba(8, 11, 18, 0.85));
  pointer-events: none;
}
.demo-tag i { width: 6px; height: 6px; border-radius: 50%; }
.demo-tag-l { left: 0.8rem; }
.demo-tag-l i { background: var(--cyan-soft); }
.demo-tag-r { right: 0.8rem; }
.demo-tag-r i { background: rgba(255, 255, 255, 0.55); }
/* Die Naht: weiche Glut hinter einer feinen Linie — Markierung des
   Schnitts, kein Greifzeug. Sie steht IM Bild und trennt nicht zwei Dinge,
   sie IST der Gegenstand der Abbildung. */
.demo-glow {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--pos, 90%);
  width: 26px;
  translate: -13px 0;
  pointer-events: none;
  background: radial-gradient(50% 62% at 50% 50%, rgba(127, 224, 242, 0.45), transparent 72%);
  filter: blur(5px);
}
.demo-line {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--pos, 90%);
  width: 1.5px;
  translate: -0.75px 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.85) 50%, rgba(255, 255, 255, 0.14));
}
.demo-handle {
  position: absolute;
  top: 50%;
  left: var(--pos, 90%);
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  color: rgba(255, 255, 255, 0.85);
  background: rgba(13, 21, 38, 0.55);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  pointer-events: none;
}
/* Auf dem Foto braucht die Zeile einen eigenen Grund — dieselbe Lektion wie
   die Mikrozeilen der Preisseite (dort nachgemessen: 4,07:1 auf dem
   Sonnenteil). Glaspille wie .eyebrow/.micro-pill: von jedem Bildinhalt
   unabhaengig. */
.demo-cap {
  width: fit-content;
  margin: 0.85rem auto 0;
  padding: 0.42rem 0.95rem;
  border-radius: 999px;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 0 0 1px var(--edge-strong), 0 6px 18px -12px rgba(13, 18, 32, 0.4);
}
.demo-cap b { color: var(--ink); font-weight: 560; }

/* ---------- Die drei Angaben darunter ------------------------------------- */
.show-facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0.7rem;
  width: 100%;
  margin-top: 0.5rem;
}
.show-facts li {
  display: grid;
  gap: 0.15rem;
  padding: 0.75rem 0.85rem;
  border-radius: var(--r-sm);
  text-align: left;
  background: rgba(255, 255, 255, 0.72);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 0 0 1px var(--edge-strong), 0 8px 20px -16px rgba(13, 18, 32, 0.4);
}
.show-facts b { font-size: 0.885rem; font-weight: 580; letter-spacing: -0.015em; }
.show-facts span { font-size: 0.78rem; line-height: 1.4; color: var(--ink-3); }

/* ---------- Schmale Fenster ----------------------------------------------
   Gestapelt steht das FORMULAR oben: es ist der Zweck der Seite, und wer
   sich anmelden will, soll nicht erst an einer Abbildung vorbeiscrollen. */
@media (max-width: 980px) {
  .auth { grid-template-columns: 1fr; min-height: 0; }
  /* Gestapelt kehrt sich die Reihenfolge um: das Formular ist der Zweck der
     Seite und gehoert nach oben, die Schauspalte darunter. */
  .auth-side { order: 1; padding-block: clamp(2rem, 7vw, 3.5rem); }
  .auth-show { order: 2; }
  .auth-show { padding-block: clamp(2.5rem, 8vw, 4rem); }
  .show-claim { max-width: 22ch; }
}
@media (max-width: 560px) {
  .show-facts { grid-template-columns: 1fr; }
  .cmp-tag { font-size: 0.5rem; top: 0.45rem; }
  .cmp-tag-l { left: 0.45rem; }
  .cmp-tag-r { right: 0.45rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   PORTAL — der angemeldete Bereich (24.08.2026)
   --------------------------------------------------------------------------
   account.html · sessions.html · documents.html · settings.html.
   Diese vier Seiten laden NUR NOCH v4.css; `styles.css`/`auth.css` sind fuer
   sie Geschichte (admin.html bleibt auf dem alten Paar — Operator-Seite).

   Der VERTRAG: die Seitenlogik lebt in js/dashboard.js (Sidebar-Markup!),
   js/sessionsUI.js (Zeilen, Leser, Dialoge), js/activityChart.js (cx-*-SVG),
   js/docPreview.js (Vorschau im Leser) und den Inline-Modulen der Seiten.
   ALLE Klassen dort sind hier gestylt, KEINE wurde umbenannt — wer hier
   Namen aendert, muss zuerst diese vier Dateien lesen.
   Zustands-Haken der Skripte: html[data-sidebar="collapsed"],
   html[data-mobilenav="open"], .is-active, .is-hi, .is-hit, .is-selected,
   .is-selectable, .is-over, .is-full, .is-frame, [hidden].

   Gestaltung: dieselbe Werkzeugseiten-Linie wie die Anmeldung — Lichtflaeche
   statt Bergbild, Karten in --card-cool, keine Trennlinien (die Sidebar
   endet in einem weichen Lichtabfall, nicht in einem Strich), Zahlen in der
   .fig-Gradientsprache, Rot nur an Formular-Fehlern und Loeschwegen.
   ══════════════════════════════════════════════════════════════════════════ */

/* ---------- Die Schale ----------------------------------------------------- */
.app-shell {
  --sbw: 264px;
  display: grid;
  grid-template-columns: var(--sbw) minmax(0, 1fr);
  min-height: 100vh;
  min-height: 100svh;
}
html[data-sidebar="collapsed"] .app-shell { --sbw: 76px; }

.app-main { position: relative; min-width: 0; overflow-x: clip; }
/* Das Lichtfeld der Werkzeugseiten hinter dem Inhalt — dieselben drei Farben
   wie ueberall, leiser als im Auftakt. */
.app-main::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(46% 34% at 10% -4%,  color-mix(in srgb, var(--cyan) 14%, transparent) 0%, transparent 70%),
    radial-gradient(42% 32% at 94% -6%,  color-mix(in srgb, var(--blue) 11%, transparent) 0%, transparent 68%),
    radial-gradient(60% 34% at 60% 110%, color-mix(in srgb, var(--amber) 12%, transparent) 0%, transparent 72%);
}
.app-content {
  position: relative;
  max-width: 1080px;
  margin-inline: auto;
  padding: clamp(1.6rem, 3vw, 2.8rem) var(--pad) clamp(3.5rem, 7vw, 5.5rem);
  display: grid;
  /* Uejs, 24.08.: „die Kaesten sind viel zu nah beieinander" — der Abstand
     zwischen den Bloecken ist seither das Doppelte der ersten Fassung.
     Gliederung ueber Weissraum ist die Grundregel der ganzen Website; sie
     gilt im Portal genauso. */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.8rem, 3.6vw, 2.8rem);
  align-content: start;
}
/* DER ABSTANDSFEHLER, 24.08.: die Panels sind NICHT Kinder von .app-content,
   sondern von #dashView (und auf der Operations-Seite noch eine Ebene tiefer
   von #adminBody). Das `gap` oben wirkte damit nur zwischen Spinner und
   Inhalt — die Kaesten selbst stiessen als normale Bloecke aneinander.
   Beide Huellen sind jetzt selbst Raster mit demselben Mass.
   `[hidden] { display:none !important }` (Zeile 161) schlaegt das weiterhin,
   der Spinner-Zustand bleibt also heil. */
#dashView,
#adminBody {
  display: grid;
  /* `minmax(0, 1fr)` statt der Vorgabe `auto`: ein Grid-Kind hat
     `min-width: auto` und schrumpft damit NICHT unter seinen Inhalt — die
     980 px breite Konten-Tabelle drueckte so die ganze Seite seitlich auf.
     Mit einer Null-Untergrenze bleibt die Spalte in der Breite des Fensters,
     und der breite Inhalt scrollt INNERHALB seines Kastens (.admin-scroll). */
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.8rem, 3.6vw, 2.8rem);
  align-content: start;
}

/* ---------- Die Seitenleiste ----------------------------------------------
   Eine eigene helle Flaeche, die in einem weichen Lichtabfall endet — KEIN
   border-right: das waere eine raumhohe Trennlinie. */
.sb {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  padding: 0.9rem 0.8rem 1rem;
  overflow-y: auto;
  overflow-x: clip;
  background: linear-gradient(178deg, #FFFFFF 0%, #F8FAFD 55%, #F1F4FA 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.9),
    14px 0 34px -28px rgba(22, 41, 94, 0.25);
}
.sb-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.4rem;
  padding: 0.25rem 0.35rem 0.7rem;
}
.sb-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  font-size: 1.05rem;
  font-weight: 620;
  letter-spacing: -0.035em;
  color: var(--ink);
}
.sb-brand img { border-radius: 8px; flex: none; }
.sb-collapse {
  flex: none;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  color: var(--ink-3);
  transition: color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.sb-collapse:hover { color: var(--ink); background: color-mix(in srgb, var(--blue) 8%, transparent); }
.sb-collapse svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.8; }

.sb-nav { display: grid; gap: 0.2rem; }
.sb-item {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.58rem 0.7rem;
  border-radius: 11px;
  font-size: 0.9rem;
  font-weight: 520;
  letter-spacing: -0.012em;
  color: var(--ink-2);
  white-space: nowrap;
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease);
}
.sb-item svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; }
.sb-item:hover { background: color-mix(in srgb, var(--blue) 6%, transparent); color: var(--ink); }
/* Der aktive Punkt: getoente Pille, blaues Zeichen — Zustand, kein Aufruf. */
.sb-item.is-active {
  background: color-mix(in srgb, var(--blue) 10%, #fff);
  color: var(--blue-deep);
  font-weight: 580;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 16%, transparent);
}
.sb-item.is-active svg { color: var(--blue); }

.sb-foot { margin-top: auto; display: grid; gap: 0.2rem; padding-top: 0.6rem; }
.sb-link { color: var(--ink-3); }
.sb-user {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.5rem;
  padding: 0.6rem 0.65rem;
  border-radius: var(--r-md);
  background: var(--card-cool);
  box-shadow: var(--lift-1);
  min-width: 0;
}
.sb-user-av {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  font-size: 0.9rem;
  font-weight: 640;
  color: #fff;
  background: linear-gradient(140deg, var(--blue) 20%, var(--cyan) 120%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4) inset, 0 6px 14px -8px rgba(36, 86, 232, 0.55);
}
.sb-user-meta { display: grid; min-width: 0; }
.sb-user-name {
  font-size: 0.84rem;
  font-weight: 570;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sb-user-tier {
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.sb-user-tier.is-hi { color: #10707E; }
.sb-logout {
  flex: none;
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  color: var(--ink-3);
  transition: color 0.22s var(--ease), background-color 0.22s var(--ease);
}
.sb-logout:hover { color: #8A1F1F; background: rgba(192, 57, 43, 0.08); }
.sb-logout svg { width: 16px; height: 16px; fill: none; stroke: currentColor; }

/* Eingeklappt: nur die Zeichen. Die Labels FALLEN (display), sie schrumpfen
   nicht — ein halb abgeschnittenes Wort liest sich als Fehler. */
html[data-sidebar="collapsed"] .sb { padding-inline: 0.55rem; }
html[data-sidebar="collapsed"] .sb-brand span,
html[data-sidebar="collapsed"] .sb-item span,
html[data-sidebar="collapsed"] .sb-user-meta { display: none; }
html[data-sidebar="collapsed"] .sb-top { justify-content: center; flex-direction: column; gap: 0.6rem; }
html[data-sidebar="collapsed"] .sb-item { justify-content: center; padding-inline: 0; }
html[data-sidebar="collapsed"] .sb-user { justify-content: center; padding: 0.5rem 0.4rem; }
html[data-sidebar="collapsed"] .sb-logout { margin-left: 0; }

/* ---------- Das App-Band oben ---------------------------------------------
   Glasband in der eyebrow-Sprache — eine Auskunft, kein Balken. */
.topbar-banner {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  flex-wrap: wrap;
  max-width: 1080px;
  margin: clamp(0.9rem, 2vw, 1.4rem) auto 0;
  margin-inline: max(var(--pad), calc((100% - 1080px) / 2 + var(--pad)));
  padding: 0.65rem 1rem;
  border-radius: var(--r-md);
  position: relative;
  background: rgba(255, 255, 255, 0.75);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  box-shadow: 0 0 0 1px var(--edge-strong), 0 10px 26px -20px rgba(13, 18, 32, 0.4);
}
.topbar-banner-text { font-size: 0.86rem; color: var(--ink-2); }
.topbar-banner-text b { font-weight: 580; }
.topbar-banner-link {
  font-size: 0.86rem;
  font-weight: 560;
  color: var(--blue);
  white-space: nowrap;
}
.topbar-banner-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.topbar-banner-x {
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  color: var(--ink-3);
  transition: color 0.22s var(--ease), background-color 0.22s var(--ease);
}
.topbar-banner-x:hover { color: var(--ink); background: color-mix(in srgb, var(--blue) 8%, transparent); }
.topbar-banner-x svg { width: 14px; height: 14px; fill: none; stroke: currentColor; }

/* ---------- Laden ---------------------------------------------------------- */
.auth-status { display: grid; place-items: center; min-height: 40vh; }
.spinner {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--blue) 16%, transparent);
  border-top-color: var(--blue);
  animation: portal-spin 0.8s linear infinite;
}
.spinner-sm { width: 16px; height: 16px; border-width: 2.5px; flex: none; }
@keyframes portal-spin { to { rotate: 360deg; } }

/* ---------- Seitenkopf und Panels ----------------------------------------- */
.page-head { display: grid; gap: 0.3rem; padding-top: 0.4rem; }
.page-title {
  font-size: clamp(1.5rem, 2.4vw, 1.9rem);
  font-weight: 620;
  letter-spacing: -0.035em;
  line-height: 1.1;
  color: var(--ink);
}
.page-sub { font-size: 0.94rem; color: var(--ink-3); max-width: 62ch; text-wrap: pretty; }

.app-panel {
  position: relative;
  overflow: clip;
  min-width: 0;
  padding: clamp(1.4rem, 2.6vw, 2rem);
  border-radius: var(--r-lg);
  background: var(--card-cool);
  box-shadow: var(--lift-1);
}
.app-panel-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin-bottom: 1.3rem;
}
.app-panel-title {
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.chart-sub { font-size: 0.83rem; color: var(--ink-3); margin-top: 0.15rem; }
.panel-link { font-size: 0.86rem; font-weight: 550; color: var(--blue); white-space: nowrap; }
.panel-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.chart-head-right { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.badge-app {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  color: var(--ink-3);
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--blue) 7%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 14%, transparent);
}
.app-two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(1rem, 2vw, 1.4rem); }

/* ---------- Dashboard: Begruessung ----------------------------------------
   Die getcard-Sprache der Downloadseite: staerkste Fassung, App-Haarlinie. */
.hero-card {
  position: relative;
  overflow: clip;
  padding: clamp(1.5rem, 3vw, 2.2rem);
  border-radius: var(--r-xl);
  background: var(--card-cool);
  box-shadow: var(--lift-3);
}
.hero-card::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  pointer-events: none;
  background: var(--app-edge);
}
.hero-body { display: grid; gap: 0.55rem; justify-items: start; }
.hero-title {
  font-size: clamp(1.6rem, 2.8vw, 2.15rem);
  font-weight: 620;
  letter-spacing: -0.04em;
  line-height: 1.08;
  color: var(--ink);
}
.hero-sub { font-size: 0.95rem; color: var(--ink-3); max-width: 52ch; }
.hero-go { margin-top: 0.7rem; gap: 0.5rem; }
.hero-go svg { fill: none; stroke: currentColor; }

/* ---------- Dashboard: die drei Zahlen -------------------------------------
   Werte in der .fig-Gradientsprache des Zahlenbands der Startseite. */
.stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(0.8rem, 1.6vw, 1.15rem); }
.stat {
  position: relative;
  overflow: clip;
  display: grid;
  gap: 0.45rem;
  align-content: start;
  padding: clamp(1.05rem, 2vw, 1.4rem);
  border-radius: var(--r-lg);
  background: var(--card-cool);
  box-shadow: var(--lift-1);
}
.stat-link { transition: transform 0.45s var(--spring), box-shadow 0.35s var(--ease); }
.stat-link:hover { transform: translateY(-3px); box-shadow: var(--lift-2); }
.stat-top { display: flex; align-items: center; gap: 0.55rem; }
.stat-ic {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  color: var(--blue);
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--blue) 13%, #fff),
    color-mix(in srgb, var(--cyan) 11%, #fff));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9),
              inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent);
}
.stat-ic svg { width: 18px; height: 18px; fill: none; stroke: currentColor; }
.stat-ic-credits { color: #10707E;
  background: linear-gradient(158deg, color-mix(in srgb, var(--cyan) 18%, #fff), color-mix(in srgb, var(--cyan) 8%, #fff));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), inset 0 0 0 1px color-mix(in srgb, var(--cyan) 26%, transparent); }
.stat-ic-access { color: #8A6A1F;
  background: linear-gradient(158deg, color-mix(in srgb, var(--amber) 22%, #fff), color-mix(in srgb, var(--amber) 10%, #fff));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.9), inset 0 0 0 1px color-mix(in srgb, var(--amber) 34%, transparent); }
.stat-ic-sessions { /* Grundfassung oben — eigener Name bleibt fuer die Seite */ }
.stat-label {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.stat-value {
  font-size: clamp(1.7rem, 2.6vw, 2.2rem);
  font-weight: 600;
  letter-spacing: -0.045em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(158deg, var(--ink) 8%, var(--blue-deep) 62%, var(--blue) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.stat-note { font-size: 0.8rem; color: var(--ink-3); }

/* ---------- Dashboard-Neubau (24.08., zweiter Durchgang) -------------------
   Uejs: „komplett aendern … neue Ideen … 2000-Dollar-Niveau". Der Schnitt:
   1) Begruessung als einzige DISPLAY-Zeile des Portals (Serif-Kursiv-Akzent
      auf dem Namen — die Geste der Schauseiten, genau EINMAL);
   2) das DECK: links die Minuten (das, was man hier verwaltet) in der
      getcard-Sprache, rechts das letzte Interview (das, wofuer man
      wiederkommt) mit direktem Sprung in den Leser;
   3) drei Bestandszahlen auf EINEM Objekt — woertlich `.figures` der
      Startseite, nur mit Portal-Massen.
   Alles Rechnungen aus echten Daten; die alten Einzel-Stat-Karten sind
   damit ersetzt (.stats/.stat* bleiben im Blatt: sessions/documents/
   settings nutzen Teile weiter — nicht aufraeumen wollen). */
.dash-hello { display: grid; gap: 0.35rem; padding-top: 0.5rem; }
.dash-hello h1 { font-size: clamp(1.9rem, 3.4vw, 2.7rem); }
.hello-sub { font-size: 0.95rem; color: var(--ink-3); }

.dash-deck {
  display: grid;
  grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr);
  gap: clamp(0.9rem, 1.8vw, 1.3rem);
}
.balcard {
  position: relative;
  overflow: clip;
  display: grid;
  gap: 0.45rem;
  align-content: start;
  justify-items: start;
  padding: clamp(1.3rem, 2.6vw, 1.9rem);
  border-radius: var(--r-xl);
  background: var(--card-cool);
  box-shadow: var(--lift-3);
}
.balcard::after {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  pointer-events: none;
  background: var(--app-edge);
}
.bal-k, .last-k {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}
.bal-num {
  font-size: clamp(2.6rem, 4.4vw, 3.6rem);
  font-weight: 600;
  letter-spacing: -0.05em;
  line-height: 1;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(158deg, var(--ink) 8%, var(--blue-deep) 62%, var(--blue) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.bal-note { font-size: 0.85rem; color: var(--ink-3); }
.bal-plan {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  color: var(--ink-2);
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
}
.bal-acts { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.6rem; }

.lastcard {
  position: relative;
  overflow: clip;
  display: grid;
  gap: 0.6rem;
  align-content: start;
  padding: clamp(1.3rem, 2.6vw, 1.9rem);
  border-radius: var(--r-xl);
  background: var(--card-cool);
  box-shadow: var(--lift-1);
}
.last-title {
  font-size: clamp(1.15rem, 1.9vw, 1.45rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.2;
  color: var(--ink);
}
.last-meta { font-family: var(--mono); font-size: 0.72rem; line-height: 1.6; color: var(--ink-3); overflow-wrap: anywhere; }
.last-acts { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.5rem; }
.last-empty { display: grid; gap: 0.55rem; justify-items: start; }
#lastBody { display: grid; gap: 0.55rem; justify-items: start; }

/* Das Zahlenband der Startseite, im Portal-Mass: volle Breite, kein
   Riesenabstand darunter. */
.dash-figs { max-width: none; margin-bottom: 0; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.dash-figs li { min-width: 0; }
.dash-figs .fig, .dash-figs .fig-l { max-width: 100%; overflow-wrap: anywhere; }

@media (max-width: 900px) {
  .dash-deck { grid-template-columns: 1fr; }
}

/* ---------- Hinweiskarten (Guthaben, Plan-Wahl) ---------------------------- */
.fuel {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  flex-wrap: wrap;
  padding: 0.95rem 1.1rem;
  border-radius: var(--r-md);
  background: linear-gradient(180deg, #FFFDF9, color-mix(in srgb, var(--amber) 13%, #fff));
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset,
              0 0 0 1px color-mix(in srgb, var(--amber) 42%, transparent),
              0 12px 26px -20px rgba(184, 147, 63, 0.5);
}
/* Die Plan-Wahl ist keine Warnung — sie traegt blau. */
#planIntentBanner {
  background: linear-gradient(180deg, #FDFEFF, color-mix(in srgb, var(--blue) 8%, #fff));
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset,
              0 0 0 1px color-mix(in srgb, var(--blue) 22%, transparent),
              0 12px 26px -20px rgba(36, 86, 232, 0.4);
}
.fuel-ic {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 11px;
  color: var(--ink-2);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
}
.fuel-ic svg { width: 18px; height: 18px; fill: none; stroke: currentColor; }
.fuel-text { display: grid; gap: 0.1rem; min-width: 200px; flex: 1; }
.fuel-text b { font-size: 0.94rem; font-weight: 580; color: var(--ink); }
.fuel-text span { font-size: 0.85rem; color: var(--ink-2); }

/* ---------- Der Einstieg (Checkliste) -------------------------------------- */
.onboard { /* traegt .app-panel — nur der Inhalt ist eigen */ }
.onboard-count {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  color: var(--blue);
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--blue) 9%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 16%, transparent);
}
.onboard-list { display: grid; gap: 0.65rem; }
.onboard-item {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.75rem 0.9rem;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px var(--edge);
}
.onboard-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  color: #fff;
  box-shadow: inset 0 0 0 1.6px var(--edge-strong);
}
.onboard-item.is-done .onboard-mark {
  background: linear-gradient(180deg, #3563EE, var(--blue));
  box-shadow: 0 4px 10px -6px rgba(36, 86, 232, 0.7);
}
.onboard-mark svg { width: 13px; height: 13px; fill: none; stroke: currentColor; }
.onboard-text { display: grid; gap: 0.08rem; min-width: 0; flex: 1; }
.onboard-text b { font-size: 0.9rem; font-weight: 570; color: var(--ink); }
.onboard-text span { font-size: 0.82rem; color: var(--ink-3); }
.onboard-item.is-done .onboard-text b { color: var(--ink-3); }
.onboard-cta { flex: none; }

/* ---------- Wochenaktivitaet ------------------------------------------------ */
.chart-total { font-size: 1.05rem; font-weight: 620; letter-spacing: -0.03em; color: var(--ink); font-variant-numeric: tabular-nums; }
.chart-total small { font-size: 0.72rem; font-weight: 500; color: var(--ink-3); }
.chart-toggle {
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding: 0.34rem 0.7rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease);
}
.chart-toggle:hover { background: #fff; color: var(--ink); }
.chart-wrap { position: relative; }
.chart-svg svg { display: block; width: 100%; height: auto; }
.cx-grid { stroke: var(--edge-strong); stroke-width: 1; }
.cx-tick, .cx-label {
  font-family: var(--mono);
  font-size: 10px;
  fill: var(--ink-3);
}
.cx-bar { fill: var(--blue); }
.cx-bar-empty { fill: color-mix(in srgb, var(--blue) 14%, transparent); }
.cx-hit { fill: transparent; cursor: default; outline: none; }
.cx-hit:focus-visible { fill: color-mix(in srgb, var(--blue) 7%, transparent); }
.chart-tip {
  position: absolute;
  display: grid;
  justify-items: center;
  gap: 0.05rem;
  padding: 0.4rem 0.7rem;
  border-radius: var(--r-sm);
  background: #fff;
  box-shadow: var(--lift-2);
  pointer-events: none;
  white-space: nowrap;
}
.chart-tip .num, .chart-table .num { font-weight: 640; color: var(--ink); font-variant-numeric: tabular-nums; }
.chart-tip span:last-child { font-size: 0.72rem; color: var(--ink-3); }
.chart-table table { width: 100%; border-collapse: collapse; }
.chart-table th {
  text-align: left;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--ink-3);
  padding: 0.4rem 0.75rem;
}
.chart-table td { padding: 0.5rem 0.75rem; font-size: 0.9rem; color: var(--ink-2); }
/* Zebra-Toenung statt Zeilenlinien — Flaechen, keine Striche. */
.chart-table tbody tr:nth-child(odd) td { background: color-mix(in srgb, var(--blue) 4%, #fff); }
.chart-table tbody tr:first-child td:first-child { border-top-left-radius: 8px; }
.chart-table tbody tr:first-child td:last-child { border-top-right-radius: 8px; }
.chart-table td.num, .chart-table th:last-child { text-align: right; }
.chart-note { font-size: 0.85rem; color: var(--ink-3); margin-top: 0.6rem; }

/* Live-Zeichen: pulsierender Punkt; „is-hit" leuchtet kurz auf, wenn wirklich
   etwas angekommen ist. */
.live-dot {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  padding: 0.3rem 0.65rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 0 0 1px var(--edge);
  transition: color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}
.live-dot i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cyan);
  animation: live-pulse 2.2s var(--ease) infinite;
}
@keyframes live-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cyan) 45%, transparent); }
  55%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--cyan) 0%, transparent); }
}
.live-dot.is-hit {
  color: #10707E;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 40%, transparent);
}

/* ---------- Sitzungen ------------------------------------------------------ */
.sess-list { display: grid; gap: 0.65rem; }
.sess-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: inset 0 0 0 1px var(--edge);
  transition: box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.sess-row:hover { background: #fff; box-shadow: inset 0 0 0 1px var(--edge-strong), 0 10px 24px -18px rgba(22, 41, 94, 0.3); }
.sess-open {
  flex: 1 1 0;
  min-width: 0;
  display: grid;
  gap: 0.12rem;
  text-align: left;
  cursor: pointer;
}
.sess-title {
  font-size: 0.93rem;
  font-weight: 570;
  letter-spacing: -0.015em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sess-meta {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sess-right { display: flex; align-items: center; gap: 0.4rem; flex: none; }
.sess-review { flex: none; }
.sess-del {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  color: var(--ink-3);
  transition: color 0.22s var(--ease), background-color 0.22s var(--ease);
}
.sess-del:hover { color: #8A1F1F; background: rgba(192, 57, 43, 0.08); }
.sess-del svg { width: 16px; height: 16px; fill: none; stroke: currentColor; }
.sess-note { font-size: 0.9rem; color: var(--ink-3); }
.sess-more { font-size: 0.82rem; color: var(--ink-3); margin-top: 0.7rem; }

/* Auswahlmodus — die ganze Zeile ist das Ziel, wie in der App. */
.sess-row.is-selectable { cursor: pointer; }
.sess-box {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 7px;
  color: #fff;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 1.6px var(--edge-strong);
  transition: background-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.sess-box svg { width: 13px; height: 13px; opacity: 0; }
.sess-row.is-selected { background: color-mix(in srgb, var(--blue) 7%, #fff); box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--blue) 45%, transparent); }
.sess-row.is-selected .sess-box { background: var(--blue); box-shadow: inset 0 0 0 1.6px var(--blue); }
.sess-row.is-selected .sess-box svg { opacity: 1; }
.select-actions { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }

.dash-empty {
  display: grid;
  justify-items: center;
  gap: 0.7rem;
  padding: clamp(1.6rem, 3.5vw, 2.6rem) 1rem;
  text-align: center;
}
.dash-empty .ic {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  color: var(--blue);
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--blue) 13%, #fff),
    color-mix(in srgb, var(--cyan) 11%, #fff));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9),
              inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent);
}
.dash-empty .ic svg { width: 20px; height: 20px; fill: none; stroke: currentColor; }
.dash-empty p { max-width: 46ch; font-size: 0.9rem; line-height: 1.55; color: var(--ink-3); }

/* ---------- Kleinkram ------------------------------------------------------ */
.dash-hint { font-size: 0.83rem; line-height: 1.55; color: var(--ink-3); margin-top: 0.9rem; text-wrap: pretty; }
.dash-hint a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }
.field-hint { font-size: 0.8rem; color: var(--ink-3); }
.has-toggle { /* Altname aus den Formularen — das Polster regelt :has() im Anmeldeblock */ }

.btn-sm { padding: 0.48rem 0.9rem; font-size: 0.84rem; }
.btn-danger {
  color: #fff;
  background: linear-gradient(180deg, #D4574A, #C0392B 60%);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.25) inset,
              0 10px 22px -12px rgba(192, 57, 43, 0.6);
}
.btn-danger:hover { box-shadow: 0 1px 0 rgba(255,255,255,0.3) inset, 0 14px 28px -12px rgba(192, 57, 43, 0.7); }
.btn-danger-ghost {
  color: #8A1F1F;
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px rgba(192, 57, 43, 0.3);
}
.btn-danger-ghost:hover { background: #FDF2F2; }

/* ---------- Dokumente ------------------------------------------------------ */
.drop {
  display: grid;
  justify-items: center;
  gap: 0.5rem;
  padding: clamp(1.6rem, 3.4vw, 2.4rem) 1rem;
  border-radius: var(--r-md);
  text-align: center;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.6);
  /* Gestrichelt UM die ganze Flaeche — ein Umriss, keine Trennlinie. */
  outline: 1.6px dashed var(--edge-strong);
  outline-offset: -8px;
  transition: background-color 0.25s var(--ease), outline-color 0.25s var(--ease);
}
.drop:hover { background: rgba(255, 255, 255, 0.9); }
.drop.is-over { background: color-mix(in srgb, var(--blue) 6%, #fff); outline-color: color-mix(in srgb, var(--blue) 55%, transparent); }
.drop.is-full { cursor: default; background: color-mix(in srgb, var(--amber) 9%, #fff); outline-color: color-mix(in srgb, var(--amber) 50%, transparent); }
.drop-ic {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  color: var(--blue);
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--blue) 13%, #fff),
    color-mix(in srgb, var(--cyan) 11%, #fff));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.9),
              inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent);
}
.drop-ic svg { width: 20px; height: 20px; fill: none; stroke: currentColor; }
.drop-title { font-size: 0.95rem; font-weight: 560; color: var(--ink); }
.drop-title u { text-decoration-color: var(--blue); text-underline-offset: 3px; }
.drop-sub { font-size: 0.8rem; color: var(--ink-3); }
.upload-progress {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 0.9rem;
  font-size: 0.88rem;
  color: var(--ink-2);
}

.doc-rows { display: grid; gap: 0.65rem; }
.doc-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  padding: 0.7rem 0.85rem;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: inset 0 0 0 1px var(--edge);
  transition: box-shadow 0.25s var(--ease), background-color 0.25s var(--ease);
}
.doc-row:hover { background: #fff; box-shadow: inset 0 0 0 1px var(--edge-strong), 0 10px 24px -18px rgba(22, 41, 94, 0.3); }
.doc-file-ic {
  flex: none;
  display: grid;
  place-items: center;
  min-width: 44px;
  height: 34px;
  padding-inline: 0.4rem;
  border-radius: 9px;
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--blue-deep);
  background: color-mix(in srgb, var(--blue) 9%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 16%, transparent);
}
.doc-main { flex: 1 1 0; min-width: 0; display: grid; gap: 0.12rem; }
.doc-name-row { display: flex; align-items: center; gap: 0.5rem; min-width: 0; }
.doc-name {
  font-size: 0.93rem;
  font-weight: 570;
  letter-spacing: -0.015em;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.doc-src {
  flex: none;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #10707E;
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--cyan) 16%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 30%, transparent);
}
.doc-meta {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.doc-actions { display: flex; align-items: center; gap: 0.4rem; flex: none; }

.doc-list { display: grid; gap: 0.85rem; }
.doc-list li { display: flex; align-items: flex-start; gap: 0.7rem; }
.doc-list b { display: block; font-size: 0.9rem; font-weight: 570; color: var(--ink); }
.doc-list span:not(.doc-ic) { font-size: 0.85rem; line-height: 1.55; color: var(--ink-3); }
.doc-ic {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  margin-top: 0.1rem;
}
.doc-ic svg { width: 13px; height: 13px; fill: none; stroke: currentColor; }
.doc-ic.ok {
  color: var(--blue);
  background: color-mix(in srgb, var(--blue) 10%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 18%, transparent);
}
.doc-ic.pending {
  color: #8A6A1F;
  background: color-mix(in srgb, var(--amber) 18%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--amber) 36%, transparent);
}

/* ---------- Konto ----------------------------------------------------------- */
.account-meta { display: grid; gap: 0.45rem; margin-top: 1.1rem; }
.account-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 0 0 1px var(--edge);
}
.account-row .k {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.account-row .v { font-size: 0.9rem; font-weight: 540; color: var(--ink); min-width: 0; overflow-wrap: anywhere; text-align: right; }
.role-pill {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  padding: 0.26rem 0.6rem;
  border-radius: 999px;
}
.role-user {
  color: var(--blue-deep);
  background: color-mix(in srgb, var(--blue) 9%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 16%, transparent);
}
.role-unlimited {
  color: #10707E;
  background: color-mix(in srgb, var(--cyan) 16%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 30%, transparent);
}
.dev-forget { flex: none; }
.panel-danger { box-shadow: 0 0 0 1px rgba(192, 57, 43, 0.22), var(--lift-1); }

/* ---------- Der Leser (Transkript + Dokumentvorschau) ---------------------- */
.reader-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: clamp(0.8rem, 2.5vw, 2rem);
  background: rgba(13, 18, 32, 0.44);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.reader-panel {
  display: flex;
  flex-direction: column;
  width: min(100%, 860px);
  max-height: min(88svh, 900px);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: #fff;
  box-shadow: var(--lift-3);
}
.reader-head {
  display: grid;
  gap: 0.7rem;
  padding: 1.1rem clamp(1rem, 2.5vw, 1.5rem) 0.9rem;
  background: linear-gradient(180deg, #FFFFFF, #F8FAFD);
}
.reader-head-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.8rem; }
.reader-title { font-size: 1.05rem; font-weight: 620; letter-spacing: -0.025em; color: var(--ink); }
.reader-sub { font-family: var(--mono); font-size: 0.68rem; color: var(--ink-3); margin-top: 0.15rem; }
.reader-actions { display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap; }
.reader-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  font-size: 0.84rem;
  font-weight: 550;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
  transition: background-color 0.22s var(--ease);
}
.reader-btn:hover { background: #fff; }
.reader-btn:disabled { opacity: 0.5; cursor: default; }
.reader-btn svg { width: 15px; height: 15px; fill: none; stroke: currentColor; }
.reader-btn-primary {
  color: #fff;
  background: linear-gradient(180deg, #3563EE, var(--blue) 55%, #1C46CE);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.28) inset, 0 10px 22px -12px rgba(36, 86, 232, 0.6);
}
.reader-btn-primary:hover { background: linear-gradient(180deg, #3D6AF2, var(--blue) 55%, #1C46CE); }
.reader-close {
  margin-left: auto;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 9px;
  color: var(--ink-3);
  transition: color 0.22s var(--ease), background-color 0.22s var(--ease);
}
.reader-close:hover { color: var(--ink); background: color-mix(in srgb, var(--blue) 8%, transparent); }
.reader-close svg { width: 16px; height: 16px; fill: none; stroke: currentColor; }
.reader-body {
  flex: 1;
  overflow-y: auto;
  padding: clamp(1rem, 2.5vw, 1.5rem);
  display: grid;
  gap: 1rem;
  align-content: start;
  background: var(--paper);
}
.reader-body.is-frame { padding: 0; display: block; }
.reader-note { font-size: 0.9rem; color: var(--ink-3); }
.docprev-frame { display: block; width: 100%; height: 72svh; border: 0; }
.docprev-text {
  white-space: pre-wrap;
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--ink-2);
  max-width: 72ch;
}

/* Ein Austausch: Frage, gesprochene Antwort, Supace-Antwort. */
.rx { display: grid; gap: 0.5rem; }
.rx-block {
  padding: 0.85rem 1rem;
  border-radius: var(--r-md);
  display: grid;
  gap: 0.3rem;
}
.rx-block p { font-size: 0.92rem; line-height: 1.6; color: var(--ink-2); }
.rx-label {
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.rx-q { background: color-mix(in srgb, var(--blue) 6%, #fff); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 13%, transparent); }
.rx-you { background: rgba(255, 255, 255, 0.85); box-shadow: inset 0 0 0 1px var(--edge); }
.rx-ai { background: color-mix(in srgb, var(--cyan) 7%, #fff); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 20%, transparent); }
.rx-ai .rx-label { color: #10707E; }
.rx-time { font-family: var(--mono); font-size: 0.64rem; color: var(--ink-3); }

/* Die ANTWORT im Leser: `answerHtml()` liefert einen Vorspann und eine
   Punktliste (`<p class="intro">` + `<ul><li>`), Hervorhebungen als
   `<span class="ans-kw">`. Diese vier Regeln standen im alten `auth.css`
   und sind beim Umzug des Portals auf v4.css nicht mitgekommen — die Liste
   lief danach in der Browser-Grundeinstellung (40 px Einzug, fremde
   Schriftgroesse). `check-v4.py` faengt das NICHT: die Klassen entstehen
   im JavaScript, geprueft wird das HTML. */
.rx-ai .intro { font-size: 0.92rem; line-height: 1.62; color: var(--ink-2); margin: 0 0 0.5rem; }
.rx-ai ul { margin: 0; padding-left: 1.15rem; }
.rx-ai li { font-size: 0.92rem; line-height: 1.6; color: var(--ink-2); margin-bottom: 0.4rem; }
.rx-ai li:last-child { margin-bottom: 0; }
.rx-ai li::marker { color: var(--blue); }
/* Die Hervorhebung bleibt IM Satz — `display: inline` ist hier kein
   Schmuck, sondern die Absicherung gegen genau die Kollision oben. */
.ans-kw { display: inline; font-weight: 650; color: var(--blue-deep); }

/* ---------- Bestaetigungsdialoge ------------------------------------------- */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: grid;
  place-items: center;
  padding: 1rem;
  background: rgba(13, 18, 32, 0.44);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.modal-card {
  position: relative;
  width: min(100%, 440px);
  padding: clamp(1.3rem, 3vw, 1.7rem);
  border-radius: var(--r-lg);
  background: #fff;
  box-shadow: var(--lift-3);
}
.modal-card h3 { font-size: 1.08rem; font-weight: 620; letter-spacing: -0.02em; color: var(--ink); padding-right: 2rem; }
.modal-card p { margin-top: 0.55rem; font-size: 0.9rem; line-height: 1.6; color: var(--ink-2); }
.modal-x {
  position: absolute;
  top: 0.9rem;
  right: 0.9rem;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 9px;
  color: var(--ink-3);
  transition: color 0.22s var(--ease), background-color 0.22s var(--ease);
}
.modal-x:hover { color: var(--ink); background: color-mix(in srgb, var(--blue) 8%, transparent); }
.modal-x svg { width: 15px; height: 15px; fill: none; stroke: currentColor; }
.modal-actions { display: flex; justify-content: flex-end; gap: 0.5rem; margin-top: 1.2rem; flex-wrap: wrap; }

/* ---------- Schmale Fenster ------------------------------------------------
   ≤780 px: die Leiste wird zur Schublade (dashboard.js erzeugt Knopf+Schleier). */
.sb-mobile-toggle { display: none; }
.sb-scrim { display: none; }
@media (max-width: 900px) {
  .stats { grid-template-columns: 1fr; }
  .app-two { grid-template-columns: 1fr; }
}
@media (max-width: 780px) {
  .app-shell { grid-template-columns: 1fr; }
  .sb {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 90;
    width: min(84vw, 300px);
    translate: -105% 0;
    transition: translate 0.35s var(--spring);
    box-shadow: 24px 0 60px -30px rgba(13, 18, 32, 0.4);
  }
  html[data-mobilenav="open"] .sb { translate: 0 0; }
  /* Eingeklappt gibt es auf dem Telefon nicht — die Schublade ist immer voll. */
  html[data-sidebar="collapsed"] .sb-brand span,
  html[data-sidebar="collapsed"] .sb-item span,
  html[data-sidebar="collapsed"] .sb-user-meta { display: revert; }
  html[data-sidebar="collapsed"] .sb-item { justify-content: flex-start; padding-inline: 0.7rem; }
  .sb-collapse { display: none; }
  .sb-scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 85;
    background: rgba(13, 18, 32, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s var(--ease);
  }
  html[data-mobilenav="open"] .sb-scrim { opacity: 1; pointer-events: auto; }
  .sb-mobile-toggle {
    display: grid;
    place-items: center;
    position: fixed;
    top: 0.8rem;
    left: 0.8rem;
    z-index: 80;
    width: 40px;
    height: 40px;
    border-radius: 12px;
    color: var(--ink);
    background: rgba(255, 255, 255, 0.8);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    box-shadow: 0 0 0 1px var(--edge-strong), 0 10px 24px -16px rgba(13, 18, 32, 0.45);
  }
  .sb-mobile-toggle svg { width: 18px; height: 18px; }
  .topbar-banner { margin-inline: var(--pad); margin-top: 3.6rem; }
  .reader-overlay { padding: 0.5rem; }
  .reader-panel { max-height: 94svh; }
}

/* ══════════════════════════════════════════════════════════════════════════
   OPERATIONS — admin.html (24.08.2026), nur fuer den Operator sichtbar.
   --------------------------------------------------------------------------
   Neu geschnitten auf „ein Blick, dann handeln": Zahlenband → Auffaelliges →
   die Konten-Tabelle MIT Handhabe (Ban/Unban) → die Verlaufscharts → das
   Jahr. Die Bann-Kette: adminActions.js (Oberflaeche + /api/admin-user-
   Aufrufe) haengt sich ueber adminUsage.setRowAction() an die Tabelle; die
   eigentliche Sperre setzt die Cloudflare Function mit dem Secret, nachdem
   sie den Aufrufer GEGEN DIE DATENBANK als admin verifiziert hat.
   Chart-Klassen (cx-*) malt adminUsage.js in SVG — cx-bar/-grid/-tick/-label
   sind schon vom Wochendiagramm definiert, hier kommen nur die Zusaetze.
   ══════════════════════════════════════════════════════════════════════════ */

.op-filters { display: flex; align-items: center; gap: 0.4rem; flex-wrap: wrap; }
.range-btn {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding: 0.42rem 0.85rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
  transition: background-color 0.22s var(--ease), color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.range-btn:hover { background: #fff; color: var(--ink); }
.range-btn.is-active {
  color: #fff;
  background: var(--blue);
  box-shadow: 0 6px 14px -8px rgba(36, 86, 232, 0.8);
}
.range-select {
  font: inherit;
  font-size: 0.84rem;
  color: var(--ink-2);
  padding: 0.42rem 0.7rem;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.75);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
  cursor: pointer;
}
.scope-line { font-size: 0.85rem; color: var(--ink-3); display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; }
.scope-line b { color: var(--ink); font-weight: 570; }
.scope-reset {
  font-size: 0.82rem;
  color: var(--blue);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Das Zahlenband der Startseite in der Operations-Teilung. */
.figs-op { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.figs-op-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.fig-mail { font-size: clamp(0.95rem, 1.4vw, 1.15rem); letter-spacing: -0.02em; overflow-wrap: anywhere; }

/* Auffaelligkeiten: eine Karte je Fund, Grad ueber Farbe — Bernstein heisst
   „ansehen", Rot heisst „handeln". Gruen gibt es nicht: kein Fund = die
   Liste sagt es in einem Satz. */
.flag-list { display: grid; gap: 0.5rem; }
.flag {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r-md);
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink-2);
}
.flag svg { width: 17px; height: 17px; flex: none; margin-top: 0.1rem; fill: none; stroke: currentColor; }
.flag b { font-weight: 580; color: var(--ink); }
.flag-warning {
  background: linear-gradient(180deg, #FFFDF9, color-mix(in srgb, var(--amber) 12%, #fff));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--amber) 40%, transparent);
}
.flag-warning svg { color: #8A6A1F; }
.flag-serious {
  background: #FDF2F2;
  box-shadow: inset 0 0 0 1px rgba(192, 57, 43, 0.28);
}
.flag-serious svg { color: #C0392B; }
.flag-level {
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.alert-detail { font-size: 0.8rem; color: var(--ink-3); }

/* Die Konten-Tabelle: breit, deshalb in einer eigenen Scrollflaeche — die
   SEITE scrollt nie seitlich. Zebra statt Linien, wie die Wochentabelle. */
.admin-scroll { min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; }
.admin-table table { min-width: 980px; }
.admin-table th { white-space: nowrap; position: sticky; top: 0; background: linear-gradient(180deg, #FFFFFF, #F8FAFD); }
.admin-table td { white-space: nowrap; font-variant-numeric: tabular-nums; }
.admin-table td:first-child { max-width: 240px; overflow: hidden; text-overflow: ellipsis; }
.admin-table td.act, .admin-table th.act { text-align: right; }
.act-you {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}
/* Gesperrte Zeile: rot getoent — der Zustand ist beim Ueberfliegen lesbar,
   nicht erst am Knopf. */
tr.is-banned td { background: #FDF2F2 !important; color: var(--ink-3); }
.ban-badge {
  display: inline-block;
  margin-left: 0.5rem;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #8A1F1F;
  padding: 0.16rem 0.45rem;
  border-radius: 999px;
  background: rgba(192, 57, 43, 0.1);
  box-shadow: inset 0 0 0 1px rgba(192, 57, 43, 0.25);
}

.user-search {
  font: inherit;
  font-size: 0.88rem;
  color: var(--ink);
  width: min(100%, 260px);
  padding: 0.52rem 0.9rem;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: inset 0 0 0 1px var(--edge-strong);
}
.user-search::placeholder { color: var(--ink-4); }
.user-search:focus {
  outline: none;
  background: #fff;
  box-shadow: inset 0 0 0 1.5px var(--blue), 0 0 0 4px color-mix(in srgb, var(--blue) 15%, transparent);
}
.app-panel-hint { font-size: 0.8rem; color: var(--ink-3); }

/* Zusaetze der Operations-Charts (Basis-cx-* kommt vom Wochendiagramm). */
.cx-legend { display: flex; gap: 1rem; flex-wrap: wrap; margin-bottom: 0.6rem; }
.cx-legend-item { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.8rem; color: var(--ink-2); }
.cx-legend-dot { width: 9px; height: 9px; border-radius: 3px; }
.cx-rowlabel, .cx-value { font-family: var(--mono); font-size: 10px; fill: var(--ink-3); }
.cx-value { fill: var(--ink-2); }
.cx-hit-clickable { cursor: pointer; }
@media (max-width: 900px) {
  .figs-op, .figs-op-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Der sprechende Fehler statt des ewigen Spinners (siehe die Wache in den
   Portalseiten). Bewusst ruhig: es ist eine Auskunft, kein Alarm. */
.boot-fail {
  display: grid;
  justify-items: center;
  gap: 0.6rem;
  max-width: 46ch;
  padding: clamp(1.4rem, 3vw, 2rem);
  border-radius: var(--r-lg);
  text-align: center;
  background: var(--card-cool);
  box-shadow: var(--lift-1);
}
.boot-fail b { font-size: 1rem; font-weight: 600; color: var(--ink); }
.boot-fail p { font-family: var(--mono); font-size: 0.75rem; line-height: 1.6; color: var(--ink-3); overflow-wrap: anywhere; }

/* ══════════════════════════════════════════════════════════════════════════
   FRAGENSAMMLUNG & VORBEREITUNGSBLAETTER (24.08.2026)
   --------------------------------------------------------------------------
   Zwei Seiten fuer Daten, die die DESKTOP-APP laengst in die Cloud schreibt
   (`bookmarked_questions`, `prep_sheets`) und die das Web-Portal bis heute
   nie gezeigt hat. Nichts davon ist neu erfunden — es wird sichtbar gemacht.
   Die Fragen benutzen die FAQ-Fassung der Schauseiten (`.faq-item`): eine
   Frage, die man aufklappt, ist auf dieser Website ueberall dasselbe Ding.
   ══════════════════════════════════════════════════════════════════════════ */

.qa-list { display: grid; gap: 0.4rem; }
/* `.faq-item` bringt Rahmen, Aufklappzeichen und den Kartenzustand mit;
   hier kommen nur die Masse des Portals dazu. */
.qa-item summary { align-items: flex-start; gap: 0.9rem; }
.qa-q { font-size: 0.97rem; font-weight: 560; letter-spacing: -0.015em; color: var(--ink); text-wrap: pretty; }
.qa-item .faq-ic { margin-top: 0.35rem; }
.qa-a {
  font-size: 0.93rem;
  line-height: 1.65;
  color: var(--ink-2);
  max-width: 78ch;
  white-space: pre-wrap;      /* die Antwort kommt mit eigenen Umbruechen */
  text-wrap: pretty;
}
.qa-none { color: var(--ink-3); font-style: italic; }
.qa-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin-top: 1rem;
}
.qa-date { font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.04em; color: var(--ink-3); }

/* ---------- Vorbereitungsblaetter ----------------------------------------
   Ein Blatt = eine Karte mit bis zu vier Rubriken. Leere Rubriken werden gar
   nicht gezeichnet (das Skript ueberspringt sie) — eine leere Ueberschrift
   waere ein Versprechen ohne Inhalt. */
.prep-cards { display: grid; gap: clamp(0.9rem, 1.8vw, 1.3rem); }
.prep-card {
  min-width: 0;
  padding: clamp(1.1rem, 2.2vw, 1.5rem);
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.8);
  box-shadow: inset 0 0 0 1px var(--edge);
}
.prep-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.8rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.prep-date { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.05em; color: var(--ink-3); }
.prep-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: clamp(1rem, 2vw, 1.6rem);
}
.prep-col { min-width: 0; display: grid; gap: 0.5rem; align-content: start; }
.prep-k {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--blue);
}
.prep-list { display: grid; gap: 0.45rem; }
.prep-list li {
  display: grid;
  grid-template-columns: 6px minmax(0, 1fr);
  gap: 0.6rem;
  align-items: start;
  font-size: 0.9rem;
  line-height: 1.55;
  color: var(--ink-2);
  text-wrap: pretty;
}
/* Ein Punkt, kein Strich — Aufzaehlungen tragen auf dieser Website nie eine
   Linie vor sich her. */
.prep-list li::before {
  content: "";
  width: 5px;
  height: 5px;
  margin-top: 0.55rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--blue) 45%, transparent);
}

/* ---------- „What they ask" (24.08.2026) ----------------------------------
   Wiederkehrende Fragen aus den eigenen Transkripten. Die Eintraege sind
   dieselbe FAQ-Fassung wie die Fragensammlung; dazu die Haeufigkeit als
   Zaehler am Kopf und die verschiedenen Wortlaute als Beleg darunter. */
.ask-n {
  margin-left: auto;
  flex: none;
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--blue-deep);
  padding: 0.22rem 0.55rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--blue) 10%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 18%, transparent);
  white-space: nowrap;
}
/* Die Fragen-Kachel hat den Zaehler VOR dem Aufklappzeichen — `.faq-ic` holt
   sich seinen Platz sonst per `margin-left: auto` und schoebe ihn weg. */
.qa-item summary .faq-ic { margin-left: 0.7rem; }
.ask-vars { margin-top: 0.9rem; }
.ask-all { margin-top: 0.2rem; }
.ask-all li { font-size: 0.89rem; }

/* ---------- Der Abgleich: traf die Vorbereitung zu? (24.08.2026) ----------
   Auf einem Vorbereitungsblatt bekommt JEDE erwartete Frage eine Marke,
   wenn sie in einem spaeteren Interview wirklich gestellt wurde — samt dem
   echten Wortlaut als Beleg. Das kann sonst niemand, weil niemand beide
   Seiten hat: die Vorhersage UND das Transkript.
   Kein Rot fuer „kam nicht vor": eine nicht gestellte Frage ist kein Fehler,
   sie ist nur nicht drangekommen. Nur der Treffer wird markiert. */
.hit-band {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 1.1rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.7);
  box-shadow: inset 0 0 0 1px var(--edge);
}
.hit-band.is-hit {
  background: color-mix(in srgb, var(--cyan) 8%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 26%, transparent);
}
.hit-n {
  font-size: 1.05rem;
  font-weight: 640;
  letter-spacing: -0.02em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.hit-band.is-hit .hit-n { color: #0F6B79; }
.hit-t { font-size: 0.86rem; line-height: 1.5; color: var(--ink-2); }

/* Eine erwartete Frage in der Liste. `.prep-list li` gibt den Punkt davor;
   hier kommt nur der Zustand dazu. */
.prep-list li.hit-yes,
.prep-list li.hit-no { align-items: start; }
.prep-list li.hit-yes::before { background: var(--cyan); }
.hit-q { display: block; }
.prep-list li.hit-no .hit-q { color: var(--ink-3); }
.hit-mark {
  display: inline-block;
  margin-top: 0.25rem;
  font-family: var(--mono);
  font-size: 0.56rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #0F6B79;
  padding: 0.18rem 0.5rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--cyan) 16%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--cyan) 30%, transparent);
}
/* Der echte Wortlaut aus dem Transkript — der Beleg, dass der Abgleich eine
   Fundstelle ist und keine Behauptung. */
.hit-real {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--ink-3);
  text-wrap: pretty;
}

/* ---------- Rangliste, Sprachwahl, Ausblenden (25.08.2026) ----------------
   Uejs: Ranking der haeufigsten Fragen, Filter je Sprache, und die Liste
   aufraeumen koennen. Die Rangzahl traegt KEINE fuehrende Null — die
   Website fuehrt keine 01/02/03-Nummerierung; hier ist die Zahl auch keine
   Dekoration, sondern der Platz in der Rangliste. */
.ask-bar { margin-bottom: 0.2rem; }
.ask-lang { display: inline-flex; align-items: center; gap: 0.5rem; }
.ask-lang > span {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.ask-spacer { flex: 1; }
.ask-rank {
  flex: none;
  display: grid;
  place-items: center;
  min-width: 26px;
  height: 26px;
  padding-inline: 0.35rem;
  border-radius: 8px;
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--blue-deep);
  background: color-mix(in srgb, var(--blue) 11%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 20%, transparent);
  font-variant-numeric: tabular-nums;
}
/* Die ersten drei Plaetze tragen die Marke etwas kraeftiger — mehr
   Unterscheidung braucht eine Rangliste nicht. */
.qa-list > .qa-item:nth-child(-n+3) .ask-rank {
  color: #fff;
  background: linear-gradient(180deg, #3563EE, var(--blue) 70%);
  box-shadow: 0 4px 10px -6px rgba(36, 86, 232, 0.7);
}

/* ---------- „Everything you were asked": Zeilen mit stillen Aktionen ------
   Statt einer Aufzaehlung mit Punkten dieselbe Kartensprache wie die
   Sitzungsliste. Die zwei Aktionen liegen rechts und sind im Ruhezustand
   unsichtbar — sie treten beim Ueberfahren hervor, bei Tastaturbedienung
   beim Fokus, und auf Beruehrgeraeten (kein Hover) bleiben sie stehen.
   Der Platz ist IMMER reserviert: erschienen sie erst beim Hover im Layout,
   spraenge die Zeile unter dem Zeiger weg. */
.ask-list { display: grid; gap: 0.4rem; }
.ask-item {
  display: flex;
  align-items: center;   /* die Aktionen bleiben mittig zur GANZEN Zeile */
  gap: 0.7rem;
  padding: 0.6rem 0.7rem 0.6rem 0.9rem;
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, 0.72);
  box-shadow: inset 0 0 0 1px var(--edge);
  transition: background-color 0.22s var(--ease), box-shadow 0.22s var(--ease);
}
.ask-item:hover,
.ask-item:focus-within {
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--edge-strong), 0 8px 20px -16px rgba(22, 41, 94, 0.32);
}
.ask-text {
  flex: 1 1 0;
  min-width: 0;
  font-size: 0.89rem;
  line-height: 1.5;
  color: var(--ink-2);
  text-wrap: pretty;
}
.ask-acts {
  flex: none;
  display: flex;
  gap: 0.2rem;
  opacity: 0;
  transition: opacity 0.2s var(--ease);
}
.ask-item:hover .ask-acts,
.ask-item:focus-within .ask-acts { opacity: 1; }
@media (hover: none) { .ask-acts { opacity: 1; } }
.ask-act {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  color: var(--ink-3);
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.ask-act svg { width: 15px; height: 15px; fill: none; stroke: currentColor; }
.ask-act:hover { color: var(--ink); background: color-mix(in srgb, var(--blue) 9%, transparent); }
.ask-act-del:hover { color: #8A1F1F; background: rgba(192, 57, 43, 0.09); }
.ask-act-save:hover { color: var(--blue); background: color-mix(in srgb, var(--blue) 10%, transparent); }
/* Gespeichert: der Haken bleibt SICHTBAR, auch wenn der Zeiger die Zeile
   verlaesst — sonst waere die einzige Rueckmeldung wieder verschwunden,
   sobald man weiterliest. Deshalb hebt `.is-saved` die Ruhe-Deckkraft der
   ganzen Aktionsgruppe auf. */
.ask-act.is-saved { color: #10707E; cursor: default; }   /* dasselbe Tiefcyan wie .rx-ai .rx-label */
.ask-acts:has(.is-saved) { opacity: 1; }
.ask-act:disabled { opacity: 0.45; cursor: default; }
.ask-act.is-saved:disabled { opacity: 1; }

/* „Was nicht in der Liste steht" — dieselbe Aufklapp-Fassung wie die FAQ,
   nur ruhiger: es ist Rechenschaft, kein Angebot. Die Zeilen darin tragen
   KEINE Aktionen (sie sind ja gerade nicht in der Liste), deshalb ohne den
   reservierten Platz rechts. */
.ask-why { margin-top: 1.1rem; }
.ask-why .user-search { margin: 0.9rem 0 0.6rem; width: 100%; }
.ask-why-list { max-height: 22rem; overflow-y: auto; }
.ask-why-item {
  display: block;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--ink-2);
}

/* Eigene Frage eintragen (questions.html). Bewusst KEIN eigenes
   Feld-Vokabular: `.field` / `.input-shell` / `.field-error` sind die
   Bausteine der Anmeldeseiten und bringen Fokusring, Fehlerfarbe und
   Abstaende schon mit. Neu ist nur die Huelle. */
.qadd {
  display: grid;
  gap: 0.9rem;
  margin: 0.2rem 0 1.4rem;
  padding: 1.1rem 1.2rem 1.2rem;
  border-radius: var(--r-md);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
}
.qadd .input-shell textarea {
  font: inherit;
  width: 100%;
  padding: 0.72rem 0.9rem;
  border: none;
  border-radius: var(--r-sm);
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--edge);
  color: var(--ink);
  resize: vertical;
}
.qadd .input-shell textarea::placeholder { color: var(--ink-4); }
.qadd .input-shell textarea:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 1.5px var(--blue), 0 0 0 3.5px color-mix(in srgb, var(--blue) 16%, transparent);
}
.qadd-acts { display: flex; flex-wrap: wrap; gap: 0.6rem; }

/* „Auch gefunden in …" — der Wegweiser, wenn ein Suchtreffer ausserhalb der
   gezeigten Liste liegt. Getoent, damit er als Antwort auf die Suche liest
   und nicht als Teil der Ergebnisse. */
.ask-elsewhere {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.55rem;
  margin: 0 0 0.9rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--blue) 6%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 15%, transparent);
  color: var(--ink-2);
}
.ask-elsewhere b { color: var(--ink); font-weight: 600; }
/* Der Textblock einer Zeile: Frage oben, voller Wortlaut gedaempft darunter.
   `min-width: 0`, sonst schiebt eine lange Zeile die Aktionen hinaus (die
   Grid/Flex-Falle aus §6). Der Wortlaut ist auf EINE Zeile gekappt und
   klappt per Klick auf — die Liste bleibt eine Fragenliste, aber jede
   Zeile ist als das wiederzuerkennen, was wirklich gesagt wurde. */
.ask-main { display: grid; gap: 0.18rem; min-width: 0; flex: 1; }
/* Der volle Wortlaut haengt an einer MARKE, nicht an einem Tooltip:
   Ueberfahren blendet ihn ein, Klick haelt ihn fest. Ein reiner
   title-Tooltip war der Zustand, in dem eine Frage fuenfmal nicht
   wiedererkannt wurde — und auf Beruehrgeraeten gibt es kein Ueberfahren. */
.ask-ctx { display: grid; gap: 0.15rem; justify-items: start; }
.ask-ctx-mark {
  font-family: var(--mono);
  font-size: 0.6rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: none;
  border: none;
  padding: 0.1rem 0;
  cursor: pointer;
  transition: color 0.18s var(--ease);
}
.ask-ctx-mark:hover,
.ask-ctx.is-open .ask-ctx-mark { color: var(--blue); }
.ask-ctx-text {
  display: none;
  font-size: 0.8rem;
  line-height: 1.55;
  color: var(--ink-3);
}
/* Ueberfahren zeigt ihn fluechtig, Klick dauerhaft. Beide Wege fuehren zum
   selben Ergebnis — die Maus ist der schnelle, der Klick der verlaessliche. */
/* In der Fragensammlung sitzt die Marke in einer Karte statt in einer
   Listenzeile — sie braucht nur etwas Luft nach oben. */
.qa-ctx { margin-top: 0.5rem; }
/* Fehlermeldung ueber den Preiskarten. Nutzt `.auth-alert` (Rot ist auf
   den Schauseiten sonst verboten — eine gescheiterte Zahlung ist die
   Ausnahme, in der eine Warnfarbe traegt, genau wie ein Formularfehler)
   und braucht hier nur Breite und Abstand. */
.buy-alert { max-width: 640px; margin: 0 auto 1.2rem; }

/* Rechtslinks am Fuss der Portal-Seitenleiste. Klein und zurueckhaltend —
   eine Pflichtangabe, die erreichbar sein muss, aber nichts anbietet. */
/* ---------- DOKUMENTSEITEN (Legal, 25.08.2026) --------------------------
   Acht Seiten (vier Sprachen-Paare) tragen lange Rechtstexte. Kein
   Himmelsband, kein Produktbild — die Seite SELBST ist der Inhalt, jede
   Dekoration waere Ablenkung, nicht Schmuck.
   Kopf UND Koerper LINKSBUENDIG: dieselbe Ausnahme von Regel 9e wie die
   FAQ — bei langem Fliesstext sucht das Auge sonst bei jeder Zeile neu
   den Anfang. Eine mittige Ueberschrift ueber linksbuendigem Text waere
   hier vertretbar, aber der Vorspann selbst ist schon mehrzeilig; mittig
   heisst dann eine schmale Rinne mitten auf der Seite. */
main > section.doctop {
  /* Der Kopf ist FIXIERT (`.hdr { position: fixed }`) und legt sich ueber
     den Seitenanfang — jede erste Sektion unter ihm braucht dieselbe
     Freiflaeche wie `.hero` (7,5rem-11rem), sonst liegt die Ueberschrift
     unter dem Glasband. GENAU DAS war der Fehler: 3rem waren zu wenig,
     die Seite "sah komisch aus" (Uejs, 25.08.2026) — die Kopfzeile
     ueberlagerte den Titel. */
  padding-top: clamp(7.5rem, 15vh, 11rem);
  padding-bottom: clamp(1.4rem, 3vw, 2.2rem);
}
main > section.docbody {
  padding-block: 0 clamp(4rem, 8vw, 6rem);
}
/* Die SPALTE sitzt mittig, der TEXT bleibt linksbuendig — dieselbe
   Kombination wie die FAQ der Startseite (Regel 9e): bei 1470 px Fenster
   klebte die 680-px-Spalte sonst am linken Rand, und rechts lag ein
   Drittel der Seite leer. Im Screenshot gesehen. */
.dochead { max-width: 880px; margin-inline: auto; display: grid; gap: 0.75rem; }
.dochead h1 { font-size: clamp(2rem, 4.2vw, 2.85rem); margin: 0; }
.doclede { font-size: 1.05rem; line-height: 1.65; color: var(--ink-3); }
/* Welche Sprachfassung massgeblich ist — eine Angabe, kein Haftungsausschluss.
   Direkt unter der Ueberschrift, damit sie vor jedem Absatz gelesen wird. */
.doclang {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.7rem;
  font-size: 0.85rem;
}
.doclang a { color: var(--blue); font-weight: 560; text-decoration: underline; text-underline-offset: 3px; }
.doclang span { color: var(--ink-4); }

/* ⚠ ZWEI FEHLER NACHEINANDER an dieser Stelle (25.08.2026):
   1. `* { margin: 0 }` frass die Absatzabstaende (unten dokumentiert).
   2. Die Klasse hiess erst `.doc` — KOLLISION mit den Dokument-Pillen der
      Startseite (Zeile ~1630: `display: inline-flex`, runde Pille, grauer
      Grund). Ergebnis: der ganze Rechtstext lief WAAGERECHT nebeneinander,
      hinter ihm ein riesiger grauer Kreis. Am Screenshot gesehen, nicht
      vermutet. Deshalb heisst sie jetzt `.ldoc` (legal document) — und die
      Falle aus §6 gilt woertlich: VOR jedem neuen Klassennamen
      `grep -n "\.name" site/css/v4.css`.
   (urspruenglicher Kommentar: FEHLERURSACHE, GEFUNDEN 25.08.2026: `* { margin: 0; }` (Zeile 139)
   setzt JEDES Element auf Randmass null — auch jeden Absatz. Ohne einen
   eigenen `margin-bottom` klebten alle <p> aneinander: „der Text
   ist nicht untereinander geschrieben" (Uejs). Jetzt bekommt JEDES
   Block-Kind einen unteren Rand, und nur das LETZTE Element vor einer
   Ueberschrift oder dem Textende hat keinen — sonst waere der Abstand vor
   jedem <h2> doppelt (der eigene margin-bottom PLUS der margin-top der
   naechsten Ueberschrift). */
/* EIN Breitenmass: die Box (880px), Text laeuft buendig bis zur Kante.
   Die inneren 76ch-Grenzen sind RAUS — sie stoppten den Text vor der
   Box-Kante und liessen rechts einen asymmetrischen Leerstreifen (Uejs
   zweimal: „weiter ausbreiten"). Die Schrift ist dafuer auf 1rem/1.75
   angehoben — laengere Zeilen brauchen mehr Zeilenabstand. */
.ldoc { max-width: 880px; margin-inline: auto; }
.ldoc h2 {
  font-size: 1.16rem;
  font-weight: 620;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 2.3rem 0 0.7rem;
}
.ldoc h2:first-of-type { margin-top: 0; }
.ldoc > p,
.ldoc > ul,
.ldoc > .ldocblock,
.ldoc > .ldocnote { margin-bottom: 1.15rem; }
.ldoc > :last-child { margin-bottom: 0; }
/* Ein Satz, der in eine Liste MUENDET („…after you have:"), gehoert zu ihr —
   der volle Absatzabstand riss beide auseinander und der Einleitungssatz
   wirkte verwaist (Uejs, 26.08.2026: „wieso ist das so komisch
   voneinander geschrieben"). */
.ldoc > p:has(+ ul) { margin-bottom: 0.45rem; }
.ldoc p { font-size: 1rem; line-height: 1.75; color: var(--ink-2); }
.ldoc ul { padding-left: 1.25rem; }
.ldoc li { font-size: 1rem; line-height: 1.7; color: var(--ink-2); margin-bottom: 0.55rem; }
.ldoc li:last-child { margin-bottom: 0; }
.ldoc li::marker { color: var(--blue); }
/* :not(.btn) — sonst faerbt die Textlink-Regel auch die KNOEPFE im
   .docfoot: „Zur Startseite" stand blau auf blauem Grund und war unsichtbar
   (im Screenshot gesehen). Ein Knopf ist ein Knopf, kein Fliesstext-Link. */
.ldoc a:not(.btn) { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }
/* Kleingedrucktes — Randnotizen, keine Kernaussage. Trotzdem AA-Kontrast:
   --ink-3 traegt auch bei 0.86rem. */
.docnote { font-size: 0.88rem; line-height: 1.62; color: var(--ink-3); }
/* Adresse, Musterformular — dieselbe Kartensprache wie die Preiskarten
   (--card-cool + --lift-card), damit ein Rechtstext nicht wie eine
   Fremdseite neben dem Rest der Website wirkt. */
.docblock {
  margin: 0.6rem 0 1.15rem;
  padding: 1rem 1.3rem;
  border-radius: var(--r-md);
  background: var(--card-cool);
  box-shadow: var(--lift-card);
  font-size: 0.94rem;
  line-height: 1.68;
  color: var(--ink-2);
}
.docblock p { margin: 0 0 0.6rem; max-width: none; }
.docblock p:last-child { margin-bottom: 0; }
/* Schlusszeile: Kontakt + Wege weiter. KEINE Trennlinie (Regel 4) — der
   Abstand traegt die Gliederung. */
.docfoot { margin-top: 2.6rem; display: grid; gap: 1.1rem; }
.docfoot-contact { font-size: 0.95rem; color: var(--ink-3); }
.docfoot-contact a { color: var(--blue); font-weight: 560; }
.docfoot-acts { display: flex; flex-wrap: wrap; gap: 0.7rem; }

/* ---------- Einspaltige Auth-Karte fuer Zwischenschritte -----------------
   forgot-password, reset-password, verify-email, callback, 404: keine
   Schauspalte. Fuer einen Zwischenschritt (Passwort vergessen, E-Mail
   bestaetigen) waere die grosse Illustration zu viel Buehne — dieselbe
   Karte wie beim Anmelden, aber einspaltig und zentriert, auf demselben
   Lichtgrund. */
.auth.auth-solo { grid-template-columns: minmax(0, 1fr); justify-items: center; }
.auth.auth-solo .auth-side { width: 100%; }
/* Der Kreis-Anhaenger auf verify-email.html — ein Umschlag-Zeichen, zentriert
   ueber der Ueberschrift. Getoenter Rueckwurf statt vollflaechiger Farbe,
   dieselbe Zurueckhaltung wie ueberall auf der Website. */
.auth-badge {
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  margin: 0.4rem auto 1.1rem;
  border-radius: 16px;
  background: color-mix(in srgb, var(--blue) 10%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--blue) 20%, transparent);
  color: var(--blue);
}
.auth-badge svg { width: 24px; height: 24px; fill: none; stroke: currentColor; }

.sb-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.7rem;
  margin: 0.7rem 0 0;
  padding: 0 0.2rem;
  font-size: 0.68rem;
  line-height: 1.5;
}
.sb-legal a { color: var(--ink-4); text-decoration: none; }
.sb-legal a:hover { color: var(--ink-2); text-decoration: underline; }
/* Eingeklappte Leiste: kein Platz fuer Woerter — die Links wandern in die
   Fusszeilen der Schauseiten, erreichbar bleiben sie ueber jede davon. */
[data-sidebar="collapsed"] .sb-legal { display: none; }

/* Dieselben Links am Fuss der Anmeldeseiten. Zurueckhaltend — sie sind eine
   Pflichtangabe, kein Angebot, und duerfen dem Formular nicht die
   Aufmerksamkeit nehmen. */
.auth-legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.2rem 0.9rem;
  margin: 1.4rem 0 0;
  font-size: 0.72rem;
}
.auth-legal a { color: var(--ink-4); text-decoration: none; }
.auth-legal a:hover { color: var(--ink-2); text-decoration: underline; }
/* Die Supace-Antwort in der Fragensammlung: `answerHtml()` liefert einen
   Vorspann und eine Punktliste, Hervorhebungen als `.ans-kw`. Dieselben
   Masse wie im Transkript-Leser — es ist derselbe Inhalt, er soll auch
   gleich aussehen. */
.qa-answer .intro { margin: 0 0 0.5rem; }
.qa-answer ul { margin: 0; padding-left: 1.15rem; }
.qa-answer li { margin-bottom: 0.4rem; }
.qa-answer li:last-child { margin-bottom: 0; }
.qa-answer li::marker { color: var(--blue); }
/* NUR KLICK — kein :hover (25.08.2026, von Uejs gemeldet).
   Hover-Vorschau UND Klick-Umschalter am selben Element widersprechen sich
   zwangslaeufig: beim Zuklappen liegt die Maus noch darauf, `:hover` zeigt
   den Text also sofort wieder, und der zweite Klick sieht wirkungslos aus.
   Genau das war der Fehler. Dazu ging der Kontext von selbst auf, sobald
   man beim Scrollen mit dem Zeiger darueberkam.
   Ein Umschalter, der genau einen Weg hat, ist verlaesslicher als zwei, die
   sich gegenseitig aufheben — und Beruehrgeraete haben ohnehin nur den
   Klick. Die Marke sagt jetzt selbst, was sie tut („+ context" / „− context"). */
.ask-ctx.is-open .ask-ctx-text { display: block; }
/* Eine Zeile, die als Ganzes umschaltet, muss das auch zeigen. Nur dort,
   wo es wirklich Kontext gibt — sonst verspricht der Zeiger etwas, das
   nicht passiert. */
.ask-item.has-ctx { cursor: pointer; }
.qa-item.has-ctx > *:not(summary) { cursor: pointer; }
/* Absenderzeile ueber einer Antwort in der Fragensammlung — dieselbe
   Kennzeichnungssprache wie die Labels im Transkript-Leser (.rx-label),
   nur als eigene Regel, weil sie in einem anderen Kasten lebt. */
.qa-src {
  font-family: var(--mono);
  font-size: 0.58rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: #10707E;
  margin: 0.8rem 0 0.25rem;
}
/* Der Hinweis, dass das eigene Gedaechtnis noch nicht laeuft — bernstein,
   nicht rot: es ist ein „noch nicht", kein Fehler. Dieselbe Linie wie
   `is-soon` auf der Downloadseite. */
.ask-nostore {
  margin-top: 1rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--amber) 9%, #fff);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--amber) 26%, transparent);
}
.ask-foot { margin-top: 1rem; }
.ask-foot a { color: var(--blue); text-decoration: underline; text-underline-offset: 3px; }
