/* Smashq website. Tokens follow the app design system (docs/design-system, Concept B). */

@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:500;font-display:swap;
  src:url(/assets/fonts/space-grotesk-500.woff2) format('woff2')}
@font-face{font-family:'Space Grotesk';font-style:normal;font-weight:700;font-display:swap;
  src:url(/assets/fonts/space-grotesk-700.woff2) format('woff2')}
@font-face{font-family:'Instrument Sans';font-style:normal;font-weight:400;font-display:swap;
  src:url(/assets/fonts/instrument-sans-400.woff2) format('woff2')}
@font-face{font-family:'Instrument Sans';font-style:normal;font-weight:600;font-display:swap;
  src:url(/assets/fonts/instrument-sans-600.woff2) format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url(/assets/fonts/jetbrains-mono-400.woff2) format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:600;font-display:swap;
  src:url(/assets/fonts/jetbrains-mono-600.woff2) format('woff2')}

/* ---------- tokens: light is the base, dark via media query, data-theme wins ---------- */
:root{
  --bg:oklch(97.2% 0.004 250);
  --raise:oklch(99.2% 0.002 250);
  --over:oklch(94.5% 0.005 250);
  --line:oklch(88% 0.006 250);
  --fg:oklch(24% 0.012 250);
  --mut:oklch(46% 0.01 250);
  --acc:oklch(55% 0.16 230);
  --acc10:oklch(55% 0.16 230 / 0.08);
  --glow:oklch(55% 0.16 230 / 0.1);
  --btnfg:oklch(99% 0.002 250);
  /* Semantische Farben folgen derselben Regel wie der Akzent: je eine Fassung
     pro Theme. Vorher waren sie die einzigen Tokens ohne Dunkelfassung, und
     die Vorabversions-Marke stand hell bei 3,16:1 auf ihrem eigenen Chip.
     Gerechnet wird gegen den Chipgrund (color-mix 12 Prozent auf --bg bzw.
     --raise), nicht gegen --bg allein: der Chip hebt den Grund an und ist der
     unguenstigste Fall. Hell erreichen die drei so 4,98 bis 5,21:1 auf dem
     Chip, dunkel 5,49 bis 7,83:1. */
  --ok:oklch(46% 0.12 155);
  --warn:oklch(48% 0.11 70);
  --err:oklch(55% 0.19 25);
  /* Eine zweite, kraeftigere Linienstaerke fuer Bedienelemente gab es hier
     einmal (--line-strong). Sie erfuellte WCAG 1.4.11, liess Umschalter,
     Sprachwahl, Geisterknopf, Abrechnungsschalter und Kopierknopf aber
     deutlich schwerer wirken als jede andere Kante der Seite. Auf
     ausdrueckliche Ansage des Betreibers tragen diese fuenf wieder --line.
     Wer sie erneut anhebt, hebt sie fuer alle fuenf zugleich an. */
}
@media (prefers-color-scheme: dark){
  :root{
    --bg:oklch(16% 0.01 250);
    --raise:oklch(19.5% 0.011 250);
    --over:oklch(23% 0.012 250);
    --line:oklch(29% 0.012 250);
    --fg:oklch(93% 0.005 250);
    --mut:oklch(63% 0.01 250);
    --acc:oklch(72% 0.14 230);
    --acc10:oklch(72% 0.14 230 / 0.1);
    --glow:oklch(72% 0.14 230 / 0.15);
    --btnfg:oklch(15% 0.02 250);
    --ok:oklch(72% 0.13 155);
    --warn:oklch(78% 0.12 70);
    --err:oklch(70% 0.16 25);
  }
}
:root[data-theme="dark"]{
  --bg:oklch(16% 0.01 250);
  --raise:oklch(19.5% 0.011 250);
  --over:oklch(23% 0.012 250);
  --line:oklch(29% 0.012 250);
  --fg:oklch(93% 0.005 250);
  --mut:oklch(63% 0.01 250);
  --acc:oklch(72% 0.14 230);
  --acc10:oklch(72% 0.14 230 / 0.1);
  --glow:oklch(72% 0.14 230 / 0.15);
  --btnfg:oklch(15% 0.02 250);
  --ok:oklch(72% 0.13 155);
  --warn:oklch(78% 0.12 70);
  --err:oklch(70% 0.16 25);
}
:root[data-theme="light"]{
  --bg:oklch(97.2% 0.004 250);
  --raise:oklch(99.2% 0.002 250);
  --over:oklch(94.5% 0.005 250);
  --line:oklch(88% 0.006 250);
  --fg:oklch(24% 0.012 250);
  --mut:oklch(46% 0.01 250);
  --acc:oklch(55% 0.16 230);
  --acc10:oklch(55% 0.16 230 / 0.08);
  --glow:oklch(55% 0.16 230 / 0.1);
  --btnfg:oklch(99% 0.002 250);
  /* Muessen hier stehen, obwohl :root sie schon hell setzt: unter
     prefers-color-scheme:dark mit data-theme="light" gewinnt sonst der
     spaeter notierte @media-Block und die drei Tokens blieben dunkel. */
  --ok:oklch(46% 0.12 155);
  --warn:oklch(48% 0.11 70);
  --err:oklch(55% 0.19 25);
}

/* Radien. Die Skala des Design-Systems kennt 2, 4, 6, 8 und 9999px; 6px ist
   der Standardwert, 8px gehoert den grossen Flaechen. Die Seite hatte davon
   abweichend 3, 5, 9, 10, 12, 999px und 50% im Einsatz, teils an baugleichen
   Flaechen nebeneinander: die groesste Karte der Seite war schwaecher gerundet
   als die halb so hohe daneben. Farbunabhaengig, deshalb ein eigener Block. */
:root{
  --r-md:6px;
  --r-lg:8px;
  --r-pill:9999px;
  /* Hoehe der klebenden Kopfzeile: .nav mit min-height:64px plus die
     Trennlinie darunter. Sie steht als Token, weil die Inszenierung gegen
     den Rest UNTER der Kopfzeile zentriert, nicht gegen den vollen
     Sichtbereich. */
  --nav-h:65px;
}

/* ---------- base ---------- */
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{
  margin:0;background:var(--bg);color:var(--fg);
  font-family:'Instrument Sans',system-ui,sans-serif;
  font-size:16px;line-height:1.55;
  -webkit-font-smoothing:antialiased;
  position:relative;
}
/* Ruhige Hintergrund-Akzente: zwei weiche Azure-Flecken und ein feines
   Raster. Nur Tokens, keine Bilder, kein CDN. Bleiben hinter dem Content. */
/* Der obere Rand laeuft weich aus. Die Kopfzeile ist seit D-108 deckend und
   schnitt den fixierten Zierfleck oben rechts sonst als waagerechte Kante ueber
   die volle Fensterbreite ab, und zwar nahe seiner vollen Staerke. Der Fleck
   liegt bewusst weit ueber der Fensterkante; ihn nach unten zu schieben haette
   die Komposition verstellt, die Maske nimmt ihm nur die Kante. */
.site-bg{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden;
  -webkit-mask-image:linear-gradient(to bottom, transparent 0 40px, #000 200px);
  mask-image:linear-gradient(to bottom, transparent 0 40px, #000 200px)}
.site-bg::before,.site-bg::after{content:"";position:absolute;border-radius:var(--r-pill);
  filter:blur(72px);opacity:.55}
.site-bg::before{
  width:min(62vw,720px);height:min(62vw,720px);top:-18%;right:-8%;
  background:radial-gradient(circle at 40% 40%,var(--glow),transparent 68%);
}
.site-bg::after{
  width:min(48vw,520px);height:min(48vw,520px);bottom:8%;left:-12%;
  background:radial-gradient(circle at 55% 45%,var(--acc10),transparent 70%);
  opacity:.4;
}
/* Transform-skalierte App-Mocks behalten intern volle Layout-Breite; ohne
   Clip entsteht auf schmalen Viewports horizontaler Scroll um wenige Pixel. */
html{overflow-x:clip}
body{overflow-x:clip}
/* Hebt den Inhalt ueber die fixierten Zierflecken. Die Regel ist bewusst ohne
   jede Klasse geschrieben: mit (0,0,2) ist sie schwaecher als jeder
   Komponentenselektor, also darf sich jedes Kind selbst anders positionieren
   (.site-bg, .nav-shell, .rail). Eine Ausnahmeliste aus :not(.klasse) waere
   der falsche Weg: sie zaehlt die Klassen mit, hebt die Spezifitaet mit jedem
   Eintrag und ueberstimmt dann genau die Komponenten, die sie befreien soll.
   Erst hat das die Kopfzeile am Kleben gehindert, dann die Kapitelleiste. */
body > *{position:relative;z-index:1}
a{color:inherit;text-decoration:none}
/* Nicht auf a und button beschraenkt: ein <summary> ist keines von beiden, ist
   aber fokussierbar, und die vierzehn Katalog-Gruppen fielen deshalb auf die
   Browser-Vorgabe zurueck (outline auto 1px in rgb(16,16,16), im dunklen Modus
   unsichtbar). */
:focus-visible{outline:2px solid var(--acc);outline-offset:2px}
.mono{font-family:'JetBrains Mono',ui-monospace,monospace}
.in{max-width:1040px;margin:0 auto;padding:0 28px}
/* Die Story-Abschnitte brechen bewusst breiter aus als der Textrumpf: das
   App-Fenster ist informationsdicht und wird sonst unlesbar klein skaliert.
   Die drei Abschnitte der Inszenierung (Story, Bibliothek, Review) tragen
   baugleiche Copy-Spalten und muessen deshalb auf EINER Kante stehen. Der
   zweite, 80px breitere Container war der Grund, warum sie es nicht taten:
   die Bibliotheks- und die Review-Spalte begannen ab 1440px bis zu 40px
   weiter links als die Kapitelspalte. Der Wert ist deshalb derselbe, und die
   beiden Namen bleiben nur, damit das Markup unberuehrt bleibt.
   Wer hier wieder zwei Werte einsetzt, verschiebt zugleich die Grenze der
   Kapitelleiste weiter unten: die rechnet gegen genau diese Kante. */
.in-wide,.in-bleed{max-width:1420px;margin:0 auto;padding:0 28px}
.eyebrow{
  font-family:'Space Grotesk',sans-serif;font-weight:500;
  text-transform:uppercase;letter-spacing:0.14em;font-size:12px;color:var(--mut);
}
.eyebrow .n{color:var(--acc)}
.chip-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;align-self:flex-start}
/* Die Marke steht in den Review-Kapiteln unmittelbar ueber .ui-ref, beide
   linksbuendig an derselben Textspalte. Innenabstand, Schriftgroesse und Form
   sind deshalb dieselben; vorher begann ihr Text 1px versetzt. */
.badge-prerelease{
  font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:.02em;
  color:var(--warn);background:color-mix(in oklch, var(--warn) 12%, transparent);
  /* Nicht mit --line mischen: das Neutral liegt auf Hue 250, der Warnton auf
     70. Bei exakt 180 Grad Abstand interpoliert OKLCH ueber den steigenden
     Bogen und landet bei Hue 187, also im Tuerkis. Mit transparent bleibt der
     Farbton erhalten und die Daempfung entsteht ueber die Deckkraft. */
  border:1px solid color-mix(in oklch, var(--warn) 35%, transparent);
  border-radius:var(--r-md);padding:3px 8px;white-space:nowrap;
}

/* ---------- nav ---------- */
/* Deckende Flaeche und genau eine Trennlinie. Vorher trug die 66px hohe
   Leiste drei waagerechte Linien: einen Akzentstreifen an der Fensterkante,
   der nichts markiert, und darunter ein zweifarbiges Paar aus Rahmen und
   Akzentschatten, das als doppelte Trennung liest und die einzige zweifarbige
   Trennung der Seite war. Der Hintergrundweichzeichner faellt mit weg: das
   Design-System schliesst Glassmorphism und backdrop-blur aus. */
.nav-shell{
  position:sticky;top:0;z-index:40;
  background:var(--bg);
  border-bottom:1px solid var(--line);
}
/* Die Hoehe der Leiste haengt nicht davon ab, welche Bedienelemente eine
   Seite traegt. Ohne Mindesthoehe bestimmten auf den Rechtsseiten die 32,9px
   hohen Links die Zeile, die Leiste war dort 61,9 statt 65,0px hoch und
   sprang beim Sprung von der Startseite ins Impressum. */
.nav{display:flex;align-items:center;gap:26px;padding:14px 0;min-height:64px}
/* Die Marke war das einzige anklickbare Element der Seite ohne jede
   Rueckmeldung und mit 31,3px zugleich die kleinste Trefferflaeche. Der
   Cursor traegt die Rueckmeldung: er steht im Ruhezustand auf --acc und geht
   im Hover auf --fg, das Wort umgekehrt. Beides sind vorhandene Tokens. */
.logo{position:relative;font-family:'JetBrains Mono',monospace;font-weight:600;font-size:15px;color:var(--fg);
  display:inline-flex;align-items:center;gap:0;padding:4px 0}
.logo::after{content:"";position:absolute;inset:-7px 0}
.logo .cur{color:var(--acc);transition:color .15s ease}
.logo .logo-word{transition:color .15s ease}
.logo:hover .cur{color:var(--fg)}
.logo:hover .logo-word{color:var(--acc)}
.logo-word{font-family:'Space Grotesk',sans-serif;font-weight:700;letter-spacing:0.04em;margin-left:8px;font-size:14px}
.nav .links{display:flex;gap:4px;font-size:13.5px;color:var(--mut);margin-left:8px}
/* Die Trefferflaechen wachsen ueber Pseudoelemente auf 44px, ohne dass ein
   sichtbares Mass sich aendert. Waagerecht wird nicht vergroessert: Nachbarn
   stehen in derselben Zeile, ueberlappende Trefferflaechen waeren schlimmer
   als kleine. */
.nav .links a{position:relative;padding:6px 10px;border-radius:var(--r-md);transition:color .15s ease,background-color .15s ease}
.nav .links a::after{content:"";position:absolute;inset:-6px 0}
.nav .links a:hover{color:var(--fg);background:var(--acc10)}
.nav .right{margin-left:auto;display:flex;align-items:center;gap:12px}
.nav .right .btn{height:36px;min-height:36px;padding:0 16px;display:inline-flex;align-items:center;
  position:relative}
.nav .right .btn::after{content:"";position:absolute;inset:-4px 0}
/* Die drei Bedienelemente der Kopfzeile teilen eine Hoehe von 36px und stehen
   damit auf denselben Kanten; vorher waren es 29,0 / 32,0 / 36,9px und drei
   verschiedene Ober- und Unterkanten in einer zentrierten Zeile. Die
   Trefferflaechen wachsen ueber Pseudoelemente und Innenabstaende auf 48px,
   ohne die Leiste hoeher zu machen. */
.theme-btn{position:relative;width:36px;height:36px;border:1px solid var(--line);border-radius:var(--r-lg);background:var(--raise);
  display:inline-flex;align-items:center;justify-content:center;color:var(--mut);cursor:pointer;padding:0;
  transition:color .15s ease,border-color .15s ease,background-color .15s ease}
.theme-btn::after{content:"";position:absolute;inset:-6px}
.theme-btn:hover{color:var(--fg);border-color:var(--mut);background:var(--over)}
/* Die Lucide-Sonne zeichnet ihre acht Strahlen zwei Rastereinheiten lang, bei
   einer Strichstaerke von zwei. Strahl und Strich sind damit gleich lang wie
   dick, und mit den runden Kappen bleibt bei 14px wie bei 16px ein Punkt
   uebrig statt eines Strahls. Das Verhaeltnis aendert sich mit der Groesse
   nicht, die absolute Laenge schon: 20px ist die oberste Stufe der Skala, der
   Strahl misst dort 1,67px plus Kappen, und der Knopf ist mit 36px weit genug,
   um das Symbol zu tragen. */
.theme-btn svg{width:20px;height:20px;stroke:currentColor;fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round}
:root[data-theme="dark"] .icon-moon{display:none}
:root:not([data-theme="dark"]) .icon-sun{display:none}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .icon-moon{display:none}
  :root:not([data-theme="light"]) .icon-sun{display:inline}
}
/* Kein overflow:hidden mehr: es klippte die vergroesserte Trefferflaeche des
   Umschaltlinks weg. Die einzige Flaeche, die eine Rundung braucht, ist die
   Marke der aktiven Sprache, und die traegt sie jetzt selbst. */
.lang{font-family:'JetBrains Mono',monospace;font-size:11px;border:1px solid var(--line);border-radius:var(--r-lg);display:flex;background:var(--raise);height:36px}
.lang b{display:flex;align-items:center;padding:0 13px;background:var(--over);color:var(--fg);font-weight:400}
.lang a{position:relative;display:flex;align-items:center;padding:0 13px;color:var(--mut)}
/* Die Rundung haengt an der Position, nicht am Element: auf der deutschen
   Seite steht die aktive Marke rechts (<a>EN</a><b>DE</b>), auf der
   englischen links. Elementgebunden trug die aussenliegende Haelfte dort
   eckige Ecken ueber der 8px-Rundung des Containers und verdeckte dessen
   Rahmen, waehrend mitten im Schalter eine Rundungsnase sass. */
.lang > :first-child{border-radius:var(--r-md) 0 0 var(--r-md)}
.lang > :last-child{border-radius:0 var(--r-md) var(--r-md) 0}
/* Beide Achsen. inset:-5px 0 setzte den waagerechten Anteil ausdruecklich
   auf 0 und liess die Flaeche mit 39,2px unter derselben Schwelle, die den
   Fix ausgeloest hat. */
.lang a::after{content:"";position:absolute;inset:-6px -3px}
.lang a:hover{color:var(--fg)}
/* Ein Knopf ist eine Flaeche: die Trefferflaeche ist hier der Knopf selbst,
   kein Pseudoelement. 44px gilt fuer die kleinsten Links dieser Seite, also
   erst recht fuer die fuenf Download- und Kauf-Knoepfe; die lagen mit 36,0
   bis 38,9px unter derselben Schwelle, die fuer die 11px-Fusszeilenlinks
   durchgesetzt wurde. Der einzige Knopf, der bei 36px bleibt, ist der in der
   Kopfzeile: dort bestimmt die Hoehe die Hoehe der Leiste (D-309), und die
   Trefferflaeche waechst deshalb ueber ein Pseudoelement. */
.btn{background:var(--acc);color:var(--btnfg);border-radius:var(--r-lg);padding:8px 15px;
  font-weight:600;font-size:13.5px;display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;box-shadow:0 1px 0 oklch(100% 0 0 / .12) inset}
.btn:hover{opacity:0.92}
.btn-ghost{border:1px solid var(--line);border-radius:var(--r-lg);padding:8px 15px;font-size:13.5px;color:var(--fg);
  display:inline-flex;align-items:center;justify-content:center;min-height:44px;background:var(--raise)}
.btn-ghost:hover{border-color:var(--mut)}

/* ---------- hero ---------- */
.hero{padding:88px 0 76px;display:flex;flex-direction:column;gap:20px;align-items:flex-start;
  position:relative}
/* Der Kasten spannt die Fensterbreite, nicht die Hero-Breite. Sonst liegt die
   linke Ellipse an der Kastenkante noch fast voll deckend an und wird dort
   hart abgeschnitten: man sieht nicht das Licht, sondern den Kasten. So faellt
   der Schnitt mit der Viewportkante zusammen und bleibt unsichtbar. */
/* Der Kasten beginnt an der Unterkante der Kopfzeile, nicht 20px darueber,
   und die Ellipsenmitten liegen so tief, dass an dieser Oberkante bereits
   ausgelaufen ist (Mitte 45 bzw. 33 Prozent gegen eine senkrechte Reichweite
   von 42 bzw. 29 Prozent). Solange die Kopfzeile durchsichtig war, fiel es
   nicht auf; seit sie deckend ist, schnitt sie den Schein ueber die volle
   Fensterbreite gerade ab, und zwar auf nahezu voller Staerke: 29 Stufen im
   Blaukanal innerhalb einer Pixelzeile. Das ist derselbe Kantentyp, den
   D-019 an den senkrechten Raendern beseitigt hat. */
.hero::before{
  content:"";position:absolute;top:0;left:50%;width:100vw;transform:translateX(-50%);
  height:min(52vh,420px);z-index:-1;
  background:
    radial-gradient(ellipse 70% 60% at 12% 45%, var(--glow), transparent 70%),
    radial-gradient(ellipse 50% 45% at 88% 33%, var(--acc10), transparent 65%);
  pointer-events:none;
}
/* Deutsche Komposita duerfen trennen: "Produktionsdisziplin" misst bei der
   Untergrenze des clamp 305px und lief bei 320px Viewport 18px aus dem Bild.
   overflow-wrap ist nur das Netz fuer den Fall ohne Trennwoerterbuch. */
.hero h1{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(32px,5vw,54px);line-height:1.05;letter-spacing:-0.018em;
  margin:6px 0 4px;max-width:16ch;text-wrap:balance;
  /* Als Flex-Element waere die Mindestbreite der Ueberschrift ihr laengstes
     Wort; als fit-content-Element sprengte sie damit die Spalte, bevor ein
     Umbruch ueberhaupt greifen konnte. */
  align-self:stretch;hyphens:auto;overflow-wrap:break-word}
.hero p{color:var(--mut);font-size:clamp(15.5px,1.5vw,18px);max-width:56ch;margin:0}
.hero p b{color:var(--fg);font-weight:600}
.cta{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.plats{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:10px}
.plat{display:inline-flex;align-items:baseline;gap:8px;padding:7px 12px;
  background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg)}
.plat-name{font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:13.5px;color:var(--fg)}
.plat-note{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--acc)}
.meta{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--mut)}
.hero .meta{margin-top:2px}
/* Die Version kommt zur Laufzeit aus /releases/latest.json. Bis dahin - und
   dauerhaft, falls der Abruf scheitert - ist der Span leer und traegt seinen
   Trenner selbst. Eine eingebaute Zahl waere schlimmer als gar keine: sie
   stammt aus dem Build, nicht aus der Realitaet, und behauptet bei totem
   Manifest eine Version, die die Tabelle darunter gerade dementiert.

   Trenner-Zeichen als Escapes: ein Leerzeichen NACH \00B7 wuerde die
   Escape-Sequenz beenden und dabei selbst verschluckt - der Punkt klebte dann
   am naechsten Wort. Geschuetzte Leerzeichen halten den Trenner ausserdem beim
   Umbruch bei der Versionsnummer statt ihn allein in die naechste Zeile zu
   schicken. */
#release-version:empty{display:none}
#release-version:not(:empty)::after{content:'\00A0\00B7\00A0'}
.scroll-cue{display:flex;align-items:center;gap:10px;margin-top:22px;
  font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--mut)}
.scroll-cue i{width:1px;height:30px;background:var(--line);position:relative;overflow:hidden;display:block}
.scroll-cue i::after{content:"";position:absolute;left:0;top:-40%;width:100%;height:40%;
  background:var(--acc);animation:cue 1.9s ease-in-out infinite}
@keyframes cue{to{top:110%}}

/* ---------- Kapitel-Leiste ---------- */
/* Ohne JS unsichtbar: sie behauptet einen Zustand, den nur das Skript kennt. */
.rail{display:none}
/* Geltungsbereich: die Leiste ist die Fortschrittsanzeige der Inszenierung und
   steht nur, solange eine der drei Story-Sektionen im Bild ist. Vorher war
   data-story="on" ein reines Einschaltsignal und die Leiste begleitete Katalog,
   Preise und Fusszeile mit einer Kapitelangabe, die dort nichts mehr bedeutet.
   Aus- und Einblendung ueber opacity, damit nichts springt; visibility nimmt
   sie im ausgeblendeten Zustand aus dem Zugaenglichkeitsbaum. */
[data-story="on"] .rail{position:fixed;left:26px;top:50%;transform:translateY(-50%);z-index:20;
  display:flex;flex-direction:column;gap:14px;pointer-events:none;
  opacity:0;visibility:hidden;transition:opacity .3s ease,visibility 0s linear .3s}
[data-story="on"][data-rail="on"] .rail{opacity:1;visibility:visible;
  transition:opacity .3s ease,visibility 0s linear 0s}
/* Die Abstufung laeuft ueber die Farbe, nicht ueber die Deckkraft. Mit
   opacity:0.45 lagen zehn der elf Marken bei 1,93:1, und selbst 0.9 haette in
   beiden Themes die geforderten 4,5:1 fuer 10px-Text verfehlt (gerechnet 4,34
   bzw. 4,81). Der Strich davor ist ein Zierelement und darf gedimmt bleiben. */
.rail span{display:flex;align-items:center;gap:9px;font-family:'JetBrains Mono',monospace;
  font-size:10px;color:var(--mut);transition:color .25s ease}
.rail span i{display:block;width:14px;height:1px;background:currentColor;opacity:.5;
  transition:width .25s ease,opacity .25s ease}
.rail span[data-state="past"]{color:color-mix(in oklch, var(--fg) 55%, var(--mut))}
.rail span[data-state="past"] i{opacity:1}
/* Der reine Akzent traegt im hellen Modus nur 3,75:1. Ein Viertel Vordergrund
   dazu haelt den Farbton und hebt beide Themes ueber die Schwelle. */
.rail span[data-state="current"]{color:color-mix(in oklch, var(--acc), var(--fg) 25%);font-weight:600}
.rail span[data-state="current"] i{width:26px;opacity:1}
/* Die Grenze ist Geometrie, nicht Geschmack: die Leiste steht bei left:26 und
   ist 59px breit, endet also bei x=85. Gerechnet wird gegen die LINKESTE der
   drei Copy-Spalten, nicht gegen die erstbeste. Solange .in-bleed 1500px mass,
   begannen .libbeatcol und .beatcol 40px weiter links als .chapters; die
   Rechnung gegen .chapters allein ergab bei 1600px 34px Luft, tatsaechlich
   lagen dort 7px Ueberlappung auf dem Text der Bibliotheks- und der
   Review-Spalte. Seit alle drei Abschnitte in einem 1420px-Container stehen,
   gilt eine Kante fuer alle: Spaltenbeginn = (Viewport - 1420) / 2 + 28,
   bei 1600px also x=118 und 33px Luft, bei 1440px x=38 und die Leiste laege
   auf dem Text. Die Breite der Leiste haengt NICHT vom aktiven Kapitel ab
   (Flex-Spalte, alle Marken auf der Breite der breitesten) und ist in beiden
   Sprachen gleich, weil die Marken nur Ziffern tragen. */
@media (max-width:1599px){[data-story="on"] .rail{display:none}}

/* ---------- Story-Layout ---------- */
.story{display:grid;grid-template-columns:minmax(0,clamp(240px,24vw,300px)) minmax(0,1fr);gap:40px;
  align-items:start;padding:0 0 40px}
/* Der Auslauf gehoert in die Kapitelspalte, nicht an den Abschnitt: die
   Grid-Zeile ist so hoch wie ihr hoechstes Element, und nur sie begrenzt den
   Weg des klebenden Fensters. Padding am Abschnitt liegt ausserhalb der Zeile
   und wuerde den Rahmen weiterhin mitten im letzten Kapitel loesen. */
.chapters{display:flex;flex-direction:column;padding-bottom:30vh}
.chapter{min-height:78vh;display:flex;flex-direction:column;justify-content:center;gap:14px}
.chapter h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(21px,2.1vw,27px);line-height:1.16;letter-spacing:-0.01em;margin:0;text-wrap:balance}
.chapter h2 em{font-style:normal;color:var(--acc)}
.chapter p{color:var(--mut);font-size:15px;margin:0;max-width:40ch}
.chapter p b{color:var(--fg);font-weight:600}
.ui-ref{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--mut);
  border:1px solid var(--line);border-radius:var(--r-md);padding:3px 8px;align-self:flex-start}
/* Erst wenn das Skript uebernommen hat, wird gedimmt. Ohne JS bleibt alles lesbar. */
.story[data-ready] .chapter{opacity:.22;transition:opacity .45s cubic-bezier(.22,.61,.36,1)}
.story[data-ready] .chapter[data-state="current"]{opacity:1}
/* Die drei klebenden Buehnen (Sessions, Bibliothek, Review-Center) stehen
   optisch mittig im freien Bereich UNTER der Kopfzeile, nicht mittig im
   vollen Sichtbereich. Vorher klebten sie bei top:72px: ueber dem Fenster
   blieben 7px Luft, darunter 200px, und man musste die Seite ein Stueck
   weiterschieben, damit das Fenster mittig aussah.
   Zentriert wird ueber den Klebepunkt, nicht ueber die Hoehe der Buehne:
   eine hohe Buehne mit zentriertem Inhalt haette das Fenster auch beim
   Hereinscrollen verschoben, wo es noch gar nicht klebt, und es dort unten
   angeschnitten. --stage-off ist die halbe verbleibende Luft und wird im
   Skript gemessen (siehe centerStickyStages in main.js). Ohne JavaScript ist
   der Wert 0 und die Buehne klebt wie bisher direkt unter der Kopfzeile. */
.stage,.libstick,.rcstick{position:sticky;top:calc(var(--nav-h) + var(--stage-off,0px))}
/* Leichter Rahmen hinter dem skalierten Fenster: trennt Mock vom Seitengrund,
   ohne mit App-Chrome zu konkurrieren. */
/* Nur der 1px-Ring. Die beiden weichen Schatten darunter reichten 75px unter
   das Fenster und legten im hellen Modus einen grauen Schleier unter die
   Bildunterschrift; Tiefe kommt in diesem System aus Flaechenhelligkeit und
   Rahmen, nicht aus einem 80px-Weichzeichner. */
.stage .aw,.libstick .aw,.rcstick .aw{
  border-radius:var(--r-lg);
  box-shadow:0 0 0 1px color-mix(in oklch, var(--line) 80%, transparent);
}
.cap{margin-top:14px;font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--mut);min-height:17px}
.cap span{display:none}
.cap span b{color:var(--acc);font-weight:400}
/* captions bound in ZUSTAENDE block */

/* ================= APP-FENSTER: 1:1-Nachbau der echten Oberflaeche =================
   Werte stammen aus smashq/src/index.css (.dark) und den React-Komponenten.
   Der Rahmen wird in echten Pixeln gebaut und per transform skaliert, damit die
   Proportionen exakt bleiben statt naeherungsweise nachgestellt zu werden. */
/* Hoehe kommt aus dem Seitenverhaeltnis, nicht erst aus dem Skript: sonst
   springt das Layout nach dem Laden und ein Ankersprung landet daneben. */
.aw{position:relative;width:100%;overflow:hidden}
.stage .aw{max-width:1200px;aspect-ratio:1200 / 700}
.libstick .aw{max-width:900px;aspect-ratio:900 / 700}
.rcstick .aw{max-width:1320px;aspect-ratio:1320 / 820}
/* Kein eigener Radius und kein aeusserer Schatten. Der Rahmen .aw liegt
   deckungsgleich darueber, klippt mit overflow:hidden und rundet; ein eigener
   Radius liefe gegenskaliert und waere damit nicht konzentrisch, und ein
   aeusserer Schatten faellt vollstaendig in den weggeschnittenen Bereich. */
.app{position:absolute;top:0;left:0;transform-origin:top left;
  transform:scale(var(--s,1));overflow:hidden;border:1px solid oklch(100% 0 0 / .08);
  /* Spalte statt Block: die Innenhoehen kamen bisher als feste Zahlen
     (Titelleiste 32 plus Rumpf 668 = 700). Der Rahmen rechnet aber
     border-box, seine beiden 1px-Kanten fressen also 2px vom Inhalt,
     und der Rumpf stand 2px zu hoch. Sichtbar wurde das an der
     Unterkante der letzten Gitterzelle: ihr 2px-Akzentrahmen lag zur
     Haelfte unter der Fensterkante und wirkte abgeschnitten. Der Rumpf
     nimmt jetzt, was uebrig bleibt, und die Rechnung geht in jedem der
     drei Fenster von selbst auf. */
  display:flex;flex-direction:column;
  box-shadow:inset 0 1px 0 oklch(100% 0 0 / .06);
  /* Mindestgroesse fuer die gerenderte Schrift im Fenster. Das Fenster wird
     als Ganzes skaliert, die gerenderte Schriftgroesse ist deshalb Nennwert
     mal --s: bei 1181px Fensterbreite waren das 5,47px, und daran aendert
     ein verschobener Breakpoint nichts. --fmin ist der Nennwert, der nach
     der Skalierung genau 7px ergibt; jede Schriftangabe im Fenster steht
     als max(Nennwert, var(--fmin)). Oberhalb von rund 1370px ist --fmin
     kleiner als jeder Nennwert und die Regel wirkungslos, das Fenster sieht
     dort unveraendert aus. Ohne JavaScript ist --s nicht gesetzt, --fmin
     ist dann 7px und ebenfalls wirkungslos.
     7px und nicht mehr: bei 7,5px reicht der Platz im Terminal-Nachbau nicht
     mehr, dort wird ab 1250px abwaerts die Zeile unter dem Freigabe-Kasten
     abgeschnitten (nachgemessen), und die Groessenstaffelung im Fenster
     faellt in sich zusammen, weil dann auch 12px-Text mit angehoben wird. */
  --fmin:calc(7px / var(--s,1));
  /* App-Tokens, dark ist der kanonische Look der Anwendung */
  --accent-l:72%;--accent-c:0.16;--accent-h:230;
  --a-acc:oklch(var(--accent-l) var(--accent-c) var(--accent-h));
  --a-a05:oklch(var(--accent-l) var(--accent-c) var(--accent-h) / .05);
  --a-a10:oklch(var(--accent-l) var(--accent-c) var(--accent-h) / .10);
  --a-a15:oklch(var(--accent-l) var(--accent-c) var(--accent-h) / .15);
  --a-a30:oklch(var(--accent-l) var(--accent-c) var(--accent-h) / .30);
  --a-a40:oklch(var(--accent-l) var(--accent-c) var(--accent-h) / .40);
  --n100:oklch(95% .003 280);--n200:oklch(87% .004 280);--n300:oklch(70% .006 280);
  --n400:oklch(62% .011 280);--n500:oklch(56% .012 280);--n600:oklch(46% .010 280);
  --n700:oklch(36% .008 280);--n800:oklch(27% .007 280);--n900:oklch(22% .006 280);
  --n950:oklch(18% .005 280);
  --sbase:var(--n950);--sraised:var(--n900);--soverlay:var(--n800);--sinset:oklch(15% .004 280);
  --a-ok:oklch(72% .16 155);--a-err:oklch(62% .22 25);--a-warn:oklch(75% .14 70);
  --hovov:oklch(100% 0 0 / .05);
  --hairline:inset 0 0 0 1px oklch(100% 0 0 / .06);
  --lift:0 1px 2px oklch(0% 0 0 / .4),0 8px 16px oklch(0% 0 0 / .3),inset 0 0 0 1px oklch(100% 0 0 / .08);
  --dadd:oklch(72% .16 155 / .12);--drem:oklch(62% .22 25 / .12);
  --daddw:oklch(72% .16 155 / .30);--dremw:oklch(62% .22 25 / .30);
  --dmark:oklch(75% .14 70 / .10);
  --asans:'Inter','Segoe UI',system-ui,sans-serif;
  --amono:'JetBrains Mono','Fira Code','Consolas',monospace;
  --eout:cubic-bezier(.16,1,.3,1);
  background:var(--sbase);color:var(--n200);font-family:var(--asans);
  font-size:14px;line-height:1.45;
}
.app-1{width:1200px;height:700px}
/* Das Review-Center braucht mehr Breite als das Sessions-Fenster: bei
   geoeffnetem Seitenpanel bleiben von 1200 nur 580 fuer die Diff-Spalte, und
   die Fusszeile passt dann nicht mehr in eine Zeile. */
.app-3{width:900px;height:700px}
.app-2{width:1320px;height:820px}
/* Eine gezeichnete Strichstaerke fuer alle Darstellungsgroessen. Ohne
   non-scaling-stroke steht die Staerke in viewBox-Einheiten und waechst mit
   der Symbolgroesse UND mit der Skalierung des Fensters; zwischen dem
   duennsten und dem dicksten Symbol desselben Sets lag der Faktor 3,6.
   1,25px ist die Staerke, die das Website-Set bei 14px zeichnet. */
.app svg{stroke:currentColor;fill:none;stroke-width:1.25;vector-effect:non-scaling-stroke;
  stroke-linecap:round;stroke-linejoin:round;display:block}
/* Fremdglyphe im Claude-Code-Nachbau: ihre Rechtecke tragen eine Fuellung,
   aber kein eigenes stroke-Attribut und erben deshalb die Kontur der Regel
   darueber. Auf den 3x3-Augen frisst sie zwei Drittel der Flaeche. */
.cf-bot svg{stroke:none}
@keyframes twpulse{0%,100%{opacity:1}50%{opacity:.5}}
@keyframes fadein{to{opacity:1}}
@keyframes blink{50%{opacity:0}}
@keyframes spin{to{transform:rotate(360deg)}}

/* Fenster-Titelleiste */
.tbar{display:flex;flex:none;align-items:center;gap:9px;height:32px;padding:0 12px;
  background:var(--n900);border-bottom:1px solid var(--n700)}
.tbar .tl{font-family:var(--amono);font-size:12px;color:var(--n300)}
.tbar .tl b{color:var(--a-acc);font-weight:400}
.tbar .tn{font-size:12px;font-weight:600;color:var(--n300);letter-spacing:.02em}
.tbar .tw{margin-left:auto;display:flex;gap:18px;color:var(--n500);font-size:12px}

/* ---------- Sidebar (SessionList, 240px) ---------- */
.abody{display:flex;flex:1;min-height:0}
.app-3 .lib-body{flex:1;min-height:0}
.sb{width:240px;flex:none;display:flex;flex-direction:column;height:100%;
  background:var(--sbase);border-right:1px solid var(--n700)}
.sbs{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}
.favs{padding:8px 0 0 8px;display:flex;flex-direction:column;gap:2px}
.fav{position:relative;display:flex;align-items:center;gap:8px;height:28px;padding:0 8px 0 12px;
  border-radius:6px;transition:background-color .3s ease}
.fav i{flex:none;width:8px;height:8px;border-radius:9999px;
  background:oklch(var(--accent-l) var(--accent-c) var(--accent-h))}
.fav .nm{font-weight:500;font-size:14px;color:var(--n200);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fav .fa{display:none;align-items:center;gap:2px;flex:none}
.ib{padding:4px;border-radius:6px;display:inline-flex;color:var(--n400)}
.ib svg{width:14px;height:14px}
.ib.play{color:var(--a-ok)}
.ib.play svg{fill:currentColor;stroke:none}
.favfoot{padding:8px 12px;display:flex;align-items:center;gap:6px}
.favfoot .ng{display:flex;align-items:center;gap:6px;font-size:max(11px,var(--fmin,0px));color:var(--n600)}
.favfoot .ng svg{width:12px;height:12px}
.favfoot .sp{flex:1}
.isq{display:flex;align-items:center;justify-content:center;width:24px;height:24px;
  border-radius:6px;color:var(--n400)}
.isq svg{width:14px;height:14px}
.sdiv{display:flex;align-items:center;gap:8px;margin:6px 12px}
.sdiv u{height:1px;flex:1;background:var(--n800);text-decoration:none}
.rows{position:relative;display:flex;flex-direction:column;gap:2px;padding:0 4px 0 8px}
.nosess{padding:12px;text-align:center;color:var(--n500);font-size:12px;transition:opacity .3s ease}
.srow{position:relative;display:flex;align-items:center;gap:8px;height:28px;padding:0 8px 0 12px;
  border-radius:6px;opacity:0;transform:translateX(-8px);
  transition:opacity .5s var(--eout),transform .5s var(--eout),background-color .3s ease}
.srow.sel{background:var(--a-a10)}
.srow i{flex:none;width:8px;height:8px;border-radius:9999px;
  background:oklch(var(--accent-l) var(--accent-c) var(--accent-h))}
.srow i.run{animation:twpulse 2s cubic-bezier(.4,0,.6,1) infinite}
.srow .nm{font-weight:500;font-size:14px;color:var(--n200);flex:1;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.srow .pj{flex:none;max-width:92px;font-size:max(11px,var(--fmin,0px));color:var(--n500);font-family:var(--amono);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:margin .3s ease}
/* Mini-Map: Geometrie exakt aus sessionGridLayout.ts, 6 Kacheln quer */
.mm{position:absolute;right:4px;top:50%;transform:translateY(-50%);display:grid;
  width:18px;height:12px;gap:1px;grid-template-columns:1fr 1fr 1fr;grid-template-rows:1fr 1fr;
  grid-template-areas:"a b c" "d e f";opacity:0;transition:opacity .35s ease}
.mm span{border-radius:2px;background:var(--n600)}
.mm span.on{background:oklch(var(--accent-l) var(--accent-c) var(--accent-h))}
/* Kontextmenue "Starten mit" (SessionAccentMenu)
   Muss UEBER der Terminalflaeche liegen: Sidebar und .sbs clippen sonst,
   und .tmain liegt im DOM spaeter und wuerde das Menue zudecken. */
.ctx{position:absolute;left:100px;top:2px;z-index:80;display:flex;flex-direction:column;gap:6px;
  border-radius:var(--r-lg);background:var(--soverlay);padding:10px;width:200px;
  opacity:0;transform:scale(.96);transform-origin:top left;pointer-events:none;
  border:1px solid var(--a-a30);
  box-shadow:0 0 0 1px oklch(100% 0 0 / .06),0 12px 40px oklch(0% 0 0 / .55),
    0 0 24px color-mix(in oklch, var(--a-acc) 28%, transparent)}
.ctx .lb{padding:0 4px;font-size:max(10px,var(--fmin,0px));text-transform:uppercase;letter-spacing:.1em;color:var(--n500)}
.ctx .gp{display:flex;flex-direction:column;gap:2px}
.ctx .mi{font-size:12.5px;text-align:left;padding:6px 8px;border-radius:var(--r-md);color:var(--n300);
  transition:color .2s ease,background-color .2s ease}
.ctx .mi.hv{color:var(--a-acc);background:var(--a-a15);font-weight:600}
.ctx .mi.ds{color:var(--n600)}
.ctx .more{padding:2px 8px 0;font-size:max(10px,var(--fmin,0px));font-family:var(--amono);color:var(--n500);letter-spacing:.02em}
.ctx .sep{border-top:1px solid var(--n700);margin-top:2px}
.ctx .sw{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:6px}
.ctx .sw u{width:20px;height:20px;border-radius:9999px;display:block;text-decoration:none}
/* Kapitel 01: Menue in den Vordergrund, Overflow freigeben, Terminal abdunkeln */
.story[data-active="0"] .sb{position:relative;z-index:6}
.story[data-active="0"] .sbs,
.story[data-active="0"] .favs{overflow:visible}
.story[data-active="0"] .tmain{z-index:1}
.story[data-active="0"] .tmain::after{content:"";position:absolute;inset:0;z-index:3;
  background:oklch(0% 0 0 / .42);opacity:0;pointer-events:none;
  animation:menudim .01s .7s forwards,menudimout .45s 5.4s forwards}
@keyframes menudim{to{opacity:1}}
@keyframes menudimout{to{opacity:0}}
/* OpenMdPathInput + SessionPanelDock */
.mdin{flex:none;border-top:1px solid var(--n800);padding:6px 8px;display:flex;align-items:center;gap:6px}
.mdin .ip{flex:1;min-width:0;border-radius:6px;background:var(--sraised);padding:4px 8px;
  font-size:12px;color:var(--n500)}
.mdin .go{display:flex;align-items:center;justify-content:center;width:28px;height:28px;
  border-radius:6px;color:var(--n400)}
.mdin .go svg{width:12px;height:12px}
.dock{flex:none;border-top:1px solid var(--n800);background:var(--sbase);padding:10px 12px;
  display:flex;flex-direction:column;gap:8px}
.dock .r1{display:flex;flex-wrap:wrap;align-items:center;gap:2px}
.dock .r2{display:flex;flex-wrap:wrap;align-items:center;column-gap:6px;row-gap:6px;
  border-top:1px solid var(--n800);padding-top:8px}
.db{position:relative;display:flex;align-items:center;justify-content:center;width:32px;height:32px;
  border-radius:6px;color:var(--n400)}
.db svg{width:16px;height:16px}
.bdg{position:absolute;top:2px;right:2px;min-width:14px;height:14px;padding:0 2px;
  border-radius:9999px;background:var(--a-acc);color:var(--sbase);font-size:max(9px,var(--fmin,0px));font-weight:700;
  font-family:var(--amono);display:inline-flex;align-items:center;justify-content:center}
.vp{margin-left:auto;display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:6px;
  background:var(--sraised);font-size:max(10px,var(--fmin,0px));font-weight:500;letter-spacing:-.025em;color:var(--n500)}
.vp u{width:6px;height:6px;border-radius:9999px;background:var(--a-acc);display:block;text-decoration:none}
.grip{width:4px;flex:none;background:var(--n700)}

/* ---------- Terminal-Bereich ---------- */
.tmain{flex:1;min-width:0;position:relative;display:flex;flex-direction:column}
.tpill{position:absolute;top:8px;right:8px;z-index:10;display:flex;align-items:center;gap:4px;
  padding:2px 4px;border-radius:6px;background:var(--sbase);box-shadow:var(--hairline);
  opacity:0;transition:opacity .35s ease}
.bchip{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;border-radius:4px;
  background:var(--n800);font-size:max(10px,var(--fmin,0px));color:var(--n400);max-width:140px}
.bchip svg{width:12px;height:12px;flex:none}
.bchip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tb{position:relative;padding:4px;border-radius:6px;display:inline-flex;color:var(--n500)}
.tb svg{width:16px;height:16px}
.tb.s14 svg{width:14px;height:14px}
.tb.s12 svg{width:12px;height:12px}
.tb.on{color:var(--a-acc);background:var(--a-a10)}
.tb .bdg{top:-4px;right:-2px;padding:0 4px;font-size:max(8.5px,var(--fmin,0px));font-weight:400}
.segc{display:flex;align-items:stretch;border-radius:6px;box-shadow:var(--hairline);
  overflow:hidden;background:var(--sraised)}
.segc .tb{border-radius:0}
/* EmptyState, wortgleich mit EmptyState.tsx */
.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:24px;padding:32px;text-align:center;z-index:2;transition:opacity .4s ease}
.empty .ic{position:relative}
.empty .ic u{position:absolute;inset:0;border-radius:9999px;background:var(--a-a10);
  filter:blur(24px);display:block;text-decoration:none}
/* 48px und Strichstaerke 1,5 im 24er-Raster stehen so in EmptyState.tsx
   (`w-12 h-12`, `strokeWidth={1.5}`), das Fenster ist ein 1:1-Nachbau. Weil
   non-scaling-stroke die Staerke in gezeichneten Pixeln misst, muss sie hier
   explizit stehen: die Sammelregel oben zeichnete auch dieses Symbol mit
   1,25px, also relativ zu seiner Groesse ein Drittel des Gewichts aller
   Nachbarsymbole und im Bild eine Haarlinie. */
.empty .ic svg{position:relative;width:48px;height:48px;stroke:var(--n500);stroke-width:3}
.empty h4{margin:0;font-size:18px;line-height:28px;font-weight:600;color:var(--n200)}
.empty p{font-size:14px;line-height:1.625;color:var(--n500);max-width:384px;margin:0}
.empty .pb{display:inline-flex;align-items:center;gap:8px;padding:6px 12px;border-radius:6px;
  background:var(--a-acc);color:var(--n950);font-weight:500;font-size:14px;box-shadow:var(--hairline)}
.empty .pb svg{width:16px;height:16px}
.empty .hn{font-size:12px;color:var(--n500)}

/* ================= CLI-SIMULATIONEN =================
   Wiederverwendbar: .cli traegt die Terminal-Flaeche, .cli-claude/.cli-codex/
   .cli-grok die jeweilige Chrome. Format nach Recherche am App-Repo und an den
   oeffentlichen Quellen der drei CLIs; die Inhalte sind Platzhalter.
   Farben: GitHub-Dark-16 auf dem in SessionTerminal.tsx gepinnten #0d1117. */
.cli{background:#0d1117;color:#e6edf3;
  font-family:ui-monospace,'SF Mono',Menlo,Monaco,'Cascadia Code','Fira Code',Consolas,monospace;
  font-size:13px;line-height:1.5;white-space:pre;overflow:hidden;
  background-image:linear-gradient(180deg, oklch(100% 0 0 / .02), transparent 28px)}
.cli .d{color:#6e7681}
.cli .w{color:#f0f6fc;font-weight:600}
.cli .g{color:#3fb950}
.cli .r{color:#ff7b72}
.cli .y{color:#d29922}
.cli .c{color:#39c5cf}
.cli .m{color:#bc8cff}
.cli .b{color:#58a6ff}
.cli .ln{opacity:0}
.cli .cur{display:inline-block;width:7px;height:14px;vertical-align:-2px;background:#00b5f5;
  animation:blink 1.1s steps(1) infinite}
/* Claude Code haengt sein eigenes 2-Spalten-Margin an jede Zeile an. Die Regel
   sitzt auf der Zeile, nicht auf dem Container: sonst kollidiert sie mit dem
   Padding der Terminalflaeche. */
.cli-claude .ln{padding-left:2ch}
.cli-claude .bl{color:#d29922}
.cli-codex .bl{color:#6e7681}
.cli-grok .bl{color:#6e7681}
.cli-grok .barbox{border-left:2px solid #39c5cf;padding-left:6px}

/* ---------- Einzelansicht und Grid ---------- */
.single{position:absolute;inset:0;padding:4px 10px;opacity:0;transition:opacity .4s ease}
/* Grok Build welcome TUI (real interactive start screen, not invented tool slop) */
.tui-grok{display:flex;flex-direction:column;padding:0 !important;background:#0c0c0c;color:#c9c9c9;
  font-family:ui-monospace,'Cascadia Code','Consolas',monospace;font-size:12.5px;line-height:1.45;
  position:absolute;inset:0}
.tui-grok .tui-fill{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;
  padding:18px 22px 12px;gap:18px}
.tui-grok .tui-tilde{position:absolute;top:10px;left:14px;color:#555;font-size:13px}
.tui-grok .tui-panel{border:1px solid #3a3a3a;border-radius:6px;padding:16px 18px 14px;
  background:#111;max-width:520px;width:100%;margin:0 auto;box-shadow:0 0 0 1px #1a1a1a}
.tui-grok .tui-brand{font-size:13.5px;color:#e8e8e8;margin-bottom:12px}
.tui-grok .tui-brand b{font-weight:600}
.tui-grok .tui-brand .ver{color:#8a8a8a;font-weight:400;margin-left:6px}
.tui-grok .tui-hl{color:#e3b341;font-weight:600;margin-bottom:2px}
.tui-grok .tui-sub{color:#9a9a9a;margin-bottom:14px}
.tui-grok .tui-menu{display:flex;flex-direction:column;gap:5px}
.tui-grok .tui-row{display:flex;justify-content:space-between;gap:24px;color:#d0d0d0}
.tui-grok .tui-row .kb{color:#6e6e6e;font-size:11.5px}
.tui-grok .tui-tip{color:#7a7a7a;font-size:11.5px;max-width:560px;margin:0 auto;text-align:left;
  padding:0 8px;line-height:1.5}
.tui-grok .tui-composer{flex:none;padding:0 14px 12px;display:flex;flex-direction:column;gap:6px}
.tui-grok .tui-input{border:1px solid #3a3a3a;border-radius:6px;padding:10px 12px;display:flex;
  align-items:center;gap:6px;background:#0c0c0c;min-height:40px}
.tui-grok .tui-input .pr{color:#c9c9c9}
.tui-grok .tui-input .cur{display:inline-block;width:7px;height:14px;background:#c9c9c9;
  animation:blink 1.1s steps(1) infinite;vertical-align:-2px}
.tui-grok .tui-status{display:flex;justify-content:flex-end;align-items:center;gap:14px;
  font-size:max(11px,var(--fmin,0px));color:#8a8a8a;padding:0 4px}
.tui-grok .tui-status .stable{color:#6e6e6e}
/* Claude Code full single welcome (from real Claude Code v2.1.227 screenshot) */
.tui-claude-full{display:flex;flex-direction:column;padding:0 !important;position:absolute;inset:0;
  background:#0c0c0c;color:#e6edf3;font-family:ui-monospace,'Cascadia Code','Consolas',monospace;font-size:12px}
.tui-claude-full .cf-wrap{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;
  padding:16px 22px 8px;gap:10px}
.tui-claude-full .cf-panel{display:grid;grid-template-columns:1.05fr 1.15fr;gap:0;border:1px solid #c45c26;
  border-radius:6px;overflow:hidden;background:#0c0c0c;max-width:760px;width:100%;margin:0 auto}
.tui-claude-full .cf-left{padding:14px 16px 16px;border-right:1px solid #3a2a20;text-align:center}
.tui-claude-full .cf-right{padding:12px 14px 14px;text-align:left}
.tui-claude-full .cf-title{color:#e07a3a;font-weight:600;font-size:12px;margin-bottom:14px;
  display:flex;align-items:center;justify-content:center;gap:8px}
.tui-claude-full .cf-title .ver{color:#c47a4a;font-weight:500}
.tui-claude-full .cf-rule{flex:1;height:1px;background:#c45c26;opacity:.85;max-width:48px}
.tui-claude-full .cf-welcome{color:#f0f0f0;font-size:15px;font-weight:600;margin-bottom:12px}
.tui-claude-full .cf-bot{display:flex;justify-content:center;margin:6px 0 14px}
.tui-claude-full .cf-bot svg{display:block}
.tui-claude-full .cf-meta{color:#9a9a9a;font-size:max(11px,var(--fmin,0px));line-height:1.55}
.tui-claude-full .cf-meta .path{color:#6e6e6e}
.tui-claude-full .cf-meta .sep{opacity:.55;margin:0 2px}
.tui-claude-full .cf-h{color:#e07a3a;font-weight:600;font-size:11.5px;margin:0 0 5px}
.tui-claude-full .cf-p{color:#9a9a9a;font-size:max(10.5px,var(--fmin,0px));line-height:1.5;margin:0 0 12px}
.tui-claude-full .cf-more{color:#c47a4a}
.tui-claude-full .cf-using{color:#8a8a8a;font-size:max(11px,var(--fmin,0px));max-width:760px;margin:0 auto;width:100%}
.tui-claude-full .cf-using .sep{opacity:.5;margin:0 3px}
.tui-claude-full .cf-composer{flex:none;padding:0 18px 10px;display:flex;flex-direction:column;gap:0}
.tui-claude-full .cf-usage{color:#e3b341;font-size:max(11px,var(--fmin,0px));text-align:right;padding:0 2px 10px}
.tui-claude-full .cf-usage .sep{opacity:.55;margin:0 3px}
.tui-claude-full .cf-input{border-top:1px solid #2a2a2a;padding:10px 2px 6px;display:flex;align-items:center;gap:6px}
.tui-claude-full .cf-input .pr{color:#c9c9c9}
.tui-claude-full .cf-input .cur{width:7px;height:14px;background:#c9c9c9;display:inline-block;
  animation:blink 1.1s steps(1) infinite}
.tui-claude-full .cf-bar{font-size:max(10.5px,var(--fmin,0px));color:#8a8a8a;padding:2px 2px 0}
.tui-claude-full .cf-bar .sep{opacity:.5;margin:0 3px}
.tui-claude-full .cf-bar-mode{padding-top:2px}
.tui-claude-full .cf-bar-mode .mode{color:#e3b341;font-weight:600}
.tui-claude-full .cf-bar-mode .dim{color:#6e6e6e}
/* Codex full single welcome (from real Codex CLI v0.147.0 screenshot) */
.tui-codex-full{display:flex;flex-direction:column;padding:0 !important;position:absolute;inset:0;
  background:#0c0c0c;color:#e6edf3;font-family:ui-monospace,'Cascadia Code','Consolas',monospace;font-size:12px}
.tui-codex-full .cx-fill{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:flex-start;
  padding:14px 22px 12px;gap:14px}
.tui-codex-full .cx-ps-block{font-size:11.5px;line-height:1.45}
.tui-codex-full .cx-ps-line{color:#c9c9c9}
.tui-codex-full .cx-ps-line.dim{color:#8a8a8a}
.tui-codex-full .cx-ps-line .d{color:#c9c9c9}
.tui-codex-full .cx-ps-line .cmd{color:#e3b341;font-weight:600}
.tui-codex-full .cx-box.big{border:1px solid #4a4a4a;border-radius:4px;padding:10px 12px;background:#0c0c0c;
  max-width:380px}
.tui-codex-full .cx-title{color:#e8e8e8;margin-bottom:8px;font-size:12.5px}
.tui-codex-full .cx-gt{color:#8a8a8a}
.tui-codex-full .cx-ver{color:#8a8a8a}
.tui-codex-full .cx-meta{font-size:11.5px;color:#9a9a9a;margin-top:3px;display:flex;align-items:baseline;gap:6px}
.tui-codex-full .cx-meta .k{color:#6e6e6e;min-width:5.5em}
.tui-codex-full .cx-meta .v{color:#d0d0d0}
.tui-codex-full .cx-meta .link{color:#58a6ff}
.tui-codex-full .cx-meta .dim{color:#6e6e6e}
.tui-codex-full .cx-tip{color:#9a9a9a;font-size:11.5px;max-width:560px;line-height:1.45}
.tui-codex-full .cx-tip .tip-k{color:#8a8a8a}
.tui-codex-full .cx-tip .tip-new{font-style:italic;color:#b0b0b0}
.tui-codex-full .cx-composer{flex:none;padding:0 18px 12px}
.tui-codex-full .cx-input{background:#2a2a2a;border-radius:3px;padding:10px 12px;display:flex;
  align-items:center;gap:6px;margin-bottom:8px;min-height:36px}
.tui-codex-full .cx-input .pr{color:#c9c9c9}
.tui-codex-full .cx-input .ph{color:#6e6e6e}
.tui-codex-full .cx-input .cur{width:7px;height:14px;background:#c9c9c9;display:inline-block;
  animation:blink 1.1s steps(1) infinite}
.tui-codex-full .cx-foot{color:#c9a227;font-size:11.5px}
.tui-codex-full .cx-foot .sep{opacity:.55;margin:0 3px}
/* Full fleet = 2×3 landscape (real app), not 3×2 tall stacks */
/* 2px Innenabstand rundum, gleich dem Abstand zwischen den Zellen. Ohne ihn
   lagen die 2px-Akzentrahmen der Randzellen direkt auf der Fensterkante; an
   der Unterkante verschwand der Rahmen der letzten Zelle sogar zur Haelfte
   darunter. Der Abstand ist dieselbe Zahl wie gap, das Raster bleibt also
   gleichmaessig. */
.grid6{position:absolute;inset:0;width:100%;height:100%;display:grid;gap:2px;padding:2px;
  grid-template:"a b c" 1fr "d e f" 1fr / 1fr 1fr 1fr;opacity:0;
  box-sizing:border-box}
.cell{position:relative;border-radius:4px;overflow:hidden;box-sizing:border-box;
  border:2px solid oklch(var(--accent-l) var(--accent-c) var(--accent-h));
  display:flex;flex-direction:column;min-height:0;min-width:0;
  opacity:0;transform:scale(.985);
  transition:opacity .5s var(--eout),transform .5s var(--eout),box-shadow .3s ease}
.cell .ct{flex:1;min-height:0;padding:28px 0 0;font-size:max(11px,var(--fmin,0px));line-height:1.45}
/* Mid-session CLI surfaces (from real Smashq 6-up screenshots) */
.cell .tui-cell{display:flex;flex-direction:column;padding:26px 0 0 !important;font-size:max(10px,var(--fmin,0px));
  line-height:1.38;background:#0a0a0a;color:#d4d4d4;
  font-family:ui-monospace,'Cascadia Code','Consolas',monospace}
.cell .tui-cell .tc-body{flex:1;min-height:0;overflow:hidden;padding:2px 8px 2px;white-space:pre-wrap;
  word-break:break-word}
.cell .tui-cell .tc-meta{flex:none;padding:2px 8px 0;font-size:max(9px,var(--fmin,0px));color:#6e6e6e;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cell .tui-cell .tc-foot{flex:none;display:flex;align-items:center;gap:6px;padding:2px 8px 3px;
  font-size:max(9px,var(--fmin,0px));color:#6e6e6e}
.cell .tui-cell .tc-keys{flex:none;display:flex;gap:10px;padding:0 8px 4px;font-size:max(8.5px,var(--fmin,0px));color:#555}
/* Claude Code mid-session (no welcome panel; status + mode footer) */
.tui-claude{color:#e6edf3}
.tui-claude .y{color:#d29922}.tui-claude .w{color:#f0f6fc;font-weight:600}
.tui-claude .c{color:#39c5cf}.tui-claude .d{color:#6e7681}.tui-claude .m{color:#bc8cff}
.tui-claude .r{color:#ff7b72}
.tui-claude .ins{color:#a78bfa;font-weight:600}
.tui-claude .ins-l{color:#a78bfa;display:block;border-bottom:1px solid #5b4a8a;padding-bottom:2px;margin-bottom:4px}
.tui-claude .bash-ask{display:inline-block;border:1px solid #c9a227;border-radius:3px;
  padding:3px 7px 4px;margin:2px 0;background:#14120c;max-width:100%}
.tui-claude .bash-h{display:block;color:#e3b341;font-size:max(9.5px,var(--fmin,0px));margin-bottom:2px}
.tui-claude .tc-foot .mode{color:#e3b341;font-weight:600}
.tui-claude .tc-foot .dim{color:#6e6e6e}
.tui-codex .tc-foot .sep,.tui-codex .cx-foot .sep{opacity:.55;margin:0 3px}
/* Codex cell (splash chrome + yellow model footer) */
.tui-codex{color:#e6edf3}
/* Der Kasten des Codex-Starts ist im Original inhaltsbreit, nicht panelbreit
   (die Einzelansicht deckelt ihn ebenso, siehe .tui-codex-full .cx-box.big).
   Ohne Deckel zog er sich im Fleet-Schritt, wo die Zelle die volle
   Fensterbreite hat, auf rund 950px auseinander. In den schmalen Zellen des
   Sechserrasters bleibt der Deckel wirkungslos. */
.tui-codex .cx-box{flex:none;margin:4px 8px 6px;padding:6px 8px;border:1px solid #4a4a4a;
  border-radius:4px;background:#0c0c0c;max-width:380px}
.tui-codex .cx-title{color:#e8e8e8;font-size:max(10px,var(--fmin,0px));margin-bottom:3px}
.tui-codex .cx-gt{color:#8a8a8a}.tui-codex .cx-ver{color:#8a8a8a}
.tui-codex .cx-meta{font-size:max(9.5px,var(--fmin,0px));color:#9a9a9a;display:flex;align-items:baseline;gap:5px;flex-wrap:wrap}
.tui-codex .cx-meta .k{color:#6e6e6e}.tui-codex .cx-meta .v{color:#d0d0d0}
.tui-codex .cx-meta .link{color:#58a6ff}.tui-codex .cx-meta .dim{color:#6e6e6e}
.tui-codex .cx-foot{color:#c9a227}
.tui-codex .d{color:#6e7681}.tui-codex .w{color:#f0f6fc;font-weight:600}
.tui-codex .c{color:#39c5cf}.tui-codex .g{color:#3fb950}.tui-codex .r{color:#ff7b72}
.tui-codex .tip-new{font-style:italic;color:#b0b0b0}
/* Grok Build mid-session (tool diamonds, keys, always-approve) */
.tui-grok-cell{color:#c9c9c9;background:#121212}
.tui-grok-cell .d{color:#6e7681}.tui-grok-cell .w{color:#e8e8e8;font-weight:600}
.tui-grok-cell .m{color:#9a9a9a}.tui-grok-cell .hk{color:#7a7a7a;font-size:max(9px,var(--fmin,0px))}
.tui-grok-cell .tg-foot{color:#8a8a8a}
.cell.ca{grid-area:a}.cell.cb{grid-area:b}.cell.cc{grid-area:c}
.cell.cd{grid-area:d}.cell.ce{grid-area:e}.cell.cf{grid-area:f}
.cpill{position:absolute;top:6px;right:6px;z-index:5;display:flex;align-items:center;gap:4px;
  padding:2px 4px;border-radius:6px;background:var(--sbase);box-shadow:var(--hairline);opacity:.9}
.cpill .bchip{max-width:104px;font-size:max(9px,var(--fmin,0px))}
.cpill .bchip svg{width:12px;height:12px}
.cpill .tb{padding:3px}
.cpill .tb svg{width:12px;height:12px}

/* ================= LIBRARY (eigenes Fenster, analog Review) ================= */
.libsec{border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--raise);padding:72px 0 0;margin-top:56px}
.libbeats{display:grid;grid-template-columns:minmax(0,clamp(240px,24vw,300px)) minmax(0,1fr);gap:40px;
  align-items:start;padding-bottom:40px}
.libbeatcol{display:flex;flex-direction:column;padding-bottom:28vh}
.libbeat{min-height:88vh;display:flex;flex-direction:column;justify-content:center;gap:14px}
.libbeat h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(21px,2.1vw,27px);line-height:1.16;letter-spacing:-0.01em;margin:0;text-wrap:balance}
.libbeat h2 em{font-style:normal;color:var(--acc)}
.libbeat p{color:var(--mut);font-size:15px;margin:0;max-width:40ch}
.libbeat p b{color:var(--fg);font-weight:600}
.libbeats[data-ready] .libbeat{opacity:.22;transition:opacity .45s cubic-bezier(.22,.61,.36,1)}
.libbeats[data-ready] .libbeat[data-state="current"]{opacity:1}
.app-3{display:flex;flex-direction:column;background:var(--sbase);border:1px solid var(--n700);
  overflow:hidden}
.app-3 .lib-hd{display:flex;align-items:center;justify-content:space-between;
  padding:8px 14px;border-bottom:1px solid var(--n800);flex:none}
.app-3 .lib-hd-title{display:inline-flex;align-items:center;gap:8px;font-size:13px;
  font-weight:600;color:var(--n100)}
.app-3 .lib-hd-title svg{width:16px;height:16px;stroke:var(--a-acc);fill:none;stroke-width:1.25;
  vector-effect:non-scaling-stroke;stroke-linecap:round;stroke-linejoin:round}
.app-3 .lib-refresh{color:var(--n500);font-size:13px;padding:2px 4px}
.app-3 .lib-body{flex:1;min-height:0;overflow:auto;padding:12px 14px;display:flex;
  flex-direction:column;gap:8px;
  /* Sichtbarer, schmaler Scrollbalken statt Overlay: er ist die Ankuendigung,
     dass die Liste unter der Fensterkante weitergeht. Chromium blendet
     Overlay-Balken im Ruhezustand aus, deshalb zusaetzlich die klassische
     Ausfuehrung ueber das Vendor-Pseudoelement. */
  scrollbar-width:thin;scrollbar-color:var(--n700) transparent;
  /* Der weiche Auslauf am unteren Rand ist die Ankuendigung, dass die Liste
     unter der Fensterkante weitergeht, und er ersetzt den harten Schnitt
     mitten durch eine Zeile. Wo der Inhalt in das Fenster passt (Kapitel 05),
     endet er 90px darueber und der Verlauf bleibt unsichtbar. Dasselbe Mittel
     wie am rechten Rand der Release-Tabelle. */
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 28px),transparent);
  mask-image:linear-gradient(to bottom,#000 calc(100% - 28px),transparent)}
.app-3 .lib-body::-webkit-scrollbar{width:8px}
.app-3 .lib-body::-webkit-scrollbar-track{background:transparent}
.app-3 .lib-body::-webkit-scrollbar-thumb{background:var(--n700);border-radius:4px}
/* Die Kinder duerfen NICHT schrumpfen. Als Flex-Elemente hatten sie
   flex-shrink:1 und wurden zusammengedrueckt, sobald die Liste hoeher wurde
   als das Fenster: der aufgeklappte Geltungsbereich verlor 156px seines
   eigenen Inhalts und schnitt die Zeile "TEMPLATES" waagerecht durch die
   Versalien, weil er selbst overflow:hidden traegt. Der Behaelter hat
   overflow:auto und ist die richtige Stelle zum Abschneiden: dort faellt der
   Schnitt mit der Fensterkante zusammen und der Scrollbalken sagt, dass es
   weitergeht. Betroffen waren alle fuenf Geltungsbereiche, nicht nur der
   aufgeklappte (die vier geschlossenen verloren je 10px ihrer Kopfzeile). */
.app-3 .lib-body > *{flex:none}
.app-3 .lib-note{font-size:max(11px,var(--fmin,0px));line-height:1.45;color:var(--n500);padding:8px 10px;
  border:1px solid var(--n800);border-radius:6px;background:var(--sinset)}
.app-3 .lib-scope{border:1px solid var(--n700);border-radius:6px;background:var(--sraised);
  overflow:hidden}
.app-3 .lib-scope-hd{display:flex;align-items:center;gap:8px;padding:9px 12px;font-size:12.5px}
.app-3 .lib-scope-hd .chev{color:var(--n500);width:12px;flex:none;display:inline-flex;align-items:center}
.app-3 .lib-scope-hd b{color:var(--n100);font-weight:600}
/* Jede Zeile fuehrt links dasselbe Format: 14x14, und darin ein Symbol. Vorher
   standen an derselben Stelle ein 12px-Quadrat, ein 14px-Quadrat und ein
   Kreis, alle drei leer, obwohl das Design-System hier Lucide vorsieht. */
.app-3 .lib-scope-hd .ico,
.app-3 .lib-sec-hd .ico{width:14px;height:14px;flex:none;display:inline-flex;
  align-items:center;justify-content:center;color:var(--a-acc)}
.app-3 .lib-scope-hd .ico svg,
.app-3 .lib-sec-hd .ico svg{width:14px;height:14px}
.app-3 .lib-secs{border-top:1px solid var(--n800)}
/* Section rows (Skills, Knowledge, …) — collapsible like ScopePanel */
.app-3 .lib-sec{border-top:1px solid var(--n800)}
.app-3 .lib-sec:first-child{border-top:none}
.app-3 .lib-sec-hd{display:flex;align-items:center;gap:8px;padding:7px 12px 7px 20px;
  font-size:12px;color:var(--n200)}
.app-3 .lib-sec-hd .chev{color:var(--n500);width:12px;flex:none;display:inline-flex;align-items:center}
/* Ein Symbol, zwei Zustaende: der Aufklapp-Pfeil dreht, statt die Glyphe zu
   tauschen. Die Textdreiecke davor haben ihre Groesse und Hoehenlage aus den
   Glyphenmassen der Schrift bezogen und liessen sich nicht steuern. */
.app-3 .chev svg{width:12px;height:12px;transition:transform .15s ease}
.app-3 .chev.open svg{transform:rotate(90deg)}
.app-3 .lib-sec-hd .ico{color:var(--n400)}
.app-3 .lib-sec-hd .nm{flex:1;min-width:0}
.app-3 .lib-sec-hd u{margin-left:auto;font-size:max(11px,var(--fmin,0px));color:var(--n500);text-decoration:none;
  font-family:var(--amono)}
.app-3 .lib-sec-body{display:none;padding:0 10px 10px 28px}
.app-3 .lib-cat{font-size:max(10px,var(--fmin,0px));font-weight:700;text-transform:uppercase;letter-spacing:.08em;
  color:var(--n500);padding:8px 4px 4px;display:flex;align-items:center;gap:6px}
.app-3 .lib-cat u{margin-left:auto;font-family:var(--amono);font-weight:400;font-size:max(10px,var(--fmin,0px));
  text-decoration:none;color:var(--n500)}
.app-3 .lib-item{border:1px solid var(--n800);border-radius:6px;background:var(--sbase);
  margin-top:4px;overflow:hidden}
.app-3 .lib-item-hd{display:flex;align-items:center;gap:8px;padding:7px 10px;font-size:11.5px;
  color:var(--n200)}
/* Ein Punkt derselben Bedeutung hat dieselbe Form. Vorher war .dot in der
   Dateizeile ein Quadrat (2px) und in der Memory-Karte ein Kreis (9999px),
   beide 10x10 und beide links vor einem Dateinamen im selben Fenster. Der
   Klassenname sagt Kreis, also ist es ein Kreis. */
.app-3 .lib-item-hd .dot{width:10px;height:10px;border-radius:var(--r-pill);flex:none;
  background:color-mix(in oklch, var(--a-acc) 40%, transparent);
  box-shadow:inset 0 0 0 1px color-mix(in oklch, var(--a-acc) 55%, transparent)}
.app-3 .lib-item-hd .nm{font-weight:600;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
.app-3 .lib-item-hd .ext{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500)}
/* Kopier-Marke. Vorher stand hier eine massive, mattgraue 12x12-Flaeche ohne
   jede Binnenform, waehrend in derselben Zeilenhoehe 84 echte Lucide-Konturen
   stehen. Jetzt steht dort das Lucide-Copy in derselben Bauart. */
.app-3 .lib-item-hd .copy{width:12px;height:12px;flex:none;color:var(--n500);
  display:inline-flex;align-items:center;justify-content:center}
.app-3 .lib-item-hd .copy svg{width:12px;height:12px}
.app-3 .lib-preview{display:none;margin:0 8px 8px;padding:10px 12px;border-radius:6px;
  background:var(--sinset);border:1px solid var(--n800);font-family:var(--amono);
  font-size:max(10.5px,var(--fmin,0px));line-height:1.55;color:var(--n300);white-space:pre-wrap;max-height:148px;
  overflow:hidden}
.app-3 .lib-preview .pt{display:block;font-size:max(9.5px,var(--fmin,0px));text-transform:uppercase;letter-spacing:.08em;
  color:var(--n500);margin-bottom:6px;font-family:var(--asans);font-weight:600}
.app-3 .lib-mem{display:none;flex-direction:column;gap:4px}
.app-3 .lib-mem-card{display:flex;align-items:flex-start;gap:8px;padding:7px 10px;
  border:1px solid var(--n800);border-radius:6px;background:var(--sbase)}
.app-3 .lib-mem-card .dot{width:10px;height:10px;border-radius:var(--r-pill);flex:none;margin-top:2px;
  background:color-mix(in oklch, var(--a-acc) 45%, transparent)}
.app-3 .lib-mem-card .meta{min-width:0;display:flex;flex-direction:column;gap:2px}
.app-3 .lib-mem-card .fn{font-size:11.5px;font-weight:600;color:var(--n100)}
.app-3 .lib-mem-card .sn{font-size:max(10.5px,var(--fmin,0px));color:var(--n500);line-height:1.4;
  overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
/* Scroll-driven open states (beat 0 overview, 1 knowledge, 2 claude+memory) */
.libbeats[data-active="1"] .lib-sec-kn > .lib-sec-body{display:block}
.libbeats[data-active="1"] .lib-sec-kn > .lib-sec-hd{background:var(--a-a10);color:var(--n100)}
.libbeats[data-active="1"] .lib-sec-kn > .lib-sec-hd .chev svg{transform:rotate(90deg)}
.libbeats[data-active="1"] .lib-item-xss{border-color:color-mix(in oklch, var(--a-acc) 40%, var(--n800));
  background:var(--a-a10)}
.libbeats[data-active="1"] .lib-item-xss .lib-preview{display:block}
.libbeats[data-active="2"] .lib-sec-md > .lib-sec-body,
.libbeats[data-active="2"] .lib-sec-me > .lib-sec-body{display:block}
.libbeats[data-active="2"] .lib-sec-md > .lib-sec-hd,
.libbeats[data-active="2"] .lib-sec-me > .lib-sec-hd{background:var(--a-a10);color:var(--n100)}
.libbeats[data-active="2"] .lib-sec-md .lib-preview{display:block;max-height:120px}
.libbeats[data-active="2"] .lib-sec-me .lib-mem{display:flex}
/* Fokus: obere Sektionen einklappen, damit CLAUDE.md + Memory im Viewport liegen */
.libbeats[data-active="2"] .lib-sec-sk,
.libbeats[data-active="2"] .lib-sec-ag,
.libbeats[data-active="2"] .lib-sec-hk,
.libbeats[data-active="2"] .lib-sec-ru,
.libbeats[data-active="2"] .lib-sec-kn,
.libbeats[data-active="2"] .lib-sec-st{display:none}
/* Knowledge-Beat: weniger Rauschen oberhalb der geoeffneten Sektion */
.libbeats[data-active="1"] .lib-sec-sk,
.libbeats[data-active="1"] .lib-sec-ag,
.libbeats[data-active="1"] .lib-sec-hk,
.libbeats[data-active="1"] .lib-sec-ru{display:none}
.libbeats[data-active="1"] .lib-sec-kn > .lib-sec-hd .chev,
.libbeats[data-active="2"] .lib-sec-md > .lib-sec-hd .chev,
.libbeats[data-active="2"] .lib-sec-me > .lib-sec-hd .chev{color:var(--a-acc)}
.libbeats[data-active="1"] .lib-sec-kn > .lib-sec-hd .chev svg,
.libbeats[data-active="2"] .lib-sec-md > .lib-sec-hd .chev svg,
.libbeats[data-active="2"] .lib-sec-me > .lib-sec-hd .chev svg{transform:rotate(90deg)}
.libstick .cap{margin-top:12px}
/* Ohne data-active (noch vor dem ersten Library-Beat) und bei 0: Overview. */
.libbeats:not([data-active]) .cap .c0,
.libbeats[data-active="0"] .cap .c0,
.libbeats[data-active="1"] .cap .c1,
.libbeats[data-active="2"] .cap .c2{display:inline}

/* ================= REVIEW-CENTER ================= */
.rcsec{border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--raise);padding:72px 0 0;margin-top:56px}
/* Bibliothek und Review-Center folgen unmittelbar aufeinander. Mit dem
   Aussenabstand lag zwischen ihnen ein 56px hoher Streifen Seitengrund,
   oben und unten von je einer Linie begrenzt: zwei gleich helle Flaechen,
   dazwischen ein dunklerer Balken quer ueber die volle Breite. Er las sich
   als eigenes Element, obwohl er nur der Abstand zweier Abschnitte war.
   Die beiden Abschnitte stossen jetzt aneinander und teilen sich eine
   einzige Trennlinie (die Unterkante der Bibliothek). Die 72px Innenabstand
   der Kopfzeile des Review-Centers bleiben und tragen den Abstand. */
.libsec + .rcsec{margin-top:0;border-top:0}
.beats{display:grid;grid-template-columns:minmax(0,clamp(240px,24vw,300px)) minmax(0,1fr);gap:40px;
  align-items:start;padding-bottom:40px}
.beatcol{display:flex;flex-direction:column;padding-bottom:30vh}
.rcbeat{min-height:96vh;display:flex;flex-direction:column;justify-content:center;gap:14px}
.rcbeat h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(21px,2.1vw,27px);line-height:1.16;letter-spacing:-0.01em;margin:0;text-wrap:balance}
.rcbeat h2 em{font-style:normal;color:var(--acc)}
.rcbeat p{color:var(--mut);font-size:15px;margin:0;max-width:40ch}
.rcbeat p b{color:var(--fg);font-weight:600}
.beats[data-ready] .rcbeat{opacity:.22;transition:opacity .45s cubic-bezier(.22,.61,.36,1)}
.beats[data-ready] .rcbeat[data-state="current"]{opacity:1}

.rct{display:flex;align-items:center;gap:8px;height:49px;padding:0 16px;
  border-bottom:1px solid var(--n700);flex:none}
.rct h5{margin:0;font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--n300)}
.rct .fd{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500)}
/* Sidebar 300px */
.rsb{width:300px;flex:none;border-right:1px solid var(--n700);background:var(--sraised);
  display:flex;flex-direction:column;min-height:0}
.rh{display:flex;width:100%;align-items:center;gap:6px;padding:8px 12px;
  border-top:1px solid var(--n700);border-bottom:1px solid var(--n700);background:var(--soverlay);
  font-size:max(11px,var(--fmin,0px));font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--n100)}
.rh.mt{margin-top:4px}
.rh svg{width:12px;height:12px;flex:none}
.rsec{background:var(--sbase);overflow:hidden}
.rgl{padding:10px 12px 4px;font-size:max(10px,var(--fmin,0px));font-weight:700;text-transform:uppercase;
  letter-spacing:.1em;color:var(--n500)}
.rsr{display:flex;width:100%;align-items:flex-start;gap:8px;padding:8px 10px;border-left:2px solid transparent}
.rsr.sel{border-left-color:var(--a-acc);background:var(--a-a10)}
.rsr u{width:8px;height:8px;border-radius:9999px;flex:none;margin-top:4px;background:var(--a-acc);
  display:block;text-decoration:none}
.rsr u.hist{background:var(--n600)}
.rsr .cc{min-width:0;display:flex;flex-direction:column}
.rsr .t1{font-size:12px;color:var(--n100);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rsr .t2{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rov{margin-top:2px;display:inline-flex;width:fit-content;align-items:center;gap:4px;border-radius:4px;
  border:1px solid var(--n700);background:color-mix(in oklch, var(--a-warn) 10%, transparent);
  padding:1px 6px;font-family:var(--amono);font-size:max(9px,var(--fmin,0px));color:var(--a-warn)}
.rov svg{width:12px;height:12px;flex:none}
.rscope{display:flex;flex-direction:column;gap:4px;border-bottom:1px solid var(--n700);padding:8px 12px;flex:none}
.rscope .ch{display:flex;align-items:center;gap:4px}
.rscope .ch span{border-radius:9999px;padding:4px 10px;font-size:max(11px,var(--fmin,0px));color:var(--n400)}
.rscope .ch span.on{background:var(--a-a15);color:var(--a-acc)}
.rscope .bs{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rbulk{display:flex;align-items:center;gap:8px;border-bottom:1px solid var(--n700);padding:6px 12px;flex:none}
.rbulk svg{width:14px;height:14px;flex:none;color:var(--n500)}
.rbulk .lb{font-size:max(11px,var(--fmin,0px));color:var(--n300)}
.rbulk .pg{margin-left:auto;font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n400);white-space:nowrap}
.rfiles{flex:1;min-height:0;overflow:hidden;background:var(--sbase)}
.rdir{padding:8px 12px 4px;font-family:var(--amono);font-size:max(10px,var(--fmin,0px));letter-spacing:.025em;color:var(--n500)}
.rf{display:flex;width:100%;align-items:stretch;border-left:2px solid transparent;
  transition:background-color .3s ease,border-color .3s ease}
.rf.sel{border-left-color:var(--a-acc);background:var(--a-a10)}
.rf .st{display:flex;flex:none;align-items:center;padding:0 4px 0 8px}
.rf .st svg{width:14px;height:14px;color:var(--n500)}
.rf .st svg.ok{color:var(--a-ok)}
.rf .rw{display:flex;min-width:0;flex:1;align-items:center;gap:8px;padding:6px 12px 6px 6px;
  font-size:12px;color:var(--n300)}
.rf.sel .rw{color:var(--n100)}
.rf .ch{width:12px;flex:none;font-family:var(--amono);font-weight:700}
.rf .ch.m{color:var(--a-warn)}.rf .ch.a{color:var(--a-ok)}.rf .ch.d{color:var(--a-err)}
.rf .pt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;font-family:var(--amono);font-size:max(11px,var(--fmin,0px))}
.bal{flex:none;font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n400)}
.bal .p{color:var(--a-ok)}.bal .m{color:var(--a-err)}.bal .s{padding:0 2px;color:var(--n500)}
/* Diff-Spalte */
.rcol{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;position:relative}
.rsum{margin:12px 16px 0;flex:none;border-radius:6px;border:1px solid var(--n700);
  border-left:2px solid var(--a-acc);background:var(--sraised)}
.rsum .hd{display:flex;width:100%;align-items:center;gap:6px;padding:8px 12px;font-size:max(10px,var(--fmin,0px));
  font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--n400)}
.rsum .hd svg{width:12px;height:12px}
.rsum .hd svg.ac{color:var(--a-acc)}
.rsum .bd{padding:0 12px 12px;font-size:12px;line-height:1.625;color:var(--n300);max-width:78ch}
.rph{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--n700);flex:none}
.rph .pp{font-family:var(--amono);font-size:12px;color:var(--n300)}
.rph .bal{margin-left:auto}
.rrg{display:flex;align-items:stretch;border:1px solid var(--n700);font-size:12px;flex:none}
.rrg span{padding:4px 8px;color:var(--n400)}
.rrg span+span{border-left:1px solid var(--n700)}
.rrg span.on{background:var(--a-a15);color:var(--a-acc)}
.pri{display:inline-flex;align-items:center;gap:6px;border-radius:6px;background:var(--a-acc);
  padding:4px 10px;font-size:12px;font-weight:500;color:var(--n950);box-shadow:var(--hairline)}
.pri svg{width:14px;height:14px}
.sec{display:inline-flex;align-items:center;gap:6px;border-radius:6px;border:1px solid var(--n700);
  padding:4px 10px;font-size:12px;color:var(--n300)}
.sec svg{width:14px;height:14px}
.rdw{display:flex;flex:1;min-height:0;background:var(--sbase)}
.rdiff{flex:1;min-width:0;overflow:hidden;font-family:var(--amono);font-size:13px;line-height:1.4}
.dl{display:flex;align-items:flex-start}
.dl .gm{width:10px;flex:none;display:flex;align-items:center;justify-content:center;
  background:var(--sraised);align-self:stretch}
.dl .gm u{width:8px;height:8px;border-radius:9999px;display:none;text-decoration:none}
.dl .gm u.nt{background:var(--a-acc)}
.dl .gm u.rq{background:var(--a-warn);animation:twpulse 2s cubic-bezier(.4,0,.6,1) infinite}
.dl .no{width:42px;flex:none;padding:0 6px;text-align:right;font-size:12px;color:var(--n500);
  background:var(--sraised);border-right:1px solid var(--n800);align-self:stretch}
.dl .sg{width:16px;flex:none;text-align:center;font-weight:700;font-size:12px;color:transparent}
.dl .tx{flex:1;min-width:0;padding:0 16px 0 6px;white-space:pre;overflow:hidden;color:var(--n200)}
.dl.add{background:var(--dadd)}
.dl.add .sg{color:var(--a-ok)}
.dl.del{background:var(--drem)}
.dl.del .sg{color:var(--a-err)}
.dl .hl{background:var(--daddw);border-radius:2px}
.dl.del .hl{background:var(--dremw)}
.dcol{padding:4px 16px;color:var(--a-acc);background:var(--a-a05);font-size:max(11px,var(--fmin,0px))}
.sy-k{color:var(--a-acc)}.sy-s{color:var(--a-ok)}.sy-c{color:var(--n500)}
.sy-f{color:oklch(76% .13 285)}.sy-p{color:oklch(76% .10 250)}
.rrul{position:relative;width:8px;flex:none;border-left:1px solid var(--n700);background:var(--sinset)}
.rrul u{position:absolute;border-radius:4px;opacity:.9;display:block;text-decoration:none}
.rrul u.ad{left:0;width:5px;background:var(--a-ok)}
.rrul u.rm{left:0;width:3px;background:var(--a-err)}
.rrul u.rq{right:0;width:3px;background:var(--a-warn);opacity:0;transition:opacity .5s ease}
.rrul u.nt{right:0;width:3px;background:var(--a-acc)}
.rft{display:flex;align-items:center;gap:8px;padding:8px 12px;border-top:1px solid var(--n700);
  background:var(--sbase);font-size:12px;flex:none}
/* Die Mitte gibt zuerst nach, die Schaltflaechen bleiben einzeilig. */
.rft .md{flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:flex-end;gap:12px;
  overflow:hidden;white-space:nowrap;font-family:var(--amono);color:var(--n400)}
.rft .rst,.rft .pri,.rft .rrf,.rft .rrg{flex:none;white-space:nowrap}
.rst{display:inline-flex;align-items:center;gap:6px;border-radius:6px;padding:4px 8px;color:var(--a-err)}
.rst svg{width:14px;height:14px}
.rrf{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;color:var(--n300)}
.rrf svg{width:14px;height:14px}
/* Ueber der Fusszeile, nicht darauf: die Trigger sind im Original ebenfalls
   so gesetzt, dass sie nichts Bedienbares verdecken. */
.rtrig{position:absolute;right:8px;bottom:48px;z-index:10;display:flex;flex-direction:column;gap:4px}
.rtrig span{position:relative;border-radius:6px;border:1px solid var(--n700);padding:4px;
  background:var(--soverlay);color:var(--n400);display:inline-flex;transition:all .3s ease}
.rtrig span svg{width:16px;height:16px}
.rtrig span u{position:absolute;right:2px;top:2px;width:6px;height:6px;border-radius:9999px;display:block}
.rtrig span u.ac{background:var(--a-acc)}
.rtrig span u.wr{background:var(--a-warn)}
.rside{width:0;flex:none;overflow:hidden;transition:width .6s var(--eout)}
.rpanel{width:320px;height:100%;display:flex;flex-direction:column;min-height:0;
  border-left:1px solid var(--n700);background:var(--sraised)}
.rpt{display:flex;flex:none;align-items:center;gap:8px;border-bottom:1px solid var(--n700);padding:8px 12px}
.rpt .tt{font-size:max(11px,var(--fmin,0px));font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--n300)}
.rpt .sp{flex:1}
.rpt .ib svg{width:14px;height:14px}
.rpl{display:flex;min-height:0;flex:1;flex-direction:column;gap:8px;overflow:hidden;padding:12px}
.crd{border-radius:6px;border:1px solid var(--n700);border-left:2px solid var(--a-warn);
  background:var(--sraised);opacity:0;transform:translateY(6px);
  transition:opacity .5s var(--eout),transform .5s var(--eout)}
.crd .hd{display:flex;flex-direction:column;gap:4px;padding:8px 12px}
.crd .k{display:flex;align-items:center;gap:6px;font-size:max(10px,var(--fmin,0px));font-weight:700;text-transform:uppercase;
  letter-spacing:.1em;color:var(--n400)}
.crd .k svg{width:12px;height:12px;flex:none;color:var(--a-warn)}
.crd .pp{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.crd .tx{font-size:12px;color:var(--n300)}
.rpp{border-top:1px solid var(--n700);flex:none}
.rpp .tp{padding:8px 12px}
.rpp .lb{font-size:max(10px,var(--fmin,0px));font-weight:700;text-transform:uppercase;letter-spacing:.1em;
  color:var(--n500);padding-bottom:4px;display:block}
.rpp .ta{width:100%;border-radius:6px;border:1px solid var(--n700);background:var(--soverlay);
  padding:8px 12px;font-family:var(--amono);font-size:max(10.5px,var(--fmin,0px));line-height:1.625;color:var(--n400);
  white-space:pre-wrap;height:100px;overflow:hidden}
.rpp .ac{display:flex;flex-wrap:wrap;align-items:center;gap:8px;border-top:1px solid var(--n700);padding:8px 12px}
.rpp .cn{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500)}
.rpp .sp{flex:1}
.rfb{display:flex;width:100%;align-items:center;gap:6px;padding-top:4px;font-size:max(10.5px,var(--fmin,0px));
  color:var(--n400);opacity:0}
.rfb svg{width:14px;height:14px;flex:none;animation:spin 1s linear infinite}

/* ================= ZUSTAENDE DER KAPITEL (scroll-gesteuerte Unterschritte) =================
   Sessions-Fenster (.story data-active 0..5): 0-2 Start, 3 Fleet (2 Sessions),
   4 Notify, 5 Steer. Library und Review sind eigene Sections (app-3 / app-2).
   Config-Tab-Tour und Kanban/Tasks nicht in der Story.
   Kein harter Sprung von 2 Single-Sessions auf 6er-Grid.
*/

/* Baselines: alles aus, was spaeter eingeschaltet wird */
.story .single-claude,
.story .single-codex,
.story .grid6{opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .4s ease,visibility .4s ease}
.story .empty{opacity:0;visibility:hidden;transition:opacity .35s ease,visibility .35s ease}
.story .ctx{opacity:0;transform:scale(.97);transition:opacity .3s ease,transform .3s ease}
.story .srow{opacity:0;transform:translateX(-8px);
  transition:opacity .4s var(--eout),transform .4s var(--eout),background-color .3s ease}
.story .tpill{opacity:0;transition:opacity .3s ease}
.story .mm{opacity:0;transition:opacity .3s ease}
.story .cell{display:none;opacity:0;min-height:0;min-width:0}
.story .seg-1{color:var(--n500);background:none;transition:color .25s,background-color .25s}
.story .seg-6{color:var(--n500);background:none;transition:color .25s,background-color .25s,outline .25s}

/* Benachrichtigungen (nur im Sessions-Fenster).
   Nachbau von NotificationWindow.tsx: seit dem Umbau ist das kein 260px
   breites Aufklapp-Menue mehr, sondern ein eigenes, verschiebbares Fenster
   das die Glocke im Dock oeffnet. Die App oeffnet es mit 420x440; im Nachbau
   steht es auf 360x375, weil die Buehne ohnehin skaliert und das Fenster in
   der Inszenierung sonst den halben Terminalbereich verdeckt. Die Liste fuehrt
   deshalb sechs Zeilen statt acht: Die Zeilenmasse bleiben die der App, und
   eine achte Zeile wuerde an der Unterkante abgeschnitten. Es startet unten links
   (x=24, 96px ueber der Unterkante), traegt eine Kopfzeile mit Titel und den
   drei Knoepfen Aktualisieren, Alle als gelesen markieren, Schliessen, darunter
   die Zeile "Zuletzt geprueft", dann die Liste.
   Eine Zeile ist: Symbol, Titel (zweizeilig gekappt), darunter Repository und
   Zeitangabe, ganz rechts der Punkt fuer ungelesen. Der Grund einer Meldung
   steckt im Symbol (Pull Request, At-Zeichen, Personensymbol), nicht im Text;
   die App schreibt ihn nur bei CI- und Sicherheitsmeldungen aus.
   Das Fenster liegt als Geschwister von Sidebar und Terminalbereich im
   .abody, damit es sich am Fensterrahmen ausrichtet und nicht am Terminal:
   im Dock steht die Glocke, aus der es kommt. */
.story .notif-pop{
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .35s ease,visibility .35s ease,transform .35s var(--eout);
  position:absolute;left:24px;bottom:96px;z-index:20;width:360px;height:375px;
  display:flex;flex-direction:column;
  background:var(--sraised);border:1px solid var(--n700);border-radius:var(--r-lg);
  box-shadow:var(--lift);transform:translateY(8px)}
.story .notif-h{flex:none;display:flex;align-items:center;gap:4px;padding:7px 8px 7px 10px;
  border-bottom:1px solid var(--n800)}
.story .notif-t{flex:1;min-width:0;font-size:max(11px,var(--fmin,0px));font-weight:600;
  text-transform:uppercase;letter-spacing:.12em;color:var(--n300)}
.story .notif-hb{flex:none;display:inline-flex;align-items:center;justify-content:center;
  width:20px;height:20px;border-radius:var(--r-md);color:var(--n500)}
.story .notif-hb svg{width:14px;height:14px}
.story .notif-hint{flex:none;padding:6px 10px;color:var(--n500);
  font-size:max(10.5px,var(--fmin,0px));white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.story .notif-l{flex:1;min-height:0;overflow:hidden;padding:2px 4px 4px;
  display:flex;flex-direction:column;gap:1px}
.story .notif-i{flex:none;display:grid;grid-template-columns:16px minmax(0,1fr) 6px;
  align-items:start;gap:8px;padding:7px 8px;border-radius:var(--r-md)}
.story .n-ic{display:flex;justify-content:center;padding-top:1px;color:var(--n400)}
.story .n-ic svg{width:14px;height:14px}
.story .n-c{min-width:0;display:flex;flex-direction:column;gap:3px}
.story .n-ti{color:var(--n200);font-weight:500;font-size:max(12px,var(--fmin,0px));line-height:1.3;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.story .n-mt{display:flex;align-items:center;gap:6px;min-width:0}
.story .n-rp{font-family:var(--amono);font-size:max(10px,var(--fmin,0px));color:var(--n500);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.story .n-ag{margin-left:auto;flex:none;font-size:max(10px,var(--fmin,0px));color:var(--n600);
  white-space:nowrap}
.story .n-dot{align-self:center;width:6px;height:6px;border-radius:var(--r-pill);background:var(--a-acc)}
/* Gelesen: der Punkt bleibt stehen und wird nur unsichtbar, damit die Zeilen
   nicht unterschiedlich breit werden. Genau das macht die App. */
.story .notif-i.read .n-ti{color:var(--n400);font-weight:400}
.story .notif-i.read .n-dot{opacity:0}


/* ---- 0: Favoriten + Starten mit (Claude-Menue) ---- */
.story[data-active="0"] .empty{opacity:1;visibility:visible}
.story[data-active="0"] .fav-1{background:var(--a-a10);
  box-shadow:0 0 0 1px color-mix(in oklch, var(--a-acc) 35%, transparent)}
.story[data-active="0"] .fav-1 .fa{display:flex}
.story[data-active="0"] .ctx:not(.ctx-2){opacity:1;transform:scale(1)}
.story[data-active="0"] .ctx:not(.ctx-2) .mi-claude{color:var(--a-acc);background:var(--a-a15);font-weight:600}
.story[data-active="0"] .sb{position:relative;z-index:6}
.story[data-active="0"] .sbs,.story[data-active="0"] .favs{overflow:visible}
.story[data-active="0"] .tmain{z-index:1}
.story[data-active="0"] .tmain::after{content:"";position:absolute;inset:0;z-index:3;
  background:oklch(0% 0 0 / .38);pointer-events:none}
.story[data-active="0"] .seg-1{color:var(--a-acc);background:var(--a-a10)}
.story[data-active="0"] .nosess{opacity:1;position:static}

/* ---- 1: Claude Session (single) ---- */
.story[data-active="1"] .single-claude{opacity:1;visibility:visible;pointer-events:auto}
.story[data-active="1"] .srow.s1{opacity:1;transform:none;background:var(--a-a10)}
.story[data-active="1"] .tpill{opacity:.85}
.story[data-active="1"] .seg-1{color:var(--a-acc);background:var(--a-a10)}
.story[data-active="1"] .nosess{opacity:0;position:absolute;pointer-events:none}
.story[data-active="1"] .fav-1{background:transparent;box-shadow:none}

/* ---- 2: Codex maximiert (single, 2 Sessions in Liste, Menue zu) ---- */
.story[data-active="2"] .single-codex{opacity:1;visibility:visible;pointer-events:auto}
.story[data-active="2"] .srow.s1{opacity:1;transform:none;background:transparent}
.story[data-active="2"] .srow.s2{opacity:1;transform:none;background:var(--a-a10)}
.story[data-active="2"] .tpill{opacity:.85}
.story[data-active="2"] .seg-1{color:var(--a-acc);background:var(--a-a10)}
.story[data-active="2"] .nosess{opacity:0;position:absolute;pointer-events:none}

/* Shared grid chrome for 3..5 (session fleet + ambient) */
.story[data-active="3"] .grid6,
.story[data-active="4"] .grid6,
.story[data-active="5"] .grid6{
  opacity:1;visibility:visible;pointer-events:auto;
  width:100%;height:100%;display:grid;gap:2px}
.story[data-active="3"] .tpill,
.story[data-active="4"] .tpill,
.story[data-active="5"] .tpill{opacity:.85}
.story[data-active="3"] .seg-6,
.story[data-active="4"] .seg-6,
.story[data-active="5"] .seg-6{color:var(--a-acc);background:var(--a-a10)}
.story[data-active="3"] .seg-1,
.story[data-active="4"] .seg-1,
.story[data-active="5"] .seg-1{color:var(--n500);background:none}
.story[data-active="3"] .nosess,
.story[data-active="4"] .nosess,
.story[data-active="5"] .nosess{opacity:0;position:absolute;pointer-events:none}
.story[data-active="3"] .pj,
.story[data-active="4"] .pj,
.story[data-active="5"] .pj{margin-right:22px}
.story[data-active="3"] .ct .ln:not(.seq),
.story[data-active="4"] .ct .ln:not(.seq){opacity:1}
.story[data-active="3"] .ct .ln.seq,
.story[data-active="4"] .ct .ln.seq{opacity:0}

/* ---- 3: Grid switch · only the two sessions from 1.2/1.3 ---- */
.story[data-active="3"] .grid6{grid-template:"a" 1fr "b" 1fr / 1fr}
.story[data-active="3"] .cell.ca,
.story[data-active="3"] .cell.cb{display:flex;opacity:1;transform:none}
.story[data-active="3"] .cell.cc,
.story[data-active="3"] .cell.cd,
.story[data-active="3"] .cell.ce,
.story[data-active="3"] .cell.cf{display:none;opacity:0}
.story[data-active="3"] .srow.s1,
.story[data-active="3"] .srow.s2{opacity:1;transform:none}
.story[data-active="3"] .srow.s3,
.story[data-active="3"] .srow.s4,
.story[data-active="3"] .srow.s5,
.story[data-active="3"] .srow.s6{opacity:0;transform:translateX(-8px)}
.story[data-active="3"] .srow.s1{background:transparent}
.story[data-active="3"] .srow.s2{background:var(--a-a10)}
.story[data-active="3"] .srow.s1 .mm,
.story[data-active="3"] .srow.s2 .mm{opacity:1}
/* Die Mini-Map zeichnet das Layout, das gerade geschaltet ist. In diesem
   Schritt sind zwei Sessions offen und uebereinander angeordnet; ein Raster
   fuer sechs Kacheln behauptete an dieser Stelle eine Flotte, die es erst
   zwei Kapitel spaeter gibt. Die vier ungenutzten Kacheln fallen deshalb
   weg, statt nur leer zu bleiben: sonst platziert das Raster sie unter den
   beiden ersten und erzeugt implizite Zeilen. */
.story[data-active="3"] .mm{width:12px;height:14px;
  grid-template-columns:1fr;grid-template-rows:1fr 1fr;grid-template-areas:"a" "b"}
.story[data-active="3"] .mm span:nth-child(n+3){display:none}
.story[data-active="3"] .seg-6{
  outline:2px solid var(--a-acc);outline-offset:2px;
  box-shadow:0 0 0 4px color-mix(in oklch, var(--a-acc) 22%, transparent)}

/* ---- 4..5: full fleet ambient (notify + steer) ---- */
.story[data-active="4"] .grid6,
.story[data-active="5"] .grid6{
  grid-template:"a b c" 1fr "d e f" 1fr / 1fr 1fr 1fr}
.story[data-active="4"] .cell,
.story[data-active="5"] .cell{display:flex;opacity:1;transform:none}
.story[data-active="4"] .srow,
.story[data-active="5"] .srow{opacity:1;transform:none}
.story[data-active="4"] .mm,
.story[data-active="5"] .mm{opacity:1}
.story[data-active="4"] .srow.s1{background:var(--a-a10)}

/* ---- 4: Notifications ---- */
.story[data-active="4"] .notif-pop{opacity:1;visibility:visible;transform:none}
.story[data-active="4"] .db-bell{color:var(--a-acc);background:var(--a-a15);border-radius:6px}
.story[data-active="4"] .grid6{opacity:.45}
.story[data-active="4"] .sb{position:relative;z-index:7}

/* ---- 5: Steer ---- */
.story[data-active="5"] .ct .ln:not(.seq){opacity:1}
.story[data-active="5"] .ca{box-shadow:0 0 6px color-mix(in oklch, var(--a-acc) 40%, transparent),
  0 0 12px color-mix(in oklch, var(--a-acc) 15%, transparent)}
.story[data-active="5"] .q-base{opacity:0}
.story[data-active="5"] .q-ask{opacity:1}
.story[data-active="5"] .q-pick{opacity:1}
.story[data-active="5"] .q-run{opacity:1}
.story[data-active="5"] .e-fail{opacity:1}
.story[data-active="5"] .e-restart{opacity:1}
.story[data-active="5"] .srow.s1{background:var(--a-a10)}
.story[data-active="5"] .srow.s4 i{animation:none;background:var(--a-err)}

/* Captions 0..5 (session) */
.story[data-active="0"] .cap .c0,
.story[data-active="1"] .cap .c1,
.story[data-active="2"] .cap .c2,
.story[data-active="3"] .cap .c3,
.story[data-active="4"] .cap .c4,
.story[data-active="5"] .cap .c5{display:inline}

/* Beats des Review-Centers */
.beats[data-active="1"] .rside{width:320px}
.beats[data-active="1"] .dl.mk{background:var(--dmark);box-shadow:inset 2px 0 0 var(--a-warn)}
.beats[data-active="1"] .dl.mk .gm u.rq{display:block}
.beats[data-active="1"] .rrul u.rq{opacity:.9}
.beats[data-active="1"] .crd{opacity:1;transform:none}
.beats[data-active="1"] .crd.k2{transition-delay:.35s}
.beats[data-active="1"] .crd.k3{transition-delay:.7s}
.beats[data-active="1"] .rfb{animation:fadein .01s 2.2s forwards}
.beats[data-active="1"] .t-req{border-color:color-mix(in oklch, var(--a-warn) 50%, transparent);
  background:color-mix(in oklch, var(--a-warn) 10%, transparent);color:var(--a-warn)}
.beats[data-active="0"] .dl .gm u.nt{display:block}
.beats[data-active="0"] .cap .c3,.beats[data-active="1"] .cap .c4{display:inline}

/* ================= FEATURES: Säulen, Bereichskarten, Inventar-Akkordeon ================= */
/* Nur die senkrechten Werte: die Kurzform setzte den Seitenrand von .in auf 0,
   und da .in.fsec dieselbe Spezifitaet hat, aber spaeter steht, verlor .in.
   Folge war ein Abschnitt, der ab 901px 28px links von jedem anderen stand und
   zwischen 901 und 1000px randlos an der Fensterkante klebte. Unterhalb von
   901px war der Fehler nur zufaellig gedeckt, weil der Mobilblock Langformen
   benutzt. */
.fsec{padding-top:80px;padding-bottom:28px}
.fhead{margin-bottom:28px}
.fhead h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(22px,2.6vw,30px);letter-spacing:-0.01em;margin:10px 0 8px;text-wrap:balance}
.fhead p{color:var(--mut);max-width:58ch;font-size:15px;margin:0}
.fsub{font-family:'Space Grotesk',sans-serif;font-weight:500;font-size:11px;text-transform:uppercase;
  letter-spacing:.14em;color:var(--mut);margin:36px 0 16px;padding-bottom:9px;border-bottom:1px solid var(--line)}
.fsec .fsub:first-of-type{margin-top:8px}

/* Stufe 1a: sechs Säulen */
.fpillars{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}
.fpillar{background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px 16px 14px;
  display:flex;flex-direction:column;gap:8px;min-height:100%}
.fpillar h3{font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:15.5px;margin:0;
  letter-spacing:-0.01em;color:var(--fg)}
.fpillar p{margin:0;font-size:13.5px;line-height:1.5;color:var(--mut);flex:1}
.fpillar .badge-prerelease{align-self:flex-start;margin-top:2px}

/* Stufe 1b: vierzehn Bereichskarten */
.fcards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.fcard{background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px 16px 14px}
/* Feste Kopfhoehe. Genau eine der vierzehn Karten traegt eine
   Vorabversions-Marke, und die ist 25,05px hoch gegen 23,47px Zeilenhoehe
   daneben: ohne Mindesthoehe lag die Kopftrennlinie dieser einen Karte 2,6px
   tiefer als die der Nachbarkarte in derselben Rasterzeile. */
.fcard-hd{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:12px;
  min-height:37px;padding-bottom:10px;border-bottom:1px solid var(--line)}
/* Das Bereichssymbol steht einmal im Kartenkopf. Es stand vorher dreimal je
   Karte an den Aufzaehlungspunkten und wiederholte dort nur die Ueberschrift,
   statt die Punkte zu unterscheiden. */
.fcard-hd svg{width:20px;height:20px;flex:none;stroke:var(--acc);fill:none;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.fcard-hd h3{font-family:'Space Grotesk',sans-serif;font-weight:600;font-size:14.5px;margin:0;color:var(--fg)}
.fcard ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:11px}
.fcard li{display:flex;gap:10px;align-items:flex-start;font-size:13.5px;line-height:1.45;color:var(--mut)}
.fcard li svg{width:14px;height:14px;flex:none;margin-top:3px;stroke:var(--acc);fill:none;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.fcard li b{font-weight:600;color:var(--fg)}

/* Stufe 2: nativer Accordion-Katalog */
.finv{margin-top:12px;padding-top:8px}
.finv-lead{color:var(--mut);font-size:14.5px;max-width:62ch;margin:0 0 16px;line-height:1.5}
.finv-groups{display:flex;flex-direction:column;gap:8px}
.finv-group{border:1px solid var(--line);border-radius:var(--r-lg);background:var(--raise);overflow:hidden}
.finv-group summary{cursor:pointer;list-style:none;display:flex;flex-wrap:wrap;align-items:center;gap:10px;
  padding:12px 14px;font-size:14px;color:var(--fg);user-select:none}
.finv-group summary::-webkit-details-marker{display:none}
/* Dasselbe Zeichen wie im Bibliotheks-Mock: ein Lucide-ChevronRight, das im
   offenen Zustand um 90 Grad dreht. Der Winkel davor war aus zwei
   border-Kanten gezeichnet und um 45 Grad gedreht: groesser, heller, spitz
   auslaufend, also ein zweites Zeichen fuer denselben Zweck auf derselben
   Seite. Die Sollquelle nennt fuer Aufklappen ChevronDown und schliesst
   Ersatzformen aus. */
.finv-chev{width:12px;height:12px;flex:none;display:inline-flex;align-items:center;
  justify-content:center;color:var(--mut);margin-right:2px}
.finv-chev svg{width:12px;height:12px;stroke:currentColor;fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;display:block;transition:transform .15s ease}
.finv-group[open] .finv-chev svg{transform:rotate(90deg)}
.finv-group summary:hover{background:var(--acc10)}
/* Die Gruppe klippt mit overflow:hidden, ein nach aussen versetzter Ring
   waere also angeschnitten. Er liegt deshalb innen und folgt der Rundung. */
.finv-group summary:focus-visible{outline-offset:-2px;border-radius:var(--r-lg)}
.finv-title{font-weight:600;font-family:'Space Grotesk',sans-serif;letter-spacing:-0.01em}
.finv-list{list-style:none;margin:0;padding:0 14px 14px 28px;display:flex;flex-direction:column;gap:7px;
  border-top:1px solid var(--line)}
.finv-list li{font-size:13px;line-height:1.45;color:var(--mut);padding-top:7px;
  display:flex;flex-wrap:wrap;align-items:baseline;gap:8px}
.finv-list li::before{content:"";width:5px;height:5px;border-radius:var(--r-pill);background:var(--acc);
  flex:none;transform:translateY(-1px)}
.finv-list .badge-prerelease{font-size:10px;padding:2px 7px}

.price-catalog{margin:12px 0 0;font-size:12.5px}
/* Freistehender Link in eigener Zeile: die Trefferflaeche waechst ueber ein
   Pseudoelement auf 45px, ohne den Satzrhythmus zu aendern. Der naechste
   andere Bedienpunkt liegt 229px entfernt, es kann nichts kollidieren. */
.price-catalog a{position:relative;color:var(--acc);font-weight:600}
.price-catalog a::after{content:"";position:absolute;inset:-15px -4px}
.price-catalog a:hover{text-decoration:underline}

/* ---------- Versprechen ---------- */
.promise{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--raise);
  padding:80px 0;text-align:center}
.promise h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(24px,3.2vw,38px);letter-spacing:-0.015em;max-width:20ch;margin:12px auto 16px;text-wrap:balance}
.promise p{color:var(--mut);max-width:60ch;margin:0 auto;font-size:15.5px}
.promise p b{color:var(--fg);font-weight:600}

/* ---------- Preise ----------
   Die hervorgehobene Karte traegt denselben 2px-Akzentrahmen wie .cell im
   Sechs-Terminal-Beat. Die Seite hat fuer diese Geste bereits eine Bedeutung
   ("das hier ist das aktive Element"); Pro erbt sie, statt eine zweite
   Hervorhebungssprache einzufuehren. */
.pricing{padding:72px 0 8px}
.pricing h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(20px,2.4vw,28px);letter-spacing:-0.01em;margin:10px 0 10px;text-wrap:balance}
.price-lead{color:var(--mut);max-width:58ch;margin:0 0 22px;font-size:15px}

/* Abrechnungsschalter. Baugleich mit dem Sprachumschalter: die Seite hat genau
   zwei Schalter mit zwei sich ausschliessenden Optionen, und die trugen vorher
   zwei Bauarten (Pille gegen 8px, 44 gegen 36px hoch, Akzent-Tint gegen hellere
   Flaeche). Die Pillenform war ausserdem der einzige 9999px-Radius der Seite
   ausserhalb von Punkten und Marken. Die Ersparnis steht in --ok, damit sie
   nicht mit der Auswahl um dieselbe Farbe konkurriert. */
.bill{display:inline-flex;background:var(--raise);border:1px solid var(--line);
  border-radius:var(--r-lg);height:36px;margin:0 0 26px}
.bill-opt{font-family:'Instrument Sans',system-ui,sans-serif;font-size:13.5px;color:var(--mut);
  background:none;border:0;padding:0 16px;cursor:pointer;line-height:1;
  display:inline-flex;align-items:center;gap:8px}
.bill-opt{position:relative}
/* Die Trefferflaeche bleibt ueber 44px, ohne den Schalter hoeher zu machen. */
.bill-opt::after{content:"";position:absolute;inset:-6px 0}
.bill-opt:hover{color:var(--fg)}
.bill-opt[aria-pressed="true"]{background:var(--over);color:var(--fg);font-weight:600}
.bill > :first-child{border-radius:var(--r-md) 0 0 var(--r-md)}
.bill > :last-child{border-radius:0 var(--r-md) var(--r-md) 0}
.bill-save{font-size:11.5px;color:var(--ok);white-space:nowrap}

/* Sichtbar ist immer genau eine Abrechnungsvariante. */
.pricing[data-billing="monthly"] [data-bill="annual"]{display:none}
.pricing[data-billing="annual"] [data-bill="monthly"]{display:none}

.price-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}

/* Randstaerken und Innenabstaende ergaenzen sich zu derselben Aussenkante:
   1+19 bei den ruhigen Karten, 2+18 bei der hervorgehobenen. */
.price-card{background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:19px 17px;display:flex;flex-direction:column}
.price-card-featured{background:var(--over);border:2px solid var(--acc);padding:18px 16px;
  box-shadow:0 0 0 4px var(--glow)}
.price-kicker{font-family:'Space Grotesk',sans-serif;font-weight:500;text-transform:uppercase;
  letter-spacing:0.1em;font-size:10.5px;color:var(--mut)}
.price-card-featured .price-kicker{color:var(--acc)}
.price-card h3{font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:17px;margin:6px 0 0}

/* Beschreibung und Preis bekommen eine Mindesthoehe, damit Preiszeile und
   Knopf ueber alle drei Karten auf derselben Linie liegen. Ohne sie
   verschiebt ein einziger zusaetzlicher Zeilenumbruch die halbe Karte. */
.price-for{color:var(--mut);font-size:12.5px;line-height:1.6;margin:8px 0 0;min-height:40px}
.price-value{font-family:'Space Grotesk',sans-serif;margin:14px 0 16px;min-height:47px;
  display:flex;align-items:baseline;flex-wrap:wrap;gap:7px}
.price-value b{font-weight:700;font-size:30px;letter-spacing:-0.02em}
.price-value.is-text b{font-size:22px}
.price-unit{color:var(--mut);font-family:'Instrument Sans',system-ui,sans-serif;font-size:12.5px}

/* Der gefuellte Knopf hat keinen Rand, der Geister-Knopf einen von 1px. Ohne
   Ausgleich waeren die Karten um genau diese 2px gegeneinander verschoben. */
/* Volle Kartenbreite, aber weiterhin mittig: display:block haette den Text
   mit der neuen Mindesthoehe von 44px oben im Knopf kleben lassen. */
.price-action{display:flex;align-items:center;justify-content:center;text-align:center}
.price-action.btn{border:1px solid transparent}
.price-action[aria-disabled="true"]{opacity:.4;cursor:not-allowed}
/* Zwei Zeilen sind reserviert, weil diese Zeile ihren Text zur Laufzeit
   wechselt (Wartehinweis, Testmodus, verbunden). Ohne feste Hoehe verschiebt
   der laengere Text nur die eine Karte und die Listen laufen auseinander. */
.price-status{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--mut);
  margin:9px 0 0;line-height:1.55;min-height:calc(2 * 1.55em)}
.price-status.is-ready{color:var(--ok)}
.price-status.is-test{color:var(--warn)}

.price-head{font-size:12.5px;font-weight:600;color:var(--fg);
  margin:18px 0 10px;padding-top:16px;border-top:1px solid var(--line)}
.price-list{list-style:none;margin:0;padding:0;font-size:12.5px;line-height:1.85;color:var(--mut)}
.price-list li{display:flex;gap:8px}
/* Der Haken ist ein Lucide-Symbol, kein U+2713: das Design-System schliesst
   Unicode-als-Symbol ausdruecklich aus, und eine Textglyphe laesst sich in
   Groesse und Hoehenlage nicht steuern. Dasselbe Bild fuehrt die Punkte der
   Bereichskarten. */
.price-list li svg{width:14px;height:14px;flex:none;margin-top:5px;stroke:var(--acc);fill:none;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.price-fine{font-size:11.5px;line-height:1.6;color:var(--mut);margin:16px 0 0}

@media (max-width:820px){
  .price-grid{grid-template-columns:minmax(0,1fr)}
  .price-for,.price-value{min-height:0}
}

/* ---------- Vertrauen ---------- */
.trust{padding:72px 0 8px}
.trust .gr{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:48px;align-items:center}
.trust h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(20px,2.4vw,28px);letter-spacing:-0.01em;margin:10px 0 14px;text-wrap:balance}
.trust p{color:var(--mut);max-width:46ch;margin:0}
.trust p b{color:var(--fg);font-weight:600}
.term{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-lg);padding:16px 18px;
  font-family:'JetBrains Mono',monospace;font-size:12px;line-height:1.9;overflow-x:auto}
.term .c{color:var(--mut)}.term .g{color:var(--ok)}.term .a{color:var(--acc)}

/* ---------- releases ---------- */
.rel{border-top:1px solid var(--line);padding:40px 0 48px;margin-top:40px}
.rel .rt{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:16px;flex-wrap:wrap;gap:8px}
.rel h2{font-family:'Space Grotesk',sans-serif;font-weight:500;font-size:12px;
  text-transform:uppercase;letter-spacing:0.14em;color:var(--mut);margin:0}
.reltab{background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg);overflow-x:auto}
.reltab table{width:100%;border-collapse:collapse;font-family:'JetBrains Mono',monospace;font-size:12px;min-width:520px}
.reltab th{padding:8px 16px;border-bottom:1px solid var(--line);text-align:left;
  font-family:'Space Grotesk',sans-serif;font-weight:500;font-size:10px;
  text-transform:uppercase;letter-spacing:0.12em;color:var(--mut)}
/* Die Downloadlinks sind das einzige Ziel der Seite, das seine Nachbarn
   senkrecht ueber sich hat: eine ueber die Zeilengrenze hinaus vergroesserte
   Trefferflaeche wuerde den falschen Download ausloesen. Hier traegt deshalb
   die Zeile selbst das Mass. */
.reltab td{padding:0 16px;height:44px;border-bottom:1px solid var(--line);white-space:nowrap}
.reltab td a{display:inline-block;padding:13px 0}
.reltab tr:last-child td{border-bottom:none}
/* Anklickbares traegt den Akzent, so wie im Katalog und in der Karriere-Zeile.
   Vorher standen die vier Downloadlinks in Textfarbe und die Endpunkt-Adresse
   darunter, die gar kein Link ist, in der Linkfarbe. */
.reltab a{color:var(--acc)}
.reltab a:hover{text-decoration:underline}
.reltab .dim{color:var(--mut)}
.note{font-family:'JetBrains Mono',monospace;font-size:11.5px;color:var(--mut);margin-top:12px}
.note b{color:var(--fg);font-weight:400}

/* ---------- Abschluss ---------- */
.fin{padding:16px 0 48px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:16px}
.fin h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(24px,3.2vw,36px);letter-spacing:-0.015em;max-width:18ch;margin:8px 0 0;text-wrap:balance}
.fin p{color:var(--mut);max-width:46ch;margin:0}
.fin .cta{justify-content:center;margin-top:4px}

/* ---------- Karriere ---------- */
.careers{padding:28px 0 72px;border-top:1px solid var(--line);display:flex;
  flex-direction:column;align-items:flex-start;gap:14px}
.careers h2{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(22px,2.8vw,32px);letter-spacing:-0.015em;margin:4px 0 0;text-wrap:balance}
.careers > p{color:var(--mut);max-width:58ch;margin:0;font-size:15px;line-height:1.55}
.career-roles{list-style:none;margin:6px 0 0;padding:0;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;width:100%}
.career-roles li{background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:16px 16px 14px;display:flex;flex-direction:column;gap:6px}
.career-role{font-family:'Space Grotesk',sans-serif;font-weight:700;font-size:15px;color:var(--fg)}
.career-desc{font-size:13.5px;line-height:1.5;color:var(--mut)}
.career-contact{font-family:'JetBrains Mono',monospace;font-size:12.5px;color:var(--mut);margin:4px 0 0}
.career-contact a{position:relative;color:var(--acc);font-weight:600}
.career-contact a::after{content:"";position:absolute;inset:-13px -4px}
.career-contact a:hover{text-decoration:underline}
@media (max-width:900px){
  .career-roles{grid-template-columns:1fr}
}

/* ---------- footer ---------- */
.foot{border-top:1px solid var(--line);padding:12px 0;display:flex;justify-content:space-between;
  align-items:center;font-size:12.5px;color:var(--mut);flex-wrap:wrap;gap:8px}
/* 15px hohe Links sind kein Ziel. Der Innenabstand hebt sie ohne Aenderung am
   Satzrhythmus auf 27px; das Aussenmass der Zeile bleibt durch das kuerzere
   Aussenpolster gleich. */
.foot a{position:relative;display:inline-block;padding:6px 0}
.foot a::after{content:"";position:absolute;inset:-7px -3px}
.foot a:hover{color:var(--fg)}

/* ---------- legal pages ---------- */
.legal-wrap{max-width:720px;margin:0 auto;padding:40px 28px 72px}
/* Die einzige feste Ueberschriftgroesse des Stylesheets: "Datenschutzerklaerung"
   misst bei 28px rund 303px und lief bei 320px Viewport aus dem Bild. */
.legal-wrap h1{font-family:'Space Grotesk',sans-serif;font-weight:700;
  font-size:clamp(22px,6vw,28px);margin:24px 0 16px}
.legal-wrap h2{font-family:'Space Grotesk',sans-serif;font-weight:500;font-size:17px;margin:28px 0 8px}
/* Der einzige Textcontainer der Seite ohne Begrenzung des Satzspiegels: 664px
   bei 14,5px sind gemessen 94,8 Zeichen je Zeile, und hier steht der laengste
   Fliesstext der Website. Der Container behaelt seine 720px, damit
   Ueberschriften und Listenraster die Breite weiter nutzen.

   53ch und nicht 68ch: das ch von Instrument Sans ist die Breite der Null und
   misst 0,67em, das durchschnittliche Zeichen dieser Texte aber nur 0,48em.
   68ch waeren 657px gewesen und haetten nichts geaendert. 53ch sind 512px und
   gemessen 74 Zeichen je Zeile. */
.legal-wrap p,.legal-wrap li{font-size:14.5px;color:var(--fg);max-width:53ch}
/* Der einzige Ort der Seite, an dem eine Browser-Vorgabe unveraendert
   durchschlug: disc-Punkte mit 40px Einzug, beides ausserhalb der Skala.
   Jetzt derselbe Akzentpunkt wie im Katalog. */
.legal-wrap ul{list-style:none;margin:10px 0;padding:0;display:flex;flex-direction:column;gap:6px}
.legal-wrap ul li{display:flex;align-items:baseline;gap:12px}
.legal-wrap ul li::before{content:"";width:5px;height:5px;flex:none;border-radius:var(--r-pill);
  background:var(--acc);transform:translateY(-2px)}
.legal-wrap p a,.legal-wrap li a{color:var(--acc)}
.legal-wrap p a:hover,.legal-wrap li a:hover{text-decoration:underline}
.legal-wrap .back{font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--mut)}
.legal-wrap .back:hover{color:var(--acc)}

/* Die Tabelle ist 520px breit und laeuft unterhalb von 558px Fensterbreite
   ueber ihren Container hinaus. Sichtbar war davon nichts: die Spalte endete
   hart an der gerundeten Kante mitten im Wort, ohne Auslauf und ohne
   Bildlaufleiste. Eine weiche Maske am rechten Rand zeigt, dass es weitergeht,
   und laeuft ueber die Bildlaufposition auf null, sobald durchgescrollt ist.
   Ohne Unterstuetzung fuer scroll()-Zeitachsen bleibt alles wie bisher: eine
   Maske, die am Ende stehen bliebe, wuerde das letzte Wort beschneiden.
   Die Grenze rechnet aus der AUSSENbreite: 520px Tabelle + 2 x 1px Rahmen
   + 2 x 18px Seitenrand = 558px. Die frueheren 555px liessen 2px offen
   (556 und 557px liefen ohne Maske ueber), weil sie den Rahmen vergassen -
   clientWidth ist um die beiden Rahmenpixel kleiner als die Aussenbreite. */
@property --reltab-fade{syntax:"<length>";inherits:false;initial-value:28px}
@keyframes reltab-fade{to{--reltab-fade:0px}}
@media (max-width:557px){
  @supports (animation-timeline: scroll(self inline)){
    .reltab{
      -webkit-mask-image:linear-gradient(to right,#000 calc(100% - var(--reltab-fade)),transparent);
      mask-image:linear-gradient(to right,#000 calc(100% - var(--reltab-fade)),transparent);
      animation-name:reltab-fade;
      animation-duration:auto;
      animation-timing-function:linear;
      animation-fill-mode:both;
      animation-timeline:scroll(self inline);
    }
  }
}

/* ---------- success page ---------- */
/* Zustaende der Schluessel-Abholung. Alle drei stehen im HTML und werden per
   hidden umgeschaltet, damit ohne JavaScript wenigstens ein sinnvoller
   Hinweis stehen bleibt. */
.claim-state{font-size:14.5px}
.claim-state.err{color:var(--err)}
.claim-hint{font-size:13px;color:var(--mut);margin-top:14px}
.keybox{background:var(--raise);border:1px solid var(--line);border-radius:var(--r-lg);padding:14px;margin:18px 0}
.keybox .row{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}
.keybox code{
  font-family:'JetBrains Mono',ui-monospace,monospace;font-size:12.5px;line-height:1.5;
  color:var(--fg);word-break:break-all;display:block;
}
.copy-btn{
  border:1px solid var(--line);border-radius:var(--r-md);background:none;color:var(--fg);
  font-family:'Instrument Sans',system-ui,sans-serif;font-size:12.5px;padding:8px 12px;
  min-height:36px;cursor:pointer;flex-shrink:0;
}
.copy-btn{position:relative}
.copy-btn::after{content:"";position:absolute;inset:-4px 0}
.copy-btn:hover{border-color:var(--mut)}
.steps{margin:16px 0 0;padding-left:20px}
.steps li{margin:4px 0}

/* Displayueberschriften teilen eine Durchschuss-Regel. Ohne sie erben sieben
   von elf den Wert des Fliesstextes (1,55): eine 36px-Zeile stand dann mit
   55,8px Zeilenabstand und las sich als zwei Ueberschriften statt als eine. */
.chapter h2,.libbeat h2,.rcbeat h2,
.fhead h2,.promise h2,.pricing h2,.fin h2,.careers h2,.trust h2{line-height:1.15}
.hero h1{line-height:1.05}

/* ---------- responsive ---------- */
/* Die Inszenierung lebt vom mitlaufenden Fenster. Sobald das Raster einspaltig
   wird, gibt es keine zweite Spalte mehr, in der das Fenster stehenbleiben
   koennte: es liefe entweder durch den Kapiteltext hindurch (das war D-002)
   oder es stuende einmal ganz oben und waere ab dem zweiten Kapitel aus dem
   Bild (das war D-202, von elf Substeps kein einziger vollstaendig sichtbar).
   Dazwischen gibt es nichts. Deshalb faellt der Umbruch der Spalten mit dem
   Verschwinden des Fensters zusammen: oberhalb von 1180px zweispaltig und
   klebend, darunter traegt die Copy den Abschnitt allein.

   Die Grenze steht bei 1300px, nicht bei 1180px: gemessen misst die kleinste
   Schrift im groessten Fenster bei 1181px 5,68px und im mittleren 5,47px, bei
   1300px dagegen 6,40 und 6,16px, und das dritte Fenster laeuft dort erstmals
   unskaliert (--s = 1). Das war der Rest von D-004, den der Fix zu D-202 nur
   nach oben verschoben hatte. Weiter hinauf geht die Grenze nicht: --s
   erreicht seinen Deckel erst bei 1420px, und eine Grenze dort haette allen
   1366er-Laptops das Fenster genommen. */
@media (max-width:1180px){
  .fpillars{grid-template-columns:repeat(2,minmax(0,1fr))}
}
/* Die Grenze steht wieder bei 1180px. Sie war in einer frueheren Runde auf
   1300px angehoben worden, um das Band 1181-1300px mit seinen 5,5 bis 6,4px
   kleiner Mock-Schrift loszuwerden. Der Preis war zu hoch und wurde damals
   nicht benannt: auf 1280px, einer verbreiteten Laptop-Breite, zeigte die
   Seite ueber den gesamten Scrollweg KEIN Produktfenster mehr, und die
   kleinste Schrift war am neuen unteren Rand mit 6,41px praktisch dieselbe
   wie vorher. Die Groesse ist jetzt an ihrer Ursache behoben (Mindestgroesse
   im Mock, siehe --fmin weiter oben), nicht ueber die Grenze.
   Was bleibt: zwischen 1181 und 1420px steht die Copy-Spalte der Inszenierung
   nicht auf der Kante des Hero, sondern bis zu 190px weiter links, und der
   Abstand waechst mit der Fensterbreite, solange .in-wide seine Hoechstbreite
   noch nicht erreicht hat. Das ist der Preis fuer ein Fenster in diesem Band
   und laesst sich nicht wegrechnen: ein Container, der frueher deckelt als
   ein zweiter, hat zwangslaeufig einen mitwachsenden Versatz. */
@media (max-width:1180px){
  /* Ohne Fenster tragen die Story-Abschnitte nur noch Copy. Ihre breiteren
     Container haetten die Copy-Spalte an eine zweite linke Kante gehaengt
     (bei 1180px 70px links der uebrigen Abschnitte), deshalb messen sie hier
     wie .in. */
  .in-wide,.in-bleed{max-width:1040px}
  .story,.libbeats,.beats{grid-template-columns:minmax(0,1fr);gap:0}
  .stage,.libstick,.rcstick{display:none}
  .chapter,.libbeat,.rcbeat{min-height:0;justify-content:flex-start;padding:20px 0}
  /* Ohne Fenster ist die Spalte eine reine Lesespalte: rund 70 Zeichen je
     Zeile. Vorher stand der Text in einem 800px-Band, dessen rechte Haelfte
     ueber alle elf Kapitel leer blieb, weil der Absatz auf 40ch begrenzt war. */
  /* margin-right:auto statt margin:0 auto: zentriert war die Kapitelspalte die
     einzige zentrierte Inhaltsspalte der Seite und stand bei 1180px 222px
     rechts von Hero, Preisen und Fusszeile. */
  .chapters,.libbeatcol,.beatcol{padding-bottom:0;max-width:540px;margin:0 auto 0 0;width:100%}
  .chapter p,.libbeat p,.rcbeat p{max-width:none}
  /* Die monospaced Marken benennen Bedienelemente des Fensters. Ohne das
     Fenster zeigen sie ins Leere. */
  .chapter .ui-ref,.libbeat .ui-ref,.rcbeat .ui-ref{display:none}
  .story[data-ready] .chapter,
  .libbeats[data-ready] .libbeat,
  .beats[data-ready] .rcbeat{opacity:1}
}
@media (max-width:900px){
  .trust .gr{grid-template-columns:1fr}
  /* Nav-Links bleiben als zweite Zeile erreichbar (kein Hamburger, kein JS).
     Zweizeilig ist die Leiste 141px hoch, also ein Sechstel eines
     Telefonbildschirms. Sie klebt deshalb nur oberhalb dieses Umbruchs. */
  .nav-shell{position:static}
  /* 14px statt 8px Zeilenabstand: die Trefferflaechen der Kopfzeile sind je
     44px hoch und ragen ueber ihre sichtbaren Kaesten hinaus; bei 8px lagen
     die der Marke und der Navigationslinks uebereinander. */
  .nav{flex-wrap:wrap;row-gap:14px;padding:12px 0 10px}
  .nav .links{
    display:flex;order:3;width:100%;margin:0;padding:0 0 2px;
    gap:2px;overflow-x:auto;-webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .nav .links::-webkit-scrollbar{display:none}
  .nav .links a{padding:6px 10px;white-space:nowrap;font-size:13px}
  .fpillars,.fcards{grid-template-columns:1fr}
  /* .legal-wrap fehlte in dieser Liste und behielt als einziger Container den
     Desktop-Seitenrand von 28px. */
  .in,.in-wide,.in-bleed,.legal-wrap{padding-left:18px;padding-right:18px}
}

/* Die rechte Gruppe der Startseiten misst 237px; neben der 104px breiten Marke
   und dem 26px-Abstand braucht sie samt Seitenrand 403px. Darunter nimmt sie
   eine eigene Zeile, auf den Rechtsseiten mit ihrem einzelnen Knopf aber nicht:
   die Leiste war dort eine Zeile niedriger, und der Sprung von der Startseite
   ins Impressum liess sie um 39,3px springen. Unterhalb von 420px nimmt die
   Gruppe deshalb ueberall eine eigene Zeile; ab 420px passt sie ueberall
   daneben. Die Zeilenzahl haengt damit nicht mehr davon ab, wie viele
   Bedienelemente eine Seite traegt. */
@media (max-width:419px){
  .nav .right{order:2;width:100%;margin-left:0;justify-content:flex-end}
}

/* Bei 320px war die Linkzeile 12px (EN) bis 24px (DE) breiter als ihr
   Scroll-Container, dessen Bildlaufleiste ausgeblendet ist: "Releases" endete
   als "Releas", ohne dass etwas darauf hinwies. Enger gesetzt passt sie. */
@media (max-width:380px){
  .nav .links{gap:0}
  .nav .links a{padding:6px 7px}
}
/* Unterhalb von 360px passt "Produktionsdisziplin" bei der Untergrenze des
   clamp (32px, Wortbreite 305px) nicht mehr in die 269px breite Textspalte.
   Eine Stufe kleiner passt es; die Trennung darueber bleibt das Netz. */
@media (max-width:359px){
  .hero h1{font-size:27px}
}

/* Ohne Bewegung: keine Uebergaenge, aber dieselbe Zuordnung.
   Die Umschaltung ueber data-active ist keine Animation, sondern die
   Verbindung zwischen einem Kapitel und dem Bild, das es beschreibt. Sie
   bleibt deshalb bestehen und nur die Wege dorthin fallen weg.

   Vorher stand hier eine Ausnahmeliste, die alle Zustaende gleichzeitig
   erzwang. Sie behandelte drei gleichartige Ueberlagerungen auf drei Arten:
   die Benachrichtigungsliste war immer sichtbar (auch in Kapiteln, die von
   etwas anderem handeln), Kontextmenue und Leerzustand waren immer
   unsichtbar (auch in genau dem Kapitel, das sie beschreibt), und der Katalog
   im Bibliotheksfenster stand mit allen Abschnitten zugleich offen. Kein
   Kapitel stimmte mit seinem Bild ueberein.

   animation-delay wird mitgenullt: sonst erscheint ein per Keyframe
   eingeblendetes Element zwar sofort, aber erst nach seiner urspruenglichen
   Wartezeit. */
@media (prefers-reduced-motion: reduce){
  *{animation-duration:0.01ms !important;animation-delay:0s !important;
    animation-iteration-count:1 !important;
    transition-duration:0.01ms !important;transition-delay:0s !important}
  html{scroll-behavior:auto}
  .story[data-ready] .chapter,.libbeats[data-ready] .libbeat,.beats[data-ready] .rcbeat{opacity:1 !important}
}
