/* ============================================================================
   ThurData CI 2030 — Base
   ----------------------------------------------------------------------------
   VERSION 20260927a   <- bei JEDER Aenderung hochzaehlen (Datum + Buchstabe)

   Derselbe Wert steht an drei Stellen und MUSS uebereinstimmen:
     1. diese Zeile
     2. --td-base-version in :root (unten) — dadurch im Browser messbar:
        getComputedStyle(document.documentElement).getPropertyValue('--td-base-version')
     3. der Cache-Stempel im Template: ?v={$ciVer} — gesetzt in
        thurdata/ci-version.tpl (EINZIGE Stelle, von ai-pre-header.tpl
        und login.tpl eingebunden)
   Weicht 2 von 1 ab, laeuft eine andere Fassung als die im Repo. Weicht 3 ab,
   halten Browser die alte Fassung im Cache (Vorfall 21.09.2026: Downloads-Seite
   mit riesigen SVG-Symbolen). Hintergrund und Ausrollweg: Issue homepage#71.

   Diese Datei ist die QUELLE. Ausgeliefert wird eine Kopie unter
   whmcsCrosterTemplates (Branch homepage/beta1) -> thurdata/css/ci-2030-base.css.
   Jede Aenderung hier gehoert in derselben Runde dorthin — sonst sieht das
   Mockup etwas, das auf Devel nicht existiert.
   ----------------------------------------------------------------------------
   CI 2030 Base V1 — fuer Produktseiten an realen Referenzseiten validiert.
   Referenzen: ThurWeb (Matrix, 5 Produkte) · ThurVDC (Flex, Foto-Hero) ·
   ThurVServer (Flex, Split-Hero) · ThurBuilder (Kacheln, 3 Produkte).
   Stand 28.08.2026.

   Als Foundation zusaetzlich real bestaetigt an Zielgruppen-Seiten (KMU,
   Entwickler) und an einer Hub-/Routing-Seite mit Mini-Hero (Entwickler-Hub).
   Der Mini-/Routing-Hero — ohne Bild, ohne Buehne — braucht KEINE eigene
   Padding-Stufe: --td-hero-pad traegt ihn (gemessen 197 gegen 192 px
   Gesamtluft im Vergleichsstand).

   Aenderung 28.08.2026 (Bugfix, keine neue Generation): Hero-Luft haengt
   nicht mehr am Elementtyp des letzten Inhalts, siehe Abschnitt 4.

   Aenderungen seit dem 28.08.2026 (25 Commits, thematisch gebuendelt — die
   Einzelschritte stehen in der Git-Historie dieser Datei):
     28.08. Lightbox als Komponente (Base + components.js), Swipe mit der Maus
     02.09. Lightbox nimmt auch Videos; Produktkachel: Theme-Kollision bei
            .label, Kleinstgroessen auf zwei Stufen
     04.-08.09. Produktliste: EIN Markup fuer Matrix und Kacheln; Pakettabelle
            als Muster B2, Quermatrix entfernt; Leistungsliste einspaltig mit
            Haken im Kaestchen; Matrix mit fester Aktionsspalte; Wisch-Hinweis
            fuer waagrecht ueberlaufende Tabellen (components.js 1.4); zwei
            Theme-Kollisionen behoben (Buttons wurden beim Klicken rot,
            Empfehlungs-Badge war grau)
     17.09. Abschnitt 13 Formulare (Muster + Entscheid)
     22.09. Abschnitt 14 Dokumentseiten (.td-doc-*), components.js 1.5
     22.-23.09. Doc-Layout ausgebaut: Verzeichnis-Zaehler nur auf Listen-
            eintraegen, Seitenumbruch je Ziffer, Druck bringt nur den
            Vertragsteil, Briefkopf Variante A mit claim-losem Logo (PDF)

   Normative Quelle ist der Skill `ci-2030` (thurdata/skills ->
   plugins/thurdata-skills/skills/ci-2030/SKILL.md).

   Regel: Seiten binden diese Datei ein und definieren KEINE CI-Tokens lokal
   neu. Seitenspezifisches CSS ergaenzt, es ueberschreibt die Foundation nicht.

   Aenderungen am Foundation-/Komponentenkern kuenftig nur aufgrund eines
   realen neuen Falls, eines Fehlers oder eines dokumentierten CI-Entscheids —
   nicht aus theoretischer Optimierung. V1 deckt PRODUKTSEITEN, Zielgruppen-
   Landings und Hub-/Routing-Seiten ab. Tool-Hero und Formulare sind seit
   17.09.2026 an der Domain-Seite real geprueft (Abschnitt 13), DOKUMENTSEITEN
   seit 22.09.2026 an den SLA-Bedingungen (Abschnitt 14).

   Entscheidungsspur: thurdata/homepage -> content/entscheidungen/
   ============================================================================ */

/* ---------------------------------------------------------------- 1. Tokens */

:root{
  /* Fassung dieser Datei — im Browser auslesbar, siehe Kopf.
     MUSS mit der VERSION-Zeile im Kopf uebereinstimmen. */
  --td-base-version: "20260927a";

  /* Marke */
  --td-primary:      #1B5F8F;
  --td-secondary:    #7690C9;
  --td-accent:       #F08228;
  --td-accent-hover: #D96F1D;
  --td-dark:         #0F1A24;
  --td-light:        #F5F7FA;
  --td-blue:         #EEF4FA;

  /* Text hell — Kontrastwerte siehe content/ci-konventionen.md 3b */
  --td-text:   #2A2E36;   /* Headlines, zentrale Aussagen        */
  --td-body:   #3F4A5A;   /* Fliesstext, wichtige Erklaertexte   */
  --td-muted:  #526173;   /* Leads, sekundaere Erklaerungen      */
  --td-subtle: #64748B;   /* NUR Metadaten, nie Kaufentscheidung */

  /* Text dunkel */
  --td-dark-text:   rgba(255,255,255,.82);
  --td-dark-muted:  rgba(255,255,255,.68);
  --td-dark-subtle: rgba(255,255,255,.52);

  /* Linien */
  --td-line:        #DCE4EC;
  --td-line-strong: #C9D5E0;
  --td-border:      var(--td-line);

  /* Radius — 6 klein / 10 Karten+Panels / Pill Badges */
  --td-radius-sm:   6px;
  --td-radius-lg:   10px;
  --td-radius-pill: 999px;
  --td-radius:      var(--td-radius-sm);   /* Alias, Altbestand */

  /* Container */
  --td-container:      1180px;
  --td-container-wide: 1400px;
  --td-stage-max:       760px;

  /* Page Gutter — schaltet unten an den Foundation-Breakpoints um */
  --td-page-gutter-desktop: 40px;
  --td-page-gutter-tablet:  28px;
  --td-page-gutter-mobile:  20px;
  --td-page-gutter: var(--td-page-gutter-desktop);

  /* Element-Spacing (Abstaende INNERHALB von Komponenten) */
  --td-space-1:  4px;
  --td-space-2:  8px;
  --td-space-3: 16px;
  --td-space-4: 24px;
  --td-space-5: 32px;
  --td-space-6: 48px;
  --td-space-7: 64px;

  /* Hero-Padding — eigene Skala, schaltet unten an den Foundation-Breakpoints */
  --td-hero-pad: 90px;

  /* Section-Rhythmus — eigene Skala, NICHT an das Element-Raster gebunden */
  --td-sec-compact:  56px;
  --td-sec-default:  84px;
  --td-sec-spacious:104px;
  --td-sec: var(--td-sec-default);

  /* Interaktion */
  --td-focus-ring: 0 0 0 3px rgba(240,130,40,.24);
  --td-shadow-interaction: 0 8px 20px rgba(0,0,0,.08); /* NUR Hover/Overlay */
  --td-transition: .16s ease;
}

/* -------------------------------------------------- 2. Foundation / Reset */

*,*::before,*::after{box-sizing:border-box}

body{
  margin:0;
  font-family:Roboto,"Helvetica Neue",sans-serif;   /* kein Arial, kein system-ui */
  font-size:16px;
  line-height:1.5;
  color:var(--td-text);
  background:#fff;
  -webkit-font-smoothing:antialiased;
}

a{color:var(--td-primary)}
a:hover{color:var(--td-accent)}

img,video{max-width:100%;height:auto}

:focus-visible{outline:none;box-shadow:var(--td-focus-ring)}

/* ------------------------------------------------------------ 3. Typografie */

h1,h2,h3,h4{color:var(--td-text);margin:0 0 .4em}

h1{font-size:42px;line-height:1.08;font-weight:900;letter-spacing:-1px}
h2{font-size:36px;line-height:1.12;font-weight:700;letter-spacing:-.4px}
h3{font-size:21px;line-height:1.18;font-weight:700;letter-spacing:-.01em}

/* Hero-H1 — benannter Sonderfall, nur die H1 im Hero */
.hero h1,h1.td-h1-hero{
  font-size:52px;line-height:1.04;letter-spacing:-.025em;max-width:760px;
}

p{margin:0 0 1em}

.td-lead{
  font-size:17px;line-height:1.6;font-weight:400;
  color:var(--td-muted);max-width:68ch;
}

.td-small,.td-caption{font-size:13px;line-height:1.5;color:var(--td-muted)}

.td-kicker{
  font-size:12px;font-weight:700;letter-spacing:.11em;text-transform:uppercase;
  color:var(--td-primary);margin-bottom:10px;
}

/* Lesbarkeit: erklaerende Texte nie font-weight 300 unter 18px */
.td-text  {color:var(--td-text)}
.td-body  {color:var(--td-body)}
.td-muted {color:var(--td-muted)}
.td-subtle{color:var(--td-subtle)}   /* NUR Metadaten */

/* -------------------------------------------------- 4. Container & Sections */

.td-container{
  width:100%;
  max-width:var(--td-container);
  margin-inline:auto;
  padding-inline:var(--td-page-gutter);
}

/* NUR fuer breite technische Tabellen, Visualisierungen, Datenansichten */
.td-container--wide{max-width:var(--td-container-wide)}

/* Full Bleed: der Hintergrund ist viewportbreit, der Content bleibt im Container */
.td-bleed{width:100%}

.sec{padding:var(--td-sec) 0}
.sec--compact  {--td-sec:var(--td-sec-compact)}
.sec--spacious {--td-sec:var(--td-sec-spacious)}

.sec-white{background:#fff}
.sec-light{background:var(--td-light)}
.sec-blue {background:var(--td-blue)}
.sec-dark {background:var(--td-dark);color:var(--td-dark-text)}

.sec-dark h1,.sec-dark h2,.sec-dark h3{color:#fff}
.sec-dark .td-lead{color:var(--td-dark-muted)}
.sec-dark .td-kicker{color:#9fb2c4}
.sec-dark a{color:#fff}
/* Hover-Antwort fuer gewoehnliche TEXTLINKS auf dunklem Grund. Ohne sie bleibt
   der Link weiss und signalisiert nur ueber die Unterstreichung des Croster-Themes
   - die Knoepfe daneben wechseln dort laengst in die Akzentfarbe (ANEB 25.09.2026).
   !! :not([class*="btn"]) ist zwingend. Knoepfe sind hier <a>-Elemente; ohne den
   Ausschluss schlaegt diese Regel (0,2,1) die Base-Regel .btn-primary:hover (0,2,0)
   und faerbt die Knopfschrift orange auf orangem Grund - am 25.09.2026 auf 15 Seiten
   gemessen, nachdem die erste Fassung ohne Ausschluss ausgeliefert war. */
.sec-dark a:not([class*="btn"]):hover,
.hero-dark a:not([class*="btn"]):hover{color:var(--td-accent)}

/* Buehnen (Hero mit Bild, Standort-Sektion): nie reines vh, immer gedeckelt */
.td-stage{min-height:min(76vh,var(--td-stage-max))}

/* --- Hero: gemeinsames Skelett, KEIN Universal-Hero -----------------------
   Traegt alle fuenf Hero-Typen des CI, ohne einen davon zu gestalten. Geregelt
   ist nur, was sonst jede Seite neu erfindet: Buehne, Bildebene, Overlay,
   Textbreite, Padding und die Dunkel-/Hellzustaende.
   Die Bildebene gibt es bewusst in ZWEI Formen, beide kommen real vor:
     a) CSS-Hintergrund auf .hero          (ThurWeb — Aufloesungsschwellen im CSS)
     b) .hero-bg mit einem echten <img>    (ThurVDC — srcset, object-position,
        nie loading="lazy", weil der Hero das LCP-Element ist)
   Motiv-Abhaengiges bleibt lokal: welches Bild, welcher Bildausschnitt, wie
   stark der Verlauf deckt. Buehnenhoehe ist opt-in ueber .td-stage. */
.hero{
  position:relative;display:flex;align-items:center;overflow:hidden;
  background-position:center;background-size:cover;background-repeat:no-repeat;
}
.hero>.td-container{position:relative;z-index:2;padding-block:var(--td-hero-pad)}

/* Die aeussere Hero-Luft kommt aus dem Padding, NICHT aus dem Margin des
   letzten Inhaltselements. Ohne diese Regel addiert ein abschliessender
   Absatz sein margin-bottom (1em) auf --td-hero-pad, und der Hero wird unten
   schwerer als oben — je nachdem, welcher Elementtyp zufaellig zuletzt steht.
   Gemessen 28.08.2026 an zwei unabhaengigen Seiten: ThurBuilder (endet mit
   p.tb-trust) 90/104 px, Entwickler-Hub (endet mit p.td-lead) 90/107 px;
   drei Heroes, die mit einem div enden, waren symmetrisch.
   Beide Selektoren noetig: nicht jeder Hero benutzt .hero-copy (ThurVServer
   setzt seine Textspalte direkt in den Container). */
.hero>.td-container>:last-child,
.hero-copy>:last-child{margin-bottom:0}

.hero-bg{position:absolute;inset:0;z-index:0}
.hero-bg img{display:block;width:100%;height:100%;object-fit:cover}

/* NUR die Ebene, KEIN Verlauf. Deckung, Richtung und Intensitaet sind
   Bildkorrektur und haengen am Motiv — an VDC gemessen (27.08.2026): derselbe
   Default-Verlauf, der ThurWeb traegt, liess dort die weisse H1 auf dem hellen
   Monitor stehen. Base definiert die Overlay-Ebene, nicht die Bildkorrektur.
   Jede Seite mit Foto-Hero setzt ihren eigenen background auf .hero-overlay. */
.hero-overlay{position:absolute;inset:0;z-index:1}

/* Textspalte: gedeckelt, damit die Zeilen lesbar kurz bleiben. */
.hero-copy{max-width:var(--td-stage-max)}
/* 42ch ist der Regelfall: im Hero konkurriert der Lead mit einem Bild oder
   einer Medienspalte, und kurze Zeilen halten ihn dort lesbar. Aktiv an
   ThurVDC, ThurWeb und ThurBuilder (je 401 px gemessen 28.08.2026).
   ENTSCHEID ANEB 28.08.2026: der Deckel BLEIBT. Ein Hero OHNE Bild und ohne
   Medienspalte (Mini-/Routing-Hero) weitet lokal auf den globalen Lead-Deckel
   (68ch) — bisher genau ein realer Fall, der Entwickler-Hub. Erst wenn ein
   zweiter unabhaengiger Fall dazukommt, wird daraus eine Base-Regel.
   Kein Umkehrschluss: enger duerfen Heroes lokal jederzeit werden. */
.hero-copy .td-lead{max-width:42ch}

/* Medienflaeche fuer Split-/UI-Heroes — nur Rahmen, keine Typ-Gestaltung. */
.hero-media{position:relative;z-index:2;min-width:0}
.hero-media img{display:block;width:100%;height:auto;border-radius:var(--td-radius-lg)}

/* Dunkel: die Textfarben der Section-Ebene gelten im Hero nicht automatisch,
   weil .hero-dark keine .sec-dark ist. */
.hero-dark{background-color:var(--td-dark);color:var(--td-dark-text)}
.hero-dark h1,.hero-dark h2,.hero-dark h3{color:#fff}
.hero-dark .td-lead{color:var(--td-dark-text)}
.hero-dark .td-kicker{color:#9fb2c4}
.hero-dark .td-small,.hero-dark .td-caption{color:var(--td-dark-muted)}
/* Hell: erbt die Standard-Textfarben, bekommt hier bewusst KEINEN Hintergrund
   aufgezwungen — weiss und --td-light sind beide zulaessig. */

/* --------------------------------------------------------- 5. Basis-Grids */

.td-grid-2,.td-grid-3,.td-grid-cards{display:grid;gap:var(--td-space-4)}
.td-grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.td-grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.td-grid-cards{grid-template-columns:repeat(auto-fit,minmax(280px,1fr))}
.td-grid--tight{gap:var(--td-space-3)}

/* ------------------------------------------------------------- 6. Buttons */
/* Orange = primaere Handlung · Blau = sekundaer, Navigation, Routing.
   Es gibt KEINEN blau gefuellten Button.                                    */

.btn{
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;padding:0 18px;
  border:1.5px solid transparent;border-radius:var(--td-radius-sm);
  font-size:14px;font-weight:700;line-height:1;
  text-decoration:none;cursor:pointer;outline:none;
  transition:background-color var(--td-transition),border-color var(--td-transition),
             color var(--td-transition),box-shadow var(--td-transition);
}

.btn-primary{background:var(--td-accent);border-color:var(--td-accent);color:#fff}
.btn-primary:hover{background:var(--td-accent-hover);border-color:var(--td-accent-hover);color:#fff}
.btn-primary:focus-visible{box-shadow:var(--td-focus-ring)}

.btn-secondary{background:#fff;border-color:var(--td-primary);color:var(--td-primary)}
.btn-secondary:hover,
.btn-secondary:focus-visible{
  border-color:var(--td-accent);color:var(--td-accent);
  background:rgba(240,130,40,.055);
}
.btn-secondary:focus-visible{box-shadow:0 0 0 3px rgba(240,130,40,.15)}

.btn-text{
  min-height:auto;padding:7px 0;border:0;border-radius:0;
  background:transparent;color:var(--td-primary);text-decoration:none;
}
/* text-decoration auch im Hover: Crosters a:hover{underline} (0,1,1) schlaegt
   sonst die Ruhe-Regel (0,1,0) - gleiche Kollision wie .product-tile. */
.btn-text:hover{color:var(--td-accent);text-decoration:none}
.btn-text:focus-visible{color:var(--td-accent);box-shadow:0 2px 0 var(--td-accent)}

/* Auf dunklem Grund: kontrastiert, Bedeutung unveraendert */
.sec-dark .btn-secondary,.hero-dark .btn-secondary{
  background:transparent;border-color:rgba(255,255,255,.78);color:#fff;
}
.sec-dark .btn-secondary:hover,.hero-dark .btn-secondary:hover{
  color:var(--td-accent);border-color:var(--td-accent);background:rgba(240,130,40,.07);
}
.sec-dark .btn-text,.hero-dark .btn-text{color:#fff}
.sec-dark .btn-text:hover,.hero-dark .btn-text:hover{color:var(--td-accent)}
.sec-dark .btn-outline,.hero-dark .btn-outline{
  background:transparent;border-color:rgba(255,255,255,.35);color:#fff;
}
.sec-dark .btn-outline:hover,.hero-dark .btn-outline:hover{
  border-color:rgba(255,255,255,.65);
}

/* --- Zustaende gegen das Croster-Theme durchsetzen -----------------------
   Das Theme bringt Bootstrap mit, und dort heissen die Klassen GENAUSO:
   `.btn-secondary` ist dort ROT (#db3f3b), `.btn-primary` BLAU (#1b5f8f).
   Im Ruhezustand gewinnen wir ueber die Ladereihenfolge — bei gleicher
   Spezifitaet zaehlt die spaetere Datei, und unser Base laedt nach dem Theme.

   Bei den ZUSTAENDEN kippt das:
     Bootstrap  .btn-secondary:focus                              = (0,2,0)
     Bootstrap  .btn-secondary:not(:disabled):not(.disabled):active = (0,4,0)
     wir        .btn-secondary                                     = (0,1,0)
   Wir hatten nur `:focus-visible`, und das feuert bei der MAUS gar nicht —
   nur bei Tastatur. Ein Mausklick loest aber `:focus` aus. Ergebnis, am Render
   gesehen (MAEB 08.09.2026): Der angeklickte Bestellknopf wurde ROT und blieb
   es, solange der Fokus stand. Das las sich wie ein Auswahlzustand, den es gar
   nicht gibt — geklickt wird direkt in den Warenkorb. Beim orangen Knopf waere
   dasselbe in Dunkelblau passiert; das hatte nur noch niemand angeklickt.

   Deshalb hier `:focus` UND `:active` mit (0,4,0), also gleich schwer wie
   Bootstraps schwerste Regel und spaeter im Quelltext. Der Tastatur-Ring kommt
   danach mit derselben Spezifitaet zurueck, damit er wieder obenauf liegt.
   Barrierefreiheit bleibt: Wer mit der Tastatur navigiert, sieht den Ring. */
.btn:not(:disabled):not(.disabled):focus{box-shadow:none;outline:none}
.btn-primary:not(:disabled):not(.disabled):focus,
.btn-primary:not(:disabled):not(.disabled):active{
  background:var(--td-accent-hover);border-color:var(--td-accent-hover);color:#fff;
}
.btn-secondary:not(:disabled):not(.disabled):focus,
.btn-secondary:not(:disabled):not(.disabled):active{
  background:rgba(240,130,40,.055);border-color:var(--td-accent);color:var(--td-accent);
}
.btn-primary:not(:disabled):not(.disabled):focus-visible{box-shadow:var(--td-focus-ring)}
.btn-secondary:not(:disabled):not(.disabled):focus-visible{box-shadow:0 0 0 3px rgba(240,130,40,.15)}
.btn-text:not(:disabled):not(.disabled):focus-visible{box-shadow:0 2px 0 var(--td-accent)}

.btn-row{display:flex;gap:12px;flex-wrap:wrap}

/* ══ LEGACY-ALIASE — nur fuer den Altbestand, KEIN neues Markup damit ══
   Kanonisch sind .td-lead und .td-kicker. Die Kurznamen .lead / .kicker /
   .eyebrow stammen aus den Serienseiten vor dem Base-CSS. Zwei gleichwertige
   Namen fuer dieselbe Sache waren ein Grund, warum die Seiten auseinander-
   gedriftet sind (Reifebericht 27.08.2026). Sie bleiben, damit bestehende
   Seiten nicht brechen — der Migrationsweg ist Suchen-und-Ersetzen, kein Umbau.
   Lint-Kandidat: .lead / .kicker / .eyebrow in neuem Markup. */
.lead{font-size:17px;line-height:1.6;color:var(--td-muted);max-width:68ch;margin:14px 0 0}
.kicker,.eyebrow{
  font-size:12px;font-weight:700;letter-spacing:.11em;
  text-transform:uppercase;color:var(--td-primary);
}
.sec-dark .lead{color:var(--td-dark-muted)}
.sec-dark .kicker,.sec-dark .eyebrow{color:#9fb2c4}
.hero-copy .lead{max-width:42ch}
.hero-dark .lead{color:var(--td-dark-text)}
.hero-dark .kicker,.hero-dark .eyebrow{color:#9fb2c4}

/* LEGACY-Buttons — dieselbe Regel: kein neues Markup damit bauen. */
.btn-cta{background:var(--td-accent);border-color:var(--td-accent);color:#fff}
/* color gehoert hier zwingend dazu: Bootstrap im Croster-Theme fuehrt
   .btn:hover{color:#212529} mit (0,2,0) und schlaegt damit .btn-cta (0,1,0).
   Ohne diese Angabe wird die Schrift beim Ueberfahren dunkelgrau auf Orange -
   am 25.09.2026 an 10 Knoepfen gemessen, nachdem die lokalen .btn-cta-Regeln
   der ZG-Seiten gefallen waren, die es bis dahin zufaellig abgefangen hatten.
   .btn-primary, .btn-secondary und .btn-outline setzen ihre Hover-Farbe schon. */
.btn-cta:hover{background:var(--td-accent-hover);border-color:var(--td-accent-hover);color:#fff}
.btn-outline{background:#fff;border-color:var(--td-primary);color:var(--td-primary)}
.btn-outline:hover{border-color:var(--td-accent);color:var(--td-accent);background:rgba(240,130,40,.055)}
.btn-hero{padding:9px 24px;font-size:14px}

/* ------------------------------------------- 7. Standardflaechen & Content */

.card{
  background:#fff;
  border:1px solid var(--td-border);
  border-radius:var(--td-radius-lg);
  padding:32px 28px;
  /* kein dekorativer Dauerschatten */
}
/* Keine eigene Card-Typografie: H3 und Fliesstext folgen der Typografie-Skala.
   Die frueheren Werte (H3 18px, p 14.5px) stammten aus den Referenzseiten und
   waren nie beschlossen — entfernt 27.08.2026. */

/* Karten-Icon: Kachel 40 px, Radius klein, Icon 24 px Primaerblau, 10 px zum Titel.
   Entscheid ANEB 24.09.2026 (Muster ci-2030/muster-card-icon-2026-09-24.html, Variante B):
   das Icon bekommt eine Zone und steht in jeder Karte auf derselben Hoehe.
   Karten als Flex-Spalte mit gap:10px und >*{margin:0} setzen den Abstand ueber gap. */
.card-icon{
  width:40px;height:40px;
  display:flex;align-items:center;justify-content:center;
  border-radius:var(--td-radius-sm);
  margin-bottom:10px;
  background:#E7EEF6;color:var(--td-primary);
}
.card-icon svg{
  width:24px;height:24px;
  /* CI: Lucide Outline, monochrom, currentColor, KEIN Filled-Icon-Mix.
     Ohne fill:none rendern Pfade ohne eigenes fill-Attribut schwarz gefuellt
     (an ThurVDC gemessen 27.08.2026). */
  fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
.sec-dark .card-icon{background:rgba(255,255,255,.08);color:rgba(255,255,255,.8)}

.panel{
  background:#fff;border:1px solid var(--td-line);
  border-radius:var(--td-radius-lg);padding:18px 20px;
}

/* !important ist hier KEINE Schlamperei, sondern der einzige Weg: Das
   Croster-Theme (Bootstrap-Basis) setzt `.badge{background-color:#999!important;
   border-radius:12px!important}`. Gegen ein !important aus einer Datei, die in
   keinem unserer Repos liegt, hilft keine Spezifitaet — nur ein eigenes
   !important. Betraf beide Empfehlungs-Badges (Auswahlmatrix und Tabellenkopf):
   Sie waren auf Devel GRAU statt weiss. Lokal faellt das nie auf, weil dort das
   Theme fehlt (MAEB am Render gesehen, 08.09.2026).
   Nur diese beiden Eigenschaften tragen !important. Schriftgrad, Gewicht und
   Innenabstand setzt das Theme ohne — die gewinnen wir ueber die Ladereihenfolge. */
.badge{
  display:inline-flex;align-items:center;justify-content:center;
  background:#fff!important;color:var(--td-primary);
  border:1px solid rgba(255,255,255,.28);border-radius:var(--td-radius-pill)!important;
  padding:4px 9px;
  font-size:11px;font-weight:700;letter-spacing:.035em;text-transform:uppercase;
  white-space:nowrap;
}

/* FAQ — details/summary, kein JS */
.faq details{border-bottom:1px solid var(--td-line)}
.faq summary{
  cursor:pointer;list-style:none;
  padding:16px 0;font-size:17px;font-weight:700;color:var(--td-text);
  display:flex;justify-content:space-between;align-items:center;gap:16px;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:"+";font-weight:400;font-size:22px;color:var(--td-primary);
  transition:transform var(--td-transition);
}
.faq details[open] summary::after{content:"\00d7"}
.faq p{color:var(--td-muted);margin:0 0 16px}

/* ------------------------------------------------------- 8. Produktsystem */
/* VERTRAG Swipe (Base-CSS <-> ci-2030-components.js), festgehalten 27.08.2026:
   Der Scroller traegt IMMER beides — seine Klasse UND data-swipe-container:

       <div class="mobile-products" data-swipe-container> … </div>

   Das Attribut ist der kanonische Marker. Das Swipe-LAYOUT haengt daran
   (siehe Abschnitt 9), und das JS bindet den Tap-vs-Swipe-Schutz und den
   Swipe-Hinweis an denselben Selektor. Damit kann kein stiller Fehlzustand
   entstehen: ohne Attribut gibt es KEIN Swipe-Layout — der Fehler ist sofort
   sichtbar, statt dass ein Wisch versehentlich ein Produkt auswaehlt.
   Umgekehrt gilt: Layout ohne Verhalten ist nicht vorgesehen.
   Lint-Kandidat: .product-grid / .mobile-products ohne data-swipe-container. */
/* Regeln: CI -> "Produktauswahl & Paketvergleich".
   Bis 3 Produkte zeigen, ab 4 vergleichen. Eine Designsprache, zwei Formen. */

.product-responsive{container-type:inline-size;container-name:products}
.swipe-wrap{position:relative}

/* --- Produktkachel (2-3 Produkte) --- */
/* align-items:start — sonst zieht das Grid alle Kacheln einer Reihe auf die
   Hoehe der hoechsten. Klappt eine Kachel auf, bekommen die geschlossenen
   leeren Raum unter dem Knopf (am Render gemessen 03.09.2026). */
.product-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px;align-items:start}

.product-tile{
  position:relative;display:flex;flex-direction:column;min-width:0;
  background:#fff;border:1px solid var(--td-line-strong);
  border-radius:var(--td-radius-lg);overflow:hidden;
  text-decoration:none;color:inherit;outline:none;
  transition:border-color var(--td-transition),box-shadow var(--td-transition);
}
/* ACHTUNG Theme-Kollision: Die Kachel ist ein <a>, und das Croster-Theme setzt
   fuer a:hover ein text-decoration:underline. Die Grundregel oben deckt nur den
   Ruhezustand — beim Hover unterstreicht das Theme JEDEN Text in der Kachel,
   vom Produktnamen bis zum Merkmalwert (auf Devel gesehen 04.09.2026 an
   ThurBuilder). Vorher fiel es nicht auf, weil die orange Flaechenfaerbung
   dominierte; seit die weg ist, ist es der einzige verbliebene Effekt.
   Deshalb hier explizit und inklusive Kindelementen. */
.product-tile:hover,.product-tile:hover *,
.product-tile:focus-visible,.product-tile:focus-visible *{text-decoration:none}

/* HOVER = UMRANDUNG, NICHT TEXTFLAECHE (Entscheid ANEB/MAEB 03.09.2026).
   Zwei Aenderungen gegenueber V1:
   1. Der Zustand faerbt keine Textflaechen mehr ein, nur noch den Rahmen.
      Die zweite Linie liegt als Innenschatten darin — eine echte
      Border-Verbreiterung wuerde das Layout verschieben.
   2. Gekapselt in @media (hover:hover): Auf Tablets bleibt ein Hover sonst
      nach dem Antippen kleben, bis man woanders hintippt. Auf Touch gibt es
      den Zustand damit gar nicht — dort wird ohnehin direkt getroffen. */
.product-tile:hover{border-color:var(--td-line-strong);box-shadow:none}
@media (hover:hover) and (pointer:fine){
  .product-tile:hover{
    border-color:var(--td-accent);
    box-shadow:inset 0 0 0 1px var(--td-accent);
  }
}
.product-tile:focus-visible{box-shadow:0 0 0 3px rgba(240,130,40,.2),0 8px 22px rgba(15,26,36,.06)}

/* Empfohlen = permanenter Status -> Primary, nie Orange.
   Die Statuslinie liegt als Pseudo-Element UEBER dem Header: ein inset-Schatten
   am .product-tile wird vom dunklen .tile-head verdeckt und bliebe unsichtbar
   (gemessen 27.08.2026 am Referenz-Render). */
.product-tile.recommended{border-color:rgba(27,95,143,.52)}
.product-tile.recommended::before{
  content:"";position:absolute;top:0;left:0;right:0;height:3px;
  background:var(--td-primary);z-index:2;pointer-events:none;
  transition:background var(--td-transition);
}
.product-tile.recommended:hover,.product-tile.recommended:focus-visible{
  border-color:var(--td-accent);
  box-shadow:0 0 0 2px rgba(240,130,40,.16),0 10px 24px rgba(15,26,36,.08);
}
/* Die weisse Pill der Kachel bleibt in JEDEM Zustand Status */
.product-tile .badge{background:#fff;color:var(--td-primary)}

.tile-head{
  padding:21px 22px 18px;background:var(--td-dark);color:#fff;
  border-bottom:1px solid rgba(255,255,255,.08);
}
.tile-head h3{color:#fff;margin:0}
.tile-head-top{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:7px}
.tile-claim{font-size:14px;color:rgba(255,255,255,.72);margin:6px 0 0;min-height:42px}
/* HINWEIS: Das CI verlangt gleiche Headerhoehe je Produktgruppe. min-height traegt
   nur einzeilige Claims. Den Angleich mehrzeiliger .tile-head macht zentral
   ci-2030-components.js (equalizeTileHeads) — nicht seitenlokales JS. */
/* Der dunkle Header bleibt beim Hover dunkel */
.product-tile:hover .tile-head,.product-tile:focus-visible .tile-head{background:var(--td-dark)}
/* Die Textflaechen bleiben ruhig — siehe Hover-Entscheid oben. ANEB wollte den
   Zustand ausdruecklich am Rahmen sehen, nicht im Text. */
.product-tile:hover .tile-price,.product-tile:hover .setup-fee,.product-tile:hover .tile-fact,
.product-tile:focus-visible .tile-price,.product-tile:focus-visible .setup-fee,
.product-tile:focus-visible .tile-fact{background:transparent}

/* Preis und einmalige Aufschaltung sind getrennte Ebenen */
.tile-price{padding:18px 22px 14px;border-bottom:1px solid var(--td-line)}
.price-main{font-size:29px;line-height:1.05;font-weight:900;color:var(--td-dark);letter-spacing:-.025em}
.price-period{font-size:13px;color:var(--td-muted);margin-top:5px}
.setup-fee{
  padding:10px 22px;border-bottom:1px solid var(--td-line);
  font-size:13px;color:var(--td-body);background:rgba(245,247,250,.65);
}
.setup-fee strong{font-weight:700;color:var(--td-text)}

/* max. 4 entscheidungsrelevante Merkmale */
.tile-facts{display:flex;flex-direction:column}
.tile-fact{
  display:flex;align-items:baseline;justify-content:space-between;gap:18px;
  padding:12px 22px;border-bottom:1px solid var(--td-line);font-size:14px;
}
.tile-fact:last-child{border-bottom:0}
/* ACHTUNG Namenskollision: Das Croster-Theme (assets/css/themes/style.min.css)
   fuehrt eine eigene Klasse .label - ein Bootstrap-Etikett mit font-size:75%,
   eigenem Innenabstand und Radius. Sie trifft jede Produktkachel und macht die
   Merkmalsbezeichnung ein Viertel kleiner als vorgesehen. Im Mockup faellt das
   nicht auf, weil dort kein Theme geladen ist. Die folgenden Angaben setzen die
   Etikett-Eigenschaften bewusst zurueck - nicht entfernen. */
.tile-fact .label{
  color:var(--td-muted);
  font-size:inherit;line-height:inherit;font-weight:400;
  padding:0;max-width:none;border-radius:0;
}
.tile-fact .value{font-weight:700;color:var(--td-dark);text-align:right}

/* --- Produktmatrix (4+ Produkte) --- */
/* Produkte als ZEILEN, Merkmale als Spalten. Max. 6 Spalten, keine Aktionsspalte. */
.product-matrix,.matrix-shell{
  background:#fff;border:1px solid var(--td-line-strong);
  border-radius:var(--td-radius-lg);overflow:hidden;
}
.matrix-head,.matrix-row{
  display:grid;grid-template-columns:1.42fr .82fr .92fr .80fr .92fr 1.38fr;
  align-items:center;column-gap:14px;
}
/* Header NICHT sticky */
.matrix-head{
  background:var(--td-dark);color:#fff;min-height:56px;padding:0 22px;
  font-size:13px;font-weight:700;
}
.matrix-row{
  position:relative;min-height:78px;padding:11px 22px;
  border-top:1px solid var(--td-line);background:#fff;
  text-decoration:none;color:inherit;outline:none;
  transition:background var(--td-transition),box-shadow var(--td-transition);
}
/* Dieselbe Theme-Kollision wie bei der Kachel: a:hover unterstreicht sonst
   jeden Wert in der Zeile. */
.matrix-row:hover,.matrix-row:hover *,
.matrix-row:focus-visible,.matrix-row:focus-visible *{text-decoration:none}
.matrix-row:first-of-type{border-top:0}
.matrix-row::after{
  content:"";position:absolute;inset:-1px;pointer-events:none;
  border:1.5px solid transparent;transition:border-color var(--td-transition);
}
.matrix-row:hover::after,.matrix-row:focus-visible::after{
  border-color:var(--td-accent);
  box-shadow:0 0 0 2px rgba(240,130,40,.16),inset 0 0 18px rgba(240,130,40,.03);
}
.matrix-row:hover,.matrix-row:focus-visible{background:rgba(240,130,40,.028)}

.matrix-row.recommended{background:rgba(27,95,143,.052);box-shadow:inset 3px 0 0 var(--td-primary)}
/* Nur die Zeile als Ganzes reagiert Richtung Orange. Der Badge NICHT:
   Primary = permanenter Status, Orange = aktuelle Interaktion — das gilt fuer
   die Pill in jedem Zustand, in der Kachel wie in der Matrix (ANEB 27.08.2026,
   praezisiert die frueheren "der Badge folgt der Zeile"-Formulierung). */
.matrix-row.recommended:hover,.matrix-row.recommended:focus-visible{
  background:rgba(240,130,40,.07);box-shadow:inset 3px 0 0 var(--td-accent);
}
/* Auf hellem Grund braucht die Pill einen Primary-Rand — der weisse Rand der
   Basisdefinition traegt nur auf dem dunklen Kachelheader. */
.matrix-row .badge{background:#fff;color:var(--td-primary);border-color:rgba(27,95,143,.3)}

.pkg-stack{display:flex;flex-direction:column;align-items:flex-start;gap:5px}
.pkg-name{font-weight:800;color:var(--td-dark)}
.pkg-sub{font-size:12px;color:var(--td-muted);margin-top:2px}
.metric{font-size:14px;color:var(--td-body)}
.metric strong{font-size:15px;color:var(--td-dark)}
.row-price{font-weight:800;color:var(--td-dark);font-size:16px;white-space:nowrap;text-align:right}
/* In der dunklen Kopfzeile traegt die dunkle Schrift nicht (an ThurWeb gemessen
   27.08.2026: die Spaltenueberschrift "Preis" war unsichtbar). */
.matrix-head .row-price{color:#fff;font-weight:700;font-size:13px}
.row-price small{display:block;font-weight:400;color:var(--td-muted);font-size:11px}

/* --- Gemeinsame Leistungen (Ebene 2) --- */
.included{
  margin-top:18px;background:#fff;border:1px solid var(--td-line);
  border-radius:var(--td-radius-lg);padding:18px 20px;
  display:flex;align-items:flex-start;gap:22px;
}
.included h3{font-size:16px;min-width:195px;padding-top:2px}
/* Einspaltig untereinander, Haken im Kaestchen (Entscheid MAEB 07.09.2026).
   Vorher flex-wrap: Die Punkte versackten je nach Textlaenge, die rechte
   Spalte lief unten aus. Untereinander stehen sie in einer klaren Linie —
   die Sektion wird hoeher, aber neben der Pakettabelle ist genug Platz.
   Das Haekchen steht direkt im Text, nicht als CSS-Escape: robuster, und die
   Datei ist ohnehin UTF-8. */
.included-list{display:grid;grid-template-columns:1fr;gap:9px;
               color:var(--td-body);font-size:14px}
.included-list span{display:flex;align-items:flex-start;gap:10px;line-height:1.45}
.included-list span::before{
  content:"✓";flex:0 0 auto;width:19px;height:19px;border-radius:4px;margin-top:1px;
  display:flex;align-items:center;justify-content:center;
  font-size:12px;font-weight:800;
  background:rgba(27,95,143,.10);color:var(--td-primary);
}

.decision-links{display:flex;gap:16px;align-items:center;margin-top:16px;flex-wrap:wrap}

/* --- Swipe-Hinweis: einmaliger Impuls, deshalb Orange zulaessig --- */
.mobile-arrow{display:none}
.mobile-only{display:none}
@keyframes td-nudge{0%,100%{transform:translateX(0);opacity:.88}50%{transform:translateX(5px);opacity:1}}

/* ============================================================================
   9. Responsive — Ebene B: die KOMPONENTENBREITE entscheidet (@container)
   Nicht das Geraet. cqw statt vw. Nie durch Viewport-Breakpoints ersetzen.
   ============================================================================ */

/* 2-3 Produkte: unter 900px Komponentenbreite -> Swipe.
   Angehoben von 820 auf 900 (Entscheid ANEB 27.08.2026 nach dem
   ThurBuilder-Realtest): bei 824-844px passen drei Kacheln zwar hinein, jede
   ist dann aber nur noch ~260px breit und die Claims brechen dreizeilig.
   Drei Kacheln nur, wenn jede Breite fuer ruhige Typografie hat.
   Die Matrixgrenze fuer 4+ Produkte bleibt bewusst bei 860px — eine
   Matrixzeile braucht pro Produkt weniger Platz als eine Kachel. */
@container products (max-width: 899px){
  .product-grid[data-swipe-container]{
    display:flex;overflow-x:auto;scroll-snap-type:x mandatory;
    overscroll-behavior-x:contain;gap:14px;padding:0 0 8px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .product-grid::-webkit-scrollbar{display:none}
  .product-grid .product-tile{flex:0 0 min(92cqw,600px);scroll-snap-align:start}
  .tile-claim{min-height:auto}

  .product-responsive:not(.matrix-responsive) .mobile-arrow{
    display:flex;position:absolute;right:2px;top:46%;
    width:34px;height:34px;border-radius:var(--td-radius-pill);
    background:var(--td-accent);color:#fff;
    align-items:center;justify-content:center;font-size:22px;font-weight:700;
    z-index:5;box-shadow:0 5px 16px rgba(240,130,40,.24);
    animation:td-nudge 1.35s ease-in-out 2 forwards;
    pointer-events:none;opacity:0;transition:opacity .28s ease;
  }
}

/* 4+ Produkte: Matrix nur, wenn die Komponente ~860px hat — sonst Swipe-Karten.
   Matrix nicht erzwingen: sie erscheint nur, wenn sie komfortabel lesbar ist. */
@container products (max-width: 859px){
  .matrix-responsive .desktop-matrix,
  .matrix-responsive .product-matrix{display:none}
  .matrix-responsive .mobile-only{display:block}
  .matrix-responsive .mobile-products[data-swipe-container]{
    display:flex;overflow-x:auto;scroll-snap-type:x mandatory;
    overscroll-behavior-x:contain;gap:14px;padding:0 0 8px;
    scrollbar-width:none;-webkit-overflow-scrolling:touch;
  }
  .matrix-responsive .mobile-products::-webkit-scrollbar{display:none}
  .matrix-responsive .mobile-products .product-tile{flex:0 0 min(92cqw,600px);scroll-snap-align:start}

  .matrix-responsive .mobile-arrow{
    display:flex;position:absolute;right:2px;top:46%;
    width:34px;height:34px;border-radius:var(--td-radius-pill);
    background:var(--td-accent);color:#fff;
    align-items:center;justify-content:center;font-size:22px;font-weight:700;
    z-index:5;box-shadow:0 5px 16px rgba(240,130,40,.24);
    animation:td-nudge 1.35s ease-in-out 2 forwards;
    pointer-events:none;opacity:0;transition:opacity .28s ease;
  }
}

.mobile-arrow.show{opacity:1}
.mobile-arrow.hide{opacity:0}
.mobile-arrow::after{content:"\203A";transform:translateY(-1px)}

/* Querformat / flache Viewports: Karten decken statt aufblasen */
@media (orientation:landscape) and (max-height:650px){
  .sec{padding:42px 0}
  .product-grid .product-tile,
  .matrix-responsive .mobile-products .product-tile{
    flex-basis:clamp(320px,48cqw,390px);
  }
  .tile-head{padding-top:16px;padding-bottom:14px}
  .tile-price{padding-top:14px;padding-bottom:11px}
  .tile-fact{padding-top:10px;padding-bottom:10px}
  .setup-fee{padding-top:8px;padding-bottom:8px}
}

/* ============================================================================
   10. Responsive — Ebene A: globale Foundation (@media, Viewport)
   Genau drei Breakpoints. Sie zwingen KEINE Komponente.
   ============================================================================ */

/* Intermediate / Tablet: 768-1023px */
@media (max-width:1023px){
  :root{
    --td-hero-pad: 72px;
    --td-page-gutter: var(--td-page-gutter-tablet);
    --td-sec-compact:  48px;
    --td-sec-default:  64px;
    --td-sec-spacious: 84px;
  }
  .td-grid-3{grid-template-columns:repeat(2,minmax(0,1fr))}
}

/* Mobile: <=767px */
@media (max-width:767px){
  :root{
    --td-hero-pad: 64px;
    --td-page-gutter: var(--td-page-gutter-mobile);
    --td-sec-compact:  40px;
    --td-sec-default:  56px;
    --td-sec-spacious: 72px;
  }

  h1{font-size:32px}
  h2{font-size:28px}
  h3{font-size:19px}
  .hero h1,h1.td-h1-hero{font-size:38px}
  .td-lead{font-size:16px}
  .td-kicker{font-size:11px}
  .lead{font-size:16px}                    /* LEGACY, siehe Alias-Block */
  .kicker,.eyebrow{font-size:11px}         /* LEGACY */

  .td-grid-2,.td-grid-3{grid-template-columns:1fr}
  .td-stage{min-height:0}
  /* Auf einer Spalte gibt es nichts mehr zu deckeln */
  .hero-copy{max-width:none}

  .included{display:block;padding:17px}
  .included h3{min-width:0;margin-bottom:12px}
  /* Einspaltig auch hier. Diese Regel stammt aus der Zeit, als die Liste
     ueberall flex-wrap war und auf Mobile zwei Spalten bekam. Seit der
     Umstellung auf einspaltig (07.09.2026) stand sie dagegen und drehte das
     Ergebnis um: Desktop einspaltig, Handy zweispaltig — bei 377px zwei
     137px-Spalten, in denen "Taegliche Sicherungen, bis 180 Tage zurueck"
     dreizeilig brach. Beim Aendern einer Basisregel immer die
     Media-Query-Bloecke mitpruefen. */
  .included-list{grid-template-columns:1fr;gap:9px;font-size:13px}
  .decision-links{gap:10px}

  /* Mobile-Hero-Routing: Full Width, ca. 48px, linksbuendig, KEIN Orange.
     Gilt NUR im Hero — keine globale Full-Width-Buttonregel. */
  .hero .btn-row,.hero-light .btn-row,.hero-dark .btn-row{
    display:grid;grid-template-columns:1fr;gap:10px;margin-top:32px;
  }
  .hero .btn-secondary,.hero-light .btn-secondary,.hero-dark .btn-secondary{
    width:100%;min-height:48px;justify-content:flex-start;padding-inline:16px;
  }
  .hero .btn-secondary,.hero-light .btn-secondary{
    background:rgba(27,95,143,.055);border-color:rgba(27,95,143,.55);color:var(--td-primary);
  }
  .hero .btn-secondary:hover,.hero .btn-secondary:focus-visible,
  .hero-light .btn-secondary:hover,.hero-light .btn-secondary:focus-visible{
    background:rgba(27,95,143,.09);border-color:var(--td-primary);color:var(--td-primary);
    box-shadow:0 0 0 3px rgba(27,95,143,.10);
  }
  .sec-dark .btn-secondary,.hero-dark .btn-secondary{
    background:rgba(255,255,255,.045);border-color:rgba(255,255,255,.42);color:#fff;
  }
  .sec-dark .btn-secondary:hover,.sec-dark .btn-secondary:focus-visible,
  .hero-dark .btn-secondary:hover,.hero-dark .btn-secondary:focus-visible{
    background:rgba(255,255,255,.075);border-color:rgba(255,255,255,.72);color:#fff;
    box-shadow:0 0 0 3px rgba(255,255,255,.08);
  }
  /* Der Textlink steht deutlich hinter den Routing-Flaechen */
  .hero .btn-text,.hero-light .btn-text,.hero-dark .btn-text{
    justify-content:flex-start;margin-top:2px;width:auto;
  }
}

/* Flaches Querformat, NACH den Breakpoint-Bloecken:
   844x420 trifft auch @media(max-width:1023px) — stuende diese Regel weiter
   oben, wuerde der Tablet-Wert sie ueberschreiben und der Hero bliebe hoch. */
@media (orientation:landscape) and (max-height:650px){
  :root{--td-hero-pad:40px}
}

/* ============================================================================
   11. Tabellen & Facts — zwei Muster, beide aus dem Bestand abgeleitet
   ----------------------------------------------------------------------------
   NICHT die Produktmatrix: die ist eine eigene Komponente mit eigenen Regeln
   (Zeilen = Produkte, ganze Zeile klickbar). Hier geht es um Datenblatt und
   Vergleichstabelle — statischer Inhalt, nichts ist auswaehlbar.

   Muster A  .td-facts   Key-Value-Liste, einspaltig, optional gruppiert.
                         Belegt an ThurVDC und ThurVServer.
   Muster B  .td-table   klassische Datentabelle mit Kopf oder Zeilenkopf.
                         Belegt an ThurWeb (Datenblatt + Paketdetails).

   Faustregel: ein Wert je Merkmal -> A. Mehrere Spalten zu vergleichen -> B.
   ============================================================================ */

/* --- A) Facts-Liste ------------------------------------------------------- */
.td-facts{max-width:860px}
.td-fact-group{
  font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--td-subtle);margin:34px 0 4px;      /* Gruppentitel = Metadaten */
}
.td-fact-group:first-child{margin-top:0}
.td-fact{
  display:flex;justify-content:space-between;align-items:baseline;gap:24px;
  padding:12px 0;border-bottom:1px solid var(--td-line);font-size:15px;
}
.td-fact:last-child{border-bottom:0}
.td-fact-label{color:var(--td-muted);font-weight:400}
/* Der Wert ist die Information, nach der jemand sucht — nie zurueckgenommen. */
.td-fact-value{font-weight:700;color:var(--td-dark);text-align:right}
.td-fact-value a{color:var(--td-primary);font-weight:700}
.sec-dark .td-fact{border-bottom-color:rgba(255,255,255,.14)}
.sec-dark .td-fact-label{color:var(--td-dark-muted)}
.sec-dark .td-fact-value{color:#fff}

/* --- B) Datentabelle ------------------------------------------------------ */
/* Breite Tabellen scrollen in ihrem eigenen Container, nie die Seite. */
.td-table-scroll{overflow-x:auto}
/* Der Hinweis darueber wird von ci-2030-components.js eingesetzt — und NUR
   dann, wenn die Tabelle wirklich ueber ihren Kasten hinausragt. Er
   verschwindet, sobald sie einmal bewegt wurde. Die Klasse hier zu haben ist
   Absicht: Das Aussehen gehoert ins CSS, die Messung ins JS.
   Orange wie beim Karussell-Hinweis — es ist derselbe Impuls, und Orange ist
   fuer genau diesen Fall zugelassen. */
.td-scroll-hint{
  display:flex;align-items:center;gap:7px;
  margin:0 0 9px;font-size:13px;color:var(--td-muted);
}
.td-scroll-hint::after{content:"→";color:var(--td-accent);font-weight:700}
.td-table{
  width:100%;border-collapse:collapse;font-size:14.5px;background:#fff;
  border:1px solid var(--td-line-strong);
  /* kein Radius: border-collapse und abgerundete Ecken vertragen sich nicht,
     und eine Tabelle ist keine Karte. */
}
.td-table th,.td-table td{
  padding:11px 16px;border-bottom:1px solid var(--td-line);
  text-align:left;vertical-align:top;
}
.td-table tr:last-child th,.td-table tr:last-child td{border-bottom:0}
/* Zeilenkopf (Merkmal links) */
.td-table tbody th{font-weight:700;color:var(--td-primary);background:rgba(27,95,143,.04)}
/* Spaltenkopf (thead) — dunkel wie die Matrix-Kopfzeile, damit die Seite
   EINE Kopfzeilen-Sprache hat, ohne die Matrixregeln zu erben. */
.td-table thead th{background:var(--td-dark);color:#fff;font-weight:700}
.td-table td{color:var(--td-body)}
/* :not(.btn) ist Pflicht, nicht Kosmetik. `.td-table a` (0,1,1) schlaegt
   `.btn-primary` (0,1,0) — in der Pakettabelle stand deshalb BLAUE Schrift auf
   dem orangen Bestellknopf, waehrend derselbe Knopf in der Auswahlmatrix weiss
   war. Beim Klicken sprang er kurz auf Weiss, weil dort eine andere Regel griff.
   Dritte Kollision dieser Bauart nach der Theme-Unterstreichung und `.label`:
   eine breite Element-Regel faengt eine Komponente ein, die ihre Farbe selbst
   mitbringt. Buttons bleiben ab hier ueberall bei ihrer eigenen Farbe. */
.td-table a:not(.btn){color:var(--td-primary)}
/* Zwei Datenblatt-Tabellen nebeneinander brauchen mehr als die halbe
   Tablet-Breite (an ThurWeb gemessen) — deshalb erst ab Desktop zweispaltig. */
@media (max-width:1023px){
  .td-table-grid{grid-template-columns:1fr}
}

/* --- B2) Pakettabelle: die Datentabelle als Produktvergleich --------------
   BESCHLOSSEN 04.09.2026 (MAEB). Die ausfuehrliche Gegenueberstellung am
   Seitenende: **Merkmale als Zeilen, Pakete als Spalten** — die Umkehrung der
   Auswahlmatrix in S1. Beim Vergleichen liest man ein Merkmal ueber alle
   Pakete, also waagrecht entlang einer Zeile mit Beschriftung am Anfang. Als
   Spalte waere es senkrecht in rund 150px Breite, deren Ueberschrift beim
   Scrollen verschwindet.

   Kein Widerspruch zu «nie Produkte als Spalten»: Diese Regel gilt fuer S1,
   wo die Darstellung auf Mobile stapelbar bleiben muss. Das hier ist die
   separate Detailtabelle auf tieferer Ebene, fuer die der CI den sticky
   Header ausdruecklich erlaubt.

   Ergaenzt .td-table nur um das, was der Produktvergleich zusaetzlich braucht.
   Das Markup bleibt eine echte <table> — semantisch richtig, vorlesbar,
   kopierbar. Grenze: bis 6 Pakete, darueber werden die Spalten zu schmal.
   ---------------------------------------------------------------------- */
.td-pakettabelle{--td-pt-spalten:5}
.td-pakettabelle th,.td-pakettabelle td{text-align:center;vertical-align:middle}
.td-pakettabelle tbody th{text-align:left}
/* Die Produktzeile bleibt beim Scrollen stehen — sonst weiss man nach dem
   fuenften Merkmal nicht mehr, welche Spalte welches Paket ist. */
.td-pakettabelle thead th{position:sticky;top:0;z-index:5}
/* Zebra: bei vielen Merkmalen untereinander verrutscht das Auge sonst. */
.td-pakettabelle tbody tr:nth-child(even) th,
.td-pakettabelle tbody tr:nth-child(even) td{background:#FAFBFC}
.td-pakettabelle tbody tr:nth-child(even) th{background:rgba(27,95,143,.055)}

/* Preiszeile und Bestellzeile rahmen die Merkmale ein: oben der Preis, unten
   die Handlung — dieselbe Reihenfolge wie in der Auswahl. */
.td-pakettabelle .td-pt-preis td{padding-top:14px;padding-bottom:14px;background:#F5F7FA}
.td-pakettabelle .td-pt-preis .td-pt-betrag{font-size:18px;font-weight:900;color:var(--td-dark);
                                            white-space:nowrap;display:block}
.td-pakettabelle .td-pt-preis .td-pt-takt{font-size:11px;color:var(--td-muted);display:block}
.td-pakettabelle .td-pt-cta td{padding:14px 10px}
.td-pakettabelle .td-pt-cta .btn{width:100%;justify-content:center;padding:8px 10px;font-size:13px}

/* Die Empfehlung steht NUR im Spaltenkopf — dieselbe Linie wie Variante A in der
   Auswahlmatrix (MAEB 07.09.2026): die Kennzeichnung traegt der Badge, nicht eine
   Dauereinfaerbung. Zuvor lag ueber der ganzen Spalte ein blauer Ton; zusammen mit
   dem orangen Bestellknopf las sich das wie eine bereits getroffene Vorauswahl,
   und die Zeilen der Spalte hoben sich staerker ab als die Werte, die man
   vergleichen will. Damit faellt der Entscheid vom 04.09. («Spalte durchgehend
   markiert») — er stammte aus der Zeit, als es die Zeilen-Variante noch gab. */
.td-pakettabelle thead .td-pt-empfohlen{background:var(--td-primary)}
.td-pakettabelle thead .td-pt-empfohlen .badge{background:#fff;color:var(--td-primary);
                                               display:inline-block;margin-top:4px}

/* Zeilen-Hover (Variante 1, MAEB 07.09.2026). Die ganze Zeile hebt sich — das
   deckt sich mit der Leserichtung dieser Tabelle: ein Merkmal ueber alle Pakete,
   also waagrecht. Die Spalte waere der Gegenweg und braeuchte ausserdem JS, weil
   CSS keinen Spalten-Selektor kennt; einzelne Zellen helfen beim Vergleichen gar
   nicht. Nur mit echtem Zeiger — auf Touch bliebe der Zustand nach dem Antippen
   kleben, dieselbe Falle wie bei den Kacheln.

   Spezifitaet gegen das Zebra GERECHNET, nicht geschaetzt:
     Zebra   tbody tr:nth-child(even) th = (0,2,3)
     hier    tbody tr:hover th           = (0,2,3)  -> spaeter im Quelltext, gewinnt
   Die Zeile faerbt sich gleichmaessig durch. Seit die Empfehlungsspalte keine
   Dauereinfaerbung mehr hat, gibt es in der Zeile nichts auszunehmen. */
@media (hover:hover) and (pointer:fine){
  .td-pakettabelle tbody tr:hover th,
  .td-pakettabelle tbody tr:hover td{background:rgba(27,95,143,.085)}
}

/* Auf Mobile entfaellt die Tabelle: dort tragen die Swipe-Karten bereits ALLE
   Merkmale im Akkordeon (Entscheid 04.09.2026 «Mobile nie Tabellen»).

   ACHTUNG BEIM BREAKPOINT — hier lag ein Fehler (gefunden 07.09.2026):
   Zuerst stand hier 1023px. Die Auswahl schaltet aber ueber eine
   CONTAINER-Query bei 860px Komponentenbreite um, was rund 920px Viewport
   entspricht. Zwischen 920 und 1023px war damit die MATRIX aktiv — und dort
   ist das Akkordeon ausgeblendet, weil die Details ja in der Tabelle stehen.
   Ergebnis: In diesem Fenster waren die uebrigen Merkmale NIRGENDS erreichbar,
   und der Lead darueber versprach trotzdem "hier stehen sie vollstaendig".

   767px ist der Foundation-Breakpoint fuer Mobile. Dort sind die Karten
   sicher aktiv (Container ~727px < 860px), tragen also alles im Akkordeon.
   Zwischen 767 und 920px stehen Karten UND Tabelle nebeneinander — doppelt,
   aber vollstaendig. Fehlend waere schlimmer als doppelt.

   Der Scroll-Wrapper wird mit ausgeblendet, sonst bleibt ein leerer Kasten
   stehen. Gilt nur fuer die Pakettabelle — andere Datentabellen scrollen
   weiterhin in .td-table-scroll. */
@media(max-width:767px){
  .td-table-scroll:has(.td-pakettabelle){display:none}
  .td-pakettabelle{display:none}
}

/* ----------------------------------------------------------------------------
   11b. Swipe am Rechner - Bildlaufleiste und Greifhand
   Mit dem Finger scrollt das Betriebssystem, die ausgeblendete Leiste stoert
   dort nicht. Mit der Maus fehlt beides: kein Ziehen, keine Leiste - der
   Zustand ist dann unbedienbar, zumal die Karte ein Link ist. Deshalb bekommt
   ein praeziser Zeiger die Leiste zurueck; das Ziehen liefert das Komponenten-JS.
   ---------------------------------------------------------------------------- */
@media (pointer: fine) {
  .product-grid[data-swipe-container],
  .matrix-responsive .mobile-products[data-swipe-container] {
    scrollbar-width: thin;
    scrollbar-color: rgba(15,26,36,.28) transparent;
    cursor: grab;
  }
  .product-grid[data-swipe-container]::-webkit-scrollbar,
  .matrix-responsive .mobile-products[data-swipe-container]::-webkit-scrollbar {
    display: block; height: 8px;
  }
  .product-grid[data-swipe-container]::-webkit-scrollbar-thumb,
  .matrix-responsive .mobile-products[data-swipe-container]::-webkit-scrollbar-thumb {
    background: rgba(15,26,36,.28); border-radius: var(--td-radius-pill);
  }
  .product-grid[data-swipe-container]::-webkit-scrollbar-track,
  .matrix-responsive .mobile-products[data-swipe-container]::-webkit-scrollbar-track {
    background: transparent;
  }
}

/* Waehrend des Ziehens: Greifhand halten, keine Textmarkierung, kein Link-Hover. */
[data-swipe-container].td-zieht { cursor: grabbing; user-select: none; }
[data-swipe-container].td-zieht * { pointer-events: none; }

/* ============================================================================
   12. Lightbox — Aufnahmen gross ansehen
   Standard seit 28.08.2026: jede Aufnahme oeffnet per Klick, mehrere Aufnahmen
   derselben Gruppe lassen sich durchblaettern. Den Dialog baut das
   Komponenten-JS; die Seite markiert nur das Bild mit .td-zoom.
   Vorlaeufer waren die seitenlokalen .lb-* auf der VDC-Entwicklerseite und
   .td-lb auf ThurWeb — zwei Belege, deshalb hier.
   ============================================================================ */
.td-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.td-zoom{cursor:zoom-in}
.td-zoom:focus-visible{outline:2px solid var(--td-accent);outline-offset:4px;border-radius:var(--td-radius-lg)}
button.td-zoom{display:block;width:100%;padding:0;border:0;background:none;text-align:left;font:inherit;color:inherit}
.td-zoom-hint{display:block;margin-top:10px;font-size:13.5px;color:var(--td-muted)}

.td-lb{border:0;padding:0;background:transparent;width:100vw;height:100vh;max-width:100vw;max-height:100vh;overflow:hidden}
.td-lb::backdrop{background:rgba(15,26,36,.88)}
.td-lb .td-lb-fig{
  margin:0;height:100%;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;padding:24px;
  overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;
}
.td-lb .td-lb-img{
  display:block;max-width:94vw;max-height:78vh;width:auto;height:auto;
  border-radius:var(--td-radius);box-shadow:0 24px 60px rgba(0,0,0,.5);background:#fff;
}
/* Videos teilen sich die Buehne mit den Bildern. Das hidden-Attribut braucht
   eine eigene Regel, weil display:block es sonst uebersteuert. */
.td-lb .td-lb-video{
  display:block;max-width:94vw;max-height:78vh;width:auto;height:auto;
  border-radius:var(--td-radius);box-shadow:0 24px 60px rgba(0,0,0,.5);background:#000;
}
.td-lb .td-lb-img[hidden],.td-lb .td-lb-video[hidden]{display:none}
.td-lb .td-lb-cap{max-width:760px;text-align:center;font-size:15px;line-height:1.6;color:rgba(255,255,255,.82)}
.td-lb .td-lb-cap b,.td-lb .td-lb-cap strong{color:#fff;font-weight:600}
.td-lb .td-lb-hint,.td-lb .td-lb-count{font-size:13px;color:rgba(255,255,255,.6);letter-spacing:.06em}
.td-lb .td-lb-btn{
  position:fixed;z-index:2;width:44px;height:44px;border-radius:var(--td-radius-pill);
  border:1px solid rgba(255,255,255,.4);background:rgba(15,26,36,.6);color:#fff;
  font-size:24px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;
  transition:background var(--td-transition),border-color var(--td-transition);
}
.td-lb .td-lb-btn:hover{background:rgba(15,26,36,.9);border-color:#fff}
.td-lb .td-lb-btn:focus-visible{outline:2px solid #fff;outline-offset:2px}
.td-lb .td-lb-close{top:20px;right:20px}
.td-lb .td-lb-prev{left:20px;top:50%;transform:translateY(-50%)}
.td-lb .td-lb-next{right:20px;top:50%;transform:translateY(-50%)}
/* Eine einzelne Aufnahme braucht weder Pfeile noch Zaehler. */
.td-lb.td-lb-einzeln .td-lb-prev,
.td-lb.td-lb-einzeln .td-lb-next,
.td-lb.td-lb-einzeln .td-lb-count{display:none}

/* Originalgroesse: die Figur wird zum Scrollrahmen. Ohne das ist die
   Grossansicht auf dem Handy wirkungslos — 367px statt 335px im Fliesstext. */
.td-lb.kann-zoomen .td-lb-img{cursor:zoom-in}
.td-lb.ist-gezoomt .td-lb-fig{align-items:flex-start;justify-content:flex-start}
.td-lb.ist-gezoomt .td-lb-img{max-width:none;max-height:none;cursor:zoom-out}
.td-lb.ist-gezoomt .td-lb-cap,
.td-lb.ist-gezoomt .td-lb-hint,
.td-lb.ist-gezoomt .td-lb-count{display:none}
.td-lb:not(.kann-zoomen) .td-lb-hint{display:none}

@media (max-width:1023px){
  .td-lb .td-lb-img{max-height:70vh}
  .td-lb .td-lb-close{top:10px;right:10px}
  .td-lb .td-lb-prev{left:8px}
  .td-lb .td-lb-next{right:8px}
}
/* Flache Viewports: die Bildunterschrift weicht dem Bild. */
@media (orientation:landscape) and (max-height:650px){
  .td-lb .td-lb-img{max-height:84vh}
  .td-lb .td-lb-cap{display:none}
}

/* ============================================================================
   12b. PRODUKTLISTE — ein Markup, zwei Darstellungen
   ----------------------------------------------------------------------------
   Beschlossen ANEB + MAEB 04.09.2026, am Geraet geprueft.

   Ersetzt mittelfristig .product-tile / .product-matrix aus Abschnitt 8. Beide
   Systeme stehen bewusst nebeneinander, bis die Seiten migriert sind:
   ThurBuilder, ThurCloud und ThurWeb laufen heute auf dem alten Markup.
   NICHT beide auf derselben Seite mischen.

   Das Modell:

     | Produkte | breit                  | schmal                    |
     |----------|------------------------|---------------------------|
     | bis 3    | Kacheln nebeneinander  | Kacheln gestapelt         |
     | ab 4     | Zeilenmatrix           | Swipe-Bahn                |

   Es gibt genau EIN Markup. Die Umschaltung passiert ausschliesslich per
   Container-Query — kein zweites Markup, keine doppelt gepflegten Zahlen.
   Der Wrapper .pl-wrap traegt container-type und die Modusklasse, gestylt
   wird .pl: eine Container-Query kann den Container SELBST nicht stylen,
   nur seine Nachfahren.

   Aufbau eines Eintrags (DOM-Reihenfolge folgt der Matrix):
     .pl-item > .pl-kopf · .pl-fakten (4 Merkmale) · .pl-preis ·
                .pl-mehr (details, alle uebrigen Merkmale) · .pl-cta
   In der Kachelform zieht `order` den Preis nach oben — ein Markup,
   zwei Leserichtungen.

   Verhalten aus ci-2030-components.js: gemeinsames Aufklappen, Position
   in der Swipe-Bahn, Tap-vs-Swipe.
   ============================================================================ */

/* --pl-spalten ist das Spaltenraster der Zeilenmatrix. Der Standardwert ist das
   an ThurWeb gemessene Raster: Paketname, vier Merkmale, Preis, feste
   Aktionsspalte. Eine Seite mit weniger Merkmalen ueberschreibt die Variable auf
   ihrem eigenen Wrapper — ThurCloud hat nur ein unterscheidendes Merkmal
   (Speicher) und braucht deshalb vier Spalten statt sieben. Ohne die Variable
   muesste jede solche Seite den kompletten Matrix-Regelsatz kopieren. */
.pl-wrap{container-type:inline-size;container-name:pl;
         --pl-spalten:1.5fr .78fr .95fr .68fr .78fr .92fr 132px}
.pl{display:grid;gap:18px;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));
    align-items:start}
.pl-matrixkopf{display:none}

.pl-item{
  display:flex;flex-direction:column;min-width:0;position:relative;
  background:#fff;border:1px solid var(--td-line-strong);border-radius:var(--td-radius-lg);
  overflow:hidden;transition:border-color var(--td-transition),box-shadow var(--td-transition);
}
/* Hover = Umrandung, nur mit echtem Zeiger. Auf Touch bliebe er sonst kleben. */
@media (hover:hover) and (pointer:fine){
  .pl-item:hover{border-color:var(--td-accent);box-shadow:inset 0 0 0 1px var(--td-accent)}
  .pl-item.empfohlen:hover{border-color:var(--td-accent)}
}
.pl-item:focus-within{border-color:var(--td-accent);box-shadow:inset 0 0 0 1px var(--td-accent)}
.pl-item.empfohlen{border-color:rgba(27,95,143,.52)}
.pl-item.empfohlen::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;
  background:var(--td-primary);z-index:2}

/* Leseführung in der Kachel: Kopf, Preis, Merkmale, Akkordeon, Knopf */
.pl-kopf{order:1}
.pl-preis{order:2}
.pl-fakten{order:3}
.pl-mehr{order:4}
.pl-cta{order:5}

.pl-kopf{padding:21px 22px 17px;background:var(--td-dark);color:#fff}
/* Badge NEBEN dem Namen, nie darunter: sonst waechst der Kopf einer Kachel und
   alle folgenden Zeilen fluchten nicht mehr mit den Nachbarkacheln. Deshalb ist
   der Text kurz ("Topseller") und der Umbruch unterbunden. */
.pl-name{font-size:19px;font-weight:700;display:flex;align-items:center;
         justify-content:space-between;gap:10px;flex-wrap:nowrap;min-width:0}
.pl-name .badge{background:#fff;color:var(--td-primary);font-size:11px;flex:0 0 auto;
                white-space:nowrap}
/* Claim-Hoehe reservieren, damit unterschiedlich lange Claims die Zeilen nicht
   verschieben. equalizeTileHeads in ci-2030-components.js macht das genauer. */
.pl-claim{font-size:14px;color:rgba(255,255,255,.72);margin-top:6px;min-height:2.9em}

.pl-preis{padding:17px 22px 14px;border-bottom:1px solid var(--td-line);
          display:flex;flex-direction:column}
.pl-betrag{font-size:28px;font-weight:900;color:var(--td-dark);letter-spacing:-.025em;
           line-height:1.05}
.pl-takt{font-size:13px;color:var(--td-muted);margin-top:4px}
.pl-setup{font-size:12.5px;color:var(--td-body);margin-top:7px}

.pl-fakten{display:flex;flex-direction:column;border-top:1px solid var(--td-line)}
.pl-fakt{display:flex;align-items:baseline;justify-content:space-between;gap:18px;
         padding:11px 22px;border-bottom:1px solid var(--td-line);font-size:14px}
.pl-label{color:var(--td-muted)}
.pl-wert{font-weight:700;color:var(--td-dark);text-align:right}

/* --- Akkordeon: traegt ALLE uebrigen Merkmale ---------------------------
   Bewusst nativ per <details>: funktioniert ohne JavaScript. Das gemeinsame
   Aufklappen kommt aus components.js und ist eine Zutat, keine Bedingung. */
.pl-mehr{border-bottom:1px solid var(--td-line)}
.pl-mehr > summary{list-style:none;cursor:pointer;padding:13px 22px;min-height:44px;
  font-size:14px;font-weight:700;color:var(--td-primary);
  display:flex;align-items:center;justify-content:space-between;gap:12px}
.pl-mehr > summary::-webkit-details-marker{display:none}
/* Plus und Minus erben Farbe, Groesse und Schnitt vom Text daneben.
   U+2212 ist das echte Minuszeichen, nicht der kuerzere Gedankenstrich. */
.pl-mehr > summary::after{content:"+";font-size:inherit;font-weight:inherit;color:inherit;
                          line-height:1;width:1em;text-align:center}
.pl-mehr[open] > summary::after{content:"\2212"}
@media (hover:hover) and (pointer:fine){
  .pl-mehr > summary:hover{color:var(--td-accent)}
}
.pl-mehr > summary:focus-visible{box-shadow:var(--td-focus-ring);border-radius:var(--td-radius-sm)}
.pl-mehr-inhalt .pl-fakt:last-child{border-bottom:0}

/* --- Bestellknopf in jeder Kachel ---------------------------------------
   Abweichung vom fruehen CI-Entscheid "ganze Kachel klickbar, kein Button
   darin" (MAEB 04.09.2026): Beim Wischen auf dem Handy loeste die klickbare
   Flaeche ungewollt den Bestellprozess aus. Nur der Knopf reagiert. */
.pl-cta{padding:16px 22px 20px;margin-top:auto}
.pl-cta .btn{width:100%;justify-content:center}
.pl-cta .hint{display:block;margin-top:9px;font-size:12.5px;color:var(--td-subtle);
              text-align:center}

/* ---------------------------------------------- ab 860px: ZEILENMATRIX --
   Gilt nur fuer .modus-auto (4+ Produkte). Bis 3 Produkte bleibt es in jeder
   Breite bei Kacheln. */
@container pl (min-width:860px){
  .modus-auto .pl{display:block;background:#fff;border:1px solid var(--td-line-strong);
                  border-radius:var(--td-radius-lg);overflow:hidden}

  /* Die Aktionsspalte hat eine FESTE Breite. Mit `auto` richtet sie sich nach
     ihrem Inhalt — und weil jede Zeile ein eigenes Grid ist, bekommt dann jede
     Zeile andere Spaltenbreiten. An ThurWeb gemessen (07.09.2026): Kopf und
     Zeilen liefen um bis zu 56px auseinander, die Knoepfe waren 180-213px
     breit. Deshalb feste Breite und ein kurzer, fuer alle gleicher Knopftext;
     das Produkt steht im aria-label. */
  .modus-auto .pl-matrixkopf,
  .modus-auto .pl-item{
    display:grid;
    grid-template-columns:var(--pl-spalten);
    align-items:center;column-gap:14px;
  }
  .modus-auto .pl-matrixkopf{background:var(--td-dark);color:#fff;min-height:54px;
                             padding:0 22px;font-size:13px;font-weight:700}
  .modus-auto .pl-item{border:0;border-top:1px solid var(--td-line);border-radius:0;
                       padding:12px 22px;min-height:78px;box-shadow:none}
  .modus-auto .pl-item:first-of-type{border-top:0}
  /* In der Matrix gilt wieder die DOM-Reihenfolge */
  .modus-auto .pl-kopf,.modus-auto .pl-preis,.modus-auto .pl-fakten,
  .modus-auto .pl-fakt,.modus-auto .pl-mehr,.modus-auto .pl-cta{order:0}
  @media (hover:hover) and (pointer:fine){
    .modus-auto .pl-item:hover{box-shadow:inset 0 0 0 1.5px var(--td-accent);
                               border-color:var(--td-line)}
  }
  /* Variante A (MAEB 07.09.2026): Hintergrund weg, Balken bleibt. Die
     empfohlene Zeile soll sich wie die uebrigen vier lesen — die Empfehlung
     traegt der Badge, der Balken haelt sie beim Ueberfliegen auffindbar.
     Variante B (auch der Balken weg) war zu leise, C (Balken nur bei Hover)
     verschenkt die Marke genau beim Ueberfliegen, wo sie wirken soll.

     Die Hover-Regel darueber hat dieselbe Spezifitaet (0,3,0) und steht frueher
     im Quelltext — .empfohlen schlaegt sie also und loescht den Rahmen. Solange
     der Hintergrund da war, fiel das nicht auf; ohne ihn waere die empfohlene
     Zeile die einzige, die auf den Zeiger gar nicht reagiert. Deshalb hier
     beide Schatten zusammen: Balken UND Rahmen. */
  .modus-auto .pl-item.empfohlen{box-shadow:inset 3px 0 0 var(--td-primary)}
  @media (hover:hover) and (pointer:fine){
    .modus-auto .pl-item.empfohlen:hover{
      box-shadow:inset 3px 0 0 var(--td-primary),inset 0 0 0 1.5px var(--td-accent);
      border-color:var(--td-line)}
  }
  .modus-auto .pl-item.empfohlen::before{display:none}

  .modus-auto .pl-kopf{background:transparent;color:inherit;padding:0}
  .modus-auto .pl-name{font-size:15.5px;font-weight:800;color:var(--td-dark);
                       display:flex;justify-content:flex-start;gap:8px}
  .modus-auto .pl-name .badge{border:1px solid rgba(27,95,143,.3)}
  .modus-auto .pl-claim{color:var(--td-muted);font-size:12px;margin-top:2px;min-height:0}

  /* Die vier Merkmale werden zu Spalten — Beschriftung traegt der Kopf.
     Werte UND Ueberschriften zentriert, sonst fluchten sie bei
     unterschiedlich langen Werten nicht. */
  .modus-auto .pl-fakten{display:contents}
  .modus-auto .pl-fakt{display:block;padding:0;border:0;font-size:15px;text-align:center}
  .modus-auto .pl-label{display:none}
  .modus-auto .pl-wert{text-align:center;font-weight:700;display:block}
  /* Alle Spalten ausser Paketname und Aktionsspalte zentriert — auch der Preis.
     Vorher stand die Ueberschrift "Preis" zentriert und der Betrag darunter
     rechtsbuendig: Die zentrierende Regel hat wegen der beiden :not() mehr
     Gewicht und schlug die rechtsbuendige (MAEB 07.09.2026 auf Devel gesehen).
     Statt die Spezifitaeten gegeneinander hochzuziehen, ist der Preis jetzt
     wie jede andere Spalte zentriert — Ueberschrift und Wert fluchten. */
  .modus-auto .pl-matrixkopf > div:not(:first-child):not(:last-child){text-align:center}

  .modus-auto .pl-preis{padding:0;border:0;text-align:center;align-items:center}
  .modus-auto .pl-betrag{font-size:17px;font-weight:800;white-space:nowrap}
  .modus-auto .pl-takt{font-size:11px}
  .modus-auto .pl-setup{display:none}

  /* In der Matrix kein Akkordeon — die Details stehen in der Quermatrix */
  .modus-auto .pl-mehr{display:none}

  .modus-auto .pl-cta{padding:0;margin:0}
  .modus-auto .pl-cta .btn{width:100%;justify-content:center;padding:9px 12px;
                           font-size:13.5px;white-space:nowrap}
}

/* -------------------------------------------- unter 860px: SWIPE-BAHN --
   Nur bei 4+ Produkten (.modus-auto). Bis 3 Pakete bleibt es gestapelt:
   dort ist die Seite kurz genug, und man scrollt ohnehin an allen vorbei.
   Am Geraet geprueft 04.09.2026 — Wischen, Akkordeon und Zurueckwischen
   funktionieren zusammen. */
@container pl (max-width:859px){
  /* grid-template-columns MUSS zurueckgesetzt werden: sonst landet die erste
     Karte in der 1fr-Spalte der Kachelform und wird schmaler als alle
     anderen (gemessen 04.09.2026: Kopf 227px statt 113px). */
  .modus-auto .pl{
    grid-template-columns:none;grid-auto-flow:column;grid-auto-columns:82%;gap:14px;
    overflow-x:auto;scroll-snap-type:x mandatory;padding:2px 2px 12px;
    overscroll-behavior-x:contain;scrollbar-color:var(--td-line-strong) transparent;
  }
  .modus-auto .pl > .pl-item{scroll-snap-align:center}
  .modus-auto .pl::-webkit-scrollbar{height:8px}
  .modus-auto .pl::-webkit-scrollbar-thumb{background:var(--td-line-strong);border-radius:999px}
  .modus-auto .pl::-webkit-scrollbar-track{background:transparent}

  /* Feste Zeilenhoehen: NUR so stehen die Merkmale auf allen Karten gleich
     hoch. Sonst verrutscht die Zeile beim Wischen und der Vergleich ist
     dahin — der ganze Zweck der Bahn. Gemessen: 0px Abweichung ueber alle
     Karten und Zeilen. */
  .modus-auto .pl-fakt{min-height:46px}
  .modus-auto .pl-wert{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .modus-auto .pl-mehr > summary{min-height:46px}
  .modus-auto .pl-preis{min-height:96px}
  .modus-auto .pl-kopf{min-height:104px}
  .modus-auto .pl-cta{min-height:76px}
}

/* --- Kennzeichnung der Bahn: ohne sie sieht niemand, dass es weitergeht --- */
.pl-swipekopf{display:none;align-items:baseline;gap:10px;margin-bottom:9px;padding:0 2px}
.pl-swipezahl{font-weight:800;font-size:14.5px;color:var(--td-dark)}
.pl-swipehinweis{font-size:13px;color:var(--td-muted)}
.pl-swipepos{font-size:13px;color:var(--td-muted);margin-left:auto;
             font-variant-numeric:tabular-nums}
.pl-punkte{display:none;gap:6px;justify-content:center;margin-top:2px}
.pl-punkte i{width:20px;height:4px;border-radius:999px;background:var(--td-line-strong);
             transition:background var(--td-transition)}
.pl-punkte i.aktiv{background:var(--td-accent)}
@container pl (max-width:859px){
  .modus-auto .pl-swipekopf{display:flex}
  .modus-auto .pl-punkte{display:flex}
}

/* ============================================================================
   13. Formulare — BESCHLOSSEN 17.09.2026 (ROKA), erster realer Fall: Domaincheck
   ----------------------------------------------------------------------------
   Bis hierher stand an dieser Stelle «OFFEN — bewusst nicht gestaltet». Der
   Tool-Hero der Domain-Seite brauchte das erste echte Formularfeld; daran ist
   das Muster entstanden und gemessen worden (Desktop 1440, Mobile 375).

   Grundsaetze — aus dem CI abgeleitet, nichts Neues erfunden:
     * Ein Feld ist RUHE, kein Impuls. Deshalb blaue Familie fuer Fokus und
       Auswahl (Primary = Status), NIE Orange am Feld: Orange bleibt dem
       Knopf daneben vorbehalten. Zwei orange Rahmen nebeneinander (Feld im
       Fokus + Knopf) wuerden um dieselbe Aufmerksamkeit konkurrieren.
     * Feldhoehe = Knopfhoehe. Standard 44 px wie .btn, gross 52 px wie der
       Hero-Domaincheck. Ein Feld und sein Knopf stehen auf einer Linie.
     * Radius --td-radius-sm (6 px) wie Buttons — kleine UI, keine Karte.
     * Schrift 15 px im Feld, 16 px mobil (unter 16 px zoomt iOS beim Tippen
       in die Seite hinein).
     * Beschriftung 14 px / 700 --td-body: sichtbar, nicht laut. Kein
       Platzhalter als Ersatz fuer die Beschriftung — er verschwindet beim
       Tippen. Im Hero-Werkzeug darf die Beschriftung unsichtbar sein
       (.td-sr), weil die H1 darueber die Aufgabe erklaert.
     * Fehler sind die einzige zusaetzliche Farbe (--td-error). Sie erscheinen
       am Feld UND als Satz darunter — Farbe allein reicht nicht (WCAG 1.4.1).
     * Ankreuzfelder ueber accent-color in Primary: das native Element bleibt,
       nichts wird nachgebaut. Bedienbar, vorlesbar, 18 px gross.
     * Auf dunklem Grund bleibt das Feld weiss — Kontrast der Eingabe geht vor
       Stimmung. Beschriftung und Hilfetext wechseln auf die Dunkel-Textfarben.

   Klassen:
     .td-field            Beschriftung + Feld + Hilfe/Fehler, senkrecht
     .td-field--error     Fehlerzustand (Rahmen + .td-error-text sichtbar)
     .td-help             Hilfetext unter dem Feld (13 px, --td-muted)
     .td-error-text       Fehlersatz (13 px, --td-error)
     .td-input-group      Feld und Knopf in EINER Zeile (Suche, Domaincheck,
                          Newsletter); mobil gestapelt
     .td-input-group--lg  52 px hoch — fuer den Tool-Hero
     .td-check            Zeile aus Ankreuzfeld/Radio und Text
     .td-form-grid        zwei Felder nebeneinander, mobil untereinander
     .td-form-actions     Knopfzeile am Formularende (= .btn-row)
     .td-sr               nur fuer Screenreader (Beschriftung unsichtbar)
   ============================================================================ */

:root{
  --td-error:   #B3261E;   /* einzige zusaetzliche Farbe: Fehler am Feld    */
  --td-success: #3FA66A;   /* Bestaetigung; identisch mit dem Hero-Trust-Punkt */
  --td-field-h:    44px;
  --td-field-h-lg: 52px;
  --td-field-ring: 0 0 0 3px rgba(27,95,143,.14);   /* blau, nie orange */
}

/* --- Grundelemente ------------------------------------------------------- */
/* Aussehen gilt NUR in unseren Formularkontexten (.td-form, .td-field, .td-input-group,
   .td-check) — nicht global. Grund (homepage#81, 24.09.2026): Element-Regeln ohne Klasse
   trafen fremde Komponenten im selben DOM (Beiz-Chat-Textarea 128 px hoch, Bunki musste mit
   !important dagegenhalten) und WHMCS-Formulare. :where() im Scope haelt die Spezifitaet
   unveraendert. Die LAYOUT-Eigenschaften display/width haengen wie bisher an .td-field und
   .td-input-group — Croster hat im Kopf eigene Felder (Suche, Waehrung). */
/* :where() haelt die Spezifitaet bei (0,0,1) — sonst schlaegt die :not-Kette
   (0,4,1) spaeter jeden Zustand wie :disabled oder .td-field--error. */
:where(.td-form,.td-field,.td-input-group,.td-check) :is(input:where(:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"])),select,textarea){
  font-family:inherit;font-size:15px;line-height:1.3;color:var(--td-text);
  background:#fff;border:1px solid var(--td-line-strong);border-radius:var(--td-radius-sm);
  min-height:var(--td-field-h);padding:0 14px;margin:0;
  -webkit-appearance:none;appearance:none;
  transition:border-color var(--td-transition),box-shadow var(--td-transition);
}
:where(.td-form,.td-field,.td-input-group,.td-check) textarea{min-height:128px;padding:11px 14px;resize:vertical;line-height:1.5}
:where(.td-form,.td-field,.td-input-group,.td-check) select{
  padding-right:40px;cursor:pointer;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23526173' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
  background-repeat:no-repeat;background-position:right 12px center;background-size:18px;
}
:where(.td-form,.td-field,.td-input-group,.td-check) select[multiple]{padding:8px 14px;background-image:none;min-height:auto}
:where(.td-form,.td-field,.td-input-group,.td-check) ::placeholder{color:var(--td-subtle);opacity:1}

@media (hover:hover){
  :where(.td-form,.td-field,.td-input-group,.td-check) :is(input:where(:not([type="checkbox"]):not([type="radio"])),select,textarea):hover{
    border-color:#A9B8C6;
  }
}
:where(.td-form,.td-field,.td-input-group,.td-check) :is(input,select,textarea):focus{
  outline:none;border-color:var(--td-primary);box-shadow:var(--td-field-ring);
}
:where(.td-form,.td-field,.td-input-group,.td-check) :is(input,select,textarea):disabled{
  background:var(--td-light);color:var(--td-subtle);cursor:not-allowed;border-color:var(--td-line);
}
:where(.td-form,.td-field,.td-input-group,.td-check) input[readonly]:where(:not([type="checkbox"]):not([type="radio"])){background:var(--td-light)}
@media (max-width:767px){
  :where(.td-form,.td-field,.td-input-group,.td-check) :is(input:where(:not([type="checkbox"]):not([type="radio"])),select,textarea){font-size:16px}
}

/* --- Beschriftung, Hilfe, Fehler ----------------------------------------- */
:where(.td-form,.td-field,.td-input-group,.td-check) label{font-size:14px;font-weight:700;color:var(--td-body);line-height:1.35}
.td-field>label{display:block}
:where(.td-form,.td-field,.td-input-group,.td-check) fieldset{border:0;padding:0;margin:0;min-width:0}
legend{padding:0;font-size:16px;font-weight:700;color:var(--td-text);margin-bottom:12px}

.td-field{display:flex;flex-direction:column;gap:6px;margin:0 0 18px}
.td-field>input,.td-field>select,.td-field>textarea,
.td-input-group>input,.td-input-group>select{display:block;width:100%}
.td-field:last-child{margin-bottom:0}
.td-field>label .td-optional{font-weight:400;color:var(--td-subtle);margin-left:.35em}
.td-help{font-size:13px;line-height:1.45;color:var(--td-muted);margin:0}
.td-error-text{display:none;font-size:13px;line-height:1.45;color:var(--td-error);font-weight:500;margin:0}
.td-field--error input,.td-field--error select,.td-field--error textarea{border-color:var(--td-error)}
.td-field--error input:focus,.td-field--error select:focus,.td-field--error textarea:focus{
  border-color:var(--td-error);box-shadow:0 0 0 3px rgba(179,38,30,.14);
}
.td-field--error .td-error-text{display:block}
.td-field--error>label{color:var(--td-error)}

/* --- Ankreuzfeld und Radio: nativ, in Primary ------------------------------ */
:where(.td-form,.td-field,.td-input-group,.td-check) :is(input[type="checkbox"],input[type="radio"]){
  width:18px;height:18px;margin:0;accent-color:var(--td-primary);cursor:pointer;flex:none;
}
:where(.td-form,.td-field,.td-input-group,.td-check) :is(input[type="checkbox"],input[type="radio"]):focus-visible{
  outline:none;box-shadow:var(--td-field-ring);border-radius:3px;
}
:where(.td-form,.td-field,.td-input-group,.td-check) input[type="radio"]:focus-visible{border-radius:50%}
.td-check{display:flex;align-items:flex-start;gap:10px;font-size:15px;font-weight:400;
          color:var(--td-body);cursor:pointer;margin:0 0 10px}
.td-check:last-child{margin-bottom:0}
.td-check input{margin-top:2px}
/* Der Text steht in EINEM <span> — als lose Textknoten wuerde jeder Link im
   Satz zum eigenen Flex-Element mit 10 px Luft davor und danach. */
.td-check>span{flex:1 1 auto}
.td-check a{color:var(--td-primary)}

/* --- Feld + Knopf in einer Zeile ------------------------------------------ */
.td-input-group{display:flex;gap:10px;align-items:stretch}
.td-input-group>input{flex:1 1 auto;min-width:0}
.td-input-group>.btn{flex:0 0 auto;white-space:nowrap;min-height:var(--td-field-h)}
.td-input-group--lg>input{min-height:var(--td-field-h-lg);font-size:17px;padding:0 16px}
.td-input-group--lg>.btn{min-height:var(--td-field-h-lg);padding:0 22px}
@media (max-width:767px){
  .td-input-group{flex-direction:column;gap:8px}
  .td-input-group>.btn{width:100%}
  .td-input-group--lg>input{min-height:48px;font-size:16px}
  .td-input-group--lg>.btn{min-height:48px}
}

/* --- Formular-Layout ------------------------------------------------------ */
.td-form{max-width:640px}
.td-form-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 20px}
/* Im Raster behaelt auch das letzte Feld seinen Abstand — gestapelt (mobil) klebte es
   sonst am naechsten Feld (an der Ticket-Maske gesehen, 17.09.2026). */
.td-form-grid>.td-field:last-child{margin-bottom:18px}
@media (max-width:767px){.td-form-grid{grid-template-columns:1fr}}
.td-form-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center;margin-top:24px}
.td-form-note{font-size:13px;color:var(--td-muted);margin:14px 0 0}

/* Nur fuer Screenreader — Beschriftung bleibt im Baum, nicht auf dem Bild */
.td-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:-1px}

/* --- Auf dunklem Grund ---------------------------------------------------- */
.sec-dark label,.hero-dark label{color:#fff}
.sec-dark .td-help,.hero-dark .td-help{color:var(--td-dark-muted)}
.sec-dark .td-check,.hero-dark .td-check{color:var(--td-dark-text)}
.sec-dark input:where(:not([type="checkbox"]):not([type="radio"])),.hero-dark input:where(:not([type="checkbox"]):not([type="radio"])),
.sec-dark select,.hero-dark select,.sec-dark textarea,.hero-dark textarea{
  border-color:transparent;   /* weisses Feld auf Dunkel braucht keinen Rand */
}
.sec-dark input:focus,.hero-dark input:focus,.sec-dark select:focus,.hero-dark select:focus,
.sec-dark textarea:focus,.hero-dark textarea:focus{
  border-color:transparent;box-shadow:0 0 0 3px rgba(255,255,255,.35);
}
.sec-dark .td-error-text,.hero-dark .td-error-text{color:#FF8A7A}
.sec-dark .td-field--error>label,.hero-dark .td-field--error>label{color:#FF8A7A}

/* Reduzierte Bewegung respektieren */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;transition-duration:.01ms !important}
}


/* ============================================================================
   14. Dokumentseiten — Vertragstext mit mitlaufendem Inhaltsverzeichnis
   ----------------------------------------------------------------------------
   Realer Fall: AGB, Impressum, Datenschutz, Verhaltenskodex Domains und die
   SLA-Bedingungen. Bis 22.09.2026 lag dasselbe Geruest viermal seitenlokal,
   mit zwei Fehlern in allen vier Kopien: der Druck quetschte den Text in die
   260-px-Spalte, und das Verzeichnis blieb zu, wenn das Fenster nach dem Laden
   wuchs. Beide sind hier behoben.

   Die Komponente umschliesst NICHT die ganze Seite — sie steht in der Sektion,
   die den Dokumentteil traegt; Hero, Matrix und CTA bleiben voll breit.

   Markup:
     .td-doc-layout            Grid, traegt .td-container
       nav.td-doc-toc            Verzeichnis, sticky
         details.td-doc-toc-box    Aufklappen auf schmalen Geraeten
       .td-doc-content           rechte Spalte als EIN Grid-Item
         .td-doc-kopf              optionaler Dokumentkopf
         article.td-doc-text       der Dokumenttext

   Die Ziffer steht IM Ueberschriftentext (<h2 id="x-1">1. Titel</h2>) — der
   Vertragstext verweist auf sich selbst, und beim Zitieren muss sie mitgehen.
   Der CSS-Zaehler nummeriert ausschliesslich das Verzeichnis.

   Verhalten (Aufklappen, Breitenwechsel): ci-2030-components.js -> docToc().
   Entscheide und Messwerte: content/entscheidungen/doc-layout-komponente-vorschlag-2026-09-22.md
   ============================================================================ */

:root{
  /* Hoehe der Kopfleiste. ai-navbar.css fuehrt --bar-h (60 px, ab 767 px 56 px).
     Der Fallback traegt Seiten ohne Navbar (Mockups, Standalone-Vorschau) und
     muss dort SELBST umschalten — sonst rechnet die Komponente auf dem Handy
     mit 60 statt 56 px weiter (gemessen: 84 statt 80 px Ankerversatz). */
  --td-header-h:   var(--bar-h, 60px);
  --td-doc-offset: calc(var(--td-header-h) + var(--td-space-4));
  --td-doc-toc-w:  260px;
}
@media (max-width:767px){
  :root{ --td-header-h: var(--bar-h, 56px); }
}

/* ---- Grid ---------------------------------------------------------------- */
.td-doc-layout{
  display:grid;
  grid-template-columns:var(--td-doc-toc-w) minmax(0,1fr);
  gap:var(--td-space-7);
  align-items:start;
}
/* Die rechte Spalte ist EIN Grid-Item; Kopf und Text liegen darin.
   Nicht beide einzeln ins Grid haengen: ein Verzeichnis, das ueber zwei
   auto-Zeilen spannt, blaeht die erste Zeile auf ihre halbe Hoehe auf und
   reisst ein Loch zwischen Kopf und erster Ziffer (gemessen: ~490 px). */
/* min-width:0 an BEIDEN Stellen: einspaltig loest display:contents den
   Wrapper auf, und dann braucht der Text den Schutz selbst — ohne ihn
   sprengen breite Tabellen die Spalte (gemessen: 539 px Dokument bei
   375 px Viewport). */
.td-doc-content,.td-doc-text,.td-doc-kopf{min-width:0}

/* Dokumentkopf (Titel, Fassung, Lead) — OPTIONAL, nur wenn der Dokumentteil
   eine eigene Ueberschrift traegt; bei den Legal-Seiten macht das der Hero.
   Er liegt in der Textspalte und flieht damit mit dem Text, den er
   ueberschreibt. Ueber die ganze Breite gesetzt flieht er stattdessen mit dem
   Verzeichnis, und der Block liest sich als «Titel gehoert zum Verzeichnis». */
.td-doc-kopf{max-width:74ch;margin:0 0 var(--td-space-6)}
.td-doc-kopf > :last-child{margin-bottom:0}

/* ---- Inhaltsverzeichnis -------------------------------------------------- */
.td-doc-toc{
  position:sticky;
  top:var(--td-doc-offset);
  max-height:calc(100vh - var(--td-doc-offset) - var(--td-space-4));
  overflow-y:auto;
  overscroll-behavior:contain;
  /* Platz fuer den Fokusring, der sonst am Scrollrand abgeschnitten wuerde. */
  padding-inline:3px;
  margin-inline:-3px;
}
.td-doc-toc-box summary{list-style:none;cursor:default}
.td-doc-toc-box summary::-webkit-details-marker{display:none}
.td-doc-toc-box summary .td-kicker{margin-bottom:0}
/* Am Desktop steht die Liste offen darunter — die Nutzenzeile erklaert dort
   nichts, was man nicht schon sieht. */
.td-doc-toc-nutzen{display:none}

.td-doc-toc ol{margin:var(--td-space-3) 0 0;padding:0;list-style:none;counter-reset:tddoc}
.td-doc-toc li{counter-increment:tddoc;border-top:1px solid var(--td-line)}
.td-doc-toc li:last-child{border-bottom:1px solid var(--td-line)}
.td-doc-toc li a{
  display:grid;grid-template-columns:28px 1fr;gap:6px;
  padding:9px 0;
  font-size:14px;line-height:1.35;
  color:var(--td-body);text-decoration:none;
}
/* Nur die LISTENeintraege nummerieren. Seit 23.09.2026 traegt die Leiste
   darunter einen PDF-Link statt eines Knopfes — eine Regel auf alle <a>
   im Verzeichnis hing ihm den Zaehlerstand an, er hiess «12. Bedingungen
   als PDF». Als <button> war das nie aufgefallen. */
.td-doc-toc li a::before{content:counter(tddoc) ".";font-weight:700;color:var(--td-primary)}
@media (hover:hover) and (pointer:fine){
  .td-doc-toc li a:hover{color:var(--td-primary)}
}
/* Werkzeugleiste unter dem Verzeichnis (PDF-Link, frueher ein Druckknopf).
   Im Druck selbst hat sie nichts verloren — sie ist die Bedienung, nicht das
   Dokument. */
.td-doc-aktion{margin-top:var(--td-space-4)}

/* ---- Dokumenttypografie -------------------------------------------------- */
/* Die Lesebreite gilt dem FLIESSTEXT, nicht dem Dokument. Laege sie auf dem
   Container, muesste jede Tabelle darin scrollen, auch wenn daneben Platz
   frei ist — gemessen 22.09.2026 an den SLA-Bedingungen: die Support-Level-
   Matrix braucht 760 px und bekam in der 74ch-Spalte nur 665. */
.td-doc-text{max-width:none;color:var(--td-body)}
.td-doc-text > :is(p,ul,ol,dl,h2,h3,h4,blockquote){max-width:74ch}
.td-doc-text h2{font-size:28px;line-height:1.15;margin:0 0 var(--td-space-3);padding-top:12px}
.td-doc-text h2:not(:first-child){
  margin-top:40px;border-top:1px solid var(--td-line);padding-top:var(--td-space-5);
}
.td-doc-text h3{font-size:19px;line-height:1.25;margin:28px 0 var(--td-space-2)}
.td-doc-text h2+h3{margin-top:0}
.td-doc-text :is(h2,h3){scroll-margin-top:var(--td-doc-offset)}
.td-doc-text p{margin:0 0 14px}
.td-doc-text :is(ul,ol){margin:0 0 14px;padding-left:var(--td-space-4)}
.td-doc-text li{margin-bottom:6px}
.td-doc-text ol ol{list-style:lower-alpha;margin:6px 0 0}
.td-doc-text a{color:var(--td-primary);text-decoration:underline;text-underline-offset:2px}
.td-doc-text table.td-table{margin:0 0 var(--td-space-2)}

/* Dokument als ABSCHNITT einer Seite: Traegt die Seite den Dokumenttitel
   bereits als h2 (SLA-Seite: «SLA-Bedingungen» neben «Haeufige Fragen»),
   sind die Ziffern h3 — sonst stuenden sie in der Gliederung auf derselben
   Ebene wie die Verkaufsabschnitte, was ein Screenreader falsch vorliest.
   Optisch brauchen sie trotzdem die Trennlinie, die sonst das h2 traegt.
   Der Modifier spiegelt die h2-Abstaende auf h3; die Schriftgroesse bleibt
   bei 19px, damit die Ziffern unter dem Abschnittstitel bleiben. */
.td-doc-text--h3 h3{margin:0 0 var(--td-space-3);padding-top:12px}
.td-doc-text--h3 h3:not(:first-child){
  margin-top:40px;border-top:1px solid var(--td-line);padding-top:var(--td-space-5);
}

/* Briefkopf — NUR im Druck. Am Bildschirm traegt die Seite ihren eigenen
   Kopf; das PDF steht dagegen allein und muss sagen, von wem es stammt.
   aria-hidden, weil es fuer Screenreader die Angaben des Impressums
   wiederholt. */
.td-doc-briefkopf{display:none}

/* Stand des Dokuments. Bei einem Rechtstext gehoert die Fassung sichtbar auf
   die Seite — wer ihn liest, muss wissen, welchen Stand er vor sich hat, und
   beim Zitieren gehoert sie dazu. Gehoert in den .td-doc-kopf. */
.td-doc-stand{
  margin:var(--td-space-3) 0 0;
  font-size:14px;color:var(--td-muted);
}

/* ---- Tablet und Handy: einspaltig, Verzeichnis oben ---------------------- */
@media (max-width:1023px){
  .td-doc-layout{grid-template-columns:1fr;gap:var(--td-space-5)}
  /* Einspaltig gehoert der Titel nach oben, dann das Verzeichnis, dann der
     Text. Dafuer wird die rechte Spalte aufgeloest (display:contents), sonst
     liesse sich der Kopf nicht zwischen Verzeichnis und Text schieben —
     gemessen ohne diese Regel: Verzeichnis y=112 vor Titel y=242. */
  .td-doc-content{display:contents}
  .td-doc-kopf{order:1}
  .td-doc-toc {order:2}
  .td-doc-text{order:3}
  .td-doc-toc{
    position:static;max-height:none;overflow:visible;
    padding-inline:0;margin-inline:0;
  }
  /* Einspaltig ist das Verzeichnis eine zugeklappte Zeile zwischen zwei
     Textbloecken und geht mit einem --td-line-Rahmen unter (Kontrast 1.20
     gegen sec-light, gemessen). Was traegt, ist NICHT die Flaeche — weder
     Weiss (1.07) noch die blaue Toenung (1.03) hebt sich rechnerisch ab —
     sondern der kraeftigere Rahmen, die lesbare Schriftgroesse und der
     gefuellte Kreis. Die Toenung ordnet die Box der Primary-Familie zu.
     Orange waere hier falsch: permanente UI ist nie orange (Skill ci-2030,
     «Orange-Disziplin»), und gegen diesen hellen Grund ist es sogar
     kontrastschwaecher als Primary — gemessen 2.47 gegen 6.35. */
  .td-doc-toc-box{
    border:1px solid rgba(27,95,143,.22);border-radius:var(--td-radius-lg);
    background:var(--td-blue);padding:14px 18px;
  }
  .td-doc-toc-box summary{
    cursor:pointer;display:flex;justify-content:space-between;align-items:center;
    min-height:44px;gap:12px;
  }
  /* Im Kasten ist «Inhalt» kein Uebertitel mehr, sondern die Beschriftung der
     Schaltflaeche — deshalb Lesegroesse statt Kicker-Versalien. Darunter eine
     Zeile, die den NUTZEN nennt: ein Etikett allein beantwortet nicht, warum
     man tippen soll. Auf acht Druckseiten Vertragstext ist das Springen der
     eigentliche Gewinn. */
  .td-doc-toc-box summary .td-kicker{
    font-size:16px;text-transform:none;letter-spacing:0;
    font-weight:700;color:var(--td-primary);margin:0;
  }
  .td-doc-toc-nutzen{
    display:block;margin-top:2px;
    font-size:14px;font-weight:400;line-height:1.35;color:var(--td-muted);
  }
  .td-doc-toc-box summary::after{
    content:"+";width:34px;height:34px;border-radius:50%;flex:0 0 auto;
    background:var(--td-primary);color:#fff;
    display:flex;align-items:center;justify-content:center;
    font-size:22px;line-height:1;
  }
  .td-doc-toc-box[open] summary::after{content:"\00d7";font-size:19px}
  /* Tap-Ziel 44 px: 15 px x 1.35 + 2 x 12. */
  .td-doc-toc li a{padding:12px 0;font-size:15px}
  .td-doc-aktion{display:none}
}

/* ---- Drucken ------------------------------------------------------------- */
@media print{
  /* Traegt eine Seite einen Dokumentteil, gehoert NUR dieser aufs Papier.
     Gemessen 23.09.2026 an der SLA-Seite: der Druck brachte alle neun
     Sections mit — Hero, Stufenmatrix, FAQ und CTA — rund zehn A4-Seiten fuer
     acht Seiten Vertragstext. Auf den Legal-Seiten fiel das nie auf, weil das
     Dokument dort die ganze Seite IST; die SLA-Seite traegt es als eine
     Section von neun. Wo :has() fehlt, bleibt es beim alten Verhalten.
     Aus derselben Regel entsteht das Vertrags-PDF (tools/doc-pdf.py). */
  body:has(.td-doc-layout) section:not(:has(.td-doc-layout)){display:none}
  body:has(.td-doc-layout) > :is(header,footer),
  body:has(.td-doc-layout) .td-doc-aktion{display:none}

  /* Der Sektionston (sec-light, #F5F7FA) ist Bildschirmgliederung. Auf Papier
     gliedert die Seite selbst; ein Flaechenton kostet nur Toner und laesst das
     Dokument wie ein Screenshot aussehen statt wie ein Vertrag. Die dunkle
     Tabellenkopfzeile bleibt — sie traegt weisse Schrift. */
  body:has(.td-doc-layout) :is(section,.sec){background:#fff}

  /* ZUERST das Grid aufloesen, sonst druckt der Text in der 260-px-Spalte. */
  .td-doc-layout{display:block}
  .td-doc-toc{display:none}
  .td-doc-text{max-width:none;color:#000}
  .td-doc-text :is(h2,h3){color:#000;break-after:avoid}
  .td-doc-text li,.td-doc-text tr{break-inside:avoid}

  /* Briefkopf nur auf der ersten Seite; ab Seite zwei traegt die Fusszeile
     Fassung und Seitenzahl. */
  /* Variante A (Entscheid ANEB 23.09.2026): Logo und Adressblock beginnen auf
     DERSELBEN Oberkante — die Logo-Oberkante liegt auf der Zeile «ThurData
     GmbH». Geprueft und verworfen wurde die gemeinsame Grundlinie: bei
     Hoehen von 11 gegen 22 mm wirkt sie wie ein Absacken des Logos.
     Massgeblich ist die Spezifikation in Seafile,
     Marketing/Corporate Identity/THURDATA GmbH/Briefkopf CI 2030/. */
  .td-doc-briefkopf{
    display:flex;align-items:flex-start;justify-content:space-between;gap:24px;
    padding-bottom:7mm;margin-bottom:10mm;border-bottom:.5pt solid var(--td-primary);
  }
  /* Anordnung wie auf dem Geschaeftspapier (Marketing/Corporate Identity/
     THURDATA GmbH/Briefpapier.pdf): Angaben links, Signet rechts. Ein
     Vertrags-PDF, das den Kopf spiegelverkehrt traegt, sieht neben einer
     Offerte aus wie von einer anderen Firma. */
  .td-doc-briefkopf img{width:45mm;height:auto;flex:0 0 auto;order:2}
  .td-doc-briefkopf p{
    margin:0;font-size:8.5pt;line-height:1.65;color:#444;order:1;
    padding-left:3.5mm;border-left:1px solid var(--td-primary);
  }
  .td-doc-briefkopf strong{
    display:block;font-size:9.5pt;color:var(--td-text);margin-bottom:1.2mm;
  }

  /* Wo ein Abschnitt eine neue Seite beginnen soll. Von Hand gesetzt, nicht
     geraten: welcher Schnitt gut liegt, sieht man erst am fertigen Satz. */
  /* :is(h2,h3) hebt das Gewicht auf das der Trennlinien-Regel
     (.td-doc-text--h3 h3:not(:first-child)); ohne das behielt die
     Ueberschrift ihre Linie, gemessen 23.09.2026. */
  .td-doc-text :is(h2,h3).td-doc-umbruch{
    break-before:page;
    /* Am Seitenanfang trennt die Seitengrenze — die Linie sieht dort aus wie
       ein abgeschnittener Rest der Vorseite. */
    border-top:0;margin-top:0;padding-top:0;
  }
  .td-doc-text :is(h2,h3).td-doc-umbruch:first-child{break-before:auto}

  /* Papier scrollt nicht. Eine Tabelle mit min-width wird auf A4 schlicht
     ABGESCHNITTEN — gemessen 23.09.2026 am SLA-PDF: die Stufenmatrix braucht
     760 px, A4 bietet bei 16-mm-Raendern rund 673, und die Spalte «Gold»
     fehlte im Ausdruck vollstaendig. Am Bildschirm faellt es nicht auf, dort
     schiebt .td-table-scroll die Tabelle seitlich. Die Selektoren tragen
     bewusst drei Klassen: das Seiten-CSS setzt min-width mit derselben
     Gewichtung, eine schwaechere Regel bliebe wirkungslos. */
  .td-doc-text .td-table-scroll{overflow:visible}
  .td-doc-text .td-table-scroll table.td-table{
    min-width:0;width:100%;font-size:9.5px;
  }
  .td-doc-text .td-table-scroll :is(th,td){padding:5px 7px}
}

/* ============================================================================
   15. Reiter — Segment-Leiste (Entscheid ANEB 27.09.2026, Variante A2)
   ----------------------------------------------------------------------------
   Eine Spur mit Reitern; der aktive Reiter ist schwarz wie der Kopf der
   Produktkachel (.tile-head), auf dunklem Grund weiss. Kein Orange: das bleibt
   der einen Handlung je Ansicht. Ersetzt die seitenlokalen .cs-tab/.stepper
   (Unterstrich) auf den Produkt- und Entwicklerseiten.

   Markup (Umschalten macht das Seiten-JS, die Base nur das Aussehen):
     .td-tabs[role=tablist]            Spur; --dark auf dunklem Grund ohne .sec-dark,
                                       --fill = Reiter teilen sich die Breite
       .td-tab[role=tab][aria-selected]  <button> oder <a>; .is-active geht auch
         .td-tab-num                     Nummer vor dem Text (01 02 03)
         .td-tab-count                   Zaehler hinter dem Text

   Greift NUR mit Klasse — keine Regel auf button/a/[role=tab] allein (Konvention §5).
   Spezifikation: homepage content/entscheidungen/reiter-a2-2026-09-27.md,
   Muster: homepage ci-2030/muster-reiter-2026-09-27.html
   ============================================================================ */
.td-tabs{
  display:inline-flex;max-width:100%;gap:4px;padding:4px;
  background:#EEF2F6;border:1px solid var(--td-line);border-radius:var(--td-radius-lg);
  overflow-x:auto;scrollbar-width:none;
}
.td-tabs::-webkit-scrollbar{display:none}
.td-tab{
  appearance:none;margin:0;border:0;background:transparent;cursor:pointer;
  display:inline-flex;align-items:center;gap:8px;flex:0 0 auto;
  min-height:40px;padding:0 16px;border-radius:7px;
  font-family:inherit;font-size:14.5px;font-weight:500;line-height:1;
  color:var(--td-body);white-space:nowrap;text-decoration:none;
  transition:background-color var(--td-transition),color var(--td-transition);
}
/* Theme (Croster/Bootstrap) unterstreicht a:hover und faerbt Links: hier aus */
.td-tab:hover,.td-tab:focus{background:rgba(15,26,36,.07);color:var(--td-text);text-decoration:none}
.td-tab[aria-selected="true"],.td-tab.is-active{background:var(--td-dark);color:#fff;font-weight:700}
.td-tab:focus-visible{outline:none;box-shadow:var(--td-focus-ring)}
.td-tab-num{font:700 11px/1 "Roboto Mono",Consolas,monospace;letter-spacing:.08em;opacity:.75}
.td-tab-count{
  display:inline-flex;align-items:center;justify-content:center;min-width:18px;height:18px;padding:0 5px;
  border-radius:var(--td-radius-pill);background:rgba(27,95,143,.08);color:var(--td-muted);
  font-size:11px;font-weight:700;line-height:1;
}
.td-tab[aria-selected="true"] .td-tab-count,.td-tab.is-active .td-tab-count{background:rgba(255,255,255,.16);color:#fff}

/* Dunkler Grund: aktiver Reiter weiss. Selektoren mit .td-tabs dazwischen (0,4,0),
   damit .sec-dark a:not([class*="btn"]):hover (0,3,1) einen <a>-Reiter nicht orange faerbt. */
.td-tabs--dark,.sec-dark .td-tabs,.hero-dark .td-tabs{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.12)}
.td-tabs--dark .td-tab,.sec-dark .td-tabs .td-tab,.hero-dark .td-tabs .td-tab{color:rgba(255,255,255,.72)}
.td-tabs--dark .td-tab:hover,.sec-dark .td-tabs .td-tab:hover,.hero-dark .td-tabs .td-tab:hover,
.td-tabs--dark .td-tab:focus,.sec-dark .td-tabs .td-tab:focus,.hero-dark .td-tabs .td-tab:focus{background:rgba(255,255,255,.08);color:#fff}
.td-tabs--dark .td-tab[aria-selected="true"],.sec-dark .td-tabs .td-tab[aria-selected="true"],.hero-dark .td-tabs .td-tab[aria-selected="true"],
.td-tabs--dark .td-tab.is-active,.sec-dark .td-tabs .td-tab.is-active,.hero-dark .td-tabs .td-tab.is-active{background:#fff;color:var(--td-dark)}
.td-tabs--dark .td-tab[aria-selected="true"] .td-tab-num,.sec-dark .td-tabs .td-tab[aria-selected="true"] .td-tab-num,
.hero-dark .td-tabs .td-tab[aria-selected="true"] .td-tab-num{color:var(--td-primary);opacity:1}

/* Reiter teilen sich die volle Breite (wenige, kurze Reiter) */
.td-tabs--fill{display:flex;width:100%}
.td-tabs--fill .td-tab{flex:1 1 0;justify-content:center}

@media (max-width:767px){
  .td-tabs{display:flex;width:100%}
  .td-tab{min-height:44px;padding:0 14px}
}
