/*!
 * Inverta — bundled stylesheet.
 * Generated by tools/build-css.php from contact.css.
 * Do not edit: change the module under assets/css/ and rebuild.
 * Modules inlined: 1
 */
/* =============================================================
   Inverta — Section: Contact

   Four layouts behind one markup tree, in the same glass capsule the
   rest of the page uses. The variant is a class on the section; the
   grid and the picture's place are decided here.

     split        form on the left, picture on the right
     split-left   mirrored — picture leads
     stacked      details above, form below, no picture
     bare         form alone, centred, for a page that is only this

   Everything reads the global tokens, so a style preset moves the
   section with the site.
   ============================================================= */

.vf-section-contact {
  /* The gap to the capsule above, from "Abstand zur vorherigen Sektion". */
  margin-block-start: var(--vf-contact-mt, 0px);
  --vf-contact-radius: var(--inv-radius, 16px);
  --vf-contact-dur: var(--inv-motion, 400ms);
  --vf-contact-ease: var(--inv-ease, cubic-bezier(.22, .61, .36, 1));
  --vf-contact-glass: 62%;

  position: relative;
  isolation: isolate;
  color: var(--vf-contact-fg, var(--inv-fg, #0f172a));
  padding-block: var(--vf-contact-pt, var(--inv-section-rhythm, 80px)) var(--vf-contact-pb, var(--inv-section-rhythm, 80px));
  padding-inline: var(--inv-section-px, var(--inv-edge, 10px));
}

/* -------------------------------------------------------------
   Capsule
   ------------------------------------------------------------- */

/* The heading, over the whole capsule.
 *
 * It used to be the first thing inside .vf-contact-aside, which is one column of
 * the grid — so "Zentriert" centred it inside that column. Measured at 1440 px
 * the title's centre sat 343 px left of the capsule's: centred over the form,
 * not over the section. Above the grid it spans the capsule, and the same option
 * now means what it says. */
.vf-contact-head {
  position: relative;
  z-index: 1;
  margin-bottom: clamp(22px, 2.8vw, 40px);
}

/* Heading alignment — "Ausrichtung der Überschrift".
 *
 * The heading block is the shared .vf-section-title-area, so the rule works on
 * the container rather than on each line: text-align carries the eyebrow, the
 * title and the description together, and the auto margins let a title with a
 * max-width sit in the middle of its column rather than at its left edge. */
.vf-section-contact.vf-contact-head-center .vf-section-title-area {
  text-align: center;
  /* The block is 42rem wide by default (base/layout.css). Centring the text
     inside a 672 px block that sits at the left edge of a 1322 px capsule is
     not centring the heading: measured, its centre was still 325 px off. */
  margin-inline: auto;
}

.vf-section-contact.vf-contact-head-center .vf-section-title,
.vf-section-contact.vf-contact-head-center .vf-section-desc {
  margin-inline: auto;
}

.vf-section-contact.vf-contact-head-right .vf-section-title-area {
  text-align: right;
  margin-left: auto;
}

.vf-section-contact.vf-contact-head-right .vf-section-title,
.vf-section-contact.vf-contact-head-right .vf-section-desc {
  margin-left: auto;
}

.vf-contact-capsule {
  position: relative;
  /* Full width, like the bento, services and about capsules — the section's
     own "Maximale Breite" option narrows it, and 0 means full. Capping at
     --inv-container here made that option read as broken: the slider sat at 0
     and the section was still 1280px wide, a good deal narrower than every
     capsule above it. */
  max-width: min(var(--vf-contact-max-w, 100%), var(--inv-shell-max, 100%));
  margin-inline: auto;
  padding: clamp(26px, 3.6vw, 56px) var(--inv-gutter, clamp(20px, 3vw, 48px));
  border-radius: var(--vf-contact-capsule-radius, var(--inv-radius-capsule, 20px));
  isolation: isolate;
}

.vf-contact-capsule-mode .vf-contact-capsule {
  border: 1px solid rgba(15, 23, 42, 0.08);
  border-top-color: color-mix(in srgb, var(--inv-surface, #fff) 90%, transparent);
  background: linear-gradient(150deg, color-mix(in srgb, var(--inv-surface, #fff) 74%, transparent) 0%, color-mix(in srgb, var(--inv-surface, #fff) 44%, transparent) 100%);
  -webkit-backdrop-filter: blur(28px) saturate(180%);
  backdrop-filter: blur(28px) saturate(180%);
  box-shadow: var(--inv-shadow-capsule);
}

.vf-contact-fullwidth-mode .vf-contact-capsule {
  padding-inline: 0;
  background: none;
  border: 0;
  box-shadow: none;
}

/* Clipped by itself rather than by the capsule: overflow on the parent
   would cancel position:sticky on anything inside it. */
.vf-contact-glow {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: .5;
  /* Kein filter: blur() — Safari rechnet ihn auf dieser Fläche beim Scrollen
     jedes Bild neu (1.7.23). Der Verlauf läuft ohnehin weich aus. */
  clip-path: inset(0 round var(--vf-contact-capsule-radius, var(--inv-radius-capsule, 20px)));
  background:
    radial-gradient(ellipse 42% 46% at 88% 16%, color-mix(in srgb, var(--vf-accent, var(--inv-accent, #24a9b3)) 30%, transparent) 0%, transparent 70%),
    radial-gradient(ellipse 40% 40% at 10% 88%, color-mix(in srgb, var(--vf-accent, var(--inv-accent, #24a9b3)) 18%, transparent) 0%, transparent 72%);
}

/* -------------------------------------------------------------
   Grid
   ------------------------------------------------------------- */
.vf-contact-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
  gap: clamp(26px, 3.4vw, 56px);
  align-items: start;
}

/* The details column holds still while the form scrolls past it. */
.vf-contact-aside {
  position: sticky;
  top: calc(var(--inv-header-h, 60px) + var(--inv-header-bar-pt, 10px) + 24px);
  min-width: 0;
}

.vf-contact-form { min-width: 0; }

/* A details column with nothing in it still took a grid gap.
 *
 * Phone, e-mail and address are each emitted with `hidden` when the field is
 * empty, so a shop that has filled in none of them had a 0 px column and a gap
 * of up to 56 px between the picture and the form. Written with :has() rather
 * than decided in PHP on purpose: the live preview removes `hidden` the moment
 * a number is typed, and the column comes back with it. */
.vf-contact-aside:not(:has(.vf-contact-info-item:not([hidden]))) {
  display: none;
}

/* Die Schalter „Telefon / E-Mail / Adresse / Symbole anzeigen“
   (Kontaktangaben). Klassen auf der Sektion statt `hidden` aus PHP, damit
   die Vorschau sie sofort schaltet. */
.vf-contact--no-phone .vf-contact-info-item--phone,
.vf-contact--no-email .vf-contact-info-item--email,
.vf-contact--no-address .vf-contact-info-item--address,
.vf-contact--no-icons .vf-contact-info-item > svg {
  display: none;
}

/* Und die Spalte verschwindet, sobald keine Zeile mehr steht — gleich ob
   eine leer ist (hidden) oder ausgeschaltet (Klasse). */
.vf-section-contact:not(
  :has(.vf-contact-info-item--phone:not([hidden])):not(.vf-contact--no-phone),
  :has(.vf-contact-info-item--email:not([hidden])):not(.vf-contact--no-email),
  :has(.vf-contact-info-item--address:not([hidden])):not(.vf-contact--no-address)
) .vf-contact-aside {
  display: none;
}

/* -------------------------------------------------------------
   The picture — and how much of it one gets to see

   "Bildanpassung" decides this, and the default decides it in favour of the
   picture. A workshop uploads a photo of its shop; a photo with a third of it
   cut off is not the photo they uploaded.

     full      the picture keeps its own proportions. The cell is as tall as
               the picture is at that width and nothing is cut away — so the
               row can end up taller than the form, which is the price of
               showing a whole picture.
     contain   the picture stands level with the form and fits inside that
               height. Nothing is cut away; what is left over stays empty.
     cover     the picture fills the cell and is cut to fit. The old, and only,
               behaviour — still the right one for a wide backdrop.

   The cell only ever gets a shape of its own in the last two. Under "full" the
   picture *is* the shape, so every rule that hands the cell a height or takes
   the image out of the flow is scoped to the other two.
   ------------------------------------------------------------- */
.vf-contact-media {
  display: none;
  position: relative;
  margin: clamp(20px, 2.4vw, 30px) 0 0;
  width: var(--vf-contact-media-w, 100%);
  border-radius: calc(var(--vf-contact-radius) * 1.15);
  overflow: hidden;
}

.vf-contact-media img {
  display: block;
  width: 100%;
  height: auto;
  object-position: var(--vf-contact-media-pos, center center);
}

.vf-contact-fit-cover .vf-contact-media,
.vf-contact-fit-contain .vf-contact-media {
  aspect-ratio: var(--vf-contact-media-ratio, 4 / 5);
}

.vf-contact-fit-cover .vf-contact-media img,
.vf-contact-fit-contain .vf-contact-media img {
  height: 100%;
  object-fit: cover;
}

.vf-contact-fit-contain .vf-contact-media img {
  object-fit: contain;
}

/* The reveal, and why it is two different animations.
 *
 * The figure clips what overflows it, so the slow zoom-out this section has
 * always had — the image parked at scale(1.04) and released on reveal — takes
 * 2% off each edge. Where the picture is being cropped to fill the cell anyway
 * that is invisible; where showing the whole picture is the point it is a crop,
 * and a permanent one on a browser that never fires the observer or on a
 * machine that asks for reduced motion: `transition: none` leaves the transform
 * standing at 1.04 forever.
 *
 * So it is a @keyframes now, for both. That is the rule the rest of the theme
 * follows (assets/css/components/reveal.css): nothing is parked at rest, the
 * animation runs once `is-revealed` lands, and a page without JavaScript is
 * simply the finished page. */
@keyframes inv-contact-media-zoom {
  from { transform: scale(1.04); }
  to   { transform: none; }
}

@keyframes inv-contact-media-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.vf-section-contact.is-revealed .vf-contact-media img {
  animation: inv-contact-media-fade 900ms var(--vf-contact-ease) both;
}

.vf-section-contact.vf-contact-fit-cover.is-revealed .vf-contact-media img {
  animation: inv-contact-media-zoom 1.6s var(--vf-contact-ease) both;
}

.vf-contact-badge {
  position: absolute;
  left: 16px;
  bottom: 16px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 10px 14px;
  border-radius: calc(var(--vf-contact-radius) * 0.7);
  background: color-mix(in srgb, var(--inv-surface, #fff) 84%, transparent);
  /* Stärke aus „Design-Grundlagen → Rahmenstärke“. */
  border: var(--inv-border-w, 1px) solid color-mix(in srgb, var(--inv-fg, #0f172a) 10%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  backdrop-filter: blur(14px) saturate(160%);
  text-align: start;
}

.vf-contact-badge__value {
  font-family: var(--inv-font-display, system-ui, sans-serif);
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--vf-accent, var(--inv-accent, #24a9b3));
  font-variant-numeric: tabular-nums;
}

.vf-contact-badge__label {
  font-size: .66rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--inv-fg, #0f172a) 62%, transparent);
}

/* -------------------------------------------------------------
   Variants
   ------------------------------------------------------------- */

/* split — form left, picture right. The picture is its own column, so it
   stands beside the form rather than under the contact details. */
.vf-contact--split .vf-contact-grid,
.vf-contact--split-left .vf-contact-grid {
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
}

/* The picture is a cell in the grid, not a pane floating over the capsule.
 *
 * It used to be position:absolute with top:0 and bottom:0, which measured the
 * whole capsule — so it started level with the section's heading and ran to
 * the very edge, towering over a form that begins much further down. Placed in
 * the grid it shares the form's row and its top edge, which is what "level
 * with the form" means. */
.vf-contact--split .vf-contact-grid,
.vf-contact--split-left .vf-contact-grid {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
}

.vf-contact--split .vf-contact-grid {
  grid-template-areas:
    "aside ."
    "form  media";
}

.vf-contact--split-left .vf-contact-grid {
  grid-template-areas:
    ".     aside"
    "media form";
}

.vf-contact--split .vf-contact-aside,
.vf-contact--split-left .vf-contact-aside {
  grid-area: aside;
  position: static;
}

.vf-contact--split .vf-contact-form,
.vf-contact--split-left .vf-contact-form { grid-area: form; }

.vf-contact--split .vf-contact-media,
.vf-contact--split-left .vf-contact-media {
  grid-area: media;
  display: block;
  position: relative;
  /* Bildbreite gilt auch hier. Feste 100% haben den Regler in genau der
     Variante abgeschaltet, in der das Bild überhaupt zu sehen ist. */
  width: var(--vf-contact-media-w, 100%);
  margin: 0;
}

/* Level with the form, because the picture no longer decides how tall the row is.
 *
 * Measured at 1440 px: the form was 540 px tall, the picture 1140 — it hung
 * 600 px below the form. `height: 100%` on an image inside a grid item that
 * takes its own height from its content is a circle, and the browser falls back
 * to the image's natural height, which was 1186 px. Taken out of the flow the
 * image contributes nothing to the row, the row is as tall as the form, and
 * `align-self: stretch` pulls the cell to exactly that.
 *
 * This is what "level with the form" costs, and it is why it is no longer the
 * only option: a cell whose height comes from the form has to crop or letterbox
 * whatever is put in it. Under "full" the cell keeps the picture's own height
 * and sits at the top of the row instead. */
.vf-contact-fit-cover.vf-contact--split .vf-contact-media,
.vf-contact-fit-cover.vf-contact--split-left .vf-contact-media,
.vf-contact-fit-contain.vf-contact--split .vf-contact-media,
.vf-contact-fit-contain.vf-contact--split-left .vf-contact-media {
  align-self: stretch;
  aspect-ratio: auto;
}

.vf-contact-fit-cover.vf-contact--split .vf-contact-media img,
.vf-contact-fit-cover.vf-contact--split-left .vf-contact-media img,
.vf-contact-fit-contain.vf-contact--split .vf-contact-media img,
.vf-contact-fit-contain.vf-contact--split-left .vf-contact-media img {
  position: absolute;
  inset: 0;
}

.vf-contact-fit-full.vf-contact--split .vf-contact-media,
.vf-contact-fit-full.vf-contact--split-left .vf-contact-media {
  align-self: start;
}

/* Wenn das ganze Bild höher ist als das Formular, steht das Formular in der
   Mitte daneben statt oben mit einer halben Spalte Leere darunter. Ist das
   Formular das höhere, ändert die Regel nichts: dann ist die Zeile so hoch wie
   es selbst. */
.vf-contact-fit-full.vf-contact--split .vf-contact-form,
.vf-contact-fit-full.vf-contact--split-left .vf-contact-form {
  align-self: center;
}

/* stacked — details above the form, full width, no picture. */
.vf-contact--stacked .vf-contact-grid {
  grid-template-columns: minmax(0, 1fr);
}

.vf-contact--stacked .vf-contact-aside {
  position: static;
  max-width: 760px;
}

/* bare — the form alone, for a page that exists to be filled in. */
.vf-contact--bare .vf-contact-grid { grid-template-columns: minmax(0, 1fr); }
.vf-contact--bare .vf-contact-aside { display: none; }
.vf-contact--bare .vf-contact-form { max-width: 680px; margin-inline: auto; }

/* -------------------------------------------------------------
   Details list
   ------------------------------------------------------------- */
.vf-contact-info-list {
  list-style: none;
  /* The gap above belonged to the heading, which no longer stands here. */
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}

.vf-contact-info-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: .94rem;
  line-height: 1.5;
}

.vf-contact-info-item svg {
  width: 18px;
  height: 18px;
  flex: none;
  margin-top: 2px;
  color: var(--vf-accent, var(--inv-accent, #24a9b3));
}

.vf-contact-info-item a {
  color: inherit;
  text-decoration: none;
  box-shadow: inset 0 -1px 0 0 color-mix(in srgb, currentColor 22%, transparent);
  transition: box-shadow var(--vf-contact-dur) var(--vf-contact-ease), color var(--vf-contact-dur) var(--vf-contact-ease);
}

.vf-contact-info-item a:hover {
  color: var(--vf-accent, var(--inv-accent, #24a9b3));
  box-shadow: inset 0 -1px 0 0 currentColor;
}

/* -------------------------------------------------------------
   The form, on glass

   Everything from here down is scoped to the section.

   .vf-input, .vf-label, .vf-textarea and the form messages are the site's own
   form classes — shared with the account pages, the comment form and
   WooCommerce. This file loads after components/forms.css, so styling them
   bare handed the contact section's glass skin to every form on the page.
   ------------------------------------------------------------- */
.vf-contact-form {
  position: relative;
  padding: clamp(20px, 2.6vw, 34px);
  border-radius: var(--vf-contact-radius);
  border: 1px solid color-mix(in srgb, var(--inv-fg, #0f172a) 8%, transparent);
  background: color-mix(in srgb, var(--inv-surface, #fff) var(--vf-contact-glass), transparent);
  -webkit-backdrop-filter: blur(20px) saturate(175%);
  backdrop-filter: blur(20px) saturate(175%);
  box-shadow: inset 0 1px 0 0 color-mix(in srgb, #fff 70%, transparent);
}

.vf-contact-fullwidth-mode .vf-contact-form {
  background: var(--inv-surface, #fff);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

.vf-section-contact .vf-form-row.vf-two-col {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 1rem;
}

/* Name, e-mail and phone belong in one row: they are the one thing the visitor
   is being asked — who they are — and splitting them over two rows makes the
   form look longer than it is. Below 900px a three-column row leaves each field
   too narrow to read its own label, so it becomes two rows (name across the
   top, the two ways of reaching them beneath) before it becomes one column. */
.vf-section-contact .vf-form-row.vf-three-col {
  display: grid;
  /* Nicht `repeat(3, …)`, sondern auto-fit mit Untergrenze.
     Gemessen am 06.10.2026 war jedes der drei Felder bei 1024 px
     Fensterbreite 125 px breit — zu schmal, um die eigene Beschriftung zu
     lesen, und das lag nicht am Fenster, sondern an der Breite des
     Formulars darin. Die hängt davon ab, wie breit der Betreiber seinen
     Container gestellt hat; ein Haltepunkt am Fenster kann das nicht
     wissen, eine Untergrenze je Spalte schon. */
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 1rem;
}

/* Der Haltepunkt bleibt zusätzlich: er sorgt dafür, dass der Name eine
   eigene Zeile bekommt, sobald es nicht mehr für drei reicht. 1200 statt
   900 — bei 1024 waren es sonst weiterhin drei Spalten. */
@media (max-width: 1200px) {
  .vf-section-contact .vf-form-row.vf-three-col {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .vf-section-contact .vf-form-row.vf-three-col > .vf-field:first-child {
    grid-column: 1 / -1;
  }
}

.vf-section-contact .vf-field { min-width: 0; }

.vf-section-contact .vf-label {
  display: block;
  margin-bottom: 5px;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: color-mix(in srgb, var(--inv-fg, #0f172a) 70%, transparent);
}

.vf-section-contact .vf-input,
.vf-section-contact .vf-select,
.vf-section-contact .vf-textarea {
  width: 100%;
  padding: 11px 14px;
  font: inherit;
  font-size: .92rem;
  color: inherit;
  background: color-mix(in srgb, var(--inv-surface, #fff) 78%, transparent);
  /* Die Stärke kommt aus „Design-Grundlagen → Rahmenstärke“. Hier stand eine
     feste 1px, und weil dieser Selektor zwei Klassen trägt und die
     Token-Regel in base/section-chrome.css nur eine, hat der Regler die
     sichtbarsten Felder der ganzen Website nie erreicht — gemessen mit der
     CSS-Domäne von DevTools: diese Regel gewann, und sie las die Variable
     nicht. */
  border: var(--inv-border-w, 1px) solid color-mix(in srgb, var(--inv-fg, #0f172a) 10%, transparent);
  border-radius: var(--inv-radius-sm, 10px);
  outline: none;
  transition:
    border-color var(--vf-contact-dur) var(--vf-contact-ease),
    box-shadow var(--vf-contact-dur) var(--vf-contact-ease),
    background-color var(--vf-contact-dur) var(--vf-contact-ease);
}

.vf-section-contact .vf-input:focus,
.vf-section-contact .vf-select:focus,
.vf-section-contact .vf-textarea:focus {
  border-color: var(--vf-accent, var(--inv-accent, #24a9b3));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--vf-accent, var(--inv-accent, #24a9b3)) 18%, transparent);
  background: var(--inv-surface, #fff);
}

.vf-section-contact .vf-textarea { resize: vertical; min-height: 88px; }

.vf-section-contact .vf-select-wrap { position: relative; }

/* Sicherheitscode: Bild, Feld und „neuer Code“ in einer Zeile. Das Bild
   bringt contact.js; bis dahin hält eine leere Fläche den Platz. */
.vf-section-contact .vf-captcha {
  margin-bottom: 1rem;
}

.vf-section-contact .vf-captcha__row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.vf-section-contact .vf-captcha__img {
  display: grid;
  place-items: center;
  flex: none;
  width: 132px;
  height: 48px;
  border-radius: var(--inv-cofield-radius, var(--inv-radius-sm, 10px));
  border: var(--inv-border-w, 1px) solid color-mix(in srgb, var(--inv-fg, #0f172a) 12%, transparent);
  background: color-mix(in srgb, var(--inv-surface, #fff) 92%, var(--inv-fg, #0f172a));
  color: var(--inv-fg, #0f172a);
  user-select: none;
}

.vf-section-contact .vf-captcha__img svg {
  display: block;
}

.vf-section-contact .vf-captcha__input {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 9rem;
  letter-spacing: .3em;
  font-variant-numeric: tabular-nums;
}

.vf-section-contact .vf-captcha__new {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: var(--inv-radius-sm, 10px);
  background: transparent;
  color: inherit;
  opacity: .7;
  cursor: pointer;
}

.vf-section-contact .vf-captcha__new:hover,
.vf-section-contact .vf-captcha__new:focus-visible {
  opacity: 1;
  background: color-mix(in srgb, var(--inv-fg, #0f172a) 6%, transparent);
}

.vf-section-contact .vf-captcha__hint {
  margin: .4rem 0 0;
  font-size: .8rem;
  opacity: .7;
}

.vf-section-contact .vf-consent-wrap {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0 0 1.1rem;
}

.vf-section-contact .vf-consent-label {
  font-size: .78rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--inv-fg, #0f172a) 66%, transparent);
}

.vf-section-contact .vf-privacy-link { color: var(--vf-accent, var(--inv-accent, #24a9b3)); }

/* The submit button is the site's button, full width. */
.vf-contact-submit {
  width: 100%;
  justify-content: center;
  background: var(--vf-accent, var(--inv-primary, #111827));
  /* Die Flaeche darueber ist --vf-accent, also der Akzent — und nicht die
     Primaerfarbe, auf die der zweite Zweig zeigt. Weiss darauf misst 2,84:1,
     gemessen am 08.10.2026 am Knopf fuer den Kostenvoranschlag. Die Tinte des
     Akzents misst 6,29:1. */
  color: var(--vf-contact-btn-ink, var(--inv-accent-fg, var(--inv-fg, #0f172a)));
  border-radius: var(--vf-contact-btn-radius, var(--inv-radius-sm, 10px));
  padding: .95rem 1.5rem;
  font-family: var(--inv-font-display, system-ui, sans-serif);
  font-size: var(--vf-contact-btn-size, .95rem);
  font-weight: var(--vf-contact-btn-weight, 600);
}

/* The label rolls like the header's CTA. */
.vf-contact-submit .txt-anim {
  display: block;
  overflow: hidden;
  line-height: 1.2;
}

.vf-section-contact .vf-form-note {
  margin: .8rem 0 0;
  font-size: .72rem;
  text-align: center;
  /* 55 % ergaben bei 11,5 px gemessene 3,97:1 (08.10.2026), 62 % ergeben
     4,89:1. Kleiner Text hat keinen Rabatt auf die 4,5 aus WCAG AA. */
  color: color-mix(in srgb, var(--inv-fg, #0f172a) 62%, transparent);
}

.vf-section-contact .vf-form-success,
.vf-section-contact .vf-form-error {
  padding: 14px 16px;
  border-radius: var(--inv-radius-sm, 10px);
  font-size: .9rem;
}

.vf-section-contact .vf-form-success { background: color-mix(in srgb, #12795c 14%, transparent); color: #0b5741; }
.vf-section-contact .vf-form-error   { background: color-mix(in srgb, #ef4444 12%, transparent); color: #9b1c1c; margin-bottom: 1rem; }

/* -------------------------------------------------------------
   Responsive
   ------------------------------------------------------------- */
/* One set of breakpoints for the whole page.
 *
 * The bento, and the sections built around it, change at 991px and 767px. This
 * section used to change at its own width, so on a tablet you could be looking
 * at one section already stacked and the next still in two columns. */
@media (max-width: 991px) {
  /* `grid-template-areas: none` is the line this block was missing.
   *
   * One column was declared, but the two-row area map from the split variants
   * stayed in force — and an area map declares its own columns, so the grid kept
   * a second, auto-sized track for `media`. The picture took it and the form was
   * left with what remained: measured, the contact form was 42 px wide at 768 px
   * and 30 px wide at 390 px, a column of inputs too narrow to type a name into.
   * Releasing the map also gives `order` back its say — with an explicit
   * grid-area, `order: -1` on the picture did nothing. */
  .vf-contact-grid,
  .vf-contact--split .vf-contact-grid,
  .vf-contact--split-left .vf-contact-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: none;
  }

  .vf-contact-aside,
  .vf-contact--split .vf-contact-aside,
  .vf-contact--split-left .vf-contact-aside { position: static; }

  .vf-contact--split .vf-contact-aside,
  .vf-contact--split .vf-contact-form,
  .vf-contact--split .vf-contact-media,
  .vf-contact--split-left .vf-contact-aside,
  .vf-contact--split-left .vf-contact-form,
  .vf-contact--split-left .vf-contact-media {
    grid-area: auto;
    grid-column: 1;
  }

  /* The picture leads on a phone: it is the thing being scrolled past. */
  .vf-contact--split .vf-contact-media,
  .vf-contact--split-left .vf-contact-media {
    position: relative;
    inset: auto;
    width: 100%;
    order: -1;
    align-self: auto;
    margin-bottom: clamp(18px, 3vw, 28px);
  }

  /* A letterbox shape for the two fits that have a cell to fill — on a phone a
     4:5 portrait would take most of the first screen before the form starts.
     "full" keeps the picture's own proportions here too: that is the whole
     point of it, and a phone is where a cropped picture is most obvious. */
  .vf-contact-fit-cover.vf-contact--split .vf-contact-media,
  .vf-contact-fit-cover.vf-contact--split-left .vf-contact-media,
  .vf-contact-fit-contain.vf-contact--split .vf-contact-media,
  .vf-contact-fit-contain.vf-contact--split-left .vf-contact-media {
    aspect-ratio: 16 / 10;
  }
}

@media (max-width: 767px) {
  .vf-section-contact .vf-form-row.vf-two-col,
  .vf-section-contact .vf-form-row.vf-three-col { grid-template-columns: minmax(0, 1fr); }

  /* One column already puts the name on its own row. */
  .vf-section-contact .vf-form-row.vf-three-col > .vf-field:first-child { grid-column: auto; }
  .vf-contact-capsule { padding-inline: var(--inv-gutter, 18px); }
}

@media (max-width: 420px) {
  .vf-contact-capsule { padding: 20px 14px; }

  .vf-section-contact .vf-contact-form { padding: 16px 14px; }
}

@media (prefers-reduced-motion: reduce) {
  /* No zoom, no fade — and, because both are @keyframes now, no transform left
     standing at 1.04 either. The picture is simply there. */
  .vf-section-contact.is-revealed .vf-contact-media img,
  .vf-section-contact.vf-contact-fit-cover.is-revealed .vf-contact-media img {
    animation: none;
  }
}

/* The section's own button ink, handed to the shared button styles. Unset it
   resolves to nothing and the chosen style keeps its own colour. */
.vf-section-contact {
  --inv-btn-ink: var(--vf-contact-btn-ink);
}

/* Das Lockfeld gegen Formular-Skripte.
 *
 * Nicht display:none — manche Skripte überspringen genau das, und manche
 * Browser lassen ein so verstecktes Pflichtfeld nicht validieren. Statt dessen
 * aus dem Fluss genommen und auf einen Punkt geschnitten: im Dokument
 * vorhanden, auf dem Schirm nicht. Aus dem Tab-Weg und aus dem Vorlesebaum
 * nimmt es die Auszeichnung selbst (tabindex -1, aria-hidden).
 *
 * Logische Eigenschaften, kein left: -9999px — das wandert in einer
 * RTL-Sprache mitten in die Seite. */
.vf-hp {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
