diff --git a/juconnect-patterns-plugin/juconnect-patterns.zip b/juconnect-patterns-plugin/juconnect-patterns.zip
index 0a790ba..403b050 100644
Binary files a/juconnect-patterns-plugin/juconnect-patterns.zip and b/juconnect-patterns-plugin/juconnect-patterns.zip differ
diff --git a/juconnect-patterns-plugin/juconnect-patterns/juconnect-patterns.php b/juconnect-patterns-plugin/juconnect-patterns/juconnect-patterns.php
index 719ef06..98c4ac0 100644
--- a/juconnect-patterns-plugin/juconnect-patterns/juconnect-patterns.php
+++ b/juconnect-patterns-plugin/juconnect-patterns/juconnect-patterns.php
@@ -2,7 +2,7 @@
/**
* Plugin Name: JuConnect Patterns
* Description: Gutenberg Block Patterns fuer JuConnect (Styleguide-Klassen).
- * Version: 0.1
+ * Version: 0.2
*/
if (!defined('ABSPATH')) exit;
@@ -294,6 +294,317 @@ HTML
+HTML
+ ]);
+
+ register_block_pattern('juconnect/single-card-with-graphic-right', [
+ 'title' => __('Info Card + Grafik rechts', 'juconnect'),
+ 'categories' => ['juconnect'],
+ 'description' => __('Zweispaltig: links eine einzelne Inhaltskarte, rechts Bild/Grafik.', 'juconnect'),
+ 'content' => <<
+
+
+
Leistung im Ueberblick
+
+
+
+
Kerninformationen klar und ruhig dargestellt.
+
+
+
+
+
+
+
Wann ist dieses Angebot passend?
+
+
+
+
Fuer Traeger mit klaren Zielen, transparenten Ablaeufen und verbindlicher Kommunikation.
+
+
+
+
- klare Zustaendigkeiten
- regelmaessige Rueckmeldungen
- dokumentierte Entwicklung
+
+
+
+
+
+
+
+
+
+

+
+
+
Rechts: Illustration oder Projektfoto.
+
+
+
+
+HTML
+ ]);
+
+ register_block_pattern('juconnect/single-card-with-graphic-left', [
+ 'title' => __('Grafik links + Info Card', 'juconnect'),
+ 'categories' => ['juconnect'],
+ 'description' => __('Zweispaltig: links Bild/Grafik, rechts eine einzelne Inhaltskarte.', 'juconnect'),
+ 'content' => <<
+
+
+
Leistung im Ueberblick
+
+
+
+
Kerninformationen klar und ruhig dargestellt.
+
+
+
+
+
+
+

+
+
+
Links: Illustration oder Projektfoto.
+
+
+
+
+
+
Wann ist dieses Angebot passend?
+
+
+
+
Fuer Traeger mit klaren Zielen, transparenten Ablaeufen und verbindlicher Kommunikation.
+
+
+
+
- klare Zustaendigkeiten
- regelmaessige Rueckmeldungen
- dokumentierte Entwicklung
+
+
+
+
+
+
+
+
+HTML
+ ]);
+
+ register_block_pattern('juconnect/section-grid-2', [
+ 'title' => __('Section + 2 Cards', 'juconnect'),
+ 'categories' => ['juconnect'],
+ 'description' => __('Standard-Zweispalter fuer Inhalte oder Angebotskarten.', 'juconnect'),
+ 'content' => <<
+
+
+
Schwerpunkte
+
+
+
+
Zwei zentrale Themen kompakt nebeneinander.
+
+
+
+
+
+
+
Begleitung
+
+
+
Verlaessliche Begleitung mit klarer Struktur fuer alle Beteiligten.
+
+
+
Mehr erfahren
+
+
+
+
+
+
Koordination
+
+
+
Abgestimmte Kommunikation zwischen Traegern, Familien und Fachkraeften.
+
+
+
Mehr erfahren
+
+
+
+
+HTML
+ ]);
+
+ register_block_pattern('juconnect/kpi-overview-3', [
+ 'title' => __('KPI Ueberblick (3 Karten)', 'juconnect'),
+ 'categories' => ['juconnect'],
+ 'description' => __('Drei Kennzahlenkarten fuer Verlaesslichkeit, Bearbeitungszeit und Reichweite.', 'juconnect'),
+ 'content' => <<
+
+
+
Fakten im Ueberblick
+
+
+
+
Beispielwerte fuer eine transparente Darstellung.
+
+
+
+
+
+
+
+
Antwortzeit
+
+
+
< 48h
+
+
+
+
+
+
+
+
Abgestimmte Plaene
+
+
+
95%
+
+
+
+
+
+
+
+
Kooperationspartner
+
+
+
24
+
+
+
+
+
+HTML
+ ]);
+
+ register_block_pattern('juconnect/contact-cta-split', [
+ 'title' => __('Kontakt CTA (Split)', 'juconnect'),
+ 'categories' => ['juconnect'],
+ 'description' => __('Linke Infokarte mit Aktionen, rechte Karte mit Kontaktfakten.', 'juconnect'),
+ 'content' => <<
+
+
+
+
Naechster Schritt
+
+
+
+
Unverbindlich Kontakt aufnehmen
+
+
+
+
Wir melden uns zeitnah und klaeren den passenden Rahmen fuer Ihr Anliegen.
+
+
+
+
+
+
+
+
+
+
Kontaktzeiten
+
+
+
+
+
Mo - Fr
+
+
+
08:00 - 17:00
+
+
+
+
+
+
E-Mail
+
+
+
kontakt@juconnect.de
+
+
+
+
+
+
Hinweis
+
+
+
Bitte Anlass und Rueckrufzeit kurz angeben.
+
+
+
+
+
+HTML
+ ]);
+
+ register_block_pattern('juconnect/downloads-table', [
+ 'title' => __('Downloads (Tabelle)', 'juconnect'),
+ 'categories' => ['juconnect'],
+ 'description' => __('Downloadbereich mit Tabelle im Styleguide-Look.', 'juconnect'),
+ 'content' => <<
+
+
+
Downloads
+
+
+
+
Dokumente, Vorlagen und Nachweise auf einen Blick.
+
+
+
+
+
+
+
+
+ | Dokument | Status | Aktion |
+
+
+ | Leistungsbeschreibung | Entwurf | Oeffnen |
+ | Datenschutz | Final | Oeffnen |
+ | Ansprechpartner | Update | Oeffnen |
+
+
+
+
+
+
HTML
]);
});
diff --git a/juconnect-strict-theme-v3/juconnect-strict.zip b/juconnect-strict-theme-v3/juconnect-strict.zip
index 5097497..a219f97 100644
Binary files a/juconnect-strict-theme-v3/juconnect-strict.zip and b/juconnect-strict-theme-v3/juconnect-strict.zip differ
diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js b/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js
index ba03cbb..ce3fddf 100644
--- a/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js
+++ b/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js
@@ -69,6 +69,48 @@ const Toast = (() => {
return { show };
})();
+/* Equalize steps+image pattern column heights */
+(() => {
+ const collectColumns = (layout) => {
+ const inner = layout.querySelector(":scope > .wp-block-group__inner-container");
+ if (inner) return Array.from(inner.children);
+ return Array.from(layout.children);
+ };
+
+ const hasTiles = (el) => !!el.querySelector(".grid.grid--4, .wp-block-group.grid.grid--4");
+ const hasImage = (el) => !!el.querySelector(".wp-block-image img, img");
+
+ const equalize = () => {
+ const layouts = $$(".section .grid.grid--2, .wp-block-group.section .wp-block-group.grid.grid--2");
+ layouts.forEach((layout) => {
+ const columns = collectColumns(layout).filter((el) => el.nodeType === 1);
+ if (columns.length < 2) return;
+
+ const tilesCol = columns.find(hasTiles);
+ const imageCol = columns.find((el) => el !== tilesCol && hasImage(el));
+ if (!tilesCol || !imageCol) return;
+
+ tilesCol.style.minHeight = "";
+ imageCol.style.minHeight = "";
+
+ const h = Math.max(tilesCol.offsetHeight, imageCol.offsetHeight);
+ if (!h) return;
+ tilesCol.style.minHeight = `${h}px`;
+ imageCol.style.minHeight = `${h}px`;
+ });
+ };
+
+ let raf = 0;
+ const schedule = () => {
+ if (raf) cancelAnimationFrame(raf);
+ raf = requestAnimationFrame(equalize);
+ };
+
+ window.addEventListener("load", schedule);
+ window.addEventListener("resize", schedule);
+ schedule();
+})();
+
/* Clipboard copy helper */
async function copyText(text, label="Kopiert.") {
try {
diff --git a/juconnect-strict-theme-v3/juconnect-strict/footer.php b/juconnect-strict-theme-v3/juconnect-strict/footer.php
index 7b7b845..458c707 100644
--- a/juconnect-strict-theme-v3/juconnect-strict/footer.php
+++ b/juconnect-strict-theme-v3/juconnect-strict/footer.php
@@ -1,7 +1,23 @@
diff --git a/juconnect-strict-theme-v3/juconnect-strict/functions.php b/juconnect-strict-theme-v3/juconnect-strict/functions.php
index 0827512..de9549f 100644
--- a/juconnect-strict-theme-v3/juconnect-strict/functions.php
+++ b/juconnect-strict-theme-v3/juconnect-strict/functions.php
@@ -19,9 +19,17 @@ function juconnect_setup() {
add_action('after_setup_theme', 'juconnect_setup');
function juconnect_assets() {
- $ver = wp_get_theme()->get('Version');
- wp_enqueue_style('juconnect-style', get_stylesheet_uri(), [], $ver);
- wp_enqueue_script('juconnect-app', get_template_directory_uri().'/assets/js/app.js', [], $ver, true);
+ $theme_ver = wp_get_theme()->get('Version');
+ $style_ver = filemtime(get_stylesheet_directory() . '/style.css');
+ $script_ver = filemtime(get_template_directory() . '/assets/js/app.js');
+ if (!$style_ver) {
+ $style_ver = $theme_ver;
+ }
+ if (!$script_ver) {
+ $script_ver = $theme_ver;
+ }
+ wp_enqueue_style('juconnect-style', get_stylesheet_uri(), [], $style_ver);
+ wp_enqueue_script('juconnect-app', get_template_directory_uri().'/assets/js/app.js', [], $script_ver, true);
}
add_action('wp_enqueue_scripts', 'juconnect_assets');
@@ -68,7 +76,7 @@ function juconnect_render_sidenav_nav() {
// Add styleguide classes to WP menus
function juconnect_nav_link_attributes($atts, $item, $args, $depth){
- if (!empty($args->theme_location) && $args->theme_location === 'primary'){
+ if (!empty($args->theme_location) && in_array($args->theme_location, ['primary', 'footer'], true)){
$existing = isset($atts['class']) ? $atts['class'].' ' : '';
$atts['class'] = $existing . 'navlink';
}
diff --git a/juconnect-strict-theme-v3/juconnect-strict/style.css b/juconnect-strict-theme-v3/juconnect-strict/style.css
index 53538f1..3d156d1 100644
--- a/juconnect-strict-theme-v3/juconnect-strict/style.css
+++ b/juconnect-strict-theme-v3/juconnect-strict/style.css
@@ -339,7 +339,14 @@ a{ color: inherit; }
}
/* Sections */
-.section{ margin: 0 0 var(--s6) 0; }
+.section{
+ margin: 0 0 var(--s6) 0;
+ padding-bottom: var(--s4);
+}
+.wp-block-group.section{
+ padding-bottom: var(--s4);
+ margin-bottom: var(--s4) !important;
+}
.section__head{ margin-bottom: var(--s4); }
.main .wp-block-group.section{
width: 100%;
@@ -355,6 +362,45 @@ a{ color: inherit; }
padding-top: var(--s4);
border-top: 1px solid var(--line);
}
+.footer__inner{
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-between;
+ gap: var(--s3);
+ flex-wrap: wrap;
+}
+.footer__nav{
+ min-width: 0;
+}
+.footer__menu{
+ list-style: none;
+ display: flex;
+ align-items: flex-start;
+ flex-wrap: wrap;
+ gap: 6px;
+ margin: 0;
+ padding: 0;
+}
+.footer__menu > li{
+ margin: 0;
+}
+.footer__menu a.navlink{
+ padding: 8px 10px;
+ border-radius: 10px;
+}
+.footer__menu .current-menu-item > a.navlink,
+.footer__menu .current-page-ancestor > a.navlink{
+ background: rgba(29,53,79,.10);
+ border-color: rgba(29,53,79,.18);
+ color: var(--text);
+}
+
+@media (max-width: 760px){
+ .footer__inner{
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
/* Typography helpers */
.h1{ font-size: var(--fs-1); line-height: var(--lh-tight); margin: 0 0 var(--s2) 0; }
@@ -381,6 +427,77 @@ a{ color: inherit; }
.wp-block-group.grid.grid--2 > .wp-block-group__inner-container{ grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
.wp-block-group.grid.grid--3 > .wp-block-group__inner-container{ grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
.wp-block-group.grid.grid--4 > .wp-block-group__inner-container{ grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container{
+ align-items: stretch !important;
+}
+.grid.grid--2{
+ align-items: stretch !important;
+}
+.grid.grid--2 > .wp-block-group,
+.grid.grid--2 > .card{
+ height: 100% !important;
+ align-self: stretch !important;
+}
+.grid.grid--2 > .wp-block-group{
+ display: flex;
+ flex-direction: column;
+}
+.grid.grid--2 > .wp-block-group > .grid{
+ flex: 1;
+}
+.grid.grid--4 > .card{
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container > .wp-block-group{
+ display: flex;
+ flex-direction: column;
+ height: 100% !important;
+ align-self: stretch !important;
+}
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container > .wp-block-group > .wp-block-group__inner-container{
+ display: flex;
+ flex-direction: column;
+ height: 100% !important;
+}
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container > .wp-block-group > .wp-block-group.grid{
+ flex: 1;
+}
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container > .wp-block-group > .wp-block-group__inner-container > .wp-block-group.grid{
+ flex: 1;
+}
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container > .wp-block-group > .wp-block-group__inner-container > .wp-block-group.grid > .wp-block-group__inner-container{
+ height: 100%;
+}
+.wp-block-group.grid.grid--4 > .wp-block-group__inner-container > .card{
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+}
+.wp-block-group.grid.grid--2 > .wp-block-group__inner-container > .card{
+ height: 100% !important;
+ align-self: stretch !important;
+}
+.main .wp-block-group.section + .wp-block-group.section{
+ margin-top: var(--s4);
+}
+.main .wp-block-group.section + .section{
+ margin-top: var(--s4);
+}
+
+/* Fallback for pages built with core Columns instead of grid classes */
+.section .wp-block-columns{
+ align-items: stretch !important;
+}
+.section .wp-block-column{
+ display: flex;
+ flex-direction: column;
+}
+.section .wp-block-column > .wp-block-group,
+.section .wp-block-column > .card{
+ height: 100% !important;
+}
.section > .grid + .grid{ margin-top: var(--s4); }
.section > .grid + .card,
.section > .card + .grid{ margin-top: var(--s4); }
@@ -919,7 +1036,7 @@ a{ color: inherit; }
.topnav__submenu{
list-style:none;
position:absolute;
- top: calc(100% + 8px);
+ top: 100%;
right: 0;
min-width: 240px;
margin: 0;
@@ -930,7 +1047,8 @@ a{ color: inherit; }
box-shadow: var(--shadow);
display:none;
}
-.topnav__list li:hover > .topnav__submenu{ display:block; }
+.topnav__list li:hover > .topnav__submenu,
+.topnav__list li:focus-within > .topnav__submenu{ display:block; }
.topnav__submenu a.navlink{
display:flex;
width: 100%;
@@ -938,6 +1056,24 @@ a{ color: inherit; }
border-radius: 12px;
}
+/* Touch devices don't have hover; expose submenus inline for reliable access */
+@media (hover: none){
+ .topnav__list > li{ width: 100%; }
+ .topnav__list a.navlink{ width: 100%; }
+ .topnav__submenu{
+ position: static;
+ display: block;
+ min-width: 0;
+ margin-top: 4px;
+ padding: 4px 0 0 12px;
+ border: 0;
+ border-left: 1px solid var(--line);
+ border-radius: 0;
+ background: transparent;
+ box-shadow: none;
+ }
+}
+
/* Hide original sidenav if any page still contains it */
.sidenav{ display:none !important; }
@@ -989,7 +1125,7 @@ a{ color: inherit; }
.wp-block-buttons .wp-block-button{ margin: 0; }
/* Groups: don't add unexpected margins that break cards/grids */
-.wp-block-group{ margin: 0; }
+.wp-block-group:not(.section){ margin: 0; }
/* Images: prevent WP default inline styles from breaking rounded cards */
.wp-block-image img{ max-width: 100%; height: auto; }