@charset "UTF-8";
/**
 * Barrierefreiheit – Korrekturen und Ergänzungen
 * ---------------------------------------------------------------------------
 * Relaunch vhs Worms, Stand 12.08.2026 – Kufer Software GmbH
 *
 * Diese Datei wird BEWUSST separat kompiliert und NICHT über import.scss in
 * style.css eingebunden. Grund: style.css ist ein bestehender, minifizierter
 * Build; ein Komplett-Rebuild mit einer anderen sass-Version würde die ganze
 * Datei umformatieren (calc()- und @media-Schreibweise) und den Diff
 * unbrauchbar machen. Die Regeln liegen deshalb in einem eigenen Stylesheet,
 * das nach style.css geladen wird (0000045_accessibility.typoscript).
 *
 * Build:
 *   npx sass --style=expanded --no-source-map \
 *     Scss/_accessibility.scss Css/accessibility.css
 *
 * Bei einem späteren offiziellen Gesamt-Build kann stattdessen
 * `@import "accessibility";` in import.scss aufgenommen und der separate
 * Include entfernt werden.
 */
/**
 * VHS Farben
 */
/**
 * Theme Farben
 */
/**
 * Sizes
 */
/**
 * Mixin
 */
/* Sichtbarer Fokus-Indikator, mind. 3:1 zum Hintergrund
 * ---------------------------------------------------------------------------
 * WCAG 2.2 – 2.4.7 Focus Visible (AA), 1.4.11 Non-Text Contrast (AA)
 *
 * Gemessener Ist-Zustand vor der Korrektur:
 *   .form-control:focus  Ring #B6BBCF auf #FFFFFF = 1,91:1  (Soll >= 3:1)
 *   .btn-main:focus      Ring #E7E7EF auf #FFFFFF = 1,23:1  (Soll >= 3:1)
 *   .kw-filter-label     kein Fokus-Indikator vorhanden
 *
 * Nach der Korrektur: #00285A auf #FFFFFF = 14,47:1.
 * Der zusaetzliche weisse Innenring (box-shadow) haelt den Indikator auch auf
 * dunklen Flaechen (#00285A) sichtbar – dort wirkt Weiss mit 14,47:1.
 */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible,
[role=button]:focus-visible {
  outline: 3px solid #00285A !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
}

/* Auf dunklem Grund den Ring invertieren, damit er nicht "verschwindet". */
#top-bar a:focus-visible,
.bg-main a:focus-visible,
.btn-main:focus-visible,
.knews-article-big-sidebar a:focus-visible {
  outline: 3px solid #FFFFFF !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
  box-shadow: 0 0 0 5px rgba(0, 40, 90, 0.9) !important;
}

/* Formularfelder: Ring #B6BBCF (1,91:1) -> #00285A (14,47:1) */
.form-control:focus,
.form-select:focus,
.form-check-input:focus {
  border-color: #00285A;
  outline: 3px solid #00285A !important;
  outline-offset: 1px;
  box-shadow: none !important;
}

/* Kursfilter-Umschalter hatten ueberhaupt keinen Fokus-Indikator. */
.kw-filter-label:focus-visible {
  outline: 3px solid #00285A !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
}

/* Bootstrap entfernt bei .btn den Outline und ersetzt ihn durch einen
 * kontrastarmen box-shadow. Hier wieder ein echter Outline. */
.btn:focus-visible,
.page-link:focus,
.nav-link:focus-visible,
.navbar-toggler:focus,
.dropdown-item:focus,
.btn-close:focus {
  outline: 3px solid #00285A !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
}

/* Sprunglink ("Hauptinhalt anspringen")
 * ---------------------------------------------------------------------------
 * WCAG 2.4.1 Bypass Blocks. Vorher Bootstrap-Blau #0d6efd (Weiss darauf =
 * 4,50:1, genau an der Grenze). Jetzt Hausfarbe #00285A = 14,47:1.
 */
/* Der Basis-Build (_typo3.scss) versteckt den Sprunglink mit
 * `position:absolute; top:-150%`. Ein Prozentwert bei `top` rechnet gegen die
 * Hoehe des umgebenden Blocks - das ist hier `nav.navbar` (position:relative,
 * 142 px hoch). Der Versatz reicht daher nicht aus und der Link stand sichtbar
 * im Kopfbereich. Ausserdem blendete `:hover` ihn auch fuer Mausnutzung ein.
 *
 * Der Link wird deshalb mit festen Werten aus dem sichtbaren Bereich genommen
 * (nicht display:none - er muss fuer Tastatur und Screenreader erreichbar
 * bleiben) und ausschliesslich im Fokus eingeblendet. Im Fokus wechselt er auf
 * position:fixed, damit er unabhaengig vom umgebenden Block und von
 * `overflow:hidden`-Vorfahren immer am Anfang des Viewports erscheint und nicht
 * verdeckt wird (WCAG 2.4.1 Bypass Blocks, 2.4.7 Focus Visible,
 * 2.4.11 Focus Not Obscured). */
.skip-nav {
  position: absolute !important;
  top: auto !important;
  left: -10000px !important;
  width: 1px !important;
  height: 1px !important;
  padding: 0 !important;
  overflow: hidden !important;
  white-space: nowrap;
  background-color: #00285A !important;
  border-color: #00285A !important;
  color: #FFFFFF !important;
  /* Bewusst nur :focus / :focus-visible - kein :hover und kein :active,
   * damit der Link bei Mausbedienung nicht aufblitzt. */
}
.skip-nav:focus, .skip-nav:focus-visible {
  position: fixed !important;
  top: 0.5rem !important;
  left: 0.5rem !important;
  width: auto !important;
  height: auto !important;
  padding: 0.6rem 1.25rem !important;
  overflow: visible !important;
  z-index: 1080 !important;
  background-color: #00285A !important;
  color: #FFFFFF !important;
  text-decoration: none;
  outline: 3px solid #FFFFFF !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
  box-shadow: 0 0 0 5px rgba(0, 40, 90, 0.9) !important;
}

/* Reflow: umbruchsichere Überschriften
 * ---------------------------------------------------------------------------
 * WCAG 1.4.10 Reflow (AA), 1.4.4 Resize Text (AA)
 *
 * Gemessen bei 375 px Viewport: der Titel-Link im Aktuelles-Teaser war 253 px
 * breit, sein Container (.knews-article-big-sidebar-content, overflow:hidden)
 * nur 169 px – der Text wurde rechts abgeschnitten. Ursache: einzelne lange
 * Wörter ("Einzelsprechstunde") ohne Umbruchmöglichkeit bei 28 px Schriftgrad.
 */
.knews-title,
.knews-article-big-sidebar-content .knews-title,
.knews-article-big-sidebar-content .knews-title a,
.kw-kurstitel a,
.kw-best-data,
.image-caption,
h1, h2, h3, h4, h5, h6 {
  -ms-word-break: break-all;
  -ms-word-wrap: break-all;
  -webkit-word-break: break-word;
  -webkit-word-wrap: break-word;
  word-break: break-word;
  word-wrap: break-word;
  -webkit-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}

.knews-article-big-sidebar-content {
  /* Kein Abschneiden mehr: der Inhalt darf in die Höhe laufen. */
  overflow: visible;
}

@media (max-width: 575.98px) {
  .knews-article-big-sidebar-content .knews-title,
  .knews-article-big-sidebar-content .knews-title a {
    font-size: 1.25rem;
    line-height: 1.35;
  }
}
/* Fachbereichs-Kacheln: gleichmäßige Abstände
 * ---------------------------------------------------------------------------
 * Gemessen: Kachel "Kultur" (1-zeilige Beschriftung) 194 px hoch,
 * Kachel "Beruf, EDV und Digitalisierung" (2-zeilig) 225 px. Da die Kacheln
 * in Zeilen von je 2 bzw. 4 Spalten umbrechen, wurde die gesamte Folgezeile
 * um die Differenz nach unten verschoben -> ungleiche vertikale Abstände.
 * Lösung: Beschriftungsbereich auf zwei Zeilen Mindesthöhe festlegen, damit
 * alle Kacheln exakt gleich hoch sind.
 */
.cat-icon-row {
  align-items: stretch;
}
.cat-icon-row > .ce-column {
  display: flex;
}
.cat-icon-row figure.image {
  display: flex;
  flex-direction: column;
  width: 100%;
  margin-bottom: 0;
}
.cat-icon-row .image-caption {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  /* Platz für zwei Textzeilen – verhindert unterschiedlich hohe Kacheln. */
  min-height: 3em;
  margin-top: 0.5rem;
  text-align: center;
}

/* Bei 320 px Breite (400 % Zoom) stehen nur zwei Kacheln je Zeile. Die längste
 * Beschriftung ("Grundbildung und Schulabschluss") benötigte dort vier Zeilen
 * und machte ihre Kachelzeile 31 px höher als die übrigen. Mit etwas kleinerer
 * Beschriftung und einer Mindesthöhe von drei Zeilen sind alle acht Kacheln
 * gleich hoch – nachgemessen: durchgängig 209 px. Die Mindesthöhe ist in em
 * angegeben und wächst damit mit der Textgröße mit. */
@media (max-width: 575.98px) {
  .cat-icon-row .image-caption {
    font-size: 0.9375rem;
    line-height: 1.35;
    min-height: 4.05em;
  }
}
/* Waagerecht verschiebbare Tabellen
 * ---------------------------------------------------------------------------
 * WCAG 2.1.1 Keyboard (A), 1.4.10 Reflow (AA)
 *
 * Gemessen bei 375 px Viewport: die Kursübersicht ist 421 px breit und liegt
 * in einem .table-responsive-Container mit overflow-x:auto. Der Container war
 * nicht fokussierbar – mit der Tastatur liess sich der überstehende Bereich
 * (Spalten "Ort"/"Nr.") deshalb nicht erreichen. Der Container erhält in den
 * Sichten nun tabindex="0" und wird hier sichtbar als scrollbarer Bereich
 * gekennzeichnet.
 */
.kw-table-scroll:focus-visible {
  outline: 3px solid #00285A !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
}

/* Kursübersicht auf schmalen Viewports tatsächlich verschiebbar machen
 * ---------------------------------------------------------------------------
 * Der Container hat overflow-x:auto, die Tabelle nutzt aber table-layout:auto
 * ohne Mindestbreite. Sie presst sich dadurch in den Container statt
 * überzulaufen, und die Spalten werden unbrauchbar schmal. Gemessen auf
 * /kurse/gesellschaft bei 375 px Viewport: Container 351 px, Tabelle 351 px,
 * kein Scrollbereich – und die Titelspalte nur 51 px breit, weil ein langer
 * Ortsname ("Webinar - virtuelles Klassenzimmer") die Ortsspalte auf 131 px
 * gezogen hat.
 *
 * Mit einer Mindestbreite läuft die Tabelle über, der Container scrollt, und
 * jede Spalte behält eine lesbare Breite. Der Scrollbereich ist über die
 * Sichten bereits fokussierbar (tabindex="0", role="region"), also auch ohne
 * Maus erreichbar. Die Mindestbreite ist in rem angegeben und wächst mit der
 * eingestellten Schriftgröße mit.
 */
@media (max-width: 767.98px) {
  .kw-table-scroll {
    /* Verlauf am rechten Rand als Hinweis, dass dort weiterer Inhalt folgt.
     * Nur in diesem Bereich, weil nur hier gescrollt wird. */
    background: linear-gradient(to right, rgba(0, 40, 90, 0), rgba(0, 40, 90, 0.14)) 100% 0/16px 100% no-repeat;
  }
  .kw-kursuebersicht-table,
  .kw-kw-highlight .table,
  .kw-demnaechstmenue .table {
    min-width: 34rem; /* 544 px bei 16 px Wurzel-Schriftgröße */
  }
  /* Datum und Kursnummer sollen nicht mitten im Wert umbrechen. */
  .kw-kursuebersicht-table td,
  .kw-kursuebersicht-table th {
    white-space: normal;
  }
}
@media (max-width: 575.98px) {
  .kw-kursuebersicht-table {
    font-size: 0.95rem;
  }
}
/* Veranstaltungskalender
 * ---------------------------------------------------------------------------
 * WCAG 1.4.10 Reflow (AA) - Inhalt muss bei 320 px Breite (entspricht 400 %
 * Zoom auf 1280 px) ohne waagerechtes Scrollen nutzbar sein.
 *
 * Gemessen bei 320 px: Die Monatstabelle war 338 px breit, ihr Container
 * (.kw-kalender-body) nur 284 px - die Spalten Samstag/Sonntag lagen ausserhalb
 * des Bildschirms. Ursache: table-layout:auto mit sieben Spalten bei 18 px
 * Schrift. Mit fester Spaltenaufteilung und kleinerem Innenabstand passt der
 * Kalender in 320 px.
 */
.kw-kalender-body table {
  table-layout: fixed;
  width: 100%;
}

@media (max-width: 575.98px) {
  .kw-kalender-body table {
    font-size: 0.8125rem;
  }
  .kw-kalender-body th,
  .kw-kalender-body td {
    padding: 2px !important;
    text-align: center;
  }
}
/* Lange Wörter im Fließtext
 * ---------------------------------------------------------------------------
 * Gemessen bei 320 px: ein Textabsatz lief mit 307 px über seinen 272 px
 * breiten Container hinaus, weil ein einzelnes langes Wort nicht umbrechen
 * konnte (overflow-wrap: normal).
 */
.frame-type-text p,
.frame-type-text li,
.frame-type-text span,
.frame-type-text td,
.frame-type-textmedia p,
.frame-type-textmedia li,
.frame-type-textmedia span,
.frame-type-textmedia td,
.ce-bodytext p,
.ce-bodytext li,
.ce-bodytext span,
.ce-bodytext td {
  -ms-word-break: break-all;
  -ms-word-wrap: break-all;
  -webkit-word-break: break-word;
  -webkit-word-wrap: break-word;
  word-break: break-word;
  word-wrap: break-word;
  -webkit-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}

/* Mobile Navigation: Login mit Textbeschriftung
 * ---------------------------------------------------------------------------
 * WCAG 2.4.4 Link Purpose (A), 4.1.2 Name, Role, Value (A)
 * In der mobilen Navigation war der Login nur als Personen-Icon ohne
 * Textbeschriftung erkennbar, während Warenkorb, Merkliste und Suche
 * ausgeschrieben sind. Die Sicht liefert jetzt zusätzlich Text.
 */
.tn-login-text {
  margin-left: 0;
  font-weight: inherit;
}

/* Unterhalb der Desktop-Breite (navbar-expand-xxl klappt unter 1400 px ein)
 * zeigt der Login-Eintrag nur den Text "Login" bzw. "Mein Konto". Das Personen-
 * Symbol entfaellt dort, damit der Eintrag wie Warenkorb, Kurs-Merkliste und
 * Suche ausschliesslich als Text erscheint.
 *
 * Fuer Screenreader aendert sich dadurch nichts: Das Symbol ist in der Sicht
 * bereits mit aria-hidden="true" ausgezeichnet, der zugaengliche Name kommt aus
 * dem Text im Link. Ab xxl bleibt die bisherige Darstellung (Symbol plus
 * visuell verborgener Name) erhalten. */
@media (max-width: 1399.98px) {
  .tn-login-container .bi-person,
  .tn-login .bi-person {
    display: none;
  }
  /* Der Haken-Indikator des angemeldeten Zustands haengt am Symbol. Ohne Symbol
   * wird er nicht mehr gebraucht; der angemeldete Zustand ist am Text
   * "Mein Konto" erkennbar. */
  .tn-login > a > .badge {
    display: none;
  }
  .tn-login-container,
  .tn-login-item .tn-login,
  .tn-login-item .tn-login-container {
    width: 100%;
  }
  .tn-login-item .tn-login > a {
    display: inline-flex;
    align-items: center;
  }
  /* Das Dropdown-Menü soll im Fluss stehen und nicht über die Seitenlinks legen. */
  .tn-login-item .dropdown-menu {
    position: static !important;
    float: none;
    width: 100%;
    border: 0;
    box-shadow: none;
  }
}
/* Zielgrößen von Bedienelementen
 * ---------------------------------------------------------------------------
 * WCAG 2.2 – 2.5.8 Target Size (Minimum), AA: mind. 24 x 24 CSS-Pixel.
 */
.kw-filter-label,
.page-link,
.tl-navigation a,
.tr-navigation a,
.socialMedia .nav-item > a,
.dark-mode a,
.sizer a {
  min-height: 24px;
  min-width: 24px;
}

.socialMedia .nav-item > a,
.sizer a,
.dark-mode a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px 6px;
}

/* Cookie-Hinweis (Klaro)
 * ---------------------------------------------------------------------------
 * Der Hinweis ist eine fixierte Leiste am unteren Rand (z-index 999).
 * Auf iOS/Safari überlagert die Browser-Bedienleiste den unteren
 * Viewport-Rand, wodurch die Schaltflächen "OK"/"Ablehnen" praktisch nicht
 * erreichbar waren. Zusätzlich lag die Leiste unter dem Warenkorb-Offcanvas
 * (z-index 9999).
 */
.klaro .cookie-notice:not(.cookie-modal-notice) {
  z-index: 10000 !important;
  padding-bottom: calc(1rem + env(safe-area-inset-bottom, 0px)) !important;
}

.klaro .cn-buttons button.cm-btn,
.klaro .cookie-notice .cm-btn {
  min-height: 44px;
  padding: 0.5rem 1rem;
  font-size: 1rem;
}

.klaro .cookie-notice a:focus-visible,
.klaro .cookie-notice button:focus-visible,
.klaro .cookie-modal button:focus-visible {
  outline: 3px solid #FFFFFF !important;
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(255, 255, 255, 0.9) !important;
  border-radius: 2px;
  box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.6) !important;
}

/* Mitarbeiter-/Ansprechpartner-Karten
 * ---------------------------------------------------------------------------
 * Markup: .row.kw-mitarbeiter-liste > .col-md-6 > .kw-mitarbeiter
 *         (darin h3, .kw-mitarbeiter-foto, .kw-mitarbeiter-text)
 *
 * Zwei Ursachen für die verschobenen Fotos und die ungleich großen Kästen:
 *
 * 1) .kw-mitarbeiter-foto ist absolut mit top:-100px positioniert und ragt
 *    damit 100 px über die Karte hinaus. Ab 991 px Breite wird das Foto in
 *    _kuferweb.scss auf 150x150 px verkleinert, der Versatz top:-100px bleibt
 *    aber unverändert. Bei 5rem (80 px) Innenabstand oben ragte das Foto
 *    dadurch über die Karte hinaus in das vorherige Element.
 *    Korrektur: Versatz = halbe Fotohöhe, damit das Foto immer mittig auf der
 *    oberen Kante der Karte sitzt.
 *
 * 2) Die Karten hatten keine gemeinsame Höhe. Sobald ein Name zweizeilig
 *    umbrach ("Armine Chopikyan, M.A.") oder eine E-Mail-Adresse umbrach, war
 *    der graue Kasten höher als der daneben – Fotos und Kästen standen
 *    dadurch nicht mehr auf einer Linie.
 */
.kw-mitarbeiter-liste {
  align-items: stretch;
  /* Lange E-Mail-Adressen sprengten den grauen Kasten. */
}
.kw-mitarbeiter-liste > [class*=col-] {
  display: flex;
  /* Platz für das nach oben herausragende Foto */
  margin-top: 100px;
}
.kw-mitarbeiter-liste .kw-mitarbeiter {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
}
.kw-mitarbeiter-liste .kw-mitarbeiter-text {
  margin-top: auto;
}
.kw-mitarbeiter-liste .kw-mitarbeiter-text p,
.kw-mitarbeiter-liste a[href^="mailto:"] {
  -ms-word-break: break-all;
  -ms-word-wrap: break-all;
  -webkit-word-break: break-word;
  -webkit-word-wrap: break-word;
  word-break: break-word;
  word-wrap: break-word;
  -webkit-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}
.kw-mitarbeiter-liste h3 {
  -ms-word-break: break-all;
  -ms-word-wrap: break-all;
  -webkit-word-break: break-word;
  -webkit-word-wrap: break-word;
  word-break: break-word;
  word-wrap: break-word;
  -webkit-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}

.kw-mitarbeiter-foto {
  /* halbe Fotohöhe von 200px */
  top: -100px;
}

@media (max-width: 991px) {
  .kw-mitarbeiter-foto {
    /* halbe Fotohöhe von 150px – vorher unverändert -100px */
    top: -75px;
  }
  .kw-mitarbeiter-liste > [class*=col-] {
    margin-top: 75px;
  }
}
/* Kontakt-/Info-Kästen: umbruchsichere E-Mail-Adressen und Rufnummern
 * (lange Adressen rutschten unter das Symbol und sprengten den Kasten). */
.contact-info a[href^="mailto:"],
.contact-info a[href^="tel:"],
.contact-info .menu-icon-text,
.footer-main a[href^="mailto:"],
.footer-main a[href^="tel:"],
.footer-main .menu-icon-text,
.top-bar-info a[href^="mailto:"],
.top-bar-info a[href^="tel:"],
.top-bar-info .menu-icon-text {
  -ms-word-break: break-all;
  -ms-word-wrap: break-all;
  -webkit-word-break: break-word;
  -webkit-word-wrap: break-word;
  word-break: break-word;
  word-wrap: break-word;
  -webkit-hyphens: auto;
  -moz-hyphens: auto;
  hyphens: auto;
}

/* Eingebettete Karten und Bilder dürfen ihren Container nicht überlaufen
 * (auf Tablets überdeckten Fotos die daneben liegende Karte). */
.ce-gallery img,
.ce-column img,
figure.image img,
iframe[src*=map],
.frame iframe {
  max-width: 100%;
  height: auto;
}

.frame iframe {
  border: 0;
}

/* Reduzierte Bewegung respektieren – WCAG 2.3.3 (AAA) / gute Praxis */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
