/* Isar Informatics — site component layer (nav CTA, hero, services, promise,
   testimonials, booking, footer, floating widgets, utility bar, dark mode).

   ---------------------------------------------------------------------------
   COLOUR RULE — read this before touching any colour in here.

   Two kinds of component live in this file:

   1. Theme-reactive (the default). Use the SEMANTIC tokens — --bg, --bg-elevated,
      --fg1/2/3, --border. These flip automatically in dark mode.

   2. Fixed-brand. A few components ARE "the dark editorial band" and must look
      identical in light and dark mode: .isar-promise-card and the credentials
      tiles (.cred-card). These use the RAW brand constants — --ink, --canvas,
      --sky — precisely because those don't flip.

   Using --bg-inverse/--fg-on-ink for group 2 is the trap: --bg-inverse flips to
   a LIGHT surface in dark mode while --fg-on-ink stays light, so the card washes
   out to cream-on-cream. That bug was introduced twice during the build.

   Also: raw --slate is 2.05:1 on --canvas. Never use it for text on a light
   background — it's for decorative marks and for labels sitting ON --ink.
   --------------------------------------------------------------------------- */

/* ---------- Whole-page background/text follow the theme tokens, so dark mode
   actually swaps the page background — not just component text color. ---------- */
body {
  background: var(--bg);
  color: var(--fg1);
}
/* Kadence's "boxed" content style hardcodes a white card background on
   .content-bg (the <article> wrapper), independent of body — without this
   override, dark mode swaps text to a light color on that still-white
   card and becomes unreadable. */
.content-bg {
  background: var(--bg) !important;
  color: var(--fg1);
  box-shadow: none !important;
}

/* ---------- Utility bar (search + account) ----------
   Identical 38x38 bordered icon buttons in a row: search, and the
   account icon (sign-in + settings when logged out; a real profile menu,
   including Einstellungen, when logged in -- see functions.php's
   wp_body_open hook). Starts fixed top-right as a safe default (in case
   the header isn't found yet), then site.js docks it inside the header
   row next to the nav. */
.isar-utility-bar {
  position: fixed;
  top: var(--sp-lg);
  right: var(--sp-lg);
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  gap: 4px;
}
.isar-utility-bar--docked {
  position: static;
  margin-left: var(--sp-lg);
}
.isar-search-toggle,
.isar-settings-toggle,
.isar-account-toggle,
.isar-home-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--fg2);
  cursor: pointer;
  font-family: var(--sans-mono);
  font-size: var(--fs-caption);
  text-decoration: none;
  transition: border-color var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out), background var(--dur-micro) var(--ease-out);
}
/* Hit area only -- these stay 38px visually (the panel-centering maths in
   .isar-account-panel is measured against that width, and the header's
   density is deliberate), but a centred
   pseudo-element extends the pointer/touch target to the 44px minimum
   without moving anything on screen. Same trick applied to Kadence's own
   mobile drawer toggle further down. */
.isar-search-toggle,
.isar-settings-toggle,
.isar-account-toggle,
.isar-home-toggle {
  position: relative;
}
.isar-search-toggle::before,
.isar-settings-toggle::before,
.isar-account-toggle::before,
.isar-home-toggle::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}
.isar-search-toggle:hover,
.isar-settings-toggle:hover,
.isar-account-toggle:hover,
.isar-home-toggle:hover {
  /* Same hover treatment as the dropdown's own items (.sub-menu a:hover),
     for a consistent selection colour across the header's interactive
     chrome. */
  border-color: var(--fg3);
  background: var(--bg-accent);
  color: var(--fg-on-sky);
}
/* ---------- Portal/Akademie header: no Home/Leistungen/Über uns text nav.
   The shared site header lives in Kadence's parent theme (no local
   header.php to edit, and Kadence Pro's per-page header builder was
   ruled out earlier) -- scoped entirely by the body template class WP
   already adds, the same way the booking widget is excluded from
   specific pages elsewhere in this codebase. .isar-home-toggle (added
   to the utility bar only on these two templates, see functions.php's
   wp_body_open hook) is the replacement way back to the main site.
   The mobile drawer's hamburger toggle is hidden too, not just its nav
   content -- that drawer holds nothing else, so leaving the toggle
   visible would open a genuinely empty panel. */
body.page-template-template-portal-php .site-header-item-main-navigation,
body.page-template-template-akademie-php .site-header-item-main-navigation,
body.page-template-template-portal-php .site-header-item-mobile-navigation,
body.page-template-template-akademie-php .site-header-item-mobile-navigation,
body.page-template-template-portal-php .site-header-item-navgation-popup-toggle,
body.page-template-template-akademie-php .site-header-item-navgation-popup-toggle {
  display: none;
}

/* Shared with .isar-faq-search's focus-glow further down this file — keep
   these even though the nav search itself no longer uses the glow. */
@keyframes isar-search-spin {
  to { --isar-search-angle: 360deg; }
}
@property --isar-search-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

/* ---------- Search: collapsed icon button by default; clicking expands
   an input to the LEFT of the button (anchored by its right edge so
   growth reads as "opening leftward" rather than dropping down), reusing
   the existing type-ahead results logic in site.js. The width animation
   lives on .isar-search-collapse specifically, not the outer .isar-search
   panel, so the absolutely-positioned results dropdown (a sibling inside
   .isar-search) isn't clipped by the collapse's own overflow:hidden. ---------- */
.isar-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
}
.isar-search {
  position: absolute;
  top: 50%;
  right: calc(100% + 4px);
  transform: translateY(-50%);
}
.isar-search-collapse {
  width: 0;
  overflow: hidden;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  transition: width var(--dur-comp) var(--ease-out), border-color var(--dur-comp) var(--ease-out);
  white-space: nowrap;
}
.isar-search-wrap.is-open .isar-search-collapse {
  width: 220px;
  border-color: var(--sky);
}
.isar-search-wrap.is-open .isar-search-toggle {
  border-color: var(--sky);
  background: var(--bg-accent);
  color: var(--fg-on-sky);
}
.isar-search-input {
  width: 220px;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  color: var(--fg1);
  padding: var(--sp-sm) var(--sp-md);
}
.isar-search-input::placeholder {
  color: var(--fg4);
}

/* ---------- Settings/account dropdown shared parts: .isar-settings-group/
   -item/-divider are reused by .isar-account-panel below (the standalone
   gear icon that used to share this geometry is gone -- Einstellungen now
   lives inside the account panel itself, see functions.php's wp_body_open
   hook). ---------- */
.isar-settings-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.isar-settings-divider {
  height: 1px;
  background: var(--border);
  margin: var(--sp-xs) 0;
}
.isar-settings-item {
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
  width: 100%;
  border: none;
  background: none;
  color: var(--fg2);
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  text-decoration: none;
  text-align: left;
  padding: var(--sp-sm) var(--sp-md);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.isar-settings-item:hover {
  background: var(--bg-accent);
  color: var(--fg-on-sky);
}
/* Both languages / both themes are listed at once now (not a single
   toggle showing only the inactive option), so the active one needs its
   own marked state. */
.isar-settings-item.is-selected {
  color: var(--fg1);
  font-weight: 500;
  cursor: default;
}
.isar-settings-item.is-selected::after {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: var(--radius-full);
  background: var(--sky);
  margin-left: auto;
  flex: 0 0 auto;
}

/* ---------- Account icon: sign-in + settings, or (logged in) a real
   profile menu -- both states share this one panel geometry. Reuses
   .isar-settings-group/.isar-settings-item for the menu itself. ---------- */
.isar-account-wrap {
  position: relative;
}
.isar-account-panel {
  /* Centered under its own toggle button now that there's no separate
     settings icon next to it to share this spot with. */
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: 190px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-floating);
  padding: var(--sp-xs);
  display: none;
}
.isar-account-wrap.is-open .isar-account-panel {
  display: block;
}
.isar-account-wrap.is-open .isar-account-toggle {
  border-color: var(--sky);
  background: var(--bg-accent);
  color: var(--fg-on-sky);
}

/* ---------- Header: branded background + logo ---------- */
#main-header,
.site-header-wrap {
  background: transparent !important;
}
/* Sticky + translucent while scrolling, with a blur so content passing
   underneath doesn't clash with the logo/nav. Border only on the
   outermost element — #main-header/.site-header-wrap is the same element
   nested directly inside .site-header, so applying the border-bottom to
   all three stacked two 1px lines into a visually thicker divider than
   the footer's single one. */
.site-header {
  position: sticky !important;
  top: 0 !important;
  z-index: var(--z-sticky);
  background: color-mix(in oklab, var(--bg) 85%, transparent) !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
  /* Full-bleed at the top (flush with the viewport edge, nothing to round
     against), so only the bottom edge — where the header meets scrolling
     page content — gets rounded. No overflow:hidden here: the mega
     dropdown, search popup and settings panel all need to render outside
     this box; background-clip already respects border-radius on its own. */
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}
.site-title-wrap {
  display: flex;
  align-items: center;
}
.isar-logo {
  display: block;
  /* Matches the footer's own logo size. */
  height: 56px;
  width: auto;
}
/* Legacy <img> variants. No longer emitted — the logo is inline SVG now — but
   the rules are kept so the standalone wordmark files still behave if reused. */
.isar-logo-dark {
  display: none !important;
}
[data-theme="dark"] .isar-logo-light {
  display: none !important;
}
[data-theme="dark"] .isar-logo-dark {
  display: block !important;
}

/* ---------- Inline wordmark ----------
   One SVG for both themes: only the plate outline and the text colour differ.
   The waves sit on the dark plate in either theme, so they keep fixed brand
   colours rather than semantic tokens. */
.isar-logo--inline .plate {
  fill: var(--ink);
  stroke: transparent;
  stroke-width: 2;
}
:root[data-theme="dark"] .isar-logo--inline .plate {
  stroke: var(--canvas);
}
.isar-logo--inline .wave {
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
}
.isar-logo--inline .wave-1 { stroke: var(--sky); }
.isar-logo--inline .wave-2 { stroke: var(--slate); }
.isar-logo--inline .wave-3 { stroke: var(--canvas); }
.isar-logo--inline .wm {
  font-family: var(--serif-display);
  font-size: 34px;
  letter-spacing: -0.4px;
  fill: var(--fg1);
}
/* Waves drift in alternating directions on hover — the river, briefly moving.
   2px keeps every stroke inside the plate, and it never loops. */
@media (prefers-reduced-motion: no-preference) {
  .isar-logo--inline .wave {
    transition: transform 400ms ease-out;
  }
  .isar-logo--inline:hover .wave-1 { transform: translateX(2px); }
  .isar-logo--inline:hover .wave-2 { transform: translateX(-2px); }
  .isar-logo--inline:hover .wave-3 { transform: translateX(2px); }
}

/* ---------- Kadence's built-in page-title band ----------
   Hardcodes a pale blue-gray background independent of our tokens. */
.entry-hero-container-inner {
  background: var(--bg) !important;
}
.entry-hero .entry-title {
  color: var(--fg1);
}

/* ---------- Dropdown submenu: same rounding as the CTA button ---------- */
.sub-menu {
  border-radius: var(--radius-md) !important;
  overflow: hidden;
  border: 1px solid var(--border) !important;
  background: var(--bg) !important;
  box-shadow: var(--shadow-floating) !important;
  padding: var(--sp-xs) !important;
}
.sub-menu a {
  border-radius: var(--radius-sm) !important;
  transition: background var(--dur-micro) var(--ease-out), color var(--dur-micro) var(--ease-out) !important;
}
.sub-menu a:hover {
  background: var(--bg-accent) !important;
  color: var(--fg-on-sky) !important;
}

/* ---------- Mega-dropdown (Leistungen/Services): progressive enhancement
   of the same .sub-menu, added by site.js. Falls back to the plain stacked
   list above 900px-down or with JS disabled — the real links never change.

   Every container-level property here needs !important: Kadence's own
   dropdown CSS sets `.sub-menu { display: block !important; }` (and similar)
   to force its plain stacked-list behavior open/closed, which otherwise
   silently wins over an un-flagged `display: grid` — confirmed via
   getComputedStyle() on the live site (display resolved to "block", not
   "grid", collapsing every item to a full-width row).

   IMPORTANT: display must stay conditional, not an unconditional
   `!important` grid (an earlier version did that and permanently beat
   Kadence's own closed-state `display: none` on every page load).

   The actual trigger took two rounds to get right:
   1st attempt kept it open via .menu-item--toggled-on, which turned out to
   only ever be ADDED by Kadence's JS, never removed on a second click — so
   it's not a reliable "is it open" signal.
   2nd attempt switched to :has(button[aria-expanded="true"]), which DOES
   toggle correctly — but only covers keyboard/programmatic activation.
   Checking getComputedStyle(toggleButton).pointerEvents on the live site
   showed Kadence sets `pointer-events: none` on that chevron button
   deliberately (confirmed in its own shipped CSS) — it's a keyboard-only
   affordance, a real mouse click on it passes straight through to the
   underlying "Leistungen" link and just navigates. So aria-expanded alone
   left mouse users with no way to open it at all. :hover and :focus-within
   are added back for that reason; unlike the very first broken version,
   there's no stuck-open risk here because a mouse user can't click that
   button to begin with, so the earlier "focus lingers after a close-click"
   failure mode never arises through :hover. */
@media (min-width: 901px) {
  /* Kit's own docs mockup renders this panel at the SAME width as the
     site's real content container (measured live: .content-container.
     site-container maxes out at 1290px) — confirmed by opening the kit
     file and comparing header/container widths side-by-side at matching
     viewports (1263px kit vs 1265px live at a 1280px viewport).

     IMPORTANT: the panel must stay anchored to the TRIGGER LI, not to
     the header. An earlier version switched the li to `position: static`
     so the panel could center on `header.site-header` instead — that
     made the panel visually wide and centered, but broke opening it:
     :hover only holds while the pointer is over the li or one of its
     DOM descendants, and once the panel's box no longer overlaps the
     li's own box, moving the mouse from the (narrow) li down to the
     (wide, header-centered) panel crosses the header's plain background
     first — which isn't part of the li's hover subtree — so :hover on
     the li dropped to false and the panel closed via `display: none`
     before the cursor ever reached it. Anchoring to the li instead (top:
     100% of the LI, centered via translateX(-50%) on the LI's own
     centre) keeps the panel's top edge touching the li's bottom edge
     with zero gap, so the pointer never crosses anything outside the
     li's subtree while moving straight down into it. */
  #primary-menu > li:has(> .sub-menu.isar-mega) {
    position: relative;
  }
  /* Invisible hover bridge (site.js) spanning the gap between the LI's own
     bottom and the header's true bottom edge, so the dropdown can sit
     flush with the header (see the panel's own top: calc rule) without
     breaking the mouse-hover path through that gap. Height set per-instance
     by JS; position:absolute keeps it out of flow so it can't affect the
     LI's own flex-centered height. */
  .isar-mega-hover-bridge {
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
  }
  .sub-menu.isar-mega {
    display: none !important;
  }
  #primary-menu > li:hover > .sub-menu.isar-mega,
  #primary-menu > li:focus-within > .sub-menu.isar-mega,
  li:has(> button[aria-expanded="true"]) > .sub-menu.isar-mega {
    position: absolute !important;
    top: 100% !important;
    left: 50% !important;
    right: auto !important;
    transform: translateX(-50%) !important;
    margin: 0 !important;
    padding: 0 !important;
    width: min(1290px, calc(100vw - 32px)) !important;
    max-width: calc(100vw - 32px) !important;
    display: grid !important;
    grid-template-columns: repeat(4, 1fr) 260px !important;
    gap: 0 !important;
    background: var(--bg) !important;
    border: 1px solid var(--border) !important;
    /* No top border/radius: the panel sits with zero gap directly under
       the header's own bottom border, so a second border line right there
       would double up into a visibly thicker seam. Square top corners
       read as a clean, single-line extension of the navbar; only the
       bottom corners (the panel's own free edge) get rounded. */
    border-top: none !important;
    border-radius: 0 0 var(--radius-md) var(--radius-md) !important;
    overflow: hidden !important;
  }
  /* Solid, opaque dividers between cells instead of a background-through-
     gap trick — the gap approach depends on every cell having a fully
     opaque background to read as a clean hairline, and any gap in that
     (a semi-transparent surface, a cell that doesn't fill its track)
     shows as a "transparent" seam with page content behind it visible
     through the dropdown. Explicit borders can't do that. */
  .sub-menu.isar-mega > li {
    margin: 0 !important;
    width: auto !important;
    min-width: 0;
    background: var(--bg);
  }
  .sub-menu.isar-mega .isar-mega-link {
    position: relative;
    display: flex !important;
    flex-direction: column;
    gap: var(--sp-xs);
    height: 100%;
    width: auto !important;
    padding: var(--sp-lg) var(--sp-lg) !important;
    border-radius: 0 !important;
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
  }
  .sub-menu.isar-mega > li:nth-child(4n) .isar-mega-link {
    border-right: none;
  }
  .sub-menu.isar-mega .isar-mega-num {
    font-family: var(--sans-mono);
    font-size: var(--fs-micro);
    letter-spacing: var(--tracking-caps);
    color: var(--fg3);
  }
  .sub-menu.isar-mega .isar-mega-name {
    font-family: var(--serif-display);
    font-size: var(--fs-heading-sm);
    color: var(--fg1);
  }
  /* Carries each service's own hero/spotlight-card glyph into the nav
     dropdown too, so "Leistungen" reads as eight distinct services at a
     glance instead of a plain numbered text list — matches the same
     always-slate, decorative-only icon convention used everywhere else. */
  .sub-menu.isar-mega .isar-mega-icon {
    position: absolute;
    top: var(--sp-lg);
    right: var(--sp-lg);
    width: 20px;
    height: 20px;
    color: var(--slate);
    pointer-events: none;
  }
  .isar-mega-promo {
    /* grid-row is set inline by site.js (1/span 1 for a 4-item menu like
       Über uns, 1/span 2 for an 8-item one like Leistungen) since it has
       to match the actual item count, not a fixed guess. */
    grid-column: 5;
    width: auto !important;
  }
}
.isar-mega-promo {
  /* !important: needed to beat .sub-menu.isar-mega > li's background rule,
     which has higher specificity (2 classes + element vs. 1 class here).
     Theme-reactive (ink in light, canvas in dark -- per request, the
     opposite pairing of what the raw token names might suggest) so the
     CTA button's own theme-flipped colour below always has a contrasting
     panel to sit on. */
  background: var(--ink) !important;
  padding: var(--sp-xl);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
:root[data-theme="dark"] .isar-mega-promo {
  background: var(--canvas) !important;
}
.isar-mega-promo-eyebrow {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--slate);
  margin: 0 0 var(--sp-md);
}
.isar-mega-promo-title {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  line-height: var(--lh-snug);
  color: var(--canvas);
  margin: 0;
}
:root[data-theme="dark"] .isar-mega-promo-title {
  color: var(--ink);
}
.isar-mega-promo-cta {
  align-self: flex-start;
  margin-top: var(--sp-lg);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  text-decoration: none;
  padding: var(--sp-sm) var(--sp-lg);
  border-radius: var(--radius-sm);
  transition: background var(--dur-micro) var(--ease-out);
  /* Light mode: canvas-on-ink. Dark mode below flips to ink-on-canvas —
     both contrast correctly since .isar-mega-promo's own background
     flips the opposite way in each theme (see above). */
  color: var(--ink);
  background: var(--canvas);
}
.isar-mega-promo-cta:hover {
  background: color-mix(in oklab, var(--canvas) 85%, var(--ink) 15%);
}
:root[data-theme="dark"] .isar-mega-promo-cta {
  color: var(--canvas);
  background: var(--ink);
}
:root[data-theme="dark"] .isar-mega-promo-cta:hover {
  background: color-mix(in oklab, var(--ink) 85%, var(--canvas) 15%);
}

/* ---------- Live search results dropdown ---------- */
.isar-search-results {
  display: none;
  position: absolute;
  top: calc(100% + var(--sp-sm));
  right: 0;
  min-width: 260px;
  max-width: 340px;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg);
  box-shadow: var(--shadow-floating);
  overflow: hidden;
  z-index: var(--z-pop, 800);
}
.isar-search-results.is-open {
  display: block;
}
.isar-search-results a {
  display: flex;
  align-items: baseline;
  gap: var(--sp-md);
  padding: var(--sp-md) var(--sp-lg);
  text-decoration: none;
  border-bottom: 1px solid var(--border);
  transition: background var(--dur-micro) var(--ease-out);
}
.isar-search-results a:last-child {
  border-bottom: none;
}
.isar-search-results a:hover {
  background: var(--bg-accent);
}
.isar-search-results a:hover .isar-search-result-title {
  color: var(--fg-on-sky);
}
.isar-search-result-kind {
  flex: 0 0 auto;
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
}
.isar-search-result-title {
  font-size: var(--fs-body-sm);
  color: var(--fg1);
}

/* ---------- Center the nav in the header, matching the kit's header row
   (logo — nav centered — controls). The flex:1+justify-content:center
   approach centers the nav links only within their OWN zone's box — and
   that zone turned out not to be symmetric: measured live, the logo zone
   ends around x=147 but the nav zone doesn't start until x=480 (Kadence
   reserves extra space ahead of it), while the controls zone on the
   right is a tight 122px. Centering inside that lopsided middle zone
   put the nav links visibly right of the header's true center. Taking
   the nav fully out of flex flow and centering it absolutely against
   the header itself is centering that can't be thrown off by how wide
   the logo/controls zones happen to be. */
@media (min-width: 901px) {
  .site-header-item-main-navigation {
    position: absolute !important;
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%, -50%) !important;
    flex: 0 0 auto !important;
  }
}

/* ---------- Top-level nav links: one unified color at rest, the old
   Leistungen/Über uns gray as the hover feedback (was: current-page "Home"
   in dark ink, other items in a lighter gray — now unified to ink, with
   that same gray reserved for :hover). ---------- */
#primary-menu > li:not(.menu-item-cta) > a {
  color: var(--fg1) !important;
}
#primary-menu > li:not(.menu-item-cta) > a:hover {
  color: var(--fg2) !important;
}
/* Defensive dark-mode override: the current-page ("Home") link was
   measured resolving to the raw light-mode --ink value even with
   data-theme="dark" set and --fg1 itself correctly resolving to the
   dark value at that exact element — a var()-in-!important cascade
   quirk that didn't reproduce for any other themed element on the
   page. Hardcoding the dark value directly, scoped to dark mode, sidesteps
   whatever that is rather than depending on var(--fg1) resolving
   correctly for this one selector. */
:root[data-theme="dark"] #primary-menu > li:not(.menu-item-cta) > a {
  color: #F1ECE2 !important;
}
:root[data-theme="dark"] #primary-menu > li:not(.menu-item-cta) > a:hover {
  color: #C9C3B5 !important;
}

/* ---------- Nav CTA button ---------- */
.menu-item-cta > a {
  background: var(--ink) !important;
  color: var(--fg-on-ink) !important;
  border: 1px solid var(--fg-on-ink) !important;
  border-radius: var(--radius-sm) !important;
  padding: var(--sp-sm) var(--sp-lg) !important;
  transition: background var(--dur-micro) var(--ease-out);
}
.menu-item-cta > a:hover {
  background: var(--ink-deep) !important;
}

/* ---------- Motion ----------
   Restrained by intent: ~300ms, 6-8px of travel, no overshoot. All of it sits
   behind prefers-reduced-motion, and the scroll-reveal class is only applied
   by JS so content is never hidden if JS fails to run. */
@media (prefers-reduced-motion: no-preference) {
  .isar-reveal {
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 340ms ease-out, transform 340ms ease-out;
    transition-delay: var(--isar-reveal-delay, 0ms);
  }
  .isar-reveal.is-visible {
    opacity: 1;
    transform: none;
  }

  /* Hero entrance. Delays stay tight because the h1 is an LCP candidate —
     an element at opacity 0 does not count as painted. */
  .isar-hero--photo .isar-hero-photo-content > * {
    animation: isar-rise-in 280ms ease-out backwards;
  }
  .isar-hero--photo .isar-hero-photo-content > :nth-child(1) { animation-delay: 0ms; }
  .isar-hero--photo .isar-hero-photo-content > :nth-child(2) { animation-delay: 60ms; }
  .isar-hero--photo .isar-hero-photo-content > :nth-child(3) { animation-delay: 120ms; }
  .isar-hero--photo .isar-hero-photo-content > :nth-child(4) { animation-delay: 180ms; }
}
@keyframes isar-rise-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* Card hover: colour shift only — no lift, no scale, no drop shadow, per
   the design system's "the card stays put" rule. The cursor-following
   radial-gradient glow that used to live here (::before, driven by
   --mx/--my/--spot custom properties) was removed per request; --spot
   itself stays (site.js still sets it on mouseenter/leave) since
   .svc-icon's own hover-reveal further down this file still uses it. */
.svc,
.cred-pill,
.team-member {
  position: relative;
  overflow: hidden;
  transition: border-color var(--dur-comp, 240ms) var(--ease-out, ease-out);
}
.svc:hover,
.svc:focus-within,
.team-member:hover {
  border-color: var(--border-strong);
}
/* .cred-pill sits on the dark --ink credentials band, where --border-strong
   (ink-based) would be invisible — same contrast trap as the fixed-vs-theme
   collision documented elsewhere in this file. Use a sky-based hover instead. */
.cred-pill:hover {
  border-color: color-mix(in oklab, var(--sky) 60%, transparent);
}

/* ---------- Hero ---------- */
.isar-hero {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-section) var(--sp-xl);
  text-align: center;
}
.isar-hero .badge {
  display: inline-block;
  font-family: var(--sans-body);
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
  background: var(--bg-accent);
  border-radius: var(--radius-full);
  padding: var(--sp-xs) var(--sp-lg);
  margin-bottom: var(--sp-lg);
}
.isar-hero h1 {
  font-family: var(--serif-display);
  font-size: clamp(2.25rem, 5vw, var(--fs-display-xl));
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-display-xl);
  color: var(--fg1);
  max-width: 18ch;
  margin: 0 auto var(--sp-xl);
  text-wrap: balance;
}
.isar-hero .lede {
  font-size: var(--fs-body-lg);
  line-height: var(--lh-relaxed);
  color: var(--fg2);
  max-width: var(--container-prose);
  margin: 0 auto var(--sp-xxl);
}
.isar-hero .cta-row {
  display: flex;
  gap: var(--sp-lg);
  justify-content: center;
  flex-wrap: wrap;
}
/* Photo hero (Home): fixed brand-light styling like the promise card is
   fixed brand-navy — the artwork is a warm cream illustration, so this
   section deliberately doesn't invert with dark mode. Text sits over the
   image's own blank left-hand area; the scrim guarantees legibility even
   when that area gets cropped at narrow widths. */
/* Faint dot-field texture (6% opacity, two dot sizes) — reads as paper
   grain, not decoration, per the design system's "kaum sichtbar, genau
   richtig" rule. CSS-only, no image request. */
.isar-hero--photo {
  --isar-hero-edge: #F1F1EF;
  --isar-hero-light-image: url("hero-munich-light.webp");
  --isar-hero-dark-image: url("hero-munich-dark.webp");
  position: relative;
}
:root[data-theme="dark"] .isar-hero--photo {
  --isar-hero-edge: #1B212B;
}
.isar-hero--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.06;
  background-image:
    radial-gradient(circle, var(--ink) 1px, transparent 1px),
    radial-gradient(circle, var(--ink) 1px, transparent 1px);
  background-size: 28px 28px, 28px 28px;
  background-position: 0 0, 14px 14px;
}
:root[data-theme="dark"] .isar-hero--photo::before {
  background-image:
    radial-gradient(circle, var(--canvas) 1px, transparent 1px),
    radial-gradient(circle, var(--canvas) 1px, transparent 1px);
}
.isar-hero--photo .isar-hero-photo-content {
  position: relative;
  z-index: 3;
}

.isar-hero--photo {
  text-align: left;
  /* --border (12% ink) composited to rgb(227,228,229) against a rgb(231,232,228)
     page — 1.03:1, i.e. invisible. The scrim starts at full --canvas, so at the
     left edge the frame has the same colour on both sides and needs real
     contrast to read at all. 50% ink gives 3.07:1, meeting the WCAG 1.4.11
     non-text minimum while still reading as a hairline.
     Dark mode needs the opposite treatment: the artwork stays light and the
     page goes dark, so the edge is already high-contrast and only wants a
     light hairline to define the radius. */
  border: 1px solid color-mix(in oklab, var(--ink) 50%, transparent);
  border-radius: var(--radius-md);
  overflow: hidden;
  background-size: cover;
  background-position: center;
  min-height: clamp(320px, 42vw, 460px);
  display: flex;
  align-items: center;
  padding: var(--sp-xxl);
}
.isar-hero--photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(to right, var(--isar-hero-edge) 0, transparent clamp(80px, 10vw, 150px), transparent calc(100% - clamp(42px, 5vw, 82px)), var(--isar-hero-edge) 100%),
    linear-gradient(to bottom, var(--isar-hero-edge) 0, transparent clamp(34px, 5vw, 68px), transparent calc(100% - clamp(34px, 5vw, 68px)), var(--isar-hero-edge) 100%);
}
/* Image URLs are relative to THIS stylesheet (assets/site.css), so they resolve
   against assets/ without needing the theme URI injected from PHP.
   Two declarations: the plain url() one is the universal fallback; the
   image-set() one wins where supported and serves WebP (161KB vs 275KB on the
   LCP element). A browser that can't parse image-set()/type() drops that
   declaration at parse time and keeps the first.
   NB: do NOT reference an undefined custom property here. Unlike a
   parse-error, an unresolvable var() invalidates the declaration at
   computed-value time and yields `none` — which blanks the hero entirely
   instead of falling back to the previous declaration. */
.isar-hero--photo {
  background-image:
    linear-gradient(to right, var(--canvas) 0%, color-mix(in oklab, var(--canvas) 65%, transparent) 40%, transparent 65%),
    url("hero-munich-bg.jpg");
  background-image:
    linear-gradient(to right, var(--canvas) 0%, color-mix(in oklab, var(--canvas) 65%, transparent) 40%, transparent 65%),
    image-set(
      url("hero-munich-bg.webp") type("image/webp"),
      url("hero-munich-bg.jpg") type("image/jpeg")
    );
}
:root[data-theme="dark"] .isar-hero--photo {
  border-color: color-mix(in oklab, var(--canvas) 40%, transparent);
}
.isar-hero--photo .isar-hero-photo-content {
  max-width: 46%;
}
.isar-hero--photo .badge {
  background: var(--sky);
  color: var(--ink-mute);
}
.isar-hero--photo h1 {
  font-size: clamp(1.5rem, 2.6vw, 2.5rem);
  max-width: none;
  margin: 0 0 var(--sp-md);
  color: var(--ink);
}
.isar-hero--photo .lede {
  max-width: none;
  margin: 0 0 var(--sp-lg);
  color: var(--ink-mute);
  font-size: var(--fs-body-md);
}
.isar-hero--photo .cta-row {
  justify-content: flex-start;
}
/* The photo hero deliberately never inverts with dark mode (see the .isar-
   hero--photo comment above) — h1/lede already use the fixed --ink/--ink-
   mute constants for that reason. The ghost CTA was missed: it fell through
   to the global .isar-btn.ghost rule, which uses the theme-reactive --fg1/
   --border-strong. In dark mode those resolve to light colours, rendering
   near-invisible against this section's permanently-light photo scrim.
   Found by toggling dark mode and screenshotting the live homepage hero. */
.isar-hero--photo .isar-btn.ghost {
  color: var(--ink);
  border-color: color-mix(in oklab, var(--ink) 30%, transparent);
}
.isar-hero--photo .isar-btn.ghost:hover {
  background: color-mix(in oklab, var(--ink) 8%, transparent);
}

/* ---------- Dark motif hero: the 8 service detail pages' distinct
   identity. Same box/radius/padding contract as the photo hero, but no
   photography — a large faded service glyph stands in for it (kit's Hero
   Variant C: "kein Foto, [Motiv] trägt die Fläche"). One glyph per service,
   always --slate, never --ink — matches the ASCII-system rule. ---------- */
.isar-hero--motif {
  text-align: left;
  position: relative;
  overflow: hidden;
  background: var(--ink);
  border-radius: var(--radius-md);
  min-height: clamp(320px, 42vw, 460px);
  display: flex;
  align-items: center;
  padding: var(--sp-xxl);
}
.isar-hero--motif .isar-hero-photo-content {
  position: relative;
  max-width: 62%;
}
.isar-hero--motif .isar-motif-icon {
  position: absolute;
  right: -30px;
  bottom: -30px;
  width: clamp(160px, 22vw, 320px);
  height: clamp(160px, 22vw, 320px);
  color: var(--slate);
  opacity: 0.5;
  pointer-events: none;
}
/* Infrastruktur only: "eine Lampe wechselt" — the rack glyph's two LED
   dots blink on staggered, slow intervals (kit's "Rack-LEDs" idle motion,
   one designated use case). Scoped via WordPress's automatic page-id-N body
   class, so it needs no page-content change and can't drift to other pages. */
body.page-id-70 .isar-motif-icon circle,
body.page-id-71 .isar-motif-icon circle {
  animation: isar-rack-blink 3.4s ease-in-out infinite;
}
body.page-id-70 .isar-motif-icon circle:nth-of-type(2),
body.page-id-71 .isar-motif-icon circle:nth-of-type(2) {
  animation-delay: 1.1s;
}
@keyframes isar-rack-blink {
  0%, 80%, 100% { opacity: 1; }
  88%, 94% { opacity: 0.2; }
}
@media (prefers-reduced-motion: reduce) {
  body.page-id-70 .isar-motif-icon circle,
  body.page-id-71 .isar-motif-icon circle {
    animation: none;
  }
}

.isar-hero--motif .badge {
  background: transparent;
  border: 1px solid color-mix(in oklab, var(--canvas) 22%, transparent);
  color: var(--sky);
}
.isar-hero--motif h1 {
  font-size: clamp(1.5rem, 2.6vw, 2.5rem);
  max-width: none;
  margin: 0 0 var(--sp-md);
  color: var(--canvas);
}
.isar-hero--motif .lede {
  max-width: none;
  margin: 0 0 var(--sp-lg);
  color: var(--sky);
  font-size: var(--fs-body-md);
}
.isar-hero--motif .cta-row {
  justify-content: flex-start;
}
.isar-hero--motif .isar-btn.primary {
  background: var(--canvas);
  color: var(--ink);
}
.isar-hero--motif .isar-btn.primary:hover {
  background: color-mix(in oklab, var(--canvas) 85%, var(--ink) 15%);
}
.isar-hero--motif .isar-btn.ghost {
  color: var(--canvas);
  border-color: color-mix(in oklab, var(--canvas) 28%, transparent);
}
@media (max-width: 640px) {
  .isar-hero--motif {
    min-height: 0;
    padding: var(--sp-xl);
  }
  .isar-hero--motif .isar-hero-photo-content {
    max-width: 100%;
  }
  .isar-hero--motif .isar-motif-icon {
    width: 120px;
    height: 120px;
    opacity: 0.25;
  }
}

/* ---------- Homepage hero: the kit's own homepage example uses a
   DIFFERENT dark hero than the service pages' single-glyph motif — no
   photography, and the type scale is the site's largest (this is the
   one hero that gets full display-xl treatment, not the smaller
   service-page clamp). The kit's version also has an ASCII wave filling
   the background; dropped here — it rendered as a squashed, illegible
   block instead of a wide flowing pattern (the column-count sizing
   depends on the hero's rendered width, which wasn't reliably available
   when the paint ran) and wasn't worth the added complexity to debug. ---------- */
.isar-hero--home {
  --isar-hero-edge: #F1F1EF;
  position: relative;
  overflow: hidden;
  background-color: var(--isar-hero-edge);
  border-radius: var(--radius-md);
  padding: clamp(56px, 9vw, 104px) clamp(28px, 5vw, 48px);
}
:root[data-theme="dark"] .isar-hero--home {
  --isar-hero-edge: #1B212B;
}
.isar-hero--home .isar-hero-photo-content {
  position: relative;
  z-index: 3;
  max-width: 640px;
}
.isar-hero--home::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(to right, var(--isar-hero-edge) 0, transparent clamp(90px, 12vw, 180px), transparent calc(100% - clamp(42px, 5vw, 82px)), var(--isar-hero-edge) 100%),
    linear-gradient(to bottom, var(--isar-hero-edge) 0, transparent clamp(38px, 5vw, 72px), transparent calc(100% - clamp(38px, 5vw, 72px)), var(--isar-hero-edge) 100%);
}
.isar-hero--home .badge {
  display: inline-block;
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--sky);
  background: transparent;
  border: 1px solid color-mix(in oklab, var(--canvas) 22%, transparent);
  border-radius: var(--radius-full);
  padding: 6px 16px;
  margin-bottom: var(--sp-lg);
}
.isar-hero--home h1 {
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(38px, 5.4vw, 76px);
  line-height: 0.98;
  letter-spacing: -0.03em;
  color: var(--canvas);
  margin: 0 0 var(--sp-lg);
  max-width: none;
  text-wrap: balance;
}
.isar-hero--home .lede {
  font-size: 18px;
  line-height: 1.55;
  color: var(--sky);
  margin: 0 0 var(--sp-xl);
  max-width: 48ch;
}
.isar-hero--home .cta-row {
  justify-content: flex-start;
  gap: var(--sp-md);
}
.isar-hero--home .isar-btn.primary {
  background: var(--canvas);
  color: var(--ink);
}
.isar-hero--home .isar-btn.primary:hover {
  background: color-mix(in oklab, var(--canvas) 85%, var(--ink) 15%);
}
.isar-hero--home .isar-btn.ghost {
  color: var(--canvas);
  border-color: color-mix(in oklab, var(--canvas) 28%, transparent);
}
@media (max-width: 640px) {
  .isar-hero--home {
    padding: var(--sp-xl);
  }
}

/* ---------- Service-page split hero: the kit's actual built page examples
   (extracted from #templates, verified across 4 of the 7 services) use a
   two-column split — real photo on the right, a light bg-elevated text
   panel on the left — not a dark ink hero with an icon glyph. Replaces
   .isar-hero--motif on the 7 services that have a photo (Akademie's kit
   example has no photo/split, kept on the motif treatment). Real photos
   already existed in the theme from an earlier build, referenced by the
   same filenames the kit itself uses. ---------- */
.isar-hero--split {
  --isar-hero-edge: #F1F1EF;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  overflow: hidden;
  /* The framed panel carries its own 56px inner padding, so inheriting the
     full --sp-section (96px) above and below made the hero swallow most of
     the first screen without adding information. Trimmed here only; the
     token itself is unchanged for every other section that uses it. */
  padding-top: 48px;
  padding-bottom: 48px;
}
:root[data-theme="dark"] .isar-hero--split {
  --isar-hero-edge: #1B212B;
}
.isar-hero--split-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-bottom: 1px solid var(--border);
  min-height: 340px;
  /* The photo's transparent edge veil resolves to the same surface as the
     text panel in both light and dark mode. */
  background: var(--isar-hero-edge);
  /* Rounds this card's own 4 outer corners (overflow:hidden clips the
     content/photo panels to that shape) -- there's no separate radius on
     the content/photo panels themselves, so the seam between them (a
     straight edge on desktop, top-to-bottom; a straight edge on mobile,
     where they stack instead) is never rounded on its own. Desktop reads
     as "outer corners only" and mobile as "upper and lower corners only"
     simply because it's one box either way, just laid out as a row or a
     column -- not two separately-rounded boxes touching. */
  border-radius: var(--radius-md);
  overflow: hidden;
}
.isar-hero--split-content {
  padding: 56px 48px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  background: var(--isar-hero-edge);
}
.isar-hero--split-photo {
  position: relative;
  background-size: cover;
  background-position: center center;
  --split-photo-fade-start: clamp(72px, 10vw, 144px);
  --split-photo-fade-end: clamp(40px, 5vw, 80px);
  --split-photo-fade-block: clamp(36px, 5vw, 72px);
}
.isar-hero--split-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  background:
    linear-gradient(
      to right,
      var(--isar-hero-edge) 0,
      transparent var(--split-photo-fade-start),
      transparent calc(100% - var(--split-photo-fade-end)),
      var(--isar-hero-edge) 100%
    ),
    linear-gradient(
      to bottom,
      var(--isar-hero-edge) 0,
      transparent var(--split-photo-fade-block),
      transparent calc(100% - var(--split-photo-fade-block)),
      var(--isar-hero-edge) 100%
    );
}
.isar-hero--split .badge {
  display: inline-block;
  align-self: flex-start;
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg3);
  background: transparent;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-full);
  padding: 6px 15px;
  margin-bottom: var(--sp-lg);
}
.isar-hero--split h1 {
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(28px, 3.4vw, 44px);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--fg1);
  max-width: none;
  margin: 0 0 var(--sp-md);
  text-wrap: balance;
}
.isar-hero--split .lede {
  font-size: 16px;
  line-height: 1.55;
  color: var(--fg2);
  max-width: 46ch;
  margin: 0 0 var(--sp-lg);
}
.isar-hero--split .cta-row {
  justify-content: flex-start;
}
.isar-hero--split .isar-btn.primary {
  display: inline-block;
  align-self: flex-start;
  font-size: 15px;
  font-weight: 500;
  color: var(--canvas);
  background: var(--ink);
  text-decoration: none;
  padding: 12px 24px;
  border-radius: var(--radius-sm);
}
.isar-hero--split .isar-btn.primary:hover {
  background: var(--ink-deep, var(--ink));
}
@media (max-width: 780px) {
  .isar-hero--split-grid {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .isar-hero--split-photo {
    min-height: 220px;
    order: -1;
    --split-photo-fade-start: 44px;
    --split-photo-fade-end: 44px;
    --split-photo-fade-block: 32px;
  }
  .isar-hero--split-content {
    padding: var(--sp-xl);
  }
}

@media (max-width: 640px) {
  .isar-hero--photo {
    min-height: 0;
    padding: var(--sp-xl);
  }
  .isar-hero--photo .isar-hero-photo-content {
    max-width: 100%;
  }
  .isar-hero--photo .cta-row {
    justify-content: flex-start;
  }
}
/* Per-page hero photo backgrounds: superseded by the light/dark
   --isar-hero-light-image/--isar-hero-dark-image variable system further
   down this file. These used to set the same background-image via a
   fixed *-bg.jpg/webp per page, with two classes (.isar-hero--photo.hero-X)
   giving them higher specificity than the new single-class var-based
   rules -- meaning light mode kept showing the old fixed image while only
   dark mode (which ties on specificity and wins on source order) picked
   up the new one. Removed entirely rather than fought on specificity. */

/* ---------- Matched light/dark hero photo system.
   The generated photography stays free of UI graphics. A page-specific,
   code-native SVG layer is injected by site.js above the photo and below the
   four-sided edge veil, so its geometry is identical in both themes. ---------- */
.isar-hero--home {
  --isar-hero-light-image: url("hero-munich-light.webp");
  --isar-hero-dark-image: url("hero-munich-dark.webp");
}
.hero-infrastruktur {
  --isar-hero-light-image: url("hero-infrastruktur-light.webp");
  --isar-hero-dark-image: url("hero-infrastruktur-dark.webp");
}
.hero-beratung {
  --isar-hero-light-image: url("hero-beratung-light.webp");
  --isar-hero-dark-image: url("hero-beratung-dark.webp");
}
.hero-sicherheit {
  --isar-hero-light-image: url("hero-sicherheit-light.webp");
  --isar-hero-dark-image: url("hero-sicherheit-dark.webp");
}
.hero-ki {
  --isar-hero-light-image: url("hero-ki-light.webp");
  --isar-hero-dark-image: url("hero-ki-dark.webp");
}
.hero-managed-services {
  --isar-hero-light-image: url("hero-managed-services-light.webp");
  --isar-hero-dark-image: url("hero-managed-services-dark.webp");
}
.hero-managed-security {
  --isar-hero-light-image: url("hero-managed-security-light.webp");
  --isar-hero-dark-image: url("hero-managed-security-dark.webp");
}
.hero-managed-cloud {
  --isar-hero-light-image: url("hero-managed-cloud-light.webp");
  --isar-hero-dark-image: url("hero-managed-cloud-dark.webp");
}
.hero-akademie {
  --isar-hero-light-image: url("hero-akademie-light.webp");
  --isar-hero-dark-image: url("hero-akademie-dark.webp");
}
.hero-karriere {
  --isar-hero-light-image: url("hero-karriere-light.webp");
  --isar-hero-dark-image: url("hero-karriere-dark.webp");
}
.hero-team {
  --isar-hero-light-image: url("hero-team-light.webp");
  --isar-hero-dark-image: url("hero-team-dark.webp");
}
.hero-unternehmen {
  --isar-hero-light-image: url("hero-unternehmen-light.webp");
  --isar-hero-dark-image: url("hero-unternehmen-dark.webp");
}
.hero-faq {
  --isar-hero-light-image: url("hero-faq-light.webp");
  --isar-hero-dark-image: url("hero-faq-dark.webp");
}
.hero-home {
  --isar-hero-light-image: url("hero-munich-light.webp");
  --isar-hero-dark-image: url("hero-munich-dark.webp");
}

/* Mobile hero images: the split-photo box never renders past ~220px tall
   on narrow viewports (see the max-width:780px rule above), so the
   full desktop-width photos were shipping roughly 2.7x more pixels than
   the layout ever displays. These -mobile variants are downscaled to
   900px wide and re-compressed, cutting hero payload by ~70% on mobile
   without touching the desktop images. */
@media (max-width: 780px) {
  .isar-hero--home {
    --isar-hero-light-image: url("hero-munich-light-mobile.webp");
    --isar-hero-dark-image: url("hero-munich-dark-mobile.webp");
  }
  .hero-infrastruktur {
    --isar-hero-light-image: url("hero-infrastruktur-light-mobile.webp");
    --isar-hero-dark-image: url("hero-infrastruktur-dark-mobile.webp");
  }
  .hero-beratung {
    --isar-hero-light-image: url("hero-beratung-light-mobile.webp");
    --isar-hero-dark-image: url("hero-beratung-dark-mobile.webp");
  }
  .hero-sicherheit {
    --isar-hero-light-image: url("hero-sicherheit-light-mobile.webp");
    --isar-hero-dark-image: url("hero-sicherheit-dark-mobile.webp");
  }
  .hero-ki {
    --isar-hero-light-image: url("hero-ki-light-mobile.webp");
    --isar-hero-dark-image: url("hero-ki-dark-mobile.webp");
  }
  .hero-managed-services {
    --isar-hero-light-image: url("hero-managed-services-light-mobile.webp");
    --isar-hero-dark-image: url("hero-managed-services-dark-mobile.webp");
  }
  .hero-managed-security {
    --isar-hero-light-image: url("hero-managed-security-light-mobile.webp");
    --isar-hero-dark-image: url("hero-managed-security-dark-mobile.webp");
  }
  .hero-managed-cloud {
    --isar-hero-light-image: url("hero-managed-cloud-light-mobile.webp");
    --isar-hero-dark-image: url("hero-managed-cloud-dark-mobile.webp");
  }
  .hero-akademie {
    --isar-hero-light-image: url("hero-akademie-light-mobile.webp");
    --isar-hero-dark-image: url("hero-akademie-dark-mobile.webp");
  }
  .hero-karriere {
    --isar-hero-light-image: url("hero-karriere-light-mobile.webp");
    --isar-hero-dark-image: url("hero-karriere-dark-mobile.webp");
  }
  .hero-team {
    --isar-hero-light-image: url("hero-team-light-mobile.webp");
    --isar-hero-dark-image: url("hero-team-dark-mobile.webp");
  }
  .hero-unternehmen {
    --isar-hero-light-image: url("hero-unternehmen-light-mobile.webp");
    --isar-hero-dark-image: url("hero-unternehmen-dark-mobile.webp");
  }
  .hero-faq {
    --isar-hero-light-image: url("hero-faq-light-mobile.webp");
    --isar-hero-dark-image: url("hero-faq-dark-mobile.webp");
  }
  .hero-home {
    --isar-hero-light-image: url("hero-munich-light-mobile.webp");
    --isar-hero-dark-image: url("hero-munich-dark-mobile.webp");
  }
}

.isar-hero--split-photo {
  background-image: var(--isar-hero-light-image);
}
:root[data-theme="dark"] .isar-hero--split-photo {
  background-image: var(--isar-hero-dark-image);
}
/* Real <img> layer (see functions.php's the_content filter), painted above
   the background-image fallback (z-index: 0, below .isar-hero-visual's
   z-index: 1) so it can be discovered and painted without waiting on this
   stylesheet -- the background-image above stays as-is and simply never
   becomes visible once the <img> loads successfully. */
.isar-hero-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.isar-hero-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}
.isar-hero--photo,
.isar-hero--home {
  background-image:
    linear-gradient(to right, var(--isar-hero-edge) 0%, color-mix(in oklab, var(--isar-hero-edge) 82%, transparent) 38%, transparent 68%),
    var(--isar-hero-light-image);
  background-size: cover;
  background-position: center;
}
:root[data-theme="dark"] .isar-hero--photo,
:root[data-theme="dark"] .isar-hero--home {
  background-image:
    linear-gradient(to right, var(--isar-hero-edge) 0%, color-mix(in oklab, var(--isar-hero-edge) 82%, transparent) 38%, transparent 68%),
    var(--isar-hero-dark-image);
}

.isar-hero-visual {
  position: absolute;
  inset: 5% 4% 5% 30%;
  z-index: 1;
  --isar-visual-opacity: 0.98;
  --isar-visual-line: #315B8A;
  --isar-visual-node: #244E7C;
  --isar-visual-node-surface: color-mix(in oklab, var(--isar-hero-edge) 95%, transparent);
  --isar-visual-left: 14%;
  --isar-visual-top: 5%;
  --isar-visual-width: 72%;
  --isar-visual-height: 88%;
  color: var(--isar-visual-line);
  opacity: var(--isar-visual-opacity);
  pointer-events: none;
}
.isar-hero--split-photo .isar-hero-visual {
  inset: auto;
  left: var(--isar-visual-left);
  top: var(--isar-visual-top);
  width: var(--isar-visual-width);
  height: var(--isar-visual-height);
}
.isar-hero--split-photo.hero-home .isar-hero-visual { --isar-visual-left: 7%; --isar-visual-top: 5%; --isar-visual-width: 86%; --isar-visual-height: 88%; }
.isar-hero--split-photo.hero-infrastruktur .isar-hero-visual { --isar-visual-left: 12%; --isar-visual-top: 5%; --isar-visual-width: 74%; --isar-visual-height: 88%; }
.isar-hero--split-photo.hero-beratung .isar-hero-visual { --isar-visual-left: 15%; --isar-visual-top: 5%; --isar-visual-width: 70%; --isar-visual-height: 86%; }
.isar-hero--split-photo.hero-sicherheit .isar-hero-visual { --isar-visual-left: 14%; --isar-visual-top: 4%; --isar-visual-width: 72%; --isar-visual-height: 88%; }
.isar-hero--split-photo.hero-ki .isar-hero-visual { --isar-visual-left: 14%; --isar-visual-top: 5%; --isar-visual-width: 70%; --isar-visual-height: 86%; }
.isar-hero--split-photo.hero-managed-services .isar-hero-visual { --isar-visual-left: 11%; --isar-visual-top: 5%; --isar-visual-width: 74%; --isar-visual-height: 88%; }
.isar-hero--split-photo.hero-managed-security .isar-hero-visual { --isar-visual-left: 15%; --isar-visual-top: 6%; --isar-visual-width: 70%; --isar-visual-height: 86%; }
.isar-hero--split-photo.hero-managed-cloud .isar-hero-visual { --isar-visual-left: 11%; --isar-visual-top: 6%; --isar-visual-width: 74%; --isar-visual-height: 86%; }
.isar-hero--split-photo.hero-akademie .isar-hero-visual { --isar-visual-left: 14%; --isar-visual-top: 3%; --isar-visual-width: 70%; --isar-visual-height: 90%; }
.isar-hero--split-photo.hero-karriere .isar-hero-visual { --isar-visual-left: 18%; --isar-visual-top: 3%; --isar-visual-width: 66%; --isar-visual-height: 90%; }
.isar-hero--split-photo.hero-team .isar-hero-visual { --isar-visual-left: 17%; --isar-visual-top: 5%; --isar-visual-width: 68%; --isar-visual-height: 88%; }
.isar-hero--split-photo.hero-unternehmen .isar-hero-visual { --isar-visual-left: 15%; --isar-visual-top: 5%; --isar-visual-width: 70%; --isar-visual-height: 88%; }
.isar-hero--split-photo.hero-faq .isar-hero-visual { --isar-visual-left: 18%; --isar-visual-top: 2%; --isar-visual-width: 66%; --isar-visual-height: 92%; }
.isar-hero-visual > svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.isar-hero-visual .isar-visual-orbit,
.isar-hero-visual .isar-visual-path {
  fill: none;
  stroke: currentColor;
  vector-effect: non-scaling-stroke;
}
/* Orbit and connector lines sit well below the photograph and the icons in
   the visual hierarchy -- they read as structure, not content -- so they
   run lighter than the nodes they connect. */
.isar-hero-visual .isar-visual-orbit {
  opacity: 0.58;
  stroke-width: 1.35;
}
.isar-hero-visual .isar-visual-path {
  opacity: 0.76;
  stroke-width: 1.45;
  stroke-dasharray: 2.4 3.2;
}
.isar-hero-visual .isar-visual-node {
  color: var(--isar-visual-node);
}
.isar-hero-visual .isar-visual-node-ring {
  fill: var(--isar-visual-node-surface);
  stroke: currentColor;
  stroke-width: 1.65;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 1px 2px color-mix(in oklab, var(--isar-visual-node) 24%, transparent));
}
.isar-hero-visual .isar-visual-node-halo {
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  stroke-dasharray: 1.2 1.8;
  opacity: 0.82;
  vector-effect: non-scaling-stroke;
}
.isar-hero-visual .isar-visual-icon {
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.isar-hero-visual .isar-visual-node.is-accent .isar-visual-icon {
  color: #D4AD7A;
  stroke-width: 2.2;
  filter: drop-shadow(0 0 1.5px color-mix(in oklab, #D4AD7A 38%, transparent));
}
.isar-hero-visual .isar-visual-core {
  fill: var(--isar-visual-node-surface);
  stroke: currentColor;
  stroke-width: 1.4;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 1px 2px color-mix(in oklab, var(--isar-visual-node) 24%, transparent));
}
:root[data-theme="dark"] .isar-hero-visual {
  --isar-visual-opacity: 0.94;
  --isar-visual-line: #AFC9EB;
  --isar-visual-node: #E1EBF8;
  --isar-visual-node-surface: color-mix(in oklab, #1B212B 92%, transparent);
}

/* Photo copy now follows the matching theme instead of remaining permanently
   dark-on-light. The split hero already uses semantic text tokens. */
:root:not([data-theme="dark"]) .isar-hero--home h1,
:root:not([data-theme="dark"]) .isar-hero--home .lede,
:root:not([data-theme="dark"]) .isar-hero--home .badge,
:root:not([data-theme="dark"]) .isar-hero--home .isar-btn.ghost {
  color: #18202B;
}
:root:not([data-theme="dark"]) .isar-hero--home .badge,
:root:not([data-theme="dark"]) .isar-hero--home .isar-btn.ghost {
  border-color: color-mix(in oklab, #18202B 28%, transparent);
}
:root:not([data-theme="dark"]) .isar-hero--home .isar-btn.primary {
  color: #F1F1EF;
  background: #18202B;
}
:root[data-theme="dark"] .isar-hero--photo h1,
:root[data-theme="dark"] .isar-hero--photo .lede,
:root[data-theme="dark"] .isar-hero--photo .badge,
:root[data-theme="dark"] .isar-hero--photo .isar-btn.ghost,
:root[data-theme="dark"] .isar-hero--home h1,
:root[data-theme="dark"] .isar-hero--home .lede,
:root[data-theme="dark"] .isar-hero--home .badge,
:root[data-theme="dark"] .isar-hero--home .isar-btn.ghost {
  color: #F1ECE2;
}
:root[data-theme="dark"] .isar-hero--photo .badge,
:root[data-theme="dark"] .isar-hero--photo .isar-btn.ghost,
:root[data-theme="dark"] .isar-hero--home .badge,
:root[data-theme="dark"] .isar-hero--home .isar-btn.ghost {
  border-color: color-mix(in oklab, #F1ECE2 28%, transparent);
}
:root[data-theme="dark"] .isar-hero--home .isar-btn.primary {
  color: #1B212B;
  background: #F1ECE2;
}

@media (max-width: 780px) {
  .isar-hero-visual {
    inset: 8% 4% 8% 34%;
    --isar-visual-opacity: 0.9;
  }
  .isar-hero--split-photo .isar-hero-visual {
    inset: auto;
    left: 12%;
    top: 6%;
    width: 76%;
    height: 88%;
  }
  :root[data-theme="dark"] .isar-hero-visual { --isar-visual-opacity: 0.88; }
}
@media (max-width: 520px) {
  .isar-hero-visual {
    inset: 12% 2% 12% 42%;
    --isar-visual-opacity: 0.86;
  }
  .isar-hero--split-photo .isar-hero-visual {
    inset: auto;
    left: 16%;
    top: 8%;
    width: 68%;
    height: 84%;
  }
  :root[data-theme="dark"] .isar-hero-visual { --isar-visual-opacity: 0.84; }
  /* Scoped to the homepage's 8-icon constellation specifically, not by
     node count: standard pages are now exactly 3 icons (no longer 3-5),
     so an nth-of-type(n+3) threshold here would silently drop one of
     only three icons -- and its connecting path, since is-secondary-path
     (index > 1) covers that 3rd path too, leaving an orphaned icon with
     no line to the core. isar-hero-visual--home-services is the only
     layout with more than 3 nodes, so it's the only one that needs
     decluttering on the smallest screens. */
  .isar-hero-visual--home-services .isar-visual-node:nth-of-type(n + 3),
  .isar-hero-visual--home-services .isar-visual-path.is-secondary-path {
    display: none;
  }
}
.isar-btn {
  font-family: var(--sans-body);
  font-weight: 500;
  border-radius: var(--radius-sm);
  padding: var(--sp-sm) var(--sp-xl);
  text-decoration: none;
  display: inline-block;
}
.isar-btn.primary {
  background: var(--ink);
  color: var(--fg-on-ink);
}
.isar-btn.primary:hover { background: var(--ink-deep); }
/* --ink is a fixed brand constant, not theme-reactive (see the note at the
   top of this file) -- but --bg/--bg-elevated in dark mode sit almost the
   same near-black as --ink itself, so a primary button on a dark card (the
   booking widget's submit button, service-page CTA cards) nearly vanishes.
   Dark mode swaps to the brand's own lifted accent instead, same fix as
   the day-tab selection below. */
:root[data-theme="dark"] .isar-btn.primary {
  background: var(--bg-accent);
  color: var(--fg-on-sky);
}
:root[data-theme="dark"] .isar-btn.primary:hover {
  /* Lightens rather than darkens: the light-mode hover (--ink-deep) darkens
     against light --fg-on-ink text, which increases contrast there. Here
     the text (--fg-on-sky) is dark, so the same "move toward more contrast"
     rule means going lighter, not darker -- darkening would wreck it. */
  background: color-mix(in oklab, var(--bg-accent) 85%, white 15%);
}
.isar-btn.ghost {
  background: transparent;
  color: var(--fg1);
  border: 1px solid var(--border-strong);
}
.isar-btn.ghost:hover { background: var(--bg-elevated); }

/* ---------- Services grid ---------- */
.isar-services {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-section) var(--sp-xl);
}
/* Homepage "Ablauf" (bg-elevated tint) and "Für wen" (divider) sections
   both break from the plain page background per the kit — modifiers
   rather than new section markup so they still share the standard
   container width/eyebrow/h2 treatment above. */
.isar-services--tinted {
  background: var(--bg-elevated);
}
.isar-services--divided {
  border-top: 1px solid var(--border);
}
.isar-audience-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--sp-lg);
}
.isar-audience-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-xl);
}
.isar-audience-card .value {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  color: var(--fg1);
  margin: 0 0 var(--sp-sm);
}
.isar-audience-card p {
  font-size: var(--fs-body-sm);
  line-height: var(--lh-relaxed);
  color: var(--fg2);
  margin: 0;
}
/* Every heading extracted from the kit — the homepage's "Was wir tun" /
   "Ablauf" / "Für wen" sections, the promise band, every service-page
   template — leads with a small left-aligned mono eyebrow (11px, uppercase,
   0.12em tracking, --fg3) directly above a left-aligned serif h2. This
   class had instead become the BIG heading itself (56px serif, centered,
   with a blinking "?"), with the real <h2> centered again below it —
   fixed to match the kit's actual, consistently left-aligned pattern. */
.isar-services .eyebrow {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg3);
  text-align: left;
  margin: 0 0 var(--sp-sm);
}
.isar-services .eyebrow .blink {
  animation: isar-blink 1.4s step-end infinite;
}
@keyframes isar-blink {
  0%, 45%  { opacity: 1; }
  50%, 95% { opacity: 0; }
  100%     { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .isar-services .eyebrow .blink { animation: none; }
}
.isar-services h1,
.isar-services h2 {
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(28px, 3.2vw, 42px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--fg1);
  text-align: left;
  max-width: 22ch;
  margin: 0 0 var(--sp-xxl);
  text-wrap: balance;
}
/* Secondary section headings ("Ablauf", "Für wen") -- same font-size/
   weight as "Was wir tun" (h1/h2 above) per request; previously a fixed
   32px instead of that fluid clamp. */
.isar-services h3.isar-section-heading {
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(28px, 3.2vw, 42px);
  line-height: 1.1;
  color: var(--fg1);
  text-align: left;
  max-width: 24ch;
  margin: 0 0 var(--sp-xxl);
  text-wrap: balance;
}
/* Lead-in copy under a section h2 — the problem-framing block that opens
   each service page. Left-aligned and left-anchored to match the heading
   above it, not centred as a block (the kit never centres a text block). */
.isar-services h2:has(+ .section-intro) {
  margin-bottom: var(--sp-lg);
}
.isar-services .section-intro {
  font-size: var(--fs-body-md);
  line-height: var(--lh-relaxed);
  color: var(--fg2);
  max-width: var(--container-prose);
  margin: 0 0 var(--sp-md);
}
.isar-services .section-intro:last-of-type {
  margin-bottom: 0;
}
/* Flex, not grid: CSS Grid's auto-fit has no way to centre a leftover
   partial last row — 8 cards at 3-per-row leaves the last row's 2 cards
   flush left with a wide empty gap. Flexbox with grow capped at a
   max-width and justify-content:center fills full rows exactly like the
   grid version did, but once a row can't fill (fewer items, or items
   already at their cap), the extra space becomes real leftover space
   that justify-content can center instead of nowhere for it to go. */
.isar-services .grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-xl);
}
.isar-services .grid > * {
  flex: 1 0 260px;
  max-width: 320px;
}
/* Four-card rows ("Leistungen im Detail"). Explicit counts rather than
   auto-fit: at container width auto-fit lands on three columns and leaves
   a single orphan card on a second row. */
.isar-services .grid--quad {
  grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 1000px) {
  .isar-services .grid--quad {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 560px) {
  .isar-services .grid--quad {
    grid-template-columns: 1fr;
  }
}

/* Leistungen overview (DE /leistungen/ id 9, EN /en/services/ id 46):
   fixed 2-row x 4-column grid for the 8 service cards, instead of the
   flex-wrap auto-flow every other .isar-services .grid uses -- scoped to
   these pages' body classes so it doesn't touch the "Leistungen im
   Detail" 4-card rows or any other page reusing the same .grid class. */
body.page-id-9 .isar-services .grid,
body.page-id-46 .isar-services .grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--sp-xl);
}
body.page-id-9 .isar-services .grid > *,
body.page-id-46 .isar-services .grid > * {
  max-width: none;
}
@media (max-width: 1000px) {
  body.page-id-9 .isar-services .grid,
  body.page-id-46 .isar-services .grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 560px) {
  body.page-id-9 .isar-services .grid,
  body.page-id-46 .isar-services .grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- Numbered sequence: replaces the flat "Leistungen im Detail"
   card grid on services whose kit motif calls for a process/flow rhythm
   (layers, steps, decision path) instead of a flat grid — same content,
   same "svc" cards were structurally identical for all 8 services before,
   which is exactly what the kit's #templates section is written against.
   No borders/background on the steps themselves (unlike .svc cards) so it
   reads as a sequence, not another card row; a connecting line + numbered
   dot carries the "flow" idea. ---------- */
.isar-sequence {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
/* Homepage "Ablauf" only: wraps .isar-sequence in a rounded ink card,
   matching .isar-promise-card's treatment. Scoped to this wrapper class
   rather than changing .isar-sequence itself, since that class is
   shared with several service pages' own (un-carded) process sections.
   --fg1/--fg2/--border are theme-reactive and would lose contrast on
   this fixed --ink background in one theme (the same trap documented
   throughout this file) -- overridden below with the same fixed tokens
   .isar-promise-card itself uses (--canvas for headings, --sky for
   body text). */
.isar-ablauf-card {
  background: var(--ink);
  border-radius: var(--radius-md);
  padding: var(--sp-xxl);
}
.isar-ablauf-card .isar-sequence-step h3 {
  color: var(--canvas);
}
.isar-ablauf-card .isar-sequence-step p {
  color: var(--sky);
}
.isar-ablauf-card .isar-sequence-num {
  color: var(--slate);
}
/* Moved from its own line above the heading to sit inline in the dot/line
   row instead (between the dot and the connecting line) -- markup order
   in the Home page content was changed to match, this just drops the
   block-level spacing that made sense there but not here. */
.isar-ablauf-card .isar-sequence-dot-row .isar-sequence-num {
  flex: 0 0 auto;
  margin-bottom: 0;
}
.isar-ablauf-card .isar-sequence-line {
  background: color-mix(in oklab, var(--canvas) 18%, transparent);
}
@media (max-width: 768px) {
  .isar-ablauf-card {
    padding: var(--sp-xl);
  }
}
.isar-sequence-step {
  position: relative;
  padding: 0 var(--sp-xl) 0 0;
}
.isar-sequence-step:last-child {
  padding-right: 0;
}
.isar-sequence-dot-row {
  display: flex;
  align-items: center;
  gap: var(--sp-md);
  margin-bottom: var(--sp-lg);
}
.isar-sequence-dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: var(--radius-full);
  background: var(--slate);
}
.isar-sequence-line {
  flex: 1 1 auto;
  height: 1px;
  background: var(--border);
}
.isar-sequence-step:last-child .isar-sequence-line,
.isar-sequence-step:nth-child(4n) .isar-sequence-line {
  display: none;
}
.isar-sequence-num {
  display: block;
  font-family: var(--sans-mono);
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  color: var(--fg3);
  margin-bottom: var(--sp-sm);
}
.isar-sequence-step h3 {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-sm);
  color: var(--fg1);
  margin: 0 0 var(--sp-sm);
}
.isar-sequence-step p {
  font-size: var(--fs-body-sm);
  line-height: var(--lh-relaxed);
  color: var(--fg2);
  margin: 0;
  padding-right: var(--sp-md);
}
@media (max-width: 1000px) {
  .isar-sequence {
    grid-template-columns: repeat(2, 1fr);
    row-gap: var(--sp-xl);
  }
  .isar-sequence-step:nth-child(2n) .isar-sequence-line {
    display: none;
  }
}
@media (max-width: 560px) {
  .isar-sequence {
    grid-template-columns: 1fr;
  }
  .isar-sequence-step {
    padding-right: 0;
  }
  .isar-sequence-line {
    display: none;
  }
}

/* ---------- Sequence marker variants: four more services, four more
   connector/marker treatments — content and structure stay exactly the
   isar-sequence markup already shipped, only the dot/line language changes
   per page to echo that page's kit motif. Every marker stays typographic
   (a mono/serif glyph or a plain CSS shape), never a new icon asset, per
   the kit's own icon budget (hero + footer wave + hero background grid,
   nothing else). ---------- */

/* IT-Beratung — "Pfad": each step is a fork in a decision path, not a
   neutral checkpoint, so the dot becomes a small directional arrow. */
.isar-sequence--path .isar-sequence-dot {
  width: 0;
  height: 0;
  border-radius: 0;
  background: transparent;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 7px solid var(--slate);
}

/* IT-Sicherheit — "Schild": a checked box instead of a dot, echoing an
   audit finding that's been reviewed rather than a step in a sequence. */
.isar-sequence--checklist .isar-sequence-dot {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  background: transparent;
  border: 1px solid var(--slate);
  position: relative;
}
.isar-sequence--checklist .isar-sequence-dot::after {
  content: "\2713";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 9px;
  line-height: 1;
  color: var(--slate);
}

/* Managed Services — "Kreislauf": the work here repeats every month
   rather than finishing once, so the dot hollows out into a ring and the
   connector turns dashed instead of a solid one-way line. */
.isar-sequence--cycle .isar-sequence-dot {
  background: transparent;
  border: 1.5px solid var(--slate);
  box-sizing: border-box;
}
.isar-sequence--cycle .isar-sequence-line {
  background: none;
  border-top: 1px dashed var(--border);
  height: 0;
}

/* Managed Cloud — "Wolke": a soft asymmetric blob instead of a round dot. */
.isar-sequence--cloud .isar-sequence-dot {
  border-radius: 40% 60% 60% 40% / 50% 40% 60% 50%;
}

/* Akademie — "Kursheft": a catalog to browse, not a flow or a grid of
   parallel nodes — large serif numerals like a table of contents, no
   connecting dot or line at all. */
.isar-sequence--catalog {
  grid-template-columns: repeat(2, 1fr);
  row-gap: var(--sp-xl);
}
.isar-sequence--catalog .isar-sequence-dot-row {
  display: none;
}
.isar-sequence--catalog .isar-sequence-num {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-lg);
  letter-spacing: 0;
  color: var(--stone);
  margin-bottom: var(--sp-sm);
}
@media (max-width: 560px) {
  .isar-sequence--catalog {
    grid-template-columns: 1fr;
  }
}

/* ---------- Sequence grid modifier: nodes, not a flow (KI-Implementierung's
   kit motif is a 2x2 criteria grid, not a left-to-right process) — same
   dot/number/heading language as .isar-sequence, just wrapped instead of
   linear, with the connecting line dropped since these aren't steps in
   order. ---------- */
.isar-sequence--grid {
  grid-template-columns: repeat(2, 1fr);
  row-gap: var(--sp-xl);
}
.isar-sequence--grid .isar-sequence-line {
  display: none;
}
.isar-sequence--grid .isar-sequence-step {
  padding-right: var(--sp-xl);
}
@media (max-width: 560px) {
  .isar-sequence--grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- Layered rows: IT-Infrastruktur's kit motif is "Rack —
   gestapelte Ebenen" (stacked layers) — the page's three intro paragraphs
   (Was wir tun / Wie wir es umsetzen / Warum wir) map onto exactly three
   layers, so this rotates the same dot+line flow language 90° into a
   vertical stack instead of the flat 3-column .grid used on every other
   page. Purely typographic, same real copy — no new icons, per the kit's
   own ASCII rule (icon budget is hero + footer wave + hero grid, nothing
   else). ---------- */
.isar-motif-layers {
  display: flex;
  flex-direction: column;
}
.isar-motif-layers-row {
  display: flex;
  gap: var(--sp-lg);
}
.isar-motif-layers-rail {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 9px;
  flex: 0 0 auto;
}
.isar-motif-layers-dot {
  width: 9px;
  height: 9px;
  border-radius: var(--radius-full);
  background: var(--slate);
  flex: 0 0 auto;
}
.isar-motif-layers-line {
  width: 1px;
  flex: 1 1 auto;
  background: var(--border);
  margin-top: var(--sp-sm);
}
.isar-motif-layers-row:last-child .isar-motif-layers-line {
  display: none;
}
.isar-motif-layers-content {
  flex: 1 1 auto;
  padding-bottom: var(--sp-xl);
  max-width: 640px;
}
.isar-motif-layers-row:last-child .isar-motif-layers-content {
  padding-bottom: 0;
}
.isar-motif-layers-content h3 {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  color: var(--fg1);
  margin: 0 0 var(--sp-sm);
}
.isar-motif-layers-content p {
  font-size: var(--fs-body-md);
  line-height: var(--lh-relaxed);
  color: var(--fg2);
  margin: 0;
}

.svc {
  position: relative;
  display: flex;
  flex-direction: column;
  text-decoration: none;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-xl);
}
/* Job listing that's filled/not being actively hired for -- greyed
   rather than removed, since the card itself (title, description) still
   has reference value, it's just not an open CTA any more. Opacity on
   the whole card dims text/icons together in one step; the status
   banner in place of the link is the only full-opacity element so the
   reason is legible at a glance.
   !important: this card also carries .isar-reveal.is-visible (the
   scroll-in animation every card gets), whose own opacity:1 rule at
   two classes' specificity would otherwise win over this one-class
   rule once the reveal finishes and silently un-grey the card. */
.svc--paused {
  opacity: 0.55 !important;
}
/* Replaces the .svc-more link entirely on a filled/paused listing --
   same position (end of the card, via the shared .svc-more rules below)
   and the same font as that link (not the mono/uppercase/tracked style
   the old top-of-card badge used, which read as harsh here), but not a
   link, so it still needs its own non-interactive styling rather than
   inheriting the link's hover/underline treatment. Centered as a pill
   rather than left-aligned, so it reads as a status chip, not a label. */
.svc--paused .svc-filled-badge {
  display: inline-block;
  opacity: 1;
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  text-decoration: none;
  color: var(--fg1);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 4px var(--sp-md);
}
/* Same wpautop gotcha as .svc p:has(> .svc-more) below: the badge's real
   flex child is the <p> wpautop wrapped it in, not the span itself, so
   align-self on the span had no box to center within -- text-align on
   that wrapping <p> is what actually centers it. */
.svc p:has(> .svc-filled-badge) {
  text-align: center;
}
/* Status note for a paused/not-hiring listing -- sits at the end of the
   card, in the .svc-more link's old spot, so it reads as "here's what
   became of the CTA" rather than interrupting the title/description.
   Full opacity like .svc-filled-badge above, for the same reason: it's
   the one element on a dimmed card that has to stay legible.
   margin-top: auto rather than a fixed top gap -- .svc rows share a
   height (flex-wrap's default align-items: stretch), but a plain top
   margin only positions the note relative to its OWN card's content, so
   Teilzeit (shorter description + list) left its note floating well
   above Vollzeit's and above Werkstudent's "Mehr erfahren" whenever a
   row's cards have unequal content length. auto pushes it to consume
   the rest of the column instead, flush with the card's bottom padding
   regardless of how much shorter this card's own content is -- so it
   lines up with any neighbour, not just one whose content happens to be
   just as long. */
.svc--paused .svc-paused-note {
  display: flex;
  align-items: center;
  gap: var(--sp-xs);
  opacity: 1;
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg3);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-xs) var(--sp-md);
  margin: auto 0 0;
  width: fit-content;
}
.svc--paused .svc-paused-note svg {
  flex: none;
  width: 14px;
  height: 14px;
}
/* Stretched-link pattern: the card itself is a <div> (wpautop leaves that
   alone), and this invisible full-card <a> — simple enough that wpautop
   has nothing inside it to mangle — makes the whole card clickable
   without wpautop fragmenting the card's h3/p/ul across the page (see
   the "Was wir tun" homepage cards' commit history for what that looked
   like: wpautop doesn't treat <a> as a protected block tag the way it
   treats <div>, so a <h3> etc. directly inside an <a> got wrapped in a
   stray, unbalanced <p> that the browser's parser then used as an excuse
   to auto-close the <a> early). */
.svc-stretched-link {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: inherit;
}
.svc .svc-more {
  position: relative;
  z-index: 2;
}
.svc h3 {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  color: var(--fg1);
  margin-bottom: var(--sp-sm);
}
.svc p {
  font-size: var(--fs-body-md);
  color: var(--fg2);
  margin-bottom: var(--sp-lg);
}
.svc ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
}
.svc ul li {
  font-size: var(--fs-body-sm);
  color: var(--fg3);
  padding-left: var(--sp-lg);
  position: relative;
}
.svc ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--slate);
}
/* wpautop wraps the loose <a> in its own <p> — that <p>, not the <a>
   itself, is the actual direct flex child of .svc, so the auto margin
   that pushes it to the bottom has to go there (confirmed live: putting
   it on .svc-more directly resolved to 0px, since an inline-block inside
   a block-formatting-context <p> has no flex space to distribute). */
.svc p:has(> .svc-more) {
  margin: auto 0 0;
}
.svc .svc-more {
  display: inline-block;
  padding-top: var(--sp-lg);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg1);
  text-decoration: none;
}
/* The application-email CTA is the one .svc-more that's a long email
   address rather than a short "Mehr erfahren"/"Learn more" label --
   at the shared font-size it wraps by a handful of pixels at every
   card width the grid actually renders. Once prefixed with "Bewerbung
   an:"/"Apply to:" it's too long to force onto one line at any font
   size that's still readable in a ~216px-wide card -- nowrap would
   just overflow the card instead of wrapping, which is worse. The
   smaller size keeps the (now two-line) wrap compact rather than
   fixing the line count outright. */
.svc .svc-more--email {
  font-size: 13px;
}
.svc .svc-more:hover {
  text-decoration: underline;
}
/* Shares the .svc-more class (for shared position/spacing), but it isn't
   a link any more -- the rule above doesn't know that and underlines it
   whenever the cursor happens to land on the card's own status text, not
   just on a real link. Same specificity as that rule (2 classes + a
   pseudo-class each), so this has to come after it to actually win. */
.svc .svc-filled-badge:hover {
  text-decoration: none;
}
/* The application-email link reads more like a labelled action than a
   classic inline hyperlink once it's prefixed with "Bewerbung an:" /
   "Apply to:" -- no underline in either state. */
.svc .svc-more--email,
.svc .svc-more--email:hover {
  text-decoration: none;
}
/* Homepage "Was wir tun" spotlight cards, per the kit: a number badge
   above the title, and a per-service icon (the SAME glyph used in that
   service's own hero) that fades in top-right on hover — reusing the
   --spot custom property the spotlight glow above already sets, so no
   new JS/mouse-tracking is needed for the icon to fade in and out with
   the same hover state. */
/* Solution-area label (Hardware/Software/Cloud) under each service card's
   heading -- content-only addition per the copy brief, reuses .svc-num's
   small-caps mono treatment rather than introducing a new visual style. */
.svc .svc-solution {
  display: block;
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  color: var(--fg3);
  margin: 0 0 var(--sp-xs);
}
.svc .svc-num {
  display: block;
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  color: var(--fg3);
  margin-bottom: var(--sp-sm);
}
.svc .svc-icon {
  position: absolute;
  top: var(--sp-lg);
  right: var(--sp-md);
  width: 34px;
  height: 34px;
  color: var(--slate);
  opacity: var(--spot, 0);
  transition: opacity var(--dur-comp, 240ms) var(--ease-out, ease-out);
  pointer-events: none;
}

/* ---------- FAQ search + filter (injected by site.js, no markup change
   needed in page content — same glow-on-focus treatment as the nav search) ---------- */
.isar-faq-search-wrap {
  max-width: var(--container-prose);
  margin: 0 auto var(--sp-xl);
}
.isar-faq-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-md);
  border-radius: var(--radius-full);
  padding: 2px;
  background: var(--bg-elevated);
  transition: background var(--dur-comp) var(--ease-out);
}
.isar-faq-search:focus-within {
  background: conic-gradient(from var(--isar-search-angle, 0deg), var(--slate), var(--sky), var(--stone), var(--slate));
  animation: isar-search-spin 3.2s linear infinite;
}
.isar-faq-search-inner {
  display: flex;
  align-items: center;
  gap: var(--sp-md);
  flex: 1;
  background: var(--bg);
  border-radius: var(--radius-full);
  padding: var(--sp-md) var(--sp-xl);
}
.isar-faq-search-icon {
  flex: 0 0 auto;
  color: var(--fg3);
}
.isar-faq-search-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  font-family: var(--sans-body);
  font-size: var(--fs-body-md);
  color: var(--fg1);
}
.isar-faq-search-input::placeholder {
  color: var(--fg4);
}
.isar-faq-search-count {
  flex: 0 0 auto;
  font-family: var(--sans-mono);
  font-size: var(--fs-caption);
  color: var(--fg3);
}
.isar-faq-list details.is-faq-hidden,
.isar-faq-list .isar-faq-group.is-faq-hidden {
  display: none;
}
/* Group heading inside the accordion. The list is one flex column, so the
   headings are siblings of the <details> rather than wrappers -- that keeps
   the search filtering a single flat set of items (and the FAQPage schema
   parser reading one uninterrupted run of summary/answer pairs). */
.isar-faq-group {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
  margin: var(--sp-xl) 0 0;
  padding-bottom: var(--sp-sm);
  border-bottom: 1px solid var(--border);
}
.isar-faq-group:first-child {
  margin-top: 0;
}
.isar-faq-empty {
  display: none;
  max-width: var(--container-prose);
  margin: 0 auto;
  text-align: center;
  padding: var(--sp-xxl);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-md);
}
.isar-faq-empty.is-visible {
  display: block;
}
.isar-faq-empty p {
  color: var(--fg2);
  margin: 0;
}

/* ---------- FAQ accordion ---------- */
.isar-faq-list {
  max-width: var(--container-prose);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-md);
}
.isar-faq-list details.svc {
  padding: var(--sp-lg) var(--sp-xl);
}
.isar-faq-list summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-lg);
  cursor: pointer;
  list-style: none;
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  color: var(--fg1);
}
.isar-faq-list summary::-webkit-details-marker {
  display: none;
}
.isar-faq-list summary::after {
  content: "";
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  background:
    linear-gradient(var(--fg3), var(--fg3)) center / 100% 2px no-repeat,
    linear-gradient(var(--fg3), var(--fg3)) center / 2px 100% no-repeat;
  transition: transform 200ms ease;
}
.isar-faq-list details[open] summary::after {
  transform: rotate(45deg);
}
.isar-faq-list .faq-answer {
  font-size: var(--fs-body-md);
  color: var(--fg2);
  margin-top: var(--sp-md);
}

/* ---------- Related services ("Passt dazu") pill row ---------- */
/* Sits above the card now (was inside it) — same role/gap as
   .isar-credentials h2's margin-bottom before its own card starts.
   Still on the page's normal theme-following background here, so --fg3
   (not a fixed token) is correct, unlike the card-scoped rules below. */
.isar-related-eyebrow {
  font-family: var(--sans-body);
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
  text-align: left;
  margin: 0 0 var(--sp-xxl);
}
.isar-related-row {
  display: flex;
  gap: var(--sp-md);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding: 4px 4px var(--sp-sm);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, black 24px, black calc(100% - 24px), transparent 100%);
}
.isar-related-row::-webkit-scrollbar {
  display: none;
}
.isar-related-row .isar-related-pill {
  flex: 0 0 auto;
  white-space: nowrap;
}
/* Card variant: reuses .isar-credentials-card's fixed --canvas ink-card
   shell (see the isar_related_services shortcode), but thinner — this
   card only holds the pill row now (the eyebrow moved above it), and
   its own 3-row wave (.isar-related-wave-box, not the credentials
   card's 6-row box) needs less vertical room. --fg3/--fg1 etc. flip
   with theme; on a card that's fixed regardless of theme, those would
   go invisible in one theme the same way --ink-mute did on .cred-pill
   earlier — fixed raw tokens only here. */
.isar-related-card {
  padding: var(--sp-lg) 0;
}
.isar-related-wave-box {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  overflow: hidden;
  padding: var(--sp-xs) 0;
  pointer-events: none;
  mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%);
}
.isar-related-wave-box .isar-footer-wave-row {
  margin: 0 !important;
  opacity: 0.55;
}
.isar-related-card .isar-related-row {
  position: relative;
  /* Same gap as .isar-credentials-row (36px, not the base row's --sp-md
     12px), matching "the example" card. */
  gap: 36px;
  padding-left: var(--sp-xxl);
  padding-right: var(--sp-xxl);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%);
}
.isar-related-card .isar-related-pill {
  background: var(--canvas);
  color: var(--ink);
  border-color: color-mix(in oklab, var(--canvas) 18%, transparent);
}
.isar-related-card .isar-related-pill:hover {
  background: color-mix(in oklab, var(--canvas) 85%, var(--ink) 15%);
}
@media (max-width: 640px) {
  .isar-related-card {
    padding: var(--sp-xl);
  }
}

/* ---------- Akademie video player ---------- */
.isar-video-wrap {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--ink);
}
.isar-video-player {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--ink);
}
.isar-video-play {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 64px;
  height: 64px;
  border: none;
  border-radius: 50%;
  background: color-mix(in oklab, var(--canvas) 92%, transparent);
  color: var(--ink);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 160ms cubic-bezier(0.2, 0, 0, 1), background 160ms;
}
.isar-video-play svg {
  width: 28px;
  height: 28px;
  margin-left: 3px; /* optical centering: the triangle's mass sits left of its bbox center */
}
.isar-video-play:hover {
  transform: scale(1.06);
  background: var(--canvas);
}
.isar-video-play:disabled {
  cursor: default;
  opacity: 0;
}
.isar-video-wrap.is-loading .isar-video-play,
.isar-video-wrap.is-playing .isar-video-play {
  opacity: 0;
  pointer-events: none;
}
.isar-video-wrap.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid color-mix(in oklab, var(--canvas) 25%, transparent);
  border-top-color: var(--canvas);
  animation: isar-video-spin 0.8s linear infinite;
  pointer-events: none;
}
@keyframes isar-video-spin {
  to { transform: rotate(360deg); }
}
.isar-video-wrap.is-error::after {
  content: "Video konnte nicht geladen werden.";
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--sp-lg);
  text-align: center;
  color: var(--canvas);
  font-size: 14px;
}
.isar-video-gate {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-xl);
  text-align: center;
  background: var(--bg-elevated);
}
.isar-video-gate p {
  margin: 0 0 var(--sp-md);
  color: var(--fg2);
}

/* ---------- Team ---------- */
.isar-team {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-section) var(--sp-xl);
  display: flex;
  flex-direction: column;
  gap: var(--sp-xl);
}
.team-member {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-xl);
  display: flex;
  align-items: center;
  gap: var(--sp-xl);
}
.team-member .photo {
  flex: 0 0 auto;
  width: 140px;
  height: 140px;
  border-radius: var(--radius-md);
  border: 1px solid var(--border-strong);
  object-fit: cover;
}
.team-member h3 {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  font-weight: 400;
  color: var(--fg1);
  margin: 0 0 var(--sp-xs);
}
.team-member .role {
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
  margin-bottom: var(--sp-sm);
}
.team-member p.bio {
  font-size: var(--fs-body-md);
  color: var(--fg2);
  margin: 0;
}
@media (max-width: 640px) {
  .team-member {
    flex-direction: column;
    text-align: center;
  }
}

/* One-line link from a service page to its most relevant FAQ entry,
   sitting between the "Leistungen im Detail" section and the promise
   band. Styled like .svc-more (same font-size/weight) rather than a
   plain paragraph link, since it's functioning as a small CTA, not
   body copy. */
.isar-faq-crosslink {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--sp-xl);
  text-align: center;
}
.isar-faq-crosslink a {
  display: inline-block;
  padding: var(--sp-lg) 0;
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg1);
  text-decoration: none;
}
.isar-faq-crosslink a:hover {
  text-decoration: underline;
}

/* ---------- Service-page FAQ module ----------
   The FAQ page's accordion reused on a service page: same
   .isar-faq-list / details.svc markup, so questions stay in post_content
   where the FAQPage JSON-LD parser can still read them. Two differences
   from /faq/ -- the list is left-aligned rather than centred in a prose
   column, to sit with its neighbouring sections, and site.js skips the
   search field here (four questions don't need filtering). */
.isar-faq-module .isar-faq-list {
  max-width: 860px;
  margin: 0;
}
/* The crosslink centres itself on /faq/; here it belongs under the
   left-aligned content it follows. */
.isar-faq-module .isar-faq-crosslink {
  max-width: none;
  padding: 0;
  text-align: left;
}

/* ---------- Promise band ---------- */
.isar-promise {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-section) var(--sp-xl);
}
/* Fixed brand-navy card, deliberately not theme-reactive: unlike the rest of
   the site (which flips light/dark via --bg-inverse etc.), this band matches
   the marketing template's always-dark promise card in both modes. */
.isar-promise-card {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: var(--canvas);
  border-radius: var(--radius-md);
  padding: var(--sp-3xl) var(--sp-xxl);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-xxl);
  align-items: center;
}
.isar-promise-card p {
  color: var(--sky);
  margin: 0;
  font-size: var(--fs-body-md);
}
.isar-promise-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-lg);
}
.isar-promise-stats .stat {
  border-left: 1px solid color-mix(in oklab, var(--canvas) 18%, transparent);
  padding-left: var(--sp-md);
}
.isar-promise-stats .value {
  font-family: var(--serif-display);
  font-size: var(--fs-display-md);
  font-weight: 400;
  line-height: var(--lh-tight);
  color: var(--canvas);
}
.isar-promise-stats .label {
  margin-top: var(--sp-xs);
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--slate);
}
@media (max-width: 768px) {
  .isar-promise-card {
    grid-template-columns: 1fr;
    padding: var(--sp-xxl);
  }
}

/* ---------- Credentials ----------
   One scrolling row of individual certification cards -- publisher on the
   first line, credential title below -- using the same auto-scroll/loop
   mechanism as the related-services row (.isar-related-row is generic;
   the JS auto-scroll init selects on that class alone). Fixed brand navy
   like the promise card — see the colour rule at the top. */
.isar-credentials {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--sp-xl) var(--sp-section);
}
/* Matches .isar-services .eyebrow/h2 exactly — this section had its own
   separate, unsynced rules (13px caption eyebrow with no mono font, a
   fixed 40px heading with no letter-spacing/text-wrap) left over from
   before that pattern was standardized site-wide. */
.isar-credentials .eyebrow,
.isar-testimonials .eyebrow,
.isar-promise .eyebrow {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  font-weight: 400;
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg3);
  text-align: left;
  margin: 0 0 var(--sp-sm);
}
.isar-credentials h2,
.isar-testimonials h2,
.isar-promise > h2 {
  /* No max-width: the shared 22ch cap (from .isar-services h2) wraps
     "Zertifiziert. Geprüft. Anerkannt." (33 characters) onto two lines —
     this heading should read as one. */
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(28px, 3.2vw, 42px);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--fg1);
  text-align: left;
  margin: 0 0 var(--sp-xxl);
  text-wrap: balance;
}
.isar-credentials-card,
.isar-testimonials-card {
  /* Left/right padding moved to .isar-credentials-row below — with it
     here instead, the row (and its edge-fade mask) sat inset from the
     card's actual left/right edges by this padding, so the fade
     happened partway into the card rather than right at its border. */
  position: relative;
  overflow: hidden;
  background: var(--ink);
  border-radius: var(--radius-md);
  padding: var(--sp-xxl) 0;
}
/* Isar-wave watermark behind the tiles — same waveFrame() system as the
   footer/404 waves (see site.js), just fainter (0.22 vs 0.55 opacity) and
   scoped to this card. */
/* Exactly .isar-footer-wave's own block layout (no flex) — each row is a
   plain stacked <pre>, same as the footer, sized purely by its own
   content/line-height, nothing stretching its width. Vertical centering
   (6 rows, taller than the footer's 3) uses a transform instead of flex
   justify-content, since transform can't affect width the way flex's
   default cross-axis stretch did — that stretch is what was quietly
   widening these rows past the footer's real width. */
.isar-credentials-wave-box,
.isar-testimonials-wave-box {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  overflow: hidden;
  padding: var(--sp-xs) 0;
  pointer-events: none;
  /* Same slim edge fade as the pill row above it, on the watermark itself
     so the wave text doesn't cut off hard at the card's rounded corners. */
  mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%);
}
.isar-credentials-wave-box .isar-footer-wave-row,
.isar-testimonials-wave-box .isar-footer-wave-row {
  margin: 0 !important;
  opacity: 0.55;
}
/* Endless auto-scroll, same pause-on-hover mechanism as the
   related-services row (.isar-related-row is the class site.js's
   auto-scroll init selects on; a scroll-reverse data attribute on this
   one flips the direction) — the tile under the cursor still brightens
   via the existing --spot mechanism while it scrolls. Gap is 3x the
   shared --sp-md (200% larger, per request) and the edge fade is
   narrower than the shared 24px — both overridden here rather than in
   .isar-related-row itself, since that class is also used for the
   unrelated "Passt dazu" related-services rows on service pages. */
.isar-credentials-row,
.isar-testimonials-row {
  /* Padding-left/right moved here from .isar-credentials-card, so the
     row's own box — and its mask fade below — reaches the card's true
     edges instead of stopping short at the card's old padding. */
  position: relative;
  flex-wrap: nowrap;
  padding-left: var(--sp-xxl) !important;
  padding-right: var(--sp-xxl) !important;
  gap: 36px !important;
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%) !important;
  mask-image: linear-gradient(to right, transparent 0, black 2px, black calc(100% - 2px), transparent 100%) !important;
}
.cred-pill {
  /* Caps how wide a pill can grow -- short badge text (e.g.
     "CompTIA-Zertifiziert") never gets near this, but the testimonials
     row's full-sentence quotes would otherwise stay on one very wide
     line instead of wrapping like a card. */
  max-width: 320px;
  /* flex: 0 0 auto — without it, nowrap + the row's default flex-shrink:1
     squeezes every pill down to fit the container instead of letting the
     row overflow (which is what makes it scrollable): measured this
     collapsing pills to ~46px wide with their text wrapping into a
     640px-tall column instead of staying a normal-width pill. */
  position: relative;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
  min-width: 200px;
  background: var(--canvas);
  border: 1px solid color-mix(in oklab, var(--canvas) 18%, transparent);
  border-radius: var(--radius-sm);
  padding: var(--sp-md) var(--sp-lg);
}
.cred-pill-brand {
  font-family: var(--sans-body);
  font-size: var(--fs-body-lg);
  font-weight: 700;
  line-height: var(--lh-tight);
  color: var(--ink);
  margin: 0;
}
.cred-pill-title {
  /* Raw --ink mix, not the theme-reactive --ink-mute: this pill's own
     background is the fixed --canvas (same in both themes, see the card
     colour rule at the top of this file), so its text needs a fixed dark
     colour too — --ink-mute flips light in dark mode and would wash out. */
  font-size: var(--fs-body-sm);
  line-height: var(--lh-snug);
  color: color-mix(in oklab, var(--ink) 70%, var(--canvas) 30%);
  margin: 0;
}
@media (max-width: 640px) {
  .isar-credentials-card {
    padding: var(--sp-xl);
  }
}

/* ---------- Testimonials ----------
   Deliberately the same card as .isar-credentials below (wave-watermarked
   dark band + an auto-scrolling row of canvas pills) rather than its own
   design -- .isar-testimonials/.isar-testimonials-wave-box/
   .isar-testimonials-row exist only because the wave-paint and pill-row
   rules key off a box/row per section (see the querySelector list in
   site.js); every actual rule is shared with .isar-credentials via the
   combined selectors below. */
.isar-testimonials {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--sp-xl) var(--sp-section);
}

/* ---------- Projects (case studies) ---------- */
.isar-projects {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-section) var(--sp-xl);
}
.isar-projects .eyebrow {
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
  margin-bottom: var(--sp-sm);
}
.isar-projects h2 {
  font-family: var(--serif-display);
  font-size: var(--fs-display-md);
  color: var(--fg1);
  margin: 0 0 var(--sp-xxl);
}
.project-grid {
  display: flex;
  flex-direction: column;
  gap: var(--sp-lg);
}
.project-card {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--sp-xl);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--sp-xl);
}
.project-main {
  display: flex;
  flex-direction: column;
  gap: var(--sp-md);
  min-width: 0;
}
.project-main h3 {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  font-weight: 400;
  color: var(--fg1);
  margin: 0;
}
.project-desc {
  color: var(--fg2);
  font-size: var(--fs-body-sm);
  line-height: var(--lh-snug);
  margin: 0;
}
.project-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-sm);
  margin-top: auto;
}
.project-tag {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: 4px var(--sp-md);
  font-size: var(--fs-micro);
  color: var(--fg2);
}
.project-side {
  display: flex;
  flex-direction: column;
  gap: var(--sp-sm);
}
.project-meta {
  background: var(--ink);
  color: var(--canvas);
  border-radius: var(--radius-sm);
  padding: var(--sp-sm) var(--sp-md);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  /* It is a <p>, so it inherited the theme's 16px paragraph margin on top of
     .project-side's 8px flex gap: 24px to the first stat, against 8px between
     the stats themselves. Zero margin leaves the gap alone to space it, so the
     meta line sits in the same rhythm as the stats under it. */
  margin: 0;
}
.project-stat {
  display: flex;
  align-items: baseline;
  gap: var(--sp-sm);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-sm) var(--sp-md);
}
.project-stat .value {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-sm);
  color: var(--sky);
  flex-shrink: 0;
}
/* --sky is a fixed (non-theme-reactive) pale blue -- reads fine against
   this card's --bg in dark mode (contrast ~13:1) but is nearly invisible
   in light mode (~1.1:1, fails WCAG AA even for large text), since --bg
   itself flips to a light warm-grey there. --sky-deep isn't usable as a
   drop-in fix: it's already spoken for by --selection, tuned for pale
   text-on-selection-highlight contrast, not this darker-on-light need.
   Same brand blue (#4C6FA3, already used as dark mode's --bg-accent/
   --sky-deep base) darkened further for light-mode contrast (~6.5:1). */
:root[data-theme="light"] .project-stat .value {
  color: color-mix(in oklab, #4C6FA3 80%, black 20%);
}
.project-stat .label {
  font-size: var(--fs-micro);
  color: var(--fg3);
  line-height: var(--lh-snug);
}
.project-quote {
  grid-column: 1 / -1;
  background: var(--ink);
  color: var(--canvas);
  border-radius: var(--radius-sm);
  padding: var(--sp-lg) var(--sp-xl);
  margin: 0;
}
.project-quote q {
  display: block;
  font-style: normal;
  font-size: var(--fs-body-md);
  line-height: var(--lh-snug);
  color: var(--canvas);
}
.project-quote q::before,
.project-quote q::after {
  content: "";
}
.project-quote .project-quote-who {
  margin-top: var(--sp-sm);
  color: var(--slate);
  font-size: var(--fs-caption);
}
@media (max-width: 800px) {
  .project-card {
    grid-template-columns: 1fr;
  }
  .project-quote {
    grid-column: 1;
  }
}

/* ---------- Booking / contact section ---------- */
.isar-booking {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-section) var(--sp-xl);
  border-top: 1px solid var(--border);
}
.isar-booking .contact-grid {
  display: grid;
  grid-template-columns: minmax(280px, 0.8fr) minmax(420px, 1.2fr);
  gap: var(--sp-3xl);
  align-items: start;
}
.isar-booking .eyebrow {
  font-size: var(--fs-caption);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg3);
  margin-bottom: var(--sp-sm);
}
.isar-booking h2 {
  font-family: var(--serif-display);
  font-size: var(--fs-display-md);
  color: var(--fg1);
  margin: 0 0 var(--sp-lg);
  text-wrap: balance;
}
.isar-booking .intro {
  color: var(--fg2);
  max-width: 440px;
  margin: 0 0 var(--sp-xxl);
}
.isar-booking form,
.isar-booking-widget {
  display: flex;
  flex-direction: column;
  gap: var(--sp-lg);
  padding: var(--sp-xxl);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}
/* Progress bar: bleeds to the widget's outer edges (negative margin cancels
   the card's own padding), one cell per step. Colour shift only between
   pending/active/done — no motion beyond the text-colour transition. */
.ibw-progress {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: calc(var(--sp-xxl) * -1) calc(var(--sp-xxl) * -1) 0;
  border-bottom: 1px solid var(--border);
}
.ibw-progress-step {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xxs);
  align-items: center;
  padding: var(--sp-md) var(--sp-sm);
  text-align: center;
  border-right: 1px solid var(--border);
  transition: background var(--dur-comp) var(--ease-out);
}
.ibw-progress-step:last-child {
  border-right: none;
}
.ibw-progress-num {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
  color: var(--fg4);
}
.ibw-progress-label {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg4);
}
.ibw-progress-step.is-active {
  background: var(--bg-accent);
}
.ibw-progress-step.is-active .ibw-progress-num {
  color: var(--fg3);
}
.ibw-progress-step.is-active .ibw-progress-label {
  color: var(--fg-on-sky);
}
.ibw-progress-step.is-done .ibw-progress-num,
.ibw-progress-step.is-done .ibw-progress-label {
  color: var(--fg3);
}
.isar-booking .row2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-md);
}
/* German address convention: Straße gets most of the width, Hausnummer is
   short; PLZ is a fixed 5 digits, Ort gets the rest. */
.isar-booking .row2.row2-street {
  grid-template-columns: 2.4fr 1fr;
}
.isar-booking .row2.row2-zip {
  grid-template-columns: 1fr 2fr;
}
.isar-booking .field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
}
.isar-booking .field label {
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--fg2);
}
.isar-booking .field input,
.isar-booking .field textarea {
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  color: var(--fg1);
  background: var(--bg);
  border: 1px solid var(--border);
  padding: var(--sp-sm) var(--sp-md);
  border-radius: var(--radius-sm);
  outline: none;
  width: 100%;
  box-sizing: border-box;
}
.isar-booking .field input:focus,
.isar-booking .field textarea:focus {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px var(--sky);
}
.isar-booking .field textarea {
  resize: vertical;
  min-height: 90px;
  font-family: inherit;
}
.isar-booking form .isar-btn {
  align-self: flex-start;
  border: none;
  cursor: pointer;
  font-size: var(--fs-body-sm);
}
/* Honeypot. Kept in the layout but off-screen rather than display:none —
   some bots skip fields that are display:none, which defeats the point. */
.isar-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
.isar-form-status {
  border-radius: var(--radius-sm);
  padding: var(--sp-md) var(--sp-lg);
  margin: 0 0 var(--sp-lg);
  font-size: var(--fs-body-sm);
}
.isar-form-status.is-ok {
  background: var(--bg-accent);
  color: var(--fg-on-sky);
}
.isar-form-status.is-error {
  background: color-mix(in oklab, var(--bg-elevated) 80%, var(--ink) 20%);
  color: var(--fg1);
  border: 1px solid var(--border-strong);
}
@media (max-width: 800px) {
  .isar-booking .contact-grid {
    grid-template-columns: 1fr;
  }
}

/* ---------- Booking widget: service -> slot -> details -> success ---------- */
.isar-booking-widget [hidden] {
  display: none !important;
}
.ibw-step {
  display: flex;
  flex-direction: column;
  gap: var(--sp-lg);
  /* Set via JS (site.js) to the "Kontakt"/details step's own natural
     height, the tallest of the four -- so the widget doesn't resize as
     you move between steps with less content. */
  min-height: var(--ibw-step-min-h, auto);
}
/* The shorter steps (service picker, success message) get their content
   vertically centred within that taller box instead of sitting pinned
   to the top with a bare gap below -- "slot" is dynamic (day tabs + a
   time grid, JS-built) and generally fills the space on its own, so it's
   left out here. */
.ibw-step-service,
.ibw-step-success {
  justify-content: center;
}
.ibw-step-success {
  align-items: center;
  text-align: center;
}
.ibw-step-service .ibw-services {
  gap: var(--sp-lg);
}
.ibw-step-label {
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--fg2);
  margin: 0;
}
.ibw-back {
  align-self: flex-start;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-xs) var(--sp-md);
  font-family: var(--sans-body);
  font-size: var(--fs-caption);
  color: var(--fg2);
  cursor: pointer;
}
.ibw-back:hover {
  color: var(--fg1);
  background: var(--bg);
  border-color: var(--border-strong);
  box-shadow: none;
}
.ibw-services {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-md);
}
.ibw-service {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
  text-align: left;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-lg);
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg1);
  cursor: pointer;
}
.ibw-service-name {
  font-size: var(--fs-body-md);
}
.ibw-service-desc {
  font-size: var(--fs-caption);
  font-weight: 400;
  color: var(--fg2);
  line-height: 1.4;
}
.ibw-service-duration {
  font-size: var(--fs-caption);
  font-weight: 400;
  color: var(--fg3);
  margin-top: auto;
  padding-top: var(--sp-xs);
}
/* Explicit background/color/box-shadow here, not just border-color --
   Kadence's global `button:hover` rule (background: var(--global-palette-
   btn-bg-hover)) otherwise wins that property on every plain <button>,
   since these selectors only outrank it on the properties they actually
   declare. The active day-tab is excluded so hovering it doesn't flash
   back to the unselected look. */
.ibw-service:hover,
.ibw-service:focus-visible,
.ibw-slot:hover,
.ibw-slot:focus-visible,
.ibw-week-nav:not(:disabled):hover,
.ibw-week-nav:not(:disabled):focus-visible,
.ibw-day-tab:not(.is-active):not(:disabled):hover,
.ibw-day-tab:not(.is-active):not(:disabled):focus-visible {
  background: var(--bg);
  color: var(--fg1);
  border-color: var(--border-strong);
  box-shadow: none;
}
@media (prefers-reduced-motion: no-preference) {
  .ibw-service,
  .ibw-day-tab,
  .ibw-week-nav,
  .ibw-slot {
    transition: transform 150ms ease-out, border-color 150ms ease-out;
  }
  .ibw-service:hover,
  .ibw-service:focus-visible,
  .ibw-slot:hover,
  .ibw-slot:focus-visible,
  .ibw-week-nav:not(:disabled):hover,
  .ibw-week-nav:not(:disabled):focus-visible,
  .ibw-day-tab:not(:disabled):hover,
  .ibw-day-tab:not(:disabled):focus-visible {
    transform: translateY(-2px);
  }
}
.ibw-week-controls {
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
  padding-bottom: var(--sp-md);
  margin-bottom: var(--sp-md);
  border-bottom: 1px solid var(--border);
}
.ibw-week-nav {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  font-size: var(--fs-body-md);
  line-height: 1;
  color: var(--fg1);
  cursor: pointer;
}
.ibw-week-nav:disabled {
  opacity: 0.35;
  cursor: default;
}
.ibw-days-row {
  flex: 1 1 auto;
  min-width: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sp-xs);
}
.ibw-day-tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-width: 0;
  min-height: 52px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--sp-sm) var(--sp-xs);
  font-family: var(--sans-body);
  cursor: pointer;
}
.ibw-day-tab:disabled {
  opacity: 0.35;
  cursor: default;
}
.ibw-day-tab.is-placeholder {
  background: transparent;
  border-style: dashed;
  opacity: 0.3;
}
.ibw-day-tab-weekday {
  font-size: var(--fs-caption);
  color: var(--fg3);
  text-transform: capitalize;
}
.ibw-day-tab-date {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg1);
}
/* CI navy in light mode -- matches the primary button, headings and the
   logo plate, instead of the soft pale-blue accent tint. Dark mode keeps
   the lifted accent: --ink is a fixed brand constant that doesn't flip
   with the theme, and it sits almost the same near-black as --bg/
   --bg-elevated there, so it would all but disappear (the same bug just
   fixed on .isar-btn.primary). */
.ibw-day-tab.is-active {
  background: var(--ink);
  border-color: var(--ink);
}
.ibw-day-tab.is-active .ibw-day-tab-weekday,
.ibw-day-tab.is-active .ibw-day-tab-date {
  color: var(--fg-on-ink);
}
:root[data-theme="dark"] .ibw-day-tab.is-active {
  background: var(--bg-accent);
  border-color: var(--bg-accent);
}
:root[data-theme="dark"] .ibw-day-tab.is-active .ibw-day-tab-weekday,
:root[data-theme="dark"] .ibw-day-tab.is-active .ibw-day-tab-date {
  color: var(--fg-on-sky);
}
.ibw-slots-panel {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-content: flex-start;
  gap: var(--sp-sm);
  max-height: 220px;
  overflow-y: auto;
  padding: var(--sp-xs) var(--sp-xs) var(--sp-xs) 0;
}
.ibw-slot {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  padding: var(--sp-xs) var(--sp-md);
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  color: var(--fg1);
  cursor: pointer;
}
.ibw-loading,
.ibw-error {
  font-size: var(--fs-body-sm);
  color: var(--fg3);
}
.ibw-summary {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg1);
  margin: 0;
}
.ibw-submit {
  align-self: flex-start;
  margin-top: var(--sp-sm);
}
.ibw-success-title {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  color: var(--fg1);
  margin: 0 0 var(--sp-xs);
}
/* One-shot celebration on reaching the success step (site.js) -- 3 ASCII
   rockets launch and burst, same mono-ASCII character technique as the
   site's wave motif. Unlike the wave (which cycles sky/slate/canvas on
   a fixed --ink background), this sits on the widget's own theme-
   reactive --bg-elevated, where --canvas would go near-invisible in
   light mode -- a single accent colour (--sky) instead, which has
   working contrast in both themes. Fixed height reserved up front so
   the step doesn't jump as the rocket trails/burst paint in. */
.isar-rocket-fx {
  display: block;
  margin: 0 0 var(--sp-md);
  height: 108px;
  overflow: hidden;
  font-family: var(--mono-ascii, "DejaVu Sans Mono", "Menlo", "Consolas", monospace);
  font-size: 14px;
  line-height: 1.2;
  white-space: pre;
  background: transparent;
  border: none;
  padding: 0;
  color: var(--sky);
}
@media (max-width: 500px) {
  .ibw-services {
    grid-template-columns: 1fr;
  }
  .ibw-day-tab {
    min-height: 44px;
    padding: var(--sp-xs) 2px;
  }
  .ibw-day-tab-weekday,
  .ibw-day-tab-date {
    font-size: 11px;
  }
  .ibw-week-nav {
    width: 30px;
    height: 30px;
    font-size: var(--fs-caption);
  }
}

/* ---------- Footer ---------- */
.site-footer {
  /* Divider lives on .isar-footer-wave below, not here -- that element
     already has rounded top corners, so a border-top declared there
     follows the same curve. Declared on this outer, full-bleed, square
     element instead it would be a straight line spanning past where the
     wave card's corners actually curve inward. */
}
/* Kadence's default "© {year} {site} - WordPress Theme by Kadence WP" bar —
   removed entirely; our own footer contact block is the only footer content. */
.site-footer-wrap {
  display: none;
}

/* ---------- Footer ASCII wave band: the one ornamental motif, per the
   design system README ("the wave appears at most once per page"). Text
   content is generated/animated in site.js; CSS just lays out the rows. ---------- */
.isar-footer-wave {
  overflow: hidden;
  background: var(--ink);
  padding: var(--sp-xs) 0;
  /* Top edge only — this is where the ink band meets the lighter page
     content above it; the bottom is a plain internal seam into
     .isar-footer-contact, nothing to round against. */
  border-radius: var(--radius-md) var(--radius-md) 0 0;
  /* Divider (moved here from .site-footer): declaring the border on the
     same element as the radius makes it follow the rounded corners
     automatically instead of cutting straight across them. */
  border-top: 1px solid var(--border);
}
.isar-footer-wave-row {
  /* Kadence's theme stylesheet styles bare <pre> as a code block (padding,
     a light-blue background, a border) — all overridden here, confirmed
     via computed-style inspection on the live site (padding:21px and
     background:rgb(237,242,247) were leaking through and washing out the
     dark band into a tall grey box instead of a thin dark strip). */
  margin: 0;
  padding: 0;
  background: transparent;
  border: none;
  border-radius: 0;
  font-family: var(--mono-ascii, "DejaVu Sans Mono", "Menlo", "Consolas", monospace);
  font-size: 14px;
  line-height: 1.18;
  white-space: pre;
  overflow: hidden;
  opacity: 0.55;
}
.isar-footer-wave-row[data-wave-offset="0"] { color: var(--sky); }
.isar-footer-wave-row[data-wave-offset="1"] { color: var(--slate); }
.isar-footer-wave-row[data-wave-offset="2"] { color: var(--canvas); }
/* Credentials wave is 6 rows (footer/404 are 3) — same 3-colour cycle
   repeated once more rather than inventing extra colours. */
.isar-footer-wave-row[data-wave-offset="3"] { color: var(--sky); }
.isar-footer-wave-row[data-wave-offset="4"] { color: var(--slate); }
.isar-footer-wave-row[data-wave-offset="5"] { color: var(--canvas); }

/* ---------- 404 page: same wave band, carrying the "404" digits ---------- */
.isar-404-wave-box .isar-footer-wave-row {
  opacity: 0.4;
}
.isar-404-digits {
  position: absolute;
  top: 50%;
  left: 0;
  font-family: var(--mono-ascii, "DejaVu Sans Mono", "Menlo", "Consolas", monospace);
  font-size: 26px;
  font-weight: 500;
  line-height: 1;
  color: var(--canvas);
  white-space: nowrap;
  pointer-events: none;
}

/* ---------- Footer contact ----------
   .legal is a full-bleed dark bar (matches the kit's own footer mock: a
   distinct --ink strip below the content columns, not a hairline-topped
   continuation of the same background) so it has to sit OUTSIDE the
   max-width/padding wrapper — hence the extra .isar-footer-contact-inner
   layer that carries what .isar-footer-contact used to carry directly. */
.isar-footer-contact {
  color: var(--fg3);
}
.isar-footer-contact-inner {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: var(--sp-3xl) var(--sp-xl) var(--sp-xxl);
}
.isar-footer-contact .row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--sp-xl);
}
.isar-footer-contact .col.brand .isar-logo {
  /* height now matches the base .isar-logo rule (nav uses the same
     size) -- kept here only for the margin. */
  margin-bottom: var(--sp-md);
}
.isar-footer-contact .col.brand p {
  font-size: var(--fs-caption);
  color: var(--fg3);
  margin: var(--sp-sm) 0 0;
}
/* Roughly one blank line between the brand statements, so EU hosting and the
   support languages each read as their own claim instead of a run-on. */
.isar-footer-contact .col.brand p + p {
  margin-top: 1.6em;
}
.isar-footer-contact .col h3 {
  font-family: var(--sans-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg2);
  margin: 0 0 var(--sp-md);
}
.isar-footer-contact .col a,
.isar-footer-contact .col span {
  display: block;
  color: var(--fg2);
  text-decoration: none;
  font-size: var(--fs-body-sm);
  line-height: 2;
}
.isar-footer-contact .col a:hover {
  color: var(--fg1);
}
/* Kontakt column rows: email/phone with icons (same set as the now-
   removed booking widget contact-info block). The address line was
   dropped -- it's already covered in Impressum. */
.isar-footer-contact .col a.row {
  display: flex;
  align-items: center;
  gap: var(--sp-sm);
}
.isar-footer-contact .col .row svg {
  width: 16px;
  height: 16px;
  stroke: var(--slate);
  stroke-width: 1.75;
  fill: none;
  flex-shrink: 0;
}
.isar-footer-contact .legal {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--sp-lg);
  padding: var(--sp-lg) var(--sp-xl);
  background: var(--ink);
  color: var(--slate);
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--tracking-caps);
}
.isar-footer-legal-links {
  display: flex;
  gap: var(--sp-lg);
}
.isar-footer-contact .legal a {
  color: var(--slate);
  text-decoration: none;
}
.isar-footer-contact .legal a:hover {
  color: var(--canvas);
}
.isar-footer-contact .legal .blink {
  color: var(--sky);
  animation: isar-blink 1.4s step-end infinite;
}
@media (prefers-reduced-motion: reduce) {
  .isar-footer-contact .legal .blink { animation: none; }
}
@media (max-width: 640px) {
  .isar-footer-contact .row {
    grid-template-columns: 1fr 1fr;
  }
  .isar-footer-contact .col.brand {
    grid-column: 1 / -1;
  }
  .isar-footer-contact .legal {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--sp-sm);
  }
}

/* ---------- Floating contact widget (homepage only) ---------- */
.isar-float-contact {
  position: fixed;
  right: var(--sp-lg);
  top: 50%;
  transform: translateY(-50%);
  z-index: var(--z-sticky);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--sp-sm);
}
/* Fixed dark --ink, not the theme-reactive --bg-elevated: a light pill on
   a light page reads as barely-there, so this now matches the same
   "pops in either theme" fixed-ink treatment used for the nav CTA and
   mega-dropdown promo, instead of blending into the background. */
.isar-float-contact .item {
  display: flex;
  align-items: center;
  width: 38px;
  background: var(--ink);
  border: 1px solid var(--border-on-ink);
  border-radius: var(--radius-sm);
  overflow: hidden;
  white-space: nowrap;
  box-shadow: var(--shadow-floating);
  transition: width var(--dur-comp) var(--ease-out);
}
.isar-float-contact .item:hover {
  width: 210px;
}
.isar-float-contact .item .label {
  flex: 1;
  min-width: 0;
  text-align: center;
  opacity: 0;
  font-size: var(--fs-caption);
  color: var(--slate);
  transition: opacity var(--dur-micro) var(--ease-out);
}
.isar-float-contact .item:hover .label {
  padding-left: var(--sp-md);
  opacity: 1;
}
.isar-float-contact .item a.icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  flex-shrink: 0;
  color: var(--canvas);
  text-decoration: none;
}
/* Dark mode: a fixed --ink pill on an --ink-ish page background would
   blend in rather than pop, so this flips to --canvas here specifically
   — light pill, dark icon — while staying fixed --ink in light mode. */
:root[data-theme="dark"] .isar-float-contact .item {
  background: var(--canvas);
  border-color: color-mix(in oklab, var(--ink) 18%, transparent);
}
:root[data-theme="dark"] .isar-float-contact .item .label {
  /* Raw --ink mix, not the theme-reactive --ink-mute: this label sits on
     the fixed --canvas set above, so it needs a fixed dark colour too —
     --ink-mute flips light in dark mode and would wash out here. */
  color: color-mix(in oklab, var(--ink) 70%, var(--canvas) 30%);
}
:root[data-theme="dark"] .isar-float-contact .item a.icon {
  color: var(--ink);
}

/* ---------- Dark mode is handled by assets-tokens.css :root[data-theme="dark"] ---------- */
@media (max-width: 640px) {
  .isar-float-contact { display: none; }
}

/* ---------- Login gateway (behind the nav account icon) ----------
   Deliberately inert: neither portal exists yet, so the forms are
   disabled rather than wired to nothing — a real password typed into a
   form with no backend is still a bad idea even though nothing would
   actually be transmitted. */
.isar-login-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--sp-xl);
}
.isar-login-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
  padding: var(--sp-xxl);
}
.isar-login-card .isar-login-icon {
  width: 34px;
  height: 34px;
  color: var(--slate);
  margin-bottom: var(--sp-lg);
}
.isar-login-card h2 {
  font-family: var(--serif-display);
  font-size: var(--fs-heading-md);
  color: var(--fg1);
  margin: 0 0 var(--sp-sm);
}
.isar-login-card .isar-login-desc {
  font-size: var(--fs-body-sm);
  line-height: var(--lh-relaxed);
  color: var(--fg2);
  margin: 0 0 var(--sp-xl);
}
.isar-login-card .field {
  display: flex;
  flex-direction: column;
  gap: var(--sp-xs);
  margin-bottom: var(--sp-md);
}
.isar-login-card .field label {
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--fg2);
}
.isar-login-card .field input {
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  color: var(--fg1);
  background: var(--bg);
  border: 1px solid var(--border);
  padding: var(--sp-sm) var(--sp-md);
  border-radius: var(--radius-sm);
  outline: none;
  width: 100%;
  box-sizing: border-box;
}
.isar-login-card .field input:disabled {
  color: var(--fg4);
  cursor: not-allowed;
}
.isar-login-card .isar-btn {
  width: 100%;
  text-align: center;
  border: none;
  margin-top: var(--sp-sm);
}
.isar-login-card .isar-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.isar-login-card .isar-login-note {
  font-size: var(--fs-caption);
  color: var(--fg3);
  margin: var(--sp-md) 0 0;
}
.isar-login-help {
  font-size: var(--fs-caption);
  color: var(--fg3);
  margin: var(--sp-xl) 0 0;
  text-align: center;
}

/* ---------- Custom cursor ----------
   32x32 arrowhead, brand-drawn (isar-cursor-light/dark.png), hotspot at
   the tip (2,2). JS adds .isar-custom-cursor to <html> only once it's
   confirmed a fine pointer is present, so nothing here applies (native
   cursor stays) if that never happens — touch devices or JS simply not
   running. Falls back to the native cursor on coarse pointers and
   forced-colors mode regardless, since a custom raster cursor can't
   respect a forced-colors palette. */
html.isar-custom-cursor,
html.isar-custom-cursor a,
html.isar-custom-cursor button,
html.isar-custom-cursor label {
  cursor: url("isar-cursor-light.png") 2 2, auto;
}
html.isar-custom-cursor[data-theme="dark"],
html.isar-custom-cursor[data-theme="dark"] a,
html.isar-custom-cursor[data-theme="dark"] button,
html.isar-custom-cursor[data-theme="dark"] label {
  cursor: url("isar-cursor-dark.png") 2 2, auto;
}
html.isar-custom-cursor input,
html.isar-custom-cursor textarea,
html.isar-custom-cursor [contenteditable="true"] {
  cursor: text;
}
html.isar-custom-cursor select {
  cursor: default;
}
@media (pointer: coarse), (forced-colors: active) {
  html.isar-custom-cursor,
  html.isar-custom-cursor a,
  html.isar-custom-cursor button,
  html.isar-custom-cursor label {
    cursor: auto;
  }
}

/* ---------- Touch targets (WCAG 2.5.5) ----------
   Kadence's own drawer toggle measures ~37x31px and the drawer's menu
   links ~38px high. Both are parent-theme markup, so rather than restyle
   them (which changes the header's look), the same invisible centred
   pseudo-element used on the utility icons above extends each hit area to
   44px. Nothing moves on screen; only the pointer/touch target grows. */
#mobile-toggle,
.menu-toggle-open.drawer-toggle,
.menu-toggle-close.drawer-toggle {
  position: relative;
}
#mobile-toggle::before,
.menu-toggle-open.drawer-toggle::before,
.menu-toggle-close.drawer-toggle::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 44px;
  height: 44px;
  transform: translate(-50%, -50%);
}
/* Drawer links keep their existing type and spacing; the extra height is
   padding, so the tap area reaches 44px without a visible gap change. */
#mobile-drawer .drawer-navigation .menu-item > a {
  min-height: 44px;
  display: flex;
  align-items: center;
}

/* ---------- Closing CTA band ----------
   The booking widget is deliberately excluded from Unser Team, Unser
   Unternehmen, Karriere, FAQ and Rechtliches (see $isar_booking_excluded_slugs),
   which left those pages with no conversion path at all -- an #booking anchor
   there points at nothing. This band links to the dedicated /termin/ page,
   which does carry the widget. Self-contained rather than reusing .cta-row,
   which is only ever styled inside a hero. */
.isar-cta-band {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--sp-xl) var(--sp-section);
}
.isar-cta-band-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-lg);
  padding: var(--sp-xl);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.isar-cta-band h2 {
  margin: 0 0 var(--sp-xs);
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(22px, 2.2vw, 30px);
  line-height: 1.15;
  color: var(--fg1);
}
.isar-cta-band p {
  margin: 0;
  color: var(--fg2);
  max-width: 52ch;
}
@media (max-width: 640px) {
  .isar-cta-band-inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ---------- Hero entrance sequence ----------
   Staged reveal in the brief's order: eyebrow, headline, lede, CTAs, each
   one --motion-stagger behind the last. Driven by CSS animation rather
   than JS so it runs without waiting on the footer bundle, and so
   reduced-motion is handled by the collapsed tokens (1ms duration + 0ms
   stagger = content simply present) with no separate media query here.

   Only opacity and transform are animated. The photo panel uses a
   clip-path mask rather than the 12px translation the brief also allows:
   .isar-hero--split has overflow:hidden, so translating the panel would
   open a visible gap at its top edge for the length of the animation. */
@keyframes isar-hero-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}
@keyframes isar-hero-photo-in {
  from { opacity: 0; clip-path: inset(0 0 6% 0); }
  to   { opacity: 1; clip-path: inset(0 0 0 0); }
}
@keyframes isar-hero-overlay-in {
  from { opacity: 0; }
  to   { opacity: var(--isar-visual-opacity, 0.98); }
}
/* Everything below is gated on .isar-motion, set by the inline head script.
   These animations start at opacity:0 with fill-mode both, so without the
   gate anything that stops them running -- no JS, a script error, a print
   stylesheet -- would leave the hero permanently invisible. No class means
   no animation and a hero that is simply there.

   Targeted by role rather than :nth-child: wpautop injects a stray empty
   <p> between the badge and the h1, so positional selectors put the stagger
   on the wrong elements and left the CTA row animating first. */
.isar-motion .isar-hero--split-content > .badge,
.isar-motion .isar-hero--split-content > h1,
.isar-motion .isar-hero--split-content > .lede,
.isar-motion .isar-hero--split-content > .cta-row {
  animation: isar-hero-rise var(--motion-hero) var(--motion-ease-entrance) both;
}
.isar-motion .isar-hero--split-content > h1       { animation-delay: calc(var(--motion-stagger) * 1); }
.isar-motion .isar-hero--split-content > .lede    { animation-delay: calc(var(--motion-stagger) * 2); }
.isar-motion .isar-hero--split-content > .cta-row { animation-delay: calc(var(--motion-stagger) * 3); }
.isar-motion .isar-hero--split-photo {
  animation: isar-hero-photo-in var(--motion-hero) var(--motion-ease-entrance) both;
}
/* Enters once and then holds -- no looping, no idle drift. The end state
   matches .isar-hero-visual's static opacity so nothing shifts when the
   animation hands back control. */
.isar-motion .isar-hero--split-photo .isar-hero-visual {
  animation: isar-hero-overlay-in var(--motion-section) var(--motion-ease-entrance) both;
  animation-delay: calc(var(--motion-stagger) * 4);
}

/* ---------- Service cards: regular grid + restrained spotlight ----------
   The grid was flex-wrap with max-width:320px per card, so eight cards
   flowed into uneven centred rows. Switched to a real 3/2/1 grid, but only
   for sections with five or more cards: :has() keeps the two- and
   four-card sections (Unternehmen, Karriere) on the centred flex layout,
   where a fixed three-column track would strand them against a gap.
   :has() is already relied on elsewhere in this file. */
.isar-services .grid:has(> :nth-child(5)) {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  justify-content: stretch;
}
.isar-services .grid:has(> :nth-child(5)) > * {
  max-width: none;
}
@media (max-width: 1000px) {
  .isar-services .grid:has(> :nth-child(5)) { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .isar-services .grid:has(> :nth-child(5)) { grid-template-columns: 1fr; }
}

/* Home's "Ein Team. Ein Ansprechpartner. Eine Telefonnummer." grid: 2
   columns (2x4) for its 8 cards on desktop, not the shared 3-column
   default above -- scoped to #was-wir-tun (the section's own id) rather
   than changing the shared rule, since the Leistungen overview page has
   its own 8-card grid on the same selector and wasn't asked to change.
   The ID alone outweighs the shared rule's specificity regardless of
   source order -- including inside the shared rule's own <=1000px/<=640px
   breakpoints, which an unqualified override like this would otherwise
   silently beat too, so mobile needs its own explicit 1-column override
   below rather than "inheriting" the shared rule's collapse. */
#was-wir-tun .grid:has(> :nth-child(5)) {
  grid-template-columns: repeat(2, 1fr);
}
@media (max-width: 640px) {
  /* One column (8x1): two-per-row reads cluttered at phone widths. */
  #was-wir-tun .grid:has(> :nth-child(5)) {
    grid-template-columns: 1fr;
  }
}

/* Registered so the tint can transition -- a plain custom property inside
   rgba() substitutes fine but animates as a discrete jump. Where @property
   is unsupported the highlight simply snaps in instead of fading, which is
   an acceptable degradation. */
@property --spot-a {
  syntax: "<number>";
  inherits: false;
  initial-value: 0;
}
.svc {
  --spot-a: 0;
  /* background-image paints above background-color but below content, so
     the tint never sits over the card's own text. */
  background-image: radial-gradient(
    260px circle at var(--spot-x, 50%) var(--spot-y, 0%),
    rgba(76, 111, 163, var(--spot-a)) 0%,
    transparent 70%
  );
  transition:
    transform var(--motion-panel) var(--motion-ease-state),
    border-color var(--motion-panel) var(--motion-ease-state),
    box-shadow var(--motion-panel) var(--motion-ease-state),
    --spot-a var(--motion-panel) var(--motion-ease-state);
}
/* focus-within, not just hover, so keyboard users get the same affordance
   and the card is never hover-dependent. */
.svc:hover,
.svc:focus-within {
  --spot-a: 0.1;
  transform: translateY(-3px);
  box-shadow: var(--shadow-floating);
}
.svc .svc-more {
  display: inline-block;
  transition: transform var(--motion-panel) var(--motion-ease-state);
}
.svc:hover .svc-more,
.svc:focus-within .svc-more {
  transform: translateX(3px);
}
.svc .svc-icon {
  transition: transform var(--motion-panel) var(--motion-ease-state);
}
.svc:hover .svc-icon,
.svc:focus-within .svc-icon {
  transform: scale(1.02);
}
@media (prefers-reduced-motion: reduce) {
  .svc:hover,
  .svc:focus-within { transform: none; }
  .svc:hover .svc-more,
  .svc:focus-within .svc-more,
  .svc:hover .svc-icon,
  .svc:focus-within .svc-icon { transform: none; }
}

/* ---------- Booking steps ----------
   One stable container; the widget already pins a shared min-height
   (--ibw-step-min-h) so moving between steps never resizes it. What was
   missing was direction: steps simply appeared. Forward enters from the
   right, back from the left, both settling to 0.

   The entering class is added by JS at the moment of the step change, so
   there is no state in which markup sits at opacity 0 without a script to
   resolve it -- no JS means no class and a plainly visible step. */
@keyframes ibw-step-in-fwd {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes ibw-step-in-back {
  from { opacity: 0; transform: translateX(-14px); }
  to   { opacity: 1; transform: none; }
}
.ibw-step.is-entering-fwd {
  animation: ibw-step-in-fwd var(--motion-panel) var(--motion-ease-entrance) both;
}
.ibw-step.is-entering-back {
  animation: ibw-step-in-back var(--motion-panel) var(--motion-ease-entrance) both;
}

/* Travelling progress indicator. Scoped to .has-progress-bar, added by JS
   only once the bar exists, so the numbered steps keep their own
   is-active/is-done styling untouched if the script never runs. */
.ibw-progress.has-progress-bar {
  position: relative;
}
.ibw-progress.has-progress-bar .ibw-progress-step {
  position: relative;
  z-index: 1;
}
.ibw-progress .ibw-progress-bar {
  position: absolute;
  left: 0;
  bottom: -2px;
  height: 2px;
  z-index: 0;
  border-radius: var(--radius-full);
  background: var(--ink);
  pointer-events: none;
  transition:
    transform var(--motion-panel) var(--motion-ease-state),
    width var(--motion-panel) var(--motion-ease-state);
}
:root[data-theme="dark"] .ibw-progress .ibw-progress-bar {
  background: var(--bg-accent);
}
@media (prefers-reduced-motion: reduce) {
  .ibw-progress .ibw-progress-bar { transition-duration: 1ms; }
}

/* ---------- Booking success checkmark ----------
   Draws once alongside the existing rocket flourish. No JS involvement:
   the success step is display:none until it is shown, and CSS animations
   do not run on a display:none element -- so revealing the step is what
   starts the draw, and it starts from the beginning each time success is
   reached rather than having silently "played" while hidden.

   stroke-dashoffset animates on the SVG geometry itself, so nothing about
   the surrounding layout moves. Durations come from the motion scale, so
   reduced-motion collapses the draw to a static, already-complete mark. */
.ibw-check {
  display: block;
  width: 52px;
  height: 52px;
  margin: 0 auto var(--sp-md);
  stroke: var(--ink);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
:root[data-theme="dark"] .ibw-check {
  stroke: var(--bg-accent);
}
.ibw-check-circle {
  stroke-dasharray: 145;
  stroke-dashoffset: 145;
  animation: ibw-draw var(--motion-hero) var(--motion-ease-entrance) forwards;
}
.ibw-check-mark {
  stroke-dasharray: 36;
  stroke-dashoffset: 36;
  /* Starts as the circle finishes, so the tick lands inside a closed ring. */
  animation: ibw-draw var(--motion-section) var(--motion-ease-entrance) forwards;
  animation-delay: var(--motion-panel);
}
@keyframes ibw-draw {
  to { stroke-dashoffset: 0; }
}

/* Per-field validation message, sitting beside its own input rather than
   only in the single form-level status line. */
.isar-field-error {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-caption);
  color: var(--rust, #b5623f);
}
.isar-booking-widget [aria-invalid="true"] {
  border-color: var(--rust, #b5623f);
}

/* ---------- Portal profile dropdown (§8) ----------
   Reuses .isar-settings-item for the rows; only the identity header needs
   its own styling. Shown only inside the authenticated portal/academy --
   the public header keeps the Portal/Akademie destination picker. */
.isar-account-identity {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: var(--sp-sm) var(--sp-md) var(--sp-xs);
}
.isar-account-name {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--fg1);
  overflow-wrap: anywhere;
}
/* Wider than the signed-out panel: real names run longer than "Anmelden"
   or "Einstellungen", and the 190px base would wrap most of them. */
.isar-account-panel:has(.isar-account-identity) {
  width: 232px;
}
.isar-account-signout { color: var(--rust, #b5623f); }
/* "Einstellungen" toggle for the language/theme controls nested below it
   -- same .isar-settings-item look as its siblings, just with the chevron
   pushed to the far edge instead of sitting flush after the label. */
.isar-settings-expand-toggle {
  justify-content: space-between;
}
.isar-settings-expand-chevron {
  flex: 0 0 auto;
  transition: transform var(--motion-panel, 200ms) var(--motion-ease-state, ease);
}
.isar-settings-expand-toggle[aria-expanded="true"] .isar-settings-expand-chevron {
  transform: rotate(180deg);
}
/* :not([hidden]) rather than a bare display:flex -- an author-stylesheet
   class selector otherwise beats the UA stylesheet's [hidden]{display:none}
   on cascade origin even at equal specificity, so the collapsed panel was
   rendering open regardless of the hidden attribute JS was toggling. */
.isar-settings-expand:not([hidden]) {
  display: flex;
  flex-direction: column;
}

/* ---------- Complianz "Manage consent" revoke tab (P1-05) ----------
   Complianz ships this as a peek tab that's supposed to slide fully into
   view on hover/focus (cookiebanner.css sets --cmplz-manage-consent-offset:
   -35px at rest, with a :hover/:focus animation meant to bring it to 0).
   Confirmed live that the slide-in never actually triggers -- the button
   sits permanently 35px below the fold with only ~15px, and its click
   centre, visible at any viewport height we tested. Rather than debug the
   plugin's own animation wiring, this fixes the outcome WCAG cares about
   directly: the control is always fully on-screen, no hover/focus needed.
   !important + a selector matching the plugin's own specificity, since
   this deliberately overrides third-party CSS regardless of enqueue order. */
#cmplz-manage-consent .cmplz-manage-consent {
  bottom: 0 !important;
}

/* ---------- Einsatzgebiet / service area ----------
   The town list on /unser-unternehmen/ and /en/about-us/. Pills rather
   than the .grid/.svc cards the rest of those pages use: twenty cards
   would dwarf the sections above them, and a town name needs no
   description. Borrows the hero badge's mono-uppercase treatment so it
   reads as metadata, not as twenty links. */
.isar-area-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-sm);
  list-style: none;
  margin: var(--sp-xl) 0 0;
  padding: 0;
  max-width: 860px;
}
.isar-area-list li {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg3);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-full);
  padding: 6px 15px;
}
.isar-area-note {
  max-width: 62ch;
  margin-top: var(--sp-xl);
  color: var(--fg2);
}

/* ---------- Deployment picker ([isar_deployment_picker]) ----------
   Interactive "which path fits" card on the KI pages. Same ink card as
   .isar-promise-card / .isar-credentials-card, so it uses the fixed brand
   tokens (--ink, --canvas, --sky, --slate) rather than the theme-reactive
   text and surface tokens (--fg1, --bg and friends): the card is ink in both
   themes, so a token that flips with the theme would go dark-on-dark in one
   of them, exactly as .cred-pill once did. Selection is sky-on-ink rather
   than an orange accent -- sky is the brand's own interactive colour.

   The options are real radio inputs stretched over their label, so the
   whole pill is clickable, arrow keys move within a question, and the
   focus ring is drawn on the pill (input:focus-visible + span) instead of
   on an invisible box. */
.isar-picker {
  position: relative;
  text-align: left;
  background: var(--ink);
  color: var(--canvas);
  border-radius: var(--radius-md);
  padding: var(--sp-3xl) var(--sp-xxl);
  /* Ink and dark mode's --bg are near-identical, so give the card an edge. */
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--canvas) 9%, transparent);
}
.isar-picker [hidden] {
  display: none !important;
}
.isar-picker-label {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 0 0 var(--sp-md);
}
.isar-picker-lead {
  font-size: var(--fs-body-lg);
  line-height: 1.55;
  color: var(--sky);
  max-width: 62ch;
  margin: 0 0 var(--sp-xxl);
}
.isar-picker-q {
  border: 0;
  margin: 0 0 var(--sp-xl);
  padding: 0;
  min-width: 0;
}
.isar-picker-legend {
  position: relative;
  display: block;
  float: none;
  width: 100%;
  padding: 0 0 0 var(--sp-xl);
  margin: 0 0 var(--sp-md);
  font-size: var(--fs-body-md);
  font-weight: 500;
  line-height: 1.45;
  color: var(--canvas);
  max-width: 68ch;
}
.isar-picker-num {
  position: absolute;
  left: 0;
  top: 0.15em;
  font-family: var(--sans-mono);
  font-size: var(--fs-caption);
  color: var(--slate);
}
.isar-picker-opts {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-sm);
  padding-left: var(--sp-xl);
}
.isar-picker-opt {
  position: relative;
  display: inline-flex;
  margin: 0;
  cursor: pointer;
}
.isar-picker-opt input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.isar-picker-opt span {
  display: inline-block;
  padding: var(--sp-sm) var(--sp-lg);
  border: 1px solid color-mix(in oklab, var(--canvas) 26%, transparent);
  border-radius: var(--radius-full);
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  line-height: 1.3;
  color: var(--canvas);
  background: transparent;
  transition: background 160ms cubic-bezier(0.2, 0, 0, 1), color 160ms cubic-bezier(0.2, 0, 0, 1),
    border-color 160ms cubic-bezier(0.2, 0, 0, 1);
}
.isar-picker-opt:hover span {
  border-color: color-mix(in oklab, var(--canvas) 60%, transparent);
}
.isar-picker-opt input:checked + span {
  background: var(--sky);
  border-color: var(--sky);
  color: var(--ink);
}
.isar-picker-opt input:focus-visible + span {
  outline: 2px solid var(--sky);
  outline-offset: 3px;
}
.isar-picker-out {
  margin-top: var(--sp-xxl);
  padding-top: var(--sp-xl);
  border-top: 1px solid color-mix(in oklab, var(--canvas) 16%, transparent);
}
.isar-picker-pending {
  margin: 0;
  font-size: var(--fs-body-sm);
  color: color-mix(in oklab, var(--sky) 72%, transparent);
}
.isar-picker-result:not([hidden]) {
  animation: isarPickerIn 240ms cubic-bezier(0.2, 0, 0, 1);
}
@keyframes isarPickerIn {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .isar-picker-result:not([hidden]) { animation: none; }
  .isar-picker-opt span { transition: none; }
}
.isar-picker-result-label {
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate);
  margin: 0 0 var(--sp-sm);
}
.isar-picker-result-title {
  font-family: var(--serif-display);
  font-weight: 400;
  font-size: clamp(26px, 3.4vw, 36px);
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--sky);
  margin: 0 0 var(--sp-md);
}
.isar-picker-result-body {
  font-size: var(--fs-body-lg);
  line-height: 1.6;
  color: color-mix(in oklab, var(--canvas) 90%, transparent);
  max-width: 62ch;
  margin: 0 0 var(--sp-lg);
}
.isar-picker-tradeoff {
  max-width: 62ch;
  margin: 0 0 var(--sp-xl);
  padding-left: var(--sp-md);
  border-left: 2px solid var(--slate);
  font-size: var(--fs-body-md);
  line-height: 1.55;
  color: color-mix(in oklab, var(--canvas) 74%, transparent);
}
.isar-picker-tradeoff-label {
  display: block;
  font-family: var(--sans-mono);
  font-size: var(--fs-micro);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--slate);
  margin-bottom: var(--sp-xs);
}
.isar-picker-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-md);
  margin-bottom: var(--sp-lg);
}
.isar-picker .isar-picker-cta {
  display: inline-block;
  padding: var(--sp-sm) var(--sp-xl);
  border-radius: var(--radius-sm);
  background: var(--sky);
  color: var(--ink);
  font-family: var(--sans-body);
  font-size: var(--fs-body-md);
  font-weight: 500;
  text-decoration: none;
}
.isar-picker .isar-picker-cta:hover {
  background: color-mix(in oklab, var(--sky) 86%, white 14%);
}
.isar-picker .isar-picker-cta:focus-visible,
.isar-picker .isar-picker-reset:focus-visible {
  outline: 2px solid var(--sky);
  outline-offset: 3px;
}
.isar-picker .isar-picker-reset {
  padding: var(--sp-sm) var(--sp-lg);
  border: 1px solid color-mix(in oklab, var(--canvas) 30%, transparent);
  border-radius: var(--radius-full);
  background: transparent;
  color: color-mix(in oklab, var(--canvas) 86%, transparent);
  font-family: var(--sans-body);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  cursor: pointer;
}
.isar-picker .isar-picker-reset:hover {
  background: color-mix(in oklab, var(--canvas) 10%, transparent);
}
.isar-picker-note {
  max-width: 62ch;
  margin: 0;
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: color-mix(in oklab, var(--canvas) 58%, transparent);
}
/* No JavaScript: the interactive part cannot work, so it is hidden and the
   <noscript> summary of the four possible paths stands in for it. */
html.no-js .isar-picker-form,
html.no-js .isar-picker-out {
  display: none;
}
.isar-picker-static {
  margin: 0 0 var(--sp-lg);
  padding-left: var(--sp-lg);
  color: var(--sky);
  line-height: 1.6;
}
@media (max-width: 640px) {
  /* Narrow screens: less padding all round, and the options drop back under
     the question's full width instead of hanging indented beneath its number. */
  .isar-picker {
    padding: var(--sp-xl);
  }
  .isar-picker-legend {
    padding-left: var(--sp-lg);
  }
  .isar-picker-opts {
    padding-left: 0;
  }
}
