/* ============================================================
   JJW Project Solutions — shared design system
   Source: Marken- & Website-Umsetzungsdokument v1.5, Kapitel 2 & 11.
   Used by every page (Hub + AI spoke + Retail spoke). Page-specific
   sections (hub's photo hero, the Jeremy trust block, spoke heroes)
   live in each page's own <style> block, on top of this file.

   Color/type/layout VALUES live in tokens.css (--jjw-* — the source
   of truth Ionut scaffolded from the Brand Book + Umsetzungsdokument).
   This file just aliases the shorter --navy/--accent-blue/... names
   already used throughout the existing markup onto those tokens, so
   there's exactly one place the actual hex/px values are defined.
   Load order: tokens.css, then outfit-fontface.css, then this file.
   ============================================================ */

:root{
  --navy:var(--jjw-navy); --navy-75:var(--jjw-navy-75); --navy-50:var(--jjw-navy-50); --navy-25:var(--jjw-navy-25);
  --accent-blue:var(--jjw-accent-blue); --black:var(--jjw-black);
  --silver:var(--jjw-silver-grey); --silver-75:var(--jjw-silver-grey-75); --silver-50:var(--jjw-silver-grey-50); --silver-25:var(--jjw-silver-grey-25);
  --light-grey:var(--jjw-light-grey);
  --amber:var(--jjw-amber); --amber-25:var(--jjw-amber-25);
  --mint:var(--jjw-mint); --mint-25:var(--jjw-mint-25);
  --text-body:var(--jjw-text-body); --hairline:var(--jjw-border-hairline);
  --font:var(--jjw-font-family);
  --maxw:var(--jjw-max-width);
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
/* keep iOS/Chrome from inflating body copy when a phone is held landscape */
html{-webkit-text-size-adjust:100%; text-size-adjust:100%;}
body{
  font-family:var(--font);
  color:var(--text-body);
  background:#fff;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
@media (prefers-reduced-motion: no-preference){
  a, button { transition: background-color .15s ease, border-color .15s ease, color .15s ease; }
}
.wrap{max-width:var(--maxw); margin:0 auto; padding:0 24px; box-sizing:border-box; width:100%;}
a{color:inherit;}
h1,h2,h3,h4{color:var(--navy); font-weight:600; margin:0;}
h1{font-size:var(--jjw-h1); line-height:1.15;}
h2{font-size:var(--jjw-h2); line-height:1.2;}
h3{font-size:var(--jjw-h3); font-weight:600;}
h4{font-size:var(--jjw-h4); font-weight:600;}
p{margin:0; font-size:var(--jjw-body); line-height:1.6;}
.sub, .lead{font-size:var(--jjw-subline); line-height:1.55; color:var(--navy-75);}
.kicker{
  font-size:var(--jjw-kicker); font-weight:600; text-transform:uppercase; letter-spacing:.08em; color:var(--navy-75);
}
button:focus-visible, a:focus-visible{
  outline:2px solid var(--navy); outline-offset:2px;
}
/* responsive h1-h4 sizing comes from tokens.css's --jjw-h* overrides at 640px — no duplicate media query needed here */

/* ---- Header ----
   Three states, driven by mobile-nav.js (owner's brief, 2026-10-20):
   - at the top of the page: the full header, see-through over the banner on
     the hero pages (.chrome-overlay) and a navy bar on the plain pages;
   - scrolling down: it fades out over its own height, then stays out of the
     way (.header--hidden);
   - scrolling back up: a compact navy header slides in (.is-stuck), and the
     full one returns once the reader is back at the top.
   The bar is attached to the top of the viewport throughout. On the plain
   pages it is sticky; on the hero pages it is fixed, so it can lie over the
   banner. */
header{
  position:sticky; top:0; z-index:90;
  border-bottom:1px solid var(--hairline);
  background:#fff;
  transition:transform .28s cubic-bezier(.16,1,.3,1), opacity .2s ease, background-color .25s ease, box-shadow .25s ease;
}
body .chrome-overlay{
  position:fixed; top:0; left:0; right:0; z-index:90;
  transition:transform .28s cubic-bezier(.16,1,.3,1), opacity .2s ease, background-color .25s ease, box-shadow .25s ease;
}
header.header--hidden,
body .chrome-overlay.header--hidden{transform:translateY(-100%);}
.chrome-overlay.is-stuck{
  background:var(--navy);
  box-shadow:0 4px 18px rgba(9,18,30,.22);
  border-bottom:1px solid rgba(255,255,255,.12);
}
header.is-stuck{box-shadow:0 4px 18px rgba(9,18,30,.22);}
.chrome-overlay.is-stuck nav.primary > a,
.chrome-overlay.is-stuck nav.primary > .nav-item > a,
.chrome-overlay.is-stuck .lang-switch{text-shadow:none;}
.chrome-overlay.is-stuck .header-inner,
header.is-stuck .header-inner{padding-top:10px; padding-bottom:10px;}
.chrome-overlay.is-stuck .logo-svg,
header.is-stuck .logo .logo-svg{height:54px; filter:none;}
.chrome-overlay.is-stuck .header-right .btn,
header.is-stuck .header-right .btn{font-size:13.5px; padding:8px 16px; min-height:36px;}
[id]{scroll-margin-top:84px;}
@media (prefers-reduced-motion:reduce){
  .chrome-overlay, header{transition:none;}
}
header .header-right .btn{font-size:15px; padding:10px 20px; min-height:42px; white-space:nowrap;}
.header-inner{display:grid; grid-template-columns:1fr auto 1fr; align-items:center; padding:18px 28px; gap:28px; transition:padding .2s ease;}
.logo{display:flex; align-items:center;}
.logo-svg{height:84px; width:auto; display:block; transition:height .2s ease;}
nav.primary{display:flex; gap:30px; font-size:16px; font-weight:500;}
nav.primary a{text-decoration:none; color:var(--navy); padding-bottom:4px; border-bottom:2px solid transparent;}
nav.primary a:hover{border-bottom-color:var(--navy-25);}
nav.primary a.nav-active-ai,
nav.primary a[href^="/ai"]:hover,
nav.primary a[href^="/en/ai"]:hover,
nav.primary .nav-item:hover > a[href^="/ai"],
nav.primary .nav-item:hover > a[href^="/en/ai"],
nav.primary .nav-item:focus-within > a[href^="/ai"],
nav.primary .nav-item:focus-within > a[href^="/en/ai"],
.chrome-overlay nav.primary a[href^="/ai"]:hover,
.chrome-overlay nav.primary a[href^="/en/ai"]:hover,
.chrome-overlay nav.primary .nav-item:hover > a[href^="/ai"],
.chrome-overlay nav.primary .nav-item:hover > a[href^="/en/ai"],
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/ai"],
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/en/ai"]{
  border-bottom-color:var(--mint);
}
nav.primary a.nav-active-retail,
nav.primary a[href^="/retail-it"]:hover,
nav.primary a[href^="/en/retail-it"]:hover,
nav.primary .nav-item:hover > a[href^="/retail-it"],
nav.primary .nav-item:hover > a[href^="/en/retail-it"],
nav.primary .nav-item:focus-within > a[href^="/retail-it"],
nav.primary .nav-item:focus-within > a[href^="/en/retail-it"],
.chrome-overlay nav.primary a[href^="/retail-it"]:hover,
.chrome-overlay nav.primary a[href^="/en/retail-it"]:hover,
.chrome-overlay nav.primary .nav-item:hover > a[href^="/retail-it"],
.chrome-overlay nav.primary .nav-item:hover > a[href^="/en/retail-it"],
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/retail-it"],
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/en/retail-it"]{
  border-bottom-color:var(--amber);
}
/* Home, Über uns, Insights, Kontakt and KMU.DIGITAL are Dachmarke, not a
   sub-brand — amber belongs to Retail and mint to AI (see tokens.css), so their
   marker takes the link's own colour: white over the hero, navy on light
   headers. /kontakt used to carry .nav-active-retail, which put an amber rule
   under a tab that has nothing to do with Retail; -team and -news were spelled
   in the markup but never defined here, so those tabs had no marker at all. */
nav.primary a.nav-active-home,
nav.primary a.nav-active-team,
nav.primary a.nav-active-news,
nav.primary a.nav-active-contact,
nav.primary a.nav-active-keynote{border-bottom-color:currentColor;}

/* ---- Nav dropdowns (Website-Review v1: "Netzwerk beitreten" und "AI Angebot"
   sollten als eigene Reiter erreichbar sein). Two spokes have more than one
   page each, and eight flat tabs do not survive a 1024px laptop next to the
   longer CTA — so each spoke keeps one tab and opens a panel. The parent link
   still navigates: the panel is progressive enhancement, never the only route.
   nav.primary is display:none below 900px; the drawer in mobile-nav.js renders
   the same groups as an indented list. ---- */
.nav-item{position:relative; display:inline-flex; align-items:center;}
.nav-item > a{display:inline-flex; align-items:center; gap:5px;}
.nav-item > a::after{
  content:""; width:0; height:0; margin-top:1px;
  border-left:3.5px solid transparent; border-right:3.5px solid transparent;
  border-top:4px solid currentColor; opacity:.6;
  transition:border-top-color .15s ease, opacity .15s ease, transform .15s ease;
}
.nav-item:hover > a::after,
.nav-item:focus-within > a::after{opacity:1; transform:translateY(1px);}

/* Sub-brand carets when hovering / open / active */
.nav-item:hover > a[href^="/retail-it"]::after,
.nav-item:hover > a[href^="/en/retail-it"]::after,
.nav-item:focus-within > a[href^="/retail-it"]::after,
.nav-item:focus-within > a[href^="/en/retail-it"]::after,
nav.primary a.nav-active-retail::after,
.chrome-overlay nav.primary .nav-item:hover > a[href^="/retail-it"]::after,
.chrome-overlay nav.primary .nav-item:hover > a[href^="/en/retail-it"]::after,
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/retail-it"]::after,
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/en/retail-it"]::after{
  border-top-color:var(--amber);
  opacity:1;
}
.nav-item:hover > a[href^="/ai"]::after,
.nav-item:hover > a[href^="/en/ai"]::after,
.nav-item:focus-within > a[href^="/ai"]::after,
.nav-item:focus-within > a[href^="/en/ai"]::after,
nav.primary a.nav-active-ai::after,
.chrome-overlay nav.primary .nav-item:hover > a[href^="/ai"]::after,
.chrome-overlay nav.primary .nav-item:hover > a[href^="/en/ai"]::after,
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/ai"]::after,
.chrome-overlay nav.primary .nav-item:focus-within > a[href^="/en/ai"]::after{
  border-top-color:var(--mint);
  opacity:1;
}
.nav-item:hover > a[href*="insight"]::after,
.nav-item:focus-within > a[href*="insight"]::after,
nav.primary a.nav-active-insights::after,
.chrome-overlay nav.primary .nav-item:hover > a[href*="insight"]::after,
.chrome-overlay nav.primary .nav-item:focus-within > a[href*="insight"]::after{
  border-top-color:var(--accent-blue);
  opacity:1;
}

.nav-sub{
  position:absolute; top:calc(100% + 8px); left:-16px; z-index:60;
  display:flex; flex-direction:column; min-width:256px; padding:6px 0;
  background:#fff; border:1px solid var(--hairline); border-radius:var(--jjw-radius-control);
  box-shadow:0 18px 44px rgba(9,18,30,.16);
  opacity:0; visibility:hidden; transform:translateY(-4px);
  transition:opacity .16s ease, transform .16s ease, visibility 0s linear .16s;
  overflow:hidden;
}
.nav-sub::before{
  content:""; position:absolute; top:-12px; left:0; right:0; height:12px;
}
.nav-item:hover > .nav-sub,
.nav-item:focus-within > .nav-sub{
  opacity:1; visibility:visible; transform:translateY(0); transition-delay:0s;
}

/* Sub-brand top accent border on dropdown panels */
.nav-item:has(> a[href^="/retail-it"]) .nav-sub,
.nav-item:has(> a[href^="/en/retail-it"]) .nav-sub,
nav.primary a[href^="/retail-it"] + .nav-sub,
nav.primary a[href^="/en/retail-it"] + .nav-sub,
.chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub,
.chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub,
body .chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub,
body .chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub{
  border-top:3px solid var(--amber);
}
.nav-item:has(> a[href^="/ai"]) .nav-sub,
.nav-item:has(> a[href^="/en/ai"]) .nav-sub,
nav.primary a[href^="/ai"] + .nav-sub,
nav.primary a[href^="/en/ai"] + .nav-sub,
.chrome-overlay nav.primary a[href^="/ai"] + .nav-sub,
.chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub,
body .chrome-overlay nav.primary a[href^="/ai"] + .nav-sub,
body .chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub{
  border-top:3px solid var(--mint);
}
.nav-item:has(> a[href*="insight"]) .nav-sub,
nav.primary a[href*="insight"] + .nav-sub,
.chrome-overlay nav.primary a[href*="insight"] + .nav-sub,
body .chrome-overlay nav.primary a[href*="insight"] + .nav-sub{
  border-top:3px solid var(--accent-blue);
}

/* Dropdown items base styling */
nav.primary .nav-sub a,
.chrome-overlay nav.primary .nav-sub a,
body .chrome-overlay nav.primary .nav-sub a,
.nav-sub a{
  display:block;
  padding:9px 18px;
  font-size:14.5px;
  font-weight:500;
  white-space:nowrap;
  color:var(--navy) !important;
  text-shadow:none !important;
  border-bottom:none !important;
  border-left:3px solid transparent !important;
  text-decoration:none;
  transition:background-color .15s ease, color .15s ease, border-left-color .15s ease, padding-left .15s ease;
}

/* Retail dropdown links hover & active state */
.nav-item:has(> a[href^="/retail-it"]) .nav-sub a:hover,
.nav-item:has(> a[href^="/retail-it"]) .nav-sub a:focus,
.nav-item:has(> a[href^="/en/retail-it"]) .nav-sub a:hover,
.nav-item:has(> a[href^="/en/retail-it"]) .nav-sub a:focus,
nav.primary a[href^="/retail-it"] + .nav-sub a:hover,
nav.primary a[href^="/retail-it"] + .nav-sub a:focus,
nav.primary a[href^="/en/retail-it"] + .nav-sub a:hover,
nav.primary a[href^="/en/retail-it"] + .nav-sub a:focus,
.chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub a:hover,
.chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub a:focus,
.chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub a:hover,
.chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub a:focus,
body .chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub a:hover,
body .chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub a:focus,
body .chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub a:hover,
body .chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub a:focus,
.nav-sub a[href^="/retail-it"]:hover,
.nav-sub a[href^="/retail-it"]:focus,
.nav-sub a[href^="/en/retail-it"]:hover,
.nav-sub a[href^="/en/retail-it"]:focus{
  background:rgba(255,153,50,.12) !important;
  color:var(--navy) !important;
  border-left-color:var(--amber) !important;
  padding-left:22px !important;
  text-shadow:none !important;
}
.nav-item:has(> a[href^="/retail-it"]) .nav-sub a.is-current-page,
.nav-item:has(> a[href^="/en/retail-it"]) .nav-sub a.is-current-page,
nav.primary a[href^="/retail-it"] + .nav-sub a.is-current-page,
nav.primary a[href^="/en/retail-it"] + .nav-sub a.is-current-page,
.chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub a.is-current-page,
.chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub a.is-current-page,
body .chrome-overlay nav.primary a[href^="/retail-it"] + .nav-sub a.is-current-page,
body .chrome-overlay nav.primary a[href^="/en/retail-it"] + .nav-sub a.is-current-page,
.nav-sub a[href^="/retail-it"].is-current-page,
.nav-sub a[href^="/en/retail-it"].is-current-page{
  background:rgba(255,153,50,.08) !important;
  color:var(--navy) !important;
  border-left-color:var(--amber) !important;
  font-weight:600 !important;
  padding-left:22px !important;
}

/* AI dropdown links hover & active state */
.nav-item:has(> a[href^="/ai"]) .nav-sub a:hover,
.nav-item:has(> a[href^="/ai"]) .nav-sub a:focus,
.nav-item:has(> a[href^="/en/ai"]) .nav-sub a:hover,
.nav-item:has(> a[href^="/en/ai"]) .nav-sub a:focus,
nav.primary a[href^="/ai"] + .nav-sub a:hover,
nav.primary a[href^="/ai"] + .nav-sub a:focus,
nav.primary a[href^="/en/ai"] + .nav-sub a:hover,
nav.primary a[href^="/en/ai"] + .nav-sub a:focus,
.chrome-overlay nav.primary a[href^="/ai"] + .nav-sub a:hover,
.chrome-overlay nav.primary a[href^="/ai"] + .nav-sub a:focus,
.chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub a:hover,
.chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub a:focus,
body .chrome-overlay nav.primary a[href^="/ai"] + .nav-sub a:hover,
body .chrome-overlay nav.primary a[href^="/ai"] + .nav-sub a:focus,
body .chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub a:hover,
body .chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub a:focus,
.nav-sub a[href^="/ai"]:hover,
.nav-sub a[href^="/ai"]:focus,
.nav-sub a[href^="/en/ai"]:hover,
.nav-sub a[href^="/en/ai"]:focus{
  background:rgba(62,247,174,.16) !important;
  color:var(--navy) !important;
  border-left-color:var(--mint) !important;
  padding-left:22px !important;
  text-shadow:none !important;
}
.nav-item:has(> a[href^="/ai"]) .nav-sub a.is-current-page,
.nav-item:has(> a[href^="/en/ai"]) .nav-sub a.is-current-page,
nav.primary a[href^="/ai"] + .nav-sub a.is-current-page,
nav.primary a[href^="/en/ai"] + .nav-sub a.is-current-page,
.chrome-overlay nav.primary a[href^="/ai"] + .nav-sub a.is-current-page,
.chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub a.is-current-page,
body .chrome-overlay nav.primary a[href^="/ai"] + .nav-sub a.is-current-page,
body .chrome-overlay nav.primary a[href^="/en/ai"] + .nav-sub a.is-current-page,
.nav-sub a[href^="/ai"].is-current-page,
.nav-sub a[href^="/en/ai"].is-current-page{
  background:rgba(62,247,174,.10) !important;
  color:var(--navy) !important;
  border-left-color:var(--mint) !important;
  font-weight:600 !important;
  padding-left:22px !important;
}

/* Insights dropdown links hover & active state */
.nav-item:has(> a[href*="insight"]) .nav-sub a:hover,
.nav-item:has(> a[href*="insight"]) .nav-sub a:focus,
nav.primary a[href*="insight"] + .nav-sub a:hover,
nav.primary a[href*="insight"] + .nav-sub a:focus,
.chrome-overlay nav.primary a[href*="insight"] + .nav-sub a:hover,
.chrome-overlay nav.primary a[href*="insight"] + .nav-sub a:focus,
body .chrome-overlay nav.primary a[href*="insight"] + .nav-sub a:hover,
body .chrome-overlay nav.primary a[href*="insight"] + .nav-sub a:focus,
.nav-sub a[href*="blog"]:hover,
.nav-sub a[href*="blog"]:focus,
.nav-sub a[href*="news"]:hover,
.nav-sub a[href*="news"]:focus{
  background:rgba(46,95,138,.10) !important;
  color:var(--navy) !important;
  border-left-color:var(--accent-blue) !important;
  padding-left:22px !important;
  text-shadow:none !important;
}
.nav-item:has(> a[href*="insight"]) .nav-sub a.is-current-page,
nav.primary a[href*="insight"] + .nav-sub a.is-current-page,
.chrome-overlay nav.primary a[href*="insight"] + .nav-sub a.is-current-page,
body .chrome-overlay nav.primary a[href*="insight"] + .nav-sub a.is-current-page,
.nav-sub a[href*="blog"].is-current-page,
.nav-sub a[href*="news"].is-current-page{
  background:rgba(46,95,138,.07) !important;
  color:var(--navy) !important;
  border-left-color:var(--accent-blue) !important;
  font-weight:600 !important;
  padding-left:22px !important;
}

/* Generic fallback hover */
nav.primary .nav-sub a:hover,
.chrome-overlay nav.primary .nav-sub a:hover,
body .chrome-overlay nav.primary .nav-sub a:hover,
.nav-sub a:hover{
  background:var(--silver-25) !important;
  color:var(--navy) !important;
  border-bottom-color:transparent !important;
  text-shadow:none !important;
}
@media (prefers-reduced-motion:reduce){
  .nav-sub{transition:none;}
}
.header-right{display:flex; align-items:center; justify-content:flex-end; gap:20px;}
.lang-switch{font-size:14px; font-weight:600; color:var(--navy-75); display:flex; gap:6px;}
.lang-switch .active{color:var(--navy); text-decoration:underline;}
/* The switch used to be three inert <span>s. The translated routes now hand
   it an <a>; on the routes that have no English twin yet it stays a <span>,
   so both shapes have to look identical. Anchors inherit the switch colour
   rather than the global link colour, and the overlay pages' white
   `.chrome-overlay .lang-switch` rule keeps working for the same reason. */
.lang-switch a{color:inherit; text-decoration:none;}
.lang-switch a:hover{color:var(--navy); text-decoration:underline;}
.lang-switch a.active{color:var(--navy); text-decoration:underline;}
.chrome-overlay .lang-switch a:hover,
.chrome-overlay .lang-switch a.active{color:#fff;}

/* ---- One header on every page. Same markup, menu, logo size and CTA
   everywhere; chrome:check fails if a page's header drifts from the rest.
   Only the backdrop differs. The plain routes (`body > header`) get a navy
   bar. The hero routes (`.chrome-overlay > header`) lie see-through over
   their photo/video banner, with a dark top gradient and soft shadows to keep
   the white text legible, and fade out with the banner as the page scrolls
   (mobile-nav.js). The owner asked for that on 2026-10-20: a navy bar over
   the banner read as a sticky header. Hero pages must not restyle the header
   in their own <style>. ---- */
body .chrome-overlay{background:linear-gradient(180deg, rgba(4,10,18,.55) 0%, rgba(4,10,18,.16) 65%, transparent 100%);}
body .chrome-overlay > header{background:none; border-bottom:none;}
.chrome-overlay nav.primary > a,
.chrome-overlay nav.primary > .nav-item > a,
.chrome-overlay .lang-switch{text-shadow:0 1px 4px rgba(0,0,0,.45);}
.chrome-overlay .logo-svg{filter:drop-shadow(0 2px 9px rgba(0,0,0,.58));}
:is(body, .chrome-overlay) > header{background:var(--navy); border-bottom-color:rgba(255,255,255,.14);}
:is(body, .chrome-overlay) > header nav.primary > a,
:is(body, .chrome-overlay) > header nav.primary > .nav-item > a{color:#fff;}
:is(body, .chrome-overlay) > header nav.primary > a:hover,
:is(body, .chrome-overlay) > header nav.primary > .nav-item:hover > a{border-bottom-color:rgba(255,255,255,.55);}
:is(body, .chrome-overlay) > header nav.primary > a[href^="/retail-it"]:hover,
:is(body, .chrome-overlay) > header nav.primary > a[href^="/en/retail-it"]:hover,
:is(body, .chrome-overlay) > header nav.primary > .nav-item:hover > a[href^="/retail-it"],
:is(body, .chrome-overlay) > header nav.primary > .nav-item:hover > a[href^="/en/retail-it"],
:is(body, .chrome-overlay) > header nav.primary > .nav-item:focus-within > a[href^="/retail-it"],
:is(body, .chrome-overlay) > header nav.primary > .nav-item:focus-within > a[href^="/en/retail-it"]{border-bottom-color:var(--amber);}
:is(body, .chrome-overlay) > header nav.primary > a[href^="/ai"]:hover,
:is(body, .chrome-overlay) > header nav.primary > a[href^="/en/ai"]:hover,
:is(body, .chrome-overlay) > header nav.primary > .nav-item:hover > a[href^="/ai"],
:is(body, .chrome-overlay) > header nav.primary > .nav-item:hover > a[href^="/en/ai"],
:is(body, .chrome-overlay) > header nav.primary > .nav-item:focus-within > a[href^="/ai"],
:is(body, .chrome-overlay) > header nav.primary > .nav-item:focus-within > a[href^="/en/ai"]{border-bottom-color:var(--mint);}
:is(body, .chrome-overlay) > header .lang-switch{color:rgba(255,255,255,.72);}
:is(body, .chrome-overlay) > header .lang-switch .active,
:is(body, .chrome-overlay) > header .lang-switch a:hover,
:is(body, .chrome-overlay) > header .lang-switch a.active{color:#fff;}
:is(body, .chrome-overlay) > header .nav-toggle{color:#fff;}
:is(body, .chrome-overlay) > header .nav-toggle:focus-visible{outline:2px solid #fff; outline-offset:0;}

/* The header CTA is .btn-primary, i.e. navy — on a navy bar it lost its edges
   and read as a bold label rather than a button. Lifted onto the brand accent
   blue with a white hairline, which separates it from the bar without going as
   loud as a solid white pill. It is the same button on every page: the AI and
   Retail routes used to swap in a mint or amber one, which was a third way the
   header changed from tab to tab. */
:is(body, .chrome-overlay) > header .header-right .btn-primary{
  background:var(--accent-blue);
  border-color:rgba(255,255,255,.55);
  box-shadow:0 2px 10px rgba(9,18,30,.28);
}
:is(body, .chrome-overlay) > header .header-right .btn-primary:hover{
  background:#37709f;
  border-color:#fff;
  box-shadow:0 6px 18px rgba(9,18,30,.34);
}
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px; font-size:16.5px; font-weight:600; line-height:1.2;
  padding:14px 26px; min-height:48px; border-radius:var(--jjw-radius-control); text-decoration:none; cursor:pointer; border:1px solid transparent;
  text-align:center;
  transition:background-color .18s ease, color .18s ease, border-color .18s ease, box-shadow .2s ease, transform .18s ease;
}
.btn:hover{transform:translateY(-1px);}
.btn:active{transform:translateY(0);}
.btn-primary{background:var(--navy); color:#fff; box-shadow:0 4px 14px rgba(30,58,95,.22);}
.btn-primary:hover{background:#16304f; box-shadow:0 8px 22px rgba(30,58,95,.32);}
.btn-secondary{background:transparent; color:var(--navy); border-color:var(--navy);}
.btn-secondary:hover{background:var(--silver-25);}
.btn-spoke-ai{background:transparent; color:var(--navy); border-color:var(--mint);}
.btn-spoke-ai:hover{background:var(--mint-25);}
.btn-spoke-retail{background:transparent; color:var(--navy); border-color:var(--amber);}
.btn-spoke-retail:hover{background:var(--amber-25);}
/* ---- Amber CTA -------------------------------------------------------
   The Retail spoke's action colour, for a page whose own conversion has
   to out-rank the navy header button instead of matching it. Kept as a
   modifier on .btn rather than a bespoke class so a page's CTAs are one
   style in three places (hero, mid-page band, form submit) — /retail-it/
   pm-netzwerk previously shipped a navy .btn in two of those and an
   amber .photo-panel__cta in the third.
   The lift on hover is the same move .card already makes; #09121e on
   #FF9932 is the dark ink the amber needs to stay readable. ---- */
.btn-amber{
  background:var(--amber); color:#09121e; font-weight:700;
  padding:14px 26px; min-height:48px;
  box-shadow:0 6px 18px rgba(255,153,50,.32);
  transition:background-color .18s ease, box-shadow .22s ease, transform .22s ease;
}
.btn-amber:hover{background:var(--amber-75); box-shadow:0 10px 26px rgba(255,153,50,.42); transform:translateY(-2px);}
.btn-amber:active{transform:translateY(0); box-shadow:0 4px 12px rgba(255,153,50,.34);}

/* ---- Mint CTA (AI Spoke) ---------------------------------------------
   The AI spoke's action colour, matching the amber CTA on Retail pages.
   #09121e on #3EF7AE provides crisp, high-contrast readability. ---- */
.btn-mint{
  background:var(--mint); color:#09121e; font-weight:700;
  border-color:var(--mint);
  padding:14px 26px; min-height:48px;
  box-shadow:0 6px 18px rgba(62,247,174,.32);
  transition:background-color .18s ease, border-color .18s ease, box-shadow .22s ease, transform .22s ease;
}
.btn-mint:hover{
  background:var(--mint-75); border-color:var(--mint-75);
  box-shadow:0 10px 26px rgba(62,247,174,.42); transform:translateY(-2px);
}
.btn-mint:active{
  transform:translateY(0); box-shadow:0 4px 12px rgba(62,247,174,.34);
}

@media (prefers-reduced-motion:reduce){
  .btn, .btn-amber, .btn-mint{transition:background-color .18s ease;}
  .btn:hover, .btn-amber:hover, .btn-mint:hover{transform:none;}
}
/* On wide desktop screens the primary brand controls can carry a little more
   visual weight. This deliberately starts above common laptop widths, where the
   balanced base grid has more room to breathe. */
@media (min-width:1320px){
  header .header-right .btn{font-size:16px; padding:11px 22px; min-height:46px;}
  .header-inner{padding:20px 32px; gap:32px;}
  .logo-svg{height:92px;}
  nav.primary{gap:32px; font-size:17px;}
  .header-right{gap:22px;}
  .lang-switch{font-size:15px;}
}
/* The header CTA reads "Kostenloses Erstgespräch vereinbaren" (Review v1,
   Kontakt). At 16px that button is ~290px wide and the six-tab bar stops
   fitting somewhere around 1180px. Step the CTA down rather than the nav —
   the nav is the thing a visitor scans, the button they already know. */
@media (max-width:1180px){
  .header-inner{gap:16px;}
  nav.primary{gap:20px; font-size:14.5px;}
  header .header-right{gap:12px;}
  header .header-right .btn{font-size:14px; padding:10px 14px; min-height:38px; white-space:nowrap;}
  .lang-switch{font-size:12px;}
}
/* Second step for the 900–1080 band, where the six tabs, the language switch
   and a 34-character button stop fitting on one line and the CTA breaks in
   two. The lockup gives up the most width for the least: at 64px the Retail
   and AI marks are still legible, and the button stays one line.
   `.chrome-overlay header` outranks the `.chrome-overlay .logo-svg{height:90px}`
   the photo-hero pages set in their own <style> — same two classes, but one
   element deeper, so it wins on specificity rather than on order. */
@media (max-width:1080px){
  .header-inner{gap:12px; padding:14px 18px;}
  header .logo-svg,
  .chrome-overlay header .logo-svg{height:64px;}
  nav.primary{gap:16px; font-size:14px;}
  header .header-right{gap:10px;}
  header .header-right .btn{font-size:13px; padding:9px 12px; min-height:36px;}
}
@media (max-width:900px){
  .header-inner{display:flex; justify-content:space-between;}
  .logo-svg{height:70px;}
  nav.primary{display:none;}
}

/* ---- Keynote banner (temporary, November only — see Kapitel 9.6) ---- */
/* ---- Generic page hero (label/kicker + H1 + subline + CTA row) ---- */
.page-hero{padding:72px 24px 64px; text-align:center; background:#fff;}
.page-hero .kicker{display:block; margin-bottom:18px;}
.page-hero h1{max-width:780px; margin:0 auto 20px;}
.page-hero .sub{font-size:18px; color:var(--navy-75); max-width:620px; margin:0 auto; line-height:1.55;}
.cta-row{display:flex; align-items:center; justify-content:center; gap:20px; flex-wrap:wrap; margin-top:32px;}
.ghost-link{
  display:inline-flex; align-items:center; gap:6px; font-weight:600; color:var(--navy);
  text-decoration:none; border-bottom:2px solid var(--navy-25); padding-bottom:2px;
}
.ghost-link:hover{border-bottom-color:var(--navy);}

/* ---- Split page hero: left-aligned copy + a right-hand anchor panel on
   the spoke accent rule. Generalised from /ai/kmu-digital, which is the
   reference for how a secondary page should open. The centred .page-hero
   above gives a subpage no visual anchor and — because the copy is short
   and the CTA row usually absent — leaves a band of dead white between
   the subline and the first section. The grid's min-height is what closes
   that gap: the hero earns its height instead of padding into it.
   Column ratio, gap and rule are the KMU values, which are proven at
   1440 and collapse cleanly at 900. ---- */
.page-hero--split{padding:74px 0 64px; text-align:left; width:100%; box-sizing:border-box;}
.hero-split{
  display:grid; grid-template-columns:minmax(0,1.3fr) minmax(340px,.7fr);
  gap:68px; align-items:center; min-height:360px;
  max-width:var(--maxw); margin:0 auto; padding:0 24px; box-sizing:border-box; width:100%;
}
.hero-split > *{min-width:0;}
/* A photo needs more of the row than a meta list does: at the base ratio
   the aside column lands at ~396px, and once the 42px rule gutter is off
   the front an image is only ~354px wide — small enough next to a
   three-line H1 that it reads as an afterthought. */
.hero-split--photo{grid-template-columns:minmax(0,1.15fr) minmax(360px,.85fr);}
.page-hero--split h1{max-width:800px; margin:0 0 22px; text-wrap:balance;}
.page-hero--split .sub{max-width:660px; margin:0;}
.page-hero--split .cta-row{justify-content:flex-start;}
/* The retail kicker ink, carried over from .photo-panel__kicker: amber
   itself is far under 4.5:1 on white, #8A5300 is the darkened form that
   clears it. Also wins over .hero-wash .kicker inside a symbol band. */
.kicker--retail,
.hero-wash .kicker.kicker--retail{color:#8A5300;}
.kicker--ai,
.hero-wash .kicker.kicker--ai{color:#087a52; font-weight:700;}

/* The anchor panel. Carries either an image or a short meta list, but
   always sits on the accent rule so the hero reads as two related parts
   rather than a headline with something parked beside it. */
.hero-aside{justify-self:end; width:min(100%,460px); padding-left:42px; border-left:2px solid var(--mint);}
.hero-aside--retail{border-left-color:var(--amber);}
.hero-aside > img{display:block; width:100%; height:auto;}
/* Portrait-ish, so the image carries roughly the same height as the copy
   beside it and the accent rule runs the full depth of the row. */
.hero-aside--photo > img{aspect-ratio:4/5; object-fit:cover;}
.hero-aside__label{
  display:block; margin-bottom:22px; color:var(--navy-75);
  font-size:12px; font-weight:700; letter-spacing:.12em; text-transform:uppercase;
}
.hero-facts{display:flex; flex-direction:column; margin:0; padding:0; list-style:none;}
.hero-facts li{padding-bottom:16px; margin-bottom:16px; border-bottom:1px solid var(--hairline);}
.hero-facts li:last-child{padding-bottom:0; margin-bottom:0; border-bottom:0;}
.hero-facts strong{display:block; margin-bottom:5px; color:var(--navy); font-size:16px; font-weight:600;}
.hero-facts span{display:block; color:var(--navy-75); font-size:14.5px; line-height:1.55;}
.hero-facts a{color:var(--navy); font-weight:600; border-bottom:1px solid var(--mint);}
.hero-aside--retail .hero-facts a{border-bottom-color:var(--amber);}

/* The hero already ends on a CTA row or a panel edge, so the following
   section's full 96px on top of the hero's own 74px reads as a hole —
   the same trim /ai/kmu-digital makes by hand for its status strip. */
.page-hero--split + .section{padding-top:56px;}

/* ---- Mid-page symbol band --------------------------------------------
   The split hero's layout, dropped in the middle of a page: copy in the
   left column, the WebGL mark in the empty right one. It exists because
   /retail-it/pm-netzwerk moved its portrait up into the hero and the
   symbol had to go somewhere — a statement band reads better here than a
   third photo panel would.
   Not folded into .page-hero--split: that class means "this is the top of
   the page" everywhere else, and .page-hero--split + .section would then
   trim the padding of whatever section follows the band. ---- */
.symbol-band{
  padding:74px 24px; text-align:left;
  border-block:1px solid var(--hairline);
}
.symbol-band h2{max-width:800px; margin:0 0 20px; text-wrap:balance;}
.symbol-band .sub{max-width:660px; margin:0; font-size:18px; color:var(--navy-75); line-height:1.55;}
.symbol-band .kicker{display:block; margin-bottom:18px;}
.symbol-band .cta-row{justify-content:flex-start;}

/* Below 900 the two columns can't both hold their measure, so the panel
   drops under the copy and the rule rotates to the top edge — same move
   the KMU page makes, kept here so every split hero collapses alike. */
@media (max-width:900px){
  .hero-split,
  .hero-split--photo{grid-template-columns:minmax(0,1fr); gap:44px; min-height:0;}
  .hero-aside{justify-self:start; width:100%; max-width:500px; padding:28px 0 0; border-left:0; border-top:2px solid var(--mint);}
  .hero-aside--retail{border-top-color:var(--amber);}
}

/* ---- Hero colour wash -------------------------------------------------
   A soft diagonal light entering from the top-right corner, in the colours
   of whichever brand level the page belongs to. Kept as its own class
   rather than folded into .page-hero--split so it can be dropped on any
   hero, and pulled off again by deleting one word in the markup.

   Colours come from the palette sheet (Accent Blue, Silver Grey, Amber,
   Teal, Green) — the wash mixes brand hues, it does not invent any.
   Spoke assignment follows the same rule as the accent rules: mint/teal
   on AI, amber on Retail, the parent palette everywhere else.

   Three constraints set the numbers:
   - The copy column has to stay on near-white. The radial mask holds the
     dense part of the wash in the top-right corner, so what reaches the
     headline is the tail of the fade, not the body of it.
   - No stop goes above ~.34 alpha. Past that the hero-facts secondary
     text (navy-75) starts dropping under 4.5:1 against the tint.
   - blur() instead of more gradient stops: wide low-alpha stops band
     visibly on 8-bit displays, and the blur lets the shape stay simple.
   ---- */
.hero-wash{
  position:relative; overflow:hidden; isolation:isolate; background:#fff;
  /* Dachmarke: exact base colours from Colour palette.pdf — Navy,
     Accent Blue and Silver Grey. Repeating a base colour across two lanes
     gives the animated material five broad fields without inventing
     intermediate RGB values. Alpha alone creates the lighter tints. */
  --wash-1:rgba(30,58,95,.34);
  --wash-2:rgba(46,95,138,.54);
  --wash-3:rgba(192,200,212,.30);
  --wash-4:rgba(46,95,138,.24);
  /* WebGL-only fifth lane; the CSS fallback has four available layers. */
  --wash-5:rgba(192,200,212,.22);
  /* Drop the cast shadow below the lowest ribbon tip. Positive values move
     the shadow down; the shader also feathers it out before the logo. */
  --hero-shadow-offset:.022;
  /* Applied on top of the alphas above, because alpha is not perceived
     density — a palette's colours shift white by very different amounts
     at identical alpha, so each brand needs one explicit correction
     rather than a formula nobody can predict from the channel values.
     1 is the reference; the sub-brands are scaled to match what this one
     looks like, not what its numbers say. Re-measured by the contrast
     run at 1920 and 390 on every change, never assumed. */
  --storm-density:1.25;
}
/* AI: the supplied proposal palette uses its exact Teal and Green beside
   the shared Navy, Accent Blue and Silver Grey. */
.hero-wash--ai{
  --wash-1:rgba(30,58,95,.20);
  --wash-2:rgba(46,95,138,.28);
  --wash-3:rgba(0,183,181,.42);
  --wash-4:rgba(1,210,142,.38);
  --wash-5:rgba(192,200,212,.18);
  --storm-density:1.08;
}
/* Retail: shared Navy and Accent Blue with the exact Amber base from the
   proposal palette; Silver Grey carries the connecting light. */
.hero-wash--retail{
  --wash-1:rgba(30,58,95,.20);
  --wash-2:rgba(46,95,138,.28);
  --wash-3:rgba(255,153,50,.48);
  --wash-4:rgba(255,153,50,.28);
  --wash-5:rgba(192,200,212,.18);
  --storm-density:1.15;
}
/* Two layers, because the thing that makes Stripe's hero read as alive is
   not one moving gradient — it is two structures moving against each
   other at different rates, so the combination never visibly repeats.

   ::before is the ambient bed: four overlapping colour fields strung
   along a NE→SW diagonal. They have to sit in different places rather
   than being stops on one gradient — a single linear-gradient averages
   its stops into one flat pastel and every spoke ends up looking alike.

   ::after is the blade fan. Stripe's is a three.js mesh; a conic-gradient
   does the same job here, because a conic whose apex sits off the
   top-right corner throws exactly that spray of tapering blades down
   into the frame. Rotating it about its own apex is what makes the
   blades sweep rather than slide.

   Both overhang the hero on every side so the blur feathers outside the
   frame — at inset:0 it fades the top edge and leaves a pale strip
   under the header. ---- */
.hero-wash::before,
.hero-wash::after{
  content:""; position:absolute; z-index:-1; inset:-70px -90px; pointer-events:none;
  /* The hero clips its overflow, so without this the descending end of
     the band is sheared off flat against the next section's white. The
     fade is deliberately long: the mask travels with the layer, so it
     has to still cover the hero's bottom edge at the far end of the
     animation, not just at rest. */
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 46%,transparent 88%);
  mask-image:linear-gradient(180deg,#000 0%,#000 46%,transparent 88%);
  will-change:transform;
}
.hero-wash::before{
  background:
    radial-gradient(46%  88% at  38% -24%, var(--wash-1) 0%, transparent 66%),
    radial-gradient(40% 100% at  60%  -6%, var(--wash-2) 0%, transparent 68%),
    radial-gradient(40% 110% at  82%  16%, var(--wash-3) 0%, transparent 68%),
    radial-gradient(48% 130% at 106%  46%, var(--wash-4) 0%, transparent 70%);
  filter:blur(34px);
  animation:hero-wash-drift 48s ease-in-out infinite alternate;
}
/* Angles run clockwise from 12 o'clock. With the apex above the top-right
   corner the whole frame lies between roughly 166° and 242°, and the far
   end of that arc is the bottom-LEFT corner — a fan spanning all of it
   buries the copy column. The blades stop at 228° so the spray stays on
   the right two-thirds and the headline keeps its white.

   The gaps between blades are what make them read as separate blades
   rather than one smear. The opacity is the important number: the fan
   lands on top of the bed, and at full strength the two together doubled
   the density and cost the hero the clean feel it is supposed to have. */
.hero-wash::after{
  background:conic-gradient(at 88% -16%,
    transparent 162deg,
    var(--wash-2)  174deg, transparent 186deg,
    var(--wash-3)  195deg, transparent 206deg,
    var(--wash-4)  214deg, transparent 224deg,
    var(--wash-1)  230deg, transparent 240deg);
  opacity:.58;
  filter:blur(30px);
  transform-origin:88% -16%;
  animation:hero-wash-sweep 70s ease-in-out infinite alternate;
}
/* The fallback follows the shader's calmer tempo. Unequal periods keep
   the two layers from moving as one rigid object, and alternate removes
   any visible reset seam. */
@keyframes hero-wash-drift{
  from{transform:translate3d(0,0,0) scale(1);}
  to  {transform:translate3d(-3.5%,1.8%,0) scale(1.10);}
}
@keyframes hero-wash-sweep{
  from{transform:rotate(-5deg) scale(1.02);}
  to  {transform:rotate(4deg) scale(1.07);}
}
/* Motion behind text is exactly what this setting is for. The pose at
   35% of the drift is the one the stills were judged on. */
@media (prefers-reduced-motion:reduce){
  .hero-wash::before{animation:none; transform:translate3d(-1.8%,.9%,0) scale(1.05);}
  .hero-wash::after{animation:none; transform:rotate(-2deg) scale(1.03);}
}
/* navy-75 is 4.9:1 on pure white — it has almost no headroom, and the
   densest part of the wash sits exactly where the panel's 14.5px
   secondary text is, which measures out at ~4.4:1. One step darker buys
   back the headroom the wash spends (6.8:1 on white, ~5.4:1 on the
   tint) and is close enough to navy-75 to read as the same grey-blue.
   Scoped to .hero-wash so unwashed heroes keep the token.

   .kicker was missing from this list and it matters more now than it
   did: on the compact legal heroes it is the only small text there is,
   and it sits in the densest part of the band. Measured against what the
   storm actually paints it came out at 3.73:1 in navy-75 and 4.64:1 in
   the first darker grey-blue (#4A5C78).

   That one step was not enough once the storm got its density back. The
   kicker sits at the top of the copy column, which is both the densest
   part of the field and the part the bottom fade does nothing for: on
   /news it measured 3.77:1 and on /team 4.20:1, while every sub-brand
   page cleared 5:1 comfortably. The parent palette is the problem
   because navy and accent blue are its two darkest hues and it has no
   light one to hide behind the way AI has mint and Retail has amber.

   Two ways to pay for that, and this is the cheaper one. Dimming the
   storm to 0.82 fixes the text and undoes the entire point of the work —
   a hero nobody can see moving. Darkening the text by one more step
   costs a shade of muted grey-blue that almost nobody will consciously
   register, and it lifts every row on every palette at once rather than
   trading one against another. Worst row after this change is 4.69:1.

   Scoped to .hero-wash, so heroes without a wash keep the lighter token. */
.hero-wash .sub,
.hero-wash .kicker,
.hero-wash .hero-aside__label,
.hero-wash .hero-facts span{color:#3D4E68;}
/* Small copy can cross the ribbon's shaded face on AI/Retail split
   heroes. Use the official Navy token there; muted Navy 75 has no
   contrast headroom against the saturated Mint/Amber folds. */
.hero-wash .hero-aside__label,
.hero-wash .hero-facts span{color:var(--navy);}
/* The kicker needs one step beyond the rest, and only on /news and /team
   does it actually bite — but the rule is unconditional because the thing
   that makes it the worst case is structural, not per-page. It is the
   smallest text in the hero, it is set uppercase and letterspaced (which
   costs legibility on its own), and it sits at the top of the band where
   the field is densest and the bottom fade does nothing. At #3D4E68 it
   measured 4.40:1 on /news against a 4.5 floor.

   Taking this rather than another density cut: the alternative was
   trimming the parent palette ~10%, which dims the whole hero to rescue
   one eyebrow label. This is an already-de-emphasised label going one
   shade further down, which is what the element is for. */
.hero-wash .kicker{color:#36455C;}

/* Stacked, the hero is roughly twice as tall and the panel sits directly
   under the copy — a wash sized to the desktop row would run down behind
   the whole thing. Pin it to the top band instead. */
@media (max-width:900px){
  .hero-wash::before{top:-24%; bottom:auto; height:64%; left:0;}
  /* The fan's shape comes from its apex sitting just off a wide, short
     box. Stacked, the hero is taller than it is wide, and the same apex
     throws near-vertical blades down the length of it. The bed carries
     the mobile hero on its own — which also saves a second large blurred
     animating layer on the devices least able to afford one. */
  .hero-wash::after{display:none;}
}

/* Off screen the wash is invisible but still animating, which is a
   repaint per frame for nothing while the reader is further down the
   page. Paused by the observer in reveal.js. */
.hero-wash.is-wash-paused::before,
.hero-wash.is-wash-paused::after,
.hero-wash.is-wash-paused .hero-wash-layer{animation-play-state:paused;}

/* ---- Storm variant A: WebGL ------------------------------------------
   hero-storm.js paints the field in a fragment shader and adds
   .has-storm once a context is actually live. The CSS layers stay in the
   sheet and stay correct — they are the fallback for a missing context,
   a failed compile, or a context lost mid-session — so they are hidden
   by the class rather than removed.

   The canvas sits at z-index:-1 alongside them, inside the hero's
   isolation context, so the copy and the aside rule stay on top. ---- */
.hero-storm-canvas{
  position:absolute; inset:0; z-index:-1;
  width:100%; height:100%;
  display:block; pointer-events:none;
}
.hero-ground-shadow{
  position:absolute;
  z-index:0;
  pointer-events:none;
  border-radius:50%;
  background:radial-gradient(ellipse at center, rgba(10,24,45,0.72) 0%, rgba(10,24,45,0.32) 38%, rgba(10,24,45,0.08) 65%, transparent 75%);
  filter:blur(8px);
  /* width/height/left/top are layout properties — will-change cannot promote
     them onto their own layer, so listing them bought nothing and only asked
     the compositor to hold a layer for an element that now changes size on
     resize alone. opacity is the one it can actually act on. */
  will-change:opacity;
}
.hero-wash.has-storm::before,
.hero-wash.has-storm::after{display:none;}

/* ---- Storm variant B: CSS -------------------------------------------
   The same effect pushed as far as gradient stops go, for the side by
   side. Three differences from the base wash, all of them about the one
   complaint that started this: at .58 on the fan and a mask that starts
   fading at 46% it reads as a faint smudge rather than weather.

   1. Denser. The alphas below are the palette values scaled up, not new
      colours — the base wash was tuned to disappear, and this is the
      same hues asked to actually show up.
   2. A later, shorter mask fade, so the field holds its strength through
      the middle of the hero instead of dying just past the headline.
   3. A third layer, injected by hero-storm.js rather than added to the
      markup — an element has two pseudo-elements and both are spent. It
      counter-rotates against the fan, which is what stops the pair from
      reading as one rigid shape being turned.

   What it still cannot do, and the reason the WebGL variant exists: the
   shapes here are fixed. Stops do not move relative to each other, so
   the layer can slide, spin and scale but the blades themselves never
   bend.

   And the honest result of measuring it: the lift below is much smaller
   than it started out, because the first pass at it failed AA on every
   split hero — 3.16:1 behind the AI aside panel, 3.47:1 on Retail,
   3.57:1 on the parent. A CSS gradient tints uniformly, so density and
   legibility trade off one-for-one and there is no room to spend. The
   WebGL variant gets 5.3-5.8:1 in the same places while looking denser,
   because the noise leaves real white between the masses rather than
   laying an even film over everything. That is the finding, and it is
   most of the argument for which variant to keep. ---- */
.hero-wash--v2{
  --wash-1:rgba(30,58,95,.22);
  --wash-2:rgba(46,95,138,.34);
  --wash-3:rgba(192,200,212,.30);
  --wash-4:rgba(192,200,212,.46);
}
/* The sub-brands get a smaller lift than the parent palette, for the
   same reason they get a lower --storm-density: they were never the ones
   that failed to show up. */
.hero-wash--v2.hero-wash--ai{
  --wash-1:rgba(30,58,95,.20);
  --wash-2:rgba(46,95,138,.30);
  --wash-3:rgba(0,183,181,.36);
  --wash-4:rgba(1,210,142,.40);
}
.hero-wash--v2.hero-wash--retail{
  --wash-1:rgba(30,58,95,.18);
  --wash-2:rgba(46,95,138,.28);
  --wash-3:rgba(255,153,50,.36);
  --wash-4:rgba(255,153,50,.40);
}
/* Heroes and bands that use the mark as a standalone visual rather than as
   ambient tint: the material matches the exact navy of the brand. Kept below
   the fallback variants so the same colour wins in both WebGL and CSS
   rendering modes. */
.hero-symbol--navy,
.hero-wash--v2.hero-symbol--navy{
  --hero-symbol-ink:.14;
  --hero-symbol-scale:.72;
  --hero-symbol-y-offset:.055;
  --hero-shadow-offset:.025;
  --wash-1:rgba(30,58,95,.48);
  --wash-2:rgba(46,95,138,.58);
  --wash-3:rgba(192,200,212,.44);
  --wash-4:rgba(46,95,138,.36);
  --wash-5:rgba(192,200,212,.28);
  --storm-density:1.15;
}
.hero-symbol--navy .hero-symbol-fallback{
  top:9%;
  right:8%;
  height:59%;
  filter:drop-shadow(0 22px 13px rgba(30,58,95,.12));
}
/* 62% put the full-strength part of the field over the subline on every
   split hero. 54% is the compromise the measurements allow: still later
   than the base wash's 46%, so the field holds through the middle rather
   than dying just past the headline, but off the small text. */
.hero-wash--v2::before,
.hero-wash--v2::after,
.hero-wash--v2 .hero-wash-layer{
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 54%,transparent 96%);
  mask-image:linear-gradient(180deg,#000 0%,#000 54%,transparent 96%);
}
/* .58 was the number that made the fan disappear. It is only this low
   because it lands on top of the bed; the bed is what gets pulled back
   instead, via a slightly harder blur, so the pair gains density without
   the copy column losing its white. */
.hero-wash--v2::after{opacity:.70; filter:blur(26px);}
.hero-wash--v2::before{filter:blur(40px);}

/* The third layer. Same apex as the fan so it reads as the same light,
   but half as many blades and turning the other way — at matched counts
   the two moiré against each other and the interference is very visible
   on a slow sweep. 67s against the fan's 41s and the bed's 29s: three
   mutually prime periods, so the stack takes hours to repeat a pose. */
.hero-wash-layer{
  position:absolute; z-index:-1; inset:-70px -90px; pointer-events:none;
  background:conic-gradient(at 88% -16%,
    transparent 158deg,
    var(--wash-4)  180deg, transparent 198deg,
    var(--wash-1)  212deg, transparent 232deg);
  opacity:.5;
  filter:blur(38px);
  transform-origin:88% -16%;
  will-change:transform;
  animation:hero-wash-counter 67s ease-in-out infinite alternate;
}
@keyframes hero-wash-counter{
  from{transform:rotate(5deg) scale(1.06);}
  to  {transform:rotate(-8deg) scale(1);}
}
@media (prefers-reduced-motion:reduce){
  .hero-wash-layer{animation:none; transform:rotate(1deg) scale(1.03);}
}
/* Same call the fan makes: stacked, the apex throws near-vertical blades
   down the length of a hero that is now taller than it is wide. */
@media (max-width:900px){
  .hero-wash-layer{display:none;}
}

/* Exact-symbol fallback. WebGL normally supplies the illuminated material;
   this keeps the canonical mark visible while its texture loads and on
   browsers without WebGL. The SVG owns the contour and negative space. */
.hero-wash--v2::before,
.hero-wash--v2::after,
.hero-wash--v2 .hero-wash-layer{display:none;}
.hero-symbol-fallback{
  position:absolute;
  z-index:-1;
  top:7%;
  right:6%;
  height:82%;
  aspect-ratio:1;
  pointer-events:none;
  background:linear-gradient(135deg,
    #1E3A5F 0%,
    #1E3A5F 38%,
    #2E5F8A 45%,
    #C0C8D4 50%,
    #2E5F8A 55%,
    #1E3A5F 62%,
    #1E3A5F 100%);
  background-size:260% 260%;
  background-position:0% 50%;
  -webkit-mask:url("symbol-mark.svg") center/contain no-repeat;
  mask:url("symbol-mark.svg") center/contain no-repeat;
  filter:drop-shadow(0 26px 14px rgba(10,24,45,.22)) drop-shadow(0 8px 4px rgba(10,24,45,.14));
  transform-origin:50% 50%;
  will-change:transform,filter,background-position;
  animation:
    hero-symbol-hover 12.0s ease-in-out infinite,
    hero-symbol-gradient 45.0s ease-in-out infinite;
}
/* A 300px mark is the visual size reference for every full split hero and
   for the mid-page symbol band. Use an absolute target rather than a
   percentage of host height: wrapped headlines make some tablet heroes
   taller, but must not make their logo larger. Compact legal heroes remain
   proportional to their shorter bands. hero-storm.js mirrors these
   desktop/mobile targets for WebGL — keep the two class lists in step. */
.page-hero--split.hero-wash .hero-symbol-fallback,
.symbol-band.hero-wash .hero-symbol-fallback{
  width:300px;
  height:300px;
}
@keyframes hero-symbol-hover{
  0%,100%{transform:translateY(0); filter:drop-shadow(0 26px 14px rgba(10,24,45,.22)) drop-shadow(0 8px 4px rgba(10,24,45,.14));}
  50%{transform:translateY(-8px); filter:drop-shadow(0 34px 20px rgba(10,24,45,.15)) drop-shadow(0 12px 6px rgba(10,24,45,.09));}
}
@keyframes hero-symbol-gradient{
  0%,100%{background-position:0% 50%;}
  50%{background-position:100% 50%;}
}
.hero-wash--compact .hero-symbol-fallback{right:14%; animation-duration:7.5s,24s;}
@media (prefers-reduced-motion:reduce){
  .hero-symbol-fallback{animation:none; transform:none;}
}
@media (max-width:900px){
  /* A logo needs recognisable clear space, unlike the old ambient wash.
     Reserve one visual beat after the stacked hero content instead of
     placing the mark beneath buttons or facts copy. */
  .page-hero--split.hero-wash{padding-bottom:clamp(244px,calc(53vw + 40px),500px);}
  .symbol-band.hero-wash{padding-bottom:clamp(210px,calc(36vw + 84px),388px);}
  .hero-symbol-fallback{
    top:auto;
    left:0;
    right:0;
    margin-inline:auto;
    bottom:2%;
    width:49vw;
    height:auto;
    opacity:.72;
  }
  .hero-wash--ai .hero-symbol-fallback,
  .hero-wash--retail .hero-symbol-fallback{opacity:.52;}
  .hero-wash--compact .hero-symbol-fallback{left:auto; right:11%; margin-inline:0; width:35vw;}
  .hero-symbol--navy .hero-symbol-fallback{
    top:auto;
    left:0;
    right:0;
    margin-inline:auto;
    bottom:6%;
    width:36vw;
    height:auto;
  }
  .hero-wash--compact.hero-symbol--navy .hero-symbol-fallback{
    left:auto;
    right:11%;
    margin-inline:0;
  }
  .page-hero--split.hero-wash .hero-symbol-fallback,
  .symbol-band.hero-wash .hero-symbol-fallback{
    width:min(36vw,300px);
    height:auto;
  }
}

/* ---- Compact heroes (Impressum, Datenschutz) -------------------------
   The legal heroes are a kicker and an H1 in a ~200px band, centred
   rather than in a left column. Two things follow from that.

   The density has to come down. Every alpha above was set against a
   360px split hero where the field has room to fall off; compressed into
   200px the same numbers put full strength directly behind the H1.

   And the fan has to go. Its blades are shaped by an apex sitting just
   off a wide, short box — at this height they enter and leave the frame
   over a few dozen pixels, which reads as diagonal streaks rather than a
   fan. The bed alone is the right weight for a page whose job is to be
   read, not to sell. ---- */
.hero-wash--compact{
  --wash-1:rgba(30,58,95,.14);
  --wash-2:rgba(46,95,138,.20);
  --wash-3:rgba(192,200,212,.20);
  --wash-4:rgba(192,200,212,.26);
  /* Silver Grey is kept quiet because compact heroes centre the
     copy and cannot rely on the split layout's protected left column. */
  --wash-5:rgba(192,200,212,.20);
}
.hero-wash--compact::after,
.hero-wash--compact .hero-wash-layer{display:none;}
.hero-wash--compact::before{
  inset:-40px -60px;
  filter:blur(46px);
  -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 40%,transparent 92%);
  mask-image:linear-gradient(180deg,#000 0%,#000 40%,transparent 92%);
}
/* The alphas above already carry most of the reduction for the WebGL
   variant, since it reads the same custom properties. This is the rest
   of it: centred copy runs through the middle of the frame, so the
   left-column protection the split heroes rely on buys nothing here and
   the whole band has to stay light instead. */
.hero-wash--compact{--storm-density:.95;}

/* ---- Section rhythm ---- */
.section{padding:var(--jjw-section-gap) 0; width:100%; box-sizing:border-box;}
.section--white{background:var(--jjw-bg-white);}
.section--alt{background:var(--jjw-bg-alt);}
.section-narrow{max-width:820px; margin:0 auto; padding:0 24px; box-sizing:border-box;}
.section-head{max-width:780px; margin:0 auto 40px; text-align:center;}
.section-head--left{text-align:left; margin:0 0 36px;}
.section-head h2{font-size:var(--jjw-h2); line-height:1.2; margin-bottom:14px;}
.section-head p{font-size:var(--jjw-subline); line-height:1.55; color:var(--navy-75);}
/* A section that follows a full-bleed band (the AI/Retail network fields),
   which already carries ~92px of its own bottom padding plus a hairline.
   The full 96px on top of that reads as a hole, so this trims it — but it
   must stay a real gap, not zero, or the eyebrow sits on the hairline.
   Shared so /ai and /retail-it can never drift apart again. Doubled up as
   .section.credential-section because a later @media block re-declares the
   .section padding shorthand — equal specificity, so order alone would lose. */
.section.credential-section{padding-top:72px;}
@media (max-width:640px){ .section{padding:var(--jjw-section-gap-mobile) 0;} }
@media (max-width:760px){ .section.credential-section{padding-top:44px;} }

/* ---- Cards (Weiche AI/Retail on the hub; reused wherever a clickable
        summary card is needed) ---- */
.card-grid{display:grid; grid-template-columns:1fr 1fr; gap:24px; max-width:var(--maxw); margin:0 auto;}
@media (max-width:800px){ .card-grid{grid-template-columns:1fr;} }
.card{
  border:1px solid var(--hairline); border-radius:var(--jjw-radius-card); padding:36px 32px; background:#fff;
  border-top:4px solid var(--navy-25);
  display:flex; flex-direction:column; gap:16px;
  color:inherit; text-decoration:none; cursor:pointer;
  transition:background-color .22s ease, border-color .22s ease, box-shadow .22s ease, transform .22s ease;
}
.card.ai{border-top-color:var(--mint);}
.card.retail{border-top-color:var(--amber);}
.card.ai:hover{background:var(--mint-25); border-color:var(--mint);}
.card.retail:hover{background:var(--amber-25); border-color:var(--amber);}
.card:hover{transform:translateY(-3px); box-shadow:0 12px 28px rgba(30,58,95,.10);}
.card:focus-visible{outline:3px solid var(--navy); outline-offset:4px;}
.card .label{font-size:13.5px; font-weight:600; text-transform:uppercase; letter-spacing:.06em;}
.card.ai .label{color:#1f9e6e;}
.card.retail .label{color:#c76f0f;}
.card h3{font-size:24px; line-height:1.3; text-wrap:balance;}
.card p{color:var(--text-body); font-size:16.5px; line-height:1.6; text-wrap:pretty;}
.card .card-btn{
  margin-top:auto; align-self:flex-start; font-weight:600; font-size:16px; text-decoration:none;
  display:inline-flex; align-items:center; gap:6px; padding-top:32px;
}
.card.ai .card-btn{color:var(--navy); border-bottom:2px solid var(--mint);}
.card.retail .card-btn{color:var(--navy); border-bottom:2px solid var(--amber);}
.card:hover .card-btn{opacity:.78;}
@media (prefers-reduced-motion: reduce){
  .card{transition:none;}
  .card:hover{transform:none;}
}

/* ---- Pillar columns ("Die vier Säulen" — AI Kap. 4/9, Retail Kap. 5/10) ----
   Column/plinth motif: cap + shaft + base per pillar, numbered label, short
   accent rule, diamond-marker list. Grid uses align-items:stretch (not the
   default "end") so cap/base bars stay level across all four columns even
   when a title wraps to two lines — the shaft (flex:1) absorbs the extra
   height, not the outer frame. Cap/base are the same height and full-width
   (no protrusion) so they read as one consistent frame; the bullet/eyebrow
   still use a deeper hand-picked shade of the accent hue on white text,
   since the flat brand tokens fail AA there (see tokens.css) — same
   approach as the amber step-number text elsewhere in this file. */
.pillar-columns-head{max-width:620px; margin:0 auto 40px; text-align:center;}
.pillar-columns-eyebrow{font-size:12px; font-weight:700; letter-spacing:.18em; text-transform:uppercase; margin-bottom:14px;}
.pillar-columns-eyebrow.accent-ai{color:#0E7A52;}
.pillar-columns-eyebrow.accent-retail{color:#8A5300;}

.pillar-columns{display:grid; grid-template-columns:repeat(4,1fr); gap:28px; align-items:stretch; max-width:var(--maxw); margin:0 auto;}
.pillar-col{display:flex; flex-direction:column;}
.pillar-col__cap, .pillar-col__base{height:8px; background:var(--navy);}
.pillar-columns.accent-ai .pillar-col__cap, .pillar-columns.accent-ai .pillar-col__base{background:var(--mint);}
.pillar-columns.accent-retail .pillar-col__cap, .pillar-columns.accent-retail .pillar-col__base{background:var(--amber);}
.pillar-col__shaft{background:var(--light-grey); border-left:1px solid var(--hairline); border-right:1px solid var(--hairline); padding:26px 24px 30px; display:flex; flex-direction:column; gap:18px; flex:1; min-height:268px;}
.pillar-col__label{display:flex; align-items:baseline; gap:10px;}
.pillar-col__num{font-size:12px; font-weight:800; letter-spacing:.1em; color:var(--navy-50);}
.pillar-col__name{margin:0; font-size:23px; font-weight:700; letter-spacing:-.015em;}
.pillar-col__tag{margin:6px 0 0; font-size:15px; font-style:italic; color:var(--navy-75);}
.pillar-col__rule{width:28px; height:2px; background:var(--mint);}
.pillar-columns.accent-retail .pillar-col__rule{background:var(--amber);}
.pillar-col__items{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:10px;}
.pillar-col__items li{display:flex; gap:10px; align-items:baseline; font-size:15.5px; line-height:1.4; font-weight:500; color:var(--text-body);}
.pillar-col__items li::before{content:"◆"; font-size:11px; line-height:1.5; color:#0E7A52;}
.pillar-columns.accent-retail .pillar-col__items li::before{color:#8A5300;}

.pillar-columns-ground{max-width:var(--maxw); margin:6px auto 0; height:3px; background:var(--navy); opacity:.12;}

@media (max-width:900px){ .pillar-columns{grid-template-columns:repeat(2,1fr); row-gap:32px;} }
@media (max-width:560px){ .pillar-columns{grid-template-columns:1fr;} .pillar-col__shaft{min-height:0;} }

/* ---- Info table (Beratungsweg, Preise, Fördermodule) ---- */
.info-table{width:100%; border-collapse:collapse; max-width:var(--maxw); margin:0 auto; font-size:15.5px;}
.info-table th{
  background:var(--navy); color:#fff; text-align:left; font-weight:600; font-size:13.5px;
  text-transform:uppercase; letter-spacing:.05em; padding:14px 18px;
}
.info-table td{padding:16px 18px; border-bottom:1px solid var(--hairline); vertical-align:top; color:var(--text-body);}
.info-table tr:last-child td{border-bottom:none;}
.info-table tr:nth-child(even) td{background:var(--light-grey);}
.info-table td:first-child{font-weight:600; color:var(--navy); white-space:nowrap;}
.table-scroll{overflow-x:auto; -webkit-overflow-scrolling:touch;}
@media (max-width:700px){ .info-table td:first-child{white-space:normal;} }

/* ---- Module booking browser (filterable, expandable module list — AI Kap. 9 Angebote) ---- */
.module-filters{display:flex; flex-wrap:wrap; justify-content:center; gap:10px; max-width:var(--maxw); margin:0 auto 44px;}
.module-filter{
  font-family:inherit; cursor:pointer; font-size:14.5px; font-weight:600; padding:9px 18px;
  border-radius:999px; border:1px solid var(--hairline); background:#fff; color:var(--navy-75);
}
.module-filter:hover{border-color:var(--navy-50); color:var(--navy);}
.module-filter.is-active{background:var(--navy); border-color:var(--navy); color:#fff;}

.module-groups{max-width:var(--maxw); margin:0 auto; display:flex; flex-direction:column; gap:48px;}
.module-group-head{display:flex; align-items:baseline; gap:14px; flex-wrap:wrap; padding-bottom:12px; margin-bottom:4px; border-bottom:2px solid var(--navy);}
.module-group-head h3{font-size:22px;}
.module-group-note{font-size:14.5px; color:var(--navy-75);}

.module-list{display:flex; flex-direction:column;}
.module-item{border-bottom:1px solid var(--hairline);}
.module-item summary{
  list-style:none; cursor:pointer; padding:22px 4px; display:flex; align-items:flex-start; gap:16px;
}
.module-item summary::-webkit-details-marker{display:none;}
.module-item summary .chevron{flex-shrink:0; width:20px; height:20px; margin-top:5px; transition:transform .2s ease; color:var(--navy-75);}
.module-item[open] summary .chevron{transform:rotate(180deg);}
.module-item-body{flex:1; min-width:0; display:flex; flex-direction:column; gap:5px;}
.module-step{font-size:12.5px; font-weight:700; text-transform:uppercase; letter-spacing:.08em; color:#1f9e6e;}
.module-title{font-size:19px; font-weight:600; color:var(--navy); line-height:1.3;}
.module-summary{font-size:15.5px; color:var(--navy-75); line-height:1.5;}
.module-price{flex-shrink:0; align-self:center; text-align:right; font-size:15.5px; font-weight:600; color:var(--navy); max-width:14ch;}
.module-price.is-free{color:#1f9e6e;}

.module-detail{padding:0 4px 32px 44px; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:32px; align-items:end;}
.module-detail p{margin:0; font-size:16px; line-height:1.6; color:var(--text-body); max-width:62ch;}
.module-actions .btn{justify-content:center; white-space:nowrap;}
@media (max-width:700px){
  .module-detail{grid-template-columns:1fr; padding-left:4px;}
  .module-price{align-self:flex-start; text-align:left; max-width:none;}
}

/* ---- Status tag (KI-Lösungen availability labels) ---- */
.status-tag{
  display:inline-block; font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:.04em;
  padding:3px 10px; border-radius:20px; background:var(--silver-25); color:var(--navy-75);
}
.status-tag.available{background:var(--mint-25); color:#1f9e6e;}

/* ---- Solution / offer list rows ---- */
.solution-list{display:flex; flex-direction:column; gap:0; max-width:var(--maxw); margin:0 auto; border-top:1px solid var(--hairline);}
.solution-row{
  display:flex; align-items:center; justify-content:space-between; gap:20px; flex-wrap:wrap;
  padding:22px 4px; border-bottom:1px solid var(--hairline);
}
.solution-row .solution-title{font-weight:600; color:var(--navy); font-size:17px; display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
.solution-row .solution-desc{font-size:15px; color:var(--navy-75); margin-top:4px;}

/* ---- Callout box (dated status notes, important asides) ---- */
.callout{
  border-left:4px solid var(--accent-blue); background:var(--light-grey); border-radius:0 10px 10px 0;
  padding:22px 26px; max-width:var(--maxw); margin:0 auto; font-size:15.5px; color:var(--text-body);
}
.callout .callout-label{display:block; font-size:12.5px; font-weight:600; text-transform:uppercase; letter-spacing:.05em; color:var(--accent-blue); margin-bottom:8px;}

/* ---- Checklist (checkmark bullet list — "Was Sie erhalten" style blocks) ---- */
.checklist{max-width:640px; margin:0 auto; display:flex; flex-direction:column; gap:14px; list-style:none; padding:0;}
.checklist li{display:flex; gap:12px; font-size:16.5px; align-items:flex-start;}
.checklist li::before{content:"✓"; color:#1f9e6e; font-weight:700; flex-shrink:0;}

/* ---- Proof strip (compact credentials line) ---- */
.proof-strip{
  text-align:center; font-size:15px; color:var(--navy-75); max-width:var(--maxw); margin:0 auto;
  display:flex; flex-wrap:wrap; justify-content:center; gap:8px 10px;
}
.proof-strip .sep{color:var(--silver);}

/* ---- Team list (stacked rows with photo — dedicated /team page) ---- */
.team-rows{display:flex; flex-direction:column; max-width:840px; margin:0 auto; border-top:1px solid var(--hairline);}
.team-row{display:flex; gap:32px; align-items:flex-start; padding:32px 4px; border-bottom:1px solid var(--hairline);}
.team-row .row-photo{width:240px; height:240px; border-radius:var(--jjw-radius-card); overflow:hidden; flex-shrink:0; background:var(--light-grey);}
.team-row .row-photo img{width:100%; height:100%; object-fit:cover; object-position:50% 22%; display:block;}
.team-row .row-body{display:flex; flex-direction:column; gap:8px; padding-top:8px;}
.team-row .row-name{font-weight:600; color:var(--navy); font-size:20px;}
.team-row .row-role{font-size:14px; color:var(--navy-75); text-transform:uppercase; letter-spacing:.04em; font-weight:600;}
.team-row .row-desc{font-size:15.5px; color:var(--text-body); margin-top:2px;}
@media (max-width:560px){ .team-row{flex-direction:column; align-items:flex-start;} .team-row .row-photo{width:100%; height:auto; aspect-ratio:1/1;} }

/* ---- News list (title + date rows) ---- */
.news-list{max-width:760px; margin:0 auto; display:flex; flex-direction:column; gap:0; border-top:1px solid var(--hairline);}
.news-item{padding:24px 4px; border-bottom:1px solid var(--hairline); display:flex; flex-direction:column; gap:8px;}
.news-item-head{display:flex; align-items:center; gap:12px; flex-wrap:wrap;}
.news-item .news-date{font-size:13px; font-weight:600; text-transform:uppercase; letter-spacing:.05em; color:var(--navy-75);}
.news-badge{font-size:11.5px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; padding:3px 8px; border-radius:4px;}
.news-badge--blue{background:rgba(46,95,138,.12); color:var(--accent-blue);}
.news-badge--amber{background:rgba(255,153,50,.15); color:#994d00;}
.news-badge--mint{background:rgba(62,247,174,.22); color:#085734;}
.news-item .news-title{font-size:18px; font-weight:600; color:var(--navy); line-height:1.35;}
.news-excerpt{font-size:15px; color:var(--navy-75); line-height:1.6; margin:0;}

/* ---- Insights category tabs (News: Retail / AI) ----
   Hidden until insights.js confirms the feed loaded, so a failed fetch leaves
   the fallback cards on screen without dead filters above them.
   Accent colours follow the site convention: AI mint/green, Retail amber. */
.insights-tabs{max-width:760px; margin:0 auto 4px; display:flex; gap:8px; flex-wrap:wrap;}
.insights-tabs[hidden]{display:none;}
.insights-tab{appearance:none; cursor:pointer; font-family:inherit; background:transparent;
  border:1px solid var(--hairline); border-radius:999px; padding:7px 16px;
  font-size:13.5px; font-weight:600; letter-spacing:.01em; color:var(--navy-75);
  transition:background .15s ease, border-color .15s ease, color .15s ease;}
.insights-tab:hover{border-color:var(--navy-50); color:var(--navy);}
.insights-tab:focus-visible{outline:2px solid var(--accent-blue); outline-offset:2px;}
.insights-tab[aria-selected="true"]{background:var(--navy); border-color:var(--navy); color:#fff;}
.insights-tab[aria-selected="true"][data-cat="AI"]{background:#0E7A52; border-color:#0E7A52;}
.insights-tab[aria-selected="true"][data-cat="Retail"]{background:#8A5300; border-color:#8A5300;}
.insights-tab .insights-tab-count{margin-left:6px; opacity:.65; font-weight:500;}
.insights-empty{padding:32px 4px; color:var(--navy-75); font-size:15px; text-align:center;}

/* ---- Contact page: form + info panel ---- */
.contact-grid{display:grid; grid-template-columns:1.3fr 1fr; gap:48px; max-width:var(--maxw); margin:0 auto; align-items:start;}
@media (max-width:800px){ .contact-grid{grid-template-columns:1fr;} }
.form-grid{display:grid; grid-template-columns:1fr 1fr; gap:20px;}
.form-field{display:flex; flex-direction:column; gap:6px;}
.form-field.full{grid-column:1/-1;}
.form-field[hidden]{display:none;}
.form-field label{font-size:13.5px; font-weight:600; color:var(--navy);}
.form-field input, .form-field textarea, .form-field select{
  height:46px; border:1.5px solid #c8d1dc; border-radius:var(--jjw-radius-control);
  padding:0 14px; font-family:var(--font); font-size:15.5px; color:var(--text-body); background:#fff;
  box-shadow:0 1px 3px rgba(15,47,88,.05);
  transition:border-color .18s ease, box-shadow .18s ease;
}
.form-field textarea{height:140px; padding:12px 14px; resize:vertical;}
.form-field input:hover, .form-field textarea:hover, .form-field select:hover{
  border-color:#94a3b8;
}
.form-field input:focus, .form-field textarea:focus, .form-field select:focus{
  outline:none; border-color:var(--navy); box-shadow:0 0 0 3px rgba(15,47,88,.14);
}
.form-note{font-size:13.5px; color:var(--navy-75); margin-top:14px;}
.form-checkbox{display:flex; align-items:flex-start; gap:10px; font-size:14.5px; color:var(--text-body); line-height:1.5;}
.form-checkbox input{margin-top:3px; flex-shrink:0; width:16px; height:16px; accent-color:var(--navy);}
.form-checkbox.optional{background:var(--light-grey); border-radius:var(--jjw-radius-control); padding:14px 16px;}

/* ---- Contact Form Bot Protection & Feedback States ---- */
.form-hp {
  position: absolute !important;
  left: -9999px !important;
  top: -9999px !important;
  width: 0 !important;
  height: 0 !important;
  opacity: 0 !important;
  pointer-events: none !important;
  overflow: hidden !important;
  z-index: -1 !important;
  visibility: hidden !important;
}

.contact-feedback {
  display: none;
  margin-top: 20px;
  padding: 16px 20px;
  border-radius: var(--jjw-radius-control);
  font-size: 14.5px;
  line-height: 1.55;
  animation: contactFeedbackIn 0.25s ease-out;
}
@keyframes contactFeedbackIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

.contact-feedback.is-success {
  background: #f0fdf4;
  border: 1.5px solid #86efac;
  color: #14532d;
}
.contact-feedback.is-success h4 {
  margin: 0 0 4px 0;
  font-size: 16px;
  font-weight: 700;
  color: #14532d;
}
.contact-feedback.is-success p {
  margin: 0;
  color: #166534;
}

.contact-feedback.is-error {
  background: #fef2f2;
  border: 1.5px solid #fca5a5;
  color: #991b1b;
}
.contact-feedback.is-error h4 {
  margin: 0 0 4px 0;
  font-size: 16px;
  font-weight: 700;
  color: #991b1b;
}
.contact-feedback.is-error p {
  margin: 0;
  color: #991b1b;
}
.contact-feedback.is-error a {
  color: #991b1b;
  font-weight: 600;
  text-decoration: underline;
}

.btn.is-submitting {
  position: relative;
  opacity: 0.8 !important;
  pointer-events: none !important;
  cursor: wait !important;
}
.btn.is-submitting::after {
  content: "";
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: 8px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: btnSpin 0.6s linear infinite;
  vertical-align: -2px;
}
@keyframes btnSpin {
  to { transform: rotate(360deg); }
}
.contact-info{background:var(--light-grey); border-radius:var(--jjw-radius-card); padding:32px; display:flex; flex-direction:column; gap:22px; overflow:hidden;}
.contact-section{padding-top:72px;}
.contact-person{display:flex; flex-direction:column; align-items:center; gap:20px; padding-bottom:28px; text-align:center; border-bottom:1px solid rgba(18,55,96,.12);}
.contact-person-photo{width:240px; height:240px; flex:0 0 240px; object-fit:cover; object-position:center top; border-radius:50%; box-shadow:0 14px 38px rgba(18,55,96,.2);}
.contact-person-copy{display:flex; flex-direction:column; align-items:center;}
.contact-person h3{font-size:24px; line-height:1.2; margin:5px 0 4px;}
.contact-person p{margin:0; color:var(--navy-75); font-size:14px;}
.contact-intro{margin:-2px 0 0; color:var(--navy-75); line-height:1.55;}
.contact-info .info-row{display:flex; align-items:center; gap:16px;}
.contact-info .info-content{display:flex; flex-direction:column; gap:2px; min-width:0;}
.contact-icon{width:28px; height:28px; flex:0 0 28px; fill:none; stroke:var(--navy); stroke-width:1.7; stroke-linecap:round; stroke-linejoin:round;}
.contact-info .info-label{font-size:12.5px; font-weight:600; text-transform:uppercase; letter-spacing:.05em; color:var(--navy-75);}
.contact-info .info-value{font-size:16px; color:var(--navy); font-weight:600;}
.contact-info a{text-decoration:none; color:var(--navy);}
.contact-info a:hover{text-decoration:underline;}
@media (max-width:420px){
  .contact-info{padding:24px;}
  .contact-section{padding-top:48px;}
  .contact-person{gap:18px;}
  .contact-person-photo{width:190px; height:190px; flex-basis:190px;}
}

/* ---- FAQ accordion (native details/summary; first item open per spec) ---- */
.faq-list{max-width:820px; margin:0 auto; display:flex; flex-direction:column; gap:1px; background:var(--hairline); border:1px solid var(--hairline); border-radius:var(--jjw-radius-card); overflow:hidden;}
.faq-item{background:#fff;}
.faq-item summary{
  list-style:none; cursor:pointer; padding:20px 24px; font-weight:600; color:var(--navy); font-size:16px;
  display:flex; align-items:center; justify-content:space-between; gap:16px;
}
.faq-item summary::-webkit-details-marker{display:none;}
.faq-item summary .chevron{flex-shrink:0; width:20px; height:20px; transition:transform .2s ease; color:var(--navy-75);}
.faq-item[open] summary .chevron{transform:rotate(180deg);}
.faq-item .faq-answer{padding:0 24px 22px; font-size:15.5px; color:var(--text-body); max-width:70ch;}
.faq-answer a{color:var(--navy); font-weight:600; text-decoration:underline;}
/* Each question has an id (/faq#kosten-interim-manager); clear the compact header. */
.faq-item{scroll-margin-top:96px;}
.faq-group{max-width:820px; margin:0 auto 44px;}
.faq-group:last-child{margin-bottom:0;}
.faq-group h2{font-size:20px; line-height:1.3; margin:0 0 14px;}
/* Four /faq questions on a service page, then the way to the rest. */
.faq-teaser__more{max-width:820px; margin:28px auto 0; text-align:center;}

/* ---- Photo panel (full-bleed portrait with the copy floating on the cleared
        side). Lifted out of retail-it.html once /retail-it/leistungen and
        /retail-it/pm-netzwerk needed it too. The composition itself is neutral;
        the accent CTA is amber, so keep this to Retail pages — the AI spoke
        has its own mint equivalents in ai.html. ---- */
/* border-block, not :last-of-type — that matched nothing, since the last
   <section> on the page is the proof strip rather than a panel, so neither
   panel ever got its closing hairline. The adjacency rule keeps the seam a
   single line if two panels ever sit next to each other again. */
.photo-panel{padding:0; background:#fff; border-block:1px solid var(--hairline);}
.photo-panel + .photo-panel{border-top:0;}
.photo-panel__panel{position:relative; width:100%; min-height:560px; overflow:hidden; background:#fff; display:flex; align-items:center;}
/* direct child only: the copy block may itself contain an <img> (the
   KMU.DIGITAL badge on /ai), which a descendant selector would blow up
   to the full plate. */
.photo-panel__panel > img{position:absolute; top:0; right:0; width:64%; height:100%; object-fit:cover; object-position:center;}
/* Blur band across the dissolve so photographic detail melts into the page
   rather than the gradient laying a flat wash over everything still sharp. */
.photo-panel__panel::after{content:""; position:absolute; z-index:1; inset:0; background:linear-gradient(90deg,#fff 0%,#fff 31%,rgba(255,255,255,.94) 41%,rgba(255,255,255,.5) 53%,transparent 67%);}
.photo-panel__copy{position:relative; z-index:2; width:min(560px,calc(100% - 48px)); margin-left:max(24px,calc((100vw - 1240px)/2)); padding:72px 0;}
.photo-panel__copy .cta-row{justify-content:flex-start; margin-top:24px;}

/* ---- Image placeholder (50/50 ratio) --------------------------------
   When a photo panel carries a placeholder instead of an <img>, render
   as an exact 50/50 containerized split rather than a 64% full-bleed
   plate so the layout stays visually balanced. ---- */
.photo-panel:has(.img-placeholder) .photo-panel__panel,
.photo-panel--split .photo-panel__panel{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:56px;
  align-items:center;
  max-width:var(--maxw);
  margin:0 auto;
  min-height:auto;
  padding:72px 24px;
  box-sizing:border-box;
}
.photo-panel:has(.img-placeholder) .photo-panel__panel::before,
.photo-panel:has(.img-placeholder) .photo-panel__panel::after,
.photo-panel--split .photo-panel__panel::before,
.photo-panel--split .photo-panel__panel::after{
  display:none !important;
}
.photo-panel:has(.img-placeholder) .photo-panel__copy,
.photo-panel--split .photo-panel__copy{
  position:static;
  width:100%;
  max-width:none;
  margin:0;
  padding:0;
  order:1;
}
.photo-panel:has(.img-placeholder) .photo-panel__panel > .img-placeholder,
.photo-panel--split .photo-panel__panel > .img-placeholder{
  position:relative;
  top:auto; right:auto; bottom:auto; left:auto;
  width:100%;
  height:auto;
  aspect-ratio:4/3;
  min-height:360px;
  order:2;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px;
  padding:24px; text-align:center;
  background:repeating-linear-gradient(135deg,var(--silver-25) 0 14px,var(--silver-50) 14px 28px);
  border:2px dashed var(--navy-25);
  border-radius:var(--jjw-radius-card);
  box-sizing:border-box;
}

/* Flipped variation: placeholder left (50%), copy right (50%) */
.photo-panel--flip:has(.img-placeholder) .photo-panel__panel > .img-placeholder,
.photo-panel--flip.photo-panel--split .photo-panel__panel > .img-placeholder{
  order:1;
}
.photo-panel--flip:has(.img-placeholder) .photo-panel__copy,
.photo-panel--flip.photo-panel--split .photo-panel__copy{
  order:2;
  margin:0;
}

/* Hero variation: generous vertical rhythm for page header duty */
.photo-panel--hero:has(.img-placeholder) .photo-panel__panel,
.photo-panel--hero.photo-panel--split .photo-panel__panel{
  min-height:auto;
  padding:84px 24px 72px;
}
.photo-panel--hero:has(.img-placeholder) .photo-panel__panel > .img-placeholder,
.photo-panel--hero.photo-panel--split .photo-panel__panel > .img-placeholder{
  aspect-ratio:4/3;
}

.img-placeholder span{
  font-size:11px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--navy-50);
}
.img-placeholder b{font-size:17px; font-weight:600; color:var(--navy-75);}
.img-placeholder code{font-size:12px; color:var(--navy-50); word-break:break-all; max-width:34ch;}

@media(max-width:900px){
  .photo-panel:has(.img-placeholder) .photo-panel__panel,
  .photo-panel--split .photo-panel__panel{
    grid-template-columns:minmax(0,1fr);
    gap:36px;
    padding:56px 20px;
  }
  .photo-panel:has(.img-placeholder) .photo-panel__panel > .img-placeholder,
  .photo-panel--split .photo-panel__panel > .img-placeholder{
    order:1;
    min-height:260px;
    aspect-ratio:16/10;
  }
  .photo-panel:has(.img-placeholder) .photo-panel__copy,
  .photo-panel--split .photo-panel__copy{
    order:2;
    padding:0;
  }
}

.photo-panel--flip .photo-panel__panel > img{right:auto; left:0;}
.photo-panel--flip .photo-panel__panel::before{right:auto; left:34%;}
.photo-panel--flip .photo-panel__panel::after{background:linear-gradient(270deg,#fff 0%,#fff 31%,rgba(255,255,255,.94) 41%,rgba(255,255,255,.5) 53%,transparent 67%);}
.photo-panel--flip .photo-panel__copy{margin-left:auto; margin-right:max(24px,calc((100vw - 1240px)/2));}

/* ---- The plate as a page hero ---------------------------------------
   /retail-it introduces the network on this component, so the subpage it
   links to opens on the same one — the two hand off in a single visual
   language instead of the subpage restating it in a boxed aside.
   Hero duty needs three things the mid-page plate does not: no top
   hairline (the header already draws one), an H1's measure rather than an
   H2's, and enough depth that a four-line German headline still clears
   the CTA row. Every override below is keyed on --hero and so outranks
   the plain-class responsive rules further down (0,2,0 vs 0,1,0) — which
   is why each of those breakpoints needs a --hero twin, not why it does
   not. ---- */
.photo-panel--hero{border-top:0;}
/* This plate was built for landscape photography — every other panel on the
   site carries a 1600x1067 shot. The PM hero carries a portrait (1067x1600),
   and a portrait in a box that grows wider at a fixed height loses its subject
   from the bottom up: the image covers by width, so at 1440 the panel shows
   43% of the photo and at 1920 only 32% — head-to-thigh becomes head-to-waist
   on a wide monitor. Scaling the height with the width holds that fraction
   constant (0.64 width share x 1600/1067 x 43% = 41.4vw). The clamp's ceiling
   means the crop does tighten again past ~1980px; if this plate ever gets a
   landscape photo, drop the whole rule back to a flat min-height. */
.photo-panel--hero .photo-panel__panel{min-height:clamp(600px,41.4vw,820px);}
.photo-panel--hero .photo-panel__copy{padding:84px 0;}
.photo-panel--hero h1{
  margin:0 0 20px; color:var(--navy);
  font-size:clamp(30px,3.1vw,44px); line-height:1.12;
  hyphens:manual;
}
.photo-panel--hero .sub{margin:0 0 30px; color:var(--navy-75); font-size:18px; line-height:1.6;}
.photo-panel--hero .cta-row{justify-content:flex-start; margin-top:0;}
/* Where the dissolve sits, relative to the man in the photo.
   The stock plate starts whitening at 33% of the panel and does not finish
   until 69% — tuned for a landscape photo whose subject sits well left of it.
   This portrait puts Jeremy at roughly 37-64% of the photo box, which is 41%
   of the panel, so the stock fade opens over his shoulder and dissolves his
   arm. Note object-position cannot help: the scaled photo is exactly the box
   width, so there is no horizontal overflow for it to shift.
   The copy column starts at 53-54% of the panel at every width above 1100
   (its margin is (100vw-1240)/2 and its measure 560px), so the dissolve has to
   open after him and be solid before the text: inside 41%-53%. Narrower than
   stock and further right. Stops are quoted 270deg, i.e. from the right. */
.photo-panel--hero .photo-panel__panel::after{
  background:linear-gradient(270deg,
    #fff 0%, #fff 46%,
    rgba(255,255,255,.82) 51%,
    rgba(255,255,255,.35) 56%,
    transparent 61%);
}
.photo-panel--hero .photo-panel__panel::before{left:38%; width:20%;}
/* And where the man sits inside the frame. He is centred in the source, so
   the plate rendered him centre-right with a stretch of empty pavement to his
   left. object-position cannot move him — the scaled photo is exactly the box
   width, so there is no horizontal overflow to shift — but sliding the whole
   image box left does, and costs nothing vertically because the width, and so
   the scale, is unchanged.
   -10% is bounded by where the gradient goes fully opaque: the image's right
   edge lands at -10% + 64% = 54%, and the fade reaches solid white at 46% from
   the right, i.e. exactly 54% from the left. So the photo ends precisely where
   the page turns white and no gap opens. Both numbers are panel percentages,
   so the two track each other at every width. */
.photo-panel--hero .photo-panel__panel > img{left:-10%;}

.photo-panel__kicker{display:block; margin-bottom:14px; color:#8A5300; font-size:12px; font-weight:700; letter-spacing:.14em; text-transform:uppercase;}
/* hyphens as a safety net, not a habit: at 52px a German compound like
   "Massenausschreibungen" is wider than the 560px copy column and would
   otherwise slide out under the panel's overflow:hidden. */
.photo-panel__copy h2{margin:0 0 18px; color:var(--navy); font-size:var(--jjw-h2); line-height:1.2; hyphens:auto;}
.photo-panel__copy p{margin:0 0 24px; color:var(--navy-75); font-size:var(--jjw-body); line-height:1.6;}
.photo-panel__creds{margin:0 0 30px; padding:20px 0 0; list-style:none; border-top:1px solid var(--hairline);}
.photo-panel__creds li{font-size:14.5px; line-height:1.6; color:var(--navy-75);}
.photo-panel__creds li:first-child{font-weight:600; color:var(--navy);}
.photo-panel__cta{display:inline-flex; align-items:center; min-height:48px; padding:0 20px; color:#09121e; background:var(--amber); border-radius:8px; font-size:15px; font-weight:700; text-decoration:none; transition:background .18s ease;}
.photo-panel__cta:hover{background:#f6b95d;}

/* Between 760 and 1100 the copy column stops being centred by the 1240px
   gutter and slides onto the photo. Narrow the plate and start the
   dissolve sooner so the text keeps a clear field. */
@media(max-width:1100px){
  .photo-panel__panel{min-height:520px;}
  .photo-panel__panel > img{width:56%;}
  .photo-panel__panel::before{right:26%; width:34%;}
  .photo-panel__panel::after{background:linear-gradient(90deg,#fff 0%,#fff 38%,rgba(255,255,255,.95) 47%,rgba(255,255,255,.55) 58%,transparent 72%);}
  .photo-panel--flip .photo-panel__panel::before{right:auto; left:26%;}
  .photo-panel--flip .photo-panel__panel::after{background:linear-gradient(270deg,#fff 0%,#fff 38%,rgba(255,255,255,.95) 47%,rgba(255,255,255,.55) 58%,transparent 72%);}
  .photo-panel__copy{width:min(520px,calc(100% - 40px)); padding:56px 0;}
  .photo-panel--hero .photo-panel__panel{min-height:560px;}
  .photo-panel--hero .photo-panel__copy{padding:64px 0;}
  /* At this width the copy loses the 1240px gutter and starts at ~50% while the
     photo narrows to 56%, putting Jeremy's edge near 36%. Same rule, shifted. */
  .photo-panel--hero .photo-panel__panel::after{
    background:linear-gradient(270deg,
      #fff 0%, #fff 50%,
      rgba(255,255,255,.82) 55%,
      rgba(255,255,255,.35) 60%,
      transparent 65%);
  }
  .photo-panel--hero .photo-panel__panel::before{left:34%; width:20%;}
  /* Same bound, different numbers: the photo is 56% wide here and the fade goes
     solid at 50% from the left, so the shift cannot exceed -6%. */
  .photo-panel--hero .photo-panel__panel > img{left:-6%;}
}
@media(max-width:760px){
  /* Stacked, the photo sits above the copy at its natural crop — the side
     dissolve has nothing left to dissolve into, so it becomes a bottom
     fade and the blur band goes away. */
  .photo-panel__panel{min-height:0; flex-direction:column; align-items:stretch;}
  .photo-panel__panel > img{position:relative; width:100%; height:320px;}
  .photo-panel__panel::before{display:none;}
  .photo-panel__panel::after,
  .photo-panel--flip .photo-panel__panel::after{inset:0 0 auto 0; height:320px; background:linear-gradient(180deg,transparent 58%,rgba(255,255,255,.72) 84%,#fff 100%);}
  .photo-panel__copy,
  .photo-panel--flip .photo-panel__copy{width:100%; margin:0; padding:34px 20px 52px;}
  /* Stacked, the hero plate is just a photo over copy like any other, so it
     drops back to the shared measure — but keeps its own top padding: it sits
     directly under the header with no section gap above it. */
  .photo-panel--hero .photo-panel__panel{min-height:0;}
  /* Stacked, the photo is position:relative and full width — the desktop shift
     would just drag it off the left edge. */
  .photo-panel--hero .photo-panel__panel > img{left:0;}
  .photo-panel--hero .photo-panel__copy{width:100%; margin:0; padding:30px 20px 48px;}

}

.photo-panel__badge{display:block;width:330px;max-width:100%;height:auto;margin:0 0 24px;}
@media(max-width:760px){.photo-panel__badge{width:270px;margin-bottom:20px;}}

/* ---- AI Solutions Showcase & Pre-built Modules ---- */
.solutions-showcase{background:#f5f7f8;}
.solutions-showcase .solution-list{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;max-width:1120px;margin:40px auto 0;border:0;}
.solutions-showcase .solution-row{position:relative;display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;flex-wrap:nowrap;min-height:300px;padding:28px;border:1px solid rgba(15,47,88,.12);border-top:4px solid var(--mint);border-radius:var(--jjw-radius-card);background:#fff;box-shadow:0 14px 34px rgba(15,47,88,.05);transition:transform .2s ease,box-shadow .2s ease;}
.solutions-showcase .solution-row:hover{transform:translateY(-3px);box-shadow:0 18px 40px rgba(15,47,88,.09);}
.solutions-showcase .solution-index{display:block;margin-bottom:32px;color:rgba(15,47,88,.28);font-size:42px;font-weight:600;line-height:1;letter-spacing:-.04em;}
.solutions-showcase .solution-title{display:block;font-size:20px;font-weight:700;color:var(--navy);line-height:1.3;}
.solutions-showcase .solution-desc{margin-top:12px;font-size:15px;line-height:1.55;color:var(--navy-75);flex-grow:1;}
.solutions-showcase .solution-row > .ghost-link{margin-top:auto;padding-top:24px;text-align:left;color:var(--navy);font-weight:600;text-decoration:none;transition:color .18s ease;}
.solutions-showcase .solution-row > .ghost-link:hover{color:#087a52;}
@media(max-width:900px){
  .solutions-showcase .solution-list{grid-template-columns:1fr;}
  .solutions-showcase .solution-row{min-height:0;}
  .solutions-showcase .solution-index{margin-bottom:20px;}
  .solutions-showcase .solution-row > .ghost-link{margin-top:20px;padding-top:0;}
}
@media(max-width:640px){
  .solutions-showcase .solution-row{padding:22px 20px;}
}

/* ---- Custom Workflow Panel (Individuell statt Standard) ---- */
.custom-workflow{padding:0;background:#fff;border:none;}
.custom-workflow__panel{position:relative;width:100%;min-height:560px;overflow:hidden;background:#fff;display:flex;align-items:center;}
.custom-workflow__panel img{position:absolute;top:0;right:0;width:58%;height:100%;object-fit:contain;object-position:right center;opacity:1;filter:none;}
.custom-workflow__panel::before{content:"";position:absolute;z-index:1;top:0;bottom:0;left:34%;width:26%;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);mask-image:linear-gradient(90deg,transparent,#000 28%,#000 68%,transparent);-webkit-mask-image:linear-gradient(90deg,transparent,#000 28%,#000 68%,transparent);}
.custom-workflow__panel::after{content:"";position:absolute;z-index:1;inset:0;background:linear-gradient(90deg,#fff 0%,#fff 42%,rgba(255,255,255,.96) 50%,rgba(255,255,255,.45) 62%,transparent 74%);}
.custom-workflow__copy{position:relative;z-index:2;width:min(580px,calc(100% - 48px));margin-left:max(24px,calc((100vw - 1240px)/2));padding:72px 0;}
.custom-workflow__kicker{display:block;margin-bottom:14px;color:#087a52;font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;}
.custom-workflow__copy h2{margin:0 0 18px;color:var(--navy);font-size:var(--jjw-h2);line-height:1.2;}
.custom-workflow__copy p{margin:0 0 28px;color:var(--navy-75);font-size:var(--jjw-body);line-height:1.6;}
.custom-workflow__cta{display:inline-flex;align-items:center;min-height:48px;padding:0 24px;color:#071522;background:var(--mint);border-radius:8px;font-size:15.5px;font-weight:700;text-decoration:none;transition:background .18s ease,transform .18s ease,box-shadow .18s ease;box-shadow:0 1px 2px rgba(0,0,0,.08);}
.custom-workflow__cta:hover{background:#34dc9b;transform:translateY(-1px);box-shadow:0 4px 14px rgba(62,247,174,.32);}
@media(max-width:900px){
  .custom-workflow__panel{min-height:650px;align-items:flex-start;}
  .custom-workflow__copy{width:calc(100% - 40px);margin-left:20px;padding:52px 0;}
  .custom-workflow__panel img{top:auto;bottom:0;right:0;width:100%;height:58%;object-fit:contain;opacity:.72;}
  .custom-workflow__panel::before{display:none;}
  .custom-workflow__panel::after{background:linear-gradient(180deg,#fff 0%,#fff 48%,rgba(255,255,255,.82) 61%,transparent 100%);}
}

/* ---- Tool Landscape ---- */
.tool-landscape{text-align:center;}
.tool-landscape__copy{max-width:780px;margin:0 auto 44px;}
.tool-landscape__copy .kicker{display:block;margin-bottom:14px;color:#087a52;font-weight:700;}
.tool-landscape__copy h2{font-size:var(--jjw-h2);line-height:1.2;margin-bottom:16px;text-wrap:balance;}
.tool-landscape__copy > p{color:var(--navy-75);font-size:var(--jjw-subline);line-height:1.6;}
.tool-landscape__visual{max-width:920px;margin:0 auto;}
.tool-landscape__visual img{display:block;width:100%;height:auto;}
.tool-landscape__note{display:block;max-width:740px;margin:24px auto 0;color:var(--navy-50);font-size:13px;line-height:1.55;}
@media(max-width:900px){
  .tool-landscape__copy{margin-bottom:30px;}
  .tool-landscape__copy > p{font-size:16.5px;}
}

/* ---- Bookkeeping workflow modal sketch canvas (.bk-*) ---- */
.bk-canvas{position:relative; width:2040px; height:700px; flex-shrink:0;}
.bk-node{position:absolute; width:128px; display:flex; flex-direction:column; align-items:center; gap:14px;}
.bk-box{width:92px; height:92px; border:2.6px solid #1a1a1a; background:#fff; border-radius:255px 16px 225px 16px/16px 225px 16px 255px; display:flex; align-items:center; justify-content:center;}
.bk-node:nth-of-type(even) .bk-box{border-radius:16px 235px 16px 235px/225px 16px 235px 16px; transform:rotate(.8deg);}
.bk-node:nth-of-type(odd) .bk-box{transform:rotate(-.8deg);}
.bk-node svg{width:40px; height:40px; fill:none; stroke:#1a1a1a; stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round;}
.bk-label{font-family:'Kalam',cursive; font-weight:700; font-size:17px; color:#1a1a1a; text-align:center; line-height:1.3;}
.bk-engine{width:172px;}
.bk-engine .bk-box{width:148px; height:148px; border-width:3px; background:#e8fbf1; box-shadow:6px 8px 0 -2px rgba(26,26,26,.12);}
.bk-engine svg{width:66px; height:66px;}
.bk-engine .bk-label{font-size:21px; white-space:nowrap;}
.bk-good .bk-box{border-color:#1e9e62; background:#e8fbf1;}
.bk-good .bk-box svg{stroke:#1e9e62; stroke-width:1.8;}
.bk-bad .bk-box{border-color:#b74b4b; background:#fff0f0;}
.bk-bad .bk-box svg{stroke:#b74b4b; stroke-width:1.8;}
.bk-branch{position:absolute; width:170px; text-align:center; font-family:'Architects Daughter',cursive; font-size:13px; letter-spacing:.08em; text-transform:uppercase; font-weight:700;}

/* ---- CRM Interactive Canvas in Modal ---- */
.crm-canvas{width:1500px;min-height:480px;padding:82px 54px;display:flex;align-items:center;gap:20px;background-image:radial-gradient(rgba(15,47,88,.11) 1px,transparent 1px);background-size:22px 22px;}
.crm-node{width:190px;min-height:210px;padding:24px 20px;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;background:#fff;border:2px solid #1a1a1a;border-radius:18px;box-shadow:6px 7px 0 rgba(26,26,26,.08);}
.crm-node--engine{width:220px;background:var(--mint-25);border-width:3px;}
.crm-node svg{width:42px;height:42px;margin-bottom:18px;fill:none;stroke:#1a1a1a;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;}
.crm-node strong{font-family:'Kalam',cursive;font-size:18px;line-height:1.3;color:#1a1a1a;}
.crm-node small{margin-top:10px;color:var(--navy-75);font-size:12.5px;line-height:1.4;}
.crm-arrow{flex:0 0 34px;color:var(--navy);font-size:30px;text-align:center;}

/* ---- AI Ribbon (high-conversion closing stage — pure white matching main AI page) ---- */
.ai-ribbon{background:#ffffff; color:var(--navy); padding:96px 0 104px; text-align:center;}
.ai-ribbon h2{color:var(--navy); font-size:var(--jjw-h2); line-height:1.2; font-weight:600; max-width:780px; margin:14px auto 18px; text-wrap:balance;}
.ai-ribbon .kicker{color:#2e5f8a; font-size:var(--jjw-kicker); letter-spacing:.12em; text-transform:uppercase; font-weight:700; display:inline-block; margin-bottom:14px;}
.ai-ribbon p{color:var(--navy-75); font-size:var(--jjw-subline); line-height:1.55; max-width:720px; margin:0 auto 36px; text-wrap:balance;}
.ai-ribbon .btn-mint{background:var(--mint); color:#071522; border:1px solid var(--mint); font-weight:700; font-size:16px; min-height:52px; padding:0 28px; border-radius:8px; box-shadow:0 12px 30px rgba(62,247,174,.42),0 4px 14px rgba(30,58,95,.12); transition:all 180ms ease;}
.ai-ribbon .btn-mint:hover{background:#6ef9c2; border-color:#6ef9c2; color:#071522; transform:translateY(-2px); box-shadow:0 16px 38px rgba(62,247,174,.52),0 6px 18px rgba(30,58,95,.18);}
.ai-ribbon .btn-secondary{background:#ffffff; color:var(--navy); border:1.5px solid rgba(30,58,95,.22); border-radius:8px; font-size:16px; font-weight:600; min-height:52px; padding:0 26px; box-shadow:0 8px 24px rgba(30,58,95,.09),0 2px 6px rgba(30,58,95,.04); transition:all 180ms ease;}
.ai-ribbon .btn-secondary:hover{border-color:var(--navy); background:rgba(30,58,95,.03); color:var(--navy); transform:translateY(-2px); box-shadow:0 12px 30px rgba(30,58,95,.15),0 4px 10px rgba(30,58,95,.08);}
@media(max-width:640px){.ai-ribbon{padding:64px 20px 72px;}}


/* ---- Process flow (step sequences — Retail Kap. 10.2 Auswahlprozess, 10.3 Aufnahme) ---- */
.process-flow{display:flex; align-items:flex-start; justify-content:center; gap:2px; max-width:var(--maxw); margin:0 auto; flex-wrap:wrap;}
.process-step{display:flex; flex-direction:column; align-items:center; text-align:center; width:150px; gap:10px; padding:0 6px;}
.process-step .step-num{
  width:38px; height:38px; border-radius:50%; background:var(--light-grey); color:var(--navy);
  display:flex; align-items:center; justify-content:center; font-weight:600; font-size:15px; border:2px solid var(--hairline); flex-shrink:0;
}
.process-step.is-personal .step-num{background:var(--amber-25); border-color:var(--amber); color:#8a5300;}
.process-step .step-label{font-size:13.5px; color:var(--text-body); line-height:1.4;}
.process-step.is-personal .step-label{font-weight:600; color:var(--navy);}
.process-arrow{color:var(--navy-25); font-size:18px; padding-top:9px; flex-shrink:0;}
@media (max-width:800px){
  .process-flow{flex-direction:column; align-items:center;}
  .process-arrow{transform:rotate(90deg); padding:2px 0;}
}

/* ---- Connected node path / Responsibility & Intake flows (.mf-section, .mf-row) ---- */
.mf-section{background:var(--light-grey); border:none;}
.mf-row{position:relative; display:grid; grid-template-columns:repeat(3,1fr); gap:64px; max-width:1040px; margin:48px auto 0;}
.mf-row::before{content:""; position:absolute; top:68px; left:16.66%; right:16.66%; height:2px; background:var(--navy-25);}

/* 5-step intake / process flow */
.mf-row--5{grid-template-columns:repeat(5,1fr); gap:28px; max-width:1160px; margin:48px auto 0;}
.mf-row--5::before{left:10%; right:10%;}

.mf-node{position:relative; z-index:1; display:flex; flex-direction:column; align-items:center; text-align:center;}
.mf-level{display:block; color:rgba(15,47,88,.62); font-size:11px; font-weight:700; letter-spacing:.12em; text-transform:uppercase; margin-bottom:14px;}
.mf-box{width:76px; height:76px; border:2px solid var(--navy); background:var(--light-grey); border-radius:50%; display:flex; align-items:center; justify-content:center; flex-shrink:0; box-shadow:0 0 0 10px var(--light-grey); transition:transform .2s ease, background .2s ease, box-shadow .2s ease, border-color .2s ease;}
.mf-node:hover .mf-box{transform:translateY(-2px); background:#ffffff; border-color:var(--navy); box-shadow:0 6px 18px rgba(15,47,88,.12), 0 0 0 10px var(--light-grey);}
.mf-node svg{width:30px; height:30px; fill:none; stroke:var(--navy); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; transition:stroke .2s ease;}
.mf-node:hover svg{stroke:var(--navy);}
.mf-node strong{display:block; color:var(--navy); font-size:18px; line-height:1.25; margin:22px 0 9px;}
.mf-node p{max-width:260px; color:var(--navy-75); font-size:14px; line-height:1.55; margin:0;}

@media (max-width:1080px) and (min-width:761px){
  .mf-row--5{gap:16px;}
  .mf-row--5 .mf-node strong{font-size:16px;}
  .mf-row--5 .mf-node p{font-size:13px; line-height:1.45;}
}

@media (max-width:760px){
  .mf-row, .mf-row--5{grid-template-columns:1fr; max-width:440px; gap:36px; margin:36px auto 0;}
  .mf-row::before, .mf-row--5::before{top:40px; bottom:40px; left:37px; right:auto; width:2px; height:auto; background:var(--navy-25);}
  .mf-node{display:grid; grid-template-columns:76px minmax(0,1fr); column-gap:20px; text-align:left; align-items:start;}
  .mf-level{grid-column:2; margin:0 0 2px;}
  .mf-box{grid-column:1; grid-row:1 / span 3; box-shadow:0 0 0 8px var(--light-grey);}
  .mf-node strong{grid-column:2; margin:0 0 6px; overflow-wrap:break-word; font-size:17px;}
  .mf-node p{grid-column:2; max-width:none; font-size:13.5px;}
}

/* ---- Workflow modal (solution-row "window" preview — full intake-to-signature flow) ---- */
dialog.wf-modal{
  border:none; border-radius:16px; padding:0; width:min(760px, calc(100vw - 48px));
  max-height:min(88vh, 800px); box-shadow:0 24px 64px rgba(10,20,35,.28);
}
dialog.wf-modal::backdrop{background:rgba(8,16,28,.55); backdrop-filter:blur(2px);}
.wf-modal__inner{padding:40px 40px 36px; max-height:min(88vh, 800px); overflow-y:auto; position:relative;}
.wf-modal__close{
  position:absolute; top:16px; right:16px; width:34px; height:34px; border-radius:50%; border:none;
  background:var(--light-grey); color:var(--navy); font-size:19px; line-height:1; cursor:pointer; z-index:2;
}
.wf-modal__close:hover{background:var(--mint-25);}

.wf-modal__text h3{font-size:15px; margin-bottom:8px; color:var(--navy);}
.wf-modal__text p{font-size:14.5px; color:var(--navy-75); line-height:1.6;}
.wf-modal__text > div + div{margin-top:20px;}

/* Sketch variant: hand-drawn process diagram, own type scale and card color —
   deliberately distinct from the site's Outfit/navy language so it reads as a
   whiteboard sketch, with the Problem/Lösung copy below back in site type. */
/* Wider than the plain modal because the diagrams inside are fixed-pixel
   canvases up to 2040px — every px here is one less px they have to be
   scaled down by to fit. */
dialog.wf-modal.wf-modal--sketch{width:min(1880px, 96vw); max-height:min(94vh, 980px);}
.wf-modal--sketch .wf-modal__inner{background:#FFFDF8; padding:32px 32px 36px; max-height:min(94vh, 980px);}
.wf-modal--sketch .wf-modal__close{background:#F6F4EF; border:2px solid #1A1A1A; color:#1A1A1A;}
.wf-modal--sketch .wf-modal__close:hover{background:#E8FBF1;}
.wf-sketch-head{padding:0 24px 22px; display:flex; flex-direction:column; gap:4px;}
.wf-sketch-kicker{font-family:'Architects Daughter',cursive; font-size:15px; letter-spacing:.22em; text-transform:uppercase; color:#6E6A62;}
.wf-sketch-title{font-family:'Kalam',cursive; font-weight:700; font-size:26px; color:#1A1A1A;}

.wf-diagram-scroll{overflow-x:auto; margin:0 -32px 28px; padding:0 32px; -webkit-overflow-scrolling:touch;}
.wf-sketch-canvas{position:relative; width:2040px; height:650px; flex-shrink:0;}
/* Each diagram is a fixed pixel canvas with every node absolutely placed, so
   scaling the whole plate is the only way to fit one without redrawing all of
   its coordinates. The scale factor is measured per diagram at open — see the
   fit-to-width script on /ai — and applied here from the top left corner. */
.wf-diagram-scroll > *{transform-origin:top left;}
/* Once it fits there is nothing to scroll to and nothing to swipe for. */
.wf-diagram-scroll.is-fitted{overflow-x:hidden;}
.wf-diagram-scroll.is-fitted::before{content:none;}

/* Prose, not diagram: without a measure this runs the modal's full 1800px. */
.wf-modal--sketch .wf-modal__text{padding:0 24px; max-width:1000px;}

/* ---- Footer ---- */
footer{background:var(--navy); color:#fff; padding:64px 24px 32px; font-size:14.5px;}
.footer-grid{max-width:var(--maxw); margin:0 auto; display:grid; grid-template-columns:1.4fr 1fr 1fr 1fr; gap:32px;}
@media (max-width:750px){ .footer-grid{grid-template-columns:1fr 1fr;} }
footer h4{color:#fff; font-size:14px; text-transform:uppercase; letter-spacing:.06em; margin-bottom:14px; font-weight:600;}
footer ul{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:9px;}
footer a{color:var(--navy-25); text-decoration:none; font-size:14.5px;}
footer a:hover{color:#fff;}
/* The footer repeats the language switch; the current language is marked
   the same way the header marks it. */
.footer-bottom .active{color:#fff;}
.footer-bottom{
  max-width:var(--maxw); margin:40px auto 0; padding-top:24px; border-top:1px solid rgba(255,255,255,.15);
  display:flex; justify-content:space-between; flex-wrap:wrap; gap:12px; color:var(--navy-25); font-size:13.5px;
}

/* ============================================================
   MOBILE LAYER
   Everything below is phone/tablet only. With two deliberate
   exceptions (.nav-toggle's display:none default and the two
   min-width:0 overflow guards, all no-ops at desktop width) every
   rule lives inside a max-width media query, so the ≥901px desktop
   rendering is byte-for-byte what it was before.
   Breakpoints match the ones already used above: 900px (nav/header)
   and 640px (type scale, section rhythm).
   ============================================================ */

/* ---- Mobile navigation: hamburger + drawer ----
   Markup is injected by assets/mobile-nav.js from the existing
   header, so no page had to change. Hidden entirely on desktop. */
.nav-toggle{display:none;}
.mobile-nav{display:none;}

@media (max-width:900px){
  /* Header on phones: logo + hamburger only. nav.primary was already
     hidden here; .header-right (lang + CTA) moves into the drawer,
     which is what stopped the CTA overflowing/clipping off-screen. */
  .header-inner{padding:12px 20px; gap:12px; align-items:center;}
  .header-right{display:none;}
  /* three classes so this beats the page-level .logo-svg / .chrome-overlay
     .logo-svg overrides on hub, /ai and /retail-it */
  header .logo .logo-svg{height:62px;}
  /* on a phone-height screen every pixel the header takes is one the first
     screen doesn't get */
  @media (max-width:640px){
    header .logo .logo-svg{height:54px;}
    .header-inner{padding:10px 20px;}
  }
  .chrome-overlay.is-stuck .header-inner,
  header.is-stuck .header-inner{padding-top:8px; padding-bottom:8px;}
  [id]{scroll-margin-top:92px;}

  .nav-toggle{
    display:inline-flex; align-items:center; justify-content:center;
    width:46px; height:46px; margin-right:-8px; flex-shrink:0;
    padding:0; border:none; background:none; cursor:pointer;
    color:var(--navy); -webkit-tap-highlight-color:transparent;
  }
  .nav-toggle__bars{display:flex; flex-direction:column; justify-content:center; gap:5px; width:24px;}
  .nav-toggle__bars i{display:block; height:2px; border-radius:2px; background:currentColor;}
  /* over the dark photo/video heroes the header chrome is white — and
     so must the focus ring be, the navy default disappears there */
  .chrome-overlay .nav-toggle{color:#fff; filter:drop-shadow(0 1px 3px rgba(0,0,0,.5));}
  .chrome-overlay .nav-toggle:focus-visible{outline:2px solid #fff; outline-offset:0;}

  .mobile-nav{display:block; position:fixed; inset:0; z-index:1000;}
  .mobile-nav[hidden]{display:none;}
  .mobile-nav__scrim{
    position:absolute; inset:0; background:rgba(9,18,30,.5);
    opacity:0; transition:opacity .24s ease;
  }
  .mobile-nav.is-open .mobile-nav__scrim{opacity:1;}
  .mobile-nav__panel{
    position:absolute; top:0; right:0; bottom:0;
    width:min(340px, 88vw); background:#fff; box-shadow:-16px 0 44px rgba(9,18,30,.22);
    display:flex; flex-direction:column;
    padding:calc(12px + env(safe-area-inset-top)) calc(24px + env(safe-area-inset-right))
            calc(24px + env(safe-area-inset-bottom)) 24px;
    overflow-y:auto; -webkit-overflow-scrolling:touch;
    transform:translateX(100%); transition:transform .26s cubic-bezier(.22,.61,.36,1);
  }
  .mobile-nav.is-open .mobile-nav__panel{transform:translateX(0);}
  .mobile-nav__panel:focus{outline:none;}
  .mobile-nav__head{display:flex; justify-content:flex-end; margin-bottom:8px;}
  .mobile-nav__close{
    width:46px; height:46px; padding:0; border:none; background:none; cursor:pointer;
    color:var(--navy); font-size:20px; line-height:1; -webkit-tap-highlight-color:transparent;
  }
  .mobile-nav__links{list-style:none; margin:0; padding:0; display:flex; flex-direction:column;}
  .mobile-nav__links a{
    display:flex; align-items:center; min-height:52px; padding:4px 2px;
    font-size:18px; font-weight:500; color:var(--navy); text-decoration:none;
    border-bottom:1px solid var(--hairline);
  }
  .mobile-nav__links a.nav-active-home,
  .mobile-nav__links a.nav-active-team,
  .mobile-nav__links a.nav-active-news,
  .mobile-nav__links a.nav-active-contact,
  .mobile-nav__links a.nav-active-keynote{box-shadow:inset 3px 0 0 currentColor; padding-left:14px;}
  /* Dachmarke destinations use JJW navy as their current-page banner; amber
     and mint remain reserved for the two specialist areas below. */
  .mobile-nav__links > li:not(.mobile-nav__group) > a.is-current-page{
    padding-left:14px;
    background:var(--navy); border-bottom-color:transparent; color:#fff; font-weight:600;
  }
  /* Retail and AI keep their own rails all the time, not just while their
     landing pages are active. The rail belongs to the whole group so it flows
     continuously from its parent row through the indented links. */
  .mobile-nav__links > li.mobile-nav__group{position:relative;}
  .mobile-nav__links > li.mobile-nav__group::before{
    content:""; position:absolute; z-index:0; top:0; bottom:0; left:0; width:3px;
  }
  .mobile-nav__links > li.mobile-nav__group--retail::before{background:var(--amber);}
  .mobile-nav__links > li.mobile-nav__group--ai::before{background:var(--mint);}
  .mobile-nav__links > li.mobile-nav__group > a{padding-left:14px;}
  /* The parent row becomes the section banner on its own pages. This lets a
     reader identify Retail (orange) and AI (mint) at a glance in the drawer. */
  .mobile-nav__links > li.mobile-nav__group--retail.is-active-section > a{
    background:var(--amber); border-bottom-color:transparent; color:var(--navy); font-weight:600;
  }
  .mobile-nav__links > li.mobile-nav__group--ai.is-active-section > a{
    background:var(--mint); border-bottom-color:transparent; color:var(--navy); font-weight:600;
  }
  /* Spoke sub-pages, indented under their parent tab — the drawer's answer to
     the desktop dropdown. Hairline on the left instead of a rule under each
     row, so a group reads as one block rather than five equal tabs. */
  .mobile-nav__sublinks{
    list-style:none; margin:0 0 0 2px; padding:2px 0 8px 14px;
    display:flex; flex-direction:column; border-left:2px solid var(--silver-50);
  }
  .mobile-nav__sublinks--retail{
    border-left-color:transparent;
  }
  .mobile-nav__sublinks--ai{
    border-left-color:transparent;
  }
  .mobile-nav__sublinks a{
    min-height:44px; font-size:15.5px; font-weight:400;
    color:var(--navy-75); border-bottom:none;
    transition:background-color .15s ease, color .15s ease, margin-left .15s ease, padding-left .15s ease;
  }
  .mobile-nav__sublinks--retail a:hover,
  .mobile-nav__sublinks--retail a:focus,
  .mobile-nav__sublinks--retail a.is-current-page{
    color:var(--navy);
    font-weight:600;
    padding-left:4px;
  }
  .mobile-nav__sublinks--ai a:hover,
  .mobile-nav__sublinks--ai a:focus,
  .mobile-nav__sublinks--ai a.is-current-page{
    color:var(--navy);
    font-weight:600;
    padding-left:4px;
  }
  /* On a spoke page, colour the exact active destination rather than its
     parent category. Pull it back to the permanent rail so it reads as the
     full section banner while the remaining sublinks stay quietly nested. */
  .mobile-nav__sublinks--retail a.is-current-page{
    margin-left:-16px; padding-left:20px;
    background:var(--amber); color:var(--navy); font-weight:600;
  }
  .mobile-nav__sublinks--ai a.is-current-page{
    margin-left:-16px; padding-left:20px;
    background:var(--mint); color:var(--navy); font-weight:600;
  }
  .mobile-nav__sublinks--insights a:hover,
  .mobile-nav__sublinks--insights a:focus,
  .mobile-nav__sublinks--insights a.is-current-page{
    color:var(--navy);
    font-weight:600;
    padding-left:4px;
  }
  .mobile-nav__sublinks--insights a.is-current-page{
    margin-left:-16px; padding-left:20px;
    background:var(--navy); color:#fff; font-weight:600;
  }
  .mobile-nav__foot{margin-top:28px; display:flex; flex-direction:column; gap:20px;}
  .mobile-nav__cta{justify-content:center; min-height:50px; font-size:16.5px; text-align:center;}
  .mobile-nav__lang{gap:10px; font-size:14px;}
  .mobile-nav__lang span{min-height:32px; display:inline-flex; align-items:center;}
  @media (prefers-reduced-motion:reduce){
    .mobile-nav__scrim, .mobile-nav__panel{transition:none;}
  }

  /* scroll lock while the drawer is open (paired with body.style.top
     in mobile-nav.js, which preserves the scroll position) */
  html.has-mobile-nav, html.has-mobile-nav body{overflow:hidden;}
  html.has-mobile-nav body{position:fixed; width:100%;}
}

/* ---- Forms on phones ----
   .form-grid stayed two columns at every width, and the intrinsic
   min-content width of two side-by-side inputs (~500px) was forcing
   the whole /kontakt and /retail-it/pm-netzwerk pages to scroll
   sideways. One column plus min-width:0 removes the cause.
   The min-width:0 guards are scoped to ≤800px on purpose: the same
   intrinsic minimum is what gives the form column its width in the
   1.3fr/1fr desktop .contact-grid, and relaxing it there would move
   the desktop layout. */
@media (max-width:800px){
  .contact-grid > *{min-width:0;}
  .form-field{min-width:0;}
  .form-field input, .form-field textarea, .form-field select{min-width:0; max-width:100%;}
}
@media (max-width:640px){
  .form-grid{grid-template-columns:1fr;}
  /* iOS Safari zooms the viewport when focusing a field under 16px */
  .form-field input, .form-field textarea, .form-field select{font-size:16px;}
  .form-checkbox input{width:20px; height:20px;}
}

/* ---- Touch targets & phone spacing ----
   Footer links, ghost links and the banner close button were 19–30px
   tall — well under the 44px comfortable-tap minimum.
   Links that carry an underline (ghost-link, card-btn, keynote-back,
   keynote card links) must keep their rule tight against the text, so
   those grow an invisible 44px-tall ::after hit area instead of
   growing the box itself. Links without a rule just get min-height. */
@media (max-width:900px){
  .btn{min-height:44px;}
  footer ul{gap:2px;}
  /* padding as well as min-height: the two-line links ("JJW Retail IT
     Project Management") already exceed 44px, so without it they'd butt
     straight up against the next link */
  footer ul a{display:inline-flex; align-items:center; min-height:44px; padding:5px 0;}
  .footer-bottom{gap:8px 20px;}
  .contact-info a{display:inline-flex; align-items:center; min-height:32px;}
  .mf-level{font-size:12px;}

  .ghost-link,
  .card-btn,
  .keynote-header .keynote-back,
  .keynote-actions .ghost-light,
  .keynote-card a{position:relative;}
  .ghost-link::after,
  .card-btn::after,
  .keynote-header .keynote-back::after,
  .keynote-actions .ghost-light::after,
  .keynote-card a::after{
    content:""; position:absolute; left:0; right:0; top:50%;
    height:44px; transform:translateY(-50%);
  }
}
@media (max-width:640px){
  /* Safety net for long German compounds — "Datenschutzerklärung" is
     323px wide at the 32px mobile h1 and was pushing /datenschutz
     sideways on a 360px screen. break-word only engages when a word
     genuinely cannot fit, so headings that already fit are untouched.
     (hyphens:auto was tried and rejected: it re-wrapped 7 headings
     across the site to fix this one.) */
  h1, h2, h3, h4{overflow-wrap:break-word;}
  .wrap{padding:0 20px;}
  .section{padding:var(--jjw-section-gap-mobile) 20px;}
  .page-hero{padding:48px 20px 44px;}
  .page-hero .sub{font-size:16.5px;}
  .cta-row{gap:14px; margin-top:26px;}
  .section-head{margin-bottom:30px;}
  .section-head p{font-size:16px;}
  footer{padding:48px 20px 28px;}
  .footer-grid{gap:24px;}
}
/* ---- Mobile button structure & CTA arrow hiding (phone view only) ---- */
@media (max-width:700px){
  .cta-arrow,
  .btn-arrow,
  .btn__arrow,
  .pf-btn__arrow{
    display:none !important;
  }
}
@media (max-width:640px){
  .cta-row{flex-direction:column; align-items:stretch; gap:14px;}
  .cta-row .btn{
    width:100%;
    justify-content:center;
    text-align:center;
    text-wrap:balance;
    box-sizing:border-box;
  }
  /* the ghost link keeps its intrinsic width and centers symmetrically below */
  .cta-row .ghost-link{
    align-self:center;
    justify-content:center;
    text-align:center;
  }
  .btn{
    text-align:center;
    justify-content:center;
  }
}

/* ---- Mobile rhythm: give the text its width back ----
   Measured on a 390px screen: prose was averaging 30 characters per
   line, with 90% of blocks under 40. The comfortable band is 45-75, and
   at ~30 the copy reads as a narrow ragged ribbon.

   The cause was nested gutters, not type size. Every page is
   <section class="section"><div class="wrap">, and BOTH carry 20px of
   horizontal padding — 80px of a 390px screen gone before any card.
   Card padding then took another 56-64px, leaving ~246px for text.
   On desktop none of this shows: .wrap is a centred 1200px box, so its
   padding only engages below 1248px.

   Below: one gutter instead of two, and inner padding on cards and
   panels scaled for a phone rather than inherited from the desktop
   composition. */
@media (max-width:640px){
  .wrap{padding-left:20px; padding-right:20px;}

  /* German prose on a narrow column wraps raggedly — "Standortbestimmung",
     "Projektführung", "Transformationsprojekten" don't fit the leftover
     space, so lines break early and the rag is deep. Hyphenation is the
     normal fix for German setting and fills the measure properly.
     Body copy only: the same property was tried on headings and rejected,
     because it re-wrapped display type that was already fine. */
  p, li, dd, td, .faq-answer, .module-summary, .solution-desc{hyphens:auto;}
  /* never break these — hyphenating a brand or an address reads as a typo */
  .logo, .kicker, .btn, .status-tag, .module-step, h1, h2, h3, h4{hyphens:manual;}

  .card{padding:26px 22px;}
  .card .card-btn{padding-top:24px;}
  .pillar-col__shaft{padding:22px 18px 26px;}
  .faq-item summary{padding:18px;}
  .faq-item .faq-answer{padding:0 18px 20px;}
  .callout{padding:20px 18px;}
  .contact-info{padding:22px 20px;}
  .checklist{gap:12px;}

  /* stacked steps are a column now, so the 150px desktop width and its
     side padding only squeeze the label */
  .process-step{width:100%; max-width:none; padding:0;}

  /* the footer's brand blurb was 161px wide in a two-column grid —
     19 characters a line. Span it, and let the link lists pair up. */
  .footer-grid > *:first-child{grid-column:1 / -1;}

  /* Three-column comparison table: at 390px it stayed 578px wide and
     scrolled sideways inside .table-scroll, with 188px cells. Stack each
     row into a card instead and carry the column heading down as a label
     (from data-label on each <td>), so every cell gets the full width. */
  .info-table thead{position:absolute; width:1px; height:1px; overflow:hidden; clip-path:inset(50%);}
  .info-table, .info-table tbody, .info-table tr, .info-table td{display:block; width:100%;}
  .info-table tr{
    margin-bottom:16px; border:1px solid var(--hairline);
    border-top:3px solid var(--navy); border-radius:var(--jjw-radius-card);
    overflow:hidden; background:#fff;
  }
  .info-table tr:last-child{margin-bottom:0;}
  .info-table{font-size:16px;}
  .info-table td{padding:14px 18px; border-bottom:1px solid var(--hairline);}
  .info-table tr td:last-child{border-bottom:none;}
  .info-table tr:nth-child(even) td{background:transparent;}
  .info-table td[data-label]::before{
    content:attr(data-label); display:block; margin-bottom:5px;
    font-size:11.5px; font-weight:700; letter-spacing:.07em; text-transform:uppercase;
    color:var(--navy-75);
  }
  /* first cell is the row's subject — treat it as the card's title */
  .info-table td:first-child{
    background:var(--light-grey); font-size:17px; color:var(--navy); white-space:normal;
  }
  .table-scroll{overflow-x:visible;}
}

/* ---- Mobile type scale ----
   Running prose was set at 13.5 / 14.5 / 15 / 15.5 / 16 / 16.5 / 17 /
   18 / 19px across the pages — nine sizes doing one job, because each
   section was tuned against the desktop composition it sits in. At
   1200px those half-point steps read as texture; at 390px they just
   read as inconsistency.

   Three roles on a phone, and nothing else:
     lead  17px  — hero sublines and section intros
     body  16px  — all running copy
     small 14px  — notes, captions, meta
   Headings collapse onto the token scale (h3 = 20px), so an h3 stops
   colliding with the 24px mobile h2.

   Chrome keeps its own sizes on purpose — buttons, kickers, nav, table
   headers, price labels are sized for their function, not for reading.

   The `body ` prefix on some selectors is only there to outrank the
   page-level <style> blocks, which load after this file. */
@media (max-width:640px){
  /* --- prose to 16px --- */
  .card p,
  .checklist li,
  .callout,
  .faq-item .faq-answer,
  .pillar-col__items li,
  .team-row .row-desc,
  .module-summary,
  .solution-row .solution-desc,
  body .trust p,
  body .benefit p,
  body .mf-node p,
  body .credential-row__body p,
  body .solutions-showcase .solution-desc,
  body .tool-landscape__copy > p{font-size:16px;}

  /* --- section leads to 17px --- */
  .page-hero .sub,
  body .page-hero .sub,
  body .keynote-hero .lead,
  body .keynote-intro p,
  body .keynote-final p,
  body .custom-code__copy p,
  body .custom-workflow__copy p,
  body .photo-panel__copy p{font-size:17px;}

  /* --- small print to 14px --- */
  .form-note,
  body .bw__step p,
  body .bw__sub-list{font-size:14px;}

  /* --- headings onto the token scale --- */
  .card h3,
  .module-group-head h3,
  body .pillar-col__name,
  body .keynote-card h3,
  body .process-grid .process-step h3{font-size:20px;}
}

/* ---- Wide diagrams ----
   The hand-drawn process canvases are 2040px wide, so on a phone only
   about a sixth is on screen at a time. They already live in an
   overflow-x:auto scroller (so they never widen the page) — what's
   missing on touch is the scrollbar that tells you so. Hence the hint;
   pinch-zoom handles the rest, which is why no page sets
   user-scalable=no. */
@media (max-width:900px){
  .wf-modal__inner{padding:32px 22px 28px;}
  .wf-modal--sketch .wf-modal__inner{padding:24px 18px 28px;}
  .wf-sketch-head{padding:0 4px 18px;}
  .wf-modal--sketch .wf-modal__text{padding:0 4px;}
  .wf-diagram-scroll{margin:0 -18px 22px; padding:0 18px;}
  .wf-diagram-scroll::before{
    content:"Seitlich wischen, um das ganze Diagramm zu sehen →";
    display:block; position:sticky; left:0; margin-bottom:10px;
    font-size:12.5px; font-weight:600; letter-spacing:.02em; color:#6E6A62;
  }
}

/* ---- Lightweight content reveal ---- */
.reveal-on-scroll{
  opacity:0;
  transform:translateY(16px);
  transition:opacity .55s ease, transform .55s cubic-bezier(.22,.61,.36,1);
  transition-delay:var(--reveal-delay, 0ms);
  will-change:opacity, transform;
}
/* Release the layer once the reveal has played. Held permanently this kept up
   to 31 elements promoted on /retail-it for the life of the page, long after
   the one transition they were promoted for had finished. */
.reveal-on-scroll.is-revealed{opacity:1; transform:translateY(0); will-change:auto;}
@media (prefers-reduced-motion:reduce){
  .reveal-on-scroll{opacity:1; transform:none; transition:none;}
}

/* ---- Unified FAQ Hub (Tabs & Views) ---- */
.faq-category-switcher{
  display:flex; gap:16px; align-items:center; margin-top:24px; flex-wrap:wrap;
}
.faq-cat-btn{
  display:inline-flex; align-items:center; justify-content:center;
  min-width:130px; height:44px; padding:0 30px;
  font-family:var(--font-heading, inherit);
  font-size:16px; font-weight:600;
  border-radius:8px;
  cursor:pointer; transition:all .2s cubic-bezier(.16, 1, .3, 1);
  background:#fff;
}
.faq-cat-btn[data-tab="retail"]{
  border:2px solid var(--amber); color:var(--navy);
}
.faq-cat-btn[data-tab="retail"]:hover{
  background:#fffaf3;
}
.faq-cat-btn[data-tab="retail"].is-active{
  background:linear-gradient(180deg, #fff 0%, #fff6ea 100%);
  border-color:var(--amber);
  color:#09121e;
  font-weight:700;
  box-shadow:0 4px 16px rgba(255,153,50,.35), inset 0 0 0 1px var(--amber);
}
.faq-cat-btn[data-tab="ai"]{
  border:2px solid var(--mint); color:var(--navy);
}
.faq-cat-btn[data-tab="ai"]:hover{
  background:#f2fcf7;
}
.faq-cat-btn[data-tab="ai"].is-active{
  background:linear-gradient(180deg, #fff 0%, #ebfaf3 100%);
  border-color:var(--mint);
  color:#09121e;
  font-weight:700;
  box-shadow:0 4px 16px rgba(62,247,174,.42), inset 0 0 0 1px var(--mint);
}
.faq-panel{display:none;}
.faq-panel.is-active{display:block;}

/* ---- Solutions & Support Card enhancements ---- */
.support-section{background:var(--light-grey); border-block:1px solid var(--hairline);}
.support-cards{display:grid; grid-template-columns:repeat(3, 1fr); gap:24px; margin-top:40px;}
@media (max-width:960px){.support-cards{grid-template-columns:1fr;}}
/* Photo panel split with real image */
.photo-panel--split .photo-panel__panel > img {
  position: relative !important;
  top: auto !important;
  right: auto !important;
  bottom: auto !important;
  left: auto !important;
  width: 100% !important;
  height: auto !important;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--jjw-radius-card);
  box-shadow: var(--jjw-shadow-card);
  display: block;
}

.photo-panel--split.photo-panel--flip .photo-panel__panel > img,
.photo-panel--flip.photo-panel--split .photo-panel__panel > img {
  order: 1;
}

.photo-panel--split.photo-panel--flip .photo-panel__copy,
.photo-panel--flip.photo-panel--split .photo-panel__copy {
  order: 2;
  margin: 0;
}

@media (max-width: 900px) {
  .photo-panel--split .photo-panel__panel > img {
    aspect-ratio: 16 / 10;
  }
}

/* ---- Mobile footer hierarchy ----
   A four-column desktop footer needs deliberate grouping once it becomes a
   two-column phone layout. Give the brand, navigation groups and contact
   details their own rhythm instead of letting them read as one long list. */
@media (max-width:750px){
  footer{
    padding:44px 20px 26px;
    background:linear-gradient(135deg, var(--navy) 0%, #172f4f 100%);
  }
  .footer-grid{
    grid-template-columns:minmax(0, 1fr) minmax(0, 1fr);
    column-gap:28px;
    row-gap:0;
  }
  .footer-grid > *{min-width:0;}
  .footer-grid > *:first-child{
    grid-column:1 / -1;
    padding:0 0 26px;
    border-bottom:1px solid rgba(255,255,255,.18);
  }
  .footer-grid > *:first-child h4{
    margin-bottom:9px;
    font-size:16px;
    letter-spacing:.04em;
  }
  .footer-grid > *:first-child p{
    max-width:480px !important;
    font-size:15px;
    line-height:1.6;
    hyphens:manual;
  }
  .footer-grid > *:first-child p span{display:block; margin-top:7px;}
  .footer-grid > :nth-child(2),
  .footer-grid > :nth-child(3){padding:26px 0 24px;}
  footer ul{gap:0;}
  footer ul a{
    min-height:42px;
    padding:6px 0;
    font-size:14px;
    line-height:1.4;
  }
  .footer-grid > .footer-contact{
    grid-column:1 / -1;
    margin-top:0;
    padding-top:27px;
    border-top:1px solid rgba(255,255,255,.18);
  }
  .footer-contact h4{margin-bottom:9px;}
  .footer-contact ul{gap:5px;}
  .footer-contact li{font-size:14px; line-height:1.6;}
  .footer-contact li:not(:first-child){min-height:42px;}
  .footer-bottom{
    flex-direction:column;
    align-items:flex-start;
    gap:14px;
    margin-top:30px;
    padding-top:22px;
    line-height:1.65;
  }
  .footer-bottom > span:last-child{
    order:-1;
    font-size:12px;
    font-weight:600;
    letter-spacing:.08em;
  }
}
