/*
  Ferienwohnung Almzeit — styles.
  One file, in page order. Every banner below is named exactly like the
  data-sid of the section it styles in index.html.

  The idea of the page: you look through a larch-framed window (the hero
  photograph). So the palette is what you see there — sky, snow, pale wood —
  and one deep blue-black for everything that has to be read.
  Below the window you are inside the flat: the page is its wall (WAND) and
  every picture and every text hangs on it in a frame of the same larch (RAHMEN).
*/

/* ======== SCHRIFTEN — two faces, self-hosted, latin subset ======== */
/* Cormorant: tall and thin, the voice of the house. Variable 300–700. */
@font-face {
  font-family: "Cormorant";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/cormorant-latin.woff2?v=356e67f0") format("woff2");
}
@font-face {
  font-family: "Cormorant";
  font-style: italic;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/cormorant-italic-latin.woff2?v=0b465a71") format("woff2");
}
/* Hanken Grotesk: everything that is information. Variable 300–700. */
@font-face {
  font-family: "Hanken Grotesk";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("fonts/hankengrotesk-latin.woff2?v=c501f578") format("woff2");
}
/* The stand-ins shown until the woff2 files arrive. size-adjust was measured
   in the browser (the same paragraph set in both faces, canvas measureText):
   Cormorant runs at 87.9% of Georgia's width, its italic at 79% of Georgia
   Italic, Hanken at 99.3% of Arial and its semibold at 94% of Arial Bold.
   ascent/descent are the web font's own (hhea 924/-287 and 1000/-303 per
   1000) divided by that factor. So the swap re-wraps no line and CLS stays 0
   on a slow connection. */
@font-face {
  font-family: "Cormorant Ersatz";
  src: local("Georgia");
  size-adjust: 87.9%;
  ascent-override: 105.1%;
  descent-override: 32.6%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Cormorant Ersatz";
  font-style: italic;
  src: local("Georgia Italic");
  size-adjust: 79%;
  ascent-override: 117%;
  descent-override: 36.3%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Hanken Ersatz";
  font-weight: 300 500;
  src: local("Arial");
  size-adjust: 99.3%;
  ascent-override: 100.7%;
  descent-override: 30.5%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Hanken Ersatz";
  font-weight: 600 700;
  src: local("Arial Bold");
  size-adjust: 94%;
  ascent-override: 106.4%;
  descent-override: 32.2%;
  line-gap-override: 0%;
}

/* ======== FARBEN UND MASSE — decided once, obeyed everywhere ======== */
:root {
  --schnee: #F7F9FB;        /* snow white: theme colour of the first screen */
  --weiss: #FFFFFF;         /* the sheet of paper the calendar is on */
  --tinte: #101B2B;         /* deep blue-black: all text */
  --tinte-weich: #3B4A5E;   /* secondary text, still 8:1 on snow */
  --himmel: #9CC7EA;        /* the sky itself, decoration only */
  --himmel-hell: #DDEBF6;   /* the chosen nights */
  --himmel-tief: #1D5E96;   /* the one colour that means "yours": arrival, departure, buttons, links */
  --laerche: #E7D5B7;       /* pale larch: frame, sill, footer */
  --laerche-hell: #F3E8D6;
  --laerche-tief: #8A6A3C;  /* the shadow line in the wood, never text */
  --linie: rgba(16, 27, 43, .16);

  --serif: "Cormorant", "Cormorant Ersatz", Georgia, serif;
  --sans: "Hanken Grotesk", "Hanken Ersatz", Arial, sans-serif;

  --rand: clamp(1.25rem, 5vw, 5rem);      /* page gutter */
  --ruhig: cubic-bezier(.4, 0, .2, 1);

  /* Below the window (WAND, RAHMEN). These six follow the season: summer here,
     winter in the block underneath. app.js sets data-jahreszeit on <html> in
     the same breath as on the window (setzeBlick). */
  --wandrand: clamp(.75rem, 3.4vw, 5rem);   /* gutter of the wall: tighter than --rand, a phone gives pictures the width */
  --wand: #EDE4D3;          /* limewash in afternoon light */
  --papier: #FBF6EC;        /* what text is written on */
  --karton: #F1EADB;        /* the passe-partout */
  --schatten: 70 48 20;     /* what a frame throws on the wall, as r g b */
  --holzlicht: saturate(1.08) brightness(1);
  --film: saturate(1.05) contrast(.95) brightness(1.03) sepia(.09);
  --film-glanz: rgba(255, 214, 150, .13);
  --film-rand: rgba(64, 38, 10, .42);
}
/* THE SEASON TRAVELS DOWN THE PAGE: in the snow months the same wall stands in
   blue daylight, the larch greys a little, and the photographs are graded cold. */
:root[data-jahreszeit="winter"] {
  --wand: #E3E7EA;
  --papier: #FAFBFC;
  --karton: #EAEEF1;
  --schatten: 30 46 74;
  --holzlicht: saturate(.72) brightness(1.03);
  --film: saturate(.9) contrast(.95) brightness(1.04) sepia(0);
  --film-glanz: rgba(176, 206, 238, .14);
  --film-rand: rgba(16, 32, 62, .42);
}

/* ======== GRUND — reset, type, links, focus ======== */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  color: var(--tinte);
  font: 400 1.0625rem/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}
img, svg { display: block; max-width: 100%; }
h1, h2, h3, p, ul, ol, dl, dd, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: var(--himmel-tief); text-underline-offset: .18em; }
a:hover { color: var(--tinte); }
button, input, select, textarea { font: inherit; color: inherit; }
/* One focus ring for the whole page: ink, 2px, off the element. */
:focus-visible { outline: 2px solid var(--tinte); outline-offset: 3px; }

h2 {
  font: 400 clamp(2.2rem, 5.2vw, 4.1rem)/1.04 var(--serif);
  letter-spacing: -.01em;
  text-wrap: balance;
}
h3 { font: 500 1.6rem/1.15 var(--serif); }

/* The small label over every section heading, with a sliver of larch. */
.marker {
  display: flex;
  align-items: center;
  gap: .8rem;
  margin-bottom: 1.1rem;
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--himmel-tief);
}
.marker::before { content: ""; width: 2.5rem; height: 2px; background: var(--laerche-tief); }

/* Text for screen readers only (the spoken half of a calendar day). */
.nur-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Keyboard users jump past the note and the navigation straight to the calendar. */
.sprung {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 20;
  padding: .7rem 1rem;
  background: var(--tinte);
  color: var(--weiss);
}
.sprung:focus { top: 1rem; color: var(--weiss); }

/* ======== HINWEIS — the visible "this is a demo" line ======== */
.erste {
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100svh;
  min-height: 35rem;
}
.hinweis {
  padding: .5rem var(--rand);
  background: var(--laerche-hell);
  /* A system face on purpose. This line is the studio speaking, not the house,
     and it is the first text on the screen: with no web font to wait for it
     can never re-wrap after the first paint (measured: that re-wrap was the
     page's only layout shift on a phone). */
  font-family: Arial, Helvetica, sans-serif;
  font-size: .875rem;
  line-height: 1.45;
  text-align: center;
}
/* The padding makes the link 44px tall for a thumb; the same margin taken back keeps the lines around it where they were. */
.hinweis a { display: inline-block; padding: .75rem 0; margin-block: -.75rem; color: var(--tinte); }

/* ======== BLICK — the window: the photograph, and words on its wood ======== */
/* The photograph is a window already (frame, lintel, sill), so the layout is
   measured in ITS proportions, not the screen's. .blick is a size container:
   1cqh is 1% of the window's height, and the 16:9 photograph is always exactly
   as tall as the window, so
     - the lintel is the top 14cqh, the sill the bottom 15cqh, on every screen;
     - a point at x% of the photograph sits at 50cqw + (x - 50) * 1.7778cqh.
   On a screen narrower than 16:9 the sides of the photograph are simply out of
   sight; on a wider one its dark outer edge is continued by the background. */
.blick {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow: hidden;
  isolation: isolate;
  container-type: size;
  background: #1C1008;
}
.blick__bilder {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 177.78cqh;
  /* A phone shows a 28%-wide slice. Centred a little right of the middle
     (56%), it holds the highest peak AND the farms in the valley. */
  margin-left: -99.5cqh;
  background: #8A7A66;
}
.blick__bild { position: absolute; inset: 0; width: 100%; height: 100%; }
/* THE moment of the page. Winter lies over summer and fades in; summer never
   fades out, so there is no dip to the background in between. */
.blick__bild--winter { opacity: 0; transition: opacity 1.4s var(--ruhig); }
.blick[data-jahreszeit="winter"] .blick__bild--winter { opacity: 1; }
/* Until app.js has given the winter view its file there is nothing to show,
   and an empty img must not paint its alt text over the summer view. */
.blick__bild--winter:not([srcset]) { visibility: hidden; }

/* The light of the month: a thin wash app.js tints (amber in October, blue in
   January), so two months with the same photograph still look different. */
.blick__licht {
  position: absolute;
  inset: 0;
  background-color: var(--licht, transparent);
  /* The lintel's own shade: grain highlights in the beam would otherwise let
     the white name and links dip under 4.5:1 (measured on rendered pixels). It
     stops where the lintel stops, so the sky below is untouched. */
  background-image: linear-gradient(to bottom, rgba(28, 16, 8, .3), rgba(28, 16, 8, .22) 9cqh, rgba(28, 16, 8, 0) 15cqh);
  transition: background-color 1.4s var(--ruhig);
  pointer-events: none;
}

/* ON THE LINTEL: name, navigation, language. The beam is dark wood in both
   seasons (measured #7C6434 and #6E5D49), so this is the one place on the page
   where text is white. 3.4cqh from the top clears the photograph's dark edge. */
.blick__kopf {
  position: absolute;
  top: 3.4cqh;
  left: max(1rem, calc(50cqw - 80cqh));
  right: max(1rem, calc(50cqw - 80cqh));
  z-index: 3;
  display: flex;
  align-items: center;
  gap: 1.5rem;
  height: 10cqh;
  color: var(--weiss);
  text-shadow: 0 1px 10px rgba(28, 16, 8, .6);
}
.marke { margin-right: auto; }
.marke__art {
  display: block;
  font: 600 clamp(.75rem, 1.5cqh, .8rem)/1 var(--sans);
  letter-spacing: .24em;
  text-transform: uppercase;
}
/* The wordmark is sized by the beam it is written on. */
.marke__name { display: block; margin-left: -.03em; font: 400 7.6cqh/.92 var(--serif); letter-spacing: -.01em; }
/* The six links need the beam of a wide screen; below 1100px the page is one
   scroll and the sheet's button leads to the request. */
.blick__nav { display: none; gap: 1.4rem; }
.blick__nav a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0;
  color: var(--weiss);
  font-size: .95rem;
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
}
.blick__nav a:hover { text-decoration: underline; }
.blick__kopf :focus-visible { outline-color: var(--weiss); }

/* Its button is inserted after the page has loaded; the room is reserved, or the
   links beside it would slide left when it arrives (the page's one layout shift). */
.lang-host { display: block; min-width: 3rem; min-height: 2.75rem; }
/* The studio's language switch (/js/i18n.js), dressed for this page. */
.wdm-lang {
  --wdm-lang-bg: rgba(255, 255, 255, .94);
  --wdm-lang-fg: var(--tinte);
  --wdm-lang-border: rgba(16, 27, 43, .4);
  --wdm-lang-font: var(--sans);
  text-shadow: none;
}
/* This demo speaks German and English only. */

/* IN THE SKY: the one sentence. Ink on sky blue (measured #A1CEF7, 10:1); the
   soft white halo is for the moment a cloud edge or a peak passes behind it. */
.blick__satz {
  position: absolute;
  top: 16cqh;
  left: 1.1rem;
  z-index: 2;
  max-width: min(21rem, calc(100cqw - 2.2rem));
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
  text-shadow: 0 0 .7rem rgba(255, 255, 255, .95), 0 0 .25rem rgba(255, 255, 255, .8);
}

/* The sill carries text from tablet up; on a phone the sheet lies on it. */
.blick__bank { display: none; }

/* ======== BLATT — the calendar sheet: bottom sheet on phones ======== */
.blatt {
  --guck: 6.6rem;   /* how much of the closed sheet looks out: month line + handle */
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  display: flex;
  flex-direction: column;
  /* A fixed height, so nothing on the sheet moves when a month has six weeks
     or the price lines appear. Never the whole window: a strip of the view
     stays above it, and that strip is where the season is seen to change. */
  height: 34.5rem;
  /* Open, it takes about half the phone: what is left above it is the strip
     in which the season is seen to change (see "the view lifts" below). */
  max-height: min(calc(100% - 5.5rem), 56svh);
  padding-top: 1.1rem;
  background: var(--weiss);
  border-radius: 14px 14px 0 0;
  box-shadow: 0 -14px 40px rgba(16, 27, 43, .28);
  /* Closed: pushed down until only --guck is left. transform, so opening it
     never moves anything else on the page. */
  transform: translateY(calc(100% - var(--guck)));
  transition: transform .55s cubic-bezier(.2, .8, .2, 1);
}
.blatt[data-offen] { transform: none; }
/* The little bar every bottom sheet has: "this can be pulled up". */
.blatt::before {
  content: "";
  position: absolute;
  top: .45rem;
  left: 50%;
  width: 2.5rem;
  height: 4px;
  margin-left: -1.25rem;
  border-radius: 2px;
  background: var(--linie);
}
.blatt__blick {
  flex: none;
  padding: 0 1.1rem;
  font: italic 500 1.35rem/1.75rem var(--serif);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.blatt__griff {
  flex: none;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: .1rem 1rem;
  width: 100%;
  height: 3.75rem;
  padding: 0 1.1rem;
  border: 0;
  background: none;
  text-align: left;
  cursor: pointer;
}
.blatt__frage { font-weight: 600; font-size: 1.05rem; }
.blatt__wahl {
  grid-column: 1;
  overflow: hidden;
  color: var(--tinte-weich);
  font-size: .9rem;
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* Chevron: up when closed (pull me), down when open. */
.blatt__griff::after {
  content: "";
  grid-column: 2;
  grid-row: 1 / span 2;
  width: .7rem;
  height: .7rem;
  border: solid var(--tinte);
  border-width: 2px 0 0 2px;
  transform: translateY(.2rem) rotate(45deg);
  transition: transform .3s var(--ruhig);
}
.blatt__griff[aria-expanded="true"]::after { transform: translateY(-.15rem) rotate(225deg); }
.blatt__koerper {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: .2rem 1.1rem .6rem;
  border-top: 1px solid var(--linie);
}
/* On a phone the handle already asks the question. */
.blatt__titel { display: none; }

/* The way on to the request, shown only on the closed sheet of a finished stay. */
/* .blatt in front: .knopf (further down) would otherwise win the display. */
.blatt .blatt__weiter { display: none; flex: none; margin: .1rem 1.1rem 1rem; }

@media (max-width: 719px) {
  /* The view lifts while the calendar is open: the photograph moves up behind
     the sheet until the peaks and the upper valley stand in the strip above it.
     transform only, so nothing is re-laid-out and CLS stays 0. Browsing months
     then flips summer and winter right there. */
  .blick__bilder { transition: transform .55s cubic-bezier(.2, .8, .2, 1); }
  .blick:has(.blatt[data-offen]) .blick__bilder { transform: translateY(-20cqh); }
  /* The lintel has lifted out of sight, so name and language now stand on the
     sky: ink with the same white halo the sentence uses, and the sentence
     itself makes room for the peaks. */
  .blick__kopf, .blick__satz { transition: color .55s var(--ruhig), text-shadow .55s var(--ruhig), opacity .4s var(--ruhig); }
  .blick:has(.blatt[data-offen]) .blick__kopf {
    color: var(--tinte);
    text-shadow: 0 0 .7rem rgba(255, 255, 255, .95), 0 0 .25rem rgba(255, 255, 255, .8);
  }
  .blick:has(.blatt[data-offen]) .blick__kopf :focus-visible { outline-color: var(--tinte); }
  .blick:has(.blatt[data-offen]) .blick__satz { opacity: 0; pointer-events: none; }
  /* A finished stay folds the sheet to dates, nights, total and this button. */
  .blatt[data-summe]:not([data-offen]) { --guck: 10.5rem; }
  .blatt[data-summe]:not([data-offen]) .blatt__weiter { display: block; }
  /* The language button keeps its look; its hit area grows to 44 x 44. */
  .wdm-lang__btn { position: relative; min-height: 2.75rem; min-width: 2.75rem; }
  /* The handle asks "when do you come" once; the sentence in the sky asked it a second time. */
  .blick__satz { display: none; }
}
.wdm-lang__list li { min-height: 2.75rem; display: flex; align-items: center; }

/* ======== KALENDER — the month grid inside the sheet ======== */
.kal__kopf { display: flex; align-items: center; justify-content: space-between; padding: .2rem 0; }
.kal__monat { position: relative; display: flex; align-items: center; gap: .45rem; min-height: 2.75rem; padding: 0 .4rem; font: 500 1.45rem/1 var(--serif); }
/* A small chevron says the title is a list. The select lies over it, invisible, so a tap opens the phone's own picker. */
.kal__monat::after { content: ""; width: .5rem; height: .5rem; border: solid var(--tinte); border-width: 0 2px 2px 0; transform: translateY(-.15rem) rotate(45deg); }
.kal__wahl { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: pointer; font-size: 1rem; }
.kal__monat:has(.kal__wahl:focus-visible) { outline: 2px solid var(--tinte); outline-offset: 2px; }
.kal__pfeil {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border: 1px solid var(--linie);
  border-radius: 50%;
  background: var(--weiss);
  cursor: pointer;
}
.kal__pfeil:hover { background: var(--himmel-hell); }
.kal__pfeil[aria-disabled="true"] { opacity: .35; cursor: default; }

.kal__gitter { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 0 2px; }
.kal__gitter th {
  height: 1.5rem;
  padding: 0;
  color: var(--tinte-weich);
  font-size: .72rem;
  line-height: 1;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.kal__gitter td { padding: 0; }

/* One day. The number on top, the night's price under it: the price is on the
   page before anyone has asked for it. Always 6 rows of these, so the sheet
   keeps its height from month to month. */
.tag {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .12rem;
  width: 100%;
  height: 2.75rem;   /* 44px for a thumb; 2.5rem from 720px, see there */
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: none;
  font-size: .95rem;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  cursor: pointer;
}
.tag small { color: var(--tinte-weich); font-size: .75rem; }
.tag:hover { background: var(--himmel-hell); }
.tag:focus-visible { outline-offset: 1px; z-index: 1; }
/* Today: a short larch underline, nothing louder. */
.tag.is-heute::after {
  content: "";
  position: absolute;
  bottom: 2px;
  left: 35%;
  right: 35%;
  height: 2px;
  background: var(--laerche-tief);
}
/* Past days and days without a price yet; a free night that can never start a stay looks the same, minus the price. */
.tag.is-zu, .tag.is-tot { color: #66717F; cursor: default; }
.tag.is-zu:hover, .tag.is-tot:hover, .tag.is-zu-kurz:hover { background: none; }
/* After an arrival is chosen: fewer nights than the season allows. Dimmed, not a departure. */
.tag.is-zu-kurz { color: #66717F; cursor: not-allowed; }
/* Taken night, free morning: half free, half hatched, no strike. Tappable only as the departure of a chosen arrival. */
.tag.is-nur-ab {
  background: linear-gradient(135deg, var(--weiss) 0 50%, transparent 50%), repeating-linear-gradient(135deg, var(--laerche-hell) 0 4px, #FBF6EC 4px 8px);
  color: var(--tinte);
  text-decoration: none;
}
.tag.is-nur-ab[aria-disabled="true"] { cursor: not-allowed; }
.tag.is-nur-ab:hover { background: linear-gradient(135deg, var(--himmel-hell) 0 50%, transparent 50%), repeating-linear-gradient(135deg, var(--laerche-hell) 0 4px, #FBF6EC 4px 8px); }
/* Taken: struck through on a larch hatch, the way a paper calendar on a
   kitchen wall gets crossed out. */
.tag.is-belegt {
  color: #4A5568;
  text-decoration: line-through;
  background: repeating-linear-gradient(135deg, var(--laerche-hell) 0 4px, #FBF6EC 4px 8px);
  cursor: not-allowed;
}
/* The nights in between, and the preview while the departure is still open. */
.tag.is-drin, .tag.is-vorschau { background: var(--himmel-hell); border-radius: 0; text-decoration: none; }
.tag.is-vorschau { background: #EAF2F9; }
/* Arrival and departure: the one deep blue on the sheet. */
.tag.is-an, .tag.is-ab {
  background: var(--himmel-tief);
  color: var(--weiss);
  text-decoration: none;
  cursor: pointer;
}
.tag.is-an small, .tag.is-ab small { color: var(--weiss); }
.tag.is-an { border-radius: 1.25rem 0 0 1.25rem; }
.tag.is-ab { border-radius: 0 1.25rem 1.25rem 0; }

/* Phones get the legend too: it is how a guest learns what the half-hatched day means. */
.kal__legende { display: flex; flex-wrap: wrap; gap: .2rem 1rem; padding: .45rem 0 .1rem; font-size: .76rem; color: var(--tinte-weich); }
.kal__legende li { display: flex; align-items: center; gap: .4rem; }
.kal__legende li::before { content: ""; width: .8rem; height: .8rem; border-radius: 2px; border: 1px solid var(--linie); }
.kal__legende-belegt::before { background: repeating-linear-gradient(135deg, var(--laerche) 0 2px, #FBF6EC 2px 4px); }
.kal__legende-nurab::before { background: linear-gradient(135deg, var(--weiss) 0 50%, transparent 50%), repeating-linear-gradient(135deg, var(--laerche) 0 2px, #FBF6EC 2px 4px); }
.kal__legende-wahl::before { background: var(--himmel-tief); }

/* ======== STAND — nights, price per night, total (sheet and request) ======== */
.stand {
  margin-top: .35rem;
  padding-top: .55rem;
  border-top: 1px solid var(--linie);
  font-size: .92rem;
}
.stand__hinweis { color: var(--tinte-weich); }
/* A refusal ("a taken night lies in between") speaks in ink with a larch bar,
   not in alarm red: nothing broke, the calendar just said no. */
.stand__nein { margin-bottom: .5rem; padding-left: .7rem; border-left: 3px solid var(--laerche-tief); font-weight: 600; }
.stand__kopf { display: flex; justify-content: space-between; align-items: baseline; gap: .75rem; font-weight: 600; }
.stand__leeren {
  flex: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--himmel-tief);
  font-size: .82rem;
  text-decoration: underline;
  cursor: pointer;
}
.stand__zeilen { margin-top: .35rem; }
.stand__zeilen div { display: flex; justify-content: space-between; gap: 1rem; padding: .08rem 0; color: var(--tinte-weich); }
.stand__zeilen dd { font-variant-numeric: tabular-nums; white-space: nowrap; }
/* The total and the way on to the request, side by side where they fit. */
.stand__ende {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem 1rem;
  margin-top: .35rem;
  padding-top: .45rem;
  border-top: 1px solid var(--linie);
}
.stand__gesamt { display: grid; grid-template-columns: auto auto; align-items: baseline; column-gap: .6rem; font-weight: 600; }
.stand__gesamt b { font: 500 1.85rem/1 var(--serif); }
.stand__gesamt small { grid-column: 1 / -1; color: var(--tinte-weich); font-size: .78rem; font-weight: 400; }

.knopf {
  display: inline-block;
  padding: .85rem 1.5rem;
  border: 0;
  border-radius: 2px;
  background: var(--himmel-tief);
  color: var(--weiss);
  font-weight: 600;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .2s var(--ruhig);
}
.knopf:hover { background: var(--tinte); color: var(--weiss); }
.stand .knopf { flex: 1 1 9rem; padding: .7rem .9rem; }

/* ======== BLICK + BLATT ab 720px — left pane wordmark, right pane calendar ======== */
@media (min-width: 720px) {
  .erste { min-height: 46rem; }
  .blick__bilder { margin-left: -88.89cqh; }   /* the photograph centred */
  /* The sheet hangs on the right jamb; lintel text ends before it. */
  .blick { --blatt-rechts: max(1rem, calc(50cqw - 85cqh)); }
  .blick__kopf { right: calc(var(--blatt-rechts) + 24rem + 1.5rem); }
  .blick__satz { left: 1.25rem; max-width: min(19rem, calc(100cqw - 24rem - 4rem)); font-size: 1.0625rem; }

  /* ON THE SILL, left of the mug (the mug starts at 47% of the photograph):
     a slip of paper, the way a host leaves a note for whoever arrives. Paper,
     because weathered wood under an amber October wash is no ground to read
     small type on; the slip makes the month and the price ink on white. */
  .blick__bank {
    position: absolute;
    left: max(1.25rem, calc(50cqw - 77cqh));
    bottom: 3.6cqh;
    z-index: 2;
    display: block;
    max-width: calc(50cqw - 7cqh - max(1.25rem, calc(50cqw - 77cqh)));
    padding: .55rem 1.1rem .6rem;
    background: var(--weiss);
    box-shadow: 0 10px 22px -8px rgba(28, 16, 8, .6), 0 1px 3px rgba(28, 16, 8, .3);
    transform: rotate(-1.2deg);
  }
  .blick__monat { font: italic 500 clamp(1.4rem, 3.4cqh, 2rem)/1.15 var(--serif); white-space: nowrap; }
  .blick__fakten { display: flex; flex-wrap: wrap; font-size: .9rem; font-weight: 500; line-height: 1.5rem; }
  .blick__fakten li + li::before { content: "·"; margin: 0 .6rem; }
  /* The narrow sill of a tablet keeps one fact: the price. */
  .blick__fakten li:not([data-ab-preis]) { display: none; }
  .blick__fakten li[data-ab-preis]::before { content: none; }

  /* The sheet stops being a drawer and becomes a piece of paper hung in the
     right pane. Always open, so the handle and its month line go. */
  .blatt {
    left: auto;
    right: var(--blatt-rechts);
    top: max(1rem, 3.4cqh);
    bottom: auto;
    width: 24rem;
    height: auto;
    max-height: none;
    padding: 1.2rem 1.25rem 1.1rem;
    border-radius: 3px;
    box-shadow: 0 34px 60px -24px rgba(28, 16, 8, .7), 0 2px 10px rgba(28, 16, 8, .3);
    transform: none;
    transition: none;
  }
  .blatt::before, .blatt__blick, .blatt__griff { display: none; }
  /* On the paper every month is drawn six weeks tall and the grid has that
     height before app.js has drawn a single day: the price lines below it
     never move, not at load and not from month to month.
     1.5rem weekday row + 6 day rows + the 2px gaps around all 7 rows. */
  .tag, .kal__gitter td { height: 2.75rem; }
  .tag small { font-size: .75rem; }
  .kal__gitter { height: calc(1.5rem + 6 * 2.75rem + 16px); }
  /* Room for the full sum from the start, so the paper keeps its size while
     the nights are being chosen. */
  .blatt .stand { min-height: 9.6rem; }
  .blatt__koerper { overflow: visible; padding: 0; border-top: 0; }
  /* Two lines reserved: German needs two, Italian one. The paper hangs from its top edge, so a title
     that re-wraps when the translation arrives would push the whole calendar up by a line. */
  .blatt__titel { display: block; margin-bottom: .5rem; font-size: 2rem; min-height: 2lh; }
}
@media (min-width: 1100px) {
  .blick__nav { display: flex; }
  .blick__fakten li:not([data-ab-preis]) { display: block; }
  .blick__fakten li[data-ab-preis]::before { content: "·"; }
  /* Wide enough to stand between the two open casements (29% of the photograph). */
  .blick__satz { left: calc(50cqw - 37cqh); max-width: 21rem; }
}

/* ======== BLICK hochkant — portrait phones get their own photograph of the same window ======== */
/* A 16:9 window cut down to a phone shows a strip of valley and no frame at
   all. So portrait phones load a 9:16 photograph of the same window
   (index.html, <picture>) and everything is placed in ITS proportions: the
   lintel is the top 7%, the sill the bottom 14%, the casements stand at
   5–19% and 82–95%, the mug's rim at 50.4% / 84%. The photograph is as
   tall as the window (or as wide as the phone, whichever is larger) and
   centred. Its lintel is the same brown beam (measured #7B6740, white on it
   5.4:1 before any shade), so the name stays white and the shade only gets
   shorter, as short as this lintel. If a portrait file is missing, index.html
   sets .blick--quer and all of this steps aside for the landscape photograph. */
@media (max-width: 719px) and (orientation: portrait) {
  .blick:not(.blick--quer) .blick__bilder {
    top: 50%;
    bottom: auto;
    width: max(100cqw, 56.25cqh);
    aspect-ratio: 9 / 16;
    margin-left: 0;
    translate: -50% -50%;
  }
  .blick:not(.blick--quer) .blick__licht { background-image: linear-gradient(to bottom, rgba(28, 16, 8, .3), rgba(28, 16, 8, .22) 5cqh, rgba(28, 16, 8, 0) 8cqh); }
  .blick:not(.blick--quer) .blick__kopf { top: .4cqh; height: 6.5cqh; }
  .blick:not(.blick--quer) .marke__art { font-size: .75rem; }
  .blick:not(.blick--quer) .marke__name { font-size: 4.8cqh; }
  /* The sentence stands in the sky between the two casements. */
  .blick:not(.blick--quer) .blick__satz { top: 9.5cqh; left: max(1.1rem, calc(50cqw - 16cqh)); max-width: min(32cqh, calc(100cqw - 2.2rem)); }
  /* Snow and steam, in this photograph's percentages (LEBEN). */
  .blick:not(.blick--quer) .schnee { left: 19%; right: 18%; top: 8%; bottom: 17%; }
  .blick:not(.blick--quer) .dampf { left: 50.4%; top: 84.3%; }
}

/* ======== LEBEN — what moves inside the window photograph: steam and snow ======== */
/* Additive to BLICK: nothing above is moved by this. Both are placed in the
   photograph's own percentages (the opening between the two casements is
   29–74% across and 14.5–79% down, the mug's rim sits at 50.3% / 80%), so they
   stay on the mug and outside the frame on every screen. Only transform and
   opacity move. app.js adds .is-ruht while the window is out of sight. */
.blick__leben { position: absolute; inset: 0; pointer-events: none; }
.schnee, .dampf { display: none; }
@media (prefers-reduced-motion: no-preference) {
  /* Snow falls OUTSIDE: clipped to the opening, faded out before the sill,
     so no flake ever crosses the larch or the mug. */
  .schnee {
    display: block;
    position: absolute;
    left: 29%;
    right: 26%;
    top: 14.5%;
    bottom: 21%;
    overflow: hidden;
    opacity: 0;
    transition: opacity 1.4s var(--ruhig);
    -webkit-mask-image: linear-gradient(#000 72%, transparent);
    mask-image: linear-gradient(#000 72%, transparent);
  }
  .blick[data-jahreszeit="winter"] .schnee { opacity: 1; }
  /* Three depths. Each layer is one repeating tile of flakes that travels
     exactly one tile height (--weg) along its slanted axis, so the loop has no
     seam. */
  .schnee i {
    --weg: 360px;
    --schraeg: 9deg;
    position: absolute;
    inset: -420px -18% -12% -18%;
    background-image:
      radial-gradient(circle at 22px 40px, #fff 0 1.7px, transparent 2.4px),
      radial-gradient(circle at 131px 96px, #fff 0 1.3px, transparent 2px),
      radial-gradient(circle at 78px 188px, #fff 0 1.9px, transparent 2.6px),
      radial-gradient(circle at 186px 250px, #fff 0 1.4px, transparent 2.1px),
      radial-gradient(circle at 44px 312px, #fff 0 1.2px, transparent 1.9px);
    background-size: 170px 360px;
    animation: schneit 10s linear infinite;
  }
  .schnee i:nth-child(2) { --weg: 300px; --schraeg: 6deg; background-size: 130px 300px; opacity: .8; animation-duration: 15s; }
  .schnee i:nth-child(3) { --weg: 240px; --schraeg: 12deg; background-size: 100px 240px; opacity: .6; animation-duration: 23s; }
  @keyframes schneit {
    from { transform: rotate(var(--schraeg)) translate3d(0, 0, 0); }
    to { transform: rotate(var(--schraeg)) translate3d(0, var(--weg), 0); }
  }
  .blick:not([data-jahreszeit="winter"]) .schnee i { animation-play-state: paused; }

  /* Steam: three soft wisps that rise from the rim and thin out. */
  .dampf { display: block; position: absolute; left: 50.3%; top: 80%; }
  .dampf i {
    position: absolute;
    left: -2cqh;
    bottom: 0;
    width: 4cqh;
    height: 10cqh;
    border-radius: 50%;
    background: radial-gradient(closest-side, rgba(255, 255, 255, .95), rgba(255, 255, 255, .5) 45%, rgba(255, 255, 255, 0));
    filter: blur(.35cqh);
    opacity: 0;
    transform-origin: 50% 100%;
    animation: dampft 6s ease-out infinite;
  }
  .dampf i:nth-child(2) { left: -3cqh; animation-delay: -2.1s; }
  .dampf i:nth-child(3) { left: -1.1cqh; animation-delay: -4s; }
  @keyframes dampft {
    0% { opacity: 0; transform: translate3d(0, 1cqh, 0) scale(.5, .4); }
    25% { opacity: .8; }
    60% { opacity: .45; }
    100% { opacity: 0; transform: translate3d(1.3cqh, -8cqh, 0) scale(1.3, 1.2); }
  }
  .blick__leben.is-ruht i { animation-play-state: paused; }
}

/* ======== WAND — below the window you are inside: the page is the wall ======== */
/* Limewash, not white: a fine tooth and a few slow clouds of the trowel, drawn
   by one small SVG filter (no file, no request). The tone itself is --wand
   and follows the season (FARBEN). Text never stands on the wall: everything
   that is said hangs in a frame. */
body {
  background-color: var(--wand);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='420' height='420'%3E%3Cfilter id='a' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' seed='7' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .32 0 0 0 0 .24 0 0 0 0 .13 0 0 0 .1 0'/%3E%3C/filter%3E%3Cfilter id='b' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.004 .009' numOctaves='3' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .36 0 0 0 0 .27 0 0 0 0 .15 0 0 0 .3 -.1'/%3E%3C/filter%3E%3Crect width='420' height='420' filter='url(%23b)'/%3E%3Crect width='420' height='420' filter='url(%23a)'/%3E%3C/svg%3E");
  transition: background-color 1.4s var(--ruhig);
}
.sprungleiste, .wohnung, .zimmer, .preise, .hausnotizen, .anfrage {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: clamp(2.25rem, 7vw, 5rem);
  padding: clamp(2.5rem, 8vw, 6.5rem) max(var(--wandrand), calc((100% - 84rem) / 2));
}
/* Nothing below the window is laid out until it is about to be scrolled into
   view. Measured on a throttled phone: a full layout of the page drops from
   about 85ms to under 40ms, and the first screen needs six of them. The
   intrinsic size is only the height a section is assumed to have before it
   has been seen once; "auto" remembers the real one afterwards. It is
   deliberately on the tall side: assumed too short, the room pictures count
   as "nearly in view" and the browser fetches them while the window view is
   still loading. */
.wohnung, .zimmer, .preise, .hausnotizen, .anfrage, .fuss {
  content-visibility: auto;
  contain-intrinsic-size: auto 115rem;
}
/* One guess for all seven made the scrollbar's thumb jump whenever a section
   was seen for the first time (the rooms are twice as tall as the guess
   was). Each gets the height measured at 390, 768 and 1440px, rounded. The
   first two are assumed taller than before, so every section still starts
   further down than it did and the note above holds. */
.zimmer { contain-intrinsic-size: auto 240rem; }
.preise { contain-intrinsic-size: auto 118rem; }
.hausnotizen { contain-intrinsic-size: auto 55rem; }
.anfrage { contain-intrinsic-size: auto 80rem; }
.fuss { contain-intrinsic-size: auto 28rem; }
@media (min-width: 900px) {   /* side by side, the same sections are shorter */
  .zimmer { contain-intrinsic-size: auto 225rem; }
  .wohnung { contain-intrinsic-size: auto 90rem; }
  .preise { contain-intrinsic-size: auto 105rem; }
  .anfrage { contain-intrinsic-size: auto 70rem; }
}

/* ======== RAHMEN — the one frame system: larch, bevel, mat, shadow ======== */
/* A frame is  .rahmen > .rahmen__innen > content.  Three layers do the work:
     ::after   the wood. img/frame-larch-*.webp is a square frame cut from the
               hero window's own jambs, with the mitres and the light (from the
               upper left) already in it. border-image slices it into four
               corners and four rails; the rails stretch ALONG the grain, so a
               frame of any size keeps its joints and its profile.
     ::before  the frame's shadow on the wall, a blurred slab behind it,
               pushed down and to the right of the light.
     __innen   what is behind the glass: paper for text, a photograph, or a
               mat (--karton) around either.
   Variants only change numbers:
     --schmal / --breit   the profile width (--profil)
     --dunkel             the darker cut of the same larch
     --karton             a passe-partout between wood and content
     --links / --rechts   hangs a little crooked (--neig)
     --schnur             hangs from a nail on a cord (needs .rahmen__schnur) */
.rahmen {
  --profil: .6rem;
  --neig: 0deg;
  position: relative;
  isolation: isolate;
  display: block;
  padding: var(--profil);
  rotate: var(--neig);
  /* the hairline of dark where wood meets wall */
  box-shadow: 0 1px 2px rgb(var(--schatten) / .55);
}
.rahmen::before {
  content: "";
  position: absolute;
  inset: .5rem .1rem -.75rem .65rem;
  z-index: -1;
  background: rgb(var(--schatten) / .5);
  filter: blur(.7rem);
}
.rahmen::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  border: var(--profil) solid transparent;
  border-image: url("img/frame-larch-light.webp?v=3e64328b") 60 stretch;
  /* the wood stands proud of the glass: its own small shadow falls inward */
  box-shadow: inset .1rem .14rem .28rem rgba(28, 16, 8, .5), inset 0 0 0 1px rgba(28, 16, 8, .28);
  filter: var(--holzlicht);
  transition: filter 1.4s var(--ruhig);
  pointer-events: none;
}
.rahmen--dunkel::after { border-image-source: url("img/frame-larch-dark.webp?v=5798e341"); }
.rahmen--schmal { --profil: .42rem; }
.rahmen--breit { --profil: .8rem; }
.rahmen--links { --neig: -.7deg; }
.rahmen--rechts { --neig: .6deg; }

.rahmen__innen {
  display: block;
  position: relative;
  height: 100%;
  background-color: var(--papier);
  /* paper is never one flat tone: the light comes from the upper left here too */
  background-image: linear-gradient(140deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, 0) 45%);
  transition: background-color 1.4s var(--ruhig), border-color 1.4s var(--ruhig);
}
/* The mat is the border of the inner sheet; the two inset lines are the 45°
   cut every passe-partout has, dark where it faces away from the light. */
.rahmen--karton > .rahmen__innen {
  border: var(--karton-breite, .5rem) solid var(--karton);
  box-shadow: inset 1px 1px 2px rgba(60, 40, 10, .34), inset -1px -1px 0 rgba(255, 255, 255, .9);
}
.rahmen--text > .rahmen__innen { padding: 1.5rem 1.2rem 1.6rem; }
.rahmen--text > .rahmen__innen > * + * { margin-top: .85rem; }

/* The cord and its nail: two lines and a dot, above the frame, on a few. */
.rahmen--schnur { margin-top: 2.6rem; }
.rahmen__schnur {
  position: absolute;
  left: 50%;
  bottom: calc(100% - 2px);
  z-index: -1;
  width: min(44%, 12rem);
  height: 2.5rem;
  translate: -50% 0;
  background:
    radial-gradient(circle at 50% 5px, #F1E9DA 0 1px, #4E453B 1.4px 3.4px, rgba(30, 20, 10, .35) 3.8px, transparent 5.5px),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 50' preserveAspectRatio='none'%3E%3Cpath d='M1 50 100 6 199 50' fill='none' stroke='%236E5E46' stroke-width='1.5' vector-effect='non-scaling-stroke'/%3E%3C/svg%3E") center / 100% 100% no-repeat;
}

/* A photograph behind glass. The picture is a little larger than its opening
   (114% tall) so it can travel behind the frame while the page scrolls
   (BEWEGUNG): that is what makes a framed picture read as a window. */
.rahmen__bild {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--karton);
}
.rahmen__bild img {
  position: absolute;
  left: 0;
  top: -7%;
  width: 100%;
  max-width: none;
  height: 114%;
  object-fit: cover;
  /* ONE grade for every photograph, so seven pictures read as one film:
     soft contrast, a touch of warmth; cooler in the snow months (FARBEN). */
  filter: var(--film);
  transition: opacity 1.4s var(--ruhig), filter 1.4s var(--ruhig);
}
/* The rest of the grade lies over the picture: lifted blacks, a warm (or
   cold) highlight from the light's corner, a faint vignette, and the shadow
   the wood throws onto the glass. */
.rahmen__bild::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  background:
    linear-gradient(150deg, var(--film-glanz), transparent 46%),
    radial-gradient(120% 95% at 50% 46%, transparent 56%, var(--film-rand) 128%),
    rgba(255, 244, 228, .045);
  box-shadow: inset .12rem .16rem .4rem rgba(20, 12, 4, .42);
  pointer-events: none;
}
/* SEASON: winter lies underneath, summer on top and fades. Opacity only, so
   the change of season moves nothing. A missing file is hidden by app.js. */
:root[data-jahreszeit="winter"] .jz--sommer { opacity: 0; }
/* A frame whose new season's file has not arrived keeps the picture it is
   showing (app.js, saisonBilder): the season on <html> has already turned,
   this frame follows when its photograph is there. Never an empty frame. */
:root .rahmen__bild[data-haelt="sommer"] > .jz--sommer { opacity: 1; }
:root .rahmen__bild[data-haelt="winter"] > .jz--sommer { opacity: 0; }
/* The other season's picture waits without a file (app.js, saisonBilder). An
   <img> without one would write its alt text into the frame for as long as
   the picture on top of it is still loading. */
.jz:not([src]):not([srcset]) { visibility: hidden; }
.rahmen__bild img[hidden] { display: none; }
.rahmen--foto:has(.rahmen__bild):not(:has(.rahmen__bild img:not([hidden]))) { display: none; }

/* Type inside a frame: the hero's scale, and nothing smaller than 17px that
   is meant to be read. */
.rahmen h2 { font-size: clamp(2.25rem, 1.45rem + 3.5vw, 4.4rem); line-height: 1.02; letter-spacing: -.012em; }
.rahmen h3 { font-size: clamp(1.9rem, 1.55rem + 1.5vw, 2.6rem); line-height: 1.06; }
.rahmen .marker { margin-bottom: 0; }
.szene__satz { font: 500 clamp(1.4rem, 1.2rem + .9vw, 1.85rem)/1.24 var(--serif); text-wrap: pretty; }

/* A scene: one large picture and the frame with its words, hung so that the
   smaller overlaps the larger, the way a wall fills up over the years. */
.szene { display: grid; grid-template-columns: minmax(0, 1fr); }
.szene > .rahmen--text { z-index: 1; margin: -1.1rem .7rem 0; }
.szene--rechts > .rahmen--text { margin-right: 1.6rem; margin-left: .2rem; }
/* [data-ihr]: the lines app.js rewrites once nights are chosen (zeichneIhres). */
.szene__ihr, [data-ihr="zeit"] { color: var(--himmel-tief); font-weight: 600; }
.szene__ihr.ist-ihres { color: var(--tinte); font: italic 500 clamp(1.5rem, 1.3rem + .9vw, 1.9rem)/1.2 var(--serif); }
/* A link inside a sentence still has to be hit by a thumb: 44px of height. */
[data-ihr] a, .preise__ihr a:not(.knopf) { display: inline-block; padding: .7rem 0; color: inherit; }

/* ======== SPRUNGLEISTE — three small framed labels where the lintel has no menu ======== */
.sprungleiste {
  display: flex;
  flex-wrap: wrap;   /* narrow screens and enlarged text: the labels wrap instead of pushing the page wider */
  justify-content: center;
  gap: clamp(.6rem, 3vw, 1.5rem);
  padding-top: 1.6rem;
  padding-bottom: 0;
}
.sprungleiste .rahmen, .zimmer__weiter { color: var(--tinte); font-size: 1rem; font-weight: 600; text-decoration: none; }
.sprungleiste .rahmen__innen, .zimmer__weiter .rahmen__innen {
  display: grid;
  place-items: center;
  min-width: 5.4rem;
  min-height: 2.75rem;   /* 44px inside the wood: the row is for thumbs */
  padding: 0 .9rem;
}
.sprungleiste .rahmen:hover .rahmen__innen, .zimmer__weiter:hover .rahmen__innen { text-decoration: underline; }
@media (min-width: 1100px) { .sprungleiste { display: none; } }

/* ======== WOHNUNG — scene 1, arriving: the house, the letter, five figures ======== */
.wohnung__brief { margin: 0 .3rem; }
.wohnung .wohnung__gruss { margin-top: 1.3rem; font: italic 500 1.7rem/1.2 var(--serif); }
/* The five figures hang as a small dark-framed card, a little crooked. */
.wohnung__zahlen { margin: -.8rem .9rem 0; }
/* On a phone two figures share a line: five rows of them would be a screen of nothing else. */
.wohnung__zahlen dl { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.2rem; padding: .5rem 1.1rem .7rem; }
.wohnung__zahlen div { padding: .65rem 0 .55rem; border-bottom: 1px solid var(--linie); }
.wohnung__zahlen div:last-child { grid-column: 1 / -1; border-bottom: 0; }
.wohnung__zahlen dt { color: var(--tinte-weich); }
.wohnung__zahlen dd { margin-top: .15rem; font: 500 1.6rem/1.05 var(--serif); }

/* ======== PREISE — the framed price card, and the month's view beside it ======== */
.preise__blick { justify-self: end; width: 68%; margin: -1rem .4rem -3.2rem 0; z-index: 1; }
.preise__blick .rahmen__bild { aspect-ratio: 5 / 3; }
.preise__karte > .rahmen__innen { padding-top: 2.6rem; }
/* The first lines of the card are the guest's own: the stay and its total, or
   the season of the month in view. The height is held so the list below never
   moves when one turns into the other. */
.preise__ihr { min-height: 11.5rem; }
.preise__ihr > * + * { margin-top: .6rem; }
.preise__ihr-gross { font: 500 clamp(2rem, 1.6rem + 2vw, 3.2rem)/1.04 var(--serif); letter-spacing: -.01em; }
.preise__ihr-summe { display: flex; flex-wrap: wrap; align-items: baseline; gap: .2rem .7rem; font-weight: 600; }
.preise__ihr-summe b { font: 500 2.2rem/1 var(--serif); }
.preise__ihr-summe small { color: var(--tinte-weich); font-size: 1rem; font-weight: 400; }
/* Honest scarcity: a count from data/belegung.json, said once, in ink. */
.preise__frei { padding-left: .7rem; border-left: 3px solid var(--laerche-tief); font-weight: 600; }

/* The band: every night from the first season to the last, in one line.
   A segment is as wide as its season is long. */
.preise__segmente { display: flex; height: clamp(2.6rem, 6vw, 3.6rem); border-radius: 2px; overflow: hidden; }
.preise__segmente span {
  display: flex;
  align-items: center;
  overflow: hidden;
  padding-left: .6rem;
  font-size: .9rem;
  font-weight: 600;
  white-space: nowrap;
  color: transparent;   /* the price shows from tablet up, where it fits */
  background: var(--stufe);
  opacity: .5;
  transition: opacity .6s var(--ruhig);
}
.preise__segmente .is-jetzt { opacity: 1; }
.preise__monate { display: flex; margin-top: .4rem; color: var(--tinte-weich); font-size: .8rem; }
.preise__monate span { overflow: hidden; border-left: 1px solid var(--linie); padding-left: .25rem; }
.preise__monate .lang { display: none; }
/* Four price steps, cheapest to dearest: wood, wood, sky, ink. The same
   colour marks the season's row in the list. */
.stufe-0 { --stufe: #EFE3CC; --stufe-text: var(--tinte); }
.stufe-1 { --stufe: #C9A873; --stufe-text: var(--tinte); }
.stufe-2 { --stufe: var(--himmel); --stufe-text: var(--tinte); }
.stufe-3 { --stufe: var(--tinte); --stufe-text: var(--weiss); }

.preise__liste { border-top: 1px solid rgba(16, 27, 43, .3); }
.preise__liste li {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: .15rem 1.2rem;
  padding: 1rem .2rem 1rem 0;
  border-bottom: 1px solid rgba(16, 27, 43, .3);
  transition: background-color .6s var(--ruhig), padding .6s var(--ruhig);
}
/* THE SEASON IN VIEW (or the season of the chosen stay): its row is the one
   the eye lands on. A wash of the mat tone and a larch bar; the other rows
   stay fully readable. */
.preise__liste li.is-jetzt { padding-left: 1rem; background: var(--karton); box-shadow: inset 4px 0 0 var(--laerche-tief); }
.preise__liste li.is-jetzt .preise__preis { font-weight: 600; }
.preise__saison { display: flex; align-items: center; gap: .7rem; font-size: 1.7rem; }
.preise__saison::before {
  content: "";
  flex: none;
  width: .9rem;
  height: .9rem;
  border-radius: 50%;
  background: var(--stufe);
  border: 1px solid rgba(16, 27, 43, .35);
}
.preise__zeit { grid-column: 1; color: var(--tinte-weich); }
.preise__preis { grid-column: 2; grid-row: 1 / span 2; font: 500 2.4rem/1 var(--serif); text-align: right; }
.preise__preis small { display: block; margin-top: .2rem; font: 400 .85rem/1.2 var(--sans); color: var(--tinte-weich); }
.preise__zeigen {
  grid-column: 1 / -1;
  justify-self: start;
  min-height: 2.75rem;
  padding: .3rem 0;
  border: 0;
  background: none;
  color: var(--himmel-tief);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: .18em;
  cursor: pointer;
}
.preise__zeigen:hover { color: var(--tinte); }
/* The seasons whose price repeats hide behind one fold. */
.preise__liste .preise__mehr { display: block; padding: 0; border-bottom: 0; }
.preise__mehr summary { display: flex; align-items: center; min-height: 2.75rem; color: var(--himmel-tief); font-weight: 600; text-decoration: underline; text-underline-offset: .18em; cursor: pointer; }
.preise__mehr summary:hover { color: var(--tinte); }
.preise__mehr ol { border-top: 1px solid rgba(16, 27, 43, .3); }
.preise__mehr ol li:last-child { border-bottom: 0; }
.preise__fuss { font-weight: 500; }

/* ======== ANFRAGE — one framed sheet, like a page of the guest book ======== */
.anfrage__blatt > .rahmen__innen { display: grid; gap: 2rem; padding: 1.7rem 1.1rem 1.8rem; }
.anfrage__blatt > .rahmen__innen > * + * { margin-top: 0; }
.anfrage__kopf > * + * { margin-top: 1rem; }
/* The same sum as in the window, at the head of the sheet the guest is about to send. */
.stand--anfrage { margin-top: 1.5rem; padding-top: 1rem; border-top: 3px solid var(--laerche-tief); font-size: 1.0625rem; }
.stand--anfrage .stand__hinweis { margin-bottom: .9rem; color: var(--tinte); }
.anfrage__form { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem 1rem; align-content: start; }
/* display: grid above would beat the hidden attribute: after a sent request the
   form stayed on screen and pushed the thank-you below it (live audit 2026-10-07). */
.anfrage__form[hidden] { display: none; }
.feld { grid-column: 1 / -1; }
.feld--halb { grid-column: auto; }
/* Phone | guests stand side by side. A label that wraps (the French one at
   390px) pushed its own field down alone, so the pair is seated on the foot
   of the row. Not while the phone field shows its error underneath: then the
   select would sink to the foot of the error, and the pair stays on top. */
.anfrage__form:not(:has(.feld--halb .feld__fehler:not([hidden]))) .feld--halb { align-self: end; }
.feld label { display: block; margin-bottom: .35rem; font-weight: 600; }
.feld__frei { margin-left: .3rem; color: var(--tinte-weich); font-weight: 400; }
.feld input, .feld select, .feld textarea {
  display: block;
  width: 100%;
  min-height: 3.2rem;   /* a select and an input side by side end up the same height */
  padding: .75rem .8rem;
  border: 1px solid #66717F;
  border-radius: 2px;
  background: var(--weiss);
}
.feld textarea { resize: vertical; min-height: 6.5rem; }
.feld input:focus-visible, .feld select:focus-visible, .feld textarea:focus-visible { outline-color: var(--himmel-tief); outline-offset: 1px; }
.feld [aria-invalid="true"] { border-color: var(--tinte); border-width: 2px; }
/* Errors are sentences under the field, in ink, with the same larch bar as the
   calendar's refusals. */
.feld__fehler, .anfrage__meldung:not(:empty) {
  margin-top: .4rem;
  padding-left: .7rem;
  border-left: 3px solid var(--laerche-tief);
  font-size: 1rem;
  font-weight: 600;
}
.anfrage__form .knopf { grid-column: 1 / -1; justify-self: start; min-height: 3.2rem; padding-inline: 2rem; }
.anfrage__form .knopf[disabled] { opacity: .6; cursor: progress; }
.anfrage__meldung, .anfrage__klein { grid-column: 1 / -1; }
.anfrage__klein { color: var(--tinte-weich); font-size: 1rem; }
/* The padding makes the link 44px tall for a thumb; the same margin taken
   back keeps it from spreading the lines of the small print around it. */
.anfrage__klein a { display: inline-block; padding: .65rem 0; margin-block: -.65rem; }
/* The success state: the reference number is the thing to keep. */
.anfrage__danke > * + * { margin-top: .9rem; }
.anfrage__ref {
  display: inline-block;
  padding: .5rem 1rem;
  border: 1px solid var(--tinte);
  font: 500 2rem/1 var(--serif);
  letter-spacing: .04em;
}
.anfrage__danke .stand { max-width: 28rem; font-size: 1.0625rem; }

/* ======== ZIMMER — scenes 2 to 5, then kitchen and bath as a pair ======== */
.zimmer { padding-top: 0; }
/* Two upright pictures side by side and one frame of words under both. */
.zimmer__paar { display: grid; grid-template-columns: 1fr 1fr; gap: 0 clamp(.7rem, 3vw, 2rem); align-items: start; }
.zimmer__paar .rahmen__bild { aspect-ratio: 4 / 5; }
.zimmer__paar .rahmen--rechts { margin-top: 1.4rem; }
.zimmer__paartext { grid-column: 1 / -1; z-index: 1; margin: -.9rem .7rem 0; }
.zimmer__paartext .rahmen__innen > div > p { margin-top: .4rem; }
/* The way back to the request, after the last room (same look as the SPRUNGLEISTE labels above). */
.zimmer__weiter { justify-self: center; }

/* ======== HAUSNOTIZEN — six framed notes that open ======== */
.hausnotizen { padding-top: 0; }
.hausnotizen__liste { display: grid; gap: 1.5rem 1.6rem; align-items: start; }
/* Not one of them hangs quite like its neighbour. */
.hausnotizen__liste > :nth-child(3n + 1) { --neig: -.5deg; }
.hausnotizen__liste > :nth-child(3n + 2) { --neig: .45deg; margin-inline: .5rem; }
.hausnotizen .rahmen--text > details { padding: 0; }
.hausnotizen summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1.2rem;
  min-height: 2.75rem;
  padding: 1.05rem 1.2rem;
  font: 500 clamp(1.45rem, 1.3rem + .7vw, 1.75rem)/1.15 var(--serif);
  list-style: none;
  cursor: pointer;
}
.hausnotizen summary::-webkit-details-marker { display: none; }
/* A plus that turns into a minus: the upright stroke lies down. */
.hausnotizen summary::after {
  content: "";
  flex: none;
  width: 1rem;
  height: 1rem;
  background:
    linear-gradient(var(--tinte), var(--tinte)) center / 100% 2px no-repeat,
    linear-gradient(var(--tinte), var(--tinte)) center / 2px 100% no-repeat;
  transition: transform .3s var(--ruhig);
}
.hausnotizen details[open] summary::after { transform: rotate(90deg); background-size: 100% 2px, 0 0; }
.hausnotizen details p { margin: 0; padding: 0 1.2rem 1.3rem; }

/* ======== FUSS — where the wall ends: skirting board, then the floor ======== */
/* The board is the top rail of the darker frame, stretched across the room. */
.fuss {
  margin-top: clamp(2rem, 6vw, 4rem);
  padding: clamp(2.5rem, 7vw, 4.5rem) var(--rand) 2rem;
  border-top: 1.5rem solid var(--laerche-tief);
  border-image: url("img/frame-larch-dark.webp?v=5798e341") 60 / 1.5rem 0 0 0 stretch;
  background: var(--laerche);
  box-shadow: 0 -.5rem .9rem -.3rem rgb(var(--schatten) / .45);
  font-size: 1.0625rem;
}
.fuss p { max-width: 40rem; margin-top: .7rem; }
.fuss a { display: inline-block; padding: .6rem 0; margin-block: -.6rem; color: var(--tinte); font-weight: 600; }   /* as .anfrage__klein a */
.fuss .fuss__marke { margin: 0 0 1.2rem -.03em; font: 300 clamp(3.5rem, 9vw, 6rem)/.9 var(--serif); letter-spacing: -.02em; }
.fuss .fuss__klein { margin-top: 1.6rem; font-size: 1rem; }
.fuss .fuss__klein a { padding: .7rem 0; margin-block: -.7rem; }
/* Where the credit line does not fit in one row it breaks after the studio's
   name, and the dot that would dangle there becomes the break itself. */
@media (max-width: 899.98px) { .fuss__punkt { display: block; height: 0; overflow: hidden; } }
/* The studio seal sits directly under the footer; give it the same wood. */
.wdm-seal { background: var(--laerche); }

/* ======== TIEFE — a frame that can be entered: the plate, the invitation, the opened picture ======== */
/* A .rahmen--tief can be stepped into (app.js TIEFE opens it, tiefe.js draws
   it). Three things say so before anything is pressed: a small plate screwed
   to the frame like the label under a painting, one breath of the picture
   when its frame first comes into view, and under a mouse the picture leans
   towards the pointer. Nothing here is loaded for it: no file, no font. */
/* The pointer only promises a way in where the plate is showing: app.js
   un-hides it, so without JavaScript (or with the feature switched off,
   EDITING.md) the picture is a picture. */
.rahmen--tief:has(> .rahmen__schild:not([hidden])) .rahmen__bild { cursor: zoom-in; }
.rahmen__schild {
  position: absolute;
  left: calc(var(--profil) + .55rem);
  /* On a phone the frame with the words hangs over the picture's lower edge
     (1.1rem); the plate sits just above that, in the corner of the glass. */
  bottom: calc(var(--profil) + 1.15rem);
  z-index: 3;   /* above the wood, which is 2 */
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  min-height: 2.75rem;   /* 44px: it is a button for a thumb */
  padding: 0 1.05rem;
  border: 0;
  border-radius: 2px;
  /* a sliver of planed larch with a screw at either end */
  background:
    radial-gradient(circle at .42rem 50%, rgba(70, 48, 16, .7) 0 1.1px, transparent 1.9px),
    radial-gradient(circle at calc(100% - .42rem) 50%, rgba(70, 48, 16, .7) 0 1.1px, transparent 1.9px),
    linear-gradient(172deg, #FCF5E6, var(--laerche) 92%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), 0 0 0 1px rgba(90, 62, 22, .5), .12rem .22rem .5rem rgb(var(--schatten) / .55);
  color: var(--tinte);
  font-size: .95rem;
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
}
/* display above would otherwise undo `hidden` (the state without JavaScript) */
.rahmen__schild[hidden] { display: none; }
.rahmen__schild svg { fill: none; stroke: var(--himmel-tief); stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.rahmen__schild:hover, .rahmen__schild:focus-visible { background: var(--himmel-tief); color: var(--weiss); }
.rahmen__schild:hover svg, .rahmen__schild:focus-visible svg { stroke: currentColor; }
/* The plate keeps to the side the words do not hang on. */
.szene--rechts .rahmen__schild { left: auto; right: calc(var(--profil) + .55rem); }
.zimmer__paar .rahmen__schild { left: 50%; translate: -50% 0; }
/* The sentence in the first scene that says it in words: the colour of everything that can be pressed. */
.szene__tief { color: var(--himmel-tief); font-weight: 600; }
/* Between 720 and 900px the words overlap the picture by 3rem. */
@media (min-width: 720px) and (max-width: 899.98px) {
  .szene .rahmen__schild { bottom: 3.5rem; }
}
/* On a wide wall the words hang beside the picture, so the plate can sit
   where such a label belongs: on the lower rail, a little over its edge. */
@media (min-width: 900px) {
  .rahmen__schild { bottom: calc(var(--profil) * -.3); min-height: 3rem; padding: 0 1.4rem; font-size: 1.05rem; }
}
/* While a picture is entered its frame stays on the wall, empty. */
.is-betreten .rahmen__bild img { visibility: hidden; }

@media (prefers-reduced-motion: no-preference) {
  /* transform is free on these pictures: the scroll movement and the slow
     push-in (BEWEGUNG) use translate and scale, which add to it. */
  .rahmen--tief .rahmen__bild img { transition: opacity 1.4s var(--ruhig), filter 1.4s var(--ruhig), transform .7s var(--ruhig); }
  /* THE BREATH, once per frame (app.js sets .is-atmet for a good second):
     the picture comes a step closer and lets go, the plate calls. */
  .rahmen--tief.is-atmet .rahmen__bild img { transform: scale(1.1); }
  .rahmen--tief.is-atmet .rahmen__schild { animation: schild-ruft 1.2s var(--ruhig); }
  @keyframes schild-ruft {
    from { outline: 2px solid rgb(29 94 150 / .9); outline-offset: 0; }
    40% { scale: 1.08; }
    to { outline: 2px solid rgb(29 94 150 / 0); outline-offset: .9rem; }
  }
  /* THE LEAN: --zx / --zy are where the mouse is over the picture, -1 to 1
     (app.js). The 6% of scale is the room the tilt needs at the edges. */
  @media (hover: hover) {
    .rahmen--tief .rahmen__bild:hover img {
      transform: perspective(50rem) rotateY(calc(var(--zx, 0) * 2.2deg)) rotateX(calc(var(--zy, 0) * -1.6deg))
        translate3d(calc(var(--zx, 0) * 1%), calc(var(--zy, 0) * 1%), 0) scale(1.06);
      transition-duration: 1.4s, 1.4s, .35s;
    }
  }
}

/* THE OPENED PICTURE (built by tiefe.js on the first opening). The window is
   the cut-out that grows from the frame to the screen, the stage inside it
   holds the photograph twice: as <img> (what flies, and the fallback) and as
   the canvas that draws it with depth. Both get the film grade of the frames. */
.tiefe { position: fixed; inset: 0; z-index: 50; color: var(--tinte); }
.tiefe::before { content: ""; position: absolute; inset: 0; background: var(--tinte); opacity: 0; }
.tiefe.is-offen::before { opacity: 1; }
.tiefe__fenster { position: absolute; inset: 0; overflow: hidden; transform-origin: 0 0; touch-action: none; cursor: move; }
.tiefe__buehne { position: absolute; inset: 0; filter: var(--film); }
.tiefe.is-wechselt .tiefe__buehne { opacity: 0; }
.tiefe__foto, .tiefe__glas { position: absolute; inset: 0; width: 100%; height: 100%; max-width: none; }
/* 1.05 is the canvas's own zoom (tiefe.js, ZOOM): the two must not jump when one replaces the other */
.tiefe__foto { object-fit: cover; scale: 1.05; }
.tiefe__glas { opacity: 0; }
.tiefe.hat-tiefe .tiefe__glas { opacity: 1; }
.tiefe__fenster::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(150deg, var(--film-glanz), transparent 46%),
    radial-gradient(120% 95% at 50% 46%, transparent 56%, var(--film-rand) 128%);
  pointer-events: none;
}
/* The label of the room, as a card of the same paper as the frames' words. */
.tiefe__schild {
  position: absolute;
  left: max(1rem, env(safe-area-inset-left));
  bottom: max(1rem, env(safe-area-inset-bottom));
  max-width: min(31rem, calc(100% - 2rem));
  padding: 1rem 1.3rem 1.15rem;
  background: var(--papier);
  box-shadow: 0 .5rem 1.6rem rgba(8, 14, 24, .4);
  pointer-events: none;   /* a finger that starts on the card still moves the picture */
}
.tiefe__schild h2 { font-size: clamp(1.9rem, 1.55rem + 1.5vw, 2.6rem); line-height: 1.06; }
.tiefe__schild p { margin-top: .4rem; font: 500 clamp(1.2rem, 1.1rem + .5vw, 1.45rem)/1.25 var(--serif); text-wrap: pretty; }
.tiefe__knopf {
  position: absolute;
  display: grid;
  place-items: center;
  width: 3rem;    /* 48px */
  height: 3rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--papier);
  box-shadow: 0 .2rem .8rem rgba(8, 14, 24, .4);
  cursor: pointer;
}
.tiefe__knopf:hover { background: var(--tinte); color: var(--weiss); }
/* the page's ink focus ring would vanish on a dark photograph */
.tiefe__knopf:focus-visible { outline-color: var(--weiss); }
.tiefe__zu { top: max(1rem, env(safe-area-inset-top)); right: max(1rem, env(safe-area-inset-right)); }
.tiefe__zurueck, .tiefe__vor { top: 50%; translate: 0 -50%; }
.tiefe__zurueck { left: max(.75rem, env(safe-area-inset-left)); }
.tiefe__vor { right: max(.75rem, env(safe-area-inset-right)); }
.tiefe__vor svg { rotate: 180deg; }
.tiefe__schild, .tiefe__knopf { opacity: 0; }
.tiefe.is-offen .tiefe__schild, .tiefe.is-offen .tiefe__knopf { opacity: 1; }
@media (prefers-reduced-motion: no-preference) {
  .tiefe::before { transition: opacity .5s var(--ruhig); }
  .tiefe__buehne { transition: opacity .2s var(--ruhig); }
  .tiefe__glas { transition: opacity .35s var(--ruhig); }
  /* label and buttons arrive after the picture has */
  .tiefe__schild, .tiefe__knopf { transition: opacity .25s var(--ruhig), background-color .2s; }
  .tiefe.is-offen .tiefe__schild, .tiefe.is-offen .tiefe__knopf { transition-delay: .4s, 0s; }
  /* NO DEPTH (no WebGL, a lost context, no depth map; tiefe.js sets
     .ist-flach): the photograph alone, coming slowly closer. */
  .tiefe.ist-flach .tiefe__foto { animation: tiefe-naeher 18s ease-in-out infinite alternate; }
  @keyframes tiefe-naeher { to { scale: 1.16; } }
}

/* ======== ab 720px — two notes side by side, the sheet gets its margins ======== */
@media (min-width: 720px) {
  .rahmen { --profil: .95rem; }
  .rahmen--schmal { --profil: .6rem; }
  .rahmen--breit { --profil: 1.3rem; }
  .rahmen--karton > .rahmen__innen { --karton-breite: .8rem; }
  .rahmen--text > .rahmen__innen { padding: 2rem 2rem 2.2rem; }
  .rahmen__bild { aspect-ratio: 16 / 9; }
  .szene > .rahmen--text { justify-self: end; width: min(100%, 34rem); margin: -3rem 2rem 0 0; }
  .szene--rechts > .rahmen--text { justify-self: start; margin: -3rem 0 0 2rem; }
  .zimmer__paartext { justify-self: center; width: min(100%, 36rem); }
  .preise__blick { width: 44%; }
  .hausnotizen__liste { grid-template-columns: 1fr 1fr; }
  .hausnotizen__liste > :nth-child(3n + 2) { margin-inline: 0; }
  .anfrage__blatt > .rahmen__innen { padding: 2.6rem 2.4rem 2.8rem; }
  .preise__segmente span { color: var(--stufe-text); }
  .preise__monate .kurz { display: none; }
  .preise__monate .lang { display: inline; }
}

/* ======== ab 900px — the wall is wide: pictures at 62% of it, words beside them ======== */
@media (min-width: 900px) {
  .rahmen { --profil: 1.35rem; }
  .rahmen--schmal { --profil: .85rem; }
  .rahmen--breit { --profil: 1.9rem; }
  .rahmen--karton > .rahmen__innen { --karton-breite: 1.1rem; }
  .rahmen--text > .rahmen__innen { padding: 2.4rem 2.5rem 2.6rem; font-size: 1.125rem; }
  .rahmen--schnur { margin-top: 3.4rem; }
  .rahmen__schnur { height: 3.4rem; }

  /* Twelve columns to hang on. A scene's picture takes eight of them, its
     words five, and they share one: that is the overlap. */
  .wohnung, .zimmer, .preise, .hausnotizen, .anfrage {
    grid-template-columns: repeat(12, minmax(0, 1fr));
    column-gap: clamp(1rem, 2.2vw, 2.25rem);
  }
  .wohnung > *, .zimmer > *, .preise > *, .hausnotizen > *, .anfrage > * { grid-column: 1 / -1; }
  .szene { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(1rem, 2.2vw, 2.25rem); align-items: end; }
  .szene > .rahmen--foto { grid-column: 1 / span 8; grid-row: 1; }
  .szene > .rahmen--text { grid-column: 8 / -1; grid-row: 1; width: auto; margin: 0 0 -3.5rem; }
  .szene--rechts > .rahmen--foto { grid-column: 5 / -1; }
  .szene--rechts > .rahmen--text { grid-column: 1 / span 5; width: auto; margin: 0 0 -3.5rem; }
  /* in a five-column frame the section headline steps down a size, or it breaks after every second word */
  .szene h2 { font-size: clamp(2.6rem, 1.3rem + 2.5vw, 3.6rem); }

  .wohnung__brief { grid-column: 2 / span 7; margin: 2rem 0 0; }
  .wohnung__zahlen { grid-column: 9 / -1; align-self: start; margin: 4.5rem 0 0; }
  .wohnung__zahlen dl { display: block; }
  .wohnung__zahlen div { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding: .7rem 0; }
  .wohnung__zahlen dd { margin-top: 0; text-align: right; }

  /* room for the overlap of each scene's words (3.5rem) and a breath, no more: a wall hung too thinly reads as empty */
  .zimmer { row-gap: clamp(5.5rem, 7vw, 7rem); }
  .zimmer__kopf { grid-column: 2 / span 9; }
  .zimmer__paar { grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: clamp(1rem, 2.2vw, 2.25rem); align-items: end; }
  .zimmer__paar > .rahmen--foto:nth-child(1) { grid-column: 2 / span 3; }
  .zimmer__paar > .rahmen--foto:nth-child(2) { grid-column: 5 / span 3; margin-bottom: 3rem; }
  .zimmer__paartext { grid-column: 8 / span 5; width: auto; margin: 0 0 1rem; }

  .preise__kopf { grid-column: 1 / span 8; grid-row: 1; }
  .preise__blick { grid-column: 9 / -1; grid-row: 1; align-self: end; justify-self: stretch; width: auto; margin: 0 1rem -4rem; }
  .preise__blick .rahmen__bild { aspect-ratio: 4 / 5; }
  .preise__karte { grid-column: 1 / span 11; }
  .preise__karte > .rahmen__innen { padding-top: 3rem; }
  .preise__ihr { min-height: 9.5rem; max-width: 44rem; }
  .preise__liste li { grid-template-columns: 1.1fr 1.4fr auto 12rem; padding-block: .7rem; }
  .preise__zeit, .preise__preis, .preise__zeigen { grid-column: auto; grid-row: auto; }
  .preise__zeigen { justify-self: end; }

  .hausnotizen__kopf { grid-column: 1 / span 8; }
  .hausnotizen__liste { grid-template-columns: 1fr 1fr 1fr; gap: 2.4rem 2.2rem; }
  .hausnotizen__liste > :nth-child(3n + 2) { margin-top: 1.6rem; }

  .anfrage__blatt { grid-column: 2 / span 10; }
  .anfrage__blatt > .rahmen__innen { grid-template-columns: 1fr 1fr; gap: 3.5rem; padding: 3.4rem 3.4rem 3.6rem; }
}

/* ======== BEWEGUNG — one system: CSS, driven by the scrollbar ======== */
/* The window itself only cross-fades (see BLICK). Everything that moves below
   it is tied to the scroll position (animation-timeline), not to a clock: a
   fast scroller cannot outrun it and scrolling back plays it backwards. Only
   translate, rotate, scale and opacity move, so nothing here can shift the
   layout. Browsers without scroll timelines, and people who asked for less
   motion, get the finished state: all of this sits inside both conditions.
   The few things that DO run on a clock (the slow push-in, the light, the
   fire) are the living pictures; they stand still under reduced motion and
   app.js stops them (.is-ruht) while their frame is off screen. */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* A frame is hung as it enters: it comes down the last finger's width,
       swings straight, and its shadow lands on the wall. */
    .rahmen {
      animation: haengt linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 80%;
    }
    @keyframes haengt { from { translate: 0 -1.3rem; rotate: calc(var(--neig) + 1.1deg); } }
    .rahmen::before {
      animation: schatten-faellt linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 80%;
    }
    @keyframes schatten-faellt { from { opacity: .2; translate: -.5rem -.6rem; } }

    /* The picture travels behind its frame while the frame crosses the screen. */
    .rahmen__bild img {
      animation: zieht-vorbei linear both, kommt-naeher 30s ease-in-out infinite alternate;
      animation-timeline: view(), auto;
      animation-range: cover 0% cover 100%, normal;
    }
    @keyframes zieht-vorbei { from { translate: 0 -4.5%; } to { translate: 0 4.5%; } }
    /* resting: the scroll movement stays, only the clock stops */
    .is-ruht .rahmen__bild img { animation-play-state: running, paused; }
  }

  /* LIVING PICTURES. A push-in so slow it is only noticed as "the picture is
     not a print" (kommt-naeher, attached above so it can share the element
     with the scroll movement) … */
  @keyframes kommt-naeher { to { scale: 1.07; } }
  @supports not (animation-timeline: view()) {
    .rahmen__bild img { animation: kommt-naeher 30s ease-in-out infinite alternate; }
    .is-ruht .rahmen__bild img { animation-play-state: paused; }
  }
  /* … summer light that wanders across the glass … */
  .rahmen__bild::before {
    content: "";
    position: absolute;
    inset: -10% -70%;
    z-index: 1;
    background: linear-gradient(104deg, transparent 38%, rgba(255, 238, 196, .17) 47%, rgba(255, 238, 196, .05) 55%, transparent 63%);
    animation: licht-wandert 38s ease-in-out infinite alternate;
    transition: opacity 1.4s var(--ruhig);
    pointer-events: none;
  }
  @keyframes licht-wandert { from { transform: translate3d(-16%, 0, 0); } to { transform: translate3d(16%, 0, 0); } }
  :root[data-jahreszeit="winter"] .rahmen__bild::before { opacity: 0; animation-play-state: paused; }
  /* … and in the snow months the stove in the Stube: a glow that is never
     twice the same for long. */
  .glut {
    position: absolute;
    left: 44%;
    top: 34%;
    z-index: 1;
    width: 32%;
    height: 50%;
    background: radial-gradient(closest-side, rgba(255, 150, 60, .5), rgba(255, 120, 40, .16) 55%, transparent);
    mix-blend-mode: soft-light;
    animation: glut-flackert 4.3s ease-in-out infinite;
    pointer-events: none;
  }
  @keyframes glut-flackert {
    0%, 100% { opacity: .55; } 13% { opacity: .9; } 22% { opacity: .5; } 41% { opacity: .8; }
    48% { opacity: .62; } 67% { opacity: 1; } 79% { opacity: .58; } 88% { opacity: .85; }
  }
  .is-ruht .rahmen__bild::before, .is-ruht .glut { animation-play-state: paused; }
}
.glut { display: none; }
@media (prefers-reduced-motion: no-preference) {
  :root[data-jahreszeit="winter"] .glut { display: block; }
  /* No firelight on a summer photograph that is still waiting for its winter one. */
  :root .rahmen__bild[data-haelt="sommer"] > .glut { display: none; }
}
/* Less motion: the season still changes, it just does not fade, and the sheet
   opens without sliding. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .blick__bild--winter, .blick__licht, .blatt, .blatt__griff::after, .knopf, .hausnotizen summary::after,
  .blick__bilder, .blick__kopf, .blick__satz,
  body, .rahmen::after, .rahmen__innen, .rahmen__bild img, .preise__segmente span, .preise__liste li { transition: none; }
}
