diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/fonts/SourceSans3-Italic-VariableFont_wght.ttf b/juconnect-strict-theme-v3/juconnect-strict/assets/fonts/SourceSans3-Italic-VariableFont_wght.ttf new file mode 100644 index 0000000..75865b9 Binary files /dev/null and b/juconnect-strict-theme-v3/juconnect-strict/assets/fonts/SourceSans3-Italic-VariableFont_wght.ttf differ diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/fonts/SourceSans3-VariableFont_wght.ttf b/juconnect-strict-theme-v3/juconnect-strict/assets/fonts/SourceSans3-VariableFont_wght.ttf new file mode 100644 index 0000000..5b7248b Binary files /dev/null and b/juconnect-strict-theme-v3/juconnect-strict/assets/fonts/SourceSans3-VariableFont_wght.ttf differ diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/img/gruppe.png b/juconnect-strict-theme-v3/juconnect-strict/assets/img/gruppe.png new file mode 100644 index 0000000..3c54caa Binary files /dev/null and b/juconnect-strict-theme-v3/juconnect-strict/assets/img/gruppe.png differ diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/img/helfer.png b/juconnect-strict-theme-v3/juconnect-strict/assets/img/helfer.png new file mode 100644 index 0000000..5156986 Binary files /dev/null and b/juconnect-strict-theme-v3/juconnect-strict/assets/img/helfer.png differ diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect.svg b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect.svg new file mode 100644 index 0000000..ad3ce82 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_icon.svg b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_icon.svg new file mode 100644 index 0000000..2e4a4ea --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_icon_light.svg b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_icon_light.svg new file mode 100644 index 0000000..a489005 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_icon_light.svg @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_light.svg b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_light.svg new file mode 100644 index 0000000..aca41c9 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/assets/img/juconnect_light.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js b/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js new file mode 100644 index 0000000..ba03cbb --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/assets/js/app.js @@ -0,0 +1,381 @@ +/* JuConnect · Tool-first UI interactions (v0.2) */ + +const $ = (sel, root=document) => root.querySelector(sel); +const $$ = (sel, root=document) => Array.from(root.querySelectorAll(sel)); + +function normalizeHexColor(value) { + if (!value) return ""; + const trimmed = value.trim(); + if (trimmed.startsWith("#")) return trimmed; + + const match = trimmed.match(/^rgba?\(([^)]+)\)$/i); + if (!match) return trimmed; + + const parts = match[1].split(",").map(p => p.trim()); + if (parts.length < 3) return trimmed; + + const toHex = (n) => { + const num = Number.parseInt(n, 10); + if (Number.isNaN(num)) return "00"; + return Math.max(0, Math.min(255, num)).toString(16).padStart(2, "0"); + }; + + return `#${toHex(parts[0])}${toHex(parts[1])}${toHex(parts[2])}`.toLowerCase(); +} + +function syncBackgroundSwatch() { + const swatch = document.querySelector('[data-swatch][data-name="bg"]'); + if (!swatch) return; + + const rawBg = getComputedStyle(document.documentElement).getPropertyValue("--bg"); + const hex = normalizeHexColor(rawBg); + if (!hex) return; + + swatch.setAttribute("data-hex", hex); + const label = swatch.querySelector("[data-bg-hex]"); + if (label) label.textContent = hex; +} + +function syncThemeLogos() { + const isDark = document.documentElement.getAttribute("data-theme") === "dark"; + $$("[data-logo-light][data-logo-dark]").forEach((img) => { + const src = isDark ? img.getAttribute("data-logo-dark") : img.getAttribute("data-logo-light"); + if (src) img.setAttribute("src", src); + }); +} + +/* Toasts */ +const Toast = (() => { + const container = () => document.querySelector(".toasts"); + + const show = (text, timeoutMs=2600) => { + const c = container(); + if (!c) return; + + const el = document.createElement("div"); + el.className = "toast"; + el.innerHTML = ` +
+ + `; + $(".toast__text", el).textContent = text; + + const close = () => { el.remove(); clearTimeout(t); }; + $(".toast__close", el).addEventListener("click", close); + c.appendChild(el); + const t = setTimeout(close, timeoutMs); + }; + + return { show }; +})(); + +/* Clipboard copy helper */ +async function copyText(text, label="Kopiert.") { + try { + await navigator.clipboard.writeText(text); + Toast.show(label); + } catch { + // Fallback + const ta = document.createElement("textarea"); + ta.value = text; + ta.style.position = "fixed"; + ta.style.left = "-9999px"; + document.body.appendChild(ta); + ta.select(); + document.execCommand("copy"); + ta.remove(); + Toast.show(label); + } +} + +function decodeCopyText(text) { + if (!text) return ""; + return text + .replace(/\\r\\n/g, "\n") + .replace(/\\n/g, "\n") + .replace(/\\t/g, "\t"); +} + +/* Generic [data-copy] buttons */ +document.addEventListener("click", (e) => { + const btn = e.target.closest("[data-copy]"); + if (!btn) return; + const text = decodeCopyText(btn.getAttribute("data-copy") || ""); + const label = btn.getAttribute("data-copy-label") || "Kopiert."; + copyText(text, label); +}); + +/* Copy for snippet blocks */ +document.addEventListener("click", (e) => { + const btn = e.target.closest("[data-snippet-copy]"); + if (!btn) return; + const snippet = btn.closest("[data-snippet]") || btn.closest(".card"); + const code = snippet?.querySelector("pre code"); + if (!code) return; + copyText(code.innerText, btn.getAttribute("data-copy-label") || "Snippet kopiert"); +}); + +/* Swatch copy buttons */ +document.addEventListener("click", (e) => { + const btn = e.target.closest("[data-swatch-copy]"); + if (!btn) return; + const swatch = btn.closest("[data-swatch]"); + if (!swatch) return; + + const mode = btn.getAttribute("data-swatch-copy"); + const name = swatch.getAttribute("data-name") || ""; + const hex = swatch.getAttribute("data-hex") || ""; + if (mode === "hex") return copyText(hex, "Hex kopiert"); + if (mode === "token") return copyText(`var(--${name})`, "Token kopiert"); +}); + +/* Theme toggle */ +(() => { + const btn = document.querySelector("[data-theme-toggle]"); + const saved = localStorage.getItem("juconnect_theme"); + if (saved) document.documentElement.setAttribute("data-theme", saved); + syncBackgroundSwatch(); + syncThemeLogos(); + + btn?.addEventListener("click", () => { + const current = document.documentElement.getAttribute("data-theme"); + const next = current === "dark" ? "light" : "dark"; + document.documentElement.setAttribute("data-theme", next); + localStorage.setItem("juconnect_theme", next); + syncBackgroundSwatch(); + syncThemeLogos(); + Toast.show(`Theme: ${next}`); + }); +})(); + +/* Active nav link on scroll */ +(() => { + const links = $$(".navlink"); + const sections = links + .map(a => document.querySelector(a.getAttribute("href"))) + .filter(Boolean); + + const obs = new IntersectionObserver((entries) => { + const visible = entries + .filter(e => e.isIntersecting) + .sort((a,b) => b.intersectionRatio - a.intersectionRatio)[0]; + if (!visible) return; + + links.forEach(a => a.classList.remove("is-active")); + const id = "#" + visible.target.id; + const active = links.find(a => a.getAttribute("href") === id); + active?.classList.add("is-active"); + }, { rootMargin: "-25% 0px -65% 0px", threshold: [0.12, 0.25, 0.45] }); + + sections.forEach(s => obs.observe(s)); +})(); + +/* Nav search filter */ +(() => { + const input = document.querySelector("[data-nav-search]"); + const nav = document.querySelector("[data-nav]"); + if (!input || !nav) return; + + const allLinks = $$("a.navlink", nav); + + input.addEventListener("input", () => { + const q = input.value.trim().toLowerCase(); + allLinks.forEach(a => { + const show = !q || a.textContent.toLowerCase().includes(q) || a.getAttribute("href").toLowerCase().includes(q); + a.style.display = show ? "" : "none"; + }); + + // hide empty groups + $$(".navgroup", nav).forEach(g => { + const anyVisible = $$("a.navlink", g).some(a => a.style.display !== "none"); + g.style.display = anyVisible ? "" : "none"; + }); + }); +})(); + +/* Bildsprache prompt generator */ +(() => { + const topicInput = document.querySelector("[data-bild-topic]"); + const copyBtn = document.querySelector("[data-bild-copy]"); + if (!topicInput || !copyBtn) return; + + const template = `Erstelle eine ruhige, sachliche Illustration zum Thema: {THEMA}. + +Stil: +- reduzierte, professionelle Vektorillustration +- klare Formen, weiche Kanten, keine Comic-\u00dcberzeichnung +- keine Verniedlichung, keine \u00fcbertriebenen Emotionen +- sachlich, freundlich, respektvoll +- geeignet f\u00fcr Jugend- und Familienhilfe im Kontext \u00f6ffentlicher Tr\u00e4ger + +Farbwelt: +- Prim\u00e4rfarbe: tiefes, seri\u00f6ses Blau (#1d354f) f\u00fcr Struktur, Kleidung, Rahmen +- Akzentfarbe: dezenter, warmer Salbeiton (#8FAE9A) nur f\u00fcr kleine Hervorhebungen +- neutrale Off-White- und Grau-T\u00f6ne f\u00fcr Hintergr\u00fcnde +- keine grellen Farben, kein hoher Kontrast, kein Schwarz + +Motivik: +- abstrahierte Menschen oder Symbole (keine realistischen Portr\u00e4ts) +- keine konkreten Alters-, Ethnie- oder Rollenklischees +- Fokus auf Handlung, Beziehung oder Prozess \u2013 nicht auf Drama +- positive, ruhige K\u00f6rpersprache +- ausreichend Freiraum (Whitespace), damit Text erg\u00e4nzt werden kann + +Komposition: +- klarer Bildaufbau, gut lesbar auch in klein +- geeignet f\u00fcr Website-Sektionen, Infoboxen oder Erkl\u00e4rgrafiken +- Hintergrund ruhig und nicht detailreich + +Ausschl\u00fcsse: +- keine Fotos, kein Fotorealismus +- keine Stock-Illustrations-Klischees +- keine kindlichen Comic-Stile +- keine starken Schatten, Glows oder Effekte`; + + const buildPrompt = () => { + const topic = topicInput.value.trim() || "[THEMA EINF\u00dcGEN]"; + return template.replace("{THEMA}", topic); + }; + + copyBtn.addEventListener("click", () => { + copyText(buildPrompt(), copyBtn.getAttribute("data-copy-label") || "Bildprompt kopiert"); + }); +})(); + +/* Tabs */ +(() => { + $$("[data-tabs]").forEach((tabs) => { + const buttons = $$(".tab", tabs); + const panels = $$(".tabs__panel", tabs); + + const activate = (btn) => { + buttons.forEach(b => { + const active = b === btn; + b.classList.toggle("is-active", active); + b.setAttribute("aria-selected", String(active)); + b.tabIndex = active ? 0 : -1; + }); + + const id = btn.getAttribute("aria-controls"); + panels.forEach(p => p.classList.toggle("is-active", p.id === id)); + }; + + buttons.forEach((btn) => { + btn.addEventListener("click", () => activate(btn)); + btn.addEventListener("keydown", (e) => { + const idx = buttons.indexOf(btn); + if (e.key === "ArrowRight") { e.preventDefault(); buttons[(idx + 1) % buttons.length].focus(); } + if (e.key === "ArrowLeft") { e.preventDefault(); buttons[(idx - 1 + buttons.length) % buttons.length].focus(); } + if (e.key === "Enter" || e.key === " ") { e.preventDefault(); activate(btn); } + }); + }); + }); +})(); + +/* Accordion */ +(() => { + $$("[data-accordion]").forEach((acc) => { + $$(".acc__trigger", acc).forEach((btn) => { + const panel = btn.nextElementSibling; + if (!panel) return; + + btn.addEventListener("click", () => { + const open = btn.getAttribute("aria-expanded") === "true"; + btn.setAttribute("aria-expanded", String(!open)); + panel.hidden = open; + }); + }); + }); +})(); + +/* Modal */ +(() => { + let lastFocus = null; + + const openModal = (modal) => { + if (!modal) return; + lastFocus = document.activeElement; + modal.hidden = false; + + const focusables = $$("button,[href],input,select,textarea,[tabindex]:not([tabindex='-1'])", modal) + .filter(el => !el.hasAttribute("disabled")); + const first = focusables[0]; + const last = focusables[focusables.length - 1]; + first?.focus(); + + const onKey = (e) => { + if (e.key === "Escape") closeModal(modal); + if (e.key !== "Tab") return; + if (!focusables.length) return; + + if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); } + else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); } + }; + + modal.__onKey = onKey; + document.addEventListener("keydown", onKey); + }; + + const closeModal = (modal) => { + if (!modal) return; + modal.hidden = true; + document.removeEventListener("keydown", modal.__onKey); + lastFocus?.focus?.(); + }; + + document.addEventListener("click", (e) => { + const openBtn = e.target.closest("[data-modal-open]"); + if (openBtn) { + const sel = openBtn.getAttribute("data-modal-open"); + openModal(document.querySelector(sel)); + return; + } + + const closeBtn = e.target.closest("[data-modal-close]"); + if (closeBtn) { + const modal = closeBtn.closest(".modal"); + closeModal(modal); + } + }); +})(); + +/* Demo form validation */ +(() => { + const form = document.querySelector("[data-demo-form]"); + if (!form) return; + + const status = $(".form__status", form); + + const setStatus = (msg, type="info") => { + status.textContent = msg; + status.style.marginTop = "6px"; + status.style.color = type === "danger" ? "var(--danger)" : "var(--muted)"; + }; + + form.addEventListener("submit", (e) => { + e.preventDefault(); + + const name = form.name.value.trim(); + const email = form.email.value.trim(); + const topic = form.topic.value.trim(); + const privacy = form.privacy.checked; + + const errors = []; + if (!name) errors.push("Name fehlt."); + if (!email || !email.includes("@")) errors.push("E-Mail ungültig."); + if (!topic) errors.push("Thema auswählen."); + if (!privacy) errors.push("Datenschutz bestätigen."); + + if (errors.length) { + setStatus("Bitte prüfen: " + errors.join(" "), "danger"); + Toast.show("Formular unvollständig."); + return; + } + + setStatus("Demo: Formular wäre jetzt versendet.", "info"); + Toast.show("Danke. Anfrage gespeichert (Demo)."); + form.reset(); + }); + + form.addEventListener("reset", () => setStatus("Zurückgesetzt.")); +})(); diff --git a/juconnect-strict-theme-v3/juconnect-strict/footer.php b/juconnect-strict-theme-v3/juconnect-strict/footer.php new file mode 100644 index 0000000..7b7b845 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/footer.php @@ -0,0 +1,14 @@ + + + + + + + +
+ + + + diff --git a/juconnect-strict-theme-v3/juconnect-strict/front-page.php b/juconnect-strict-theme-v3/juconnect-strict/front-page.php new file mode 100644 index 0000000..1066a6e --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/front-page.php @@ -0,0 +1,7 @@ + + + + + + + diff --git a/juconnect-strict-theme-v3/juconnect-strict/functions.php b/juconnect-strict-theme-v3/juconnect-strict/functions.php new file mode 100644 index 0000000..0827512 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/functions.php @@ -0,0 +1,85 @@ + 120, + 'width' => 120, + 'flex-height' => true, + 'flex-width' => true, + ]); + + register_nav_menus([ + 'primary' => __('Primary Navigation', 'juconnect'), + 'footer' => __('Footer Navigation', 'juconnect'), + ]); +} +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); +} +add_action('wp_enqueue_scripts', 'juconnect_assets'); + +/** + * Render primary nav in strict styleguide markup: + * - groups = top-level items + * - links = children + optionally the parent itself + */ +function juconnect_render_sidenav_nav() { + $locations = get_nav_menu_locations(); + if (!isset($locations['primary'])) return; + + $menu_obj = wp_get_nav_menu_object($locations['primary']); + if (!$menu_obj) return; + + $items = wp_get_nav_menu_items($menu_obj->term_id); + if (!$items) return; + + $by_parent = []; + foreach ($items as $it) { + $pid = (int)$it->menu_item_parent; + if (!isset($by_parent[$pid])) $by_parent[$pid] = []; + $by_parent[$pid][] = $it; + } + + $top = $by_parent[0] ?? []; + foreach ($top as $parent) { + echo ''; + } +} + + +// Add styleguide classes to WP menus +function juconnect_nav_link_attributes($atts, $item, $args, $depth){ + if (!empty($args->theme_location) && $args->theme_location === 'primary'){ + $existing = isset($atts['class']) ? $atts['class'].' ' : ''; + $atts['class'] = $existing . 'navlink'; + } + return $atts; +} +add_filter('nav_menu_link_attributes', 'juconnect_nav_link_attributes', 10, 4); + +function juconnect_nav_menu_submenu_class($classes, $args, $depth){ + if (!empty($args->theme_location) && $args->theme_location === 'primary'){ + $classes[] = 'topnav__submenu'; + } + return $classes; +} +add_filter('nav_menu_submenu_css_class', 'juconnect_nav_menu_submenu_class', 10, 3); diff --git a/juconnect-strict-theme-v3/juconnect-strict/header.php b/juconnect-strict-theme-v3/juconnect-strict/header.php new file mode 100644 index 0000000..54d9ad2 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/header.php @@ -0,0 +1,47 @@ + + +> + + + + + + + +> + + + +
+ +
+
+ + +
+
+
+
+
+ + +
+
+ + +
diff --git a/juconnect-strict-theme-v3/juconnect-strict/index.php b/juconnect-strict-theme-v3/juconnect-strict/index.php new file mode 100644 index 0000000..3f66938 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/index.php @@ -0,0 +1,19 @@ + + +
+
+

+

+
+ +
+ +
+

+

+
+ +
+
+ + diff --git a/juconnect-strict-theme-v3/juconnect-strict/page.php b/juconnect-strict-theme-v3/juconnect-strict/page.php new file mode 100644 index 0000000..1066a6e --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/page.php @@ -0,0 +1,7 @@ + + + + + + + diff --git a/juconnect-strict-theme-v3/juconnect-strict/style.css b/juconnect-strict-theme-v3/juconnect-strict/style.css new file mode 100644 index 0000000..5e28c18 --- /dev/null +++ b/juconnect-strict-theme-v3/juconnect-strict/style.css @@ -0,0 +1,943 @@ +/* +Theme Name: JuConnect (Strict Styleguide) +Author: Sven Steinert +Description: WordPress Theme basierend auf dem JuConnect Styleguide v0.2 (Markup & Tokens 1:1 übernommen). +Version: 0.3.0 +Text Domain: juconnect.de +*/ + +/* ========================= + JuConnect · Tool-first Styleguide (v0.2) + ========================= */ + +/* Source Sans 3 (lokal) */ +@font-face{ + font-family: "Source Sans 3"; + src: url("assets/fonts/SourceSans3-VariableFont_wght.ttf") format("truetype"); + font-weight: 200 900; + font-style: normal; + font-display: swap; +} +@font-face{ + font-family: "Source Sans 3"; + src: url("assets/fonts/SourceSans3-Italic-VariableFont_wght.ttf") format("truetype"); + font-weight: 200 900; + font-style: italic; + font-display: swap; +} + +:root{ + /* Brand */ + --primary: #1d354f; /* JuConnect Blau */ + --accent: #8FAE9A; /* Salbei warm (support only) */ + + /* Neutral scale (light) */ + --bg: #f6f7f8; + --surface: #ffffff; + --surface2: #eef1f3; + --text: #101922; + --text2: #3c4a58; + --muted: #607384; + --line: #d7dee5; + + /* Status */ + --info: #2b6cb0; + --success: #2f855a; + --warn: #b7791f; + --danger: #c53030; + + /* Typography */ + --font: "Source Sans 3", system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; + --fs-1: 2.0rem; /* H1 */ + --fs-2: 1.5rem; /* H2 */ + --fs-3: 1.125rem; /* H3 */ + --fs-b: 1.0rem; /* body */ + --fs-s: 0.92rem; /* small */ + + --lh-tight: 1.2; + --lh-base: 1.55; + + /* Layout */ + --maxw: 1120px; + --radius: 14px; + --radius-sm: 10px; + + /* Spacing */ + --s1: 6px; + --s2: 10px; + --s3: 14px; + --s4: 18px; + --s5: 24px; + --s6: 32px; + + /* Shadows */ + --shadow-sm: 0 6px 16px rgba(16, 25, 34, .08); + --shadow: 0 10px 28px rgba(16, 25, 34, .10); + + /* Focus (accent only for focus/marker) */ + --focus: 0 0 0 3px rgba(143, 174, 154, .35); + + /* Header/Hero gradient system */ + --header-shell-border: rgba(29,53,79,.16); + --header-grad-accent: rgba(143,174,154,.22); + --header-grad-primary: rgba(29,53,79,.10); +} + +[data-theme="dark"]{ + --bg: #0e1318; + --surface: #131a21; + --surface2: #18212a; + --text: #e8eef4; + --text2: #c2cdd8; + --muted: #9fb0c0; + --line: #24303b; + --shadow-sm: 0 8px 18px rgba(0,0,0,.35); + --shadow: 0 12px 30px rgba(0,0,0,.45); + --header-shell-border: rgba(143,174,154,.28); + --header-grad-accent: rgba(143,174,154,.18); + --header-grad-primary: rgba(143,174,154,.15); +} + +/* Base */ +*{ box-sizing: border-box; } +html, body{ height: 100%; } +body{ + margin: 0; + font-family: var(--font); + font-size: var(--fs-b); + line-height: var(--lh-base); + color: var(--text); + background: var(--bg); +} +code{ + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; + font-size: .95em; +} +a{ color: inherit; } +.hr{ + border: 0; + border-top: 1px solid var(--line); + margin: var(--s4) 0; +} +.spacer{ height: var(--s4); } + +/* Screen-reader only */ +.sr-only{ + position:absolute; + width:1px;height:1px; + padding:0;margin:-1px; + overflow:hidden;clip:rect(0,0,0,0); + white-space:nowrap;border:0; +} + +/* Skip Link */ +.skip-link{ + position: absolute; + left: -999px; + top: 10px; + background: var(--surface); + border: 1px solid var(--line); + padding: var(--s2) var(--s3); + border-radius: var(--radius-sm); + box-shadow: var(--shadow-sm); + z-index: 999; +} +.skip-link:focus{ + left: 10px; + outline: none; + box-shadow: var(--focus), var(--shadow-sm); +} + +/* App layout (ProcXera-ish) */ +.app{ + display: grid; + grid-template-columns: 320px 1fr; + min-height: 100vh; +} +@media (max-width: 1020px){ + .app{ grid-template-columns: 1fr; } +} + +/* Side nav (sticky) */ +.sidenav{ + border-right: 1px solid var(--line); + background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%); +} +.sidenav__inner{ + position: sticky; + top: 0; + min-height: 100vh; + padding: var(--s5); + display: flex; + flex-direction: column; +} +@media (max-width: 1020px){ + .sidenav__inner{ + position: static; + height: auto; + overflow: visible; + padding-bottom: var(--s4); + } +} + +.sidenav__top{ display:flex; flex-direction:column; gap: var(--s3); } +.brand{ + display:flex; + gap: var(--s3); + text-decoration:none; + align-items:center; +} +.brand__logo{ + width: 44px; height: 44px; + border-radius: 12px; +} +.brand__name{ font-weight: 800; letter-spacing: .2px; } +.brand__tagline{ font-size: var(--fs-s); color: var(--muted); } + +.sidenav__actions{ display:flex; gap: 8px; flex-wrap: wrap; } + +.sidenav__search{ margin-top: var(--s2); } +.input--sm{ padding: 8px 10px; border-radius: 12px; font-size: var(--fs-s); } + +.sidenav__nav{ + margin-top: var(--s4); + display:flex; + flex-direction:column; + gap: var(--s3); +} +.navgroup__title{ + font-size: var(--fs-s); + color: var(--muted); + text-transform: uppercase; + letter-spacing: .08em; + margin: var(--s2) 0; +} +.navlink{ + text-decoration:none; + padding: 10px 12px; + border-radius: 12px; + color: var(--text2); + border: 1px solid transparent; + display:block; +} +.navlink:hover{ + background: var(--surface2); + color: var(--text); +} +.navlink.is-active{ + background: rgba(29,53,79,.10); + color: var(--text); + border-color: rgba(29,53,79,.18); +} +.sidenav__bottom{ margin-top: auto; padding-top: var(--s5); } + +@media (min-width: 1021px) and (max-height: 1080px){ + .sidenav__inner{ padding: var(--s4); } + .sidenav__top{ gap: var(--s2); } + .sidenav__nav{ margin-top: var(--s3); gap: var(--s2); } + .navgroup__title{ margin: var(--s1) 0; } + .navlink{ padding: 8px 10px; } + .sidenav__bottom{ padding-top: var(--s4); } +} + +.mini-note{ + border: 1px solid var(--line); + background: var(--surface); + border-radius: var(--radius); + padding: var(--s4); + box-shadow: var(--shadow-sm); +} +.mini-note__title{ font-weight: 800; margin-bottom: 6px; } +.mini-note__text{ color: var(--muted); font-size: var(--fs-s); } + +/* Main */ +.main{ + padding: var(--s6); + max-width: calc(var(--maxw) + 2*var(--s6)); +} +@media (max-width: 1020px){ + .main{ padding: var(--s5); } +} + +/* Page head */ +.pagehead{ + display:grid; + grid-template-columns: 1fr 340px; + gap: var(--s5); + align-items: start; + margin-bottom: var(--s6); + position: relative; + padding: var(--s6); + border: 1px solid var(--header-shell-border); + border-radius: 20px; + background: + radial-gradient(120% 140% at 100% 0%, var(--header-grad-accent) 0%, rgba(143,174,154,0) 50%), + radial-gradient(120% 140% at 0% 100%, var(--header-grad-primary) 0%, rgba(29,53,79,0) 60%), + var(--surface); + box-shadow: var(--shadow-sm); + overflow: hidden; +} +@media (max-width: 1020px){ + .pagehead{ + grid-template-columns: 1fr; + padding: var(--s5); + } +} +.pagehead__left{ + display: flex; + flex-direction: column; + gap: var(--s3); +} +.pagehead__eyebrow{ + display: flex; + align-items: center; + gap: var(--s2); +} +.pagehead__chips{ + display:flex; + gap: 10px; + flex-wrap: wrap; +} +.pagehead__brand img{ + display: block; + width: auto; + height: 104px; +} +.pagehead .h1{ + font-size: clamp(2rem, 3.2vw, 2.7rem); + margin: 0; +} +.pagehead .lead{ + max-width: 64ch; +} +.pagehead__right .card{ + border-color: var(--header-shell-border); + background: var(--surface); +} +@media (max-width: 1020px){ + .pagehead__brand img{ height: 84px; } +} + +/* Sections */ +.section{ margin: 0 0 var(--s6) 0; } +.section__head{ margin-bottom: var(--s4); } +.footer{ + padding-top: var(--s4); + border-top: 1px solid var(--line); +} + +/* Typography helpers */ +.h1{ font-size: var(--fs-1); line-height: var(--lh-tight); margin: 0 0 var(--s2) 0; } +.h2{ font-size: var(--fs-2); line-height: 1.25; margin: 0 0 var(--s2) 0; } +.h3{ font-size: var(--fs-3); line-height: 1.25; margin: 0; } +.lead{ font-size: 1.1rem; color: var(--text2); margin: 0; max-width: 75ch; } +.muted{ color: var(--muted); } +.typeset p{ max-width: 75ch; } + +/* Layout utilities */ +.grid{ display:grid; gap: var(--s4); } +.grid--2{ grid-template-columns: repeat(2, minmax(0, 1fr)); } +.grid--3{ grid-template-columns: repeat(3, minmax(0, 1fr)); } +.section > .grid + .grid{ margin-top: var(--s4); } +.section > .grid + .card, +.section > .card + .grid{ margin-top: var(--s4); } +@media (max-width: 1020px){ + .grid--2, .grid--3{ grid-template-columns: 1fr; } +} +.row{ display:flex; gap: var(--s2); align-items:center; } +.wrap{ flex-wrap: wrap; } + +/* Cards */ +.card{ + background: var(--surface); + border: 1px solid var(--line); + border-radius: var(--radius); + padding: var(--s5); + box-shadow: var(--shadow-sm); +} +.card--tight{ padding: var(--s4); } +.card:not(.card--tight):not(.swatch) > * + *{ margin-top: var(--s4); } +.card:not(.card--tight):not(.swatch) > .card__head{ margin-bottom: 0; } +.card__head{ + display:flex; + align-items:center; + justify-content: space-between; + gap: var(--s3); + margin-bottom: var(--s3); +} + +/* KPI */ +.kpi{ display:flex; justify-content: space-between; gap: var(--s3); padding: 10px 0; border-bottom: 1px solid var(--line); } +.kpi:last-child{ border-bottom: 0; } +.kpi__label{ color: var(--muted); font-size: var(--fs-s); } +.kpi__value{ font-weight: 800; color: var(--text2); } + +/* Pills with copy */ +.pill{ + display:inline-flex; + align-items:center; + gap: 10px; + border: 1px solid var(--line); + background: var(--surface); + border-radius: 999px; + padding: 8px 10px 8px 12px; + color: var(--text2); +} +.pill__dot{ + width: 10px; height: 10px; + border-radius: 999px; + background: var(--primary); +} +.pill--accent .pill__dot{ background: var(--accent); } +.pill__copy{ + border: 1px solid var(--line); + background: var(--surface2); + border-radius: 999px; + width: 28px; height: 28px; + cursor: pointer; +} +.pill__copy:hover{ filter: brightness(0.98); } + +/* Links */ +.link{ + color: var(--primary); + text-underline-offset: 3px; +} +.link:hover{ text-decoration-thickness: 2px; } + +/* Focus */ +:focus-visible{ outline: none; box-shadow: var(--focus); border-radius: 10px; } + +/* Buttons */ +.btn{ + border: 1px solid transparent; + background: transparent; + color: var(--text); + padding: 10px 14px; + border-radius: 12px; + cursor: pointer; + font: inherit; + display:inline-flex; + align-items:center; + gap: 10px; + transition: transform .06s ease, background .15s ease, border-color .15s ease, filter .15s ease; +} +.btn:active{ transform: translateY(1px); } +.btn[disabled]{ opacity: .55; cursor: not-allowed; transform: none; } + +.btn--primary{ + background: var(--primary); + border-color: rgba(0,0,0,.06); + color: #fff; +} +.btn--primary:hover{ filter: brightness(0.98); } + +.btn--secondary{ + background: var(--surface2); + border-color: var(--line); + color: var(--text); +} +.btn--secondary:hover{ filter: brightness(0.98); } + +.btn--ghost{ + border-color: var(--line); + background: transparent; + color: var(--text); +} +.btn--ghost:hover{ background: var(--surface2); } + +.btn--danger{ + border-color: rgba(197,48,48,.35); + background: rgba(197,48,48,.10); + color: var(--danger); +} + +.btn--sm{ padding: 8px 10px; border-radius: 12px; font-size: var(--fs-s); } +.btn--icon{ padding: 8px 10px; } + +.btn__icon{ opacity: .9; } + +/* Lists */ +.list{ margin: 0; padding-left: 18px; color: var(--text2); } +.list li{ margin: 6px 0; } + +/* Badges */ +.badge{ + display:inline-flex; + align-items:center; + padding: 6px 10px; + border-radius: 999px; + border: 1px solid var(--line); + font-size: var(--fs-s); + color: var(--text2); + background: var(--surface2); +} +.badge--info{ border-color: rgba(43,108,176,.35); background: rgba(43,108,176,.10); color: var(--info); } +.badge--success{ border-color: rgba(47,133,90,.35); background: rgba(47,133,90,.10); color: var(--success); } +.badge--warn{ border-color: rgba(183,121,31,.35); background: rgba(183,121,31,.12); color: var(--warn); } +.badge--danger{ border-color: rgba(197,48,48,.35); background: rgba(197,48,48,.12); color: var(--danger); } + +/* Callouts */ +.callout{ + border-radius: var(--radius); + border: 1px solid var(--line); + background: var(--surface2); + padding: var(--s4); +} +.callout__title{ font-weight: 800; margin-bottom: 4px; } +.callout__text{ color: var(--text2); } +.callout--info{ border-color: rgba(43,108,176,.28); background: rgba(43,108,176,.08); } +.callout--accent{ border-color: rgba(143,174,154,.35); background: rgba(143,174,154,.10); } + +/* Forms */ +.form{ display:flex; flex-direction:column; gap: var(--s4); } +.field{ display:flex; flex-direction:column; gap: 6px; } +.field--inline{ flex-direction: row; align-items: center; justify-content: space-between; gap: var(--s3); } +.label{ font-weight: 800; color: var(--text2); } +.help{ font-size: var(--fs-s); color: var(--muted); } +.error{ font-size: var(--fs-s); color: var(--danger); } +.field.is-error .input, +.field.is-error .select, +.field.is-error .textarea{ + border-color: rgba(197,48,48,.55); + box-shadow: 0 0 0 3px rgba(197,48,48,.12); +} + +.input, .select, .textarea{ + width: 100%; + border: 1px solid var(--line); + background: var(--surface); + color: var(--text); + border-radius: 12px; + padding: 10px 12px; + font: inherit; + transition: border-color .15s ease, box-shadow .15s ease, background .15s ease; +} +.input::placeholder, .textarea::placeholder{ color: var(--muted); } +.input:focus, .select:focus, .textarea:focus{ + outline: none; + border-color: rgba(29,53,79,.55); + box-shadow: var(--focus); +} + +.check{ display:flex; align-items:center; gap: 10px; } +.check__box{ width: 18px; height: 18px; } + +/* Snippets (tool-first copy blocks) */ +.snippet{ + border: 1px solid var(--line); + border-radius: var(--radius); + background: var(--surface); + overflow: hidden; +} +.snippet__head{ + display:flex; + align-items:center; + justify-content: space-between; + gap: var(--s3); + padding: 12px 14px; + background: var(--surface2); + border-bottom: 1px solid var(--line); +} +.snippet__title{ font-weight: 800; color: var(--text2); } +.snippet__code{ + margin: 0; + padding: 14px; + overflow:auto; + font-size: 0.92rem; + line-height: 1.5; + background: var(--surface); +} + +/* Swatches */ +.swatch{ display:flex; align-items:flex-start; gap: var(--s4); } +.swatch__chip{ + width: 58px; height: 58px; + border-radius: 16px; + border: 1px solid var(--line); + flex: 0 0 auto; +} +.swatch__chip--primary{ background: var(--primary); border-color: rgba(0,0,0,.08); } +.swatch__chip--accent{ background: var(--accent); border-color: rgba(0,0,0,.08); } +.swatch__chip--bg{ background: var(--bg); } +.swatch__name{ font-weight: 800; margin-bottom: 4px; } +.swatch__row{ color: var(--muted); font-size: var(--fs-s); display:flex; align-items:center; gap: 8px; flex-wrap: wrap; } +.dot{ opacity: .7; } +.swatch__actions{ margin-top: 10px; display:flex; gap: 8px; } +.gradient-preview{ + height: 120px; + border-radius: var(--radius-sm); + border: 1px solid var(--header-shell-border); + background: + radial-gradient(120% 140% at 100% 0%, var(--header-grad-accent) 0%, rgba(143,174,154,0) 50%), + radial-gradient(120% 140% at 0% 100%, var(--header-grad-primary) 0%, rgba(29,53,79,0) 60%), + var(--surface); +} +.image-grid{ + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--s3); +} +.image-card{ + margin: 0; + border: 1px solid var(--line); + border-radius: var(--radius-sm); + padding: var(--s2); + background: var(--surface2); +} +.image-card img{ + display: block; + width: 100%; + height: 180px; + object-fit: cover; + border-radius: 10px; +} +.image-card figcaption{ + margin-top: var(--s2); + font-size: var(--fs-s); +} +@media (max-width: 760px){ + .image-grid{ grid-template-columns: 1fr; } +} + +/* Logo demo */ +.logo-demo{ display:grid; grid-template-columns: 1fr 1fr; gap: var(--s3); } +@media (max-width: 520px){ .logo-demo{ grid-template-columns: 1fr; } } +.logo-demo__label{ font-size: var(--fs-s); color: var(--muted); margin-bottom: 6px; } +.logo-demo__surface{ + border-radius: var(--radius); + border: 1px solid var(--line); + padding: var(--s4); + display:flex; + align-items:center; + justify-content:center; +} +.logo-demo__surface--light{ background: #fff; } +.logo-demo__surface--dark{ background: var(--primary); } +.logo-demo--icon .logo-demo__surface{ min-height: 130px; } +.logo-demo__icon{ + width: 64px; + height: 64px; +} +.logo-downloads{ + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--s2); + align-items: stretch; +} +.logo-downloads .btn{ + justify-content: center; + text-decoration: none; +} +@media (max-width: 640px){ + .logo-downloads{ grid-template-columns: 1fr; } +} + +/* Tabs */ +.tabs__list{ + display:flex; + gap: 8px; + border-bottom: 1px solid var(--line); + padding-bottom: 10px; +} +.tab{ + border: 1px solid var(--line); + background: var(--surface); + color: var(--text2); + padding: 8px 12px; + border-radius: 12px; + cursor: pointer; + font: inherit; +} +.tab:hover{ background: var(--surface2); } +.tab.is-active{ + background: rgba(29,53,79,.10); + border-color: rgba(29,53,79,.18); + color: var(--text); +} +.tabs__panel{ padding-top: var(--s3); display:none; } +.tabs__panel.is-active{ display:block; } + +/* Accordion */ +.accordion{ display:flex; flex-direction:column; gap: 8px; } +.acc__trigger{ + width: 100%; + text-align: left; + border: 1px solid var(--line); + background: var(--surface); + color: var(--text); + padding: 12px 14px; + border-radius: 12px; + cursor: pointer; + display:flex; + align-items:center; + justify-content: space-between; + gap: 12px; +} +.acc__trigger:hover{ background: var(--surface2); } +.acc__panel{ + border: 1px solid var(--line); + border-top: 0; + background: var(--surface); + border-radius: 0 0 12px 12px; + padding: 12px 14px; + margin-top: -8px; +} + +/* Table */ +.tablewrap{ overflow:auto; } +.table{ + width: 100%; + border-collapse: collapse; + min-width: 520px; +} +.table th, .table td{ + text-align: left; + padding: 12px 10px; + border-bottom: 1px solid var(--line); +} +.table th{ color: var(--text2); font-weight: 800; background: var(--surface2); } +.table tr:hover td{ background: rgba(29,53,79,.05); } + +@media (min-width: 1021px){ + #layout .layout__table{ grid-column: 1 / -1; } +} + +/* Hero pattern */ +.hero{ + margin-top: var(--s4); + border-radius: var(--radius); + border: 1px solid var(--header-shell-border); + background: + radial-gradient(120% 140% at 100% 0%, var(--header-grad-accent) 0%, rgba(143,174,154,0) 50%), + radial-gradient(120% 140% at 0% 100%, var(--header-grad-primary) 0%, rgba(29,53,79,0) 60%), + var(--surface); + padding: var(--s6); +} +.hero__inner{ max-width: 75ch; } +.hero .row{ margin-top: var(--s3); } + +/* Modal */ +.modal{ + position: fixed; + inset: 0; + display:grid; + place-items: center; + z-index: 1000; +} +.modal[hidden]{ display:none !important; } +.modal__backdrop{ + position:absolute; + inset: 0; + background: rgba(0,0,0,.35); + z-index: 0; +} +.modal__panel{ + position: relative; + z-index: 1; + width: min(640px, calc(100% - 32px)); + border-radius: var(--radius); + border: 1px solid var(--line); + background: var(--surface); + box-shadow: var(--shadow); + overflow: hidden; +} +.modal__head, .modal__foot{ + padding: var(--s4) var(--s5); + display:flex; + align-items:center; + justify-content: space-between; + gap: var(--s3); + background: var(--surface2); +} +.modal__body{ padding: var(--s5); } + +/* Toasts */ +.toasts{ + position: fixed; + right: 18px; + bottom: 18px; + display:flex; + flex-direction: column; + gap: 10px; + z-index: 1100; +} +.toast{ + width: min(380px, calc(100vw - 36px)); + border: 1px solid var(--line); + background: var(--surface); + border-radius: 14px; + padding: 12px 14px; + box-shadow: var(--shadow-sm); + display:flex; + justify-content: space-between; + gap: 12px; +} +.toast__text{ color: var(--text2); } +.toast__close{ border: 0; background: transparent; cursor:pointer; font: inherit; color: var(--muted); } +.toast__close:hover{ color: var(--text); } + +/* Tooltip */ +.tooltip{ + position: fixed; + z-index: 1200; + pointer-events: none; + max-width: 320px; + border: 1px solid var(--line); + background: var(--surface); + color: var(--text2); + border-radius: 12px; + padding: 10px 12px; + box-shadow: var(--shadow-sm); + font-size: var(--fs-s); +} + + +/* ========================= + Strict WP additions + ========================= */ + +/* Switch from sidebar grid to top navigation layout */ +.app{ + display:block; + min-height: 100vh; +} +.main{ + margin: 0 auto; + max-width: calc(var(--maxw) + 2*var(--s6)); +} + +/* Top navigation (built from existing tokens/components) */ +.topnav{ + position: sticky; + top: 0; + z-index: 20; + border-bottom: 1px solid var(--line); + background: linear-gradient(180deg, var(--surface) 0%, var(--bg) 100%); +} +.topnav__inner{ + max-width: calc(var(--maxw) + 2*var(--s6)); + margin: 0 auto; + padding: var(--s4) var(--s6); + display:flex; + align-items:center; + justify-content: space-between; + gap: var(--s5); +} +@media (max-width: 1020px){ + .topnav__inner{ padding: var(--s4) var(--s5); flex-wrap: wrap; } +} + +.topnav__list{ + list-style:none; + display:flex; + align-items:center; + gap: 8px; + margin: 0; + padding: 0; + flex-wrap: wrap; + justify-content: flex-end; +} +.topnav__list > li{ position: relative; } +.topnav__list a.navlink{ + display:inline-flex; + align-items:center; + text-decoration:none; + padding: 10px 12px; + border-radius: 12px; + color: var(--text2); + border: 1px solid transparent; +} +.topnav__list a.navlink:hover{ + background: var(--surface2); + color: var(--text); + border-color: rgba(29,53,79,.10); +} +.topnav__list .current-menu-item > a.navlink, +.topnav__list .current-page-ancestor > a.navlink{ + background: rgba(29,53,79,.10); + border-color: rgba(29,53,79,.18); + color: var(--text); +} + +/* Submenu dropdown */ +.topnav__submenu{ + list-style:none; + position:absolute; + top: calc(100% + 8px); + right: 0; + min-width: 240px; + margin: 0; + padding: 8px; + border: 1px solid var(--line); + border-radius: 14px; + background: var(--surface); + box-shadow: var(--shadow); + display:none; +} +.topnav__list li:hover > .topnav__submenu{ display:block; } +.topnav__submenu a.navlink{ + display:flex; + width: 100%; + padding: 10px 12px; + border-radius: 12px; +} + +/* Hide original sidenav if any page still contains it */ +.sidenav{ display:none !important; } + +/* WordPress content niceties using existing tokens */ +.prose :where(p,ul,ol){ max-width: 72ch; } +.prose a{ color: var(--primary); text-underline-offset: 3px; } + + +/* ========================= + WP block bridges (Gutenberg) + ========================= */ + +/* Keep WP editor output from fighting the design system */ + +/* Buttons: apply JuConnect .btn styles to the actual clickable element */ +.wp-block-button .wp-block-button__link{ + border: 1px solid var(--line); + border-radius: 14px; + padding: 12px 14px; + font-weight: 700; + text-decoration: none; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + background: var(--surface); + color: var(--text); +} + +/* When the Button block carries JuConnect classes, map them to the link */ +.wp-block-button.btn--primary .wp-block-button__link{ + background: var(--primary); + border-color: rgba(29,53,79,.35); + color: #fff; +} +.wp-block-button.btn--secondary .wp-block-button__link{ + background: rgba(29,53,79,.10); + border-color: rgba(29,53,79,.18); + color: var(--text); +} +.wp-block-button.btn--ghost .wp-block-button__link{ + background: transparent; + border-color: var(--line); + color: var(--text); +} + +/* Button spacing: match styleguide rhythm */ +.wp-block-buttons{ gap: 10px; } +.wp-block-buttons .wp-block-button{ margin: 0; } + +/* Groups: don't add unexpected margins that break cards/grids */ +.wp-block-group{ margin: 0; } + +/* Images: prevent WP default inline styles from breaking rounded cards */ +.wp-block-image img{ max-width: 100%; height: auto; } + +/* Default content wrapper for pages without patterns (optional) */ +.main > .wp-block-group.section:first-child{ margin-top: 0; }