:root {
  --font-system-ui: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif;
  --indigo-7: #4263eb;
  --purple-7: #ae3ec9;
  --gray-12: #030507;
  --gray-7: #495057;
  --gray-0: #f8f9fa;
  --gray-2: #e9ecef;
  --gray-3: #dee2e6;
  --gray-4: #ced4da;
  --red-6: #fa5252;
  --red-1: #ffe3e3;
  --red-9: #c92a2a;
  --green-6: #40c057;
  --green-1: #d3f9d8;
  --green-9: #2b8a3e;
  --blue-6: #228be6;
  --blue-1: #d0ebff;
  --blue-9: #1864ab;
  --yellow-9: #e67700;
  --yellow-1: #fff3bf;
  --size-content-3: 60ch;
  --size-fluid-4: max(2rem,min(4vw,3rem));
  --size-fluid-3: max(1.5rem,min(3vw,2rem));
  --indigo-3: #91a7ff;
  --purple-3: #e599f7;
  --gray-1: #f1f3f5;
  --gray-9: #212529;
  --gray-8: #343a40;
  --gray-6: #868e96;
  --red-4: #ff8787;
  --green-4: #69db7c;
  --blue-4: #4dabf7;
  --yellow-4: #ffd43b;
  --font-lineheight-3: 1.5;
  --ease-2: cubic-bezier(.25,0,.4,1);
  --font-weight-9: 900;
  --font-lineheight-1: 1.25;
  --font-size-8: 3.5rem;
  --size-header-1: 20ch;
  --font-size-6: 2.5rem;
  --size-header-2: 25ch;
  --font-size-5: 2rem;
  --font-size-4: 1.5rem;
  --font-size-3: 1.25rem;
  --size-header-3: 35ch;
  --font-size-2: 1.1rem;
  --indigo-2: #bac8ff;
  --purple-2: #eebefa;
  --size-1: .25rem;
  --size-2: .5rem;
  --size-relative-4: 1.25ch;
  --size-content-1: 20ch;
  --size-3: 1rem;
  --size-10: 5rem;
  --font-monospace-code: Dank Mono,Operator Mono,Inconsolata,Fira Mono,ui-monospace,SF Mono,Monaco,Droid Sans Mono,Source Code Pro,Cascadia Code,Menlo,Consolas,DejaVu Sans Mono,monospace;
  --radius-2: 5px;
  --border-size-1: 1px;
  --size-8: 3rem;
  --size-content-2: 45ch;
  --font-weight-7: 700;
  --size-5: 1.5rem;
  --font-size-0: .75rem;
  --border-size-2: 2px;
  --size-fluid-5: max(4rem,min(5vw,5rem));
  --font-size-1: 1rem;
  --border-size-3: 5px;
  --size-4: 1.25rem;
  --red-2: #ffc9c9;
  --blue-5: #339af0;
  --radius-3: 1rem;
  --shadow-6: 0 -1px 2px 0 hsl(var(--shadow-color)/var(--shadow-strength-3)),0 3px 2px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 7px 5px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 12px 10px -2px hsl(var(--shadow-color)/var(--shadow-strength-5)),0 22px 18px -2px hsl(var(--shadow-color)/var(--shadow-strength-6)),0 41px 33px -2px hsl(var(--shadow-color)/var(--shadow-strength-7)),0 100px 80px -2px hsl(var(--shadow-color)/var(--shadow-strength-8));
  --size-fluid-2: max(1rem,min(2vw,1.5rem));
  --red-3: #ffa8a8;
  --inner-shadow-4: inset 0 2px 14px 0 hsl(var(--shadow-color)/var(--shadow-strength-10)),var(--inner-shadow-highlight);
  --size-relative-6: 1.75ch;
  --font-weight-6: 600;
  --shadow-color: 220 40% 2%;
  --shadow-strength-3: calc(var(--shadow-strength) + 2%);
  --shadow-strength-4: calc(var(--shadow-strength) + 3%);
  --shadow-strength-5: calc(var(--shadow-strength) + 4%);
  --shadow-strength-6: calc(var(--shadow-strength) + 5%);
  --shadow-strength-7: calc(var(--shadow-strength) + 6%);
  --shadow-strength-8: calc(var(--shadow-strength) + 7%);
  --shadow-strength-10: calc(var(--shadow-strength) + 9%);
  --inner-shadow-highlight: inset 0 -.5px 0 0 hsla(0,0%,100%,.067),inset 0 .5px 0 0 rgba(0,0,0,.467);
  --shadow-strength: 25%;
  --size-relative-7: 2ch;
  --shadow-2: 0 3px 5px -2px hsl(var(--shadow-color)/var(--shadow-strength-4)),0 7px 14px -5px hsl(var(--shadow-color)/var(--shadow-strength-6));
  --shadow-1: 0 1px 2px -1px hsl(var(--shadow-color)/var(--shadow-strength-10));
  --gray-5: #adb5bd;
  --ease-3: cubic-bezier(.25,0,.3,1);
  --ease-4: cubic-bezier(.25,0,.2,1);
  --shadow-3: 0 -1px 3px 0 hsl(var(--shadow-color)/var(--shadow-strength-3)),0 1px 2px -5px hsl(var(--shadow-color)/var(--shadow-strength-3)),0 2px 5px -5px hsl(var(--shadow-color)/var(--shadow-strength-5)),0 4px 12px -5px hsl(var(--shadow-color)/var(--shadow-strength-6)),0 12px 15px -5px hsl(var(--shadow-color)/var(--shadow-strength-8));
}

/*
 * Test-Einstieg: komplettes Framework (styles.css) plus die JS-Variante des
 * mobilen Navigationsschalters. Nur zum Ausprobieren gedacht, damit styles.css
 * unverändert bleibt. Zusammen mit src/js/navigation.js verwenden.
 */

/*
 * Contao Theme Framework – Haupteinstiegspunkt.
 * Reihenfolge folgt ITCSS (generisch -> Basis -> komponentenspezifisch),
 * damit die Cascade genutzt werden kann statt Spezifität hochzuschrauben.
 */

/* abstracts: Design-Tokens & Farbschema (Light/Dark), zuerst importiert,
   damit alle folgenden Dateien die Tokens (--ctf-, --clr-, --grid-) nutzen
   können */

/*
 * Framework-Tokens & Farbschema.
 * Ergänzt die Design-Tokens von Open Props um Werte, die dort fehlen:
 * eine fluide Schriftgrößen-Skala nach der Utopia-Methode (utopia.fyi),
 * ein eigenes, Light/Dark-fähiges Farbschema und ein paar layoutbezogene
 * Basiswerte. Abstände, Radien usw. kommen weiterhin direkt aus Open Props
 * (var(--size-4), var(--radius-2) ...) statt hier dupliziert zu werden.
 *
 * Anders als in einer früheren Version wird diese Datei jetzt ganz normal
 * per @import eingebunden (siehe styles.css) statt per postcss-jit-props
 * injiziert: Für ein kleines, von Hand gepflegtes Token-Set ist eine
 * build-tool-spezifische Just-in-Time-Injektion unnötige Komplexität –
 * vor allem, weil Light/Dark-Werte ohnehin einen echten, verschachtelten
 * @media-Block brauchen, den jit-props nicht abbilden kann (es kennt nur
 * eine flache Property-zu-Wert-Zuordnung, keine Selektor-/Media-Struktur).
 * Für die große Open-Props-Rohfarbpalette (open-props.min.css) bleibt
 * jit-props weiterhin sinnvoll (siehe postcss.config.js) – nur dort lohnt
 * sich Tree-Shaking wirklich.
 */
:root {
  /* Fluide Typografie: Viewport 320px–1240px, Basisschrift 18px–20px,
     Skalenverhältnis 1.2 (klein) bis 1.25 (groß) */
  --ctf-step--2: clamp(0.7813rem, 0.7747rem + 0.0326vw, 0.8rem);
  --ctf-step--1: clamp(0.9375rem, 0.9158rem + 0.1087vw, 1rem);
  --ctf-step-0: clamp(1.125rem, 1.0815rem + 0.2174vw, 1.25rem);
  --ctf-step-1: clamp(1.35rem, 1.2761rem + 0.3696vw, 1.5625rem);
  --ctf-step-2: clamp(1.62rem, 1.5041rem + 0.5793vw, 1.9531rem);
  --ctf-step-3: clamp(1.944rem, 1.771rem + 0.8651vw, 2.4414rem);
  --ctf-step-4: clamp(2.3328rem, 2.0827rem + 1.2504vw, 3.0518rem);
  --ctf-step-5: clamp(2.7994rem, 2.4462rem + 1.7658vw, 3.8147rem);
  --ctf-step-6: clamp(3.3592rem, 2.8691rem + 2.4507vw, 4.7684rem);

  /* Schrift-Aliase auf die Open-Props-Stacks (modernfontstacks.com).
     Themes können hier umschalten, ohne Selektoren im Framework anzufassen */
  --ctf-font-body: var(--font-system-ui);
  --ctf-font-heading: var(--font-system-ui);

  /*
   * Farbschema (Light, Standardwert). Komponenten referenzieren nur noch
   * --clr-*, nie direkt Open-Props-Rohfarben wie --red-6 – ein Theme kann so
   * sein eigenes Farbschema definieren, ohne Selektoren in contao/*.css oder
   * generic/normalize.css anzufassen. Die numerischen Stufen (-1..-4 bzw.
   * -2) entsprechen der Open-Props-eigenen Konvention (text-1/-2,
   * surface-1..4), die generic/normalize.css als Vorbild übernimmt.
   */
  --clr-link: var(--indigo-7);
  --clr-link-visited: var(--purple-7);
  --clr-text-1: var(--gray-12);
  --clr-text-2: var(--gray-7);
  --clr-surface-1: var(--gray-0);
  --clr-surface-2: var(--gray-2);
  --clr-surface-3: var(--gray-3);
  --clr-surface-4: var(--gray-4);
  --clr-scrollthumb: var(--gray-7);

  /*
   * Status-Farben, je drei Stufen:
   *   <status>             Akzentfarbe (z. B. Text/Icon auf neutraler Fläche)
   *   <status>-surface       Hintergrund einer gefüllten Box (z. B. .message)
   *   <status>-surface-text  Textfarbe auf dieser Box
   * error/success werden von echten Contao-Klassen genutzt
   * (.message.error/.message.confirm, siehe contao/modules.css für den
   * tl_error-Alias – tl_confirm bewusst nicht gespiegelt, siehe dort).
   * info/warning sind (noch) keine von Contao selbst gesetzten Klassen,
   * aber als Helper-Klassen nutzbar (.message.info/.message.warning),
   * falls ein Projekt sie manuell braucht.
   */
  --clr-error: var(--red-6);
  --clr-error-surface: var(--red-1);
  --clr-error-surface-text: var(--red-9);

  --clr-success: var(--green-6);
  --clr-success-surface: var(--green-1);
  --clr-success-surface-text: var(--green-9);

  --clr-info: var(--blue-6);
  --clr-info-surface: var(--blue-1);
  --clr-info-surface-text: var(--blue-9);

  --clr-warning: var(--yellow-9);
  --clr-warning-surface: var(--yellow-1);
  --clr-warning-surface-text: var(--yellow-9);

  /* Breitenbegrenzung für header/main/footer > .inside (base/skeleton.css) */
  --ctf-content-width: 75rem;

  /* Lesemaß (typografische Zeilenlänge): generic/normalize.css (:where(p))
     und contao/elements.css (.content-text) referenzieren beide dieses eine
     Token, damit eine andere Zeilenlänge nur an dieser Stelle geändert
     werden muss, statt an mehreren Dateien synchron */
  --ctf-measure: var(--size-content-3);

  /* Vertikaler Rhythmus (base/typography.css): Abstand zwischen Artikeln,
     größer als der zwischen Inhaltselementen (--size-fluid-3) */
  --ctf-article-space: var(--size-fluid-4);

  /* Gridsystem (base/grid.css): Spaltenzahl und Rinnenbreite waren dort
     bisher referenziert, aber nirgends definiert – ohne diese beiden
     Werte griff var(--grid-columns)/var(--grid-gutter) ins Leere */
  --grid-columns: 12;
  --grid-gutter: var(--size-fluid-3);

  /* .row hat per gap: var(--grid-gutter) standardmäßig denselben Abstand in
     beide Richtungen. --grid-gutter-y ist der Override-Punkt für .row--gap-y,
     wenn ein Theme einen abweichenden vertikalen Abstand braucht; per Default
     identisch zu --grid-gutter, also ohne eigene Anpassung ein No-op */
  --grid-gutter-y: var(--grid-gutter);
}

/*
 * Farbschema (Dark). Echter, verschachtelter @media-Block statt einer
 * build-tool-spezifischen Konvention – funktioniert unabhängig vom
 * verwendeten PostCSS-Setup und ist für jeden CSS-Entwickler auf Anhieb
 * lesbar. Nur die Farb-Tokens werden hier überschrieben, alles andere
 * (Typografie, Grid, Abstände) bleibt schemaunabhängig.
 */
@media (prefers-color-scheme: dark) {
  :root {
    --clr-link: var(--indigo-3);
    --clr-link-visited: var(--purple-3);
    --clr-text-1: var(--gray-1);
    --clr-text-2: var(--gray-4);
    --clr-surface-1: var(--gray-9);
    --clr-surface-2: var(--gray-8);
    --clr-surface-3: var(--gray-7);
    --clr-surface-4: var(--gray-6);
    --clr-scrollthumb: var(--gray-6);

    --clr-error: var(--red-4);
    --clr-error-surface: var(--red-9);
    --clr-error-surface-text: var(--red-1);

    --clr-success: var(--green-4);
    --clr-success-surface: var(--green-9);
    --clr-success-surface-text: var(--green-1);

    --clr-info: var(--blue-4);
    --clr-info-surface: var(--blue-9);
    --clr-info-surface-text: var(--blue-1);

    --clr-warning: var(--yellow-4);
    --clr-warning-surface: var(--yellow-9);
    --clr-warning-surface-text: var(--yellow-1);
  }
}
/* generic: Reset & Basiswerte, an die normalize.css von Open Props angelehnt */
/*
 * Reset & sinnvolle Basiswerte, nach dem Vorbild der normalize.css von Open
 * Props (siehe node_modules/open-props/normalize.min.css) – möglichst
 * unverändert übernommen, wo es rein strukturelles Reset-Verhalten betrifft
 * (box-sizing, Ränder, Formular-/Tabellen-Grundstyling, Fokus-Stile usw.).
 *
 * Farben wurden bewusst ersetzt: statt der eingebauten --text-1/--surface-1/
 * --link-Tokens von Open Props referenziert dieses File unser eigenes
 * Farbschema (--clr-*, siehe abstracts/custom-properties.css) – so pflegen
 * wir Light/Dark-Werte an einer Stelle, statt zwei parallele Systeme
 * (Open-Props-Semantik und unser eigenes) im Framework zu haben.
 *
 * Ausgelassen: die button/.btn-bezogenen Custom-Property-Zuweisungen aus dem
 * Original (--_highlight, --_bg, --_ink-shadow usw.) – die greifen nur im
 * Zusammenspiel mit Open Props' eigenem Buttons-Modul, das wir nicht
 * einbinden, und wären hier totes Gewicht ohne Wirkung.
 */

:where(html) {
  -webkit-text-size-adjust: none;
  accent-color: var(--brand, var(--clr-link));
  background-color: var(--clr-surface-1);
  block-size: 100%;
  caret-color: var(--brand, var(--clr-link));
  color: var(--clr-text-1);
  --csstools-color-scheme--light: initial;
  color-scheme: light;
  font-family: var(--font-system-ui);
  line-height: var(--font-lineheight-3);
  scrollbar-color: var(--clr-scrollthumb) transparent;
}

@media (prefers-color-scheme: dark) {
  :where(html) {
    --csstools-color-scheme--light:  ;
    color-scheme: dark;
    --shadow-strength: 10%;
    --shadow-color: 220 40% 2%;
  }
}

:where(html) :where(dialog) {
  background-color: var(--clr-surface-1);
}

:where(html) :where(textarea, select, input:not([type="button"]):not([type="submit"]):not([type="reset"])) {
  background-color: var(--clr-surface-2);
}

:where(a[href]) {
  color: var(--brand, var(--clr-link));
}

:where(a[href]):where(:visited) {
  color: var(--clr-link-visited);
}

:focus-visible {
  outline-color: var(--brand, var(--clr-link));
}

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

:where(:not(dialog)) {
  margin: 0;
}

:where(:not(fieldset):not(progress):not(meter)) {
  background-origin: border-box;
  background-repeat: no-repeat;
  border-style: solid;
  border-width: 0;
}

@media (prefers-reduced-motion: no-preference) {
  :where(html) {
    scroll-behavior: smooth;
  }

  :where(:focus-visible) {
    transition: outline-offset 145ms var(--ease-2);
  }

  :where(:not(:active):focus-visible) {
    transition-duration: 0.25s;
  }
}

:where(:not(:active):focus-visible) {
  outline-offset: 5px;
}

:where(body) {
  min-block-size: 100%;
}

:where(h1, h2, h3, h4, h5, h6) {
  text-wrap: balance;
  font-weight: var(--font-weight-9);
  line-height: var(--font-lineheight-1);
}

:where(h1) {
  font-size: var(--font-size-8);
  max-inline-size: var(--size-header-1);
}

:where(h2) {
  font-size: var(--font-size-6);
  max-inline-size: var(--size-header-2);
}

:where(h3) {
  font-size: var(--font-size-5);
}

:where(h4) {
  font-size: var(--font-size-4);
}

:where(h5) {
  font-size: var(--font-size-3);
}

:where(h3, h4, h5, h6, dt) {
  max-inline-size: var(--size-header-3);
}

:where(p, ul, ol, dl, h6) {
  font-size: var(--font-size-2);
}

:where(a, u, ins, abbr) {
  text-underline-offset: 1px;
}

@supports (-moz-appearance: none) {
  :where(a, u, ins, abbr) {
    text-underline-offset: 2px;
  }
}

:where(a[href], area, button, input:not([type="text"]):not([type="email"]):not([type="number"]):not([type="password"]):not([type=""]):not([type="tel"]):not([type="url"]), label[for], select, summary, [tabindex]:not([tabindex*="-"]):not(pre)) {
  cursor: pointer;
}

:where(a[href], area, button, input, label[for], select, summary, textarea, [tabindex]:not([tabindex*="-"])) {
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

:where(a):where([href]) {
  text-decoration-color: var(--indigo-2);
}

:where(a):where([href]):where(:visited) {
  text-decoration-color: var(--purple-2);
}

:where(a):where(:not(:hover)) {
  text-decoration: inherit;
}

:where(img, svg, video, canvas, audio, iframe, embed, object) {
  display: block;
}

:where(img, svg, video) {
  block-size: auto;
  max-inline-size: 100%;
}

:where(input, button, textarea, select),
:where(input[type="file"])::-webkit-file-upload-button {
  color: inherit;
  font: inherit;
  font-size: inherit;
  letter-spacing: inherit;
}

::-moz-placeholder {
  color: var(--clr-text-2);
  opacity: 0.75;
}

::placeholder {
  color: var(--clr-text-2);
  opacity: 0.75;
}

:where(input:not([type="range"]), textarea) {
  padding-block: var(--size-1);
  padding-inline: var(--size-2);
}

:where(select) {
  field-sizing: content;
  padding-block: 0.75ch;
  padding-inline: var(--size-relative-4) 0;
}

:where(textarea, select, input:not([type="button"]):not([type="submit"]):not([type="reset"])) {
  background-color: var(--clr-surface-2);
  border-radius: var(--radius-2);
}

:where(textarea) {
  field-sizing: content;
  min-block-size: 2lh;
  min-inline-size: var(--size-content-1);
  resize: vertical;
}

:where(input[type="checkbox"], input[type="radio"]) {
  block-size: var(--size-3);
  inline-size: var(--size-3);
}

:where(svg:not([width])) {
  inline-size: var(--size-10);
}

:where(code, kbd, samp, pre) {
  font-family: var(--font-monospace-code), monospace;
}

:where(:not(pre) > code, kbd) {
  white-space: nowrap;
}

:where(pre) {
  direction: ltr;
  max-inline-size: -moz-max-content;
  max-inline-size: max-content;
  min-inline-size: 0;
  white-space: pre;
  writing-mode: lr;
}

:where(:not(pre) > code) {
  background: var(--clr-surface-2);
  border-radius: var(--radius-2);
  padding: var(--size-1) var(--size-2);
  writing-mode: lr;
}

:where(kbd, var) {
  border-color: var(--clr-surface-4);
  border-radius: var(--radius-2);
  border-width: var(--border-size-1);
  padding: var(--size-1) var(--size-2);
}

:where(mark) {
  border-radius: var(--radius-2);
  padding-inline: var(--size-1);
}

:where(ol, ul) {
  padding-inline-start: var(--size-8);
}

:where(li) {
  padding-inline-start: var(--size-2);
}

:where(li, dd, figcaption) {
  max-inline-size: var(--size-content-2);
}

:where(p) {
  text-wrap: pretty;
  max-inline-size: var(--ctf-measure);
}

:where(dt, summary) {
  font-weight: var(--font-weight-7);
}

:where(dt:not(:first-of-type)) {
  margin-block-start: var(--size-5);
}

:where(small) {
  font-size: max(0.5em, var(--font-size-0));
  max-inline-size: var(--size-content-1);
}

:where(hr) {
  background-color: var(--clr-surface-3);
  height: var(--border-size-2);
  margin-block: var(--size-fluid-5);
}

:where(figure) {
  display: grid;
  grid-gap: var(--size-2);
  gap: var(--size-2);
  align-items: center;
  justify-items: center;
  place-items: center;
}

:where(figure) > :where(figcaption) {
  text-wrap: balance;
  font-size: var(--font-size-1);
}

:where(blockquote, :not(blockquote) > cite) {
  border-inline-start-width: var(--border-size-3);
}

:where(blockquote) {
  display: grid;
  grid-gap: var(--size-3);
  gap: var(--size-3);
  max-inline-size: var(--size-content-2);
  padding-block: var(--size-3);
  padding-inline: var(--size-4);
}

:where(:not(blockquote) > cite) {
  padding-inline-start: var(--size-2);
}

:where(summary) {
  background: var(--clr-surface-3);
  border-radius: var(--radius-2);
  margin: calc(var(--size-2) * -1) calc(var(--size-3) * -1);
  padding: var(--size-2) var(--size-3);
}

:where(details) {
  background: var(--clr-surface-2);
  border-radius: var(--radius-2);
  padding-block: var(--size-2);
  padding-inline: var(--size-3);
}

:where(details[open] > summary) {
  border-end-end-radius: 0;
  border-end-start-radius: 0;
  margin-bottom: var(--size-2);
}

:where(fieldset) {
  border: var(--border-size-1) solid var(--clr-surface-4);
  border-radius: var(--radius-2);
}

:where(del) {
  background: var(--red-9);
  color: var(--red-2);
}

:where(ins) {
  background: var(--green-9);
  color: var(--green-1);
}

:where(abbr) {
  text-decoration-color: var(--blue-5);
}

:where(dialog) {
  background-color: var(--clr-surface-1);
  border-radius: var(--radius-3);
  box-shadow: var(--shadow-6);
  color: inherit;
}

:where(menu) {
  display: flex;
  gap: var(--size-3);
  padding-inline-start: 0;
}

:where(sup) {
  font-size: 0.5em;
}

:where(table) {
  --nice-inner-radius: calc(var(--radius-3) - 2px);
  background: var(--clr-surface-2);
  border: 1px solid var(--clr-surface-2);
  border-radius: var(--radius-3);
  width: -moz-fit-content;
  width: fit-content;
}

:where(table:not(:has(tfoot)) tr:last-child td:first-child) {
  border-end-start-radius: var(--nice-inner-radius);
}

:where(table:not(:has(tfoot)) tr:last-child td:last-child) {
  border-end-end-radius: var(--nice-inner-radius);
}

:where(table thead tr:first-child th:first-child) {
  border-start-start-radius: var(--nice-inner-radius);
}

:where(table thead tr:first-child th:last-child) {
  border-start-end-radius: var(--nice-inner-radius);
}

:where(tfoot tr:last-child th:first-of-type) {
  border-end-start-radius: var(--nice-inner-radius);
}

:where(tfoot tr:last-child td:first-of-type) {
  border-end-start-radius: var(--nice-inner-radius);
}

:where(tfoot tr:last-child th:last-of-type) {
  border-end-end-radius: var(--nice-inner-radius);
}

:where(tfoot tr:last-child td:last-of-type) {
  border-end-end-radius: var(--nice-inner-radius);
}

:where(th) {
  background-color: var(--clr-surface-2);
  color: var(--clr-text-1);
}

:where(table a:not(.does-not-exist):focus-visible),
:where(table button:not(.does-not-exist):focus-visible),
:where(table [contenteditable]:focus-visible) {
  outline-offset: -2px;
}

:where(td) {
  text-wrap: pretty;
  background: var(--clr-surface-1);
  max-inline-size: var(--size-content-2);
}

:where(td, th) {
  padding: var(--size-2);
  text-align: left;
}

:where(td:not([align])),
:where(th:not([align])) {
  text-align: center;
}

:where(thead) {
  border-collapse: collapse;
}

:where(table tr:hover td),
:where(tbody tr:nth-child(2n):hover td) {
  background-color: var(--clr-surface-3);
}

:where(table > caption) {
  margin: var(--size-3);
}

:where(tfoot button) {
  padding-block: var(--size-1);
  padding-inline: var(--size-3);
}

/* Im Original ein eigener Dark-Mode-Override (Dialog etwas heller als der
   normale Seitenhintergrund) – die übrigen Dark-Anpassungen des Originals
   (Eingabefelder, Placeholder) entfallen hier, da sie über --clr-surface-2/
   --clr-text-2 schon automatisch mit dem Farbschema mitschalten */
@media (prefers-color-scheme: dark) {
  :where(dialog) {
    background-color: var(--clr-surface-2);
  }
}
/* base: unstyled HTML-Elemente, Seitengerüst, Gridsystem */
/*
 * Seitengerüst nach page/layout.html.twig (siehe resources/layout.html.twig):
 * #wrapper enthält <header>, <main> und <footer>, jeweils mit einem
 * .inside-Div für die Breitenbegrenzung/Zentrierung. Kein #container,
 * kein #left/#right: Sidebars sind hier bewusst nicht vorgesehen, das
 * wäre Aufgabe des Projekt-Layouts, das diese Vorlage erweitert.
 */

body {
  font-family: var(--ctf-font-body);
}

/* Sticky Footer per Grid statt Flex: header/main/footer liegen ohnehin
   schon in dieser Reihenfolge im Markup, "auto 1fr auto" reicht als einzige
   Regel – main braucht keine zusätzliche flex:1-Angabe mehr.
   100dvh statt 100vh, damit mobile Adressleisten (ein-/ausblendend) nicht zu
   Sprüngen führen; 100vh bleibt als Fallback für ältere Browser stehen */
#wrapper {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-block-size: 100vh;
  min-block-size: 100dvh;
}

/* Breitenbegrenzung/Zentrierung für header/main/footer. padding-inline
   verhindert, dass der Inhalt auf schmalen Viewports am Rand klebt; nutzt
   denselben Wert wie der Grid-Gutter statt einen weiteren Token einzuführen */
:is(header, main, footer) > .inside {
  max-inline-size: var(--ctf-content-width);
  margin-inline: auto;
  padding-inline: var(--grid-gutter);
}

/* Visuell verborgen, aber für Screenreader vorhanden (Skip-Links etc.) */
.invisible {
  position: absolute;
  overflow: hidden;
  inline-size: 1px;
  block-size: 1px;
  clip-path: inset(50%);
  white-space: nowrap;
}
/*
 * Fluide Typografie. Überschreibt die statischen Schriftgrößen aus der
 * Open-Props-normalize.css mit der Utopia-Skala aus abstracts/custom-properties.css –
 * das ist die Cascade in Aktion, kein zusätzlicher Reset nötig.
 */

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

h1 { font-size: var(--ctf-step-6); }
h2 { font-size: var(--ctf-step-5); }
h3 { font-size: var(--ctf-step-4); }
h4 { font-size: var(--ctf-step-3); }
h5 { font-size: var(--ctf-step-2); }
h6 { font-size: var(--ctf-step-1); }

:is(body, p, ul, ol, dl) {
  font-size: var(--ctf-step-0);
}

small {
  font-size: var(--ctf-step--2);
}

/*
 * Vertikaler Rhythmus per Owl-Selektor (* + *), statt jedem Inhaltselement
 * einzeln einen margin-block-end mitzugeben – ein zentraler Ort statt
 * verstreuter Regeln, und kein doppelter Abstand zwischen zwei Elementen.
 * Drei Stufen, von grob nach fein:
 *   1. Zwischen Artikeln (padding statt margin: die Artikel-Hintergrundfarbe
 *      reicht dadurch bis an die Kante, außerdem kein Margin-Collapsing
 *      zwischen den .mod_article-Geschwistern).
 *   2. Zwischen den Inhaltselementen eines Artikels (.mod_article > .inside
 *      wird per angepasstem Template um dieses .inside-Div ergänzt).
 *   3. Innerhalb eines einzelnen Inhaltselements bzw. Rich-Text-Blocks
 *      (.rte kommt aus component/_rich_text.html.twig), z. B. zwischen
 *      Absätzen eines Textelements.
 */
main .mod_article {
  padding-block: var(--ctf-article-space);
}

.mod_article > .inside > * + * {
  margin-block-start: var(--size-fluid-3);
}

:is([class*="content-"], .rte) > * + * {
  margin-block-start: var(--size-fluid-2);
}

/*
 * 12-Spalten-Gridsystem, abgeleitet vom Nutshell-Framework-Grid, aber
 * konsolidiert: keine SCSS-Loops mehr, sondern handgeschriebenes,
 * dedupliziertes CSS mit @custom-media fuer die Breakpoints. Die
 * urspruengliche Version dieser Datei liegt unter grid_orig.css.
 *
 * Aufbau: .row (Grid-Container) + Utility-Klassen fuer Spalten-/Zeilen-
 * Spannweite, -Start und Ausrichtung, jeweils optional mit Breakpoint-
 * Suffix (-sm-/-md-/-lg-/-xl-). Die "xs"-Variante (kleinster Breakpoint)
 * ist mit der unpraefigierten Basisklasse identisch (min-width: 0 gilt
 * immer) und wurde daher per :is() zusammengefuehrt statt dupliziert.
 */

/* Breakpoints einmal benennen statt die em-Werte mehrfach zu wiederholen */ /* ~550px */     /* ~768px */  /* ~940px */  /* ~1100px */

/* Grid-Container: Spaltenzahl und Rinnenbreite kommen aus Custom
   Properties, damit Themes sie ueberschreiben koennen. gap statt nur
   column-gap, da .row-Elemente in der Praxis meist mehrzeilig umbrechen
   (Galerien, Teaser-Listen) und dort auch ohne Opt-in ein Row-Gap wollen */
.row {
  display: grid;
  grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
  grid-auto-columns: 1fr;
  grid-gap: var(--grid-gutter);
  gap: var(--grid-gutter);
}

/* Override fuer einen abweichenden vertikalen Abstand (z. B. mehr Weissraum
   zwischen Zeilen als zwischen Spalten) – ueber --grid-gutter-y steuerbar */
.row--gap-y {
  row-gap: var(--grid-gutter-y);
}

/* Kindelemente von Contao-Artikeln/-Galerien, die eine Spaltenbreite
   bekommen sollen, muessen selbst Grid-Items sein. [class*="…"] statt
   der bisherigen 1-durch-12-Aufzaehlung pro Breakpoint (120 Selektoren) */
[class*="article-xl-"] > .inside > *,
[class*="article-lg-"] > .inside > *,
[class*="article-md-"] > .inside > *,
[class*="article-sm-"] > .inside > *,
[class*="article-xs-"] > .inside > *,
.content-gallery > ul > li,
[class*="col-xl-"],
[class*="col-lg-"],
[class*="col-md-"],
[class*="col-sm-"],
[class*="col-xs-"] {
  display: grid;
  grid-column: 1 / -1;
  max-inline-size: 100%;
}

/* Basis-Tier: gilt auf jeder Breite. -xs-Pendants sind hier eingeschlossen */
.col {
  grid-column: 1 / -1;
}

:is(.col-1, .col-xs-1) {
  grid-column: span 1 / span 1;
}

:is(.col-2, .col-xs-2) {
  grid-column: span 2 / span 2;
}

:is(.col-3, .col-xs-3) {
  grid-column: span 3 / span 3;
}

:is(.col-4, .col-xs-4) {
  grid-column: span 4 / span 4;
}

:is(.col-5, .col-xs-5) {
  grid-column: span 5 / span 5;
}

:is(.col-6, .col-xs-6) {
  grid-column: span 6 / span 6;
}

:is(.col-7, .col-xs-7) {
  grid-column: span 7 / span 7;
}

:is(.col-8, .col-xs-8) {
  grid-column: span 8 / span 8;
}

:is(.col-9, .col-xs-9) {
  grid-column: span 9 / span 9;
}

:is(.col-10, .col-xs-10) {
  grid-column: span 10 / span 10;
}

:is(.col-11, .col-xs-11) {
  grid-column: span 11 / span 11;
}

:is(.col-12, .col-xs-12) {
  grid-column: span 12 / span 12;
}

:is(.row-start-1, .row-start-xs-1) {
  grid-row-start: 1;
}

:is(.row-start-2, .row-start-xs-2) {
  grid-row-start: 2;
}

:is(.row-start-3, .row-start-xs-3) {
  grid-row-start: 3;
}

:is(.row-start-4, .row-start-xs-4) {
  grid-row-start: 4;
}

:is(.row-start-5, .row-start-xs-5) {
  grid-row-start: 5;
}

:is(.row-start-6, .row-start-xs-6) {
  grid-row-start: 6;
}

:is(.row-start-7, .row-start-xs-7) {
  grid-row-start: 7;
}

:is(.row-start-8, .row-start-xs-8) {
  grid-row-start: 8;
}

:is(.row-start-9, .row-start-xs-9) {
  grid-row-start: 9;
}

:is(.row-start-10, .row-start-xs-10) {
  grid-row-start: 10;
}

:is(.row-start-11, .row-start-xs-11) {
  grid-row-start: 11;
}

:is(.row-start-12, .row-start-xs-12) {
  grid-row-start: 12;
}

:is(.row-span-1, .row-span-xs-1) {
  grid-row: span 1 / span 1;
}

:is(.row-span-2, .row-span-xs-2) {
  grid-row: span 2 / span 2;
}

:is(.row-span-3, .row-span-xs-3) {
  grid-row: span 3 / span 3;
}

:is(.row-span-4, .row-span-xs-4) {
  grid-row: span 4 / span 4;
}

:is(.row-span-5, .row-span-xs-5) {
  grid-row: span 5 / span 5;
}

:is(.row-span-6, .row-span-xs-6) {
  grid-row: span 6 / span 6;
}

:is(.row-span-7, .row-span-xs-7) {
  grid-row: span 7 / span 7;
}

:is(.row-span-8, .row-span-xs-8) {
  grid-row: span 8 / span 8;
}

:is(.row-span-9, .row-span-xs-9) {
  grid-row: span 9 / span 9;
}

:is(.row-span-10, .row-span-xs-10) {
  grid-row: span 10 / span 10;
}

:is(.row-span-11, .row-span-xs-11) {
  grid-row: span 11 / span 11;
}

:is(.row-span-12, .row-span-xs-12) {
  grid-row: span 12 / span 12;
}

/* Nur als -xs-Variante vorhanden (kein unpraefigiertes Pendant im
   Original) – bewusst ohne @media (min-width: 0), da das ohnehin immer
   zutrifft */
.col-start-xs-1 { grid-column-start: 1; }
.col-start-xs-2 { grid-column-start: 2; }
.col-start-xs-3 { grid-column-start: 3; }
.col-start-xs-4 { grid-column-start: 4; }
.col-start-xs-5 { grid-column-start: 5; }
.col-start-xs-6 { grid-column-start: 6; }
.col-start-xs-7 { grid-column-start: 7; }
.col-start-xs-8 { grid-column-start: 8; }
.col-start-xs-9 { grid-column-start: 9; }
.col-start-xs-10 { grid-column-start: 10; }
.col-start-xs-11 { grid-column-start: 11; }
.col-start-xs-12 { grid-column-start: 12; }

.pull-right-xs { grid-column-end: -1; }
.pull-left-xs {
  grid-row-start: 1;
  grid-column-end: inherit;
}

/* -- Breakpoint sm (--bp-sm) -- */
@media screen and (min-width: 34.375em) {
  .col-sm-1 { grid-column: span 1 / span 1; }
  .col-sm-2 { grid-column: span 2 / span 2; }
  .col-sm-3 { grid-column: span 3 / span 3; }
  .col-sm-4 { grid-column: span 4 / span 4; }
  .col-sm-5 { grid-column: span 5 / span 5; }
  .col-sm-6 { grid-column: span 6 / span 6; }
  .col-sm-7 { grid-column: span 7 / span 7; }
  .col-sm-8 { grid-column: span 8 / span 8; }
  .col-sm-9 { grid-column: span 9 / span 9; }
  .col-sm-10 { grid-column: span 10 / span 10; }
  .col-sm-11 { grid-column: span 11 / span 11; }
  .col-sm-12 { grid-column: span 12 / span 12; }

  .row-span-sm-1 { grid-row: span 1 / span 1; }
  .row-span-sm-2 { grid-row: span 2 / span 2; }
  .row-span-sm-3 { grid-row: span 3 / span 3; }
  .row-span-sm-4 { grid-row: span 4 / span 4; }
  .row-span-sm-5 { grid-row: span 5 / span 5; }
  .row-span-sm-6 { grid-row: span 6 / span 6; }
  .row-span-sm-7 { grid-row: span 7 / span 7; }
  .row-span-sm-8 { grid-row: span 8 / span 8; }
  .row-span-sm-9 { grid-row: span 9 / span 9; }
  .row-span-sm-10 { grid-row: span 10 / span 10; }
  .row-span-sm-11 { grid-row: span 11 / span 11; }
  .row-span-sm-12 { grid-row: span 12 / span 12; }

  .col-start-sm-1 { grid-column-start: 1; }
  .row-start-sm-1 { grid-row-start: 1; }
  .col-start-sm-2 { grid-column-start: 2; }
  .row-start-sm-2 { grid-row-start: 2; }
  .col-start-sm-3 { grid-column-start: 3; }
  .row-start-sm-3 { grid-row-start: 3; }
  .col-start-sm-4 { grid-column-start: 4; }
  .row-start-sm-4 { grid-row-start: 4; }
  .col-start-sm-5 { grid-column-start: 5; }
  .row-start-sm-5 { grid-row-start: 5; }
  .col-start-sm-6 { grid-column-start: 6; }
  .row-start-sm-6 { grid-row-start: 6; }
  .col-start-sm-7 { grid-column-start: 7; }
  .row-start-sm-7 { grid-row-start: 7; }
  .col-start-sm-8 { grid-column-start: 8; }
  .row-start-sm-8 { grid-row-start: 8; }
  .col-start-sm-9 { grid-column-start: 9; }
  .row-start-sm-9 { grid-row-start: 9; }
  .col-start-sm-10 { grid-column-start: 10; }
  .row-start-sm-10 { grid-row-start: 10; }
  .col-start-sm-11 { grid-column-start: 11; }
  .row-start-sm-11 { grid-row-start: 11; }
  .col-start-sm-12 { grid-column-start: 12; }
  .row-start-sm-12 { grid-row-start: 12; }

  .pull-right-sm { grid-column-end: -1; }
  .pull-left-sm {
    grid-row-start: 1;
    grid-column-end: inherit;
  }
}

/* -- Breakpoint md (--bp-md) -- */
@media screen and (min-width: 48em) {
  .col-md-1 { grid-column: span 1 / span 1; }
  .col-md-2 { grid-column: span 2 / span 2; }
  .col-md-3 { grid-column: span 3 / span 3; }
  .col-md-4 { grid-column: span 4 / span 4; }
  .col-md-5 { grid-column: span 5 / span 5; }
  .col-md-6 { grid-column: span 6 / span 6; }
  .col-md-7 { grid-column: span 7 / span 7; }
  .col-md-8 { grid-column: span 8 / span 8; }
  .col-md-9 { grid-column: span 9 / span 9; }
  .col-md-10 { grid-column: span 10 / span 10; }
  .col-md-11 { grid-column: span 11 / span 11; }
  .col-md-12 { grid-column: span 12 / span 12; }

  .row-span-md-1 { grid-row: span 1 / span 1; }
  .row-span-md-2 { grid-row: span 2 / span 2; }
  .row-span-md-3 { grid-row: span 3 / span 3; }
  .row-span-md-4 { grid-row: span 4 / span 4; }
  .row-span-md-5 { grid-row: span 5 / span 5; }
  .row-span-md-6 { grid-row: span 6 / span 6; }
  .row-span-md-7 { grid-row: span 7 / span 7; }
  .row-span-md-8 { grid-row: span 8 / span 8; }
  .row-span-md-9 { grid-row: span 9 / span 9; }
  .row-span-md-10 { grid-row: span 10 / span 10; }
  .row-span-md-11 { grid-row: span 11 / span 11; }
  .row-span-md-12 { grid-row: span 12 / span 12; }

  .col-start-md-1 { grid-column-start: 1; }
  .row-start-md-1 { grid-row-start: 1; }
  .col-start-md-2 { grid-column-start: 2; }
  .row-start-md-2 { grid-row-start: 2; }
  .col-start-md-3 { grid-column-start: 3; }
  .row-start-md-3 { grid-row-start: 3; }
  .col-start-md-4 { grid-column-start: 4; }
  .row-start-md-4 { grid-row-start: 4; }
  .col-start-md-5 { grid-column-start: 5; }
  .row-start-md-5 { grid-row-start: 5; }
  .col-start-md-6 { grid-column-start: 6; }
  .row-start-md-6 { grid-row-start: 6; }
  .col-start-md-7 { grid-column-start: 7; }
  .row-start-md-7 { grid-row-start: 7; }
  .col-start-md-8 { grid-column-start: 8; }
  .row-start-md-8 { grid-row-start: 8; }
  .col-start-md-9 { grid-column-start: 9; }
  .row-start-md-9 { grid-row-start: 9; }
  .col-start-md-10 { grid-column-start: 10; }
  .row-start-md-10 { grid-row-start: 10; }
  .col-start-md-11 { grid-column-start: 11; }
  .row-start-md-11 { grid-row-start: 11; }
  .col-start-md-12 { grid-column-start: 12; }
  .row-start-md-12 { grid-row-start: 12; }

  .pull-right-md { grid-column-end: -1; }
  .pull-left-md {
    grid-row-start: 1;
    grid-column-end: inherit;
  }
}

/* -- Breakpoint lg (--bp-lg) -- */
@media screen and (min-width: 58.75em) {
  .col-lg-1 { grid-column: span 1 / span 1; }
  .col-lg-2 { grid-column: span 2 / span 2; }
  .col-lg-3 { grid-column: span 3 / span 3; }
  .col-lg-4 { grid-column: span 4 / span 4; }
  .col-lg-5 { grid-column: span 5 / span 5; }
  .col-lg-6 { grid-column: span 6 / span 6; }
  .col-lg-7 { grid-column: span 7 / span 7; }
  .col-lg-8 { grid-column: span 8 / span 8; }
  .col-lg-9 { grid-column: span 9 / span 9; }
  .col-lg-10 { grid-column: span 10 / span 10; }
  .col-lg-11 { grid-column: span 11 / span 11; }
  .col-lg-12 { grid-column: span 12 / span 12; }

  .row-span-lg-1 { grid-row: span 1 / span 1; }
  .row-span-lg-2 { grid-row: span 2 / span 2; }
  .row-span-lg-3 { grid-row: span 3 / span 3; }
  .row-span-lg-4 { grid-row: span 4 / span 4; }
  .row-span-lg-5 { grid-row: span 5 / span 5; }
  .row-span-lg-6 { grid-row: span 6 / span 6; }
  .row-span-lg-7 { grid-row: span 7 / span 7; }
  .row-span-lg-8 { grid-row: span 8 / span 8; }
  .row-span-lg-9 { grid-row: span 9 / span 9; }
  .row-span-lg-10 { grid-row: span 10 / span 10; }
  .row-span-lg-11 { grid-row: span 11 / span 11; }
  .row-span-lg-12 { grid-row: span 12 / span 12; }

  .col-start-lg-1 { grid-column-start: 1; }
  .row-start-lg-1 { grid-row-start: 1; }
  .col-start-lg-2 { grid-column-start: 2; }
  .row-start-lg-2 { grid-row-start: 2; }
  .col-start-lg-3 { grid-column-start: 3; }
  .row-start-lg-3 { grid-row-start: 3; }
  .col-start-lg-4 { grid-column-start: 4; }
  .row-start-lg-4 { grid-row-start: 4; }
  .col-start-lg-5 { grid-column-start: 5; }
  .row-start-lg-5 { grid-row-start: 5; }
  .col-start-lg-6 { grid-column-start: 6; }
  .row-start-lg-6 { grid-row-start: 6; }
  .col-start-lg-7 { grid-column-start: 7; }
  .row-start-lg-7 { grid-row-start: 7; }
  .col-start-lg-8 { grid-column-start: 8; }
  .row-start-lg-8 { grid-row-start: 8; }
  .col-start-lg-9 { grid-column-start: 9; }
  .row-start-lg-9 { grid-row-start: 9; }
  .col-start-lg-10 { grid-column-start: 10; }
  .row-start-lg-10 { grid-row-start: 10; }
  .col-start-lg-11 { grid-column-start: 11; }
  .row-start-lg-11 { grid-row-start: 11; }
  .col-start-lg-12 { grid-column-start: 12; }
  .row-start-lg-12 { grid-row-start: 12; }

  .pull-right-lg { grid-column-end: -1; }
  .pull-left-lg {
    grid-row-start: 1;
    grid-column-end: inherit;
  }
}

/* -- Breakpoint xl (--bp-xl) -- */
@media screen and (min-width: 68.75em) {
  .col-xl-1 { grid-column: span 1 / span 1; }
  .col-xl-2 { grid-column: span 2 / span 2; }
  .col-xl-3 { grid-column: span 3 / span 3; }
  .col-xl-4 { grid-column: span 4 / span 4; }
  .col-xl-5 { grid-column: span 5 / span 5; }
  .col-xl-6 { grid-column: span 6 / span 6; }
  .col-xl-7 { grid-column: span 7 / span 7; }
  .col-xl-8 { grid-column: span 8 / span 8; }
  .col-xl-9 { grid-column: span 9 / span 9; }
  .col-xl-10 { grid-column: span 10 / span 10; }
  .col-xl-11 { grid-column: span 11 / span 11; }
  .col-xl-12 { grid-column: span 12 / span 12; }

  .row-span-xl-1 { grid-row: span 1 / span 1; }
  .row-span-xl-2 { grid-row: span 2 / span 2; }
  .row-span-xl-3 { grid-row: span 3 / span 3; }
  .row-span-xl-4 { grid-row: span 4 / span 4; }
  .row-span-xl-5 { grid-row: span 5 / span 5; }
  .row-span-xl-6 { grid-row: span 6 / span 6; }
  .row-span-xl-7 { grid-row: span 7 / span 7; }
  .row-span-xl-8 { grid-row: span 8 / span 8; }
  .row-span-xl-9 { grid-row: span 9 / span 9; }
  .row-span-xl-10 { grid-row: span 10 / span 10; }
  .row-span-xl-11 { grid-row: span 11 / span 11; }
  .row-span-xl-12 { grid-row: span 12 / span 12; }

  .col-start-xl-1 { grid-column-start: 1; }
  .row-start-xl-1 { grid-row-start: 1; }
  .col-start-xl-2 { grid-column-start: 2; }
  .row-start-xl-2 { grid-row-start: 2; }
  .col-start-xl-3 { grid-column-start: 3; }
  .row-start-xl-3 { grid-row-start: 3; }
  .col-start-xl-4 { grid-column-start: 4; }
  .row-start-xl-4 { grid-row-start: 4; }
  .col-start-xl-5 { grid-column-start: 5; }
  .row-start-xl-5 { grid-row-start: 5; }
  .col-start-xl-6 { grid-column-start: 6; }
  .row-start-xl-6 { grid-row-start: 6; }
  .col-start-xl-7 { grid-column-start: 7; }
  .row-start-xl-7 { grid-row-start: 7; }
  .col-start-xl-8 { grid-column-start: 8; }
  .row-start-xl-8 { grid-row-start: 8; }
  .col-start-xl-9 { grid-column-start: 9; }
  .row-start-xl-9 { grid-row-start: 9; }
  .col-start-xl-10 { grid-column-start: 10; }
  .row-start-xl-10 { grid-row-start: 10; }
  .col-start-xl-11 { grid-column-start: 11; }
  .row-start-xl-11 { grid-row-start: 11; }
  .col-start-xl-12 { grid-column-start: 12; }
  .row-start-xl-12 { grid-row-start: 12; }

  .pull-right-xl { grid-column-end: -1; }
  .pull-left-xl {
    grid-row-start: 1;
    grid-column-end: inherit;
  }
}

/* Ausrichtung innerhalb der Grid-Zelle, Basis-Tier inkl. -xs-Pendants */
:is(.justify-start, .justify-xs-start) {
  justify-self: start;
  text-align: left;
}

:is(.justify-center, .justify-xs-center) {
  justify-self: center;
  text-align: center;
}

:is(.justify-end, .justify-xs-end) {
  justify-self: end;
  text-align: right;
}

:is(.align-start, .align-xs-start) {
  align-self: start;
}

:is(.align-center, .align-xs-center) {
  align-self: center;
}

:is(.align-end, .align-xs-end) {
  align-self: end;
}

@media screen and (min-width: 34.375em) {
  .justify-sm-start {
    justify-self: start;
    text-align: left;
  }
  .justify-sm-center {
    justify-self: center;
    text-align: center;
  }
  .justify-sm-end {
    justify-self: end;
    text-align: right;
  }

  .align-sm-start { align-self: start; }
  .align-sm-center { align-self: center; }
  .align-sm-end { align-self: end; }
}

@media screen and (min-width: 48em) {
  .justify-md-start {
    justify-self: start;
    text-align: left;
  }
  .justify-md-center {
    justify-self: center;
    text-align: center;
  }
  .justify-md-end {
    justify-self: end;
    text-align: right;
  }

  .align-md-start { align-self: start; }
  .align-md-center { align-self: center; }
  .align-md-end { align-self: end; }
}

@media screen and (min-width: 58.75em) {
  .justify-lg-start {
    justify-self: start;
    text-align: left;
  }
  .justify-lg-center {
    justify-self: center;
    text-align: center;
  }
  .justify-lg-end {
    justify-self: end;
    text-align: right;
  }

  .align-lg-start { align-self: start; }
  .align-lg-center { align-self: center; }
  .align-lg-end { align-self: end; }
}

@media screen and (min-width: 68.75em) {
  .justify-xl-start {
    justify-self: start;
    text-align: left;
  }
  .justify-xl-center {
    justify-self: center;
    text-align: center;
  }
  .justify-xl-end {
    justify-self: end;
    text-align: right;
  }

  .align-xl-start { align-self: start; }
  .align-xl-center { align-self: center; }
  .align-xl-end { align-self: end; }
}

/* Vertikale Ausrichtung von Grid-Items innerhalb einer .row (nicht zu
   verwechseln mit .row-start-N, das die Startzeile eines Items setzt!) */
.row-align-start {
  align-self: start;
}

.row-align-center {
  align-content: center;
}

/*
 * Buttons – übernommen aus Open Props (src/extra/buttons.css), mit CSS-Nesting
 * wie in der Quelle. Light/Dark über prefers-color-scheme. Gestylt werden alle
 * nativen Buttons (button, input[type=button|submit|reset], input[type=file])
 * sowie die Klasse .btn, die bei Bedarf manuell vergeben werden kann (z. B. als
 * CSS-Klasse eines Hyperlink-Elements im Contao-Backend). Alles steht in
 * :where() und hat damit Spezifität 0 – Vendor-CSS (z. B. handorgel) und
 * Themes überschreiben es ohne Spezifitäts-Rennen.
 *
 * Abweichungen vom Original:
 *  - Farb-Tokens zeigen auf unser Schema (--clr-surface-1 bis -3, --clr-link,
 *    --clr-text-2) statt auf --surface-N, --link und --text-2 aus der
 *    Open-Props-normalize.css, die es bei uns nicht mehr gibt. Die übrigen
 *    Rohfarben (--gray-N, --red-N) bleiben wie im Original.
 *  - Die Selektorliste steht einmal als @custom-selector (:--ctf-btn) statt
 *    in jeder Regel neu.
 *  - @media (--OSdark) heißt hier ausgeschrieben prefers-color-scheme: dark.
 *  - Das ::-webkit-file-upload-button-Präfix entfällt, alle aktuellen Browser
 *    kennen ::file-selector-button.
 *  - Sämtliche Transitions stehen gebündelt am Ende der Datei (siehe dort).
 */

/* Alles, was wie ein Button aussieht. Neben den nativen Buttons und .btn
   stehen hier die Contao-Elemente, die Contao selbst als Link ausgibt, aber
   als Button zeigen soll – hier ergänzen, was zusätzlich dazu gehören soll.
   - .content-toplink a: "Nach oben"-Link (content_element/toplink.html.twig)
   - a.submit: als Link ausgegebene Submit-Aktionen, z. B. "Abbrechen" und
     "Bearbeiten" in content_element/two_factor.html.twig */

:where(html) {
  --gray-0-hsl: 210 17% 98%;
  --gray-1-hsl: 210 17% 95%;
  --gray-2-hsl: 210 16% 93%;
  --gray-3-hsl: 210 14% 89%;
  --gray-4-hsl: 210 14% 83%;
  --gray-5-hsl: 210 11% 71%;
  --gray-6-hsl: 210 7% 56%;
  --gray-7-hsl: 210 9% 31%;
  --gray-8-hsl: 210 10% 23%;
  --gray-9-hsl: 210 11% 15%;
  --gray-10-hsl: 214 14% 10%;
  --gray-11-hsl: 216 16% 6%;
  --gray-12-hsl: 210 40% 2%;
}

/* Grundaussehen: Variablen mit Unterstrich (--_*) sind intern und lassen
   sich pro Button überschreiben (z. B. --_accent, --_size, --_bg).
   Der Datei-Upload-Button ist ein Pseudo-Element und kann nicht per & an die
   Liste hängen, steht deshalb mit im Selektor dieser einen Regel. */
:where(:is(button, input[type="button"], input[type="submit"], input[type="reset"], .btn, .content-toplink a, a.submit)),
:where(input[type="file"])::file-selector-button {
  --_accent: initial;
  --_text: initial;
  --_size: initial;
  --_bg-light: white;
  --_bg-dark: var(--clr-surface-3);
  --_bg: var(--_bg-light);
  --_border: var(--clr-surface-3);
  --_highlight-size: 0;
  --_highlight-light: hsl(var(--gray-5-hsl) / 25%);
  --_highlight-dark: hsl(var(--gray-12-hsl) / 25%);
  --_highlight: var(--_highlight-light);
  --_ink-shadow-light: 0 1px 0 var(--gray-3);
  --_ink-shadow-dark: 0 1px 0 var(--clr-surface-1);
  --_ink-shadow: var(--_ink-shadow-light);
  --_icon-size: var(--size-relative-7);
  --_icon-color: var(--_accent, var(--clr-link));
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
  align-items: center;
  background: var(--_bg);
  border: var(--border-size-2) solid var(--_border);
  border-radius: var(--radius-2);
  box-shadow: var(--shadow-2), 0 1px var(--clr-surface-3), 0 0 0 var(--_highlight-size) var(--_highlight);
  color: var(--_text);
  display: inline-flex;
  font-size: var(--_size);
  font-weight: var(--font-weight-7);
  gap: var(--size-2);
  justify-content: center;
  padding-block: 0.75ch;
  padding-inline: var(--size-relative-6);
  text-align: center;
  text-shadow: var(--_ink-shadow);
  -webkit-user-select: none;
     -moz-user-select: none;
          user-select: none;

  @media (prefers-color-scheme: dark) {
    --_highlight: var(--_highlight-dark);
    --_bg: var(--_bg-dark);
    --_ink-shadow: var(--_ink-shadow-dark);
  }
}

:where(:is(button, input[type="button"], input[type="submit"], input[type="reset"], .btn, .content-toplink a, a.submit)) {
  /* Hover: der Highlight-Ring wächst von 0 auf --size-2 */
  &:where(:not(:active):hover) {
    --_highlight-size: var(--size-2);
  }

  /* Icons (inline-SVG) direkt im Button */
  & > :where(svg) {
    block-size: var(--_icon-size);
    filter: drop-shadow(var(--_ink-shadow));
    flex-shrink: 0;
    inline-size: var(--_icon-size);

    & > * {
      stroke: var(--_icon-color);
      stroke-width: var(--border-size-2);
    }
  }
}

/* Links im Button-Look nicht unterstreichen */
:where(a:is(button, input[type="button"], input[type="submit"], input[type="reset"], .btn, .content-toplink a, a.submit)) {
  -webkit-text-decoration: none;
  text-decoration: none;
}

/* Deaktiviert (nur echte Formular-Buttons, Links kennen kein [disabled]) */
[disabled]:where(:is(button, input[type="button"], input[type="submit"], input[type="reset"], .btn, .content-toplink a, a.submit)) {
  --_bg: none;
  --_text: var(--gray-6);
  box-shadow: var(--shadow-1);
  cursor: not-allowed;

  @media (prefers-color-scheme: dark) {
    --_text: var(--gray-5);
  }
}

/* Absenden-Buttons (auch als Link ausgegebene, a.submit) in Akzentfarbe */
:where([type="submit"], a.submit, form button:not([type]):not([disabled])) {
  --_text: var(--_accent, var(--clr-link));
}

/* Zurücksetzen-Buttons in Rot */
:where([type="reset"]) {
  --_text: var(--red-6);
  --_border: var(--red-3);

  &:focus-visible {
    outline-color: var(--red-6);
  }

  @media (prefers-color-scheme: dark) {
    --_text: var(--red-2);
    --_border: var(--clr-surface-3);
  }
}

/* Hover/Fokus: Rahmen nimmt die Textfarbe an */
:where(form button:not([type]), [type="submit"], a.submit, [type="reset"]) {
  &:is(:hover, :focus-visible):not([disabled]) {
    --_border: currentColor;
  }
}

/* Datei-Upload */
:where(input[type="file"]) {
  align-self: flex-start;
  border: var(--border-size-1) solid var(--clr-surface-2);
  border-radius: var(--radius-2);
  box-shadow: var(--inner-shadow-4);
  color: var(--clr-text-2);
  cursor: auto;
  cursor: initial;
  max-inline-size: 100%;
  padding: 0;

  &::file-selector-button {
    cursor: pointer;
    margin-inline-end: var(--size-relative-6);
  }
}

/* Dark: Hintergrund für deaktivierte, Reset-, Submit- und Formular-Buttons */
@media (prefers-color-scheme: dark) {
  :where([disabled], [type="reset"], [type="submit"], form button:not([type="button"])) {
    --_bg: var(--clr-surface-1);
  }
}

/*
 * Bewegung. Bewusste Ausnahme von der Regel "keine Easings/Animationen" aus
 * CLAUDE.md: Die Button-Transitions aus Open Props bleiben im Framework. Im
 * Original über die ganze Datei verteilt, hier gebündelt. Ein Theme, das sie
 * nicht will, löscht einfach diesen Abschnitt: die Buttons funktionieren
 * unverändert, Zustandswechsel (Hover, Fokus) passieren dann ohne Übergang.
 */
:where(:is(button, input[type="button"], input[type="submit"], input[type="reset"], .btn, .content-toplink a, a.submit)),
:where(input[type="file"])::file-selector-button {
  transition: border-color 0.5s var(--ease-3);

  @media (prefers-reduced-motion: no-preference) {
    transition:
      border-color 0.5s var(--ease-3),
      box-shadow 145ms var(--ease-4),
      outline-offset 145ms var(--ease-4);
  }
}

:where(:is(button, input[type="button"], input[type="submit"], input[type="reset"], .btn, .content-toplink a, a.submit)):where(:not(:active):hover) {
  transition-duration: 0.25s;
}

/* contao: Klassen aus den Contao-Core-Templates */

/*
 * Textbasierte Inhaltselemente: content-text, content-html, content-code,
 * content-hyperlink, content-list, content-table, content-teaser, content-toplink
 * (twig/content_element/text.html.twig, code.html.twig, list.html.twig, table.html.twig,
 * teaser.html.twig, toplink.html.twig, twig/component/_read_more.html.twig).
 *
 * Wichtig: Die Wrapper-Klasse jedes Inhaltselements wird von
 * content_element/_base.html.twig dynamisch aus dem Elementtyp gebaut:
 * "content-#{type}" (Unterstriche im Typ werden zu Bindestrichen), also z. B.
 * content-text, content-download, content-element-group. Keine ce_*-Klassen mehr!
 *
 * Der Abstand zwischen den Inhaltselementen kommt zentral aus dem
 * vertikalen Rhythmus in base/typography.css, nicht aus einzelnen
 * margin-block-end-Regeln hier.
 */

/* content-text: dieselbe Maßbegrenzung wie :where(p) in generic/normalize.css,
   aber auf dem Wrapper statt nur auf <p>. <p> und <figure> sind Geschwister
   im selben Wrapper (siehe unten) – ohne das hier läuft <p> auf seine eigene,
   schmalere max-inline-size, während ein gefloatetes <figure> sich am
   (breiteren) Containing Block des Wrappers ausrichtet. Zwei unabhängige
   Breiten, die besonders bei einspaltigem Layout auseinanderlaufen: das Bild
   "rutscht" zum entfernten Wrapper-Rand, der Text bleibt davon losgelöst
   schmal. Mit der Grenze auf dem Wrapper teilen sich Bild und Text denselben
   Containing Block – kein Sonderfall für "einspaltig" nötig. */
.content-text {
  max-inline-size: var(--ctf-measure);
}

/* Bild im Fließtext per Layout-Modifier "media media--{above|left|right|below}".
   Die Modifier-Klasse sitzt am content-text-Wrapper selbst (content_layout_attributes
   in text.html.twig), das Bild liegt als <figure> darin – daher float auf dem
   Nachfahren, nicht auf der Modifier-Klasse. flow-root auf dem Wrapper statt eines
   Clearfix-Hacks, damit das gefloatete Bild ihn nicht nach unten überragt.
   .media--above/.media--below brauchen keine eigene Regel mehr: die Reihenfolge von
   Bild und Text im Markup ändert sich zwar, der Abstand dazwischen kommt aber
   bereits aus dem vertikalen Rhythmus in base/typography.css. */
:is(.media--left, .media--right) {
  display: flow-root;
}

.media--left figure {
  float: left;
  margin-inline-end: var(--size-4);
}

.media--right figure {
  float: right;
  margin-inline-start: var(--size-4);
}

/* content-code: Syntax-Highlighting per highlight.js (Klasse .hljs kommt von dort) */
.content-code pre {
  padding: var(--size-3);
  background-color: var(--clr-surface-2);
  border-radius: var(--radius-2);
  overflow-x: auto;
}

/* content-list/-table: reine semantische Elemente, Grundstyling kommt bereits
   aus der Open-Props-normalize.css (ul/ol/table/th/td) */

/* content-teaser: der "Weiterlesen"-Link ist ein unstyled <a> (component/_read_more.html.twig) */
.content-teaser a {
  font-weight: var(--font-weight-6);
}

/* content-toplink: "Nach oben"-Link, per [data-toplink] statt fester Klasse erkannt */
.content-toplink {
  text-align: end;
}
/*
 * Medien-Inhaltselemente: content-image, content-gallery, content-player,
 * content-youtube, content-vimeo (twig/content_element/image.html.twig,
 * gallery.html.twig, player.html.twig, _video.html.twig, twig/component/_figure.html.twig).
 *
 * figure/figcaption/img/picture bleiben bewusst ohne eigene Wrapper-Klassen
 * (component/_figure.html.twig gibt keine vor) – das Grundstyling kommt aus
 * der Open-Props-normalize.css. Der Abstand zwischen den Inhaltselementen
 * kommt zentral aus dem vertikalen Rhythmus in base/typography.css.
 */

/* content-gallery: Spaltenzahl kommt als BEM-Modifier auf dem Wrapper-Div an
   (content-gallery--cols-N, 1–12 laut tl_content.perRow), nicht mehr auf dem <ul> */
.content-gallery ul {
  display: grid;
  grid-template-columns: repeat(var(--ctf-cols, 4), 1fr);
  grid-gap: var(--size-4);
  gap: var(--size-4);
  padding-inline-start: 0;
  list-style: none;
}

.content-gallery[class~="content-gallery--cols-1"] ul { --ctf-cols: 1; }
.content-gallery[class~="content-gallery--cols-2"] ul { --ctf-cols: 2; }
.content-gallery[class~="content-gallery--cols-3"] ul { --ctf-cols: 3; }
.content-gallery[class~="content-gallery--cols-4"] ul { --ctf-cols: 4; }
.content-gallery[class~="content-gallery--cols-5"] ul { --ctf-cols: 5; }
.content-gallery[class~="content-gallery--cols-6"] ul { --ctf-cols: 6; }
.content-gallery[class~="content-gallery--cols-7"] ul { --ctf-cols: 7; }
.content-gallery[class~="content-gallery--cols-8"] ul { --ctf-cols: 8; }
.content-gallery[class~="content-gallery--cols-9"] ul { --ctf-cols: 9; }
.content-gallery[class~="content-gallery--cols-10"] ul { --ctf-cols: 10; }
.content-gallery[class~="content-gallery--cols-11"] ul { --ctf-cols: 11; }
.content-gallery[class~="content-gallery--cols-12"] ul { --ctf-cols: 12; }

/* Container Query: unabhängig von der konfigurierten Spaltenzahl nie enger
   als eine Mindestbreite pro Spalte werden lassen (z. B. schmale Sidebar) */
.content-gallery {
  container-type: inline-size;
}

@container (width < 30rem) {
  .content-gallery ul {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* content-youtube/content-vimeo: Seitenverhältnis über die aspect--"16:9"-Klasse.
   Der Doppelpunkt aus den Contao-Optionen (16:9, 4:3, 21:9 …) ist nur als
   Attribut-Selektor sicher zu matchen, nicht als CSS-Bezeichner */
.aspect {
  position: relative;
  aspect-ratio: var(--ctf-aspect-ratio, 16 / 9);
}

.aspect[class~="aspect--16:9"] { --ctf-aspect-ratio: 16 / 9; }
.aspect[class~="aspect--16:10"] { --ctf-aspect-ratio: 16 / 10; }
.aspect[class~="aspect--21:9"] { --ctf-aspect-ratio: 21 / 9; }
.aspect[class~="aspect--4:3"] { --ctf-aspect-ratio: 4 / 3; }
.aspect[class~="aspect--3:2"] { --ctf-aspect-ratio: 3 / 2; }
.aspect[class~="aspect--9:16"] { --ctf-aspect-ratio: 9 / 16; }
.aspect[class~="aspect--1:1"] { --ctf-aspect-ratio: 1 / 1; }

.aspect iframe {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
}

/* content-player: lokale Video-/Audio-Dateien ohne aspect-ratio-Zwang */
.content-player :is(video, audio) {
  inline-size: 100%;
}
/*
 * content-download / content-downloads: einzelne bzw. mehrere Dateien zum
 * Herunterladen (twig/content_element/download.html.twig, downloads.html.twig,
 * twig/component/_download.html.twig). Die .download-element/.ext-<ext>-Klassen
 * sitzen weiterhin auf dem Wrapper bzw. den Listenelementen.
 *
 * component/_download.html.twig gibt nur einen Link aus (plus optionale
 * Vorschaubilder bei show_file_previews) – kein .size-Element wie im alten
 * Legacy-Template. Vorschaubilder sind bewusst nicht gestylt: Sonderfall,
 * der ins Theme gehört, nicht in dieses Basis-Framework.
 */

.content-downloads ul {
  padding-inline-start: 0;
  list-style: none;
}

/* Generisches Datei-Icon aus Contaos eigenem Icon-Satz. iconPLAIN.svg ist der
   extensionsunabhängige Fallback; ein Theme kann .ext-pdf/.ext-zip/... gezielt
   mit den passenden Icons (iconPDF.svg, iconZIP.svg, ...) überschreiben.
   Absoluter Pfad ab Domain-Root, da diese Dateien unabhängig vom Ablageort
   der kompilierten CSS-Datei immer an derselben Stelle liegen.
   background-position bleibt bewusst physisch ("left", nicht "start"): CSS
   kennt für Hintergrundbilder noch keine logische Positionierung. */
.download-element {
  padding-inline-start: 1.25em;
  background: url("/assets/contao/images/iconPLAIN.svg") no-repeat left center;
  background-size: 1em;
}

/* Beispiel für ein dateityp-spezifisches Icon: PDF ist der mit Abstand
   häufigste Downloadtyp. Überschreibt nur background-image, Position/Größe
   bleiben vom generischen Fallback oben geerbt. Weitere Typen (.ext-zip,
   .ext-docx, ...) nach demselben Muster bei Bedarf ergänzen. */
.download-element.ext-pdf {
  background-image: url("/assets/contao/images/iconPDF.svg");
}
/*
 * content-accordion / content-swiper: seit Contao 5 laufen Akkordeon und
 * Slider über Drittanbieter-Bibliotheken (handorgel bzw. Swiper), die ihr
 * eigenes CSS mitbringen (twig/content_element/accordion.html.twig,
 * swiper.html.twig – jeweils per {% add … to stylesheets %} eingebunden).
 * Wir überschreiben hier bewusst nichts von deren Innenleben – der Abstand
 * zu benachbarten Inhaltselementen kommt zentral aus dem vertikalen
 * Rhythmus in base/typography.css.
 */
/*
 * mod_navigation und mod_customnav (twig/mod_navigation.html.twig,
 * twig/nav_default.html.twig). Breadcrumb, Artikel-Pagination und Buch-
 * Navigation haben eigene Dateien (breadcrumb.css, pagination.css, booknav.css).
 *
 * Markup, das Contao ausgibt:
 *   <nav class="mod_navigation block [eigene Klasse]">
 *     <ul class="level_1">
 *       <li class="submenu trail"><a class="submenu trail" aria-haspopup="true">…</a>
 *         <ul class="level_2"> … </ul></li>
 *       <li class="active"><strong class="active">…</strong></li>   (aktuelle Seite)
 *       <li class="forward"><a class="forward">…</a></li>            (Weiterleitung)
 *
 * Zwei Stufen:
 *  1. Grundstil für jede Navigation (ohne Zusatzklasse): Liste ohne
 *     Aufzählungszeichen, Einträge nebeneinander.
 *  2. Hauptnavigation: Im Navigationsmodul unter "CSS-Klasse" nav--main
 *     eintragen. Ab --bp-nav waagerechte Leiste mit Dropdown für level_2,
 *     darunter untereinander. Ohne Zusatzklassen funktioniert sie bereits;
 *     für den Mobil-Schalter siehe "Mobile Ansicht" weiter unten.
 *
 * Bewusst ohne Übergänge/Animationen (Theme-Sache).
 */

/* Ab dieser Breite wird aus dem Mobil-Menü die waagerechte Leiste. Wert hier
   ändern, wenn die Navigation mehr/weniger Platz braucht */
/* Gegenstück für "schmaler als --bp-nav" (ein "not (--bp-nav)" lässt sich
   nicht zuverlässig bauen). Beide Werte zusammen ändern: 52em -> 51.99em */

/* --- 1. Grundstil für jede Navigation --- */
:is(.mod_navigation, .mod_customnav) {
  & ul {
    display: flex;
    flex-wrap: wrap;
    gap: var(--size-2);
    padding-inline-start: 0;
    list-style: none;
  }

  & li {
    padding-inline-start: 0;
  }

  /* Verschachtelte Ebenen (level_2, level_3 …) untereinander statt nebeneinander */
  & li ul {
    flex-direction: column;
    inline-size: 100%;
  }

  /* Aktuelle Seite (strong.active) und Pfad dorthin (.trail) hervorheben */
  & :is(strong.active, a.trail, strong.trail, strong.forward) {
    font-weight: var(--font-weight-7);
  }

  & a {
    -webkit-text-decoration: none;
    text-decoration: none;

    &:hover {
      -webkit-text-decoration: underline;
      text-decoration: underline;
    }
  }
}

/* --- 2. Hauptnavigation --- */
.nav--main {
  /* Mobil: eine Spalte, level_1 untereinander */
  & ul {
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
  }

  & :is(a, strong) {
    display: block;
    padding: var(--size-2) var(--size-3);
  }

  /* Eintrag mit Unterebene: kleiner Pfeil hinter dem Text. Aus Rahmenlinien
     gebaut statt aus einer Bilddatei, damit keine Icon-Datei nötig ist und
     der Pfeil die Textfarbe annimmt */
  & li.submenu > :is(a, strong) {
    display: flex;
    align-items: center;
    gap: var(--size-2);

    &::after {
      content: "";
      inline-size: 0.5em;
      block-size: 0.5em;
      border-inline-end: 2px solid currentColor;
      border-block-end: 2px solid currentColor;
      rotate: 45deg;
      translate: 0 -0.15em;
    }
  }

  /* Unterebene mobil eingerückt */
  & .level_2 {
    padding-inline-start: var(--size-4);
  }

  @media screen and (min-width: 52em) {
    & .level_1 {
      flex-direction: row;
      flex-wrap: wrap;
      gap: var(--size-2);

      & > li {
        position: relative;

        & > :is(a, strong) {
          white-space: nowrap;
        }
      }
    }

    /* Dropdown: aus dem Fluss genommen, standardmäßig ausgeblendet.
       display:none nimmt das Menü zugleich aus der Tab-Reihenfolge; per
       :hover und :focus-within (Tastatur) wird es sichtbar. */
    & .level_2 {
      display: none;
      position: absolute;
      inset-inline-start: 0;
      inset-block-start: 100%;
      z-index: 10;
      min-inline-size: 11rem;
      padding-inline-start: 0;
      background: var(--clr-surface-1);
      border: var(--border-size-1) solid var(--clr-surface-3);
      border-radius: var(--radius-2);
      box-shadow: var(--shadow-3);
    }

    & li.submenu:is(:hover, :focus-within) > .level_2 {
      display: flex;
    }
  }
}

/* --- Mobile Ansicht ---
   Unterhalb von --bp-nav wird die Navigation per Popover-API geöffnet, ganz
   ohne JavaScript. Im Template gehören dazu ZWEI Buttons – der Schließen-
   Button ist Pflicht, weil ein langes Menü die ganze Höhe füllt und es dann
   weder eine Fläche "daneben" zum Antippen noch auf dem Smartphone ein Esc
   gibt:
     <button class="nav-toggler" popovertarget="nav-main">Menü</button>
     <nav id="nav-main" popover class="nav--main …">
       <button class="nav-toggler" popovertarget="nav-main"
               popovertargetaction="hide">Schließen</button>
       …
     </nav>
   Ohne das popover-Attribut zeigt sich die Navigation mobil einfach
   dauerhaft als Liste (der Schließen-Button ist dann nutzlos, schadet aber
   nicht) – das Menü ist also nie unerreichbar. Zusätzlich schließen Esc und
   ein Tipp außerhalb des Menüs (Light-Dismiss), solange das Menü nicht die
   ganze Höhe füllt. */
.nav--main[popover] {
  /* Geöffnet: volle Breite, Höhe nach Inhalt (maximal die Bildschirmhöhe,
     dann scrollt das Menü) */
  &:popover-open {
    inset: 0 0 auto 0;
    inline-size: 100%;
    block-size: auto;
    max-inline-size: none;
    max-block-size: 100dvh;
    margin: 0;
    padding: var(--grid-gutter);
    border: 0;
    background: var(--clr-surface-1);
    color: var(--clr-text-1);
    overflow-y: auto;
  }

  /* Schließen-Button bleibt beim Scrollen oben rechts sichtbar */
  & .nav-toggler {
    position: sticky;
    inset-block-start: 0;
    margin-inline-start: auto;
  }

  /* Breit: Popover-Standardverhalten abschalten, Navigation ist wieder ein
     normales Element im Seitenfluss und immer sichtbar */
  @media screen and (min-width: 52em) {
    display: block;
    position: static;
    inline-size: auto;
    block-size: auto;
    margin: 0;
    padding: 0;
    border: 0;
    background: transparent;
    color: inherit;
    overflow: visible;
  }
}

/* Der Schalter wird nur mobil gebraucht */
.nav-toggler {
  @media screen and (min-width: 52em) {
    display: none;
  }
}
/* Alternative zur Popover-Variante: mobiler Menü-Schalter mit JS (src/js/navigation.js)
@import "contao/navigation-js.css";
*/
/*
 * mod_breadcrumb (twig/mod_breadcrumb.html.twig): <nav> mit <ul>, der letzte
 * Eintrag ist <li class="active" aria-current="page"> ohne Link. Die
 * Trennzeichen kommen per ::after, damit sie nicht im Markup stehen (und von
 * Screenreadern nicht vorgelesen werden).
 */
.mod_breadcrumb ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--size-2);
  padding-inline-start: 0;
  list-style: none;

  & li {
    padding-inline-start: 0;

    &:not(:last-child)::after {
      content: "/";
      margin-inline-start: var(--size-2);
      color: var(--clr-text-2);
    }
  }
}
/*
 * mod_articlenav (twig/mod_articlenav.html.twig): Blättern zwischen den
 * Artikeln einer Seite. Wrapper-Klasse .pagination, Einträge first/previous/
 * link/active/next/last. Die Klasse .pagination wird auch von anderen
 * Contao-Paginierungen verwendet und bekommt hier dasselbe Aussehen.
 */
.pagination ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--size-2);
  padding-inline-start: 0;
  list-style: none;

  & li {
    padding-inline-start: 0;
  }

  /* Aktuelle Seite ist <strong class="active">, kein Link */
  & strong.active {
    font-weight: var(--font-weight-7);
  }
}
/*
 * mod_booknav (twig/mod_booknav.html.twig): "Buch"-Navigation mit
 * previous/up/next. Fehlt ein Ziel, gibt Contao <li class="... empty">&nbsp;</li>
 * aus – die Liste bleibt dadurch dreispaltig und "up" bleibt mittig.
 */
.mod_booknav ul {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: var(--size-2);
  gap: var(--size-2);
  padding-inline-start: 0;
  list-style: none;

  & li {
    padding-inline-start: 0;
  }

  & .up {
    text-align: center;
  }

  & .next {
    text-align: end;
  }
}
/*
 * Formulare (twig/form_row.html.twig, form_text.html.twig, form_textarea.html.twig,
 * form_select.html.twig, form_checkbox.html.twig, form_submit.html.twig,
 * form_upload.html.twig, form_explanation.html.twig). Die Klassen stammen aus
 * der jeweiligen Contao\Widget-Unterklasse (this.prefix) und sind in den
 * Twig-Templates identisch zu den klassischen Vorlagen. Grundstyling von
 * input/select/textarea kommt bereits aus der Open-Props-normalize.css.
 */

.widget {
  display: grid;
  grid-gap: var(--size-1);
  gap: var(--size-1);
  margin-block-end: var(--size-4);
}

.mandatory {
  color: var(--clr-error);
}

.widget .error {
  color: var(--clr-error);
  font-size: var(--ctf-step--2);
}

.widget .help {
  color: var(--clr-text-2);
  font-size: var(--ctf-step--2);
}

/* Zeile mit einer Meldung, statt eines Eingabefelds, hebt sich per :has()
   automatisch etwas ab, ohne dass form_row eine eigene Fehler-Klasse braucht */
.widget:has(.error) {
  border-inline-start: var(--border-size-3) solid var(--clr-error);
  padding-inline-start: var(--size-3);
}

:is(.checkbox_container, .radio_container) {
  border: 0;
  padding: 0;
  display: grid;
  grid-gap: var(--size-1);
  gap: var(--size-1);
}

:is(.checkbox_container, .radio_container) legend {
  font-weight: var(--font-weight-6);
}

:is(.checkbox_container, .radio_container) span {
  display: flex;
  align-items: center;
  gap: var(--size-2);
}

.explanation {
  margin-block-end: var(--size-4);
  color: var(--clr-text-2);
}

.form-confirmation {
  padding: var(--size-3);
  background-color: var(--clr-surface-2);
  border-radius: var(--radius-2);
}

/* .formbody: Wrapper der handgeschriebenen (Nicht-Symfony-)Formulare wie
   Login, Suche, Quicknav/-link, Passwort ändern/Konto löschen (u. a.
   mod_login.html.twig, mod_search.html.twig, content_element/login.html.twig).
   Übernimmt den Zeilenabstand selbst, damit .widget darin nicht zusätzlich
   seinen eigenen margin-block-end aufaddiert */
.formbody {
  display: grid;
  grid-gap: var(--size-2);
  gap: var(--size-2);
}

.formbody .widget {
  margin-block-end: 0;
}

/* Hinweistext bei bereits angemeldeten Nutzern ("Angemeldet als …"),
   in content_element/login.html.twig UND mod_login.html.twig identisch */
.login_info {
  color: var(--clr-text-2);
}

/* Link zum Passwort-Reset unterhalb des Login-Formulars */
.password-reset {
  margin-block-start: var(--size-2);
  font-size: var(--ctf-step--2);
}
/*
 * mod_article (Syndication-Icons, "Zurück"-Link) und mod_message.
 * Twig-Ports sind auch hier 1:1-identisch zu den klassischen Vorlagen
 * (twig/mod_article.html.twig, twig/mod_message.html.twig).
 */

.syndication {
  display: flex;
  gap: var(--size-2);
  margin-block-end: var(--size-3);
}

.syndication a {
  display: inline-flex;
}

/* mod_message: Klasse ist $this->type (z. B. "confirm", "error") + " message"
   (u. a. von ModuleRegistration so gesetzt – Registrierungsbestätigungen
   laufen über dieses normale .message.confirm, kein tl_-Präfix).

   .tl_error ist eigentlich eine Backend-Klasse, sickert aber real im
   Frontend durch: content_element/two_factor.html.twig rendert sie direkt
   bei ungültigem Code bzw. erzwungener 2FA (TwoFactorController setzt
   invalid_verification_code/enforce_two_factor echt) – deshalb als Alias
   mitgestylt.

   .tl_confirm dagegen NICHT mitgestylt: das wird nur noch von den alten
   Legacy-Modulklassen ModuleChangePassword/ModulePersonalData gesetzt.
   Reales Testen (2026-10-01) hat gezeigt, dass "Passwort ändern" in dieser
   Contao-Version über den modernen Content-Element-Flow läuft (eigenes
   Symfony-Form-Theme @Contao/form/contao_layout.html.twig, das nur
   .mandatory/.error erzeugt, nie message/tl_confirm) – der Legacy-Modul-Pfad
   ist damit praktisch tot, ein Alias dafür wäre spekulativ.

   .message.info/.message.warning sind (noch) keine von Contao selbst gesetzten
   Typen, aber als Helper-Klassen nutzbar, falls ein Projekt sie manuell braucht. */
:is(.message, .tl_error) {
  padding: var(--size-3);
  border-radius: var(--radius-2);
  background-color: var(--clr-surface-2);
}

:is(.message.error, .tl_error) {
  background-color: var(--clr-error-surface);
  color: var(--clr-error-surface-text);
}

.message.confirm {
  background-color: var(--clr-success-surface);
  color: var(--clr-success-surface-text);
}

.message.info {
  background-color: var(--clr-info-surface);
  color: var(--clr-info-surface-text);
}

.message.warning {
  background-color: var(--clr-warning-surface);
  color: var(--clr-warning-surface-text);
}

/*
 * ALTERNATIVE zur Popover-Lösung in navigation.css: mobiler Menü-Schalter mit
 * JavaScript (src/js/navigation.js). In styles.css wahlweise diese Datei ODER
 * die Popover-Variante nutzen – beide gleichzeitig sind unnötig, stören sich
 * aber nicht: die Popover-Regeln greifen nur bei vorhandenem popover-Attribut,
 * diese hier nur bei vorhandenem data-nav-Attribut (setzt das Skript).
 *
 * Unterschiede zur Popover-Variante:
 *  - Das Menü legt sich nicht über die Seite, sondern klappt im Seitenfluss
 *    unter dem Schalter auf. Der Schalter bleibt immer sichtbar und ist
 *    zugleich der Schließen-Knopf – kein zweiter Button nötig.
 *  - Zustand steht in data-nav="closed|open" am <nav> und in aria-expanded am
 *    Button (wichtig für Screenreader).
 *  - Ohne JavaScript bleibt die Navigation eine sichtbare Liste.
 *
 * Markup und Skript: siehe Kopf von src/js/navigation.js.
 */
.nav--main[data-nav="closed"] {
  /* Eingeklappt gilt nur mobil, ab --bp-nav ist die Navigation immer offen
     (@custom-media --bp-nav und --bp-nav-down stehen in navigation.css) */
  @media screen and (max-width: 51.99em) {
    display: none;
  }
}

.nav--main[data-nav="open"] {
  @media screen and (max-width: 51.99em) {
    padding-block: var(--size-3);
  }
}
