/* ==========================================================================
   SECA Security — Design System
   Palette derived from the SECA logo: charcoal artwork on warm bone paper,
   with a single restrained brass accent picked from the paper's warm undertone.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Ink — warm near-blacks, taken from the logo's charcoal */
  --ink-900: #131311;
  --ink-800: #1B1A17;
  --ink-700: #26251F;
  --ink-600: #3A382F;

  /* Neutrals */
  --stone-600: #6E6A5F;
  --stone-500: #8A8578;
  --stone-300: #C2BCAD;
  --stone-200: #DED8C9;

  /* Bone — straight from the logo background */
  --bone-100: #EFE9DD;
  --bone-50:  #F4F0E7;
  --paper:    #FBF9F5;
  --white:    #FFFFFF;

  /* Accent — restrained brass, the warm undertone of the bone made visible */
  --brass:     #7E6238;  /* AA on all three light grounds: 5.4 / 5.0 / 5.7 */
  --brass-lt:  #C5A876;

  /* Hairlines */
  --rule-dark:  rgba(19, 19, 17, 0.13);
  --rule-light: rgba(239, 233, 221, 0.16);

  /* Type */
  --font-display: "Manrope", "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Layout */
  --container: 1400px;
  --gutter: clamp(1.25rem, 5vw, 5rem);
  --section-y: clamp(5.5rem, 11vw, 10.5rem);

  /* Header */
  --header-h: 112px;
  --header-h-sm: 80px;

  /* Logo aspect ratios — must match the viewBox of the traced SVGs */
  --logo-lockup-ratio: 2.2273;  /* 567.17 / 254.64 */
  --logo-mark-ratio: 4.9582;    /* 567.17 / 114.39 */

  /* Motion */
  --ease: cubic-bezier(0.22, 0.80, 0.28, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.30, 1);
  --dur: 500ms;
  --dur-slow: 700ms;
}

/* --------------------------------------------------------------------------
   1b. Dim page — TRIAL, September 2026
   --------------------------------------------------------------------------
   Takes the page off white and onto the warm bone the logo actually sits on.
   Only the light grounds move; the dark sections, the type and the layout are
   untouched.

   TO GO BACK TO THE WHITE PAGE: delete this block. Nothing else refers to it.

   Two foreground tokens move with the backgrounds, because a darker ground eats
   contrast and both were close to the line already. Measured against the new
   --bone-50, the tighter of the two grounds:

     --brass      #7E6238 -> 4.37  under AA        #6E5530 -> 5.36  AA
     --stone-600  #6E6A5F -> 4.14  under AA        #645F57 -> 4.86  AA

   --stone-600 carries the card, course, rental and step body text, so it has to
   clear 4.5 rather than the 3.0 that large text would allow.

   A second step took every ground 5% darker again for a while and pulled
   --stone-600 down with it; both were put back. Measured against --bone-50,
   the tightest ground, on the values that stand today:

     --stone-600  #645F57 -> 4.86  AA
     --brass      #6E5530 -> 5.36  AA

   The rental plates' KI marker stays at 0.64 rather than the 0.60 it carried
   before the darker step: on this lighter --bone-50 that value measures 4.44
   and misses the small-text bar, while 0.64 clears it at 5.04.
   -------------------------------------------------------------------------- */
:root {
  --paper:     #EFEAE0;
  --bone-50:   #E7E1D4;
  --white:     #F7F4EC;
  --brass:     #6E5530;
  --stone-600: #645F57;
  --rule-dark: rgba(19, 19, 17, 0.17);
}

/* --------------------------------------------------------------------------
   2. Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: var(--header-h-sm);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-800);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.7;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

img, video, svg { display: block; max-width: 100%; }
img { height: auto; }

/* `display: contents` makes <picture> generate no box of its own, so an <img>
   sized with height:100% resolves against the real container. As a block-level
   wrapper it would collapse to auto height and letterbox the image instead. */
picture { display: contents; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  margin: 0;
  letter-spacing: -0.028em;
  line-height: 1.08;
  text-wrap: balance;
  /* German compounds like "Sicherheitsanforderungen" are wider than a phone
     viewport at display sizes — let them hyphenate rather than run off-screen. */
  overflow-wrap: break-word;
  hyphens: auto;
}

p { margin: 0 0 1.15em; }
p:last-child { margin-bottom: 0; }

ul, ol { margin: 0; padding: 0; list-style: none; }

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

button, input, select, textarea { font: inherit; color: inherit; }

address { font-style: normal; }

::selection { background: var(--ink-900); color: var(--bone-100); }

/* --------------------------------------------------------------------------
   3. Utilities
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.75rem, 3.2vw, 3.25rem);
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

.skip-link {
  position: absolute; top: 0; left: 50%;
  transform: translate(-50%, -120%);
  z-index: 200;
  background: var(--ink-900); color: var(--bone-100);
  padding: 0.85rem 1.5rem;
  font-size: 0.85rem; font-weight: 600;
  transition: transform 200ms var(--ease);
}
.skip-link:focus { transform: translate(-50%, 0); }

:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 3px;
  border-radius: 1px;
}

/* --------------------------------------------------------------------------
   4. Typography scale
   -------------------------------------------------------------------------- */
.display-xl {
  font-size: clamp(2.6rem, 6.1vw, 5.4rem);
  line-height: 1.02;
  letter-spacing: -0.038em;
  font-weight: 700;
}
.display-lg {
  font-size: clamp(2rem, 4.1vw, 3.5rem);
  line-height: 1.06;
  letter-spacing: -0.032em;
}
.display-md {
  font-size: clamp(1.7rem, 3vw, 2.6rem);
  line-height: 1.1;
  letter-spacing: -0.028em;
}

.lead {
  font-size: clamp(1.06rem, 1.15vw, 1.22rem);
  line-height: 1.62;
  color: var(--ink-700);
}
.section--facts .lead,
.section--contact .lead { color: rgba(239, 233, 221, 0.76); }

.note {
  font-size: 0.9rem;
  color: var(--stone-600);
}

/* Eyebrow ------------------------------------------------------------------ */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin: 0 0 1.6rem;
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brass);
}
.eyebrow__rule {
  display: block;
  width: 2.25rem;
  height: 1px;
  background: currentColor;
  opacity: 0.55;
  flex: none;
}
.eyebrow--light { color: var(--brass-lt); }

/* --------------------------------------------------------------------------
   5. Logo (SVG mask so it inherits currentColor)
   -------------------------------------------------------------------------- */
.logo {
  display: block;
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
}
.logo--lockup {
  -webkit-mask-image: url("../brand/seca-lockup.svg");
  mask-image: url("../brand/seca-lockup.svg");
  height: var(--logo-h, 34px);
  width: calc(var(--logo-h, 34px) * var(--logo-lockup-ratio));
}
.logo--mark {
  -webkit-mask-image: url("../brand/seca-mark.svg");
  mask-image: url("../brand/seca-mark.svg");
  height: var(--logo-h, 34px);
  width: calc(var(--logo-h, 34px) * var(--logo-mark-ratio));
}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--ink-900);
  --btn-fg: var(--bone-100);
  --btn-bd: var(--ink-900);
  --btn-hover: var(--ink-600);

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 1.05rem 2.1rem;
  border: 1px solid var(--btn-bd);
  border-radius: 2px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-body);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  line-height: 1;
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  transition: color 320ms var(--ease), border-color 320ms var(--ease), background-color 320ms var(--ease);
}
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--btn-hover);
  transform: scaleY(0);
  transform-origin: bottom;
  transition: transform 420ms var(--ease-out);
}
.btn:hover::before, .btn:focus-visible::before { transform: scaleY(1); }

.btn--solid { --btn-bg: var(--ink-900); --btn-fg: var(--bone-100); --btn-bd: var(--ink-900); --btn-hover: var(--ink-600); }

.btn--solid-bone {
  --btn-bg: var(--bone-100); --btn-fg: var(--ink-900);
  --btn-bd: var(--bone-100); --btn-hover: var(--white);
}

.btn--outline {
  --btn-bg: transparent; --btn-fg: currentColor;
  --btn-bd: currentColor; --btn-hover: transparent;
  border-color: color-mix(in srgb, currentColor 45%, transparent);
}
.btn--outline:hover, .btn--outline:focus-visible { border-color: currentColor; }

.btn--ghost-light {
  --btn-bg: transparent; --btn-fg: var(--bone-100);
  --btn-bd: rgba(239, 233, 221, 0.4); --btn-hover: rgba(239, 233, 221, 0.12);
}
.btn--ghost-light:hover, .btn--ghost-light:focus-visible { --btn-fg: var(--white); border-color: rgba(239,233,221,0.75); }

.btn--sm { padding: 0.9rem 1.6rem; font-size: 0.75rem; }
.btn--block { display: flex; width: 100%; }

/* --------------------------------------------------------------------------
   7. Header
   -------------------------------------------------------------------------- */
.header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 90;
  color: var(--bone-100);
  transition: background-color 450ms var(--ease), color 450ms var(--ease),
              box-shadow 450ms var(--ease), border-color 450ms var(--ease);
  border-bottom: 1px solid transparent;
}
.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  height: var(--header-h);
  transition: height 450ms var(--ease);
}
.header__brand { --logo-h: 44px; display: block; transition: opacity 300ms var(--ease); }
.header__brand:hover { opacity: 0.7; }
.header__brand .logo { transition: height 450ms var(--ease), width 450ms var(--ease); }

/* Scrolled state */
.header.is-scrolled {
  background: color-mix(in srgb, var(--paper) 88%, transparent);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  backdrop-filter: saturate(160%) blur(14px);
  color: var(--ink-900);
  border-bottom-color: var(--rule-dark);
}
.header.is-scrolled .header__inner { height: var(--header-h-sm); }
.header.is-scrolled .header__brand { --logo-h: 34px; }

/* Menu-open state on mobile */
/* The open menu is a fixed sheet that scrolls its own content, and the header
   sits above it. Left transparent, the logo stayed put while the menu items
   slid underneath it — "04 Verleih" ended up written across the wordmark. The
   header therefore takes the menu's own ink while it is open: nothing changes
   at rest, and scrolled items now disappear behind the bar instead of through
   the logo. */
.header.is-menu-open { color: var(--bone-100); background: var(--ink-900); border-bottom-color: transparent; -webkit-backdrop-filter: none; backdrop-filter: none; }

/* Nav ---------------------------------------------------------------------- */
/* The language switch used to live inside .nav, which the burger hides whole —
   so on a phone DE/EN was two taps away behind the menu. It now sits beside the
   burger in .header__right, which stays visible at every width; only the link
   list and the CTA drop out. */
.header__right { display: flex; align-items: center; gap: clamp(1.5rem, 2.6vw, 2.75rem); }
.nav { display: flex; align-items: center; }
.nav__list { display: flex; align-items: center; gap: clamp(1.4rem, 2.4vw, 2.5rem); }

.nav__link {
  position: relative;
  display: inline-block;
  /* Seven items, a language switch and a button make a full bar. Without this,
     "Über uns" and "Anfrage stellen" broke across two lines at 1024-1080px and
     again at 1181-1279px — a two-line label in a one-line bar. The widths below
     then make sure nowrap does not turn into an overflow. */
  white-space: nowrap;
  padding: 0.5rem 0;
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  opacity: 0.86;
  transition: opacity 300ms var(--ease);
}
.nav__link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 420ms var(--ease-out);
}
.nav__link:hover, .nav__link:focus-visible { opacity: 1; }
.nav__link:hover::after, .nav__link:focus-visible::after { transform: scaleX(1); transform-origin: left; }
.nav__link.is-active { opacity: 1; }
.nav__link.is-active::after { transform: scaleX(1); background: var(--brass); }
.header.is-scrolled .nav__link.is-active::after { background: var(--brass); }

.nav__cta { margin-left: 0.25rem; white-space: nowrap; }

/* Language switcher --------------------------------------------------------- */
.langswitch {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
}
.langswitch__item {
  padding: 0.35rem 0.1rem;
  /* The inactive language is a link people are meant to find, so it is held to
     4.5:1 like any other text. Over the hero it measures 3.87:1 at 0.45 and
     5.11:1 at 0.55 — still clearly the quieter of the two. */
  opacity: 0.55;
  transition: opacity 300ms var(--ease);
}
.langswitch__item:hover { opacity: 0.9; }
.langswitch__item.is-current { opacity: 1; }
.langswitch__sep {
  width: 1px; height: 0.7rem;
  background: currentColor;
  opacity: 0.25;
}

/* Burger ------------------------------------------------------------------- */
.burger {
  display: none;
  place-items: center;
  width: 46px; height: 46px;
  margin-right: -10px;
  background: none; border: 0; cursor: pointer;
  color: inherit;
}
.burger__box { position: relative; display: block; width: 24px; height: 12px; }
.burger__line {
  position: absolute; left: 0;
  width: 100%; height: 1.5px;
  background: currentColor;
  transition: transform 420ms var(--ease-out), width 420ms var(--ease-out);
}
.burger__line:nth-child(1) { top: 0; }
.burger__line:nth-child(2) { bottom: 0; width: 70%; }
.burger[aria-expanded="true"] .burger__line:nth-child(1) { transform: translateY(5.25px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__line:nth-child(2) { width: 100%; transform: translateY(-5.25px) rotate(-45deg); }

/* --------------------------------------------------------------------------
   8. Mobile menu
   -------------------------------------------------------------------------- */
.mobilemenu {
  position: fixed;
  inset: 0;
  z-index: 80;
  background: var(--ink-900);
  color: var(--bone-100);
  opacity: 0;
  visibility: hidden;
  transition: opacity 460ms var(--ease), visibility 460ms;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mobilemenu.is-open { opacity: 1; visibility: visible; }

.mobilemenu__inner {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 3rem;
  padding-top: calc(var(--header-h-sm) + 3rem);
  padding-bottom: 3rem;
}

.mobilemenu__list { display: flex; flex-direction: column; }
.mobilemenu__list li {
  border-bottom: 1px solid var(--rule-light);
  opacity: 0;
  transform: translateY(14px);
}
.mobilemenu.is-open .mobilemenu__list li,
.mobilemenu.is-open .mobilemenu__foot {
  opacity: 1;
  transform: none;
  transition: opacity 520ms var(--ease) calc(var(--i) * 65ms + 120ms),
              transform 520ms var(--ease-out) calc(var(--i) * 65ms + 120ms);
}
.mobilemenu__list a {
  display: flex;
  align-items: baseline;
  gap: 1rem;
  padding: 1.15rem 0;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 8vw, 2.5rem);
  font-weight: 600;
  letter-spacing: -0.03em;
}
.mobilemenu__num {
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  color: var(--brass-lt);
}
.mobilemenu__foot { opacity: 0; transform: translateY(14px); }
.mobilemenu__meta {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-top: 1.75rem;
  font-size: 0.95rem;
  color: rgba(239, 233, 221, 0.7);
}
.mobilemenu__meta a:hover { color: var(--bone-100); }
.mobilemenu__lang { margin-top: 0.85rem; color: var(--bone-100); }

/* --------------------------------------------------------------------------
   9. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 620px;
  height: 88vh;
  max-height: 1000px;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--ink-900);
  color: var(--bone-100);
  isolation: isolate;
}
/* Oversized by 14% top and bottom so the parallax shift never exposes an edge.
   Keep this in sync with the 0.10 factor in main.js (0.10 < 0.14). */
.hero__media { position: absolute; inset: -14% 0; z-index: -2; will-change: transform; }
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.40) contrast(1.06) brightness(0.88);
}

.hero__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    /* 0% is the bottom edge. Solid for the last few percent, so the frame the
       next section fades out of is flat ink rather than ink-over-photograph. */
    linear-gradient(to top, rgba(19,19,17,1) 0%, rgba(19,19,17,0.99) 4%, rgba(19,19,17,0.94) 11%, rgba(19,19,17,0.55) 42%, rgba(19,19,17,0.28) 72%, rgba(19,19,17,0.45) 100%),
    linear-gradient(to right, rgba(19,19,17,0.74) 0%, rgba(19,19,17,0.34) 52%, rgba(19,19,17,0.10) 100%),
    linear-gradient(rgba(126, 98, 56, 0.10), rgba(126, 98, 56, 0.10));
}

.hero__content { padding-bottom: clamp(5.5rem, 11vh, 9rem); padding-top: calc(var(--header-h) + 2rem); }
.hero__title {
  max-width: 17ch;
  font-size: clamp(2.5rem, 6vw, 5.2rem);
  line-height: 1.03;
  letter-spacing: -0.038em;
  margin-bottom: 1.5rem;
  text-wrap: pretty;
}
.hero__lead {
  max-width: 44ch;
  font-size: clamp(1.05rem, 1.3vw, 1.28rem);
  line-height: 1.6;
  color: rgba(239, 233, 221, 0.82);
  margin-bottom: 2.6rem;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; }

/* Scroll cue --------------------------------------------------------------- */
.scrollcue {
  position: absolute;
  right: var(--gutter);
  bottom: clamp(2rem, 5vh, 3.25rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  color: rgba(239, 233, 221, 0.65);
  transition: color 300ms var(--ease);
}
.scrollcue:hover { color: var(--bone-100); }
.scrollcue__label {
  font-size: 0.62rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  writing-mode: vertical-rl;
}
.scrollcue__line { position: relative; width: 1px; height: 56px; background: rgba(239, 233, 221, 0.22); overflow: hidden; }
.scrollcue__line::after {
  content: "";
  position: absolute; inset: 0;
  background: var(--brass-lt);
  animation: cue 2.4s var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: translateY(-100%); }
  55%  { transform: translateY(0); }
  100% { transform: translateY(100%); }
}

/* --------------------------------------------------------------------------
   10. Sections — shared
   -------------------------------------------------------------------------- */
.section { position: relative; padding-block: var(--section-y); }
/* The hero ends on ink and this section stands on paper, and the two met as a
   hard line straight across the page.

   The first attempt at this faded ink into paper over 180px and still read as an
   edge. Measuring a pixel column across the seam showed why: the brightness was
   continuous, but its SLOPE was not. Above the seam the hero is flat to within a
   point; one pixel below, the ramp was already climbing 2.5 points per pixel and
   held that rate. The eye reads that corner in the curve as a line — a Mach band
   — even though no step in value exists.

   So the stops below follow a smoothstep (3t^2 - 2t^3) rather than a straight
   ramp: the slope leaves zero gradually at the top and returns to zero at the
   bottom, and no corner is left for the eye to catch. The cost is a steeper
   middle, which is why the band is also half again as long as it was.

   Painted as a background layer, not a pseudo-element: nothing to manage in the
   stacking context, and it cannot end up over the copy. At 230px it stays under
   this section's own top padding, which starts the copy at 88-168px. */
.section--intro {
  background-color: var(--paper);
  background-image: linear-gradient(to bottom,
    rgba(19, 19, 17, 1)     0%,
    rgba(19, 19, 17, 0.972) 10%,
    rgba(19, 19, 17, 0.896) 20%,
    rgba(19, 19, 17, 0.784) 30%,
    rgba(19, 19, 17, 0.648) 40%,
    rgba(19, 19, 17, 0.5)   50%,
    rgba(19, 19, 17, 0.352) 60%,
    rgba(19, 19, 17, 0.216) 70%,
    rgba(19, 19, 17, 0.104) 80%,
    rgba(19, 19, 17, 0.028) 90%,
    rgba(19, 19, 17, 0)     100%);
  background-repeat: no-repeat;
  background-position: top center;
  background-size: 100% clamp(140px, 18vh, 230px);
  /* The band needs room above the first line or the eyebrow ends up sitting on
     tinted ground: at 375px the section's own top padding bottoms out at 88px
     while the band is 140px, which put the eyebrow at 35% ink and its contrast
     at 3.95:1, under AA. This clears the band at every size — 148px of padding
     against a 140px band on the shortest phone, 268 against 230 on the tallest
     desktop — and the extra air under the hero suits a fade anyway. */
  padding-top: calc(var(--section-y) + clamp(60px, 8vh, 110px));
}
.section--services { background: var(--bone-50); }
.section--facts { background: var(--ink-900); color: var(--bone-100); overflow: hidden; }
.section--approach { background: var(--paper); }
.section--training { background: var(--bone-50); }
.section--rental { background: var(--paper); }
.section--industries { background: var(--bone-50); }
.section--jobs { background: var(--paper); }

/* The section opener. Eyebrow, heading, then the deck directly beneath it.

   It used to be two columns — heading on the left, explanation pinned to the
   right — and that ran through six sections in a row. Two blocks at opposite
   ends of the page read as two things that happen to share a line, with a hole
   between them whose width changed with every heading. Stacked, it reads as one
   opener: the deck sits under the words it belongs to, its measure is set by
   reading comfort rather than by a column, and the space to the right becomes
   margin instead of a gap. */
.section__head { margin-bottom: clamp(3.25rem, 6vw, 5.5rem); }
.section__head-right {
  margin: clamp(1.4rem, 2.4vw, 2rem) 0 0;
  /* 68ch, not the textbook 54: this face renders ~1.5 characters per ch, so the
     narrower measure was already running 81-character lines *and* breaking most
     decks over three or four lines. Widening drops the whole page from 18 deck
     lines to 14 and no deck past three. Past 68ch the line count stops falling
     and only the line length keeps growing, so this is where it pays off. */
  max-width: 68ch;
  font-size: 1.06rem;
  line-height: 1.7;
  color: var(--stone-600);
}
.section--facts .section__head-right,
.section--contact .section__head-right { color: rgba(239, 233, 221, 0.7); }

/* --------------------------------------------------------------------------
   11. Intro
   -------------------------------------------------------------------------- */
/* The sentence that hands over to the principles band. Same voice and measure
   as the deck above it, so the section reads as one column of text rather than
   as an introduction followed by an aside. */
/* Every other section puts a component under its head, so the head carries a
   large bottom margin. Here the next thing is another paragraph, and that gap
   read as a hole between two pieces of the same text. */
.section--intro .section__head { margin-bottom: clamp(1.4rem, 2.4vw, 2rem); }

.intro__lead-in {
  max-width: 68ch;
  margin: 0;
  font-size: 1.06rem;
  line-height: 1.7;
  color: var(--stone-600);
}

/* The numbers, set large. Every figure here is already established elsewhere on
   the page — the founding year, the three divisions, the eleven courses, the
   round-the-clock line in the contact block — so the band states what the site
   already says, in a form that can be taken in at a glance. Nothing invented:
   a figure nobody can check does not belong on a security company's page. */
.stats {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  margin: clamp(2.5rem, 4.5vw, 3.75rem) 0 clamp(2.75rem, 5vw, 4rem);
  border-top: 1px solid var(--rule-dark);
  border-bottom: 1px solid var(--rule-dark);
}
.stats li {
  padding: clamp(1.5rem, 2.4vw, 2.25rem) clamp(1.1rem, 1.8vw, 1.6rem);
  border-right: 1px solid var(--rule-dark);
}
.stats li:first-child { padding-left: 0; }
.stats li:last-child { padding-right: 0; border-right: 0; }

.stat__figure {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.4rem, 4.2vw, 3.6rem);
  font-weight: 600;
  letter-spacing: -0.035em;
  line-height: 1;
  /* Brass, not ink. It is the only colour the page owns besides the two
     greys, and on a figure this size it carries — 5.22:1 against the paper,
     well past the 3:1 large text is held to. */
  color: var(--brass);
  font-variant-numeric: tabular-nums;
}
.stat__label {
  display: block;
  margin-top: 0.8rem;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--stone-600);
}

/* The four principles the copy announces. Set as one typographic line rather
   than a divided band: the "Warum SECA" section directly below is a band of
   four numbered cells, and the same component twice in a row — once light, once
   dark — read as a repeat rather than as two different things. Large display
   type with brass separators gives this section its own anchor instead. */
.principles {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  margin: clamp(2.25rem, 4vw, 3.25rem) 0 clamp(2.75rem, 5vw, 4rem);
  font-family: var(--font-display);
  font-size: clamp(1.15rem, 1.9vw, 1.7rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.35;
  color: var(--ink-900);
}
.principles li { display: inline-flex; align-items: baseline; }
.principles li:not(:last-child)::after {
  content: "·";
  margin: 0 clamp(0.6rem, 1.4vw, 1.1rem);
  color: var(--brass);
  font-weight: 400;
}

/* --------------------------------------------------------------------------
   12. Services
   -------------------------------------------------------------------------- */
/* The service cards run on the same rail as the sectors: three in view instead
   of six at once, so the section is one row deep rather than two.
   Doubled selector on purpose — .rail sets --rail-per-view: 4 further down the
   file, and at equal specificity the later rule would win. */
.rail.rail--services { --rail-gap: clamp(1.5rem, 2.4vw, 2.5rem); --rail-per-view: 3; }
.section--services .section__head { margin-bottom: clamp(1.5rem, 2.6vw, 2.25rem); }

.card__inner {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  transition: transform 550ms var(--ease-out);
}
.card__media {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--stone-200);
  border-radius: 2px;
}
.card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transform: scale(1.001);
  transition: transform 900ms var(--ease-out), filter 550ms var(--ease);
  filter: saturate(0.72) contrast(1.06);
}
.card__media::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(19,19,17,0.35), rgba(19,19,17,0) 55%);
  opacity: 0.85;
  transition: opacity 550ms var(--ease);
}

.card__body {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  padding-top: 1.6rem;
  margin-top: 1.5rem;
  border-top: 1px solid var(--rule-dark);
}
.card__body::before {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  height: 1px; width: 100%;
  background: var(--brass);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 620ms var(--ease-out);
}
.card__num {
  position: absolute;
  top: 1.6rem; right: 0;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--stone-600);
}
.card__title {
  font-size: clamp(1.2rem, 1.55vw, 1.45rem);
  letter-spacing: -0.022em;
  margin-bottom: 0.6rem;
  padding-right: 3rem;
}
.card__text {
  font-size: 0.95rem;
  line-height: 1.62;
  color: var(--stone-600);
  margin-bottom: 1.1rem;
  max-width: 34ch;
}

.card__more {
  margin-top: auto;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  /* 0.75rem top/bottom takes the control to a 44px tap target. */
  padding: 0.75rem 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-900);
  transition: color 300ms var(--ease);
}
.card__arrow {
  position: relative;
  display: block;
  width: 26px; height: 1px;
  background: currentColor;
  transition: width 420ms var(--ease-out);
}
.card__arrow::after {
  content: "";
  position: absolute;
  right: 0; top: 50%;
  width: 6px; height: 6px;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
  transform: translateY(-50%) rotate(45deg);
}

/* Card hover / focus — one shared trigger */
.card__inner:hover, .card__inner:focus-within { transform: translateY(-6px); }
.card__inner:hover .card__media img,
.card__inner:focus-within .card__media img { transform: scale(1.06); filter: saturate(0.88) contrast(1.06); }
.card__inner:hover .card__media::after,
.card__inner:focus-within .card__media::after { opacity: 0.45; }
.card__inner:hover .card__body::before,
.card__inner:focus-within .card__body::before { transform: scaleX(1); }
.card__inner:hover .card__more, .card__inner:focus-within .card__more { color: var(--brass); }
.card__inner:hover .card__arrow, .card__inner:focus-within .card__arrow { width: 38px; }

/* Detail is revealed inline only when JS is unavailable */
.card__detail { padding-top: 1.25rem; font-size: 0.92rem; color: var(--stone-600); }
.no-js .card__detail { display: block !important; }
.no-js .card__more { display: none; }

.ticklist { display: grid; gap: 0.6rem; margin-top: 1rem; }
.ticklist li {
  position: relative;
  padding-left: 1.4rem;
  font-size: 0.93rem;
  line-height: 1.55;
}
.ticklist li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.62em;
  width: 8px; height: 1px;
  background: var(--brass);
}

/* --------------------------------------------------------------------------
   13. Facts
   -------------------------------------------------------------------------- */
/* Sized by width — the mark is ~5:1, so driving it off height would blow it
   far past the viewport. */
.facts__watermark {
  --w: clamp(420px, 52vw, 900px);
  position: absolute;
  right: -4%;
  top: 50%;
  width: var(--w);
  height: calc(var(--w) / var(--logo-mark-ratio));
  transform: translateY(-50%);
  color: var(--bone-100);
  opacity: 0.04;
  pointer-events: none;
}

.facts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  border-top: 1px solid var(--rule-light);
}
.fact {
  position: relative;
  padding: clamp(2rem, 3.2vw, 3rem) clamp(1.25rem, 2vw, 2.25rem) 0.5rem;
  border-right: 1px solid var(--rule-light);
}
.fact:first-child { padding-left: 0; }
.fact:last-child { border-right: 0; padding-right: 0; }

.fact__index {
  display: block;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--brass-lt);
  margin-bottom: 1.5rem;
}
.fact__value {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 2.1vw, 1.95rem);
  font-weight: 600;
  letter-spacing: -0.026em;
  line-height: 1.14;
  /* Two headings wrap and two do not — reserve both lines so every
     description below starts on the same baseline. */
  min-height: 2.28em;
  margin-bottom: 0.85rem;
  color: var(--bone-100);
}
.fact__text {
  font-size: 0.92rem;
  line-height: 1.6;
  color: rgba(239, 233, 221, 0.6);
  max-width: 28ch;
}

/* --------------------------------------------------------------------------
   14. Approach
   -------------------------------------------------------------------------- */
/* The three steps are a sequence, so they are drawn as one. A single line runs
   the width of the row and is stroked in as the block comes into view, with a
   marker sitting on it at each step. Each step keeps its own rule underneath as
   the resting state, so without JS — or under prefers-reduced-motion — the row
   simply appears finished. */
.steps {
  --draw: 1400ms;
  position: relative;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  counter-reset: step;
}
.steps::after {
  content: "";
  position: absolute;
  top: -1px; left: 0;
  width: 100%; height: 1px;
  background: var(--brass);
  transform: scaleX(1);
  transform-origin: left center;
}
/* Linear, deliberately. With the site's ease-out the line covered 70% of its
   length in the first fifth of the time, so the markers — timed to where they
   sit — always lit up long after the stroke had swept past them. Linear makes
   position and time the same thing, and the markers are simply placed at the
   fraction of the duration that matches their fraction of the width. */
.js-reveal-ready .steps::after {
  transform: scaleX(0);
  transition: transform var(--draw) linear;
}
.js-reveal-ready .steps.is-drawn::after { transform: scaleX(1); }

/* Measured: the three columns start at 0%, ~35% and ~70% of the row, and that
   holds from 1024 to 1600px. --cue is that share of --draw. */
.step { position: relative; padding-top: 2.25rem; border-top: 1px solid var(--rule-dark); --cue: 0ms; }
.step:nth-child(2) { --cue: calc(var(--draw) * 0.35); }
.step:nth-child(3) { --cue: calc(var(--draw) * 0.70); }

.step::before {
  content: "";
  position: absolute;
  top: -4px; left: 0;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--brass);
  transform: scale(1);
}
.js-reveal-ready .step::before {
  transform: scale(0);
  transition: transform 340ms var(--ease-out);
}
.js-reveal-ready .steps.is-drawn .step::before {
  transform: scale(1);
  transition-delay: var(--cue);
}

/* The step's own content follows its marker rather than the page-wide reveal,
   which ran at 0/90/180ms and so had all three columns standing before the
   line had drawn. */
.js-reveal-ready .step > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease-out);
}
.js-reveal-ready .steps.is-drawn .step > * {
  opacity: 1;
  transform: none;
}
.js-reveal-ready .steps.is-drawn .step__num   { transition-delay: calc(var(--cue) + 90ms); }
.js-reveal-ready .steps.is-drawn .step__title { transition-delay: calc(var(--cue) + 160ms); }
.js-reveal-ready .steps.is-drawn .step__text  { transition-delay: calc(var(--cue) + 230ms); }
.step__num {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 4.5vw, 3.75rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--stone-500);
  margin-bottom: 1.4rem;
  transition: color 500ms var(--ease);
}
.step:hover .step__num { color: var(--brass); }
.step__title {
  font-size: clamp(1.25rem, 1.7vw, 1.6rem);
  margin-bottom: 0.7rem;
}
.step__text { font-size: 0.98rem; line-height: 1.65; color: var(--stone-600); max-width: 34ch; }

/* The three steps used to have a section of their own on paper. They now sit
   under the facts on ink, so the tones that worked on a light ground have to be
   restated — --stone-600 body text on #131311 measures 2.1:1 and is unreadable.
   The sub-heading replaces the section head the steps lost, and carries the
   sentence that used to be their intro. */
.approach {
  margin-top: clamp(3.5rem, 6vw, 5.5rem);
  padding-top: clamp(2.5rem, 4vw, 3.5rem);
  border-top: 1px solid var(--rule-light);
}
.approach__title {
  font-size: clamp(1.15rem, 1.6vw, 1.45rem);
  letter-spacing: -0.022em;
  color: var(--bone-100);
  margin-bottom: clamp(2rem, 3.5vw, 3rem);
}
.section--facts .step { border-top-color: var(--rule-light); }
/* 40% rather than the 32% it looked best at: the step numbers are large text,
   which is held to 3:1, and 32% measured 2.58:1. */
.section--facts .step__num { color: rgba(239, 233, 221, 0.40); }
.section--facts .step:hover .step__num { color: var(--brass-lt); }
.section--facts .step__title { color: var(--bone-100); }
.section--facts .step__text { color: rgba(239, 233, 221, 0.6); }

/* --------------------------------------------------------------------------
   15. Training
   -------------------------------------------------------------------------- */
/* The course catalogue. Eleven entries, so the names carry the section and the
   description and datasheet stay folded away until asked for — a three-column
   grid of full entries ran to two screens and buried the list it was meant to
   show.

   Built on <details>/<summary>, not on a script: the rows open and close with
   JavaScript off, keyboard and screen-reader behaviour come from the browser,
   and there is no state for the site to get wrong. */
.courses {
  border-top: 1px solid var(--rule-dark);
}

/* Eleven courses in one column left about 750px of nothing between each name
   and its "Mehr erfahren", eleven times over — the list read as a bare table of
   contents. Two columns close that gap and halve the section's height. Only
   here: the jobs section reuses .courses for two panels, which belong stacked. */
.section--training .courses {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
  /* Eleven is odd, so the last row has only a left cell and its rule would stop
     half way. The container closes the block across both columns. */
  border-bottom: 1px solid var(--rule-dark);
}
/* …and the last cell drops its own rule, which otherwise landed 1px above the
   container's and read as a thicker line under the left column only. */
.section--training .courses > li:last-child { border-bottom: 0; }
.courses > li { border-bottom: 1px solid var(--rule-dark); }

.course__head {
  display: flex;
  align-items: baseline;
  gap: clamp(1rem, 2.4vw, 2rem);
  padding: clamp(1rem, 1.6vw, 1.35rem) 0;
  cursor: pointer;
  list-style: none;                 /* the default triangle, Firefox and others */
  transition: color 300ms var(--ease);
}
.course__head::-webkit-details-marker { display: none; }   /* …and Safari */
.course__head:hover { color: var(--brass); }
.course__head:focus-visible { outline: 2px solid var(--brass); outline-offset: 4px; }

/* A dot rather than a running number. Eleven courses are a catalogue, not a
   sequence — the numbering implied an order to work through that does not
   exist, and in two columns it read as 01/02, 03/04 across the rows rather
   than down them. Decorative, so it is hidden from assistive technology. */
.course__dot {
  flex: none;
  align-self: center;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--brass);
  transition: transform 300ms var(--ease-out), background 300ms var(--ease);
}
.course__head:hover .course__dot { transform: scale(1.35); }
details[open] .course__dot { transform: scale(1.35); }
.course__name {
  flex: 1;
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.25vw, 1.18rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.3;
  margin: 0;
}
/* The affordance. Set like the card links so the row reads as openable rather
   than as a heading someone forgot to link. */
.course__more {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--stone-600);
  transition: color 300ms var(--ease);
}
.course__more::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform 340ms var(--ease-out);
}
.course__head:hover .course__more { color: var(--brass); }
details[open] .course__more::after { transform: rotate(225deg) translate(-2px, -2px); }
details[open] .course__more { color: var(--brass); }

.course__text {
  max-width: 62ch;
  margin: 0 0 0.9rem;
  padding-left: calc(0.66rem + clamp(1rem, 2.4vw, 2rem));
  font-size: 0.93rem;
  line-height: 1.65;
  color: var(--stone-600);
}
.course__doc {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1.35rem;
  margin-left: calc(0.66rem + clamp(1rem, 2.4vw, 2rem));
  /* 0.5rem top and bottom takes this to a 44px tap target. */
  padding: 0.5rem 0;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-700);
  border-bottom: 1px solid var(--rule-dark);
  transition: color 300ms var(--ease), border-color 300ms var(--ease);
}
.course__doc::before {
  content: "";
  flex: none;
  width: 9px; height: 9px;
  border-left: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(-45deg) translate(1px, -1px);
}
.course__doc:hover, .course__doc:focus-visible { color: var(--brass); border-color: var(--brass); }

/* Same closing row as the jobs section: anchored at both ends of the rule it
   hangs from, rather than a button parked mid-row with the rest of the width
   empty behind it. */
.training__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.5rem, 3vw, 3rem);
  /* No rule of its own: the list above already closes with one, and the two
     sat a blank stretch apart with nothing between them. Spacing separates. */
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
}
.training__foot .note { margin: 0; max-width: 76ch; }

/* --------------------------------------------------------------------------
   16b. AI marker
   --------------------------------------------------------------------------
   Every photographic frame on this page is AI-generated, and several of them
   read as staff at real locations. Art. 50 of the AI Act and the WKO's own
   guidance both ask for the label to sit AT the picture, not only in the
   imprint — so a line in the imprint alone is not enough.

   Kept as quiet as the requirement allows: the site's smallest lettered type,
   bottom-right where every frame already carries a dark gradient, no chip, no
   border, no icon. It reads at arm's length and disappears at a glance.
   Deliberately not `aria-hidden`: a disclosure that screen readers cannot hear
   is not a disclosure. -------------------------------------------------------- */
.aimark {
  position: absolute;
  right: 0.7rem;
  bottom: 0.5rem;
  z-index: 2;
  /* Smaller than first drawn, with the opacity raised to compensate: shrinking
     the type and dimming it at the same time would have taken the contrast
     under 2.5:1, at which point it stops being a disclosure and becomes an
     alibi. Less ink on the page, same legibility. */
  /* "KI*", not a bare asterisk. Art. 50(5) of the AI Act wants the disclosure
     "spätestens zum Zeitpunkt der ersten Interaktion oder Aussetzung in klarer
     und eindeutiger Weise" — at first sight of the picture, in clear terms. An
     asterisk alone says nothing at that moment; the reader would have to go
     hunting in the footer, and a screen reader would announce "Sternchen".
     The two letters carry the disclosure, the asterisk carries the detail. */
  font-size: 0.54rem;
  line-height: 1;
  /* Light weight, tight spacing, and no more opacity than the contrast needs.
     "KI*" is text, so it is held to 4.5:1, not to the 3:1 that non-text and
     large text get — an earlier pass read it as non-text and settled at 0.45,
     which measures 3.28-3.95:1 across the twenty-one marks. Re-measured the
     same way (screenshot with the glyphs hidden, average the pixels behind each
     mark, composite the colour over that): 0.65 puts the weakest at 5.09:1.
     The mark did not grow or move — it only became readable. */
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(239, 233, 221, 0.65);
  pointer-events: none;
}
/* The rental shots are the one set keyed against the paper rather than shot on
   a dark ground, so the bone mark landed light-on-light: 1.03:1, which is not a
   quiet disclosure but an absent one. Same size, same place, ink instead of
   bone — 5.20:1. */
.rental .aimark { color: rgba(19, 19, 17, 0.65); }

/* The hero and contact backgrounds sit at z-index -2 and the hero one is moved
   by the parallax, so their markers hang off the section instead of the media. */
.aimark--fixed {
  right: var(--gutter);
  bottom: 0.9rem;
  font-weight: 400;
  color: rgba(239, 233, 221, 0.55);
}
/* The scroll cue owns the hero's bottom-right corner. */
.hero .aimark--fixed { right: auto; left: var(--gutter); }

/* --------------------------------------------------------------------------
   16. Rental — equipment row
   -------------------------------------------------------------------------- */
/* Five short entries that belong to one another, so they read as one divided
   row rather than five stacked paragraphs: a rule top and bottom, hairlines
   between the columns, and the numbers carrying the count. The responsive
   overrides in section 23 fold this to two-up and then to a single column. */
.rentals {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  border-top: 1px solid var(--rule-dark);
  border-bottom: 1px solid var(--rule-dark);
}
.rental {
  padding: clamp(1.6rem, 2.4vw, 2.25rem) clamp(1.1rem, 1.8vw, 1.6rem);
  border-right: 1px solid var(--rule-dark);
}
.rental:first-child { padding-left: 0; }
.rental:last-child { padding-right: 0; border-right: 0; }

.rental__num {
  display: block;
  margin-bottom: clamp(0.9rem, 1.4vw, 1.2rem);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--brass);
}
/* The equipment shots. They arrive as objects on a white studio field; rather
   than cut each one out, the white is multiplied away against the paper, which
   costs nothing and leaves no matte edge. The pipeline snaps that field to pure
   white first (flatten_white) so the blend is exact.
   Fixed height, contain, bottom-aligned: a tall archway and a wide barrier then
   share one standing line instead of each floating in its own box. */
.rental__shot {
  position: relative;
  display: block;
  /* The blend must not depend on what the ancestors are doing. .reveal animates
     opacity and transform, and each of those creates a stacking context, so
     during the fade the image can end up multiplying against transparency
     instead of against the page — which shows the studio white for a frame or
     two. Isolating here and carrying the paper tone on the box itself means the
     image always has the same ground underneath, at every stage of the
     animation and on every engine. */
  isolation: isolate;
  /* A plate under each object. The fill alone is invisible — every light tone
     on this page sits within 1.09:1 of the next — so the hairline is what
     makes it read, and the fill is there for the multiply blend to land on. */
  background: var(--bone-50);
  border: 1px solid var(--rule-dark);
  border-radius: 2px;
  height: clamp(7rem, 10.5vw, 9.25rem);
  margin-bottom: clamp(1.1rem, 1.8vw, 1.5rem);
}
.rental__shot img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: center;
  padding: clamp(0.5rem, 1vw, 0.85rem);
  mix-blend-mode: multiply;
}
/* The marker sits on paper here, not on a dark photograph, so it needs ink
   rather than bone — the shared bone value would be invisible. */
.rental__shot .aimark {
  right: 0.35rem;
  bottom: 0.2rem;
  /* Ink at 0.60 over --paper resolves to rgb(107,105,100) — 4.57:1, the lowest
     alpha that clears the 4.5:1 small-text bar. The bone value the photographic
     marks use would be invisible here; 0.50 looked right but measures 3.36:1,
     which only satisfies the non-text bar, and this is text. */
  /* Raised from 0.60 when the grounds went a further 5% darker: 0.60 fell to
     4.40 against the new --paper, just under the bar. Now 4.98:1. */
  color: rgba(19, 19, 17, 0.64);
}

/* One press opens all five at once, for anyone who would rather read the row
   than click through it. The label and aria-expanded follow the actual state,
   so opening the last one by hand flips the button to "close" as well. */
.rentals__tools { display: flex; justify-content: flex-end; margin-bottom: clamp(0.9rem, 1.4vw, 1.25rem); }
.no-js .rentals__tools { display: none; }

.toggle-all {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.35rem 0;
  border: 0;
  background: none;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--stone-600);
  transition: color 300ms var(--ease);
}
/* Same glyph and geometry as .course__more, so the section has one chevron. */
.toggle-all::after {
  content: "";
  width: 7px; height: 7px;
  border-right: 1px solid currentColor;
  border-bottom: 1px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform 340ms var(--ease-out);
}
.toggle-all[aria-expanded="true"]::after { transform: rotate(225deg) translate(-2px, -2px); }
.toggle-all:hover { color: var(--brass); }
.toggle-all:focus-visible { outline: 2px solid var(--brass); outline-offset: 4px; }

/* The descriptions fold away behind the name, the same disclosure the course
   catalogue uses — five short paragraphs at once made the row look busier than
   the five words actually are. Native <details>, so it still opens without JS. */
/* No words on the rows — five identical "Mehr erfahren" labels said the same
   thing as the one button above the grid. Just the chevron, in the same size
   and geometry as the one on the course rows and on that button, so the whole
   page still has a single kind of arrow. */
.rental__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  cursor: pointer;
  list-style: none;
}
.rental__head::-webkit-details-marker { display: none; }
.rental__head::after {
  content: "";
  flex: none;
  width: 7px; height: 7px;
  border-right: 1px solid var(--stone-600);
  border-bottom: 1px solid var(--stone-600);
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform 340ms var(--ease-out), border-color 300ms var(--ease);
}
.rental__more[open] .rental__head::after { transform: rotate(225deg) translate(-2px, -2px); }
.rental__head:hover::after,
.rental__more[open] .rental__head::after { border-color: var(--brass); }
.rental__head:hover .rental__name,
.rental__more[open] .rental__name { color: var(--brass); }
.rental__head:focus-visible { outline: 2px solid var(--brass); outline-offset: 4px; }

.rental__name {
  /* The names run one or two lines. Reserving both keeps every chevron on the
     same line across the row. */
  min-height: 2.6em;
  margin: 0;
  transition: color 300ms var(--ease);
  font-family: var(--font-display);
  font-size: clamp(0.98rem, 1.15vw, 1.1rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.3;
}
.rental__text {
  margin: 0.7rem 0 0;
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--stone-600);
}
/* The only closing action on the page that was not anchored to the end of the
   rule above it. Aligned right now, like the training and jobs rows. */
.rental__foot {
  display: flex;
  justify-content: flex-end;
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
}
.rental__cta { margin: 0; }

/* --------------------------------------------------------------------------
   17. Industries — image tiles
   -------------------------------------------------------------------------- */
/* A rail rather than a block of eight. Four tiles are in view, the rest arrive
   by scrolling — natively, so a trackpad swipe works and the arrows are only a
   second way in. Scroll snap keeps the row aligned to a tile edge after every
   move, and the whole thing degrades to a plain horizontal scroller when the
   buttons are unavailable. */
.rail { --rail-gap: clamp(0.65rem, 1.2vw, 1.1rem); --rail-per-view: 4; }

/* Under this head comes the small control row, not a component, so the full
   section gap left a hole between the deck and the arrows. */
.section--industries .section__head { margin-bottom: clamp(1.5rem, 2.6vw, 2.25rem); }

.rail__nav {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  margin-bottom: clamp(1rem, 1.6vw, 1.4rem);
}
.no-js .rail__nav { display: none; }

/* Outlined, these read as decoration on a page already full of hairlines and
   were easy to miss. Filled, at the weight of the page's solid buttons, they
   are unmistakably the control. The end state falls back to an outline: still
   visible, clearly not available. */
.rail__btn {
  width: 3rem;
  height: 3rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--ink-900);
  border-radius: 2px;
  background: var(--ink-900);
  color: var(--bone-100);
  cursor: pointer;
  transition: background 300ms var(--ease), color 300ms var(--ease),
              border-color 300ms var(--ease), opacity 300ms var(--ease);
}
.rail__btn::before {
  content: "";
  width: 9px; height: 9px;
  border-top: 1.5px solid currentColor;
  border-right: 1.5px solid currentColor;
}
[data-rail-prev]::before { transform: rotate(-135deg) translate(-1px, -1px); }
[data-rail-next]::before { transform: rotate(45deg) translate(-1px, 1px); }
.rail__btn:hover:not(:disabled) { background: var(--brass); border-color: var(--brass); }
.rail__btn:focus-visible { outline: 2px solid var(--brass); outline-offset: 3px; }
.rail__btn:disabled {
  background: transparent;
  border-color: var(--rule-dark);
  color: var(--stone-600);
  opacity: 0.5;
  cursor: default;
}

/* Says how far along the row is and — more usefully — that there is a row to
   scroll at all, which the arrows alone do not convey on a touch screen. */
.rail__progress {
  position: relative;
  height: 1px;
  margin-top: clamp(1rem, 1.6vw, 1.4rem);
  background: var(--rule-dark);
}
.rail__progress span {
  position: absolute;
  top: -1px;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--ink-900);
  transform-origin: left center;
  transform: scaleX(0);
  transition: transform 220ms var(--ease-out);
}

[data-rail-track] {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - (var(--rail-per-view) - 1) * var(--rail-gap)) / var(--rail-per-view));
  gap: var(--rail-gap);
  overflow-x: auto;
  /* The reveal translates each item down 22px before it settles; without this
     the rail would grow a vertical scrollbar for the length of that animation. */
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
[data-rail-track]::-webkit-scrollbar { display: none; }
[data-rail-track]:focus-visible { outline: 2px solid var(--brass); outline-offset: 4px; }
[data-rail-track] > * { scroll-snap-align: start; }

.industry__inner {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  border-radius: 2px;
  background: var(--ink-800);
}
.industry__media { position: absolute; inset: 0; }
.industry__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Only a light touch here: these files are already tonally matched to each
     other on disk, so the heavier grade used on the service cards would stack
     on top of it and crush the tiles into unreadable black. */
  filter: saturate(0.82) contrast(1.02) brightness(1.08);
  transform: scale(1.001);
  transition: transform 900ms var(--ease-out), filter 550ms var(--ease);
}
/* Dark where the name sits, near-clear through the middle so the picture is
   actually visible, with a slight top wash to hold the number. */
.industry__inner::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to top,
    rgba(19,19,17,0.88) 0%,
    rgba(19,19,17,0.36) 40%,
    rgba(19,19,17,0.08) 72%,
    rgba(19,19,17,0.26) 100%);
  transition: opacity 550ms var(--ease);
}

.industry__num,
.industry__name { position: absolute; z-index: 1; }

.industry__num {
  top: clamp(0.85rem, 1.3vw, 1.15rem);
  left: clamp(0.9rem, 1.4vw, 1.25rem);
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--brass-lt);
}
.industry__name {
  left: clamp(0.9rem, 1.4vw, 1.25rem);
  right: clamp(0.9rem, 1.4vw, 1.25rem);
  bottom: clamp(0.9rem, 1.4vw, 1.25rem);
  padding-top: 0.85rem;
  font-family: var(--font-display);
  font-size: clamp(0.98rem, 1.25vw, 1.22rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.2;
  color: var(--bone-100);
  hyphens: manual;
}
.industry__name::before {
  content: "";
  position: absolute;
  top: 0; left: 0;
  width: 1.75rem; height: 1px;
  background: var(--brass-lt);
  transition: width 620ms var(--ease-out);
}

.industry__inner:hover .industry__media img { transform: scale(1.06); }
.industry__inner:hover::after { opacity: 0.82; }
.industry__inner:hover .industry__name::before { width: 3.25rem; }

.industries__note {
  margin-top: 2.5rem;
  font-size: 0.92rem;
  color: var(--stone-600);
}
.industries__note strong { color: var(--ink-900); font-weight: 600; }


/* --------------------------------------------------------------------------
   17b. Partners
   -------------------------------------------------------------------------- */
/* Two entries, so a two-up divided row rather than the wider grids elsewhere.
   No logos: the marks belong to the partners and we have no licence for them,
   so the name is set in the display face and carries itself. */
.section--partners { background: var(--paper); }

/* On a rail now, three in view: four stacked cards over two rows made this the
   tallest section on the page for the least content. The container rules and
   the dividers between cells went with the grid — in a scrolling row each card
   stands on its own, and the framed logo plate already gives it an edge.
   The grounds alternate ink / paper, which is not decoration: Pfeffer's and
   LOTHAR's marks are light and need the dark plate, Movetos' and Tresor's are
   dark and need the light one, so the order makes rhythm and artwork agree. */
.rail.rail--partners { --rail-gap: clamp(1.25rem, 2vw, 2rem); --rail-per-view: 3; }

.partner {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

/* A shot of the partner's own homepage, the way a link preview shows a page.
   Decorative: the name and the link right underneath already say where this
   goes, so it is hidden from assistive technology and taken out of the tab
   order rather than read out twice. */
.partner__shot {
  display: block;
  margin-top: clamp(0.9rem, 1.6vw, 1.25rem);
  border: 1px solid var(--rule-dark);
  border-radius: 2px;
  overflow: hidden;
  /* Neutral placeholder: half these cards are light, so the ink one used
     here flashed dark behind them before the image arrived. */
  background: var(--white);
  aspect-ratio: 16 / 10;
}
.partner__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  transform: scale(1.001);
  transition: transform 900ms var(--ease-out);
}
.partner:hover .partner__shot img { transform: scale(1.04); }

.partner__num {
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--brass);
}
.partner__name {
  margin: clamp(0.9rem, 1.5vw, 1.2rem) 0 0.6rem;
  font-family: var(--font-display);
  font-size: clamp(1.05rem, 1.3vw, 1.22rem);
  font-weight: 600;
  letter-spacing: -0.022em;
  line-height: 1.25;
}
.partner__text {
  margin: 0 0 clamp(1rem, 1.6vw, 1.35rem);
  font-size: 0.88rem;
  line-height: 1.6;
  color: var(--stone-600);
}
/* An underlined caption read as a footnote next to a full-bleed logo card. As
   a bordered button it is plainly the way out to the partner, and it fills on
   hover like the rail controls do. */
.partner__link {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  align-self: flex-start;
  margin-top: auto;
  padding: 0.7rem 1.15rem;
  border: 1px solid var(--ink-900);
  border-radius: 2px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-900);
  text-decoration: none;
  transition: color 300ms var(--ease), background 300ms var(--ease),
              border-color 300ms var(--ease);
}
/* Leaves the site, so it says so rather than relying on the visitor noticing
   a new tab opening. */
.partner__link::after {
  content: "";
  width: 7px; height: 7px;
  border-top: 1px solid currentColor;
  border-right: 1px solid currentColor;
  transform: rotate(45deg) translateY(1px);
  transition: transform 300ms var(--ease-out);
}
.partner__link:hover {
  background: var(--ink-900);
  border-color: var(--ink-900);
  color: var(--bone-100);
}
.partner__link:hover::after { transform: rotate(45deg) translate(2px, -1px); }
.partner__link:focus-visible { outline: 2px solid var(--brass); outline-offset: 4px; }

/* --------------------------------------------------------------------------
   18. Jobs
   -------------------------------------------------------------------------- */
/* The open positions are the news here; the requirements and the offer are
   detail, so they fold away behind the same disclosure rows the course
   catalogue uses — one component, one behaviour, half the height. */
.jobs__lead {
  font-size: clamp(1.1rem, 1.5vw, 1.35rem);
  letter-spacing: -0.022em;
  margin-bottom: 1.1rem;
}
.ticklist--folded { margin: 0 0 1.35rem; }

/* The closing row sits under a full-width rule, so it has to reach both ends of
   it. Left unanchored the button landed mid-row with 505px of dead space behind
   it — space-between pins it to the right edge and the emptiness between the two
   reads as layout instead of as a gap someone forgot to close. */
/* The requirements are the section's whole content now, so they are set as a
   divided three-up block rather than a dashed list: each one numbered, named
   and spelled out, in the same language as the rental row and the facts. */
.reqs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  margin-top: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--rule-dark);
}
.req {
  padding: clamp(1.4rem, 2.2vw, 2rem) clamp(1.1rem, 1.8vw, 1.6rem);
  border-right: 1px solid var(--rule-dark);
  border-bottom: 1px solid var(--rule-dark);
}
.req:nth-child(3n + 1) { padding-left: 0; }
.req:nth-child(3n) { padding-right: 0; border-right: 0; }

.req__num {
  display: block;
  font-size: 0.66rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--brass);
}
.req__label {
  margin: clamp(0.9rem, 1.5vw, 1.25rem) 0 0.5rem;
  font-family: var(--font-display);
  font-size: clamp(1rem, 1.2vw, 1.15rem);
  font-weight: 600;
  letter-spacing: -0.022em;
}
.req__text {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--stone-600);
}

.jobs__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 3rem);
  /* No rule of its own: the list above already closes with one, and the two
     sat a blank stretch apart with nothing between them. Spacing separates. */
  margin-top: clamp(2.25rem, 4vw, 3.25rem);
}
/* 76ch: at 0.9rem this lands the note on two nearly equal lines (114 and 110
   characters) instead of three with a 36-character stub, and it ends up the
   same pixel width as the deck above, so both blocks share a right edge. */
.jobs__foot .note { margin: 0; max-width: 76ch; }

/* --------------------------------------------------------------------------
   19. Contact
   -------------------------------------------------------------------------- */
.section--contact {
  position: relative;
  background: var(--ink-900);
  color: var(--bone-100);
  overflow: hidden;
  isolation: isolate;
}
.contact__media { position: absolute; inset: 0; z-index: -2; }
.contact__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(0.5) contrast(1.05);
}
.contact__scrim {
  position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to right, rgba(19,19,17,0.96) 0%, rgba(19,19,17,0.88) 45%, rgba(19,19,17,0.78) 100%);
}

.contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}
/* The section's own headline, on the dark ground. Full display size now that
   it is one short word — the cap was there for "Sicherheitsanforderungen",
   which used to hyphenate in this column. */
.contact__intro .display-lg {
  margin-bottom: clamp(1.5rem, 2.6vw, 2.25rem);
  color: var(--bone-100);
}

/* Every entry labelled and on its own line, separated by a hairline: on a dark
   photograph an unlabelled telephone number and an unlabelled address are just
   two blocks of light text, and the visitor has to work out which is which. */
.contact__list {
  margin: clamp(2.25rem, 4vw, 3rem) 0 0;
  border-top: 1px solid var(--rule-light);
}
.contact__row {
  display: grid;
  grid-template-columns: minmax(0, 10rem) minmax(0, 1fr);
  gap: 0.35rem 1.5rem;
  padding: clamp(0.85rem, 1.4vw, 1.1rem) 0;
  border-bottom: 1px solid var(--rule-light);
}
.contact__row dt {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--brass-lt);
  align-self: center;
}
.contact__row dd {
  margin: 0;
  font-size: 1rem;
  line-height: 1.55;
  color: var(--bone-100);
  align-self: center;
}
.contact__row address { font-style: normal; }
.contact__row a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-color: rgba(239, 233, 221, 0.3);
  transition: color 300ms var(--ease), text-decoration-color 300ms var(--ease);
}
.contact__row a:hover { color: var(--brass-lt); text-decoration-color: var(--brass-lt); }


/* Form --------------------------------------------------------------------- */
.contact__formwrap {
  background: rgba(27, 26, 23, 0.72);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid var(--rule-light);
  border-radius: 3px;
  padding: clamp(1.75rem, 3vw, 2.75rem);
}
.form { color-scheme: dark; }
.form__title {
  font-family: var(--font-display);
  font-size: 1.1rem;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin-bottom: 1.75rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid var(--rule-light);
}
.form__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }

.field { margin-bottom: 1.1rem; display: flex; flex-direction: column; gap: 0.45rem; }
.field label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(239, 233, 221, 0.62);
}
.field label span { color: var(--brass-lt); }

/* The CV field belongs to one choice in the dropdown, so it is hidden until
   that choice is made. The rule is scoped to the scripted page: without JS
   nothing can toggle it, and an applicant would be left with no way to attach
   anything — so there it simply stays visible. */
html:not(.no-js) .field--file { display: none; }
html:not(.no-js) .field--file.is-on { display: flex; }

.field__hint {
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(239, 233, 221, 0.45);
}
.field--file input[type="file"] {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border: 1px dashed var(--rule-light);
  border-radius: 2px;
  background: transparent;
  color: rgba(239, 233, 221, 0.78);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}
.field--file input[type="file"]::file-selector-button {
  margin-right: 0.85rem;
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--rule-light);
  border-radius: 2px;
  background: transparent;
  color: var(--bone-100);
  font: inherit;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
}
.field--file input[type="file"]:hover { border-color: var(--brass-lt); }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.8rem 0.95rem;
  background: rgba(239, 233, 221, 0.05);
  border: 1px solid rgba(239, 233, 221, 0.17);
  border-radius: 2px;
  color: var(--bone-100);
  font-size: 0.95rem;
  transition: border-color 260ms var(--ease), background-color 260ms var(--ease), box-shadow 260ms var(--ease);
}
.field textarea { resize: vertical; min-height: 6.5rem; line-height: 1.6; }
.field input::placeholder, .field textarea::placeholder { color: rgba(239, 233, 221, 0.35); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--brass-lt);
  background: rgba(239, 233, 221, 0.08);
  box-shadow: 0 0 0 3px rgba(197, 168, 118, 0.16);
}
.field.has-error input, .field.has-error select, .field.has-error textarea { border-color: #C56B5A; }
.field__error { margin: 0; font-size: 0.78rem; color: #E09384; }

.field--check {
  flex-direction: row;
  align-items: flex-start;
  gap: 0.7rem;
  flex-wrap: wrap;
  margin-bottom: 1.6rem;
}
.field--check input {
  width: 17px; height: 17px;
  margin-top: 0.22rem;
  flex: none;
  accent-color: var(--brass-lt);
  padding: 0;
}
.field--check label {
  flex: 1;
  min-width: 12rem;
  font-size: 0.82rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  line-height: 1.55;
  color: rgba(239, 233, 221, 0.62);
}
.field--check a { text-decoration: underline; text-underline-offset: 3px; }
.field--check a:hover { color: var(--bone-100); }
.field--check .field__error { flex-basis: 100%; }

.form__status { margin: 1.1rem 0 0; font-size: 0.88rem; line-height: 1.55; min-height: 1px; }
.form__status.is-ok { color: var(--brass-lt); }
.form__status.is-err { color: #E09384; }

/* --------------------------------------------------------------------------
   20. Footer
   -------------------------------------------------------------------------- */
.footer { background: var(--ink-900); color: var(--bone-100); padding-top: clamp(4rem, 7vw, 6.5rem); }
.footer__inner {
  display: grid;
  /* Three columns since the navigation one went: it repeated the sticky header
     line for line, on a page that is reachable from that header at any scroll
     position. Rechtliches stays — those three are not in the header, and the
     footer is where people look for them. */
  /* Two columns since the contact block went: the mark on the left, the three
     legal links on the right. Both sit on their own edge, which is why the
     second track takes what it needs rather than a share of the row. */
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(2.25rem, 4vw, 4rem);
  padding-bottom: clamp(3rem, 5vw, 4.5rem);
}
.footer__logo { --logo-h: 52px; color: var(--bone-100); }
.footer__h {
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brass-lt);
  margin-bottom: 1.4rem;
}
.footer__nav ul { display: flex; flex-direction: column; gap: 0.7rem; }
.footer__nav a, .footer__contact a {
  font-size: 0.93rem;
  color: rgba(239, 233, 221, 0.68);
  transition: color 280ms var(--ease);
}
.footer__nav a:hover, .footer__contact a:hover { color: var(--bone-100); }
.footer__contact address { font-size: 0.93rem; line-height: 1.7; color: rgba(239, 233, 221, 0.55); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 2rem;
  padding-block: 1.6rem 2rem;
  border-top: 1px solid var(--rule-light);
  font-size: 0.8rem;
  color: rgba(239, 233, 221, 0.55);
}
/* Resolves the asterisk the image markers carry. Sits in the footer rather than
   under each grid because two of the sixteen frames are full-bleed backgrounds
   with nowhere to put a legend of their own — and a footnote that resolves in
   one place on every page is easier to find than four scattered ones. */
.footer__ai {
  grid-column: 1 / -1;
  margin-top: 0.9rem;
  font-size: 0.72rem;
  color: rgba(239, 233, 221, 0.55);
}
.footer__bottom p { margin: 0; }

/* --------------------------------------------------------------------------
   21. Modal
   -------------------------------------------------------------------------- */
.modal { position: fixed; inset: 0; z-index: 120; display: grid; place-items: center; padding: 1.25rem; }
.modal[hidden] { display: none; }
.modal__backdrop {
  position: absolute; inset: 0;
  background: rgba(19, 19, 17, 0.72);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0;
  transition: opacity 400ms var(--ease);
}
.modal__panel {
  position: relative;
  width: min(640px, 100%);
  max-height: min(86vh, 780px);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--paper);
  border-radius: 3px;
  padding: clamp(2rem, 4vw, 3.25rem);
  box-shadow: 0 40px 90px -30px rgba(19, 19, 17, 0.55);
  opacity: 0;
  transform: translateY(18px) scale(0.99);
  transition: opacity 480ms var(--ease), transform 480ms var(--ease-out);
}
.modal.is-open .modal__backdrop { opacity: 1; }
.modal.is-open .modal__panel { opacity: 1; transform: none; }

.modal__close {
  position: absolute;
  top: 1.1rem; right: 1.1rem;
  width: 42px; height: 42px;
  display: grid; place-items: center;
  background: none; border: 1px solid var(--rule-dark); border-radius: 50%;
  cursor: pointer;
  transition: background-color 300ms var(--ease), border-color 300ms var(--ease), transform 300ms var(--ease);
}
.modal__close span, .modal__close span::before {
  content: "";
  display: block;
  width: 14px; height: 1.5px;
  background: var(--ink-900);
}
.modal__close span { transform: rotate(45deg); }
.modal__close span::before { transform: rotate(-90deg); }
.modal__close:hover { background: var(--ink-900); border-color: var(--ink-900); transform: rotate(90deg); }
.modal__close:hover span, .modal__close:hover span::before { background: var(--bone-100); }

.modal__eyebrow {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--brass);
  margin-bottom: 1rem;
}
.modal__title {
  font-size: clamp(1.6rem, 3vw, 2.25rem);
  letter-spacing: -0.03em;
  margin-bottom: 1.4rem;
  padding-right: 2.5rem;
}
.modal__body { font-size: 1rem; line-height: 1.7; color: var(--ink-700); }
.modal__body .ticklist { margin-top: 1.5rem; }
.modal__cta { margin-top: 2.25rem; }

/* --------------------------------------------------------------------------
   19b. Legal pages (Impressum, Datenschutz)
   -------------------------------------------------------------------------- */
.pagehead {
  background: var(--ink-900);
  color: var(--bone-100);
  padding-top: calc(var(--header-h) + clamp(3.5rem, 8vw, 6rem));
  padding-bottom: clamp(3rem, 6vw, 5rem);
}
.pagehead .display-lg { max-width: 22ch; }
.pagehead__back {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 2rem;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(239, 233, 221, 0.7);
  transition: color 300ms var(--ease);
}
.pagehead__back:hover { color: var(--bone-100); }
.pagehead__back::before {
  content: "";
  width: 22px; height: 1px;
  background: currentColor;
}

.legal { background: var(--paper); padding-block: clamp(3.5rem, 7vw, 6rem); }
.legal__inner { max-width: 68ch; }
.legal h2 {
  font-size: clamp(1.3rem, 2vw, 1.65rem);
  margin: 3rem 0 1.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--rule-dark);
}
.legal h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.legal h3 { font-size: 1.05rem; margin: 1.75rem 0 0.6rem; }
.legal p, .legal li { color: var(--ink-700); font-size: 0.98rem; line-height: 1.75; }
.legal ul { margin: 0 0 1.15em; display: grid; gap: 0.5rem; }
.legal ul li { position: relative; padding-left: 1.4rem; }
.legal ul li::before {
  content: "";
  position: absolute; left: 0; top: 0.72em;
  width: 8px; height: 1px; background: var(--brass);
}
.legal a { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--stone-300); }
.legal a:hover { text-decoration-color: var(--brass); }
.legal dl { display: grid; grid-template-columns: minmax(0, 13rem) minmax(0, 1fr); gap: 0.7rem 1.5rem; margin: 0; }
.legal dt { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--stone-600); padding-top: 0.2rem; }
.legal dd { margin: 0; font-size: 0.98rem; color: var(--ink-700); }

/* The WKO badge is the chamber's own artwork, carried over from the old site and
   linked to the company's entry in its register — required alongside the § 5 ECG
   disclosure. It ships at its native 233x35 and is shown at exactly that size:
   the only copy that exists is a bitmap, and scaling it up would just blur it. */
.wko { margin: 2.5rem 0 0; }
.wko a {
  display: inline-block;
  border: 0;
  opacity: 0.88;
  transition: opacity 300ms var(--ease);
}
.wko a:hover, .wko a:focus-visible { opacity: 1; }
.wko img { display: block; width: 233px; height: auto; }

.callout {
  margin: 2rem 0;
  padding: 1.35rem 1.5rem;
  background: var(--bone-50);
  border-left: 2px solid var(--brass);
  border-radius: 2px;
  font-size: 0.92rem;
  line-height: 1.65;
  color: var(--stone-600);
}

@media (max-width: 600px) {
  .legal dl { grid-template-columns: 1fr; gap: 0.15rem 0; }
  .legal dt { margin-top: 1rem; }
}

/* --------------------------------------------------------------------------
   19c. Message pages (404, thank-you)
   -------------------------------------------------------------------------- */
.msgpage {
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  place-items: center;
  background: var(--ink-900);
  color: var(--bone-100);
  text-align: center;
  padding: calc(var(--header-h) + 3rem) var(--gutter) 4rem;
}
.msgpage__inner { max-width: 46rem; }
.msgpage .eyebrow { justify-content: center; }
.msgpage__title {
  font-size: clamp(2rem, 4.4vw, 3.4rem);
  letter-spacing: -0.032em;
  line-height: 1.06;
  margin-bottom: 1.25rem;
}
.msgpage__text {
  font-size: clamp(1.02rem, 1.15vw, 1.18rem);
  line-height: 1.65;
  color: rgba(239, 233, 221, 0.72);
  margin-bottom: 2.5rem;
  max-width: 42ch;
  margin-inline: auto;
}
.msgpage__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; justify-content: center; }
.msgpage__mark {
  --w: clamp(150px, 22vw, 230px);
  width: var(--w);
  height: calc(var(--w) / var(--logo-mark-ratio));
  margin: 0 auto 2.75rem;
  color: var(--bone-100);
  opacity: 0.16;
}
@media (max-width: 767px) {

  .msgpage__actions { flex-direction: column; align-items: stretch; }
  .msgpage__actions .btn { width: 100%; }
}

/* --------------------------------------------------------------------------
   22. Reveal animation
   -------------------------------------------------------------------------- */
.reveal { opacity: 0; transform: translateY(22px); }
.js-reveal-ready .reveal {
  transition: opacity var(--dur-slow) var(--ease), transform var(--dur-slow) var(--ease-out);
  transition-delay: calc(var(--d, 0) * 90ms);
}
.reveal.is-visible { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   23. Responsive
   -------------------------------------------------------------------------- */

/* Laptop ------------------------------------------------------------------- */
/* Eight items with long German labels. At full size the row needs about
   1450px before the "Anfrage stellen" button clears the window edge, so it
   tightens in two steps and hands over to the burger earlier than the rest of
   the layout does. Measured, not guessed: at 1280 the button used to sit 49px
   past the edge and at 1024 41px, clipped by the header rather than scrolling. */
@media (max-width: 1450px) {
  .header__right { gap: 1.5rem; }
  .nav__list { gap: 1.15rem; }
  .nav__link { font-size: 0.86rem; }
}
/* The burger takes over at 1140 rather than 1023: below that the eight labels
   no longer fit beside the logo and the button, however tight the gaps. */
@media (max-width: 1140px) {
  .nav, .nav__cta { display: none; }
  .burger { display: grid; }
  /* Tighter than the desktop gap: the switch and the burger read as one group
     in the corner rather than two separate controls. */
  .header__right { gap: 1rem; }
  /* DE and EN measured 23x32 on a phone, just under the 24x24 a touch target
     needs. The padding grows and the gap shrinks by the same amount, so the
     tappable area passes without the two labels drifting apart. */
  .header__right .langswitch { gap: 0.25rem; }
  .header__right .langswitch__item { padding-left: 0.35rem; padding-right: 0.35rem; }
}

@media (max-width: 1240px) {
  .header__right { gap: 1.1rem; }
  .nav__list { gap: 0.9rem; }
  .nav__link { font-size: 0.82rem; }
  .btn--sm { padding: 0.8rem 1.15rem; font-size: 0.7rem; }
}

@media (max-width: 1279px) {


  /* Below this the longest course name no longer fits beside its label in half
     a container, and a wrapped name leaves the two columns' rules out of step.
     One column again. */
  /* One column again: the container's rule goes, so the last cell carries its
     own closing rule once more. */
  .section--training .courses { grid-template-columns: 1fr; border-bottom: 0; }
  .section--training .courses > li:last-child { border-bottom: 1px solid var(--rule-dark); }
}

/* The last stretch before the burger takes over at 1023px. */
/* Tablet ------------------------------------------------------------------- */
@media (max-width: 1023px) {

  /* Two-up: the outer side of each column clears the container edge, the inner
     side keeps its padding away from the divider. */
  .reqs { grid-template-columns: repeat(2, 1fr); }
  .req { padding-inline: clamp(1.1rem, 3vw, 1.6rem); }
  .req:nth-child(odd) { padding-left: 0; }
  .req:nth-child(even) { padding-right: 0; border-right: 0; }

  /* Two-up: each cell clears the container edge on its outer side and keeps the
     padding that faces the divider. */
  .stats { grid-template-columns: repeat(2, 1fr); }
  .stats li { padding-inline: clamp(1.1rem, 3vw, 1.6rem); }
  .stats li:nth-child(odd) { padding-left: 0; }
  .stats li:nth-child(even) { border-right: 0; padding-right: 0; }
  .stats li:nth-child(n + 3) { border-top: 1px solid var(--rule-dark); }
  :root { --header-h: 88px; --header-h-sm: 70px; }



  /* Below this width every user of .grid spans the full row anyway, so the
     twelve tracks only cost their gaps: eleven of them at the 1.75rem minimum
     is 308px of gap, which is more than a 320px phone has to give and pushed
     the whole page 8px wider than the viewport. One track, no gap floor. */
  .grid { grid-template-columns: 1fr; }

  /* Four position cells need roughly 230px each to hold their longest label on
     one or two lines. Below this the row gets cramped, so it folds to two-up —
     which keeps four items as a tidy block instead of a 3 + 1 orphan. */

  /* Two-up. Each column clears the container edge on its outer side and keeps
     its padding on the side that faces the divider, otherwise the right-hand
     column's text sits flush against the hairline. */
  .rentals { grid-template-columns: repeat(2, 1fr); }
  .rental { padding-inline: clamp(1.25rem, 3vw, 2.5rem); }
  .rental:nth-child(odd) { padding-left: 0; }
  .rental:nth-child(even) { border-right: 0; padding-right: 0; }
  .rental:nth-child(n + 3) { border-top: 1px solid var(--rule-dark); }
  .rental__name { min-height: 0; }

  .section__head-left, .section__head-right { grid-column: 1 / -1; }
  .section__head-right { max-width: 52ch; padding-bottom: 0; }

  .intro__head, .intro__body { grid-column: 1 / -1; }
  .intro__body { max-width: 60ch; }

  .rail.rail--services { --rail-per-view: 2; }

  .facts { grid-template-columns: repeat(2, 1fr); }
  .fact { padding-inline: 0 clamp(1.25rem, 3vw, 2.5rem); }
  .fact:nth-child(2n) { border-right: 0; padding-right: 0; }
  .fact:nth-child(n + 3) { border-top: 1px solid var(--rule-light); margin-top: 0; }
  .fact:nth-child(2n + 1) { padding-left: 0; }

  .steps { grid-template-columns: 1fr; gap: 2.25rem; }
  .step__text { max-width: 56ch; }



  /* Two tiles in view below this; one and a sliver on a phone, so the row
     visibly continues past the edge. */
  .rail { --rail-per-view: 2; }
  .rail.rail--partners { --rail-per-view: 2; }


  .contact { grid-template-columns: 1fr; }
  .contact__row { grid-template-columns: minmax(0, 8.5rem) minmax(0, 1fr); }
  .contact__formwrap { max-width: 620px; }

  .footer__inner { grid-template-columns: 1fr; }
}

/* Mobile ------------------------------------------------------------------- */
@media (max-width: 767px) {

  /* Nach dem 1023er-Block, sonst gewinnt dessen Zweispalter auch auf dem
     Handy und die Zellen laufen aus dem Viewport. */
  .reqs { grid-template-columns: 1fr; }
  .req { padding-inline: 0; border-right: 0; }

  .rentals { grid-template-columns: 1fr; }
  .rental { padding: 1.85rem 0 1.6rem; border-right: 0; }
  .rental:not(:first-child) { border-top: 1px solid var(--rule-dark); }
  .rental__num { margin-bottom: 0.9rem; }

  html { scroll-padding-top: calc(var(--header-h-sm) + 8px); }

  /* The <br>s in headings are desktop line-break control. On a phone they force
     over-long lines, so drop them and let the text wrap and hyphenate. */
  h1 br, h2 br { display: none; }

  .hero { height: auto; min-height: 0; padding-top: 0; }
  .hero__content {
    padding-top: calc(var(--header-h) + clamp(6rem, 22vh, 10rem));
    padding-bottom: clamp(6.5rem, 16vh, 8rem);
  }
  .hero__title { font-size: clamp(2.1rem, 9.5vw, 3rem); max-width: 14ch; }
  .hero__lead { font-size: 1.02rem; margin-bottom: 2.1rem; }
  .hero__actions { flex-direction: column; align-items: stretch; }
  .hero__actions .btn { width: 100%; }
  .scrollcue { display: none; }

  .rail.rail--services { --rail-per-view: 1.12; }
  .card__text { max-width: none; }

  .facts { grid-template-columns: 1fr; }
  .fact { padding: 1.85rem 0 1.6rem; border-right: 0; }
  .fact:not(:first-child) { border-top: 1px solid var(--rule-light); }
  .fact__index { margin-bottom: 1rem; }
  .fact__text { max-width: none; }

  .rail { --rail-per-view: 1.15; }
  .rail.rail--partners { --rail-per-view: 1.1; }



  /* Label over value on a phone: two columns leave the value about 120px. */
  .contact__row { grid-template-columns: 1fr; gap: 0.3rem; }

  .form__row { grid-template-columns: 1fr; gap: 0; }


  .footer__inner { grid-template-columns: 1fr; gap: 2.5rem; }

  .btn { padding: 1.05rem 1.75rem; }
  .modal__panel { max-height: 88vh; }
}

/* Fine pointer only — avoid sticky hover states on touch ------------------- */
@media (hover: none) {
  .card__inner:hover { transform: none; }
  .industry__inner:hover .industry__media img { transform: scale(1.001); }
}

/* --------------------------------------------------------------------------
   24. Reduced motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
  .hero__media { transform: none !important; }
  .scrollcue__line::after { animation: none; transform: translateY(0); }
  .modal__panel { transform: none; }
}

/* --------------------------------------------------------------------------
   25. Print
   -------------------------------------------------------------------------- */
@media print {
  .header, .mobilemenu, .scrollcue, .modal, .contact__media, .contact__scrim, .hero__media { display: none !important; }
  body { background: #fff; color: #000; }
  .section { padding-block: 1.5rem; }
  .reveal { opacity: 1 !important; transform: none !important; }
}
