/* ============================================================
   CAFÉ DÉLICE — style.css
   Design tokens carried over from the previous build.
   Mobile-first · Parisian bistro aesthetic
   ============================================================ */

/* ── Self-hosted fonts ──────────────────────────────────────────
   Self-hosted (no Google Fonts CDN request) — closes the "no
   third-party requests on load" gap flagged in the legal review.
   Regenerate with scripts/fetch-fonts.sh (manual, never part of the
   build — the four woff2 files below are committed). Variable fonts
   where the source has one, so a single file covers the weight range
   actually used instead of shipping a file per weight. */
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter.woff2') format('woff2-variations');
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Playfair Display';
  src: url('/assets/fonts/playfair.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Playfair Display';
  src: url('/assets/fonts/playfair-italic.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: 'Monsieur La Doulaise';
  src: url('/assets/fonts/monsieur-la-doulaise-subset.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Metric-matched fallback, so the swap from system font to webfont costs no
   layout shift. One fallback face covers both Playfair weights/styles here
   (upright-metrics matched) — a still-simpler version of the two-fallback
   split (separate italic metrics) a full layout pass could add later; this
   is the one place this build intentionally trades a little swap-in
   precision for not touching every var(--font-display) call site yet. */
@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial'), local('Helvetica'), local('Liberation Sans');
  size-adjust: 107.6%;
  ascent-override: 90.1%;
  descent-override: 22.4%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Playfair Fallback';
  src: local('Georgia'), local('Times New Roman'), local('Liberation Serif');
  size-adjust: 95.8%;
  ascent-override: 113.0%;
  descent-override: 26.2%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Monsieur La Doulaise Fallback';
  src: local('Georgia'), local('Times New Roman'), local('Liberation Serif');
  size-adjust: 85.7%;
  ascent-override: 122.2%;
  descent-override: 59.8%;
  line-gap-override: 0%;
}

/* ── Variables ─────────────────────────────────────────────── */
:root {
  --cream:       #f4f4f2;
  --cream-dark:  #e6e6e3;
  --green:       #13501b;
  --green-light: #e4ede6;
  --ink:         #1a1a18;
  --ink-light:   #5c5c5a;
  --charcoal:    #2e2e2c;
  --white:       #ffffff;
  --muted-on-dark: #9a9a97;

  --font-display: 'Playfair Display', 'Playfair Fallback', Georgia, serif;
  --font-body:    'Inter', 'Inter Fallback', system-ui, sans-serif;
  --font-logo:    'Monsieur La Doulaise', 'Monsieur La Doulaise Fallback', cursive;

  --radius:   4px;
  --shadow:   0 2px 16px rgba(30,26,23,0.10);
  --shadow-lg:0 8px 40px rgba(30,26,23,0.16);

  --max-width: 1100px;
  --section-gap: 5rem;
  --header-h: 48px;
  --action-bar-h: 56px;
}

/* ── Reset ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  font-size: 16px;
  /* Disable mobile browsers' automatic text-size boosting — without this,
     WebKit/Chrome can inflate/shrink text differently per element based on
     its containing block's shape (e.g. a <ul> of short lines vs. a <p>),
     especially noticeable when the viewport shape changes in landscape. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  background: var(--charcoal);
  color: var(--ink);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

img { display: block; max-width: 100%; height: auto; }
a { color: var(--green); text-decoration: none; }
a:hover { text-decoration: underline; }
address { font-style: normal; }
ul { list-style: none; }

/* ── Typography ─────────────────────────────────────────────── */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  font-style: italic;
  line-height: 1.15;
  color: var(--green);
}

h1 {
  font-style: normal;
}

h1 { font-size: clamp(2.4rem, 6vw, 4rem); font-weight: 900; }
h2 { font-size: clamp(1.8rem, 4vw, 2.8rem); }
h3 { font-size: clamp(1.2rem, 2.5vw, 1.6rem); font-weight: 400; }

/* ── Layout helpers ─────────────────────────────────────────── */
.container {
  width: 100%;
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: 1.25rem;
}

/* ── Header / Nav ─────────────────────────────────────────────── */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background-color: transparent;
  /* background-color is in here on purpose: without it the transparent→cream
     swap snapped instantly while only the shadow faded, which read as abrupt.
     Now the whole handoff (background, shadow, and the logo/nav colours below,
     all 0.4s) animates together. */
  transition: background-color 0.4s ease, box-shadow 0.4s ease;
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: 0.6rem;
  line-height: 1;
}
.site-logo {
  font-family: var(--font-logo);
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--white);
  transition: color 0.4s ease;
}
.site-logo:hover {
  text-decoration: none;
}
.site-nav ul {
  display: flex;
  gap: 2rem;
}
.site-nav a {
  color: var(--white);
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  transition: color 0.4s ease;
}
.site-nav a:hover {
  text-decoration: none;
  opacity: 0.8;
}
.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.5rem;
}
.nav-toggle span {
  width: 24px;
  height: 2px;
  background: var(--white);
  transition: background-color 0.4s ease;
}

/* .scrolled is set server-side via the headerScrolled front-matter flag, for
   hero-less pages (delice-pur, impressum, speisekarte) whose header should
   just always read as "scrolled" (dark logo). .is-past-hero is the
   homepage's equivalent, toggled at runtime by main.js's header-handoff
   feature once the hero is ~60% scrolled (a bit before the fold fully
   passes). Both get identical styling. */
.site-header.scrolled,
.site-header.is-past-hero {
  /* Slightly translucent cream, with a backdrop blur so the green nav text
     stays legible over whatever busy photo scrolls behind it. */
  background-color: rgba(244, 244, 242, 0.82);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow);
}
.site-header.scrolled .site-logo,
.site-header.is-past-hero .site-logo {
  color: var(--green);
}
.site-header.scrolled .site-nav a,
.site-header.is-past-hero .site-nav a {
  color: var(--green);
}
.site-header.scrolled .nav-toggle span,
.site-header.is-past-hero .nav-toggle span {
  background: var(--green);
}

/* The homepage's served default suppresses the header wordmark — the hero
   carries one below it. Served suppressed so the duplicate is never painted
   for a frame; base.njk's <noscript> restores it without scripting.
   Colour is green even while hidden: the header wordmark is only ever shown
   over the cream header (scrolled past the hero), never white over the photo,
   so on scroll-up it fades out staying green instead of flashing to the base
   white as the is-past-hero colour is removed. */
.page-home .site-header .site-logo {
  color: var(--green);
  opacity: 0;
  visibility: hidden;
  transition: opacity .18s ease, visibility 0s linear .18s;
}
.page-home .site-header.is-past-hero .site-logo {
  opacity: 1;
  visibility: visible;
  transition: opacity .18s ease, visibility 0s;
}

@media (max-width: 720px) {
  .nav-toggle { display: flex; }
  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: rgba(244, 244, 242, 0.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    box-shadow: var(--shadow);
  }
  .site-nav.is-open {
    display: block;
  }
  .site-nav ul {
    flex-direction: column;
    gap: 0;
    padding: 0.5rem 1.25rem 1rem;
  }
  .site-nav a {
    display: block;
    padding: 0.75rem 0;
    color: var(--green);
  }
}

/* ── Hero ("fold") ────────────────────────────────────────────── */
.fold {
  background: var(--cream);
}
.fold-figure {
  position: relative;
  width: 100%;
  min-height: clamp(400px, 70vh, 700px);
  min-height: clamp(400px, 70dvh, 700px);
  margin: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: calc(var(--header-h) + 1rem) 1.25rem 1.25rem;
}
/* Out of flow, so the figure's height comes from the clamp above and never
   from the photograph's intrinsic ratio — keeps the image swap free of
   layout shift on every viewport. */
/* Taller than the figure and pulled up, so the parallax handler (main.js) can
   translate it a little without ever exposing the figure's cream edge. The
   15% buffer matches the handler's factor: the offset only reaches ~15% of the
   figure's height by the time the fold has fully scrolled off. */
.fold-figure > .fold-bg {
  position: absolute;
  top: -15%;
  left: 0;
  width: 100%;
  height: 130%;
  will-change: transform;
}
.fold-photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
}
/* Two layers, one pseudo-element each. The flat wash carries the wordmark's
   contrast over a high-key photograph; the gradient on top clears WCAG
   1.4.11 for the white hamburger/nav against a bright window in the shot. */
.fold-figure::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(12, 10, 8, 0.5), rgba(12, 10, 8, 0) 96px),
    rgba(12, 10, 8, 0.38);
}
/* Bottom-weighted scrim, deepening toward the status line at the bottom edge.
   Six stops rather than four: a coarser ramp bands visibly on wide-gamut
   phone displays, and a short steep one reads as a hard bar. */
.fold-figure::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to top,
      rgba(12, 10, 8, 0.82)  0%,
      rgba(12, 10, 8, 0.76) 18%,
      rgba(12, 10, 8, 0.62) 34%,
      rgba(12, 10, 8, 0.38) 48%,
      rgba(12, 10, 8, 0.12) 60%,
      rgba(12, 10, 8, 0)    70%);
}
.fold-content,
.hero-status {
  position: relative;
  z-index: 2;
  max-width: var(--max-width);
  width: 100%;
  margin-inline: auto;
  text-align: center;
}
.fold-content { margin-bottom: auto; margin-top: auto; }
/* The document h1. Real DOM text, not an image, so it's indexable, announced
   by a screen reader, and survives a failed image load. */
.fold-wordmark {
  margin: 0;
  font-family: var(--font-logo);
  font-size: clamp(3.25rem, 16vw, 7rem);
  font-style: normal;
  font-weight: 400;
  line-height: 1.2;
  color: var(--white);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.5);
}
.fold-subtitle {
  margin: 0.5rem 0 0;
  font-size: clamp(1rem, 2.6vw, 1.25rem);
  line-height: 1.45;
  color: var(--white);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.5);
}
/* One line of running text, not a flex row of three boxes — it must read and
   wrap as one sentence, since a flex row would break the status internally
   and strand the address on a line of its own. */
.hero-status {
  margin-top: 1.25rem;
  font-size: 0.9375rem;
  font-weight: 500;
  line-height: 1.6;
  text-wrap: balance;
  color: var(--white);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.55);
}
.hours-status,
.hero-address {
  display: inline;
  margin: 0;
  font-weight: inherit;
  color: inherit;
}
/* Reserves 44px against the moment the hours engine replaces the served
   fallback text, so the swap costs no layout shift. display: inline (the
   one-sentence wrap depends on it) makes the 44px a declared floor, not a
   box the layout grows to. */
.hero-status .hours-status { min-height: 44px; }
/* The address is a directions link and the only link here that must stay
   legible over an arbitrary photograph — --green on the scrim is unreadable,
   so it inherits the status line's white and takes a soft underline. */
.hero-address-link {
  color: inherit;
  text-decoration: none;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}
.hero-address-link:hover,
.hero-address-link:focus-visible {
  text-decoration: underline;
  text-decoration-color: currentColor;
}
/* Over the photograph the state accent is the dot alone — tinting 15px of
   text on a dark scrim costs more contrast than the signal is worth. Open
   and closing-soon get a lit dot, closed/unknown a dimmed one. */
.hours-status::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.45rem;
  vertical-align: 0.04em;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.45;
}
.hours-status[data-state="open"]::before,
.hours-status[data-state="closing-soon"]::before {
  background: #7fd68b;
  opacity: 1;
  box-shadow: 0 0 0 1px rgba(12, 10, 8, 0.35);
}
/* No dimming: the separator dot matches the "·" inside the status text
   (same weight, same opacity) so both middle dots read identically. */
.hero-status-sep { color: inherit; }
.fold-sentinel { height: 0; }

/* ── Sticky action bar ────────────────────────────────────────── */
/* Tier 1: the only layer that follows the user from route to route, in the
   one region a one-handed thumb reaches without regripping. */
.action-bar {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  min-width: 320px;
  z-index: 90;
  display: none;
  gap: 12px;
  padding: 0 12px;
  padding-bottom: env(safe-area-inset-bottom, 0px);
  height: calc(var(--action-bar-h) + env(safe-area-inset-bottom, 0px));
  background: var(--cream);
  border-top: 1px solid var(--cream-dark);
  box-shadow: 0 -2px 16px rgba(30, 26, 23, 0.10);
}
.action-bar-item {
  flex: 1 1 0;
  min-width: min(88px, 30%);
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-block: 6px;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--green);
  background: var(--green-light);
  border-radius: var(--radius);
}
.action-bar-item:hover { text-decoration: none; }

@media (max-width: 720px) {
  .action-bar { display: flex; }
  body { padding-bottom: calc(var(--action-bar-h) + env(safe-area-inset-bottom, 0px)); }

  /* On `/` the bar stays down until the fold sentinel clears, so it never
     sits over the hero — the hero-status line is the address/hours affordance
     on screen at scrollY 0, so no position leaves neither reachable. */
  .page-home .action-bar {
    transform: translateY(100%);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: transform .2s ease, opacity .2s ease, visibility 0s linear .2s;
  }
  .page-home.is-past-hero .action-bar {
    transform: none;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: transform .2s ease, opacity .2s ease, visibility 0s;
  }
}

/* ── Intro ────────────────────────────────────────────────────── */
.section-label {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--green);
  margin-bottom: 0.5rem;
}
.intro {
  background: var(--white);
}
.intro-inner {
  display: flex;
  min-height: 500px;
}
.intro-text {
  flex: 1 1 60%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 1rem;
  padding: 4rem 2rem;
}
.intro-break {
  display: none;
}
@media (min-width: 721px) {
  .intro-break {
    display: inline;
  }
}
.intro-body {
  color: var(--ink-light);
  max-width: 40ch;
}
.intro-since {
  color: var(--ink-light);
  margin-top: 0.75rem;
}
.intro-sign {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.3rem;
}
.intro-delice-teaser {
  margin-top: 1.5rem;
  color: var(--ink-light);
  max-width: 52ch;
}
.intro-delice-link {
  font-weight: 500;
  text-decoration: underline;
}
.intro-image {
  position: relative;
  flex: 1 1 40%;
}
.intro-image-photo {
  position: absolute;
  top: 20%;
  bottom: 20%;
  left: 20%;
  right: 0;
  background-size: cover;
  background-position: center;
}

@media (max-width: 720px) {
  .intro-inner {
    flex-direction: column;
  }
  .intro-image {
    min-height: 300px;
  }
  .intro-image-photo {
    top: 6%;
    bottom: 10%;
    left: 10%;
    right: 10%;
    background-position: center 25%;
  }
}

/* ── Info ─────────────────────────────────────────────────────── */
.info {
  position: relative;
  overflow: hidden;
}
.info-bg {
  position: absolute;
  top: -50%;
  left: 0;
  right: 0;
  height: 200%;
  background-size: cover;
  background-position: center;
  will-change: transform;
}
.info-overlay {
  position: absolute;
  inset: 0;
  background: rgba(19, 80, 27, 0.8);
}
.info-inner {
  position: relative;
  z-index: 1;
  max-width: 500px;
  margin-inline: auto;
  padding-block: var(--section-gap);
  text-align: center;
}
.info-heading {
  font-size: clamp(1.3rem, 3.5vw, 1.8rem);
  margin-bottom: 1.5rem;
  color: var(--white);
}
.info-hours,
.info-closed,
.info-address {
  color: var(--white);
}
.info-hours {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}
.info-hours li,
.contact-hours li {
  text-wrap: pretty;
}
.info-closed {
  margin-bottom: 0.4rem;
}
.info-address {
}

/* ── Angebot ──────────────────────────────────────────────────── */
.angebot {
  background: var(--white);
  padding-block: var(--section-gap);
}
.angebot-heading {
  text-align: center;
  margin-bottom: 3rem;
}
.angebot-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
}
.angebot-item {
  display: flex;
  flex-direction: column;
}
.angebot-photo {
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  margin-bottom: 1.25rem;
}
.angebot-title {
  margin-bottom: 0.75rem;
}
.angebot-text {
  color: var(--ink-light);
}

@media (max-width: 900px) {
  .angebot-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (max-width: 600px) {
  .angebot-grid {
    grid-template-columns: 1fr;
  }
}

/* ── Auswahl ──────────────────────────────────────────────────── */
.auswahl {
  background: var(--cream-dark);
  padding-block: var(--section-gap);
}
.auswahl-heading {
  text-align: center;
}
.auswahl-subheading {
  text-align: center;
  color: var(--ink-light);
  margin-top: 0.5rem;
}
.auswahl-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0;
  margin-top: 3rem;
}
.auswahl-item {
  display: flex;
}
/* Desktop: 2 dishes per row: keep both dishes in a row the same
   orientation, flip the whole row every other pair. */
.auswahl-item:nth-child(4n+3),
.auswahl-item:nth-child(4n) {
  flex-direction: row-reverse;
}
.auswahl-photo {
  flex: 1 1 50%;
  aspect-ratio: 1 / 1;
  background-size: cover;
  background-position: center;
}
.auswahl-text {
  flex: 1 1 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: var(--white);
  padding: 1.5rem 1rem;
}
.auswahl-title {
  margin-bottom: 0.35rem;
}
.auswahl-subtitle {
  font-size: 0.85rem;
  color: var(--ink-light);
  margin-bottom: 0.9rem;
}
.auswahl-price {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.2rem;
  color: var(--ink);
}
.price-cents {
  font-size: 0.7em;
}

@media (max-width: 900px) {
  .auswahl-grid {
    grid-template-columns: 1fr;
  }
  /* 1 dish per row now: reset the desktop pair-flip and alternate
     every single row instead. */
  .auswahl-item:nth-child(4n+3),
  .auswahl-item:nth-child(4n) {
    flex-direction: row;
  }
  .auswahl-item:nth-child(even) {
    flex-direction: row-reverse;
  }
}

@media (max-width: 600px) {
  /* Narrowest: always stack photo above text, no left/right variant.
     Must match/exceed the specificity of the nth-child rules above —
     both media queries are active at once at these widths, so a plain
     .auswahl-item reset here would lose to :nth-child(4n+3) etc. */
  .auswahl-item,
  .auswahl-item:nth-child(4n+3),
  .auswahl-item:nth-child(4n),
  .auswahl-item:nth-child(even) {
    flex-direction: column;
  }
  .auswahl-photo {
    aspect-ratio: 4 / 3;
  }
  .auswahl-text {
    padding: 2rem 1.25rem;
  }
}

/* ── Galerie ──────────────────────────────────────────────────── */
.galerie {
  background: var(--white);
  padding-block: var(--section-gap);
}
.galerie-heading {
  text-align: center;
  margin-bottom: 3rem;
}
.galerie-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.75rem;
}
.galerie-thumb {
  display: block;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
.galerie-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}
.galerie-thumb:hover img {
  transform: scale(1.05);
}

@media (max-width: 900px) {
  .galerie-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

.galerie-mobile-arrow {
  display: none;
}

/* Narrow OR short viewport (covers phones in both portrait and landscape,
   since landscape keeps the same small height even though width grows past
   480px): instead of a long single-column list of thumbnails with no
   context, show just the first photo as a cover, with prev/next arrows
   that jump straight into the lightbox (see main.js for swipe handling). */
@media (max-width: 480px), (max-height: 480px) {
  .galerie-grid {
    grid-template-columns: 1fr;
    position: relative;
  }
  .galerie-thumb {
    display: none;
  }
  .galerie-thumb:first-child {
    display: block;
    aspect-ratio: 4 / 3;
    /* Let the browser handle vertical page scrolling as normal, but leave
       horizontal drags to our own touchstart/touchend swipe handling in
       main.js instead of letting iOS's gesture heuristics intercept them
       (which otherwise can silently cancel/eat the touch sequence). */
    touch-action: pan-y;
  }
  .galerie-mobile-arrow {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 2.75rem;
    height: 2.75rem;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.85);
    color: var(--ink);
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    touch-action: manipulation;
  }
  .galerie-mobile-prev {
    /* Kept clear of the screen's very edge, where iOS's own edge-swipe
       back/forward gesture can intercept a tap or drag before it ever
       reaches this button. */
    left: 1.25rem;
  }
  .galerie-mobile-next {
    right: 1.25rem;
  }
}

/* ── Lightbox ─────────────────────────────────────────────────── */
body.lightbox-open {
  overflow: hidden;
}
.lightbox {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  align-items: center;
  justify-content: center;
  background: rgba(26, 26, 24, 0.85);
  /* Let JS handle horizontal swipe-to-navigate instead of iOS's own
     gesture heuristics intercepting/canceling the touch sequence. */
  touch-action: pan-y;
}
.lightbox.is-open {
  display: flex;
}
.lightbox-image {
  max-width: 88vw;
  max-height: 85vh;
  object-fit: contain;
  box-shadow: var(--shadow-lg);
}
.lightbox-close,
.lightbox-prev,
.lightbox-next {
  position: absolute;
  background: none;
  border: none;
  color: var(--white);
  cursor: pointer;
  line-height: 1;
}
.lightbox-close {
  top: 1.5rem;
  right: 1.5rem;
  font-size: 2.25rem;
}
.lightbox-prev,
.lightbox-next {
  top: 50%;
  transform: translateY(-50%);
  font-size: 3rem;
  padding: 0.5rem 1rem;
}
.lightbox-prev {
  left: 0.5rem;
}
.lightbox-next {
  right: 0.5rem;
}

@media (max-width: 600px) {
  .lightbox-prev,
  .lightbox-next {
    font-size: 2.25rem;
    padding: 0.5rem;
  }
}

/* ── Reservierung ─────────────────────────────────────────────── */
.reservierung-hero-img {
  display: block;
  width: 100%;
  height: auto;
}
.reservierung {
  background: var(--white);
  padding-block: var(--section-gap);
}
.reservierung-title {
  margin-bottom: 0.75rem;
}
.reservierung-subtitle {
  font-size: clamp(1.2rem, 3vw, 1.5rem);
  margin-bottom: 2rem;
}
.reservierung-text {
  color: var(--ink-light);
  margin-bottom: 1.25rem;
  text-align: left;
}
.reservierung-text:last-child {
  margin-bottom: 0;
}
/* Homepage 2-column reservation grid: image spans the full height of the left
   column, head + body mutually centred in the right (the 1fr top/bottom rows
   centre them). */
.reservierung-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  grid-template-areas: "media ." "media head" "media body" "media .";
  grid-template-rows: 1fr auto auto 1fr;
  gap: 0 4rem;
  align-items: center;
}
.reservierung-head { grid-area: head; }
.reservierung-media { grid-area: media; }
.reservierung-body { grid-area: body; }
.reservierung-tables {
  margin-top: 1.25rem;
  color: var(--ink-light);
}
.reservierung-tables a { text-decoration: underline; white-space: nowrap; }

/* /delice-pur/ variant: the title is centred above the grid (its own
   container, not a grid cell), then the image|text pair, then a full-width map
   band spanning both columns. Reuses .reservierung-layout's columns/gap/
   centring; only the areas and rows change. */
.container.reservierung-head { text-align: center; margin-bottom: 3rem; }
.reservierung-rail {
  grid-template-areas: "media body" "map map";
  grid-template-rows: auto auto;
  row-gap: 4rem;
}
.reservierung-map-slot { grid-area: map; }

@media (max-width: 900px) {
  .reservierung-layout {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "media" "body";
    row-gap: 2.5rem;
  }
  .reservierung-layout > .reservierung-head,
  .reservierung-layout > .reservierung-body {
    width: 100%;
    max-width: 660px;
    margin-inline: auto;
    text-align: center;
  }
  /* Rail stacks image → text → map (map stays last on screen). */
  .reservierung-rail { grid-template-areas: "media" "body" "map"; row-gap: 2rem; }
}

/* ── Contact ──────────────────────────────────────────────────── */
.contact {
  position: relative;
  overflow: hidden;
  padding-block: var(--section-gap);
}
.contact-bg {
  position: absolute;
  top: -50%;
  left: 0;
  right: 0;
  height: 200%;
  background-size: cover;
  background-position: center;
  will-change: transform;
}
.contact-overlay {
  position: absolute;
  inset: 0;
  background: rgba(19, 80, 27, 0.8);
}
.contact-inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3rem;
  align-items: start;
}
.contact-heading {
  margin-bottom: 1.25rem;
  color: var(--white);
}
.contact-address {
  color: var(--white);
  margin-bottom: 1rem;
}
.contact-line {
  margin-bottom: 0.5rem;
}
.contact-line a {
  color: var(--white);
  text-decoration: none;
}
.contact-line a:hover {
  text-decoration: underline;
}
/* E-mail and phone on one line below the hours, a centred dot between them. */
.contact-contacts {
  margin-top: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}
.contact-faq {
  /* Same 1.5rem the hours and the e-mail/phone line use, so "Häufige Fragen"
     is set apart as its own line rather than hugging the contact row. */
  margin-top: 1.5rem;
}
.contact-faq a {
  color: var(--white);
  text-decoration: none;
}
/* Underline the label only, never the arrow. */
.contact-faq a:hover .contact-faq-text {
  text-decoration: underline;
}
.contact-sep {
  color: var(--white);
  opacity: 0.6;
}
.contact-hours {
  margin-top: 1.5rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  color: var(--white);
}
.contact-closed {
  margin-top: 0.4rem;
  color: var(--white);
}
/* A white card, 12px padding, holding either the consent placeholder or (once
   loaded) the live iframe. No `aspect-ratio` here: that ties height to width
   both ways, so at 200% zoom the button text would double while the frame
   stayed put and clip it. A zero-width ::before sharing the grid cell with
   the content sets the *minimum* row height instead — anything taller, the
   content sets. The `- 6px` keeps the box the same size as a straight
   aspect-ratio version would be: 12 + (0.75·(W−24) − 6) + 12 = 0.75·W. */
.contact-map {
  /* z-index lifts the whole card above the section's absolutely-positioned
     .contact-overlay (the green tint). Without it the card's white padding
     background paints *below* the overlay while the map photo — which is
     position: absolute — paints above it, so the frame looked green/
     transparent even though the background was set. */
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  background: var(--white);
  padding: 12px;
  border-radius: var(--radius);
}
.contact-map::before {
  content: "";
  grid-area: 1 / 1;
  width: 0;
  min-width: 0;
  padding-top: calc(75% - 6px);
}
.contact-map > * { grid-area: 1 / 1; min-width: 0; }
.contact-map iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: none;
  border-radius: var(--radius);
}

@media (max-width: 800px) {
  .contact-inner {
    grid-template-columns: 1fr;
  }
}

/* ── Map, click-to-load ───────────────────────────────────────── */
/* Nothing here reaches Google — no preconnect, no third-party byte of any
   kind — until the button is pressed (§25 TDDDG). One grid cell, stretched:
   the inner box fills the card without a percentage height. */
.map-consent {
  position: relative;
  display: grid;
}
.map-consent > * { grid-area: 1 / 1; min-width: 0; }
/* The preview photo is out of flow so its own intrinsic height never sizes
   the grid row — that stays the card's ::before spacer, keeping the
   zero-CLS reservation exact. */
.map-consent-photo { position: relative; border-radius: 6px; overflow: hidden; }
.map-consent-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius);
}
/* ODbL requires the credit visible with the tiles. `position: relative` here
   and on .map-consent-inner is load-bearing: the photo is absolutely
   positioned, and positioned boxes paint after in-flow ones, so a static
   card would sit *under* the picture with an unclickable button. Positioning
   all three restores paint order. */
.map-consent-attribution {
  place-self: end;
  position: relative;
  z-index: 1;
  margin: 0;
  padding: 0.1rem 0.4rem;
  font-size: 0.7rem;
  line-height: 1.4;
  color: var(--ink-light);
  background: rgba(255, 255, 255, 0.8);
  border-radius: var(--radius) 0 var(--radius) 0;
}
.map-consent-inner {
  place-self: center;
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin: 0.75rem 0.75rem 1.6rem;
  padding: 1rem 1.25rem;
  background: rgba(255, 255, 255, 0.94);
  border-radius: var(--radius);
  text-align: center;
}
@supports (justify-content: safe center) {
  .map-consent-inner { justify-content: safe center; }
}
/* Hidden rather than removed once loaded: the button keeps its accessible
   name and the placeholder can be restored without a re-render. */
.map-consent.is-loaded .map-consent-inner,
.map-consent.is-loaded .map-consent-photo,
.map-consent.is-loaded .map-consent-attribution { display: none; }
.map-consent-address { font-weight: 500; color: var(--ink); }
.map-consent-note {
  max-width: 36ch;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--ink-light);
}
.map-consent-link { font-size: 0.78rem; }
.map-consent-link a { text-decoration: none; }
.map-consent-link a:hover { text-decoration: underline; }

@media (max-width: 480px) {
  .map-consent-inner { gap: 0.45rem; padding: 1rem; }
  .map-consent-address { font-size: 0.85rem; }
  .map-consent-note { font-size: 0.8rem; max-width: 30ch; }
}
@media (max-width: 359px) {
  .map-consent-inner { gap: 0.4rem; margin: 0.4rem 0.4rem 1.5rem; }
  .map-consent-address { font-size: 0.8rem; }
}

/* A map spanning the full container instead of a half column (delice-pur's
   .reservierung-map, the homepage Kontakt section's .contact-map-wide). Same
   wide capture (2200x700, 31.8% aspect) on both routes, but the white
   padding card only makes sense where it's needed for contrast. */
@media (min-width: 901px) {
  /* delice-pur: the section itself is white (.reservierung), so a white
     padding frame around the photo would be invisible — flush instead,
     same treatment as reservierung-hero-img just above it, which also has
     no border/radius of its own. Straight 31.8%, no -6px adjustment: with
     no padding there's nothing to compensate for. */
  .reservierung-map {
    padding: 0;
    background: transparent;
    border-radius: 0;
  }
  .reservierung-map::before { padding-top: 31.8%; }

  /* Homepage: the Kontakt section's dark-green background needs the white
     card for contrast (same reasoning as the standard contact-map). Same
     aspect ratio as delice-pur, inset by the standard 12px frame (inherited
     from .contact-map): 12 + (0.318·(W−24) − 6) + 12 ≈ 0.318·W. */
  .contact-map-wide::before { padding-top: calc(31.8% - 6px); }
}

/* Separates the map from the text/form row above at every width — the form
   card would otherwise touch this one. Outside the 901px block so it also
   applies when the row is stacked on narrow viewports. */
.contact-map-wide { margin-top: 2.5rem; }

/* A soft card, not bare labels floating on the section's dark overlay —
   gives the form the same visual weight as the map/text either side of it,
   so the row reads as two balanced halves rather than text vs. a stray
   list of inputs. */
.contact-form {
  position: relative;
  z-index: 1;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius);
  padding: 2rem;
}
.form-group {
  margin-bottom: 1.25rem;
}
.form-group label {
  display: block;
  font-size: 0.85rem;
  color: var(--white);
  margin-bottom: 0.35rem;
}
.form-group input,
.form-group textarea {
  width: 100%;
  font-family: var(--font-body);
  font-size: 1rem;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--cream-dark);
  border-radius: var(--radius);
  padding: 0.65rem 0.85rem;
}
.form-group textarea {
  resize: vertical;
}
.form-group input:focus,
.form-group textarea:focus {
  outline: 2px solid var(--green);
  outline-offset: 1px;
}
.hp-field {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  opacity: 0;
  pointer-events: none;
}
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.03em;
  padding: 0.75rem 2rem;
  border: none;
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
}
.btn-primary {
  background: var(--green);
  color: var(--white);
}
.btn-primary:hover {
  opacity: 0.85;
}
.form-status {
  margin-top: 1rem;
  font-size: 0.9rem;
}
.form-status.is-success {
  color: var(--white);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.1rem;
}
.form-status.is-error {
  color: #ff8a80;
}
.field-error {
  margin-top: 0.35rem;
  font-size: 0.85rem;
  color: #ffd7d2;
}
.field-error:empty { display: none; }

/* ── Footer ───────────────────────────────────────────────────── */
.site-footer { background: var(--ink); padding-block: 2rem; }
/* Wordmark, contact row, social row — three centred rows on one axis. The gap
   is deliberately tighter than the 44 px rows themselves, so the stack reads
   as one block rather than three floating lines. */
.footer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.5rem;
}
/* The centred anchor of the stack, a step up from the 1.75rem header logo. */
.footer-name {
  font-family: var(--font-logo);
  font-size: 2rem;
  color: var(--cream);
  line-height: 1.2;
}
/* One row — address, phone, e-mail, Instagram, Facebook. The wrapper carries
   the same column gap as the two lists inside it, so the gap across the list
   boundary is the gap within each, and the row reads as five equal items.
   Its row gap separates the lists once the row becomes a column. */
.footer-row, .footer-contact, .footer-social {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  column-gap: 2.5rem;
}
.footer-row { align-items: center; row-gap: 0.5rem; }
.footer-contact {
  color: var(--cream-dark);
  font-size: 0.85rem;
  line-height: 1.4;
}
.footer-contact a { color: var(--cream-dark); text-decoration: none; }
.footer-contact a:hover { color: var(--white); text-decoration: underline; }
.footer-legal { display: flex; gap: 1.25rem; }
.footer-social a, .footer-legal a {
  color: var(--cream-dark);
  font-size: 0.85rem;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.footer-social a:hover, .footer-legal a:hover { color: var(--white); text-decoration: underline; }
/* A hairline of the footer's own link colour at low alpha: visible against
   --ink, invisible as a "line". The bar is two-ended, copyright against legal
   links, which keeps the centred stack above from looking like a column that
   ran out. */
.footer-bottom {
  border-top: 1px solid rgba(230, 230, 227, 0.18);
  margin-top: 1.25rem;
  padding-top: 0.5rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.25rem 1.5rem;
  flex-wrap: wrap;
}
.footer-copyright { color: var(--muted-on-dark); font-size: 0.8rem; }

/* Both breakpoints are measured, not guessed, and sit a little above the width
   at which a row stops holding what it holds.
   860 px: the five links measure roughly 620 px, so with four 2.5rem gaps the
   line is 780 px, 820 px with the container's gutters, and clears that by
   20 px a side at 860. Below it, flex wrap alone would leave a ragged split,
   so the line becomes the narrow arrangement: contact links as one centred
   column, the social pair as a centred row under them.
   390 px: below this the copyright and legal nav no longer sit abreast
   comfortably, so they centre into a stack instead. */
@media (max-width: 860px) {
  .footer-row, .footer-contact { flex-direction: column; align-items: center; }
  .footer-social { column-gap: 1.25rem; }
}
@media (max-width: 390px) {
  .footer-bottom { flex-direction: column; justify-content: center; }
}

/* ── Legal (Impressum) ────────────────────────────────────────── */
.legal {
  background: var(--charcoal);
  padding-block: var(--section-gap);
}
.legal-inner {
  max-width: 650px;
}
.legal-heading {
  color: var(--white);
  margin-bottom: 2rem;
}
.legal-subheading {
  /* Smaller than the base h2 (a page title's size): these are numbered
     section headings on a long legal page, not headlines. */
  font-size: clamp(1.15rem, 2.5vw, 1.4rem);
  color: var(--white);
  margin-top: 2.5rem;
  margin-bottom: 1rem;
}
.legal-block {
  color: var(--cream-dark);
  margin-bottom: 1.5rem;
  line-height: 1.8;
}
.legal-block a {
  color: var(--white);
}
.legal-contact {
  list-style: none;
  color: var(--cream-dark);
  margin-bottom: 1.5rem;
  line-height: 1.8;
}
.legal-contact a {
  color: var(--white);
}
.legal-label {
  color: var(--cream-dark);
}
.legal-stand {
  color: var(--cream-dark);
  font-size: 0.85rem;
  margin-bottom: 2rem;
}

/* ── 404 ──────────────────────────────────────────────────────── */
/* Smaller than the shared .legal-heading default: "Diese Seite gibt es
   nicht" is long enough to wrap at that size, and a 404 heading gains
   nothing from being the biggest thing on the page. */
.notfound .legal-heading {
  font-size: clamp(1.6rem, 4vw, 2.2rem);
}
.notfound-links {
  margin-bottom: 1.5rem;
  line-height: 2.2;
}
.notfound-links a {
  color: var(--white);
  font-weight: 700;
}
.notfound-links a::before {
  content: "→";
  display: inline-block;
  margin-right: 0.5rem;
  color: var(--green-light);
}

/* ── Speisekarte ──────────────────────────────────────────────── */
.menu-page {
  background: var(--white);
  padding-block: var(--section-gap);
  min-height: 50vh;
}
.menu-page-inner {
  text-align: center;
}
/* Sticky jump-to-group chips. Lives inside .menu-page-inner (after the h1),
   so the menu section's own top padding clears the fixed header at rest;
   once scrolled, it pins just below the header at top: var(--header-h). */
.menu-index {
  position: sticky;
  top: var(--header-h);
  z-index: 50;
  display: flex;
  gap: 0.5rem;
  margin: 1.5rem 0 0;
  padding: 0.5rem 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  /* Opaque: menu rows scrolling through the chips is the ugliest outcome. */
  background: var(--white);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.menu-index::-webkit-scrollbar { display: none; }
.menu-index a {
  flex: 0 0 auto;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  padding-inline: 0.9rem;
  white-space: nowrap;
  scroll-snap-align: start;
  font-size: 0.875rem;
  color: var(--green);
  background: var(--cream);
  border: 1px solid var(--cream-dark);
  border-radius: var(--radius);
}
.menu-index a:hover { text-decoration: none; background: var(--green-light); }
.menu-group {
  max-width: 700px;
  margin: 3rem auto 0;
  text-align: left;
  /* Fixed header + the sticky chip index + breathing room, or a #anchor jump
     lands under the chrome. */
  scroll-margin-top: calc(var(--header-h) + 52px + 1rem);
}
.menu-group-heading {
  text-align: center;
}
.menu-group-de {
  display: block;
  font-family: var(--font-body);
  font-style: normal;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-light);
  margin-top: 0.4rem;
}
.menu-group-hours {
  text-align: center;
  color: var(--ink-light);
  font-size: 0.9rem;
  margin-top: 0.5rem;
  margin-bottom: 3rem;
}
.menu-group-desc {
  text-align: center;
  color: var(--ink-light);
  font-size: 0.9rem;
  margin-top: 0.5rem;
  margin-bottom: 3rem;
}
.menu-group + .menu-group {
  margin-top: 4rem;
  padding-top: 4rem;
  border-top: 1px solid var(--cream-dark);
}
.menu-closing {
  text-align: center;
}
.menu-closing-text {
  color: var(--ink-light);
  margin-bottom: 0.75rem;
}
.menu-closing .menu-category-title {
  margin-top: 2rem;
}

/* ── FAQ (foot of the menu page) ──────────────────────────────── */
.faq {
  max-width: 700px;
  margin: 4rem auto 0;
  padding-top: 4rem;
  border-top: 1px solid var(--cream-dark);
  text-align: left;
  /* clears the fixed header + mobile action bar when jumped to via #fragen */
  scroll-margin-top: calc(var(--header-h) + 56px + 1rem);
}
.faq-heading { text-align: center; }
.faq-intro {
  text-align: center;
  color: var(--ink-light);
  font-size: 0.9rem;
  margin-top: 0.5rem;
  margin-bottom: 2.5rem;
}
.faq-list { display: grid; gap: 1.5rem; }
.faq-q {
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--green);
  margin-bottom: 0.25rem;
}
.faq-a { color: var(--ink-light); margin: 0; }
.menu-category {
  margin-bottom: 2.5rem;
}
.menu-category-title {
  margin-bottom: 0.25rem;
}
.menu-category-desc {
  color: var(--ink-light);
  font-size: 0.9rem;
  margin-bottom: 1rem;
}
.menu-items {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
}
.menu-item-row {
  display: flex;
  align-items: baseline;
  justify-content: flex-start;
  gap: 0.5rem;
}
.menu-item-name {
  font-weight: 500;
}
.menu-item-price {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--green);
  white-space: nowrap;
}
.menu-item-desc {
  color: var(--ink-light);
  font-size: 0.85rem;
  margin-top: 0.15rem;
}
.menu-sketch {
  display: block;
  max-width: 220px;
  width: 100%;
  height: auto;
  margin: 2rem auto 0;
  opacity: 0.85;
}

/* ── Reservierung CTA ─────────────────────────────────────────── */
.reservierung-cta {
  text-align: center;
  margin-top: 2.5rem;
  margin-bottom: 2.5rem;
}

/* ── Modal ────────────────────────────────────────────────────── */
body.modal-open {
  overflow: hidden;
}
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(26, 26, 24, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
.modal-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}
.modal {
  background: var(--cream);
  width: 100%;
  max-width: 660px;
  max-height: 90vh;
  overflow-y: auto;
  padding: 2.5rem;
  position: relative;
  transform: translateY(16px);
  transition: transform 0.25s ease;
}
.modal-overlay.is-open .modal {
  transform: translateY(0);
}
.modal-close {
  position: absolute;
  top: 1rem;
  right: 1.25rem;
  background: none;
  border: none;
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ink-light);
  cursor: pointer;
  padding: 0.25rem;
}
.modal-close:hover {
  color: var(--ink);
}
.modal-title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-style: italic;
  font-weight: 700;
  color: var(--green);
  margin: 0 0 0.4rem;
}
.modal-intro {
  font-size: 0.9rem;
  color: var(--ink-light);
  margin: 0 0 1.75rem;
}
.modal-form .form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 1.25rem;
}
.modal-form .form-group {
  margin-bottom: 1.1rem;
}
.modal-form .form-group label {
  display: block;
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-light);
  margin-bottom: 0.35rem;
}
.modal-form .form-group input,
.modal-form .form-group select,
.modal-form .form-group textarea {
  width: 100%;
  background: var(--white);
  border: 1px solid var(--cream-dark);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink);
  box-sizing: border-box;
}
.modal-form .form-group input:focus,
.modal-form .form-group select:focus,
.modal-form .form-group textarea:focus {
  outline: none;
  border-color: var(--green);
}
.modal-form .form-group textarea {
  resize: vertical;
}
.modal-submit {
  margin-top: 0.5rem;
  width: 100%;
}
/* "* Pflichtfelder" legend + the * marks on the two required labels (modal,
   light background). */
.form-required-note { font-size: 0.8rem; color: var(--ink-light); margin: 0 0 1rem; }
.req-mark { color: var(--ink-light); }
/* Datenschutz line under a form. Base = the Kontakt form, which sits on the
   dark-green section (light text); the modal override re-colours it for its
   own light background. */
.form-privacy {
  margin-top: 1rem;
  font-size: 0.8rem;
  color: var(--cream-dark);
}
.form-privacy a { color: var(--white); text-decoration: underline; }
.modal-form .form-privacy { color: var(--ink-light); }
.modal-form .form-privacy a { color: var(--green); }
.modal-success {
  text-align: center;
  padding: 2rem 1rem;
}
.modal-success-logo {
  font-family: var(--font-logo);
  font-size: 3rem;
  color: var(--green);
  margin: 0 0 1.25rem;
}
.modal-success-msg {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.2rem;
  color: var(--ink);
  margin: 0 0 2rem;
  line-height: 1.5;
}
.modal-ok-btn {
  min-width: 120px;
}
.modal .form-status.is-success {
  color: var(--green);
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.05rem;
}
.modal .form-status.is-error {
  color: #c0392b;
}
.modal-form .field-error {
  color: #c0392b;
}
@media (max-width: 480px) {
  .modal {
    padding: 1.75rem 1.25rem;
  }
  .modal-form .form-row {
    grid-template-columns: 1fr;
  }
}

