1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 5 <meta charset="utf-8" /> 6 <meta name="color-scheme" content="dark light"> 7 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 8 <title>Publications | Alphadi</title> 9 <meta name="description" content="Lean Six Sigma, Operational Excellence und Qualitätsmanagement: Alphadi bietet Weiterbildung, Zertifizierung, Coaching, Beratung und AlphadiTab Software für Verbesserungsprojekte." /> 10 <meta name="og:title" content="Publications | Alphadi" /> 11 <meta name="og:description" content="Lean Six Sigma, Operational Excellence und Qualitätsmanagement: Alphadi bietet Weiterbildung, Zertifizierung, Coaching, Beratung und AlphadiTab Software für Verbesserungsprojekte." /> 12 <meta name="og:type" content="website" /> 13 <meta name="og:locale" content="en" /> 14 15 <link rel="icon" href="/img/favicon.ico" sizes="any"> 16 <link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png"> 17 18 <link rel="preconnect" href="https://fonts.googleapis.com"> 19 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 20 <link rel="stylesheet" href="/bundles/hp-styles.css?v=_0Jinmn5XM4Jg2spIz_GA6SmJGHyq_C09ckEcirX2Nk" /> 21 <link rel="stylesheet" href="/lib/katex/katex.min.css?v=7NQzvryVCIQkViOS3GPdLDyHtm1nHMrm7xzxO09F158" /> 22 <style> 23 /* Mobile nav sheet: ALL top-level items look identical, whether or not they have sub-levels. 24 The plain links (Home, Events, â¦) are adjusted to match the dropdown group-triggers 25 (Akademie, Consulting, â¦) â uppercase section-header style. Inline so it always wins 26 over the prebuilt hp-styles bundle (which the browser may cache). */ 27 .nav__sheet-link, 28 .nav__sheet-group-trigger { 29 font-family: var(--f-ui); 30 font-size: 0.72rem; 31 font-weight: 700; 32 letter-spacing: 0.5px; /* matches desktop, reduced from the old 0.12em */ 33 text-transform: uppercase; 34 color: var(--c-subtle); 35 } 36 .nav__sheet-link { border-left: none; } 37 .nav__sheet-link:hover, 38 .nav__sheet-link.is-active { color: var(--c-dark); background: none; } 39 /* "Request a date" inquiry link (training/event booking box). It's a bare <button>, so with 40 color-scheme:dark light the browser paints its text white in OS dark mode and it vanishes. 41 Force it orange in every mode/device. Inline so it wins over the cached hp-styles bundle. */ 42 .btn-link-inline { 43 background: none; 44 border: none; 45 padding: 0; 46 font: inherit; 47 color: var(--c-orange) !important; 48 font-weight: 600; 49 text-decoration: underline; 50 cursor: pointer; 51 } 52 .btn-link-inline:hover { color: var(--c-orange) !important; opacity: 0.8; } 53 /* Per-date "By invoice" inquiry toggle in the training/event booking box. Clicking 54 "By invoice" expands an inline note whose "Inquire here" link opens the request 55 modal. Inline so it wins over the cached hp-styles bundle (which dotnet build 56 does not regenerate). */ 57 .date-item--two-row { flex-direction: column; align-items: stretch; gap: 0; } 58 .date-item--two-row .date-item__top { 59 display: flex; align-items: center; justify-content: space-between; 60 gap: 1rem; flex-wrap: wrap; width: 100%; 61 } 62 .date-item__actions { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; } 63 .date-invoice-body { 64 flex-basis: 100%; 65 display: grid; grid-template-rows: 0fr; 66 transition: grid-template-rows 0.25s ease; 67 } 68 .date-item.is-open .date-invoice-body { grid-template-rows: 1fr; } 69 .date-invoice-content { overflow: hidden; } 70 .date-invoice-content p { 71 font-family: var(--f-ui); font-size: 0.8rem; color: var(--c-dark); line-height: 1.6; 72 margin: 0.75rem 0 0; padding-top: 0.75rem; border-top: 1px solid var(--c-border); 73 } 74 .link-btn { 75 background: none; border: none; padding: 0; margin: 0; font: inherit; 76 color: var(--c-orange) !important; text-decoration: underline; cursor: pointer; 77 } 78 .link-btn:hover { opacity: 0.8; } 79 /* Two-row date item: date + action buttons on top, location on its own row below, so the 80 buttons always have room even with a long location. Inline so it wins over the cached 81 hp-styles bundle (which dotnet build does not regenerate). */ 82 .date-item--two-row { flex-direction: column; align-items: stretch; gap: 0; } 83 .date-item--two-row .date-item__top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; width: 100%; } 84 .date-item--two-row .date-item__loc { margin-top: 0.25rem; } 85 :root { 86 color-scheme: dark light; 87} 88 /* Logo strip is dark so the WHITE logo stays visible in light AND force-dark mode. 89 The white logo has a declared filter (filter:none) so browser force-dark won't re-invert it. */ 90 .account-menu { position: relative; display: flex; align-items: center; } 91 .account-menu__chevron { flex-shrink: 0; transition: transform var(--t-base); } 92 .account-menu.is-open .account-menu__chevron { transform: rotate(180deg); } 93 .account-menu__dropdown { 94 position: absolute; top: calc(100% + 0.75rem); right: 0; 95 background: var(--c-white); border: 1px solid var(--c-border); 96 border-radius: 6px; padding: 0.5rem; width: 300px; 97 box-shadow: 0 8px 24px rgba(0,0,0,.12); 98 opacity: 0; pointer-events: none; transform: translateY(-4px); 99 transition: opacity 0.18s ease, transform 0.18s ease; z-index: 1100; 100 } 101 .account-menu__dropdown::before { 102 content: ''; position: absolute; top: -5px; right: 13px; 103 width: 9px; height: 9px; background: #fff; 104 border-top: 1px solid var(--c-border); border-left: 1px solid var(--c-border); 105 border-radius: 2px 0 0 0; transform: rotate(45deg); 106 } 107 .account-menu.is-open .account-menu__dropdown { opacity: 1; pointer-events: all; transform: translateY(0); } 108 .account-menu__body { display: flex; flex-direction: column; gap: 1rem; padding: 0.5rem 0.5rem 0.75rem; } 109 .account-menu__lead { display: flex; align-items: center; gap: 0.75rem; font-family: var(--f-ui), sans-serif; font-size: 1rem; line-height: 1.5; color: var(--c-dark); margin: 0; } 110 .account-menu__lead-icon { color: var(--c-orange); flex: 1 1 25%; min-width: 0; display: flex; justify-content: center; } 111 .account-menu__lead-text { flex: 3 3 75%; min-width: 0; } 112 .account-menu__actions { display: flex; flex-direction: column; gap: 0.5rem; } 113 .account-menu__actions .btn { width: 100%; justify-content: center; } 114 .nav__sheet-account { display: flex; flex-direction: column; gap: 0.5rem; padding: 0.5rem 0 0.375rem; } 115 .nav__sheet-account-lead { font-family: var(--f-ui), sans-serif; font-size: 0.9rem; line-height: 1.5; color: var(--c-subtle); margin: 0 0 0.25rem; } 116 .nav__sheet-account .btn { width: 100%; justify-content: center; } 117 </style> 118
118<script src="/bundles/hp-plugins.min.js"></script>
118 119 120 121 122 <style>#training-modules { 123background-color: #efefef; 124} 125 126section[class*="hero-padded"] { 127 padding-top: 114px; 128} 129.hero { 130 position: relative; background: var(--c-bg-warm); overflow: hidden; 131 padding-bottom: 4rem; 132} 133 134section[class*="sa-hero"] { 135 padding-top: 190px; 136} 137 138 139:root { 140 color-scheme: light only; 141} 142 143@media (prefers-color-scheme: dark) { 144 :root { 145 color-scheme: light only; 146 } 147} 148 149.sa-freetext-wrap textarea { 150 151 color: #555555 !important; 152 153} 154#cartPageContent::after { 155 content: ""; 156 display: block; 157 width: 100%; 158 max-width: 420px; 159 aspect-ratio: 3 / 4; 160 margin: 3rem auto 0; 161 background: url("https://www.alphadi.org/image/1705") center / contain no-repeat; 162} 163 164html[lang="en"] #cartPageContent::after { background-image: url("https://www.alphadi.org/image/1706"); } 165html[lang="es"] #cartPageContent::after { background-image: url("https://www.alphadi.org/image/1707"); } 166html[lang="fr"] #cartPageContent::after { background-image: url("https://www.alphadi.org/image/1708"); } 167html[lang="it"] #cartPageContent::after { background-image: url("https://www.alphadi.org/image/1709"); } 168html[lang="pl"] #cartPageContent::after { background-image: url("https://www.alphadi.org/image/1710"); } 169html[lang="pt"] #cartPageContent::after { background-image: url("https://www.alphadi.org/image/1711"); }</style> 170</head> 171 172<body class=""> 173 <!-- Floating alerts --> 174 175 <!-- âââââââ NAVIGATION âââââââ --> 176 <nav class="nav nav--white nav--two-row" id="mainNav"> 177 <!-- Row 1: topbar (desktop only) --> 178 <div class="nav__row--top-wrap"> 179 <div class="nav__row--top"> 180 <div class="nav__row--top-right"> 181 <div class="lang-switch" id="topbarLangSwitch"> 182 <button class="lang-switch__btn" type="button" aria-haspopup="true"> 183 EN 184 <svg viewBox="0 0 10 6" fill="none" stroke="currentColor"> 185 <path d="M1 1L5 5L9 1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 186 </svg> 187 </button> 188 <div class="lang-switch__dropdown"> 189 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 190 <button type="submit" name="culture" value="de-DE" 191 class="lang-switch__opt "> 192 DE â German 193 </button> 194 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 195 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 196 <button type="submit" name="culture" value="en-US" 197 class="lang-switch__opt is-active"> 198 EN â English 199 </button> 200 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 201 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 202 <button type="submit" name="culture" value="es-ES" 203 class="lang-switch__opt "> 204 ES â Spanish 205 </button> 206 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 207 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 208 <button type="submit" name="culture" value="it-IT" 209 class="lang-switch__opt "> 210 IT â Italian 211 </button> 212 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 213 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 214 <button type="submit" name="culture" value="fr-FR" 215 class="lang-switch__opt "> 216 FR â French 217 </button> 218 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 219 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 220 <button type="submit" name="culture" value="pl-PL" 221 class="lang-switch__opt "> 222 PL â Polish 223 </button> 224 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 225 <form method="post" style="margin:0;padding:0;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 226 <button type="submit" name="culture" value="pt-PT"
227 class="lang-switch__opt "> 228 PT â Portuguese 229 </button> 230 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 231 </div> 232 </div> 233 234 <div class="account-menu" id="accountMenu"> 235 <button class="nav__login-btn" id="accountMenuBtn" type="button" aria-haspopup="true" aria-expanded="false" aria-label="Account"> 236 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg> 237 Account 238 <svg class="account-menu__chevron" width="10" height="10" viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg> 239 </button> 240 <div class="account-menu__dropdown"> 241 <div class="account-menu__body"> 242 <div class="account-menu__lead"> 243 <div class="account-menu__lead-icon"> 244 <svg width="42" height="42" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg> 245 </div> 246 <div class="account-menu__lead-text">Log in into your shop account or create a new one.</div> 247 </div> 248 <div class="account-menu__actions"> 249 <a class="btn btn--primary" href="/Internal/Account/Login?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 250 Login 251 </a> 252 <a class="btn btn--outline" href="/Internal/Account/Register?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 253 Create account 254 </a> 255 </div> 256 </div> 257 </div> 258 </div> 259 260 <button class="cart-btn" id="cartNavBtn" aria-label="Cart"> 261 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z" /><line x1="3" y1="6" x2="21" y2="6" /><path d="M16 10a4 4 0 01-8 0" /></svg> 262 <span class="cart-badge">0</span> 263 </button> 264 </div> 265 </div> 266 </div> 267 268 <!-- Row 2: main nav bar --> 269 <div class="nav__inner"> 270 <a class="nav__logo" style="flex-shrink:0;" href="/en"> 271 <img src="/img/logo_f.svg" alt="Alphadi" /> 272 </a> 273 274 <button class="nav__toggle" id="sheetToggle" aria-label="Menu"> 275 <svg class="menu-icon" viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" width="22" height="22"> 276 <path class="menu-icon__morph" d="M27 10 13 10C10.8 10 9 8.2 9 6 9 3.5 10.8 2 13 2 15.2 2 17 3.8 17 6L17 26C17 28.2 18.8 30 21 30 23.2 30 25 28.2 25 26 25 23.8 23.2 22 21 22L7 22"/> 277 <path d="M7 16 27 16"/> 278 </svg> 279 </button> 280 281 <div class="nav__menu"> 282 <div class="nav__item nav__link "> 283 <button class="nav__dropdown-trigger"> 284 Academy 285 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 286 </button> 287 288 <div class="nav__dropdown"> 289 <a href="/en/workshops" class="nav__dropdown-item "> 290 <div class="nav__dropdown-icon"> 291 <img src="/image/1164" alt="" width="25" height="25" style="object-fit:contain;"> 292 </div> 293 <div> 294 <div class="nav__dropdown-text-title">Further training & seminars</div> 295 <div class="nav__dropdown-text-desc"><p>Internationally certified – with access to the Excellence Program.</p> 296</div> 297 </div> 298 </a> 299 <a href="/en/excellence-program" class="nav__dropdown-item "> 300 <div class="nav__dropdown-icon"> 301 <img src="/image/1180" alt="" width="25" height="25" style="object-fit:contain;"> 302 </div> 303 <div> 304 <div class="nav__dropdown-text-title">Excellence Program</div> 305 <div class="nav__dropdown-text-desc"><p>Internationally recognized certifications for professionals and executives</p> 306</div> 307 </div> 308 </a> 309 <a href="/en/coaching" class="nav__dropdown-item "> 310 <div class="nav__dropdown-icon"> 311 <img src="/image/1167" alt="" width="25" height="25" style="object-fit:contain;"> 312 </div> 313 <div> 314 <div class="nav__dropdown-text-title">Coaching & Consulting</div> 315 <div class="nav__dropdown-text-desc"><p>Individual support for companies and executives – on demand</p> 316</div> 317 </div> 318 </a> 319 <a href="/en/shingo-model" class="nav__dropdown-item "> 320 <div class="nav__dropdown-icon"> 321 <img src="/image/1178" alt="" width="25" height="25" style="object-fit:contain;"> 322 </div> 323 <div> 324 <div class="nav__dropdown-text-title">Shingo Model™</div> 325 <div class="nav__dropdown-text-desc"><p>Systemically develop operational excellence — with culture, behavior, and leadership as the foundation.</p> 326</div> 327 </div> 328 </a> 329 </div> 330 </div> 331 <a href="/en/events" class="nav__link ">Events</a> 332 <div class="nav__item nav__link "> 333 <button class="nav__dropdown-trigger"> 334 Consulting 335 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 336 </button> 337 338 <div class="nav__dropdown"> 339 <a href="/en/benchmarking" class="nav__dropdown-item "> 340 <div class="nav__dropdown-icon"> 341 <img src="/image/1165" alt="" width="25" height="25" style="object-fit:contain;"> 342 </div> 343 <div> 344 <div class="nav__dropdown-text-title">Benchmarking</div> 345 <div class="nav__dropdown-text-desc"><p>Identify potential improvements in processes, structures, and collaboration.</p> 346</div> 347 </div> 348 </a> 349 <a href="/en/culture-development-system-explained" class="nav__dropdown-item "> 350 <div class="nav__dropdown-icon"> 351 <img src="/image/1713" alt="" width="25" height="25" style="object-fit:contain;"> 352 </div> 353 <div> 354 <div class="nav__dropdown-text-title">What is the Culture Development System?</div> 355 <div class="nav__dropdown-text-desc"><p>Develop culture purposefully</p> 356</div> 357 </div> 358 </a> 359 <a href="/en/excellence-community" class="nav__dropdown-item "> 360 <div class="nav__dropdown-icon"> 361 <img src="/image/1181" alt="" width="25" height="25" style="object-fit:contain;"> 362 </div> 363 <div> 364 <div class="nav__dropdown-text-title">Excellence Community</div> 365 <div class="nav__dropdown-text-desc"><p>Network, refresh knowledge, and exchange best practices.</p> 366</div> 367 </div> 368 </a> 369 <a href="/en/talent-development" class="nav__dropdown-item "> 370 <div class="nav__dropdown-icon"> 371 <img src="/image/1173" alt="" width="25" height="25" style="object-fit:contain;"> 372 </div> 373 <div> 374 <div class="nav__dropdown-text-title">Talent development</div> 375 <div class="nav__dropdown-text-desc"><p>Strengthen employees in a targeted manner – for performance, change, and competitiveness.</p> 376</div> 377 </div> 378 </a> 379 <a href="/en/opex-roll-out" class="nav__dropdown-item "> 380 <div class="nav__dropdown-icon"> 381 <img src="/image/1170" alt="" width="25" height="25" style="object-fit:contain;"> 382 </div> 383 <div> 384 <div class="nav__dropdown-text-title">OPEX Roll-out</div> 385 <div class="nav__dropdown-text-desc"><p>Effectively roll out OPEX – for less waste and more sustainable impact.</p> 386</div> 387 </div> 388 </a> 389 </div> 390 </div> 391 <div class="nav__item nav__link is-active"> 392 <button class="nav__dropdown-trigger"> 393 Products 394 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 395 </button> 396 397 <div class="nav__dropdown"> 398 <a href="/en/products/books" class="nav__dropdown-item is-active"> 399 <div class="nav__dropdown-icon"> 400 <img src="/image/1166" alt="" width="25" height="25" style="object-fit:contain;"> 401 </div> 402 <div> 403 <div class="nav__dropdown-text-title">Publications</div> 404 <div class="nav__dropdown-text-desc"><p>Books, case studies, and booklets for process managers and organizations.</p> 405</div> 406 </div> 407 </a> 408 <a href="/en/products/tools-templates" class="nav__dropdown-item "> 409 <div class="nav__dropdown-icon"> 410 <img src="/image/1184" alt="" width="25" height="25" style="object-fit:contain;"> 411 </div> 412 <div> 413 <div class="nav__dropdown-text-title">Tools</div> 414 <div class="nav__dropdown-text-desc"><p>Handouts, plots, and presentations for Lean & LSS — ready to use.</p> 415</div> 416 </div> 417 </a> 418 <a href="/en/products/workshops" class="nav__dropdown-item "> 419 <div class="nav__dropdown-icon"> 420 <img src="/image/1293" alt="" width="25" height="25" style="object-fit:contain;"> 421 </div> 422 <div> 423 <div class="nav__dropdown-text-title">Workshops</div> 424 <div class="nav__dropdown-text-desc"><p>Interactive formats for targeted awareness and knowledge transfer – compact and practical.</p> 425</div> 426 </div> 427 </a> 428 </div> 429 </div> 430 <div class="nav__item nav__link "> 431 <button class="nav__dropdown-trigger">
432 Software 433 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 434 </button> 435 436 <div class="nav__dropdown"> 437 <a href="/en/support" class="nav__dropdown-item "> 438 <div class="nav__dropdown-icon"> 439 <img src="/image/1172" alt="" width="25" height="25" style="object-fit:contain;"> 440 </div> 441 <div> 442 <div class="nav__dropdown-text-title">Support</div> 443 <div class="nav__dropdown-text-desc"><p>Everything about documentation, help, and support for our software solutions</p> 444</div> 445 </div> 446 </a> 447 <a href="/en/alphadi-tab" class="nav__dropdown-item "> 448 <div class="nav__dropdown-icon"> 449 <img src="/image/1169" alt="" width="25" height="25" style="object-fit:contain;"> 450 </div> 451 <div> 452 <div class="nav__dropdown-text-title">AlphadiTab</div> 453 <div class="nav__dropdown-text-desc"><p>Project management software for problem solving</p> 454</div> 455 </div> 456 </a> 457 </div> 458 </div> 459 <div class="nav__item nav__link "> 460 <button class="nav__dropdown-trigger"> 461 About us 462 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 463 </button> 464 465 <div class="nav__dropdown"> 466 <a href="/en/career" class="nav__dropdown-item "> 467 <div class="nav__dropdown-icon"> 468 <img src="/image/1416" alt="" width="25" height="25" style="object-fit:contain;"> 469 </div> 470 <div> 471 <div class="nav__dropdown-text-title">Career </div> 472 <div class="nav__dropdown-text-desc"><p>Open positions at Alphadi – flat hierarchies, real responsibility, and room for professional development.</p> 473</div> 474 </div> 475 </a> 476 <a href="/en/ueber-uns" class="nav__dropdown-item "> 477 <div class="nav__dropdown-icon"> 478 <img src="/image/1182" alt="" width="25" height="25" style="object-fit:contain;"> 479 </div> 480 <div> 481 <div class="nav__dropdown-text-title">Meet the Team</div> 482 <div class="nav__dropdown-text-desc"><p>Get to know the people who shape Alphadi with heart and experience.</p> 483</div> 484 </div> 485 </a> 486 <a href="/en/glossary" class="nav__dropdown-item "> 487 <div class="nav__dropdown-icon"> 488 <img src="/image/216" alt="" width="25" height="25" style="object-fit:contain;"> 489 </div> 490 <div> 491 <div class="nav__dropdown-text-title">Glossary</div> 492 <div class="nav__dropdown-text-desc"><p>Terms, definitions and important technical terms explained at a glance.</p> 493</div> 494 </div> 495 </a> 496 </div> 497 </div> 498 499 500 </div> 501 502 <a href="/en/contact" class="nav__cta nav__cta--desktop">Contact</a> 503 </div> 504 </nav> 505 506 <!-- Backdrop --> 507 <div class="nav__sheet-overlay" id="sheetOverlay"></div> 508 509 <!-- Right-side nav sheet --> 510 <div class="nav__sheet" id="navSheet"> 511 <div class="nav__sheet-header"> 512 <div class="nav__sheet-logo"> 513 <a href="/en"> 514 <img src="/img/logo_f.svg" alt="Alphadi" style="height:35px;width:auto;" /> 515 </a> 516 </div> 517 <button class="nav__sheet-close" id="sheetClose" aria-label="Close menu"> 518 <svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"> 519 <path d="M1 1l12 12M13 1L1 13"/> 520 </svg> 521 </button> 522 </div> 523 524 <div class="nav__sheet-body"> 525 526 <a class="nav__sheet-link " href="/en">Home</a> 527 528 <button class="nav__sheet-group-trigger" type="button">
529 <span>Academy</span> 530 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 531 </button> 532 <div class="nav__sheet-sub"> 533 <a href="/en/workshops" class="nav__sheet-sub-item"> 534 <div class="nav__sheet-sub-icon"> 535 <img src="/image/1164" alt="" width="20" height="20" style="object-fit:contain;"> 536 </div> 537 Further training & seminars 538 </a> 539 <a href="/en/excellence-program" class="nav__sheet-sub-item"> 540 <div class="nav__sheet-sub-icon"> 541 <img src="/image/1180" alt="" width="20" height="20" style="object-fit:contain;"> 542 </div> 543 Excellence Program 544 </a> 545 <a href="/en/coaching" class="nav__sheet-sub-item"> 546 <div class="nav__sheet-sub-icon"> 547 <img src="/image/1167" alt="" width="20" height="20" style="object-fit:contain;"> 548 </div> 549 Coaching & Consulting 550 </a> 551 <a href="/en/shingo-model" class="nav__sheet-sub-item"> 552 <div class="nav__sheet-sub-icon"> 553 <img src="/image/1178" alt="" width="20" height="20" style="object-fit:contain;"> 554 </div> 555 Shingo Model™ 556 </a> 557 </div> 558 <a href="/en/events" class="nav__sheet-link ">Events</a> 559 <button class="nav__sheet-group-trigger" type="button"> 560 <span>Consulting</span> 561 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 562 </button> 563 <div class="nav__sheet-sub"> 564 <a href="/en/benchmarking" class="nav__sheet-sub-item"> 565 <div class="nav__sheet-sub-icon"> 566 <img src="/image/1165" alt="" width="20" height="20" style="object-fit:contain;"> 567 </div> 568 Benchmarking 569 </a> 570 <a href="/en/culture-development-system-explained" class="nav__sheet-sub-item"> 571 <div class="nav__sheet-sub-icon"> 572 <img src="/image/1713" alt="" width="20" height="20" style="object-fit:contain;"> 573 </div> 574 What is the Culture Development System? 575 </a> 576 <a href="/en/excellence-community" class="nav__sheet-sub-item"> 577 <div class="nav__sheet-sub-icon"> 578 <img src="/image/1181" alt="" width="20" height="20" style="object-fit:contain;"> 579 </div> 580 Excellence Community 581 </a> 582 <a href="/en/talent-development" class="nav__sheet-sub-item"> 583 <div class="nav__sheet-sub-icon"> 584 <img src="/image/1173" alt="" width="20" height="20" style="object-fit:contain;"> 585 </div> 586 Talent development 587 </a> 588 <a href="/en/opex-roll-out" class="nav__sheet-sub-item"> 589 <div class="nav__sheet-sub-icon"> 590 <img src="/image/1170" alt="" width="20" height="20" style="object-fit:contain;"> 591 </div> 592 OPEX Roll-out 593 </a> 594 </div> 595 <button class="nav__sheet-group-trigger" type="button">
596 <span>Products</span> 597 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 598 </button> 599 <div class="nav__sheet-sub"> 600 <a href="/en/products/books" class="nav__sheet-sub-item"> 601 <div class="nav__sheet-sub-icon"> 602 <img src="/image/1166" alt="" width="20" height="20" style="object-fit:contain;"> 603 </div> 604 Publications 605 </a> 606 <a href="/en/products/tools-templates" class="nav__sheet-sub-item"> 607 <div class="nav__sheet-sub-icon"> 608 <img src="/image/1184" alt="" width="20" height="20" style="object-fit:contain;"> 609 </div> 610 Tools 611 </a> 612 <a href="/en/products/workshops" class="nav__sheet-sub-item"> 613 <div class="nav__sheet-sub-icon"> 614 <img src="/image/1293" alt="" width="20" height="20" style="object-fit:contain;"> 615 </div> 616 Workshops 617 </a> 618 </div> 619 <button class="nav__sheet-group-trigger" type="button"> 620 <span>Software</span> 621 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 622 </button> 623 <div class="nav__sheet-sub"> 624 <a href="/en/support" class="nav__sheet-sub-item"> 625 <div class="nav__sheet-sub-icon"> 626 <img src="/image/1172" alt="" width="20" height="20" style="object-fit:contain;"> 627 </div> 628 Support 629 </a> 630 <a href="/en/alphadi-tab" class="nav__sheet-sub-item"> 631 <div class="nav__sheet-sub-icon"> 632 <img src="/image/1169" alt="" width="20" height="20" style="object-fit:contain;"> 633 </div> 634 AlphadiTab 635 </a> 636 </div> 637 <button class="nav__sheet-group-trigger" type="button"> 638 <span>About us</span> 639 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 640 </button> 641 <div class="nav__sheet-sub"> 642 <a href="/en/career" class="nav__sheet-sub-item"> 643 <div class="nav__sheet-sub-icon"> 644 <img src="/image/1416" alt="" width="20" height="20" style="object-fit:contain;"> 645 </div> 646 Career 647 </a> 648 <a href="/en/ueber-uns" class="nav__sheet-sub-item"> 649 <div class="nav__sheet-sub-icon"> 650 <img src="/image/1182" alt="" width="20" height="20" style="object-fit:contain;"> 651 </div> 652 Meet the Team 653 </a> 654 <a href="/en/glossary" class="nav__sheet-sub-item"> 655 <div class="nav__sheet-sub-icon"> 656 <img src="/image/216" alt="" width="20" height="20" style="object-fit:contain;"> 657 </div> 658 Glossary 659 </a> 660 </div> 661 662 663 664 <div class="nav__sheet-divider"></div> 665 <button class="nav__sheet-group-trigger" type="button" aria-haspopup="true" aria-expanded="false">
666 <span> 667 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle;margin-right:.35rem;"><circle cx="12" cy="8" r="4"/><path d="M4 20c0-4 3.6-7 8-7s8 3 8 7"/></svg> 668 Account 669 </span> 670 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 671 </button> 672 <div class="nav__sheet-sub"> 673 <div class="nav__sheet-account"> 674 <p class="nav__sheet-account-lead">Log in into your shop account or create a new one.</p> 675 <a class="btn btn--primary" href="/Internal/Account/Login?returnUrl=~%2Fen%2Fproducts%2Fbooks">Login</a> 676 <a class="btn btn--outline" href="/Internal/Account/Register?returnUrl=~%2Fen%2Fproducts%2Fbooks">Create account</a> 677 </div> 678 </div> 679 680 <div class="nav__sheet-divider"></div> 681 <button class="nav__sheet-group-trigger" id="sheetLangTrigger" type="button"> 682 <span> 683 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle;margin-right:.35rem;"><circle cx="12" cy="12" r="10"/><path d="M2 12h20"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg> 684 Language 685 </span> 686 <svg viewBox="0 0 10 6" fill="none"><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg> 687 </button> 688 <div class="nav__sheet-sub" id="sheetLangSub"> 689 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 690 <button type="submit" name="culture" value="de-DE" 691 class="nav__sheet-sub-item "> 692 DE â German 693 </button> 694 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 695 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 696 <button type="submit" name="culture" value="en-US" 697 class="nav__sheet-sub-item is-active"> 698 EN â English 699 </button> 700 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 701 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 702 <button type="submit" name="culture" value="es-ES" 703 class="nav__sheet-sub-item "> 704 ES â Spanish 705 </button> 706 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 707 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 708 <button type="submit" name="culture" value="it-IT" 709 class="nav__sheet-sub-item "> 710 IT â Italian 711 </button> 712 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 713 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 714 <button type="submit" name="culture" value="fr-FR" 715 class="nav__sheet-sub-item "> 716 FR â French 717 </button> 718 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 719 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 720 <button type="submit" name="culture" value="pl-PL" 721 class="nav__sheet-sub-item "> 722 PL â Polish 723 </button> 724 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 725 <form method="post" style="margin:0;padding:0;display:contents;" action="/Home/SetLanguage?returnUrl=~%2Fen%2Fproducts%2Fbooks"> 726 <button type="submit" name="culture" value="pt-PT"
727 class="nav__sheet-sub-item "> 728 PT â Portuguese 729 </button> 730 <input name="__RequestVerificationToken" type="hidden" value="CfDJ8BIMwQTuEtBBtnnpT6fmYEJCq1euYtJf14bdoh3dRblKaauYY3LZcSN_Wig0b0P5VozGedmy-95E-Cgw4wjObF7by22hOv58OilJxidx5BDriS3daXs1CdebtViczD-MsEBUGCahPQTntfTYKYMlnAE" /></form> 731 </div> 732 </div> 733 734 <div class="nav__sheet-footer"> 735 <a href="/en/contact">Contact</a> 736 </div> 737 </div> 738 739 <!-- âââââââ MAIN âââââââ --> 740 741<div class="page-hero"> 742 <div class="container"> 743 <div class="page-hero__label">Books & Tools</div> 744 <h1 class="page-hero__title">Publications</h1> 745 <p class="page-hero__sub"> 746Guides, reference works and toolkits written by practitioners for process owners, change agents and ambitious organizations. </p> 747 </div> 748</div> 749 750<section class="section bg-warm"> 751 <div class="container"> 752 753 <span class="eyebrow fade-up">Alle publications & Tools</span> 754 755 <div class="product-grid" id="prodGrid" style="margin-top:2rem;"> 756 <div class="product-card fade-up" 757 data-title="black book" 758 data-created="2026-07-08T19:08:57.0691084" 759 data-price="93.00" 760 data-tags=""> 761 <a href="/en/products/books/black-book"> 762 <div class="product-card__cover"> 763 <img src="/image/171" alt="Black Book" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 764 </div> 765 </a> 766 <div class="product-card__body"> 767 <div class="product-card__info"> 768 <div class="product-card__title">Black Book</div> 769 <div class="product-card__author"> 770 Yvonn Gaßner & Dimitri Pitikaris 771 </div> 772 </div> 773 <div class="product-card__price"> 774 93,00 € 775 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 776 </div> 777 778 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 779 <button class="btn btn--primary product-card__atc" 780 data-add-to-cart="product-2" 781 data-cart-type="product" 782 data-cart-name="Black Book" 783 data-cart-price="93" 784 data-cart-format="Incl. VAT." 785 data-cart-image="/image/171" 786 data-cart-features="[{"name":"Format","isRequired":true,"options":[{"name":"Hardcover (in colour)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Language","isRequired":true,"options":[{"name":"German","price":0.0,"isDefault":true,"badgeText":""}]}]"> 787 Add to cart 788 </button> 789 790 </div> 791 </div> 792 </div> 793 <div class="product-card fade-up" 794 data-title="blue book" 795 data-created="2026-07-06T11:10:23.7968352" 796 data-price="93.00" 797 data-tags=""> 798 <a href="/en/products/books/blue-book"> 799 <div class="product-card__cover"> 800 <img src="/image/174" alt="Blue Book" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 801 </div> 802 </a> 803 <div class="product-card__body"> 804 <div class="product-card__info"> 805 <div class="product-card__title">Blue Book</div> 806 <div class="product-card__author"> 807 Yvonn Gaßner & Dimitri Pitikaris 808 </div> 809 </div> 810 <div class="product-card__price"> 811 93,00 €
812 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 813 </div> 814 815 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 816 <button class="btn btn--primary product-card__atc" 817 data-add-to-cart="product-3" 818 data-cart-type="product" 819 data-cart-name="Blue Book" 820 data-cart-price="93" 821 data-cart-format="incl. VAT" 822 data-cart-image="/image/174" 823 data-cart-features="[{"name":"Format","isRequired":true,"options":[{"name":"Hardcover (in colour)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Language","isRequired":true,"options":[{"name":"German","price":0.0,"isDefault":true,"badgeText":""}]}]"> 824 Add to cart 825 </button> 826 827 </div> 828 </div> 829 </div> 830 <div class="product-card fade-up" 831 data-title="cerulean book" 832 data-created="2026-07-06T11:07:40.5786942" 833 data-price="99.00" 834 data-tags=""> 835 <a href="/en/products/books/cerulean-book"> 836 <div class="product-card__cover"> 837 <img src="/image/173" alt="Cerulean Book" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 838 </div> 839 </a> 840 <div class="product-card__body"> 841 <div class="product-card__info"> 842 <div class="product-card__title">Cerulean Book</div> 843 <div class="product-card__author"> 844 Yvonn Gaßner & Dimitri Pitikaris 845 </div> 846 </div> 847 <div class="product-card__price"> 848 99,00 € 849 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 850 </div> 851 852 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 853 <button class="btn btn--primary product-card__atc" 854 data-add-to-cart="product-5" 855 data-cart-type="product" 856 data-cart-name="Cerulean Book" 857 data-cart-price="99" 858 data-cart-format="Incl. VAT." 859 data-cart-image="/image/173" 860 data-cart-features="[{"name":"Format","isRequired":true,"options":[{"name":"Hardcover (in colour)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Language","isRequired":true,"options":[{"name":"German","price":0.0,"isDefault":true,"badgeText":""}]}]"> 861 Add to cart 862 </button> 863 864 </div> 865 </div> 866 </div> 867 <div class="product-card fade-up" 868 data-title="discover excellence" 869 data-created="2026-07-06T11:05:07.3010137" 870 data-price="77.00" 871 data-tags=""> 872 <a href="/en/products/books/discover-excellence-book"> 873 <div class="product-card__cover"> 874 <img src="/image/172" alt="Discover Excellence" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 875 </div> 876 </a> 877 <div class="product-card__body"> 878 <div class="product-card__info"> 879 <div class="product-card__title">Discover Excellence</div> 880 <div class="product-card__author"> 881 Dimitri Pitikaris 882 </div> 883 </div> 884 <div class="product-card__price"> 885 77,00 €
886 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 887 </div> 888 889 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 890 <button class="btn btn--primary product-card__atc" 891 data-add-to-cart="product-6" 892 data-cart-type="product" 893 data-cart-name="Discover Excellence" 894 data-cart-price="77" 895 data-cart-format="incl. VAT" 896 data-cart-image="/image/172" 897 data-cart-features="[{"name":"Format","isRequired":true,"options":[{"name":"Hardcover (in colour)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Language","isRequired":true,"options":[{"name":"German","price":0.0,"isDefault":true,"badgeText":""}]}]"> 898 Add to cart 899 </button> 900 901 </div> 902 </div> 903 </div> 904 <div class="product-card fade-up" 905 data-title="green book" 906 data-created="2026-07-10T06:29:30.4735672" 907 data-price="88.00" 908 data-tags=""> 909 <a href="/en/products/books/green-book"> 910 <div class="product-card__cover"> 911 <img src="/image/170" alt="Green Book" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 912 </div> 913 </a> 914 <div class="product-card__body"> 915 <div class="product-card__info"> 916 <div class="product-card__title">Green Book</div> 917 <div class="product-card__author"> 918 Yvonn Gaßner & Dimitri Pitikaris · 4. Ausgabe 919 </div> 920 </div> 921 <div class="product-card__price"> 922 88,00 € 923 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 924 </div> 925 926 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 927 <button class="btn btn--primary product-card__atc" 928 data-add-to-cart="product-1" 929 data-cart-type="product" 930 data-cart-name="Green Book" 931 data-cart-price="88" 932 data-cart-format="incl. VAT" 933 data-cart-image="/image/170" 934 data-cart-features="[{"name":"Edition","isRequired":true,"options":[{"name":"Hardcover (in color)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Sprache","isRequired":true,"options":[{"name":"Deutsch","price":0.0,"isDefault":true,"badgeText":""}]}]"> 935 Add to cart 936 </button> 937 938 </div> 939 </div> 940 </div> 941 <div class="product-card fade-up" 942 data-title="roll-out of lss in retail logistics" 943 data-created="2026-07-06T10:53:16.8414405" 944 data-price="65.00" 945 data-tags=""> 946 <a href="/en/products/books/lss-roll-out-trade-logistics"> 947 <div class="product-card__cover"> 948 <img src="/image/175" alt="Roll-out of LSS in retail logistics" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 949 </div> 950 </a> 951 <div class="product-card__body"> 952 <div class="product-card__info"> 953 <div class="product-card__title">Roll-out of LSS in retail logistics</div> 954 <div class="product-card__author"> 955 Yusuf Yazicioğlu 956 </div> 957 </div> 958 <div class="product-card__price"> 959 65,00 €
960 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 961 </div> 962 963 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 964 <button class="btn btn--primary product-card__atc" 965 data-add-to-cart="product-7" 966 data-cart-type="product" 967 data-cart-name="Roll-out of LSS in retail logistics" 968 data-cart-price="65" 969 data-cart-format="Incl. VAT." 970 data-cart-image="/image/175" 971 data-cart-features="[{"name":"Format","isRequired":true,"options":[{"name":"Paperback (in colour)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Language","isRequired":true,"options":[{"name":"German","price":0.0,"isDefault":true,"badgeText":""},{"name":"English","price":0.0,"isDefault":true,"badgeText":""}]}]"> 972 Add to cart 973 </button> 974 975 </div> 976 </div> 977 </div> 978 <div class="product-card fade-up" 979 data-title="yellow book" 980 data-created="2026-09-28T12:29:51.4230174" 981 data-price="58.00" 982 data-tags=""> 983 <a href="/en/products/books/yellow-book"> 984 <div class="product-card__cover"> 985 <img src="/image/169" alt="Yellow Book" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;" loading="lazy" /> 986 </div> 987 </a> 988 <div class="product-card__body"> 989 <div class="product-card__info"> 990 <div class="product-card__title">Yellow Book</div> 991 <div class="product-card__author"> 992 Yvonn Gaßner & Dimitri Pitikaris 993 </div> 994 </div> 995 <div class="product-card__price"> 996 58,00 € 997 <span style="color:var(--c-subtle);font-weight:400;font-size:0.75rem;"> incl. VAT</span> 998 </div> 999 1000 <div style="display: flex; gap: 5px; flex-wrap: wrap; align-items: center; justify-content: space-between"> 1001 <button class="btn btn--primary product-card__atc" 1002 data-add-to-cart="product-4" 1003 data-cart-type="product" 1004 data-cart-name="Yellow Book" 1005 data-cart-price="58" 1006 data-cart-format="incl. VAT" 1007 data-cart-image="/image/169" 1008 data-cart-features="[{"name":"Ausführung","isRequired":true,"options":[{"name":"Hardcover (in Farbe)","price":0.0,"isDefault":true,"badgeText":""}]},{"name":"Sprache","isRequired":true,"options":[{"name":"Deutsch","price":0.0,"isDefault":true,"badgeText":""}]}]"> 1009 Add to cart 1010 </button> 1011 1012 </div> 1013 </div> 1014 </div> 1015 </div> 1016 <p id="prodEmpty" style="display:none;text-align:center;color:var(--c-mid);font-family:var(--f-ui);padding:3rem 0;">No products found.</p> 1017 </div> 1018</section> 1019
1020<script> 1021(function () { 1022 var sortEl = document.getElementById('prodSort'); 1023 var grid = document.getElementById('prodGrid'); 1024 if (!sortEl || !grid) { return; } 1025 sortEl.addEventListener('change', function () { 1026 var key = this.value; 1027 var arr = Array.from(grid.querySelectorAll('.product-card')); 1028 arr.sort(function (a, b) { 1029 var ta = (a.dataset.title || '').toLowerCase(); 1030 var tb = (b.dataset.title || '').toLowerCase(); 1031 var pa = a.dataset.price === '' ? null : parseFloat(a.dataset.price); 1032 var pb = b.dataset.price === '' ? null : parseFloat(b.dataset.price); 1033 var ca = new Date(a.dataset.created || 0).getTime(); 1034 var cb = new Date(b.dataset.created || 0).getTime(); 1035 switch (key) { 1036 case 'NewestFirst': return cb - ca; 1037 case 'OldestFirst': return ca - cb; 1038 case 'PriceAsc': return (pa ?? Infinity) - (pb ?? Infinity) || ta.localeCompare(tb); 1039 case 'PriceDesc': return (pb ?? -Infinity) - (pa ?? -Infinity) || ta.localeCompare(tb); 1040 case 'AlphabeticalAsc': return ta.localeCompare(tb); 1041 case 'AlphabeticalDesc': return tb.localeCompare(ta); 1042 default: return 0; 1043 } 1044 }); 1045 arr.forEach(function (el) { grid.appendChild(el); }); 1046 }); 1047})(); 1048 1049(function () { 1050 var pillWrap = document.getElementById('prodTagPills'); 1051 var grid = document.getElementById('prodGrid'); 1052 if (!pillWrap || !grid) { return; } 1053 1054 var activeTags = []; 1055 var allBtn = pillWrap.querySelector('[data-filter="all"]'); 1056 var empty = document.getElementById('prodEmpty'); 1057 1058 function applyTagFilter() { 1059 var visible = 0; 1060 grid.querySelectorAll('.product-card').forEach(function (card) { 1061 var tags = (card.dataset.tags || '').split(/\s+/).filter(Boolean); 1062 var show = activeTags.length === 0 || activeTags.some(function (t) { return tags.indexOf(t) !== -1; }); 1063 card.style.display = show ? '' : 'none'; 1064 if (show) { visible++; } 1065 }); 1066 if (empty) { empty.style.display = visible === 0 ? '' : 'none'; } 1067 } 1068 1069 function refreshPillStates() { 1070 var pills = pillWrap.querySelectorAll('.ws-cat-pill'); 1071 if (activeTags.length === 0) { 1072 pills.forEach(function (b) { b.classList.remove('is-active', 'is-dimmed'); }); 1073 allBtn.classList.add('is-active'); 1074 return; 1075 } 1076 pills.forEach(function (b) { 1077 var selected = activeTags.indexOf(b.dataset.filter) !== -1; 1078 b.classList.toggle('is-active', selected); 1079 b.classList.toggle('is-dimmed', !selected); 1080 }); 1081 } 1082 1083 pillWrap.addEventListener('click', function (e) { 1084 var btn = e.target.closest('.ws-cat-pill'); 1085 if (!btn) { return; }
1086 var key = btn.dataset.filter; 1087 if (key === 'all') { 1088 activeTags = []; 1089 } else { 1090 var idx = activeTags.indexOf(key); 1091 if (idx === -1) { activeTags.push(key); } else { activeTags.splice(idx, 1); } 1092 } 1093 refreshPillStates(); 1094 applyTagFilter(); 1095 }); 1096})(); 1097</script>
1097 1098 1099 1100 1101 <!-- âââââââ FOOTER âââââââ --> 1102<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"> 1103<title></title> 1104<link href="https://api.fontshare.com" rel="preconnect" /> 1105<link href="https://fonts.googleapis.com" rel="preconnect" /> 1106<link href="https://api.fontshare.com/v2/css?f[]=satoshi@300,400,500,600,700,900&display=swap" rel="stylesheet" /> 1107<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap" rel="stylesheet" /> 1108<style type="text/css">*, *::before, *::after { 1109 box-sizing: border-box; 1110 margin: 0; 1111 padding: 0; 1112 } 1113 html { 1114 font-size: 16px; 1115 } 1116 body { 1117 font-family: 'Satoshi', system-ui, sans-serif; 1118 -webkit-font-smoothing: antialiased; 1119 } 1120 a { 1121 color: inherit; 1122 text-decoration: none; 1123 } 1124 img { 1125 max-width: 100%; 1126 display: block; 1127 } 1128 .footer-v2 { 1129 background: #111111; 1130 position: relative; 1131 overflow: hidden; 1132 } 1133 .footer-v2::before { 1134 content: ''; 1135 position: absolute; 1136 top: 0; 1137 left: 0; 1138 right: 0; 1139 height: 3px; 1140 background: linear-gradient(90deg, #111111, #EC841F, #1a0a00); 1141 } 1142 .footer-v2::after { 1143 content: ''; 1144 position: absolute; 1145 top: -120px; 1146 left: -80px; 1147 width: 500px; 1148 height: 500px; 1149 border-radius: 50%; 1150 background: radial-gradient(circle, rgba(236,132,31,.07) 0%, transparent 65%); 1151 pointer-events: none; 1152 } 1153 .footer-v2__inner { 1154 max-width: 1280px; 1155 margin: 0 auto; 1156 padding: 4rem 3rem 0; 1157 } 1158 @media (max-width: 767px) { 1159 .footer-v2__inner { 1160 padding: 3rem 1.5rem 0; 1161 } 1162 } 1163 .footer-v2__top { 1164 display: grid; 1165 grid-template-columns: 1.6fr 2.4fr; 1166 gap: 4rem; 1167 padding-bottom: 3rem; 1168 border-bottom: 1px solid rgba(255,255,255,.08); 1169 } 1170 @media (max-width: 767px) { 1171 .footer-v2__top { 1172 grid-template-columns: 1fr; 1173 gap: 2.5rem; 1174 } 1175 } 1176 .footer-v2__brand img { 1177 height: 56px; 1178 width: auto; 1179 margin-bottom: 2rem; 1180 filter: none !important; 1181 /* Prevents browser dark mode from inverting the white logo to black */ 1182 forced-color-adjust: none; 1183 /* Exclude logo from automatic color adjustment (Dark Mode/High Contrast) */ 1184 } 1185 .footer-v2__claim { 1186 font-family: 'Satoshi', system-ui, sans-serif; 1187 font-size: clamp(1.15rem, 1.8vw, 1.45rem); 1188 font-weight: 700; 1189 color: #ffffff; 1190 line-height: 1.35; 1191 letter-spacing: -0.02em; 1192 margin-bottom: 1.5rem; 1193 max-width: 280px; 1194 } 1195 .footer-v2__claim em { 1196 font-style: normal; 1197 color: #EC841F; 1198 } 1199 .footer-v2__contact { 1200 display: flex; 1201 flex-direction: column; 1202 gap: 0.4rem; 1203 } 1204 .footer-v2__contact a { 1205 display: flex;
1206 align-items: center; 1207 gap: 0.5rem; 1208 font-family: 'Satoshi', system-ui, sans-serif; 1209 font-size: 0.78rem; 1210 color: rgba(255,255,255,.88); 1211 text-decoration: none; 1212 transition: color 0.15s; 1213 font-weight: 400; 1214 letter-spacing: 0.8px; 1215 } 1216 .footer-v2__contact a:hover { 1217 color: #EC841F; 1218 } 1219 .footer-v2__contact svg { 1220 flex-shrink: 0; 1221 opacity: .6; 1222 } 1223 .footer-v2__links { 1224 display: grid; 1225 grid-template-columns: repeat(3, 1fr); 1226 gap: 2rem; 1227 padding-top: 0.25rem; 1228 } 1229 @media (max-width: 479px) { 1230 .footer-v2__links { 1231 grid-template-columns: repeat(2, 1fr); 1232 } 1233 } 1234 .footer-v2__col h4 { 1235 font-family: 'Satoshi', system-ui, sans-serif; 1236 font-size: 0.65rem; 1237 font-weight: 700; 1238 letter-spacing: 0.14em; 1239 text-transform: uppercase; 1240 color: #ffffff; 1241 margin-bottom: 1rem; 1242 } 1243 .footer-v2__col a { 1244 display: block; 1245 font-family: 'Satoshi', system-ui, sans-serif; 1246 font-size: 0.78rem; 1247 color: rgba(255,255,255,.88); 1248 margin-bottom: 0.5rem; 1249 text-decoration: none; 1250 transition: color 0.15s, padding-left 0.15s; 1251 font-weight: 300; 1252 letter-spacing: 0.8px; 1253 } 1254 .footer-v2__col a:hover { 1255 color: #fff; 1256 padding-left: 3px; 1257 } 1258 .footer-v2__bottom { 1259 max-width: 1280px; 1260 margin: 0 auto; 1261 padding: 1.25rem 3rem; 1262 border-top: 1px solid rgba(255,255,255,.14); 1263 display: flex; 1264 flex-wrap: wrap; 1265 justify-content: space-between; 1266 align-items: center; 1267 gap: 0.75rem; 1268 } 1269 @media (max-width: 767px) { 1270 .footer-v2__bottom { 1271 padding: 1.25rem 1.5rem; 1272 flex-direction: column; 1273 align-items: flex-start; 1274 } 1275 } 1276 .footer-v2__copy { 1277 font-family: 'Satoshi', system-ui, sans-serif; 1278 font-size: 0.75rem; 1279 color: rgba(255,255,255,.88); 1280 } 1281 .footer-v2__socials { 1282 display: flex;
1283 align-items: center; 1284 gap: 0.5rem; 1285 } 1286 .footer-v2__social { 1287 width: 36px; 1288 height: 36px; 1289 display: flex; 1290 align-items: center; 1291 justify-content: center; 1292 border: 1px solid rgba(255,255,255,.5); 1293 border-radius: 8px; 1294 color: rgba(255,255,255,.9); 1295 text-decoration: none; 1296 transition: border-color 0.15s, color 0.15s, background 0.15s; 1297 } 1298 .footer-v2__social:hover { 1299 border-color: #EC841F; 1300 color: #EC841F; 1301 background: rgba(236,132,31,.08); 1302 } 1303 .footer-v2__social svg { 1304 width: 14px; 1305 height: 14px; 1306 } 1307</style> 1308<footer class="footer-v2"> 1309<div class="footer-v2__inner"> 1310<div class="footer-v2__top"> 1311<div class="footer-v2__brand"> 1312<a href="/"><img alt="Alphadi" src="/image/222" /></a> 1313 1314<p class="footer-v2__claim">We focus on<br /> 1315<em>people</em>.</p> 1316 1317<div class="footer-v2__contact"> 1318<a href="tel:+4956194918900"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1319 <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.68 12a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.59 1.23h3a2 2 0 0 1 2 1.72c.128.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.91 8.87a16 16 0 0 0 6 6l.87-.87a2 2 0 0 1 2.11-.45c.907.339 1.85.572 2.81.7A2 2 0 0 1 22 16.92z"/> 1320 </svg>+49 561 949 189 0</a> 1321 1322<a href="mailto:[email protected]"><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 1323 <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/> 1324 <polyline points="22,6 12,13 2,6"/> 1325 </svg>[email protected]</a> 1326</div> 1327</div> 1328 1329<div class="footer-v2__links"> 1330<div class="footer-v2__col"> 1331<h4>Programs</h4> 1332 1333<a href="/en/workshops">Workshops & Seminars</a> 1334 1335<a href="/en/events">Events</a> 1336 1337<a href="/en/assessments">Assessments</a> 1338 1339<a href="/en/support">Software Support & Help</a> 1340</div> 1341 1342<div class="footer-v2__col"> 1343<h4>Company</h4> 1344 1345<a href="/en/ueber-uns">About us</a> 1346 1347<a href="/en/contact">Contact</a> 1348 1349<a href="/en/career">Career</a> 1350</div> 1351 1352<div class="footer-v2__col"> 1353<h4>Legal</h4> 1354 1355<a href="/en/privacy-policy">Privacy Policy</a> 1356 1357<a href="/en/t&c">Terms and Conditions</a> 1358 1359<a href="/en/imprint">Imprint</a> 1360 1361<a href="/en/cancellation-policy">Revoke Contract Here</a> 1362 1363<a href="/en/shipping-payment-terms">Shipping & Payment</a> 1364</div> 1365</div> 1366</div> 1367 1368<div class="footer-v2__bottom"><span class="footer-v2__copy">© 2026 Alphadi Deutschland GmbH. All rights reserved.</span> 1369 1370<div class="footer-v2__socials"> 1371<a aria-label="YouTube" class="footer-v2__social" href="#"><svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16"> 1372 <path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/> 1373 </svg></a> 1374 1375<a aria-label="LinkedIn" class="footer-v2__social" href="#"><svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16"> 1376 <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 0 1-2.063-2.065 2.064 2.064 0 1 1 2.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/> 1377 </svg></a> 1378</div> 1379</div> 1380</div> 1381</footer> 1382 1383
1383<script> 1384 // Shared price formatter â mirrors DecimalUtils.PriceDisplay (German format, e.g. "6.600,00 â¬"). 1385 // Used by every client-side price render (cart drawer, cart page, checkout, product options). 1386 window.formatPrice = function (value, symbol) { 1387 var n = Number(value); 1388 if (!isFinite(n)) { n = 0; } 1389 var number = n.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }); 1390 return number + ' ' + (symbol || 'â¬'); 1391 }; 1392 </script>
1392 1393
1393<script src="/bundles/hp-scripts.min.js?v=ZHApbpWBMcSvjokQcwPZYptpuVDzcPqCftH9nsYyTTE"></script>
1393 1394
1394<script src="/js/cart-sync.js?v=9IsathfVPUw6nubjgrQKNjXkyoTVZ-DBaj0qJNKNn8w"></script>
1394 1395 1396 <!-- KaTeX: render LaTeX math anywhere in the page content (delimiters \( \), \[ \], $$ $$) --> 1397
1397<script src="/lib/katex/katex.min.js?v=3ISyluw-iE3gkxWPdg_Z1Ftser5YtTgVV_ThOPRqWK4"></script>
1397 1398
1398<script src="/lib/katex/contrib/auto-render.min.js?v=nLjaz8CGwpZsnsS6VPSi3EO3y-KzPOwaJ0PYhsf7R6c"></script>
1398 1399
1399<script> 1400 1401 1402 (function () { 1403 function renderMath() { 1404 if (typeof renderMathInElement !== 'function') { return; } 1405 renderMathInElement(document.body, { 1406 delimiters: [ 1407 { left: '$$', right: '$$', display: true }, 1408 { left: '\\[', right: '\\]', display: true }, 1409 { left: '\\(', right: '\\)', display: false } 1410 ], 1411 throwOnError: false, 1412 ignoredTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'] 1413 }); 1414 } 1415 1416 if (document.readyState === 'loading') { 1417 document.addEventListener('DOMContentLoaded', renderMath); 1418 } else { 1419 renderMath(); 1420 } 1421 })(); 1422 </script>
1422 1423 1424 <!-- Topbar user menu toggle --> 1425
1425<script> 1426 (function () { 1427 var userMenu = document.getElementById('userMenu'); 1428 var userMenuBtn = document.getElementById('userMenuBtn'); 1429 if (userMenu && userMenuBtn) { 1430 userMenuBtn.addEventListener('click', function (e) { 1431 e.stopPropagation(); 1432 userMenu.classList.toggle('is-open'); 1433 }); 1434 document.addEventListener('click', function () { 1435 userMenu.classList.remove('is-open'); 1436 }); 1437 userMenu.addEventListener('click', function (e) { e.stopPropagation(); }); 1438 } 1439 // Note: lang-switch toggles are already handled globally by hp-scripts.js 1440 })(); 1441 </script>
1441 1442 1443 <!-- Topbar account (signed out) dropdown toggle --> 1444
1444<script> 1445 (function () { 1446 var accountMenu = document.getElementById('accountMenu'); 1447 var accountMenuBtn = document.getElementById('accountMenuBtn'); 1448 if (accountMenu && accountMenuBtn) { 1449 accountMenuBtn.addEventListener('click', function (e) { 1450 e.stopPropagation(); 1451 var open = accountMenu.classList.toggle('is-open'); 1452 accountMenuBtn.setAttribute('aria-expanded', open ? 'true' : 'false'); 1453 }); 1454 document.addEventListener('click', function () { 1455 if (accountMenu.classList.contains('is-open')) { 1456 accountMenu.classList.remove('is-open'); 1457 accountMenuBtn.setAttribute('aria-expanded', 'false'); 1458 } 1459 }); 1460 accountMenu.addEventListener('click', function (e) { e.stopPropagation(); }); 1461 } 1462 })(); 1463 </script>
1463 1464 1465 1466 1467 1468 <!-- Cart FAB (mobile) --> 1469 <button class="cart-fab cart-btn" id="cartFab" aria-label="Cart"> 1470 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/><line x1="3" y1="6" x2="21" y2="6"/><path d="M16 10a4 4 0 01-8 0"/></svg> 1471 <span class="cart-fab__badge cart-badge">0</span> 1472 </button> 1473 1474 <!-- Cart Overlay + Drawer --> 1475 <div class="cart-overlay" id="cartOverlay"></div> 1476 <div class="cart-drawer" id="cartDrawer" 1477 data-label-empty="Your cart is empty." 1478 data-label-remove="Remove" 1479 data-label-order="Order now" 1480 data-label-continue="Continue shopping" 1481 data-label-unit="unit" 1482 data-label-required="This option is required."> 1483 <div class="cart-drawer__head"> 1484 <span class="cart-drawer__title">Cart</span> 1485 <button class="cart-drawer__close" id="cartClose">✕</button> 1486 </div> 1487 <div class="cart-drawer__notice" id="cartNotice" style="display:none;padding:0.9rem 1.1rem 0;" 1488 data-msg-title="Your cart was updated" 1489 data-msg-removed="{name} is no longer available and was removed." 1490 data-msg-repriced="Price of {name} changed to {price}."></div> 1491 <div class="cart-drawer__body" id="cartBody"></div> 1492 <div class="cart-drawer__foot" id="cartFoot" style="display:none;"> 1493 <div class="cart-subtotal"> 1494 <span class="cart-subtotal__label">Total</span> 1495 <span class="cart-subtotal__amount" id="cartTotal">0,00 €</span> 1496 </div> 1497 <a href="/en/cart" class="btn btn--primary btn--lg" style="width:100%;justify-content:center;">View cart</a> 1498 <button class="cart-continue" id="cartContinue">Continue shopping</button> 1499 </div> 1500 </div> 1501 1502 1503<div class="modal-overlay" id="bookingRequestModal"> 1504 <div class="modal" role="dialog" aria-modal="true" aria-labelledby="bookingRequestModalTitle"> 1505 <button type="button" class="modal__close" data-booking-request-close aria-label="Close">×</button> 1506 <div class="modal__title" id="bookingRequestModalTitle">Reserve a seat</div> 1507 <p style="font-family:var(--f-ui);font-size:0.875rem;color:var(--c-mid);margin-bottom:1.5rem;"> 1508 <strong id="bookingRequestProduct"></strong> 1509 <span id="bookingRequestFormat"></span> 1510 </p> 1511 <form id="bookingRequestForm" novalidate> 1512 <div class="form-group"> 1513 <label class="form-label">First name *</label> 1514 <input type="text" class="form-input" name="firstName" required /> 1515 <div class="field-error"></div> 1516 </div> 1517 <div class="form-group"> 1518 <label class="form-label">Last name *</label> 1519 <input type="text" class="form-input" name="lastName" required /> 1520 <div class="field-error"></div> 1521 </div> 1522 <div class="form-group"> 1523 <label class="form-label">Company *</label> 1524 <input type="text" class="form-input" name="company" required /> 1525 <div class="field-error"></div> 1526 </div> 1527 <div class="form-group"> 1528 <label class="form-label">Email *</label> 1529 <input type="email" class="form-input" name="email" required /> 1530 <div class="field-error"></div> 1531 </div> 1532 <div class="form-group"> 1533 <label class="form-label">Phone *</label> 1534 <input type="tel" class="form-input" name="phone" required /> 1535 <div class="field-error"></div> 1536 </div> 1537 <div class="form-group"> 1538 <label class="form-label">Notes / special requirements</label> 1539 <textarea class="form-textarea" name="notes" rows="3"></textarea> 1540 </div> 1541 <div class="checkout-check-field"> 1542 <label class="checkout-check-label"> 1543 <input type="checkbox" id="br-terms" name="terms" />
1544 <span> 1545 I have read the 1546 <a href="/en/t&c" target="_blank" rel="noopener">Terms & Conditions</a> 1547 and agree to them. <span class="req">*</span> 1548 </span> 1549 </label> 1550 <span class="field-error fw-bold text-danger" id="brTermsError"></span> 1551 </div> 1552 <div class="checkout-check-field"> 1553 <label class="checkout-check-label"> 1554 <input type="checkbox" id="br-privacy" name="privacy" /> 1555 <span> 1556 I have read the 1557 <a href="/en/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a> 1558 and agree that my data will be processed. <span class="req">*</span> 1559 </span> 1560 </label> 1561 <span class="field-error fw-bold text-danger" id="brPrivacyError"></span> 1562 </div> 1563 1564 <div class="field-error" id="bookingRequestFormError" style="margin-bottom:.75rem;"></div> 1565 <button type="submit" class="btn btn--primary" style="width:100%;justify-content:center;"> 1566 Send booking request 1567 </button> 1568 </form> 1569 </div> 1570</div> 1571
1572<script> 1573(function () { 1574 'use strict'; 1575 1576 var overlay = document.getElementById('bookingRequestModal'); 1577 var form = document.getElementById('bookingRequestForm'); 1578 if (!overlay || !form) { return; } 1579 1580 var productEl = document.getElementById('bookingRequestProduct'); 1581 var formatEl = document.getElementById('bookingRequestFormat'); 1582 var formError = document.getElementById('bookingRequestFormError'); 1583 var pending = null; 1584 var submitting = false; 1585 1586 var POST_URL = '/en/cart/submit-booking-request'; 1587 var MSG_REQUIRED = "This field is required."; 1588 var MSG_EMAIL = "Please enter a valid e-mail address."; 1589 var MSG_ERROR = "An error occurred. Please try again."; 1590 var MSG_TERMS = "You must agree to the Terms & Conditions to continue."; 1591 var MSG_PRIVACY = "You must agree to the Privacy Policy to continue."; 1592 1593 function isEmail(v) { return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test((v || '').trim()); } 1594 1595 function openModal(data) { 1596 pending = data; 1597 productEl.textContent = data.name || ''; 1598 formatEl.innerHTML = data.format ? (' · ' + data.format) : ''; 1599 form.reset(); 1600 formError.textContent = ''; 1601 form.querySelectorAll('.is-invalid').forEach(function (el) { el.classList.remove('is-invalid'); }); 1602 form.querySelectorAll('.field-error').forEach(function (el) { el.textContent = ''; }); 1603 overlay.classList.add('is-open'); 1604 document.body.style.overflow = 'hidden'; 1605 setTimeout(function () { form.querySelector('[name=firstName]')?.focus(); }, 50); 1606 } 1607 1608 function closeModal() { 1609 overlay.classList.remove('is-open'); 1610 document.body.style.overflow = ''; 1611 pending = null; 1612 } 1613 1614 overlay.addEventListener('click', function (e) { 1615 if (e.target === overlay) { closeModal(); } 1616 }); 1617 overlay.querySelectorAll('[data-booking-request-close]').forEach(function (b) { 1618 b.addEventListener('click', closeModal); 1619 }); 1620 document.addEventListener('keydown', function (e) { 1621 if (e.key === 'Escape' && overlay.classList.contains('is-open')) { closeModal(); } 1622 }); 1623 1624 // Capture-phase interception so we beat both the cart booking modal and the global add-to-cart handler. 1625 document.addEventListener('click', function (e) { 1626 var btn = e.target.closest('[data-add-to-cart][data-cart-type]'); 1627 if (!btn) { return; } 1628 if (btn.dataset.onlyBooking !== 'true') { return; } // not an OnlyBooking appointment â let the cart flow run 1629 var type = btn.dataset.cartType; 1630 if (type !== 'training' && type !== 'event') { return; } 1631 if (btn.disabled) { return; } 1632 e.preventDefault(); 1633 e.stopImmediatePropagation(); 1634 openModal({ 1635 id: btn.dataset.addToCart, 1636 type: type, 1637 name: btn.dataset.cartName || btn.dataset.addToCart, 1638 format: btn.dataset.cartFormat || '', 1639 }); 1640 }, true); 1641 1642 function showErr(field, msg) { 1643 field.classList.add('is-invalid'); 1644 var s = field.parentElement.querySelector('.field-error'); 1645 if (s) { s.textContent = msg; } 1646 } 1647 function clearErr(field) { 1648 field.classList.remove('is-invalid'); 1649 var s = field.parentElement.querySelector('.field-error'); 1650 if (s) { s.textContent = ''; } 1651 } 1652 function validate(field) { 1653 var val = (field.value || '').trim(); 1654 if (field.hasAttribute('required') && !val) { showErr(field, MSG_REQUIRED); return false; } 1655 if (field.type === 'email' && val && !isEmail(val)) { showErr(field, MSG_EMAIL); return false; } 1656 clearErr(field); return true; 1657 } 1658 1659 form.querySelectorAll('input, textarea').forEach(function (f) { 1660 f.addEventListener('blur', function () { validate(f); }); 1661 f.addEventListener('input', function () { if (f.classList.contains('is-invalid')) { clearErr(f); } }); 1662 }); 1663 1664 form.addEventListener('submit', function (e) { 1665 e.preventDefault(); 1666 if (!pending || submitting) { return; } 1667 formError.textContent = ''; 1668 var ok = true; 1669 form.querySelectorAll('input[required], input[type=email]').forEach(function (f) { 1670 if (!validate(f)) { ok = false; } 1671 }); 1672 1673 var termsCb = document.getElementById('br-terms'); 1674 var termsErr = document.getElementById('brTermsError'); 1675 if (termsCb) { 1676 if (!termsCb.checked) { 1677 termsCb.classList.add('is-invalid'); 1678 if (termsErr) { termsErr.textContent = MSG_TERMS; } 1679 ok = false; 1680 } else { 1681 termsCb.classList.remove('is-invalid'); 1682 if (termsErr) { termsErr.textContent = ''; } 1683 } 1684 } 1685 1686 var privacyCb = document.getElementById('br-privacy'); 1687 var privacyErr = document.getElementById('brPrivacyError'); 1688 if (!privacyCb.checked) { 1689 privacyCb.classList.add('is-invalid'); 1690 if (privacyErr) { privacyErr.textContent = MSG_PRIVACY; } 1691 ok = false; 1692 } else { 1693 privacyCb.classList.remove('is-invalid'); 1694 if (privacyErr) { privacyErr.textContent = ''; } 1695 } 1696 1697 if (!ok) { return; } 1698 1699 var fd = new FormData(form); 1700 var payload = {
1701 id: pending.id, 1702 type: pending.type, 1703 firstName: (fd.get('firstName') || '').trim(), 1704 lastName: (fd.get('lastName') || '').trim(), 1705 company: (fd.get('company') || '').trim(), 1706 email: (fd.get('email') || '').trim(), 1707 phone: (fd.get('phone') || '').trim(), 1708 notes: (fd.get('notes') || '').trim(), 1709 }; 1710 1711 submitting = true; 1712 var submitBtn = form.querySelector('button[type=submit]'); 1713 if (submitBtn) { submitBtn.disabled = true; } 1714 1715 fetch(POST_URL, { 1716 method: 'POST', 1717 headers: { 'Content-Type': 'application/json' }, 1718 body: JSON.stringify(payload), 1719 }).then(function (res) { 1720 return res.ok ? res.json() : Promise.reject(res); 1721 }).then(function (data) { 1722 if (data && data.redirectUrl) { 1723 window.location = data.redirectUrl; 1724 } else { 1725 window.location.reload(); 1726 } 1727 }).catch(function () { 1728 submitting = false; 1729 if (submitBtn) { submitBtn.disabled = false; } 1730 formError.textContent = MSG_ERROR; 1731 }); 1732 }); 1733})(); 1734</script>
1734 1735 1736 1737<div class="modal-overlay" id="bookingModal"> 1738 <div class="modal" role="dialog" aria-modal="true" aria-labelledby="bookingModalTitle"> 1739 <button type="button" class="modal__close" data-booking-close aria-label="Close">×</button> 1740 <div class="modal__title" id="bookingModalTitle">Reserve a seat</div> 1741 <p style="font-family:var(--f-ui);font-size:0.875rem;color:var(--c-mid);margin-bottom:1.5rem;"> 1742 <strong id="bookingModalProduct"></strong> 1743 <span id="bookingModalFormat"></span> 1744 </p> 1745 <form id="bookingForm" novalidate> 1746 <div class="form-group"> 1747 <label class="form-label">First name *</label> 1748 <input type="text" class="form-input" name="participantFirstName" required /> 1749 <div class="field-error"></div> 1750 </div> 1751 <div class="form-group"> 1752 <label class="form-label">Last name *</label> 1753 <input type="text" class="form-input" name="participantLastName" required /> 1754 <div class="field-error"></div> 1755 </div> 1756 <div class="form-group"> 1757 <label class="form-label">Company *</label> 1758 <input type="text" class="form-input" name="participantCompany" required /> 1759 <div class="field-error"></div> 1760 </div> 1761 <div class="form-group"> 1762 <label class="form-label">Email *</label> 1763 <input type="email" class="form-input" name="participantEmail" required /> 1764 <div class="field-error"></div> 1765 </div> 1766 <div class="form-group"> 1767 <label class="form-label">Phone *</label> 1768 <input type="tel" class="form-input" name="participantPhone" required /> 1769 <div class="field-error"></div> 1770 </div> 1771 <div class="form-group"> 1772 <label class="form-label">Notes / special requirements</label> 1773 <textarea class="form-textarea" name="participantNotes" rows="3"></textarea> 1774 </div> 1775 <button type="submit" class="btn btn--primary" style="width:100%;justify-content:center;"> 1776 Add to cart 1777 </button> 1778 </form> 1779 </div> 1780</div> 1781
1782<script> 1783(function () { 1784 'use strict'; 1785 1786 var overlay = document.getElementById('bookingModal'); 1787 var form = document.getElementById('bookingForm'); 1788 if (!overlay || !form) { return; } 1789 1790 var productEl = document.getElementById('bookingModalProduct'); 1791 var formatEl = document.getElementById('bookingModalFormat'); 1792 var pending = null; 1793 1794 var MSG_REQUIRED = 'This field is required.'; 1795 var MSG_EMAIL = 'Please enter a valid e-mail address.'; 1796 1797 function isEmail(v) { return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test((v || '').trim()); } 1798 1799 function openModal(data) { 1800 pending = data; 1801 productEl.textContent = data.name || ''; 1802 formatEl.innerHTML = data.format ? (' · ' + data.format) : ''; 1803 form.reset(); 1804 form.querySelectorAll('.is-invalid').forEach(function (el) { el.classList.remove('is-invalid'); }); 1805 form.querySelectorAll('.field-error').forEach(function (el) { el.textContent = ''; }); 1806 overlay.classList.add('is-open'); 1807 document.body.style.overflow = 'hidden'; 1808 setTimeout(function () { form.querySelector('[name=participantFirstName]')?.focus(); }, 50); 1809 } 1810 1811 function closeModal() { 1812 overlay.classList.remove('is-open'); 1813 document.body.style.overflow = ''; 1814 pending = null; 1815 } 1816 1817 overlay.addEventListener('click', function (e) { 1818 if (e.target === overlay) { closeModal(); } 1819 }); 1820 overlay.querySelectorAll('[data-booking-close]').forEach(function (b) { 1821 b.addEventListener('click', closeModal); 1822 }); 1823 document.addEventListener('keydown', function (e) { 1824 if (e.key === 'Escape' && overlay.classList.contains('is-open')) { closeModal(); } 1825 }); 1826 1827 // Intercept add-to-cart clicks for trainings/events so we collect participant info first. 1828 document.addEventListener('click', function (e) { 1829 var btn = e.target.closest('[data-add-to-cart][data-cart-type]'); 1830 if (!btn) { return; } 1831 var type = btn.dataset.cartType; 1832 if (type !== 'training' && type !== 'event') { return; } 1833 // OnlyBooking appointments are handled by the separate "Send booking request" modal. 1834 if (btn.dataset.onlyBooking === 'true') { return; } 1835 if (btn.disabled) { return; } 1836 e.preventDefault(); 1837 e.stopImmediatePropagation(); 1838 openModal({ 1839 id: btn.dataset.addToCart, 1840 name: btn.dataset.cartName || btn.dataset.addToCart, 1841 price: btn.dataset.cartPrice || '0', 1842 format: btn.dataset.cartFormat || '', 1843 image: btn.dataset.cartImage || '', 1844 type: type, 1845 }); 1846 }, true); // capture phase so we beat the global add-to-cart handler 1847 1848 function showErr(field, msg) { 1849 field.classList.add('is-invalid'); 1850 var s = field.parentElement.querySelector('.field-error'); 1851 if (s) { s.textContent = msg; } 1852 } 1853 function clearErr(field) { 1854 field.classList.remove('is-invalid'); 1855 var s = field.parentElement.querySelector('.field-error'); 1856 if (s) { s.textContent = ''; } 1857 } 1858 function validate(field) { 1859 var val = (field.value || '').trim(); 1860 if (field.hasAttribute('required') && !val) { showErr(field, MSG_REQUIRED); return false; } 1861 if (field.type === 'email' && val && !isEmail(val)) { showErr(field, MSG_EMAIL); return false; } 1862 clearErr(field); return true; 1863 } 1864 1865 form.querySelectorAll('input, textarea').forEach(function (f) { 1866 f.addEventListener('blur', function () { validate(f); }); 1867 f.addEventListener('input', function () { if (f.classList.contains('is-invalid')) { clearErr(f); } }); 1868 }); 1869 1870 form.addEventListener('submit', function (e) { 1871 e.preventDefault(); 1872 if (!pending) { return; } 1873 var ok = true; 1874 form.querySelectorAll('input[required], input[type=email]').forEach(function (f) { 1875 if (!validate(f)) { ok = false; } 1876 }); 1877 if (!ok) { return; } 1878 1879 var fd = new FormData(form); 1880 var firstName = (fd.get('participantFirstName') || '').trim(); 1881 var lastName = (fd.get('participantLastName') || '').trim(); 1882 var participant = { 1883 firstName: firstName, 1884 lastName: lastName, 1885 // Combined name kept for the mini-cart display (and legacy back-compat). 1886 name: (firstName + ' ' + lastName).trim(), 1887 company: (fd.get('participantCompany') || '').trim(), 1888 email: (fd.get('participantEmail') || '').trim(), 1889 phone: (fd.get('participantPhone') || '').trim(), 1890 notes: (fd.get('participantNotes') || '').trim(), 1891 }; 1892 1893 if (typeof window.alphadiAddBookingToCart === 'function') { 1894 window.alphadiAddBookingToCart(pending, participant); 1895 } 1896 closeModal(); 1897 });
1898})(); 1899</script>
1899 1900 1901 1902<div class="modal-overlay" id="requestModal"> 1903 <div class="modal" role="dialog" aria-modal="true" aria-labelledby="requestModalTitle"> 1904 <button type="button" class="modal__close" data-request-close aria-label="Close">×</button> 1905 <div class="modal__title" id="requestModalTitle">Request</div> 1906 <p style="font-family:var(--f-ui);font-size:0.875rem;color:var(--c-mid);margin-bottom:1.5rem;"> 1907 <strong id="requestModalProduct"></strong> 1908 </p> 1909 <form id="requestForm" novalidate> 1910 <input type="hidden" name="itemName" id="requestItemName" /> 1911 <div class="form-group"> 1912 <label class="form-label">First name *</label> 1913 <input type="text" class="form-input" name="firstName" required /> 1914 <div class="field-error"></div> 1915 </div> 1916 <div class="form-group"> 1917 <label class="form-label">Last name *</label> 1918 <input type="text" class="form-input" name="lastName" required /> 1919 <div class="field-error"></div> 1920 </div> 1921 <div class="form-group"> 1922 <label class="form-label">Company</label> 1923 <input type="text" class="form-input" name="company" /> 1924 <div class="field-error"></div> 1925 </div> 1926 <div class="form-group"> 1927 <label class="form-label">Email *</label> 1928 <input type="email" class="form-input" name="email" required /> 1929 <div class="field-error"></div> 1930 </div> 1931 <div class="form-group"> 1932 <label class="form-label">Phone *</label> 1933 <input type="tel" class="form-input" name="phone" required /> 1934 <div class="field-error"></div> 1935 </div> 1936 <div class="form-group"> 1937 <label class="form-label">Message</label> 1938 <textarea class="form-textarea" name="message" rows="3"></textarea> 1939 </div> 1940 <div id="requestFormStatus" style="display:none;margin-bottom:1rem;font-family:var(--f-ui);font-size:0.875rem;"></div> 1941 1942 <div class="checkout-check-field"> 1943 <label class="checkout-check-label"> 1944 <input type="checkbox" id="req-terms" name="terms" /> 1945 <span> 1946 I have read the 1947 <a href="/en/t&c" target="_blank" rel="noopener">Terms & Conditions</a> 1948 and agree to them. <span class="req">*</span> 1949 </span> 1950 </label> 1951 <span class="field-error fw-bold text-danger" id="reqTermsError"></span> 1952 </div> 1953 <div class="checkout-check-field"> 1954 <label class="checkout-check-label"> 1955 <input type="checkbox" id="req-privacy" name="privacy" /> 1956 <span> 1957 I have read the 1958 <a href="/en/privacy-policy" target="_blank" rel="noopener">Privacy Policy</a> 1959 and agree that my data will be processed. <span class="req">*</span> 1960 </span> 1961 </label> 1962 <span class="field-error fw-bold text-danger" id="reqPrivacyError"></span> 1963 </div> 1964 1965 <button type="submit" class="btn btn--primary" style="width:100%;justify-content:center;"> 1966 Send request 1967 </button> 1968 </form> 1969 </div> 1970</div> 1971
1972<script> 1973(function () { 1974 'use strict'; 1975 1976 var overlay = document.getElementById('requestModal'); 1977 var form = document.getElementById('requestForm'); 1978 var productEl = document.getElementById('requestModalProduct'); 1979 var itemNameEl = document.getElementById('requestItemName'); 1980 var statusEl = document.getElementById('requestFormStatus'); 1981 if (!overlay || !form) { return; } 1982 1983 var MSG_REQUIRED = "This field is required."; 1984 var MSG_EMAIL = "Please enter a valid e-mail address."; 1985 var MSG_SUCCESS = "Your request has been sent. We will get back to you shortly."; 1986 var MSG_ERROR = "Something went wrong. Please try again."; 1987 var MSG_TERMS = "You must agree to the Terms & Conditions to continue."; 1988 var MSG_PRIVACY = "You must agree to the Privacy Policy to continue."; 1989 1990 function isEmail(v) { return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test((v || '').trim()); } 1991 1992 function openModal(name) { 1993 if (productEl) { productEl.textContent = name || ''; } 1994 if (itemNameEl) { itemNameEl.value = name || ''; } 1995 form.reset(); 1996 if (itemNameEl) { itemNameEl.value = name || ''; } 1997 form.querySelectorAll('.is-invalid').forEach(function (el) { el.classList.remove('is-invalid'); }); 1998 form.querySelectorAll('.field-error').forEach(function (el) { el.textContent = ''; }); 1999 statusEl.style.display = 'none'; 2000 statusEl.textContent = ''; 2001 overlay.classList.add('is-open'); 2002 document.body.style.overflow = 'hidden'; 2003 setTimeout(function () { form.querySelector('[name=firstName]')?.focus(); }, 50); 2004 } 2005 2006 function closeModal() { 2007 overlay.classList.remove('is-open'); 2008 document.body.style.overflow = ''; 2009 } 2010 2011 overlay.addEventListener('click', function (e) { 2012 if (e.target === overlay) { closeModal(); } 2013 }); 2014 overlay.querySelectorAll('[data-request-close]').forEach(function (b) { 2015 b.addEventListener('click', closeModal); 2016 }); 2017 document.addEventListener('keydown', function (e) { 2018 if (e.key === 'Escape' && overlay.classList.contains('is-open')) { closeModal(); } 2019 }); 2020 2021 document.addEventListener('click', function (e) { 2022 var btn = e.target.closest('[data-open-request-modal]'); 2023 if (!btn) { return; } 2024 e.preventDefault(); 2025 openModal(btn.dataset.openRequestModal || ''); 2026 }); 2027 2028 // Per-date "By invoice" toggle â expands the inline note ("Inquire here â¦") within the 2029 // booking box; the link inside it opens this modal. 2030 document.addEventListener('click', function (e) { 2031 var toggle = e.target.closest('[data-invoice-toggle]'); 2032 if (!toggle) { return; } 2033 var item = toggle.closest('[data-date-item]'); 2034 if (item) { item.classList.toggle('is-open'); } 2035 }); 2036 2037 function showErr(field, msg) { 2038 field.classList.add('is-invalid'); 2039 var s = field.parentElement.querySelector('.field-error'); 2040 if (s) { s.textContent = msg; } 2041 } 2042 function clearErr(field) { 2043 field.classList.remove('is-invalid'); 2044 var s = field.parentElement.querySelector('.field-error'); 2045 if (s) { s.textContent = ''; } 2046 } 2047 function validate(field) { 2048 var val = (field.value || '').trim(); 2049 if (field.hasAttribute('required') && !val) { showErr(field, MSG_REQUIRED); return false; } 2050 if (field.type === 'email' && val && !isEmail(val)) { showErr(field, MSG_EMAIL); return false; } 2051 clearErr(field); return true; 2052 } 2053 2054 form.querySelectorAll('input, textarea').forEach(function (f) { 2055 f.addEventListener('blur', function () { validate(f); }); 2056 f.addEventListener('input', function () { if (f.classList.contains('is-invalid')) { clearErr(f); } }); 2057 }); 2058 2059 form.addEventListener('submit', function (e) { 2060 e.preventDefault(); 2061 var ok = true; 2062 form.querySelectorAll('input[required], input[type=email]').forEach(function (f) { 2063 if (!validate(f)) { ok = false; } 2064 }); 2065 2066 var termsCb = document.getElementById('req-terms'); 2067 var termsErr = document.getElementById('reqTermsError'); 2068 if (termsCb) { 2069 if (!termsCb.checked) { 2070 termsCb.classList.add('is-invalid'); 2071 if (termsErr) { termsErr.textContent = MSG_TERMS; } 2072 ok = false; 2073 } else { 2074 termsCb.classList.remove('is-invalid'); 2075 if (termsErr) { termsErr.textContent = ''; } 2076 } 2077 } 2078 2079 var privacyCb = document.getElementById('req-privacy'); 2080 var privacyErr = document.getElementById('reqPrivacyError'); 2081 if (!privacyCb.checked) { 2082 privacyCb.classList.add('is-invalid'); 2083 if (privacyErr) { privacyErr.textContent = MSG_PRIVACY; } 2084 ok = false; 2085 } else { 2086 privacyCb.classList.remove('is-invalid'); 2087 if (privacyErr) { privacyErr.textContent = ''; } 2088 } 2089 2090 if (!ok) { return; } 2091 2092 var submitBtn = form.querySelector('[type=submit]'); 2093 submitBtn.disabled = true; 2094 2095 var fd = new FormData(form); 2096 var payload = { 2097 itemName: (fd.get('itemName') || '').trim(), 2098 firstName: (fd.get('firstName') || '').trim(), 2099 lastName: (fd.get('lastName') || '').trim(), 2100 company: (fd.get('company') || '').trim(), 2101 email: (fd.get('email') || '').trim(), 2102 phone: (fd.get('phone') || '').trim(), 2103 message: (fd.get('message') || '').trim(), 2104 }; 2105 2106 fetch('/Home/SendRequest', { 2107 method: 'POST', 2108 headers: { 'Content-Type': 'application/json' }, 2109 body: JSON.stringify(payload), 2110 }) 2111 .then(function (r) { return r.json(); }) 2112 .then(function (data) { 2113 if (data.success) { 2114 if (data.redirectUrl) { 2115 window.location.href = data.redirectUrl; 2116 } else { 2117 statusEl.style.display = 'block'; 2118 statusEl.style.color = 'var(--c-green, green)'; 2119 statusEl.textContent = MSG_SUCCESS; 2120 form.querySelectorAll('input, textarea, button[type=submit]').forEach(function (el) { el.disabled = true; }); 2121 } 2122 } else { 2123 statusEl.style.display = 'block'; 2124 statusEl.style.color = 'var(--c-error, red)'; 2125 statusEl.textContent = data.message || MSG_ERROR; 2126 submitBtn.disabled = false; 2127 } 2128 }) 2129 .catch(function () { 2130 statusEl.style.display = 'block'; 2131 statusEl.style.color = 'var(--c-error, red)'; 2132 statusEl.textContent = MSG_ERROR; 2133 submitBtn.disabled = false; 2134 }); 2135 });
2136})(); 2137</script>
2137 2138 2139 2140<div class="modal-overlay" id="productFeatureModal"> 2141 <div class="modal" role="dialog" aria-modal="true" aria-labelledby="productFeatureModalTitle" style="max-width:560px;"> 2142 <button type="button" class="modal__close" data-pf-close aria-label="Close">×</button> 2143 <div class="modal__title" id="productFeatureModalTitle">Choose options</div> 2144 <p style="font-family:var(--f-ui);font-size:0.875rem;color:var(--c-mid);margin-bottom:1.25rem;"> 2145 <strong id="pfModalProduct"></strong> 2146 </p> 2147 2148 <div id="pfModalBody"></div> 2149 2150 <div style="display:flex;align-items:baseline;justify-content:space-between;gap:1rem;margin:1.25rem 0 1rem;padding-top:1rem;border-top:1px solid var(--c-border);"> 2151 <span style="font-family:var(--f-ui);font-size:0.8rem;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:var(--c-subtle);">Total</span> 2152 <span id="pfModalTotal" style="font-family:var(--f-display);font-size:1.75rem;font-weight:700;color:var(--c-orange);line-height:1;">0,00 €</span> 2153 </div> 2154 2155 <button type="button" id="pfModalSubmit" class="btn btn--primary" style="width:100%;justify-content:center;"> 2156 Add to cart 2157 </button> 2158 </div> 2159</div> 2160
2161<script> 2162(function () { 2163 'use strict'; 2164 2165 var overlay = document.getElementById('productFeatureModal'); 2166 if (!overlay) { return; } 2167 2168 var productEl = document.getElementById('pfModalProduct'); 2169 var bodyEl = document.getElementById('pfModalBody'); 2170 var totalEl = document.getElementById('pfModalTotal'); 2171 var submitBtn = document.getElementById('pfModalSubmit'); 2172 2173 var MSG_REQUIRED = 'Please select an option.'; 2174 2175 var pending = null; // { id, name, basePrice, image, shippableMap } 2176 var features = []; // [{ name, isRequired, options: [...] }] 2177 var selected = {}; // { [featureIndex]: { name, price, isShippable } } 2178 2179 function fmtPrice(v) { 2180 return window.formatPrice 2181 ? window.formatPrice(v) 2182 : '\u20AC' + (v < 0 ? '-' + Math.abs(v).toFixed(2) : v.toFixed(2)); 2183 } 2184 2185 // Build shippability lookup from raw DB JSON (PascalCase, all feature types). 2186 // Returns map[listFeatureIndex][optionIndex] = bool 2187 function buildShippableMap(rawJson) { 2188 var map = {}; 2189 try { 2190 var all = JSON.parse(rawJson || '[]'); 2191 var listIdx = 0; 2192 all.forEach(function (f) { 2193 if ((f.Type !== undefined ? f.Type : f.type) !== 0) { return; } 2194 var fi = listIdx++; 2195 map[fi] = {}; 2196 (f.Options || f.options || []).forEach(function (o, oi) { 2197 map[fi][oi] = !!(o.IsShippable || o.isShippable); 2198 }); 2199 }); 2200 } catch (e) {} 2201 return map; 2202 } 2203 2204 function recalcTotal() { 2205 var delta = 0; 2206 Object.keys(selected).forEach(function (k) { delta += selected[k].price; }); 2207 var total = Math.max(0, pending.basePrice + delta); 2208 totalEl.textContent = fmtPrice(total); 2209 return total; 2210 } 2211 2212 function renderBody() { 2213 selected = {}; 2214 if (!features.length) { bodyEl.innerHTML = ''; return; } 2215 var sm = (pending && pending.shippableMap) || {}; 2216 2217 bodyEl.innerHTML = features.map(function (f, fi) { 2218 var opts = (f.options || []).map(function (o, oi) { 2219 var deltaHtml = ''; 2220 if (o.price > 0) { deltaHtml = '<span class="product-fmt-card__delta">+' + fmtPrice(o.price) + '</span>'; } 2221 else if (o.price < 0) { deltaHtml = '<span class="product-fmt-card__delta product-fmt-card__delta--down">' + fmtPrice(o.price) + '</span>'; } 2222 2223 var badgeHtml = o.badgeText 2224 ? '<span class="product-fmt-card__badge">' + o.badgeText + '</span>' 2225 : ''; 2226 2227 var isShippable = !!(sm[fi] && sm[fi][oi]); 2228 var isDefault = !!o.isDefault; 2229 if (isDefault) { 2230 selected[fi] = { name: o.name, price: parseFloat(o.price) || 0, isShippable: isShippable }; 2231 } 2232 2233 return '<label class="product-fmt-card' + (isDefault ? ' is-selected' : '') + '"' + 2234 ' data-feature-index="' + fi + '"' + 2235 ' data-option-index="' + oi + '"' + 2236 ' data-option-name="' + (o.name || '').replace(/"/g, '"') + '"' + 2237 ' data-option-price="' + (parseFloat(o.price) || 0) + '"' + 2238 ' data-option-shippable="' + (isShippable ? 'true' : 'false') + '">' + 2239 '<input type="radio" name="pf-' + fi + '" ' + (isDefault ? 'checked' : '') + ' style="display:none">' + 2240 '<div class="product-fmt-card__name">' + (o.name || '') + ' ' + badgeHtml + '</div>' +
2241 (deltaHtml ? '<div class="product-fmt-card__meta">' + deltaHtml + '</div>' : '') + 2242 '</label>'; 2243 }).join(''); 2244 2245 return '<div class="product-fmt-group" data-feature-index="' + fi + '" data-feature-required="' + (f.isRequired ? 'true' : 'false') + '">' + 2246 '<div class="product-fmt-group__label">' + 2247 (f.name || '') + 2248 (f.isRequired ? '<span class="product-fmt-group__req" title="Required">*</span>' : '') + 2249 '</div>' + 2250 '<div class="product-fmt-grid">' + opts + '</div>' + 2251 '<div class="product-fmt-error"></div>' + 2252 '</div>'; 2253 }).join(''); 2254 } 2255 2256 function openModal(data, parsedFeatures, shippableMap) { 2257 pending = data; 2258 pending.shippableMap = shippableMap || {}; 2259 features = parsedFeatures || []; 2260 productEl.textContent = data.name || ''; 2261 renderBody(); 2262 recalcTotal(); 2263 overlay.classList.add('is-open'); 2264 document.body.style.overflow = 'hidden'; 2265 } 2266 2267 function closeModal() { 2268 overlay.classList.remove('is-open'); 2269 document.body.style.overflow = ''; 2270 pending = null; 2271 features = []; 2272 selected = {}; 2273 } 2274 2275 overlay.addEventListener('click', function (e) { 2276 if (e.target === overlay) { closeModal(); } 2277 }); 2278 overlay.querySelectorAll('[data-pf-close]').forEach(function (b) { 2279 b.addEventListener('click', closeModal); 2280 }); 2281 document.addEventListener('keydown', function (e) { 2282 if (e.key === 'Escape' && overlay.classList.contains('is-open')) { closeModal(); } 2283 }); 2284 2285 bodyEl.addEventListener('click', function (e) { 2286 var card = e.target.closest('.product-fmt-card'); 2287 if (!card) { return; } 2288 var fi = card.dataset.featureIndex; 2289 var group = card.closest('.product-fmt-group'); 2290 if (group) { 2291 group.querySelectorAll('.product-fmt-card').forEach(function (c) { c.classList.remove('is-selected', 'is-error'); }); 2292 var errEl = group.querySelector('.product-fmt-error'); 2293 if (errEl) { errEl.textContent = ''; } 2294 } 2295 card.classList.add('is-selected'); 2296 var input = card.querySelector('input[type=radio]'); 2297 if (input) { input.checked = true; } 2298 selected[fi] = { 2299 name: card.dataset.optionName, 2300 price: parseFloat(card.dataset.optionPrice) || 0, 2301 isShippable: card.dataset.optionShippable === 'true', 2302 }; 2303 recalcTotal(); 2304 }); 2305 2306 submitBtn.addEventListener('click', function () { 2307 if (!pending) { return; } 2308 2309 var ok = true; 2310 bodyEl.querySelectorAll('.product-fmt-group[data-feature-required="true"]').forEach(function (group) { 2311 var fi = group.dataset.featureIndex; 2312 var errEl = group.querySelector('.product-fmt-error'); 2313 if (!selected[fi]) { 2314 if (errEl) { errEl.textContent = MSG_REQUIRED; } 2315 group.querySelectorAll('.product-fmt-card').forEach(function (c) { c.classList.add('is-error'); }); 2316 ok = false; 2317 } 2318 }); 2319 if (!ok) { return; } 2320 2321 var finalPrice = recalcTotal(); 2322 var parts = []; 2323 features.forEach(function (f, fi) { if (selected[fi]) { parts.push(selected[fi].name); } }); 2324 var finalFormat = parts.join(', ') || (pending.format || ''); 2325 var isShippable = Object.values(selected).some(function (s) { return s.isShippable; }); 2326 2327 if (typeof window.alphadiAddProductToCart === 'function') { 2328 window.alphadiAddProductToCart({ 2329 id: pending.id, 2330 name: pending.name, 2331 price: finalPrice, 2332 format: finalFormat, 2333 image: pending.image, 2334 isShippable: isShippable, 2335 }); 2336 } 2337 closeModal(); 2338 });
2339 2340 // Intercept add-to-cart clicks for products that ship feature data. 2341 document.addEventListener('click', function (e) { 2342 var btn = e.target.closest('[data-add-to-cart][data-cart-type="product"]'); 2343 if (!btn) { return; } 2344 if (btn.disabled) { return; } 2345 2346 var raw = btn.dataset.cartFeatures; 2347 if (!raw) { return; } // no features â fall through to global handler 2348 2349 var parsed = null; 2350 try { parsed = JSON.parse(raw); } catch (_) { parsed = null; } 2351 if (!parsed || !parsed.length) { return; } 2352 2353 e.preventDefault(); 2354 e.stopImmediatePropagation(); 2355 2356 var shippableMap = buildShippableMap(btn.dataset.featuresRaw || ''); 2357 2358 openModal({ 2359 id: btn.dataset.addToCart, 2360 name: btn.dataset.cartName || btn.dataset.addToCart, 2361 basePrice: parseFloat(btn.dataset.cartPrice) || 0, 2362 format: btn.dataset.cartFormat || '', 2363 image: btn.dataset.cartImage || '', 2364 }, parsed, shippableMap); 2365 }, true); // capture phase â beat the global add-to-cart handler 2366})(); 2367</script>
2367 2368 2369 2370 <div style="display: none !important"> 2371 <a href="https://www.alphadi.org/de">Publications German</a> 2372 <a href="https://www.alphadi.org/en">Publications English</a> 2373 <a href="https://www.alphadi.org/es">Publications Spanish</a> 2374 <a href="https://www.alphadi.org/it">Publications Italian</a> 2375 <a href="https://www.alphadi.org/fr">Publications French</a> 2376 <a href="https://www.alphadi.org/pl">Publications Polish</a> 2377 <a href="https://www.alphadi.org/pt">Publications Portuguese</a> 2378 </div> 2379</body> 2380</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.