/* =========================================================
   safeT.watch — design tokens
   ========================================================= */
:root {
  --nav-h: 80px; /* fallback; JS overwrites with the nav's real rendered height */

  --paper: #F0F2F3;
  --paper-dim: #E4E7E9;
  --ink: #12141A;
  --ink-soft: #4B4E58;
  --ink-faint: #6C707B; /* darkened from #8A8D96 — that value read 3.02:1 on --paper, below WCAG AA's 4.5:1 for normal text */
  --line: rgba(18, 20, 26, 0.10);

  /* Always-dark chrome — console, footer. Independent of the light/dark toggle:
     the Daylight-First Rule reserves darkness for real product surfaces. */
  --console: #0E1016;
  --console-line: rgba(255, 255, 255, 0.08);
  --console-text: #E7E6E0;
  --console-text-dim: #9497A3;

  --accent: #EB5C38;
  --accent-strong: #BC4A2D;
  --accent-soft: rgba(235, 92, 56, 0.10);
  /* Text/icon/line-art tint for the brand accent sitting directly on --paper/--ink.
     Plain --accent only reaches 3.12:1 on --paper (fails WCAG AA for normal
     text), so light mode uses --accent-strong instead; dark mode brightens to
     FF7A52, which is legible on the dark page surface. .console re-pins this
     locally since its background stays dark regardless of theme. */
  --accent-ink: var(--accent-strong);

  /* Success feedback (form submissions), same light/dark split as --accent-ink. */
  --success-ink: #1F7A4D;

  /* Hero hex-field gradient — its own quiet blue-grey family, deliberately
     separate from --accent: decorative background, not a signal color. */
  --hexfield-grad-a: #8892A6;
  --hexfield-grad-b: #4E5A72;

  --font-display: "Sora", ui-sans-serif, system-ui, sans-serif;
  --font-body: "Archivo", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;

  /* Type scale — every literal font-size in this file resolves to one of these steps */
  --text-2xs: 11px;
  --text-xs: 12px;
  --text-sm: 13px;
  --text-sm-alt: 14px;
  --text-body-sm: 14.5px;
  --text-body: 16px;
  --text-md: 15px;
  --text-lg: 17px;
  --text-xl: 18px;
  --text-title-sm: 20px;
  --text-title: 24px;
  --text-headline: clamp(28px, 4vw, 44px);
  --text-headline-lg: clamp(30px, 4.5vw, 50px);
  --text-display: clamp(42px, 6vw, 76px);

  --container: 1280px;
  --edge: clamp(24px, 5vw, 64px);
  --radius: 18px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Dark mode: system preference by default, explicit toggle always wins.
   Only the "paper" side of the system flips — console/accent/footer chrome
   stays fixed, per the Daylight-First Rule. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --paper: #14161B;
    --paper-dim: #1B1E25;
    --ink: #F3F1EA;
    --ink-soft: #B9BBC4;
    --ink-faint: #83868F;
    --line: rgba(255, 255, 255, 0.12);
    --accent-ink: #FF7A52;
    --success-ink: #7BE0A8;
    --hexfield-grad-a: #94A3B8;
    --hexfield-grad-b: #64748B;
  }
}
:root[data-theme="dark"] {
  --paper: #14161B;
  --paper-dim: #1B1E25;
  --ink: #F3F1EA;
  --ink-soft: #B9BBC4;
  --ink-faint: #83868F;
  --line: rgba(255, 255, 255, 0.12);
  --accent-ink: #FF7A52;
  --success-ink: #7BE0A8;
  --hexfield-grad-a: #94A3B8;
  --hexfield-grad-b: #64748B;
}

* { box-sizing: border-box; }
html { scroll-behavior: auto; } /* Lenis owns smooth scrolling; native smooth would double up */

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background-color 0.3s var(--ease), color 0.3s var(--ease);
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.02em;
  margin: 0;
}

p { margin: 0; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; }

/* faint film-grain overlay to keep flat colour fields from feeling sterile */
.grain {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 2000;
  opacity: 0.035;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* =========================================================
   Reveal-on-scroll
   ========================================================= */
[data-reveal] {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.9s var(--ease), transform 0.9s var(--ease);
}
[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* =========================================================
   Nav
   ========================================================= */
main#top,
section[id],
#kontakt,
#mitmachen-formular {
  scroll-margin-top: calc(var(--nav-h) + 16px);
}

.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  padding: 18px var(--edge) 0;
}
.nav__inner {
  position: relative; /* anchor for the collapsed nav panel */
  max-width: var(--container);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--paper) 60%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  -webkit-backdrop-filter: blur(14px) saturate(1.4);
  border: 1px solid transparent;
  transition: background 0.4s var(--ease), border-color 0.4s var(--ease), box-shadow 0.4s var(--ease);
}
.nav.is-scrolled .nav__inner {
  background: color-mix(in srgb, var(--paper) 85%, transparent);
  border-color: var(--line);
  box-shadow: 0 8px 30px rgba(18, 20, 26, 0.06);
}
.nav__logo {
  display: flex;
  align-items: center;
}
.nav__logo img { height: 38px; width: auto; }

/* =========================================================
   Theme toggle + logo light/dark swap
   ========================================================= */
.logo-dark-mode { display: none; }
:root[data-theme="dark"] .logo-light-mode { display: none; }
:root[data-theme="dark"] .logo-dark-mode { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .logo-light-mode { display: none; }
  :root:not([data-theme="light"]) .logo-dark-mode { display: block; }
}

.nav__meta {
  display: flex;
  align-items: center;
  gap: 14px;
}
.lang-switch {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
}
.lang-switch__sep { color: var(--line); }
.lang-switch__option {
  background: none;
  border: none;
  padding: 0;
  color: var(--ink-faint);
  cursor: pointer;
}
.lang-switch__option:disabled { cursor: default; }
.lang-switch__option.is-active { color: var(--ink); font-weight: 600; }

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease), transform 0.2s var(--ease);
}
.theme-toggle:hover { border-color: var(--ink); color: var(--ink); transform: translateY(-1px); }
.theme-toggle__icon--moon { display: none; }
:root[data-theme="dark"] .theme-toggle__icon--sun { display: none; }
:root[data-theme="dark"] .theme-toggle__icon--moon { display: block; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle__icon--sun { display: none; }
  :root:not([data-theme="light"]) .theme-toggle__icon--moon { display: block; }
}

@media (max-width: 720px) {
  .theme-toggle { width: 32px; height: 32px; }
}
.nav__links {
  display: flex;
  gap: 32px;
  font-size: var(--text-sm-alt);
  color: var(--ink-soft);
}
.nav__links a { transition: color 0.2s; }
.nav__links a:hover { color: var(--ink); }
.nav__cta {
  font-size: var(--text-sm);
  font-weight: 600;
  padding: 9px 18px;
  border-radius: 999px;
  background: var(--ink);
  color: var(--paper);
  transition: background 0.2s var(--ease), transform 0.2s var(--ease);
}
.nav__cta:hover { background: var(--accent); transform: translateY(-1px); }

/* Burger: hidden until the links stop fitting beside the logo and CTA.
   Previously the links were simply display:none below 720px, which left
   small screens with no way to reach any section at all. */
.nav__burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.nav__burger:hover { border-color: var(--ink); color: var(--ink); }
.nav__burger-box {
  position: relative;
  width: 16px;
  height: 12px;
}
.nav__burger-line {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  border-radius: 999px;
  background: currentColor;
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}
.nav__burger-line:nth-child(1) { top: 0; }
.nav__burger-line:nth-child(2) { top: 5.25px; }
.nav__burger-line:nth-child(3) { top: 10.5px; }
.nav.is-menu-open .nav__burger-line:nth-child(1) { transform: translateY(5.25px) rotate(45deg); }
.nav.is-menu-open .nav__burger-line:nth-child(2) { opacity: 0; }
.nav.is-menu-open .nav__burger-line:nth-child(3) { transform: translateY(-5.25px) rotate(-45deg); }

/* 1070px is where four links, the logo and the CTA stop coexisting in the
   pill. Below it the same list becomes a panel under the pill — the markup
   is reused rather than duplicated, so there is only one set of links. */
@media (max-width: 1070px) {
  .nav__burger { display: inline-flex; }
  .nav__logo img { height: 28px; }
  .nav__links {
    position: absolute;
    top: calc(100% + 12px);
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 2px;
    padding: 12px;
    border-radius: var(--radius);
    font-size: var(--text-lg);
    background: color-mix(in srgb, var(--paper) 94%, transparent);
    backdrop-filter: blur(14px) saturate(1.4);
    -webkit-backdrop-filter: blur(14px) saturate(1.4);
    border: 1px solid var(--line);
    box-shadow: 0 18px 40px rgba(18, 20, 26, 0.10);
    /* visibility (not display) so the panel can transition, and so its links
       leave the tab order while collapsed */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.28s var(--ease), transform 0.28s var(--ease), visibility 0.28s;
  }
  .nav__links a {
    padding: 11px 14px;
    border-radius: 10px;
  }
  .nav__links a:hover { background: var(--paper-dim); }
  .nav__links .nav__panel-cta:hover { background: var(--accent); }
  .nav.is-menu-open .nav__links {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }
}

/* The panel's own CTA. Only ever visible while the pill's CTA is hidden,
   so the two never announce the same action twice. */
.nav__panel-cta { display: none; }

@media (max-width: 560px) {
  .nav__cta { font-size: var(--text-xs); padding: 8px 13px; }
}

/* Below 500px the pill can no longer carry logo, theme toggle, CTA and
   burger at once — the CTA moves into the panel and leads it as a full
   width primary button. */
@media (max-width: 500px) {
  .nav__cta { display: none; }
  .nav__logo img { height: 24px; }
  .nav__links .nav__panel-cta {
    display: block;
    margin-top: 10px;
    padding: 13px 14px;
    border-radius: 999px;
    background: var(--ink);
    color: var(--paper);
    font-size: var(--text-md);
    font-weight: 600;
    text-align: center;
  }
}

/* =========================================================
   Buttons
   ========================================================= */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 26px;
  border-radius: 999px;
  font-size: var(--text-md);
  font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform 0.25s var(--ease), background 0.25s var(--ease), border-color 0.25s var(--ease), color 0.25s var(--ease);
}
.btn svg { transition: transform 0.25s var(--ease); }
.btn:hover svg { transform: translateX(3px); }
.btn:hover { transform: translateY(-2px); }

.btn--primary { background: var(--ink); color: var(--paper); }
.btn--primary:hover { background: var(--accent); }
.btn--primary.btn--light { background: #F6F4EE; color: var(--accent-strong); }
.btn--primary.btn--light:hover { background: #fff; }

.btn--ghost { background: transparent; color: var(--ink); border-color: var(--line); }
/* Size step for a section whose whole purpose is one action. */
.btn--lg { font-size: var(--text-lg); padding: 18px 34px; }
.btn--ghost:hover { border-color: var(--ink); }

/* =========================================================
   Hero
   ========================================================= */
.hero {
  position: relative;
  min-height: 100svh;
  padding: 160px var(--edge) 100px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: 60px;
  align-items: center;
  max-width: var(--container);
  margin: 0 auto;
}
.hero__bg {
  position: absolute;
  /* Full-bleed: spans the whole viewport width regardless of .hero's own
     max-width container, so the hex field never looks cropped at the
     content edge on wide screens. body has overflow-x:hidden already, so
     100vw here can't cause a horizontal scrollbar. */
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  transform: translateX(-50%);
  z-index: -1;
  overflow: hidden;
  /* Own compositing layer: keeps the hex-field animation smooth when the
     console tilts on hover instead of both repainting together. */
  will-change: transform;
}
.hero__hexfield {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__headline {
  font-size: var(--text-display);
  margin-bottom: 26px;
}
.hero__headline--logo {
  /* Grid-stack both theme variants in the same cell so a light/dark toggle
     can never reflow or shift the logo — only one is ever visible, but both
     always claim the same box. */
  display: grid;
}
.hero__headline--logo img {
  grid-area: 1 / 1;
  width: min(100%, 540px);
  height: auto;
  aspect-ratio: 595.11 / 342.71;
}

.hero__sub,
.btn--ghost {
  transition: color 220ms var(--ease), background-color 220ms var(--ease), border-color 220ms var(--ease);
}

@media (max-width: 920px) {
  .hero__headline--logo img { width: min(100%, 420px); }
}

.hero__sub {
  font-size: var(--text-xl);
  color: var(--ink-soft);
  max-width: 46ch;
  margin-bottom: 34px;
}

.hero__actions { display: flex; flex-direction: column; align-items: flex-start; gap: 16px; }
.hero__cta-row { display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }

/* A status pill above the buttons, not a caption squeezed beside or under
   them — its own row removes any ambiguity about where it sits. Faint tint
   rather than a solid fill, so it reads as a quiet status, not a third CTA. */
.hero__status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  color: var(--accent-ink);
  background: var(--accent-soft);
  padding: 6px 14px 6px 10px;
  border-radius: 999px;
}
.hero__status-dot {
  width: 5px;
  height: 5px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--accent-ink);
  animation: hero-status-pulse 2.6s ease-in-out infinite;
}
@keyframes hero-status-pulse {
  0%, 100% { box-shadow: 0 0 0 3px var(--accent-soft); }
  50% { box-shadow: 0 0 0 6px transparent; }
}

/* console mockup */
.hero__console { perspective: 1400px; }
.console {
  --accent-ink: #FF7A52; /* always-dark surface: stay bright regardless of page theme */
  box-shadow: 0 40px 80px -20px rgba(14, 16, 22, 0.45);
  transform: rotateY(-6deg) rotateX(2deg);
  transition: transform 0.6s var(--ease);
  border-radius: var(--radius); /* shadow needs the same radius to sit flush */
  /* Own compositing layer: the hover tilt below used to force a repaint of
     the whole hero on hover, visibly stalling the hex-field animation. */
  will-change: transform;
}
/* Clipping (overflow:hidden + border-radius) lives on its own, non-rotated
   element rather than the 3D-transformed .console: some browsers rasterize
   a rounded clip sloppily when it sits directly on a tilted layer, showing a
   thin colored fringe (like chromatic aberration) along the curve. */
.console__clip {
  background: var(--console);
  border-radius: var(--radius);
  overflow: hidden;
}
.console__mock { display: block; width: 100%; height: auto; }
.hero__console:hover .console { transform: rotateY(-2deg) rotateX(0deg); }

@media (max-width: 920px) {
  .hero { grid-template-columns: 1fr; padding-top: 130px; }
  .console { transform: none; }
}

/* =========================================================
   Problem → Lösung (ein gepinnter Übergang)
   ========================================================= */
/* Problem and solution are one section, not two: the four costs and the four
   answers occupy the same four places, so the page can show the second as a
   change of state rather than as a new list. The mark sits in the centre of
   both — shut and furrowed while the cycle turns, open once the spokes reach
   it. js/main.js drives --a (problem opacity), --b (solution opacity) and
   --open (eye) from the scroll position inside the pin. */
.morph { --a: 1; --b: 0; --open: 0; }
/* 220vh, not the 300vh this started at: at 300vh the crossfade window (see
   js/main.js) had to span a long stretch of travel to avoid leaving a dead
   "already solved but still pinned" tail — but that same width made the
   double-exposure of both states visible for far too long while actively
   scrolling through it, not just when scrolling happened to stop there.
   Shrinking the whole pin lets the crossfade stay short in both senses at
   once: brief in scroll-distance and without reopening that dead tail. */
.morph__pin { height: 220vh; position: relative; }
.morph__viewport {
  position: sticky;
  top: 0;
  height: 100vh;
  max-width: var(--container);
  margin: 0 auto;
  /* Top-aligned, not centered: centering left the section jumping to #problem
     landing on a screen-mid heading with dead space above it, unlike every
     other nav target, which starts right under the nav. */
  padding: calc(var(--nav-h) + 48px) var(--edge) 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 84px;
  overflow: hidden;
}

/* Both states share one cell, so the taller one sets the height and neither
   reflows while they cross over. */
.morph__head { display: grid; }
.morph__copy {
  grid-area: 1 / 1;
  max-width: 62ch;
}
.morph__copy h2 {
  font-size: var(--text-headline);
  max-width: 22ch;
  color: var(--ink);
  margin-bottom: 16px;
}
.morph__copy p {
  font-size: var(--text-lg);
  color: var(--ink-soft);
  max-width: 58ch;
}
.morph__copy--problem { opacity: var(--a); }
.morph__copy--solution { opacity: var(--b); }

/* Must not grow: with flex: 1 the stage swallowed the whole remaining
   viewport height and centred the diagram inside it, tearing a gap open
   between heading and cards. Head and stage now stay one block, which the
   viewport's justify-content centres as a whole. */
.morph__stage {
  position: relative;
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 100%;
}
.morph__layer {
  grid-area: 1 / 1;
  width: 100%;
  pointer-events: none;
}
.morph__layer--problem {
  opacity: var(--a);
  transform: scale(calc(0.965 + var(--a) * 0.035));
}
.morph__layer--solution {
  opacity: var(--b);
  transform: scale(calc(1.035 - var(--b) * 0.035));
}
.morph.is-problem .morph__layer--problem,
.morph.is-solution .morph__layer--solution { pointer-events: auto; }

.morph .hub { gap: 48px 40px; }

/* The mark belongs to neither layer: it is the one element that persists
   through the change, which is what makes the change read as one thing
   happening rather than two pictures swapping. */
.morph__mark {
  grid-area: 1 / 1;
  width: 160px;
  pointer-events: none;
  z-index: 1;
}

/* Unpin wherever the transition cannot be shown honestly: too narrow, too
   short, or motion turned down. Both states then stand as two static blocks,
   which is what the page did before they were merged. */
@media (max-width: 900px), (max-height: 700px), (prefers-reduced-motion: reduce) {
  /* The pinned base rule (.morph { --open: 0 }) otherwise survives into this
     static layout untouched — nothing else here resets custom properties,
     only opacity/transform — leaving the eye stuck shut on every screen this
     query matches, including reduced-motion, where the JS that would
     normally clear it never runs at all. */
  .morph { --open: 1; }
  .morph__pin { height: auto; }
  .morph__viewport {
    position: static;
    height: auto;
    display: grid;
    overflow: visible;
    padding: 110px var(--edge);
    gap: 0;
  }
  .morph__head,
  .morph__stage { display: contents; }

  .morph__copy,
  .morph__layer,
  .morph__mark {
    grid-area: auto;
    opacity: 1;
    transform: none;
    width: auto;
    pointer-events: auto;
  }
  .morph__copy--problem { order: 1; }
  .morph__layer--problem { order: 2; margin-top: 56px; }
  .morph__copy--solution { order: 3; margin-top: 110px; }
  .morph__mark { order: 4; width: 112px; justify-self: center; margin: 40px 0; }
  .morph__layer--solution { order: 5; }
}

/* ---------------------------------------------------------
   Solution hub — the deliberate counter-form to the problem
   ring: there, four nodes chained to each other around an
   empty centre; here, four answers all hanging off one.
   --------------------------------------------------------- */
.hub {
  position: relative;
  display: grid;
  grid-template-columns: 1fr minmax(150px, 190px) 1fr;
  grid-template-rows: auto auto;
  gap: 70px 60px;
  align-items: center;
}

.hub__spokes {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.spoke {
  fill: none;
  stroke: var(--accent-ink);
  stroke-width: 1;
  stroke-linecap: round;
  /* The viewBox is stretched to the hub's box, so the stroke and dash
     pattern have to opt out of that scaling to stay even. */
  vector-effect: non-scaling-stroke;
  opacity: 0.45;
  stroke-dasharray: 6 40;
  animation: spoke-pulse 3.4s linear infinite;
}
.spoke--2 { animation-delay: -0.85s; }
.spoke--3 { animation-delay: -1.7s; }
.spoke--4 { animation-delay: -2.55s; }
/* Each line is drawn card-end first, so the pulse runs inward — the
   counter-movement to the ring circling in section 01. Offset travels
   exactly one dash period, so the loop is seamless. */
@keyframes spoke-pulse {
  to { stroke-dashoffset: -46; }
}

/* The real icon (img/logo/header/Logo_Small_Icon_Orange.svg) redrawn inline:
   its own viewBox and five polygons, unchanged, split into the three groups
   this component animates. Every OTHER logo asset embeds a raster PNG, so
   this is the one place the mark exists as addressable vector geometry —
   still a section-local echo, not a replacement for the files used in
   header, hero and footer. */
.mark {
  display: block;
  width: 100%;
  height: auto;
  /* Fixed, not --accent-ink: the logo assets (img/logo/**) render the icon
     at this exact orange in both themes, and --accent-ink drifts from it
     (contrast-safe darkening for text/line-art) — this mark has to match
     the static logo above it, not the text-safe token. */
  color: #F26344;
}
.mark__ring,
.mark__brow,
.mark__pupil { fill: currentColor; }
/* Ring and brow hold still in both states — only the pupil moves. In the
   problem state it glances up into the gap under the brow (a fixed −12px
   bias, comfortably short of the 19.6px this geometry actually clears);
   opening blends that back to centre and hands off to pointer-follow.

   The bias is stated as (--open − 1), not (1 − --open): the pointer term
   already carries its own --open factor, so this needs the same zero at
   open=1 without a second minus sign fighting it. Follow and blink sit on
   two nested elements because they drive the same transform property at
   very different speeds. */
.mark__eye {
  transform-box: fill-box;
  transform-origin: center;
  transform: translate(
    calc(var(--px, 0px) * var(--open, 1)),
    calc(var(--py, 0px) * var(--open, 1) + (var(--open, 1) - 1) * 12px)
  );
  transition: transform 0.5s var(--ease);
}
.mark__pupil {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.11s ease-in-out;
}
.mark__pupil.is-blinking { transform: scaleY(0.08); }

.solution--1 { grid-column: 1; grid-row: 1; text-align: left; }
.solution--2 { grid-column: 3; grid-row: 1; text-align: right; }
.solution--3 { grid-column: 1; grid-row: 2; text-align: left; }
.solution--4 { grid-column: 3; grid-row: 2; text-align: right; }

.solution h3 {
  font-size: var(--text-title-sm);
  margin: 0 0 14px;
}
.solution__num {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  color: var(--accent-ink);
  letter-spacing: 0.06em;
  margin-right: 8px;
  vertical-align: 2px;
}
/* The problem state fills the same card shell with a sentence where the
   solution state carries tags: identical arrangement, different content. */
.solution__text {
  font-size: var(--text-body-sm);
  line-height: 1.55;
  color: var(--ink-faint);
  margin: 0;
}
.solution--2 .solution__text,
.solution--4 .solution__text { margin-left: auto; }

.solution__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.solution--2 .solution__tags,
.solution--4 .solution__tags { justify-content: flex-end; }
.solution__tags li {
  padding: 6px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--paper);
  font-size: var(--text-xs);
  color: var(--ink-soft);
}


@media (max-width: 1100px) {
  .hub {
    grid-template-columns: 1fr minmax(120px, 150px) 1fr;
    gap: 56px 40px;
  }
}

/* The hub becomes a stacked run: mark first, answers below it. */
@media (max-width: 900px) {
  .hub {
    grid-template-columns: 1fr;
    grid-template-rows: none;
    gap: 44px;
    justify-items: start;
  }
  .hub__spokes { display: none; }
    .solution { grid-column: 1; grid-row: auto; text-align: left; }
  .solution--2 .solution__tags,
  .solution--4 .solution__tags { justify-content: flex-start; }
}

/* =========================================================
   Status / roadmap
   ========================================================= */
/* Centred, unlike every other section: phases 4 and 5 run in parallel, and
   a fork only reads as a fork when it has a centre axis to fork from. The
   heading block follows the graphic so the centring looks decided, not
   accidental. */
.status {
  padding: 140px var(--edge);
  max-width: var(--container);
  margin: 0 auto;
  text-align: center;
}
.status__inner h2 { font-size: var(--text-headline); margin-bottom: 14px; }
.status__sub {
  color: var(--ink-soft);
  max-width: 54ch;
  margin: 0 auto 80px;
  font-size: var(--text-body);
}

.roadmap {
  --branch: 110px; /* half-width of the parallel fork */
  --dot: 15px;
  --gutter: 32px;
  max-width: 1100px;
  margin: 0 auto;
  text-align: left;
}

.roadmap__spine {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}
.roadmap__spine:not(.roadmap__spine--end)::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 7px;
  bottom: 0;
  width: 1px;
  margin-left: -0.5px;
  background: var(--line);
}
/* Scroll-linked fill, kept from the previous timeline: it only ever covers
   the phases that are actually done or running, so the movement cannot
   claim progress the project has not made. */
.roadmap__progress {
  position: absolute;
  left: 50%;
  top: 7px;
  bottom: 0;
  width: 1px;
  margin-left: -0.5px;
  background: var(--accent-ink);
  transform-origin: top;
  transform: scaleY(0);
}

.phase {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  padding-bottom: 58px;
}
.roadmap__spine .phase > .phase__dot { grid-column: 2; }
.roadmap__spine .phase > .phase__body { grid-column: 3; padding-left: var(--gutter); }
.roadmap__spine--end .phase { padding-bottom: 0; }

.phase__dot {
  width: var(--dot);
  height: var(--dot);
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--ink-faint);
  margin-top: 3px;
  position: relative;
  z-index: 1;
  transition: transform 0.25s var(--ease);
}
.phase--done .phase__dot { background: var(--accent-ink); border-color: var(--accent-ink); }
.phase--active .phase__dot {
  border-color: var(--accent-ink);
  animation: phase-pulse 2.6s ease-in-out infinite;
}
@keyframes phase-pulse {
  0%, 100% { box-shadow: 0 0 0 4px var(--accent-soft); }
  50% { box-shadow: 0 0 0 10px transparent; }
}
.phase:hover .phase__dot { transform: scale(1.3); }

.phase__meta {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-ink);
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}
.phase__body h3 { font-size: var(--text-title-sm); margin-bottom: 8px; }
.phase__body p {
  color: var(--ink-faint);
  font-size: var(--text-body-sm);
  line-height: 1.55;
  margin-bottom: 12px;
  max-width: 42ch;
}
.phase__state {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.06em;
  padding: 4px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--ink-faint);
}
.phase--done .phase__state { border-color: var(--accent-ink); color: var(--accent-ink); }
.phase__state--active {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
  color: var(--paper);
}

/* Fork and merge are drawn 1:1 (viewBox width equals CSS width), so the
   curves keep their shape and the branch ends land exactly on the two
   branch lines below. */
.roadmap__fork,
.roadmap__merge {
  display: block;
  width: calc(var(--branch) * 2 + 20px);
  height: 80px;
  margin: 0 auto;
  overflow: visible;
}
.roadmap__fork path,
.roadmap__merge path {
  fill: none;
  stroke-width: 1;
}
.rm-line { stroke: var(--line); }
.rm-fill { stroke: var(--accent-ink); }

.roadmap__parallel {
  position: relative;
  display: grid;
  grid-template-columns: 1fr calc(var(--branch) * 2) 1fr;
  align-items: start;
  padding-bottom: 24px;
}
.roadmap__parallel::before,
.roadmap__parallel::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--line);
}
.roadmap__parallel::before { left: calc(50% - var(--branch)); }
.roadmap__parallel::after { left: calc(50% + var(--branch)); }
/* Accent overlay on the two branch lines, filled by the same scroll
   fraction that drives spine, fork and merge — so the orange runs the whole
   roadmap instead of stopping where the spine ends. */
.roadmap__branchfill {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--accent-ink);
  transform-origin: top;
  transform: scaleY(0);
}
.roadmap__branchfill--l { left: calc(50% - var(--branch)); }
.roadmap__branchfill--r { left: calc(50% + var(--branch)); }

.phase--branch { display: block; padding-bottom: 0; }
.phase--left { grid-column: 1; text-align: right; padding-right: var(--gutter); }
.phase--right { grid-column: 3; text-align: left; padding-left: var(--gutter); }
.phase--left .phase__body p { margin-left: auto; }
.phase--branch .phase__dot { position: absolute; top: 3px; margin-top: 0; }
.phase--left .phase__dot { right: calc(var(--dot) / -2); }
.phase--right .phase__dot { left: calc(var(--dot) / -2); }

.roadmap__note {
  grid-column: 2;
  align-self: center;
  justify-self: center;
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  letter-spacing: 0.05em;
  color: var(--ink-faint);
  text-align: center;
}

/* Below the fork's comfortable width the whole roadmap becomes one left
   aligned run; the "laufen parallel" note then carries what the fork
   carried above. */
@media (max-width: 820px) {
  .status { text-align: left; }
  .status__sub { margin-left: 0; margin-right: 0; }
  .roadmap { --branch: 7px; }
  .roadmap__branchfill--r { display: none; }
  .roadmap__branchfill--l { left: 7px; }
  .roadmap__fork,
  .roadmap__merge { display: none; }
  .roadmap__spine:not(.roadmap__spine--end)::before,
  .roadmap__progress { left: 7px; margin-left: 0; }

  .phase { grid-template-columns: auto 1fr; }
  .roadmap__spine .phase > .phase__dot { grid-column: 1; }
  .roadmap__spine .phase > .phase__body { grid-column: 2; padding-left: 24px; }

  .roadmap__parallel { display: block; }
  .roadmap__parallel::before { left: 7px; }
  .roadmap__parallel::after { display: none; }

  .phase--branch {
    display: grid;
    grid-template-columns: auto 1fr;
    text-align: left;
    padding: 0 0 58px;
  }
  .phase--branch:last-child { padding-bottom: 0; }
  .phase--left,
  .phase--right { padding-left: 0; padding-right: 0; }
  .phase--branch .phase__dot {
    position: static;
    grid-column: 1;
    margin-top: 3px;
  }
  .phase--branch .phase__body {
    grid-column: 2;
    padding-left: 24px;
    text-align: left;
  }
  .roadmap__note {
    display: block;
    margin: 0 0 22px 31px;
    text-align: left;
  }
}

/* =========================================================
   Mitwirkung + Kontakt (CTA-Band)
   ========================================================= */
/* One loud surface, one loud action. The former three equal cards gave the
   visitor no way to tell what to do first, so the form now carries the
   section and the two remaining paths are visibly subordinate. */
.cta {
  background: linear-gradient(160deg, var(--accent) 0%, var(--accent-strong) 100%);
  color: #fff;
  padding: 140px var(--edge);
}
.cta__inner {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 72px;
  align-items: start;
}
.cta__inner h2 { font-size: var(--text-headline-lg); margin-bottom: 18px; }
.cta__intro {
  color: rgba(255,255,255,0.82);
  font-size: var(--text-lg);
  max-width: 46ch;
  margin-bottom: 40px;
}

.ways { display: flex; flex-direction: column; gap: 14px; }
.way {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.16);
  border-radius: var(--radius);
  padding: 20px 22px;
  transition: transform 0.3s var(--ease), background 0.3s var(--ease), border-color 0.3s var(--ease);
}
.way:hover {
  transform: translateY(-3px);
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.32);
}
.way__icon {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  color: rgba(255,255,255,0.85);
  transition: transform 0.3s var(--ease);
}
.way__icon svg { width: 100%; height: 100%; display: block; }
.way:hover .way__icon { transform: scale(1.12); }
.way h3 { font-size: var(--text-lg); color: #fff; margin-bottom: 6px; }
.way p { font-size: var(--text-sm); color: rgba(255,255,255,0.72); line-height: 1.5; margin-bottom: 10px; }

.way__link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: #fff;
}
/* The arrow used to twitch 3px on hover. Now it travels, and a short line
   grows out behind it, so the movement reads as the arrow drawing a path
   rather than as a nudge. One gesture, two parts. */
.way__trail {
  display: block;
  width: 14px;
  height: 1.5px;
  border-radius: 999px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s var(--ease);
}
.way__link svg { transition: transform 0.35s var(--ease); }
.way:hover .way__trail { transform: scaleX(1); }
.way:hover .way__link svg { transform: translateX(8px); }

/* Form on the accent ground, as DESIGN.md's input-field component always
   specified — it drifted to paper tokens while it lived in the light
   Vertrauen section. */
/* The panel darkens its ground instead of lightening it. White on the light
   end of the gradient (#EB5C38) only reaches 3.43:1 — below AA — and the form
   put far more small text on that surface than the section had before. A 28%
   ink tint lifts it to 5.57:1, and the fields darken once more on top. */
.cta__form {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  background: rgba(18, 20, 26, 0.28);
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: var(--radius);
  padding: 30px;
}
.cta__form-title { grid-column: span 2; font-size: var(--text-title); color: #fff; }
.cta__form-hint {
  grid-column: span 2;
  margin-top: -6px;
  font-size: var(--text-xs);
  color: rgba(255,255,255,0.9);
  line-height: 1.5;
}
.cta__field { display: flex; flex-direction: column; gap: 8px; }
.cta__field--wide, .cta__field:last-of-type { grid-column: span 2; }
.cta__field label {
  font-size: var(--text-xs);
  color: rgba(255,255,255,0.9);
  font-family: var(--font-mono);
}
.cta__field input, .cta__field select, .cta__field textarea {
  background: rgba(18, 20, 26, 0.3);
  border: 1px solid rgba(255,255,255,0.24);
  border-radius: 10px;
  padding: 12px 14px;
  color: #fff;
  font-family: var(--font-body);
  font-size: var(--text-body-sm);
  resize: vertical;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.cta__field input:focus, .cta__field textarea:focus {
  outline: none;
  background: rgba(18, 20, 26, 0.42);
  border-color: rgba(255,255,255,0.7);
}
.cta__field input::placeholder, .cta__field textarea::placeholder { color: rgba(255,255,255,0.72); }
.cta__consent {
  grid-column: span 2;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: var(--text-xs);
  color: rgba(255,255,255,0.9);
  line-height: 1.4;
}
.cta__consent input { margin-top: 2px; }
.cta__form .btn { grid-column: span 2; justify-content: center; margin-top: 6px; }
.cta__note {
  grid-column: span 2;
  font-size: var(--text-xs);
  color: rgba(255,255,255,0.9);
  text-align: center;
}
.form-feedback:empty { display: none; }
.form-feedback.is-success { color: #7be0a8; }
.form-feedback.is-error { color: #ff9c8a; }
/* Umfrage-Seite steht auf --paper statt auf der dunklen Kontakt-Karte,
   braucht daher die theme-abhängigen Tokens statt der Fixfarben oben. */
.survey-page .form-feedback.is-success { color: var(--success-ink); }
.survey-page .form-feedback.is-error { color: var(--accent-ink); }

.visually-hidden-field {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 980px) {
  .cta__inner { grid-template-columns: 1fr; gap: 48px; }
  .cta__intro { max-width: none; }
}

@media (max-width: 640px) {
  .cta__form { grid-template-columns: 1fr; padding: 24px; }
  .cta__form-title, .cta__form-hint,
  .cta__field--wide, .cta__field:last-of-type,
  .cta__consent, .cta__form .btn, .cta__note { grid-column: span 1; }
}

/* =========================================================
   Umfrage
   ========================================================= */
/* Full-bleed band with the larger headline step: this is the page's primary
   ask (the hero leads with it), and as a plain paper block between two other
   paper blocks it read as a footnote rather than as the invitation it is. */
.umfrage {
  padding: 160px var(--edge);
  background: var(--paper-dim);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.umfrage__inner { max-width: var(--container); margin: 0 auto; }
.umfrage__inner h2 { font-size: var(--text-headline); margin-bottom: 14px; }
.umfrage__sub { color: var(--ink-soft); font-size: var(--text-body); max-width: 50ch; margin-bottom: 56px; }
.umfrage__inner--teaser { text-align: center; max-width: 780px; }
.umfrage__inner--teaser h2 {
  font-size: var(--text-headline-lg);
  max-width: 18ch;
  margin: 0 auto 20px;
}
.umfrage__inner--teaser .umfrage__sub {
  font-size: var(--text-xl);
  max-width: 46ch;
  margin: 0 auto 44px;
}
.umfrage__inner--teaser .btn { margin: 0 auto; }

.survey__options {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 20px;
}
.survey__options label {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--text-body-sm);
  color: var(--ink-soft);
  cursor: pointer;
}
.survey__options input { accent-color: var(--accent-ink); width: 16px; height: 16px; flex-shrink: 0; }
.survey__contact { display: flex; gap: 14px; flex-wrap: wrap; }
.survey__contact input {
  flex: 1 1 220px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  font-family: var(--font-body);
  font-size: var(--text-body-sm);
  color: var(--ink);
}
@media (max-width: 640px) {
  .survey__options { grid-template-columns: 1fr; }
}

/* =========================================================
   Umfrage — standalone wizard page (umfrage.html)
   ========================================================= */
.survey-page {
  padding: 160px var(--edge) 80px;
  max-width: var(--container);
  margin: 0 auto;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
}
.survey-page__inner {
  max-width: 640px;
  width: 100%;
  margin: 0 auto;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.survey-progress { display: flex; align-items: center; gap: 16px; margin-bottom: 64px; }
.survey-progress__track {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}
.survey-progress__fill {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--accent-ink);
  border-radius: 999px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.survey-progress__label {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink-faint);
  white-space: nowrap;
}

.survey-steps { position: relative; flex: 1; }
.survey-step {
  display: none;
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
  scroll-margin-top: 120px;
}
.survey-step.is-active { display: block; }
.survey-step.is-active.is-shown { opacity: 1; transform: translateY(0); }
.survey-step__eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--accent-ink);
  letter-spacing: 0.06em;
  margin-bottom: 18px;
}
.survey-step h1 { font-size: var(--text-headline); margin-bottom: 36px; max-width: 22ch; }

.survey__options--stack { display: flex; flex-direction: column; gap: 12px; }
.survey__options--stack label {
  padding: 16px 18px;
  border: 1px solid var(--line);
  border-radius: 10px;
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
.survey__options--stack label:hover { border-color: var(--accent-ink); }
.survey__options--stack label:has(input:checked) {
  border-color: var(--accent-ink);
  background: var(--accent-soft);
}

.survey__contact--stack { flex-direction: column; }
.survey__contact--stack input { flex: none; width: 100%; }

.survey-nav { display: flex; justify-content: space-between; gap: 16px; margin-top: 48px; }
.survey-nav .btn { min-width: 132px; justify-content: center; }
.survey-nav .btn[data-hidden] { visibility: hidden; }

.survey__feedback { margin-top: 16px; font-size: var(--text-xs); }

.survey-step--thanks { text-align: center; }
.survey-thanks__mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent-ink);
  margin-bottom: 28px;
}
.survey-step--thanks h1 { max-width: none; }
.survey-step--thanks p {
  color: var(--ink-soft);
  max-width: 40ch;
  margin: 0 auto 32px;
}
.survey-step--thanks .btn { margin: 0 auto; }

@media (max-width: 640px) {
  .survey-page { padding-top: 130px; }
  .survey-nav { flex-direction: column-reverse; }
  .survey-nav .btn { width: 100%; }
}

/* =========================================================
   FAQ
   ========================================================= */
.faq { background: var(--paper-dim); padding: 140px var(--edge); }
.faq__inner { max-width: 780px; margin: 0 auto; }
.faq__inner h2 { font-size: var(--text-headline); margin-bottom: 48px; text-align: center; }

.faq__list { display: flex; flex-direction: column; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.faq__item { background: var(--paper); padding: 22px 24px; }
.faq__item summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-lg);
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.faq__item summary::-webkit-details-marker { display: none; }
/* A drawn arrow rather than the former "+" glyph: the rest of the page uses
   authored SVG icons at a consistent stroke, and a text character in that
   slot never matched them. It flips a half turn on open, so the direction
   always names what the next click does. */
.faq__icon {
  flex-shrink: 0;
  color: var(--accent-ink);
  transition: transform 0.3s var(--ease);
}
.faq__item[open] .faq__icon { transform: rotate(180deg); }
.faq__item p {
  margin-top: 14px;
  font-size: var(--text-body-sm);
  color: var(--ink-faint);
  line-height: 1.6;
  max-width: 60ch;
}

/* =========================================================
   Warum wir
   ========================================================= */
.warum { padding: 140px var(--edge); max-width: var(--container); margin: 0 auto; }
.warum__inner { max-width: 640px; margin: 0 auto; }
.warum__text h2 { font-size: var(--text-headline); margin-bottom: 26px; }
.warum__text p {
  color: var(--ink-soft);
  font-size: var(--text-body);
  line-height: 1.62;
  max-width: 58ch;
}
.warum__text p + p { margin-top: 20px; }
/* The claim is the one place in this text that is brand voice rather than
   prose, so it carries the display face instead of an italic. */
.warum__claim {
  font-style: normal;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--accent-ink);
}

.warum__people {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 32px;
}
.warum__names { font-family: var(--font-display); font-weight: 600; font-size: var(--text-md); }
.warum__roles {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--ink-faint);
  letter-spacing: 0.04em;
}

/* =========================================================
   Footer
   ========================================================= */
.footer { background: var(--console); color: var(--console-text-dim); padding: 80px var(--edge) 32px; }
.footer__inner {
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr;
  gap: 40px;
  padding-bottom: 60px;
}
.footer__col { display: flex; flex-direction: column; gap: 14px; }
.footer__col a { font-size: var(--text-sm); color: var(--console-text-dim); transition: color 0.2s; }
.footer__col a:hover { color: var(--console-text); }
.footer__col a[href^="mailto:"],
.footer__col a[target="_blank"] { display: inline-flex; align-items: center; gap: 8px; }
.footer__col-title {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.4);
  margin-bottom: 4px;
}
.footer__logo { display: inline-flex; }
.footer__logo img { height: 28px; width: auto; }
.footer__tagline { font-size: var(--text-sm); line-height: 1.5; margin-top: 4px; }

.footer__bottom {
  max-width: var(--container);
  margin: 0 auto;
  padding-top: 28px;
  border-top: 1px solid var(--console-line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.footer__legal { display: flex; flex-wrap: wrap; gap: 24px; font-size: var(--text-sm); }
.link--underline { text-decoration: underline; }
.footer__legal a { color: var(--console-text-dim); transition: color 0.2s; }
.footer__legal a:hover { color: var(--console-text); }
.footer .lang-switch__option { color: rgba(255,255,255,0.45); }
.footer .lang-switch__option.is-active { color: var(--console-text); }
.footer .lang-switch__sep { color: rgba(255,255,255,0.2); }
.footer .theme-toggle { border-color: rgba(255,255,255,0.2); color: var(--console-text-dim); }
.footer .theme-toggle:hover { border-color: var(--console-text); color: var(--console-text); }

@media (max-width: 760px) {
  .footer__inner { grid-template-columns: 1fr; gap: 36px; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  [data-reveal] {
    transition: none !important;
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  /* Kept out of the block above: these carry a resting opacity that is part
     of their look, not an entrance state, so it must survive the reset. */
  .spoke { animation: none !important; }
}
