-
-
diff --git a/app/pages/mitmachen.php b/app/pages/mitmachen.php
index a8f9b56..1d65740 100644
--- a/app/pages/mitmachen.php
+++ b/app/pages/mitmachen.php
@@ -52,7 +52,7 @@ component('hero', ['hero' => $page['hero']]);
$f): ?>
-
+
diff --git a/public/assets/css/components.css b/public/assets/css/components.css
index 5f8f4b5..23edf01 100644
--- a/public/assets/css/components.css
+++ b/public/assets/css/components.css
@@ -987,7 +987,14 @@
margin-bottom: var(--space-2xl);
}
-.filter-bar__tab {
+/* Gemeinsame Tab-Basis für Filter-Leiste und Gruppen-Tabs. Beide waren bis auf
+ flex-shrink und 4px Innenabstand zeichengleich implementiert. Aktiv-Zustand
+ kommt je nach Muster über aria-pressed (Filter) oder aria-selected (Tabs).
+ Fokus liegt inset, damit der Ring nicht in den Nachbar-Tab ragt. */
+.tab {
+ display: inline-flex;
+ align-items: center;
+ min-height: var(--tap-min);
padding: var(--space-xs) var(--space-m);
background: none;
border: none;
@@ -1000,24 +1007,26 @@
transition: color var(--transition), box-shadow var(--transition);
}
-.filter-bar__tab:first-child {
- padding-inline-start: 0;
-}
-
-.filter-bar__tab:hover {
+.tab:hover {
color: var(--clr-text);
}
-.filter-bar__tab[aria-pressed="true"] {
+.tab[aria-pressed="true"],
+.tab[aria-selected="true"] {
color: var(--clr-text);
box-shadow: inset 0 -2px 0 var(--clr-accent);
}
-.filter-bar__tab:focus-visible {
- outline: 2px solid var(--clr-accent);
+.tab:focus-visible {
+ outline: var(--focus-ring);
outline-offset: -2px;
}
+/* Erster Filter bündig zur Textkante links. */
+.filter-bar__tab:first-child {
+ padding-inline-start: 0;
+}
+
.positions__list {
display: grid;
gap: var(--space-l);
@@ -1730,55 +1739,27 @@
display: none;
}
-.ad-banner__toggle {
- display: inline-grid;
- place-items: center;
- width: 2.25rem;
- height: 2.25rem;
- padding: 0;
- color: var(--clr-text);
- background: var(--clr-glass-bg);
- border: 1px solid var(--clr-glass-border);
- border-radius: 999px;
- cursor: pointer;
- transition: background var(--transition);
-}
-
.ad-banner__toggle[hidden] {
display: none;
}
-.ad-banner__nav-btn {
- display: inline-grid;
- place-items: center;
- width: 2.25rem;
- height: 2.25rem;
- padding: 0;
+/* Glas-Optik als Delta zu .btn--icon — Größe, Rundung, Zentrierung und die
+ 44px-Trefferfläche kommen von dort. Beide Controls waren vorher zeichengleich
+ dupliziert. .btn muss im Selektor mitstehen: utilities.css lädt nach
+ components.css, bei gleicher Spezifität gewänne sonst die rote .btn-Fläche. */
+.btn.ad-banner__toggle,
+.btn.ad-banner__nav-btn {
font-size: var(--icon-s);
color: var(--clr-text);
background: var(--clr-glass-bg);
border: 1px solid var(--clr-glass-border);
- border-radius: 999px;
- cursor: pointer;
transition: background var(--transition);
}
-.ad-banner__nav-btn:hover {
+.btn.ad-banner__toggle:hover,
+.btn.ad-banner__nav-btn:hover {
background: rgb(255 255 255 / 0.2);
-}
-
-.ad-banner__nav-btn:focus-visible {
- outline: 2px solid var(--clr-text);
- outline-offset: 3px;
-}
-
-.ad-banner__toggle:hover {
- background: rgb(255 255 255 / 0.2);
-}
-
-.ad-banner__toggle:focus-visible {
- outline: 2px solid var(--clr-text);
- outline-offset: 3px;
+ border-color: var(--clr-glass-border);
}
.ad-banner__toggle-icon {
@@ -1806,20 +1787,34 @@
gap: var(--space-2xs);
}
+/* Trefferfläche 48x44px, sichtbar bleibt der 6px-Balken. Der Balken liegt im
+ ::before statt auf dem Button selbst — so kann overflow:hidden entfallen, das
+ sonst jede Vergrößerung der Trefferfläche wieder abschneiden würde. */
.ad-banner__dot {
position: relative;
width: 48px;
- height: 6px;
+ height: var(--tap-min);
padding: 0;
+ background: none;
border: 0;
- border-radius: 999px;
- background: var(--clr-glass-border);
cursor: pointer;
- overflow: hidden;
+}
+
+.ad-banner__dot::before,
+.ad-banner__progress {
+ position: absolute;
+ inset: calc(50% - 3px) 0 auto;
+ height: 6px;
+ border-radius: 999px;
+}
+
+.ad-banner__dot::before {
+ content: "";
+ background: var(--clr-glass-border);
transition: background var(--transition);
}
-.ad-banner__dot:hover {
+.ad-banner__dot:hover::before {
background: rgb(255 255 255 / 0.35);
}
@@ -1829,8 +1824,6 @@
}
.ad-banner__progress {
- position: absolute;
- inset: 0;
background: var(--clr-accent);
transform: scaleX(0);
transform-origin: left;
@@ -2217,32 +2210,9 @@
.group-tabs__bar::-webkit-scrollbar { display: none; }
+/* Tabs im Panel dürfen nicht schrumpfen — sie scrollen stattdessen horizontal. */
.group-tabs__tab {
flex-shrink: 0;
- padding: var(--space-xs) var(--space-l);
- background: none;
- border: none;
- box-shadow: inset 0 -2px 0 var(--clr-glass-border);
- font-family: var(--ff-body);
- font-size: var(--fs-500);
- color: var(--clr-text-muted);
- cursor: pointer;
- white-space: nowrap;
- transition: color var(--transition), box-shadow var(--transition);
-}
-
-.group-tabs__tab:hover {
- color: var(--clr-text);
-}
-
-.group-tabs__tab[aria-selected="true"] {
- color: var(--clr-text);
- box-shadow: inset 0 -2px 0 var(--clr-accent);
-}
-
-.group-tabs__tab:focus-visible {
- outline: 2px solid var(--clr-accent);
- outline-offset: -2px;
}
/* Panel-Karte übernimmt das bestehende group-card--stacked-Layout */
@@ -3407,11 +3377,9 @@
}
.department-choice__btn {
+ /* display/align-items/gap kommen jetzt aus .btn */
align-self: start;
margin-top: auto;
- display: inline-flex;
- align-items: center;
- gap: var(--space-2xs);
}
.department-choice__arrow {
diff --git a/public/assets/css/layout.css b/public/assets/css/layout.css
index 362a13c..92a2c01 100644
--- a/public/assets/css/layout.css
+++ b/public/assets/css/layout.css
@@ -89,6 +89,11 @@
}
.site-nav__list a:not(.btn) {
+ display: inline-flex;
+ align-items: center;
+ /* 44px Trefferfläche (WCAG 2.5.5). Die Leiste ist --header-h (60px) hoch und
+ zentriert ihre Punkte, die Höhe ist deshalb nicht sichtbar. */
+ min-height: var(--tap-min);
color: var(--clr-text);
text-decoration: none;
padding-block: 0.25em;
@@ -123,6 +128,7 @@
.site-nav__sublink {
display: inline-flex;
align-items: center;
+ min-height: var(--tap-min);
gap: 0.3em;
margin: 0;
padding: 0.25em 0;
@@ -599,6 +605,7 @@
.site-footer__social a {
display: inline-flex;
align-items: center;
+ min-height: var(--tap-min);
gap: var(--space-2xs);
padding-block: var(--space-3xs);
color: var(--clr-text-muted);
diff --git a/public/assets/css/utilities.css b/public/assets/css/utilities.css
index 12d767a..b60dfae 100644
--- a/public/assets/css/utilities.css
+++ b/public/assets/css/utilities.css
@@ -1,8 +1,39 @@
/* ============================================================
UTILITIES — Buttons, visually-hidden, kleine Helfer
============================================================ */
+/* --- Trefferflächen ---------------------------------------------------------
+ WCAG 2.5.5 wertet die Trefferfläche, nicht die gezeichnete Fläche. Controls,
+ die optisch klein bleiben sollen (dezente Buttons, Slider-Punkte), strecken
+ sie deshalb über ein unsichtbares Pseudo-Element auf --tap-min, statt zu
+ wachsen. Voraussetzung: das Element darf kein overflow: hidden tragen und
+ ::after muss frei sein. */
+.tap-target,
+.btn--sm {
+ position: relative;
+}
+
+.tap-target::after,
+.btn--sm::after {
+ content: "";
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ translate: -50% -50%;
+ width: 100%;
+ height: 100%;
+ min-width: var(--tap-min);
+ min-height: var(--tap-min);
+}
+
+/* --- Buttons ---------------------------------------------------------------
+ inline-flex statt inline-block, damit min-height die Trefferfläche sichern
+ kann und Icon+Label ohne Zusatz-Markup zentriert nebeneinander liegen. */
.btn {
- display: inline-block;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: var(--space-2xs);
+ min-height: var(--tap-min);
padding: var(--btn-pad-y) var(--btn-pad-x);
white-space: nowrap;
background: var(--clr-accent);
@@ -26,7 +57,7 @@
}
.btn:focus-visible {
- outline: 2px solid var(--clr-text);
+ outline: var(--focus-ring);
outline-offset: 2px;
}
@@ -53,8 +84,37 @@
color: var(--clr-text);
}
-/* Größenmodifier — Padding ist em-basiert, skaliert mit der font-size */
-.btn--sm { font-size: var(--btn-font-sm); }
+/* tertiary — ohne Fläche und Rahmen, für Aktionen neben einem primären Button.
+ Unterstrichen, damit der Button nicht allein über die Farbe erkennbar ist. */
+.btn--ghost {
+ background: transparent;
+ border-color: transparent;
+ text-decoration: underline;
+}
+
+.btn--ghost:hover {
+ background: var(--clr-glass-bg);
+ border-color: transparent;
+ color: var(--clr-text);
+}
+
+/* Icon-Button — quadratisch, nur ein Icon, Label über aria-label.
+ Das Icon selbst skaliert über font-size (siehe --icon-*). */
+.btn--icon {
+ gap: 0;
+ min-width: var(--tap-min);
+ padding: 0;
+ border-radius: 999px;
+}
+
+/* Größenmodifier — Padding ist em-basiert, skaliert mit der font-size.
+ --sm bleibt bewusst optisch klein und holt die 44px über die Trefferfläche;
+ dafür muss min-height hier zurückgenommen werden. */
+.btn--sm {
+ min-height: 0;
+ font-size: var(--btn-font-sm);
+}
+
.btn--lg { font-size: var(--btn-font-lg); }
.visually-hidden {
diff --git a/public/dateien/.htaccess b/public/dateien/.htaccess
new file mode 100644
index 0000000..a027ed2
--- /dev/null
+++ b/public/dateien/.htaccess
@@ -0,0 +1,28 @@
+# Dateiablage /dateien (Files Gallery). Die Regeln aus public/.htaccess gelten hier vererbt
+# weiter — nur diese drei Punkte müssen abweichen.
+
+
+ # Files Gallery rendert Inline-