/* =============================================================
   Komponenten

   Konvention: .block, .block__element, .block--variante.
   Schriftgrößen kommen aus den Textrollen in base.css, Farben
   und Maße aus tokens.css — hier steht nur, was die Komponente
   selbst ausmacht.
   ============================================================= */

/* --- Button -------------------------------------------------
   Im Figma geflachte Vektoren (47:964, 225 x 50). Aus dem SVG
   gelesen: rx="9". Schriftfamilie kommt aus base.css.
   ------------------------------------------------------------ */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3.125rem; /* 50px bei Standardschriftgroesse */
  padding-inline: var(--space-m);
  border-radius: var(--radius-button);
  background-color: var(--color-accent);
  color: var(--color-button-text);
  font-size: var(--text-button);
  /* Eigene Zeilenhoehe statt der geerbten: Im Footer gilt 1.444,
     die Beschriftung sass dadurch in einem 39px hohen Zeilenkasten.
     Bei einem Knopf traegt die Zeilenhoehe nichts bei — die Hoehe
     macht min-height, die Mitte das Flexbox-Zentrieren. */
  line-height: 1;
  /* Keine Sperrung und keine Versalien: Im Entwurf steht die
     Beschriftung klein und ungesperrt. Soyuz ist unicase, sichtbar
     waeren Versalien also nicht — wohl aber in der Ersatzschrift. */
  text-decoration: none;
  /* Lange Beschriftungen duerfen auf schmalen Fenstern umbrechen —
     „Externe Inhalte laden" passte bei 320px sonst nicht mehr in
     den Ausschnitt. Die Hoehe ist eine Mindesthoehe, der Knopf
     waechst also einfach mit. Kurze Beschriftungen bleiben ohnehin
     einzeilig. */
  max-width: 100%;
  text-wrap: balance;
  transition:
    background-color var(--duration-base) var(--ease),
    color var(--duration-base) var(--ease);
}

.button:hover {
  background-color: var(--color-button-hover-bg);
  color: var(--color-button-hover-text);
  opacity: 1;
}

/* Heller Button auf dunklem Grund, z. B. „weiter" im Buchungs-
   stepper (12.1). */
.button--light {
  background-color: var(--color-steingrau);
  color: var(--color-urbangrau);
}

.button--light:hover {
  background-color: var(--color-accent);
  color: var(--color-button-text);
}

/* Dunkle Flaeche statt Koralle — so steht „senden" im Kontaktformular
   (49:1679). Der Kontrast ist hier der beste der drei Varianten:
   Steingrau auf Urbangrau sind 11.9:1. */
.button--dunkel {
  background-color: var(--color-urbangrau);
  color: var(--color-steingrau);
}

.button--dunkel:hover {
  background-color: var(--color-accent);
  color: var(--color-button-text);
}

/* „nach oben" vor dem Footer (49:621). Im Entwurf misst die Zeile
   160 x 20px; bei --text-section kommen wir auf 154 x 19 — deutlich
   naeher als die vorherigen 85 x 11 und ohne eigenen Token. */
.to-top {
  display: block;
  /* Im Entwurf steht die Zeile weit frei: 181px ueber und 180px
     unter ihr (Band endet 3440, Zeile 3621-3641, Footer ab 3821).
     Der vw-Wert trifft die 180 bei 1728px Artboardbreite. */
  margin-block: clamp(4rem, 10.42vw, 11.25rem);
  color: var(--color-accent);
  font-size: var(--text-section);
  line-height: 1;
  text-align: center;
}

/* --- Karte --------------------------------------------------
   438 x 652, Radius 25px, randabfallendes Bild (49:2162)
   ------------------------------------------------------------ */

.card {
  aspect-ratio: 438 / 652;
  overflow: hidden;
  border-radius: var(--radius-card);
  background-color: var(--color-placeholder);
}

/* --- Formularfelder -----------------------------------------
   Einzeilige Felder: nur Unterlinie (49:1632)
   Textarea: gerahmter Block mit Radius 25px (49:1637)
   ------------------------------------------------------------ */

/* Das Label steht im Feld und wandert beim Tippen darueber. Oben
   ist deshalb Platz reserviert — sonst schoebe es beim Aufsteigen
   das Feld darueber an. */
.field {
  position: relative;
  padding-top: var(--schwebe-weg);

  /* Weg des Labels und seine Ruhelage. Die Ruhelage sitzt auf der
     Grundlinie des Eingabetexts, haengt also am Innenabstand des
     jeweiligen Feldes. */
  --schwebe-weg: 1.5rem;
  --label-oben: calc(var(--schwebe-weg) + var(--space-2xs));
  /* Das geschrumpfte Label klebt nicht oben in der Luecke, sondern
     sitzt dicht ueber dem Text. Sein Zeilenkasten ist geschrumpft
     19,6px hoch; mit diesem Versatz bleiben darunter gut 4px Luft
     zur ersten Textzeile. Beim einzeiligen Feld darf er dabei in
     dessen oberen Innenabstand ragen — dort ist keine Kante. */
  --label-hoch: calc(var(--label-oben) - var(--space-2xs));
}

/* Das Textfeld hat im Gegensatz zu den einzeiligen Feldern eine
   Kante oben. Das Label kann dort nicht hineinragen, es braucht
   also mehr Platz darueber. */
.field:has(.field__textarea) {
  --schwebe-weg: 2rem;
  --label-oben: calc(var(--schwebe-weg) + var(--space-s));
}

/* Kein eigener Abstand: Der reservierte Platz ueber dem Label
   trennt die Felder schon. Im Entwurf liegen sie 68px auseinander. */
.field + .field {
  margin-top: 0;
}

/* Im Markup steht das Label hinter dem Feld — nur so erreicht der
   Geschwisterselektor es. Verknuepft sind beide ueber for/id, die
   Reihenfolge im Quelltext aendert daran nichts. */
.field__label {
  position: absolute;
  inset-block-start: var(--label-oben);
  inset-inline-start: var(--space-s);
  transform-origin: left top;
  color: var(--color-label);
  font-size: var(--text-body);
  line-height: var(--leading-nav);
  /* Ein Klick soll das Feld treffen, nicht das Label darueber. */
  pointer-events: none;
  transition:
    transform var(--duration-base) var(--ease),
    color var(--duration-fast) var(--ease);
}

/* Beim Fokus und sobald etwas drinsteht. Fuer den zweiten Fall
   braucht das Feld ein placeholder-Attribut — ein Leerzeichen
   genuegt, sichtbar wird es nie. */
.field__input:focus ~ .field__label,
.field__input:not(:placeholder-shown) ~ .field__label,
.field__textarea:focus ~ .field__label,
.field__textarea:not(:placeholder-shown) ~ .field__label {
  transform: translateY(calc(var(--label-hoch) * -1)) scale(0.727);
}

.field__input:focus ~ .field__label,
.field__textarea:focus ~ .field__label {
  color: var(--color-accent-text);
}

.field__input,
.field__textarea {
  width: 100%;
  background: transparent;
  font-size: var(--text-body);
  transition: border-color var(--duration-fast) var(--ease);
}

.field__input {
  padding: var(--space-2xs) var(--space-s);
  border: 0;
  border-bottom: var(--border-width) solid var(--color-border);
  line-height: var(--leading-nav);
}

.field__textarea {
  /* Im Entwurf 430px. Halbiert — 430 waren fuer eine Nachricht
     mehr Flaeche, als sie meist braucht, und der Knopf rutschte
     weit unter die Falz. */
  min-height: 13.4375rem;
  padding: var(--space-s);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-card);
  line-height: var(--leading-body);
  resize: vertical;
}

/* Der Fokus zeigt sich an der Feldkante selbst, nicht als Kasten
   darum herum. Der Rahmen aus dem Reset umschloss auch die Luecke,
   in die das Label aufsteigt — es stand dann ausserhalb seines
   eigenen Feldes. Die Linie wird dafuer doppelt so stark und
   wechselt die Farbe, damit der Fokus deutlich bleibt. */
.field__input:focus-visible,
.field__textarea:focus-visible {
  outline: none;
}

.field__input:focus,
.field__textarea:focus {
  border-color: var(--color-accent);
  border-width: calc(var(--border-width) * 2);
}

/* Die Unterlinie waechst nach unten, sonst haette das Feld beim
   Fokussieren einen Pixel weniger Innenhoehe und der Text ruckte. */
.field__input:focus {
  padding-block-end: calc(var(--space-2xs) - var(--border-width));
}

.field__textarea:focus {
  padding: calc(var(--space-s) - var(--border-width));
}

/* Der Platzhalter traegt nur das Leerzeichen, das :placeholder-shown
   braucht — er darf nichts anzeigen, das Label steht ja im Feld. */
.field__input::placeholder,
.field__textarea::placeholder {
  color: transparent;
}

/* Wer die Bewegung abbestellt hat, bekommt den Sprung ohne Weg. */
@media (prefers-reduced-motion: reduce) {
  .field__label {
    transition-duration: 1ms;
  }
}

/* --- Externe Einbettung (Synaptos) --------------------------
   Die Buchungs- und Fragebogenstrecke ist ein externer Dienst,
   im Design mittig in der 748px-Spalte (12.1-12.6, 13.1-13.3).

   Die Datenschutzeinstellung (44:268) führt Synaptos unter
   „Externe Inhalte" — der Embed lädt erst nach Einwilligung.
   ------------------------------------------------------------ */

.embed {
  max-width: var(--layout-measure);
  margin-inline: auto;
}

/* Cross-origin: wächst nicht mit dem Inhalt mit, die Höhe wird
   pro Einbettung gesetzt. Synaptos deckelt die Breite bei 996px. */
.embed iframe {
  display: block;
  width: 100%;
  max-width: 996px;
  /* derselbe Abstand wie der Einwilligungskasten, an dessen Stelle
     der Rahmen tritt */
  margin-top: var(--space-xl);
  border: 0;
  color-scheme: light;
}

.embed__consent {
  margin-top: var(--space-xl);
  padding: var(--space-xl);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-card);
  text-align: center;
}

.embed__consent > * + * {
  margin-top: var(--space-m);
}

/* --- Standortkarte ------------------------------------------
   Selbst gehostete Karte (MapLibre GL + PMTiles). Im Entwurf
   905 x 652 neben einem 438 breiten Bild (148:804 / 49:1667).

   Anders als der Synaptos-Embed braucht sie kein Einwilligungs-
   Gate: die Kacheln liegen unter assets/map/, es geht keine
   Anfrage an Dritte.
   ------------------------------------------------------------ */

.standortkarte {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-card);
  /* Grundton des Kartenstils — steht schon, bevor die erste Kachel
     da ist, damit die Flaeche nicht weiss aufblitzt. */
  background-color: #e7e3db;
}

/* Das Canvas wird als eigene Ebene zusammengesetzt und entkommt
   damit dem overflow:hidden des Containers. Sichtbar wird das erst,
   sobald Kacheln gezeichnet sind — die leere Flaeche sieht rund aus,
   die gezeichnete Karte hatte eckige Ecken. Es traegt die Rundung
   deshalb selbst. Bedienelemente und Infofenster liegen daneben und
   bleiben unbeschnitten. */
.standortkarte canvas {
  border-radius: var(--radius-card);
}

/* Ohne JavaScript bleibt der Behaelter leer. Die Adressen stehen
   ohnehin darunter, deshalb genuegt eine Mindesthoehe statt eines
   Ersatztextes im Nichts. */
.standortkarte:not(.maplibregl-map) {
  min-height: 20rem;
}

/* Die Marke: runder Punkt in Koralle mit hellem Ring, damit sie
   sich sowohl vom Grundton als auch von Gruenflaechen abhebt. */
.kartenmarke {
  width: 1.5rem;
  height: 1.5rem;
  border: 0.1875rem solid var(--color-steingrau);
  border-radius: 50%;
  background-color: var(--color-accent);
  box-shadow: 0 1px 4px rgb(0 0 0 / 0.35);
  cursor: pointer;
  transition: transform var(--duration-fast) var(--ease);
}

.kartenmarke:hover,
.kartenmarke:focus-visible {
  transform: scale(1.15);
}

/* MapLibre bringt eigene Fensterstile mit — hier auf die Typografie
   der Seite zurueckgeholt. */
.maplibregl-popup-content {
  padding: var(--space-s) var(--space-m);
  border-radius: var(--radius-button);
  background-color: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-serif);
  font-size: var(--text-small);
  line-height: var(--leading-body);
}

.kartenfenster strong {
  display: block;
  font-weight: var(--weight-bold);
}

.kartenfenster p {
  margin-top: var(--space-3xs);
}

.maplibregl-popup-tip {
  border-top-color: var(--color-bg);
  border-bottom-color: var(--color-bg);
}

/* „© powered by synaptos | Datenschutz" unter dem Embed */
.embed__credit {
  margin-top: var(--space-m);
  text-align: center;
}
