/* TALVAXO PUBLIC WEBSITE (Mandat "PUBLIC WEBSITE 10/10 VISUAL EXPERIENCE PASS"). Nutzt
   ausschliesslich bestehende Tokens (tokens.css/tokens-light.css) und die bestehende Wave-Engine
   -- kein neues Designsystem. */

/* ============================================================
   PUBLIC BRAND TOKENS (Mandat "BRAND EXPERIENCE" Teil 8/9) -- single source of truth for every
   public-page color decision. These are pure ALIASES onto tokens.css/tokens-light.css (which
   already carry the real, brand-kit-sourced hex values, see docs/branding/README.md) -- no new
   colors are introduced here, this layer exists so every public section reads --talvaxo-pub-* by
   name instead of reaching for --panel/--talvaxo-cyan/etc. directly and drifting over time.
   Resolved values (Dark / Light):
     --talvaxo-pub-bg             #060D1C / #9CA2AF   (page background)
     --talvaxo-pub-surface        #0D1D36 / #DADDE3   (panel / card)
     --talvaxo-pub-surface-raised #163259 / #BEC2CC   (raised panel)
     --talvaxo-pub-blue           #007AFF (both)      (data IN)
     --talvaxo-pub-cyan           #00E5FF (both)      (intelligence / active)
     --talvaxo-pub-violet         #7A5CFF (both)      (decision OUT)
     --talvaxo-pub-text           #EAF0FA / #101C33
     --talvaxo-pub-text-muted     #8296B8 / #4E5D78
     --talvaxo-pub-border         rgba(0,122,255,.16) / rgba(16,28,51,.28)
     --talvaxo-pub-glow           rgba(0,229,255,.35) (both, medium-glow default)
   ============================================================ */
:root {
  --talvaxo-pub-bg: var(--bg);
  --talvaxo-pub-surface: var(--panel);
  --talvaxo-pub-surface-raised: var(--panel-raised);
  --talvaxo-pub-blue: var(--talvaxo-blue);
  --talvaxo-pub-cyan: var(--talvaxo-cyan);
  --talvaxo-pub-violet: var(--talvaxo-violet);
  --talvaxo-pub-text: var(--text);
  --talvaxo-pub-text-muted: var(--text-muted);
  --talvaxo-pub-border: var(--border-soft);
  --talvaxo-pub-glow: rgba(0, 229, 255, 0.35);
  /* Design-Print Teil 54 nennt diese Namen wörtlich -- als Aliase auf die bestehenden, bereits
     zentralisierten Tokens ergänzt (tokens.css), statt bestehende Namen umzubenennen/zu riskieren.
     --talvaxo-blue/-cyan/-violet existieren bereits exakt so in tokens.css, hier nicht erneut
     definiert. Kein separates "deep"-Navy vorhanden -- --bg IST bereits die tiefste Navy-Stufe. */
  --talvaxo-bg: var(--bg);
  --talvaxo-bg-deep: var(--bg);
  --talvaxo-surface: var(--panel);
  --talvaxo-surface-raised: var(--panel-raised);
  --talvaxo-text: var(--text);
  --talvaxo-text-secondary: var(--text-muted);
  --talvaxo-border: var(--border-soft);
  --talvaxo-glow: rgba(0, 229, 255, 0.35);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Smooth-Scroll fuer Nav-Anker-Klicks (User-Referenz: sp.stefan-pertl.at -- dort reines natives
   `scroll-behavior: smooth` auf <html>, keine JS-Bibliothek). Reduced-Motion-Nutzer bekommen den
   Standard-Sofortsprung, konsistent mit jeder anderen Motion-Reduktion auf dieser Seite. */
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Public-Website-eigene Light-Mode-Flaechenfarben (User-Feedback: "der graue Hintergrund ist auch
   nicht das Wahre... lebendiger"). Bewusst NUR auf .pub-body gescoped, NICHT in tokens-light.css
   (globale Datei) geaendert -- dort ist --bg: #9CA2AF das Ergebnis mehrerer expliziter frueherer
   Nutzeranweisungen fuer das App/Dashboard-Light-Mode ("darf nicht ganz weiss sein, muss grau
   sein", siehe Kommentar in tokens-light.css) und wird von Login/Dashboard/allen App-Seiten
   mitgenutzt -- eine globale Aenderung wuerde deren Light Mode ungefragt mit umbauen. Da
   --talvaxo-pub-bg/-surface/-surface-raised (oben) und alle .pub-*-Regeln ausschliesslich ueber
   var(--bg)/var(--panel)/var(--panel-raised) arbeiten, reicht eine lokale Neudefinition dieser drei
   Custom Properties auf .pub-body, um NUR die oeffentliche Website heller/lebendiger zu machen --
   ohne eine einzige Regel in tokens-light.css oder eine andere Seite anzufassen. Kuehles,
   markenkonsistentes Blau-Weiss statt neutralem Grau: heller Hintergrund, klar davon abgesetzte
   weisse Karten (starke Flaechenhierarchie statt dem vorherigen "Grau auf Grau"), plus staerkere
   Blau/Violett-Ambient-Glows fuer mehr visuelles Leben. */
[data-theme="light"] .pub-body {
  --bg: #E4EAF7;
  --panel: #FBFCFE;
  --panel-raised: #FFFFFF;
  --border-soft: rgba(16, 28, 51, 0.14);
  --text-dim: #6B7A97;
}
.pub-body {
  background: var(--bg); color: var(--text);
  font-family: var(--font-body); overflow-x: hidden;
  min-height: 100vh;
}
[data-theme="light"] .pub-body {
  background: radial-gradient(1100px 620px at 14% -8%, rgba(0,122,255,0.10), transparent 60%),
              radial-gradient(1000px 640px at 100% 18%, rgba(122,92,255,0.09), transparent 55%),
              radial-gradient(900px 700px at 45% 100%, rgba(0,229,255,0.06), transparent 60%),
              var(--bg);
}
.hl-blue { color: var(--talvaxo-blue); }
.hl-cyan { color: var(--talvaxo-cyan); }
.hl-violet { color: var(--talvaxo-violet); }
.pub-good { color: var(--status-good); }
.pub-warn { color: var(--status-warn); }
.pub-bad { color: var(--status-bad); }

/* Light Mode: --talvaxo-cyan reads at ~1.6:1 against the light page background — too low for text
   (the app already solves this for --nav-active-accent, see tokens.css, by swapping to
   --talvaxo-blue in light mode; mirrored here for this page's own cyan-as-text usages). Decorative
   dots/markers/glows are left on cyan — they're shapes, not text, and read fine on light grey. */
[data-theme="light"] .hl-cyan,
[data-theme="light"] .pub-eyebrow,
[data-theme="light"] .pub-plan-change b,
[data-theme="light"] .pub-beta-alt a,
[data-theme="light"] .pub-link-btn:hover,
[data-theme="light"] .pub-link-btn:focus-visible,
[data-theme="light"] .pub-theme-toggle:hover,
[data-theme="light"] .pub-lang-toggle:hover {
  color: var(--talvaxo-blue);
}

/* Light Mode: decision/output elements are Violet (Mandat "BRAND EXPERIENCE" Teil 11/15/28 —
   Violet = decision output). Raw --talvaxo-violet on the light --bg reads only ~1.7:1, same class
   of problem as cyan above -- darkened via color-mix instead of a flat blue swap, so the "this is
   the decision/output" meaning (violet) survives into Light Mode instead of being replaced by blue. */
[data-theme="light"] .pub-window-eyebrow,
[data-theme="light"] .pub-window-decision-row b,
[data-theme="light"] .pub-decision-result-change b,
[data-theme="light"] .pub-think-decision-list li,
[data-theme="light"] .hl-violet {
  color: color-mix(in srgb, var(--talvaxo-violet) 65%, black);
}
/* Claim-specific: "Train"/"Recover"/"Perform" must read as three DISTINCT brand colors (Mandat
   Teil 3) -- the page-wide hl-cyan->blue swap above would make "Train" and "Recover" identical in
   Light Mode. A darker, more saturated cyan (30% cyan / 70% black) keeps Recover visually distinct
   from Train's blue while clearing ~4.2:1 contrast on the light page background (raw --talvaxo-
   cyan only reaches ~1.6:1 here). */
[data-theme="light"] .pub-hero-claim .hl-cyan {
  color: color-mix(in srgb, var(--talvaxo-cyan) 30%, black);
}

/* Light Mode: --text-dim (#8996AC) sits almost on top of the light-mode page --bg (#9CA2AF) —
   near-1:1 contrast. Elsewhere --text-dim only ever labels text on top of a lighter --panel
   surface, where the gap is large enough; here these specific labels sit directly on the bare
   page background, so they get --text-muted instead in light mode only. */
[data-theme="light"] .pub-disclaimer,
[data-theme="light"] .pub-signals-arrow,
[data-theme="light"] .pub-timeline-day,
[data-theme="light"] .pub-demo-note,
[data-theme="light"] .pub-footer,
[data-theme="light"] .pub-footer-brand small,
[data-theme="light"] .pub-footer-links a {
  color: var(--text-muted);
}

.wave-bg, .wave-particles-bg {
  position: fixed; inset: 0; width: 100%; height: 100%;
  z-index: 0; pointer-events: none; display: block;
}

/* ============ MOTION SYSTEM (Mandat Teil 30/31/33) ============ */
[data-reveal] { opacity: 0; transform: translateY(22px); transition: opacity 550ms ease, transform 550ms ease; }
[data-reveal].pub-in-view { opacity: 1; transform: translateY(0); }
[data-reveal-child] { opacity: 0; transform: translateY(14px); transition: opacity 450ms ease, transform 450ms ease; }
[data-reveal-child].pub-in-view { opacity: 1; transform: translateY(0); }
.pub-hero-window { transition: transform 450ms ease, opacity 450ms ease; }
.pub-window--main { animation: pub-float 6s ease-in-out infinite; }
@keyframes pub-float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }

@media (prefers-reduced-motion: reduce) {
  [data-reveal], [data-reveal-child] { transition: opacity 200ms linear !important; transform: none !important; }
  .pub-window--main { animation: none !important; }
  .pub-cta-btn, .pub-toast, .pub-theme-toggle, .pub-lang-toggle { transition: none !important; }
}
/* Mandat Teil 33 "REAL TEST": .pub-motion-off ist eine manuell togglebare Klasse, die exakt
   dieselben Regeln wie die obige @media-Regel anwendet -- damit laesst sich das tatsaechliche
   Reduced-Motion-Verhalten in dieser Sitzung sichtbar pruefen, ohne die (hier nicht verfuegbare)
   echte OS-Media-Query-Emulation zu benoetigen. Siehe TALVAXO_PUBLIC_10_ACCESSIBILITY.md fuer die
   volle Einordnung dieser Testmethode. Niemals im normalen Betrieb aktiv. */
.pub-motion-off { scroll-behavior: auto !important; }
.pub-motion-off [data-reveal], .pub-motion-off [data-reveal-child] { transition: opacity 200ms linear !important; transform: none !important; }
.pub-motion-off .pub-window--main { animation: none !important; }
.pub-motion-off .pub-cta-btn, .pub-motion-off .pub-toast, .pub-motion-off .pub-theme-toggle, .pub-motion-off .pub-lang-toggle { transition: none !important; }

/* ============ NAV ============ */
.pub-nav {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 32px; backdrop-filter: blur(14px);
  background: color-mix(in srgb, var(--bg) 72%, transparent);
  border-bottom: 1px solid var(--hairline);
  /* Scroll-Farbverlauf (2026-09-26, Nutzerwunsch "beim Scrollen die Farben anpassen"): --scroll-accent
     wird in public.js (derselbe scrollChrome()-Listener wie Progress-Bar/Parallax) aus dem
     vorhandenen Scroll-Fortschritt (0..1) berechnet -- linear durch die drei Markenfarben Blau/Cyan/
     Violett gemischt (dieselbe Reihenfolge wie im Hero-Claim "Train/Recover/Perform"). Bewusst als
     leiser Glow unter der Nav (box-shadow, niedrige Alpha), nicht als Text-/Hintergrundfarbe --
     Kontrast/Lesbarkeit bleibt unangetastet. transition glaettet die Werte zwischen rAF-Ticks. */
  box-shadow: 0 10px 26px -14px var(--scroll-accent, transparent);
  transition: background 200ms ease, backdrop-filter 200ms ease, border-bottom-color 200ms ease, box-shadow 220ms ease;
}
.pub-nav-brand { display: flex; align-items: center; gap: 9px; text-decoration: none; color: var(--text); font-family: var(--font-display); font-weight: 700; font-size: 16px; letter-spacing: 0.03em; }
/* v10.1(11) Logo-Kit-Pass: ersetzt Icon+Text durch die echte Wordmark-Grafik (siehe
   .app-nav .brand-logo in components.css fuer die volle Begruendung -- identisches Prinzip). */
.pub-nav-brand img { display: block; height: 26px; width: auto; }
.pub-nav-links { display: flex; gap: 26px; }
.pub-nav-links a { color: var(--text-muted); text-decoration: none; font-size: 13.5px; transition: color 160ms ease; }
.pub-nav-links a:hover, .pub-nav-links a:focus-visible { color: var(--text); }
.pub-nav-actions { display: flex; align-items: center; gap: 14px; }
.pub-theme-toggle, .pub-lang-toggle {
  background: none; border: 1px solid var(--border-soft); border-radius: 8px;
  min-width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
  color: var(--text-muted); cursor: pointer; font-family: var(--font-mono); font-size: 11.5px; font-weight: 600;
  padding: 0 8px;
}
.pub-theme-toggle:hover, .pub-lang-toggle:hover { color: var(--talvaxo-cyan); border-color: var(--talvaxo-cyan); }
.pub-theme-toggle:focus-visible, .pub-lang-toggle:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
.pub-link-btn { color: var(--text); text-decoration: none; font-size: 13.5px; font-weight: 500; background: none; border: none; cursor: pointer; font-family: var(--font-body); }
.pub-link-btn:hover, .pub-link-btn:focus-visible { color: var(--talvaxo-cyan); }
.pub-nav-login-btn {
  display: inline-flex; align-items: center; height: 34px; padding: 0 16px;
  border: 1px solid var(--border-soft); border-radius: 8px;
  color: var(--text); text-decoration: none; font-size: 13px; font-weight: 500;
  transition: border-color 200ms ease, color 200ms ease;
}
.pub-nav-login-btn:hover, .pub-nav-login-btn:focus-visible { border-color: var(--talvaxo-cyan); color: var(--talvaxo-cyan); }
.pub-cta-btn {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--talvaxo-gradient); color: #fff; border: none; border-radius: 9px;
  padding: 10px 18px; font-family: var(--font-display); font-weight: 600; font-size: 13.5px;
  cursor: pointer; transition: filter 160ms ease, transform 160ms ease; text-decoration: none;
}
.pub-cta-btn:hover { filter: brightness(1.1); }
.pub-cta-btn:active { transform: scale(0.98); }
.pub-cta-btn:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
/* v10.3.5: #pub-nav-try-mobile can now be conditionally [hidden] for authenticated visitors --
   same display-vs-[hidden] specificity fix as .pub-nav-auth-anon/.pub-nav-auth-user above. */
.pub-cta-btn[hidden] { display: none; }
.pub-cta-btn--lg { padding: 16px 28px; font-size: 15.5px; border-radius: 12px; }
.pub-link-btn--lg { font-size: 15px; padding: 16px 10px; }

/* v10.3.5 (Website/App Session Continuity, Mandat §7-9): authentifizierter Zustand ersetzt
   Anmelden/Registrieren/Demo -- ein einziger, kompakter Link (Avatar + Name + "Zum Dashboard"),
   kein zweites Nav-Actions-System. .pub-nav-auth-anon ist ein reiner Wrapper (kein eigener Stil
   noetig, die Kind-Elemente tragen bereits .pub-nav-login-btn/.pub-cta-btn). */
.pub-nav-auth-anon { display: flex; align-items: center; gap: 14px; }
.pub-nav-auth-user {
  display: inline-flex; align-items: center; gap: 9px; height: 34px; padding: 3px 14px 3px 3px;
  border: 1px solid var(--border-soft); border-radius: 999px; text-decoration: none;
  transition: border-color 200ms ease, background 200ms ease;
}
/* Bugfix (derselbe wiederkehrende Bug-Typ wie .acct-btn[hidden] in dashboard.css): eine
   Klassen-Selektor-Regel, die display setzt, schlaegt bei gleicher Spezifitaet die
   Browser-Default-Regel [hidden]{display:none} allein durch Quellreihenfolge (diese Regel steht
   nach der UA-Stylesheet-Regel). Explizite Ueberschreibung noetig, sonst bleibt ein "hidden"
   Element trotzdem sichtbar. */
.pub-nav-auth-anon[hidden], .pub-nav-auth-user[hidden] { display: none; }
.pub-nav-auth-user:hover, .pub-nav-auth-user:focus-visible { border-color: var(--talvaxo-cyan); background: color-mix(in srgb, var(--talvaxo-cyan) 8%, transparent); }
.pub-nav-auth-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--talvaxo-gradient); background-size: cover; background-position: center;
  color: #fff; font-family: var(--font-display); font-size: 11px; font-weight: 700;
}
.pub-nav-auth-info { display: flex; flex-direction: column; line-height: 1.25; }
.pub-nav-auth-name { font-size: 12.5px; font-weight: 600; color: var(--text); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pub-nav-auth-cta { font-size: 10.5px; color: var(--talvaxo-cyan); font-weight: 500; }
.pub-nav-auth-user--mobile { width: 100%; height: auto; padding: 10px 14px; border-radius: 10px; margin: 4px 0; }
.pub-nav-auth-user--mobile .pub-nav-auth-avatar { width: 34px; height: 34px; font-size: 13px; }
.pub-nav-auth-user--mobile .pub-nav-auth-name { font-size: 14px; max-width: none; }
.pub-nav-burger { display: none; background: none; border: none; color: var(--text); cursor: pointer; padding: 6px; flex-shrink: 0; }
.pub-nav-burger svg { display: block; width: 22px; height: 22px; }
/* Bug-Fund (2026-09-26, beim Nav-Reihenfolge-Fix entdeckt): top:0 bei gleichzeitig sticky
   .pub-nav (z-index:40, Hoehe 67px) liess den ersten Menu-Eintrag hinter dem Header verschwinden
   UND unklickbar sein (elementFromPoint traf das Logo-Bild, nicht den Link) -- vorher betraf das
   "Produkt", jetzt genau "Preview", den wir eben nach vorne geholt haben. top:67px statt top:0
   haengt das Menu direkt UNTER den Header statt dahinter. */
.pub-nav-mobile { display: none; flex-direction: column; gap: 2px; padding: 10px 20px 20px; background: var(--panel); border-bottom: 1px solid var(--hairline); position: sticky; top: 67px; z-index: 39; }
.pub-nav-mobile a, .pub-nav-mobile button { color: var(--text); text-decoration: none; padding: 13px 4px; border: none; background: none; font-size: 15px; text-align: left; font-family: var(--font-body); cursor: pointer; border-bottom: 1px solid var(--hairline); }
.pub-nav-mobile-row { display: flex; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--hairline); }
.pub-nav-mobile-row button { border: 1px solid var(--border-soft); border-radius: 8px; padding: 8px 12px; }
.pub-nav-mobile .pub-cta-btn { border-bottom: none; margin-top: 10px; justify-content: center; }

/* Bug-Fund ("Final Public Website Composition"-Mandat, 900px-Pflicht-Check, 2026-09-26): war
   max-width:860px, waehrend praktisch jeder andere "wird jetzt mobil"-Breakpoint der Seite (Laeufer
   ausblenden, Brand-Opening verkleinern usw.) bei 900px liegt -- im Bereich 861-900px zeigte die
   Seite dadurch weiterhin die volle Desktop-Nav, die dort nicht mehr genug Platz hat und umbricht
   ("So funktioniert" / "es" auf zwei Zeilen). Auf 900px angeglichen, damit Nav und der Rest der
   Seite genau denselben Umschaltpunkt teilen. Vorbestehender Bug, unabhaengig von der Athlete-
   Preview-Verschiebung -- nur bei der fuer diesen Pass ohnehin geforderten 900px-Pruefung
   aufgefallen. */
@media (max-width: 900px) {
  .pub-nav-links, .pub-nav-actions { display: none; }
  .pub-nav-burger { display: block; }
  .pub-nav-mobile[data-open="true"] { display: flex; }
}

/* ============ BRAND OPENING (Mandat v10.1(11) Teil 1-20, Layout nach User-Skizze) ============
   Kompaktes Banner (KEIN vollflaechiger Screen mehr -- User-Korrektur: die urspruengliche 88vh-
   Variante wirkte zu dominant, das Hero-Produkt sollte im selben ersten Bildschirm mit anklingen).
   X-Symbol ist ins Wordmark selbst integriert (TALVA + echtes talvaxo-x.png als grosser "X"-Buch-
   stabe + O), flankiert von zwei schmalen Wortstapeln -- alles reale Brand-Assets + bereits
   etablierte Copy (kein neues Logo/keine neue Typografie erfunden). Normaler Dokumentfluss (kein
   position:fixed/Scroll-Jacking) -> sofort scrollbar. Animation bleibt reiner Compositor-Kram
   (opacity/transform, keine Filter-Animation), keine neue Canvas-Instanz, keine neuen Pointer-
   Listener. Gemeinsame .wave-bg-Ebene (oben, position:fixed hinter der gesamten Seite) sorgt fuer
   den nahtlosen Uebergang in den Hero. Rein dekorativ (Wordmark/Claim-Woerter wiederholen Nav/
   Hero) -> aria-hidden. */
.pub-brand-open {
  position: relative; z-index: 1; overflow: hidden;
  display: grid; grid-template-columns: 1fr minmax(0, 640px) 1fr; column-gap: 20px;
  min-height: 42vh; box-sizing: border-box;
  padding: 40px 28px 32px;
  text-align: center;
}
/* User-Feedback: Text lag DIREKT AUF dem Wordmark im Header-Bild (ueberlappte die Buchstaben,
   unlesbar). Fix: in Dark Mode (Bild aktiv) sitzt der gesamte Text-Block jetzt UNTER dem Wordmark
   -- die Bildkomposition selbst hat dort bereits eine ruhigere Boden-/Reflexionsflaeche. Light Mode
   (kein Bild, CSS-Wordmark) bleibt beim bewaehrten vertikal zentrierten Layout. */
.pub-brand-open { align-items: center; }
/* Ab v10.1(11) Light-Mode-Header-Pass: beide Themes zeigen jetzt ein echtes Foto (>=900px), daher
   gilt das End-ausgerichtete, hoehere Layout fuer BEIDE Themes -- nicht mehr nur Dark. */
/* User-Fund (Ultra-Widescreen): bei sehr breiten Viewports wird die Sektion (Breite=100vw, Hoehe
   nur 46vh) im Seitenverhaeltnis viel extremer/breiter als das 3:1-Quellbild -- object-fit:cover
   muss dann deutlich mehr oben/unten wegschneiden, um die Breite zu fuellen (je breiter/kuerzer die
   Box, desto staerker der Crop). Dadurch ruecken Text/Wortstapel (per align-items:end unten
   verankert) sichtbar naeher an die Buchstaben heran, als auf normalen Breitbild-Monitoren. Fix:
   min-height waechst zusaetzlich mit der Breite (max(46vh, 31.25vw) haelt das Sektions-
   Seitenverhaeltnis nahe am 3.2:1 des Quellbilds), damit der Crop-Anteil auf jeder Breite aehnlich
   bleibt statt bei Ultra-Wide zu eskalieren. */
/* Nutzerwunsch: der gesamte untere Textblock (Tagline/Closed-Beta plus beide Seitenspalten) etwas
   weiter von der unteren Kante weg nach oben -- reiner padding-bottom-Zuwachs, da .pub-brand-open
   bottom-verankert ist (align-items:end), Bildausschnitt/min-height bleiben unveraendert. */
/* Website-Feedback-Pass (2026-09-26, Nutzerwunsch "Besucher catchen"): die Brand-Opening-Sektion
   nahm bislang bis zu ~50vh ein, BEVOR der eigentliche Hero (Claim + CTA + Produkt-Vorschau)
   ueberhaupt sichtbar wurde -- ein Erstbesucher sah in den ersten Sekunden nur Wordmark/Tagline,
   keine konkrete Aussage, keinen klickbaren CTA. Kompaktiert auf ca. 60% der vorherigen Hoehe, damit
   der echte Hero deutlich frueher ins Blickfeld ruecklt. Reversibel: siehe Backup in scratchpad
   website-backup-20260926/ falls diese Aenderung wieder verworfen wird. */
.pub-brand-open { align-items: end; min-height: max(38vh, 25vw); padding-bottom: 48px; }
@media (max-width: 900px) {
  .pub-brand-open { align-items: center; min-height: 34vh; padding-bottom: 24px; }
}
/* Echtes Header-Design des Nutzers (v10.1(11) Logo-Kit-Pass) -- volle Sektionsflaeche, HINTER dem
   restlichen Inhalt (z-index:0, Content-Spalten liegen implizit darueber). Zwei Bilder (--dark/
   --light) fuer dieselbe Komposition in beiden Themes, siehe Umschaltung unten. Unter 900px faellt
   BEIDES auf das transparente CSS-Wordmark zurueck (object-fit:cover wuerde dort Anfang/Ende des
   Wortmarks sichtbar abschneiden, siehe .pub-brand-wordmark weiter unten). */
.pub-brand-header-bg {
  position: absolute; inset: 0; z-index: 0; overflow: hidden;
  display: block; opacity: 0; transform: scale(1.03);
  /* User-Feedback (4x): (1) harte Kante am unteren Rand -- Fix per Masken-Verlauf unten transparent;
     (2) "breiterer, weicherer Verlauf" gewuenscht; (3) oberer Fade-IN entfernt (schnitt in die
     Buchstaben-Oberkanten); (4) PRAEZISE VERMESSEN (Saettigungs-/Helligkeits-Analyse der Rohdatei,
     siehe qa/v10.1.11): der Schriftzug "TALVAXO" reicht bis ca. Bild-Y=68% (unter Beruecksichtigung
     des object-fit:cover-Crops bei object-position:"center 30%" ca. Sektions-Y=73%) -- der vorherige
     Fade-Start bei 40% lag damit MITTEN im Schriftzug, nicht darunter (User-Fund: "faengt zu weit
     oben an, mittig vom Header"). Jetzt auf 74% verschoben, sicher unterhalb der Buchstaben. */
  mask-image: linear-gradient(to bottom, black 0%, black 74%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 74%, transparent 100%);
}
.pub-brand-header-bg img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center 30%; }
.pub-brand-header-bg--light { display: none; }
[data-theme="light"] .pub-brand-header-bg--dark { display: none; }
[data-theme="light"] .pub-brand-header-bg--light { display: block; }
/* !important noetig: die themespezifischen --dark/--light-Sichtbarkeitsregeln unten
   ([data-theme="light"] .pub-brand-header-bg--light {display:block}) haben durch den Attribut-
   Selektor hoehere Spezifitaet als eine einfache Klassenregel und wuerden diese Media-Query sonst
   aushebeln -- Bug-Fund: ohne !important blieb das Foto unter 900px sichtbar UND ueberlappte das
   CSS-Wordmark-Fallback. */
@media (max-width: 900px) { .pub-brand-header-bg { display: none !important; } }

/* Gezielter Verdunkelungs-Verlauf NUR im unteren Textbereich (siehe .pub-brand-open align-items:end
   oben) -- Lesbarkeits-Garantie unabhaengig vom exakten Bildinhalt dort, zusaetzlich zum Text-
   Shadow auf den einzelnen Elementen. Liegt UEBER dem Bild, UNTER dem Text (z-index 0, Text-Spalten
   haben z-index 1). Gilt jetzt fuer BEIDE Themes (beide zeigen ein Foto), Farbe pro Theme
   angepasst (dunkler Scrim auf Dark-Foto, heller Scrim auf Light-Foto). */
.pub-brand-scrim {
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  /* User-Feedback (3x): (1) blieb vorher bis zum Sektionsrand opak -- Fix per "Huegel"-Verlauf,
     wieder transparent VOR dem Rand; (2) "breiterer, weicherer Verlauf"; (3) derselbe Fund wie beim
     Foto-Fade oben -- der Scrim begann bei 40%, also MITTEN im Schriftzug ("TALVAXO" reicht bis
     Sektions-Y~73%, siehe dortiger Messkommentar) und trug zum wahrgenommenen "Verblassen" der
     Buchstaben bei, obwohl das Bild selbst voll deckend ist. Jetzt beginnt der Scrim (wie das Foto)
     erst bei 74%, deutlich unter dem Schriftzug, direkt dort wo Tagline/Divider/Wortstapel sitzen. */
  background: linear-gradient(to bottom,
    transparent 0%, transparent 74%,
    rgba(4,9,20,.7) 84%, rgba(4,9,20,.78) 88%,
    transparent 100%);
}
[data-theme="light"] .pub-brand-scrim {
  background: linear-gradient(to bottom,
    transparent 0%, transparent 74%,
    rgba(230,236,248,.75) 84%, rgba(230,236,248,.85) 88%,
    transparent 100%);
}
@media (max-width: 900px) { .pub-brand-scrim { display: none; } }

/* Nutzerwunsch: drittes Element links ("ECHTER FORTSCHRITT") ergaenzt das bisherige Zweier-Paar auf
   dieselbe Zeilenzahl wie rechts (TRAIN/RECOVER/PERFORM) -- plus insgesamt groessere, praesentere
   Schrift fuer den allerersten Eindruck der Seite. */
.pub-brand-side { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 6px; font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.16em; color: var(--talvaxo-pub-text-muted); opacity: 0; align-self: end; }
.pub-brand-side--left { align-items: flex-start; padding-left: 14px; border-left: 1px solid var(--talvaxo-pub-border); justify-self: end; transform: translateX(-8px); }
.pub-brand-side--right { align-items: flex-end; text-align: right; padding-right: 14px; border-right: 1px solid var(--talvaxo-pub-border); justify-self: start; transform: translateX(8px); }
/* Kontrast-Sicherung ueber dem Foto-Hintergrund -- gilt jetzt fuer BEIDE Themes (beide zeigen ein
   Foto ab v10.1(11) Light-Mode-Header-Pass), Halo-Farbe je Theme angepasst. */
:root:not([data-theme="light"]) .pub-brand-side { color: var(--talvaxo-pub-text); text-shadow: 0 1px 4px rgba(0,0,0,.85), 0 0 12px rgba(0,0,0,.6); }
[data-theme="light"] .pub-brand-side { color: var(--talvaxo-pub-text); text-shadow: 0 1px 4px rgba(255,255,255,.85), 0 0 12px rgba(255,255,255,.7); }

/* User-Feedback (Verlauf, endet mit Entfernung): der Glow-Kreis hinter dem X wurde mehrfach
   nachjustiert (Blend-Mode/Groesse), wirkte am Ende aber wie ein grosser weicher "Schleier" ueber
   dem Partikelbereich statt wie ein gezielter Akzent -- auf User-Wunsch komplett entfernt. Nur die
   Partikel (.pub-brand-particles unten) bleiben als Effekt am Logo. */

/* User-Wunsch ("den Partikeleffekt 1:1 von der Welle ueber die Schrift legen"): eigenes Canvas
   HIER (nicht das globale #wave-particles) -- siehe Kommentar in index.html fuer die genaue
   Stacking-Ursache. z-index:0 wie Foto/Scrim/Glow, aber SPAETER im DOM -> malt ueber sie, bleibt
   aber unter dem Text (.pub-brand-side/-center haben z-index:1). */
/* canvas ist ein "replaced element" -- inset:0 allein streckt es NICHT (anders als bei normalen
   Blockelementen), es bleibt bei seiner intrinsischen 300x150-Default-Groesse. Explizit width/
   height:100% noetig, genau wie bei .pub-brand-header-bg img oben. */
.pub-brand-particles { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; display: block; }
@media (max-width: 900px) { .pub-brand-particles { display: none; } }

/* v10.1(12) "FINAL BRAND OPENING EXPERIENCE" -- cursor-getriebene Fine-Pointer-Akzente (Teil 16-25).
   EIN gemeinsamer pointermove-Listener auf #pub-brand-open (public.js) schreibt pro rAF-Tick
   --bpx/--bpy (Parallax-Versatz, -0.5..0.5) -- kein eigener RAF-Loop, nur CSS liest die Custom
   Properties. Sichtbarkeit selbst ueber :hover (automatisch nur bei echtem Pointer, kein
   zusaetzliches JS-Flag noetig).
   Nutzeranweisung (nach Auslieferung): "den hellen Kreis, der die Maus verfolgt" (den Cursor-
   Spotlight, ehemals .pub-brand-spotlight, --bsx/--bsy) wieder entfernt -- Parallaxe und die
   X-Reflexion an der Kreuzung bleiben, nur der mitlaufende Spotlight-Kreis ist weg. */
/* translate (nicht transform!) -- die Reveal-Sequenz (pub-brand-header-bg-reveal) animiert bereits
   transform (scale) auf demselben Element; ein zweiter transform-Wert wuerde vom
   animation-fill-mode:forwards der Reveal-Animation dauerhaft ueberschrieben und nie sichtbar
   werden. Die eigenstaendige CSS-translate-Property komponiert unabhaengig mit transform, deshalb
   funktioniert der Parallax-Versatz sowohl waehrend als auch nach der Reveal-Animation. */
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .pub-brand-header-bg {
    transition: translate 260ms ease-out;
    translate: calc(var(--bpx, 0) * 7px) calc(var(--bpy, 0) * 5px);
  }
}
/* Gemeinsame Basis fuer JEDEN X-Glow-Layer (Hover-Reflexion UND Lade-Aufblinken, siehe unten) --
   3. Folgekorrektur (Nutzer-Fund per zwei Bildschirmaufnahmen: "nicht genau so gross, versetzt" --
   auch die vorherige Loesung mit der separaten freigestellten X-Grafik als Overlay traf die echte
   Silhouette nie exakt, weil diese Grafik ein ANDERES Asset mit leicht anderen Proportionen ist als
   das X, wie es in DIESER Wortmarke/diesem Foto gezeichnet ist -- selbe Marken-Familie, aber kein
   pixelidentischer Match). Endgueltige, garantiert praezise Loesung: der Glow-Layer zeigt das FOTO
   SELBST als background-image, mit DENSELBEN background-size:cover/background-position:center 30%
   wie das sichtbare <img> (siehe .pub-brand-header-bg img) -- dadurch ist die Positionierung/
   Skalierung dieser Ebene IMMER identisch zur sichtbaren Ebene, unabhaengig vom Viewport. clip-path
   schneidet auf die X-Bounding-Box zurecht (Insets als --x-clip-*-Custom-Properties, live berechnet
   in alignBrandXCrossing() in public.js -- haengen wie --x-cx/--x-cy vom object-fit:cover-Crop ab,
   siehe dortiger Kommentar). filter:blur() weicht die harte clip-path-Kante zu einem weichen
   Uebergang auf; brightness()/saturate() erzeugen den eigentlichen "Aufleuchten"-Effekt. Farben
   kommen automatisch aus dem Foto selbst -- kein manuelles Farbmapping noetig. Einmal hier gepflegt,
   wirkt fuer beide Verwendungen (Hover + Lade-Blink) identisch. */
.pub-brand-x-glow {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0;
  background-image: url(/assets/hero/talvaxo-brand-header.jpg);
  background-size: cover;
  background-position: center 30%;
  /* Wichtiger Bug-Fund waehrend dieser Korrektur: clip-path + filter:blur() auf demselben Element
     ergibt KEINE weiche Kante -- die CSS-Rendering-Reihenfolge wendet filter VOR clip-path an, der
     harte Clip schneidet den weichgezeichneten Bildrand danach wieder scharf ab (verifiziert:
     blur(28px) aenderte die sichtbare Kante nicht). Fix: mask-image mit einem radial-gradient (Ellipse
     in Groesse/Position der X-Bounding-Box) statt clip-path -- der weiche Verlauf IST die Maske,
     kein nachtraeglicher Blur-Versuch mehr noetig. */
  --x-rx: calc((100% - var(--x-clip-left, 46%) - var(--x-clip-right, 25%)) / 2);
  --x-ry: calc((100% - var(--x-clip-top, 10%) - var(--x-clip-bottom, 17%)) / 2);
  -webkit-mask-image: radial-gradient(ellipse var(--x-rx) var(--x-ry) at var(--x-cx, 64.2%) var(--x-cy, 40.15%), black 40%, transparent 85%);
  mask-image: radial-gradient(ellipse var(--x-rx) var(--x-ry) at var(--x-cx, 64.2%) var(--x-cy, 40.15%), black 40%, transparent 85%);
  mix-blend-mode: screen;
  filter: brightness(2.1) saturate(1.35);
}
[data-theme="light"] .pub-brand-x-glow {
  background-image: url(/assets/hero/talvaxo-brand-header-light.jpg);
}
@media (max-width: 900px) { .pub-brand-x-glow { display: none; } }

/* X-Reflexion (Teil 18): das X soll auf Hover "aufleuchten" -- nur Opazitaet aendert sich, Form/
   Position/Farbe kommen aus .pub-brand-x-glow oben. */
@media (pointer: fine) and (prefers-reduced-motion: no-preference) {
  .pub-brand-reflect { transition: opacity 280ms ease; }
  .pub-brand-open:hover .pub-brand-reflect { opacity: 1; }
}

/* Lade-Aufblinken (Teil 12/13, Reveal-Phase) -- Nutzeranweisung (3. Folgekorrektur): "der Opening-
   Pulse in Kreisform soll auch der X-Glow-Effekt sein, loesche den Kreis, X einmal beim Laden
   aufblinken lassen". Ersetzt die vorherige Drei-Farb-Kreis-Annaeherung (drei gestaffelte
   radial-gradient-Spans in Blue/Cyan/Violet) durch EIN einzelnes Aufblinken derselben X-Grafik wie
   bei der Hover-Reflexion -- die Grafik selbst enthaelt bereits den vollen Farbverlauf, ein
   zusaetzliches Drei-Schritt-Farbmapping ist nicht mehr noetig. Spielt EINMALIG waehrend
   .pub-brand-play (siehe Reveal-Sequenz unten), endet vollstaendig bei Opazitaet 0 -> kein
   dauerhafter Glow (User-Feedback v10.1(11): "keinen Grand Schleier" -- bewusst nur ein kurzer,
   einmaliger Reveal-Akzent). */
@media (prefers-reduced-motion: no-preference) {
  .pub-brand-play .pub-brand-xflash { animation: pub-brand-xflash-blink 900ms ease forwards; animation-delay: 700ms; }
}
@keyframes pub-brand-xflash-blink { 0%, 100% { opacity: 0; } 45% { opacity: .9; } }

/* Boden-Reflexion (Teil 26): derselbe Puls, tiefer positioniert (Bodenflaeche unter dem Wordmark),
   deutlich schwaecher (Echo-Charakter, kein zweites Logo) und minimal zeitversetzt NACH dem
   Haupt-Energie-Fluss oben -- wirkt wie eine kurze Reflexion, die "ankommt". */
.pub-brand-floor {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; opacity: 0;
  background: radial-gradient(360px circle at var(--x-cx, 62.5%) 84%, rgba(0,180,255,.16), transparent 60%);
  mix-blend-mode: screen;
}
@media (prefers-reduced-motion: no-preference) {
  .pub-brand-play .pub-brand-floor { animation: pub-brand-floor-pulse 900ms ease forwards; animation-delay: 900ms; }
}
@keyframes pub-brand-floor-pulse { 0%, 100% { opacity: 0; } 50% { opacity: .35; } }
@media (max-width: 900px) { .pub-brand-floor { display: none; } }

.pub-brand-center { display: flex; flex-direction: column; align-items: center; gap: 10px; position: relative; z-index: 1; }
/* Beide Themes zeigen jetzt ein Foto (>=900px), das bereits "TALVAXO" selbst zeigt -- das
   CSS-Wordmark hier waere ein sichtbares Duplikat davor, deshalb per Default ausgeblendet und nur
   unter 900px wieder eingeblendet (siehe dortige Media-Query), wo das Foto seinerseits ausgeblendet
   wird. */
.pub-brand-wordmark {
  position: relative; z-index: 1; display: none;
  align-items: center; justify-content: center;
  margin: 0; opacity: 0; transform: scale(0.94);
}
.pub-brand-wordmark img { display: block; height: clamp(40px, 6vw, 64px); width: auto; }
.pub-brand-tagline {
  font-family: var(--font-mono); font-size: 15px; letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--talvaxo-pub-text-muted); margin: 0; opacity: 0; transform: translateY(8px);
}
.pub-brand-divider { display: flex; align-items: center; gap: 14px; margin-top: 4px; opacity: 0; transform: translateY(8px); }
.pub-brand-divider-line { width: 46px; height: 1px; background: var(--talvaxo-pub-border); }
.pub-brand-divider p { margin: 0; font-family: var(--font-mono); font-size: 12.5px; letter-spacing: 0.22em; color: var(--talvaxo-pub-text-muted); }
/* Kontrast-Sicherung ueber dem Foto-Hintergrund -- gilt jetzt fuer BEIDE Themes (beide zeigen ab
   v10.1(11) Light-Mode-Header-Pass ein Foto >=900px), Halo-Farbe je Theme angepasst, plus der
   .pub-brand-scrim-Verlauf darunter (siehe oben) als zweite, bildunabhaengige Absicherung. */
:root:not([data-theme="light"]) .pub-brand-tagline,
:root:not([data-theme="light"]) .pub-brand-divider p {
  color: var(--talvaxo-pub-text);
  text-shadow: 0 1px 4px rgba(0,0,0,.85), 0 0 12px rgba(0,0,0,.6);
}
[data-theme="light"] .pub-brand-tagline,
[data-theme="light"] .pub-brand-divider p {
  color: var(--talvaxo-pub-text);
  text-shadow: 0 1px 4px rgba(255,255,255,.85), 0 0 12px rgba(255,255,255,.7);
}
.pub-brand-scrollcue {
  margin-top: 8px; width: 20px; height: 32px; border: 1.5px solid var(--talvaxo-pub-border); border-radius: 11px;
  opacity: 0; display: flex; justify-content: center; padding-top: 6px; box-sizing: border-box;
}
.pub-brand-scrollcue span { width: 3px; height: 7px; border-radius: 2px; background: var(--talvaxo-pub-cyan); display: block; }

@media (max-width: 900px) {
  /* Seitliche Wortstapel sind reine Desktop-Zier (User-Skizze) -- auf schmaleren Viewports kein
     Platz ohne das zentrale Wordmark zu quetschen; ausblenden statt umbrechen. */
  .pub-brand-open { grid-template-columns: 1fr; }
  .pub-brand-side { display: none; }
  /* Bug-Fund: das Header-Bild ist ein sehr breites 3:1-Panorama (2172x724) -- object-fit:cover
     schneidet bei schmalen Viewports Anfang/Ende des Wortmarks ("T"/"O") sichtbar ab, egal welche
     object-position gewaehlt wird (die Sektion ist dort schlicht schmaler als das Bild lang ist).
     Unter 900px daher zurueck auf das bereits verifizierte CSS-Wordmark, dieselbe Loesung wie fuer
     Light Mode. */
  .pub-brand-header-bg { display: none; }
  .pub-brand-wordmark { display: flex; }
  .pub-brand-tagline, .pub-brand-divider p { color: var(--talvaxo-pub-text-muted); text-shadow: none; }
  .pub-brand-side { color: var(--talvaxo-pub-text-muted); text-shadow: none; }
}
@media (max-width: 640px) {
  /* Mandat: Logo soll auf Mobile "wichtig" wirken, nicht geschrumpft. */
  .pub-brand-open { min-height: 26vh; padding: 24px 22px 18px; gap: 8px; }
  .pub-brand-wordmark img { height: clamp(34px, 11vw, 46px); }
}

/* ---- Reveal-Sequenz -- identisches Presequence/Play-Muster wie .pub-hero-seq-N (siehe unten),
   nur mit @keyframes statt Transitions fuer die mehrstufige Farb-Erzaehlung. JS setzt
   .pub-brand-play NIE bei reduced motion (siehe public.js). ---- */
@media (prefers-reduced-motion: no-preference) {
  .pub-brand-play .pub-brand-header-bg { animation: pub-brand-header-bg-reveal 1400ms cubic-bezier(.22,.61,.36,1) forwards; }
  .pub-brand-play .pub-brand-wordmark { animation: pub-brand-wordmark-reveal 2600ms cubic-bezier(.22,.61,.36,1) forwards; }
  .pub-brand-play .pub-brand-tagline { animation: pub-brand-fade-up 600ms ease forwards; animation-delay: 1750ms; }
  .pub-brand-play .pub-brand-divider { animation: pub-brand-fade-up 600ms ease forwards; animation-delay: 1950ms; }
  .pub-brand-play .pub-brand-scrollcue { animation: pub-brand-fade-up 550ms ease forwards; animation-delay: 2150ms; }
  .pub-brand-play .pub-brand-scrollcue span { animation: pub-brand-scrollcue-dot 1900ms ease-in-out 2700ms infinite; }
  .pub-brand-play .pub-brand-side--left { animation: pub-brand-side-in-left 700ms ease forwards; animation-delay: 1600ms; }
  .pub-brand-play .pub-brand-side--right { animation: pub-brand-side-in-right 700ms ease forwards; animation-delay: 1600ms; }
}
@keyframes pub-brand-wordmark-reveal {
  0%   { opacity: 0; transform: scale(0.94); }
  22%  { opacity: 1; transform: scale(1); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes pub-brand-header-bg-reveal {
  0%   { opacity: 0; transform: scale(1.03); }
  100% { opacity: 1; transform: scale(1); }
}
@keyframes pub-brand-fade-up { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes pub-brand-side-in-left { from { opacity: 0; transform: translateX(-8px); } to { opacity: 1; transform: none; } }
@keyframes pub-brand-side-in-right { from { opacity: 0; transform: translateX(8px); } to { opacity: 1; transform: none; } }
@keyframes pub-brand-scrollcue-dot { 0%, 100% { transform: translateY(0); opacity: .4; } 50% { transform: translateY(9px); opacity: 1; } }

/* Default (no JS / reduced motion): everything already visible via base opacity:1 override below,
   so the section works with zero JS dependency (progressive enhancement, same principle as Hero). */
.pub-brand-open:not(.pub-brand-presequence) .pub-brand-header-bg,
.pub-brand-open:not(.pub-brand-presequence) .pub-brand-wordmark,
.pub-brand-open:not(.pub-brand-presequence) .pub-brand-tagline,
.pub-brand-open:not(.pub-brand-presequence) .pub-brand-divider,
.pub-brand-open:not(.pub-brand-presequence) .pub-brand-scrollcue,
.pub-brand-open:not(.pub-brand-presequence) .pub-brand-side { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .pub-brand-header-bg, .pub-brand-wordmark, .pub-brand-tagline, .pub-brand-divider, .pub-brand-scrollcue, .pub-brand-side { opacity: 1 !important; transform: none !important; }
  .pub-brand-scrollcue span { animation: none !important; }
}
.pub-motion-off .pub-brand-header-bg,
.pub-motion-off .pub-brand-wordmark, .pub-motion-off .pub-brand-tagline, .pub-motion-off .pub-brand-divider,
.pub-motion-off .pub-brand-scrollcue, .pub-motion-off .pub-brand-side {
  opacity: 1 !important; transform: none !important; animation: none !important;
}
.pub-motion-off .pub-brand-scrollcue span { animation: none !important; }

/* Nav transparent/minimal ueber der Brand Opening (Mandat Teil 6/7) -- IntersectionObserver in
   public.js togglet is-over-opening waehrend #pub-brand-open sichtbar ist; .is-scrolled (bestehend,
   scrollTop>8) uebernimmt danach automatisch wieder die normale Oberflaeche. */
.pub-nav.is-over-opening { background: transparent; backdrop-filter: none; border-bottom-color: transparent; }

/* ============ HERO ============ */
/* Mandat "BRAND EXPERIENCE" Teil 5/6: bewusst kein striktes 50/50 mehr -- die Produktseite bekommt
   den groesseren Anteil (0.86fr : 1.28fr statt 1fr : 1.1fr) und darf per negativem Bottom-Margin
   unter die eigentliche Hero-Grundlinie in den Wave-Bereich hineinreichen (siehe .pub-hero-window),
   statt zwei strikt getrennte Spalten zu sein. */
/* Mandat "CINEMATIC" Teil 15: der erste Screen soll sich wie ein Erlebnis anfuehlen -- min-height
   statt fixem height, damit laengerer Content (z. B. kleinere Breiten mit mehr Zeilenumbruch) nie
   abgeschnitten wird. */
.pub-hero {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 0.86fr 1.28fr; gap: 48px; align-items: center;
  max-width: 1520px; margin: 0 auto; padding: 80px 40px 56px;
  /* Website-Feedback-Pass (2026-09-26, Nutzer-Fund "Sektion viel zu gross, Abstand oben/unten zu
     gross"): min-height:92vh zwang den Inhalt (Copy/Window messen ca. 460px) in eine viel zu
     grosse Box, die per align-items:center vertikal zentriert wurde -- das erzeugte ca. 440px
     Leerraum oben und ca. 380px unten, weit ueber echtes Padding hinaus (gemessen per
     getBoundingClientRect bei 1321px Viewport-Hoehe). Ersetzt durch inhaltsgetriebenes Padding,
     die Sektion umschliesst jetzt ihren Inhalt statt eine feste Bildschirm-Fraktion zu erzwingen. */
  box-sizing: border-box;
  /* v10.1(11) Bug-Fund (check_overflow.py, 1024x768): .pub-window--float (die schwebende
     Decision-Karte, per Parallax-Transform positioniert) reicht am 1024px-Breakpoint um ~2px
     ueber den rechten Seitenrand hinaus -- overflow-x:clip (NICHT hidden, das wuerde auch den
     bewusst gewuenschten vertikalen Bleed von .pub-hero-window in den Wave-Bereich kappen, siehe
     margin-bottom:-64px oben) schneidet nur die horizontale Achse. */
  overflow-x: clip;
}
.pub-hero-logo { display: block; width: min(300px, 78%); height: auto; margin-bottom: 26px; }
.pub-hero-logo--light { display: none; }
[data-theme="light"] .pub-hero-logo--dark { display: none; }
[data-theme="light"] .pub-hero-logo--light { display: block; }
/* Login-Claim (Mandat Teil 3/70/71): bleibt Englisch in DE UND EN, siehe HTML-Kommentar in
   index.html. Groesser als die bisherige Product-Headline (Mandat Teil 48: Claim > Produkt-
   Headline), da er jetzt die primaere Hero-Aussage ist. */
/* Visual Redesign Execution Pass §12 ("Hero — Material Redesign", §76 "immediately noticeable"):
   42px read as a page subheading, not a hero moment -- the product visual (55-70% of hero width per
   the pre-existing composition rule below) was doing more visual work than the claim itself. Scaled
   up to genuine display size, letter-spacing tightened slightly at this size (large display type
   needs negative tracking to avoid looking loose -- standard type practice, not an invented rule). */
.pub-hero-claim { font-family: var(--font-display); font-size: 60px; line-height: 1.08; letter-spacing: -0.01em; font-weight: 700; margin: 0 0 22px; text-wrap: balance; }
.pub-hero-sub { font-size: 18px; line-height: 1.6; color: var(--text-muted); max-width: 42ch; margin: 0 0 36px; }
/* At the claim's new 60px size, the generic 11px .pub-eyebrow read as an afterthought immediately
   beneath it -- a touch larger keeps it legible as its own line, not a rounding error next to the
   claim. */
.pub-hero-eyebrow { font-size: 13px; letter-spacing: 0.12em; margin: 0 0 18px; }
.pub-hero-ctas { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; }

/* Hero product window composition -- 55-70% der visuellen Hero-Flaeche (Mandat Teil 6), reicht
   bewusst unter die Hero-Grundlinie in den Wave-Bereich (Teil 5/56). */
.pub-hero-window { position: relative; min-height: 460px; display: flex; align-items: center; justify-content: center; margin-bottom: -64px; padding-bottom: 64px; }

/* Hero Athlete Band (Mandat "DESIGN PRINT IMPLEMENTATION" Teil 10-27). "Runner/Linien ueber die
   volle Breite, er bleibt im Hintergrund, die Wave liegt UEBER dem Runner, darueber erst die
   Website-Elemente, nur im obersten Feld sichtbar" (User-Skizze aus einem frueheren Pass, weiterhin
   gueltig). Seit diesem Pass ein vom User direkt bereitgestelltes photorealistisches Foto/Render mit
   ECHTEM Alpha-Cutout (talvaxo-runner-male-v3, siehe TALVAXO_ATHLETE_ASSET_AUDIT.md) -- kein
   mask-image-Workaround mehr noetig, das Quellbild bringt sein eigenes weiches, transparentes
   Glow-Fadeout bereits mit. Stacking-Loesung unveraendert: das Band liegt als direktes Geschwister
   VOR den Wave-Canvases im DOM und bewusst AUSSERHALB von .pub-hero (das seinen eigenen
   z-index:1-Stacking-Context oeffnet, aus dem ein Nachfahre nie unter die global-fixe Wave-Canvas
   gelangen koennte). Mit z-index:-1 auf Root-Ebene sitzt es zuverlaessig HINTER der Wave (z-index:0)
   und HINTER dem Seitenhintergrund -- die Wave zeichnet sichtbar ueber den Laeufer. position:absolute
   (nicht fixed) verankert am Dokumentanfang, damit es beim Scrollen normal wegscrollt (bleibt "nur im
   obersten Feld"), nicht wie die Wave dauerhaft haften bleibt. */
.pub-hero-athlete-band {
  position: absolute; top: 0; left: 0; width: 100%; height: min(980px, 100vh);
  z-index: -1; overflow: hidden; pointer-events: none;
}
.pub-hero-athlete {
  /* Master-Design (real erhaltene Screenshots, nicht nur Blueprint-Text): Laeufer sitzt visuell
     ZWISCHEN Brand-Copy und Product-UI (Blueprint: "visual center x≈850-940 bei 1440px", NICHT
     einfach rechtsbuendig) und wird vom Product-Fenster spuerbar ueberlappt (~15-25%). Vorheriger
     Wert (right:2%) haette bei 1440px einen visuellen Mittelpunkt bei ~81% erzeugt -- deutlich zu
     weit rechts, mit kaum Ueberlappung zum Fenster. right:20% verschiebt den Mittelpunkt auf ~62%. */
  position: absolute; right: 20%; bottom: 1%;
  height: 73%; width: auto;
  display: block;
  filter: drop-shadow(0 0 46px rgba(0,122,255,0.28));
  transition: transform 480ms cubic-bezier(.2,.8,.2,1), opacity 320ms ease;
  /* --px/--py werden von der bestehenden Hero-Pointer-Logik auf #pub-hero-tilt gesetzt und
     vererben sich NICHT hierher (anderer Teilbaum) -- eigene, separate Parallax-Zuweisung in
     public.js auf #pub-hero-athlete-band selbst (Mandat Teil 25: Athlete 2-3px). */
  transform: translate3d(calc(var(--apx, 0) * 3px), calc(var(--apy, 0) * 3px), 0);
}
.pub-hero-athlete img { display: block; width: auto; height: 100%; object-fit: contain; }
/* Light Mode: leicht reduzierte Deckkraft (statt 1:1 wie im Dark Mode) haelt das dunkle Foto
   erkennbar als eigenes Element von der helleren Seitenflaeche abgesetzt, ohne wie in einer
   frueheren Fassung dieser Regel (0.3) fast unsichtbar/"verschleiert" zu wirken -- User-Feedback:
   bei zu niedriger Deckkraft wirkt der Laeufer nur noch transparent statt integriert. */
[data-theme="light"] .pub-hero-athlete { opacity: 0.9; }
@media (max-width: 980px) {
  .pub-hero-athlete-band { height: min(820px, 100vh); }
  .pub-hero-athlete { right: 10%; height: 58%; bottom: 1%; }
}
@media (max-width: 640px) {
  /* Mobile: eigene Position statt verkleinertem Desktop-Bild (Mandat Teil 17/18) -- etwas
     zentraler und kleiner, damit er nicht mit der Nav/dem Claim kollidiert, bleibt aber klar
     erkennbar praesent, nicht dekorativ-winzig. */
  .pub-hero-athlete-band { height: min(760px, 100vh); }
  .pub-hero-athlete { right: 50%; transform: translate3d(calc(50% + var(--apx, 0) * 3px), calc(var(--apy, 0) * 3px), 0); height: 50%; bottom: 2%; }
  /* Bug gefunden bei der V10.1-Screenshot-Matrix (390x844, Light): der "Mehr erfahren"-Link liegt
     im Fliesstext unterhalb des CTA-Buttons genau in der Zone, in der das Athlete-Band (s.o.)
     durchscheint -- ohne eigenen Hintergrund kollidiert dunkler Light-Mode-Text dort mit der
     dunklen Laeuferkleidung (fast unlesbar). Halo statt Neupositionierung, da die Athlete-Position
     bereits ueber mehrere Mandate hinweg bewusst abgestimmt wurde. */
  .pub-hero-more { text-shadow: 0 0 10px var(--bg), 0 0 3px var(--bg), 0 1px 2px var(--bg); }
}
@media (prefers-reduced-motion: reduce) {
  .pub-hero-athlete { transform: none !important; transition: none !important; }
}
.pub-motion-off .pub-hero-athlete { transform: none !important; transition: none !important; }
.pub-window {
  background: color-mix(in srgb, var(--panel) 92%, transparent);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border-soft); border-radius: 18px;
  box-shadow: 0 30px 70px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.02) inset;
  overflow: hidden;
}
.pub-window--main { width: 100%; max-width: 620px; }
.pub-window--main .pub-window-body { padding: 34px; gap: 32px; }
.pub-window--main .pub-window-ring { width: 128px; height: 128px; }
.pub-window--main .pub-ring-label b { font-size: 32px; }
.pub-window--main .pub-window-row { font-size: 15.5px; }
.pub-window--main .pub-window-row span { font-size: 11px; }

/* Hero Product-Window "live" content (Master-Design: Begruessung + Readiness + Empfohlenes Training
   + WARUM DAS HEUTE-Liste, statt einer reduzierten 3-Zeilen-Card -- siehe HTML-Kommentar). */
.pub-window--hero-live { padding: 30px 34px 26px; display: flex; flex-direction: column; gap: 18px; }
.pub-hero-greeting { margin: 4px 0 0; font-size: 15px; font-weight: 600; color: var(--text); }
.pub-hero-live-top { display: flex; align-items: center; gap: 24px; }
.pub-hero-live-top .pub-window-ring { width: 96px; height: 96px; }
.pub-hero-live-top .pub-ring-label b { font-size: 22px; }
.pub-hero-live-stats { display: flex; flex-direction: column; gap: 14px; flex: 1; min-width: 0; }
.pub-hero-live-stat { display: flex; flex-direction: column; gap: 3px; }
.pub-hero-live-stat b { font-size: 15px; color: var(--text); }
.pub-hero-live-stat small { font-size: 11.5px; color: var(--text-dim); }
.pub-hero-live-label { display: block; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; color: var(--text-dim); text-transform: uppercase; margin-bottom: 6px; }
.pub-hero-live-why { border-top: 1px solid var(--hairline); padding-top: 16px; }
.pub-hero-live-why-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 8px 20px; }
.pub-hero-live-why-list li { display: flex; align-items: center; justify-content: space-between; font-size: 12.5px; gap: 10px; }
.pub-hero-live-why-list li span { color: var(--text-dim); }
.pub-hero-live-why-list li b { color: var(--text); font-weight: 600; }
/* Duenne, dekorative Verbindungslinie vom Hero-Fenster zur schwebenden Adaptive-Entscheidung-Karte
   (Master-Design: WARUM-Zeilen fliessen sichtbar in die Entscheidung) -- rein atmosphaerisch, hinter
   beiden Karten (z-index 0), kein eigener Interaktions-/Informationswert. */
.pub-hero-live-link { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; overflow: visible; }
.pub-hero-live-link path { fill: none; stroke: var(--talvaxo-violet); stroke-width: 1.5; opacity: 0.35; stroke-dasharray: 3 4; }
.pub-hero-details-btn {
  align-self: flex-start; margin-top: 4px; background: none; border: 1px solid rgba(122,92,255,0.35);
  color: var(--talvaxo-violet); font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em;
  padding: 8px 14px; border-radius: 8px; cursor: pointer; transition: border-color 200ms ease, background 200ms ease;
}
.pub-hero-details-btn:hover, .pub-hero-details-btn:focus-visible { border-color: var(--talvaxo-violet); background: rgba(122,92,255,0.08); }
.pub-window-bar { display: flex; align-items: center; gap: 6px; padding: 14px 18px; border-bottom: 1px solid var(--hairline); }
.pub-window-bar span { width: 8px; height: 8px; border-radius: 50%; background: var(--text-dim); opacity: 0.5; }
.pub-window-bar b { margin-left: 10px; font-size: 11.5px; font-weight: 600; color: var(--text-muted); font-family: var(--font-mono); letter-spacing: 0.04em; }
/* Product Experience Closure Mandat §9-10: honest "this is illustrative" label on the hero product
   preview -- muted enough not to fight the app-window illusion, legible enough to actually be read. */
.pub-window-badge { margin-left: auto; font-style: normal; font-size: 9.5px; font-weight: 600; letter-spacing: 0.05em; color: var(--text-dim); font-family: var(--font-mono); white-space: nowrap; padding: 3px 8px; border-radius: 999px; background: var(--status-neutral-dim); }
@media (max-width: 480px) {
  /* Narrow the bar wraps rather than hides -- the "this is a preview" disclosure matters most on
     the device most visitors actually use, not least (Mandat §9: honesty, not just desktop). */
  .pub-window-bar { flex-wrap: wrap; row-gap: 6px; }
  .pub-window-badge { margin-left: 24px; }
}
.pub-window-body { padding: 26px; display: flex; align-items: center; gap: 26px; }
.pub-window-body--stack { flex-direction: column; align-items: stretch; gap: 18px; }
.pub-window-body--stack .pub-baseline-range { width: 100%; }
.pub-window-body--stack .pub-baseline-legend { justify-content: space-between; }
.pub-window-ring { position: relative; width: 100px; height: 100px; flex-shrink: 0; }
.pub-ring-svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.pub-ring-track { fill: none; stroke: var(--hairline); stroke-width: 9; }
.pub-ring-value { fill: none; stroke: var(--talvaxo-cyan); stroke-width: 9; stroke-linecap: round; stroke-dasharray: calc(52 * 3.14159 * 2); stroke-dashoffset: calc(52 * 3.14159 * 2 * (1 - var(--ring-pct, 0.7))); filter: drop-shadow(0 0 6px rgba(0,229,255,0.5)); }
.pub-ring-label { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; }
.pub-ring-label b { font-size: 26px; font-family: var(--font-display); }
.pub-ring-label small { font-size: 9.5px; letter-spacing: 0.08em; color: var(--text-dim); font-family: var(--font-mono); }
.pub-window-rows { display: flex; flex-direction: column; gap: 12px; flex: 1; }
.pub-window-row { display: flex; align-items: center; justify-content: space-between; font-size: 13.5px; gap: 12px; }
.pub-window-row span { color: var(--text-dim); font-size: 10.5px; letter-spacing: 0.06em; font-family: var(--font-mono); }
.pub-window-row b { color: var(--text); font-weight: 600; text-align: right; }
/* Bug gefunden bei der Athlete-Product-Preview-Verifikation: .pub-window-row b (Spezifitaet 0,1,1)
   ueberstimmt .pub-good/-warn/-bad (0,1,0) unabhaengig von der Quellreihenfolge -- Status-Farben
   in JEDEM .pub-window-row auf der Seite (auch das bereits bestehende Hero-Fenster) haben dadurch
   nie sichtbar gegriffen. Praezisere Selektoren statt !important. */
.pub-window-row b.pub-good { color: var(--status-good); }
.pub-window-row b.pub-warn { color: var(--status-warn); }
.pub-window-row b.pub-bad { color: var(--status-bad); }

.pub-window--float { position: absolute; }
.pub-window--decision { bottom: -18px; right: -30px; padding: 18px 22px; max-width: 220px; border-color: rgba(122,92,255,0.4); }
/* Decision/output elements are Violet (Intelligence Color Flow: Blue/Cyan data+analysis IN, Violet
   decision OUT) -- consistent across every "this is the adaptive decision" element on the page. */
.pub-window-eyebrow { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; color: var(--talvaxo-violet); margin-bottom: 10px; }
.pub-window-decision-row { display: flex; align-items: center; gap: 8px; font-size: 15px; }
.pub-window-decision-row svg { width: 14px; height: 14px; color: var(--talvaxo-violet); }
.pub-window-decision-row b { color: var(--talvaxo-violet); font-size: 17px; }
.pub-strike { color: var(--text-dim); text-decoration: line-through; }

@media (max-width: 1180px) and (min-width: 981px) {
  .pub-hero { gap: 32px; padding-left: 28px; padding-right: 28px; }
  .pub-hero-claim { font-size: 46px; }
  .pub-hero-logo { width: min(260px, 78%); }
}

@media (max-width: 980px) {
  /* Mobile Reihenfolge (Mandat Teil 65): Logo -> Claim -> Copy -> CTA -> Product Window -- bereits
     die DOM-Reihenfolge, hier nur noch die Desktop-Ueberlapp-Komposition zurueckgenommen (der
     negative Bottom-Margin/Overflow-Trick ist ein Desktop-Kompositionsmittel, gestapelt braucht die
     Seite stattdessen normalen Abstand). */
  .pub-hero { grid-template-columns: 1fr; padding: 44px 22px 60px; gap: 36px; min-height: auto; }
  .pub-hero-claim { font-size: 40px; }
  .pub-hero-logo { width: min(240px, 70%); margin: 0 auto 22px; }
  .pub-hero-window { min-height: 320px; margin-bottom: 0; padding-bottom: 0; }
  .pub-window--decision { right: 0; bottom: -14px; }
}
@media (max-width: 640px) {
  .pub-hero-copy { text-align: center; }
  .pub-hero-ctas { justify-content: center; }
  /* Mobile: die Adaptive-Entscheidung-Karte sitzt bottom-right ueber dem vollbreiten Hero-Fenster
     (Mandat/Master: bleibt als schwebende Karte erhalten, keine Desktop-Verkleinerung) -- ohne
     Anpassung ueberlappt sie die rechte Spalte der WARUM-DAS-HEUTE-Liste. Liste wird einspaltig,
     Fenster bekommt unten mehr Luft, damit nichts verdeckt wird. */
  .pub-hero-live-why-list { grid-template-columns: 1fr; }
  .pub-window--hero-live { padding-bottom: 74px; }
}
@media (max-width: 480px) {
  .pub-hero-claim { font-size: 32px; }
  .pub-window-body { flex-direction: column; align-items: flex-start; gap: 18px; }
}

/* ============ SECTIONS ============ */
.pub-section { position: relative; z-index: 1; padding: 96px 32px; }
/* Website-Feedback-Pass (2026-09-26, "ohne Abstand direkt nach dem Hero"): die Cinematic-Runner-
   Szene folgt unmittelbar auf den Hero (siehe Verschiebungs-Kommentar in index.html) -- die normale
   .pub-section-Basis-Polsterung von 96px oben addierte sich mit .pub-cinematic-break's eigenem
   Innenabstand zu spuerbarem Leerraum. Nur der obere Abstand entfernt, unten bleibt die normale
   Polsterung (Uebergang zur naechsten Sektion unveraendert). Traegt seit dem "Final Public Website
   Composition"-Mandat (2026-09-26, Athlete-Preview zog nach #product um) die ID #runner-scene statt
   #athletes -- #athletes bezeichnet jetzt ausschliesslich die verschobene Preview-Sektion, die ganz
   normale Section-Polsterung braucht (sitzt nicht mehr direkt am Hero). */
#runner-scene.pub-section { padding-top: 0; }
/* Website-Feedback-Pass (2026-09-26, "visuelle Abwechslung"): die Struktur (canvas -> alt -> plain
   -> alt) war bereits korrekt alternierend, der Tint war beim tatsaechlichen Durchscrollen aber zu
   schwach, um bewusst als Rhythmus-Signal wahrgenommen zu werden -- von 45% auf 68% angehoben, plus
   dezente Top-/Bottom-Trennlinien, damit der Sektionswechsel sichtbar, nicht nur messbar ist. */
.pub-section--alt {
  background: color-mix(in srgb, var(--panel) 68%, transparent);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
/* Intelligence Canvas: eigene, sehr dezente technische Atmosphaere (Mandat "CINEMATIC" Teil 31) --
   ein feines Punktraster, keine Matrix/HUD-Optik. */
.pub-section--canvas {
  position: relative;
  background-image: radial-gradient(circle, rgba(0,229,255,0.16) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, black 40%, transparent 90%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, black 40%, transparent 90%);
}
.pub-section-inner { max-width: 760px; margin: 0 auto 44px; text-align: center; }
.pub-eyebrow { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; color: var(--talvaxo-cyan); margin: 0 0 14px; text-transform: uppercase; }
.pub-section h2 { font-family: var(--font-display); font-size: 32px; line-height: 1.25; font-weight: 700; margin: 0 0 4px; text-wrap: balance; }
.pub-section-lead { font-size: 16px; line-height: 1.65; color: var(--text-muted); max-width: 60ch; margin: 16px auto 0; }
/* Bug-Fund (User-Feedback): --text-dim (fuer einzelne kleine Labels gedacht) war fuer einen
   ganzen Satz Disclaimer-Text ueber der visuell unruhigen Wave-Linien-Grafik kaum lesbar -- eine
   Stufe heller (--text-muted) plus ein dunkler (nicht hintergrundfarbener) Text-Shadow als echter
   Kontrast-Scrim, statt eines bg-farbenen Halos, der auf dem ohnehin dunklen Hintergrund kaum
   Wirkung zeigte. */
.pub-disclaimer { font-size: 12px; color: var(--text-muted); margin: 32px auto 0; max-width: 62ch; text-align: center; text-shadow: 0 1px 2px rgba(0,0,0,0.9), 0 0 8px rgba(0,0,0,0.9), 0 0 20px rgba(0,0,0,0.7); }
/* Website-Feedback-Pass (2026-09-26, "Redundanz reduzieren"): siehe Kommentar in index.html an der
   Nutzungsstelle. Ausblenden statt Loeschen -- Klasse einfach entfernen, um wiederherzustellen. */
.pub-hidden-redundant { display: none !important; }

/* Website-Feedback-Pass (2026-09-26, "menschliche Note"): kompakte Gruender-Notiz direkt vor dem
   Beta-Formular, siehe index.html fuer den Platzierungs-/Inhalts-Hinweis. Kein Karten-Chrome wie
   .pub-window -- ein Zitat mit echtem Foto/Byline, kein weiteres Produkt-Feature. */
.pub-founder-note { padding-top: 64px; padding-bottom: 64px; }
.pub-founder-note-inner { max-width: 620px; }
.pub-founder-quote {
  font-family: var(--font-display); font-weight: 600; font-size: 24px; line-height: 1.45;
  color: var(--text); margin: 0 0 18px; text-wrap: balance; font-style: normal;
  position: relative; padding: 0 8px;
}
.pub-founder-quote::before {
  content: '\201C'; color: var(--talvaxo-cyan); opacity: 0.55; font-size: 48px;
  font-family: Georgia, serif; line-height: 0; position: absolute; left: -22px; top: 22px;
}
.pub-founder-body { font-size: 15px; line-height: 1.65; color: var(--text-muted); margin: 0 0 16px; }
/* Byline (2026-09-26, Nutzerwunsch "Foto fuer Glaubwuerdigkeit"): echtes Profilfoto statt reinem
   Text-Signatur -- .pub-founder-note-inner ist text-align:center (geerbt von .pub-section-inner),
   daher hier explizit auf linksbuendig zurueckgesetzt, damit Foto+Name wie eine Byline nebeneinander
   sitzen statt zentriert zu vereinzeln. */
.pub-founder-byline { display: flex; align-items: center; gap: 14px; text-align: left; }
.pub-founder-photo {
  width: 52px; height: 52px; border-radius: 50%; object-fit: cover; flex-shrink: 0;
  border: 1.5px solid var(--talvaxo-cyan);
}
.pub-founder-byline-text { display: flex; flex-direction: column; gap: 2px; }
.pub-founder-name { font-size: 14px; font-weight: 700; color: var(--text); margin: 0; }
.pub-founder-role { font-size: 12.5px; color: var(--talvaxo-cyan); font-weight: 600; margin: 0; }

@media (max-width: 640px) {
  .pub-section { padding: 60px 20px; }
  .pub-section h2 { font-size: 25px; }
}

/* Signals flow (Section 02) */
.pub-signals-section { padding-bottom: 60px; }
/* Complete Visual Redesign Mandat §5/§11: the merged "problem" + "how TALVAXO thinks" beats now
   share one section; a thin separator plus extra top space marks the second beat as a distinct
   story step without needing a whole new section wrapper. */
.pub-section-inner--follow-up { margin-top: 72px; padding-top: 56px; border-top: 1px solid var(--border-soft); }
@media (max-width: 640px) { .pub-section-inner--follow-up { margin-top: 48px; padding-top: 40px; } }
.pub-signals-flow { display: flex; align-items: center; justify-content: center; gap: 16px; flex-wrap: wrap; max-width: 1100px; margin: 0 auto; }
.pub-signal-chip { background: var(--panel); border-radius: 12px; padding: 12px 16px; display: flex; flex-direction: column; gap: 4px; min-width: 110px; border-left: 3px solid var(--status-bad); }
.pub-signal-chip--bad { border-left-color: var(--status-bad); }
.pub-signal-chip--warn { border-left-color: var(--status-warn); }
.pub-signal-chip span { font-size: 11px; letter-spacing: 0.06em; color: var(--text-muted); font-family: var(--font-mono); }
.pub-signal-chip b { font-size: 15px; }
.pub-signals-arrow { width: 22px; height: 22px; color: var(--text-dim); flex-shrink: 0; }
/* Nutzeranweisung ("hier auch tauschen"): keine blaue Kreis-Badge mehr, siehe .pub-think-core fuer
   dieselbe Aenderung -- die freigestellte X-Grafik ist jetzt selbst das Element, Glow per
   drop-shadow statt box-shadow. */
.pub-signals-x { width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; filter: drop-shadow(0 0 16px rgba(0,229,255,0.4)); transition: filter 220ms ease; }
.pub-signals-x img { width: 100%; height: auto; display: block; }
.pub-decision-result { background: var(--panel); border: 1px solid rgba(0,229,255,0.3); border-radius: 16px; padding: 22px 26px; text-align: left; min-width: 260px; }
.pub-decision-result-title { font-size: 15px; color: var(--text-muted); margin-bottom: 6px; }
.pub-decision-result-change { display: flex; align-items: center; gap: 10px; font-size: 17px; margin-bottom: 16px; }
.pub-decision-result-change svg { width: 15px; height: 15px; color: var(--talvaxo-cyan); }
.pub-decision-result-change b { color: var(--talvaxo-cyan); font-size: 19px; }
.pub-decision-result-change--lg { font-size: 20px; }
.pub-decision-result-change--lg b { font-size: 23px; }
.pub-decision-why { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.pub-decision-why li { font-size: 13.5px; color: var(--text-muted); }
@media (max-width: 860px) { .pub-signals-flow { flex-direction: column; } .pub-signals-arrow { transform: rotate(0); } }

/* How TALVAXO Thinks */
.pub-think-diagram { display: flex; flex-direction: column; align-items: center; gap: 30px; margin-top: 30px; }
.pub-think-inputs { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; max-width: 620px; }
.pub-think-node { display: flex; align-items: center; gap: 8px; background: var(--panel-raised); border: 1px solid var(--border-soft); border-radius: 999px; padding: 10px 18px; font-size: 13px; color: var(--text); }
.pub-think-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--talvaxo-cyan); box-shadow: 0 0 6px rgba(0,229,255,0.6); }
/* Nutzeranweisung ("statt diesem Element koenntest du das X verwenden"): keine blaue Kreis-Badge
   mehr -- die freigestellte X-Grafik (assets/brand/talvaxo-x-mark.png) ist jetzt selbst der
   Diagramm-Mittelpunkt, ohne Kreisflaeche/Text. Glow per drop-shadow (folgt der X-Silhouette,
   anders als box-shadow, das nur an einer rechteckigen/runden Box haengen wuerde). */
.pub-think-core {
  display: flex; align-items: center; justify-content: center;
  width: 96px; height: 96px;
  filter: drop-shadow(0 0 22px rgba(0,229,255,0.35));
}
.pub-think-core img { width: 100%; height: auto; display: block; }
/* Design-Print Teil 34: "Adaptive Entscheidung" als Karte mit 4 Output-Bullets statt einer
   einzelnen Pille -- ersetzt .pub-think-output, gleiche Position im Flow (unter .pub-think-line--out). */
.pub-think-decision-card {
  background: var(--panel); border: 1px solid rgba(122,92,255,0.35); border-radius: 16px;
  padding: 20px 26px; max-width: 320px; text-align: left; transition: box-shadow 260ms ease;
}
.pub-think-decision-sub { font-size: 13px; color: var(--text-muted); margin: 2px 0 14px; }
.pub-think-decision-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.pub-think-decision-list li {
  font-size: 14px; font-weight: 600; color: var(--talvaxo-violet); position: relative; padding-left: 16px;
}
.pub-think-decision-list li::before {
  content: ''; position: absolute; left: 0; top: 7px; width: 6px; height: 6px; border-radius: 50%;
  background: var(--talvaxo-violet); box-shadow: 0 0 6px rgba(122,92,255,0.6);
}
.hl-grad { background: var(--talvaxo-gradient); -webkit-background-clip: text; background-clip: text; color: transparent; }

/* Product chapters */
.pub-chapter { position: relative; z-index: 1; max-width: 1280px; margin: 0 auto; padding: 88px 40px; display: grid; grid-template-columns: 0.85fr 1.15fr; gap: 60px; align-items: center; }
.pub-chapter--reverse { direction: rtl; }
.pub-chapter--reverse > * { direction: ltr; }
.pub-chapter-copy h2 { font-family: var(--font-display); font-size: 30px; font-weight: 700; margin: 0 0 14px; text-wrap: balance; }
.pub-chapter-text { font-size: 15.5px; line-height: 1.65; color: var(--text-muted); max-width: 42ch; }
.pub-chapter-visual { display: flex; justify-content: center; }
.pub-window--wide { width: 100%; max-width: 500px; }
.pub-window-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--hairline); }
.pub-metric-tile { background: var(--panel); padding: 20px; display: flex; flex-direction: column; gap: 6px; }
.pub-metric-tile span { font-size: 11px; letter-spacing: 0.06em; color: var(--text-muted); font-family: var(--font-mono); }
.pub-metric-tile b { font-size: 26px; font-family: var(--font-display); }
.pub-metric-tile small { font-size: 11px; font-weight: 600; letter-spacing: 0.03em; color: var(--text-muted); }
.pub-window-body--plan { flex-direction: column; align-items: stretch; gap: 0; padding: 8px 0; }
.pub-plan-row { display: flex; align-items: center; gap: 14px; padding: 14px 22px; font-size: 14px; border-bottom: 1px solid var(--hairline); }
.pub-plan-row:last-child { border-bottom: none; }
.pub-plan-row span { font-family: var(--font-mono); font-size: 10.5px; color: var(--text-dim); width: 26px; }
.pub-plan-row b { flex: 1; }
/* Die aktive Zeile hat zusaetzliche Geschwister (.pub-plan-change, .pub-plan-why-hint) -- dort darf
   das <b> (Session-Name) nicht mehr aggressiv wachsen und ihnen den Platz wegnehmen, sonst
   schrumpfen die Nachbarn unter ihre Inhaltsbreite und ihr Text laeuft sichtbar ueber die eigene
   Box hinaus (Layout-Bug: Text von .pub-plan-change ueberlappte "WARUM?"). */
.pub-plan-row--active b { flex: 0 1 auto; }
.pub-plan-change, .pub-plan-why-hint { flex-shrink: 0; white-space: nowrap; min-width: max-content; }
.pub-plan-change .pub-strike { flex-shrink: 0; }
.pub-plan-row--active { background: rgba(0,229,255,0.06); }
.pub-plan-change { font-size: 12.5px; color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.pub-plan-change b { color: var(--talvaxo-cyan); flex: none; }
.pub-window--decision-lg { max-width: 500px; padding: 28px 30px; }
.pub-baseline-label { font-size: 11px; letter-spacing: 0.06em; color: var(--text-dim); font-family: var(--font-mono); margin-bottom: 16px; }
.pub-baseline-range { margin-bottom: 20px; }
.pub-baseline-track { position: relative; height: 6px; border-radius: 999px; background: var(--hairline); }
.pub-baseline-marker { position: absolute; left: var(--pos, 50%); top: 50%; transform: translate(-50%, -50%); width: 14px; height: 14px; border-radius: 50%; background: var(--talvaxo-cyan); box-shadow: 0 0 10px rgba(0,229,255,0.6); }
.pub-baseline-legend { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-dim); margin-top: 8px; }
.pub-baseline-today { display: flex; align-items: center; gap: 10px; }
.pub-baseline-today span { font-size: 11px; color: var(--text-muted); font-family: var(--font-mono); }
.pub-baseline-today b { font-size: 20px; }
.pub-baseline-today small { font-size: 11px; font-weight: 600; }

@media (max-width: 980px) {
  .pub-chapter, .pub-chapter--reverse { grid-template-columns: 1fr; direction: ltr; padding: 56px 22px; gap: 32px; text-align: left; }
  .pub-window--wide, .pub-window--decision-lg { max-width: 100%; }
}

/* ---- Cinematic Break / zweiter Athlete-Moment (Mandat "ATHLETE INTEGRATION & CINEMATIC HERO") ----
   Full-bleed visual reset zwischen den technischen Product Chapters, traegt die weibliche Laeuferin
   (echtes Foto mit Alpha-Cutout, siehe index.html + TALVAXO_ATHLETE_ASSET_AUDIT.md). Linksbuendig
   (User-Anweisung), Typografie bleibt zentriert -- auf breiten Viewports getrennte visuelle Zonen,
   auf schmaleren Viewports rueckt der Statement-Block per margin nach rechts, damit er nicht mit
   dem Laeufer kollidiert (siehe .pub-cinematic-statement unten). */
/* Website-Feedback-Pass (2026-09-26, Nutzer-Fund: "Abstand zwischen den Sektionen viel zu gross",
   dann "Laeuferin jetzt viel zu klein, ohne Abstand direkt einfuegen"): der erste Versuch
   reduzierte min-height direkt, was auch das Laeuferin-Foto schrumpfte (.pub-cinematic-athlete ist
   90% DIESER Hoehe, siehe dort). Richtige Trennung: min-height bleibt gross genug fuer ein
   praesentes Foto, die vertikale PADDING (reiner Leerraum, nicht das Foto) wird auf 0 gesetzt --
   die Sektion beginnt jetzt exakt dort, wo #runner-scene selbst beginnt (siehe dortiger
   padding-top:0-Override; hiess zum Zeitpunkt dieser Notiz noch #athletes, siehe Umbenennung beim
   "Final Public Website Composition"-Mandat). */
.pub-cinematic-break {
  position: relative; z-index: 1; overflow: hidden;
  /* Nutzerwunsch (2026-09-27, verdoppelter Scroll-Parallax-Hub, siehe .pub-cinematic-athlete
     unten): 46vh -> 56vh gibt dem jetzt doppelt so grossen Hub (bis zu 56px) auch auf kurzen
     Viewports (getestet bis 640px Hoehe) genug absoluten Platz, ohne den top/bottom-Puffer allein
     auf einen die Laeufer stark verkleinernden Wert hochtreiben zu muessen. */
  min-height: 56vh; display: flex; align-items: center; justify-content: center;
  padding: 0 32px; text-align: center;
  /* Nutzer-Fund (2026-09-26): die Sektion selbst erreichte den Bildschirmrand nicht, weil die
     ELTERN-Section (#runner-scene.pub-section, damals noch #athletes) ihr eigenes 32px
     Links/Rechts-Padding behaelt (nur padding-top wurde dort auf 0 gesetzt). margin: 0 -32px
     bricht exakt aus diesem
     Eltern-Padding aus, damit .pub-cinematic-break selbst bis zum echten Viewport-Rand reicht --
     die eigene padding:0 32px oben bleibt fuer den Innenabstand des Textblocks bestehen, und die
     bestehenden -32px-Offsets auf den Laeufer-Bildern (die dieses eigene Padding kompensieren)
     bleiben dadurch weiterhin korrekt. */
  margin-left: -32px; margin-right: -32px;
}
.pub-track-motif { position: absolute; inset: 0; z-index: 0; opacity: 0.22; pointer-events: none; }
.pub-track-motif svg { width: 100%; height: 100%; }
/* Bug-Fund (User-Feedback): das Quellbild selbst hat den vorderen Schuh direkt an der linken
   Bildkante abgeschnitten (im Foto so komponiert, nicht durch CSS). User-Vorgabe: die Datei
   bleibt unveraendert ("so wie es ist"), stattdessen wird sie per Transform so weit an/ueber den
   linken Rand geschoben, dass genau dieser Bildbereich vom overflow:hidden der Section
   weggeschnitten wird -- translateX() ist relativ zur EIGENEN Bildbreite (nicht zum Container),
   daher an jedem Breakpoint gleich wirksam, ohne Breakpoint-spezifisches Nachjustieren. -28%
   entspricht exakt der Breite des abgeschnittenen Schuhbereichs im Quellbild (verifiziert per
   Alpha-Kanal-Analyse: Schuh-Pixel enden bei ca. x=185 von 693px = 26.7%, der ausgestreckte
   Arm/die Faust beginnt erst bei ca. x=200-210 = 28.9-30.3% -- -28% liegt sicher dazwischen). */
/* Website-Feedback-Pass (2026-09-26, Nutzer-Fund: "Laeuferin ganz links an den Rand, wirkt
   abgeschnitten"): die vorherige -28%-Verschiebung (siehe Historie oben) versteckte bewusst einen
   Krop-Fehler im Quellbild selbst -- seit die Sektion eine andere Hoehe/Breite hat (siehe
   .pub-cinematic-break oben), schnitt derselbe Wert sichtbar in die Figur statt nur den Schuh.
   Auf translateX(0) zurueckgesetzt (Bild sitzt buendig links) -- wirkt jetzt sauber, kein
   Nachjustieren mit Rateswerten. */
.pub-cinematic-athlete {
  position: absolute; z-index: 0; pointer-events: none;
  /* Bug-Fund (2026-09-26, Nutzer-Fund "Runner bewegen sich aktuell nicht gegenlaeufig"): bottom:2%
     + height:90% liess nur ~8px Puffer UNTEN, aber ~33px OBEN (gemessen) -- der urspruengliche
     Parallax-Hub (bis zu +18px) schnitt dadurch am unteren Rand bereits leicht an. top/bottom:7%
     (statt bottom+height) gab zunaechst symmetrischen Puffer auf BEIDEN Seiten.
     Nutzerwunsch (2026-09-27): Hub verdoppelt (siehe public.js, jetzt bis zu 56px/40px) -- 7% Puffer
     reichte dafuer nicht mehr (real gemessen: bei 640-720px Viewport-Hoehe schnitt der neue Hub um
     bis zu ~33px in die Figur). 7% -> 18% (kombiniert mit min-height 46vh -> 56vh oben) wurde real
     an einem 640px-hohen Viewport verifiziert: durchgehend >=8px Sicherheitsabstand an beiden
     Extremen (-56px/+56px), kein Clipping mehr, siehe Screenshot-Verifikation dieser Aenderung. */
  left: 0; top: 18%; bottom: 18%; height: auto; width: auto;
  /* Scroll-Parallax (2026-09-26, Nutzerwunsch "leichte Scroll-Effekte"; Vorzeichen/Betrag am
     2026-09-27 geaendert, siehe public.js): --sp wird per rAF-throttled Scroll-Listener in public.js
     gesetzt (scrollChrome(), einziger gemeinsamer Scroll-Listener der Seite -- kein zusaetzlicher
     Listener), weiblich/maennlich mit gleichem Vorzeichen (beide bewegen sich beim Scrollen nach
     unten in dieselbe Richtung) und leicht unterschiedlichem Betrag. Faellt bei
     prefers-reduced-motion und ohne JS auf 0px zurueck (Fallback im var()). */
  transform: translateX(0) translateY(var(--sp, 0px));
  will-change: transform;
  filter: drop-shadow(0 0 46px rgba(122,92,255,0.22));
}
.pub-cinematic-athlete img { display: block; width: auto; height: 100%; object-fit: contain; }
[data-theme="light"] .pub-cinematic-athlete { opacity: 0.9; }
.pub-cinematic-statement { position: relative; z-index: 1; max-width: 900px; margin-left: auto; }
/* Website-Feedback-Pass (2026-09-26): zweiter Laeufer (maennlich, vorher im Hero) jetzt rechts in
   derselben Sektion -- spiegelt .pub-cinematic-athlete (weiblich, links) exakt. Text dazwischen
   zentriert statt rechtsbuendig. */
/* Korrektur (2026-09-26, Nutzer-Fund "Sektion springt beidseitig ein"): die fruehere Annahme
   hier war falsch -- absolut positionierte Kinder richten "left:0"/"right:0" nach der PADDING-BOX
   der Eltern (die bei fehlendem Border identisch zur Border-Box ist), NICHT nach der Content-Box
   innerhalb des Paddings. Der tatsaechliche Fehler war, dass die Eltern-Section (heute
   #runner-scene, damals noch #athletes) ihr eigenes 32px-Padding behielt und .pub-cinematic-break
   dadurch selbst 32px vom echten Rand
   entfernt startete -- jetzt an der Quelle behoben (siehe margin-Ausbruch bei .pub-cinematic-break
   oben). left:0/right:0 (aus der Basisregel) sind daher bereits korrekt; eine zusaetzliche
   -32px-Verschiebung hier wuerde jetzt ueber den echten Rand hinausschiessen. */
.pub-cinematic-athlete--female { left: 0; right: auto; }
.pub-cinematic-athlete--male { left: auto; right: 0; z-index: 0; }
.pub-cinematic-statement--centered { margin-left: auto; margin-right: auto; text-align: center; z-index: 2; }
@media (max-width: 900px) {
  /* Zwei volle Laeufer-Figuren nebeneinander UND zentrierter Text passen unter 900px nicht mehr
     kollisionsfrei -- der maennliche Laeufer bleibt hier bewusst ausgeblendet (nicht verkleinert,
     das machte auf Mobile bereits an anderer Stelle Probleme, siehe Historie), die Laeuferin und
     der zentrierte Text bleiben wie gehabt sichtbar. */
  .pub-cinematic-athlete--male { display: none; }
  .pub-cinematic-statement--centered { text-align: center; }
}
/* Bug gefunden bei der v10.1(10)-Screenshot-QA (768x1024, Light): die Statement-Zeile beginnt so
   nah an der Laeuferin, dass "Dein Koerper..." teilweise ueber ihre dunkle Kleidung reicht --
   dunkler Light-Mode-Text auf dunklem Stoff war schwer lesbar, dieselbe Bug-Kategorie wie zuvor
   bei "Mehr erfahren" im Hero. Derselbe bewaehrte dunkle Halo-Schatten (wirkt in Dark Mode
   unsichtbar, da er auf dem ohnehin dunklen Hintergrund verschwindet). */
.pub-cinematic-line {
  font-family: var(--font-display); font-weight: 700; text-wrap: balance;
  font-size: clamp(30px, 5.6vw, 68px); line-height: 1.08; margin: 0;
  color: var(--text);
  text-shadow: 0 1px 2px rgba(0,0,0,0.55), 0 0 16px rgba(0,0,0,0.35);
}
.pub-cinematic-line--accent {
  background: var(--talvaxo-gradient); -webkit-background-clip: text; background-clip: text;
  color: transparent; margin-top: 4px;
}
@media (max-width: 640px) {
  /* #runner-scene.pub-section's eigenes Links/Rechts-Padding sinkt hier von 32px auf 20px (siehe
     .pub-section-Override oben) -- der margin-Ausbruch von .pub-cinematic-break muss exakt
     mitziehen, sonst haengt die Sektion 12px zu weit ueber den echten Viewport-Rand hinaus. */
  .pub-cinematic-break { min-height: 40vh; padding: 0 22px; margin-left: -20px; margin-right: -20px; }
  /* transform hier bewusst fix (kein --sp) -- bei nur 40vh Sektionshoehe und 46%-Laeuferin bleibt
     zu wenig vertikaler Puffer fuer den Scroll-Parallax-Effekt, ohne Clipping zu riskieren. */
  .pub-cinematic-athlete { left: 0; right: auto; transform: translateX(0); height: 46%; bottom: 0; opacity: 0.6; }
  [data-theme="light"] .pub-cinematic-athlete { opacity: 0.85; }
  .pub-cinematic-statement { margin-left: 0; }
}

/* Timeline */
.pub-timeline { max-width: 560px; margin: 0 auto; display: flex; flex-direction: column; gap: 0; }
.pub-timeline-item { display: flex; align-items: flex-start; gap: 18px; padding: 18px 0; border-left: 2px solid var(--hairline); padding-left: 24px; position: relative; }
.pub-timeline-item:last-child { border-left-color: transparent; }
.pub-timeline-dot { position: absolute; left: -6px; top: 22px; width: 10px; height: 10px; border-radius: 50%; background: var(--talvaxo-cyan); box-shadow: 0 0 8px rgba(0,229,255,0.5); }
.pub-timeline-day { display: block; font-size: 10.5px; letter-spacing: 0.06em; color: var(--text-dim); font-family: var(--font-mono); margin-bottom: 4px; }
.pub-timeline-item b { font-size: 15px; }

/* Feature grid (supplementary) */
.pub-feature-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; max-width: 900px; margin: 0 auto; text-align: left; }
.pub-feature-card { background: var(--panel); border: 1px solid var(--border-soft); border-radius: 14px; padding: 24px; }
.pub-feature-icon { display: inline-flex; align-items: center; justify-content: center; width: 38px; height: 38px; border-radius: 10px; margin-bottom: 14px; }
.pub-feature-icon svg { width: 20px; height: 20px; }
.pub-feature-icon--cyan { background: rgba(0,229,255,0.12); color: var(--talvaxo-cyan); }
.pub-feature-icon--blue { background: rgba(0,122,255,0.12); color: var(--talvaxo-blue); }
.pub-feature-icon--violet { background: rgba(122,92,255,0.12); color: var(--talvaxo-violet); }
.pub-feature-card b { display: block; font-size: 15px; margin-bottom: 8px; }
.pub-feature-card p { font-size: 13.5px; color: var(--text-muted); line-height: 1.55; margin: 0; }
@media (max-width: 760px) { .pub-feature-grid { grid-template-columns: 1fr; } }

/* Demo CTA */
.pub-section--demo { text-align: center; }
.pub-demo-inner .pub-cta-btn { margin: 22px 0 14px; }
.pub-demo-note { font-size: 12.5px; color: var(--text-dim); }
/* Complete Visual Redesign Mandat §5/§11: closing CTA block of the merged "athletes" section
   (formerly its own standalone "demo" section with a redundant fourth app-window mockup). Centered
   to match .pub-section--preview's text-align, with the same top-separator treatment used
   elsewhere for a second beat within one section. */
.pub-demo-cta-block { max-width: 480px; margin: 64px auto 0; padding-top: 48px; border-top: 1px solid var(--border-soft); text-align: center; }
.pub-demo-cta-block .pub-demo-trust { justify-content: center; margin-top: 18px; }
.pub-demo-cta-block .pub-demo-note { margin-top: 10px; }
@media (max-width: 640px) { .pub-demo-cta-block { margin-top: 44px; padding-top: 36px; } }
/* Design-Print Teil 49 */
.pub-demo-trust { list-style: none; display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 4px 0 14px; padding: 0; }
.pub-demo-trust li { font-size: 12.5px; color: var(--text-muted); display: flex; align-items: center; gap: 7px; }
.pub-demo-trust li::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: var(--talvaxo-cyan); box-shadow: 0 0 5px rgba(0,229,255,0.6); flex-shrink: 0; }

/* Beta form */
.pub-beta-inner { max-width: 480px; }
.pub-beta-form { text-align: left; margin-top: 32px; display: flex; flex-direction: column; gap: 16px; }
.pub-field { display: flex; flex-direction: column; gap: 7px; }
.pub-field span { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted); }
.pub-field input, .pub-field textarea {
  background: var(--panel); border: 1px solid var(--border-soft); border-radius: 10px;
  padding: 13px 14px; color: var(--text); font-family: var(--font-body); font-size: 14.5px; resize: vertical;
}
.pub-field input:focus-visible, .pub-field textarea:focus-visible,
.pub-field input:focus, .pub-field textarea:focus { outline: none; border-color: var(--talvaxo-blue); box-shadow: 0 0 0 3px rgba(0,122,255,0.18); }
.pub-beta-status { font-size: 13.5px; min-height: 18px; margin: 0; }
.pub-beta-status[data-state="ok"] { color: var(--status-good); }
.pub-beta-status[data-state="error"] { color: var(--status-bad); }
.pub-beta-alt { margin-top: 18px; font-size: 13px; color: var(--text-muted); }
.pub-beta-alt a { color: var(--talvaxo-cyan); }

/* Footer */
.pub-footer { position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 20px; padding: 36px 32px; border-top: 1px solid var(--hairline); font-size: 12.5px; color: var(--text-dim); }
.pub-footer-brand { display: flex; align-items: center; gap: 10px; }
/* v10.1(11) Logo-Kit-Pass: ersetzt Icon+"TALVAXO"-Text durch die echte Wordmark-Grafik (siehe
   .pub-nav-brand img fuer dieselbe Begruendung). */
.pub-footer-logo { display: block; height: 18px; width: auto; }
.pub-footer-brand small { display: block; font-family: var(--font-mono); font-size: 8.5px; letter-spacing: 0.08em; color: var(--text-dim); }
/* Bug-Fund (2026-09-26, Website-Feedback-Pass, gemessen bei 375px): ohne flex-wrap laeuft die
   Legal-Link-Zeile (Impressum/Datenschutz/Nutzungsbedingungen/Cookie-Hinweis) auf schmalen
   Viewports ueber den rechten Bildschirmrand hinaus, statt umzubrechen. */
.pub-footer-links { display: flex; flex-wrap: wrap; gap: 10px 18px; }
.pub-footer-links a { color: var(--text-dim); text-decoration: none; }
.pub-footer-links a:hover { color: var(--text-muted); }
@media (max-width: 760px) { .pub-footer { flex-direction: column; align-items: flex-start; } }

.pub-toast {
  position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(120%);
  background: var(--panel-raised); border: 1px solid var(--border-soft); border-radius: 10px;
  padding: 12px 20px; font-size: 13.5px; z-index: 100; transition: transform 220ms ease;
  box-shadow: 0 10px 30px rgba(0,0,0,0.35);
}
.pub-toast[data-visible="true"] { transform: translateX(-50%) translateY(0); }

/* ================================================================
   INTERACTION SYSTEM (Mandat "PUBLIC WEBSITE PREMIUM INTERACTION & MOTION PASS")
   Alles hier ist zusätzlich zum bestehenden Motion-System oben -- nichts davon ersetzt es.
   ================================================================ */

/* ---- Button-Reset für Elemente, die zwecks Tastatur-/Touch-Zugänglichkeit von <div> auf
   <button> umgestellt wurden (Signal-Chips, Think-Nodes, Hot-Area-Kacheln, Plan-Toggle,
   Timeline-Items) -- ihre visuelle Gestaltung kommt weiterhin aus den bestehenden Klassenregeln,
   hier wird nur UA-Button-Chrome neutralisiert. */
.pub-signal-chip, .pub-think-node, .pub-metric-tile.pub-hot, #pub-plan-toggle, .pub-timeline-item {
  font: inherit; font-family: inherit; color: inherit; text-align: left; -webkit-appearance: none; appearance: none;
  margin: 0; border: none;
}
/* .pub-timeline-item keeps its left connector border (its own, non-UA rule) -- the shared reset
   above only needed to strip the UA default button border, which has no "side" to preserve on the
   other three, but does here. */
.pub-timeline-item { border-left: 2px solid var(--hairline); }
.pub-timeline-item:last-child { border-left-color: transparent; }
#pub-plan-toggle, .pub-timeline-item { width: 100%; }

/* ---- Scroll Progress (Mandat Teil 13) ---- */
.pub-scroll-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 50;
  background: var(--talvaxo-gradient); transform: scaleX(var(--progress, 0)); transform-origin: left;
  pointer-events: none;
}

/* ---- Nav Scroll State (Mandat Teil 51) ---- */
.pub-nav.is-scrolled { background: color-mix(in srgb, var(--bg) 90%, transparent); backdrop-filter: blur(18px); }

/* ---- Nav Active Indicator (Mandat Teil 11/12) ---- */
.pub-nav-links a { position: relative; }
.pub-nav-links a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px;
  background: var(--talvaxo-gradient); transform: scaleX(0); transform-origin: left;
  transition: transform 220ms ease;
}
.pub-nav-links a:hover::after, .pub-nav-links a:focus-visible::after, .pub-nav-links a.is-active::after { transform: scaleX(1); }
.pub-nav-links a.is-active { color: var(--text); }

/* ---- Footer Link Microinteraction (Mandat Teil 52) ---- */
.pub-footer-links a {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px; background-position: left bottom; background-repeat: no-repeat;
  transition: background-size 220ms ease, color 160ms ease; padding-bottom: 1px;
}
.pub-footer-links a:hover, .pub-footer-links a:focus-visible { background-size: 100% 1px; }

/* ---- Primary CTA Upgrade (Mandat Teil 8/9) ---- */
.pub-cta-btn {
  position: relative; overflow: hidden;
  background-size: 170% 170%; background-position: 0% 50%;
  transition: background-position 320ms ease, box-shadow 220ms ease, transform 160ms ease, filter 160ms ease;
}
.pub-cta-btn::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(115deg, transparent 30%, rgba(255,255,255,0.35) 48%, transparent 66%);
  transform: translateX(-140%) skewX(-18deg); transition: transform 550ms cubic-bezier(.2,.7,.2,1);
}
/* Bug gefunden bei der Athlete-Product-Preview-Verifikation: .pub-cta-arrow hatte nie eine
   explizite Groesse -- funktionierte an jeder bisherigen Stelle nur zufaellig, weil dort keiner
   der Buttons width:100% trug (Inhaltsbreite hielt die SVG dort implizit klein). Sobald .pub-
   preview-cta (width:100%, neu in diesem Pass) denselben Pfeil verwendet, waechst die groessenlose
   SVG als Flex-Kind auf einen absurden Default (~199px) -- deshalb hier fest auf Icon-Groesse
   verankert, schuetzt jetzt auch jede kuenftige width:100%-Verwendung. */
.pub-cta-arrow { width: 18px; height: 18px; flex-shrink: 0; transition: transform 220ms ease; }
@media (hover: hover) and (pointer: fine) {
  .pub-cta-btn:hover { background-position: 100% 50%; box-shadow: 0 8px 26px rgba(0,229,255,0.28); transform: translateY(-2px); filter: none; }
  .pub-cta-btn:hover::after { transform: translateX(140%) skewX(-18deg); }
  .pub-cta-btn:hover .pub-cta-arrow { transform: translateX(4px); }
}
.pub-cta-btn:active { transform: scale(0.97) translateY(0); }

/* ---- Secondary CTA (Mandat Teil 10) ---- */
.pub-link-btn--lg {
  position: relative; display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid transparent; border-radius: 8px; transition: border-color 200ms ease, background 200ms ease, color 160ms ease;
}
.pub-link-btn--lg::after { content: '→'; display: inline-block; transform: translateX(0); transition: transform 200ms ease; }
@media (hover: hover) and (pointer: fine) {
  .pub-link-btn--lg:hover, .pub-link-btn--lg:focus-visible { border-color: var(--border-soft); background: color-mix(in srgb, var(--panel) 70%, transparent); }
  .pub-link-btn--lg:hover::after, .pub-link-btn--lg:focus-visible::after { transform: translateX(4px); }
}

/* ---- Hero Pointer Response (Mandat Teil 4/5/6) ----
   --rx/--ry (Grad) und --px/--py (0..1, Richtung) werden per JS bei pointermove gesetzt, nur wenn
   (hover:hover) and (pointer:fine) -- siehe public.js. Ohne JS bleiben alle Variablen auf ihrem
   Default (0), die Fenster stehen still. */
#pub-hero-tilt { perspective: 1600px; }
#pub-hero-main-window {
  transform: rotateX(var(--ry, 0deg)) rotateY(var(--rx, 0deg));
  transition: transform 420ms cubic-bezier(.2,.8,.2,1);
  will-change: transform;
}
#pub-hero-main-window::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(220px circle at var(--sx, 50%) var(--sy, 50%), rgba(255,255,255,0.07), transparent 62%);
  opacity: 0; transition: opacity 260ms ease;
}
@media (hover: hover) and (pointer: fine) {
  #pub-hero-tilt:hover #pub-hero-main-window::before { opacity: 1; }
}
#pub-hero-float-card {
  transform: translate3d(calc(var(--px, 0) * 14px), calc(var(--py, 0) * 14px), 0);
  transition: transform 480ms cubic-bezier(.2,.8,.2,1);
  will-change: transform;
}

/* ---- Hero Initial Reveal Sequence (Mandat Teil 7) ----
   Default: alles sofort sichtbar (kein JS/CSS-Abhaengigkeit fuer Kern-Inhalt -> progressive
   enhancement). Nur wenn JS die .pub-hero-presequence-Klasse setzt (siehe public.js, NIE bei
   reduced motion), werden die Segmente kurz gestaffelt eingeblendet. */
.pub-hero-presequence .pub-hero-seq-1,
.pub-hero-presequence .pub-hero-seq-2,
.pub-hero-presequence .pub-hero-seq-3,
.pub-hero-presequence .pub-hero-seq-4,
.pub-hero-presequence .pub-hero-seq-5,
.pub-hero-presequence .pub-hero-seq-6 {
  opacity: 0; transform: translateY(10px); transition: opacity 420ms ease, transform 420ms ease;
}
.pub-hero-presequence .pub-hero-seq-1 { transition-delay: 0ms; }
.pub-hero-presequence .pub-hero-seq-2 { transition-delay: 70ms; }
.pub-hero-presequence .pub-hero-seq-3 { transition-delay: 140ms; }
.pub-hero-presequence .pub-hero-seq-4 { transition-delay: 210ms; }
.pub-hero-presequence .pub-hero-seq-5 { transition-delay: 280ms; }
.pub-hero-presequence .pub-hero-seq-6 { transition-delay: 380ms; }
.pub-hero-presequence.pub-hero-play .pub-hero-seq-1,
.pub-hero-presequence.pub-hero-play .pub-hero-seq-2,
.pub-hero-presequence.pub-hero-play .pub-hero-seq-3,
.pub-hero-presequence.pub-hero-play .pub-hero-seq-4,
.pub-hero-presequence.pub-hero-play .pub-hero-seq-5,
.pub-hero-presequence.pub-hero-play .pub-hero-seq-6 {
  opacity: 1; transform: none;
}

/* ---- Signal Cards Interaction + Signal->Decision Link (Mandat Teil 14/15) ---- */
.pub-signal-chip {
  transition: transform 220ms ease, box-shadow 220ms ease, border-left-color 220ms ease;
  cursor: pointer;
}
.pub-signal-chip:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
  .pub-signal-chip:hover { transform: translateY(-3px); box-shadow: 0 10px 24px rgba(0,0,0,0.22); }
}
/* Intelligence Color Flow (Mandat Teil 15): Signale->X ist Blue/Cyan (Daten rein), X->Entscheidung
   ist Violet (Entscheidung raus) -- zwei Pfeile, zwei Richtungen, zwei Farben. */
#pub-signals-flow[data-active-signal] .pub-signals-arrow--in { color: var(--talvaxo-cyan); transition: color 200ms ease; }
#pub-signals-flow[data-active-signal] .pub-signals-arrow--out { color: var(--talvaxo-violet); transition: color 200ms ease; }
#pub-signals-flow[data-active-signal] #pub-signals-x { filter: drop-shadow(0 0 24px rgba(0,229,255,0.6)); }
.pub-decision-why li {
  transition: color 160ms ease, background 160ms ease; border-radius: 6px; padding: 3px 7px; margin: -3px -7px;
}
.pub-decision-why li:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
#pub-signals-flow[data-active-signal="sleep"] .pub-decision-why li[data-why~="sleep"],
#pub-signals-flow[data-active-signal="recovery"] .pub-decision-why li[data-why~="recovery"],
#pub-signals-flow[data-active-signal="load"] .pub-decision-why li[data-why~="load"],
#pub-signals-flow[data-active-signal="hrv"] .pub-decision-why li[data-why~="hrv"] {
  color: var(--talvaxo-cyan); background: rgba(0,229,255,0.09);
}
.pub-decision-why--interactive li:hover, .pub-decision-why--interactive li:focus-visible {
  color: var(--talvaxo-cyan); background: rgba(0,229,255,0.09);
}

/* ---- Adaptive Decision Story (Mandat Teil 16/17) -- reiner CSS-Ablauf, getriggert durch die
   bestehende .pub-in-view-Klasse (IntersectionObserver, einmalig pro Session). ---- */
.pub-signals-flow > [data-reveal-child]:nth-child(1) { transition-delay: 0ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(2) { transition-delay: 70ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(3) { transition-delay: 140ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(4) { transition-delay: 210ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(5) { transition-delay: 300ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(6) { transition-delay: 360ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(7) { transition-delay: 420ms; }
.pub-signals-flow > [data-reveal-child]:nth-child(8) { transition-delay: 480ms; }
.pub-decision-why > li[data-reveal-child]:nth-child(1) { transition-delay: 560ms; }
.pub-decision-why > li[data-reveal-child]:nth-child(2) { transition-delay: 630ms; }
.pub-decision-why > li[data-reveal-child]:nth-child(3) { transition-delay: 700ms; }

@keyframes pub-x-pulse {
  0% { filter: drop-shadow(0 0 16px rgba(0,229,255,0.4)); }
  40% { filter: drop-shadow(0 0 30px rgba(0,229,255,0.8)); }
  100% { filter: drop-shadow(0 0 16px rgba(0,229,255,0.4)); }
}
#pub-signals-x.pub-in-view { animation: pub-x-pulse 700ms ease 420ms 1 both; }

.pub-value-transition .pub-strike { opacity: 1; }
.pub-value-transition > b { opacity: 1; }
.pub-decision-result.pub-in-view .pub-value-transition .pub-strike {
  animation: pub-value-fade-in 300ms ease 480ms both;
}
.pub-decision-result.pub-in-view .pub-value-transition > b {
  animation: pub-value-slide-in 340ms ease 620ms both;
}
@keyframes pub-value-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pub-value-slide-in { from { opacity: 0; transform: translateX(-6px); } to { opacity: 1; transform: translateX(0); } }

/* ---- Dynamic X as Intelligence Node (Mandat Teil 18/19/20; individuelle Pfade: "CINEMATIC"-Pass
   Teil 27-31) ---- */
.pub-think-diagram { position: relative; }
/* Intelligence Color Flow (Mandat Teil 15): Blue/Cyan travels IN toward X, Violet travels OUT as
   the decision. */
.pub-think-line {
  width: 2px; height: 26px;
  opacity: 0.35; transform: scaleY(0); transform-origin: top; transition: opacity 240ms ease;
}
.pub-think-line--out { background: linear-gradient(var(--talvaxo-cyan), var(--talvaxo-violet)); }
.pub-think-line.pub-in-view { transform: scaleY(1); transition: transform 420ms ease, opacity 240ms ease; }

/* Individuelle Daten-Pfade: eine SVG-Ueberlagerung mit einem eigenen, JS-berechneten Pfad pro
   Input-Node (siehe public.js buildThinkPaths()) statt einer einzigen gemeinsamen Linie. Fein,
   ruhig, technisch -- keine "cables everywhere" (Mandat Teil 13/28: niedrige Grunddeckkraft,
   Farbe/Deckkraft nur bei aktivem Zustand verstaerkt). */
.pub-think-paths { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; overflow: visible; }
.pub-think-path {
  fill: none; stroke: var(--talvaxo-cyan); stroke-width: 1.6; opacity: 0.4;
  stroke-dasharray: 400; stroke-dashoffset: 400;
  transition: opacity 260ms ease, stroke 260ms ease;
}
.pub-think-path.pub-path-drawn { stroke-dashoffset: 0; transition: stroke-dashoffset 700ms ease, opacity 260ms ease, stroke 260ms ease; }
#pub-think-diagram[data-think-active] .pub-think-path { opacity: 0.28; }
#pub-think-diagram[data-think-active="training"] .pub-think-path[data-source="training"],
#pub-think-diagram[data-think-active="health"] .pub-think-path[data-source="health"],
#pub-think-diagram[data-think-active="recovery"] .pub-think-path[data-source="recovery"],
#pub-think-diagram[data-think-active="baselines"] .pub-think-path[data-source="baselines"],
#pub-think-diagram[data-think-active="plan"] .pub-think-path[data-source="plan"],
#pub-think-diagram[data-think-active="all"] .pub-think-path {
  opacity: 0.95; stroke: var(--talvaxo-cyan); filter: drop-shadow(0 0 3px rgba(0,229,255,0.5));
}

.pub-think-node { cursor: pointer; transition: border-color 220ms ease, color 220ms ease, transform 220ms ease; position: relative; z-index: 1; }
.pub-think-node:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
.pub-think-core { cursor: pointer; transition: filter 220ms ease, transform 220ms ease; position: relative; z-index: 1; }
.pub-think-core:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) {
  .pub-think-node:hover { transform: translateY(-2px); border-color: var(--talvaxo-cyan); color: var(--talvaxo-cyan); }
  .pub-think-core:hover { transform: scale(1.04); }
}
#pub-think-diagram[data-think-active] .pub-think-line--out { opacity: 0.9; }
#pub-think-diagram[data-think-active] .pub-think-core { filter: drop-shadow(0 0 32px rgba(0,229,255,0.55)); }
#pub-think-diagram[data-think-active] .pub-think-node[data-source] { border-color: var(--border-soft); }
#pub-think-diagram[data-think-active="training"] .pub-think-node[data-source="training"],
#pub-think-diagram[data-think-active="health"] .pub-think-node[data-source="health"],
#pub-think-diagram[data-think-active="recovery"] .pub-think-node[data-source="recovery"],
#pub-think-diagram[data-think-active="baselines"] .pub-think-node[data-source="baselines"],
#pub-think-diagram[data-think-active="plan"] .pub-think-node[data-source="plan"],
#pub-think-diagram[data-think-active="all"] .pub-think-node[data-source] {
  border-color: var(--talvaxo-cyan); color: var(--talvaxo-cyan);
}
#pub-think-diagram[data-think-active] .pub-think-decision-card { box-shadow: 0 0 24px rgba(122,92,255,0.35); }

/* ---- Product Window Hover + Spotlight (Mandat Teil 21/22) ---- */
.pub-window--wide, .pub-window--decision-lg, .pub-window--demo, .pub-window--preview-lg {
  position: relative; transition: transform 220ms ease, box-shadow 220ms ease, border-color 220ms ease;
}
.pub-window--wide::before, .pub-window--decision-lg::before, .pub-window--demo::before, .pub-window--preview-lg::before {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(260px circle at var(--sx, 50%) var(--sy, 50%), rgba(255,255,255,0.05), transparent 62%);
  opacity: 0; transition: opacity 260ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .pub-window--wide:hover, .pub-window--decision-lg:hover, .pub-window--demo:hover,
  .pub-preview-product:hover .pub-window--preview-lg, .pub-preview-product:focus-visible .pub-window--preview-lg {
    transform: translateY(-3px); border-color: rgba(0,229,255,0.35);
    box-shadow: 0 34px 76px rgba(0,0,0,0.42), 0 0 0 1px rgba(255,255,255,0.03) inset;
  }
  .pub-window--wide:hover::before, .pub-window--decision-lg:hover::before, .pub-window--demo:hover::before,
  .pub-preview-product:hover .pub-window--preview-lg::before, .pub-preview-product:focus-visible .pub-window--preview-lg::before { opacity: 1; }
}

/* ---- Overview Hot Areas (Mandat Teil 23/24) ---- */
.pub-metric-tile.pub-hot { cursor: pointer; transition: background 220ms ease, box-shadow 220ms ease; position: relative; }
.pub-metric-tile.pub-hot:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: -2px; }
.pub-hot-note {
  display: block; font-size: 11.5px; line-height: 1.4; color: var(--text-muted); font-family: var(--font-body);
  max-height: 0; opacity: 0; overflow: hidden; margin-top: 0; transition: max-height 240ms ease, opacity 200ms ease, margin-top 240ms ease;
}
@media (hover: hover) and (pointer: fine) {
  .pub-metric-tile.pub-hot:hover { background: color-mix(in srgb, var(--panel) 60%, var(--talvaxo-cyan) 6%); box-shadow: inset 0 0 0 1px rgba(0,229,255,0.3); }
  .pub-metric-tile.pub-hot:hover .pub-hot-note, .pub-metric-tile.pub-hot:focus-visible .pub-hot-note { max-height: 70px; opacity: 1; margin-top: 8px; }
}
.pub-metric-tile.pub-hot.is-active { background: color-mix(in srgb, var(--panel) 60%, var(--talvaxo-cyan) 6%); box-shadow: inset 0 0 0 1px rgba(0,229,255,0.3); }
.pub-metric-tile.pub-hot.is-active .pub-hot-note { max-height: 70px; opacity: 1; margin-top: 8px; }

/* ---- Training Chapter WHY Reveal (Mandat Teil 25/26) ---- */
#pub-plan-toggle { cursor: pointer; position: relative; transition: background 200ms ease; }
#pub-plan-toggle:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: -2px; }
.pub-plan-why-hint {
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.08em; color: var(--talvaxo-cyan);
  margin-left: 10px; opacity: 0.75; transition: opacity 200ms ease;
}
#pub-plan-toggle:hover .pub-plan-why-hint, #pub-plan-toggle:focus-visible .pub-plan-why-hint { opacity: 1; }
.pub-plan-why {
  max-height: 0; overflow: hidden; opacity: 0; padding: 0 22px;
  transition: max-height 280ms ease, opacity 220ms ease, padding 280ms ease;
  border-bottom: 1px solid var(--hairline); background: color-mix(in srgb, var(--talvaxo-cyan) 4%, transparent);
}
.pub-plan-why .pub-decision-why { padding-left: 16px; margin: 10px 0; }
.pub-plan-why .pub-decision-why li { font-size: 12.5px; }
@media (hover: hover) and (pointer: fine) {
  #pub-plan-toggle:hover + .pub-plan-why { max-height: 160px; opacity: 1; padding: 4px 22px 16px; }
}
.pub-plan-why.is-open { max-height: 160px; opacity: 1; padding: 4px 22px 16px; }

/* ---- Personal Baseline Interaction (Mandat Teil 29/30/31) ---- */
.pub-baseline-toprow { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 0; }
.pub-baseline-toprow .pub-baseline-label { margin-bottom: 0; }
.pub-baseline-toggle { display: flex; gap: 6px; }
.pub-baseline-toggle-btn {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
  background: none; border: 1px solid var(--border-soft); border-radius: 999px; padding: 5px 12px;
  color: var(--text-muted); cursor: pointer; transition: color 160ms ease, border-color 160ms ease, background 160ms ease;
}
.pub-baseline-toggle-btn:hover { color: var(--text); }
.pub-baseline-toggle-btn:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
.pub-baseline-toggle-btn[aria-pressed="true"] { color: var(--talvaxo-blue); border-color: var(--talvaxo-blue); background: rgba(0,122,255,0.08); }
.pub-baseline-track { cursor: help; }
.pub-baseline-marker { cursor: help; transition: left 320ms cubic-bezier(.2,.8,.2,1), background 200ms ease, box-shadow 200ms ease; }
.pub-baseline-marker:focus-visible, .pub-baseline-track:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 3px; }
.pub-baseline-marker.is-example { background: var(--status-warn); box-shadow: 0 0 10px rgba(240,169,78,0.5); }
.pub-baseline-today small, .pub-baseline-today b { transition: color 200ms ease; }
.pub-baseline-example-note {
  font-size: 11px; color: var(--text-dim); margin: 10px 0 0; font-style: italic;
}

/* ---- Decision Timeline Interaction (Mandat Teil 32/33/34) ---- */
.pub-timeline-layout { display: grid; grid-template-columns: 1fr 260px; gap: 40px; max-width: 820px; margin: 0 auto; align-items: start; }
.pub-timeline { max-width: none; margin: 0; width: 100%; }
.pub-timeline-item {
  cursor: pointer; background: none; transition: transform 220ms ease, opacity 220ms ease;
}
.pub-timeline-item:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 3px; }
.pub-timeline-dot { transition: transform 220ms ease, box-shadow 220ms ease; }
.pub-timeline-item.is-active .pub-timeline-dot { transform: scale(1.35); box-shadow: 0 0 14px rgba(0,229,255,0.7); }
.pub-timeline-item.is-active { transform: translateX(4px); }
.pub-timeline-item.is-dimmed { opacity: 0.5; }
@media (hover: hover) and (pointer: fine) {
  .pub-timeline-item:hover .pub-timeline-dot { transform: scale(1.2); }
  .pub-timeline-item:hover { transform: translateX(2px); }
}
.pub-timeline-detail {
  background: var(--panel); border: 1px solid var(--border-soft); border-radius: 14px; padding: 18px 20px;
  position: sticky; top: 96px;
}
.pub-timeline-detail-row { display: flex; flex-direction: column; gap: 2px; margin-bottom: 12px; }
.pub-timeline-detail-row:last-child { margin-bottom: 0; }
.pub-timeline-detail-row span { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.08em; color: var(--text-dim); }
.pub-timeline-detail-row b { font-size: 14px; transition: opacity 180ms ease; }
.pub-timeline-detail-reason b { color: var(--talvaxo-cyan); }
@media (max-width: 760px) {
  .pub-timeline-layout { grid-template-columns: 1fr; gap: 20px; }
  .pub-timeline-detail { position: static; }
}

/* ---- Demo Composition (Mandat Teil 35/36/37/38) ---- */
/* Demo als zweiter Hoehepunkt (Mandat "CINEMATIC" Teil 60/64): Preview-Fenster deutlich vergroessert
   -- Sektion breiter, Spaltenverhaeltnis zugunsten des Produktfensters, groesseres Fenster selbst. */
.pub-demo-composition {
  max-width: 1280px; margin: 0 auto; display: grid; grid-template-columns: 0.8fr 1.2fr; gap: 56px; align-items: center; text-align: left;
}
.pub-demo-copy .pub-eyebrow, .pub-demo-copy h2, .pub-demo-lead { text-align: left; margin-left: 0; margin-right: 0; }
.pub-demo-preview { display: flex; justify-content: center; }
.pub-window--demo { width: 100%; max-width: 560px; transition: transform 220ms cubic-bezier(.2,.8,.2,1), box-shadow 220ms ease; }
.pub-window--demo .pub-window-body { padding: 30px; gap: 28px; }
.pub-window--demo .pub-window-ring { width: 116px; height: 116px; }
.pub-window--demo .pub-ring-label b { font-size: 28px; }
@media (hover: hover) and (pointer: fine) {
  .pub-demo-composition:hover .pub-window--demo { transform: translateY(-6px) scale(1.015); box-shadow: 0 40px 90px rgba(0,0,0,0.45); }
  .pub-demo-composition:hover #pub-demo-try { box-shadow: 0 10px 30px rgba(0,229,255,0.35); }
}
#pub-demo-try { transform: translate3d(var(--mx, 0px), var(--my, 0px), 0); }
@media (max-width: 900px) {
  .pub-demo-composition { grid-template-columns: 1fr; text-align: center; gap: 36px; }
  .pub-demo-copy .pub-eyebrow, .pub-demo-copy h2, .pub-demo-lead { text-align: center; }
}

/* ============ V10.1 COMPLETION — NEUE STORY-SEKTIONEN (S4-S9) ============ */

/* S4 Interactive Athlete Preview */
.pub-section--preview { text-align: center; }
.pub-preview-widget { max-width: 1100px; margin: 0 auto; }
.pub-sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.pub-preview-tabs { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-bottom: 4px; }
.pub-preview-tab {
  background: var(--panel); border: 1px solid var(--border-soft); border-radius: 12px;
  padding: 10px 18px; text-align: left; cursor: pointer; display: flex; flex-direction: column; gap: 2px;
  transition: border-color 200ms ease, transform 200ms ease;
}
.pub-preview-tab b { font-size: 13.5px; color: var(--text); }
.pub-preview-tab small { font-size: 11px; color: var(--text-dim); }
.pub-preview-tab.is-active { border-color: var(--talvaxo-cyan); box-shadow: 0 0 0 1px var(--talvaxo-cyan) inset; }
.pub-preview-tab.is-active b { color: var(--talvaxo-cyan); }
[data-theme="light"] .pub-preview-tab.is-active b { color: var(--talvaxo-blue); }
.pub-preview-tab:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
@media (prefers-reduced-motion: no-preference) { .pub-preview-tab:hover { transform: translateY(-2px); } }
.pub-preview-panel {
  margin-top: 22px; background: var(--panel); border: 1px solid var(--border-soft); border-radius: 18px;
  padding: 30px; text-align: left; box-shadow: 0 20px 50px rgba(0,0,0,0.25);
}
.pub-preview-content { display: none; }
.pub-preview-content.is-active { display: block; }

/* Athlete + Product Preview layout (Mandat "V10.1 IA REFINEMENT" Teil 20-36): Info-Spalte
   ~25-35%, Produkt-Vorschau ~65-75% -- das Produkt ist der visuelle Fokus, nicht die CTA (Teil
   32/66). Grid-Areas statt reiner DOM-Reihenfolge, damit Mobile (info -> preview -> cta, Teil 36)
   unabhaengig von der fuer Screenreader sinnvollen DOM-Reihenfolge (info -> preview -> cta liest
   sich ohnehin logisch) erreicht wird. */
.pub-preview-layout {
  display: grid; grid-template-columns: minmax(220px, 30%) 1fr;
  grid-template-areas: "info product" "cta product";
  gap: 22px 36px; align-items: start;
}
.pub-preview-info { grid-area: info; display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.pub-preview-cta-row { grid-area: cta; }
.pub-preview-meta { display: flex; flex-direction: column; gap: 10px; }
.pub-preview-meta div { display: flex; justify-content: space-between; font-size: 13px; gap: 12px; }
.pub-preview-meta span { color: var(--text-dim); font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.05em; }
.pub-preview-meta b { color: var(--text); }
.pub-preview-why { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pub-preview-why li { font-size: 12.5px; color: var(--text-muted); padding-left: 16px; position: relative; }
.pub-preview-why li::before { content: ''; position: absolute; left: 0; top: 6px; width: 5px; height: 5px; border-radius: 50%; background: var(--talvaxo-violet); }
.pub-preview-cta { width: 100%; justify-content: center; }

/* Grosse Produkt-Vorschau ersetzt das vormalige leere CTA-Feld (Mandat Teil 21/66 Hard Fail).
   .pub-preview-product ist ein natives <button> (volle Tastaturbedienbarkeit ohne eigene
   Keydown-Logik) mit einem einzigen sr-only-Label als Accessible Name -- der visuelle Inhalt
   darunter ist aria-hidden, damit Screenreader nicht Ring/Zeilen einzeln vorlesen. Die beiden
   Hotspots sind bewusst GESCHWISTER, nicht Kinder des Buttons (kein verschachteltes
   interaktives Element), rein visuell per absoluter Position ueber der Vorschau platziert. */
.pub-preview-product-wrap { grid-area: product; position: relative; }
.pub-preview-product { all: unset; display: block; width: 100%; cursor: pointer; border-radius: 18px; box-sizing: border-box; }
.pub-preview-product:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 3px; border-radius: 18px; }
/* Bug-Fund (User-Feedback): bei voller Kartenbreite liess .pub-window-rows{flex:1} +
   .pub-window-row{justify-content:space-between} Ring und Text weit auseinanderreissen --
   wirkte "nicht mittig". Fix: Ring+Zeilen bleiben als kompakte Einheit zusammen und zentrieren
   sich gemeinsam in der breiten Karte, statt sich ueber die volle Breite zu verteilen. */
.pub-window--preview-lg { width: 100%; }
.pub-window--preview-lg .pub-window-body { padding: 34px; gap: 40px; justify-content: center; }
.pub-window--preview-lg .pub-window-ring { width: 124px; height: 124px; }
.pub-window--preview-lg .pub-ring-label b { font-size: 30px; }
.pub-window--preview-lg .pub-window-rows { flex: none; min-width: 200px; }
.pub-window--preview-lg .pub-window-row { font-size: 15px; gap: 24px; }
.pub-window--preview-lg .pub-window-row span { font-size: 11px; }

/* Mandat "v10.1(10) FINAL POLISH" Teil 7D: kompakte Gesundheits-/Erholungssignal-Zeile, damit die
   Produkt-Vorschau nicht nur "Ring + Ergebnis" zeigt, sondern echten TALVAXO-Kontext -- reale
   Werte aus server/demo.py PROFILES[*].health_baseline gespiegelt (Single Source of Truth, kein
   erfundener zweiter Datensatz). Bewusst nur 3 Werte (Schlaf/HRV/Ruhepuls), keine vollstaendige
   Dashboard-Kopie (Teil 7: "purpose is context, not a full dashboard clone"). Selektoren mit
   erhoehter Spezifitaet fuer .pub-warn/.pub-bad (derselbe Spezifitaets-Bug wie bei .pub-window-row
   b, hier praeventiv vermieden statt erneut einzubauen). */
.pub-window-signals {
  display: flex; justify-content: space-around; gap: 10px;
  padding: 16px 34px; margin-top: 4px; border-top: 1px solid var(--hairline);
}
.pub-window-signals div { display: flex; flex-direction: column; align-items: center; gap: 3px; }
.pub-window-signals span { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: 0.06em; color: var(--text-dim); }
.pub-window-signals b { font-size: 13.5px; color: var(--text); font-weight: 600; }
.pub-window-signals b.pub-good { color: var(--status-good); }
.pub-window-signals b.pub-warn { color: var(--status-warn); }
.pub-window-signals b.pub-bad { color: var(--status-bad); }
@media (max-width: 640px) {
  .pub-window-signals { padding: 14px 24px; }
}

/* Bug-Fund (User-Feedback): Hotspots direkt auf dem Ring-Rand bzw. auf dem Status-Text wirkten
   wie Anzeigefehler (ein Punkt "auf" dem Ring las sich wie ein Bruch im Ring-Verlauf, ein Punkt
   auf dem Wort "adjusted" wie abgeschnittener Text). Fix: beide Hotspots sitzen jetzt als klar
   abgesetzte Karten-Ecken-Badges, nicht mehr direkt auf Ring/Text. */
.pub-preview-hotspot {
  position: absolute; width: 20px; height: 20px; border-radius: 50%; padding: 0; cursor: pointer;
  background: var(--talvaxo-cyan); border: 2px solid var(--panel);
  box-shadow: 0 0 0 4px rgba(0,229,255,0.18);
}
[data-theme="light"] .pub-preview-hotspot { background: var(--talvaxo-blue); box-shadow: 0 0 0 4px rgba(0,122,255,0.16); }
.pub-preview-hotspot--ready { top: 16px; right: 52px; }
.pub-preview-hotspot--why { top: 138px; right: 16px; }
.pub-preview-hotspot--why::after { bottom: calc(100% + 10px); }
.pub-preview-hotspot::after {
  content: attr(data-tooltip);
  position: absolute; bottom: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  background: var(--panel-raised, var(--panel)); border: 1px solid var(--border-soft);
  color: var(--text); font-size: 11.5px; line-height: 1.4; padding: 8px 10px; border-radius: 8px;
  width: max-content; max-width: 220px; box-shadow: 0 12px 30px rgba(0,0,0,0.35);
  opacity: 0; pointer-events: none; transition: opacity 160ms ease;
}
.pub-preview-hotspot--why::after { left: auto; right: 0; transform: none; }
.pub-preview-hotspot:hover::after, .pub-preview-hotspot:focus-visible::after { opacity: 1; }
.pub-preview-hotspot:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }

/* v10.1(11) Bug-Fund (automatisierte Horizontal-Overflow-Assertion, qa/v10.1.11/check_overflow.py):
   bei 768px Breite (768x1024, ein mandatierter QA-Viewport) lag die 2-Spalten-Grid-Mindestbreite
   (info minmax(220px,30%) + product-Spalte mit min-content ~432px aus Ring+Rows+Padding + 36px
   Gap = ~688px Grid-Inhalt, + 60px Panel-Padding = ~748px) knapp UEBER der damals verfuegbaren
   Breite (~642-704px je nach Verschachtelung) -- der Grid-Track konnte nicht schrumpfen und hat
   die ganze Seite um wenige Pixel horizontal ueberlaufen lassen (kein sichtbarer Scrollbalken dank
   .pub-body{overflow-x:hidden}, aber ein echter document.documentElement.scrollWidth-Ueberlauf).
   War bei der urspruenglichen 760px-Schwelle unentdeckt, weil 768 knapp DARUEBER liegt. Fix:
   Schwelle auf 820px angehoben, mit Sicherheitsabstand ueber dem berechneten Minimum. */
@media (max-width: 820px) {
  .pub-preview-layout { grid-template-columns: 1fr; grid-template-areas: "info" "product" "cta"; }
}
@media (max-width: 640px) {
  /* v10.1(11) Bug-Fund (check_overflow.py, 390x844): der ::after-Tooltip von --ready ist
     center-verankert (left:50%; translateX(-50%)) unter einem Hotspot, der selbst nahe am rechten
     Kartenrand sitzt (right:52px) -- bei max-width:220px reicht die (bei Ruhezustand unsichtbare,
     aber layoutwirksame) Tooltip-Box auf schmalen Karten ueber die Seite hinaus. Gleiche
     rechtsverankerte Strategie wie --why (die deshalb nie betroffen war). */
  .pub-preview-hotspot--ready::after { left: auto; right: 0; transform: none; }
}
@media (max-width: 640px) {
  .pub-preview-tabs { flex-direction: column; }
  .pub-preview-tab { flex-direction: row; justify-content: space-between; align-items: center; }
  .pub-window--preview-lg .pub-window-body { padding: 24px; gap: 22px; }
  .pub-window--preview-lg .pub-window-ring { width: 96px; height: 96px; }
  .pub-window--preview-lg .pub-ring-label b { font-size: 24px; }
  /* v10.1(11) Bug-Fund (check_overflow.py, 390x844): der desktop-min-width:200px auf
     .pub-window-rows (fuer den breiten 2-Spalten-Grid gedacht) passte nicht mehr in die
     geschrumpfte Karte (24px Padding + 96px Ring + Gap) und liess die Seite horizontal
     ueberlaufen -- hier fuer die schmale Karte reduziert. */
  .pub-window--preview-lg .pub-window-rows { min-width: 150px; }
  .pub-window--preview-lg .pub-window-row { gap: 14px; }
}

/* S5 A Day With TALVAXO */
.pub-day-journey { display: flex; align-items: stretch; gap: 14px; max-width: 1100px; margin: 0 auto; }
.pub-day-step {
  flex: 1; background: var(--panel); border: 1px solid var(--border-soft); border-radius: 16px;
  padding: 22px 20px; display: flex; flex-direction: column; gap: 8px; min-width: 0;
  transition: transform 200ms ease, border-color 200ms ease;
}
@media (prefers-reduced-motion: no-preference) {
  .pub-day-step:hover { transform: translateY(-3px); border-color: var(--talvaxo-cyan); }
}
.pub-day-time { font-family: var(--font-mono); font-size: 11px; color: var(--talvaxo-cyan); }
[data-theme="light"] .pub-day-time { color: var(--talvaxo-blue); }
.pub-day-label { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.08em; color: var(--talvaxo-violet); }
.pub-day-step p { font-size: 13px; line-height: 1.5; color: var(--text-muted); margin: 0; }
.pub-day-arrow { width: 20px; height: 20px; color: var(--text-dim); flex-shrink: 0; align-self: center; }
@media (max-width: 900px) {
  .pub-day-journey { flex-direction: column; }
  .pub-day-arrow { transform: rotate(90deg); align-self: center; }
}

/* S6 Product Overview — kompakte Module */
.pub-overview-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 18px; max-width: 1200px; margin: 0 auto 56px; }
.pub-overview-card {
  background: var(--panel); border: 1px solid var(--border-soft); border-radius: 14px;
  padding: 24px 20px; display: flex; flex-direction: column; gap: 8px;
  transition: transform 200ms ease, border-color 200ms ease;
}
@media (prefers-reduced-motion: no-preference) {
  .pub-overview-card:hover { transform: translateY(-3px); border-color: var(--talvaxo-cyan); }
}
/* Visual Redesign Execution Pass §13: 18px read as body text, not a feature-grid headline -- this
   grid supports the hero, so kept modest rather than matching the hero's own 60px, just enough to
   stop it reading as five identical small boxes. */
.pub-overview-stat { font-family: var(--font-display); font-size: 22px; font-weight: 700; margin-top: 4px; }
.pub-overview-card small { font-size: 11px; color: var(--text-dim); }
.pub-overview-card p { font-size: 12px; line-height: 1.5; color: var(--text-muted); margin: 8px 0 0; }
.pub-timeline-layout--deepdive { max-width: 900px; grid-template-columns: 1fr 260px; }
.pub-timeline-intro { grid-column: 1 / -1; margin-bottom: 8px; }
.pub-timeline-intro h3 { font-family: var(--font-display); font-size: 22px; margin: 4px 0 0; }
@media (max-width: 1080px) {
  .pub-overview-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 760px) {
  .pub-overview-grid { grid-template-columns: 1fr 1fr; }
  .pub-timeline-layout--deepdive { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .pub-overview-grid { grid-template-columns: 1fr; }
}

/* S7 Before / After */
.pub-beforeafter-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; max-width: 900px; margin: 0 auto; }
.pub-beforeafter-col { border-radius: 16px; padding: 26px 24px; }
.pub-beforeafter-col--before { background: color-mix(in srgb, var(--panel) 60%, transparent); border: 1px dashed var(--border-soft); opacity: 0.85; }
.pub-beforeafter-col--after { background: var(--panel); border: 1px solid var(--talvaxo-cyan); box-shadow: 0 0 0 1px rgba(0,229,255,0.15) inset; }
.pub-beforeafter-col b { display: block; font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.06em; margin-bottom: 14px; }
.pub-beforeafter-col--before b { color: var(--text-dim); }
.pub-beforeafter-col--after b { color: var(--talvaxo-cyan); }
[data-theme="light"] .pub-beforeafter-col--after b { color: var(--talvaxo-blue); }
.pub-beforeafter-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.pub-beforeafter-col li { font-size: 13.5px; padding-left: 20px; position: relative; }
.pub-beforeafter-col--before li { color: var(--text-muted); }
.pub-beforeafter-col--after li { color: var(--text); font-weight: 500; }
.pub-beforeafter-col--before li::before { content: '–'; position: absolute; left: 0; color: var(--text-dim); }
.pub-beforeafter-col--after li::before { content: ''; position: absolute; left: 0; top: 7px; width: 6px; height: 6px; border-radius: 50%; background: var(--talvaxo-cyan); box-shadow: 0 0 6px rgba(0,229,255,0.6); }
@media (max-width: 760px) { .pub-beforeafter-grid { grid-template-columns: 1fr; } }

/* S8 Road to Goal */
.pub-road-track { display: flex; max-width: 900px; margin: 0 auto; gap: 4px; }
.pub-road-phase {
  flex: 1; background: none; border: none; border-top: 3px solid var(--hairline); padding: 16px 10px 0;
  display: flex; flex-direction: column; gap: 4px; text-align: left; cursor: pointer; transition: border-color 200ms ease;
}
.pub-road-phase span { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.08em; color: var(--text-dim); }
.pub-road-phase b { font-size: 12.5px; color: var(--text-muted); font-weight: 600; }
.pub-road-phase.is-active { border-top-color: var(--talvaxo-gradient, var(--talvaxo-violet)); border-image: var(--talvaxo-gradient) 1; }
.pub-road-phase.is-active span { color: var(--talvaxo-cyan); }
[data-theme="light"] .pub-road-phase.is-active span { color: var(--talvaxo-blue); }
.pub-road-phase.is-active b { color: var(--text); }
.pub-road-phase:focus-visible { outline: 2px solid var(--talvaxo-cyan); outline-offset: 2px; }
.pub-road-detail { max-width: 640px; margin: 22px auto 0; min-height: 48px; }
.pub-road-detail-content { display: none; }
.pub-road-detail-content.is-active { display: block; }
.pub-road-detail p { font-size: 14px; line-height: 1.6; color: var(--text-muted); text-align: center; margin: 0; }
@media (max-width: 760px) {
  .pub-road-track { flex-wrap: wrap; }
  .pub-road-phase { flex: 1 1 40%; }
}

/* S9 Ecosystem */
.pub-ecosystem-flow { display: flex; flex-direction: column; align-items: center; gap: 10px; max-width: 700px; margin: 0 auto; }
.pub-ecosystem-row { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; width: 100%; }
.pub-ecosystem-node {
  background: var(--panel); border: 1px solid var(--border-soft); border-radius: 10px;
  padding: 12px 18px; font-size: 12.5px; color: var(--text-muted); text-align: center;
}
.pub-ecosystem-node--wide { width: 100%; padding: 14px 20px; font-size: 13px; color: var(--text); }
.pub-ecosystem-node--core {
  width: 100%; padding: 16px 20px; font-family: var(--font-display); font-size: 15px; font-weight: 700;
  color: #fff; background: var(--talvaxo-gradient); border: none;
}
.pub-ecosystem-node--decision { color: var(--talvaxo-violet); font-weight: 600; border-color: rgba(122,92,255,0.4); }
[data-theme="light"] .pub-ecosystem-node--decision { color: color-mix(in srgb, var(--talvaxo-violet) 65%, black); }
.pub-ecosystem-arrow { width: 16px; height: 16px; color: var(--text-dim); }

/* ---- Beta Form Microinteractions (Mandat Teil 40) ---- */
.pub-field span { transition: color 160ms ease; }
.pub-field:focus-within span { color: var(--talvaxo-blue); }

/* ---- Reduced Motion: alle NEUEN dynamischen Effekte deaktivieren (Mandat Teil 46/62) ----
   Ergaenzt (nicht ersetzt) den bestehenden Block oben. Bewegungsbasierte Effekte (Tilt, Parallax,
   Sweep, Pulse, Line-Reveal, Value-Transition, Magnetic CTA, Hero-Sequence) werden entfernt;
   Sichtbarkeits-/Farbzustaende (Hot-Area-Note, Plan-Why, Timeline-Detail, aktive Signal-Farbe)
   bleiben als reiner, unmittelbarer Zustand ohne Bewegung erhalten. */
@media (prefers-reduced-motion: reduce) {
  #pub-hero-main-window, #pub-hero-float-card { transform: none !important; transition: none !important; }
  #pub-hero-main-window::before, .pub-window--wide::before, .pub-window--decision-lg::before, .pub-window--demo::before, .pub-window--preview-lg::before { display: none !important; }
  .pub-hero-presequence .pub-hero-seq-1, .pub-hero-presequence .pub-hero-seq-2, .pub-hero-presequence .pub-hero-seq-3,
  .pub-hero-presequence .pub-hero-seq-4, .pub-hero-presequence .pub-hero-seq-5, .pub-hero-presequence .pub-hero-seq-6 {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .pub-cta-btn::after { display: none !important; }
  .pub-cta-btn:hover, .pub-cta-btn:active { transform: none !important; }
  .pub-cta-arrow, .pub-link-btn--lg::after { transition: none !important; }
  .pub-preview-tab:hover, .pub-overview-card:hover, .pub-day-step:hover { transform: none !important; }
  #pub-signals-x.pub-in-view { animation: none !important; }
  .pub-decision-result.pub-in-view .pub-value-transition .pub-strike,
  .pub-decision-result.pub-in-view .pub-value-transition > b { animation: none !important; opacity: 1 !important; transform: none !important; }
  .pub-signals-flow > [data-reveal-child], .pub-decision-why > li[data-reveal-child] { transition-delay: 0ms !important; }
  .pub-think-line { transition: none !important; transform: none !important; opacity: 0.6 !important; }
  .pub-think-node:hover, .pub-think-core:hover { transform: none !important; }
  .pub-window--wide:hover, .pub-window--decision-lg:hover, .pub-window--demo:hover, .pub-signal-chip:hover,
  .pub-preview-product:hover .pub-window--preview-lg, .pub-preview-product:focus-visible .pub-window--preview-lg { transform: none !important; }
  .pub-baseline-marker { transition: none !important; }
  .pub-timeline-item, .pub-timeline-item.is-active, .pub-timeline-item:hover, .pub-timeline-dot, .pub-timeline-item.is-active .pub-timeline-dot {
    transform: none !important; transition: opacity 150ms linear !important;
  }
  .pub-window--demo, .pub-demo-composition:hover .pub-window--demo { transform: none !important; transition: none !important; }
  #pub-demo-try { transform: none !important; }
  .pub-hot-note, .pub-plan-why { transition: opacity 150ms linear !important; }
  /* "CINEMATIC"-Pass Teil 68: "path travel" explizit deaktivieren -- Pfade sofort in ihrem
     Zielzustand statt ueber 700ms gezeichnet, Hover-Uebergaenge nur noch Opacity. */
  .pub-think-path { stroke-dashoffset: 0 !important; transition: opacity 150ms linear !important; }
}
.pub-motion-off #pub-hero-main-window, .pub-motion-off #pub-hero-float-card { transform: none !important; transition: none !important; }
.pub-motion-off .pub-hero-presequence .pub-hero-seq-1, .pub-motion-off .pub-hero-presequence .pub-hero-seq-2,
.pub-motion-off .pub-hero-presequence .pub-hero-seq-3, .pub-motion-off .pub-hero-presequence .pub-hero-seq-4,
.pub-motion-off .pub-hero-presequence .pub-hero-seq-5, .pub-motion-off .pub-hero-presequence .pub-hero-seq-6 {
  opacity: 1 !important; transform: none !important; transition: none !important;
}
.pub-motion-off .pub-cta-btn::after { display: none !important; }
.pub-motion-off #pub-signals-x.pub-in-view { animation: none !important; }
.pub-motion-off .pub-decision-result.pub-in-view .pub-value-transition .pub-strike,
.pub-motion-off .pub-decision-result.pub-in-view .pub-value-transition > b { animation: none !important; opacity: 1 !important; transform: none !important; }
.pub-motion-off .pub-think-line { transition: none !important; transform: none !important; }
.pub-motion-off #pub-demo-try { transform: none !important; }
.pub-motion-off .pub-hot-note, .pub-motion-off .pub-plan-why { transition: opacity 150ms linear !important; }
.pub-motion-off .pub-timeline-item, .pub-motion-off .pub-timeline-item.is-active,
.pub-motion-off .pub-timeline-dot, .pub-motion-off .pub-timeline-item.is-active .pub-timeline-dot {
  transform: none !important; transition: opacity 150ms linear !important;
}
.pub-motion-off .pub-window--wide:hover, .pub-motion-off .pub-window--decision-lg:hover,
.pub-motion-off .pub-window--demo:hover, .pub-motion-off .pub-signal-chip:hover,
.pub-motion-off .pub-think-node:hover, .pub-motion-off .pub-think-core:hover { transform: none !important; }
.pub-motion-off .pub-preview-tab:hover, .pub-motion-off .pub-overview-card:hover, .pub-motion-off .pub-day-step:hover { transform: none !important; }
.pub-motion-off .pub-preview-product:hover .pub-window--preview-lg, .pub-motion-off .pub-preview-product:focus-visible .pub-window--preview-lg { transform: none !important; }
.pub-motion-off .pub-think-path { stroke-dashoffset: 0 !important; transition: opacity 150ms linear !important; }
.pub-motion-off .pub-window--wide::before, .pub-motion-off .pub-window--decision-lg::before, .pub-motion-off .pub-window--demo::before, .pub-motion-off .pub-window--preview-lg::before { display: none !important; }
.pub-motion-off .pub-baseline-marker { transition: none !important; }
