body,form,figure{margin:0;padding:0}img{border:0}header,footer,nav,section,aside,article,figure,figcaption{display:block}body{font-size:100.01%}select,input,textarea{font-size:99%}#container,.inside{position:relative}#main,#left,#right{float:left;position:relative}#main{width:100%}#left{margin-left:-100%}#right{margin-right:-100%}#footer{clear:both}#main .inside{min-height:1px}.ce_gallery>ul,.content-gallery>ul{margin:0;padding:0;overflow:hidden;list-style:none}.ce_gallery>ul li,.content-gallery>ul li{float:left}.ce_gallery>ul li.col_first,.content-gallery>ul li.col_first{clear:left}.float_left,.media--left>figure{float:left}.float_right,.media--right>figure{float:right}.block{overflow:hidden}.media{display:flow-root}.clear,#clear{height:.1px;font-size:.1px;line-height:.1px;clear:both}.invisible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.custom{display:block}#container:after,.custom:after{content:"";display:table;clear:both}
@media (max-width:767px){#wrapper{margin:0;width:auto}#container{padding-left:0;padding-right:0}#main,#left,#right{float:none;width:auto}#left{right:0;margin-left:0}#right{margin-right:0}}img{max-width:100%;height:auto}.audio_container audio{max-width:100%}.video_container video{max-width:100%;height:auto}.aspect,.responsive{position:relative;height:0}.aspect iframe,.responsive iframe{position:absolute;top:0;left:0;width:100%;height:100%}.aspect--16\:9,.responsive.ratio-169{padding-bottom:56.25%}.aspect--16\:10,.responsive.ratio-1610{padding-bottom:62.5%}.aspect--21\:9,.responsive.ratio-219{padding-bottom:42.8571%}.aspect--4\:3,.responsive.ratio-43{padding-bottom:75%}.aspect--3\:2,.responsive.ratio-32{padding-bottom:66.6666%}.aspect--9\:16,.responsive.ratio-916{padding-bottom:177.7777%}.aspect--1\:1,.responsive.ratio-11{padding-bottom:100%}
/* Site-wide page scaffold: content container width + basic typography.
   Container widths match the header's Bootstrap-3-style stepped
   breakpoints (see main-nav.css): 970px from 992px up, 1170px from
   1200px up, fluid with side padding below that. */

body {
  margin: 0;
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-weight: 300;
  font-size: 14px;
  color: var(--cato-text, #343434);
  line-height: 1.42857143;
}

#main .inside {
  max-width: 970px;
  margin: 0 auto;
  padding: 40px 20px;
}

@media (min-width: 1200px) {
  #main .inside {
    max-width: 1170px;
  }
}

@media (max-width: 767px) {
  #main .inside {
    padding: 24px 20px;
  }
}

/* Spacing utility classes: add alongside "content-element-group" on
   whichever Element group needs more/less rhythm than its neighbors (some
   sections need more breathing room than others). Fixed scale
   (5/10/30/50px), kept as-is across all breakpoints incl. mobile - not
   automatic, assign per element as needed. */
.margin-top-5    { margin-top: 5px; }
.margin-top-10   { margin-top: 10px; }
.margin-top-30   { margin-top: 30px; }
.margin-top-50   { margin-top: 50px; }

.margin-bottom-5  { margin-bottom: 5px; }
.margin-bottom-10 { margin-bottom: 10px; }
.margin-bottom-30 { margin-bottom: 30px; }
.margin-bottom-50 { margin-bottom: 50px; }

.margin-left-5  { margin-left: 5px; }
.margin-left-10 { margin-left: 10px; }
.margin-left-30 { margin-left: 30px; }
.margin-left-50 { margin-left: 50px; }

.margin-right-5  { margin-right: 5px; }
.margin-right-10 { margin-right: 10px; }
.margin-right-30 { margin-right: 30px; }
.margin-right-50 { margin-right: 50px; }

.opacity-60 {
  opacity: 0.6;
}

.text-center {
  text-align: center;
}

/* Opt-in: add this alongside any margin-*-N class above to force it off
   below 768px - for instances inside patterns that stack on mobile
   (image-pair, icon-box), where a left/right margin from the desktop
   side-by-side layout no longer makes sense once stacked. Must stay
   below the margin-*-N rules to win on equal specificity. Leave it off
   for spacing between whole sections, which should stay on mobile too. */
@media (max-width: 767px) {
  .mobile-margin-off {
    margin: 0;
  }
}

h1, h2, h3, h4, h5, h6 {
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-weight: 700;
  color: #202020;
  line-height: 1.3;
}

h1, h2 {
  font-weight: 300;
  font-size: 27px;
  margin-top: 55px;
  margin-bottom: 35px;
  line-height: 35px;
  color: var(--cato-red, #9a1818);
  hyphens: auto;
  overflow-wrap: break-word;
}

strong {
  font-weight: bold;
}

a {
  color: var(--cato-red, #9a1818);
}

/* Single-column narrow text: caps the content at 700px reading width,
   centered, via calculated padding rather than max-width + margin:auto
   (so it composes with a plain Text element sitting inside #main .inside
   without needing its own box). Below 768px the calc() would eventually
   go negative as the viewport narrows, so it's replaced with a flat
   15px. Class goes directly on a Text element's "CSS class" field - no
   Element group needed for a single block. */
.text-narrow {
  box-sizing: border-box;
  padding-left: calc(50% - 350px);
  padding-right: calc(50% - 350px);
}

.text-narrow h1,
.text-narrow h2 {
  text-align: center;
}

@media (max-width: 767px) {
  .text-narrow {
    padding-left: 15px;
    padding-right: 15px;
  }
}

/* Generic 2-column text pattern (Element group wrapping headline + 2 Text
   elements). The headline spans both columns; the two Text elements
   auto-place into the row below. Class goes on the Element group's
   "CSS class" field. */
.intro-text {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 60px;
}

.intro-text > h2 {
  grid-column: 1 / -1;
  min-width: 0;
  color: var(--cato-red, #9a1818);
  text-transform: uppercase;
  text-align: center;
}

@media (max-width: 767px) {
  .intro-text {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Generic 2-image side-by-side pattern (Element group wrapping 2 Image
   elements). Old site hid these on mobile entirely (display: none); we
   stack them full-width instead so the content isn't lost. Default is an
   even 1/1 split — use --wide-narrow / --narrow-wide for the old
   Bootstrap-style 8/4 uneven split. Class goes on the Element group's
   "CSS class" field. */
.image-pair {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
}

.image-pair--wide-narrow {
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
}

.image-pair--narrow-wide {
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
}

.image-pair .content-image,
.image-pair figure {
  height: 100%;
}

.image-pair figure {
  margin: 0;
}

.image-pair img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 767px) {
  .image-pair,
  .image-pair--wide-narrow,
  .image-pair--narrow-wide {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Red CTA band (Element group: headline + 2x nested Element group
   "icon-box__item", each wrapping [Image icon + Hyperlink]). Each item
   is its own grid cell, so no auto-flow trickery is needed here - the
   headline spans row 1, the two items fill row 2 left/right. Outer class
   goes on the outer Element group's "CSS class" field. */
.icon-box {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  justify-items: center;
  row-gap: 16px;
  column-gap: 60px;
  background: var(--cato-red, #9a1818);
  color: #fff;
  padding-bottom: 20px;
  padding-left: 80px;
  padding-right: 80px;
  padding-top: 0;
  text-align: center;
}

.icon-box > h2 {
  grid-column: 1 / -1;
  min-width: 0;
  color: #fff;
  text-transform: uppercase;
}

.icon-box strong {
  color: #fff;
}

/* Inner item: Image icon + Hyperlink, whole box clickable via a
   "stretched link" - the real <a> from the Hyperlink element gets an
   ::after pseudo-element stretched (inset: 0) over the item's full
   position: relative box, so clicking the icon or the gap works too,
   not just the link text itself. Class goes on the inner (nested)
   Element group's "CSS class" field. */
.icon-box__item {
  position: relative;
}

.icon-box__item a {
  color: #fff;
  text-decoration: none;
  font-size: 18px;
  font-weight: 400;
}

.icon-box__item a::after {
  content: "";
  position: absolute;
  inset: 0;
}

@media (max-width: 767px) {
  .icon-box {
    grid-template-columns: minmax(0, 1fr);
    padding-left: 20px;
    padding-right: 20px;
  }
}

/* Red 2-column text band (Element group wrapping 2 Text elements). Unlike
   .intro-text, each column has its own headline (left-aligned, not a
   shared centered one), so the headline lives on each Text element, not
   the group. Spacing between the two columns is handled per-instance via
   the margin-top-5/margin-right-5/... utility classes above, not baked
   in here. Class goes on the Element group's "CSS class" field. */
.text-band {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  color: #fff;
}

/* Background sits on each column, not the outer grid - otherwise a
   margin-right-5/margin-left-5 gap between columns would just reveal more
   of the same red (the container's own background) instead of white. */
.text-band .content-text {
  background: var(--cato-red, #9a1818);
  padding: 60px 80px;
}

.text-band h2 {
  color: #fff;
  text-transform: uppercase;
  margin-top: 0;
  margin-bottom: 20px;
}

@media (max-width: 767px) {
  .text-band {
    grid-template-columns: minmax(0, 1fr);
  }

  .text-band .content-text {
    padding-top: 20px;
    padding-bottom: 20px;
    padding-left: 20px;
    padding-right: 20px;
  }
}

/* Person cards (Element group: centered headline + 2x nested Element
   group "person-card", each wrapping [Image photo + Text]). Same
   structure as .icon-box (outer group + 2 nested groups), but photos
   instead of icons and no red band. Text convention within each card:
   wrap the name in <strong> (stays black/bold), wrap role/location/phone
   lines in <small> (styled grey) - matches the <small> convention already
   used in hero__caption. Email stays a plain link (already red via the
   global "a" rule). Class goes on the outer Element group's "CSS class"
   field, "person-card" on each of the 2 nested groups. */
.person-cards {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 60px;
  row-gap: 30px;
}

.person-cards > h2 {
  grid-column: 1 / -1;
  min-width: 0;
  text-align: center;
}

.person-card {
  text-align: center;
}

.person-card img {
  display: block;
  width: 100%;
  max-width: 330px;
  height: auto;
  margin: 0 auto;
  border-radius: 12px;
}

.person-card strong {
  display: inline-block;
  margin-top: 16px;
  color: #202020;
}

/* Thin divider between the contact-info paragraph (role/location/email/
   phone, greyed out via .opacity-60 spans) and the bio text that follows
   in a separate ".geschCV" div within the same person-card. */
.person-card .geschCV {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid rgba(0, 0, 0, 0.15);
}

@media (max-width: 767px) {
  .person-cards {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Compact variant for pages with many contact cards and no bio text
   (e.g. "Ansprechpartner"): add "person-cards--compact" alongside
   "person-cards" on the outer Element group (same 2 classes on one
   field). 4 columns from 992px up, stepping down to 2 in the 768-991px
   tablet range and 1 below 768px (the existing 767px stacking rule
   above already covers that last step too, since it targets
   ".person-cards", which this variant still carries). All 3 column
   counts are scoped to their own min/max range rather than one being
   an unscoped "default" - an earlier version left the 4-column rule
   unscoped, and since it's equal specificity to (and comes after, in
   source order) the 767px stacking rule, it silently won at every
   width including mobile, undoing the stack.

   Photos target 165x200 via object-fit: cover - the backend files come
   in either 330x400 or 165x200, and while most share that ~0.825
   aspect ratio, some originals are taller, so a plain max-width cap
   (which just scales, preserving each photo's own ratio) rendered
   those inconsistently; a fixed-ratio box + cover crops every photo to
   the same shape regardless of its source ratio. width is capped via
   max-width rather than set outright so the photo still shrinks with
   its grid column on narrow viewports instead of overflowing it (which
   is what caused cards to overlap before this was in aspect-ratio/
   max-width form). Don't add a .geschCV div in this variant's Text
   elements - just the name/contact-info block. */
.person-cards--compact {
  column-gap: 30px;
}

.person-cards--compact .person-card img {
  width: 100%;
  max-width: 165px;
  height: auto;
  aspect-ratio: 165 / 200;
  object-fit: cover;
}

@media (min-width: 992px) {
  .person-cards--compact {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 768px) and (max-width: 991px) {
  .person-cards--compact {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Sticky header + main navigation, matching the reference design:
   white header bar, logo left, dark grey uppercase nav links, red
   hover/active state, dropdown panel opening below the trigger. */

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 300;
  src: url('/files/fonts/roboto-v30-latin-300.woff2') format('woff2');
  font-display: swap;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  src: url('/files/fonts/roboto-v30-latin-regular.woff2') format('woff2');
  font-display: swap;
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  src: url('/files/fonts/roboto-v30-latin-700.woff2') format('woff2');
  font-display: swap;
}

:root {
  --cato-red: #9a1818;
  --cato-text: #343434;
  --cato-header-height: 90px;
}

#header {
  position: sticky;
  top: 0;
  z-index: 999;
  background: #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
}

#header .inside {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--cato-header-height);
  max-width: 970px;
  margin: 0 auto;
  padding: 0 30px;
}

/* Bootstrap 3 container steps (matches the old site): 970px from 992px up,
   970px to 1170px stepped, not fluid — full 1170px only from 1200px up. */
@media (min-width: 1200px) {
  #header .inside {
    max-width: 1170px;
  }
}

#header .site-logo {
  display: block;
  flex-shrink: 0;
}

#header .site-logo img {
  display: block;
  width: 200px;
  max-width: 200px;
  height: auto;
}

/* Contao's layout.css framework applies a generic ".block{overflow:hidden}"
   clearfix utility to every module wrapper (incl. "mod_navigation block"),
   which clips the dropdown submenus below it. Undo that here. */
#header .mod_navigation.block {
  overflow: visible;
}

/* Top-level menu */

#header .mod_navigation .level_1 {
  display: flex;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
}

#header .mod_navigation a,
#header .mod_navigation strong,
#header .mod_navigation label {
  -webkit-tap-highlight-color: transparent;
}

#header .mod_navigation .level_1 > li {
  position: relative;
  margin: 0 0 0 32px;
}

#header .mod_navigation .level_1 > li > a,
#header .mod_navigation .level_1 > li > strong {
  display: flex;
  align-items: center;
  gap: 6px;
  height: var(--cato-header-height);
  color: var(--cato-text);
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-size: 14px;
  font-weight: 300;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s ease-out;
}

#header .mod_navigation .level_1 > li > a:hover,
#header .mod_navigation .level_1 > li.active > a,
#header .mod_navigation .level_1 > li.active > strong,
#header .mod_navigation .level_1 > li.trail > a,
#header .mod_navigation .level_1 > li.trail > strong {
  color: var(--cato-red);
}

.submenu-caret {
  color: var(--cato-red);
  transition: transform 0.2s ease-out;
}

#header .mod_navigation li:hover > a > .submenu-caret {
  transform: rotate(180deg);
}

/* Dropdown submenus (level 2+), open below the trigger on hover */

#header .mod_navigation .level_1 ul {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 99;
  width: 280px;
  margin: 0;
  padding: 0;
  list-style: none;
  background: linear-gradient(155deg, #a52020 0%, var(--cato-red) 45%, #7a1313 100%);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.25);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.2s ease-out, transform 0.2s ease-out, visibility 0.2s;
}

#header .mod_navigation .level_1 > li:hover > ul {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

/* Submenus nested a further level offset to the right */

#header .mod_navigation .level_1 ul ul {
  top: 0;
  left: 100%;
}

/* The last top-level item sits at the right edge of the nav — its
   dropdown opening further rightward (the default "left:0") can run
   past the viewport edge and cause a phantom horizontal scrollbar even
   while closed. Open it flush to its own right edge instead. */
#header .mod_navigation .level_1 > li:last-child > ul {
  left: auto;
  right: 0;
}

#header .mod_navigation .level_1 > li:last-child > ul ul {
  left: auto;
  right: 100%;
}

/* All rules below are scoped to ".level_1 ul" (i.e. nested dropdown lists
   only) — ".level_1" is itself a "ul", so an unscoped "ul li" would also
   match (and override) the top-level items. */

#header .mod_navigation .level_1 ul li {
  border-top: 1px solid rgba(255, 255, 255, 0.25);
}

#header .mod_navigation .level_1 ul li:first-child {
  border-top: none;
}

#header .mod_navigation .level_1 ul li a,
#header .mod_navigation .level_1 ul li strong {
  display: block;
  padding: 14px 18px;
  color: #fff;
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-size: 14px;
  font-weight: 300;
  text-decoration: none;
}

#header .mod_navigation .level_1 ul li a:hover {
  background: rgba(0, 0, 0, 0.15);
}

/* Current page within a dropdown: Contao renders it as <strong>, mark it
   as "you are here" instead of just inheriting bold browser defaults. */
#header .mod_navigation .level_1 ul li strong {
  background: rgba(0, 0, 0, 0.15);
  font-weight: 700;
}

/* Mobile menu toggle (checkbox + label, no JS). Hidden entirely on desktop;
   shown/wired up only inside the max-width:992px block below. */

.nav-toggle-input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
}

.nav-toggle-label {
  display: none;
  cursor: pointer;
}

/* Small/mobile: stack the menu behind a hamburger toggle instead of a
   horizontal bar with hover dropdowns. 992px matches the old site's own
   breakpoint (Bootstrap 3's lg tier starts at 992px). */

@media (max-width: 992px) {
  #header .inside {
    position: relative;
    flex-direction: column;
    align-items: stretch;
    height: auto;
    padding: 21px 20px 16px;
  }

  .nav-toggle-label {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 16px;
    right: 20px;
    width: 44px;
    height: 44px;
    color: var(--cato-red);
  }

  .nav-toggle-input:focus-visible + .nav-toggle-label {
    outline: 2px solid var(--cato-red);
    outline-offset: 2px;
  }

  #header .mod_navigation .level_1 {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    margin-top: 0;
    max-height: 0;
    overflow: hidden;
    opacity: 0;
    transition: max-height 0.3s ease-out, opacity 0.2s ease-out, margin-top 0.3s ease-out;
  }

  #header .nav-toggle-input:checked ~ .level_1 {
    max-height: 1000px;
    opacity: 1;
    margin-top: 16px;
  }

  #header .mod_navigation .level_1 > li {
    margin: 0;
    border-top: 1px solid #000;
  }

  #header .mod_navigation .level_1 > li:first-child {
    border-top: none;
  }

  #header .mod_navigation .level_1 > li > a,
  #header .mod_navigation .level_1 > li > strong {
    height: auto;
    padding: 12px 20px;
  }

  #header .mod_navigation .level_1 ul {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    width: auto;
    box-shadow: none;
  }

  /* Indent submenu links further than their level_1 parent, so the
     nesting stays visible now that both levels share the same padding
     scheme. */
  #header .mod_navigation .level_1 ul li a,
  #header .mod_navigation .level_1 ul li strong {
    padding-left: 38px;
  }

  #header .mod_navigation .level_1 ul ul li a,
  #header .mod_navigation .level_1 ul ul li strong {
    padding-left: 56px;
  }

  /* Desktop's red dropdown panel doesn't apply here - level 2 sits
     inline in the stacked mobile menu instead of a floating panel, so it
     drops the red background/white text and uses the same colour scheme
     as level 1 (dark grey text, red on hover/active/trail, no bold and
     no background box for the current page). */
  #header .mod_navigation .level_1 ul {
    background: none;
  }

  /* The separator can't just be the li's own border-top (that always
     spans the full box width, regardless of the link's padding-left) -
     use an indented ::before instead so the line starts at the same x
     as the text above/below it. */
  #header .mod_navigation .level_1 ul li {
    position: relative;
    border-top: none;
  }

  #header .mod_navigation .level_1 ul li::before {
    content: "";
    position: absolute;
    top: 0;
    left: 38px;
    right: 0;
    border-top: 1px solid rgba(0, 0, 0, 0.1);
  }

  #header .mod_navigation .level_1 ul ul li::before {
    left: 56px;
  }

  #header .mod_navigation .level_1 ul li:first-child::before {
    border-top: none;
  }

  #header .mod_navigation .level_1 ul li a,
  #header .mod_navigation .level_1 ul li strong {
    color: var(--cato-text);
    font-weight: 300;
  }

  #header .mod_navigation .level_1 ul li a:hover,
  #header .mod_navigation .level_1 ul li.active > a,
  #header .mod_navigation .level_1 ul li.active > strong,
  #header .mod_navigation .level_1 ul li.trail > a,
  #header .mod_navigation .level_1 ul li.trail > strong,
  #header .mod_navigation .level_1 ul li strong {
    background: none;
    color: var(--cato-red);
  }
}

/* Page-header "hero" pattern: full-width image, image fades in first,
   then an optional caption box slides in from below.

   Built entirely from native Contao elements — no plugin needed (Contao
   5.7 core has no Grid/Raster element; Element group is the only native
   wrapper). In the backend:

     1. New content element > Elementtyp "Elementgruppe", CSS-Klasse: hero
     2. Inside it, nest an Image element (and optionally a Text element)
     3. Text element's CSS-Klasse: hero__caption, plus exactly one size
        modifier: hero__caption--sm | hero__caption--md | hero__caption--lg

   Leave the Text element out entirely for an image-only hero with no
   caption (e.g. the Kontakt page) — the Elementgruppe + Image alone is
   enough, no extra classes required. Pick whichever size modifier fits
   the amount of text on that particular page.
*/

.hero {
  position: relative;
}

.hero img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0;
  animation: heroImageIn 0.5s ease-out forwards;
}

@keyframes heroImageIn {
  to {
    opacity: 1;
  }
}

.hero__caption {
  position: absolute;
  right: 30px;
  bottom: 0;
  max-width: 570px;
  background: rgba(154, 24, 24, 0.92);
  color: #fff;
  padding: 30px 40px;
  opacity: 0;
  transform: translateY(30px);
  animation: heroCaptionIn 0.7s ease-out 0.35s forwards;
}

@keyframes heroCaptionIn {
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hero__caption p {
  margin: 0 0 0.6em;
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-weight: 300;
  line-height: 1.4;
}

.hero__caption p:last-child {
  margin-bottom: 0;
}

/* Optional smaller sub-line within the caption — wrap it in <small> in
   the text element's editor (source view). Scales with the chosen
   hero__caption--sm/--md/--lg size, since it's set in em. */
.hero__caption small {
  display: inline-block;
  font-size: 0.65em;
  opacity: 0.85;
}

/* Font-size modifiers — pick whichever fits the amount of text. */
.hero__caption--lg {
  font-size: 34px;
}
.hero__caption--md {
  font-size: 26px;
}
.hero__caption--sm {
  font-size: 20px;
}

/* Shrink to keep the box from overflowing as the viewport narrows. */
@media (max-width: 991px) {
  .hero__caption {
    right: 20px;
    max-width: 70%;
    padding: 24px 30px;
  }
  .hero__caption--lg {
    font-size: 26px;
  }
  .hero__caption--md {
    font-size: 21px;
  }
  .hero__caption--sm {
    font-size: 17px;
  }
}

/* Full-width on mobile (phones, portrait AND landscape — 932px covers
   iPhone landscape too) — more room per line, so text can grow back up.
   Image and caption go edge-to-edge (bleed out of the #main .inside
   container's side padding); header/nav/breadcrumb keep theirs. */
@media (max-width: 932px) {
  .hero {
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    margin-bottom: 20px;
  }

  /* Contao's ".block{overflow:hidden}" clearfix (see main-nav.css) is
     also on the article wrapper here, which would clip the bleed. */
  #main .mod_article.block {
    overflow: visible;
  }

  .hero__caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: -20px;
    max-width: none;
    width: auto;
    padding: 20px;
    transform: translateY(16px);
  }
  .hero__caption--lg {
    font-size: 28px;
  }
  .hero__caption--md {
    font-size: 19px;
  }
  .hero__caption--sm {
    font-size: 19px;
  }
}

/* Narrow phones in portrait (iPhone etc., ~375–430px) — the 932px tier
   above is still too large here. */
@media (max-width: 430px) {
  .hero__caption {
    padding: 16px;
  }
  .hero__caption--lg {
    font-size: 22px;
  }
  .hero__caption--md {
    font-size: 13px;
  }
  .hero__caption--sm {
    font-size: 13px;
  }
}

/* Breadcrumb navigation, matching the reference design: muted grey
   trail, "›" separators, current page bold/uppercase/dark.

   Inserted per page as a "Modul" content element (not a layout module),
   right after the hero element group — that's what lets it sit below
   the header image and be left out entirely on the home page. A layout
   module can't be positioned between two content elements within an
   article, and the root+home page pair always yields 2 breadcrumb
   items, so there's no reliable page-agnostic CSS way to hide it there. */

.mod_breadcrumb {
  margin: 30px 0 0;
}

.mod_breadcrumb ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-size: 12px;
  font-weight: 300;
  color: #8a8a8a;
}

.mod_breadcrumb li {
  display: flex;
  align-items: center;
}

.mod_breadcrumb li + li::before {
  content: '\203A';
  margin: 0 10px;
  color: #b0b0b0;
}

.mod_breadcrumb a {
  color: inherit;
  text-decoration: none;
}

.mod_breadcrumb a:hover {
  color: var(--cato-red, #9a1818);
}

.mod_breadcrumb li.active {
  color: var(--cato-text, #343434);
  font-weight: 700;
  text-transform: uppercase;
}

/* Site-wide footer (same on every page). Company name + social icons are
   hardcoded in templates/fe_page.html.twig's footer block - static chrome,
   same precedent as the header logo, not editorial content. The legal
   links nav ("Datenschutz | Impressum | Kontakt") comes from a native
   Contao "Custom navigation" module configured in the Layout's Footer
   region, scoped to those pages, so it stays correct if pages get
   renamed. Container width matches #main .inside (see base.css) exactly -
   duplicated here rather than shared since this is its own file per the
   project's one-file-per-component convention. */
#footer {
  color: #000;
}

/* Background sits on .inside, not #footer itself - unlike the white
   header bar (always 100vw), the grey should follow the same raster as
   the rest of the content (970/1170px, centered) and only reach full
   width once the viewport is too narrow for that box to matter. */
#footer .inside {
  background: #dcddde;
  box-sizing: border-box;
  max-width: 970px;
  margin: 0 auto;
  padding: 40px 40px;
}

@media (min-width: 1200px) {
  #footer .inside {
    max-width: 1170px;
  }
}

@media (max-width: 767px) {
  #footer .inside {
    padding: 24px 20px;
  }
}

/* Flexbox instead of a 2fr/1fr grid: with a grid column, .footer-meta's
   content (much narrower than its column) left it stranded away from the
   right edge, so its gap to the right edge didn't match .footer-company's
   gap to the left edge. space-between docks each side to its own edge
   regardless of content width. */
.footer-inner {
  display: flex;
  justify-content: space-between;
  gap: 20px;
}

@media (max-width: 767px) {
  .footer-inner {
    flex-direction: column;
  }
}

.footer-company p {
  margin: 0;
  font-size: 18px;
}

.footer-company strong {
  color: var(--cato-red, #9a1818);
}

.footer-links {
  margin-bottom: 20px;
}

.footer-links ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-links li {
  display: inline;
}

.footer-links li + li::before {
  content: " | ";
}

.footer-links a {
  color: #000;
}

.footer-links a:hover {
  text-decoration: none;
}

.footer-social {
  display: flex;
  gap: 4px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.footer-social a {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--cato-red, #9a1818);
  border-radius: 50%;
}

.footer-social img {
  transition: transform 0.6s ease-out;
}

.footer-social a:hover img {
  transform: rotate(720deg);
}

/* Native Contao "Accordion" content element. Contao renders it via the
   bundled Handorgel JS library (no plugin/JS of our own needed) with
   fixed class names: .content-accordion (outer wrapper), .handorgel__header
   / __button (each panel's clickable header), .handorgel__content /
   __inner (each panel's body). Open state is read off the button's
   aria-expanded attribute (set by Handorgel itself) rather than guessing
   a modifier class name.

   Backend: Elementtyp "Accordion" as the outer element, then nest
   "Akkordeon-Element" items inside it - each with its own Überschrift
   ("Allgemeines", "Curriculum Vitae") and its own nested Text content. */

.content-accordion {
  border-top: 1px solid rgba(0, 0, 0, 0.15);
}

.handorgel__header {
  border-bottom: 1px solid rgba(0, 0, 0, 0.15);
}

.handorgel__header__button {
  display: block;
  width: 100%;
  padding: 16px 20px;
  background: none;
  border: none;
  color: var(--cato-red, #9a1818);
  font-family: 'Roboto', Arial, Helvetica, sans-serif;
  font-size: 16px;
  font-weight: 400;
  text-align: left;
  text-transform: uppercase;
  cursor: pointer;
}

.handorgel__header__button:hover,
.handorgel__header__button[aria-expanded="true"] {
  background: linear-gradient(155deg, #a52020 0%, var(--cato-red, #9a1818) 45%, #7a1313 100%);
  color: #fff;
}

.handorgel__content__inner {
  padding: 24px 20px;
  text-align: left;
}

/* Fullscreen Ken-Burns image slideshow (replaces the old site's vegas.js
   on "Standorte - Impressionen"). Pure CSS, no JS/plugin needed — each
   image gets the same @keyframes animation, staggered via a positive
   animation-delay so only one is visible/zooming at a time, in order.
   (Delay must be positive, not negative: a negative delay makes the
   animation start already mid-cycle, which plays the images back in
   reverse order instead of waiting its turn.)

   Built specifically for exactly 8 images (files/impressionen/*.jpg).
   In the backend:

     1. New content element > Elementtyp "Elementgruppe", CSS-Klasse:
        imageslider
     2. Inside it, nest 8 Image elements (no captions), in the order you
        want them to cycle — pick from files/impressionen/

   Markup Contao renders per image: .content-image > figure > img — the
   nth-child staggering below targets the .content-image wrapper (the
   actual nth-child among .imageslider's children), not the img itself,
   since each img is always the lone/first child of its own <figure>.

   All images zoom the same direction — large to small (@keyframes
   imageSliderCycle) — no alternation.

   Instead of a hard cut, each outgoing image stays fully opaque for the
   first ~0.25s of the next image's fade-in (both sit at opacity:1 at
   the same time — a true double exposure), then the outgoing image
   snaps out over the following ~0.25s. Every image has a mix-blend-mode
   set, so during that double-exposure window the two images actually
   blend with each other (Photoshop blend modes: screen = "Negativ
   multiplizieren", multiply = "Multiplizieren", difference = "Differenz"
   in the German UI), giving a brief punchy flash instead of a plain
   crossfade. (An earlier version overlapped the two images' fade curves
   directly instead of holding a full-opacity plateau — both images were
   only ever ~20-40% opaque at once, so the blend was too faint to
   notice; the visible effect needs both layers near-opaque
   simultaneously.) .imageslider has isolation: isolate so the blending
   stays contained to the slider and doesn't affect the rest of the
   page. Outside the transition window only one image is ever opaque, so
   the blend mode against an empty backdrop is a no-op and the image
   just looks normal.

   Important: .content-image must NOT get an explicit z-index (even 0) —
   any explicit z-index on a positioned element creates its own stacking
   context, which would isolate each image from its siblings and mix-
   blend-mode would then have nothing to blend with (silently no-op,
   regardless of which mode is chosen). Stacking order here relies
   purely on DOM order instead.

   Changing the image count later means recalculating the percentages in
   @keyframes imageSliderCycle (each image's on-screen slot is 100/N%)
   and adding/removing the matching nth-child animation-delay rule below
   (step * 2s per image).
*/

.imageslider {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  height: clamp(320px, 60vh, 640px);
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* Same clearfix-clipping issue as the hero bleed (see hero.css) — the
   article wrapper's overflow:hidden would otherwise clip the bleed. */
#main .mod_article.block {
  overflow: visible;
}

.imageslider .content-image {
  position: absolute;
  inset: 0;
}

.imageslider .content-image figure {
  margin: 0;
  width: 100%;
  height: 100%;
}

.imageslider img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  mix-blend-mode: color;
  animation-name: imageSliderCycle;
  animation-duration: 16s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}

.imageslider .content-image:nth-child(1) img { animation-delay: 0s; }
.imageslider .content-image:nth-child(2) img { animation-delay: 2s; }
.imageslider .content-image:nth-child(3) img { animation-delay: 4s; }
.imageslider .content-image:nth-child(4) img { animation-delay: 6s; }
.imageslider .content-image:nth-child(5) img { animation-delay: 8s; }
.imageslider .content-image:nth-child(6) img { animation-delay: 10s; }
.imageslider .content-image:nth-child(7) img { animation-delay: 12s; }
.imageslider .content-image:nth-child(8) img { animation-delay: 14s; }

/* One 16s loop = 8 images x 2s each. Opacity and transform use separate
   keyframe stops (allowed — each just interpolates against whichever
   stops mention that property):
     - opacity fades in fast (0% - 1.5625% = 0 - 0.25s), holds at 1 all
       the way to 14.0625% (2.25s) — i.e. 0.25s INTO the next image's
       slot, where the two are both fully opaque at once — then snaps
       out over 14.0625% - 15.625% (2.25s - 2.5s).
     - transform only has 2 stops (0% and 15.625%) so the zoom is one
       constant-speed ramp across the image's whole visible span —
       adding intermediate stops here made the zoom speed uneven
       (fast in the middle, crawling right before the blend). */
@keyframes imageSliderCycle {
  0% {
    opacity: 0;
    transform: scale(1.1);
  }
  1.5625% {
    opacity: 1;
  }
  14.0625% {
    opacity: 1;
  }
  15.625% {
    opacity: 0;
    transform: scale(1);
  }
  100% {
    opacity: 0;
    transform: scale(1);
  }
}

@media (max-width: 767px) {
  .imageslider {
    height: clamp(220px, 45vh, 420px);
  }
}

/* Respect reduced-motion: freeze on the first image instead of cycling. */
@media (prefers-reduced-motion: reduce) {
  .imageslider img {
    animation: none;
    opacity: 0;
  }
  .imageslider .content-image:first-child img {
    opacity: 1;
  }
}

/* "Bildmaterial zum Download" pattern (Kontakt/Mediathek page). Same
   outer/inner scaffold as Ansprechpartner: outer Elementgruppe carries
   "person-cards person-cards--download" (modifier alongside the base
   class, same convention as "person-cards--compact"), each nested
   Elementgruppe carries only the plain "person-card" class - the variant
   modifier lives on the OUTER group and all overrides below are scoped
   as ".person-cards--download .person-card ...", not on the card itself.
   The inner shape is different from a normal person-card though: photo
   on top, a red button bar with two download links underneath, whole
   card clickable to open the photo in Contao's own native lightbox
   (dark-backdrop overlay), like a gallery - no name/text content at all.

   Backend, per person (nested Elementgruppe "person-card" inside the
   outer "person-cards person-cards--download" Elementgruppe):
     1. Image element - single source file, the high-res original (e.g.
        files/downloads/<name>_ret.jpg, ~1000-1500px wide, the same file
        also linked below for the 300 dpi download). Give it an image
        size preset that crops to a square (e.g. 330x330, Größenänderungs-
        modus "Exaktes Format" - Contao crops centered by default, no
        separate position field) so mismatched portrait originals all
        read as a uniform photo grid - see the "CSS Grid gotchas" style
        note for why a plain max-width alone doesn't work when source
        ratios differ. Also set "Bilddichten"/densities to "1x, 2x" on
        that same preset - a single 330x330 raster stretched to a 330px
        CSS box looks visibly soft on retina/HiDPI displays; densities
        makes Contao add a 660x660 candidate to the img's srcset (both
        source originals are comfortably larger than 660px on both
        sides, so nothing gets upscaled) and the browser picks it
        automatically. Check "Vollbildansicht"/fullsize - this is what
        makes Contao wrap the image in the native lightbox <a data-
        lightbox> link. Leave the layout's own "lightboxSize" (Design >
        Layouts > JavaScript tab > image_legend) empty so the lightbox
        shows the ORIGINAL uncropped file, not the same small square crop
        used on the card.
     2. Nested Elementgruppe, class "download-bar", wrapping 2x native
        "Download" content elements: one linking the _96.jpg (screen/96
        dpi) file with label "96 dpi", one linking the _ret.jpg (print/
        300 dpi, same file as the image above) file with label "300 dpi".
        Using the native Download element (not raw HTML links) means the
        file is picked via Contao's file picker and the title/mime type
        are derived automatically.

   One-time layout setup (Design > Layouts > default > JavaScript tab):
   check "jQuery", then tick "Colorbox" in the jQuery script list. This
   is Contao core's own bundled j_colorbox template (contao-components/
   colorbox, already a project dependency) - literally the same script
   and init options (loop:false, maxWidth/maxHeight 95%) the OLD site
   used for this exact page, just shipped as a native Contao feature
   instead of hand-added. No custom JS of our own needed. */

.person-cards--download .person-card {
  position: relative;
  max-width: 330px;
  margin: 0 auto;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
}

.person-cards--download .person-card .content-image {
  margin: 0;
}

.person-cards--download .person-card .content-image img {
  display: block;
  width: 100%;
  max-width: none;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 0;
  margin: 0;
  transition: transform 0.3s ease;
}

.person-cards--download .person-card:hover .content-image img {
  transform: scale(1.04);
}

/* Stretched link: the <a data-lightbox> Contao renders around the photo
   (only present because "fullsize" is checked on the Image element) gets
   an ::after stretched over the whole card via inset: 0, relative to
   .person-card (position: relative, above) - not just its own figure -
   so the card reads as "click anywhere to enlarge", same stretched-link
   technique as .icon-box__item. */
.person-cards--download .person-card .content-image figure > a {
  display: block;
}

.person-cards--download .person-card .content-image figure > a::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* The download bar needs "position: relative" (any non-static value) to
   move it into the browser's "positioned elements" paint layer - the
   same layer the stretched ::after above lives in. Without it, the bar
   would stay in the plain/static layer, which always paints BELOW
   positioned elements regardless of DOM order, so the ::after would
   silently swallow every click on the buttons. Once both are positioned
   (z-index: auto on both), plain DOM order decides paint order, and the
   bar comes after .content-image in the markup - no z-index needed. */
.person-cards--download .person-card .download-bar {
  position: relative;
  display: flex;
  background: var(--cato-red, #9a1818);
}

.person-cards--download .person-card .download-bar .content-download {
  flex: 1 1 50%;
  text-align: center;
}

.person-cards--download .person-card .download-bar .content-download:first-child {
  border-right: 1px solid rgba(255, 255, 255, 0.3);
}

.person-cards--download .person-card .download-bar a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 10px;
  color: #fff;
  font-size: 14px;
  text-decoration: none;
  transition: background-color 0.2s;
}

.person-cards--download .person-card .download-bar a:hover {
  background-color: rgba(255, 255, 255, 0.15);
}

.person-cards--download .person-card .download-bar a::before {
  content: "";
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  background: url('/files/icons/download.svg') no-repeat center / contain;
}

