/* ============================================================================
   Designsystem Talentschmiede Bode - Stufe 1
   Eine Datei, eine Wahrheit. Ersetzt die 13 Kopien im post_content (Stufe 3).
   Geladen von tsb-design.php nach allen Theme-Stylesheets (deps).

   Stufe 1 enthaelt: Tokens + Basis-Typografie + die drei Fehler, die Besucher heute treffen.
   Die Komponenten (Button, Karte, Hero, Baender) folgen in Stufe 3.
   ============================================================================ */

/* ---------------------------------------------------------------- 1. Tokens */
:root{
  /* --- Schrift ---------------------------------------------------------- */
  --font-head: 'Titillium Web', system-ui, sans-serif;
  --font-body: 'Lato', system-ui, sans-serif;

  /* Stufen. Kein Paar liegt unter Faktor 1,12 - sonst waeren es zwei Namen fuer eine Groesse. */
  --fs-xs:      0.75rem;                          /* 12px - Kicker, Label, Badge, Chip-Meta */
  --fs-sm:      0.875rem;                         /* 14px - Stat-Label, Fussnote */
  --fs-base:    1rem;                             /* 16px - Fliesstext, Felder, Kartentext */
  --fs-md:      1.1875rem;                        /* 19px - Lead, Hero-Sub, Intro */
  --fs-lg:      1.375rem;                         /* 22px - Kartentitel */
  --fs-xl:      1.625rem;                         /* 26px - h3 Lesespalte */
  --fs-2xl:     clamp(1.9rem, 2.8vw, 2.25rem);    /* 36px - h2, Stat-Zahl, h1 Rechtsseiten */
  --fs-3xl:     clamp(2.2rem, 4.2vw, 3.25rem);    /* 52px - h1 Verkaufsseiten */
  --fs-display: clamp(2.75rem, 5.5vw, 4.4rem);    /* 70px - Preis */
  --fs-suffix:  0.42em;                           /* Euro-Zeichen im Preis */

  --lh-1:     1;      /* Buttons, Kicker, Stat-Zahl */
  --lh-tight: 1.04;   /* h1, Preis */
  --lh-flat:  1.2;    /* h2, h3, Kartentitel */
  --lh-base:  1.5;    /* Fliesstext bei kurzem Mass */
  --lh-loose: 1.7;    /* Fliesstext in Lesespalten */

  --track-display: -0.02em;   /* ohne negatives Tracking wirkt Titillium 700 bei 52px hochskaliert */
  --track-tight:   -0.01em;
  --track-normal:  0;
  --track-kicker:  0.14em;

  /* --- Farbe: Rollen, keine Farbnamen ----------------------------------- */
  --ink:            #141615;   /* 18,18:1 auf Weiss  - Ueberschriften, dunkle Flaechen */
  --ink-body:       #1c201d;   /* 16,49:1 auf Weiss  - Fliesstext site-weit */
  --muted:          #5f6862;   /*  5,76:1 auf Weiss  - Sekundaertext, Meta */
  --line:           #e6e9e6;   /* dekorativ          - Trenner, Kartenkanten */
  --line-field:     #7d8680;   /*  3,75:1 (SC 1.4.11) - NUR Bedienelemente */
  --placeholder:    #6b736d;   /*  4,89:1 auf Weiss */
  --surface:        #ffffff;
  --surface-alt:    #f4f6f4;
  --surface-dark:   #141615;
  /* Trenner auf dunklem Grund. Weiss mit Alpha, damit es auf jeder dunklen Flaeche
     traegt und nicht nur auf --surface-dark; dort ergibt es effektiv #353635 (1,50:1,
     dekorativ). Getragen wird damit der mobile Kopf: Linie unter der Kopfleiste,
     Abschluss unter dem geoeffneten Menue [TSB-BLOCK:kopf-sticky] und die Trenner
     zwischen den Menueeintraegen [TSB-BLOCK:kopf-mobil].
     ⚠️ Bis 16.08.2026 gab es dieses Token NICHT, obwohl drei Abschnitte es aufriefen -
     die Deklarationen fielen lautlos aus und die Trenner behielten das Theme-Grau
     #eaeaea. Wer den Wert aendert, aendert damit drei Stellen im mobilen Kopf auf
     einmal: nachmessen UND ins Bild schauen. */
  --line-on-dark:   rgba(255,255,255,.14); /* dekorativ, 1,50:1 auf --surface-dark */
  --accent:         #0a6b2e;   /*  6,66:1 auf Weiss  - Marken-Gruen: Links, Kicker, Fokus, Raender */
  --accent-bright:  #43ec6b;   /*  Flaeche, 1,56:1   - immer nur als Flaeche, nie als Text auf Hell */
  --accent-ink:     #06331a;   /*  8,99:1 auf accent-bright - Text auf dem Primaerbutton */
  --accent-soft:    rgba(10,107,46,.12);
  --gold:           #e9c46a;   /*  9,92:1 auf #1b2018 - Label der Gutschein-/Bonuskarten-Grafik */
  --on-dark:        #ffffff;
  --on-dark-muted:  #9aa39c;   /*  7,00:1 auf --ink */
  --error:          #c0392b;   /*  5,44:1 auf Weiss */
  --focus:          var(--accent);
  --focus-on-dark:  var(--accent-bright);

  /* --- Abstand: 8px-Raster ---------------------------------------------- */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 72px;

  --band-y:            var(--s-9);
  --band-y-mobile:     var(--s-7);
  --band-first:        var(--s-5);
  --band-first-mobile: 18px;
  --gutter:            clamp(16px, 4vw, 22px);
  --anchor-offset:     var(--s-5);   /* kein Sticky-Header mehr, daher klein */

  /* --- Form ------------------------------------------------------------- */
  --r-sm: 10px; --r-md: 14px; --r-lg: 18px; --r-pill: 999px; --r-full: 50%;

  --b-hair:   1px solid var(--line);
  --b-field:  1px solid var(--line-field);
  --b-accent: 3px solid var(--accent);

  --sh-card:  0 1px 2px rgba(20,22,21,.04), 0 8px 24px rgba(20,22,21,.06);
  --sh-lift:  0 2px 4px rgba(20,22,21,.06), 0 12px 32px rgba(20,22,21,.10);
  --sh-focus: 0 0 0 3px var(--accent-soft);

  --t-fast: 120ms ease;   /* transform */
  --t-base: 150ms ease;   /* color, background, border-color, box-shadow */

  /* --- Mass ------------------------------------------------------------- */
  --w-page:   1100px;
  --w-read:   62ch;   /* in Lato 16px ~547px ~75 Zeichen */
  --w-narrow: 46ch;
  --w-sub:    52ch;

  /* --- Alias fuer den Bestand (Stufe 3) --------------------------------- */
  /*
     Die 13 Seitenkopien definierten ihre Tokens selbst - in drei Varianten, mit drei
     Namen fuer dasselbe Gruen (--green-dk und --green-ink sind beide #0a6b2e) und zwei
     Werten fuer --gold (#e9c46a trug das Label der Produktgrafiken, #f2c14e war tot).
     Die Kopien fallen, die var()-Referenzen im Bestand bleiben - diese Alias loesen sie auf.
     Ohne sie waeren die Referenzen ungueltig, und eine ungueltige background-Deklaration
     faellt in keinem HTML-Diff auf, nur im Bild.

     NICHT als "unbenutzt" streichen. Erst wenn grep -c 'var(--green' = 0 ist.
  */
  --green:     var(--accent-bright);
  --green-dk:  var(--accent);
  --green-ink: var(--accent);
  --alt:       var(--surface-alt);
}

/* ------------------------------------------------- 2. Basis-Typografie */
/*
   NUR die Textfarbe global: das Theme setzt body{color:#929191} = 2,84:1 auf Weiss
   und verfehlt damit AA auf jeder Seite (auch Shop, Portrait, Aktuelles).
   Groesse und Zeilenhoehe bleiben bewusst am Theme - body{font-size:15px;line-height:1.66667em}
   global umzustellen wuerde Shop, Kasse, Warenkorb, Blog und alle Widgets mitverschieben.
*/
body{ color: var(--ink-body) }

:is(h1,h2,h3,h4,h5,h6){ font-family: var(--font-head) }

/*
   Auf den eigenen Seiten setzen wir die Basis vollstaendig.
   ZWINGEND: line-height als Faktor. Das Theme vererbt 1.66667em = eine LAENGE (25px),
   die sich NICHT mit der Schriftgroesse skaliert - daher ist .btn heute 54px hoch
   und .tsb-btn 44,2px, obwohl beide dasselbe sein sollten.
*/
.tsb, .tsb-legal, .tsb-tm{
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}

/* --------------------------------------------- 3. Container-Fix (Handy) */
/*
   modules-responsive.min.css schaltet den Container in festen px-Stufen:
   >=1400:1300 | 1201-1399:1100 | 1025-1200:950 | 769-1024:768 | 601-768:600 | 481-600:420 | 321-480:300
   Bei 390px Viewport bleiben nach 2x22px Gutter 256px Inhalt - 134px liegen brach.
   Ein 320px-Handy bekommt mit 95% MEHR Text als ein 480px-Handy mit 300px.

   Nur unter 768px. Darueber bleibt die Theme-Leiter unangetastet: dort ist sie sinnvoll
   und dort liegt das Risiko (Shop, Blog, Startseite). Kein :has()-Scope, weil ein nach
   Seitentyp unterschiedlicher Container auf jedem Handy einen sichtbaren Kantenversatz
   zwischen Header, Inhalt und Footer erzeugen wuerde - schlechter als der Bug.

   Spezifitaet (0,1,0) reicht, weil diese Datei nach modules-responsive.min.css laedt.
*/
@media (max-width: 768px){
  /*
     .mkd-grid-section .mkd-section-inner ist bewusst NICHT dabei, obwohl die Theme-Regel
     es mitnennt: das traegt die Startseite (Full-Width-Template, RevSlider). Dort liegen
     die Rows nicht in .mkd-container-inner, die Neutralisierung der WPBakery-Margins
     unten greift also nicht - gemessen wurde ein Anstieg des Ueberlaufs von 15 auf 35px.
     Die Startseite gewinnt durch die Befreiung nichts (ihr Inhalt ist ohnehin Full-Width)
     und bleibt deshalb unangetastet.
  */
  .mkd-container-inner,
  .mkd-grid{
    width: auto;
    max-width: none;
  }

  /*
     Der Titelbereich zentriert seinen Titel per display:table + vertical-align:middle.
     Fuer ein Tabellen-Element heisst width:auto NICHT "volle Breite", sondern shrink-to-fit:
     gemessen 155px statt 390px auf /portrait/, 145px auf /camps/ - ein langer Untertitel
     wuerde dadurch unnoetig umbrechen. Er braucht die Breite explizit.
     Betrifft die 6 Seiten mit Titelbereich-Hero (Typ B/E).
  */
  .mkd-title .mkd-container-inner{ width: 100% }

  /* Der Gutter sitzt jetzt am Container - damit fluchten Header, Inhalt und Footer. */
  .mkd-container-inner,
  .mkd-grid{
    padding-inline: var(--gutter);
  }

  /*
     js_composer: .vc_row{margin-inline:-15px} und .vc_column-inner{padding-inline:15px}
     heben sich heute nur auf, weil der Container 45px Luft daneben hat. Ohne diese zwei
     Zeilen schoebe die Row 15px ueber den Viewport hinaus. body{overflow-x:hidden!important}
     wuerde das VERSTECKEN statt zu loesen - der Ueberlauf waere real und die Karte rechts
     abgeschnitten.
  */
  .vc_row{ margin-inline: 0 }
  .vc_column_container > .vc_column-inner{ padding-inline: 0 }

  /*
     Dasselbe Muster noch einmal in Theme-eigenen Klassen: die Spaltengitter des Footers
     tragen margin:0 -15px auf ihrem *-inner. Ohne diese Zeilen ragt der Footer 15px nach
     links aus dem Bild, sobald der Container befreit ist (gemessen an .mkd-column: 420px
     breit in einem 358px-Container).
  */
  .mkd-two-columns-50-50 > .mkd-two-columns-50-50-inner,
  .mkd-three-columns > .mkd-three-columns-inner,
  .mkd-four-columns > .mkd-four-columns-inner,
  .mkd-five-columns > .mkd-five-columns-inner{ margin-inline: 0 }

  .mkd-column > .mkd-column-inner{ padding-inline: 0 }

  /*
     Der Gutter sitzt jetzt am Container, die eigenen Wrapper wuerden ihn verdoppeln
     (16 + 22 = 38px Rand auf einem 390px-Display).

     Das !important ist temporaer und faellt in Stufe 3: die Seitenregeln stehen als
     body.page-id-XXXX .tsb-inner (0,2,1) im post_content, also spaeter im Dokument
     und hoeher spezifiziert als alles, was diese Datei aus dem <head> beitragen kann.
     Ohne das !important bleiben 314px statt 358px.
  */
  .tsb-inner, .tsb-legal-wrap, .tsb-tm-wrap{ padding-inline: 0 !important }
}

/* Kein Titelbereich = kein Theme-Vorabstand ueber dem eigenen Hero.
   ACHTUNG: Die frueher hier stehende Regel

       .tsb .mkd-container-inner,
       .tsb-legal .mkd-container-inner{ padding-top: 0 }

   hat NIE gegriffen. Sie verlangt den Container innerhalb von `.tsb`, tatsaechlich
   liegt `.tsb` im Container (`closest('.tsb')` ueber 19 Seiten ausnahmslos false).
   Folge waren 66px toter Weissraum auf 15 Seiten. Ersatz mit `:has()` steht in
   Abschnitt 41 [TSB-BLOCK:seitenanfang], 22.07.2026. */

/* ------------------------------------------------ 4. Kartengitter (Mobil) */
/*
   Vorgezogen aus Stufe 3, weil es ein sichtbarer Fehler ist und zwei Zeilen kostet:
   .tsb-hl (760px), .perks (720px) und .amts (640px) haben feste Spalten und schneiden
   auf 5 Verkaufsseiten unter ihrem Breakpoint die letzte Karte ab.
   auto-fit reflowt von selbst und braucht gar keinen Breakpoint.

   Das !important ist bewusst und temporaer: die Seitenregeln haengen an body.page-id-XXXX
   (Spezifitaet 0,3,1) und stehen spaeter im Dokument. Sie fallen in Stufe 3, dann faellt
   auch dieses !important.
*/
body:has(.tsb) :is(.tsb-hl, .perks, .amts){
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)) !important;
}
body:has(.tsb) :is(.tsb-hl, .perks, .amts) > *{ min-width: 0 }

/* ---------------------------------------------------- 5. Links (global) */
/*
   modules.min.css faerbt JEDEN Link mit der Trophy-Lime #c1e729 = 1,43:1 auf Weiss.
   Das ist auf allen 18 Seiten ein AA-Verstoss, nicht nur in der Navigation.
*/
/*
   Die Theme-Regel lautet vollstaendig:
     a, h1 a:hover, ... h6 a:hover, p a { color:#c1e729 }
   Ein blosses a{} (0,0,1) verliert deshalb gegen "p a" (0,0,2) - gemessen an 5 Links
   auf der Startseite, die trotz der Regel unten limettengruen blieben.
*/
a{ color: var(--accent) }
p a{ color: var(--accent) }
a:hover, p a:hover{ color: var(--ink) }
:is(h1,h2,h3,h4,h5,h6) a,
:is(h1,h2,h3,h4,h5,h6) a:hover{ color: inherit }
.tsb :is(p, li, td) a:not([class]){ text-decoration: underline; text-underline-offset: 2px }

/* Auf dunklem Grund traegt Weiss, nicht Gruen. */
.tsb-band--dark a,
.mkd-page-footer a,
.mkd-footer-inner a{ color: var(--on-dark) }
.tsb-band--dark a:hover,
.mkd-page-footer a:hover,
.mkd-footer-inner a:hover{ color: var(--accent-bright) }

/* ------------------------------------- 6. Navigation und Dropdown (Lime) */
/*
   Aktive und gehoverte Menuepunkte stehen in #c1e729 auf Weiss (1,43:1), die Ruhefarbe
   #9b9a9a bei 2,81:1. style_dynamic.css enthaelt dazu keine Regel, die das aufhebt.
*/
.mkd-main-menu > ul > li > a:hover,
.mkd-main-menu > ul > li.mkd-active-item > a{ color: var(--accent) }

.mkd-drop-down .second .inner ul li a{ color: var(--ink-body) }
.mkd-drop-down .second .inner ul li a:hover,
.mkd-drop-down .second .inner ul li.current-menu-item > a,
.mkd-drop-down .second .inner ul li.current_page_item > a{ color: var(--accent) }

/*
   BESTANDSFEHLER (per A/B mit abgeschalteten mu-plugins verifiziert - NICHT aus dieser Runde):
   zwischen ca. 1025 und 1200px Fensterbreite ist die Hauptnavigation unlesbar, weisse Schrift
   auf weisser Flaeche.

   Ursache (gemessen, nicht geraten): das Theme-Raster ist dort nur 950px breit, Logo (77px)
   und Menue (918px) passen mit 995px nicht nebeneinander -> das Menue bricht in eine zweite
   Zeile um. Die dunkle .mkd-menu-area ist aber fest 85px hoch, der Header 170px: das
   umgebrochene Menue liegt UNTERHALB der dunklen Flaeche, auf dem weissen Seitengrund.
   Es half deshalb nicht, .mkd-menu-area einzufaerben - die Farbe war schon richtig, nur die
   Flaeche zu klein.

   Fix: der Header traegt die Marken-Flaeche selbst. Damit ist jede Zeile abgedeckt, egal ob
   der Header ein- oder zweizeilig umbricht. Auf einem 1440px-Monitor sieht man den Fehler nie,
   auf einem normalen Laptop sofort.
*/
.mkd-page-header{ background-color: var(--ink) }

/* Der Button ist die einzige Flaeche, auf der die helle Marke traegt. */
#mkd-back-to-top > span{
  background-color: var(--ink);
  border-color: var(--ink);
  color: var(--on-dark);
}
#mkd-back-to-top:hover > span{
  background-color: var(--accent);
  border-color: var(--accent);
  color: var(--on-dark);
}

/* -------------------------------------------------------- 7. Fokusring */
/*
   modules.min.css setzt in einem 61-Selektoren-Reset outline:0 auf a. Keine der 25
   Stylesheets holt ihn zurueck: Tastaturnutzer sehen auf den meisten Seiten nicht,
   wo sie sind. :focus-visible zeigt ihn nur bei Tastaturbedienung, nicht bei Mausklick.
*/
/*
   Das !important ist hier bewusst und bleibt auch nach Stufe 3.
   Begruendung: WooCommerce und das Theme setzen outline:none auf hoeher spezifizierten
   Selektoren (a.button.add_to_cart_button, input.search-field, button#searchsubmit -
   gemessen: 8 Elemente auf /shop/, 4 auf der Startseite). Diesen Wettlauf gewinnt man
   nicht dauerhaft ueber Spezifitaet, und es gibt keinen legitimen Grund, den Fokusring
   zu unterdruecken: ohne ihn ist die Seite per Tastatur unbedienbar (WCAG 2.4.7).
*/
/*
   Einzelwerte statt Kurzschreibweise, das ist hier zwingend:
   "outline: 2px solid var(--focus)" enthaelt ein var() und wird deshalb zur Parse-Zeit
   NICHT in seine Langformen zerlegt (pending substitution). outline-width blieb dadurch
   leer und das outline:0 des Themes gewann - trotz !important. Verifiziert per
   CSS.getMatchedStylesForNode: 'outline-width: !important' ohne Wert.
*/
:is(a, button, input, select, textarea, [tabindex]):focus-visible{
  outline-width: 2px !important;
  outline-style: solid !important;
  outline-color: var(--focus) !important;
  outline-offset: 3px;
  border-radius: 2px;
}
.tsb-band--dark :is(a, button):focus-visible,
.mkd-page-header :is(a, button):focus-visible,
.mkd-page-footer :is(a, button):focus-visible,
.mkd-footer-inner :is(a, button):focus-visible{
  outline-color: var(--focus-on-dark);
}

/*
   Das Dropdown wird nur per Hover-JS sichtbar - die 6 Unterpunkte (Einzeltraining,
   Gruppentraining, Bonuskarte, Geschenkgutschein, BSA, Tagescamp) sind per Tastatur
   sonst unerreichbar (WCAG 2.1.1, Level A).
*/
.mkd-drop-down .second{ visibility: hidden }
.mkd-main-menu > ul > li:focus-within .second{
  visibility: visible;
  opacity: 1;
  height: auto !important;
  overflow: visible;
}

/* ------------------------------------------------------ 8. Formulare */
/*
   EINE Quelle fuer alle 8 CF7-Formulare. Ersetzt die 7 seiteneigenen Bloecke im
   post_content und den Inline-Block aus tsb-forms.php.

   SPEZIFITAETS-FALLE, die alles entscheidet: modules.min.css setzt
     .wpcf7-form-control.wpcf7-text, ...-textarea, ...-select, ...-date, ...-number
     { border:2px solid #edecec; font-size:15px; padding:10px 15px; margin-bottom:16px }
   = (0,2,0). Ein Selektor wie ".wpcf7 input[type=text]" ist (0,1,1) und verliert dagegen
   IMMER. Deshalb selektieren wir ueber die CF7-Klasse .wpcf7-form-control -> (0,2,1).
   Heute gewinnt nur "body.page-id-X .wpcf7 ..." (0,3,1) - also genau das, was hier faellt.
*/
.wpcf7{
  max-width: 100%;
  margin: 0;
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-lg);
  padding: clamp(18px, 5vw, 32px);
  box-shadow: var(--sh-card);
  font-family: var(--font-body);
  color: var(--ink-body);
}

.wpcf7 .mkd-cf7-50-50{ display: grid; grid-template-columns: 1fr 1fr; gap: 2px var(--s-4); margin: 0 }
@media (max-width: 768px){ .wpcf7 .mkd-cf7-50-50{ grid-template-columns: 1fr } }
.wpcf7 .mkd-cf7-col-right,
.wpcf7 .mkd-cf7-col-left{ float: none !important; width: auto !important; padding: 0 !important }
.wpcf7 .mkd-cf7-50-50 > [style*="clear"]{ display: none }

.wpcf7 label{
  display: block;
  font: 700 var(--fs-xs)/var(--lh-flat) var(--font-head);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s-3);
}
.wpcf7 :is(h3, h4){ font-family: var(--font-head); color: var(--ink) }
.wpcf7 .tsb-fsub{
  font: 700 var(--fs-md)/var(--lh-flat) var(--font-head);
  color: var(--ink); margin: var(--s-2) 0 var(--s-3);
  text-transform: none; letter-spacing: var(--track-normal);
}

/* 16px ist die Grenze, ab der iOS beim Antippen NICHT mehr hineinzoomt. */
.wpcf7 :is(input.wpcf7-form-control, textarea.wpcf7-form-control, select.wpcf7-form-control){
  width: 100%;
  box-sizing: border-box;
  border: var(--b-field);
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  margin: var(--s-2) 0 0;          /* das Theme setzt margin-bottom:16px */
  min-height: 48px;                /* Fingerkuppe */
  background: var(--surface);
  color: var(--ink-body);
  -webkit-appearance: none; appearance: none;
}
/*
   Kontakt #5989 traegt .cf7_custom_style_2. style_dynamic.css setzt dort
     .cf7_custom_style_2 input.wpcf7-form-control.wpcf7-text, ... { border-color:rgba(227,226,226,1) }
   = (0,3,1). Ein ".cf7_custom_style_2 :is(input.wpcf7-form-control)" waere nur (0,2,1) und
   verliert (gemessen: Feldrand blieb #e3e2e2 statt #7d8680). Deshalb die Selektorstruktur
   des Themes spiegeln -> (0,3,1) und damit Gleichstand; tsb-design.css laedt per deps NACH
   style_dynamic.css und gewinnt.
*/
.cf7_custom_style_2 :is(
  input.wpcf7-form-control.wpcf7-text,
  input.wpcf7-form-control.wpcf7-email,
  input.wpcf7-form-control.wpcf7-tel,
  input.wpcf7-form-control.wpcf7-number,
  input.wpcf7-form-control.wpcf7-date,
  input.wpcf7-form-control.wpcf7-quiz,
  textarea.wpcf7-form-control.wpcf7-textarea,
  select.wpcf7-form-control.wpcf7-select
){
  border-color: var(--line-field);
  font-size: var(--fs-base);
}
.wpcf7 ::placeholder{ color: var(--placeholder); opacity: 1 }

.wpcf7 select.wpcf7-form-control{
  /* url() akzeptiert kein var() -> der Pfeil traegt den Hex von --muted literal (Ausnahmeliste) */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='none' stroke='%235f6862' stroke-width='1.6' d='M1 1.5 6 6l5-4.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  padding-right: 36px;             /* funktional: Platz fuer das Pfeil-Icon */
}
.wpcf7 textarea.wpcf7-form-control{ min-height: 96px }

.wpcf7 :is(input, textarea, select):focus{
  outline: 2px solid var(--focus);
  outline-offset: 1px;
  border-color: var(--accent);
}

.wpcf7 :is(.wpcf7-radio, .wpcf7-checkbox) .wpcf7-list-item{ display: block; margin: var(--s-2) 0 0 }
.wpcf7 :is(.wpcf7-radio, .wpcf7-checkbox) .wpcf7-list-item-label{
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  text-transform: none; letter-spacing: var(--track-normal); color: var(--ink-body);
}
/* Radios und Checkboxen sind heute 13px - mit dem Daumen nicht zu treffen. */
.wpcf7 input[type=radio],
.wpcf7 input[type=checkbox]{ width: 24px; height: 24px; accent-color: var(--accent) }

/*
   Die AGB-Zeile: heute steht sie auf 7 von 8 Formularen auf display:block, weil
   ".wpcf7 label{display:block}" aus den Seitenkopien (0,3,1) gewinnt. Folge: die Checkbox
   klebt am Text und der zweizeilige Satz bricht unter die Box.
*/
.wpcf7 .wpcf7-acceptance{ display: block; margin: var(--s-3) 0 0 }
.wpcf7 .wpcf7-acceptance .wpcf7-list-item{ margin: 0 0 var(--s-2) }
.wpcf7 .wpcf7-acceptance label{
  display: flex; gap: var(--s-2); align-items: flex-start;
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  text-transform: none; letter-spacing: var(--track-normal);
  color: var(--muted); margin: 0;
}
.wpcf7 .wpcf7-acceptance input[type=checkbox]{ flex: 0 0 auto; margin-top: 1px }
.wpcf7 .wpcf7-acceptance a{ color: var(--accent); font-weight: 700 }
.wpcf7 .tsb-reassure{
  font: 700 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--accent); margin: var(--s-2) 0 var(--s-4);
  text-transform: none; letter-spacing: var(--track-normal);
}

/* Absenden: gruen wie der Seiten-CTA (Kundenentscheidung 16.07.), mit Rand fuer SC 1.4.11. */
.wpcf7 input.wpcf7-submit{
  background: var(--accent-bright);
  color: var(--accent-ink);
  border: 1.5px solid var(--accent);
  border-radius: var(--r-sm);
  padding: var(--s-4) var(--s-5);
  min-height: 48px;
  font: 700 var(--fs-base)/var(--lh-1) var(--font-head);
  cursor: pointer;
  width: auto; height: auto;
  -webkit-appearance: none; appearance: none;
  margin-top: var(--s-3);
  transition: background var(--t-base), color var(--t-base);
}
.wpcf7 input.wpcf7-submit:hover{ background: var(--accent); color: var(--on-dark) }
.wpcf7 input.wpcf7-submit:disabled{ opacity: .6; cursor: not-allowed }

/*
   Geschwisterlogik "Weiteres Kind hinzufuegen" (Gruppentraining #10702, Tagescamp #10712).
   Stand vorher als body.page-id-XXXX-Regel im post_content und faellt sonst mit den
   Formularkopien - dann waeren ALLE Kinderbloecke gleichzeitig sichtbar (gemessen:
   Gruppentraining 12 -> 26 Felder). Hier ungescopt, damit sie beide Seiten traegt.

   .tsb-rmkind: das JS setzt display:inline-block, nicht "" - sonst faellt es auf dieses
   display:none zurueck und der Entfernen-Knopf bleibt unsichtbar (Review-Blocker vom 16.07.).
   .tsb-kind-controls>p: CF7 laesst wpautop laufen und wickelt die Knopfzeile in ein <p>,
   deshalb muss das Flex dort sitzen (v9-Fix).
*/
.wpcf7 .tsb-kind{ display: none }
.wpcf7 .tsb-kind.tsb-kind--show{ display: block }
.wpcf7 .tsb-kind-controls,
.wpcf7 .tsb-kind-controls > p{
  display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap;
}
.wpcf7 .tsb-kind-controls{ margin: var(--s-1) 0 var(--s-4) }
.wpcf7 .tsb-kind-controls > p{ margin: 0; flex: 1 1 100% }
.wpcf7 .tsb-rmkind{ color: var(--muted); display: none }
.wpcf7 .tsb-kind-count{ margin-left: auto; color: var(--muted); font-size: var(--fs-sm) }

.wpcf7 .wpcf7-not-valid{ border-color: var(--error) !important }
.wpcf7 .wpcf7-not-valid-tip{
  color: var(--error);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  text-transform: none;
}
.wpcf7 .wpcf7-response-output{
  border-radius: var(--r-sm);
  font-family: var(--font-body);
  font-size: var(--fs-base);
}

/* ------------------------------------------- 9. Merch-Slider (Startseite) */
/*
   Kundenwunsch 16.07.: 4 Produkte sichtbar, per Pfeil durchblaettern.
   Grund: [recent_products per_page="4"] zeigte die 4 NEUESTEN - Trikot und
   Schluesselanhaenger waren dadurch von keiner Seite aus erreichbar, und ein siebtes
   Produkt haette unbemerkt das naechste verdraengt. /shop/ ist bewusst nicht verlinkt.

   Technik: natives CSS-Scroll-Snapping statt Owl. Owl hat bei der Partner-Logoleiste am
   16.07. drei Fallstricke gekostet (Loop-Guard, Stacking-Context durch translate3d,
   fehlender margin-Default). Scroll-Snapping ist auf dem Handy von Haus aus wischbar und
   funktioniert auch ohne JS - die Pfeile sind nur Komfort.

   Nur auf der Startseite (body.home). Auf /shop/ bleibt das Gitter ein Gitter.
*/
body.home .tsb-merch{ position: relative }

body.home .woocommerce ul.products{
  display: flex;
  gap: var(--s-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  margin: 0;
  padding: 0 0 var(--s-2);
  list-style: none;
  scrollbar-width: none;              /* Firefox */
  -ms-overflow-style: none;
}
body.home .woocommerce ul.products::-webkit-scrollbar{ display: none }

/* Das Theme setzt Breite und Rand pro Kachel (mkd-woocommerce-columns-4) - hier zaehlt Flex. */
body.home .woocommerce ul.products > li.product{
  flex: 0 0 calc((100% - 3 * var(--s-5)) / 4);
  width: auto !important;
  margin: 0 !important;
  scroll-snap-align: start;
}
@media (max-width: 1024px){
  body.home .woocommerce ul.products > li.product{ flex-basis: calc((100% - 2 * var(--s-5)) / 3) }
}
@media (max-width: 768px){
  body.home .woocommerce ul.products > li.product{ flex-basis: calc((100% - var(--s-5)) / 2) }
}
@media (max-width: 480px){
  body.home .woocommerce ul.products > li.product{ flex-basis: 78% }   /* der Anschnitt zeigt: hier geht es weiter */
}

body.home .tsb-merch__nav{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1.5px solid var(--accent);
  border-radius: var(--r-full);
  background: var(--surface);
  color: var(--accent);
  cursor: pointer;
  padding: 0;
  transition: background var(--t-base), color var(--t-base), opacity var(--t-base);
}
body.home .tsb-merch__nav:hover{ background: var(--accent); color: var(--on-dark) }
body.home .tsb-merch__nav--prev{ left: -22px }
body.home .tsb-merch__nav--next{ right: -22px }
body.home .tsb-merch__nav[disabled]{ opacity: 0; pointer-events: none }
body.home .tsb-merch__nav svg{ width: 18px; height: 18px; display: block }

/* Auf schmalen Bildschirmen wird gewischt, nicht geklickt. */
@media (max-width: 768px){
  body.home .tsb-merch__nav{ display: none }
}

/* ------------------------------------------------ 10. Bankverbindung */
/*
   Die vier Angaben stehen als je ein <code> im Markup - und <code> ist von Haus aus
   display:inline. Gemessen auf /einzeltraining/: "Ostseesparkasse Rostock" und die IBAN
   landeten auf derselben Zeile, BIC und Kontoinhaber ebenso. Wer das abtippen soll,
   verliert die Zeile.

   Untereinander, mit Luft, und die Ziffern in gleicher Laufweite (tabular-nums), damit
   die IBAN-Bloecke ruhig stehen. Kundenwunsch 16.07.
*/
:is(.tsb, .tsb-tm, .tsb-legal) .bank code{
  display: block;
  width: fit-content;
  margin-top: var(--s-2);
  font-variant-numeric: tabular-nums;
  line-height: var(--lh-base);
}
:is(.tsb, .tsb-tm, .tsb-legal) .bank code:first-of-type{ margin-top: 0 }

/* ------------------------------------------------------ 11. Kleinigkeiten */
.mkd-comment-form:empty{ display: none }

/* ----------------------------------------------------- 26. Bewegung  [TSB-BLOCK:bewegung] */
@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    transition-duration: 1ms !important;
    animation-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}


/* =========================================================================
   27. Komponenten (Stufe 3)  [TSB-BLOCK:komponenten]
   Konsolidiert aus den 13 Inline-Kopien im post_content: 74.688 -> 33.512 Zeichen.
   250 Selektoren kamen mehrfach vor, 245 davon byte-identisch - die Drift war
   auf 5 Stellen begrenzt (Bandtakt, Mobil-Bandtakt, Button-Basis, Monospace-Stack,
   Token-Namen). Alle fuenf sind in consolidate.py dokumentiert aufgeloest.
   Erzeugt von scripts/design-2026-07/consolidate.py - nicht von Hand pflegen.
   ========================================================================= */

/* ==========================================================================
   Komponenten, konsolidiert aus den 13 Inline-Kopien (Stufe 3, 16.07.2026).
   Erzeugt von scripts/design-2026-07/consolidate.py - nicht von Hand pflegen,
   sondern die Quelle aendern und neu erzeugen.
   276 Basis-Regeln + 39 in Media-Queries.
   ========================================================================== */
.tsb-legal *{box-sizing:border-box}
.tsb-legal-wrap{max-width:760px;margin:0 auto;padding:0 22px}
/* Kopf */ .tsb-legal-head{padding:2px 0 24px;border-bottom:1px solid var(--line);margin-bottom:32px}
.tsb-legal-head .kick{font-family:'Titillium Web',sans-serif;text-transform:uppercase;letter-spacing:.14em; font-size:.72rem;color:var(--green-dk);font-weight:700;margin:0 0 12px}
.tsb-legal-head h1{font-family:'Titillium Web',sans-serif;font-weight:700;color:var(--ink); font-size:2.35rem;line-height:1.12;margin:0 0 16px}
.tsb-legal-head .acc{width:56px;height:4px;background:var(--green);border-radius:3px;margin:0 0 18px}
.tsb-legal-head .lead{font-size:1.04rem;color:var(--muted);margin:0 0 12px;max-width:600px;line-height:1.6}
.tsb-legal-head .stand{font-family:'Titillium Web',sans-serif;font-size:.82rem;color:var(--muted);letter-spacing:.03em}
/* TOC */ .tsb-legal-toc{background:var(--alt);border:1px solid var(--line);border-radius:14px;padding:20px 24px;margin:0 0 40px}
.tsb-legal-toc h2{font-family:'Titillium Web',sans-serif;font-size:.78rem;text-transform:uppercase; letter-spacing:.09em;color:var(--muted);margin:0 0 14px;font-weight:700}
.tsb-legal-toc ol{margin:0;padding:0;list-style:none;columns:2;column-gap:30px}
.tsb-legal-toc li{margin:0 0 9px;break-inside:avoid}
.tsb-legal-toc a{font-family:'Titillium Web',sans-serif;font-size:.92rem;color:#23282a;text-decoration:none; display:flex;gap:8px;line-height:1.35}
.tsb-legal-toc a:hover{color:var(--green-dk)}
.tsb-legal-toc a .num{color:var(--green-dk);font-weight:700;flex:0 0 auto}
/* Body */ .tsb-legal-body section{margin:0 0 30px;scroll-margin-top:96px}
.tsb-legal-body h2{font-family:'Titillium Web',sans-serif;font-weight:700;font-size:1.32rem;color:var(--ink); margin:0 0 14px;line-height:1.25}
.tsb-legal-body h2 .secnum{color:var(--green-dk)}
.tsb-legal-body h3{font-family:'Titillium Web',sans-serif;font-weight:600;font-size:1.06rem;color:var(--ink);margin:24px 0 9px}
.tsb-legal-body p{font-size:1rem;line-height:1.74;margin:0 0 13px}
.tsb-legal-body .n{color:var(--green-dk);font-weight:700;font-family:'Titillium Web',sans-serif;margin-right:5px}
.tsb-legal-body ul{margin:2px 0 15px;padding:0;list-style:none}
.tsb-legal-body ul li{position:relative;padding-left:24px;margin:0 0 9px;line-height:1.62;font-size:1rem}
.tsb-legal-body ul li::before{content:"";position:absolute;left:3px;top:.63em;width:7px;height:7px; background:var(--green);border-radius:2px}
.tsb-legal-body a{color:var(--green-dk);text-decoration:underline;text-underline-offset:2px}
.tsb-legal-body a:hover{text-decoration:none}
.tsb-legal-body .contact{background:var(--alt);border:1px solid var(--line);border-radius:12px; padding:18px 20px;margin:0 0 8px;font-size:1rem;line-height:1.8}
.tsb-legal-body .contact strong{font-family:'Titillium Web',sans-serif}
.tsb-legal-body .quote{background:var(--alt);border-left:3px solid var(--green);border-radius:0 10px 10px 0; padding:16px 20px;margin:4px 0 16px;font-size:.95rem;color:#3a4042;line-height:1.75}
.tsb-legal-body .quote p{margin:0 0 6px;font-size:.95rem}
.tsb-legal-body .quote p:last-child{margin:0}
/* Querverweise */ .tsb-legal-more{margin:44px 0 0;padding:20px 0 0;border-top:1px solid var(--line); font-family:'Titillium Web',sans-serif;font-size:.9rem;color:var(--muted)}
.tsb-legal-more span{margin-right:6px}
.tsb-legal-more a{color:var(--green-dk);text-decoration:none;font-weight:600}
.tsb-legal-more a:hover{text-decoration:underline}
.tsb *{box-sizing:border-box}
.tsb h2,.tsb h3,.tsb h4{font-family:'Titillium Web',sans-serif;color:var(--ink)}
.tsb-inner{max-width:1100px;margin:0 auto;padding:0}
.tsb-band{padding-top:var(--band-y);padding-bottom:var(--band-y)}
.tsb .tsb-grid{display:grid;gap:20px;grid-template-columns:1fr}
.tsb .ptile{background:#fff;border:1px solid var(--line);border-radius:16px;overflow:hidden;display:flex;flex-direction:column;box-shadow:0 12px 28px -20px rgba(20,22,21,.45);transition:transform .15s ease,box-shadow .15s ease;color:inherit;text-decoration:none}
.tsb .ptile:hover{transform:translateY(-4px);box-shadow:0 22px 40px -22px rgba(20,22,21,.5)}
.tsb .ptile:focus-visible{outline:2px solid var(--green-dk);outline-offset:3px}
.tsb .ptile .img{position:relative;height:196px;background-size:cover;background-position:center;display:grid;place-items:center}
.tsb .ptile .img.ph1{background:linear-gradient(135deg,#1f2a22,#0a6b2e 130%)}
.tsb .ptile .img.ph2{background:linear-gradient(135deg,#242a20,#3a9d4e 150%)}
.tsb .ptile .img.ph3{background:linear-gradient(135deg,#20262a,#2f6f8f 150%)}
.tsb .ptile .img.ph4{background:linear-gradient(135deg,#2a241f,#8a6a2e 150%)}
.tsb .ptile .phn{color:rgba(255,255,255,.9);display:flex;flex-direction:column;align-items:center;gap:8px;font-family:'Titillium Web';font-size:.72rem;letter-spacing:.1em;text-transform:uppercase}
.tsb .ptile .tag{position:absolute;top:14px;left:14px;background:rgba(255,255,255,.94);color:var(--green-dk);font-family:'Titillium Web';font-weight:700;font-size:11px;letter-spacing:.06em;text-transform:uppercase;padding:5px 11px;border-radius:7px}
.tsb .ptile .pb{padding:22px 22px 20px;display:flex;flex-direction:column;flex:1}
.tsb .ptile :is(h2,h3){font-size:1.22rem;line-height:1.24;margin:0 0 6px;font-weight:700}
.tsb .ptile .desc{color:var(--muted);font-size:.92rem;margin:0 0 14px;flex:1}
.tsb .ptile .meta{font-family:'Titillium Web';font-size:.8rem;color:#1c201d;margin-bottom:16px;display:flex;gap:8px;flex-wrap:wrap}
.tsb .ptile .meta span{background:var(--alt);border:1px solid var(--line);border-radius:20px;padding:4px 12px}
.tsb .ptile .meta .price{background:rgba(10,107,46,.1);border-color:transparent;color:var(--green-dk);font-weight:700}
.tsb .ptile .go{font-family:'Titillium Web';font-weight:700;font-size:.88rem;color:var(--green-dk);display:inline-flex;align-items:center;gap:6px}
.tsb .ptile:hover .go svg{transform:translateX(3px)}
.tsb .ptile .go svg{transition:transform .15s ease}
/* Info-Streifen */ .tsb .tsb-info{margin:24px 0 0;background:var(--alt);border:1px solid var(--line);border-radius:16px;padding:26px;display:grid;grid-template-columns:1.1fr 1fr;gap:26px}
.tsb .tsb-info .probe{display:flex;gap:14px;align-items:flex-start}
.tsb .tsb-info .probe .pic{flex:0 0 auto;width:46px;height:46px;border-radius:12px;background:var(--green);color:#06331a;display:grid;place-items:center}
.tsb .tsb-info .probe :is(h3,h4){font-size:1.08rem;line-height:1.4;margin:0 0 3px;font-weight:700}
.tsb .tsb-info .probe p{margin:0;color:var(--muted);font-size:.92rem}
.tsb .tsb-info .prices :is(h3,h4){font-size:.82rem;line-height:1.4;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin:0 0 10px;font-family:'Titillium Web'}
.tsb .tsb-info .prices ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px}
.tsb .tsb-info .prices li{display:flex;justify-content:space-between;gap:16px;font-size:.9rem;border-bottom:1px dashed #d9ddd9;padding-bottom:6px}
.tsb .tsb-info .prices li:last-child{border-bottom:0;padding-bottom:0}
.tsb .tsb-info .prices li b{font-family:'Titillium Web';color:var(--ink)}
.tsb .tsb-info .prices .note{color:var(--muted);font-size:.82rem;margin-top:8px}
.tsb h1,.tsb h2,.tsb h3,.tsb h4,.tsb .tsb-stats b{font-family:'Titillium Web',sans-serif;color:var(--ink)}
.tsb-band-first{padding-top:24px}
.tsb-band-alt{background:#f4f6f4;border-top:1px solid #e6e9e6;border-bottom:1px solid #e6e9e6}
.tsb-band-white{background:#fff}
#buchen,#anmelden{scroll-margin-top:110px}
.tsb .kick{font-family:'Titillium Web';font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--green-dk);font-weight:700;margin:0 0 12px}
.tsb h1.h1{font-size:clamp(2.1rem,4vw,3.2rem);line-height:1.04;margin:0 0 16px;font-weight:700}
.tsb .sub{color:#454c47;font-size:1.06rem;margin:0 0 18px;max-width:50ch}
.tsb .sub strong{color:var(--ink)}
.tsb .actions{display:flex;gap:12px;margin-top:22px;flex-wrap:wrap}
:is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn{display:inline-flex;align-items:center;justify-content:center;align-self:flex-start;gap:var(--s-2);font-family:var(--font-head);font-weight:700;font-size:var(--fs-base);line-height:var(--lh-1);padding:var(--s-4) var(--s-5);min-height:48px;border-radius:var(--r-sm);text-decoration:none;border:1.5px solid transparent;cursor:pointer;transition:transform var(--t-fast),background var(--t-base),color var(--t-base)}
:is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn:hover{transform:translateY(-2px)}
:is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn:focus-visible{outline:2px solid var(--green-dk);outline-offset:3px}
:is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn-green{background:var(--green);color:#06331a}
:is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn-ghost{border-color:var(--line);color:var(--ink);background:#fff}
/* Split-Hero mit Foto */ .tsb .heroC{display:grid;grid-template-columns:1.06fr .94fr;background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:0 18px 42px -28px rgba(20,22,21,.42)}
.tsb .heroC-text{padding:52px 46px;display:flex;flex-direction:column;justify-content:center}
.tsb .heroC-img{position:relative;min-height:392px;background-size:cover}
.tsb .heroC-img.ph{background:linear-gradient(140deg,#1f2a22,#0a6b2e 150%);display:grid;place-items:center}
.tsb .heroC-img .phn{color:rgba(255,255,255,.9);font-family:'Titillium Web';font-size:.74rem;letter-spacing:.1em;text-transform:uppercase;display:flex;flex-direction:column;align-items:center;gap:8px;z-index:1}
.tsb .heroC-img::before{content:"";position:absolute;inset:0;background:linear-gradient(90deg,#fff 0%,rgba(255,255,255,.5) 14%,rgba(255,255,255,0) 42%),linear-gradient(0deg,rgba(20,22,21,.16),transparent 46%)}
.tsb .heroC-img.ph::before{background:none}
/* Stats */ .tsb .stats{display:grid;grid-template-columns:repeat(3,1fr);background:#fff;border:1px solid var(--line);border-radius:16px;margin:22px 0 0;overflow:hidden;box-shadow:0 8px 22px -18px rgba(20,22,21,.25)}
.tsb .stats>div{padding:22px;text-align:center;border-left:1px solid var(--line)}
.tsb .stats>div:first-child{border-left:0}
.tsb .stats b{font-size:2.1rem;display:block;line-height:1}
.tsb .stats b.txt{font-size:1.55rem}
.tsb .stats b span{color:var(--green-dk);font-size:.5em;vertical-align:.4em}
.tsb .stats small{font-family:'Titillium Web';font-size:11px;letter-spacing:.06em;color:var(--muted);text-transform:uppercase;display:block;margin-top:8px}
/* Sektionen + Highlights */ .tsb .bt{font-size:clamp(1.6rem,2.5vw,2.05rem);font-weight:700;margin:0 0 8px;display:flex;align-items:baseline;gap:12px;line-height:1.1}
.tsb .bt .num{font-family:'Titillium Web';color:var(--green-dk);font-size:.62em;font-weight:700}
.tsb .lead{color:var(--muted);margin:0 0 26px;max-width:64ch;font-size:1.02rem}
.tsb .hl{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:18px}
.tsb .hl .i{background:#fff;border:1px solid var(--line);border-radius:14px;padding:24px 22px;box-shadow:0 8px 22px -16px rgba(20,22,21,.25);transition:transform .15s ease,box-shadow .15s ease}
.tsb .hl .i:hover{transform:translateY(-3px);box-shadow:0 16px 30px -18px rgba(20,22,21,.35)}
.tsb .hl .ic{width:40px;height:40px;border-radius:11px;background:rgba(10,107,46,.12);display:grid;place-items:center;margin-bottom:14px;color:var(--green-dk)}
.tsb .hl :is(h3,h4){margin:0 0 4px;line-height:1.4;font-size:1rem;font-weight:700}
.tsb .hl p{margin:0;color:var(--muted);font-size:.88rem;line-height:1.5}
/* Buchen/Bestellablauf */ .tsb .order{display:grid;grid-template-columns:1.3fr 1fr;gap:24px;margin:0 0 26px}
.tsb .order h3{font-size:1.1rem;margin:0 0 12px;font-weight:700}
.tsb .order ol{margin:0;padding-left:20px;color:#333934;font-size:.95rem}
.tsb .order ol li{margin-bottom:8px}
/* Track B: Bestellablauf OHNE Bank-Spalte (BACS zeigt die Kontodaten in der Kasse selbst).
   Der Kauf-Button steht direkt im Ablauf, keine zweite Spalte -> einspaltig, schmal. */
.tsb .order--single{grid-template-columns:1fr;max-width:640px}
.tsb .order--single .tsb-btn{margin-top:18px}
.tsb .bank{background:#fff;border:1px solid var(--line);border-radius:13px;padding:18px 20px;font-size:.88rem;height:fit-content}
.tsb .bank :is(h3,h4){font-family:'Titillium Web';line-height:1.4;font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin:0 0 10px}
.tsb .bank code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:var(--fs-sm);color:var(--ink);background:var(--surface-alt);padding:2px 6px;border-radius:6px}
.tsb h1,.tsb h2,.tsb h3,.tsb h4{font-family:'Titillium Web',sans-serif;color:var(--ink)}
#bestellen{scroll-margin-top:110px}
/* Split-Hero */ .tsb .hero{display:grid;grid-template-columns:1.04fr .96fr;background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:0 18px 42px -28px rgba(20,22,21,.42)}
.tsb .hero .tx{padding:48px 42px;display:flex;flex-direction:column;justify-content:center}
.tsb .hero .kick{font-family:'Titillium Web';font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--green-dk);font-weight:700;margin:0 0 10px}
.tsb .hero h1{font-size:clamp(2rem,3.8vw,2.9rem);margin:0 0 12px;line-height:1.04;font-weight:700}
.tsb .hero .sub{color:#454c47;font-size:1.05rem;margin:0 0 16px;max-width:46ch}
.tsb .hero .facts{display:flex;gap:20px;flex-wrap:wrap;font-family:'Titillium Web';font-size:12px;color:var(--muted);margin-bottom:22px}
.tsb .hero .facts b{color:var(--ink)}
.tsb .hero .vis{background:linear-gradient(150deg,#12160f,#1f2a22);display:grid;place-items:center;padding:40px 30px;position:relative;overflow:hidden}
.tsb .hero .vis::after{content:"";position:absolute;inset:0;background:repeating-linear-gradient(45deg,transparent 0 22px,rgba(67,236,107,.05) 22px 23px)}
/* Bonuskarte-Grafik */ .tsb .bcard{position:relative;z-index:1;width:300px;max-width:100%;background:linear-gradient(145deg,#20261d,#0d120b);border:1px solid #38402f;border-radius:16px;padding:22px 22px 18px;box-shadow:0 26px 50px -24px rgba(0,0,0,.8)}
.tsb .bcard .top{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}
.tsb .bcard .bn{font-family:'Titillium Web';font-weight:700;color:#fff;font-size:1.05rem}
.tsb .bcard .bn span{color:var(--green)}
.tsb .bcard .chip{font-family:'Titillium Web';font-size:10px;letter-spacing:.1em;text-transform:uppercase;color:#06331a;background:var(--green);padding:3px 9px;border-radius:5px;font-weight:700}
.tsb .bcard .stamps{display:grid;grid-template-columns:repeat(5,1fr);gap:9px}
.tsb .bcard .stamps i{aspect-ratio:1;border-radius:50%;border:1.5px dashed #4a5340;display:grid;place-items:center;color:#5a6350;font-family:'Titillium Web';font-size:12px;font-style:normal}
.tsb .bcard .stamps i.on{border-style:solid;border-color:var(--green);background:rgba(67,236,107,.14);color:var(--green)}
.tsb .bcard .cfoot{margin-top:16px;padding-top:12px;border-top:1px solid #2c3325;font-family:'Titillium Web';font-size:11px;color:#9aa39c;display:flex;justify-content:space-between}
/* Gutschein-Grafik */ .tsb .gcard{position:relative;z-index:1;width:320px;max-width:100%;background:linear-gradient(145deg,#1b2018,#0d120b);border:1px solid #38402f;border-radius:16px;padding:24px;box-shadow:0 26px 50px -24px rgba(0,0,0,.8);text-align:center}
.tsb .gcard .lbl{font-family:'Titillium Web';font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:var(--gold);font-weight:700}
.tsb .gcard .big{font-family:'Titillium Web';font-weight:700;color:#fff;font-size:2.6rem;line-height:1;margin:8px 0 4px}
.tsb .gcard .big small{color:var(--green);font-size:.4em;vertical-align:.5em}
.tsb .gcard .for{color:#c7ccc8;font-size:.85rem}
.tsb .gcard .rule{height:1px;background:repeating-linear-gradient(90deg,#3a4230 0 7px,transparent 7px 14px);margin:16px 0}
.tsb .gcard .sign{display:flex;justify-content:space-between;font-family:'Titillium Web';font-size:10px;color:#8a9384;text-transform:uppercase;letter-spacing:.08em}
/* Sektionstitel */ .tsb .sec-t{font-size:clamp(1.6rem,2.4vw,2rem);color:var(--ink);font-weight:700;margin:0 0 6px;display:flex;gap:10px;align-items:baseline;line-height:1.1}
.tsb .sec-t .num{font-family:'Titillium Web';color:var(--green-dk);font-size:.62em;font-weight:700}
.tsb .sec-lead{color:var(--muted);margin:0 0 24px;font-size:1.02rem;max-width:64ch}
/* Preis-Pakete */ .tsb .packs{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.tsb .pack{background:#fff;border:1px solid var(--line);border-radius:16px;padding:28px 26px;display:flex;flex-direction:column;box-shadow:0 12px 28px -22px rgba(20,22,21,.4);position:relative}
.tsb .pack.feature{border:1.5px solid var(--green-dk);box-shadow:0 20px 44px -26px rgba(10,107,46,.5)}
.tsb .pack .badge{position:absolute;top:-12px;right:22px;background:var(--green);color:#06331a;font-family:'Titillium Web';font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:.06em;padding:5px 12px;border-radius:20px}
.tsb .pack h3{font-size:1.3rem;margin:0 0 2px;font-weight:700}
.tsb .pack .pmeta{font-family:'Titillium Web';font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin:0 0 14px}
.tsb .pack .price{font-family:'Titillium Web';font-size:2.5rem;font-weight:700;color:var(--ink);line-height:1;margin:0}
.tsb .pack .price span{font-size:.34em;color:var(--green-dk);vertical-align:.5em}
.tsb .pack .save{font-family:'Titillium Web';font-size:.85rem;color:var(--green-dk);font-weight:700;margin:6px 0 0}
.tsb .pack ul{list-style:none;margin:16px 0 22px;padding:0;display:flex;flex-direction:column;gap:9px;flex:1}
.tsb .pack li{display:flex;gap:9px;align-items:flex-start;font-size:.92rem;color:#333934}
.tsb .pack li svg{flex:0 0 auto;margin-top:3px;color:var(--green-dk)}



/* Betrags-Optionen (3 feste Beträge, kein freier Wunschbetrag mehr) */ .tsb .amts{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.tsb .amt{background:#fff;border:1.5px solid var(--line);border-radius:14px;padding:20px 14px;text-align:center;text-decoration:none;color:inherit;cursor:pointer;display:block;transition:border-color .15s ease,transform .15s ease}
.tsb .amt:hover{border-color:var(--green-dk);transform:translateY(-2px)}
.tsb .amt.sel{border-color:var(--green-dk);background:rgba(10,107,46,.05)}
.tsb .amt .n{font-family:'Titillium Web';font-weight:700;font-size:1.5rem;color:var(--ink)}
.tsb .amt .n span{font-size:.5em;color:var(--green-dk)}
.tsb .amt .u{font-family:'Titillium Web';font-size:.72rem;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin-top:4px}
/* Vorteile */ .tsb .perks{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.tsb .perk{background:#fff;border:1px solid var(--line);border-radius:13px;padding:20px;box-shadow:0 8px 22px -18px rgba(20,22,21,.3)}
.tsb .perk .pi{width:38px;height:38px;border-radius:10px;background:rgba(10,107,46,.11);color:var(--green-dk);display:grid;place-items:center;margin-bottom:12px}
.tsb .perk :is(h3,h4){font-family:'Titillium Web';line-height:1.4;font-size:.98rem;margin:0 0 3px;color:var(--ink);font-weight:700}
.tsb .perk p{margin:0;font-size:.86rem;color:var(--muted);line-height:1.5}
/* Bestellablauf + Bank */ .tsb .order{display:grid;grid-template-columns:1.3fr 1fr;gap:24px;margin:0 0 26px}
.tsb h1,.tsb h2,.tsb h3,.tsb h4,.tsb .tsb-price-n,.tsb .tsb-stats b{font-family:'Titillium Web',sans-serif}
/* Baender */ .tsb-band{padding:72px 0}
.tsb-band-dark{background:#141615;border-top:1px solid #23271f;padding-bottom:0}
/* Anker unter Sticky-Header */ #tsb-anfrage,#tsb-ablauf{scroll-margin-top:110px}
/* Hero */ .tsb .tsb-hero{background:linear-gradient(180deg,#fbfdfb,#fff),repeating-linear-gradient(90deg,transparent 0 84px,rgba(10,107,46,.05) 84px 85px);border:1px solid var(--line);border-radius:18px;padding:48px 44px;position:relative;overflow:hidden}
.tsb .tsb-hero::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;background:linear-gradient(90deg,transparent,rgba(10,107,46,.4),transparent)}
.tsb .tsb-hero-grid{display:grid;grid-template-columns:1.4fr .75fr;gap:44px;align-items:center}
.tsb .tsb-kicker{font-family:'Titillium Web';font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--green-ink);font-weight:700;margin:0 0 12px}
.tsb .tsb-h1{font-size:clamp(2.1rem,4vw,3.2rem);line-height:1.04;margin:0 0 16px;color:var(--ink);font-weight:700;text-wrap:balance}
.tsb .tsb-sub{color:#454c47;font-size:1.08rem;margin:0 0 18px;max-width:52ch}
.tsb .tsb-facts{display:flex;gap:24px;flex-wrap:wrap;font-family:'Titillium Web';font-size:13px;color:var(--muted)}
.tsb .tsb-facts b{color:var(--ink)}
.tsb .tsb-actions{display:flex;gap:12px;margin-top:24px;flex-wrap:wrap}





.tsb .tsb-hero-side{display:flex;flex-direction:column;gap:16px}
.tsb .tsb-price{background:var(--ink);border-radius:16px;padding:32px 26px;text-align:center;color:#fff;box-shadow:0 24px 46px -26px rgba(20,22,21,.6);border:1px solid #23271f}
.tsb .tsb-price-l{font-family:'Titillium Web';font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:#9aa39c}
.tsb .tsb-price-n{font-size:clamp(3.4rem,7vw,4.4rem);font-weight:700;line-height:1;color:#fff;margin:6px 0 2px}
.tsb .tsb-price-n span{color:var(--green);font-size:.42em;vertical-align:.5em;margin-left:3px}
.tsb .tsb-price-s{font-family:'Titillium Web';font-size:12px;color:#c7ccc8}
.tsb .tsb-price-note{margin-top:16px;padding-top:14px;border-top:1px solid #2a2f28;font-family:'Lato';font-size:.82rem;color:#c7ccc8;line-height:1.45}
/* Hero Variante C: Split (Text + Bild) mit weichem Bild-Uebergang */ .tsb .tsb-heroC{display:grid;grid-template-columns:1.06fr .94fr;background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:0 18px 42px -28px rgba(20,22,21,.42)}
.tsb .tsb-heroC-text{padding:56px 48px;display:flex;flex-direction:column;justify-content:center}
.tsb .tsb-heroC-text .tsb-sub{margin-bottom:24px}
.tsb .tsb-heroC-text .tsb-sub strong{color:var(--ink)}
.tsb .tsb-heroC-img{position:relative;min-height:392px;background-size:cover;background-position:center}
.tsb .tsb-heroC-img::before{content:"";position:absolute;inset:0;background:linear-gradient(90deg,#fff 0%,rgba(255,255,255,.5) 14%,rgba(255,255,255,0) 42%),linear-gradient(0deg,rgba(20,22,21,.16),transparent 46%)}
/* Stats-Band */ .tsb .tsb-stats{display:grid;grid-template-columns:repeat(3,1fr);background:#fff;border:1px solid var(--line);border-radius:16px;margin:22px 0 0;overflow:hidden;box-shadow:0 8px 22px -18px rgba(20,22,21,.25)}
.tsb .tsb-stats>div{padding:22px;text-align:center;border-left:1px solid var(--line)}
.tsb .tsb-stats>div:first-child{border-left:0}
.tsb .tsb-stats b{font-size:2.2rem;color:var(--ink);display:block;line-height:1;font-variant-numeric:tabular-nums}
.tsb .tsb-stats b span{color:var(--green-ink);font-size:.5em;vertical-align:.4em;margin-left:2px}
.tsb .tsb-stats small{font-family:'Titillium Web';font-size:11px;letter-spacing:.06em;color:var(--muted);text-transform:uppercase;display:block;margin-top:8px}
/* Sektionen */ .tsb .tsb-bt{font-size:clamp(1.75rem,2.6vw,2.1rem);color:var(--ink);font-weight:700;margin:0 0 8px;display:flex;align-items:baseline;gap:12px;line-height:1.1;text-wrap:balance}
.tsb .tsb-bt .num{font-family:'Titillium Web';color:var(--green-ink);font-size:.62em;font-weight:700;letter-spacing:.02em}
.tsb .tsb-lead{color:var(--muted);margin:0 0 26px;max-width:64ch;font-size:1.02rem}
.tsb .tsb-hl{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
.tsb .tsb-hl .i{background:#fff;border:1px solid var(--line);border-radius:14px;padding:24px 22px;box-shadow:0 8px 22px -16px rgba(20,22,21,.25);transition:transform .15s ease,box-shadow .15s ease}
.tsb .tsb-hl .i:hover{transform:translateY(-3px);box-shadow:0 16px 30px -18px rgba(20,22,21,.35)}
.tsb .tsb-hl .ic{width:40px;height:40px;border-radius:11px;background:rgba(10,107,46,.12);display:grid;place-items:center;margin-bottom:14px;color:var(--green-ink)}
.tsb .tsb-hl :is(h3,h4){margin:0 0 4px;line-height:1.4;font-size:1rem;color:var(--ink);font-weight:700}
.tsb .tsb-hl p{margin:0;color:var(--muted);font-size:.88rem;line-height:1.5}
/* PROZESS / So laeuft's ab -- verbundene Schritt-Kette (bewusst anders als die Karten) */ .tsb .tsb-flow{list-style:none;margin:8px 0 0;padding:0;display:grid;grid-template-columns:repeat(4,1fr);gap:0}
.tsb .tsb-flow-step{position:relative;padding:0 22px 0 0}
.tsb .tsb-flow-step:last-child{padding-right:0}
.tsb .tsb-flow-top{display:flex;align-items:center;margin-bottom:16px}
.tsb .tsb-flow-n{flex:0 0 auto;width:48px;height:48px;border-radius:50%;background:var(--ink);color:#fff;font-family:'Titillium Web';font-weight:700;font-size:1.2rem;display:grid;place-items:center;position:relative;z-index:1;box-shadow:0 0 0 6px #fff}
.tsb .tsb-flow-line{flex:1 1 auto;height:3px;background:linear-gradient(90deg,var(--green-ink),rgba(10,107,46,.3));margin-left:8px;margin-right:-22px;border-radius:3px}
.tsb .tsb-flow-step:last-child .tsb-flow-line{display:none}
.tsb .tsb-flow :is(h3,h4){margin:0 0 4px;line-height:1.4;font-size:1.05rem;color:var(--ink);font-weight:700}
.tsb .tsb-flow p{margin:0;color:var(--muted);font-size:.9rem;line-height:1.5;max-width:22ch}
.tsb .tsb-flow-cta{margin-top:32px}
/* CTA-Band dunkel, nahtlos in den Footer */ .tsb .tsb-cta{background:transparent;overflow:hidden}
.tsb .tsb-cta-in{display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;padding:8px 0 30px}
.tsb .tsb-cta-k{font-family:'Titillium Web';color:var(--green);font-size:12px;letter-spacing:.14em;text-transform:uppercase;font-weight:700;margin:0 0 6px}
.tsb .tsb-cta-h{font-family:'Titillium Web';color:#fff;font-size:clamp(1.4rem,2.4vw,1.7rem);font-weight:700;margin:0;max-width:26ch;line-height:1.15}
.tsb .tsb-cta-foot{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;padding:16px 0 26px;border-top:1px solid #23271f;font-family:'Titillium Web';font-size:.82rem;color:#9aa39c;letter-spacing:.02em}
.tsb h1,.tsb h2,.tsb h3,.tsb h4,.tsb .tsb-pack-price{font-family:'Titillium Web',sans-serif}
#tsb-anfrage,#tsb-ablauf,#tsb-pakete{scroll-margin-top:110px}
/* Split-Hero (Variante C) */ .tsb .tsb-heroC{display:grid;grid-template-columns:1.06fr .94fr;background:#fff;border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:0 18px 42px -28px rgba(20,22,21,.42)}
/* Paket-Vergleich */ .tsb .tsb-packs{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin:8px 0 0}
.tsb .tsb-pack{background:#fff;border:1px solid var(--line);border-radius:18px;padding:32px 30px;display:flex;flex-direction:column;box-shadow:0 12px 30px -22px rgba(20,22,21,.35);position:relative}
.tsb .tsb-pack--feature{border:1.5px solid var(--green-ink);box-shadow:0 20px 46px -26px rgba(10,107,46,.5)}
.tsb .tsb-pack-badge{position:absolute;top:-13px;right:24px;background:var(--green);color:#06331a;font-family:'Titillium Web';font-weight:700;font-size:11px;letter-spacing:.08em;text-transform:uppercase;padding:5px 13px;border-radius:20px}
.tsb .tsb-pack h3{font-size:1.45rem;color:var(--ink);margin:0 0 2px;font-weight:700}
.tsb .tsb-pack-meta{font-family:'Titillium Web';font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);margin:0 0 16px}
.tsb .tsb-pack-price{font-size:3rem;font-weight:700;color:var(--ink);line-height:1;margin:0}
.tsb .tsb-pack-price span{font-size:.34em;color:var(--green-ink);vertical-align:.55em;margin-left:2px}
.tsb .tsb-pack-list{list-style:none;margin:18px 0 24px;padding:0;display:flex;flex-direction:column;gap:11px;flex:1}
.tsb .tsb-pack-list li{display:flex;gap:10px;align-items:flex-start;font-size:.95rem;color:#333934;line-height:1.45}
.tsb .tsb-pack-list li svg{flex:0 0 auto;margin-top:2px;color:var(--green-ink)}
.tsb :is(.pack, .tsb-pack) .tsb-btn{width:100%}
/* PROZESS */ .tsb .tsb-flow{list-style:none;margin:8px 0 0;padding:0;display:grid;grid-template-columns:repeat(4,1fr);gap:0}
#tsb-anfrage,#tsb-ablauf{scroll-margin-top:110px}
.tsb .tsb-stats b.txt{font-size:1.7rem}
/* PROZESS -- verbundene Schritt-Kette */ .tsb .tsb-flow{list-style:none;margin:8px 0 0;padding:0;display:grid;grid-template-columns:repeat(4,1fr);gap:0}
.tsb-tm *{box-sizing:border-box}
.tsb-tm-wrap{max-width:940px;margin:0 auto;padding:0 22px}
/* Intro */ .tsb-tm-intro{max-width:680px;margin:0 auto 40px;text-align:center}
.tsb-tm-intro h2{font-family:'Titillium Web',sans-serif;font-weight:700;color:var(--ink);font-size:1.9rem;line-height:1.18;margin:0 0 14px}
.tsb-tm-intro p{font-size:1.05rem;line-height:1.7;color:var(--muted);margin:0 auto 10px}
/* Schrittkette */ .tsb-tm-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:0 0 46px;position:relative}
.tsb-tm-step{background:#fff;border:1px solid var(--line);border-radius:16px;padding:24px 22px;position:relative}
.tsb-tm-step .no{position:absolute;top:16px;right:18px;font-family:'Titillium Web',sans-serif;font-weight:700; font-size:1.5rem;color:#eef1ee;line-height:1}
.tsb-tm-step .ic{width:50px;height:50px;border-radius:13px;background:var(--alt);color:var(--green-dk); display:grid;place-items:center;margin:0 0 15px}
.tsb-tm-step h3{font-family:'Titillium Web',sans-serif;font-weight:700;font-size:1.08rem;color:var(--ink);margin:0 0 7px}
.tsb-tm-step p{font-size:.94rem;line-height:1.6;color:var(--muted);margin:0}
/* Kalender-Karte */ .tsb-tm-cal{background:#fff;border:1px solid var(--line);border-radius:18px; box-shadow:0 20px 44px -30px rgba(20,22,21,.55);padding:28px 26px 30px;margin:6px 0 0}
.tsb-tm-cal-head{display:flex;align-items:flex-start;gap:14px;margin:0 0 20px; padding:0 0 18px;border-bottom:1px solid var(--line)}
.tsb-tm-cal-head .pin{flex:0 0 auto;width:44px;height:44px;border-radius:12px;background:var(--green); color:#06331a;display:grid;place-items:center}
.tsb-tm-cal-head h2{font-family:'Titillium Web',sans-serif;font-weight:700;font-size:1.35rem;color:var(--ink);margin:0 0 4px;line-height:1.2}
.tsb-tm-cal-head p{font-size:.95rem;color:var(--muted);margin:0;line-height:1.55}
/* CTA */ .tsb-tm-cta{max-width:940px;margin:34px auto 0;padding:22px 24px;background:var(--alt);border:1px solid var(--line); border-radius:16px;display:flex;align-items:center;justify-content:space-between;gap:18px;flex-wrap:wrap}
.tsb-tm-cta .txt{font-size:1rem;color:#23282a}
.tsb-tm-cta .txt strong{font-family:'Titillium Web',sans-serif}


.tsb-tm-cta a.tsb-btn svg{transition:transform .15s ease}
.tsb-tm-cta a.tsb-btn:hover svg{transform:translateX(3px)}
@media(max-width:640px){
  .tsb-legal-toc ol{columns:1}
  .tsb .packs{grid-template-columns:1fr}
  .tsb .amts{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:1140px){
  .tsb-inner{padding:0 22px}
}
@media(min-width:720px){
  .tsb .tsb-grid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:720px){
  .tsb .tsb-info{grid-template-columns:1fr;gap:20px}
  .tsb .order{grid-template-columns:1fr}
  .tsb .perks{grid-template-columns:repeat(2,1fr)}
  .tsb-tm-steps{grid-template-columns:1fr}
}
@media(prefers-reduced-motion:no-preference){
  html{scroll-behavior:smooth}
}
@media(max-width:620px){
  .tsb-band{padding-top:var(--band-y-mobile);padding-bottom:var(--band-y-mobile)}
  .tsb .stats{grid-template-columns:1fr}
  .tsb .stats>div{border-left:0;border-top:1px solid var(--line)}
  .tsb .stats>div:first-child{border-top:0}
  .tsb-band-first{padding-top:18px}
  .tsb .tsb-stats{grid-template-columns:1fr}
  .tsb .tsb-stats>div{border-left:0;border-top:1px solid var(--line)}
  .tsb .tsb-stats>div:first-child{border-top:0}
}
@media(max-width:820px){
  .tsb .heroC{grid-template-columns:1fr}
  .tsb .heroC-text{padding:38px 26px}
  .tsb .heroC-img{min-height:230px;order:-1}
  .tsb .heroC-img:not(.ph)::before{background:linear-gradient(0deg,#fff 0%,rgba(255,255,255,0) 48%)}
  .tsb .tsb-heroC{grid-template-columns:1fr}
  .tsb .tsb-heroC-text{padding:40px 28px}
  .tsb .tsb-heroC-img{min-height:240px;order:-1}
  .tsb .tsb-heroC-img::before{background:linear-gradient(0deg,#fff 0%,rgba(255,255,255,0) 48%)}
}
@media(max-width:760px){
  .tsb .hero{grid-template-columns:1fr}
  .tsb .tsb-hero-grid{grid-template-columns:1fr;gap:28px}
  .tsb .tsb-hl{grid-template-columns:repeat(2,1fr)}
  .tsb .tsb-flow{grid-template-columns:1fr}
  .tsb .tsb-flow-step{padding:0 0 26px 0;display:grid;grid-template-columns:48px 1fr;column-gap:18px;align-items:stretch}
  .tsb .tsb-flow-step:last-child{padding-bottom:0}
  .tsb .tsb-flow-top{flex-direction:column;align-items:center;margin:0}
  .tsb .tsb-flow-line{display:block!important;width:3px;height:auto;flex:1 1 auto;min-height:24px;margin:8px 0 0;background:linear-gradient(180deg,var(--green-ink),rgba(10,107,46,.3))}
  .tsb .tsb-flow-step:last-child .tsb-flow-line{display:none!important}
  .tsb .tsb-flow-body{padding-top:9px}
  .tsb .tsb-flow p{max-width:none}
  .tsb .tsb-packs{grid-template-columns:1fr}
}
@media(max-width:600px){
  .tsb-tm-cal{padding:20px 16px 22px}
}

/* ------------------------------------- 12. Guthaben und Buchung (Track B) */
/*
   Die Bloecke der Shortcodes aus plugins/tsb-guthaben (inc/frontend.php, inc/login.php,
   inc/codes.php, inc/konto.php). Sie bringen bewusst KEIN eigenes <style> mit.

   ALLE Bloecke tragen im Markup zusaetzlich '.tsb'. Das ist Pflicht, nicht Kosmetik:
   die Buttonregeln (Abschnitt 27) haengen an :is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn, und
   die Basis-Typografie (Abschnitt 2) an .tsb. Ohne den Wrapper schluege das Theme-
   body{font-size:15px;line-height:1.66667em} durch - dessen 'em' vererbt als LAENGE und
   erzeugt wieder die verschiedenen Buttonhoehen, die Stufe 3 beseitigt hat.

   Die Klassen heissen .tsb-btn-green / .tsb-btn-ghost (EIN Bindestrich). Eine BEM-Form
   '.tsb-btn--primary' existiert nicht und traefe nichts.

   FELDER: Das Theme stylt Eingabefelder ausschliesslich ueber .wpcf7-form-control,
   #respond, .post-password-form und .mkd-search-form (verifiziert in modules.min.css).
   Unsere Felder tragen keine dieser Klassen, deshalb genuegt hier (0,1,0) - der
   Spezifitaets-Wettlauf aus Stufe 2 findet nicht statt. Die WERTE spiegeln trotzdem
   das CF7-Feld, damit beide Formulararten identisch aussehen; 16px bleibt die Grenze,
   ab der iOS beim Antippen nicht hineinzoomt.
*/

/* --- Gemeinsame Karte: Login, Einloesen, und die Sackgassen-Zustaende der Buchung. */
.tsb-login,
.tsb-einloesen,
.tsb-buchung--leer,
.tsb-buchung--fehler{
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-lg);
  padding: clamp(18px, 5vw, 32px);
  box-shadow: var(--sh-card);
}
/* [tsb_login] steht INNERHALB von [tsb_buchung] (Zustand "nicht angemeldet"). Zwei
   verschachtelte Karten waeren ein Rahmen im Rahmen. */
.tsb-buchung .tsb-login{
  border: 0;
  padding: 0;
  box-shadow: none;
  background: none;
}
.tsb-einloesen .tsb-login{ margin-top: var(--s-4) }

/* --- Buchungsbereich (/termine/) */
.tsb-buchung{ /* tsb-buchung-abstand */
  max-width: var(--w-page);
  margin-inline: auto;
  /* Oben schliesst die Schritt-Kette an, unten der dunkle Footer. Beide hatten
     0px Luft. Einzeln gesetzt, nie als Kurzschreibweise, sonst faellt
     margin-inline:auto weg und der Block rutscht nach links. */
  margin-top: var(--s-8);
  margin-bottom: var(--s-9);
}
@media (max-width: 767px){
  .tsb-buchung{ margin-top: var(--s-7); margin-bottom: var(--s-7) }
}
/* Anmeldung und Sackgasse sind Lesetexte, kein Kalender: volle Breite waere hier
   nur Leere um ein Formular herum. */
.tsb-buchung--anmelden{ max-width: var(--w-sub) }
.tsb-buchung--leer,
.tsb-buchung--fehler{ max-width: var(--w-read) }

.tsb-buchung__intro{ margin-bottom: var(--s-5) }
.tsb-buchung__titel{
  font: 700 var(--fs-2xl)/var(--lh-flat) var(--font-head);
  letter-spacing: var(--track-tight);
  color: var(--ink);
  margin: 0 0 var(--s-3);
}
.tsb-buchung__text{
  font-size: var(--fs-md);
  line-height: var(--lh-base);
  color: var(--ink-body);
  margin: 0;
}

/* Der Guthabenstand ist die Information, wegen der die Seite aufgerufen wird. */
.tsb-buchung__stand{
  background: var(--accent-soft);
  border-left: var(--b-accent);
  border-radius: var(--r-sm);
  padding: var(--s-4) var(--s-5);
  margin: 0 0 var(--s-5);
}
.tsb-buchung__saldo{
  font-size: var(--fs-md);
  line-height: var(--lh-flat);
  color: var(--ink-body);
  margin: 0;
}
.tsb-buchung__betrag{
  font-family: var(--font-head);
  font-size: var(--fs-xl);
  color: var(--accent);
  letter-spacing: var(--track-tight);
}
.tsb-buchung__einheiten{
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
  margin: var(--s-2) 0 0;
}
/* Leer heisst leer: eine Zeile "Das reicht fuer 0 Trainings" waere Rauschen. */
.tsb-buchung__einheiten:empty{ display: none }

.tsb-buchung__fakten{
  list-style: none;
  margin: 0 0 var(--s-5);
  padding: 0;
  border-top: var(--b-hair);
}
.tsb-buchung__fakten li{
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: var(--b-hair);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink-body);
}

/* Fristsatz: im Buchungsbereich und als [tsb_stornofrist] auf den Kaufseiten. */
.tsb-buchung__hinweis,
.tsb-hinweis{
  background: var(--surface-alt);
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  margin: 0 0 var(--s-5);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
}

/* Spiegelt .tsb-tm-cal (Abschnitt 27), damit der Kalender in beiden Einbettungen
   gleich sitzt. Der Inhalt ist ein same-origin iframe: kein Seiten-CSS greift hinein,
   gestaltet wird er ueber den styles-Block in ssa_settings_json. */
.tsb-buchung__kalender{
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-card);
  padding: clamp(16px, 4vw, 28px);
  margin: 0 0 var(--s-5);
}

.tsb-buchung__aktionen{
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin: var(--s-5) 0 0;
}
.tsb-buchung__fuss{
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
  margin: var(--s-5) 0 0;
}
.tsb-buchung--anmelden .tsb-buchung__fuss{
  border-top: var(--b-hair);
  padding-top: var(--s-4);
}

/* --- Anmeldung und Gutschein einloesen: gleiche Bauteile, gleiche Werte. */
.tsb-login__titel,
.tsb-einloesen__titel{
  font: 700 var(--fs-lg)/var(--lh-flat) var(--font-head);
  color: var(--ink);
  margin: 0 0 var(--s-3);
}
.tsb-login__text,
.tsb-einloesen__text{
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink-body);
  margin: 0 0 var(--s-4);
}
.tsb-login__form,
.tsb-einloesen__form{
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--s-2);
}
.tsb-login__label,
.tsb-einloesen__label{
  font: 700 var(--fs-xs)/var(--lh-flat) var(--font-head);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--muted);
}
.tsb-login__feld,
.tsb-einloesen__feld{
  width: 100%;
  box-sizing: border-box;
  border: var(--b-field);
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  min-height: 48px;
  margin: 0;
  background: var(--surface);
  color: var(--ink-body);
  -webkit-appearance: none;
  appearance: none;
}
.tsb-login__feld::placeholder,
.tsb-einloesen__feld::placeholder{ color: var(--placeholder); opacity: 1 }
.tsb-login__feld:focus,
.tsb-einloesen__feld:focus{ border-color: var(--accent) }
/* Der Code wird von einer Karte abgetippt: Ziffern gleich breit, Gross wie im Druck. */
.tsb-einloesen__feld{
  text-transform: uppercase;
  letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
}
/* Der Knopf soll nicht ueber die Feldbreite wachsen, aber auch nicht daran kleben. */
.tsb-login__form .tsb-btn,
.tsb-einloesen__form .tsb-btn{ margin-top: var(--s-2) }

.tsb-einloesen__fuss{
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
  margin: var(--s-4) 0 0;
}

/* --- Meldungen. Farbe ist nie der einzige Traeger (SC 1.4.1): der Text sagt es auch. */
.tsb-login__hinweis,
.tsb-einloesen__meldung{
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  margin: 0 0 var(--s-4);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
}
.tsb-login__hinweis--ok,
.tsb-einloesen__meldung--ok{
  background: var(--accent-soft);
  border-left: var(--b-accent);
  color: var(--ink-body);
}
.tsb-login__hinweis--fehler,
.tsb-einloesen__meldung--fehler{
  background: var(--surface-alt);
  border-left: 3px solid var(--error);
  color: var(--ink-body);
}

/* --- Guthaben-Zeile [tsb_guthaben] */
.tsb-guthaben__zeile{
  background: var(--surface-alt);
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  margin: 0;
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink-body);
}
.tsb-guthaben__betrag{ font-family: var(--font-head); color: var(--accent) }

/* --- Kasse: warum hier ploetzlich ein Konto noetig ist.
   Kein '.tsb'-Wrapper moeglich, der Hinweis wird von WooCommerce in dessen eigenes
   Formular gehaengt. Deshalb traegt er seine Basis vollstaendig selbst. */
.tsb-kasse__hinweis{
  background: var(--accent-soft);
  border-left: var(--b-accent);
  border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  margin-top: var(--s-5);
  margin-bottom: var(--s-5);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}
/* Ohne diese gespiegelte Kette klebt der Hinweis am E-Mail-Feld: das Theme setzt in der
   Kasse JEDEN Absatz auf `margin:0`, und zwar mit (0,3,1) - spezifischer als unsere Klasse.
   Gemessen am 22.07.: margin 0px/0px trotz der Regel darueber. */
.mkd-woocommerce-page .woocommerce-checkout .col-1 p.tsb-kasse__hinweis,
.mkd-woocommerce-page .woocommerce-checkout .col-2 p.tsb-kasse__hinweis{
  margin-top: var(--s-5);
  margin-bottom: var(--s-5);
}

@media (max-width: 600px){
  .tsb-buchung__stand{ padding: var(--s-3) var(--s-4) }
  .tsb-buchung__aktionen .tsb-btn{ width: 100% }
}

/* ------------------------------------- 13. WooCommerce-Kaufstrecke (Track B) */
/*
   /warenkorb/, /kasse/, /mein-konto/ trugen Theme-Standard: Buttons in Trophy-Lime
   #c1e729 (1,43:1), Felder 15px in Grau. Hier aufs Designsystem gehoben.

   SPEZIFITAET: Die hoechste Theme-Regel ist
     .woocommerce-page .mkd-content a.button            = (0,3,1)
     .woocommerce-page .mkd-content a.button:hover      = (0,4,1)
   Deshalb Prefix `body.woocommerce-page .mkd-content` (body als Element hebt die
   Spezifitaet ueber die Theme-Regel, unabhaengig von der Ladereihenfolge):
     body.woocommerce-page .mkd-content :is(a.button)        = (0,3,2)  > (0,3,1)
     body.woocommerce-page .mkd-content :is(.button.alt):hover = (0,5,1) > (0,4,1)
*/

/* --- Buttons: eine Form, gruen als Default (wie .tsb-btn-green) ---
   Modell bewusst umgekehrt: ALLE Kaufstrecken-Buttons sind primaer (gruen), NUR die zwei
   Neben-Aktionen (Warenkorb aktualisieren, Gutschein anwenden) sind ghost. Der fruehere
   Ansatz "alle .button ohne .alt = ghost" scheiterte, weil primaere Buttons wie der
   Login-Submit ebenfalls nur .button tragen und faelschlich ghost wurden; die
   :not()-Ketten hoben zudem die Spezifitaet ueber die Primaer-Regel. */
body.woocommerce-page .mkd-content :is(
  a.button, button.button, input.button, a.checkout-button,
  button[type="submit"], input[type="submit"],
  .woocommerce-button, .mainbutton, a.added_to_cart
){
  display: inline-flex; align-items: center; justify-content: center;
  width: auto; box-sizing: border-box;
  font-family: var(--font-head); font-weight: 700; font-size: var(--fs-base);
  line-height: var(--lh-1); text-transform: none; letter-spacing: var(--track-normal);
  min-height: 48px;
  padding-top: var(--s-3); padding-bottom: var(--s-3);
  padding-left: var(--s-5); padding-right: var(--s-5);
  border-radius: var(--r-sm); border: 1.5px solid transparent; cursor: pointer;
  background: var(--accent-bright); color: var(--accent-ink);
  transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
}
body.woocommerce-page .mkd-content :is(
  a.button, button.button, input.button, a.checkout-button,
  button[type="submit"], input[type="submit"],
  .woocommerce-button, .mainbutton, a.added_to_cart
):hover{
  background: var(--accent); color: var(--on-dark);
}
/* Ghost NUR fuer die Neben-Aktionen. name-Selektoren haben dieselbe Spezifitaet wie die
   Default-Regel; sie stehen SPAETER und gewinnen dadurch. Kein :not(), keine ID im :is(). */
body.woocommerce-page .mkd-content :is(
  button[name="update_cart"], input[name="update_cart"],
  button[name="apply_coupon"], input[name="apply_coupon"]
){
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
body.woocommerce-page .mkd-content :is(
  button[name="update_cart"], input[name="update_cart"],
  button[name="apply_coupon"], input[name="apply_coupon"]
):hover{
  background: var(--surface-alt); color: var(--ink); border-color: var(--line-field);
}
/*
   Ausnahme: "Warenkorb aktualisieren" und "Gutschein anwenden" sind Neben-Aktionen und
   sollen nicht mit dem Haupt-Grün konkurrieren (eine Primaeraktion je Seite). Sie sind
   button[type=submit] und faengen sonst die Primaer-Regel. Gleiche Spezifitaet, deshalb
   MUSS diese Regel NACH der Primaer-Regel stehen, damit sie gewinnt.
*/
body.woocommerce-page .mkd-content :is(
  button[name="update_cart"], input[name="update_cart"],
  button[name="apply_coupon"], input[name="apply_coupon"]
){
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
body.woocommerce-page .mkd-content :is(
  button[name="update_cart"], input[name="update_cart"],
  button[name="apply_coupon"], input[name="apply_coupon"]
):hover{
  background: var(--surface-alt); color: var(--ink); border-color: var(--line-field);
}

/* "Warenkorb anzeigen" (a.button.wc-forward in der "Produkt hinzugefuegt"-Meldung): das
   Theme faerbt es Lime mit (0,5,0):
     .woocommerce-page .mkd-content .wc-forward:not(.added_to_cart):not(.checkout-button)
   (0,5,2) schlaegt das; height:auto loest die feste 38px-Hoehe. .added_to_cart faengt schon
   die Basis-Regel oben, hier also ausgeschlossen. */
body.woocommerce-page .mkd-content a.button.wc-forward:not(.added_to_cart){
  background: var(--accent-bright); color: var(--accent-ink);
  height: auto; line-height: var(--lh-1); min-height: 48px;
  font-size: var(--fs-base); letter-spacing: var(--track-normal);
}
body.woocommerce-page .mkd-content a.button.wc-forward:not(.added_to_cart):hover{
  background: var(--accent); color: var(--on-dark);
}

/* --- Formularfelder (Kasse, Login, Konto): wie das CF7-Feld --- */
body.woocommerce-page .mkd-content :is(.input-text, input.input-text, textarea.input-text, select){
  width: 100%; box-sizing: border-box;
  border: var(--b-field); border-radius: var(--r-sm);
  padding: var(--s-3) var(--s-4);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  min-height: 48px; margin: 0;
  background: var(--surface); color: var(--ink-body);
  -webkit-appearance: none; appearance: none;
}
body.woocommerce-page .mkd-content :is(.input-text, select):focus{
  border-color: var(--accent);
}
body.woocommerce-page .mkd-content ::placeholder{ color: var(--placeholder); opacity: 1 }
body.woocommerce-page .mkd-content textarea.input-text{ min-height: 96px }
body.woocommerce-page .mkd-content label{ color: var(--ink-body) }

/* --- Links raus aus Lime (Passwort vergessen, Tabellen-Links, "zur Kasse") --- */
body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart){
  color: var(--accent);
}

/* --- Tabellen ruhig: Warenkorb, Bestelluebersicht, Kontoansicht --- */
body.woocommerce-page .mkd-content .woocommerce :is(table.shop_table, table.cart, .cart_totals table){
  border-color: var(--line);
}
body.woocommerce-page .mkd-content .woocommerce :is(table.shop_table th, table.cart th){
  color: var(--ink); font-family: var(--font-head);
}
body.woocommerce-page .mkd-content .woocommerce :is(table.shop_table td, table.cart td){
  color: var(--ink-body);
}
/* Erfolgs-/Infomeldungen im Markenton statt Theme-Farbe */
body.woocommerce-page .mkd-content .woocommerce-message{ border-top-color: var(--accent) }

/* ------------------------------- 14. WooCommerce-Feinschliff (Kundenfeedback 18.07.) */
/*
   BEFUND 1 — Icon lag ueber der Schrift.
   woocommerce.min.css haengt an JEDEN Kaufstrecken-Button einen absolut positionierten
   FontAwesome-Chevron:
     ... a.button:after { content:"\f054"; position:absolute; right:25px }
   und reserviert dafuer eine ASYMMETRISCHE Polsterung `padding:15px 40px 15px 32px`.
   Abschnitt 13 setzt den Button auf `display:inline-flex` + `padding-right:24px`.
   Damit brechen ZWEI Voraussetzungen des Icons gleichzeitig:
     (a) 24px < right:25px -> der Pfeil steht in der Contentbox, auf dem letzten Zeichen
         (im :hover ruecken 22px ihn noch 2px tiefer in den Text),
     (b) in einem Flex-Container liegt die statische Position eines absoluten
         Pseudoelements an der START-ECKE der Contentbox, nicht mehr auf der Textzeile.
         Da das :after kein `top` setzt, wandert es nach oben — waehrend der Text per
         `align-items:center` mittig bleibt. Ergebnis: Icon UEBER der Schrift.
   ENTSCHEIDUNG: Icon abschalten statt Polsterung aufweiten. Das Designsystem kennt an
   keinem der 18 vereinheitlichten .tsb-btn ein Button-Icon; die Kaufstrecke soll sich
   nicht als Sonderfall abheben. Der Gegenweg (padding-right >= 40px + top/translateY am
   :after) haette die Regel "eine Polsterung (16/24px)" aus dem Protokoll vom 17.07.
   gebrochen und die Buttons je nach Beschriftung unterschiedlich breit gemacht.
   SPEZIFITAET: (0,3,2) schlaegt Theme (0,3,1) und `div.woocommerce a.button:after` (0,2,2).
*/
body.woocommerce-page .mkd-content :is(
  a.button, button.button, input.button, a.checkout-button,
  button[type="submit"], input[type="submit"],
  .woocommerce-button, .mainbutton, a.added_to_cart
)::after{
  content: none;
}

/*
   BEFUND 2 — "Beschreibung"-Tab trug noch Trophy-Lime.
   Die Produktdetailseite war von Abschnitt 13 gar nicht erfasst: zu `woocommerce-tabs`
   gab es dort keine einzige Regel. Der aktive/gehoverte Tab kam unveraendert aus
   woocommerce.min.css mit `background-color:#c1e729` (1,43:1).
   SPEZIFITAET: (0,4,4) schlaegt die Theme-Regel (0,4,1).
   Die Responsive-Variante stellt die Tabs unter Breakpoint auf `width:35%` neben den
   Inhalt und aendert Hoehe/Polsterung — Farbe ist davon unabhaengig, daher hier nur die
   Farbrollen, keine Geometrie.
*/
body.mkd-woo-single-page .woocommerce-tabs ul.tabs > li:is(.active, :hover) a{
  background-color: var(--accent);
  color: var(--on-dark);
}
/* Ruhende Tabs: neutraler Rahmen statt Theme-Grau, damit der aktive Tab traegt */
body.mkd-woo-single-page .woocommerce-tabs ul.tabs > li a{
  border-color: var(--line);
  color: var(--ink);
}

/* ------------------------- 15. Trophy-Lime ausmustern (Kundenentscheidung 18.07.) */
/*
   AUSGANGSLAGE (gemessen, nicht aus dem CSS gelesen):
   Die Lime #c1e729 (1,43:1 auf Weiss) steckt WEDER in der Datenbank NOCH im
   post_content - `wp_options LIKE '%c1e729%'` = 0 Zeilen. Sie kommt ausschliesslich
   aus zwei ausgelieferten Theme-Dateien: modules.min.css (139x) und
   woocommerce.min.css (31x). Theme-Optionen umzustellen haette also nichts bewirkt,
   und die Theme-Dateien zu editieren waere beim naechsten Update weg.
   -> Gegenregeln hier, in der einen Design-Quelle.

   FARBROLLE STATT EINEM FARBWERT:
   --accent (#0a6b2e, 6,66:1) ist auf DUNKLEM Grund fast unsichtbar. Der Header
   (#141615), der Titelbereich-Hero (dunkles Bild) und der Footer bekommen deshalb
   --accent-bright (#43ec6b), alle hellen Flaechen --accent. Beides ist "das neue
   Gruen", nur in der jeweils lesbaren Rolle.

   BUTTON-MUSTER: Ruhe --accent-bright auf --accent-ink, Hover --accent auf
   --on-dark. Das ist exakt das Muster der Kaufstrecke aus Abschnitt 13 - der Kunde
   hat den Hover von "Zum Shop" ausdruecklich als richtig bestaetigt.
*/

/* --- 15.1 Startseiten-CTAs (.mkd-btn-solid, 6 Stueck) ---
   Groesster sichtbarer Rest: volle Lime-Flaeche. Die konkurrierende Theme-Regel
   `.mkd-btn.mkd-btn-solid{background-color:#221f1b!important}` matcht diese Buttons
   nachweislich NICHT (gemessen: sie rendern lime), daher reicht normale Spezifitaet.
   `border` mitfuehren, sonst bleibt der 2px-Lime-Rahmen stehen. */
body .mkd-btn.mkd-btn-solid{
  background-color: var(--accent-bright);
  border-color: var(--accent-bright);
  color: var(--accent-ink);
}
/* Der Hover braucht die :not()-Kette des Themes mit: dessen Regeln sind
     .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-bg):hover        = (0,4,0)
     .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-border-hover):hover = (0,4,0)
   Ein blosses `body …:hover` waere (0,3,1) und verliert - Klassen wiegen schwerer
   als Elemente. Das :not() zaehlt fuer die Spezifitaet wie eine Klasse. */
body .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-bg):hover,
body .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-hover-bg):hover,
body .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-border-hover):hover{
  background-color: var(--accent);
  border-color: var(--accent);
  color: var(--on-dark);
}

/* --- 15.2 Hauptnavigation: Pfeile + aktiver Unterstrich (DUNKLER Header) ---
   Der Pfeil ist ein KIND des Menuelinks mit eigener `color` - er erbt die in
   Abschnitt 9 gesetzte Linkfarbe nicht. Der Unterstrich ist ein `box-shadow: inset`,
   kein border; eine reine `color`-Regel erreicht ihn nie. */
body .mkd-page-header .mkd-main-menu > ul > li.has_sub > a .mkd-menu-arrow,
body .mkd-page-header .mkd-main-menu > ul > li.has_sub > a .item_inner > .mkd-menu-arrow{
  color: var(--accent-bright);
}
body .mkd-page-header .mkd-main-menu > ul > li > a.current,
body .mkd-page-header .mkd-main-menu > ul > li > a:hover{
  box-shadow: inset 0 -4px 0 var(--accent-bright);
}

/* --- 15.3 Dropdown-Panel: Oberkante + Hover-Balken (WEISSES Panel -> --accent) ---
   Das Panel hat `background-color:#fff` (im Theme geprueft), hier waere das helle
   Gruen ein grellter Streifen ohne Kontrast. */
body .mkd-drop-down > ul > li.narrow > .second > .inner > ul,
body .mkd-drop-down > ul > li.wide > .second > .inner > ul,
body .mkd-drop-down .narrow .second .inner ul li ul{
  border-top-color: var(--accent);
}
body .mkd-drop-down .second .inner ul li a:before{
  background: var(--accent);
}

/* --- 15.4 Warenkorb im Header: Zaehler + Dropdown-Kante ---
   Der Zaehler traegt im Theme `!important`, deshalb hier ebenfalls - sonst bleibt er
   lime. Kleine Flaeche auf dunklem Header mit dunkler Schrift -> --accent-bright.
   Das Warenkorb-Dropdown ist wieder ein weisses Panel -> --accent. */
body .mkd-shopping-cart-holder .mkd-header-cart .mkd-cart-number{
  background-color: var(--accent-bright) !important;
  color: var(--accent-ink) !important;
}
/* ACHTUNG: `mkd-dropdown-animate-height` sitzt auf dem BODY selbst, nicht auf einem
   Vorfahren. `body .mkd-dropdown-animate-height …` (Nachfahre) matcht deshalb nie -
   es muss `body.mkd-dropdown-animate-height …` heissen. Mit dem Leerzeichen blieb die
   Kante lime, weil dann nur `body .mkd-shopping-cart-dropdown` (0,1,1) uebrig war und
   gegen die Theme-Regel (0,2,0) verlor. */
body .mkd-shopping-cart-dropdown,
body.mkd-dropdown-animate-height .mkd-shopping-cart-dropdown{
  border-top-color: var(--accent);
}

/* --- 15.5 Trennstriche (.mkd-separator) - nach Untergrund getrennt ---
   Standard steht auf weissen Sektionen, die beiden Ausnahmen auf dunklem Grund:
   .mkd-title = Titelbereich-Hero (dunkles Bild), footer = #141615. */
body .mkd-separator{ border-color: var(--accent) }
body .mkd-title .mkd-separator-holder .mkd-separator,
body footer .mkd-footer-top .widget .mkd-widget-title-holder .mkd-separator{
  border-color: var(--accent-bright);
}
/* Widget-Titel in hellen Sidebars (Shop) bleiben auf --accent */
body .wpb_widgetised_column .widget .mkd-widget-title-holder .mkd-separator,
body aside.mkd-sidebar .widget .mkd-widget-title-holder .mkd-separator{
  border-color: var(--accent);
}

/* --- 15.6 WooCommerce-Shop-Loop: Hover der Kachel-Buttons ---
   Hier war es KEINE fehlende Regel, sondern Spezifitaet: die Theme-Regel
     ul.products>.product .mkd-pl-inner .mkd-pl-text-inner .button:hover  = (0,6,1)
   schlaegt den Kaufstrecken-Hover aus Abschnitt 13 (0,3,2). Der Ruhezustand war
   bereits gruen, nur der Hover kippte auf Lime - genau die Kundenmeldung.
   Diese Regel = (0,7,4). */
body.woocommerce ul.products > li.product .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart):hover,
body.woocommerce-page ul.products > li.product .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart):hover{
  background-color: var(--accent);
  color: var(--on-dark);
}

/* --- 15.7 Mengen-Waehler auf der Produktseite (+/-) --- */
/* Theme ist `div.woocommerce .mkd-quantity-buttons .mkd-quantity-plus:hover` = (0,4,1);
   ein `body .mkd-quantity-buttons …` waere (0,3,1) und verliert. Beide Theme-Aeste
   (div.woocommerce UND .woocommerce-page .mkd-content) spiegeln. */
body div.woocommerce .mkd-quantity-buttons :is(.mkd-quantity-plus, .mkd-quantity-minus):hover,
body.woocommerce-page .mkd-content .mkd-quantity-buttons :is(.mkd-quantity-plus, .mkd-quantity-minus):hover{
  color: var(--accent);
}

/* --- 15.8 Textmarkierung --- */
body ::selection{ background: var(--accent); color: var(--on-dark) }
body ::-moz-selection{ background: var(--accent); color: var(--on-dark) }

/* --- 15.9 Listen-Icons: KEINE Regel noetig.
   Gemessen rendern sie bereits weiss (rgb(255,255,255)) im dunklen Footer - die
   Lime-Regel des Themes wird dort schon ueberschrieben. Bewusst nicht angefasst. */

/* --- 15.10 Produktkacheln AUSSERHALB der Kaufstrecke (Merch-Slider auf der Startseite)
   Die Startseite traegt am <body> KEINE Klasse `woocommerce-page` - nur ein
   `div.woocommerce` um den Slider (Kette geprueft: body.home … > div.woocommerce.tsb-merch
   > ul.products > li.product > … > a.button). Damit greift dort weder Abschnitt 13
   (verlangt `body.woocommerce-page`) noch 15.6 (verlangt `body.woocommerce`), und die
   6 Kachel-Buttons blieben im Ruhezustand lime - aus dem Theme-Ast `div.woocommerce a.button`.
   Diese Regeln kommen deshalb OHNE body-Klasse aus und haengen nur am Kachel-Markup.

   Bewusst auf `.mkd-pl-text-inner` eingegrenzt statt pauschal auf `div.woocommerce`:
   sonst wuerden die Ghost-Nebenaktionen der Kaufstrecke (Warenkorb aktualisieren,
   Gutschein anwenden) aus Abschnitt 13 mit erfasst. */
body .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart){
  background-color: var(--accent-bright);
  color: var(--accent-ink);
}
/* Theme-Hover ist `ul.products>.product .mkd-pl-inner .mkd-pl-text-inner .button:hover`
   = (0,6,1); diese Regel = (0,6,4). */
body ul.products > li.product .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart):hover{
  background-color: var(--accent);
  color: var(--on-dark);
}

/* --- 15.11 Produktsuche in der Shop-Sidebar ---
   Theme: `.widget.woocommerce.widget_product_search .input-holder button{background:#c1e729}`
   = (0,4,1). Diese Regel = (0,4,2). Der Fokusring dieses Feldes wurde am 17.07. bereits
   per box-shadow geloest (outline kam an Woo-Buttons grundsaetzlich nicht durch) - hier
   geht es nur um die Flaeche. */
body .widget.woocommerce.widget_product_search .input-holder button{
  background: var(--accent);
  color: var(--on-dark);
}
body .widget.woocommerce.widget_product_search .input-holder button:hover{
  background: var(--accent-bright);
  color: var(--accent-ink);
}

/* --- 15.12 Lesbarkeit des CTA-Hovers: die !important-Textfarben des Themes
   Gemessen: die vier "Einheit buchen"-Buttons der Startseite stehen in Info-Boxen, und
   dafuer setzt das Theme
     .mkd-info-box-holder … .mkd-btn.mkd-btn-solid:hover{color:#221f1b!important}
   Zusammen mit unserem gruenen Hover-Grund (--accent #0a6b2e) ergaebe das dunklen Text
   auf dunklem Gruen = ~1,9:1 - schlechter als die Lime, die wir gerade ersetzt haben.
   Gegen `!important` hilft nur `!important`, und bei gleichem Gewicht entscheidet die
   Spezifitaet: die Theme-Kette (0,6,1) wird hier mit vorangestelltem `body` (0,6,2)
   gespiegelt. Ein kurzer Selektor wuerde trotz !important verlieren.
   Die zwei Preistabellen-Varianten sind mitgespiegelt, obwohl aktuell kein
   .mkd-price-table im Markup steht - sonst faellt es beim naechsten Einsatz auf. */
body .mkd-info-box-holder .mkd-ib-front-holder .mkd-ib-bottom-holder .mkd-ib-button-holder .mkd-btn.mkd-btn-solid:hover,
body .mkd-price-table:not(.mkd-active) .mkd-price-table-inner .mkd-btn.mkd-btn-solid:hover,
body .mkd-price-table.mkd-active .mkd-price-table-inner .mkd-btn.mkd-btn-solid:hover{
  color: var(--on-dark) !important;
}

/* --- 15.13 Listen-Icons im Inhaltsbereich (Kontaktseite: Telefon, E-Mail)
   Theme: `.mkd-unordered-list ul>li.mkd-list-item .icon i{color:#c1e729}` = (0,3,3).
   BEWUSST auf `.mkd-content` eingegrenzt (= (0,4,4)): dieselben Icons stehen auch im
   Footer, dort sind sie bereits weiss auf dunklem Grund - eine ungescopte Regel wuerde
   diesen korrekten Zustand mit uebersteuern und Dunkelgruen auf Schwarz erzeugen.
   Der Footer liegt ausserhalb von .mkd-content und bleibt damit unberuehrt. */
body .mkd-content .mkd-unordered-list ul > li.mkd-list-item .icon i{
  color: var(--accent);
}

/* =========================================================================
   16. Startseite (#5788, Umbau 18.07.2026)
   -------------------------------------------------------------------------
   Bewusst KLEIN gehalten: Intro, Baustein-Karten, Trainer-Band, Vertrauens-
   Streifen und FAQ sind neu. Alles andere kommt aus Abschnitt 27:
   .tsb-inner .tsb-band .tsb-band-alt .kick .bt .lead .tsb-btn .tsb-btn-green
   .tsb-btn-ghost .packs .pack .tsb-flow .tsb-cta

   Zwei Abweichungen von Abschnitt 27, jeweils als Modifier statt als Kopie:
   .packs--3 (drei statt zwei Pakete) und .tsb-flow--3 (drei statt vier Schritte).
   ========================================================================= */

/* Die Startseite nutzt das Full-Width-Template; ihre Rows liegen AUSSERHALB
   von .mkd-container-inner, der Container-Fix aus Abschnitt 3 greift hier
   also nicht. Deshalb setzt der Wrapper seine Breite selbst. */
.tsb-start .tsb-inner{ max-width: var(--w-page); margin: 0 auto; padding-inline: var(--gutter) }

/* Abschnitt 27 setzt .tsb-band-dark{padding-bottom:0} - gedacht fuer das alte
   CTA-Band, das nahtlos in den Footer laeuft. Auf der Startseite sind die
   dunklen Baender eigenstaendig (Trainer, Abschluss-CTA) und brauchen ihren
   Bandtakt unten zurueck, sonst klebt der Inhalt an der Kante. */
.tsb-start .tsb-band-dark{ padding-bottom: var(--band-y) }
@media (max-width: 768px){
  .tsb-start .tsb-band-dark{ padding-bottom: var(--band-y-mobile) }
}

/* ---- Intro: "Schoen, dass du hier bist!" -------------------------------- */
.tsb-start .tsb-intro{
  max-width: var(--w-read);
  margin: 0 auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.tsb-start .tsb-intro :is(h1,h2){
  font-size: var(--fs-2xl); font-weight: 700; line-height: var(--lh-flat);
  letter-spacing: var(--track-tight); margin: 0 0 var(--s-2);
}
/* :not(.kick) ist PFLICHT. Ohne das schlaegt diese Regel (0,2,1) die Kicker-
   Regel .tsb .kick (0,2,0) und der Kicker verliert Farbe und Groesse - er
   stand dadurch in 19px Fliesstextfarbe statt in 12px Gruen. */
.tsb-start .tsb-intro p:not(.kick){
  font-size: var(--fs-md); line-height: var(--lh-loose);
  color: var(--ink-body); margin: 0;
}

/* ---- Baustein-Karten: Bild IMMER sichtbar ------------------------------- */
/* Vorher waren es .mkd_info_box mit background_image, das Bild erschien erst
   beim Zeigen. Jetzt traegt jede Karte ihr Bild dauerhaft; der Hover bewegt
   nur noch. .ptile taugte nicht als Basis: das ist ein Link mit Preis-Chip
   und Pfeil, diese Karten verlinken nirgendwohin. */
.tsb-start .tsb-bcards{
  display: grid; gap: var(--s-5);
  grid-template-columns: repeat(4, 1fr);
}
.tsb-start .tsb-bcard{
  display: flex; flex-direction: column;
  background: var(--surface); border: var(--b-hair);
  border-radius: var(--r-md); overflow: hidden;
  box-shadow: var(--sh-card);
  transition: box-shadow var(--t-base), transform var(--t-fast);
}
.tsb-start .tsb-bcard__media{
  position: relative; aspect-ratio: 16 / 10;
  overflow: hidden; background: var(--surface-alt);
}
.tsb-start .tsb-bcard__media img{
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform 400ms cubic-bezier(.2,.6,.2,1);
}
/* Verlauf nur unten: traegt das Icon lesbar, ohne das Bild flaechig abzudunkeln */
.tsb-start .tsb-bcard__media::after{
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(20,22,21,0) 45%, rgba(20,22,21,.55) 100%);
  transition: opacity 250ms ease;
}
.tsb-start .tsb-bcard__badge{
  position: absolute; left: var(--s-4); bottom: var(--s-4); z-index: 1;
  width: 40px; height: 40px; border-radius: var(--r-sm);
  background: var(--accent-bright); color: var(--accent-ink);
  display: grid; place-items: center;
  transition: transform 250ms ease;
}
.tsb-start .tsb-bcard__badge svg{ width: 21px; height: 21px }
.tsb-start .tsb-bcard__body{
  padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-2);
}
.tsb-start .tsb-bcard__body h3{
  font-size: var(--fs-lg); font-weight: 600; margin: 0; line-height: var(--lh-flat);
}
.tsb-start .tsb-bcard__body p{
  margin: 0; color: var(--muted); line-height: var(--lh-base);
}
.tsb-start .tsb-bcard:hover,
.tsb-start .tsb-bcard:focus-within{
  box-shadow: var(--sh-lift); transform: translateY(-3px);
}
.tsb-start .tsb-bcard:hover .tsb-bcard__media img,
.tsb-start .tsb-bcard:focus-within .tsb-bcard__media img{ transform: scale(1.06) }
.tsb-start .tsb-bcard:hover .tsb-bcard__media::after,
.tsb-start .tsb-bcard:focus-within .tsb-bcard__media::after{ opacity: .75 }
.tsb-start .tsb-bcard:hover .tsb-bcard__badge,
.tsb-start .tsb-bcard:focus-within .tsb-bcard__badge{ transform: translateY(-3px) }

/* ---- Trainer-Band (dunkel) ---------------------------------------------- */
.tsb-start .tsb-band-dark{ background: var(--surface-dark); color: var(--on-dark) }
.tsb-start .tsb-band-dark :is(h2,h3,h4){ color: var(--on-dark) }
.tsb-start .tsb-band-dark .kick{ color: var(--accent-bright) }

.tsb-start .tsb-trainer{
  display: grid; grid-template-columns: .85fr 1.15fr;
  gap: var(--s-8); align-items: center;
}
.tsb-start .tsb-trainer__media{
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: var(--sh-lift); aspect-ratio: 4 / 5;
}
.tsb-start .tsb-trainer__media img{
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.tsb-start .tsb-trainer__quote{
  font-family: var(--font-head);
  font-size: var(--fs-xl); font-weight: 600; line-height: 1.32;
  letter-spacing: var(--track-tight);
  color: var(--on-dark);
  margin: 0 0 var(--s-5); max-width: 26ch;
}
.tsb-start .tsb-trainer__body{ max-width: var(--w-read); line-height: var(--lh-loose); color: #d7ddd8 }
.tsb-start .tsb-trainer__body p{ margin: 0 }
.tsb-start .tsb-trainer__body p + p{ margin-top: var(--s-4) }

.tsb-start .tsb-belege{
  display: flex; flex-wrap: wrap; gap: var(--s-2);
  list-style: none; margin: var(--s-6) 0 0; padding: 0;
}
.tsb-start .tsb-belege li{
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-head); font-size: var(--fs-sm); font-weight: 700;
  color: var(--on-dark);
  background: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.16);
  border-radius: var(--r-pill); padding: 8px 14px;
}
.tsb-start .tsb-belege svg{ width: 15px; height: 15px; flex: none; color: var(--accent-bright) }

.tsb-start .tsb-sig{
  margin-top: var(--s-6);
  display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap;
}
/* Die Signaturzeile ist das letzte Element der Trainer-Spalte. Auf schmalen
   Fenstern klebte sie an der Bandkante, weil die Spalte selbst keinen
   Innenabstand hat. */
.tsb-start .tsb-trainer > div:last-child{ padding-bottom: var(--s-2) }
/* Auf dem dunklen Band liegt eine eigene, weisse Fassung der Unterschrift
   (#10818). Ein CSS-Filter taugte hier nicht: das Original ist blau, und
   invert() macht daraus Gelb statt Weiss. */
.tsb-start .tsb-sig img{ height: 52px; width: auto; display: block }
.tsb-start .tsb-sig span{ font-size: var(--fs-sm); color: var(--on-dark-muted) }

/* ---- Vertrauens-Streifen ------------------------------------------------ */
/* Ersetzt den alten Kasten "Hinweis: Es werden keine Spieler ... abgeworben".
   NICHT .tsb-hinweis nehmen, das ist der kleine Fristsatz aus Abschnitt 12. */
.tsb-start .tsb-trust{
  background: var(--surface-alt);
  border-left: var(--b-accent);
  border-radius: var(--r-sm);
  padding: var(--s-6);
  display: flex; gap: var(--s-5); align-items: flex-start;
}
.tsb-start .tsb-trust > svg{ width: 32px; height: 32px; flex: none; color: var(--accent); margin-top: 2px }
.tsb-start .tsb-trust :is(h2,h3){ font-size: var(--fs-lg); font-weight: 600; margin: 0 0 var(--s-2) }
.tsb-start .tsb-trust p{ margin: 0; max-width: 64ch; line-height: var(--lh-loose) }

/* ---- Preis-Karten: drei statt zwei -------------------------------------- */
.tsb-start .packs--3{ grid-template-columns: repeat(3, 1fr) }

/* ---- Schritt-Kette: drei statt vier ------------------------------------- */
.tsb-start .tsb-flow--3{ grid-template-columns: repeat(3, 1fr) }

/* ---- FAQ ---------------------------------------------------------------- */
/* Eigenes <details>-Markup statt [mkd_accordion_holder]. Grund: der Theme-
   Akkordeon rendert seine Titel als <h6> in 13px und #898888 (3,50:1, unter
   AA) und braucht jQuery-UI. <details> kann das ohne JavaScript.
   ACHTUNG: damit ist scripts/faq-2026-07/build-faq.php gegenstandslos - es
   sucht genau einen [mkd_accordion_holder] und bricht sonst ab. */
.tsb .tsb-faq{
  max-width: 840px; margin: 0 auto;
  display: flex; flex-direction: column; gap: var(--s-3);
}
.tsb .tsb-faq details{
  background: var(--surface); border: var(--b-hair);
  border-radius: var(--r-sm); overflow: hidden;
}
.tsb .tsb-faq summary{
  cursor: pointer; padding: 18px var(--s-5);
  font-family: var(--font-head); font-size: var(--fs-lg); font-weight: 600;
  color: var(--ink); list-style: none;
  display: flex; justify-content: space-between; align-items: center; gap: var(--s-4);
}
.tsb .tsb-faq summary::-webkit-details-marker{ display: none }
.tsb .tsb-faq summary:focus-visible{ outline: 3px solid var(--accent); outline-offset: -3px }
.tsb .tsb-faq summary::after{
  content: ""; width: 11px; height: 11px; flex: none;
  border-right: 2px solid var(--accent); border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  /* gleiche Dauer und Kurve wie die Hoehenanimation in tsb-startseite.php,
     sonst laeuft der Pfeil dem Aufklappen davon */
  transition: transform 280ms cubic-bezier(.32,.72,0,1);
}
.tsb .tsb-faq details[open] summary::after{ transform: rotate(-135deg) }
/* Beim Zuklappen faellt [open] erst NACH der Animation - der Pfeil wuerde 280 ms
   zu spaet drehen. Diese Klasse setzt das Skript sofort beim Klick. */
.tsb .tsb-faq details.tsb-is-closing summary::after{ transform: rotate(45deg) }
.tsb .tsb-faq__body{
  padding: 0 var(--s-5) var(--s-5);
  line-height: var(--lh-loose); color: var(--ink-body);
}
.tsb .tsb-faq__body p{ margin: 0 }
.tsb .tsb-faq__body p + p{ margin-top: var(--s-3) }
.tsb .tsb-faq__body a{ color: var(--accent); font-weight: 700 }

/* ---- Ueberschriften der Abschnitte --------------------------------------- */
.tsb .tsb-shortcode-head{ margin-bottom: var(--s-7) }
.tsb .tsb-shortcode-head--center{ text-align: center }
/* Bei Merch sitzt der Slider direkt unter dem Kopf, dort ist der volle
   Bandtakt zu viel Luft. */
.tsb .tsb-shortcode-head--eng{ margin-bottom: var(--s-5) }

/* =========================================================================
   Merch- und Partner-Band
   -------------------------------------------------------------------------
   ⚠️ Diese beiden Baender werden NICHT von einem eigenen <div> umschlossen.
   Grund: WPBakery rendert JEDEN [vc_raw_html] in ein eigenes
   .wpb_raw_code > .wpb_wrapper. Ein dort geoeffnetes <section> wird vom
   Browser am Blockende wieder geschlossen - der Shortcode-Output landet
   danach als GESCHWISTER und steht ausserhalb. Genau so standen die
   Partner-Logos unter der grauen Flaeche statt darin, und der Merch-Slider
   lief ueber die volle Fensterbreite statt im 1100er-Raster.
   Deshalb traegt hier die vc_row selbst die Klasse (el_class) und das Band
   wird ueber sie gestaltet. Der raw-Block enthaelt nur noch den Kopf und ist
   in sich geschlossen.
   ========================================================================= */
.tsb-band-merch,
.tsb-band-partner{
  padding-top: var(--band-y);
  padding-bottom: var(--band-y);
}
.tsb-band-merch{ background: var(--surface) }
.tsb-band-partner{ background: var(--surface-alt) }

/* Der innere Wrapper der Spalte traegt das Raster fuer Kopf UND Shortcode. */
.tsb-band-merch .vc_column-inner > .wpb_wrapper,
.tsb-band-partner .vc_column-inner > .wpb_wrapper{
  /* box-sizing gehoert dazu: WPBakery vererbt hier content-box, dadurch
     wurden aus 1100px Raster 1144px (Padding oben drauf gerechnet). */
  box-sizing: border-box;
  max-width: var(--w-page);
  margin: 0 auto;
  padding-inline: var(--gutter);
}
@media (max-width: 768px){
  .tsb-band-merch,
  .tsb-band-partner{
    padding-top: var(--band-y-mobile);
    padding-bottom: var(--band-y-mobile);
  }
}

/* ---- Merch-Pfeile aus den Kacheln herausholen ----------------------------
   Abschnitt 9 setzt die Pfeile auf left/right: -22px. Bei 44px Durchmesser
   liegt damit die Haelfte des Knopfes UEBER der ersten und letzten Kachel.
   Solange der Slider die volle Fensterbreite hatte, fiel das nicht auf; seit
   er im 1100er-Raster steht, sitzt er auf den Produktbildern.

   Statt fester Negativwerte bekommt der Slider einen eigenen Seitenraum, in
   dem die Pfeile stehen. Damit koennen sie in KEINER Fensterbreite ueberlappen.
   Ist genug Platz, bricht der Raum nach aussen aus, damit die Kacheln ihre
   volle Rasterbreite behalten; ist es eng, rueckt der Slider ein.
   Unter 768px sind die Pfeile ohnehin aus (dort wird gewischt). */
:root{ --merch-pfeil: 56px }

@media (min-width: 769px){
  body.home .tsb-merch{ padding-inline: var(--merch-pfeil) }
  /* left/right beziehen sich auf die Border-Box, der Knopf sitzt also im
     Seitenraum und nicht auf der Kachel. */
  body.home .tsb-merch__nav--prev{ left: 0 }
  body.home .tsb-merch__nav--next{ right: 0 }
}
/* Genug Luft neben dem Raster: nach aussen ausbrechen, damit die Kacheln
   nicht schmaler werden. 1100 Raster + 2x56 Seitenraum + Rand = ab ~1240px. */
@media (min-width: 1240px){
  body.home .tsb-merch{ margin-inline: calc(-1 * var(--merch-pfeil)) }
}

/* ---- Partner-Leiste, mobil ----------------------------------------------
   Bestandsfehler, unabhaengig vom Umbau: Owl legt eine 1320px breite Stage in
   ein 370px-Fenster, also ist bei 390px genau EIN Partner von vier sichtbar.
   Da Autoplay, Loop und Pagination am 16.07. abgeschaltet wurden (auf dem
   Desktop voellig richtig, dort stehen alle vier nebeneinander), gibt es
   keinen Weg zu den anderen dreien.
   Loesung: unterhalb von 768px das Owl-Layout neutralisieren und die Logos
   als einfaches Raster zeigen. Owl setzt width und transform INLINE, deshalb
   ist !important hier unvermeidbar. Der Desktop bleibt unberuehrt. */
@media (max-width: 768px){
  .tsb-band-partner .mkd-clients-carousel .owl-stage-outer{ overflow: visible !important }
  .tsb-band-partner .mkd-clients-carousel .owl-stage{
    width: auto !important;
    transform: none !important;
    display: flex !important;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: var(--s-6) var(--s-7);
  }
  .tsb-band-partner .mkd-clients-carousel .owl-item{
    width: auto !important;
    flex: 0 0 calc(50% - var(--s-7));
    margin: 0 !important;
    float: none !important;
  }
  .tsb-band-partner .mkd-clients-carousel .owl-item img{
    max-width: 100%;
    max-height: 52px;
    width: auto;
    margin: 0 auto;
  }
}
@media (max-width: 420px){
  /* Zwei nebeneinander werden bei sehr schmalen Geraeten zu klein. */
  .tsb-band-partner .mkd-clients-carousel .owl-item{ flex: 0 0 100% }
}

/* ---- Breakpoints -------------------------------------------------------- */
@media (max-width: 1024px){
  .tsb-start .tsb-bcards{ grid-template-columns: repeat(2, 1fr) }
  .tsb-start .packs--3{ grid-template-columns: 1fr }
  .tsb-start .tsb-flow--3{ grid-template-columns: 1fr; gap: var(--s-5) }
  /* Die Verbindungslinie ergibt untereinander keinen Sinn mehr. */
  .tsb-start .tsb-flow--3 .tsb-flow-line{ display: none }
  .tsb-start .tsb-flow--3 .tsb-flow-step{ padding-right: 0 }
}
@media (max-width: 900px){
  .tsb-start .tsb-trainer{ grid-template-columns: 1fr; gap: var(--s-6) }
  /* Portraetfoto bleibt Portraet: ein 3/2-Zuschnitt kappt den Kopf. */
  .tsb-start .tsb-trainer__media{ aspect-ratio: 4 / 5; max-height: 60vh }
}
@media (max-width: 768px){
  .tsb-start .tsb-bcards{ grid-template-columns: 1fr }
}
@media (max-width: 600px){
  .tsb-start .tsb-trust{ flex-direction: column; gap: var(--s-4); padding: var(--s-5) }
}

@media (prefers-reduced-motion: reduce){
  .tsb-start .tsb-bcard,
  .tsb-start .tsb-bcard__media img,
  .tsb-start .tsb-bcard__badge,
  .tsb .tsb-faq summary::after{ transition: none }
  .tsb-start .tsb-bcard:hover{ transform: none }
  .tsb-start .tsb-bcard:hover .tsb-bcard__media img{ transform: none }
}

/* =========================================================================
   17. Porträt (#5746) und Kontakt (#5989), Umbau 18.07.2026
   -------------------------------------------------------------------------
   Die ANORDNUNG beider Seiten bleibt unveraendert (Kundenwort): Titelbereich,
   dann "Ueber mich" mit Foto rechts bzw. Karte links mit Text rechts, dann
   die vier Karten bzw. Formular und Abschlussband.

   Wiederverwendet aus Abschnitt 27/16: .tsb .tsb-inner .tsb-band .kick .bt
   .lead .tsb-btn .tsb-btn-green .tsb-btn-ghost .stats .tsb-bcard (Karten mit
   Bild + Hover) sowie das Formular-CSS aus Abschnitt 8.
   Neu sind nur: Zwei-Spalter fuer beide Seiten, Kontaktdaten-Kacheln und das
   Abschlussband.
   ========================================================================= */

/* Beide Seiten nutzen dasselbe Grundgeruest wie die Startseite. */
.tsb-pk .tsb-inner{ max-width: var(--w-page); margin: 0 auto; padding-inline: var(--gutter) }

/* Wie in Abschnitt 16: .tsb-band-dark bringt padding-bottom:0 aus Abschnitt 27
   mit (alter Footer-Uebergang). Hier sind die dunklen Baender eigenstaendig. */
.tsb-pk .tsb-band-dark{ background: var(--surface-dark); color: var(--on-dark); padding-bottom: var(--band-y) }
.tsb-pk .tsb-band-dark :is(h2,h3,h4){ color: var(--on-dark) }
.tsb-pk .tsb-band-dark .kick{ color: var(--accent-bright) }
@media (max-width: 768px){ .tsb-pk .tsb-band-dark{ padding-bottom: var(--band-y-mobile) } }

/* ---- Zwei-Spalter: Text + Medium ---------------------------------------- */
/* Porträt: Text links, Foto rechts. Kontakt: Karte links, Text rechts.
   Beides dieselbe Mechanik, nur die Spaltenanteile unterscheiden sich. */
.tsb-pk .tsb-split{ display: grid; gap: var(--s-8); align-items: start }
.tsb-pk .tsb-split--portrait{ grid-template-columns: 1.25fr .75fr }
.tsb-pk .tsb-split--kontakt{ grid-template-columns: 1fr 1fr; align-items: center }
@media (max-width: 900px){
  .tsb-pk .tsb-split{ grid-template-columns: 1fr !important; gap: var(--s-6) }
}

.tsb-pk .tsb-split__media{
  border-radius: var(--r-lg); overflow: hidden;
  box-shadow: var(--sh-lift); aspect-ratio: 3 / 4;
}
.tsb-pk .tsb-split__media img{ width: 100%; height: 100%; object-fit: cover; display: block }
@media (max-width: 900px){
  /* Portraetfoto bleibt Portraet, ein 3/2-Zuschnitt kappt den Kopf. */
  .tsb-pk .tsb-split__media{ aspect-ratio: 4 / 5; max-height: 62vh }
}

/* Die Karte ist ein same-origin Leaflet-Block mit eigener Hoehe (290px),
   deshalb hier KEIN aspect-ratio erzwingen - sonst kollabiert sie. */
.tsb-pk .tsb-karte{
  border-radius: var(--r-md); overflow: hidden;
  border: var(--b-hair); box-shadow: var(--sh-card);
}
.tsb-pk .tsb-karte .ts-osm-map-holder{ border-radius: var(--r-md) }

/* ---- Zahlenband: die Belege aus dem Fliesstext holen --------------------- */
/* "30 Jahre", "10 Jahre", "DFB B-Lizenz" standen mitten in einem Absatz und
   wurden dort ueberlesen. Genau diese drei Angaben ueberzeugen Eltern. */
.tsb-pk .tsb-belege{
  display: grid; grid-template-columns: repeat(3, 1fr);
  background: var(--surface); border: var(--b-hair); border-radius: var(--r-md);
  overflow: hidden; box-shadow: var(--sh-card); margin: var(--s-6) 0 0;
}
.tsb-pk .tsb-belege > div{ padding: var(--s-5); text-align: center; border-left: var(--b-hair) }
.tsb-pk .tsb-belege > div:first-child{ border-left: 0 }
.tsb-pk .tsb-belege b{
  font-family: var(--font-head); font-size: 2.1rem; font-weight: 700;
  color: var(--ink); display: block; line-height: 1; font-variant-numeric: tabular-nums;
}
.tsb-pk .tsb-belege b.txt{ font-size: 1.5rem }
.tsb-pk .tsb-belege b span{ color: var(--accent); font-size: .5em; vertical-align: .4em }
.tsb-pk .tsb-belege small{
  font-family: var(--font-head); font-size: var(--fs-xs); letter-spacing: .06em;
  color: var(--muted); text-transform: uppercase; display: block; margin-top: var(--s-2);
}
@media (max-width: 700px){
  .tsb-pk .tsb-belege{ grid-template-columns: 1fr }
  .tsb-pk .tsb-belege > div{ border-left: 0; border-top: var(--b-hair) }
  .tsb-pk .tsb-belege > div:first-child{ border-top: 0 }
}

/* ---- Unterschrift -------------------------------------------------------- */
.tsb-pk .tsb-sig{ margin-top: var(--s-6); display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap }
.tsb-pk .tsb-sig img{ height: 52px; width: auto; display: block }
.tsb-pk .tsb-sig span{ font-size: var(--fs-sm); color: var(--muted) }

/* ---- Kontaktdaten als Kacheln ------------------------------------------- */
/* Vorher zwei kleine Zeilen mit Icon. Jetzt anklickbare Flaechen mit
   Erreichbarkeit und Anfahrt darunter. */
.tsb-pk .tsb-kdaten{
  display: flex; flex-direction: column; gap: var(--s-3);
  margin: var(--s-6) 0 0; padding: 0; list-style: none;
}
.tsb-pk .tsb-kdaten li{
  display: flex; align-items: center; gap: var(--s-4);
  background: var(--surface-alt); border: var(--b-hair);
  border-radius: var(--r-sm); padding: 14px var(--s-5);
}
.tsb-pk .tsb-kdaten .ic{
  width: 40px; height: 40px; flex: none; border-radius: var(--r-sm);
  background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center;
}
.tsb-pk .tsb-kdaten .ic svg{ width: 20px; height: 20px }
.tsb-pk .tsb-kdaten b{ font-family: var(--font-head); display: block; font-size: var(--fs-base); color: var(--ink) }
.tsb-pk .tsb-kdaten a{ color: var(--ink); text-decoration: none; font-family: var(--font-head); font-weight: 700 }
.tsb-pk .tsb-kdaten a:hover{ color: var(--accent) }
.tsb-pk .tsb-kdaten small{ color: var(--muted); font-size: var(--fs-sm); display: block }

/* ---- Formularband -------------------------------------------------------- */
/* Das Formular selbst kommt aus Abschnitt 8 (eine Quelle fuer alle CF7).
   Hier nur die Karte drumherum.

   ⚠️ Die Karte liegt auf .wpcf7, NICHT auf einem eigenen <div> aus einem
   raw-Block. Ein dort geoeffnetes <div> wird am Blockende vom Browser
   geschlossen; der CF7-Shortcode steht danach als Geschwister und die Karte
   bleibt als LEERE weisse Flaeche ueber dem Formular stehen. Genau das war
   im ersten Anlauf sichtbar - derselbe Fehler wie bei Merch und Partner. */
.tsb-band-formular .wpcf7{
  background: var(--surface); border: var(--b-hair); border-radius: var(--r-lg);
  box-shadow: var(--sh-card); padding: clamp(20px, 4vw, 40px);
  max-width: 860px; margin: 0 auto;
}
.tsb-pk .tsb-formnote{
  font-size: var(--fs-sm); color: var(--muted);
  margin: var(--s-5) auto 0; max-width: 860px; text-align: center;
}

/* Feldbeschriftungen ueber den Feldern. Der Platzhalter allein verschwindet
   beim Tippen - wer dann unterbrochen wird, weiss nicht mehr, welches Feld
   er ausfuellt. */
.tsb-band-formular .tsb-label{
  display: block; font-family: var(--font-head); font-size: var(--fs-sm);
  font-weight: 700; color: var(--ink); margin-bottom: 6px;
}
.tsb-band-formular .tsb-label span{ font-weight: 400; color: var(--muted) }

/* ---- Abschlussband ------------------------------------------------------- */
/* Ersetzt auf Kontakt das Trophy-Limette-Band (1,43:1). Die Farbe ist seit
   dem 18.07. ueberall sonst ausgemustert; auf dieser Seite hatte sie ueberlebt. */
.tsb-pk .tsb-abschluss{
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-6); flex-wrap: wrap;
}
.tsb-pk .tsb-abschluss p{ color: var(--on-dark-muted); margin-top: 6px; max-width: 52ch }
.tsb-pk .tsb-abschluss .actions{ margin-top: 0 }

/* ---- Kopfbereiche -------------------------------------------------------- */
.tsb-pk .tsb-kopf{ margin-bottom: var(--s-7) }
.tsb-pk .tsb-kopf--center{ text-align: center; max-width: var(--w-sub); margin-inline: auto }

/* Formularband auf der Kontaktseite: das Band traegt die vc_row (el_class),
   damit Kopf, CF7-Shortcode und Fuss im selben Raster stehen. Siehe die
   Begruendung bei .tsb-band-merch in Abschnitt 16. */
.tsb-band-formular{ background: var(--surface-alt); padding-top: var(--band-y); padding-bottom: var(--band-y) }
.tsb-band-formular .vc_column-inner > .wpb_wrapper{ box-sizing: border-box; max-width: var(--w-page); margin: 0 auto; padding-inline: var(--gutter) }
@media (max-width: 768px){ .tsb-band-formular{ padding-top: var(--band-y-mobile); padding-bottom: var(--band-y-mobile) } }

/* =========================================================================
   18. Buttons vereinheitlicht (18.07.2026)
   -------------------------------------------------------------------------
   Auslöser: Kundenbeschwerde „die Buttons der Formulare sehen komisch aus und
   haben einen Glow-Effekt".

   ⚠️ ES IST KEIN GLOW. Gemessen am CF7-Submit: box-shadow, filter und
   text-shadow sind in ALLEN Zuständen `none`. Was wie ein Schein aussieht,
   ist ein heller Trophy-Lime-Rand (#c8ea40) um eine dunkelgrüne Fläche:
     themes/trophy/assets/css/modules.css:4258  border: 1px solid #c1e729
     themes/trophy/assets/css/modules.css:4280  :hover border-color: #c8ea40
   Abschnitt 8 setzte im Hover nur `background` und `color`, nie `border-color`
   und nie `text-transform` - beides fiel deshalb aufs Theme zurück.
   Der Submit war dadurch auch das EINZIGE Element der Seite in Versalien.

   Bestandsaufnahme vor diesem Abschnitt: 10 verschiedene Button-Looks,
   7 Höhen (21/44/48/50/52/57/58px), 3 Radien, 2 Schriftfamilien.
   Ziel: eine Geometrie, darunter nur noch Farbvarianten.
   ========================================================================= */

/* ---- 18.1 Die gemeinsame Geometrie --------------------------------------- */
/* Referenz ist .tsb-btn: 50px, --r-sm, Titillium 700/16, keine Versalien. */
:is(.tsb, .tsb-tm, .tsb-legal, .tsb-pk) .tsb-btn,
.wpcf7 input.wpcf7-form-control.wpcf7-submit,
.wpcf7 :is(.tsb-addkind, .tsb-rmkind){
  min-height: 50px;
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-sm);
  font-family: var(--font-head);
  font-size: var(--fs-base);
  font-weight: 700;
  line-height: var(--lh-1);
  letter-spacing: var(--track-normal);
  text-transform: none;
}

/* ---- 18.2 CF7-Submit: Rand und Versalien ---------------------------------
   Selektor mit .wpcf7-form-control = (0,4,1). Das Theme kommt auf (0,3,1),
   style_dynamic.css:9/11 ebenfalls auf (0,3,1) - beide werden sicher
   geschlagen, auch wenn ein Formular später auf cf7_custom_style_3/4
   umgestellt wird (die setzen dort abweichende Polsterung). */
.wpcf7 input.wpcf7-form-control.wpcf7-submit{
  background: var(--accent-bright);
  color: var(--accent-ink);
  /* transparent statt --accent: dann ist der Submit exakt ein .tsb-btn-green.
     Der Rand war der zweite Teil des „komisch"-Eindrucks - er machte den
     Submit sichtbar anders als jeden anderen Knopf daneben. */
  border: 1.5px solid transparent;
  height: auto;              /* Theme setzt height:47px + line-height:45px */
  cursor: pointer;
  transition: background var(--t-base), color var(--t-base), transform var(--t-fast);
}
.wpcf7 input.wpcf7-form-control.wpcf7-submit:hover{
  background: var(--accent);
  color: var(--on-dark);
  /* DAS ist die Zeile, die den vermeintlichen Glow beseitigt. */
  border-color: var(--accent);
  transform: translateY(-2px);
}
.wpcf7 input.wpcf7-form-control.wpcf7-submit:focus-visible{
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* ---- 18.3 Ghost-Rand sichtbar machen -------------------------------------
   Gemessen: Rand --line #e6e9e6 gegen Weiss = 1,22:1. SC 1.4.11 verlangt 3:1
   fuer Bedienelement-Umrisse. --line-field #7d8680 = 3,75:1 existiert genau
   dafuer (Abschnitt 1) und wird schon von den Formularfeldern benutzt. */
:is(.tsb, .tsb-tm, .tsb-legal, .tsb-pk) .tsb-btn-ghost{
  border-color: var(--line-field);
}
:is(.tsb, .tsb-tm, .tsb-legal, .tsb-pk) .tsb-btn-ghost:hover{
  border-color: var(--accent);
  color: var(--accent);
}

/* ---- 18.4 Teilnehmer-Knöpfe in den Formularen ----------------------------
   Standen als ungestylte Browser-Knöpfe da: Arial 13,3px, border:2px outset,
   21px hoch - direkt neben einem 50px-Submit. */
.wpcf7 :is(.tsb-addkind, .tsb-rmkind){
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  background: var(--surface);
  color: var(--ink);
  border: 1.5px solid var(--line-field);
  cursor: pointer;
  transition: background var(--t-base), border-color var(--t-base), color var(--t-base);
}
.wpcf7 :is(.tsb-addkind, .tsb-rmkind):hover{
  border-color: var(--accent);
  color: var(--accent);
  background: var(--accent-soft);
}
.wpcf7 :is(.tsb-addkind, .tsb-rmkind):focus-visible{
  outline: 2px solid var(--focus);
  outline-offset: 3px;
}

/* ---- 18.5 Merch-Kaufknöpfe auf der STARTSEITE ----------------------------
   ⚠️ Die Startseite traegt am <body> KEINE Klasse `woocommerce-page`
   (gemessen: home wp-singular page-template-full-width … page-id-5788).
   Abschnitt 13 und 14 haengen aber genau daran - deshalb greift dort weder
   die Geometrie noch die Chevron-Abschaltung, und Abschnitt 15.10 korrigierte
   nur die Farbe. Ergebnis waren 58px hohe, eckige Versalien-Knoepfe direkt
   neben 50px-Knoepfen auf derselben Seite.
   Selektor (0,3,3) schlaegt die Theme-Kette. */
body .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart, a.add_to_cart_button){
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  height: auto;
  line-height: var(--lh-1);
  /* Das Theme setzt hier asymmetrisch 15px 40px 15px 32px - Platz fuer einen
     Chevron, den wir gleich abschalten. */
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-sm);
  font-family: var(--font-head);
  font-size: var(--fs-base);
  font-weight: 700;
  letter-spacing: var(--track-normal);
  text-transform: none;
}
/* Ohne das steht der Chevron ueber dem Text, sobald die Polsterung symmetrisch
   wird - derselbe Fehler wie am 18.07. in der Kaufstrecke. */
body .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart, a.add_to_cart_button)::after{
  content: none;
}
/* Fokusring: hier greift weder outline noch der box-shadow-Fix vom 17.07.
   Doppelring, weil ein einfacher dunkelgruener Ring gegen die hellgruene
   Flaeche nur 4,26:1 erreicht. */
body .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart, a.add_to_cart_button):focus-visible{
  outline: none;
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--accent) !important;
}

/* ---- 18.6 Produktsuche in der Shop-Sidebar -------------------------------
   Gemessen: font-size 27px. Die Farbregel steht bereits in Abschnitt 15.11,
   nur die Groesse fehlte. */
body .widget.woocommerce.widget_product_search .input-holder button{
  min-height: 50px;
  font-size: var(--fs-base);
  font-family: var(--font-head);
  font-weight: 700;
  line-height: var(--lh-1);
}

/* ---- 18.7 Hero- und Theme-Knöpfe (.mkd-btn) ------------------------------
   Diese sitzen im RevSlider. Seit dem Hero-Umbau (Vorschlag 1) sind die Texte
   und Groessen dort neu gesetzt, deshalb kann jetzt auch die Hoehe angeglichen
   werden: 58px -> 50px wie ueberall sonst.
   Die Layer sind absolut positioniert, eine Hoehenaenderung des Knopfes
   verschiebt die uebrigen Layer nicht. */
body :is(.mkd-btn.mkd-btn-solid, .mkd-btn.mkd-btn-outline){
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  height: auto;
  line-height: var(--lh-1);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-sm);
  font-size: var(--fs-base);
  letter-spacing: var(--track-normal);
  text-transform: none;
}
/* Fokusring fehlte an diesen Knoepfen komplett (outline-style:none). */
body :is(.mkd-btn.mkd-btn-solid, .mkd-btn.mkd-btn-outline):focus-visible{
  outline: none;
  box-shadow: 0 0 0 2px rgba(0,0,0,.55), 0 0 0 4px var(--accent-bright) !important;
}

/* --- 18.7a Hero-Knöpfe an .tsb-btn angleichen ------------------------------
   Gemessen war der gruene Hero-Knopf trotz gleicher Geometrie anders als jeder
   andere gruene Knopf der Seite:
     Hero   Ruhe 2px Rand #43ec6b · Hover bg -> #0a6b2e, Text -> weiss
     .tsb-btn-green  Ruhe 1px transparent · Hover NUR Anheben, Farbe bleibt
   Der Farbwechsel ist Theme-Verhalten und macht den Knopf im Hero zum
   Fremdkoerper. Hier also exakt das Verhalten von .tsb-btn-green.
   Das Theme setzt seine Hover-Farben mit !important (belegt in Abschnitt
   15.12), deshalb ist !important hier unvermeidbar. */
body .mkd-btn.mkd-btn-solid{
  border-width: 1.5px;
  border-color: transparent;
  transition: transform var(--t-fast), background var(--t-base), border-color var(--t-base);
}
body .mkd-btn.mkd-btn-solid:hover{
  background-color: var(--accent-bright) !important;
  color: var(--accent-ink) !important;
  border-color: transparent !important;
  transform: translateY(-2px);
}

/* Der zweite Hero-Knopf hatte GAR KEINEN Hover (gemessen: keine einzige
   Eigenschaft aendert sich) und einen Rand in #ededec, der auf dem Bild
   praktisch unsichtbar ist.
   Er steht auf einem Foto, nicht auf Weiss - die helle .tsb-btn-ghost-Variante
   waere hier falsch. Stattdessen die Fassung fuer dunklen Grund: sichtbarer
   heller Rand, beim Zeigen fuellt sich die Flaeche leicht. */
body .mkd-btn.mkd-btn-outline{
  background-color: rgba(255, 255, 255, .08);
  border-width: 1.5px;
  border-color: rgba(255, 255, 255, .55) !important;
  color: var(--on-dark) !important;
  transition: transform var(--t-fast), background-color var(--t-base), border-color var(--t-base);
}
body .mkd-btn.mkd-btn-outline:hover{
  background-color: rgba(255, 255, 255, .18) !important;
  border-color: #fff !important;
  color: var(--on-dark) !important;
  transform: translateY(-2px);
}

/* ---- 18.8 Letzter Feinschliff (nachgemessen) -----------------------------
   Nach 18.1-18.7 waren 31 von 35 Knoepfen identisch. Diese drei Reste
   ergaben sich erst aus der Messung: */

/* Der Rahmen wurde AUSSERHALB gerechnet - aus min-height 50px wurden 52px. */
body :is(.mkd-btn.mkd-btn-solid, .mkd-btn.mkd-btn-outline),
.wpcf7 input.wpcf7-form-control.wpcf7-submit,
body .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart, a.add_to_cart_button){
  box-sizing: border-box;
}

/* Suchknopf in der Shop-Sidebar: eckig statt --r-sm. */
body .widget.woocommerce.widget_product_search .input-holder button{
  box-sizing: border-box;
  border-radius: var(--r-sm);
}

/* "Zurueck zum Shop" im Warenkorb blieb bei 48px. */
body.woocommerce-page .mkd-content :is(a.button.wc-backward, a.button.wc-forward){
  box-sizing: border-box;
  min-height: 50px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ============================================================================
   29. Finale Design-Abnahme (18.07.2026)  [TSB-BLOCK:abnahme-final] - B2 Cookie, K1 Kaufstrecke, K5 BSA
   Rein additiv. Rollback = diesen Abschnitt entfernen.
   ============================================================================ */

/* --- B2: DSGVO-Cookie-Hinweis als saubere Bodenleiste -----------------------
   Behebt: (1) Ueberlauf mobil (fehlendes box-sizing -> 100%+padding = >Viewport),
   (2) graue ungestylte System-Buttons, (3) schwebt 25px ueber dem Boden.
   Der Plugin-Container traegt Inline-Styles (background/bottom/Button-Farben),
   daher ist !important hier unvermeidlich. */
#fhw_cookiehinweis{
  box-sizing:border-box;
  left:0 !important; right:0 !important; bottom:0 !important;
  width:100% !important; max-width:100% !important;
  padding:var(--s-3) clamp(16px,4vw,32px) !important;
  column-gap:var(--s-5); row-gap:var(--s-3);
  background:var(--surface) !important;
  border-top:1px solid var(--line);
  box-shadow:0 -6px 24px -12px rgba(20,22,21,.28);
}
#fhw_cookiehinweis *{box-sizing:border-box;}
#fhw_cookiehinweis p{
  color:var(--ink-body) !important;
  font-size:var(--fs-sm) !important;
  line-height:var(--lh-base) !important;
}
#fhw_cookiehinweis .mainbutton,
#fhw_cookiehinweis .privacybutton{
  margin:0 !important;
  min-height:44px;
  padding:10px 22px !important;
  border:1.5px solid transparent !important;
  border-radius:var(--r-sm) !important;
  font-family:var(--font-head) !important;
  font-weight:700 !important;
  font-size:var(--fs-sm) !important;
  line-height:var(--lh-1) !important;
  white-space:nowrap;
  cursor:pointer;
  transition:transform var(--t-base),background var(--t-base);
}
#fhw_cookiehinweis .mainbutton{
  background:var(--accent) !important;
  color:var(--on-dark) !important;
}
#fhw_cookiehinweis .mainbutton:hover{transform:translateY(-2px);}
#fhw_cookiehinweis .privacybutton{
  background:transparent !important;
  color:var(--accent) !important;
  border-color:var(--line-field) !important;
}
#fhw_cookiehinweis .privacybutton:hover{background:var(--line) !important;}
#fhw_cookiehinweis form{margin:0 !important;}

/* --- K1: Merch / Kaufstrecke Feinschliff ------------------------------------ */
/* Veraltete Theme-Social-Share-Leiste auf Produkten entfernen (alter Twitter-Vogel) */
.mkd-woo-social-share-holder{display:none !important;}
/* Warenkorb-Summe von "loser Flaeche" zu einer ruhigen Karte machen */
.woocommerce .cart-collaterals .cart_totals{
  border:1px solid var(--line);
  border-radius:var(--r-sm);
  padding:var(--s-5) var(--s-6);
  background:var(--surface);
}
.woocommerce .cart-collaterals .cart_totals > h2{margin-top:0;}
/* Produkt-Tab-Panel als ruhige Karte statt schlichter Rahmenbox */
.woocommerce div.product .woocommerce-tabs .woocommerce-Tabs-panel{
  border:1px solid var(--line);
  border-radius:var(--r-sm);
  background:var(--surface);
  padding:var(--s-5) var(--s-6);
  margin-top:var(--s-4);
}

/* --- K5: BSA - fuenfte Vorteil-Karte nicht mehr einsam links --------------- */
/* Reihen zentrieren, damit die 5. Karte mittig unter den vier sitzt */
body.page-id-527 .hl{
  grid-template-columns:repeat(auto-fit,minmax(200px,232px));
  justify-content:center;
}

/* --- Startseite-Befund (Kunde 18.07.): Schrittkette symmetrisch zentrieren -----
   Die Kette stand zwar mittig, aber Nummer/Text linksbuendig je Spalte -> der
   Inhalt wirkte gegenueber der zentrierten Ueberschrift nach links verschoben.
   Jetzt Nummer + Text mittig, Verbindungslinie als Segment zwischen den Nummern.
   Nur Desktop; die Mobile-Query (<768) behaelt die vertikale Variante. */
@media (min-width:768px){
  .tsb .tsb-flow-step{ text-align:center; padding-right:0; }
  .tsb .tsb-flow-top{ justify-content:center; position:relative; }
  .tsb .tsb-flow-n{ box-shadow:none; }
  .tsb .tsb-flow-line{
    position:absolute; top:24px; transform:translateY(-50%);
    left:calc(50% + 34px); right:calc(-50% + 34px);
    width:auto; height:3px; margin:0;
  }
  .tsb .tsb-flow-step:last-child .tsb-flow-line{ display:none; }
  .tsb .tsb-flow p{ margin-left:auto; margin-right:auto; }
}

/* K5 Nachbesserung: CSS-Grid zentriert unvollstaendige Reihen NICHT -> Flexbox,
   damit die einzelne 5. Karte mittig unter den vier sitzt. */
body.page-id-527 .hl{ display:flex; flex-wrap:wrap; justify-content:center; }
body.page-id-527 .hl .i{ flex:1 1 200px; max-width:236px; }

/* --- W7: Start-Hero-Subline lesbarer auf hellem Slider-Bild ------------------
   Kraeftiger dunkler Textschatten nur auf die drei Text-Layer (Headline, Kicker,
   Subline) von Slide 6; die Button-Layer (8,9) bleiben unberuehrt. */
#slider-1-slide-6-layer-6,
#slider-1-slide-6-layer-7,
#slider-1-slide-6-layer-10{
  text-shadow:0 2px 12px rgba(20,22,21,.92), 0 1px 3px rgba(20,22,21,.9) !important;
}

/* ------------------------------- 28. Elternstimmen (Kundenfeedback ab 18.07.2026)  [TSB-BLOCK:elternstimmen-basis] */
/*
   Bis 18.07. gab es auf 33 Seiten keinen einzigen Erfahrungsbericht - laut Textpruefung
   die groesste Luecke ueberhaupt. Diese Komponente traegt die Stimmen.
   Bewusst KEIN Sternchen-Rating: drei echte Zitate mit Name, Alter und Verein wirken
   staerker als anonyme Sterne, und es gibt keine erfundenen Bewertungen zu pflegen.
*/
.tsb-voice{
  max-width: 62ch;
  margin-inline: auto;
  padding-top: var(--s-2); padding-bottom: var(--s-2);
  padding-left: var(--s-6); padding-right: var(--s-4);
  position: relative;
}
/* Akzentbalken statt dekorativem Anfuehrungszeichen.
   Grund: Das Glyph „ sitzt auf der Grundlinie und ist relativ zur Schriftgroesse
   winzig - bei 70px wirkte es wie ein Artefakt auf halber Zitathoehe statt wie
   Dekoration. Der Balken ist ruhiger, skaliert mit und passt zu den uebrigen
   Akzentlinien des Systems. */
.tsb-voice::before{
  content: "";
  position: absolute;
  left: 0; top: .35em; bottom: .35em;
  width: 3px;
  border-radius: 2px;
  background: var(--accent);
  opacity: .55;
}
.tsb-voice blockquote{
  margin: 0;
  border: 0;                       /* Theme setzt sonst einen grauen Balken */
  padding: 0;
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-relaxed, 1.7);
  color: var(--ink);
  font-style: normal;              /* Theme kursiviert Zitate, das liest sich schlechter */
}
.tsb-voice figcaption{
  margin-top: var(--s-3);
  font-family: var(--font-head);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: var(--track-wide, .02em);
  color: var(--muted);
}
.tsb-voice figcaption b{ color: var(--ink); font-weight: 700 }

/* Mehrere Stimmen nebeneinander, sobald weitere dazukommen */
.tsb-voices{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 26rem), 1fr));
  gap: var(--s-6);
  align-items: start;
}
.tsb-voices .tsb-voice{ margin-inline: 0 }

@media (max-width: 600px){
  .tsb-voice{ padding-left: var(--s-4) }
}

/* ============================================================================
   19. Buttonfarbe: Primaerbuttons im Ruhezustand DUNKEL (Kundenentscheidung 18.07.)
   Kehrt das bisherige Muster um -> Ruhe var(--accent) #0a6b2e + weiss,
   Hover var(--accent-bright) #43ec6b + var(--accent-ink). Gilt fuer ALLE
   Primaerbuttons, auf hellen wie dunklen Flaechen (konsistent, Kundenwunsch).
   Akzente (Badges .badge/.chip/.pack .badge, Haekchen, Kicker, Menue-Unterstrich,
   Warenkorb-Zaehler, Legal-Linie .acc, Stempel) sind NICHT gelistet und bleiben hell.
   Steht am Dateiende -> schlaegt bei gleicher Spezifitaet die Originalregel.
   Neben-Aktionen (Warenkorb aktualisieren / Gutschein anwenden) bleiben Ghost.
   ============================================================================ */

/* --- 19.1 .tsb-btn-green (Seiten-CTAs, Login-Buttons) --- */
:is(.tsb,.tsb-tm,.tsb-legal,.tsb-pk) .tsb-btn-green{
  background: var(--accent); color: var(--on-dark); border-color: var(--accent);
}
:is(.tsb,.tsb-tm,.tsb-legal,.tsb-pk) .tsb-btn-green:hover{
  background: var(--accent-bright); color: var(--accent-ink); border-color: var(--accent-bright);
}

/* --- 19.2 CF7-Submit (beide Regelstufen: 0,3,1 und 0,4,1) --- */
.wpcf7 input.wpcf7-submit,
.wpcf7 input.wpcf7-form-control.wpcf7-submit{
  background: var(--accent); color: var(--on-dark); border-color: var(--accent);
}
.wpcf7 input.wpcf7-submit:hover,
.wpcf7 input.wpcf7-form-control.wpcf7-submit:hover{
  background: var(--accent-bright); color: var(--accent-ink); border-color: var(--accent-bright);
}

/* --- 19.3 Startseiten-/Hero-CTAs (.mkd-btn-solid) --- */
body .mkd-btn.mkd-btn-solid{
  background-color: var(--accent); border-color: var(--accent); color: var(--on-dark);
}
/* Hover-Kette des Themes spiegeln; Hero-Hover-Original traegt !important (Abschnitt 18.7a). */
body .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-bg):hover,
body .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-hover-bg):hover,
body .mkd-btn.mkd-btn-solid:not(.mkd-btn-custom-border-hover):hover{
  background-color: var(--accent-bright) !important;
  border-color: var(--accent-bright) !important;
  color: var(--accent-ink) !important;
}

/* --- 19.4 WooCommerce-Kaufstrecke (Primaeraktionen) ---
   update_cart / apply_coupon bleiben Ghost -> ausgeschlossen. */
body.woocommerce-page .mkd-content :is(
  a.button, button.button, input.button, a.checkout-button,
  button[type="submit"], input[type="submit"],
  .woocommerce-button, a.added_to_cart
){
  background: var(--accent); color: var(--on-dark); border-color: var(--accent);
}
body.woocommerce-page .mkd-content :is(
  a.button, button.button, input.button, a.checkout-button,
  button[type="submit"], input[type="submit"],
  .woocommerce-button, a.added_to_cart
):hover{
  background: var(--accent-bright); color: var(--accent-ink); border-color: var(--accent-bright);
}

/* --- 19.5 "Warenkorb anzeigen" (a.button.wc-forward in der Hinzugefuegt-Meldung) --- */
body.woocommerce-page .mkd-content a.button.wc-forward:not(.added_to_cart){
  background: var(--accent); color: var(--on-dark);
}
body.woocommerce-page .mkd-content a.button.wc-forward:not(.added_to_cart):hover{
  background: var(--accent-bright); color: var(--accent-ink);
}

/* --- 19.6 Shop-/Merch-Produktkacheln (Ruhe + beide Hover-Aeste 15.6/15.10 spiegeln) --- */
body .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart){
  background-color: var(--accent); color: var(--on-dark);
}
body.woocommerce ul.products > li.product .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart):hover,
body.woocommerce-page ul.products > li.product .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart):hover,
body ul.products > li.product .mkd-pl-inner .mkd-pl-text-inner :is(a.button, a.added_to_cart):hover{
  background-color: var(--accent-bright); color: var(--accent-ink);
}

/* --- 19.7 Neben-Aktionen (Warenkorb aktualisieren / Gutschein anwenden) bleiben Ghost.
   Sie tragen die Klasse .button und wurden daher von 19.4 (button.button) miterfasst.
   Diese Regel steht NACH 19.4 und stellt den Ghost-Look wieder her. */
body.woocommerce-page .mkd-content :is(
  button[name="update_cart"], input[name="update_cart"],
  button[name="apply_coupon"], input[name="apply_coupon"]
){
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
body.woocommerce-page .mkd-content :is(
  button[name="update_cart"], input[name="update_cart"],
  button[name="apply_coupon"], input[name="apply_coupon"]
):hover{
  background: var(--surface-alt); color: var(--ink); border-color: var(--line-field);
}

/* =========================================================================
   20. Kaufstrecken-Formulare: Raster, Beschriftungen, Fehler, Meldungen
   (Kundenmeldung 18.07.: "Rechnungsdaten sieht kaputt aus", "Validierungs-
   fehler werden nicht ordentlich angezeigt", "Warenkorb-anzeigen-Button:
   Text ungestylt und haengt oben am Button")

   BEFUND 1 — DIE FELDER STEHEN AUF FLOATS, DIE NIEMAND CLEART.
   Gemessen auf /kasse/: ALLE 11 .form-row im Rechnungsblock haben
   float:left / clear:none — auch die .form-row-wide, die bei WooCommerce
   normalerweise clear:both traegt. Folge: .woocommerce-billing-fields
   kollabiert auf die Hoehe der H3 (gemessen 31px bei 915px Inhalt), und der
   nachfolgende Guthaben-Hinweis beginnt mit seiner Flaeche direkt unter der
   Ueberschrift, waehrend sein Text an den Floats vorbei nach unten rutscht.
   Sichtbar wird das als grosse gruene Flaeche HINTER allen Feldern.
   Deshalb hier Raster statt Floats: das Problem kann so nicht wiederkehren.

   BEFUND 2 — Beschriftungen fielen aufs Theme zurueck (Titillium 15px),
   waehrend die Felder darunter laengst Lato 16px tragen. Sie folgen jetzt
   exakt der CF7-Regel aus Abschnitt 6, damit Kasse und Formulare gleich lesen.

   BEFUND 3 — .woocommerce-error war voellig ungestylt: kein Rahmen, keine
   Signalfarbe, list-style:disc, Titillium 15px. Der Fehler las sich wie
   Fliesstext. Zusaetzlich blieb der Rand der beanstandeten Felder auf
   --line-field, obwohl WooCommerce sie mit .woocommerce-invalid markiert —
   der Kunde sah also nicht, WELCHES Feld gemeint war.
   ========================================================================= */

/* --- 20.1 Feldraster statt Floats ---------------------------------------- */
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm){
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--s-4);
  row-gap: var(--s-5);
}
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .form-row{
  float: none !important;      /* woocommerce.min.css setzt float:left ohne clear */
  width: auto !important;
  margin: 0;
  padding: 0;
  grid-column: 1 / -1;         /* Standard: volle Breite */
}
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .form-row-first{ grid-column: 1 }
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .form-row-last{ grid-column: 2 }

@media (max-width: 768px){
  body.woocommerce-page .mkd-content :is(
    .woocommerce-billing-fields__field-wrapper,
    .woocommerce-shipping-fields__field-wrapper,
    .woocommerce-additional-fields__field-wrapper,
    .woocommerce-address-fields__field-wrapper,
    .woocommerce-EditAccountForm){ grid-template-columns: 1fr }
  body.woocommerce-page .mkd-content :is(
    .woocommerce-billing-fields__field-wrapper,
    .woocommerce-shipping-fields__field-wrapper,
    .woocommerce-additional-fields__field-wrapper,
    .woocommerce-address-fields__field-wrapper,
    .woocommerce-EditAccountForm) > :is(.form-row-first, .form-row-last){
    grid-column: 1 / -1;
  }
}

/* Die Bloecke selbst duerfen nicht mehr kollabieren (Guthaben-Hinweis!) */
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields,
  .woocommerce-shipping-fields,
  .woocommerce-additional-fields){ display: flow-root }

/* --- 20.2 Beschriftungen wie im uebrigen Formularbestand ------------------
   Ausgenommen bleiben die Checkbox-Beschriftungen (AGB, Konto anlegen,
   Lieferadresse): sie stehen NEBEN der Box, tragen Links und duerfen weder
   umbrechen noch in Versalien stehen. */
body.woocommerce-page .mkd-content :is(form.checkout, .woocommerce-address-fields, .woocommerce-EditAccountForm)
  .form-row > label:not(.checkbox):not(.woocommerce-form__label){
  display: block;
  font: 700 var(--fs-xs)/var(--lh-flat) var(--font-head);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--s-3);
}
body.woocommerce-page .mkd-content .form-row label .required{
  color: var(--error); text-decoration: none; border: 0;
}

/* --- 20.3 Validierungsfehler sichtbar machen ------------------------------ */
/* a) Das beanstandete Feld faerbt seinen Rand. Theme-Regel traegt eine hohe
      Spezifitaet und wird beim Tippen von WooCommerce-JS neu gesetzt →
      hier ist !important nicht vermeidbar. */
body.woocommerce-page .mkd-content .form-row.woocommerce-invalid
  :is(input.input-text, select, textarea.input-text){
  border-color: var(--error) !important;
}
/*    Der Scope aus 20.2 muss gespiegelt werden: ohne ihn ist diese Regel
      (0,6,2) und verliert gegen die Beschriftungsregel darueber (0,7,2) —
      gemessen, die Beschriftung blieb grau statt rot. */
body.woocommerce-page .mkd-content :is(form.checkout, .woocommerce-address-fields, .woocommerce-EditAccountForm)
  .form-row.woocommerce-invalid > label:not(.checkbox):not(.woocommerce-form__label){
  color: var(--error);
}

/* b) Die Sammelmeldung oben liest sich jetzt als Fehler, nicht als Fliesstext */
body.woocommerce-page .mkd-content ul.woocommerce-error{
  list-style: none;
  margin: 0 0 var(--s-6);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-left: var(--s-6);
  padding-right: var(--s-6);
  background: var(--surface-alt);
  border: 1px solid var(--error);
  border-left-width: 3px;
  border-radius: var(--r-sm);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink);
}
body.woocommerce-page .mkd-content ul.woocommerce-error::before{ content: none }
body.woocommerce-page .mkd-content ul.woocommerce-error li{
  margin: 0; padding: 0; list-style: none;
}
body.woocommerce-page .mkd-content ul.woocommerce-error li + li{ margin-top: var(--s-2) }
body.woocommerce-page .mkd-content ul.woocommerce-error li::before{ content: none }
body.woocommerce-page .mkd-content ul.woocommerce-error strong{ color: inherit; font-weight: 700 }

/*    ⚠️ DER ANKER IN JEDEM EINTRAG FLOATET RECHTS (gemessen: float:right am
      <a>, nicht am <li>). Folge: die sieben <li> hatten Hoehe 0 und lagen alle
      auf derselben y-Koordinate, die Meldungen liefen als eine zusammenhaengende
      Zeile — und zwar in UMGEKEHRTER Reihenfolge zu den Feldern (die Postleitzahl
      stand vorn, der Vorname hinten). Am <li> war nichts zu sehen: dort meldet
      der Browser brav display:list-item und float:none. */
/*    Die :not()-Kette muss mit, sonst faerbt die Linkregel aus Abschnitt 13
      (body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart),
      also 0,5,2) die Meldung gruen — sie liest sich dann wie ein Link, nicht
      wie ein Fehler. Mit der Kette ist diese Regel 0,5,4 und gewinnt. */
body.woocommerce-page .mkd-content ul.woocommerce-error li
  > a:not(.button):not(.added_to_cart){
  float: none !important;
  display: block;
  width: auto;
  color: inherit;
  text-decoration: none;
}
body.woocommerce-page .mkd-content ul.woocommerce-error li > a:hover{
  color: var(--error); text-decoration: underline;
}

/* c) Die feldnahe Meldung, die WooCommerce unter das Feld schreibt */
body.woocommerce-page .mkd-content .form-row p.checkout-inline-error-message{
  margin: var(--s-2) 0 0;
  color: var(--error);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
}

/* --- 20.4 Meldungszeile: Text und Knopf auf einer Achse -------------------
   Der Knopf stand auf float:right, der Meldungstext blieb dadurch oben an
   der Oberkante haengen (gemessen: Meldung y=278, Knopf y=300). Eine Zeile
   loest das, ohne dass eine Hoehe geraten werden muss. */
body.woocommerce-page .mkd-content :is(.woocommerce-message, .woocommerce-info){
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}
body.woocommerce-page .mkd-content :is(.woocommerce-message, .woocommerce-info) > a.button{
  float: none !important;
  margin: 0 0 0 auto;
  flex: 0 0 auto;
}
/*    Geometrie und Schriftschnitt brauchen die volle :not()-Kette des Themes.
      Gemessen ohne sie: die Theme-Regel
        .woocommerce-page .mkd-content .wc-forward:not(.added_to_cart):not(.checkout-button)
      ist (0,6,0) und haelt font-weight:500; die eigene Regel aus Abschnitt 13
      haelt mit (0,5,1) min-height:48px. Der Knopf blieb dadurch 48px/500,
      waehrend alle uebrigen 50px/700 sind. */
body.woocommerce-page .mkd-content :is(.woocommerce-message, .woocommerce-info)
  > a.button.wc-forward:not(.added_to_cart):not(.checkout-button){
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: auto;
  min-height: 50px;            /* Hoehe aller uebrigen Knoepfe (Abschnitt 18) */
  padding-top: 0;
  padding-bottom: 0;
  padding-left: var(--s-5);
  padding-right: var(--s-5);
  font-weight: 700;
  line-height: 1;
}

/* === Abschnitt 20: Stornohinweis auf Angebots-/Anfrageseiten (Tagescamp, BSA, Kindergeburtstag) ===
   Dezenter Hinweisblock im Anfrage-Abschnitt. Wortlaut folgt AGB Paragraf 7. */
.tsb .tsb-storno{display:flex;gap:12px;align-items:flex-start;max-width:64ch;margin-top:22px;margin-bottom:0;padding:16px 18px;background:var(--alt);border:1px solid var(--line);border-radius:14px}
.tsb .tsb-storno svg{flex:0 0 auto;width:20px;height:20px;margin-top:1px;color:var(--accent)}
.tsb .tsb-storno p{margin:0;font-family:'Lato',sans-serif;font-size:.86rem;line-height:1.5;color:var(--muted)}
.tsb .tsb-storno strong{color:var(--ink-body);font-weight:700}

/* ===========================================================================
 * 21. Ueberschriften-Struktur (Massnahmenliste Abschnitt 5.1 + 5.2)
 * Gegenstueck zu tsb-ui-tweaks.php Abschnitt 7. Die Optik bleibt unveraendert
 * (Kundenentscheidung 18.07.), es aendern sich nur die Tags.
 * =========================================================================== */

/* 21.1 Der Produktname ist jetzt die H1 (war eine H2).
 * Ohne diese Zeile griffe die globale Regel h1{font-size:60px} aus
 * modules.min.css. Gemessener Bestandswert der bisherigen h2: 36px, und zwar
 * konstant auf 1440/1200/1024/768/480/390px - deshalb ein fester Wert und
 * kein Token: --fs-2xl ist ein clamp() und wuerde mobil kleiner ausfallen.
 * Zeilenhoehe, Abstand und Farbe kommen weiterhin aus der Klassenregel bzw.
 * der Tag-Regel h1..h6 und stimmen ohne Zutun. */
.mkd-woo-single-page .mkd-single-product-summary h1.mkd-single-product-title{ font-size: 36px }

/* 21.2 Die Ueberschrift im Titelbereich ist auf Produktseiten ein Absatz.
 * Statische Basis, gespiegelt von '.mkd-title .mkd-title-holder h1'
 * (modules.min.css). Farbe, Groesse und Transform liefert tsb-ui-tweaks.php
 * als Inline-Style aus denselben Theme-Optionen, aus denen das Theme seine
 * eigene Regel erzeugt - so bleibt beides synchron. */
.mkd-title .mkd-title-holder .tsb-title-h1{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.2em;
  display: inline-block;
  vertical-align: middle;
  margin: 0;
}
.mkd-title .mkd-title-holder .tsb-title-h1 span{ display: inline-block }

/* ========================================================================== *
 * 22. W5 — die 3er-Kreis-Kette ist nicht mehr an die Startseite gebunden.
 *
 * Abschnitt 16 hatte "--3" auf .tsb-start gescoped, weil es dort entstand.
 * Die Termine-Seite nutzt dieselbe Kette, also gilt es jetzt fuer jeden
 * .tsb-Scope. Die Werte sind zeichengleich zu den .tsb-start-Regeln; steht
 * spaeter in der Datei und gewinnt damit bei Gleichstand mit gleichem Wert.
 * ========================================================================== */

.tsb .tsb-flow--3{ grid-template-columns: repeat(3, 1fr) }

@media (max-width: 1024px){
  .tsb .tsb-flow--3{ grid-template-columns: 1fr; gap: var(--s-5) }
  /* Die Verbindungslinie ergibt untereinander keinen Sinn mehr. */
  .tsb .tsb-flow--3 .tsb-flow-line{ display: none }
  .tsb .tsb-flow--3 .tsb-flow-step{ padding-right: 0 }
}

/* ========================================================================== *
 * 23. K4 — der Kauf-Button im Shop-Raster ist dauerhaft sichtbar.
 *
 * Vorher: das Theme legt .mkd-pl-text als Ueberlagerung mit opacity 0 ueber
 * das Foto und blendet sie nur bei :hover ein. Gemessen auf 1440 und 390px:
 *   - Ruhezustand opacity 0, also auf Touch-Geraeten NIE erreichbar
 *   - der Tastaturfokus landet auf einem unsichtbaren Knopf (SC 2.4.7)
 *   - ein Klick in die Buttonmitte traf a.woocommerce-LoopProduct-link,
 *     der als 295x295-Flaeche darueber liegt und im DOM spaeter kommt
 *
 * Nachher: Foto -> Name/Preis -> Button, immer sichtbar, auf jedem Geraet.
 * Das folgt der Entscheidung vom Startseiten-Umbau: Inhalt dauerhaft sichtbar,
 * Hover bewegt nur noch.
 *
 * ACHTUNG, drei Dinge haengen zusammen und duerfen nicht einzeln geaendert
 * werden (jedes fuer sich erzeugt einen neuen Fehler):
 *  a) .mkd-pl-inner wird display:contents, damit seine Kinder Raster-Felder von
 *     li.product werden und hinter Name/Preis rutschen koennen.
 *  b) Damit verliert .mkd-pl-inner seine Box — und mit ihr BEIDES:
 *     das overflow:hidden (das den Bild-Zoom klippt) und den
 *     Positionierungskontext des Produktlinks. Ersatz steht unten.
 *  c) :hover auf einem display:contents-Element greift nicht mehr
 *     (keine Box = nichts zu ueberfahren) -> der Zoom haengt jetzt an li.
 * ========================================================================== */

/* Raster statt Flex, weil der Produktlink dadurch OHNE Rechnerei genau auf dem
   Foto liegt: beide bekommen dieselbe Rasterzelle. Der erste Anlauf hatte ihn
   absolut positioniert und per aspect-ratio quadratisch gemacht — das rechnete
   auf die Kachelbreite (329px) statt auf die Bildbreite (295px), weil li ein
   padding von 0 17px hat, und ragte dadurch 19px ueber den Produktnamen. */
.woocommerce ul.products > li.product{
  display: grid;
  grid-template-columns: 1fr;
  /* Traegt jetzt den Reihenabstand, den vorher der Text-Wrapper trug (s.u.). */
  margin-bottom: var(--s-7);
}

/* (a) Die Huelle aufloesen, damit ihre Kinder Rasterfelder werden. */
.woocommerce ul.products > li.product .mkd-pl-inner{ display: contents }

.woocommerce ul.products > li.product .mkd-pl-image{ grid-column: 1; grid-row: 1 }
.woocommerce ul.products > li.product .mkd-pl-text-wrapper{ grid-column: 1; grid-row: 2 }
.woocommerce ul.products > li.product .mkd-pl-text{ grid-column: 1; grid-row: 3 }

/* (b1) Ersatz fuer das verlorene overflow:hidden. Der Zoom lief bisher auf
   .mkd-pl-image selbst — ein Element kann sich nicht selbst klippen, also
   zoomt jetzt das Bild darin. */
.woocommerce ul.products > li.product .mkd-pl-image{
  overflow: hidden;
}
.woocommerce ul.products > li.product:hover .mkd-pl-image{
  transform: none;
}
.woocommerce ul.products > li.product .mkd-pl-image img{
  transition: transform .35s cubic-bezier(.48,1,.48,1);
}
.woocommerce ul.products > li.product:hover .mkd-pl-image img{
  transform: scale(1.06);
}

/* (b2) Ersatz fuer den verlorenen Positionierungskontext. Ohne diese Regel
   spannt sich der Produktlink ueber die GANZE Kachel und deckt den neuen
   Button wieder zu — derselbe Fehler in neuer Form. Er bekommt deshalb
   dieselbe Rasterzelle wie das Foto und deckt damit exakt dessen Flaeche,
   ohne dass irgendwo eine Groesse nachgerechnet werden muss. */
.woocommerce ul.products > li.product > .mkd-pl-inner > a.woocommerce-LoopProduct-link{
  grid-column: 1;
  grid-row: 1;
  position: static;
  width: auto;
  height: auto;
}

/* (c) Die Ueberlagerung wird zur normalen Zeile unter der Kachel. */
.woocommerce ul.products > li.product .mkd-pl-text{
  position: static;
  opacity: 1;
  background: none;
  padding: 0;
  height: auto;
  transition: none;
}
.woocommerce ul.products > li.product .mkd-pl-text-outer,
.woocommerce ul.products > li.product .mkd-pl-text-inner{
  display: block;
  height: auto;
  width: auto;
  text-align: left;
}

/* Der Button hob sich bisher aus der Ueberlagerung heraus (translate3d 50%)
   und war mittig zentriert. Jetzt sitzt er als volle Zeile unter dem Preis. */
.woocommerce ul.products > li.product .mkd-pl-text-inner .button,
.woocommerce ul.products > li.product .mkd-pl-text-inner .added_to_cart{
  transform: none;
  transition: background-color .2s ease-in-out, color .2s ease-in-out;
  display: block;
  width: 100%;
  text-align: center;
  margin-top: var(--s-3);
}
/* Nach dem Ajax-Kauf steht "Warenkorb ansehen" als zweite Zeile darunter. */
.woocommerce ul.products > li.product .mkd-pl-text-inner .added_to_cart{
  margin-top: var(--s-2);
}

/* Der Wrapper trug margin: 15px 0 30px. Die 30px waren der Abstand zur naechsten
   Kachelreihe — seit der Button darunter steht, sassen sie ZWISCHEN Preis und
   Button: 42px Luft oben, aber nur 10px zur naechsten Kachel. Der Button las sich
   dadurch wie der des Produkts darunter (im Screenshot sofort zu sehen, in den
   Messwerten nicht). Der Reihenabstand wandert deshalb ans li (oben). */
.woocommerce ul.products > li.product .mkd-pl-text-wrapper{
  margin-bottom: 0;
}






/* ============================================================================
   30. INSTAGRAM-FEED (.tsb-insta)  [TSB-BLOCK:instagram] — Seite "Aktuelles"
   Gehoert zum mu-plugin tsb-instagram. Das Plugin gibt nur HTML aus, alles
   Sichtbare steht hier (Regel: eine Designentscheidung kostet eine Stelle).

   Lehren, die hier eingebaut sind:
   - C2: nichts Wichtiges nur bei :hover zeigen. Bildunterschrift und Datum stehen
     DAUERHAFT unter dem Bild - als Hover-Overlay waeren sie mobil unerreichbar.
     Hover bewegt nur das Foto, die Randfarbe wechselt auch bei Tastaturfokus.
   - Rasterzellen schrumpfen nicht unter ihren Inhalt: darum minmax(0,1fr) UND
     min-width:0 - sonst sprengt ein 640px-Bild oder ein langes Wort die Spalte.
   - Reservierte Hoehen in em/eigener Zeilenzahl, nie in fremden Tokens
     nachgerechnet: sonst laufen Clamp und Hoehe beim naechsten Breakpoint
     still auseinander, und die Kacheln werden wieder ungleich hoch.
   ============================================================================ */

.tsb-insta{
  padding-top: var(--band-y);
  padding-bottom: var(--band-y);
}

.tsb-insta .tsb-insta-intro{
  font-size: var(--fs-md);
  line-height: var(--lh-loose);
  color: var(--ink-body);
  max-width: var(--w-read);   /* war 60ch — das ist --w-read (62ch), Faktor 1,03 = ein Token */
  margin: 0 0 var(--s-6);
}

/* --- 30.1 Raster ---------------------------------------------------------
   Nur EIN Spaltenwechsel (3 -> 2 bei 768px), damit die Kachel ueber alle Breiten
   monoton schrumpft. Mit dem frueheren Wechsel bei 1024px wurde die Kachel beim
   VERKLEINERN des Fensters groesser (1200px/3 Spalten = ~350px gegen
   1024px/2 Spalten = 372px) — das las sich als Fehler. */
.tsb-insta-grid{
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tsb-insta-kachel{
  margin: 0;
  padding: 0;
  list-style: none;
  /* Zwingend: Rasterzellen haben min-width:auto und schrumpfen sonst NICHT unter die
     Eigenbreite ihres Inhalts. Das gespiegelte Bild bringt 640px mit und sprengte damit
     bei 360px Viewport das Raster um 107px nach rechts (gemessen, nicht vermutet).
     minmax(0,1fr) oben deckt denselben Fall fuer lange Woerter und URLs ab. */
  min-width: 0;
}

/* --- 30.2 Die Kachel -----------------------------------------------------
   Kein Schatten im Ruhezustand: neun Karten mit Schatten erzeugen auf Weiss eine
   graue Suppe und lenken auf die Kanten statt auf die Fotos. Das Foto IST die Karte,
   der Haarstrich haelt nur die Reihe zusammen, wenn ein Bild hell auslaeuft. */
.tsb-insta-link{
  display: flex;
  flex-direction: column;
  text-decoration: none;
  color: var(--ink-body);
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-md);
  overflow: hidden;            /* haelt den Bild-Zoom in der Kachel */
  height: 100%;
  transition: border-color var(--t-base);
}

/* Randfarbe statt Schatten: erscheint bei Maus UND Tastatur, also in jedem
   Eingabemodus. Der Zoom darunter ist Zugabe fuer die Maus und traegt keine Information. */
.tsb-insta-link:hover,
.tsb-insta-link:focus-visible{
  border-color: var(--accent);
}

/* PFLICHT, kein Feinschliff: Abschnitt 7 setzt border-radius:2px auf JEDES fokussierte
   Element. Spezifitaet :is(a,…):focus-visible (0,1,1) schlaegt .tsb-insta-link (0,1,0),
   dadurch klappten die Ecken beim Tastaturfokus von 14px auf 2px zusammen — und
   overflow:hidden schnitt das Foto sichtbar mit. Nur der Radius wird zurueckgeholt,
   der Fokusring selbst bleibt site-weit unveraendert. */
.tsb-insta-link:focus-visible{
  border-radius: var(--r-md);
}

/* Traeger fuer das Video-Abzeichen. Eigene Box, damit position:relative nicht am
   Link haengt (dessen Stapelkontext braucht der Fokusring). */
.tsb-insta-bildbox{
  display: block;
  position: relative;
  line-height: 0;              /* kein Zeilenkasten-Spalt unter dem Bild */
  /* Wie bei der Rasterzelle: als Flex-Kind gilt min-width:auto, also die Eigenbreite
     des Inhalts. Das img traegt width="640" und sprengte damit bei 390px Viewport
     die Kachel auf 640px (gemessen). Beides noetig - width fuer den Normalfall,
     min-width fuer die Schrumpfsperre. */
  width: 100%;
  min-width: 0;
}

.tsb-insta-bild{
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;         /* die Kachel traegt hier kein padding, daher sauber */
  object-fit: cover;
  background: var(--surface-alt);   /* ruhige Flaeche, solange lazy noch laedt */
  transition: transform var(--t-base);
}

/* Bewusst NUR bei :hover, nicht bei :focus-visible — sich durch neun Kacheln zu
   tabben und jedes Mal ein Bild wackeln zu sehen ist unruhig. */
.tsb-insta-link:hover .tsb-insta-bild{
  transform: scale(1.06);
}

/* Video-Abzeichen: Dreieck aus Rahmen statt Emoji (Designregel).
   Das rgba() ist eine der technisch unvermeidbaren Ausnahmen — eine halbtransparente
   Abdeckung ueber unbekanntem Fotoinhalt braucht Alpha, und es gibt kein Token dafuer
   (gleicher Fall wie --accent-soft). Bei einem zweiten Anwendungsfall gehoert daraus
   ein --scrim in :root. */
.tsb-insta-video{
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  width: var(--s-5);
  height: var(--s-5);
  border-radius: var(--r-full);
  background: rgba(20, 22, 21, .55);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tsb-insta-video::before{
  content: "";
  width: 0;
  height: 0;
  margin-left: 2px;                      /* optischer Ausgleich des Dreiecks */
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 8px solid var(--on-dark);
}

/* --- 30.3 Text unter dem Bild -------------------------------------------- */
.tsb-insta-text{
  /* EINE Zahl fuer Clamp und reservierte Hoehe. Standen beide getrennt da, lief die
     Hoehe beim naechsten Breakpoint still auseinander. */
  --insta-zeilen: 2;

  box-sizing: border-box;      /* WPBakery-Umgebung: dort gilt content-box */
  display: block;
  padding-top: var(--s-3);
  padding-bottom: var(--s-4);
  padding-left: var(--s-4);
  padding-right: var(--s-4);
}

/* Leise. Erzeugt zusammen mit der Unterschrift ueberhaupt erst eine Hierarchie
   innerhalb der Kachel. */
.tsb-insta-datum{
  display: block;
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  line-height: var(--lh-base);
  color: var(--muted);
  margin-bottom: var(--s-1);
}

/* Traegt Paddings und Mindesthoehe — NICHT den Clamp.
   overflow:hidden beschneidet an der Padding-Box, nicht an der Content-Box: laege der
   Clamp hier, schiene die verworfene dritte Zeile im padding-bottom als Streifen durch. */
.tsb-insta-caption{
  display: block;
  min-height: calc(var(--insta-zeilen) * var(--lh-base) * 1em);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  /* Die Unterschrift ist nicht Meta, sondern die einzige inhaltliche Beschriftung des
     Links. In --muted wirkte das ganze Raster grau; --muted bleibt dem Datum. */
  color: var(--ink-body);
}

/* Traegt Clamp und Overflow, ohne Padding. */
.tsb-insta-caption-text{
  display: -webkit-box;
  -webkit-line-clamp: var(--insta-zeilen);
  line-clamp: var(--insta-zeilen);
  -webkit-box-orient: vertical;
  overflow: hidden;
  /* Eine lange URL oder eine Hashtag-Kette ohne Leerzeichen wuerde sonst seitlich
     aus der Kachel laufen. */
  overflow-wrap: anywhere;
}

.tsb-insta-fuss{
  /* 48 statt 32: ein Neun-Kachel-Block wiegt mehr als ein Einleitungssatz. Bei gleichem
     Abstand klebte der Button an der letzten Reihe und las sich als deren Fortsetzung. */
  margin-top: var(--s-7);
  margin-bottom: 0;
}

/* --- 30.4 Leerer Zustand -------------------------------------------------
   Nie eine leere Seite, nie eine technische Fehlermeldung fuer den Besucher. */
.tsb-insta-leer{
  border: var(--b-hair);
  border-radius: var(--r-md);
  background: var(--surface-alt);
  padding-top: var(--s-7);
  padding-bottom: var(--s-7);
  padding-left: var(--s-5);
  padding-right: var(--s-5);
  text-align: center;
}

.tsb-insta-leer p{
  color: var(--ink-body);
  margin: 0 0 var(--s-5);
}

.tsb-insta-leer p:last-child{
  margin-bottom: 0;
}

/* --- 30.5 Schmalere Fenster ---------------------------------------------- */
@media (max-width: 768px){
  .tsb-insta{
    padding-top: var(--band-y-mobile);
    padding-bottom: var(--band-y-mobile);
  }
  .tsb-insta-grid{
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--s-4);
  }
  /* 9 Beitraege in 2 Spalten lassen eine einzelne Kachel als halbe Reihe stehen —
     das liest sich als Fehler. Die neunte entfaellt hier, vier volle Reihen bleiben.
     Bewusst in CSS und nicht in PHP: die Anzahl haengt am Breakpoint, nicht am Inhalt. */
  .tsb-insta-kachel:nth-child(n+9){ display: none; }
}

/* Auch auf dem Handy zwei Spalten: einspaltig ergaben 9 Kacheln eine 4410px lange
   Seite (gemessen bei 390px). Zwei Spalten halbieren den Weg und lassen den Feed
   als Raster lesen statt als Liste. */
@media (max-width: 480px){
  .tsb-insta-grid{ gap: var(--s-3); }

  .tsb-insta-text{
    /* Dritte Zeile: bei ~150px Kachelbreite fasst eine Zeile nur ~18 Zeichen,
       zwei Zeilen waeren ein Wortfetzen. Vertikaler Platz ist hier das billigste Gut.
       Clamp und Mindesthoehe folgen dieser einen Zahl. */
    --insta-zeilen: 3;
    padding-top: var(--s-2);
    padding-bottom: var(--s-3);
    padding-left: var(--s-3);
    padding-right: var(--s-3);
  }
}

/* Wer Bewegung reduziert haben will, bekommt keine. */
@media (prefers-reduced-motion: reduce){
  .tsb-insta-link,
  .tsb-insta-bild{ transition: none; }
  .tsb-insta-link:hover .tsb-insta-bild{ transform: none; }
}

/* ============================================================================
   31. MEIN KONTO (.tsb-konto)  [TSB-BLOCK:mein-konto], Umbau 19.07.2026

   Vorher: WooCommerce-Standard plus TeraWallet-Rohoberflaeche. Halb englisches Menue,
   eine englische Wallet-Seite mit 'Wallet topup' und 'Wallet transfer' (beides
   widerspricht Kundenentscheidungen, Begruendung in inc/mein-konto.php) - und nirgends
   der Guthabenstand, obwohl er der einzige Grund fuer das Konto ist.

   Die Buttons im Kontobereich sind bereits versorgt: /mein-konto/ traegt am body die
   Klasse 'woocommerce-page', damit greift Abschnitt 13. Hier steht nur, was dort fehlt:
   das Menue, der Guthabenstand, die Bewegungsliste.

   SCOPE: 'body.tsb-konto-seite' (Klasse aus inc/mein-konto.php). AM body, deshalb OHNE
   Leerzeichen - 'body .tsb-konto-seite' matcht nie (CLAUDE.md).
   ============================================================================ */

/* --- Aufbau: Menue links, Inhalt rechts ------------------------------------
   WooCommerce loest das mit float:left/right und Prozentbreiten. Floats ohne clear
   haben in diesem Projekt schon einmal die Kasse zerlegt (Block 31px hoch bei 915px
   Inhalt, gruene Flaeche hinter allen Feldern). Grid kann das nicht: die Zeilenhoehe
   ergibt sich aus der hoeheren der beiden Spalten, ohne dass jemand clear setzen muss. */
body.tsb-konto-seite .mkd-content .woocommerce{
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: var(--s-7);
  align-items: start;
}

body.tsb-konto-seite .woocommerce-MyAccount-navigation,
body.tsb-konto-seite .woocommerce-MyAccount-content{
  /* Die Prozentbreiten und Floats aus woocommerce.css abraeumen, sonst kaempfen
     zwei Layoutmodelle um dieselben zwei Kinder. */
  float: none;
  width: auto;
  margin: 0;
}

/* Unter 860px passen 240px Menue plus Lesetext nicht mehr nebeneinander:
   der Inhalt bekaeme rund 570px, was bei Tabellen (Bestellungen) schon knapp ist.
   Darunter also untereinander, Menue zuerst. */
@media (max-width: 860px){
  body.tsb-konto-seite .mkd-content .woocommerce{
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-5);
  }
}

/* --- Das Menue ------------------------------------------------------------- */
body.tsb-konto-seite .woocommerce-MyAccount-navigation ul{
  list-style: none;
  margin: 0;
  padding: 0;
  border: var(--b-hair);
  border-radius: var(--r-sm);
  overflow: hidden;
}

body.tsb-konto-seite .woocommerce-MyAccount-navigation li{
  margin: 0;
  border-bottom: var(--b-hair);
}
body.tsb-konto-seite .woocommerce-MyAccount-navigation li:last-child{ border-bottom: 0 }

body.tsb-konto-seite .woocommerce-MyAccount-navigation li a{
  display: block;
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  padding-left: var(--s-4);
  padding-right: var(--s-4);
  font: 700 var(--fs-base)/var(--lh-base) var(--font-head);
  color: var(--ink-body);
  text-decoration: none;
  transition: background var(--t-base), color var(--t-base);
}
body.tsb-konto-seite .woocommerce-MyAccount-navigation li a:hover{
  background: var(--surface-alt);
  color: var(--accent);
}
body.tsb-konto-seite .woocommerce-MyAccount-navigation li a:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

/* Der aktive Eintrag. Der gruene Balken links ist der zweite Traeger neben der
   Flaeche - Farbe allein duerfte den Zustand nicht tragen (SC 1.4.1).
   border-left statt einer Kurzschreibweise, damit die Media-Query unten nichts
   still ueberschreibt. */
body.tsb-konto-seite .woocommerce-MyAccount-navigation li.is-active a{
  background: var(--accent-soft);
  color: var(--accent);
  border-left-width: 3px;
  border-left-style: solid;
  border-left-color: var(--accent);
  padding-left: calc(var(--s-4) - 3px);
}

/* --- Der Guthabenstand ----------------------------------------------------- */
.tsb-konto__stand{
  background: var(--surface-dark);
  border-radius: var(--r-md);
  padding-top: var(--s-6);
  padding-bottom: var(--s-6);
  padding-left: var(--s-6);
  padding-right: var(--s-6);
  margin: 0 0 var(--s-6);
  color: var(--on-dark);
}

.tsb-konto__label{
  margin: 0 0 var(--s-2);
  font: 700 var(--fs-xs)/var(--lh-1) var(--font-head);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--on-dark-muted);
}

/* Die Einheiten fuehren, der Euro-Betrag steht klein darunter
   (Kundenentscheidung 19.07.2026). */
.tsb-konto__zahl{
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin: 0 0 var(--s-2);
}

.tsb-konto__einheiten{
  font: 700 var(--fs-3xl)/var(--lh-tight) var(--font-head);
  letter-spacing: var(--track-display);
  color: var(--accent-bright);
}

/* Bei krummem Restbetrag steht dort ein Euro-Betrag statt einer Zahl. Der ist
   deutlich laenger ('15,00 EUR' gegen '4') und braucht deshalb weniger Groesse,
   sonst bricht er auf dem Handy um. */
.tsb-konto__zahl--rest .tsb-konto__einheiten{ font-size: var(--fs-2xl) }

/* Ohne Guthaben waere eine leuchtend gruene Null eine Auszeichnung fuer nichts. */
.tsb-konto__zahl--leer .tsb-konto__einheiten{ color: var(--on-dark-muted) }

.tsb-konto__einheit{
  font: 400 var(--fs-md)/var(--lh-flat) var(--font-body);
  color: var(--on-dark);
}

.tsb-konto__euro{
  margin: 0 0 var(--s-5);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--on-dark-muted);
}

.tsb-konto__aktionen{
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin: 0;
}

/* Die Ghost-Variante ist fuer helle Flaechen gebaut (weisse Fuellung, dunkler Text)
   und verschwaende hier ihren Kontrast. Auf Dunkel also umgedreht. */
.tsb-konto__stand .tsb-btn-ghost{
  background: transparent;
  border-color: var(--on-dark-muted);
  color: var(--on-dark);
}
.tsb-konto__stand .tsb-btn-ghost:hover{
  border-color: var(--on-dark);
  background: rgba(255,255,255,.08);
}
.tsb-konto__stand .tsb-btn:focus-visible{
  outline: 2px solid var(--focus-on-dark);
  outline-offset: 3px;
}

.tsb-konto__hinweis{
  margin: var(--s-5) 0 0;
  padding-top: var(--s-4);
  border-top: 1px solid rgba(255,255,255,.14);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--on-dark-muted);
  max-width: var(--w-read);
}

/* --- Uebersicht: Gruss und Wegweiser --------------------------------------- */
.tsb-konto__gruss{
  margin: 0 0 var(--s-5);
  font: 700 var(--fs-lg)/var(--lh-flat) var(--font-head);
  color: var(--ink);
}
.tsb-konto__gruss-abmelden{
  display: inline-block;
  margin-left: var(--s-3);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
}

/* --- Die Bewegungsliste ---------------------------------------------------- */
.tsb-konto__titel{
  margin: 0 0 var(--s-4);
  font: 700 var(--fs-xl)/var(--lh-flat) var(--font-head);
  color: var(--ink);
}

.tsb-konto__leer{
  margin: 0;
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--muted);
}

.tsb-konto__liste{
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--b-hair);
}

/* Drei Spalten: Text waechst, Datum und Betrag bleiben so breit wie ihr Inhalt.
   Der Betrag rechtsbuendig und mit tabellarischen Ziffern, damit die Kommas
   untereinander stehen - eine Guthabenliste liest man senkrecht, nicht zeilenweise. */
.tsb-konto__zeile{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: var(--s-3);
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: var(--b-hair);
}

.tsb-konto__zeile-text{
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}

.tsb-konto__zeile-datum{
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
  white-space: nowrap;
}

.tsb-konto__zeile-betrag{
  font: 700 var(--fs-base)/var(--lh-base) var(--font-head);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
}

/* Das Vorzeichen im Text traegt die Richtung bereits, die Farbe verstaerkt sie nur
   (SC 1.4.1). Deshalb darf Minus auch schlicht die Textfarbe behalten. */
.tsb-konto__zeile--plus .tsb-konto__zeile-betrag{ color: var(--accent) }
.tsb-konto__zeile--minus .tsb-konto__zeile-betrag{ color: var(--ink-body) }

/* Unter 560px stehen Text, Datum und Betrag nicht mehr nebeneinander: bei
   'Guthaben aus Bestellung #10822' bliebe der Textspalte zweistellig wenig Platz. */
@media (max-width: 560px){
  .tsb-konto__zeile{
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .tsb-konto__zeile-text{ grid-column: 1 / -1 }
  .tsb-konto__zeile-datum{ grid-column: 1 }
  .tsb-konto__zeile-betrag{ grid-column: 2 }
}

/* --- Feldhinweis unter der E-Mail-Adresse ---------------------------------- */
.tsb-konto__feldhinweis{
  display: block;
  margin-top: var(--s-2);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
}

.tsb-konto__fehler{
  background: var(--surface-alt);
  border-left-width: 3px;
  border-left-style: solid;
  border-left-color: var(--error);
  border-radius: var(--r-sm);
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  padding-left: var(--s-4);
  padding-right: var(--s-4);
  margin: 0;
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}

@media (max-width: 560px){
  .tsb-konto__stand{
    padding-top: var(--s-5);
    padding-bottom: var(--s-5);
    padding-left: var(--s-4);
    padding-right: var(--s-4);
  }
  .tsb-konto__aktionen .tsb-btn{ width: 100% }
}

/* --- Konto in der Kopfzeile (.tsb-kontowidget) -----------------------------
   Sitzt im Theme-Widgetbereich 'mkd-right-from-main-menu', links neben dem Warenkorb.
   Kein '.tsb'-Wrapper moeglich: die Umrandung kommt vom Theme, unser Markup steckt
   darin. Die Regeln tragen ihre Basis deshalb vollstaendig selbst - sonst schlaegt
   body{font-size:15px;line-height:1.66667em} durch, dessen 'em' als LAENGE vererbt. */

.tsb-kontowidget{
  position: relative;
  display: inline-flex;
  align-items: center;
}

.tsb-kontowidget__link{
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding-top: var(--s-2);
  padding-bottom: var(--s-2);
  padding-left: var(--s-2);
  padding-right: var(--s-2);
  font: 700 var(--fs-sm)/var(--lh-1) var(--font-head);
  color: inherit;           /* der Kopf wechselt die Textfarbe je Header-Zustand */
  text-decoration: none;
  transition: color var(--t-base);
}
.tsb-kontowidget__link:hover{ color: var(--accent) }
.tsb-kontowidget__link:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

.tsb-kontowidget__symbol{ flex: none }

/* Der Name kostet in der Kopfzeile Platz, den das Hauptmenue braucht. Ab hier
   traegt das Symbol allein - es steht neben dem Warenkorb und ist damit im
   erwarteten Zusammenhang eindeutig. */
@media (max-width: 1200px){
  .tsb-kontowidget__text{
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* --- Das Klappmenue --------------------------------------------------------
   :focus-within ist hier kein Extra, sondern die Bedingung dafuer, dass der Eintrag
   'Abmelden' per Tastatur ueberhaupt erreichbar ist. Mit :hover allein waere er es
   nicht (SC 2.1.1). */
.tsb-kontowidget__panel{
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 120;
  min-width: 170px;
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-sm);
  box-shadow: var(--sh-card);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity var(--t-base), transform var(--t-fast), visibility var(--t-base);
}

.tsb-kontowidget--an:hover .tsb-kontowidget__panel,
.tsb-kontowidget--an:focus-within .tsb-kontowidget__panel{
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.tsb-kontowidget__panel ul{
  list-style: none;
  margin: 0;
  padding: 0;
}
.tsb-kontowidget__panel li{ margin: 0; border-bottom: var(--b-hair) }
.tsb-kontowidget__panel li:last-child{ border-bottom: 0 }

.tsb-kontowidget__panel a{
  display: block;
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  padding-left: var(--s-4);
  padding-right: var(--s-4);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--t-base), color var(--t-base);
}
.tsb-kontowidget__panel a:hover{ background: var(--surface-alt); color: var(--accent) }
.tsb-kontowidget__panel a:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce){
  .tsb-kontowidget__panel{ transition: none }
}

/* --- Anmeldeseite unter /mein-konto/ --------------------------------------- */
.tsb-konto__anmelden-fuss{
  margin: var(--s-5) 0 0;
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
  max-width: var(--w-read);
}

/* Ausgeloggt gibt es kein Kontomenue - das Grid haette sonst eine leere 240px-Spalte. */
body.tsb-konto-seite .mkd-content .woocommerce:not(:has(.woocommerce-MyAccount-navigation)){
  display: block;
}

/* --- 31.1 Spezifitaet: zwei Fremdregeln, die den Bereich uebernommen hatten -----

   Beides erst im SCREENSHOT aufgefallen. Die DOM-Messung war gruen: das Grid stand,
   der Ueberlauftest meldete nichts, der Button hatte Text. Nur eben unsichtbaren.

   (a) DAS MENUE WAR 72px BREIT, die Beschriftungen abgeschnitten ("Übe...", "Gut...").
       Das Grid griff (240px 812px), aber das Theme setzt die Breite hart:
         .mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-navigation
                                                                            = (0,3,0)
       Dagegen stand
         body.tsb-konto-seite .woocommerce-MyAccount-navigation              = (0,2,1)
       Drei Klassen schlagen zwei Klassen plus ein Element - das Element zaehlt in der
       niedrigeren Stelle und kann eine Klasse nie aufwiegen. Die Theme-Kette muss
       deshalb mitgespiegelt werden. Beide Klassen sitzen AM body, also ohne Leerzeichen
       ankoppeln (CLAUDE.md: 'body .klasse-am-body' matcht nie).

   (b) JEDER LINK IM KONTOBEREICH WAR GRUEN, auch die Buttonbeschriftung. Aus Abschnitt 13:
         body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart)
           { color: var(--accent) }                                          = (0,5,2)
       Unsere Buttons heissen .tsb-btn, nicht .button - die :not()-Kette schliesst sie
       also NICHT aus und faerbt ihren Text. Auf dem dunklen Guthabenfeld liegt dann
       --accent auf --accent: Text und Flaeche dieselbe Farbe, der Knopf sah leer aus.
       ':not()' zaehlt dabei wie eine Klasse, deshalb kommt die Kette auf (0,5,2) und
       schlaegt die Buttonregel :is(.tsb,...) .tsb-btn-green = (0,2,0) muehelos.

   Der gemeinsame Praefix unten kommt auf (0,6,2) und gewinnt gegen beide - ohne
   ein einziges !important und ohne sich auf die Reihenfolge in der Datei zu verlassen.
   ---------------------------------------------------------------------------- */

/* (a) Menuebreite und Float wirklich abraeumen. */
body.tsb-konto-seite.mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-navigation,
body.tsb-konto-seite.mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-content{
  float: none;
  width: auto;
  margin: 0;
}

/* (b) Die Links im Menue tragen wieder Lesefarbe statt Akzentgruen. */
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .woocommerce-MyAccount-navigation li a{
  color: var(--ink-body);
}
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .woocommerce-MyAccount-navigation li a:hover,
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .woocommerce-MyAccount-navigation li.is-active a{
  color: var(--accent);
}

/* (b) Die Buttons auf dem dunklen Guthabenfeld.
   Primaer: heller Text auf gruener Flaeche (wie Abschnitt 19 es vorsieht).
   Ghost: die helle Variante taugt auf Dunkel nicht, deshalb umgedreht. */
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-konto__stand a.tsb-btn-green{
  color: var(--on-dark);
  background: var(--accent);
  border-color: var(--accent);
}
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-konto__stand a.tsb-btn-ghost{
  color: var(--on-dark);
  background: transparent;
  border-color: var(--on-dark-muted);
}
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-konto__stand a.tsb-btn-ghost:hover{
  border-color: var(--on-dark);
  background: rgba(255,255,255,.08);
}

/* Das Konto-Widget in der Kopfzeile steht ausserhalb von .mkd-content und ist von
   der :not()-Kette nicht betroffen - dort bleibt 'color: inherit' richtig. */




/* --- 31.2 Das Klappmenue war weiss auf weiss ---------------------------------

   Auch das war in den Messwerten unsichtbar: Panel sichtbar, opacity 1, Links im DOM,
   Text vorhanden. Nur eben in Weiss auf weissem Grund. Erst der Screenshot zeigte eine
   leere Box mit Trennlinien.

   Ursache: das Theme faerbt ALLE Links in den Kopf-Widgets weiss, damit sie auf dem
   dunklen Header lesbar sind. Die Regel ist eine lange Komma-Gruppe der Form
     .mkd-light-header ... .mkd-main-menu-widget-area
       .widget:not(.widget_mkd_woocommerce_dropdown_cart) ... a      = (0,5,1)
   Das ':not()' schliesst nur den Warenkorb aus - unser Widget heisst
   'widget_tsb_konto' und faellt darunter. Dagegen stand
     .tsb-kontowidget__panel a                                       = (0,1,1)

   Das Klappmenue ist aber die einzige Stelle des Widgets, die NICHT auf dem dunklen
   Header liegt: es ist eine weisse Karte davor. Genau dort ist Weiss falsch.

   ACHTUNG, DAS KOSTETE EINEN ANLAUF: der erste Versuch spiegelte '.mkd-logo-area' mit,
   weil dieser Selektor in der Theme-Gruppe steht. Die Kette unseres Widgets enthaelt
   ihn aber NICHT - sie laeuft ueber '.mkd-menu-area'. Die Regel wurde ausgeliefert,
   war korrekt geschrieben und matchte trotzdem nichts. Bei einer Regel ohne Wirkung
   also zuerst die ECHTE Vorfahrenkette am Element auslesen, statt den Selektor aus
   der fremden Datei zu uebernehmen: eine Komma-Gruppe matcht schon, wenn irgendein
   Zweig passt - nicht unbedingt der, den man gerade liest.

   Die Regel unten kommt auf (0,5,2) - fuenf Klassen wie das Theme, plus ein Element
   mehr ('li'). Elemente entscheiden bei Klassengleichstand, deshalb gewinnt sie, ohne
   sich auf die Reihenfolge in der Datei zu verlassen und ohne !important.

   Der Link im Header selbst behaelt bewusst 'color: inherit' und bleibt damit weiss -
   dort ist die Theme-Farbe richtig.
   ---------------------------------------------------------------------------- */

.mkd-menu-area .mkd-main-menu-widget-area .widget .tsb-kontowidget .tsb-kontowidget__panel li a{
  color: var(--ink-body);
}
.mkd-menu-area .mkd-main-menu-widget-area .widget .tsb-kontowidget .tsb-kontowidget__panel li a:hover,
.mkd-menu-area .mkd-main-menu-widget-area .widget .tsb-kontowidget .tsb-kontowidget__panel li a:focus-visible{
  color: var(--accent);
}

/* Der Kopf-Widgetbereich ist rechtsbuendig ausgerichtet, und das vererbt sich in die
   Karte hinein - die Eintraege standen rechts an der Kante. In einer Liste, die man
   von oben nach unten liest, gehoert der Zeilenanfang untereinander. */
.mkd-menu-area .mkd-main-menu-widget-area .widget .tsb-kontowidget .tsb-kontowidget__panel{
  text-align: left;
}

/* ===== TSB-BLOCK:voice-24 START — nicht von Hand bearbeiten, Quelle:
        scripts/voice-2026-07/abschnitt-24.css ===== */

/* ========================================================================== *
 * 24. Elternstimme im dunklen Band (Variante A, Kundenentscheidung 19.07.)
 *
 * Vorher: Die Stimme stand in einem .tsb-band OHNE Farbmodifier, erbte damit
 * Weiss — und direkt darueber liegt das weisse Preisband. Ohne Zaesur las sie
 * sich als Nachsatz zum Preisblock statt als eigener Abschnitt. Dazu trug sie
 * nur einen 3px-Balken (0,4 % der Blockflaeche) und stand in Lato 19px, also
 * exakt in der Fliesstextgroesse der ganzen Seite: nichts signalisierte, dass
 * hier jemand anderes spricht.
 *
 * Nachher: eigenes dunkles Band. Ein Flaechenwechsel ist die staerkste
 * verfuegbare Zaesur und braucht weder Foto noch neue Kartenform. Das
 * Trainerband ist ebenfalls dunkel — dieselbe Flaeche fuer „hier sprechen
 * Menschen" ist ein lesbares System statt Zufall.
 *
 * Bewusst 26px und KEIN Knopf: ein buehnenreifes Einzelzitat sagt unfreiwillig
 * „mehr haben wir nicht", und ein Knopf hier wuerde mit dem Abschluss-CTA
 * konkurrieren. Die Schrittkette danach ist bereits die naechste Handlung.
 *
 * Die Basis .tsb-voice (heller Grund, 19px, Balken links) bleibt unangetastet —
 * sie traegt spaeter die dreispaltige Fassung .tsb-voices.
 * ========================================================================== */

.tsb-start .tsb-band-dark .tsb-voice{
  max-width: 640px;
  /* Der Innenabstand der Basis stammt vom Akzentbalken, der hier entfaellt. */
  padding-top: 0;
  padding-bottom: 0;
  padding-left: 0;
  padding-right: 0;
}

/* Der Balken links entfaellt: auf dunklem Grund traegt die Flaeche das Gewicht,
   und unter dem Zitat steht eine eigene Akzentlinie. */
.tsb-start .tsb-band-dark .tsb-voice::before{ content: none }

.tsb-start .tsb-band-dark .tsb-voice .kick{ margin-bottom: var(--s-5) }

.tsb-start .tsb-band-dark .tsb-voice blockquote{
  font-size: var(--fs-xl);
  line-height: 1.55;
  color: var(--on-dark);
}
/* Der Ankersatz gibt einen Einstiegspunkt in die 368 Zeichen. Er ist WOERTLICH
   hervorgehoben und der vollstaendige Text steht unveraendert darum herum —
   ein O-Ton wird nicht gekuerzt und nicht umgedeutet. */
.tsb-start .tsb-band-dark .tsb-voice blockquote strong{
  font-weight: 700;
  color: var(--on-dark);
}

.tsb-start .tsb-band-dark .tsb-voice figcaption{
  margin-top: 0;                 /* den Abstand traegt die Linie darunter */
  color: var(--on-dark);
}
.tsb-start .tsb-band-dark .tsb-voice figcaption::before{
  content: "";
  display: block;
  width: 40px;
  height: 2px;
  background: var(--accent-bright);
  opacity: .85;
  margin-top: var(--s-6);
  margin-bottom: var(--s-4);
}
.tsb-start .tsb-band-dark .tsb-voice figcaption b{
  display: block;
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--on-dark);
}
/* Der Verein ist der ueberpruefbarste Teil des ganzen Bausteins und belegt
   nebenbei aus fremdem Mund die Reichweite „Schwerin bis Neubrandenburg" aus
   dem Trainerband. Deshalb eigene Zeile statt Anhaengsel hinter einem Komma. */
.tsb-start .tsb-band-dark .tsb-voice figcaption span{
  display: block;
  margin-top: var(--s-1);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 400;
  letter-spacing: normal;
  color: var(--on-dark-muted);
}

@media (max-width: 767px){
  /* 26px ergaeben auf 390px rund 14 Zeilen. */
  .tsb-start .tsb-band-dark .tsb-voice blockquote{ font-size: var(--fs-lg) }
}

/* -------------------------------------------------------------------------- *
 * 24.1 BESTANDSFEHLER, beim Bau der Elternstimme aufgefallen:
 *      auf schmalen Geraeten hat die Startseite keinen Seitenrand.
 *
 * Abschnitt 3 setzt in @media (max-width: 768px) ein
 *   .tsb-inner{ padding-inline: 0 !important }
 * mit der Begruendung, der Gutter sitze am Theme-Container .mkd-container-inner
 * und wuerde sich sonst verdoppeln (16 + 22 = 38px auf einem 390px-Display).
 *
 * Das stimmt fuer jede Seite AUSSER der Startseite: sie nutzt full-width.php,
 * ihre Rows liegen ausserhalb von .mkd-container-inner. Dort gibt es also gar
 * keinen Gutter, der sich verdoppeln koennte — der Reset entfernt ersatzlos den
 * einzigen, den es gibt (Zeile 1646 setzt ihn auf .tsb-start .tsb-inner).
 *
 * Gemessen bei 390px, alle bei links 0 / rechts 390, also direkt an beiden
 * Displaykanten: Intro-Absatz, Trainer-Text, CTA-Text und die Elternstimme.
 * Karten fallen nicht auf, weil sie eigenen Innenabstand mitbringen — deshalb
 * ist es bisher niemandem aufgefallen.
 *
 * Gegen ein !important hilft nur ein !important; .tsb-start .tsb-inner (0,2,0)
 * schlaegt .tsb-inner (0,1,0) bei sonst gleichem Gewicht.
 *
 * ACHTUNG, .tsb-start liegt NICHT nur auf der Startseite: die Portraitseite
 * traegt "tsb tsb-pk tsb-start" (aus dem Umbau vom 18.07., um die Startseiten-
 * Komponenten wiederzuverwenden). Diese Regel wirkt dort also mit — geprueft
 * und erwuenscht, denn dort klebte der Text genauso an der Kante (gemessen
 * 0 -> 16px, kein Ueberlauf, 6/6 Bilder, 4 Karten unveraendert). Die
 * Kontaktseite traegt die Klasse nicht und bleibt unberuehrt.
 * Wer kuenftig auf .tsb-start scoped, trifft immer beide Seiten.
 * -------------------------------------------------------------------------- */
@media (max-width: 768px){
  .tsb-start .tsb-inner{ padding-inline: var(--gutter) !important }
}

/* -------------------------------------------------------------------------- *
 * 24.2 Zwei Stimmen nebeneinander (Kundenentscheidung 19.07.)
 *
 * Zwei Stimmen nebeneinander zeigen MENGE — „mehrere Eltern sagen das" ist ein
 * anderer Beweis als zwei Einzelzitate an verschiedenen Stellen der Seite.
 * Das Raster .tsb-voices war dafuer bereits vorbereitet (auto-fit, min 26rem),
 * es kippt unter ~440px von selbst auf eine Spalte.
 *
 * Die Einzelfassung aus 24 bleibt gueltig: faellt eine Stimme weg, steht die
 * verbliebene wieder gross und mittig — kein Raster mit einem Kind.
 * -------------------------------------------------------------------------- */

.tsb-start .tsb-band-dark .tsb-voices-kick{
  text-align: center;
  margin-bottom: var(--s-6);
}

/* Im Raster traegt die Spalte die Breite, nicht die einzelne Stimme. */
.tsb-start .tsb-band-dark .tsb-voices .tsb-voice{
  max-width: none;
}

/* 26px sind fuer eine halbe Spalte zu gross (rund 30 Zeichen je Zeile).
   22px bleiben deutlich ueber der Fliesstextgroesse der Seite (19px), das
   Zitat liest sich also weiter als Zitat. */
.tsb-start .tsb-band-dark .tsb-voices .tsb-voice blockquote{
  font-size: var(--fs-lg);
}

/* Das auto-fit der Basis (min 26rem = 416px) braucht 2x416 + 32px Abstand,
   also 864px Inhaltsbreite. Gemessen bei 900px Fenster: nur 856px vorhanden —
   es kippte um 8px knapp auf eine Spalte, und die Zitate liefen dann ueber die
   vollen 856px, also weit ueber 100 Zeichen je Zeile. Deshalb hier ein fester
   Umbruch statt auto-fit. */
@media (min-width: 900px){
  .tsb-start .tsb-band-dark .tsb-voices{ grid-template-columns: repeat(2, 1fr) }
}
@media (max-width: 899px){
  .tsb-start .tsb-band-dark .tsb-voices{
    grid-template-columns: 1fr;
    /* Einspaltig gilt dieselbe Lesebreite wie fuer die Einzelfassung. */
    max-width: 640px;
    margin-inline: auto;
  }
}

/* --- Drei Stimmen (seit 19.07.) -------------------------------------------
   Bei drei Zitaten waere ein Zweispalter ungluecklich: eines bliebe allein in
   der zweiten Zeile stehen. Deshalb ab 1024px drei Spalten. Das Raster ist auf
   1100px begrenzt, jede Spalte also rund 340px breit — 22px ergaeben dort nur
   etwa 26 Zeichen je Zeile, zu schmal. Mit 19px sind es rund 37, das entspricht
   einer Zeitungsspalte und liest sich ruhig.
   Unter 1024px direkt eine Spalte, damit nie ein Waisenkind entsteht. */
@media (min-width: 1024px){
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(3)){
    grid-template-columns: repeat(3, 1fr);
  }
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(3)) .tsb-voice blockquote{
    font-size: var(--fs-md);
  }
  /* Die drei Zitate sind unterschiedlich lang (225 / 437 / 377 Zeichen). Ohne
     Ausgleich enden ihre Zuordnungen auf drei Hoehen, gemessen bis zu 147px
     versetzt — die Akzentlinien bilden dann eine Treppe. Die Basis setzt
     align-items:start; hier werden die Spalten gleich hoch und die Zuordnung
     wird nach unten geschoben, damit alle drei auf einer Linie stehen. */
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(3)){ align-items: stretch }
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(3)) .tsb-voice{
    display: flex;
    flex-direction: column;
  }
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(3)) .tsb-voice figcaption{
    margin-top: auto;
  }
}
@media (max-width: 1023px){
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(3)){
    grid-template-columns: 1fr;
    max-width: 640px;
    margin-inline: auto;
  }
}

@media (max-width: 767px){
  .tsb-start .tsb-band-dark .tsb-voices .tsb-voice blockquote{ font-size: var(--fs-md) }
  /* Untereinander brauchen die beiden Stimmen eine sichtbare Trennung, sonst
     laufen sie zu einem Textblock zusammen. */
  .tsb-start .tsb-band-dark .tsb-voices .tsb-voice + .tsb-voice{
    padding-top: var(--s-6);
    /* Aus dem Token gemischt statt als Farbliteral — die Projektregel erlaubt
       im Komponenten-CSS nur var(). */
    border-top: 1px solid color-mix(in srgb, var(--on-dark) 14%, transparent);
  }
}
/* ===== TSB-BLOCK:voice-24 END ===== */

/* ===== TSB-BLOCK:voice-25 START — nicht von Hand bearbeiten, Quelle:
        scripts/voice-2026-07/abschnitt-25.css ===== */
/* ========================================================================== *
 * 25. Vier und mehr Elternstimmen: Scroll-Streifen statt Raster
 *     (Kundenentscheidung 19.07.2026 — "wie waere es mit einem Slider")
 *
 * ANLASS
 * Mit der vierten Stimme (Pepe) kippt das Raster. OFFENE-PUNKTE A2 hatte das
 * vorhergesagt: „Ab etwa vier Stimmen umdenken — dann wird Nebeneinander zur
 * Textwand." Dazu kommt ein handfestes Layoutproblem: die Basis rechnet mit
 * auto-fit/minmax(26rem), vier Karten ergeben je nach Fensterbreite 3+1 oder
 * 2x2 — im ersten Fall steht die vierte allein in der zweiten Zeile, genau die
 * Waise, die Abschnitt 24 fuer den Dreierfall eigens verhindert hat.
 *
 * TECHNIK: natives CSS-Scroll-Snapping, KEIN Owl.
 * Uebernommen aus Abschnitt 9 (Merch-Slider) samt Begruendung: Owl kostete bei
 * der Partner-Logoleiste am 16.07. drei Fallstricke (Loop-Guard, Stacking-
 * Context durch translate3d, fehlender margin-Default) und setzt Breite und
 * transform INLINE, was jede Korrektur zu einer !important-Schlacht macht.
 * Scroll-Snapping ist auf dem Handy von Haus aus wischbar und funktioniert
 * ohne JS — die Pfeile sind Komfort, keine Voraussetzung.
 *
 * DER ANSCHNITT IST DER KERN, NICHT DIE DEKORATION.
 * Der uebliche Einwand gegen Karussells stimmt: gelesen wird Slide 1. Deshalb
 * ist hier NICHT eine Karte sichtbar, sondern drei plus ein sichtbarer Rest der
 * vierten. Auf dem Desktop bleibt der Anblick damit praktisch der heutige —
 * der Streifen zeigt nur zusaetzlich an, dass es weitergeht. Dieselbe Loesung
 * wie im Merch-Slider, dort kommentiert als „der Anschnitt zeigt: hier geht es
 * weiter". Wer nicht wischt, verliert also nichts, was er heute saehe.
 *
 * WARUM :has(> :nth-child(4))
 * Der Streifen greift erst ab der vierten Stimme. Faellt eine weg, gilt wieder
 * Abschnitt 24 (drei Spalten mit Hoehenausgleich), darunter der Zweispalter,
 * darunter die Einzelfassung. Vier Ausbaustufen, jede fuer sich gueltig — kein
 * Zustand, in dem ein Raster mit einem Kind oder ein Slider mit zwei Karten
 * steht.
 *
 * ⚠️ SPEZIFITAET: :has(> :nth-child(3)) aus Abschnitt 24 matcht bei vier
 * Kindern MIT (ein drittes Kind ist ja vorhanden). Beide Selektoren sind exakt
 * gleich spezifisch — :has() erbt die Spezifitaet seines Arguments, und
 * :nth-child(3) wie :nth-child(4) zaehlen beide (0,1,0). Es entscheidet also
 * allein die Reihenfolge: dieser Abschnitt MUSS nach Abschnitt 24 stehen.
 * Dasselbe Muster nutzt bereits Abschnitt 19 („Steht am Dateiende -> schlaegt
 * bei gleicher Spezifitaet die Originalregel").
 * ========================================================================== */

/* Der Wrapper traegt die Pfeile. Er MUSS ausserhalb des scrollenden Elements
   liegen, sonst wandern die Pfeile beim Wischen mit dem Inhalt aus dem Bild. */
.tsb-start .tsb-band-dark .tsb-voices-slider{ position: relative }

/* --- Der Streifen --------------------------------------------------------- */
.tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4)){
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  align-items: stretch;            /* Karten gleich hoch, s. figcaption unten */
  /* Abschnitt 24 begrenzt den Dreierfall unter 1024px auf 640px und zentriert
     ihn. Fuer einen Streifen waere das eine 640px-Gasse mitten im Band. */
  max-width: none;
  margin-inline: 0;
  /* Raum fuer den Schatten/Fokusring der Karten, analog Merch-Slider. */
  padding-bottom: var(--s-2);
  scrollbar-width: none;                /* Firefox */
  -ms-overflow-style: none;
}
.tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4))::-webkit-scrollbar{
  display: none;
}

/* --- Die einzelne Karte im Streifen --------------------------------------- */
/* Schmal: eine Karte plus Anschnitt. 86 % statt der 78 % des Merch-Sliders —
   Produktkacheln sind Bild plus zwei Zeilen, hier steht Fliesstext, der bei
   78 % auf rund 28 Zeichen je Zeile faellt. */
.tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4)) > .tsb-voice{
  flex: 0 0 86%;
  scroll-snap-align: start;
  /* Hoehenausgleich wie im Dreierfall: ohne ihn enden die Zuordnungen auf
     verschiedenen Hoehen und die Akzentlinien bilden eine Treppe. */
  display: flex;
  flex-direction: column;
}
.tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4)) > .tsb-voice figcaption{
  margin-top: auto;
}

/* Breit: drei ganze Karten + 40px Anschnitt der vierten.
   Rechnung: 3 Karten + 3 Abstaende + 40px Anschnitt = 100 %. Der dritte
   Abstand gehoert zum Anschnitt, deshalb 3 und nicht 2. */
@media (min-width: 1024px){
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4)) > .tsb-voice{
    flex-basis: calc((100% - 3 * var(--s-6) - 40px) / 3);
  }
}

/* ⚠️ Abschnitt 24 trennt die Stimmen unter 768px mit einer Linie OBEN, weil sie
   dort untereinander stehen. Im Streifen stehen sie nebeneinander — die Linie
   liefe dann quer ueber den Kartenkopf. Muss zurueckgenommen werden. */
@media (max-width: 767px){
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4)) > .tsb-voice + .tsb-voice{
    padding-top: 0;
    border-top-width: 0;
    border-top-style: none;
  }
}

/* --- Pfeile (Komfort; ohne JS bleibt der Streifen wischbar) ---------------- */
/* ⚠️ NICHT seitlich neben dem Streifen wie im Merch-Slider (Abschnitt 9).
   Dort sitzen sie mit left/right:-22px halb ueber dem Inhalt — bei Produkt-
   kacheln faellt das kaum auf, auf Fliesstext sehr wohl: gemessen am 19.07.
   ueberlappten sie die erste Karte auf JEDER Breite um 22px.
   „Weiter nach aussen schieben" loest es nicht. Neben dem Streifen ist nur bei
   sehr breiten Fenstern Platz — gemessen 192px bei 1440 und 112px bei 1280,
   aber nur 22px ab 1024 abwaerts, wo die Pfeile bereits am Bildschirmrand
   klebten (prev lag bei [0..44]).
   Deshalb eine eigene Bedienzeile UNTER dem Streifen: eine Regel fuer alle
   Breiten, kein Ueberlappen, kein Platzproblem — und sie koennen dadurch auf
   dem Handy sichtbar bleiben, wo sie vorher ausgeblendet waren. Dass es vier
   Stimmen gibt, ist damit auch ohne Wischen erkennbar. */
.tsb-start .tsb-band-dark .tsb-voices-nav-zeile{
  display: flex;
  justify-content: center;
  gap: var(--s-4);
  margin-top: var(--s-5);
}

/* Form und Masse aus Abschnitt 9 uebernommen, Farben fuer den dunklen Grund:
   dort accent auf hellem Grund, hier accent-bright auf surface-dark. */
.tsb-start .tsb-band-dark .tsb-voices-nav{
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  /* Langformen statt der Kurzschreibweise: `border: 1.5px solid var(--x)` wird
     zur Parse-Zeit nicht zerlegt (Projektregel). */
  border-top-width: 1.5px; border-right-width: 1.5px;
  border-bottom-width: 1.5px; border-left-width: 1.5px;
  border-style: solid;
  border-color: var(--accent-bright);
  border-radius: var(--r-full);
  background: var(--surface-dark);
  color: var(--on-dark);
  cursor: pointer;
  padding: 0;
  transition: background var(--t-base), color var(--t-base), opacity var(--t-base);
}
.tsb-start .tsb-band-dark .tsb-voices-nav:hover{
  background: var(--accent-bright);
  color: var(--accent-ink);
}
/* Am Anfang bzw. Ende wird der jeweilige Pfeil gedaempft, NICHT ausgeblendet.
   Abschnitt 9 blendet ihn ganz aus (opacity:0) — dort schwebt er ueber dem
   Inhalt und waere sonst ein toter Knopf im Bild. Hier steht er in einer
   eigenen Zeile: verschwaende er, wuerde die Zeile bei jedem Wisch zucken.
   Gedaempft zeigt er zusaetzlich an, dass der Streifen hier zu Ende ist. */
.tsb-start .tsb-band-dark .tsb-voices-nav[disabled]{
  opacity: .3;
  pointer-events: none;
}
.tsb-start .tsb-band-dark .tsb-voices-nav svg{
  width: 18px;
  height: 18px;
  display: block;
}

@media (prefers-reduced-motion: reduce){
  .tsb-start .tsb-band-dark .tsb-voices:has(> :nth-child(4)){ scroll-behavior: auto }
  .tsb-start .tsb-band-dark .tsb-voices-nav{ transition: none }
}
/* ===== TSB-BLOCK:voice-25 END ===== */
/* ===== TSB-BLOCK:konto-feinschliff START ===== */
/* Feinschliff Mein Konto (19.07.2026, nach Kundenrückmeldung).

   In Marker gefasst, damit ein Rollout diesen Block ersetzen statt anhängen kann
   (CLAUDE.md: eine Marker-Prüfung erkennt kein Wachstum).

   (a) DIE MARKIERUNG IM SEITENMENUE "PASST NICHT IN DIE MENUEPUNKTE REIN".
       Gemessen war kein Ueberstand: der Link sitzt exakt 1px innerhalb der Liste,
       links wie rechts (a 91..299 in ul 90..300, bei 1280/900/700/390px identisch).
       Der Eindruck kommt nicht von einem Fehler, sondern davon, dass die Markierung
       RANDLOS bis auf die Rahmenlinie laeuft und der gruene Balken direkt darauf klebt.
       Jede andere Komponente im System hat Innenabstand - hier fehlte er.
       Also: Innenabstand an der Liste, eigene Rundung an den Eintraegen. Die Markierung
       sitzt damit sichtbar IN der Karte statt an ihrem Rand.

   (b) Der Balken des aktiven Eintrags als 'inset box-shadow' statt 'border-left'.
       Ein Rahmen an einem abgerundeten Kasten folgt der Rundung und wirkt an den Ecken
       dick; der Schatten liegt innen und braucht keine Padding-Korrektur
       (das alte 'padding-left: calc(var(--s-4) - 3px)' entfaellt damit).

   (c) Der Feldhinweis unter der E-Mail-Adresse hatte 8px nach oben und 0px nach unten.
       Der Abstand nach unten ist mit der Aufnahme des Formulars in Abschnitt 20 bereits
       gelöst (Raster-Abstand 24px vor dem Button). Nach oben zieht er hier auf 12px an -
       denselben Wert, den Abschnitt 20 zwischen Beschriftung und Feld verwendet, damit
       der Hinweis im selben Rhythmus liegt und nicht am Feld klebt.
   ============================================================================ */

/* (a) Innenabstand an der Liste, damit die Markierung nicht am Rahmen klebt.

   ZUM VIERTEN MAL DIESELBE FALLE, deshalb hier ausgeschrieben: das Theme setzt
     .mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-navigation ul
       { padding: 0 }                                                    = (0,3,1)
   Ein erster Versuch mit
     body.tsb-konto-seite .woocommerce-MyAccount-navigation ul            = (0,2,2)
   verlor - zwei Elemente wiegen eine Klasse nicht auf. Rundung und Balken darunter
   kamen an, nur das Padding nicht: EIN Selektor kann teilweise wirken, wenn die
   fremde Regel nur EINE Eigenschaft belegt. Also nicht "die Regel greift nicht"
   pruefen, sondern jede Eigenschaft einzeln.
   Praefix wie in 23.1: vier Klassen, damit es sicher gewinnt.                    */
body.tsb-konto-seite.mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-navigation ul{
  padding-top: var(--s-2);
  padding-bottom: var(--s-2);
  padding-left: var(--s-2);
  padding-right: var(--s-2);
}

/* Die Trennlinien liegen dadurch eingerueckt - gewollt, sie gehoeren zu den
   Eintraegen, nicht zur Kartenkante. */
body.tsb-konto-seite.mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-navigation li a{
  border-radius: var(--r-sm);
}

/* (b) Aktiver Eintrag: Balken innen, keine Padding-Korrektur mehr noetig.
   Der Praefix spiegelt Abschnitt 31.1, sonst gewinnt die Theme-Kette wieder. */
body.tsb-konto-seite.mkd-woocommerce-page.woocommerce-account .woocommerce-MyAccount-navigation li.is-active a{
  border-left-width: 0;
  padding-left: var(--s-4);
  box-shadow: inset 3px 0 0 var(--accent);
}

/* (c) Feldhinweis: 12px nach oben, im Rhythmus von Abschnitt 20. */
.tsb-konto__feldhinweis{
  margin-top: var(--s-3);
}
/* ===== TSB-BLOCK:konto-feinschliff END ===== */

/* ===== TSB-BLOCK:flow-zentriert START — nicht von Hand bearbeiten, Quelle:
        scripts/flow-2026-07-19/abschnitt-32.css ===== */
/* ------------------------------------------------------------------------
   32. Ablauf-Abschnitt komplett zentriert  [TSB-BLOCK:flow-zentriert]
   Kundenbefund 19.07.2026: "So laeuft's ab sieht komisch aus."

   BEFUND (gemessen, nicht vermutet): Am 18.07. wurde die Schrittkette selbst
   zentriert (Abschnitt "Startseite-Befund", @media min-width:768px). Die
   KOEPFE der drei Angebotsseiten sind dabei nicht mitgezogen worden. Ergebnis
   auf /gruppentraining/, /tagescamp/, /kindergeburtstag/:
       h2.tsb-bt      links
       p.tsb-lead     links
       ol.tsb-flow    zentriert   <- der Bruch
       .tsb-flow-cta  links
   Startseite (#5788) und /termine/ (#573) waren schon stimmig, weil ihre
   Koepfe .tsb-shortcode-head--center bzw. .tsb-tm-intro tragen.

   ENTSCHEIDUNG: die Komponente ist ganz zentriert, wie die 1-2-3-Kette auf
   /termine/. Also nicht drei Seiten einzeln nachziehen, sondern die Regel an
   die Komponente haengen: wo eine .tsb-flow direkt in einem .tsb-inner steht,
   ist der ganze Block zentriert. Kostet eine Stelle statt drei und gilt
   automatisch fuer den naechsten Ablauf-Abschnitt.

   WARUM :has() UND KEINE MODIFIER-KLASSE: die Alternative waere ein
   .tsb-inner--center im Markup — das haette drei base64-[vc_raw_html]-Bloecke
   in der DB veraendert. Rein deklarativ ist risikoaermer und rollbackbar
   durch Loeschen dieses Blocks. Kennt ein Browser :has() nicht, faellt die
   Regel weg und es bleibt exakt der heutige Zustand.
   Deshalb steht :has() in KEINER gemischten Selektorliste — sonst risse ein
   nicht unterstuetzter Selektor die ganze Liste mit weg.

   WARUM NUR AB 768px: darunter ist die Kette bewusst vertikal und linksbuendig
   (48px-Spalte + Text, Verbindungslinie senkrecht). Ein zentrierter Kopf ueber
   einer linksbuendigen Kette waere derselbe Bruch, nur andersherum. Die Query
   spiegelt damit die vom 18.07.
   ------------------------------------------------------------------------ */
@media (min-width:768px){

  /* Der Block als Ganzes. Die Vererbung ist hier gewollt und gefahrlos: die
     Schritte darin sind ab 768px ohnehin schon zentriert. */
  .tsb .tsb-inner:has(> .tsb-flow){
    text-align:center;
  }

  /* .tsb-bt ist display:flex (wegen der .num-Ziffer) — text-align allein
     zentriert es NICHT, es braucht justify-content. Genau dafuer stand auf der
     Startseite bisher ein Inline-Style im Markup. */
  .tsb .tsb-inner:has(> .tsb-flow) .tsb-bt{
    justify-content:center;
  }

  /* .tsb-lead hat max-width:64ch — ohne auto-Raender bliebe der Block links
     stehen und nur sein Text waere zentriert. */
  .tsb .tsb-inner:has(> .tsb-flow) .tsb-lead{
    margin-left:auto;
    margin-right:auto;
  }

  /* Der CTA ist ein inline-flex .tsb-btn, den traegt text-align schon. Explizit
     trotzdem, damit die Absicht am Element steht und ein spaeteres display:flex
     am Wrapper nicht still nach links kippt. */
  .tsb .tsb-inner:has(> .tsb-flow) .tsb-flow-cta{
    text-align:center;
  }
}
/* ===== TSB-BLOCK:flow-zentriert END ===== */

/* ===== TSB-BLOCK:hero-dxa START =====
   Seitenanfang (Hero) und die Komponenten der Seite Einzeltraining.
   Entwurf: Variante A, 19.07.2026. Ersetzt .heroC und .tsb-heroC.
   Die FAQ nutzt bewusst .tsb-faq (Komponente der Startseite), deshalb
   ist .dxa-faq hier NICHT enthalten.
   ========================================================================== */
/* ==========================================================================
   [TSB-BLOCK:dxa-hero] Variante A "Der Hero verschwindet als Objekt"
   --------------------------------------------------------------------------
   Leitgedanke: Der Seitenanfang ist kein Element AUF der Seite, sondern das
   erste Band DER Seite. Kein Rahmen, kein Radius, kein Schatten, keine
   Hintergrundflaeche. Das Foto haengt am rechten Viewportrand und loest sich
   per Maske nach links und nach unten auf. Faellt das Foto weg, bleibt exakt
   dieselbe Typografie in denselben Abstaenden stehen. Genau das ist die
   Loesung fuer den gemeldeten Bruch: Seiten ohne Foto sind keine Ausnahme
   mehr, sondern der Normalfall derselben Komponente.

   Ausnahme von "nur var()": die Alpha-Stopps der CSS-Maske. Eine Maske
   arbeitet mit Deckkraft, nicht mit Farbe; `transparent`/`#000` sind dort
   Alphawerte und tragen keine Designentscheidung.
   ========================================================================== */

/* --- 1. Das Band ---------------------------------------------------------- */

.tsb .dxa-hero{
  position: relative;
  isolation: isolate;
  overflow: hidden;                 /* Maskenrand darf nie horizontal scrollen */
  background: var(--surface);
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding-top: var(--s-8);
  padding-bottom: var(--s-8);
}

/* Kein Trenner nach unten. Das naechste Band setzt nur den Abstand fort. */
.tsb .dxa-hero + .tsb-band{ border-top: 0 }

.tsb .dxa-hero-inner{
  position: relative;
  z-index: 1;
  padding-inline: var(--gutter);
}

/* --- 2. Das Foto ---------------------------------------------------------- */
/* Absolut am rechten Bandrand. Weil .tsb-band ueber die volle Breite laeuft,
   ist right:0 die Viewportkante. Kein 100vw-Trick, kein Overflow-Risiko.     */

.tsb .dxa-hero-media{
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: min(54%, 860px);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: 72% center;
  z-index: 0;
  pointer-events: none;

  /* Nach links ausblenden, nach unten ausblenden. Zwei Masken, verschnitten. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent 0, transparent 10%, #000 62%),
    linear-gradient(to top,  transparent 0, #000 34%);
  mask-image:
    linear-gradient(90deg, transparent 0, transparent 10%, #000 62%),
    linear-gradient(to top,  transparent 0, #000 34%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* --- 3. Typografie im Seitenanfang ---------------------------------------- */

.tsb .dxa-hero-text{
  max-width: var(--w-sub);
}

.tsb .dxa-h1{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-3xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--track-display);
  color: var(--ink);
  margin: 0 0 var(--s-4);
}

.tsb .dxa-sub{
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-base);
  color: var(--ink-body);
  margin: 0;
  max-width: var(--w-sub);
}
.tsb .dxa-sub strong{ color: var(--ink); font-weight: 700 }

.tsb .dxa-actions{
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-6);
}

/* --- 4. Kennzahlenzeile: Teil des Seitenanfangs, keine Karte -------------- */
/* Eine Haarlinie in Lesebreite ist Typografie, keine Kartenkante. Sie endet
   sichtbar innerhalb des Satzspiegels und liest sich deshalb nicht als Rahmen. */

.tsb .dxa-facts{
  list-style: none;
  margin: var(--s-8) 0 0;
  padding-top: var(--s-5);
  padding-bottom: 0;
  padding-inline: 0;
  max-width: min(100%, 640px);
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-5);
}

.tsb .dxa-facts b{
  display: block;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-2xl);
  line-height: var(--lh-1);
  letter-spacing: var(--track-tight);
  color: var(--ink);
}
.tsb .dxa-facts b.txt{ font-size: var(--fs-lg); line-height: var(--lh-flat) }
.tsb .dxa-facts b span{
  font-size: var(--fs-suffix);
  color: var(--accent);
  vertical-align: 0.35em;
  letter-spacing: var(--track-normal);
}
.tsb .dxa-facts small{
  display: block;
  margin-top: var(--s-2);
  font-family: var(--font-head);
  font-size: var(--fs-xs);
  line-height: var(--lh-flat);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--muted);
}

/* --- 5. Variante ohne Foto ------------------------------------------------ */
/* Nichts wird zurueckgenommen, es faellt nur das Bild weg. Deshalb passt die
   Komponente auf Portrait, Kontakt, Angebote, Camps und die Rechtsseiten.    */

.tsb .dxa-hero-plain .dxa-hero-text{ max-width: var(--w-read) }
.tsb .dxa-hero-plain .dxa-sub{ max-width: var(--w-read) }


/* ==========================================================================
   [TSB-BLOCK:dxa-einzeltraining] Abschnitte der Seite
   ========================================================================== */

/* --- 6. Ablauf: nummerierte Schritte mit Verbindungslinie ----------------- */

.tsb .dxa-steps{
  list-style: none;
  margin: 0;
  padding-top: 0;
  padding-bottom: 0;
  padding-inline: 0;
  display: grid;
  gap: var(--s-6);
}

.tsb .dxa-steps > li{
  display: grid;
  grid-template-columns: 44px 1fr;
  align-items: start;
  gap: var(--s-4);
}

.tsb .dxa-steps-n{
  position: relative;
  width: 44px;
  height: 44px;
  border-radius: var(--r-full);
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-md);
  line-height: var(--lh-1);
  display: grid;
  place-items: center;
}

/* Die Kette haelt die vier Schritte zusammen, ohne dass eine Karte noetig ist. */
.tsb .dxa-steps > li:not(:last-child) .dxa-steps-n::after{
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  width: 1px;
  height: calc(var(--s-6) + var(--s-1));
  background: var(--line);
}

.tsb .dxa-steps-b h3{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: var(--lh-flat);
  color: var(--ink);
  margin: var(--s-2) 0 var(--s-2);
}
.tsb .dxa-steps-b p{
  margin: 0;
  font-size: var(--fs-base);
  line-height: var(--lh-loose);
  color: var(--ink-body);
  max-width: var(--w-read);
}

/* --- 7. Fuer wen das passt ------------------------------------------------ */

.tsb .dxa-fit{
  display: grid;
  grid-template-columns: 1fr 1fr;     /* fest, kein auto-fit */
  gap: var(--s-7);
  align-items: start;
}

.tsb .dxa-fit-h{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: var(--lh-flat);
  color: var(--ink);
  margin: 0 0 var(--s-4);
}

.tsb .dxa-list{
  list-style: none;
  margin: 0;
  padding-top: 0;
  padding-bottom: 0;
  padding-inline: 0;
  max-width: var(--w-read);
}
.tsb .dxa-list li{
  position: relative;
  padding-left: var(--s-5);
  margin: 0 0 var(--s-3);
  font-size: var(--fs-base);
  line-height: var(--lh-loose);
  color: var(--ink-body);
}
.tsb .dxa-list li:last-child{ margin-bottom: 0 }

.tsb .dxa-list-yes li::before{
  content: "";
  position: absolute;
  left: 1px;
  top: 0.6em;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}
.tsb .dxa-list-no li::before{
  content: "";
  position: absolute;
  left: 1px;
  top: 0.85em;
  width: 12px;
  height: 2px;
  background: var(--muted);
}

/* --- 8. Trainer ----------------------------------------------------------- */

.tsb .dxa-trainer-q{
  margin: 0;
  border-left: var(--b-accent);
  padding-left: var(--s-5);
  font-size: var(--fs-md);
  line-height: var(--lh-loose);
  color: var(--ink-body);
  max-width: var(--w-read);
}

.tsb .dxa-creds{
  list-style: none;
  margin: var(--s-6) 0 0;
  padding-top: 0;
  padding-bottom: 0;
  padding-inline: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-7);
}
.tsb .dxa-creds b{
  display: block;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-xl);
  line-height: var(--lh-1);
  color: var(--ink);
}
.tsb .dxa-creds small{
  display: block;
  margin-top: var(--s-2);
  font-family: var(--font-head);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--muted);
}

.tsb .dxa-trainer-more{ margin: var(--s-6) 0 0 }
.tsb .dxa-trainer-more a{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.tsb .dxa-trainer-more a:hover{ text-decoration: none }

/* --- 9. Buchen ------------------------------------------------------------ */

.tsb .dxa-buy{
  display: grid;
  grid-template-columns: 1.35fr 1fr;   /* fest, kein auto-fit */
  gap: var(--s-7);
  align-items: start;
}

.tsb .dxa-buy-steps{
  margin: 0;
  padding-top: 0;
  padding-bottom: 0;
  padding-inline-start: var(--s-5);
  max-width: var(--w-read);
}
.tsb .dxa-buy-steps li{
  margin: 0 0 var(--s-4);
  font-size: var(--fs-base);
  line-height: var(--lh-loose);
  color: var(--ink-body);
}
.tsb .dxa-buy-steps li:last-child{ margin-bottom: 0 }
.tsb .dxa-buy-steps li::marker{
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--accent);
}
.tsb .dxa-buy-steps b{ color: var(--ink); font-weight: 700 }
.tsb .dxa-buy-steps a{ color: var(--accent); text-decoration: underline; text-underline-offset: 2px }

/* Seitenspalte ohne Flaeche und ohne Rahmen: nur eine Haarlinie als Zaesur. */
.tsb .dxa-buy-side{
  border-left: 1px solid var(--line);
  padding-left: var(--s-5);
}
.tsb .dxa-buy-price{ margin: 0 0 var(--s-4) }
.tsb .dxa-buy-price b{
  display: block;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-2xl);
  line-height: var(--lh-1);
  color: var(--ink);
}
.tsb .dxa-buy-price b span{
  font-size: var(--fs-suffix);
  color: var(--accent);
  vertical-align: 0.35em;
}
.tsb .dxa-buy-price small{
  display: block;
  margin-top: var(--s-2);
  font-family: var(--font-head);
  font-size: var(--fs-xs);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--muted);
}
.tsb .dxa-buy-alt{
  margin: var(--s-4) 0 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-loose);
  color: var(--muted);
}
.tsb .dxa-buy-alt a{ color: var(--accent); text-decoration: underline; text-underline-offset: 2px }

.tsb .dxa-note{
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  margin: var(--s-7) 0 0;
  padding-top: var(--s-5);
  padding-bottom: 0;
  border-top: 1px solid var(--line);
  max-width: var(--w-read);
  font-size: var(--fs-sm);
  line-height: var(--lh-loose);
  color: var(--muted);
}
.tsb .dxa-note svg{ flex: 0 0 auto; color: var(--accent); margin-top: 3px }


/* ==========================================================================
   [TSB-BLOCK:dxa-mq] Breakpoints 1200 / 1024 / 768 / 480
   ========================================================================== */

@media (max-width: 1200px){
  .tsb .dxa-hero-media{ width: min(50%, 720px) }
}

@media (max-width: 1024px){
  .tsb .dxa-hero{
    padding-top: var(--s-7);
    padding-bottom: var(--s-7);
  }
  .tsb .dxa-hero-media{
    width: 46%;
    background-position: 78% center;
  }
  .tsb .dxa-hero-text{ max-width: 30rem }

  .tsb .dxa-buy{ grid-template-columns: 1fr }
  .tsb .dxa-buy-side{
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-left: 0;
    padding-top: var(--s-5);
  }
}

@media (max-width: 768px){
  /* Das Foto wird zum randlosen Streifen unter dem Text. Oben ausgeblendet,
     damit auch hier keine Kante entsteht. Es bleibt Band, nie Karte.        */
  .tsb .dxa-hero{
    display: flex;
    flex-direction: column;
    padding-bottom: 0;
  }
  .tsb .dxa-hero-inner{ order: 1 }
  .tsb .dxa-hero-media{
    order: 2;
    position: relative;
    top: auto;
    bottom: auto;
    right: auto;
    width: 100%;
    height: 220px;
    margin-top: var(--s-6);
    background-position: center 32%;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 46%);
    mask-image: linear-gradient(to bottom, transparent 0, #000 46%);
    -webkit-mask-composite: source-over;
    mask-composite: add;
  }
  .tsb .dxa-hero-text{ max-width: none }
  .tsb .dxa-hero-plain{ padding-bottom: var(--s-7) }

  .tsb .dxa-facts{ max-width: none; gap: var(--s-4) }
  .tsb .dxa-facts b{ font-size: var(--fs-xl) }
  .tsb .dxa-facts b.txt{ font-size: var(--fs-base) }

  .tsb .dxa-fit{ grid-template-columns: 1fr; gap: var(--s-6) }
  .tsb .dxa-steps{ gap: var(--s-5) }
  .tsb .dxa-steps > li{ grid-template-columns: 38px 1fr; gap: var(--s-3) }
  .tsb .dxa-steps-n{ width: 38px; height: 38px; font-size: var(--fs-base) }
  .tsb .dxa-steps > li:not(:last-child) .dxa-steps-n::after{
    height: calc(var(--s-5) + var(--s-1));
  }
  .tsb .dxa-creds{ gap: var(--s-6) }
}

@media (max-width: 480px){
  /* Unter 480px traegt das Foto nichts mehr bei und wuerde nur Hoehe kosten.
     Der Seitenanfang faellt auf die fotolose Variante zurueck, also genau auf
     das, was Kontakt oder Portrait ohnehin zeigen. Kein Sonderfall.          */
  .tsb .dxa-hero-media{ display: none }
  .tsb .dxa-hero{ padding-bottom: var(--s-7) }

  .tsb .dxa-facts{
    grid-template-columns: 1fr;
    gap: var(--s-3);
  }
  .tsb .dxa-facts li{
    display: flex;
    align-items: baseline;
    gap: var(--s-3);
  }
  .tsb .dxa-facts b,
  .tsb .dxa-facts b.txt{ font-size: var(--fs-lg) }
  .tsb .dxa-facts small{ margin-top: 0 }

  .tsb .dxa-actions{ gap: var(--s-2) }
  .tsb .dxa-actions .tsb-btn{ width: 100% }
  .tsb .dxa-creds{ gap: var(--s-5) }
  .tsb .dxa-trainer-q{ padding-left: var(--s-4) }
}/* ===== TSB-BLOCK:hero-platzhalter START =====
   Derzeit KEINE Platzhalter-Markierung. Der Block bleibt als Notiz stehen,
   falls wieder ein Hero ohne eigenes Foto auskommen muss.

   Damals verwendet: .dxa-hero-media--ph (filter: saturate(.45) brightness(.92))
   plus ein Schild .dxa-ph-mark. Wichtig dabei: das Schild muss GESCHWISTER von
   .dxa-hero-media sein, nicht dessen Kind - das Foto traegt eine Maske, und eine
   Maske blendet ihre Kinder mit aus.
   ========================================================================== */
/* ===== TSB-BLOCK:hero-platzhalter END ===== */

/* ===== TSB-BLOCK:kopf-zentriert START =====
   .bt ist display:flex, deshalb reicht das text-align aus
   .tsb-shortcode-head--center nicht aus, um die Ueberschrift zu zentrieren.
   Die Startseite loest das inline; hier als Regel, damit es jede Seite erbt.
   ========================================================================== */
.tsb .tsb-shortcode-head--center .bt{ justify-content: center }
/* ===== TSB-BLOCK:kopf-zentriert END ===== */

/* ===== TSB-BLOCK:hero-dxa END ===== */







/* ===== TSB-BLOCK:back-to-top START — nicht von Hand bearbeiten, Quelle:
        scripts/backtotop-2026-07-21/abschnitt-34.css ===== */
/* ------------------------------- 34. Zurück-nach-oben-Knopf [TSB-BLOCK:back-to-top] */
/*
   Der Knopf kommt aus dem Theme (`header.php`, `#mkd-back-to-top`) und war der einzige
   scharfkantige Baustein auf einer Seite, deren Karten, Felder und Buttons durchgehend
   Radien tragen. Hier bekommt er die Form des Designsystems - Farbe und Position bleiben,
   damit ein Hilfselement ein Hilfselement bleibt und nicht mit den Handlungsknöpfen
   konkurriert.

   Das Pfeil-Zeichen selbst wird NICHT hier repariert, sondern in `tsb-fonts.php`: der Knopf
   zeigte bis zum 21.07. eine nackte "2", weil eine zu breite Schriftregel dem ElegantIcons-
   Glyph seine Icon-Schrift nahm (`.arrow_carrot-up:before{content:"\32"}`). Das weiche
   Scrollen liegt in `tsb-back-to-top.php`.
*/
#mkd-back-to-top{
  border-radius: var(--r-md);
  box-shadow: var(--sh-card);
  overflow: hidden;                        /* sonst stehen die Ecken des Innen-Spans über */
  transition: transform var(--t-fast), box-shadow var(--t-base);
}
#mkd-back-to-top > span{
  border-radius: inherit;
}
#mkd-back-to-top:hover{
  transform: translateY(-2px);
  box-shadow: var(--sh-lift);
}
@media (prefers-reduced-motion: reduce){
  #mkd-back-to-top{ transition: none }
  #mkd-back-to-top:hover{ transform: none }
}
/* ===== TSB-BLOCK:back-to-top END ===== */

/* ===== TSB-BLOCK:catering START — nicht von Hand bearbeiten, Quelle:
        scripts/catering-2026-07-21/abschnitt-35.css ===== */
/* ------------------------------- 35. Catering-Partner [TSB-BLOCK:catering] */
/*
   Baustein auf der Kindergeburtstagsseite, gefüllt über Einstellungen → Catering-Partner
   (mu-plugin `tsb-catering.php`). Solange kein Partner gepflegt ist, gibt der Shortcode
   nichts aus - dieses CSS ist dann wirkungslos, aber harmlos.

   BEWUSST OHNE ABSCHNITTSZIFFER: die Seite zählt ihre Bänder (01 … 04). Eine Ziffer hier
   hinterließe im leeren Zustand eine Lücke in der Zählung.

   Das Band selbst (Hintergrund, vertikale Polsterung) kommt von der `vc_row` mit
   `el_class="tsb-band tsb-band-alt"` - NICHT von diesem Abschnitt. Grund: ein Shortcode
   darf nicht von einem raw-Block umschlossen werden, WPBakery zieht das Wrapper-Div sonst
   zwischen Bandkopf und Inhalt (dreimal erlebt, siehe CLAUDE.md).
*/
.tsb-catering__titel{
  font-size: var(--fs-2xl);
  line-height: var(--lh-flat);
  letter-spacing: var(--track-tight);
  color: var(--ink);
  margin-top: var(--s-2);
  margin-bottom: var(--s-5);
}

.tsb-catering__karte{
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: var(--s-6);
  align-items: center;
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-card);
  padding-top: var(--s-6);
  padding-bottom: var(--s-6);
  padding-inline: var(--s-6);
}

/* Feste Bühne fürs Logo: fremde Logos kommen in jedem Seitenverhältnis, ohne feste
   Höhe springt die Karte je nach Datei. Vorbild ist die Partner-Logoleiste. */
.tsb-catering__logo{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
}
.tsb-catering__logo img{
  max-width: 100%;
  max-height: 120px;
  width: auto;
  height: auto;
  object-fit: contain;
}

.tsb-catering__lead{
  font-size: var(--fs-md);
  line-height: var(--lh-base);
  color: var(--ink-body);
  margin-top: 0;
  margin-bottom: var(--s-4);
}

.tsb-catering__liste{
  list-style: none;
  margin: 0 0 var(--s-5);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--s-2) var(--s-5);
}
.tsb-catering__liste li{
  position: relative;
  padding-left: var(--s-5);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink-body);
}
/* Häkchen als Pseudoelement statt als Zeichen im Text: der Punkt bleibt so kopierbar
   und der Screenreader liest keine Dekoration mit. */
.tsb-catering__liste li::before{
  content: "";
  position: absolute;
  left: 0;
  top: .55em;
  width: 11px;
  height: 6px;
  border-left: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(-45deg);
}

.tsb-catering__wege{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-4);
  margin-top: 0;
  margin-bottom: 0;
}
.tsb-catering__kontakt{
  font-size: var(--fs-base);
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.tsb-catering__hinweis{
  margin-top: var(--s-4);
  margin-bottom: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
}

/* Unter 768px untereinander. Die Bruchstelle liegt bewusst hier und nicht tiefer:
   200px Logospalte + 220px Mindestbreite der Listenspalte + Abstände brauchen mehr
   Platz, als ein Tablet quer im Inhaltsbereich übrig lässt. */
@media (max-width: 768px){
  .tsb-catering__karte{
    grid-template-columns: 1fr;
    gap: var(--s-5);
    padding-inline: var(--s-5);
  }
  .tsb-catering__logo{
    justify-content: flex-start;
    min-height: 0;
  }
  .tsb-catering__logo img{ max-height: 92px }
  .tsb-catering__titel{ font-size: var(--fs-xl) }
}
/* ===== TSB-BLOCK:catering END ===== */


/* ===== TSB-BLOCK:hinweis START — nicht von Hand bearbeiten, Quelle:
        scripts/hinweise-2026-07-21/abschnitt-36.css ===== */
/* ---------------------------- 36. Hinweisbloecke vereinheitlicht  [TSB-BLOCK:hinweis]
 *
 * Bis 21.07. gab es ZWEI fast gleiche Komponenten fuer dieselbe Rolle
 * ("kleiner grauer Hinweis zu Storno/Frist"):
 *
 *   .tsb-storno  (Abschnitt 20) Tagescamp, Kindergeburtstag, BSA
 *                13,76px Lato, Rahmen + Info-Icon, margin-bottom:0
 *   .tsb-hinweis (Abschnitt 12) Einzeltraining, Bonuskarte, Buchungsbereich
 *                14px Titillium, ohne Rahmen, ohne Icon, margin-top:0
 *
 * Gemessen am 21.07. auf Staging, jeder Punkt mit Screenshot belegt:
 *   - .tsb-hinweis hatte OBEN 0px Luft und klebte an der Unterkante des
 *     Kaufblocks (margin-top fehlte in der Regel schlicht).
 *   - .tsb-storno hatte UNTEN 0px Luft und lag auf der Formularkarte auf;
 *     zwei gerundete Kaesten, die sich beruehren.
 *   - .tsb-hinweis lag ausserhalb von .tsb-inner und war deshalb 1300px
 *     statt 1100px breit, ragte also ueber allen anderen Inhalt hinaus.
 *   - Auf der Bonuskarte war seine Flaeche #f4f6f4 = exakt die Bandfarbe.
 *     Ohne Rahmen war der Kasten dort unsichtbar.
 *
 * 14px und 13,76px liegen um Faktor 1,017 auseinander - nach der Regel
 * "weniger als Faktor 1,12 ist EIN Token" sind das keine zwei Groessen.
 * Deshalb hier eine Komponente fuer beide Klassen. Das Markup der drei
 * Storno-Seiten bleibt unveraendert (es passt bereits), geaendert wird nur
 * die Ausgabe von [tsb_stornofrist] in tsb-guthaben/inc/frontend.php.
 *
 * Zur Spezifitaet: Abschnitt 20 adressiert ".tsb .tsb-storno" (0,2,0). Ein
 * blosses ".tsb-storno" (0,1,0) wuerde dagegen verlieren, obwohl es spaeter
 * steht. Deshalb ist jede Variante einzeln aufgefuehrt.
 * ------------------------------------------------------------------------- */

.tsb .tsb-storno,
.tsb .tsb-hinweis,
.tsb .tsb-buchung__hinweis,
.tsb-storno,
.tsb-hinweis,
.tsb-buchung__hinweis{
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;

  /* Volle Breite des umgebenden .tsb-inner (Kundenentscheidung 21.07.2026).
     Vorher stand hier max-width:64ch - das ergab 520px von 1100px, also knapp
     die halbe Flaeche, und der Kasten wurde dadurch unnoetig hoch (4 Zeilen
     statt 2). Der Bestand hatte dasselbe Problem schon: .tsb-storno lief auf
     593px. Vertretbar, weil hier KEIN Lesetext steht, sondern zwei bis drei
     Saetze - die 64ch-Regel gilt fuer Fliesstext, nicht fuer Hinweiskaesten.
     Die Breite kommt jetzt allein vom Container; auf den Anfrageseiten liegt
     der Kasten damit buendig auf der Formularkarte darunter. */
  max-width: none;

  /* Der eigentliche Befund. Einzeln gesetzt, nie als margin-Kurzschreibweise:
     eine Media-Query hat hier schon einmal bei gleicher Spezifitaet still
     ein padding-top ueberschrieben. */
  margin-top: var(--s-5);
  margin-bottom: var(--s-5);

  padding-top: var(--s-4);
  padding-bottom: var(--s-4);
  padding-left: var(--s-4);
  padding-right: var(--s-4);

  background: var(--surface-alt);
  border: var(--b-hair);        /* traegt den Kasten auch auf dem grauen Band */
  border-radius: var(--r-md);

  /* Vollstaendig gesetzt, weil dieser Block auch AUSSERHALB von .tsb stehen
     kann. Dort gilt sonst body{font-size:15px;line-height:1.66667em} - und
     dieses em vererbt als LAENGE (25px), nicht als Faktor.
     Der generische Fallback am Ende ist Pflicht: ohne ihn rendert eine
     fehlende Schrift in Times, nicht im System-Sans. */
  font-family: 'Lato', sans-serif;
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  font-weight: 400;
  color: var(--muted);
}

/* Der Text liegt je nach Herkunft im Element selbst oder in einem <p> darin.
   Beide Formen sollen gleich aussehen, deshalb erbt das <p> nur. */
.tsb .tsb-storno > p,
.tsb .tsb-hinweis > p,
.tsb .tsb-buchung__hinweis > p,
.tsb-storno > p,
.tsb-hinweis > p,
.tsb-buchung__hinweis > p{
  margin: 0;
  font: inherit;
  color: inherit;
}

.tsb .tsb-storno > svg,
.tsb .tsb-hinweis > svg,
.tsb .tsb-buchung__hinweis > svg,
.tsb-storno > svg,
.tsb-hinweis > svg,
.tsb-buchung__hinweis > svg{
  flex: 0 0 auto;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  color: var(--accent);
}

.tsb .tsb-storno strong,
.tsb .tsb-hinweis strong,
.tsb .tsb-buchung__hinweis strong,
.tsb-storno strong,
.tsb-hinweis strong,
.tsb-buchung__hinweis strong{
  color: var(--ink-body);
  font-weight: 700;
}
/* ===== TSB-BLOCK:hinweis END ===== */

/* ===== 37. Schlussabsatz nach dem Highlight-Raster [TSB-BLOCK:lead-breit] ===== */
/* ===== TSB-BLOCK:lead-breit START ===== */
/*
  .tsb-lead traegt site-weit max-width:64ch (gemessen 606px). Fuer eine
  Einleitung UNTER einer Ueberschrift ist das richtig - dort steht der Text
  bewusst in Lesebreite.

  Der ABSCHLIESSENDE Absatz nach einem .tsb-hl-Raster wirkt damit aber halb
  leer: 606px Text in einem 1100px breiten Container, die rechte Haelfte
  bleibt weiss. Auffaellig wird das erst ab ~1024px; bei 768px fuellt der
  Text den Container ohnehin (606 von 724px).

  Aufgehoben wird deshalb nur diese eine Stellung. Der Selektor trifft
  site-weit genau zwei Absaetze (/camps/ und /angebote-und-preise/, am
  21.07.2026 im Browser gegengeprueft) - kein HTML-Eingriff noetig, damit
  allein ueber diesen Block rollbackbar.

  Die groessere Zeilenhoehe faengt die laengeren Zeilen ab: bei voller Breite
  sind es rund 125 statt 67 Zeichen, und mehr Durchschuss haelt das Auge
  beim Zeilenwechsel in der Spur.
*/
.tsb .tsb-hl + .tsb-lead{
  max-width: none;
  line-height: var(--lh-loose);
}
/* ===== TSB-BLOCK:lead-breit END ===== */



/* ===== TSB-BLOCK:warenkorb-mobil START — nicht von Hand bearbeiten, Quelle:
        scripts/kaufwege-2026-07-21/abschnitt-33.css ===== */
/* ------------------------------- 33. Warenkorb auf dem Handy [TSB-BLOCK:warenkorb-mobil] */
/*
   BEFUND (21.07., gemessen bei 320/390/430/768px):
   Die Warenkorbtabelle braucht bei 390px Fensterbreite 382px, der Container gibt ihr 358px.
   Sie ragt also 8px ueber den rechten Rand, die Spalte "Zwischensumme" ist angeschnitten.
   `body{overflow-x:hidden}` versteckt das - die Seite scrollt NICHT horizontal, im Screenshot
   sieht man nur das abgeschnittene Wort. Gemessen wurde deshalb per getBoundingClientRect()
   gegen den Viewport, nicht per scrollWidth.

   Treiber der 382px sind zwei Spalten, die nicht schmaler koennen:
     "Zwischensumme" als Kopfzelle  113px  (ein Wort, kein Umbruchpunkt)
     Mengensteuerung               93px
   Dazu 24 + 95 + 55 fuer Entfernen, Name, Preis.

   WARUM NICHT einfach eine Spalte ausblenden:
   Trophy versucht das bereits - `woocommerce-responsive.min.css` blendet ab 768px das
   Vorschaubild aus, kuerzt ab 600px die Polsterung auf 3px und schrumpft ab 480px den
   Entfernen-Knopf auf 20px. Die Tabelle bleibt trotzdem zu breit. Weiter quetschen heisst
   nur, die naechste Spalte zu opfern.

   WooCommerce liefert fuer genau diesen Fall `shop_table_responsive` samt `data-title` an
   jeder Zelle - aber das zugehoerige `woocommerce-smallscreen.css` wird gar nicht geladen,
   Trophy ersetzt Woos Stylesheets durch eigene. Die Klasse und die Beschriftungen sind da,
   nur die Regeln fehlen. Dieser Abschnitt liefert sie nach, im eigenen Designsystem.

   ERGEBNIS: unter 600px wird jede Zeile eine Karte. Bild und Name oben, darunter Preis,
   Anzahl und Zwischensumme je als Zeile mit Beschriftung links und Wert rechts.
   Nichts wird abgeschnitten, keine Angabe entfaellt.

   ZWEI FALLEN, die hier bewusst adressiert sind:
   (a) Das Raster braucht ALLE vier Tabellenebenen (table, thead, tbody, tr) auf block/grid.
       Bleibt eine stehen, baut der Browser anonyme Tabellenboxen um die Zellen und
       `grid-area` greift nicht - sichtbar wird das erst im Bild, die Messwerte sind gruen.
   (b) Trophy blendet `td.product-thumbnail` ab 768px per `display:none` aus (0,4,3).
       Die Kette hier ist (0,6,4) und holt das Bild gezielt zurueck.
*/
@media only screen and (max-width: 600px){

  /* --- Tabellenlayout aufloesen ----------------------------------------- */
  body.woocommerce-page .mkd-content .woocommerce table.cart,
  body.woocommerce-page .mkd-content .woocommerce table.cart tbody{
    display: block;
    width: 100%;
    border-width: 0;
  }
  /* Die Kopfzeile entfaellt - ihre Beschriftungen wandern vor die Werte. */
  body.woocommerce-page .mkd-content .woocommerce table.cart thead{ display: none }

  /* --- Eine Zeile = eine Karte ------------------------------------------ */
  /*
     Die Zellen stehen im HTML in der Reihenfolge entfernen, bild, name, preis, anzahl,
     summe. Ueber benannte Rasterfelder werden sie umsortiert, ohne das Markup anzufassen.
  */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item{
    display: grid;
    grid-template-columns: 60px 1fr 24px;
    grid-template-areas:
      "bild   name   entfernen"
      "preis  preis  preis"
      "anzahl anzahl anzahl"
      "summe  summe  summe";
    column-gap: var(--s-3);
    align-items: center;
    border: var(--b-hair);
    border-radius: var(--r-md);
    padding-top: var(--s-4);
    padding-bottom: var(--s-2);
    padding-inline: var(--s-4);
    margin-bottom: var(--s-4);
  }

  /* Grundzustand aller Zellen: kein Tabellenrest mehr. */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item > td{
    display: block;
    width: auto;
    max-width: none;
    border-width: 0;
    text-align: left;
    padding-top: var(--s-2);
    padding-bottom: var(--s-2);
    padding-inline: 0;
  }

  /* --- Kopf der Karte: Bild, Name, Entfernen ----------------------------- */
  /* (b) holt das vom Theme ausgeblendete Vorschaubild zurueck. */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-thumbnail{
    grid-area: bild;
    display: block;
    padding-top: 0;
    padding-bottom: 0;
  }
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-thumbnail img{
    display: block;
    width: 60px;
    height: auto;
    max-width: none;
    border-radius: var(--r-sm);
  }
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-name{
    grid-area: name;
    font-family: var(--font-head);
    font-size: var(--fs-base);
    font-weight: 600;
    line-height: var(--lh-flat);
    color: var(--ink);
  }
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-name a{
    color: var(--ink);
  }
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-remove{
    grid-area: entfernen;
    width: 24px;
    text-align: right;
    padding-top: 0;
    padding-bottom: 0;
  }

  /* --- Werte-Zeilen: Beschriftung links, Wert rechts --------------------- */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-price{  grid-area: preis }
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-quantity{ grid-area: anzahl }
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-subtotal{ grid-area: summe }

  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item
    > td:is(.product-price, .product-quantity, .product-subtotal){
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s-3);
    border-top: var(--b-hair);
    margin-top: var(--s-2);
  }
  /*
     Die Beschriftung kommt aus `data-title`, das WooCommerce ohnehin setzt. Bewusst NICHT
     an td.product-name - dort stuende "Produkt" ueber dem Produktnamen.
  */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item
    > td:is(.product-price, .product-quantity, .product-subtotal)::before{
    content: attr(data-title);
    flex: 0 0 auto;
    font-family: var(--font-body);
    font-size: var(--fs-sm);
    font-weight: 400;
    color: var(--muted);
  }
  /* Die Zwischensumme ist der Wert, auf den es ankommt - sie darf kraeftiger stehen. */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-subtotal{
    font-weight: 700;
    color: var(--ink);
  }

  /* Die Mengensteuerung braucht in der Flex-Zeile keine eigene Ausrichtung mehr. */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item td.product-quantity .quantity{
    margin: 0;
  }
  /*
     Trophy blendet die Plus-/Minus-Pfeile unter 600px aus (`... td .mkd-quantity-buttons>span
     {display:none}`, 0,4,4) - in der gequetschten Tabelle war dafuer kein Platz. In der Karte
     ist er da, und ohne die Pfeile bliebe auf dem Handy nur "Zahl eintippen und aktualisieren".
     Diese Kette ist (0,7,5) und holt sie zurueck.
  */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item
    td.product-quantity .mkd-quantity-buttons > span{
    display: inline-block;
  }
  /*
     ...und dann muss der Platz fuer sie auch da sein. Trophy positioniert die beiden Pfeile
     ABSOLUT und reserviert ihre Breite ueber den Seitenrand des Eingabefelds: 32px auf dem
     Desktop (= Pfeilbreite, passt genau), aber `margin:0 10px` unter 600px - dort waren die
     Pfeile ja ausgeblendet. Ohne diese Zeile lagen sie auf dem Feld und es entstand ein
     doppelter, versetzter Rahmen. Im Messwert faellt das nicht auf, nur im Bild.
  */
  body.woocommerce-page .mkd-content .woocommerce table.cart tr.cart_item
    td.product-quantity .mkd-quantity-buttons > input.mkd-quantity-input{
    margin-inline: 32px;
  }

  /* --- Die Aktionszeile (Gutschein, Aktualisieren) ----------------------- */
  /*
     Sie ist keine cart_item-Zeile und bleibt eine schlichte Blockzeile. Ohne diese
     Regel baut der Browser um ihr td eine anonyme Tabellenbox im Block-tbody.
  */
  body.woocommerce-page .mkd-content .woocommerce table.cart > tbody > tr:not(.cart_item){
    display: block;
  }
  body.woocommerce-page .mkd-content .woocommerce table.cart td.actions{
    display: block;
    width: auto;
    border-width: 0;
    padding-inline: 0;
  }
}

/* ---------------------------------------------------------------------------
   Die Summen-Box (ANHANG-SUMMENBOX, 22.07.2026)

   BEFUND: Auf einem 390px-Bildschirm war die Tabelle in `.cart_totals` **392px** breit
   und ragte damit ueber den Bildschirmrand hinaus - sichtbar daran, dass
   "Versandkostenpauschale: 2,00 EUR" rechts an der Kante klebte.
   Gemessen (`scripts/warenkorb-2026-07-22/summenbox-ursache.cjs`): Innenraum der Box
   358 - 2x32 Innenabstand - 2x1 Rahmen = 292px, die Tabelle brauchte aber 344px.

   ZWEI URSACHEN, beide muessen weg:
   1. Der Innenabstand der Box (`--s-6` = 32px je Seite) ist auf dem Handy zu grosszuegig,
      dazu kommen 18px in jeder Zelle - zusammen 100px allein fuer Luft.
   2. "Versandkostenpauschale:" ist EIN Wort von ~175px. Ohne Umbrucherlaubnis ist das die
      Mindestbreite der Spalte, egal wie schmal der Bildschirm ist.

   SPEZIFITAET: Die Zellenwerte kommen aus `woocommerce-responsive.min.css`
   `.mkd-woocommerce-page .cart-collaterals table td` (0,3,1) - ebenfalls in einer
   600px-Abfrage. Eine blosse Klasse verliert dagegen, also wird die Kette gespiegelt.
   Links und rechts einzeln setzen, nie die Kurzschreibweise (siehe CLAUDE.md).
   --------------------------------------------------------------------------- */
@media only screen and (max-width: 600px){
  .woocommerce .cart-collaterals .cart_totals{
    padding-left:  var(--s-4);
    padding-right: var(--s-4);
  }
  .mkd-woocommerce-page .cart-collaterals table td,
  .mkd-woocommerce-page .cart-collaterals table th{
    padding-left:  var(--s-3);
    padding-right: var(--s-3);
    /* Erlaubt den Umbruch im langen Wort - sonst bleibt die Spalte 175px breit. */
    overflow-wrap: break-word;
  }
}
/* ===== TSB-BLOCK:warenkorb-mobil END ===== */

/* ===== TSB-BLOCK:warenkorb-auto START — nicht von Hand bearbeiten, Quelle:
        scripts/warenkorb-2026-07-22/abschnitt-38.css ===== */
/* ------------------------------- 38. Warenkorb rechnet selbst nach [TSB-BLOCK:warenkorb-auto]

   Gehoert zu mu-plugin `tsb-cart-auto-update.php`. Die Klasse `tsb-cart-auto` setzt
   dessen Skript selbst an den <body> - und zwar erst, nachdem feststeht, dass Woos
   cart.js vorhanden ist. Ohne JavaScript traegt der Body die Klasse nicht, dann bleibt
   der Knopf sichtbar und der Warenkorb bedienbar. Deshalb haengt hier alles an ihr.        */

/* Der Knopf bleibt im Formular stehen (das Skript betaetigt ihn), er wird nur unsichtbar.
   `visibility` statt `display` waere falsch - er wuerde weiter Platz belegen.
   Woo/Trophy faerben den Knopf ueber `.woocommerce table.cart td.actions .button`,
   das ist spezifischer als eine einzelne Klasse - daher die Kette mit dem Body.        */
body.tsb-cart-auto .woocommerce-cart-form td.actions button[name="update_cart"],
body.tsb-cart-auto .woocommerce-cart-form td.actions input[name="update_cart"],
body.tsb-cart-auto .woocommerce-cart-form button[name="update_cart"],
body.tsb-cart-auto .woocommerce-cart-form input[name="update_cart"]{
  display: none !important;
}

/* Die Statuszeile ersetzt die gruene Meldungsbox, zu der Woo sonst hochscrollen wuerde.
   Sie steht direkt unter der Tabelle, ist `role="status"` und wird deshalb vorgelesen.  */
.tsb-cart-status{
  margin-top:    var(--s-3);
  margin-bottom: 0;
  font-size:     var(--fs-sm);
  line-height:   var(--lh-base);     /* das Theme vererbt line-height als LAENGE (25px) */
  color:         var(--muted);
  display:       flex;
  align-items:   center;
  gap:           var(--s-2);
}

/* Solange nichts zu melden ist, soll die Zeile keinen Platz kosten. */
.tsb-cart-status:empty{
  display: none;
}

/* Ein ruhiger Punkt in Markengruen als Anker fuers Auge - kein Spinner, keine Bewegung:
   das Formular ist waehrenddessen ohnehin von Woo verdeckt.                            */
.tsb-cart-status::before{
  content:       "";
  width:         8px;
  height:        8px;
  flex:          0 0 8px;
  border-radius: var(--r-full);
  background:    var(--accent);
}
/* ===== TSB-BLOCK:warenkorb-auto END ===== */




/* ===== TSB-BLOCK:cookie-mobil START ===== */
/* 40. Cookie-Hinweis auf dem Handy  [TSB-BLOCK:cookie-mobil]
   ------------------------------------------------------------------
   Gemessener Ist-Zustand 22.07. bei 390px, frischer Kontext ohne Consent:
   `div#fhw_cookiehinweis`, position:fixed, z-index 9999, 390x200px ab y=644,
   auf allen 23 Seiten. Es ist ein EINSPALTIGES Raster
   (`grid-template-columns:358px`, `grid-template-rows:63px 44px 44px`), deshalb
   stehen die beiden Knoepfe untereinander und das Band wird 200px hoch. Beide
   Knoepfe sind bereits 44px hoch, an ihnen liegt es nicht.

   Verdeckt sind dadurch auf fuenf Angebotsseiten die Kennzahlen direkt unter dem
   Seitenanfang. Auf /angebote-und-preise/ nachgemessen: "ohne", "Mitgliedschaft",
   "12", "Monate Guthaben", "1:1" - also genau die Preis- und Leistungszeile.

   Das Band gehoert dem Plugin DSGVO-Cookie-Hinweis. Seine Masse gehoeren deshalb
   hierher und NICHT in die Plugin-Einstellungen, sonst ist die Entscheidung beim
   naechsten Update weg.

   Das Element traegt ein Inline-`style="bottom:25px; background:#fff; display:grid"`
   und seine Knoepfe Inline-`margin`/`background`/`color` (Spezifitaet 1,0,0,0).
   Was dort steht, ist nur mit `!important` zu erreichen - hier bewusst und begrenzt
   auf die Marginwerte.

   NICHT hier geloest: der Knopf "Nach oben" liegt unter dem Band. Ursache ist ein
   Stapelkontext, nicht die Bandhoehe (`.mkd-wrapper{position:relative;z-index:1000}`
   enthaelt `#mkd-back-to-top` mit z-index 10001 - effektiv treten 1000 gegen 9999 an,
   deshalb gewinnt das Band mit der kleineren Zahl). Wer am z-index des Knopfes dreht,
   wundert sich, dass nichts passiert. Das gehoert zu Abschnitt 42, wo der Knopf
   ohnehin angefasst wird.

   OFFEN, weil CSS es nicht kann: `role="dialog"` und `aria-label` am Band. Braucht
   einen Filter im mu-plugin, steht in Stufe 7.
   ------------------------------------------------------------------ */

@media (max-width: 768px) {
  #fhw_cookiehinweis {
    /* zwei Spalten: der Text spannt beide, die Knoepfe teilen sich die Zeile.
       Die Zeilen MUESSEN mitgesetzt werden: eine Bestandsregel gibt drei Zeilen vor,
       und die dritte blieb nach dem Umbau als leere 0px-Zeile stehen - kostete
       zusammen mit ihrem Abstand 12px, gemessen 160px statt 148px. */
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto;
    gap: var(--s-3) var(--s-3);
    padding-top:    var(--s-3);
    padding-bottom: var(--s-3);
    padding-left:   var(--s-4);
    padding-right:  var(--s-4);
    align-items: center;
  }
  #fhw_cookiehinweis > p {
    grid-column: 1 / -1;
    margin: 0;
    font-size: var(--fs-sm);
    /* Das Theme vererbt `line-height:1.66667em` als LAENGE (25px). Als Faktor
       spart derselbe Text sichtbar Hoehe, ohne dass ein Wort entfaellt. */
    line-height: var(--lh-base);
  }
  /* Die Inline-Margins (30px links und rechts) zwingen den Knopf in die Mitte
     seiner Spalte und verhindern gleich breite Knoepfe. */
  #fhw_cookiehinweis > button.mainbutton,
  #fhw_cookiehinweis > form {
    margin: 0 !important;
    width: 100%;
    min-height: var(--s-7);
  }
  #fhw_cookiehinweis > form > button.privacybutton {
    width: 100%;
    min-height: var(--s-7);
  }
  #fhw_cookiehinweis button {
    font-size: var(--fs-sm);
    line-height: var(--lh-1);
    border-radius: var(--r-sm);
  }
}
/* ===== TSB-BLOCK:cookie-mobil END ===== */

/* ===== TSB-BLOCK:seitenanfang START ===== */
/* 41. Seitenanfang und Seitenrand  [TSB-BLOCK:seitenanfang]
   ------------------------------------------------------------------
   Zwei Bestandsregeln haengen an Klassen statt an Bedingungen und greifen deshalb
   an den falschen Stellen. Beide sind am 22.07. im DOM nachgemessen.

   (a) Die Regel weiter oben in dieser Datei

           .tsb .mkd-container-inner,
           .tsb-legal .mkd-container-inner{ padding-top: 0 }

       kann NIE greifen. Sie verlangt, dass `.mkd-container-inner` INNERHALB von
       `.tsb` liegt. Tatsaechlich ist es umgekehrt: `.tsb` liegt im Container.
       Gemessen ueber 19 Seiten ist `container.closest('.tsb')` ausnahmslos false
       und `container.querySelector('.tsb')` auf den betroffenen Seiten true.
       Richtig ist deshalb `:has()`.

       Wirkung: 66px toter Weissraum unter dem Kopf auf **15** Seiten. Das Konzept
       nannte 11; nachgezaehlt sind es 12 mit `.tsb` (die 9 Angebotsseiten plus
       aktuelles, termine, mein-konto) und 3 mit `.tsb-legal` (agbs, impressum,
       datenschutz). Auf aktuelles, termine und mein-konto ist der Inhaltscontainer
       nicht der erste im Dokument - wer nur `querySelector` nimmt, zaehlt sie nicht mit.

       `:has(.tsb)` ist trennscharf nachgemessen: true auf genau den 66px-Containern,
       false auf dem 75px-Container (Fusszeilenbereich, 607px hoch, auf JEDER Seite)
       und false auf dem 80px-Container des Shops. Die alte Regel wird an ihrer
       Stelle entfernt, nicht hier danebengestellt - sonst bleibt eine tote Regel
       stehen, die beim naechsten Mal wieder wie eine Loesung aussieht.

   (b) Der Seitenrand fehlt auf /kontakt/ vollstaendig. Abschnitt 3 setzt unter 768px
       `.tsb-inner{padding-inline:0!important}`, weil der Gutter sonst doppelt kaeme.
       Die Ausnahme in 24.1 haengt aber an `.tsb-start`, und /kontakt/ traegt diese
       Klasse nicht, obwohl die Seite wie Startseite und Portrait
       `page-template-full-width` ist und damit ausserhalb von `.mkd-container-inner`
       liegt. Gemessen: beide `.tsb-inner` dort mit `padding-left:0`, und Kicker
       ("Du hast Fragen?"), H2 ("Dann bist du hier richtig"), Leadzeile und die
       Kontaktliste beginnen bei **x=0**. Startseite und Portrait haben korrekt 16px.

       Der Selektor haengt deshalb an der Vorlage, nicht an einer Inhaltsklasse.
       Er umfasst die `.tsb-start`-Ausnahme aus 24.1 vollstaendig; jene wird dadurch
       redundant, bleibt aber stehen, weil sie nicht falsch ist und ein zweiter
       Eingriff in einen Bestandsabschnitt kein Risiko wert ist.

   Das `!important` ist Pflicht, weil Abschnitt 3 `padding-inline:0!important` setzt.
   Spezifitaet (0,2,1) gegen (0,1,0) reicht.
   ------------------------------------------------------------------ */

/* Die Theme-Kette muss GESPIEGELT werden, sonst ist die Regel zwar richtig und wird
   ausgeliefert, trifft aber nicht. Am 22.07. genau so passiert und per CDP
   `CSS.getMatchedStylesForNode` aufgeklaert: der 66px-Wert kommt aus

       .mkd-content .mkd-content-inner > .mkd-container > .mkd-container-inner

   mit Spezifitaet (0,4,0), zweimal ausgeliefert (Stylesheet 19 und 22). Die erste
   Fassung dieser Regel hatte (0,3,0) und verlor, obwohl `matches()` true meldete.
   Mit der vollen Kette sind es (0,5,0). */
.mkd-content .mkd-content-inner > .mkd-container > .mkd-container-inner:has(.tsb),
.mkd-content .mkd-content-inner > .mkd-container > .mkd-container-inner:has(.tsb-legal) {
  padding-top: 0;
}

@media (max-width: 768px) {
  body.page-template-full-width .tsb-inner {
    padding-inline: var(--gutter) !important;
  }
}
/* ===== TSB-BLOCK:seitenanfang END ===== */






/* ===== TSB-BLOCK:touch START ===== */
/* 42. Was der Daumen erreicht  [TSB-BLOCK:touch]
   ------------------------------------------------------------------
   Gemessen am 22.07. ueber 14 Seiten bei 390px, nach den Stufen 1 und 2:
   407 sichtbare Bedienelemente, davon **127 echte** unter 44x44. Die im Konzept
   genannten 307 zaehlten Links im Fliesstext mit; die sind eine andere Klasse
   Problem und werden hier bewusst NICHT angefasst (ein Mindestmass auf jedem
   Inline-Link zerreisst den Zeilenfluss).

   Verteilung der 127, das ist der ganze Punkt dieses Abschnitts:
       84  Fusszeile        (6 Links x 14 Seiten - EINE Regel erschlaegt zwei Drittel)
       16  Inhalt
       15  Inhaltsverzeichnis der Rechtsseiten
        6  Formularbeschriftungen
        4  Brotkrume
        2  Warenkorb

   Kein neues Token `--tap-min: 44px`: es laege zu `--s-7` (48px) bei Faktor 1,09 und
   verletzt die 1,12-Regel. `--s-7` wird direkt als Mindestmass genommen; 48 >= 44
   erfuellt WCAG 2.5.5 mit Reserve und kostet weder Token noch Ausnahme.
   ------------------------------------------------------------------ */

@media (max-width: 1024px) {

  /* --- Fusszeile: 84 der 127 Faelle -------------------------------
     Die Fusszeile ist `<footer>` OHNE Klasse; `.mkd-page-footer` trifft nichts.
     Gemessene Ist-Groessen: Telefon 115x24, "AGB" 29x24, "Datenschutzerklaerung"
     154x24, "Impressum" 78x24, Instagram 27x23, TikTok 17x23 - letzteres ist das
     kleinste Bedienelement der ganzen Seite.

     Bewusst `inline-block` mit senkrechtem Polster statt `inline-flex`: der
     Telefonlink steht in einem Fliesstext-Widget, und `inline-flex` nimmt ihn aus
     dem Zeilenfluss. 24px Textzeile + 2 x 12px = 48px. */
  footer a {
    display: inline-block;
    /* `min-height` statt blossem Polster: die Textzeile ist gemessen 19,2px hoch,
       nicht 24. 19,2 + 2 x 12 ergab 43px und blieb damit einen Pixel unter dem
       Mindestmass - in der Summenzahl unsichtbar, weil sie weiter als "zu klein"
       zaehlte. Nachmessen, nicht nachrechnen. */
    /* `border-box` ist Pflicht, sobald `min-height` und Polster zusammenkommen:
       im Bestand gilt `content-box`, dort ist `min-height` die INHALTShoehe und das
       Polster kommt obendrauf. Ohne diese Zeile wurden die Fusszeilenlinks 72px hoch
       (48 + 2 x 12) und die Fusszeile unnoetig hoch. */
    box-sizing: border-box;
    min-height: var(--s-7);
    padding-top:    var(--s-3);
    padding-bottom: var(--s-3);
  }
  /* Die drei Rechtslinks liegen in Widget-Listen und werden von einer Theme-Kette
     zurueckgesetzt, die `footer a` schlaegt:

         footer .mkd-footer-top .widget.widget_archive ul li a, ...
             { display:inline; padding:0 }

     Der erste Rollout am 22.07. hat deshalb NUR den Telefonlink erwischt
     (115x24 auf 115x43), waehrend "AGB" (29x24), "Datenschutzerklaerung" (154x24)
     und "Impressum" (78x24) unveraendert blieben. In der Summenzahl sah das nach
     Fortschritt aus. `!important`, weil die Theme-Kette mehrere `.widget_*`-Varianten
     aufzaehlt und eine gespiegelte Kette bei der naechsten Variante wieder verlöre. */
  footer .widget ul li a,
  footer .mkd-footer-top .widget ul li a {
    display: inline-block !important;
    box-sizing: border-box !important;
    min-height: var(--s-7) !important;
    padding-top:    var(--s-3) !important;
    padding-bottom: var(--s-3) !important;
  }

  /* Die beiden Social-Symbole stehen 3,3px auseinander (Instagram endet bei x=320,
     TikTok beginnt bei 323) - auf 14 von 14 Seiten der haeufigste Treffer unter 8px.
     Die Trefferflaeche muss UM das Piktogramm wachsen, nicht das Piktogramm selbst. */
  footer .mkd-icon-shortcode a,
  footer .textwidget a[href*="instagram"],
  footer .textwidget a[href*="tiktok"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width:  var(--s-7);
    min-height: var(--s-7);
    padding-top: 0;
    padding-bottom: 0;
    margin-left:  var(--s-1);
    margin-right: var(--s-1);
  }

  /* --- Inhaltsverzeichnis der Rechtsseiten -------------------------
     Gemessen auf /agbs/: 15 Eintraege, 308x20 beziehungsweise 308x40, ALLE unter 44.
     `--s-3` ist der richtige Wert: 20 + 2 x 12 = 44. Mit `--s-2` waeren es 36px
     Flaeche in einem 44px-Raster, das ist nicht dasselbe.
     Folge: das Verzeichnis waechst auf /agbs/ um rund 360px. Bei 10.116px Seitenhoehe
     vertretbar, aber im BILD abnehmen. Das `ol` traegt `columns:2`, mehr Innenabstand
     verschiebt den Spaltenumbruch auf breiten Fenstern - deshalb nur bis 1024px. */
  /* `:has(.num)` schliesst einen LEEREN Eintrag aus. Im Verzeichnis steht als erster
     Punkt `<li><a href="#agb-anbieter"><span></span></a></li>` ohne Text - ein
     Bestandsfehler, der bei 20px Zeilenhoehe nicht auffiel. Ohne diese Einschraenkung
     blaeht ihn das Mindestmass zu einer 308x48-Luecke auf: eine Regel, die
     Trefferflaechen vergroessert, macht dann einen unsichtbaren Fehler sichtbar.
     Der leere Eintrag selbst gehoert in die Inhaltsarbeit, nicht ins CSS. */
  .tsb-legal-toc a:has(.num) {
    display: block;
    box-sizing: border-box;
    min-height: var(--s-7);
    padding-top:    var(--s-3);
    padding-bottom: var(--s-3);
  }

  /* --- Brotkrume ---------------------------------------------------
     13px ist zu `--fs-xs` (12px) Faktor 1,08, also ein Token zu viel. */
  .mkd-breadcrumbs a,
  .woocommerce-breadcrumb a {
    display: inline-block;
    font-size: var(--fs-sm);
    /* Die Zeilenhoehe muss mit, sonst reicht das Polster nicht: gemessen stand sie
       auf 13px (als Laenge geerbt), 13 + 2 x 8 ergab 29px. Mit `--lh-base` sind es
       21 + 2 x 12 = 45px. Nachmessen, nicht nachrechnen. */
    line-height: var(--lh-base);
    box-sizing: border-box;
    min-height: var(--s-7);
    padding-top:    var(--s-3);
    padding-bottom: var(--s-3);
  }

  /* --- Warenkorb ---------------------------------------------------
     Nachgemessen mit gefuelltem Korb: das Mengenfeld ist bereits 67x48, es gibt
     KEINE Plus/Minus-Knoepfe (das Konzept nannte 32x44 Mengensteller - die gibt es
     hier nicht). Zu klein ist allein `a.remove` mit 20x20.
     ACHTUNG: es gibt ZWEI `a.remove`, einer davon 0x0 (Rest einer zweiten
     Markup-Variante). Der Glyph steht auf `font-size:0` und kommt aus einem
     Pseudoelement - die Groesse darf deshalb nicht ueber die Schrift wachsen.
     `a.remove` ist nachgemessen der EINZIGE Weg, einen Posten zu entfernen. */
  .woocommerce-cart-form a.remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width:  var(--s-7);
    min-height: var(--s-7);
  }

  /* --- Karte auf /kontakt/ -----------------------------------------
     `#ts-osm-map` ist 356x290px und hat `touch-action:none`. Fuenf CDP-Touch-
     Durchlaeufe ergaben 0px Seitenbewegung im Kartenfeld gegen 301px daneben: die
     Karte haelt den Finger fest, die Seite laesst sich dort nicht scrollen.
     `pan-y` gibt den senkrechten Wisch an die Seite zurueck und laesst der Karte
     den waagerechten. Die Attribution stand in fremdem Blau #0078a8 (4,94:1),
     die Zoom-Knoepfe in Schwarz. */
  #ts-osm-map {
    touch-action: pan-y;
  }
  #ts-osm-map .leaflet-control-attribution a {
    color: var(--accent);
  }
  #ts-osm-map .leaflet-control-zoom a {
    color: var(--ink-body);
    min-width:  var(--s-7);
    min-height: var(--s-7);
    display: flex;
    align-items: center;
    justify-content: center;
  }

  /* --- Knopf "Nach oben" -------------------------------------------
     Er ist mit 64x64 gross genug, liegt aber unter dem Cookie-Band: `#mkd-back-to-top`
     hat z-index 10001, sitzt aber in `.mkd-wrapper{position:relative;z-index:1000}`,
     also in einem Stapelkontext. Effektiv treten **1000 gegen 9999** an, deshalb
     gewinnt das Band mit der kleineren Zahl. Wer am z-index des Knopfes dreht,
     wundert sich, dass nichts passiert.

     Den Wrapper ueber 9999 zu heben waere der naheliegende Weg und der falsche: dann
     liegt der gesamte Seiteninhalt ueber dem Cookie-Band. Stattdessen weicht der
     Knopf aus, solange das Band sichtbar ist.

     Das Band bleibt nach dem Einverstaendnis im DOM und bekommt nur `display:none`
     per Inline-`style` - deshalb der Attributtest statt eines blossen `:has()`.
     Traegt der Test eines Tages nicht mehr, ist der Zustand wie heute, nicht
     schlechter. Beide Zustaende sind nach dem Rollout einzeln nachzumessen. */
  body:has(#fhw_cookiehinweis:not([style*="none"])) #mkd-back-to-top {
    bottom: 168px;
  }
}

/* Nebenbefund aus dem Inhaltsverzeichnis, BEWUSST ohne Media Query: das Markup lautet
   `<span class="num">§ 1</span><span>Geltungsbereich</span>` - ohne Leerzeichen und ohne
   Abstand, gerendert also "§ 1Geltungsbereich". Der Fehler ist Bestand und steht auf
   JEDER Breite, nicht nur mobil. Er stand zuerst irrtuemlich in der 1024px-Abfrage,
   womit er am Schreibtisch geblieben waere. */
.tsb-legal-toc .num {
  margin-right: var(--s-2);
}

/* ===== TSB-BLOCK:touch END ===== */












/* ===== TSB-BLOCK:kopf-sticky START ===== */
/* 43. Mobiler Kopf: bleibt stehen, traegt Konto und Warenkorb  [TSB-BLOCK:kopf-sticky]
   ------------------------------------------------------------------
   Gehoert zu Stufe 4. Bewusst ein EIGENER Block und nicht eine Erweiterung von
   Abschnitt 39: er haengt an einer Datenbankaenderung (zwei Widget-Instanzen im
   Bereich 'mkd-right-from-mobile-logo', siehe scripts/mobil-2026-07-22/stufe4-widgets.php)
   und muss zusammen mit ihr zurueckgedreht werden koennen.

   Warum das ueberhaupt noetig war: auf dem Handy gab es KEINEN Weg zum Warenkorb ausser
   der Zurueck-Taste. Kein Symbol im Kopf, kein Menuepunkt; die drei Links auf
   /warenkorb/ im Dokument massen alle 0x0, weil ihr Vorfahr `header.mkd-page-header`
   mobil `display:none` traegt. Ein Kind von `display:none` holt kein CSS zurueck.
   Der Ausweg war kein Neubau: das Theme rendert im mobilen Kopf laengst
   `dynamic_sidebar('mkd-right-from-mobile-logo')` direkt vor dem Burger, der Bereich
   war nur leer.

   NICHT ANFASSEN: `font-family` von `.mkd-cart-icon` (FontAwesome) und vom Burger
   (Ionicons). Wer sie ueberschreibt, bekommt statt des Piktogramms das Rohzeichen -
   der Fehler vom 21.07. `font-size` und `line-height` sind dagegen unbedenklich und
   hier auch noetig: das Warenkorbsymbol mass gemessen 21x0.
   ------------------------------------------------------------------ */

@media (max-width: 1199px) {

  /* --- Der Kopf bleibt stehen --------------------------------------
     Er stand auf `position:relative` auf 21 von 21 Seiten und scrollte weg; ein
     `.mkd-sticky-header` existiert im mobilen DOM nicht. Bei 11.502px Seitenlaenge
     auf der Startseite heisst das: ab dem zweiten Bildschirm gibt es keinen Weg mehr
     zu Menue, Konto oder Warenkorb.

     WARUM `fixed` UND NICHT `sticky`. `position:sticky` wurde zuerst versucht und
     scheiterte an drei Vorfahren mit `overflow`. Ein Test, der die Kette Element fuer
     Element auf `visible` setzt und nach jedem Schritt misst, ergab: es braucht
     `.mkd-wrapper-inner` UND `body` gleichzeitig, `overflow-x:clip` genuegt Chromium
     entgegen der Spezifikation nicht (gemessen top=-1652 statt 0), und am `body` steht
     `overflow-x:hidden` mit `!important`. Selbst mit allen drei Eingriffen klebte der
     Kopf auf 0 von 22 Seiten.

     Der Preis waere hoch gewesen: der waagerechte Ueberlaufschutz der ganzen Seite
     haette mobil fallen muessen, dauerhaft, fuer jede kuenftige Aenderung.
     `position:fixed` braucht davon nichts. Es kostet stattdessen einen Ausgleich in
     Hoehe des Kopfes, und der ist bekannt und fest.

     Das Menue liegt IM Kopf (`.mkd-mobile-nav` ist sein Kind). Aufgeklappt sind es
     14 Eintraege = 673px. Deshalb `max-height` und eigenes Scrollen: auf einem
     667px-Geraet passt die Liste sonst nicht. */
  .mkd-mobile-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 120;
  }
  /* Ausgleich, sonst liegt der Kopf ueber dem ersten Inhalt. Die Kette muss
     gespiegelt werden (`.mkd-wrapper .mkd-wrapper-inner` ist (0,2,0)).
     Kopfhoehe mobil einheitlich `--s-8` plus die 1px-Kante aus Abschnitt 39. */
  .mkd-wrapper .mkd-wrapper-inner {
    padding-top: calc(var(--s-8) + 1px);
  }
  /* Der `-inner` BEHAELT seine feste Hoehe. Der Versuch, sie auf den `-holder` zu
     verlegen, liess Kopfleiste und Logo auf 0px kollabieren (gemessen: inner 390x0,
     holder 390x0) - die Kinder des Kopfes tragen keine eigene Hoehe, sie leiten sie
     vom Elternteil ab. Sichtbar wurde es erst im Bild: ein durchsichtiger Kopf, durch
     den der Text lief, waehrend alle Messwerte gruen waren.

     Damit die feste Hoehe das aufgeklappte Menue nicht einklemmt, wird das Menue aus
     dem Fluss genommen und haengt unter dem Kopf - die uebliche Bauweise fuer ein
     fixiertes Menue. Es ueberlagert dann den Inhalt, statt ihn zu schieben. */
  .mkd-mobile-header .mkd-mobile-header-inner {
    height: var(--s-8);
    /* KEIN `position: relative` hier. Der erste Versuch setzte es, damit das Menue
       daran haengen kann - und verschob damit den Positionierungskontext der bereits
       absolut positionierten Kinder: Konto, Warenkorb und Burger rutschten aus dem
       Kopf heraus und schwebten ueber dem Text darunter. Auch das war in den
       Messwerten unsichtbar (der Kopf mass weiter 390x64 mit dunkler Flaeche) und
       nur im Bild zu sehen.
       Der fixierte `.mkd-mobile-header` ist selbst schon ein Kontext; das Menue
       haengt deshalb an IHM. */
  }
  .mkd-mobile-header .mkd-mobile-nav {
    position: absolute;
    top: var(--s-8);
    left: 0;
    right: 0;
    max-height: calc(100vh - var(--s-8));
    overflow-y: auto;
    overscroll-behavior: contain;
    border-bottom: 1px solid var(--line-on-dark);
  }

  /* --- Die drei Bedienelemente in eine Zeile -----------------------
     Der Widgetbereich gibt jedes Widget als `div.widget` im Block aus, dadurch
     stapelten sich Konto (58x36), Warenkorb (58x25) und Burger (58x48)
     UNTEREINANDER und der Kopf wurde 109px hoch. */
  /* Der Kopf ist im Theme eine TABELLE: `.mkd-position-right` ist die Zeile,
     `-inner` die Zelle mit `vertical-align`. Wer nur die Zelle auf `flex` setzt,
     loest sie aus der Tabelle - sie rutscht dann als Block UNTER die (nun leere)
     Zeile. Genau das passierte am 22.07.: Konto, Warenkorb und Burger sassen bei
     y=64 statt y=0, also knapp unter dem Kopf, und schwebten ueber dem Fliesstext.
     Deshalb muessen BEIDE Ebenen umgestellt werden. */
  .mkd-mobile-header .mkd-position-right {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    height: var(--s-8);
  }
  .mkd-mobile-header .mkd-position-right-inner {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--s-2);
  }
  .mkd-mobile-header .mkd-position-right-inner > .widget {
    margin: 0;
    display: flex;
    align-items: center;
  }
  /* Der Theme-Wrapper des Warenkorbs rechnet in Tabellenzellen. */
  .mkd-mobile-header .mkd-shopping-cart-holder,
  .mkd-mobile-header .mkd-shopping-cart-inner {
    display: block;
  }

  /* --- Warenkorb ---------------------------------------------------
     Trefferflaeche `--s-7`, Symbol sichtbar machen. Die Zahl sitzt IM Symbol und
     wird zur Blase in der Rolle, fuer die `--accent-bright` da ist: Flaeche, nie Text. */
  .mkd-mobile-header a.mkd-header-cart {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    min-width:  var(--s-7);
    min-height: var(--s-7);
    position: relative;
    color: var(--on-dark);
  }
  .mkd-mobile-header .mkd-cart-icon {
    font-size: var(--fs-lg);
    line-height: var(--lh-1);
    display: block;
  }
  /* Die Textfassung ("1 item, 166,25 EUR") ist im Kopf schon vom Theme abgeschaltet
     (`mkd-cart-info-is-disabled`) und bleibt es - sie passt mobil nicht daneben. */
  .mkd-mobile-header .mkd-cart-info {
    display: none;
  }
  .mkd-mobile-header .mkd-cart-number {
    position: absolute;
    top: 4px;
    right: 2px;
    min-width: 18px;
    height: 18px;
    box-sizing: border-box;
    padding-left:  var(--s-1);
    padding-right: var(--s-1);
    border-radius: var(--r-pill);
    background-color: var(--accent-bright);
    color: var(--accent-ink);
    font-size: var(--fs-xs);
    line-height: 18px;
    font-weight: 700;
    text-align: center;
  }
  /* Das Klappmenue des Warenkorbs gehoert nicht in einen 390px-Kopf: der Tipp aufs
     Symbol soll zum Warenkorb fuehren, nicht eine Vorschau ueber die halbe Seite legen. */
  .mkd-mobile-header .mkd-shopping-cart-dropdown {
    display: none !important;
  }

  /* --- Konto -------------------------------------------------------
     Stand als `rgb(28,32,29)` auf dem nun dunklen Kopf, war also praktisch unsichtbar.
     Der Name beziehungsweise "Anmelden" entfaellt mobil, das Symbol traegt allein. */
  .mkd-mobile-header .tsb-kontowidget__link {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    min-width:  var(--s-7);
    min-height: var(--s-7);
    color: var(--on-dark);
  }
  .mkd-mobile-header .tsb-kontowidget__text {
    /* nicht `display:none`: der Text traegt die Bedeutung des Links fuer
       Screenreader. Er wird nur optisch entfernt. */
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .mkd-mobile-header .tsb-kontowidget__panel {
    display: none;
  }

  /* --- Sprungmarken unter dem klebenden Kopf ------------------------
     Ohne das verschwindet jedes Sprungziel unter dem Kopf. Das Token
     `--anchor-offset` war definiert und wurde NULLMAL verwendet - sein Kommentar
     ("kein Sticky-Header mehr, daher klein") stimmt ab hier nicht mehr, deshalb
     rechnet die Regel die tatsaechliche Kopfhoehe dazu. */
  [id] {
    scroll-margin-top: calc(var(--s-8) + var(--anchor-offset));
  }
}
/* ===== TSB-BLOCK:kopf-sticky END ===== */




/* ===== TSB-BLOCK:typo-mobil START ===== */
/* 45. Typografie auf dem Handy  [TSB-BLOCK:typo-mobil]
   ------------------------------------------------------------------
   Stufe 6, bewusst der KLEINE Teil davon.

   Gemessen am 22.07. ueber 10 Seiten bei 390px UND 768px: beide Breiten liefern bei
   jeder Ueberschrift denselben Wert. Die fluide `clamp()`-Skala ist unterhalb von
   rund 840px also wirkungslos, weil der `vw`-Anteil dort unter den Mindestwert faellt.
   Die Folge sind H1-Groessen zwischen 30,4px und 50px und H1-zu-H2-Verhaeltnisse
   zwischen 1,25 und 3,01 - fuenf Groessen fuer eine Rolle.

   Das wird hier NICHT vereinheitlicht. Eine gemeinsame mobile H1-Groesse aendert das
   Aussehen jeder Seite und ist eine Gestaltungsentscheidung, keine Fehlerkorrektur;
   sie gehoert zur Kundenabnahme (Frage 4 in Fragen-an-Alexander.md). Was hier steht,
   ist der belegbare Fehler: lange deutsche Woerter laufen aus ihrer Box.

   Gemessen: die H1 auf /agbs/ ("Allgemeine Geschaeftsbedingungen") ist 374px breit in
   einer 358px-Box, laeuft also um 16px hinaus. Sichtbar wird das nur im Bild - in der
   Ueberlaufmessung taucht es nicht auf, weil der Titelbereich clippt.
   ------------------------------------------------------------------ */

/* BEWUSST ohne Media Query: lange Woerter laufen auf jeder schmalen Spalte heraus,
   nicht nur auf dem Handy. `hyphens` braucht die Sprachauszeichnung am `<html>`;
   sie ist vorhanden (`lang="de-DE"`), sonst waere die Regel wirkungslos. */
.tsb h1, .tsb h2, .tsb h3, .tsb h4,
.tsb-legal h1, .tsb-legal h2, .tsb-legal h3,
.tsb-legal-head h1,
.mkd-title h1, .mkd-title h2 {
  overflow-wrap: break-word;
  hyphens: auto;
}

@media (max-width: 480px) {
  /* Auf der schmalsten Stufe reicht die Trennung allein nicht: "Geschaeftsbedingungen"
     ist auch getrennt noch breit. Der Titel der Rechtsseiten faellt deshalb dort eine
     Stufe auf `--fs-2xl` (36px; gemessen standen 37,6px, Faktor 1,04 - nach der
     1,12-Regel derselbe Wert, also kein neuer). */
  .tsb-legal-head h1 {
    font-size: var(--fs-2xl);
  }
}
/* ===== TSB-BLOCK:typo-mobil END ===== */

/* ===== TSB-BLOCK:woo-mobil START ===== */
/* 44. Kaufstrecke und Farbrollen  [TSB-BLOCK:woo-mobil]
   ------------------------------------------------------------------
   Stufe 5. Alle Werte am 22.07. nach den Stufen 1 bis 4 nachgemessen.

   Zwei Dinge, die das Konzept richtig hatte, und zwei Korrekturen:
     - Die Fehlerliste der Kasse ist tatsaechlich riesig, aber der Grund ist NICHT
       ein Float: der ANKER im `li` traegt `margin: 0 70% 15px 0` (gemessen 203px
       rechts bei 290px Zeilenbreite). Dem Text bleiben 87px, jede Meldung bricht auf
       VIER Zeilen. Bei 8 Pflichtfeldern sind das 1130px Fehlerkasten, und die Seite
       waechst von 3698px auf 5134px.
     - Die Formularfelder sind BESSER als angenommen: 16px Schriftgroesse (kein
       iOS-Zoom), 50px hoch, mit vollstaendigem `autocomplete`. Nur zwei Felder liegen
       darunter, drei ohne `autocomplete`. Kein Handlungsbedarf im CSS.
   ------------------------------------------------------------------ */

@media (max-width: 1024px) {

  /* --- Fehlerliste der Kasse ---------------------------------------
     Das `margin-right` stammt aus einer Theme-Regel fuer den Schreibtisch, wo neben
     der Meldung noch Platz ist. Auf 390px ist dort nichts. */
  /* Die Theme-Kette muss GESPIEGELT werden: sie heisst
     `.mkd-woocommerce-page .woocommerce-error a` (0,2,1) und schlaegt ein
     `.woocommerce-error li a` (0,1,2) - Klassen zaehlen vor Elementen. Da dieser
     Block am Dateiende steht, genuegt die gleiche Spezifitaet. */
  .mkd-woocommerce-page .woocommerce-error a,
  .mkd-woocommerce-page .woocommerce-info a,
  .mkd-woocommerce-page .woocommerce-message a {
    margin-right: 0;
  }
  .woocommerce-error {
    padding-left:  var(--s-5);
    padding-right: var(--s-5);
  }
  .woocommerce-error li {
    padding-top:    var(--s-2);
    padding-bottom: var(--s-2);
  }
}

/* --- Farbrollen im Shop -------------------------------------------
   BEWUSST ohne Media Query: `#929191` steht auf jeder Breite zu blass da, der Fehler
   ist keine Handy-Eigenheit.

   Gemessen:
     Preis           `rgb(146,145,145)` auf Weiss      = 3,14:1
     Sortierung      `rgb(146,145,145)` auf Weiss      = 3,14:1
     Brotkrume       `rgb(146,145,145)` auf `#f0f0ef`  = 2,76:1

   Der Preis ist die wichtigste Zahl einer Verkaufsseite und war der blasseste Text
   der Kachel. Er bekommt `--ink` (18,18:1), nicht `--muted`: er ist keine Nebenangabe.
   Artikelnummer, Kategorie, Sortierung und Brotkrume sind Nebenangaben und bekommen
   `--muted` (5,76:1 auf Weiss, 5,3:1 auf dem #f0f0ef-Titelband - beides ueber 4,5). */
.woocommerce ul.products li.product .price,
.woocommerce ul.products li.product .price bdi,
.woocommerce div.product p.price,
.woocommerce div.product p.price bdi,
.woocommerce div.product span.price,
.woocommerce div.product span.price bdi {
  color: var(--ink);
}
.woocommerce .product_meta,
.woocommerce .product_meta a,
.woocommerce .woocommerce-breadcrumb,
.woocommerce .woocommerce-breadcrumb a,
.woocommerce-ordering select {
  color: var(--muted);
}
/* Zwei Ketten mussten gespiegelt werden, sonst bleibt #929191 stehen:
   die Brotkrume haengt an `.mkd-title .mkd-title-holder .mkd-breadcrumbs a` (0,3,1),
   die Sortierung an `.select2-container--default .select2-selection--single
   .select2-selection__rendered` (0,3,0). */
.mkd-title .mkd-title-holder .mkd-breadcrumbs,
.mkd-title .mkd-title-holder .mkd-breadcrumbs a,
.mkd-title .mkd-title-holder .mkd-breadcrumbs span {
  color: var(--muted);
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
  color: var(--muted);
}

/* Nachtrag 22.07. abends, aus der Schlussmessung. Drei Stellen trugen weiter #929191
   (3,14:1), weil sie an ANDEREN Ketten haengen als die Produktkacheln:

     Preise im Produkt-Widget   `.widget.woocommerce.widget_products ul li .amount`
     Artikelnummer              `.mkd-woo-single-page .mkd-single-product-summary
                                 .product_meta > span .sku`
     Kategorie-Link             dieselbe Kette mit `a`

   Die Widget-Preise sind die vier Zahlen in der Produktliste am Seitenfuss (30,00 /
   2,50 / 24,99 / 9,99 Euro), nicht die Preise der Kacheln - die sind seit Stufe 5
   korrekt. Sie bekommen `--ink` wie jeder andere Preis auch, damit es nicht zwei
   Preisfarben gibt. */
.widget.woocommerce.widget_products ul li .amount,
.widget.woocommerce.widget_products ul li .amount bdi,
.widget.woocommerce.widget_recent_reviews ul li .amount,
.widget.woocommerce.widget_top_rated_products ul li .amount {
  color: var(--ink);
}
.mkd-woo-single-page .mkd-single-product-summary .product_meta > span .sku,
.mkd-woo-single-page .mkd-single-product-summary .product_meta > span a {
  color: var(--muted);
}
/* ===== TSB-BLOCK:woo-mobil END ===== */


/* ===== TSB-BLOCK:kasse-felder START ===== */
/* =========================================================================
   46. Rechnungsformular entschlackt: PLZ neben Ort  [TSB-BLOCK:kasse-felder]
   (Kundenwunsch 22.07.: "Rechnungsformular entschlacken")

   Gehoert zum mu-plugin tsb-kasse-felder.php. Das Plugin nimmt die Felder
   weg und vergibt die Klassen, hier bekommen sie ihre Breite.

   WARUM 12 SPALTEN STATT 2:
   Abschnitt 20.1 legt die Kaufstrecken-Formulare in ein Raster aus zwei
   gleichen Spalten (form-row-first | form-row-last). Fuer PLZ und Ort passt
   50:50 aber nicht - fuenf Ziffern brauchen kein halbes Formular, ein
   Ortsname schon. Ein feineres Raster loest das, ohne die uebrigen Zeilen
   anzufassen: bei gleichem column-gap ist "1 / 7" in zwoelf Spalten exakt so
   breit wie "1" in zweien. Nachgerechnet:
     zwoelf Spalten: 6c + 5g, mit c = (W - 11g)/12  ->  W/2 - g/2
     zwei Spalten:   (W - g)/2                      ->  W/2 - g/2
   Vor- und Nachname stehen also weiterhin pixelgenau wie vorher.

   ⚠️ DIESER BLOCK STEHT NACH ABSCHNITT 20 UND SCHLAEGT IHN DESHALB BEI
   GLEICHER SPEZIFITAET - AUCH IN DESSEN MEDIA-QUERY. Eine @media-Regel ist
   nicht spezifischer, sie ist nur eine Bedingung. Der mobile Umbruch aus
   20.1 muss hier also wiederholt werden, sonst bliebe das Formular unter
   768px zwoelfspaltig und die PLZ waere ein Drittel Handybreite.
   ========================================================================= */

/* --- 46.1 Das Landfeld ist da, aber unsichtbar ---------------------------
   type=hidden allein genuegt nicht: woocommerce_form_field() legt trotzdem
   den <p class="form-row">-Container an, und der ist im Raster eine Zeile.
   Die Kette aus Abschnitt 20 wird gespiegelt, weil woocommerce.min.css
   .form-row auf display:flex setzt (0,2,1) - eine einzelne Klasse verliert
   dagegen. */
body.woocommerce-page .mkd-content .form-row.tsb-feld-aus{ display: none }

/* --- 46.2 Feineres Raster fuer die Kaufstrecken-Formulare ---------------- */
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm){
  grid-template-columns: repeat(12, 1fr);
}
/* Halbe Breite wie gehabt - nur in der neuen Rastereinteilung ausgedrueckt. */
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .form-row-first{ grid-column: 1 / 7 }
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .form-row-last{ grid-column: 7 / 13 }

/* Und die eine Zeile, wegen der das alles hier steht. */
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .tsb-feld-plz{ grid-column: 1 / 5 }
body.woocommerce-page .mkd-content :is(
  .woocommerce-billing-fields__field-wrapper,
  .woocommerce-shipping-fields__field-wrapper,
  .woocommerce-additional-fields__field-wrapper,
  .woocommerce-address-fields__field-wrapper,
  .woocommerce-EditAccountForm) > .tsb-feld-ort{ grid-column: 5 / 13 }

/* --- 46.3 Auf dem Handy steht alles untereinander ------------------------
   Wiederholung von 20.1, siehe Warnung im Kopf. */
@media (max-width: 768px){
  body.woocommerce-page .mkd-content :is(
    .woocommerce-billing-fields__field-wrapper,
    .woocommerce-shipping-fields__field-wrapper,
    .woocommerce-additional-fields__field-wrapper,
    .woocommerce-address-fields__field-wrapper,
    .woocommerce-EditAccountForm){ grid-template-columns: 1fr }
  body.woocommerce-page .mkd-content :is(
    .woocommerce-billing-fields__field-wrapper,
    .woocommerce-shipping-fields__field-wrapper,
    .woocommerce-additional-fields__field-wrapper,
    .woocommerce-address-fields__field-wrapper,
    .woocommerce-EditAccountForm) > :is(.form-row-first, .form-row-last, .tsb-feld-plz, .tsb-feld-ort){
    grid-column: 1 / -1;
  }
}
/* ===== TSB-BLOCK:kasse-felder END ===== */








/* ===== TSB-BLOCK:anmerkungen-2026-07-23 START ===== */
/* 47. Kundenanmerkungen 23.07.2026 (mobil)  [TSB-BLOCK:anmerkungen-2026-07-23]
   ------------------------------------------------------------------
   Fuenf gemessene Befunde aus der Handy-Abnahme (390px, ausgeloggt gemessen,
   Screenshots). Bewusst EIN eigener Block am Dateiende: er ueberschreibt die
   Abschnitte 41/42/43 auf gleicher Spezifitaet, weil er spaeter kommt, und laesst
   sich als Ganzes zurueckdrehen, ohne einen Bestandsblock anzufassen.

   Wo eine THEME-Kette den Wert stellt (Titel-Innenabstand, Footer-Spalten,
   .tsb-inner unter 768), ist die Kette gespiegelt bzw. !important gesetzt - sonst
   ist die Regel richtig, ausgeliefert und wirkungslos (der Fehler, der in dieser
   Datei mehrfach dokumentiert ist).
   ------------------------------------------------------------------ */

@media (max-width: 1024px) {

  /* --- 1. Kopf: Konto und Warenkorb als aufgeraeumtes Paar --------------
     Gemessen (390px): Konto- und Warenkorb-Glyph standen ~49px auseinander,
     weil jeder Glyph in einer 48px-Box zentriert sass (je ~14px Totraum) und
     der Warenkorb-Wrapper zusaetzlich 15px Vorlauf hatte. Das Personen-Icon
     wirkte dadurch verloren. Die Tap-HOEHE (48px, Abschnitt 43) bleibt; nur die
     waagerechte Box wird schmaler, damit die Glyphen zusammenruecken. 32x48 ist
     WCAG 2.5.8 (AA) mit Reserve; die Hoehe traegt die Bedienbarkeit im Kopf. */
  .mkd-mobile-header .mkd-position-right-inner {
    gap: var(--s-1);
  }
  .mkd-mobile-header .tsb-kontowidget__link,
  .mkd-mobile-header a.mkd-header-cart {
    min-width: var(--s-6);
  }
  /* Der 15px-Vorlauf sass im Warenkorb-Wrapper (Theme rechnet in Tabellenzellen).
     Neutralisieren, dann zentriert der Link seinen Glyph selbst. */
  .mkd-mobile-header .widget_mkd_woocommerce_dropdown_cart,
  .mkd-mobile-header .mkd-shopping-cart-holder,
  .mkd-mobile-header .mkd-shopping-cart-inner {
    margin: 0;
    padding-left: 0;
    padding-right: 0;
  }
  /* Konto + Warenkorb lesen sich als Paar, der Burger (Navigation) bekommt einen
     Hauch mehr Abstand - das ist der "aufgeraeumte" Gruppen-Eindruck. */
  .mkd-mobile-header .mkd-mobile-menu-opener {
    margin-left: var(--s-2);
  }
  /* Das Personen-Icon war ein duennes 20px-SVG (stroke 1.8) neben dem fuelligen
     FontAwesome-Warenkorb. Gleiche Bildwirkung: 22px, stroke 2. stroke-width als
     CSS schlaegt das Praesentationsattribut im SVG. */
  .mkd-mobile-header .tsb-kontowidget__symbol {
    width: 22px;
    height: 22px;
    stroke-width: 2;
  }

  /* --- 2. Titelbox "Mein Konto": Luft statt Klebefall -------------------
     Gemessen: .mkd-title .mkd-container-inner hatte padding 0, H1 und Brotkrume
     klebten bei x=0. Der Innenabstand kommt ueber die volle Titel-Kette, damit
     eine Theme-Regel ihn nicht still schlaegt. Die feste Inline-Hoehe (114px)
     wird geloest, sonst bleibt unter der (entfernten) Brotkrume ein leerer Sockel;
     stattdessen umschliesst die Box den Titel mit gleichmaessiger Luft. */
  /* Feste Inline-Hoehe (114px) loesen, sonst blieb unter der (entfernten) Brotkrume
     ein leerer Sockel. Danach traegt die Box ihre Hoehe aus dem Polster - das MUSS
     ankommen: die erste Fassung setzte `--s-5` ohne !important und wurde gemessen von
     einer spezifischeren Theme-Regel auf 0 geschlagen, die Box schrumpfte auf 27px
     (nur die H1-Zeile) und sah aus wie ein duenner Streifen. Jetzt mit !important und
     etwas grosszuegiger (--s-6), damit es ein ordentlicher Seitenkopf ist.
     `box-sizing:border-box`, weil der Container `content-box` ist - sonst addiert der
     Gutter 32px auf die 100%-Breite (gemessen 422px) und laeuft aus dem Viewport. */
  .mkd-title,
  .mkd-title .mkd-title-holder {
    height: auto !important;
    min-height: 0 !important;
  }
  .mkd-title .mkd-title-holder .mkd-container-inner {
    box-sizing: border-box;
    padding-top: var(--s-6) !important;
    padding-bottom: var(--s-6) !important;
    padding-left: var(--gutter) !important;
    padding-right: var(--gutter) !important;
  }

  /* --- 5. Graue Baender: Inhalt klebt an der Flaeche -------------------
     Gemessen auf /einzeltraining/ ("04 Wer trainiert"): das graue Band ist auf
     x=16-374 eingerueckt UND der Inhalt beginnt ebenfalls bei x=16 - null Luft,
     Zitatrand und Zahlen kleben an der grauen Kante. Nur gefuellte Baender
     (tsb-band-alt) bekommen 24px Innenabstand; weisse Baender brauchen keinen,
     da man dort keine Flaechenkante sieht. !important, weil Abschnitt 3
     `.tsb-inner{padding-inline:0}` und Abschnitt 41 den Gutter je mit !important
     setzen - dieser Block kommt spaeter und auf hoeherer Spezifitaet. */
  .tsb-band-alt .tsb-inner {
    padding-left: var(--s-5) !important;
    padding-right: var(--s-5) !important;
  }
}

/* --- 3. Weisser Abstand ueber "Guthaben" & Co. vereinheitlichen -------
   Abschnitt 41 entfernt den 66px-Totraum nur auf Seiten mit `.tsb`. Die eigene
   Guthaben-Seite traegt `.tsb` (kein Abstand), die NATIVEN WooCommerce-Endpunkte
   (Deine Daten, Adressen, Bestellungen) nicht - dort kam der 66px-Sockel zurueck,
   also je nach Menuepunkt mal da, mal nicht. `body.woocommerce-account` liegt auf
   JEDER Kontoseite an (Woo-Garantie) und deckt sie alle ab. Spezifitaet (0,6,0)
   schlaegt die Theme-Kette (0,4,0), deshalb ohne !important. Global wie
   Abschnitt 41, nicht nur mobil - der Sockel steht auf jeder Breite.
   Hinweis: eingeloggt gegengeprueft werden muss noch (Konto-Login blockiert), die
   Regel ist aus der DOM-Kette und dem Woo-Body-Klassenvertrag hergeleitet. */
body.woocommerce-account .mkd-content .mkd-content-inner > .mkd-container > .mkd-container-inner {
  padding-top: 0;
}
/* Auf dem HANDY bleibt es bei 0 (dort war der 66px-Sockel der "komische" Weissraum).
   Am DESKTOP klebte der Inhalt ("Hallo Mathias ...") dadurch aber direkt an der grauen
   Titelleiste - hier darf es atmen. --s-7 (48px) statt des unschoenen 66px-Theme-Sockels. */
@media (min-width: 1025px) {
  body.woocommerce-account .mkd-content .mkd-content-inner > .mkd-container > .mkd-container-inner {
    padding-top: var(--s-7);
  }
}

/* --- 3b. Brotkrume KOMPLETT entfernen (Kundenentscheidung 23.07., revidiert) -------
   Ursprünglich nur mobil; der Kunde hat sich umentschieden: überall raus, auch Desktop.
   Wenige Unterseiten, kein erkennbarer Mehrwert. Global, ohne Media Query. */
.mkd-title .mkd-breadcrumbs-holder,
.mkd-breadcrumbs,
.woocommerce-breadcrumb {
  display: none !important;
}

/* --- 4. Footer aufgeraeumt (mobil) -----------------------------------
   Drei gemessene Punkte:
   (a) Die Rechtslinks standen mit ~31px Leerraum zwischen den 48px-Boxen -
       zerrissen. Der Zwischenraum kommt aus den Menue-Eintraegen, nicht aus der
       Tap-Groesse; er wird gestrafft, die 48px-Tap-Hoehe bleibt.
   (b) "© 2026 Talentschmiede Bode" brach um, weil die Unterleiste zwei
       50%-Spalten (je ~179px) nutzt. Mobil werden die Spalten voll und zentriert.
   (c) "Folge mir auf:" - Instagram sass oben, TikTok darunter, weil die Spalte
       nur 149px breit war. Mit voller Breite passen beide Icons in eine Reihe. */
@media (max-width: 1024px) {

  /* (a) Rechtslinks direkt untereinander (Kundenwunsch, 2. Nachfass). Der
     Zwischenraum sass als 26px `padding-bottom` am li; zusaetzlich trug der Anker
     48px min-height + 12px Polster. Der Kunde will sie eng gestapelt -> min-height
     raus, Polster auf 6px. Die Trefferflaeche sinkt auf ~31px (ueber WCAG-AA-24px,
     bewusst unter der frueheren AAA-48px, weil hier Optik ausdruecklich vorgeht). */
  footer .mkd-footer-top .widget_nav_menu ul li,
  footer .mkd-footer-top .widget ul li {
    margin-top: 0;
    margin-bottom: 0;
    padding-bottom: 0;
  }
  footer .mkd-footer-top .widget_nav_menu ul li a,
  footer .mkd-footer-top .widget ul li a {
    min-height: 0 !important;
    padding-top: 6px !important;
    padding-bottom: 6px !important;
  }
  /* Die grossen SENKRECHTEN Luecken (23.07. nachgemessen): der Footer nutzt
     `.mkd-four-columns`; JEDE der vier Spalten traegt `margin-bottom:40px`. Spalte 3
     und 4 sind LEER, tragen ihre 40px aber trotzdem -> ~80px schwarzer Sockel unter
     "Impressum". Dazu `padding-top:75px` am Footer-Container. Mobil aufgeraeumt: */
  /* Leere Spalten (kein Widget) raus. Nur mobil - am Desktop tragen sie das
     4-Spalten-Raster, deshalb steht diese Regel in der 1024px-Abfrage. */
  footer .mkd-footer-top .mkd-column:not(:has(.widget)) {
    display: none;
  }
  /* Der 40px-Spaltenabstand faellt weg (die Widgets tragen ihren eigenen Abstand);
     gilt fuer Top UND Unterleiste, deshalb ungescoped auf `footer .mkd-column`. */
  footer .mkd-column {
    margin-bottom: 0;
  }
  /* Kopfabstand des Footers von 75px auf --s-7 (48). */
  footer .mkd-footer-top .mkd-container-inner {
    padding-top: var(--s-7);
  }
  /* Spaltenabstand traegt jetzt das Widget; Titel ("Rechtliches") enger an die Liste. */
  footer .mkd-footer-top .widget {
    margin-bottom: var(--s-5);
  }
  footer .mkd-footer-top .widget .mkd-widget-title-holder {
    margin-bottom: var(--s-4);
  }

  /* (b)+(c) Unterleiste: `.mkd-two-columns-50-50-inner` ist gemessen `display:flex`
     (Reihe), die beiden Spalten je 179px -> Copyright und Social brechen um.
     `width:100%` auf Flex-Items wirkt NICHT (Flex sizet sie); die Richtung muss
     auf `column`. Dann volle Breite, zentriert, beide Icons in einer Zeile. */
  footer .mkd-footer-bottom-holder .mkd-two-columns-50-50-inner {
    flex-direction: column;
    align-items: center;
  }
  footer .mkd-footer-bottom-holder .mkd-two-columns-50-50-inner > .mkd-column {
    width: auto;
    float: none;
    text-align: center;
  }
  /* Copyright -> Social hing an je 18px `padding-top/-bottom` an BEIDEN
     Unterleisten-Widgets (Theme) plus dem Spaltenabstand -> gemessen ~94px, und der
     gleiche 18px-Sockel machte den zu grossen Leerraum nach unten. Widget-Polster
     raus; die Luft traegt jetzt der Container (--s-4) aussen und --s-2 zwischen den
     beiden Zeilen. (Das leere <p> hat Hoehe 0 und ist unschuldig.) */
  footer .mkd-footer-bottom-holder .widget {
    padding-top: 0;
    padding-bottom: 0;
  }
  footer .mkd-footer-bottom-holder .mkd-column + .mkd-column {
    margin-top: var(--s-2);
  }
  footer .mkd-footer-bottom-holder .mkd-container-inner {
    padding-top: var(--s-4);
    padding-bottom: var(--s-4);
  }
  /* Der Text traegt ein Inline-`text-align:left` (1,0,0,0) - nur !important
     schlaegt es. Betrifft Copyright UND "Folge mir auf:". */
  footer .mkd-footer-bottom-holder .mkd-custom-font-holder {
    text-align: center !important;
    white-space: normal;
  }
  /* Die Social-Icons folgen als Inline-Elemente auf "Folge mir auf:". Sie standen
     ~40px auseinander (je 48px-Box + 4px Margin). Enger: Box auf --s-6 (32), Margin
     weg -> Glyphen ~15px auseinander. Tap-Hoehe (48) bleibt, nur die Breite schrumpft. */
  footer .mkd-footer-bottom-holder .mkd-icon-shortcode {
    display: inline-block;
  }
  /* ACHTUNG: nur Instagram ist ein `.mkd-icon-shortcode`; TikTok ist ein BLANKER
     `<a href*=tiktok>`. Block 42 traf beide ueber die textwidget-href-Selektoren
     (48px-Box + 4px Margin) - deshalb muss dieselbe Selektorgruppe her, sonst bleibt
     TikTok breit und das Paar steht schief. Auf die Unterleiste gescoped, damit die
     48px-Regel anderswo bleibt. */
  footer .mkd-footer-bottom-holder .mkd-icon-shortcode a,
  footer .mkd-footer-bottom-holder .textwidget a[href*="instagram"],
  footer .mkd-footer-bottom-holder .textwidget a[href*="tiktok"] {
    min-width: var(--s-6);
    margin-left: 0;
    margin-right: 0;
  }
  /* Das Instagram-Piktogramm traegt inline `margin:0 6px` (1,0,0,0). Auf 2px. */
  footer .mkd-footer-bottom-holder .mkd-icon-shortcode i {
    margin-left: 2px !important;
    margin-right: 2px !important;
  }
}
/* ===== TSB-BLOCK:anmerkungen-2026-07-23 END ===== */


/* ===== TSB-BLOCK:formular-abstand START ===== */
/* Formular: Abstand Label zu textarea  [TSB-BLOCK:formular-abstand]
   ------------------------------------------------------------------
   Gemessen 23.07.: der Abstand Beschriftung -> textarea war 39px, bei jedem anderen
   Feld 14px. Ursache ist ein <br> zwischen Label und textarea-Wrap, das die anderen
   Felder nicht haben (CF7-Markup-Inkonsistenz in der DB-Formulardefinition). Statt die
   acht Formulare in der Datenbank anzufassen, wird das <br> per CSS entfernt - aber NUR
   in Absaetzen, die eine textarea enthalten, damit keine gewollte Zeile woanders faellt.
   Danach traegt der Abstand wieder Label-margin (6px) + Feld-margin (8px) = 14px. */
.wpcf7-form p:has(> span.wpcf7-form-control-wrap textarea) br,
.wpcf7-form label:has(+ br + span.wpcf7-form-control-wrap textarea) + br {
  display: none;
}
/* ===== TSB-BLOCK:formular-abstand END ===== */


/* ===== TSB-BLOCK:ust START ===== */
/* 49. Umsatzsteuer-Hinweis nach § 19 UStG  [TSB-BLOCK:ust]  (23.07.2026)
   ----------------------------------------------------------------------------
   Eine Zeile, ueberall dieselbe. Markup und Wortlaut kommen aus
   mu-plugins/tsb-ust.php - hier steht nur, wie sie aussieht.

   Sie soll leise sein und trotzdem lesbar: --muted ist 5,76:1 auf Weiss, also
   auch bei 14px ueber AA. Kein kleinerer Grad als --fs-sm, sonst waere die
   Pflichtangabe kleiner als jede Fussnote der Seite.

   --eng ist die Fassung im Shop, wo die Zeile innerhalb einer Karte oder direkt
   unter dem Preis sitzt und den Bandtakt nicht selbst tragen muss.

   ZWEI GEMESSENE FALLSTRICKE, beide am 23.07. erst im Bild aufgefallen:

   1. Der Seitenrand kam DOPPELT. Die Startseite nutzt full-width.php, dort haengt die
      Zeile in .mkd-full-width-inner und braucht den Gutter selbst. Alle anderen Seiten
      liegen in .mkd-container-inner, der ihn schon traegt - dort schob die eigene
      padding-inline den Text um 22px (Desktop) bzw. 16px (mobil) gegen den Rest der
      Seite. Deshalb die zweite Regel: im Container KEIN eigener Rand. Gemessen wurde
      gegen die linke Kante der Nachbarelemente, nicht geschaetzt.

   2. KEIN box-sizing setzen. Im WPBakery-Bestand gilt content-box, und die Baender der
      Startseite (.tsb-start .tsb-inner) rechnen genauso: max-width 1100 PLUS Polster,
      Kante bei 90px. Mit border-box waere die Zeile 22px nach innen gerutscht und haette
      als einzige nicht mehr mit den Baendern darueber gefluchtet.
*/
.tsb-ust{
  max-width: var(--w-page);
  margin-left: auto;
  margin-right: auto;
  padding-inline: var(--gutter);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
}
.mkd-container-inner .tsb-ust{
  padding-inline: 0;
}
.tsb-ust p{
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
}
.tsb-ust--eng{
  padding-inline: 0;
  padding-top: var(--s-3);
  padding-bottom: 0;
}
/* ===== TSB-BLOCK:ust END ===== */


/* ===== TSB-BLOCK:struktur START — nicht von Hand bearbeiten, Quelle:
        scripts/struktur-2026-07-24/abschnitt-50-struktur.css ===== */
/* ----------------------------------------------------------------------------
   50. Strukturangleichung  [TSB-BLOCK:struktur]           24.07.2026

   Drei zurueckgestellte Strukturbefunde aus dem Mobil-Audit (22.07.), jetzt
   umgesetzt. Die zwei Hero-Seiten bekommen zusaetzlich neues Markup
   (Skript 01-hero-umbau.php), die Gutscheinkacheln eine Textzeile
   (Skript 02-betragskacheln.php).

   NICHT enthalten:
   - Bandkante hell gegen hell: im Bild geprueft und VERWORFEN (24.07., Kunde).
     Der Messwert 1,086:1 beschreibt den Kontrast der beiden Flaechen und ist
     schwach - im Bild traegt der Wechsel trotzdem, weil das Auge auf die Kante
     reagiert und nicht auf den Absolutwert. Vier Staerken wurden im echten
     Seitenkontext gegenuebergestellt. Nicht erneut vorschlagen.
   - Startseiten-Reihenfolge: eigener Eingriff in post_content, gehoert zu D3.
   - SSA-Kalender-Optik: ohne Login nicht messbar, gehoert zu D2.
   - Partner-Logoleiste: bereits durch mu-plugin tsb-partner-logos.php geloest.
   ------------------------------------------------------------------------- */


/* === 50.1  Hero-Variante mit Produktgrafik ================================
   Bonuskarte und Geschenkgutschein trugen als einzige zwei Seiten einen
   Karten-Hero: weisse Flaeche, 1px Rahmen, 18px Radius, Schlagschatten, und
   rechts daneben eine dunkle Bildflaeche. Die anderen sieben Seiten nutzen
   dxa-hero, dessen Leitgedanke ausdruecklich lautet: der Seitenanfang ist
   kein Element AUF der Seite, sondern das erste Band DER Seite.

   Die Produktgrafik (.bcard / .gcard) bleibt erhalten - sie erklaert das
   Produkt und ist auf diesen zwei Seiten der Ersatz fuer das fehlende Foto.
   Sie steht jetzt frei im Band statt in einer eigenen Farbflaeche; die Karte
   traegt ihre Optik selbst, deshalb faellt nur der Rahmen darum weg.

   Warum ein Grid und keine absolute Positionierung wie beim Foto:
   .dxa-hero-media haengt absolut am rechten Bandrand und darf beschnitten
   werden. Eine Produktgrafik darf das nicht - sie ist Inhalt, kein Dekor.
   Sie braucht ihre Eigenhoehe und muss vollstaendig sichtbar bleiben.      */

.tsb .dxa-hero--grafik .dxa-hero-inner{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: var(--s-8);
  row-gap: 0;
  align-items: center;
}

.tsb .dxa-hero--grafik .dxa-hero-text{ grid-column: 1; grid-row: 1 }

.tsb .dxa-hero-vis{
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
}

/* Die Kennzahlenzeile spannt unter beidem durch, wie beim Foto-Hero auch. */
.tsb .dxa-hero--grafik .dxa-facts{ grid-column: 1 / -1; grid-row: 2 }

/* Unter 1024px einspaltig. Der Umbruch ist bewusst FEST gesetzt und nicht
   ueber auto-fit geregelt: die Karte ist 300 bis 320px breit, daneben braucht
   die H1 "Geschenkgutschein" bei --fs-3xl rund 430px. Zusammen mit dem
   Spaltenabstand kippt das rechnerisch schon bei rund 830px Inhaltsbreite -
   also mitten im Tablet-Bereich, wo auto-fit den Text dann ueber die volle
   Bandbreite laufen liesse. */
@media (max-width: 1024px){
  .tsb .dxa-hero--grafik .dxa-hero-inner{ grid-template-columns: 1fr }
  .tsb .dxa-hero--grafik .dxa-hero-text{ grid-row: 1 }
  .tsb .dxa-hero-vis{
    grid-column: 1;
    grid-row: 2;
    justify-self: start;
    margin-top: var(--s-7);
  }
  .tsb .dxa-hero--grafik .dxa-facts{ grid-row: 3 }
}


/* === 50.2  Ziffernmarke der Schrittketten ================================
   Es gibt zwei Schrittketten-Bauformen, und das bleibt auch so: die
   waagerechte (.tsb-flow, 5 Seiten) fasst kurze Schritte nebeneinander, die
   senkrechte (.dxa-steps, Einzeltraining) traegt Flieusstext je Schritt. Zwei
   Aufgaben, zwei Formen - das Zusammenlegen haette die laengeren Texte in
   eine 48px-Spalte gezwungen.

   Angeglichen wird nur die MARKE, weil sie dieselbe Bedeutung hat: "Schritt
   Nummer n". Sie stand als dunkler Kreis mit weisser Ziffer (5 Seiten) neben
   einem hellgruenen Kreis mit gruener Ziffer (1 Seite). Die Mehrheit gibt die
   Form vor.

   Der Kontrast steigt dabei von 4,9:1 (Akzent auf --accent-soft) auf 17,4:1
   (weiss auf --ink). */

.tsb .dxa-steps-n{
  background: var(--ink);
  color: var(--on-dark);
}

/* Die Verbindungslinie der senkrechten Kette folgt der Marke: sie war
   --line (#e6e9e6) und damit deutlich blasser als die Linie der waagerechten
   Kette, die in --accent verlaeuft. */
.tsb .dxa-steps > li:not(:last-child) .dxa-steps-n::after{
  width: 2px;
  background: linear-gradient(180deg, var(--accent), rgba(10, 107, 46, .3));
}


/* === 50.3  Betragskacheln als Bedienelement ==============================
   Die drei Kacheln auf /geschenkgutschein/ (35 / 105 / 175 Euro) legen direkt
   in den Warenkorb, sahen aber aus wie die Infokarten derselben Seite. Hover
   und Fokusring sind vorhanden und wurden nachgemessen (2px solid --accent,
   Offset 3px, per echtem Tab-Durchlauf geprueft) - es fehlte allein die
   Ansage, dass ein Klick etwas ausloest.

   Die Abschlusszeile ist dieselbe Bauform wie bei den .ptile-Angebotskacheln.
   Der Text steht im Markup, nicht in einem ::after: eine Handlungsansage ist
   Inhalt und muss vorgelesen werden koennen. */

.tsb .amt{
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}

.tsb .amt-cta{
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-xs);
  line-height: var(--lh-flat);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--accent);
}

/* Der Pfeil ist Dekor und darf dem Screenreader entgehen. */
.tsb .amt-cta::after{
  content: " \2192";
  white-space: nowrap;
}
/* ===== TSB-BLOCK:struktur END ===== */







/* ===== TSB-BLOCK:qualifikation START — Quelle: scripts/qualifikation-2026-07-23/abschnitt-48.css ===== */
/* ---------------------------- 48. Qualifikation & Sicherheit  [TSB-BLOCK:qualifikation]
 *
 * Vertrauensblock auf der Porträtseite (#5746): "Erweitertes Führungszeugnis liegt vor."
 * und "Aktueller Erste-Hilfe-Kurs." Nur als AUSSAGE, nie als Dokument (das Führungszeugnis
 * enthält personenbezogene Daten und gehört nicht ins Web).
 *
 * POSITION: im Textkopf direkt NACH der Beleg-Leiste (.tsb-belege: 30+/10+/DFB B) und VOR
 * der Unterschrift. Begründung: beides ist dieselbe Sorte Nachweis wie die DFB-Lizenz -
 * alle Qualifikationen stehen so beieinander, im ersten sichtbaren Band.
 *
 * Reine Textkomponente (kein Bild). Häkchen als inline-SVG mit stroke="currentColor",
 * Farbe kommt per CSS `color` (kein Hex-Literal - Regel des Designsystems). Scope
 * ".tsb .tsb-qual" (0,2,0), damit Theme-Ketten mit :not() nicht gewinnen.
 * -------------------------------------------------------------------------------------- */
.tsb .tsb-qual{
  /* KEINE max-width: die Box soll die volle Spaltenbreite tragen, exakt so breit
     wie die Beleg-Leiste .tsb-belege direkt darueber (Kundenwunsch 06.08.). Frueher
     stand hier max-width:var(--w-read) - das machte die Box schmaler als die Belege. */
  /* Abstand einzeln, nie die margin-Kurzschreibweise (Media-Query-Falle). */
  margin-top: var(--s-6);
  margin-bottom: var(--s-6);
  /* Ebenso padding einzeln (eine Media-Query hat hier im Projekt schon still
     ein padding-top ueberschrieben). */
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-left: var(--s-5);
  padding-right: var(--s-5);
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-md);
  box-shadow: var(--sh-card);
}
.tsb .tsb-qual__kick{
  margin: 0 0 var(--s-4);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-xs);
  letter-spacing: var(--track-kicker);
  text-transform: uppercase;
  color: var(--accent);
}
.tsb .tsb-qual__list{
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}
.tsb .tsb-qual__item{
  display: flex;
  gap: var(--s-4);
  align-items: flex-start;
}
.tsb .tsb-qual__ic{
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  margin-top: 1px;
  border-radius: var(--r-pill);
  background: var(--accent-soft);
  color: var(--accent);
  display: grid;
  place-items: center;
}
.tsb .tsb-qual__ic svg{ display: block }
.tsb .tsb-qual__t{
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--fs-md);
  line-height: var(--lh-flat);
  color: var(--ink);
}
.tsb .tsb-qual__s{
  display: block;
  margin-top: 3px;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--muted);
}
@media (max-width: 480px){
  .tsb .tsb-qual__t{ font-size: var(--fs-base) }
}
/* ===== TSB-BLOCK:qualifikation END ===== */






/* ===== TSB-BLOCK:dxa-fullbleed START ===== */
/* 52. [TSB-BLOCK:dxa-fullbleed] dxa-hero: rechter Auslauf am Rasterrand (06.08.).
   Das Foto endet BUENDIG am 1300px-Rasterrand (Basisregel .dxa-hero-media: right:0 +
   .dxa-hero overflow:hidden) - also dort, wo auch der Textinhalt/die Trennlinien enden,
   NICHT am Viewportrand. Ein frueher probierter fullbleed-Shift (right:calc + overflow:
   visible, Bild bis zum Bildschirmrand) wurde bewusst verworfen (Kundenwunsch 06.08.:
   das Bild soll da enden, wo es vorher endete - weiter links - und dort auslaufen).

   Deshalb setzt dieser Block NUR die Maske: die horizontale Maske laeuft jetzt auch nach
   rechts aus, SYMMETRISCH zum linken Rand (gleiche Rampenlaenge 36 %, gespiegelt):
   links Fade 6 % -> 34 %, voll 34 % -> 72 %, rechts Fade 72 % -> 100 % (weich bis zur
   Rasterkante). Der 2. Maskenlayer (unten) und mask-composite (intersect) werden von der
   Basisregel getragen. Nur >768px (mobil ist das Foto ein voller Streifen).
   (Alpha-Stopps der Maske sind Deckkraft, keine Farbe - Ausnahme von "nur var()".) */
@media (min-width: 769px){
  .tsb .dxa-hero-media{
    -webkit-mask-image:
      linear-gradient(90deg, transparent 0, transparent 6%, #000 34%, #000 72%, transparent 100%),
      linear-gradient(to top, transparent 0, #000 34%);
    mask-image:
      linear-gradient(90deg, transparent 0, transparent 6%, #000 34%, #000 72%, transparent 100%),
      linear-gradient(to top, transparent 0, #000 34%);
  }
}
/* ===== TSB-BLOCK:dxa-fullbleed END ===== */


/* ===== TSB-BLOCK:termine-ux START ===== */
/* 54. [TSB-BLOCK:termine-ux] Termin-buchen-Seite, unangemeldeter Zustand (07.08.).
 *
 * Vorher: drei konkurrierende H2 (Intro "Buche deine Trainingsstunden online",
 * Plugin "Termin buchen", "Anmelden") + viele Schriftgroessen, kein klarer Weg.
 * Die redundante Plugin-Intro ("Termin buchen") wurde im Shortcode entfernt
 * (inc/frontend.php). Bleibt: EINE Hauptueberschrift + 3-Schritt-Prozess +
 * EIN Handlungsblock. Dieser Block macht den Handlungsblock zur klaren, zentrierten
 * Aktions-Karte, damit "so nutzt man die Seite" auf einen Blick sichtbar ist.
 * Scope eng auf den Anmelde-Zweig, damit der Login anderswo unberuehrt bleibt.
 * ------------------------------------------------------------------------------------------ */

/* Die Anmelde-Karte: der eine, klare naechste Schritt. */
.tsb-buchung--anmelden .tsb-login{
  max-width: 34rem;
  margin-inline: auto;
  margin-top: var(--s-7);
  padding: var(--s-6);
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-md);
  box-shadow: var(--sh-card);
  text-align: left;
}
.tsb-buchung--anmelden .tsb-login__titel{
  margin-top: 0;
  margin-bottom: var(--s-3);
  font-size: var(--fs-lg);
}
.tsb-buchung--anmelden .tsb-login__text{
  margin-top: 0;
  margin-bottom: var(--s-5);
  font-size: var(--fs-base);
  color: var(--ink-body);
}
.tsb-buchung--anmelden .tsb-login__form .tsb-btn{ width: 100%; margin-top: var(--s-2); }

/* Der Alternativen-Hinweis: zentriert unter der Karte, dezent. */
.tsb-buchung--anmelden .tsb-buchung__fuss{
  max-width: 34rem;
  margin-inline: auto;
  margin-top: var(--s-5);
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--muted);
}
/* ===== TSB-BLOCK:termine-ux END ===== */


/* ===== TSB-BLOCK:termine-header-abstand START ===== */
/* 55. [TSB-BLOCK:termine-header-abstand] Abstand unter dem Titelbalken auf der Buchungsseite (07.08.).
 *   Der frueher GLOBALE margin-bottom auf .mkd-title (Abschnitt 53) wurde am 07.08. global entfernt
 *   (anderswo "zu viel", parallele Sitzung). Auf /termine/ (#573, Einzeltraining-Buchung) war der
 *   Abstand aber gewuenscht und schon geloest - hier SEITEN-SPEZIFISCH wiederhergestellt, damit die
 *   globale Entscheidung unberuehrt bleibt. Nur >768px (mobil ist der Titelbalken ausgeblendet). */
@media (min-width: 769px){
  body.page-id-573 .mkd-title{ margin-bottom: var(--s-7) }
}
/* ===== TSB-BLOCK:termine-header-abstand END ===== */

/* ===== 56. [TSB-BLOCK:wahl] Buchungs-Auswahl auf /termine/ (Einzel- vs. Gruppentraining) ===== */
/* ===== TSB-BLOCK:wahl START ===== */
.tsb .tsb-wahl{ display:grid; gap:var(--s-4); grid-template-columns:1fr; margin-top:var(--s-6) }
.tsb .tsb-wahl__karte{
  display:flex; flex-direction:column;
  background:var(--surface); border:var(--b-hair); border-radius:var(--r-lg);
  box-shadow:var(--sh-card); padding:var(--s-5);
  transition:transform .15s ease, box-shadow .15s ease;
}
.tsb .tsb-wahl__karte:hover{ transform:translateY(-3px); box-shadow:0 16px 30px -18px rgba(20,22,21,.35) }
.tsb .tsb-wahl__karte h3{ margin:0 0 var(--s-2); font:700 var(--fs-lg)/var(--lh-flat) var(--font-head); color:var(--ink) }
.tsb .tsb-wahl__karte p{ margin:0 0 var(--s-4); color:var(--ink-body); font-size:var(--fs-base); line-height:var(--lh-base) }
.tsb .tsb-wahl__karte .tsb-btn{ margin-top:auto; align-self:flex-start }
@media (min-width:768px){ .tsb .tsb-wahl{ grid-template-columns:repeat(2,1fr) } }
/* Abstand der Auswahl-Section zum Footer (sonst klebt er an den Kacheln). padding, kein margin (Collapse). */
body.page-id-573 .tsb-tm{ padding-bottom:var(--s-8) }
/* ===== TSB-BLOCK:wahl END ===== */

/* ===== 57. [TSB-BLOCK:buchung-v2] Buchungsbereich neu: zwei Schritte, Chips, Kaufen, Login ===== */
/* ===== TSB-BLOCK:buchung-v2 START ===== */
/* Auslastungsfarbe "nur noch wenige frei" - semantisch, NICHT der Akzent. Neue Rolle. */
:root{ --warn:#c67c00 }

/* Nummerierter Schritt */
.tsb .tsb-buchung__step{ display:grid; grid-template-columns:auto 1fr; gap:var(--s-4) }
.tsb .tsb-buchung__step + .tsb-buchung__step{ margin-top:var(--s-5); padding-top:var(--s-5); border-top:var(--b-hair) }
.tsb .tsb-buchung__step-n{ width:28px; height:28px; border-radius:var(--r-full); background:var(--accent); color:var(--on-dark);
  font:700 var(--fs-base)/1 var(--font-head); display:grid; place-items:center }
.tsb .tsb-buchung__step-body{ min-width:0 }
.tsb .tsb-buchung__step-t{ font:700 var(--fs-md)/var(--lh-flat) var(--font-head); color:var(--ink) }
.tsb .tsb-buchung__step-sub{ display:block; font-size:var(--fs-sm); color:var(--muted); font-weight:400; margin-top:var(--s-1) }

/* Guthaben-Stand: accent-soft-Box, eine Zeile */
.tsb .tsb-buchung__gh{ display:flex; align-items:center; justify-content:space-between; gap:var(--s-3);
  background:var(--accent-soft); border-radius:var(--r-md); padding:var(--s-3) var(--s-4); margin-top:var(--s-3) }
.tsb .tsb-buchung__gh-l{ display:block; font-size:var(--fs-xs); color:var(--muted); font-weight:600 }
.tsb .tsb-buchung__gh-b{ font:700 var(--fs-xl)/var(--lh-flat) var(--font-head); color:var(--accent); letter-spacing:var(--track-tight) }
.tsb .tsb-buchung__gh-r{ font-size:var(--fs-sm); color:var(--ink-body); margin-left:var(--s-2) }

/* Kaufen-Zeile + Alternativen */
.tsb .tsb-buchung__kaufen{ display:flex; align-items:center; justify-content:space-between; gap:var(--s-3); flex-wrap:wrap;
  border:var(--b-hair); border-radius:var(--r-md); padding:var(--s-3) var(--s-4); margin-top:var(--s-3) }
.tsb .tsb-buchung__kf-txt{ font-size:var(--fs-sm); color:var(--ink-body) }
.tsb .tsb-buchung__kf-txt strong{ color:var(--ink); font-weight:700 }
.tsb .tsb-buchung__kf-alt{ font-size:var(--fs-sm); color:var(--muted); margin:var(--s-3) 0 0; line-height:var(--lh-base) }
.tsb .tsb-buchung__kf-alt a{ color:var(--accent); font-weight:600 }

/* Termin-Chips (Gruppe): nur die Zahl, kein Balken */
.tsb .tsb-buchung__chips{ display:grid; grid-template-columns:repeat(auto-fit,minmax(128px,1fr)); gap:var(--s-2); margin-top:var(--s-3) }
.tsb .tsb-buchung__chip{ font:inherit; text-align:left; cursor:pointer; background:var(--surface);
  border:1.5px solid var(--line); border-radius:var(--r-md); padding:var(--s-3);
  display:flex; flex-direction:column; gap:var(--s-1) }
.tsb .tsb-buchung__chip:hover{ border-color:color-mix(in srgb, var(--accent) 40%, var(--line)) }
.tsb .tsb-buchung__chip.is-selected{ border-color:var(--accent); background:var(--accent-soft) }
.tsb .tsb-buchung__chip[disabled],
.tsb .tsb-buchung__chip.is-info{ cursor:default }
.tsb .tsb-buchung__chip.is-info:hover{ border-color:var(--line) }
.tsb .tsb-buchung__chip-d{ font-weight:700; color:var(--ink); font-size:var(--fs-md) }
.tsb .tsb-buchung__chip-f{ font-size:var(--fs-base); font-weight:600; color:var(--muted); font-variant-numeric:tabular-nums }
.tsb .tsb-buchung__chip-f strong{ color:var(--accent); font-weight:700 }
.tsb .tsb-buchung__chip-f.is-low strong{ color:var(--warn) }

/* Anzahl Kinder */
.tsb .tsb-buchung__anzahl{ display:flex; align-items:center; justify-content:space-between; gap:var(--s-3); flex-wrap:wrap; margin-top:var(--s-4) }
.tsb .tsb-buchung__anzahl-l{ font-size:var(--fs-base); color:var(--ink-body); font-weight:600 }
.tsb .tsb-buchung__stepper{ display:flex; gap:var(--s-2) }
.tsb .tsb-buchung__stepper button{ font:inherit; font-weight:700; width:40px; height:40px; border-radius:var(--r-sm);
  border:1.5px solid var(--line); background:var(--surface); color:var(--ink); cursor:pointer; font-variant-numeric:tabular-nums }
.tsb .tsb-buchung__stepper button.is-on{ background:var(--accent); border-color:var(--accent); color:var(--on-dark) }
.tsb .tsb-buchung__stepper button[disabled]{ opacity:.3; cursor:not-allowed }

/* Anmeldung (ausgeloggter Zustand) */
.tsb .tsb-buchung__login{ background:var(--accent-soft); border-radius:var(--r-md); padding:var(--s-4); margin-top:var(--s-3) }
.tsb .tsb-buchung__login-t{ font:700 var(--fs-base)/var(--lh-flat) var(--font-head); color:var(--ink) }
.tsb .tsb-buchung__login-p{ font-size:var(--fs-sm); color:var(--ink-body); margin:var(--s-2) 0 var(--s-3); line-height:var(--lh-base) }
.tsb .tsb-buchung__login-form{ display:flex; gap:var(--s-2); flex-wrap:wrap }
.tsb .tsb-buchung__login-form input{ flex:1 1 150px; min-width:0; font:inherit; font-size:var(--fs-sm);
  padding:11px 13px; border:var(--b-field); border-radius:var(--r-sm); background:var(--surface); color:var(--ink) }
.tsb .tsb-buchung__login-form input::placeholder{ color:var(--muted) }
.tsb .tsb-buchung__login-hint{ font-size:var(--fs-sm); color:var(--muted); margin:var(--s-3) 0 0; line-height:var(--lh-base) }

/* Abstand ueber dem Kalender/Formular, damit er nicht am Schritt-Untertitel bzw. an den
   Chips klebt. Bei der Gruppe im eingeklappten Zustand per JS auf 0 gesetzt (kein Leerraum). */
.tsb .tsb-buchung__kalender{ margin-top:var(--s-4) }

@media (max-width:520px){
  .tsb .tsb-buchung__step{ grid-template-columns:1fr; gap:var(--s-2) }
}
/* ===== TSB-BLOCK:buchung-v2 END ===== */

/* ===== TSB-BLOCK:header-feinschliff START ===== */
/* 53. [TSB-BLOCK:header-feinschliff] Titelbalken-Lesbarkeit (06.–07.08., korrigiert 10.08.).
 *
 * LESBARKEIT des Titelbalkens. Titel + Subtitle sind weiß (mkd_page_title_color = #fff),
 * auf hellen Fotos (Himmel) kaum lesbar. Lösung: ein ZENTRIERTER Scrim hinter dem Text
 * (radial, Mitte abgedunkelt) - die Bildränder mit den Personen bleiben hell/lebendig -
 * plus ein Textschatten. Kein Umbau des Balkens, das Foto bleibt sichtbar.
 * Ausnahme von "nur var()": rgba(0,0,0,a) sind Deckkraft-/Schatten-Alphawerte, keine
 * Farb-Designentscheidung (dieselbe Ausnahme wie bei den Foto-Masken).
 *
 * ⚠️ KORREKTUR 10.08.2026 — der Scrim hing an ALLEN Titelbalken, nicht nur an den bebilderten.
 * Vier Seiten tragen einen Balken OHNE Bild (Shop, Warenkorb, Kasse, Mein Konto; Theme-Klasse
 * `mkd-has-background` fehlt dort, Balkenhöhe 114px statt 366px, Fläche #f0f0ef). Auf diesen
 * legte der radiale Verlauf einen dunklen Schleier über die helle Fläche und den schwarzen
 * Titel - gemessen als grauer Verlauf mit dunkler Mitte, der wie ein Rendering-Fehler aussah.
 * Der Textschatten verschmierte den dunklen Titel zusätzlich.
 * Deshalb hängen Scrim UND Schatten jetzt an `.mkd-has-background`. Die Klasse setzt das Theme
 * in framework/modules/title/filter-functions.php genau dann, wenn ein Bild vorhanden ist -
 * sie ist damit die richtige Bedingung und nicht bloß ein Symptom.
 *
 * HINWEIS: Der frühere Teil (a) "Abstand unter den Headern" (margin-bottom auf .dxa-hero /
 * .mkd-title) wurde am 07.08. auf Kundenwunsch wieder ENTFERNT (war zu viel, wird anders gelöst).
 * ------------------------------------------------------------------------------------------ */
.mkd-title{ position: relative }
.mkd-title .mkd-title-holder{ position: relative; z-index: 2 }
.mkd-title.mkd-has-background::after{
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 55%,
    rgba(0,0,0,.5) 0%, rgba(0,0,0,.32) 45%, transparent 80%);
}
.mkd-title.mkd-has-background .mkd-page-title,
.mkd-title.mkd-has-background .mkd-page-subtitle{ text-shadow: 0 2px 10px rgba(0,0,0,.5) }
/* ===== TSB-BLOCK:header-feinschliff END ===== */










/* ===== TSB-BLOCK:trainer-foto START ===== */
/* 59. [TSB-BLOCK:trainer-foto] Foto neben dem Trainerblock (10.08.2026).
 *
 * ANLASS: Der Block "04 Wer trainiert" auf /einzeltraining/ (#288) behauptet, dass bei
 * jeder Einheit dieselbe Person auf dem Platz steht, zeigte diese Person aber nicht.
 *
 * Der Container .dxa-trainer hatte bis hierher keine eigene Regel, nur seine Kinder.
 * Er wird jetzt zum zweispaltigen Raster. Das Markup dazu setzt trainer-foto.php:
 * die drei Textteile liegen in .dxa-trainer-text, das Bild daneben in .dxa-trainer-foto.
 *
 * ⚠️ .dxa-trainer kommt ausschliesslich auf #288 vor (gemessen 10.08. ueber alle Seiten
 * und Produkte, auch in den base64-Bloecken). Diese Regel trifft also nichts anderes.
 * Falls der Block je auf eine zweite Seite kommt, muss er das Foto mitbringen, sonst
 * bleibt rechts eine leere Spalte stehen.
 * ------------------------------------------------------------------------------- */

/* --- Das Raster spannt sich ueber den GANZEN Abschnitt ------------------------- */
/*
   Kundenrueckmeldung 10.08.: das Bild soll wieder hochformatig sein und schon neben der
   Ueberschrift beginnen. Das eine bedingt das andere. Als das Raster nur den Textteil
   unter der Ueberschrift umfasste, war die linke Spalte 269px hoch, und ein 4:5-Bild
   mit 425px haette darunter ein Loch von 156px hinterlassen. Mit Ueberschrift und Lead
   in derselben Spalte stehen rund 450px zur Verfuegung, und das Hochformat passt.

   Das Markup dazu setzt trainer-foto-hoch.php: .dxa-trainer-saeule ist das Raster,
   .dxa-trainer-haupt die linke Spalte mit allem Text, .dxa-trainer-foto die rechte.
*/
.tsb .dxa-trainer-saeule{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
  gap: var(--s-8);
  align-items: start;
}


/*
   ⚠️ KEIN aspect-ratio auf dem Desktop, und das ist der Kern dieser Regel.
   Die Datei ist 4:5. Bei 340px Spaltenbreite waere die figure damit 425px hoch,
   der Text daneben ist aber nur 269px hoch - gemessen 10.08. bei 1400px Fenster.
   Ergebnis war ein 156px hohes Loch unter der Textspalte. Statt das Bild kleiner
   zu rechnen (dann wirkt es beliebig) laesst align-self:stretch die figure exakt
   so hoch werden wie die Textspalte. Wird der Text spaeter laenger oder kuerzer,
   zieht das Bild mit, ohne dass hier jemand nachrechnen muss.

   object-position haelt dabei den Kopf im Bild: der sichtbare Streifen wandert
   sonst in die Mitte, und dort ist der Gymnastikball, nicht das Gesicht.
   min-height faengt sehr breite Fenster ab, wo der Text auf wenige Zeilen
   zusammenlaeuft und das Bild sonst zum Briefschlitz wuerde.
*/
.tsb .dxa-trainer-foto{
  margin: 0;
  position: relative;
  align-self: stretch;
  min-height: 420px;
  border-radius: var(--r-md);
  overflow: hidden;
  background-color: var(--surface-alt);
}
/*
   ⚠️ Das Bild MUSS absolut liegen, sonst wirkt align-self:stretch nicht.
   Gemessen: mit `height:100%` im Fluss loest der Prozentwert gegen einen Elternteil
   ohne feste Hoehe zu `auto` auf. Das Bild nimmt dann seine natuerliche Hoehe an
   (340px Breite mal 1000/800 = 425px), die figure waechst mit, und die figure setzt
   damit die Zeilenhoehe des Rasters, an der sie sich eigentlich orientieren sollte.
   Das Ergebnis sieht exakt so aus wie ohne stretch, und im Messwert steht die Zahl
   ohne Hinweis darauf, dass die Regel wirkungslos ist.
   Aus dem Fluss genommen traegt das Bild nichts mehr zur Hoehe bei: die Zeile ist
   so hoch wie der Text (oder min-height), und das Bild fuellt sie.
*/
.tsb .dxa-trainer-foto img{
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}

@media (max-width: 900px){
  /* Einspaltig. Ohne Breitenbegrenzung wuerde das Hochformat auf einem Handy
     ueber 450px hoch und schoebe die Kennzahlen aus dem Bild. */
  .tsb .dxa-trainer-saeule{
    grid-template-columns: 1fr;
    gap: var(--s-6);
  }
  /* Einspaltig gibt es keine Nachbarspalte mehr, an der sich die Hoehe messen
     koennte. Hier traegt das Seitenverhaeltnis der Datei die Hoehe. */
  .tsb .dxa-trainer-foto{
    align-self: auto;
    min-height: 0;
    aspect-ratio: 4 / 5;
    max-width: 340px;
    margin-inline: auto;
    width: 100%;
  }
}
/* ===== TSB-BLOCK:trainer-foto END ===== */






/* ===== TSB-BLOCK:kaufstrecke START ===== */
/* 58. [TSB-BLOCK:kaufstrecke] Titelbalken ohne Bild + Schrittanzeige (10.08.2026).
 *
 * ANLASS: Vier Seiten tragen einen Titelbalken OHNE Foto - Shop, Warenkorb, Kasse,
 * Mein Konto. Sie wirkten grau und defekt. Ursache war nicht das fehlende Bild,
 * sondern der Scrim aus Abschnitt 53, der an ALLEN Balken hing (dort korrigiert).
 * Hier bekommt der unbebilderte Balken jetzt eine eigene, absichtliche Form.
 *
 * ⚠️ REIHENFOLGE: dieser Abschnitt muss NACH 53 stehen. Er setzt die Balkenfläche,
 * 53 setzt Scrim und Textschatten - beide greifen auf .mkd-title, und bei gleicher
 * Spezifität entscheidet die Reihenfolge.
 * ------------------------------------------------------------------------------- */

/* --- a) Der Balken ohne Bild ---------------------------------------------------- */
/*
   Das Theme legt hier #f0f0ef an. Das ist ein vierter Grauton neben --surface-alt
   (#f4f6f4), und der Unterschied ist genau die Art "fast gleich", die von Hand
   gemacht aussieht. Deshalb auf das vorhandene Token gezogen: der Streifen mit der
   Schrittanzeige darunter trägt dieselbe Fläche und schließt fugenlos an.
*/
.mkd-title:not(.mkd-has-background){
  background-color: var(--surface-alt);
}
/* Grüne Unterkante als Abschluss - aber nur, wenn NICHT die Schrittanzeige folgt,
   die trägt sie sonst ein zweites Mal. Die Klasse setzt tsb-kaufstrecke.php. */
.mkd-title:not(.mkd-has-background):not(.tsb-hat-kaufweg){
  border-bottom-width: 3px;
  border-bottom-style: solid;
  border-bottom-color: var(--accent);
}

/* --- b) Schrittanzeige der Kaufstrecke ------------------------------------------ */
/*
   ABSTAENDE, gemessen am 10.08. und nach Kundenrueckmeldung korrigiert.
   Vorher: der Balken hatte die feste Theme-Hoehe von 114px und der Titel stand darin
   vertikal zentriert. Unter der Ueberschrift blieben dadurch 43px Balkenrest stehen,
   bevor die Schrittzeile begann, waehrend darunter nur 19px bis zur gruenen Kante
   folgten. Der Titel klebte also an der Schrittzeile und die Schrittzeile an der Kante,
   und zwar in der falschen Reihenfolge: der groessere Abstand gehoert NACH die Schritte,
   nicht davor, weil die Schritte zum Titel gehoeren.

   Deshalb bekommt der Balken auf diesen Seiten seine Hoehe aus dem Inhalt und die
   Abstaende werden hier gesetzt: 32px ueber dem Titel, 16px zwischen Titel und
   Schritten, 24px unter den Schritten. Gesamthoehe damit rund 116px statt 155px.

   ⚠️ height:auto braucht !important. Das Theme setzt die Balkenhoehe als Inline-Style
      auf .mkd-title UND auf .mkd-title-holder (title.php, beide aus $title_height).
*/
.mkd-title.tsb-hat-kaufweg,
.mkd-title.tsb-hat-kaufweg .mkd-title-holder{
  height: auto !important;
}
.mkd-title.tsb-hat-kaufweg .mkd-title-holder{
  padding-top: var(--s-6);
  padding-bottom: var(--s-4);
}

.tsb-kaufweg{
  background-color: var(--surface-alt);
  border-bottom-width: 3px;
  border-bottom-style: solid;
  border-bottom-color: var(--accent);
  padding-top: 0;
  padding-bottom: var(--s-5);
}
/*
   ⚠️ Das Theme setzt `.mkd-container{ background-color:#fff }` (modules.css:488).
   Der Container ist hier nur da, damit die Schrittzeile mit der Überschrift im Balken
   fluchtet - seine weiße Fläche schnitt aber einen weißen Streifen quer durch den
   grauen Streifen. Im Messwert fällt das nicht auf: getComputedStyle des <nav> meldet
   weiterhin die graue Fläche, sichtbar wird es nur im Bild.
*/
.tsb-kaufweg .mkd-container{ background-color: transparent }

.tsb-kaufweg .tsb-kaufweg__liste{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.tsb-kaufweg .tsb-kaufweg__schritt{
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  font: 600 var(--fs-sm)/1 var(--font-head);
  letter-spacing: 0.02em;
  color: var(--muted);
}
/* Die Ziffer ist hier keine Dekoration: sie benennt die Reihenfolge der Schritte,
   und sie ist der einzige Anker, wenn die Namen mobil umbrechen. */
.tsb-kaufweg .tsb-kaufweg__nr{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 700;
  background-color: var(--line);
  color: var(--muted);
}
.tsb-kaufweg .ist-aktuell{ color: var(--ink) }
.tsb-kaufweg .ist-aktuell .tsb-kaufweg__nr{
  background-color: var(--accent);
  color: var(--on-dark);
}
.tsb-kaufweg .ist-erledigt{ color: var(--accent) }
.tsb-kaufweg .ist-erledigt .tsb-kaufweg__nr{
  background-color: var(--accent-soft);
  color: var(--accent);
}

/* --- c) Die Überweisungsanleitung auf der Bestätigungsseite ---------------------- */
.tsb-ueberweisung{
  margin-top: var(--s-6);
  margin-bottom: var(--s-6);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-inline: var(--s-5);
  background-color: var(--surface-alt);
  border-left: var(--b-accent);
  border-radius: var(--r-sm);
}
.tsb-ueberweisung .tsb-ueberweisung__titel{
  margin: 0 0 var(--s-2);
  font: 700 var(--fs-xl)/1.24 var(--font-head);
  color: var(--ink);
}
.tsb-ueberweisung .tsb-ueberweisung__lead,
.tsb-ueberweisung .tsb-ueberweisung__danach{
  margin: 0 0 var(--s-4);
  max-width: var(--w-read);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}
.tsb-ueberweisung .tsb-ueberweisung__danach{ margin-bottom: var(--s-5) }

/* Das Raster hält Beschriftung und Wert in zwei Spalten. IBAN und Betrag stehen
   damit untereinander bündig, was das Abtippen spürbar erleichtert. */
.tsb-ueberweisung .tsb-ueberweisung__daten{
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--s-2) var(--s-5);
  margin: 0 0 var(--s-5);
  padding: var(--s-4) var(--s-5);
  background-color: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-sm);
}
.tsb-ueberweisung .tsb-ueberweisung__daten dt{
  margin: 0;
  font: 400 var(--fs-sm)/1.4 var(--font-body);
  color: var(--muted);
}
.tsb-ueberweisung .tsb-ueberweisung__daten dd{
  margin: 0;
  font: 400 var(--fs-base)/1.4 var(--font-body);
  color: var(--ink-body);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.tsb-ueberweisung .tsb-ueberweisung__daten dd b{
  font-weight: 700;
  color: var(--ink);
}
.tsb-ueberweisung .tsb-ueberweisung__weiter{ margin: 0 }

@media (max-width: 600px){
  /* Zweispaltig wird die Wertspalte für die IBAN zu schmal: untereinander lesen
     sich Beschriftung und Wert dort besser als ein umbrechender Zahlenblock. */
  .tsb-ueberweisung .tsb-ueberweisung__daten{
    grid-template-columns: 1fr;
    gap: 0;
  }
  .tsb-ueberweisung .tsb-ueberweisung__daten dt{ margin-top: var(--s-3) }
  .tsb-ueberweisung .tsb-ueberweisung__daten dt:first-child{ margin-top: 0 }
  .tsb-kaufweg .tsb-kaufweg__liste{ gap: var(--s-2) var(--s-3) }
  .tsb-kaufweg .tsb-kaufweg__schritt{ font-size: var(--fs-xs) }
}

/* --- d) Der Knopf in der Anleitung ---------------------------------------------- */
/*
   ⚠️ GRÜN AUF GRÜN. Auf der Bestätigungsseite war der Knopf eine leere grüne Fläche.
   Ursache ist eine Woo-Kette aus dem Bestand:
     body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart){color:var(--accent)}
   Sie hat die Spezifität (0,5,2) und schlägt damit `:is(.tsb,…) .tsb-btn-green`, das die
   Textfarbe auf --on-dark setzt. Der Text bekam also dieselbe Farbe wie die Fläche.
   `:not()` zählt wie eine Klasse - genau die Falle, die in diesem Projekt schon mehrfach
   zugeschlagen hat. Die Kette muss mitgespiegelt und um eine Klasse überboten werden.
   Deshalb .tsb UND .tsb-ueberweisung, das ergibt (0,6,2).

   Nur die Textfarbe wird gesetzt. Fläche und Form kommen weiterhin aus Abschnitt 18.
*/
body.woocommerce-page .mkd-content .woocommerce .tsb.tsb-ueberweisung a.tsb-btn-green,
body.woocommerce-page .mkd-content .tsb.tsb-ueberweisung a.tsb-btn-green{
  color: var(--on-dark);
}

/* --- e) Kein Fokusrahmen um die Warenkorb-Meldung -------------------------------- */
/*
   WooCommerce setzt auf seine Meldungen `tabindex="-1"` und ruft danach .focus() auf,
   damit Screenreader die Meldung vorlesen. Gemessen: die Meldung IST nach dem Laden das
   aktive Element, und der Fokusring (2px solid var(--accent)) bleibt sichtbar, bis man
   irgendwo hinklickt. Der Rahmen sieht dadurch aus, als wäre die Meldung angeklickt.

   `:focus-visible` trennt hier sauber: ein per Skript gesetzter Fokus erfüllt es nicht,
   ein echter Tabulator-Durchlauf schon. Der Ring verschwindet also nur in dem Fall, in
   dem er nichts aussagt, und bleibt für die Tastaturbedienung erhalten.
*/
/*
   ⚠️ `:focus-visible` reicht hier NICHT, gegen die Erwartung. Chromium wertet einen per
   Skript gesetzten Fokus nach einem Seitenwechsel als tastaturartig und erfüllt
   :focus-visible trotzdem - gemessen am 10.08., der Ring blieb stehen.
   Der Attributselektor ist die belastbare Bedingung: ein Element mit tabindex="-1" ist
   per Tastatur gar nicht erreichbar, es kann ausschliesslich programmatisch fokussiert
   werden. Ein Fokusring darauf sagt einem Tastaturnutzer also nie etwas.
*/
.woocommerce-message[tabindex="-1"]:focus,
.woocommerce-info[tabindex="-1"]:focus,
.woocommerce-error[tabindex="-1"]:focus{
  /* !important gemessen noetig: ohne bleibt der Ring stehen. Die Regel, die ihn setzt,
     war ueber document.styleSheets nicht auffindbar (vermutlich ein inline <style>),
     mit !important verschwindet er zuverlaessig. Gegenprobe im Browser gemacht. */
  outline: none !important;
}
/* ===== TSB-BLOCK:kaufstrecke END ===== */


















/* ===== TSB-BLOCK:kaufstrecke-v2 START ===== */
/* 61. [TSB-BLOCK:kaufstrecke-v2] Warenkorb, Kasse, Bestätigung nach dem Entwurf (10.08.2026).
 *
 * Freigegebener Entwurf: mockup-bestellvorgang.html in scripts/kaufstrecke-2026-08-10/.
 * Leitgedanke: links, was man ändern kann. Rechts, was es kostet und wie es weitergeht.
 * Gehört zu mu-plugin tsb-kaufstrecke-v2.php.
 *
 * ⚠️ Dieser Abschnitt muss NACH 44 (woo-mobil) und NACH 46 (kasse-felder) stehen. Beide
 *    greifen auf dieselben WooCommerce-Selektoren, und bei gleicher Spezifität entscheidet
 *    die Reihenfolge in der Datei.
 *
 * WARUM DIE TABELLE PER CSS ZUR LISTE WIRD UND NICHT PER TEMPLATE-KOPIE:
 *    WooCommerce rendert den Warenkorb in cart/cart.php als <table>. Eine Kopie dieses
 *    Templates müsste bei jeder Woo-Aktualisierung gegengeprüft werden, und sie trägt die
 *    Mengen- und Entfernen-Logik. `display:grid` auf <tr> erreicht dasselbe Layout, ohne
 *    dass wir Bestelllogik duplizieren. Dieselbe Überlegung wie bei den Mail-Templates.
 * -------------------------------------------------------------------------------------- */

/* ============================ 1. WARENKORB ============================ */

/* --- a) Zwei Spalten: Positionen links, Summe rechts ---------------------------- */
/*
   .woocommerce enthält drei Kinder: den Meldungsbereich, das Formular und
   .cart-collaterals. Der Meldungsbereich muss über beide Spalten laufen, sonst
   säße die Erfolgsmeldung in der schmalen rechten Spalte.
*/
body.woocommerce-cart .mkd-content .woocommerce{
  display: grid;
  grid-template-columns: minmax(0, 1fr) 348px;
  gap: var(--s-6);
  align-items: start;
}
body.woocommerce-cart .mkd-content .woocommerce > .woocommerce-notices-wrapper{
  grid-column: 1 / -1;
  grid-row: 1;
}
/*
   ⚠️ Die drei Plätze sind fest vergeben, nicht dem Auto-Placement überlassen.
   Grund (gemessen 14.08.2026): Beim Mengenwechsel hängt `tsb-cart-auto-update.php` eine
   Statuszeile `<p class="tsb-cart-status">` HINTER das Formular - und die ist ein
   direktes Kind dieses Rasters. Automatisch platziert belegte sie die freie Zelle oben
   rechts, und die Summenkarte rutschte eine Zeile tiefer: von links 1022 / 348px breit
   auf links 70 / 920px breit, also unter die Position über die volle Breite. Sobald die
   Meldung geleert wird, greift `.tsb-cart-status:empty{display:none}`, das Element ist
   kein Rasterkind mehr und die Karte sprang zurück. Genau dieses Hin und Her hat der
   Kunde gesehen.
   Mit festen Plätzen kann eine später eingefügte Zeile die Karte nicht mehr verschieben.
*/
body.woocommerce-cart .mkd-content .woocommerce > form.woocommerce-cart-form{
  grid-column: 1;
  grid-row: 2;
}
body.woocommerce-cart .mkd-content .woocommerce > .cart-collaterals{
  grid-column: 2;
  grid-row: 2;
}
body.woocommerce-cart .mkd-content .woocommerce > .tsb-cart-status{
  grid-column: 1;
  grid-row: 3;
}

/* --- b) Aus der Tabelle wird eine Liste ----------------------------------------- */
body.woocommerce-cart .woocommerce-cart-form table.shop_table,
body.woocommerce-cart .woocommerce-cart-form table.shop_table tbody{
  display: block;
  width: 100%;
  border: 0;
  margin: 0;
}
/* Der Tabellenkopf hat fünf Spaltentitel für ein Layout, das es nicht mehr gibt. */
body.woocommerce-cart .woocommerce-cart-form table.shop_table thead{ display: none }

body.woocommerce-cart .woocommerce-cart-form table.shop_table{
  border: var(--b-hair);
  border-radius: var(--r-lg);
  overflow: hidden;
  background-color: var(--surface);
}

body.woocommerce-cart .woocommerce-cart-form tr.cart_item{
  display: grid;
  grid-template-columns: 72px minmax(0, 1fr) auto auto auto;
  align-items: center;
  gap: var(--s-4);
  padding-top: var(--s-4);
  padding-bottom: var(--s-4);
  padding-inline: var(--s-4);
  border-bottom: var(--b-hair);
}
body.woocommerce-cart .woocommerce-cart-form tr.cart_item:last-of-type{ border-bottom: 0 }

body.woocommerce-cart .woocommerce-cart-form tr.cart_item td{
  display: block;
  border: 0;
  padding: 0;
  width: auto;
  text-align: left;
}

/*
   Die Zellen stehen im Markup in der Reihenfolge entfernen, Bild, Name, Preis, Menge,
   Zwischensumme. Gebraucht wird Bild, Name, Menge, Preis, entfernen. `order` sortiert
   das, ohne dass ein Template angefasst werden muss.
   ⚠️ Preis UND Zwischensumme zeigen bei Menge 1 dieselbe Zahl. Sichtbar bleibt die
      Zwischensumme, weil sie sich mit der Menge ändert - der Einzelpreis stünde sonst
      direkt daneben und man müsste zweimal hinsehen, um zu erkennen, was was ist.
*/
/* ⚠️ `order` allein reicht nicht: Abschnitt 44 blendet die Zellen auf dem Handy per
   display um, und der Einzelpreis blieb sichtbar. Mit expliziter Spaltenzuweisung sitzt
   jede Zelle unabhängig von der Markup-Reihenfolge an ihrem Platz, und der Einzelpreis
   verschwindet zuverlässig. */
body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-thumbnail{ grid-column: 1; order: 1 }
body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-name    { grid-column: 2; order: 2 }
body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-quantity{ grid-column: 3; order: 3 }
body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-subtotal{ grid-column: 4; order: 4; text-align: right }
body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-remove  { grid-column: 5; order: 5 }
body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-price   { display: none !important }

body.woocommerce-cart .woocommerce-cart-form td.product-thumbnail img{
  display: block;
  width: 72px;
  height: 72px;
  object-fit: cover;
  border-radius: var(--r-sm);
  background-color: var(--surface-alt);
}
body.woocommerce-cart .woocommerce-cart-form td.product-name,
body.woocommerce-cart .woocommerce-cart-form td.product-name a{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  line-height: 1.3;
  color: var(--ink);
  text-decoration: none;
}
.tsb-kk__meta{
  display: block;
  margin-top: var(--s-1);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-sm);
  color: var(--muted);
}
body.woocommerce-cart .woocommerce-cart-form td.product-subtotal{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  min-width: 84px;
}
body.woocommerce-cart .woocommerce-cart-form td.product-remove a.remove{
  font-size: 20px;
  color: var(--muted);
  margin-left: var(--s-2);
}

/* Die Zeile mit dem Gutscheinfeld und dem Aktualisieren-Knopf entfällt: der Gutschein
   steht jetzt in der Summenkarte (tsb-kaufstrecke-v2.php), und der Warenkorb rechnet
   seit dem 22.07. selbst nach (Abschnitt 38), der Knopf war ohnehin ohne Funktion. */
/* !important, weil Abschnitt 44 (woo-mobil) auf dem Handy allen Zellen der
   shop_table wieder display:block gibt - dort tauchte die Zeile sonst auf. */
body.woocommerce-cart .woocommerce-cart-form td.actions{ display: none !important }

/* --- c) Die Summenkarte ---------------------------------------------------------- */
/*
   ⚠️ Die Karte stand rund 23px tiefer als die Produktliste daneben. Das Theme gibt
   .cart-collaterals und .cart_totals je einen oberen Außenabstand, und `align-items:start`
   im Raster setzt beide Spalten zwar oben an, der Abstand schiebt die Karte danach aber
   wieder nach unten. Beide Werte werden deshalb hier genullt.
*/
body.woocommerce-cart .cart-collaterals{
  width: 100%;
  float: none;
  margin: 0 !important;
  position: sticky;
  top: var(--s-4);
}
body.woocommerce-cart .cart-collaterals .cart_totals{
  margin-top: 0 !important;
}
body.woocommerce-cart .cart-collaterals .cart_totals{
  width: 100%;
  float: none;
  border: var(--b-hair);
  border-radius: var(--r-lg);
  background-color: var(--surface-alt);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-inline: var(--s-5);
}
body.woocommerce-cart .cart_totals > h2{
  margin: 0 0 var(--s-4) !important;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: 1.2;
  color: var(--ink);
  /* !important, weil das Theme die Überschriften der Woo-Boxen zentriert. Im Entwurf
     fluchtet der Kartentitel mit den Beschriftungen darunter. */
  text-align: left !important;
  text-transform: none;
}
body.woocommerce-cart .cart_totals table.shop_table,
body.woocommerce-cart .cart_totals table.shop_table tbody{
  display: block;
  width: 100%;
  border: 0;
  margin: 0;
}
body.woocommerce-cart .cart_totals table.shop_table tr{
  display: flex;
  justify-content: space-between;
  gap: var(--s-3);
  padding-top: var(--s-2);
  padding-bottom: var(--s-2);
  border-bottom: var(--b-hair);
}
body.woocommerce-cart .cart_totals table.shop_table tr:last-child{ border-bottom: 0 }
body.woocommerce-cart .cart_totals table.shop_table th,
body.woocommerce-cart .cart_totals table.shop_table td{
  display: block;
  border: 0;
  padding: 0;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-base);
  color: var(--ink-body);
  text-align: right;
  width: auto;
}
body.woocommerce-cart .cart_totals table.shop_table th{
  text-align: left;
  text-transform: none;
  letter-spacing: 0;
}
body.woocommerce-cart .cart_totals tr.order-total{
  padding-top: var(--s-3);
}
body.woocommerce-cart .cart_totals tr.order-total th,
body.woocommerce-cart .cart_totals tr.order-total td,
body.woocommerce-cart .cart_totals tr.order-total .amount{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--ink);
}

/* --- d) Knöpfe und Gutschein in der Karte ---------------------------------------- */
/*
   ⚠️ Die Reihenfolge wird hier gesetzt, nicht über die Hook-Priorität. WooCommerce hängt
   den Kasse-Knopf an `woocommerce_proceed_to_checkout`, unsere Ergänzungen hängen am
   selben Hook - gemessen erschien "Weiter einkaufen" trotz höherer Priorität davor.
   Als Flex-Spalte mit `order` steht die Reihenfolge unabhängig davon fest: der grüne
   Hauptknopf zuerst, dann der leise, dann der Gutschein.
*/
body.woocommerce-cart .wc-proceed-to-checkout{
  padding: 0;
  margin-top: var(--s-4);
  display: flex;
  flex-direction: column;
}
body.woocommerce-cart .wc-proceed-to-checkout a.checkout-button{ order: 1 }
body.woocommerce-cart .wc-proceed-to-checkout .tsb-kk__knopf--leise{ order: 2 }
body.woocommerce-cart .wc-proceed-to-checkout .tsb-kk__gutschein{ order: 3 }
body.woocommerce-cart .wc-proceed-to-checkout a.checkout-button,
.tsb-kk__knopf{
  display: block;
  width: 100%;
  text-align: center;
  padding-top: 15px;
  padding-bottom: 15px;
  padding-inline: var(--s-5);
  border: 0;
  border-radius: var(--r-sm);
  background-color: var(--accent);
  color: var(--on-dark);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  line-height: 1;
  text-decoration: none;
  margin-top: 0;
}
.tsb-kk__knopf--leise{
  background-color: transparent;
  color: var(--accent);
  border: 2px solid var(--accent);
  margin-top: var(--s-2);
}
.tsb-kk__gutschein{
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: var(--b-hair);
}
.tsb-kk__gutschein summary{
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--accent);
  cursor: pointer;
}
.tsb-kk__gutschein-feld{
  display: flex;
  gap: var(--s-2);
  margin-top: var(--s-3);
}
.tsb-kk__gutschein-feld input{
  flex: 1 1 auto;
  min-width: 0;
  padding: 11px 12px;
  border: var(--b-field);
  border-radius: var(--r-sm);
  background-color: var(--surface);
  color: var(--ink);
  font: 400 var(--fs-sm)/1.4 var(--font-body);
}
.tsb-kk__gutschein-feld button{
  padding: 11px 15px;
  border: var(--b-field);
  border-radius: var(--r-sm);
  background-color: var(--surface);
  color: var(--ink);
  font: 700 var(--fs-sm)/1.4 var(--font-head);
  cursor: pointer;
}
body.woocommerce-cart .cart_totals .tsb-ust{
  margin-top: var(--s-3);
  text-align: center;
}
/* Feine Trennlinien wie im Entwurf: jede Summenzeile bekommt eine, die letzte nicht. */
body.woocommerce-cart .cart_totals table.shop_table tr{
  border-bottom: var(--b-hair) !important;
}
body.woocommerce-cart .cart_totals table.shop_table tr.order-total{
  border-bottom: 0 !important;
}


/* --- e) box-sizing, und warum es hier alles entscheidet ------------------------- */
/*
   ⚠️ GEMESSEN 10.08.: die Summenkarte war 398px statt 348px breit und der Knopf
   "Weiter einkaufen" 400px statt 348px - er ragte 27px über die Karte hinaus.
   Ursache ist das bekannte content-box im WPBakery-Umfeld: `width:100%` plus
   `padding-inline` plus `border` ergibt dann MEHR als 100 Prozent.
   Der grüne Kasse-Knopf fiel nicht auf, weil er sein border-box vom Theme mitbringt.
   Alles, was hier eine Breite und einen Innenabstand hat, bekommt deshalb border-box.
*/
body.woocommerce-cart .cart-collaterals,
body.woocommerce-cart .cart-collaterals .cart_totals,
body.woocommerce-cart .cart_totals table.shop_table,
.tsb-kk__knopf,
.tsb-kk__gutschein,
.tsb-kk__gutschein-feld,
.tsb-kk__gutschein-feld input,
.tsb-kk__gutschein-feld button,
.tsb-kk__karte,
.tsb-kk__zahlkarte,
.tsb-kk__erfolg{
  box-sizing: border-box;
}

/* --- f) Die Rahmen der Summentabelle abräumen ----------------------------------- */
/*
   Das Theme rahmt die Zeilen der shop_table ein. Im Entwurf trennen nur feine
   waagerechte Linien, gesetzt an der Zeile - senkrechte Striche und ein Kasten um
   den Block gehören nicht dazu. Die Theme-Regeln sitzen auf tr, th und td zugleich,
   deshalb hier gesammelt und mit !important: sie stammen aus mehreren Dateien und
   sind einzeln nicht zuverlässig zu überbieten.
*/
body.woocommerce-cart .cart_totals table.shop_table,
body.woocommerce-cart .cart_totals table.shop_table tbody,
body.woocommerce-cart .cart_totals table.shop_table tr,
body.woocommerce-cart .cart_totals table.shop_table th,
body.woocommerce-cart .cart_totals table.shop_table td{
  border: 0 !important;
  background: transparent !important;
}
/* Nur diese eine Trennlinie bleibt, und zwar an der Zeile. */


/* --- g) Versand: nur die Zahl, kein Rechner ------------------------------------- */
/*
   Kundenentscheidung 10.08.: "Den Versandkosten-berechnen-Teil, das kann raus, auch
   der Versandoption-Text." Es gibt genau eine Versandart (Pauschale 2,00 Euro), der
   Rechner konnte also nie etwas anderes ausrechnen, und der Satz über Aktualisierung
   während des Bezahlvorgangs beschreibt etwas, das hier nicht passiert.
   Der BETRAG bleibt, er gehört zur Summe.
*/
body.woocommerce-cart .cart_totals .woocommerce-shipping-destination,
body.woocommerce-cart .cart_totals .shipping-calculator-button,
body.woocommerce-cart .cart_totals .shipping-calculator-form,
body.woocommerce-cart .cart_totals .woocommerce-shipping-methods li input,
body.woocommerce-cart .cart_totals .woocommerce-shipping-methods li label::before{
  display: none !important;
}
body.woocommerce-cart .cart_totals ul#shipping_method,
body.woocommerce-cart .cart_totals .woocommerce-shipping-methods{
  list-style: none;
  margin: 0;
  padding: 0;
}
body.woocommerce-cart .cart_totals ul#shipping_method li{
  margin: 0;
  padding: 0;
  text-align: right;
}
body.woocommerce-cart .cart_totals ul#shipping_method li label{
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-base);
  color: var(--ink-body);
}

/* ============================== 2. KASSE ============================== */

body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout{
  display: grid;
  grid-template-columns: minmax(0, 1fr) 348px;
  /*
     ⚠️ Die Zeilenangabe ist Pflicht, nicht Kosmetik. #customer_details spannt beide
     Zeilen (siehe unten) und ist hoeher als Titel + Karte zusammen. Ohne feste Tracks
     verteilt das Raster diesen Ueberschuss gleichmaessig auf BEIDE Zeilen - Zeile 1
     waechst dann ueber die Titelhoehe hinaus, und weil Titel und Karte zwei getrennte
     Elemente mit eigenem Hintergrund sind, klafft genau dort ein weisser Streifen.
     Gemessen am 14.08.2026: 76px bei 1440px, 88px bei 1200px, 112px bei 1024px - je
     schmaler die Inhaltsspalte, desto hoeher das Adressformular, desto groesser der
     Spalt. `1fr` in Zeile 2 faengt den Ueberschuss ab, weil ein spannendes Element
     ueberschuessige Hoehe zuerst den flexiblen Tracks zuschlaegt.
  */
  grid-template-rows: min-content 1fr;
  gap: var(--s-6);
  align-items: start;
}
/*
   ⚠️ Die linke Spalte muss über BEIDE Rasterzeilen laufen. Ohne `grid-row` landet
   #customer_details in Zeile 1 und #order_review in Zeile 2 - und Zeile 1 ist so hoch
   wie das ganze Formular. Gemessen: die Bestellübersicht stand dann 1 273px weit unten
   in der richtigen Spalte, also genau unterhalb des Formulars statt daneben.
*/
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #customer_details{
  grid-column: 1;
  grid-row: 1 / span 2;
}
/* Die Überschrift "Deine Bestellung" sitzt im Markup zwischen den beiden Spalten.
   Sie wandert in die rechte Spalte und wird dort zum Kartentitel. */
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #order_review_heading{
  grid-column: 2;
  grid-row: 1;
  align-self: start;
  margin: 0;
  padding-top: var(--s-5);
  padding-inline: var(--s-5);
  background-color: var(--surface-alt);
  border: var(--b-hair);
  border-bottom: 0;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: 1.2;
  color: var(--ink);
}
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #order_review{
  grid-column: 2;
  grid-row: 2;
  position: sticky;
  top: var(--s-4);
  padding-top: var(--s-4);
  padding-bottom: var(--s-5);
  padding-inline: var(--s-5);
  background-color: var(--surface-alt);
  border: var(--b-hair);
  border-top: 0;
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > .tsb-ust{
  grid-column: 1 / -1;
}
/* Die beiden Spalten des Adressblocks stehen untereinander: nebeneinander wären sie in
   der linken Spalte je rund 300px breit, und ein Adressfeld braucht mehr. */
body.woocommerce-checkout #customer_details.col2-set,
body.woocommerce-checkout #customer_details .col-1,
body.woocommerce-checkout #customer_details .col-2{
  width: 100%;
  float: none;
  margin: 0;
}

/* Bestellübersicht rechts: Tabelle zu Liste */
body.woocommerce-checkout #order_review table.shop_table,
body.woocommerce-checkout #order_review table.shop_table tbody,
body.woocommerce-checkout #order_review table.shop_table tfoot{
  display: block;
  width: 100%;
  border: 0;
  margin: 0;
}
body.woocommerce-checkout #order_review table.shop_table thead{ display: none }
body.woocommerce-checkout #order_review table.shop_table tr{
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-3);
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: var(--b-hair);
}
body.woocommerce-checkout #order_review table.shop_table th,
body.woocommerce-checkout #order_review table.shop_table td{
  display: block;
  border: 0;
  padding: 0;
  width: auto;
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--ink-body);
  text-align: right;
  text-transform: none;
  letter-spacing: 0;
}
body.woocommerce-checkout #order_review table.shop_table td.product-name,
body.woocommerce-checkout #order_review table.shop_table th{ text-align: left }
body.woocommerce-checkout #order_review tr.order-total th,
body.woocommerce-checkout #order_review tr.order-total td,
body.woocommerce-checkout #order_review tr.order-total .amount{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--ink);
}
.tsb-kk__zeilenname{
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.tsb-kk__minibild{
  width: 38px;
  height: 38px;
  object-fit: cover;
  border-radius: 7px;
  background-color: var(--surface);
  flex: 0 0 auto;
}
body.woocommerce-checkout #order_review .product-quantity{ color: var(--muted) }

/* Zahlungsart und Bestellknopf */
body.woocommerce-checkout #order_review #payment{
  background: transparent;
  border-radius: 0;
  margin-top: var(--s-4);
}
body.woocommerce-checkout #order_review #payment ul.payment_methods{
  padding: 0;
  border-bottom: 0;
  margin: 0 0 var(--s-3);
}
body.woocommerce-checkout #order_review #payment .place-order{ padding: 0 }
body.woocommerce-checkout #order_review #payment button#place_order{
  width: 100%;
  padding-top: 15px;
  padding-bottom: 15px;
  border-radius: var(--r-sm);
  background-color: var(--accent);
  color: var(--on-dark);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  float: none;
}

/* ========================== 3. BESTÄTIGUNG ========================== */

.tsb-kk--danke{
  display: grid;
  grid-template-columns: minmax(0, 1fr) 348px;
  gap: var(--s-6);
  align-items: start;
  margin-top: var(--s-5);
  margin-bottom: var(--s-7);
}
.tsb-kk--danke .tsb-kk__seite{ position: sticky; top: var(--s-4) }

/*
   ⚠️ EINE BAUFORM FÜR DIE GANZE SEITE (14.08.2026, Kundenbefund "zu unaufgeräumt").
   Gemessen hatte die Bestätigungsseite davor FÜNF verschiedene Kastenformen: drei
   Eckenradien (4/10/18px), vier Rahmenlogiken (grüner Rahmen, Haarlinie, 3px-Balken links,
   gestrichelt) und drei Flächenfarben - bei nur 1 324 Zeichen Text. Nicht der Inhalt war
   zu viel, die Formen waren es.
   Seitdem gilt: alles links ist `.tsb-kk__box` (weiß, Haarlinie, --r-lg), die Erfolgsmeldung
   ist eine Zeile ohne Kasten, und der Beleg rechts ist die einzige graue Fläche.
   Wer hier eine sechste Form ergänzt, macht den Befund rückgängig.
*/
.tsb-kk__erfolg{
  display: flex;
  gap: var(--s-3);
  align-items: flex-start;
  padding-bottom: var(--s-5);
  border-bottom: var(--b-hair);
  margin-bottom: var(--s-5);
}
.tsb-kk__haken{
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: var(--r-full);
  background-color: var(--accent);
  color: var(--on-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  line-height: 1;
  margin-top: 2px;
}
.tsb-kk__erfolg-titel{
  margin: 0 0 var(--s-1);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-md);
  line-height: 1.25;
  color: var(--ink);
}
.tsb-kk__erfolg-text{
  margin: 0;
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
}
/* Der Betrag gehört in die Kopfzeile, damit die offene Zahlung sichtbar ist, ohne dass die
   Zahlkarte dafür laut sein muss (Kundenentscheidung 14.08.: "A mit dem Betragszusatz"). */
.tsb-kk__erfolg-offen{
  display: inline-block;
  margin-left: var(--s-2);
  padding-left: var(--s-2);
  border-left: var(--b-hair);
  color: var(--ink-body);
}
.tsb-kk__erfolg-offen strong{ color: var(--ink); font-variant-numeric: tabular-nums }

/* Die eine Kartenform. */
.tsb-kk__box{
  border: var(--b-hair);
  border-radius: var(--r-lg);
  background-color: var(--surface);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-inline: var(--s-6);
}
.tsb-kk__box + .tsb-kk__box{ margin-top: var(--s-4) }
.tsb-kk__box-titel{
  margin: 0 0 var(--s-2);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: 1.2;
  color: var(--ink);
}
.tsb-kk__box-text{
  margin: 0;
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}
.tsb-kk__box-text + .tsb-kk__box-text{ margin-top: var(--s-3) }
.tsb-kk__box-text--leise{ font-size: var(--fs-sm); color: var(--muted) }

/* Ein Knopf, daneben ein Textlink - nicht zwei gleich laute Knöpfe. */
.tsb-kk__aktionen{
  display: flex;
  align-items: center;
  gap: var(--s-4);
  flex-wrap: wrap;
  margin: var(--s-5) 0 0;
}
.tsb-kk__textlink{
  font: 700 var(--fs-base)/1 var(--font-head);
  color: var(--accent);
  text-decoration: none;
}
.tsb-kk__textlink:hover,
.tsb-kk__textlink:focus-visible{ text-decoration: underline }

.tsb-kk__frist{
  margin: var(--s-4) 0 0;
  padding-top: var(--s-4);
  border-top: var(--b-hair);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
}
.tsb-kk__frist + .tsb-kk__frist{ border-top: 0; padding-top: 0; margin-top: var(--s-2) }
.tsb-kk__frist strong{ color: var(--ink-body) }

.tsb-kk__kopieren{
  flex: 0 0 auto;
  padding: 8px 12px;
  border: var(--b-field);
  border-radius: 8px;
  background-color: var(--surface);
  color: var(--ink);
  font: 700 var(--fs-sm)/1.4 var(--font-head);
  cursor: pointer;
  white-space: nowrap;
}
.tsb-kk__kopieren.ist-kopiert{
  border-color: var(--accent);
  color: var(--accent);
}

/* Die Bankangaben als Datenliste: eine Zeile je Wert, die zwei abtippbaren mit Kopierknopf.
   Vorher standen Betrag, Verwendungszweck und Bankdaten in drei verschiedenen Bauformen
   übereinander (große Zahl mit Kicker, gestrichelter Kasten, Definitionsliste). */
.tsb-kk__bank{
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--s-3) var(--s-5);
  align-items: center;
  margin: var(--s-5) 0 0;
}
.tsb-kk__bank dt{
  margin: 0;
  font: 400 var(--fs-sm)/1.4 var(--font-body);
  color: var(--muted);
}
.tsb-kk__bank dd{
  margin: 0;
  font: 400 var(--fs-base)/1.4 var(--font-body);
  color: var(--ink-body);
  font-variant-numeric: tabular-nums;
  overflow-wrap: anywhere;
}
.tsb-kk__bank dd.ist-betrag{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-xl);
  line-height: 1.1;
  color: var(--ink);
}
.tsb-kk__bank dd.ist-kopierbar{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-2);
  padding-left: var(--s-3);
  background-color: var(--surface-alt);
  border-radius: var(--r-sm);
  color: var(--ink);
}

/* Die Karte rechts */
.tsb-kk__karte{
  border: var(--b-hair);
  border-radius: var(--r-lg);
  background-color: var(--surface-alt);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-inline: var(--s-5);
}
.tsb-kk__karte-titel{
  margin: 0 0 var(--s-4);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  line-height: 1.2;
  color: var(--ink);
}
.tsb-kk__pos{
  display: flex;
  align-items: center;
  gap: var(--s-3);
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: var(--b-hair);
  font-size: var(--fs-sm);
}
.tsb-kk__pos-name{
  flex: 1 1 auto;
  font: 400 var(--fs-sm)/1.35 var(--font-body);
  color: var(--ink-body);
}
.tsb-kk__pos-menge{
  display: block;
  color: var(--muted);
  font-size: var(--fs-xs);
}
.tsb-kk__pos-preis,
.tsb-kk__pos-preis .amount{
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.tsb-kk__summenzeile{
  display: flex;
  justify-content: space-between;
  gap: var(--s-3);
  padding-top: var(--s-2);
  padding-bottom: var(--s-2);
  border-bottom: var(--b-hair);
  font: 400 var(--fs-base)/1.4 var(--font-body);
  color: var(--ink-body);
}
.tsb-kk__summenzeile.ist-gesamt{
  border-bottom: 0;
  padding-top: var(--s-3);
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--ink);
}
.tsb-kk__summenzeile.ist-gesamt .amount{ font-weight: 700; color: var(--ink) }

/* Die Karte ist der Beleg, nicht die Handlung: Bestellnummer als Meta-Zeile, darunter zwei
   Textlinks. Bis zum 14.08.2026 standen hier zwei Knöpfe, einer davon grün - er konkurrierte
   mit "Termin buchen" links, und die Seite hatte damit zwei gleich laute nächste Schritte. */
.tsb-kk__karte-meta{
  display: flex;
  justify-content: space-between;
  gap: var(--s-3);
  padding-top: var(--s-3);
  margin-top: var(--s-2);
  border-top: var(--b-hair);
  font: 400 var(--fs-sm)/1.4 var(--font-body);
  color: var(--muted);
}
.tsb-kk__karte-meta span:last-child{ color: var(--ink-body); font-variant-numeric: tabular-nums }
.tsb-kk__karte-links{
  display: grid;
  gap: var(--s-2);
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: var(--b-hair);
  font: 400 var(--fs-sm)/1.4 var(--font-body);
}
.tsb-kk__karte-links a{ color: var(--accent); text-decoration: none }
.tsb-kk__karte-links a:hover,
.tsb-kk__karte-links a:focus-visible{ text-decoration: underline }

/* ====================== 4. SCHMALE FENSTER ====================== */
/*
   Unter 1000px ist für zwei Spalten kein Platz mehr: die Inhaltsspalte wäre bei
   1000px Fensterbreite abzüglich Gutter und 348px Karte nur noch rund 570px breit,
   und die Positionszeile braucht davon allein 56 + Menge + Preis.
   Einspaltig rutscht die Summe unter die Positionen, wo sie hingehört.
*/
@media (max-width: 999px){
  body.woocommerce-cart .mkd-content .woocommerce,
  body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout,
  .tsb-kk--danke{
    grid-template-columns: 1fr;
    /* Einspaltig stehen vier Zeilen im Raster (der Adressblock spannt weiter zwei davon);
       die Zweizeilen-Vorgabe von oben passt hier nicht mehr und muss weg. */
    grid-template-rows: none;
    gap: var(--s-5);
  }
  /* ⚠️ Und die festen Plätze aus dem zweispaltigen Raster ebenfalls: eine `grid-column: 2`
     zeigt hier auf eine Spalte, die es nicht mehr gibt - das Raster legte dafür eine
     zweite an, und die Karte stünde wieder neben statt unter den Positionen. */
  body.woocommerce-cart .mkd-content .woocommerce > form.woocommerce-cart-form,
  body.woocommerce-cart .mkd-content .woocommerce > .cart-collaterals,
  body.woocommerce-cart .mkd-content .woocommerce > .tsb-cart-status{
    grid-column: 1;
    grid-row: auto;
  }
  body.woocommerce-cart .cart-collaterals,
  .tsb-kk--danke .tsb-kk__seite,
  body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #order_review{
    position: static;
  }
  body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #order_review_heading,
  body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #order_review{
    grid-column: 1;
    grid-row: auto;
  }
}

@media (max-width: 560px){
  /* Menge und Preis brauchen nebeneinander rund 200px. Bleibt für den Namen zu wenig,
     wandern sie unter das Bild-Namen-Paar. */
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item{
    grid-template-columns: 72px minmax(0, 1fr) auto;
    row-gap: var(--s-3);
  }
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-name    { grid-column: 2 / 4 }
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-quantity{ grid-column: 2 / 3; order: 6 }
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-subtotal{ grid-column: 3 / 4; order: 7 }
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item td.product-remove  { grid-column: 1 / 2; order: 8 }
  .tsb-kk__bank{ grid-template-columns: 1fr; gap: 0 }
  .tsb-kk__bank dt{ margin-top: var(--s-3) }
  .tsb-kk__bank dt:first-child{ margin-top: 0 }
  .tsb-kk__bank dd{ margin-top: var(--s-1) }
  /* Wert und Kopierknopf nebeneinander bräuchten bei einer IBAN mehr als 358px. */
  .tsb-kk__bank dd.ist-kopierbar{
    flex-direction: column;
    align-items: flex-start;
    gap: var(--s-2);
  }
  .tsb-kk__box{ padding-inline: var(--s-5) }
  .tsb-kk__aktionen .tsb-btn{ width: 100% }
  .tsb-kk__erfolg-offen{
    display: block;
    margin-left: 0;
    margin-top: var(--s-1);
    padding-left: 0;
    border-left: 0;
  }
}


/* ====== 5. VORRANG GEGENÜBER ABSCHNITT 44 (woo-mobil) ====== */
/*
   Abschnitt 44 macht die WooCommerce-Tabellen auf dem Handy zu Blöcken mit
   eingeblendeten Spaltentiteln (`shop_table_responsive`). Das war die richtige Lösung,
   solange der Warenkorb eine Tabelle war. Jetzt ist er eine Liste, und zwar auf jeder
   Breite - die Zeilenhöhe stieg dadurch auf 310px, weil beide Darstellungen übereinander
   lagen. Die Rasterform gilt deshalb auch mobil.
*/
@media (max-width: 768px){
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item{
    display: grid;
    padding-inline: var(--s-4);
  }
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item td::before,
  body.woocommerce-checkout #order_review table.shop_table td::before,
  body.woocommerce-cart .cart_totals table.shop_table td::before{
    display: none !important;
  }
  body.woocommerce-cart .woocommerce-cart-form tr.cart_item td{
    display: block;
    padding: 0 !important;
    text-align: left;
  }
  body.woocommerce-cart .woocommerce-cart-form td.product-subtotal{ text-align: right }
}


/* ====== 6. ABSTÄNDE UND AUFRÄUMEN, NACH KUNDENRÜCKMELDUNG 13:44 ====== */

/* --- a) Oben weniger, unten mehr ------------------------------------------------- */
/*
   GEMESSEN: zwischen der Schrittanzeige und dem Inhalt standen 79px, zwischen Inhalt und
   Fußbereich nur 10px. Die 79px kommen aus `.mkd-container-inner{padding-top:66px}` plus
   13px der WPBakery-Row, die 10px allein aus der Row.

   ⚠️ NUR DER INHALTS-CONTAINER, und darum der Kind-Selektor.
   `.mkd-container-inner` kommt auf dieser Seite DREIMAL vor: im Titelbalken, in der
   Schrittanzeige und im Inhalt. Beide oberen benutzen ihn absichtlich, damit ihr Text mit
   dem Inhalt fluchtet. Ein Nachfahren-Selektor traf deshalb alle drei: erst wuchs die
   Schrittanzeige von 49 auf 129px, dann der Titelbalken. Die Kette
   `.mkd-content-inner > .mkd-container > .mkd-container-inner` trifft ausschließlich den
   Inhalt (gemessen an der DOM-Kette der Warenkorbseite).
*/
body.woocommerce-cart .mkd-content-inner > .mkd-container > .mkd-container-inner,
body.woocommerce-checkout .mkd-content-inner > .mkd-container > .mkd-container-inner{
  padding-top: var(--s-5);
  padding-bottom: var(--s-7);
}

/* --- b) Der Gutscheinhinweis oben in der Kasse ----------------------------------- */
/* Der Gutschein wird einen Schritt vorher im Warenkorb eingelöst, dort steht das Feld
   in der Summenkarte. Ein zweiter Einstieg an dieser Stelle führt nur vom Formular weg. */
body.woocommerce-checkout .woocommerce-form-coupon-toggle,
body.woocommerce-checkout form.checkout_coupon{
  display: none !important;
}

/* --- c) Der weiße Balken unter "Deine Bestellung" -------------------------------- */
/*
   Überschrift und Karte sind zwei Rasterzellen übereinander, und der `gap` des Rasters
   lief als 32px weiße Fuge quer durch die graue Karte. Die Spalten brauchen den Abstand,
   die Zeilen nicht.
*/
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout{
  row-gap: 0;
}

/* --- d) Weniger Text in der Bestellkarte ---------------------------------------- */
/*
   Kundenrückmeldung: "relativ viel Text, kann man das cleaner machen". Der
   Datenschutzhinweis und die Beschreibung der Überweisung stehen beide vollständig in
   der schmalen Spalte und drängen den Bestellknopf nach unten. Der Datenschutzhinweis
   ist inhaltlich in der Datenschutzerklärung abgedeckt und dort verlinkt.
*/
body.woocommerce-checkout #order_review .woocommerce-privacy-policy-text{
  display: none !important;
}
body.woocommerce-checkout #order_review .payment_box{
  background-color: transparent;
  /* ⚠️ !important: das Theme rahmt die Zahlungsbox über mehrere Kanten getrennt. Ohne
     !important blieben Rahmen links, rechts und oben stehen und unten fehlte einer -
     ein dreiseitiger Kasten, der wie ein Darstellungsfehler aussieht. */
  border: 0 !important;
  padding-top: var(--s-2);
  padding-bottom: 0;
  padding-inline: 0;
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--muted);
}
body.woocommerce-checkout #order_review .payment_box::before{ display: none }
body.woocommerce-checkout #order_review .payment_box p{ margin: 0 }
body.woocommerce-checkout #order_review ul.payment_methods li label{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: var(--fs-base);
  color: var(--ink);
}
body.woocommerce-checkout #order_review .woocommerce-terms-and-conditions-wrapper{
  font-size: var(--fs-sm);
  margin-bottom: var(--s-3);
}


/* ====== 7. LETZTE KORREKTUREN AN DER KASSE (14:05) ====== */

/* Die Überschrift "Lieferung an eine andere Adresse?" ist eine h3 in Kartentitelgröße.
   Ohne Abstand klebt sie am E-Mail-Feld darüber. */
body.woocommerce-checkout #ship-to-different-address{
  margin-top: var(--s-6);
  margin-bottom: var(--s-3);
}

/*
   Der Umsatzsteuer-Hinweis stand zentriert unter dem Formular, also unter der linken
   Spalte. Er gehört zur Summe und damit unter den Bestellknopf, genau wie im Warenkorb.
   Das Element ist ein direktes Kind von form.checkout, lässt sich also im selben Raster
   in die rechte Spalte unter die Bestellkarte setzen - ohne Eingriff ins Markup.
*/
/* Die ursprüngliche Ausgabe von tsb-ust.php entfällt hier: sie liegt außerhalb der Karte.
   Denselben Satz gibt tsb-kaufstrecke-v2.php innerhalb der Karte unter dem Knopf aus. */
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > .tsb-ust{
  display: none;
}
/*
   Der Hinweis soll in der Karte GENAUSO aussehen wie im Warenkorb. Gemessen war er dort
   15px/25px in --ink-body und zentriert, in der Kasse 12px/18px in --muted und links -
   derselbe Satz in zwei Optiken.
   Bevorzugt gibt tsb-kaufstrecke-v2.php die vorhandene Komponente `tsb_ust_zeile('eng')`
   aus. Greift der Fallback (Funktion zur Laufzeit nicht verfügbar), tragen diese Werte
   dieselbe Darstellung nach. Beide Wege enden damit im selben Bild.
*/
/*
   ⚠️ tsb_ust_zeile('eng') setzt die Variantenklasse als `eng`, nicht als `tsb-ust--eng`.
   Abschnitt 49 gestaltet aber `tsb-ust--eng`, weshalb der obere Innenabstand von 12px
   in der Kasse fehlte. Beide Schreibweisen werden hier gleich behandelt; Schriftgröße,
   Zeilenhöhe und Farbe kommen unverändert aus Abschnitt 49 und sind damit auf beiden
   Seiten dieselben (gemessen 14px/21px).
*/
body.woocommerce-checkout #order_review .tsb-ust,
body.woocommerce-checkout #order_review .tsb-kk__ust{
  margin-top: var(--s-3);
  margin-bottom: 0;
  padding-top: var(--s-3);
  padding-bottom: 0;
  text-align: center;
}
/* Unter dem Hinweis stand rund 100px leere graue Fläche: das untere Polster der Karte
   plus der Abstand, den WooCommerce nach dem Absenden-Bereich setzt. */
body.woocommerce-checkout #order_review #payment .place-order{
  margin-bottom: 0;
  padding-bottom: 0;
}
/* Unter dem Hinweis blieben 87px leere graue Fläche stehen. Der Bereich unter dem
   Absenden-Knopf bringt eigene Abstände mit, die hier nichts mehr tragen. */
body.woocommerce-checkout:not(.woocommerce-order-received) form.checkout > #order_review{
  padding-bottom: var(--s-5);
}
body.woocommerce-checkout #order_review #payment,
body.woocommerce-checkout #order_review #payment .place-order,
body.woocommerce-checkout #order_review #payment .form-row{
  margin-bottom: 0;
  padding-bottom: 0;
}

/*
   ⚠️ DER RAHMEN UM DIE ZAHLUNGSART SITZT NICHT AN .payment_box.
   Gemessen: .payment_box hat rundum 0px. Der sichtbare Kasten - links, rechts und oben
   eine Linie, unten offen - kommt vom Listeneintrag der Zahlungsarten. Das Theme rahmt
   ihn dreiseitig, weil es mehrere Einträge untereinander erwartet und die letzte Kante
   erst am Listenende setzt. Hier gibt es nur eine Zahlungsart, also fehlt sie immer.
   Der Eintrag bekommt deshalb seinen Rahmen hier vollständig und selbst.
*/
body.woocommerce-checkout #order_review ul.payment_methods,
body.woocommerce-checkout #order_review ul.payment_methods li{
  border: 0 !important;
  background: transparent !important;
  padding: 0;
  margin: 0;
  list-style: none;
}
body.woocommerce-checkout #order_review ul.payment_methods li.wc_payment_method{
  border: var(--b-hair) !important;
  border-radius: var(--r-sm);
  padding-top: var(--s-4);
  padding-bottom: var(--s-4);
  padding-inline: var(--s-4);
  margin-bottom: var(--s-4);
}


/* ====== 8. BESTÄTIGUNGSSEITE: die Reste des Woo-Templates (14:35) ====== */

/*
   Das Template checkout/thankyou.php gibt VOR jedem Hook zwei Dinge selbst aus: den Satz
   "Vielen Dank. Deine Bestellung ist eingegangen." und die Liste mit Bestellnummer, Datum,
   E-Mail, Gesamt und Zahlungsart. Beides steht jetzt in der Erfolgsbox und in der Karte
   rechts, also doppelt. Über einen Hook ist es nicht zu entfernen - es steht im Template
   selbst, und dafür bräuchte es eine Template-Kopie, die wir bewusst vermeiden.
*/
body.woocommerce-order-received .woocommerce-order > .woocommerce-notice--success,
body.woocommerce-order-received ul.woocommerce-order-overview{
  display: none !important;
}

/* Die Kartentitel erben auf Woo-Seiten eine Textfarbe aus dem Theme, deshalb wird ihre
   Farbe hier festgenagelt. (Bis zum 14.08.2026 hieß die Klasse `tsb-kk__zahlkopf` und die
   Fläche war schwarz - der Titel stand dort erst schwarz auf schwarz.) */
body.woocommerce-order-received .tsb-kk .tsb-kk__box-titel,
.tsb-kk .tsb-kk__box-titel{
  color: var(--ink) !important;
}

/*
   ⚠️ GRÜN AUF GRÜN, ZWEITER FALL. Dieselbe Woo-Kette wie bei der Überweisungsbox
   (`body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart)`)
   trifft auch die Knöpfe in der Karte auf der Bestätigungsseite - der Knopf
   "Zu meinem Guthaben" war eine leere grüne Fläche. Die Kette wird gespiegelt und um
   eine Klasse überboten.
*/
body.woocommerce-page .mkd-content .woocommerce .tsb-kk .tsb-kk__karte-links a,
body.woocommerce-page .mkd-content .tsb-kk .tsb-kk__karte-links a,
body.woocommerce-page .mkd-content .woocommerce .tsb-kk a.tsb-kk__textlink,
body.woocommerce-page .mkd-content .tsb-kk a.tsb-kk__textlink{
  color: var(--accent);
}

/*
   ⚠️ BETRÄGE IM FLIESSTEXT. wc_price() liefert
   `<span class="amount"><bdi>350,00 <span class="currencySymbol">€</span></bdi></span>`.
   Das Theme gibt diesen Spans auf Woo-Seiten `display:inline-block` und eine Mindestbreite,
   damit Preise in Tabellenspalten fluchten. Mitten in einem Satz reißt das den Betrag auf
   eine eigene Zeile und hinterlässt links und rechts große Lücken - genau so stand
   "Dein Guthaben über 350,00 € wird ..." dreizeilig da.
   Innerhalb der Fließtexte wird der Betrag deshalb wieder zu normalem Inline-Text.
   !important, weil die Theme-Regel auf .woocommerce-Price-amount direkt zielt.
*/
.tsb-kk__box-text .amount,
.tsb-kk__box-text .woocommerce-Price-amount,
.tsb-kk__box-text bdi,
.tsb-kk__frist .amount,
.tsb-kk__frist .woocommerce-Price-amount,
.tsb-kk__frist bdi,
.tsb-kk__erfolg .amount,
.tsb-kk__erfolg .woocommerce-Price-amount,
.tsb-kk__erfolg bdi{
  display: inline !important;
  min-width: 0 !important;
  width: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  white-space: nowrap;
}

/* Die Summenzeilen der Karte: Beschriftung links, Wert rechts, nichts dazwischen. */
.tsb-kk__summenzeile{ align-items: baseline }
.tsb-kk__summenzeile > span:last-child{
  text-align: right;
  white-space: nowrap;
}
/* ===== TSB-BLOCK:kaufstrecke-v2 END ===== */

/* ===== TSB-BLOCK:logo-lockup START ===== */
/* 60. [TSB-BLOCK:logo-lockup] Emblem plus gesetzter Markenname im Kopf (10.08.2026).
 *
 * Gehört zu mu-plugin tsb-logo.php, das die Wortmarke hinter dem Logo ausgibt.
 * Variante A der Entscheidungsvorlage: Emblem wird Signet, der Name steht lesbar daneben.
 *
 * ═══ ZWEI THEME-EIGENHEITEN, DIE HIER ALLES ENTSCHEIDEN (gemessen 10.08.2026) ═══
 *
 * (1) DIE DREI LOGO-BILDER LIEGEN GESTAPELT UND WERDEN PER opacity UMGESCHALTET.
 *     Im <a> stehen drei <img> (normal, dark, light). Das Theme zeigt nicht eines und
 *     versteckt zwei per display:none, sondern legt alle drei übereinander und regelt
 *     die Sichtbarkeit über opacity (gemessen: normal 0, dark 0, light 1).
 *     Ein display:flex auf dem <a> reißt den Stapel auseinander: die drei Bilder stehen
 *     dann nebeneinander, und das einzige sichtbare landet 125px rechts und 87px über
 *     seinem Platz, also außerhalb des Kopfes. Im Ergebnis war das Logo schlicht weg.
 *     ⇒ Am <a> nichts an display ändern. Nur die Höhe.
 *
 * (2) DIE KOPFZEILE IST EINE TABELLE, UND DIE RECHTE SPALTE SCHRUMPFT NICHT MIT.
 *     .mkd-position-left-inner ist display:table, .mkd-logo-wrapper eine table-cell.
 *     Ein zusätzliches Element daneben wird zur anonymen zweiten Zelle und macht die
 *     linke Spalte breiter (gemessen 273px auf 338px). .mkd-position-right behält aber
 *     seine Breite von 1104px, beides zusammen passt nicht mehr in 1400px, und die
 *     Kopfzeile bricht um: Menü unter dem Logo, Kopfhöhe 85px auf 170px.
 *     ⇒ Die Wortmarke wird deshalb absolut positioniert. Sie belegt keinen Platz im
 *       Tabellenlayout und steht in der Lücke, die ohnehin leer war (gemessen 197px
 *       zwischen Logo-Ende und erstem Menüpunkt).
 *
 * ⚠️ !important bei der Bildhöhe ist unvermeidbar: das Theme setzt die Logohöhe als
 *    INLINE-Style auf dem <a> (header/template-functions.php: intval($hoehe/2), hier
 *    187px). Gegen einen Inline-Style hilft nur !important.
 * ------------------------------------------------------------------------------- */

/* --- a) Das Emblem wird zum Signet ---------------------------------------------- */
.mkd-page-header .mkd-logo-wrapper a{
  height: 52px !important;
}
.mkd-page-header .mkd-logo-wrapper img{
  height: 52px !important;
  width: auto !important;
  max-height: none;
}

/* --- b) Die Wortmarke daneben ---------------------------------------------------- */
.mkd-page-header .mkd-position-left-inner{
  position: relative;
}
.mkd-page-header .tsb-wortmarke{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  /* 52px Emblembreite plus 13px Abstand. Die Zahl hängt an der Emblemgröße oben:
     ändert sich die eine, muss die andere mit. Deshalb stehen beide in diesem Block. */
  left: 65px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1;
  white-space: nowrap;
  /* ⚠️ Hier stand bis 10.08. abends pointer-events:none, weil die Wortmarke nur Text war
     und keine Klicks abfangen sollte. Sie ist jetzt ein Link auf die Startseite - das
     eine schließt das andere aus. Gefahrlos ist das, weil sie absolut positioniert in
     der gemessen leeren Lücke zwischen Logo und erstem Menüpunkt steht (41px Luft
     selbst bei 1400px, darunter ist sie ausgeblendet) und durch white-space:nowrap nur
     so breit ist wie ihr Text. */
  text-decoration: none;
  /* Das Theme animiert Linkfarben mit .3s. Der Kopf soll nicht flackern, also wird
     hier nur die Deckkraft bewegt - und zwar mit derselben Dauer. */
  transition: opacity .3s ease;
}
/* Ohne sichtbare Rückmeldung liest sich der Name als Beschriftung, nicht als Ziel.
   Der Zeigefinger allein kommt erst, wenn die Maus schon dort ist. */
.mkd-page-header .tsb-wortmarke:hover,
.mkd-page-header .tsb-wortmarke:focus{
  opacity: .82;
  text-decoration: none;
}
.mkd-page-header .tsb-wortmarke .tsb-wortmarke__zeile1{
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: 0.135em;
  text-transform: uppercase;
  /* Der Kopf ist dunkel, also die Auf-Dunkel-Rolle und nicht --ink. */
  color: var(--on-dark);
}
.mkd-page-header .tsb-wortmarke .tsb-wortmarke__zeile2{
  margin-top: 5px;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 12px;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  /* Gold aus dem Emblem, Token --gold. Auf #141615 sind das 9,92:1, also auch als
     kleine gesperrte Schrift sicher lesbar. */
  color: var(--gold);
}

/* --- c) Schmale Fenster ---------------------------------------------------------- */
/*
   GEMESSEN (10.08., Startseite, Abstand zwischen Wortmarken-Ende und erstem Menüpunkt):
     1920px: 561px   1600px: 241px   1400px:  41px
     1300px:  -59px  1250px: -109px  1200px:  -90px
   Das Menü ist rechtsbündig und wandert mit dem Fenster nach links, die Wortmarke steht
   fest hinter dem Logo. Ab 1400px abwärts liefe das Menü über sie.
   Deshalb erst ab 1400px. Darunter trägt das Emblem allein, wie bisher. Die Wortmarke
   ist aria-hidden, es geht also keine Information verloren.

   ⚠️ Diese Grenze bleibt bei 1400px, obwohl Abschnitt d) unten den mobilen Kopf schon ab
      1200px zeigt. Dazwischen, also von 1200 bis 1399px, steht der Desktop-Kopf ohne
      Wortmarke: dort passt das Menü noch in eine Zeile, aber nicht mehr neben den Namen.

   Der mobile Kopf ist ohnehin unberührt: er liegt in .mkd-mobile-header, alle Regeln
   hier hängen an .mkd-page-header.
*/
@media (max-width: 1399px){
  .mkd-page-header .tsb-wortmarke{ display: none }
}

/* --- d) Unter 1200px gilt der mobile Kopf --------------------------------------- */
/*
   BEFUND vom 10.08. (Bestand, nicht von diesem Umbau verursacht): das Theme schaltet erst
   bei 1024px auf den mobilen Kopf um. Zwischen 1025 und 1200px bleibt der Desktop-Kopf
   stehen, obwohl Menü, Knopf und die beiden Icons dort nicht mehr in eine Zeile passen.
   Gemessen bei 1100px: Kopfhöhe 170 statt 85px, das Menü steht unter dem Logo.
   Betrifft Tablets im Querformat und kleine Notebooks.

   Deshalb wird die Grenze auf 1200px vorgezogen (Kundenwunsch 10.08.: "zeige unter 1200
   dann auch das mobile Navi an").

   ⚠️ !important, weil das Theme die Sichtbarkeit beider Köpfe selbst per Media-Query
      setzt und diese Regeln später in derselben Datei stehen müssten, um ohne auszukommen.
*/
@media (max-width: 1199px){
  .mkd-page-header{ display: none !important }
  .mkd-mobile-header{ display: block !important }
}
/* ===== TSB-BLOCK:logo-lockup END ===== */




/* ===== TSB-BLOCK:balken-rand START ===== */
/* 62. [TSB-BLOCK:balken-rand] Titelbalken ohne graue Ränder (11.08.2026).
 *
 * ANLASS: Die Titelbilder sind 1600px breit und werden vom Theme in Originalgröße mittig
 * gezeigt (background-size:auto). Ab 1600px Fensterbreite blieb daneben der Elementhinter-
 * grund stehen: 160px je Seite bei 1920px, 480px bei 2560px, in einem Hellgrau, das nirgends
 * sonst auf der Seite vorkommt. Betroffen: Porträt, Aktuelles, Kontakt, Termin buchen.
 *
 * WAS HIER PASSIERT (Variante D, Kundenwahl 11.08.: erst weißer, dann schwarzer Auslauf):
 *   1. Das Bild darf bis 1840px mitwachsen, also höchstens auf das 1,15-fache. Bis etwa
 *      1900px Fensterbreite bleibt damit gar kein Rand.
 *   2. Was darüber hinaus übrig bleibt, läuft weich aus statt hart in Hellgrau zu enden.
 *      Die Farbe steht als --auslauf an EINER Stelle (unten), aktuell das Schwarz der
 *      Kopfzeile.
 *   3. Dafür liegen hochaufgelöste Dateien bereit (2560px statt 1600px breit), die
 *      EXAKT denselben Bildausschnitt zeigen - nur ohne die Verkleinerung.
 *      Herkunft und Nachweis: scripts/balken-2026-08-10/README.md.
 *
 * ═══ VIER PUNKTE, DIE HIER NICHT VERHANDELBAR SIND ═══
 *
 * (1) `@media (min-width:1025px)` TRÄGT DIE HALBE KORREKTHEIT.
 *     Unter 1025px ist der Balken kein ausgeblendeter, sondern ein ANDERS GEBAUTER Balken:
 *     modules-responsive.min.css räumt den Elementhintergrund per Kurzschreibweise ab
 *     (background:rgba(0,0,0,0)!important; height:auto!important) und zeigt stattdessen das
 *     <img> in .mkd-title-image. Gemessen: 390px -> Balken 112px, KEIN background-image.
 *     Ohne diese Klammer lüde jedes Handy zusätzlich die 226-KB-Datei, die dort unsichtbar
 *     hinter dem <img> liegt. Deshalb stehen die Bild-URLs auch hier drin und nicht in der
 *     Post-Meta: von dort bekäme das mobile <img> die große Datei ohne srcset ab.
 *
 * (2) `--fade` MUSS an `--rand` gekoppelt bleiben.
 *     `--rand` wird unterhalb der Bildbreite zu 0. Stünde der Übergang dann weiter auf
 *     festen 110px, läge ein 110px breiter weißer Schleier über beiden Bildkanten - also
 *     genau dort, wo es gar keinen Rand zu füllen gibt. Bei 1400px war das Motiv in einem
 *     Testlauf sichtbar aufgehellt. `min(110px, var(--rand))` fängt das ab.
 *
 * (3) ÜBERALL `100%`, NIRGENDS `100vw`.
 *     100vw schließt die klassische Scrollbar mit ein (Windows: bis 17px), die
 *     Positionierungsfläche des Hintergrunds tut das nicht. Gemischt würden Bildkante und
 *     Verlaufskante auseinanderdriften und einen weißen Streifen auf dem Bild hinterlassen.
 *     Nachgemessen am Bildpunkt über fünf Breiten: Kanten decken sich auf ±1px.
 *
 * (4) DER AUSLAUF MUSS ÜBER DEN SCRIM (z-index:2), NICHT DARUNTER.
 *     Der Scrim aus Abschnitt 53 ist am Balkenrand noch bei rund 28% Schwarz. Ein weißes
 *     Band darunter wird davon mitgefärbt: gemessen #AAAAAA statt #FFFFFF - praktisch
 *     dasselbe Grau, das hier verschwinden soll. Über dem Scrim wirkt dieser nur noch auf
 *     dem Bild, wo er den Titel lesbar macht. Bei einer dunklen Auslauffarbe wäre das egal,
 *     bei Weiß entscheidet es über Erfolg oder Wirkungslosigkeit.
 *     ⚠️ Die Randfarbe am Bildpunkt messen, nicht aus dem CSS schließen: die falsche
 *        Fassung setzt völlig korrekt #ffffff und sieht im Quelltext richtig aus.
 *
 * ⚠️ NICHT `background-size:cover` VERSUCHEN. Das Theme setzt über
 *    .mkd-has-parallax-background ein background-attachment:fixed, und dort ist die
 *    Bezugsfläche der VIEWPORT (1920x1080), nicht der 366px hohe Balken - cover skaliert
 *    dann auf 1080px Höhe statt auf 366. Das kostete am 07.08.2026 zwei komplette Anläufe,
 *    die beide am Bild drehten statt am CSS.
 *
 * REICHWEITE: hängt an .mkd-title.mkd-has-background - das tragen genau die vier
 * Bild-Balken. Warenkorb/Kasse/Konto haben einen .mkd-title OHNE diese Klasse,
 * Angebote/Camps/Kindergeburtstag haben gar keinen. Auf neun Seiten pixelweise gegengeprüft.
 * ------------------------------------------------------------------------------- */

@media (min-width: 1025px){

  /* ══ DIE EINE STELLSCHRAUBE FÜR DIE RANDFARBE ══════════════════════════════
     Umstellen auf Weiß: var(--surface) statt var(--surface-dark). Mehr ist nicht
     nötig - beide Verwendungen unten greifen hierauf zu.
     Der Kunde hat am 11.08. erst Weiß gewählt und dann Schwarz; deshalb steht der
     Wert an einer Stelle statt an dreien.
     ⚠️ Bei WEISS ist die z-index-Lage unten Pflicht (siehe Punkt 4), bei Schwarz
        nur unschädlich. Wer auf Weiß zurückgeht, darf sie also nicht entfernen. */
  .mkd-title.mkd-has-background{ --auslauf: var(--surface-dark) }

  /* Der Titeltext muss über dem Auslauf bleiben. */
  .mkd-title.mkd-has-background .mkd-title-holder{ position: relative; z-index: 3 }

  .mkd-title.mkd-has-background{
    --bild: clamp(1600px, 100%, 1840px);
    /* Alle vier Dateien haben dasselbe Seitenverhältnis 3,478 (= 1600/460). Das ist beim
       Zuschnitt so hergestellt worden, damit hier eine Zahl genügt. */
    --bild-hoehe: calc(var(--bild) / 3.478);

    background-size: var(--bild) auto !important;

    /* Hält die OBERE Bildkante an ihrem Platz - dort, wo die Köpfe sitzen.
       Bei background-attachment:fixed liegt die Bildoberkante am oberen Fensterrand, der
       Balken beginnt aber erst unter der 85px hohen Kopfzeile. Bisher war das Bild 460px
       hoch, an der Balkenoberkante lag also Bildzeile 85 von 460 = 18,5%. Wächst das Bild
       auf 1840px Breite, ist es 529px hoch, und dieselbe Bildzeile läge bei 97px - das
       Motiv rutschte um 13px nach oben aus dem Balken. Die Rechnung schiebt es um genau
       diesen Betrag zurück, bei jeder Fensterbreite. Bei 1600px ergibt sie 0.

       ⚠️ Sie behebt NICHT die leichte Aufhellung hinter dem Titel (gemessen 130 -> 143
          von 255 auf /portrait/). Die kommt von der 1,15-fachen Vergrößerung selbst, und
          eine Verschiebung kann eine Skalierung nicht ausgleichen - nachgemessen: mit und
          ohne diese Zeile stehen dort dieselben 143. Der weiße Titel hat damit noch
          3,23:1 Kontrast plus seinen Schatten; die Norm verlangt für Schrift dieser Größe
          3:1. Wer mehr will, senkt den Deckel von 1840px ab - das kostet umgekehrt
          Randfreiheit bei 1920px. */
    background-position: 50% calc(85px - (var(--bild-hoehe) * 85 / 460)) !important;

    background-color: var(--auslauf) !important;
  }

  /* Der weiche Auslauf. Liegt auf z-index 2, also über dem Scrim (siehe Punkt 4). */
  .mkd-title.mkd-has-background::before{
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    /* --bild wird vom Elternteil geerbt, damit beide Stellen nie auseinanderlaufen. */
    --rand: max(0px, (100% - var(--bild))/2);
    --fade: min(110px, var(--rand));
    background:
      linear-gradient(to right, var(--auslauf) 0, var(--auslauf) var(--rand), transparent calc(var(--rand) + var(--fade))),
      linear-gradient(to left,  var(--auslauf) 0, var(--auslauf) var(--rand), transparent calc(var(--rand) + var(--fade)));
  }

  /* Die hochaufgelösten Dateien, je Seite. Ausschnitt identisch zum bisherigen Bild.
     ⚠️ Kommt eine fünfte Seite mit Titelbild dazu, braucht sie hier eine Zeile - sonst
        wird ihr 1600er Bild auf 1840px hochgezogen und ist sichtbar unscharf. */
  body.page-id-5746 .mkd-title.mkd-has-background{
    background-image: url("/wp-content/uploads/2026/08/tsb-balken-portrait-hires.jpg") !important;
  }
  body.page-id-563 .mkd-title.mkd-has-background{
    background-image: url("/wp-content/uploads/2026/08/tsb-balken-aktuelles-hires.jpg") !important;
  }
  body.page-id-5989 .mkd-title.mkd-has-background{
    background-image: url("/wp-content/uploads/2026/08/tsb-balken-kontakt-hires.jpg") !important;
  }
  body.page-id-573 .mkd-title.mkd-has-background{
    background-image: url("/wp-content/uploads/2026/08/tsb-balken-termine-hires.jpg") !important;
  }
}
/* ===== TSB-BLOCK:balken-rand END ===== */




/* ===== TSB-BLOCK:sofortguthaben START ===== */
/* 63. [TSB-BLOCK:sofortguthaben] Die gute Nachricht auf der Bestätigungsseite (11.08.2026,
   auf die eine Kartenform gebracht am 14.08.2026).

   ANLASS: Seit der Sofortfreigabe (A10) liegt das Guthaben schon auf dem Konto, wenn die
   Bestätigungsseite erscheint. Diese Nachricht stand vorher als letzter Listenpunkt unter
   "So bezahlst du" und las sich damit wie etwas, das erst nach der Überweisung passiert.
   Sie steht deshalb in einer eigenen Karte ÜBER der Zahlkarte.

   ⚠️ DIE BAUFORM KOMMT SEIT DEM 14.08.2026 AUS ABSCHNITT 61 (`.tsb-kk__box`), nicht mehr
   von hier. Diese Karte hatte eigene Werte: 4px Radius statt 18 und einen 3px starken
   grünen Balken links. Zusammen mit den vier anderen Kastenformen der Seite ergab das den
   Kundenbefund "zu unaufgeräumt" (gemessen: fünf Bauformen, drei Radien, vier Rahmenlogiken
   bei 1 324 Zeichen Text). Hier bleibt nur, was diese Karte von den anderen unterscheidet:
   die Farbe des Titels - und die Ketten, die das Theme sonst überfärbt.
   Wer die Sonderform zurückholt, macht den Befund rückgängig.
*/
.tsb-kk__sofort .tsb-kk__box-titel{
  color: var(--accent);
}

/*
   ⚠️ GRÜN AUF GRÜN, DRITTER FALL (die ersten beiden stehen in Abschnitt 61).
   `body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart)`
   färbt jeden Link in Woo-Seiten grün - auch den auf grüner Fläche. Die Kette wird
   gespiegelt und um eine Klasse überboten, sonst ist der Knopf eine leere Fläche.

   ⚠️ UND DIE TEXTFARBE MUSS ZUR TATSÄCHLICHEN FLÄCHE PASSEN, nicht zur erwarteten:
   `.tsb-btn-green` trägt normalerweise die HELLE Fläche (--green) mit dunklem Text.
   Auf der Kaufstrecke setzt Abschnitt 61 aber alle Buttons auf --accent (dunkelgrün) mit
   weißem Text. Der erste Anlauf hier schrieb --accent-ink hinein - gemessen ergab das
   #06331a auf #0a6b2e, also dunkel auf dunkel und praktisch unlesbar. Deshalb --on-dark,
   wie bei allen anderen Knöpfen dieser Seite.
*/
body.woocommerce-page .mkd-content .woocommerce .tsb-kk .tsb-kk__sofort a.tsb-btn,
body.woocommerce-page .mkd-content .tsb-kk .tsb-kk__sofort a.tsb-btn,
.tsb-kk .tsb-kk__sofort a.tsb-btn{
  background-color: var(--accent);
  color: var(--on-dark);
  margin: 0;
}

/*
   ⚠️ BETRÄGE IM FLIESSTEXT, wie in Abschnitt 61: wc_price() liefert Spans, denen das Theme
   auf Woo-Seiten `display:inline-block` samt Mindestbreite gibt. Mitten im Satz reißt das
   den Betrag heraus.
*/
.tsb-kk__sofort .amount,
.tsb-kk__sofort .woocommerce-Price-amount,
.tsb-kk__sofort bdi{
  display: inline !important;
  min-width: 0 !important;
  width: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  white-space: nowrap;
}
/* ===== TSB-BLOCK:sofortguthaben END ===== */



/* ===== TSB-BLOCK:termine-alternativen START ===== */
/* 64. [TSB-BLOCK:termine-alternativen] Alternativen-Block auf /termine/ (14.08.2026).
 *
 * ANLASS: Der Menüknopf heißt „TERMIN BUCHEN" und führt auf /termine/. Die Seite zeigt aber
 * nur die zwei online buchbaren Trainingsarten. Camps und Kindergeburtstage laufen über eine
 * Anfrage statt über den Kalender und kamen dort gar nicht vor - wer sie suchte, stand in
 * einer Sackgasse und musste zurück ins Menü.
 *
 * ⚠️ NUMMER 64, nicht 63: Abschnitt 63 (sofortguthaben) ist am 11.08. aus einem parallelen
 *    Strang dazugekommen, während CLAUDE.md hier noch „nächste freie Nummer 63" sagte. Vor
 *    dem Anlegen dieses Blocks am Server gegengeprüft (höchste vorhandene Nummer war 63).
 *
 * Wiederverwendet wird, was es schon gibt: .tsb-btn und .tsb-btn-ghost für die zwei Wege,
 * die Textfarben aus den Tokens. Neu ist nur die Anordnung.
 * ------------------------------------------------------------------------------- */

.tsb-tm-alt{
  max-width: 680px;
  /* Abstand OBERHALB der Trennlinie, nicht nur darunter. Mit reinem padding-top saß die
     Linie direkt auf der Unterkante der letzten Karte (gemessen 0px) und las sich als
     deren Unterstrich statt als Trennung zweier Abschnitte. */
  margin: var(--s-8) auto 0;
  padding-top: var(--s-7);
  text-align: center;
  border-top: 1px solid var(--line);
}
.tsb-tm-alt h2{
  font-family: var(--font-head);
  font-weight: 700;
  color: var(--ink);
  /* Bewusst kleiner als die Hauptüberschrift der Seite (1,9rem): der Block ist ein
     Nebenweg, kein zweites Hauptangebot. Semantisch bleibt es ein h2, weil er ein
     eigener Abschnitt neben „Was möchtest du buchen?" ist. */
  font-size: 1.3rem;
  line-height: 1.25;
  margin: 0 0 10px;
}
.tsb-tm-alt p{
  font-size: 1.05rem;
  line-height: 1.7;
  color: var(--muted);
  margin: 0 auto var(--s-5);
}
.tsb-tm-alt__wege{
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  justify-content: center;
  /* ⚠️ .tsb-btn bringt `align-self: flex-start` mit. In einer Zeile mit zwei verschieden
     hohen Knöpfen stünden sie dadurch oben statt auf einer Linie - hier zurücksetzen. */
  align-items: stretch;
}
.tsb-tm-alt__wege .tsb-btn{ align-self: auto }

@media (max-width: 480px){
  /* Nebeneinander wären die beiden Beschriftungen zu eng; untereinander über die volle
     Breite bleibt die Tippfläche groß. */
  .tsb-tm-alt__wege{ flex-direction: column }
  .tsb-tm-alt__wege .tsb-btn{ width: 100% }
}

/* ── Sprungziel #buchung, damit die Karten oben nicht unter die Kopfzeile springen ──
 *
 * GEMESSEN am 14.08. auf 1440px: ein Klick auf „Einzeltraining buchen" oder
 * „Gruppentraining buchen" landete mit der Zielüberschrift bei 0px Fensterrand, also
 * teilweise UNTER der 85px hohen Kopfzeile. Grund ist derselbe wie beim Anker #ablauf,
 * der am selben Tag aus einem parallelen Strang repariert wurde: tsb-design.css vergibt
 * die Sprungmarge NAMENTLICH (`#tsb-anfrage,#tsb-ablauf{…}` und `#buchen,#anmelden{…}`),
 * nicht strukturell. `#buchung` stand in keiner dieser Listen und ging deshalb leer aus.
 * Zum Vergleich gemessen: #buchen landet korrekt bei 110px, #buchung bei 0px.
 *
 * Hier wird die vorhandene Konvention nur um den fehlenden Namen ergänzt - der fremde
 * Block bleibt unangetastet. Wer die Sprungmarken einmal strukturell lösen will
 * (z.B. `[id]{scroll-margin-top:110px}`), kann diese Regel dann ersatzlos streichen. */
#buchung{ scroll-margin-top: 110px }
/* ===== TSB-BLOCK:termine-alternativen END ===== */

/* ===== TSB-BLOCK:konto-guthaben START ===== */
/* 65. [TSB-BLOCK:konto-guthaben] Der Euro-Betrag führt auf der Guthabenseite (14.08.2026).

   ANLASS: Unter "Mein Konto → Guthaben" stand die Einheitenzahl groß ("7 Trainings") und der
   Betrag klein darunter ("entspricht 260,00 €"). Kundenentscheidung vom 14.08.: umgekehrt.
   Zwei Gründe, die über den Geschmack hinausgehen: Das Guthaben IST ein Euro-Betrag (der
   Ledger führt Euro), und die Einheitenzahl hing an EINEM Preis - bei 260 Euro stand dort
   "7 Trainings", obwohl dasselbe Guthaben für 10 Gruppentrainings reicht. Die Zeile darunter
   nennt jetzt beide.

   Hier steht nur die Größe: der große Slot trug bisher eine Zahl ("7") in --fs-3xl. Ein
   Betrag ist deutlich länger ("260,00 €") und bräche auf dem Handy um. Abschnitt 23 hatte
   dafür bereits `.tsb-konto__zahl--rest` mit --fs-2xl - dieselbe Begründung, nur für den
   Sonderfall krummer Restbeträge. Da der Slot jetzt IMMER einen Betrag trägt, gilt die
   Größe für die neue Klasse `--betrag` generell.

   ⚠️ Dieser Block muss NACH Abschnitt 23 stehen (Konto-Kachel), sonst gewinnt dessen
   --fs-3xl bei gleicher Spezifität. Am Dateiende ist das erfüllt.
*/
.tsb-konto__zahl--betrag .tsb-konto__einheiten{
  font-size: var(--fs-2xl);
}

/* Unter 480px wird auch das noch knapp: "1.260,00 €" bei 36px sprengt die Kachel. */
@media (max-width: 480px){
  .tsb-konto__zahl--betrag .tsb-konto__einheiten{
    font-size: var(--fs-xl);
  }
}
/* ===== TSB-BLOCK:konto-guthaben END ===== */




/* ===== TSB-BLOCK:konto-termine START — nicht von Hand bearbeiten, Quelle:
        scripts/konto-termine-2026-08-14/block-66-konto-termine.css ===== */
/* ============================================================================
   66. TERMINE IM KONTO (.tsb-termine)  [TSB-BLOCK:konto-termine], 14.08.2026

   Die Seite /mein-konto/termine/ (Plugin tsb-guthaben, inc/termine.php). Sie zeigt
   anstehende Trainings als Karten und die letzten fuenf als kompakte Liste.

   Sie borgt sich bewusst zwei Bausteine der Nachbarseite: die Ueberschrift
   .tsb-konto__titel und die Buttons aus Abschnitt 13/18. Hier steht nur, was neu ist.

   KEINE dunkle Kachel: die traegt im Konto der Guthabenstand (Abschnitt 31). Ein
   zweiter dunkler Block auf der Nachbarseite nimmt ihr diese Rolle - und Termine sind
   eine Liste, kein einzelner Kennwert (Entscheidung 14.08.2026, Variante A des Entwurfs
   in scripts/konto-termine-2026-08-14/mockup-termine.html).
   ============================================================================ */

.tsb-termine__vorspann{
  margin: 0 0 var(--s-6);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--muted);
  max-width: var(--w-read);
}

/* Der Abstand liegt AM BLOCK, nicht an den Karten: sonst traegt ihn die letzte Karte
   mit nach unten und der Rueckblick rutscht weg (Abstaende gehoeren zur Schnittstelle
   einer Komponente, CLAUDE.md). */
.tsb-termine__block{ margin-top: var(--s-7) }
.tsb-termine__block:first-of-type{ margin-top: 0 }

/* --- Die Karten ------------------------------------------------------------ */

.tsb-termine__liste{
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

/* Zwei Spalten: Text waechst, der Knopf bleibt so breit wie sein Inhalt.
   align-items:center haelt den Knopf auf halber Hoehe, auch wenn der Fristsatz
   zweizeilig wird. */
.tsb-termine__karte{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-5);
  border: var(--b-hair);
  border-left-width: 3px;
  border-left-style: solid;
  border-left-color: var(--line);
  border-radius: var(--r-md);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-left: var(--s-5);
  padding-right: var(--s-5);
  background: var(--surface);
  box-shadow: var(--sh-card);
}

/* Der naechste Termin ist der, um den es geht. Ueber :first-child statt ueber eine
   eigene Klasse aus PHP - die Reihenfolge steht ohnehin schon in der Sortierung, und
   zwei Quellen fuer dieselbe Aussage laufen frueher oder spaeter auseinander. */
.tsb-termine__liste .tsb-termine__karte:first-child{
  border-left-color: var(--accent);
}

/* Abgelaufene Frist: die gruene Kante waere hier ein falsches Signal. */
.tsb-termine__liste .tsb-termine__karte--frist-vorbei:first-child{
  border-left-color: var(--line);
}

.tsb-termine__datum{
  margin: 0 0 var(--s-1);
  font: 700 var(--fs-lg)/var(--lh-flat) var(--font-head);
  color: var(--ink);
}

.tsb-termine__art{
  margin: 0 0 var(--s-3);
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}

.tsb-termine__frist{
  margin: 0;
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
  max-width: var(--w-read);
}

/* Die Farbe verstaerkt nur, was der Satz bereits sagt ("Die kostenlose Frist ist
   abgelaufen") - sie traegt die Aussage nicht allein (SC 1.4.1). */
.tsb-termine__frist--vorbei{ color: var(--error) }

.tsb-termine__aktion{ margin: 0 }

/* --- Kein anstehender Termin ----------------------------------------------- */

/* Gestrichelt, nicht durchgezogen: der Kasten ist ein Platzhalter fuer etwas, das
   noch kommt, und keine Karte mit Inhalt. */
.tsb-termine__leer{
  border: 1px dashed var(--line);
  border-radius: var(--r-md);
  padding-top: var(--s-6);
  padding-bottom: var(--s-6);
  padding-left: var(--s-6);
  padding-right: var(--s-6);
  background: var(--surface-alt);
}

.tsb-termine__leer p{
  margin: 0 0 var(--s-4);
  font: 400 var(--fs-md)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
  max-width: var(--w-read);
}

.tsb-termine__leer-aktionen{
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin: 0;
}

/* --- Die Knoepfe: Textfarbe gegen die Kontobereich-Regel verteidigen ---------

   Abschnitt 13 faerbt JEDEN Link im Kontobereich gruen:
     body.woocommerce-page .mkd-content .woocommerce a:not(.button):not(.added_to_cart)
       { color: var(--accent) }                                          = (0,5,2)
   Unsere Knoepfe heissen .tsb-btn, nicht .button - die :not()-Kette schliesst sie
   also nicht aus und faerbt ihre Beschriftung. Auf dem gruenen Primaerknopf lag damit
   --accent auf --accent: eine leere gruene Flaeche, ohne lesbaren Text.

   Derselbe Fehler traf am 19.07. bereits das Guthabenfeld (Abschnitt 50 (b)). Die
   Gegenmassnahme ist dort wie hier dieselbe Kette mit einer Klasse mehr, (0,6,2) gegen
   (0,5,2) - ohne !important und ohne sich auf die Reihenfolge in der Datei zu verlassen.

   ⚠️ Aufgefallen ist es NUR im Screenshot. Jede DOM-Messung war gruen: den Text gab es,
   er war im Baum, er hatte eine Breite. Er war lediglich unsichtbar. */

body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-termine a.tsb-btn-green{
  color: var(--on-dark);
  background: var(--accent);
  border-color: var(--accent);
}
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-termine a.tsb-btn-green:hover{
  color: var(--accent-ink);
  background: var(--accent-bright);
  border-color: var(--accent-bright);
}

/* Ghost wie im Bestand: weisse Flaeche, Lesefarbe, Rand --line-field (3,75:1, SC 1.4.11).
   Ohne diese Zeile traegt die Beschriftung Akzentgruen - lesbar zwar, aber eine dritte
   Buttonfarbe auf einer Seite, die sonst genau zwei kennt. */
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-termine a.tsb-btn-ghost{
  color: var(--ink);
  background: var(--surface);
  border-color: var(--line-field);
}
body.tsb-konto-seite.woocommerce-page .mkd-content .woocommerce .tsb-termine a.tsb-btn-ghost:hover{
  color: var(--accent);
  border-color: var(--accent);
}

/* --- Der Rueckblick --------------------------------------------------------- */

/* Bewusst eine Liste und keine Karten: vergangene Trainings sind zum Nachschlagen da,
   nicht zum Handeln. Gleicher Aufbau wie die Guthaben-Bewegungen (Abschnitt 31), damit
   die beiden Kontoseiten dieselbe Sprache sprechen. */
.tsb-termine__rueckblick{
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--b-hair);
}

.tsb-termine__rueckblick li{
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--s-3);
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
  border-bottom: var(--b-hair);
}

.tsb-termine__rueckblick-art{
  font: 400 var(--fs-base)/var(--lh-base) var(--font-body);
  color: var(--ink-body);
}

.tsb-termine__rueckblick-datum{
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.tsb-termine__fussnote{
  margin: var(--s-4) 0 0;
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
  max-width: var(--w-read);
}

/* --- Der Schlusssatz -------------------------------------------------------- */

.tsb-termine__kulanz{
  margin: var(--s-7) 0 0;
  padding-top: var(--s-4);
  border-top: var(--b-hair);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
  max-width: var(--w-read);
}

/* --- Der Rueckweg auf /termin-verwalten/ ------------------------------------

   Die Seite traegt [ssa_confirmation] und darunter unseren Weg zurueck ins Konto.
   Ohne ihn beantwortet die Seite die Frage "und was jetzt?" nicht: Kopf und Menue
   allein sagen niemandem, dass die Terminuebersicht im Konto liegt.

   Der Innenabstand richtet den Block an der Karte des Shortcodes aus - die sitzt
   16px weiter innen als .mkd-container-inner (gemessen: Container links 90px,
   Karte 106px). */

.tsb-terminverwaltung{
  margin-top: var(--s-6);
  padding-left: var(--s-4);
  padding-right: var(--s-4);
}

/* Luft zwischen Titelbalken und Karte, und zwischen Karte und Fuss.
   Gemessen ohne diese Regeln: der Rahmen begann bei 451px - exakt an der Unterkante
   des 366px hohen Balkens - und der Fuss setzte direkt am Hinweistext an. Eine normale
   Seite bekommt diesen Abstand von den WPBakery-Reihen; diese Seite besteht nur aus
   einem Shortcode und hat keine.

   Der Scope haengt an der body-Klasse aus inc/termine.php, NICHT an .page-id-11362:
   beim Cutover bekommt Live andere Beitrags-IDs, und eine ID-Regel waere dort lautlos
   wirkungslos. */
body.tsb-terminverwaltung-seite .ssa_booking_iframe{
  margin-top: var(--s-7);
}
body.tsb-terminverwaltung-seite .tsb-terminverwaltung{
  margin-bottom: var(--s-8);
}

.tsb-terminverwaltung__zurueck{ margin: 0 0 var(--s-4) }

/* Lesebreite: ueber die vollen 1100px des Containers waere der Satz eine Zeile
   mit rund 150 Zeichen. */
.tsb-terminverwaltung__hinweis{
  margin: 0;
  max-width: var(--w-read);
  font: 400 var(--fs-sm)/var(--lh-base) var(--font-body);
  color: var(--muted);
}

/* --- Schmale Fenster -------------------------------------------------------- */

/* Unter 560px stehen Text und Knopf nicht mehr nebeneinander: dem Fristsatz blieben
   sonst rund 150px. Der Knopf nimmt dann die volle Breite - er ist die einzige
   Handlung auf der Karte. */
@media (max-width: 560px){
  .tsb-termine__karte{
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-4);
  }
  .tsb-termine__aktion .tsb-btn{
    display: block;
    width: 100%;
    text-align: center;
  }
}
/* ===== TSB-BLOCK:konto-termine END ===== */

/* ===== TSB-BLOCK:insta-raster START ===== */
/* ============================================================================
   67. INSTAGRAM-RASTER, Nachtrag  [TSB-BLOCK:insta-raster], 14.08.2026

   Ergaenzt Abschnitt 30 (.tsb-insta). Zwei Aenderungen, beide gemessen:

   a) SPALTENWECHSEL VON 768 AUF 1024.
      Abschnitt 30.1 begruendet den Wechsel bei 768px damit, dass die Kachel beim
      VERKLEINERN des Fensters sonst groesser werde. Das stimmt - aber der Preis war
      hoeher als der Gewinn: der Theme-Container steht zwischen 769 und 1024px
      konstant auf 768px, also teilen sich dort DREI Spalten dieselbe Breite.
      Gemessen 14.08.2026: bei 768px ist die Kachel 354px, bei 769px nur noch 240px -
      sie schrumpft um 32 %, waehrend das Fenster waechst, und bleibt ueber 256px
      Fensterbreite hinweg die kleinste der ganzen Seite (kleiner als auf dem Handy).
      Mit dem Wechsel bei 1025px bleibt ein Sprung uebrig (1024px zwei Spalten a 376px
      -> 1025px drei a ~301px), aber er ist kleiner (-20 % statt -32 %), er trifft nur
      eine einzige Fensterbreite statt eines ganzen Bereichs, und 301px ist immer noch
      deutlich mehr als 240px. Der Sprung selbst ist nicht wegzugestalten: er kommt
      vom Theme-Container, der in Stufen springt (768 -> 950 -> 1300).

   b) "MEHR ANZEIGEN" STATT NEUN FESTER KACHELN.
      Das Dokument traegt jetzt 24 Kacheln, sichtbar sind zunaechst neun. Der Rest
      haengt an .ist-begrenzt, das erst PER SKRIPT gesetzt wird - ohne JavaScript ist
      also alles da, statt dass Kacheln unerreichbar waeren.
      display:none ist hier Pflicht und nicht Geschmack: gemessen 14.08.2026 laedt ein
      Bild in einer so versteckten Kachel NICHT (0 Requests), waehrend
      visibility:hidden und height:0 alle 24 laden. Die Seite wiegt also weiter so viel
      wie neun Kacheln, bis jemand den Knopf drueckt.

   Die alte Regel `nth-child(n+9)` aus 30.5 (die neunte Kachel unter 768px ausblenden,
   damit keine halbe Reihe stehen bleibt) wird hier ueberfluessig - dieselbe Aufgabe
   erledigt jetzt die Begrenzung, und zwar fuer beide Spaltenzahlen. Sie bleibt in
   Abschnitt 30 stehen und wird hier gezielt zurueckgenommen, damit Abschnitt 30
   unveraendert bleibt und diese Aenderung an EINER Stelle steht.
   ============================================================================ */

/* --- a) Zwei Spalten bis 1024px ----------------------------------------- */
@media (max-width: 1024px){
  .tsb-insta-grid{
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Der Abstand nur im NEUEN Bereich. Unterhalb von 768px gelten weiter die Werte aus
   Abschnitt 30.5 und 30.6 (--s-4 bzw. --s-3) - stuende gap hier ungeteilt, wuerde
   dieser Block die 480er-Regel ueberschreiben, weil er spaeter in der Datei steht. */
@media (min-width: 769px) and (max-width: 1024px){
  .tsb-insta-grid{
    gap: var(--s-4);
  }
}

/* --- b) Begrenzung und Knopf --------------------------------------------
   Drei Spalten: neun sichtbar, also drei volle Reihen.
   Zwei Spalten: acht sichtbar, also vier volle Reihen - neun liessen wieder eine
   einzelne Kachel als halbe Reihe stehen, genau der Fall, den 30.5 loesen wollte. */
.tsb-insta-grid.ist-begrenzt > .tsb-insta-kachel:nth-child(n+10){
  display: none;
}

@media (max-width: 1024px){
  .tsb-insta-grid.ist-begrenzt > .tsb-insta-kachel:nth-child(n+9){
    display: none;
  }
}

/* Die Regel aus 30.5 zuruecknehmen: sie versteckte die neunte Kachel unter 768px
   dauerhaft - auch nach dem Aufklappen, wo sie sichtbar sein soll. */
@media (max-width: 768px){
  .tsb-insta-grid:not(.ist-begrenzt) > .tsb-insta-kachel:nth-child(n+9){
    display: block;
  }
}

.tsb-insta-mehr-zeile{
  /* Derselbe Abstand wie .tsb-insta-fuss in Abschnitt 30.3: der Knopf gehoert optisch
     zum Raster, nicht zum Folgeabsatz. */
  margin-top: var(--s-6);
  margin-bottom: 0;
  text-align: center;
}

/* Der Knopf erbt Form und Groesse von .tsb-btn (Abschnitt 18). Hier steht nur, was
   ihn vom gruenen Hauptweg "Mehr auf Instagram" unterscheidet: er ist die leisere,
   zweite Handlung auf der Seite. Farben ausschliesslich ueber Tokens - und die
   Textfarbe ausdruecklich gesetzt, weil ein Knopf ohne sie im Kontobereich schon
   einmal unsichtbar war (14.08.2026, Block 66). */
.tsb-insta-mehr{
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  cursor: pointer;
}

.tsb-insta-mehr:hover,
.tsb-insta-mehr:focus-visible{
  border-color: var(--accent);
  color: var(--accent);
}

/* Zwischen Knopf und "Mehr auf Instagram" braucht es Luft, sonst lesen sich zwei
   Schaltflaechen untereinander als ein Block. */
.tsb-insta-mehr-zeile + .tsb-insta-fuss{
  margin-top: var(--s-5);
}
/* ===== TSB-BLOCK:insta-raster END ===== */

/* ===== TSB-BLOCK:insta-tafel START ===== */
/* ============================================================================
   68. INSTAGRAM ALS TAFEL  [TSB-BLOCK:insta-tafel], 14.08.2026

   Loest das Kachelraster der Abschnitte 30 und 67 als SICHTBARE Form ab. Beide
   bleiben stehen: sie greifen an .tsb-insta-grid / .tsb-insta-kachel, und diese
   Klassen gibt die Ausgabe seit dem Umbau nicht mehr aus. Wer zurueckdrehen will,
   braucht damit nur die Ausgabe zurueckzunehmen, nicht das CSS wiederherzustellen.

   WARUM UEBERHAUPT:
   Der Feed ersetzt die Nachrichtenseite. Die Beitragstexte sind im Median
   413 Zeichen lang (min 194, max 736, gemessen ueber die 30 Beitraege im Cache) -
   als zweizeiliger Anriss unter einem Bild ging davon der Sinn verloren.

   DREI ENTSCHEIDUNGEN, DIE NICHT GESCHMACK SIND:

   a) DAS BILD WIRD UMFLOSSEN (float), es steht NICHT in einer zweiten Spalte.
      Bei Bild-neben-Text als Flex-Spalten muss man sich zwischen zwei Fehlern
      entscheiden: Streckt man das Bild auf die Kartenhoehe, wird aus dem Quadrat ein
      Hochformat - gemessen 240x422px, also ein Beschnitt auf 57 % der Bildbreite, der
      bei den Plakatgrafiken den Text kappt. Laesst man es quadratisch, steht darunter
      eine dunkle Luecke, sobald der Text laenger ist als das Bild - und das ist bei
      194 bis 736 Zeichen der Normalfall. Umflossen gibt es beides nicht, und die Karte
      wird nebenbei deutlich kompakter, weil die Zeilen unterhalb des Bildes die volle
      Breite nutzen: 576 Zeichen brauchen so 266px statt der geschaetzten 400.

   b) DIE BEGRENZUNG IST EINE HOEHE, KEINE ZEILENZAHL.
      -webkit-line-clamp arbeitet mit umflossenen Elementen nicht zuverlaessig. Deshalb
      max-height plus Verlauf am Fuss. Welche Karte den Knopf "Weiterlesen" bekommt,
      entscheidet das Skript durch Messung - es haengt an der Fensterbreite. Gemessen
      braucht ihn am Rechner 1 von 30 Beitraegen, auf dem Handy 2.

   c) DAS FELD IST EIN GERUNDETES PANEL, KEIN RANDLOSES BAND.
      Die Seite "Aktuelles" liegt in .mkd-container-inner (1300px). Ein randloses Band
      braeuchte den 100vw-Trick - und der ist in dieser Datei aus gutem Grund verboten
      (Abschnitt 51: 100vw schliesst die Scrollbar mit ein und erzeugt Ueberlauf).

   HELL, NICHT DUNKEL (Entscheidung des Kunden vom 14.08.2026 abends).
   Der erste Bau stand auf --surface-dark. Das dunkle Feld war die Antwort auf die
   schwarzen Reel-Startbilder - und dieses Argument fiel am selben Abend weg, weil
   fuer 12 der 24 Kacheln eigene Startbilder hinterlegt wurden. Uebrig blieb ein
   dunkler Block in einer durchgehend hellen Seite. Die Tafel steht deshalb auf
   --surface-alt mit weissen Karten, wie die uebrigen Baender der Seite. Geaendert
   wurden ausschliesslich Farbrollen; Aufbau, Abstaende und Grenzwerte sind dieselben.

   Kein Schatten auf den Karten: dieselbe Ueberlegung wie in Abschnitt 30 - viele
   Karten mit Schatten ergeben auf Weiss eine graue Suppe und lenken auf die Kanten
   statt auf die Fotos. Der Haarstrich reicht.
   ============================================================================ */

/* --- 68.1 Das dunkle Feld ------------------------------------------------
   Die Abstaende der Sektion aus Abschnitt 30 bleiben: sie sind der WEISSE Abstand
   ueber und unter dem Feld. Das Polster INNERHALB des Feldes kommt hier dazu. */
.tsb-insta-tafel-feld{
  background: var(--surface-alt);
  border-radius: var(--r-lg);
  padding-top: var(--s-7);
  padding-bottom: var(--s-7);
  padding-left: var(--s-7);
  padding-right: var(--s-7);
  color: var(--ink-body);
}

/* --- 68.2 Kopfzeile mit Konto -------------------------------------------- */
.tsb-insta-tafel .tsb-insta-kopf{
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--s-6);
  margin-bottom: var(--s-7);
}

/* Kicker und Ueberschrift stehen mit den Abschnitten 1 und 2 schon richtig - auf dem
   hellen Feld ist hier nichts zurechtzuruecken. Nur der Abstand unter der Zeile
   entfaellt, weil ihn die Kopfzeile traegt. */
.tsb-insta-tafel .tsb-insta-intro{
  margin-bottom: 0;
}

/* Traegt den Weg zu Instagram. Deshalb steht am Fuss nur noch EINE Schaltflaeche. */
.tsb-insta-tafel .tsb-insta-profil{
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  flex: none;
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-pill);
  padding-top: var(--s-1);
  padding-bottom: var(--s-1);
  padding-left: var(--s-1);
  padding-right: var(--s-5);
  text-decoration: none;
  color: var(--ink);
  transition: border-color var(--t-base);
}

.tsb-insta-tafel .tsb-insta-profil:hover,
.tsb-insta-tafel .tsb-insta-profil:focus-visible{
  border-color: var(--accent);
}

.tsb-insta-tafel .tsb-insta-avatar{
  width: 46px;
  height: 46px;
  border-radius: var(--r-full);
  flex: none;
  overflow: hidden;
  background: var(--surface-alt);
  display: grid;
  place-items: center;
}

.tsb-insta-tafel .tsb-insta-avatar img{
  width: 34px;
  height: 34px;
  object-fit: contain;
  display: block;
}

.tsb-insta-tafel .tsb-insta-profiltext{
  display: flex;
  flex-direction: column;
  line-height: var(--lh-flat);
}

.tsb-insta-tafel .tsb-insta-profiltext strong{
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--ink);
}

.tsb-insta-tafel .tsb-insta-profilmeta{
  font-size: var(--fs-sm);
  color: var(--accent);
}

/* --- 68.3 Die Liste ------------------------------------------------------
   Mehrspaltensatz statt Raster: bei Texten zwischen 194 und 736 Zeichen ist "eine
   Karte hoeher als ihre Nachbarin" der Normalfall, und zwei Rasterreihen reissen
   daraus ein Loch (dieselbe Lehre wie bei den Produktkarten). column-gap traegt den
   Abstand seitlich, margin-bottom den nach unten - gap wirkt im Mehrspaltensatz
   nicht auf die Elemente. */
.tsb-insta-tafel .tsb-insta-liste{
  column-count: 1;
  column-gap: var(--s-5);
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Die Ausnahmen fuer breitere Fenster stehen am ENDE dieses Blocks, nicht hier.
   Grund: sie heben unter anderem die Grenze aus 68.4 an, und bei gleicher
   Spezifitaet gewinnt die spaetere Regel. Stuenden sie hier, waeren sie wirkungslos,
   ohne dass irgendetwas meckert - genau so passiert am 14.08.2026, gemessen sechs
   Knoepfe statt null. */

.tsb-insta-tafel .tsb-insta-eintrag{
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  margin: 0 0 var(--s-5);
  padding: 0;
  list-style: none;
}

/* Welche Eintraege spaeter kommen, entscheidet PHP (dort steht 'sofort'). Ohne
   JavaScript wird .ist-begrenzt nie gesetzt - dann stehen alle da, statt dass
   welche unerreichbar waeren. display:none ist Absicht: ein so verstecktes Bild
   laedt NICHT (gemessen 14.08.2026), die Seite wiegt also nur die sichtbaren. */
.tsb-insta-tafel .tsb-insta-liste.ist-begrenzt > .tsb-insta-spaeter{
  display: none;
}

/* --- 68.4 Die Karte ------------------------------------------------------ */
.tsb-insta-tafel .tsb-insta-karte{
  /* In einer Spalte liefe der Text sonst ueber 1100px, also rund 140 Zeichen je
     Zeile. Mit 740px bleiben neben dem Bild rund 63 Zeichen - das ist die
     Lesebreite des Designsystems (--w-read). */
  max-width: 740px;
  background: var(--surface);
  border: var(--b-hair);
  border-radius: var(--r-md);
  padding-top: var(--s-5);
  padding-bottom: var(--s-5);
  padding-left: var(--s-5);
  padding-right: var(--s-5);
}

/* Die Grenze haengt an der Spaltenzahl, nicht am Geschmack.
   EINE Spalte heisst: jeder Beitrag steht in voller Hoehe untereinander, sechs
   davon ergaben ungebremst eine 3200 bis 4000px lange Seite (gemessen 14.08.2026
   bei 1024 und 390px). Dort ist die Begrenzung der Zweck, nicht der Notbehelf:
   jeder Beitrag ist ein lesbarer Anfang mit Weg zum Rest.
   ZWEI Spalten halbieren die Hoehe, dort ist Platz fuer den ganzen Text - und
   die gemessenen Inhaltshoehen bei 590px Karte (min 212, Median 294, Maximum 414)
   passen mit 420px vollstaendig hinein: kein heutiger Beitrag bekommt dort einen
   Knopf. Die zuerst gesetzten 320px trafen 5 von 6. */
.tsb-insta-tafel .tsb-insta-inhalt{
  max-height: 300px;
  overflow: hidden;
  position: relative;
}

/* Der Verlauf steht nur, wo wirklich abgeschnitten wird - die Klasse setzt das Skript
   nach der Messung. Sonst laege ein Schleier auch ueber kurzen Beitraegen, bei denen
   es nichts zu verbergen gibt. */
.tsb-insta-tafel .tsb-insta-karte.ist-geklappt .tsb-insta-inhalt::after{
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: var(--s-8);
  background: linear-gradient(to bottom, transparent, var(--surface));
  pointer-events: none;
}

.tsb-insta-tafel .tsb-insta-karte.ist-offen .tsb-insta-inhalt{
  max-height: none;
}

/* --- 68.5 Das Bild ------------------------------------------------------- */
/* 130px ist der Normalfall, 200px die Ausnahme fuer den 1300er-Container.
   Das Bild bleibt ueber den Spaltenwechsel hinweg gleich gross - dadurch faellt der
   Sprung der Kartenbreite (692 auf 372px zwischen 768 und 769px Fenster) kaum auf:
   sichtbar aendert sich nur, wie viel Text neben dem Bild steht. Beim frueheren
   Kachelraster war derselbe Sprung auffaellig, weil dort das BILD kleiner wurde. */
.tsb-insta-tafel .tsb-insta-bildlink{
  float: left;
  width: 130px;
  position: relative;
  line-height: 0;                 /* kein Zeilenkasten-Spalt unter dem Bild */
  margin-top: var(--s-1);
  margin-right: var(--s-3);
  margin-bottom: var(--s-2);
  border-radius: var(--r-sm);
  overflow: hidden;               /* haelt den Zoom im Rund */
}

.tsb-insta-tafel .tsb-insta-bild{
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--surface-alt);
  transition: transform var(--t-base);
}

.tsb-insta-tafel .tsb-insta-karte:hover .tsb-insta-bild{
  transform: scale(1.04);
}

/* Aus der Ecke in die Mitte und deutlich groesser: bei 200px Bild war das
   24px-Abzeichen aus Abschnitt 30 kaum als Abspielzeichen zu erkennen, und genau
   das ist bei 22 von 24 Reels die wichtigste Aussage der Kachel.
   right:auto ist noetig - Abschnitt 30 setzt dort einen Wert. */
.tsb-insta-tafel .tsb-insta-video{
  top: 50%;
  left: 50%;
  right: auto;
  transform: translate(-50%, -50%);
  width: var(--s-6);
  height: var(--s-6);
  /* Die halbtransparente Abdeckung kommt aus Abschnitt 30 und bleibt dort - sie ist
     die eine dokumentierte Ausnahme vom "nur var()"-Gebot, und ein zweites Literal
     hier waere genau die Kopie, die das Designsystem verhindern soll. */
  border: 1px solid var(--on-dark);
}

.tsb-insta-tafel .tsb-insta-video::before{
  margin-left: 2px;
  border-top-width: 5px;
  border-bottom-width: 5px;
  border-left-width: 8px;
}

/* --- 68.6 Text, Datum, Wege ---------------------------------------------- */
.tsb-insta-tafel .tsb-insta-datum{
  display: block;
  color: var(--muted);
  margin-bottom: var(--s-2);
}

.tsb-insta-tafel .tsb-insta-text{
  margin: 0;
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--ink-body);
  /* Die Umbrueche des Beitrags zeigen, waagerechten Leerraum aber nicht.
     Instagram-Beitraege gliedern mit Umbruechen; ohne pre-line liefe die
     Aufzaehlung "Technik / Athletik / Mentalitaet" als ein Satz durch.
     Das Zusammenfassen mehrfacher Leerzeilen passiert schon beim Einlesen. */
  white-space: pre-line;
  /* Eine lange URL oder Hashtag-Kette ohne Leerzeichen liefe sonst seitlich heraus. */
  overflow-wrap: anywhere;
}

/* Ein echter Knopf ohne Knopfoptik: er klappt Text auf, er fuehrt nicht weg.
   Die [hidden]-Regel MUSS vor der display-Regel stehen und darf nicht schwaecher
   sein: eine eigene display-Angabe (Klasse + Element) schlaegt die Browserregel
   [hidden]{display:none} (Attribut). Ohne diese Zeile steht "Weiterlesen" auf JEDER
   Karte, obwohl das Attribut korrekt gesetzt ist - in der DOM-Messung unsichtbar,
   im Screenshot sofort. Genau so passiert, 14.08.2026. */
.tsb-insta-tafel .tsb-insta-mehrlesen[hidden]{ display: none }

.tsb-insta-tafel .tsb-insta-mehrlesen{
  display: block;
  margin-top: var(--s-3);
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.tsb-insta-tafel .tsb-insta-weiter{
  margin: var(--s-3) 0 0;
}

.tsb-insta-tafel .tsb-insta-weiter a{
  font-family: var(--font-head);
  font-weight: 600;
  font-size: var(--fs-sm);
  color: var(--accent);
  text-decoration: none;
}

.tsb-insta-tafel .tsb-insta-weiter a:hover,
.tsb-insta-tafel .tsb-insta-weiter a:focus-visible{
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --- 68.7 Der Knopf am Fuss ----------------------------------------------
   Farbe und Form kommen aus Abschnitt 67 und passen auf dem hellen Feld
   unveraendert. Hier steht nur, was dort fehlt: dass das Attribut hidden ihn auch
   wirklich verschwinden laesst.

   PFLICHT, kein Feinschliff: .tsb-btn setzt display:inline-flex, und eine Regel des
   Autors schlaegt die Browserregel [hidden]{display:none} IMMER - unabhaengig von
   Reihenfolge und Spezifitaet. Das Skript setzte hidden=true, die DOM-Pruefung
   meldete brav "true", und der Knopf stand trotzdem 50px hoch weiter da (gemessen
   14.08.2026, gemeldet vom Kunden). Betrifft jeden .tsb-btn, der je versteckt wird,
   deshalb steht die Regel allgemein. */
.tsb-btn[hidden]{
  display: none;
}

/* Und die Haarlinie zurueckholen. Abschnitt 67 setzt sie mit `.tsb-insta-mehr`
   (0,1,0), die Basis in Abschnitt 18 aber mit `:is(.tsb,.tsb-tm,.tsb-legal) .tsb-btn`
   - und :is() zaehlt wie seine spezifischste Auswahl, macht also (0,2,0). Die Basis
   gewinnt damit trotz frueherer Stelle, und der Knopf stand randlos da (gemessen
   14.08.2026: border-color rgba(0,0,0,0)). Zwei Klassen reichen zum Kontern.
   Nur die FARBE, nicht die Kurzschreibweise: Breite und Stil stehen in der Basis,
   und `border` mit var() darin wird zur Parse-Zeit nicht in Langformen zerlegt. */
.tsb-insta-tafel .tsb-insta-mehr{
  border-color: var(--line);
}

/* --- 68.8 Schmale Fenster ------------------------------------------------
   Eine Spalte: im Mehrspaltensatz liefe die Reihenfolge sonst spaltenweise, und
   die Daten spraengen sichtbar zurueck. Das Bild wird klein und bleibt links -
   ueber die volle Breite waere es genau das grosse Aufmacherbild, das hier nicht
   gewollt ist. Mehr Hoehe, weil derselbe Text in schmaleren Zeilen mehr Platz
   braucht: mit 320px bekaeme fast jeder Beitrag einen Knopf, den er am Rechner
   nicht hat. */
@media (max-width: 768px){
  .tsb-insta-tafel-feld{
    border-radius: var(--r-md);
    padding-top: var(--s-5);
    padding-bottom: var(--s-5);
    padding-left: var(--s-4);
    padding-right: var(--s-4);
  }

  .tsb-insta-tafel .tsb-insta-kopf{
    flex-direction: column;
    align-items: stretch;
    gap: var(--s-4);
    margin-bottom: var(--s-5);
  }

  .tsb-insta-tafel .tsb-insta-profil{ align-self: flex-start }

  .tsb-insta-tafel .tsb-insta-liste{
    column-count: 1;
  }

  .tsb-insta-tafel .tsb-insta-eintrag{ margin-bottom: var(--s-4) }

  .tsb-insta-tafel .tsb-insta-karte{
    padding-top: var(--s-4);
    padding-bottom: var(--s-4);
    padding-left: var(--s-4);
    padding-right: var(--s-4);
  }

  /* Bildbreite, Abzeichen und Grenze stehen schon im Normalfall richtig -
     hier bleibt nur, was wirklich vom schmalen Fenster abhaengt. */
}

@media (max-width: 480px){
  .tsb-insta-tafel .tsb-insta-bildlink{ width: 110px }
}
/* --- 68.9 Ab Tablet: zwei Spalten ---------------------------------------
   ZWEI SPALTEN AB 769px, WEIL SIE DIE HOEHE HALBIEREN.
   Der Theme-Container springt in festen Stufen; gemessen am 14.08.2026 ueber elf
   Fensterbreiten:

       Fenster        Container   Karte (2 Spalten)
       bis 1024px     768px       372px
       1025-1279px    950px       463px
       1280-1399px    1100px      538px
       ab 1400px      1300px      590px

   Einspaltig waere die Karte bei 1024px zwar 672px breit, der Abschnitt aber
   3208px hoch (gemessen) - sechs Beitraege in voller Hoehe untereinander. Zwei
   Spalten kosten Breite und sparen die Haelfte davon. Das Bild bleibt dabei
   gleich gross, deshalb faellt der Sprung der Kartenbreite kaum auf.

   DIE GRENZE STEIGT MIT, WEIL DIE SPALTEN DIE HOEHE HALBIEREN.
   Gemessene Inhaltshoehen ueber alle 24 Eintraege bei 590px Karte: min 342,
   Median 438, 85. Perzentil 534, Maximum 606. Mit 480px bleibt der Median
   vollstaendig stehen, und "Weiterlesen" trifft die laengeren - genau die, bei
   denen ein Knopf besser ist als eine halbe Bildschirmhoehe Text. */
@media (min-width: 769px){
  .tsb-insta-tafel .tsb-insta-liste{ column-count: 2 }
  .tsb-insta-tafel .tsb-insta-karte{ max-width: none }
  .tsb-insta-tafel .tsb-insta-inhalt{ max-height: 480px }
}

/* Erst im 1300er-Container ist die Karte breit genug, dass ein 200px-Bild neben
   dem Text nicht die halbe Zeile frisst. */
@media (min-width: 1400px){
  /* Im breitesten Container ist die Karte 590px breit, der Text also kompakter.
     Gemessen liegen dort 85 % der Beitraege unter 534px Inhaltshoehe - mit 560px
     bleibt "Weiterlesen" den wirklich langen vorbehalten. */
  .tsb-insta-tafel .tsb-insta-inhalt{ max-height: 560px }

  .tsb-insta-tafel .tsb-insta-bildlink{
    width: 200px;
    margin-right: var(--s-4);
  }

  .tsb-insta-tafel .tsb-insta-video{
    width: var(--s-7);
    height: var(--s-7);
  }

  .tsb-insta-tafel .tsb-insta-video::before{
    margin-left: 3px;
    border-top-width: 7px;
    border-bottom-width: 7px;
    border-left-width: 11px;
  }
}
/* ===== TSB-BLOCK:insta-tafel END ===== */

/* ===== TSB-BLOCK:kopf-mobil START ===== */
/* 39. Mobiler Kopf und Slide-out-Menue  [TSB-BLOCK:kopf-mobil]
   ------------------------------------------------------------------
   Ausgerollt am 22.07.2026, Abnahme 14/14. Grundlage:
   Konzept-Mobil-Optimierung-2026-07-22.md, Stufe 1.

   Warum es diesen Abschnitt gibt: `grep -c 'mkd-mobile'` ergab in dieser Datei 0.
   Der mobile Kopf war im Designsystem nicht vorhanden und lebte von Theme-Resten.
   Gemessener Ist-Zustand bei 390px (22.07.):
     Kopfflaeche #ffffff, Links #9b9a9a (2,81:1), Burger/Hover #c1e729 (1,43:1),
     CTA "Termin buchen" #43ec6b als TEXT auf Weiss (1,56:1), Schrift 15px in Versalien.
   Am Schreibtisch ist derselbe Kopf #141615 mit weissen Links (18,18:1) und der CTA
   eine gruene Pille. Der Bruch sitzt also genau bei 1025px.

   VORAUSSETZUNG, sonst wirkungslos: in `mu-plugins/tsb-nav-cta.php` v1.1 muss der
   <style id="tsb-nav-cta-css">-Block ZUERST entfernt werden. Seine Zeile 29
   `.mkd-mobile-nav ul li.tsb-nav-cta > a{color:#43ec6b!important}` schlaegt sonst die
   Regeln hier. Sie wurde laut eigenem Kommentar fuer ein "dunkles Slide-out"
   geschrieben, das es nie gab - dieser Abschnitt macht diese Annahme wahr.

   NICHT ANFASSEN: die `font-family` von `.mkd-icon-ion-icon` (Burger, Ionicons) und
   des Untermenue-Pfeils (FontAwesome). Wer sie ueberschreibt, bekommt statt des
   Piktogramms das Rohzeichen darunter - der Fehler vom 21.07.
   ------------------------------------------------------------------ */

/* --- Uebernahme aus tsb-nav-cta.php v1.1 (Desktop) --------------------
   ACHTUNG: Der geloeschte <style>-Block enthielt NICHT nur die mobile Zeile,
   sondern auch die Desktop-Pille. Wer ihn ersatzlos entfernt, ohne diese Regeln
   mitzunehmen, nimmt dem Schreibtisch-Kopf seinen Button. Die Werte sind der
   gemessene Ist-Zustand vom 22.07. (Ruhe 152x33px, bg #0a6b2e auf weissem Text,
   Hover #43ec6b auf #06331a) und werden hier nur auf Tokens gehoben.
   Die Polsterwerte 9px/20px bleiben Literale: sie auf das 8px-Raster zu runden
   waere eine Groessenaenderung am Desktop, die niemand bestellt hat. Groessen
   werden erst in Stufe 6 angefasst.
   Der Radius geht von 9px auf --r-sm (10px), Faktor 1,111 - nach der 1,12-Regel
   derselbe Wert, also kein Token dafuer. */
.mkd-main-menu ul li.tsb-nav-cta > a .menu_icon_wrapper { display: none !important }
.mkd-main-menu ul li.tsb-nav-cta > a { padding: 0 !important }
.mkd-main-menu ul li.tsb-nav-cta > a .item_inner {
  display: inline-flex;
  align-items: center;
}
.mkd-main-menu ul li.tsb-nav-cta > a .item_text {
  background:    var(--accent);
  color:         var(--on-dark) !important;
  padding-top:    9px;
  padding-bottom: 9px;
  padding-left:  20px;
  padding-right: 20px;
  border-radius: var(--r-sm);
  font-weight: 700;
  line-height: var(--lh-1);
  display: inline-block;
  transition: background .15s ease, color .15s ease, transform .15s ease;
}
.mkd-main-menu ul li.tsb-nav-cta > a:hover .item_text {
  background: var(--accent-bright);
  color:      var(--accent-ink) !important;
  transform:  translateY(-1px);
}

/* ⚠️ GRENZE AM 10.08.2026 VON 1024px AUF 1199px GEZOGEN.
   Das Theme zeigte den mobilen Kopf erst ab 1024px, ließ aber zwischen 1025 und 1200px
   den Desktop-Kopf stehen, obwohl Menü, Knopf und Icons dort nicht mehr in eine Zeile
   passen (gemessen bei 1100px: Kopfhöhe 170 statt 85px, Menü unter dem Logo). Block 60
   blendet den Desktop-Kopf deshalb ab 1199px aus. Damit der mobile Kopf dort auch so
   AUSSIEHT wie unterhalb von 1024px, muss diese Grenze mitwandern - sonst steht bei
   1100px ein ungestalteter weißer Kopf mit auseinandergerissenen Icons.
   Alle Regeln in dieser Media-Query hängen an .mkd-mobile-header (und am Abstand des
   Wrappers darunter), greifen also ohnehin nur, wenn der mobile Kopf sichtbar ist. */
@media (max-width: 1199px) {

  /* --- Flaeche ---------------------------------------------------- */
  /* Die `.mkd-mobile-header` selbst ist transparent, die Farbe traegt `-inner`. */
  .mkd-mobile-header .mkd-mobile-header-inner,
  .mkd-mobile-header .mkd-mobile-nav {
    background-color: var(--surface-dark);
  }
  .mkd-mobile-header .mkd-mobile-header-inner {
    border-bottom: 1px solid var(--line-on-dark);
  }

  /* --- Menueeintraege --------------------------------------------- */
  /* Die Trennlinie sitzt am ANKER, nicht am li (alle li haben border-bottom:0).
     Deshalb wird sie auch dort ersetzt und nicht danebengestellt.
     ⚠️ Bis 16.08.2026 gab es --line-on-dark nicht, und das sah NICHT so aus, wie man
     erwartet: Ein ausgefallenes var() macht die Deklaration nicht ungueltig, sondern
     "invalid at computed-value time" - die Eigenschaft faellt dann auf ihren
     INITIALWERT, nicht auf den Wert aus der vorigen Regel. Fuer border-bottom-color
     ist der Initialwert `currentColor`, und `color` steht hier zwei Zeilen darueber
     auf --on-dark. Gemessen war der Trenner deshalb REINWEISS (#fff, 15,7:1 auf der
     Kopffarbe), nicht das Theme-Grau #eaeaea, das man vermutet. Ein Gitter aus harten
     weissen Strichen - im Bild sofort zu sehen, in keiner Regel nachzulesen. */
  .mkd-mobile-header .mkd-mobile-nav ul li > a,
  .mkd-mobile-header .mkd-mobile-nav ul li > h3 {
    color: var(--on-dark);
    border-bottom-color: var(--line-on-dark);
    font-size: var(--fs-base);
    /* Zeilenhoehe als FAKTOR. Das Theme vererbt `1.66667em` als Laenge (25px) und
       erzeugt damit die uneinheitlichen Hoehen. */
    line-height: var(--lh-flat);
    text-transform: none;
    /* Hoehe ueber `flex` + `min-height`, NICHT ueber Polster. Gemessen am 22.07.:
       `padding: 12px 0` plus `min-height: 48px` ergab 73px, weil im Anker neben dem
       <span> noch ein Textknoten mit eigener Zeilenhoehe steht und beides addiert
       wird. Bei 14 Eintraegen wurde das Menue dadurch 1041px lang und der
       Handlungsaufruf rutschte auf y=1013, also unter den Bildschirmrand.
       Mit `flex` traegt `min-height` die Hoehe allein: 8 x 48 + 6 x 40 + 64 = 688px
       und passt in 844px. Nachmessen, nicht nachrechnen. */
    display: flex;
    align-items: center;
    min-height: var(--s-7);
    padding-top: 0;
    padding-bottom: 0;
  }
  /* Der letzte Eintrag bekommt BEWUSST keine Linie (16.08.2026).
     Hier stand bis dahin `border-bottom-color: var(--line-on-dark)` mit dem Vorsatz
     "die Liste soll unten abschliessen". Die Regel konnte nie wirken - und zwar aus
     zwei unabhaengigen Gruenden, was beim Anlegen des Tokens auffiel:
       1. Das Theme setzt `…mkd-mobile-nav>ul>li:last-child>a{border-bottom:none}`.
          Eine Farbe an einem Rand mit `style: none` malt nichts; noetig waere die
          Langform mit `-width` und `-style`.
       2. Der Abschluss liegt ohnehin woanders: `.mkd-mobile-nav` traegt ihn als
          Containerkante [TSB-BLOCK:kopf-sticky]. Gemessen sitzt sie 20px unter dem
          letzten Eintrag - beide Linien zusammen waeren ein doppelter Abschluss mit
          20px Luft dazwischen, nicht ein sauberer.
     Der Container gewinnt, weil er auch dann unten abschliesst, wenn das Menue
     scrollt. Wer die Anker-Linie zurueckholen will, braucht 1. UND muss 2. aufloesen. */

  /* --- Aktive Seite ------------------------------------------------
     Heute gibt es mobil keinerlei Kennzeichnung (::before/::after = none).
     Der Balken spiegelt den 4px-Balken des Desktop-Menues. */
  .mkd-mobile-header .mkd-mobile-nav ul li.mkd-active-item > a,
  .mkd-mobile-header .mkd-mobile-nav ul li.current-menu-item > a {
    border-left-width: 3px;
    border-left-style: solid;
    border-left-color: var(--accent-bright);
    padding-left: var(--s-3);
  }

  /* --- Hover und Fokus --------------------------------------------
     Loest die Trophy-Demo-Lime #c1e729 (1,43:1) ab. */
  .mkd-mobile-header .mkd-mobile-nav ul li > a:hover,
  .mkd-mobile-header .mkd-mobile-nav ul li > a:focus-visible,
  .mkd-mobile-header .mkd-mobile-nav ul li.mkd-active-item > a:hover {
    color: var(--accent-bright);
  }
  .mkd-mobile-header .mkd-mobile-nav ul li > a:focus-visible,
  .mkd-mobile-header .mkd-mobile-menu-opener a:focus-visible {
    outline-width: 2px;
    outline-style: solid;
    outline-color: var(--focus-on-dark);
    outline-offset: 2px;
  }

  /* --- Der Handlungsaufruf wird zur Flaeche ------------------------
     Das ist der Kern: `--accent-bright` steht am Token mit dem Kommentar
     "immer nur als Flaeche, nie als Text auf Hell". Mobil war es genau das
     Gegenteil. Markup ist <a><span>Termin Buchen</span></a>; ein `.item_text`
     wie im Desktop-Menue existiert hier NICHT und traefe lautlos nichts. */
  .mkd-mobile-header .mkd-mobile-nav ul li.tsb-nav-cta > a {
    border-bottom-color: transparent;
    min-height: var(--s-8);      /* 48px Pille + je 8px Luft */
  }
  .mkd-mobile-header .mkd-mobile-nav ul li.tsb-nav-cta > a > span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--s-7);
    padding-left: var(--s-5);
    padding-right: var(--s-5);
    background-color: var(--accent-bright);
    color: var(--accent-ink);
    /* Desktop-Knopf hat 9px, --r-sm hat 10px, Faktor 1,111 - nach der
       Projektregel (unter 1,12) derselbe Wert, also kein neues Token. */
    border-radius: var(--r-sm);
    font-weight: 700;
  }
  .mkd-mobile-header .mkd-mobile-nav ul li.tsb-nav-cta > a:hover > span {
    color: var(--accent-ink);
    filter: brightness(1.06);
  }

  /* --- Burger ------------------------------------------------------
     Nur die FARBE, nie die font-family (Ionicons-Glyph). */
  .mkd-mobile-header .mkd-mobile-menu-opener a,
  .mkd-mobile-header .mkd-mobile-menu-opener .mkd-mobile-opener-icon-holder,
  .mkd-mobile-header .mkd-mobile-menu-opener i {
    color: var(--on-dark);
  }
  .mkd-mobile-header .mkd-mobile-menu-opener a:hover .mkd-mobile-opener-icon-holder,
  .mkd-mobile-header .mkd-mobile-menu-opener a:hover i,
  .mkd-mobile-header .mkd-mobile-menu-opener.mkd-opened .mkd-mobile-opener-icon-holder,
  .mkd-mobile-header .mkd-mobile-menu-opener.mkd-opened i {
    color: var(--accent-bright);
  }
  /* Trefferflaeche: gemessen 34x34 als Box. --s-7 statt eines neuen --tap-min:44px,
     weil 44 zu 48 Faktor 1,09 waere und damit die 1,12-Regel braeche. */
  .mkd-mobile-header .mkd-mobile-menu-opener > a {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--s-7);
    min-height: var(--s-7);
  }

  /* --- Untermenues dauerhaft offen ---------------------------------
     Gemessen sichtbar sind heute 8 von 14 Eintraegen. Die beiden Untermenues
     ("Angebote & Preise", "Camps") verstecken 6 Angebotsseiten hinter einem
     7x10px grossen Pfeil, und 83 Prozent der Zeilenbreite navigiert stattdessen
     zur Uebersicht. Dauerhaft offen kostet Hoehe und spart einen Fehlgriff. */
  .mkd-mobile-header .mkd-mobile-nav ul li ul {
    display: block;
    /* Das Theme bringt am Untermenue `margin-left:20px` und `padding-left:15px` mit.
       Zusammen mit einem eigenen Einzug ergab das 51px Textkante. Zuruecksetzen und
       den Einzug an EINER Stelle vergeben. */
    margin-left: 0;
    padding-left: 0;
  }
  .mkd-mobile-header .mkd-mobile-nav ul li ul li > a {
    padding-left: var(--s-5);
    min-height: 40px;              /* Nebenweg, deshalb flacher als die Hauptebene */
    font-size: var(--fs-sm);
    color: var(--on-dark-muted);   /* 7,00:1 auf --ink */
  }
  /* Der Aufklapp-Pfeil hat damit keine Aufgabe mehr. */
  .mkd-mobile-header .mkd-mobile-nav .mobile_arrow {
    display: none;
  }

  /* Logo. ACHTUNG, der Wrapper heisst `.mkd-mobile-logo-wrapper`, nicht
     `.mkd-logo-wrapper` (das ist der Desktop-Kopf). Ein Selektor auf den falschen
     Namen faellt lautlos aus - genau das ist am 22.07. im ersten Entwurf passiert,
     das Logo blieb 80px hoch und ragte aus dem 64px-Kopf heraus.
     Die Hoehe kommt aus einem Inline-`style="height:187px"` am Anker
     (Spezifitaet 1,0,0,0), deshalb am `img` begrenzen, nicht am `a`. */
  .mkd-mobile-header .mkd-mobile-logo-wrapper a img {
    max-height: var(--s-7);
    width: auto;
  }
}

@media (max-width: 768px) {
  /* Kopfhoehe von 100px auf 64px. Bei 844px Bildschirm sind 100px 11,8 Prozent,
     die auf jeder Seite ueber dem Inhalt stehen.

     Die Hoehe MUSS am `-inner` stehen: die Kinder des Kopfes leiten ihre Hoehe vom
     Elternteil ab, ein Verlegen auf den `-holder` liess beide auf 0px kollabieren.
     Dass der `-inner` auch das Menue enthaelt, loest Abschnitt 43, indem er das Menue
     absolut unter den Kopf haengt. */
  .mkd-mobile-header .mkd-mobile-header-inner {
    height: var(--s-8);
  }
}
/* ===== TSB-BLOCK:kopf-mobil END ===== */
