/* ============================================================
   Self-hosted fonts
   ============================================================ */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('../assets/fonts/fraunces-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../assets/fonts/inter-variable.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

/* ============================================================
   Blumen Herzog — Design Tokens
   ============================================================ */
:root {
  /* ---- Core palette (OKLCH) ----------------------------------
     Scene: Samstagvormittag im Gewächshaus an der Arsterdamm,
     diffuses Nordlicht durch beschlagenes Glas.
     Neutrals carry a trace of the brand hue (chroma 0.006–0.018).
     Exactly one saturated colour: --accent (terracotta = the pots).
     No pure black, no pure white anywhere.                       */
  --bg:     oklch(0.968 0.014 84);
  --ink:    oklch(0.250 0.018 148);
  --muted:  oklch(0.462 0.016 148);
  --accent: oklch(0.552 0.155 32);

  /* Neutral steps derived from --bg / --ink */
  --surface:    oklch(0.988 0.006 84);  /* stand-in for white; chroma pulled down at extreme lightness */
  --bg-alt:     oklch(0.942 0.018 82);
  --accent-deep: oklch(0.468 0.140 31);

  /* Brand greens — restrained on purpose, the accent stays alone */
  --green-900: oklch(0.270 0.032 150);
  --green-700: oklch(0.390 0.045 150);
  /* Kräftiges Grün, ausschließlich für den Stellen-Aufruf.
     Chroma 0.095 liegt bewusst unter dem Terrakotta-Akzent (0.155): Das Grün
     ist deutlich sichtbar, bleibt aber die zweitstärkste Farbe der Seite. Der
     Bestell-Button behält damit den Vorrang, den er haben muss.
     Ein eigener Aufruf für Bewerbungen darf sich vom Bestell-Aufruf farblich
     unterscheiden — es sind zwei verschiedene Zielgruppen mit zwei
     verschiedenen Handlungen. */
  --green-signal: oklch(0.430 0.095 150);
  --green-signal-tief: oklch(0.360 0.090 150);
  --green-600: oklch(0.470 0.050 150);
  --green-100: oklch(0.920 0.020 150);

  /* Warm light on dark green. Desaturated so it reads as light, not as a second accent. */
  --sand: oklch(0.860 0.045 78);

  /* Text/UI on dark surfaces. Stands in for white — warm, never pure. */
  --paper: oklch(0.976 0.008 84);

  /* ---- Legacy aliases (keep existing rules working) ---- */
  --color-bg: var(--bg);
  --color-bg-alt: var(--bg-alt);
  --color-surface: var(--surface);
  --color-ink: var(--ink);
  --color-ink-soft: var(--muted);
  --color-green-900: var(--green-900);
  --color-green-700: var(--green-700);
  --color-green-600: var(--green-600);
  --color-green-100: var(--green-100);
  --color-terracotta: var(--accent);
  --color-terracotta-dark: var(--accent-deep);
  --color-border: oklch(0.250 0.018 148 / 0.12);
  --color-border-strong: oklch(0.250 0.018 148 / 0.22);

  /* Typography */
  --font-display: 'Fraunces', 'Georgia', serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  --fs-xs: 0.8125rem;
  --fs-sm: 0.9375rem;
  --fs-base: 1rem;
  --fs-md: 1.125rem;
  --fs-lg: 1.375rem;
  --fs-2xl: clamp(2rem, 1.6rem + 1.8vw, 2.75rem);
  --fs-3xl: clamp(2.6rem, 1.9rem + 3.2vw, 4.25rem);

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;
  --space-9: 96px;

  /* Effects */
  --radius-sm: 6px;
  --radius-md: 14px;
  --radius-lg: 28px;
  --shadow-sm: 0 1px 2px oklch(0.250 0.018 148 / 0.08);
  --shadow-md: 0 8px 24px -8px oklch(0.250 0.018 148 / 0.22);
  --shadow-lg: 0 24px 60px -20px oklch(0.250 0.018 148 / 0.35);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 180ms;
  --duration-base: 320ms;

  --container-w: 1200px;
  --header-h: 84px;
}

/* ============================================================
   Reset
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* ---- Lenis ----------------------------------------------------
   Deliberately omits Lenis' default `iframe { pointer-events: none }`:
   that rule would make the contact map impossible to use. The map opts
   out of smooth scrolling via data-lenis-prevent instead.            */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
picture { display: contents; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
h1, h2, h3, h4, p { margin: 0; }
button { font: inherit; background: none; border: none; padding: 0; cursor: pointer; color: inherit; }
iframe { border: 0; }

:focus-visible {
  outline: 2px solid var(--color-terracotta);
  outline-offset: 3px;
  border-radius: 4px;
}

.container {
  max-width: var(--container-w);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

/* Keep anchor targets clear of the fixed header when jumped to via nav links */
main section[id] {
  scroll-margin-top: calc(var(--header-h) + 20px);
}

.icon { width: 20px; height: 20px; flex-shrink: 0; }

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: -60px;
  background: var(--color-green-900);
  color: var(--paper);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-sm);
  z-index: 1000;
  transition: top var(--duration-base) var(--ease-out);
}
.skip-link:focus { top: var(--space-4); }

.scroll-progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline-start: 0;
  height: 3px;
  width: 0%;
  background: linear-gradient(90deg, var(--color-terracotta), var(--sand));
  z-index: 1100;
  transition: width 120ms linear;
}
@media (prefers-reduced-motion: reduce) {
  .scroll-progress { transition: none; }
}

h2 {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  font-weight: 600;
  line-height: 1.15;
  color: var(--color-green-900);
  letter-spacing: -0.01em;
}

.eyebrow {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-terracotta-dark);
  margin-bottom: var(--space-3);
}

.center { text-align: center; }

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 14px 26px;
  /* Every button reserves the same border box, visible or not: otherwise a
     bordered neighbour (.btn-ghost) is 2.7px taller and flex-stretch drags
     the filled button with it — same button, two heights across the page. */
  border: 1.5px solid transparent;
  border-radius: 999px;
  font-weight: 600;
  font-size: var(--fs-sm);
  line-height: 1.6;
  white-space: nowrap;
  transition: transform var(--duration-fast) var(--ease-out), background var(--duration-fast) var(--ease-out), box-shadow var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
  min-height: 48px;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn-primary {
  background: var(--color-terracotta);
  color: var(--paper);
  box-shadow: var(--shadow-md);
}
.btn-primary:hover { background: var(--color-terracotta-dark); }

.btn-ghost {
  background: transparent;
  color: var(--paper);
  border: 1.5px solid oklch(0.976 0.008 84 / 0.55);
}
.btn-ghost:hover { background: oklch(0.976 0.008 84 / 0.12); border-color: var(--paper); }

/* .btn-ghost ist für dunkle Flächen gebaut — heller Text, heller Rand. Auf
   einem hellen Abschnitt wird daraus ein unsichtbarer Button: Er ist da,
   klickbar und im Tastaturfokus, aber niemand sieht ihn. Genau das war im
   Abschnitt „Arbeiten bei uns" passiert.
   Deshalb eine ausdrückliche Variante statt einer Ausnahme pro Fundstelle. */
/* Gefüllt statt umrandet: Eine dünne Kontur auf hellem Grund ist zwar lesbar,
   liest sich aber als Nebenweg. Der Stellen-Aufruf ist der einzige Aufruf in
   seinem Abschnitt und darf entsprechend auftreten. */
.btn-gruen {
  background: var(--green-signal);
  border-color: var(--green-signal);
  color: var(--paper);
}
.btn-gruen:hover {
  background: var(--green-signal-tief);
  border-color: var(--green-signal-tief);
  color: var(--paper);
  transform: translateY(-1px);
}
.btn-gruen:focus-visible {
  outline: 2px solid var(--green-signal-tief);
  outline-offset: 3px;
}

.btn-phone {
  color: var(--color-green-900);
  font-size: var(--fs-sm);
  padding: 10px 18px;
  border-radius: 999px;
  border: 1.5px solid var(--color-border-strong);
}
.btn-phone:hover { background: var(--color-green-100); border-color: var(--color-green-600); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-weight: 600;
  color: var(--color-green-700);
  padding-bottom: 2px;
  border-bottom: 1.5px solid var(--color-green-700);
  width: fit-content;
}
.link-arrow .icon { width: 18px; height: 18px; transition: transform var(--duration-fast) var(--ease-out); }
.link-arrow:hover .icon { transform: translateX(4px); }

/* ============================================================
   Header
   ============================================================ */
.site-header {
  position: fixed;
  /* Die fixierte Kopfzeile würde sonst den Entwurfs-Hinweis überdecken.
     --header-top ist der noch sichtbare Rest des Hinweises; main.js zählt
     ihn beim Scrollen herunter, damit die Kopfzeile mitwandert statt zu
     springen. Ohne Hinweis (Livegang) bleibt der Wert 0. */
  inset-block-start: var(--header-top, 0px);
  inset-inline: 0;
  z-index: 100;
  height: var(--header-h);
  display: flex;
  align-items: center;
  transition: background var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out), height var(--duration-base) var(--ease-out);
}
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, oklch(0.180 0.015 148 / 0.75), oklch(0.180 0.015 148 / 0.08));
  z-index: -1;
  opacity: 1;
  transition: opacity var(--duration-base) var(--ease-out);
}
.site-header.is-scrolled {
  height: 72px;
  background: oklch(0.968 0.014 84 / 0.92);
  backdrop-filter: blur(10px);
  box-shadow: var(--shadow-sm);
}
.site-header.is-scrolled::before { opacity: 0; }

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  width: 100%;
}

.brand-logo {
  height: 38px;
  width: auto;
  filter: brightness(0) invert(1);
  transition: filter var(--duration-base) var(--ease-out);
}
.site-header.is-scrolled .brand-logo { filter: none; }

.main-nav {
  position: relative;
  color: var(--paper);
  transition: color var(--duration-fast) var(--ease-out);
}
.main-nav ul {
  display: flex;
  gap: var(--space-6);
  position: relative;
  z-index: 1;
}
.main-nav a {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: inherit;
  position: relative;
  padding: 4px 0;
  display: inline-block;
}
/* "true" setzt die Scrollspy für den gerade sichtbaren Abschnitt der
   Startseite, "page" steht im Quelltext der Unterseiten für die Seite, auf
   der man sich befindet. Beide sollen gleich aussehen — sonst ist die
   Markierung nur für Screenreader da und für alle anderen unsichtbar. */
.main-nav a[aria-current="true"],
.main-nav a[aria-current="page"] { font-weight: 600; }
.site-header.is-scrolled .main-nav { color: var(--color-green-900); }

.nav-indicator {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 1.5px;
  width: 0;
  background: currentColor;
  opacity: 0;
  transform: translateX(0);
  transition: transform 320ms var(--ease-out), width 320ms var(--ease-out), opacity 200ms var(--ease-out);
  pointer-events: none;
}
.nav-indicator.is-visible { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .nav-indicator { transition: opacity 200ms; }
}

.header-actions { display: flex; align-items: center; gap: var(--space-4); }
.site-header:not(.is-scrolled) .btn-phone { color: var(--paper); border-color: oklch(0.976 0.008 84 / 0.55); }
.site-header:not(.is-scrolled) .btn-phone:hover { background: oklch(0.976 0.008 84 / 0.12); }

.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  align-items: center;
  justify-content: center;
  color: var(--paper);
  border-radius: var(--radius-sm);
}
.site-header.is-scrolled .nav-toggle { color: var(--color-green-900); }
.icon-close { display: none; }
.nav-toggle[aria-expanded="true"] .icon-open { display: none; }
.nav-toggle[aria-expanded="true"] .icon-close { display: block; }

/* ============================================================
   Hero
   ============================================================ */
.hero {
  position: relative;
  /* Der Entwurfs-Hinweis steht im Fluss über dem Hero. Volle 100dvh würden
     den Hero exakt um dessen Höhe unter die Falz schieben — der Anruf-Button
     landet außerhalb des Bildschirms. --banner-h setzt main.js; ohne JS
     greift 0px und es bleibt beim bisherigen Verhalten. */
  min-height: calc(100dvh - var(--banner-h, 0px));
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: var(--paper);
}
.hero-media {
  position: absolute;
  inset: 0;
  z-index: -2;
}
.hero-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 65%;
  animation: bloom-in 1900ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes bloom-in {
  from { transform: scale(1.18); filter: blur(14px) saturate(0.85); }
  to { transform: scale(1.06); filter: blur(0) saturate(1); }
}
@media (prefers-reduced-motion: reduce) {
  .hero-media img { animation: none; transform: scale(1.06); filter: none; }
}
/* Der Verlauf ist kein Stilmittel, sondern trägt die Lesbarkeit: Der Text liegt
   auf einem Foto, dessen Helligkeit sich pro Bildausschnitt ändert. Gemessen
   wurde gegen den hellsten tatsächlich gerenderten Hintergrundpixel unter jeder
   Textzeile — bei 42 % lag der Eyebrow vorher bei 1,90:1 statt der nötigen
   4,5:1, die H1 auf dem Handy bei 2,61:1 statt 3:1. Die mittleren Stopps sind
   deshalb angehoben; wer hier aufhellt, muss neu messen, nicht schätzen. */
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, oklch(0.180 0.015 148 / 0.96) 0%, oklch(0.180 0.015 148 / 0.86) 42%, oklch(0.180 0.015 148 / 0.72) 65%, oklch(0.180 0.015 148 / 0.72) 100%);
}
.hero-content {
  padding-block: var(--space-9) var(--space-9);
  max-width: 780px;
}
.hero .eyebrow { color: var(--sand); }
.rating-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: var(--space-5);
  padding: 8px 16px;
  border-radius: 999px;
  background: oklch(0.976 0.008 84 / 0.1);
  border: 1px solid oklch(0.976 0.008 84 / 0.25);
  backdrop-filter: blur(6px);
  font-size: var(--fs-sm);
  color: var(--paper);
  transition: background var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out);
}
.rating-badge:hover { background: oklch(0.976 0.008 84 / 0.18); border-color: oklch(0.976 0.008 84 / 0.4); }
.rating-stars { display: inline-flex; gap: 2px; color: var(--sand); }
.rating-stars svg { width: 14px; height: 14px; }
/* Teilgefüllter Stern: Ein blasser Stern liegt unten, darüber derselbe Stern
   in voller Farbe, per clip-path auf --fuellung beschnitten. Kein zweites
   SVG-Motiv, keine Maske — bleibt damit auch bei geänderter Sternform korrekt. */
.stern-teil {
  position: relative;
  display: inline-flex;
  width: 14px;
  height: 14px;
}
.stern-teil svg { position: absolute; inset: 0; opacity: 0.3; }
.stern-teil .stern-fuellung {
  opacity: 1;
  clip-path: inset(0 calc(100% - var(--fuellung, 50%)) 0 0);
}
/* Der Stand macht sichtbar, dass die Zahl eine Momentaufnahme ist. Bewusst
   leiser gesetzt als die Bewertung selbst — er soll die Aussage einordnen,
   nicht mit ihr konkurrieren. */
.rating-date {
  font-size: 0.75rem;
  opacity: 0.7;
  white-space: nowrap;
}
.rating-badge strong { font-weight: 700; }
.rating-badge span { color: oklch(0.976 0.008 84 / 0.8); }
.hero h1 {
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: 600;
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin-bottom: var(--space-5);
  /* Ersetzt den früheren harten <br>. Der saß bei 1440px gut und bei jeder
     anderen Breite daneben — auf mittleren Fenstern stand „blüht." allein auf
     Zeile drei. `balance` verteilt die Zeilen gleichmäßig, die max-width hält
     die Zeilenlänge lesbar, statt sie über die ganze Spalte zu ziehen.
     Browser ohne `balance` brechen normal um, also weiterhin korrekt. */
  text-wrap: balance;
  max-width: 16ch;
}
.hero-lead {
  font-size: var(--fs-md);
  max-width: 46ch;
  color: oklch(0.976 0.008 84 / 0.9);
  margin-bottom: var(--space-6);
}
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-4); }

.scroll-cue {
  position: absolute;
  bottom: var(--space-5);
  left: 50%;
  transform: translateX(-50%);
  /* The arrow is only 20px wide; the hit area must not be. WCAG 2.2 asks for
     24x24 minimum, 44x44 is the comfortable thumb target. */
  display: grid;
  place-items: center;
  min-width: 44px;
  min-height: 44px;
  color: var(--paper);
  opacity: 0.75;
  animation: bob 2.2s ease-in-out infinite;
}
.scroll-cue:hover { opacity: 1; }
@keyframes bob {
  0%, 100% { transform: translate(-50%, 0); }
  50% { transform: translate(-50%, 8px); }
}
@media (prefers-reduced-motion: reduce) { .scroll-cue { animation: none; } }

/* ============================================================
   Thesis — the claim the hero line has to earn
   ============================================================ */
.thesis {
  padding-block: var(--space-9);
  text-align: center;
}
.thesis-line {
  font-family: var(--font-display);
  font-size: clamp(2.1rem, 1.4rem + 3.4vw, 3.9rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--green-900);
  max-width: 18ch;
  margin-inline: auto;
  margin-bottom: var(--space-6);
  text-wrap: balance;
}
/* Wrapped per word by JS so the line can rise as it is read */
.thesis-line .word {
  display: inline-block;
  will-change: transform, opacity;
}
.thesis-sub {
  color: var(--muted);
  font-size: var(--fs-md);
  max-width: 54ch;
  margin-inline: auto;
  text-wrap: pretty;
}

/* ============================================================
   USP strip
   ============================================================ */
.usp {
  background: var(--color-green-900);
  color: var(--paper);
  padding-block: var(--space-6);
}
.usp-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-6);
}
.usp-item {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.usp-item .icon { width: 30px; height: 30px; color: var(--sand); transition: transform 420ms var(--ease-out); }
.usp-item:hover .icon { transform: scale(1.15); }
.usp-item strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: 600;
}
.usp-item span { font-size: var(--fs-xs); color: oklch(0.976 0.008 84 / 0.7); }

/* ============================================================
   About / Produktion
   ============================================================ */
.about { padding-block: var(--space-9); }
.about-grid {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: var(--space-8);
  align-items: center;
}
.about-media {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: visible;
  max-width: 100%;
}
.about-media-main {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.about-media-small {
  position: absolute;
  width: 46%;
  max-width: 260px;
  min-width: 120px;
  aspect-ratio: 4/3;
  height: auto;
  object-fit: cover;
  right: -6%;
  bottom: -8%;
  border-radius: var(--radius-md);
  border: 6px solid var(--color-bg);
  box-shadow: var(--shadow-lg);
}
.about-text h2 { margin-bottom: var(--space-5); }
.about-text p {
  color: var(--color-ink-soft);
  font-size: var(--fs-md);
  margin-bottom: var(--space-4);
  max-width: 52ch;
}
.about-text .link-arrow { margin-top: var(--space-3); }

/* ============================================================
   Season calendar
   ============================================================ */
.season { padding-block: var(--space-8); background: var(--color-bg-alt); }
.season h2 { margin-bottom: var(--space-3); }
.season-lead {
  color: var(--color-ink-soft);
  max-width: 46ch;
  margin-inline: auto;
  margin-bottom: var(--space-7);
}
:root {
  /* Season markers carry information, so they stay muted (chroma ≤ 0.07).
     The accent (chroma 0.155) remains the only saturated colour on the page.
     Autumn sits at hue 62, deliberately clear of the accent at hue 32. */
  --season-spring: oklch(0.700 0.060 145);
  --season-summer: oklch(0.755 0.070 85);
  --season-autumn: oklch(0.625 0.070 62);
  --season-winter: oklch(0.665 0.040 235);
}

.season-groups {
  display: grid;
  /* Fits as many cards as the width comfortably allows instead of jumping
     2 -> 4 at a fixed breakpoint, which left 900–1024px half empty. */
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--space-5);
}
.season-group {
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: transform 400ms var(--ease-out), box-shadow 400ms var(--ease-out), border-color 400ms var(--ease-out);
}
.season-group:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.season-group[data-season="spring"] { --season-accent: var(--season-spring); }
.season-group[data-season="summer"] { --season-accent: var(--season-summer); }
.season-group[data-season="autumn"] { --season-accent: var(--season-autumn); }
.season-group[data-season="winter"] { --season-accent: var(--season-winter); }
.season-group.has-current {
  border-color: var(--season-accent);
  box-shadow: var(--shadow-md);
}

.season-group-photo { position: relative; aspect-ratio: 4/3; }
.season-group-photo img { width: 100%; height: 100%; object-fit: cover; }
.season-group-photo::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 4px;
  background: var(--season-accent);
}

.season-group-body { padding: var(--space-5); }
.season-group h3 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--color-green-900);
  margin-bottom: var(--space-4);
}

.season-months { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.season-months li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-sm);
  border-radius: var(--radius-sm);
  transition: background 400ms var(--ease-out);
}
.season-months li:last-child { border-bottom: none; }
.season-months li strong { color: var(--color-green-900); font-weight: 600; white-space: nowrap; }
.season-months li span { color: var(--color-ink-soft); text-align: right; }
.season-months li.is-current {
  margin-inline: calc(-1 * var(--space-3));
  padding-inline: var(--space-3);
  background: var(--color-green-900);
  border-bottom-color: transparent;
}
.season-months li.is-current strong { color: var(--sand); }
.season-months li.is-current span { color: oklch(0.976 0.008 84 / 0.85); }

@media (max-width: 560px) {
  /* Below this the auto-fit minimum would still allow two very cramped columns. */
  .season-groups { grid-template-columns: 1fr; }
}

/* ============================================================
   Services
   ============================================================ */
.services {
  background: var(--color-bg-alt);
  padding-block: var(--space-9);
}
.services h2 { margin-bottom: var(--space-7); }
.services .eyebrow { display: block; }
.services-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}
.service-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: transform var(--duration-base) var(--ease-out), box-shadow var(--duration-base) var(--ease-out), border-color var(--duration-base) var(--ease-out);
}
/* Die Hebung beim Überfahren nur dort, wo die Karte auch irgendwohin führt.
   Vorher hoben sich alle sechs Karten an, obwohl fünf davon Sackgassen sind —
   sie sahen anklickbar aus und waren es nicht. Ein Aufheben ist ein
   Versprechen; wo nichts folgt, darf es nicht gegeben werden.
   :has() fehlt nur in sehr alten Browsern, und dort fällt die Hebung
   ersatzlos weg — die sichere Richtung. */
.service-card:has(a):hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: transparent;
}
.service-card img {
  width: 100%;
  height: auto;
  aspect-ratio: 4/3;
  object-fit: cover;
  transition: transform 600ms var(--ease-out);
}
.service-card:has(a):hover img { transform: scale(1.05); }
.service-card-body { padding: var(--space-6); }
.service-card .icon {
  width: 28px;
  height: 28px;
  color: var(--color-terracotta);
  margin-bottom: var(--space-4);
  transition: transform 420ms var(--ease-out);
}
.service-card:has(a):hover .icon { transform: rotate(-8deg) scale(1.12); }
.service-card h3 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--color-green-900);
  margin-bottom: var(--space-2);
}
.service-card p {
  color: var(--color-ink-soft);
  font-size: var(--fs-sm);
}

/* ============================================================
   Gallery — interactive accordion
   ============================================================ */
.gallery { padding-block: var(--space-9) var(--space-8); }
.gallery-heading { margin-bottom: var(--space-7); }
.gallery-heading h2 { max-width: 22ch; }

.accordion-gallery {
  display: flex;
  gap: var(--space-3);
  height: 460px;
  border-radius: var(--radius-lg);
}
.accordion-item {
  position: relative;
  flex: 1 1 0%;
  min-width: 64px;
  border: none;
  margin: 0;
  padding: 0;
  background: var(--color-green-900);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  transition: flex-grow 650ms var(--ease-out);
}
.accordion-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.8) saturate(0.9);
  transition: filter 500ms var(--ease-out), transform 650ms var(--ease-out);
}
.accordion-item:hover,
.accordion-item:focus-visible,
.accordion-item.is-expanded {
  flex-grow: 5;
}
.accordion-item:hover img,
.accordion-item:focus-visible img,
.accordion-item.is-expanded img {
  filter: brightness(1) saturate(1.05);
  transform: scale(1.03);
}
.accordion-caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: var(--space-5) var(--space-4) var(--space-4);
  background: linear-gradient(to top, oklch(0.180 0.015 148 / 0.88), transparent 80%);
  color: var(--paper);
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 400ms var(--ease-out), transform 400ms var(--ease-out);
}
.accordion-item:hover .accordion-caption,
.accordion-item:focus-visible .accordion-caption,
.accordion-item.is-expanded .accordion-caption {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .accordion-item, .accordion-item img, .accordion-caption { transition: none; }
}

/* Auf dem Handy KEIN Akkordeon.
   Die frühere Fassung stapelte die Bilder in eine 620px hohe Spalte: Bei vier
   Motiven blieben je 150px, bei acht nur noch 77px — Streifen, auf denen nichts
   zu erkennen ist, und jedes Bild muss erst angetippt werden. Ein Akkordeon
   lebt davon, dass man die Alternativen sieht; auf 390px sieht man sie nicht.
   Deshalb ein zweispaltiges Raster: alle acht Motive gleichzeitig sichtbar,
   in brauchbarer Größe, ohne Interaktionszwang. */
@media (max-width: 860px) {
  .accordion-gallery {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-3);
    height: auto;
  }
  .accordion-item {
    min-width: 0;
    min-height: 0;
    flex: none;
    aspect-ratio: 3 / 4;
    border-radius: var(--radius-sm);
  }
  .accordion-item img { height: 100%; }
  /* Bildunterschrift dauerhaft sichtbar: Ohne Hover gäbe es sonst keinen Weg,
     sie zu lesen, und ein Tippen sollte nichts kosten müssen. */
  /* Umbrechen statt abschneiden: Im Akkordeon auf dem Desktop ist der Streifen
     breit genug für eine Zeile, deshalb dort `nowrap` mit Ellipse. Im
     173px-Raster wurde daraus „Weihnachtsste…" — eine Beschriftung, die den
     Namen verschweigt, kann man auch weglassen. */
  .accordion-caption {
    opacity: 1;
    transform: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    font-size: 0.8rem;
    line-height: 1.25;
    padding: var(--space-6) 10px 10px;
  }
  /* Das Aufklappen ergibt im Raster keinen Sinn mehr — die Klasse setzt JS
     weiterhin, sie darf nur nichts mehr bewirken. */
  .accordion-item.is-expanded { flex: none; }
}

/* ============================================================
   Delivery
   ============================================================ */
.delivery { padding-block: var(--space-9); }
.delivery-grid {
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: var(--space-8);
  align-items: center;
  background: var(--color-green-900);
  border-radius: var(--radius-lg);
  overflow: hidden;
  color: var(--paper);
}
.delivery-media { height: 100%; min-height: 320px; }
.delivery-media img { width: 100%; height: 100%; object-fit: cover; }
.delivery-text { padding: var(--space-8) var(--space-8) var(--space-8) 0; }
.delivery .eyebrow { color: var(--sand); }
.delivery h2 { color: var(--paper); margin-bottom: var(--space-4); }
.delivery-text p { color: oklch(0.976 0.008 84 / 0.82); font-size: var(--fs-md); margin-bottom: var(--space-4); max-width: 44ch; }
.delivery-text .btn { margin-top: var(--space-3); }

/* ============================================================
   Contact
   ============================================================ */
.contact { padding-block: var(--space-9); }
.contact-grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: var(--space-8);
  align-items: start;
}
.contact-info h2 { margin-bottom: var(--space-6); }
.contact-list { display: flex; flex-direction: column; gap: var(--space-5); margin-bottom: var(--space-6); }
.contact-list li { display: flex; align-items: flex-start; gap: var(--space-4); }
.contact-list .icon { color: var(--color-terracotta); margin-top: 3px; }
.contact-list a:hover { color: var(--color-terracotta); }
.muted { color: var(--color-ink-soft); font-size: var(--fs-sm); }

.hours-table { display: flex; flex-direction: column; gap: 2px; }
.hours-table div { display: flex; gap: var(--space-5); font-size: var(--fs-sm); }
.hours-table span:first-child { min-width: 150px; color: var(--color-ink-soft); }
.hours-table span:last-child { font-weight: 600; font-variant-numeric: tabular-nums; }

.contact-map {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}
.map-image { display: block; position: relative; }
/* `height: auto` ist Pflicht, sobald ein <img> HTML-Attribute width/height
   trägt: ohne sie gewinnt das Attribut über aspect-ratio und das Bild wird
   auf 600px Höhe gestreckt. Dieser Fehler ist auf dieser Seite schon
   dreimal aufgetreten. */
.contact-map img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}
.map-cta {
  display: block;
  padding: var(--space-4) var(--space-5);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--color-green-700);
  border-top: 1px solid var(--color-border);
}
.map-image:hover .map-cta { color: var(--color-terracotta); }
/* Die OSM-Lizenz (ODbL) verlangt die Namensnennung am Kartenbild. Leise
   gesetzt, aber vorhanden — weglassen ist keine Option. */
.map-attribution {
  padding: 0 var(--space-5) var(--space-3);
  margin: 0;
  font-size: 0.6875rem;
  color: var(--muted);
}

/* ============================================================
   Footer
   ============================================================ */
.site-footer {
  background: var(--color-green-900);
  color: oklch(0.976 0.008 84 / 0.75);
  padding-block: var(--space-7) var(--space-5);
}
.footer-inner {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  flex-wrap: wrap;
  gap: var(--space-6);
  padding-bottom: var(--space-6);
  border-bottom: 1px solid oklch(0.976 0.008 84 / 0.14);
}
.footer-brand img { filter: brightness(0) invert(1); height: 34px; width: auto; margin-bottom: var(--space-3); }
.footer-brand p { font-size: var(--fs-sm); line-height: 1.7; }
.footer-nav { display: flex; gap: var(--space-5); flex-wrap: wrap; }
.footer-nav a { font-size: var(--fs-sm); }
.footer-nav a:hover { color: var(--paper); }
.footer-bottom { padding-top: var(--space-5); font-size: var(--fs-xs); }

/* ============================================================
   Scroll reveal
   ============================================================ */
/* Content is visible by default. Only once JS has confirmed it can run do we
   hide it to animate it in — otherwise a script failure blanks the page. */
.reveal { opacity: 1; }
/* Uses `translate`, not `transform`: a .reveal element that also lifts on hover
   would otherwise have its hover transform overridden by the more specific
   `.js .reveal.is-visible` rule. These are separate properties, so they compose. */
.js .reveal {
  opacity: 0;
  translate: 0 18px;
  transition: opacity 700ms var(--ease-out), translate 700ms var(--ease-out);
}
.js .reveal.is-visible { opacity: 1; translate: 0 0; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; translate: none; transition: none; }
}

/* The hero is above the fold and must never wait for 143KB of animation library.
   It fades itself in from CSS; JS only takes over for everything further down.
   On a throttled connection this is the difference between a readable page at
   ~1s and a blank one until GSAP has downloaded. */
.js .hero .reveal {
  animation: hero-in 700ms var(--ease-out) both;
  animation-delay: calc(var(--hero-step, 0) * 90ms);
}
.js .hero .reveal:nth-child(1) { --hero-step: 0; }
.js .hero .reveal:nth-child(2) { --hero-step: 1; }
.js .hero .reveal:nth-child(3) { --hero-step: 2; }
.js .hero .reveal:nth-child(4) { --hero-step: 3; }
.js .hero .reveal:nth-child(5) { --hero-step: 4; }
@keyframes hero-in {
  from { opacity: 0; translate: 0 18px; }
  to   { opacity: 1; translate: 0 0; }
}
@media (prefers-reduced-motion: reduce) {
  .js .hero .reveal { animation: none; opacity: 1; translate: none; }
}

/* Same rule for the thesis line: readable without JS, animated with it. */
.js .thesis-line .word {
  opacity: 0;
  transform: translateY(0.4em);
}
.js [data-thesis-fade] { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  .js .thesis-line .word { opacity: 1; transform: none; }
  .js [data-thesis-fade] { opacity: 1; }
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 1024px) {
  .about-grid, .delivery-grid, .contact-grid { grid-template-columns: 1fr; }
  .delivery-media { min-height: 240px; }
  .delivery-text { padding: 0 var(--space-6) var(--space-6); }
  .delivery-grid { grid-template-columns: 1fr; }
  .about-media { width: 100%; max-width: 480px; margin-inline: auto; }
  /* The overlay deliberately hangs past its parent. On narrow screens -6% grows
     wider than the container padding and pushes the whole document sideways,
     so cap the overhang at a value that still fits inside the page margin. */
  .about-media-small { right: -12px; }
  .services-grid { grid-template-columns: repeat(2, 1fr); }
  .usp-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 860px) {
  :root { --header-h: 68px; }

  .main-nav {
    position: fixed;
    inset: 68px 0 0 0;
    background: var(--color-bg);
    padding: var(--space-6) var(--space-5);
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-out), transform var(--duration-base) var(--ease-out);
  }
  .main-nav.is-open { opacity: 1; transform: translateY(0); pointer-events: auto; }
  .main-nav ul { flex-direction: column; gap: var(--space-1); }
  .main-nav a { display: block; padding: var(--space-4) var(--space-2); color: var(--color-green-900); font-size: var(--fs-lg); font-family: var(--font-display); border-bottom: 1px solid var(--color-border); }
  .site-header:not(.is-scrolled) .main-nav.is-open a { color: var(--color-green-900); }

  /* The number is hidden visually, never from assistive tech: `display: none`
     removed it from the accessibility tree and left the main call-to-action
     announced as a bare "link". */
  .header-actions .btn-phone span {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .header-actions .btn-phone { padding: 10px; }
  .nav-toggle { display: inline-flex; }
  .nav-indicator { display: none; }

  .hero-content { padding-block: var(--space-8) var(--space-7); }
  .usp-grid { grid-template-columns: 1fr; gap: var(--space-4); }
  .services-grid { grid-template-columns: 1fr; }
}

@media (max-width: 560px) {
  .container { padding-inline: var(--space-4); }
  .hero h1 { font-size: clamp(2.2rem, 1.6rem + 6vw, 3rem); }
  .btn { padding: 13px 20px; }
  .rating-badge { font-size: 0.8125rem; padding: 6px 12px; gap: 6px; }
  .rating-stars svg { width: 12px; height: 12px; }
  .rating-google { display: none; }
}

/* ============================================================
   404 page
   ============================================================ */
.not-found {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-6);
  background: var(--color-bg);
}
.not-found .eyebrow { color: var(--color-terracotta-dark); }
.not-found h1 {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 2rem + 3vw, 4rem);
  font-weight: 600;
  color: var(--color-green-900);
  margin-bottom: var(--space-4);
}
.not-found p {
  color: var(--color-ink-soft);
  font-size: var(--fs-md);
  max-width: 44ch;
  margin-bottom: var(--space-6);
}
.not-found img { height: 40px; width: auto; margin-bottom: var(--space-6); }

/* ============================================================
   Print — someone printing this page wants the address,
   the opening hours and the phone number. Nothing else.
   ============================================================ */
@media print {
  /* Reveal animations must never withhold content on paper. */
  .js .reveal,
  .js .reveal.is-visible,
  .js .thesis-line .word,
  .js [data-thesis-fade] {
    opacity: 1 !important;
    translate: none !important;
    transform: none !important;
    transition: none !important;
  }

  /* Chrome */
  * { -webkit-print-color-adjust: exact; print-color-adjust: exact; }

  body { background: #fff; color: #000; font-size: 11pt; }

  /* Decoration and navigation carry no meaning on paper. */
  .site-header,
  .scroll-progress,
  .scroll-cue,
  .hero-media,
  .gallery,
  .season,
  .footer-nav,
  .contact-map,
  .rating-badge,
  .service-card img,
  .about-media,
  .delivery-media { display: none !important; }

  .hero { min-height: auto; color: #000; padding-block: 0 1cm; }
  .hero-scrim { display: none; }
  .hero h1 { font-size: 24pt; color: #000; }
  .hero-lead { color: #000; }
  .hero-actions { display: none; }

  .usp, .delivery-grid, .site-footer { background: none !important; color: #000 !important; }
  .usp-item strong, .usp-item span,
  .delivery h2, .delivery-text p,
  .site-footer, .footer-brand p { color: #000 !important; }

  section { padding-block: 0.5cm !important; break-inside: avoid; }
  .contact-grid { display: block; }
  .hours-table span { color: #000 !important; }

  /* Print the phone number and address as text, not as a dead button. */
  .btn { display: none !important; }
  a[href^="tel:"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  a[href^="tel:"] { color: #000 !important; }

  h1, h2, h3 { break-after: avoid; color: #000 !important; }
}

/* ============================================================
   Draft banner — moved out of inline styles: the CSP forbids
   style attributes, so inline styling would be stripped on the
   Apache/Hostinger target and the banner would render raw.
   ============================================================ */
.draft-banner {
  background: oklch(0.240 0.012 60);
  color: var(--paper);
  padding: 10px var(--space-5);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  align-items: center;
  font-size: 0.82rem;
  line-height: 1.45;
}
.draft-banner-tag {
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-family: ui-monospace, monospace;
}
.draft-banner span:last-child { opacity: 0.85; }

/* ============================================================
   Legal pages (Impressum, Datenschutz)
   ============================================================ */
.legal { padding-block: var(--space-8) var(--space-9); background: var(--bg); }
.legal-inner { max-width: 68ch; }
.legal-back {
  display: inline-block;
  margin-bottom: var(--space-6);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--green-700);
}
.legal-back:hover { color: var(--accent); }
.legal h1 {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.6rem + 1.8vw, 2.75rem);
  font-weight: 600;
  color: var(--green-900);
  margin-bottom: var(--space-6);
}
.legal h2 {
  font-size: var(--fs-lg);
  margin-top: var(--space-7);
  margin-bottom: var(--space-3);
}
.legal p, .legal li { color: var(--ink); font-size: var(--fs-base); }
.legal p { margin-bottom: var(--space-4); }
.legal ul { list-style: disc; padding-left: 1.4em; margin-bottom: var(--space-4); }
.legal li { margin-bottom: var(--space-2); }
.legal a { color: var(--green-700); text-decoration: underline; text-underline-offset: 3px; }
.legal a:hover { color: var(--accent); }
.legal em {
  background: oklch(0.942 0.055 90);
  padding: 1px 5px;
  border-radius: 3px;
  font-style: normal;
  color: oklch(0.380 0.070 60);
}
.legal-todo {
  border-left: 3px solid var(--accent);
  background: var(--bg-alt);
  padding: var(--space-5);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  margin-bottom: var(--space-7);
  font-size: var(--fs-sm);
  color: var(--muted);
}
.legal-todo strong { display: block; color: var(--green-900); margin-bottom: var(--space-2); }
.legal-todo em { background: none; padding: 0; color: inherit; font-style: italic; }

/* Footer legal links + AI disclosure */
.footer-legal { margin-top: var(--space-2); }
.footer-legal a { text-decoration: underline; text-underline-offset: 3px; }
.footer-legal a:hover { color: var(--paper); }
.footer-disclosure {
  margin-top: var(--space-3);
  max-width: 62ch;
  font-size: var(--fs-xs);
  opacity: 0.72;
}

/* Available to screen readers and voice control, invisible on screen.
   Preferred over aria-label wherever visible text also exists, so the
   accessible name always contains what the user can actually read. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ============================================================
   Öffnungsstatus-Chip
   Sitzt neben jeder Telefonnummer. Der Punkt ist Dekoration —
   die Aussage steht immer als Text daneben, damit sie nicht
   allein an einer Farbe hängt.
   ============================================================ */
.open-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--surface);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.4;
  color: var(--muted);
}
.open-status__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

/* Sechs Zustände. Alle Textfarben gegen ihre Fläche gerechnet. */
.open-status--open    { color: oklch(0.430 0.090 150); border-color: oklch(0.430 0.090 150 / .3); background: oklch(0.960 0.030 150); }
.open-status--closing { color: oklch(0.470 0.100 70);  border-color: oklch(0.470 0.100 70 / .3);  background: oklch(0.960 0.040 85); }
.open-status--opening { color: oklch(0.470 0.100 70);  border-color: oklch(0.470 0.100 70 / .3);  background: oklch(0.960 0.040 85); }
.open-status--closed,
.open-status--holiday,
.open-status--vacation { color: var(--muted); border-color: var(--color-border); background: var(--bg-alt); }

/* Auf dunklen Flächen (Hero, Lieferservice, Footer) */
.hero .open-status,
.delivery .open-status,
.site-footer .open-status {
  background: oklch(0.976 0.008 84 / .12);
  border-color: oklch(0.976 0.008 84 / .25);
  color: var(--paper);
}
.hero .open-status--open,
.delivery .open-status--open,
.site-footer .open-status--open { color: oklch(0.880 0.090 150); }
.hero .open-status--closing, .hero .open-status--opening,
.delivery .open-status--closing, .delivery .open-status--opening,
.site-footer .open-status--closing, .site-footer .open-status--opening { color: var(--sand); }

.hero-status { margin-top: var(--space-4); }
.contact-status { margin-top: var(--space-3); }
.footer-status { margin-top: var(--space-3); }

/* Zurück nach oben — Pflichtelement im Footer */
.footer-top-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.footer-top-link:hover { color: var(--paper); }

@media print {
  .open-status { border: none; background: none !important; color: #000 !important; padding: 0; }
  .footer-top-link { display: none; }
}

/* ============================================================
   Unterseiten (Kosten, Ablauf, Stellen)
   ============================================================ */
/* Die Kopfzeile ist fixiert und liegt damit über dem Inhalt. Auf der
   Startseite ist das gewollt — der Hero läuft darunter durch. Eine Unterseite
   beginnt aber mit Text, und der stand bisher zur Hälfte hinter der Kopfzeile.
   Deshalb ihre Höhe als Innenabstand einrechnen statt einen festen Wert zu
   raten: --header-h ändert sich beim Breakpoint mit. */
.subpage { padding-block: calc(var(--header-h) + var(--space-6)) var(--space-9); }
.subpage-inner { max-width: 72ch; }

/* Breadcrumbs — Pflicht auf jeder Seite außer der Startseite,
   sichtbar auf der Seite, nicht nur im Schema. */
.breadcrumb {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-bottom: var(--space-6);
}
.breadcrumb ol { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.breadcrumb li { display: flex; align-items: center; gap: 6px; }
.breadcrumb li:not(:last-child)::after { content: "›"; color: var(--color-border-strong); }
.breadcrumb a { color: var(--green-700); text-decoration: underline; text-underline-offset: 3px; }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb [aria-current="page"] { color: var(--muted); }

.subpage h1 {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.5rem + 2.2vw, 3rem);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--green-900);
  margin-bottom: var(--space-4);
  text-wrap: balance;
}
.subpage-lead {
  font-size: var(--fs-md);
  color: var(--muted);
  margin-bottom: var(--space-7);
  max-width: 58ch;
}
.subpage h2 {
  font-size: var(--fs-xl, 1.75rem);
  margin-top: var(--space-8);
  margin-bottom: var(--space-4);
}
.subpage h3 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--green-900);
  margin-bottom: var(--space-2);
}
.subpage p { color: var(--ink); margin-bottom: var(--space-4); }
.subpage p.muted { color: var(--muted); }

/* Auszufüllende Angaben. Bewusst auffällig: was hier steht, ist
   noch nicht bestätigt und darf so nicht live gehen. */
/* Beispielwert statt Leerstelle: Die Seite soll zeigen, wie sie fertig wirkt,
   ohne dass jemand die Zahl für bestätigt hält. Deshalb dieselbe gelbe Fläche
   wie bei .fill-in plus ein hochgestelltes DEMO an jedem einzelnen Wert — eine
   Fußnote am Seitenende würde beim Überfliegen untergehen, und genau beim
   Überfliegen entstehen falsche Erwartungen. */
.demo-value {
  background: oklch(0.945 0.060 90);
  color: oklch(0.380 0.075 60);
  padding: 1px 6px;
  border-radius: 4px;
  font-weight: 600;
  white-space: normal;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.demo-value::after {
  content: "DEMO";
  margin-left: 4px;
  font-size: 0.55em;
  font-weight: 700;
  letter-spacing: 0.08em;
  vertical-align: 0.45em;
  opacity: 0.75;
  font-family: ui-monospace, monospace;
}
/* Im Druck trägt Farbe nicht — dort muss die Kennzeichnung als Text stehen. */
@media print {
  .demo-value { background: none; border: 1px solid #000; }
}

.fill-in {
  background: oklch(0.945 0.060 90);
  color: oklch(0.380 0.075 60);
  padding: 1px 7px;
  border-radius: 4px;
  font-style: normal;
  font-weight: 600;
  /* Kein `white-space: nowrap`. Das hielt kurze Platzhalter wie „ab … €"
     zusammen, sprengte aber jeden Platzhalter, der ein ganzer Satz ist: der
     Überlauf weitet auf dem Handy den Layout-Viewport, und die fixierte
     Kopfzeile wird auf Dokumentbreite mitgezogen. Umbrechen darf er also —
     `clone` sorgt dafür, dass Hintergrund und Innenabstand auf jeder Zeile
     sauber sitzen statt nur am Anfang und Ende. */
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.note {
  border-left: 3px solid var(--accent);
  background: var(--bg-alt);
  padding: var(--space-5);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  margin-bottom: var(--space-7);
  font-size: var(--fs-sm);
  color: var(--muted);
}
.note strong { display: block; color: var(--green-900); margin-bottom: var(--space-2); }

/* Preisspannen */
.price-list { margin-bottom: var(--space-6); }
.price-list > li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-4);
  padding-block: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}
.price-list > li:last-child { border-bottom: none; }
.price-list .price-what strong { display: block; color: var(--green-900); }
.price-list .price-what span { font-size: var(--fs-sm); color: var(--muted); }
.price-list .price-range {
  font-family: var(--font-display);
  font-weight: 600;
  white-space: nowrap;
  color: var(--green-900);
}

/* Ablauf in Schritten */
.steps { counter-reset: step; margin-bottom: var(--space-6); }
.steps > li {
  counter-increment: step;
  position: relative;
  padding-left: 56px;
  padding-bottom: var(--space-6);
}
.steps > li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 36px;
  height: 36px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--green-900);
  color: var(--sand);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-sm);
}
/* Verbindungslinie zwischen den Schritten */
.steps > li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 17.5px;
  top: 42px;
  bottom: 8px;
  width: 1px;
  background: var(--color-border);
}
.steps > li:last-child { padding-bottom: 0; }

/* DEMO-Kennzeichnung */
.demo-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  background: oklch(0.240 0.012 60);
  color: var(--paper);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-family: ui-monospace, monospace;
}
/* An Bildern: sitzt auf der Fläche, die sonst als Beweis gelesen wird */
/* `relative` nur dort, wo das Element noch keinen Bezugsrahmen hat.
   .hero-media ist absolut positioniert und liegt als Ebene hinter dem Text —
   ein `relative` macht daraus ein Flex-Kind neben dem Text und sprengt die
   Hero-Höhe. Ein absolut positioniertes Element ist ohnehin Bezugsrahmen
   genug für das ::after. */
.demo-mark { position: relative; }
.hero-media.demo-mark { position: absolute; }
.demo-mark::after {
  content: "DEMO";
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  padding: 3px 8px;
  border-radius: 999px;
  background: oklch(0.240 0.012 60 / 0.82);
  color: oklch(0.976 0.008 84);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  font-family: ui-monospace, monospace;
  pointer-events: none;
}
.hero .demo-mark::after { top: auto; bottom: 16px; right: 16px; left: auto; }

/* ============================================================
   Wegweiser unter dem Hero
   ============================================================ */
/* Ein Viertel des üblichen Abschnitts-Polsters: Eine einzeilige Leiste in
   einem Feld Leerraum behauptet wieder die Wichtigkeit, die ihr die
   schmucklose Gestaltung gerade genommen hat. Nur unten eine Haarlinie —
   oben grenzt bereits die Merkmalsleiste ab, zwei Linien ergäben einen
   sichtbaren Doppelstrich. */
.wegweiser {
  background: var(--bg);
  border-bottom: 1px solid var(--color-border);
}
.wegweiser-inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding-block: var(--space-6);
}
.wegweiser h2 {
  margin: 0;
  flex-shrink: 0;
}
.wegweiser ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-7);
  align-items: baseline;
  list-style: none;
  padding: 0;
  margin: 0;
}
.wegweiser a {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: var(--fs-base);
  font-weight: 600;
  color: var(--green-900);
  text-decoration: underline;
  text-decoration-color: var(--color-border-strong);
  text-underline-offset: 5px;
  transition: color var(--duration-fast) var(--ease-out), text-decoration-color var(--duration-fast) var(--ease-out);
}
.wegweiser a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
/* Der direkte Weg zum Telefon ist der einzige farbige Eintrag — er richtet
   sich an die Person, die nicht mehr lesen, sondern anrufen will. */
.wegweiser .wegweiser-direkt { color: var(--accent); }
.pfeil {
  display: inline-block;
  color: var(--muted);
  transition: transform var(--duration-base) var(--ease-out);
}
.wegweiser a:hover .pfeil { transform: translateX(3px); }
.wegweiser a:hover .pfeil-runter { transform: translateY(3px); }
@media (prefers-reduced-motion: reduce) {
  .pfeil { transition: none; }
  .wegweiser a:hover .pfeil,
  .wegweiser a:hover .pfeil-runter { transform: none; }
}
/* Ab Tablet nebeneinander: Überschrift links, Ziele rechts daneben. */
@media (min-width: 900px) {
  .wegweiser-inner {
    flex-direction: row;
    align-items: baseline;
    gap: var(--space-7);
    padding-block: var(--space-7);
  }
  .wegweiser h2 { width: 14rem; }
}
/* Im Druck ist ein Wegweiser sinnlos — Papier kann nicht springen. */
@media print { .wegweiser { display: none; } }

/* Verweise auf die Anlass-Seiten in der Sortiments-Kachel */
.service-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
  margin-top: var(--space-3);
}
.service-links a {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--green-700);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.service-links a:hover { color: var(--accent); }

.anlass-links { margin: var(--space-4) 0 var(--space-6); padding-left: 0; list-style: none; }
.anlass-links li { margin-bottom: var(--space-3); }
.anlass-links a {
  font-weight: 600;
  color: var(--green-700);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.anlass-links a:hover { color: var(--accent); }

/* Die Trauerseite bekommt bewusst KEIN Bild — dort wäre Bildschmuck deplatziert.
   Diese Klasse gilt nur für Anlässe, bei denen das Aussehen Teil der
   Kaufentscheidung ist. */
.anlass-bild {
  margin: var(--space-6) 0 var(--space-7);
  border-radius: var(--radius-md);
  overflow: hidden;
  position: relative;
}
.anlass-bild img {
  display: block;
  width: 100%;
  height: auto;          /* Pflicht neben width/height-Attributen, sonst Streckung */
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.anlass-checkliste {
  margin: var(--space-4) 0 var(--space-5);
  padding-left: var(--space-5);
}
.anlass-checkliste li { margin-bottom: var(--space-2); color: var(--ink); }

/* Direktpfad im Trauerfall. Steht bewusst weit oben und ohne Bildschmuck:
   Wer hier landet, sucht eine Telefonnummer, keine Gestaltung. */
.soforthilfe {
  margin: var(--space-5) 0 var(--space-7);
  padding: var(--space-5);
  border-left: 3px solid var(--accent);
  background: var(--color-surface);
  border-radius: var(--radius-sm);
}
.soforthilfe p { margin: 0 0 var(--space-4); }
.soforthilfe .open-status { margin-top: var(--space-3); }

.subpage-cta {
  margin-top: var(--space-8);
  padding: var(--space-6);
  background: var(--green-900);
  border-radius: var(--radius-md);
  color: var(--paper);
}
.subpage-cta h2 { color: var(--paper); margin-top: 0; }
.subpage-cta p { color: oklch(0.976 0.008 84 / 0.82); }
.subpage-cta .open-status { margin-top: var(--space-4); }

@media print {
  .demo-mark::after { background: none; color: #000; border: 1px solid #000; }
}

.gallery-note {
  color: var(--muted);
  font-size: var(--fs-sm);
  max-width: 52ch;
  margin-top: var(--space-3);
}

/* Chip sitzt zwischen Fließtext und Buttons: die Frage "haben die auf?"
   wird beantwortet, bevor zum Anruf aufgefordert wird. */
.hero-status { margin-top: 0; margin-bottom: var(--space-4); }

/* Flache Displays (iPhone SE und Co.): Der Hero-Stapel aus Bewertung,
   Überschrift, Fließtext, Status und zwei Buttons passt bei 667px Höhe
   sonst nicht über die Falz — und der Anruf-Button ist das, wofür die
   Seite existiert. Verdichtet den Rhythmus, ändert nicht das Konzept. */
@media (max-height: 720px) and (max-width: 860px) {
  .hero-content { padding-block: var(--space-6) var(--space-5); }
  .hero h1 {
    font-size: clamp(1.85rem, 1.3rem + 4.4vw, 2.4rem);
    margin-bottom: var(--space-3);
  }
  .hero-lead {
    font-size: var(--fs-base);
    margin-bottom: var(--space-4);
  }
  .rating-badge { margin-bottom: var(--space-3); }
  .hero .eyebrow { margin-bottom: var(--space-2); }
  .hero-status { margin-bottom: var(--space-3); }
  /* Der Pfeil kostet genau den Platz, den der CTA braucht — und dass es
     weitergeht, zeigt der angeschnittene nächste Abschnitt ohnehin. */
  .scroll-cue { display: none; }
}

/* Querformat auf dem Handy: bei ~360px Höhe ist der Inhalt höher als das
   Fenster, egal wie eng man setzt. Der Fließtext tritt zurück — Überschrift,
   Öffnungsstatus und Anruf-Button tragen die Aussage auch allein. */
@media (max-height: 500px) and (max-width: 900px) {
  .hero-lead { display: none; }
  /* Bewertung und Eyebrow würden bei dieser Höhe oben abgeschnitten —
     abgeschnitten ist schlechter als bewusst weggelassen. Beide stehen
     weiter unten auf der Seite noch einmal. */
  .hero .eyebrow,
  .hero .rating-badge { display: none; }
  .hero h1 { font-size: 1.65rem; margin-bottom: var(--space-3); }
  .hero-content { padding-block: var(--space-4) var(--space-4); }
}

/* Foto des Ladens im Kontaktbereich. Bewusst mit Bildunterschrift: Das Bild
   erklärt nicht sich selbst, sondern wofür es da ist — Wiedererkennung an der
   Straße. Ohne Unterschrift liest es sich als Dekoration. */
.contact-foto {
  margin: 0 0 var(--space-6);
  border-radius: var(--radius-md);
  overflow: hidden;
}
.contact-foto img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
}
.contact-foto figcaption {
  margin-top: var(--space-2);
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* Ortsliste im Liefergebiet — mehrspaltig, damit 8 Ortsteile nicht als
   lange dünne Spalte dastehen. */
.ort-liste {
  list-style: none;
  padding: 0;
  margin: var(--space-3) 0 var(--space-4);
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 6px var(--space-4);
}
.ort-liste li {
  padding-left: 18px;
  position: relative;
  color: var(--ink);
}
.ort-liste li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.55em;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

/* Bewertungen im Volltext */
.stimmen { list-style: none; padding: 0; margin: var(--space-5) 0 var(--space-7); }
.stimmen li {
  border-left: 3px solid var(--color-border-strong);
  padding: 2px 0 2px var(--space-5);
  margin-bottom: var(--space-5);
}
.stimme-text {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  line-height: 1.45;
  color: var(--green-900);
  margin-bottom: var(--space-2);
}
.stimme-quelle { font-size: var(--fs-sm); color: var(--muted); margin: 0; }

/* ============================================================
   FAQ
   ============================================================ */
.faq { background: var(--bg-alt); padding-block: var(--space-9); }
.faq-inner { max-width: 74ch; }
.faq h2 { margin-bottom: var(--space-7); }
.faq-liste { border-top: 1px solid var(--color-border); }
.faq details {
  border-bottom: 1px solid var(--color-border);
}
.faq summary {
  /* list-style: none entfernt das Standard-Dreieck in Firefox,
     ::-webkit-details-marker in Safari/Chrome. Beide nötig. */
  list-style: none;
  cursor: pointer;
  padding: var(--space-4) 40px var(--space-4) 0;
  position: relative;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--green-900);
  /* Tippziel nach WCAG 2.5.8 — die ganze Zeile ist klickbar, nicht nur der Text. */
  min-height: 44px;
  display: flex;
  align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
/* Eigenes Zeichen: + wird beim Aufklappen zu −, gedreht statt getauscht,
   damit die Bewegung den Zustandswechsel zeigt. */
.faq summary::after {
  content: "";
  position: absolute;
  right: 8px;
  top: 50%;
  width: 14px;
  height: 2px;
  background: var(--accent);
  transform: translateY(-50%);
}
.faq summary::before {
  content: "";
  position: absolute;
  right: 14px;
  top: 50%;
  width: 2px;
  height: 14px;
  background: var(--accent);
  transform: translateY(-50%) rotate(0deg);
  transition: transform var(--duration-base) var(--ease-out), opacity var(--duration-base) var(--ease-out);
}
.faq details[open] summary::before { transform: translateY(-50%) rotate(90deg); opacity: 0; }
.faq summary:hover { color: var(--accent); }
.faq summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
.faq details p {
  margin: 0 0 var(--space-5);
  padding-right: 40px;
  color: var(--muted);
  line-height: 1.7;
}
.faq details a { color: var(--green-700); text-decoration: underline; text-underline-offset: 3px; }
.faq details a:hover { color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .faq summary::before { transition: none; }
}
/* Im Druck alle Antworten offen — Papier kann nicht aufklappen. */
@media print {
  .faq details > p { display: block !important; }
}


/* ============================================================
   Anlässe (Trauer & Hochzeit) und Arbeiten bei uns
   ============================================================ */
.anlaesse { padding-block: var(--space-9); background: var(--bg); }
.anlaesse h2 { margin-bottom: var(--space-7); }
.anlass-paar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--space-7);
}
/* Nur eine Haarlinie links statt Kasten oder Schatten: Die beiden Blöcke sind
   gleichrangig, und eine Karte mit Hebung würde beim Trauerfall wie ein
   Angebot wirken. */
.anlass-block {
  border-left: 2px solid var(--color-border-strong);
  padding-left: var(--space-5);
}
.anlass-block h3 {
  font-family: var(--font-display);
  font-size: var(--fs-xl, 1.6rem);
  font-weight: 600;
  color: var(--green-900);
  margin-bottom: var(--space-3);
}
.anlass-block p { color: var(--muted); line-height: 1.7; margin-bottom: var(--space-4); }
.anlass-link { margin-bottom: 0; }
.anlass-link a {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-weight: 600;
  color: var(--green-700);
  text-decoration: underline;
  text-underline-offset: 4px;
  transition: color var(--duration-fast) var(--ease-out);
}
.anlass-link a:hover { color: var(--accent); }
.anlass-link a:hover .pfeil { transform: translateX(3px); }

.arbeiten { padding-block: var(--space-8); background: var(--bg-alt); }
.arbeiten-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5) var(--space-7);
}
.arbeiten h2 { margin-bottom: var(--space-3); }
.arbeiten p { color: var(--muted); max-width: 58ch; margin: 0; }
.arbeiten-link { flex-shrink: 0; }

/* ============================================================
   Zonenkarte Liefergebiet
   ============================================================ */
.zonenkarte {
  margin: var(--space-8) auto 0;
  max-width: 820px;
}
.zonenkarte svg { width: 100%; height: auto; display: block; }

/* Die drei Zonen: nach außen blasser. Keine Umrisslinie bei den äußeren —
   eine gestrichelte Kante behauptet eine Grenze, die es so nicht gibt.
   Nur die innerste bekommt eine Kontur, weil dort das Versprechen gilt
   („in der Regel am selben Tag"). */
.zonenkarte .zone { fill: var(--sand); stroke: none; }
.zonenkarte .zone-3 { fill-opacity: 0.16; }
.zonenkarte .zone-2 { fill-opacity: 0.20; }
.zonenkarte .zone-1 {
  fill-opacity: 0.30;
  stroke: var(--accent);
  stroke-opacity: 0.55;
  stroke-width: 1.5;
}

/* Die Weser bleibt im Neutralton: Die Seite hat genau eine gesättigte Farbe.
   Ein blauer Fluss wäre die zweite — beschriftet ist er ohnehin. */
.zonenkarte .fluss path {
  fill: none;
  stroke: oklch(0.905 0.014 84);
  stroke-width: 22;
  stroke-linecap: round;
}
.zonenkarte .fluss-name {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.08em;
  fill: var(--muted);
  opacity: 0.75;
  text-anchor: middle;
}

/* Straßen: durchgezogen statt gestrichelt. Eine gestrichelte Linie liest sich
   als „ungefähr" — hier steht sie für eine Fahrt, die tatsächlich stattfindet. */
.zonenkarte .strassen path {
  fill: none;
  stroke: var(--accent);
  stroke-opacity: 0.22;
  stroke-width: 2;
  stroke-linecap: round;
}

.zonenkarte text {
  font-family: var(--font-body);
  text-anchor: middle;
  font-size: 14px;
}
.zonenkarte .zn {
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  fill: var(--muted);
}
.zonenkarte .zn-1 { fill: var(--accent-deep); }
/* Näher = dunkler. Trägt dieselbe Abstufung wie die Flächen, ohne ein
   weiteres Zeichen zu brauchen. */
.zonenkarte .orte-1 text { fill: var(--ink); font-weight: 600; }
.zonenkarte .orte-2 text { fill: var(--muted); }
.zonenkarte .orte-3 text { fill: var(--muted); opacity: 0.82; font-size: 13px; }

.zonenkarte .punkt { fill: var(--accent); }
.zonenkarte .puls { fill: var(--accent); opacity: 0.3; }
.zonenkarte .standort text {
  font-weight: 700;
  font-size: 14px;
  fill: var(--green-900);
}

.zonenkarte .wagen-form rect,
.zonenkarte .wagen-form path { fill: var(--accent); }
.zonenkarte .wagen-form .rad { fill: var(--green-900); }

.zonenkarte figcaption {
  margin-top: var(--space-3);
  font-size: var(--fs-sm);
  color: var(--muted);
  text-align: center;
}
.zonenkarte figcaption a {
  color: var(--green-700);
  text-decoration: underline;
  text-underline-offset: 3px;
  margin-left: 6px;
}
.zonenkarte figcaption a:hover { color: var(--accent); }

/* --- Aufbau beim Hereinscrollen ---
   Reihenfolge = Leserichtung: erst die Landmarke (Weser), dann die Flächen von
   innen nach außen, dann Straßen und Beschriftung, zuletzt die Wagen. Wer
   zuschaut, bekommt die Karte in der Reihenfolge erklärt, in der man sie liest.
   Ohne JavaScript steht alles sofort. */
.js .zonenkarte .fluss,
.js .zonenkarte .fluss-name,
.js .zonenkarte .zone,
.js .zonenkarte .strassen,
.js .zonenkarte .zn,
.js .zonenkarte .orte text,
.js .zonenkarte .standort > *,
.js .zonenkarte .fahrzeuge { opacity: 0; }

.js .zonenkarte.is-visible .fluss,
.js .zonenkarte.is-visible .fluss-name { animation: karte-ein 700ms var(--ease-out) both; }

.js .zonenkarte.is-visible .zone {
  animation: karte-flaeche 800ms var(--ease-out) both;
  transform-origin: 360px 330px;
}
.js .zonenkarte.is-visible .zone-1 { animation-delay: 220ms; }
.js .zonenkarte.is-visible .zone-2 { animation-delay: 400ms; }
.js .zonenkarte.is-visible .zone-3 { animation-delay: 560ms; }

.js .zonenkarte.is-visible .standort > * { animation: karte-ein 500ms var(--ease-out) 340ms both; }
.js .zonenkarte.is-visible .zn-1        { animation: karte-ein 500ms var(--ease-out) 480ms both; }
.js .zonenkarte.is-visible .orte-1 text { animation: karte-ein 500ms var(--ease-out) 520ms both; }
.js .zonenkarte.is-visible .zn-2        { animation: karte-ein 500ms var(--ease-out) 640ms both; }
.js .zonenkarte.is-visible .orte-2 text { animation: karte-ein 500ms var(--ease-out) 680ms both; }
.js .zonenkarte.is-visible .zn-3        { animation: karte-ein 500ms var(--ease-out) 800ms both; }
.js .zonenkarte.is-visible .orte-3 text { animation: karte-ein 500ms var(--ease-out) 840ms both; }

/* Die Straßen zeichnen sich, statt zu erscheinen — das zeigt die Fahrtrichtung
   vom Laden nach außen, bevor der erste Wagen losfährt. */
.js .zonenkarte.is-visible .strassen { opacity: 1; }
.js .zonenkarte.is-visible .strassen path {
  stroke-dasharray: 620;
  stroke-dashoffset: 620;
  animation: strasse-zeichnen 1100ms var(--ease-out) 900ms both;
}
.js .zonenkarte.is-visible .fahrzeuge { animation: karte-ein 600ms var(--ease-out) 1700ms both; }

/* Der Standortpunkt pulst weiter — er markiert den Ort, um den es geht. */
.js .zonenkarte.is-visible .puls {
  animation: karte-ein 500ms var(--ease-out) 340ms both,
             karte-puls 3000ms ease-in-out 1200ms infinite;
  transform-origin: 360px 330px;
}

@keyframes karte-ein     { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
@keyframes karte-flaeche { from { opacity: 0; transform: scale(0.9); }      to { opacity: 1; transform: scale(1); } }
@keyframes strasse-zeichnen { to { stroke-dashoffset: 0; } }
@keyframes karte-puls    { 0%, 100% { transform: scale(1); opacity: 0.3; } 50% { transform: scale(1.8); opacity: 0.06; } }

/* Bei reduzierter Bewegung: alles sofort da, nichts wächst, nichts pulst,
   und die Wagen fahren nicht. Ein stehendes Fahrzeug erklärt nichts — SMIL
   lässt sich per Media Query nicht anhalten, also kommt es weg. */
@media (prefers-reduced-motion: reduce) {
  .js .zonenkarte.is-visible .fluss,
  .js .zonenkarte.is-visible .fluss-name,
  .js .zonenkarte.is-visible .zone,
  .js .zonenkarte.is-visible .zn,
  .js .zonenkarte.is-visible .orte text,
  .js .zonenkarte.is-visible .standort > *,
  .js .zonenkarte.is-visible .puls {
    animation: karte-ein 1ms linear both;
  }
  .js .zonenkarte.is-visible .strassen path { animation: none; stroke-dasharray: none; stroke-dashoffset: 0; }
  .zonenkarte .fahrzeuge { display: none; }
}

@media (max-width: 620px) {
  /* Vierzehn Ortsnamen laufen auf 390px ineinander. Das Umland tritt zurück —
     seine Orte stehen vollständig auf der Liefergebietsseite; hier zählt,
     dass es drei Zonen gibt und wo der Laden liegt. */
  .zonenkarte .orte-1 text { font-size: 17px; }
  .zonenkarte .orte-2 text { font-size: 16px; }
  .zonenkarte .orte-3 { display: none; }
  /* "Woltmershausen" ist der längste Name der Karte und stößt bei größerer
     Schrift mit dem Zonennamen zusammen. Auf dem Handy zählt die Struktur,
     nicht die Vollständigkeit — die Liste steht auf liefergebiet.html. */
  .zonenkarte .orte-2 text:nth-of-type(4) { display: none; }
  .zonenkarte .zn { font-size: 15px; }
  .zonenkarte .standort text { font-size: 17px; }
  .zonenkarte .fluss-name { font-size: 16px; }
}
