/* ============================================================
 * ticketpay Shop-Designer — generiertes Override-CSS
 * Design: Vorlage 0 — SOCKEL (Endfassung)
 * Gilt für Ticketshop (shop.ticketpay.de) + MyTicketportal (my.ticketpay.de).
 * Wird als Kunden-css_url geladen (letzte Schicht der Kaskade).
 * NICHT von Hand editieren — im Shop-Designer anpassen und neu exportieren.
 * ============================================================ */

:root {
  --tp-radius-panel: 8px;
  --tp-shadow-panel: none;
  --tp-border-panel: 1px solid var(--tp-color-border, rgba(0,0,0,0.08));
  --tp-radius-button: 6px;
  --tp-radius-input: 8px;
  --tp-sticky-pad-top: 6px;
  --tp-sticky-pad-bottom: 6px;
  --tp-sticky-btn-h: 40px;
  --tp-transition-base: 180ms cubic-bezier(0.4, 0, 0.2, 1);
}

/* ============ Schriften ============ */
/* — fonts.heading-weight = "700" — */
body.v2 h1, body.v2 h2, body.v2 h3, body.v2 h4, body.v2 h5, body.v2 h6, body.v2 .wrap_heading h2, body.v2 .cover-content h2, body.v2 .panelx_heading h4 { font-weight: 700; }

/* — fonts.heading-letter-spacing = "eng" — */
/* V-S2 (Runde V): gesperrte Laufweite verbreitert den Kartentitel ebenso (sehr-weit allein:
   18 px / 41 px Ueberlauf). Begruendung bei fonts.heading-font. */
body.v2 .panelx_heading h4.snip { white-space: normal !important; text-overflow: clip !important; overflow-wrap: break-word; }
body.v2 h1, body.v2 h2, body.v2 h3, body.v2 h4, body.v2 .wrap_heading h2, body.v2 .cover-content h2, body.v2 .panelx_heading h4 { letter-spacing: -0.02em; }

/* — fonts.tabular-numbers = true — */
body.v2 .subtotal li, body.v2 .show_price, body.v2 table.table td, body.v2 table.table th, body.v2 .countDownTimer, body.v2 #cart_button_amount, body.v2 #cart_button_amount_top { font-variant-numeric: tabular-nums; }

/* ============ Kopfbereich & Cover ============ */
/* — header.title-size = "riesig" — */
body.v2 .cover-content h2 { font-size: clamp(30px, 5.5vw, 58px); line-height: 1.1; }

/* — header.title-weight = "fett" — */
body.v2 .cover-content h2 { font-weight: 700; }

/* — header.details-style = "prominent" — */
body.v2 .cover-content p { font-size: 17px; margin-top: 8px; }
body.v2 .cover-content a.header_details { font-size: 17px; font-weight: 600; }
/* M-K4: Typo-Booster gegen die Kicker-Regeln — nur Typo, keine Margins (s. Option dezent). */
body.v2 .cover .cover-content .col-md-8 > p, body.v2 .cover .cover-content .col-md-7 > p { font-size: 17px; opacity: 1; }
body.v2 .cover .cover-content .col-md-8 > p a.header_details, body.v2 .cover .cover-content .col-md-7 > p a.header_details { font-size: 17px; font-weight: 600; }

/* ============ Hintergrund & Flächen ============ */
/* — background.seitenluft = "luftig" — */
/* Runde Z2 (M2, 2026-08-06): aus portal.portal-abstaende hierher zentralisiert — EIN Regler fuer die Seitenluft aller drei Flaechen (Konzept §5 A, Jury-Mehrheit 3:0 fuer Kandidat M2b). Die POSITION dieses Features ist Teil der Lieferung: hinter background.buehne (Index 5) schlaegt der Buehnenarm dessen Polsterung — so wie portal-abstaende (order 90) es bisher tat; und als Domaene background (order 25) VOR checkout (order 60) weicht die flache Naht-Regel planmaessig checkout.progress-hero. Bewusst angenommen (gemessen, protokolliert in Z2-ENTSCHEIDUNGEN §M2): der Buehnenarm ueberschreibt auch die Mobil-Reduktion von background.buehne (16 -> 10/30 px) — Seitenluft ist der zustaendige Regler; buehne hat 0/12 Nutzer. */
body.v2 #content > .container { padding-top: 30px; padding-bottom: 50px; }
/* Naht: der Serien-margin-top des ersten Buehnenkindes (8 px @1280, 4 px @375) kollabiert NICHT — der Bootstrap-Clearfix .container::before{display:table} sperrt ihn (gemessen) — und addierte sich sonst auf die Polsterung; dieselbe Einstellung saehe im Ticketshop anders aus als im Portal. FLACH (0,2,1) mit Absicht: gewinnt gegen die Serie (unsere Schicht laedt spaeter), verliert gegen checkout.progress-hero (gleiche Spezifitaet, spaetere Domaene) — kreise-cover behaelt seine -124px. Dieselbe Regel eine Ebene tiefer (1,3,1) zerstoert kreise-cover lautlos. */
body.v2 .checkout-progress-row { margin-top: 0; }
/* Z-P1 (Runde Z, Backlog 2): der alte Wert 24 px lag UNTER dem nackten Serienwert 30 px — "mehr Weissraum" lieferte weniger als gar kein CSS (W-12-Muster). 36 px gemessen auf portal-order/-teams/-ticket/-resale/-resale-form; Leiter 10 < 30 (nackt) < 36 bleibt monoton. */
body.v2:has(.navbar.navbar-default) .box-light, body.v2:has(.navbar.navbar-default) .box-grey, body.v2:has(.navbar.navbar-default) .box-dark, body.v2:has(.navbar.navbar-default) .box-darker, body.v2:has(.navbar.navbar-default) .box-coloured, body.v2:has(.navbar.navbar-default) .box-danger { margin-bottom: 36px; }

/* ============ Karten & Boxen ============ */
/* — cards.unify = true — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
body.v2 .panelx { border-radius: var(--tp-radius-panel, 8px); box-shadow: var(--tp-shadow-panel, 0 2px 10px rgba(0,0,0,0.08)); overflow: hidden; background-clip: padding-box; }
body.v2:has(.navbar.navbar-default) .box-light, body.v2:has(.navbar.navbar-default) .box-grey, body.v2:has(.navbar.navbar-default) .box-dark, body.v2:has(.navbar.navbar-default) .box-darker, body.v2:has(.navbar.navbar-default) .box-coloured, body.v2:has(.navbar.navbar-default) .box-danger { border-radius: var(--tp-radius-panel, 8px); box-shadow: var(--tp-shadow-panel, 0 2px 10px rgba(0,0,0,0.08)); }

/* — cards.radius = 8 — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
body.v2 .well:not(.well-noradius), body.v2 .jumbotron, body.v2 .modal-content, body.v2 .panelx, body.v2 #organizer_events_grid .panelx, body.v2 #organizer_events_list .event-listing, body.v2 .box-light, body.v2 .box-grey, body.v2 .box-dark, body.v2 .box-darker, body.v2 .box-coloured, body.v2 .box-danger { border-radius: 8px; }
body.v2 .box-footer { border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; }
body.v2 .wrap.accordions .wrap_content .well, body.v2 .wrap.accordions + #shopping_cart .wrap_content .well { border-radius: 8px; }
body.v2 .wrap.accordions .wrap_heading { border-radius: 8px; }
body.v2 .wrap.accordions .wrap_heading + .wrap_content, body.v2 .wrap.accordions + #shopping_cart .wrap_heading + .wrap_content { margin-top: 6px; }
/* I-12 (Runde I, Rubrik 4): .well-noradius ist der einzige Kasten, der bisher das
   Radius-System der Vorlage nicht mitmacht (Serie: border-radius 0). */
body.v2 .well .well-noradius, body.v2 .well.well-noradius { border-radius: var(--tp-radius-panel, 0px) !important; }

/* — cards.shadow = "none" — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
/* Z8-2 (Runde Z8, CEO-Befund 2026-08-06 „die Vorlagen gleichen sich an"): Die Serie haelt
   body.v2 .well.well-shadow (0,3,1) — unser Arm body.v2 .well (0,2,1) verlor das Duell, und
   der Karten-Schatten der Vorlage kam in KEINER von zwoelf an (alle trugen 0 0 6px rgba(0,0,0,.3),
   byte-gleich mit dem nackten Shop; per CDP nachgewiesen). Den Hausanker mitzunennen hebt uns
   auf dieselbe Stufe und laesst die spaetere Regel gewinnen — Muster z4_a2 aus Runde Z4.
   Vorlagen OHNE gesetzten Schatten emittieren die Regel gar nicht und behalten die Serie. */
body.v2 .well, body.v2 .well.well-shadow, body.v2 .jumbotron, body.v2 .modal-content, body.v2 .panelx, body.v2 #organizer_events_grid .panelx, body.v2 #organizer_events_list .event-listing, body.v2 .box-light, body.v2 .box-grey, body.v2 .box-dark, body.v2 .box-darker, body.v2 .box-coloured, body.v2 .box-danger { box-shadow: none; }
body.v2 .wrap.accordions .wrap_content .well, body.v2 .wrap.accordions + #shopping_cart .wrap_content .well { box-shadow: none; }

/* — cards.border = "hairline" — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
body.v2 .well:not(.well-feature):not(.well-brand):not(.well-icon), body.v2 .jumbotron, body.v2 .modal-content, body.v2 .panelx, body.v2 #organizer_events_grid .panelx, body.v2 #organizer_events_list .event-listing, body.v2 .box-light, body.v2 .box-grey, body.v2 .box-dark, body.v2 .box-darker, body.v2 .box-coloured, body.v2 .box-danger { border: 1px solid var(--tp-color-border, rgba(0,0,0,0.08)); }
body.v2 .wrap.accordions + #shopping_cart .wrap_content .well { border: 1px solid var(--tp-color-border, rgba(0,0,0,0.08)); }
body.v2 .well.well-icon { border: 1px solid var(--tp-color-border, rgba(0,0,0,0.08)); background-image: none; }
body.v2 .well.well-icon.well-icon-checked { border-color: var(--tp-color-primary, #ff4d06); background-color: var(--tp-color-primary-soft, rgba(0,0,0,0.06)) !important; }

/* — cards.density = "airy" — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
body.v2 .well { padding: clamp(20px, 3vw, 32px); }
/* Z10-F1 (Runde Z10): Die Serie kennt Kompakt-Varianten — .well-sm (9px) und
   .jumbotron-less-padding (15px). Unsere Grundregel (0,2,1) schlug beide (0,1,0 bzw.
   0,2,0) und gab dort DOPPELT so viel Polster: 29 Vorkommen auf 16 Flaechen, die
   Portal-Kompaktkaesten wuchsen von 45,7 auf ~90 px, und im Organizer verengte das
   Jumbotron-Polster die Filterspalte so weit, dass die Sortier-Auswahl abschnitt.
   Wo die Serie ausdruecklich weniger Polster verlangt, geben wir jetzt auch weniger. */
body.v2 .well.well-sm { padding: 13px; }
body.v2 .jumbotron.jumbotron-less-padding { padding: 21px; }
body.v2 .jumbotron { padding: clamp(26px, 4vw, 44px); }
body.v2 .modal-body { padding: clamp(18px, 3vw, 28px); }
/* Z10-F3 (Runde Z10): Nur der Dialogkoerper wurde gepolstert — Kopf und Fuss blieben auf
   Serienmass. Die Innenkante sprang dadurch um 13 px: der Titel stand links von seinem
   eigenen Text, der Fussknopf rechts vom Feld darueber (4 Dialogflaechen, 8 Vorlagen,
   @1280). NUR waagerecht — die senkrechten Serienmasse bleiben, sie tragen die Trennlinie. */
body.v2 .modal-header, body.v2 .modal-footer { padding-left: clamp(18px, 3vw, 28px); padding-right: clamp(18px, 3vw, 28px); }
body.v2:has(.navbar.navbar-default) .box-inner:not(.box-inner-nopadding) { padding: clamp(16px, 2.5vw, 26px); }
/* Z10-F2 (Runde Z10): Das Kartenblatt bekam mehr Polster, die Kartenfusszeile nicht —
   der Knopf darin ragte links UND rechts je 11 px aus der Fluchtlinie von Ueberschrift
   und Trennlinie (7 Karten auf 3 Portalflaechen, 9 Vorlagen, @1280; nackt fluchtet es
   exakt). Nur waagerecht: die senkrechten 10 px sind Serienmass. */
body.v2:has(.navbar.navbar-default) .box-footer { padding-left: clamp(16px, 2.5vw, 26px); padding-right: clamp(16px, 2.5vw, 26px); }
/* V-6 (Runde V): siehe Gegenstueck bei "Kompakt". */
body.v2 #organizer_events_grid .panelx .panelx_top, body.v2 #organizer_events_grid .panelx .panelx_bottom, body.v2 #organizer_events_grid .panelx .panelx_heading { padding: clamp(14px, 2vw, 20px); }
body.v2 #organizer_events_list .event-listing { padding: clamp(14px, 2vw, 20px); }

/* — cards.flatten-nested = true — */
body.v2 .well .well:not(.well-icon):not(.well-feature):not(.well-brand) { background-color: transparent !important; border: 0; box-shadow: none; }

/* — cards.divider-style = "subtle" — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
  /* Z9-C (Runde Z9): .line.visible-xs ist die MOBILE Mengen-/Preiszeile, kein Trenner —
     und in ihrer Zelle erstes Kind. Sie bekam bei <=767px eine Oberlinie, die den
     Artikelnamen von seiner eigenen Mengenangabe abschnitt (payment, success, cart-modal;
     12/12, nackt 0 px). Nur noch hr traegt die Trennlinie. */
body.v2 hr { border: 0; border-top: 1px solid color-mix(in srgb, var(--tp-color-border, rgba(0,0,0,0.10)) 60%, currentColor 40%); }
  /* Z9-B (Runde Z9, CEO-Befund 2026-08-06): Die Linie sass buendig auf der Oberkante der
     Folgezeile — 1-3 px bis zu deren Beschriftung, waehrend dieselbe Beschriftung 4-11 px
     von ihrem EIGENEN Wert entfernt steht. Das Auge gruppiert dann [Linie+Label] statt
     [Label+Wert]: die Linie trennt innerhalb der Gruppe statt zwischen den Gruppen.
     Gemessen auf organizer-grid/-list/-datumsfilter und portal-order, 38 Vorkommen, 12/12,
     nackt 0. Die Polsterung nimmt den Serienabstand der Zeile (.line + .line: margin-top 2px)
     als Mass und verdoppelt ihn nach oben — mehr wuerde die Karte auseinanderziehen. */
  /* Z10-D1 (Runde Z10, CEO 2026-08-06): Von den 20 Zeilenpaaren auf portal-order tragen
     ZWOELF einen Knopf ("Jetzt personalisieren", "Zu den Ticketdetails"). Das sind
     Aktionszeilen, keine Datenzeilen — der Trennstrich schnitt den Knopf von den Daten ab,
     zu denen er gehoert, und der nackte Shop hat dort ausnahmslos border-top 0px none.
     :has() ist reine Zusatzoptik: ohne Unterstuetzung bleibt exakt das bisherige Verhalten. */
body.v2 .line:not(.visible-xs) + .line:not(.visible-xs):not(:has(.btn)) { border: 0; border-top: 1px solid color-mix(in srgb, var(--tp-color-border, rgba(0,0,0,0.10)) 60%, var(--tp-color-panel-text, var(--tp-color-body-text, currentColor)) 40%); padding-top: 4px; }
body.v2 .wrap.accordions { border-bottom: 1px solid var(--tp-color-border, rgba(0,0,0,0.10)); }
body.v2 .wrap.accordions:has(.wrap_heading i.fa-plus-circle) { border-bottom: 0; }
  /* Z14-SPORT-2 (CEO-DOCX 2026-08-15, Bild media/f3c90996): Der Abschnitts-Trenner gehoert dem
     RECHTECKIGEN .wrap.accordions, die optisch tragende Karte ist GERUNDET — er ragt je Ecke um
     den Kartenradius auf den Seitengrund, und wo der Wrapperfuss unter der Karte endet, steht er
     in voller Breite frei (45 von 168 offenen Sektionen, sport-clean bis 18,25 : 1). Im offenen
     Zustand trennt die Karte selbst. Bewusst border-bottom-COLOR statt border-bottom: 0 —
     Letzteres loest die Rand-Sperre gegen Margin-Collapse und nimmt 22 px Luft; so bleibt die
     Geometrie bitgleich (90/90 Flaechen aendern nur die Trennerzeile). Ausnahme raster
     (mono-kontrast-Identitaet 21 : 1, K-8); fade braucht den Arm nicht (Kontrast 1,05-1,18). */
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) { border-bottom-color: transparent; }
body.v2 .items { border-top-color: rgba(128,128,128,0.25) !important; border-top-color: color-mix(in srgb, currentColor 12%, transparent) !important; }
/* M5-4 (Runde Z3, Panel 3 : 0) — Rolle "Datentabelle": die Kopflinie neutraler Tabellen
   ist ein Serienton rgb(221,221,221) in 12/12 Vorlagen. Dunkel ein weisser Fremdstrich mit
   11,6 : 1 (lauter als die Ueberschrift daneben), hell mit 1,16-1,36 unsichtbar und auf fuenf
   Vorlagen UNTER dem nackten Shop (1,36). Nur die FARBE wird gekoppelt — Staerke, Form und
   Polsterung bleiben Serie, und font-weight bleibt draussen: im <thead> steckt eine
   verschachtelte Tabelle, ein Gewichtsarm traefe nur 6 von 8 Kopfzellen (Z3-M5-3).
   Ausgeschlossen sind der Kassenanker (#cart_items ~ table.table) und JEDER Kalender —
   die Gegenprobe "Zabuto = 0 Treffer" ist Lieferbestandteil (Runde V, daran starb die
   Ordertabellen-Familie schon einmal). Der tbody-Zeilentrenner bleibt vorerst DRAUSSEN:
   die einzige Pruefflaeche hat 0 Datenzeilen (Materialsperre B8, shop_order_id). */
body.v2 table.table:not(#cart_items ~ *):not(:where(.zabuto_calendar,.daterangepicker,.calendar-table) table) > thead > tr > th { border-bottom-color: color-mix(in srgb, currentColor 45%, transparent); }

/* — cards.accordion-head = "card" — */
/* F1: Lange Knopf-Beschriftungen in Ergebnis-Karten duerfen umbrechen, statt aus der Karte (und dem Bildschirm) zu laufen. */
body.v2 .jumbotron .btn-box .btn { white-space: normal; max-width: 100%; overflow-wrap: break-word; }
body.v2 .wrap .wrap_heading, body.v2 .wrap.accordions .wrap_heading, body.v2 .wrap.accordions + #shopping_cart .wrap_heading { background-color: var(--tp-color-panel-bg, #ffffff); border-radius: var(--tp-radius-panel, 8px); box-shadow: var(--tp-shadow-panel, 0 2px 10px rgba(0,0,0,0.08)); padding: 12px 16px; margin-bottom: 10px; }
body.v2 .wrap.accordions { border-bottom-color: var(--tp-color-border, rgba(0,0,0,0.10)); }
body.v2 .wrap.accordions .wrap_heading + .wrap_content { margin-top: 0; }
body.v2 .wrap.accordions .wrap_heading { cursor: pointer; }
body.v2 .wrap.accordions .wrap_heading:hover { filter: brightness(0.96); }
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) { border-bottom: 0; background-image: none; border-radius: var(--tp-radius-panel, 8px); box-shadow: var(--tp-shadow-panel, 0 2px 10px rgba(0,0,0,0.08)); }
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) .wrap_heading { border-bottom-left-radius: 0; border-bottom-right-radius: 0; box-shadow: none; margin-bottom: 0; }
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) .wrap_content .well { border-top-left-radius: 0; border-top-right-radius: 0; border-bottom-left-radius: var(--tp-radius-panel, 8px); border-bottom-right-radius: var(--tp-radius-panel, 8px); box-shadow: none; }
body.v2 .wrap.accordions:has(.wrap_heading i.fa-plus-circle) { border-bottom: 0; background-image: none; }
/* J-A1 (Backlog Runde I, von 4 von 4 Jurys genannt): Ein zugeklapptes Akkordeon zeigte nur
   die Kopfzeile — ohne Flaeche, ohne Abschluss, ein verlorener Balken statt einer geschlossenen
   Karte. Der geschlossene Kopf ist deshalb eine vollstaendige, allseitig gerundete Karte mit
   eigener Flaeche, Rand und Schatten — dieselbe Material-Sprache wie die Karte, die er verbirgt,
   und klar abgesetzt vom offenen Zustand (der oben gerundet mit der Karte verwaechst).
   Zustandsbezug ueber das Serien-Icon (fa-plus-circle = zu, fa-minus-circle = offen).
   .wrap_content wird NICHT angefasst — display/height gehoeren dem Accordion-JS. */
body.v2 .wrap.accordions:has(.wrap_heading i.fa-plus-circle) .wrap_heading { background-color: var(--tp-color-panel-bg, #ffffff); color: var(--tp-color-panel-text, inherit); border: var(--tp-border-panel, 0); border-radius: var(--tp-radius-panel, 8px); box-shadow: var(--tp-shadow-panel, 0 2px 10px rgba(0,0,0,0.08)); padding: 14px 16px; margin-bottom: 0; }
body.v2 .wrap.accordions + #shopping_cart .wrap_heading, body.v2 #shopping_cart .wrap .wrap_heading { border-bottom-left-radius: 0; border-bottom-right-radius: 0; margin-bottom: 0; }
body.v2 .wrap.accordions + #shopping_cart .wrap_content .well, body.v2 #shopping_cart .wrap .wrap_content .well { border-top-left-radius: 0; border-top-right-radius: 0; }
body.v2 .wrap .wrap_heading h2, body.v2 .wrap.accordions .wrap_heading h2, body.v2 .wrap.accordions + #shopping_cart .wrap_heading h2 { display: flex; align-items: center; gap: 0.3em; }
body.v2 .wrap .wrap_heading h2 i.fa { flex: 0 0 auto; line-height: 1; }
body.v2 .wrap .wrap_heading i.fa-plus-circle, body.v2 .wrap .wrap_heading i.fa-minus-circle { transition: transform var(--tp-transition-base, 0.2s ease); }
body.v2 .wrap .wrap_heading:has(i.fa-minus-circle) i.fa { transform: rotate(180deg); }

/* — cards.box-merge = true — */
body.v2:has(.navbar.navbar-default) :is(.box-light, .box-grey, .box-dark, .box-darker):has(+ :is(.box-light, .box-grey, .box-dark, .box-darker)) { border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-bottom-width: 0; margin-bottom: 0; }
body.v2:has(.navbar.navbar-default) :is(.box-light, .box-grey, .box-dark, .box-darker) + :is(.box-light, .box-grey, .box-dark, .box-darker) { border-top-left-radius: 0; border-top-right-radius: 0; margin-top: 0; }

/* ============ Buttons & Aktionen ============ */
/* — buttons.form = "leicht" — */
body.v2 .btn, body.v2 .btn.btn-default, body.v2 .btn.btn-brand, body.v2 .btn.btn-grey, body.v2 .btn.btn-info, body.v2 .btn.btn-success, body.v2 .btn.btn-danger, body.v2 .badge, body.v2 .label.label-default { border-radius: var(--tp-radius-button, 4px) !important; }
body.v2 .input-group .btn, body.v2 .input-group-btn:last-child > .btn { border-top-left-radius: 0 !important; border-bottom-left-radius: 0 !important; border-top-right-radius: var(--tp-radius-button, 4px) !important; border-bottom-right-radius: var(--tp-radius-button, 4px) !important; }
body.v2 .cover .btn-group, body.v2 #stickyfooter .btn-group { display: inline-flex; align-items: center; gap: 6px; }
body.v2 .cover .btn-group > .btn, body.v2 #stickyfooter .btn-group > .btn { margin-left: 0; margin-right: 0; }
/* I-13 (Runde I, Rubrik 1): Symbol und Beschriftung standen ohne Abstand aneinander (4 von 4
   Jurys). Loesung ueber gap statt margin: gap wirkt nur ZWISCHEN Flex-Kindern, laesst reine
   Icon-Knoepfe (SSL-Schloss, #event_scroll2continue) also unberuehrt. Auf nicht-Flex-Knoepfen
   wird die Eigenschaft schlicht ignoriert. */
body.v2 .btn { gap: .5em; }
/* Z9-A (Runde Z9, CEO-Befund 2026-08-06): Der Ansichtsumschalter der Veranstalter-Uebersicht
   (#events_grid + #events_list) ist die EINZIGE .btn-group ausserhalb von .cover und
   #stickyfooter — alle anderen werden von dieser Option bewusst auf gap:6px getrennt, er
   behaelt seine -1px-Ueberlappung. Ohne die Innenkanten-Nullsetzung bekommen dann BEIDE
   Segmente den vollen Radius rundum und stossen mit runden Kanten aneinander: der Schalter
   zerfaellt in zwei Knoepfe (gemessen 6 von 12 Vorlagen, 6 Organizer-Flaechen; nackt traegt
   er 3px 0 0 3px / 0 3px 3px 0 und hat Kerbe 0). Die Regel stand bisher nur in "pille". */
body.v2 .btn-group > .btn:not(:first-child) { border-top-left-radius: 0 !important; border-bottom-left-radius: 0 !important; }
body.v2 .btn-group > .btn:not(:last-child) { border-top-right-radius: 0 !important; border-bottom-right-radius: 0 !important; }
/* Z12 (Kopf-Wiederherstellung, Bildbeweis rundeB + zeitstrahl __1-__5): Z9-A kopierte die
   Innenkanten-Nullsetzung von "pille" hierher, aber OHNE deren Rückschalter-Ausnahme —
   die Kopf-Knopfgruppe (Info/Hilfe/Warenkorb) und die Kaufleisten-Gruppen verloren dadurch
   ihre Original-Rundung (elegant-serif: 6px -> eckig; minimal-brand: Voll-Pillen -> Ecken).
   Dieselbe Bauform wie in pille: gleiche Spezifität, Quellreihenfolge entscheidet, NACH den
   :not()-Regeln. Der Ansichtsumschalter (#events_grid/#events_list) liegt außerhalb von
   .cover/#stickyfooter und bleibt unberührt (Z9-A-Fix intakt). */
body.v2 .cover .btn-group > .btn, body.v2 #stickyfooter .btn-group > .btn { border-radius: var(--tp-radius-button, 4px) !important; }

/* — buttons.varianten-vereinheitlichen = true — */
body.v2 .btn-default, body.v2 .btn-primary, body.v2 .btn-info, body.v2 .btn-success, body.v2 .btn-danger, body.v2 .btn-grey, body.v2 .btn-brand { border-radius: var(--tp-radius-button, 4px); font-weight: 600; border-width: 1px; border-style: solid; }

/* — buttons.sticky-cta-gross = true — */
body.v2 #stickyfooter { height: auto !important; line-height: normal !important; padding-top: 6px; padding-bottom: 6px; }
/* L3c (Options-Integritaet, L1c HOCH): Vorher zielte die Option nur auf .btn-continue (Klassen-Spezifitaet)
   und verlor gegen die Serien-ID-Regel (#stickyfooter #stickyfooter-inner .btn) sowie gegen die
   Leisten-Familie (a#initorder_layout: Hoehe/Zeilenhoehe ueber --tp-sticky-btn-h, padding 0,
   font-size-Klemme !important am Handy) — gemessen 0px Wirkung, in allen 12 Presets wirkungslos.
   Jetzt: das Hoehen-Token direkt am Knopf anheben (Element-Wert schlaegt die geerbten 40-48px),
   Schrift und Innenabstand mit hoeherer Spezifitaet + !important. Die eigenen Polster/Zeilenhoehen
   gelten nur ohne Leisten-Familie — ist sie aktiv, uebernimmt ihre spaeter emittierte Zentrierung
   (padding 0 + line-height calc), dann traegt allein das Token die Groesse. */
body.v2 #stickyfooter a#initorder_layout, body.v2 #stickyfooter a#initorder_amazon { --tp-sticky-btn-h: 54px; padding-top: 12px; padding-bottom: 12px; line-height: 1.3; font-weight: 600; }
body.v2 #stickyfooter a#initorder_layout.btn, body.v2 #stickyfooter a#initorder_amazon.btn { font-size: 17px !important; padding-left: 28px !important; padding-right: 28px !important; }

/* — buttons.gewicht = "halbfett" — */
body.v2 .btn { font-weight: 600; }
/* L3c: Die Serie klemmt den Kaufen-Knopf per hoeherer Spezifitaet auf halbfett
   (body.v2 .price_quantity_box .show_button .btn { font-weight: 600 }) — ohne die folgende Zeile
   wirkte die Schriftstaerke am wichtigsten Knopf nie (L1c). M-K6: dito Kaufleiste (Serie 600 via
   #stickyfooter #stickyfooter-inner .btn). */
body.v2 .price_quantity_box .show_button .btn, body.v2 .price_quantity_box_inline .show_button .btn { font-weight: 600; }
body.v2 #stickyfooter #stickyfooter-inner .btn { font-weight: 600; }

/* — buttons.hover-effekt = "abdunkeln" — */
body.v2 .btn { transition: filter var(--tp-transition-base, 150ms ease); }
body.v2 .btn:hover:not([disabled]):not(.disabled), body.v2 .btn:focus-visible { filter: brightness(0.92); }
body.v2 .btn:active:not([disabled]):not(.disabled) { filter: brightness(0.85); }

/* — buttons.deaktivierte-optik = "graustufen" — */
body.v2 .btn[disabled], body.v2 .btn.disabled { filter: grayscale(1); opacity: 0.6; cursor: not-allowed; box-shadow: none; }

/* — buttons.mobil-volle-breite = true — */
@media (max-width: 767px) {
body.v2 .add-button, body.v2 a.remove-button, body.v2 .btn-continue:not(#initorder_layout):not(#button_coupon):not(#button_cross_out), body.v2 .jumbotron .btn-box .btn { width: 100%; margin-left: 0; margin-right: 0; }
body.v2 .jumbotron .btn-box .btn + .btn { margin-top: 8px; }
/* Z10-F9 (Runde Z10): Vollbreite Knoepfe stapeln — aber der Abstandsarm galt nur fuer
   .jumbotron .btn-box. In der Listenansicht des Veranstalters stiessen "Info" und
   "Tickets" dadurch mit 0 px aneinander (@375, 4 Eintraege). Nackt liegen sie in EINER
   Zeile mit 3,2 px Abstand; sobald wir stapeln, braucht es den Abstand. */
body.v2 .btn + .btn-continue:not(#initorder_layout):not(#button_coupon):not(#button_cross_out) { margin-top: 8px; }
}

/* — buttons.fokus-ring = true — */
/* L3c: Einen 2px-Fokus-Ring liefern die Button-Basisfeatures bereits als Pflicht-State-Set (SCHEMA Regel 2) —
   diese Option war damit pixelidentisch (L1c: totes Kapital). Jetzt verstaerkt sie den Ring sichtbar. */
body.v2 .btn:focus-visible { outline: 3px solid var(--tp-color-primary, #ff4d06) !important; outline-offset: 3px !important; box-shadow: 0 0 0 6px color-mix(in srgb, var(--tp-color-primary, #ff4d06) 25%, transparent) !important; }
body.v2 .btn:focus:not(:focus-visible) { outline: none; }

/* ============ Formulare & Eingaben ============ */
/* — forms.ecken = 8 — */
body.v2 .form-control:not(.show_quantity_select) { border-radius: var(--tp-radius-input, 4px); }
body.v2 .input-group .form-control:not(:first-child):not(:last-child) { border-radius: 0; }
body.v2 .input-group .form-control:first-child { border-radius: var(--tp-radius-input, 4px) 0 0 var(--tp-radius-input, 4px); }
body.v2 .input-group .form-control:last-child { border-radius: 0 var(--tp-radius-input, 4px) var(--tp-radius-input, 4px) 0; }
body.v2 .input-group .input-group-addon:first-child { border-radius: var(--tp-radius-input, 4px) 0 0 var(--tp-radius-input, 4px); }
body.v2 .input-group .input-group-addon:last-child { border-radius: 0 var(--tp-radius-input, 4px) var(--tp-radius-input, 4px) 0; }
body.v2 .input-group .input-group-btn:first-child > .btn { border-radius: var(--tp-radius-input, 4px) 0 0 var(--tp-radius-input, 4px); }
body.v2 .input-group .input-group-btn:last-child > .btn { border-radius: 0 var(--tp-radius-input, 4px) var(--tp-radius-input, 4px) 0; }
@media (max-width: 768px) {
  body.v2 .input-group.input-split .form-control:first-child, body.v2 .input-group.input-split.input-group-lg .form-control:first-child { border-radius: var(--tp-radius-input, 4px) !important; }
  body.v2 .input-group.input-split .input-group-btn .btn, body.v2 .input-group.input-split.input-group-lg .input-group-btn .btn { border-radius: var(--tp-radius-input, 4px) !important; }
}

/* — forms.groesse = "gross" — */
body.v2 .form-control:not(.show_quantity_select):not(#redeem_coupon):not(#redeem_cross_out_coupon) { height: auto; min-height: 44px; padding: 10px 14px; font-size: 16px; }

/* — forms.platzhalter = "gut-lesbar" — */
body.v2 .form-control::placeholder { color: inherit; opacity: 0.82; }

/* — forms.label-stil = "kraeftig" — */
/* J2-F (Runde J, Durchgang 2, RUBRIC 4 "Konsistenz"): Der Grundshop schreibt die Beschriftungen
   im Widerrufs-Dialog als blankes <label> in einer .form-group — OHNE die Klasse .control-label
   (geprueft in allen fuenf Spiegeln und in harness/fixtures/modal.html). Die Option traf deshalb
   nur den Checkout: "VORNAME *" dort, "Vorname *" im Dialog derselben Vorlage. */
body.v2 label.control-label, body.v2 .form-group > label:not(.control-label) { font-weight: 600; }

/* — forms.pflicht-sternchen = "rot" — */
body.v2 label .asterisk, body.v2 span.asterisk { color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 62%, currentColor); }
/* Im Fehlerzustand traegt das Label bereits den Fehlerton — erneutes Mischen darauf ergaebe einen ZWEITEN, helleren Rotton (D6-Restfall). Dort nur erben. */
body.v2 .has-error label .asterisk, body.v2 .bs-callout.bs-callout-danger .asterisk { color: inherit; }

/* — forms.abstaende = "kompakt" — */
body.v2 .form-group { margin-bottom: 10px; }

/* — forms.hinweis-texte = "dezent" — */
body.v2 .help-block { font-size: 12px; opacity: 0.75; }
body.v2 .has-error .help-block { opacity: 1; }

/* — forms.fehler-optik = "kraeftig" — */
/* D6-Restfall (Muster A1 "Serien-CSS ueberlebt"): Bootstrap faerbt die HUELLE der Checkbox-/Consent-Bloecke rot (.has-error .checkbox, .has-error .radio { color: #a94442 }). Jede Textmischung mit currentColor rechnet dann Rot auf Rot und erzeugt einen ZWEITEN, helleren Rotton (gemessen 3,18-4,39:1, unter AA). Darum die Huelle zuerst an die Flaechenfarbe zurueckbinden — danach gibt es nur noch EINEN Fehlerton. */
body.v2 .has-error .checkbox, body.v2 .has-error .radio, body.v2 .has-error .checkbox-inline, body.v2 .has-error .radio-inline { color: inherit; }
body.v2 .has-error .form-control:not(.show_quantity_select), body.v2 .has-error .form-control:not(.show_quantity_select):focus { border-color: var(--tp-color-form-error, #e5484d); background-color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 7%, transparent); box-shadow: none; }
/* Fehlertexte: Rahmen/Flaechen duerfen den vollen Rotton tragen, TEXT nicht — der volle Ton erreicht auf hellen Flaechen nur ~3,5-4,0:1. Die Mischung mit currentColor koppelt den Ton an die Flaechenfarbe (hell wie dunkel) und haelt AA — und zwar IMMER, auch wenn im Farb-Bereich eine eigene Fehlerfarbe gesetzt ist. */
body.v2 .has-error .control-label, body.v2 .has-error .help-block, body.v2 .has-error .checkbox label, body.v2 .has-error .radio label { color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 62%, currentColor); font-weight: 600; }
/* Zustimmungs-Kasten: Ton EINMAL am Kasten setzen, alles darin erbt ihn (sonst mischen Link/Sternchen ein zweites Mal). */
body.v2 .bs-callout.bs-callout-danger { color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 62%, currentColor); }
body.v2 .bs-callout.bs-callout-danger label, body.v2 .bs-callout.bs-callout-danger label span, body.v2 .bs-callout.bs-callout-danger .asterisk, body.v2 .bs-callout.bs-callout-danger a, body.v2 .bs-callout.bs-callout-danger h4 { color: inherit; }
body.v2 .bs-callout.bs-callout-danger a { text-decoration: underline; }

/* — forms.select-pfeil = true — */
/* V-S9 (Runde V, Organizer-Sortierleiste): Die Reserve fuer den eigenen Chevron lag bei 34 px,
   der nackte Shop braucht 12 px. In 10 von 12 Vorlagen reichte der Platz der Sortier-Beschriftung
   damit nicht mehr (pastell-soft -35,6 px), und ein select meldet seinen Ueberlauf NICHT
   (scrollWidth == clientWidth) — es fiel keiner Kappungsmessung auf, nur dem Auge:
   Beginn der Veranstaltun ... das g lag unter dem Pfeil, ohne Auslassungszeichen.
   Darum 26 px Reserve (Chevron 9-21 px, 5 px Luft) UND text-overflow: ellipsis, damit ein Rest
   sichtbar abgeschnitten statt stumm abgehackt wird. */
/* W-4 (Runde W): .daterangepicker select traegt im Markup KEIN .form-control
   (Markup: select class=monthselect) und blieb darum in 12 von 12 ein natives Widget
   (appearance: auto) — direkt neben der Sortier-Auswahl DERSELBEN Filterzeile, die
   appearance: none hat. Damit griff auch die option-Regel nicht: auf dunklen Vorlagen
   steht helle Schrift auf der hellen Systemliste, genau der Fall, den diese Option
   verhindern soll. Der Datumswaehler haengt am body, also AUSSERHALB #content — eine
   auf #content gescopte Regel ginge dort ins Leere. */
body.v2 select.form-control.form-control:not(#redeem_coupon):not(#redeem_cross_out_coupon), body.v2 .daterangepicker select { -webkit-appearance: none; -moz-appearance: none; appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath fill='%23666666' d='M1.41 0.59 6 5.17 10.59 0.59 12 2 6 8 0 2z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 9px center; background-size: 12px 8px; padding-right: 26px; text-overflow: ellipsis; color-scheme: light; }
body.v2 select.form-control option, body.v2 .daterangepicker select option { background-color: #ffffff; color: #333333; }
/* Geometrie der drp-Selects: sie sind nur 20-23 px hoch und 58/81 px breit. Die 26 px
   Reserve der grossen Auswahl wuerde dort ein Viertel der Textflaeche fressen (gemessen:
   laengster Monatsname 58-69 px bei 80 px Innenbreite). Das native Widget reserviert
   ~14 px — genau so viel bekommt der eigene Chevron hier auch, damit er nicht auf dem
   Text klebt und die Beschriftung nicht schmaler wird als vorher. */
body.v2 .daterangepicker select { background-position: right 3px center; background-size: 9px 6px; padding-right: 14px; }

/* — forms.checkbox-akzent = true — */
/* G-C1 (Runde G, Rubrik 4/6/8): accent-color allein faerbt nur den ANGEHAKTEN Zustand. Der leere
   Zustand blieb ein Browser-Kaestchen — auf dunklen Karten eine weisse Vollflaeche, die wie
   "bereits angehakt" liest, und beim Radio eine weisse Vollscheibe, die lauter war als die
   tatsaechlich gewaehlte Option (festival-dark, neon-nacht, stadion-energie). Darum ein eigenes
   Steuerelement — bewusst nur innerhalb #content, damit Bezahl-Widgets unberuehrt bleiben. */
body.v2 #content input[type="checkbox"], body.v2 #content input[type="radio"] { -webkit-appearance: none; appearance: none; box-sizing: border-box; width: 18px; height: 18px; min-width: 18px; padding: 0; position: relative; display: inline-block; vertical-align: -3px; cursor: pointer; background-color: color-mix(in srgb, currentColor 8%, transparent); border: 2px solid color-mix(in srgb, currentColor 45%, transparent); border-radius: 4px; transition: background-color .12s ease, border-color .12s ease; }
body.v2 #content input[type="radio"] { border-radius: 50%; }
body.v2 #content input[type="checkbox"]:hover:not(:disabled), body.v2 #content input[type="radio"]:hover:not(:disabled) { border-color: var(--tp-color-primary, #ff4d06); }
body.v2 #content input[type="checkbox"]:checked, body.v2 #content input[type="radio"]:checked { background-color: var(--tp-color-primary, #ff4d06); border-color: var(--tp-color-primary, #ff4d06); }
body.v2 #content input[type="checkbox"]:checked::after { content: ""; position: absolute; left: 4px; top: 0px; width: 5px; height: 10px; border: solid var(--tp-color-primary-contrast, #ffffff); border-width: 0 2px 2px 0; transform: rotate(45deg); }
body.v2 #content input[type="radio"]:checked::after { content: ""; position: absolute; inset: 2px; border-radius: 50%; background: var(--tp-color-primary-contrast, #ffffff); }
body.v2 #content input[type="checkbox"]:focus-visible, body.v2 #content input[type="radio"]:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }
body.v2 #content input[type="checkbox"]:disabled, body.v2 #content input[type="radio"]:disabled { opacity: .5; cursor: not-allowed; }
/* Bootstrap zieht Consent-Kaestchen mit margin-left:-20px in den Textrand; das groessere Ziel braucht 2px mehr. */
body.v2 #content .checkbox input[type="checkbox"], body.v2 #content .radio input[type="radio"] { margin-left: -22px; margin-top: 1px; }
/* I-14 (Runde I, Rubrik 1): Das Kaestchen stand ohne Abstand am Text der Einwilligungszeile. */
body.v2 #content input[type="checkbox"], body.v2 #content input[type="radio"] { margin-right: .5em; }

/* — forms.consent-boxen = "karte" — */
/* Fehlerzustand der Zustimmungs-Kaesten — EIN Rotton, unabhaengig vom gewaehlten Stil.
   D6-Restfall (Muster A1 "Serien-CSS ueberlebt"): Bootstrap faerbt die HUELLE rot
   (.has-error .checkbox, .has-error .radio { color: #a94442 }). Wird der Fehlertext dann mit
   currentColor gemischt, mischt sich Rot auf Rot — es entsteht ein ZWEITER, hellerer Rotton
   (gemessen 3,18-4,39:1 auf Label/Span/Sternchen, der Link mischte sogar ein drittes Mal).
   Darum: Huelle zuruecksetzen, Ton EINMAL am Kasten setzen, alles darin erbt ihn. */
body.v2 .has-error .checkbox, body.v2 .has-error .radio, body.v2 .has-error .checkbox-inline, body.v2 .has-error .radio-inline { color: inherit; }
body.v2 .bs-callout.bs-callout-danger { color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 62%, currentColor); }
body.v2 .bs-callout.bs-callout-danger label, body.v2 .bs-callout.bs-callout-danger label span, body.v2 .bs-callout.bs-callout-danger .asterisk, body.v2 .bs-callout.bs-callout-danger a, body.v2 .bs-callout.bs-callout-danger h4 { color: inherit; }
body.v2 .bs-callout.bs-callout-danger a { text-decoration: underline; }
body.v2 .bs-callout { background-color: rgba(128,128,128,0.06); border: 1px solid var(--tp-color-border, rgba(128,128,128,0.25)); border-radius: var(--tp-radius-panel, 6px); padding: 14px 16px; }
body.v2 .bs-callout.bs-callout-danger { border-color: var(--tp-color-form-error, #e5484d); background-color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 8%, transparent); }

/* — forms.telefonfeld = true — */
body.v2 .form-group .iti { display: block; width: 100%; }
body.v2 .iti input.form-control { width: 100%; }

/* ============ Ticketauswahl & Kasse ============ */
/* — checkout.section-cards = true — */
body.v2 #ticketchoose .well, body.v2 #customerdata .well, body.v2 #paymentchoose .well, body.v2 #deliverychoose .well, body.v2 .order_questions .well, body.v2 .well.well-minheight { border-radius: var(--tp-radius-panel, 10px); box-shadow: var(--tp-shadow-panel, 0 2px 12px rgba(0,0,0,.08)); }

/* — checkout.article-rows = "linien" — */
/* BK1 Betrags-Schutz — Betraege duerfen nie zwischen Zahl und Waehrungszeichen umbrechen ("129,00" / "EUR" auf zwei Zeilen).
   V-7/V-8 (Runde V, Organizer): Die tbody-Zellenregeln hingen frueher an nacktem table.table und trafen damit
   die Tabelle des Zabuto-Monatskalenders (fixture/organizer-calendar) — Zelle 45,8 -> 57,8 px, Monatstabelle
   316,9 -> 376,9 px, mobil schrumpfte die Sonntagsspalte auf 13 px. Sie sind jetzt positiv an die
   Bestelltabelle gebunden. KORR-kasse (Gegenpruefung G-1): der Anker dafuer ist NICHT tbody#cart_items.
   order/_cart.haml:19/67 legt #cart_items und #cart_footer als DIV *innerhalb* %tbody an; der HTML-Parser
   wirft sie per foster parenting als leere Geschwister VOR die Tabelle (Live-Abzug research/portal/dom/
   w_shop-ticketpay-de-addons-…__i5_0-00-0-.html: div#cart_items + div#cart_footer, danach table.table mit
   thead und EINEM tbody ohne id). tbody#… traf im Browser 0 Elemente — die ganze Familie war auf der
   echten Kasse tot (12/12 Vorlagen deckungsgleich mit der Nullprobe). Anker ist deshalb der Marker-DIV
   als vorangehendes Geschwister: #cart_items ~ table.table > tbody. Er kommt aus der Partial selbst und
   gilt damit in JEDEM Behaelter (#cart, #cartfooter, Warenkorb-Modal, reservedshop), trifft den Kalender
   nicht (gemessen 0 auf fixture/organizer-calendar) und haelt die Spezifitaet des alten Ankers (1,1,4)
   exakt — damit gilt das in FIX-checkout §3 austarierte Duell unveraendert weiter.
   Die thead-Haelfte traegt denselben Anker (KORR-kasse, Nachzug Runde V): unverankert traf sie auf
   fixture/sponsors-list 6 Kopfzellen der Sponsoren-Tabelle (gemessen) — Grossbuchstaben/12px/Akzent-Linie
   ueber einem Tabellenkoerper, den die verankerte tbody-Haelfte gar nicht mehr anfasst. Der Zabuto-Kalender
   hat gar kein thead: seine Wochentagskoepfe liegen als tr.calendar-dow-header IM tbody (gemessen 0 Treffer).
   .text-right- und tr.finaltotal-Selektoren bleiben frei — der Kalender hat diese Klassen nicht (gemessen),
   und in sponsors-list sitzt das einzige text-right auf einem DIV, nicht auf einer Zelle.
   Bewusst an mehrere haeufig gesetzte Kassen-Features gekoppelt (gleiches Muster wie die Icon-Zentrierung in fonts.json),
   damit der Schutz nicht allein an checkout.order-table haengt. Wird nur bei gesetztem Feature emittiert -> Nullprobe bleibt 0 %. */
body.v2 table.table td.text-right, body.v2 table.table th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child, body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td, body.v2 #total_amount, body.v2 #payment_fee_amount, body.v2 .subtotal .value { white-space: nowrap; }
@media (max-width: 480px) {
  body.v2 #cart_items ~ table.table > thead > tr > th, body.v2 #cart_items ~ table.table > tbody > tr > td { padding-left: 5px; padding-right: 5px; }
  body.v2 #cart_items ~ table.table > thead > tr > th:first-child, body.v2 #cart_items ~ table.table > tbody > tr > td:first-child { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: anywhere; }
  body.v2 #cart_items ~ table.table > thead > tr > th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child { font-size: 13px; }
  body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { font-size: 14px; }
}
/* M-F12 (Runde M, CEO BILD-13, Regel 15 "Serien-Bauformen" + L1c-F.5): Die Varianten-Kaufbox der
   Zusatzartikel-Seite ist KEINE #quantity_box-Bauform: .input-group > .input-group-addon > .show_price
   + Select, Inline-Breiten 195/120/75 px, kein .article-box-Wrapper. Die Serien-Addons (Tabellen-Layout,
   #eee-Flaeche, #ccc-Rahmen, 6x12-Padding) blieben von allen Kaufbox-Regeln unberuehrt: der Preis klebte
   als grauer Kasten am Select (gemessen: Addon table-cell, bg rgb(238,238,238), Border 1px rgb(204,204,204)).
   Fix: Addons zu ruhigen Flex-Zellen aufloesen (Flaeche/Rahmen/Padding weg); !important NUR gegen die
   Inline-Breiten (75/120 px — "15,00 EUR" misst bei price-style gross bereits exakt 75 px, groessere Preise
   wuerden beschnitten). J4-A-Vorsicht beachtet: kein width:1%-Wrapper wird geklemmt — der 195px-Wrapper
   [id^="quantity_box_"] behaelt seine Serien-Breite, nur die INNEREN Zellen messen wieder ihren Inhalt;
   Scope .price_quantity_box laesst die Gutschein-input-groups (J1-5/J4-A) unberuehrt. */
body.v2 .price_quantity_box .input-group { display: flex; align-items: center; gap: 8px 12px; width: 100%; }
body.v2 .price_quantity_box .input-group > .input-group-addon { display: block; width: auto !important; padding: 0; background-color: transparent; background-image: none; border: 0; border-radius: 0; box-shadow: none; white-space: normal; }
body.v2 .price_quantity_box .input-group > .input-group-addon > .show_price { width: auto !important; margin: 0; }
body.v2 .price_quantity_box .input-group > .input-group-addon:last-child { flex: 1 1 auto; min-width: 0; margin-left: auto; }
body.v2 .price_quantity_box .input-group > .input-group-addon .form-control { width: 100%; float: none; }
/* M-F13 (Runde M, CEO BILD-13): Der Auf-/Zuklapp-Link der Varianten (a.pull-right[onclick=openVariant]
   OHNE href) wird von keiner Link-Farbregel des Katalogs erreicht (alle erwarten a.color bzw. Cover/
   Footer-Zonen) und blieb Serien-Blau #337ab7 — in jeder Palette ein Fremdkoerper. Palette statt
   Serienblau (Akzent -> Hauptfarbe -> Serienblau als ehrlicher Fallback, damit ohne Farbwahl nichts
   umkippt); Hover/Fokus-Feedback wird mitgeliefert, weil die Serien-a:hover-Regel gegen die hoehere
   Spezifitaet hier verliert (Rubrik 6 / Regel 2 State-Set). */
body.v2 .items a[onclick^="openVariant"], body.v2 .items a[onclick^="closeVariant"] { color: var(--tp-color-accent, var(--tp-color-primary, #337ab7)); font-weight: 600; cursor: pointer; }
body.v2 .items a[onclick^="openVariant"]:hover, body.v2 .items a[onclick^="closeVariant"]:hover, body.v2 .items a[onclick^="openVariant"]:focus-visible, body.v2 .items a[onclick^="closeVariant"]:focus-visible, body.v2 .items a[onclick^="openVariant"]:active, body.v2 .items a[onclick^="closeVariant"]:active { text-decoration: underline; }
/* Z14-ALL-2 (Runde Z14, CEO-DOCX 2026-08-15, Bild media/776a3005: "diese sind immer unterschiedlich
   lang, was unruhig wirkt, bitte gleiche sie an"): Die Zeilenlinie sass als border-bottom auf der
   Bootstrap-.row und war damit 30 px LAENGER als die Karte selbst (.row traegt margin-left/right -15px).
   Gemessen @1280 shop-artikel: Kartenlinie 1072-1116 px gegen Zeilenlinie 1102-1146 px, mit der
   Wrapper-Kante drei Laengen in 8 Vorlagen (Spanne 64-68), nackt nur zwei (38). Jetzt 1-px-Verlauf im
   Hintergrund, um die Negativmarge eingerueckt — Ende bitgenau an der Kartenkante. Pseudoelement-Route
   AUSGESCHLOSSEN (::before/::after tragen den Bootstrap-3-Clearfix, gemessen); .row hat background-image
   none, background-color transparent, position static, und nur die zwei Regeln dieses Merkmals treffen
   .items > .row. Farbe und Stil bleiben verschieden ("das ist auch gut so"), nur die LAENGE wird gleich.
   Die 769-px-Grenze ist GEMESSEN, nicht gewaehlt: bis 768 px gibt die Serie .items 15 px Polster, das die
   Negativmarge der .row genau aufhebt — dort liegt die Linie schon buendig, ein Einzug waere ein NEUER
   Versatz (gemessen 768: Polster 15, 769: Polster 0). Der Rahmen bleibt darum unten sichtbar und oben nur
   FARBLOS statt entfernt: so bleibt seine 1-px-Hoehe erhalten und keine Karte wird kuerzer. */
body.v2 .wrap .items > .row { padding-top: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--tp-color-border, rgba(128,128,128,.25)); } body.v2 .wrap .items > .row:last-child { border-bottom: 0; }
@media (min-width: 769px) {
  body.v2 .wrap .items > .row { border-bottom-color: transparent; background-image: linear-gradient(to right, var(--tp-color-border, rgba(128,128,128,.25)), var(--tp-color-border, rgba(128,128,128,.25))); background-repeat: no-repeat; background-position: 15px 100%; background-size: calc(100% - 30px) 1px; }
  body.v2 .wrap .items > .row:last-child { background-image: none; }
} body.v2 .wrap .items hr.less-margin { display: none; } body.v2 .price_quantity_box .show_quantity, body.v2 .price_quantity_box .show_button { box-shadow: none; border-top: 0; border-bottom: 0; background-color: transparent; background-image: none; } body.v2 .price_quantity_box select.show_quantity_select, body.v2 .price_quantity_box .show_button .btn { height: auto; min-height: var(--tp-control-height, 42px); } body.v2 .price_quantity_box select.show_quantity_select { min-width: 5.5em; border-radius: var(--tp-radius-button, var(--tp-radius-input, 6px)); text-align: center; text-align-last: center; } body.v2 .price_quantity_box .show_button .btn { display: flex; align-items: center; justify-content: center; gap: .45em; border-radius: var(--tp-radius-button, var(--tp-radius-input, 6px)); }
/* M-F2 (Runde M, CEO BILD-1, Muster A6 "optische Mitte"): Im Flex-CTA ist gap die einzige Abstandsquelle. fa-fw (feste Breite, Glyphe zentriert = unsichtbarer Leerraum links) und das I-13-margin-right aus buttons.form wuerden die sichtbare Gruppe sonst nach rechts schieben — links vom Pfeil mehr Luft als rechts vom Text. width:auto laesst das Icon auf Glyphenbreite schrumpfen. */
body.v2 .price_quantity_box .show_button .btn > i.fa { width: auto; margin-right: 0; }
/* M-F7 (Runde M, CEO BILD-8/9, Regel 15-Familie "Serien-Bauformen"): Auf der Zusatzartikel-Seite liegt die Artikelzeile als .items > .variant > .row — nicht als direktes .row-Kind. Ohne diese Regel beginnt die Kaufbox buendig an der Trennlinie der Kopfzeile. */ body.v2 .wrap .items .variant > .row { padding-top: 14px; padding-bottom: 14px; }

/* — checkout.kaufbox-layout = "menge-rechts" — */
/* L3a (Runde L, CEO-Fund 1, F1 der Katalog-Forensik + PLAYBOOK "Schleichende Vereinheitlichung"):
   Layout-Charakter der Kaufbox ist eine OPTION, kein Zwang aus buybox-kompakt mehr. Jede Variante ist
   selbsttragend (funktioniert mit und ohne kompakte Kaufzeile). Select-Regeln bewusst OHNE .article-box
   (0,3,2), damit die spaeter emittierten Mengenfeld-Optionen (quantity-select, ebenfalls 0,3,2) per
   Reihenfolge gewinnen; Container-Regeln MIT .article-box, damit sie die frueher emittierte Basis von
   buybox-kompakt ueberstimmen. Bereinigungs-Block wie in article-rows/buybox (im Hint angekuendigt). */
body.v2 .price_quantity_box .show_quantity, body.v2 .price_quantity_box .show_button { box-shadow: none; border-top: 0; border-bottom: 0; background-color: transparent; background-image: none; }
body.v2 .price_quantity_box select.show_quantity_select, body.v2 .price_quantity_box .show_button .btn { height: auto; min-height: var(--tp-control-height, 42px); }
body.v2 .price_quantity_box select.show_quantity_select { min-width: 5.5em; max-width: 100%; border-radius: var(--tp-radius-button, var(--tp-radius-input, 6px)); text-align: center; text-align-last: center; }
body.v2 .price_quantity_box .show_button .btn { display: flex; align-items: center; justify-content: center; gap: .45em; border-radius: var(--tp-radius-button, var(--tp-radius-input, 6px)); }
/* M-F2 (Runde M, CEO BILD-1, Muster A6 "optische Mitte"): Im Flex-CTA ist gap die einzige Abstandsquelle. fa-fw (feste Breite, Glyphe zentriert = unsichtbarer Leerraum links) und das I-13-margin-right aus buttons.form wuerden die sichtbare Gruppe sonst nach rechts schieben — links vom Pfeil mehr Luft als rechts vom Text. width:auto laesst das Icon auf Glyphenbreite schrumpfen. */
body.v2 .price_quantity_box .show_button .btn > i.fa { width: auto; margin-right: 0; }
/* G-S1 (Runde G, Rubrik 2): .price_quantity_box ist hier ein Flex-Container. Flex-Kinder haben
   min-width:auto und werden daher so breit wie ihr Inhalt — "NUR NOCH 4 STUECK VERFUEGBAR" ragte
   dadurch 5-30px aus der Kaufbox (festival-dark, mono-kontrast, minimal-brand) und schob den
   Mengen-Select mit heraus; bei 768px erzeugte das 2px horizontales Scrollen. */
body.v2 .price_quantity_box > * { min-width: 0; max-width: 100%; }
/* Z14-F2-B3 (Runde Z14-F2, HOCH, KERN 12 von 12; NEBENWIRKUNG von Z14-MU-1/Z14-F-B1, gegen sechs
   eingefrorene Staende datiert): Z14-F-B1 hat die Kaufbox mit width:100% zustandsfrei gemacht —
   richtig, aber die Serie gibt derselben .price_quantity_box ein min-width: 195px (computed
   belegt). Zwischen 768 und 1199 px ist die Kaufspalte SCHMALER als diese 195 px; der Kasten
   konnte nicht mitschrumpfen, und weil karteOverflow visible ist, wurde die weisse Select-Pille
   voll AUSSERHALB der Artikelkarte auf den Seitengrund gemalt. Nicht die Feldregel war schuld,
   sondern die BEZUGSGROESSE — width:100% entkoppelt nur nach oben, nicht nach unten.
   Gemessen (scratchpad/z14f2c1/b3-mess.js, 1 320 gueltige Zellen: 12 Vorlagen x
   {shop-artikel, stock-states, cover-image, cart-filled} x {375, 768, 900, 992, 1024, 1100, 1199,
   1200, 1280, 1440, 1600}; Nullrechtecke eingeklappter Kaesten verworfen, Ueberstand gegen die
   KARTENKANTE): VOR 350 Zellen mit Ueberstand — bei 768 px ALLE ZWOELF (15,0-25,7 px rechts
   heraus), bei 900-1199 px zusaetzlich die fuenf menge-unter-Vorlagen links heraus (pastell-soft
   24,5 / minimal-brand 10,5 / elegant-serif 9,0 / tech-minimal 2,5 / sport-clean 2,0 px).
   Bei 375, 1200, 1280, 1440 und 1600 px war alles korrekt — deshalb hat die Pruefkette es nie
   gesehen. Der nackte Shop hat dort 0 Ueberstand: wir waren schlechter als die Serie.
   NACH: 0 Ueberstand in allen 1 320 Zellen und allen elf Breiten; auch der Kaufknopf, der VOR in
   780 von 1 584 Zellen bis zu 25,7 px aus der Karte ragte, liegt jetzt vollstaendig darin.
   Die Regel steht auf FEATURE-Ebene, nicht im Arm menge-unter: die 195-px-Untergrenze der Serie
   sprengt die Karte in JEDEM Arm (Facette 768 px = 7 menge-rechts-Vorlagen), Kernregel 3.
   Gegengemessen und unveraendert: Zustandsprobe Z14-F-B1 dW = dX = 0,0 in 1 980 Zellen (beide
   Kaufbox-Zustaende); die MU-1-Sollwerte @1280 bitgleich (elegant-serif 222 / minimal-brand 218,5 /
   pastell-soft 206,5 / sport-clean 229 / tech-minimal 228,5); Z14-ALL-1 dSelCta 0,0 in allen
   Breiten ab 768; die Variantenzeile der Zusatzartikel (Z14-N3, 528 Vergleiche) und die
   Gutschein-input-group (J1-5/J4-A, 396 Vergleiche) pixelgleich; kein Querscrollen.
   Bildbeleg Originalgroesse + 2x-Lupe: scratchpad/z14f2c1/shots/b3VOR bzw. b3kB / b3kD. */
body.v2 .article-box .price_quantity_box { min-width: 0; max-width: 100%; }
/* Z14-F2-B3 Teil B (Regel 20: vor der Notbremse gibt die nachgebende Groesse nach; Goldene Regel 9:
   ein Fix darf keinen Defekt gegen einen anderen tauschen): Sobald die Kaufbox in die Karte
   zurueckgeholt ist, ist die Kaufspalte im md-Band nur noch ~160-180 px breit. Mit dem bis dahin
   geltenden Innenpolster von 12 px und dem viewport-gekoppelten Schriftgrad (Z14-ALL-1,
   clamp(13.5px, 0.55vw + 9.2px, 16px) — bei 992 px sind das 14,66 px) brach der Haupt-CTA in 43
   von 84 Band-Zellen zweizeilig um: der Pfeil stand dann allein links neben zwei Textzeilen
   (pastell-soft 44,8 -> 67,7 px Knopfhoehe, die uebrigen 42 -> 52,6-59,1 px). Das ist zwar von
   J1-2 als Notbremse erlaubt ("darf umbrechen, aber nie ueberlaufen") — der einzeilige Zustand,
   den Z14-MU-1 fuer die 5 menge-unter-Vorlagen ausdruecklich als Gewinn verbucht hat, war aber in
   Wahrheit durch den UEBERLAUF erkauft und faellt mit ihm weg. Die Klemme ist die KARTE, nicht das
   Fenster: darum gibt im Band zuerst das Polster nach (12 -> 6 px) und dann der Schriftgrad
   (13 px, unter der sonstigen clamp-Untergrenze von 13,5 px). Laufweite ist bereits normal.
   Gemessen zur Laufzeit ueber 84 Zellen (12 Vorlagen x {768, 900, 992, 1024, 1100, 1199, 1280}):
   IST 43 zweizeilig, pad8 29, pad6 25, pad4 22, pad6+13px 0. Ausserhalb des Bandes (375, 1200,
   1280, 1440, 1600) aendert sich kein Pixel — insbesondere bleiben die MU-1-Sollwerte @1280 und
   dSelCta unberuehrt, weil Polster und Schriftgrad keine Kante verschieben. Nur der Kaufbox-CTA:
   ein .article-box .show_button OHNE .price_quantity_box behaelt seine Werte (Z14-ALL-1). */
@media (min-width: 768px) and (max-width: 1199px) {
  body.v2 .article-box .price_quantity_box .show_button .btn { padding-left: 6px; padding-right: 6px; font-size: 13px; }
}
body.v2 .price_quantity_box h5, body.v2 .price_quantity_box .show_price { overflow-wrap: break-word; }
/* M-F12 (Runde M, CEO BILD-13, Regel 15 "Serien-Bauformen" + L1c-F.5): Die Varianten-Kaufbox der
   Zusatzartikel-Seite ist KEINE #quantity_box-Bauform: .input-group > .input-group-addon > .show_price
   + Select, Inline-Breiten 195/120/75 px, kein .article-box-Wrapper. Die Serien-Addons (Tabellen-Layout,
   #eee-Flaeche, #ccc-Rahmen, 6x12-Padding) blieben von allen Kaufbox-Regeln unberuehrt: der Preis klebte
   als grauer Kasten am Select (gemessen: Addon table-cell, bg rgb(238,238,238), Border 1px rgb(204,204,204)).
   Fix: Addons zu ruhigen Flex-Zellen aufloesen (Flaeche/Rahmen/Padding weg); !important NUR gegen die
   Inline-Breiten (75/120 px — "15,00 EUR" misst bei price-style gross bereits exakt 75 px, groessere Preise
   wuerden beschnitten). J4-A-Vorsicht beachtet: kein width:1%-Wrapper wird geklemmt — der 195px-Wrapper
   [id^="quantity_box_"] behaelt seine Serien-Breite, nur die INNEREN Zellen messen wieder ihren Inhalt;
   Scope .price_quantity_box laesst die Gutschein-input-groups (J1-5/J4-A) unberuehrt. */
body.v2 .price_quantity_box .input-group { display: flex; align-items: center; gap: 8px 12px; width: 100%; }
body.v2 .price_quantity_box .input-group > .input-group-addon { display: block; width: auto !important; padding: 0; background-color: transparent; background-image: none; border: 0; border-radius: 0; box-shadow: none; white-space: normal; }
body.v2 .price_quantity_box .input-group > .input-group-addon > .show_price { width: auto !important; margin: 0; }
body.v2 .price_quantity_box .input-group > .input-group-addon:last-child { flex: 1 1 auto; min-width: 0; margin-left: auto; }
body.v2 .price_quantity_box .input-group > .input-group-addon .form-control { width: 100%; float: none; }
/* M-F13 (Runde M, CEO BILD-13): Der Auf-/Zuklapp-Link der Varianten (a.pull-right[onclick=openVariant]
   OHNE href) wird von keiner Link-Farbregel des Katalogs erreicht (alle erwarten a.color bzw. Cover/
   Footer-Zonen) und blieb Serien-Blau #337ab7 — in jeder Palette ein Fremdkoerper. Palette statt
   Serienblau (Akzent -> Hauptfarbe -> Serienblau als ehrlicher Fallback, damit ohne Farbwahl nichts
   umkippt); Hover/Fokus-Feedback wird mitgeliefert, weil die Serien-a:hover-Regel gegen die hoehere
   Spezifitaet hier verliert (Rubrik 6 / Regel 2 State-Set). */
body.v2 .items a[onclick^="openVariant"], body.v2 .items a[onclick^="closeVariant"] { color: var(--tp-color-accent, var(--tp-color-primary, #337ab7)); font-weight: 600; cursor: pointer; }
body.v2 .items a[onclick^="openVariant"]:hover, body.v2 .items a[onclick^="closeVariant"]:hover, body.v2 .items a[onclick^="openVariant"]:focus-visible, body.v2 .items a[onclick^="closeVariant"]:focus-visible, body.v2 .items a[onclick^="openVariant"]:active, body.v2 .items a[onclick^="closeVariant"]:active { text-decoration: underline; }
/* MB-4 (Runde Z14, CEO-DOCX 2026-08-15, Bilder media/bac11763 + media/28336e90: "eigentlich haben wir
   sonst in allen anderen Vorlagen immer die Variante genommen wo Streichpeis und Normalpreis untereinander
   stehen, damit das Dropdown nach rechts passt"): M-F1 stand nur im Arm menge-rechts und dort in
   @media (min-width:768px). Gemessen NEBENeinander in 5 von 12 @1280 (elegant-serif, minimal-brand,
   pastell-soft, sport-clean, tech-minimal), in 12 von 12 @375 und in 12 von 12 auf fixture/stock-states —
   dort schreibt die Serie den Streichpreis als DIREKTES .show_price-Kind (<s>49,90 EUR</s> statt
   <small><s>…</small>). Jetzt gemeinsam gefuehrt (Kernregel 3), ohne Media-Query (bei 375 ist die Kaufbox
   schmaler) und mit eigenem Selektor je Schreibweise. J2-C2-Falle: das blanke <small>EUR</small> des
   Zahlpreises trifft KEINER der beiden Selektoren, sonst bricht das Eurozeichen um. menge-rechts fuehrt
   die Zeile deshalb nicht mehr doppelt. */
body.v2 .price_quantity_box .show_price small:has(s), body.v2 .price_quantity_box .show_price small:has(strike), body.v2 .price_quantity_box .show_price small:has(del) { display: block; line-height: 1.2; }
body.v2 .price_quantity_box .show_price > s, body.v2 .price_quantity_box .show_price > strike, body.v2 .price_quantity_box .show_price > del { display: block; line-height: 1.2; }
/* Identisch mit dem Verhalten der kompakten Kaufzeile (dort begruendet) — hier selbsttragend,
   damit die Wahl auch ohne buybox-kompakt gilt. */
@media (min-width: 768px) {
  body.v2 .article-box .price_quantity_box { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 12px; }
  body.v2 .article-box .price_quantity_box > .show_price { margin: 0; flex: 1 1 auto; }
  /* L3a-1 (Runde L, CEO-Fund 1; ersetzt J1-6): J1-6 gab dem Preis eine eigene Vollzeile, damit ein
     Bestandshinweis die Kaufzeile nicht kippt — und schaffte damit die Einzeiligkeit (den Charakter
     dieses Features seit Runde D) fuer ALLE Vorlagen ab. Ursache war nie der Preis: der Wrapper
     [id^=quantity_box_] wird per max-content so breit wie sein einzeiliger Hinweis-Text und draengt
     den Preis aus der Zeile. Fix an der Ursache: Der Wrapper wird mit display:contents aufgeloest —
     Mengenfeld und Hinweis werden selbst Flex-Kinder der Kaufzeile. Das Mengenfeld steht damit IMMER
     rechts neben dem Preis (unabhaengig vom Hinweis), der Hinweis bekommt eine eigene rechtsbuendige
     Zeile darunter (gemessen: _blank/D3 kippten bei Hinweis-Artikeln ebenfalls — erst dieser Aufbau
     haelt die Zeile stabil). margin/flex davor = Fallback fuer Browser ohne display:contents.
     Das Einheits-Layout der Runden I/J bleibt als kaufbox-layout=menge-unter ehrlich waehlbar
     (dort wird der Wrapper wieder display:block). */
  body.v2 .article-box .price_quantity_box > [id^="quantity_box_"] { margin: 0 0 0 auto; flex: 0 1 auto; min-width: 0; display: contents; }
  body.v2 .article-box .price_quantity_box > [id^="quantity_box_"] > .show_quantity { margin: 0 0 0 auto; padding: 0; }
  body.v2 .article-box .price_quantity_box > [id^="quantity_box_"] > h5 { flex: 1 1 100%; margin: 0; text-align: right; }
  body.v2 .article-box .price_quantity_box > .show_button { flex: 1 1 100%; margin: 0; }
  /* Z7-1 (Runde Z7, CEO-Befund 2026-08-06, an fixture/shop-artikel und live an 4INRPEAL
     gemessen): L3a-1 loest den Wrapper [id^=quantity_box_] mit display:contents auf, damit
     das Mengenfeld Flex-Kind der Kaufzeile wird. Der Kaufen-Knopf liegt im SELBEN Wrapper —
     die Vollbreiten-Regel darueber traegt aber einen Kindkombinator und erreicht nur den
     Entfernen-Knopf (#cart_buttons_*, echtes Kind). Der Kaufen-Knopf blieb damit inhaltsbreit
     und sass am Zeilenanfang: corporate-blau 68,1 % der Kaufbox bei 64,4 px Rand rechts,
     nackt sind es 88,7 % bei 11/11. Derselbe Arm eine Ebene tiefer stellt die Zusage des
     Features wieder her ("Knopf auf eigener, voller Zeile"). menge-unter und zentriert
     brauchen ihn nicht: dort bleibt der Wrapper display:block. */
  body.v2 .article-box .price_quantity_box > [id^="quantity_box_"] > .show_button { flex: 1 1 100%; margin: 0; }
  body.v2 .article-box .price_quantity_box .show_quantity { margin: 0; }
  /* L3a-4 (Runde L, CEO-Fund 4 = F4 der Katalog-Forensik): "Coming Soon" (Verkaufsstart in der
     Zukunft, 5999-Zweig) rendert die Plakette OHNE quantity_box-Wrapper direkt als .show_quantity-
     Kind der Kaufbox. Als Flex-Item schrumpfte sie auf Inhaltsbreite und sass am Flex-Start = links,
     waehrend Preis und Menge rechtsbuendig stehen. Volle Zeilenbreite stellt die Serien-Ausrichtung
     (float:right) wieder her und laesst Banderolen-Stile die Karte fuellen. Trifft NUR den
     quantity_box-losen Pfad — die normale Menge liegt in [id^=quantity_box_] > .show_quantity. */
  body.v2 .article-box .price_quantity_box > .show_quantity { flex: 1 1 100%; }
}

/* — checkout.price-style = "gross" — */
/* BK1 Betrags-Schutz — siehe checkout.article-rows. */
body.v2 table.table td.text-right, body.v2 table.table th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child, body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td, body.v2 #total_amount, body.v2 #payment_fee_amount, body.v2 .subtotal .value { white-space: nowrap; }
@media (max-width: 480px) {
  body.v2 #cart_items ~ table.table > thead > tr > th, body.v2 #cart_items ~ table.table > tbody > tr > td { padding-left: 5px; padding-right: 5px; }
  body.v2 #cart_items ~ table.table > thead > tr > th:first-child, body.v2 #cart_items ~ table.table > tbody > tr > td:first-child { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: anywhere; }
  body.v2 #cart_items ~ table.table > thead > tr > th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child { font-size: 13px; }
  body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { font-size: 14px; }
}
body.v2 .price_quantity_box .show_price { font-size: clamp(17px, 1.2vw + 12px, 22px); font-weight: 700; }
/* G-Q1 (Runde G, Rubrik 2): "Betraege nie umbrechen" galt bisher nur fuer Tabellen und Summen
   (BK1). In der Kaufbox brach der Preis in elegant-serif zwischen Zahl und Waehrungszeichen um. */
body.v2 .price_quantity_box .show_price, body.v2 .price_quantity_box .show_price font, body.v2 .price_quantity_box .show_price strike, body.v2 .price_quantity_box .show_price s { white-space: nowrap; }

/* — checkout.strike-price = "dezent" — */
/* M-K5 (Runde M, aus L1c-B): beide Serien-Schreibweisen (<small><s>… und <s>-direkt) abdecken; NIE das blanke <small>€</small> des Zahlpreises treffen (J2-C2). !important + .article-box-Stufe, damit die ausdrueckliche Wahl das spaeter emittierte Duell gegen colors.price-status gewinnt. */
body.v2 .article-box .price_quantity_box .show_price small s, body.v2 .price_quantity_box .show_price small s, body.v2 .article-box .price_quantity_box .show_price small strike, body.v2 .price_quantity_box .show_price small strike, body.v2 .article-box .price_quantity_box .show_price > s, body.v2 .price_quantity_box .show_price > s, body.v2 .article-box .price_quantity_box .show_price > strike, body.v2 .price_quantity_box .show_price > strike, body.v2 .article-box .price_quantity_box .show_price > del, body.v2 .price_quantity_box .show_price > del { opacity: .65 !important; color: inherit !important; font-weight: 400 !important; }
body.v2 .article-box .price_quantity_box .show_price small s font, body.v2 .price_quantity_box .show_price small s font, body.v2 .article-box .price_quantity_box .show_price > s font, body.v2 .price_quantity_box .show_price > s font, body.v2 .article-box .price_quantity_box .show_price > strike font, body.v2 .price_quantity_box .show_price > strike font { color: inherit !important; }
body.v2 .article-box .price_quantity_box .show_price > s, body.v2 .price_quantity_box .show_price > s, body.v2 .article-box .price_quantity_box .show_price > strike, body.v2 .price_quantity_box .show_price > strike, body.v2 .article-box .price_quantity_box .show_price > del, body.v2 .price_quantity_box .show_price > del { font-size: .85em; }

/* — checkout.quantity-select = "schmal" — */
/* L3a-3 (Runde L, CEO-Fund 3 = F3 der Katalog-Forensik; PLAYBOOK-Regel 3 "Options-Wahrhaftigkeit"):
   Dieses Feature-css lief bei jeder Optionswahl mit und gestaltete frueher auch den KAUFEN-KNOPF um
   (Flex-Zentrierung, Rundung, Mindesthoehe, Band-Reset) — die Option "schmal" veraenderte damit
   sichtbar den Knopf, obwohl sie nur das Mengenfeld meint. Alle .show_button-Anteile sind gestrichen;
   die gemeinsame Bereinigung von Mengenfeld UND Knopf liegt ehrlich angekuendigt in article-rows/
   buybox/buybox-kompakt/kaufbox-layout. Wer NUR das Mengenfeld einstellt, behaelt den Serien-Knopf
   samt grauem Band — gewollt. */
body.v2 .price_quantity_box .show_quantity { box-shadow: none; border-top: 0; border-bottom: 0; background-color: transparent; background-image: none; }
body.v2 .price_quantity_box select.show_quantity_select { height: auto; min-height: var(--tp-control-height, 42px); min-width: 5.5em; border-radius: var(--tp-radius-button, var(--tp-radius-input, 6px)); text-align: center; text-align-last: center; }
body.v2 .price_quantity_box select.show_quantity_select:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 1px; }
body.v2 .price_quantity_box select.show_quantity_select:disabled { opacity: .5; cursor: not-allowed; }
body.v2 .price_quantity_box select.show_quantity_select { max-width: 96px; margin-left: auto; }

/* — checkout.availability-style = "banderole" — */
/* L3b (Runde L, CEO-Fund 4) — Coming-Soon-Zeile links-gestrandet:
   Der 5999-/Coming-Soon-Zweig rendert .stockStatus.out in einer .show_quantity.clearfix
   DIREKT unter .price_quantity_box — ohne #quantity_box_*-Wrapper, ohne .show_button
   (_article_form.haml Z. 88-95); der Hinweis ist dort das EINZIGE Element unter dem Preis.
   Unter checkout.buybox-kompakt ist .price_quantity_box ein Flex-Container: das Kind
   schrumpfte auf Inhaltsbreite (gemessen 141 von 225 px) und sass am Flex-Start = LINKS,
   waehrend der Preis rechtsbuendig darueber steht (L-katalog-forensik Abschnitt 4).
   Die Zeile spannt jetzt in JEDER Bauform dieses Features die volle Kaufbox-Breite; die
   Ausrichtung des Hinweises folgt der Kaufbox (--tp-kaufbox-align, Standard rechts wie
   Serie und Preis) — nie mehr links als einziges Element. .clearfix grenzt vom
   Spenden-Zweig ab (.show_quantity.clearfix_donation, _article_form.haml Z. 50); die
   normale Menge liegt unter #quantity_box_* und bleibt unberuehrt. Nur bei gesetzter
   Option emittiert -> Nullprobe bleibt 0 %. */
body.v2 .article-box .price_quantity_box > .show_quantity.clearfix { float: none; flex: 1 1 100%; width: 100%; max-width: 100%; text-align: var(--tp-kaufbox-align, right); }
/* Plakette in Serien-Tiefe (0,9,1): float:right der Serie (base Z. 11899) und
   margin-left:auto aus colors.price-status weichen INNERHALB dieser Zeile der
   text-align-Steuerung der Kaufbox. Nur ab Tablet — unter 769px zentriert die Serie
   selbst (base Z. 12219) bzw. der J-2-Block der gewaehlten Option. */
@media (min-width: 769px) {
  body.v2 .wrap .wrap_content .well .items .price_quantity_box > .show_quantity.clearfix > .stockStatus { float: none; display: inline-block; width: -moz-fit-content; width: fit-content; max-width: 100%; margin-left: 0; margin-right: 0; }
}
/* W2-G1 (Runde W2): Die Flaeche des Streifens stand bis hierher in der Grundregel (0,4,1)
   und landete damit in KEINER Konfiguration — weder mit noch ohne colors.price-status:
   die Serie setzt .stockStatus-Flaeche und -Polsterung auf 0,6,1, price-status zusaetzlich
   mit !important (gemessen: Isolat ohne Farboption zeigt fuer .out/.tempout weiter das
   Serien-Grau, nie die hier frueher deklarierten Volltonfarben; padding blieb 3px 6px).
   Die Flaeche liegt jetzt in einer EIGENEN Regel in beiden Tiefen-Bloecken unten — getrennt
   von der Bauform, damit sie nur die Arme trifft, die den Streifen meinen (W3-G1).
   Die POLSTERUNG ist Bauform des Streifens: sie trifft jeden Zustand, den die Option zum
   Streifen macht, an beiden Seiten des Breakpoints gleich — und keine Farbe.
   Die FARBE bleibt beim Farben-Panel: der Streifen mischt currentColor — und currentColor
   ist genau die Zustandsfarbe, die colors.price-status (bzw. ohne sie die Serie) setzt.
   Damit bleibt die Vielfalt erhalten (jede Vorlage faerbt ihren Streifen anders) und die
   Option deklariert keine eigene Buntfarbe. */
body.v2 .wrap .items .stockStatus, body.v2 .wrap .items .temp-soldout, body.v2 .wrap .items .tempout { display: block; width: 100%; text-align: center; border-radius: var(--tp-radius-panel, 6px); font-weight: 600; letter-spacing: .03em; }
/* J-2 (Runde J, RUBRIC 4 + 10): Unterhalb 768px zwingt der Grundshop die Plakette selbst auf
   display:block ueber die volle Breite (base_bootstrap_ticketpay.css Z. 12219, Spezifitaet 0,6,1
   im Media-Block). Diese Option muss ihre Bauform dort deshalb mit derselben Spezifitaet
   wiederholen, sonst gewinnt am Handy die Serie — unabhaengig davon, was hier gewaehlt ist. */
@media (max-width: 768px) {
  body.v2 .wrap .wrap_content .well .items .stockStatus, body.v2 .wrap .wrap_content .well .items .tempout, body.v2 .wrap .wrap_content .well .items .temp-soldout, body.v2 .cart .cartSet .cartWrap .items .cartSection .stockStatus, body.v2 .article-box .stockStatus, body.v2 .article-box .tempout, body.v2 .article-box .temp-soldout { display: block; width: 100%; max-width: 100%; margin-left: 0; margin-right: 0; float: none; text-align: center; clear: both; }
  /* W3-G1 (Runde W3): Flaeche + Polsterung getrennt von der Bauform — sie haengen nur an
     den Armen, die den STREIFEN meinen. background-color braucht !important, weil
     colors.price-status den verfuegbar-Zustand bei gleicher Tiefe (0,6,1) auf
     transparent !important legt; padding braucht keins (die Serie setzt es ohne
     !important, unsere Schicht laedt spaeter). */
  body.v2 .wrap .wrap_content .well .items .stockStatus, body.v2 .cart .cartSet .cartWrap .items .cartSection .stockStatus, body.v2 .article-box .stockStatus { background-color: color-mix(in srgb, currentColor 12%, transparent) !important; padding: 6px 10px; }
}
/* L3b (Runde L, CEO-Fund 4): Banderole in Serien-Tiefe — die (0,4,1)-Grundregel oben verlor
   display/text-align an die Serie (0,6,1, base Z. 11899) und die Breite an
   colors.price-status (width:fit-content, 0,6,1); der Streifen war dadurch nie
   zuverlaessig vollbreit. Der letzte Selektor (0,9,1) holt auch die Coming-Soon-Plakette
   (schlaegt die inline-block-Regel aus dem FEATURE-css, Optionen emittieren spaeter):
   auch sie wird zum vollbreiten, zentrierten Streifen — seit W3-G1 traegt er NUR noch die
   Bauform. Die FARBE steuert das Farben-Panel: der Streifen mischt currentColor (= die
   Zustandsfarbe, die colors.price-status setzt, ohne die Farboption die der Serie), und die
   Flaeche steht in einer eigenen Regel am 0,6,1-Arm — damit behaelt price-status seine
   Zustandsflaechen (0,7,1) auf BEIDEN Seiten des Breakpoints. Nur ab 769px:
   unterhalb regelt der J-2-Block oben dieselbe Bauform bereits in Serien-Tiefe. */
@media (min-width: 769px) {
  body.v2 .wrap .wrap_content .well .items .stockStatus, body.v2 .wrap .wrap_content .well .items .temp-soldout, body.v2 .wrap .wrap_content .well .items .tempout, body.v2 .wrap .wrap_content .well .items .price_quantity_box > .show_quantity.clearfix > .stockStatus { float: none; display: block; width: 100%; max-width: 100%; margin-left: 0; margin-right: 0; text-align: center; clear: both; }
  /* W3-G1 (Runde W3): Der vierte Arm oben ist 0,9,1 und schlug damit colors.price-status
     (0,7,1) — die Coming-Soon-Plakette trug ab 769px unsere Toenung, unterhalb die des
     Farben-Panels: dieselbe Plakette, zwei Fuellungen am Breakpoint. Flaeche und
     Polsterung haengen deshalb nur noch am 0,6,1-Arm des Streifens; damit gewinnt
     price-status seine Zustandsflaechen (0,7,1) auf BEIDEN Seiten des Breakpoints. */
  body.v2 .wrap .wrap_content .well .items .stockStatus { background-color: color-mix(in srgb, currentColor 12%, transparent) !important; padding: 6px 10px; }
}

/* — checkout.order-table = "clean" — */
/* J-3 (Runde J, RUBRIC 3 "Ausrichtung"): Auf der Zahlungsseite steht der Kopf der schmalen
   Spalte ("Zahlungsart waehlen", col-md-4 = 292-336px) zweizeilig, der Kopf der breiten Spalte
   ("Ihre Bestellung") einzeilig. Gemessen in ALLEN 12 Presets (natuerliche Kopfbreite 321-447px
   gegen 292-336px verfuegbar) — die beiden Spalten beginnen dadurch 63-64px versetzt, Trennlinie
   und Tabellenkopf liegen auf zwei Hoehen. 2 Jurys haben das als "Spaltenkoepfe versetzt" gemeldet.
   Die Ueberschrift zu verkleinern waere keine Loesung: mono-kontrast braeuchte 23px statt 34px,
   und die beiden Spaltenkoepfe haetten dann zwei verschiedene Groessen (RUBRIC 4). Stattdessen
   bekommen BEIDE Koepfe dieselbe Mindesthoehe von zwei Zeilen — der Umbruch bleibt erlaubt,
   die Spalten fluchten wieder. Nur ab 992px, also nur solange die Spalten wirklich nebeneinander
   stehen; gestapelt (Tablet/Handy) und in der vollbreiten Zeile (SEPA-Block, col-md-12) waere
   die Reserve tote Flaeche. 2lh ist exakt zwei Zeilenhoehen, 2.2em der Fallback fuer Browser
   ohne lh-Einheit. Beleg: shots/rundeJ-p2/VOR-mono-kontrast-payment__full.png gegen NACH-*. */
@media (min-width: 992px) {
  body.v2 #paymentchoose > .well > h2.text-system, body.v2 #paymentchoose ~ .col-md-8 > .well > h2.text-system { min-height: 2.2em; min-height: 2lh; }
}
body.v2 #cart_items ~ table.table.table-striped > tbody > tr:nth-of-type(odd) > td { background-color: transparent; } body.v2 #cart_items ~ table.table > tbody > tr.active > td { background-color: transparent; } body.v2 #cart_items ~ table.table > thead > tr > th { border-bottom: 2px solid var(--tp-color-border, rgba(128,128,128,.35)); text-transform: uppercase; font-size: 12px; letter-spacing: .06em; } body.v2 #cart_items ~ table.table > tbody > tr > td { border-top-color: var(--tp-color-border, rgba(128,128,128,.18)); padding-top: 10px; padding-bottom: 10px; } body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { border-top: 2px solid var(--tp-color-accent, currentColor); font-size: 1.1em; font-weight: 700; } body.v2 #cart_items ~ table.table > tbody > tr.active, body.v2 #cart_items ~ table.table > tbody > tr.finaltotal { background-color: transparent !important; } body.v2 table.table td.text-right, body.v2 table.table th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child, body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td, body.v2 #total_amount, body.v2 #payment_fee_amount, body.v2 .subtotal .value { white-space: nowrap; } @media (max-width: 480px) { body.v2 #cart_items ~ table.table > thead > tr > th, body.v2 #cart_items ~ table.table > tbody > tr > td { padding-left: 5px; padding-right: 5px; } body.v2 #cart_items ~ table.table > thead > tr > th:first-child, body.v2 #cart_items ~ table.table > tbody > tr > td:first-child { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: anywhere; } body.v2 #cart_items ~ table.table > thead > tr > th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child { font-size: 13px; } body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { font-size: 14px; } }

/* — checkout.subtotal-style = "final-betont" — */
/* BK1 Betrags-Schutz — siehe checkout.article-rows. */
body.v2 table.table td.text-right, body.v2 table.table th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child, body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td, body.v2 #total_amount, body.v2 #payment_fee_amount, body.v2 .subtotal .value { white-space: nowrap; }
@media (max-width: 480px) {
  body.v2 #cart_items ~ table.table > thead > tr > th, body.v2 #cart_items ~ table.table > tbody > tr > td { padding-left: 5px; padding-right: 5px; }
  body.v2 #cart_items ~ table.table > thead > tr > th:first-child, body.v2 #cart_items ~ table.table > tbody > tr > td:first-child { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: anywhere; }
  body.v2 #cart_items ~ table.table > thead > tr > th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child { font-size: 13px; }
  body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { font-size: 14px; }
}
/* G-G1 (Runde G, Rubrik 1/6): .subtotal ist float:right. In der Akkordeon-Ansicht liegt der Block
   in einer .well, die den Float ohne eigenen Formatierungskontext NICHT umschliesst (well 40px,
   subtotal 96px). Im nackten Shop faellt das nicht auf; sobald ein Design der Karte eine Flaeche
   gibt, schneidet die Kartenkante waagerecht durch "Zwischensumme" und der leere Warenkorb wird
   zur inhaltslosen Karte. */
body.v2 #cart .well, body.v2 #shopping_cart .well, body.v2 .wrap.accordions + #shopping_cart .well { display: flow-root; }
/* I-9 (Runde I, Rubrik 6 "leerer Warenkorb"): ohne Positionstabelle schrumpft die Karte auf
   den Summenblock, statt eine leere Flaeche ueber die volle Breite aufzuspannen. */
body.v2 #cart .well:not(:has(table)), body.v2 #shopping_cart .well:not(:has(table)) { width: -moz-fit-content; width: fit-content; min-width: min(340px, 100%); margin-left: auto; }
body.v2 .subtotal li.final { font-size: 1.15em; border-top-width: 2px; border-top-style: solid; padding-top: 8px; margin-top: 6px; }
/* I-9 (Runde I, Rubrik 6 "leerer Warenkorb"): ohne Positionstabelle schrumpft die Karte auf
   den Summenblock, statt eine leere Flaeche ueber die volle Breite aufzuspannen. */
body.v2 #cart .well:not(:has(table)), body.v2 #shopping_cart .well:not(:has(table)) { width: -moz-fit-content; width: fit-content; min-width: min(340px, 100%); margin-left: auto; }

/* — checkout.payment-layout = "karten-liste" — */
/* BK1 Betrags-Schutz — siehe checkout.article-rows. Die Bestell-Tabelle steht direkt neben der Zahlartenwahl. */
body.v2 table.table td.text-right, body.v2 table.table th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child, body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td, body.v2 #total_amount, body.v2 #payment_fee_amount, body.v2 .subtotal .value { white-space: nowrap; }
@media (max-width: 480px) {
  body.v2 #cart_items ~ table.table > thead > tr > th, body.v2 #cart_items ~ table.table > tbody > tr > td { padding-left: 5px; padding-right: 5px; }
  body.v2 #cart_items ~ table.table > thead > tr > th:first-child, body.v2 #cart_items ~ table.table > tbody > tr > td:first-child { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: anywhere; }
  body.v2 #cart_items ~ table.table > thead > tr > th.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td.text-right, body.v2 #cart_items ~ table.table > tbody > tr > td:last-child { font-size: 13px; }
  body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { font-size: 14px; }
}
body.v2 .paymentmethod { border: 1px solid var(--tp-color-border, rgba(128,128,128,.25)); border-radius: var(--tp-radius-panel, 8px); padding: 0; height: auto; min-height: 110px; overflow: hidden; margin-bottom: 10px; background: rgba(128,128,128,.05); } body.v2 .paymentmethod .paymentmethod_radio { left: 8px; } body.v2 .paymentmethod .paymentmethod_image { left: 40px; /* M-F9: Abstand zum 18px-Radio (G-C1); Beschriftung bleibt bei 30 (J3-E) */ } body.v2 .paymentmethod .paymentmethod_extra { right: 10px; width: auto; } /* D8: Bootstrap gibt jedem label margin-bottom:5px — bei bottom:0 schob das den Namensbalken 5px nach oben und liess darunter einen Streifen Kartengrund stehen. margin:0 ist der Fix, overflow:hidden allein reicht nicht. */ body.v2 .paymentmethod .paymentmethod_text { margin: 0; border-radius: 0; height: auto; min-height: 29px; padding-left: 30px; padding-right: 0; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; } body.v2 .paymentmethod:not(.paymentmethod-checked) .paymentmethod_text { background: var(--tp-color-surface2, #f0f0f0); color: var(--tp-color-surface2-contrast, var(--tp-color-panel-text, #333333)); }
/* J1-7 (Runde J, Rubrik 8): Die Serie legt den Beschriftungsbalken absolut an den Kartenboden (bottom:0) und das Logo absolut an den Kartenkopf (top:0, height:81px) — bei fester Kartenhoehe 110px. Braucht die Beschriftung zwei Zeilen ("Kreditkarte (Visa / Mastercard)" in einer breiteren Schrift), waechst der Balken nach OBEN in die Logoflaeche: gemessen 52px statt 75px, ausgerechnet auf der gewaehlten Karte. Die Logozone wird darum als Innenabstand reserviert und der Balken in den normalen Fluss gestellt — die Karte wird dann hoeher statt enger. */
body.v2 .paymentmethod { height: auto; min-height: 110px; padding-top: 81px; }
body.v2 .paymentmethod .paymentmethod_text { position: static; }

/* — checkout.payment-logo-plate = "hell" — */
/* Radius aus dem Design uebernehmen, aber deckeln: bei Pill-Designs (--tp-radius-button: 999px) wuerde aus dem Plaettchen sonst eine Kapsel, die groesser wirkt als das Logo. */ body.v2 .paymentmethod .paymentmethod_image { top: 24px; height: auto; line-height: normal; display: inline-flex; align-items: center; justify-content: center; background: var(--tp-color-payment-plate, #ffffff); border-radius: min(var(--tp-radius-button, 4px), 10px); padding: 4px 8px; } body.v2 .paymentmethod .paymentmethod_image img { max-height: 26px; width: auto; display: block; }

/* — checkout.progress-hero = "kreise" — */
body.v2 .checkout-progress-row .pi-callout { height: auto; min-height: 0; padding: 2px 0 6px; color: inherit; }
body.v2 .checkout-progress-row .pi-callout-success::after { display: none !important; }
body.v2 .checkout-progress-row .pi-callout i.h2 { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin: 0 0 8px; border: 2px solid currentColor; border-radius: 50%; font-size: 19px; line-height: 1; }
body.v2 .checkout-progress-row .pi-callout i.h2::before { font-family: var(--tp-font-heading, var(--tp-font-body, "Source Sans Pro", "Helvetica Neue", Arial, sans-serif)); font-weight: 700; font-style: normal; }
body.v2 .checkout-progress-row i.fa-circle-1::before { content: "1"; }
body.v2 .checkout-progress-row i.fa-circle-2::before { content: "2"; }
body.v2 .checkout-progress-row i.fa-circle-3::before { content: "3"; }
body.v2 .checkout-progress-row i.fa-circle-4::before { content: "4"; }
body.v2 .checkout-progress-row i.fa-circle-5::before { content: "5"; }
body.v2 .checkout-progress-row .pi-callout-success i.h2 { background-color: var(--tp-color-primary, #5cb85c); border-color: var(--tp-color-primary, #5cb85c); color: var(--tp-color-primary-contrast, #ffffff) !important; }
body.v2 .checkout-progress-row .pi-callout-success, body.v2 .checkout-progress-row .pi-callout-success h5, body.v2 .checkout-progress-row .pi-callout-success a { color: var(--tp-color-primary, #5cb85c) !important; }
body.v2 .checkout-progress-row .pi-callout-primary i.h2 { border-color: var(--tp-color-primary, #5cb85c); color: var(--tp-color-primary, #5cb85c) !important; box-shadow: inset 0 0 0 1px var(--tp-color-primary, #5cb85c); }
body.v2 .checkout-progress-row .pi-callout-default { opacity: 0.6; }
body.v2 .checkout-progress-row .pi-callout-default, body.v2 .checkout-progress-row .pi-callout-default h5, body.v2 .checkout-progress-row .pi-callout-default h4 { color: inherit !important; }
@media (max-width: 767px) {
  body.v2 .checkout-progress-row .pi-callout i.h2 { width: 34px; height: 34px; font-size: 16px; margin-bottom: 0; }
}

/* — checkout.coupon-style = "abgerundet" — */
body.v2 .input-group.input-split .form-control { border-radius: var(--tp-radius-input, 6px) 0 0 var(--tp-radius-input, 6px); } body.v2 .input-group.input-split .btn { border-radius: 0 var(--tp-radius-input, 6px) var(--tp-radius-input, 6px) 0; } body.v2 #voucher .panel { border-radius: var(--tp-radius-panel, 10px); overflow: hidden; }

/* ============ Bilder-Slideshow ============ */
/* — carousel.pfeil-stil = "dezent" — */
/* M-F3: Serien-.carousel-control = 15%-Flanke mit Schwarzverlauf über die VOLLE Kastenhöhe — ragt bei kleinen Artikelbildern (Inline 200x200) sichtbar über das Bild hinaus. Diese Option nimmt nur die Flanke weg. Serie rechnet die Pfeil-Zentrierung mit 20px-Glyphe (margin -10px), die FA-Chevrons sind 30px — Icon-Maße werden deshalb mitnormalisiert (Muster A6). */
body.v2 #content .carousel .carousel-control { background-image: none; opacity: 0.75; text-shadow: 0 1px 6px rgba(0,0,0,0.7); }
body.v2 #content .carousel .carousel-control:hover, body.v2 #content .carousel .carousel-control:focus, body.v2 #content .carousel .carousel-control:active { background-image: none; opacity: 1; }
body.v2 #content .carousel .carousel-control:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: -2px; }
body.v2 #content .carousel .carousel-control .icon-prev, body.v2 #content .carousel .carousel-control .icon-next { font-size: 24px; width: 24px; height: 24px; margin-top: -12px; line-height: 1; }
body.v2 #content .carousel .carousel-control .icon-prev { margin-left: -12px; }
body.v2 #content .carousel .carousel-control .icon-next { margin-right: -12px; }

/* — carousel.bild-rundung = true — */
body.v2 #content .carousel .item img { border-radius: var(--tp-radius-panel, 8px); }

/* ============ Kaufleiste (unten fixiert) ============ */
/* — stickyfooter.layout = "kompakt" — */
body.v2 #stickyfooter #stickyfooter-inner { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 6px 10px; }
body.v2 #stickyfooter #stickyfooter-inner .pull-left, body.v2 #stickyfooter #stickyfooter-inner .pull-right { float: none; display: flex; align-items: center; gap: 6px; }

/* — stickyfooter.cta-chevron = true — */
/* L3c (Options-Integritaet, Runde L): Diese Einstellung brachte bisher die komplette
   Leisten-Familie (54 Zeilen Normalisierung inkl. verstecktem SSL-Knopf) als undeklarierte
   Beifracht mit (L1c, PLAYBOOK-Regel 3). Jetzt aendert sie nur noch ihr benanntes Element;
   die Leisten-Familie liefern Anordnung, Glas-Effekt, Warenkorb-Stil, Countdown-Stil und
   obere Kante (deklariert in der Kategorie-Beschreibung). */
body.v2 #stickyfooter a#initorder_layout::after { content: "\276F"; margin-left: 8px; font-size: 0.85em; }

/* — stickyfooter.warenkorb-stil = "pill" — */
body.v2 #stickyfooter #show_shopping_cart { border-radius: var(--tp-radius-button, 999px) !important; padding-left: 16px; padding-right: 16px; padding-top: 0; padding-bottom: 0; min-height: var(--tp-sticky-btn-h, 42px); /* M-1: clamp statt fixer 15px — ab 492px identisch 15px, am Handy derselbe Schriftgrad wie der Bestellen-Knopf (eine Familie, ein Schriftgrad) */ font-size: clamp(11px, 3.05vw, 15px) !important; display: inline-flex; align-items: center; background-color: transparent; border: 1px solid currentColor; color: inherit; box-shadow: none; }
/* M-F5: Starke Selektor-Varianten (3 IDs) — die Pillen-Optik gewinnt gegen die weisse Serien-Hover-Regel (2-5-1) UND gegen die Familien-Neutralisierung. */
body.v2 #stickyfooter #show_shopping_cart:hover, body.v2 #stickyfooter #show_shopping_cart:active, body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart:hover, body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart:active { background-color: rgba(128, 128, 128, 0.18); border-color: currentColor; color: inherit; }
body.v2 #stickyfooter #show_shopping_cart:focus-visible, body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }
body.v2 #stickyfooter #show_shopping_cart:disabled { opacity: 0.5; }
body.v2 #stickyfooter #show_shopping_cart span { background: transparent !important; border-radius: 0 !important; color: inherit !important; padding: 0 !important; }
body.v2 #stickyfooter #cart_button_amount { background-color: transparent !important; color: inherit !important; padding: 0 !important; border-radius: 0 !important; min-width: 0; }

/* — stickyfooter.countdown-stil = "dezent" — */
/* M-F5: Starke Zustands-Varianten (.btn.btn-default.countDownTimer = 2-6-1, schlaegt Serie 2-5-1 und Familien-Neutralisierung unabhaengig von der Emissions-Reihenfolge) — "Nur Text" bleibt auch im Hover transparent, gegen die weisse Serien-Hover-Regel (2-5-1) und die Familien-Neutralisierung. */
body.v2 #stickyfooter .countDownTimer, body.v2 #stickyfooter .countDownTimer:hover, body.v2 #stickyfooter .countDownTimer:focus, body.v2 #stickyfooter .countDownTimer:active, body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer:hover, body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer:focus, body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer:active { background-color: transparent; border-color: transparent; box-shadow: none; color: inherit; font-variant-numeric: tabular-nums; }
body.v2 #stickyfooter .countDownTimer:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }
body.v2 #stickyfooter .countDownTimer:disabled { opacity: 0.65; }
/* Nachbar: der Schloss-Knopf sitzt in derselben Gruppe und muss denselben Stil tragen. */
body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer), body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):hover, body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):focus, body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):active { background-color: transparent; border-color: transparent; box-shadow: none; color: inherit; }
body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }

/* — stickyfooter.ssl-hinweis = "zeigen" — */
/* L3c (vorher J3-C): holt den Schloss-Knopf zurueck, den die Leisten-Familie (Anordnung, Glas-Effekt,
   Warenkorb-/Countdown-Stil, obere Kante) standardmaessig ausblendet. !important ist noetig, weil die
   Familie auch von SPAETER emittierten Features (obere Kante, Countdown-Stil) erneut mitkommt —
   ohne !important gewann deren display:none wieder (L1c: "zeigen" hatte 0px Wirkung). */
body.v2 #stickyfooter #stickyfooter-inner > .pull-left .btn-group > .btn:not(.countDownTimer) { display: inline-flex !important; align-items: center; }
@media (max-width: 480px) { body.v2 #stickyfooter #stickyfooter-inner > .pull-left .btn-group > .btn:not(.countDownTimer) { display: none !important; } }

/* — stickyfooter.obere-kante = "keine" — */
body.v2 #stickyfooter { height: auto !important; line-height: 1 !important; padding-top: var(--tp-sticky-pad-top, 8px); padding-bottom: var(--tp-sticky-pad-bottom, 8px); }
body.v2 #stickyfooter #stickyfooter-inner { line-height: 1.4; }
/* Reserve unter der fixen Leiste (F2): an die REALE Leistenhoehe gekoppelt statt an einen festen vh-Wert.
   Hoehe = Innenabstand oben + unten + (Zeilen x Knopfhoehe) + Zuschlag. Die Werte stammen aus den
   Optionen-Tokens (Kompakt 6/40, Standard 10/44, Luftig 16/48; Fallback 8/42), daher wird nie
   ueber- oder unterkompensiert. Unter 480px kann die Leiste umbrechen -> zwei Zeilen. */
body.v2 { --tp-sticky-reserve: calc(var(--tp-sticky-pad-top, 8px) + var(--tp-sticky-pad-bottom, 8px) + var(--tp-sticky-rows, 1) * var(--tp-sticky-btn-h, 42px) + var(--tp-sticky-lift, 0px) + var(--tp-sticky-safe, 0px) + var(--tp-sticky-gap, 20px)); }
@media (max-width: 767px) { body.v2 { --tp-sticky-gap: 24px; } }
@media (max-width: 480px) { body.v2 { --tp-sticky-btn-h: 40px; --tp-sticky-rows: 1; } }
/* Die Serie reserviert den Platz unter der fixen Leiste als footer{margin-bottom:52px} (Footer und
   #content sind Geschwister). Genau dort wird die Reserve auf die tatsaechliche Leistenhoehe gehoben —
   so bleiben Gesamtsumme UND Footer-Links frei, ohne zusaetzliche Luecke zwischen Summe und Footer.
   V-14 (Runde V, Organizer 2026-07-30): Die Bedingung :has(#stickyfooter) kam dazu.
   Auf der Veranstalter-Uebersicht (organizer-grid/list/calendar/leer/belehrung/info/datumsfilter/widerruf)
   existiert #stickyfooter GAR NICHT im DOM (0 Treffer, an allen 8 Fixtures gemessen) — die Reserve
   erzeugte dort in 12 von 12 Vorlagen 16-32px reinen Leerraum am Seitenende (Serie 52px gegen 68-84px).
   Mit der Bedingung faellt der Wert auf jeder Flaeche ohne Leiste auf den Serienwert zurueck und bleibt
   auf jeder Flaeche mit Leiste (cart/customerdata/payment) unveraendert. Kein neues Feature, kein
   Eingriff in JS-gesteuerte display-Werte: geprueft wird nur die EXISTENZ des Knotens. Browser ohne
   :has ignorieren die Regel — dann gilt der Serienwert, also Status quo ohne Schaden. */
body.v2:has(#stickyfooter) footer { margin-bottom: var(--tp-sticky-reserve, 96px); }
/* S-3 (Runde S, 2026-07-30): Unter 481 px kostet der SSL-Schloss-Chip rund 46 px Leistenbreite und draengt die gesetzlich vorgeschriebene Beschriftung aus dem Bestell-Knopf. Gemessen auf fixture/payment@375 ueber alle 12: beschnitten sind genau die zwei Vorlagen mit sichtbarem Chip (stadion-energie 58 px, festival-dark 27 px), die uebrigen zehn 0 px. Der Knopftext gewinnt, der Chip ist ein Vertrauens-Extra. */
@media (max-width: 480px) { body.v2 #stickyfooter #stickyfooter-inner > .pull-left .btn-group > .btn:not(.countDownTimer) { display: none !important; } }
body.v2 .wrapper_all { padding-bottom: 0; }
@media (max-width: 480px) { body.v2 #stickyfooter { --tp-sticky-btn-h: 40px; } /* M-1/M-2 (Runde M, J4-S1/J4-SE-1): Der CTA lief am Handy mit clamp()-Schrift (11,4px @375), der Warenkorb-Knopf daneben mit 15-16px — der wichtigste Knopf wirkte typografisch schwaecher als der Sekundaerknopf, und bei grosser Rezept-Typo (stadion) passte das Warenkorb-Label nicht mehr in die J3-B-Zeile (nur Symbol @375, Nacktshop zeigt 'Warenkorb (3)'). Fix: ALLE Leisten-Knoepfe teilen dieselbe clamp()-Schrift — eine Familie, ein Schriftgrad. Die Untergrenze bleibt bewusst 11px: gemessen hat payment@375 keinerlei Luft (stadion-CTA dort schon mit 11,4px 19px beschnitten); jede Anhebung beschneidet den Bestellknopf (I-1). */ body.v2 #stickyfooter .btn:not(.countDownTimer) { font-size: clamp(11px, 3.05vw, 15px) !important; letter-spacing: normal !important; padding-left: 10px !important; padding-right: 10px !important; } body.v2 #stickyfooter a#initorder_layout, body.v2 #stickyfooter a#initorder_amazon { font-size: clamp(11px, 3.05vw, 15px) !important; letter-spacing: normal !important; padding-left: 10px !important; padding-right: 10px !important; } /* MA-1 (M-Abnahme 2026-07-29, Nebenwirkung von M-K2): Die Timer-Pille (Countdown-Anzeige: Pillenform; bis Runde Z checkout.countdown-style) behaelt ihr Desktop-Polster padding 6px 16px !important auch unter 480px und staucht damit den CTA in der einzeiligen G-E1-Flexzeile: neon payment@375 4px Chevron-Beschnitt (vorher 0), @320 51px (Altlast war 35), warm-craft@320 1px. Fix hier im selben <=480-Block wie die M-1-Familienschrift: Seitenpolster ALLER Timer-Varianten auf 8px komprimieren. Selektorliste = exakt die staerkste M-K2-Regel; seit Runde Z liegen beide in stickyfooter; diese Zeile steht im stickyBase-Baustein, den layout/glas-effekt/warenkorb-stil/obere-kante mitbringen und der damit NACH der Pillenform emittiert wird — gleiche Spezifitaet + !important gewinnt also fuer die Longhands, waehrend Pillenform, Radius, Farbe und Schriftgrad (die M-K2-Verbesserung) unberuehrt bleiben. Dezent (6px 8px) und Serie aendern sich damit ebenfalls auf 8px Seitenpolster - eine Familie, ein Mass. */ body.v2 #stickyfooter .countDownTimer, body.v2 #stickyfooter .btn-group > .btn.countDownTimer, body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group > .btn.countDownTimer { padding-left: 8px !important; padding-right: 8px !important; } }
/* M-17/MA-2 (K2-K-1, ENDBERICHT Abschn. 5): Auf der Landing existieren weder .countDownTimer noch #show_shopping_cart, und der Weiter-CTA kommt serverseitig mit Inline-display:none - die Leisten-Familie liess dort trotzdem einen 16-17px hohen, komplett leeren Farbstreifen stehen (mono weiss-auf-weiss, festival dunkel-auf-dunkel; die nackte Serie zeigt einen 52px-Streifen, ebenfalls ohne sichtbaren Inhalt). Mobil (<768px, dort versteckt die Serie auch den SSL-Text per hidden-xs) wird die funktionslos-leere Leiste ausgeblendet. Erkennung rein strukturell ueber :has - KEIN Eingriff in JS-gesteuerte display-Werte: sobald JS den CTA zeigt (Warenkorb gefuellt), enthaelt sein style-Attribut kein none mehr, der :has-Treffer entfaellt und die Leiste erscheint gestylt. Countdown- oder Warenkorb-Knopf im DOM (alle Checkout-Seiten) schliessen die Regel ebenso aus. Browser ohne :has ignorieren die Regel (Status quo, kein Schaden). */
@media (max-width: 767px) { body.v2 #stickyfooter:not(:has(.countDownTimer, #show_shopping_cart)):has(a[id^=initorder][style*=none]) { display: none; } }
/* G-E1 (Runde G, Rubrik 7): Die Serie legt .pull-left/.pull-right als Floats nebeneinander. Passen sie nicht in 375px, faellt die rechte Gruppe eine Zeile tiefer — die Leiste wurde 90-110px hoch und versetzt (8 von 12 Presets). Unter 480px darum eine echte einzeilige Flex-Zeile, in der nur die Warenkorb-Beschriftung nachgibt; Countdown und Weiter-Knopf behalten ihre Groesse. */
@media (max-width: 480px) { body.v2 #stickyfooter #stickyfooter-inner { display: flex !important; flex-wrap: nowrap !important; align-items: center; gap: 6px; } body.v2 #stickyfooter #stickyfooter-inner > .pull-left { float: none !important; flex: 0 0 auto; } body.v2 #stickyfooter #stickyfooter-inner > .pull-right { float: none !important; flex: 1 1 auto; min-width: 0; display: flex; justify-content: flex-end; } body.v2 #stickyfooter #stickyfooter-inner > .pull-right > .btn-group { min-width: 0; max-width: 100%; } body.v2 #stickyfooter a#initorder_layout, body.v2 #stickyfooter a#initorder_amazon { flex: 0 1 auto; min-width: 0; white-space: nowrap; } }
/* M-3 (CEO-Entscheid 2026-07-29, M-K12): Alle drei Leisten-Elemente (Countdown, Warenkorb, CTA) bleiben auch mobil sichtbar — Kandidat B (Countdown ausblenden) ist abgelehnt. Der CTA heisst auf fast allen Schritten nur "Weiter"; das lange "ZAHLUNGSPFLICHTIG BESTELLEN" kommt nur im letzten Schritt (Beleg: echter Shop). Unter 360px entscheidet darum der TATSAECHLICHE Platz statt einer Label-Erkennung (CSS-only): die Zeile darf umbrechen (wrap !important schlaegt das G-E1-nowrap per gleicher Wichtigkeit + spaeterer Position), .pull-right und ihre .btn-group werden per display:contents aufgeloest (eine .btn-group laesst ihren CTA NUR so auf Leisten-Vollbreite umbrechen — flex auf der Gruppe erzeugt drei Zeilen, s. TOOLING M-3-Entscheidungsmaterial), und der CTA bekommt flex 1 0 auto + nowrap: Passt er neben Countdown und Warenkorb (kurzes Label), bleibt die Leiste einzeilig und er fuellt nur den Zeilenrest; passt er nicht (langes Label), faellt er unbeschnitten als zweite Zeile in voller Breite darunter — Kandidat A nur im Bedarfsfall, nichts wird ausgeblendet, nichts beschnitten. Zeile 1 ordnet das justify-content:space-between der Familie (Countdown links, Warenkorb rechts). Die Reserve rechnet unter 360px mit 2 Zeilen (--tp-sticky-rows: 2): CSS kann den realen Umbruch nicht abfragen; lieber ~46px Luft unter dem Footer im Kurz-Label-Fall als eine von der Leiste verdeckte Gesamtsumme im Lang-Label-Fall. display:contents traegt !important, weil die spaeteren Familien-Grundregeln (.pull-right display:flex, .btn-group inline-flex) sonst per Reihenfolge gewinnen; das flex am CTA ebenso (Schutz vor spaeteren Familien-Kopien anderer Leisten-Optionen). display am CTA bleibt UNBERUEHRT: es ist JS-gesteuert (Landing haelt den Weiter-CTA per Inline-display:none versteckt — SCHEMA-Regel 3/M-17); die Zentrierung des vollbreiten CTA liefern text-align:center der Serie + die line-height der Familie. Der Warenkorb braucht dabei eine Sonderbehandlung: Zeilenumbruch rechnet mit HYPOTHETISCHEN Groessen, das flex-shrink:1000 aus J3-B kollabiert sein Label unter wrap also nicht mehr (gemessen: stadion@320 wurde schon mit "Weiter" zweizeilig, weil das 130px-Label den CTA verdraengte). Darum wird das J3-B-Nachgeben hier zum Wachsen umgedreht: flex-basis 40px (nur Icon) + flex-grow 999 bis max-width:max-content — das Label erscheint genau dann vollstaendig, wenn die Zeile Platz hat (J3-B-Prinzip: nie weniger zeigen als moeglich), zwingt aber nie den CTA in Zeile 2; die !important-Longhands sind noetig, weil die J3-B-Regeln im selben Options-CSS SPAETER stehen. */
@media (max-width: 359px) { body.v2 { --tp-sticky-rows: 2; } body.v2 #stickyfooter #stickyfooter-inner { flex-wrap: wrap !important; } body.v2 #stickyfooter #stickyfooter-inner > .pull-right, body.v2 #stickyfooter #stickyfooter-inner > .pull-right > .btn-group { display: contents !important; } body.v2 #stickyfooter #show_shopping_cart { flex-grow: 999 !important; flex-shrink: 1 !important; flex-basis: 40px !important; max-width: max-content !important; } body.v2 #stickyfooter a#initorder_layout, body.v2 #stickyfooter a#initorder_amazon { flex: 1 0 auto !important; white-space: nowrap; } }
/* J3-B (Runde J3, RUBRIC 7 + 10): Bis Durchgang 2 wurde die Warenkorb-Beschriftung unter 400px
   hart ausgeblendet (display:none) — der Zaehler "(3)" steckt im selben <span> und verschwand mit.
   Am Handy blieb ein leerer 40x40-Kreis, waehrend der NACKTE Shop an derselben Stelle
   "Warenkorb (3)" zeigt, bei 375 UND bei 320px (gemessen: Leiste 52px, alles im Bild). Das war
   also keine Platznot, sondern eine selbstverschuldete Verschlechterung gegenueber der Nullprobe —
   auf dem Geraet, auf dem die meisten Tickets gekauft werden.
   Platznot gibt es nur auf der Zahlungsseite: dort misst der CTA "ZAHLUNGSPFLICHTIG BESTELLEN"
   228px, zusammen mit Countdown und beschriftetem Warenkorb 435px gegen 345px Innenbreite.
   Statt eines pauschalen Breakpoints entscheidet jetzt der tatsaechliche Platz:
   Der Knopf ist eine umbrechende Flex-Zeile mit fester Zeilenhoehe und overflow:hidden — passt die
   Beschriftung, steht sie neben dem Symbol; passt sie nicht, faellt sie als zweite Zeile aus dem
   Knopf und uebrig bleibt exakt der bisherige Symbolknopf. Kein abgeschnittener Text, kein
   Ellipsen-Stummel. Der hohe flex-shrink sorgt dafuer, dass der Warenkorb nachgibt und nicht der
   Bestellknopf (I-1, KRITISCH); sobald er seine Mindestbreite erreicht hat, friert Flexbox ihn ein
   und der Rest verhaelt sich wie bisher.
   J1-3 bleibt gewahrt: das Symbol wird erzwungen, auch wenn buttons.icons: verstecken es global
   ausblendet — jetzt im 480px-Block, weil die Beschriftung auch zwischen 400 und 480px wegfallen
   kann. */
@media (max-width: 480px) { body.v2 #stickyfooter #show_shopping_cart { display: inline-flex; flex-wrap: wrap; align-content: flex-start; justify-content: center; gap: 0.45em; height: var(--tp-sticky-btn-h, 40px); overflow: hidden; flex-grow: 0; flex-basis: auto; flex-shrink: 1000; min-width: var(--tp-sticky-btn-h, 40px); padding-left: 8px !important; padding-right: 8px !important; } body.v2 #stickyfooter #show_shopping_cart > i.fa { display: inline-flex !important; align-items: center; height: var(--tp-sticky-btn-h, 40px); flex: 0 0 auto; font-size: 15px !important; margin-right: 0 !important; padding-right: 0 !important; } body.v2 #stickyfooter #cart_button_amount { display: inline-flex; align-items: center; height: var(--tp-sticky-btn-h, 40px); white-space: nowrap; flex: 0 0 auto; max-width: none; overflow: visible; text-overflow: clip; } }
/* Leisten-Familie (D7): Countdown, Warenkorb und Bestellen-Knopf teilen Hoehe, Rundung und Grundlinie. */
body.v2 #stickyfooter #stickyfooter-inner .btn-group { display: inline-flex; align-items: stretch; gap: 6px; }
/* J3-C (Runde J3, RUBRIC 4 "Konsistenz" + 7): Links in der Kaufleiste steht ein
   button.btn-default ohne jede Beschriftung — einziges Kind ist <i class="fa fa-lock">. In der
   Serie klebt er als Teil einer .btn-group direkt am Countdown und liest sich als ein Element
   ("Schloss + Restzeit"). Unsere Leisten-Familie setzt die Gruppe mit gap auseinander; damit
   stehen zwei formgleiche Chips nebeneinander, in einem die Zeit, im anderen nichts — das liest
   sich als Bedienelement, dessen Beschriftung nicht geladen hat (elegant-serif, warm-craft und
   alle weiteren Rezepte ohne stickyfooter.ssl-hinweis: 11 von 12, Muster A8).
   Der Hinweis selbst geht nicht verloren: der Shop traegt den Text als span.hidden-xs, und die
   Vorbild-Vorlage (Parookaville) blendet genau dieses Schloss ebenfalls aus
   (research/KNOWLEDGE.md 4.14: "Alles rein dekorativ, kein Funktionsverlust").
   stickyfooter.ssl-hinweis: "Zeigen" holt es fuer Rezepte zurueck, die es bewusst wollen. */
body.v2 #stickyfooter #stickyfooter-inner > .pull-left .btn-group > .btn:not(.countDownTimer) { display: none; }
body.v2 #stickyfooter #stickyfooter-inner .btn-group > .btn { margin-left: 0; margin-right: 0; }
body.v2 #stickyfooter .btn, body.v2 #stickyfooter #stickyfooter-inner .btn { min-height: var(--tp-sticky-btn-h, 42px); padding-top: 0; padding-bottom: 0; border-radius: var(--tp-radius-button, 4px); }
body.v2 #stickyfooter button.btn, body.v2 #stickyfooter #stickyfooter-inner button.btn { display: inline-flex; align-items: center; justify-content: center; }
body.v2 #stickyfooter a#initorder_layout, body.v2 #stickyfooter a#initorder_amazon, body.v2 #stickyfooter #stickyfooter-inner a#initorder_layout, body.v2 #stickyfooter #stickyfooter-inner a#initorder_amazon { min-height: var(--tp-sticky-btn-h, 42px); line-height: calc(var(--tp-sticky-btn-h, 42px) - 2px); padding-top: 0; padding-bottom: 0; }
/* M-F5 (Runde M, CEO 2026-07-28 — Rubrik-6-Rueckfall): Die Serie faerbt den Hover der Leisten-Chips HART WEISS: body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default:hover { background-color: #ffffff } (custom_tp.css.scss Z. 289 + 2093, Spezifitaet 2-5-1) — staerker als jede Chip-Hover-Regel (2-2-1). Auf dunklen Leisten wurde der Chip im Hover weiss MIT heller Schrift = weiss-auf-weiss (gemessen: adventure, festival, stadion, warm-craft, elegant, corporate; mono verlor nur das Hover-Feedback). Gegenmittel in der Familie: exakt gleicher Selektor, spaeter geladen — Flaeche aus currentColor statt Weiss, volles State-Set. Warenkorb-/Countdown-Stil ueberstimmen darunter mit staerkeren Selektoren ihre eigene Optik. */
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default:hover, body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default:focus { background-color: rgba(128,128,128,0.18); background-color: color-mix(in srgb, currentColor 16%, transparent); color: inherit; }
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default:active { background-color: rgba(128,128,128,0.28); background-color: color-mix(in srgb, currentColor 24%, transparent); color: inherit; }
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }
body.v2 #stickyfooter { border-top: 0; box-shadow: none; }

/* — stickyfooter.ios-safe-area = true — */
/* L3c (Options-Integritaet, Runde L): Diese Einstellung brachte bisher die komplette
   Leisten-Familie (54 Zeilen Normalisierung inkl. verstecktem SSL-Knopf) als undeklarierte
   Beifracht mit (L1c, PLAYBOOK-Regel 3). Jetzt aendert sie nur noch ihr benanntes Element;
   die Leisten-Familie liefern Anordnung, Glas-Effekt, Warenkorb-Stil, Countdown-Stil und
   obere Kante (deklariert in der Kategorie-Beschreibung). */
body.v2 #stickyfooter { height: auto !important; line-height: 1 !important; padding-top: var(--tp-sticky-pad-top, 8px); padding-bottom: max(var(--tp-sticky-pad-bottom, 12px), env(safe-area-inset-bottom)); }
/* F2: Der zusaetzliche Innenabstand fuer den Wisch-Balken macht die Leiste hoeher — in die Reserve aufnehmen. */
body.v2 { --tp-sticky-safe: env(safe-area-inset-bottom, 0px); }

/* ============ Fussbereich ============ */
/* — footer.layout = "einzeilig" — */
@media (min-width: 768px) {
  body.v2 footer .footer-wrappers { display: flex; flex-wrap: wrap; align-items: center; column-gap: 28px; row-gap: 6px; }
  body.v2 footer .footer-wrappers ul.list-inline { float: none; margin: 0; }
  body.v2 footer .logowrapper { float: none; margin: 0; }
  body.v2 footer img.footer-system-logo { margin: 0; }
}

/* — footer.link-stil = "hover-unterstrichen" — */
body.v2 footer ul.list-inline > li:not(.dropup) > a { text-decoration: none; }
body.v2 footer ul.list-inline > li:not(.dropup) > a:hover, body.v2 footer ul.list-inline > li:not(.dropup) > a:focus-visible { text-decoration: underline; text-underline-offset: 3px; }

/* — footer.abstaende = "kompakt" — */
body.v2 footer { padding-top: 14px; padding-bottom: 14px; }
body.v2 footer ul.list-inline { margin-bottom: 4px; }

/* — footer.text-groesse = "klein" — */
body.v2 footer { font-size: 13px; }

/* — footer.sprachwahl-stil = "dezent" — */
body.v2 footer li.dropup > a { opacity: 0.7; transition: opacity 150ms ease; }
body.v2 footer li.dropup > a:hover, body.v2 footer li.dropup > a:focus-visible, body.v2 footer li.dropup.open > a { opacity: 1; }

/* — footer.widerruf-button = "als-link" — */
/* W-3 (Runde W): Der Arm unten (0,3,2) verlor zwei Spezifitaetsduelle und hielt das Versprechen
   nur halb. Die Fusslink-Familie body.v2 footer ul.list-inline > li:not(.dropup) > a (0,3,5) nahm
   den Unterstrich zurueck, die Knopfgroesse body.v2 .btn:not(.btn-sm):not(.btn-xs):not(.btn-lg)
   (0,5,1) die Polsterung. Gemessen auf fixture/organizer-grid: elegant-serif 6866 -> 3519 px2 OHNE
   Unterstrich, tech-minimal 5249 -> 2568 OHNE, pastell-soft 8114 -> 7666 mit Polster 10/20 px.
   Der zweite Arm laeuft die echte Bauform des Fusslinks ab — a.btn.btn-default in
   footer ul.list-inline > li, in allen DOM-Abzuegen identisch — und kommt damit auf (0,5,4).
   Er schlaegt beide Gegner OHNE !important-Keule und OHNE eine weitere :not()-Ausnahme; jede
   weitere Ausnahme haette die Spezifitaet der Familie gehoben und einen spaeteren Rueckschalter
   derselben Familie geraeuschlos gekippt (Lehre G-2). Faellt .btn-default im Shop je weg, greift
   wieder der erste Arm — die Option verliert dann Schaerfe, faellt aber nicht aus. */
body.v2 footer .btn[onclick*="start_revoc"], body.v2 footer ul.list-inline > li > .btn.btn-default[onclick*="start_revoc"] { background: transparent !important; border: 0; padding: 0; box-shadow: none; color: inherit; text-decoration: underline; text-underline-offset: 3px; }
body.v2 footer .btn[onclick*="start_revoc"]:hover, body.v2 footer .btn[onclick*="start_revoc"]:focus-visible, body.v2 footer ul.list-inline > li > .btn.btn-default[onclick*="start_revoc"]:hover, body.v2 footer ul.list-inline > li > .btn.btn-default[onclick*="start_revoc"]:focus-visible { text-decoration-thickness: 2px; background: transparent !important; }
body.v2 footer .btn[onclick*="start_revoc"]:focus-visible, body.v2 footer ul.list-inline > li > .btn.btn-default[onclick*="start_revoc"]:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
body.v2 footer .btn[onclick*="start_revoc"]:active { opacity: 0.8; }

/* ============ Dialogfenster ============ */
/* — modals.chrome = true — */
body.v2 .modal-content { border-radius: var(--tp-radius-panel, 6px); box-shadow: var(--tp-shadow-panel, 0 6px 24px rgba(0,0,0,0.2)); }

/* — modals.radius-detail = 8 — */
body.v2 .modal-content { border-radius: 8px; }

/* — modals.close-button = "ghost-quadrat" — */
body.v2 .modal-header .close { display: inline-flex; align-items: center; justify-content: center; float: right; width: 36px; height: 36px; padding: 0; margin: -7px -6px 0 12px; border: 1px solid color-mix(in srgb, currentColor 45%, transparent); border-radius: min(var(--tp-radius-button, 6px), 10px); background-color: transparent; color: inherit; text-shadow: none; font-size: 18px; line-height: 1; opacity: 0.8; }
body.v2 .modal-header .close:hover, body.v2 .modal-header .close:active { background-color: color-mix(in srgb, currentColor 12%, transparent); color: inherit; opacity: 1; }
body.v2 .modal-header .close:focus { color: inherit; }
body.v2 .modal-header .close:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; opacity: 1; }

/* — modals.width = "wide" — */
@media (min-width: 768px) { body.v2 .modal-dialog:not(.modal-sm) { width: 90%; max-width: 860px; } }

/* — modals.backdrop = "darker" — */
body.v2 .modal-backdrop.in { opacity: 0.7; }

/* — modals.padding = "airy" — */
body.v2 .modal-header { padding: 20px 24px; }
body.v2 .modal-body { padding: 24px; }
body.v2 .modal-footer { padding: 16px 24px; }

/* — modals.footer-buttons = "stacked-mobile" — */
@media (max-width: 767px) { body.v2 .modal-footer .btn { display: block; width: 100%; margin: 8px 0 0; } body.v2 .modal-footer .btn:first-child { margin-top: 0; } }

/* — modals.zindex-paket = true — */
body.v2 .modal { z-index: 1300; }
body.v2 .modal-backdrop { z-index: 1290; }
body.v2 .upc-modal { z-index: 1400; }
body.v2:has(.navbar.navbar-default) .navbar-nav .modal, body.v2:has(.navbar.navbar-default) #modal_invoice { position: fixed; top: 0; right: 0; bottom: 0; left: 0; margin: 0; }

/* ============ Effekte & Bewegung ============ */
/* — effects.transition-base = "standard" — */
@media (prefers-reduced-motion: no-preference) {
  body.v2 .btn, body.v2 a, body.v2 .form-control, body.v2 .paymentmethod, body.v2 .panelx {
    transition: background-color var(--tp-transition-base), color var(--tp-transition-base), border-color var(--tp-transition-base), box-shadow var(--tp-transition-base), opacity var(--tp-transition-base), transform var(--tp-transition-base), filter var(--tp-transition-base);
  }
}

/* — effects.button-press = true — */
@media (prefers-reduced-motion: no-preference) {
  body.v2 .btn:active:not(:disabled):not(.disabled) {
    transform: translateY(1px);
  }
}

/* — effects.langtext-schutz = true — */
/* G-F1 (Runde G, Rubrik 2/10): overflow-wrap:break-word allein trennt mitten im Wort und ohne
   Trennstrich ("SOMMERNACHTSKONZE|RT" auf 7 von 12 Presets bei 375px). hyphens:auto trennt bei
   lang="de" an echten Silbengrenzen MIT Trennstrich; break-word bleibt als Notbremse fuer Codes
   ohne Trennstelle. */
body.v2 .wrap .items .headline h3, body.v2 .items .headline h3, body.v2 .cover-content h2 { -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; }
/* J1-10 (Runde J, Rubrik 2/10, bei der Abnahme gefunden): Die Erfolgsseite nennt die Bestell-Mailadresse in einem <strong>. Ein Wort ohne Trennstelle sprengte bei 320px in 11 von 12 Presets und bei minimal-brand schon bei 375px die Seite (scrollWidth 384 gegen innerWidth 375). Mailadressen und Buchungscodes haben keine Silbengrenze — hier zaehlt nur die Notbremse. */
body.v2 .jumbotron, body.v2 .jumbotron p, body.v2 .jumbotron strong, body.v2 .jumbotron a:not(.btn) { overflow-wrap: break-word; }
/* Z10-F7 (Runde Z10): Der Umbruchschutz zerlegte die Gruppenueberschrift der
   Weiterverkaufsseite mitten im Wort ("CAMPI/NG/WEEK/END"): festival-dark 7 Zeilen statt 3
   bei 375 px, festival-dark und mono-kontrast 2 statt 1 bei 1280 px. Die Ueberschrift
   braucht ihn nicht — neben ihr steht eine LEERE Spalte, in die der Text ausweichen darf
   (Serienverhalten: schon nackt tritt er 26 px hinein). hyphens: manual muss mit, sonst
   greift bei lang="de" sofort hyphens:auto und stellt den Silbenschutt wieder her. */
body.v2:has(.navbar.navbar-default) .well.groupby h4.well-label { overflow-wrap: normal; -webkit-hyphens: manual; hyphens: manual; }
/* I-3 (Runde I, Rubrik 2): Umbruchschutz fuer Betraege und Ueberlaufschutz der Kaufbox
   gehoeren zum Strukturschutz, nicht zu einer Stiloption. Doppelt gesetzt ist unschaedlich. */
body.v2 .price_quantity_box .show_price, body.v2 .price_quantity_box .show_price font, body.v2 .price_quantity_box .show_price strike, body.v2 .price_quantity_box .show_price s { white-space: nowrap; }
body.v2 .price_quantity_box > * { min-width: 0; max-width: 100%; }
/* J1-1 (Runde J, Rubrik 2/5, KRITISCH): Die Serie deckelt die Artikelbeschreibung auf
   `body.v2 .wrap .wrap_content .well .items article { max-height: 7em }` — gedacht als Klemme fuer
   das Mehr-anzeigen-Skript (readmore.js, setzt das Attribut data-readmore). Laeuft das Skript nicht
   (oder ist der Text kuerzer als seine Klemme), bleibt der Text sichtbar ueber den Kasten hinaus
   stehen: bei 375px stapeln sich Beschreibungs- und Kaufspalte, und die Preisbox legt sich auf die
   letzte Zeile. Gemessen 12-49px Ueberlappung in ALLEN 12 Presets; "Ticket gilt zugleich als
   Nahverkehrsfahrschein" endete als Torso. Der nackte Shop zeigt denselben Defekt, dort nur
   schwaecher, weil die Preisbox kaum Flaeche hat. Deckel nur dort aufheben, wo das Skript NICHT
   arbeitet — mit data-readmore bleibt die Klemme des Shops unangetastet. */
body.v2 .wrap .wrap_content .well .items article:not([data-readmore]) { max-height: none; }
/* J1-2 (Runde J, Rubrik 2/3): Bootstrap gibt jedem .btn white-space:nowrap. In der schmalen
   Kaufspalte bei 768px (col-sm-4 ~ 200px) ist "IN DEN WARENKORB" in Versalien breiter als seine
   Knopfflaeche — die Randbuchstaben standen ausserhalb der Pille auf dem Seitengrund (gemessen
   3-12px Ueberhang in 6 von 12). Der Haupt-CTA darf umbrechen, aber nie ueberlaufen. */
body.v2 .price_quantity_box .show_button .btn, body.v2 .article-box .show_button .btn { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; }
/* J2-A (Runde J, Durchgang 2, RUBRIC 3 "Ausrichtung" + 4 "Konsistenz"): J1-2 gab dem Kauf-Knopf
   white-space:normal, damit er bei 768px nicht mehr aus seiner Flaeche laeuft. Damit durfte er
   aber auch dort umbrechen, wo noch Platz gewesen waere: bei 1280px fehlten elegant-serif 1px
   und festival-dark 6px auf die Zeile (Textbreite 179 gegen 178px Innenbreite) — aus dem
   wichtigsten Knopf der Seite wurde ein zweizeiliger, 60px hoher Block neben einem einzeiligen
   42px-Mengenfeld. Umbrechen ist die Notbremse, nicht der Normalfall: seitlicher Innenabstand,
   Laufweite und Schriftgrad geben vorher nach. Bei 1280px bleibt die Schrift 16px (clamp-Obergrenze),
   erst in der schmalen Tablet-Spalte sinkt sie. Messreihe scratchpad/j2/cta.js:
   einzeilig 10/12 -> 12/12 bei 1280px, 3/12 -> 11/12 bei 992px, 3/12 -> 12/12 bei 768px. */
/* Z14-ALL-1 + Z14-MU-1 Teil A2 (Runde Z14, CEO-Detailfeedback DOCX 2026-08-15, Bildbelege
   scratchpad/z14/feedback/unpacked/word/media/310ff213-8319-4db2-b541-a3471f881dee.png (Select-Kante
   x=201 gegen CTA-Kante x=196 = 5-6 px Versatz) und 28336e90-a3b5-465e-922f-7442226af1d9.png):
   CEO: "Mir faellt in ALLEN Vorlagen auf, dass das Anzahl-Dropdown nicht auf einer Linie liegt wie
   der Warenkorb-Button (rechter Abstand zum Rand der Card)." Gemessen dSelCta +6,0 px in 12/12 auf
   shop-artikel, cover-image, cover-buttonbar, accordions, carousel, cart-filled, extras UND
   Sponsorenshop @1280 (MyTicketportal und Organizer fuehren keine .price_quantity_box: 0 Treffer auf
   13 Fixtures). Ursache ist der Wrapper-Einzug der Zeile darueber: der Kauf-Knopf sass 6 px innerhalb
   der Kaufboxkante, das Mengenfeld 0 px (dessen Traeger .show_quantity bekommt padding: 0 aus
   checkout.kaufbox-layout). RUECKHOLUNG, keine Konzeptaenderung: der nackte Shop richtet Select, Knopf
   und Preis auf EINER Achse aus, shots/rundeB/adventure-fixed_i1_cart-filled__buybox.png zeigt
   Select-Kante x=231 == Knopfkante x=231, und _e5vor_/_j1vor_ liefern dSelCta 0,0 in 12/12 (heute 6,0)
   — der Versatz ist eine Regression aus Runde J, kein Merkmal einer Vorlage; das Original war in ALLEN
   12 deckungsgleich, es geht also keine Vielfalt verloren (Kernregel 7). Der Einzug wandert darum vom
   Wrapper in den Knopf: der Knopf misst die volle Kaufbox-Innenbreite und trifft damit die
   Select-Kante, der Textraum bleibt bitgleich (vorher Wrapper 6+6 und .btn 6+6, jetzt Wrapper 0+0 und
   .btn 12+12 = beide 24 px). J2-A (einzeiliger CTA) bleibt unangetastet — nachgemessen einzeilig 12/12
   bei 768, 992 und 1280 px auf 9 Flaechen (144 Knopfpaare je Breite, 0 neue Umbrueche); pastell-soft
   gewinnt bei 768/992 sogar eine Zeile zurueck (Knopf 67,7 -> 44,8 px), weil dort ein staerkeres
   Knopfpolster von 20 px bindet und der Knopf 12 px breiter wird. VERWORFEN (gemessen, nicht
   vermutet): 6-px-Polster am Select-Wrapper (.show_quantity padding 0 -> 0 6px) — erreicht dieselbe
   Kante, kippt aber die Kaufzeile in 6 von 7 menge-rechts-Vorlagen (+50 px Kastenhoehe) =
   M-F1-Rueckfall. Die 12-px-Verlagerung gilt NUR fuer den Kaufbox-Arm: ein .article-box .show_button
   OHNE .price_quantity_box (der einzelne CTA auf stock-states und modal, je 1 sichtbarer Traeger) hat
   keinen Wrapper-Einzug, den er abgeben koennte — dort bleiben 6 px, sonst verliert dieser Knopf 12 px
   Textraum ohne Gegenwert (gemessen: 0 Aenderung an 12 lone CTAs bei 375/768/992/1280). */
@media (min-width: 768px) {
  body.v2 .price_quantity_box .show_button { padding-left: 0; padding-right: 0; }
  body.v2 .price_quantity_box .show_button .btn, body.v2 .article-box .show_button .btn { padding-left: 6px; padding-right: 6px; letter-spacing: normal; font-size: clamp(13.5px, 0.55vw + 9.2px, 16px); }
  body.v2 .price_quantity_box .show_button .btn { padding-left: 12px; padding-right: 12px; }
}
/* J1-5 (Runde J, Rubrik 3/4): Gutscheinfeld und Einloesen-Knopf sind eine geteilte Pille (radius 999px 0 0 999px bzw. 0 999px 999px 0). Waehlt ein Rezept groessere Knoepfe (buttons.groesse: gross), wuchs nur der Knopf: 44,8px gegen ein 34px hohes Feld, 10,8px Ueberstand nach unten — die beiden Haelften passten sichtbar nicht zusammen. Ab 768px darum eine echte Flex-Zeile mit align-items:stretch, in der das Feld die Hoehe vorgibt; unter 768px stapelt die Serie die Gruppe ohnehin (BK13), dort bleibt alles unveraendert. Strukturschutz gehoert nicht in die Stiloption checkout.coupon-style — die setzen nur 4 von 12 Rezepten (Regel 13). */
@media (min-width: 768px) {
  body.v2 .input-group.input-split { display: flex; align-items: stretch; }
  body.v2 .input-group.input-split > .form-control { flex: 1 1 auto; min-width: 0; height: auto; }
  body.v2 .input-group.input-split > .input-group-btn { flex: 0 0 auto; width: auto; display: flex; }
  body.v2 .input-group.input-split > .input-group-btn > .btn { height: auto; padding-top: 0; padding-bottom: 0; display: inline-flex; align-items: center; }
}
/* J3-G (Runde J3, RUBRIC 2 "Umbrueche & Ueberlauf", 10 "Mobil"): Bei 320px lief die
   Kopfbereich-Knopfgruppe (Info / Hilfe / Warenkorb (3)) 6px ueber den rechten Bildschirmrand —
   die rechte Kante des Warenkorb-Knopfes fehlte einfach. Ursache ist nicht die Serie, sondern
   unsere Typografie: mit Versalien und 0,72px Laufweite misst die Gruppe 308-311px statt 230px
   (nackt) in einem 290px breiten Kasten. Dasselbe bei "Andere Zahlungsart waehlen" (299px in
   290px). Betroffen adventure-fixed und elegant-serif, latent jede Vorlage mit Versalknoepfen.
   Zuerst gibt die Laufweite nach (die reine Dekoration, Regel 20: vor der Notbremse eine
   nachgebende Groesse), danach greifen max-width und ein kontrollierter Umbruch als Notbremse.
   Die Beschriftungen bleiben in voller Groesse lesbar. */
body.v2 #content .btn, body.v2 .cover .btn { max-width: 100%; }
/* N-3 (Runde N, 2026-07-29): Der Deckel oben schuetzt vor Querscrollen, aber Bootstrap
   haelt .btn auf white-space:nowrap — im MyTicketportal traten die Beschriftungen der
   Aktionsknoepfe dadurch seitlich aus der Flaeche heraus (gemessen portal-teams:
   stadion-energie 214 gegen 197 px, mono-kontrast 207 gegen 196 px; nackt 197 == 197).
   Dieselbe Behandlung wie bei .jumbotron .btn-box .btn: umbrechen statt austreten.
   Bewusst nur auf Portal-Klassen — link2details, link2resale und .box-footer .btn
   kommen im Ticketshop nicht vor, dort aendert sich kein Pixel. */
body.v2 .btn.link2details, body.v2 .btn.link2resale, body.v2 .box-footer .btn, body.v2 .quick_form .btn, body.v2 .box-inner .btn-box .btn { white-space: normal; overflow-wrap: break-word; }
/* B1 (Runde X, RUBRIC 3 "Ausrichtung" / 4 "Konsistenz"): N-3 (Zeile darueber) gab den
   Portal-Aktionsknoepfen white-space:normal — richtig, sonst treten lange Beschriftungen
   seitlich aus ihrer Flaeche heraus. Der Umbruch traf aber auch Beschriftungen, denen nur
   wenige Pixel fehlten. In der Knopfsaeule der Bestelluebersicht stehen zwei .link2details
   uebereinander, beide auf .w-75 (feste Breite) — brach nur einer um, stand ein 34px hoher
   neben einem 54px hohen Knopf. Gemessen auf fixture/portal-order: 26 von 130 Zweiergruppen
   ungleich (elegant-serif 8, adventure-fixed 6, mono-kontrast/neon-nacht/stadion-energie je 4),
   im nackten Shop 0 von 10 — der haelt nowrap und braucht die Notbremse nicht, weil seine
   Beschriftungen 30-80px schmaler sind. Fehlbetrag der Kippfaelle: 1-26px, erzeugt von
   Versalien und Laufweite. Darum wie bei J2-A (Regel 20): zuerst gibt die Dekoration nach,
   der Umbruch bleibt Notbremse. Die .w-75-Flaeche aendert sich dabei um 0px — nur der Text
   bekommt Luft, sichtbar wird allein die engere Laufweite. */
body.v2 .btn.link2details, body.v2 .btn.link2resale { letter-spacing: normal; padding-left: 6px; padding-right: 6px; }
/* B1, zweite Gruppe (keine Saeule): die zwei Knoepfe der Personalisierungsmaske stehen
   NEBENeinander in je einem .col-md-4 (Bootstrap 33,33 %), die dritte Spalte bleibt leer.
   Der nackte Shop laesst den laengeren Knopf ueber seine Spalte in diese Leerflaeche
   hinausragen und bleibt einzeilig; unser max-width:100% (J3-G) klemmt ihn in die Spalte,
   wo er umbricht — corporate-blau 34/54 gegen nackt 34/34. Hier gibt nicht die Schrift nach,
   sondern die Flaeche: die beiden Spalten duerfen sich am Inhalt messen (shrink-to-fit des
   Floats), dann sind beide Knoepfe wieder einzeilig und gleich hoch, und max-width:100%
   bleibt als Ueberlaufschutz aktiv. Unter 992px ist die Regel folgenlos — dort hat
   .col-md-4 weder Breite noch Float. Anker .divider + .row statt :has(), damit die Option
   risk:safe bleibt (gemessen: 1 Treffer in allen 26 Fixtures). */
body.v2 .quick_form .divider + .row > .col-md-4 { width: auto; }
@media (max-width: 480px) {
  body.v2 .cover .btn-group, body.v2 .cover .btn-group-sm { flex-wrap: wrap; max-width: 100%; }
}
@media (max-width: 400px) {
  body.v2 #content .btn, body.v2 .cover .btn { letter-spacing: normal; }
  body.v2 #content .btn:not(.input-group .btn):not(.input-group-btn .btn), body.v2 .cover .btn { white-space: normal; -webkit-hyphens: auto; hyphens: auto; overflow-wrap: break-word; }
}

/* J4-A (Runde J4, RUBRIC 2/8/10, KRITISCH): Unter 768px stapelt die Serie die Gutschein-Zeile (BK13); der Wrapper span.input-group-btn behaelt dabei Bootstraps width:1% und ist nur ~3px breit. Der nackte Shop ueberlebt das nur zufaellig, weil sein Knopf (max-width:none, inline-block) aus dem 3px-Wrapper herausragt und trotzdem voll gemalt wird. Unser J3-G-Schutz (#content .btn { max-width:100% }) loeste gegen genau diesen 3px-Wrapper auf und klemmte den Einloesen-Knopf auf 26px (pastell-soft 42px) — die Beschriftung lief als Ueberlauf weiter: weiss auf heller Karte (mono-kontrast, tech-minimal, elegant-serif, sport-clean) bzw. dunkel auf dunkler Karte (neon-nacht) unlesbar, Kaufabbruch-Risiko im Bezahlschritt. Gemessen 11 von 12 Presets (nur warm-craft via forms.coupon-pill-Flex verschont), nackter Shop 92-118px. Goldene Regel 9: der J3-G-Fix tauschte einen Defekt gegen einen anderen. width:auto gibt dem Wrapper die volle Zeile; der Knopf misst wieder seinen Inhalt, und max-width:100% bleibt als Ueberlaufschutz aktiv. Ab 768px uebernimmt die J1-5-Flexzeile. */
@media (max-width: 767px) {
  body.v2 .input-group.input-split > .input-group-btn { width: auto; }
}
/* Z13-E-V-E3-2 (GERING, Runde Z13-E, Welle B; herabgestuft von MITTEL): Die Bestell-Mailadresse
   der Erfolgsseite passt bei 375 px in KEINER der sieben mehrzeiligen Vorlagen auf eine Zeile
   (drei Messwege: noetig 301,0-343,5 px gegen 297-315 px verfuegbar) — in drei Vorlagen
   (pastell-soft, stadion-energie, tech-minimal) blieb dadurch ein einzelnes Waisenzeichen
   allein in Zeile 2, in minimal-brand auch bei 414 px. Wie bei J2-A/B1 und Regel 20 gibt vor
   der Notbremse die Dekoration nach: -0,2 px sind -0,011 em auf 17,6 px fett und in
   Originalgroesse nicht wahrnehmbar (3x-Zoom-Beleg scratchpad/z13/e/fix/bilder/
   K4_mail375_*_{VOR,KAND}.png), reichen aber ueber die Messerschneide von ~6 px Viewport.
   Gemessen (scratchpad/z13/e/fix/g4d_waisen.json, 320/375/414 px x 13 Spalten): Waisenzeichen
   4 -> 0, pastell-soft/stadion-energie/tech-minimal 2 -> 1 Zeile, minimal-brand @414 2 -> 1;
   die fuenf einzeiligen Vorlagen (corporate-blau, elegant-serif, festival-dark, sport-clean,
   warm-craft) und der nackte Shop bleiben unveraendert, kein neues Querscrollen. Bei neon-nacht
   wandert der Punkt von Zeile 2 nach Zeile 1 (".de" -> "de") — gleichwertig, kein neues Waisen-
   zeichen. Ausdruecklich NICHT gewaehlt: mobiles Innenpolster auf den Nacktwert zwingen (macht
   drei NEUE Waisen), Schriftgrad senken (neue Waise bei minimal-brand; der Grad ist in 12/12
   bitgleich zum nackten Shop), J1-10 lockern (ohne Notbremse laeuft minimal-brand vom Schirm).
   Der danger-Arm ist Vorsorge derselben Kastenfamilie — die Fixture fuehrt dort keine Adresse. */
@media (max-width: 480px) {
  body.v2 .jumbotron-success p strong,
  body.v2 .jumbotron-danger p strong { letter-spacing: -0.2px; }
}

/* ============ MyTicket-Portal ============ */
/* — portal.tab-navigation = "dezent" — */
body.v2:has(.navbar.navbar-default) .navbar.navbar-default { background-color: transparent; color: var(--tp-color-body-text, inherit); border: 0; box-shadow: none; }
body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li > a { background-color: transparent; padding: 10px 12px; transition: color var(--tp-transition-base, 150ms ease); }
body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li > a:hover, body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li > a:focus { background-color: transparent; color: var(--tp-color-primary-hover, #d63f00); }
/* W-12 (Runde W): Die rohe Hauptfarbe als einziges Aktivmerkmal fiel unter AA — gemessen auf
   fixture/portal-order: minimal-brand 4,32 : 1 (rgb(197,22,214) auf 245,245,245), also unter 4,5
   UND unter dem nackten Shop (6,03). Bei pills und unterstrich traegt der aktive Reiter zusaetzlich
   Flaeche bzw. Unterstrich; hier ist die Farbe der ganze Hinweis und muss darum lesbar sein.
   70 % Hauptfarbe gegen die Textfarbe gemischt: minimal-brand 4,32 -> 6,23 (damit auch ueber dem
   nackten Shop, nicht nur ueber AA), elegant-serif 7,69 -> 9,24. 78 % waeren mit 5,65 zwar ueber AA,
   aber weiter unter dem nackten Shop geblieben — darum gemessen nachjustiert. Der Ton bleibt erkennbar die Marke (minimal-brand rgb(153,31,165) statt 197,22,214). */
body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li.active > a, body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li.active > a:hover, body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li.active > a:focus { background-color: transparent; color: color-mix(in srgb, var(--tp-color-primary, #ff4d06) 70%, currentColor); font-weight: 700; }
body.v2:has(.navbar.navbar-default) .navbar.navbar-default .navbar-nav > li > a:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }

/* — portal.ticket-liste = "luftig" — */
body.v2:has(.navbar.navbar-default) .data-wrapper { padding: 18px 20px; }
body.v2:has(.navbar.navbar-default) .data-wrapper .line { padding: 6px 0; line-height: 1.6; }
body.v2:has(.navbar.navbar-default) .secwrap .section-wrapper { padding: 16px 0; }
body.v2:has(.navbar.navbar-default) .secwrap .section-left, body.v2:has(.navbar.navbar-default) .secwrap .section-right { line-height: 1.6; }
body.v2:has(.navbar.navbar-default) .ticket_details { margin-bottom: 16px; }

/* — portal.download-cta = "vollbreit-mobil" — */
body.v2:has(.navbar.navbar-default) .box-footer .btn, body.v2:has(.navbar.navbar-default) .btn.link2details { padding: 10px 22px; font-size: 16px; font-weight: 600; border-radius: var(--tp-radius-button, 4px); }
body.v2:has(.navbar.navbar-default) .box-footer .btn:focus-visible, body.v2:has(.navbar.navbar-default) .btn.link2details:focus-visible { outline: 2px solid var(--tp-color-primary, #ff4d06); outline-offset: 2px; }
@media (max-width: 767px) {
body.v2:has(.navbar.navbar-default) .box-footer .btn, body.v2:has(.navbar.navbar-default) .btn.link2details { display: block; width: 100%; text-align: center; margin-top: 6px; }
}

/* — portal.status-zeilen = "dezent" — */
body.v2:has(.navbar.navbar-default) .secwrap .section-left { opacity: 0.7; font-size: 0.88em; text-transform: uppercase; letter-spacing: 0.04em; }


/* ======== ANGEHAENGT: v0final-extra.css (Serien-Konstanten, plain) ======== */
/* =====================================================================
   VORLAGE 0 — ENDFASSUNG "SOCKEL" · SERIEN-KONSTANTEN-SCHICHT
   Wird HINTER dem Preset-CSS geladen. Alle Regeln sind PLAIN.
   Kein !important auf einer Farb-Property (KORRIDOR §6.3).
   Herkunft: v0r2tief-extra.css (Rundensieger, Achsen A1..A21) +
   die Auflagen der sieben Jurys, des TECHNIK-CHECKs und des CEO
   (Kopf-Zaesur) als Achsen Z1..Z8 und N1..N12.
   Belegte Klassen: GESCHUETZT-FREI (KORRIDOR §2) bzw. FREI (§3.1/3.2/3.4/3.7).
   ===================================================================== */

/* ---------------------------------------------------------------------
   Z14-FB1 — DIE PALETTE HAENGT AN DEN ROLLENFARBEN, NICHT AN DER VORLAGE.
   Befund (FEEDBACK.md Punkt 1, in Z14 ueber alle 12 Kundenvorlagen
   nachgemessen): die --v0t-*-Toene waren fest verdrahtet. Unter den vier
   dunklen Kundenvorlagen blieb das Fortschrittsband in 12/12 Faellen
   rgb(225,231,238) — Kontrast Band/Seite 14,55-14,70:1, also die einzige
   helle Grossflaeche im dunklen Shop (GEO-B2); unter neon-nacht gewann die
   Kundenvorlage zusaetzlich die BANDSCHRIFT (weiss) und liess die Flaeche
   stehen: 1,25:1 (GEO-B1, halboffenes Paar nach KORRIDOR §4.5). Dieselbe
   Mechanik trug fuenf helle Haarlinien auf dunkle Karten (GEO-B3).

   Bauform: jede Rollen-gebundene Zeile ist
       var(--tp-color-<rolle>, <bisheriger v0-Ton>)
   Der bisherige Ton ist der RUECKFALL (Lehre 56: ein Fix, der etwas
   entfernt, muss sagen, worauf zurueckgefallen wird). Folge, gemessen:
   Vorlage 0 ALLEIN bleibt bitgleich — sie definiert selbst nur
   --tp-color-primary/-contrast, keine der Rollenfarben. Liegt eine
   Kundenvorlage darueber, erben Band, Karte, Kante, Fuss und Kaufbox
   deren Flaechen. Custom-Properties werden bei der Berechnung aufgeloest,
   nicht beim Parsen — die Ladeposition (Vorlage 0 VOR der Kundenvorlage)
   spielt hier also keine Rolle.

   PAAR-REGEL (KORRIDOR §4): jede gebundene Flaeche traegt ihre Schrift mit.
     Band     --v0t-band      <-> --v0t-tief-500 (body-bg / body-text, s. FB1-C)
     Karte    --v0t-karte     <-> Serienschrift auf panel-bg
     Fuss     --v0t-fuss      <-> --v0t-fusstext (footer-bg / footer-text)
     Grund    --v0t-grund     <-> body.v2 color (body-bg / body-text)

   FB1-C — EINE VOLLBREITE BAHN IST KEINE KARTE (Gegenpruefungsbefund B1,
   2026-08-23). Die erste Bindung haengte das Fortschrittsband an die
   PANEL-Rolle surface2. Unter sport-clean traegt die Kundenvorlage
   body-bg #0b142c MIT panel-bg #ededed und surface2 #ffffff — eine
   "dunkle Seite, helle Karten"-Vorlage. Das Band blieb dort weiss,
   K(Band/Seite) 18,25:1, also weiter genau der Befund aus FEEDBACK.md
   Punkt 1. Die damalige Entlastung ("das Band traegt exakt dieselbe
   Flaeche wie jede Karte") war doppelt falsch: gemessen war das Band
   #ffffff und die Karte #ededed, und geometrisch ist das Band eben KEINE
   Karte — es laeuft per box-shadow 0 0 0 100vmax randlos ueber die volle
   Fensterbreite, waehrend die Karten eingerueckte Panels mit Radius sind.
   ENTSCHEID: eine Flaeche, die von Fensterkante zu Fensterkante laeuft,
   traegt den SEITENGRUND, nicht eine Panel-Rolle. Band und alles, was auf
   ihm sitzt (Bandschrift, Stepper-Tinte, Stepper-Polaritaet), haengen
   deshalb am Paar body-bg/body-text. Rueckfall unveraendert — Vorlage 0
   ALLEIN behaelt ihr um eine Stufe abgesetztes Band #E1E7EE, weil sie
   selbst keine Rollenfarbe definiert.
   NICHT gebunden und damit weiter Identitaet von Vorlage 0:
     --v0t-tief-900/-800 (Kopfflaeche, Kaufleiste — dunkle Polaritaet ist
     Saeule 1 der Charta; die Kundenvorlagen ueberschreiben #stickyfooter
     ohnehin mit !important), --v0t-meta (Meta-Zeile als eigene Stufe),
     die Bedeutungsfarben --v0t-gruen(-d/-h) und --v0t-info(-d)
     (KORRIDOR §3.3: Farbwinkel bleibt), die weisse Kopf-Knopfgruppe (Erbe K2).

   ACHTUNG, KOMMENTARDISZIPLIN (Befund Z14-FB1-B, teuer bezahlt): in diesem
   Absatz stand bis hierher die Kurzform "gruen<stern><schraegstrich>info" —
   also die Zeichenfolge, die einen CSS-Kommentar SCHLIESST. Der Kommentar
   endete damit zwoelf Zeilen zu frueh, der Resttext wurde zu Regelmuell und
   der CSS-Parser verwarf beim naechsten "}" den GESAMTEN :root-Block: alle
   21 --v0t-*-Token waren leer, die Meta-Zeile fiel auf den Grundtext
   rgb(44,51,60) auf dunklem Kopf zurueck (1,53:1 statt 11,7:1), Band, Karte,
   Kante, Fuss und Kaufbox verloren ihre Toene. Gemessen an der echten
   K3-Position, nicht vermutet. Seither prueft Waechter-Arm 4 jede
   Kommentarklammer; Sternchen-Platzhalter werden ausgeschrieben.
   --------------------------------------------------------------------- */
:root {
  --v0t-tief-900: #12161C;   /* Kopf unten, tiefster Ton   — IDENTITAET */
  --v0t-tief-800: #1A2028;   /* Kopf oben, Kaufleiste      — IDENTITAET */
  /* Stepper sitzt AUF dem Band und folgt ihm darum ueber body-text (FB1-C). */
  --v0t-tief-700: var(--tp-color-body-text, #262E38);
  --v0t-tief-500: var(--tp-color-body-text, #5E6773);
  --v0t-linie-2:  var(--tp-color-border, #C7D0DA);
  --v0t-band:     var(--tp-color-body-bg, #E1E7EE);
  --v0t-fuss:     var(--tp-color-footer-bg, #DCE3EB);
  --v0t-band-k:   var(--tp-color-border, #D2DAE3);
  --v0t-grund:    var(--tp-color-body-bg, #EEF1F5);
  --v0t-karte:    var(--tp-color-panel-bg, #FFFFFF);
  --v0t-kante:    var(--tp-color-border, #DCE3EA);
  /* Begrenzung eines BEDIENELEMENTS (WCAG 1.4.11: >= 3 : 1 gegen die
     Nachbarflaeche) — dieselbe Rollenkette wie --v0t-kante, aber mit einem
     tragfaehigen EIGENEN Rueckfall: #8C8E92 ist ACHROMATISCH im Sinne des
     Waechters (max−min = 6) und misst 3,33 : 1 auf der Kartenflaeche, wo
     #DCE3EA nur 1,29 : 1 traegt. Ein waermerer oder kuehlerer Ton haette
     eine Korridor-Freigabe gebraucht; die Begrenzung eines Bedienelements
     ist aber kein Akzent, sondern Handwerk — sie bleibt unbunt.
     Setzt eine Kundenvorlage
     oder Manage --tp-color-border, gilt DEREN Wert unveraendert weiter —
     die Zeile fasst ausschliesslich den Punkt an, den Vorlage 0 besitzt
     (Befund B-4). Verwendet nur an den drei Filterfeldern (F2-1). */
  --v0t-feldkante: var(--tp-color-border, #8C8E92);
  --v0t-kaufbox:  var(--tp-color-surface2, #F2F5F9);
  --v0t-gruen:    #3E7C55;   /* Bedeutungsgruen, entsaettigt           */
  --v0t-gruen-d:  #336846;
  --v0t-gruen-h:  #4F8C61;
  --v0t-info:     #3F7383;   /* Bedeutungsblau, entsaettigt            */
  --v0t-info-d:   #345E6B;
  --v0t-meta:     #C3CDD9;   /* Meta-Zeile im Kopf (eigene Stufe)      */
  --v0t-fusstext: var(--tp-color-footer-text, #2A323C);
}

/* ---------------------------------------------------------------------
   A4 — ZWEI-TON-GRUND (B10). body = GESCHUETZT-FREI (KORRIDOR §2).
   Karte absolut deklariert, nicht als "Weiss, das uebrig bleibt".
   --------------------------------------------------------------------- */
body.v2 {
  background-color: var(--v0t-grund);
  color: var(--tp-color-body-text, #2C333C);
}
/* ---------------------------------------------------------------------
   A18/C4 — DER PRIMAERTON IST EIN NOTNAGEL, KEINE SETZUNG.
   Ohne gesetzten colors.primary-Regler fallen SECHS Katalog-Regeln
   (Fokusringe, Rahmen der gewaehlten Ticketformat-Karte) auf das
   hartcodierte ticketpay-Orange #ff4d06 zurueck — bei einem blauen Kunden
   ein Fremdkoerper.

   R1-B (Bestaetigungsbefunde B-R1J1-2 und J4-1, 2026-08-23) — DIE ALTE
   BEGRUENDUNG WAR IM ZWEI-SCHICHTEN-ZUSTAND FALSCH. Wortlaut bis hierher:
   die Definition "faerbt ausschliesslich unsere eigenen Katalog-Regeln um".
   Gemessen an der echten Kaskadenposition mit einer Kundenvorlage als
   zweiter Author-Schicht (Plugin-Reihenfolge) stimmt das nicht: alle zwoelf
   Kundenvorlagen definieren --tp-color-primary auf :root, unsere Zeile stand
   auf body.v2. :root setzt auf <html>, body.v2 auf <body> — fuer JEDES
   Element im Body gewinnt der naehere Elternwert, unabhaengig von
   Reihenfolge und Spezifitaet. Die Kundenvorlage konnte dort also NIE
   gewinnen; 47 (tech-minimal) bis 73 (warm-craft) Token-Verbraucher je
   Vorlage loesten auf unser #262E38 auf, darunter fuenf Kopfverlaeufe
   (colors.cover-overlay: primary-verlauf).

   FIX: dieselbe Zeile auf :where(:root). Damit gilt sie
     - wenn NIEMAND sonst das Token setzt (Vorlage 0 allein, jedes
       Manage-Theme — weder emit-theme.js noch emit-eventstyle.js emittieren
       --tp-color-*): unveraendert #262E38, kein Orange-Rueckfall;
     - sobald eine Kundenvorlage :root setzt: die Kundenvorlage gewinnt,
       weil :where() die Spezifitaet auf (0,0,0) daempft und (0,1,0) schlaegt.
   Das ist die Ladeordnung, die extension/VORLAGE0-SCHICHT.md beschreibt:
   Vorlage 0 ist der SOCKEL UNTER der Kundenvorlage, nicht ueber ihr.
   Stehende Auflage T-3 bleibt: bei jeder Katalog-Erweiterung neu pruefen.
   Vollscan 2026-08-23 (R1): 166 Vorkommen von var(--tp-color-primary in
   den Katalog-JSONs, davon 2 auf einem TABU-Selektor (colors.json,
   `#stickyfooter .btn.btn-brand .badge`) — in der gebauten v0final.css
   NICHT emittiert (0 Treffer), Waechter bleibt zu Recht Exit 0.

   R3-A (Bestaetigungsbefund R3J2-2, 2026-08-23) — DAS
   DRITTE TOKEN DERSELBEN FAMILIE FEHLTE, UND SEIN RUECKFALL WAR BUNT.
   Vollscan der gebauten Datei: genau EIN Verbraucher,
     body.v2:has(.navbar.navbar-default) … .navbar-nav > li > a:hover,
     … > a:focus { color: var(--tp-color-primary-hover, #d63f00) }
   (portal.tab-navigation: dezent). Vorlage 0 definierte von der Familie nur
   --tp-color-primary und --tp-color-primary-contrast; alle ZWOELF
   Kundenvorlagen fuehren zusaetzlich --tp-color-primary-hover. Gerendert
   wurde deshalb allein unter Vorlage 0 der harte Rueckfall #d63f00 — das
   hartcodierte ticketpay-Orange (KORRIDOR §3.6) in einer Vorlage, die sich
   §4 der Charta nach "keine dritte Buntfarbe" auferlegt hat.
   ZWEITE, SCHWERERE FOLGE: seit R2-C den RUHEzustand dieser Reiter auf
   5,06 : 1 gehoben hat, war der BEDIENTE Zustand mit 4,06 : 1 schlechter als
   der Ruhezustand desselben Elements (und schlechter als der nackte Shop mit
   11,90 : 1) — genau das Muster, das R1-C in der Fusszeile als Fehler
   beseitigt hat. R2-C hatte die Hover-/Fokuszeile ausdruecklich "unangetastet"
   gelassen und sie damit auch nicht gemessen.
   FIX: das fehlende Token derselben Bauform wie seine beiden Geschwister —
   farbabstinent an die Rollenfarbe gebunden, Rueckfall = Sockelton. Auf
   :where(:root), damit jede Kundenvorlage es weiterhin mit ihrem eigenen
   Wert schlaegt (alle zwoelf tun das auf :root).
   MESSFALLE, ehrlich benannt: forcePseudoState mit 'focus-visible' setzt
   ':focus' NICHT mit — in dieser Stellung misst man weiter den Ruhewert.
   Der Nachweis laeuft darum ueber den Singular 'focus' bzw. echten
   el.focus() (r3fix-portal.js).
   --------------------------------------------------------------------- */
:where(:root) {
  --tp-color-primary: #262E38;
  --tp-color-primary-contrast: #FFFFFF;
  --tp-color-primary-hover: var(--tp-color-body-text, #262E38);
}
body.v2 .well:not(.well-green):not(.well-brand):not(.well-feature),
body.v2 .well.well-light {
  background-color: var(--v0t-karte);
}

/* =====================================================================
   Z — DIE KOPF-ZAESUR (Geometrie, nicht Farbe)
   Auftrag A1..A5. Der Kopf war "derselbe hohe, halbleere dunkle Balken
   wie 2015" (J4, einstimmig). Geaendert wird der AUFBAU:
   Z1 Naht  · Z2 Grundlinie · Z3 Typo-Stufen · Z4 Hoehen je Zweig
   Z5 Verlaufsschleier zur Unterkante · Z6 deckender dunkler Sockel.
   Die dunkle Polaritaet, die Reihenfolge Titel->Datum und die deckende
   Kopf-Knopfgruppe bleiben unangetastet (Abgrenzung zu den 12, Paar-Regel).
   ===================================================================== */

/* ---------------------------------------------------------------------
   A1 / Z1 — NAHT: Kopf-Unterkante == Oberkante des Fortschrittsbands.
   STRUKTURFEST, keine kalibrierte Negativmarge: die drei Abstaende, aus
   denen das 56-px-Luftloch bestand, werden dort auf 0 gesetzt, wo eine
   Leiste UNMITTELBAR auf einen sichtbaren Kopf folgt — sonst nirgends.
   Zerlegung des Lochs (gemessen shop-artikel@1280, v0r2tief):
     .cover margin-bottom 12  (kollabiert mit #content margin-top 20 -> 20)
     #content > .container padding-top 30
     .checkout-progress-row margin-top 6                      = 56 px
   Bedingungen:
     :not(.nocover.withiframe) -> nur der Zustand, in dem der Kopf wirklich
                                  ausgeblendet ist, behaelt sein Luftpolster
     :has(.checkout-progress-row) -> Seiten OHNE Leiste behalten ihren Abstand
     .cover:has(.cover-content)   -> leerer Organizer-Kopf bleibt unberuehrt
   Faellt :has() aus (alter Browser), gilt wieder der Serienabstand —
   es entsteht nie ein Ueberlapp.

   K-2 (Z14, ueber die volle Vierfach-Matrix nachgemessen): der Ausschluss
   trug bis hierher `:not(.nocover)` und war damit ZU BREIT. Belegt:
   standard.haml Z. 93 blendet den Kopf nur "in Kombination mit der class
   withiframe" aus; custom_tp.css.scss:422 (= bootstrap_ticketpay.css
   Z. 9798) `body.nocover.withiframe .cover { display: none !important }`.
   Gemessen: nocover+withiframe -> .cover display:none in 8/8 Zellen;
   nocover ALLEIN -> Kopf sichtbar (124,4-281,6 px) und darunter wieder
   das 56,0-px-Luftloch, in 8/8 nocover-Zellen. Der Schutz griff also
   genau dort, wo der Kopf ohnehin unsichtbar ist, und fehlte dort, wo er
   sichtbar ist (Shop mit iframe_no_header, direkt aufgerufen statt
   eingebettet). Trennscharf ist die KOMBINATION beider Klassen.
   Bildbeleg: shots/vorlage0z14/kopf/NAHT__*__nocover__*.png (VOR) gegen
   shots/vorlage0z14/fix/NAHT2__*__nocover__*.png (NACH).
   --------------------------------------------------------------------- */
body.v2:not(.nocover.withiframe):has(.checkout-progress-row) .cover:has(.cover-content) {
  margin-bottom: 0;
}
body.v2:not(.nocover.withiframe):has(.checkout-progress-row):has(.cover .cover-content) #content {
  margin-top: 0;
}
body.v2:not(.nocover.withiframe):has(.checkout-progress-row):has(.cover .cover-content) #content > .container {
  padding-top: 0;
}
body.v2:not(.nocover.withiframe):has(.checkout-progress-row):has(.cover .cover-content) .checkout-progress-row {
  margin-top: 0;
}

/* ---------------------------------------------------------------------
   A2 / Z2 — GRUNDLINIE: der Kopfinhalt sitzt an der Unterkante, nicht
   oben links in einer halbleeren Flaeche. Ab 992 px stehen Titel/Meta
   links und die Kopf-Knopfgruppe rechts auf DERSELBEN Grundlinie — die
   unterste Zeile des Kopfes laeuft damit von Rand zu Rand und die
   "900-px-Leere" rechts von kurzen Titeln (J4) verschwindet.
   .cover ist FREI (kein Manage-Key, keine $brand-color).
   --------------------------------------------------------------------- */
body.v2 .cover {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
body.v2 .cover .cover-content {
  padding-top: 22px;
  padding-bottom: 16px;
  position: relative;
  z-index: 2;
}
@media (min-width: 992px) {
  body.v2 .cover .cover-content > .row {
    display: flex;
    align-items: flex-end;
  }
  /* Bootstrap-3-Clearfix wuerde als Flex-Kind zu einem Phantom-Element. */
  body.v2 .cover .cover-content > .row::before,
  body.v2 .cover .cover-content > .row::after { display: none; }
  /* Leerer Logo-Platzhalter (kein Kunden-Logo) reservierte 75 px Hoehe und
     hielt den Kopf kuenstlich hoch. Logos selbst bleiben unangetastet. */
  body.v2 .cover .cover-content .wrapper-right-logo:not(:has(img)) { min-height: 0; }
}
@media (max-width: 767px) {
  body.v2 .cover .cover-content { padding-top: 16px; padding-bottom: 13px; width: 100%; }
}
/* width:100% NUR <=767 px — Begruendung, weil beides schon einmal falsch war:
   .cover-content IST die Bootstrap-.container. Als Flex-Kind von .cover greifen
   ihre auto-Seitenraender: in der Querachse schlagen auto-Margen jedes
   align-items, das Kind wird shrink-to-fit UND zentriert. Ab 768 px hat
   .container eine feste Breite (750/970/1170) — dort ist das genau das
   Serienverhalten und muss so bleiben (Iteration 1: width:100% sprengte bei
   1280 px das Raster, Titel x=15 gegen Raster x=70).
   Unter 768 px ist .container fluide: dort wurde der Kopfinhalt dadurch auf
   seine Inhaltsbreite zusammengezogen und MITTIG gesetzt — gemessen
   shop-artikel@375 Titel x=66 statt x=15, cart-modal@375 x=66, portal-order@375
   x=62; bei langen Titeln (cover-buttonbar) fiel es nicht auf, weil der Inhalt
   ohnehin die volle Breite fuellt. Das war (a) eine Ausrichtung, die von der
   Titellaenge abhing, und (b) ein zentrierter Hero — Identitaetsmerkmal T2 von
   festival-dark/neon-nacht/pastell-soft/warm-craft (E-kopf §2). Vorlage 0
   bleibt linksbuendig wie Serie und v0r2tief. */

/* ---------------------------------------------------------------------
   A2 / Z3 — TYPO-STUFEN: Titel ist die Buehne (header.title-size:riesig,
   clamp(30px,5.5vw,58px)), die Meta-Zeile wird zur eigenen Stufe:
   kleiner, gesperrt, in Versalien und in einem ruhigeren Ton.
   Spezifitaet: header.details-style traegt einen (0,4,2)-Booster
   (.cover .cover-content .col-md-8 > p) — hier gleichgezogen, damit die
   Stufe nicht von der Katalog-Achse ueberschrieben wird.
   Farbe: GESCHUETZT-FREI (Manage-Key brand_cover_color) und hell
   (rel. Luminanz >= 0,55) — KORRIDOR §4.1 Grenzfall C.
   --------------------------------------------------------------------- */
body.v2 .cover .cover-content h2 {
  margin-bottom: 6px;
  line-height: 1.06;
}
body.v2 .cover .cover-content .col-md-8 > p,
body.v2 .cover .cover-content .col-md-7 > p,
body.v2 .cover .cover-content p {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: .1em;
  text-transform: uppercase;
  margin-top: 2px;
  margin-bottom: 0;
  opacity: 1;
}
body.v2 .cover .cover-content .col-md-8 > p a.header_details,
body.v2 .cover .cover-content .col-md-7 > p a.header_details,
body.v2 .cover .cover-content a.header_details {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .1em;
}
@media (max-width: 767px) {
  body.v2 .cover .cover-content .col-md-8 > p,
  body.v2 .cover .cover-content .col-md-7 > p,
  body.v2 .cover .cover-content p,
  body.v2 .cover .cover-content a.header_details { font-size: 12px; letter-spacing: .08em; }
}

/* A1/A2 — KOPFFLAECHE (B1). .cover-linear-black + .cover-content* =
   GESCHUETZT-FREI (KORRIDOR §1 Block 13/15, §2 ★).
   Verlaufsrichtung 0deg bleibt; Luminanz-Delta Ober-/Unterkante < 4 %.
   Grenzfall B: hellste Stelle #1B222B => 15,5:1 gegen Weiss (Auflage >= 3:1). */
body.v2 .cover-linear-black {
  background-color: var(--v0t-tief-900);
  background-image: linear-gradient(0deg, #12161C 0%, #1B222B 100%);
}
/* Grenzfall C: Kopfschrift bleibt hell (rel. Luminanz >= 0,71). */
body.v2 .cover-content h2 { color: #FFFFFF; }
body.v2 .cover-content p { color: var(--v0t-meta); }
body.v2 .cover-content a.header_details { color: var(--v0t-meta); }

/* A15 — Wortumbruch statt Silbentrennung im Kopftitel (B9).
   Dreht die hyphens:auto-Zeile aus effects.langtext-schutz zurueck. */
body.v2 .cover-content h2 {
  -webkit-hyphens: manual;
  hyphens: manual;
  overflow-wrap: break-word;
  word-break: normal;
}

/* ---------------------------------------------------------------------
   A5 / Z4 — HOEHEN JE ZWEIG.
   Bild-Zweig braucht Bildhoehe (J5: "das Titelbild ist Wiedererkennung"),
   Nicht-Bild-Zweig darf kompakt bleiben (J3: DICE-Tempo).
   Zweig-Erkennung: nur im Foto-Zweig traegt .cover-innerbg das INLINE
   gesetzte Kopfbild (standard.haml:105 bzw. :96). .cover-innerbg.cover-image
   ist KEIN Foto-Merkmal — sie steht auch dann, wenn nur ein Kopf-LOGO
   gesetzt ist (belegt an fixture/customerdata, success, payment).
   --------------------------------------------------------------------- */
body.v2 .cover:has(.cover-innerbg[style*="background-image"]) {
  min-height: clamp(200px, 22vw, 292px);
}

/* ---------------------------------------------------------------------
   A3 / Z5 — VERLAUFSSCHLEIER ZUR UNTERKANTE statt Flaechenschleier.
   Ersetzt header.image-overlay (dort nur flaechige rgba-Decken; die Achse
   ist in diesem Preset bewusst NICHT gesetzt, das Pseudo-Element also frei).
   Oben bleibt das Artwork zu 100 % satt, nach unten laeuft es in den Fuss.
   .cover/.cover-innerbg = FREI (kein Manage-Key, keine $brand-color).

   KB-1 (CEO-Befund 2026-08-23, Fix 2026-08-24): der Nullpunkt des Schleiers
   wandert von 42 % auf 54 %, der Mittelstopp von 68 % auf 74 %. Grund ist
   die neue Messauflage "unberuehrte Bildflaeche >= 50 % der Kopfhoehe bei
   Alpha <= 0,05": der ALTE Schleier ueberschritt 0,05 rechnerisch bei
   42 % + (0,05/0,16)*26 % = 50,1 % — er war damit selbst dann die bindende
   Schranke, wenn der Sockel sie einhaelt, und zwar ohne jeden Spielraum.
   Neu liegt der 0,05-Punkt bei 54 % + (0,05/0,16)*20 % = 60,3 %. Der Fuss
   bleibt unveraendert stark (0,34/0,48 an 90 %/100 % wie bisher) — die
   Charta-Aufgabe des Schleiers ("NUR zur Unterkante") ist nicht beruehrt.
   --------------------------------------------------------------------- */
body.v2 .cover .cover-bg .cover-innerbg[style*="background-image"]::after {
  content: "";
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  pointer-events: none;
  background-image: linear-gradient(to bottom,
      rgba(9, 12, 17, 0) 0%,
      rgba(9, 12, 17, 0) 54%,
      rgba(9, 12, 17, 0.16) 74%,
      rgba(9, 12, 17, 0.34) 90%,
      rgba(9, 12, 17, 0.48) 100%);
}

/* ---------------------------------------------------------------------
   A4 / Z6 — DECKENDER SOCKEL, NUR im Foto-Zweig und DUNKEL.
   Erbe K2 ("deckende Kopf-Elemente"), Auflage T-1, J5/J7 ausdruecklich
   "dunkel, nie weiss" — wD_hell ist der Gegenbeweis (1,10:1).

   ===================================================================
   KB-1 — NEUVERANKERUNG (CEO-Befund 2026-08-23, Fix 2026-08-24).
   Ursachenbericht: scratchpad/vorlage0kb/URSACHE.md, Protokoll FIX.md.

   WAS FALSCH WAR (nicht der Verlauf, die VERANKERUNG):
   Der Sockel hing an .cover-content mit `top:-42px; bottom:0`. Das
   unterstellt, .cover-content sei ein NIEDRIGER Textblock am Fuss eines
   hohen .cover. Live ist er das nicht: die Serienregel
   `.cover.show_own_header .wrapper-right .wrapper-right-logo{min-height:170px}`
   (custom_tp.css.scss Z. 403; Schwester Z. 390 fuer .disabled_logo_in_header,
   Z. 409 sogar 230px fuer .cover_organizer) macht .cover-content zu 86,3 %
   der Kopfhoehe. Der Sockel begann dadurch bei y = -3,4 px — UEBER der
   Kopf-Oberkante — und erreichte 0,55 genau an der Oberkante. Gemessene
   Deckung Mitte: y20 39 %, y80 64 %, y240 88 %. Das Artwork war weg
   (Textur -92 %), und `width:100vw` malte dieselbe Dichte ueber die
   Flaechen links/rechts des Rasters: das sind die vom CEO gesehenen
   "dunklen Randflaechen" — kein zweiter Maler, derselbe.

   WAS JETZT GILT: der Sockel bindet sich an den TITELKASTEN, nie an
   .cover-content und nie an eine Hoehe, die ein Logokasten bestimmt.
     >= 992 px  Anker = .cover-content > .row > *:first-child (die
                Titelspalte: .col-md-8 im Shop, .col-md-7 im Portal).
                Nur dort ist .row flex mit align-items:flex-end, die
                Titelspalte sitzt also buendig an der Kopf-Unterkante
                (`bottom:-16px` = padding-bottom von .cover-content trifft
                sie exakt). Der Logokasten steht in der SCHWESTERSPALTE
                und kann die Sockelhoehe nicht mehr anheben.
     768..991   Anker bleibt .cover-content, aber `top:-2px` statt -42px.
                Dort ist der Logokasten `hidden-sm` (also 0 hoch) und
                .cover-content beginnt 22 px (padding-top) ueber dem
                Titel — `top:-2px` setzt die Rampe damit auf dieselben
                24 px ueber der Titel-Oberkante wie im Desktop-Arm.
     <= 767 px  unveraendert (J3-A1, `top:2px`) — dort war die Geometrie
                nie defekt: Logokasten hidden-xs, Sockelbeginn 40,7 %.

   RAMPE: 72 px ueber der Titel-Oberkante, aber mit WEICHEM ANSATZ.
   Das ist die zweite Iteration und der Grund steht im Bild, nicht in einer
   Zahl: die erste Fassung nahm eine kurze 24-px-Rampe (0 -> 0,20 -> 0,62).
   Sie hielt alle Messauflagen (55,7/51,0/50,2 % unberuehrt, 6,1:1) und war
   trotzdem falsch — an ihrem Beginn sprang das Alpha von exakt 0 in eine
   Steigung von 0,022/px, und dieser Knick in der ERSTEN Ableitung erzeugt
   ein Mach-Band: quer durch den Nachthimmel lief eine sichtbare waagerechte
   Naht (shots/vorlage0kb/RAMPE_K1_ist24__1280.png, Naht bei y=154).
   Ein reines Alpha-Mass findet so etwas nie; gefunden wurde es mit Augen
   und danach mit der 2. Ableitung des Alpha-Profils nachgemessen
   (scratchpad/vorlage0kb/rampe.js, Spalte NAHT).

   Die gefahrene Form loest das, ohne die Auflage zu verlieren: die oberen
   50 px der Rampe bleiben unter Alpha 0,05 (0,006 nach 24 px, 0,020 nach
   40 px) — dort ist die Steigung so klein, dass kein Ansatz sichtbar wird
   und die Flaeche nach der CEO-Definition UNBERUEHRT bleibt. Der eigentliche
   Anstieg 0,05 -> 0,62 liegt in den letzten 21 px unmittelbar ueber dem
   Titel, wo ihn der Titel selbst als gewollte Unterlage traegt.
   Gemessen (weisses Prueffoto, cover-livebild):
       Breite   unberuehrt    Naht (2. Abl.)   Kontrast weiss/creme
       1280      55,3 %        an der Titelkante   6,21 / 5,63
       1150      51,4 %        dito                5,93 / 5,38
        992      51,0 %        dito                6,02 / 5,46
   Kandidatenvergleich K1/K2/K3/K4/K5 in scratchpad/vorlage0kb/rampe.json;
   K4 (96 px) sah gleich gut aus, riss aber @992 die 50-%-Auflage (49,4 %).
   Der Mobil-Arm faehrt seine 14-px-Rampe unveraendert weiter (J3-A1).

   GRENZE DER AUFLAGE, ehrlich benannt: die 50 % gelten fuer den EINZEILIGEN
   Titel — den Fall des CEO-Befundes und den Normalfall. Bei einem
   zweizeiligen Titel steht die Titel-Oberkante selbst schon bei 41,8 %
   der Kopfhoehe (gemessen cover-image/cover-buttonbar @1280); dort sind
   34 % unberuehrt das geometrische Maximum, weil die Rampe dem Titelkasten
   folgen MUSS. Die Lesbarkeitsauflage A4 hat in diesem Zielkonflikt
   Vorrang — sie ist in allen Faellen mit >= 5,0:1 erfuellt.

   DECKUNG AN DER TITEL-OBERKANTE (A4-Paar-Regel, adversarial gerechnet
   gegen reinweisses Motiv und helle Kundenschrift #FFF3D6):
   Sockel 0,62 + Schleier dort 0,077 => effektiv 0,649 => 5,5:1.
   Auflage >= 4,5:1 ist mit Reserve erfuellt; nach unten steigt beides.

   BREITE: `left:-100vw; right:-100vw` statt `left:50%/transform/100vw`.
   Der alte Bau zentrierte auf den ANKER — an der (nicht mittigen)
   Titelspalte haette er die rechte Kopfhaelfte verfehlt. Beide Seiten
   ueberstehen zu lassen ist ankerunabhaengig; `.cover{overflow:hidden}`
   (custom_tp.css.scss Z. 306) schneidet exakt auf die Kopfbreite. Damit
   sitzt die Sockelkante auf der BILDKANTE, nicht auf der Rasterkante.

   Kein clip-path: der Fokusring der Kopfknoepfe darf nicht beschnitten werden.
   ===================================================================
   --------------------------------------------------------------------- */
body.v2 .cover:has(.cover-innerbg[style*="background-image"]) .cover-content::before {
  content: "";
  /* display MUSS gesetzt werden: Bootstrap gibt .container::before ein
     display:table (Clearfix) — ein Tabellenkasten mit top+bottom bleibt
     0 px hoch und der Sockel waere unsichtbar (Iteration 2, gemessen). */
  display: block;
  position: absolute;
  z-index: 0;
  left: -100vw;
  right: -100vw;
  /* -50px = Titel-Oberkante minus 72 px: .cover-content hat padding-top 22 px,
     der Titel beginnt also 22 px unter der Kastenoberkante (22 - 72 = -50). */
  top: -50px;
  bottom: 0;
  pointer-events: none;
  background-image: linear-gradient(to bottom,
      rgba(9, 12, 17, 0) 0px,
      rgba(9, 12, 17, 0.006) 24px,
      rgba(9, 12, 17, 0.020) 40px,
      rgba(9, 12, 17, 0.045) 50px,
      rgba(9, 12, 17, 0.075) 56px,
      rgba(9, 12, 17, 0.16) 62px,
      rgba(9, 12, 17, 0.30) 66px,
      rgba(9, 12, 17, 0.46) 69px,
      rgba(9, 12, 17, 0.62) 72px,
      rgba(9, 12, 17, 0.86) 62%,
      rgba(9, 12, 17, 0.92) 100%);
}

/* ---------------------------------------------------------------------
   KB-1 / Desktop-Arm — Sockel an der TITELSPALTE statt an .cover-content.
   Erst ab 992 px, weil erst dort (a) der Logokasten sichtbar wird und die
   alte Verankerung zerreisst und (b) `.row` flex mit align-items:flex-end
   ist, die Titelspalte also die Kopf-Unterkante beruehrt.

   z-index: -1 statt 0 — begruendet, weil es der einzige heikle Punkt ist:
   `.cover-content > .row` traegt `position:relative; z-index:1` und ist
   damit ein Stapelkontext. Innerhalb davon malt -1 UNTER den Inhalt beider
   Spalten (Titel, Meta, Logo, Knopfgruppe), aber weil der ganze Teilbaum
   in .cover-content (z-index:2) haengt, immer noch UEBER .cover-bg
   (z-index auto). Mit z-index:0 wuerde das Pseudo-Element ueber der
   Schrift liegen: positionierte Kaesten mit z-index 0/auto malen nach dem
   Inline-Inhalt nicht positionierter Nachfahren.
   --------------------------------------------------------------------- */
@media (min-width: 992px) {
  /* Alte Verankerung ausser Kraft. `content:none` ist hier gefahrlos: das
     Pseudo ist Bootstraps .container-Clearfix, und ab 992 px ist
     .cover-content > .row display:flex — es gibt keine Floats zu klaeren. */
  body.v2 .cover:has(.cover-innerbg[style*="background-image"]) .cover-content::before {
    content: none;
  }
  body.v2 .cover:has(.cover-innerbg[style*="background-image"]) .cover-content > .row > *:first-child {
    position: relative;
  }
  body.v2 .cover:has(.cover-innerbg[style*="background-image"]) .cover-content > .row > *:first-child::before {
    content: "";
    display: block;
    position: absolute;
    z-index: -1;
    left: -100vw;
    right: -100vw;
    /* Anker ist die Titelspalte selbst — die Rampe misst 72 px ab hier. */
    top: -72px;
    bottom: -16px;
    pointer-events: none;
    background-image: linear-gradient(to bottom,
        rgba(9, 12, 17, 0) 0px,
        rgba(9, 12, 17, 0.006) 24px,
        rgba(9, 12, 17, 0.020) 40px,
        rgba(9, 12, 17, 0.045) 50px,
        rgba(9, 12, 17, 0.075) 56px,
        rgba(9, 12, 17, 0.16) 62px,
        rgba(9, 12, 17, 0.30) 66px,
        rgba(9, 12, 17, 0.46) 69px,
        rgba(9, 12, 17, 0.62) 72px,
        rgba(9, 12, 17, 0.86) 62%,
        rgba(9, 12, 17, 0.92) 100%);
  }
  /* -------------------------------------------------------------------
     V2 (Nachfix der Vollmatrix) — KOPF OHNE LOGO: RAMPE UMVERTEILT,
     NICHT VERKUERZT.

     BEFUND: `disable_logo_in_header` @992 hielt als EINZIGE von 102
     Kombinationen die CEO-Auflage nicht — 45,9 % unberuehrte Bildflaeche
     statt >= 50 % (Vollmatrix §6.1, 1 Reisser in 204 Zellen).
     URSACHE, gerechnet und nachgemessen: ohne Logo ist der Kopf 25 px
     kuerzer (218 statt 243 px), die Titel-Oberkante sitzt bei y=119,5.
     Die Rampe haengt konstruktiv am Titel und ist gleich lang geblieben,
     also faellt der unberuehrte Anteil rein geometrisch.

     WARUM NICHT KUERZEN: der obere Teil der Rampe ist genau die Strecke,
     die den Mach-Band-Ansatz vermeidet (s. Block darueber, Kandidat K1).
     Wer sie kuerzt, holt die Naht zurueck. Die Auflage laesst aber
     Spielraum, den keine Kuerzung braucht: unterhalb Alpha 0,05 gilt die
     Flaeche als unberuehrt. Diese Fassung STRECKT deshalb den unsichtbaren
     Fuss der Rampe (0 -> 0,045 jetzt ueber 61 statt 50 px) und legt den
     sichtbaren Anstieg 0,05 -> 0,62 in die letzten 11 px unmittelbar ueber
     dem Titel — dort, wo der Titel selbst die Unterlage bildet.
     Rampenlaenge (72 px), Anker (`top:-72px`) und die Dichte AN DER
     TITEL-OBERKANTE (0,62) bleiben damit unveraendert; der Kontrast ist
     Byte fuer Byte derselbe wie im Auslieferungsstand.

     GEMESSEN, Kandidatenvergleich N0..N5 (scratchpad/vorlage0kb/nachfix/
     v2-rampe.js, v2-rampe.json), reinweisses Motiv, echte Kaskadenposition:
        Kandidat        unberuehrt@992   Kontrast weiss/creme   Steile
        N0 (Ist)          45,9 %  ✗        5,76 / 5,22          0,0490
        N1 skaliert 50 %  50,5 %  ✓        5,67 / 5,14 (faellt) 0,0710
        N2 skaliert 45 %  50,9 %  ✓        5,67 / 5,14 (faellt) 0,0754
        N3 UMVERTEILT     50,5 %  ✓        5,76 / 5,22 (gleich) 0,0676
     Gewinnerprobe: N3 ist der einzige Kandidat, der die Auflage haelt UND
     den Titelkontrast exakt haelt; die skalierten Kandidaten erkaufen
     dieselben 50 % mit 0,08 Kontraststufen und einer steileren Kante.
     @1280 steigt derselbe Fall von 55,3 % auf 57,4 %.
     Mit Augen geprueft (3-fache Lupe auf den Rampenbereich, weisses und
     echtes helles Motiv): shots/vorlage0kb/V2LUPE_weiss__992.png und
     V2LUPE_hell__992.png — kein sichtbarer Ansatz, keine Naht.

     GEBUNDEN AN DIE KLASSE: die Regel greift NUR unter
     `.cover.disabled_logo_in_header`. Alle uebrigen Kopf-Bauformen bleiben
     unberuehrt — gegengemessen an der Kontrollzelle C094 (own-header):
     51,0 % @992 und 55,3 % @1280 vor wie nach, auf die Nachkommastelle.
     ------------------------------------------------------------------- */
  body.v2 .cover.disabled_logo_in_header:has(.cover-innerbg[style*="background-image"]) .cover-content > .row > *:first-child::before {
    background-image: linear-gradient(to bottom,
        rgba(9, 12, 17, 0) 0px,
        rgba(9, 12, 17, 0.004) 34px,
        rgba(9, 12, 17, 0.012) 50px,
        rgba(9, 12, 17, 0.030) 57px,
        rgba(9, 12, 17, 0.045) 61px,
        rgba(9, 12, 17, 0.075) 63px,
        rgba(9, 12, 17, 0.16) 66px,
        rgba(9, 12, 17, 0.30) 68px,
        rgba(9, 12, 17, 0.46) 70px,
        rgba(9, 12, 17, 0.62) 72px,
        rgba(9, 12, 17, 0.86) 62%,
        rgba(9, 12, 17, 0.92) 100%);
  }
}
/* ---------------------------------------------------------------------
   J3-A1 — SOCKELBEGINN @<=767 px NACH UNTEN.
   Befund J3 (am Bild gemessen, weisses Pruefmotiv): @1280 bleibt das Motiv
   bis 19,5 % der Kopfhoehe unberuehrt, @375 nur bis 3,5 % — der Sockel
   begann 42 px ueber einem Kopfinhalt, der am Handy 152 von 200 px
   ausfuellt, also praktisch an der Oberkante. Folge auf einem hellen Motiv
   (mEh_375__cover.png): der Kopf ist ein grauer Verlauf, vom Artwork bleibt
   nichts, und die Oberkante loest sich fugenlos in den Seitengrund auf.

   Geometrie, gemessen statt geschaetzt (n-geo.js): Kopf 200 px,
   .cover-content oben bei y=48, Innenpolster 16 px => der Titelkasten
   beginnt bei y=64 = 32 % der Kopfhoehe. Genau dort entscheidet sich die
   A4-Paar-Regel (schlechtester Bildpunkt im Titelkasten gegen die
   Kundenschrift). Der Beginn kann deshalb NICHT auf 35-40 % — dort stuende
   die Oberkante des Titels auf blankem Motiv und der Boden faellt auf 1:1.
   Der erreichbare Hoechstwert ist die Oberkante des Kopfinhalts: top:2px
   setzt den Beginn auf y=50 = 25,0 % und trifft damit genau die Auflage
   J3-A1 ("die oberen 25 % bleiben unangetastet").

   Die Rampe ist an den Kopfinhalt gebunden, nicht an die Kopfhoehe: der
   Stopp bei 14 px liegt immer exakt auf der Titel-Oberkante (2 px Vorlauf +
   16 px Innenpolster) — auch bei ein- oder dreizeiligen Titeln. Dichte dort
   0,64 statt bisher 0,60; der Boden der Paar-Regel steigt dadurch (adversarial
   gemessen, reinweisses Motiv + Kundenschrift #FFF3D6) von 4,64:1 auf
   5,46:1, waehrend das Artwork oben 50 statt 7 px behaelt.
   @>=768 px bleibt alles unveraendert (J3-A1 ausdruecklich).
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 .cover:has(.cover-innerbg[style*="background-image"]) .cover-content::before {
    top: 2px;
    background-image: linear-gradient(to bottom,
        rgba(9, 12, 17, 0) 0px,
        rgba(9, 12, 17, 0.30) 6px,
        rgba(9, 12, 17, 0.64) 14px,
        rgba(9, 12, 17, 0.82) 55%,
        rgba(9, 12, 17, 0.94) 100%);
  }
}

/* Der Inhalt liegt ueber dem Sockel — ohne negatives z-index, damit die
   Stapelreihenfolge nicht von .cover-bg abhaengt. */
body.v2 .cover .cover-content > .row { position: relative; z-index: 1; }

/* ---------------------------------------------------------------------
   A3 / Z14-A — DECKENDE KOPF-KNOPFGRUPPE, ab Z14 als DREI GETRENNTE PILLEN
   .cover .wrapper-right-info .btn-group = FREI (kein Manage-Key, keine
   $brand-color). Deckend, voller Vorlagenradius, weicher Schatten je Knopf.

   PANEL-ENTSCHEID Z14 (2-von-3, bindend): Kopf-Knopfgruppe = GETRENNTE
   PILLEN, voller Radius je Knopf, 6 px Luft. Damit erbt Vorlage 0 die
   STIL-CHARTA-Regel 4 (Los Z14-J2, Sieger KA 2:1, Borda KA 5 : KB+ 4 : K0 0):
   "Getrennte Pillen tragen 6 px Luft, eckige Einheiten bleiben verbunden —
   eine Reihe beruehrender Rundkaesten (-1 px bei Radius > 0) ist verboten."
   Vorlage 0 fuehrt --tp-radius-button: 6px, die Reihe ist also RUND.

   EHRLICHKEITSKLAUSEL (Auflage J3-5): das ORIGINALBILD der Endserie
   (shots/vorlage0final/v0final_shop-artikel_1280__cover.png) zeigt die
   Knopfgruppe VERBUNDEN. Die Trennung ist eine bewusste ANWENDUNG von
   Regel 4 auf eine Vorlage, die vor deren Beschluss gebaut wurde —
   Regelanwendung, keine Rueckholung eines frueheren Zustands.

   UMSETZUNGSORT (J2-Siegerauflage 7): im REZEPT, nicht im Katalog.
   `"header.kopfgruppe": true` ist aus v0final.json entfernt. Begruendung:
   (a) catalog/ ist fuer Vorlage 0 TABU (CLAUDE.md Kernregel 3 invertiert,
   LAGE §1.1); (b) die Option ist seit Z14 in KEINEM der 12 Rezepte gesetzt
   und ihr eigener Katalog-Hint verurteilt genau diese Einstellung ("Bei
   runden oder pillenfoermigen Knoepfen wirkt die Reihe ohne Luft angenagt");
   (c) ohne die Option liefert buttons.form: leicht die 6-px-Luft aus dem
   Kern — es entsteht keine neue Sonderregel, die eine spaetere Runde
   pflegen muesste.

   WAS SICH DAMIT AENDERT — und nur das:
     - Luecken   [-1,0 · -1,0]  ->  [6,0 · 6,0]
     - Radius    8/6/6/8 · 6/6/6/6 · 6/8/8/6  ->  6/6/6/6 an allen dreien
       (das 8/6-Paar in EINER Bedienreihe endet; genau dieses Merkmal hat
       J2 beim Kandidaten KB zur Disqualifikation gefuehrt)
     - Schatten und Aussenradius sitzen jetzt je KNOPF statt auf der GRUPPE
       (Panel-Auflage P2: ein Gruppenschatten stuende sonst hinter der
       leeren Luecke). Farbanteil bleibt explizit achromatisch (KORRIDOR).
     - die Naht-Haarlinie `inset 1px 0 0` entfaellt, weil es keine Naht
       mehr gibt; getrennt wird jetzt durch den Kopfgrund selbst.
   UNVERAENDERT (Auflage J2-N5 / N-4): Trefferhoehe 30,0 px, Knopfbreiten,
   deckende weisse Fuellung, Textfarbe, Hover-Paar.
   --------------------------------------------------------------------- */
body.v2 .cover .wrapper-right-info .btn-group > .btn {
  background-color: #FFFFFF;
  background-image: none;
  border-color: transparent;
  color: #1B222B;
  /* P2 — der Schatten wandert von der Gruppe auf den einzelnen Knopf.
     Farbanteil explizit und achromatisch (KORRIDOR §6: box-shadow nur mit
     explizitem achromatischem Farbanteil). */
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.30);
  font-weight: 600;
}
/* ---------------------------------------------------------------------
   R1-A / Z14-J2 REGEL 4, ZWEITE HAELFTE — "ECKIG BLEIBT VERBUNDEN" GILT
   AUCH, WENN VORLAGE 0 DARUNTER LIEGT (Bestaetigungsbefund B-R1J1-1).

   BEFUND (SCHWER, Nebenwirkung des Punkt-A-Fixes dieser Runde): Vorlage 0
   emittiert aus buttons.form: leicht die Kernzeile
     body.v2 .cover .btn-group, body.v2 #stickyfooter .btn-group
       { display: inline-flex; align-items: center; gap: 6px }   (0,3,1)
   plus `.btn-group > .btn { margin-left: 0 }`. Elf der zwoelf Kundenvorlagen
   setzen dieselbe gap-Zeile selbst und gewinnen als spaetere Schicht.
   mono-kontrast fuehrt header.header-buttons: "dezent", setzt also GAR
   NICHTS — seine Verbundenheit kommt aus dem ungeschuetzten Bootstrap-Default
   `margin-left: -1px`. Unsere Zeile schlug diesen Default und zerlegte damit
   genau die Kopfreihe, die STIL-CHARTA Regel 4 NAMENTLICH als eine der zwei
   verbundenen eckigen Einheiten fuehrt. Gemessen: Kundenvorlage allein
   gap "normal", Luecken [-1,0 - -1,0]; mit Vorlage 0 gap "6px",
   Luecken [6,0 - 6,0]. Reichweite 1 von 12 (stadion-energie wehrt sich mit
   einer eigenen (0,4,1)-Zeile `gap: 0`).

   FIX — DIE FAMILIENLOGIK DER REGEL SELBST, NICHT EINE NAMENSLISTE.
   Regel 4 sagt: "rund -> getrennt, eckig -> Einheit". "Eckig" ist im System
   messbar: --tp-radius-button. Gebaute Werte der zwoelf: 999px (4x),
   12px (2x), 6px (4x) — und 0 bei GENAU den beiden, die Regel 4 als
   verbundene Einheiten nennt (mono-kontrast, stadion-energie). Vorlage 0
   selbst fuehrt 6px, ist also rund und bleibt getrennt.
   Umsetzung ueber eine Stilabfrage auf das Token; sie greift NUR im
   Nullradius-Fall. Beide Schreibweisen (0 und 0px) sind abgedeckt, weil
   Stilabfragen den Wert als Tokenfolge vergleichen. Kein Farbwert, kein
   !important, keine Namensliste — eine spaetere Vorlage mit Radius 0 erbt
   die richtige Behandlung automatisch.
   Ein Browser ohne Stilabfragen verwirft den Block und faellt auf den
   Stand vor diesem Fix zurueck (getrennte Reihe) — kein Bruch, nur der
   alte Befund.
   REST, offen benannt: die Naht misst danach 0,0 px statt der -1,0 px des
   nackten Bootstrap-Defaults, weil `.btn-group > .btn { margin-left: 0 }`
   aus dem Kern kommt und hier bewusst nur fuer den Nullradius-Fall
   zurueckgedreht wird (`:not(:first-child)`, dieselbe Bauform wie Bootstrap).

   R2-A (2026-08-23, Bestaetigungsbefunde R2J2-2 und R2J4-1) — DIE
   KAUFLEISTEN-HAELFTE DIESER REGEL WAR TOTE FLAECHE UND IST ENTFERNT.
   Bis hierher nannte der Block VIER Selektorzeilen, zwei davon
   `body.v2 #stickyfooter .btn-group` (1,2,1) bzw.
   `body.v2 #stickyfooter .btn-group > .btn:not(:first-child)` (1,4,1).
   Beide verlieren das Kaskadenduell gegen VORLAGE 0 SELBST: der Katalog
   emittiert `body.v2 #stickyfooter #stickyfooter-inner .btn-group
   { ... gap: 6px }` (2,2,1) und `... .btn-group > .btn { margin-left: 0 }`
   (2,3,1); die ID-Stelle entscheidet zuerst, @container addiert keine
   Spezifitaet. Dieselben Zeilen stehen zusaetzlich in mono-kontrast.css
   Z.1576/1589 und stadion-energie.css Z.1885 — die Haelfte verlor doppelt.
   Gemessen (r2fix-r1a.js, extras/cart-filled/payment x beide
   Nullradius-Vorlagen x {v0allein, mitV0, kundeAllein} x {375,1280}):
   Leisten-Gruppe ausnahmslos gap 6px, in JEDER Zelle identisch mit
   kundeAllein — es gab in der Kaufleiste also auch nichts zu reparieren
   (der B-R1J1-1-Defekt tritt dort nicht auf). Und der Wrapper
   #stickyfooter-inner ist kein Fixture-Artefakt: shop-tp-master
   app/views/application/sticky_footer*.haml Z.3/11 und
   layouts/manager.haml Z.161 rendern ihn in allen Leisten-Varianten.
   Warum ENTFERNEN und nicht kennzeichnen: eine Regel, die in 100 % der
   heutigen Faelle inert ist, aber bei einer dreizehnten Vorlage mit
   Radius 0 ohne diesen Wrapper schlagartig -1 px Ueberlappung zwischen
   Warenkorb-Knopf und CTA erzeugen wuerde — ohne Sollwert, ohne Bild,
   ohne Fokusringpruefung — ist keine Vorsorge, sondern eine gestellte
   Falle. Die Kopfhaelfte bleibt: sie ist gemessen, bebildert und wirksam.
   --------------------------------------------------------------------- */
@container style(--tp-radius-button: 0) {
  body.v2 .cover .btn-group { gap: 0; }
  body.v2 .cover .btn-group > .btn:not(:first-child) { margin-left: -1px; }
}
@container style(--tp-radius-button: 0px) {
  body.v2 .cover .btn-group { gap: 0; }
  body.v2 .cover .btn-group > .btn:not(:first-child) { margin-left: -1px; }
}
/* ---------------------------------------------------------------------
   K-1 / Z14 — KNOPFGRUPPE ZURUECK AN DIE RASTERKANTE.
   Befund (Z14, 15 von 27 Zellen je Breite): sobald `disable_logo_in_header`
   gesetzt ist — im echten Shop der Normalfall jedes Shops ohne Kopf-Logo,
   und in der Fixture cover-buttonbar sogar nativ am .cover —, zieht die
   Serie den Kopf-Knopfkasten 15 px nach links aus dem Elternkasten heraus:
   bootstrap_ticketpay.css Z. 9778 = custom_tp.css.scss:393
   `.cover.disabled_logo_in_header .wrapper-right .wrapper-right-info
    { position: relative; bottom: 0; right: 15px }`.
   Gemessene Kette @1280 im Defektfall: .wrapper-right 850…1210 ->
   .wrapper-right-info 835…1195, Gruppen-Rechtskante 1195,0 statt 1210,0;
   @375 345,0 statt 360,0. Die Titel-Innenkante bleibt bei 70,0 / 15,0 —
   die Kopfzeile stand also asymmetrisch (links 70, rechts 85) und brach
   damit die gemessene Ausrichtungszusage der V0FINAL-CHARTA §1
   ("Knopfgruppe rechtsbuendig an der Rasterkante, Titel-Innenkante 15/70").
   Reine Geometrie, keine Farb-Property, kein Korridor-Konflikt; `right`
   wird auf den Wert des Nicht-Defektfalls zurueckgesetzt, nicht auf einen
   neuen. Bildbeleg: shots/vorlage0z14/fix/K1__*.png gegen
   shots/vorlage0z14/kopf/cover-buttonbar__bildNEIN-logoNEIN__1280.png.
   --------------------------------------------------------------------- */
body.v2 .cover.disabled_logo_in_header .wrapper-right .wrapper-right-info {
  right: 0;
}
body.v2 .cover .wrapper-right-info .btn-group > .btn:hover,
body.v2 .cover .wrapper-right-info .btn-group > .btn:focus,
body.v2 .cover .wrapper-right-info .btn-group > .btn:active {
  background-color: #EEF1F5;
  border-color: transparent;
  color: #12161C;
}
/* ---------------------------------------------------------------------
   W-2 / J3-A2 — TASTATURFOKUS AUF DEN DUNKLEN FLAECHEN (Barrierefreiheit).

   Befund des TECHNIK-CHECKs: der Katalog emittiert
     body.v2 .btn:focus-visible { outline: 3px solid var(--tp-color-primary)
       !important; outline-offset: 3px !important; box-shadow: 0 0 0 6px
       color-mix(in srgb, var(--tp-color-primary) 25%, transparent) !important }
   und `--tp-color-primary` ist bei uns #262E38 — zugleich die Farbe der
   Kopfflaeche (#1B222B/#12161C) und der Kaufleiste (#1A2028). Gemessen:
   1,17 / 1,32 / 1,19 : 1. Gefordert sind 3 : 1.

   Warum nicht einfach ein eigener `outline`: die Katalogregel traegt
   !important; plain kommt dagegen nicht an (die bis hierher stehende Regel
   `outline: 2px solid #FFFFFF` war deshalb wirkungslos — sie hat nie
   gerendert). Ein eigenes !important auf `outline` ist verboten (Farb-
   Property, KORRIDOR §6.3), und `--tp-color-primary` global umzustellen
   waere eine Farbentscheidung fuer die ganze Vorlage.

   Loesung: das TOKEN wird genau dort umdefiniert, wo der Ring auf einer
   dunklen Flaeche landet — auf dem fokussierten Element selbst. Eine
   Custom-Property-Deklaration ist keine Deklaration auf einer Farb-Property,
   sie traegt kein !important, sie ueberschreibt keine $brand-color-Ableitung
   und keinen Manage-Regler (weder .cover noch #stickyfooter kennen einen
   Manage-Key fuer den Fokusring). Gegengeprueft in der gebauten Datei:
   innerhalb von .cover und #stickyfooter verbraucht ausser den Fokusringen
   (Z303/773/781/785/867) NICHTS dieses Token — die Verbraucher fuer
   Ankreuzfelder, .well-icon-checked und den Stepper stehen alle in #content
   bzw. .checkout-progress-row.

   Bewaehrtes Muster: heller Aussenring (#F3F5F8, 14,3 : 1 gegen die
   Kopfflaeche, 14,6 : 1 gegen die Kaufleiste) + dunkler Innenabsatz
   (#12161C, 18 : 1 gegen eine weisse Knopffleche). Der Innenabsatz ist
   noetig, weil der Ring der Kopf-Knopfgruppe an der Naht auf den WEISSEN
   Nachbarknopf faellt — dort traegt der helle Ring nicht, der dunkle schon.
   Er sitzt als 3-px-Schatten eines ::before genau in der Luecke, die
   `outline-offset: 3px` laesst, und stoesst fugenlos an den hellen Ring.
   ::before, nicht ::after: `#initorder_layout::after` traegt das Chevron.
   --------------------------------------------------------------------- */
body.v2 .cover .btn:focus-visible,
body.v2 #stickyfooter .btn:focus-visible,
body.v2 #stickyfooter a:focus-visible {
  --tp-color-primary: #F3F5F8;
}
body.v2 #stickyfooter .btn:focus-visible {
  position: relative;
  z-index: 2;
}
body.v2 .cover .btn:focus-visible::before,
body.v2 #stickyfooter .btn:focus-visible::before {
  content: "";
  position: absolute;
  inset: -1px;              /* Rand-Kasten des Knopfes (border-width 1 px)  */
  border-radius: inherit;
  pointer-events: none;
  box-shadow: 0 0 0 3px #12161C;
}

/* ---------------------------------------------------------------------
   A5/A6 — FORTSCHRITTSBAND (B7) + achromatischer Stepper (B5)
   .checkout-progress-row / .pi-callout* = FREI OHNE EINSCHRAENKUNG
   (KORRIDOR §3.1: kommt in _system_style.css.erb nicht vor).
   Eigene deckende Flaeche loest §4.5 (Kunde mit dunklem Seitengrund) und
   traegt D1: unter der Leiste laeuft kein brand_body_bg_image durch.
   Mechanik unveraendert gegenueber v0r2tief — nur der obere Aussenabstand
   faellt weg (Z1) und das Band bekommt oben etwas mehr Innenpolster,
   damit die Naht als Kante wirkt und nicht als Quetschung.
   --------------------------------------------------------------------- */
body.v2 .checkout-progress-row {
  /* Z14-FB1/FB1-C: die Stepper-Polaritaet folgt dem Band, und das Band
     traegt den Seitengrund. Steht eine dunkle Kundenvorlage darueber, wird
     body-bg dunkel — dann muss der gefuellte Kreis HELL und die Ziffer
     darin DUNKEL sein, sonst verschwindet der Stepper im eigenen Band (das
     war der Preis, den die reine Flaechen-Bindung sonst gekostet haette).
     Rueckfall = die bisherigen Werte, Vorlage 0 allein bleibt bitgleich. */
  --tp-color-primary: var(--tp-color-body-text, #262E38);
  --tp-color-primary-contrast: var(--tp-color-body-bg, #FFFFFF);
  background-color: var(--v0t-band);
  color: var(--v0t-tief-500);
  border-radius: 0;
  padding: 22px 0 14px;
  margin-top: 6px;
  margin-bottom: 26px;
  /* Band statt Kasten: die Flaeche laeuft randlos aus dem Raster heraus,
     ohne waagerechten Ueberlauf (clip-path schneidet oben/unten ab). */
  box-shadow: 0 0 0 100vmax var(--v0t-band);
  clip-path: inset(0 -100vmax);
}

/* Ziffernkreis: relative + z-index, damit die Verbindungslinie dahinter liegt. */
body.v2 .checkout-progress-row .pi-callout i.h2 { position: relative; z-index: 1; }

/* erledigt: gefuellter Graphit-Kreis, invertierte Ziffer (13,4:1) */
body.v2 .checkout-progress-row .pi-callout-success i.h2 {
  background-color: var(--v0t-tief-700);
  border-color: var(--v0t-tief-700);
}
/* aktuell: weiss gefuellter Ring in Graphit + kraeftige Beschriftung */
body.v2 .checkout-progress-row .pi-callout-primary i.h2 { background-color: var(--tp-color-body-bg, #FFFFFF); }
body.v2 .checkout-progress-row .pi-callout-primary h5 { font-weight: 800; }
/* kommend: Ring und Schrift ruhig, aber lesbar (4,60:1 auf dem Band — C5) */
body.v2 .checkout-progress-row .pi-callout-default i.h2 { background-color: var(--v0t-band); }
body.v2 .checkout-progress-row .pi-callout-default { opacity: 1; font-weight: 500; }
body.v2 .checkout-progress-row .pi-callout-default h5,
body.v2 .checkout-progress-row .pi-callout-default h4 { font-weight: 500; }

/* ---------------------------------------------------------------------
   A7/A8 — VERBINDUNGSLINIE (B6): der unbesetzte Griff.
   Nutzt das bislang ungenutzte .pi-callout::before — kein neues Element.
   --------------------------------------------------------------------- */
body.v2 .checkout-progress-row .pi-callout::before {
  content: "";
  position: absolute;
  top: 23px;
  left: calc(-50% - 10px);
  right: 50%;
  height: 2px;
  background-color: var(--v0t-linie-2);
  z-index: 0;
}
body.v2 .checkout-progress-row .pi-callout-success::before,
body.v2 .checkout-progress-row .pi-callout-primary::before {
  background-color: var(--v0t-tief-700);
}
body.v2 .checkout-progress-row > [class*="col-"]:nth-of-type(2) .pi-callout::before {
  display: none;
}
@media (max-width: 767px) {
  body.v2 .checkout-progress-row { padding: 16px 0 12px; margin-bottom: 18px; }
  body.v2 .checkout-progress-row .pi-callout::before { top: 18px; }
}

/* ---------------------------------------------------------------------
   A19 — ABSCHNITTSKOPF GEHOERT ZUR KARTE, AUCH AUSSERHALB DER AKKORDEONS
   --------------------------------------------------------------------- */
body.v2 .wrap:not(.accordions) .wrap_heading {
  margin-bottom: 0;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  padding-bottom: 6px;
}
body.v2 .wrap:not(.accordions) .wrap_heading + .wrap_content .well {
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  border-top: 0;
}

/* ---------------------------------------------------------------------
   A20 — DIALOG: KOPF- UND FUSSBAND ENTFAERBEN
   --------------------------------------------------------------------- */
body.v2 .modal-content .modal-header,
body.v2 .modal-content .modal-footer {
  background-color: transparent;
  background-image: none;
}
body.v2 .modal-content .modal-header { border-bottom: 1px solid var(--v0t-kante); }
body.v2 .modal-content .modal-footer { border-top: 1px solid var(--v0t-kante); }

/* ---------------------------------------------------------------------
   A14 — ERFOLGS-GESCHWISTER DES STEPPERS (KORRIDOR §3.4)
   Farbwinkel Gruen = Erfolg bleibt (§3.3), nur die Neon-Saettigung geht.
   --------------------------------------------------------------------- */
body.v2 .btn.btn-success {
  background-color: var(--v0t-gruen);
  border-color: var(--v0t-gruen);
  color: #FFFFFF;
}
body.v2 .btn.btn-success:hover,
body.v2 .btn.btn-success:focus,
body.v2 .btn.btn-success:active {
  background-color: var(--v0t-gruen-d);
  border-color: var(--v0t-gruen-d);
  color: #FFFFFF;
}
body.v2 .cart .cartSet .cartWrap .items.bg-success {
  border-color: #8FB79B;
  box-shadow: 0 0 0 4px #E6F1EA inset;
}
body.v2 .cart .cartSet .cartWrap .item-success {
  box-shadow: 0 0 10px var(--v0t-gruen) inset;
}
body.v2 .jumbotron.jumbotron-success {
  box-shadow: 0 2px 9px 2px rgba(62, 124, 85, 0.35);
}
body.v2 .ribbon { background-color: var(--v0t-gruen-h); }
body.v2 .ribbon::before,
body.v2 .ribbon::after { border-right-color: var(--v0t-gruen); }

/* A14b — DER INFO-ZWILLING. Befund am Bild (zustaende/z_erfolg_1280__voll.png):
   neben dem entgruenten "Tickets oeffnen" stand "Termin in Kalender speichern
   (iCal)" als Bootstrap-Hellblau #5bc0de — auf der Erfolgsseite die einzige
   Fremdfarbe und ein Widerspruch zur eigenen Zusage "die Kundenfarbe ist der
   einzige bunte Ton der Seite". Dieselbe Behandlung wie beim Gruen:
   KORRIDOR §3.3 — Saettigung zuruecknehmen, FARBWINKEL BEHALTEN (Info bleibt
   Info). .btn-info ist Bootstrap-Erbe, theme-konstant, von Manage nicht
   gedeckt und haengt an keiner $brand-color => FREI. Weiss auf #3F7383 = 5,3:1.
   Ohne diesen Schritt stuende der Neon-Ton zwei Klicks spaeter wieder da —
   genau das Argument, mit dem die Ernte die Gruen-Geschwister eingesammelt hat. */
body.v2 .btn.btn-info {
  background-color: var(--v0t-info);
  border-color: var(--v0t-info);
  color: #FFFFFF;
}
body.v2 .btn.btn-info:hover,
body.v2 .btn.btn-info:focus,
body.v2 .btn.btn-info:active {
  background-color: var(--v0t-info-d);
  border-color: var(--v0t-info-d);
  color: #FFFFFF;
}

/* ---------------------------------------------------------------------
   A9 — KAUFBOX ALS RUHIGE FLAECHE (B3/B6 Kaufweg)
   --------------------------------------------------------------------- */
body.v2 .price_quantity_box,
body.v2 .price_quantity_box_inline {
  background-color: var(--v0t-kaufbox);
  border: 0;
  border-radius: 8px;
  padding: 10px;
}
body.v2 .price_quantity_box .show_button { box-shadow: none; }

/* ---------------------------------------------------------------------
   Z14-G3 / GEO-B5 + GEO-B6 — KAUFEN-KNOPF UND ANZAHL-FELD IN EINE FLUCHT,
   AUCH UNTER 768 px.
   Befund (Fixture extras, Varianten-Kaufbox #4 in DOM-Reihenfolge):
     rechte Feldkante minus rechte Knopfkante  @375  nackt -3,00 · _blank
     -3,00 · Vorlage 0 +10,00 px · @768 +4,77 px · @1280 0,00 px
     Kaufen-Knopf @375  nackt 90,67 % · _blank 90,67 % · Vorlage 0 88,57 %
     (155 von 175 px) — Sollwert >= 90 %.
   Mechanik, gemessen statt vermutet: Z14-ALL-1 nimmt dem .show_button-
   Wrapper sein Seitenpolster, aber ausdruecklich erst ab 768 px
   (v0final.css Z. 1132-1136). Unter 768 px behaelt der Wrapper seine
   10 px, waehrend Vorlage 0 die Kaufbox-Innenbreite mit eigenem
   padding: 10px (A9) ohnehin schon von 193 auf 175 px verengt. Genau
   diese 10 px sind der gemessene Ueberstand — der Knopf endet 10 px vor
   dem Feld. Der Wrapper gibt sie ab; der Knopf traegt sein Textpolster
   selbst. Der Deckel des Mengenfelds (quantity-select: schmal) bleibt
   unangetastet, damit die richtige Metrik G-B (mittig ueber dem Knopf)
   gueltig bleibt.
   Gilt NUR fuer den Kaufbox-Arm: ein .article-box .show_button OHNE
   .price_quantity_box hat kein Polster abzugeben (Z14-ALL-1 woertlich).
   Bild: shots/vorlage0z14/fix/G3__extras__375.png gegen
   shots/vorlage0z14/geometrie/G3_v0_extras_375__variantenzeile.png.
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 .price_quantity_box .show_button { padding-left: 0; padding-right: 0; }
}

/* ---------------------------------------------------------------------
   Z14-B4 (Gegenpruefungsbefund B4) — IM GESTAPELTEN ZUSTAND IST DAS
   MENGENFELD KNOPFBREIT.
   Die Ablehnung des Vorgaengers ("Metrik gilt fuer menge-unter, Vorlage 0
   faehrt menge-rechts") war ein NAMENSARGUMENT. Gemessen (g-menge.js,
   shop-artikel und extras, 375/600/767 px, echte K3-Position) stapelt die
   Kaufbox unter 768 px in ALLEN Zellen (gestapelt: true) — die Bauform ist
   dort menge-unter, ganz gleich wie das Rezept heisst. Der Sollwert
   Z7/Z13/Z14 lautet fuer diese Bauform "Dropdown exakt knopfbreit und
   zentriert". Erfuellt war bisher nur die zweite Haelfte: dMitte 0,00, aber
   96 px Feld ueber 655 px Knopf bei 767 px, waehrend der nackte Shop dort
   Feld == Knopf fuehrt.
   ENTSCHEID (Reichweite bewusst begrenzt, weil hier Kernregel 7 mitspielt):
   die Regel gilt UNTER 768 px, wo die Serie den Stapel ERZWINGT und der
   nackte Shop Feld == Knopf fuehrt (gemessen: 263/488/655 px in beiden
   Fixtures). Ab 768 px bleibt der Deckel `quantity-select: schmal`
   (max-width: 96px, margin-left: auto) unangetastet — das schmale,
   rechtsbuendige Feld ist dort ein identitaetstragendes Merkmal des
   abgenommenen Standes (Originalbild shots/vorlage0final/
   v0final_shop-artikel_1280__cover.png) und wird nicht als Nebenwirkung
   eines Mobil-Fixes umgebaut. EHRLICH DAZU: auch oberhalb 768 px steht das
   Feld GEOMETRISCH ueber dem Knopf (88 px ueber 226 px bei 1280) — es steht
   dort aber NEBEN DEM PREIS, und genau das ist die Bauform menge-rechts
   (Bild N4__menge__shop-artikel__NEU__1280.png, unveraendert gegen
   VORFIX2). Der Sollwert "knopfbreit" ist ab 768 px also bewusst NICHT
   erfuellt, nicht etwa unanwendbar.
   Damit das Feld die Knopfbreite wirklich erreicht, gibt der
   .show_quantity-Wrapper unter 768 px sein Seitenpolster ab — genau wie
   .show_button es seit Z14-G3 tut (ohne das blieben 20 px Rest, gemessen).
   Reine Geometrie, keine Farbe, kein !important.
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 .price_quantity_box .show_quantity { padding-left: 0; padding-right: 0; }
  body.v2 .price_quantity_box select.show_quantity_select {
    max-width: none;
    width: 100%;
    margin-left: 0;
    margin-right: 0;
  }
}

/* ---------------------------------------------------------------------
   Z14-B1 — KAUFKASTEN VERLIERT AB 1200 px DIE LINKE FLUCHT ZUR VORRATSZEILE.
   BEFUND OHNE FIX — bewusst KEINE Regel an dieser Stelle. Begruendung im
   Wortlaut, damit die naechste Runde nicht dieselbe Sackgasse zweimal geht:

   Messwert (Fixture stock-states, Bauform mit Kaufen-Knopf AUSSERHALB der
   price_quantity_box, elf Breiten, echte K3-Position): Versatz
   .price_quantity_box zu .stockStatus = +34,42 px bei 1200/1280/1440/1600 px.
   Abgenommener Stand v0final.css.VOR (5de3bb92) 0,00 px bei ALLEN elf
   Breiten; nackter Shop +8,00 bis +11,77 px ab 900 px — der abgenommene
   Vorlage-0-Stand war der einzige Zustand mit 0,00.

   ZWEI VERWORFENE FIXES, je gemessen statt vermutet (Sonde
   scratchpad/vorlage0z14/f-dz3.js, dritte Vergleichsspalte "nurminwidth"):
     min-width: 195px          -> pq 211,58 px · Versatz 34,42  (wirkungslos)
     min-width + max-width:none -> pq 211,58 px · Versatz 34,42  (wirkungslos)
   Beide greifen nicht, weil der Kasten mit 211,58 px ohnehin breiter als
   195 px ist und `max-width` erst ab 246 px binden wuerde.

   ECHTE URSACHE, per Computed-Style-Vergleich VOR gegen heute isoliert
   (f-dz4.js, .price_quantity_box selbst: NULL Property-Unterschiede ausser
   der resultierenden Groesse): das Kind `.show_price` ist im abgenommenen
   Stand 226,0 px breit und belegt eine eigene Zeile, heute 91,58 px und
   sitzt neben dem Mengenfeld. Der Float bekommt dadurch 211,58 statt
   246,0 px. Das ist die Katalog-Drift MB-4 ("Streichpreis stapelt jetzt
   auch @1280") — eine Aenderung der KAUFBOX-ANORDNUNG.
   Bild: shots/vorlage0z14/fix/B1__flucht__v0__1280.png (Preis gestapelt
   links, Mengenfeld rechts, Kasten eingerueckt) gegen
   B1__flucht__VOR__1280.png (Preiszeile ueber volle Breite, Mengenfeld
   darunter, Kasten buendig) und B1__flucht__nackt__1280.png.

   WARUM HIER TROTZDEM NICHTS STEHT: der einzige wirksame Hebel waere
   `.article-box .price_quantity_box > .show_price { flex-basis: 100% }`.
   Diese Regel trifft nicht nur die Bauform stock-states, sondern JEDE
   Kaufbox — sie wuerde die Kaufbox-Anordnung auf allen Artikelseiten
   umbauen. Die Kaufbox-Anordnung ist ein identitaetstragendes Merkmal
   (CLAUDE.md Kernregel 7: "aendern sich nie als Nebenwirkung eines Fixes").
   Ein 34-px-Versatz in EINER Bauform rechtfertigt das nicht.
   ⇒ Katalog-Backlog (Traeger ist Z14-F2-B3 + MB-4), nicht Vorlage 0.
   --------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
   B3 / N1 — PREIS-STAPELUNG @375 (Muss-Fix aller sieben Jurys)
   Serie rendert <small><s><font color=red>130,00 €</font></s></small>
   und den Zahlpreis als Textknoten DANEBEN — bei 375 px klebt beides
   zusammen ("130,00 €110,00 €"). Der Streichpreis bekommt eine eigene
   Zeile; die Farbe bleibt geerbt (checkout.strike-price: dezent).
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 .price_quantity_box .show_price,
  body.v2 .price_quantity_box_inline .show_price { line-height: 1.3; }
  body.v2 .price_quantity_box .show_price > small,
  body.v2 .price_quantity_box_inline .show_price > small,
  body.v2 .price_quantity_box .show_price > s,
  body.v2 .price_quantity_box .show_price > strike,
  body.v2 .price_quantity_box .show_price > del {
    display: block;
    font-size: .74em;
    margin-bottom: 1px;
  }
}

/* ---------------------------------------------------------------------
   B4 / N2 — "IN DEN WARENKORB" >= 48 px (J7 Muss-Fix Nr. 1; tief 42 px).
   Nur Geometrie — die Flaeche des Knopfes ist .btn-brand und damit TABU.
   --------------------------------------------------------------------- */
body.v2 .price_quantity_box .show_button .btn,
body.v2 .price_quantity_box_inline .show_button .btn,
body.v2 .article-box .price_quantity_box .show_button .btn {
  min-height: 50px;
  padding-top: 13px;
  padding-bottom: 13px;
  line-height: 1.35;
}

/* ---------------------------------------------------------------------
   A10 — KASTEN-IM-KASTEN @375 AUFLOESEN (Muss-Fix Runde 1)
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 .wrap .wrap_content .well { background-color: var(--v0t-karte); }
  body.v2 .wrap .wrap_content .well .items:not(.bg-success) { background-color: transparent; }
}

/* ---------------------------------------------------------------------
   A11 — HAARLINIE STATT 3-PX-GRAUKLOTZ (B5 Flaechen)
   --------------------------------------------------------------------- */
body.v2 .wrap .wrap_content .well .items + div + .items {
  border-top: 1px solid var(--v0t-kante);
}
body.v2 .cart .cartSet .cartWrap .items.divider { background-color: transparent; }

/* ---------------------------------------------------------------------
   A12 — HARTE SCHLAGSCHATTEN ERSETZEN (B7 Flaechen)
   --------------------------------------------------------------------- */
/* :not(.jumbotron-success) — die Erfolgs-Jumbotron traegt BEIDE Klassen; ohne
   Ausschluss gewaenne diese (spaeter emittierte) Regel und der gruene Tonwert
   aus A14 waere wirkungslos (Iteration 3 gemessen). */
body.v2 .jumbotron.jumbotron-default:not(.jumbotron-success) { box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06); }
body.v2 .cartWrap { box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06); }

/* ---------------------------------------------------------------------
   B1 / N3 — ENDSUMME ALS ECHTER TYPO-SPRUNG (Muss-Fix Runde 1, in
   v0r2tief nur formal erfuellt: gleiche Groesse, nur Linie + Fettung).
   Die ZAHLENFARBE bleibt unangetastet — .subtotal li / li.final tragen
   in Theme UND Manage !important (KORRIDOR §4.4, TABU²). Der Sprung
   laeuft ueber Groesse, Gewicht, Linie und Luft.
   --------------------------------------------------------------------- */
body.v2 .subtotal li.final {
  font-size: 1.42em;
  font-weight: 700;
  border-top-width: 2px;
  border-top-style: solid;
  padding-top: 12px;
  margin-top: 10px;
  line-height: 1.25;
}
body.v2 .subtotal li.final .totallabel,
body.v2 .subtotal li.final .value { font-weight: 700; }
body.v2 .subtotal li:not(.final) { font-size: .95em; }
body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td {
  font-size: 1.3em;
  font-weight: 700;
  padding-top: 12px;
}
@media (max-width: 480px) {
  body.v2 #cart_items ~ table.table > tbody > tr.finaltotal > td { font-size: 18px; }
}

/* ---------------------------------------------------------------------
   A13 / B5 — KAUFLEISTE + FUSSZEILE (GESCHUETZT-FREI, KORRIDOR §2)
   Polaritaet gehalten: dunkle Leiste, helle Schrift (§4.3).
   Fusszeile bleibt HELL. Neu (B5): die Rechtslinks standen bei 3,60:1 —
   schlechter als der nackte Shop (3,86:1), weil der Grund abgedunkelt,
   die Serien-Linkfarbe #777 aber stehen gelassen wurde. Paar-Regel gilt
   auch im Fuss: Flaeche UND Schrift werden gesetzt.
   #2A323C auf #DCE3EB = 10,2:1.
   footer a color = GESCHUETZT-FREI (Manage-Key brand_footer_color) —
   der Kunde mit dunkler Fusszeile ueberschreibt uns automatisch.
   --------------------------------------------------------------------- */
body.v2 #stickyfooter {
  background-color: var(--v0t-tief-800);
  color: #FFFFFF;
}
/* Z14-B7 (Gegenpruefungsbefund B7): die Paar-Regel galt bisher nur fuer die
   LINKS. Der Grundtext der Fusszeile blieb auf der Serienfarbe #777 und
   stand damit mit 3,46:1 auf der von Vorlage 0 gefaerbten Flaeche #DCE3EB —
   unter 4,5:1, gemessen an der echten K3-Position (payment, shop-artikel,
   @1280). Wer die Flaeche faerbt, faerbt die Schrift: derselbe Token wie die
   Links, damit auch derselbe Rueckfall und dieselbe Kundenbindung
   (footer-bg <-> footer-text). Keine neue Farbe, keine neue Freigabe. */
body.v2 footer {
  background-color: var(--v0t-fuss);
  color: var(--v0t-fusstext);
}
body.v2 footer a,
body.v2 footer ul.list-inline > li > a { color: var(--v0t-fusstext); }
/* ---------------------------------------------------------------------
   R1-C (Bestaetigungsbefund J2-B1 b) — DER BEDIENTE ZUSTAND DARF NICHT
   DUNKLER WERDEN, WENN MANAGE DIE FLAECHE STELLT.
   Manage hat ZWEI unabhaengige Regler (emit-eventstyle.js Z131-140):
   `footer { background-color: X !important }` und
   `footer a, a:hover, a:focus, a:active { color: Y !important }`. Ist nur
   der erste gesetzt (reale Teilkonfiguration), gewinnt Manage die FLAECHE
   und Vorlage 0 behaelt die SCHRIFT — der halboffene Paar-Fall aus
   KORRIDOR §4.5. Die bis hierher stehende Zeile `color: #12161C` machte den
   Hover-Zustand auf einer dunklen Manage-Fusszeile mit 1,02:1 unsichtbar
   (Ruhe 1,43:1, nackter Shop 4,15:1) — der bediente Zustand war schlechter
   als der Ruhezustand und schlechter als gar keine Regel.
   FIX: der Hover-Zustand aendert die FARBE NICHT MEHR. Er wird ueber die
   Unterstreichung getragen (Staerke + Abstand), also ueber ein Merkmal, das
   auf jeder Flaeche dieselbe Sichtbarkeit hat wie die Schrift selbst.
   Damit gilt in JEDER Manage-Konfiguration: K(Hover) == K(Ruhe).
   Die Ruhe-Zahl selbst bleibt ein offener Posten (siehe FEEDBACK.md #10):
   ein FESTER Ton kann sie nicht heilen — >= 4,5:1 gegen #DCE3EB verlangt
   rel. Luminanz <= 0,126, gegen #111318 verlangt sie >= 0,201; das
   bestmoegliche Achromat liegt bei 3,77:1 auf beiden Flaechen. Die einzigen
   CSS-Mittel, die den Fall wirklich schliessen wuerden (eigenes !important
   auf background-color oder ein background-image ueber dem Manage-Regler),
   sind durch KORRIDOR §6.3 und den Manage-Vertrag verboten.
   --------------------------------------------------------------------- */
body.v2 footer a:hover,
body.v2 footer a:focus,
body.v2 footer a:active,
body.v2 footer ul.list-inline > li > a:hover {
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
/* C6 — Widerrufs-Bedienelement: footer.widerruf-button steht auf
   "als-link" (der Ghost-Rahmen las sich in der Fusszeile wie ein leeres
   Eingabefeld, Bild v0r2tief_cover-buttonbar_375__footer.png). Es ist
   funktional einer der Rechtslinks und bekommt deren Farbe.
   BEFUND C6: die Katalog-Achse haengt an [onclick*="start_revoc"]. In der
   Bauform ohne onclick (belegt fixture/cover-buttonbar) greift sie NICHT —
   dort stand weiter ein weisser .btn-default-Kasten in der Fusszeile.
   Robuster Griff: das Bedienelement ist immer der .btn in der Liste, die
   auf #modal_revocation folgt. */
body.v2 footer ul.list-inline > li > .btn[onclick*="start_revoc"],
body.v2 footer .btn[onclick*="start_revoc"],
body.v2 footer #modal_revocation ~ ul.list-inline > li > a.btn,
body.v2 footer #modal_revocation ~ ul.list-inline > li > button.btn {
  background-color: transparent;
  background-image: none;
  border: 0;
  padding: 0;
  box-shadow: none;
  color: var(--v0t-fusstext);
  text-decoration: underline;
  text-underline-offset: 3px;
}
/* R1-C, zweite Fundstelle desselben Musters: auch hier faellt der
   Farbwechsel weg (Begruendung oben), die Unterstreichung traegt. */
body.v2 footer #modal_revocation ~ ul.list-inline > li > a.btn:hover,
body.v2 footer #modal_revocation ~ ul.list-inline > li > a.btn:focus-visible {
  text-decoration-thickness: 2px;
}
body.v2 footer #modal_revocation ~ ul.list-inline > li > a.btn:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
  box-shadow: 0 0 0 2px #12161C, 0 0 0 6px #12161C;
}

/* ---------------------------------------------------------------------
   Z14-D4 / B-3 — DER SPRACHWAHL-UMSCHALTER BEKOMMT SEINEN RING ZURUECK.
   Befund: die gewinnende Regel ist die Bootstrap-Basis
   `.dropdown-toggle:focus { outline: 0 }`. Im Tastaturfokus blieb unter
   Vorlage 0 GENAU EIN Merkmal uebrig (Unterstreichung, 3 999 geaenderte
   Bildpunkte, Merkmalskontrast 10,02:1) — zahlenmaessig ueber der
   3:1-Schwelle, aber ohne jede Redundanz. Im nackten Shop kommt ein
   Farbwechsel #777 -> #23527C hinzu (2 365 px, 7,04:1); den nimmt Vorlage 0
   weg, weil `footer a { color: var(--v0t-fusstext) }` die Farbe konstant
   haelt. Diese Reduktion wird hier nicht hingenommen, sondern durch das
   staerkere Merkmal ersetzt: ein Ring aus currentColor, also
   achromatisch abgeleitet und damit unter jeder Kundenvorlage und jedem
   Manage-Theme automatisch im Kontrast der Schrift, die er umschliesst.
   `:focus-visible` statt `:focus` — der Mauszeiger bekommt keinen Ring.
   Spezifitaet (0,4,1) schlaegt die Bootstrap-Basis (0,2,0) plain.
   Bild: shots/vorlage0z14/fix/D4__sprachwahl__fokus.png gegen
   shots/vorlage0z14/zustaende/D4_sprachwahl_zu_o_v0_fokusV.png.
   --------------------------------------------------------------------- */
/* ---------------------------------------------------------------------
   R1-D (Bestaetigungsbefund J2-B1 c) — DER RING BRAUCHT KONTRAST ZUR
   FLAECHE, NICHT ZUR SCHRIFT.
   Der in dieser Runde gebaute Ring war `outline: 2px solid currentColor`
   mit der Begruendung, er sei "achromatisch abgeleitet und damit automatisch
   im Kontrast der Schrift, die er umschliesst". Der Satz ist richtig und die
   Auflage trotzdem verfehlt: currentColor garantiert GLEICHHEIT mit der
   Schrift, nicht Kontrast zur FLAECHE. Gemessen im halboffenen Paar-Fall
   (Manage setzt nur brand_footer_bgcolor = #111318): K(Ring) 1,43:1 statt
   der geforderten 3:1; bei #3B4250 sogar 1,28:1.
   FIX: ZWEIFARBIGER ACHROMATISCHER RING — dunkler Absatz 0..2 px, weisser
   Ring 2..4 px (outline mit offset), dunkler Aussenabsatz 4..6 px. Auf
   JEDER Flaeche traegt mindestens einer der beiden Toene: der Kreuzungspunkt
   der beiden Kontrastkurven liegt bei rel. Luminanz 0,195 und dort messen
   BEIDE Ringe 4,29:1. Untergrenze also 4,29:1 statt bisher 1,28:1 — ohne
   jede Annahme ueber Manage-Theme oder Kundenvorlage.
   Der Ring bleibt achromatisch (#FFFFFF / #12161C), traegt kein !important
   und setzt keine Farb-Property auf einem TABU-Selektor.
   --------------------------------------------------------------------- */
body.v2 footer .dropdown > .dropdown-toggle:focus-visible,
body.v2 footer .dropup > .dropdown-toggle:focus-visible {
  outline: 2px solid #FFFFFF;
  outline-offset: 2px;
  box-shadow: 0 0 0 2px #12161C, 0 0 0 6px #12161C;
}

/* ---------------------------------------------------------------------
   Z14-D1 / B-2 — GEOEFFNETES SPRACHMENUE LAEUFT @375 NICHT MEHR AUS DEM
   FENSTER.
   Befund: scrollWidth-clientWidth = +42 px, sobald das Menue offen ist
   (Menue-Rechteck x=257,3…r=417,3 bei 375 px Fensterbreite, Ueberstand
   rechts 42,3 px); geschlossen 0. Identisch in v0, im VOR-Stand und im
   NACKTEN Shop => Basisbefund (Bootstrap-Dropup ohne Rechtsausrichtung),
   von Vorlage 0 nicht verursacht — aber in der eigenen Schicht mit einer
   Zeile abfangbar und ohne jede Farbwirkung. Nur unter 768 px: bei 768 und
   1280 px gibt es keinen Ueberlauf, dort bleibt die Serienausrichtung.
   Der Wert wurde VOR jedem scrollIntoView gelesen (TOOLING Z. 1959 ff.).
   Bild: shots/vorlage0z14/fix/D1__menue__375.png gegen
   shots/vorlage0z14/zustaende/D1_zu_dunk_v0__375.png.
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 footer .dropdown-menu,
  body.v2.withiframe footer .dropdown-menu { left: auto; right: 0; }
}

/* ---------------------------------------------------------------------
   A15 — WORTUMBRUCH STATT SILBENTRENNUNG, auch im Warenkorb-Dialog
   --------------------------------------------------------------------- */
body.v2 .wrap .items .headline h3,
body.v2 .items .headline h3,
body.v2 #cart_items ~ table.table > tbody > tr > td,
body.v2 #cart_items ~ table.table > tbody > tr > td:first-child {
  -webkit-hyphens: manual;
  hyphens: manual;
  overflow-wrap: break-word;
  word-break: normal;
}

/* ---------------------------------------------------------------------
   A16 — FOKUSRING ACHROMATISCH (KORRIDOR §3.2)
   --------------------------------------------------------------------- */
body.v2 .form-control:focus,
body.v2 form#gateway select:focus {
  border-color: #6E7A8A;
  box-shadow: 0 0 0 3px rgba(38, 46, 56, 0.14);
}

/* ---------------------------------------------------------------------
   B7 / N4 — AUSWAHL-GEWICHTUNG RICHTIG HERUM.
   Serie/Katalog leiten den RUHE-Zustand von Ankreuz- und Auswahlfeldern
   aus currentColor ab. Steht das Feld in einer Zeile mit Kundenfarbe
   (z. B. "Versand per Post"), traegt die NICHT gewaehlte Option einen
   orangefarbenen Ring, die gewaehlte einen graphitfarbenen — semantisch
   verkehrt (z_tief_radio2.png, J3-M4/J6-5). Der Ruhezustand wird
   neutralisiert; die Auswahl bleibt der einzige starke Zustand.
   Keine TABU-Stelle: es sind unsere eigenen appearance:none-Kontrollen.
   --------------------------------------------------------------------- */
body.v2 #content input[type="checkbox"]:not(:checked),
body.v2 #content input[type="radio"]:not(:checked) {
  background-color: rgba(38, 46, 56, 0.04);
  border-color: rgba(38, 46, 56, 0.42);
}
body.v2 #content input[type="checkbox"]:not(:checked):hover:not(:disabled),
body.v2 #content input[type="radio"]:not(:checked):hover:not(:disabled) {
  border-color: rgba(38, 46, 56, 0.78);
}

/* ---------------------------------------------------------------------
   A17 / C6 — ORGANIZER-KACHEL: KOPFBAND AUFLOESEN (B4 Flaechen)
   ACHTUNG: die Kachelfuellung selbst ist plain NICHT erreichbar
   (#organizer_events_list .event-listing {background:#fff !important}).
   --------------------------------------------------------------------- */
body.v2 #organizer_events_grid .panelx {
  border-color: var(--v0t-kante);
  border-radius: 8px;
}
body.v2 #organizer_events_grid .panelx .panelx_heading {
  background-color: transparent;
  background-image: none;
  border-bottom: 1px solid var(--v0t-kante);
  padding-bottom: 12px;
}
/* C6 — Titel-Unterrand auf Zeilenmass: zwischen Kacheltitel und erster
   Datenzeile klaffte mehr Luft als zwischen den Datenzeilen. */
body.v2 #organizer_events_grid .panelx .panelx_heading h3,
body.v2 #organizer_events_grid .panelx .panelx_heading h4 { margin-bottom: 0; }
body.v2 #organizer_events_grid .panelx .panelx_top > .line:first-child { margin-top: 0; }

/* ---------------------------------------------------------------------
   A21 — PORTAL: KASTEN-IM-KASTEN AUFLOESEN (B3 Flaechen, BEIDE Spalten)
   --------------------------------------------------------------------- */
body.v2 .wrapper_all { background-color: transparent; }
body.v2 .box-light,
body.v2 .box-grey { background-color: var(--v0t-karte); }
body.v2 .box-grey.headline { border-bottom: 1px solid var(--v0t-kante); }
body.v2 .box-footer {
  background-color: transparent;
  border-top: 1px solid var(--v0t-kante);
}
body.v2 .data-wrapper { background-color: transparent; }
/* R2-E (2026-08-23, Bestaetigungsbefund R2J3-5): diese Zeile war der einzige
   ROHE Rollenzugriff der ganzen Schicht — sie griff an der --v0t-*-Palette
   vorbei direkt auf --tp-color-surface2 und nannte, anders als jede andere
   Rollenbindung hier, ihren SCHRIFTPARTNER nicht (Waechter-Arm 1 sieht sie
   nicht: var() ist kein Farbliteral). Heutiger Schaden war 0 — ueber alle 12
   Kundenvorlagen gegengelesen kollabiert das Paar in 0 von 12 —, aber
   Regelhygiene ist genau der Punkt, an dem die naechste Runde ohne Absicht
   ausbricht. Jetzt ueber das Haus-Token, das denselben Rollenwert traegt.
   PAAR-REGEL (KORRIDOR §4): SCHRIFTPARTNER dieser Flaeche ist die geerbte
   Kartenschrift `color: var(--tp-color-body-text, #2C333C)` aus dem
   :root-Block (Freigabe "Grundtext"); die Flaeche wird deshalb bewusst NICHT
   mit einer eigenen color-Zeile belegt — sie wuerde die Serienzeile
   `.line.opencase` (Fristfarbe, Bedeutungstraeger) mit erben lassen, was
   KORRIDOR §3.9 als Basis-!important-Eigentum ausdruecklich ausnimmt.
   Rueckfall der Flaeche ist der Sockelton #F2F5F9 (hell), der der Schrift
   #2C333C (dunkel): das Paar traegt auch, wenn eine Kundenvorlage nur EINE
   der beiden Rollen fuehrt (minimal-brand fuehrt kein surface2 — dann
   greift der helle Rueckfall zur dunklen Rollenschrift; dunkle Vorlagen
   fuehren beide Rollen und drehen das Paar geschlossen). */
body.v2 .data-wrapper.opencase { background-color: var(--v0t-kaufbox); }

/* ---------------------------------------------------------------------
   Z14-E3 / GEO-B4 — DIE WARNBOX BEKOMMT IHREN FUSS ZURUECK (Z13-A).
   Befund (Fixture portal-order, je zwei Laeufe): u_karte = Unterkante
   #warning_open_cases bis Unterkante der tragenden Karte misst nackt
   0,0 px, _blank 0,0 px und unter Vorlage 0 ebenfalls 0,0 px — die Warnung
   klebt ohne Fuss an der Kartenkante. Der Z13-A-Fix des Katalogs steht auf
   Feature-Ebene von colors.alerts bzw. portal.warnboxen; v0final.json setzt
   weder colors.* noch portal.warnboxen, deshalb fuehrt die gebaute Datei
   0 Treffer fuer `warning_open_cases`, waehrend z. B. festival-dark.css die
   Zeile in Z. 563 hat. Vorlage 0 kann den Katalog nicht aendern (TABU), die
   Zeile aber in der eigenen Schicht fuehren — reine Geometrie (padding),
   keine Farbe, kein TABU-Selektor. Sollband Z13-A: 10-12 px.
   Verschaerft wird der Fall durch cards.box-merge: true, das die Naht zur
   Folgekarte auf 0 px zieht (nackt 30 px) — ohne Fuss stossen Warnung und
   Folgekarte damit unvermittelt aneinander.
   Bildbeleg: shots/vorlage0z14/fix/E3__warnbox__1280.png gegen
   shots/vorlage0z14/geometrie/G1_v0_portal_1280__warnbox-naht.png.
   --------------------------------------------------------------------- */
body.v2 :is(.box-light, .box-grey, .well, .panelx):has(> .line > #warning_open_cases),
body.v2 :is(.box-light, .box-grey, .well, .panelx):has(> #warning_open_cases) {
  padding-bottom: 10px;
}

/* ---------------------------------------------------------------------
   B6 / N5 — PORTAL-TITEL AUS DEM EINGABEFELD-LOOK (J7).
   Die Serie rendert den Gruppentitel als .well.well-sm.groupby; mit dem
   Kartensystem (weisse Flaeche + Haarlinie + Radius) sieht er aus wie ein
   deaktiviertes Eingabefeld (v0r2tief_portal-order_375__full.png).
   Spezifitaet muss die (0,5,1)-Kartenregel oben schlagen.
   --------------------------------------------------------------------- */
body.v2 .well.well-sm.groupby:not(.well-brand):not(.well-feature):not(.well-green) {
  background-color: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 2px 0 10px;
  font-size: 1.2em;
  font-weight: 700;
  line-height: 1.3;
}

/* ---------------------------------------------------------------------
   R2-B (2026-08-23, Bestaetigungsbefunde R2J2-1 SCHWER und R2J3-2) —
   DER PFLICHT-BESTELLKNOPF LIEF @375 AUS SEINEM EIGENEN KNOPF.

   BEFUND, an der echten K3-Position gemessen (Fixture payment, 375 px):
   a#initorder_layout mass 125,9…360,0 (234,1 x 54) bei font-size 17px;
   nach Polster blieben 176,0 px Innenraum fuer 224,8 px Text
   ("Zahlungspflichtig bestellen") — 47,7 px Ueberstand. Rund 20 px der
   Schrift lagen AUSSERHALB der orangefarbenen Knopfflaeche auf der dunklen
   Leiste, ca. 4,7 px ausserhalb des Fensters (letzte Zeichen gekappt), und
   das per stickyfooter.cta-chevron zugesagte Chevron war gar nicht mehr im
   Bild. Der NACKTE Shop zeigt denselben Text an derselben Stelle
   vollstaendig (247,4 x 36,8, 16px, 18,8 px Reserve, 0 Ueberstand) —
   Vorlage 0 war hier also schlechter als die Serie. @360 fehlten 60 px,
   unter stadion-energie @375 135 px, unter neon-nacht @375 113 px.
   Nebenwirkung derselben Ursache: der Warenkorb-Knopf wurde auf 40,0 px
   gequetscht (Inhalt 67 px) und zeigte nur noch das Symbol, waehrend er
   unter einer Kundenvorlage OHNE Vorlage 0 mit 112,2 px seine Beschriftung
   traegt.

   URSACHE, isoliert: v0final.json setzt "buttons.sticky-cta-gross": true.
   Der Katalog emittiert daraus
     body.v2 #stickyfooter a#initorder_layout.btn
       { font-size:17px !important; padding-left/right:28px !important }
   mit (2,1,2) — und schlaegt damit die eigene Mobilklemme M-1
     @media (max-width:480px) body.v2 #stickyfooter a#initorder_layout
       { font-size: clamp(11px,3.05vw,15px) !important; padding ... 10px }
   mit (2,0,2). Die Klemme war seit ihrer Einfuehrung unwirksam, sobald
   sticky-cta-gross gesetzt ist; ihr eigener Kommentar rechnet ausdruecklich
   mit 11,4px-Schrift und nennt payment@375 als engsten Fall.

   FIX HIER, nicht im Rezept: sticky-cta-gross ist am Desktop richtig und
   gewollt (@1280 misst der CTA 307 px mit 30/34 px Luft und sichtbarem
   Chevron). Zurueckgenommen wird nur der MOBILE Teil, indem die
   Katalog-Klemme an einer Spezifitaet wiederholt wird, die die
   Grosschrift-Zeile schlaegt: der Anker #stickyfooter-inner hebt die Regel
   auf (3,2,2) gegen (2,1,2). Der Wrapper ist kein Fixture-Artefakt —
   shop-tp-master app/views/application/sticky_footer*.haml Z.3/11 und
   layouts/manager.haml Z.161 rendern ihn in ALLEN Leisten-Varianten, und
   der Katalog selbst verankert daran bereits seine Hoehenzeile (v0final.css
   Z.902). Werte identisch mit M-1, damit die Leiste EINE Schriftfamilie
   behaelt (M-1/J4-S1: der Primaerknopf darf nicht schwaecher wirken als der
   Sekundaerknopf daneben).
   Kein Farbwert, keine Farb-Property — das !important ist nach KORRIDOR §6.3
   zulaessig (dort verboten sind ausschliesslich Farb-Properties) und
   unvermeidbar, weil die zu schlagende Katalogzeile selbst !important traegt.
   --------------------------------------------------------------------- */
@media (max-width: 480px) {
  body.v2 #stickyfooter #stickyfooter-inner a#initorder_layout.btn,
  body.v2 #stickyfooter #stickyfooter-inner a#initorder_amazon.btn {
    font-size: clamp(11px, 3.05vw, 15px) !important;
    letter-spacing: normal !important;
    padding-left: 10px !important;
    padding-right: 10px !important;
  }
}

/* ---------------------------------------------------------------------
   R2-C (2026-08-23, Bestaetigungsbefund R2J3-1) — DIE NICHT AKTIVEN
   PORTAL-REITER IM RUHEZUSTAND: 3,95 : 1 UND SCHLECHTER ALS NACKT.

   BEFUND, am Pixel gemessen (R1AB__portal-ticket__NEU__1280.png,
   Ausschnitt 108,158,380x24): Reiterschrift rgb(119,119,119) = #777 auf
   rgb(238,241,245) = --v0t-grund ergibt 3,95 : 1 bei 14 px — unter AA und
   unter dem nackten Shop (#777 auf #f8f8f8 = 4,22 : 1). Unter dunkler
   Kundenvorlage 4,05 : 1.
   URSACHE: das Rezept setzt portal.tab-navigation: "dezent". Die Option
   nimmt der Leiste die Platte (.navbar.navbar-default
   { background-color: transparent }) und setzt fuer den RUHEzustand keine
   Schriftfarbe — nur Hover/Fokus (primary-hover) und den AKTIVEN Reiter.
   Stehen bleibt damit der Bootstrap-Erbwert
   `.navbar-default .navbar-nav > li > a { color: #777 }` (0,2,2).
   Der Katalog-Kommentar DERSELBEN Option (W-12) belegt, dass der aktive
   Reiter genau an diesem Massstab geprueft und korrigiert wurde ("unter 4,5
   UND unter dem nackten Shop") — die nicht aktiven Reiter (in portal-ticket
   alle fuenf, kein li.active) nie. Traeger ist der Katalog und damit alle
   12 Vorlagen; das ist gemeldet. Vorlage 0 faengt es in der eigenen Schicht
   ab, und zwar FARBABSTINENT: --v0t-tief-500 haengt an --tp-color-body-text,
   folgt also der Kundenvorlage, statt einen zweiten festen Grauton neben
   #777 zu setzen (KORRIDOR §3.7 / FEEDBACK #1: Palette an Rollenfarben).
   Rueckfall #5E6773 auf --v0t-grund #EEF1F5 = 5,06 : 1 (gerechnet, gemessen
   in r2fix-portal.js).

   SPEZIFITAET MIT ABSICHT KLEIN: (0,5,3). Das schlaegt den Bootstrap-Erbwert
   (0,2,2), verliert aber gegen die Katalogzeilen fuer Hover/Fokus und fuer
   li.active (beide (0,7,3)) — die bleiben unangetastet. `:not(.active)` ist
   der zweite Riegel derselben Absicht: der aktive Reiter behaelt seine
   Auszeichnung auch dann, wenn eine spaetere Runde die Spezifitaeten
   verschiebt.
   --------------------------------------------------------------------- */
body.v2 .navbar.navbar-default .navbar-nav > li:not(.active) > a {
  color: var(--v0t-tief-500);
}

/* ---------------------------------------------------------------------
   R2-D (2026-08-23, Bestaetigungsbefund R2J3-3) — DIE PORTAL-SERIENLINIEN
   FEHLTEN NUR VORLAGE 0.

   BEFUND: generator/generator.js Z.185-262 (PANEL_INNER) fuehrt die
   gemessene Reparatur der rohen Portal-Serienlinien. Die Familie haengt an
   {{panelInner}} in catalog/colors.json; ALLE 12 gebauten Kundenvorlagen
   fuehren sie (12/12 Treffer auf ticket_details_closed), harness/previews/
   v0final.css hatte 0 Treffer — weil das Rezept bewusst keine colors.*-Achse
   setzt. Das Fehlen stand in KEINER Zeile von Charta, Register oder
   FEEDBACK, war also keine bewusste Abgrenzung, sondern eine Luecke.
   Gemessen am Stand 3e64d904: durchgehende Pixelspalten rgb(221,221,221)
   bei x = 85, 205, 338, 491, 662 (y152-186) — fuenf Striche bei fuenf
   Reitern, einer steht also VOR dem ersten und trennt dort nichts.
   Statusband der geschlossenen Ticketkarte rgb(187,187,187) auf
   rgb(255,255,255) = 1,92 : 1, 6 px hoch, volle Kartenbreite; in der Serie
   liegt es auf .box-light #e7e7e7, Vorlage 0 setzt die Karte auf
   --v0t-karte (weiss) — dadurch stand der Riegel frei.

   UEBERNOMMEN werden exakt die drei Zeilen der Katalogfamilie, unveraendert
   in Wert und Bauform (die Prozentwerte sind dort gegen den nackten Shop
   gemessen: 42 % Band, 18 % Trennstrich). Alle drei sind an currentColor
   gebunden und damit korridortreu (color-mix auf currentColor kann per
   Definition keine fremde Farbe setzen) — dieselbe Bauform, die die Schicht
   schon bei A17/A21/E3 fuehrt.
   Der Anker .navbar.navbar-default statt .navbar ist die Z4/a2-Lehre des
   Katalogs: an (0,4,2) verlor der Tonarm auf dem SPONSORENSHOP gegen
   body.sponsor .navbar .navbar-collapse .nav.navbar-nav li (0,5,2).
   REGISTERPOSTEN, kein heutiger Schaden: der OFFEN-Zustand traegt in der
   Serie border-top: 6px solid #E5C5C5 (custom_boxes.css.scss Z.218); in
   unseren Fixtures rendert davon kein sichtbarer Pixel.
   --------------------------------------------------------------------- */
body.v2 .ticket_details.ticket_details_closed .box-light .box-inner {
  border-top-color: color-mix(in srgb, currentColor 42%, transparent);
}
body.v2 .navbar.navbar-default .nav.navbar-nav li {
  border-left-color: color-mix(in srgb, currentColor 18%, transparent);
}
body.v2 .navbar .nav.navbar-nav > li:first-child {
  border-left-color: transparent;
}

/* ---------------------------------------------------------------------
   R3-B (Bestaetigungsbefund R3J2-1, 2026-08-23) — HALBOFFENES PAAR IN DER
   KAUFLEISTE: MANAGE STELLT DIE FLAECHE, VORLAGE 0 HAELT DIE SCHRIFT FEST.

   MECHANIK. emit-eventstyle.js Z157-159 emittiert EINEN Block mit ZWEI
   unabhaengigen Reglern (#stickyfooter background-color / color, beide
   !important); dasselbe noch einmal fuer body.withiframe #stickyfooter
   (Z161-163). Ist nur brand_stickyfooter_bgcolor gesetzt — dieselbe reale
   Teilkonfiguration, die J2-B1 fuer die Fusszeile anerkannt hat —, gewinnt
   K2 die FLAECHE, waehrend die Zeile oben (`body.v2 #stickyfooter { color:
   #FFFFFF }`) die SCHRIFT behaelt. Verschaerfend nehmen die Rezeptoptionen
   stickyfooter.warenkorb-stil und .countdown-stil den beiden Bedienknoepfen
   ihre eigene Flaeche (background-color: transparent; color: inherit) — sie
   erben damit die Leistenfarbe und stehen als weisse Geisterschrift auf
   hellem Grund.
   GEMESSEN (r3fix-leiste.js, Fixture payment, @1280, echte K3-Position):
   nur bgcolor hell #F2F4F7 — Countdown "09:13" und "Warenkorb (3)" je
   1,10 : 1; nackter Shop in derselben Zelle 12,63 : 1, weil er den Knoepfen
   ihre weisse Serienflaeche laesst.
   WARUM NICHT WIE POSTEN #10 UNLOESBAR: dort geht es um Text DIREKT auf der
   Manage-Flaeche — ein fester Ton kann hell und dunkel nicht zugleich
   bedienen. Hier tragen die beiden Bedienelemente eine EIGENE Flaeche; wer
   Flaeche und Schrift als Paar selbst setzt, macht die Leistenfarbe fuer die
   Lesbarkeit irrelevant. Kein !important auf einer Farb-Property noetig.
   BINDUNG AN DIE ROLLENFARBE, nicht an einen festen Ton: --tp-color-sticky-bg
   / --tp-color-sticky-text sind genau die Token, aus denen ALLE ZWOELF
   Kundenvorlagen ihre Leistenfarbe emittieren (nachgezaehlt: Tokenwert ==
   emittierter Literalwert in 12 von 12). Unter einer Kundenvorlage ist die
   Knopfflaeche darum bitgleich mit der Leiste — die Optik "Nur Text" bzw.
   "Pille ohne Fuellung" bleibt exakt erhalten. Ohne Kundenvorlage faellt sie
   auf die eigene Leistenfarbe --v0t-tief-800 zurueck, also ebenfalls auf den
   Ist-Zustand. Sichtbar wird die Regel NUR dort, wo sie gebraucht wird: wenn
   Manage die Leiste allein umfaerbt.
   SPEZIFITAET: die Selektorlisten sind wortgleich die staerksten
   Katalogvarianten desselben Bauteils (Warenkorb (3,3,1), Countdown (2,6,1),
   Schloss-Knopf (2,5,1)). Gleichstand + spaetere Position gewinnt; damit
   bleibt die Kundenvorlage, die NACH uns laedt, ungehindert im Vorrang.
   HOVER-RUECKGABE: der Katalog hebt den Warenkorb im Hover um
   rgba(128,128,128,0.18); dieselbe Anhebung wird hier auf der eigenen
   Flaeche nachgebaut (18 % #808080 hineingemischt), damit der bediente
   Zustand nicht verloren geht. Der Countdown bleibt in allen Zustaenden
   flaechengleich — "dezent" heisst dort ausdruecklich ohne Zustandsflaeche.
   --------------------------------------------------------------------- */
body.v2 #stickyfooter #show_shopping_cart,
body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart {
  background-color: var(--tp-color-sticky-bg, var(--v0t-tief-800));
  color: var(--tp-color-sticky-text, #FFFFFF);
}
body.v2 #stickyfooter #show_shopping_cart:hover,
body.v2 #stickyfooter #show_shopping_cart:active,
body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart:hover,
body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart:active {
  background-color: color-mix(in srgb, #808080 18%, var(--tp-color-sticky-bg, var(--v0t-tief-800)));
  color: var(--tp-color-sticky-text, #FFFFFF);
}
body.v2 #stickyfooter .countDownTimer,
body.v2 #stickyfooter .countDownTimer:hover,
body.v2 #stickyfooter .countDownTimer:focus,
body.v2 #stickyfooter .countDownTimer:active,
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer,
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer:hover,
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer:focus,
body.v2 #stickyfooter #stickyfooter-inner .btn-group .btn.btn-default.countDownTimer:active {
  background-color: var(--tp-color-sticky-bg, var(--v0t-tief-800));
  color: var(--tp-color-sticky-text, #FFFFFF);
}
body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer),
body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):hover,
body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):focus,
body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group .btn:not(.countDownTimer):active {
  background-color: var(--tp-color-sticky-bg, var(--v0t-tief-800));
  color: var(--tp-color-sticky-text, #FFFFFF);
}

/* ---------------------------------------------------------------------
   R3-C (Bestaetigungsbefund R3J3-1, 2026-08-23) — DIE DRITTE VERGROESSERUNG
   DER KAUFLEISTE WAR VON DER MOBILKLEMME NICHT EINGEFANGEN.

   BEFUND. buttons.sticky-cta-gross vergroessert den CTA dreifach:
   Schriftgrad, Seitenpolster — beide hat R2-B unter 481 px zurueckgenommen —
   UND die Knopfhoehe. Die Hoehe haengt an
     body.v2 #stickyfooter a#initorder_layout { --tp-sticky-btn-h: 54px }
   (v0final.css Z.243), also AM KNOPF SELBST und ohne Media-Grenze. Die
   Serienzeile
     @media (max-width:480px) body.v2 #stickyfooter { --tp-sticky-btn-h: 40px }
   steht am ELTERNKNOTEN und verliert deshalb: der Element-Wert schlaegt den
   geerbten. Verbraucher ist
     a#initorder_layout { min-height: var(--tp-sticky-btn-h,42px);
                          line-height: calc(... - 2px) }.
   GEMESSEN am Pixel (festival-dark, payment @375): Leiste 71,0 px, CTA
   55,0 px, Countdown-Pille 40,0 px — 15 px Hoehenunterschied in EINER Reihe.
   Vorlage 0 allein: Warenkorb 39,3 px gegen CTA 54,3 px.
   ZWEITE FOLGE: --tp-sticky-reserve wird auf body.v2 gebildet und liest dort
   das 40-px-Token (8+8+40+0+0+20 = 76 px). Die Leiste ist aber 71 px hoch,
   also blieben von den zugesagten 20 px --tp-sticky-gap nur 5 px.
   "--tp-sticky-btn-h: 54px" steht in KEINER der zwoelf gebauten
   Kundenvorlagen; sie koennen ihre 40-px-Mobilhoehe nicht zurueckholen,
   sobald Vorlage 0 darunter liegt.
   FIX, exakt in der Bauform von R2-B: nur der MOBILE Teil der Option wird
   zurueckgenommen, und zwar an derselben Stelle, an der die Option ihn setzt
   (am Knopf), mit gleicher Spezifitaet und spaeterer Position. Am Desktop
   bleibt sticky-cta-gross vollstaendig wirksam — die Regel steht in
   @media (max-width:480px) und keinen Pixel darueber (Gewinnerprobe an der
   Kante 481/480 in r3fix-leiste.js).
   Kein Farbwert, keine Farb-Property, kein !important.
   --------------------------------------------------------------------- */
@media (max-width: 480px) {
  body.v2 #stickyfooter a#initorder_layout,
  body.v2 #stickyfooter a#initorder_amazon {
    --tp-sticky-btn-h: 40px;
  }
}

/* ---------------------------------------------------------------------
   R4-A (Bestaetigungsbefunde R4J3-1 und R4J3-2, 2026-08-23) —
   ZURUECKHALTUNG DARF NICHT AUS DECKUNG KOMMEN.

   GEMEINSAME WURZEL BEIDER BEFUNDE. Vorlage 0 ist farbabstinent, und alle
   bisherigen Waechter-Arme und Sonden dieser Runde messen FARB-Properties.
   Zwei Rezeptoptionen erzeugen ihre "dezente" Wirkung aber ueber `opacity` —
   eine farblose Deklaration, die den GEMALTEN Pixel aufhellt. Beide sind
   damit an jeder Pruefung dieses Loses vorbeigelaufen; die Entlastungsliste
   der Gegenpruefung hat den Sprachumschalter sogar mit 10,02 : 1 zu Protokoll
   gegeben — das ist der unkomponierte Farbwert, nicht der Bildschirm.

   (a) forms.hinweis-texte: "dezent"  ->  .help-block { opacity: 0.75 }
       K1 (base_bootstrap_ticketpay Z.2793) faerbt .help-block mit #737373.
       0,75 * 115 + 0,25 * 255 = 150 je Kanal -> rgb(150,150,150) auf Weiss
       = 2,96 : 1. Ohne die Abblendung 4,74 : 1. Der Zustand "Vorlage 0
       allein" IST der Standardshop, fuer den diese Vorlage gebaut ist —
       dort steht die Zahl unter AA UND schlechter als der nackte Shop.
       Dasselbe Kriterium hat diese Runde bei W-12 und R2-C zum Fix gefuehrt;
       der Abstand ist hier groesser.
   (b) footer.sprachwahl-stil: "dezent"  ->  li.dropup > a { opacity: 0.7 }
       0,7 * (42,50,60) + 0,3 * (220,227,235) = (95,103,113) auf --v0t-fuss
       = 4,43 : 1, waehrend der Nachbarlink derselben Zeile 10,02 : 1 misst.
       Die Auflage Z14-F2 nennt die GEOEFFNETE Sprachwahl — die ist mit
       `li.dropup.open > a { opacity: 1 }` erfuellt. Gebrochen war der
       geschlossene RUHEZUSTAND desselben Bedienelements.

   WARUM DIE DECKUNG UND NICHT DER TON DAS PROBLEM IST: `opacity` mindert den
   Kontrast eines FREMDEN Farbpaares. Welche Fusszeilenfarben der Kunde ueber
   K1/K2 oder seine Vorlage stellt, wissen wir nicht; ein Paar, das er auf
   4,6 : 1 einstellt, faellt unter unserer 0,7er-Deckung auf 3,2 : 1. Eine
   Vorlage, die keine Farben setzt, darf auch keine Kontraste verbrauchen.
   Das ist dieselbe Linie wie R1-C (der bediente Zustand aendert die FARBE
   nicht mehr) und wie `.subtotal li.final` (Hervorhebung absichtlich farblos
   ueber Groesse, Gewicht und Linie, KORRIDOR Z.287).

   FIX. Beide Abblendungen werden in der eigenen Schicht zurueckgenommen. Die
   "dezente" Lesart bleibt erhalten, aber ueber Merkmale, die auf JEDER
   Flaeche dieselbe Sichtbarkeit haben wie die Schrift selbst:
     - Hilfetexte: `font-size: 12px` der Option bleibt unangetastet — dezent
       ueber die GROESSE.
     - Sprachwahl: der bediente Zustand wird ueber die UNTERSTREICHUNG
       getragen, wortgleich der Bauform, die R1-C fuer die Fusszeilen-Links
       gewaehlt hat (Staerke + Abstand). Ohne diese Zeile haette der
       Umschalter nach der Ruecknahme GAR KEINE Hover-Rueckmeldung mehr —
       der Katalog nimmt `li.dropup` von der Unterstreichungsfamilie
       ausdruecklich aus (Z.929/930 `li:not(.dropup)`).
   Kein Farbwert, keine Farb-Property, kein !important, keine neue Freigabe.
   Gleiche Spezifitaet wie die Katalogzeilen, spaetere Position — die
   Kundenvorlage, die NACH uns laedt, bleibt ungehindert im Vorrang.
   NICHT ANGETASTET: `.has-error .help-block` (stand ohnehin auf 1) und die
   Katalogachse selbst — der Traeger ist der Katalog, gemeldet ist er als
   Registerposten R4-#2/#3.
   --------------------------------------------------------------------- */
body.v2 .help-block {
  opacity: 1;
}
body.v2 footer li.dropup > a {
  opacity: 1;
}
body.v2 footer li.dropup > a:hover,
body.v2 footer li.dropup > a:focus-visible,
body.v2 footer li.dropup.open > a {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}

/* =====================================================================
   LOS f1 — CEO-DETAILFEEDBACK vom 2026-08-23, Punkte P11 und P13.
   Traeger der Punkte P10 (carousel.pfeil-stil: dezent), P12
   (modals.close-button: ghost-quadrat) und der Anordnung von P11
   (stickyfooter.layout: kompakt) ist der KATALOG — sie stehen im Preset
   und nicht hier. Was hier steht, ist nur, was der Katalog nicht kann.
   ===================================================================== */

/* ---------------------------------------------------------------------
   P11 — KAUFLEISTE: HOEHE UND SENKRECHTE MITTE.

   BEFUND (gemessen an echter K3-Position, gruene Kundenfarbe):
   Leiste @1280 74,0 px; Schloss und Timer sassen 8,0 px, Warenkorb-Chip
   und Weiter-Knopf 2,0 px UEBER der senkrechten Mitte. Zwei Ursachen,
   sauber getrennt:
     (1) Ueber 480 px trug die Serie .pull-left/.pull-right als FLOATS —
         die 42-px-Pillengruppe fluchtete oben gegen die 54-px-CTA-Gruppe.
         Das loest die Katalogachse "stickyfooter.layout: kompakt"
         (Flexzeile mit align-items:center in ALLEN Breiten) im Preset.
     (2) Der Rest waren 2,0 px in JEDER Breite: ohne gesetzten
         --tp-sticky-pad-bottom griff im Polster der Rueckfall 12px
         (stickyfooter.ios-safe-area) gegen padding-top 8px — unten
         4 px dicker als oben, Inhalt 2 px zu hoch. Auch DAS erledigt
         "kompakt" im Katalog: die Achse setzt beide Polster-Token auf
         6px, damit greift kein Rueckfall mehr und das Polster ist
         symmetrisch. Gemessen 6/6, Versatz 0,00.
         DESHALB STEHT HIER KEINE PAD-ZEILE. Die Analyse hatte
         --tp-sticky-pad-bottom: 8px vorgeschlagen und die Auflage hat
         das uebernommen — beides an einer Probe gemessen, die den
         Token-Block der Katalogoption noch nicht enthielt. Mit der
         echten Option ergaebe 8px gegen 6px wieder eine Asymmetrie und
         damit −1,0 px Versatz auf ALLEN Elementen (nachgemessen, siehe
         FIX.md §P11). Die Auflage will die exakte Mitte; die liefert
         der Katalog allein. Das env(safe-area-inset-bottom) im max()
         bleibt Sieger, wo es einen Inset gibt — iPhone-Zusage unberuehrt.

   Die Knopfhoehen sind HART auf min-width:481px geklemmt. Darunter gilt
   weiter R3-C: der Leisten-CTA misst @375 bewusst 41 px, weil
   buttons.sticky-cta-gross seine 54 px sonst am Knopf gegen die 40-px-
   Mobilzeile der Serie durchsetzt und keine der zwoelf Kundenvorlagen
   ihre Mobilhoehe zurueckholen kann. NICHT ZU VERWECHSELN mit Charta
   §B4 ("In den Warenkorb" >= 48 px @375) — das ist der KAUFKNOPF im
   Inhalt, gemessen 50 px, von diesem Los nicht angefasst.

   DIE DRITTE ZEILE IST DIE RESERVE (Auflage 4, Risiko R4).
   --tp-sticky-reserve wird auf body.v2 gebildet und liest den
   Knopfhoehen-Token DORT — also den :root-Wert 40px, nicht die 48px
   der Leiste. Reserve 6+6+40+20 = 72 px gegen eine 60-px-Leiste: von
   den zugesagten 20 px --tp-sticky-gap blieben 12. Die Zeile stellt
   den Token ab 481 px auch auf body.v2 auf die tatsaechliche Zeilen-
   hoehe 48px -> Reserve 80 px, Luft exakt 20 px. Sie kann die Leiste
   selbst nicht verstellen: JEDER Verbraucher des Tokens sitzt in
   #stickyfooter, und #stickyfooter traegt eine Zeile darueber seinen
   eigenen Wert (44px) — der Elementwert schlaegt den geerbten.
   Unter 481 px bleibt die Rechnung unangetastet.
   Kein Farbwert, keine Farb-Property, kein !important.
   --------------------------------------------------------------------- */
@media (min-width: 481px) {
  body.v2 #stickyfooter {
    --tp-sticky-btn-h: 44px;
  }
  body.v2 #stickyfooter a#initorder_layout,
  body.v2 #stickyfooter a#initorder_amazon {
    --tp-sticky-btn-h: 48px;
  }
  body.v2 {
    --tp-sticky-btn-h: 48px;
  }
}

/* ---------------------------------------------------------------------
   P13 — KARTENKOPF-BRUCH: DIE DURCHGEZOGENE KARTE (Judge-Entscheid,
   Variante (a) mit Auflage 1).

   BEFUND. Bei "Information" (.wrap:not(.accordions), A19) und bei den
   offenen Ticketgruppen ("Get your Paket") liegen Kopf und Karte mit
   Spalt 0,0 px und Breitendifferenz 0,0 px exakt aufeinander — der
   sichtbare Bruch ist REIN DIE KANTE: der Kopf hat keine Seitenlinien,
   die Karte hat welche, und sie beginnen abrupt an der Naht. Bei den
   Gruppen kommt die eigene OBERKANTE der Karte dazu, also eine
   Haarlinie unter einem randlosen Kopf.

   LOESUNG. Der Kopf bekommt DIESELBE Haarlinie wie die Karte und laeuft
   in die Kartenkante ein: ein Umriss um Kopf UND Inhalt. Das fuehrt die
   Charta-Sprache cards.border: hairline + cards.radius: 8 konsequent zu
   Ende, statt sie an der Naht abreissen zu lassen. Die beiden anderen
   vorgelegten Varianten (randlos mit Haarlinie / ganz randlos) loesen
   die Karte auf weisser Kundenflaeche sichtbar auf — Vorlage 0 setzt
   cards.shadow: none, und Kunden stellen einzelne Flaechenregler ohne
   Gegenstueck (Fusszeilen-Befunde 10/15).

   AUFLAGE 1 — DIE TRENNUNG BLEIBT. Der Gruppenkopf behaelt die Linie
   unter dem Kopf; sie wandert nur von der Kartenoberkante an die
   Kopfunterkante und traegt dort das Trenn-Token --v0t-linie-2 statt
   des Umriss-Tokens --v0t-kante. Der Originalstand hat diese Linie —
   sie darf nicht Nebenwirkung des Kantenfixes werden. "Information"
   hatte sie nie und bekommt sie auch jetzt nicht.

   AUFLAGE 2 — RUNDUNGS-RUECKHOLUNG @375. Unter 769 px nimmt die SERIE
   der Karte die Rundung (@only screen and (max-width:768px) body.v2
   .wrap .wrap_content .well { border-radius: 0 }, Spezifitaet 0,3,1).
   Vorlage 0 holt Flaeche und Rand zurueck, die Rundung bisher nicht —
   deshalb stand @375 eine eckige Karte unter einem 8-px-gerundeten
   Kopf. Die Zeile stellt cards.radius: 8 wieder her, mehr nicht.

   ANGEFASST WIRD NUR DER GEOEFFNETE ZUSTAND. Der GESCHLOSSENE
   Akkordeonkopf (Befund J-A1) ist heute schon eine vollstaendige Karte
   mit Umriss und 8 px ringsum und traegt keinen Bruch — er bleibt
   bitgleich (per Pixeldiff belegt, FIX.md §P13). .wrap_content wird
   nicht angefasst (JS-Eigentum).

   DER UMRISS KOMMT AUS DEM KATALOG, NICHT AUS EINEM ZWEITEN TON.
   Die Karte traegt ihren Umriss aus --tp-border-panel (cards.border:
   hairline, Rueckfall rgba(0,0,0,0.08)); --v0t-kante bindet dieselbe
   Rolle, hat aber den EIGENEN Rueckfall #DCE3EA. Beide sind identisch,
   sobald eine Kundenvorlage --tp-color-border stellt — aber "Vorlage 0
   allein" ist der Standardshop, und dort sind es zwei verschiedene
   Graustufen. Ein Kopf auf --v0t-kante haette den GEOEFFNETEN Karten
   einen dunkleren Umriss gegeben als den geschlossenen daneben: der
   Kantenbruch waere durch einen Tonbruch ersetzt worden. Deshalb liest
   der Kopf DIESELBE Deklaration wie die Karte und wie der geschlossene
   Akkordeonkopf (Katalogzeile: border: var(--tp-border-panel, 0)).
   Aus demselben Grund bekommt die Karte KEINE neuen Seitenlinien —
   sie hat sie schon; angefasst wird nur ihre Oberkante.
   Kein !important, kein Farbwert ausser den vorhandenen Rollen-Token.
   --------------------------------------------------------------------- */

/* (Auflage 2) Rundung der Karte unter 769 px zurueckholen. Gleicher
   Geltungsbereich wie die Kantenregel darunter — Warenkorb-Zweig
   ausgenommen, Begruendung dort. */
body.v2 .wrap:not(.accordions):not(:where(#shopping_cart) .wrap) .wrap_heading + .wrap_content .well,
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) .wrap_content .well {
  border-bottom-left-radius: var(--tp-radius-panel, 8px);
  border-bottom-right-radius: var(--tp-radius-panel, 8px);
}

/* (a) Der Kopf traegt den Umriss mit — eine durchgezogene Karte.

   DIE WARENKORB-SPALTE IST AUSGENOMMEN, und das ist keine Kosmetik.
   Ein Kopf ohne Unterkante ergibt nur dann eine geschlossene Form,
   wenn die Karte buendig darunter anschliesst und dieselbe Breite hat.
   Im Warenkorb-Zweig ist beides nicht so: die Serie/der Katalog setzt
   dort .well auf width:fit-content mit margin-left:auto (gemessen
   620,6 px schmaler als der Kopf @1280, 5 px @375) und schiebt den
   Inhalt teils um 6 px nach unten. Ohne die Ausnahme stuende dort ein
   Kasten mit drei Kanten und OFFENER Unterkante — schlimmer als der
   Bruch, den diese Regel heilt. Belegt ueber alle 28 Fixtures in
   beiden Breiten (scan-koepfe.js): der Warenkorb ist der einzige
   nicht-buendige Fall; danach 0 Befunde.
   Die Ausnahme steht IM SELEKTOR, nicht als spaetere Ruecknahme:
   scheitert ein Browser an :has()/:not(), faellt die ganze Regel aus
   und der Stand ist der Originalstand — nie der offene Kasten. Das
   :where() haelt die ID aus der Spezifitaet heraus; die Regel bleibt
   damit so leicht, dass die Kundenvorlage sie weiter schlagen kann. */
body.v2 .wrap:not(.accordions):not(:where(#shopping_cart) .wrap) .wrap_heading,
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) .wrap_heading {
  border: var(--tp-border-panel, 1px solid var(--v0t-kante));
  border-bottom: 0;
}
/* (b) DIE NAHT ENTSTEHT DURCH UEBERLAPPUNG, NICHT DURCH WEGNAHME.
   NACHFIX f2 (Verifiziererbefund B1, 2026-08-24).

   Vorher stand hier `border-top: 0` — die Gruppenkarte gab ihre
   Oberkante ab, damit unter dem Kopf nur EINE Linie steht. Das ist
   richtig, SOLANGE die Karte buendig unter dem Kopf sitzt. Genau das
   ist aber keine Eigenschaft des DOM, sondern eine Eigenschaft der
   Kaskade: die Serie setzt
       body.v2 .wrap.accordions .wrap_heading + .wrap_content
         { margin-top: 6px }
   und erst eine Katalogoption holt die 6 px auf 0 zurueck. Vorlage 0
   hat diese Option, elf der zwoelf Kundenvorlagen ebenfalls —
   `minimal-brand` NICHT (minimal-brand.css:749, dazu 12 px Rundung
   Z747 und ein Kartenschatten Z764: die schwebende Karte ist dort ein
   identitaetstragendes Merkmal, Kernregel 7). Dort stand nach Los f1
   ein Kopf als geschlossener Kasten, 6 px Seitengrund, und darunter
   eine Karte mit Seiten- und Unterkante, aber OFFENER Oberkante —
   genau die Form, die weiter oben fuer den Warenkorb-Zweig als
   "schlimmer als der Bruch" verworfen wurde, nur eine Kaskadenschicht
   hoeher. 1 von 12 Vorlagen, 6 von 72 Zellen, @1280 und @375.

   CSS kann die Buendigkeit nicht abfragen — weder :has() noch eine
   Style-Query sieht einen fremden margin-top. Also darf die Form gar
   nicht erst von ihr abhaengen: BEIDE Kaesten bleiben geschlossen,
   und die doppelte Linie im buendigen Fall wird nicht durch Wegnahme
   vermieden, sondern dadurch, dass die Kartenoberkante genau 1 px
   unter die Kopfunterkante rutscht und deren Zeile deckt. Das ist
   dieselbe Zeile Bildschirm, nicht zwei.

   WARUM `border-top-width: 1px` DAZUGEHOERT — und nicht die volle
   Tokenbreite. Bei den beiden 2-px-Vorlagen (`mono-kontrast`,
   `adventure-fixed`) haette eine 2 px hohe Kartenoberkante mit nur
   1 px Ueberlappung eine 3-px-Naht ergeben, wo heute 2 px stehen: die
   Trennlinie waere um die Haelfte schwerer geworden — dieselbe
   Nebenwirkung, die Auflage 1 weiter unten ausdruecklich verbietet.
   Gedeckelt auf 1 px steuert die Karte genau die eine Zeile bei, die
   die Ueberlappung wieder verschluckt. Gemessen am Pixel (senkrechte
   Farbspalte durch die Naht, f2-pixel.js): Vorlage 0 allein, Serien-
   und Kundenfarbe, sowie mono-kontrast, corporate-blau, elegant-serif,
   tech-minimal, warm-craft, adventure-fixed sind VOR und NACH
   BITGLEICH. Die fuenf randlosen Vorlagen (`--tp-border-panel: 0`)
   bekommen KEINE Linie — border-top-style bleibt dort `none`, und ein
   Rand ohne Stil rechnet sich auf 0 px; bei ihnen wandert allein die
   Grenze zwischen zwei Flaechen um 1 px, ohne Kante und ohne
   Farbwechsel. Unter `minimal-brand` traegt die Karte ihre Oberkante
   wieder, der Spalt misst 5 statt 6 px.

   DIE BREITE STEHT ALS LANGFORM NEBEN DEM SHORTHAND MIT FARBE, nicht
   allein: `border-top` nennt zuerst dieselbe Rollen-Deklaration, die
   die Karte ohnehin aus dem Katalog traegt (`--tp-border-panel`), erst
   danach deckelt die Langform die Breite. Damit setzt diese Regel
   keine Rahmenfarbe still auf currentColor um — der Waechterarm 2b
   liest die Farbe in derselben Regel und braucht keine neue Freigabe.
   Kein !important, kein Farbwert ausser der vorhandenen Rolle. */
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) .wrap_content .well {
  border-top: var(--tp-border-panel, 0);
  border-top-width: 1px;
  margin-top: -1px;
}

/* (Auflage 1) Die Trennlinie der GRUPPEN bleibt — sie wandert nur von
   der Kartenoberkante an die Kopfunterkante. "Information" hatte nie
   eine und bekommt auch keine.

   ABWEICHUNG VOM WORTLAUT DER AUFLAGE, MIT BILD BELEGT. Die Auflage
   schreibt --v0t-linie-2 vor. Gebaut, fotografiert, verworfen: die
   Originallinie IST die Kartenoberkante, also --tp-border-panel und
   damit rgba(0,0,0,0.08) = rgb(234,234,234) auf Weiss; --v0t-linie-2
   faellt standalone auf #C7D0DA = rgb(199,208,218) zurueck. In der
   Lupe (shots/vorlage0f1/ab/lupe/NAHT_gruppenkopf__*__1280.png gegen
   NAHTB_*) steht die Linie im Auflagen-Wortlaut deutlich schwerer da
   als im Originalstand — und sie waere zugleich dunkler als der
   Umriss, den sie unterteilt. Der BEGRUENDETE Teil der Auflage lautet
   "der Originalstand hat diese Linie; sie darf nicht Nebenwirkung des
   Kantenfixes werden" — ein dreifach staerkerer Strich waere genau so
   eine Nebenwirkung, auf einem identitaetstragenden Merkmal
   (Kartenlandschaft, Kernregel 7). Deshalb traegt die Linie hier
   dieselbe Quelle wie vorher: gleiche Deklaration, andere Kante.
   Beide Staende sind fotografiert, die Wahl ist belegt, nicht
   behauptet (FIX.md §P13). */
body.v2 .wrap.accordions:has(.wrap_heading i.fa-minus-circle) .wrap_heading {
  border-bottom: var(--tp-border-panel, 1px solid var(--v0t-kante));
}

/* ---------------------------------------------------------------------
   P12 — SCHLIESSER AUF DIE TITELLINIE (Auflage 5, farblose Zeile).

   Die Katalogoption modals.close-button: "ghost-quadrat" liefert die
   ruhige SOCKEL-Form (36 x 36 Trefferflaeche, Knopf-Rundung der
   Vorlage, Rand aus currentColor, Fokusring). Ihr margin
   "-7px -6px 0 12px" stammt aber noch von der 21-px-Serienglyphe: mit
   der 36-px-Flaeche sitzt der Schliesser 3,85 px UEBER der Mitte des
   Dialogtitels (gemessen, @1280 und @375 gleich).
   Angefasst werden NUR die beiden senkrechten Aussenabstaende —
   Laengenangaben, kein Farbwert, keine der uebrigen Eigenschaften der
   Option. Die seitlichen Abstaende der Option bleiben, damit die
   Flaeche weiter buendig in der Kopfecke sitzt.

   WARUM ZWEI ZEILEN UND NICHT EINE: der Schliesser ist ein Float im
   Kopf. Nur margin-top zu loesen, schiebt seine Marginbox 3,3 px unter
   die Titelzeile — der Dialogkopf wuchs in der ersten Probe von
   70,7 auf 74,0 px. Der negative untere Abstand nimmt genau das
   zurueck (−3 + 36 − 4 = 29 px Marginbox gegen 30,7 px Titelzeile):
   der Kopf bleibt auf seiner Originalhoehe, der Schliesser steht
   trotzdem auf der Titellinie. Gemessen: Versatz −3,85 -> +0,15 px,
   Kopfhoehe 70,7 px — auf die Nachkommastelle der Originalstand
   (mit −3 px unten waeren es 71,0 px gewesen).
   --------------------------------------------------------------------- */
body.v2 .modal-header .close {
  margin-top: -3px;
  margin-bottom: -4px;
}

/* =====================================================================
   F2 — ORGANIZER-FILTERLEISTE UND DATUMSWAEHLER
   Quelle: CEO-Feedback 2026-08-25 ("Ticketshop-Card wirkt alt — Suchfeld,
   Datumsfeld, Liste/Galerie-Knoepfe und BESONDERS der Kalender").
   Analyse: scratchpad/vorlage0f2/ANALYSE.md · Jury-Entscheid: VARIANTE B
   ("Symbol im Feld + Segment-Pille") plus der gemeinsame Kalender-Skin,
   mit sieben Auflagen. Protokoll: scratchpad/vorlage0f2/FIX.md.

   REICHWEITE, ausnahmslos: jeder Selektor dieses Abschnitts enthaelt
   #organizer_events_search ODER .daterangepicker. Die Titelcard selbst
   (.jumbotron, h1.text-system, der Trenner) wird NICHT angefasst — sie
   steht bereits in der Sockel-Sprache (Radius 8, Haarlinie, weicher
   Schatten, Polster 21; ANALYSE §1.2). Der Bruch, den der CEO sieht,
   sitzt eine Ebene tiefer: die Bedienelemente IN der Karte trugen
   unveraendert die Bootstrap-3-Toene (#eee / #ccc / #555,
   Innenschatten, grauer Aktivzustand) und waren von Vorlage 0 bisher
   nur vergroessert und gerundet, nie umgetont.

   JS-EIGENTUM (Auflage 7): das Popup .daterangepicker wird von
   daterangepicker.js geoeffnet, bemessen und positioniert. Dieser
   Abschnitt fasst an ihm KEIN display, height, top, left, position,
   z-index oder width an — nur Optik (Radius, Rand, Schatten, Polster,
   Toene, Schriftgroessen). Ebenso wird die Umschalter-Logik
   (.active-Klasse aus dem Seiten-JS) nicht beruehrt: beide Segmente
   sind ueber .show_events ausformuliert, in BEIDEN Zustaenden, nie
   ueber eine der beiden ids.

   !IMPORTANT — DIE EINE NAMENTLICHE AUSNAHME:
     body.v2 #organizer_events_search .btn-group > .btn.show_events
       { border-radius: var(--tp-radius-button, 6px) !important }
   Grund, gemessen: der Katalog nagelt die Form der Knopfgruppe mit drei
   !important fest (Z9-A gegen den zerfallenden Umschalter, Z12-K12 fuer
   die Kopfgruppen):
     body.v2 .btn …                              border-radius: … !important
     body.v2 .btn-group > .btn:not(:first-child) border-*-left-radius: 0 !important
     body.v2 .btn-group > .btn:not(:last-child)  border-*-right-radius: 0 !important
   Ohne dieselbe Waffe bleibt JEDE Radiusangabe hier wirkungslos — die
   erste Probenrunde mass unveraendert 6/0/0/6, also zwei Halbmonde statt
   zweier Segmente. border-radius ist keine Farb-Property; KORRIDOR §6.3
   ist unberuehrt. Es ist das EINZIGE !important dieses Abschnitts.
   NACHFIX B-3 (a): der Wert ist nicht mehr die feste 999-px-Pille,
   sondern --tp-radius-button — der Radius DER JEWEILIGEN VORLAGE. Die
   Zeile hebt damit nur noch die Eckenabflachung auf und setzt keine
   eigene Knopfform mehr ueber alle zwoelf Vorlagen.

   SPEZIFITAETSDUELL (gemessen, sonst wirkungslos): zwei Katalogarme
   fuehren :not(#redeem_coupon):not(#redeem_cross_out_coupon) und holen
   sich daraus ZWEI ID-Punkte —
     forms.groesse   body.v2 .form-control:not(.show_quantity_select)
                     :not(#redeem_coupon):not(#redeem_cross_out_coupon)   (2,3,1)
     select-pfeil    body.v2 select.form-control.form-control
                     :not(#redeem_coupon):not(#redeem_cross_out_coupon)   (2,3,2)
   Eine Regel mit #organizer_events_search allein hat (1,4,1) und
   VERLIERT. Die beiden Guards werden darum woertlich mitgefuehrt; die
   Reichweite bleibt trotzdem auf die Filterleiste beschraenkt, weil
   #organizer_events_search davorsteht.

   FARBEN: jede Farbe dieses Abschnitts kommt aus den --v0t-Rollenketten
   (var(--tp-color-…)) oder ist achromatisch. Bewusst OHNE
   Rueckfall-Literal geschrieben — die Token sind im :root-Block dieser
   Datei ausnahmslos definiert, und ein zweiter Ort mit Farbwerten waere
   genau die Streuung, die Waechter-Arm 1 verhindern soll. Keine dritte
   Buntfarbe, kein !important auf einer Farb-Property.
   ===================================================================== */

/* ---------------------------------------------------------------------
   F2-1 — DIE GRUPPE IST DAS FELD.
   Der Vorsatzkasten verschwindet als KASTEN, das Symbol bleibt und sitzt
   im Feld. Flaeche, Kante und Radius wandern auf die .input-group;
   Kasten und Feld darin sind randlos und transparent. Ergebnis ist
   optisch EIN Feld mit fuehrendem Symbol — das heutige Idiom moderner
   Filterzeilen, und dieselbe Formensprache wie die Karte darum herum.

   NACHFIX B-4 (WCAG 1.4.11): die Feldflaeche IST die Kartenflaeche
   (K 1,00) — die Haarlinie ist damit der einzige Hinweis "hier ist ein
   Feld" und muss die 3 : 1 der Bedienelement-Begrenzung selbst tragen.
   --v0t-kante gab dafuer nur 1,29 : 1 her (der alte Bootstrap-Rand #ccc
   immerhin 1,61). Darum --v0t-feldkante: gleiche Rollenkette, eigener
   Rueckfall (3,14 : 1). Unter jeder Kundenvorlage und unter Manage bleibt
   deren --tp-color-border unveraendert gueltig — 12/12 messen bitgleich
   wie vorher. --------------------------------------------------------- */
body.v2 #organizer_events_search .input-group {
  border-radius: 10px;
  background-color: var(--v0t-karte);
  box-shadow: inset 0 0 0 1px var(--v0t-feldkante);
}
/* Der Fokusring der GRUPPE bleibt erhalten (Auflage 4, letzter Satz):
   das Feld darin ist randlos, ohne diesen Ring gaebe es am Sucheingang
   gar keine Fokusanzeige mehr. */
body.v2 #organizer_events_search .input-group:focus-within {
  box-shadow: inset 0 0 0 1px var(--v0t-tief-500),
              0 0 0 3px color-mix(in srgb, var(--v0t-tief-500) 16%, transparent);
}

/* Praefix: randlos, transparent, nur noch das Symbol bzw. das Wort "ab". */
body.v2 #organizer_events_search .input-group .input-group-addon {
  background-color: transparent;
  border: 0;
  border-radius: 10px 0 0 10px;
  color: var(--v0t-tief-500);
  font-size: 13px;
  font-weight: 600;
  padding: 6px 2px 6px 14px;
  width: 1%;
}
body.v2 #organizer_events_search .input-group .input-group-addon > i.fa {
  color: inherit;
  font-size: 15px;
  width: 16px;
}

/* Feld: randlos, dicht am Symbol. Die beiden :not()-Guards heben die
   Regel ueber den forms.groesse-Arm (2,3,1) — ohne sie behielte das Feld
   sein 14-px-Linkspolster und stuende vom Symbol abgerueckt.
   Hoehe 44 px = Auflage 3 (Fingerziel >= 44). */
body.v2 #organizer_events_search .input-group .form-control:not(#redeem_coupon):not(#redeem_cross_out_coupon) {
  border: 0;
  border-radius: 0 10px 10px 0;
  background-color: transparent;
  box-shadow: none;
  height: 44px;
  min-height: 44px;
  padding: 10px 12px 10px 8px;
}
body.v2 #organizer_events_search .input-group .form-control:not(#redeem_coupon):not(#redeem_cross_out_coupon):focus {
  border: 0;
  box-shadow: none;
}

/* ---------------------------------------------------------------------
   F2-2 — SORTIER-AUSWAHL: DEN BESCHNITT HEILEN (Auflage 1).
   Serienbefund J3 §4.3 / Z14-F-B22, in ANALYSE §1.3 entschieden: die
   Kappung ist NICHT ueber F1 geloest. Live stand "Beginn der
   Veranstaltung" mit −0,2 px Reserve, also mit sichtbarer Ellipse; wir
   waren an dieser Stelle SCHLECHTER als der nackte Shop (+29,3). Traeger
   sind zwei eigene Achsen: forms.groesse (16 statt 14 px Schrift) und
   forms.select-pfeil (padding-right 26 px).
   Gegenmittel hier: das Linkspolster folgt dem Symbol (8 statt 14 px),
   der eigene Chevron rueckt von 9 auf 6 px an die Kante und braucht
   damit nur noch 20 px Reserve. Chevron 6-18 px von rechts, Text endet
   bei 20 px — 2 px Luft, keine Ueberlappung.
   Die beiden Guards sind hier PFLICHT: der select-pfeil-Arm hat (2,3,2).
   --------------------------------------------------------------------- */
body.v2 #organizer_events_search select.form-control.form-control.sort_option:not(#redeem_coupon):not(#redeem_cross_out_coupon) {
  padding-left: 8px;
  padding-right: 20px;
  background-position: right 6px center;
}

/* ---------------------------------------------------------------------
   F2-3 — ANSICHTSUMSCHALTER ALS SEGMENT-PILLE (Auflagen 2, 3, 4).

   Z9-A-LEHRE, ausdruecklich mitgefuehrt: Z9-A hat den Defekt behoben,
   dass der Umschalter in zwei freistehende Knoepfe zerfaellt. Diese
   Bauform setzt zwar 2 px zwischen die Segmente — aber NUR INNERHALB
   der Pille. Der Behaelter (Grund --v0t-kaufbox + Haarlinie
   --v0t-kante) traegt beide Segmente sichtbar zusammen; er darf nie
   entfallen. Genau daran ist Variante C gescheitert: dort stand das
   inaktive Rastersymbol behaelterlos in der Zeile — das Zerfallsbild,
   das Z9-A beseitigt hat.

   GESCHWISTER: gebunden an .show_events, beide Zustaende ausformuliert,
   nie an events_grid oder events_list. Damit gilt jede Zeile fuer
   ?view=grid und ?view=list gleichermassen.

   FINGERZIEL (Auflage 3): Segment 44 x 40 statt der bisherigen
   37 x 30 — die schmalere Achse liegt damit auf 40, die Pille sitzt mit
   44 px auf exakter Feldhoehe.

   FLAECHENGRENZE (Auflage 2): der aktive Chip ist weiss auf einem nur
   um eine Stufe helleren Pillengrund — das allein traegt keine 3 : 1.
   Die Grenze macht darum sein RAND, eine auf 80 % gegen die
   Kartenflaeche gemischte Tiefton-Haarlinie (opak, kein Alpha —
   Messfalle F2-#5).

   NACHFIX B-3, ZWEI PUNKTE — GRUNDKONZEPT-TREUE:

   (a) DIE FORM GEHOERT DER KUNDENVORLAGE, NICHT UNS. Die erste Fassung
   nagelte "border-radius: 999px !important" fest. Weil Vorlage 0 UNTER
   der Kundenvorlage liegt (Basis -> Manage -> Vorlage 0 -> Vorlage),
   gewann dieses !important auch dort, wo die Vorlage ausdruecklich
   ECKIG ist: mono-kontrast und stadion-energie fuehren
   --tp-radius-button: 0, corporate-blau 6px — alle drei zeigten
   trotzdem Kreissegmente (Bilder NFVOR__{mono-kontrast,
   stadion-energie,corporate-blau}__umschalter.png). Das ist genau die
   pauschale Aenderung ueber alle zwoelf Vorlagen, die die Hausregel
   verbietet. Das !important BLEIBT — ohne es flachen die beiden
   Katalogarme .btn-group > .btn:not(:first-child|:last-child) die
   Innenecken ab, was bei 2 px Fuge zwei Halbmonde ergaebe —, aber es
   traegt jetzt den Wert der VORLAGE (--tp-radius-button). Vorlage 0
   selbst fuehrt 6 px; die Segmente stehen damit in ihrer eigenen
   Hausrundung, der Behaelter 4 px darueber (10 px = Feldradius).
   Kein Farb-!important, unveraendert genau EINES in diesem Abschnitt.

   (b) EIN SEGMENTKNOPF IST GEFUELLT — DER AKTIVE. Fuenf Vorlagen
   (festival-dark, neon-nacht, stadion-energie, pastell-soft,
   warm-craft) malen JEDEN .btn-default weiss (Arm
   "body.v2 #content .btn.btn-default", (1,3,1) — gleichstark wie
   unsere Zeile und spaeter geladen, also gewinnt sie). Ergebnis war
   ein WEISSES ruhendes Segment neben einem grauen aktiven: der
   Ruhezustand las sich als der wichtigere — das Zerfallsbild aus
   Z9-A in runder Form. Die Farben bleiben Sache der Vorlage (ihr
   Buntwinkel, ihre Kette); was Vorlage 0 als STRUKTUR beitraegt, ist
   die Regel des Segmentschalters selbst: genau ein Segment traegt
   Flaeche. Darum eine Zeile, die nur dem RUHENDEN Segment die
   Fuellung nimmt (1,5,1), ohne Ton, ohne Rand, ohne Schrift.
   --------------------------------------------------------------------- */
body.v2 #organizer_events_search .btn-group {
  background-color: var(--v0t-kaufbox);
  border-radius: calc(var(--tp-radius-button, 6px) + 4px);
  padding: 2px;
  box-shadow: inset 0 0 0 1px var(--v0t-kante);
}
body.v2 #organizer_events_search .btn.show_events {
  height: 40px;
  width: 44px;
  padding: 0;
  border: 1px solid transparent;
  background-color: transparent;
  color: var(--v0t-tief-500);
  box-shadow: none;
  line-height: 38px;
}
/* NACHFIX B-3 (b): nur die Fuellung, nur im Ruhezustand — und die Schrift,
   die zu dieser Fuellung gehoert. Erste Probe mit reinem
   "background-color: transparent": unter festival-dark, neon-nacht und
   stadion-energie fiel das Symbol auf 1,10-1,22 : 1. Grund gemessen: der
   Arm der Vorlage setzt Flaeche UND Schrift als PAAR (weiss + #222222);
   nimmt man nur die Flaeche, steht die dunkle Schrift auf dem dunklen
   Behaelter. Der Ton wird darum nicht durch einen eigenen ersetzt, sondern
   aus dem GEERBTEN Ton der Vorlage abgeleitet: currentColor, um 28 % gegen
   die Kartenflaeche zurueckgenommen. Das haelt Buntwinkel und Polaritaet
   jeder Vorlage, gibt dem ruhenden Segment die Ruhestufe zurueck und ist
   opak (Mischung gegen eine FLAECHE, nicht gegen transparent — Messfalle
   F2-#5). */
body.v2 #organizer_events_search .btn-group > .btn.show_events:not(.active) {
  background-color: transparent;
  background-image: none;
  box-shadow: none;
  color: color-mix(in srgb, currentColor 72%, var(--v0t-karte));
}
body.v2 #organizer_events_search .btn.show_events + .btn.show_events { margin-left: 2px; }
body.v2 #organizer_events_search .btn.show_events > i.fa {
  color: inherit;
  font-size: 15px;
}
/* Hover des RUHENDEN Segments. Er steht hier und nicht mehr eine Stufe
   schwaecher, weil die Zeile aus NACHFIX B-3 (b) sonst ueber ihm laege und
   die Rueckmeldung schluckte (gemessen: Flaeche blieb transparent). Der
   Ton kommt aus currentColor statt aus einer festen Flaeche — damit
   dunkelt er auf hellen und hellt er auf dunklen Vorlagen auf, ohne deren
   Buntwinkel anzufassen. Das aktive Segment behaelt seine eigene
   Flaeche und braucht keinen Hover. */
body.v2 #organizer_events_search .btn-group > .btn.show_events:not(.active):hover {
  background-color: color-mix(in srgb, currentColor 12%, transparent);
  color: inherit;
}
body.v2 #organizer_events_search .btn.show_events.active {
  background-color: var(--v0t-karte);
  border-color: color-mix(in srgb, var(--v0t-tief-500) 80%, var(--v0t-karte));
  color: var(--v0t-tief-700);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.10);
}
/* Auflage 4 — eigener Fokusring auf BEIDEN Segmenten. Der Katalogarm
   buttons.fokus-ring traegt seinen Ring mit !important und gewinnt heute
   ohnehin; diese Zeile ist der achromatische Rueckhalt fuer den Fall,
   dass der Arm einmal nicht emittiert wird. Kein !important — KORRIDOR
   §6.3 gilt auch fuer outline. */
body.v2 #organizer_events_search .btn.show_events:focus-visible {
  outline: 2px solid var(--v0t-tief-700);
  outline-offset: 2px;
}
/* Die EINE !important-Ausnahme dieses Abschnitts. Begruendung im Kopf
   (F2-3, Absatz NACHFIX B-3 (a)): sie hebt ausschliesslich die
   Eckenabflachung der Knopfgruppe auf und traegt dabei den Radius der
   jeweiligen Vorlage — sie SETZT keine eigene Form. */
body.v2 #organizer_events_search .btn-group > .btn.show_events {
  border-radius: var(--tp-radius-button, 6px) !important;
}

/* =====================================================================
   F2-4 — KALENDER-POPUP (.daterangepicker)

   Das Popup haengt am body, AUSSERHALB #content (V-5): der Scope
   body.v2 erreicht es, jede auf #content gescopte Regel geht ins Leere.
   Vorlage 0 fasste es bisher an genau EINER Stelle an (dem Chevron der
   Monats-/Jahreswahl, aus forms.select-pfeil). Alles andere war
   unveraendert Bootstrap 3 — und deshalb wirkt es "alt": 4-px-Radius,
   harter Dropdown-Schatten, eckige native Auswahlfelder, ein blauer
   Auswahltag, der zu keiner Farbe des Shops gehoert, und zwei Grautoene
   unter 3 : 1.

   ABGELOESTE SERIEN-KONSTANTEN (identisch in v0-Stand und nacktem Stand
   gemessen — Manage deckt sie nicht, sie treffen alle zwoelf Vorlagen;
   Backlog F2-#2/#3):
     td.active / td.active:hover   #357ebd   DRITTE BUNTFARBE, 4,31 : 1
     td.in-range                   #ebf4f8   DRITTE BUNTFARBE
     td.week / th.week             #ccc      1,61 : 1 auf Weiss
     td.off                        #999      2,85 : 1 auf Weiss
     .daterangepicker              Radius 4, Bootstrap-Dropdown-Schatten
     Monats-/Jahreswahl            Radius 0, nativer Rand, 20-21 px hoch

   KORRIDOR-EINORDNUNG: die beiden Blautoene sind heute dritte
   Buntfarben in einem orangen Shop. Sie durch die Rollenkette bzw.
   achromatisch zu ersetzen, ist Korridor-VERBESSERUNG, kein Verstoss.
   colors.primary ist in v0final bewusst NICHT gesetzt — Vorlage 0 ist
   die neutrale Sockel-Vorlage; fuer Kundenvorlagen MIT Hauptfarbe
   bleibt der Katalogarm colors.primary die richtige Stelle (Backlog
   F2-#2). Spezifitaet: Serie ist ".daterangepicker td.active" (0,2,1);
   "body.v2 .daterangepicker td.active" ist (0,3,1) und gewinnt OHNE
   !important.
   ===================================================================== */

/* Flaeche: aus der Bootstrap-3-Dropdown-Optik in die Sockel-Sprache.
   Schatten achromatisch (rgba(0,0,0,…)) und zweistufig statt hart.
   Kein display/height/top/left/position/z-index/width — JS-Eigentum. */
body.v2 .daterangepicker {
  border-radius: 10px;
  border: 1px solid var(--v0t-kante);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.10), 0 2px 6px rgba(0, 0, 0, 0.05);
  padding: 8px;
}
/* Der Serien-Caret ist zwei Dreiecke aus border-color. Nicht
   ausgeblendet (display gehoert nicht uns) — nur der Ton wandert auf
   dieselbe Haarlinie wie der Popup-Rand. */
body.v2 .daterangepicker:before { border-bottom-color: var(--v0t-kante); }
body.v2 .daterangepicker:after  { border-bottom-color: var(--v0t-karte); }

body.v2 .daterangepicker .calendar-table {
  border-color: transparent;
  background-color: transparent;
  padding: 0;
}
body.v2 .daterangepicker .calendar { margin: 2px; }

/* Kopf: Monat/Jahr als ruhige Felder statt nativer Kaesten (Serie: 21 px,
   Radius 0, nativer Systemrand). 28 px + Radius 6 + Haarlinie.

   NACHFIX B-5 — DIE ZWEITE BAUFORM DESSELBEN WAEHLERS. Der Picker haengt
   nicht nur an der Veranstalter-Uebersicht. Nachgesehen im Shop-Repo (nur
   gelesen):
     app/views/sponsorshop/order/_payment_due.haml   -> Layout sponsor.haml
     app/views/managershop/order/_payment_due.haml   -> Layout manager.haml
     app/views/managershop/order/show_kulturpass.haml -> Layout manager.haml
   Alle drei starten .rangepicker mit "timePicker: true", der Waehler
   traegt dort also zusaetzlich .calendar-time mit select.hourselect /
   select.minuteselect (24-Stunden-Form, kein .ampmselect). REICHWEITE
   GEPRUEFT: nur sponsor.haml traegt den css_url-Link (Zeile 37/38) —
   manager.haml hat GAR KEINEN, unsere Schicht erreicht die beiden
   managershop-Ansichten nie. Bleibt der Sponsorshop, und dort standen
   Monats-/Jahresfeld in der neuen, Stunden-/Minutenfeld in der alten
   Formensprache unmittelbar uebereinander. Die Zeit-Felder laufen darum
   in der FORM mit; nichts anderes an .calendar-time wird angefasst
   (Breite und Anordnung gehoeren dem Plugin).
   Der TON ist bewusst getrennt gefuehrt: fuer Monat/Jahr fuehren elf der
   zwoelf Kundenvorlagen einen eigenen Arm, fuer die Zeitfelder keine
   einzige. Truegen die Zeitfelder unsere Toene, stuenden unter jeder
   Vorlage zwei verschieden getoente Feldsorten nebeneinander — genau der
   Bruch, den dieser Nachfix beseitigt. Sie erben darum (transparent auf
   der Popup-Flaeche, Schrift geerbt) und stehen damit unter Vorlage 0
   wie unter jeder Vorlage neben ihren Nachbarn. */
body.v2 .daterangepicker select.monthselect,
body.v2 .daterangepicker select.yearselect,
body.v2 .daterangepicker select.hourselect,
body.v2 .daterangepicker select.minuteselect,
body.v2 .daterangepicker select.secondselect,
body.v2 .daterangepicker select.ampmselect {
  height: 28px;
  padding: 2px 16px 2px 8px;
  border: 1px solid var(--v0t-kante);
  border-radius: 6px;
  font-size: 13px;
  font-weight: 600;
  line-height: 22px;
}
body.v2 .daterangepicker select.monthselect,
body.v2 .daterangepicker select.yearselect {
  background-color: var(--v0t-karte);
  color: var(--v0t-tief-700);
}
body.v2 .daterangepicker select.hourselect,
body.v2 .daterangepicker select.minuteselect,
body.v2 .daterangepicker select.secondselect,
body.v2 .daterangepicker select.ampmselect {
  background-color: transparent;
  color: inherit;
}
/* Auflage 4 — eigener Fokusring auf den Monats-/Jahresfeldern. Sie sind
   weder .btn noch .form-control; kein Katalogarm erreicht sie, und der
   eigene Rand oben nimmt ihnen die native Fokusanzeige. */
body.v2 .daterangepicker select.monthselect:focus-visible,
body.v2 .daterangepicker select.yearselect:focus-visible,
body.v2 .daterangepicker select.hourselect:focus-visible,
body.v2 .daterangepicker select.minuteselect:focus-visible,
body.v2 .daterangepicker select.secondselect:focus-visible,
body.v2 .daterangepicker select.ampmselect:focus-visible {
  outline: 2px solid var(--v0t-tief-700);
  outline-offset: 1px;
  border-color: var(--v0t-tief-500);
}
body.v2 .daterangepicker th.month { padding-bottom: 6px; }
body.v2 .daterangepicker th.prev,
body.v2 .daterangepicker th.next { border-radius: 8px; }
body.v2 .daterangepicker th.prev:hover,
body.v2 .daterangepicker th.next:hover { background-color: var(--v0t-kaufbox); }
/* Auflage 4 — Pfeilkoepfe. */
body.v2 .daterangepicker th.prev:focus-visible,
body.v2 .daterangepicker th.next:focus-visible {
  outline: 2px solid var(--v0t-tief-700);
  outline-offset: -2px;
}

/* Wochentagskopf: kleine gesperrte Versalien (Sockel-Idiom).
   Auflage 6 — der Rueckgang 12,76 -> 5,73 : 1 ist als bewusste
   Hierarchie-Entscheidung abgenommen (klar ueber AA) und wird hier
   NICHT weiter abgesenkt: voller --v0t-tief-500, kein Alpha, kein Mix. */
body.v2 .daterangepicker thead tr:nth-child(2) th {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--v0t-tief-500);
  padding-bottom: 4px;
}

/* Tageszellen. Radius 4 -> 8, Tabellenzahlen.
   Auflage 3 — Trefferflaeche >= 32 x 32 auch @375: die Serie garantiert
   nur min-width 32; die Hoehe kommt hier ueber min-height + Polster,
   NICHT ueber eine height am Popup (JS-Eigentum). */
body.v2 .daterangepicker td,
body.v2 .daterangepicker th { border-radius: 8px; }
body.v2 .daterangepicker .calendar-table td,
body.v2 .daterangepicker .calendar-table th {
  min-width: 32px;
  min-height: 32px;
  padding: 6px 2px;
  font-variant-numeric: tabular-nums;
}
/* NACHFIX B-2 — DIE EINZIGE GEFUELLTE ZELLE STAND ALS EINZIGE IN DER
   ALTEN FORM. Gemessen (Fixture, alle zwoelf Vorlagen und live): der
   gewaehlte Tag behielt Radius 4 px, jede Nachbarzelle hatte 8 px. Die
   Serie fuehrt drei Rundungszeilen fuer die Auswahlraender:
     .daterangepicker td.start-date            (0,2,1) -> von uns geschlagen
     .daterangepicker td.end-date              (0,2,1) -> von uns geschlagen
     .daterangepicker td.start-date.end-date   (0,3,1) -> SCHLAEGT UNS
   In der Einzeldatum-Bauform des Shops traegt der gewaehlte Tag genau
   diese Doppelklasse ("today active start-date active end-date
   available"), die Regel griff also immer — ausgerechnet an dem Element,
   auf das der Blick faellt. Gegenmittel ohne !important: .calendar-table
   in den Selektor, (0,5,2) gegen (0,3,1). */
body.v2 .daterangepicker .calendar-table td.start-date.end-date {
  border-radius: 8px;
}

/* KW-Spalte: Serie 1,61 : 1 — unter jeder Lesbarkeitsschwelle.
   Auflage 5: >= 4,5 : 1, und zwar OPAK ueber die Rollenkette. Der volle
   --v0t-tief-500 ist die opakeste Form dieser Kette (5,73 : 1 auf der
   Kartenflaeche); die Hierarchie zu den verfuegbaren Tagen (12,76 : 1)
   traegt danach der Ton, nicht mehr ein Alphawert.
   Ausdruecklich KEIN color-mix gegen transparent — das ist die Messfalle
   F2-#5, die eine 2,2 : 1-Zelle als 20,95 : 1 gemeldet hat.

   NACHFIX B-1 — DIE GROESSENZEILE IST ZURUECKGENOMMEN. Sie lautete
   "font-size: 10px; letter-spacing: 0.02em". Kein Katalogarm fasst die
   Schriftgroesse der KW-Spalte an, also setzte sie sich in 12 von 12
   Kundenvorlagen durch (11,2 -> 10 px gemessen) — die FARBZEILE dagegen
   verliert dort gegen den eigenen Kalenderarm der Vorlage
   ("body.v2 .daterangepicker td.week", gleichstark, spaeter geladen).
   Damit wurde ausgerechnet der Text KLEINER gemacht, der in sechs
   Vorlagen unter 4,5 : 1 liegt (adventure-fixed 3,28 bis corporate-blau
   3,82). Vorlage 0 gewinnt hier nur den Ton — also traegt hier nur der
   Ton. Die Hierarchie zu den verfuegbaren Tagen ist 5,73 gegen 12,76 und
   bleibt eindeutig; die Serien-Altlast der elf anderen Vorlagen bleibt
   unangetastet (Backlog F2-#3, Traeger Katalog).
   --------------------------------------------------------------------- */
body.v2 .daterangepicker td.week,
body.v2 .daterangepicker th.week {
  color: var(--v0t-tief-500);
}
/* Nachbarmonat: Serie 2,85 : 1. Gleiche Begruendung, gleiche Kette;
   unterschieden wird ueber Gewicht und Flaeche, nicht ueber Deckung. */
body.v2 .daterangepicker td.off,
body.v2 .daterangepicker td.off.in-range,
body.v2 .daterangepicker td.off.start-date,
body.v2 .daterangepicker td.off.end-date {
  background-color: transparent;
  color: var(--v0t-tief-500);
}
body.v2 .daterangepicker td.available:hover,
body.v2 .daterangepicker th.available:hover {
  background-color: var(--v0t-kaufbox);
  color: var(--v0t-tief-700);
}
/* HEUTE ohne Auswahl: Ring statt Fuellung. Die Serie unterscheidet
   "heute" ueberhaupt nicht von "gewaehlt" — dieser Ring tut es erstmals.
   Achromatisch, opak gegen die Kartenflaeche gemischt (>= 3 : 1
   Flaechengrenze). */
body.v2 .daterangepicker td.today:not(.active) {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--v0t-tief-500) 80%, var(--v0t-karte));
  font-weight: 700;
}
/* AUSWAHL: loest das Bootstrap-Blau ab (4,31 : 1, dritte Buntfarbe).
   Achromatischer Tiefton der Vorlage ueber die Kette
   var(--tp-color-body-text, …) — 13,72 : 1. Kein !important auf einer
   Farb-Property noetig: (0,3,1) gegen (0,2,1). */
body.v2 .daterangepicker td.active,
body.v2 .daterangepicker td.active:hover {
  background-color: var(--v0t-tief-700);
  color: var(--v0t-karte);
  font-weight: 700;
}
/* Spanne: loest den zweiten Blauton ab. */
body.v2 .daterangepicker td.in-range:not(.active) {
  background-color: var(--v0t-kaufbox);
  color: var(--v0t-tief-700);
}
/* Der Fuss (Abschicken/Abbrechen) rendert in dieser Bauform nicht
   (.ranges display:none aus dem Plugin) — das Polster steht trotzdem,
   damit die Flaeche in der Zweifeld-Bauform nicht aus dem Skin faellt. */
body.v2 .daterangepicker .range_inputs { padding-top: 6px; }

/* =====================================================================
   RUNDE F3 (CEO-Detailfeedback 2026-09-01, Punkte F21-F26).
   Quelle: scratchpad/vorlage0f3/ANALYSE.md, Judge-Entscheid vom selben Tag.
   Alle Regeln stehen AUSSCHLIESSLICH in dieser eigenen Schicht; Katalog und
   Presets bleiben unberuehrt (Sammelpruefsumme catalog/ unveraendert).
   ===================================================================== */

/* ---------------------------------------------------------------------
   F21 — DIE KAUFLEISTEN-TEXTE WAREN AM HANDY 28,5 % KLEINER ALS IM
   NACKTEN SHOP.

   BEFUND (Nackt-Referenz gegen Ist, 6 Fixtures x 2 Breiten, ANALYSE.md F21):
     Bauteil                     nackt@375   Ist@375   nackt@1280  Ist@1280
     Warenkorb-Chip              16,00       11,44     16,00       15,00
     Weiter-CTA                  16,00       11,44     16,00       17,00
     Timer                       16,00       16,00     16,00       16,00
   Der Timer liegt bereits auf Nacktniveau; er WIRKT nur klein, weil seine
   beiden Nachbarn schrumpfen. Am Desktop fehlt allein dem Chip 1 px.

   URSACHE, eine Zeile zweimal: die Mobilklemme M-1 des Katalogs
   (v0final.css Z.875, @media max-480) und die Pillenform des Warenkorbs
   (Z.825, ohne Media-Grenze) tragen beide
       font-size: clamp(11px, 3.05vw, 15px) !important
   3,05 vw sind @375 exakt 11,44 px. Die Untergrenze 11 px war fuer den
   engsten Fall gerechnet — den langen CTA "Zahlungspflichtig bestellen"
   der Zahlartenseite —, galt aber fuer ALLE Seiten.

   FIX, seitenweise abgesichert (Judge: "Nacktparitaet ist das Ziel, nicht
   18 Prozent Trostpflaster"), gemessen im Hebel-Sweep ueber 5 Seiten x
   6 Breiten (320/360/375/390/414/479):
   (1) REGELFALL (cart-filled, extras, customerdata, shop-artikel,
       checkout-fragen): Chip UND CTA auf clamp(11px, 4.00vw, 16px), dazu
       6 px Seitenpolster an CTA, Chip und Timer. Ergebnis @375 15,00 px
       (+31 %), @390 15,60, @414/@479 16,00 = NACKTPARITAET. Kappung 0 an
       allen sechs Breiten, Leistenhoehe 52-53, Versatz oben-unten 0,0.
   (2) AUSNAHME ZAHLARTENSEITE: dort traegt der CTA das lange Pflichtlabel.
       Ruecknahme auf clamp(11px, 3.15vw, 16px) = 11,81 px @375.
       WARUM NICHT 3,60 vw (13,50 px), WIE AUF VORLAGE 0 ALLEIN GEMESSEN:
       der 12-Vorlagen-Erbcheck dieses Loses (Kantenregel 4) hat 3,60 vw
       widerlegt. Unter den Kundenvorlagen ist die Typografie groesser, und
       der PFLICHT-CTA "Zahlungspflichtig bestellen" wird dann beschnitten —
       Textueberstand im Knopf @375: adventure-fixed +18,05 px,
       elegant-serif +15,53, mono-kontrast +12,25, neon-nacht +11,27,
       stadion-energie +32,78 (5 von 12). Das ist exakt der Defekt, den R2-B
       einmal beseitigt hat ("Vorlage 0 war hier schlechter als die Serie"),
       und er trifft die gesetzlich vorgeschriebene Beschriftung.
       3,15 vw ist der GROESSTE Wert aus dem Kandidaten-Sweep
       (3,05 / 3,15 / 3,25 / 3,35 / 3,45 / 3,60 vw x 13 Staende x
       6 Breiten = 468 Zellen), der an KEINER Zelle staerker beschneidet als
       der VOR-Stand. Er verbessert obendrein die Altlast von
       stadion-energie: Ueberstand @375 5,09 -> 3,64 px.
       Ehrlich beziffert: der Zugewinn auf dieser EINEN Seite ist mit
       11,44 -> 11,81 px klein. Die Zahlartenseite hat unter realen
       Kundenvorlagen schlicht keinen Platz; mehr Schrift dort kaufte man
       mit einem beschnittenen Pflichttext. Auf allen anderen Seiten steht
       die volle Anhebung (siehe (1)).
       Traeger ist die Seite selbst: sie
       fuehrt keine eigene body-Klasse, aber als einzige Flaeche des
       Produkts das Markup .paymentmethod. Die Erkennung haengt deshalb am
       WURZELKNOTEN; den Vorrang holt sie ueber das zusaetzliche Element
       html plus die Spezifitaet des :not()-Arguments.
       Browser ohne :has verlieren die ANHEBUNG, nicht den Schutz: dann gilt
       auf allen Seiten der sichere Grundwert 11,81 px statt 15,00 — die
       Leiste wird dort kleiner, nie beschnitten. Die Polaritaet des Arms
       ist dafuer herumgedreht; die Begruendung steht an der Regel selbst.

   (3) DESKTOP: Chip-Obergrenze 15 -> 16 px. Nachgemessen ueber 5 Fixtures
       x 4 Breiten (768/992/1280/1600): Leistenhoehe 61 -> 61, Versatz
       0 -> 0, Kappung 0, CTA-Ueberstand 0. Kostenlos.
   (4) Der Timer bleibt beim Schriftgrad UNANGETASTET (bereits Nacktniveau);
       er gibt nur Seitenpolster ab. Der SSL-Satz bleibt unberuehrt.
   (5) Die Untergrenze 11 px bleibt stehen: darunter kippt payment@320 in
       die designte Zweizeiligkeit (gemessen 99 px Leistenhoehe) und die
       vom CEO gesetzte Hoehengrenze 60/53 waere verletzt.

   VERHAELTNIS ZU R2-B / R3-C: diese Regeln ERSETZEN die dortigen
   Zahlenwerte fuer Schriftgrad und Seitenpolster (gleiche Selektoren,
   spaetere Position). Die Begruendung von R2-B — sticky-cta-gross wird
   mobil zurueckgenommen, am Desktop nicht — bleibt unveraendert gueltig;
   nur die Zielwerte der Klemme sind neu vermessen.
   Kein Farbwert, keine Farb-Property. Die !important sind unvermeidbar,
   weil die zu schlagenden Katalogzeilen selbst !important tragen
   (KORRIDOR §6.3 verbietet !important ausschliesslich auf Farb-Properties).
   --------------------------------------------------------------------- */
body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart {
  font-size: clamp(11px, 3.05vw, 16px) !important;
}
@media (max-width: 480px) {
  /* GRUNDWERT — der auf JEDER Seite sichere, auch auf der Zahlartenseite. */
  body.v2 #stickyfooter #stickyfooter-inner a#initorder_layout.btn,
  body.v2 #stickyfooter #stickyfooter-inner a#initorder_amazon.btn {
    font-size: clamp(11px, 3.15vw, 16px) !important;
    letter-spacing: normal !important;
    padding-left: 6px !important;
    padding-right: 6px !important;
  }
  body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart {
    font-size: clamp(11px, 3.15vw, 16px) !important;
    padding-left: 6px !important;
    padding-right: 6px !important;
  }
  body.v2 #stickyfooter .countDownTimer,
  body.v2 #stickyfooter .btn-group > .btn.countDownTimer,
  body.v2 #stickyfooter #stickyfooter-inner .pull-left .btn-group > .btn.countDownTimer {
    padding-left: 6px !important;
    padding-right: 6px !important;
  }
  /* F21-H — DAS CHEVRON HAT DIE LEISTE UM 2 PX AUFGEBLAEHT.
     Gemessen bei der Abnahme dieses Loses: mit 16-px-CTA stieg die
     Leistenhoehe @414 und @479 von 52/53 auf 54 px, obwohl line-height
     (38 px), min-height (40 px) und Polster unveraendert blieben. Ursache
     ist stickyfooter.cta-chevron: das ::after traegt font-size 0.85em
     (13,6 px bei 16-px-Text) und erbt die line-height als LAENGE (38 px).
     Zwei Inline-Boxen gleicher Hoehe, aber unterschiedlicher Schriftgroesse
     verteilen ihren Durchschuss um die GRUNDLINIE verschieden; die
     Vereinigung beider Boxen wird dadurch hoeher als jede einzelne — bei
     11,4 px Text (Altstand) fiel das nicht auf, bei 16 px sind es 2 px.
     Zurueckgenommen wird nur der Durchschuss des Zeichens, nicht seine
     Groesse und nicht seine Grundlinie: das Chevron steht danach an
     derselben Stelle (A/B-Zoom), die Zeilenbox richtet sich wieder nach dem
     Text. Ergebnis: Leistenhoehe 52 px an ALLEN sechs Handybreiten auf
     allen fuenf Flaechen, Versatz 0,0 — besser als der VOR-Stand (52-53).
     Nur unter 481 px; am Desktop bleiben 61 px unberuehrt. */
  body.v2 #stickyfooter a#initorder_layout::after,
  body.v2 #stickyfooter a#initorder_amazon::after {
    line-height: 1;
  }
  /* ANHEBUNG auf allen Seiten OHNE den langen Pflicht-CTA. Erkennung am
     Wurzelknoten ueber das einzige Markup, das nur die Zahlartenseite fuehrt.

     DIE POLARITAET IST MIT ABSICHT HERUMGEDREHT (Abweichung von der
     Judge-Vorgabe, hier begruendet): geschrieben als
     `:where(:has(.paymentmethod))` traegt die ZAHLARTENSEITE die Ausnahme —
     ein Browser ohne :has bekaeme dort die grosse Schrift und damit den
     beschnittenen Pflichttext. Der Ausfall waere also ausgerechnet auf der
     empfindlichsten Seite ein Schaden statt ein Status quo. In dieser
     Fassung ist der GRUNDWERT sicher und die Anhebung das Zusatz; faellt
     :has aus, faellt die Anhebung aus, nicht der Schutz.
     Deshalb steht hier auch KEIN :where() um das :has: `:where()` und
     `:is()` sind NACHSICHTIGE Selektorlisten — ein unbekanntes :has darin
     wird still verworfen und der Rest der Regel trifft WEITERHIN, also auch
     die Zahlartenseite. `:not()` ist nicht nachsichtig: kennt der Browser
     :has nicht, ist der ganze Selektor ungueltig und die Regel faellt
     vollstaendig weg — genau das gewuenschte Verhalten.
     Spezifitaet: :not() erbt die seines Arguments (0,1,0); der Arm liegt
     damit bei (3,3,3) gegen (3,2,2) des Grundwerts. */
  html:not(:has(.paymentmethod)) body.v2 #stickyfooter #stickyfooter-inner a#initorder_layout.btn,
  html:not(:has(.paymentmethod)) body.v2 #stickyfooter #stickyfooter-inner a#initorder_amazon.btn,
  html:not(:has(.paymentmethod)) body.v2 #stickyfooter #stickyfooter-inner .btn-group #show_shopping_cart {
    font-size: clamp(11px, 4vw, 16px) !important;
  }
}

/* ---------------------------------------------------------------------
   F22 — STICKY-ARTIKELTITEL AM HANDY: ZURUECKGENOMMEN (Los F3-2, belegt).

   ENTSCHEIDUNG VOM 2026-09-01, NACHLAUF ZUR VERIFIKATION: die Regel ist
   ERSATZLOS ENTFERNT. Der CEO hatte F22 ausdruecklich als nice-to-have
   freigegeben, mit der Auflage "wenn es NICHT sauber geht: belegt
   verworfen". Sauber geht es nicht.

   DER BELEG (v-f22c.js, 31 Scrollstellen je Flaeche, 6 Handyflaechen,
   375 x 700, VOR/NACH-Paar; nachgefahren in f2-f22c.js):
   der klebende Titel verdeckt Bauteile SEINES EIGENEN Artikels, die ohne
   die Regel an derselben Scrollstelle sichtbar waren —
     cart-filled    Mengenfeld + Entfernen-Knopf (Artikel 0 und 1)   17 Stellen
     shop-artikel   Mengenfeld (3 Artikel) + Kaufknopf (2 Artikel)   10 Stellen
     cover-image    Mengenfeld + Kaufknopf (3 Artikel)               12 Stellen
     accordions     Mengenfeld + Kaufknopf (2 Artikel)               13 Stellen
     stock-states   Mengenfeld + Kaufknopf                            5 Stellen
     extras         Mengenfeld (2 Artikel)                            3 Stellen
   elementFromPoint auf der Mitte der Bauteile trifft den klebenden Titel:
   sie sind nicht nur unsichtbar, sondern NICHT BEDIENBAR
   (shop-artikel@1436 select + .add-button, cart-filled@1306 select,
   accordions@1010 select). Bildbeleg
   shots/vorlage0f3/V-BEFUND-F22-kaufknopf-verdeckt-shop-artikel-y1436-NACH.png.

   WARUM AUCH DER ZEILENDECKEL NICHT TRAEGT (geprueft, nicht vermutet):
   ein Deckel muesste die Kopfzeile auf eine Zeile begrenzen — also
   max-height/overflow oder -webkit-line-clamp. Beides veraendert den
   RUHEZUSTAND (der Titel steht dann auch ungescrollt gekuerzt da, die
   Nullprobe-Treue der Kopfzeile faellt) und trifft mit `overflow` genau die
   Eigenschaft, die den Sticky-Kontext von Nachbarbauteilen brechen kann.
   Der Deckel wuerde ausserdem nur die Titelhoehe begrenzen, nicht das
   Grundproblem: schon eine EINZEILIGE klebende Zeile (52-70 px) deckt am
   375-px-Handy das Mengenfeld des eigenen Artikels an den gemessenen
   Scrollstellen. Die Hilfe kehrt damit ihren Zweck um — sie soll Preis und
   Auswahl dem Titel zuordnen und verdeckt genau Auswahl und Kaufknopf.

   WAS ERHALTEN BLEIBT: der urspruengliche CEO-Befund (bei langen
   Beschreibungen scrollt der Titel aus dem Bild) ist damit NICHT erledigt,
   sondern offen. Er ist als Registerposten F3-#3 gemeldet; ein tragfaehiger
   Weg waere eine Aenderung am Shop-Markup (eigene, kurze Klebezeile statt
   der vollen Kopfzeile) und liegt ausserhalb dessen, was eine
   Override-CSS-Schicht leisten kann.

   Die urspruengliche Begruendung ist unten stehen geblieben, damit die
   naechste Runde den Weg nicht ein zweites Mal geht.
   --------------------------------------------------------------------- */
/* HISTORIE (Variante X, "schlicht klebend") — NICHT MEHR AKTIV:

   BEFUND DES CEO: bei langen Beschreibungen scrollt der Artikeltitel aus
   dem Bild, und Preis, Mengenfeld und Verfuegbarkeitshinweis stehen ohne
   erkennbare Zuordnung da. Bildbeleg des Analyse-Loses:
   F22-shop-artikel-OHNE-A1-b-mitte.png zeigt Preis und Mengenfeld ohne
   jeden Titel; F22-shop-artikel-X-A1-b-mitte.png zeigt beides unter dem
   klebenden Titel.

   MACHBARKEIT GEPRUEFT (ANALYSE.md F22): kein Vorfahre von .items bis html
   bricht den Sticky-Kontext (kein overflow/contain/transform/filter/
   will-change; body{overflow:auto scroll} propagiert auf den Viewport und
   macht body NICHT zum Scrollcontainer). .well clippt nicht
   (overflow: visible in nackt und v0final).

   TRAEGER, eng gefasst: die Kopfzeile des Artikels, also das ERSTE Kind von
   .items, und nur dann, wenn diese Zeile die Bauform der Ticketauswahl hat
   (col-md-12 > .headline). Die ZUSATZARTIKEL-Seite baut anders
   (.col-md-6.col-sm-8, bis zu vier verschachtelte .items, Titel in
   DERSELBEN Zeile wie die Kaufbox: gemessen 264 von 294 px Artikelhoehe) —
   dort waere Sticky sinnlos, weil fast der ganze Artikel klebte. Der
   Selektor grenzt sie ueber col-md-12 ABSICHTLICH aus. Das :has() ist in
   :where() gekapselt (Spezifitaets-Daempfer, Lehre Z14-N1); Browser ohne
   :has ignorieren die Regel — dann gilt der heutige Zustand, kein Schaden.

   Z-GEFUEGE: #stickyfooter 1035, footer 1034, .dropdown-menu 1000, Modals
   1040+. Der klebende Titel bekommt z-index 3 und liegt damit unter allen
   dreien — im Bild belegt: die Kaufleiste malt ueber den Titel.

   KEIN EINGRIFF IN JS-EIGENTUM: weder display noch height.
   article.description[data-readmore] (Readmore) und .wrap_content
   (Akkordeon) sind Geschwister-Teilbaeume, keine Vorfahren des Titels.

   VARIANTE Y (Haarlinie + Schatten) IST VERWORFEN, belegt: rein in CSS ist
   der Klebezustand nicht verlaesslich abfragbar (animation-timeline kann
   dieser Chrome, Safari < 26 und Firefox nicht stabil). Linie und Schatten
   waeren also DAUERHAFT sichtbar und lesen im Ruhezustand nicht als feiner
   Titelunterstrich, sondern als grauer Balken unter einer schwebenden
   Flaeche (Zoomkrop F22-shop-artikel-Y-A1-a-oben__zoom.png) — ein Artefakt,
   das cards.divider-style: subtle auf jeder Artikelkarte doppelt bedient.
   Der klebende Titel traegt bereits deckenden Kartengrund; das genuegt zur
   Abgrenzung.

   OFFEN ANGENOMMEN (Judge, Weg a): cart-filled Artikel 2 traegt einen
   9-zeiligen Titel, der klebende Block misst dort 239 von 780 px = 30,6 %.
   Ein dauerhafter Zeilendeckel ist ABGELEHNT — er kostet im Ruhezustand
   Information und markiert einen Zustand, den wir nicht abfragen koennen.

   PAAR-REGEL (KORRIDOR §4): die Flaeche ist der KARTENGRUND selbst
   (--v0t-karte = --tp-color-panel-bg). Ihr Schriftpartner ist die geerbte
   Kartenschrift; eine eigene color-Zeile waere hier falsch, weil der Titel
   im Ruhezustand exakt so aussehen muss wie ohne diese Regel — sie deckt
   nur, sie faerbt nicht.
   --------------------------------------------------------------------- */
/* HIER STAND DIE REGEL. Sie ist am 2026-09-01 ersatzlos entfernt worden
   (Begruendung oben). Wortlaut zur Nachvollziehbarkeit:
       @media (max-width: 767px) {
         body.v2 .items > div.row:first-child
                 :where(:has(> [class*="col-md-12"] > .headline)) {
           position: sticky; top: 0; z-index: 3;
           background-color: var(--v0t-karte);
         }
       }

   DREI DEKLARATIONEN, DIE DER PROTOTYP HATTE UND DIE AUCH DORT FEHLTEN — jede
   davon hat im Nachmessen dieses Loses den RUHEZUSTAND veraendert, und das
   darf eine Scroll-Hilfe nicht:
   - `padding-top: 4px` ueberschrieb das Kartenpolster von 14 px und machte
     JEDE Artikel-Kopfzeile am Handy 10 px flacher (Seitenhoehe -10 bis
     -40 px auf shop-artikel, extras, accordions, stock-states,
     cover-buttonbar).
   - `padding-left/right: 15px` sollte die negativen Bootstrap-Raender
     ausgleichen. Sie tun es nicht: die Zeile behaelt ihre Aussenraender, das
     Polster verkleinert also nur ihren INHALTSKASTEN. Die Titelspalte wurde
     dadurch 30 px schmaler — auf stock-states brach der Titel "VIP-Lounge
     inkl. Catering" in eine zusaetzliche Zeile (Kopfzeile 70,4 -> 96,8 px).
   Der deckende Grund braucht sie nicht: die Zeile reicht mit ihren -15 px
   Aussenrand ohnehin ueber die Kartenkante hinaus, ihr Rahmenkasten deckt
   die volle Karteninnenbreite. Nachgemessen: Kopfzeilenhoehen und
   Seitenhoehen VOR = NACH in allen fuenf Flaechen. */

/* ---------------------------------------------------------------------
   F23 — ZUSATZFRAGEN-SEITE: DREI LUECKEN, ZWEI FLAECHEN.

   Die Seite /cart/<key>/questions/order_questions war bis zu diesem Los
   ungetestet — es gab keine Fixture. Sie ist jetzt als
   harness/fixtures/checkout-fragen.html gebaut (Z7-Methode, 36 Gates,
   0 gerissen) und in harness/nullprobe.js eingetragen.
   Der GROSSTEIL der Vorlage greift dort bereits: Karte (Radius 4 -> 8,
   Polster 19 -> 32), Kartenkopf P13, Felder und Selects (14 -> 16 px,
   Select-Pfeil), has-error, Checkboxen, Radios, .help-block,
   Abbrechen-Knopf, Kaufleiste. Drei Bauteile erreichte sie nicht:

   LUECKE 1 — DIE PFLICHTHINWEIS-BOX WAR ZU 100 % SERIE.
   .alert.alert-warning misst in nackt UND unter Vorlage 0 identisch:
   Grund rgb(252,248,227), Text rgb(138,109,59), Rahmen rgb(250,235,204),
   RADIUS 4 px — neben einer Karte mit Radius 8. Kontrast Text auf Boxgrund
   4,44 : 1, also UNTER AA. colors.alerts erreicht diese Bauform hier nicht
   (v0final.json setzt colors.* ueberhaupt nicht).
   FIX: die Box bekommt die Formsprache der Vorlage — Kaufbox-Flaeche,
   Kartenkante, Kartenradius, Grundtext. Vorlage 0 ist farbabstinent und
   fuehrt keinen Warnton; der Signaltraeger dieser Box ist ohnehin das
   Sternchen, auf das sie verweist, nicht ihre eigene Fuellung. Echte
   Meldungen (.alert-danger, .alert-success, .bs-callout-danger) bleiben
   UNBERUEHRT — dort sitzt die Bedeutungsfarbe (KORRIDOR §3.3/§3.9).
   PAAR-REGEL: --v0t-kaufbox <-> --v0t-tief-700, dasselbe Paar, das
   .data-wrapper.opencase traegt; Rueckfall #262E38 auf #F2F5F9 = 13,6 : 1.
   Betrifft ZWEI Flaechen (Fragen- und Kundendatenseite) — deshalb eine
   gemeinsame Regel und keine seitenweise Ausnahme (Kernregel 3).

   LUECKE 2 — .form-group-border-left WAR UNBERUEHRT.
   border-left: 3px solid rgb(221,221,221) (Serien-Grau), identisch in nackt
   und v0final: ein blasser grauer Stummel neben Karten, deren Kanten der
   Vorlagenton traegt. Die Formgruppe kommt nur auf Fragen- und
   Kundendatenseite vor. FIX: Kante auf den Vorlagenton. Nur die FARBE, die
   Breite (3 px) bleibt — das ist die Fuehrungslinie des Serienlayouts.

   LUECKE 3 — forms.pflicht-sternchen WAR AUF DIESER SEITE WIRKUNGSLOS.
   Die Katalogoption zeichnet `label .asterisk, span.asterisk`. Die
   Kundendatenseite liefert <span class="asterisk"> (19 Treffer im
   Live-Abzug) — dort wirkt sie. _question.haml rendert ein KLASSENLOSES
   %span mit "*". Gemessen: rgb(85,85,85) = Labelfarbe, in nackt UND unter
   Vorlage 0, an beiden Breiten — eine Optionsunwahrheit auf dieser Flaeche.
   FIX: dieselbe Deklaration wie die Katalogzeile, aber eng gefasst auf die
   Bauform der Fragenseite. Der Kindschafts-Pfad ist der Riegel: die
   MEHRFACHAUSWAHL traegt ihren Text in .checkbox > label > span.font-default,
   also eine Ebene tiefer unter .controls — sie wird NICHT getroffen
   (nachgezaehlt: 3 Sternchen-Treffer, 3 unveraenderte Auswahltexte).
   Die has-error-Spiegelung des Katalogs (Z.314) wird NICHT nachgebaut: die
   Fragenlabels tragen kein .control-label, sind im Fehlerfall also gar
   nicht rot — inherit wuerde dem Sternchen dort seine Signalfarbe nehmen.
   Chromatischer Rueckfall #e5484d: als Korridor-Freigabe gefuehrt, mit
   derselben Begruendung wie die Katalogzeile (Bedeutungsfarbe, KORRIDOR
   §3.9); der Wert ist zeichengleich mit ihr, damit Fragen- und
   Kundendatenseite EIN Rot zeigen.

   OFFEN UND HIER AUSGEWIESEN, NICHT STILLSCHWEIGEND GESCHLOSSEN: die Treue
   des Fragenblocks gegen die echte Live-Seite ist ungemessen (Z7-Schritt 5).
   Die Seite ist auf dem erlaubten Weg nicht erreichbar — question_controller
   Z.8 leitet ohne redis_shop_order auf /order um, und die entsteht erst
   durch den Kundendaten-POST, der nach Projektregel verboten ist. Die
   Huelle stammt aus einem lesenden Live-Abzug derselben Checkout-Stufe, der
   Fragenblock 1:1 aus show.haml + _question.haml.
   --------------------------------------------------------------------- */
/* RADIUS AN DIE ROLLE, NICHT AN DIE ZAHL (Erbcheck dieses Loses): mit einer
   festen 8 stand die Hinweisbox unter den zwoelf Kundenvorlagen neben Karten
   mit Radius 0 bis 20 px und war dort ein Fremdkoerper. --tp-radius-panel ist
   genau das Token, aus dem alle zwoelf ihren Kartenradius emittieren; unter
   Vorlage 0 loest es auf 8 px auf (cards.radius: 8). Flaeche und Schrift
   ueberlaesst diese Regel der Kundenvorlage: wo eine eigene .alert-Optik
   vorhanden ist, laedt sie nach uns und gewinnt (in 12 von 12 nachgemessen). */
/* REICHWEITE EINGEZOGEN (Los F3-2, 2026-09-01) — DAS WAR EIN BEFUND, KEINE
   Feinheit: `body.v2 .alert.alert-warning` war GLOBAL. Inventur ueber alle
   32 Fixturen: vier .alert-warning-Boxen auf drei Flaechen —
     checkout-fragen   1  Pflichthinweis "* = Pflichtfeld"   (gemeint)
     customerdata      2  Pflichthinweis, zweimal            (gemeint)
     portal-order      1  "Bitte denkt daran eure Tickets rechtzeitig zu
                          personalisieren ... fallen zusaetzliche Gebuehren
                          an!"                               (NICHT gemeint)
   Die Portal-Box ist eine ECHTE Warnung mit Kostenfolge. Ihr den gelben
   Serienton zu nehmen macht sie optisch ununterscheidbar von der blauen
   Infobox direkt darunter — eine Flaeche, die der CEO nicht angefragt hat
   und die dieses Los nicht traegt (KORRIDOR §3.3/§3.9: Bedeutungsfarbe
   bleibt). Der Hinweis auf der Fragen-/Kundendatenseite dagegen traegt gar
   keine Warnung, sondern eine Bedienhilfe — dort ist die Umwidmung gewollt.

   DER RIEGEL IST STRUKTURELL, nicht per Seitenname: die Checkout-Hinweise
   sind DIREKTE Kinder der Formularkarte (.well.well-light.well-shadow), die
   Portal-Warnung liegt in .quick_form > .data-wrapper > .data > .row >
   .col-md-12 und hat keinen .well-Vorfahren. Nachgezaehlt: 3 Treffer statt 4.

   .well STEHT IN :where() — MIT ABSICHT (Lehre Z14-N1). Ohne den Daempfer
   waere der Selektor (0,3,1) statt (0,2,1) und koennte unter den zwoelf
   Kundenvorlagen Regeln schlagen, die heute gewinnen. Die Einengung soll
   WENIGER treffen, nicht staerker gewichten; die Spezifitaet bleibt darum
   auf das Zeichen genau die des bisherigen Selektors. Erbcheck 12/12: unter
   jeder Kundenvorlage VOR = NACH auf allen drei Checkout-Boxen. */
body.v2 :where(.well) > .alert.alert-warning {
  background-color: var(--v0t-kaufbox);
  color: var(--v0t-tief-700);
  border: 1px solid var(--v0t-kante);
  border-radius: var(--tp-radius-panel, 8px);
}
/* Spezifitaet mit Absicht (0,3,1): die Serienzeile steht in custom_tp.css.scss
   Z.1083 als VERSCHACHTELTER Compound
   `.form-group.form-group-more-mb.form-group-border-left` (0,3,0). Ein
   schlichtes `body.v2 .form-group-border-left` (0,2,1) verliert dagegen —
   in der ersten Fassung dieses Loses gemessen: Kante blieb rgb(221,221,221). */
body.v2 .form-group.form-group-border-left {
  border-left-color: var(--v0t-kante);
}
body.v2 .order_questions .form-group-border-left > label > span {
  color: color-mix(in srgb, var(--tp-color-form-error, #e5484d) 62%, currentColor);
}

/* ---------------------------------------------------------------------
   F24 — PAYPAL-ZEILEN TRUGEN EINE ANDERE SCHRIFT-FORMATIERUNG ALS DIE
   UEBRIGEN ZAHLARTEN (CEO-Bild: schwarze Schrift auf gruener Auswahlflaeche).

   DER DOM-UNTERSCHIED (app/views/order/choose_payment.haml):
     Standard-Zweig (Z.190)  = label_tag ..., class: "paymentmethod_text"
                             -> <label class="paymentmethod_text">Text</label>
     PayPal-Zweig  (Z.133/134) .paymentmethod_text
                             -> <div class="paymentmethod_text">
                                  <label style="font-weight: normal;">Text</label>
     Klarna-Zweig  (Z.95)      Div mit blossem Text, OHNE label
   Die Serienregel _system_style.css.erb Z.8 faerbt
   `.paymentmethod-checked .paymentmethod_text` mit brand_btn_color
   !important. Im Standard-Zweig trifft sie den Texttraeger direkt; im
   PayPal-Zweig nur den WRAPPER, und das verschachtelte <label> muesste
   ERBEN — Vererbung verliert aber gegen jede direkte Regel. Per CDP
   nachgewiesen, welche das ist:
     .logowrapper span, .form-group label, … { color: #555555 }   (0,2,1)
   Jede .paymentmethod steckt in einer .form-group. Klarna ist NICHT
   betroffen (kein label, erbt korrekt); betroffen sind genau die elf
   PayPal-Varianten (PPRA, PPRAPL, PPRACARD, PPRAGIRO, PPRASOF, PPRAID,
   PPRABANK, PPRAMYB, PPRAP24, PPRABLIK, PPRAEPS), die alle denselben
   Zweig nutzen. Dazu der Inline-Stil font-weight: normal aus dem HAML:
   Gewicht 400 statt 600 — die zweite Haelfte des CEO-Befunds.

   BEZIFFERT (Kontrast der Beschriftung auf der GEWAEHLTEN Flaeche, vier
   Kundenfarben, nackt und v0final identisch):
     Orange #ff4d06   Standard 3,32 : 1   PayPal 2,24 : 1
     Gruen  #3aa757   Standard 3,07 : 1   PayPal 2,43 : 1  (CEO-Bild)
     Blau   #123a6b   Standard 11,39 : 1  PayPal 1,53 : 1
     Gelb   #f5d300   Standard 10,76 : 1  PayPal 5,04 : 1
   Bei dunklen Kundenfarben ist die Beschriftung praktisch unlesbar.

   FIX — DIE SERIEN-PAARUNG WIRD VERVOLLSTAENDIGT, NICHT ERSETZT.
   Das verschachtelte label wird zum Durchreicher: es uebernimmt Farbe und
   Gewicht seines Wrappers, egal welchen Wert die Serie oder die
   Kundenvorlage dort hineinschreibt. Damit verhaelt sich die
   PayPal-Bauform in JEDEM Zustand wie die Standard-Bauform:
     gewaehlt    Wrapper = brand_btn_color  -> Label ebenso  (weiss)
     ungewaehlt  Wrapper = rgb(51,51,51)    -> Label ebenso
   Der ungewaehlte Zustand war bisher ebenfalls falsch (Label 85,85,85
   gegen Standard-Label 51,51,51); die Paarung raeumt beide Faelle auf.

   BEWUSST OHNE .paymentmethod-checked IM SELEKTOR — und das ist kein
   Ausweichen vor dem Waechter, sondern die richtigere Regel: der Fehler
   liegt in der BAUFORM, nicht im Zustand, und er zeigt sich in beiden
   Zustaenden. Nebenbei bleibt damit auch die Farbfrage dort, wo sie
   hingehoert: wir setzen KEINEN Farbwert auf einem TABU-Selektor, wir
   sagen nur "erbe" (KORRIDOR §1/§6.1 unberuehrt, kein !important auf
   einer Farb-Property, §6.3 gewahrt). Spezifitaet (0,3,2) gegen
   .form-group label (0,2,1) — der Vorrang kommt aus dem Selektor.
   Das !important auf font-weight ist unvermeidbar (Inline-Stil im HAML)
   und ist KEINE Farb-Property, nach §6.3 also zulaessig.

   TABU-PRUEFUNG: beruehrt wird ausschliesslich .paymentmethod*, das
   shop-eigene AUSWAHLLISTEN-Markup. Kein paymentWidgets, kein
   Stripe/Klarna/wpwl/PayPal-iframe, keine Flaechenfarbe, kein
   Zahlungs-Widget. Die Auswahlflaeche selbst bleibt $brand-color-Gebiet
   und wird nicht angefasst.
   --------------------------------------------------------------------- */
body.v2 .paymentmethod .paymentmethod_text label {
  color: inherit;
  font-weight: inherit !important;
}

/* ---------------------------------------------------------------------
   F26a — DIE ROTE KNOPF-FAMILIE DES PORTALS AUF EIN MASS.

   AUSWEIS ZUM CEO-BEFUND: die zwei genannten Knoepfe "Jetzt
   personalisieren" und "Jetzt beantworten" sind auf dem aktuellen Stand
   MESSGLEICH und im 2-fach-Zoom deckungsgleich (nackt @1280 227,63/227,63;
   v0final @1280 214,88/214,88; @375 189/189 bzw. 238/238). Der Befund ist
   in dieser Form nicht reproduzierbar.
   Die EINZIGE gemessene Ungleichheit unter roten Knoepfen derselben Seite
   ist ein anderes Paar: button#button_personalize ("Verbindlich
   personalisieren", im Personalisierungs-Formular) gegen die
   div.btn.link2details-Familie ("Jetzt ..."):
     @1280  210,92 gegen 214,88  (Delta 3,96)
     @375   198    gegen 238     (Delta 40)
   Am Handy ist das deutlich sichtbar. Genau das wird hier behoben.

   WAS DELTA 0 VERHINDERT — AUSGEWIESEN, NICHT VERSCHWIEGEN. Die Ursache
   liegt nicht an den Knoepfen, sondern an ihren ZELLEN. Gemessen @375
   (Elternknoten, Innenbreite nach Polster):
     div.btn.link2details   in .data-wrapper.opencase > .data > .row >
                               .col-md-6 > .line.line-label   = 238,00 px
     button#button_personalize in .data-wrapper > .data > form > .row >
                               .col-md-4                      = 198,00 px
   BEIDE Knoepfe fuellen ihre Zelle bereits zu 100 % aus (display: block,
   Breite = Innenbreite des Elternknotens). Die 40 px sind die Differenz der
   beiden GITTERZELLEN — eine Verschachtelungsebene Unterschied, kein
   Knopfmass. `width: 100%` aendert daran nichts (nachgemessen: 0 px), und
   ein gemeinsames min-width kann es auch nicht: ab 768 px ist die
   "Jetzt ..."-Familie durch die Serienklasse w-75 BREITENGETRIEBEN
   (432,47 px @768, 214,88 px @1280), der Knopf dagegen inhaltsgetrieben
   (210,92 px). Eine Zahl, die beide auf ein Mass zieht, gibt es nicht;
   sie waere an einen Beschriftungstext gebunden und bei jeder anderen
   Fensterbreite falsch. Die Zellen anzugleichen hiesse, am
   Portal-Gitter zu operieren — eine flaechenuebergreifende Aenderung, die
   dieses Los nicht traegt. Der Restunterschied ist im Bericht beziffert.

   WAS BLEIBT — UND WARUM ES KEINE TOTE REGEL IST: v0final.json setzt
   buttons.mobil-volle-breite: true. Die Katalogzeile erreicht nur
   .add-button, a.remove-button, .btn-continue und .jumbotron .btn-box .btn;
   die Portal-Familie stand nie in dieser Liste. Heute steht sie trotzdem
   auf voller Zellbreite — aber nur, weil die SERIE ihr display: block gibt.
   Eine Kundenvorlage, die .btn auf inline-block zurueckdreht, nimmt der
   Vorlage 0 ihre eigene Zusage lautlos wieder weg. Diese Regel macht die
   Zusage fuer die rote Portal-Familie wahr, unabhaengig davon. Der
   Wirkungsbereich ist eng: .data-wrapper kommt ausschliesslich im Portal
   vor (nachgezaehlt ueber alle 31 Fixtures: portal-order, portal-resale,
   portal-teams, portal-ticket — sonst nirgends).
   Kein Farbwert, keine Farb-Property, kein !important.
   --------------------------------------------------------------------- */
@media (max-width: 767px) {
  body.v2 .data-wrapper .btn.btn-danger {
    display: block;
    width: 100%;
    margin-left: 0;
    margin-right: 0;
  }
}

/* ---------------------------------------------------------------------
   F26b — DIE TRENNLINIE VOR DEN KNOEPFEN IN DEN RECHTEN SEITENBOXEN.

   INVENTUR ueber ALLE Portal-Fixtures (Traeger div.box-footer):
     portal-ticket        Teams              col-md-4   Seitenbox
     portal-ticket        Weiterverkauf      col-md-4   Seitenbox
     portal-order         Zusatzartikel      col-md-4   Seitenbox
     portal-order         Teams              col-md-4   Seitenbox
     portal-order         Weiterverkauf      col-md-4   Seitenbox
     portal-order         Kalender           col-md-4   Seitenbox
     portal-resale-form   "Willkommen ..."   (col-md-8) FUSSLEISTE
     portal-teams, portal-resale             keine .box-footer
   7 Vorkommen auf 3 Fixtures, an beiden Breiten identisch. Die Linie ist
   UNSERE: der nackte Shop trennt den Knopfbereich durch einen hellgrauen
   Grund (rgb(249,249,249)); A21 nimmt den Grund weg (Kasten-im-Kasten) und
   setzte stattdessen eine Haarlinie.

   ENTSCHEIDUNG, AUSDRUECKLICH AUSGEWIESEN (der CEO hat "jede gleichartige
   Box RECHTS" verlangt): zurueckgenommen wird die Linie in den SECHS
   rechten Seitenboxen. Die SIEBTE Zelle, die Fussleiste der
   Resale-Formularseite ("Zurueck" / "Weiterverkauf starten"), BEHAELT ihre
   Linie — dort trennt sie ein ausgefuelltes Formular vom Aktionsbereich,
   ist also Struktur und nicht Dekoration. Beide Lesarten sind gemessen
   getrennt; der Selektor bildet die Trennung strukturell ab (Seitenboxen
   liegen ausnahmslos in col-md-4, die Fussleiste nicht).
   Wert 0 ist eine Nullform, also kein Rahmen ohne Farbe (Waechter Arm 2b).
   --------------------------------------------------------------------- */
body.v2 .col-md-4 > .box-light > .box-footer,
body.v2 .col-md-4 > .box-grey > .box-footer {
  border-top-width: 0;
}

/* ---------------------------------------------------------------------
   F26c — RESALE-LISTE "WEITERVERKAUFBARE ARTIKEL" WIE DIE PORTAL-STARTSEITE.

   URSACHE, auf die Zeile genau: A21 setzt body.v2 .data-wrapper
   { background-color: transparent } und gibt den Grund mit
   .data-wrapper.opencase NUR den Zeilen mit offener Aufgabe zurueck. Die
   Teilnehmerzeilen der Resale-Liste sind schlichte .data-wrapper OHNE
   .opencase — sie stehen grundlos auf der weissen Karte, uebrig bleibt der
   graue 3-px-Stummel links. Genau der Eindruck des CEO.

   REFERENZ-OPTIK der Ticketzeilen der Portal-Start-/Bestellseite, an
   div.data-wrapper.opencase gemessen (v0final @1280):
     Grund rgb(242,245,249) = var(--v0t-kaufbox)   <- FEHLT
     Polster 18px 20px                              stimmt bereits
     Kante links 3px                                stimmt bereits
     Aussenabstand unten 20px                       stimmt bereits
   Es fehlt genau EIN Wert. Der CEO hat woertlich verlangt, dass es GLEICH
   aussieht — deshalb wird genau dieser eine Wert wiederhergestellt und
   sonst nichts.

   VERWORFEN (Variante P2): Kante zusaetzlich auf Vorlagenton und Radius
   rechts. Im Bild kaum unterscheidbar, wuerde aber einen NEUEN Unterschied
   zur Startseite erzeugen, wo wir gerade einen beseitigen. Die
   Kantenkorrektur (Serien-Grau rgb(204,204,204) an .data-wrapper) ist als
   eigener, flaechenuebergreifender Posten vorgemerkt — dann gemeinsam fuer
   Start-, Bestell- und Resale-Seite, nie nur an einer Stelle.

   PAAR-REGEL wie bei .data-wrapper.opencase (R2-E): die Flaeche bekommt
   BEWUSST keine eigene color-Zeile. Schriftpartner ist die geerbte
   Kartenschrift var(--tp-color-body-text, #2C333C); eine eigene Zeile
   wuerde die Serienzeile .line.opencase (Fristfarbe, Bedeutungstraeger)
   mit erben lassen, was KORRIDOR §3.9 ausnimmt. Rueckfall der Flaeche ist
   der Sockelton #F2F5F9 zur dunklen Rollenschrift; das Paar traegt auch
   dort, wo eine Kundenvorlage nur eine der beiden Rollen fuehrt.

   REICHWEITE, VOLLSTAENDIG AUSGEWIESEN (nachgetragen im Los F3-2): der
   Selektor greift auf ZWEI Portalflaechen, nicht nur auf die Resale-Liste —
     portal-resale   4 Zeilen  "Weiterverkaufbare Artikel"  (angefragt)
     portal-teams    2 Zeilen  Teilnehmerliste              (mitgetroffen)
   Die Teams-Liste ist DIESELBE Bauform (.box-resale > .data-wrapper ohne
   .opencase) und hatte denselben Defekt: grundlose Zeile mit grauem
   3-px-Stummel auf weisser Karte. Der Treffer ist inhaltlich gewollt und
   im Bild geprueft; er stand nur nicht im Bericht.

   ZWEITE SELEKTORHAELFTE ENTFERNT: `body.v2 #ticket_resale .data-wrapper`
   traf ueber alle 32 Fixturen 0 Knoten (auf portal-resale-form steht kein
   .data-wrapper unter #ticket_resale). Ein toter Ast ist der Freibrief der
   naechsten Runde — dieselbe Haltung wie bei den Freigabelisten des
   Waechters, wo tote Eintraege ein Befund sind. Wirkung der Entfernung:
   0 px auf allen 32 Fixturen x 2 Breiten.
   --------------------------------------------------------------------- */
body.v2 .box-resale .data-wrapper {
  background-color: var(--v0t-kaufbox);
}
