/* @tillit-feld: css-ende */
/* @tillit-reihenfolge: 50 */

/* ========================================
   TILLIT SYSTEM (L4) — geteilte Komponenten

   Stand: im Backend noch NICHT uebertragen.
   Ziel-Feld: "CSS - Ende" (nach tillit-shop-dom.css
   und tillit-header.css).

   AUFNAHMEKRITERIUM: mindestens zwei Verwender oder
   Shop-DOM-Zwang. Was genau eine Seite braucht,
   bleibt in deren <style>. Benannte Ausnahme seit
   2026-09-02: .tb-hero__meta (ein Verwender, s. dort).

   HERKUNFT: Kanonisierung 2026-08-23. Alle Bloecke
   hier standen bis dahin ZWEIMAL — in
   pages/startseite/index.html und
   pages/beratung/index.html — und
   waren kommentarfrei verglichen deklarationsgleich:
   Reveal-Register 24/24, Bildbuehne 7/7, Button
   17/17, Sektions-Huelle 12/16. Die vier
   Abweichungen der Huelle sind unten benannt.

   WARUM "CSS - Ende": das Feld steht nach allen
   Werks-Media-Queries. Eine schlichte Regel schlaegt
   hier ein @media(min-width) des Werks ohne
   !important. Preis: sie schlaegt auch UNSERE eigenen
   Media Queries — deshalb stehen max-width-Bloecke in
   diesem Feld immer hinter allen min-width-Bloecken.
   ======================================== */


/* ======== SCROLL-REVEAL: VIER REGISTER ========
   Ein Attribut, vier Werte. Text, Bild, Aussage und Buehne haben
   verschiedene Aufgaben und bekommen deshalb verschiedene Auftritte -
   vorher lief ein einziges Rezept (Blur 10px + 3D-Kipp, ~1s) auf
   Headline, Fliesstext, Bildflaeche und FAQ-Zeile gleichermassen.

     (ohne Wert) copy    Opacity + --tb-move-near, KEIN Blur. Der
                         Standard.
     display             + --tb-move-far + Blur --tb-blur-deep. Max. 1
                         pro Sektion, nur auf reiner
                         Auszeichnungs-/Titeltypo.
     media               Clip-Wipe von unten. Kein Filter, kein
                         Transform - siehe unten.
     still               Reine Blende, kein Versatz. Zitate,
                         Markenversprechen.

   Hier stehen absichtlich die Token und nicht ihre Pixelwerte: die
   Regeln unten lesen dieselben Namen, die Zahlen selbst gehoeren
   nach tillit-tokens.css - so kann diese Liste nicht wieder altern.

   perspective/rotateX/translateZ sind ersatzlos gestrichen: bei
   4 Grad und -50px unter der Wahrnehmungsschwelle, aber Ursache
   einer Bugklasse - getBoundingClientRect lieferte waehrend der
   Blende die PROJIZIERTE Box, woran die Verbindungslinien der
   Individualisierung schief sassen. clip-path hat dieses Problem
   nicht: es veraendert weder Layoutbox noch Messung.

   Gate ist .tb-motion - ohne JS, ohne IntersectionObserver oder bei
   reduzierter Bewegung existiert der versteckte Startzustand gar
   nicht erst. In e-vendo darf nichts dauerhaft unsichtbar bleiben,
   nur weil ein Observer nicht feuert.

   --sh-reveal-extra entfaellt: nach dem Auftritt tauscht das Skript
   data-reveal gegen data-revealed, danach matcht keine dieser Regeln
   mehr und die Komponente bekommt ihre eigenen Zustands-Uebergaenge
   zurueck. */
.tb-page.tb-motion [data-reveal]{
  --sh-reveal-delay:calc(min(var(--sh-i,0),var(--tb-stag-cap)) * var(--tb-stag-step));
  opacity:0;transform:translate3d(0,var(--tb-move-near),0);
  transition:opacity var(--tb-dur-enter) var(--tb-ease-entry) var(--sh-reveal-delay),
             transform var(--tb-dur-enter) var(--tb-ease-entry) var(--sh-reveal-delay);
}
.tb-page.tb-motion [data-reveal="display"]{
  filter:blur(var(--tb-blur-deep));transform:translate3d(0,var(--tb-move-far),0);
  transition:opacity var(--tb-dur-stage) var(--tb-ease-entry) var(--sh-reveal-delay),
             filter var(--tb-dur-stage) var(--tb-ease-entry) var(--sh-reveal-delay),
             transform var(--tb-dur-stage) var(--tb-ease-entry) var(--sh-reveal-delay);
}
.tb-page.tb-motion [data-reveal="still"]{
  transform:none;
  transition:opacity var(--tb-dur-stage) var(--tb-ease-entry) var(--sh-reveal-delay);
}
.tb-page.tb-motion [data-reveal="media"]{
  transform:none;clip-path:inset(0 0 22% 0);
  transition:opacity var(--tb-dur-click) var(--tb-ease-entry) var(--sh-reveal-delay),
             clip-path var(--tb-dur-stage) var(--tb-ease-entry) var(--sh-reveal-delay);
}
/* Aufloesung bewusst in drei Regeln: so behaelt kein Element dauerhaft
   filter oder clip-path. Jeder Filterwert ausser none erzeugt sonst
   einen Stacking Context UND einen Containing Block fuer absolut oder
   fix positionierte Nachfahren - auch lange nach der Blende. */
.tb-page.tb-motion [data-reveal].is-in{opacity:1;transform:none}
.tb-page.tb-motion [data-reveal="display"].is-in{filter:none}
.tb-page.tb-motion [data-reveal="media"].is-in{clip-path:inset(0 0 0 0)}

/* DRUCK. Der Observer misst gegen das Fenster, nie gegen die
   Druckseite - im Druck feuert er nicht, und jedes [data-reveal],
   das beim Strg+P noch nicht im Fenster war, belegt Layout ohne
   sichtbaren Inhalt. Die Regel gehoert hierher zum Register, nicht
   in die Seiten: der Beratungsprozess traegt 23 Auszeichnungen und
   druckte bis zum 2026-08-24 leer, weil die Reparatur nur im
   Startseiten-<style> stand.
   'transition:none' ist kein Zierat: ohne sie beginnt die Blende
   beim Wechsel auf Druckmedien erst zu LAUFEN, und der Browser
   friert die Seite mitten darin ein - gemessen opacity .83 statt 1. */
@media print{
  .tb-page.tb-motion [data-reveal]{opacity:1 !important;transform:none !important;filter:none !important;clip-path:none !important;transition:none !important}
}


/* ==== TILLIT BILDBUEHNE v1.0 - Zustandsschicht fuer Experience-Bilder ====
   Die dritte Wiederholungs-Klasse aus Abschnitt 0 des Motion-Systems:
   scrollgebunden, bidirektional, ohne Erinnerung. Reveal ist der
   Auftritt, das hier ist die Tiefe.

   GEOMETRIE. Das Bild ist HOEHER als sein Fenster und wandert nur - es
   wird nicht skaliert. Bei Amplitude a ist es 2a hoeher und um a nach
   oben versetzt, gewandert wird um +-a. Damit ist die Deckung eine
   Identitaet: an keiner Position kann eine Luecke an der Kante
   entstehen, unabhaengig von Viewport, Bildformat und Fensterhoehe.
   Der Vorgaenger loeste dasselbe ueber scale(1.12) per Inline-Style -
   das resampelt eine bereits gerasterte Ebene, blaeht die zu
   kompositierende Textur auf das 1,25-fache auf (die horizontale
   Haelfte davon funktionslos) und stand ohne JS gar nicht.

   WARUM vh UND NICHT PROZENT. Alle drei Werte (top, height, translate)
   loesen dieselbe absolute Laenge auf. Ein Prozentwert im translate
   bezoege sich auf die BILDBOX (100% + 2a), top und height aber auf die
   Buehne - drei Bezugsgroessen in einer Formel. Erwuenschte Nebenwirkung:
   der Faktor faellt automatisch auf grossen Buehnen, wo das bewegte
   Bild den groessten Teil des Blickfelds einnimmt.

   DIE ZAHL. 6vh, am Prueftstand entschieden (Canvas "Bildbuehnen im
   Scroll", 2026-08-21): auf der 84vh-Buehne wandert das Bild damit um
   6,5 % des Scrollwegs. Der Ist-Zustand lag gemessen bei 3,9 % und
   damit knapp ueber der Wahrnehmungsschwelle. Nach oben begrenzt: ab
   10 % verschiebt sich das Bild je 100 px Scroll um mehr als eine
   Drittel-Zeilenhoehe gegen den stehenden Text - der Punkt, an dem
   Parallax billig aussieht und den WCAG 2.3.3 meint. Mobil eine Stufe
   leiser, weil Touch-Flicks ein Vielfaches der Mausrad-Spitze erreichen
   und der Faktor die Scrollgeschwindigkeit multipliziert.

   translate STATT transform ist der zweite Kerngewinn: die Tiefe belegt
   eine eigene Eigenschaft und kollidiert deshalb nicht mit scale
   (Ken-Burns, Hover) oder clip-path (Medien-Wipe). Der Hack, dass die
   Hero-Keyframes --sh-par mittragen mussten, entfaellt ersatzlos.

   SPEZIFITAET 0,3,0 mit Absicht: die Seitenregeln der einzelnen Buehnen
   (.tb-page .sh-trust__media) liegen bei 0,2,0 und bleiben als
   Strip-Fallback stehen. Kommt dieser Block im Shop nicht an, rendert
   die Seite exakt wie vorher, statt ein 2400px breites Bild zu zeigen.

   KEIN JS NOETIG fuer die Geometrie: --tb-stage-amp loest in CSS auf.
   Ohne Skript steht das Bild in der MITTE seines Wanderwegs - nie eine
   Luecke, nie ein Bild, das an seiner letzten Scrollposition klebt.
   Das Skript schreibt ausschliesslich --sh-stage-y.

   --sh-stage-pull (optional, immer positiv) zieht den Bildausschnitt
   nach oben, ohne das Budget zu verletzen: die Box waechst um 2p und
   ihr Deckel wandert um 2p hoch, die Mitte also um p. Ober- und
   Unterkante behalten dabei ihre volle Reserve von je einer Amplitude.
   Sie ersetzt --sh-media-shift, das denselben Versatz im transform
   trug und sich dort mit dem Wanderweg addiert haette - bei -6 % auf
   der Rennrad-Haelfte waere die Unterkante aufgerissen.

   Der Auftritt ist NICHT hier: Buehnen im Seitenfluss tragen dafuer
   data-reveal="media" (Clip-Wipe, Abschnitt 2), Heroes den Ausklang
   unten. Eine Buehne, kein zweites Vokabular. */
/* --tb-stage-amp (6vh, mobil 4vh) steht seit der Kanonisierung in
   tillit-tokens.css auf :root — hier stand es doppelt. */
.tb-stage{position:relative;overflow:hidden}
.tb-page .tb-stage .tb-stage__media{position:absolute;left:0;width:100%;top:calc(-1 * var(--tb-stage-amp) - 2 * var(--sh-stage-pull,0px));height:calc(100% + 2 * var(--tb-stage-amp) + 2 * var(--sh-stage-pull,0px));object-fit:cover;translate:0 var(--sh-stage-y,0px)}
.tb-stage.is-scroll-active .tb-stage__media{will-change:translate}
/* Auftritt Heroes: Ken-Burns-Ausklang als ANIMATION ohne fill (Motion-
   System, "Lade-Intros sind Animationen, keine Transitions"). Danach
   faellt das Bild auf die Ruhelage der Regel zurueck, damit Parallax
   und Hover-Zoom leben. Weil die Geste in scale liegt und die Tiefe in
   translate, muessen die Keyframes den Parallax nicht mittragen. */
@keyframes tbStageSettle{from{scale:1.055}to{scale:1}}
/* AB DEM ERSTEN BILD (Go-live 01.10.2026), ohne Gate und ohne .is-ready.
   Bis dahin startete der Ausklang mit dem Seitenskript nach
   DOMContentLoaded, und das lag im Shop hinter dem ersten Bild: das Foto
   stand auf 1, sprang auf 1,055 und settelte dann. Jetzt laeuft er los,
   sobald die Buehne gestylt ist - wie das Lade-Intro der Zeilen. */
@media (prefers-reduced-motion:no-preference){
  .tb-page .tb-stage--hero .tb-stage__media{animation:tbStageSettle var(--tb-dur-drift) var(--tb-ease-entry)}
}

/* ======== REGISTER HALT (.tb-hero--pin, 2026-09-20) ========
   Der Hero bleibt stehen, die erste Folgesektion nimmt ihn. Haltestrecke
   = Herohoehe = 1,00 Viewport, Zusatzhoehe NULL: Dokumentlaenge, Anker,
   LCP-Element und jede abgenommene Messung bleiben unveraendert.
   Herleitung und Messwerte in tillit-tokens.css beim Token-Block.
   AUSNAHME FLACHE FENSTER (23.09.2026, H01): ist der Hero hoeher als das
   Fenster (Telefon quer, Zoom, 200 % Schrift), scrollt er zuerst um die
   Ueberhoehe mit und haelt dann ein Fenster lang; auch dort ohne
   Zusatzhoehe. Die Strecke misst der Kernel (initHeroHold).

   KEIN overflow-Problem: .tb-hero traegt selbst overflow:hidden (:240),
   fuer sticky zaehlen nur VORFAHREN. Im Shop ist der eine Vorfahr
   #shop.oflow_hidden, und der muss auf overflow:clip stehen
   (tillit-shop-header-v2.css) - hidden waere ein Scrollcontainer.

   MALREIHENFOLGE: der Hero ist als sticky ein positioniertes Element und
   wuerde die Folgebloecke ueberdecken. Die zweite Zeile hebt sie darueber.
   Negatives z-index scheidet aus: im Shop traegt #shop > .tb-page eine
   weisse Flaeche (tillit-shop-dom.css), die den Hero dann verdeckte. */
.tb-page .tb-hero--pin ~ *{position:relative;z-index:1}

/* KEIN ANIMIERTER FORTSCHRITT MEHR (24.09.2026, Befund H08). Bis dahin
   animierte der Halt eine vererbte Zahl (--tb-hold-p, @property mit
   inherits:true) am Hero, und Bild, Zeilen, Blende und Schleier rechneten
   daraus per calc(). Eine animierte Custom Property kann nicht auf den
   Compositor: in jedem Scroll-Frame wurde der ganze Hero-Teilbaum neu
   gestylt (43-75 Elemente bis in die Buchstaben des CTA, 3-7 ms je Frame
   bei 4x CPU, Chromium und WebKit), und das Bild ohne eigene Ebene
   rasterte die ganze Buehne neu. Jetzt fahren Bild und Zeilen eigene
   Scroll-Keyframes auf translate und transform; der Browser gibt sie an
   den Compositor, das Bild wird eigene Ebene. Die Ranges schreibt weiter
   der Kernel. (Die erste Fassung vom 20.09. hatte den Fortschritt schon
   von :root auf den Hero geholt - dort erbte ihn der ganze Shop.)
   HINGENOMMEN: ueber und in diesen Ebenen glaettet Chromium Text in
   Graustufen statt subpixelig, seitdem auch das CTA-Label (gemessen
   Chrome unter Windows, 1440x900, Road & Gravel: farbige Kantenpixel im
   Label 4,6 % -> 0 %). Zurueck nur
   ohne Bildebene, also ohne diesen Umbau; iOS und Android glaetten nie
   subpixelig, bei DPR 2 ist der Unterschied kaum sichtbar.
   OFFEN FUER MAX (zweite Pruefrunde): auch das Foto selbst rastert
   Chromium als eigene Ebene anders als im Seitengrund, meist weicher
   (Kantenenergie 0,71-0,88 der Basis, im Vergleich bei 1:1 sichtbar),
   vereinzelt kantiger (bis 1,30). Jede eigene Ebene des Bildes ist so -
   gemessen ohne Zoom, auf ganzen Pixeln, mit Grundfarbe, Radius, Filter,
   image-rendering, echter GPU und vor Beginn der Range. WebKit zeichnet
   das Bild wie vorher.
   Details im Motion-System (Nachtrag 24.09.).
   ANIMATIONSLISTEN WERDEN ERGAENZT, NIE ERSETZT. Das Bild traegt
   tbStageSettle, die Zeilen das Lade-Intro der Seite (tbHeroIn, fill
   both). Die Seite legt ihren Intro-Eintrag deshalb in --sh-hero-in ab
   (animation:var(--sh-hero-in)), und die Halteregel stellt ihn hinter
   den Scroll-Eintrag. Schreibt eine Seite ihr Intro direkt in animation,
   ersetzt die Halteregel ihre Liste - gemessen blieb dann der Vor-Intro-
   Zustand stehen (blur(10px), Zeilen unsichtbar). */

/* Die @supports-Klammer ist TRAGEND, nicht kosmetisch. Gemessen am
   20.09.2026: Firefox 153 kennt animation-timeline nicht, wirft die
   Zeile weg und laesst die Animation als Zeitanimation mit Dauer 0
   durchlaufen - der Endzustand stuende dann ab Scroll 0. Innerhalb der
   Klammer entsteht sie dort gar nicht erst. Ohne Timeline, ohne JS
   oder bei Reduced Motion bleibt der Hero im normalen Fluss; damit
   gibt es auch keine hinter Folgeflaechen gefangenen Links.
   DAS GATE IST .is-holding (24.09.2026, Befund H29), nicht mehr das
   Reveal-Gate .tb-page.tb-motion. Die Klasse setzt allein der Kernel
   (initHeroHold) nach der ersten Messung und nimmt sie in stop() wieder
   weg. Vorher nahmen sechs Seiten beim Wechsel auf Reduced Motion
   .tb-motion weg und setzten es mit Absicht nicht wieder (die Reveals
   sollen nicht noch einmal einblenden) - der Halt kam dann bis zum
   Neuladen nicht zurueck. Jetzt schaltet allein diese @media-Klammer,
   live in beide Richtungen. Seit dem Intro ab dem ersten Bild
   (01.10.2026) spielt das Ausschalten von Reduced Motion das Lade-Intro
   und den Bildausklang einmal neu - bewusst hingenommen, Herleitung in
   docs/strategy/tillit-motion-system.md (Lade-Intro, Grenzen). */
@supports (animation-timeline:scroll()){
  @media (prefers-reduced-motion:no-preference){
    @keyframes tbHeroGone{0%,99%{visibility:visible}100%{visibility:hidden}}
    /* Riegel des Abgangs: haelt nur den Endwert, und erst nach seiner
       Verzoegerung (fill forwards, keine Rueckwaertsfuellung). */
    @keyframes tbHoldAus{to{visibility:hidden}}
    /* DIE NAHT STEHT IN RUHE NICHT (23.09.2026, Befund H06). In voller
       Hoehe bei p=0 lag ihr Verlauf schon ueber dem Herofuss: gemessen
       bei Scroll 0 Faktenzeile Road & Gravel 1,6:1 (iPad hoch, 1440x900)
       statt 18,7:1, Beratung und MTB sichtbar vergraut. Vor dem Halt lag
       dort nur der 12-%-Auslauf des Scrims (--into-ink), und den hat Max
       am 05.09. abgenommen. Die Naht WAECHST deshalb auf den ersten 12 %
       ihrer Strecke (rund 56 px bei 844, 59 px bei 900) aus null auf
       ihren alten Pfad (.88) und schrumpft von dort linear wie bisher.
       Deckkraft bleibt 1: ihr Fuss ist #0f0f0f und schliesst die Kante
       vom ersten Pixel an. NICHT ueber opacity einblenden (erste
       Fassung): an der steigenden Kante deckt der Auslauf nur 60-70 %,
       das Foto endete an einer harten Stufe (tillit 1440 im Mittel 8,
       p95 11 Stufen; Atherton, Amflow 4-5). Wachsend bleibt die Kante
       auf dem Vorher-Wert (hoechstens 1 Stufe, Chromium und WebKit).
       Feste Prozente, weil Keyframes keine Variable nehmen. NICHT ueber
       eine Range ab --sh-hero-foot-end: der Kernel schreibt den Wert
       inline an den Hero, das ::before des Geschwisters erbt ihn nicht.
       NUR die Themen-Naht: die Werksnaht (tillit-shop-dom.css) hat keinen
       Fuss und behaelt eigene Keyframes, volle Hoehe ab p=0. */
    @keyframes tbSeamToEdge{0%{scale:1 0}12%{scale:1 .88}100%{scale:1 0}}

    /* AM SCROLL: Bild (Hub und Zoom) und die drei Zeilentempi. var() in
       Keyframes loest gegen das animierte Element auf (Chromium und
       WebKit, am 23.09. auf 1/40000 px gleich der alten Rechnung).
       START BEI 1.004, NICHT 1 (24.09.2026): als eigene Compositor-Ebene
       zeichnet Chromium die Bildkante mit Kantenglaettung, sobald der Hub
       auf einem gebrochenen Geraetepixel steht (3vh = 25,32 px) - bei
       Scroll 0 stand rechts eine dunkle Haarlinie von 1-2 Geraetepixeln
       (12 von 14 Seiten, alle Geraete; Helligkeit der letzten Spalte 0,63
       statt 1,0). 0,4 % Zoom schiebt die Kante aus dem Fenster (1,00 auf
       SE, iPhone 14 und 1440). NICHT ueber einen Ueberstand der Box
       (left/right -1 bis -2 px): gemessen dann eine noch dunklere Spalte
       (0,09-0,19). Das Ziel des Zooms bleibt --tb-hero-push. */
    @keyframes tbHoldMedia{from{translate:0 var(--tb-hero-von);transform:scale(1.004)}to{translate:0 var(--tb-hero-nach);transform:scale(var(--tb-hero-push))}}
    @keyframes tbHoldEyebrow{to{translate:0 calc(-1 * var(--tb-rise-eyebrow) * var(--sh-hold-weg))}}
    @keyframes tbHoldTitle{to{translate:0 calc(-1 * var(--tb-rise-title) * var(--sh-hold-weg))}}
    @keyframes tbHoldLead{to{translate:0 calc(-1 * var(--tb-rise-lead) * var(--sh-hold-weg))}}

    /* scroll(root block), nicht nearest: nearest haengt an einem
       unerwarteten overflow-Vorfahren und stuende dort still. Start und
       Laenge schreibt der Kernel gemessen (initHeroHold); ohne Messung
       traegt der Kanonwert, der auf allen zwoelf Seiten bis auf die
       Beratung (936 statt 900) genau stimmt. Beide stehen als statische
       Werte am Hero (--sh-hold-weg, --sh-hold-range) und aendern sich
       nur beim Messen, nie beim Scrollen.
       top ist der negative Haftversatz aus dem Kernel (--sh-hero-ueber,
       23.09.2026, Befund H01): passt der Kopf nicht in die erste
       Fensterhoehe, scrollt die Buehne mit, bis ihre Unterkante unten
       ankommt, und haelt erst dort. Sonst 0 wie bisher. */
    .tb-page .tb-hero--pin.is-holding{
      position:sticky;top:calc(-1 * var(--sh-hero-ueber,0px));
      --sh-hold-weg:var(--tb-hero-hold,calc(88vh + var(--sh-hero-over)));
      --sh-hold-range:var(--tb-hero-start,0px) calc(var(--tb-hero-start,0px) + var(--sh-hold-weg))
    }

    /* DAS BILD steigt und waechst. Reserve 10vh (mobil 7vh) statt der
       Buehnenamplitude, sonst gibt der Hub oben eine Kante frei.
       transform:scale statt der scale-Eigenschaft, weil auf demselben
       Element tbStageSettle laeuft und scale belegt - die beiden Kanaele
       multiplizieren sich sauber, und die Liste traegt beide Eintraege.
       AB DEM ERSTEN BILD IN HALT-LAGE (Befund Max 01.10.2026 an der
       Startseite, hier gemessen an Orbea bei 1440): .is-holding kommt mit
       dem Kernel (1235 ms), erst dann setzte tbHoldMedia seinen Startwert,
       und das Bild sprang mitten im Ausklang 36 px tiefer. Der Startwert
       (from) steht deshalb schon als Ruhelage hier; der Halt uebernimmt
       ab demselben Wert. Nur in dieser Klammer, ohne Timeline bleibt das
       Bild unverschoben. */
    .tb-page .tb-hero--pin .tb-stage__media{
      top:calc(-1 * var(--tb-hero-reserve));
      height:calc(100% + 2 * var(--tb-hero-reserve));
      translate:0 var(--tb-hero-von);
      transform:scale(1.004)
    }
    /* Der Ausklang steht seit 01.10.2026 immer vorn in der Liste: er laeuft
       ab dem ersten Bild (Regel bei tbStageSettle), und .is-holding kommt
       erst mit dem Kernel dazu - an Platz 0 bleibt er dabei dieselbe
       laufende Animation. */
    .tb-page .tb-hero--pin.is-holding .tb-stage__media{animation:tbStageSettle var(--tb-dur-drift) var(--tb-ease-entry),tbHoldMedia linear both;animation-timeline:auto,scroll(root block);animation-range:normal,var(--sh-hold-range)}

    /* DREI ZEILEN, DREI TEMPI, jede als eigener Scroll-Eintrag VOR dem
       Lade-Intro der Seite (--sh-hero-in, Kopfkommentar oben). Das Intro
       animiert transform, der Hub translate - beides komponiert.
       Das Intro fuellt hier nur RUECKWAERTS (backwards statt both): es
       haelt seinen Startzustand durch die gestaffelte Verzoegerung, aber
       nicht mehr den Endzustand. Den tragen die Seiten ohnehin als
       normale Deklaration (opacity:1;filter:none;transform:none an der
       Intro-Regel, seit 01.10.2026 ohne .is-ready), und nur so kann der Abgang unten Deckkraft und
       Unschaerfe per Transition fuehren - ein laufend fuellendes Intro
       schluege jede Deklaration und haette keinen Uebergang gestartet.
       --sh-leave-delay ist der Platz der Zeile in der Abgangsfolge. */
    .tb-page .tb-hero--pin.is-holding .tb-hero__content .tb-hero__inner > .tb-hero__eyebrow{animation:tbHoldEyebrow linear both,var(--sh-hero-in,none);--sh-leave-delay:0s}
    .tb-page .tb-hero--pin.is-holding .tb-hero__content .tb-hero__inner > .tb-hero__title{animation:tbHoldTitle linear both,var(--sh-hero-in,none);--sh-leave-delay:var(--tb-stag-beat)}
    .tb-page .tb-hero--pin.is-holding .tb-hero__content .tb-hero__inner > :is(.tb-hero__text,.tb-hero__actions){animation:tbHoldLead linear both,var(--sh-hero-in,none);--sh-leave-delay:calc(2 * var(--tb-stag-beat))}
    .tb-page .tb-hero--pin.is-holding .tb-hero__content .tb-hero__inner > :is(.tb-hero__eyebrow,.tb-hero__title,.tb-hero__text,.tb-hero__actions){animation-timeline:scroll(root block),auto;animation-range:var(--sh-hold-range),normal;animation-fill-mode:both,backwards}

    /* DIE RIEGEL AN DER DECKKANTE. Fuss und CTA-Link verlassen die
       Tastaturfolge, sobald die Folgeflaeche sie GANZ bedeckt (24.09.2026,
       Befund H13): der Kernel misst an ihrer Oberkante, nicht mehr an der
       Unterkante. Vorher sprangen sie beim ersten Beruehren in einem Frame
       weg (Ankerband der Flotte in 2 px Scrollweg, Atherton-CTA bei 90 %
       freier Flaeche). Jetzt passiert der Wechsel unsichtbar unter der
       deckenden Flaeche; WCAG 2.4.11 bleibt genau erfuellt, denn solange
       ein fokussierbares Element auch nur teilweise frei ist, bleibt es
       sichtbar. Im Alltag gehen beide schon vorher mit dem Abgang unten;
       die Riegel tragen den Fall, in dem der Tastaturfokus den Kopf
       haelt. Das Intro liegt auf den Kindern, die Sichtbarkeit auf dem
       Fuss bzw. dem Link selbst. */
    .tb-page .tb-hero--pin.is-holding .tb-hero__foot{
      --sh-hold-fuss:var(--tb-hero-start,0px) calc(var(--tb-hero-start,0px) + var(--sh-hero-foot-end,12vh));
      animation:tbHeroGone linear both;
      animation-timeline:scroll(root block);
      animation-range:var(--sh-hold-fuss)
    }
    .tb-page .tb-hero--pin.is-holding .tb-hero__actions > a{
      --sh-hold-lock:var(--tb-hero-start,0px) calc(var(--tb-hero-start,0px) + var(--sh-hero-actions-end,30vh));
      animation:tbHeroGone linear both;
      animation-timeline:scroll(root block);
      animation-range:var(--sh-hold-lock)
    }

    /* KEIN RIEGEL AM GANZEN KOPF (23.09.2026, Befund H11). Hier lag
       tbHeroGone auf .tb-hero__content, mit dem Ende bei --tb-hero-exit.
       visibility erbt sich, und fill:both haelt den Endzustand bis zum
       Seitenende: H1, Kappenzeile und Lead fielen ab 360 px Scroll
       (Desktop) bzw. 464 px (mobil) aus dem Accessibility-Baum, auf allen
       14 Seiten, in Chromium und WebKit - auch nach Ankersprung oder
       Reload. Die Werksseiten verloren jede Ueberschrift, weil #headline
       dort display:none steht. Gewollt war nur der Fokusteil.
       Unsichtbar werden muss nur, was fokussierbar ist (WCAG 2.4.11), und
       dafuer gibt es die Riegel oben (Fuss, CTA-Link) und den Riegel des
       Abgangs unten. Die Deckkraft 0 aus dem Abgang blendet den Rest nur
       visuell aus - H1 und Lead bleiben im Baum, gemessen pixelgleich an
       84 Messpunkten.
       KEIN Guertel .tb-hero__content :is(a,button,[tabindex]) mit einer
       Scroll-Range: er wiegt mehr als der CTA-Riegel, schlaegt ihn und
       macht den verdeckten CTA wieder fokussierbar (gemessen auf
       Atherton, Leasing, Beratung). Kommt je ein weiterer Link in den
       Kopf, bekommt er den Link-Riegel. Kein aria-hidden. */

    /* DER ABGANG IST EINE AUSGELOESTE ABFOLGE (24.09.2026, Entscheidung
       Max). Herleitung, Schwellen und Hysterese in tillit-tokens.css.
       Kurz: am Scroll haengen nur Bild, Zeilentempi, Naht und
       Folgeflaeche; der TEXT geht als Zeitfolge, sobald der Kernel
       .is-leaving an den Hero setzt, und kommt ebenso zurueck
       (.is-returning). Eingefrorene Zwischenstaende - halb durchsichtig,
       halb verwischt - gibt es damit nicht mehr, nur waehrend der Abfolge.
       .is-leaving IST DIE ZUSTANDSKLASSE DES ABGANGS: allein der Kernel
       setzt sie, und seit Paket 4 (23.09.2026) haengt der Kontrast-Hof
       (.tb-hero--hof) an genau dieser Klasse (Regeln unten beim
       Schleier). Keine zweite Schwelle bauen.
       Reihenfolge wie das Intro: Kappenzeile, Titel (+1 Takt), Lead, CTA
       und Fuss (+2 Takte), je --tb-hero-leave-dur auf der Scroll-Uhr
       (0,7 s, Satz 4), mit der Auftrittskurve: sie haelt kurz und zieht
       nicht nach vorn (die Zustandskurve der ersten Fassung stand nach
       100 ms schon auf halber Deckkraft und las sich schnappend). Deckkraft
       fuehrt; Unschaerfe nur auf der Display-Typo, erst in der zweiten
       Haelfte der eigenen Blende und gedeckelt (--tb-hero-leave-blur);
       Lead, CTA und Fuss nur ueber die Deckkraft.
       DER SCHLEIER ist die groesste Helligkeitsaenderung der Folge (bis
       +41 % Bildhelligkeit, Atherton und DEITY, Stand 24.09.; seit Paket 4
       kommt auf den Hof-Seiten der Hof dazu, Messung unten beim Hof). In 0,34 s mit der
       Zustandskurve wirkte er wie ein Lichtschalter (80 % in 150 ms, bis
       12 Stufen je 50 ms). Jetzt hebt er ab der Mitte der Textfolge ueber
       --tb-hero-leave-dur mit der symmetrischen --tb-hero-scrim-kurve
       (hoechstens 5 Stufen je 50 ms) und kommt beim Rueckweg zuerst, in
       --tb-dur-click plus einem Takt; der Text folgt dort einen Takt
       spaeter und kehrt auf dunklen Grund zurueck.
       Transitions, keine Keyframes: sie kehren aus jedem Zwischenstand
       weich um, wenn jemand waehrend der Abfolge zurueckscrollt. Den
       Uebergang nimmt der Browser aus dem Zielzustand, deshalb stehen
       Abgang, Rueckweg und Fokus in je eigenen Regeln - und NIE in Ruhe:
       sonst liefe schon das Vor-Intro (opacity 0 unter .tb-motion) als
       Transition und schluege das Lade-Intro.
       FOKUS: fokussiert die Tastatur einen Link im Kopf (:focus-visible),
       greift der Abgang nicht, und der Kopf kehrt zurueck (Befund H32,
       WCAG 2.4.7) - hier schnell, auf der Zustands-Uhr, ohne Staffel: der
       Fokus muss sofort sichtbar sein. Touch loest kein :focus-visible
       aus. Verlaesst der Fokus den Kopf (oder deckt der Riegel oben den
       Link zu), geht der Kopf wieder.
       filter endet in Ruhe und nach dem Rueckweg auf none, nie auf
       blur(0) (Befund H31): der Wert kommt aus der Seitenregel. */
    .tb-page .tb-hero--pin.is-holding.is-returning .tb-hero__content .tb-hero__inner > :is(.tb-hero__eyebrow,.tb-hero__title,.tb-hero__text,.tb-hero__actions){transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) calc(var(--sh-leave-delay) + var(--tb-stag-beat)),filter calc(var(--tb-hero-leave-dur) / 2) var(--tb-ease-state) calc(var(--sh-leave-delay) + var(--tb-stag-beat))}
    .tb-page .tb-hero--pin.is-holding.is-returning .tb-hero__foot{transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) calc(3 * var(--tb-stag-beat))}
    .tb-page .tb-hero--pin.is-holding.is-returning .tb-hero__scrim{transition:opacity calc(var(--tb-dur-click) + var(--tb-stag-beat)) var(--tb-hero-scrim-kurve)}
    .tb-page .tb-hero--pin.is-holding.is-returning .tb-hero__content{transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) var(--tb-stag-beat)}
    .tb-page .tb-hero--pin.is-holding.is-leaving .tb-hero__content .tb-hero__inner > :is(.tb-hero__eyebrow,.tb-hero__title,.tb-hero__text,.tb-hero__actions){transition:opacity var(--tb-dur-state) var(--tb-ease-state),filter var(--tb-dur-state) var(--tb-ease-state)}
    .tb-page .tb-hero--pin.is-holding.is-leaving :is(.tb-hero__content,.tb-hero__foot,.tb-hero__scrim){transition:opacity var(--tb-dur-state) var(--tb-ease-state)}
    /* Im Abgang ist das Lade-Intro abgelaufen (negative Verzoegerung,
       laenger als jedes Intro): wer gescrollt neu laedt, sieht den Kopf
       nicht erst einfliegen und dann gehen. Auch nach dem Rueckweg und bei
       Tastaturfokus bleibt es abgelaufen (25.09.2026, dritte Pruefrunde):
       sonst lief es weiter, wer binnen seiner Dauer zurueckkam - gescrollter
       Reload der Beratung, nach 1,6 s zurueck: Lead bei 0,95 mit Unschaerfe.
       AUSSER .is-hold-frueh (Herleitung im Kernel bei weg()): lief das
       Intro beim Abgang noch, startet Chromium auf den Zeilen keinen
       Uebergang, der Schnitt aus dem halben Intro stand hart im Bild (Titel
       0,5-1,0 in einem Bild). Dann laeuft das Intro weiter, und der ganze
       Kopf blendet in einem Zug mit Blende und Kurve des Abgangs, ohne
       Staffel und ohne Unschaerfe; zurueck einen Takt nach dem Schleier wie
       die Zeilen. Der Kopf traegt keine eigene Animation, auf ihm startet
       der Uebergang immer. Die Klasse gilt bis zum naechsten Abgang. */
    .tb-page .tb-hero--pin.is-holding:is(.is-leaving,.is-returning):not(.is-hold-frueh) .tb-hero__content .tb-hero__inner > :is(.tb-hero__eyebrow,.tb-hero__title,.tb-hero__text,.tb-hero__actions){animation-delay:0s,-99s}
    .tb-page .tb-hero--pin.is-holding.is-leaving.is-hold-frueh:not(:has(:focus-visible)) .tb-hero__content{opacity:0;transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry)}
    .tb-page .tb-hero--pin.is-holding.is-leaving:not(.is-hold-frueh):not(:has(:focus-visible)) .tb-hero__content .tb-hero__inner > :is(.tb-hero__eyebrow,.tb-hero__title,.tb-hero__text,.tb-hero__actions){opacity:0;transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) var(--sh-leave-delay)}
    /* Unschaerfe spaet: erst ab der Mitte der eigenen Blende, mit der
       Auftrittskurve (langsamer Beginn), bis zum Deckel. */
    .tb-page .tb-hero--pin.is-holding.is-leaving:not(.is-hold-frueh):not(:has(:focus-visible)) .tb-hero__content .tb-hero__inner > :is(.tb-hero__eyebrow,.tb-hero__title){filter:blur(var(--tb-hero-leave-blur));transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) var(--sh-leave-delay),filter calc(var(--tb-hero-leave-dur) / 2) var(--tb-ease-entry) calc(var(--sh-leave-delay) + var(--tb-hero-leave-dur) / 2)}
    .tb-page .tb-hero--pin.is-holding.is-leaving:not(:has(:focus-visible)) .tb-hero__foot{opacity:0;transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) calc(2 * var(--tb-stag-beat))}
    .tb-page .tb-hero--pin.is-holding.is-leaving:not(:has(:focus-visible)) .tb-hero__scrim{opacity:var(--tb-hero-scrim-ende);transition:opacity var(--tb-hero-leave-dur) var(--tb-hero-scrim-kurve) calc(var(--tb-hero-leave-dur) / 2 + var(--tb-stag-beat))}
    /* DER KONTRAST-HOF GEHT MIT DEM TEXT (23.09.2026, Paket 4, Befund
       H09; Hof selbst beim Kopfzeilenband unten). Nie am Scroll: ein halb
       ausgeblendeter dunkler Hof, eingefroren ueber dem Foto, waere
       derselbe Fehler, den Max am 24.09. fuer den Text gestrichen hat.
       Er geht mit Blende, Kurve und Verzoegerung der LETZTEN Zeile (Lead,
       +2 Takte) und kommt mit der ERSTEN zurueck (Kappenzeile, +1 Takt):
       seine Deckkraft ist so zu jedem Zeitpunkt die der sichtbarsten
       Zeile - kein Hof ohne Text, kein Text ohne Hof. Bei .is-hold-frueh
       und in der Sperre blendet der ganze Kopf und nimmt ihn mit, bei
       Tastaturfokus kehrt er mit dem Kopf auf der Zustands-Uhr zurueck.
       SEINE LAGE faehrt dagegen am Scroll mit, im Tempo der Kappenzeile
       (tbHoldEyebrow, schnellste Zeile): bis zur Abgangsschwelle steigen
       die Zeilen mobil bis rund 60 px, und ein stehender Hof liess die
       Kappenzeile oben herauslaufen - gemessen 6 px vor der Schwelle
       MTB-Hub 5,82 -> 2,90 (iPhone 14), Atherton 3,78, Schweiz 3,87, am
       Desktop MTB-Hub 3,98. Mit dem Tempo der Kappenzeile ab 4,94 (Galaxy S
       MTB-Hub), der langsamere Lead ab 5,13; im Titeltempo blieben 4,50.
       Bewegung am Scroll, Deckkraft als Abfolge - wie bei den Zeilen.
       --dicht braucht keine eigene Regel: es faerbt nur den Schleier, und
       der hebt oben mit.
       OFFEN FUER MAX (25.09.2026, gemessen per Screencast, Chromium,
       mittlerer sRGB-Wert, Stufen je 50 ms Abgang/Rueckweg, vorher ->
       nachher): der Hof ist eine grosse Helligkeitsaenderung auf der
       Textuhr und verfehlt auf den Hof-Seiten die Grenze von 5 Stufen, die
       der Schleier unten einhaelt. MTB-Hub 1440 Rand 3,7/4,4 -> 10,7/16,0,
       Mitte 2,1/2,5 -> 11,1/14,3; Atherton 1440 Mitte 4,2/5,8 -> 11,3/12,9,
       iPhone 14 3,1/4,0 -> 8,8/11,0; Flotte 1440 Mitte 0,9/1,1 -> 4,9/6,2.
       Die dicht-Seiten bleiben darunter (DEITY Mitte 3,5/4,2). Unter 5 ist
       es in der Textfolge nicht zu schaffen: der Hof hebt bis 88 Stufen,
       in 0,88 s ergibt jede weiche Kurve im Schnitt 5, an der Spitze 8.
       Gemessene Alternative: Blende ueber die ganze Textfolge (0,88 s ab
       der Kappenzeile) mit --tb-hero-scrim-kurve - Atherton Mitte 7,4,
       MTB-Hub Rand 8,2; dann steht der Hof mitten im Abgang ueber der
       Lead-Deckkraft (0,42 gegen 0,32). Umgesetzt ist die Vorgabe des
       Pakets (Blende der letzten Zeile). */
    .tb-page .tb-hero--hof.is-holding .tb-hero__content::before{animation:tbHoldEyebrow linear both;animation-timeline:scroll(root block);animation-range:var(--sh-hold-range)}
    .tb-page .tb-hero--hof.is-holding.is-returning .tb-hero__content::before{transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) var(--tb-stag-beat)}
    .tb-page .tb-hero--hof.is-holding.is-leaving .tb-hero__content::before{transition:opacity var(--tb-dur-state) var(--tb-ease-state)}
    .tb-page .tb-hero--hof.is-holding.is-leaving:not(.is-hold-frueh):not(:has(:focus-visible)) .tb-hero__content::before{opacity:0;transition:opacity var(--tb-hero-leave-dur) var(--tb-ease-entry) calc(2 * var(--tb-stag-beat))}
    /* DER ERSTE STAND KOMMT OHNE UEBERGANG (24.09.2026). Beim Laden mitten
       im Halt (Reload, Zurueck aus dem bfcache, Rueckkehr aus Reduced
       Motion) setzt der Kernel .is-leaving, waehrend die Zeilen noch im
       Vor-Intro-Stand mit Deckkraft 1 stehen. Als Transition startete der
       Abgang dann bei 1, und sobald .is-ready das Intro in die Liste
       brachte, verwarf Chromium sie: Kappenzeile und Titel standen 60 bis
       220 ms voll deckend auf der Buehne und verschwanden mit hartem
       Schnitt. Fuer dieses eine Bild setzt der Kernel .is-hold-instant
       und nimmt es im naechsten wieder weg. !important, weil die
       Zustandsregeln oben mehr wiegen und es nur einen Frame lebt. */
    .tb-page .tb-hero--pin.is-holding.is-hold-instant :is(.tb-hero__inner > *,.tb-hero__content,.tb-hero__foot,.tb-hero__scrim),.tb-page .tb-hero--hof.is-holding.is-hold-instant .tb-hero__content::before{transition:none!important}
    /* DIE SPERRE (24.09.2026, zweite Pruefrunde; Herleitung im Kernel bei
       WIEDERHERSTELLUNG). Der Observer meldet einen Sprung erst nach dessen
       Bild: beim Neuladen in WebKit (Wiederherstellung nach load) und im
       ersten Bild nach Reduced Motion stand dort der volle Kopf hinter der
       Schwelle. Der Kernel setzt .is-hold-offen nur, wenn der Browser eine
       Stelle herstellt (Neuladen, Zurueck/Vor, Anker, gescrollter Start,
       bfcache), bis zur ersten Eingabe, und unter Reduced Motion - beim
       Erstaufruf nie (25.09.2026, dritte Pruefrunde: ein Fruehscroller sah
       sonst bis 600 ms nach load harte Schnitte statt der Abfolge).
       Solange der Kernel .is-hold-offen setzt, haelt eine Stufe an der
       Abgangsschwelle Kopf, Fuss und Schleier im Abgangsstand, gerechnet im
       selben Bild wie der Scroll. Vor der Schwelle wirkt sie nicht (fill
       forwards), dahinter setzt .is-leaving gleich darauf dieselben Werte
       ohne Uebergang. Ohne Messung liegt die Stufe hinter jeder Seite: sie
       darf nie ab Scroll 0 greifen. Den Fokus laesst sie wie der Abgang. */
    @keyframes tbHoldSperre{from,to{opacity:var(--sh-sperre,0)}}
    .tb-page .tb-hero--pin.is-holding.is-hold-offen{--sh-hold-sperre:var(--sh-hero-gehen,99999px) calc(var(--sh-hero-gehen,99999px) + 1px)}
    .tb-page .tb-hero--pin.is-holding.is-hold-offen:not(:has(:focus-visible)) :is(.tb-hero__content,.tb-hero__scrim){animation:tbHoldSperre linear forwards;animation-timeline:scroll(root block);animation-range:var(--sh-hold-sperre)}
    .tb-page .tb-hero--pin.is-holding.is-hold-offen:not(:has(:focus-visible)) .tb-hero__foot{animation:tbHeroGone linear both,tbHoldSperre linear forwards;animation-timeline:scroll(root block);animation-range:var(--sh-hold-fuss),var(--sh-hold-sperre)}
    .tb-page .tb-hero--pin.is-holding.is-hold-offen .tb-hero__scrim{--sh-sperre:var(--tb-hero-scrim-ende)}
    /* Riegel des Abgangs: CTA und Fusslinks verlassen die Tastaturfolge
       genau am Ende ihrer Blende (+2 Takte + Dauer) und kommen beim
       Rueckweg sofort zurueck (der Eintrag faellt aus der Liste). Als
       Animation neben dem Deckkanten-Riegel, nicht als Transition: die
       Links tragen eigene Uebergaenge (Buttonfarben, Feder), die eine
       transition-Deklaration hier ueberschreiben wuerde. */
    .tb-page .tb-hero--pin.is-holding.is-leaving:not(:has(:focus-visible)) .tb-hero__actions > a{
      animation:tbHeroGone linear both,tbHoldAus 0s linear calc(var(--tb-hero-leave-dur) + 2 * var(--tb-stag-beat)) forwards;
      animation-timeline:scroll(root block),auto;
      animation-range:var(--sh-hold-lock),normal
    }
    .tb-page .tb-hero--pin.is-holding.is-leaving:not(:has(:focus-visible)) .tb-hero__foot :is(a,button,summary){animation:tbHoldAus 0s linear calc(var(--tb-hero-leave-dur) + 2 * var(--tb-stag-beat)) forwards}

    /* DIE NAHT an der Vorderkante der Folgeflaeche. Am Herofuss waere sie
       das Erste, was die steigende Flaeche verdeckt - sichtbar bliebe nur
       deren harte Kante (Befund 20.09.). Sie schrumpft auf null, weil ein
       Verlauf konstanter Hoehe als Nebel durch die helle Bildmitte
       wandert; weich gehoert er an den dunklen Bildfuss.
       Nur nach .tb-hero--into-ink: dort trifft Ink auf Ink. Die eine
       Seite ohne den Modifikator (Testbikeflotte) laeuft in eine weisse
       Flaeche, und ein weisser Verlauf ueber dem Foto waere Dunst.
       1 PX INK UNTER DER KANTE (23.09.2026, Befund H07): Chromium laesst
       die skalierte Unterkante bis zu 2 Geraetepixel vor der Sektions-
       kante enden, das Foto blitzte als helle Linie durch (iPhone 14,
       Galaxy S, quer, Chrome/Edge bei 125 %). ::after legt 1 px Ink
       UNTER die Naht (z -1) und skaliert nicht mit; es reicht 1 px in
       die Flaeche, sonst stossen bei DPR 1,25/1,5 zwei geglaettete
       Kanten aufeinander. Eigene Ebene (will-change), sonst waechst die
       Ebene der Sektion und ihre Schrift rastert bei gebrochener DPR
       auf anderer Subpixel-Phase. NICHT die Naht verlaengern: +2px
       schob den ganzen Verlauf nach unten, im Spaetteil heller und mit
       harter Stufe (SE bis +87). NICHT box-shadow an der Sektion: dann
       verliert ihre Schrift die Subpixel-Glaettung (Chrome, Windows).
       Damit sind ::before UND ::after der Folgeflaeche belegt. */
    .tb-page .tb-hero--pin.is-holding.tb-hero--into-ink + *::after{content:"";position:absolute;left:0;right:0;top:-1px;height:2px;z-index:-1;pointer-events:none;background:#0f0f0f;will-change:transform}
    .tb-page .tb-hero--pin.is-holding.tb-hero--into-ink + *::before{
      content:"";
      position:absolute;
      left:0;right:0;
      top:calc(-1 * var(--tb-seam));
      height:var(--tb-seam);
      transform-origin:50% 100%;
      animation:tbSeamToEdge linear both;
      animation-timeline:scroll(root block);
      animation-range:var(--tb-hero-start,0px) calc(var(--tb-hero-start,0px) + var(--tb-seam-ende) * var(--tb-hero-hold,100vh));
      pointer-events:none;
      background:linear-gradient(180deg,rgba(15,15,15,0) 0%,rgba(15,15,15,.38) 46%,rgba(15,15,15,.82) 80%,#0f0f0f 100%)
    }
  }
}

/* ---- FOTO-BUEHNE (Bildflaeche mit Kopf am Fuss) ----
   G1-Hebung 2026-08-26 (Kanonseiten-Audit B1/3): die Huelle stand
   wortgleich als .sh-trust__stage (Startseite, "Warum TilliT") und
   .bp-fit__stage (Beratungsprozess, Bikefitting). Instanz bleiben
   der Schleier (::after-Verlaeufe driften bewusst je Motiv), der
   Bildausschnitt und bp's Hairline-Einfaerbung des Kopf-Index.
   KOPFABSTAND: Kanon ist der Startseiten-Wert (2.4rem/6.5vh/5rem);
   der Beratungsprozess stand still auf 2.6/7vh/5.5 und rueckt mit
   der Hebung bewusst auf den Kanon (rund 5 px bei 900er-Hoehe).
   Mobilhoehe im MOBIL-Block am Dateiende. */
/* BUEHNENBODEN (17.09.2026, Canvas "Breitbild-Verhalten", Richtung B):
   die Hoehe deckelt bei 900px, die Breite ist randlos - bei 2560x1440
   war die Buehne ein Band von 2,84:1 mit 61 % des Motivs, auf einem
   Ultrawide 3,82:1. 40vw ist der Boden: nicht flacher als 2,5:1, damit
   die bei 1440 gesetzten object-position-Ausschnitte tragen. Greift
   erst, wenn 40vw ueber dem vh-Deckel liegt (ab etwa 2250px bei 1440
   Hoehe); bei 1440 (576 gegen 756) und 1920 (768 gegen 900) folgenlos.
   Die Medienbox folgt der Buehne (.tb-stage__media oben), auch dort,
   wo Seiten dem Bild eine eigene Hoehe geben (0,3,0 schlaegt sie). */
.tb-stage--foto{height:max(clamp(460px,84vh,900px),40vw);background:var(--tb-ink)}
.tb-stage__head{position:absolute;left:0;right:0;bottom:clamp(2.4rem,6.5vh,5rem);z-index:1}
.tb-stage__head-inner{max-width:40rem}
.tb-stage__head .tb-index{color:var(--tb-white);text-shadow:0 1px 14px rgba(15,15,15,.6)}
/* Ab 768 zentriert der Kopf ueber der vollen Buehne (Herleitung am
   Startseiten-Kommentar: der Zweispalter mit Lead fiel, damit auch
   sein 1280er-Zwischenschritt). */
@media (min-width:768px){
  .tb-stage__head-inner{max-width:none;margin:0;text-align:center}
  .tb-stage__head-inner .tb-index{justify-content:center;margin-bottom:clamp(1.2rem,2.6vh,1.8rem)}
}
/* ==== BILDBUEHNE ENDE ==== */


/* ======== HERO (Seiten-Buehne mit zentriertem Satz) ========
   KANONISIERT 2026-08-24 mit dem zweiten Verwender (Testbikeflotte-
   Port): bis dahin stand die komplette Fassung als bp-hero im
   Beratungsprozess. Werte 1:1 von dort — der Beratungsprozess ist die
   abgenommene Referenz.

   Geometrie: 88vh Buehne + Bildauslauf (--sh-hero-over, Default 12vh)
   unter der Falz. Ken-Burns-Ausklang und Parallax kommen aus der
   Bildbuehne (tb-stage--hero); der Bildausschnitt (object-position)
   ist Instanzsache der Seite, ebenso der Intro-Auftritt (der
   Beratungsprozess staffelt wortweise, die Flotte blockweise).

   Der Scrim ist die gemessene Fassung gegen helle Dunsthimmel:
   oben kraeftig (weisses Chrome!), in der Bildmitte zurueckgenommen,
   zur Unterkante auf .86 Ink. Das reicht fuer Lesbarkeit, wird auf
   hellen Motiven aber nicht vollstaendig deckend - dafuer gibt es seit
   23.09.2026 den Hochformat-Zuschnitt je Seite und die zwei Stufen
   .tb-hero--dicht und .tb-hero--hof (beim Kopfzeilenband). Wenn direkt eine
   Ink-Flaeche folgt, legt --into-ink deshalb auf den letzten 12 % den
   echten Nahtauslauf bis #0f0f0f darueber. Er ist ein Modifikator und
   kein Default, weil Flotte, Atherton und Kategorie ins Helle wechseln.

   KEIN font-weight am Titel: die Werks-700 auf h1-h6 kontert seit
   dem 2026-08-24 die Basisregel in tillit-base.css.

   ZENTRIERT MIT ANSCHLAG (23.09.2026, Befunde H03 Teil 2 und H04;
   nachgebessert 24.09.2026). Bis dahin zentrierte ein Flex-Kasten den
   Satz, und der Fuss hing absolut an der Unterkante. Auf flachen
   Fenstern (Telefon quer, Laptop 1280x600, SE hochkant, Seitenzoom und
   Schrift 200 %) ging beides schief: die Kappenzeile stand fest 56 px
   unter der Oberkante und damit unter Logo und Navipunkten (Kopfkante
   95 bis 159 px; 12 von 14 Seiten bei 844x390), und der Fuss lag ueber
   dem CTA (Atherton-Logo auf dem SE 21,6 px, das Ankerband der Flotte
   quer mitten durch "Termin buchen", ein Tipp dort oeffnete "E-Bike
   Alltag").
   Jetzt eine Flex-Spalte: oben waechst ::before, in der Mitte steht der
   Satz, unten waechst der Fuss selbst (ohne Fuss ::after). Beide Haelften
   beginnen bei 0 und teilen sich den Rest, der Satz steht also, wo ihn
   die Zentrierung hatte. Jede Haelfte hat ein Mindestmass: oben die
   Kopfkante plus 1,2rem (abzueglich des eigenen 4rem-Polsters), unten
   die ECHTE Fusshoehe samt Abstand zur Unterkante. Greift eines, rueckt
   der Satz nur um das Fehlende - Oberkante = clamp(Kopfluft, Mitte,
   Hoehe - Fuss - Satz) -, und passt beides nicht, waechst die Buehne um
   genau die Summe; den Rest holt der Haftversatz im Kernel (H01) ins
   Bild. Kein Hoehen-Media-Query: dieselbe Regel traegt Querformat, Zoom
   und 200 % Schrift, auch bei 844 px Fensterhoehe.
   1.00001 UNTEN IST TRAGEND: jede Engine rundet eine geteilte Haelfte
   anders. Bei gleichen Faktoren rundet WebKit beide auf (Satz bei jeder
   zweiten Satzhoehe 1/64 px tiefer als mit der alten Zentrierung, bis 23
   Stufen an Schriftkanten); mit dem Vorsprung der unteren Haelfte runden
   Chromium, WebKit und Firefox genau wie die Zentrierung ab (160 Satz-
   hoehen synthetisch, 0 Abweichungen). Nicht auf 1 kuerzen.
   VERWORFEN, gemessen: (a) Raster .5fr | Satz | .5fr (Fassung vom
   23.09.) - Firefox rundet jede fr-Zeile einzeln auf (Buehne 844,017
   statt 844 bei 390x844), und greift unten der Fuss, faellt die Summe
   der Faktoren unter 1: der Rest streckte die Satzzeile, der Satz klebte
   an der Kopfluft (MTB-Hub SE 44,5 statt 16 px nach oben); mit 1fr waechst
   die Buehne dort um das doppelte groesste Mindestmass (SE 600 statt
   568); (b) symmetrisches Polster max(4rem, Kopfkante + 1,2rem) - quer
   waechst die Buehne unten um dieselben 60-120 px wie oben; (c) ein
   Hoehen-Media-Query fuer den Fuss - 200 % Schrift bei 844 px
   Fensterhoehe faellt durch jede Schwelle; (d) der Satz ohne eigenes
   4rem-Polster - der kleinere Kasten veraendert die Unschaerfe des
   Abgangs (bis 4 Stufen waehrend des Halts). */
.tb-hero{--sh-hero-over:12vh;position:relative;display:flex;flex-direction:column;min-height:calc(88vh + var(--sh-hero-over));overflow:hidden;background:var(--tb-ink)}
.tb-hero::before,.tb-hero::after{content:"";flex:1 1 0px}
.tb-hero::before{min-height:max(0px,calc(var(--tbh-kopf-h,0px) + 1.2rem - 4rem))}
.tb-hero::after{flex-grow:1.00001}
.tb-hero:has(> .tb-hero__foot)::after{content:none}
.tb-hero__scrim{position:absolute;inset:0;background:
  linear-gradient(180deg,rgba(15,15,15,.44) 0%,rgba(15,15,15,.27) 15%,rgba(15,15,15,.16) 31%,rgba(15,15,15,.19) 44%,rgba(15,15,15,.32) 58%,rgba(15,15,15,.54) 74%,rgba(15,15,15,.74) 90%,rgba(15,15,15,.86) 100%)}
/* KOPFZEILENBAND 2026-09-06 (Befund Max "fehlt oben nicht bissl
   Abdunklung, wo der Header ueber dem Bild liegt"): der Scrim-Verlauf
   ist bei 15 % schon auf .27 zurueck - genau dort steht die Menuezeile
   (Werksmass am Desktop: Ankuendigungsleiste 0-42, Navireihe
   42-114). Ohne Kopfzeile gemessen lag der Grund unter der Menuezeile
   auf zehn von zwoelf Heroseiten zu hell fuer weisse Schrift:
   Testbikeflotte 171 (2,3:1), Amflow/Kategorie/Beratungsprozess
   155-159, Leasing 149, Ueber uns 122. Das Band legt deshalb NUR ueber
   die Kopfzeilenhoehe zusaetzliches Ink und ist bei 190 px wieder bei
   null - der hellste Fall kommt damit auf 4,5:1, das Motiv selbst
   bleibt unangetastet. Hoehe als Instanzknopf (--tb-hero-chrome),
   falls eine Seite den Kopf anders traegt.

   AUF JEDER BREITE (23.09.2026, Befund H10). Bis heute stand das Band
   nur ab 880 px, begruendet mit "darunter steht der Kopf statisch im
   Fluss". Das war schon beim Schreiben falsch: auf Heroseiten liegt
   #Header auf jeder Breite absolut und transparent ueber der Buehne
   (tillit-shop-header-v2.css, Hero-Zustand ohne Media Query, ebenso
   #special_header), und dieselbe Datei macht die mobilen Icons dafuer
   weiss. Unter 880 faellt nur das Kleben weg (header-v2-transfer.md,
   Abschnitt 7). Ohne Band standen Burger, Lupe, Warenkorb und Konto
   (1,36-px-Striche) mobil bei 2,1-2,9:1 auf hellem Himmel - unter den
   3:1 fuer Bedienelemente (SC 1.4.11), gemessen in Chromium, WebKit
   und Firefox. Mobil endet die Kopfzeile bei 95-99 px statt bei 114,
   das Band ist dort 150 px hoch (Knopf im Block BIS 879 am
   Dateiende). Gemessen danach (p10 der Strichpixel, Chromium und
   WebKit): hochkant ab 4,2:1 (SE, 390, iPad), quer ab 3,6:1 (MTB-Hub),
   Desktop unveraendert. Ein Ink-Verlauf auf dem Foto, keine Flaeche. */
.tb-hero__scrim::before{content:"";position:absolute;left:0;right:0;top:0;height:var(--tb-hero-chrome,190px);pointer-events:none;background:linear-gradient(180deg,rgba(15,15,15,.38) 0%,rgba(15,15,15,.34) 50%,rgba(15,15,15,.17) 78%,rgba(15,15,15,0) 100%)}
/* ---- HERO-SCHLEIER, ZWEI STUFEN (23.09.2026, Juror Bildregie, Befund H09) ----
   Der Kanon-Scrim oben ist bei 31-44 % der Buehnenhoehe am duennsten
   (.16/.19), und genau dort steht der Kopf: die Kappenzeile liegt auf
   allen 13 Heroseiten bei 26-41 % der Hoehe. Auf hellen Motiven
   (Dunsthimmel, weisse Wand, Nebel) stand der weisse Kopf bei 1,7-3,5:1
   (Glyphen, p05). Zuerst kommt deshalb der Hochformat-Zuschnitt je Seite
   (<picture>, Abschnitt "Art Direction ueber <picture>" in
   docs/reference/evendo-integration.md), dann eine dieser zwei Stufen,
   wo der Zuschnitt allein nicht reicht. Kein Flaechengrau, kein
   globales Abdunkeln: reiner Ink-Verlauf ueber dem Foto, nur auf den
   Seiten, die ihn brauchen. Beratung und Leasing brauchen keine Stufe
   (Werte ab 6,8).

   --dicht (sieben Seiten: Ueber uns, Road & Gravel, Pivot, AMFLOW, PR,
   PX, DEITY) ist EIN linearer Verlauf, abgeleitet aus den wortgleichen
   Instanzkurven von Atherton und DEITY (.58/.47/.42/.45/.56/.70/.84/.90;
   beide Instanzregeln sind mit Paket 4 gestrichen). Deren duennste
   Stelle (.42 bei 31 %) lag genau auf der Kappenzeile. Sie wandert nach
   15 % unter das Kopfzeilenband (::before liefert dort eigenes Ink), das
   Textband 31-58 % steigt auf .50-.58. Kopf (0 %) und Fuss (74-100 %)
   bleiben wie abgenommen. Die alte Kurve verfehlte selbst dort
   (Atherton-Kappenzeile am Desktop 3,5, DEITY 3,7, Ueber uns 4,4);
   staerkere lineare Kurven (Mitte .52-.54) grauen das ganze Foto ein und
   retten den MTB-Hub trotzdem nicht. Gemessen (p05 mit Schattenhof,
   Kappenzeile/Titel/Lead, 390x844 | 1440x900, Chromium; WebKit gleich
   +-0,1):
   Ueber uns 5,45/5,75/5,47 | 5,50/5,87/5,76
   Road & Gravel 6,98/7,32/6,51 | 7,12/7,67/7,27
   Pivot 11,78/9,31/7,84 | 8,17/9,72/5,72
   AMFLOW 5,38/6,08/8,35 | 4,90/5,74/7,58
   AMFLOW PR 13,10/9,56/7,72 | 13,31/8,43/6,40
   AMFLOW PX 7,85/5,99/5,43 | 14,19/5,33/5,02
   DEITY 8,37/10,42/10,09 | 4,61/7,58/10,58
   Knapp sind die DEITY-Kappenzeile (4,6) und AMFLOW (4,9) am Desktop:
   nach Copy- oder Umbruchaenderungen nachmessen. */
.tb-hero--dicht .tb-hero__scrim{background:linear-gradient(180deg,rgba(15,15,15,.58) 0%,rgba(15,15,15,.47) 15%,rgba(15,15,15,.50) 31%,rgba(15,15,15,.52) 44%,rgba(15,15,15,.58) 58%,rgba(15,15,15,.70) 74%,rgba(15,15,15,.84) 90%,rgba(15,15,15,.90) 100%)}
/* --hof (vier Seiten: Testbikeflotte, MTB-Hub, Atherton, AMFLOW Schweiz)
   ist die zweite Stufe fuer eine helle, gleichfoermige Bildmitte, auf
   der ein linearer Verlauf das ganze Foto eingrauen muesste: ein
   radialer Ink-Hof hinter dem Kopf, auf dem Kanon-Schleier (nie
   zusammen mit --dicht). Er liegt in .tb-hero__content und geht mit dem
   Kopf: im Halt haengt seine Deckkraft an derselben Zustandsklasse und
   Blende wie die Zeilen, nie am Scroll, und seine Lage steigt mit der
   Kappenzeile (Regeln im REGISTER HALT). In Ruhe, ohne
   Timeline (Firefox) und unter Reduced Motion steht er, weil dort auch
   der Text steht. inset -30 % verhindert eine harte Kante; Form H09
   hof58b. Gemessen (390 | 1440, wie oben):
   Testbikeflotte 11,52/13,74/6,16 | 8,58/10,99/11,19
   MTB-Hub 5,84/5,93/5,72 | 5,05/6,25/6,22 (Galaxy S Kappenzeile 4,77)
   Atherton 5,60/6,07/7,34 | 4,98/6,45/6,61
   AMFLOW Schweiz 6,01/6,48/5,67 | 5,94/6,46/6,05
   Auf gleichfoermigem Himmel (MTB-Hub, Schweiz) sieht man ihn als weiche
   Wolke; beide Motive sind ein Uebergang, empfohlen ist ein Motivtausch.
   "Hof ueberall" (alle elf Seiten) bestand ebenfalls (Desktop ab 5,0),
   machte den Satz am Kopf aber ungleichmaessiger: heller Himmel ueber
   einer dunklen Wolke. Entschieden hat Max am 25.09.2026 fuer die zwei
   Stufen wie vorgeschlagen. */
.tb-hero--hof .tb-hero__content::before{content:"";position:absolute;inset:-30% -15%;z-index:-1;pointer-events:none;background:radial-gradient(ellipse 68.7% 38.75% at 50% 48.1%,rgba(15,15,15,.58) 0%,rgba(15,15,15,.5) 52%,rgba(15,15,15,0) 100%)}
.tb-hero--into-ink .tb-hero__scrim::after{content:"";position:absolute;left:0;right:0;bottom:0;height:12%;pointer-events:none;background:linear-gradient(180deg,rgba(15,15,15,0) 0%,rgba(15,15,15,.32) 52%,rgba(15,15,15,.78) 84%,#0f0f0f 100%)}
.tb-hero__content{position:relative;z-index:1;flex:none;width:100%;padding:4rem 0;color:var(--tb-white)}
.tb-hero__inner{display:flex;flex-direction:column;align-items:center;width:100%;text-align:center}
.tb-hero__eyebrow{display:block;margin:0 0 1.7rem;color:var(--tb-white);font-family:var(--tb-mono);font-size:.88rem;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking);text-shadow:0 1px 14px rgba(15,15,15,.6)}
/* BREITBILD-STUFE: der Deckel liest --tb-wide (1, ab 1920px 1,15;
   Herleitung in tillit-tokens.css). 6.4rem sind ab 1280px erreicht,
   darueber wuchs nur noch das Foto - bei 2560 belegte der Titel 3,5 %
   der Breite statt 6 % bei 1440. */
/* BREITBILD-RAMPE STATT STUFE (18.09.2026). Bis heute schaltete --tb-wide
   die Display-Grade bei genau 1920px von 1 auf 1,15 - gemessen bei 1918,
   1919, 1920 und 1921: der Hero-Titel sprang von 89,6 auf 103,04, der
   Buehnenkopf von 109,9 auf 126,39, der Weichen-Titel von 36,4 auf 41,86.
   15 Prozent auf ein Pixel Fensteraenderung, und damit genau die
   Sprungstelle zwischen Nachbarbreiten, die der Pruefplan als Befund
   fuehrt (docs/strategy/breitbild-pruefung-2026-09-17.md, Abschnitt 5).

   Das Muster ist ueberall dasselbe:
     clamp(<mobil>, <bisherige vw-Rampe>, min(<neu>, max(<alt>, X vw)))
   max() haelt den ABGENOMMENEN Wert, solange X vw kleiner ist als der alte
   Deckel - deshalb ist bei 1425 und 1440 jeder Grad auf das Zehntel der
   von gestern. X ist so geeicht, dass die Rampe erst bei rund 1545 px
   anspringt und den bisherigen 1,15-Wert bei rund 1780 px erreicht; dort
   ist auch die Insel (1700 + 2x28) gerade voll geworden. min() laesst den
   Grad danach stehen, auf 3440 wie auf 1920.

   WARUM NICHT EINFACH DEN DECKEL ANHEBEN: weil vw das Fenster misst und
   mehrere Deckel heute schon frueh greifen - der Hero-Titel ab 1280 px.
   Ein hoeherer Deckel oeffnet die Rampe rueckwaerts in den abgenommenen
   Bereich: gemessen 100,8 statt 89,6 px bei 1440, also 12 Prozent zu gross
   auf dem Bildschirm des Auftraggebers. Erst das max() macht den Unterschied.

   WARUM KEINE CONTAINER QUERY: cqi an der Huelle leistet dasselbe (gemessen
   auf 56 Seiten folgenlos), kostet aber container-type auf .tillit-container
   - und damit einen eigenen Formatierungskontext, in dem der Aussenabstand
   des ersten Kindes nicht mehr durchfaellt (gemessen bis 117 px an
   .bp-fit__grid). Drei der acht Rollen liegen ausserdem gar nicht in der
   Huelle (die Split-Haelften der Startseite sind randlos), haetten also
   einen zweiten Container gebraucht. Dieselbe Kurve fuer null neue Technik.

   --tb-wide bleibt als Token stehen, wird aber von keiner Regel mehr
   gelesen; der 1920er Block am Dateiende ist mit ihm gefallen. */
/* DECKEL AUF DIE HUELLE (23.09.2026, Befund H19). Das rem-Minimum des
   Grads waechst mit der Nutzerschrift: bei Text-Zoom 200 % (Wurzel
   28 px) steht der Titel bei 81 px, und im Spalten-Flex von
   .tb-hero__inner (align-items:center) ist er fit-content, also nie
   schmaler als sein laengstes Wort. 21ch deckelt dort nicht mehr,
   "Mountainbikes" lief mit 473 px aus 390 heraus und wurde vom
   overflow des Heros abgeschnitten (MTB-Hub, Atherton, Pivot, DEITY).
   min(21ch,100%) haelt die Box in der Huelle, erst dann kann
   break-word das Wort brechen - break-word allein senkt min-content
   nicht und war gemessen wirkungslos. Bei Normalschrift aendert sich
   an 98 Messungen (14 Seiten x 7 Breiten) nichts. KEIN hyphens:auto:
   es trennt womoeglich auch Displaytitel bei 100 %, ungeprueft am
   echten Geraet (die Laborbrowser haben kein deutsches Woerterbuch). */
.tb-hero__title{margin:0;max-width:min(21ch,100%);overflow-wrap:break-word;color:var(--tb-white);font-size:clamp(2.9rem,7vw,min(7.36rem,max(6.4rem,5.8vw)));letter-spacing:-.03em;line-height:1.02;text-transform:none;text-wrap:balance;text-shadow:0 2px 40px rgba(15,15,15,.45)}
/* Satzbreite als Instanzknopf. DEFAULT 2026-09-03 von 38ch auf 44ch
   (Entscheidung Max am Atherton-Port): 38ch liess den Satz unter einem
   Titel stehen, der bis 6.4rem gross wird - vier bis fuenf kurze Zeilen
   lasen sich gedraengt, obwohl links und rechts Platz war. 44ch liegt
   weiter mitten im Korridor 45-75 Zeichen (Zaehlung inkl. Wortabstaenden)
   und ist zugleich der Wert, den die Flotte sich schon selbst gesetzt
   hatte - ihr Instanzknopf ist damit wertgleich zum Default und kann
   bei ihrem naechsten Anfassen fallen. Wer breiter braucht, setzt
   --sh-hero-measure hoeher (Atherton: 52ch). */
.tb-hero__text{max-width:var(--sh-hero-measure,44ch);margin:1.7rem 0 0;color:rgba(255,255,255,.84);font-size:min(1.265rem,max(1.1rem,1vw));line-height:1.6;text-wrap:balance;text-shadow:0 1px 14px rgba(15,15,15,.55)}
.tb-hero__actions{margin-top:2.6rem}
/* Fusszeile: Faktenzeile beim Beratungsprozess, Ankerband bei der
   Flotte, Wortmarke bei Atherton. Sie steht wie bisher um den
   Bildauslauf plus Luft ueber der Unterkante, aber im Fluss statt
   absolut (23.09.2026, H03 Teil 2): der Fuss ist die UNTERE HAELFTE der
   Spalte (.tb-hero oben). Sein Kasten waechst, die Tinte steht an dessen
   Boden. Die Aussenabstaende heben sich auf (oben minus, unten plus
   Abstand), damit die Haelfte bei 0 beginnt wie die obere; ::before
   haelt den Abstand minus 2,4rem frei - unter dem 4rem-Polster des
   Satzes bleiben so 1,6rem Luft zum CTA. Der Kasten reicht dadurch in
   die Satzzone hinauf: leer, durchsichtig, Zeiger gehen durch (unten).
   Die Fusstinte misst man am Kind, nicht am Kasten.
   Positioniert (z-index 1 ueber dem Satz) ist deshalb das KIND, nicht der
   Kasten: so bleibt die Buehne sein offsetParent, und der Kernel liest
   die Fussunterkante mit derselben Ganzzahlrundung wie vorher (40 von 40
   Faellen je Engine gleich; ueber den positionierten Kasten wichen 7 bis
   13 um 1 px ab). width:100% am Kind, weil die Spalte ein Kind mit
   margin:auto sonst auf Inhaltsbreite zieht. Den Abstand nach unten
   stellt eine Seite ueber --sh-hero-foot-bottom ein (Road & Gravel setzt
   ihn tief in den Auslauf), NICHT ueber bottom. */
.tb-hero__foot{--sh-hero-foot-b:var(--sh-hero-foot-bottom,calc(var(--sh-hero-over) + clamp(1.4rem,3.4vh,2.6rem)));display:flex;flex:1.00001 1 0px;flex-direction:column;justify-content:flex-end;margin:calc(-1 * var(--sh-hero-foot-b)) 0 var(--sh-hero-foot-b)}
.tb-hero__foot::before{content:"";flex:none;height:max(0px,calc(var(--sh-hero-foot-b) - 2.4rem))}
.tb-hero__foot > *{position:relative;z-index:1;width:100%}
/* KEINE UNSICHTBARE FANGFLAECHE (23.09.2026, Befund H03, Teil 1). Fuss
   und Kopf liegen beide auf z-index 1, der Fuss kommt im DOM spaeter und
   sein .tillit-container ist so breit wie die Buehne. Er fing deshalb
   auch dort Klicks und Tipps ab, wo keine Fuss-Tinte liegt: Atherton
   1366x650 und Zoom 200 % 0 bzw. 3 von 9 Treffern auf dem CTA, auf dem
   SE 3 von 9. Durchlassen darf der Fuss alles ausser seinen eigenen
   Bedienelementen (Ankerband der Flotte); Faktenzeile und Atherton-Logo
   sind reine Anzeige. Dass der Fuss auf flachen Fenstern sichtbar ueber
   dem CTA lag, loeste diese Zeile nicht; das tut seit Teil 2 die Spalte
   (.tb-hero oben). Die Zeile bleibt und ist seitdem tragend: der
   Fusskasten ist so breit wie die Buehne und reicht bis in die Satzzone
   - wo er keine Tinte hat, faengt er nichts ab. */
.tb-hero > .tb-hero__foot{pointer-events:none}
.tb-hero > .tb-hero__foot :is(a,button,summary){pointer-events:auto}
/* Faktenzeile im Hero-Fuss. Stand als .bp-hero__meta im Beratungs-
   prozess und wurde am 2026-09-02 in den Kanon gehoben, als die
   Leasingseite die Zeile als zweiter Verwender trug - Max strich sie
   dort am selben Abend. Der Block bleibt als BENANNTE AUSNAHME vom
   Aufnahmekriterium (ein Verwender): der naechste Hero mit
   Faktenzeile (Flotte, Kategorie) findet ihn hier statt eine dritte
   Kopie zu bauen. Mono-Versalien, Punkte als Trenner (<i>-Elemente ZWISCHEN
   den Spans). Mobil zentriert und umbrechend, ab 768 eine Zeile
   rechtsbuendig; die Trenner-Mechanik fuer den Umbruch steht im
   MOBIL-Block (der Punkt haengt dort VOR dem Wort statt als eigenes
   Element, damit er beim Umbruch mit seinem Wort wandert). Der
   Auftritt (Intro-Delay) bleibt Instanzsache der Seite. */
.tb-hero__meta{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:.5rem .85rem;margin:0;color:var(--tb-white);font-family:var(--tb-mono);font-size:.8rem;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking);text-shadow:0 1px 12px rgba(15,15,15,.65)}
.tb-hero__meta span{flex:none}
.tb-hero__meta i{flex:none;width:3px;height:3px;border-radius:50%;background:rgba(255,255,255,.55)}
@media (min-width:768px){
  /* nowrap: umbricht die Faktenzeile, haengt der Trennpunkt am Zeilenende. */
  .tb-hero__meta{flex-wrap:nowrap;justify-content:flex-end;text-align:right}
}

/* Hero-Auftritt: EIN Keyframe-Rumpf fuer alle Seiten (G1-Hebung
   2026-08-26, Kanonseiten-Audit B1/4) — er stand byteidentisch als
   shHeroIn/bpHeroIn/tfHeroIn dreimal inline. Keyframes statt
   Transition, weil die Wort-Spans erst im Skript entstehen und beim
   Laden der aufgeloeste Vorher-Zustand fehlt, an dem eine Transition
   ansetzen koennte (vollstaendige Herleitung an der Startseite).
   Die ANWENDUNG bleibt Instanzsache der Seiten: Selektoren, Delays
   und Staffelungs-Variablen gehoeren der jeweiligen Choreografie.
   Start bei opacity .01 statt 0 (01.10.2026, Review 2 zum Intro ab dem
   ersten Bild): bei 0 malt Chromium die Zeilen nicht und verbucht LCP
   erst mit dem naechsten Hauptthread-Bild - im Shop oft erst bei
   DOMContentLoaded (3-s-Fremdstau: 12 von 96 Laeufen bei 3,2-3,5 s).
   Mit .01 zaehlt das erste Bild, sichtbar ist der Unterschied nicht
   (Pixelabstand hoechstens 1/255). */
@keyframes tbHeroIn{
  from{opacity:.01;filter:blur(var(--tb-blur-deep));transform:translate3d(0,var(--tb-move-lift),0)}
  to{opacity:1;filter:none;transform:none}
}
/* FOKUS IM LADE-INTRO (Hero-Review 01.10.2026): Tab in der ersten
   Sekunde landete auf dem CTA, waehrend seine Zeile noch bei Deckkraft
   .01 stand - der Hausring war unsichtbar (0,5 erst nach 1,0-1,2 s). Eine
   Zeile mit Tastaturfokus steht sofort ganz; !important schlaegt die
   laufende Animation. Der Halt bewegt die Zeilen ueber translate, das
   bleibt; die Abgangsregeln nehmen Zeilen mit Fokus ohnehin aus. */
.tb-page :is(.tb-hero__inner > *,.tb-hero__foot,[data-tb-zeile]):has(:focus-visible){opacity:1!important;filter:none!important;transform:none!important}


/* ======== FLOTTENKARTE ========
   KANONISIERT 2026-08-24 mit dem zweiten Verwender (Testbikeflotte-
   Port); Fassung 1:1 vom Flotten-Auszug des Beratungsprozesses, der
   auf der abgenommenen Produktkarte steht. Hier liegen die BAUTEILE
   der Karte — das RASTER (Spaltenzahl, Subgrid-Zeilen) bleibt
   Instanzsache der Seite, weil die Zeilenzonen je Seite verschieden
   sind (der Beratungsprozess fuehrt eine Textzone, die Flotte einen
   Terminlink).

   Graue Bildflaeche statt Rad auf blankem Weiss: multiply loescht
   den weissen Freisteller-Grund gegen das Panel aus; isolation
   haelt die Mischung im Panel. Der Halbschatten liegt UNTER dem
   Bild und ist die Standflaeche (Herleitung am alten bp-Block).
   Hover nur scale — Hausregel, kein Lift. Der Bildzoom leiht sich
   BEWUSST die Auftrittsuhr (--tb-dur-enter, 0.7s) statt der
   Zustandsuhr: der langsame Zoom ist der abgenommene Ist-Stand, mit
   .35s wirkte das grosse Bild nervoes. Zwilling mit identischer
   Begruendung: .prodpic in tillit-produktkarten.css — beide Kartenzooms
   fahren dieselbe Uhr und duerfen nicht auseinanderlaufen. */
.tb-fleet__card{display:flex;flex-direction:column}
.tb-fleet__media{position:relative;isolation:isolate;margin:0 0 1.15rem;aspect-ratio:var(--tb-panel-ratio);padding:var(--tb-panel-pad);background:var(--tb-panel-media);border-radius:var(--tb-radius);overflow:hidden}
/* Kanten der Standflaeche bleiben Instanz: diese Karte fuellt ihr
   Panel mit cover und beschneidet, die Produktkarte passt ein — das
   Rad steht dort schmaler. Herleitung an den Token in L0. */
.tb-fleet__media::before{content:'';position:absolute;z-index:0;left:15%;right:15%;bottom:11%;height:10%;background:var(--tb-panel-stand)}
.tb-page .tb-fleet__media img{position:relative;z-index:1;width:100%;height:100%;object-fit:cover;mix-blend-mode:multiply;transition:transform var(--tb-dur-enter,.7s) var(--tb-ease-state)}
.tb-fleet__card:hover .tb-fleet__media img{transform:scale(var(--tb-panel-zoom))}
/* Hairline UEBER der Auszeichnung: klare Kopfkante fuer den Block
   unter dem Bild, der Name darf ein- oder zweizeilig laufen. */
.tb-fleet__head{padding-top:.95rem;border-top:1px solid var(--tb-line)}
.tb-fleet__usage{display:block;color:var(--tb-ink-1);font-family:var(--tb-mono);font-size:.76rem;line-height:1.5;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking)}
/* 1.5rem statt der 1.4 der Produktkarten-Paritaet: die Sichtpruefung
   des Flotten-Ports (Max, 2026-08-24) wollte die Namen eine Stufe
   praesenter — bewusster Abschied von der exakten Kachel-Groesse,
   die Verwandtschaft tragen weiter Panel, Hairline und Mono-Zeile. */
.tb-fleet__model{margin:.45rem 0 0;color:var(--tb-ink-1);font-size:1.5rem;letter-spacing:-.022em;line-height:1.2;text-wrap:pretty}
/* Ausstattungs-/Farbnotiz: Abstufung ueber die Farbe, nicht ueber
   Groesse oder Schnitt. */
.tb-fleet__meta{margin:.35rem 0 0;color:var(--tb-muted);font-size:.92rem;line-height:1.5}
/* Groessen als Ziffernreihe statt gerahmter Pillen: Label gedeckt,
   Ziffern in Ink — die Abstufung traegt die Farbe. */
/* .78rem statt der .72 der Lieferzeitzeile: gleiche Sichtpruefung —
   Label und Ziffern duerfen eine Spur lauter sein. */
.tb-page .tb-fleet__sizes{display:flex;flex-wrap:wrap;align-items:baseline;gap:.35rem .55rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--tb-line);color:var(--tb-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label,.78rem);line-height:1.5;letter-spacing:var(--tb-mono-tracking);text-transform:uppercase}
.tb-fleet__sizes-label{flex:none;margin-right:.2rem}
/* tnum: die Ziffern benachbarter Karten stehen auf einer Senkrechten. */
.tb-fleet__size{color:var(--tb-ink-1);font-feature-settings:"tnum" 1}
/* Trennpunkt NACHGESTELLT: er haengt am Flex-Item und schliesst beim
   Umbruch die erste Zeile ab ("49 · 51 · 53 ·"), statt die zweite
   anzufuehren. Abstand symmetrisch zum .55rem-gap. */
.tb-fleet__size:not(:last-child)::after{content:'·';margin-left:.55rem;color:var(--tb-line-strong)}
/* Dreispaltig (ab 600 auf beiden Verwenderseiten) sind die Karten
   die schmalsten der Seite: kleinerer Name, engeres Panel. Ab 1024
   traegt die Spaltenbreite wieder die Basiswerte. */
@media (min-width:600px){
  .tb-fleet__media{padding:var(--tb-panel-pad-narrow)}
  .tb-fleet__model{font-size:1.15rem}
  .tb-fleet__meta{font-size:.82rem}
}
@media (min-width:1024px){
  .tb-fleet__media{padding:var(--tb-panel-pad)}
  .tb-fleet__model{font-size:1.5rem}
  .tb-fleet__meta{font-size:.92rem}
}


/* ======== BILD-TEXT-ZEILE (.tb-feature) ========
   KANONISIERT 2026-09-03 mit dem Atherton-Port. Die Rolle stand als
   .tillit-feature-row im Altbestand (tillit-feldspiegel-alt.css:1547-1640 plus
   MQ 1973-2000) und hat VIER Verwender: atherton (6), pivot-shuttle-ampd
   (6), orbea-rallon-rs (5), amflow-pr (4) — G1 mit Abstand. Das Markup
   ist auf allen vier Seiten dasselbe (Bild / Auszeichnung, Titel, Text,
   Aufzaehlung), der Port der drei uebrigen Seiten kann diesen Block
   deshalb 1:1 uebernehmen.

   WAS DABEI FAELLT, damit es niemand versehentlich zurueckbaut:
   - Der Schlagschatten unter dem Bild (0 15px 40px) und der DOPPELTE
     Hover des Altbestands: scale 1.02 auf dem KASTEN, 1.03 auf dem
     Bild, dazu ein zweiter, groesserer Schatten. Drei Dinge, die sich
     gleichzeitig bewegen, sind drei Gesten; die Hausregel kennt eine.
     Der Zoom IM Bild bleibt (Hover-Absatz unten).
   - Die Gold-Pille der Auszeichnung (Chip mit Rahmen, Radius 999px,
     Gold-Hinterlegung). Auszeichnung spricht im System Mono und
     versal — das ist .tb-index, hier nur mit engerem Fuss.
   - Die Checkmark-SVGs der Aufzaehlung. Markenkonvention seit
     2026-08-19: keine Haken, Aufzaehlung typografisch als Kreis-Badge
     (docs/strategy/tillit-bikes-marke-und-beratung.md, Abschnitt
     "Keine Checkmark-Icons"). Das Zeichen ist .tb-badge; hier steht nur
     die Zeilengeometrie und der Ausgleich, den nur der Verwender kennt
     (Formel wie .sh-terrain__list: (Zeilenhoehe - Kreishoehe) / 2).

   TITEL: eigene Klasse gibt es nicht — die Rolle ist der Zeilentitel
   des Systems (.tb-row__title, clamp 1.5-2.1rem). Der Altbestand lief
   auf 1.5/1.75rem und liegt damit exakt in dieser Rampe.

   MEDIENKACHEL, zwei Faelle:
   - Default (Foto): Bildausschnitt ueber die ganze Kachel (cover).
   - --contain (Freisteller auf Weiss): Panel-Grau, Innenpolster,
     multiply. Dieselbe Mechanik wie .tb-fleet__media — multiply
     loescht den weissen Freisteller-Grund gegen das Panel aus,
     isolation haelt die Mischung in der Kachel. Ohne das Panel stuende
     ein Freisteller als weisser Kasten auf weisser Sektion und die
     Kachel waere nur an ihrer Kante zu erahnen.
   Die aspect-ratio ist der Bestandswert 4/3; das Seitenverhaeltnis
   gehoert der Rolle, nicht der Instanz (sonst laufen die vier Seiten
   wieder auseinander).

   HOVER: nur der Bildzoom, scale 1.03. Praezedenz ist doppelt und der
   Wert ist keiner der neuen: .tb-fleet__media (Karte) und
   .tb-logos__cell (Logoband) fahren dieselbe Geste — und das Logoband
   beweist, dass sie im System NICHT an einen Link gebunden ist: seine
   Zellen sind Divs. Bewegt wird ausschliesslich scale (Hausregel, kein
   Lift). Die UHR ist bewusst die Auftrittsuhr --tb-dur-enter und nicht
   die Zustandsuhr: mit .35s wirkt eine grosse Bildflaeche nervoes. Damit
   fahren jetzt DREI Bildzooms dieselbe Uhr (Karte, Produktkarte,
   Bild-Text-Zeile) — sie duerfen nicht auseinanderlaufen.

   REVEAL: die Zeile traegt EINE Auszeichnung als Ganzes (Default) statt
   media + copy getrennt — sie ist ein gemischter Block, kein Medienblock,
   und die Dichteregel zaehlt sie damit als eine Einheit. */
/* Der Kopfabstand steht auf der BASIS, nicht auf einem +-Selektor: so
   macht es jeder Kopf-Folger des Systems (.tb-proof, .tb-faq, .le-calc).
   Die Zeilen-zu-Zeile-Regel darunter wiegt 0,2,0 und schlaegt ihn. */
.tb-feature{display:grid;gap:clamp(1.6rem,4vh,2.4rem);align-items:center;margin-top:var(--tb-head-gap)}
.tb-feature + .tb-feature{margin-top:clamp(3.5rem,9vh,6rem)}
.tb-feature__media{position:relative;isolation:isolate;aspect-ratio:4/3;border-radius:var(--tb-radius);overflow:hidden}
.tb-page .tb-feature__media img{width:100%;height:100%;object-fit:cover;transition:transform var(--tb-dur-enter,.7s) var(--tb-ease-state)}
.tb-feature__media:hover img{transform:scale(var(--tb-panel-zoom))}
/* 3/2 statt 4/3 fuer Freisteller: ein Rad ist breit, und die Paritaet
   gilt der Kachel der Flottenkarte, die dieselbe Rolle spielt. */
.tb-feature__media--contain{aspect-ratio:var(--tb-panel-ratio);padding:clamp(1.2rem,3vw,2.4rem);background:var(--tb-panel-media)}
.tb-page .tb-feature__media--contain img{object-fit:contain;mix-blend-mode:multiply}
.tb-feature__body{min-width:0}
/* Engerer Fuss als der Sektionskopf: die Auszeichnung steht hier ueber
   einem Titel im Textblock, nicht ueber einer ganzen Sektion. */
.tb-feature .tb-index{margin-bottom:1.05rem}
/* LESEMASS = ABNAHMEBREITE (Matrix-Sichtpruefung 17.09.2026): auf der
   1700er Insel wuerde die Textspalte der Bild-Text-Zeile 818 px breit und
   ein Absatz 117 bis 129 Zeichen lang (gemessen AMFLOW, Atherton, Pivot bei
   1920 und 2560). 47.2rem sind die 660,5 px, die die Spalte bei 1440 hat -
   dort aendert sich nichts, darueber bleibt der Text bei seiner
   abgenommenen Zeilenlaenge und steht links in der wachsenden Spalte.
   Gleiches Muster: .tb-proof__text (46rem), .sh-trust__text der Startseite
   (55.1rem), .bp-fit__partner-text der Beratung (47.4rem). Ein echtes
   Lesemass (60-70 Zeichen) waere eine Aenderung bei 1440 und damit eine
   Entscheidung, keine Korrektur. */
.tb-feature__text{max-width:47.2rem;margin:1.15rem 0 0;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
/* .tb-page als Panzer: der Listen-Reset (.tb-page ul, 0,1,1) schluege
   ein nacktes .tb-feature__list (0,1,0) und naehme ihm den margin-top —
   dieselbe Falle wie bei .tb-proof. */
.tb-page .tb-feature__list{display:grid;gap:.9rem;margin-top:1.8rem}
.tb-feature__item{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:start;gap:.8rem;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
.tb-feature__item .tb-badge{--sh-badge-lift:calc((var(--tb-copy-size) * var(--tb-copy-leading) - 2.34em) / 2)}
.tb-feature__actions{margin-top:1.9rem}
@media (min-width:768px){
  .tb-feature{grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(2.5rem,5vw,4.5rem)}
  /* order statt row-reverse: das Raster behaelt seine Spaltenfolge,
     nur die Kachel wechselt die Seite — damit bleibt die DOM-Reihenfolge
     (Bild vor Text) auf jeder Zeile gleich und der Vorlesefluss stabil. */
  .tb-feature--reverse .tb-feature__media{order:2}
}


/* ======== DOSSIER (Hairline-dl, .tb-dossier) ========
   Label-Wert-Zeilen mit Hairlines: Adresse, Telefon, Zeiten, Rolle
   einer Person. Kanonisiert 2026-09-07 mit dem zweiten Verwender
   (Standortseiten pages/standorte/sasbach.html und gernsbach.html;
   davor Unikat .ue-dossier der Ueber-uns-Seite mit Team- und
   Besuchsblock). Geometrie wie die Rechenkette der Leasingseite
   (.le-calc__row), Labelstimme wie die Trust-Labels der Startseite:
   Mono, versal, gedeckt; der Wert in Satzschrift auf den Copy-Tokens.
   .tb-page als Panzer, damit die dl ihren Abstand behaelt.
   __set reiht mehrere Links in EINER Zeile mit Mittelpunkt als
   Trenner - inline, KEIN Flex und KEIN padding-block auf den Links:
   als Flex-Items wuerden die Links blockifiziert (23,4 statt 17,5 px
   Box bei 15,12 px Schrift) und die Feder von .tb-flow, die an der
   UNTERKANTE des Elements haengt, saesse rund 6 px zu tief; jedes
   Polster schoebe sie ebenso vom Wort weg (Befund Max 2026-09-04 an
   der Kanalzeile der Ueber-uns-Seite). Die Stapelregel bis 1023 px
   steht im Tablet-Block am Dateiende. */
.tb-page .tb-dossier{margin:clamp(1.6rem,3.5vh,2.4rem) 0 0;border-bottom:1px solid var(--tb-line)}
.tb-dossier__row{display:grid;grid-template-columns:minmax(7.5rem,11rem) minmax(0,1fr);gap:1.5rem;padding:clamp(.95rem,2vh,1.3rem) 0;border-top:1px solid var(--tb-line)}
.tb-dossier dt{padding-top:.2rem;color:var(--tb-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);text-transform:uppercase}
.tb-dossier dd{margin:0;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
.tb-dossier__set > span{margin-inline:.45rem}


/* ======== FAHRPLAN (Hairline-Zeilen mit Kappe, .tb-plan) ========
   Gruppen aus einer Kopfzeile (Mono-Kappe mit Zusatz | ein Satz) und
   Hairline-Zeilen (Titel | Meta | optional Button oder .tb-link) im
   selben Raster: feste erste Spur, damit die Kappe ueber dem Titel
   und der Satz ueber der Meta steht. Kanonisiert 2026-09-07 mit dem
   zweiten Verwender (Standortseiten pages/standorte/*; davor Unikat
   .tm-plan der Terminseite, dort Runde 4 "ein Fahrplan in EINEM
   Raster" nach Max' Befund zum Zweispalter). Ein Button je Zeile,
   immer dasselbe Label; der Kontext (Anliegen, Dauer, Ort) steht in
   Gruppe und Zeile, nicht im Label. Kein Zustand, kein Reveal.
   Unter 768 stapeln Kopfzeile und Zeilen (Mobil-Block). */
.tb-plan{--sh-plan-col:clamp(10rem,24vw,22rem);margin-top:var(--tb-head-gap)}
.tb-plan__group + .tb-plan__group{margin-top:clamp(2.6rem,6vh,4rem)}
.tb-plan__head{display:grid;grid-template-columns:var(--sh-plan-col) minmax(0,1fr);gap:.6rem 2rem;align-items:baseline;padding:0 0 clamp(1rem,2.2vh,1.4rem)}
.tb-plan__kicker{display:flex;flex-wrap:wrap;align-items:center;gap:.7rem;margin:0;color:var(--tb-ink-1);font-family:var(--tb-mono);font-size:.82rem;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking);line-height:1.5}
.tb-plan__kicker i,.tb-plan__meta i{flex:none;width:3px;height:3px;border-radius:50%;background:var(--tb-line-strong)}
.tb-plan__text{margin:0;max-width:60ch;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking);text-wrap:pretty}
.tb-page .tb-plan__rows{margin:0;padding:0;list-style:none;border-bottom:1px solid var(--tb-line)}
.tb-plan__row{display:grid;grid-template-columns:var(--sh-plan-col) minmax(0,1fr);gap:.6rem 2rem;align-items:center;padding:clamp(1.1rem,2.4vh,1.5rem) 0;border-top:1px solid var(--tb-line)}
.tb-plan__title{margin:0;color:var(--tb-ink-1);font-size:clamp(1.25rem,1.8vw,1.5rem);letter-spacing:-.02em;line-height:1.15}
.tb-plan__meta{display:flex;flex-wrap:wrap;align-items:center;gap:.4rem .7rem;margin:0;color:var(--tb-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);text-transform:uppercase;letter-spacing:var(--tb-mono-tracking)}
.tb-plan__row .tb-btn,.tb-plan__row .tb-link{justify-self:start}
@media (min-width:768px){
  .tb-plan__row{grid-template-columns:var(--sh-plan-col) minmax(0,1fr) auto}
  .tb-plan__row .tb-btn,.tb-plan__row .tb-link{justify-self:end}
}


/* ======== KONTAKTZEILE (.tb-contact) ========
   Hairline am Sektionsfuss: Satz links, Textlinks rechts (Telefon,
   WhatsApp, E-Mail als .tb-flow, Mittelpunkt als Trenner). Kanonisiert
   2026-09-07 mit dem zweiten Verwender (Standortseiten; davor Unikat
   .tm-book__contact der Terminseite). Kein Button: die Zeile ist der
   Weg fuer alle, die im Kalender keinen Slot finden. Unter 768
   stapelt sie (Mobil-Block). */
.tb-contact{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:1rem 2rem;margin-top:clamp(3rem,7vh,4.5rem);padding-top:clamp(1.2rem,2.5vh,1.65rem);border-top:1px solid var(--tb-line)}
.tb-contact__text{margin:0;max-width:44ch;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
.tb-contact__set{display:flex;flex-wrap:wrap;gap:.6rem 1rem;margin:0;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading)}
.tb-contact__set span{color:var(--tb-muted)}


/* ======== SEKTIONS-HUELLE ========
   Der vertikale Rhythmus variiert bewusst: identisches Padding
   ueberall war das staerkste Template-Signal der Vorgaengerversion.
   Zwei Stufen, Schritt und Luft, beide aus dem Sektionsrhythmus in
   tillit-tokens.css (seit 24.09.2026, Rhythmus-Studie "Mehr"). Bis
   dahin stand hier "der Rhythmus soll mit der Viewporthoehe atmen" -
   er atmet weiter, aber nur noch ueber einem Breitenboden: allein an vh
   bekam ein flaches Fenster bei gleicher Schrift 38 % weniger Luft, und
   der Mobilblock musste ab 767 mit einem Sprung gegenhalten. Die Rampe
   traegt jetzt alle Breiten, einen Mobilwert gibt es nicht mehr.
   --tb-surface haelt die eigene Flaechenfarbe der Sektion, damit
   Elemente, die sich in den Grund zurueckstanzen muessen, keine
   Farbe fest verdrahten. Aktuell ohne Abnehmer - der Zeitstrahl der
   Methode, der sich einmal in den Grund zurueckstanzte, ist erst der
   Typo-Treppe und dann dem Taktband gewichen, das mit Hairlines
   auskommt. Bleibt als Mechanik. */
.tb-section{--tb-surface:var(--tb-paper);padding:var(--tb-section-y) 0;background:var(--tb-surface)}
.tb-section--lift{--tb-surface:var(--tb-white)}
.tb-section--air{padding-block:var(--tb-section-y-air)}
.tb-section--ink{--tb-surface:var(--tb-ink);color:var(--tb-on-ink)}

/* ---- NAHTREGEL ----
   Gemessen wird an der Tinte, nicht an der Box: an einer SICHTBAREN
   Flaechenkante (Weiss/Ink) steht die letzte Tinte darueber so weit
   von der Kante wie die erste darunter. Vor dem 24.09.2026 schloss Ink
   mit vier verschiedenen Massen (Querverweiszeile 7vh, Sektion 12vh,
   Bild-Ink-Sektionen 16-17vh, Statement 17vh), Weiss oeffnete immer
   mit 12vh - an der Hub-Weiche 64 gegen 109 px, die Asymmetrie, die
   Max gesehen hat. Beide Seiten nehmen den GROESSEREN Schritt: die
   Naht gibt Luft dazu, sie nimmt keine weg. Gleichfarbige Folgen
   (Weiss auf Weiss, Ink auf Ink) haben keine sichtbare Kante und
   addieren wie bisher. Die Weiche und das Statement stehen hier mit,
   weil sie Ink-Flaechen ohne .tb-section sind; seit 25.09.2026 auch
   die Buehnenhuelle (.tb-stagehull) in der ersten Zeile - sie grenzt
   heute bei keinem Verwender an eine Luft-Sektion, die Zeile ist dort
   also stumm und steht fuer den naechsten. Seitenlokale Ink-
   Flaechen tragen die Regel in ihrer Seite: der Einsatzort der
   Startseite grenzt unten an eine Luft-Sektion und rechnet seinen Fuss
   dort selbst (.sh-terrain); .bp-fit (Beratung) grenzt heute an keine
   und bekommt die Zeile erst, wenn sich das aendert. */
:is(.tb-section--ink,.tb-weiche,.tb-stagehull):has(+ .tb-section--air:not(.tb-section--ink)){padding-bottom:var(--tb-section-y-air)}
:is(.tb-statement,.tb-section--air.tb-section--ink) + .tb-section:not(.tb-section--ink){padding-top:var(--tb-section-y-air)}
.tb-section:not(.tb-section--ink):has(+ :is(.tb-statement,.tb-section--air.tb-section--ink)){padding-bottom:var(--tb-section-y-air)}
.tb-section--air:not(.tb-section--ink) + :is(.tb-section--ink,.tb-weiche){padding-top:var(--tb-section-y-air)}

/* ---- BILDKANTE ----
   Vor einer randlosen Bildbuehne arbeitet Weiss nicht: das Bild bringt
   seine Kante selbst mit. Bis 24.09.2026 galt dort mobil 38 px (vier
   Seitenregeln im Mobilblock), ab 768 der volle Schritt - ein Sprung
   von bis zu 73 %. Jetzt EINE Breitenrampe ohne Fensterhoehe, 2.7rem
   bei 390; gedeckelt vom Schritt, den sie bei normaler Hoehe ab rund
   710 px Breite erreicht (Luft ab rund 1085 px; in flachen Fenstern
   frueher, weil der Schritt dort kleiner ist). Dieselbe Rampe fuehrt
   vom Hero ins Statement: das Bild laeuft in Ink aus (--into-ink), die
   Kante ist dort ebenfalls Bild. Das gilt jetzt auf allen zehn Hero-
   Seiten mit Statement; vorher trugen vier die Mobilnaht einzeln, sechs
   (AMFLOW-Familie, Atherton, Pivot) fuhren mobil mit 84 statt 38 px.
   Die Buehne erkennt die Regel an der Kanonklasse .tb-stage--foto:
   als Sektion selbst (AMFLOW PX) oder als erste Zeile der naechsten
   Sektion - so beginnen die Bild-Ink-Sektionen der Seiten (die
   Buehnenhuelle .tb-stagehull und .bp-fit). Deshalb braucht keine
   Seite eine eigene :has()-Zeile mehr (vorher vier Kopien im
   jeweiligen Mobilblock). Die Regel sieht nur die erste Zeile, nicht
   das Polster: alle setzen oben 0. Beginnt eine Sektion mit einer
   Foto-Buehne UNTER einem Oberpolster, ist ihre Kante Weiss und die
   Regel nimmt dem Vorgaenger trotzdem den Fuss - dann padding-top 0
   oder eine andere erste Zeile. Die Naht-Pseudoelemente des Heros
   (::before/::after der Folgeflaeche) haengen an der Oberkante, das
   Polster verschiebt sie nicht. */
.tb-section:has(+ .tb-stage--foto,+ * > .tb-stage--foto:first-child){padding-bottom:clamp(2.7rem,18.42vw - 2.431rem,var(--tb-section-y))}
.tb-section--air:has(+ .tb-stage--foto,+ * > .tb-stage--foto:first-child){padding-bottom:clamp(2.7rem,18.42vw - 2.431rem,var(--tb-section-y-air))}
.tb-hero--into-ink + .tb-statement{padding-top:clamp(2.7rem,18.42vw - 2.431rem,var(--tb-section-y-air))}

/* Eyebrow in Mono/Versalien statt Gold. Sie laeuft dunkel, nicht
   gedimmt: Schnitt, Versalien und Sperrung trennen sie schon deutlich
   genug von der Aussage - eine zusaetzliche Farbstufe hat sie nur
   schwach und beilaeufig wirken lassen. */
/* GELOESTE DRIFT (2026-08-23): margin-bottom stand auf den beiden
   Referenzseiten auf verschiedenen Werten — Startseite 4.5vh,
   Beratungsprozess 3vh, Faktor 1,46 bei gleicher Klasse.
   ENTSCHIEDEN: ein Wert fuer beide, 4.5vh. Drei Sektionskoepfe des
   Beratungsprozesses ruecken damit von 27 auf 40,5 px — bewusst.
   Instanzen mit eigenem Abstand (.bp-statement, .bp-fit__stage-inner)
   behalten ihren; das sind Kompositionen, keine Drift. */
.tb-index{display:flex;align-items:center;gap:.7rem;margin-bottom:clamp(1.9rem,4.5vh,3.2rem);color:var(--tb-ink-1);font-family:var(--tb-mono);font-size:.82rem;font-weight:400;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking)}
.tb-index--ink,.tb-section--ink .tb-index{color:var(--tb-white)}
.tb-head{margin:0 auto;text-align:center}
.tb-head .tb-index{justify-content:center}
.tb-head--split{max-width:none;text-align:left}
.tb-head--split .tb-index{justify-content:flex-start}
/* 400er Schnitt, enge Laufweite, Zeilenabstand knapp ueber 1. */
.tb-head__title{max-width:64rem;margin:0 auto;color:var(--tb-ink-1);font-size:clamp(2.3rem,5.2vw,4.4rem);font-weight:400;letter-spacing:-.035em;line-height:1.0;text-wrap:balance}
.tb-head--split .tb-head__title{max-width:18ch;margin:0}
/* Die Werte hier waren bis 2026-08-24 zur Haelfte TOT: beide Seiten
   ueberschrieben Rampe, Durchschuss und Farbe im Typo-Overlay
   (.tb-page .tb-head__text, 0,2,0) mit den Token-Werten. Jetzt traegt
   der Kanon die WIRKSAMEN Werte und die Overlays sind gefallen. */
.tb-head__text{max-width:44rem;margin:1.6rem auto 0;color:var(--tb-copy-ink);font-size:var(--tb-lead-size);font-weight:var(--tb-copy-weight);line-height:var(--tb-lead-leading);letter-spacing:var(--tb-lead-tracking)}
.tb-head--split .tb-head__text{max-width:34rem;margin:1.6rem 0 0}
.tb-section--ink .tb-head__title{color:var(--tb-white)}
.tb-section--ink .tb-head__text{color:var(--tb-copy-on-ink)}
/* Ab 768 wird der Split-Kopf ein Zweispalter: Titel links, Text
   rechts, beide auf der Grundlinie. margin-left:auto schiebt den
   Textblock an die RECHTE Kante seiner Spalte - ohne das klebte er
   bei rund 53 % Sektionsbreite und liesse rechts einen breiten
   Streifen leer: weder Mitte noch Rand, ein Block im Niemandsland.
   Kante gegen Kante ist die Spannung des Kopfes; dieselbe Logik wie
   der Fliesstext im Statement des Beratungsprozesses.

   Stand bis 2026-08-26 zeichengleich DREIFACH in den Seiten
   (Kanonseiten-Audit F4); der Beratungsprozess fuhr dabei ohne
   margin-left:auto - diese Drift traegt er jetzt als benannte
   Ausnahme in seinem <style>, bis sie entschieden ist. */
@media (min-width:768px){
  .tb-head--split{display:grid;grid-template-columns:1.05fr .95fr;gap:3rem;align-items:end}
  .tb-head--split .tb-head__text{margin-top:0;margin-left:auto}
  /* --feature: der Split-Kopf UEBER einer Bild-Text-Zeile nimmt deren
     Raster (50/50, gleiche Luecke) und setzt den Text an die linke
     Kante der zweiten Spalte - Kopftext und Zeilentext stehen dann auf
     einer Flucht. Ohne den Modifier sass der Kopftext rechtsbuendig in
     einer 1.05/.95-Spalte und sprang gegenueber dem Zeilentext um rund
     180 px (Befund Max am AMFLOW-Hub, 06.09.2026). KANONISIERT mit dem
     sechsten Verwender: vier AMFLOW-Seiten und die zwei Zeilen der
     Atherton-Seite. */
  .tb-head--feature{grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(2.5rem,5vw,4.5rem)}
  .tb-head--feature .tb-head__text{margin-left:0}
}
/* Mobil faellt der Kicker der Zeile unter einem --feature-Kopf (seit
   30.09.2026, Befund Max an Orbea MyO: "nicht klar, was zu was
   gehoert"). Einspaltig stand er nach dem Bild wie der Anfang einer
   neuen Sektion, das Bild hing zwischen zwei Koepfen. Ohne ihn lesen
   Bild, Zeilentitel und Text als eine Einheit unter dem Sektionskopf;
   der Kopf-Kicker nennt das Thema schon. Ab 768 bleibt er: dort steht
   er in der rechten Spalte auf einer Flucht mit dem Kopftext.
   13 Verwender, alle mit der Zeile direkt nach dem Kopf und dem Kicker
   als erstem Kind des Zeilenkoerpers. */
@media (max-width:767px){
  .tb-head--feature + .tb-feature .tb-feature__body > .tb-index:first-child{display:none}
}

/* ---- RIESE (Modifier --xl) und die Buehnenhaut ----
   Der Riesengrad ist der vorhandene Buehnengrad (109,9 px bei 1440,
   40,6 bei 390), er verliert nur die Voraussetzung Bild (Entscheidung
   Max 20.09.2026, Copy-Durchgang: hoechstens EIN Riese je Seite, der
   Buehnenriese zaehlt mit, ein Riese traegt nie einen Lead, Titel bis
   26 Zeichen; Copy-Konventionen Abschnitt 13). Keine vierte Display-
   Stufe: zwischen 61,6 und 109,9 waere nichts mehr rankbar.

   Bis 20.09.2026 hiess der Modifier --stage und trug Grad UND Haut
   (weiss, Schatten, Umbruch) in einer Klasse; die Haut haengt jetzt an
   der Komposition (.tb-stage__head), der Grad am Modifier. Die fuenf
   Bestandsverwender (beratung, leasing, amflow-px, startseite, tillit)
   tragen --xl und sehen bei 390/768/1440 gleich aus; zwei benannte
   Deltas: 541-767 px laeuft der Grad stetig statt eingefroren (die
   42-Prozent-Kante bei einem Pixel — 41,3 px bis 767, 58,75 ab 768 —
   ist dieselbe Pathologie, die der Schriftstufen-Kanon am 18.09. an
   der 1920er Stufe abgeschafft hat), und die Laufweite unter 768 ist
   -.04em statt -.035em (5,7 px auf 28 Zeichen).

   Der Grad kommt aus --tb-display-size (tillit-tokens.css), das bis
   heute ohne Verwender war; die Kurve dort ist die alte Mobil-Rampe
   und die alte 768er-Rampe in EINEM clamp/max/min. Die doppelte Klasse
   (0,2,0) schlaegt den spaeter stehenden Mobilblock ohne eigene Media
   Query. text-align:center kommt vom Kanon-Kopf (.tb-head) bzw. von
   .tb-stage__head-inner ab 768 — die frueher hier gesetzte Zentrierung
   war tot.

   Haut der Buehne: unter 768 links, 15ch, mit Oberabstand, text-wrap:
   wrap (die Kanon-Basis traegt balance, der Buehnenkopf unter 768 im
   Bestand NICHT — ohne die Neutralisierung braechen mobile
   Buehnentitel anders um); ab 768 zentriert ueber der vollen Buehne.
   Die Rampen sind an Inter gemessen (Gate A: nach dem Schriftwechsel
   nachmessen); die Mobil-Leiter (Faktor 1,41 zum Sektionskopf) ist im
   Typo-Staffelungs-Kommentar der Startseite hergeleitet. */
.tb-head__title.tb-head__title--xl{max-width:none;font-size:var(--tb-display-size);letter-spacing:-.04em}
.tb-head--xl .tb-index{margin-bottom:clamp(1.2rem,2.6vh,1.8rem)}
.tb-stage__head .tb-head__title{margin:1.3rem 0 0;max-width:15ch;color:var(--tb-white);text-shadow:0 2px 40px rgba(15,15,15,.45);text-wrap:wrap}
@media (min-width:768px){
  .tb-stage__head .tb-head__title{max-width:none;margin:0;text-wrap:balance}
}

/* ---- ZEILE (Modifier --zeile) ----
   Das vierte Register (Copy-Konventionen Abschnitt 13, Entscheidung
   Max 20.09.2026 mit der Budget-Anhebung css-ende 38000 -> 38500):
   der Kopf einer DIENSTFLAECHE - FAQ, Shop-Teaser, Galerie, Adresse,
   alles, was man sucht statt liest. Bis dahin behaupteten diese
   Sektionen mit Kicker + 61,6-px-Titel + 20-Wort-Lead denselben Rang
   wie das Kernargument; gegen die Monotonie hilft nicht ein Kopf
   mehr, sondern einer weniger. Eine Zeile: Kicker links, Titel rechts,
   auf der Grundlinie, Hairline darunter - nie ein Lead.

   Kein neuer Grad, kein neues clamp, kein neuer Abstand: Geometrie
   und Polster sind die des Fahrplan-Kopfs (.tb-plan__head, Spalte
   clamp(10rem,24vw,22rem)), der Grad ist --tb-row-size (29,4 px bei
   1440, 21 bei 390 - der Zeilengrad der Statement-Vorzeile und der
   Bild-Text-Zeile). Der Kanon-Kopf wickelt Kicker und Titel in ein
   inneres <div>; display:contents hebt es ins Raster, damit ein
   Registerwechsel ein Klassenwechsel bleibt und kein Umbau. Unter 768
   stapelt die Zeile zwingend (Mobilblock, Beitritt zur Fahrplan-Regel):
   bei 390 blieben neben der Kickerspalte sonst 10 Zeichen je Titelzeile.
   Titel bis 34 Zeichen; der Deckel gilt in copy-budgets.json. */
.tb-head--zeile{display:grid;grid-template-columns:clamp(10rem,24vw,22rem) minmax(0,1fr);gap:.6rem 2rem;align-items:baseline;max-width:none;padding-bottom:clamp(1rem,2.2vh,1.4rem);border-bottom:1px solid var(--tb-line);text-align:left}
.tb-head--zeile>div{display:contents}
.tb-head--zeile .tb-index{justify-content:flex-start;margin-bottom:0}
.tb-head--zeile .tb-head__title{max-width:none;margin:0;font-size:var(--tb-row-size);letter-spacing:-.025em;line-height:1.15;text-wrap:pretty}
.tb-section--ink .tb-head--zeile{border-color:var(--tb-line-ink)}

/* ---- RIESE IN DER ZEILE (Katalogkopf, Entscheidung Max 27.09.2026) ----
   Canvas "Katalogkopf E-City", Runde 2: Max fand die Zeile (C) und den
   Riesen (D) am staerksten, Richtung E nimmt die Geometrie der Zeile und
   den Grad des Riesen. Erster Verwender ist der Kopf der Blattkategorien
   (Thementext 1, pages/kategorie/e-city.html): Kicker ueber der
   Filterspalte, Riese ueber dem Sortiment, Hairline - die Spuren dazu
   stehen in tillit-shop-dom.css (KOPF DER BLATTKATEGORIE).
   Vom Riesen kommen nur Grad, Laufweite und Durchschuss; Spalten,
   Grundlinie und Hairline bleiben die der Zeile. Die Riesen-Regeln gelten
   unveraendert: kein Lead, Titel bis 26 Zeichen, einer je Seite
   (Copy-Konventionen 13). Gleiches Gewicht wie die Titelregel der Zeile
   (0,2,0) - die Regel gewinnt ueber die Reihenfolge und muss deshalb
   HINTER ihr stehen. */
.tb-head--zeile .tb-head__title--xl{font-size:var(--tb-display-size);letter-spacing:-.04em;line-height:1}


/* Erste Sektion einer flachen Seite (.tb-page--flat, Kopfzeile im
   Fluss, tillit-shop-header-v2.css Abschnitt 7): keine Buehne davor,
   deshalb weniger Luft oben als eine Kanon-Sektion, die auf eine
   andere folgt. Strukturregel statt Klasse - Kanon seit 07.09.2026
   (davor .tm-book der Terminseite; Verwender: Termin, Standorte,
   Sasbach, Gernsbach). Der Sprite-<svg> davor ist keine section.
   Seit 24.09.2026 ein Anteil des Schritts (.55, 68 px bei 1440x900)
   mit Boden 4.2rem: als reines 7vh lag der Wert bei 560 px
   Fensterhoehe auf 42 px, weniger als der Kopfabstand darunter. */
.tb-page--flat > .tb-section:first-of-type{padding-top:max(4.2rem,calc(var(--tb-section-y) * .55))}


/* ======== KREIS-BADGE (A/B/C) ========
   Das Aufzaehlungszeichen des Hauses. Ersetzt Checkmarks — die gibt es im
   System nicht (69 stecken noch in den Altseiten und fallen mit deren Port).

   GEOMETRIE. Der Kreis ist 2.34em der Badge-Schrift, der Buchstabe steht
   mittig darin. Beide Werte stammen aus dem Bestand und sind nicht neu
   erfunden.

   DIE ZAHL, entschieden 2026-08-23. Bis dahin liefen die beiden Instanzen
   auseinander: Startseite 31,48 px, Beratungsprozess 26,80 px — 17,4 %,
   obwohl der Kommentar auf der Startseite Paritaet behauptete. Ursache war
   kein Designwunsch, sondern ein stiller Bruch: der Beratungsprozess koppelt
   den Badge relativ an seine Zeile (.62em), und eine spaetere Regel
   (beratung/index.html) zog die Zeile auf --tb-proof-size herunter — der
   Badge folgte mit, die Startseite mit ihrer hart einkopierten Rampe nicht.

   Entschieden ist die groessere Fassung mit Deckel: 30 px. Der Deckel steht
   als Rechnung da (30px / 2.34), damit ablesbar bleibt, dass er den KREIS
   meint und nicht die Schrift.

   DER PREIS, offen benannt: ein fester Badge ist nicht mehr an seine Zeile
   gekoppelt. Auf dem Beratungsprozess war der Kreis vorher exakt so hoch wie
   die Zeile (1.45 x 18,48 = 26,80) und sass bei align-items:start ohne jeden
   Versatz richtig. Das ist mit 30 px vorbei — beide Instanzen brauchen jetzt
   einen Ausgleich.

   --sh-badge-lift ist dieser Ausgleich und MUSS von der Instanz kommen:
   die Zeilenhoehe haengt am Elternelement, und CSS kann sie nicht lesen.
   Formel: (Zeilenhoehe - Kreishoehe) / 2, negativ. Default 0 fuer den Fall,
   dass beide gleich hoch sind.

   GATE A: font-weight steht hier noch, weil der Reset in L1 (tillit-base.css)
   noch nicht existiert. Faellt mit dessen Bau ersatzlos. */
.tb-badge{
  box-sizing:border-box;
  display:inline-grid;
  place-items:center;
  width:2.34em;
  height:2.34em;
  margin-top:var(--sh-badge-lift,0px);
  border:1px solid var(--tb-line);
  border-radius:50%;
  color:var(--tb-ink-1);
  font-family:var(--tb-mono);
  font-size:min(calc(.62 * clamp(1.2rem,1.85vw,1.55rem)),calc(30px / 2.34));
  font-weight:400;
  letter-spacing:var(--tb-mono-tracking);
}
/* Ink ist der Modifier, nicht die Grundform — dieselbe Richtung wie
   .tb-section--ink und .tb-index--ink. Beide heutigen Verwender stehen
   auf Ink; kuenftige auf den weissen Produktseiten nicht. */
.tb-badge--ink{border-color:var(--tb-line-ink);color:var(--tb-on-ink)}


/* ======== AUSSAGENBAND (Belege) ========
   Eine Menge gleichrangiger Aussagen: Label klein in Mono, die Behauptung
   gross darunter. ENTSCHIEDEN 2026-08-23: keine Ordnungszahl — die
   Nummern der Altfassungen (.rgk-proof__num "01" in Gold/800,
   .tillit-kpi__number) waren Artefakte des alten Looks, die Aussagen sind
   eine Menge und keine Folge, und der Kreis mit Zeichen gehoert bereits
   .tb-badge. Behauptung-gross ist das Grundregister: bei den kuenftigen
   KPI-Ports wandert der WERT ("Ab 20,6 kg") in die grosse Zeile, die
   alte Schmucknummer faellt.

   Die Sektionshuelle ist KEINE eigene Klasse: das Band liegt auf
   .tb-section --air --ink (die fruehere .sh-proof-Huelle war Deklaration
   fuer Deklaration identisch damit, auch mobil).

   .tb-page als Panzer auf der Gridregel, mit Grund: der Listen-Reset der
   Seiten (.tb-page ul, 0,1,1) schluege ein nacktes .tb-proof (0,1,0) und
   naehme ihm den margin-top.

   Farben folgen dem Grund wie bei .tb-head: Basis fuer Weiss,
   .tb-section--ink hebt sie um.

   GATE A: die .78rem des Kickers sind einer der neun Mono-Grade und
   werden nach dem Schriftkauf mit den anderen konsolidiert — bis dahin
   traegt er seinen Bestandswert. */
.tb-page .tb-proof{display:grid;grid-template-columns:1fr;gap:clamp(2.4rem,6vh,3.6rem) clamp(3rem,7vw,6rem);margin-top:var(--tb-head-gap)}
.tb-proof__kicker{display:block;margin:0 0 .85rem;color:var(--tb-ink-1);font-family:var(--tb-mono);font-size:var(--tb-font-label,.78rem);font-weight:400;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking)}
.tb-section--ink .tb-proof__kicker{color:var(--tb-white)}
.tb-proof__text{max-width:46rem;margin:0;color:var(--tb-copy-ink);font-size:var(--tb-proof-size);font-weight:var(--tb-copy-weight);line-height:1.45;letter-spacing:var(--tb-copy-tracking)}
.tb-section--ink .tb-proof__text{color:var(--tb-copy-on-ink)}
@media (min-width:768px){
  .tb-page .tb-proof{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (min-width:1024px){
  .tb-page .tb-proof{gap:clamp(3rem,7vh,4.5rem) clamp(3.5rem,8vw,7rem)}
}


/* ======== ZITAT AUF INK ========
   Der Display-Moment des Systems: <blockquote> mit dem
   Anfuehrungszeichen-Glyph, mittig auf einem Lichtfeld. Beide
   Referenzseiten trugen es deklarationsgleich bis auf zwei Punkte,
   beide 2026-08-23 entschieden:

   1. DIE RAMPE lief 11 % auseinander (Startseite 3.2vw/2.7rem-Deckel,
      Beratungsprozess 3.6vw/3rem). Nirgends war ein Grund dokumentiert —
      unabhaengiges Feintuning, keine Absicht. Kanon ist die groessere
      Fassung: das Zitat ist beim Beratungsprozess das Zentrum einer
      eigenen Sektion, sie zu schrumpfen haette den staerksten Moment der
      Seite geschwaecht. Die Startseite waechst um 11 %.

   2. KEIN BORDER-RADIUS. Der Bestandskommentar sagte woertlich "die
      Flaeche soll als Lichtfeld lesen, nicht als Karte — deshalb auch
      kein border-radius", und die Zeile darunter setzte einen. Der
      Kommentar gewinnt: er deckt sich mit der Systemregel (Flaechen
      statt Karten), die 7px auf einem 62rem-Panel waren ohnehin kaum
      wahrnehmbar.

   INSTANZKNOEPFE, beide mit Grund:
   --sh-quote-top      Abstand nach oben — haengt davon ab, was ueber dem
                       Zitat steht, kann nur die Seite wissen.
   --sh-quote-measure  Zeilenbreite in ch — an den konkreten Zitattext
                       angepasst (26ch Startseite, 24ch Default).

   p und cite laufen als semantische Kinder des blockquote, wie im
   Bestand — ein <cite> ist optional (Personenzitat gegen
   Markenstatement ist Markup-Sache, kein Modifier).

   Nur fuer Ink-Gruende gebaut: das Lichtfeld ist eine Weiss-Aufhellung
   und existiert auf Papier nicht. Ein Weiss-Zitat waere eine neue
   Entscheidung, kein Modifier.

   GATE A: die .78rem des cite sind einer der neun Mono-Grade
   (identisch mit .tb-proof__kicker) und werden nach dem Schriftkauf
   konsolidiert. */
.tb-quote{max-width:62rem;margin:var(--sh-quote-top,clamp(4.5rem,12vh,8rem)) auto 0;padding:clamp(3rem,6.5vw,5.5rem) clamp(2rem,5vw,4.5rem);background:rgba(255,255,255,.045);text-align:center}
.tb-quote__mark{display:block;width:clamp(42px,5.4vw,68px);height:auto;margin:0 auto clamp(1.8rem,3.6vh,2.8rem);color:var(--tb-white)}
.tb-quote p{max-width:var(--sh-quote-measure,24ch);margin:0 auto;color:var(--tb-white);font-size:var(--tb-statement-size);font-weight:400;letter-spacing:-.028em;line-height:1.24;text-wrap:balance}
.tb-quote cite{display:block;margin-top:clamp(1.6rem,3.4vh,2.4rem);color:var(--tb-on-ink-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label,.78rem);font-style:normal;font-weight:400;letter-spacing:var(--tb-mono-tracking);text-transform:uppercase}


/* ======== BUTTON (Designsystem "Button") ========
   Pille in Satzschrift mit rundem Pfeil-Chip. Der Hover passiert nur
   im Chip: der Pfeil faehrt nach rechts raus, ein zweiter kommt von
   links nach. Zusaetzlich rollt das Label mit - Schrift nach oben
   raus, Kopie von unten nach, dieselbe Kurve, dieselbe Dauer wie der
   Pfeil. Damit bewegt sich der Button als EINE Geste. Die Kopie ist
   aria-hidden, der Button wird also einmal vorgelesen.
   Der Chip waechst dabei auf 1.06, bei 34 px rund 2 px: er laedt ein,
   und 1,06 ist die Obergrenze der Lautstaerke-Regel fuer das Element
   selbst (Motion-System, Entscheidung Max 2026-09-24).
   Varianten:
     primary   dunkle Flaeche, goldener Chip   -> Standard, auch auf Foto
     secondary weisse 2px-Kontur, weisser Chip -> nur auf Foto/dunklem Band
     white     weisse Flaeche, goldener Chip   -> nur im dunklen CTA-Band
   Die Pfeilform liegt einmalig als <symbol> am Anfang von .tb-page
   und MUSS mit nach e-vendo, sonst bleiben die Chips leer.
   Die Flaeche fuehrt #0f0f0f, denselben Wert wie --tb-ink. */
/* --tb-btn-ease / --tb-btn-drop sind KOMPONENTEN-LOKAL, keine Token:
   sie stehen auf der Komponente, nie auf der Wurzel (die Token-SSOT
   bleibt tillit-tokens.css, Pruefung 7 bewacht genau das). Bis zum
   2026-08-27 hiessen sie --tb-ease und --tb-drop - Namen, die sich
   wie Wurzel-Token lesen, neben --tb-ease-entry/-snap/-state in der
   SSOT stehen und dort nicht zu finden waren. Der Name sagt jetzt,
   wem sie gehoeren. */
.tb-page a.tb-btn{--tb-btn-ease:cubic-bezier(0.76,0,0.24,1);--tb-btn-drop:cubic-bezier(0.625,0.05,0,1);display:inline-flex;align-items:center;justify-content:center;gap:.86rem;padding:.36rem .36rem .36rem 1.43rem;border-radius:50px;font-family:inherit;font-size:1rem;font-weight:400;letter-spacing:-.005em;text-transform:none;text-decoration:none;cursor:pointer;transition:background-color .45s var(--tb-btn-ease),border-color .45s var(--tb-btn-ease),color .45s var(--tb-btn-ease)}
.tb-btn__chip{position:relative;flex:none;width:2.43rem;height:2.43rem;border-radius:50%;overflow:hidden;transition:transform .45s var(--tb-btn-ease),background-color .45s var(--tb-btn-ease),color .45s var(--tb-btn-ease)}
.tb-btn:hover .tb-btn__chip,.tb-btn:focus-visible .tb-btn__chip{transform:scale(1.06)}
.tb-btn__arrow{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;transition:transform .45s var(--tb-btn-ease)}
.tb-btn__arrow--next{transform:translateX(-160%)}
.tb-btn:hover .tb-btn__arrow,.tb-btn:focus-visible .tb-btn__arrow{transform:translateX(160%)}
.tb-btn:hover .tb-btn__arrow--next,.tb-btn:focus-visible .tb-btn__arrow--next{transform:translateX(0)}
.tb-btn__ico{width:.95rem;height:.95rem}
/* Label-Drop: Die zweite Textkopie ist der eigene text-shadow jedes
   Buchstabens, 3em ueber ihm in currentcolor. Beim Hover faellt der
   Buchstabe 3em nach unten aus dem Fenster, der Schatten landet exakt
   an seiner Stelle. Die Welle ist auf 90ms Gesamtlaenge normiert
   (Index/Anzahl), damit lange Labels genauso schnell durchlaufen wie
   kurze. Kerning aus, weil die einzelnen Buchstaben-Spans es ohnehin
   brechen wuerden. Zerlegt wird das Label einmalig in initBtnLabels();
   ohne JS steht schlicht der Text und nichts rollt.

   Der Span hiess bis zum 2026-08-27 schlicht .letter und war damit der
   EINZIGE praefixlose Klassenname des Systems - auf einem DOM, in dem
   das Werk 75 eigene, ebenso generisch benannte Custom Properties
   fuehrt (--primary, --outline, --disabled). --tb-char-i/-n sind aus
   demselben Grund umbenannt: element-lokal, per JS gesetzt, aber
   trotzdem unsere. */
.tb-btn__label{position:relative;display:inline-block;overflow:hidden;vertical-align:bottom;font-feature-settings:'kern' 0}
.tb-btn__label .tb-btn__letter{display:inline-block;white-space:pre;text-shadow:currentcolor 0 -3em;transition:transform .4s var(--tb-btn-drop);transition-delay:calc(var(--tb-char-i)/var(--tb-char-n,13)*90ms)}
/* will-change erst beim Hover: dauerhaft gesetzt promotet es jeden
   einzelnen Buchstaben auf eine eigene Ebene und schaltet damit das
   Subpixel-Antialiasing ab - die Labels rendern duenner als der
   umgebende Satz, ohne dass je gehovert wurde. */
.tb-btn:hover .tb-btn__label .tb-btn__letter,.tb-btn:focus-visible .tb-btn__label .tb-btn__letter{will-change:transform;transform:translateY(3em)}
/* .tb-page a{color:inherit} ist spezifischer, daher jede Variante ueber .tb-page. */
/* EINE BUTTONSTIMME (Entscheidung 2026-09-05, Canvas "TilliT Button"):
   Die Pille war 53px hoch fuer 14px Schrift (3,8:1) - Chip 36px mit
   6,3px Luft, dazu 2px Rand in Buttonfarbe, also drei Ringe, die Masse
   und keine Kante brachten. Neu 44px: Chip 2.43rem (34px) buendig mit
   .36rem (5px) Luft, links 1.43rem (20px), kein Rand mehr.

   --white, --secondary und --ghost sind gestrichen: der Ink-Button
   spielt auf Weiss, Foto UND Ink. Die leise Zweithandlung ist
   .tb-link (unten), nicht eine zweite Pille. Auf Ink-Sektionen
   (Startseite .sh-terrain) traegt allein der Chip die Kante - eine
   Hairline innen wurde getestet und am 2026-09-05 verworfen. */
.tb-page a.tb-btn--primary{background:#0f0f0f;border:0;color:var(--tb-white)}
.tb-btn--primary .tb-btn__chip{background:var(--tb-action);color:#0f0f0f}
/* Textlink mit Pfeil - die leise Variante des Buttons. Seit 2026-08-19
   MIT stehendem Unterstrich: Geometrie und Feder wie die Links im
   Footer-V2 (1px currentColor, bottom .15em, transform-Slide mit
   .35s cubic-bezier(.22,.61,.36,1)), aber invertiert - die Linie steht
   im Ruhezustand, verschwindet beim Hover nach rechts (origin right,
   scaleX 0) und kommt beim Verlassen von links zurueck. Der Pfeil
   faehrt dabei weiter nach rechts. Gilt fuer beide Varianten.
   Fliesstext-Links fahren seit dem 2026-08-24 die VERLAUFS-Feder
   (background-Gradient mit box-decoration-break:clone, eine Linie je
   Zeilenfragment) — die ::after-Feder kann auf umbrechenden Links
   nicht arbeiten. Einziger Verwender: .sh-trust__text a auf der
   Startseite; wird zur Kanon-Feder --flow, sobald eine zweite Stelle
   sie braucht. */
/* PHASE-3-KANDIDAT: Diese Rolle heisst auf dem Beratungsprozess
   .bp-fit__partner-link und ist dort deklarationsgleich bis auf gap
   (.45 statt .55rem), letter-spacing:0 und die Farbquelle. Wird zu
   .tb-link zusammengefasst.
   Seit dem 2026-08-24 laeuft die Rolle auf 400 (Entscheidung Max,
   vorgezogen aus Gate A): sie war der einzige Nicht-400-Wert des
   Systems. Betonung traegt die Rolle ueber den 22px-Chevron im
   Hairline-Kreis und den stehenden Unterstrich, nicht ueber das
   Gewicht — die Gewichtsregel gilt damit schon unter Inter. */
/* Die Feder-Geometrie kommt seit dem 2026-08-24 aus dem Block
   UNTERSTRICH-FEDER unten; hier stehen nur noch Element, Aussparung
   (--sh-underline-inset) und der Hover des stehenden Registers. */
/* text-decoration:none ist seit dem Flotten-Port Pflicht in der
   Basis: die Werks-CSS unterstreicht Links nativ, und auf der
   Flottenkarte standen dadurch ZWEI Linien uebereinander — die
   native Dekoration und die Feder. Die Referenzseiten sahen das
   nie, weil ihre Seitenbloecke die Dekoration global abraeumen. */
.tb-link{position:relative;display:inline-flex;align-items:center;gap:.55rem;font-size:1rem;font-weight:400;text-decoration:none;--sh-underline-inset:calc(22px + .55rem)}
/* FARBE MIT PANZER, korrigiert 2026-09-04 (Gegenlesen der Ueber-uns-
   Seite): der Linkreset der Basis (.tb-page a{color:inherit}, 0,1,1)
   ist spezifischer als die nackte Klasse - die Farbe stand hier seit
   der Kanonisierung, wirkte aber nie. Die Feder erbte stattdessen die
   Sektionsfarbe: auf Ink .8 statt Weiss, also leiser als der
   Fliesstext daneben (.94), auf Weiss #292929 statt #111. Dieselbe
   Falle und dieselbe Loesung wie bei .tb-flow und den
   Button-Varianten. Auf der Startseite blieb sie unsichtbar, weil ihr
   Ink-Fliesstext selbst auf .8 laeuft. */
.tb-page a.tb-link{color:var(--tb-ink-1)}
.tb-link:hover::after{transform:scaleX(0);transform-origin:right}
/* Chevron im Kreis statt Schaft-Pfeil (2026-08-19): 22px-Chip mit
   Hairline, innen die grosse likova-Fassung ohne Schaft. Der
   Unterstrich endet vor dem Chip (right-Offset = Chipbreite + gap).
   Bis zum Testbikeflotte-Port (2026-08-24) trug die BASIS die
   Ink-Hairline — beide damaligen Instanzen standen auf Ink und
   fuehrten den --ink-Modifier ohnehin. Jetzt gilt die Regel-Logik
   der uebrigen Komponenten: Basis fuer helle Flaechen, --ink legt
   die Weiss-Hairline darueber. */
/* PORTABILITAETSFEHLER, behoben 2026-08-23: hier stand var(--sh-ease).
   --sh-ease ist ein INSTANZWERT und steht nirgends auf :root — nur auf
   .tb-page der drei Seiten, die ihn selbst setzen. Eine Kanon-Komponente
   darf keinen Instanzwert lesen: auf jeder kuenftigen Seite, die .tb-link
   benutzt ohne --sh-ease zu deklarieren, waere die transition still
   ausgefallen. Der Alias zeigt ohnehin auf --tb-ease-state. */
.tb-link svg{box-sizing:border-box;width:22px;height:22px;padding:5px;border:1px solid var(--tb-line-strong);border-radius:50%;flex:none;transition:transform .35s var(--tb-ease-state)}
.tb-link:hover svg{transform:translateX(4px)}
.tb-page a.tb-link--ink{color:var(--tb-white)}
.tb-link--ink svg{border-color:var(--tb-line-ink)}
/* ======== UNTERSTRICH-FEDER ========
   ZEHN wortgleiche Kopien auf eine — Kanonisierung 2026-08-24. Die
   Geometrie jeder Linie unter einem Wort, ein einziges Mal:

     bottom = 50% - Fontkonstante - Design-Knopf
     (Herleitung in tillit-tokens.css, Abschnitt Unterstrich-Konvention)

   SELEKTORLISTE STATT KLASSENPFLICHT, mit Grund: vier Fundorte liegen
   auf Werks-DOM (#topnav, #Header, #Footer, Login), drei auf
   Drawer-Markup, das js/tillit/tillit-nav.js im Shop erzeugt. Alle
   Zieldateien landen im selben Backend-Feld "CSS - Ende" — die Liste
   hier ist kaskadisch identisch mit den frueheren Kopien, jeder
   Selektor behaelt seine Spezifitaet, kein Markup wurde angefasst.

   ZWEI REGISTER:
   - Grundregister "kommt": ruhend scaleX(0)/origin right, der Trigger
     der jeweiligen Stelle faehrt sie mit scaleX(1)/origin left von
     links ein. Die Trigger bleiben bei ihren Stellen — sie sind echt
     verschieden (a:hover, li:hover > a, .row:hover .label, .active).
   - Stehendes Register (Override darunter): .tb-link und
     .sh-split__link ruhen auf scaleX(1)/origin left, der Hover laesst
     die Linie nach rechts hinauslaufen.

   --sh-underline-inset ist der eine Instanzknopf: die Aussparung fuer
   den Chevron-Chip (right-Offset = Chipbreite + gap). Custom Properties
   erben ans ::after; Default 0 fuer die Fundorte ohne Chip. Die
   Chipbreite ist bewusst KEIN :root-Token — sie ist ein Instanzwert
   der jeweiligen Komponente.

   Kurve und Dauer kommen aus den Tokens (--tb-ease-state/--tb-dur-state)
   statt zehnmal hart — die Werte sind identisch, die Fallbacks tragen
   den Strip-Fall.

   body.a_login .lightlink ist NEU in der Liste: die Stelle war der eine
   dokumentierte Verstoss (text-decoration mit px-Offset statt der
   Formel) und faehrt jetzt dieselbe Feder wie alle anderen.

   .lightlink OHNE SCOPE seit 2026-09-18 (vorher body.a_login #loginarea).
   Der Login-Vorsatz war eine LUECKE, keine Eingrenzung: die
   Hover-Ausloeser in tillit-shop-dom.css nennen acht Formular-Scopes und
   feuerten auf ein ::after, das es nur auf einem davon gab — sieben
   Seiten versprachen eine Feder, die nie existierte. Und die Werksklasse
   liegt breiter, als der Vorsatz zuliess: neun Traegerseiten im Repo
   (artikel/detail sechsmal, die vier Checkout-Seiten, konto/login).
   Unscoped bekommt jeder .lightlink dieselbe Linie, und der Guillemet-
   Ersatz am Checkout hat ueberhaupt erst ein Signal, auf das er sich
   zurueckziehen kann. Dieselbe Bereinigung wie beim Schrittbalken am
   01.09., aus demselben Grund.

   .tb-mobilebar__label (17.09.2026): das aktuelle Register der mobilen
   Kontaktleiste. Trigger ist [aria-current="page"] in tillit-shop-dom.css,
   Abschnitt MOBILE KONTAKTLEISTE; Touch kennt keinen Hover, die Linie
   steht dort nur oder gar nicht.

   .pagenavigation (29.09.2026, Detail-Audit F12): die Seitenzahlen der
   Blaetterzeile. Die aktuelle Seite trug ihren Zustand allein ueber das
   Werks-Gold, das mit dem design.cfg-Import faellt; jetzt steht ihre
   Linie, die verlinkten Ziffern fahren sie im Hover ein. Trigger und
   die Aussparung auf Glyphenbreite (left/right 8px = Seitenpolster der
   24px-Trefferflaeche) in tillit-shop-dom.css, Abschnitt BLAETTERZEILE.

   #compare .my-favorite (23.09.2026): der Favoritenzustand des
   Produktvergleichs, seit der Stern davor gestrichen ist. Trigger ist
   :has(> .fa) in tillit-shop-dom.css, Abschnitt WERKS-ICONS des
   Produktvergleichs; auch dort steht die Linie nur oder gar nicht. */
#topnav .h_menu li.level0 > a .text::after,
#Header .header_options .option a::after,
.h_menu.megamenu li.level2 > a::after,
.tillit-drawer__titlelink::after,
.tillit-drawer__row-label::after,
.tillit-drawer__sublink::after,
#Footer .footermenu a.level0::after,
#Footer .footermenu .simlink::after,
#newCookieJar .cookiefooter .simlink::after,
:is(#compare_small, #wishlist) .f-color--light::after,
body:has(#compare) #compare a::after,
body:has(#compare) #compare .my-favorite::after,
#footer_mwst a:not(.button_default)::after,
#Footer .tb-credit a::after,
#Footer #footer_mail a.individual_content::after,
#Footer #footer_tel a::after,
.lightlink:not(.after)::after,
.lightlink.after::before,
body.page_agb #agbgliederung a::after,
body.page_angemeldet #Middle #mk .content a::after,
#breadcrumb a::after,
body.a_article .tb-service__cta a::after,
body.a_article #ask-a-question button.button_default::after,
.tb-anchors__link::after,
.tb-mobilebar__label::after,
.pagenavigation .navigation > :is(a:not(.button_default), .active)::after,
.tb-link::after,
.sh-split__link::after{
  content:"";
  position:absolute;
  left:0;
  right:var(--sh-underline-inset,0px);
  bottom:calc(50% - var(--tb-underline-font,0.365em) - var(--tb-underline-gap,0.17em));
  height:1px;
  background-color:currentColor;
  transform:scaleX(0);
  transform-origin:right;
  transition:transform var(--tb-dur-state,.35s) var(--tb-ease-state,cubic-bezier(0.22,0.61,0.36,1));
}
/* Stehendes Register: Linie da, laeuft bei Hover weg.
   Das AGB-TOC (Werks-DOM) faehrt es seit 2026-08-27 mit —
   Entscheidung Max: ein Verzeichnis zeigt seine Linien. */
/* .lightlink steht seit 2026-09-18 mit im Register (Entscheidung Max:
   Zeichen UND stehende Linie, also das Muster von .tb-link). Anlass war
   eine Messung: nach dem Streichen des Guillemets stand "Daten aendern"
   in #363636 neben Fliesstext in #333333 — Kontrast 1,04, im
   Ruhezustand nicht mehr als Link erkennbar. Auf Touch faellt der Hover
   ohnehin weg, also muss die Ruhe tragen. */
/* body.a_article .tb-service__cta a seit 2026-09-23 (Detail-Audit F05):
   der Service-Link der Artikelseite stand nur in der Geometrie-Liste
   oben. Sein Ausloeser (tillit-shop-dom.css, gemeinsame Regel mit
   #ask-a-question) ist der des stehenden Registers - er lief also auf
   einer Linie, die nie stand: in Ruhe keine Feder, im Hover keine.
   Dieselbe Begruendung wie beim .lightlink: auf Touch muss die Ruhe den
   Link tragen. */
.tb-link::after,
.lightlink:not(.after)::after,
.lightlink.after::before,
body.a_article .tb-service__cta a::after,
body.a_article #ask-a-question button.button_default::after,
body.page_agb #agbgliederung a::after,
body.page_angemeldet #Middle #mk .content a::after,
.sh-split__link::after{transform:scaleX(1);transform-origin:left}

/* Windows-Kontrastmodi ueberschreiben background-color zu Canvas —
   der gemalte Unterstrich verschwaende. forced-color-adjust:none
   behaelt ihn; currentColor uebernimmt die vom System forcierte
   Linkfarbe. Vorher waren nur 5 der 10 Fundorte abgesichert; im
   Megamenue war die Linie sogar das einzige Fokussignal (der
   Werksring ist dort abgeschaltet). Die Liste schliesst alle. */
@media (forced-colors:active){
  #topnav .h_menu li.level0 > a .text::after,
  #Header .header_options .option a::after,
  .h_menu.megamenu li.level2 > a::after,
  .tillit-drawer__titlelink::after,
  .tillit-drawer__row-label::after,
  .tillit-drawer__sublink::after,
  #Footer .footermenu a.level0::after,
  #Footer .footermenu .simlink::after,
  #newCookieJar .cookiefooter .simlink::after,
  :is(#compare_small, #wishlist) .f-color--light::after,
  body:has(#compare) #compare a::after,
  body:has(#compare) #compare .my-favorite::after,
  #footer_mwst a:not(.button_default)::after,
  #Footer .tb-credit a::after,
  #Footer #footer_mail a.individual_content::after,
  #Footer #footer_tel a::after,
  .lightlink:not(.after)::after,
  .lightlink.after::before,
  body.page_agb #agbgliederung a::after,
  body.page_angemeldet #Middle #mk .content a::after,
  #breadcrumb a::after,
  body.a_article .tb-service__cta a::after,
  body.a_article #ask-a-question button.button_default::after,
  .tb-anchors__link::after,
  .tb-mobilebar__label::after,
  .pagenavigation .navigation > :is(a:not(.button_default), .active)::after,
  .tb-link::after,
  .sh-split__link::after{forced-color-adjust:none}
}


/* ======== FLIESSTEXT-FEDER (.tb-flow) ========
   KANONISIERT 2026-09-03 mit dem zweiten Verwender (Atherton-Port,
   FAQ 08). Der Kommentar am ersten Verwender (.sh-trust__text a,
   Startseite) hat genau das vorgemerkt: "wird zur Kanon-Feder --flow,
   sobald eine zweite Stelle sie braucht."

   WARUM NICHT DIE ::after-FEDER. Die legt EINE Linie ueber die
   Elementbox. Ein Link im Fliesstext bricht um und braeuchte eine Linie
   je Zeilenfragment - das kann nur ein Hintergrund-Verlauf mit
   box-decoration-break:clone. Die GESTE bleibt die des stehenden
   Registers: Linie da, laeuft beim Hover nach rechts hinaus (Anker
   springt auf rechts, Breite auf 0), kommt beim Verlassen von links
   zurueck. bottom .06em kalibriert sie auf die Lage des frueheren
   text-underline-offset:3px.

   .tb-page a.tb-flow statt .tb-flow: der Linkreset der Basis
   (.tb-page a{color:inherit}, 0,1,1) ist spezifischer als eine nackte
   Klasse - dieselbe Falle und dieselbe Loesung wie bei den
   Button-Varianten.

   Basis fuer helle Flaechen, --ink legt Weiss darueber - die
   Farb-Logik aller uebrigen Komponenten. */
.tb-page a.tb-flow{color:var(--tb-ink-1);text-decoration:none;background-image:linear-gradient(currentColor,currentColor);background-repeat:no-repeat;background-size:100% 1px;background-position:left 0 bottom .06em;box-decoration-break:clone;-webkit-box-decoration-break:clone;transition:background-size var(--tb-dur-state) var(--tb-ease-state)}
/* HOVER MIT PANZER, korrigiert 2026-09-04 (Befund Max an den
   Kontaktzeilen der Ueber-uns-Seite): .tb-page a.tb-flow (0,2,1)
   schlaegt eine nackte .tb-flow:hover (0,2,0) - die Feder stand da,
   bewegte sich aber seit ihrer Kanonisierung nie. Dieselbe Falle wie
   bei der Farbe von .tb-link, nur eine Zeile tiefer. */
.tb-page a.tb-flow:hover{background-size:0 1px;background-position:right 0 bottom .06em}
.tb-page a.tb-flow--ink{color:var(--tb-white)}
/* Windows-Kontrastmodi entfernen Hintergrundbilder - dort traegt wieder
   die native text-decoration, die forced colors ueberlebt. */
@media (forced-colors:active){
  .tb-page a.tb-flow{text-decoration:underline;text-underline-offset:3px}
}


/* ======== TABS / REGISTER ========
   Die Hairline-Tableiste des Systems: Zeile mit Linie oben, Labels in
   der Mono-Stimme, die Aktivlinie liegt AUF der Hairline und wird von
   links gezeichnet — kein Rahmen, keine Flaeche, kein Gold.

   Stand bis 2026-08-24 zweimal baugleich auf der Startseite
   (.sh-terrain__tabs auf Ink, .sh-build__switch auf Weiss); der
   Bestandskommentar am Build-Umschalter sagte selbst "folgt derselben
   Bauweise wie die Terrain-Tabs".

   ZUSTAND ueber ARIA, nicht ueber Klassen: echte Tabs tragen
   aria-selected (role=tablist/tab), Umschalt-Knoepfe aria-pressed
   (role=group/button). Beide sind semantisch richtig und beide schalten
   dieselbe Linie — eine .is-active-Kruecke braucht es nicht.

   BEWUSST KEIN nowrap/overflow IN DER BASIS: am Desktop brechen beide
   Leisten um. Die rollende Fassung ist der Modifier --roll im
   Mobilblock unten — nur die Terrain-Leiste traegt ihn.

   Kurven aus den Tokens statt der Instanz-Aliase (--sh-ease/--sh-cine
   waeren Portabilitaetsfehler, wie bei .tb-link behoben): Werte
   identisch. */
.tb-tabs{display:flex;flex-wrap:wrap;gap:0 clamp(1.6rem,3.5vw,3rem);border-top:1px solid var(--tb-line)}
.tb-tabs__tab{position:relative;padding:1.15rem 0;border:0;background:none;color:var(--tb-muted);font-family:var(--tb-mono);font-size:.82rem;font-weight:400;letter-spacing:var(--tb-mono-tracking);text-transform:uppercase;cursor:pointer;transition:color .3s var(--tb-ease-state)}
/* Choreografie wie die Feder (Entscheidung 2026-08-24): die Linie
   kommt von links und laeuft beim Deaktivieren nach RECHTS aus, statt
   sich zurueckzuziehen — im Bestand stand origin:left fest, die Tabs
   waren damit die einzige Stelle, an der die Linie rueckwaerts lief. */
.tb-tabs__tab::after{content:'';position:absolute;left:0;right:0;top:-1px;height:1px;background:var(--tb-ink-1);transform:scaleX(0);transform-origin:right;transition:transform .5s var(--tb-ease-snap)}
.tb-tabs__tab:hover,
.tb-tabs__tab[aria-selected="true"],
.tb-tabs__tab[aria-pressed="true"]{color:var(--tb-ink-1)}
.tb-tabs__tab[aria-selected="true"]::after,
.tb-tabs__tab[aria-pressed="true"]::after{transform:scaleX(1);transform-origin:left}
/* Ink-Grund: gedimmtes Weiss ruht, Weiss ist aktiv. */
.tb-tabs--ink{border-top-color:var(--tb-line-ink)}
.tb-tabs--ink .tb-tabs__tab{color:var(--tb-on-ink-muted)}
.tb-tabs--ink .tb-tabs__tab::after{background:var(--tb-white)}
.tb-tabs--ink .tb-tabs__tab:hover,
.tb-tabs--ink .tb-tabs__tab[aria-selected="true"],
.tb-tabs--ink .tb-tabs__tab[aria-pressed="true"]{color:var(--tb-white)}
/* RADIO-REGISTER: KANONISIERT 2026-09-04 mit dem zweiten Verwender
   (MTB-Hub, Weiche "Dein Terrain entscheidet"); stand als
   .le-calc__tab auf der Leasingseite (Rechenbeispiel, 02.09.2026) und
   ist dort bis zum naechsten Anfassen als Instanz doppelt. Das Label
   ist der Tab, das Radio liegt unsichtbar darueber und bleibt
   fokussierbar; Pfeiltasten wechseln nativ in der Gruppe. Aktivzustand
   aus :checked statt aria-selected - dieselbe Linie, nur der Traeger
   ist ein Radio. Fokusring zweimal: ueber :has() am ganzen Tab, ohne
   :has() am Label-Text - in Browsern ohne :has() gaebe es sonst
   keinen. Farbe ueber currentColor, damit Weiss- und Ink-Leiste
   dieselben Regeln fahren. Seit 2026-09-29 der Hausring (Tokens,
   tillit-tokens.css): 3px statt 6px Abstand, und die Hausecke steht
   hier selbst - fokussiert ist das Radio, nicht der Tab, die
   Werksrundung (styles.css:371) erreicht ihn also nicht.

   MITTE-CHOREOGRAFIE GEPRUEFT UND VERWORFEN (2026-09-18, Canvas
   "Radio-Kontrollen", Richtung D1, Entscheidung Max). Der Anlass war
   richtig beobachtet: beim Radiosatz wechseln immer zwei Kappen
   gleichzeitig, es laufen also zwei Linien nebeneinander. Die Antwort
   war es nicht. Der Durchlauf von links herein und nach rechts hinaus
   ist die Haus-Choreografie und steht an fuenf Stellen — an .tb-link
   (der Feder), an .sh-split__link, an .tb-anchors__link, an den
   aria-Registern darueber und hier. Eine Ausnahme allein fuer die
   Radio-Register waere die teurere Inkonsistenz. */
.tb-tabs__tab:has(.tb-tabs__radio){position:relative;white-space:nowrap}
.tb-tabs__radio{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:pointer}
.tb-tabs__tab:has(.tb-tabs__radio:checked){color:var(--tb-ink-1)}
.tb-tabs__tab:has(.tb-tabs__radio:checked)::after{transform:scaleX(1);transform-origin:left}
.tb-tabs--ink .tb-tabs__tab:has(.tb-tabs__radio:checked){color:var(--tb-white)}
.tb-tabs__tab:has(.tb-tabs__radio:focus-visible){outline:var(--tb-focus-width) solid currentColor;outline-offset:var(--tb-focus-offset);border-radius:calc(var(--tb-focus-radius) - var(--tb-focus-offset))}
.tb-tabs__radio:focus-visible + span{outline:var(--tb-focus-width) solid currentColor;outline-offset:var(--tb-focus-offset);border-radius:calc(var(--tb-focus-radius) - var(--tb-focus-offset))}
.tb-tabs__tab:has(.tb-tabs__radio:focus-visible) .tb-tabs__radio:focus-visible + span{outline:none}


/* ======== WEICHE (Register auf der Buehne, .tb-weiche) ========
   KANONISIERT 2026-09-06 mit dem vierten Verwender (AMFLOW-Hub,
   Familienplan docs/strategy/amflow-familie-neuschnitt-plan.md,
   Schritt 2). Stand bis dahin dreimal deklarationsgleich in den
   Seiten: .mh-weiche (MTB-Hub, 04.09.), .rgk-weiche (Road-und-Gravel-
   Hub, 04.09.) und .at-weiche (Atherton, 05.09.); Werte 1:1 vom
   MTB-Hub, dort hergeleitet aus dem "Einsatzort" der Startseite
   (.sh-terrain). Kein Wert veraendert. Das Nachladen der inaktiven
   Bildebenen liegt seit demselben Tag als TilliTMotion.initWeiche im
   Kernel (stand dreimal zeichengleich in den Seitenskripten).

   WAS DIE ROLLE IST: Kopf und Tableiste (Kanon .tb-tabs als
   Radio-Register) im Container, darunter eine randlose Ink-Buehne mit
   deckungsgleichen Bildebenen, im Container der Fall der gewaehlten
   Ebene: Auszeichnung, Titel, ein Absatz, Button, Kennziffer rechts
   unten. Der Zustand liegt in den Radios; welche Ebene und welcher
   Fall zu welchem Radio gehoert, sagt die INSTANZ mit ihren
   :has()-Zeilen, z. B.
     .mh-weiche:has(#mh-t-trail:checked) .tb-weiche__case[data-case="trail"]
   Deshalb bleiben in der Seite: die Aktivzeilen fuer Fall und Ebene,
   die Bildausschnitte (object-position je Motiv) und alles, was
   zusaetzlich am selben Radio haengt (Atherton: Modellzeilen).
   FUSSPOLSTER: traegt seit 24.09.2026 die Huelle selbst, einen Schritt
   wie jede Sektion (Nahtregel, Abschnitt Sektions-Huelle). Bis dahin
   war es ein Instanzknopf --tb-weiche-foot (Default 0): die Hubs liessen
   die Querverweiszeile mit 7vh schliessen (64 px ueber der Ink-Kante,
   gegenueber oeffnete Weiss mit 109), die Modellzeilen-Seiten setzten
   16vh (144) - zwei Asymmetrien in entgegengesetzter Richtung. Jetzt
   stehen Querverweiszeile und Modellzeilen gleich weit ueber der Kante.

   Rueckfall ohne :has(): die erste Ebene steht (:first-child statt
   data-case-Wert - in allen Instanzen ist die erste Ebene die
   vorgewaehlte), die Faelle stehen mit Hairline untereinander,
   inhaltlich vollstaendig.

   Nahtdecker: die Bildebene ist waehrend des Scrollens eine
   komponierte Ebene (will-change aus der Bildbuehne) und rastert an
   einer gebrochenen Oberkante anders als der Schleier - eine 1px helle
   Zeile blieb sichtbar (MTB-Hub, gemessen 04.09.2026). Ein 3px-Streifen
   in Ink ueber beiden Kanten ist gegen den Schleier unsichtbar.
   Zwei Schleier mit klarer Arbeitsteilung (Herleitung Startseite):
   radial unten links traegt den kastenlosen Textblock, linear
   oben/unten setzt die Naehte zur Ink-Flaeche.
   Faelle: alle im selben Rasterfeld, nur der gewaehlte sichtbar, die
   uebrigen visibility:hidden (raus aus dem Zugaenglichkeitsbaum, keine
   Tab-Stopps auf unsichtbaren Buttons); das Feld hat immer die Hoehe
   des hoechsten Falls, kein Hoehensprung beim Wechsel. Der Wechsel ist
   ein Zustandswechsel in stehender Buehne: weiche Unschaerfe
   (--tb-blur-soft), kein Weg, Klickdauer .35s. Kein A/B-Band im Fall
   (Max, 04.09.2026: "ueberladen"). Der Blendwechsel der Ebenen laeuft
   ueber opacity und die eigenstaendige scale-Eigenschaft, damit
   Wechsel und Parallax (tb-stage__media) auf demselben Bild
   nebeneinander laufen. */
.tb-weiche{padding:var(--tb-section-y) 0;background:var(--tb-ink);color:var(--tb-on-ink);overflow:hidden}
/* Kopffarben wie auf .tb-section--ink: die Huelle ist keine tb-section,
   die Umhebung kommt deshalb hier. Getrennt hat sie urspruenglich das
   eigene Fusspolster; das ist seit 24.09.2026 der normale Schritt. */
.tb-weiche .tb-head__title{color:var(--tb-white)}
.tb-weiche .tb-head__text{color:var(--tb-copy-on-ink)}
.tb-weiche .tb-tabs{margin-top:clamp(2.8rem,7vh,4.2rem)}
/* Fieldset-Reset: das Werk gibt Fieldsets Rahmen und Polster, die
   Tableiste braucht nur ihre Hairline oben (Kanon .tb-tabs).
   position/z-index seit 29.09.2026: die Buehne liegt hinter der Leiste
   (BUEHNE AB DEN REITERN, unten), die Reiter muessen darueber liegen und
   klickbar bleiben. */
.tb-page .tb-weiche__reg{position:relative;z-index:2;margin-inline:0;padding:0;border-left:0;border-right:0;border-bottom:0;min-width:0}
/* Unsichtbar, aber vorlesbar (die Legende des Registers). Utility,
   stand dreimal als x-visually-hidden in den Seiten; zieht nach
   tillit-base.css, sobald ein Verwender ausserhalb der Weiche
   dazukommt. */
.tb-visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* Wort am Bindestrich nicht trennen: sonst steht "E-" am Zeilenende
   (Werkstatt: "E-Bike" in Chrome 375/390 und im Firefox-Hero-Satz;
   Startseite: Mosaik-Name "E-City & E-Trekking" mobil und 1024-1080).
   Kein &#8209;: Systemia hat keine Glyphe fuer U+2011, das Zeichen
   fiele auf die Ersatzschrift. Der Span laesst den Text byte-gleich.
   Seit 2026-09-28 Kanon mit dem zweiten Verwender (vorher .ws-nobr). */
.tb-nobr{white-space:nowrap}
/* BUEHNE AB DEN REITERN (29.09.2026, Studie prototypen/weiche-luft.html,
   Entscheidung Max: "A ab Reitern"; Anlass: hoeher, luftiger, der
   Verlauf ins Schwarze sanfter, die Texte sollen atmen). Das Bild
   beginnt an der Hairline der Tableiste: die Buehne rueckt um die Hoehe
   der Reiterzeile nach oben (--tb-weiche-reiter, 51,55 px = 1 px Linie +
   2 x 1,15rem Polster + 1,6 x .82rem Zeile aus .tb-tabs__tab - aendert
   sich dort Polster, Schriftgrad oder Zeile, muss der Wert mit; die
   Leiste wickelt nicht, mobil rollt sie) und waechst um diese Zeile plus
   den Abstand, der bis dahin zwischen Leiste und Bild stand. Die
   Unterkante bleibt damit, wo sie ohne den Vorlauf laege. Die Reiter
   liegen per z-index darueber (.tb-weiche__reg) und stehen im dunklen
   Anfang der langen Naht oben. Hoehe 84vh statt 76vh, Boden 44vw statt
   40vw (dieselbe Hebung um ein Zehntel; die 40vw-Herleitung vom
   17.09.2026 steht bei .tb-stage--foto: bei 2560 war die Weiche ein
   3,37:1-Band, mit 36vw schnitt Pivot den Helm an), Deckel 1040 statt
   760. Gemessen bei 1440 x 900: Buehne 869 px statt 684, davon 313 px
   Bild ohne Schleier statt 164. */
.tb-weiche__stage{--tb-weiche-reiter:calc(3.612rem + 1px);position:relative;display:flex;align-items:flex-end;margin-top:calc(-1 * var(--tb-weiche-reiter));min-height:calc(max(clamp(560px,84vh,1040px),44vw) + var(--tb-weiche-reiter) + clamp(2.8rem,7vh,4.4rem))}
.tb-weiche__stage::before,
.tb-weiche__stage::after{content:"";position:absolute;left:0;right:0;z-index:1;height:3px;background:var(--tb-ink);pointer-events:none}
.tb-weiche__stage::before{top:-1px}
.tb-weiche__stage::after{bottom:-1px}
.tb-weiche__layers{position:absolute;inset:0;overflow:hidden}
/* Blendwechsel seit 29.09.2026 ruhiger (Teil von "A ab Reitern"): die
   neue Ebene setzt sich aus 1,05 statt 1,08 auf 1, Blende 1,2 s statt
   ,9 s, das Setzen 2,4 s auf der Auftrittskurve statt 1,8 s. */
.tb-page .tb-weiche__layer{opacity:0;scale:1.05;transition:opacity 1.2s var(--tb-ease-snap),scale 2.4s var(--tb-ease-entry)}
/* SCHLEIER seit 29.09.2026 ("A ab Reitern", Naehte nach Max: "grosse
   naht oben, unten kleiner"). Zwei Schichten wie bisher:
   1. HOF radial unten links, 95 % x 115 %, .88 / .70 / .42 / .14 / 0
      bei 0 / 28 / 52 / 74 / 90 %. Er traegt den Text: ein kleiner Hof
      (78 % x 64 %) liess Titel im Messlauf bis 1,3:1 fallen, der
      bisherige Schleier trug die Lesbarkeit mit.
   2. NAEHTE linear, oben 36 %, unten 28 % der Buehne (bei 1440 x 900
      313 / 243 px), dazwischen das freie Bild. Die Deckkraft folgt einem
      Kosinus (1 + cos(pi t)) / 2 in sechs Schritten (die Studie hatte
      zwoelf; sechs weichen hoechstens 1,7 Prozentpunkte Deckkraft von
      der Kurve ab und sparen Feldbytes), flach an BEIDEN
      Enden: am Ink, damit die Bildkante nicht als Linie steht (die
      klassische Scrim-Kurve faellt dort steil ab), am freien Bild, damit
      kein Knick sichtbar wird wie bei den alten Geraden .85 / .45 / .12.
   Gemessen an allen 24 Welten der neun Seiten (1440 x 900, Kontrast
   pixelweise mit sRGB-Mischung der Textfarbe, 10. Perzentil): Titel ab
   4,1:1 - er haengt am Hof, nicht an der Naht unten -, Satz (.88) ab
   4,6, Kennziffer ab 5,6 (in Weiss, siehe dort). Unten nicht unter
   28 %: bei 24 fiel die Kennziffer auf 3,9 (MTB-Hub Tour). Oben endet
   die Naht in Ink, unten auch; der 3px-Nahtdecker bleibt Reserve. Die
   Einsatzort-Buehne der Startseite (.sh-terrain) traegt dieselben
   Werte als Kopie. */
.tb-weiche__layers::after{content:"";position:absolute;inset:0;background:radial-gradient(95% 115% at 0% 100%,rgba(15,15,15,.88) 0%,rgba(15,15,15,.7) 28%,rgba(15,15,15,.42) 52%,rgba(15,15,15,.14) 74%,rgba(15,15,15,0) 90%),linear-gradient(180deg,#0f0f0f 0%,rgba(15,15,15,.933) 6%,rgba(15,15,15,.75) 12%,rgba(15,15,15,.5) 18%,rgba(15,15,15,.25) 24%,rgba(15,15,15,.067) 30%,rgba(15,15,15,0) 36%,rgba(15,15,15,0) 72%,rgba(15,15,15,.067) 76.67%,rgba(15,15,15,.25) 81.33%,rgba(15,15,15,.5) 86%,rgba(15,15,15,.75) 90.67%,rgba(15,15,15,.933) 95.33%,#0f0f0f 100%)}
/* Polster um den Fall seit 29.09.2026 groesser: oben 3rem/8vh/5rem statt
   2,5/6/4, unten 3,5rem/10vh/6,5rem - der Button steht mit Luft ueber
   der kuerzeren Naht unten. */
.tb-weiche__stage > .tillit-container{position:relative;z-index:2;width:100%;padding-top:clamp(3rem,8vh,5rem);padding-bottom:clamp(3.5rem,10vh,6.5rem)}
.tb-weiche__cases{display:grid}
.tb-weiche__case{grid-area:1/1;display:flex;align-items:flex-end;justify-content:space-between;gap:2rem;opacity:0;visibility:hidden;filter:blur(var(--tb-blur-soft));transition:opacity .35s var(--tb-ease-snap),filter .35s var(--tb-ease-snap),visibility 0s linear .35s}
@supports not selector(:has(*)){
  .tb-page .tb-weiche__layer:first-child{opacity:1;scale:1}
  .tb-weiche__cases{display:block}
  .tb-weiche__case{opacity:1;visibility:visible;filter:none}
  .tb-weiche__case + .tb-weiche__case{margin-top:2rem;padding-top:2rem;border-top:1px solid var(--tb-line-ink)}
}
/* Der Fall: ohne Kasten, Lesbarkeit aus Schleier und weichem Schatten
   (Werte urspruenglich 1:1 von der Terrain-Karte der Startseite).
   LUFT seit 29.09.2026 ("A ab Reitern", Max: "nicht alles so Schlag auf
   Schlag"): die Abstaende im Fall um den Faktor 1,6 (Kicker zum Titel
   1,05 -> 1,68rem, Titel zum Satz 1,1 -> 1,76rem, Satz zum Button
   2 -> 3,2rem; bei 1440 24 / 25 / 45 px statt 15 / 15 / 28), der Titel
   eine Stufe groesser (41 statt 36 px bei 1440), der Satz mit mehr
   Durchschuss und schmaler (31rem), der Fall 36rem auf allen Breiten
   (vorher 34, ab 1024 38). Mobil bleibt der Titel auf seiner Stufe
   (Mobilblock): sein Verhaeltnis 1,32 zum Sektionskopf haelt die
   Ebenen auseinander, groesser stuende er bei 1,16. */
.tb-weiche__card{max-width:36rem;text-shadow:0 1px 14px rgba(15,15,15,.55)}
/* HOF AM FALL ab 768 px (29.09.2026). Der Hof des Schleiers haengt an
   der Buehne, nicht am Text: je nach Breite und Textlaenge ragt der Fall
   aus ihm heraus. Gemessen (Kontrast pixelweise, 10. Perzentil): schon
   der alte Kanon lag bei 1024 und 1280 auf Orbea MTB bei 1,9:1 (Kicker)
   und 2,4 (Titel), mit dem luftigeren Fall fiel bei 1440 der Kicker auf
   Cannondale Gravel von 16,6 auf 3,7. Deshalb liegt hinter dem Fall ein
   eigener weicher Schatten: eine Flaeche etwas groesser als der Fall,
   weichgezeichnet - er folgt jeder Textlaenge und Breite. Kein
   Schlagschatten: dessen Unschaerfe ist am Kastenrand schon auf rund
   84 % gefallen, zwischen Flaeche und Schatten stand eine sichtbare
   Stufe (erster Versuch, Orbea MTB). Mobil uebernimmt das Band am
   Container (Mobilblock). Liegt ueber z-index -1 im Stapelkontext des
   Containers: hinter dem Text, vor den Bildebenen. */
@media (min-width:768px){
  .tb-weiche__card{position:relative}
  .tb-weiche__card::before{content:"";position:absolute;inset:-3rem -4rem;z-index:-1;background:rgba(15,15,15,.42);filter:blur(2.5rem);pointer-events:none}
}
.tb-weiche__kicker{display:flex;align-items:center;gap:.7rem;margin:0 0 1.68rem;color:var(--tb-white);font-family:var(--tb-mono);font-size:.82rem;text-transform:uppercase;letter-spacing:var(--tb-mono-tracking)}
.tb-weiche__kicker i{flex:none;width:3px;height:3px;border-radius:50%;background:rgba(255,255,255,.55)}
.tb-weiche__title{margin:0;color:var(--tb-white);font-size:clamp(1.9rem,3.8vw,min(3.4rem,max(2.95rem,2.6vw)));letter-spacing:-.028em;line-height:1.06}
.tb-weiche__text{max-width:31rem;margin:1.76rem 0 0;color:rgba(255,255,255,.88);font-size:clamp(1.05rem,1.5vw,min(1.38rem,max(1.2rem,1.08vw)));line-height:1.72}
.tb-weiche__cta{display:flex;flex-wrap:wrap;align-items:center;gap:1rem 2rem;margin-top:3.2rem}
/* Kennziffer rechts unten: der gewaehlte Fall im Zaehlwerk. Seit
   29.09.2026 in Weiss wie der Kicker: sie steht rechts ausserhalb des
   Hofs, nur auf der Naht unten, und lag in Muted (.55) schon mit der
   alten Naht auf drei Welten unter 4,5:1 (4,3 MTB-Hub Tour). */
.tb-weiche__count{flex:none;color:var(--tb-white);font-family:var(--tb-mono);font-size:.82rem;letter-spacing:var(--tb-mono-tracking);font-variant-numeric:tabular-nums;text-shadow:0 1px 14px rgba(15,15,15,.55)}
/* Querverweiszeile nach der Buehne, auf Ink: eine Nachbarwelt, kein
   weiterer Fall (MTB-Hub: E-MTB, Road-und-Gravel-Hub: E-Road und
   E-Gravel, AMFLOW-Hub: das TL). Kein eigenes Fusspolster (bis
   24.09.2026 7vh): den Abstand zur Ink-Kante gibt die Huelle, damit die
   Zeile so weit ueber der Kante steht, wie Weiss darunter oeffnet. */
.tb-weiche__cross{display:flex;align-items:center;justify-content:space-between;gap:1.5rem;padding:clamp(1.2rem,2.5vh,1.65rem) 0 0;border-top:1px solid var(--tb-line-ink)}
.tb-weiche__cross-text{margin:0;color:var(--tb-copy-on-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
/* Modellzeilen unter der Buehne mit mehr Abstand (29.09.2026, "A ab
   Reitern"): 3,5rem/9vh/6,5rem statt des allgemeinen 2,8/7/4,5 - die
   Buehne endet jetzt mit Luft unter dem Button, die Zeilen setzen
   sichtbar neu an. Nur in der Weiche; .tb-models--fest bleibt. */
.tb-weiche .tb-models{margin-top:clamp(3.5rem,9vh,6.5rem)}


/* ======== MODELLZEILEN AUF INK (.tb-models) ========
   KANONISIERT 2026-09-06 mit dem zweiten Verwender (AMFLOW-Hub, die
   Builds der gewaehlten Plattform); stand als .at-models / .at-model
   auf der Atherton-Seite (Neuschnitt 05.09.). Werte 1:1, kein Wert
   veraendert. Hairline-Zeilen unter der Weiche, am selben Radio:
   Name | Einsatz + Satz | Daten in Mono, kein Kasten. Die Saetze
   (__set) stapeln wie die Faelle der Weiche im selben Rasterfeld, nur
   ohne Blur - Lesetext bleibt scharf (Motion-System, Satz 2). Welcher
   Satz sichtbar ist, sagt die INSTANZ mit ihren :has()-Zeilen am
   Radio der Weiche:
     .at-weiche:has(#at-t-a:checked) .tb-models__set[data-case="a"]{...}
   Rueckfall ohne :has(): alle Saetze mit Hairline untereinander.
   HOEHE (seit 30.09.2026, Befund Max mobil auf der Orbea-Seite): nur
   der sichtbare Satz steht im Fluss, die anderen liegen absolut im
   selben Rasterfeld. Vorher trugen alle Saetze die Hoehe, und unter
   einer kurzen Welt (Orbea E-Trekking: ein Modell) klaffte die Hoehe
   der laengsten. Die Instanzzeile setzt deshalb neben opacity und
   visibility auch position:relative. Der Wechsel verschiebt nur, was
   UNTER den Zeilen liegt; der Blick ist in dem Moment oben an den
   Reitern. overflow-y:clip schneidet den ausblendenden laengeren Satz
   an der neuen Kante ab (in den Zeilen stehen keine Links, kein
   Fokusring wird beschnitten).
   Das Fusspolster unter den Zeilen gibt die Huelle (.tb-weiche, ein
   Schritt); der Knopf --tb-weiche-foot, den die Zeilen-Seiten bis
   24.09.2026 auf 16vh setzten, ist entfallen.

   FASSUNG .tb-models--fest (seit 25.09.2026, Werkstatt-Plan M10 b):
   EIN Satz, der immer steht, ohne Weiche und ohne Radio. Ohne sie
   bleibt ein __set unsichtbar, auch ausserhalb einer .tb-weiche. Stand
   zweimal als Instanzzeile (.apr-weiche / .apx-weiche .tb-models__set,
   AMFLOW PR und PX: beide Builds, kein Satzwechsel); dritter Verwender
   wird die Leistungsliste von Werkstatt & Service auf .tb-section--ink.
   Der Modifier traegt NUR die Sichtbarkeit, 0,2,0 wie die alten
   Instanzzeilen. Keinen Abstand hineinlegen, sonst verschieben sich
   AMFLOW PR und PX: dort gilt unter der Buehne der Grundwert von
   .tb-models. Einen anderen Abstand setzt der Kontext in seiner
   Instanz (direkt unter einem Sektionskopf etwa --tb-head-gap). Genau
   ein __set je Liste: mehrere Saetze laegen im selben Rasterfeld
   uebereinander.
     <div class="tb-models tb-models--fest">
       <div class="tb-models__set"> __cap + __list > .tb-model ... </div>
     </div> */
.tb-models{position:relative;display:grid;overflow-y:clip;margin-top:clamp(2.8rem,7vh,4.5rem)}
.tb-models__set{grid-area:1/1;position:absolute;top:0;left:0;right:0;opacity:0;visibility:hidden;transition:opacity .35s var(--tb-ease-snap),visibility 0s linear .35s}
.tb-models--fest .tb-models__set{position:relative;opacity:1;visibility:visible}
@supports not selector(:has(*)){
  .tb-models{display:block}
  .tb-models__set{position:static;opacity:1;visibility:visible}
  .tb-models__set + .tb-models__set{margin-top:2rem;padding-top:2rem;border-top:1px solid var(--tb-line-ink)}
}
.tb-models__cap{display:flex;align-items:baseline;justify-content:space-between;gap:1.5rem;margin:0 0 .4rem;color:var(--tb-on-ink-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);text-transform:uppercase}
.tb-page .tb-models__list{margin:0;border-bottom:1px solid var(--tb-line-ink)}
/* Namensspalte als Instanzknopf (--tb-model-name, Default 8.5rem fuer
   Kuerzel wie "A.130"; die AMFLOW-Seiten setzen 15rem, weil "PX Carbon
   Pro" sonst auf drei Zeilen bricht - Befund Max, 06.09.2026). */
/* align-items:center statt baseline (Befund Max, 06.09.2026): an der
   Grundlinie der kleinen Einsatz-Zeile hing der grosse Name oben am
   dreizeiligen Block. Zentriert steht er auf Hoehe des Textes, auch die
   Datenreihe rechts. */
.tb-model{display:grid;grid-template-columns:var(--tb-model-name,8.5rem) minmax(0,1fr) auto;gap:.4rem 2rem;align-items:center;padding:clamp(1.2rem,2.6vh,1.7rem) 0;border-top:1px solid var(--tb-line-ink)}
.tb-model__name{margin:0;color:var(--tb-white);font-size:clamp(1.5rem,2.6vw,2.1rem);letter-spacing:-.025em;line-height:1.15}
.tb-model__use{display:block;margin:0 0 .35rem;color:var(--tb-on-ink-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);text-transform:uppercase}
.tb-model__text{margin:0;max-width:56ch;color:var(--tb-copy-on-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
.tb-model__data{margin:0;display:flex;flex-wrap:wrap;gap:.35rem .55rem;color:var(--tb-on-ink);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);text-transform:uppercase;white-space:nowrap}
.tb-model__data span:not(:last-child)::after{content:"·";margin-left:.55rem;color:var(--tb-on-ink-muted)}
.tb-models__actions{display:flex;flex-wrap:wrap;align-items:center;gap:1rem 2rem;margin-top:clamp(2rem,5vh,3rem)}


/* ======== ZEILENTITEL ========
   Der Titel einer Hairline-Listenzeile — eine Stufe unter dem
   Sektionskopf, deutlich ueber dem Fliesstext. Stand zweimal
   deklarationsgleich auf der Startseite (.sh-trust__item-title auf Ink,
   .sh-method__word auf Weiss); der Leiter-Kommentar dort fuehrt die
   Rolle seit dem Taktband-Umbau ausdruecklich als "Listentitel".
   Farbe wie ueberall: Basis fuer Weiss, --ink hebt um.

   Die "Claim"-Haelfte dieses Schritts hat sich beim Nachpruefen
   aufgeloest: die Rampe clamp(1.2rem,1.85vw,1.55rem) styled keinen
   lebenden Text mehr (die Feature-Zeile des Beratungsprozesses laeuft
   laengst auf --tb-proof-size) — sie lebt nur noch als
   Skalierungsformel im Kreis-Badge und braucht keinen Namen. */
.tb-row__title{margin:0;color:var(--tb-ink-1);font-size:clamp(1.5rem,2.6vw,2.1rem);font-weight:400;letter-spacing:-.025em;line-height:1.15}
.tb-row__title--ink{color:var(--tb-white)}


/* ======== ANKERBAND ========
   Sprungnavigation im Hero. ENTSCHIEDEN 2026-08-24 (P6): Register,
   keine Pillenreihe — Pillen sind Rahmenvokabular und saehen neben dem
   Ink-CTA aus wie Buttons; Navigation spricht im System Mono.

   Neubau ohne heutigen Verwender auf den Referenzseiten: die beiden
   Altfassungen (rgk-hero__anchors in Gold/800, testfleet-nav als
   Pillen) fallen mit ihren Seiten-Ports und landen dann hier.

   Der Link faehrt die Feder des Systems (Grundregister "kommt") — seine
   ::after-Geometrie steht mit in der UNTERSTRICH-FEDER-Liste oben; hier
   stehen nur Element und Trigger. Der Chevron laeuft in currentColor
   (kein Gold) und antwortet beim Hover rein ueber Opacity (gedimmt in
   Ruhe, voll beim Hover) — die fruehere translateY(3px)-Nickbewegung
   war der letzte translateY-Hover im Bestand und verstiess gegen die
   Motion-Leitplanke (Hover bewegt nur scale, Pfeil-Nudges nie
   translateY; Tilgung stand in tillit-motion-system.md unter P2).

   GATE A: .82rem ist der Navigations-Grad der Tableiste — bewusst KEINE
   neue Zahl; die Grade werden nach dem Schriftkauf konsolidiert. */
.tb-anchors{display:flex;flex-wrap:wrap;gap:.9rem clamp(1.6rem,3.5vw,3rem)}
.tb-anchors__link{position:relative;display:inline-flex;align-items:center;gap:.45rem;color:var(--tb-muted);font-family:var(--tb-mono);font-size:.82rem;font-weight:400;letter-spacing:var(--tb-mono-tracking);text-transform:uppercase;text-decoration:none;transition:color .3s var(--tb-ease-state);--sh-underline-inset:calc(14px + .45rem)}
/* Ruhewert .7 statt .55: die Sichtpruefung 2026-08-24 fand .55 schon
   fuer die LINKFARBE zu leise, und das Logoband faehrt dasselbe
   Opacity-Antwortmuster mit .7 -> 1 - der Chevron folgt dem Echo. */
.tb-anchors__link svg{width:14px;height:14px;flex:none;opacity:.7;transition:opacity var(--tb-dur-state,.35s) var(--tb-ease-state)}
.tb-anchors__link:hover,
.tb-anchors__link:focus-visible{color:var(--tb-ink-1)}
.tb-anchors__link:hover::after,
.tb-anchors__link:focus-visible::after{transform:scaleX(1);transform-origin:left}
.tb-anchors__link:hover svg,
.tb-anchors__link:focus-visible svg{opacity:1}
/* Ink-Grund (Hero): Ruhe auf --tb-on-ink (.8 Weiss), Weiss antwortet.
   Bis zur Sichtpruefung des Flotten-Ports stand hier on-ink-muted
   (.55) — auf dem Foto zu leise (Entscheidung Max, 2026-08-24;
   Kanon-Token, nicht die --tbh-Insel: die faellt beim Abbau). */
.tb-anchors--ink .tb-anchors__link{color:var(--tb-on-ink)}
.tb-anchors--ink .tb-anchors__link:hover,
.tb-anchors--ink .tb-anchors__link:focus-visible{color:var(--tb-white)}


/* ======== LOGOBAND ========
   Partner- und Markenlogos als Hairline-Raster: zwei Spalten, ab 768
   vier; nur waagerechte Linien, jede Zelle zentriert ihr Logo; Hover
   scale statt Lift, wie es die Hausregel verlangt.

   Neubau nach der Altfassung .rgk-brands/.rg-marken (kategorie.html),
   auf die Kanon-Token gezogen: die Hairlines liefen dort noch auf dem
   Alt-Grau rgba(34,34,34,.14), jetzt --tb-line.

   ERSTER VERWENDER 2026-09-02 (Leasingseite): zwoelf Partnerlogos als
   Inline-SVG in MARKENFARBE auf Weiss - Entscheidung Max, einfarbig
   in currentColor war zu wenig. Ein Band auf Ink gibt es damit nicht;
   die Zelle gibt color:var(--tb-ink-1) trotzdem weiter vor, und fuer
   den kategorie-Port bleibt vorgemerkt: dessen Alt-SVGs tragen 15
   fill-Attribute in drei Ink-Toenen (#1B1B1B, #1F1A1B, #252525), die
   auf currentColor wandern koennen, weil sie ohnehin einfarbig sind. */
/* VEREDELT 2026-09-02 mit dem ersten Verwender (Max: das Raster bleibt,
   aber hochwertiger): Ruhe in voller Farbe - die Dimmung auf .7 wusch
   farbige Logos aus; der Hover arbeitet mit der Nachbarschaft, das
   beruehrte Logo waechst auf 1.04 und die uebrigen gehen auf .9
   Deckkraft (verwandt mit der Geste der FAQ-Fragen, die dort ueber
   die Farbe laeuft; Lautstaerke-Regel des Motion-Systems: das Element
   selbst hoechstens 1,06, Nachbarn in der Deckkraft bis 0,9);
   eine Mono-Kennziffer oben links (.tb-logos__num, optional) gibt dem
   Raster die Index-DNA; die Zellen sind hoeher (120-150 px). Auftritt:
   jede Zelle traegt data-reveal mit --sh-i, die Reihe ist EINE Einheit
   (Deckel 6). Die Breite je Logo setzt die Instanz, der Kanon deckelt. */
.tb-logos{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border-top:1px solid var(--tb-line)}
.tb-logos__cell{position:relative;display:flex;align-items:center;justify-content:center;min-height:clamp(120px,16vh,150px);padding:2.4rem 1.5rem;border-bottom:1px solid var(--tb-line);color:var(--tb-ink-1)}
.tb-logos__num{position:absolute;top:1rem;left:1.5rem;color:var(--tb-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);font-variant-numeric:tabular-nums}
.tb-logos__img{max-width:150px;height:auto;transition:opacity var(--tb-dur-state) var(--tb-ease-state),transform .4s var(--tb-ease-state)}
.tb-logos__cell:hover .tb-logos__img{transform:scale(1.04)}
.tb-logos:has(.tb-logos__cell:hover) .tb-logos__cell:not(:hover) .tb-logos__img{opacity:.9}
@media (min-width:768px){
  .tb-logos{grid-template-columns:repeat(4,minmax(0,1fr))}
}


/* ======== FORMULARFELD ========
   Neubau 2026-08-24 — die groesste Luecke des Rollenkatalogs: beide
   Referenzseiten fuehren null <input> und null <form>. Das Rezept kommt
   aus dem Login-Block (tillit-feldspiegel-alt.css, body.a_login), der einzigen im
   neuen Ton gebauten Formulargestaltung: weisse Flaeche, Hairline,
   Fokus in Ink statt System-Blau, schwebendes Label.

   MARKUP-VERTRAG: das Label steht NACH dem Feld, das Feld traegt
   placeholder=" " (ein Leerzeichen). Dann schwebt das Label rein per
   CSS — :focus-within hebt es beim Fokus, :not(:placeholder-shown)
   haelt es oben, solange etwas im Feld steht. Der Login brauchte dafuer
   eine JS-Klasse (.focus), weil sein Werks-Markup andersherum steht.
   Felder ohne Platzhalter-Logik (select, date) tragen --floated und
   halten das Label dauerhaft oben.

   FOKUS: Rand auf Ink plus 1px Inset — zusammen eine 2px-Ink-Kante,
   das praezise Signal des Login-Rezepts. Der grosse Seitenring aus L1
   wird hier bewusst ersetzt, nicht ergaenzt (Ring + Kante waeren ein
   Doppelsignal): outline:none traegt !important und gewinnt gegen die
   L1-Regel ueber die Reihenfolge (gleiche Spezifitaet und Wichtigkeit,
   L4 laedt spaeter).

   PFLICHTSTERN in Ink (Entscheidung P5): der Stern markiert eine
   Pflicht, keine Aktion — Gold behaelt seinen Ein-Stellen-Vertrag,
   Rot bleibt Fehlern vorbehalten.

   OFFEN, bewusst: der Fehlerzustand. Das System hat kein Rot-Token —
   das ist eine eigene kleine Entscheidung (Farbe + Ton der
   Fehlermeldung), keine Mechanik. Der Haken --error ist reserviert. */
.tb-field{position:relative;margin:1.15rem 0 0}
.tb-field__input{width:100%;height:3.2em;padding:0 1em;background-color:var(--tb-white);border:1px solid var(--tb-line-strong);border-radius:var(--tb-radius);font-family:inherit;font-size:1rem;color:var(--tb-ink-1);transition:border-color .2s var(--tb-ease-state),box-shadow .2s var(--tb-ease-state)}
textarea.tb-field__input{height:auto;min-height:7em;padding:.85em 1em;resize:vertical}
/* Hover-Stufe zwischen Hairline (.22) und Ink — Bestandswert des Logins. */
.tb-field__input:hover{border-color:rgba(15,15,15,.38)}
.tb-field__input:focus,
.tb-field__input:focus-visible{border-color:var(--tb-ink-1);box-shadow:inset 0 0 0 1px var(--tb-ink-1);outline:none !important}
.tb-field__label{position:absolute;top:1em;left:1em;color:var(--tb-muted);font-size:1rem;line-height:1.2;pointer-events:none;transition:top .2s var(--tb-ease-state),left .2s var(--tb-ease-state),font-size .2s var(--tb-ease-state)}
.tb-field:focus-within > .tb-field__label,
.tb-field__input:not(:placeholder-shown) ~ .tb-field__label,
.tb-field--floated > .tb-field__label{top:-.62em;left:.8em;padding:0 .45em;background-color:var(--tb-white);font-size:.75rem;letter-spacing:.01em}
.tb-field--mandatory > .tb-field__label::after{content:" *";color:var(--tb-ink-1)}


/* ======== FAQ-REGISTER (.tb-faq) ========
   Kanon-Kandidat 2026-09-02. Herkunft: .bp-faq des Beratungsprozesses
   (Entscheidung 2026-08-19, Gut-zu-wissen-Canvas Variante A): die
   Fragen stehen als nummerierter Hairline-Index links, die Antwort
   wechselt rechts in einem stehenden Ink-Lesefeld. Markup bleibt
   <details name=...>/<summary> (Entscheidung P7): Auf/Zu, aria-expanded
   und Tastatur kommen nativ; die Eine-offen-Gruppe nativ erst ab
   Chrome 120 / Safari 17.2 / Firefox 130, darunter stellt sie initFaq
   im Kernel her (JS-Go-live-Audit J10).

   WAS SICH GEGENUEBER .bp-faq AENDERT (Befund Max, 2026-09-02): dort
   trug JEDE Antwort ihre eigene Ink-Flaeche, absolut gestapelt, und
   die Kreuzblende lief ueber die Deckkraft der ganzen Antwort - beim
   Fragenwechsel blendete also die komplette dunkle Box aus und wieder
   ein, obwohl nur der Text wechselt. Jetzt malt EIN Geschwister
   (.tb-faq__panel, das Lesefeld) die Ink-Flaeche genau einmal; die
   Antworten liegen ohne eigenen Grund darueber und blenden nur den
   Text (Kennziffer + Antwort). Die Hoehe des Lesefelds folgt der
   Textlaenge der offenen Antwort: das Skript misst die Antwort und
   schreibt --sh-faq-h auf .tb-faq (Instanzwert, deshalb --sh-),
   die Transition macht daraus die weiche Hoehenfahrt.

   WARUM DAS OHNE SICHTBAREN UEBERLAUF GEHT: waehrend die Flaeche
   noch faehrt, ragt die laengere Antwort kurz unter die Ink-Kante -
   in Weiss (--tb-copy-on-ink) auf der weissen Sektion. Unsichtbar,
   ohne overflow:hidden, das die absoluten Antworten ohnehin nicht
   erreichte. Voraussetzung: das Register steht auf Weiss (Marken-
   richtlinie, keine grauen Sektionsflaechen). Auf Ink-Sektionen ist
   die Komponente nicht vorgesehen.

   KLEBEN (Befund Max 2026-09-05, am Browser gemessen): das Lesefeld
   sitzt oben in der rechten Rasterzelle und blieb dort - bei langen
   Listen und flachen Fenstern lag es beim Oeffnen der letzten Fragen
   ueber dem Sichtfenster, man las die Antwort, ohne sie zu sehen.
   Deshalb klebt es ab 768px im Sichtfenster, solange die Liste
   laeuft: Klebeabstand --tb-faq-stick zur Oberkante, begrenzt durch
   die Unterkante der Liste. Drei Wege, zwei verworfen:
     - position:sticky auf dem Lesefeld allein reisst den Text ab.
       Die Antworten sind absolut gegen .tb-faq gesetzt (sie muessen
       fuer Auf/Zu, Tastatur und aria-expanded in ihrem <details>
       bleiben), das Feld faehrt mit, der Text bleibt oben (gemessen
       Feld 6px, Text -350px).
     - CSS Anchor Positioning (Antworten an das klebende Feld
       geankert) traegt in Chromium exakt. Firefox kennt die Syntax,
       rechnet den Sticky-Versatz des Ankers aber nicht mit (05.09.
       gemessen: derselbe Abriss). @supports kann das nicht
       unterscheiden - ein reiner CSS-Weg waere dort schlechter als
       der Ist-Stand.
     - Gebaut: EIN Instanzwert --sh-faq-shift (Kernel initFaq), den
       Lesefeld UND Antworten als translateY tragen. Kein position:
       sticky - beide ruecken aus derselben Zahl im selben Frame,
       nichts kann auseinanderlaufen. --tb-faq-stick liegt zusaetzlich
       als top auf dem statischen Lesefeld: ohne Wirkung aufs Layout,
       aber so liefert getComputedStyle den Abstand in Pixeln, die
       Custom Property selbst waere nur als Text (clamp...) lesbar.

   OHNE JS (.tb-faq ohne .is-js): das Panel bleibt display:none und
   jede Antwort traegt wie bisher ihre eigene Ink-Flaeche - der
   .bp-faq-Stand als Fallback, funktional identisch.

   EIN Markup fuer beide Layouts: unter 768px ist dieselbe Liste ein
   Akkordeon (Antwort unter der Frage, display:none, Pfeil dreht), ab
   768px liegen die Antworten absolut ueber dem Lesefeld. Mobile-first
   notiert, deshalb ohne max-width-Block (Feldregel "CSS - Ende":
   max-width-Bloecke hinter allen min-width-Bloecken). */
.tb-faq{position:relative;margin:var(--tb-head-gap) 0 0}
.tb-faq__list{border-bottom:1px solid var(--tb-line)}
.tb-faq__item{border-top:1px solid var(--tb-line)}
/* Die Fragen sind der Index der Sektion und tragen Display-Praesenz;
   zweizeilige Fragen sind einkalkuliert (bp, 2026-08-19). */
.tb-faq__question{display:grid;grid-template-columns:3.2rem minmax(0,1fr) auto;align-items:center;gap:1.2rem;width:100%;padding:clamp(1.7rem,3.4vh,2.4rem) 0;border:0;background:none;color:var(--tb-ink-1);font-family:inherit;font-size:clamp(1.5rem,2.4vw,2.1rem);letter-spacing:-.025em;line-height:1.15;text-align:left;cursor:pointer;transition:color var(--tb-dur-state) var(--tb-ease-state);list-style:none}
.tb-faq__question::-webkit-details-marker{display:none}
.tb-faq__num{color:var(--tb-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);font-variant-numeric:tabular-nums}
/* Mobil ist der Pfeil der Zustandstraeger des Akkordeons: gedaempft
   und nach rechts, wenn zu; praesent und nach unten gedreht, wenn
   offen. color fest, damit er nie mit ausgraut. */
.tb-faq__arrow{width:18px;height:18px;color:var(--tb-ink-1);opacity:.4;transition:transform var(--tb-dur-state) var(--tb-ease-state),opacity var(--tb-dur-state) var(--tb-ease-state)}
.tb-faq__item[open] .tb-faq__arrow{opacity:.85;transform:rotate(90deg)}
/* Mobil: Akkordeon. Antwort unter der Frage, Kennziffer des Lesefelds
   entfaellt, Lesefeld entfaellt. Die Antwort taucht aus der
   Unschaerfe auf - als Animation, nicht als Transition: aus
   display:none starten Transitions nicht zuverlaessig. Klick-Klasse
   (--tb-dur-click, --tb-ease-snap), kleine Unschaerfe (--tb-blur-soft),
   to:none statt blur(0), damit kein Filter stehen bleibt. */
.tb-faq__answer{display:none}
.tb-faq__item[open] .tb-faq__answer{display:block;animation:tbFaqReveal var(--tb-dur-click) var(--tb-ease-snap) both}
.tb-faq__kicker{display:none}
.tb-faq__panel{display:none}
/* Lesetext ausnahmslos auf --tb-copy-ink (Token-Kommentar Fliesstext);
   .bp-faq stand hier noch auf --tb-ink-2. */
.tb-faq__a-text{margin:0;padding:0 0 clamp(1.6rem,3vh,2.2rem);max-width:62ch;color:var(--tb-copy-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
/* Ein Link in der Antwort kann seine Farbe nicht selbst kennen: dieselbe
   Antwort steht mobil auf Weiss und ab 768 im Ink-Lesefeld. color:inherit
   laesst ihn beiden folgen — und die Feder zeichnet in currentColor, also
   folgt sie mit. Ohne die Regel stuende die Ink-Fassung von .tb-flow im
   Lesefeld schwarz auf schwarz. */
.tb-page .tb-faq__a-text a.tb-flow{color:inherit}
@keyframes tbFaqReveal{from{opacity:0;filter:blur(var(--tb-blur-soft));transform:translateY(var(--tb-move-near))}to{opacity:1;filter:none;transform:none}}

@media (min-width:768px){
  /* Fragenindex links, Lesefeld rechts. Die Antworten nehmen als
     absolute Elemente nicht am Raster teil - width rechnet die rechte
     Spalte deshalb nach (dieselbe Formel wie die Spalte). Die Liste
     links ist verlaesslich hoeher als das hoechste Lesefeld, die
     Sektion kollabiert also nicht.
     --tb-faq-stick ist der Klebeabstand des Lesefelds zur Fenster-
     oberkante (Kommentar KLEBEN): liegt mit Luft unter der fixierten
     Nav-Leiste (39px) und waechst mit dem Fenster. */
  .tb-faq{--tb-faq-stick:clamp(6rem,12vh,9rem);display:grid;grid-template-columns:minmax(0,.54fr) minmax(0,.46fr);gap:clamp(3rem,6vw,6rem);align-items:start}
  .tb-faq__list{grid-column:1;grid-row:1}
  .tb-faq__question{grid-template-columns:4.5rem minmax(0,1fr) auto}
  /* Solange eine Frage offen ist, nehmen sich die uebrigen zurueck -
     nur im Register, wo immer eine offen ist und der Hover es
     zuruecknimmt (mobil gibt es keinen Hover, dort bleibt alles auf
     Ink). Der Hover braucht den vollen Selektor der Dimm-Regel, sonst
     verliert er den Spezifitaetsvergleich. */
  .tb-faq__list:has(.tb-faq__item[open]) .tb-faq__item:not([open]) .tb-faq__question{color:var(--tb-muted)}
  .tb-faq__list:has(.tb-faq__item[open]) .tb-faq__item:not([open]) .tb-faq__question:hover{color:var(--tb-ink-1)}
  /* Der Pfeil gehoert der aktiven Frage - er zeigt zum Lesefeld. Der
     Pfeil der Zielfrage deutet sich beim Hover an. */
  .tb-faq__arrow{opacity:0;transform:none}
  .tb-faq__item[open] .tb-faq__arrow{opacity:.8;transform:translateX(4px)}
  .tb-faq__item:not([open]) .tb-faq__question:hover .tb-faq__arrow{opacity:.35}
  /* Geschlossene <details> rendern ihren Inhalt nicht - Kreuzblende
     UND Hoehenmessung brauchen aber alle Antworten im Baum.
     ::details-content haelt sie gerendert, wo der Browser es kann
     (Chromium seit Ende 2024, Firefox 138); opacity/visibility tragen
     die Blende, visibility nimmt geschlossene Antworten zugleich aus
     dem Zugaenglichkeitsbaum. Browser ohne ::details-content zeigen
     die Antwort per Einblendung - funktional identisch, ohne Blende. */
  .tb-faq__item:not([open])::details-content{content-visibility:visible}
  /* DAS LESEFELD. Sitzt in der rechten Rasterzelle, traegt Ink und
     Rundung genau einmal und faehrt seine Hoehe nach --sh-faq-h
     (Instanzwert aus dem Skript). Nur mit .is-js sichtbar - ohne
     Skript gaebe es niemanden, der die Hoehe schreibt. Die Fahrt
     laeuft in der Klick-Klasse auf der Klickkurve (--tb-ease-snap):
     sie rollt aus, ohne zu ueberschwingen.
     Das Kleben kommt als translateY aus --sh-faq-shift (Instanzwert
     aus dem Skript, Kommentar KLEBEN) - bewusst ohne Transition, der
     Versatz folgt dem Scroll. top ist hier nur Wertetraeger fuer das
     Skript, das Feld bleibt static. */
  .tb-faq.is-js .tb-faq__panel{display:block;grid-column:2;grid-row:1;top:var(--tb-faq-stick);height:var(--sh-faq-h,auto);background:var(--tb-ink);border-radius:var(--tb-radius);transform:translateY(var(--sh-faq-shift,0px));transition:height var(--tb-dur-click) var(--tb-ease-snap)}
  /* DIE ANTWORTEN liegen ohne eigenen Grund ueber dem Lesefeld.
     Ruhezustand geschlossen: unsichtbar und leicht unscharf - das
     ist der Startpunkt des naechsten Auftritts. Kein Weg: der Text
     blendet wie im Prozess-Panel ueber Deckkraft und Unschaerfe (die
     Wege des Token-Blocks gehoeren den Reveal-Registern). Ausgehend
     faehrt nur die Deckkraft (schnell, zwei Fuenftel der Klickdauer),
     der Filter springt erst danach zurueck; so blendet der alte Text
     glatt aus, statt beim Gehen noch zu verschwimmen.
     Sie tragen denselben Klebe-Versatz wie das Lesefeld
     (--sh-faq-shift): Text und Feld ruecken aus einer Zahl, bleiben
     also deckungsgleich. Ohne Skript ist der Wert 0. */
  .tb-faq__answer{display:block;position:absolute;top:0;right:0;z-index:1;transform:translateY(var(--sh-faq-shift,0px));width:calc((100% - clamp(3rem,6vw,6rem)) * .46);padding:clamp(2rem,3.2vw,3rem);opacity:0;visibility:hidden;filter:blur(var(--tb-blur-soft));transition:opacity calc(var(--tb-dur-click) * .4) var(--tb-ease-snap),filter 0s linear calc(var(--tb-dur-click) * .4),visibility 0s linear calc(var(--tb-dur-click) * .4)}
  /* Eingehend: nach einem Fuenftel Verzoegerung (der alte Text ist dann
     halb weg) aus der Unschaerfe auf scharf, vier Fuenftel der
     Klickdauer. Zusammen mit dem Ausgang genau eine Klickdauer, wie
     die Hoehenfahrt des Lesefelds. */
  .tb-faq__item[open] .tb-faq__answer{opacity:1;visibility:visible;filter:none;animation:none;transition:opacity calc(var(--tb-dur-click) * .8) var(--tb-ease-snap) calc(var(--tb-dur-click) * .2),filter calc(var(--tb-dur-click) * .8) var(--tb-ease-snap) calc(var(--tb-dur-click) * .2),visibility 0s}
  /* Fallback ohne Skript: jede Antwort bringt ihre Ink-Flaeche selbst
     mit (der .bp-faq-Stand). */
  .tb-faq:not(.is-js) .tb-faq__answer{background:var(--tb-ink);border-radius:var(--tb-radius)}
  .tb-faq__kicker{display:block;margin:0 0 1.4rem;color:var(--tb-on-ink-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);text-transform:uppercase;letter-spacing:var(--tb-mono-tracking);font-variant-numeric:tabular-nums}
  .tb-faq__a-text{padding:0;max-width:none;color:var(--tb-copy-on-ink)}
}


/* ======== STATEMENT (Manifest auf Ink) ========
   KANONISIERT 2026-09-04 mit dem zweiten Verwender (Ueber-uns-Seite),
   NEU GESCHNITTEN 2026-09-06 nach dem Canvas "Statement-Sektion"
   (Entscheidung Max: Richtung B, "Lesetext im Zitatgrad"). Neun
   Verwender: Die Idee (AMFLOW PX, PR, Familie; Atherton), Die
   Entscheidung (MTB- und Road-Hub), Der Unterschied (Beratungs-
   prozess), Haltung (Ueber uns), Fuer die Schweiz.

   DIE ROLLE: eine Sektion, die aus einer einzigen Aussage besteht -
   und seit dem Neuschnitt IST der Absatz die Aussage: er laeuft im
   Aussagegrad des Systems (--tb-statement-size, derselbe Grad wie das
   Zitat .tb-quote p) und wird beim Lesen hell (Leselicht, naechster
   Block). Der Titel steht als VORZEILE darueber im Zeilengrad
   (--tb-row-size, 0,7 des Aussagegrads) - Entscheidung Max 06.09.2026
   nach dem Titelgrad-Vergleich (a Aussagegrad / b Zeilengrad / c
   Zwischenwert: "b ist gut"): im Canvas standen Titel und Absatz im
   selben Grad, aber sobald das Leselicht durch ist, sind beide weiss,
   und dann truege nur noch der Abstand die Hierarchie. Die kleinere
   Vorzeile haelt sie dauerhaft. Links die Randspalte (20 %) mit nur
   dem Kicker, rechts der Block. Danach optional das Zitat des Systems (.tb-quote), dessen
   oberer Abstand hier per Instanzknopf groesser steht als der Default.
   Die Sektion traegt den Ink-Grund selbst.

   WARUM DER SCHNITT (Canvas-Befund am Ist): Titel links oben, Lesetext
   rechts unten, dazwischen 98px und zwei leere Quadranten - die Ruhe
   las sich als Leere, weil keine Achse die Bloecke verband; der
   24,5px-Absatz mit 70 Zeichen je Zeile war Fliesstext in
   Grossschrift, den niemand las; und auf neun Seiten dasselbe Bild an
   derselben Stelle wurde als Muster weggescrollt. Mobil blieb das
   98px-Loch als Desktopwert stehen. Die Alternativen (Split-Zeile,
   Faktenzeile mit Plakatgrad, drei Belege als Schrittzeilen) liegen im
   Canvas; B gewann, weil es als einzige ohne Werte und ohne Bild auf
   allen neun Seiten traegt - auf "Haltung" sogar am besten.

   RASTER: zwei gestapelte Gitter mit denselben Spalten (Kopf: Kicker |
   Titel; Koerper: leer | Absatz), damit Kicker und Titel EINE
   display-Einheit bleiben (Entscheidungsbaum Regel 6) und der Absatz
   sein eigenes Register (data-read) tragen kann, ohne verschachtelte
   data-reveal. Der Kicker haengt .15em unter der Blockkante, damit
   seine Versalhoehe mit der der Vorzeile fluchtet. text-wrap:balance am
   Titel (eine Zeile, notfalls zwei gleich lange), pretty am Absatz
   (volle Zeilen, kein Einzelwort am Ende); der Absatz folgt der
   Vorzeile um .7em seines Grads. Block auf 78rem gedeckelt,
   damit er ab 1600 nicht ueber rund 60 Zeichen je Zeile waechst; bei
   1440 ist die Spalte 1065px breit (Canvas-Mass).

   POLSTER: die Luft-Stufe des Sektionsrhythmus (tillit-tokens.css),
   auf allen Breiten; bis 24.09.2026 eigene 17vh plus ein Mobilwert.
   Die Naht zum Hero darueber ist Kanon (Abschnitt Sektions-Huelle,
   Bildkante) und haengt an .tb-hero--into-ink; bis dahin stand sie als
   .xx-hero + .tb-statement in vier Seiten, weil die Hero-Klasse je Seite
   verschieden ist. Unter 768 steht der Kicker ueber dem Block (die
   Grundspalte), kein 98px-Loch mehr. */
.tb-statement{position:relative;padding:var(--tb-section-y-air) 0;background:var(--tb-ink);color:var(--tb-white)}
.tb-statement__head,.tb-statement__body{display:grid;grid-template-columns:minmax(0,1fr);column-gap:clamp(1.5rem,3vw,3rem)}
.tb-statement .tb-index{margin:0 0 clamp(1.9rem,4.5vh,2.7rem)}
.tb-statement__title{margin:0;max-width:78rem;color:var(--tb-white);font-size:var(--tb-row-size);letter-spacing:-.025em;line-height:1.2;text-wrap:balance}
.tb-statement__text{margin:.7em 0 0;max-width:78rem;color:var(--tb-white);font-size:var(--tb-statement-size);letter-spacing:-.028em;line-height:1.24;text-wrap:pretty}
.tb-statement .tb-quote{--sh-quote-top:clamp(5.5rem,15vh,11rem)}
@media (min-width:768px){
  .tb-statement__head,.tb-statement__body{grid-template-columns:20% minmax(0,1fr)}
  .tb-statement__body > *{grid-column:2}
  .tb-statement .tb-index{margin:0;padding-top:.15em}
}

/* ======== LESELICHT (Zustandsschicht "Lesen") ========
   NEU 2026-09-06 mit dem Statement-Neuschnitt. Die zweite
   Zustandsschicht des Motion-Systems neben der Bildbuehne (Doku
   Abschnitt 6): scrollgebunden, bidirektional, ohne Erinnerung. Kein
   Reveal - der Absatz steht von Anfang an, er ist nur gedaempft
   (Alpha --tb-read-dim) und wird hell, sobald die Leselinie ueber ihn
   laeuft; zurueckgescrollt wird er wieder gedaempft.

   MECHANIK ohne Skript und ohne Wort-Spans: eine Verlaufsmaske,
   2,2-mal so hoch wie der Absatz - oben deckend (gelesen), unten
   gedaempft; der Saum (45,45-54,55 % der Maske, also ein Fuenftel
   der Absatzhoehe) liegt OBERHALB der Grenze, damit unter der
   Leselinie wirklich alles gedaempft steht und die Helligkeit von
   oben in die Linie hineinlaeuft (gemessen: Absatz unter der Linie =
   Maske 100 %). Die Laufweite ist deshalb entry 0 bis 120 %: die
   Maske faehrt um die Saumbreite ueber die Unterkante hinaus, sonst
   bliebe die letzte Zeile im Verlauf haengen (Befund Max 06.09.).
   Ihre Position haengt an der Sichtachse des Absatzes (view()) mit
   einer Einrueckung am unteren Fensterrand (--tb-read-inset): die
   Kante des eingerueckten Fensters IST die Leselinie. Der Bereich
   "entry" dieser Achse laeuft von "Oberkante des Absatzes erreicht
   die Leselinie" (0 %) ueber "Unterkante erreicht sie" (100 %) bis
   ein Fuenftel Absatzhoehe darueber hinaus (120 %); die Maske wandert
   dabei um 1,2 Absatzhoehen, die Grenze also im Gleichschritt mit der
   Leselinie - zeilengenau, unabhaengig von Absatzlaenge und
   Fensterhoehe. Die erste Fassung (Canvas) zerlegte den Absatz in
   Wort-Spans mit Index; das haette Screenreader in Einzelwoerter
   zerlegt und den Kernel gebraucht. Die Maske braucht beides nicht,
   das DOM bleibt der eine <p>.

   REIHENFOLGE: die animation-Kurzschreibweise setzt animation-timeline
   auf auto zurueck - timeline und range muessen DANACH stehen.

   VORAUSSETZUNG: kein Scroll-Container zwischen Absatz und Fenster.
   Der Werks-Wrapper #shop.oflow_hidden steht deshalb auf
   overflow:clip (tillit-shop-header-v2.css, bereits uebertragen),
   nicht auf hidden - hidden waere ein Scroll-Container, und die Achse
   hinge dann an ihm statt am Fenster.

   NETZ: Gate ist .tb-motion wie bei den Reveals (ohne Skript, ohne
   Observer, bei reduzierter Bewegung: Absatz steht weiss); Browser
   ohne Sichtachsen (Firefox, Stand 09/2026 nur Nightly) fallen ueber
   @supports auf weiss zurueck - das ist der Endzustand, kein
   Fehlerbild; im Druck faellt die Maske. Nichts bleibt gedaempft, was
   jemand lesen will: die Leselinie liegt UNTER dem Lesefokus. */
@supports (animation-timeline:view()){
  .tb-page.tb-motion [data-read]{
    -webkit-mask-image:linear-gradient(to bottom,#000 0,#000 45.45%,rgba(0,0,0,var(--tb-read-dim)) 54.55%,rgba(0,0,0,var(--tb-read-dim)) 100%);
    mask-image:linear-gradient(to bottom,#000 0,#000 45.45%,rgba(0,0,0,var(--tb-read-dim)) 54.55%,rgba(0,0,0,var(--tb-read-dim)) 100%);
    -webkit-mask-size:100% 220%;mask-size:100% 220%;
    -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
    animation:tbReadLight linear both;
    animation-timeline:view(block 0 var(--tb-read-inset));
    animation-range:entry 0% entry 120%;
  }
}
@keyframes tbReadLight{from{-webkit-mask-position:0 100%;mask-position:0 100%}to{-webkit-mask-position:0 0;mask-position:0 0}}
@media print{
  .tb-page [data-read]{-webkit-mask-image:none !important;mask-image:none !important;animation:none !important}
}


/* ======== BUEHNENHUELLE (.tb-stagehull) ========
   KANONISIERT 2026-09-25 (Werkstatt-Plan, Entscheidung M10 a): die
   Huelle stand dreimal deklarationsgleich als Seiteninstanz - .sh-trust
   (Startseite, Warum TilliT), .le-ablauf (Leasing, Ablauf), .ue-laden
   (Ueber uns, Der Laden). Vierter Verwender wird Werkstatt & Service
   (pages/werkstatt/, Ablauf). Werte 1:1; Elementboxen (Schwelle
   0,001 px) und berechnete Stile aller drei Seiten bei 390, 1440 und
   1920 px ohne Abweichung gegen c33205d (Chrome; Huelle, Schleier und
   Bild auch in Firefox und WebKit gleich).

   WAS DIE HUELLE IST: eine Ink-Sektion, deren erste Zeile eine randlose
   Foto-Buehne ist (.tb-stage--foto mit Kopf am Fuss). Der Schleier
   laesst das Bild in den Ink-Grund auslaufen, darunter steht der Inhalt
   im Container - Schrittzeilen (.tb-steps) oder eine eigene Liste
   (Startseite). Oben kein Polster: die Buehne bringt ihre Kante selbst
   mit, den Abstand davor setzt die BILDKANTE am Vorgaenger. Unten ein
   Sektionsschritt; die NAHTREGEL fuehrt die Huelle mit.

   EIGENER BLOCK, KEIN .tb-section--ink: wie Weiche und Statement ist
   die Huelle eine Ink-Flaeche ohne .tb-section. Als Sektions-Modifier
   bekaeme sie nach einer Luft-Sektion die Luft-Oberkante der Nahtregel
   (0,3,0) und stuende nicht mehr buendig - auf der Startseite ist der
   Vorgaenger (Individualisierung) genau so eine.

   SCHLEIER: der Desktop-Wert aller drei Verwender (ab 56 % Hoehe,
   weiche Stufen, Fuss exakt #0f0f0f, damit die Naht zur Ink-Flaeche
   keine Kante bekommt). :where() mit Absicht: die Regel wiegt 0,1,1
   wie die Seitenkopien, eine Instanzregel .x__stage::after schlaegt
   sie also ueber die Reihenfolge (Thementext nach "CSS - Ende"), ohne
   Spezifitaetsspiel. Mobil driftet der Schleier je Motiv - Leasing und
   Ueber uns ziehen auf 64 % an, weil der Kopf in der kuerzeren Buehne
   hoeher im Verlauf liegt; die dunkle Serpentine der Startseite bleibt
   auf dem Startwert. Deshalb steht hier kein Mobilwert.

   INSTANZ BLEIBT die Bildregel .tb-page .x__media: der Ausschnitt
   (object-position) je Motiv, und mit ihm der Strip-Fallback (width,
   height, object-fit, mobil die niedrigere Hoehe). Der Fallback haelt
   die Seite, falls die Bildbuehne aus "CSS - Ende" nicht ankommt - im
   selben Feld waere er mit ihr weg. Dazu der mobile Schleier und alles
   unter der Buehne.

   MARKUP: section.tb-stagehull[aria-labelledby] > ERSTES Kind
   div.tb-stage.tb-stage--foto (sonst greifen weder Schleier noch
   Bildkante) > img.tb-stage__media.x__media[data-reveal="media"] +
   div.tb-stage__head > .tillit-container > div.tb-stage__head-inner
   [data-reveal="display"] > .tb-index + h2.tb-head__title--xl; danach
   ein .tillit-container mit dem Inhalt. Instanzklassen nur, wo eine
   Seitenregel sie liest: .x__media immer (Ausschnitt), .x__stage fuer
   einen eigenen Schleier, .x an der Sektion fuer Seitenregeln darin
   (Startseite: .sh-trust .tb-quote). Leasing und Ueber uns fuehren
   deshalb keine Sektionsklasse mehr, die Startseite keine __stage.
   Gleich gebaut, aber noch Instanz: .bp-fit (Beratung, Bikefitting)
   mit eigenem Schleier ab 72 % - Kandidat, sobald die Beratungsseite
   angefasst wird. */
.tb-stagehull{position:relative;padding:0 0 var(--tb-section-y);background:var(--tb-ink);color:var(--tb-on-ink);overflow:hidden}
:where(.tb-stagehull) > .tb-stage--foto::after{content:'';position:absolute;left:0;right:0;bottom:0;height:56%;background:linear-gradient(180deg,rgba(15,15,15,0) 0%,rgba(15,15,15,.25) 40%,rgba(15,15,15,.55) 70%,rgba(15,15,15,.88) 92%,#0f0f0f 100%)}


/* ======== SCHRITTZEILEN AUF INK (.tb-steps) ========
   KANONISIERT 2026-09-04 mit dem zweiten Verwender (Ueber-uns-Seite).
   Stand bis dahin als .le-steps auf der Leasingseite (Ablauf). Werte
   1:1. Nummerierte Hairline-Zeilen auf Ink, meist unter einer
   Foto-Buehne: Mono-Kennziffer in der ersten Spalte (aria-hidden, die
   <ol> zaehlt fuer Screenreader selbst), Zeilentitel aus dem Kanon
   (.tb-row__title--ink), Lesetext auf Ink. Ab 900 zweispaltig, damit
   vier Schritte auf einer Bildschirmhoehe stehen; die letzten beiden
   Zeilen tragen die untere Hairline dann selbst, weil die Liste sie
   abgibt. Die Zeile ist eine Copy-Einheit: EIN data-reveal je <li> mit
   --sh-i, die Reihe zaehlt als eine Einheit.
   __links ist die optionale Verweiszeile unter dem Text (erster
   Verwender: Ueber-uns, Schritt "Testen"); sie fuehrt .tb-link--ink.

   Die Huelle darueber ist seit 2026-09-25 ebenfalls Kanon (Block
   BUEHNENHUELLE, .tb-stagehull); Bildausschnitt, Strip-Fallback und
   mobiler Schleier bleiben dort Instanz. Mobilspalte im MOBIL-Block. */
.tb-page .tb-steps{list-style:none;margin:clamp(3.2rem,8vh,6rem) 0 0;padding:0;border-bottom:1px solid var(--tb-line-ink)}
.tb-steps__item{display:grid;grid-template-columns:3.2rem minmax(0,1fr);gap:1.2rem;padding:clamp(1.5rem,3vh,2.1rem) 0;border-top:1px solid var(--tb-line-ink)}
.tb-steps__num{padding-top:.45rem;color:var(--tb-on-ink-muted);font-family:var(--tb-mono);font-size:var(--tb-font-label);letter-spacing:var(--tb-mono-tracking);font-variant-numeric:tabular-nums}
.tb-steps__text{margin:.8rem 0 0;max-width:52ch;color:var(--tb-copy-on-ink);font-size:var(--tb-copy-size);line-height:var(--tb-copy-leading);letter-spacing:var(--tb-copy-tracking)}
.tb-steps__links{display:flex;flex-wrap:wrap;gap:.8rem 2rem;margin-top:1.3rem}
@media (min-width:900px){
  .tb-page .tb-steps{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:clamp(3rem,6vw,5.5rem);border-bottom:0}
  .tb-steps__item:nth-last-child(-n+2){border-bottom:1px solid var(--tb-line-ink)}
}


/* ======== GALERIE (randlose Bildrolle mit Blaetterknoepfen) ========
   ACHTUNG, STAND 2026-09-04 ABEND: DIESE ROLLE HAT KEINEN VERWENDER
   MEHR. Sie wurde am Vormittag mit ihrem zweiten Verwender gehoben und
   verlor am selben Tag beide: die Ueber-uns-Seite fuehrt statt der
   Rolle ein stehendes Mosaik (Befund Max: "ux maessig bissl komisch" -
   wer Bilder sehen will, soll nichts bedienen muessen), und die
   Startseite hat ihre Einblicke-Sektion verloren (Entscheidung Max:
   "too much mit allem"). Der Block bleibt vorerst stehen, weil
   Loeschen der LETZTE Schritt ist und nie Beifang einer
   Gestaltungsaenderung (Kanonisierungsplan, Phase 7): faellt Max'
   Urteil zum Mosaik positiv aus, faellt dieser Block samt
   initGalleryNav im Kernel in einem eigenen Durchgang. Nichts davon
   ist im Shop, der Schnitt ist also folgenlos.
   KANONISIERT 2026-09-04 mit dem zweiten Verwender (Ueber-uns-Seite,
   pages/tillit/index.html). Stand bis dahin als .sh-gallery in der
   Startseite ("Einblicke", seit 2026-08-22 ohne Zieh-Geste). Werte 1:1
   uebernommen, kein Wert veraendert — einzige Ausnahme: das
   font-weight:400 der Bildunterschrift ist gefallen, weil die Gewichts-
   regel (tillit-base.css) es ohnehin setzt. Der Plan fuehrte die Rolle
   als Nr. 11 der Phase-3-Liste (".sh-gallery / .apx-gallery ->
   .tb-gallery"); die apx-Galerie (Slider mit Zaehler und Punkten) ist
   eine ANDERE Rolle und bleibt bis zu ihrem Port draussen.

   WAS DIE ROLLE IST: ein gewoehnlicher Scrollcontainer, Kante an
   Kante, erste Karte buendig mit dem Container, Scrollbar versteckt.
   Wischen mit Schwung, Trackpad, Shift+Rad, Pfeiltasten im
   fokussierten Container und Rasten macht der Browser. Die alte
   Maus-Zieh-Geste (200 Zeilen) ist 2026-08-22 gefallen: ZWEI
   Instanzen (scroll-snap-type und scrollLeft) bestimmten dieselbe
   Ruheposition, daraus kamen Spruenge bis 300 px. Wer die Geste
   zurueckholt, holt die Doppelherrschaft mit.

   proximity statt mandatory: der Streifen ist breiter als das Fenster,
   mandatory wuerde freies Stoebern verhindern. Erste und letzte Kachel
   haben keinen erreichbaren Rastpunkt und klemmen auf den Rand.

   overscroll-behavior-x:contain wie bei der rollenden Tableiste
   (.tb-tabs--roll): ohne die Regel kettet ein Trackpad-Wisch ueber das
   Ende hinaus an die Seite weiter und loest auf macOS die Zurueck-
   Geste aus.

   BLAETTERKNOEPFE: der sichtbare Griff fuer die MAUS — Finger, Trackpad
   und Tastatur brauchen ihn nicht, eine gewoehnliche Maus steht ohne
   ihn vor der Rolle und hat nichts (Rad scrollt die Seite, Scrollbar
   verborgen). Deshalb nur bei feinem Zeiger ab 768. Sie stehen UNTER
   der Rolle, nicht auf ihr (die Bilder sind die Flaeche), rechts-
   buendig. Zustandswechsel: Ring loest sich, Ink fuellt, weicher Hof,
   kein Lift. Am Ende der Rolle bleibt der Knopf STEHEN und wird still,
   statt zu verschwinden. Sie stehen MIT hidden im Markup und werden
   von initGalleryNav (Motion-Kernel) aufgedeckt: ohne Skript waeren
   sie tote Bedienung, und die Rolle scrollt ohne sie ohnehin.
   Die .3s der Knopf-Uebergaenge sind der Bestandswert der Startseite
   (Zustandsuhr --tb-dur-state waere .35s) — Kandidat beim naechsten
   Anfassen, nicht bei der Hebung.

   MARKUP: .tb-gallery (tabindex=0, role=group, aria-label) >
   figure.tb-gallery__item > img + figcaption; danach im Container
   .tb-gallery__nav[hidden] > button.tb-gallery__btn[data-gallery-step]
   mit aria-controls auf die id der Rolle. Reveal: EIN media-Wipe am
   Streifen. Mobilfassung im MOBIL-Block. */
.tb-gallery{display:flex;gap:1rem;margin-top:var(--tb-head-gap);padding-inline:max(1.25rem,calc((100vw - var(--tb-col)) / 2));padding-bottom:.5rem;overflow-x:auto;overscroll-behavior-x:contain;scrollbar-width:none;-webkit-overflow-scrolling:touch}
.tb-gallery::-webkit-scrollbar{display:none}
.tb-gallery{scroll-snap-type:x proximity}
.tb-gallery__item{flex:none;margin:0;scroll-snap-align:center}
.tb-page .tb-gallery__item img{height:clamp(300px,44vh,460px);width:auto;border-radius:var(--tb-radius);user-select:none;-webkit-user-drag:none}
.tb-gallery__item figcaption{margin-top:.9rem;color:var(--tb-ink-1);font-family:var(--tb-mono);font-size:.76rem;letter-spacing:var(--tb-mono-tracking);text-transform:uppercase}
.tb-gallery__nav{display:none}
@media (hover:hover) and (pointer:fine) and (min-width:768px){
  .tb-gallery__nav{display:flex;gap:.7rem;justify-content:flex-end;margin-top:1.5rem}
}
/* Das hidden-Attribut muss die Flex-Regel schlagen: das UA-display des
   Attributs verliert gegen jede Autorregel. Ohne diese Zeile stuenden
   die Knoepfe auch ohne Kernel da - tote Bedienung, genau das, was ihr
   hidden im Markup verhindern soll -, und nav.hidden aus initGalleryNav
   (nichts zu rollen) bliebe wirkungslos. Befund beim Gegenlesen der
   Ueber-uns-Seite 2026-09-04; die Startseite verdeckte ihn, weil ihre
   Rolle immer ueberlaeuft. */
.tb-gallery__nav[hidden]{display:none}
.tb-gallery__btn{display:grid;place-items:center;width:44px;height:44px;padding:0;border:1px solid var(--tb-line);border-radius:50%;background:transparent;color:var(--tb-ink-1);cursor:pointer;transition:background-color .3s var(--tb-ease-state),color .3s var(--tb-ease-state),border-color .3s var(--tb-ease-state),box-shadow .3s var(--tb-ease-state),opacity .3s var(--tb-ease-state)}
.tb-gallery__btn:hover,.tb-gallery__btn:focus-visible{border-color:transparent;background:var(--tb-ink);color:var(--tb-white);box-shadow:0 0 0 7px rgba(15,15,15,.08)}
/* Kein pointer-events:none: der Knopf bleibt fokussierbar und behaelt
   den Fokus, wenn er am Rollenende still wird (siehe initGalleryNav). */
.tb-gallery__btn[aria-disabled="true"]{opacity:.26;cursor:default}
.tb-gallery__ico{width:1rem;height:1rem}
.tb-gallery__ico--prev{transform:scaleX(-1)}
/* TABLET-BAND 768-1023 (Befund Gegenlesen 2026-09-04): die Hoehenformel
   der Basis macht die Bilder dort BREITER als das Fenster - gemessen bei
   768 px ein 801 px breites Bild in einem 753 px breiten Rollfenster.
   Kein Bild ist je ganz zu sehen, und der Rastpunkt der Mitte ist
   unerreichbar. Wie mobil deckelt hier die BREITE, die Hoehe folgt; die
   ungleiche Kante liegt wie dort oben. Ab 1024 traegt wieder die Hoehe,
   weil das Fenster dann breit genug ist. */
@media (min-width:768px) and (max-width:1023px){
  .tb-gallery{align-items:flex-end}
  .tb-page .tb-gallery__item img{width:min(62vw,520px);height:auto}
}


/* ======== MOSAIK (stehendes Bildfeld, .tb-mosaic) ========
   KANONISIERT 2026-09-24 (Entscheidung Max) mit dem zweiten
   Verwender. Stand bis dahin ZWEIMAL als Seitenkopie: .sh-mosaic auf
   der Startseite (Kategorien, seit 2026-09-02, Kategorien-Canvas
   Richtung H) und .ue-mosaic auf der Ueber-uns-Seite (Einblicke, seit
   2026-09-04, "Bauweise wie .sh-mosaic"). Die Kopien waren
   auseinandergelaufen: vier Spalten ab 1024 gegen ab 768, Reihen bei
   1440 px 380/300 gegen 2 x 331, mobil 218/179 gegen 4 x 164, und den
   Breitbild-Deckel vom 17.09. trug nur die Startseite. Gehoben ist die
   Geometrie der Startseite, fuer beide Verwender; sichtbar aendert
   sich damit nur die Ueber-uns-Seite (hoehere erste Reihe, vier
   Spalten erst ab 1024). Die Startseite ist pixelgleich.

   WAS DAS MOSAIK IST. Alle Bilder stehen, als EIN Feld: vier Spalten,
   zwei Reihen, zwei breite Felder (erste und letzte Kachel),
   dazwischen ein Pixel Weiss - die Hairline der Seite, nur als Luecke
   statt als Linie. Kein Zustand, kein Skript, keine Hoehenaenderung.
   Feste Zeilenhoehen statt Seitenverhaeltnissen, Bild absolut in der
   Kachel: so fluchten die Reihen unabhaengig vom Format der Motive
   (Ueber uns: zwei Hochformate, vier quer). Die Startseite fuehrt seit
   2026-09-28 sieben Kacheln mit EINEM breiten Feld (vorn); das Raster
   traegt beide Belegungen ohne eigene Regel (sechs Kacheln mit zwei
   breiten, sieben mit einem; mobil dann breit oben und drei Paare).
   Ohne Bildunterschriften:
   sie braeuchten Luecken und machten aus der Flaeche ein
   Kartenraster; was zu sehen ist, tragen die Alt-Texte.

   HERKUNFT DER FORM (Startseite, 2026-09-02). Das Mosaik loeste dort
   die Aufklappende Zeile vom 2026-08-22 ab, die ihrerseits das
   zeigerfolgende Bildfenster vom 2026-08-19 abgeloest hatte. Die Zeile
   zeigte genau ein Bild, und welches, entschied der Zeiger: fuenf von
   sechs Kategorien waren im Ruhezustand Text. Ihr Hover bewegte
   Geometrie (116 -> 396 px) - die einzige Stelle der Seite, an der ein
   Zeiger Layout verschob; min-height, Vorlauf und flex-grow standen
   dort nur als Schutz gegen die eigene Rueckkopplung -, und mobil
   brauchte sie ein Skript, das die Zeile nach Bildschirmmitte
   oeffnete. Die Bauart "Bild neben dem Link" stammt aus der Zeile und
   ist geblieben (s. MARKUP). Auf der Ueber-uns-Seite ersetzt
   das Mosaik seit 2026-09-04 eine Bildrolle (Befund Max: "ux maessig
   bissl komisch" - wer Einblicke sehen will, soll nicht blaettern).

   ZWEI FASSUNGEN. Das schlichte Mosaik (.tb-mosaic) zeigt Bilder als
   Inhalt: kein Link, kein Schleier, kein Label und KEIN Hover. Hover
   nur, wo ein Klick folgt (Lautstaerke-Regel, Motion-System): ein
   Zoom ueber einem Foto ohne Ziel verspraeche einen Klick, der nichts
   tut. Verwender: Ueber uns, Einblicke. Die Navigationsfassung
   (.tb-mosaic--nav) macht jede Kachel zum Link mit Schleier, Nummer,
   Name und Pfeil, Hover-Zoom im Bild und eigenem Fokusring.
   Verwender: Startseite, Kategorien. Regeln fuer die gemeinsamen
   Elemente (Kachel, Bild), die nur der Link-Kachel gelten, tragen
   deshalb :where(.tb-mosaic--nav) im Selektor - :where MIT ABSICHT,
   es wiegt 0: so behalten alle Regeln das Gewicht der Seitenkopie,
   und das Zusammenspiel von Hover, Fokus und Reduced Motion bleibt
   exakt das alte (die Fokusregel 0,5,0 schlaegt den stillgelegten
   Hover 0,4,0). Die reinen Link-Elemente (__scrim, __link, __label,
   __num, __name, __arrow) gibt es nur in dieser Fassung.

   GEOMETRIE. Das Feld liegt IM Container, nicht randlos: die
   1px-Luecken brauchen den weissen Grund. (Der zweite Grund der
   Startseite, "randlos hinter der randlosen Galerie waere Buehne nach
   Buehne", ist mit deren Einblicke-Sektion am 2026-09-04 entfallen;
   der erste traegt allein.) Mobil-first zwei Spalten (breite Felder
   oben und unten, zwei Paare dazwischen), ab 1024px vier Spalten.
   Die Reihenhoehen laufen in vw mit Deckel: das Feld waechst mit der
   Breite und belegt auf breiten Schirmen nicht die halbe Falz.
   Desktop 26.4vw/20.8vw sind 380/300px bei 1440, mobil 56vw/46vw
   sind 218/179px bei 390 - die Paare also nahezu quadratisch.

   RUNDUNG AM FELD, NICHT AN DEN KACHELN (Max, 2026-09-02). Die
   Systemregel: was als begrenztes Objekt im Container liegt, traegt
   --tb-radius (Galeriebilder, Testbike-Panels, Prozesskarten); was
   randlos laeuft oder als Flaeche liest, bleibt eckig (Buehnen,
   Zitat). Das Mosaik liegt im Container, also die Rundung - aber nur
   an den vier Aussenecken: sechs einzeln gerundete Kacheln laesen als
   sechs Karten, und genau das Kachelbild soll das Feld nicht sein.
   overflow:hidden schneidet die Aussenecken der Randkacheln;
   Hover-Skalierung und Fokusring liegen innerhalb der Kacheln und
   bleiben unberuehrt.

   .tb-page-Praefix ist Pflicht: der Listen-Reset (.tb-page ul,
   .tb-page ol {margin:0}) liegt bei 0,1,1 und schluckt sonst den
   Abstand zum Kopf. Gleiches fuer Bild und Link: '.tb-page img' und
   '.tb-page a' liegen bei 0,1,1, Lage und Weiss brauchen 0,2,0.

   MARKUP: ul.tb-mosaic[role=list][data-reveal="media"] >
   li.tb-mosaic__tile(--wide) > img.tb-mosaic__media. Die Navigations-
   fassung legt je Kachel dazu span.tb-mosaic__scrim[aria-hidden] und
   a.tb-mosaic__link > span.tb-mosaic__label > span.tb-mosaic__num
   [aria-hidden] + span.tb-mosaic__name + svg.tb-mosaic__arrow. DER
   LINK LIEGT UEBER DEM BILD, NICHT UM ES HERUM: das Bild ist Inhalt
   mit echtem alt und steht als Geschwister neben dem Link; laege es
   im Link, hinge sein alt-Text am zugaenglichen Namen ("Zwei
   E-Mountainbikes ... E-MTB" statt "E-MTB"). Die Nummern sind
   aria-hidden, der Name der Kachel ist die Kategorie selbst.
   Reveal: EIN media-Wipe am Feld, die Kacheln tragen keinen Zustand. */
.tb-page .tb-mosaic{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));grid-template-rows:clamp(11rem,56vw,18rem) clamp(9rem,46vw,16rem) clamp(9rem,46vw,16rem) clamp(9.5rem,46vw,16rem);gap:1px;margin-top:var(--tb-head-gap);border-radius:var(--tb-radius);overflow:hidden}
/* Ink als Grund, nicht Weiss: die Bilder laden lazy, und bis dahin
   soll die Kachel als dunkles Feld stehen, nicht als Loch im Feld. */
.tb-mosaic__tile{position:relative;overflow:hidden;background:var(--tb-ink)}
.tb-mosaic__tile--wide{grid-column:span 2}
.tb-page .tb-mosaic__media{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* Skalierung ueber 'scale', nicht 'transform' - dieselbe Eigenschaft
   wie an Hero und Einsatzort-Buehne. Dauer nach Ursache: eine
   Zeigergeste bewegt Flaeche, also --tb-dur-click. Nur die Link-
   Kachel bewegt sich, das schlichte Mosaik hat nichts zu ueberblenden. */
.tb-page :where(.tb-mosaic--nav) .tb-mosaic__media{transition:scale var(--tb-dur-click) var(--tb-ease-state)}
/* Ein Verlauf, nur unten: der Name braucht Grund, das Motiv nicht.
   45% Start, damit die obere Bildhaelfte unberuehrt bleibt. */
.tb-mosaic__scrim{position:absolute;inset:0;background:linear-gradient(180deg,rgba(15,15,15,0) 45%,rgba(15,15,15,.58) 100%)}
/* Der Link fuellt die Kachel absolut und traegt Nummer, Name und
   Pfeil unten links. */
.tb-page .tb-mosaic__link{position:absolute;inset:0;z-index:2;display:flex;align-items:flex-end;padding:clamp(1rem,1.55vw,1.6rem);color:var(--tb-white)}
.tb-mosaic__label{display:flex;align-items:center;gap:.7rem;width:100%;min-width:0}
.tb-mosaic__num{flex:none;color:rgba(255,255,255,.72);font-family:var(--tb-mono);font-size:.82rem;letter-spacing:var(--tb-mono-tracking)}
/* Der Name skaliert mit der Kachelbreite: bei 1024px sind die
   schmalen Kacheln 241px breit, "MTB Hardtail" muss neben Nummer
   und Pfeil in eine Zeile. 2.1rem (29,4px) erst ab 1440. Unter
   der Sektions-H2 und unter dem alten Zeilenindex (54,6px): die
   Kachel ist Bild, der Name ist Beschriftung. */
.tb-mosaic__name{flex:1;min-width:0;font-size:clamp(1.5rem,2.05vw,2.1rem);letter-spacing:-.025em;line-height:1.1}
/* Pfeil in fester Groesse statt clamp(13px,1.05vw,15px): mit der
   Box wanderte der Strich (7.75/76 x 13..15px = 1,33..1,53px).
   Jetzt die Groesse des Button-Chips, die einzige, fuer die der
   Sprite-Strich gerechnet ist: 13,3px, 7.75/76 = 1,36px. */
.tb-mosaic__arrow{width:.95rem;height:.95rem;flex:none;opacity:.9;transition:transform .4s var(--tb-ease-entry)}
/* FOKUSRING. Die Werksregel ':where(:focus-visible){outline:none
   !important}' loescht jeden Outline, gegen !important hilft keine
   Spezifitaet. Der Ring steht immer ueber dem Foto, also Weiss mit
   dunkler INSET-Unterlage: ein Gegenlichtbild hat helle Stellen
   genau dort, wo der Ring laeuft (WCAG 2.4.11). Offset negativ und
   Schatten inset, weil overflow:hidden der Kachel alles ausserhalb
   wegschneidet. Auch Offset und box-shadow brauchen !important:
   '.tillit-page a:focus-visible' (0,2,1) setzt sonst seinen eigenen
   'outline-offset:3px' - und ein Ring ausserhalb der Kachel ist
   genau der, den overflow:hidden frisst. Gegen den Systemring aus
   tillit-base.css (0,2,0, ebenfalls !important) gewinnt diese Regel
   ueber die Reihenfolge: das Feld CSS - Ende steht hinter CSS - Anfang. */
.tb-mosaic__link:focus-visible{outline:var(--tb-focus-width) solid var(--tb-white) !important;outline-offset:var(--tb-focus-inset) !important;border-radius:calc(var(--tb-focus-radius) - var(--tb-focus-inset));box-shadow:inset 0 0 0 7px rgba(15,15,15,.55) !important}
@media (min-width:1024px){
  /* Reihen-Deckel seit 17.09.2026 (Matrix-Sichtpruefung) um 1700/1384 gehoben
     (27.2rem -> 33.4rem, 21.5rem -> 26.4rem): die vw-Rampe deckelte exakt bei
     1442 px, darueber wurden die Kacheln mit der Insel breiter, aber nicht
     hoeher (E-MTB-Kachel 1,8:1 -> 2,2:1). Jetzt folgen die Reihen der Rampe
     bis rund 1770 px, wo auch die Insel steht. Bei 1440 gleich (380/300 px). */
  .tb-page .tb-mosaic{grid-template-columns:repeat(4,minmax(0,1fr));grid-template-rows:clamp(15rem,26.4vw,33.4rem) clamp(12rem,20.8vw,26.4rem)}
}
/* HOVER nur auf echten Zeigergeraeten und nur an der Link-Kachel:
   Skalierung im Bild und der Pfeil, die Geometrie steht. Das Bild
   skaliert INNERHALB der Kachel (overflow:hidden) auf
   --tb-panel-zoom (1.03, wie die Hero-Haelfte im :active und die
   Bildrollen des Kanons); der Pfeil rueckt 4px wie zuvor in der
   Zeile. Fokus loest dasselbe aus wie der Zeiger - der Ring dazu
   steht in der Basisregel. */
@media (hover:hover) and (pointer:fine) and (min-width:768px){
  .tb-page :where(.tb-mosaic--nav) .tb-mosaic__tile:hover .tb-mosaic__media,
  .tb-page .tb-mosaic__tile:has(.tb-mosaic__link:focus-visible) .tb-mosaic__media{scale:var(--tb-panel-zoom)}
  .tb-mosaic__tile:hover .tb-mosaic__arrow,
  .tb-mosaic__link:focus-visible .tb-mosaic__arrow{transform:translateX(4px)}
}
/* DRUCK, nur die Navigationsfassung. Ihr Schleier ist ein
   background-image und wird von Chrome und Firefox standardmaessig
   NICHT gedruckt - weisse Schrift stuende ungeschuetzt auf dem Foto.
   Auf Papier wird das Feld deshalb zur Kachelliste: Bild und
   Schleier weg, Name in Ink auf Weiss, eine Linie als Kachelrand
   (Rahmen drucken, Schatten nicht). gap:0, weil die weisse Luecke
   auf weissem Papier nichts mehr trennt. Auf der Startseite trifft es
   die Kategorien sicher, nicht nur wahrscheinlich: sie sind der letzte
   Inhalt der Seite und koennen per Konstruktion nie im ersten Fenster
   stehen. Das schlichte Mosaik druckt seine Fotos: auf ihnen steht
   keine Schrift, die Schutz braeuchte. Das Bild braucht das
   .tb-page-Praefix gegen '.tb-page img{display:block}' (0,1,1). */
@media print{
  .tb-page .tb-mosaic--nav{gap:0}
  .tb-page :where(.tb-mosaic--nav) .tb-mosaic__tile{background:#fff;border:1px solid #bbb}
  .tb-page :where(.tb-mosaic--nav) .tb-mosaic__media,
  .tb-mosaic__scrim{display:none}
  .tb-page .tb-mosaic__link{color:#111}
  .tb-mosaic__num{color:#666}
  .tb-mosaic__arrow{opacity:.5}
}


/* ======== TABLET — bis 1023px ========
   Dossier gestapelt: in einer halben Feature-Spalte blieben dem Wert
   zweispaltig nur rund 150 px, die Adresse brach dreizeilig (Befund
   Gegenlesen Ueber-uns 2026-09-04). Steht vor dem Mobil-Block, weil
   er ihn einschliesst (Regel: max-width hinter allen min-width-
   Bloecken; Kanon seit 07.09.2026). */
@media (max-width:1023px){
  .tb-dossier__row{grid-template-columns:1fr;gap:.35rem}
}


/* ======== KOPFZEILE MOBIL — bis 879px ========
   Grenze des Kopfs, nicht des Layouts: unter 880 endet die mobile
   Kopfzeile bei 95-99 px (Band 38 px plus Zeile) statt bei 114, das
   Kopfzeilenband ueber dem Hero (.tb-hero__scrim::before) wird deshalb
   kuerzer (23.09.2026, Befund H10). Steht zwischen TABLET und MOBIL,
   weil sein Bereich den Mobil-Block einschliesst und selbst vom
   Tablet-Block eingeschlossen wird (Regel: max-width hinter allen
   min-width-Bloecken, die breiteren zuerst). */
@media (max-width:879px){
  .tb-hero{--tb-hero-chrome:150px}
}


/* ======== MOBIL — bis 767px ========
   Steht als letzter LAYOUT-Block der Datei (Regel: max-width hinter
   allen min-width-Bloecken; im Feld "CSS - Ende" schlaegt sonst die
   Basisregel den eigenen Mobilwert). Dahinter folgt nur noch das
   Reduced-Motion-Netz, das aus demselben Grund zuletzt kommt.

   Die Kopf-Leiter, hergeleitet im Typo-Staffelungs-Kommentar der
   Startseite: der gewoehnliche Sektionskopf geht mobil eine Stufe
   zurueck, der Buehnenkopf traegt Faktor 1,41 darueber. Stand bis
   2026-08-24 je zweimal in den Seiten. An Inter gemessen (Gate A). */
@media (max-width:767px){
  /* Fahrplan und Kontaktzeile (Kanon seit 07.09.2026): eine Spalte,
     Button bzw. Link rutschen unter die Meta. */
  .tb-head--zeile,.tb-plan__head,.tb-plan__row{grid-template-columns:1fr}
  .tb-plan__row .tb-btn,.tb-plan__row .tb-link{margin-top:.5rem}
  .tb-contact{flex-direction:column;align-items:flex-start}
  /* Faktenzeile im Hero-Fuss: die <i>-Trenner verschwinden, der Punkt
     haengt stattdessen VOR dem folgenden Wort und wandert beim
     Umbruch mit ihm (Herleitung im Beratungsprozess, 2026-08). */
  .tb-hero__meta i{display:none}
  .tb-hero__meta span:not(:first-of-type)::before{content:"\00b7";margin-right:.85rem}
  /* Logoband: die Kennziffer rueckt mit dem kleineren Zellpolster ein. */
  .tb-logos__cell{padding:1.8rem 1rem}
  .tb-logos__num{top:.8rem;left:1rem}

  /* Galerie: mobil deckelt die BREITE, die Hoehe folgt (Herleitung
     Startseite 2026-08-21: die Basisregel bemisst die Kachel ueber die
     Hoehe — bei 390 px rendern die Bilder 484-814 px breit, keines
     passt ins Fenster, der Rastpunkt ist unerreichbar). 78vw/290px:
     ein Bild steht zentriert, links und rechts lugt der Nachbar hervor.
     Das Seitenverhaeltnis bleibt nativ; die ungleiche Kante liegt
     bewusst OBEN (flex-end), weil eine versetzte Bildoberkante als
     Anordnung liest, eine versetzte Unterschriftzeile als Fehler.
     Polster 14px = mobiler Seitenrand (die Basis ergaebe 17,5). */
  .tb-gallery{align-items:flex-end;padding-inline:14px}
  .tb-page .tb-gallery__item img{width:min(78vw,290px);height:auto}

  /* Statement: keine Zeile mehr. Die frueher hier gesetzte kleinere
     Lesestufe ist mit dem Neuschnitt 2026-09-06 gefallen (der Absatz
     laeuft im Aussagegrad, 24,5px am 390er-Boden, die Vorzeile im
     Zeilengrad, 21px), das Mobilpolster mit dem Rhythmus 2026-09-24. */
  /* Schrittzeilen: schmalere Kennziffernspalte. */
  .tb-steps__item{grid-template-columns:2.6rem minmax(0,1fr)}

  .tb-head__title{font-size:clamp(1.85rem,7.4vw,2.3rem)}
  /* Der Riese (--xl) braucht hier keine Zeile mehr: seine Kurve in
     --tb-display-size traegt die Mobil-Rampe selbst (seit 20.09.2026). */

  /* KEIN Sektionsrhythmus in diesem Block (seit 24.09.2026). Hier
     standen die Mobilpolster von .tb-section, --air, .tb-statement und
     .tb-weiche (G1-Hebung 2026-08-26: mobil blieben sonst 101/135 px
     Desktop-Polster neben einer 347-px-Spalte). Der Befund bleibt
     richtig, die Antwort war ein Sprung von 37-45 % bei 767/768. Die
     Rampe in tillit-tokens.css (--tb-rhythm) laesst die Breite fuehren,
     sobald das Fenster schmal ist: 74 px bei 390, stetig bis 768. Nicht
     wieder einen Mobilwert setzen - er wuerde die Rampe schlagen. */

  /* Foto-Buehne: mobil niedriger (Herleitung an der Startseite —
     84vh trugen 547 px Bild ohne Inhalt ueber dem Kopf). */
  .tb-stage--foto{height:clamp(320px,52vh,560px)}

  /* ---- Rollende Tableiste (Modifier --roll) ----
     Die Leiste wird randlos scrollbar; die Hairline bleibt auf der
     Textkante und kommt deshalb aus dem HINTERGRUND statt aus dem
     Rahmen (der Hintergrund steht am Element und rollt nicht mit).
     --sh-tabs-bleed ist der Randauszug (Default 14px = mobiler
     Seitenrand); die Maske blendet die Rolle rechts aus.

     KLIPPFIX, entschieden 2026-08-24 und am Browser bewiesen: der
     Bestand liess den transparenten Rahmen stehen, "damit die
     Aktivlinie bei top:-1px nicht weggeschnitten wird" — die Rechnung
     ging an der falschen Kante. Ein Scrollport clippt an der
     PADDING-Box, und die liegt hinter dem Rahmen: die Aktivlinie sass
     exakt 1px oberhalb der Clip-Kante und war mobil UNSICHTBAR
     (gemessen: Linie 1805,84–1806,84 gegen Clip-Kante 1806,84).
     Deshalb: die Linie rueckt auf top:0 (erste sichtbare Zeile des
     Scrollports) und die Hintergrund-Hairline zieht auf y=1 mit —
     damit liegen beide wieder exakt uebereinander, wie am Desktop. */
  .tb-tabs--roll{
    flex-wrap:nowrap;
    overflow-x:auto;
    overscroll-behavior-x:contain;
    margin-inline:calc(-1 * var(--sh-tabs-bleed,14px));
    padding-inline:var(--sh-tabs-bleed,14px);
    scrollbar-width:none;
    border-top-color:transparent;
    background-image:linear-gradient(var(--tb-line),var(--tb-line));
    background-repeat:no-repeat;
    background-origin:border-box;
    background-position:var(--sh-tabs-bleed,14px) 1px;
    background-size:calc(100% - 2 * var(--sh-tabs-bleed,14px)) 1px;
    -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 88%,transparent 100%);
    mask-image:linear-gradient(90deg,#000 0%,#000 88%,transparent 100%);
  }
  .tb-tabs--ink.tb-tabs--roll{background-image:linear-gradient(var(--tb-line-ink),var(--tb-line-ink))}
  .tb-tabs--roll::-webkit-scrollbar{display:none}
  .tb-tabs--roll .tb-tabs__tab{flex:none;white-space:nowrap}
  .tb-tabs--roll .tb-tabs__tab::after{top:0}
  /* Weiche: Falltitel auf der mobilen Leiter, Kennziffer entfaellt, die
     Querverweiszeile stapelt. */
  .tb-weiche__title{font-size:clamp(1.45rem,5.6vw,1.75rem)}
  /* WEICHE MOBIL: BAND AM FALL (29.09.2026). Der Hof unten links deckt
     bei 390 px nur die linke Haelfte des Falls, der hier ueber die volle
     Breite laeuft und je nach Seite bei 45 bis 70 % der Buehne beginnt.
     Gemessen (390 x 844, Kontrast pixelweise, 10. Perzentil): schon der
     alte Kanon lag auf drei Welten unter 4,5:1 (Road & Gravel Schotter
     Titel 1,8, Orbea MTB Satz 2,4, Cannondale Gravel Titel 2,3), mit der
     kuerzeren Naht unten fiel es bis 1,0. Deshalb liegt das Band mobil am
     Fall selbst: ein Verlauf hinter dem Container, der 4rem ueber dem
     Polster einsetzt (Kosinus in sechs Schritten) und an der Oberkante des
     Falls .84 erreicht - er folgt jeder Textlaenge, ohne Prozentwerte je
     Seite. Der Hof entfaellt (Herleitung wie an der Einsatzort-Buehne der
     Startseite), die Naht oben ist mobil 24 % statt 36 %: die Reiter
     stehen weiter im Dunkeln, das Bild bekommt vor dem Band noch Platz. */
  .tb-weiche__layers::after{background:linear-gradient(180deg,#0f0f0f 0%,rgba(15,15,15,.933) 4%,rgba(15,15,15,.75) 8%,rgba(15,15,15,.5) 12%,rgba(15,15,15,.25) 16%,rgba(15,15,15,.067) 20%,rgba(15,15,15,0) 24%,rgba(15,15,15,0) 72%,rgba(15,15,15,.25) 81.33%,rgba(15,15,15,.75) 90.67%,#0f0f0f 100%)}
  .tb-weiche__stage > .tillit-container::before{--tb-weiche-band:calc(4rem + clamp(3rem,8vh,5rem));content:"";position:absolute;left:0;right:0;top:-4rem;bottom:0;z-index:-1;pointer-events:none;background:linear-gradient(180deg,rgba(15,15,15,0) 0,rgba(15,15,15,.056) calc(var(--tb-weiche-band) / 6),rgba(15,15,15,.21) calc(var(--tb-weiche-band) / 3),rgba(15,15,15,.42) calc(var(--tb-weiche-band) / 2),rgba(15,15,15,.63) calc(var(--tb-weiche-band) * 2 / 3),rgba(15,15,15,.784) calc(var(--tb-weiche-band) * 5 / 6),rgba(15,15,15,.84) var(--tb-weiche-band),rgba(15,15,15,.9) 100%)}
  .tb-weiche__count{display:none}
  .tb-weiche__cross{align-items:flex-start;flex-direction:column;gap:.9rem}
  /* Modellzeilen: eine Spalte, die Datenreihe darf umbrechen. */
  .tb-model{grid-template-columns:minmax(0,1fr);gap:.5rem}
  .tb-model__data{white-space:normal}
}


/* ======== SCHMAL — bis 359px ========
   Faktenzeile im Hero-Fuss: unter 360px stapelt sie, der Trenner
   entfaellt (untereinander braucht es keinen). */
@media (max-width:359px){
  .tb-hero__meta{flex-direction:column;gap:.3rem}
  .tb-hero__meta span:not(:first-of-type)::before{content:none}
}


/* ======== REDUCED-MOTION-NETZ ========
   ANS DATEIENDE GEZOGEN (2026-09-01): der Block stand vorher hinter
   der Unterstrich-Feder und damit VOR den Basisregeln der Tabs — bei
   gleicher Spezifitaet gewinnt die spaetere Quellposition, die
   Tabs-Neutralisierung war toter Code (maskiert nur, solange jeder
   Verwender in .tb-page steht und der !important-Hammer greift).
   Gleiche Mechanik und gleiche Loesung wie in
   tillit-shop-header-v2.css: das Netz kommt zuletzt. */
@media (prefers-reduced-motion:reduce){
  /* Pauschalnetz zuerst: faengt alles ab, was die handgepflegten
     Selektoren nicht kennen oder in der Spezifitaet verlieren
     (Belegfall FAQ-Register, seit 2026-09-02 Kanon .tb-faq:
     .tb-faq__item[open] .tb-faq__answer wiegt 0,3,0 und schlaegt jeden
     einfachen Klassenselektor im Netz).
     !important ist Absicht - eine Luecke im Reduced-Motion-Netz ist
     ein A11y-Fehler, keine Stilfrage.

     Stand bis 2026-08-26 wortgleich doppelt in den Referenzseiten,
     waehrend die Testbikeflotte GAR KEIN Netz hatte (Kanonseiten-Audit
     F1) - als Kanon erbt es jetzt jeder Port automatisch. Die
     Seitenbloecke behalten nur noch ihre Unikate; Regeln, die
     zusaetzlich ZUSTAENDE setzen (Farbe, Deckkraft, Endposition),
     bleiben bestehen, weil eine blosse Dauerverkuerzung das nicht
     leistet. */
  .tb-page *,.tb-page *::before,.tb-page *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    animation-delay:0s !important;
    transition-duration:.01ms !important;
    transition-delay:0s !important;
  }
  /* Doppelt abgesichert: das Skript setzt .tb-motion bei Reduzierung
     ohnehin nicht - faellt das Gate doch, steht alles sichtbar. */
  .tb-page.tb-motion [data-reveal],
  .tb-page.tb-motion [data-reveal].is-in{opacity:1;filter:none;transform:none;transition:none}
  .tb-page [data-read]{-webkit-mask-image:none !important;mask-image:none !important;animation:none !important}
  #topnav .h_menu li.level0 > a .text::after,
  #Header .header_options .option a::after,
  .h_menu.megamenu li.level2 > a::after,
  .tillit-drawer__titlelink::after,
  .tillit-drawer__row-label::after,
  .tillit-drawer__sublink::after,
  #Footer .footermenu a.level0::after,
  #Footer .footermenu .simlink::after,
  #newCookieJar .cookiefooter .simlink::after,
  :is(#compare_small, #wishlist) .f-color--light::after,
  body:has(#compare) #compare a::after,
  body:has(#compare) #compare .my-favorite::after,
  #footer_mwst a:not(.button_default)::after,
  #Footer .tb-credit a::after,
  #Footer #footer_mail a.individual_content::after,
  #Footer #footer_tel a::after,
  .lightlink:not(.after)::after,
  .lightlink.after::before,
  body.page_agb #agbgliederung a::after,
  body.page_angemeldet #Middle #mk .content a::after,
  #breadcrumb a::after,
  body.a_article .tb-service__cta a::after,
  body.a_article #ask-a-question button.button_default::after,
  .tb-anchors__link::after,
  .pagenavigation .navigation > :is(a:not(.button_default), .active)::after,
  .tb-link::after,
  .sh-split__link::after{transition:none}
  /* Auch der Chevron-Chip steht still: keine Gleitfahrt beim Hover.
     Stand vorher nur im Reduced-Block des Beratungsprozesses — das
     Verhalten gehoert der Komponente, nicht der Seite. Der
     Anker-Chevron faehrt seit der P2-Tilgung nur noch Opacity —
     auch die springt hier statt zu gleiten. */
  .tb-link svg,.tb-anchors__link svg{transition:none}
  /* Fliesstext-Feder: die Linie springt, statt zu laufen. */
  .tb-page a.tb-flow{transition:none}
  .tb-link:hover svg{transform:none}
  /* Bildbuehnen: der Parallax-Treiber laeuft bei Reduzierung gar nicht
     erst an, --sh-stage-y bleibt ungesetzt und das Bild steht in der
     Mitte seines Wanderwegs. Die Regel ist das Netz gegen einen
     Inline-Wert, der aus einer Sitzung vor dem Umschalten stehen
     geblieben ist. */
  .tb-page .tb-stage .tb-stage__media{translate:none;animation:none}
  /* Button: ohne Bewegung fallen die Buchstaben nicht - der text-shadow
     liegt ausserhalb des Fensters und bleibt von selbst unsichtbar.
     Chip- und Pfeilfahrt stehen still. */
  .tb-btn__chip,.tb-btn__arrow,.tb-btn__label .tb-btn__letter,
  .tb-btn:hover .tb-btn__chip,.tb-btn:hover .tb-btn__arrow{transition:none}
  .tb-btn:hover .tb-btn__label .tb-btn__letter,.tb-btn:focus-visible .tb-btn__label .tb-btn__letter{transform:none}
  /* Register: die Aktivlinie springt statt zu gleiten. */
  .tb-tabs__tab,.tb-tabs__tab::after{transition:none}
  /* Flottenkarte: der Hover-Zoom entfaellt. */
  .tb-page .tb-fleet__media img{transition:none}
  .tb-fleet__card:hover .tb-fleet__media img{transform:none}
  /* Bild-Text-Zeile: derselbe Zoom, dieselbe Stilllegung. */
  .tb-page .tb-feature__media img{transition:none}
  .tb-feature__media:hover img{transform:none}
  /* Mosaik, Link-Kachel: Zoom und Pfeil fahren nicht, der Zeiger-Hover
     entfaellt. Der Tastaturfokus behaelt Zoom und Pfeilversatz, nur
     ohne Fahrt - Bestand der Startseite, 1:1 gehoben. Das Bild steht
     BEWUSST NICHT in der transition:none-Zeile: die Seitenkopie
     fuehrte es dort mit 0,1,0, die Zeile verlor gegen die eigene
     Basisregel (0,2,0), und die Fahrt kuerzte allein das Pauschalnetz
     auf .01ms. Eine greifende Zeile aendert das Compositing des Bildes
     (gemessen 2026-09-24 in Chrome: 221 Pixel um 1/255 anders) - der
     Kanon uebernimmt das wirksame Verhalten, nicht die tote Zeile. */
  .tb-mosaic__arrow{transition:none}
  .tb-mosaic__tile:hover .tb-mosaic__arrow{transform:none}
  .tb-page :where(.tb-mosaic--nav) .tb-mosaic__tile:hover .tb-mosaic__media{scale:1}
  /* Logoband: kein Zoom, kein Nachbar-Dimmen im Gleiten. */
  .tb-logos__img{transition:none}
  .tb-logos__cell:hover .tb-logos__img{transform:none}
  /* FAQ-Register: die Antwort steht sofort scharf da, das Lesefeld
     springt auf seine Hoehe. Der volle Selektor .tb-faq__item[open]
     .tb-faq__answer (0,3,0) ist noetig - er schlaegt jeden einfachen
     Klassenselektor im Netz (Belegfall aus dem Beratungsprozess). */
  .tb-faq__question,.tb-faq__arrow,.tb-faq__answer,.tb-faq.is-js .tb-faq__panel{transition:none}
  .tb-faq__item[open] .tb-faq__answer{animation:none;transition:none}
  /* Weiche: Ebenen und Faelle wechseln ohne Blende, kein Zoom-Ausklang. */
  .tb-page .tb-weiche__layer,.tb-weiche__case{transition:none}
  .tb-page .tb-weiche__layer{scale:1}
  /* Modellzeilen: der Satzwechsel springt. */
  .tb-models__set{transition:none}
}
