/* ==========================================================================
   CanyeraTech — canyeratech.de
   Plain CSS, no build step, no JavaScript.
   Palette and proportions mirror liveprices.canyeratech.de so both sites
   read as one brand.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Design tokens
   -------------------------------------------------------------------------- */

:root {
  /* Surfaces */
  --bg:            #020617;   /* page + primary sections */
  --bg-alt:        #0f172a;   /* alternating sections */
  --card:          #0f172a;   /* card on --bg  */
  --card-alt:      #020617;   /* card on --bg-alt */
  --card-hover:    #1e293b;   /* one step lighter on the slate scale */
  --card-alt-hover:#0f172a;
  --line:          #1e293b;   /* borders, dividers */
  --line-hover:    #334155;

  /* Text */
  --fg:            #f1f5f9;   /* headings */
  --body:          #cbd5e1;   /* list / emphasised body text */
  --muted:         #94a3b8;   /* paragraphs, captions */

  /* Accent */
  --accent:        #2563eb;   /* buttons */
  --accent-hover:  #3b82f6;
  --accent-soft:   #60a5fa;   /* highlights, icons, links */
  --accent-tint:   rgb(37 99 235 / 0.20);
  --accent-edge:   rgb(59 130 246 / 0.30);
  --accent-glow:   rgb(37 99 235 / 0.10);

  /* Image treatment — tunable in one place.
     The veil lays --bg over every photo, weaker at the top than at the bottom
     so the image runs into the section below it. --img-boost gives the picture
     back some of the definition the veil takes away.
     Higher values = flatter; lower = punchier. */
  --veil-top:      0.14;
  --veil-bottom:   0.38;
  --img-boost:     contrast(1.08) saturate(1.06);

  /* Geometry */
  --radius:        0.75rem;
  --radius-sm:     0.5rem;
  --wrap:          80rem;     /* wide grids */
  --prose:         48rem;     /* running text */
  --gutter:        1rem;
  --card-col:      35rem;     /* width of the single-column card (and of the
                                 claim above it) below 64rem */

  /* Chrome — logo sizing lives here so it can be tuned in one place.
     The logo carries the line "TRUSTED SOLUTIONS" and therefore needs height to
     stay legible: it deliberately fills most of the header bar. */
  --header-h:      5rem;
  --logo-h:        3.75rem;
  --logo-h-footer: 4.5rem;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", "Noto Sans", Arial, sans-serif,
          "Apple Color Emoji", "Segoe UI Emoji";

  color-scheme: dark;
}

@media (max-width: 48rem) {
  :root {
    --header-h:      4.25rem;
    --logo-h:        3rem;
    --logo-h-footer: 3.75rem;
  }
}

/* --------------------------------------------------------------------------
   Reset / base
   -------------------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* anchor targets must clear the sticky header */
  scroll-padding-top: calc(var(--header-h) + 1rem);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.65;
  background: var(--bg);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  margin: 0;
  line-height: 1.2;
  font-weight: 700;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

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

a {
  color: var(--accent-soft);
  text-decoration: none;
  transition: color 0.15s ease;
}
a:hover { color: var(--fg); }

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent-soft);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus {
  left: 0;
  color: #fff;
}

/* --------------------------------------------------------------------------
   Layout helpers
   -------------------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--prose { max-width: var(--prose); }

@media (min-width: 40rem) { .wrap { padding-inline: 1.5rem; } }
@media (min-width: 64rem) { .wrap { padding-inline: 2rem; } }

.section { padding-block: 5rem; background: var(--bg); }
.section--alt { background: var(--bg-alt); }
.section--alt .card { background: var(--card-alt); }

/* One size for every section heading, on every page.
   (The h2 elements inside the legal pages are sub-headings and stay smaller on
   purpose — see .legal h2.) */
.section__title {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  margin-bottom: 2.5rem;
}
.section__title--tight { margin-bottom: 1.5rem; }

/* Centred section (Produkte on the start page): heading and claim centred,
   the cards inside stay left-aligned. */
.section--center { text-align: center; }
.section--center .card { text-align: left; }

/* Fixed font size instead of clamp(…, 2vw, …): type that shrinks with the
   viewport lets the sentence fit back onto one line as the window narrows —
   the wrapping would otherwise not behave monotonically.
   The width is chosen so the claim fits on one line on large screens and wraps
   only once it genuinely no longer fits. */
.section__lead {
  max-width: 72rem;
  margin: 0 auto 2.5rem;
  font-size: 1.1875rem;
  color: var(--body);
  text-wrap: pretty;
}
@media (max-width: 30rem) { .section__lead { font-size: 1.0625rem; } }

.stack > * + * { margin-top: 1rem; }
.prose { color: var(--muted); }
.prose strong { color: var(--body); font-weight: 600; }

/* --------------------------------------------------------------------------
   Header / navigation
   -------------------------------------------------------------------------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  border-bottom: 1px solid var(--line);
  background: rgb(2 6 23 / 0.80);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

/* The header bar spans the full window: logo at the left edge, menu at the
   right. The .wrap in the markup still supplies the side padding (1 / 1.5 /
   2 rem depending on width), only its max-width is dropped here.
   The content below stays centred on --wrap — the header deliberately sets
   itself apart from it rather than lining up with it. */
.site-header .wrap { max-width: none; }

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  height: var(--header-h);
}

.brand { display: flex; align-items: center; }
.brand img { height: var(--logo-h); width: auto; }

/* Desktop navigation */
.nav { display: flex; align-items: center; gap: 0.25rem; }

.nav a {
  display: inline-block;
  padding: 0.5rem 0.75rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--muted);
  border-radius: var(--radius-sm);
}
.nav a:hover { color: var(--fg); background: rgb(30 41 59 / 0.6); }
.nav a[aria-current="page"] { color: var(--fg); }

/* ---- "Produkte" dropdown (desktop only, no JavaScript) -------------------
   The trigger is a real link to the product overview on the start page: a tap
   therefore goes there, a mouse opens the submenu on hover, and a keyboard
   opens it on tabbing in (:focus-within). */

.nav-group {
  position: relative;
  align-self: stretch;      /* full header height: no gap between trigger and
                               menu for the pointer to fall through */
  display: flex;
  align-items: center;
}

/* `.nav a` has specificity (0,1,1) and beats a bare class — the trigger has to
   carry the type selector too, otherwise it stays inline-block and the chevron,
   which is display:block, drops onto a line of its own. */
.nav a.nav-group__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}
.nav-group__trigger svg { width: 0.875rem; height: 0.875rem; flex: none; }
.nav-group__trigger.is-current { color: var(--fg); }

.nav-group__menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 30;
  display: none;
  min-width: 12rem;
  padding: 0.375rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  box-shadow: 0 8px 12px -2px rgb(0 0 0 / 0.7), 0 24px 48px -12px rgb(0 0 0 / 0.85);
}
.nav-group:hover > .nav-group__menu,
.nav-group:focus-within > .nav-group__menu { display: block; }

.nav-group__menu a { display: block; white-space: nowrap; }

/* ---- sub-entries in the mobile panel ------------------------------------- */
.nav__sub {
  padding-left: 1.75rem !important;
  font-size: 0.875rem !important;
}

/* Mobile disclosure menu — pure HTML <details>, no JavaScript */
.nav-toggle { display: none; }

.nav-toggle > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--fg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.nav-toggle > summary::-webkit-details-marker { display: none; }
.nav-toggle > summary .icon-close { display: none; }
.nav-toggle[open] > summary .icon-open { display: none; }
.nav-toggle[open] > summary .icon-close { display: block; }

.nav-toggle__panel {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  padding: 0.75rem var(--gutter) 1.25rem;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}
.nav-toggle__panel .nav {
  flex-direction: column;
  align-items: stretch;
  gap: 0.125rem;
}
.nav-toggle__panel .nav a { padding: 0.75rem; }

@media (max-width: 60rem) {
  .site-header__inner { position: relative; }
  .nav--desktop { display: none; }
  .nav-toggle { display: block; }
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-block;
  padding: 0.625rem 1.25rem;
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: #fff;
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1.4;
  transition: background-color 0.15s ease;
}
.btn:hover { background: var(--accent-hover); color: #fff; }

.btn--lg { padding: 0.875rem 2rem; font-size: 1rem; }

.btn--ghost {
  background: transparent;
  color: var(--muted);
  font-weight: 600;
}
.btn--ghost:hover { background: transparent; color: var(--fg); }


/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--bg);
}

.hero__glow {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.hero__glow span {
  width: min(600px, 120vw);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--accent-glow);
  filter: blur(64px);
}

.hero__inner {
  position: relative;
  padding-block: 6rem;
  text-align: center;
}
@media (min-width: 48rem) { .hero__inner { padding-block: 8rem; } }

.hero--compact .hero__inner { padding-block: 4.5rem; }


.hero h1 {
  margin-top: 1.5rem;
  font-size: clamp(2.25rem, 6vw, 3.75rem);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  margin-top: 2.5rem;
}

/* Varianten statt style="…" im Markup: die CSP verbietet Inline-Styles. */
.hero__actions--start { justify-content: flex-start; margin-top: 3rem; }

/* --------------------------------------------------------------------------
   Image hero of the start page: heading over a full-bleed photo
   -------------------------------------------------------------------------- */

/* Höhe viewport-abhängig: auf typischen Notebooks (1440×780 bis 1512×860)
   ergibt 78% Höhe eine Box von rund 2,25:1 bis 2,37:1 — also ziemlich genau
   das 21:9-Format des Motivs, sodass kaum beschnitten werden muss.

   svh statt vh: auf Mobilbrowsern meint vh die Viewport-Höhe mit
   ausgeblendeter Adressleiste. Der Hero wäre damit beim Laden höher als der
   sichtbare Bereich und würde beim Scrollen springen. svh bezieht sich auf
   den kleinen (sichtbaren) Viewport und bleibt stabil. Die vh-Zeile davor
   ist der Fallback für Browser ohne svh-Unterstützung. */
.hero--image {
  display: flex;
  align-items: center;
  min-height: 78vh;
  min-height: 78svh;
}

/* <picture> is an inline element and would sit in the hero as an empty flex
   item; display:contents removes its box from the layout while the <img> inside
   stays absolutely positioned. */
.hero picture { display: contents; }

/* object-position 2 % instead of the default centre: the man sits in the left
   third of the master, the right half is landscape. Centred, he is the first
   thing to disappear as soon as the box becomes narrower than the 2.24:1 of the
   master — on a phone only the middle 37 % of the width remains, which is pure
   landscape. Aligned to the left he stays in frame down to the narrowest box.
   On wide screens the value has no effect: from 2.24:1 upwards the full width
   is visible anyway and only height is cropped. */
.hero__bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 2% 50%;
  filter: var(--img-boost);
  z-index: 0;
}

/* Darkening: the subject stays visible, the type stays legible. Darker towards
   the bottom so the hero runs cleanly into the next section.

   Deliberately stronger than on the other images: this is the only photo with
   the headline sitting directly on it. The bottom value stays high because it
   makes the transition into the section below — a light edge there would show
   as a seam. */
.hero--image::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    to bottom,
    rgb(2 6 23 / 0.24),
    rgb(2 6 23 / 0.36) 55%,
    rgb(2 6 23 / 0.88)
  );
}

.hero--image .hero__inner {
  z-index: 2;
  width: 100%;
  padding-block: 7rem;
}
.hero--image h1 {
  margin-top: 0;
  text-shadow: 0 2px 20px rgb(2 6 23 / 0.85), 0 1px 3px rgb(2 6 23 / 0.7);
}

@media (max-width: 48rem) {
  /* Height from the width, not from the height of the window — this fixes the
     ratio of the box and thus the crop. With `cover` the visible part of the
     master is box ratio ÷ 2.24 of its width: at 56svh the box was around 0.82:1
     on a phone and showed 37 % — the pure landscape in the middle. 78vw gives
     1.28:1 and thus about 57 %, enough for the man and both screens.

     The min() caps it on a phone held sideways, where 78vw would be taller than
     the whole window. */
  .hero--image {
    min-height: 56vh;
    min-height: min(78vw, 60svh);
    /* Text to the bottom edge: in the tall crop the man's head is in the upper
       half, and the heading would sit right on his face. Below it lies the desk
       and the darkest part of the veil. */
    align-items: flex-end;
  }
  .hero--image .hero__inner { padding-block: 2.5rem; }
}

/* --------------------------------------------------------------------------
   Geteilter Kopfbereich der Unterseiten — Bild links, Text rechts
   --------------------------------------------------------------------------
   Full-bleed and unframed like the start page hero, except the photo fills the
   left half instead of the whole width. The text sits beside it rather than on
   top: it covers no part of the subject, and the image needs no empty margin
   for type. The difference from the start page is therefore structural, not
   merely a matter of height.

   The height comes from clamp() and not from aspect-ratio: aspect-ratio
   combined with max-height transfers into an implied max-width and makes the
   section narrower than the window on wide screens (the cause of the blank
   strip on the right in the earlier version).

   Below 56rem the grid stacks: image on top across the full width, text below
   it in the normal page grid.                                                */

.hero-split {
  background: var(--bg);
}

.hero-split__inner {
  display: grid;
}

@media (min-width: 56rem) {
  .hero-split__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
    min-height: clamp(22rem, 24vw, 30rem);
  }
}

/* When stacked, a capped height drives the image rather than aspect-ratio:
   otherwise the band would be almost 450 px tall just before the 56rem
   breakpoint and push the text out of view. clamp() holds it between 10rem and
   17rem. */
.hero-split__media {
  position: relative;
  overflow: hidden;
  height: clamp(10rem, 40vw, 17rem);
}
@media (min-width: 56rem) {
  /* Side by side, the row height drives the image height. */
  .hero-split__media { height: auto; }
}

.hero-split__media picture { display: contents; }

/* object-position bestimmt, welcher Ausschnitt der Vorlage zu sehen ist.

   Senkrecht (32 %): Wo die Box breiter als die Vorlage ist, fällt Höhe weg.
   Mittig ginge die Hälfte davon oben ab — genau dort, wo bei Personen die
   Köpfe sitzen. 32 % verschiebt den Verlust nach unten in den Vordergrund.

   Waagerecht (Vorgabe 50 %): Die Box ist je nach Fenster 1,3:1 bis 2,7:1 und
   zeigt entsprechend nur 45 % bis 93 % der Bildbreite. Sitzt das Wesentliche
   nicht mittig, verschiebt eine Variante am <section> das Fenster —
   0 % = linker Rand, 100 % = rechter Rand der Vorlage.                       */
.hero-split__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--focus-x, 50%) var(--focus-y, 32%);
  filter: var(--img-boost);
}

/* Hauptmotiv rechts der Bildmitte (Beratung: die Rednerin bei 65–77 % der
   Breite). Kritisch ist nicht der breite, sondern der schmale Fall: knapp
   oberhalb von 56rem ist die Bildhälfte nur rund 450 px breit, die Textspalte
   daneben aber etwa 500 px hoch — die Box wird hochkant und zeigt dann keine
   30 % der Bildbreite mehr. Mittig läge dieses Fenster auf 35–65 % und damit
   neben dem Motiv. 75 % hält die Rednerin über den gesamten Bereich im Bild,
   vom hochkanten Ausschnitt bis 2560 px. Gegenstück für ein Motiv links wäre
   entsprechend `--focus-x: 25%`. */
.hero-split--focus-right .hero-split__media img { --focus-x: 75%; }

/* Waagerecht gespiegelt. Auf der Beratungsseite blickt die Rednerin in der
   Vorlage nach links, also aus dem Bild heraus und vom Text weg; gespiegelt
   wendet sie sich ihm zu. Der Ausschnitt wird vor der Spiegelung bestimmt,
   --focus-x oben bleibt deshalb unverändert gültig. */
.hero-split--mirror .hero-split__media img { transform: scaleX(-1); }


/* Dieselbe Abdunkelung wie in den Karten, damit ein und dasselbe Foto auf
   Startseite und Unterseite gleich wirkt. */
.hero-split__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgb(2 6 23 / var(--veil-top)),
    rgb(2 6 23 / var(--veil-bottom))
  );
}

/* Der Textteil trägt das Seitenraster selbst, weil der Abschnitt randlos ist
   und deshalb kein .wrap um ihn liegen kann. overflow:hidden hält den blauen
   Schein in seiner Hälfte, damit er nicht über das Foto läuft. */
.hero-split__body {
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: 3rem;
  padding-inline: var(--gutter);
}
@media (min-width: 40rem) { .hero-split__body { padding-inline: 1.5rem; } }
@media (min-width: 56rem) {
  .hero-split__body { padding-inline: clamp(2rem, 4vw, 4.5rem); }
}

/* Der Schein liegt absolut im Hintergrund; der Text braucht deshalb eine
   eigene Ebene, sonst zeichnete ihn das positionierte Element zu. */
.hero-split__text { position: relative; text-align: center; }

.badge {
  display: inline-block;
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--accent-edge);
  border-radius: 9999px;
  background: rgb(59 130 246 / 0.10);
  color: var(--accent-soft);
  font-size: 0.875rem;
  font-weight: 500;
}

.hero-split h1 {
  margin: 1.25rem 0 0;
  font-size: clamp(2rem, 3.4vw, 3rem);
}
.hero-split h1 .accent { color: var(--accent-soft); }

.hero-split__lead {
  max-width: 34rem;
  margin: 1.25rem auto 0;
  font-size: 1.125rem;
  color: var(--muted);
  text-wrap: pretty;
}

.hero-split .hero__actions { margin-top: 2rem; }


/* Die Begriffe als zweite, akzentuierte Zeile der Überschrift */
.hero__terms {
  display: block;
  margin-top: 0.75rem;
  /* eine Stufe heller als --accent-soft: hält auch über einem hellen Foto */
  color: #93c5fd;
  font-size: clamp(1.5rem, 4vw, 2.75rem);
  line-height: 1.25;
  text-wrap: balance;
}
/* Die Trenner stehen im Markup zwischen echten Leerzeichen — nur so kann die
   Zeile auf schmalen Displays überhaupt umbrechen. */
.hero__terms .sep {
  color: var(--body);
  font-weight: 400;
  padding-inline: 0.15em;
}


/* --------------------------------------------------------------------------
   Cards & grids
   -------------------------------------------------------------------------- */

/* 1 → 2 → 3 columns, capped at three like the liveprices page. A wider
   auto-fit would break 6- and 9-item grids into ragged 4+2 / 4+4+1 rows. */
.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
}
@media (min-width: 40rem) { .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* Dreier-Reihen (Produkte, Anwendungsfelder) springen direkt von 3 auf 1
   Spalte. Die 2+1-Zwischenstufe lässt bei genau drei Karten eine Lücke.
   Einspaltig wird die Karte auf --card-col begrenzt und zentriert, damit sie
   auf Tablets nicht über die volle Breite läuft. */
.grid--wide { gap: 1.5rem; }

@media (max-width: 63.999rem) {
  .grid--wide {
    grid-template-columns: minmax(0, var(--card-col));
    justify-content: center;
  }
  /* Der Claim nimmt dieselbe Breite an wie die Karten darunter — sonst steht
     der Text deutlich breiter als das Raster und die Sektion wirkt schief. */
  .section--center .section__lead { max-width: var(--card-col); }
}
@media (min-width: 64rem) {
  .grid--wide { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Icon tile and copy sit centred in the card (Vorteile on the sales app page).
   align-items is what moves the tile — it is the cross axis of the card's
   column flex box. */
.grid--center .card {
  align-items: center;
  text-align: center;
}

.card {
  display: flex;
  flex-direction: column;
  padding: 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  /* Auf fast schwarzem Grund trägt ein zarter Schatten nicht — daher reines
     Schwarz, hohe Deckkraft und ein großer, weicher Radius. */
  box-shadow:
    0 4px 6px -1px rgb(0 0 0 / 0.65),
    0 18px 36px -8px rgb(0 0 0 / 0.75);
  transition: background-color 0.18s ease, border-color 0.18s ease,
              box-shadow 0.18s ease, transform 0.18s ease;
}

/* :focus-within, damit sich die Karte auch beim Tabben zum Link hervorhebt */
.card:hover,
.card:focus-within {
  background: var(--card-hover);
  border-color: var(--line-hover);
  box-shadow:
    0 8px 12px -2px rgb(0 0 0 / 0.7),
    0 32px 64px -12px rgb(0 0 0 / 0.9);
}

/* Karten auf der dunkleren Sektion brauchen ihre eigene Aufhellung —
   --card-hover wäre dort ein zu großer Sprung. */
.section--alt .card:hover,
.section--alt .card:focus-within { background: var(--card-alt-hover); }

/* Anheben nur bei Karten, die tatsächlich irgendwohin führen; sonst
   verspricht die Bewegung eine Klickbarkeit, die es nicht gibt. */
.card:has(.card__link):hover,
.card:has(.card__link):focus-within {
  transform: translateY(-3px);
  border-color: var(--accent-edge);
}

.card h3 {
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 0.25rem;
}
.card p {
  font-size: 0.9375rem;
  color: var(--muted);
}
.card__eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent-soft);
  margin-bottom: 0.5rem;
}
.card__link {
  margin-top: 1.25rem;
  font-size: 0.9375rem;
  font-weight: 600;
}
.card > .card__link { margin-top: auto; padding-top: 1.25rem; }

.card__media {
  position: relative;
  margin: -1.5rem -1.5rem 1.25rem;
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden;
}
.card__media picture { display: contents; }
.card__media img { width: 100%; filter: var(--img-boost); }

/* Wie beim gespiegelten Kopfbild der Beratungsseite: die Rednerin blickt in
   der Vorlage nach links aus dem Bild heraus. Gespiegelt zeigt sie ins Bild
   hinein — und beide Auftritte desselben Fotos stimmen überein. */
.card__media--mirror img { transform: scaleX(-1); }

/* Dieselbe Abdunkelung wie beim Hero: die Bilddateien sind unverändert, nur
   diese Ebene liegt darüber. Nach unten hin dunkler, damit das Foto in den
   Kartenhintergrund übergeht statt hart abzubrechen. */
.card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to bottom, rgb(2 6 23 / var(--veil-top)), rgb(2 6 23 / var(--veil-bottom)));
  transition: opacity 0.18s ease;
}

/* Beim Überfahren wird das Motiv etwas freier — passt zum Aufhellen der
   Karte selbst. */
.card:hover .card__media::after,
.card:focus-within .card__media::after { opacity: 0.55; }

/* Icon tile */
.icon-tile {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  margin-bottom: 0.75rem;
  border-radius: var(--radius-sm);
  background: var(--accent-tint);
  color: var(--accent-soft);
}
.icon-tile svg { width: 1.5rem; height: 1.5rem; }

.icon-tile--sm {
  width: 2rem;
  height: 2rem;
  margin-bottom: 0;
  background: var(--line);
}
.icon-tile--sm svg { width: 1.25rem; height: 1.25rem; }

.card__head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 0.5rem;
}
.card__head h3 { margin-bottom: 0; }

/* --------------------------------------------------------------------------
   Check list
   -------------------------------------------------------------------------- */

.checklist {
  list-style: none;
  margin: 0;
  padding: 0;
}
.checklist li {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  color: var(--body);
}
.checklist li + li { margin-top: 1rem; }
/* Nummerierte Aufzählung im Fließtext („Das Unternehmen“). Aufbau wie die
   Checkliste, aber mit Ziffern statt Haken: die beiden Säulen beschreiben den
   Ist-Zustand der Branche, sind also keine Vorteilsliste — ein Haken davor
   würde das Gegenteil behaupten. Der Abstand nach oben muss hier stehen: die
   Kurzform `margin: 0` hätte die 1rem aus `.stack > * + *` überschrieben (gleiche
   Spezifität, spätere Regel) und die Liste klebte am Absatz davor. */
.numbered {
  margin: 1rem 0 0;
  padding: 0;
  list-style: none;
  counter-reset: saeule;
}
.numbered li {
  position: relative;
  padding-left: 2.5rem;
  counter-increment: saeule;
}
.numbered li + li { margin-top: 0.75rem; }
.numbered li::before {
  content: counter(saeule);
  position: absolute;
  left: 0;
  top: 0.2rem;
  display: grid;
  place-items: center;
  width: 1.625rem;
  height: 1.625rem;
  border-radius: 9999px;
  background: var(--accent-tint);
  color: var(--accent-soft);
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1;
}
.checklist svg {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.2rem;
  color: var(--accent-soft);
}

/* --------------------------------------------------------------------------
   Inhaltsabschnitt mit randlosem Bild auf einer Hälfte („Das Unternehmen“)
   --------------------------------------------------------------------------
   Aufbau wie der Kopfbereich der Unterseiten, mit zwei Unterschieden, weil es
   kein Seitenkopf ist: der Text steht linksbündig statt zentriert, und das
   Bild liegt rechts statt links.

   Die Außenkante des Textes läuft bündig mit dem übrigen Seitenraster. Ein
   fester Innenabstand genügt dafür nicht: Sobald das Fenster breiter als
   --wrap ist, rückt der Inhalt der anderen Abschnitte nach innen, ein
   randloser Abschnitt aber nicht. max() nimmt den jeweils größeren Wert und
   hält beide Kanten auf einer Linie.                                         */

.feature { background: var(--bg); }

.feature__inner { display: grid; }

@media (min-width: 64rem) {
  .feature__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
  }
}

.feature__body {
  padding-block: 5rem;
  padding-inline: var(--gutter);
}
@media (min-width: 40rem) { .feature__body { padding-inline: 1.5rem; } }
@media (min-width: 64rem) {
  .feature__body {
    padding-inline-start: max(2rem, calc((100vw - var(--wrap)) / 2 + 2rem));
    padding-inline-end: 3rem;
  }
}

/* Gestapelt gibt das Bild sein eigenes Verhältnis vor — 3:2 wie die Vorlage,
   also unbeschnitten. Der Deckel verhindert, dass es auf Tablets die halbe
   Seite einnimmt. Kein aspect-ratio mit max-height: die Kombination überträgt
   sich zu einer max-width und rückt den Abschnitt vom rechten Rand ab.
   Nebeneinander bestimmt die Höhe der Textspalte die Bildhöhe. */
.feature__media {
  position: relative;
  overflow: hidden;
  height: min(66.6vw, 26rem);
}
@media (min-width: 64rem) { .feature__media { height: auto; } }

.feature__media picture { display: contents; }
.feature__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: var(--img-boost);
}

/* Gleiche Abdunkelung wie Kopfbilder und Karten. */
.feature__media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    rgb(2 6 23 / var(--veil-top)),
    rgb(2 6 23 / var(--veil-bottom))
  );
}

/* --------------------------------------------------------------------------
   Screenshot slideshow

   A scroll-snap track, no JavaScript. Swiping, trackpad scrolling and — once
   the track has focus — the arrow keys all work natively; the browser does the
   snapping. With CSS switched off it degrades to a plain list of images.

   One layout at every width: the track keeps a free margin of --pad on both
   sides, and the arrows sit in it — next to the picture, never on top of it and
   never gone. Only the sizes scale. Letting the neighbouring slide peek in
   would be the alternative, but the two cannot be combined: the arrows of a
   slide stick out beyond its own edge, so the strip in which a neighbour would
   peek in is exactly the strip in which that neighbour's arrows lie.

   Why a percentage flex-basis works out exactly: `flex: 0 0 100%` refers to the
   *content box* of the track, i.e. its width minus the two paddings. A slide is
   therefore automatically as wide as the space between the two margins, with no
   arithmetic and nothing to keep in sync.

   The dots below are plain anchors into the track; which slide is showing is
   marked by .shots__dots::after, driven by the scroll position. One limitation
   remains, accepted: a click on a dot or an arrow leaves the fragment in the
   URL, and it scrolls the page vertically as well — the scroll-margin-top of
   the slides catches the latter.
   -------------------------------------------------------------------------- */

/* Only the first two values are freely chosen; the rest follows from them.

   --pad is the space a button needs next to the picture. --gap has to be large
   enough for the buttons of the *neighbouring* slide to land outside the
   visible area: the neighbour starts --gap minus --pad behind the right edge,
   and its left button reaches --nav-room further to the left. Hence
   gap ≥ pad + nav-room. If --gap gets smaller, a foreign button pushes into the
   picture — the 0.5rem in both is the safety margin against rounding.

   The buttons shrink on small screens, otherwise they would eat too much of the
   width; below about 640 px the lower bound of the clamp applies, so they stay
   large enough to tap comfortably. */
.shots {
  --nav-size: clamp(2.5rem, 7vw, 3rem);     /* diameter of the buttons */
  --nav-gap:  clamp(0.375rem, 1.5vw, 0.75rem);  /* picture to button */
  --nav-room: calc(var(--nav-size) + var(--nav-gap));
  --pad: calc(var(--nav-room) + 0.5rem);
  --gap: calc(var(--pad) + var(--nav-room) + 0.5rem);
  /* Dots: --dot-hit is the tap target, --dot-size the visible dot. The marker
     travels in steps of --dot-pitch, so the three have to fit together. */
  --dot-size:  0.625rem;
  --dot-hit:   1.5rem;
  --dot-gap:   0.25rem;
  --dot-pitch: calc(var(--dot-hit) + var(--dot-gap));
  /* Number of slides — the travel of the marker depends on it. Adjust when a
     screenshot is added. */
  --shots-count: 3;
  max-width: 64rem;
  margin-inline: auto;
}

/* The track follows text inside the same section instead of opening one of its
   own. Less than the 5rem of a section boundary, more than a paragraph gap: far
   enough to read as its own block, close enough to still belong to the text
   above. */
.shots--after-text { margin-block-start: 3rem; }

.shots__track {
  display: flex;
  gap: var(--gap);
  margin: 0;
  /* Block padding leaves room for the focus ring of the track. */
  padding: 0.25rem var(--pad);
  list-style: none;
  overflow-x: auto;
  /* Do not pass the scroll on to the page once the end is reached — otherwise
     a horizontal swipe triggers the back gesture of the browser. */
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
  scrollbar-color: var(--line-hover) transparent;
}

.shots__track:focus-visible {
  outline: 2px solid var(--accent-soft);
  outline-offset: 2px;
  border-radius: var(--radius);
}

.shots__item {
  flex: 0 0 100%;
  min-width: 0;
  scroll-snap-align: center;
  /* Only relevant when a dot or an arrow is clicked: the jump to the fragment
     scrolls the page vertically as well. The scroll-padding-top of the html
     element already keeps the target clear of the sticky header; this adds the
     bit of air that keeps the slide from sticking to its lower edge. A larger
     value would push the caption and the dots below the fold. Not relevant for
     swiping or scrolling — those do not use scroll-margin. */
  scroll-margin-top: 1rem;
}

.shot { margin: 0; }

/* Reference for the arrows: the picture, not the whole figure — otherwise they
   would be centred over the caption as well and sit too low. */
.shot__frame { position: relative; }

.shot picture { display: contents; }

/* No --img-boost here, unlike every other image on the site: the screenshots
   are interface, not photography. More contrast would only harden the text
   edges and shift the colours of the app away from the original. */
.shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
}

.shot__caption {
  margin-top: 0.875rem;
  color: var(--muted);
  font-size: 0.9375rem;
  line-height: 1.5;
  text-align: center;
}

/* Arrows.

   Without JavaScript no button can know which slide is currently showing, so
   there is no single pair of arrows for the track. Instead every slide carries
   its own — the first one only a "next", the last one only a "back". Whichever
   slide is showing, its own arrows are the ones beside it. The arrows of the
   other slides lie outside the visible area; --gap ensures that, see above. */
.shots__nav {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: var(--nav-size);
  height: var(--nav-size);
  /* --line-hover rather than --line: the button stands free on the page
     background and needs a bit more definition than a card edge. */
  border: 1px solid var(--line-hover);
  border-radius: 9999px;
  background: var(--card);
  color: var(--body);
  transition: background-color 0.15s ease, border-color 0.15s ease,
              color 0.15s ease;
}

/* Beside the picture, not on it. */
.shots__nav--prev { right: 100%; margin-right: var(--nav-gap); }
.shots__nav--next { left:  100%; margin-left:  var(--nav-gap); }

.shots__nav svg { width: 45%; height: 45%; }

.shots__nav:hover {
  border-color: var(--accent-edge);
  background: var(--accent-tint);
  color: var(--accent-soft);
}

/* width: max-content instead of a centred flex row, so that the box is exactly
   as wide as the dots. Only then is `left: 0` the left edge of the first dot,
   which the marker below relies on. */
.shots__dots {
  position: relative;
  display: flex;
  gap: var(--dot-gap);
  width: max-content;
  margin: 1.25rem auto 0;
  padding: 0;
  list-style: none;
}

/* The link is --dot-hit so the tap target is big enough; the visible dot inside
   is much smaller. */
.shots__dots a {
  display: grid;
  place-items: center;
  width: var(--dot-hit);
  height: var(--dot-hit);
  border-radius: 9999px;
  transition: background-color 0.15s ease;
}

.shots__dots a::before {
  content: "";
  width: var(--dot-size);
  height: var(--dot-size);
  border-radius: 9999px;
  background: var(--line-hover);
  transition: background-color 0.15s ease, scale 0.15s ease;
}

/* On hover the dot turns light blue *and* grows — the growing is what makes the
   effect uniform. On the dot currently showing, the marker lies on top of it,
   so a mere change of colour would be invisible there and only that one dot
   would appear to have no hover. Scaled up it is larger than the marker, and
   since both are --accent-soft the marker disappears into it: hovered dots look
   exactly the same, whether they are the current one or not.

   The tinted area of the link additionally marks the tap target. */
.shots__dots a:hover,
.shots__dots a:focus-visible { background: var(--accent-tint); }

.shots__dots a:hover::before,
.shots__dots a:focus-visible::before {
  background: var(--accent-soft);
  /* > --dot-size, so that the marker (--dot-size) is covered. */
  scale: 1.4;
}

/* Which slide is showing.

   The honest answer is that CSS can only read the scroll position in one way:
   through a scroll timeline. So the marker is a single coloured dot lying on
   top of the grey ones, moved by the scroll position of the track. Not per
   slide with its own switching range — one animation across the whole track,
   linear. At progress 0.5 it is exactly on the middle dot, and it follows a
   swipe continuously instead of jumping. It also stays correct for a fourth
   screenshot; only --shots-count has to match. */
.shots__dots::after {
  content: "";
  position: absolute;
  top: 50%;
  /* Centred on the first dot: half the difference between hit area and dot. */
  left: calc((var(--dot-hit) - var(--dot-size)) / 2);
  width: var(--dot-size);
  height: var(--dot-size);
  border-radius: 9999px;
  background: var(--accent-soft);
  translate: 0 -50%;
  /* Essential, not cosmetic: the marker lies on top of the dot currently
     showing and would otherwise swallow the mouse in its middle. That dot would
     then react to hover only on its outer ring, while the other two react
     everywhere — exactly the inconsistency this is about. Pseudo-elements are
     hit-testable by default, and :hover only reaches the ancestors of what is
     under the cursor, not the link next to it. */
  pointer-events: none;
  transition: translate 0.2s ease;
}

/* Where scroll timelines exist, the scroll position of the track drives the
   marker — including a swipe. The animation overrides the translate values of
   the fallback below, because animations rank above normal declarations in the
   cascade; hence no @supports not is needed there. */
@supports (animation-timeline: scroll()) {
  .shots { timeline-scope: --shots-scroll; }
  .shots__track { scroll-timeline: --shots-scroll inline; }
  .shots__dots::after {
    animation: shots-marker linear both;
    animation-timeline: --shots-scroll;
  }
}

@keyframes shots-marker {
  from { translate: 0 -50%; }
  to   { translate: calc((var(--shots-count) - 1) * var(--dot-pitch)) -50%; }
}

/* Fallback without scroll timelines: the same marker, only moved by the
   fragment instead of by the scroll position. Every dot and every arrow sets
   one, so this covers all clicks and taps — only free scrolling is not tracked.
   Without a fragment it stays on the first dot. Deliberately the same element
   as above, so that the dots themselves stay untouched and hover behaves
   identically in both cases. */
.shots:has(.shots__item:nth-child(2):target) .shots__dots::after {
  translate: var(--dot-pitch) -50%;
}
.shots:has(.shots__item:nth-child(3):target) .shots__dots::after {
  translate: calc(2 * var(--dot-pitch)) -50%;
}

/* --------------------------------------------------------------------------
   Contact block
   -------------------------------------------------------------------------- */

.contact { text-align: center; }
.contact p { color: var(--muted); }

.contact__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.75rem;
  margin-top: 2rem;
}
.contact__links a {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.875rem 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card);
  color: var(--fg);
  font-weight: 600;
}
.contact__links a:hover { border-color: var(--accent-edge); color: var(--accent-soft); }
.contact__links svg { width: 1.25rem; height: 1.25rem; color: var(--accent-soft); }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */

.site-footer {
  border-top: 1px solid var(--line);
  background: var(--bg);
  padding-block: 3.5rem 2rem;
  font-size: 0.9375rem;
  color: var(--muted);
}

.site-footer__cols {
  display: grid;
  gap: 2rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
.site-footer img.brand-mark { height: var(--logo-h-footer); width: auto; }
.site-footer h2 {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--body);
  margin-bottom: 0.75rem;
}
.site-footer address { font-style: normal; }
.site-footer ul { list-style: none; margin: 0; padding: 0; }
.site-footer li + li { margin-top: 0.375rem; }
.site-footer a { color: var(--muted); }
.site-footer a:hover { color: var(--fg); }

.site-footer__bottom {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  justify-content: space-between;
  font-size: 0.875rem;
}

/* --------------------------------------------------------------------------
   Legal / long-form pages
   -------------------------------------------------------------------------- */

.legal h2 {
  font-size: 1.125rem;
  margin-top: 2.5rem;
  margin-bottom: 0.75rem;
  color: var(--fg);
}
.legal p { color: var(--muted); }
.legal p + p { margin-top: 1rem; }
.legal dl { margin: 0; color: var(--muted); }
.legal dt {
  font-weight: 600;
  color: var(--body);
  margin-top: 1rem;
}
.legal dd { margin: 0; }

/* --------------------------------------------------------------------------
   Cookie-Seite
   -------------------------------------------------------------------------- */

.cookie-card {
  padding: 3rem 2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card-alt);
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.65), 0 18px 36px -8px rgb(0 0 0 / 0.75);
  text-align: center;
}
@media (max-width: 30rem) { .cookie-card { padding: 2rem 1.25rem; } }

.cookie-card__mark {
  width: 4rem;
  height: 4rem;
  margin: 0 auto 1.75rem;
  color: var(--accent-soft);
}

.cookie-card p { color: var(--muted); }
.cookie-card p + p { margin-top: 1rem; }

.cookie-card__lead {
  font-size: clamp(1.125rem, 2.5vw, 1.375rem);
  font-weight: 600;
  line-height: 1.4;
  color: var(--fg) !important;
  text-wrap: pretty;
}

.cookie-card__facts {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  margin: 1.75rem 0;
  padding: 0;
  list-style: none;
}
.cookie-card__facts li {
  padding: 0.375rem 1rem;
  border: 1px solid var(--accent-edge);
  border-radius: 9999px;
  background: rgb(59 130 246 / 0.10);
  color: var(--accent-soft);
  font-size: 0.9375rem;
  font-weight: 600;
}

.cookie-card__signature {
  margin-top: 1.75rem !important;
  color: var(--body) !important;
  font-style: italic;
}

.cookie-card .contact__links { margin-top: 2rem; }

.cookie-card__footnote {
  max-width: 40rem;
  margin: 1.5rem auto 0;
  text-align: center;
  font-size: 0.875rem;
  color: var(--muted);
  text-wrap: pretty;
}
.cookie-card__footnote p + p { margin-top: 0.625rem; }


/* --------------------------------------------------------------------------
   Motion preferences
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  /* Exception: the marker of the slideshow is not animation in the sense of
     movement for its own sake — it is driven by the scroll position and only
     shows which slide is showing. A forced duration would freeze it at one end
     and thus display something wrong. */
  .shots__dots::after { animation-duration: auto !important; }
  /* Farbe und Schatten bleiben, nur die Bewegung entfällt. */
  .card:has(.card__link):hover,
  .card:has(.card__link):focus-within { transform: none; }
}
